1 /*
2    Copyright (c) 2003, 2011, Oracle and/or its affiliates. All rights reserved.
3 
4    This program is free software; you can redistribute it and/or modify
5    it under the terms of the GNU General Public License, version 2.0,
6    as published by the Free Software Foundation.
7 
8    This program is also distributed with certain software (including
9    but not limited to OpenSSL) that is licensed under separate terms,
10    as designated in a particular file or component or in included license
11    documentation.  The authors of MySQL hereby grant you an additional
12    permission to link the program and your derivative works with the
13    separately licensed software that they have included with MySQL.
14 
15    This program is distributed in the hope that it will be useful,
16    but WITHOUT ANY WARRANTY; without even the implied warranty of
17    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18    GNU General Public License, version 2.0, for more details.
19 
20    You should have received a copy of the GNU General Public License
21    along with this program; if not, write to the Free Software
22    Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301  USA
23 */
24 
25 #define DBLQH_C
26 #include "Dblqh.hpp"
27 #include <ndb_limits.h>
28 #include <md5_hash.hpp>
29 
30 #include <ndb_version.h>
31 #include <signaldata/TuxBound.hpp>
32 #include <signaldata/AccScan.hpp>
33 #include <signaldata/CopyActive.hpp>
34 #include <signaldata/CopyFrag.hpp>
35 #include <signaldata/CreateTrigImpl.hpp>
36 #include <signaldata/DropTrigImpl.hpp>
37 #include <signaldata/EmptyLcp.hpp>
38 #include <signaldata/EventReport.hpp>
39 #include <signaldata/ExecFragReq.hpp>
40 #include <signaldata/GCP.hpp>
41 #include <signaldata/TcKeyRef.hpp>
42 #include <signaldata/LqhKey.hpp>
43 #include <signaldata/NextScan.hpp>
44 #include <signaldata/NFCompleteRep.hpp>
45 #include <signaldata/NodeFailRep.hpp>
46 #include <signaldata/ReadNodesConf.hpp>
47 #include <signaldata/RelTabMem.hpp>
48 #include <signaldata/ScanFrag.hpp>
49 #include <signaldata/SrFragidConf.hpp>
50 #include <signaldata/StartFragReq.hpp>
51 #include <signaldata/StartRec.hpp>
52 #include <signaldata/TupKey.hpp>
53 #include <signaldata/TupCommit.hpp>
54 #include <signaldata/LqhFrag.hpp>
55 #include <signaldata/AccFrag.hpp>
56 #include <signaldata/TupFrag.hpp>
57 #include <signaldata/DumpStateOrd.hpp>
58 #include <signaldata/PackedSignal.hpp>
59 
60 #include <signaldata/CreateTab.hpp>
61 #include <signaldata/CreateTable.hpp>
62 #include <signaldata/PrepDropTab.hpp>
63 #include <signaldata/DropTab.hpp>
64 
65 #include <signaldata/AlterTab.hpp>
66 #include <signaldata/AlterTable.hpp>
67 #include <signaldata/DictTabInfo.hpp>
68 
69 #include <signaldata/LCP.hpp>
70 #include <DebuggerNames.hpp>
71 #include <signaldata/BackupImpl.hpp>
72 #include <signaldata/RestoreImpl.hpp>
73 #include <signaldata/KeyInfo.hpp>
74 #include <signaldata/AttrInfo.hpp>
75 #include <signaldata/TransIdAI.hpp>
76 #include <KeyDescriptor.hpp>
77 #include <signaldata/RouteOrd.hpp>
78 #include <signaldata/FsRef.hpp>
79 #include <SectionReader.hpp>
80 #include <signaldata/SignalDroppedRep.hpp>
81 #include <signaldata/FsReadWriteReq.hpp>
82 #include <signaldata/DbinfoScan.hpp>
83 #include <signaldata/SystemError.hpp>
84 #include <signaldata/FireTrigOrd.hpp>
85 #include <NdbEnv.h>
86 
87 #include "../suma/Suma.hpp"
88 #include "DblqhCommon.hpp"
89 
90 #include <EventLogger.hpp>
91 extern EventLogger * g_eventLogger;
92 
93 // Use DEBUG to print messages that should be
94 // seen only when we debug the product
95 #ifdef VM_TRACE
96 #define DEBUG(x) ndbout << "DBLQH: "<< x << endl;
97 static
98 NdbOut &
operator <<(NdbOut & out,Dblqh::TcConnectionrec::TransactionState state)99 operator<<(NdbOut& out, Dblqh::TcConnectionrec::TransactionState state){
100   out << (int)state;
101   return out;
102 }
103 
104 static
105 NdbOut &
operator <<(NdbOut & out,Dblqh::TcConnectionrec::LogWriteState state)106 operator<<(NdbOut& out, Dblqh::TcConnectionrec::LogWriteState state){
107   out << (int)state;
108   return out;
109 }
110 
111 static
112 NdbOut &
operator <<(NdbOut & out,Dblqh::TcConnectionrec::ListState state)113 operator<<(NdbOut& out, Dblqh::TcConnectionrec::ListState state){
114   out << (int)state;
115   return out;
116 }
117 
118 static
119 NdbOut &
operator <<(NdbOut & out,Dblqh::TcConnectionrec::AbortState state)120 operator<<(NdbOut& out, Dblqh::TcConnectionrec::AbortState state){
121   out << (int)state;
122   return out;
123 }
124 
125 static
126 NdbOut &
operator <<(NdbOut & out,Dblqh::ScanRecord::ScanState state)127 operator<<(NdbOut& out, Dblqh::ScanRecord::ScanState state){
128   out << (int)state;
129   return out;
130 }
131 
132 static
133 NdbOut &
operator <<(NdbOut & out,Dblqh::LogFileOperationRecord::LfoState state)134 operator<<(NdbOut& out, Dblqh::LogFileOperationRecord::LfoState state){
135   out << (int)state;
136   return out;
137 }
138 
139 static
140 NdbOut &
operator <<(NdbOut & out,Dblqh::ScanRecord::ScanType state)141 operator<<(NdbOut& out, Dblqh::ScanRecord::ScanType state){
142   out << (int)state;
143   return out;
144 }
145 
146 static
147 NdbOut &
operator <<(NdbOut & out,Operation_t op)148 operator<<(NdbOut& out, Operation_t op)
149 {
150   switch(op){
151   case ZREAD: out << "READ"; break;
152   case ZREAD_EX: out << "READ-EX"; break;
153   case ZINSERT: out << "INSERT"; break;
154   case ZUPDATE: out << "UPDATE"; break;
155   case ZDELETE: out << "DELETE"; break;
156   case ZWRITE: out << "WRITE"; break;
157   case ZUNLOCK: out << "UNLOCK"; break;
158   case ZREFRESH: out << "REFRESH"; break;
159   }
160   return out;
161 }
162 
163 #else
164 #define DEBUG(x)
165 #endif
166 
167 //#define MARKER_TRACE 0
168 //#define TRACE_SCAN_TAKEOVER 1
169 
170 #ifdef VM_TRACE
171 #ifndef NDB_DEBUG_REDO
172 #define NDB_DEBUG_REDO
173 #endif
174 #endif
175 
176 #ifdef NDB_DEBUG_REDO
177 static int DEBUG_REDO = 0;
178 #else
179 #define DEBUG_REDO 0
180 #endif
181 
182 const Uint32 NR_ScanNo = 0;
183 
184 #ifndef NDBD_TRACENR
185 #if defined VM_TRACE
186 #define NDBD_TRACENR
187 #endif
188 #endif
189 
190 #ifdef NDBD_TRACENR
191 #include <NdbConfig.h>
192 static NdbOut * tracenrout = 0;
193 static int TRACENR_FLAG = 0;
194 #define TRACENR(x) (* tracenrout) << x
195 #define SET_TRACENR_FLAG TRACENR_FLAG = 1
196 #define CLEAR_TRACENR_FLAG TRACENR_FLAG = 0
197 #else
198 #define TRACENR_FLAG 0
199 #define TRACENR(x) do { } while(0)
200 #define SET_TRACENR_FLAG
201 #define CLEAR_TRACENR_FLAG
202 #endif
203 
204 #ifdef NDBD_TRACENR
205 static NdbOut * traceopout = 0;
206 #define TRACE_OP(regTcPtr, place) do { if (TRACE_OP_CHECK(regTcPtr)) TRACE_OP_DUMP(regTcPtr, place); } while(0)
207 #else
208 #define TRACE_OP(x, y) { (void)x;}
209 #endif
210 
211 struct LogPosition
212 {
213   Uint32 m_file_no;
214   Uint32 m_mbyte;
215 };
216 
217 int
cmp(const LogPosition & pos1,const LogPosition & pos2)218 cmp(const LogPosition& pos1, const LogPosition& pos2)
219 {
220   if (pos1.m_file_no > pos2.m_file_no)
221     return 1;
222   if (pos1.m_file_no < pos2.m_file_no)
223     return -1;
224   if (pos1.m_mbyte > pos2.m_mbyte)
225     return 1;
226   if (pos1.m_mbyte < pos2.m_mbyte)
227     return -1;
228 
229   return 0;
230 }
231 
232 /**
233  * head - tail
234  */
235 static
236 Uint64
free_log(const LogPosition & head,const LogPosition & tail,Uint32 cnt,Uint32 size)237 free_log(const LogPosition& head, const LogPosition& tail,
238          Uint32 cnt, Uint32 size)
239 {
240   Uint64 headmb = head.m_file_no*Uint64(size) + head.m_mbyte;
241   Uint64 tailmb = tail.m_file_no*Uint64(size) + tail.m_mbyte;
242   if (headmb >= tailmb)
243   {
244     return (cnt * Uint64(size)) - headmb + tailmb;
245   }
246   else
247   {
248     return tailmb - headmb;
249   }
250 }
251 
252 /* ------------------------------------------------------------------------- */
253 /* -------               SEND SYSTEM ERROR                           ------- */
254 /*                                                                           */
255 /* ------------------------------------------------------------------------- */
systemError(Signal * signal,int line)256 void Dblqh::systemError(Signal* signal, int line)
257 {
258   signal->theData[0] = 2304;
259   execDUMP_STATE_ORD(signal);
260   progError(line, NDBD_EXIT_NDBREQUIRE);
261 }//Dblqh::systemError()
262 
263 /* *************** */
264 /*  ACCSEIZEREF  > */
265 /* *************** */
execACCSEIZEREF(Signal * signal)266 void Dblqh::execACCSEIZEREF(Signal* signal)
267 {
268   jamEntry();
269   ndbrequire(false);
270 }//Dblqh::execACCSEIZEREF()
271 
272 /* ******************************************************>> */
273 /* THIS SIGNAL IS USED TO HANDLE REAL-TIME                  */
274 /* BREAKS THAT ARE NECESSARY TO ENSURE REAL-TIME            */
275 /* OPERATION OF LQH.                                        */
276 /* This signal is also used for signal loops, for example   */
277 /* the timeout handling for writing logs every second.      */
278 /* ******************************************************>> */
execCONTINUEB(Signal * signal)279 void Dblqh::execCONTINUEB(Signal* signal)
280 {
281   jamEntry();
282   Uint32 tcase = signal->theData[0];
283   Uint32 data0 = signal->theData[1];
284   Uint32 data1 = signal->theData[2];
285   Uint32 data2 = signal->theData[3];
286 #if 0
287   if (tcase == RNIL) {
288     tcConnectptr.i = data0;
289     ptrCheckGuard(tcConnectptr, ctcConnectrecFileSize, tcConnectionrec);
290     ndbout << "State = " << tcConnectptr.p->transactionState;
291     ndbout << " seqNoReplica = " << tcConnectptr.p->seqNoReplica;
292     ndbout << " tcNodeFailrec = " << tcConnectptr.p->tcNodeFailrec;
293     ndbout << " activeCreat = " << tcConnectptr.p->activeCreat;
294     ndbout << endl;
295     ndbout << "abortState = " << tcConnectptr.p->abortState;
296     ndbout << "listState = " << tcConnectptr.p->listState;
297     ndbout << endl;
298     return;
299   }//if
300 #endif
301   LogPartRecordPtr save;
302   switch (tcase) {
303   case ZLOG_LQHKEYREQ:
304     if (cnoOfLogPages == 0) {
305       jam();
306   busywait:
307       sendSignalWithDelay(cownref, GSN_CONTINUEB, signal, 10, 2);
308       return;
309     }//if
310     logPartPtr.i = data0;
311     ptrCheckGuard(logPartPtr, clogPartFileSize, logPartRecord);
312     save = logPartPtr;
313 
314     logPartPtr.p->LogLqhKeyReqSent = ZFALSE;
315 
316     if (logPartPtr.p->waitWriteGciLog == LogPartRecord::WWGL_TRUE)
317     {
318       jam();
319       goto startnext;
320     }
321     if (logPartPtr.p->m_log_complete_queue.isEmpty())
322     {
323       jam();
324       /**
325        * prepare is first in queue...check that it's ok to rock'n'roll
326        */
327       if (logPartPtr.p->m_log_problems != 0)
328       {
329         /**
330          * It will be restarted when problems are cleared...
331          */
332         jam();
333         return;
334       }
335 
336       if (cnoOfLogPages < ZMIN_LOG_PAGES_OPERATION)
337       {
338         jam();
339         logPartPtr.p->LogLqhKeyReqSent = ZTRUE;
340         goto busywait;
341       }
342     }
343 
344     logFilePtr.i = logPartPtr.p->currentLogfile;
345     ptrCheckGuard(logFilePtr, clogFileFileSize, logFileRecord);
346     logPagePtr.i = logFilePtr.p->currentLogpage;
347     ptrCheckGuard(logPagePtr, clogPageFileSize, logPageRecord);
348 
349     getFirstInLogQueue(signal, tcConnectptr);
350     fragptr.i = tcConnectptr.p->fragmentptr;
351     c_fragment_pool.getPtr(fragptr);
352 
353     // so that operation can continue...
354     ndbrequire(logPartPtr.p->logPartState == LogPartRecord::ACTIVE);
355     logPartPtr.p->logPartState = LogPartRecord::IDLE;
356     switch (tcConnectptr.p->transactionState) {
357     case TcConnectionrec::LOG_QUEUED:
358       if (tcConnectptr.p->abortState != TcConnectionrec::ABORT_IDLE)
359       {
360         jam();
361         abortCommonLab(signal);
362       }
363       else
364       {
365         jam();
366         logLqhkeyreqLab(signal);
367       }
368       break;
369     case TcConnectionrec::LOG_ABORT_QUEUED:
370       jam();
371       writeAbortLog(signal);
372       removeLogTcrec(signal);
373       continueAfterLogAbortWriteLab(signal);
374       break;
375     case TcConnectionrec::LOG_COMMIT_QUEUED:
376     case TcConnectionrec::LOG_COMMIT_QUEUED_WAIT_SIGNAL:
377       jam();
378       writeCommitLog(signal, logPartPtr);
379       if (tcConnectptr.p->transactionState == TcConnectionrec::LOG_COMMIT_QUEUED) {
380         if (tcConnectptr.p->seqNoReplica == 0 ||
381 	    tcConnectptr.p->activeCreat == Fragrecord::AC_NR_COPY)
382         {
383           jam();
384           localCommitLab(signal);
385         }
386         else
387         {
388           jam();
389           commitReplyLab(signal);
390         }
391       }
392       else
393       {
394         jam();
395         tcConnectptr.p->transactionState = TcConnectionrec::LOG_COMMIT_WRITTEN_WAIT_SIGNAL;
396       }
397       break;
398     case TcConnectionrec::COMMIT_QUEUED:
399       jam();
400       localCommitLab(signal);
401       break;
402     case TcConnectionrec::ABORT_QUEUED:
403       jam();
404       abortCommonLab(signal);
405       break;
406     default:
407       ndbrequire(false);
408       break;
409     }//switch
410 
411     /**
412      * LogFile/LogPage could have altered due to above
413      */
414   startnext:
415     logPartPtr = save;
416     logFilePtr.i = logPartPtr.p->currentLogfile;
417     ptrCheckGuard(logFilePtr, clogFileFileSize, logFileRecord);
418     logPagePtr.i = logFilePtr.p->currentLogpage;
419     ptrCheckGuard(logPagePtr, clogPageFileSize, logPageRecord);
420     logNextStart(signal);
421     return;
422     break;
423   case ZSR_GCI_LIMITS:
424     jam();
425     signal->theData[0] = data0;
426     srGciLimits(signal);
427     return;
428     break;
429   case ZSR_LOG_LIMITS:
430     jam();
431     signal->theData[0] = data0;
432     signal->theData[1] = data1;
433     signal->theData[2] = data2;
434     srLogLimits(signal);
435     return;
436     break;
437   case ZSEND_EXEC_CONF:
438     jam();
439     signal->theData[0] = data0;
440     sendExecConf(signal);
441     return;
442     break;
443   case ZEXEC_SR:
444     jam();
445     signal->theData[0] = data0;
446     execSr(signal);
447     return;
448     break;
449   case ZSR_FOURTH_COMP:
450     jam();
451     signal->theData[0] = data0;
452     srFourthComp(signal);
453     return;
454     break;
455   case ZINIT_FOURTH:
456     jam();
457     signal->theData[0] = data0;
458     initFourth(signal);
459     return;
460     break;
461   case ZTIME_SUPERVISION:
462     jam();
463     signal->theData[0] = data0;
464     timeSup(signal);
465     return;
466     break;
467   case ZSR_PHASE3_START:
468     jam();
469     srPhase3Start(signal);
470     return;
471     break;
472   case ZLQH_TRANS_NEXT:
473     jam();
474     tcNodeFailptr.i = data0;
475     ptrCheckGuard(tcNodeFailptr, ctcNodeFailrecFileSize, tcNodeFailRecord);
476     lqhTransNextLab(signal);
477     return;
478     break;
479   case ZSCAN_TC_CONNECT:
480     jam();
481     tabptr.i = data1;
482     ptrCheckGuard(tabptr, ctabrecFileSize, tablerec);
483     scanTcConnectLab(signal, data0, data2);
484     return;
485     break;
486   case ZINITIALISE_RECORDS:
487     jam();
488     initialiseRecordsLab(signal, data0, data2, signal->theData[4]);
489     return;
490     break;
491   case ZINIT_GCP_REC:
492     jam();
493     gcpPtr.i = 0;
494     ptrAss(gcpPtr, gcpRecord);
495     initGcpRecLab(signal);
496     startTimeSupervision(signal);
497     return;
498     break;
499   case ZCHECK_LCP_STOP_BLOCKED:
500     jam();
501     c_scanRecordPool.getPtr(scanptr, data0);
502     tcConnectptr.i = scanptr.p->scanTcrec;
503     ptrCheckGuard(tcConnectptr, ctcConnectrecFileSize, tcConnectionrec);
504     fragptr.i = tcConnectptr.p->fragmentptr;
505     c_fragment_pool.getPtr(fragptr);
506     checkLcpStopBlockedLab(signal);
507     return;
508   case ZSCAN_MARKERS:
509     jam();
510     scanMarkers(signal, data0, data1, data2);
511     return;
512     break;
513 
514   case ZOPERATION_EVENT_REP:
515     jam();
516     /* Send counter event report */
517     {
518       const Uint32 len = c_Counters.build_event_rep(signal);
519       sendSignal(CMVMI_REF, GSN_EVENT_REP, signal, len, JBB);
520     }
521 
522     {
523       const Uint32 report_interval = 5000;
524       const Uint32 len = c_Counters.build_continueB(signal);
525       signal->theData[0] = ZOPERATION_EVENT_REP;
526       sendSignalWithDelay(cownref, GSN_CONTINUEB, signal,
527                           report_interval, len);
528     }
529     break;
530   case ZDROP_TABLE_WAIT_USAGE:
531     jam();
532     dropTab_wait_usage(signal);
533     return;
534     break;
535   case ZENABLE_EXPAND_CHECK:
536   {
537     jam();
538     fragptr.i = signal->theData[1];
539     if (fragptr.i != RNIL)
540     {
541       jam();
542       c_lcp_complete_fragments.getPtr(fragptr);
543       signal->theData[0] = fragptr.p->tabRef;
544       signal->theData[1] = fragptr.p->fragId;
545       BlockReference accRef = calcInstanceBlockRef(DBACC);
546       sendSignal(accRef, GSN_EXPANDCHECK2, signal, 2, JBB);
547       Ptr<Fragrecord> save = fragptr;
548 
549       c_lcp_complete_fragments.next(fragptr);
550       signal->theData[0] = ZENABLE_EXPAND_CHECK;
551       signal->theData[1] = fragptr.i;
552       sendSignal(reference(), GSN_CONTINUEB, signal, 2, JBB);
553 
554       c_lcp_complete_fragments.remove(save);
555       return;
556     }
557     else
558     {
559       jam();
560       cstartRecReq = SRR_REDO_COMPLETE;
561       ndbrequire(c_lcp_complete_fragments.isEmpty());
562 
563       rebuildOrderedIndexes(signal, 0);
564       return;
565     }
566   }
567   case ZRETRY_TCKEYREF:
568   {
569     jam();
570     Uint32 cnt = signal->theData[1];
571     Uint32 ref = signal->theData[2];
572     if (cnt < (10 * 60 * 5))
573     {
574       jam();
575       /**
576        * Only retry for 5 minutes...then hope that API has handled it..somehow
577        */
578       memmove(signal->theData, signal->theData+3, 4*TcKeyRef::SignalLength);
579       sendTCKEYREF(signal, ref, 0, cnt);
580     }
581     return;
582   }
583   case ZWAIT_REORG_SUMA_FILTER_ENABLED:
584     jam();
585     wait_reorg_suma_filter_enabled(signal);
586     return;
587   case ZREBUILD_ORDERED_INDEXES:
588   {
589     Uint32 tableId = signal->theData[1];
590     rebuildOrderedIndexes(signal, tableId);
591     return;
592   }
593   case ZWAIT_READONLY:
594   {
595     jam();
596     wait_readonly(signal);
597     return;
598   }
599   default:
600     ndbrequire(false);
601     break;
602   }//switch
603 }//Dblqh::execCONTINUEB()
604 
605 /* *********************************************************> */
606 /*  Request from DBDIH to include a new node in the node list */
607 /*  and so forth.                                             */
608 /* *********************************************************> */
execINCL_NODEREQ(Signal * signal)609 void Dblqh::execINCL_NODEREQ(Signal* signal)
610 {
611   jamEntry();
612   BlockReference retRef = signal->theData[0];
613   Uint32 nodeId = signal->theData[1];
614   cnewestGci = signal->theData[2];
615   cnewestCompletedGci = signal->theData[2] - 1;
616   ndbrequire(cnoOfNodes < MAX_NDB_NODES);
617   for (Uint32 i = 0; i < cnoOfNodes; i++) {
618     jam();
619     if (cnodeData[i] == nodeId) {
620       jam();
621       cnodeStatus[i] = ZNODE_UP;
622     }//if
623   }//for
624 
625   {
626     HostRecordPtr Thostptr;
627     Thostptr.i = nodeId;
628     ptrCheckGuard(Thostptr, chostFileSize, hostRecord);
629     Thostptr.p->nodestatus = ZNODE_UP;
630   }
631 
632   signal->theData[0] = nodeId;
633   signal->theData[1] = cownref;
634   sendSignal(retRef, GSN_INCL_NODECONF, signal, 2, JBB);
635   return;
636 }//Dblqh::execINCL_NODEREQ()
637 
execTUPSEIZEREF(Signal * signal)638 void Dblqh::execTUPSEIZEREF(Signal* signal)
639 {
640   jamEntry();
641   ndbrequire(false);
642 }//Dblqh::execTUPSEIZEREF()
643 
644 /* ########################################################################## */
645 /* #######                  START / RESTART MODULE                    ####### */
646 /* ########################################################################## */
647 /* ************************************************************************>> */
648 /*  This is first signal that arrives in a start / restart. Sender is NDBCNTR_REF. */
649 /* ************************************************************************>> */
execSTTOR(Signal * signal)650 void Dblqh::execSTTOR(Signal* signal)
651 {
652   UintR tstartPhase;
653 
654   jamEntry();
655                                                   /* START CASE */
656   tstartPhase = signal->theData[1];
657                                                   /* SYSTEM RESTART RANK */
658   csignalKey = signal->theData[6];
659 #if defined VM_TRACE || defined ERROR_INSERT || defined NDBD_TRACENR
660   char *name;
661   FILE *out = 0;
662 #endif
663   switch (tstartPhase) {
664   case ZSTART_PHASE1:
665     jam();
666     cstartPhase = tstartPhase;
667     c_tup = (Dbtup*)globalData.getBlock(DBTUP, instance());
668     c_acc = (Dbacc*)globalData.getBlock(DBACC, instance());
669     c_lgman = (Lgman*)globalData.getBlock(LGMAN);
670     ndbrequire(c_tup != 0 && c_acc != 0 && c_lgman != 0);
671     sendsttorryLab(signal);
672 
673 #ifdef NDBD_TRACENR
674 #ifdef VM_TRACE
675     out = globalSignalLoggers.getOutputStream();
676 #endif
677     if (out == 0) {
678       name = NdbConfig_SignalLogFileName(getOwnNodeId());
679       out = fopen(name, "a");
680     }
681     tracenrout = new NdbOut(* new FileOutputStream(out));
682 #endif
683 
684 #ifdef NDBD_TRACENR
685     traceopout = &ndbout;
686 #endif
687 
688 #ifdef NDB_DEBUG_REDO
689     {
690       char buf[100];
691       if (NdbEnv_GetEnv("NDB_DEBUG_REDO", buf, sizeof(buf)))
692       {
693         DEBUG_REDO = 1;
694       }
695     }
696 #endif
697     return;
698     break;
699   case 4:
700     jam();
701     define_backup(signal);
702     break;
703   default:
704     jam();
705     /*empty*/;
706     sendsttorryLab(signal);
707     return;
708     break;
709   }//switch
710 }//Dblqh::execSTTOR()
711 
712 void
define_backup(Signal * signal)713 Dblqh::define_backup(Signal* signal)
714 {
715   DefineBackupReq * req = (DefineBackupReq*)signal->getDataPtrSend();
716   req->backupId = 0;
717   req->clientRef = 0;
718   req->clientData = 0;
719   req->senderRef = reference();
720   req->backupPtr = 0;
721   req->backupKey[0] = 0;
722   req->backupKey[1] = 0;
723   req->nodes.clear();
724   req->nodes.set(getOwnNodeId());
725   req->backupDataLen = ~0;
726 
727   BlockReference backupRef = calcInstanceBlockRef(BACKUP);
728   sendSignal(backupRef, GSN_DEFINE_BACKUP_REQ, signal,
729 	     DefineBackupReq::SignalLength, JBB);
730 }
731 
732 void
execDEFINE_BACKUP_REF(Signal * signal)733 Dblqh::execDEFINE_BACKUP_REF(Signal* signal)
734 {
735   jamEntry();
736   m_backup_ptr = RNIL;
737   DefineBackupRef* ref = (DefineBackupRef*)signal->getDataPtrSend();
738   int err_code = 0;
739   char * extra_msg = NULL;
740 
741   switch(ref->errorCode){
742     case DefineBackupRef::Undefined:
743     case DefineBackupRef::FailedToSetupFsBuffers:
744     case DefineBackupRef::FailedToAllocateBuffers:
745     case DefineBackupRef::FailedToAllocateTables:
746     case DefineBackupRef::FailedAllocateTableMem:
747     case DefineBackupRef::FailedToAllocateFileRecord:
748     case DefineBackupRef::FailedToAllocateAttributeRecord:
749     case DefineBackupRef::FailedInsertFileHeader:
750     case DefineBackupRef::FailedInsertTableList:
751       jam();
752       err_code = NDBD_EXIT_INVALID_CONFIG;
753       extra_msg = (char*) "Probably Backup parameters configuration error, Please consult the manual";
754       progError(__LINE__, err_code, extra_msg);
755   }
756 
757   sendsttorryLab(signal);
758 }
759 
760 void
execDEFINE_BACKUP_CONF(Signal * signal)761 Dblqh::execDEFINE_BACKUP_CONF(Signal* signal)
762 {
763   jamEntry();
764   DefineBackupConf * conf = (DefineBackupConf*)signal->getDataPtrSend();
765   m_backup_ptr = conf->backupPtr;
766   sendsttorryLab(signal);
767 }
768 
769 /* ***************************************> */
770 /*  Restart phases 1 - 6, sender is Ndbcntr */
771 /* ***************************************> */
execNDB_STTOR(Signal * signal)772 void Dblqh::execNDB_STTOR(Signal* signal)
773 {
774   jamEntry();
775   Uint32 ownNodeId = signal->theData[1];   /* START PHASE*/
776   cstartPhase = signal->theData[2];  /* MY NODE ID */
777   cstartType = signal->theData[3];   /* START TYPE */
778 
779   switch (cstartPhase) {
780   case ZSTART_PHASE1:
781     jam();
782     preComputedRequestInfoMask = 0;
783     LqhKeyReq::setKeyLen(preComputedRequestInfoMask, RI_KEYLEN_MASK);
784     LqhKeyReq::setLastReplicaNo(preComputedRequestInfoMask, RI_LAST_REPL_MASK);
785     // Dont LqhKeyReq::setApplicationAddressFlag
786     LqhKeyReq::setDirtyFlag(preComputedRequestInfoMask, 1);
787     // Dont LqhKeyReq::setInterpretedFlag
788     LqhKeyReq::setSimpleFlag(preComputedRequestInfoMask, 1);
789     LqhKeyReq::setOperation(preComputedRequestInfoMask, RI_OPERATION_MASK);
790     LqhKeyReq::setGCIFlag(preComputedRequestInfoMask, 1);
791     LqhKeyReq::setNrCopyFlag(preComputedRequestInfoMask, 1);
792     // Dont setAIInLqhKeyReq
793     // Dont setSeqNoReplica
794     // Dont setSameClientAndTcFlag
795     // Dont setReturnedReadLenAIFlag
796     // Dont setAPIVersion
797     LqhKeyReq::setMarkerFlag(preComputedRequestInfoMask, 1);
798     LqhKeyReq::setQueueOnRedoProblemFlag(preComputedRequestInfoMask, 1);
799     //preComputedRequestInfoMask = 0x003d7fff;
800     startphase1Lab(signal, /* dummy */ ~0, ownNodeId);
801 
802     {
803       /* Start counter activity event reporting. */
804       const Uint32 len = c_Counters.build_continueB(signal);
805       signal->theData[0] = ZOPERATION_EVENT_REP;
806       sendSignalWithDelay(cownref, GSN_CONTINUEB, signal, 10, len);
807     }
808     return;
809     break;
810   case ZSTART_PHASE2:
811     jam();
812     startphase2Lab(signal, /* dummy */ ~0);
813     return;
814     break;
815   case ZSTART_PHASE3:
816     jam();
817     startphase3Lab(signal);
818     return;
819     break;
820   case ZSTART_PHASE4:
821     jam();
822     startphase4Lab(signal);
823     return;
824     break;
825   case ZSTART_PHASE6:
826     jam();
827     startphase6Lab(signal);
828     return;
829     break;
830   default:
831     jam();
832     /*empty*/;
833     sendNdbSttorryLab(signal);
834     return;
835     break;
836   }//switch
837 }//Dblqh::execNDB_STTOR()
838 
839 /* ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ */
840 /* +++++++                         START PHASE 2                    +++++++ */
841 /*                                                                          */
842 /*             INITIATE ALL RECORDS WITHIN THE BLOCK                        */
843 /* ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ */
startphase1Lab(Signal * signal,Uint32 _dummy,Uint32 ownNodeId)844 void Dblqh::startphase1Lab(Signal* signal, Uint32 _dummy, Uint32 ownNodeId)
845 {
846   UintR Ti;
847   HostRecordPtr ThostPtr;
848 
849 /* ------- INITIATE ALL RECORDS ------- */
850   cownNodeid    = ownNodeId;
851   caccBlockref  = calcInstanceBlockRef(DBACC);
852   ctupBlockref  = calcInstanceBlockRef(DBTUP);
853   ctuxBlockref  = calcInstanceBlockRef(DBTUX);
854   cownref       = calcInstanceBlockRef(DBLQH);
855   ndbassert(cownref == reference());
856   for (Ti = 0; Ti < chostFileSize; Ti++) {
857     ThostPtr.i = Ti;
858     ptrCheckGuard(ThostPtr, chostFileSize, hostRecord);
859     /*
860      * Valid only if receiver has same number of LQH workers.
861      * In general full instance key of fragment must be used.
862      */
863     ThostPtr.p->hostLqhBlockRef = calcInstanceBlockRef(DBLQH, ThostPtr.i);
864     ThostPtr.p->hostTcBlockRef  = calcTcBlockRef(ThostPtr.i);
865     ThostPtr.p->inPackedList = false;
866     ThostPtr.p->noOfPackedWordsLqh = 0;
867     ThostPtr.p->noOfPackedWordsTc  = 0;
868     ThostPtr.p->nodestatus = ZNODE_DOWN;
869   }//for
870   cpackedListIndex = 0;
871 
872   bool do_init =
873     (cstartType == NodeState::ST_INITIAL_START) ||
874     (cstartType == NodeState::ST_INITIAL_NODE_RESTART);
875 
876   LogFileRecordPtr prevLogFilePtr;
877   LogFileRecordPtr zeroLogFilePtr;
878 
879   ndbrequire(cnoLogFiles != 0);
880   for (logPartPtr.i = 0; logPartPtr.i < clogPartFileSize; logPartPtr.i++)
881   {
882     jam();
883     ptrAss(logPartPtr, logPartRecord);
884     initLogpart(signal);
885     for (Uint32 fileNo = 0; fileNo < cnoLogFiles; fileNo++)
886     {
887       seizeLogfile(signal);
888       if (fileNo != 0)
889       {
890         jam();
891         prevLogFilePtr.p->nextLogFile = logFilePtr.i;
892         logFilePtr.p->prevLogFile = prevLogFilePtr.i;
893       }
894       else
895       {
896         jam();
897         logPartPtr.p->firstLogfile = logFilePtr.i;
898         logPartPtr.p->currentLogfile = logFilePtr.i;
899         zeroLogFilePtr.i = logFilePtr.i;
900         zeroLogFilePtr.p = logFilePtr.p;
901       }//if
902       prevLogFilePtr.i = logFilePtr.i;
903       prevLogFilePtr.p = logFilePtr.p;
904       initLogfile(signal, fileNo);
905       if (do_init)
906       {
907         jam();
908         if (logFilePtr.i == zeroLogFilePtr.i)
909         {
910           jam();
911 /* ------------------------------------------------------------------------- */
912 /*IN AN INITIAL START WE START BY CREATING ALL LOG FILES AND SETTING THEIR   */
913 /*PROPER SIZE AND INITIALISING PAGE ZERO IN ALL FILES.                       */
914 /*WE START BY CREATING FILE ZERO IN EACH LOG PART AND THEN PROCEED           */
915 /*SEQUENTIALLY THROUGH ALL LOG FILES IN THE LOG PART.                        */
916 /* ------------------------------------------------------------------------- */
917           if (m_use_om_init == 0 || logPartPtr.i == 0)
918           {
919             /**
920              * initialize one file at a time if using OM_INIT
921              */
922             jam();
923 #ifdef VM_TRACE
924             if (m_use_om_init)
925             {
926               jam();
927               /**
928                * FSWRITEREQ does cross-thread execute-direct
929                *   which makes the clear_global_variables "unsafe"
930                *   disable it until we're finished with init log-files
931                */
932               disable_global_variables();
933             }
934 #endif
935             openLogfileInit(signal);
936           }
937         }//if
938       }//if
939     }//for
940     zeroLogFilePtr.p->prevLogFile = logFilePtr.i;
941     logFilePtr.p->nextLogFile = zeroLogFilePtr.i;
942   }
943 
944   initReportStatus(signal);
945   if (!do_init)
946   {
947     jam();
948     sendNdbSttorryLab(signal);
949   }
950   else
951   {
952     reportStatus(signal);
953   }
954 
955   return;
956 }//Dblqh::startphase1Lab()
957 
958 /* ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ */
959 /* +++++++                           START PHASE 2                    +++++++ */
960 /*                                                                            */
961 /* CONNECT LQH WITH ACC AND TUP.                                              */
962 /* EVERY CONNECTION RECORD IN LQH IS ASSIGNED TO ONE ACC CONNECTION RECORD    */
963 /*       AND ONE TUP CONNECTION RECORD.                                       */
964 /* ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ */
startphase2Lab(Signal * signal,Uint32 _dummy)965 void Dblqh::startphase2Lab(Signal* signal, Uint32 _dummy)
966 {
967   cmaxWordsAtNodeRec = MAX_NO_WORDS_OUTSTANDING_COPY_FRAGMENT;
968 /* -- ACC AND TUP CONNECTION PROCESS -- */
969   tcConnectptr.i = 0;
970   ptrAss(tcConnectptr, tcConnectionrec);
971   moreconnectionsLab(signal);
972   return;
973 }//Dblqh::startphase2Lab()
974 
moreconnectionsLab(Signal * signal)975 void Dblqh::moreconnectionsLab(Signal* signal)
976 {
977   tcConnectptr.p->tcAccBlockref = caccBlockref;
978   // set TUX block here (no operation is seized in TUX)
979   tcConnectptr.p->tcTuxBlockref = ctuxBlockref;
980 /* NO STATE CHECKING IS PERFORMED, ASSUMED TO WORK */
981 /* *************** */
982 /*  ACCSEIZEREQ  < */
983 /* *************** */
984   signal->theData[0] = tcConnectptr.i;
985   signal->theData[1] = cownref;
986   sendSignal(caccBlockref, GSN_ACCSEIZEREQ, signal, 2, JBB);
987   return;
988 }//Dblqh::moreconnectionsLab()
989 
990 /* ***************> */
991 /*  ACCSEIZECONF  > */
992 /* ***************> */
execACCSEIZECONF(Signal * signal)993 void Dblqh::execACCSEIZECONF(Signal* signal)
994 {
995   jamEntry();
996   tcConnectptr.i = signal->theData[0];
997   ptrCheckGuard(tcConnectptr, ctcConnectrecFileSize, tcConnectionrec);
998   tcConnectptr.p->accConnectrec = signal->theData[1];
999 /* *************** */
1000 /*  TUPSEIZEREQ  < */
1001 /* *************** */
1002   tcConnectptr.p->tcTupBlockref = ctupBlockref;
1003   signal->theData[0] = tcConnectptr.i;
1004   signal->theData[1] = cownref;
1005   sendSignal(ctupBlockref, GSN_TUPSEIZEREQ, signal, 2, JBB);
1006   return;
1007 }//Dblqh::execACCSEIZECONF()
1008 
1009 /* ***************> */
1010 /*  TUPSEIZECONF  > */
1011 /* ***************> */
execTUPSEIZECONF(Signal * signal)1012 void Dblqh::execTUPSEIZECONF(Signal* signal)
1013 {
1014   jamEntry();
1015   tcConnectptr.i = signal->theData[0];
1016   ptrCheckGuard(tcConnectptr, ctcConnectrecFileSize, tcConnectionrec);
1017   tcConnectptr.p->tupConnectrec = signal->theData[1];
1018 /* ------- CHECK IF THERE ARE MORE CONNECTIONS TO BE CONNECTED ------- */
1019   tcConnectptr.i = tcConnectptr.p->nextTcConnectrec;
1020   if (tcConnectptr.i != RNIL) {
1021     jam();
1022     ptrCheckGuard(tcConnectptr, ctcConnectrecFileSize, tcConnectionrec);
1023     moreconnectionsLab(signal);
1024     return;
1025   }//if
1026 /* ALL LQH_CONNECT RECORDS ARE CONNECTED TO ACC AND TUP ---- */
1027   sendNdbSttorryLab(signal);
1028   return;
1029 }//Dblqh::execTUPSEIZECONF()
1030 
1031 /* +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ */
1032 /* +++++++                    START PHASE 4                          +++++++ */
1033 /*                                                                           */
1034 /*       CONNECT LQH WITH LQH.                                               */
1035 /*       CONNECT EACH LQH WITH EVERY LQH IN THE DATABASE SYSTEM.             */
1036 /*       IF INITIAL START THEN CREATE THE FRAGMENT LOG FILES                 */
1037 /*IF SYSTEM RESTART OR NODE RESTART THEN OPEN THE FRAGMENT LOG FILES AND     */
1038 /*FIND THE END OF THE LOG FILES.                                             */
1039 /* +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ */
1040 /*        WAIT UNTIL ADD NODE PROCESSES ARE COMPLETED                        */
1041 /*        IF INITIAL START ALSO WAIT FOR LOG FILES TO INITIALISED            */
1042 /*START TIME SUPERVISION OF LOG FILES. WE HAVE TO WRITE LOG PAGES TO DISK    */
1043 /*EVEN IF THE PAGES ARE NOT FULL TO ENSURE THAT THEY COME TO DISK ASAP.      */
1044 /* +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ */
startphase3Lab(Signal * signal)1045 void Dblqh::startphase3Lab(Signal* signal)
1046 {
1047   caddNodeState = ZTRUE;
1048 /* ***************<< */
1049 /*  READ_NODESREQ  < */
1050 /* ***************<< */
1051   cinitialStartOngoing = ZTRUE;
1052 
1053   switch(cstartType){
1054   case NodeState::ST_NODE_RESTART:
1055   case NodeState::ST_SYSTEM_RESTART:
1056     jam();
1057     for (logPartPtr.i = 0; logPartPtr.i < clogPartFileSize; logPartPtr.i++)
1058     {
1059       jam();
1060       LogFileRecordPtr locLogFilePtr;
1061       ptrAss(logPartPtr, logPartRecord);
1062       locLogFilePtr.i = logPartPtr.p->firstLogfile;
1063       ptrCheckGuard(locLogFilePtr, clogFileFileSize, logFileRecord);
1064       locLogFilePtr.p->logFileStatus = LogFileRecord::OPEN_SR_FRONTPAGE;
1065       openFileRw(signal, locLogFilePtr);
1066     }//for
1067     break;
1068   case NodeState::ST_INITIAL_START:
1069   case NodeState::ST_INITIAL_NODE_RESTART:
1070     jam();
1071     for (logPartPtr.i = 0; logPartPtr.i < clogPartFileSize; logPartPtr.i++)
1072     {
1073       jam();
1074       signal->theData[0] = ZINIT_FOURTH;
1075       signal->theData[1] = logPartPtr.i;
1076       sendSignal(cownref, GSN_CONTINUEB, signal, 2, JBB);
1077     }
1078     break;
1079   }
1080 
1081   signal->theData[0] = cownref;
1082   sendSignal(NDBCNTR_REF, GSN_READ_NODESREQ, signal, 1, JBB);
1083   return;
1084 }//Dblqh::startphase3Lab()
1085 
1086 /* ****************** */
1087 /*  READ_NODESCONF  > */
1088 /* ****************** */
execREAD_NODESCONF(Signal * signal)1089 void Dblqh::execREAD_NODESCONF(Signal* signal)
1090 {
1091   jamEntry();
1092 
1093   ReadNodesConf * const readNodes = (ReadNodesConf *)&signal->theData[0];
1094   cnoOfNodes = readNodes->noOfNodes;
1095 
1096   unsigned ind = 0;
1097   unsigned i = 0;
1098   for (i = 1; i < MAX_NDB_NODES; i++) {
1099     jam();
1100     if (NdbNodeBitmask::get(readNodes->allNodes, i)) {
1101       jam();
1102       cnodeData[ind]    = i;
1103       cnodeStatus[ind]  = NdbNodeBitmask::get(readNodes->inactiveNodes, i);
1104 
1105       {
1106         HostRecordPtr Thostptr;
1107         Thostptr.i = i;
1108         ptrCheckGuard(Thostptr, chostFileSize, hostRecord);
1109         Thostptr.p->nodestatus = cnodeStatus[ind];
1110       }
1111 
1112       //readNodes->getVersionId(i, readNodes->theVersionIds) not used
1113       if (!NodeBitmask::get(readNodes->inactiveNodes, i))
1114       {
1115 	jam();
1116 	m_sr_nodes.set(i);
1117       }
1118       ind++;
1119     }//if
1120   }//for
1121   ndbrequire(ind == cnoOfNodes);
1122   ndbrequire(cnoOfNodes >= 1 && cnoOfNodes < MAX_NDB_NODES);
1123   ndbrequire(!(cnoOfNodes == 1 && cstartType == NodeState::ST_NODE_RESTART));
1124 
1125 #ifdef ERROR_INSERT
1126   c_master_node_id = readNodes->masterNodeId;
1127 #endif
1128 
1129   caddNodeState = ZFALSE;
1130   if (cstartType == NodeState::ST_SYSTEM_RESTART)
1131   {
1132     jam();
1133     sendNdbSttorryLab(signal);
1134     return;
1135   }
1136   else if (cstartType == NodeState::ST_NODE_RESTART)
1137   {
1138     jam();
1139     SET_TRACENR_FLAG;
1140     m_sr_nodes.clear();
1141     m_sr_nodes.set(getOwnNodeId());
1142     sendNdbSttorryLab(signal);
1143     return;
1144   }
1145   SET_TRACENR_FLAG;
1146 
1147   checkStartCompletedLab(signal);
1148   return;
1149 }//Dblqh::execREAD_NODESCONF()
1150 
checkStartCompletedLab(Signal * signal)1151 void Dblqh::checkStartCompletedLab(Signal* signal)
1152 {
1153   if (caddNodeState == ZFALSE) {
1154     if (cinitialStartOngoing == ZFALSE) {
1155       jam();
1156       sendNdbSttorryLab(signal);
1157       return;
1158     }//if
1159   }//if
1160   return;
1161 }//Dblqh::checkStartCompletedLab()
1162 
startphase4Lab(Signal * signal)1163 void Dblqh::startphase4Lab(Signal* signal)
1164 {
1165   sendNdbSttorryLab(signal);
1166   return;
1167 }//Dblqh::startphase4Lab()
1168 
1169 /* ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ */
1170 /* SET CONCURRENCY OF LOCAL CHECKPOINTS TO BE USED AFTER SYSTEM RESTART.      */
1171 /* ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ */
startphase6Lab(Signal * signal)1172 void Dblqh::startphase6Lab(Signal* signal)
1173 {
1174   cstartPhase = ZNIL;
1175   cstartType = ZNIL;
1176   CLEAR_TRACENR_FLAG;
1177   sendNdbSttorryLab(signal);
1178   return;
1179 }//Dblqh::startphase6Lab()
1180 
sendNdbSttorryLab(Signal * signal)1181 void Dblqh::sendNdbSttorryLab(Signal* signal)
1182 {
1183   signal->theData[0] = cownref;
1184   BlockReference cntrRef = !isNdbMtLqh() ? NDBCNTR_REF : DBLQH_REF;
1185   sendSignal(cntrRef, GSN_NDB_STTORRY, signal, 1, JBB);
1186   return;
1187 }//Dblqh::sendNdbSttorryLab()
1188 
sendsttorryLab(Signal * signal)1189 void Dblqh::sendsttorryLab(Signal* signal)
1190 {
1191 /* *********<< */
1192 /*  STTORRY  < */
1193 /* *********<< */
1194   signal->theData[0] = csignalKey; /* SIGNAL KEY */
1195   signal->theData[1] = 3;          /* BLOCK CATEGORY */
1196   signal->theData[2] = 2;          /* SIGNAL VERSION NUMBER */
1197   signal->theData[3] = ZSTART_PHASE1;
1198   signal->theData[4] = 4;
1199   signal->theData[5] = 255;
1200   BlockReference cntrRef = !isNdbMtLqh() ? NDBCNTR_REF : DBLQH_REF;
1201   sendSignal(cntrRef, GSN_STTORRY, signal, 6, JBB);
1202   return;
1203 }//Dblqh::sendsttorryLab()
1204 
1205 /* ***************>> */
1206 /*  READ_NODESREF  > */
1207 /* ***************>> */
execREAD_NODESREF(Signal * signal)1208 void Dblqh::execREAD_NODESREF(Signal* signal)
1209 {
1210   jamEntry();
1211   ndbrequire(false);
1212 }//Dblqh::execREAD_NODESREF()
1213 
1214 /* *************** */
1215 /*  SIZEALT_REP  > */
1216 /* *************** */
execREAD_CONFIG_REQ(Signal * signal)1217 void Dblqh::execREAD_CONFIG_REQ(Signal* signal)
1218 {
1219   const ReadConfigReq * req = (ReadConfigReq*)signal->getDataPtr();
1220   Uint32 ref = req->senderRef;
1221   Uint32 senderData = req->senderData;
1222   ndbrequire(req->noOfParameters == 0);
1223 
1224   jamEntry();
1225 
1226   const ndb_mgm_configuration_iterator * p =
1227     m_ctx.m_config.getOwnConfigIterator();
1228   ndbrequire(p != 0);
1229 
1230   cnoLogFiles = 8;
1231   ndbrequire(!ndb_mgm_get_int_parameter(p, CFG_DB_NO_REDOLOG_FILES,
1232 					&cnoLogFiles));
1233   ndbrequire(cnoLogFiles > 0);
1234 
1235   Uint32 log_page_size= 0;
1236   ndb_mgm_get_int_parameter(p, CFG_DB_REDO_BUFFER,
1237 			    &log_page_size);
1238 
1239   /**
1240    * Always set page size in half MBytes
1241    */
1242   clogPageFileSize= (log_page_size / sizeof(LogPageRecord));
1243   Uint32 mega_byte_part= clogPageFileSize & 15;
1244   if (mega_byte_part != 0) {
1245     jam();
1246     clogPageFileSize+= (16 - mega_byte_part);
1247   }
1248 
1249   /* maximum number of log file operations */
1250   clfoFileSize = clogPageFileSize;
1251   if (clfoFileSize < ZLFO_MIN_FILE_SIZE)
1252     clfoFileSize = ZLFO_MIN_FILE_SIZE;
1253 
1254   ndbrequire(!ndb_mgm_get_int_parameter(p, CFG_LQH_TABLE, &ctabrecFileSize));
1255   ndbrequire(!ndb_mgm_get_int_parameter(p, CFG_LQH_TC_CONNECT,
1256 					&ctcConnectrecFileSize));
1257   clogFileFileSize       = 4 * cnoLogFiles;
1258   ndbrequire(!ndb_mgm_get_int_parameter(p, CFG_LQH_SCAN, &cscanrecFileSize));
1259   cmaxAccOps = cscanrecFileSize * MAX_PARALLEL_OP_PER_SCAN;
1260 
1261   ndbrequire(!ndb_mgm_get_int_parameter(p, CFG_DB_DISCLESS, &c_diskless));
1262   c_o_direct = true;
1263   ndb_mgm_get_int_parameter(p, CFG_DB_O_DIRECT, &c_o_direct);
1264 
1265   m_use_om_init = 0;
1266   {
1267     const char * conf = 0;
1268     if (!ndb_mgm_get_string_parameter(p, CFG_DB_INIT_REDO, &conf) && conf)
1269     {
1270       jam();
1271       if (strcasecmp(conf, "sparse") == 0)
1272       {
1273         jam();
1274         m_use_om_init = 0;
1275       }
1276       else if (strcasecmp(conf, "full") == 0)
1277       {
1278         jam();
1279         m_use_om_init = 1;
1280       }
1281     }
1282   }
1283 
1284   Uint32 tmp= 0;
1285   ndbrequire(!ndb_mgm_get_int_parameter(p, CFG_LQH_FRAG, &tmp));
1286   c_fragment_pool.setSize(tmp);
1287 
1288   if (!ndb_mgm_get_int_parameter(p, CFG_DB_REDOLOG_FILE_SIZE,
1289                                  &clogFileSize))
1290   {
1291     // convert to mbyte
1292     clogFileSize = (clogFileSize + 1024*1024 - 1) / (1024 * 1024);
1293     ndbrequire(clogFileSize >= 4 && clogFileSize <= 1024);
1294   }
1295 
1296   m_startup_report_frequency = 0;
1297   ndb_mgm_get_int_parameter(p,CFG_DB_STARTUP_REPORT_FREQUENCY,
1298                             &m_startup_report_frequency);
1299   totalLogFiles = 4 * cnoLogFiles;
1300   totallogMBytes = totalLogFiles * clogFileSize;
1301 
1302   cmaxLogFilesInPageZero = (ZPAGE_SIZE - ZPAGE_HEADER_SIZE - 128) /
1303     (ZFD_MBYTE_SIZE * clogFileSize);
1304 
1305   /**
1306    * "Old" cmaxLogFilesInPageZero was 40
1307    * Each FD need 3 words per mb, require that they can fit into 1 page
1308    *   (atleast 1 FD)
1309    * Is also checked in ConfigInfo.cpp (max FragmentLogFileSize = 1Gb)
1310    *   1Gb = 1024Mb => 3(ZFD_MBYTE_SIZE) * 1024 < 8192 (ZPAGE_SIZE)
1311    */
1312   if (cmaxLogFilesInPageZero > 40)
1313   {
1314     jam();
1315     cmaxLogFilesInPageZero = 40;
1316   }
1317   else
1318   {
1319     ndbrequire(cmaxLogFilesInPageZero);
1320   }
1321 
1322   {
1323     Uint32 config_val = 20;
1324     ndb_mgm_get_int_parameter(p, CFG_DB_LCP_INTERVAL, &config_val);
1325     config_val = config_val > 31 ? 31 : config_val;
1326 
1327     const Uint32 mb = 1024 * 1024;
1328 
1329     // perform LCP after this amout of mbytes written
1330     const Uint64 config_mbytes = ((Uint64(4) << config_val) + mb - 1) / mb;
1331     const Uint64 totalmb = Uint64(cnoLogFiles) * Uint64(clogFileSize);
1332     if (totalmb > config_mbytes)
1333     {
1334       c_free_mb_force_lcp_limit = Uint32(totalmb - config_mbytes);
1335     }
1336     else
1337     {
1338       c_free_mb_force_lcp_limit = 0;
1339     }
1340 
1341     // No less than 33%
1342     Uint32 limit = Uint32(totalmb / 3);
1343     if (c_free_mb_force_lcp_limit < limit)
1344     {
1345       c_free_mb_force_lcp_limit = limit;
1346     }
1347   }
1348   c_free_mb_tail_problem_limit = 4;  // If less than 4Mb set TAIL_PROBLEM
1349 
1350   ndb_mgm_get_int_parameter(p, CFG_DB_TRANSACTION_DEADLOCK_TIMEOUT,
1351                             &cTransactionDeadlockDetectionTimeout);
1352 
1353   initRecords();
1354   initialiseRecordsLab(signal, 0, ref, senderData);
1355 
1356   c_max_redo_lag = 30;
1357   ndb_mgm_get_int_parameter(p, CFG_DB_REDO_OVERCOMMIT_LIMIT,
1358                             &c_max_redo_lag);
1359 
1360   c_max_redo_lag_counter = 3;
1361   ndb_mgm_get_int_parameter(p, CFG_DB_REDO_OVERCOMMIT_COUNTER,
1362                             &c_max_redo_lag_counter);
1363 
1364   c_max_parallel_scans_per_frag = 32;
1365   ndb_mgm_get_int_parameter(p, CFG_DB_PARALLEL_SCANS_PER_FRAG,
1366                             &c_max_parallel_scans_per_frag);
1367 
1368   if (c_max_parallel_scans_per_frag > (256 - MAX_PARALLEL_SCANS_PER_FRAG) / 2)
1369   {
1370     jam();
1371     c_max_parallel_scans_per_frag = (256 - MAX_PARALLEL_SCANS_PER_FRAG) / 2;
1372   }
1373   return;
1374 }//Dblqh::execSIZEALT_REP()
1375 
1376 /* ########################################################################## */
1377 /* #######                          ADD/DELETE FRAGMENT MODULE        ####### */
1378 /*       THIS MODULE IS USED BY DICTIONARY TO CREATE NEW FRAGMENTS AND DELETE */
1379 /*       OLD FRAGMENTS.                                                       */
1380 /*                                                                            */
1381 /* ########################################################################## */
1382 /* -------------------------------------------------------------- */
1383 /*            FRAG REQ                                            */
1384 /* -------------------------------------------------------------- */
1385 /* *********************************************************> */
1386 /*  LQHFRAGREQ: Create new fragments for a table. Sender DICT */
1387 /* *********************************************************> */
1388 
1389 // this unbelievable mess could be replaced by one signal to LQH
1390 // and execute direct to local DICT to get everything at once
1391 void
execCREATE_TAB_REQ(Signal * signal)1392 Dblqh::execCREATE_TAB_REQ(Signal* signal)
1393 {
1394   CreateTabReq* req = (CreateTabReq*)signal->getDataPtr();
1395   tabptr.i = req->tableId;
1396   ptrCheckGuard(tabptr, ctabrecFileSize, tablerec);
1397 
1398   Uint32 senderRef = req->senderRef;
1399   Uint32 senderData = req->senderData;
1400 
1401   if (tabptr.p->tableStatus != Tablerec::NOT_DEFINED)
1402   {
1403     jam();
1404     CreateTabRef* ref = (CreateTabRef*)signal->getDataPtrSend();
1405     ref->senderData = senderData;
1406     ref->senderRef = reference();
1407     ref->errorCode = CreateTableRef::TableAlreadyExist;
1408     sendSignal(senderRef, GSN_CREATE_TAB_REF, signal,
1409                CreateTabRef::SignalLength, JBB);
1410     return;
1411   }
1412 
1413   seizeAddfragrec(signal);
1414   addfragptr.p->m_createTabReq = *req;
1415   req = &addfragptr.p->m_createTabReq;
1416 
1417   tabptr.p->tableStatus = Tablerec::ADD_TABLE_ONGOING;
1418   tabptr.p->tableType = req->tableType;
1419   tabptr.p->primaryTableId = (req->primaryTableId == RNIL ? tabptr.i :
1420                               req->primaryTableId);
1421   tabptr.p->schemaVersion = req->tableVersion;
1422   tabptr.p->m_disk_table= 0;
1423 
1424   addfragptr.p->addfragStatus = AddFragRecord::WAIT_TUP;
1425   sendCreateTabReq(signal, addfragptr);
1426 }
1427 
1428 void
sendCreateTabReq(Signal * signal,AddFragRecordPtr addfragptr)1429 Dblqh::sendCreateTabReq(Signal* signal, AddFragRecordPtr addfragptr)
1430 {
1431   TablerecPtr tabPtr;
1432   tabPtr.i = addfragptr.p->m_createTabReq.tableId;
1433   ptrCheckGuard(tabPtr, ctabrecFileSize, tablerec);
1434 
1435   CreateTabReq* req = (CreateTabReq*)signal->getDataPtrSend();
1436   * req = addfragptr.p->m_createTabReq;
1437 
1438   req->senderRef = reference();
1439   req->senderData = addfragptr.i;
1440 
1441   Uint32 ref = calcInstanceBlockRef(DBTUP);
1442   switch(addfragptr.p->addfragStatus){
1443   case AddFragRecord::WAIT_TUP:
1444     if (DictTabInfo::isOrderedIndex(tabPtr.p->tableType))
1445     {
1446       jam();
1447       req->noOfAttributes = 1;
1448       req->noOfKeyAttr = 1;
1449       req->noOfNullAttributes = 0;
1450     }
1451     break;
1452   case AddFragRecord::WAIT_TUX:
1453     jam();
1454     ndbrequire(req->noOfAttributes >= 2);
1455     req->noOfAttributes--;
1456     ref = calcInstanceBlockRef(DBTUX);
1457     break;
1458   default:
1459     jamLine(addfragptr.p->addfragStatus);
1460     ndbrequire(false);
1461   }
1462 
1463   sendSignal(ref, GSN_CREATE_TAB_REQ, signal,
1464              CreateTabReq::SignalLengthLDM, JBB);
1465 }
1466 
1467 void
execCREATE_TAB_REF(Signal * signal)1468 Dblqh::execCREATE_TAB_REF(Signal* signal)
1469 {
1470   jamEntry();
1471 
1472   CreateTabRef * ref = (CreateTabRef*)signal->getDataPtr();
1473   addfragptr.i = ref->senderData;
1474   ptrCheckGuard(addfragptr, caddfragrecFileSize, addFragRecord);
1475 
1476   abortAddFragOps(signal);
1477 
1478   ref->senderRef = reference();
1479   ref->senderData = addfragptr.p->m_createTabReq.senderData;
1480   sendSignal(addfragptr.p->m_createTabReq.senderRef,
1481              GSN_CREATE_TAB_REF, signal, CreateTabConf::SignalLength, JBB);
1482 
1483   releaseAddfragrec(signal);
1484 }
1485 
1486 void
execCREATE_TAB_CONF(Signal * signal)1487 Dblqh::execCREATE_TAB_CONF(Signal* signal)
1488 {
1489   jamEntry();
1490   CreateTabConf* conf = (CreateTabConf*)signal->getDataPtr();
1491   addfragptr.i = conf->senderData;
1492   ptrCheckGuard(addfragptr, caddfragrecFileSize, addFragRecord);
1493 
1494   TablerecPtr tabPtr;
1495   tabPtr.i = addfragptr.p->m_createTabReq.tableId;
1496   ptrCheckGuard(tabPtr, ctabrecFileSize, tablerec);
1497 
1498   switch(addfragptr.p->addfragStatus){
1499   case AddFragRecord::WAIT_TUP:
1500     jam();
1501     addfragptr.p->tupConnectptr = conf->tupConnectPtr;
1502     if (DictTabInfo::isOrderedIndex(tabPtr.p->tableType))
1503     {
1504       jam();
1505       addfragptr.p->addfragStatus = AddFragRecord::WAIT_TUX;
1506       sendCreateTabReq(signal, addfragptr);
1507       return;
1508     }
1509     break;
1510   case AddFragRecord::WAIT_TUX:
1511     jam();
1512     addfragptr.p->tuxConnectptr = conf->tuxConnectPtr;
1513     break;
1514   default:
1515     jamLine(addfragptr.p->addfragStatus);
1516     ndbrequire(false);
1517   }
1518 
1519   addfragptr.p->addfragStatus = AddFragRecord::WAIT_ADD_ATTR;
1520 
1521   conf->senderRef = reference();
1522   conf->senderData = addfragptr.p->m_createTabReq.senderData;
1523   conf->lqhConnectPtr = addfragptr.i;
1524   sendSignal(addfragptr.p->m_createTabReq.senderRef,
1525              GSN_CREATE_TAB_CONF, signal, CreateTabConf::SignalLength, JBB);
1526 }
1527 
1528 /* ************************************************************************> */
1529 /*  LQHADDATTRREQ: Request from DICT to create attributes for the new table. */
1530 /* ************************************************************************> */
execLQHADDATTREQ(Signal * signal)1531 void Dblqh::execLQHADDATTREQ(Signal* signal)
1532 {
1533   jamEntry();
1534   LqhAddAttrReq * req = (LqhAddAttrReq*)signal->getDataPtr();
1535 
1536   addfragptr.i = req->lqhFragPtr;
1537   ptrCheckGuard(addfragptr, caddfragrecFileSize, addFragRecord);
1538 
1539   addfragptr.p->m_addAttrReq = * req;
1540 
1541   const Uint32 tnoOfAttr = req->noOfAttributes;
1542   const Uint32 numSections = signal->getNoOfSections();
1543   bool isLongReq= ( numSections != 0 );
1544   addfragptr.p->defValSectionI = RNIL;
1545   addfragptr.p->defValNextPos = 0;
1546 
1547   if (isLongReq)
1548   {
1549     SectionHandle handle(this, signal);
1550     SegmentedSectionPtr defValSection;
1551     handle.getSection(defValSection, LqhAddAttrReq::DEFAULT_VALUE_SECTION_NUM);
1552     addfragptr.p->defValSectionI = defValSection.i;
1553     addfragptr.p->defValNextPos = 0;
1554     //Don't free Section here. Section is freed after default values are trasfered to TUP
1555     handle.clear();
1556   }
1557 
1558   ndbrequire(addfragptr.p->addfragStatus == AddFragRecord::WAIT_ADD_ATTR);
1559   ndbrequire((tnoOfAttr != 0) && (tnoOfAttr <= LqhAddAttrReq::MAX_ATTRIBUTES));
1560   addfragptr.p->totalAttrReceived += tnoOfAttr;
1561   ndbrequire(addfragptr.p->totalAttrReceived <=
1562              addfragptr.p->m_createTabReq.noOfAttributes);
1563 
1564   addfragptr.p->attrReceived = tnoOfAttr;
1565 
1566   TablerecPtr tabPtr;
1567   tabPtr.i = addfragptr.p->m_createTabReq.tableId;
1568   ptrCheckGuard(tabPtr, ctabrecFileSize, tablerec);
1569 
1570   for (Uint32 i = 0; i < tnoOfAttr; i++)
1571   {
1572     if(AttributeDescriptor::getDiskBased(req->attributes[i].attrDescriptor))
1573     {
1574       jam();
1575       tabPtr.p->m_disk_table = 1;
1576     }
1577   }//for
1578 
1579   addfragptr.p->attrSentToTup = 0;
1580   addfragptr.p->addfragStatus = AddFragRecord::TUP_ATTR_WAIT;
1581   sendAddAttrReq(signal);
1582 }//Dblqh::execLQHADDATTREQ()
1583 
1584 /* *********************>> */
1585 /*  TUP_ADD_ATTCONF      > */
1586 /* *********************>> */
execTUP_ADD_ATTCONF(Signal * signal)1587 void Dblqh::execTUP_ADD_ATTCONF(Signal* signal)
1588 {
1589   jamEntry();
1590   addfragptr.i = signal->theData[0];
1591   // implies that operation was released on the other side
1592   const bool lastAttr = signal->theData[1];
1593   ptrCheckGuard(addfragptr, caddfragrecFileSize, addFragRecord);
1594 
1595   tabptr.i = addfragptr.p->m_createTabReq.tableId;
1596   ptrCheckGuard(tabptr, ctabrecFileSize, tablerec);
1597 
1598   Uint32 noOfAttr = addfragptr.p->m_createTabReq.noOfAttributes;
1599 
1600   switch (addfragptr.p->addfragStatus) {
1601   case AddFragRecord::TUP_ATTR_WAIT:
1602     if (DictTabInfo::isOrderedIndex(tabptr.p->tableType))
1603     {
1604       addfragptr.p->addfragStatus = AddFragRecord::TUX_ATTR_WAIT;
1605       sendAddAttrReq(signal);
1606       break;
1607     }
1608     goto done_with_attr;
1609     break;
1610   case AddFragRecord::TUX_ATTR_WAIT:
1611     jam();
1612     if (lastAttr)
1613       addfragptr.p->tuxConnectptr = RNIL;
1614     goto done_with_attr;
1615     break;
1616   done_with_attr:
1617     addfragptr.p->attrSentToTup = addfragptr.p->attrSentToTup + 1;
1618     ndbrequire(addfragptr.p->attrSentToTup <= addfragptr.p->attrReceived);
1619     ndbrequire(addfragptr.p->totalAttrReceived <= noOfAttr);
1620     if (addfragptr.p->attrSentToTup < addfragptr.p->attrReceived)
1621     {
1622       // more in this batch
1623       jam();
1624       addfragptr.p->addfragStatus = AddFragRecord::TUP_ATTR_WAIT;
1625       sendAddAttrReq(signal);
1626       return;
1627     }
1628 
1629     if (addfragptr.p->defValSectionI != RNIL)
1630     {
1631       releaseSection(addfragptr.p->defValSectionI);
1632       addfragptr.p->defValNextPos = 0;
1633       addfragptr.p->defValSectionI = RNIL;
1634     }
1635 
1636     { // Reply
1637       LqhAddAttrConf *const conf = (LqhAddAttrConf*)signal->getDataPtrSend();
1638       conf->senderData = addfragptr.p->m_addAttrReq.senderData;
1639       conf->senderAttrPtr = addfragptr.p->m_addAttrReq.senderAttrPtr;
1640       sendSignal(addfragptr.p->m_createTabReq.senderRef,
1641                  GSN_LQHADDATTCONF, signal, LqhAddAttrConf::SignalLength, JBB);
1642     }
1643     if (addfragptr.p->totalAttrReceived < noOfAttr)
1644     {
1645       jam();
1646       addfragptr.p->addfragStatus = AddFragRecord::WAIT_ADD_ATTR;
1647     }
1648     else
1649     {
1650       jam();
1651       releaseAddfragrec(signal);
1652     }
1653     break;
1654   default:
1655     ndbrequire(false);
1656     break;
1657   }
1658 }
1659 
1660 /* **********************>> */
1661 /*  TUX_ADD_ATTRCONF      > */
1662 /* **********************>> */
execTUX_ADD_ATTRCONF(Signal * signal)1663 void Dblqh::execTUX_ADD_ATTRCONF(Signal* signal)
1664 {
1665   jamEntry();
1666   execTUP_ADD_ATTCONF(signal);
1667 }//Dblqh::execTUX_ADD_ATTRCONF
1668 
1669 /* *********************> */
1670 /*  TUP_ADD_ATTREF      > */
1671 /* *********************> */
execTUP_ADD_ATTRREF(Signal * signal)1672 void Dblqh::execTUP_ADD_ATTRREF(Signal* signal)
1673 {
1674   jamEntry();
1675   addfragptr.i = signal->theData[0];
1676   ptrCheckGuard(addfragptr, caddfragrecFileSize, addFragRecord);
1677   Uint32 errorCode = terrorCode = signal->theData[1];
1678 
1679   abortAddFragOps(signal);
1680 
1681   // operation was released on the other side
1682   switch (addfragptr.p->addfragStatus) {
1683   case AddFragRecord::TUP_ATTR_WAIT:
1684     jam();
1685     break;
1686   case AddFragRecord::TUX_ATTR_WAIT:
1687     jam();
1688     break;
1689   default:
1690     ndbrequire(false);
1691     break;
1692   }
1693 
1694   if (addfragptr.p->defValSectionI != RNIL)
1695   {
1696     releaseSection(addfragptr.p->defValSectionI);
1697     addfragptr.p->defValNextPos = 0;
1698     addfragptr.p->defValSectionI = RNIL;
1699   }
1700 
1701   const Uint32 Ref = addfragptr.p->m_createTabReq.senderRef;
1702   const Uint32 senderData = addfragptr.p->m_addAttrReq.senderData;
1703 
1704   releaseAddfragrec(signal);
1705 
1706   LqhAddAttrRef *const ref = (LqhAddAttrRef*)signal->getDataPtrSend();
1707   ref->senderData = senderData;
1708   ref->errorCode = errorCode;
1709   sendSignal(Ref, GSN_LQHADDATTREF, signal,
1710 	     LqhAddAttrRef::SignalLength, JBB);
1711 }//Dblqh::execTUP_ADD_ATTRREF()
1712 
1713 /* **********************> */
1714 /*  TUX_ADD_ATTRREF      > */
1715 /* **********************> */
execTUX_ADD_ATTRREF(Signal * signal)1716 void Dblqh::execTUX_ADD_ATTRREF(Signal* signal)
1717 {
1718   jamEntry();
1719   execTUP_ADD_ATTRREF(signal);
1720 }//Dblqh::execTUX_ADD_ATTRREF
1721 
1722 /*
1723  * Add attribute in TUP or TUX.  Called up to 4 times.
1724  */
1725 void
sendAddAttrReq(Signal * signal)1726 Dblqh::sendAddAttrReq(Signal* signal)
1727 {
1728   arrGuard(addfragptr.p->attrSentToTup, LqhAddAttrReq::MAX_ATTRIBUTES);
1729   LqhAddAttrReq::Entry& entry =
1730     addfragptr.p->m_addAttrReq.attributes[addfragptr.p->attrSentToTup];
1731 
1732   const Uint32 attrId = entry.attrId & 0xffff;
1733   const Uint32 primaryAttrId = entry.attrId >> 16;
1734 
1735   tabptr.i = addfragptr.p->m_createTabReq.tableId;
1736   ptrCheckGuard(tabptr, ctabrecFileSize, tablerec);
1737 
1738   if (addfragptr.p->addfragStatus == AddFragRecord::TUP_ATTR_WAIT)
1739   {
1740     if (DictTabInfo::isTable(tabptr.p->tableType) ||
1741         DictTabInfo::isHashIndex(tabptr.p->tableType) ||
1742         (DictTabInfo::isOrderedIndex(tabptr.p->tableType) &&
1743          primaryAttrId == ZNIL)) {
1744       jam();
1745       TupAddAttrReq* const tupreq = (TupAddAttrReq*)signal->getDataPtrSend();
1746       tupreq->tupConnectPtr = addfragptr.p->tupConnectptr;
1747       tupreq->attrId = attrId;
1748       tupreq->attrDescriptor = entry.attrDescriptor;
1749       tupreq->extTypeInfo = entry.extTypeInfo;
1750       BlockReference tupRef = calcInstanceBlockRef(DBTUP);
1751 
1752       Uint32 sectionLen = 0;
1753       Uint32 startIndex = TupAddAttrReq::SignalLength;
1754       if (addfragptr.p->defValSectionI != RNIL)
1755       {
1756         SegmentedSectionPtr defValSection;
1757         getSection(defValSection, addfragptr.p->defValSectionI);
1758 
1759         SectionReader defValueReader(defValSection, getSectionSegmentPool());
1760         Uint32 defSectionWords = defValueReader.getSize();
1761 
1762         ndbrequire(defValueReader.step(addfragptr.p->defValNextPos));
1763 
1764         Uint32 defValueHeader;
1765         ndbrequire(defValueReader.peekWord(&defValueHeader));
1766 
1767         AttributeHeader ah(defValueHeader);
1768         Uint32 defValueLen = ah.getByteSize();
1769         Uint32 defValueWords = ((defValueLen +3)/4) + 1;
1770         Uint32 *dst = &signal->theData[startIndex];
1771         ndbassert(defSectionWords >= (addfragptr.p->defValNextPos + defValueWords));
1772         ndbrequire(defValueReader.getWords(dst, defValueWords));
1773         addfragptr.p->defValNextPos += defValueWords;
1774         sectionLen = defValueWords;
1775       }
1776 
1777       //A long section is attached when a default value is sent.
1778       if (sectionLen != 0)
1779       {
1780         LinearSectionPtr ptr[3];
1781         ptr[0].p= &signal->theData[startIndex];
1782         ptr[0].sz= sectionLen;
1783         sendSignal(tupRef, GSN_TUP_ADD_ATTRREQ,
1784                    signal, TupAddAttrReq::SignalLength, JBB, ptr, 1);
1785       }
1786       else
1787         sendSignal(tupRef, GSN_TUP_ADD_ATTRREQ,
1788                    signal, TupAddAttrReq::SignalLength, JBB);
1789 
1790       return;
1791     }
1792     if (DictTabInfo::isOrderedIndex(tabptr.p->tableType) &&
1793         primaryAttrId != ZNIL) {
1794       // this attribute is not for TUP
1795       jam();
1796       TupAddAttrConf* tupconf = (TupAddAttrConf*)signal->getDataPtrSend();
1797       tupconf->userPtr = addfragptr.i;
1798       tupconf->lastAttr = false;
1799       sendSignal(reference(), GSN_TUP_ADD_ATTCONF,
1800 		 signal, TupAddAttrConf::SignalLength, JBB);
1801       return;
1802     }
1803   }
1804 
1805   if (addfragptr.p->addfragStatus == AddFragRecord::TUX_ATTR_WAIT)
1806   {
1807     jam();
1808     if (DictTabInfo::isOrderedIndex(tabptr.p->tableType) &&
1809         primaryAttrId != ZNIL) {
1810       jam();
1811       TuxAddAttrReq* const tuxreq = (TuxAddAttrReq*)signal->getDataPtrSend();
1812       tuxreq->tuxConnectPtr = addfragptr.p->tuxConnectptr;
1813       tuxreq->notused1 = 0;
1814       tuxreq->attrId = attrId;
1815       tuxreq->attrDescriptor = entry.attrDescriptor;
1816       tuxreq->extTypeInfo = entry.extTypeInfo;
1817       tuxreq->primaryAttrId = primaryAttrId;
1818       BlockReference tuxRef = calcInstanceBlockRef(DBTUX);
1819       sendSignal(tuxRef, GSN_TUX_ADD_ATTRREQ,
1820 		 signal, TuxAddAttrReq::SignalLength, JBB);
1821       return;
1822     }
1823     if (DictTabInfo::isOrderedIndex(tabptr.p->tableType) &&
1824         primaryAttrId == ZNIL) {
1825       // this attribute is not for TUX
1826       jam();
1827       TuxAddAttrConf* tuxconf = (TuxAddAttrConf*)signal->getDataPtrSend();
1828       tuxconf->userPtr = addfragptr.i;
1829       tuxconf->lastAttr = false;
1830       sendSignal(reference(), GSN_TUX_ADD_ATTRCONF,
1831 		 signal, TuxAddAttrConf::SignalLength, JBB);
1832       return;
1833     }
1834   }
1835   ndbrequire(false);
1836 }//Dblqh::sendAddAttrReq
1837 
execLQHFRAGREQ(Signal * signal)1838 void Dblqh::execLQHFRAGREQ(Signal* signal)
1839 {
1840   jamEntry();
1841   LqhFragReq copy = *(LqhFragReq*)signal->getDataPtr();
1842   LqhFragReq * req = &copy;
1843 
1844   tabptr.i = req->tableId;
1845   ptrCheckGuard(tabptr, ctabrecFileSize, tablerec);
1846 
1847   if (tabptr.p->tableStatus != Tablerec::ADD_TABLE_ONGOING &&
1848       (AlterTableReq::getAddFragFlag(req->changeMask) == 0))
1849   {
1850     jam();
1851     fragrefLab(signal, ZTAB_STATE_ERROR, req);
1852     return;
1853   }//if
1854 
1855   if (getFragmentrec(signal, req->fragId))
1856   {
1857     jam();
1858     fragrefLab(signal, terrorCode, req);
1859     return;
1860   }//if
1861 
1862   if (!insertFragrec(signal, req->fragId))
1863   {
1864     jam();
1865     fragrefLab(signal, terrorCode, req);
1866     return;
1867   }//if
1868 
1869   Uint32 copyType = req->requestInfo & 3;
1870   bool tempTable = ((req->requestInfo & LqhFragReq::TemporaryTable) != 0);
1871   initFragrec(signal, tabptr.i, req->fragId, copyType);
1872   fragptr.p->startGci = req->startGci;
1873   fragptr.p->newestGci = req->startGci;
1874   ndbrequire(tabptr.p->tableType < 256);
1875   fragptr.p->tableType = (Uint8)tabptr.p->tableType;
1876 
1877   {
1878     NdbLogPartInfo lpinfo(instance());
1879     Uint32 logPartNo = lpinfo.partNoFromId(req->logPartId);
1880     ndbrequire(lpinfo.partNoOwner(logPartNo));
1881 
1882     LogPartRecordPtr ptr;
1883     ptr.i = lpinfo.partNoIndex(logPartNo);
1884     ptrCheckGuard(ptr, clogPartFileSize, logPartRecord);
1885     ndbrequire(ptr.p->logPartNo == logPartNo);
1886 
1887     fragptr.p->m_log_part_ptr_i = ptr.i;
1888     fragptr.p->lqhInstanceKey = lpinfo.instanceKey(logPartNo);
1889   }
1890 
1891   if (DictTabInfo::isOrderedIndex(tabptr.p->tableType)) {
1892     jam();
1893     // find corresponding primary table fragment
1894     TablerecPtr tTablePtr;
1895     tTablePtr.i = tabptr.p->primaryTableId;
1896     ptrCheckGuard(tTablePtr, ctabrecFileSize, tablerec);
1897     FragrecordPtr tFragPtr;
1898     tFragPtr.i = RNIL;
1899     for (Uint32 i = 0; i < MAX_FRAG_PER_NODE; i++) {
1900       if (tTablePtr.p->fragid[i] == fragptr.p->fragId) {
1901         jam();
1902         tFragPtr.i = tTablePtr.p->fragrec[i];
1903         break;
1904       }
1905     }
1906     ndbrequire(tFragPtr.i != RNIL);
1907     // store it
1908     fragptr.p->tableFragptr = tFragPtr.i;
1909   }
1910   else
1911   {
1912     jam();
1913     fragptr.p->tableFragptr = fragptr.i;
1914   }
1915 
1916   if (tempTable)
1917   {
1918 //--------------------------------------------
1919 // reqinfo bit 3-4 = 2 means temporary table
1920 // without logging or checkpointing.
1921 //--------------------------------------------
1922     jam();
1923     fragptr.p->logFlag = Fragrecord::STATE_FALSE;
1924     fragptr.p->lcpFlag = Fragrecord::LCP_STATE_FALSE;
1925   }//if
1926 
1927   seizeAddfragrec(signal);
1928   addfragptr.p->m_lqhFragReq = * req;
1929   addfragptr.p->fragmentPtr = fragptr.i;
1930 
1931   if (DictTabInfo::isTable(tabptr.p->tableType) ||
1932       DictTabInfo::isHashIndex(tabptr.p->tableType)) {
1933     jam();
1934     AccFragReq* const accreq = (AccFragReq*)signal->getDataPtrSend();
1935     accreq->userPtr = addfragptr.i;
1936     accreq->userRef = cownref;
1937     accreq->tableId = tabptr.i;
1938     accreq->reqInfo = 0;
1939     accreq->fragId = req->fragId;
1940     accreq->localKeyLen = addfragptr.p->m_lqhFragReq.localKeyLength;
1941     accreq->maxLoadFactor = addfragptr.p->m_lqhFragReq.maxLoadFactor;
1942     accreq->minLoadFactor = addfragptr.p->m_lqhFragReq.minLoadFactor;
1943     accreq->kValue = addfragptr.p->m_lqhFragReq.kValue;
1944     accreq->lhFragBits = addfragptr.p->m_lqhFragReq.lh3DistrBits;
1945     accreq->lhDirBits = addfragptr.p->m_lqhFragReq.lh3PageBits;
1946     accreq->keyLength = addfragptr.p->m_lqhFragReq.keyLength;
1947     /* --------------------------------------------------------------------- */
1948     /* Send ACCFRAGREQ, when confirmation is received send 2 * TUPFRAGREQ to */
1949     /* create 2 tuple fragments on this node.                                */
1950     /* --------------------------------------------------------------------- */
1951     addfragptr.p->addfragStatus = AddFragRecord::ACC_ADDFRAG;
1952     sendSignal(fragptr.p->accBlockref, GSN_ACCFRAGREQ,
1953 	       signal, AccFragReq::SignalLength, JBB);
1954     return;
1955   }
1956   if (DictTabInfo::isOrderedIndex(tabptr.p->tableType)) {
1957     jam();
1958     addfragptr.p->addfragStatus = AddFragRecord::WAIT_TUP;
1959     sendAddFragReq(signal);
1960     return;
1961   }
1962   ndbrequire(false);
1963 }//Dblqh::execLQHFRAGREQ()
1964 
1965 /* *************** */
1966 /*  ACCFRAGCONF  > */
1967 /* *************** */
execACCFRAGCONF(Signal * signal)1968 void Dblqh::execACCFRAGCONF(Signal* signal)
1969 {
1970   jamEntry();
1971   addfragptr.i = signal->theData[0];
1972   Uint32 taccConnectptr = signal->theData[1];
1973   //Uint32 fragId1 = signal->theData[2];
1974   Uint32 accFragPtr1 = signal->theData[4];
1975   ptrCheckGuard(addfragptr, caddfragrecFileSize, addFragRecord);
1976   ndbrequire(addfragptr.p->addfragStatus == AddFragRecord::ACC_ADDFRAG);
1977 
1978   addfragptr.p->accConnectptr = taccConnectptr;
1979   fragptr.i = addfragptr.p->fragmentPtr;
1980   c_fragment_pool.getPtr(fragptr);
1981   fragptr.p->accFragptr = accFragPtr1;
1982 
1983   addfragptr.p->addfragStatus = AddFragRecord::WAIT_TUP;
1984   sendAddFragReq(signal);
1985 }//Dblqh::execACCFRAGCONF()
1986 
1987 /* *************** */
1988 /*  TUPFRAGCONF  > */
1989 /* *************** */
execTUPFRAGCONF(Signal * signal)1990 void Dblqh::execTUPFRAGCONF(Signal* signal)
1991 {
1992   jamEntry();
1993   addfragptr.i = signal->theData[0];
1994   Uint32 tupConnectptr = signal->theData[1];
1995   Uint32 tupFragPtr = signal->theData[2];  /* TUP FRAGMENT POINTER */
1996   //Uint32 localFragId = signal->theData[3];  /* LOCAL FRAGMENT ID    */
1997   ptrCheckGuard(addfragptr, caddfragrecFileSize, addFragRecord);
1998   fragptr.i = addfragptr.p->fragmentPtr;
1999   c_fragment_pool.getPtr(fragptr);
2000   tabptr.i = fragptr.p->tabRef;
2001   ptrCheckGuard(tabptr, ctabrecFileSize, tablerec);
2002   fragptr.p->tupFragptr = tupFragPtr;
2003   switch (addfragptr.p->addfragStatus) {
2004   case AddFragRecord::WAIT_TUP:
2005     jam();
2006     fragptr.p->tupFragptr = tupFragPtr;
2007     addfragptr.p->tupConnectptr = tupConnectptr;
2008     if (DictTabInfo::isOrderedIndex(tabptr.p->tableType))
2009     {
2010       addfragptr.p->addfragStatus = AddFragRecord::WAIT_TUX;
2011       sendAddFragReq(signal);
2012       break;
2013     }
2014     goto done_with_frag;
2015     break;
2016   case AddFragRecord::WAIT_TUX:
2017     jam();
2018     fragptr.p->tuxFragptr = tupFragPtr;
2019     addfragptr.p->tuxConnectptr = tupConnectptr;
2020     goto done_with_frag;
2021     break;
2022   done_with_frag:
2023     /* ---------------------------------------------------------------- */
2024     /* Finished create of fragments. Now ready for creating attributes. */
2025     /* ---------------------------------------------------------------- */
2026     fragptr.p->fragStatus = Fragrecord::FSACTIVE;
2027     {
2028       LqhFragConf* conf = (LqhFragConf*)signal->getDataPtrSend();
2029       conf->senderData = addfragptr.p->m_lqhFragReq.senderData;
2030       conf->lqhFragPtr = RNIL;
2031       conf->tableId = addfragptr.p->m_lqhFragReq.tableId;
2032       conf->fragId = fragptr.p->fragId;
2033       conf->changeMask = addfragptr.p->m_lqhFragReq.changeMask;
2034       sendSignal(addfragptr.p->m_lqhFragReq.senderRef, GSN_LQHFRAGCONF,
2035 		 signal, LqhFragConf::SignalLength, JBB);
2036     }
2037     releaseAddfragrec(signal);
2038     break;
2039   default:
2040     ndbrequire(false);
2041     break;
2042   }
2043 }//Dblqh::execTUPFRAGCONF()
2044 
2045 /* *************** */
2046 /*  TUXFRAGCONF  > */
2047 /* *************** */
execTUXFRAGCONF(Signal * signal)2048 void Dblqh::execTUXFRAGCONF(Signal* signal)
2049 {
2050   jamEntry();
2051   execTUPFRAGCONF(signal);
2052 }//Dblqh::execTUXFRAGCONF
2053 
2054 /*
2055  * Add fragment in TUP or TUX.  Called up to 4 times.
2056  */
2057 void
sendAddFragReq(Signal * signal)2058 Dblqh::sendAddFragReq(Signal* signal)
2059 {
2060   fragptr.i = addfragptr.p->fragmentPtr;
2061   c_fragment_pool.getPtr(fragptr);
2062   tabptr.i = fragptr.p->tabRef;
2063   ptrCheckGuard(tabptr, ctabrecFileSize, tablerec);
2064   if (addfragptr.p->addfragStatus == AddFragRecord::WAIT_TUP)
2065   {
2066     TupFragReq* const tupFragReq = (TupFragReq*)signal->getDataPtrSend();
2067     tupFragReq->userPtr = addfragptr.i;
2068     tupFragReq->userRef = cownref;
2069     tupFragReq->reqInfo = 0; /* ADD TABLE */
2070     tupFragReq->tableId = tabptr.i;
2071     tupFragReq->fragId = addfragptr.p->m_lqhFragReq.fragId;
2072     tupFragReq->tablespaceid = addfragptr.p->m_lqhFragReq.tablespace_id;
2073     tupFragReq->maxRowsHigh = addfragptr.p->m_lqhFragReq.maxRowsHigh;
2074     tupFragReq->maxRowsLow = addfragptr.p->m_lqhFragReq.maxRowsLow;
2075     tupFragReq->minRowsHigh = addfragptr.p->m_lqhFragReq.minRowsHigh;
2076     tupFragReq->minRowsLow = addfragptr.p->m_lqhFragReq.minRowsLow;
2077     tupFragReq->changeMask = addfragptr.p->m_lqhFragReq.changeMask;
2078     sendSignal(fragptr.p->tupBlockref, GSN_TUPFRAGREQ,
2079                signal, TupFragReq::SignalLength, JBB);
2080     return;
2081   }
2082   if (addfragptr.p->addfragStatus == AddFragRecord::WAIT_TUX)
2083   {
2084     jam();
2085     ndbrequire(DictTabInfo::isOrderedIndex(tabptr.p->tableType));
2086     TuxFragReq* const tuxreq = (TuxFragReq*)signal->getDataPtrSend();
2087     tuxreq->userPtr = addfragptr.i;
2088     tuxreq->userRef = cownref;
2089     tuxreq->reqInfo = 0; /* ADD TABLE */
2090     tuxreq->tableId = tabptr.i;
2091     tuxreq->fragId = addfragptr.p->m_lqhFragReq.fragId;
2092     tuxreq->primaryTableId = tabptr.p->primaryTableId;
2093     // pointer to index fragment in TUP
2094     tuxreq->tupIndexFragPtrI = fragptr.p->tupFragptr;
2095     // pointers to table fragments in TUP and ACC
2096     FragrecordPtr tFragPtr;
2097     tFragPtr.i = fragptr.p->tableFragptr;
2098     c_fragment_pool.getPtr(tFragPtr);
2099     tuxreq->tupTableFragPtrI = tFragPtr.p->tupFragptr;
2100     tuxreq->accTableFragPtrI = tFragPtr.p->accFragptr;
2101     sendSignal(fragptr.p->tuxBlockref, GSN_TUXFRAGREQ,
2102                signal, TuxFragReq::SignalLength, JBB);
2103     return;
2104   }
2105 }//Dblqh::sendAddFragReq
2106 
2107 
2108 /* ************************************************************************>> */
2109 /*  TAB_COMMITREQ: Commit the new table for use in transactions. Sender DICT. */
2110 /* ************************************************************************>> */
execTAB_COMMITREQ(Signal * signal)2111 void Dblqh::execTAB_COMMITREQ(Signal* signal)
2112 {
2113   jamEntry();
2114   Uint32 dihPtr = signal->theData[0];
2115   BlockReference dihBlockref = signal->theData[1];
2116   tabptr.i = signal->theData[2];
2117 
2118   if (tabptr.i >= ctabrecFileSize) {
2119     jam();
2120     terrorCode = ZTAB_FILE_SIZE;
2121     signal->theData[0] = dihPtr;
2122     signal->theData[1] = cownNodeid;
2123     signal->theData[2] = tabptr.i;
2124     signal->theData[3] = terrorCode;
2125     sendSignal(dihBlockref, GSN_TAB_COMMITREF, signal, 4, JBB);
2126     return;
2127   }//if
2128   ptrAss(tabptr, tablerec);
2129   if (tabptr.p->tableStatus != Tablerec::ADD_TABLE_ONGOING) {
2130     jam();
2131     terrorCode = ZTAB_STATE_ERROR;
2132     signal->theData[0] = dihPtr;
2133     signal->theData[1] = cownNodeid;
2134     signal->theData[2] = tabptr.i;
2135     signal->theData[3] = terrorCode;
2136     signal->theData[4] = tabptr.p->tableStatus;
2137     sendSignal(dihBlockref, GSN_TAB_COMMITREF, signal, 5, JBB);
2138     ndbrequire(false);
2139     return;
2140   }//if
2141   tabptr.p->usageCountR = 0;
2142   tabptr.p->usageCountW = 0;
2143   tabptr.p->tableStatus = Tablerec::TABLE_DEFINED;
2144   signal->theData[0] = dihPtr;
2145   signal->theData[1] = cownNodeid;
2146   signal->theData[2] = tabptr.i;
2147   sendSignal(dihBlockref, GSN_TAB_COMMITCONF, signal, 3, JBB);
2148 
2149   return;
2150 }//Dblqh::execTAB_COMMITREQ()
2151 
2152 
fragrefLab(Signal * signal,Uint32 errorCode,const LqhFragReq * req)2153 void Dblqh::fragrefLab(Signal* signal,
2154                        Uint32 errorCode,
2155                        const LqhFragReq* req)
2156 {
2157   LqhFragRef * ref = (LqhFragRef*)signal->getDataPtrSend();
2158   ref->senderData = req->senderData;
2159   ref->errorCode = errorCode;
2160   ref->requestInfo = req->requestInfo;
2161   ref->tableId = req->tableId;
2162   ref->fragId = req->fragId;
2163   ref->changeMask = req->changeMask;
2164   sendSignal(req->senderRef, GSN_LQHFRAGREF, signal,
2165 	     LqhFragRef::SignalLength, JBB);
2166   return;
2167 }//Dblqh::fragrefLab()
2168 
2169 /*
2170  * Abort on-going ops.
2171  */
abortAddFragOps(Signal * signal)2172 void Dblqh::abortAddFragOps(Signal* signal)
2173 {
2174   if (addfragptr.p->tupConnectptr != RNIL) {
2175     jam();
2176     TupFragReq* const tupFragReq = (TupFragReq*)signal->getDataPtrSend();
2177     tupFragReq->userPtr = (Uint32)-1;
2178     tupFragReq->userRef = addfragptr.p->tupConnectptr;
2179     sendSignal(ctupBlockref, GSN_TUPFRAGREQ, signal, 2, JBB);
2180     addfragptr.p->tupConnectptr = RNIL;
2181   }
2182   if (addfragptr.p->tuxConnectptr != RNIL) {
2183     jam();
2184     TuxFragReq* const tuxFragReq = (TuxFragReq*)signal->getDataPtrSend();
2185     tuxFragReq->userPtr = (Uint32)-1;
2186     tuxFragReq->userRef = addfragptr.p->tuxConnectptr;
2187     sendSignal(ctuxBlockref, GSN_TUXFRAGREQ, signal, 2, JBB);
2188     addfragptr.p->tuxConnectptr = RNIL;
2189   }
2190 }
2191 
2192 /* ************>> */
2193 /*  ACCFRAGREF  > */
2194 /* ************>> */
execACCFRAGREF(Signal * signal)2195 void Dblqh::execACCFRAGREF(Signal* signal)
2196 {
2197   jamEntry();
2198   addfragptr.i = signal->theData[0];
2199   ptrCheckGuard(addfragptr, caddfragrecFileSize, addFragRecord);
2200   Uint32 errorCode = terrorCode = signal->theData[1];
2201   ndbrequire(addfragptr.p->addfragStatus == AddFragRecord::ACC_ADDFRAG);
2202 
2203   fragrefLab(signal, errorCode, &addfragptr.p->m_lqhFragReq);
2204   releaseAddfragrec(signal);
2205 
2206   return;
2207 }//Dblqh::execACCFRAGREF()
2208 
2209 /* ************>> */
2210 /*  TUPFRAGREF  > */
2211 /* ************>> */
execTUPFRAGREF(Signal * signal)2212 void Dblqh::execTUPFRAGREF(Signal* signal)
2213 {
2214   jamEntry();
2215   addfragptr.i = signal->theData[0];
2216   ptrCheckGuard(addfragptr, caddfragrecFileSize, addFragRecord);
2217   Uint32 errorCode = terrorCode = signal->theData[1];
2218   fragptr.i = addfragptr.p->fragmentPtr;
2219   c_fragment_pool.getPtr(fragptr);
2220 
2221   // no operation to release, just add some jams
2222   switch (addfragptr.p->addfragStatus) {
2223   case AddFragRecord::WAIT_TUP:
2224     jam();
2225     break;
2226   case AddFragRecord::WAIT_TUX:
2227     jam();
2228     break;
2229   default:
2230     ndbrequire(false);
2231     break;
2232   }
2233 
2234   fragrefLab(signal, errorCode, &addfragptr.p->m_lqhFragReq);
2235   releaseAddfragrec(signal);
2236 
2237 }//Dblqh::execTUPFRAGREF()
2238 
2239 void
execDROP_FRAG_REQ(Signal * signal)2240 Dblqh::execDROP_FRAG_REQ(Signal* signal)
2241 {
2242   DropFragReq *req = (DropFragReq*)signal->getDataPtr();
2243   seizeAddfragrec(signal);
2244   addfragptr.p->m_dropFragReq = *req;
2245 
2246   /**
2247    * 1 - self
2248    * 2 - acc
2249    * 3 - tup
2250    * 4 - tux (optional)
2251    */
2252   tabptr.i = req->tableId;
2253   ptrCheckGuard(tabptr, ctabrecFileSize, tablerec);
2254 
2255   deleteFragrec(req->fragId);
2256 
2257   Uint32 ref = calcInstanceBlockRef(DBACC);
2258   if (DictTabInfo::isOrderedIndex(tabptr.p->tableType))
2259   {
2260     jam();
2261     ref = calcInstanceBlockRef(DBTUP);
2262   }
2263 
2264   req->senderRef = reference();
2265   req->senderData = addfragptr.i;
2266   sendSignal(ref, GSN_DROP_FRAG_REQ, signal, DropFragReq::SignalLength, JBB);
2267 }
2268 
2269 void
execDROP_FRAG_REF(Signal * signal)2270 Dblqh::execDROP_FRAG_REF(Signal* signal)
2271 {
2272   ndbrequire(false);
2273 }
2274 
2275 void
execDROP_FRAG_CONF(Signal * signal)2276 Dblqh::execDROP_FRAG_CONF(Signal* signal)
2277 {
2278   DropFragConf* conf = (DropFragConf*)signal->getDataPtr();
2279   addfragptr.i = conf->senderData;
2280   ptrCheckGuard(addfragptr, caddfragrecFileSize, addFragRecord);
2281 
2282   Uint32 ref = RNIL;
2283   switch(refToMain(conf->senderRef)){
2284   case DBACC:
2285     jam();
2286     ref = calcInstanceBlockRef(DBTUP);
2287     break;
2288   case DBTUP:
2289   {
2290     tabptr.i = addfragptr.p->m_dropFragReq.tableId;
2291     ptrCheckGuard(tabptr, ctabrecFileSize, tablerec);
2292     if (DictTabInfo::isOrderedIndex(tabptr.p->tableType))
2293     {
2294       jam();
2295       ref = calcInstanceBlockRef(DBTUX);
2296     }
2297     break;
2298   }
2299   case DBTUX:
2300     break;
2301   default:
2302     ndbrequire(false);
2303   }
2304 
2305   if (ref != RNIL)
2306   {
2307     DropFragReq* req = (DropFragReq*)signal->getDataPtrSend();
2308     * req = addfragptr.p->m_dropFragReq;
2309     req->senderRef = reference();
2310     req->senderData = addfragptr.i;
2311     sendSignal(ref, GSN_DROP_FRAG_REQ, signal, DropFragReq::SignalLength,
2312                JBB);
2313     return;
2314   }
2315 
2316   conf->senderRef = reference();
2317   conf->senderData = addfragptr.p->m_dropFragReq.senderData;
2318   conf->tableId = addfragptr.p->m_dropFragReq.tableId;
2319   conf->fragId = addfragptr.p->m_dropFragReq.fragId;
2320   sendSignal(addfragptr.p->m_dropFragReq.senderRef, GSN_DROP_FRAG_CONF,
2321              signal, DropFragConf::SignalLength, JBB);
2322 
2323   releaseAddfragrec(signal);
2324 }
2325 
2326 /* ************>> */
2327 /*  TUXFRAGREF  > */
2328 /* ************>> */
execTUXFRAGREF(Signal * signal)2329 void Dblqh::execTUXFRAGREF(Signal* signal)
2330 {
2331   jamEntry();
2332   execTUPFRAGREF(signal);
2333 }//Dblqh::execTUXFRAGREF
2334 
2335 void
execPREP_DROP_TAB_REQ(Signal * signal)2336 Dblqh::execPREP_DROP_TAB_REQ(Signal* signal){
2337   jamEntry();
2338 
2339   PrepDropTabReq* req = (PrepDropTabReq*)signal->getDataPtr();
2340 
2341   Uint32 senderRef = req->senderRef;
2342   Uint32 senderData = req->senderData;
2343 
2344   TablerecPtr tabPtr;
2345   tabPtr.i = req->tableId;
2346   ptrCheckGuard(tabPtr, ctabrecFileSize, tablerec);
2347 
2348   Uint32 errCode = 0;
2349   switch(tabPtr.p->tableStatus) {
2350   case Tablerec::TABLE_DEFINED:
2351     jam();
2352     break;
2353   case Tablerec::NOT_DEFINED:
2354     jam();
2355     // Fall through
2356   case Tablerec::ADD_TABLE_ONGOING:
2357     jam();
2358     errCode = PrepDropTabRef::NoSuchTable;
2359     break;
2360   case Tablerec::PREP_DROP_TABLE_DONE:
2361     jam();
2362     errCode = PrepDropTabRef::DropInProgress;
2363     break;
2364   case Tablerec::DROP_TABLE_WAIT_USAGE:
2365   case Tablerec::DROP_TABLE_WAIT_DONE:
2366   case Tablerec::DROP_TABLE_ACC:
2367   case Tablerec::DROP_TABLE_TUP:
2368   case Tablerec::DROP_TABLE_TUX:
2369     jam();
2370     errCode = PrepDropTabRef::DropInProgress;
2371   case Tablerec::TABLE_READ_ONLY:
2372     jam();
2373     errCode = PrepDropTabRef::InvalidTableState;
2374     break;
2375   }
2376 
2377   if(errCode != 0)
2378   {
2379     jam();
2380 
2381     PrepDropTabRef* ref = (PrepDropTabRef*)signal->getDataPtrSend();
2382     ref->senderRef = reference();
2383     ref->senderData = senderData;
2384     ref->tableId = tabPtr.i;
2385     ref->errorCode = errCode;
2386     sendSignal(senderRef, GSN_PREP_DROP_TAB_REF, signal,
2387 	       PrepDropTabRef::SignalLength, JBB);
2388     return;
2389   }
2390 
2391   tabPtr.p->tableStatus = Tablerec::PREP_DROP_TABLE_DONE;
2392 
2393   PrepDropTabConf * conf = (PrepDropTabConf*)signal->getDataPtrSend();
2394   conf->tableId = tabPtr.i;
2395   conf->senderRef = reference();
2396   conf->senderData = senderData;
2397   sendSignal(senderRef, GSN_PREP_DROP_TAB_CONF, signal,
2398 	     PrepDropTabConf::SignalLength, JBB);
2399 }
2400 
2401 void
dropTab_wait_usage(Signal * signal)2402 Dblqh::dropTab_wait_usage(Signal* signal){
2403 
2404   TablerecPtr tabPtr;
2405   tabPtr.i = signal->theData[1];
2406   ptrCheckGuard(tabPtr, ctabrecFileSize, tablerec);
2407 
2408   Uint32 senderRef = signal->theData[2];
2409   Uint32 senderData = signal->theData[3];
2410 
2411   ndbrequire(tabPtr.p->tableStatus == Tablerec::DROP_TABLE_WAIT_USAGE);
2412 
2413   if (tabPtr.p->usageCountR > 0 || tabPtr.p->usageCountW > 0)
2414   {
2415     jam();
2416     sendSignalWithDelay(reference(), GSN_CONTINUEB, signal, 100, 4);
2417     return;
2418   }
2419 
2420   bool lcpDone = true;
2421   lcpPtr.i = 0;
2422   ptrAss(lcpPtr, lcpRecord);
2423   if(lcpPtr.p->lcpState != LcpRecord::LCP_IDLE)
2424   {
2425     jam();
2426 
2427     if(lcpPtr.p->currentFragment.lcpFragOrd.tableId == tabPtr.i)
2428     {
2429       jam();
2430       lcpDone = false;
2431     }
2432 
2433     if(lcpPtr.p->lcpQueued &&
2434        lcpPtr.p->queuedFragment.lcpFragOrd.tableId == tabPtr.i)
2435     {
2436       jam();
2437       lcpDone = false;
2438     }
2439   }
2440 
2441   if(!lcpDone)
2442   {
2443     jam();
2444     sendSignalWithDelay(reference(), GSN_CONTINUEB, signal, 100, 4);
2445     return;
2446   }
2447 
2448   tabPtr.p->tableStatus = Tablerec::DROP_TABLE_WAIT_DONE;
2449 
2450   DropTabConf * conf = (DropTabConf*)signal->getDataPtrSend();
2451   conf->tableId = tabPtr.i;
2452   conf->senderRef = reference();
2453   conf->senderData = senderData;
2454   sendSignal(senderRef, GSN_DROP_TAB_CONF, signal,
2455 	     DropTabConf::SignalLength, JBB);
2456 }
2457 
2458 void
execDROP_TAB_REQ(Signal * signal)2459 Dblqh::execDROP_TAB_REQ(Signal* signal){
2460   jamEntry();
2461 
2462   DropTabReq reqCopy = * (DropTabReq*)signal->getDataPtr();
2463   DropTabReq* req = &reqCopy;
2464 
2465   TablerecPtr tabPtr;
2466   tabPtr.i = req->tableId;
2467   ptrCheckGuard(tabPtr, ctabrecFileSize, tablerec);
2468 
2469   Uint32 errCode = 0;
2470   switch((DropTabReq::RequestType)req->requestType) {
2471   case DropTabReq::RestartDropTab:
2472     jam();
2473     tabPtr.p->tableStatus = Tablerec::DROP_TABLE_WAIT_DONE;
2474     break;
2475   case DropTabReq::CreateTabDrop:
2476     jam();
2477     tabPtr.p->tableStatus = Tablerec::DROP_TABLE_WAIT_DONE;
2478     break;
2479   case DropTabReq::OnlineDropTab:
2480     jam();
2481     switch(tabPtr.p->tableStatus) {
2482     case Tablerec::TABLE_DEFINED:
2483       jam();
2484       errCode = DropTabRef::DropWoPrep;
2485       break;
2486     case Tablerec::NOT_DEFINED:
2487       jam();
2488       errCode = DropTabRef::NoSuchTable;
2489       break;
2490     case Tablerec::ADD_TABLE_ONGOING:
2491       jam();
2492       ndbassert(false);
2493     case Tablerec::PREP_DROP_TABLE_DONE:
2494       jam();
2495       tabPtr.p->tableStatus = Tablerec::DROP_TABLE_WAIT_USAGE;
2496       signal->theData[0] = ZDROP_TABLE_WAIT_USAGE;
2497       signal->theData[1] = tabPtr.i;
2498       signal->theData[2] = req->senderRef;
2499       signal->theData[3] = req->senderData;
2500       dropTab_wait_usage(signal);
2501       return;
2502       break;
2503     case Tablerec::DROP_TABLE_WAIT_USAGE:
2504     case Tablerec::DROP_TABLE_ACC:
2505     case Tablerec::DROP_TABLE_TUP:
2506     case Tablerec::DROP_TABLE_TUX:
2507       ndbrequire(false);
2508     case Tablerec::DROP_TABLE_WAIT_DONE:
2509       jam();
2510       break;
2511     case Tablerec::TABLE_READ_ONLY:
2512       jam();
2513       errCode = DropTabRef::InvalidTableState;
2514       break;
2515     }
2516   }
2517 
2518   if (errCode)
2519   {
2520     jam();
2521     DropTabRef * ref = (DropTabRef*)signal->getDataPtrSend();
2522     ref->tableId = tabPtr.i;
2523     ref->senderRef = reference();
2524     ref->senderData = req->senderData;
2525     ref->errorCode = errCode;
2526     sendSignal(req->senderRef, GSN_DROP_TAB_REF, signal,
2527                DropTabRef::SignalLength, JBB);
2528     return;
2529   }
2530 
2531   ndbrequire(tabPtr.p->usageCountR == 0 && tabPtr.p->usageCountW == 0);
2532   seizeAddfragrec(signal);
2533   addfragptr.p->m_dropTabReq = * req;
2534   dropTable_nextStep(signal, addfragptr);
2535 }
2536 
2537 void
execDROP_TAB_REF(Signal * signal)2538 Dblqh::execDROP_TAB_REF(Signal* signal)
2539 {
2540   jamEntry();
2541   DropTabRef * ref = (DropTabRef*)signal->getDataPtr();
2542 
2543 #if defined ERROR_INSERT || defined VM_TRACE
2544   jamLine(ref->errorCode);
2545   ndbrequire(false);
2546 #endif
2547 
2548   Ptr<AddFragRecord> addFragPtr;
2549   addFragPtr.i = ref->senderData;
2550   ptrCheckGuard(addFragPtr, caddfragrecFileSize, addFragRecord);
2551   dropTable_nextStep(signal, addFragPtr);
2552 }
2553 
2554 void
execDROP_TAB_CONF(Signal * signal)2555 Dblqh::execDROP_TAB_CONF(Signal* signal)
2556 {
2557   jamEntry();
2558   DropTabConf * conf = (DropTabConf*)signal->getDataPtr();
2559 
2560   Ptr<AddFragRecord> addFragPtr;
2561   addFragPtr.i = conf->senderData;
2562   ptrCheckGuard(addFragPtr, caddfragrecFileSize, addFragRecord);
2563   dropTable_nextStep(signal, addFragPtr);
2564 }
2565 
2566 void
dropTable_nextStep(Signal * signal,Ptr<AddFragRecord> addFragPtr)2567 Dblqh::dropTable_nextStep(Signal* signal, Ptr<AddFragRecord> addFragPtr)
2568 {
2569   jam();
2570 
2571   TablerecPtr tabPtr;
2572   tabPtr.i = addFragPtr.p->m_dropTabReq.tableId;
2573   ptrCheckGuard(tabPtr, ctabrecFileSize, tablerec);
2574 
2575   Uint32 ref = 0;
2576   if (tabPtr.p->tableStatus == Tablerec::DROP_TABLE_WAIT_DONE)
2577   {
2578     jam();
2579     if (DictTabInfo::isTable(tabPtr.p->tableType) ||
2580         DictTabInfo::isHashIndex(tabPtr.p->tableType))
2581     {
2582       jam();
2583       ref = calcInstanceBlockRef(DBACC);
2584       tabPtr.p->tableStatus = Tablerec::DROP_TABLE_ACC;
2585     }
2586     else
2587     {
2588       jam();
2589       ref = calcInstanceBlockRef(DBTUP);
2590       tabPtr.p->tableStatus = Tablerec::DROP_TABLE_TUP;
2591     }
2592   }
2593   else if (tabPtr.p->tableStatus == Tablerec::DROP_TABLE_ACC)
2594   {
2595     jam();
2596     ref = calcInstanceBlockRef(DBTUP);
2597     tabPtr.p->tableStatus = Tablerec::DROP_TABLE_TUP;
2598   }
2599   else if (tabPtr.p->tableStatus == Tablerec::DROP_TABLE_TUP)
2600   {
2601     jam();
2602     if (DictTabInfo::isOrderedIndex(tabPtr.p->tableType))
2603     {
2604       jam();
2605       ref = calcInstanceBlockRef(DBTUX);
2606       tabPtr.p->tableStatus = Tablerec::DROP_TABLE_TUX;
2607     }
2608   }
2609 
2610   if (ref)
2611   {
2612     jam();
2613     DropTabReq* req = (DropTabReq*)signal->getDataPtrSend();
2614     req->senderData = addFragPtr.i;
2615     req->senderRef = reference();
2616     req->tableId = tabPtr.i;
2617     req->tableVersion = tabPtr.p->schemaVersion;
2618     req->requestType = addFragPtr.p->m_dropTabReq.requestType;
2619     sendSignal(ref, GSN_DROP_TAB_REQ, signal,
2620                DropTabReq::SignalLength, JBB);
2621     return;
2622   }
2623 
2624   removeTable(tabPtr.i);
2625   tabPtr.p->tableStatus = Tablerec::NOT_DEFINED;
2626 
2627   DropTabConf* conf = (DropTabConf*)signal->getDataPtrSend();
2628   conf->senderRef = reference();
2629   conf->senderData = addFragPtr.p->m_dropTabReq.senderData;
2630   conf->tableId = tabPtr.i;
2631   sendSignal(addFragPtr.p->m_dropTabReq.senderRef, GSN_DROP_TAB_CONF, signal,
2632              DropTabConf::SignalLength, JBB);
2633 
2634   addfragptr = addFragPtr;
2635   releaseAddfragrec(signal);
2636 }
2637 
removeTable(Uint32 tableId)2638 void Dblqh::removeTable(Uint32 tableId)
2639 {
2640   tabptr.i = tableId;
2641   ptrCheckGuard(tabptr, ctabrecFileSize, tablerec);
2642 
2643   for (Uint32 i = 0; i < MAX_FRAG_PER_NODE; i++) {
2644     jam();
2645     if (tabptr.p->fragid[i] != ZNIL) {
2646       jam();
2647       deleteFragrec(tabptr.p->fragid[i]);
2648     }//if
2649   }//for
2650 }//Dblqh::removeTable()
2651 
2652 void
execALTER_TAB_REQ(Signal * signal)2653 Dblqh::execALTER_TAB_REQ(Signal* signal)
2654 {
2655   jamEntry();
2656 
2657   if(!assembleFragments(signal))
2658     return;
2659 
2660   AlterTabReq copy = *(AlterTabReq*)signal->getDataPtr();
2661   const AlterTabReq* req = &copy;
2662   const Uint32 senderRef = req->senderRef;
2663   const Uint32 senderData = req->senderData;
2664   const Uint32 tableId = req->tableId;
2665   const Uint32 tableVersion = req->tableVersion;
2666   const Uint32 newTableVersion = req->newTableVersion;
2667   AlterTabReq::RequestType requestType =
2668     (AlterTabReq::RequestType) req->requestType;
2669 
2670   TablerecPtr tablePtr;
2671   tablePtr.i = tableId;
2672   ptrCheckGuard(tablePtr, ctabrecFileSize, tablerec);
2673 
2674   Uint32 len = signal->getLength();
2675   switch (requestType) {
2676   case AlterTabReq::AlterTablePrepare:
2677     jam();
2678     break;
2679   case AlterTabReq::AlterTableRevert:
2680     jam();
2681     tablePtr.p->schemaVersion = tableVersion;
2682     break;
2683   case AlterTabReq::AlterTableCommit:
2684     jam();
2685     tablePtr.p->schemaVersion = newTableVersion;
2686     if (AlterTableReq::getReorgFragFlag(req->changeMask))
2687     {
2688       jam();
2689       commit_reorg(tablePtr);
2690     }
2691     break;
2692   case AlterTabReq::AlterTableComplete:
2693     jam();
2694     break;
2695   case AlterTabReq::AlterTableSumaEnable:
2696     jam();
2697     break;
2698   case AlterTabReq::AlterTableSumaFilter:
2699     jam();
2700     signal->theData[len++] = cnewestGci + 3;
2701     break;
2702   case AlterTabReq::AlterTableReadOnly:
2703     jam();
2704     ndbrequire(tablePtr.p->tableStatus == Tablerec::TABLE_DEFINED);
2705     tablePtr.p->tableStatus = Tablerec::TABLE_READ_ONLY;
2706     signal->theData[0] = ZWAIT_READONLY;
2707     signal->theData[1] = tablePtr.i;
2708     signal->theData[2] = senderRef;
2709     signal->theData[3] = senderData;
2710     sendSignal(reference(), GSN_CONTINUEB, signal, 4, JBB);
2711     return;
2712   case AlterTabReq::AlterTableReadWrite:
2713     jam();
2714     ndbrequire(tablePtr.p->tableStatus == Tablerec::TABLE_READ_ONLY);
2715     tablePtr.p->tableStatus = Tablerec::TABLE_DEFINED;
2716     break;
2717   default:
2718     ndbrequire(false);
2719     break;
2720   }
2721 
2722   EXECUTE_DIRECT(DBTUP, GSN_ALTER_TAB_REQ, signal, len);
2723   jamEntry();
2724 
2725   Uint32 errCode = signal->theData[0];
2726   Uint32 connectPtr = signal->theData[1];
2727   if (errCode == 0)
2728   {
2729     // Request handled successfully
2730     AlterTabConf* conf = (AlterTabConf*)signal->getDataPtrSend();
2731     conf->senderRef = reference();
2732     conf->senderData = senderData;
2733     conf->connectPtr = connectPtr;
2734     sendSignal(senderRef, GSN_ALTER_TAB_CONF, signal,
2735                AlterTabConf::SignalLength, JBB);
2736   }
2737   else if (errCode == ~Uint32(0))
2738   {
2739     /**
2740      * Wait
2741      */
2742     ndbrequire(requestType == AlterTabReq::AlterTableSumaFilter);
2743     signal->theData[0] = ZWAIT_REORG_SUMA_FILTER_ENABLED;
2744     signal->theData[1] = cnewestGci + 3;
2745     signal->theData[2] = senderData;
2746     signal->theData[3] = connectPtr;
2747     signal->theData[4] = senderRef;
2748     wait_reorg_suma_filter_enabled(signal);
2749     return;
2750   }
2751   else
2752   {
2753     jam();
2754     AlterTabRef* ref = (AlterTabRef*)signal->getDataPtrSend();
2755     ref->senderRef = reference();
2756     ref->senderData = senderData;
2757     ref->connectPtr = connectPtr;
2758     ref->errorCode = errCode;
2759     sendSignal(senderRef, GSN_ALTER_TAB_REF, signal,
2760                AlterTabRef::SignalLength, JBB);
2761   }
2762 }
2763 
2764 void
wait_reorg_suma_filter_enabled(Signal * signal)2765 Dblqh::wait_reorg_suma_filter_enabled(Signal* signal)
2766 {
2767   if (cnewestCompletedGci >= signal->theData[1])
2768   {
2769     jam();
2770     Uint32 senderData = signal->theData[2];
2771     Uint32 connectPtr = signal->theData[3];
2772     Uint32 senderRef = signal->theData[4];
2773 
2774     AlterTabConf* conf = (AlterTabConf*)signal->getDataPtrSend();
2775     conf->senderRef = reference();
2776     conf->senderData = senderData;
2777     conf->connectPtr = connectPtr;
2778     sendSignal(senderRef, GSN_ALTER_TAB_CONF, signal,
2779                AlterTabConf::SignalLength, JBB);
2780     return;
2781   }
2782   sendSignalWithDelay(reference(), GSN_CONTINUEB, signal, 500, 5);
2783 }
2784 
2785 void
commit_reorg(TablerecPtr tablePtr)2786 Dblqh::commit_reorg(TablerecPtr tablePtr)
2787 {
2788   for (Uint32 i = 0; i < MAX_FRAG_PER_NODE; i++)
2789   {
2790     jam();
2791     Ptr<Fragrecord> fragPtr;
2792     if ((fragPtr.i = tablePtr.p->fragrec[i]) != RNIL)
2793     {
2794       jam();
2795       c_fragment_pool.getPtr(fragPtr);
2796       fragPtr.p->fragDistributionKey = (fragPtr.p->fragDistributionKey+1)&0xFF;
2797     }
2798   }
2799 }
2800 
2801 void
wait_readonly(Signal * signal)2802 Dblqh::wait_readonly(Signal* signal)
2803 {
2804   jam();
2805 
2806   Uint32 tableId = signal->theData[1];
2807 
2808   TablerecPtr tablePtr;
2809   tablePtr.i = tableId;
2810   ptrCheckGuard(tablePtr, ctabrecFileSize, tablerec);
2811   ndbrequire(tablePtr.p->tableStatus == Tablerec::TABLE_READ_ONLY);
2812 
2813   if (tablePtr.p->usageCountW > 0)
2814   {
2815     jam();
2816     sendSignalWithDelay(reference(), GSN_CONTINUEB, signal, 3000,
2817                         signal->getLength());
2818     return;
2819   }
2820 
2821   Uint32 senderRef = signal->theData[2];
2822   Uint32 senderData = signal->theData[3];
2823 
2824   // Request handled successfully
2825   AlterTabConf * conf = (AlterTabConf*)signal->getDataPtrSend();
2826   conf->senderRef = reference();
2827   conf->senderData = senderData;
2828   sendSignal(senderRef, GSN_ALTER_TAB_CONF, signal,
2829 	     AlterTabConf::SignalLength, JBB);
2830 }
2831 
2832 /* ************************************************************************>>
2833  * TIME_SIGNAL: Handles time-out of local operations. This is a clean-up
2834  * handler. If no other measure has succeeded in cleaning up after time-outs
2835  * or else then this routine will remove the transaction after 120 seconds of
2836  * inactivity. The check is performed once per 10 second. Sender is QMGR.
2837  * ************************************************************************>> */
execTIME_SIGNAL(Signal * signal)2838 void Dblqh::execTIME_SIGNAL(Signal* signal)
2839 {
2840   jamEntry();
2841 
2842   cLqhTimeOutCount ++;
2843   cLqhTimeOutCheckCount ++;
2844 
2845   for (logPartPtr.i = 0; logPartPtr.i < clogPartFileSize; logPartPtr.i++)
2846   {
2847     jam();
2848     ptrCheckGuard(logPartPtr, clogPartFileSize, logPartRecord);
2849     int ret = logPartPtr.p->m_io_tracker.tick(10 * cLqhTimeOutCount,
2850                                               c_max_redo_lag,
2851                                               c_max_redo_lag_counter);
2852     if (ret < 0)
2853     {
2854       /**
2855        * set problem
2856        */
2857       update_log_problem(signal, logPartPtr,
2858                          LogPartRecord::P_REDO_IO_PROBLEM, true);
2859     }
2860     else if (ret > 0)
2861     {
2862       /**
2863        * clear
2864        */
2865       update_log_problem(signal, logPartPtr,
2866                          LogPartRecord::P_REDO_IO_PROBLEM, false);
2867     }
2868   }
2869 
2870   if (cLqhTimeOutCheckCount < 1000) {
2871     jam();
2872     return;
2873   }//if
2874 
2875   cLqhTimeOutCheckCount = 0;
2876 #ifdef VM_TRACE
2877   TcConnectionrecPtr tTcConptr;
2878 
2879   for (tTcConptr.i = 0; tTcConptr.i < ctcConnectrecFileSize;
2880        tTcConptr.i++) {
2881     jam();
2882     ptrAss(tTcConptr, tcConnectionrec);
2883     if ((tTcConptr.p->tcTimer != 0) &&
2884 	((tTcConptr.p->tcTimer + 12000) < cLqhTimeOutCount)) {
2885       ndbout << "Dblqh::execTIME_SIGNAL"<<endl
2886 	     << "Timeout found in tcConnectRecord " <<tTcConptr.i<<endl
2887 	     << " cLqhTimeOutCount = " << cLqhTimeOutCount << endl
2888 	     << " tcTimer="<<tTcConptr.p->tcTimer<<endl
2889 	     << " tcTimer+12000="<<tTcConptr.p->tcTimer + 12000<<endl;
2890 
2891       signal->theData[0] = 2307;
2892       signal->theData[1] = tTcConptr.i;
2893       execDUMP_STATE_ORD(signal);
2894 
2895       // Reset the timer
2896       tTcConptr.p->tcTimer = 0;
2897     }//if
2898   }//for
2899 #endif
2900 #ifdef VM_TRACE
2901   for (lfoPtr.i = 0; lfoPtr.i < clfoFileSize; lfoPtr.i++) {
2902     ptrAss(lfoPtr, logFileOperationRecord);
2903     if ((lfoPtr.p->lfoTimer != 0) &&
2904         ((lfoPtr.p->lfoTimer + 12000) < cLqhTimeOutCount)) {
2905       ndbout << "We have lost LFO record" << endl;
2906       ndbout << "index = " << lfoPtr.i;
2907       ndbout << "State = " << lfoPtr.p->lfoState;
2908       ndbout << " Page No = " << lfoPtr.p->lfoPageNo;
2909       ndbout << " noPagesRw = " << lfoPtr.p->noPagesRw;
2910       ndbout << "lfoWordWritten = " << lfoPtr.p->lfoWordWritten << endl;
2911       lfoPtr.p->lfoTimer = cLqhTimeOutCount;
2912     }//if
2913   }//for
2914 
2915 #endif
2916 
2917 #if 0
2918   LcpRecordPtr TlcpPtr;
2919   // Print information about the current local checkpoint
2920   TlcpPtr.i = 0;
2921   ptrAss(TlcpPtr, lcpRecord);
2922   ndbout << "Information about LCP in this LQH" << endl
2923 	 << "  lcpState="<<TlcpPtr.p->lcpState<<endl
2924 	 << "   firstLcpLocAcc="<<TlcpPtr.p->firstLcpLocAcc<<endl
2925 	 << "   firstLcpLocTup="<<TlcpPtr.p->firstLcpLocTup<<endl
2926 	 << "   lcpAccptr="<<TlcpPtr.p->lcpAccptr<<endl
2927 	 << "   lastFragmentFlag="<<TlcpPtr.p->lastFragmentFlag<<endl
2928 	 << "   lcpQueued="<<TlcpPtr.p->lcpQueued<<endl
2929 	 << "   reportEmptyref="<< TlcpPtr.p->reportEmptyRef<<endl
2930 	 << "   reportEmpty="<<TlcpPtr.p->reportEmpty<<endl;
2931 #endif
2932 }//Dblqh::execTIME_SIGNAL()
2933 
2934 /* ######################################################################### */
2935 /* #######                  EXECUTION MODULE                         ####### */
2936 /* THIS MODULE HANDLES THE RECEPTION OF LQHKEYREQ AND ALL PROCESSING         */
2937 /* OF OPERATIONS ON BEHALF OF THIS REQUEST. THIS DOES ALSO INVOLVE           */
2938 /* RECEPTION OF VARIOUS TYPES OF ATTRINFO AND KEYINFO. IT DOES ALSO          */
2939 /* INVOLVE COMMUNICATION WITH ACC AND TUP.                                   */
2940 /* ######################################################################### */
2941 
noFreeRecordLab(Signal * signal,const LqhKeyReq * lqhKeyReq,Uint32 errCode)2942 void Dblqh::noFreeRecordLab(Signal* signal,
2943 			    const LqhKeyReq * lqhKeyReq,
2944 			    Uint32 errCode)
2945 {
2946   jamEntry();
2947   const Uint32 transid1  = lqhKeyReq->transId1;
2948   const Uint32 transid2  = lqhKeyReq->transId2;
2949   const Uint32 reqInfo   = lqhKeyReq->requestInfo;
2950 
2951   if(errCode == ZNO_FREE_MARKER_RECORDS_ERROR ||
2952      errCode == ZNODE_SHUTDOWN_IN_PROGESS ||
2953      errCode == ZNODE_FAILURE_ERROR){
2954     jam();
2955     releaseTcrec(signal, tcConnectptr);
2956   }
2957 
2958   if (LqhKeyReq::getDirtyFlag(reqInfo) &&
2959       LqhKeyReq::getOperation(reqInfo) == ZREAD &&
2960       !LqhKeyReq::getNormalProtocolFlag(reqInfo)){
2961     jam();
2962     /* Dirty read sends TCKEYREF direct to client, and nothing to TC */
2963     ndbrequire(LqhKeyReq::getApplicationAddressFlag(reqInfo));
2964     const Uint32 apiRef   = lqhKeyReq->variableData[0];
2965     const Uint32 apiOpRec = lqhKeyReq->variableData[1];
2966 
2967     TcKeyRef * const tcKeyRef = (TcKeyRef *) signal->getDataPtrSend();
2968 
2969     tcKeyRef->connectPtr = apiOpRec;
2970     tcKeyRef->transId[0] = transid1;
2971     tcKeyRef->transId[1] = transid2;
2972     tcKeyRef->errorCode = errCode;
2973     sendTCKEYREF(signal, apiRef, signal->getSendersBlockRef(), 0);
2974   } else {
2975     jam();
2976     /* All ops apart from dirty read send LQHKEYREF to TC
2977      * (This includes simple read)
2978      */
2979 
2980     const Uint32 clientPtr = lqhKeyReq->clientConnectPtr;
2981     Uint32 TcOprec = clientPtr;
2982     if(LqhKeyReq::getSameClientAndTcFlag(reqInfo) == 1){
2983       if(LqhKeyReq::getApplicationAddressFlag(reqInfo))
2984 	TcOprec = lqhKeyReq->variableData[2];
2985       else
2986 	TcOprec = lqhKeyReq->variableData[0];
2987     }
2988 
2989     LqhKeyRef * const ref = (LqhKeyRef*)signal->getDataPtrSend();
2990     ref->userRef = clientPtr;
2991     ref->connectPtr = TcOprec;
2992     ref->errorCode = errCode;
2993     ref->transId1 = transid1;
2994     ref->transId2 = transid2;
2995     sendSignal(signal->senderBlockRef(), GSN_LQHKEYREF, signal,
2996 	       LqhKeyRef::SignalLength, JBB);
2997   }//if
2998   return;
2999 }//Dblqh::noFreeRecordLab()
3000 
3001 Uint32
get_table_state_error(Ptr<Tablerec> tabPtr) const3002 Dblqh::get_table_state_error(Ptr<Tablerec> tabPtr) const
3003 {
3004   switch(tabPtr.p->tableStatus){
3005   case Tablerec::NOT_DEFINED:
3006     jam();
3007     return ZTABLE_NOT_DEFINED;
3008     break;
3009   case Tablerec::ADD_TABLE_ONGOING:
3010     jam();
3011   case Tablerec::PREP_DROP_TABLE_DONE:
3012     jam();
3013   case Tablerec::DROP_TABLE_WAIT_USAGE:
3014     jam();
3015   case Tablerec::DROP_TABLE_WAIT_DONE:
3016     jam();
3017   case Tablerec::DROP_TABLE_ACC:
3018     jam();
3019   case Tablerec::DROP_TABLE_TUP:
3020     jam();
3021   case Tablerec::DROP_TABLE_TUX:
3022     jam();
3023     return PrepDropTabRef::DropInProgress;
3024     break;
3025   case Tablerec::TABLE_DEFINED:
3026   case Tablerec::TABLE_READ_ONLY:
3027     ndbassert(0);
3028     return ZTABLE_NOT_DEFINED;
3029     break;
3030   }
3031   ndbassert(0);
3032   return ~Uint32(0);
3033 }
3034 
3035 int
check_tabstate(Signal * signal,const Tablerec * tablePtrP,Uint32 op)3036 Dblqh::check_tabstate(Signal * signal, const Tablerec * tablePtrP, Uint32 op)
3037 {
3038   if (tabptr.p->tableStatus == Tablerec::TABLE_READ_ONLY)
3039   {
3040     jam();
3041     if (op == ZREAD || op == ZREAD_EX || op == ZUNLOCK)
3042     {
3043       jam();
3044       return 0;
3045     }
3046     terrorCode = ZTABLE_READ_ONLY;
3047   }
3048   else
3049   {
3050     jam();
3051     terrorCode = get_table_state_error(tabptr);
3052   }
3053   abortErrorLab(signal);
3054   return 1;
3055 }
3056 
LQHKEY_abort(Signal * signal,int errortype)3057 void Dblqh::LQHKEY_abort(Signal* signal, int errortype)
3058 {
3059   switch (errortype) {
3060   case 0:
3061     jam();
3062     terrorCode = ZCOPY_NODE_ERROR;
3063     break;
3064   case 1:
3065     jam();
3066     terrorCode = ZNO_FREE_LQH_CONNECTION;
3067     break;
3068   case 2:
3069     jam();
3070     terrorCode = signal->theData[1];
3071     break;
3072   case 3:
3073     jam();
3074     ndbrequire((tcConnectptr.p->transactionState == TcConnectionrec::WAIT_ACC_ABORT) ||
3075                (tcConnectptr.p->transactionState == TcConnectionrec::ABORT_STOPPED)  ||
3076                (tcConnectptr.p->transactionState == TcConnectionrec::ABORT_QUEUED));
3077     return;
3078     break;
3079   case 4:
3080     jam();
3081     terrorCode = get_table_state_error(tabptr);
3082     break;
3083   case 5:
3084     jam();
3085     terrorCode = ZINVALID_SCHEMA_VERSION;
3086     break;
3087   default:
3088     ndbrequire(false);
3089     break;
3090   }//switch
3091   abortErrorLab(signal);
3092 }//Dblqh::LQHKEY_abort()
3093 
LQHKEY_error(Signal * signal,int errortype)3094 void Dblqh::LQHKEY_error(Signal* signal, int errortype)
3095 {
3096   switch (errortype) {
3097   case 0:
3098     jam();
3099     break;
3100   case 1:
3101     jam();
3102     break;
3103   case 2:
3104     jam();
3105     break;
3106   case 3:
3107     jam();
3108     break;
3109   case 4:
3110     jam();
3111     break;
3112   case 5:
3113     jam();
3114     break;
3115   case 6:
3116     jam();
3117     break;
3118   default:
3119     jam();
3120     break;
3121   }//switch
3122   ndbrequire(false);
3123 }//Dblqh::LQHKEY_error()
3124 
execLQHKEYREF(Signal * signal)3125 void Dblqh::execLQHKEYREF(Signal* signal)
3126 {
3127   jamEntry();
3128   tcConnectptr.i = signal->theData[0];
3129   Uint32 tcOprec  = signal->theData[1];
3130   terrorCode = signal->theData[2];
3131   Uint32 transid1 = signal->theData[3];
3132   Uint32 transid2 = signal->theData[4];
3133   if (tcConnectptr.i >= ctcConnectrecFileSize) {
3134     errorReport(signal, 3);
3135     return;
3136   }//if
3137 
3138   ptrAss(tcConnectptr, tcConnectionrec);
3139   TcConnectionrec * const regTcPtr = tcConnectptr.p;
3140 
3141   if (likely(! ((regTcPtr->connectState == TcConnectionrec::LOG_CONNECTED) ||
3142                 (regTcPtr->connectState == TcConnectionrec::COPY_CONNECTED))))
3143   {
3144     /**
3145      * This...is unpleasant...
3146      *   LOG_CONNECTED and COPY_CONNECTED will not release there tcConnectptr
3147      *   before all outstanding is finished.
3148      *
3149      *   CONNECTED on the other hand can, (in ::execABORT)
3150      *     which means that findTransaction *should* be used
3151      *     to make sure that correct tcConnectptr is accessed.
3152      *
3153      *   However, as LOG_CONNECTED & COPY_CONNECTED only uses 1 tcConnectptr
3154      *     (and fiddles) with transid and other stuff, I could
3155      *     not find an easy way to modify the code so that findTransaction
3156      *     is usable also for them
3157      */
3158     if (findTransaction(transid1, transid2, tcOprec, 0) != ZOK)
3159     {
3160       jam();
3161       warningReport(signal, 14);
3162       return;
3163     }
3164   }
3165 
3166   switch (regTcPtr->connectState) {
3167   case TcConnectionrec::CONNECTED:
3168     jam();
3169     if (regTcPtr->abortState != TcConnectionrec::ABORT_IDLE) {
3170       warningReport(signal, 15);
3171       return;
3172     }//if
3173     abortErrorLab(signal);
3174     return;
3175     break;
3176   case TcConnectionrec::LOG_CONNECTED:
3177     jam();
3178     logLqhkeyrefLab(signal);
3179     return;
3180     break;
3181   case TcConnectionrec::COPY_CONNECTED:
3182     jam();
3183     copyLqhKeyRefLab(signal);
3184     return;
3185     break;
3186   default:
3187     warningReport(signal, 16);
3188     return;
3189     break;
3190   }//switch
3191 }//Dblqh::execLQHKEYREF()
3192 
3193 /* -------------------------------------------------------------------------- */
3194 /* -------                       ENTER PACKED_SIGNAL                  ------- */
3195 /* Execution of packed signal. The packed signal can contain COMMIT, COMPLETE */
3196 /* or LQHKEYCONF signals. These signals will be executed by their resp. exec  */
3197 /* functions.                                                                 */
3198 /* -------------------------------------------------------------------------- */
execPACKED_SIGNAL(Signal * signal)3199 void Dblqh::execPACKED_SIGNAL(Signal* signal)
3200 {
3201   Uint32 Tstep = 0;
3202   Uint32 Tlength;
3203   Uint32 TpackedData[28];
3204   Uint32 sig0, sig1, sig2, sig3 ,sig4, sig5, sig6;
3205 
3206   jamEntry();
3207   Tlength = signal->length();
3208   Uint32 TsenderRef = signal->getSendersBlockRef();
3209   Uint32 TcommitLen = 5;
3210   Uint32 Tgci_lo_mask = ~(Uint32)0;
3211 
3212   if (unlikely(!ndb_check_micro_gcp(getNodeInfo(refToNode(signal->getSendersBlockRef())).m_version)))
3213   {
3214     jam();
3215     TcommitLen = 4;
3216     Tgci_lo_mask = 0;
3217   }
3218 
3219 #ifdef ERROR_INSERT
3220   Uint32 senderBlockRef = signal->getSendersBlockRef();
3221 #endif
3222 
3223   ndbrequire(Tlength <= 25);
3224   MEMCOPY_NO_WORDS(&TpackedData[0], &signal->theData[0], Tlength);
3225   while (Tlength > Tstep) {
3226     switch (TpackedData[Tstep] >> 28) {
3227     case ZCOMMIT:
3228       jam();
3229       sig0 = TpackedData[Tstep + 0] & 0x0FFFFFFF;
3230       sig1 = TpackedData[Tstep + 1];
3231       sig2 = TpackedData[Tstep + 2];
3232       sig3 = TpackedData[Tstep + 3];
3233       sig4 = TpackedData[Tstep + 4];
3234       signal->theData[0] = sig0;
3235       signal->theData[1] = sig1;
3236       signal->theData[2] = sig2;
3237       signal->theData[3] = sig3;
3238       signal->theData[4] = sig4 & Tgci_lo_mask;
3239       signal->header.theLength = TcommitLen;
3240       execCOMMIT(signal);
3241       Tstep += TcommitLen;
3242       break;
3243     case ZCOMPLETE:
3244       jam();
3245       sig0 = TpackedData[Tstep + 0] & 0x0FFFFFFF;
3246       sig1 = TpackedData[Tstep + 1];
3247       sig2 = TpackedData[Tstep + 2];
3248       signal->theData[0] = sig0;
3249       signal->theData[1] = sig1;
3250       signal->theData[2] = sig2;
3251       signal->header.theLength = 3;
3252       execCOMPLETE(signal);
3253       Tstep += 3;
3254       break;
3255     case ZLQHKEYCONF: {
3256       jam();
3257       LqhKeyConf * lqhKeyConf = CAST_PTR(LqhKeyConf, signal->theData);
3258       sig0 = TpackedData[Tstep + 0] & 0x0FFFFFFF;
3259       sig1 = TpackedData[Tstep + 1];
3260       sig2 = TpackedData[Tstep + 2];
3261       sig3 = TpackedData[Tstep + 3];
3262       sig4 = TpackedData[Tstep + 4];
3263       sig5 = TpackedData[Tstep + 5];
3264       sig6 = TpackedData[Tstep + 6];
3265       lqhKeyConf->connectPtr = sig0;
3266       lqhKeyConf->opPtr = sig1;
3267       lqhKeyConf->userRef = sig2;
3268       lqhKeyConf->readLen = sig3;
3269       lqhKeyConf->transId1 = sig4;
3270       lqhKeyConf->transId2 = sig5;
3271       lqhKeyConf->noFiredTriggers = sig6;
3272       execLQHKEYCONF(signal);
3273       Tstep += LqhKeyConf::SignalLength;
3274       break;
3275     }
3276     case ZREMOVE_MARKER:
3277       jam();
3278       sig0 = TpackedData[Tstep + 1];
3279       sig1 = TpackedData[Tstep + 2];
3280       signal->theData[0] = sig0;
3281       signal->theData[1] = sig1;
3282       signal->header.theLength = 2;
3283       execREMOVE_MARKER_ORD(signal);
3284       Tstep += 3;
3285       break;
3286     case ZFIRE_TRIG_REQ:
3287       jam();
3288       ndbassert(FireTrigReq::SignalLength == 4);
3289       sig0 = TpackedData[Tstep + 0] & 0x0FFFFFFF;
3290       sig1 = TpackedData[Tstep + 1];
3291       sig2 = TpackedData[Tstep + 2];
3292       sig3 = TpackedData[Tstep + 3];
3293       signal->theData[0] = sig0;
3294       signal->theData[1] = sig1;
3295       signal->theData[2] = sig2;
3296       signal->theData[3] = sig3;
3297       signal->header.theLength = FireTrigReq::SignalLength;
3298       signal->header.theSendersBlockRef = TsenderRef;
3299       execFIRE_TRIG_REQ(signal);
3300       Tstep += FireTrigReq::SignalLength;
3301       break;
3302     default:
3303       ndbrequire(false);
3304       return;
3305     }//switch
3306 #ifdef ERROR_INSERT
3307     signal->header.theSendersBlockRef = senderBlockRef;
3308 #endif
3309   }//while
3310   ndbrequire(Tlength == Tstep);
3311   return;
3312 }//Dblqh::execPACKED_SIGNAL()
3313 
3314 void
execREMOVE_MARKER_ORD(Signal * signal)3315 Dblqh::execREMOVE_MARKER_ORD(Signal* signal)
3316 {
3317   CommitAckMarker key;
3318   key.transid1 = signal->theData[0];
3319   key.transid2 = signal->theData[1];
3320   jamEntry();
3321 
3322   CommitAckMarkerPtr removedPtr;
3323   m_commitAckMarkerHash.remove(removedPtr, key);
3324 #if (defined VM_TRACE || defined ERROR_INSERT) && defined(wl4391_todo)
3325   ndbrequire(removedPtr.i != RNIL);
3326   m_commitAckMarkerPool.release(removedPtr);
3327 #else
3328   if (removedPtr.i != RNIL)
3329   {
3330     jam();
3331     m_commitAckMarkerPool.release(removedPtr);
3332   }
3333 #endif
3334 #ifdef MARKER_TRACE
3335   ndbout_c("%u Rem marker[%.8x %.8x]", instance(), key.transid1, key.transid2);
3336 #endif
3337 }
3338 
3339 
3340 /* -------------------------------------------------------------------------- */
3341 /* -------                 ENTER SEND_PACKED                          ------- */
3342 /* Used to force a packed signal to be sent if local signal buffer is not     */
3343 /* empty.                                                                     */
3344 /* -------------------------------------------------------------------------- */
execSEND_PACKED(Signal * signal)3345 void Dblqh::execSEND_PACKED(Signal* signal)
3346 {
3347   HostRecordPtr Thostptr;
3348   UintR i;
3349   UintR TpackedListIndex = cpackedListIndex;
3350   jamEntry();
3351   for (i = 0; i < TpackedListIndex; i++) {
3352     Thostptr.i = cpackedList[i];
3353     ptrAss(Thostptr, hostRecord);
3354     jam();
3355     ndbrequire(Thostptr.i - 1 < MAX_NDB_NODES - 1);
3356     if (Thostptr.p->noOfPackedWordsLqh > 0) {
3357       jam();
3358       sendPackedSignalLqh(signal, Thostptr.p);
3359     }//if
3360     if (Thostptr.p->noOfPackedWordsTc > 0) {
3361       jam();
3362       sendPackedSignalTc(signal, Thostptr.p);
3363     }//if
3364     Thostptr.p->inPackedList = false;
3365   }//for
3366   cpackedListIndex = 0;
3367   return;
3368 }//Dblqh::execSEND_PACKED()
3369 
3370 void
updatePackedList(Signal * signal,HostRecord * ahostptr,Uint16 hostId)3371 Dblqh::updatePackedList(Signal* signal, HostRecord * ahostptr, Uint16 hostId)
3372 {
3373   Uint32 TpackedListIndex = cpackedListIndex;
3374   if (ahostptr->inPackedList == false) {
3375     jam();
3376     ahostptr->inPackedList = true;
3377     cpackedList[TpackedListIndex] = hostId;
3378     cpackedListIndex = TpackedListIndex + 1;
3379   }//if
3380 }//Dblqh::updatePackedList()
3381 
3382 void
execREAD_PSEUDO_REQ(Signal * signal)3383 Dblqh::execREAD_PSEUDO_REQ(Signal* signal){
3384   jamEntry();
3385   TcConnectionrecPtr regTcPtr;
3386   regTcPtr.i = signal->theData[0];
3387   ptrCheckGuard(regTcPtr, ctcConnectrecFileSize, tcConnectionrec);
3388 
3389   switch(signal->theData[1])
3390   {
3391   case AttributeHeader::RANGE_NO:
3392     signal->theData[0] = regTcPtr.p->m_scan_curr_range_no;
3393     break;
3394   case AttributeHeader::ROW_COUNT:
3395   case AttributeHeader::COMMIT_COUNT:
3396   {
3397     jam();
3398     FragrecordPtr regFragptr;
3399     regFragptr.i = regTcPtr.p->fragmentptr;
3400     c_fragment_pool.getPtr(regFragptr);
3401 
3402     signal->theData[0] = regFragptr.p->accFragptr;
3403     EXECUTE_DIRECT(DBACC, GSN_READ_PSEUDO_REQ, signal, 2);
3404     break;
3405   }
3406   case AttributeHeader::RECORDS_IN_RANGE:
3407   case AttributeHeader::INDEX_STAT_KEY:
3408   case AttributeHeader::INDEX_STAT_VALUE:
3409   {
3410     jam();
3411     // scanptr gets reset somewhere within the timeslice
3412     ScanRecordPtr tmp;
3413     tmp.i = regTcPtr.p->tcScanRec;
3414     c_scanRecordPool.getPtr(tmp);
3415     signal->theData[0] = tmp.p->scanAccPtr;
3416     EXECUTE_DIRECT(DBTUX, GSN_READ_PSEUDO_REQ, signal, 2);
3417     break;
3418   }
3419   case AttributeHeader::LOCK_REF:
3420   {
3421     /* Return 3x 32-bit words
3422      *  - LQH instance info
3423      *  - TC operation index
3424      *  - Bottom 32-bits of LQH-local key-request id (for uniqueness)
3425      */
3426     jam();
3427     signal->theData[0] = (getOwnNodeId() << 16) | regTcPtr.p->fragmentid;
3428     signal->theData[1] = regTcPtr.p->tcOprec;
3429     signal->theData[2] = (Uint32) regTcPtr.p->lqhKeyReqId;
3430     break;
3431   }
3432   case AttributeHeader::OP_ID:
3433   {
3434     jam();
3435     memcpy(signal->theData, &regTcPtr.p->lqhKeyReqId, 8);
3436     break;
3437   }
3438   case AttributeHeader::CORR_FACTOR64:
3439   {
3440     Uint32 add = 0;
3441     ScanRecordPtr tmp;
3442     tmp.i = regTcPtr.p->tcScanRec;
3443     if (tmp.i != RNIL)
3444     {
3445       c_scanRecordPool.getPtr(tmp);
3446       add = tmp.p->m_curr_batch_size_rows;
3447     }
3448 
3449     signal->theData[0] = regTcPtr.p->m_corrFactorLo + add;
3450     signal->theData[1] = regTcPtr.p->m_corrFactorHi;
3451     break;
3452   }
3453   default:
3454     ndbrequire(false);
3455   }
3456 }
3457 
3458 /* ************>> */
3459 /*  TUPKEYCONF  > */
3460 /* ************>> */
execTUPKEYCONF(Signal * signal)3461 void Dblqh::execTUPKEYCONF(Signal* signal)
3462 {
3463   TcConnectionrec *regTcConnectionrec = tcConnectionrec;
3464   Uint32 ttcConnectrecFileSize = ctcConnectrecFileSize;
3465   const TupKeyConf * const tupKeyConf = (TupKeyConf *)signal->getDataPtr();
3466   Uint32 tcIndex = tupKeyConf->userPtr;
3467   jamEntry();
3468   tcConnectptr.i = tcIndex;
3469   ptrCheckGuard(tcConnectptr, ttcConnectrecFileSize, regTcConnectionrec);
3470   TcConnectionrec * regTcPtr = tcConnectptr.p;
3471   Uint32 activeCreat = regTcPtr->activeCreat;
3472 
3473   FragrecordPtr regFragptr;
3474   regFragptr.i = tcConnectptr.p->fragmentptr;
3475   c_fragment_pool.getPtr(regFragptr);
3476   fragptr = regFragptr;
3477 
3478   switch (tcConnectptr.p->transactionState) {
3479   case TcConnectionrec::WAIT_TUP:
3480     jam();
3481     if (tcConnectptr.p->seqNoReplica == 0) // Primary replica
3482       tcConnectptr.p->noFiredTriggers = tupKeyConf->noFiredTriggers;
3483     tupkeyConfLab(signal);
3484     break;
3485   case TcConnectionrec::COPY_TUPKEY:
3486     jam();
3487     copyTupkeyConfLab(signal);
3488     break;
3489   case TcConnectionrec::SCAN_TUPKEY:
3490     jam();
3491     scanTupkeyConfLab(signal);
3492     break;
3493   case TcConnectionrec::WAIT_TUP_TO_ABORT:
3494     jam();
3495 /* ------------------------------------------------------------------------- */
3496 // Abort was not ready to start until this signal came back. Now we are ready
3497 // to start the abort.
3498 /* ------------------------------------------------------------------------- */
3499     if (unlikely(activeCreat == Fragrecord::AC_NR_COPY))
3500     {
3501       jam();
3502       ndbrequire(regTcPtr->m_nr_delete.m_cnt);
3503       regTcPtr->m_nr_delete.m_cnt--;
3504       if (regTcPtr->m_nr_delete.m_cnt)
3505       {
3506 	jam();
3507 	/**
3508 	 * Let operation wait for pending NR operations
3509 	 *   even for before writing log...(as it's simpler)
3510 	 */
3511 
3512 #ifdef VM_TRACE
3513 	/**
3514 	 * Only disk table can have pending ops...
3515 	 */
3516 	TablerecPtr tablePtr;
3517 	tablePtr.i = regTcPtr->tableref;
3518 	ptrCheckGuard(tablePtr, ctabrecFileSize, tablerec);
3519 	ndbrequire(tablePtr.p->m_disk_table);
3520 #endif
3521 	return;
3522       }
3523     }
3524 
3525     abortCommonLab(signal);
3526     break;
3527   case TcConnectionrec::WAIT_ACC_ABORT:
3528   case TcConnectionrec::ABORT_QUEUED:
3529     jam();
3530 /* ------------------------------------------------------------------------- */
3531 /*      IGNORE SINCE ABORT OF THIS OPERATION IS ONGOING ALREADY.             */
3532 /* ------------------------------------------------------------------------- */
3533     break;
3534   default:
3535     ndbrequire(false);
3536     break;
3537   }//switch
3538 
3539 }//Dblqh::execTUPKEYCONF()
3540 
3541 /* ************> */
3542 /*  TUPKEYREF  > */
3543 /* ************> */
execTUPKEYREF(Signal * signal)3544 void Dblqh::execTUPKEYREF(Signal* signal)
3545 {
3546   const TupKeyRef * const tupKeyRef = (TupKeyRef *)signal->getDataPtr();
3547 
3548   jamEntry();
3549   tcConnectptr.i = tupKeyRef->userRef;
3550   terrorCode = tupKeyRef->errorCode;
3551   ptrCheckGuard(tcConnectptr, ctcConnectrecFileSize, tcConnectionrec);
3552   TcConnectionrec* regTcPtr = tcConnectptr.p;
3553   Uint32 activeCreat = regTcPtr->activeCreat;
3554 
3555   FragrecordPtr regFragptr;
3556   regFragptr.i = regTcPtr->fragmentptr;
3557   c_fragment_pool.getPtr(regFragptr);
3558   fragptr = regFragptr;
3559 
3560   TRACE_OP(regTcPtr, "TUPKEYREF");
3561 
3562   if (unlikely(activeCreat == Fragrecord::AC_NR_COPY))
3563   {
3564     jam();
3565     ndbrequire(regTcPtr->m_nr_delete.m_cnt);
3566     regTcPtr->m_nr_delete.m_cnt--;
3567     ndbassert(regTcPtr->transactionState == TcConnectionrec::WAIT_TUP ||
3568 	      regTcPtr->transactionState ==TcConnectionrec::WAIT_TUP_TO_ABORT);
3569   }
3570 
3571   switch (tcConnectptr.p->transactionState) {
3572   case TcConnectionrec::WAIT_TUP:
3573     jam();
3574     abortErrorLab(signal);
3575     break;
3576   case TcConnectionrec::COPY_TUPKEY:
3577     copyTupkeyRefLab(signal);
3578     break;
3579   case TcConnectionrec::SCAN_TUPKEY:
3580     jam();
3581     scanTupkeyRefLab(signal);
3582     break;
3583   case TcConnectionrec::WAIT_TUP_TO_ABORT:
3584     jam();
3585 /* ------------------------------------------------------------------------- */
3586 // Abort was not ready to start until this signal came back. Now we are ready
3587 // to start the abort.
3588 /* ------------------------------------------------------------------------- */
3589     abortCommonLab(signal);
3590     break;
3591   case TcConnectionrec::WAIT_ACC_ABORT:
3592   case TcConnectionrec::ABORT_QUEUED:
3593     jam();
3594 /* ------------------------------------------------------------------------- */
3595 /*       IGNORE SINCE ABORT OF THIS OPERATION IS ONGOING ALREADY.            */
3596 /* ------------------------------------------------------------------------- */
3597     break;
3598   default:
3599     jamLine(tcConnectptr.p->transactionState);
3600     ndbrequire(false);
3601     break;
3602   }//switch
3603 }//Dblqh::execTUPKEYREF()
3604 
sendPackedSignalLqh(Signal * signal,HostRecord * ahostptr)3605 void Dblqh::sendPackedSignalLqh(Signal* signal, HostRecord * ahostptr)
3606 {
3607   Uint32 noOfWords = ahostptr->noOfPackedWordsLqh;
3608   BlockReference hostRef = ahostptr->hostLqhBlockRef;
3609   MEMCOPY_NO_WORDS(&signal->theData[0],
3610                    &ahostptr->packedWordsLqh[0],
3611                    noOfWords);
3612   sendSignal(hostRef, GSN_PACKED_SIGNAL, signal, noOfWords, JBB);
3613   ahostptr->noOfPackedWordsLqh = 0;
3614 }//Dblqh::sendPackedSignalLqh()
3615 
sendPackedSignalTc(Signal * signal,HostRecord * ahostptr)3616 void Dblqh::sendPackedSignalTc(Signal* signal, HostRecord * ahostptr)
3617 {
3618   Uint32 noOfWords = ahostptr->noOfPackedWordsTc;
3619   BlockReference hostRef = ahostptr->hostTcBlockRef;
3620   MEMCOPY_NO_WORDS(&signal->theData[0],
3621                    &ahostptr->packedWordsTc[0],
3622                    noOfWords);
3623   sendSignal(hostRef, GSN_PACKED_SIGNAL, signal, noOfWords, JBB);
3624   ahostptr->noOfPackedWordsTc = 0;
3625 }//Dblqh::sendPackedSignalTc()
3626 
sendCommitLqh(Signal * signal,BlockReference alqhBlockref)3627 void Dblqh::sendCommitLqh(Signal* signal, BlockReference alqhBlockref)
3628 {
3629   HostRecordPtr Thostptr;
3630   Thostptr.i = refToNode(alqhBlockref);
3631   ptrCheckGuard(Thostptr, chostFileSize, hostRecord);
3632 
3633   Uint32 Tdata[5];
3634   Tdata[0] = tcConnectptr.p->clientConnectrec;
3635   Tdata[1] = tcConnectptr.p->gci_hi;
3636   Tdata[2] = tcConnectptr.p->transid[0];
3637   Tdata[3] = tcConnectptr.p->transid[1];
3638   Tdata[4] = tcConnectptr.p->gci_lo;
3639   Uint32 len = 5;
3640 
3641   if (unlikely(!ndb_check_micro_gcp(getNodeInfo(Thostptr.i).m_version)))
3642   {
3643     jam();
3644     ndbassert(Tdata[4] == 0 || getNodeInfo(Thostptr.i).m_version == 0);
3645     len = 4;
3646   }
3647 
3648   // currently packed signal cannot address specific instance
3649   const bool send_unpacked = getNodeInfo(Thostptr.i).m_lqh_workers != 0;
3650   if (send_unpacked) {
3651     jam();
3652     FragrecordPtr Tfragptr;
3653     Tfragptr.i = tcConnectptr.p->fragmentptr;
3654     c_fragment_pool.getPtr(Tfragptr);
3655     memcpy(&signal->theData[0], &Tdata[0], len << 2);
3656     Uint32 Tnode = Thostptr.i;
3657     Uint32 instanceKey = Tfragptr.p->lqhInstanceKey;
3658     BlockReference lqhRef = numberToRef(DBLQH, instanceKey, Tnode);
3659     sendSignal(lqhRef, GSN_COMMIT, signal, len, JBB);
3660     return;
3661   }
3662 
3663   if (Thostptr.p->noOfPackedWordsLqh > 25 - 5) {
3664     jam();
3665     sendPackedSignalLqh(signal, Thostptr.p);
3666   } else {
3667     jam();
3668     updatePackedList(signal, Thostptr.p, Thostptr.i);
3669   }
3670 
3671   Tdata[0] |= (ZCOMMIT << 28);
3672   Uint32 pos = Thostptr.p->noOfPackedWordsLqh;
3673   memcpy(&Thostptr.p->packedWordsLqh[pos], &Tdata[0], len << 2);
3674   Thostptr.p->noOfPackedWordsLqh = pos + len;
3675 }
3676 
sendCompleteLqh(Signal * signal,BlockReference alqhBlockref)3677 void Dblqh::sendCompleteLqh(Signal* signal, BlockReference alqhBlockref)
3678 {
3679   HostRecordPtr Thostptr;
3680   Thostptr.i = refToNode(alqhBlockref);
3681   ptrCheckGuard(Thostptr, chostFileSize, hostRecord);
3682 
3683   Uint32 Tdata[3];
3684   Tdata[0] = tcConnectptr.p->clientConnectrec;
3685   Tdata[1] = tcConnectptr.p->transid[0];
3686   Tdata[2] = tcConnectptr.p->transid[1];
3687   Uint32 len = 3;
3688 
3689   // currently packed signal cannot address specific instance
3690   const bool send_unpacked = getNodeInfo(Thostptr.i).m_lqh_workers != 0;
3691   if (send_unpacked) {
3692     jam();
3693     FragrecordPtr Tfragptr;
3694     Tfragptr.i = tcConnectptr.p->fragmentptr;
3695     c_fragment_pool.getPtr(Tfragptr);
3696     memcpy(&signal->theData[0], &Tdata[0], len << 2);
3697     Uint32 Tnode = Thostptr.i;
3698     Uint32 instanceKey = Tfragptr.p->lqhInstanceKey;
3699     BlockReference lqhRef = numberToRef(DBLQH, instanceKey, Tnode);
3700     sendSignal(lqhRef, GSN_COMPLETE, signal, len, JBB);
3701     return;
3702   }
3703 
3704   if (Thostptr.p->noOfPackedWordsLqh > 22) {
3705     jam();
3706     sendPackedSignalLqh(signal, Thostptr.p);
3707   } else {
3708     jam();
3709     updatePackedList(signal, Thostptr.p, Thostptr.i);
3710   }
3711 
3712   Tdata[0] |= (ZCOMPLETE << 28);
3713   Uint32 pos = Thostptr.p->noOfPackedWordsLqh;
3714   memcpy(&Thostptr.p->packedWordsLqh[pos], &Tdata[0], len << 2);
3715   Thostptr.p->noOfPackedWordsLqh = pos + len;
3716 }
3717 
sendCommittedTc(Signal * signal,BlockReference atcBlockref)3718 void Dblqh::sendCommittedTc(Signal* signal, BlockReference atcBlockref)
3719 {
3720   if (refToInstance(atcBlockref))
3721   {
3722     jam();
3723     signal->theData[0] = tcConnectptr.p->clientConnectrec;
3724     signal->theData[1] = tcConnectptr.p->transid[0];
3725     signal->theData[2] = tcConnectptr.p->transid[1];
3726     sendSignal(atcBlockref, GSN_COMMITTED, signal, 3, JBB);
3727     return;
3728   }
3729 
3730   HostRecordPtr Thostptr;
3731   Thostptr.i = refToNode(atcBlockref);
3732   ptrCheckGuard(Thostptr, chostFileSize, hostRecord);
3733 
3734   Uint32 Tdata[3];
3735   Tdata[0] = tcConnectptr.p->clientConnectrec;
3736   Tdata[1] = tcConnectptr.p->transid[0];
3737   Tdata[2] = tcConnectptr.p->transid[1];
3738   Uint32 len = 3;
3739 
3740   // currently TC is single-threaded
3741   const bool send_unpacked = false;
3742   if (send_unpacked) {
3743     jam();
3744     memcpy(&signal->theData[0], &Tdata[0], len << 2);
3745     BlockReference tcRef = Thostptr.p->hostTcBlockRef;
3746     sendSignal(tcRef, GSN_COMMITTED, signal, len, JBB);
3747     return;
3748   }
3749 
3750   if (Thostptr.p->noOfPackedWordsTc > 22) {
3751     jam();
3752     sendPackedSignalTc(signal, Thostptr.p);
3753   } else {
3754     jam();
3755     updatePackedList(signal, Thostptr.p, Thostptr.i);
3756   }
3757 
3758   Tdata[0] |= (ZCOMMITTED << 28);
3759   Uint32 pos = Thostptr.p->noOfPackedWordsTc;
3760   memcpy(&Thostptr.p->packedWordsTc[pos], &Tdata[0], len << 2);
3761   Thostptr.p->noOfPackedWordsTc = pos + len;
3762 }
3763 
sendCompletedTc(Signal * signal,BlockReference atcBlockref)3764 void Dblqh::sendCompletedTc(Signal* signal, BlockReference atcBlockref)
3765 {
3766   if (refToInstance(atcBlockref))
3767   {
3768     jam();
3769     signal->theData[0] = tcConnectptr.p->clientConnectrec;
3770     signal->theData[1] = tcConnectptr.p->transid[0];
3771     signal->theData[2] = tcConnectptr.p->transid[1];
3772     sendSignal(atcBlockref, GSN_COMPLETED, signal, 3, JBB);
3773     return;
3774   }
3775 
3776   HostRecordPtr Thostptr;
3777   Thostptr.i = refToNode(atcBlockref);
3778   ptrCheckGuard(Thostptr, chostFileSize, hostRecord);
3779 
3780   Uint32 Tdata[3];
3781   Tdata[0] = tcConnectptr.p->clientConnectrec;
3782   Tdata[1] = tcConnectptr.p->transid[0];
3783   Tdata[2] = tcConnectptr.p->transid[1];
3784   Uint32 len = 3;
3785 
3786   // currently TC is single-threaded
3787   const bool send_unpacked = false;
3788   if (send_unpacked) {
3789     jam();
3790     memcpy(&signal->theData[0], &Tdata[0], len << 2);
3791     BlockReference tcRef = Thostptr.p->hostTcBlockRef;
3792     sendSignal(tcRef, GSN_COMMITTED, signal, len, JBB);
3793     return;
3794   }
3795 
3796   if (Thostptr.p->noOfPackedWordsTc > 22) {
3797     jam();
3798     sendPackedSignalTc(signal, Thostptr.p);
3799   } else {
3800     jam();
3801     updatePackedList(signal, Thostptr.p, Thostptr.i);
3802   }
3803 
3804   Tdata[0] |= (ZCOMPLETED << 28);
3805   Uint32 pos = Thostptr.p->noOfPackedWordsTc;
3806   memcpy(&Thostptr.p->packedWordsTc[pos], &Tdata[0], len << 2);
3807   Thostptr.p->noOfPackedWordsTc = pos + len;
3808 }
3809 
sendLqhkeyconfTc(Signal * signal,BlockReference atcBlockref)3810 void Dblqh::sendLqhkeyconfTc(Signal* signal, BlockReference atcBlockref)
3811 {
3812   LqhKeyConf* lqhKeyConf;
3813   HostRecordPtr Thostptr;
3814 
3815   bool packed= true;
3816   Thostptr.i = refToNode(atcBlockref);
3817   ptrCheckGuard(Thostptr, chostFileSize, hostRecord);
3818   if (refToBlock(atcBlockref) == DBTC) {
3819     jam();
3820 /*******************************************************************
3821 // This signal was intended for DBTC as part of the normal transaction
3822 // execution.
3823 ********************************************************************/
3824     if (Thostptr.p->noOfPackedWordsTc > (25 - LqhKeyConf::SignalLength)) {
3825       jam();
3826       sendPackedSignalTc(signal, Thostptr.p);
3827     } else {
3828       jam();
3829       updatePackedList(signal, Thostptr.p, Thostptr.i);
3830     }//if
3831     lqhKeyConf = (LqhKeyConf *)
3832       &Thostptr.p->packedWordsTc[Thostptr.p->noOfPackedWordsTc];
3833     Thostptr.p->noOfPackedWordsTc += LqhKeyConf::SignalLength;
3834   } else if(refToMain(atcBlockref) == DBLQH &&
3835             refToInstance(atcBlockref) == instance()) {
3836     //wl4391_todo check
3837     jam();
3838 /*******************************************************************
3839 // This signal was intended for DBLQH as part of log execution or
3840 // node recovery.
3841 ********************************************************************/
3842     if (Thostptr.p->noOfPackedWordsLqh > (25 - LqhKeyConf::SignalLength)) {
3843       jam();
3844       sendPackedSignalLqh(signal, Thostptr.p);
3845     } else {
3846       jam();
3847       updatePackedList(signal, Thostptr.p, Thostptr.i);
3848     }//if
3849     lqhKeyConf = (LqhKeyConf *)
3850       &Thostptr.p->packedWordsLqh[Thostptr.p->noOfPackedWordsLqh];
3851     Thostptr.p->noOfPackedWordsLqh += LqhKeyConf::SignalLength;
3852   } else {
3853     packed= false;
3854     lqhKeyConf = (LqhKeyConf *)signal->getDataPtrSend();
3855   }
3856   Uint32 ptrAndType = tcConnectptr.i | (ZLQHKEYCONF << 28);
3857   Uint32 tcOprec = tcConnectptr.p->tcOprec;
3858   Uint32 ownRef = cownref;
3859   Uint32 readlenAi = tcConnectptr.p->readlenAi;
3860   Uint32 transid1 = tcConnectptr.p->transid[0];
3861   Uint32 transid2 = tcConnectptr.p->transid[1];
3862   Uint32 noFiredTriggers = tcConnectptr.p->noFiredTriggers;
3863   lqhKeyConf->connectPtr = ptrAndType;
3864   lqhKeyConf->opPtr = tcOprec;
3865   lqhKeyConf->userRef = ownRef;
3866   lqhKeyConf->readLen = readlenAi;
3867   lqhKeyConf->transId1 = transid1;
3868   lqhKeyConf->transId2 = transid2;
3869   lqhKeyConf->noFiredTriggers = noFiredTriggers;
3870 
3871   if(!packed)
3872   {
3873     lqhKeyConf->connectPtr = tcConnectptr.i;
3874     if (instance() == refToInstance(atcBlockref) &&
3875         (Thostptr.i == 0 || Thostptr.i == getOwnNodeId()))
3876     {
3877       /**
3878        * This EXECUTE_DIRECT is multi-thread safe, as we only get here
3879        * for RESTORE block.
3880        */
3881       EXECUTE_DIRECT(refToMain(atcBlockref), GSN_LQHKEYCONF,
3882 		     signal, LqhKeyConf::SignalLength);
3883     }
3884     else
3885     {
3886       sendSignal(atcBlockref, GSN_LQHKEYCONF,
3887 		 signal, LqhKeyConf::SignalLength, JBB);
3888     }
3889   }
3890 }//Dblqh::sendLqhkeyconfTc()
3891 
3892 /* ************************************************************************>>
3893  * KEYINFO: Get tuple request from DBTC. Next step is to contact DBACC to get
3894  * key to tuple if all key/attrinfo has been received, else for more attrinfo
3895  * signals.
3896  * ************************************************************************>> */
execKEYINFO(Signal * signal)3897 void Dblqh::execKEYINFO(Signal* signal)
3898 {
3899   Uint32 tcOprec = signal->theData[0];
3900   Uint32 transid1 = signal->theData[1];
3901   Uint32 transid2 = signal->theData[2];
3902   jamEntry();
3903   if (findTransaction(transid1, transid2, tcOprec, 0) != ZOK) {
3904     jam();
3905     return;
3906   }//if
3907 
3908   receive_keyinfo(signal,
3909 		  signal->theData+KeyInfo::HeaderLength,
3910 		  signal->getLength()-KeyInfo::HeaderLength);
3911 }
3912 
3913 void
receive_keyinfo(Signal * signal,Uint32 * data,Uint32 len)3914 Dblqh::receive_keyinfo(Signal* signal,
3915 		       Uint32 * data, Uint32 len)
3916 {
3917   TcConnectionrec * const regTcPtr = tcConnectptr.p;
3918   TcConnectionrec::TransactionState state = regTcPtr->transactionState;
3919   if (state != TcConnectionrec::WAIT_TUPKEYINFO &&
3920       state != TcConnectionrec::WAIT_SCAN_AI)
3921   {
3922     jam();
3923 /*****************************************************************************/
3924 /* TRANSACTION WAS ABORTED, THIS IS MOST LIKELY A SIGNAL BELONGING TO THE    */
3925 /* ABORTED TRANSACTION. THUS IGNORE THE SIGNAL.                              */
3926 /*****************************************************************************/
3927     return;
3928   }//if
3929 
3930   Uint32 errorCode =
3931     handleLongTupKey(signal, data, len);
3932 
3933   if (errorCode != 0) {
3934     if (errorCode == 1) {
3935       jam();
3936       return;
3937     }//if
3938     jam();
3939     terrorCode = errorCode;
3940     if(state == TcConnectionrec::WAIT_TUPKEYINFO)
3941       abortErrorLab(signal);
3942     else
3943       abort_scan(signal, regTcPtr->tcScanRec, errorCode);
3944     return;
3945   }//if
3946   if(state == TcConnectionrec::WAIT_TUPKEYINFO)
3947   {
3948     FragrecordPtr regFragptr;
3949     regFragptr.i = regTcPtr->fragmentptr;
3950     c_fragment_pool.getPtr(regFragptr);
3951     fragptr = regFragptr;
3952     endgettupkeyLab(signal);
3953   }
3954   return;
3955 }//Dblqh::execKEYINFO()
3956 
3957 /* ------------------------------------------------------------------------- */
3958 /* FILL IN KEY DATA INTO DATA BUFFERS.                                       */
3959 /* ------------------------------------------------------------------------- */
handleLongTupKey(Signal * signal,Uint32 * dataPtr,Uint32 len)3960 Uint32 Dblqh::handleLongTupKey(Signal* signal,
3961 			       Uint32* dataPtr,
3962 			       Uint32 len)
3963 {
3964   TcConnectionrec * const regTcPtr = tcConnectptr.p;
3965   Uint32 total = regTcPtr->save1 + len;
3966   Uint32 primKeyLen = regTcPtr->primKeyLen;
3967 
3968   if (unlikely(total > primKeyLen))
3969   {
3970     /**
3971      * DBLQH 6.3 has the bad taste to send more KEYINFO than what is
3972      *  really in the key...up to 3 words extra
3973      */
3974     Uint32 extra = total - primKeyLen;
3975     ndbrequire(extra <= 3);
3976     ndbrequire(len > extra);
3977     len -= extra;
3978   }
3979 
3980   bool ok= appendToSection(regTcPtr->keyInfoIVal,
3981                            dataPtr,
3982                            len);
3983   if (unlikely(!ok))
3984   {
3985     jam();
3986     return ZGET_DATAREC_ERROR;
3987   }
3988 
3989   regTcPtr->save1 = total;
3990   return (total >= primKeyLen ? 0 : 1);
3991 }//Dblqh::handleLongTupKey()
3992 
3993 /* ------------------------------------------------------------------------- */
3994 /* -------                HANDLE ATTRINFO SIGNALS                    ------- */
3995 /*                                                                           */
3996 /* ------------------------------------------------------------------------- */
3997 /* ************************************************************************>> */
3998 /*  ATTRINFO: Continuation of KEYINFO signal (except for scans that do not use*/
3999 /*  any KEYINFO). When all key and attribute info is received we contact DBACC*/
4000 /*  for index handling.                                                       */
4001 /* ************************************************************************>> */
execATTRINFO(Signal * signal)4002 void Dblqh::execATTRINFO(Signal* signal)
4003 {
4004   Uint32 tcOprec = signal->theData[0];
4005   Uint32 transid1 = signal->theData[1];
4006   Uint32 transid2 = signal->theData[2];
4007   jamEntry();
4008   if (findTransaction(transid1,
4009                       transid2,
4010                       tcOprec, 0) != ZOK) {
4011     jam();
4012     return;
4013   }//if
4014 
4015   receive_attrinfo(signal,
4016 		   signal->getDataPtrSend()+AttrInfo::HeaderLength,
4017 		   signal->getLength()-AttrInfo::HeaderLength);
4018 }//Dblqh::execATTRINFO()
4019 
4020 void
receive_attrinfo(Signal * signal,Uint32 * dataPtr,Uint32 length)4021 Dblqh::receive_attrinfo(Signal* signal, Uint32 * dataPtr, Uint32 length)
4022 {
4023   TcConnectionrec * const regTcPtr = tcConnectptr.p;
4024   Uint32 totReclenAi = regTcPtr->totReclenAi;
4025   Uint32 currReclenAi = regTcPtr->currReclenAi + length;
4026   regTcPtr->currReclenAi = currReclenAi;
4027   if (totReclenAi == currReclenAi) {
4028     switch (regTcPtr->transactionState) {
4029     case TcConnectionrec::WAIT_ATTR:
4030     {
4031       jam();
4032       fragptr.i = regTcPtr->fragmentptr;
4033       c_fragment_pool.getPtr(fragptr);
4034       lqhAttrinfoLab(signal, dataPtr, length);
4035       endgettupkeyLab(signal);
4036       return;
4037       break;
4038     }
4039     case TcConnectionrec::WAIT_SCAN_AI:
4040       jam();
4041       scanAttrinfoLab(signal, dataPtr, length);
4042       return;
4043       break;
4044     case TcConnectionrec::WAIT_TUP_TO_ABORT:
4045     case TcConnectionrec::LOG_ABORT_QUEUED:
4046     case TcConnectionrec::ABORT_QUEUED:
4047     case TcConnectionrec::ABORT_STOPPED:
4048     case TcConnectionrec::WAIT_ACC_ABORT:
4049     case TcConnectionrec::WAIT_AI_AFTER_ABORT:
4050       jam();
4051       aiStateErrorCheckLab(signal, dataPtr,length);
4052       return;
4053       break;
4054     default:
4055       jam();
4056       ndbrequire(regTcPtr->abortState != TcConnectionrec::ABORT_IDLE);
4057       break;
4058     }//switch
4059   } else if (currReclenAi < totReclenAi) {
4060     jam();
4061     switch (regTcPtr->transactionState) {
4062     case TcConnectionrec::WAIT_ATTR:
4063       jam();
4064       lqhAttrinfoLab(signal, dataPtr, length);
4065       return;
4066       break;
4067     case TcConnectionrec::WAIT_SCAN_AI:
4068       jam();
4069       scanAttrinfoLab(signal, dataPtr, length);
4070       return;
4071       break;
4072     case TcConnectionrec::WAIT_TUP_TO_ABORT:
4073     case TcConnectionrec::LOG_ABORT_QUEUED:
4074     case TcConnectionrec::ABORT_QUEUED:
4075     case TcConnectionrec::ABORT_STOPPED:
4076     case TcConnectionrec::WAIT_ACC_ABORT:
4077     case TcConnectionrec::WAIT_AI_AFTER_ABORT:
4078       jam();
4079       aiStateErrorCheckLab(signal, dataPtr, length);
4080       return;
4081       break;
4082     default:
4083       jam();
4084       ndbrequire(regTcPtr->abortState != TcConnectionrec::ABORT_IDLE);
4085       break;
4086     }//switch
4087   } else {
4088     switch (regTcPtr->transactionState) {
4089     case TcConnectionrec::WAIT_SCAN_AI:
4090       jam();
4091       scanAttrinfoLab(signal, dataPtr, length);
4092       return;
4093       break;
4094     default:
4095       ndbout_c("%d", regTcPtr->transactionState);
4096       ndbrequire(false);
4097       break;
4098     }//switch
4099   }//if
4100   return;
4101 }
4102 
4103 /* ************************************************************************>> */
4104 /*  TUP_ATTRINFO: Interpreted execution in DBTUP generates redo-log info      */
4105 /*  which is sent back to DBLQH for logging. This is because the decision     */
4106 /*  to execute or not is made in DBTUP and thus we cannot start logging until */
4107 /*  DBTUP part has been run.                                                  */
4108 /* ************************************************************************>> */
execTUP_ATTRINFO(Signal * signal)4109 void Dblqh::execTUP_ATTRINFO(Signal* signal)
4110 {
4111   TcConnectionrec *regTcConnectionrec = tcConnectionrec;
4112   Uint32 tcIndex = signal->theData[0];
4113   Uint32 ttcConnectrecFileSize = ctcConnectrecFileSize;
4114   jamEntry();
4115   tcConnectptr.i = tcIndex;
4116   ptrCheckGuard(tcConnectptr, ttcConnectrecFileSize, regTcConnectionrec);
4117   TcConnectionrec * const regTcPtr = tcConnectptr.p;
4118 
4119   ndbrequire(regTcPtr->transactionState == TcConnectionrec::WAIT_TUP);
4120 
4121   /* TUP_ATTRINFO signal is unrelated to ATTRINFO
4122    * It just transports a section IVAL from TUP back to
4123    * LQH
4124    */
4125   ndbrequire(signal->header.theLength == 3);
4126   Uint32 tupAttrInfoWords= signal->theData[1];
4127   Uint32 tupAttrInfoIVal= signal->theData[2];
4128 
4129   ndbassert(tupAttrInfoWords > 0);
4130   ndbassert(tupAttrInfoIVal != RNIL);
4131 
4132   /* If we have stored ATTRINFO that we sent to TUP,
4133    * free it now
4134    */
4135   if (regTcPtr->attrInfoIVal != RNIL)
4136   {
4137     /* We should be expecting to receive attrInfo back */
4138     ndbassert( !(regTcPtr->m_flags &
4139                  TcConnectionrec::OP_SAVEATTRINFO) );
4140     releaseSection( regTcPtr->attrInfoIVal );
4141     regTcPtr->attrInfoIVal= RNIL;
4142   }
4143 
4144   /* Store reference to ATTRINFO from TUP */
4145   regTcPtr->attrInfoIVal= tupAttrInfoIVal;
4146   regTcPtr->currTupAiLen= tupAttrInfoWords;
4147 
4148 }//Dblqh::execTUP_ATTRINFO()
4149 
4150 /* ------------------------------------------------------------------------- */
4151 /* -------                HANDLE ATTRINFO FROM LQH                   ------- */
4152 /*                                                                           */
4153 /* ------------------------------------------------------------------------- */
lqhAttrinfoLab(Signal * signal,Uint32 * dataPtr,Uint32 length)4154 void Dblqh::lqhAttrinfoLab(Signal* signal, Uint32* dataPtr, Uint32 length)
4155 {
4156   /* Store received AttrInfo in a long section */
4157   jam();
4158   if (saveAttrInfoInSection(dataPtr, length) == ZOK) {
4159     ;
4160   } else {
4161     jam();
4162 /* ------------------------------------------------------------------------- */
4163 /* WE MIGHT BE WAITING FOR RESPONSE FROM SOME BLOCK HERE. THUS WE NEED TO    */
4164 /* GO THROUGH THE STATE MACHINE FOR THE OPERATION.                           */
4165 /* ------------------------------------------------------------------------- */
4166     localAbortStateHandlerLab(signal);
4167     return;
4168   }//if
4169 }//Dblqh::lqhAttrinfoLab()
4170 
4171 /* ------------------------------------------------------------------------- */
4172 /* ------         FIND TRANSACTION BY USING HASH TABLE               ------- */
4173 /*                                                                           */
4174 /* ------------------------------------------------------------------------- */
findTransaction(UintR Transid1,UintR Transid2,UintR TcOprec,Uint32 hi)4175 int Dblqh::findTransaction(UintR Transid1, UintR Transid2, UintR TcOprec,
4176                            Uint32 hi)
4177 {
4178   TcConnectionrec *regTcConnectionrec = tcConnectionrec;
4179   Uint32 ttcConnectrecFileSize = ctcConnectrecFileSize;
4180   TcConnectionrecPtr locTcConnectptr;
4181 
4182   Uint32 ThashIndex = (Transid1 ^ TcOprec) & 1023;
4183   locTcConnectptr.i = ctransidHash[ThashIndex];
4184   while (locTcConnectptr.i != RNIL) {
4185     ptrCheckGuard(locTcConnectptr, ttcConnectrecFileSize, regTcConnectionrec);
4186     if ((locTcConnectptr.p->transid[0] == Transid1) &&
4187         (locTcConnectptr.p->transid[1] == Transid2) &&
4188         (locTcConnectptr.p->tcOprec == TcOprec) &&
4189         (locTcConnectptr.p->tcHashKeyHi == hi)) {
4190 /* FIRST PART OF TRANSACTION CORRECT */
4191 /* SECOND PART ALSO CORRECT */
4192 /* THE OPERATION RECORD POINTER IN TC WAS ALSO CORRECT */
4193       jam();
4194       tcConnectptr.i = locTcConnectptr.i;
4195       tcConnectptr.p = locTcConnectptr.p;
4196       return (int)ZOK;
4197     }//if
4198     jam();
4199 /* THIS WAS NOT THE TRANSACTION WHICH WAS SOUGHT */
4200     locTcConnectptr.i = locTcConnectptr.p->nextHashRec;
4201   }//while
4202 /* WE DID NOT FIND THE TRANSACTION, REPORT NOT FOUND */
4203   return (int)ZNOT_FOUND;
4204 }//Dblqh::findTransaction()
4205 
4206 /* ------------------------------------------------------------------------- */
4207 /* -------           SAVE ATTRINFO INTO ATTR SECTION                 ------- */
4208 /*                                                                           */
4209 /* ------------------------------------------------------------------------- */
saveAttrInfoInSection(const Uint32 * dataPtr,Uint32 len)4210 int Dblqh::saveAttrInfoInSection(const Uint32* dataPtr, Uint32 len)
4211 {
4212   TcConnectionrec * const regTcPtr = tcConnectptr.p;
4213 
4214   bool ok= appendToSection(regTcPtr->attrInfoIVal,
4215                            dataPtr,
4216                            len);
4217 
4218   if (unlikely(!ok))
4219   {
4220     jam();
4221     terrorCode = ZGET_ATTRINBUF_ERROR;
4222     return ZGET_ATTRINBUF_ERROR;
4223   }//if
4224 
4225   if (regTcPtr->m_flags & TcConnectionrec::OP_SAVEATTRINFO)
4226     regTcPtr->currTupAiLen += len;
4227 
4228   return ZOK;
4229 } // saveAttrInfoInSection
4230 
4231 
4232 /* ==========================================================================
4233  * =======                        SEIZE TC CONNECT RECORD             =======
4234  *
4235  *       GETS A NEW TC CONNECT RECORD FROM FREELIST.
4236  * ========================================================================= */
seizeTcrec()4237 void Dblqh::seizeTcrec()
4238 {
4239   TcConnectionrecPtr locTcConnectptr;
4240 
4241   locTcConnectptr.i = cfirstfreeTcConrec;
4242   ptrCheckGuard(locTcConnectptr, ctcConnectrecFileSize, tcConnectionrec);
4243   Uint32 nextTc = locTcConnectptr.p->nextTcConnectrec;
4244   locTcConnectptr.p->nextTcConnectrec = RNIL;
4245   locTcConnectptr.p->clientConnectrec = RNIL;
4246   locTcConnectptr.p->clientBlockref = RNIL;
4247   locTcConnectptr.p->abortState = TcConnectionrec::ABORT_IDLE;
4248   locTcConnectptr.p->tcTimer = cLqhTimeOutCount;
4249   locTcConnectptr.p->tableref = RNIL;
4250   locTcConnectptr.p->savePointId = 0;
4251   locTcConnectptr.p->gci_hi = 0;
4252   locTcConnectptr.p->gci_lo = 0;
4253   cfirstfreeTcConrec = nextTc;
4254   tcConnectptr = locTcConnectptr;
4255   locTcConnectptr.p->connectState = TcConnectionrec::CONNECTED;
4256 }//Dblqh::seizeTcrec()
4257 
checkTransporterOverloaded(Signal * signal,const NodeBitmask & all,const LqhKeyReq * req)4258 bool Dblqh::checkTransporterOverloaded(Signal* signal,
4259                                        const NodeBitmask& all,
4260                                        const LqhKeyReq* req)
4261 {
4262   // nodes likely to be affected by this op
4263   NodeBitmask mask;
4264   // tc
4265   Uint32 tc_node = refToNode(req->tcBlockref);
4266   if (tc_node < MAX_NODES) // not worth to crash here
4267     mask.set(tc_node);
4268   const Uint8 op = LqhKeyReq::getOperation(req->requestInfo);
4269   if (op == ZREAD || op == ZREAD_EX || op == ZUNLOCK) {
4270     // the receiver
4271     Uint32 api_node = refToNode(req->variableData[0]);
4272     if (api_node < MAX_NODES) // not worth to crash here
4273       mask.set(api_node);
4274   } else {
4275     // next replica
4276     Uint32 replica_node = LqhKeyReq::getNextReplicaNodeId(req->fragmentData);
4277     if (replica_node < MAX_NODES) // could be ZNIL
4278       mask.set(replica_node);
4279     // event subscribers
4280     const Suma* suma = (Suma*)globalData.getBlock(SUMA);
4281     mask.bitOR(suma->getSubscriberNodes());
4282   }
4283   mask.bitAND(all);
4284   return !mask.isclear();
4285 }
4286 
execSIGNAL_DROPPED_REP(Signal * signal)4287 void Dblqh::execSIGNAL_DROPPED_REP(Signal* signal)
4288 {
4289   /* An incoming signal was dropped, handle it
4290    * Dropped signal really means that we ran out of
4291    * long signal buffering to store its sections
4292    */
4293   jamEntry();
4294 
4295   if (!assembleDroppedFragments(signal))
4296   {
4297     jam();
4298     return;
4299   }
4300 
4301   const SignalDroppedRep* rep = (SignalDroppedRep*) &signal->theData[0];
4302   Uint32 originalGSN= rep->originalGsn;
4303 
4304   DEBUG("SignalDroppedRep received for GSN " << originalGSN);
4305 
4306   switch(originalGSN) {
4307   case GSN_LQHKEYREQ:
4308   {
4309     jam();
4310     /* Get original signal data - unfortunately it may
4311      * have been truncated.  We must not read beyond
4312      * word # 22
4313      * We will notify the client that their LQHKEYREQ
4314      * failed
4315      */
4316     const LqhKeyReq * const truncatedLqhKeyReq =
4317       (LqhKeyReq *) &rep->originalData[0];
4318 
4319     noFreeRecordLab(signal, truncatedLqhKeyReq, ZGET_DATAREC_ERROR);
4320 
4321     break;
4322   }
4323   case GSN_SCAN_FRAGREQ:
4324   {
4325     jam();
4326     /* Get original signal data - unfortunately it may
4327      * have been truncated.  We must not read beyond
4328      * word # 22
4329      * We will notify the client that their SCAN_FRAGREQ
4330      * failed
4331      */
4332     // TODO : Handle fragmented failure
4333     const ScanFragReq* const truncatedScanFragReq =
4334       (ScanFragReq*) &rep->originalData[0];
4335     const Uint32 senderData= truncatedScanFragReq->senderData;
4336     const Uint32 transid1= truncatedScanFragReq->transId1;
4337     const Uint32 transid2= truncatedScanFragReq->transId2;
4338 
4339     /* Send SCAN_FRAGREF back to the client */
4340     ScanFragRef* ref= (ScanFragRef*)&signal->theData[0];
4341     ref->senderData= senderData;
4342     ref->transId1= transid1;
4343     ref->transId2= transid2;
4344     ref->errorCode= ZGET_ATTRINBUF_ERROR;
4345 
4346     sendSignal(signal->senderBlockRef(), GSN_SCAN_FRAGREF, signal,
4347                ScanFragRef::SignalLength, JBB);
4348     break;
4349   }
4350   default:
4351     jam();
4352     /* Don't expect dropped signals for other GSNs,
4353      * default handling
4354      */
4355     SimulatedBlock::execSIGNAL_DROPPED_REP(signal);
4356   };
4357 
4358   return;
4359 }
4360 
4361 /* ------------------------------------------------------------------------- */
4362 /* -------                TAKE CARE OF LQHKEYREQ                     ------- */
4363 /* LQHKEYREQ IS THE SIGNAL THAT STARTS ALL OPERATIONS IN THE LQH BLOCK       */
4364 /* THIS SIGNAL CONTAINS A LOT OF INFORMATION ABOUT WHAT TYPE OF OPERATION,   */
4365 /* KEY INFORMATION, ATTRIBUTE INFORMATION, NODE INFORMATION AND A LOT MORE   */
4366 /* ------------------------------------------------------------------------- */
execLQHKEYREQ(Signal * signal)4367 void Dblqh::execLQHKEYREQ(Signal* signal)
4368 {
4369   UintR sig0, sig1, sig2, sig3, sig4, sig5;
4370   Uint8 tfragDistKey;
4371 
4372   const LqhKeyReq * const lqhKeyReq = (LqhKeyReq *)signal->getDataPtr();
4373   SectionHandle handle(this, signal);
4374 
4375   {
4376     const NodeBitmask& all = globalTransporterRegistry.get_status_overloaded();
4377     if (unlikely((!all.isclear() &&
4378                   checkTransporterOverloaded(signal, all, lqhKeyReq))) ||
4379         ERROR_INSERTED_CLEAR(5047)) {
4380       jam();
4381       releaseSections(handle);
4382       noFreeRecordLab(signal, lqhKeyReq, ZTRANSPORTER_OVERLOADED_ERROR);
4383       return;
4384     }
4385   }
4386 
4387   sig0 = lqhKeyReq->clientConnectPtr;
4388   if (cfirstfreeTcConrec != RNIL && !ERROR_INSERTED_CLEAR(5031)) {
4389     jamEntry();
4390     seizeTcrec();
4391   } else {
4392 /* ------------------------------------------------------------------------- */
4393 /* NO FREE TC RECORD AVAILABLE, THUS WE CANNOT HANDLE THE REQUEST.           */
4394 /* ------------------------------------------------------------------------- */
4395     releaseSections(handle);
4396     noFreeRecordLab(signal, lqhKeyReq, ZNO_TC_CONNECT_ERROR);
4397     return;
4398   }//if
4399 
4400   if(ERROR_INSERTED(5038) &&
4401      refToNode(signal->getSendersBlockRef()) != getOwnNodeId()){
4402     jam();
4403     releaseSections(handle);
4404     SET_ERROR_INSERT_VALUE(5039);
4405     return;
4406   }
4407 
4408   cTotalLqhKeyReqCount++;
4409   c_Counters.operations++;
4410 
4411   TcConnectionrec * const regTcPtr = tcConnectptr.p;
4412   Uint32 senderRef = regTcPtr->clientBlockref = signal->senderBlockRef();
4413   regTcPtr->clientConnectrec = sig0;
4414   regTcPtr->tcOprec = sig0;
4415   regTcPtr->tcHashKeyHi = 0;
4416   regTcPtr->storedProcId = ZNIL;
4417   regTcPtr->lqhKeyReqId = cTotalLqhKeyReqCount;
4418   regTcPtr->m_flags= 0;
4419   bool isLongReq= false;
4420   if (handle.m_cnt > 0)
4421   {
4422     isLongReq= true;
4423     regTcPtr->m_flags|= TcConnectionrec::OP_ISLONGREQ;
4424   }
4425 
4426   UintR attrLenFlags = lqhKeyReq->attrLen;
4427   sig1 = lqhKeyReq->savePointId;
4428   sig2 = lqhKeyReq->hashValue;
4429   UintR Treqinfo = lqhKeyReq->requestInfo;
4430   sig4 = lqhKeyReq->tableSchemaVersion;
4431   sig5 = lqhKeyReq->tcBlockref;
4432 
4433   regTcPtr->savePointId = sig1;
4434   regTcPtr->hashValue = sig2;
4435   const Uint32 schemaVersion = regTcPtr->schemaVersion = LqhKeyReq::getSchemaVersion(sig4);
4436   tabptr.i = LqhKeyReq::getTableId(sig4);
4437   regTcPtr->tcBlockref = sig5;
4438 
4439   const Uint8 op = LqhKeyReq::getOperation(Treqinfo);
4440   if ((op == ZREAD || op == ZREAD_EX) && !getAllowRead()){
4441     releaseSections(handle);
4442     noFreeRecordLab(signal, lqhKeyReq, ZNODE_SHUTDOWN_IN_PROGESS);
4443     return;
4444   }
4445 
4446   if (unlikely(get_node_status(refToNode(sig5)) != ZNODE_UP))
4447   {
4448     releaseSections(handle);
4449     noFreeRecordLab(signal, lqhKeyReq, ZNODE_FAILURE_ERROR);
4450     return;
4451   }
4452 
4453   Uint32 senderVersion = getNodeInfo(refToNode(senderRef)).m_version;
4454 
4455   regTcPtr->tcScanInfo  = lqhKeyReq->scanInfo;
4456   regTcPtr->indTakeOver = LqhKeyReq::getScanTakeOverFlag(attrLenFlags);
4457   regTcPtr->m_reorg     = LqhKeyReq::getReorgFlag(attrLenFlags);
4458 
4459   regTcPtr->readlenAi = 0;
4460   regTcPtr->currTupAiLen = 0;
4461   regTcPtr->listState = TcConnectionrec::NOT_IN_LIST;
4462   regTcPtr->logWriteState = TcConnectionrec::NOT_STARTED;
4463   regTcPtr->fragmentptr = RNIL;
4464 
4465   sig0 = lqhKeyReq->fragmentData;
4466   sig1 = lqhKeyReq->transId1;
4467   sig2 = lqhKeyReq->transId2;
4468   sig3 = lqhKeyReq->variableData[0];
4469   sig4 = lqhKeyReq->variableData[1];
4470 
4471   regTcPtr->fragmentid = LqhKeyReq::getFragmentId(sig0);
4472   regTcPtr->nextReplica = LqhKeyReq::getNextReplicaNodeId(sig0);
4473   regTcPtr->transid[0] = sig1;
4474   regTcPtr->transid[1] = sig2;
4475   regTcPtr->applRef = sig3;
4476   regTcPtr->applOprec = sig4;
4477 
4478   regTcPtr->commitAckMarker = RNIL;
4479   if (LqhKeyReq::getMarkerFlag(Treqinfo))
4480   {
4481     struct CommitAckMarker check;
4482     CommitAckMarkerPtr markerPtr;
4483     jam();
4484     check.transid1 = regTcPtr->transid[0];
4485     check.transid2 = regTcPtr->transid[1];
4486 
4487     if (m_commitAckMarkerHash.find(markerPtr, check))
4488     {
4489       /*
4490         A commit ack marker was already placed here for this transaction.
4491         We increase the reference count to ensure we don't remove the
4492         commit ack marker prematurely.
4493       */
4494       markerPtr.p->reference_count++;
4495 #ifdef MARKER_TRACE
4496       ndbout_c("Inc marker[%.8x %.8x] op: %u ref: %u",
4497                markerPtr.p->transid1, markerPtr.p->transid2,
4498                tcConnectptr.i, markerPtr.p->reference_count);
4499 #endif
4500     }
4501     else
4502     {
4503       m_commitAckMarkerHash.seize(markerPtr);
4504       if (markerPtr.i == RNIL)
4505       {
4506         releaseSections(handle);
4507         noFreeRecordLab(signal, lqhKeyReq, ZNO_FREE_MARKER_RECORDS_ERROR);
4508         return;
4509       }
4510       markerPtr.p->transid1 = sig1;
4511       markerPtr.p->transid2 = sig2;
4512       markerPtr.p->apiRef   = sig3;
4513       markerPtr.p->apiOprec = sig4;
4514       const NodeId tcNodeId  = refToNode(sig5);
4515       markerPtr.p->tcNodeId = tcNodeId;
4516       markerPtr.p->reference_count = 1;
4517       m_commitAckMarkerHash.add(markerPtr);
4518 
4519 #ifdef MARKER_TRACE
4520       ndbout_c("%u Add marker[%.8x %.8x] op: %u", instance(), markerPtr.p->transid1, markerPtr.p->transid2, tcConnectptr.i);
4521 #endif
4522     }
4523     regTcPtr->commitAckMarker = markerPtr.i;
4524   }
4525 
4526   regTcPtr->reqinfo = Treqinfo;
4527   regTcPtr->lastReplicaNo = LqhKeyReq::getLastReplicaNo(Treqinfo);
4528   regTcPtr->dirtyOp       = LqhKeyReq::getDirtyFlag(Treqinfo);
4529   regTcPtr->opExec        = LqhKeyReq::getInterpretedFlag(Treqinfo);
4530   regTcPtr->opSimple      = LqhKeyReq::getSimpleFlag(Treqinfo);
4531   regTcPtr->seqNoReplica  = LqhKeyReq::getSeqNoReplica(Treqinfo);
4532   regTcPtr->apiVersionNo  = 0;
4533   regTcPtr->m_use_rowid   = LqhKeyReq::getRowidFlag(Treqinfo);
4534   regTcPtr->m_dealloc     = 0;
4535   if (unlikely(senderVersion < NDBD_ROWID_VERSION))
4536   {
4537     regTcPtr->operation = op;
4538     regTcPtr->lockType = LqhKeyReq::getLockType(Treqinfo);
4539   }
4540   else
4541   {
4542     regTcPtr->operation = (Operation_t) op == ZREAD_EX ? ZREAD : (Operation_t) op;
4543     regTcPtr->lockType =
4544       op == ZREAD_EX ? ZUPDATE :
4545       (Operation_t) op == ZWRITE ? ZINSERT :
4546       (Operation_t) op == ZREFRESH ? ZINSERT :
4547       (Operation_t) op == ZUNLOCK ? ZREAD : // lockType not relevant for unlock req
4548       (Operation_t) op;
4549   }
4550 
4551   if (regTcPtr->dirtyOp)
4552   {
4553     ndbrequire(regTcPtr->opSimple);
4554   }
4555 
4556   CRASH_INSERTION2(5041, (op == ZREAD &&
4557                           (regTcPtr->opSimple || regTcPtr->dirtyOp) &&
4558                           refToNode(signal->senderBlockRef()) != cownNodeid));
4559 
4560   regTcPtr->noFiredTriggers = lqhKeyReq->noFiredTriggers;
4561 
4562   UintR TapplAddressInd = LqhKeyReq::getApplicationAddressFlag(Treqinfo);
4563   UintR nextPos = (TapplAddressInd << 1);
4564   UintR TsameClientAndTcOprec = LqhKeyReq::getSameClientAndTcFlag(Treqinfo);
4565   if (TsameClientAndTcOprec == 1) {
4566     regTcPtr->tcOprec = lqhKeyReq->variableData[nextPos];
4567     nextPos++;
4568   }//if
4569   UintR TnextReplicasIndicator = regTcPtr->lastReplicaNo -
4570                                  regTcPtr->seqNoReplica;
4571   if (TnextReplicasIndicator > 1) {
4572     regTcPtr->nodeAfterNext[0] = lqhKeyReq->variableData[nextPos] & 0xFFFF;
4573     regTcPtr->nodeAfterNext[1] = lqhKeyReq->variableData[nextPos] >> 16;
4574     nextPos++;
4575   }//if
4576   UintR TstoredProcIndicator = LqhKeyReq::getStoredProcFlag(attrLenFlags);
4577   if (TstoredProcIndicator == 1) {
4578     regTcPtr->storedProcId = lqhKeyReq->variableData[nextPos] & ZNIL;
4579     nextPos++;
4580   }//if
4581   UintR TreadLenAiIndicator = LqhKeyReq::getReturnedReadLenAIFlag(Treqinfo);
4582   if (TreadLenAiIndicator == 1) {
4583     regTcPtr->readlenAi = lqhKeyReq->variableData[nextPos] & ZNIL;
4584     nextPos++;
4585   }//if
4586 
4587   Uint32 TanyValueFlag = LqhKeyReq::getCorrFactorFlag(Treqinfo);
4588   if (isLongReq && TanyValueFlag == 1)
4589   {
4590     /**
4591      * For short lqhkeyreq, ai-length in-signal is stored in same pos...
4592      */
4593     regTcPtr->m_corrFactorLo = lqhKeyReq->variableData[nextPos + 0];
4594     regTcPtr->m_corrFactorHi = lqhKeyReq->variableData[nextPos + 1];
4595     nextPos += 2;
4596   }
4597 
4598   Uint32 Tdeferred = LqhKeyReq::getDeferredConstraints(Treqinfo);
4599   if (isLongReq && Tdeferred)
4600   {
4601     regTcPtr->m_flags |= TcConnectionrec::OP_DEFERRED_CONSTRAINTS;
4602     regTcPtr->m_fire_trig_pass = 0;
4603   }
4604 
4605   UintR TitcKeyLen = 0;
4606   Uint32 keyLenWithLQHReq = 0;
4607   UintR TreclenAiLqhkey   = 0;
4608 
4609   if (isLongReq)
4610   {
4611     /* Long LQHKEYREQ indicates Key and AttrInfo presence and
4612      * size via section lengths
4613      */
4614     SegmentedSectionPtr keyInfoSection, attrInfoSection;
4615 
4616     handle.getSection(keyInfoSection,
4617                       LqhKeyReq::KeyInfoSectionNum);
4618 
4619     ndbassert(keyInfoSection.i != RNIL);
4620 
4621     regTcPtr->keyInfoIVal= keyInfoSection.i;
4622     TitcKeyLen= keyInfoSection.sz;
4623     keyLenWithLQHReq= TitcKeyLen;
4624 
4625     Uint32 totalAttrInfoLen= 0;
4626     if (handle.getSection(attrInfoSection,
4627                           LqhKeyReq::AttrInfoSectionNum))
4628     {
4629       regTcPtr->attrInfoIVal= attrInfoSection.i;
4630       totalAttrInfoLen= attrInfoSection.sz;
4631     }
4632 
4633     regTcPtr->reclenAiLqhkey = 0;
4634     regTcPtr->currReclenAi = totalAttrInfoLen;
4635     regTcPtr->totReclenAi = totalAttrInfoLen;
4636 
4637     /* Detach sections from the handle, we are now responsible
4638      * for freeing them when appropriate
4639      */
4640     handle.clear();
4641   }
4642   else
4643   {
4644     /* Short LQHKEYREQ, Key and Attr sizes are in
4645      * signal, along with some data
4646      */
4647     TreclenAiLqhkey= LqhKeyReq::getAIInLqhKeyReq(Treqinfo);
4648     regTcPtr->reclenAiLqhkey = TreclenAiLqhkey;
4649     regTcPtr->currReclenAi = TreclenAiLqhkey;
4650     TitcKeyLen = LqhKeyReq::getKeyLen(Treqinfo);
4651     regTcPtr->totReclenAi = LqhKeyReq::getAttrLen(attrLenFlags);
4652 
4653     /* Note key can be length zero for NR when Rowid used */
4654     keyLenWithLQHReq= MIN(TitcKeyLen, LqhKeyReq::MaxKeyInfo);
4655 
4656     bool ok= appendToSection(regTcPtr->keyInfoIVal,
4657                              &lqhKeyReq->variableData[ nextPos ],
4658                              keyLenWithLQHReq);
4659     if (unlikely(!ok))
4660     {
4661       jam();
4662       terrorCode= ZGET_DATAREC_ERROR;
4663       abortErrorLab(signal);
4664       return;
4665     }
4666 
4667     nextPos+= keyLenWithLQHReq;
4668   }
4669 
4670   regTcPtr->primKeyLen = TitcKeyLen;
4671 
4672   /* Only node restart copy allowed to send no KeyInfo */
4673   if (unlikely(keyLenWithLQHReq == 0))
4674   {
4675     if (refToMain(senderRef) == DBSPJ)
4676     {
4677       jam();
4678       ndbassert(! LqhKeyReq::getNrCopyFlag(Treqinfo));
4679       terrorCode = ZNO_TUPLE_FOUND;
4680       abortErrorLab(signal);
4681       return;
4682     }
4683 
4684     if (! LqhKeyReq::getNrCopyFlag(Treqinfo))
4685     {
4686       LQHKEY_error(signal, 3);
4687       return;
4688     }//if
4689   }
4690 
4691   sig0 = lqhKeyReq->variableData[nextPos + 0];
4692   sig1 = lqhKeyReq->variableData[nextPos + 1];
4693   regTcPtr->m_row_id.m_page_no = sig0;
4694   regTcPtr->m_row_id.m_page_idx = sig1;
4695   nextPos += 2 * LqhKeyReq::getRowidFlag(Treqinfo);
4696 
4697   sig2 = lqhKeyReq->variableData[nextPos + 0];
4698   sig3 = cnewestGci;
4699   /* If gci_hi provided, take it and set gci_lo to max value
4700    * Otherwise, it will be decided by TUP at commit time as normal
4701    */
4702   regTcPtr->gci_hi = LqhKeyReq::getGCIFlag(Treqinfo) ? sig2 : sig3;
4703   regTcPtr->gci_lo = LqhKeyReq::getGCIFlag(Treqinfo) ? ~Uint32(0) : 0;
4704   nextPos += LqhKeyReq::getGCIFlag(Treqinfo);
4705 
4706   if (LqhKeyReq::getRowidFlag(Treqinfo))
4707   {
4708     ndbassert(refToMain(senderRef) != DBTC);
4709   }
4710   else if(op == ZINSERT)
4711   {
4712     ndbassert(refToMain(senderRef) == DBTC);
4713   }
4714 
4715   if ((LqhKeyReq::FixedSignalLength + nextPos + TreclenAiLqhkey) !=
4716       signal->length()) {
4717     LQHKEY_error(signal, 2);
4718     return;
4719   }//if
4720   UintR TseqNoReplica = regTcPtr->seqNoReplica;
4721   UintR TlastReplicaNo = regTcPtr->lastReplicaNo;
4722   if (TseqNoReplica == TlastReplicaNo) {
4723     jam();
4724     regTcPtr->nextReplica = ZNIL;
4725   } else {
4726     if (TseqNoReplica < TlastReplicaNo) {
4727       jam();
4728       regTcPtr->nextSeqNoReplica = TseqNoReplica + 1;
4729       if ((regTcPtr->nextReplica == 0) ||
4730           (regTcPtr->nextReplica == cownNodeid)) {
4731         LQHKEY_error(signal, 0);
4732       }//if
4733     } else {
4734       LQHKEY_error(signal, 4);
4735       return;
4736     }//if
4737   }//if
4738   TcConnectionrecPtr localNextTcConnectptr;
4739   Uint32 hashIndex = (regTcPtr->transid[0] ^ regTcPtr->tcOprec) & 1023;
4740   localNextTcConnectptr.i = ctransidHash[hashIndex];
4741   ctransidHash[hashIndex] = tcConnectptr.i;
4742   regTcPtr->prevHashRec = RNIL;
4743   regTcPtr->nextHashRec = localNextTcConnectptr.i;
4744   if (localNextTcConnectptr.i != RNIL) {
4745 /* -------------------------------------------------------------------------- */
4746 /* ENSURE THAT THE NEXT RECORD HAS SET PREVIOUS TO OUR RECORD IF IT EXISTS    */
4747 /* -------------------------------------------------------------------------- */
4748     ptrCheckGuard(localNextTcConnectptr,
4749                   ctcConnectrecFileSize, tcConnectionrec);
4750     jam();
4751     localNextTcConnectptr.p->prevHashRec = tcConnectptr.i;
4752   }//if
4753   if (tabptr.i >= ctabrecFileSize) {
4754     LQHKEY_error(signal, 5);
4755     return;
4756   }//if
4757   ptrAss(tabptr, tablerec);
4758   if(table_version_major_lqhkeyreq(tabptr.p->schemaVersion) !=
4759      table_version_major_lqhkeyreq(schemaVersion)){
4760     LQHKEY_abort(signal, 5);
4761     return;
4762   }
4763 
4764   if (unlikely(tabptr.p->tableStatus != Tablerec::TABLE_DEFINED))
4765   {
4766     if (check_tabstate(signal, tabptr.p, op))
4767       return;
4768   }
4769 
4770   regTcPtr->tableref = tabptr.i;
4771   regTcPtr->m_disk_table = tabptr.p->m_disk_table;
4772   if(refToMain(signal->senderBlockRef()) == RESTORE)
4773     regTcPtr->m_disk_table &= !LqhKeyReq::getNoDiskFlag(Treqinfo);
4774   else if(op == ZREAD || op == ZREAD_EX || op == ZUPDATE)
4775     regTcPtr->m_disk_table &= !LqhKeyReq::getNoDiskFlag(Treqinfo);
4776 
4777   if (op == ZREAD || op == ZREAD_EX || op == ZUNLOCK)
4778     tabptr.p->usageCountR++;
4779   else
4780     tabptr.p->usageCountW++;
4781 
4782   if (!getFragmentrec(signal, regTcPtr->fragmentid)) {
4783     LQHKEY_error(signal, 6);
4784     return;
4785   }//if
4786 
4787   if (LqhKeyReq::getNrCopyFlag(Treqinfo))
4788   {
4789     ndbassert(refToMain(senderRef) == DBLQH);
4790     ndbassert(LqhKeyReq::getRowidFlag(Treqinfo));
4791     if (! (fragptr.p->fragStatus == Fragrecord::ACTIVE_CREATION))
4792     {
4793       ndbout_c("fragptr.p->fragStatus: %d",
4794 	       fragptr.p->fragStatus);
4795       CRASH_INSERTION(5046);
4796     }
4797     ndbassert(fragptr.p->fragStatus == Fragrecord::ACTIVE_CREATION);
4798     fragptr.p->m_copy_started_state = Fragrecord::AC_NR_COPY;
4799   }
4800 
4801   Uint8 TcopyType = fragptr.p->fragCopy;
4802   Uint32 logPart = fragptr.p->m_log_part_ptr_i;
4803   tfragDistKey = fragptr.p->fragDistributionKey;
4804   if (fragptr.p->fragStatus == Fragrecord::ACTIVE_CREATION) {
4805     jam();
4806     regTcPtr->activeCreat = fragptr.p->m_copy_started_state;
4807     CRASH_INSERTION(5002);
4808     CRASH_INSERTION2(5042, tabptr.i == c_error_insert_table_id);
4809   } else {
4810     regTcPtr->activeCreat = Fragrecord::AC_NORMAL;
4811   }//if
4812   regTcPtr->replicaType = TcopyType;
4813   regTcPtr->fragmentptr = fragptr.i;
4814   regTcPtr->m_log_part_ptr_i = logPart;
4815   Uint8 TdistKey = LqhKeyReq::getDistributionKey(attrLenFlags);
4816   if ((tfragDistKey != TdistKey) &&
4817       (regTcPtr->seqNoReplica == 0) &&
4818       (regTcPtr->dirtyOp == ZFALSE))
4819   {
4820     /* ----------------------------------------------------------------------
4821      * WE HAVE DIFFERENT OPINION THAN THE DIH THAT STARTED THE TRANSACTION.
4822      * THE REASON COULD BE THAT THIS IS AN OLD DISTRIBUTION WHICH IS NO LONGER
4823      * VALID TO USE. THIS MUST BE CHECKED.
4824      * ONE IS ADDED TO THE DISTRIBUTION KEY EVERY TIME WE ADD A NEW REPLICA.
4825      * FAILED REPLICAS DO NOT AFFECT THE DISTRIBUTION KEY. THIS MEANS THAT THE
4826      * MAXIMUM DEVIATION CAN BE ONE BETWEEN THOSE TWO VALUES.
4827      * --------------------------------------------------------------------- */
4828     Int8 tmp = (TdistKey - tfragDistKey);
4829     tmp = (tmp < 0 ? - tmp : tmp);
4830     if ((tmp <= 1) || (tfragDistKey == 0)) {
4831       LQHKEY_abort(signal, 0);
4832       return;
4833     }//if
4834     LQHKEY_error(signal, 1);
4835     // Never get here
4836   }//if
4837 
4838   /*
4839    * Interpreted updates and deletes may require different AttrInfo in
4840    * different replicas, as only the primary executes the interpreted
4841    * program, and the effect of the program rather than the program
4842    * should be logged.
4843    * Non interpreted inserts, updates, writes and deletes use the same
4844    * AttrInfo in all replicas.
4845    * All reads only run on one replica, and are not logged.
4846    * The AttrInfo section is passed to TUP attached to the TUPKEYREQ
4847    * signal below.
4848    *
4849    * Normal processing :
4850    *   - LQH passes ATTRINFO section to TUP attached to direct TUPKEYREQ
4851    *     signal
4852    *   - TUP processes request and sends direct TUPKEYCONF back to LQH
4853    *   - LQH continues processing (logging, forwarding LQHKEYREQ to other
4854    *     replicas as necessary)
4855    *   - LQH frees ATTRINFO section
4856    *   Note that TUP is not responsible for freeing the passed ATTRINFO
4857    *   section, LQH is.
4858    *
4859    * Interpreted Update / Delete processing
4860    *   - LQH passes ATTRINFO section to TUP attached to direct TUPKEYREQ
4861    *     signal
4862    *   - TUP processes request, generating new ATTRINFO data
4863    *   - If new AttrInfo data is > 0 words, TUP sends it back to LQH as
4864    *     a long section attached to a single ATTRINFO signal.
4865    *     - LQH frees the original AttrInfo section and stores a ref to
4866    *       the new section
4867    *   - TUP sends direct TUPKEYCONF back to LQH with new ATTRINFO length
4868    *   - If the new ATTRINFO is > 0 words,
4869    *       - LQH continues processing with it (logging, forwarding
4870    *         LQHKEYREQ to other replicas as necessary)
4871    *       - LQH frees the new ATTRINFO section
4872    *   - If the new ATTRINFO is 0 words, LQH frees the original ATTRINFO
4873    *     section and continues processing (logging, forwarding LQHKEYREQ
4874    *     to other replicas as necessary)
4875    *
4876    */
4877   bool attrInfoToPropagate=
4878     (regTcPtr->totReclenAi != 0) &&
4879     (regTcPtr->operation != ZREAD) &&
4880     (regTcPtr->operation != ZDELETE) &&
4881     (regTcPtr->operation != ZUNLOCK);
4882   bool tupCanChangePropagatedAttrInfo= (regTcPtr->opExec == 1);
4883 
4884   bool saveAttrInfo=
4885     attrInfoToPropagate &&
4886     (! tupCanChangePropagatedAttrInfo);
4887 
4888   if (saveAttrInfo)
4889     regTcPtr->m_flags|= TcConnectionrec::OP_SAVEATTRINFO;
4890 
4891   /* Handle any AttrInfo we received with the LQHKEYREQ */
4892   if (regTcPtr->currReclenAi != 0)
4893   {
4894     jam();
4895     if (isLongReq)
4896     {
4897       /* Long LQHKEYREQ */
4898       jam();
4899 
4900       regTcPtr->currTupAiLen= saveAttrInfo ?
4901         regTcPtr->totReclenAi :
4902         0;
4903     }
4904     else
4905     {
4906       /* Short LQHKEYREQ */
4907       jam();
4908 
4909       /* Lets put the AttrInfo into a segmented section */
4910       bool ok= appendToSection(regTcPtr->attrInfoIVal,
4911                                lqhKeyReq->variableData + nextPos,
4912                                TreclenAiLqhkey);
4913       if (unlikely(!ok))
4914       {
4915         jam();
4916         terrorCode= ZGET_DATAREC_ERROR;
4917         abortErrorLab(signal);
4918         return;
4919       }
4920 
4921       if (saveAttrInfo)
4922         regTcPtr->currTupAiLen= TreclenAiLqhkey;
4923     }
4924   }//if
4925 
4926   /* If we've received all KeyInfo, proceed with processing,
4927    * otherwise wait for discrete KeyInfo signals
4928    */
4929   if (regTcPtr->primKeyLen == keyLenWithLQHReq) {
4930     endgettupkeyLab(signal);
4931     return;
4932   } else {
4933     jam();
4934     ndbassert(!isLongReq);
4935     /* Wait for remaining KeyInfo */
4936     regTcPtr->save1 = keyLenWithLQHReq;
4937     regTcPtr->transactionState = TcConnectionrec::WAIT_TUPKEYINFO;
4938     return;
4939   }//if
4940   return;
4941 }//Dblqh::execLQHKEYREQ()
4942 
4943 
4944 
4945 /**
4946  * endgettupkeyLab
4947  * Invoked when all KeyInfo and/or all AttrInfo has been
4948  * received
4949  */
endgettupkeyLab(Signal * signal)4950 void Dblqh::endgettupkeyLab(Signal* signal)
4951 {
4952   TcConnectionrec * const regTcPtr = tcConnectptr.p;
4953   if (regTcPtr->totReclenAi == regTcPtr->currReclenAi) {
4954     ;
4955   } else {
4956     jam();
4957     /* Wait for discrete AttrInfo signals */
4958     ndbrequire(regTcPtr->currReclenAi < regTcPtr->totReclenAi);
4959     ndbassert( !(regTcPtr->m_flags &
4960                  TcConnectionrec::OP_ISLONGREQ) );
4961     regTcPtr->transactionState = TcConnectionrec::WAIT_ATTR;
4962     return;
4963   }//if
4964 
4965 /* ---------------------------------------------------------------------- */
4966 /*       NOW RECEPTION OF LQHKEYREQ IS COMPLETED THE NEXT STEP IS TO START*/
4967 /*       PROCESSING THE MESSAGE. IF THE MESSAGE IS TO A STAND-BY NODE     */
4968 /*       WITHOUT NETWORK REDUNDANCY OR PREPARE-TO-COMMIT ACTIVATED THE    */
4969 /*       PREPARATION TO SEND TO THE NEXT NODE WILL START IMMEDIATELY.     */
4970 /*                                                                        */
4971 /*       OTHERWISE THE PROCESSING WILL START AFTER SETTING THE PROPER     */
4972 /*       STATE. HOWEVER BEFORE PROCESSING THE MESSAGE                     */
4973 /*       IT IS NECESSARY TO CHECK THAT THE FRAGMENT IS NOT PERFORMING     */
4974 /*       A CHECKPOINT. THE OPERATION SHALL ALSO BE LINKED INTO THE        */
4975 /*       FRAGMENT QUEUE OR LIST OF ACTIVE OPERATIONS.                     */
4976 /*                                                                        */
4977 /*       THE FIRST STEP IN PROCESSING THE MESSAGE IS TO CONTACT DBACC.    */
4978 /*------------------------------------------------------------------------*/
4979   switch (fragptr.p->fragStatus) {
4980   case Fragrecord::FSACTIVE:
4981   case Fragrecord::CRASH_RECOVERING:
4982   case Fragrecord::ACTIVE_CREATION:
4983     prepareContinueAfterBlockedLab(signal);
4984     return;
4985     break;
4986   case Fragrecord::BLOCKED:
4987     jam();
4988     linkFragQueue(signal);
4989     regTcPtr->transactionState = TcConnectionrec::STOPPED;
4990     return;
4991     break;
4992   case Fragrecord::FREE:
4993     jam();
4994   case Fragrecord::DEFINED:
4995     jam();
4996   case Fragrecord::REMOVING:
4997     jam();
4998   default:
4999     ndbrequire(false);
5000     break;
5001   }//switch
5002   return;
5003 }//Dblqh::endgettupkeyLab()
5004 
prepareContinueAfterBlockedLab(Signal * signal)5005 void Dblqh::prepareContinueAfterBlockedLab(Signal* signal)
5006 {
5007   UintR ttcScanOp;
5008 
5009 /* -------------------------------------------------------------------------- */
5010 /*       INPUT:          TC_CONNECTPTR           ACTIVE CONNECTION RECORD     */
5011 /*                       FRAGPTR                 FRAGMENT RECORD              */
5012 /* -------------------------------------------------------------------------- */
5013 /* -------------------------------------------------------------------------- */
5014 /*  CONTINUE HERE AFTER BEING BLOCKED FOR A WHILE DURING LOCAL CHECKPOINT.    */
5015 /* -------------------------------------------------------------------------- */
5016 /*       ALSO AFTER NORMAL PROCEDURE WE CONTINUE HERE                         */
5017 /* -------------------------------------------------------------------------- */
5018   Uint32 tc_ptr_i = tcConnectptr.i;
5019   TcConnectionrec * const regTcPtr = tcConnectptr.p;
5020   Uint32 activeCreat = regTcPtr->activeCreat;
5021   if (regTcPtr->operation == ZUNLOCK)
5022   {
5023     jam();
5024     handleUserUnlockRequest(signal);
5025     return;
5026   }
5027 
5028   if (regTcPtr->indTakeOver == ZTRUE) {
5029     jam();
5030     ttcScanOp = KeyInfo20::getScanOp(regTcPtr->tcScanInfo);
5031     scanptr.i = RNIL;
5032     {
5033       ScanRecord key;
5034       key.scanNumber = KeyInfo20::getScanNo(regTcPtr->tcScanInfo);
5035       key.fragPtrI = fragptr.i;
5036       c_scanTakeOverHash.find(scanptr, key);
5037 #ifdef TRACE_SCAN_TAKEOVER
5038       if(scanptr.i == RNIL)
5039 	ndbout_c("not finding (%d %d)", key.scanNumber, key.fragPtrI);
5040 #endif
5041     }
5042     if (scanptr.i == RNIL) {
5043       jam();
5044       takeOverErrorLab(signal);
5045       return;
5046     }//if
5047     Uint32 accOpPtr= get_acc_ptr_from_scan_record(scanptr.p,
5048                                                   ttcScanOp,
5049                                                   true);
5050     if (accOpPtr == RNIL) {
5051       jam();
5052       takeOverErrorLab(signal);
5053       return;
5054     }//if
5055     signal->theData[1] = accOpPtr;
5056     signal->theData[2] = regTcPtr->transid[0];
5057     signal->theData[3] = regTcPtr->transid[1];
5058     EXECUTE_DIRECT(refToMain(regTcPtr->tcAccBlockref), GSN_ACC_TO_REQ,
5059 		   signal, 4);
5060     if (signal->theData[0] == (UintR)-1) {
5061       execACC_TO_REF(signal);
5062       return;
5063     }//if
5064     jamEntry();
5065   }//if
5066 /*-------------------------------------------------------------------*/
5067 /*       IT IS NOW TIME TO CONTACT ACC. THE TUPLE KEY WILL BE SENT   */
5068 /*       AND THIS WILL BE TRANSLATED INTO A LOCAL KEY BY USING THE   */
5069 /*       LOCAL PART OF THE LH3-ALGORITHM. ALSO PROPER LOCKS ON THE   */
5070 /*       TUPLE WILL BE SET. FOR INSERTS AND DELETES THE MESSAGE WILL */
5071 /*       START AN INSERT/DELETE INTO THE HASH TABLE.                 */
5072 /*                                                                   */
5073 /*       BEFORE SENDING THE MESSAGE THE REQUEST INFORMATION IS SET   */
5074 /*       PROPERLY.                                                   */
5075 /* ----------------------------------------------------------------- */
5076   if (TRACENR_FLAG)
5077   {
5078     TRACE_OP(regTcPtr, "RECEIVED");
5079     switch (regTcPtr->operation) {
5080     case ZREAD: TRACENR("READ"); break;
5081     case ZUPDATE: TRACENR("UPDATE"); break;
5082     case ZWRITE: TRACENR("WRITE"); break;
5083     case ZINSERT: TRACENR("INSERT"); break;
5084     case ZDELETE: TRACENR("DELETE"); break;
5085     case ZUNLOCK: TRACENR("UNLOCK"); break;
5086     case ZREFRESH: TRACENR("REFRESH"); break;
5087     default: TRACENR("<Unknown: " << regTcPtr->operation << ">"); break;
5088     }
5089 
5090     TRACENR(" tab: " << regTcPtr->tableref
5091 	   << " frag: " << regTcPtr->fragmentid
5092 	   << " activeCreat: " << (Uint32)activeCreat);
5093     if (LqhKeyReq::getNrCopyFlag(regTcPtr->reqinfo))
5094       TRACENR(" NrCopy");
5095     if (LqhKeyReq::getRowidFlag(regTcPtr->reqinfo))
5096       TRACENR(" rowid: " << regTcPtr->m_row_id);
5097     TRACENR(" key: " << getKeyInfoWordOrZero(regTcPtr, 0));
5098   }
5099 
5100   if (likely(activeCreat == Fragrecord::AC_NORMAL))
5101   {
5102     if (TRACENR_FLAG)
5103       TRACENR(endl);
5104     ndbassert(!LqhKeyReq::getNrCopyFlag(regTcPtr->reqinfo));
5105     exec_acckeyreq(signal, tcConnectptr);
5106   }
5107   else if (activeCreat == Fragrecord::AC_NR_COPY)
5108   {
5109     regTcPtr->totSendlenAi = regTcPtr->totReclenAi;
5110     handle_nr_copy(signal, tcConnectptr);
5111   }
5112   else
5113   {
5114     ndbassert(activeCreat == Fragrecord::AC_IGNORED);
5115     if (TRACENR_FLAG)
5116       TRACENR(" IGNORING (activeCreat == 2)" << endl);
5117 
5118     signal->theData[0] = tc_ptr_i;
5119     regTcPtr->transactionState = TcConnectionrec::WAIT_ACC_ABORT;
5120 
5121     signal->theData[0] = regTcPtr->tupConnectrec;
5122     EXECUTE_DIRECT(DBTUP, GSN_TUP_ABORTREQ, signal, 1);
5123     jamEntry();
5124 
5125     regTcPtr->totSendlenAi = regTcPtr->totReclenAi;
5126     packLqhkeyreqLab(signal);
5127   }
5128 }
5129 
5130 void
exec_acckeyreq(Signal * signal,TcConnectionrecPtr regTcPtr)5131 Dblqh::exec_acckeyreq(Signal* signal, TcConnectionrecPtr regTcPtr)
5132 {
5133   Uint32 taccreq;
5134   regTcPtr.p->transactionState = TcConnectionrec::WAIT_ACC;
5135   taccreq = regTcPtr.p->operation;
5136   taccreq = taccreq + (regTcPtr.p->lockType << 4);
5137   taccreq = taccreq + (regTcPtr.p->dirtyOp << 6);
5138   taccreq = taccreq + (regTcPtr.p->replicaType << 7);
5139   taccreq = taccreq + (regTcPtr.p->apiVersionNo << 9);
5140 /* ************ */
5141 /*  ACCKEYREQ < */
5142 /* ************ */
5143   Uint32 sig0, sig1, sig2, sig3, sig4;
5144   sig0 = regTcPtr.p->accConnectrec;
5145   sig1 = fragptr.p->accFragptr;
5146   sig2 = regTcPtr.p->hashValue;
5147   sig3 = regTcPtr.p->primKeyLen;
5148   sig4 = regTcPtr.p->transid[0];
5149   signal->theData[0] = sig0;
5150   signal->theData[1] = sig1;
5151   signal->theData[2] = taccreq;
5152   signal->theData[3] = sig2;
5153   signal->theData[4] = sig3;
5154   signal->theData[5] = sig4;
5155 
5156   sig0 = regTcPtr.p->transid[1];
5157   signal->theData[6] = sig0;
5158 
5159   /* Copy KeyInfo to end of ACCKEYREQ signal, starting at offset 7 */
5160   sendKeyinfoAcc(signal, 7);
5161 
5162   TRACE_OP(regTcPtr.p, "ACC");
5163 
5164   EXECUTE_DIRECT(refToMain(regTcPtr.p->tcAccBlockref), GSN_ACCKEYREQ,
5165 		 signal, 7 + regTcPtr.p->primKeyLen);
5166   if (signal->theData[0] < RNIL) {
5167     signal->theData[0] = regTcPtr.i;
5168     execACCKEYCONF(signal);
5169     return;
5170   } else if (signal->theData[0] == RNIL) {
5171     ;
5172   } else {
5173     ndbrequire(signal->theData[0] == (UintR)-1);
5174     signal->theData[0] = regTcPtr.i;
5175     execACCKEYREF(signal);
5176   }//if
5177   return;
5178 }//Dblqh::prepareContinueAfterBlockedLab()
5179 
5180 void
handle_nr_copy(Signal * signal,Ptr<TcConnectionrec> regTcPtr)5181 Dblqh::handle_nr_copy(Signal* signal, Ptr<TcConnectionrec> regTcPtr)
5182 {
5183   jam();
5184   Uint32 fragPtr = fragptr.p->tupFragptr;
5185   Uint32 op = regTcPtr.p->operation;
5186 
5187   const bool copy = LqhKeyReq::getNrCopyFlag(regTcPtr.p->reqinfo);
5188 
5189   if (!LqhKeyReq::getRowidFlag(regTcPtr.p->reqinfo))
5190   {
5191     /**
5192      * Rowid not set, that mean that primary has finished copying...
5193      */
5194     jam();
5195     if (TRACENR_FLAG)
5196       TRACENR(" Waiting for COPY_ACTIVEREQ" << endl);
5197     ndbassert(!LqhKeyReq::getNrCopyFlag(regTcPtr.p->reqinfo));
5198     regTcPtr.p->activeCreat = Fragrecord::AC_NORMAL;
5199     exec_acckeyreq(signal, regTcPtr);
5200     return;
5201   }
5202 
5203   regTcPtr.p->m_nr_delete.m_cnt = 1; // Wait for real op aswell
5204   Uint32* dst = signal->theData+24;
5205   bool uncommitted;
5206   const int len = c_tup->nr_read_pk(fragPtr, &regTcPtr.p->m_row_id, dst,
5207 				    uncommitted);
5208   const bool match = (len>0) ? compare_key(regTcPtr.p, dst, len) == 0 : false;
5209 
5210   if (TRACENR_FLAG)
5211     TRACENR(" len: " << len << " match: " << match
5212 	   << " uncommitted: " << uncommitted);
5213 
5214   if (copy)
5215   {
5216     ndbassert(LqhKeyReq::getGCIFlag(regTcPtr.p->reqinfo));
5217     if (match)
5218     {
5219       /**
5220        * Case 1
5221        */
5222       jam();
5223       ndbassert(op == ZINSERT);
5224       if (TRACENR_FLAG)
5225 	TRACENR(" Changing from INSERT to ZUPDATE" << endl);
5226       regTcPtr.p->operation = ZUPDATE;
5227       goto run;
5228     }
5229     else if (len > 0 && op == ZDELETE)
5230     {
5231       /**
5232        * Case 4
5233        *   Perform delete using rowid
5234        *     primKeyLen == 0
5235        *     key[0] == rowid
5236        */
5237       jam();
5238       ndbassert(regTcPtr.p->primKeyLen == 0);
5239       if (TRACENR_FLAG)
5240 	TRACENR(" performing DELETE key: "
5241 	       << dst[0] << endl);
5242 
5243       nr_copy_delete_row(signal, regTcPtr, &regTcPtr.p->m_row_id, len);
5244       ndbassert(regTcPtr.p->m_nr_delete.m_cnt);
5245       regTcPtr.p->m_nr_delete.m_cnt--; // No real op is run
5246       if (regTcPtr.p->m_nr_delete.m_cnt)
5247       {
5248 	jam();
5249 	return;
5250       }
5251       packLqhkeyreqLab(signal);
5252       return;
5253     }
5254     else if (len == 0 && op == ZDELETE)
5255     {
5256       /**
5257        * Case 7
5258        */
5259       jam();
5260       if (TRACENR_FLAG)
5261 	TRACENR(" UPDATE_GCI" << endl);
5262       c_tup->nr_update_gci(fragPtr, &regTcPtr.p->m_row_id, regTcPtr.p->gci_hi);
5263       goto update_gci_ignore;
5264     }
5265 
5266     /**
5267      * 1) Delete row at specified rowid (if len > 0)
5268      * 2) Delete specified row at different rowid (if exists)
5269      * 3) Run insert
5270      */
5271     if (len > 0)
5272     {
5273       /**
5274        * 1) Delete row at specified rowid (if len > 0)
5275        */
5276       jam();
5277       nr_copy_delete_row(signal, regTcPtr, &regTcPtr.p->m_row_id, len);
5278     }
5279     /**
5280      * 2) Delete specified row at different rowid (if exists)
5281      */
5282     jam();
5283     nr_copy_delete_row(signal, regTcPtr, 0, 0);
5284     if (TRACENR_FLAG)
5285       TRACENR(" RUN INSERT" << endl);
5286     goto run;
5287   }
5288   else
5289   {
5290     if (!match && op != ZINSERT)
5291     {
5292       jam();
5293       if (TRACENR_FLAG)
5294 	TRACENR(" IGNORE " << endl);
5295       goto ignore;
5296     }
5297     if (match)
5298     {
5299       jam();
5300       if (op != ZDELETE && op != ZREFRESH)
5301       {
5302 	if (TRACENR_FLAG)
5303 	  TRACENR(" Changing from INSERT/UPDATE to ZWRITE" << endl);
5304 	regTcPtr.p->operation = ZWRITE;
5305       }
5306       goto run;
5307     }
5308 
5309     ndbassert(!match && op == ZINSERT);
5310 
5311     /**
5312      * 1) Delete row at specified rowid (if len > 0)
5313      * 2) Delete specified row at different rowid (if exists)
5314      * 3) Run insert
5315      */
5316     if (len > 0)
5317     {
5318       /**
5319        * 1) Delete row at specified rowid (if len > 0)
5320        */
5321       jam();
5322       nr_copy_delete_row(signal, regTcPtr, &regTcPtr.p->m_row_id, len);
5323     }
5324 
5325     /**
5326      * 2) Delete specified row at different rowid (if exists)
5327      */
5328     jam();
5329     nr_copy_delete_row(signal, regTcPtr, 0, 0);
5330     if (TRACENR_FLAG)
5331       TRACENR(" RUN op: " << op << endl);
5332     goto run;
5333   }
5334 
5335 run:
5336   jam();
5337   exec_acckeyreq(signal, regTcPtr);
5338   return;
5339 
5340 ignore:
5341   jam();
5342   ndbassert(!LqhKeyReq::getNrCopyFlag(regTcPtr.p->reqinfo));
5343 update_gci_ignore:
5344   regTcPtr.p->activeCreat = Fragrecord::AC_IGNORED;
5345   signal->theData[0] = regTcPtr.p->tupConnectrec;
5346   EXECUTE_DIRECT(DBTUP, GSN_TUP_ABORTREQ, signal, 1);
5347 
5348   packLqhkeyreqLab(signal);
5349 }
5350 
5351 /**
5352  * Compare received key data with the data supplied
5353  * returning 0 if they are the same, 1 otherwise
5354  */
5355 int
compare_key(const TcConnectionrec * regTcPtr,const Uint32 * ptr,Uint32 len)5356 Dblqh::compare_key(const TcConnectionrec* regTcPtr,
5357 		   const Uint32 * ptr, Uint32 len)
5358 {
5359   if (regTcPtr->primKeyLen != len)
5360     return 1;
5361 
5362   ndbassert( regTcPtr->keyInfoIVal != RNIL );
5363 
5364   SectionReader keyInfoReader(regTcPtr->keyInfoIVal,
5365                               getSectionSegmentPool());
5366 
5367   ndbassert(regTcPtr->primKeyLen == keyInfoReader.getSize());
5368 
5369   while (len != 0)
5370   {
5371     const Uint32* keyChunk= NULL;
5372     Uint32 chunkSize= 0;
5373 
5374     /* Get a ptr to a chunk of contiguous words to compare */
5375     bool ok= keyInfoReader.getWordsPtr(len, keyChunk, chunkSize);
5376 
5377     ndbrequire(ok);
5378 
5379     if ( memcmp(ptr, keyChunk, chunkSize << 2))
5380       return 1;
5381 
5382     ptr+= chunkSize;
5383     len-= chunkSize;
5384   }
5385 
5386   return 0;
5387 }
5388 
5389 void
nr_copy_delete_row(Signal * signal,Ptr<TcConnectionrec> regTcPtr,Local_key * rowid,Uint32 len)5390 Dblqh::nr_copy_delete_row(Signal* signal,
5391 			  Ptr<TcConnectionrec> regTcPtr,
5392 			  Local_key* rowid, Uint32 len)
5393 {
5394   Ptr<Fragrecord> fragPtr = fragptr;
5395 
5396   Uint32 keylen;
5397   Uint32 tableId = regTcPtr.p->tableref;
5398   Uint32 accPtr = regTcPtr.p->accConnectrec;
5399 
5400   signal->theData[0] = accPtr;
5401   signal->theData[1] = fragptr.p->accFragptr;
5402   signal->theData[2] = ZDELETE + (ZDELETE << 4);
5403   signal->theData[5] = regTcPtr.p->transid[0];
5404   signal->theData[6] = regTcPtr.p->transid[1];
5405 
5406   if (rowid)
5407   {
5408     jam();
5409     keylen = 2;
5410     if (g_key_descriptor_pool.getPtr(tableId)->hasCharAttr)
5411     {
5412       signal->theData[3] = calculateHash(tableId, signal->theData+24);
5413     }
5414     else
5415     {
5416       signal->theData[3] = md5_hash((Uint64*)(signal->theData+24), len);
5417     }
5418     signal->theData[4] = 0; // seach by local key
5419     signal->theData[7] = rowid->m_page_no;
5420     signal->theData[8] = rowid->m_page_idx;
5421   }
5422   else
5423   {
5424     jam();
5425     keylen = regTcPtr.p->primKeyLen;
5426     signal->theData[3] = regTcPtr.p->hashValue;
5427     signal->theData[4] = keylen;
5428 
5429     /* Copy KeyInfo inline into the ACCKEYREQ signal,
5430      * starting at word 7
5431      */
5432     sendKeyinfoAcc(signal, 7);
5433   }
5434   const Uint32 ref = refToMain(regTcPtr.p->tcAccBlockref);
5435   EXECUTE_DIRECT(ref, GSN_ACCKEYREQ, signal, 7 + keylen);
5436   jamEntry();
5437 
5438   Uint32 retValue = signal->theData[0];
5439   ndbrequire(retValue != RNIL); // This should never block...
5440   ndbrequire(retValue != (Uint32)-1 || rowid == 0); // rowid should never fail
5441 
5442   if (retValue == (Uint32)-1)
5443   {
5444     /**
5445      * Only delete by pk, may fail
5446      */
5447     jam();
5448     ndbrequire(rowid == 0);
5449     signal->theData[0] = accPtr;
5450     signal->theData[1] = 0;
5451     EXECUTE_DIRECT(ref, GSN_ACC_ABORTREQ, signal, 2);
5452     jamEntry();
5453     return;
5454   }
5455 
5456   /**
5457    * We found row (and have it locked in ACC)
5458    */
5459   ndbrequire(regTcPtr.p->m_dealloc == 0);
5460   Local_key save = regTcPtr.p->m_row_id;
5461 
5462   c_acc->execACCKEY_ORD(signal, accPtr);
5463   signal->theData[0] = accPtr;
5464   EXECUTE_DIRECT(ref, GSN_ACC_COMMITREQ, signal, 1);
5465   jamEntry();
5466 
5467   ndbrequire(regTcPtr.p->m_dealloc == 1);
5468   int ret = c_tup->nr_delete(signal, regTcPtr.i,
5469 			     fragPtr.p->tupFragptr, &regTcPtr.p->m_row_id,
5470 			     regTcPtr.p->gci_hi);
5471   jamEntry();
5472 
5473   if (ret)
5474   {
5475     ndbassert(ret == 1);
5476     Uint32 pos = regTcPtr.p->m_nr_delete.m_cnt - 1;
5477     memcpy(regTcPtr.p->m_nr_delete.m_disk_ref + pos,
5478 	   signal->theData, sizeof(Local_key));
5479     regTcPtr.p->m_nr_delete.m_page_id[pos] = RNIL;
5480     regTcPtr.p->m_nr_delete.m_cnt = pos + 2;
5481     if (0) ndbout << "PENDING DISK DELETE: " <<
5482       regTcPtr.p->m_nr_delete.m_disk_ref[pos] << endl;
5483   }
5484 
5485   TRACENR("DELETED: " << regTcPtr.p->m_row_id << endl);
5486 
5487   regTcPtr.p->m_dealloc = 0;
5488   regTcPtr.p->m_row_id = save;
5489   fragptr = fragPtr;
5490   tcConnectptr = regTcPtr;
5491 }
5492 
5493 void
get_nr_op_info(Nr_op_info * op,Uint32 page_id)5494 Dblqh::get_nr_op_info(Nr_op_info* op, Uint32 page_id)
5495 {
5496   Ptr<TcConnectionrec> tcPtr;
5497   tcPtr.i = op->m_ptr_i;
5498   ptrCheckGuard(tcPtr, ctcConnectrecFileSize, tcConnectionrec);
5499 
5500   Ptr<Fragrecord> fragPtr;
5501   c_fragment_pool.getPtr(fragPtr, tcPtr.p->fragmentptr);
5502 
5503   op->m_gci_hi = tcPtr.p->gci_hi;
5504   op->m_gci_lo = tcPtr.p->gci_lo;
5505   op->m_tup_frag_ptr_i = fragPtr.p->tupFragptr;
5506 
5507   ndbrequire(tcPtr.p->activeCreat == Fragrecord::AC_NR_COPY);
5508   ndbrequire(tcPtr.p->m_nr_delete.m_cnt);
5509 
5510 
5511   if (page_id == RNIL)
5512   {
5513     // get log buffer callback
5514     for (Uint32 i = 0; i<2; i++)
5515     {
5516       if (tcPtr.p->m_nr_delete.m_page_id[i] != RNIL)
5517       {
5518 	op->m_page_id = tcPtr.p->m_nr_delete.m_page_id[i];
5519 	op->m_disk_ref = tcPtr.p->m_nr_delete.m_disk_ref[i];
5520 	return;
5521       }
5522     }
5523   }
5524   else
5525   {
5526     // get page callback
5527     for (Uint32 i = 0; i<2; i++)
5528     {
5529       Local_key key = tcPtr.p->m_nr_delete.m_disk_ref[i];
5530       if (op->m_disk_ref.m_page_no == key.m_page_no &&
5531 	  op->m_disk_ref.m_file_no == key.m_file_no &&
5532 	  tcPtr.p->m_nr_delete.m_page_id[i] == RNIL)
5533       {
5534 	op->m_disk_ref = key;
5535 	tcPtr.p->m_nr_delete.m_page_id[i] = page_id;
5536 	return;
5537       }
5538     }
5539   }
5540   ndbrequire(false);
5541 }
5542 
5543 void
nr_delete_complete(Signal * signal,Nr_op_info * op)5544 Dblqh::nr_delete_complete(Signal* signal, Nr_op_info* op)
5545 {
5546   jamEntry();
5547   Ptr<TcConnectionrec> tcPtr;
5548   tcPtr.i = op->m_ptr_i;
5549   ptrCheckGuard(tcPtr, ctcConnectrecFileSize, tcConnectionrec);
5550 
5551   ndbrequire(tcPtr.p->activeCreat == Fragrecord::AC_NR_COPY);
5552   ndbrequire(tcPtr.p->m_nr_delete.m_cnt);
5553 
5554   tcPtr.p->m_nr_delete.m_cnt--;
5555   if (tcPtr.p->m_nr_delete.m_cnt == 0)
5556   {
5557     jam();
5558     tcConnectptr = tcPtr;
5559     c_fragment_pool.getPtr(fragptr, tcPtr.p->fragmentptr);
5560 
5561     if (tcPtr.p->abortState != TcConnectionrec::ABORT_IDLE)
5562     {
5563       jam();
5564       tcPtr.p->activeCreat = Fragrecord::AC_NORMAL;
5565       abortCommonLab(signal);
5566     }
5567     else if (tcPtr.p->operation == ZDELETE &&
5568 	     LqhKeyReq::getNrCopyFlag(tcPtr.p->reqinfo))
5569     {
5570       /**
5571        * This is run directly in handle_nr_copy
5572        */
5573       jam();
5574       packLqhkeyreqLab(signal);
5575     }
5576     else
5577     {
5578       jam();
5579       rwConcludedLab(signal);
5580     }
5581     return;
5582   }
5583 
5584   if (memcmp(&tcPtr.p->m_nr_delete.m_disk_ref[0],
5585 	     &op->m_disk_ref, sizeof(Local_key)) == 0)
5586   {
5587     jam();
5588     ndbassert(tcPtr.p->m_nr_delete.m_page_id[0] != RNIL);
5589     tcPtr.p->m_nr_delete.m_page_id[0] = tcPtr.p->m_nr_delete.m_page_id[1];
5590     tcPtr.p->m_nr_delete.m_disk_ref[0] = tcPtr.p->m_nr_delete.m_disk_ref[1];
5591   }
5592 }
5593 
5594 Uint32
readPrimaryKeys(Uint32 opPtrI,Uint32 * dst,bool xfrm)5595 Dblqh::readPrimaryKeys(Uint32 opPtrI, Uint32 * dst, bool xfrm)
5596 {
5597   TcConnectionrecPtr regTcPtr;
5598   Uint64 Tmp[MAX_KEY_SIZE_IN_WORDS >> 1];
5599 
5600   jamEntry();
5601   regTcPtr.i = opPtrI;
5602   ptrCheckGuard(regTcPtr, ctcConnectrecFileSize, tcConnectionrec);
5603 
5604   Uint32 tableId = regTcPtr.p->tableref;
5605   Uint32 keyLen = regTcPtr.p->primKeyLen;
5606   Uint32 * tmp = xfrm ? (Uint32*)Tmp : dst;
5607 
5608   copy(tmp, regTcPtr.p->keyInfoIVal);
5609 
5610   if (xfrm)
5611   {
5612     jam();
5613     Uint32 keyPartLen[MAX_ATTRIBUTES_IN_INDEX];
5614     return xfrm_key(tableId, (Uint32*)Tmp, dst, ~0, keyPartLen);
5615   }
5616 
5617   return keyLen;
5618 }
5619 
5620 /**
5621  * getKeyInfoWordOrZero
5622  * Get given word of KeyInfo, or zero if it's not available
5623  * Used for tracing
5624  */
5625 Uint32
getKeyInfoWordOrZero(const TcConnectionrec * regTcPtr,Uint32 offset)5626 Dblqh::getKeyInfoWordOrZero(const TcConnectionrec* regTcPtr,
5627                             Uint32 offset)
5628 {
5629   if (regTcPtr->keyInfoIVal != RNIL)
5630   {
5631     SectionReader keyInfoReader(regTcPtr->keyInfoIVal,
5632                                 g_sectionSegmentPool);
5633 
5634     if (keyInfoReader.getSize() > offset)
5635     {
5636       if (offset)
5637         keyInfoReader.step(offset);
5638 
5639       Uint32 word;
5640       keyInfoReader.getWord(&word);
5641       return word;
5642     }
5643   }
5644   return 0;
5645 }
5646 
unlockError(Signal * signal,Uint32 error)5647 void Dblqh::unlockError(Signal* signal, Uint32 error)
5648 {
5649   terrorCode = error;
5650   abortErrorLab(signal);
5651 }
5652 
5653 /**
5654  * handleUserUnlockRequest
5655  *
5656  * This method handles an LQHKEYREQ unlock request from
5657  * TC.
5658  */
handleUserUnlockRequest(Signal * signal)5659 void Dblqh::handleUserUnlockRequest(Signal* signal)
5660 {
5661   jam();
5662   TcConnectionrec * const regTcPtr = tcConnectptr.p;
5663   Uint32 tcPtrI = tcConnectptr.i;
5664 
5665   /* Request to unlock (abort) an existing read operation
5666    *
5667    * 1) Get user's LOCK_REF from KeyInfo
5668    *
5669    * 2) Lookup TC_OP_REF in hash
5670    *
5671    * 3) Check state of found op : TransId, state, type, lock
5672    *
5673    * 4) Check op_id portion
5674    *
5675    * 5) Abort locking op in ACC
5676    *
5677    * 6) Clean up locking op in LQH
5678    *
5679    * 7) Send LQHKEYCONF to TC for user unlock op
5680    *
5681    * 8) Clean up user unlock op
5682    */
5683   if (unlikely( regTcPtr->primKeyLen != LqhKeyReq::UnlockKeyLen ))
5684   {
5685     jam();
5686     unlockError(signal, 4109); /* Faulty primary key attribute length */
5687     return;
5688   }
5689 
5690   SectionReader keyInfoReader(regTcPtr->keyInfoIVal,
5691                               getSectionSegmentPool());
5692 
5693   ndbrequire( keyInfoReader.getSize() == regTcPtr->primKeyLen );
5694 
5695   /* Extract components of user lock reference */
5696   Uint32 tcOpRecIndex;
5697   Uint32 lqhOpIdWord;
5698   ndbrequire( keyInfoReader.getWord( &tcOpRecIndex ) ); // Locking op TC index
5699   ndbrequire( keyInfoReader.getWord( &lqhOpIdWord ) );  // Part of Locking op LQH id
5700 
5701   /* Use TC operation record index to find the operation record
5702    * This requires that this operation and the referenced
5703    * operation are part of the same transaction.
5704    * On success this sets tcConnectptr.i and .p to the
5705    * operation-to-unlock's record.
5706    */
5707   if (unlikely( findTransaction(regTcPtr->transid[0],
5708                                 regTcPtr->transid[1],
5709                                 tcOpRecIndex,
5710                                 0) != ZOK))
5711   {
5712     jam();
5713     unlockError(signal, ZBAD_OP_REF);
5714     return;
5715   }
5716 
5717   TcConnectionrec * const regLockTcPtr = tcConnectptr.p;
5718 
5719   /* Validate that the bottom 32-bits of the operation id reference
5720    * we were given are in alignment
5721    */
5722   Uint32 lockOpKeyReqId = (Uint32) regLockTcPtr->lqhKeyReqId;
5723   if (unlikely( lockOpKeyReqId != lqhOpIdWord ))
5724   {
5725     jam();
5726     unlockError(signal, ZBAD_OP_REF);
5727     return;
5728   }
5729 
5730   /* Validate the state of the locking operation */
5731   bool lockingOpValid =
5732     (( regLockTcPtr->operation == ZREAD ) &&
5733        // ZREAD_EX mapped to ZREAD above
5734      ( ! regLockTcPtr->dirtyOp ) &&
5735      ( ! regLockTcPtr->opSimple ) &&
5736      ( (regLockTcPtr->lockType == ZREAD) ||  // LM_Read
5737        (regLockTcPtr->lockType == ZUPDATE) ) // LM_Exclusive
5738      &&
5739      ( regLockTcPtr->transactionState == TcConnectionrec::PREPARED ) &&
5740      ( regLockTcPtr->commitAckMarker == RNIL ) &&
5741        // No commit ack marker
5742      ( regLockTcPtr->logWriteState ==
5743        TcConnectionrec::NOT_STARTED )); // No log written
5744 
5745   if (unlikely(! lockingOpValid))
5746   {
5747     jam();
5748     unlockError(signal, ZBAD_UNLOCK_STATE);
5749     return;
5750   }
5751 
5752   /* Ok, now we're ready to start 'aborting' this operation, to get the
5753    * effect of unlocking it
5754    */
5755   signal->theData[0] = regLockTcPtr->accConnectrec;
5756   signal->theData[1] = 0; // For Execute_Direct
5757   EXECUTE_DIRECT(refToMain(regLockTcPtr->tcAccBlockref),
5758                  GSN_ACC_ABORTREQ,
5759                  signal,
5760                  2);
5761   jamEntry();
5762 
5763   /* Would be nice to handle non-success case somehow */
5764   ndbrequire(signal->theData[1] == 0);
5765 
5766   /* Now we want to release LQH resources associated with the
5767    * locking operation
5768    */
5769   cleanUp(signal);
5770 
5771   /* Now that the locking operation has been 'disappeared', we need to
5772    * send an LQHKEYCONF for the unlock operation and then 'disappear' it
5773    * as well
5774    */
5775   tcConnectptr.i = tcPtrI;
5776   ptrCheckGuard(tcConnectptr, ctcConnectrecFileSize, tcConnectionrec);
5777 
5778   ndbrequire( regTcPtr == tcConnectptr.p );
5779 
5780   /* Set readlenAi to the unlocked operation's TC operation ref */
5781   regTcPtr->readlenAi = tcOpRecIndex;
5782 
5783   /* Clear number of fired triggers */
5784   regTcPtr->noFiredTriggers = 0;
5785 
5786   /* Now send the LQHKEYCONF to TC */
5787   sendLqhkeyconfTc(signal, regTcPtr->tcBlockref);
5788 
5789   /* Finally, clean up the unlock operation itself */
5790   cleanUp(signal);
5791 
5792   return;
5793 }
5794 
5795 /* =*======================================================================= */
5796 /* =======                 SEND KEYINFO TO ACC                       ======= */
5797 /*                                                                           */
5798 /* ========================================================================= */
sendKeyinfoAcc(Signal * signal,Uint32 Ti)5799 void Dblqh::sendKeyinfoAcc(Signal* signal, Uint32 Ti)
5800 {
5801   /* Copy all KeyInfo into the signal at offset Ti */
5802   copy(&signal->theData[Ti],
5803        tcConnectptr.p->keyInfoIVal);
5804 }//Dblqh::sendKeyinfoAcc()
5805 
execLQH_ALLOCREQ(Signal * signal)5806 void Dblqh::execLQH_ALLOCREQ(Signal* signal)
5807 {
5808   TcConnectionrecPtr regTcPtr;
5809   FragrecordPtr regFragptr;
5810 
5811   jamEntry();
5812   regTcPtr.i = signal->theData[0];
5813   ptrCheckGuard(regTcPtr, ctcConnectrecFileSize, tcConnectionrec);
5814 
5815   regFragptr.i = regTcPtr.p->fragmentptr;
5816   c_fragment_pool.getPtr(regFragptr);
5817 
5818   signal->theData[0] = regTcPtr.p->tupConnectrec;
5819   signal->theData[1] = regFragptr.p->tupFragptr;
5820   signal->theData[2] = regTcPtr.p->tableref;
5821   Uint32 tup = refToMain(regTcPtr.p->tcTupBlockref);
5822   EXECUTE_DIRECT(tup, GSN_TUP_ALLOCREQ, signal, 3);
5823 }//Dblqh::execTUP_ALLOCREQ()
5824 
execTUP_DEALLOCREQ(Signal * signal)5825 void Dblqh::execTUP_DEALLOCREQ(Signal* signal)
5826 {
5827   TcConnectionrecPtr regTcPtr;
5828 
5829   jamEntry();
5830   regTcPtr.i = signal->theData[4];
5831 
5832   if (TRACENR_FLAG)
5833   {
5834     Local_key tmp;
5835     tmp.m_page_no = signal->theData[2];
5836     tmp.m_page_idx = signal->theData[3];
5837     TRACENR("TUP_DEALLOC: " << tmp <<
5838       (signal->theData[5] ? " DIRECT " : " DELAYED") << endl);
5839   }
5840 
5841   if (signal->theData[5])
5842   {
5843     jam();
5844     Local_key tmp;
5845 
5846     tmp.m_page_no = signal->theData[2];
5847     tmp.m_page_idx = signal->theData[3];
5848 
5849     if (ERROR_INSERTED(5712))
5850     {
5851       ndbout << "TUP_DEALLOC: " << tmp << endl;
5852     }
5853 
5854     EXECUTE_DIRECT(DBTUP, GSN_TUP_DEALLOCREQ, signal, signal->getLength());
5855     return;
5856   }
5857   else
5858   {
5859     jam();
5860     ptrCheckGuard(regTcPtr, ctcConnectrecFileSize, tcConnectionrec);
5861     regTcPtr.p->m_row_id.m_page_no = signal->theData[2];
5862     regTcPtr.p->m_row_id.m_page_idx = signal->theData[3];
5863 
5864     TRACE_OP(regTcPtr.p, "SET DEALLOC");
5865 
5866     ndbrequire(regTcPtr.p->m_dealloc == 0);
5867     regTcPtr.p->m_dealloc = 1;
5868   }
5869 }//Dblqh::execTUP_ALLOCREQ()
5870 
5871 /* ************>> */
5872 /*  ACCKEYCONF  > */
5873 /* ************>> */
execACCKEYCONF(Signal * signal)5874 void Dblqh::execACCKEYCONF(Signal* signal)
5875 {
5876   TcConnectionrec *regTcConnectionrec = tcConnectionrec;
5877   Uint32 ttcConnectrecFileSize = ctcConnectrecFileSize;
5878   Uint32 tcIndex = signal->theData[0];
5879   Uint32 localKey1 = signal->theData[3];
5880   Uint32 localKey2 = signal->theData[4];
5881   jamEntry();
5882 
5883   tcConnectptr.i = tcIndex;
5884   ptrCheckGuard(tcConnectptr, ttcConnectrecFileSize, regTcConnectionrec);
5885   TcConnectionrec * const regTcPtr = tcConnectptr.p;
5886   if (regTcPtr->transactionState != TcConnectionrec::WAIT_ACC) {
5887     LQHKEY_abort(signal, 3);
5888     return;
5889   }//if
5890 
5891   /* ------------------------------------------------------------------------
5892    * IT IS NOW TIME TO CONTACT THE TUPLE MANAGER. THE TUPLE MANAGER NEEDS THE
5893    * INFORMATION ON WHICH TABLE AND FRAGMENT, THE LOCAL KEY AND IT NEEDS TO
5894    * KNOW THE TYPE OF OPERATION TO PERFORM. TUP CAN SEND THE ATTRINFO DATA
5895    * EITHER TO THE TC BLOCK OR DIRECTLY TO THE APPLICATION. THE SCHEMA VERSION
5896    * IS NEEDED SINCE TWO SCHEMA VERSIONS CAN BE ACTIVE SIMULTANEOUSLY ON A
5897    * TABLE.
5898    * ----------------------------------------------------------------------- */
5899   if (regTcPtr->operation == ZWRITE)
5900   {
5901     ndbassert(regTcPtr->seqNoReplica == 0 ||
5902 	      regTcPtr->activeCreat == Fragrecord::AC_NR_COPY);
5903     Uint32 op= signal->theData[1];
5904     Uint32 requestInfo = regTcPtr->reqinfo;
5905     if(likely(op == ZINSERT || op == ZUPDATE))
5906     {
5907       jam();
5908       regTcPtr->operation = op;
5909     }
5910     else
5911     {
5912       jam();
5913       warningEvent("Convering %d to ZUPDATE", op);
5914       op = regTcPtr->operation = ZUPDATE;
5915     }
5916     if (regTcPtr->seqNoReplica == 0)
5917     {
5918       jam();
5919       requestInfo &= ~(RI_OPERATION_MASK <<  RI_OPERATION_SHIFT);
5920       LqhKeyReq::setOperation(requestInfo, op);
5921       regTcPtr->reqinfo = requestInfo;
5922     }
5923   }//if
5924 
5925   /* ------------------------------------------------------------------------
5926    * IT IS NOW TIME TO CONTACT THE TUPLE MANAGER. THE TUPLE MANAGER NEEDS THE
5927    * INFORMATION ON WHICH TABLE AND FRAGMENT, THE LOCAL KEY AND IT NEEDS TO
5928    * KNOW THE TYPE OF OPERATION TO PERFORM. TUP CAN SEND THE ATTRINFO DATA
5929    * EITHER TO THE TC BLOCK OR DIRECTLY TO THE APPLICATION. THE SCHEMA VERSION
5930    * IS NEEDED SINCE TWO SCHEMA VERSIONS CAN BE ACTIVE SIMULTANEOUSLY ON A
5931    * TABLE.
5932    * ----------------------------------------------------------------------- */
5933   FragrecordPtr regFragptr;
5934   regFragptr.i = regTcPtr->fragmentptr;
5935   c_fragment_pool.getPtr(regFragptr);
5936 
5937   if(!regTcPtr->m_disk_table)
5938     acckeyconf_tupkeyreq(signal, regTcPtr, regFragptr.p,
5939                          localKey1, localKey2, RNIL);
5940   else
5941     acckeyconf_load_diskpage(signal, tcConnectptr, regFragptr.p,
5942                              localKey1, localKey2);
5943 }
5944 
5945 void
acckeyconf_tupkeyreq(Signal * signal,TcConnectionrec * regTcPtr,Fragrecord * regFragptrP,Uint32 lkey1,Uint32 lkey2,Uint32 disk_page)5946 Dblqh::acckeyconf_tupkeyreq(Signal* signal, TcConnectionrec* regTcPtr,
5947 			    Fragrecord* regFragptrP,
5948 			    Uint32 lkey1, Uint32 lkey2,
5949 			    Uint32 disk_page)
5950 {
5951   Uint32 op = regTcPtr->operation;
5952   regTcPtr->transactionState = TcConnectionrec::WAIT_TUP;
5953   /* ------------------------------------------------------------------------
5954    * IT IS NOW TIME TO CONTACT THE TUPLE MANAGER. THE TUPLE MANAGER NEEDS THE
5955    * INFORMATION ON WHICH TABLE AND FRAGMENT, THE LOCAL KEY AND IT NEEDS TO
5956    * KNOW THE TYPE OF OPERATION TO PERFORM. TUP CAN SEND THE ATTRINFO DATA
5957    * EITHER TO THE TC BLOCK OR DIRECTLY TO THE APPLICATION. THE SCHEMA VERSION
5958    * IS NEEDED SINCE TWO SCHEMA VERSIONS CAN BE ACTIVE SIMULTANEOUSLY ON A
5959    * TABLE.
5960    * ----------------------------------------------------------------------- */
5961   Uint32 page_idx = lkey2;
5962   Uint32 page_no = lkey1;
5963   Uint32 Ttupreq = regTcPtr->dirtyOp;
5964   Uint32 flags = regTcPtr->m_flags;
5965   Ttupreq = Ttupreq + (regTcPtr->opSimple << 1);
5966   Ttupreq = Ttupreq + (op << 6);
5967   Ttupreq = Ttupreq + (regTcPtr->opExec << 10);
5968   Ttupreq = Ttupreq + (regTcPtr->apiVersionNo << 11);
5969   Ttupreq = Ttupreq + (regTcPtr->m_use_rowid << 11);
5970   Ttupreq = Ttupreq + (regTcPtr->m_reorg << 12);
5971 
5972   /* ---------------------------------------------------------------------
5973    * Clear interpreted mode bit since we do not want the next replica to
5974    * use interpreted mode. The next replica will receive a normal write.
5975    * --------------------------------------------------------------------- */
5976   regTcPtr->opExec = 0;
5977   /* ************< */
5978   /*  TUPKEYREQ  < */
5979   /* ************< */
5980   Uint32 sig0, sig1, sig2, sig3;
5981   sig0 = regTcPtr->tupConnectrec;
5982 
5983   TupKeyReq * const tupKeyReq = (TupKeyReq *)signal->getDataPtrSend();
5984   tupKeyReq->connectPtr = sig0;
5985   tupKeyReq->request = Ttupreq;
5986   tupKeyReq->keyRef1 = page_no;
5987   tupKeyReq->keyRef2 = page_idx;
5988 
5989   sig0 = regTcPtr->totReclenAi;
5990   sig1 = regTcPtr->applOprec;
5991   sig2 = regTcPtr->applRef;
5992 
5993   tupKeyReq->attrBufLen = sig0;
5994   tupKeyReq->opRef = sig1;
5995   tupKeyReq->applRef = sig2;
5996 
5997   sig0 = regTcPtr->storedProcId;
5998   sig1 = regTcPtr->transid[0];
5999   sig2 = regTcPtr->transid[1];
6000   sig3 = regFragptrP->tupFragptr;
6001   Uint32 tup = refToMain(regTcPtr->tcTupBlockref);
6002 
6003   tupKeyReq->storedProcedure = sig0;
6004   tupKeyReq->transId1 = sig1;
6005   tupKeyReq->transId2 = sig2;
6006   tupKeyReq->fragPtr = sig3;
6007 
6008   sig0 = regTcPtr->m_row_id.m_page_no;
6009   sig1 = regTcPtr->m_row_id.m_page_idx;
6010 
6011   tupKeyReq->primaryReplica = (tcConnectptr.p->seqNoReplica == 0)?true:false;
6012   tupKeyReq->coordinatorTC = tcConnectptr.p->tcBlockref;
6013   tupKeyReq->tcOpIndex = tcConnectptr.p->tcOprec;
6014   tupKeyReq->savePointId = tcConnectptr.p->savePointId;
6015   tupKeyReq->disk_page= disk_page;
6016 
6017   tupKeyReq->m_row_id_page_no = sig0;
6018   tupKeyReq->m_row_id_page_idx = sig1;
6019 
6020   TRACE_OP(regTcPtr, "TUPKEYREQ");
6021 
6022   regTcPtr->m_use_rowid |= (op == ZINSERT || op == ZREFRESH);
6023   regTcPtr->m_row_id.m_page_no = page_no;
6024   regTcPtr->m_row_id.m_page_idx = page_idx;
6025 
6026   tupKeyReq->attrInfoIVal= RNIL;
6027   tupKeyReq->deferred_constraints =
6028     (flags & TcConnectionrec::OP_DEFERRED_CONSTRAINTS) != 0;
6029 
6030   /* Pass AttrInfo section if available in the TupKeyReq signal
6031    * We are still responsible for releasing it, TUP is just
6032    * borrowing it
6033    */
6034   if (tupKeyReq->attrBufLen > 0)
6035   {
6036     ndbassert( regTcPtr->attrInfoIVal != RNIL );
6037     tupKeyReq->attrInfoIVal= regTcPtr->attrInfoIVal;
6038   }
6039 
6040   EXECUTE_DIRECT(tup, GSN_TUPKEYREQ, signal, TupKeyReq::SignalLength);
6041 }//Dblqh::execACCKEYCONF()
6042 
6043 void
acckeyconf_load_diskpage(Signal * signal,TcConnectionrecPtr regTcPtr,Fragrecord * regFragptrP,Uint32 lkey1,Uint32 lkey2)6044 Dblqh::acckeyconf_load_diskpage(Signal* signal, TcConnectionrecPtr regTcPtr,
6045 				Fragrecord* regFragptrP,
6046                                 Uint32 lkey1, Uint32 lkey2)
6047 {
6048   int res;
6049   if((res= c_tup->load_diskpage(signal,
6050 				regTcPtr.p->tupConnectrec,
6051 				regFragptrP->tupFragptr,
6052 				lkey1, lkey2,
6053 				regTcPtr.p->operation)) > 0)
6054   {
6055     acckeyconf_tupkeyreq(signal, regTcPtr.p, regFragptrP, lkey1, lkey2, res);
6056   }
6057   else if(res == 0)
6058   {
6059     regTcPtr.p->transactionState = TcConnectionrec::WAIT_TUP;
6060     regTcPtr.p->m_row_id.m_page_no = lkey1;
6061     regTcPtr.p->m_row_id.m_page_idx = lkey2;
6062   }
6063   else
6064   {
6065     regTcPtr.p->transactionState = TcConnectionrec::WAIT_TUP;
6066     TupKeyRef * ref = (TupKeyRef *)signal->getDataPtr();
6067     ref->userRef= regTcPtr.i;
6068     ref->errorCode= ~0;
6069     execTUPKEYREF(signal);
6070   }
6071 }
6072 
6073 void
acckeyconf_load_diskpage_callback(Signal * signal,Uint32 callbackData,Uint32 disk_page)6074 Dblqh::acckeyconf_load_diskpage_callback(Signal* signal,
6075 					 Uint32 callbackData,
6076 					 Uint32 disk_page)
6077 {
6078   jamEntry();
6079   tcConnectptr.i = callbackData;
6080   ptrCheckGuard(tcConnectptr, ctcConnectrecFileSize, tcConnectionrec);
6081   TcConnectionrec * const regTcPtr = tcConnectptr.p;
6082 
6083   TcConnectionrec::TransactionState state = regTcPtr->transactionState;
6084   if (likely(disk_page > 0 && state == TcConnectionrec::WAIT_TUP))
6085   {
6086     FragrecordPtr fragPtr;
6087     c_fragment_pool.getPtr(fragPtr, regTcPtr->fragmentptr);
6088 
6089     acckeyconf_tupkeyreq(signal, regTcPtr, fragPtr.p,
6090 			 regTcPtr->m_row_id.m_page_no,
6091 			 regTcPtr->m_row_id.m_page_idx,
6092 			 disk_page);
6093   }
6094   else if (state != TcConnectionrec::WAIT_TUP)
6095   {
6096     ndbrequire(state == TcConnectionrec::WAIT_TUP_TO_ABORT);
6097     abortCommonLab(signal);
6098     return;
6099   }
6100   else
6101   {
6102     regTcPtr->transactionState = TcConnectionrec::WAIT_TUP;
6103     TupKeyRef * ref = (TupKeyRef *)signal->getDataPtr();
6104     ref->userRef= callbackData;
6105     ref->errorCode= disk_page;
6106     execTUPKEYREF(signal);
6107   }
6108 }
6109 
6110 /* --------------------------------------------------------------------------
6111  * -------                       ENTER TUP...                         -------
6112  * ENTER TUPKEYCONF WITH
6113  *           TC_CONNECTPTR,
6114  *           TDATA2,     LOCAL KEY REFERENCE 1, ONLY INTERESTING AFTER INSERT
6115  *           TDATA3,     LOCAL KEY REFERENCE 1, ONLY INTERESTING AFTER INSERT
6116  *           TDATA4,     TOTAL LENGTH OF READ DATA SENT TO TC/APPLICATION
6117  *           TDATA5      TOTAL LENGTH OF UPDATE DATA SENT TO/FROM TUP
6118  *        GOTO TUPKEY_CONF
6119  *
6120  *  TAKE CARE OF RESPONSES FROM TUPLE MANAGER.
6121  * -------------------------------------------------------------------------- */
tupkeyConfLab(Signal * signal)6122 void Dblqh::tupkeyConfLab(Signal* signal)
6123 {
6124 /* ---- GET OPERATION TYPE AND CHECK WHAT KIND OF OPERATION IS REQUESTED --- */
6125   const TupKeyConf * const tupKeyConf = (TupKeyConf *)&signal->theData[0];
6126   TcConnectionrec * const regTcPtr = tcConnectptr.p;
6127   Uint32 activeCreat = regTcPtr->activeCreat;
6128   Uint32 readLen = tupKeyConf->readLength;
6129   Uint32 writeLen = tupKeyConf->writeLength;
6130 
6131   TRACE_OP(regTcPtr, "TUPKEYCONF");
6132 
6133   Uint32 accOp = regTcPtr->accConnectrec;
6134   c_acc->execACCKEY_ORD(signal, accOp);
6135 
6136   if (readLen != 0)
6137   {
6138     jam();
6139 
6140     /* SET BIT 15 IN REQINFO */
6141     LqhKeyReq::setApplicationAddressFlag(regTcPtr->reqinfo, 1);
6142     regTcPtr->readlenAi = readLen;
6143   }//if
6144 
6145   if (regTcPtr->operation == ZREAD &&
6146       (regTcPtr->opSimple || regTcPtr->dirtyOp))
6147   {
6148     jam();
6149     /* ----------------------------------------------------------------------
6150      * THE OPERATION IS A SIMPLE READ.
6151      * WE WILL IMMEDIATELY COMMIT THE OPERATION.
6152      * SINCE WE HAVE NOT RELEASED THE FRAGMENT LOCK
6153      * (FOR LOCAL CHECKPOINTS) YET
6154      * WE CAN GO IMMEDIATELY TO COMMIT_CONTINUE_AFTER_BLOCKED.
6155      * WE HAVE ALREADY SENT THE RESPONSE SO WE ARE NOT INTERESTED IN
6156      * READ LENGTH
6157      * --------------------------------------------------------------------- */
6158     commitContinueAfterBlockedLab(signal);
6159     return;
6160   }//if
6161 
6162   regTcPtr->totSendlenAi = writeLen;
6163   /* We will propagate / log writeLen words
6164    * Check that that is how many we have available to
6165    * propagate
6166    */
6167   ndbrequire(regTcPtr->totSendlenAi == regTcPtr->currTupAiLen);
6168 
6169   if (unlikely(activeCreat == Fragrecord::AC_NR_COPY))
6170   {
6171     jam();
6172     ndbrequire(regTcPtr->m_nr_delete.m_cnt);
6173     regTcPtr->m_nr_delete.m_cnt--;
6174     if (regTcPtr->m_nr_delete.m_cnt)
6175     {
6176       jam();
6177       /**
6178        * Let operation wait for pending NR operations
6179        *   even for before writing log...(as it's simpler)
6180        */
6181 
6182 #ifdef VM_TRACE
6183       /**
6184        * Only disk table can have pending ops...
6185        */
6186       TablerecPtr tablePtr;
6187       tablePtr.i = regTcPtr->tableref;
6188       ptrCheckGuard(tablePtr, ctabrecFileSize, tablerec);
6189       ndbrequire(tablePtr.p->m_disk_table);
6190 #endif
6191 
6192       return;
6193     }
6194   }
6195 
6196   rwConcludedLab(signal);
6197   return;
6198 }//Dblqh::tupkeyConfLab()
6199 
6200 /* --------------------------------------------------------------------------
6201  *     THE CODE IS FOUND IN THE SIGNAL RECEPTION PART OF LQH
6202  * -------------------------------------------------------------------------- */
rwConcludedLab(Signal * signal)6203 void Dblqh::rwConcludedLab(Signal* signal)
6204 {
6205   TcConnectionrec * const regTcPtr = tcConnectptr.p;
6206   /* ------------------------------------------------------------------------
6207    *  WE HAVE NOW CONCLUDED READING/WRITING IN ACC AND TUP FOR THIS OPERATION.
6208    *  IT IS NOW TIME TO LOG THE OPERATION, SEND REQUEST TO NEXT NODE OR TC AND
6209    *  FOR SOME TYPES OF OPERATIONS IT IS EVEN TIME TO COMMIT THE OPERATION.
6210    * ------------------------------------------------------------------------ */
6211   if (regTcPtr->operation == ZREAD) {
6212     jam();
6213     /* ----------------------------------------------------------------------
6214      * A NORMAL READ OPERATION IS NOT LOGGED BUT IS NOT COMMITTED UNTIL THE
6215      * COMMIT SIGNAL ARRIVES. THUS WE CONTINUE PACKING THE RESPONSE.
6216      * ---------------------------------------------------------------------- */
6217     packLqhkeyreqLab(signal);
6218     return;
6219   } else {
6220     FragrecordPtr regFragptr = fragptr;
6221     if (regFragptr.p->logFlag == Fragrecord::STATE_FALSE){
6222       if (regTcPtr->dirtyOp == ZTRUE) {
6223         jam();
6224 	/* ------------------------------------------------------------------
6225 	 * THIS OPERATION WAS A WRITE OPERATION THAT DO NOT NEED LOGGING AND
6226 	 * THAT CAN CAN  BE COMMITTED IMMEDIATELY.
6227 	 * ----------------------------------------------------------------- */
6228         commitContinueAfterBlockedLab(signal);
6229         return;
6230       } else {
6231         jam();
6232 	/* ------------------------------------------------------------------
6233 	 * A NORMAL WRITE OPERATION ON A FRAGMENT WHICH DO NOT NEED LOGGING.
6234 	 * WE WILL PACK THE REQUEST/RESPONSE TO THE NEXT NODE/TO TC.
6235 	 * ------------------------------------------------------------------ */
6236         regTcPtr->logWriteState = TcConnectionrec::NOT_WRITTEN;
6237         packLqhkeyreqLab(signal);
6238         return;
6239       }//if
6240     } else {
6241       jam();
6242       /* --------------------------------------------------------------------
6243        * A DIRTY OPERATION WHICH NEEDS LOGGING. WE START BY LOGGING THE
6244        * REQUEST. IN THIS CASE WE WILL RELEASE THE FRAGMENT LOCK FIRST.
6245        * --------------------------------------------------------------------
6246        * A NORMAL WRITE OPERATION THAT NEEDS LOGGING AND WILL NOT BE
6247        * PREMATURELY COMMITTED.
6248        * -------------------------------------------------------------------- */
6249       logLqhkeyreqLab(signal);
6250       return;
6251     }//if
6252   }//if
6253 }//Dblqh::rwConcludedLab()
6254 
rwConcludedAiLab(Signal * signal)6255 void Dblqh::rwConcludedAiLab(Signal* signal)
6256 {
6257   TcConnectionrec * const regTcPtr = tcConnectptr.p;
6258   fragptr.i = regTcPtr->fragmentptr;
6259   /* ------------------------------------------------------------------------
6260    * WE HAVE NOW CONCLUDED READING/WRITING IN ACC AND TUP FOR THIS OPERATION.
6261    * IT IS NOW TIME TO LOG THE OPERATION, SEND REQUEST TO NEXT NODE OR TC AND
6262    * FOR SOME TYPES OF OPERATIONS IT IS EVEN TIME TO COMMIT THE OPERATION.
6263    * IN THIS CASE WE HAVE ALREADY RELEASED THE FRAGMENT LOCK.
6264    * ERROR CASES AT FRAGMENT CREATION AND STAND-BY NODES ARE THE REASONS FOR
6265    * COMING HERE.
6266    * ------------------------------------------------------------------------ */
6267   if (regTcPtr->operation == ZREAD) {
6268     if (regTcPtr->opSimple == 1) {
6269       jam();
6270       /* --------------------------------------------------------------------
6271        * THE OPERATION IS A SIMPLE READ. WE WILL IMMEDIATELY COMMIT THE
6272        * OPERATION.
6273        * -------------------------------------------------------------------- */
6274       localCommitLab(signal);
6275       return;
6276     } else {
6277       jam();
6278       /* --------------------------------------------------------------------
6279        * A NORMAL READ OPERATION IS NOT LOGGED BUT IS NOT COMMITTED UNTIL
6280        * THE COMMIT SIGNAL ARRIVES. THUS WE CONTINUE PACKING THE RESPONSE.
6281        * -------------------------------------------------------------------- */
6282       c_fragment_pool.getPtr(fragptr);
6283       packLqhkeyreqLab(signal);
6284       return;
6285     }//if
6286   } else {
6287     jam();
6288     c_fragment_pool.getPtr(fragptr);
6289     if (fragptr.p->logFlag == Fragrecord::STATE_FALSE) {
6290       if (regTcPtr->dirtyOp == ZTRUE) {
6291 	/* ------------------------------------------------------------------
6292 	 * THIS OPERATION WAS A WRITE OPERATION THAT DO NOT NEED LOGGING AND
6293 	 * THAT CAN CAN  BE COMMITTED IMMEDIATELY.
6294 	 * ----------------------------------------------------------------- */
6295         jam();
6296 	/* ----------------------------------------------------------------
6297 	 * IT MUST BE ACTIVE CREATION OF A FRAGMENT.
6298 	 * ---------------------------------------------------------------- */
6299         localCommitLab(signal);
6300         return;
6301       } else {
6302 	/* ------------------------------------------------------------------
6303 	 * A NORMAL WRITE OPERATION ON A FRAGMENT WHICH DO NOT NEED LOGGING.
6304 	 * WE WILL PACK THE REQUEST/RESPONSE TO THE NEXT NODE/TO TC.
6305 	 * ------------------------------------------------------------------ */
6306         jam();
6307 	  /* ---------------------------------------------------------------
6308 	   * IT MUST BE ACTIVE CREATION OF A FRAGMENT.
6309 	   * NOT A DIRTY OPERATION THUS PACK REQUEST/RESPONSE.
6310 	   * ---------------------------------------------------------------- */
6311         regTcPtr->logWriteState = TcConnectionrec::NOT_WRITTEN;
6312         packLqhkeyreqLab(signal);
6313         return;
6314       }//if
6315     } else {
6316       jam();
6317       /* --------------------------------------------------------------------
6318        * A DIRTY OPERATION WHICH NEEDS LOGGING. WE START BY LOGGING THE
6319        * REQUEST. IN THIS CASE WE WILL RELEASE THE FRAGMENT LOCK FIRST.
6320        * -------------------------------------------------------------------- */
6321       /* A NORMAL WRITE OPERATION THAT NEEDS LOGGING AND WILL NOT BE
6322        * PREMATURELY COMMITTED.
6323        * -------------------------------------------------------------------- */
6324       logLqhkeyreqLab(signal);
6325       return;
6326     }//if
6327   }//if
6328 }//Dblqh::rwConcludedAiLab()
6329 
6330 /* ##########################################################################
6331  * #######                            LOG MODULE                      #######
6332  *
6333  * ##########################################################################
6334  * --------------------------------------------------------------------------
6335  *       THE LOG MODULE HANDLES THE READING AND WRITING OF THE LOG
6336  *       IT IS ALSO RESPONSIBLE FOR HANDLING THE SYSTEM RESTART.
6337  *       IT CONTROLS THE SYSTEM RESTART IN TUP AND ACC AS WELL.
6338  * -------------------------------------------------------------------------- */
logLqhkeyreqLab(Signal * signal)6339 void Dblqh::logLqhkeyreqLab(Signal* signal)
6340 {
6341   UintR tcurrentFilepage;
6342   TcConnectionrecPtr tmpTcConnectptr;
6343 
6344   const bool out_of_log_buffer = cnoOfLogPages < ZMIN_LOG_PAGES_OPERATION;
6345 
6346   TcConnectionrec * const regTcPtr = tcConnectptr.p;
6347   logPartPtr.i = regTcPtr->m_log_part_ptr_i;
6348   ptrCheckGuard(logPartPtr, clogPartFileSize, logPartRecord);
6349   bool abort_on_redo_problems =
6350     (LqhKeyReq::getQueueOnRedoProblemFlag(regTcPtr->reqinfo) == 0);
6351 
6352 /* -------------------------------------------------- */
6353 /*       THIS PART IS USED TO WRITE THE LOG           */
6354 /* -------------------------------------------------- */
6355 /* -------------------------------------------------- */
6356 /*       CHECK IF A LOG OPERATION IS ONGOING ALREADY. */
6357 /*       IF SO THEN QUEUE THE OPERATION FOR LATER     */
6358 /*       RESTART WHEN THE LOG PART IS FREE AGAIN.     */
6359 /* -------------------------------------------------- */
6360   LogPartRecord * const regLogPartPtr = logPartPtr.p;
6361   const bool problem = out_of_log_buffer || regLogPartPtr->m_log_problems != 0;
6362   if (unlikely(problem))
6363   {
6364     if (abort_on_redo_problems)
6365     {
6366       logLqhkeyreqLab_problems(signal);
6367       return;
6368     }
6369     else
6370     {
6371       goto queueop;
6372     }
6373   }
6374 
6375   if (regLogPartPtr->logPartState == LogPartRecord::IDLE)
6376   {
6377     ;
6378   }
6379   else if (regLogPartPtr->logPartState == LogPartRecord::ACTIVE)
6380   {
6381 queueop:
6382     jam();
6383     linkWaitLog(signal, logPartPtr, logPartPtr.p->m_log_prepare_queue);
6384     regTcPtr->transactionState = TcConnectionrec::LOG_QUEUED;
6385     return;
6386   }
6387   else
6388   {
6389     ndbrequire(false);
6390     return;
6391   }//if
6392 
6393   logFilePtr.i = regLogPartPtr->currentLogfile;
6394   ptrCheckGuard(logFilePtr, clogFileFileSize, logFileRecord);
6395 /* -------------------------------------------------- */
6396 /*       CHECK IF A NEW MBYTE IS TO BE STARTED. IF    */
6397 /*       SO INSERT A NEXT LOG RECORD, WRITE THE LOG   */
6398 /*       AND PLACE THE LOG POINTER ON THE NEW POSITION*/
6399 /*       IF A NEW FILE IS TO BE USED, CHANGE FILE AND */
6400 /*       ALSO START OPENING THE NEXT LOG FILE. IF A   */
6401 /*       LAP HAS BEEN COMPLETED THEN ADD ONE TO LAP   */
6402 /*       COUNTER.                                     */
6403 /* -------------------------------------------------- */
6404   checkNewMbyte(signal);
6405 /* -------------------------------------------------- */
6406 /*       INSERT THE OPERATION RECORD LAST IN THE LIST */
6407 /*       OF NOT COMPLETED OPERATIONS. ALSO RECORD THE */
6408 /*       FILE NO, PAGE NO AND PAGE INDEX OF THE START */
6409 /*       OF THIS LOG RECORD.                          */
6410 /*       IT IS NOT ALLOWED TO INSERT IT INTO THE LIST */
6411 /*       BEFORE CHECKING THE NEW MBYTE SINCE THAT WILL*/
6412 /*       CAUSE THE OLD VALUES OF TC_CONNECTPTR TO BE  */
6413 /*       USED IN WRITE_FILE_DESCRIPTOR.               */
6414 /* -------------------------------------------------- */
6415   Uint32 tcIndex = tcConnectptr.i;
6416   tmpTcConnectptr.i = regLogPartPtr->lastLogTcrec;
6417   regLogPartPtr->lastLogTcrec = tcIndex;
6418   if (tmpTcConnectptr.i == RNIL) {
6419     jam();
6420     regLogPartPtr->firstLogTcrec = tcIndex;
6421   } else {
6422     ptrCheckGuard(tmpTcConnectptr, ctcConnectrecFileSize, tcConnectionrec);
6423     tmpTcConnectptr.p->nextLogTcrec = tcIndex;
6424   }//if
6425   Uint32 fileNo = logFilePtr.p->fileNo;
6426   tcurrentFilepage = logFilePtr.p->currentFilepage;
6427   logPagePtr.i = logFilePtr.p->currentLogpage;
6428   regTcPtr->nextLogTcrec = RNIL;
6429   regTcPtr->prevLogTcrec = tmpTcConnectptr.i;
6430   ptrCheckGuard(logPagePtr, clogPageFileSize, logPageRecord);
6431   Uint32 pageIndex = logPagePtr.p->logPageWord[ZCURR_PAGE_INDEX];
6432   regTcPtr->logStartFileNo = fileNo;
6433   regTcPtr->logStartPageNo = tcurrentFilepage;
6434   regTcPtr->logStartPageIndex = pageIndex;
6435 /* -------------------------------------------------- */
6436 /*       WRITE THE LOG HEADER OF THIS OPERATION.      */
6437 /* -------------------------------------------------- */
6438   writeLogHeader(signal);
6439 /* -------------------------------------------------- */
6440 /*       WRITE THE TUPLE KEY OF THIS OPERATION.       */
6441 /* -------------------------------------------------- */
6442   writeKey(signal);
6443 /* -------------------------------------------------- */
6444 /*       WRITE THE ATTRIBUTE INFO OF THIS OPERATION.  */
6445 /* -------------------------------------------------- */
6446   writeAttrinfoLab(signal);
6447 
6448 /* -------------------------------------------------- */
6449 /*       RESET THE STATE OF THE LOG PART. IF ANY      */
6450 /*       OPERATIONS HAVE QUEUED THEN START THE FIRST  */
6451 /*       OF THESE.                                    */
6452 /* -------------------------------------------------- */
6453 /* -------------------------------------------------- */
6454 /*       CONTINUE WITH PACKING OF LQHKEYREQ           */
6455 /* -------------------------------------------------- */
6456   tcurrentFilepage = logFilePtr.p->currentFilepage;
6457   if (logPagePtr.p->logPageWord[ZCURR_PAGE_INDEX] == ZPAGE_HEADER_SIZE) {
6458     jam();
6459     tcurrentFilepage--;
6460   }//if
6461   regTcPtr->logStopPageNo = tcurrentFilepage;
6462   regTcPtr->logWriteState = TcConnectionrec::WRITTEN;
6463   if (regTcPtr->abortState != TcConnectionrec::ABORT_IDLE) {
6464 /* -------------------------------------------------- */
6465 /*       AN ABORT HAVE BEEN ORDERED. THE ABORT WAITED */
6466 /*       FOR THE LOG WRITE TO BE COMPLETED. NOW WE    */
6467 /*       CAN PROCEED WITH THE NORMAL ABORT HANDLING.  */
6468 /* -------------------------------------------------- */
6469     abortCommonLab(signal);
6470     return;
6471   }//if
6472   if (regTcPtr->dirtyOp != ZTRUE) {
6473     packLqhkeyreqLab(signal);
6474   } else {
6475     /* ----------------------------------------------------------------------
6476      * I NEED TO INSERT A COMMIT LOG RECORD SINCE WE ARE WRITING LOG IN THIS
6477      * TRANSACTION. SINCE WE RELEASED THE LOG LOCK JUST NOW NO ONE ELSE CAN BE
6478      * ACTIVE IN WRITING THE LOG. WE THUS WRITE THE LOG WITHOUT GETTING A LOCK
6479      * SINCE WE ARE ONLY WRITING A COMMIT LOG RECORD.
6480      * ---------------------------------------------------------------------- */
6481     writeCommitLog(signal, logPartPtr);
6482     /* ----------------------------------------------------------------------
6483      * DIRTY OPERATIONS SHOULD COMMIT BEFORE THEY PACK THE REQUEST/RESPONSE.
6484      * ---------------------------------------------------------------------- */
6485     localCommitLab(signal);
6486   }//if
6487 }//Dblqh::logLqhkeyreqLab()
6488 
6489 void
logLqhkeyreqLab_problems(Signal * signal)6490 Dblqh::logLqhkeyreqLab_problems(Signal * signal)
6491 {
6492   jam();
6493   LogPartRecord * const regLogPartPtr = logPartPtr.p;
6494   Uint32 problems = regLogPartPtr->m_log_problems;
6495 
6496   if (cnoOfLogPages < ZMIN_LOG_PAGES_OPERATION)
6497   {
6498     jam();
6499     terrorCode = ZTEMPORARY_REDO_LOG_FAILURE;
6500   }
6501   else if ((problems & LogPartRecord::P_TAIL_PROBLEM) != 0)
6502   {
6503     jam();
6504     terrorCode = ZTAIL_PROBLEM_IN_LOG_ERROR;
6505   }
6506   else if ((problems & LogPartRecord::P_REDO_IO_PROBLEM) != 0)
6507   {
6508     jam();
6509     terrorCode = ZREDO_IO_PROBLEM;
6510   }
6511   else if ((problems & LogPartRecord::P_FILE_CHANGE_PROBLEM) != 0)
6512   {
6513     jam();
6514     terrorCode = ZFILE_CHANGE_PROBLEM_IN_LOG_ERROR;
6515   }
6516   abortErrorLab(signal);
6517 }
6518 
6519 void
update_log_problem(Signal * signal,Ptr<LogPartRecord> partPtr,Uint32 problem,bool value)6520 Dblqh::update_log_problem(Signal* signal, Ptr<LogPartRecord> partPtr,
6521                           Uint32 problem, bool value)
6522 {
6523   Uint32 problems = partPtr.p->m_log_problems;
6524   if (value)
6525   {
6526     /**
6527      * set
6528      */
6529     jam();
6530     if ((problems & problem) == 0)
6531     {
6532       jam();
6533       problems |= problem;
6534     }
6535   }
6536   else
6537   {
6538     /**
6539      * clear
6540      */
6541     jam();
6542     if ((problems & problem) != 0)
6543     {
6544       jam();
6545       problems &= ~(Uint32)problem;
6546 
6547       if (partPtr.p->LogLqhKeyReqSent == ZFALSE &&
6548           (!partPtr.p->m_log_prepare_queue.isEmpty() ||
6549            !partPtr.p->m_log_complete_queue.isEmpty()))
6550       {
6551         jam();
6552 
6553         partPtr.p->LogLqhKeyReqSent = ZTRUE;
6554         signal->theData[0] = ZLOG_LQHKEYREQ;
6555         signal->theData[1] = partPtr.i;
6556         sendSignal(cownref, GSN_CONTINUEB, signal, 2, JBB);
6557       }
6558     }
6559   }
6560   partPtr.p->m_log_problems = problems;
6561 }
6562 
6563 /* ------------------------------------------------------------------------- */
6564 /* -------                        SEND LQHKEYREQ                             */
6565 /*                                                                           */
6566 /* NO STATE CHECKING SINCE THE SIGNAL IS A LOCAL SIGNAL. THE EXECUTION OF    */
6567 /* THE OPERATION IS COMPLETED. IT IS NOW TIME TO SEND THE OPERATION TO THE   */
6568 /* NEXT REPLICA OR TO TC.                                                    */
6569 /* ------------------------------------------------------------------------- */
packLqhkeyreqLab(Signal * signal)6570 void Dblqh::packLqhkeyreqLab(Signal* signal)
6571 {
6572   TcConnectionrec * const regTcPtr = tcConnectptr.p;
6573   if (regTcPtr->nextReplica == ZNIL) {
6574 /* ------------------------------------------------------------------------- */
6575 /* -------               SEND LQHKEYCONF                             ------- */
6576 /*                                                                           */
6577 /* ------------------------------------------------------------------------- */
6578     sendLqhkeyconfTc(signal, regTcPtr->tcBlockref);
6579     if (! (regTcPtr->dirtyOp ||
6580            (regTcPtr->operation == ZREAD && regTcPtr->opSimple)))
6581     {
6582       jam();
6583       regTcPtr->transactionState = TcConnectionrec::PREPARED;
6584       releaseOprec(signal);
6585     } else {
6586       jam();
6587 
6588 /*************************************************************>*/
6589 /*       DIRTY WRITES ARE USED IN TWO SITUATIONS. THE FIRST    */
6590 /*       SITUATION IS WHEN THEY ARE USED TO UPDATE COUNTERS AND*/
6591 /*       OTHER ATTRIBUTES WHICH ARE NOT SENSITIVE TO CONSISTE- */
6592 /*       NCY. THE SECOND SITUATION IS BY OPERATIONS THAT ARE   */
6593 /*       SENT AS PART OF A COPY FRAGMENT PROCESS.              */
6594 /*                                                             */
6595 /*       DURING A COPY FRAGMENT PROCESS THERE IS NO LOGGING    */
6596 /*       ONGOING SINCE THE FRAGMENT IS NOT COMPLETE YET. THE   */
6597 /*       LOGGING STARTS AFTER COMPLETING THE LAST COPY TUPLE   */
6598 /*       OPERATION. THE EXECUTION OF THE LAST COPY TUPLE DOES  */
6599 /*       ALSO START A LOCAL CHECKPOINT SO THAT THE FRAGMENT    */
6600 /*       REPLICA IS RECOVERABLE. THUS GLOBAL CHECKPOINT ID FOR */
6601 /*       THOSE OPERATIONS ARE NOT INTERESTING.                 */
6602 /*                                                             */
6603 /*       A DIRTY WRITE IS BY DEFINITION NOT CONSISTENT. THUS   */
6604 /*       IT CAN USE ANY GLOBAL CHECKPOINT. THE IDEA HERE IS TO */
6605 /*       ALWAYS USE THE LATEST DEFINED GLOBAL CHECKPOINT ID IN */
6606 /*       THIS NODE.                                            */
6607 /*************************************************************>*/
6608       cleanUp(signal);
6609     }//if
6610     return;
6611   }//if
6612 /* ------------------------------------------------------------------------- */
6613 /* -------            SEND LQHKEYREQ                                 ------- */
6614 /*                                                                           */
6615 /* ------------------------------------------------------------------------- */
6616 /* ------------------------------------------------------------------------- */
6617 /* THERE ARE MORE REPLICAS TO SEND THE OPERATION TO. A NEW LQHKEYREQ WILL BE */
6618 /* PREPARED FOR THE NEXT REPLICA.                                            */
6619 /* ------------------------------------------------------------------------- */
6620 /* CLEAR REPLICA TYPE, ATTRINFO INDICATOR (IN LQHKEYREQ),                    */
6621 /* INTERPRETED EXECUTION, SEQUENTIAL NUMBER OF REPLICA.                      */
6622 // Set bit indicating Client and TC record not the same.
6623 // Set readlenAi indicator if readlenAi != 0
6624 // Stored Procedure Indicator not set.
6625 /* ------------------------------------------------------------------------- */
6626   LqhKeyReq * const lqhKeyReq = (LqhKeyReq *)&signal->theData[0];
6627 
6628   UintR Treqinfo;
6629   UintR sig0, sig1, sig2, sig3, sig4, sig5, sig6;
6630   Treqinfo = preComputedRequestInfoMask & regTcPtr->reqinfo;
6631 
6632   Uint32 nextNodeId = regTcPtr->nextReplica;
6633   Uint32 nextVersion = getNodeInfo(nextNodeId).m_version;
6634 
6635   /* Send long LqhKeyReq to next replica if it can support it */
6636   bool sendLongReq= ! ((nextVersion < NDBD_LONG_LQHKEYREQ) ||
6637                        ERROR_INSERTED(5051));
6638 
6639   UintR TAiLen = sendLongReq ?
6640     0 :
6641     MIN(regTcPtr->totSendlenAi, LqhKeyReq::MaxAttrInfo);
6642 
6643   /* Long LQHKeyReq uses section size for key length */
6644   Uint32 lqhKeyLen= sendLongReq?
6645     0 :
6646     regTcPtr->primKeyLen;
6647 
6648   UintR TapplAddressIndicator = (regTcPtr->nextSeqNoReplica == 0 ? 0 : 1);
6649   LqhKeyReq::setApplicationAddressFlag(Treqinfo, TapplAddressIndicator);
6650   LqhKeyReq::setInterpretedFlag(Treqinfo, regTcPtr->opExec);
6651   LqhKeyReq::setSeqNoReplica(Treqinfo, regTcPtr->nextSeqNoReplica);
6652   LqhKeyReq::setAIInLqhKeyReq(Treqinfo, TAiLen);
6653   LqhKeyReq::setKeyLen(Treqinfo,lqhKeyLen);
6654 
6655   if (unlikely(nextVersion < NDBD_ROWID_VERSION))
6656   {
6657     LqhKeyReq::setLockType(Treqinfo, regTcPtr->lockType);
6658   }
6659   else
6660   {
6661     regTcPtr->m_use_rowid |=
6662       fragptr.p->m_copy_started_state == Fragrecord::AC_NR_COPY;
6663     LqhKeyReq::setRowidFlag(Treqinfo, regTcPtr->m_use_rowid);
6664   }
6665 
6666   if (LqhKeyReq::getRowidFlag(Treqinfo))
6667   {
6668     //ndbassert(LqhKeyReq::getOperation(Treqinfo) == ZINSERT);
6669   }
6670   else
6671   {
6672     if (fragptr.p->m_copy_started_state != Fragrecord::AC_IGNORED)
6673     {
6674       ndbassert(LqhKeyReq::getOperation(Treqinfo) != ZINSERT ||
6675                 get_node_status(nextNodeId) != ZNODE_UP);
6676     }
6677   }
6678 
6679   UintR TreadLenAiInd = (regTcPtr->readlenAi == 0 ? 0 : 1);
6680   UintR TsameLqhAndClient = (tcConnectptr.i ==
6681                              regTcPtr->tcOprec ? 0 : 1);
6682   LqhKeyReq::setSameClientAndTcFlag(Treqinfo, TsameLqhAndClient);
6683   LqhKeyReq::setReturnedReadLenAIFlag(Treqinfo, TreadLenAiInd);
6684 
6685   /* Long LQHKeyReq uses section size for AttrInfo length */
6686   UintR TotReclenAi = sendLongReq ?
6687     0 :
6688     regTcPtr->totSendlenAi;
6689 
6690   LqhKeyReq::setReorgFlag(TotReclenAi, regTcPtr->m_reorg);
6691 
6692 /* ------------------------------------------------------------------------- */
6693 /* WE ARE NOW PREPARED TO SEND THE LQHKEYREQ. WE HAVE TO DECIDE IF ATTRINFO  */
6694 /* IS INCLUDED IN THE LQHKEYREQ SIGNAL AND THEN SEND IT.                     */
6695 /* TAKE OVER SCAN OPERATION IS NEVER USED ON BACKUPS, LOG RECORDS AND START-UP*/
6696 /* OF NEW REPLICA AND THUS ONLY TOT_SENDLEN_AI IS USED THE UPPER 16 BITS ARE */
6697 /* ZERO.                                                                     */
6698 /* ------------------------------------------------------------------------- */
6699   sig0 = tcConnectptr.i;
6700   sig1 = regTcPtr->savePointId;
6701   sig2 = regTcPtr->hashValue;
6702   sig4 = regTcPtr->tcBlockref;
6703 
6704   lqhKeyReq->clientConnectPtr = sig0;
6705   lqhKeyReq->attrLen = TotReclenAi;
6706   lqhKeyReq->savePointId = sig1;
6707   lqhKeyReq->hashValue = sig2;
6708   lqhKeyReq->requestInfo = Treqinfo;
6709   lqhKeyReq->tcBlockref = sig4;
6710 
6711   sig0 = regTcPtr->tableref + ((regTcPtr->schemaVersion << 16) & 0xFFFF0000);
6712   sig1 = regTcPtr->fragmentid + (regTcPtr->nodeAfterNext[0] << 16);
6713   sig2 = regTcPtr->transid[0];
6714   sig3 = regTcPtr->transid[1];
6715   sig4 = regTcPtr->applRef;
6716   sig5 = regTcPtr->applOprec;
6717   sig6 = regTcPtr->tcOprec;
6718   UintR nextPos = (TapplAddressIndicator << 1);
6719 
6720   lqhKeyReq->tableSchemaVersion = sig0;
6721   lqhKeyReq->fragmentData = sig1;
6722   lqhKeyReq->transId1 = sig2;
6723   lqhKeyReq->transId2 = sig3;
6724   lqhKeyReq->noFiredTriggers = regTcPtr->noFiredTriggers;
6725   lqhKeyReq->variableData[0] = sig4;
6726   lqhKeyReq->variableData[1] = sig5;
6727   lqhKeyReq->variableData[2] = sig6;
6728 
6729   nextPos += TsameLqhAndClient;
6730 
6731   if ((regTcPtr->lastReplicaNo - regTcPtr->nextSeqNoReplica) > 1) {
6732     sig0 = (UintR)regTcPtr->nodeAfterNext[1] +
6733            (UintR)(regTcPtr->nodeAfterNext[2] << 16);
6734     lqhKeyReq->variableData[nextPos] = sig0;
6735     nextPos++;
6736   }//if
6737   sig0 = regTcPtr->readlenAi;
6738   lqhKeyReq->variableData[nextPos] = sig0;
6739   nextPos += TreadLenAiInd;
6740 
6741   if (!sendLongReq)
6742   {
6743     /* Short LQHKEYREQ to older LQH
6744      * First few words of KeyInfo go into LQHKEYREQ
6745      * Sometimes have no Keyinfo
6746      */
6747     if (regTcPtr->primKeyLen != 0)
6748     {
6749       SegmentedSectionPtr keyInfoSection;
6750 
6751       ndbassert(regTcPtr->keyInfoIVal != RNIL);
6752 
6753       getSection(keyInfoSection, regTcPtr->keyInfoIVal);
6754       SectionReader keyInfoReader(keyInfoSection, g_sectionSegmentPool);
6755 
6756       UintR keyLenInLqhKeyReq= MIN(LqhKeyReq::MaxKeyInfo,
6757                                    regTcPtr->primKeyLen);
6758 
6759       keyInfoReader.getWords(&lqhKeyReq->variableData[nextPos],
6760                              keyLenInLqhKeyReq);
6761 
6762       nextPos+= keyLenInLqhKeyReq;
6763     }
6764   }
6765 
6766   sig0 = regTcPtr->gci_hi;
6767   Local_key tmp = regTcPtr->m_row_id;
6768 
6769   lqhKeyReq->variableData[nextPos + 0] = tmp.m_page_no;
6770   lqhKeyReq->variableData[nextPos + 1] = tmp.m_page_idx;
6771   nextPos += 2*LqhKeyReq::getRowidFlag(Treqinfo);
6772 
6773   lqhKeyReq->variableData[nextPos + 0] = sig0;
6774   nextPos += LqhKeyReq::getGCIFlag(Treqinfo);
6775 
6776   // pass full instance key for remote to map to real instance
6777   BlockReference lqhRef = numberToRef(DBLQH,
6778                                       fragptr.p->lqhInstanceKey,
6779                                       regTcPtr->nextReplica);
6780 
6781   if (likely(sendLongReq))
6782   {
6783     /* Long LQHKEYREQ, attach KeyInfo and AttrInfo
6784      * sections to signal
6785      */
6786     SectionHandle handle(this);
6787     handle.m_cnt= 0;
6788 
6789     if (regTcPtr->primKeyLen > 0)
6790     {
6791       SegmentedSectionPtr keyInfoSection;
6792 
6793       ndbassert(regTcPtr->keyInfoIVal != RNIL);
6794       getSection(keyInfoSection, regTcPtr->keyInfoIVal);
6795 
6796       handle.m_ptr[ LqhKeyReq::KeyInfoSectionNum ]= keyInfoSection;
6797       handle.m_cnt= 1;
6798 
6799       if (regTcPtr->totSendlenAi > 0)
6800       {
6801         SegmentedSectionPtr attrInfoSection;
6802 
6803         ndbassert(regTcPtr->attrInfoIVal != RNIL);
6804         getSection(attrInfoSection, regTcPtr->attrInfoIVal);
6805 
6806         handle.m_ptr[ LqhKeyReq::AttrInfoSectionNum ]= attrInfoSection;
6807         handle.m_cnt= 2;
6808       }
6809       else
6810       {
6811         /* No AttrInfo to be sent on.  This can occur for delete
6812          * or with an interpreted update when no actual update
6813          * is made
6814          * In this case, we free any attrInfo section now.
6815          */
6816         if (regTcPtr->attrInfoIVal != RNIL)
6817         {
6818           ndbassert(!( regTcPtr->m_flags &
6819                        TcConnectionrec::OP_SAVEATTRINFO));
6820           releaseSection(regTcPtr->attrInfoIVal);
6821           regTcPtr->attrInfoIVal= RNIL;
6822         }
6823       }
6824     }
6825     else
6826     {
6827       /* Zero-length primary key, better not have any
6828        * AttrInfo
6829        */
6830       ndbrequire(regTcPtr->totSendlenAi == 0);
6831       ndbassert(regTcPtr->keyInfoIVal == RNIL);
6832       ndbassert(regTcPtr->attrInfoIVal == RNIL);
6833     }
6834 
6835     sendSignal(lqhRef, GSN_LQHKEYREQ, signal,
6836                LqhKeyReq::FixedSignalLength + nextPos,
6837                JBB,
6838                &handle);
6839 
6840     /* Long sections were freed as part of sendSignal */
6841     ndbassert( handle.m_cnt == 0);
6842     regTcPtr->keyInfoIVal= RNIL;
6843     regTcPtr->attrInfoIVal= RNIL;
6844   }
6845   else
6846   {
6847     /* Short LQHKEYREQ to older LQH
6848      * First few words of ATTRINFO go into LQHKEYREQ
6849      * (if they fit)
6850      */
6851     if (TAiLen > 0)
6852     {
6853       if (likely(nextPos + TAiLen + LqhKeyReq::FixedSignalLength <= 25))
6854       {
6855         jam();
6856         SegmentedSectionPtr attrInfoSection;
6857 
6858         ndbassert(regTcPtr->attrInfoIVal != RNIL);
6859 
6860         getSection(attrInfoSection, regTcPtr->attrInfoIVal);
6861         SectionReader attrInfoReader(attrInfoSection, getSectionSegmentPool());
6862 
6863         attrInfoReader.getWords(&lqhKeyReq->variableData[nextPos],
6864                                 TAiLen);
6865 
6866         nextPos+= TAiLen;
6867       }
6868       else
6869       {
6870         /* Not enough space in LQHKEYREQ, we'll send everything in
6871          * separate ATTRINFO signals
6872          */
6873         Treqinfo &= ~(Uint32)(RI_AI_IN_THIS_MASK << RI_AI_IN_THIS_SHIFT);
6874         lqhKeyReq->requestInfo = Treqinfo;
6875         TAiLen= 0;
6876       }
6877     }
6878 
6879     sendSignal(lqhRef, GSN_LQHKEYREQ, signal,
6880                nextPos + LqhKeyReq::FixedSignalLength, JBB);
6881 
6882     /* Send extra KeyInfo signals if necessary... */
6883     if (regTcPtr->primKeyLen > LqhKeyReq::MaxKeyInfo) {
6884       jam();
6885       sendTupkey(signal);
6886     }//if
6887 
6888     /* Send extra AttrInfo signals if necessary... */
6889     Uint32 remainingAiLen= regTcPtr->totSendlenAi - TAiLen;
6890 
6891     if (remainingAiLen != 0)
6892     {
6893       sig0 = regTcPtr->tcOprec;
6894       sig1 = regTcPtr->transid[0];
6895       sig2 = regTcPtr->transid[1];
6896       signal->theData[0] = sig0;
6897       signal->theData[1] = sig1;
6898       signal->theData[2] = sig2;
6899 
6900       SectionReader attrInfoReader(regTcPtr->attrInfoIVal,
6901                                    g_sectionSegmentPool);
6902 
6903       ndbassert(attrInfoReader.getSize() == regTcPtr->totSendlenAi);
6904 
6905       /* Step over words already sent in LQHKEYREQ above */
6906       attrInfoReader.step(TAiLen);
6907 
6908       while (remainingAiLen != 0)
6909       {
6910         Uint32 dataInSignal= MIN(AttrInfo::DataLength, remainingAiLen);
6911         attrInfoReader.getWords(&signal->theData[3],
6912                                 dataInSignal);
6913         remainingAiLen-= dataInSignal;
6914         sendSignal(lqhRef, GSN_ATTRINFO, signal,
6915                    AttrInfo::HeaderLength + dataInSignal, JBB);
6916       }
6917     }
6918   }
6919 
6920   /* LQHKEYREQ sent */
6921 
6922   regTcPtr->transactionState = TcConnectionrec::PREPARED;
6923   if (regTcPtr->dirtyOp == ZTRUE) {
6924     jam();
6925 /*************************************************************>*/
6926 /*       DIRTY WRITES ARE USED IN TWO SITUATIONS. THE FIRST    */
6927 /*       SITUATION IS WHEN THEY ARE USED TO UPDATE COUNTERS AND*/
6928 /*       OTHER ATTRIBUTES WHICH ARE NOT SENSITIVE TO CONSISTE- */
6929 /*       NCY. THE SECOND SITUATION IS BY OPERATIONS THAT ARE   */
6930 /*       SENT AS PART OF A COPY FRAGMENT PROCESS.              */
6931 /*                                                             */
6932 /*       DURING A COPY FRAGMENT PROCESS THERE IS NO LOGGING    */
6933 /*       ONGOING SINCE THE FRAGMENT IS NOT COMPLETE YET. THE   */
6934 /*       LOGGING STARTS AFTER COMPLETING THE LAST COPY TUPLE   */
6935 /*       OPERATION. THE EXECUTION OF THE LAST COPY TUPLE DOES  */
6936 /*       ALSO START A LOCAL CHECKPOINT SO THAT THE FRAGMENT    */
6937 /*       REPLICA IS RECOVERABLE. THUS GLOBAL CHECKPOINT ID FOR */
6938 /*       THOSE OPERATIONS ARE NOT INTERESTING.                 */
6939 /*                                                             */
6940 /*       A DIRTY WRITE IS BY DEFINITION NOT CONSISTENT. THUS   */
6941 /*       IT CAN USE ANY GLOBAL CHECKPOINT. THE IDEA HERE IS TO */
6942 /*       ALWAYS USE THE LATEST DEFINED GLOBAL CHECKPOINT ID IN */
6943 /*       THIS NODE.                                            */
6944 /*************************************************************>*/
6945     cleanUp(signal);
6946     return;
6947   }//if
6948   /* ------------------------------------------------------------------------
6949    *   ALL INFORMATION NEEDED BY THE COMMIT PHASE AND COMPLETE PHASE IS
6950    *   KEPT IN THE TC_CONNECT RECORD. TO ENSURE PROPER USE OF MEMORY
6951    *   RESOURCES WE DEALLOCATE THE ATTRINFO RECORD AND KEY RECORDS
6952    *   AS SOON AS POSSIBLE.
6953    * ------------------------------------------------------------------------ */
6954   releaseOprec(signal);
6955 }//Dblqh::packLqhkeyreqLab()
6956 
6957 /* ========================================================================= */
6958 /* ==== CHECK IF THE LOG RECORD FITS INTO THE CURRENT MBYTE,         ======= */
6959 /*      OTHERWISE SWITCH TO NEXT MBYTE.                                      */
6960 /*                                                                           */
6961 /* ========================================================================= */
checkNewMbyte(Signal * signal)6962 void Dblqh::checkNewMbyte(Signal* signal)
6963 {
6964   UintR tcnmTmp;
6965   UintR ttotalLogSize;
6966 
6967 /* -------------------------------------------------- */
6968 /*       CHECK IF A NEW MBYTE OF LOG RECORD IS TO BE  */
6969 /*       OPENED BEFORE WRITING THE LOG RECORD. NO LOG */
6970 /*       RECORDS ARE ALLOWED TO SPAN A MBYTE BOUNDARY */
6971 /*                                                    */
6972 /*       INPUT:  TC_CONNECTPTR   THE OPERATION        */
6973 /*               LOG_FILE_PTR    THE LOG FILE         */
6974 /*       OUTPUT: LOG_FILE_PTR    THE NEW LOG FILE     */
6975 /* -------------------------------------------------- */
6976   ttotalLogSize = ZLOG_HEAD_SIZE + tcConnectptr.p->currTupAiLen;
6977   ttotalLogSize = ttotalLogSize + tcConnectptr.p->primKeyLen;
6978   tcnmTmp = logFilePtr.p->remainingWordsInMbyte;
6979   if ((ttotalLogSize + ZNEXT_LOG_SIZE) <= tcnmTmp) {
6980     ndbrequire(tcnmTmp >= ttotalLogSize);
6981     logFilePtr.p->remainingWordsInMbyte = tcnmTmp - ttotalLogSize;
6982     return;
6983   } else {
6984     jam();
6985 /* -------------------------------------------------- */
6986 /*       IT WAS NOT ENOUGH SPACE IN THIS MBYTE FOR    */
6987 /*       THIS LOG RECORD. MOVE TO NEXT MBYTE          */
6988 /*       THIS MIGHT INCLUDE CHANGING LOG FILE         */
6989 /* -------------------------------------------------- */
6990 /*       WE HAVE TO INSERT A NEXT LOG RECORD FIRST    */
6991 /* -------------------------------------------------- */
6992 /*       THEN CONTINUE BY WRITING THE FILE DESCRIPTORS*/
6993 /* -------------------------------------------------- */
6994     logPagePtr.i = logFilePtr.p->currentLogpage;
6995     ptrCheckGuard(logPagePtr, clogPageFileSize, logPageRecord);
6996     changeMbyte(signal);
6997     tcnmTmp = logFilePtr.p->remainingWordsInMbyte;
6998   }//if
6999   ndbrequire(tcnmTmp >= ttotalLogSize);
7000   logFilePtr.p->remainingWordsInMbyte = tcnmTmp - ttotalLogSize;
7001 }//Dblqh::checkNewMbyte()
7002 
7003 /* --------------------------------------------------------------------------
7004  * -------               WRITE OPERATION HEADER TO LOG                -------
7005  *
7006  *       SUBROUTINE SHORT NAME: WLH
7007  * ------------------------------------------------------------------------- */
writeLogHeader(Signal * signal)7008 void Dblqh::writeLogHeader(Signal* signal)
7009 {
7010   Uint32 logPos = logPagePtr.p->logPageWord[ZCURR_PAGE_INDEX];
7011   Uint32 hashValue = tcConnectptr.p->hashValue;
7012   Uint32 operation = tcConnectptr.p->operation;
7013   Uint32 keyLen = tcConnectptr.p->primKeyLen;
7014   Uint32 aiLen = tcConnectptr.p->currTupAiLen;
7015   Local_key rowid = tcConnectptr.p->m_row_id;
7016   Uint32 totLogLen = ZLOG_HEAD_SIZE + aiLen + keyLen;
7017 
7018   if ((logPos + ZLOG_HEAD_SIZE) < ZPAGE_SIZE) {
7019     Uint32* dataPtr = &logPagePtr.p->logPageWord[logPos];
7020     logPagePtr.p->logPageWord[ZCURR_PAGE_INDEX] = logPos + ZLOG_HEAD_SIZE;
7021     dataPtr[0] = ZPREP_OP_TYPE;
7022     dataPtr[1] = totLogLen;
7023     dataPtr[2] = hashValue;
7024     dataPtr[3] = operation;
7025     dataPtr[4] = aiLen;
7026     dataPtr[5] = keyLen;
7027     dataPtr[6] = rowid.m_page_no;
7028     dataPtr[7] = rowid.m_page_idx;
7029   } else {
7030     writeLogWord(signal, ZPREP_OP_TYPE);
7031     writeLogWord(signal, totLogLen);
7032     writeLogWord(signal, hashValue);
7033     writeLogWord(signal, operation);
7034     writeLogWord(signal, aiLen);
7035     writeLogWord(signal, keyLen);
7036     writeLogWord(signal, rowid.m_page_no);
7037     writeLogWord(signal, rowid.m_page_idx);
7038   }//if
7039 }//Dblqh::writeLogHeader()
7040 
7041 /* --------------------------------------------------------------------------
7042  * -------               WRITE TUPLE KEY TO LOG                       -------
7043  *
7044  *       SUBROUTINE SHORT NAME: WK
7045  * ------------------------------------------------------------------------- */
writeKey(Signal * signal)7046 void Dblqh::writeKey(Signal* signal)
7047 {
7048   TcConnectionrec * const regTcPtr = tcConnectptr.p;
7049   jam();
7050   SectionReader keyInfoReader(regTcPtr->keyInfoIVal,
7051                               g_sectionSegmentPool);
7052   const Uint32* srcPtr;
7053   Uint32 length;
7054   Uint32 wordsWritten= 0;
7055 
7056   /* Write contiguous chunks of words from the KeyInfo
7057    * section to the log
7058    */
7059   while (keyInfoReader.getWordsPtr(srcPtr,
7060                                    length))
7061   {
7062     writeLogWords(signal, srcPtr, length);
7063     wordsWritten+= length;
7064   }
7065 
7066   ndbassert( wordsWritten == regTcPtr->primKeyLen );
7067 }//Dblqh::writeKey()
7068 
7069 /* --------------------------------------------------------------------------
7070  * -------               WRITE ATTRINFO TO LOG                        -------
7071  *
7072  *       SUBROUTINE SHORT NAME: WA
7073  * ------------------------------------------------------------------------- */
writeAttrinfoLab(Signal * signal)7074 void Dblqh::writeAttrinfoLab(Signal* signal)
7075 {
7076   TcConnectionrec * const regTcPtr = tcConnectptr.p;
7077   Uint32 totLen = regTcPtr->currTupAiLen;
7078   if (totLen == 0)
7079     return;
7080 
7081   jam();
7082   ndbassert( regTcPtr->attrInfoIVal != RNIL );
7083   SectionReader attrInfoReader(regTcPtr->attrInfoIVal,
7084                                g_sectionSegmentPool);
7085   const Uint32* srcPtr;
7086   Uint32 length;
7087   Uint32 wordsWritten= 0;
7088 
7089   /* Write contiguous chunks of words from the
7090    * AttrInfo section to the log
7091    */
7092   while (attrInfoReader.getWordsPtr(srcPtr,
7093                                     length))
7094   {
7095     writeLogWords(signal, srcPtr, length);
7096     wordsWritten+= length;
7097   }
7098 
7099   ndbassert( wordsWritten == totLen );
7100 }//Dblqh::writeAttrinfoLab()
7101 
7102 /* ------------------------------------------------------------------------- */
7103 /* -------          SEND TUPLE KEY IN KEYINFO SIGNAL(S)              ------- */
7104 /*                                                                           */
7105 /*       SUBROUTINE SHORT NAME: STU                                          */
7106 /* ------------------------------------------------------------------------- */
sendTupkey(Signal * signal)7107 void Dblqh::sendTupkey(Signal* signal)
7108 {
7109   BlockReference lqhRef = 0;
7110   {
7111     // wl4391_todo fragptr
7112     FragrecordPtr Tfragptr;
7113     Tfragptr.i = tcConnectptr.p->fragmentptr;
7114     c_fragment_pool.getPtr(Tfragptr);
7115     Uint32 Tnode = tcConnectptr.p->nextReplica;
7116     Uint32 instanceKey = Tfragptr.p->lqhInstanceKey;
7117     lqhRef = numberToRef(DBLQH, instanceKey, Tnode);
7118   }
7119 
7120   signal->theData[0] = tcConnectptr.p->tcOprec;
7121   signal->theData[1] = tcConnectptr.p->transid[0];
7122   signal->theData[2] = tcConnectptr.p->transid[1];
7123 
7124   Uint32 remainingLen= tcConnectptr.p->primKeyLen -
7125     LqhKeyReq::MaxKeyInfo;
7126 
7127   SectionReader keyInfoReader(tcConnectptr.p->keyInfoIVal,
7128                               g_sectionSegmentPool);
7129 
7130   ndbassert(keyInfoReader.getSize() > LqhKeyReq::MaxKeyInfo);
7131 
7132   /* Step over the words already sent in LQHKEYREQ */
7133   keyInfoReader.step(LqhKeyReq::MaxKeyInfo);
7134 
7135   while (remainingLen != 0)
7136   {
7137     Uint32 dataInSignal= MIN(KeyInfo::DataLength, remainingLen);
7138     keyInfoReader.getWords(&signal->theData[3],
7139                            dataInSignal);
7140     remainingLen-= dataInSignal;
7141     sendSignal(lqhRef, GSN_KEYINFO, signal,
7142                KeyInfo::HeaderLength + dataInSignal, JBB);
7143   }
7144 }//Dblqh::sendTupkey()
7145 
cleanUp(Signal * signal)7146 void Dblqh::cleanUp(Signal* signal)
7147 {
7148   releaseOprec(signal);
7149   deleteTransidHash(signal);
7150   releaseTcrec(signal, tcConnectptr);
7151 }//Dblqh::cleanUp()
7152 
7153 /* --------------------------------------------------------------------------
7154  * ---- RELEASE ALL RECORDS CONNECTED TO THE OPERATION RECORD AND THE    ----
7155  *      OPERATION RECORD ITSELF
7156  * ------------------------------------------------------------------------- */
releaseOprec(Signal * signal)7157 void Dblqh::releaseOprec(Signal* signal)
7158 {
7159   TcConnectionrec * const regTcPtr = tcConnectptr.p;
7160 
7161   /* Release long sections if present */
7162   releaseSection(regTcPtr->keyInfoIVal);
7163   regTcPtr->keyInfoIVal = RNIL;
7164   releaseSection(regTcPtr->attrInfoIVal);
7165   regTcPtr->attrInfoIVal = RNIL;
7166 
7167   if (regTcPtr->m_dealloc)
7168   {
7169     jam();
7170     regTcPtr->m_dealloc = 0;
7171 
7172     if (TRACENR_FLAG)
7173       TRACENR("DELETED: " << regTcPtr->m_row_id << endl);
7174 
7175     TRACE_OP(regTcPtr, "DO DEALLOC");
7176 
7177     signal->theData[0] = regTcPtr->fragmentid;
7178     signal->theData[1] = regTcPtr->tableref;
7179     signal->theData[2] = regTcPtr->m_row_id.m_page_no;
7180     signal->theData[3] = regTcPtr->m_row_id.m_page_idx;
7181     signal->theData[4] = RNIL;
7182     EXECUTE_DIRECT(DBTUP, GSN_TUP_DEALLOCREQ, signal, 5);
7183   }
7184 }//Dblqh::releaseOprec()
7185 
7186 /* ------------------------------------------------------------------------- */
7187 /* ------         DELETE TRANSACTION ID FROM HASH TABLE              ------- */
7188 /*                                                                           */
7189 /* ------------------------------------------------------------------------- */
deleteTransidHash(Signal * signal)7190 void Dblqh::deleteTransidHash(Signal* signal)
7191 {
7192   TcConnectionrec * const regTcPtr = tcConnectptr.p;
7193   TcConnectionrecPtr prevHashptr;
7194   TcConnectionrecPtr nextHashptr;
7195 
7196   prevHashptr.i = regTcPtr->prevHashRec;
7197   nextHashptr.i = regTcPtr->nextHashRec;
7198   if (prevHashptr.i != RNIL) {
7199     jam();
7200     ptrCheckGuard(prevHashptr, ctcConnectrecFileSize, tcConnectionrec);
7201     prevHashptr.p->nextHashRec = nextHashptr.i;
7202   } else {
7203     jam();
7204 /* ------------------------------------------------------------------------- */
7205 /* THE OPERATION WAS PLACED FIRST IN THE LIST OF THE HASH TABLE. NEED TO SET */
7206 /* A NEW LEADER OF THE LIST.                                                 */
7207 /* ------------------------------------------------------------------------- */
7208     Uint32 hashIndex = (regTcPtr->transid[0] ^ regTcPtr->tcOprec) & 1023;
7209     ctransidHash[hashIndex] = nextHashptr.i;
7210   }//if
7211   if (nextHashptr.i != RNIL) {
7212     jam();
7213     ptrCheckGuard(nextHashptr, ctcConnectrecFileSize, tcConnectionrec);
7214     nextHashptr.p->prevHashRec = prevHashptr.i;
7215   }//if
7216 
7217   regTcPtr->prevHashRec = regTcPtr->nextHashRec = RNIL;
7218 }//Dblqh::deleteTransidHash()
7219 
7220 /* -------------------------------------------------------------------------
7221  * -------       RELEASE OPERATION FROM ACTIVE LIST ON FRAGMENT      -------
7222  *
7223  *       SUBROUTINE SHORT NAME = RAF
7224  * ------------------------------------------------------------------------- */
7225 /* ######################################################################### */
7226 /* #######                   TRANSACTION MODULE                      ####### */
7227 /*      THIS MODULE HANDLES THE COMMIT AND THE COMPLETE PHASE.               */
7228 /* ######################################################################### */
warningReport(Signal * signal,int place)7229 void Dblqh::warningReport(Signal* signal, int place)
7230 {
7231   switch (place) {
7232   case 0:
7233     jam();
7234 #ifdef ABORT_TRACE
7235     ndbout << "W: Received COMMIT in wrong state in Dblqh" << endl;
7236 #endif
7237     break;
7238   case 1:
7239     jam();
7240 #ifdef ABORT_TRACE
7241     ndbout << "W: Received COMMIT with wrong transid in Dblqh" << endl;
7242 #endif
7243     break;
7244   case 2:
7245     jam();
7246 #ifdef ABORT_TRACE
7247     ndbout << "W: Received COMPLETE in wrong state in Dblqh" << endl;
7248 #endif
7249     break;
7250   case 3:
7251     jam();
7252 #ifdef ABORT_TRACE
7253     ndbout << "W: Received COMPLETE with wrong transid in Dblqh" << endl;
7254 #endif
7255     break;
7256   case 4:
7257     jam();
7258 #ifdef ABORT_TRACE
7259     ndbout << "W: Received COMMITREQ in wrong state in Dblqh" << endl;
7260 #endif
7261     break;
7262   case 5:
7263     jam();
7264 #ifdef ABORT_TRACE
7265     ndbout << "W: Received COMMITREQ with wrong transid in Dblqh" << endl;
7266 #endif
7267     break;
7268   case 6:
7269     jam();
7270 #ifdef ABORT_TRACE
7271     ndbout << "W: Received COMPLETEREQ in wrong state in Dblqh" << endl;
7272 #endif
7273     break;
7274   case 7:
7275     jam();
7276 #ifdef ABORT_TRACE
7277     ndbout << "W: Received COMPLETEREQ with wrong transid in Dblqh" << endl;
7278 #endif
7279     break;
7280   case 8:
7281     jam();
7282 #ifdef ABORT_TRACE
7283     ndbout << "W: Received ABORT with non-existing transid in Dblqh" << endl;
7284 #endif
7285     break;
7286   case 9:
7287     jam();
7288 #ifdef ABORT_TRACE
7289     ndbout << "W: Received ABORTREQ with non-existing transid in Dblqh" << endl;
7290 #endif
7291     break;
7292   case 10:
7293     jam();
7294 #ifdef ABORT_TRACE
7295     ndbout << "W: Received ABORTREQ in wrong state in Dblqh" << endl;
7296 #endif
7297     break;
7298   case 11:
7299     jam();
7300 #ifdef ABORT_TRACE
7301     ndbout << "W: Received COMMIT when tc-rec released in Dblqh" << endl;
7302 #endif
7303     break;
7304   case 12:
7305     jam();
7306 #ifdef ABORT_TRACE
7307     ndbout << "W: Received COMPLETE when tc-rec released in Dblqh" << endl;
7308 #endif
7309     break;
7310   case 13:
7311     jam();
7312 #ifdef ABORT_TRACE
7313     ndbout << "W: Received LQHKEYREF when tc-rec released in Dblqh" << endl;
7314 #endif
7315     break;
7316   case 14:
7317     jam();
7318 #ifdef ABORT_TRACE
7319     ndbout << "W: Received LQHKEYREF with wrong transid in Dblqh" << endl;
7320 #endif
7321     break;
7322   case 15:
7323     jam();
7324 #ifdef ABORT_TRACE
7325     ndbout << "W: Received LQHKEYREF when already aborting in Dblqh" << endl;
7326 #endif
7327     break;
7328   case 16:
7329     jam();
7330     ndbrequire(cstartPhase == ZNIL);
7331 #ifdef ABORT_TRACE
7332     ndbout << "W: Received LQHKEYREF in wrong state in Dblqh" << endl;
7333 #endif
7334     break;
7335   default:
7336     jam();
7337     break;
7338   }//switch
7339   return;
7340 }//Dblqh::warningReport()
7341 
errorReport(Signal * signal,int place)7342 void Dblqh::errorReport(Signal* signal, int place)
7343 {
7344   switch (place) {
7345   case 0:
7346     jam();
7347     break;
7348   case 1:
7349     jam();
7350     break;
7351   case 2:
7352     jam();
7353     break;
7354   case 3:
7355     jam();
7356     break;
7357   default:
7358     jam();
7359     break;
7360   }//switch
7361   systemErrorLab(signal, __LINE__);
7362   return;
7363 }//Dblqh::errorReport()
7364 
7365 void
execFIRE_TRIG_REQ(Signal * signal)7366 Dblqh::execFIRE_TRIG_REQ(Signal* signal)
7367 {
7368   Uint32 tcOprec = signal->theData[0];
7369   Uint32 transid1 = signal->theData[1];
7370   Uint32 transid2 = signal->theData[2];
7371   Uint32 pass = signal->theData[3];
7372   Uint32 senderRef = signal->getSendersBlockRef();
7373 
7374   jamEntry();
7375 
7376   if (ERROR_INSERTED_CLEAR(5064))
7377   {
7378     // throw away...should cause timeout in TC
7379     return;
7380   }
7381 
7382   CRASH_INSERTION(5072);
7383 
7384   Uint32 err;
7385   if (findTransaction(transid1, transid2, tcOprec, 0) == ZOK &&
7386       !ERROR_INSERTED_CLEAR(5065) &&
7387       !ERROR_INSERTED(5070) &&
7388       !ERROR_INSERTED(5071))
7389   {
7390     TcConnectionrec * const regTcPtr = tcConnectptr.p;
7391 
7392     if (unlikely(regTcPtr->transactionState != TcConnectionrec::PREPARED ||
7393                  ERROR_INSERTED_CLEAR(5067)))
7394     {
7395       err = FireTrigRef::FTR_IncorrectState;
7396       goto do_err;
7397     }
7398 
7399     /**
7400      *
7401      */
7402     signal->theData[0] = regTcPtr->tupConnectrec;
7403     signal->theData[1] = regTcPtr->tcBlockref;
7404     signal->theData[2] = regTcPtr->tcOprec;
7405     signal->theData[3] = transid1;
7406     signal->theData[4] = transid2;
7407     signal->theData[5] = pass;
7408     Uint32 tup = refToMain(regTcPtr->tcTupBlockref);
7409     EXECUTE_DIRECT(tup, GSN_FIRE_TRIG_REQ, signal, 6);
7410 
7411     err = signal->theData[0];
7412     Uint32 cnt = signal->theData[1];
7413 
7414     if (ERROR_INSERTED_CLEAR(5066))
7415     {
7416       err = 5066;
7417     }
7418 
7419     if (ERROR_INSERTED_CLEAR(5068))
7420       tcOprec++;
7421     if (ERROR_INSERTED_CLEAR(5069))
7422       transid1++;
7423 
7424     if (err == 0)
7425     {
7426       jam();
7427       Uint32 Tdata[FireTrigConf::SignalLength];
7428       FireTrigConf * conf = CAST_PTR(FireTrigConf, Tdata);
7429       conf->tcOpRec = tcOprec;
7430       conf->transId[0] = transid1;
7431       conf->transId[1] = transid2;
7432       conf->noFiredTriggers = cnt;
7433       sendFireTrigConfTc(signal, regTcPtr->tcBlockref, Tdata);
7434       return;
7435     }
7436   }
7437   else
7438   {
7439     jam();
7440     err = FireTrigRef::FTR_UnknownOperation;
7441   }
7442 
7443 do_err:
7444   if (ERROR_INSERTED_CLEAR(5070))
7445     tcOprec++;
7446 
7447   if (ERROR_INSERTED_CLEAR(5071))
7448     transid1++;
7449 
7450   FireTrigRef * ref = CAST_PTR(FireTrigRef, signal->getDataPtrSend());
7451   ref->tcOpRec = tcOprec;
7452   ref->transId[0] = transid1;
7453   ref->transId[1] = transid2;
7454   ref->errCode = err;
7455   sendSignal(senderRef, GSN_FIRE_TRIG_REF,
7456              signal, FireTrigRef::SignalLength, JBB);
7457 
7458   return;
7459 }
7460 
7461 void
sendFireTrigConfTc(Signal * signal,BlockReference atcBlockref,Uint32 Tdata[])7462 Dblqh::sendFireTrigConfTc(Signal* signal,
7463                           BlockReference atcBlockref,
7464                           Uint32 Tdata[])
7465 {
7466   if (refToInstance(atcBlockref) != 0)
7467   {
7468     jam();
7469     memcpy(signal->theData, Tdata, 4 * FireTrigConf::SignalLength);
7470     sendSignal(atcBlockref, GSN_FIRE_TRIG_CONF,
7471                signal, FireTrigConf::SignalLength, JBB);
7472     return;
7473   }
7474 
7475   HostRecordPtr Thostptr;
7476   Uint32 len = FireTrigConf::SignalLength;
7477 
7478   Thostptr.i = refToNode(atcBlockref);
7479   ptrCheckGuard(Thostptr, chostFileSize, hostRecord);
7480 
7481   if (Thostptr.p->noOfPackedWordsTc > (25 - len))
7482   {
7483     jam();
7484     sendPackedSignalTc(signal, Thostptr.p);
7485   }
7486   else
7487   {
7488     jam();
7489     updatePackedList(signal, Thostptr.p, Thostptr.i);
7490   }
7491 
7492   ndbassert(FireTrigConf::SignalLength == 4);
7493   Uint32 * dst = &Thostptr.p->packedWordsTc[Thostptr.p->noOfPackedWordsTc];
7494   Thostptr.p->noOfPackedWordsTc += len;
7495   dst[0] = Tdata[0] | (ZFIRE_TRIG_CONF << 28);
7496   dst[1] = Tdata[1];
7497   dst[2] = Tdata[2];
7498   dst[3] = Tdata[3];
7499 }
7500 
7501 bool
check_fire_trig_pass(Uint32 opId,Uint32 pass)7502 Dblqh::check_fire_trig_pass(Uint32 opId, Uint32 pass)
7503 {
7504   /**
7505    * Check that trigger only fires once per pass
7506    *   (per primary key)
7507    */
7508   TcConnectionrecPtr regTcPtr;
7509   regTcPtr.i= opId;
7510   ptrCheckGuard(regTcPtr, ctcConnectrecFileSize, tcConnectionrec);
7511   if (regTcPtr.p->m_fire_trig_pass <= pass)
7512   {
7513     regTcPtr.p->m_fire_trig_pass = pass + 1;
7514     return true;
7515   }
7516   return false;
7517 }
7518 
7519 /* ************************************************************************>>
7520  *  COMMIT: Start commit request from TC. This signal is originally sent as a
7521  *  packed signal and this function is called from execPACKED_SIGNAL.
7522  *  This is the normal commit protocol where TC first send this signal to the
7523  *  backup node which then will send COMMIT to the primary node. If
7524  *  everything is ok the primary node send COMMITTED back to TC.
7525  * ************************************************************************>> */
execCOMMIT(Signal * signal)7526 void Dblqh::execCOMMIT(Signal* signal)
7527 {
7528   TcConnectionrec *regTcConnectionrec = tcConnectionrec;
7529   Uint32 ttcConnectrecFileSize = ctcConnectrecFileSize;
7530   Uint32 tcIndex = signal->theData[0];
7531   Uint32 gci_hi = signal->theData[1];
7532   Uint32 transid1 = signal->theData[2];
7533   Uint32 transid2 = signal->theData[3];
7534   Uint32 gci_lo = signal->theData[4];
7535   jamEntry();
7536   if (tcIndex >= ttcConnectrecFileSize) {
7537     errorReport(signal, 0);
7538     return;
7539   }//if
7540   if (ERROR_INSERTED(5011)) {
7541     CLEAR_ERROR_INSERT_VALUE;
7542     sendSignalWithDelay(cownref, GSN_COMMIT, signal, 2000,signal->getLength());
7543     return;
7544   }//if
7545   if (ERROR_INSERTED(5012)) {
7546     SET_ERROR_INSERT_VALUE(5017);
7547     sendSignalWithDelay(cownref, GSN_COMMIT, signal, 2000,signal->getLength());
7548     return;
7549   }//if
7550   if (ERROR_INSERTED(5062) &&
7551       ((refToMain(signal->getSendersBlockRef()) == DBTC) ||
7552        signal->getSendersBlockRef() == reference()))
7553   {
7554     Uint32 save = signal->getSendersBlockRef();
7555     ndbout_c("Delaying execCOMMIT");
7556     sendSignalWithDelay(cownref, GSN_COMMIT, signal, 2000, signal->getLength());
7557 
7558     if (refToMain(save) == DBTC)
7559     {
7560       ndbout_c("killing %u", refToNode(save));
7561       signal->theData[0] = 9999;
7562       sendSignal(numberToRef(CMVMI, refToNode(save)),
7563                  GSN_NDB_TAMPER, signal, 1, JBB);
7564     }
7565     return;
7566   }
7567 
7568   tcConnectptr.i = tcIndex;
7569   ptrAss(tcConnectptr, regTcConnectionrec);
7570   if ((tcConnectptr.p->transid[0] == transid1) &&
7571       (tcConnectptr.p->transid[1] == transid2)) {
7572 
7573     TcConnectionrec * const regTcPtr = tcConnectptr.p;
7574     TRACE_OP(regTcPtr, "COMMIT");
7575 
7576     CRASH_INSERTION(5048);
7577     if (ERROR_INSERTED(5049))
7578     {
7579       SET_ERROR_INSERT_VALUE(5048);
7580     }
7581 
7582     commitReqLab(signal, gci_hi, gci_lo);
7583     return;
7584   }//if
7585   warningReport(signal, 1);
7586   return;
7587 }//Dblqh::execCOMMIT()
7588 
7589 /* ************************************************************************>>
7590  *  COMMITREQ: Commit request from TC. This is the commit protocol used if
7591  *  one of the nodes is not behaving correctly. TC explicitly sends COMMITREQ
7592  *  to both the backup and primary node and gets a COMMITCONF back if the
7593  *  COMMIT was ok.
7594  * ************************************************************************>> */
execCOMMITREQ(Signal * signal)7595 void Dblqh::execCOMMITREQ(Signal* signal)
7596 {
7597   jamEntry();
7598   Uint32 reqPtr = signal->theData[0];
7599   BlockReference reqBlockref = signal->theData[1];
7600   Uint32 gci_hi = signal->theData[2];
7601   Uint32 transid1 = signal->theData[3];
7602   Uint32 transid2 = signal->theData[4];
7603   Uint32 tcOprec = signal->theData[6];
7604   Uint32 gci_lo = signal->theData[7];
7605 
7606   if (unlikely(signal->getLength() < 8))
7607   {
7608     jam();
7609     gci_lo = 0;
7610     ndbassert(!ndb_check_micro_gcp(getNodeInfo(refToNode(signal->getSendersBlockRef())).m_version));
7611   }
7612 
7613   if (ERROR_INSERTED(5004)) {
7614     systemErrorLab(signal, __LINE__);
7615   }
7616   if (ERROR_INSERTED(5017)) {
7617     CLEAR_ERROR_INSERT_VALUE;
7618     sendSignalWithDelay(cownref, GSN_COMMITREQ, signal, 2000,
7619                         signal->getLength());
7620     return;
7621   }//if
7622   if (findTransaction(transid1,
7623                       transid2,
7624                       tcOprec, 0) != ZOK) {
7625     warningReport(signal, 5);
7626     return;
7627   }//if
7628   TcConnectionrec * const regTcPtr = tcConnectptr.p;
7629   switch (regTcPtr->transactionState) {
7630   case TcConnectionrec::PREPARED:
7631   case TcConnectionrec::LOG_COMMIT_QUEUED_WAIT_SIGNAL:
7632   case TcConnectionrec::LOG_COMMIT_WRITTEN_WAIT_SIGNAL:
7633     jam();
7634 /*-------------------------------------------------------*/
7635 /*       THE NORMAL CASE.                                */
7636 /*-------------------------------------------------------*/
7637     regTcPtr->reqBlockref = reqBlockref;
7638     regTcPtr->reqRef = reqPtr;
7639     regTcPtr->abortState = TcConnectionrec::REQ_FROM_TC;
7640     commitReqLab(signal, gci_hi, gci_lo);
7641     return;
7642     break;
7643   case TcConnectionrec::COMMITTED:
7644     jam();
7645 /*---------------------------------------------------------*/
7646 /*       FOR SOME REASON THE COMMIT PHASE HAVE BEEN        */
7647 /*       FINISHED AFTER A TIME OUT. WE NEED ONLY SEND A    */
7648 /*       COMMITCONF SIGNAL.                                */
7649 /*---------------------------------------------------------*/
7650     regTcPtr->reqBlockref = reqBlockref;
7651     regTcPtr->reqRef = reqPtr;
7652     regTcPtr->abortState = TcConnectionrec::REQ_FROM_TC;
7653     signal->theData[0] = regTcPtr->reqRef;
7654     signal->theData[1] = cownNodeid;
7655     signal->theData[2] = regTcPtr->transid[0];
7656     signal->theData[3] = regTcPtr->transid[1];
7657     sendSignal(regTcPtr->reqBlockref, GSN_COMMITCONF, signal, 4, JBB);
7658     break;
7659   case TcConnectionrec::COMMIT_STOPPED:
7660   case TcConnectionrec::WAIT_TUP_COMMIT:
7661     jam();
7662     regTcPtr->reqBlockref = reqBlockref;
7663     regTcPtr->reqRef = reqPtr;
7664     regTcPtr->abortState = TcConnectionrec::REQ_FROM_TC;
7665     /*empty*/;
7666     break;
7667   default:
7668     jam();
7669     warningReport(signal, 4);
7670     return;
7671     break;
7672   }//switch
7673   return;
7674 }//Dblqh::execCOMMITREQ()
7675 
7676 /* ************************************************************************>>
7677  *  COMPLETE : Complete the transaction. Sent as a packed signal from TC.
7678  *  Works the same way as COMMIT protocol. This is the normal case with both
7679  *  primary and backup working (See COMMIT).
7680  * ************************************************************************>> */
execCOMPLETE(Signal * signal)7681 void Dblqh::execCOMPLETE(Signal* signal)
7682 {
7683   TcConnectionrec *regTcConnectionrec = tcConnectionrec;
7684   Uint32 ttcConnectrecFileSize = ctcConnectrecFileSize;
7685   Uint32 tcIndex = signal->theData[0];
7686   Uint32 transid1 = signal->theData[1];
7687   Uint32 transid2 = signal->theData[2];
7688   jamEntry();
7689   if (tcIndex >= ttcConnectrecFileSize) {
7690     errorReport(signal, 1);
7691     return;
7692   }//if
7693   CRASH_INSERTION(5042);
7694 
7695   if (ERROR_INSERTED(5013)) {
7696     CLEAR_ERROR_INSERT_VALUE;
7697     sendSignalWithDelay(cownref, GSN_COMPLETE, signal, 2000, 3);
7698     return;
7699   }//if
7700   if (ERROR_INSERTED(5014)) {
7701     SET_ERROR_INSERT_VALUE(5018);
7702     sendSignalWithDelay(cownref, GSN_COMPLETE, signal, 2000, 3);
7703     return;
7704   }//if
7705   if (ERROR_INSERTED(5063) &&
7706       ((refToMain(signal->getSendersBlockRef()) == DBTC) ||
7707        signal->getSendersBlockRef() == reference()))
7708   {
7709     Uint32 save = signal->getSendersBlockRef();
7710     ndbout_c("Delaying execCOMPLETE");
7711     sendSignalWithDelay(cownref, GSN_COMPLETE,signal, 2000,signal->getLength());
7712 
7713     if (refToMain(save) == DBTC)
7714     {
7715       ndbout_c("killing %u", refToNode(save));
7716       signal->theData[0] = 9999;
7717       sendSignal(numberToRef(CMVMI, refToNode(save)),
7718                  GSN_NDB_TAMPER, signal, 1, JBB);
7719     }
7720     return;
7721   }
7722 
7723   tcConnectptr.i = tcIndex;
7724   ptrAss(tcConnectptr, regTcConnectionrec);
7725   if ((tcConnectptr.p->transactionState == TcConnectionrec::COMMITTED) &&
7726       (tcConnectptr.p->transid[0] == transid1) &&
7727       (tcConnectptr.p->transid[1] == transid2)) {
7728 
7729     TcConnectionrec * const regTcPtr = tcConnectptr.p;
7730     TRACE_OP(regTcPtr, "COMPLETE");
7731 
7732     if (tcConnectptr.p->seqNoReplica != 0 &&
7733 	tcConnectptr.p->activeCreat == Fragrecord::AC_NORMAL) {
7734       jam();
7735       localCommitLab(signal);
7736       return;
7737     }
7738     else if (tcConnectptr.p->seqNoReplica == 0)
7739     {
7740       jam();
7741       completeTransLastLab(signal);
7742       return;
7743     }
7744     else
7745     {
7746       jam();
7747       completeTransNotLastLab(signal);
7748       return;
7749     }
7750   }//if
7751   if (tcConnectptr.p->transactionState != TcConnectionrec::COMMITTED) {
7752     warningReport(signal, 2);
7753   } else {
7754     warningReport(signal, 3);
7755   }//if
7756 }//Dblqh::execCOMPLETE()
7757 
7758 /* ************************************************************************>>
7759  * COMPLETEREQ: Complete request from TC. Same as COMPLETE but used if one
7760  * node is not working ok (See COMMIT).
7761  * ************************************************************************>> */
execCOMPLETEREQ(Signal * signal)7762 void Dblqh::execCOMPLETEREQ(Signal* signal)
7763 {
7764   jamEntry();
7765   Uint32 reqPtr = signal->theData[0];
7766   BlockReference reqBlockref = signal->theData[1];
7767   Uint32 transid1 = signal->theData[2];
7768   Uint32 transid2 = signal->theData[3];
7769   Uint32 tcOprec = signal->theData[5];
7770   if (ERROR_INSERTED(5005)) {
7771     systemErrorLab(signal, __LINE__);
7772   }
7773   if (ERROR_INSERTED(5018)) {
7774     CLEAR_ERROR_INSERT_VALUE;
7775     sendSignalWithDelay(cownref, GSN_COMPLETEREQ, signal, 2000, 6);
7776     return;
7777   }//if
7778   if (findTransaction(transid1,
7779                       transid2,
7780                       tcOprec, 0) != ZOK) {
7781     jam();
7782 /*---------------------------------------------------------*/
7783 /*       FOR SOME REASON THE COMPLETE PHASE STARTED AFTER  */
7784 /*       A TIME OUT. THE TRANSACTION IS GONE. WE NEED TO   */
7785 /*       REPORT COMPLETION ANYWAY.                         */
7786 /*---------------------------------------------------------*/
7787     signal->theData[0] = reqPtr;
7788     signal->theData[1] = cownNodeid;
7789     signal->theData[2] = transid1;
7790     signal->theData[3] = transid2;
7791     sendSignal(reqBlockref, GSN_COMPLETECONF, signal, 4, JBB);
7792     warningReport(signal, 7);
7793     return;
7794   }//if
7795   TcConnectionrec * const regTcPtr = tcConnectptr.p;
7796   switch (regTcPtr->transactionState) {
7797   case TcConnectionrec::COMMITTED:
7798     jam();
7799     regTcPtr->reqBlockref = reqBlockref;
7800     regTcPtr->reqRef = reqPtr;
7801     regTcPtr->abortState = TcConnectionrec::REQ_FROM_TC;
7802     /*empty*/;
7803     break;
7804 /*---------------------------------------------------------*/
7805 /*       THE NORMAL CASE.                                  */
7806 /*---------------------------------------------------------*/
7807   case TcConnectionrec::COMMIT_STOPPED:
7808   case TcConnectionrec::WAIT_TUP_COMMIT:
7809     jam();
7810 /*---------------------------------------------------------*/
7811 /*       FOR SOME REASON THE COMPLETE PHASE STARTED AFTER  */
7812 /*       A TIME OUT. WE HAVE SET THE PROPER VARIABLES SUCH */
7813 /*       THAT A COMPLETECONF WILL BE SENT WHEN COMPLETE IS */
7814 /*       FINISHED.                                         */
7815 /*---------------------------------------------------------*/
7816     regTcPtr->reqBlockref = reqBlockref;
7817     regTcPtr->reqRef = reqPtr;
7818     regTcPtr->abortState = TcConnectionrec::REQ_FROM_TC;
7819     return;
7820     break;
7821   default:
7822     jam();
7823     warningReport(signal, 6);
7824     return;
7825     break;
7826   }//switch
7827   if (regTcPtr->seqNoReplica != 0 &&
7828       regTcPtr->activeCreat != Fragrecord::AC_NR_COPY) {
7829     jam();
7830     localCommitLab(signal);
7831   }
7832   else if (regTcPtr->seqNoReplica == 0)
7833   {
7834     jam();
7835     completeTransLastLab(signal);
7836   }
7837   else
7838   {
7839     jam();
7840     completeTransNotLastLab(signal);
7841   }
7842 }//Dblqh::execCOMPLETEREQ()
7843 
7844 /* ************> */
7845 /*  COMPLETED  > */
7846 /* ************> */
execLQHKEYCONF(Signal * signal)7847 void Dblqh::execLQHKEYCONF(Signal* signal)
7848 {
7849   LqhKeyConf * const lqhKeyConf = (LqhKeyConf *)signal->getDataPtr();
7850   Uint32 tcIndex = lqhKeyConf->opPtr;
7851   Uint32 ttcConnectrecFileSize = ctcConnectrecFileSize;
7852   TcConnectionrec *regTcConnectionrec = tcConnectionrec;
7853   jamEntry();
7854   if (tcIndex >= ttcConnectrecFileSize) {
7855     errorReport(signal, 2);
7856     return;
7857   }//if
7858   tcConnectptr.i = tcIndex;
7859   ptrAss(tcConnectptr, regTcConnectionrec);
7860   switch (tcConnectptr.p->connectState) {
7861   case TcConnectionrec::LOG_CONNECTED:
7862     jam();
7863     completedLab(signal);
7864     return;
7865     break;
7866   case TcConnectionrec::COPY_CONNECTED:
7867     jam();
7868     copyCompletedLab(signal);
7869     return;
7870     break;
7871   default:
7872     jamLine(tcConnectptr.p->connectState);
7873     ndbrequire(false);
7874     break;
7875   }//switch
7876   return;
7877 }//Dblqh::execLQHKEYCONF()
7878 
7879 /* ------------------------------------------------------------------------- */
7880 /* -------                       COMMIT PHASE                        ------- */
7881 /*                                                                           */
7882 /* ------------------------------------------------------------------------- */
commitReqLab(Signal * signal,Uint32 gci_hi,Uint32 gci_lo)7883 void Dblqh::commitReqLab(Signal* signal, Uint32 gci_hi, Uint32 gci_lo)
7884 {
7885   TcConnectionrec * const regTcPtr = tcConnectptr.p;
7886   TcConnectionrec::LogWriteState logWriteState = regTcPtr->logWriteState;
7887   TcConnectionrec::TransactionState transState = regTcPtr->transactionState;
7888   regTcPtr->gci_hi = gci_hi;
7889   regTcPtr->gci_lo = gci_lo;
7890   if (transState == TcConnectionrec::PREPARED) {
7891     if (logWriteState == TcConnectionrec::WRITTEN) {
7892       jam();
7893       regTcPtr->transactionState = TcConnectionrec::PREPARED_RECEIVED_COMMIT;
7894       TcConnectionrecPtr saveTcPtr = tcConnectptr;
7895       Uint32 blockNo = refToMain(regTcPtr->tcTupBlockref);
7896       signal->theData[0] = regTcPtr->tupConnectrec;
7897       signal->theData[1] = gci_hi;
7898       signal->theData[2] = gci_lo;
7899       EXECUTE_DIRECT(blockNo, GSN_TUP_WRITELOG_REQ, signal, 3);
7900       jamEntry();
7901       if (regTcPtr->transactionState == TcConnectionrec::LOG_COMMIT_QUEUED) {
7902         jam();
7903         return;
7904       }//if
7905       ndbrequire(regTcPtr->transactionState == TcConnectionrec::LOG_COMMIT_WRITTEN);
7906       tcConnectptr = saveTcPtr;
7907     } else if (logWriteState == TcConnectionrec::NOT_STARTED) {
7908       jam();
7909     } else if (logWriteState == TcConnectionrec::NOT_WRITTEN) {
7910       jam();
7911 /*---------------------------------------------------------------------------*/
7912 /* IT IS A READ OPERATION OR OTHER OPERATION THAT DO NOT USE THE LOG.        */
7913 /*---------------------------------------------------------------------------*/
7914 /*---------------------------------------------------------------------------*/
7915 /* THE LOG HAS NOT BEEN WRITTEN SINCE THE LOG FLAG WAS FALSE. THIS CAN OCCUR */
7916 /* WHEN WE ARE STARTING A NEW FRAGMENT.                                      */
7917 /*---------------------------------------------------------------------------*/
7918       regTcPtr->logWriteState = TcConnectionrec::NOT_STARTED;
7919     } else {
7920       ndbrequire(logWriteState == TcConnectionrec::NOT_WRITTEN_WAIT);
7921       jam();
7922 /*---------------------------------------------------------------------------*/
7923 /* THE STATE WAS SET TO NOT_WRITTEN BY THE OPERATION BUT LATER A SCAN OF ALL */
7924 /* OPERATION RECORD CHANGED IT INTO NOT_WRITTEN_WAIT. THIS INDICATES THAT WE */
7925 /* ARE WAITING FOR THIS OPERATION TO COMMIT OR ABORT SO THAT WE CAN FIND THE */
7926 /* STARTING GLOBAL CHECKPOINT OF THIS NEW FRAGMENT.                          */
7927 /*---------------------------------------------------------------------------*/
7928       checkScanTcCompleted(signal);
7929     }//if
7930   } else if (transState == TcConnectionrec::LOG_COMMIT_QUEUED_WAIT_SIGNAL) {
7931     jam();
7932     regTcPtr->transactionState = TcConnectionrec::LOG_COMMIT_QUEUED;
7933     return;
7934   } else if (transState == TcConnectionrec::LOG_COMMIT_WRITTEN_WAIT_SIGNAL) {
7935     jam();
7936   } else {
7937     warningReport(signal, 0);
7938     return;
7939   }//if
7940   if (regTcPtr->seqNoReplica == 0 ||
7941       regTcPtr->activeCreat == Fragrecord::AC_NR_COPY) {
7942     jam();
7943     localCommitLab(signal);
7944     return;
7945   }//if
7946   commitReplyLab(signal);
7947   return;
7948 }//Dblqh::commitReqLab()
7949 
execLQH_WRITELOG_REQ(Signal * signal)7950 void Dblqh::execLQH_WRITELOG_REQ(Signal* signal)
7951 {
7952   jamEntry();
7953   tcConnectptr.i = signal->theData[0];
7954   ptrCheckGuard(tcConnectptr, ctcConnectrecFileSize, tcConnectionrec);
7955   TcConnectionrec * const regTcPtr = tcConnectptr.p;
7956   Uint32 gci_hi = signal->theData[1];
7957   Uint32 gci_lo = signal->theData[2];
7958   Uint32 newestGci = cnewestGci;
7959   TcConnectionrec::LogWriteState logWriteState = regTcPtr->logWriteState;
7960   TcConnectionrec::TransactionState transState = regTcPtr->transactionState;
7961   regTcPtr->gci_hi = gci_hi;
7962   regTcPtr->gci_lo = gci_lo;
7963   if (gci_hi > newestGci) {
7964     jam();
7965 /* ------------------------------------------------------------------------- */
7966 /*       KEEP TRACK OF NEWEST GLOBAL CHECKPOINT THAT LQH HAS HEARD OF.       */
7967 /* ------------------------------------------------------------------------- */
7968     cnewestGci = gci_hi;
7969   }//if
7970   if (logWriteState == TcConnectionrec::WRITTEN) {
7971 /*---------------------------------------------------------------------------*/
7972 /* I NEED TO INSERT A COMMIT LOG RECORD SINCE WE ARE WRITING LOG IN THIS     */
7973 /* TRANSACTION.                                                              */
7974 /*---------------------------------------------------------------------------*/
7975     jam();
7976     LogPartRecordPtr regLogPartPtr;
7977     Uint32 noOfLogPages = cnoOfLogPages;
7978     jam();
7979     regLogPartPtr.i = regTcPtr->m_log_part_ptr_i;
7980     ptrCheckGuard(regLogPartPtr, clogPartFileSize, logPartRecord);
7981     if (!regLogPartPtr.p->m_log_complete_queue.isEmpty() ||
7982         (noOfLogPages == 0))
7983     {
7984       jam();
7985 /*---------------------------------------------------------------------------*/
7986 /* THIS LOG PART WAS CURRENTLY ACTIVE WRITING ANOTHER LOG RECORD. WE MUST    */
7987 /* WAIT UNTIL THIS PART HAS COMPLETED ITS OPERATION.                         */
7988 /*---------------------------------------------------------------------------*/
7989 // We must delay the write of commit info to the log to safe-guard against
7990 // a crash due to lack of log pages. We temporary stop all log writes to this
7991 // log part to ensure that we don't get a buffer explosion in the delayed
7992 // signal buffer instead.
7993 /*---------------------------------------------------------------------------*/
7994       linkWaitLog(signal, regLogPartPtr, regLogPartPtr.p->m_log_complete_queue);
7995       if (transState == TcConnectionrec::PREPARED) {
7996         jam();
7997         regTcPtr->transactionState = TcConnectionrec::LOG_COMMIT_QUEUED_WAIT_SIGNAL;
7998       } else {
7999         jam();
8000         ndbrequire(transState == TcConnectionrec::PREPARED_RECEIVED_COMMIT);
8001         regTcPtr->transactionState = TcConnectionrec::LOG_COMMIT_QUEUED;
8002       }//if
8003       return;
8004     }//if
8005     writeCommitLog(signal, regLogPartPtr);
8006     if (transState == TcConnectionrec::PREPARED) {
8007       jam();
8008       regTcPtr->transactionState = TcConnectionrec::LOG_COMMIT_WRITTEN_WAIT_SIGNAL;
8009     } else {
8010       jam();
8011       ndbrequire(transState == TcConnectionrec::PREPARED_RECEIVED_COMMIT);
8012       regTcPtr->transactionState = TcConnectionrec::LOG_COMMIT_WRITTEN;
8013     }//if
8014   }//if
8015 }//Dblqh::execLQH_WRITELOG_REQ()
8016 
localCommitLab(Signal * signal)8017 void Dblqh::localCommitLab(Signal* signal)
8018 {
8019   FragrecordPtr regFragptr;
8020   regFragptr.i = tcConnectptr.p->fragmentptr;
8021   c_fragment_pool.getPtr(regFragptr);
8022   Fragrecord::FragStatus status = regFragptr.p->fragStatus;
8023   fragptr = regFragptr;
8024   switch (status) {
8025   case Fragrecord::FSACTIVE:
8026   case Fragrecord::CRASH_RECOVERING:
8027   case Fragrecord::ACTIVE_CREATION:
8028     jam();
8029     commitContinueAfterBlockedLab(signal);
8030     return;
8031     break;
8032   case Fragrecord::BLOCKED:
8033     jam();
8034     linkFragQueue(signal);
8035     tcConnectptr.p->transactionState = TcConnectionrec::COMMIT_STOPPED;
8036     break;
8037   case Fragrecord::FREE:
8038     jam();
8039   case Fragrecord::DEFINED:
8040     jam();
8041   case Fragrecord::REMOVING:
8042     jam();
8043   default:
8044     ndbrequire(false);
8045     break;
8046   }//switch
8047 }//Dblqh::localCommitLab()
8048 
commitContinueAfterBlockedLab(Signal * signal)8049 void Dblqh::commitContinueAfterBlockedLab(Signal* signal)
8050 {
8051 /* ------------------------------------------------------------------------- */
8052 /*INPUT:          TC_CONNECTPTR           ACTIVE OPERATION RECORD            */
8053 /* ------------------------------------------------------------------------- */
8054 /* ------------------------------------------------------------------------- */
8055 /*CONTINUE HERE AFTER BEING BLOCKED FOR A WHILE DURING LOCAL CHECKPOINT.     */
8056 /*The operation is already removed from the active list since there is no    */
8057 /*chance for any real-time breaks before we need to release it.              */
8058 /* ------------------------------------------------------------------------- */
8059 /*ALSO AFTER NORMAL PROCEDURE WE CONTINUE                                    */
8060 /*WE MUST COMMIT TUP BEFORE ACC TO ENSURE THAT NO ONE RACES IN AND SEES A    */
8061 /*DIRTY STATE IN TUP.                                                        */
8062 /* ------------------------------------------------------------------------- */
8063   Ptr<TcConnectionrec> regTcPtr = tcConnectptr;
8064   Ptr<Fragrecord> regFragptr = fragptr;
8065   Uint32 operation = regTcPtr.p->operation;
8066   Uint32 dirtyOp = regTcPtr.p->dirtyOp;
8067   Uint32 opSimple = regTcPtr.p->opSimple;
8068   Uint32 normalProtocol = LqhKeyReq::getNormalProtocolFlag(regTcPtr.p->reqinfo);
8069 
8070   if (regTcPtr.p->activeCreat != Fragrecord::AC_IGNORED) {
8071     if (operation != ZREAD) {
8072       TupCommitReq * const tupCommitReq =
8073         (TupCommitReq *)signal->getDataPtrSend();
8074       Uint32 sig0 = regTcPtr.p->tupConnectrec;
8075       Uint32 tup = refToMain(regTcPtr.p->tcTupBlockref);
8076       jam();
8077       tupCommitReq->opPtr = sig0;
8078       tupCommitReq->gci_hi = regTcPtr.p->gci_hi;
8079       tupCommitReq->hashValue = regTcPtr.p->hashValue;
8080       tupCommitReq->diskpage = RNIL;
8081       tupCommitReq->gci_lo = regTcPtr.p->gci_lo;
8082       tupCommitReq->transId1 = regTcPtr.p->transid[0];
8083       tupCommitReq->transId2 = regTcPtr.p->transid[1];
8084       EXECUTE_DIRECT(tup, GSN_TUP_COMMITREQ, signal,
8085 		     TupCommitReq::SignalLength);
8086 
8087       if (TRACENR_FLAG)
8088       {
8089 	TRACENR("COMMIT: ");
8090 	switch (regTcPtr.p->operation) {
8091 	case ZREAD: TRACENR("READ"); break;
8092 	case ZUPDATE: TRACENR("UPDATE"); break;
8093 	case ZWRITE: TRACENR("WRITE"); break;
8094 	case ZINSERT: TRACENR("INSERT"); break;
8095 	case ZDELETE: TRACENR("DELETE"); break;
8096         case ZUNLOCK: TRACENR("UNLOCK"); break;
8097 	}
8098 
8099 	TRACENR(" tab: " << regTcPtr.p->tableref
8100 	       << " frag: " << regTcPtr.p->fragmentid
8101 	       << " activeCreat: " << (Uint32)regTcPtr.p->activeCreat);
8102 	if (LqhKeyReq::getNrCopyFlag(regTcPtr.p->reqinfo))
8103 	  TRACENR(" NrCopy");
8104 	if (LqhKeyReq::getRowidFlag(regTcPtr.p->reqinfo))
8105 	  TRACENR(" rowid: " << regTcPtr.p->m_row_id);
8106 	TRACENR(" key: " << getKeyInfoWordOrZero(regTcPtr.p, 0));
8107 
8108         if (signal->theData[0] != 0)
8109           TRACENR(" TIMESLICE");
8110 	TRACENR(endl);
8111       }
8112 
8113       if(signal->theData[0] != 0)
8114       {
8115         regTcPtr.p->transactionState = TcConnectionrec::WAIT_TUP_COMMIT;
8116         return; // TUP_COMMIT was timesliced
8117       }
8118 
8119       TRACE_OP(regTcPtr.p, "ACC_COMMITREQ");
8120 
8121       Uint32 acc = refToMain(regTcPtr.p->tcAccBlockref);
8122       signal->theData[0] = regTcPtr.p->accConnectrec;
8123       EXECUTE_DIRECT(acc, GSN_ACC_COMMITREQ, signal, 1);
8124 
8125     } else {
8126       if(!dirtyOp){
8127 	TRACE_OP(regTcPtr.p, "ACC_COMMITREQ");
8128 
8129 	Uint32 acc = refToMain(regTcPtr.p->tcAccBlockref);
8130 	signal->theData[0] = regTcPtr.p->accConnectrec;
8131 	EXECUTE_DIRECT(acc, GSN_ACC_COMMITREQ, signal, 1);
8132       }
8133 
8134       if (dirtyOp && normalProtocol == 0)
8135       {
8136 	jam();
8137         /**
8138          * The dirtyRead does not send anything but TRANSID_AI from LDM
8139          */
8140 	fragptr = regFragptr;
8141 	tcConnectptr = regTcPtr;
8142 	cleanUp(signal);
8143 	return;
8144       }
8145 
8146       /**
8147        * The simpleRead will send a LQHKEYCONF
8148        *   but have already released the locks
8149        */
8150       if (opSimple)
8151       {
8152 	fragptr = regFragptr;
8153 	tcConnectptr = regTcPtr;
8154         packLqhkeyreqLab(signal);
8155         return;
8156       }
8157     }
8158   }//if
8159   jamEntry();
8160   fragptr = regFragptr;
8161   tcConnectptr = regTcPtr;
8162   tupcommit_conf(signal, regTcPtr.p, regFragptr.p);
8163 }
8164 
8165 void
tupcommit_conf_callback(Signal * signal,Uint32 tcPtrI)8166 Dblqh::tupcommit_conf_callback(Signal* signal, Uint32 tcPtrI)
8167 {
8168   jamEntry();
8169 
8170   tcConnectptr.i = tcPtrI;
8171   ptrCheckGuard(tcConnectptr, ctcConnectrecFileSize, tcConnectionrec);
8172   TcConnectionrec * tcPtr = tcConnectptr.p;
8173 
8174   ndbrequire(tcPtr->transactionState == TcConnectionrec::WAIT_TUP_COMMIT);
8175 
8176   FragrecordPtr regFragptr;
8177   regFragptr.i = tcPtr->fragmentptr;
8178   c_fragment_pool.getPtr(regFragptr);
8179   fragptr = regFragptr;
8180 
8181   TRACE_OP(tcPtr, "ACC_COMMITREQ");
8182 
8183   Uint32 acc = refToMain(tcPtr->tcAccBlockref);
8184   signal->theData[0] = tcPtr->accConnectrec;
8185   EXECUTE_DIRECT(acc, GSN_ACC_COMMITREQ, signal, 1);
8186   jamEntry();
8187 
8188   tcConnectptr.i = tcPtrI;
8189   tcConnectptr.p = tcPtr;
8190   tupcommit_conf(signal, tcPtr, regFragptr.p);
8191 }
8192 
8193 void
tupcommit_conf(Signal * signal,TcConnectionrec * tcPtrP,Fragrecord * regFragptr)8194 Dblqh::tupcommit_conf(Signal* signal,
8195 		      TcConnectionrec * tcPtrP,
8196 		      Fragrecord * regFragptr)
8197 {
8198   Uint32 dirtyOp = tcPtrP->dirtyOp;
8199   Uint32 seqNoReplica = tcPtrP->seqNoReplica;
8200   Uint32 activeCreat = tcPtrP->activeCreat;
8201   if (tcPtrP->gci_hi > regFragptr->newestGci) {
8202     jam();
8203 /* ------------------------------------------------------------------------- */
8204 /*IT IS THE FIRST TIME THIS GLOBAL CHECKPOINT IS INVOLVED IN UPDATING THIS   */
8205 /*FRAGMENT. UPDATE THE VARIABLE THAT KEEPS TRACK OF NEWEST GCI IN FRAGMENT   */
8206 /* ------------------------------------------------------------------------- */
8207     regFragptr->newestGci = tcPtrP->gci_hi;
8208   }//if
8209   if (dirtyOp != ZTRUE)
8210   {
8211     if (seqNoReplica == 0 || activeCreat == Fragrecord::AC_NR_COPY)
8212     {
8213       jam();
8214       commitReplyLab(signal);
8215       return;
8216     }//if
8217     if (seqNoReplica == 0)
8218     {
8219       jam();
8220       completeTransLastLab(signal);
8221     }
8222     else
8223     {
8224       jam();
8225       completeTransNotLastLab(signal);
8226     }
8227     return;
8228   } else {
8229 /* ------------------------------------------------------------------------- */
8230 /*WE MUST HANDLE DIRTY WRITES IN A SPECIAL WAY. THESE OPERATIONS WILL NOT    */
8231 /*SEND ANY COMMIT OR COMPLETE MESSAGES TO OTHER NODES. THEY WILL MERELY SEND */
8232 /*THOSE SIGNALS INTERNALLY.                                                  */
8233 /* ------------------------------------------------------------------------- */
8234     if (tcPtrP->abortState == TcConnectionrec::ABORT_IDLE)
8235     {
8236       jam();
8237       if (activeCreat == Fragrecord::AC_NR_COPY)
8238       {
8239 	jam();
8240 	ndbrequire(LqhKeyReq::getNrCopyFlag(tcPtrP->reqinfo));
8241 	ndbrequire(tcPtrP->m_nr_delete.m_cnt == 0);
8242       }
8243       packLqhkeyreqLab(signal);
8244     }
8245     else
8246     {
8247       ndbrequire(tcPtrP->abortState != TcConnectionrec::NEW_FROM_TC);
8248       jam();
8249       sendLqhTransconf(signal, LqhTransConf::Committed);
8250       cleanUp(signal);
8251     }//if
8252   }//if
8253 }//Dblqh::commitContinueAfterBlockedLab()
8254 
commitReplyLab(Signal * signal)8255 void Dblqh::commitReplyLab(Signal* signal)
8256 {
8257 /* -------------------------------------------------------------- */
8258 /* BACKUP AND STAND-BY REPLICAS ONLY UPDATE THE TRANSACTION STATE */
8259 /* -------------------------------------------------------------- */
8260   TcConnectionrec * const regTcPtr = tcConnectptr.p;
8261   TcConnectionrec::AbortState abortState = regTcPtr->abortState;
8262   regTcPtr->transactionState = TcConnectionrec::COMMITTED;
8263   if (abortState == TcConnectionrec::ABORT_IDLE) {
8264     Uint32 clientBlockref = regTcPtr->clientBlockref;
8265     if (regTcPtr->seqNoReplica == 0) {
8266       jam();
8267       sendCommittedTc(signal, clientBlockref);
8268       return;
8269     } else {
8270       jam();
8271       sendCommitLqh(signal, clientBlockref);
8272       return;
8273     }//if
8274   } else if (regTcPtr->abortState == TcConnectionrec::REQ_FROM_TC) {
8275     jam();
8276     signal->theData[0] = regTcPtr->reqRef;
8277     signal->theData[1] = cownNodeid;
8278     signal->theData[2] = regTcPtr->transid[0];
8279     signal->theData[3] = regTcPtr->transid[1];
8280     sendSignal(tcConnectptr.p->reqBlockref, GSN_COMMITCONF, signal, 4, JBB);
8281   } else {
8282     ndbrequire(regTcPtr->abortState == TcConnectionrec::NEW_FROM_TC);
8283   }//if
8284   return;
8285 }//Dblqh::commitReplyLab()
8286 
8287 /* ------------------------------------------------------------------------- */
8288 /* -------                COMPLETE PHASE                             ------- */
8289 /*                                                                           */
8290 /* ------------------------------------------------------------------------- */
completeTransNotLastLab(Signal * signal)8291 void Dblqh::completeTransNotLastLab(Signal* signal)
8292 {
8293   TcConnectionrec * const regTcPtr = tcConnectptr.p;
8294   if (regTcPtr->abortState == TcConnectionrec::ABORT_IDLE) {
8295     Uint32 clientBlockref = regTcPtr->clientBlockref;
8296     jam();
8297     sendCompleteLqh(signal, clientBlockref);
8298     cleanUp(signal);
8299     return;
8300   } else {
8301     jam();
8302     completeUnusualLab(signal);
8303     return;
8304   }//if
8305 }//Dblqh::completeTransNotLastLab()
8306 
completeTransLastLab(Signal * signal)8307 void Dblqh::completeTransLastLab(Signal* signal)
8308 {
8309   TcConnectionrec * const regTcPtr = tcConnectptr.p;
8310   if (regTcPtr->abortState == TcConnectionrec::ABORT_IDLE) {
8311     Uint32 clientBlockref = regTcPtr->clientBlockref;
8312     jam();
8313 /* ------------------------------------------------------------------------- */
8314 /*DIRTY WRITES WHICH ARE LAST IN THE CHAIN OF REPLICAS WILL SEND COMPLETED   */
8315 /*INSTEAD OF SENDING PREPARED TO THE TC (OR OTHER INITIATOR OF OPERATION).   */
8316 /* ------------------------------------------------------------------------- */
8317     sendCompletedTc(signal, clientBlockref);
8318     cleanUp(signal);
8319     return;
8320   } else {
8321     jam();
8322     completeUnusualLab(signal);
8323     return;
8324   }//if
8325 }//Dblqh::completeTransLastLab()
8326 
completeUnusualLab(Signal * signal)8327 void Dblqh::completeUnusualLab(Signal* signal)
8328 {
8329   TcConnectionrec * const regTcPtr = tcConnectptr.p;
8330   if (regTcPtr->abortState == TcConnectionrec::ABORT_FROM_TC) {
8331     jam();
8332     sendAborted(signal);
8333   } else if (regTcPtr->abortState == TcConnectionrec::NEW_FROM_TC) {
8334     jam();
8335   } else {
8336     ndbrequire(regTcPtr->abortState == TcConnectionrec::REQ_FROM_TC);
8337     jam();
8338     signal->theData[0] = regTcPtr->reqRef;
8339     signal->theData[1] = cownNodeid;
8340     signal->theData[2] = regTcPtr->transid[0];
8341     signal->theData[3] = regTcPtr->transid[1];
8342     sendSignal(regTcPtr->reqBlockref,
8343                GSN_COMPLETECONF, signal, 4, JBB);
8344   }//if
8345   cleanUp(signal);
8346   return;
8347 }//Dblqh::completeUnusualLab()
8348 
8349 /* ========================================================================= */
8350 /* =======                        RELEASE TC CONNECT RECORD          ======= */
8351 /*                                                                           */
8352 /*       RELEASE A TC CONNECT RECORD TO THE FREELIST.                        */
8353 /* ========================================================================= */
releaseTcrec(Signal * signal,TcConnectionrecPtr locTcConnectptr)8354 void Dblqh::releaseTcrec(Signal* signal, TcConnectionrecPtr locTcConnectptr)
8355 {
8356   jam();
8357   Uint32 op = locTcConnectptr.p->operation;
8358   locTcConnectptr.p->tcTimer = 0;
8359   locTcConnectptr.p->transactionState = TcConnectionrec::TC_NOT_CONNECTED;
8360   locTcConnectptr.p->nextTcConnectrec = cfirstfreeTcConrec;
8361   cfirstfreeTcConrec = locTcConnectptr.i;
8362 
8363   ndbassert(locTcConnectptr.p->tcScanRec == RNIL);
8364 
8365   TablerecPtr tabPtr;
8366   tabPtr.i = locTcConnectptr.p->tableref;
8367   if(tabPtr.i == RNIL)
8368     return;
8369 
8370   ptrCheckGuard(tabPtr, ctabrecFileSize, tablerec);
8371 
8372   /**
8373    * Normal case
8374    */
8375   if (op == ZREAD || op == ZUNLOCK)
8376   {
8377     ndbrequire(tabPtr.p->usageCountR > 0);
8378     tabPtr.p->usageCountR--;
8379   }
8380   else
8381   {
8382     ndbrequire(tabPtr.p->usageCountW > 0);
8383     tabPtr.p->usageCountW--;
8384   }
8385 }//Dblqh::releaseTcrec()
8386 
releaseTcrecLog(Signal * signal,TcConnectionrecPtr locTcConnectptr)8387 void Dblqh::releaseTcrecLog(Signal* signal, TcConnectionrecPtr locTcConnectptr)
8388 {
8389   jam();
8390   locTcConnectptr.p->tcTimer = 0;
8391   locTcConnectptr.p->transactionState = TcConnectionrec::TC_NOT_CONNECTED;
8392   locTcConnectptr.p->nextTcConnectrec = cfirstfreeTcConrec;
8393   cfirstfreeTcConrec = locTcConnectptr.i;
8394 
8395   TablerecPtr tabPtr;
8396   tabPtr.i = locTcConnectptr.p->tableref;
8397   if(tabPtr.i == RNIL)
8398     return;
8399 
8400 }//Dblqh::releaseTcrecLog()
8401 
8402 /* ------------------------------------------------------------------------- */
8403 /* -------                       ABORT PHASE                         ------- */
8404 /*                                                                           */
8405 /*THIS PART IS USED AT ERRORS THAT CAUSE ABORT OF TRANSACTION.               */
8406 /* ------------------------------------------------------------------------- */
8407 void
remove_commit_marker(TcConnectionrec * const regTcPtr)8408 Dblqh::remove_commit_marker(TcConnectionrec * const regTcPtr)
8409 {
8410   Ptr<CommitAckMarker> tmp;
8411   Uint32 commitAckMarker = regTcPtr->commitAckMarker;
8412   regTcPtr->commitAckMarker = RNIL;
8413   if (commitAckMarker == RNIL)
8414     return;
8415   jam();
8416   m_commitAckMarkerHash.getPtr(tmp, commitAckMarker);
8417 #ifdef MARKER_TRACE
8418   ndbout_c("%u remove marker[%.8x %.8x] op: %u ref: %u",
8419            instance(), tmp.p->transid1, tmp.p->transid2,
8420            Uint32(regTcPtr - tcConnectionrec), tmp.p->reference_count);
8421 #endif
8422   ndbrequire(tmp.p->reference_count > 0);
8423   tmp.p->reference_count--;
8424   if (tmp.p->reference_count == 0)
8425   {
8426     jam();
8427     m_commitAckMarkerHash.release(tmp);
8428   }
8429 }
8430 
8431 /* ***************************************************>> */
8432 /*  ABORT: Abort transaction in connection. Sender TC.   */
8433 /*  This is the normal protocol (See COMMIT)             */
8434 /* ***************************************************>> */
execABORT(Signal * signal)8435 void Dblqh::execABORT(Signal* signal)
8436 {
8437   jamEntry();
8438   Uint32 tcOprec = signal->theData[0];
8439   BlockReference tcBlockref = signal->theData[1];
8440   Uint32 transid1 = signal->theData[2];
8441   Uint32 transid2 = signal->theData[3];
8442   CRASH_INSERTION(5003);
8443   if (ERROR_INSERTED(5015)) {
8444     CLEAR_ERROR_INSERT_VALUE;
8445     sendSignalWithDelay(cownref, GSN_ABORT, signal, 2000, 4);
8446     return;
8447   }//if
8448   if (findTransaction(transid1,
8449                       transid2,
8450                       tcOprec, 0) != ZOK) {
8451     jam();
8452 
8453     if(ERROR_INSERTED(5039) &&
8454        refToNode(signal->getSendersBlockRef()) != getOwnNodeId()){
8455       jam();
8456       SET_ERROR_INSERT_VALUE(5040);
8457       return;
8458     }
8459 
8460     if(ERROR_INSERTED(5040) &&
8461        refToNode(signal->getSendersBlockRef()) != getOwnNodeId()){
8462       jam();
8463       SET_ERROR_INSERT_VALUE(5003);
8464       return;
8465     }
8466 
8467 /* ------------------------------------------------------------------------- */
8468 // SEND ABORTED EVEN IF NOT FOUND.
8469 //THE TRANSACTION MIGHT NEVER HAVE ARRIVED HERE.
8470 /* ------------------------------------------------------------------------- */
8471     signal->theData[0] = tcOprec;
8472     signal->theData[1] = transid1;
8473     signal->theData[2] = transid2;
8474     signal->theData[3] = cownNodeid;
8475     signal->theData[4] = ZTRUE;
8476     sendSignal(tcBlockref, GSN_ABORTED, signal, 5, JBB);
8477     warningReport(signal, 8);
8478     return;
8479   }//if
8480 
8481   TcConnectionrec * const regTcPtr = tcConnectptr.p;
8482   if (ERROR_INSERTED(5100))
8483   {
8484     SET_ERROR_INSERT_VALUE(5101);
8485     return;
8486   }
8487   CRASH_INSERTION2(5101, regTcPtr->nextReplica != ZNIL);
8488 
8489 /* ------------------------------------------------------------------------- */
8490 /*A GUIDING DESIGN PRINCIPLE IN HANDLING THESE ERROR SITUATIONS HAVE BEEN    */
8491 /*KEEP IT SIMPLE. THUS WE RATHER INSERT A WAIT AND SET THE ABORT_STATE TO    */
8492 /*ACTIVE RATHER THAN WRITE NEW CODE TO HANDLE EVERY SPECIAL SITUATION.       */
8493 /* ------------------------------------------------------------------------- */
8494   if (regTcPtr->nextReplica != ZNIL) {
8495 /* ------------------------------------------------------------------------- */
8496 // We will immediately send the ABORT message also to the next LQH node in line.
8497 /* ------------------------------------------------------------------------- */
8498     FragrecordPtr Tfragptr;
8499     Tfragptr.i = regTcPtr->fragmentptr;
8500     c_fragment_pool.getPtr(Tfragptr);
8501     Uint32 Tnode = regTcPtr->nextReplica;
8502     Uint32 instanceKey = Tfragptr.p->lqhInstanceKey;
8503     BlockReference TLqhRef = numberToRef(DBLQH, instanceKey, Tnode);
8504     signal->theData[0] = regTcPtr->tcOprec;
8505     signal->theData[1] = regTcPtr->tcBlockref;
8506     signal->theData[2] = regTcPtr->transid[0];
8507     signal->theData[3] = regTcPtr->transid[1];
8508     sendSignal(TLqhRef, GSN_ABORT, signal, 4, JBB);
8509   }//if
8510   regTcPtr->abortState = TcConnectionrec::ABORT_FROM_TC;
8511 
8512   remove_commit_marker(regTcPtr);
8513   TRACE_OP(regTcPtr, "ABORT");
8514 
8515   abortStateHandlerLab(signal);
8516 
8517   return;
8518 }//Dblqh::execABORT()
8519 
8520 /* ************************************************************************>>
8521  *  ABORTREQ: Same as ABORT but used in case one node isn't working ok.
8522  *  (See COMMITREQ)
8523  * ************************************************************************>> */
execABORTREQ(Signal * signal)8524 void Dblqh::execABORTREQ(Signal* signal)
8525 {
8526   jamEntry();
8527   Uint32 reqPtr = signal->theData[0];
8528   BlockReference reqBlockref = signal->theData[1];
8529   Uint32 transid1 = signal->theData[2];
8530   Uint32 transid2 = signal->theData[3];
8531   Uint32 tcOprec = signal->theData[5];
8532   if (ERROR_INSERTED(5006)) {
8533     systemErrorLab(signal, __LINE__);
8534   }
8535   if (ERROR_INSERTED(5016)) {
8536     CLEAR_ERROR_INSERT_VALUE;
8537     sendSignalWithDelay(cownref, GSN_ABORTREQ, signal, 2000, 6);
8538     return;
8539   }//if
8540   if (findTransaction(transid1,
8541                       transid2,
8542                       tcOprec, 0) != ZOK) {
8543     signal->theData[0] = reqPtr;
8544     signal->theData[2] = cownNodeid;
8545     signal->theData[3] = transid1;
8546     signal->theData[4] = transid2;
8547     sendSignal(reqBlockref, GSN_ABORTCONF, signal, 5, JBB);
8548     warningReport(signal, 9);
8549     return;
8550   }//if
8551   TcConnectionrec * const regTcPtr = tcConnectptr.p;
8552   if (regTcPtr->transactionState != TcConnectionrec::PREPARED) {
8553     warningReport(signal, 10);
8554     return;
8555   }//if
8556   regTcPtr->reqBlockref = reqBlockref;
8557   regTcPtr->reqRef = reqPtr;
8558   regTcPtr->abortState = TcConnectionrec::REQ_FROM_TC;
8559 
8560   abortCommonLab(signal);
8561   return;
8562 }//Dblqh::execABORTREQ()
8563 
8564 /* ************>> */
8565 /*  ACC_TO_REF  > */
8566 /* ************>> */
execACC_TO_REF(Signal * signal)8567 void Dblqh::execACC_TO_REF(Signal* signal)
8568 {
8569   jamEntry();
8570   terrorCode = signal->theData[1];
8571   abortErrorLab(signal);
8572   return;
8573 }//Dblqh::execACC_TO_REF()
8574 
8575 /* ************> */
8576 /*  ACCKEYREF  > */
8577 /* ************> */
execACCKEYREF(Signal * signal)8578 void Dblqh::execACCKEYREF(Signal* signal)
8579 {
8580   jamEntry();
8581   tcConnectptr.i = signal->theData[0];
8582   terrorCode = signal->theData[1];
8583   ptrCheckGuard(tcConnectptr, ctcConnectrecFileSize, tcConnectionrec);
8584   TcConnectionrec * const tcPtr = tcConnectptr.p;
8585   switch (tcPtr->transactionState) {
8586   case TcConnectionrec::WAIT_ACC:
8587     jam();
8588     break;
8589   case TcConnectionrec::WAIT_ACC_ABORT:
8590   case TcConnectionrec::ABORT_STOPPED:
8591   case TcConnectionrec::ABORT_QUEUED:
8592     jam();
8593 /* ------------------------------------------------------------------------- */
8594 /*IGNORE SINCE ABORT OF THIS OPERATION IS ONGOING ALREADY.                   */
8595 /* ------------------------------------------------------------------------- */
8596     return;
8597     break;
8598   default:
8599     ndbrequire(false);
8600     break;
8601   }//switch
8602   const Uint32 errCode = terrorCode;
8603   tcPtr->errorCode = errCode;
8604 
8605   if (TRACENR_FLAG)
8606   {
8607     TRACENR("ACCKEYREF: " << errCode << " ");
8608     switch (tcPtr->operation) {
8609     case ZREAD: TRACENR("READ"); break;
8610     case ZUPDATE: TRACENR("UPDATE"); break;
8611     case ZWRITE: TRACENR("WRITE"); break;
8612     case ZINSERT: TRACENR("INSERT"); break;
8613     case ZDELETE: TRACENR("DELETE"); break;
8614     case ZUNLOCK: TRACENR("UNLOCK"); break;
8615     default: TRACENR("<Unknown: " << tcPtr->operation << ">"); break;
8616     }
8617 
8618     TRACENR(" tab: " << tcPtr->tableref
8619 	   << " frag: " << tcPtr->fragmentid
8620 	   << " activeCreat: " << (Uint32)tcPtr->activeCreat);
8621     if (LqhKeyReq::getNrCopyFlag(tcPtr->reqinfo))
8622       TRACENR(" NrCopy");
8623     if (LqhKeyReq::getRowidFlag(tcPtr->reqinfo))
8624       TRACENR(" rowid: " << tcPtr->m_row_id);
8625     TRACENR(" key: " << getKeyInfoWordOrZero(tcPtr, 0));
8626     TRACENR(endl);
8627 
8628   }
8629 
8630   ndbrequire(tcPtr->activeCreat == Fragrecord::AC_NORMAL);
8631   ndbrequire(!LqhKeyReq::getNrCopyFlag(tcPtr->reqinfo));
8632 
8633   /**
8634    * Not only primary replica can get ZTUPLE_ALREADY_EXIST || ZNO_TUPLE_FOUND
8635    *
8636    * 1) op1 - primary insert ok
8637    * 2) op1 - backup insert fail (log full or what ever)
8638    * 3) op1 - delete ok @ primary
8639    * 4) op1 - delete fail @ backup
8640    *
8641    * -> ZNO_TUPLE_FOUND is possible
8642    *
8643    * 1) op1 primary delete ok
8644    * 2) op1 backup delete fail (log full or what ever)
8645    * 3) op2 insert ok @ primary
8646    * 4) op2 insert fail @ backup
8647    *
8648    * -> ZTUPLE_ALREADY_EXIST
8649    */
8650   tcPtr->abortState = TcConnectionrec::ABORT_FROM_LQH;
8651   abortCommonLab(signal);
8652   return;
8653 }//Dblqh::execACCKEYREF()
8654 
localAbortStateHandlerLab(Signal * signal)8655 void Dblqh::localAbortStateHandlerLab(Signal* signal)
8656 {
8657   TcConnectionrec * const regTcPtr = tcConnectptr.p;
8658   if (regTcPtr->abortState != TcConnectionrec::ABORT_IDLE) {
8659     jam();
8660     return;
8661   }//if
8662   regTcPtr->abortState = TcConnectionrec::ABORT_FROM_LQH;
8663   regTcPtr->errorCode = terrorCode;
8664   abortStateHandlerLab(signal);
8665   return;
8666 }//Dblqh::localAbortStateHandlerLab()
8667 
abortStateHandlerLab(Signal * signal)8668 void Dblqh::abortStateHandlerLab(Signal* signal)
8669 {
8670   TcConnectionrec * const regTcPtr = tcConnectptr.p;
8671   switch (regTcPtr->transactionState) {
8672   case TcConnectionrec::PREPARED:
8673     jam();
8674 /* ------------------------------------------------------------------------- */
8675 /*THE OPERATION IS ALREADY PREPARED AND SENT TO THE NEXT LQH OR BACK TO TC.  */
8676 /*WE CAN SIMPLY CONTINUE WITH THE ABORT PROCESS.                             */
8677 /*IF IT WAS A CHECK FOR TRANSACTION STATUS THEN WE REPORT THE STATUS TO THE  */
8678 /*NEW TC AND CONTINUE WITH THE NEXT OPERATION IN LQH.                        */
8679 /* ------------------------------------------------------------------------- */
8680     if (regTcPtr->abortState == TcConnectionrec::NEW_FROM_TC) {
8681       jam();
8682       sendLqhTransconf(signal, LqhTransConf::Prepared);
8683       return;
8684     }//if
8685     break;
8686   case TcConnectionrec::LOG_COMMIT_WRITTEN_WAIT_SIGNAL:
8687   case TcConnectionrec::LOG_COMMIT_QUEUED_WAIT_SIGNAL:
8688     jam();
8689 /* ------------------------------------------------------------------------- */
8690 // We can only reach these states for multi-updates on a record in a transaction.
8691 // We know that at least one of those has received the COMMIT signal, thus we
8692 // declare us only prepared since we then receive the expected COMMIT signal.
8693 /* ------------------------------------------------------------------------- */
8694     ndbrequire(regTcPtr->abortState == TcConnectionrec::NEW_FROM_TC);
8695     sendLqhTransconf(signal, LqhTransConf::Prepared);
8696     return;
8697   case TcConnectionrec::WAIT_TUPKEYINFO:
8698   case TcConnectionrec::WAIT_ATTR:
8699     jam();
8700 /* ------------------------------------------------------------------------- */
8701 /* WE ARE CURRENTLY WAITING FOR MORE INFORMATION. WE CAN START THE ABORT     */
8702 /* PROCESS IMMEDIATELY. THE KEYINFO AND ATTRINFO SIGNALS WILL BE DROPPED     */
8703 /* SINCE THE ABORT STATE WILL BE SET.                                        */
8704 /* ------------------------------------------------------------------------- */
8705     break;
8706   case TcConnectionrec::WAIT_TUP:
8707     jam();
8708 /* ------------------------------------------------------------------------- */
8709 // TUP is currently active. We have to wait for the TUPKEYREF or TUPKEYCONF
8710 // to arrive since we might otherwise jeopardise the local checkpoint
8711 // consistency in overload situations.
8712 /* ------------------------------------------------------------------------- */
8713     regTcPtr->transactionState = TcConnectionrec::WAIT_TUP_TO_ABORT;
8714     return;
8715   case TcConnectionrec::WAIT_ACC:
8716     jam();
8717     abortContinueAfterBlockedLab(signal);
8718     return;
8719     break;
8720   case TcConnectionrec::LOG_QUEUED:
8721     jam();
8722 /* ------------------------------------------------------------------------- */
8723 /*CURRENTLY QUEUED FOR LOGGING. WAIT UNTIL THE LOG RECORD HAVE BEEN INSERTED */
8724 /*AND THEN CONTINUE THE ABORT PROCESS.                                       */
8725 //Could also be waiting for an overloaded log disk. In this case it is easy
8726 //to abort when CONTINUEB arrives.
8727 /* ------------------------------------------------------------------------- */
8728     return;
8729     break;
8730   case TcConnectionrec::STOPPED:
8731     jam();
8732     /* ---------------------------------------------------------------------
8733      * WE ARE CURRENTLY QUEUED FOR ACCESS TO THE FRAGMENT BY A LCP
8734      * Since nothing has been done, just release operation
8735      * i.e. no prepare log record has been written
8736      *      so no abort log records needs to be written
8737      */
8738     releaseWaitQueue(signal);
8739     continueAfterLogAbortWriteLab(signal);
8740     return;
8741     break;
8742   case TcConnectionrec::WAIT_AI_AFTER_ABORT:
8743     jam();
8744 /* ------------------------------------------------------------------------- */
8745 /* ABORT OF ACC AND TUP ALREADY COMPLETED. THIS STATE IS ONLY USED WHEN      */
8746 /* CREATING A NEW FRAGMENT.                                                  */
8747 /* ------------------------------------------------------------------------- */
8748     continueAbortLab(signal);
8749     return;
8750     break;
8751   case TcConnectionrec::WAIT_TUP_TO_ABORT:
8752   case TcConnectionrec::ABORT_STOPPED:
8753   case TcConnectionrec::LOG_ABORT_QUEUED:
8754   case TcConnectionrec::WAIT_ACC_ABORT:
8755   case TcConnectionrec::ABORT_QUEUED:
8756     jam();
8757 /* ------------------------------------------------------------------------- */
8758 /*ABORT IS ALREADY ONGOING DUE TO SOME ERROR. WE HAVE ALREADY SET THE STATE  */
8759 /*OF THE ABORT SO THAT WE KNOW THAT TC EXPECTS A REPORT. WE CAN THUS SIMPLY  */
8760 /*EXIT.                                                                      */
8761 /* ------------------------------------------------------------------------- */
8762     return;
8763     break;
8764   case TcConnectionrec::WAIT_TUP_COMMIT:
8765   case TcConnectionrec::COMMIT_STOPPED:
8766   case TcConnectionrec::LOG_COMMIT_QUEUED:
8767   case TcConnectionrec::COMMIT_QUEUED:
8768     jam();
8769 /* ------------------------------------------------------------------------- */
8770 /*THIS IS ONLY AN ALLOWED STATE IF A DIRTY WRITE OR SIMPLE READ IS PERFORMED.*/
8771 /*IF WE ARE MERELY CHECKING THE TRANSACTION STATE IT IS ALSO AN ALLOWED STATE*/
8772 /* ------------------------------------------------------------------------- */
8773     if (regTcPtr->dirtyOp == ZTRUE) {
8774       jam();
8775 /* ------------------------------------------------------------------------- */
8776 /*COMPLETE THE DIRTY WRITE AND THEN REPORT COMPLETED BACK TO TC. SINCE IT IS */
8777 /*A DIRTY WRITE IT IS ALLOWED TO COMMIT EVEN IF THE TRANSACTION ABORTS.      */
8778 /* ------------------------------------------------------------------------- */
8779       return;
8780     }//if
8781     if (regTcPtr->opSimple) {
8782       jam();
8783 /* ------------------------------------------------------------------------- */
8784 /*A SIMPLE READ IS CURRENTLY RELEASING THE LOCKS OR WAITING FOR ACCESS TO    */
8785 /*ACC TO CLEAR THE LOCKS. COMPLETE THIS PROCESS AND THEN RETURN AS NORMAL.   */
8786 /*NO DATA HAS CHANGED DUE TO THIS SIMPLE READ ANYWAY.                        */
8787 /* ------------------------------------------------------------------------- */
8788       return;
8789     }//if
8790     ndbrequire(regTcPtr->abortState == TcConnectionrec::NEW_FROM_TC);
8791     jam();
8792 /* ------------------------------------------------------------------------- */
8793 /*WE ARE ONLY CHECKING THE STATUS OF THE TRANSACTION. IT IS COMMITTING.      */
8794 /*COMPLETE THE COMMIT LOCALLY AND THEN SEND REPORT OF COMMITTED TO THE NEW TC*/
8795 /* ------------------------------------------------------------------------- */
8796     sendLqhTransconf(signal, LqhTransConf::Committed);
8797     return;
8798     break;
8799   case TcConnectionrec::COMMITTED:
8800     jam();
8801     ndbrequire(regTcPtr->abortState == TcConnectionrec::NEW_FROM_TC);
8802 /* ------------------------------------------------------------------------- */
8803 /*WE ARE CHECKING TRANSACTION STATUS. REPORT COMMITTED AND CONTINUE WITH THE */
8804 /*NEXT OPERATION.                                                            */
8805 /* ------------------------------------------------------------------------- */
8806     sendLqhTransconf(signal, LqhTransConf::Committed);
8807     return;
8808     break;
8809   default:
8810     ndbrequire(false);
8811 /* ------------------------------------------------------------------------- */
8812 /*THE STATE WAS NOT AN ALLOWED STATE ON A NORMAL OPERATION. SCANS AND COPY   */
8813 /*FRAGMENT OPERATIONS SHOULD HAVE EXECUTED IN ANOTHER PATH.                  */
8814 /* ------------------------------------------------------------------------- */
8815     break;
8816   }//switch
8817   abortCommonLab(signal);
8818   return;
8819 }//Dblqh::abortStateHandlerLab()
8820 
abortErrorLab(Signal * signal)8821 void Dblqh::abortErrorLab(Signal* signal)
8822 {
8823   ptrCheckGuard(tcConnectptr, ctcConnectrecFileSize, tcConnectionrec);
8824   TcConnectionrec * const regTcPtr = tcConnectptr.p;
8825   if (regTcPtr->abortState == TcConnectionrec::ABORT_IDLE) {
8826     jam();
8827     regTcPtr->abortState = TcConnectionrec::ABORT_FROM_LQH;
8828     regTcPtr->errorCode = terrorCode;
8829   }//if
8830   abortCommonLab(signal);
8831   return;
8832 }//Dblqh::abortErrorLab()
8833 
abortCommonLab(Signal * signal)8834 void Dblqh::abortCommonLab(Signal* signal)
8835 {
8836   TcConnectionrec * const regTcPtr = tcConnectptr.p;
8837   const Uint32 activeCreat = regTcPtr->activeCreat;
8838 
8839   remove_commit_marker(regTcPtr);
8840 
8841   if (unlikely(activeCreat == Fragrecord::AC_NR_COPY))
8842   {
8843     jam();
8844     if (regTcPtr->m_nr_delete.m_cnt)
8845     {
8846       jam();
8847       /**
8848        * Let operation wait for pending NR operations
8849        */
8850 
8851 #ifdef VM_TRACE
8852       /**
8853        * Only disk table can have pending ops...
8854        */
8855       TablerecPtr tablePtr;
8856       tablePtr.i = regTcPtr->tableref;
8857       ptrCheckGuard(tablePtr, ctabrecFileSize, tablerec);
8858       ndbrequire(tablePtr.p->m_disk_table);
8859 #endif
8860       return;
8861     }
8862   }
8863 
8864   fragptr.i = regTcPtr->fragmentptr;
8865   if (fragptr.i != RNIL) {
8866     jam();
8867     c_fragment_pool.getPtr(fragptr);
8868     switch (fragptr.p->fragStatus) {
8869     case Fragrecord::FSACTIVE:
8870     case Fragrecord::CRASH_RECOVERING:
8871     case Fragrecord::ACTIVE_CREATION:
8872       jam();
8873       abortContinueAfterBlockedLab(signal);
8874       return;
8875       break;
8876     case Fragrecord::BLOCKED:
8877       jam();
8878       linkFragQueue(signal);
8879       regTcPtr->transactionState = TcConnectionrec::ABORT_STOPPED;
8880       return;
8881       break;
8882     case Fragrecord::FREE:
8883       jam();
8884     case Fragrecord::DEFINED:
8885       jam();
8886     case Fragrecord::REMOVING:
8887       jam();
8888     default:
8889       ndbrequire(false);
8890       break;
8891     }//switch
8892   } else {
8893     jam();
8894     continueAbortLab(signal);
8895   }//if
8896 }//Dblqh::abortCommonLab()
8897 
abortContinueAfterBlockedLab(Signal * signal)8898 void Dblqh::abortContinueAfterBlockedLab(Signal* signal)
8899 {
8900   /* ------------------------------------------------------------------------
8901    *       INPUT:          TC_CONNECTPTR           ACTIVE OPERATION RECORD
8902    * ------------------------------------------------------------------------
8903    * ------------------------------------------------------------------------
8904    *       CAN COME HERE AS RESTART AFTER BEING BLOCKED BY A LOCAL CHECKPOINT.
8905    * ------------------------------------------------------------------------
8906    *       ALSO AS PART OF A NORMAL ABORT WITHOUT BLOCKING.
8907    *       WE MUST ABORT TUP BEFORE ACC TO ENSURE THAT NO ONE RACES IN
8908    *       AND SEES A STATE IN TUP.
8909    * ----------------------------------------------------------------------- */
8910   TcConnectionrec * const regTcPtr = tcConnectptr.p;
8911 
8912   TRACE_OP(regTcPtr, "ACC ABORT");
8913   Uint32 canBlock = 2; // 2, block if needed
8914   switch(regTcPtr->transactionState){
8915   case TcConnectionrec::WAIT_TUP:
8916     jam();
8917     /**
8918      * This is when getting from execTUPKEYREF
8919      *   in which case we *do* have ACC lock
8920      *   and should not (need to) block
8921      */
8922     canBlock = 0;
8923     break;
8924   default:
8925     break;
8926   }
8927 
8928   regTcPtr->transactionState = TcConnectionrec::WAIT_ACC_ABORT;
8929   signal->theData[0] = regTcPtr->accConnectrec;
8930   signal->theData[1] = canBlock;
8931   EXECUTE_DIRECT(DBACC, GSN_ACC_ABORTREQ, signal, 2);
8932 
8933   if (signal->theData[1] == RNIL)
8934   {
8935     jam();
8936     /* ------------------------------------------------------------------------
8937      * We need to insert a real-time break by sending ACC_ABORTCONF through the
8938      * job buffer to ensure that we catch any ACCKEYCONF or TUPKEYCONF or
8939      * TUPKEYREF that are in the job buffer but not yet processed. Doing
8940      * everything without that would race and create a state error when they
8941      * are executed.
8942      * --------------------------------------------------------------------- */
8943     return;
8944   }
8945 
8946   execACC_ABORTCONF(signal);
8947   return;
8948 }//Dblqh::abortContinueAfterBlockedLab()
8949 
8950 /* ******************>> */
8951 /*  ACC_ABORTCONF     > */
8952 /* ******************>> */
execACC_ABORTCONF(Signal * signal)8953 void Dblqh::execACC_ABORTCONF(Signal* signal)
8954 {
8955   jamEntry();
8956   tcConnectptr.i = signal->theData[0];
8957   ptrCheckGuard(tcConnectptr, ctcConnectrecFileSize, tcConnectionrec);
8958   TcConnectionrec * const regTcPtr = tcConnectptr.p;
8959   ndbrequire(regTcPtr->transactionState == TcConnectionrec::WAIT_ACC_ABORT);
8960 
8961   TRACE_OP(regTcPtr, "ACC_ABORTCONF");
8962   signal->theData[0] = regTcPtr->tupConnectrec;
8963   EXECUTE_DIRECT(DBTUP, GSN_TUP_ABORTREQ, signal, 1);
8964 
8965   jamEntry();
8966   continueAbortLab(signal);
8967   return;
8968 }//Dblqh::execACC_ABORTCONF()
8969 
continueAbortLab(Signal * signal)8970 void Dblqh::continueAbortLab(Signal* signal)
8971 {
8972   TcConnectionrec * const regTcPtr = tcConnectptr.p;
8973   /* ------------------------------------------------------------------------
8974    *  AN ERROR OCCURED IN THE ACTIVE CREATION AFTER THE ABORT PHASE.
8975    *  WE NEED TO CONTINUE WITH A NORMAL ABORT.
8976    * ------------------------------------------------------------------------
8977    *       ALSO USED FOR NORMAL CLEAN UP AFTER A NORMAL ABORT.
8978    * ------------------------------------------------------------------------
8979    *       ALSO USED WHEN NO FRAGMENT WAS SET UP ON OPERATION.
8980    * ------------------------------------------------------------------------ */
8981   if (regTcPtr->logWriteState == TcConnectionrec::WRITTEN) {
8982     jam();
8983     /* ----------------------------------------------------------------------
8984      * I NEED TO INSERT A ABORT LOG RECORD SINCE WE ARE WRITING LOG IN THIS
8985      * TRANSACTION.
8986      * ---------------------------------------------------------------------- */
8987     initLogPointers(signal);
8988     if (cnoOfLogPages == 0 ||
8989         !logPartPtr.p->m_log_complete_queue.isEmpty())
8990     {
8991       jam();
8992       /* --------------------------------------------------------------------
8993        * A PREPARE OPERATION IS CURRENTLY WRITING IN THE LOG.
8994        * WE MUST WAIT ON OUR TURN TO WRITE THE LOG.
8995        * IT IS NECESSARY TO WRITE ONE LOG RECORD COMPLETELY
8996        * AT A TIME OTHERWISE WE WILL SCRAMBLE THE LOG.
8997        * -------------------------------------------------------------------- */
8998       linkWaitLog(signal, logPartPtr, logPartPtr.p->m_log_complete_queue);
8999       regTcPtr->transactionState = TcConnectionrec::LOG_ABORT_QUEUED;
9000       return;
9001     }//if
9002     writeAbortLog(signal);
9003     removeLogTcrec(signal);
9004   } else if (regTcPtr->logWriteState == TcConnectionrec::NOT_STARTED) {
9005     jam();
9006   } else if (regTcPtr->logWriteState == TcConnectionrec::NOT_WRITTEN) {
9007     jam();
9008     /* ------------------------------------------------------------------
9009      * IT IS A READ OPERATION OR OTHER OPERATION THAT DO NOT USE THE LOG.
9010      * ------------------------------------------------------------------ */
9011     /* ------------------------------------------------------------------
9012      * THE LOG HAS NOT BEEN WRITTEN SINCE THE LOG FLAG WAS FALSE.
9013      * THIS CAN OCCUR WHEN WE ARE STARTING A NEW FRAGMENT.
9014      * ------------------------------------------------------------------ */
9015     regTcPtr->logWriteState = TcConnectionrec::NOT_STARTED;
9016   } else {
9017     ndbrequire(regTcPtr->logWriteState == TcConnectionrec::NOT_WRITTEN_WAIT);
9018     jam();
9019     /* ----------------------------------------------------------------
9020      * THE STATE WAS SET TO NOT_WRITTEN BY THE OPERATION BUT LATER
9021      * A SCAN OF ALL OPERATION RECORD CHANGED IT INTO NOT_WRITTEN_WAIT.
9022      * THIS INDICATES THAT WE ARE WAITING FOR THIS OPERATION TO COMMIT
9023      * OR ABORT SO THAT WE CAN FIND THE
9024      * STARTING GLOBAL CHECKPOINT OF THIS NEW FRAGMENT.
9025      * ---------------------------------------------------------------- */
9026      checkScanTcCompleted(signal);
9027   }//if
9028   continueAfterLogAbortWriteLab(signal);
9029   return;
9030 }//Dblqh::continueAbortLab()
9031 
continueAfterLogAbortWriteLab(Signal * signal)9032 void Dblqh::continueAfterLogAbortWriteLab(Signal* signal)
9033 {
9034   TcConnectionrec * const regTcPtr = tcConnectptr.p;
9035 
9036   remove_commit_marker(regTcPtr);
9037 
9038   if (regTcPtr->operation == ZREAD && regTcPtr->dirtyOp &&
9039       !LqhKeyReq::getNormalProtocolFlag(regTcPtr->reqinfo))
9040   {
9041     jam();
9042     TcKeyRef * const tcKeyRef = (TcKeyRef *) signal->getDataPtrSend();
9043 
9044     tcKeyRef->connectPtr = regTcPtr->applOprec;
9045     tcKeyRef->transId[0] = regTcPtr->transid[0];
9046     tcKeyRef->transId[1] = regTcPtr->transid[1];
9047     tcKeyRef->errorCode = regTcPtr->errorCode;
9048     sendTCKEYREF(signal, regTcPtr->applRef, regTcPtr->tcBlockref, 0);
9049     cleanUp(signal);
9050     return;
9051   }//if
9052   if (regTcPtr->abortState == TcConnectionrec::ABORT_FROM_LQH) {
9053     LqhKeyRef * const lqhKeyRef = (LqhKeyRef *)signal->getDataPtrSend();
9054 
9055     jam();
9056     lqhKeyRef->userRef = regTcPtr->clientConnectrec;
9057     lqhKeyRef->connectPtr = regTcPtr->tcOprec;
9058     lqhKeyRef->errorCode = regTcPtr->errorCode;
9059     lqhKeyRef->transId1 = regTcPtr->transid[0];
9060     lqhKeyRef->transId2 = regTcPtr->transid[1];
9061     sendSignal(regTcPtr->clientBlockref, GSN_LQHKEYREF, signal,
9062                LqhKeyRef::SignalLength, JBB);
9063   } else if (regTcPtr->abortState == TcConnectionrec::ABORT_FROM_TC) {
9064     jam();
9065     sendAborted(signal);
9066   } else if (regTcPtr->abortState == TcConnectionrec::NEW_FROM_TC) {
9067     jam();
9068     sendLqhTransconf(signal, LqhTransConf::Aborted);
9069   } else {
9070     ndbrequire(regTcPtr->abortState == TcConnectionrec::REQ_FROM_TC);
9071     jam();
9072     signal->theData[0] = regTcPtr->reqRef;
9073     signal->theData[1] = tcConnectptr.i;
9074     signal->theData[2] = cownNodeid;
9075     signal->theData[3] = regTcPtr->transid[0];
9076     signal->theData[4] = regTcPtr->transid[1];
9077     sendSignal(regTcPtr->reqBlockref, GSN_ABORTCONF,
9078                signal, 5, JBB);
9079   }//if
9080   cleanUp(signal);
9081 }//Dblqh::continueAfterLogAbortWriteLab()
9082 
9083 void
sendTCKEYREF(Signal * signal,Uint32 ref,Uint32 routeRef,Uint32 cnt)9084 Dblqh::sendTCKEYREF(Signal* signal, Uint32 ref, Uint32 routeRef, Uint32 cnt)
9085 {
9086   const Uint32 nodeId = refToNode(ref);
9087   const bool connectedToNode = getNodeInfo(nodeId).m_connected;
9088 
9089   if (likely(connectedToNode))
9090   {
9091     jam();
9092     sendSignal(ref, GSN_TCKEYREF, signal, TcKeyRef::SignalLength, JBB);
9093   }
9094   else
9095   {
9096     if (routeRef &&
9097 	getNodeInfo(refToNode(routeRef)).m_version >= MAKE_VERSION(5,1,14))
9098     {
9099       jam();
9100       memmove(signal->theData+25, signal->theData, 4*TcKeyRef::SignalLength);
9101       RouteOrd* ord = (RouteOrd*)signal->getDataPtrSend();
9102       ord->dstRef = ref;
9103       ord->srcRef = reference();
9104       ord->gsn = GSN_TCKEYREF;
9105       ord->cnt = 0;
9106       LinearSectionPtr ptr[3];
9107       ptr[0].p = signal->theData+25;
9108       ptr[0].sz = TcKeyRef::SignalLength;
9109       sendSignal(routeRef, GSN_ROUTE_ORD, signal, RouteOrd::SignalLength, JBB,
9110 		 ptr, 1);
9111     }
9112     else
9113     {
9114       jam();
9115       memmove(signal->theData + 3, signal->theData, 4*TcKeyRef::SignalLength);
9116       signal->theData[0] = ZRETRY_TCKEYREF;
9117       signal->theData[1] = cnt + 1;
9118       signal->theData[2] = ref;
9119       sendSignalWithDelay(reference(), GSN_CONTINUEB, signal, 100,
9120 			  TcKeyRef::SignalLength + 3);
9121     }
9122   }
9123 }
9124 
9125 /* ##########################################################################
9126  * #######                       MODULE TO HANDLE TC FAILURE          #######
9127  *
9128  * ########################################################################## */
9129 
9130 /* ************************************************************************>>
9131  *  NODE_FAILREP: Node failure report. Sender Ndbcntr. Set status of failed
9132  *  node to down and reply with NF_COMPLETEREP to DIH which will report that
9133  *  LQH has completed failure handling.
9134  * ************************************************************************>> */
execNODE_FAILREP(Signal * signal)9135 void Dblqh::execNODE_FAILREP(Signal* signal)
9136 {
9137   UintR TfoundNodes = 0;
9138   UintR TnoOfNodes;
9139   UintR Tdata[MAX_NDB_NODES];
9140   Uint32 i;
9141 
9142   NodeFailRep * const nodeFail = (NodeFailRep *)&signal->theData[0];
9143 
9144   TnoOfNodes = nodeFail->noOfNodes;
9145   UintR index = 0;
9146   for (i = 1; i < MAX_NDB_NODES; i++) {
9147     jam();
9148     if(NdbNodeBitmask::get(nodeFail->theNodes, i)){
9149       jam();
9150       Tdata[index] = i;
9151       index++;
9152     }//if
9153   }//for
9154 
9155 #ifdef ERROR_INSERT
9156   c_master_node_id = nodeFail->masterNodeId;
9157 #endif
9158 
9159   lcpPtr.i = 0;
9160   ptrAss(lcpPtr, lcpRecord);
9161 
9162   ndbrequire(index == TnoOfNodes);
9163   ndbrequire(cnoOfNodes - 1 < MAX_NDB_NODES);
9164   for (i = 0; i < TnoOfNodes; i++) {
9165     const Uint32 nodeId = Tdata[i];
9166 
9167     {
9168       HostRecordPtr Thostptr;
9169       Thostptr.i = nodeId;
9170       ptrCheckGuard(Thostptr, chostFileSize, hostRecord);
9171       Thostptr.p->nodestatus = ZNODE_DOWN;
9172     }
9173 
9174     lcpPtr.p->m_EMPTY_LCP_REQ.clear(nodeId);
9175 
9176     for (Uint32 j = 0; j < cnoOfNodes; j++) {
9177       jam();
9178       if (cnodeData[j] == nodeId){
9179         jam();
9180         cnodeStatus[j] = ZNODE_DOWN;
9181 
9182         TfoundNodes++;
9183       }//if
9184     }//for
9185 
9186     /* Perform block-level ndbd failure handling */
9187     Callback cb = { safe_cast(&Dblqh::ndbdFailBlockCleanupCallback),
9188                     Tdata[i] };
9189     simBlockNodeFailure(signal, Tdata[i], cb);
9190   }//for
9191   ndbrequire(TnoOfNodes == TfoundNodes);
9192 }//Dblqh::execNODE_FAILREP()
9193 
9194 
9195 void
ndbdFailBlockCleanupCallback(Signal * signal,Uint32 failedNodeId,Uint32 ignoredRc)9196 Dblqh::ndbdFailBlockCleanupCallback(Signal* signal,
9197                                     Uint32 failedNodeId,
9198                                     Uint32 ignoredRc)
9199 {
9200   jamEntry();
9201 
9202   NFCompleteRep * const nfCompRep = (NFCompleteRep *)&signal->theData[0];
9203   nfCompRep->blockNo      = DBLQH;
9204   nfCompRep->nodeId       = cownNodeid;
9205   nfCompRep->failedNodeId = failedNodeId;
9206   BlockReference dihRef = !isNdbMtLqh() ? DBDIH_REF : DBLQH_REF;
9207   sendSignal(dihRef, GSN_NF_COMPLETEREP, signal,
9208              NFCompleteRep::SignalLength, JBB);
9209 }
9210 
9211 /* ************************************************************************>>
9212  *  LQH_TRANSREQ: Report status of all transactions where TC was coordinated
9213  *  by a crashed TC
9214  * ************************************************************************>> */
9215 /* ************************************************************************>>
9216  *  THIS SIGNAL IS RECEIVED AFTER A NODE CRASH.
9217  *  THE NODE HAD A TC AND COORDINATED A NUMBER OF TRANSACTIONS.
9218  *  NOW THE MASTER NODE IS PICKING UP THOSE TRANSACTIONS
9219  *  TO COMPLETE THEM. EITHER ABORT THEM OR COMMIT THEM.
9220  * ************************************************************************>> */
execLQH_TRANSREQ(Signal * signal)9221 void Dblqh::execLQH_TRANSREQ(Signal* signal)
9222 {
9223   jamEntry();
9224 
9225   if (!checkNodeFailSequence(signal))
9226   {
9227     jam();
9228     return;
9229   }
9230   Uint32 newTcPtr = signal->theData[0];
9231   BlockReference newTcBlockref = signal->theData[1];
9232   Uint32 oldNodeId = signal->theData[2];
9233   tcNodeFailptr.i = oldNodeId;
9234   ptrCheckGuard(tcNodeFailptr, ctcNodeFailrecFileSize, tcNodeFailRecord);
9235   if ((tcNodeFailptr.p->tcFailStatus == TcNodeFailRecord::TC_STATE_TRUE) ||
9236       (tcNodeFailptr.p->tcFailStatus == TcNodeFailRecord::TC_STATE_BREAK)) {
9237     jam();
9238     tcNodeFailptr.p->lastNewTcBlockref = newTcBlockref;
9239   /* ------------------------------------------------------------------------
9240    * WE HAVE RECEIVED A SIGNAL SPECIFYING THAT WE NEED TO HANDLE THE FAILURE
9241    * OF A TC.  NOW WE RECEIVE ANOTHER SIGNAL WITH THE SAME ORDER. THIS CAN
9242    * OCCUR IF THE NEW TC FAILS. WE MUST BE CAREFUL IN THIS CASE SO THAT WE DO
9243    * NOT START PARALLEL ACTIVITIES TRYING TO DO THE SAME THING. WE SAVE THE
9244    * NEW BLOCK REFERENCE TO THE LAST NEW TC IN A VARIABLE AND ASSIGN TO IT TO
9245    * NEW_TC_BLOCKREF WHEN THE OLD PROCESS RETURNS TO LQH_TRANS_NEXT. IT IS
9246    * CERTAIN TO COME THERE SINCE THIS IS THE ONLY PATH TO TAKE CARE OF THE
9247    * NEXT TC CONNECT RECORD. WE SET THE STATUS TO BREAK TO INDICATE TO THE OLD
9248    * PROCESS WHAT IS HAPPENING.
9249    * ------------------------------------------------------------------------ */
9250     tcNodeFailptr.p->lastNewTcRef = newTcPtr;
9251     tcNodeFailptr.p->tcFailStatus = TcNodeFailRecord::TC_STATE_BREAK;
9252     return;
9253   }//if
9254   tcNodeFailptr.p->oldNodeId = oldNodeId;
9255   tcNodeFailptr.p->newTcBlockref = newTcBlockref;
9256   tcNodeFailptr.p->newTcRef = newTcPtr;
9257   tcNodeFailptr.p->tcRecNow = 0;
9258   tcNodeFailptr.p->tcFailStatus = TcNodeFailRecord::TC_STATE_TRUE;
9259   signal->theData[0] = ZLQH_TRANS_NEXT;
9260   signal->theData[1] = tcNodeFailptr.i;
9261   sendSignal(cownref, GSN_CONTINUEB, signal, 2, JBB);
9262   return;
9263 }//Dblqh::execLQH_TRANSREQ()
9264 
lqhTransNextLab(Signal * signal)9265 void Dblqh::lqhTransNextLab(Signal* signal)
9266 {
9267   UintR tend;
9268   UintR tstart;
9269   UintR guard0;
9270 
9271   if (tcNodeFailptr.p->tcFailStatus == TcNodeFailRecord::TC_STATE_BREAK) {
9272     jam();
9273     /* ----------------------------------------------------------------------
9274      *  AN INTERRUPTION TO THIS NODE FAIL HANDLING WAS RECEIVED AND A NEW
9275      *  TC HAVE BEEN ASSIGNED TO TAKE OVER THE FAILED TC. PROBABLY THE OLD
9276      *  NEW TC HAVE FAILED.
9277      * ---------------------------------------------------------------------- */
9278     tcNodeFailptr.p->newTcBlockref = tcNodeFailptr.p->lastNewTcBlockref;
9279     tcNodeFailptr.p->newTcRef = tcNodeFailptr.p->lastNewTcRef;
9280     tcNodeFailptr.p->tcRecNow = 0;
9281     tcNodeFailptr.p->tcFailStatus = TcNodeFailRecord::TC_STATE_TRUE;
9282   }//if
9283   tstart = tcNodeFailptr.p->tcRecNow;
9284   tend = tstart + 200;
9285   guard0 = tend;
9286   for (tcConnectptr.i = tstart; tcConnectptr.i <= guard0; tcConnectptr.i++) {
9287     jam();
9288     if (tcConnectptr.i >= ctcConnectrecFileSize) {
9289       jam();
9290       /**
9291        * Finished with scanning operation record
9292        *
9293        * now scan markers
9294        */
9295 #ifdef ERROR_INSERT
9296       if (ERROR_INSERTED(5061))
9297       {
9298         CLEAR_ERROR_INSERT_VALUE;
9299         for (Uint32 i = 0; i < cnoOfNodes; i++)
9300         {
9301           Uint32 node = cnodeData[i];
9302           if (node != getOwnNodeId() && cnodeStatus[i] == ZNODE_UP)
9303           {
9304             ndbout_c("clearing ERROR_INSERT in LQH:%u", node);
9305             signal->theData[0] = 0;
9306             sendSignal(numberToRef(DBLQH, node), GSN_NDB_TAMPER,
9307                        signal, 1, JBB);
9308           }
9309         }
9310 
9311         signal->theData[0] = ZSCAN_MARKERS;
9312         signal->theData[1] = tcNodeFailptr.i;
9313         signal->theData[2] = 0;
9314         signal->theData[3] = RNIL;
9315         sendSignalWithDelay(cownref, GSN_CONTINUEB, signal, 5000, 4);
9316         return;
9317       }
9318 
9319       if (ERROR_INSERTED(5050))
9320       {
9321         ndbout_c("send ZSCAN_MARKERS with 5s delay and killing master");
9322         CLEAR_ERROR_INSERT_VALUE;
9323         signal->theData[0] = ZSCAN_MARKERS;
9324         signal->theData[1] = tcNodeFailptr.i;
9325         signal->theData[2] = 0;
9326         signal->theData[3] = RNIL;
9327         sendSignalWithDelay(cownref, GSN_CONTINUEB, signal, 5000, 4);
9328 
9329         signal->theData[0] = 9999;
9330         sendSignal(numberToRef(CMVMI, c_master_node_id),
9331                    GSN_NDB_TAMPER, signal, 1, JBB);
9332         return;
9333       }
9334 #endif
9335       scanMarkers(signal, tcNodeFailptr.i, 0, RNIL);
9336       return;
9337     }//if
9338     ptrCheckGuard(tcConnectptr, ctcConnectrecFileSize, tcConnectionrec);
9339     if (tcConnectptr.p->transactionState != TcConnectionrec::IDLE) {
9340       if (tcConnectptr.p->transactionState != TcConnectionrec::TC_NOT_CONNECTED) {
9341         if (tcConnectptr.p->tcScanRec == RNIL) {
9342           if (refToNode(tcConnectptr.p->tcBlockref) == tcNodeFailptr.p->oldNodeId) {
9343             switch( tcConnectptr.p->operation ) {
9344             case ZUNLOCK :
9345               jam(); /* Skip over */
9346               break;
9347             case ZREAD :
9348               jam();
9349               if (tcConnectptr.p->opSimple == ZTRUE) {
9350                 jam();
9351                 break; /* Skip over */
9352               }
9353               /* Fall through */
9354             default :
9355               jam();
9356               tcConnectptr.p->tcNodeFailrec = tcNodeFailptr.i;
9357               tcConnectptr.p->abortState = TcConnectionrec::NEW_FROM_TC;
9358               abortStateHandlerLab(signal);
9359               return;
9360             } // switch
9361           }//if
9362         } else {
9363           scanptr.i = tcConnectptr.p->tcScanRec;
9364 	  c_scanRecordPool.getPtr(scanptr);
9365 	  switch(scanptr.p->scanType){
9366 	  case ScanRecord::COPY:
9367 	  {
9368             jam();
9369             if (scanptr.p->scanNodeId == tcNodeFailptr.p->oldNodeId) {
9370               jam();
9371 	      /* ------------------------------------------------------------
9372 	       * THE RECEIVER OF THE COPY HAVE FAILED.
9373 	       * WE HAVE TO CLOSE THE COPY PROCESS.
9374 	       * ----------------------------------------------------------- */
9375 	      if (0) ndbout_c("close copy");
9376               tcConnectptr.p->tcNodeFailrec = tcNodeFailptr.i;
9377               tcConnectptr.p->abortState = TcConnectionrec::NEW_FROM_TC;
9378               closeCopyRequestLab(signal);
9379               return;
9380             }
9381 	    break;
9382 	  }
9383 	  case ScanRecord::SCAN:
9384 	  {
9385 	    jam();
9386 	    if (refToNode(tcConnectptr.p->tcBlockref) ==
9387 		tcNodeFailptr.p->oldNodeId) {
9388 	      jam();
9389 	      tcConnectptr.p->tcNodeFailrec = tcNodeFailptr.i;
9390 	      tcConnectptr.p->abortState = TcConnectionrec::NEW_FROM_TC;
9391 	      closeScanRequestLab(signal);
9392 	      return;
9393 	    }//if
9394 	    break;
9395 	  }
9396 	  default:
9397             ndbout_c("scanptr.p->scanType: %u", scanptr.p->scanType);
9398             ndbout_c("tcConnectptr.p->transactionState: %u",
9399                      tcConnectptr.p->transactionState);
9400 	    ndbrequire(false);
9401 	  }
9402         }
9403       }
9404       else
9405       {
9406 #if defined VM_TRACE || defined ERROR_INSERT
9407         jam();
9408         ndbrequire(tcConnectptr.p->tcScanRec == RNIL);
9409 #endif
9410       }
9411     }
9412     else
9413     {
9414 #if defined VM_TRACE || defined ERROR_INSERT
9415       jam();
9416       ndbrequire(tcConnectptr.p->tcScanRec == RNIL);
9417 #endif
9418     }
9419   }//for
9420   tcNodeFailptr.p->tcRecNow = tend + 1;
9421   signal->theData[0] = ZLQH_TRANS_NEXT;
9422   signal->theData[1] = tcNodeFailptr.i;
9423   sendSignal(cownref, GSN_CONTINUEB, signal, 2, JBB);
9424   return;
9425 }//Dblqh::lqhTransNextLab()
9426 
9427 void
scanMarkers(Signal * signal,Uint32 tcNodeFail,Uint32 startBucket,Uint32 i)9428 Dblqh::scanMarkers(Signal* signal,
9429 		   Uint32 tcNodeFail,
9430 		   Uint32 startBucket,
9431 		   Uint32 i){
9432 
9433   jam();
9434 
9435   TcNodeFailRecordPtr tcNodeFailPtr;
9436   tcNodeFailPtr.i = tcNodeFail;
9437   ptrCheckGuard(tcNodeFailPtr, ctcNodeFailrecFileSize, tcNodeFailRecord);
9438   const Uint32 crashedTcNodeId = tcNodeFailPtr.p->oldNodeId;
9439 
9440   if (tcNodeFailPtr.p->tcFailStatus == TcNodeFailRecord::TC_STATE_BREAK)
9441   {
9442     jam();
9443 
9444     /* ----------------------------------------------------------------------
9445      *  AN INTERRUPTION TO THIS NODE FAIL HANDLING WAS RECEIVED AND A NEW
9446      *  TC HAVE BEEN ASSIGNED TO TAKE OVER THE FAILED TC. PROBABLY THE OLD
9447      *  NEW TC HAVE FAILED.
9448      * ---------------------------------------------------------------------- */
9449     tcNodeFailptr = tcNodeFailPtr;
9450     lqhTransNextLab(signal);
9451     return;
9452   }
9453 
9454   CommitAckMarkerIterator iter;
9455   if(i == RNIL){
9456     m_commitAckMarkerHash.next(startBucket, iter);
9457   } else {
9458     jam();
9459     iter.curr.i = i;
9460     iter.bucket = startBucket;
9461     m_commitAckMarkerHash.getPtr(iter.curr);
9462     m_commitAckMarkerHash.next(iter);
9463   }
9464 
9465   const Uint32 RT_BREAK = 256;
9466   for(i = 0; i<RT_BREAK || iter.bucket == startBucket; i++){
9467     jam();
9468 
9469     if(iter.curr.i == RNIL){
9470       /**
9471        * Done with iteration
9472        */
9473       jam();
9474 
9475       tcNodeFailPtr.p->tcFailStatus = TcNodeFailRecord::TC_STATE_FALSE;
9476       signal->theData[0] = tcNodeFailPtr.p->newTcRef;
9477       signal->theData[1] = cownNodeid;
9478       signal->theData[2] = LqhTransConf::LastTransConf;
9479       sendSignal(tcNodeFailPtr.p->newTcBlockref, GSN_LQH_TRANSCONF,
9480 		 signal, 3, JBB);
9481       return;
9482     }
9483 
9484     if(iter.curr.p->tcNodeId == crashedTcNodeId){
9485       jam();
9486 
9487       /**
9488        * Found marker belonging to crashed node
9489        */
9490       LqhTransConf * const lqhTransConf = (LqhTransConf *)&signal->theData[0];
9491       lqhTransConf->tcRef     = tcNodeFailPtr.p->newTcRef;
9492       lqhTransConf->lqhNodeId = cownNodeid;
9493       lqhTransConf->operationStatus = LqhTransConf::Marker;
9494       lqhTransConf->transId1 = iter.curr.p->transid1;
9495       lqhTransConf->transId2 = iter.curr.p->transid2;
9496       lqhTransConf->apiRef   = iter.curr.p->apiRef;
9497       lqhTransConf->apiOpRec = iter.curr.p->apiOprec;
9498       sendSignal(tcNodeFailPtr.p->newTcBlockref, GSN_LQH_TRANSCONF,
9499 		 signal, 7, JBB);
9500 
9501       signal->theData[0] = ZSCAN_MARKERS;
9502       signal->theData[1] = tcNodeFailPtr.i;
9503       signal->theData[2] = iter.bucket;
9504       signal->theData[3] = iter.curr.i;
9505       sendSignal(cownref, GSN_CONTINUEB, signal, 4, JBB);
9506       return;
9507     }
9508 
9509     m_commitAckMarkerHash.next(iter);
9510   }
9511 
9512   signal->theData[0] = ZSCAN_MARKERS;
9513   signal->theData[1] = tcNodeFailPtr.i;
9514   signal->theData[2] = iter.bucket;
9515   signal->theData[3] = RNIL;
9516   sendSignal(cownref, GSN_CONTINUEB, signal, 4, JBB);
9517 }
9518 
9519 /* #########################################################################
9520  * #######                       SCAN MODULE                         #######
9521  *
9522  * #########################################################################
9523  * -------------------------------------------------------------------------
9524  * THIS MODULE CONTAINS THE CODE THAT HANDLES A SCAN OF A PARTICULAR FRAGMENT
9525  * IT OPERATES UNDER THE CONTROL OF TC AND ORDERS ACC TO PERFORM A SCAN OF
9526  * ALL TUPLES IN THE FRAGMENT. TUP PERFORMS THE NECESSARY SEARCH CONDITIONS
9527  * TO ENSURE THAT ONLY VALID TUPLES ARE RETURNED TO THE APPLICATION.
9528  * ------------------------------------------------------------------------- */
9529 /* *************** */
9530 /*  ACC_SCANCONF > */
9531 /* *************** */
execACC_SCANCONF(Signal * signal)9532 void Dblqh::execACC_SCANCONF(Signal* signal)
9533 {
9534   AccScanConf * const accScanConf = (AccScanConf *)&signal->theData[0];
9535   jamEntry();
9536   scanptr.i = accScanConf->scanPtr;
9537   c_scanRecordPool.getPtr(scanptr);
9538   if (scanptr.p->scanState == ScanRecord::WAIT_ACC_SCAN) {
9539     accScanConfScanLab(signal);
9540   } else {
9541     ndbrequire(scanptr.p->scanState == ScanRecord::WAIT_ACC_COPY);
9542     accScanConfCopyLab(signal);
9543   }//if
9544 }//Dblqh::execACC_SCANCONF()
9545 
9546 /* ************>> */
9547 /*  ACC_SCANREF > */
9548 /* ************>> */
execACC_SCANREF(Signal * signal)9549 void Dblqh::execACC_SCANREF(Signal* signal)
9550 {
9551   jamEntry();
9552   ndbrequire(refToMain(signal->getSendersBlockRef()) == DBTUX);
9553   const AccScanRef refCopy = *(const AccScanRef*)signal->getDataPtr();
9554   const AccScanRef* ref = &refCopy;
9555   ndbrequire(ref->errorCode != 0);
9556 
9557   scanptr.i = ref->scanPtr;
9558   c_scanRecordPool.getPtr(scanptr);
9559   tcConnectptr.i = scanptr.p->scanTcrec;
9560   ptrCheckGuard(tcConnectptr, ctcConnectrecFileSize, tcConnectionrec);
9561   tcConnectptr.p->errorCode = ref->errorCode;
9562 
9563   /*
9564    * MRR scan can hit this between 2 DBTUX scans.  Previous range has
9565    * terminated via last NEXT_SCANCONF, then index is set to Dropping,
9566    * and then next range is started and returns ACC_SCANREF.
9567    */
9568   if (scanptr.p->scanStoredProcId != RNIL) {
9569     jam();
9570     scanptr.p->scanCompletedStatus = ZTRUE;
9571     accScanCloseConfLab(signal);
9572     return;
9573   }
9574   tupScanCloseConfLab(signal);
9575 }//Dblqh::execACC_SCANREF()
9576 
9577 /* ***************>> */
9578 /*  NEXT_SCANCONF  > */
9579 /* ***************>> */
execNEXT_SCANCONF(Signal * signal)9580 void Dblqh::execNEXT_SCANCONF(Signal* signal)
9581 {
9582   NextScanConf * const nextScanConf = (NextScanConf *)&signal->theData[0];
9583   jamEntry();
9584   scanptr.i = nextScanConf->scanPtr;
9585   c_scanRecordPool.getPtr(scanptr);
9586   scanptr.p->m_row_id.m_page_no = nextScanConf->localKey[0];
9587   scanptr.p->m_row_id.m_page_idx = nextScanConf->localKey[1];
9588 
9589 #ifdef VM_TRACE
9590   if (signal->getLength() > 2 && nextScanConf->accOperationPtr != RNIL)
9591   {
9592     Ptr<TcConnectionrec> regTcPtr;
9593     regTcPtr.i = scanptr.p->scanTcrec;
9594     ptrCheckGuard(regTcPtr, ctcConnectrecFileSize, tcConnectionrec);
9595     ndbassert(regTcPtr.p->fragmentid == nextScanConf->fragId);
9596   }
9597 #endif
9598 
9599   fragptr.i = scanptr.p->fragPtrI;
9600   c_fragment_pool.getPtr(fragptr);
9601   switch (scanptr.p->scanState) {
9602   case ScanRecord::WAIT_CLOSE_SCAN:
9603     jam();
9604     accScanCloseConfLab(signal);
9605     break;
9606   case ScanRecord::WAIT_CLOSE_COPY:
9607     jam();
9608     accCopyCloseConfLab(signal);
9609     break;
9610   case ScanRecord::WAIT_NEXT_SCAN:
9611     jam();
9612     nextScanConfScanLab(signal);
9613     break;
9614   case ScanRecord::WAIT_NEXT_SCAN_COPY:
9615     jam();
9616     nextScanConfCopyLab(signal);
9617     break;
9618   case ScanRecord::WAIT_RELEASE_LOCK:
9619     jam();
9620     ndbrequire(signal->length() == 1);
9621     scanLockReleasedLab(signal);
9622     break;
9623   default:
9624     ndbout_c("%d", scanptr.p->scanState);
9625     ndbrequire(false);
9626   }//switch
9627 }//Dblqh::execNEXT_SCANCONF()
9628 
9629 /* ***************> */
9630 /*  NEXT_SCANREF  > */
9631 /* ***************> */
execNEXT_SCANREF(Signal * signal)9632 void Dblqh::execNEXT_SCANREF(Signal* signal)
9633 {
9634   jamEntry();
9635   ndbrequire(refToMain(signal->getSendersBlockRef()) == DBTUX);
9636   const NextScanRef refCopy = *(const NextScanRef*)signal->getDataPtr();
9637   const NextScanRef* ref = &refCopy;
9638   ndbrequire(ref->errorCode != 0);
9639 
9640   scanptr.i = ref->scanPtr;
9641   c_scanRecordPool.getPtr(scanptr);
9642   tcConnectptr.i = scanptr.p->scanTcrec;
9643   ptrCheckGuard(tcConnectptr, ctcConnectrecFileSize, tcConnectionrec);
9644   tcConnectptr.p->errorCode = ref->errorCode;
9645 
9646   /*
9647    * MRR scan may have other ranges left.  But the scan has already
9648    * failed.  Terminate the scan now.
9649    */
9650   scanptr.p->scanCompletedStatus = ZTRUE;
9651   accScanCloseConfLab(signal);
9652 }//Dblqh::execNEXT_SCANREF()
9653 
9654 /* ******************> */
9655 /*  STORED_PROCCONF  > */
9656 /* ******************> */
execSTORED_PROCCONF(Signal * signal)9657 void Dblqh::execSTORED_PROCCONF(Signal* signal)
9658 {
9659   jamEntry();
9660   tcConnectptr.i = signal->theData[0];
9661   Uint32 storedProcId = signal->theData[1];
9662   ptrCheckGuard(tcConnectptr, ctcConnectrecFileSize, tcConnectionrec);
9663   scanptr.i = tcConnectptr.p->tcScanRec;
9664   c_scanRecordPool.getPtr(scanptr);
9665   switch (scanptr.p->scanState) {
9666   case ScanRecord::WAIT_STORED_PROC_SCAN:
9667     jam();
9668     scanptr.p->scanStoredProcId = storedProcId;
9669     storedProcConfScanLab(signal);
9670     break;
9671   case ScanRecord::WAIT_DELETE_STORED_PROC_ID_SCAN:
9672     jam();
9673     tupScanCloseConfLab(signal);
9674     break;
9675   case ScanRecord::WAIT_STORED_PROC_COPY:
9676     jam();
9677     scanptr.p->scanStoredProcId = storedProcId;
9678     storedProcConfCopyLab(signal);
9679     break;
9680   case ScanRecord::WAIT_DELETE_STORED_PROC_ID_COPY:
9681     jam();
9682     tupCopyCloseConfLab(signal);
9683     break;
9684   default:
9685     ndbrequire(false);
9686   }//switch
9687 }//Dblqh::execSTORED_PROCCONF()
9688 
9689 /* ****************** */
9690 /*  STORED_PROCREF  > */
9691 /* ****************** */
execSTORED_PROCREF(Signal * signal)9692 void Dblqh::execSTORED_PROCREF(Signal* signal)
9693 {
9694   jamEntry();
9695   tcConnectptr.i = signal->theData[0];
9696   Uint32 errorCode  = signal->theData[1];
9697   ptrCheckGuard(tcConnectptr, ctcConnectrecFileSize, tcConnectionrec);
9698   scanptr.i = tcConnectptr.p->tcScanRec;
9699   c_scanRecordPool.getPtr(scanptr);
9700   switch (scanptr.p->scanState) {
9701   case ScanRecord::WAIT_STORED_PROC_SCAN:
9702     jam();
9703     scanptr.p->scanCompletedStatus = ZTRUE;
9704     scanptr.p->scanStoredProcId = signal->theData[2];
9705     tcConnectptr.p->errorCode = errorCode;
9706     closeScanLab(signal);
9707     break;
9708   default:
9709     ndbrequire(false);
9710   }//switch
9711 }//Dblqh::execSTORED_PROCREF()
9712 
9713 /* --------------------------------------------------------------------------
9714  *       ENTER SCAN_NEXTREQ
9715  * --------------------------------------------------------------------------
9716  *       PRECONDITION:
9717  *       TRANSACTION_STATE = SCAN_STATE
9718  *       SCAN_STATE = WAIT_SCAN_NEXTREQ
9719  *
9720  * Case scanLockHold: ZTRUE  = Unlock previous round of
9721  *                             scanned row(s) and fetch next set of rows.
9722  *                    ZFALSE = Fetch new set of rows.
9723  * Number of rows to read depends on parallelism and how many rows
9724  * left to scan in the fragment. SCAN_NEXTREQ can also be sent with
9725  * closeFlag == ZTRUE to close the scan.
9726  * ------------------------------------------------------------------------- */
execSCAN_NEXTREQ(Signal * signal)9727 void Dblqh::execSCAN_NEXTREQ(Signal* signal)
9728 {
9729   jamEntry();
9730   const ScanFragNextReq * const nextReq =
9731                                 (ScanFragNextReq*)&signal->theData[0];
9732   const Uint32 transid1 = nextReq->transId1;
9733   const Uint32 transid2 = nextReq->transId2;
9734   const Uint32 senderData = nextReq->senderData;
9735   Uint32 hashHi = signal->getSendersBlockRef();
9736 
9737   if (findTransaction(transid1, transid2, senderData, hashHi) != ZOK){
9738     jam();
9739     DEBUG(senderData <<
9740 	  " Received SCAN_NEXTREQ in LQH with close flag when closed");
9741     ndbrequire(nextReq->requestInfo == ScanFragNextReq::ZCLOSE);
9742     return;
9743   }
9744 
9745   // Crash node if signal sender is same node
9746   CRASH_INSERTION2(5021, refToNode(signal->senderBlockRef()) == cownNodeid);
9747   // Crash node if signal sender is NOT same node
9748   CRASH_INSERTION2(5022, refToNode(signal->senderBlockRef()) != cownNodeid);
9749 
9750   if (ERROR_INSERTED(5023)){
9751     // Drop signal if sender is same node
9752     if (refToNode(signal->senderBlockRef()) == cownNodeid) {
9753       CLEAR_ERROR_INSERT_VALUE;
9754       return;
9755     }
9756   }//if
9757   if (ERROR_INSERTED(5024)){
9758     // Drop signal if sender is NOT same node
9759     if (refToNode(signal->senderBlockRef()) != cownNodeid) {
9760       CLEAR_ERROR_INSERT_VALUE;
9761       return;
9762     }
9763   }//if
9764   if (ERROR_INSERTED(5025))
9765   {
9766     /**
9767      * This does not work as signal->getSendersBlockRef() is used
9768      *   as "hashHi"...not having a real data-word for this is not optimal
9769      *   but it will work...summary: disable this ERROR_INSERT
9770      */
9771     CLEAR_ERROR_INSERT_VALUE;
9772   }
9773 
9774   if (ERROR_INSERTED(5030)){
9775     ndbout << "ERROR 5030" << endl;
9776     CLEAR_ERROR_INSERT_VALUE;
9777     // Drop signal
9778     return;
9779   }//if
9780 
9781   if(ERROR_INSERTED(5036)){
9782     return;
9783   }
9784 
9785   Uint32 pos = 0;
9786   if (ScanFragNextReq::getCorrFactorFlag(nextReq->requestInfo))
9787   {
9788     jam();
9789     Uint32 corrFactorLo = nextReq->variableData[pos++];
9790     tcConnectptr.p->m_corrFactorLo &= 0xFFFF0000;
9791     tcConnectptr.p->m_corrFactorLo |= corrFactorLo;
9792   }
9793 
9794   scanptr.i = tcConnectptr.p->tcScanRec;
9795   ndbrequire(scanptr.i != RNIL);
9796   c_scanRecordPool.getPtr(scanptr);
9797   scanptr.p->scanTcWaiting = cLqhTimeOutCount;
9798 
9799   /* ------------------------------------------------------------------
9800    * If close flag is set this scan should be closed
9801    * If we are waiting for SCAN_NEXTREQ set flag to stop scanning and
9802    * continue execution else set flags and wait until the scan
9803    * completes itself
9804    * ------------------------------------------------------------------ */
9805   if (nextReq->requestInfo == ScanFragNextReq::ZCLOSE)
9806   {
9807     jam();
9808     if(ERROR_INSERTED(5034)){
9809       CLEAR_ERROR_INSERT_VALUE;
9810     }
9811     if(ERROR_INSERTED(5036)){
9812       CLEAR_ERROR_INSERT_VALUE;
9813       return;
9814     }
9815     closeScanRequestLab(signal);
9816     return;
9817   }//if
9818 
9819   fragptr.i = tcConnectptr.p->fragmentptr;
9820   c_fragment_pool.getPtr(fragptr);
9821 
9822   /**
9823    * Change parameters while running
9824    *   (is currently not supported)
9825    */
9826   const Uint32 max_rows = nextReq->batch_size_rows;
9827   const Uint32 max_bytes = nextReq->batch_size_bytes;
9828   scanptr.p->m_max_batch_size_bytes = max_bytes;
9829 
9830   if (max_rows > scanptr.p->m_max_batch_size_rows)
9831   {
9832     jam();
9833     /**
9834      * Extend list...
9835      */
9836     if (!seize_acc_ptr_list(scanptr.p,
9837                             scanptr.p->m_max_batch_size_rows, max_rows))
9838     {
9839       jam();
9840       tcConnectptr.p->errorCode = ScanFragRef::ZTOO_MANY_ACTIVE_SCAN_ERROR;
9841       closeScanRequestLab(signal);
9842       return;
9843     }
9844     cbookedAccOps += (max_rows - scanptr.p->m_max_batch_size_rows);
9845     scanptr.p->m_max_batch_size_rows = max_rows;
9846   }
9847   else if (unlikely(max_rows < scanptr.p->m_max_batch_size_rows))
9848   {
9849     jam();
9850     cbookedAccOps -= (scanptr.p->m_max_batch_size_rows - max_rows);
9851     scanptr.p->m_max_batch_size_rows = max_rows;
9852   }
9853 
9854   /* --------------------------------------------------------------------
9855    * If scanLockHold = TRUE we need to unlock previous round of
9856    * scanned records.
9857    * scanReleaseLocks will set states for this and send a NEXT_SCANREQ.
9858    * When confirm signal NEXT_SCANCONF arrives we call
9859    * continueScanNextReqLab to continue scanning new rows and
9860    * acquiring new locks.
9861    * -------------------------------------------------------------------- */
9862   if ((scanptr.p->scanLockHold == ZTRUE) &&
9863       (scanptr.p->m_curr_batch_size_rows > 0)) {
9864     jam();
9865     scanptr.p->scanReleaseCounter = 1;
9866     scanReleaseLocksLab(signal);
9867     return;
9868   }//if
9869 
9870   /* -----------------------------------------------------------------------
9871    * We end up here when scanLockHold = FALSE or no rows was locked from
9872    * previous round.
9873    * Simply continue scanning.
9874    * ----------------------------------------------------------------------- */
9875   continueScanNextReqLab(signal);
9876 }//Dblqh::execSCAN_NEXTREQ()
9877 
continueScanNextReqLab(Signal * signal)9878 void Dblqh::continueScanNextReqLab(Signal* signal)
9879 {
9880   if (scanptr.p->scanCompletedStatus == ZTRUE) {
9881     jam();
9882     closeScanLab(signal);
9883     return;
9884   }//if
9885 
9886   if(scanptr.p->m_last_row){
9887     jam();
9888     scanptr.p->scanCompletedStatus = ZTRUE;
9889     scanptr.p->scanState = ScanRecord::WAIT_SCAN_NEXTREQ;
9890     sendScanFragConf(signal, ZFALSE);
9891     return;
9892   }
9893 
9894   // Update timer on tcConnectRecord
9895   tcConnectptr.p->tcTimer = cLqhTimeOutCount;
9896   init_acc_ptr_list(scanptr.p);
9897   scanptr.p->scanFlag = NextScanReq::ZSCAN_NEXT;
9898   scanNextLoopLab(signal);
9899 }//Dblqh::continueScanNextReqLab()
9900 
9901 /* -------------------------------------------------------------------------
9902  *       WE NEED TO RELEASE LOCKS BEFORE CONTINUING
9903  * ------------------------------------------------------------------------- */
scanReleaseLocksLab(Signal * signal)9904 void Dblqh::scanReleaseLocksLab(Signal* signal)
9905 {
9906   switch (fragptr.p->fragStatus) {
9907   case Fragrecord::FSACTIVE:
9908     jam();
9909     break;
9910   case Fragrecord::BLOCKED:
9911     jam();
9912     linkFragQueue(signal);
9913     tcConnectptr.p->transactionState = TcConnectionrec::SCAN_RELEASE_STOPPED;
9914     return;
9915     break;
9916   case Fragrecord::FREE:
9917     jam();
9918   case Fragrecord::ACTIVE_CREATION:
9919     jam();
9920   case Fragrecord::CRASH_RECOVERING:
9921     jam();
9922   case Fragrecord::DEFINED:
9923     jam();
9924   case Fragrecord::REMOVING:
9925     jam();
9926   default:
9927     ndbrequire(false);
9928   }//switch
9929   continueScanReleaseAfterBlockedLab(signal);
9930 }//Dblqh::scanReleaseLocksLab()
9931 
continueScanReleaseAfterBlockedLab(Signal * signal)9932 void Dblqh::continueScanReleaseAfterBlockedLab(Signal* signal)
9933 {
9934   scanptr.i = tcConnectptr.p->tcScanRec;
9935   c_scanRecordPool.getPtr(scanptr);
9936   scanptr.p->scanState = ScanRecord::WAIT_RELEASE_LOCK;
9937   signal->theData[0] = scanptr.p->scanAccPtr;
9938   signal->theData[1]=
9939     get_acc_ptr_from_scan_record(scanptr.p,
9940                                 scanptr.p->scanReleaseCounter -1,
9941                                 false);
9942   signal->theData[2] = NextScanReq::ZSCAN_COMMIT;
9943   sendSignal(scanptr.p->scanBlockref, GSN_NEXT_SCANREQ, signal, 3, JBB);
9944 }//Dblqh::continueScanReleaseAfterBlockedLab()
9945 
9946 /* -------------------------------------------------------------------------
9947  *       ENTER SCAN_NEXTREQ
9948  * -------------------------------------------------------------------------
9949  *       SCAN_NEXT_REQ SIGNAL ARRIVED IN THE MIDDLE OF EXECUTION OF THE SCAN.
9950  *       IT WAS A REQUEST TO CLOSE THE SCAN. WE WILL CLOSE THE SCAN IN A
9951  *       CAREFUL MANNER TO ENSURE THAT NO ERROR OCCURS.
9952  * -------------------------------------------------------------------------
9953  *       PRECONDITION:
9954  *       TRANSACTION_STATE = SCAN_STATE_USED
9955  *       TSCAN_COMPLETED = ZTRUE
9956  * -------------------------------------------------------------------------
9957  *       WE CAN ALSO ARRIVE AT THIS LABEL AFTER A NODE CRASH OF THE SCAN
9958  *       COORDINATOR.
9959  * ------------------------------------------------------------------------- */
closeScanRequestLab(Signal * signal)9960 void Dblqh::closeScanRequestLab(Signal* signal)
9961 {
9962   DEBUG("transactionState = " << tcConnectptr.p->transactionState);
9963   switch (tcConnectptr.p->transactionState) {
9964   case TcConnectionrec::SCAN_STATE_USED:
9965     DEBUG("scanState = " << scanptr.p->scanState);
9966     switch (scanptr.p->scanState) {
9967     case ScanRecord::IN_QUEUE:
9968       jam();
9969       tupScanCloseConfLab(signal);
9970       break;
9971     case ScanRecord::WAIT_NEXT_SCAN:
9972       jam();
9973       /* -------------------------------------------------------------------
9974        *  SET COMPLETION STATUS AND WAIT FOR OPPORTUNITY TO STOP THE SCAN.
9975        * ------------------------------------------------------------------- */
9976       scanptr.p->scanCompletedStatus = ZTRUE;
9977       break;
9978     case ScanRecord::WAIT_ACC_SCAN:
9979     case ScanRecord::WAIT_STORED_PROC_SCAN:
9980       jam();
9981       /* -------------------------------------------------------------------
9982        *  WE ARE CURRENTLY STARTING UP THE SCAN. SET COMPLETED STATUS
9983        *  AND WAIT FOR COMPLETION OF STARTUP.
9984        * ------------------------------------------------------------------- */
9985       scanptr.p->scanCompletedStatus = ZTRUE;
9986       break;
9987     case ScanRecord::WAIT_CLOSE_SCAN:
9988       jam();
9989       scanptr.p->scanCompletedStatus = ZTRUE;
9990     case ScanRecord::WAIT_DELETE_STORED_PROC_ID_SCAN:
9991       jam();
9992       /*empty*/;
9993       break;
9994       /* -------------------------------------------------------------------
9995        *       CLOSE IS ALREADY ONGOING. WE NEED NOT DO ANYTHING.
9996        * ------------------------------------------------------------------- */
9997     case ScanRecord::WAIT_RELEASE_LOCK:
9998       jam();
9999       /* -------------------------------------------------------------------
10000        *  WE ARE CURRENTLY RELEASING RECORD LOCKS. AFTER COMPLETING THIS
10001        *  WE WILL START TO CLOSE THE SCAN.
10002        * ------------------------------------------------------------------- */
10003       scanptr.p->scanCompletedStatus = ZTRUE;
10004       break;
10005     case ScanRecord::WAIT_SCAN_NEXTREQ:
10006       jam();
10007       /* -------------------------------------------------------------------
10008        * WE ARE WAITING FOR A SCAN_NEXTREQ FROM SCAN COORDINATOR(TC)
10009        * WICH HAVE CRASHED. CLOSE THE SCAN
10010        * ------------------------------------------------------------------- */
10011       scanptr.p->scanCompletedStatus = ZTRUE;
10012 
10013       fragptr.i = tcConnectptr.p->fragmentptr;
10014       c_fragment_pool.getPtr(fragptr);
10015 
10016       if (scanptr.p->scanLockHold == ZTRUE) {
10017 	if (scanptr.p->m_curr_batch_size_rows > 0) {
10018 	  jam();
10019 	  scanptr.p->scanReleaseCounter = 1;
10020 	  scanReleaseLocksLab(signal);
10021 	  return;
10022 	}//if
10023       }//if
10024       closeScanLab(signal);
10025       break;
10026     default:
10027       ndbrequire(false);
10028     }//switch
10029     break;
10030   case TcConnectionrec::WAIT_SCAN_AI:
10031     jam();
10032     /* ---------------------------------------------------------------------
10033      *  WE ARE STILL WAITING FOR THE ATTRIBUTE INFORMATION THAT
10034      *  OBVIOUSLY WILL NOT ARRIVE. WE CAN QUIT IMMEDIATELY HERE.
10035      * --------------------------------------------------------------------- */
10036     tupScanCloseConfLab(signal);
10037     return;
10038     break;
10039   case TcConnectionrec::SCAN_TUPKEY:
10040   case TcConnectionrec::SCAN_FIRST_STOPPED:
10041   case TcConnectionrec::SCAN_CHECK_STOPPED:
10042   case TcConnectionrec::SCAN_STOPPED:
10043     jam();
10044     /* ---------------------------------------------------------------------
10045      *       SET COMPLETION STATUS AND WAIT FOR OPPORTUNITY TO STOP THE SCAN.
10046      * --------------------------------------------------------------------- */
10047     scanptr.p->scanCompletedStatus = ZTRUE;
10048     break;
10049   case TcConnectionrec::SCAN_RELEASE_STOPPED:
10050     jam();
10051     /* ---------------------------------------------------------------------
10052      *  WE ARE CURRENTLY RELEASING RECORD LOCKS. AFTER COMPLETING
10053      *  THIS WE WILL START TO CLOSE THE SCAN.
10054      * --------------------------------------------------------------------- */
10055     scanptr.p->scanCompletedStatus = ZTRUE;
10056     break;
10057   case TcConnectionrec::SCAN_CLOSE_STOPPED:
10058     jam();
10059     /* ---------------------------------------------------------------------
10060      *  CLOSE IS ALREADY ONGOING. WE NEED NOT DO ANYTHING.
10061      * --------------------------------------------------------------------- */
10062     /*empty*/;
10063     break;
10064   default:
10065     ndbrequire(false);
10066   }//switch
10067 }//Dblqh::closeScanRequestLab()
10068 
10069 /* -------------------------------------------------------------------------
10070  *       ENTER NEXT_SCANCONF
10071  * -------------------------------------------------------------------------
10072  *       PRECONDITION: SCAN_STATE = WAIT_RELEASE_LOCK
10073  * ------------------------------------------------------------------------- */
scanLockReleasedLab(Signal * signal)10074 void Dblqh::scanLockReleasedLab(Signal* signal)
10075 {
10076   tcConnectptr.i = scanptr.p->scanTcrec;
10077   ptrCheckGuard(tcConnectptr, ctcConnectrecFileSize, tcConnectionrec);
10078 
10079   check_send_scan_hb_rep(signal, scanptr.p, tcConnectptr.p);
10080 
10081   if (scanptr.p->scanReleaseCounter == scanptr.p->m_curr_batch_size_rows) {
10082     if ((scanptr.p->scanErrorCounter > 0) ||
10083         (scanptr.p->scanCompletedStatus == ZTRUE)) {
10084       jam();
10085       scanptr.p->m_curr_batch_size_rows = 0;
10086       scanptr.p->m_curr_batch_size_bytes = 0;
10087       closeScanLab(signal);
10088     } else if (scanptr.p->m_last_row && !scanptr.p->scanLockHold) {
10089       jam();
10090       closeScanLab(signal);
10091       return;
10092     } else if (scanptr.p->check_scan_batch_completed() &&
10093                scanptr.p->scanLockHold != ZTRUE) {
10094       jam();
10095       scanptr.p->scanState = ScanRecord::WAIT_SCAN_NEXTREQ;
10096       sendScanFragConf(signal, ZFALSE);
10097     } else {
10098       jam();
10099       /*
10100        * We came here after releasing locks after
10101        * receiving SCAN_NEXTREQ from TC. We only come here
10102        * when scanHoldLock == ZTRUE
10103        */
10104       scanptr.p->m_curr_batch_size_rows = 0;
10105       scanptr.p->m_curr_batch_size_bytes = 0;
10106       continueScanNextReqLab(signal);
10107     }//if
10108   } else if (scanptr.p->scanReleaseCounter < scanptr.p->m_curr_batch_size_rows) {
10109     jam();
10110     scanptr.p->scanReleaseCounter++;
10111     scanReleaseLocksLab(signal);
10112   }
10113   else if (scanptr.p->scanCompletedStatus != ZTRUE)
10114   {
10115     jam();
10116     /*
10117     We come here when we have been scanning for a long time and not been able
10118     to find m_max_batch_size_rows records to return. We needed to release
10119     the record we didn't want, but now we are returning all found records to
10120     the API.
10121     */
10122     scanptr.p->scanState = ScanRecord::WAIT_SCAN_NEXTREQ;
10123     sendScanFragConf(signal, ZFALSE);
10124   }
10125   else
10126   {
10127     jam();
10128     closeScanLab(signal);
10129   }
10130 }//Dblqh::scanLockReleasedLab()
10131 
10132 bool
seize_acc_ptr_list(ScanRecord * scanP,Uint32 curr_batch_size,Uint32 new_batch_size)10133 Dblqh::seize_acc_ptr_list(ScanRecord* scanP,
10134                           Uint32 curr_batch_size,
10135                           Uint32 new_batch_size)
10136 {
10137   /*  1 maps to 0 segments
10138    * >1 maps to enough segments to store
10139    */
10140   Uint32 segments= (new_batch_size + (SectionSegment::DataLength -2 )) /
10141     SectionSegment::DataLength;
10142 
10143   if (segments <= scanP->scan_acc_segments)
10144   {
10145     // No need to allocate more segments.
10146     return true;
10147   }
10148 
10149   if (new_batch_size > 1)
10150   {
10151     for (Uint32 i = 1 + scanP->scan_acc_segments; i <= segments; i++)
10152     {
10153       Uint32 seg= seizeSegment();
10154       if (unlikely(seg == RNIL))
10155       {
10156         jam();
10157         /* Cleanup any allocated segments and return */
10158         scanP->scan_acc_segments= (i-1);
10159         release_acc_ptr_list(scanP);
10160         return false;
10161       }
10162       scanP->scan_acc_op_ptr[i]= seg;
10163     }
10164   }
10165   scanP->scan_acc_segments= segments;
10166   return true;
10167 }
10168 
10169 void
release_acc_ptr_list(ScanRecord * scanP)10170 Dblqh::release_acc_ptr_list(ScanRecord* scanP)
10171 {
10172   Uint32 i, segments;
10173   segments= scanP->scan_acc_segments;
10174 
10175   for (i= 1; i <= segments; i++) {
10176     releaseSection(scanP->scan_acc_op_ptr[i]);
10177   }
10178   scanP->scan_acc_segments= 0;
10179   scanP->scan_acc_index = 0;
10180 }
10181 
10182 Uint32
seizeSegment()10183 Dblqh::seizeSegment()
10184 {
10185   Uint32 junk= 0;
10186   Uint32 iVal= RNIL;
10187 
10188   /* Rather grungy way to grab a segment */
10189   if (!appendToSection(iVal, &junk, 1))
10190     return RNIL;
10191 
10192   return iVal;
10193 }
10194 
10195 void
init_acc_ptr_list(ScanRecord * scanP)10196 Dblqh::init_acc_ptr_list(ScanRecord* scanP)
10197 {
10198   scanP->scan_acc_index = 0;
10199 }
10200 
10201 Uint32
get_acc_ptr_from_scan_record(ScanRecord * scanP,Uint32 index,bool crash_flag)10202 Dblqh::get_acc_ptr_from_scan_record(ScanRecord* scanP,
10203                                     Uint32 index,
10204                                     bool crash_flag)
10205 {
10206   Uint32* acc_ptr;
10207   if (!((index < MAX_PARALLEL_OP_PER_SCAN) &&
10208        index < scanP->scan_acc_index)) {
10209     ndbrequire(crash_flag);
10210     return RNIL;
10211   }
10212   i_get_acc_ptr(scanP, acc_ptr, index);
10213   return *acc_ptr;
10214 }
10215 
10216 void
set_acc_ptr_in_scan_record(ScanRecord * scanP,Uint32 index,Uint32 acc)10217 Dblqh::set_acc_ptr_in_scan_record(ScanRecord* scanP,
10218                                   Uint32 index, Uint32 acc)
10219 {
10220   Uint32 *acc_ptr;
10221   ndbrequire((index == 0 || scanP->scan_acc_index == index) &&
10222              (index < MAX_PARALLEL_OP_PER_SCAN));
10223   scanP->scan_acc_index= index + 1;
10224   i_get_acc_ptr(scanP, acc_ptr, index);
10225   *acc_ptr= acc;
10226 }
10227 
10228 /* -------------------------------------------------------------------------
10229  * SCAN_FRAGREQ: Request to start scanning the specified fragment of a table.
10230  * ------------------------------------------------------------------------- */
execSCAN_FRAGREQ(Signal * signal)10231 void Dblqh::execSCAN_FRAGREQ(Signal* signal)
10232 {
10233   jamEntry();
10234 
10235   /* Reassemble if the request was fragmented */
10236   if (!assembleFragments(signal)){
10237     jam();
10238     return;
10239   }
10240 
10241   ScanFragReq * const scanFragReq = (ScanFragReq *)&signal->theData[0];
10242   ScanFragRef * ref;
10243   const Uint32 transid1 = scanFragReq->transId1;
10244   const Uint32 transid2 = scanFragReq->transId2;
10245   Uint32 errorCode= 0;
10246   Uint32 senderData;
10247   Uint32 hashIndex;
10248   TcConnectionrecPtr nextHashptr;
10249   Uint32 senderHi = signal->getSendersBlockRef();
10250 
10251   const Uint32 reqinfo = scanFragReq->requestInfo;
10252 
10253   /* Short SCANFRAGREQ has no sections, Long SCANFRAGREQ has 1 or 2
10254    * Section 0 : Mandatory ATTRINFO section
10255    * Section 1 : Optional KEYINFO section
10256    */
10257   const Uint32 numSections= signal->getNoOfSections();
10258   bool isLongReq= ( numSections != 0 );
10259 
10260   SectionHandle handle(this, signal);
10261 
10262   SegmentedSectionPtr attrInfoPtr, keyInfoPtr;
10263   Uint32 aiLen= 0;
10264   Uint32 keyLen= 0;
10265 
10266   if (likely(isLongReq))
10267   {
10268     /* Long request, get Attr + Key len from section sizes */
10269     handle.getSection(attrInfoPtr, ScanFragReq::AttrInfoSectionNum);
10270     aiLen= attrInfoPtr.sz;
10271 
10272     if (numSections == 2)
10273     {
10274       handle.getSection(keyInfoPtr, ScanFragReq::KeyInfoSectionNum);
10275       keyLen= keyInfoPtr.sz;
10276     }
10277   }
10278   else
10279   {
10280     /* Short request, get Attr + Key len from signal */
10281     aiLen= ScanFragReq::getAttrLen(reqinfo);
10282     keyLen= (scanFragReq->fragmentNoKeyLen >> 16);
10283   }
10284 
10285   const Uint32 fragId = (scanFragReq->fragmentNoKeyLen & 0xFFFF);
10286   tabptr.i = scanFragReq->tableId;
10287   const Uint32 max_rows = scanFragReq->batch_size_rows;
10288   const Uint32 scanLockMode = ScanFragReq::getLockMode(reqinfo);
10289   const Uint8 keyinfo = ScanFragReq::getKeyinfoFlag(reqinfo);
10290   const Uint8 rangeScan = ScanFragReq::getRangeScanFlag(reqinfo);
10291 
10292   ptrCheckGuard(tabptr, ctabrecFileSize, tablerec);
10293   if (tabptr.p->tableStatus != Tablerec::TABLE_DEFINED &&
10294       tabptr.p->tableStatus != Tablerec::TABLE_READ_ONLY)
10295   {
10296     senderData = scanFragReq->senderData;
10297     goto error_handler_early_1;
10298   }
10299 
10300   if (cfirstfreeTcConrec != RNIL && !ERROR_INSERTED_CLEAR(5055)) {
10301     seizeTcrec();
10302     tcConnectptr.p->clientConnectrec = scanFragReq->senderData;
10303     tcConnectptr.p->clientBlockref = signal->senderBlockRef();
10304     tcConnectptr.p->savePointId = scanFragReq->savePointId;
10305   } else {
10306     jam();
10307     /* --------------------------------------------------------------------
10308      *      NO FREE TC RECORD AVAILABLE, THUS WE CANNOT HANDLE THE REQUEST.
10309      * -------------------------------------------------------------------- */
10310     errorCode = ZNO_TC_CONNECT_ERROR;
10311     senderData = scanFragReq->senderData;
10312     goto error_handler_early;
10313   }//if
10314   /**
10315    * A write always has to get keyinfo
10316    */
10317   ndbrequire(scanLockMode == 0 || keyinfo);
10318 
10319   ndbrequire(max_rows > 0 && max_rows <= MAX_PARALLEL_OP_PER_SCAN);
10320   if (!getFragmentrec(signal, fragId)) {
10321     errorCode = 1231;
10322     goto error_handler;
10323   }//if
10324 
10325   // Verify scan type vs table type (both sides are boolean)
10326   if (rangeScan != DictTabInfo::isOrderedIndex(fragptr.p->tableType)) {
10327     errorCode = 1232;
10328     goto error_handler;
10329   }//if
10330 
10331   // XXX adjust cmaxAccOps for range scans and remove this comment
10332   if ((cbookedAccOps + max_rows) > cmaxAccOps) {
10333     jam();
10334     errorCode = ScanFragRef::ZSCAN_BOOK_ACC_OP_ERROR;
10335     goto error_handler;
10336   }//if
10337 
10338   if (ScanFragReq::getLcpScanFlag(reqinfo))
10339   {
10340     jam();
10341     ndbrequire(m_reserved_scans.first(scanptr));
10342     m_reserved_scans.remove(scanptr);
10343   }
10344   else if (!c_scanRecordPool.seize(scanptr))
10345   {
10346     jam();
10347     errorCode = ScanFragRef::ZNO_FREE_SCANREC_ERROR;
10348     goto error_handler;
10349   }
10350 
10351   initScanTc(scanFragReq,
10352              transid1,
10353              transid2,
10354              fragId,
10355              ZNIL,
10356              senderHi);
10357   tcConnectptr.p->save1 = 0;
10358   tcConnectptr.p->primKeyLen = keyLen;
10359   tcConnectptr.p->applRef = scanFragReq->resultRef;
10360   if (likely(isLongReq))
10361   {
10362     tcConnectptr.p->attrInfoIVal= attrInfoPtr.i;
10363     if (keyLen)
10364       tcConnectptr.p->keyInfoIVal= keyInfoPtr.i;
10365     /* Scan state machine is now responsible for freeing
10366      * these sections, usually via releaseOprec()
10367      */
10368     handle.clear();
10369   }
10370 
10371   if (ScanFragReq::getCorrFactorFlag(reqinfo))
10372   {
10373     /**
10374      * Correlattion factor for SPJ
10375      */
10376     tcConnectptr.p->m_corrFactorLo = scanFragReq->variableData[0];
10377     tcConnectptr.p->m_corrFactorHi = scanFragReq->variableData[1];
10378   }
10379 
10380   errorCode = initScanrec(scanFragReq, aiLen);
10381   if (errorCode != ZOK) {
10382     jam();
10383     goto error_handler2;
10384   }//if
10385   cbookedAccOps += max_rows;
10386 
10387   hashIndex = (tcConnectptr.p->transid[0] ^ tcConnectptr.p->tcOprec) & 1023;
10388   nextHashptr.i = ctransidHash[hashIndex];
10389   ctransidHash[hashIndex] = tcConnectptr.i;
10390   tcConnectptr.p->prevHashRec = RNIL;
10391   tcConnectptr.p->nextHashRec = nextHashptr.i;
10392   if (nextHashptr.i != RNIL) {
10393     jam();
10394     /* ---------------------------------------------------------------------
10395      *   ENSURE THAT THE NEXT RECORD HAS SET PREVIOUS TO OUR RECORD
10396      *   IF IT EXISTS
10397      * --------------------------------------------------------------------- */
10398     ptrCheckGuard(nextHashptr, ctcConnectrecFileSize, tcConnectionrec);
10399     nextHashptr.p->prevHashRec = tcConnectptr.i;
10400   }//if
10401   if ((! isLongReq ) &&
10402       ( scanptr.p->scanAiLength > 0 )) {
10403     jam();
10404     tcConnectptr.p->transactionState = TcConnectionrec::WAIT_SCAN_AI;
10405     return;
10406   }//if
10407   continueAfterReceivingAllAiLab(signal);
10408   return;
10409 
10410 error_handler2:
10411   // no scan number allocated
10412   if (scanptr.p->m_reserved == 0)
10413   {
10414     jam();
10415     c_scanRecordPool.release(scanptr);
10416   }
10417   else
10418   {
10419     jam();
10420     m_reserved_scans.add(scanptr);
10421   }
10422 error_handler:
10423   ref = (ScanFragRef*)&signal->theData[0];
10424   tcConnectptr.p->abortState = TcConnectionrec::ABORT_ACTIVE;
10425   ref->senderData = tcConnectptr.p->clientConnectrec;
10426   ref->transId1 = transid1;
10427   ref->transId2 = transid2;
10428   ref->errorCode = errorCode;
10429   sendSignal(tcConnectptr.p->clientBlockref, GSN_SCAN_FRAGREF, signal,
10430 	     ScanFragRef::SignalLength, JBB);
10431   releaseSections(handle);
10432   tcConnectptr.p->tcScanRec = RNIL;
10433   releaseOprec(signal);
10434   releaseTcrec(signal, tcConnectptr);
10435   return;
10436 
10437  error_handler_early_1:
10438   errorCode = get_table_state_error(tabptr);
10439 
10440  error_handler_early:
10441   releaseSections(handle);
10442   ref = (ScanFragRef*)&signal->theData[0];
10443   ref->senderData = senderData;
10444   ref->transId1 = transid1;
10445   ref->transId2 = transid2;
10446   ref->errorCode = errorCode;
10447   sendSignal(signal->senderBlockRef(), GSN_SCAN_FRAGREF, signal,
10448 	     ScanFragRef::SignalLength, JBB);
10449 }//Dblqh::execSCAN_FRAGREQ()
10450 
continueAfterReceivingAllAiLab(Signal * signal)10451 void Dblqh::continueAfterReceivingAllAiLab(Signal* signal)
10452 {
10453   tcConnectptr.p->transactionState = TcConnectionrec::SCAN_STATE_USED;
10454 
10455   if(scanptr.p->scanState == ScanRecord::IN_QUEUE){
10456     jam();
10457     return;
10458   }
10459 
10460   scanptr.p->scanState = ScanRecord::WAIT_ACC_SCAN;
10461   AccScanReq * req = (AccScanReq*)&signal->theData[0];
10462   req->senderData = scanptr.i;
10463   req->senderRef = cownref;
10464   req->tableId = tcConnectptr.p->tableref;
10465   req->fragmentNo = tcConnectptr.p->fragmentid;
10466   req->requestInfo = 0;
10467   AccScanReq::setLockMode(req->requestInfo, scanptr.p->scanLockMode);
10468   AccScanReq::setReadCommittedFlag(req->requestInfo, scanptr.p->readCommitted);
10469   AccScanReq::setDescendingFlag(req->requestInfo, scanptr.p->descending);
10470   AccScanReq::setStatScanFlag(req->requestInfo, scanptr.p->statScan);
10471 
10472   if (refToMain(tcConnectptr.p->clientBlockref) == BACKUP)
10473   {
10474     if (scanptr.p->lcpScan)
10475     {
10476       AccScanReq::setNoDiskScanFlag(req->requestInfo, 1);
10477       AccScanReq::setLcpScanFlag(req->requestInfo, 1);
10478     }
10479     else
10480     {
10481       /* If backup scan disktables in disk order */
10482       AccScanReq::setNoDiskScanFlag(req->requestInfo,
10483                                     !tcConnectptr.p->m_disk_table);
10484       AccScanReq::setLcpScanFlag(req->requestInfo, 0);
10485     }
10486   }
10487   else
10488   {
10489 #if BUG_27776_FIXED
10490     AccScanReq::setNoDiskScanFlag(req->requestInfo,
10491                                   !tcConnectptr.p->m_disk_table);
10492 #else
10493     AccScanReq::setNoDiskScanFlag(req->requestInfo, 1);
10494 #endif
10495     AccScanReq::setLcpScanFlag(req->requestInfo, 0);
10496   }
10497 
10498   req->transId1 = tcConnectptr.p->transid[0];
10499   req->transId2 = tcConnectptr.p->transid[1];
10500   req->savePointId = tcConnectptr.p->savePointId;
10501   sendSignal(scanptr.p->scanBlockref, GSN_ACC_SCANREQ, signal,
10502              AccScanReq::SignalLength, JBB);
10503 }//Dblqh::continueAfterReceivingAllAiLab()
10504 
scanAttrinfoLab(Signal * signal,Uint32 * dataPtr,Uint32 length)10505 void Dblqh::scanAttrinfoLab(Signal* signal, Uint32* dataPtr, Uint32 length)
10506 {
10507   scanptr.i = tcConnectptr.p->tcScanRec;
10508   c_scanRecordPool.getPtr(scanptr);
10509   if (saveAttrInfoInSection(dataPtr, length) == ZOK) {
10510     if (tcConnectptr.p->currTupAiLen < scanptr.p->scanAiLength) {
10511       jam();
10512     } else {
10513       jam();
10514       ndbrequire(tcConnectptr.p->currTupAiLen == scanptr.p->scanAiLength);
10515       continueAfterReceivingAllAiLab(signal);
10516     }//if
10517     return;
10518   }//if
10519   abort_scan(signal, scanptr.i, ZGET_ATTRINBUF_ERROR);
10520 }
10521 
abort_scan(Signal * signal,Uint32 scan_ptr_i,Uint32 errcode)10522 void Dblqh::abort_scan(Signal* signal, Uint32 scan_ptr_i, Uint32 errcode){
10523   jam();
10524   scanptr.i = scan_ptr_i;
10525   c_scanRecordPool.getPtr(scanptr);
10526 
10527   tcConnectptr.p->errorCode = errcode;
10528   tupScanCloseConfLab(signal);
10529   return;
10530 }
10531 
10532 /*---------------------------------------------------------------------*/
10533 /* Send this 'I am alive' signal to TC when it is received from ACC    */
10534 /* We include the scanPtr.i that comes from ACC in signalData[1], this */
10535 /* tells TC which fragment record to check for a timeout.              */
10536 /*---------------------------------------------------------------------*/
10537 void
check_send_scan_hb_rep(Signal * signal,ScanRecord * scanPtrP,TcConnectionrec * tcPtrP)10538 Dblqh::check_send_scan_hb_rep(Signal* signal,
10539                               ScanRecord* scanPtrP,
10540                               TcConnectionrec* tcPtrP)
10541 {
10542   switch(scanPtrP->scanType){
10543   case ScanRecord::SCAN:
10544     break;
10545   case ScanRecord::COPY:
10546     return;
10547 #ifdef NDEBUG
10548   case ScanRecord::ST_IDLE:
10549   default:
10550     return;
10551 #else
10552   case ScanRecord::ST_IDLE:
10553     ndbrequire(false);
10554 #endif
10555   }
10556 
10557   Uint64 now = cLqhTimeOutCount;         // measure in 10ms
10558   Uint64 last = scanPtrP->scanTcWaiting; // last time we reported to TC (10ms)
10559   Uint64 timeout = cTransactionDeadlockDetectionTimeout; // (ms)
10560   Uint64 limit = (3*timeout) / 4;
10561 
10562   bool alarm =
10563     now >= ((10 * last + limit) / 10) || now < last; // wrap
10564 
10565   if (alarm)
10566   {
10567     jam();
10568 
10569     scanPtrP->scanTcWaiting = Uint32(now);
10570     if (tcPtrP->tcTimer != 0)
10571     {
10572       tcPtrP->tcTimer = Uint32(now);
10573     }
10574 
10575     Uint32 save[3];
10576     save[0] = signal->theData[0];
10577     save[1] = signal->theData[1];
10578     save[2] = signal->theData[2];
10579 
10580     signal->theData[0] = tcPtrP->clientConnectrec;
10581     signal->theData[1] = tcPtrP->transid[0];
10582     signal->theData[2] = tcPtrP->transid[1];
10583     sendSignal(tcPtrP->clientBlockref,
10584                GSN_SCAN_HBREP, signal, 3, JBB);
10585 
10586     signal->theData[0] = save[0];
10587     signal->theData[1] = save[1];
10588     signal->theData[2] = save[2];
10589   }
10590 }
10591 
accScanConfScanLab(Signal * signal)10592 void Dblqh::accScanConfScanLab(Signal* signal)
10593 {
10594   AccScanConf * const accScanConf = (AccScanConf *)&signal->theData[0];
10595   tcConnectptr.i = scanptr.p->scanTcrec;
10596   ptrCheckGuard(tcConnectptr, ctcConnectrecFileSize, tcConnectionrec);
10597 
10598   /* -----------------------------------------------------------------------
10599    *       PRECONDITION: SCAN_STATE = WAIT_ACC_SCAN
10600    * ----------------------------------------------------------------------- */
10601   if (accScanConf->flag == AccScanConf::ZEMPTY_FRAGMENT) {
10602     jam();
10603     /* ---------------------------------------------------------------------
10604      *       THE FRAGMENT WAS EMPTY.
10605      *       REPORT SUCCESSFUL COPYING.
10606      * --------------------------------------------------------------------- */
10607     /*
10608      * MRR scan + delete can hit this when the fragment was not
10609      * initially empty, but has become empty after previous range.
10610      */
10611     if (scanptr.p->scanStoredProcId != RNIL) {
10612       jam();
10613       scanptr.p->scanCompletedStatus = ZTRUE;
10614       accScanCloseConfLab(signal);
10615       return;
10616     }
10617     tupScanCloseConfLab(signal);
10618     return;
10619   }//if
10620 
10621   check_send_scan_hb_rep(signal, scanptr.p, tcConnectptr.p);
10622 
10623   scanptr.p->scanAccPtr = accScanConf->accPtr;
10624   if (scanptr.p->rangeScan) {
10625     jam();
10626     TuxBoundInfo* req = (TuxBoundInfo*)signal->getDataPtrSend();
10627     req->errorCode = RNIL;
10628     req->tuxScanPtrI = scanptr.p->scanAccPtr;
10629     // TODO : Any improvements to be made on this block boundary?
10630     Uint32 len = req->boundAiLength = copyNextRange(req->data, tcConnectptr.p);
10631     EXECUTE_DIRECT(DBTUX, GSN_TUX_BOUND_INFO, signal,
10632 		   TuxBoundInfo::SignalLength + len);
10633 
10634     jamEntry();
10635     if (req->errorCode != 0) {
10636       jam();
10637       /*
10638        * Cannot use STORED_PROCREF to abort since even the REF
10639        * returns a stored proc id.  So record error and continue.
10640        * The scan is already Invalid in TUX and returns empty set.
10641        */
10642       tcConnectptr.p->errorCode = req->errorCode;
10643     }
10644   }
10645 
10646   scanptr.p->scanState = ScanRecord::WAIT_STORED_PROC_SCAN;
10647   if(scanptr.p->scanStoredProcId == RNIL)
10648   {
10649     jam();
10650     /* Send AttrInfo to TUP to store as 'stored procedure'
10651      * and get storedProcId back for future reference
10652      */
10653     signal->theData[0] = tcConnectptr.p->tupConnectrec;
10654     signal->theData[1] = tcConnectptr.p->tableref;
10655     signal->theData[2] = scanptr.p->scanSchemaVersion;
10656     signal->theData[3] = ZSTORED_PROC_SCAN;
10657 // theData[4] is not used
10658     signal->theData[5] = scanptr.p->scanApiBlockref;
10659 
10660     /* Pass ATTRINFO as long section, we don't need
10661      * it after this
10662      */
10663     SectionHandle handle(this);
10664     handle.m_ptr[0].i= tcConnectptr.p->attrInfoIVal;
10665     handle.m_cnt= 1;
10666     tcConnectptr.p->attrInfoIVal= RNIL;
10667     getSections(handle.m_cnt, handle.m_ptr);
10668 
10669     sendSignal(tcConnectptr.p->tcTupBlockref,
10670 	       GSN_STORED_PROCREQ, signal, 6, JBB,
10671                &handle);
10672   }
10673   else
10674   {
10675     /* TUP already has the Stored procedure, continue */
10676     jam();
10677     storedProcConfScanLab(signal);
10678   }
10679 }//Dblqh::accScanConfScanLab()
10680 
10681 Uint32
copyNextRange(Uint32 * dst,TcConnectionrec * tcPtrP)10682 Dblqh::copyNextRange(Uint32 * dst, TcConnectionrec* tcPtrP)
10683 {
10684   /**
10685    * Copy the bound info for the next range from the KeyInfo
10686    * to *dst
10687    * There may be zero or more bounds
10688    * A SectionReader is used to read bound information, its
10689    * position is saved between calls
10690    * This method also extracts range numbers from the
10691    * KeyInfo
10692    */
10693   Uint32 totalLen = tcPtrP->primKeyLen;
10694 
10695   if (totalLen)
10696   {
10697     ndbassert( tcPtrP->keyInfoIVal != RNIL );
10698     SectionReader keyInfoReader(tcPtrP->keyInfoIVal,
10699                                 g_sectionSegmentPool);
10700 
10701     if (tcPtrP->m_flags & TcConnectionrec::OP_SCANKEYINFOPOSSAVED)
10702     {
10703       /* Second or higher range in an MRR scan
10704        * Restore SectionReader to the last position it was in
10705        */
10706       bool ok= keyInfoReader.setPos(tcPtrP->scanKeyInfoPos);
10707       ndbrequire(ok);
10708     }
10709 
10710     /* Get first word of next range and extract range
10711      * length, number from it.
10712      * For non MRR, these will be zero.
10713      */
10714     Uint32 firstWord;
10715     ndbrequire( keyInfoReader.getWord(&firstWord) );
10716     const Uint32 rangeLen= (firstWord >> 16) ? (firstWord >> 16) : totalLen;
10717     Uint32 range_no = (firstWord & 0xFFF0) >> 4;
10718     tcPtrP->m_scan_curr_range_no= range_no;
10719     tcPtrP->m_corrFactorLo &= 0x0000FFFF;
10720     tcPtrP->m_corrFactorLo |= (range_no << 16);
10721     firstWord &= 0xF; // Remove length+range num from first word
10722 
10723     /* Write range info to dst */
10724     *(dst++)= firstWord;
10725     bool ok= keyInfoReader.getWords(dst, rangeLen - 1);
10726 
10727     ndbrequire(ok);
10728 
10729     tcPtrP->primKeyLen-= rangeLen;
10730 
10731     if (rangeLen == totalLen)
10732     {
10733       /* All range information has been copied, free the section */
10734       releaseSection(tcPtrP->keyInfoIVal);
10735       tcPtrP->keyInfoIVal= RNIL;
10736     }
10737     else
10738     {
10739       /* Save position of SectionReader for next range (if any) */
10740       tcPtrP->scanKeyInfoPos= keyInfoReader.getPos();
10741       tcPtrP->m_flags|= TcConnectionrec::OP_SCANKEYINFOPOSSAVED;
10742     }
10743 
10744     return rangeLen;
10745   }
10746 
10747   return totalLen;
10748 }
10749 
10750 /* -------------------------------------------------------------------------
10751  *       ENTER STORED_PROCCONF WITH
10752  *         TC_CONNECTPTR,
10753  *         TSTORED_PROC_ID
10754  * -------------------------------------------------------------------------
10755  *       PRECONDITION: SCAN_STATE = WAIT_STORED_PROC_SCAN
10756  * ------------------------------------------------------------------------- */
storedProcConfScanLab(Signal * signal)10757 void Dblqh::storedProcConfScanLab(Signal* signal)
10758 {
10759   fragptr.i = tcConnectptr.p->fragmentptr;
10760   c_fragment_pool.getPtr(fragptr);
10761   if (scanptr.p->scanCompletedStatus == ZTRUE) {
10762     jam();
10763     // STOP THE SCAN PROCESS IF THIS HAS BEEN REQUESTED.
10764     closeScanLab(signal);
10765     return;
10766   }//if
10767   switch (fragptr.p->fragStatus) {
10768   case Fragrecord::FSACTIVE:
10769     jam();
10770     break;
10771   case Fragrecord::BLOCKED:
10772     jam();
10773     linkFragQueue(signal);
10774     tcConnectptr.p->transactionState = TcConnectionrec::SCAN_FIRST_STOPPED;
10775     return;
10776     break;
10777   case Fragrecord::FREE:
10778     jam();
10779   case Fragrecord::ACTIVE_CREATION:
10780     jam();
10781   case Fragrecord::CRASH_RECOVERING:
10782     jam();
10783   case Fragrecord::DEFINED:
10784     jam();
10785   case Fragrecord::REMOVING:
10786     jam();
10787   default:
10788     jamLine(fragptr.p->fragStatus);
10789     ndbout_c("fragptr.p->fragStatus: %u",
10790              fragptr.p->fragStatus);
10791     // wl4391_todo SR 2-node CRASH_RECOVERING from BACKUP
10792     ndbrequire(false);
10793     break;
10794   }//switch
10795   continueFirstScanAfterBlockedLab(signal);
10796 }//Dblqh::storedProcConfScanLab()
10797 
continueFirstScanAfterBlockedLab(Signal * signal)10798 void Dblqh::continueFirstScanAfterBlockedLab(Signal* signal)
10799 {
10800   scanptr.i = tcConnectptr.p->tcScanRec;
10801   c_scanRecordPool.getPtr(scanptr);
10802   scanptr.p->scanState = ScanRecord::WAIT_NEXT_SCAN;
10803   signal->theData[0] = scanptr.p->scanAccPtr;
10804   signal->theData[1] = RNIL;
10805   signal->theData[2] = NextScanReq::ZSCAN_NEXT;
10806   sendSignal(scanptr.p->scanBlockref, GSN_NEXT_SCANREQ, signal, 3, JBB);
10807   return;
10808 }//Dblqh::continueFirstScanAfterBlockedLab()
10809 
10810 /* -------------------------------------------------------------------------
10811  * When executing a scan we must come up to the surface at times to make
10812  * sure we can quickly start local checkpoints.
10813  * ------------------------------------------------------------------------- */
execCHECK_LCP_STOP(Signal * signal)10814 void Dblqh::execCHECK_LCP_STOP(Signal* signal)
10815 {
10816   jamEntry();
10817   scanptr.i = signal->theData[0];
10818   c_scanRecordPool.getPtr(scanptr);
10819   tcConnectptr.i = scanptr.p->scanTcrec;
10820   ptrCheckGuard(tcConnectptr, ctcConnectrecFileSize, tcConnectionrec);
10821   fragptr.i = tcConnectptr.p->fragmentptr;
10822 
10823   c_fragment_pool.getPtr(fragptr);
10824   if (signal->theData[1] == ZTRUE) {
10825     jam();
10826     signal->theData[0] = ZCHECK_LCP_STOP_BLOCKED;
10827     signal->theData[1] = scanptr.i;
10828     sendSignalWithDelay(cownref, GSN_CONTINUEB, signal, 10, 2);
10829     signal->theData[0] = RNIL;
10830     return;
10831   }//if
10832   if (fragptr.p->fragStatus != Fragrecord::FSACTIVE) {
10833     ndbrequire(fragptr.p->fragStatus == Fragrecord::BLOCKED);
10834     linkFragQueue(signal);
10835     tcConnectptr.p->transactionState = TcConnectionrec::SCAN_CHECK_STOPPED;
10836     signal->theData[0] = RNIL;
10837   }//if
10838 }//Dblqh::execCHECK_LCP_STOP()
10839 
checkLcpStopBlockedLab(Signal * signal)10840 void Dblqh::checkLcpStopBlockedLab(Signal* signal)
10841 {
10842   switch (fragptr.p->fragStatus) {
10843   case Fragrecord::FSACTIVE:
10844     jam();
10845     continueAfterCheckLcpStopBlocked(signal);
10846     break;
10847   case Fragrecord::BLOCKED:
10848     jam();
10849     linkFragQueue(signal);
10850     tcConnectptr.p->transactionState = TcConnectionrec::SCAN_CHECK_STOPPED;
10851     return;
10852     break;
10853   case Fragrecord::FREE:
10854     jam();
10855   case Fragrecord::ACTIVE_CREATION:
10856     jam();
10857   case Fragrecord::CRASH_RECOVERING:
10858     jam();
10859   case Fragrecord::DEFINED:
10860     jam();
10861   case Fragrecord::REMOVING:
10862     jam();
10863   default:
10864     ndbrequire(false);
10865   }//switch
10866 }//Dblqh::checkLcpStopBlockedLab()
10867 
continueAfterCheckLcpStopBlocked(Signal * signal)10868 void Dblqh::continueAfterCheckLcpStopBlocked(Signal* signal)
10869 {
10870   scanptr.i = tcConnectptr.p->tcScanRec;
10871   c_scanRecordPool.getPtr(scanptr);
10872   signal->theData[0] = scanptr.p->scanAccPtr;
10873   signal->theData[1] = AccCheckScan::ZNOT_CHECK_LCP_STOP;
10874   EXECUTE_DIRECT(refToMain(scanptr.p->scanBlockref), GSN_ACC_CHECK_SCAN,
10875       signal, 2);
10876 }//Dblqh::continueAfterCheckLcpStopBlocked()
10877 
10878 /* -------------------------------------------------------------------------
10879  *       ENTER NEXT_SCANCONF
10880  * -------------------------------------------------------------------------
10881  *       PRECONDITION: SCAN_STATE = WAIT_NEXT_SCAN
10882  * ------------------------------------------------------------------------- */
nextScanConfScanLab(Signal * signal)10883 void Dblqh::nextScanConfScanLab(Signal* signal)
10884 {
10885   NextScanConf * const nextScanConf = (NextScanConf *)&signal->theData[0];
10886   tcConnectptr.i = scanptr.p->scanTcrec;
10887   ptrCheckGuard(tcConnectptr, ctcConnectrecFileSize, tcConnectionrec);
10888 
10889   if (nextScanConf->fragId == RNIL) {
10890     jam();
10891     /* ---------------------------------------------------------------------
10892      *       THERE ARE NO MORE TUPLES TO FETCH. IF WE HAVE ANY
10893      *       OPERATIONS STILL NEEDING A LOCK WE REPORT TO THE
10894      *       APPLICATION AND CLOSE THE SCAN WHEN THE NEXT SCAN
10895      *       REQUEST IS RECEIVED. IF WE DO NOT HAVE ANY NEED FOR
10896      *       LOCKS WE CAN CLOSE THE SCAN IMMEDIATELY.
10897      * --------------------------------------------------------------------- */
10898     /*************************************************************
10899      *       STOP THE SCAN PROCESS IF THIS HAS BEEN REQUESTED.
10900      ************************************************************ */
10901     if (!scanptr.p->scanLockHold)
10902     {
10903       jam();
10904       closeScanLab(signal);
10905       return;
10906     }
10907 
10908     if (scanptr.p->scanCompletedStatus == ZTRUE) {
10909       if ((scanptr.p->scanLockHold == ZTRUE) &&
10910 	  (scanptr.p->m_curr_batch_size_rows > 0)) {
10911 	jam();
10912 	scanptr.p->scanReleaseCounter = 1;
10913 	scanReleaseLocksLab(signal);
10914 	return;
10915       }//if
10916       jam();
10917       closeScanLab(signal);
10918       return;
10919     }//if
10920 
10921     if (scanptr.p->m_curr_batch_size_rows > 0) {
10922       jam();
10923 
10924       if((tcConnectptr.p->primKeyLen) == 0)
10925 	scanptr.p->scanCompletedStatus = ZTRUE;
10926 
10927       scanptr.p->scanState = ScanRecord::WAIT_SCAN_NEXTREQ;
10928       sendScanFragConf(signal, ZFALSE);
10929       return;
10930     }//if
10931     closeScanLab(signal);
10932     return;
10933   }//if
10934 
10935   // If accOperationPtr == RNIL no record was returned by ACC
10936   Uint32 accOpPtr = nextScanConf->accOperationPtr;
10937   if (accOpPtr == RNIL)
10938   {
10939     jam();
10940     /*************************************************************
10941      *       STOP THE SCAN PROCESS IF THIS HAS BEEN REQUESTED.
10942      ************************************************************ */
10943     if (scanptr.p->scanCompletedStatus == ZTRUE) {
10944       if ((scanptr.p->scanLockHold == ZTRUE) &&
10945 	  (scanptr.p->m_curr_batch_size_rows > 0)) {
10946 	jam();
10947 	scanptr.p->scanReleaseCounter = 1;
10948 	scanReleaseLocksLab(signal);
10949 	return;
10950       }//if
10951       jam();
10952       closeScanLab(signal);
10953       return;
10954     }//if
10955 
10956     if (scanptr.p->m_curr_batch_size_rows > 0) {
10957       jam();
10958       scanptr.p->scanState = ScanRecord::WAIT_SCAN_NEXTREQ;
10959       sendScanFragConf(signal, ZFALSE);
10960       return;
10961     }//if
10962 
10963     signal->theData[0] = scanptr.p->scanAccPtr;
10964     signal->theData[1] = AccCheckScan::ZCHECK_LCP_STOP;
10965     sendSignal(scanptr.p->scanBlockref,
10966                GSN_ACC_CHECK_SCAN, signal, 2, JBB);
10967     return;
10968   }//if
10969 
10970   jam();
10971   check_send_scan_hb_rep(signal, scanptr.p, tcConnectptr.p);
10972   set_acc_ptr_in_scan_record(scanptr.p,
10973                              scanptr.p->m_curr_batch_size_rows,
10974                              accOpPtr);
10975 
10976   jam();
10977   nextScanConfLoopLab(signal);
10978 }//Dblqh::nextScanConfScanLab()
10979 
nextScanConfLoopLab(Signal * signal)10980 void Dblqh::nextScanConfLoopLab(Signal* signal)
10981 {
10982   /* ----------------------------------------------------------------------
10983    *       STOP THE SCAN PROCESS IF THIS HAS BEEN REQUESTED.
10984    * ---------------------------------------------------------------------- */
10985   if (scanptr.p->scanCompletedStatus == ZTRUE) {
10986     jam();
10987     if ((scanptr.p->scanLockHold == ZTRUE) &&
10988         (scanptr.p->m_curr_batch_size_rows > 0)) {
10989       jam();
10990       scanptr.p->scanReleaseCounter = 1;
10991       scanReleaseLocksLab(signal);
10992       return;
10993     }//if
10994     closeScanLab(signal);
10995     return;
10996   }//if
10997 
10998   Fragrecord* fragPtrP= fragptr.p;
10999   if (scanptr.p->rangeScan) {
11000     jam();
11001     // for ordered index use primary table
11002     fragPtrP= c_fragment_pool.getPtr(fragPtrP->tableFragptr);
11003   }
11004 
11005   tcConnectptr.p->transactionState = TcConnectionrec::SCAN_TUPKEY;
11006   if(tcConnectptr.p->m_disk_table)
11007   {
11008     next_scanconf_load_diskpage(signal, scanptr, tcConnectptr,fragPtrP);
11009   }
11010   else
11011   {
11012     next_scanconf_tupkeyreq(signal, scanptr, tcConnectptr.p, fragPtrP, RNIL);
11013   }
11014 }
11015 
11016 void
next_scanconf_load_diskpage(Signal * signal,ScanRecordPtr scanPtr,Ptr<TcConnectionrec> regTcPtr,Fragrecord * fragPtrP)11017 Dblqh::next_scanconf_load_diskpage(Signal* signal,
11018 				   ScanRecordPtr scanPtr,
11019 				   Ptr<TcConnectionrec> regTcPtr,
11020 				   Fragrecord* fragPtrP)
11021 {
11022   jam();
11023 
11024   int res;
11025 
11026   if((res= c_tup->load_diskpage_scan(signal,
11027 				     regTcPtr.p->tupConnectrec,
11028 				     fragPtrP->tupFragptr,
11029 				     scanPtr.p->m_row_id.m_page_no,
11030 				     scanPtr.p->m_row_id.m_page_idx,
11031 				     0)) > 0)
11032   {
11033     next_scanconf_tupkeyreq(signal, scanptr, regTcPtr.p, fragPtrP, res);
11034   }
11035   else if(unlikely(res != 0))
11036   {
11037     jam();
11038     TupKeyRef * ref = (TupKeyRef *)signal->getDataPtr();
11039     ref->userRef= regTcPtr.i;
11040     ref->errorCode= ~0;
11041     execTUPKEYREF(signal);
11042   }
11043 }
11044 
11045 void
next_scanconf_load_diskpage_callback(Signal * signal,Uint32 callbackData,Uint32 disk_page)11046 Dblqh::next_scanconf_load_diskpage_callback(Signal* signal,
11047 					    Uint32 callbackData,
11048 					    Uint32 disk_page)
11049 {
11050   jamEntry();
11051 
11052   Ptr<TcConnectionrec> regTcPtr;
11053   regTcPtr.i= callbackData;
11054   ptrCheckGuard(regTcPtr, ctcConnectrecFileSize, tcConnectionrec);
11055 
11056   ScanRecordPtr scanPtr;
11057   c_scanRecordPool.getPtr(scanPtr, regTcPtr.p->tcScanRec);
11058 
11059   if(disk_page > 0)
11060   {
11061     FragrecordPtr fragPtr;
11062     c_fragment_pool.getPtr(fragPtr, regTcPtr.p->fragmentptr);
11063 
11064     if (scanPtr.p->rangeScan) {
11065       jam();
11066       // for ordered index use primary table
11067       fragPtr.p = c_fragment_pool.getPtr(fragPtr.p->tableFragptr);
11068     }
11069 
11070     next_scanconf_tupkeyreq(signal, scanPtr, regTcPtr.p, fragPtr.p, disk_page);
11071   }
11072   else
11073   {
11074     TupKeyRef * ref = (TupKeyRef *)signal->getDataPtr();
11075     ref->userRef= callbackData;
11076     ref->errorCode= disk_page;
11077     execTUPKEYREF(signal);
11078   }
11079 }
11080 
11081 void
next_scanconf_tupkeyreq(Signal * signal,Ptr<ScanRecord> scanPtr,TcConnectionrec * regTcPtr,Fragrecord * fragPtrP,Uint32 disk_page)11082 Dblqh::next_scanconf_tupkeyreq(Signal* signal,
11083 			       Ptr<ScanRecord> scanPtr,
11084 			       TcConnectionrec * regTcPtr,
11085 			       Fragrecord* fragPtrP,
11086 			       Uint32 disk_page)
11087 {
11088   jam();
11089   Uint32 reqinfo = (scanPtr.p->scanLockHold == ZFALSE);
11090   reqinfo = reqinfo + (regTcPtr->operation << 6);
11091   reqinfo = reqinfo + (regTcPtr->opExec << 10);
11092   reqinfo = reqinfo + (regTcPtr->m_reorg << 12);
11093 
11094   TupKeyReq * const tupKeyReq = (TupKeyReq *)signal->getDataPtrSend();
11095 
11096   tupKeyReq->connectPtr = regTcPtr->tupConnectrec;
11097   tupKeyReq->request = reqinfo;
11098   tupKeyReq->keyRef1 = scanPtr.p->m_row_id.m_page_no;
11099   tupKeyReq->keyRef2 = scanPtr.p->m_row_id.m_page_idx;
11100   tupKeyReq->attrBufLen = 0;
11101   tupKeyReq->opRef = scanPtr.p->scanApiOpPtr;
11102   tupKeyReq->applRef = scanPtr.p->scanApiBlockref;
11103   tupKeyReq->storedProcedure = scanPtr.p->scanStoredProcId;
11104   tupKeyReq->transId1 = regTcPtr->transid[0];
11105   tupKeyReq->transId2 = regTcPtr->transid[1];
11106   tupKeyReq->fragPtr = fragPtrP->tupFragptr;
11107   tupKeyReq->primaryReplica = (regTcPtr->seqNoReplica == 0)?true:false;
11108   tupKeyReq->coordinatorTC = regTcPtr->tcBlockref;
11109   tupKeyReq->tcOpIndex = regTcPtr->tcOprec;
11110   tupKeyReq->savePointId = regTcPtr->savePointId;
11111   tupKeyReq->disk_page= disk_page;
11112   /* No AttrInfo sent to TUP, it uses a stored procedure */
11113   tupKeyReq->attrInfoIVal= RNIL;
11114   Uint32 blockNo = refToMain(regTcPtr->tcTupBlockref);
11115   EXECUTE_DIRECT(blockNo, GSN_TUPKEYREQ, signal,
11116 		 TupKeyReq::SignalLength);
11117 }
11118 
11119 /* -------------------------------------------------------------------------
11120  *       STORE KEYINFO IN A LONG SECTION PRIOR TO SENDING
11121  * -------------------------------------------------------------------------
11122  *       PRECONDITION:   SCAN_STATE = WAIT_SCAN_KEYINFO
11123  * ------------------------------------------------------------------------- */
11124 bool
keyinfoLab(const Uint32 * src,Uint32 len)11125 Dblqh::keyinfoLab(const Uint32 * src, Uint32 len)
11126 {
11127   ndbassert( tcConnectptr.p->keyInfoIVal == RNIL );
11128   ndbassert( len > 0 );
11129 
11130   if (ERROR_INSERTED(5052) || ERROR_INSERTED_CLEAR(5060))
11131     return false;
11132 
11133   return(appendToSection(tcConnectptr.p->keyInfoIVal,
11134                          src,
11135                          len));
11136 }//Dblqh::keyinfoLab()
11137 
11138 Uint32
readPrimaryKeys(ScanRecord * scanP,TcConnectionrec * tcConP,Uint32 * dst)11139 Dblqh::readPrimaryKeys(ScanRecord *scanP, TcConnectionrec *tcConP, Uint32 *dst)
11140 {
11141   Uint32 tableId = tcConP->tableref;
11142   Uint32 fragId = tcConP->fragmentid;
11143   Uint32 fragPageId = scanP->m_row_id.m_page_no;
11144   Uint32 pageIndex = scanP->m_row_id.m_page_idx;
11145 
11146   if(scanP->rangeScan)
11147   {
11148     jam();
11149     // for ordered index use primary table
11150     FragrecordPtr tFragPtr;
11151     tFragPtr.i = fragptr.p->tableFragptr;
11152     c_fragment_pool.getPtr(tFragPtr);
11153     tableId = tFragPtr.p->tabRef;
11154   }
11155 
11156   int ret = c_tup->accReadPk(tableId, fragId, fragPageId, pageIndex, dst, false);
11157   jamEntry();
11158   if(0)
11159     ndbout_c("readPrimaryKeys(table: %d fragment: %d [ %d %d ] -> %d",
11160 	     tableId, fragId, fragPageId, pageIndex, ret);
11161   ndbassert(ret > 0);
11162 
11163   return ret;
11164 }
11165 
11166 /* -------------------------------------------------------------------------
11167  *         ENTER TUPKEYCONF
11168  * -------------------------------------------------------------------------
11169  *       PRECONDITION:   TRANSACTION_STATE = SCAN_TUPKEY
11170  * ------------------------------------------------------------------------- */
scanTupkeyConfLab(Signal * signal)11171 void Dblqh::scanTupkeyConfLab(Signal* signal)
11172 {
11173   const TupKeyConf * conf = (TupKeyConf *)signal->getDataPtr();
11174   UintR tdata4 = conf->readLength;
11175   UintR tdata5 = conf->lastRow;
11176 
11177   tcConnectptr.p->transactionState = TcConnectionrec::SCAN_STATE_USED;
11178   scanptr.i = tcConnectptr.p->tcScanRec;
11179   c_scanRecordPool.getPtr(scanptr);
11180 
11181   Uint32 rows = scanptr.p->m_curr_batch_size_rows;
11182   Uint32 accOpPtr= get_acc_ptr_from_scan_record(scanptr.p, rows, false);
11183   if (accOpPtr != (Uint32)-1)
11184   {
11185     c_acc->execACCKEY_ORD(signal, accOpPtr);
11186     jamEntry();
11187   }
11188   else
11189   {
11190     ndbassert(refToBlock(scanptr.p->scanBlockref) != DBACC);
11191   }
11192 
11193   if (scanptr.p->scanCompletedStatus == ZTRUE) {
11194     /* ---------------------------------------------------------------------
11195      *       STOP THE SCAN PROCESS IF THIS HAS BEEN REQUESTED.
11196      * --------------------------------------------------------------------- */
11197     if ((scanptr.p->scanLockHold == ZTRUE) && rows)
11198     {
11199       jam();
11200       scanptr.p->scanReleaseCounter = 1;
11201       scanReleaseLocksLab(signal);
11202       return;
11203     }//if
11204     jam();
11205     closeScanLab(signal);
11206     return;
11207   }//if
11208   if (scanptr.p->scanKeyinfoFlag) {
11209     jam();
11210     // Inform API about keyinfo len aswell
11211     tdata4 += sendKeyinfo20(signal, scanptr.p, tcConnectptr.p);
11212   }//if
11213   ndbrequire(scanptr.p->m_curr_batch_size_rows < MAX_PARALLEL_OP_PER_SCAN);
11214   scanptr.p->m_curr_batch_size_bytes+= tdata4;
11215   scanptr.p->m_curr_batch_size_rows = rows + 1;
11216   scanptr.p->m_last_row = tdata5;
11217   if (scanptr.p->check_scan_batch_completed() | tdata5){
11218     if (scanptr.p->scanLockHold == ZTRUE) {
11219       jam();
11220       scanptr.p->scanState = ScanRecord::WAIT_SCAN_NEXTREQ;
11221       sendScanFragConf(signal, ZFALSE);
11222       return;
11223     } else {
11224       jam();
11225       scanptr.p->scanReleaseCounter = rows + 1;
11226       scanReleaseLocksLab(signal);
11227       return;
11228     }
11229   } else {
11230     if (scanptr.p->scanLockHold == ZTRUE) {
11231       jam();
11232       scanptr.p->scanFlag = NextScanReq::ZSCAN_NEXT;
11233     } else {
11234       jam();
11235       scanptr.p->scanFlag = NextScanReq::ZSCAN_NEXT_COMMIT;
11236     }
11237   }
11238   scanNextLoopLab(signal);
11239 }//Dblqh::scanTupkeyConfLab()
11240 
scanNextLoopLab(Signal * signal)11241 void Dblqh::scanNextLoopLab(Signal* signal)
11242 {
11243   switch (fragptr.p->fragStatus) {
11244   case Fragrecord::FSACTIVE:
11245     jam();
11246     break;
11247   case Fragrecord::BLOCKED:
11248     jam();
11249     linkFragQueue(signal);
11250     tcConnectptr.p->transactionState = TcConnectionrec::SCAN_STOPPED;
11251     return;
11252     break;
11253   case Fragrecord::FREE:
11254     jam();
11255   case Fragrecord::ACTIVE_CREATION:
11256     jam();
11257   case Fragrecord::CRASH_RECOVERING:
11258     jam();
11259   case Fragrecord::DEFINED:
11260     jam();
11261   case Fragrecord::REMOVING:
11262     jam();
11263   default:
11264     ndbrequire(false);
11265   }//switch
11266   continueScanAfterBlockedLab(signal);
11267 }//Dblqh::scanNextLoopLab()
11268 
continueScanAfterBlockedLab(Signal * signal)11269 void Dblqh::continueScanAfterBlockedLab(Signal* signal)
11270 {
11271   scanptr.i = tcConnectptr.p->tcScanRec;
11272   c_scanRecordPool.getPtr(scanptr);
11273   Uint32 accOpPtr;
11274   if (scanptr.p->scanFlag == NextScanReq::ZSCAN_NEXT_ABORT) {
11275     jam();
11276     scanptr.p->scanFlag = NextScanReq::ZSCAN_NEXT_COMMIT;
11277     accOpPtr= get_acc_ptr_from_scan_record(scanptr.p,
11278 					   scanptr.p->m_curr_batch_size_rows,
11279 					   false);
11280     scanptr.p->scan_acc_index--;
11281   } else if (scanptr.p->scanFlag == NextScanReq::ZSCAN_NEXT_COMMIT) {
11282     jam();
11283     accOpPtr= get_acc_ptr_from_scan_record(scanptr.p,
11284 					   scanptr.p->m_curr_batch_size_rows-1,
11285 					   false);
11286   } else {
11287     jam();
11288     accOpPtr = RNIL; // The value is not used in ACC
11289   }//if
11290   scanptr.p->scanState = ScanRecord::WAIT_NEXT_SCAN;
11291   signal->theData[0] = scanptr.p->scanAccPtr;
11292   signal->theData[1] = accOpPtr;
11293   signal->theData[2] = scanptr.p->scanFlag;
11294   sendSignal(scanptr.p->scanBlockref, GSN_NEXT_SCANREQ, signal, 3, JBB);
11295 }//Dblqh::continueScanAfterBlockedLab()
11296 
11297 /* -------------------------------------------------------------------------
11298  *         ENTER TUPKEYREF WITH
11299  *               TC_CONNECTPTR,
11300  *               TERROR_CODE
11301  * -------------------------------------------------------------------------
11302  *       PRECONDITION:   TRANSACTION_STATE = SCAN_TUPKEY
11303  * ------------------------------------------------------------------------- */
scanTupkeyRefLab(Signal * signal)11304 void Dblqh::scanTupkeyRefLab(Signal* signal)
11305 {
11306   tcConnectptr.p->transactionState = TcConnectionrec::SCAN_STATE_USED;
11307   scanptr.i = tcConnectptr.p->tcScanRec;
11308   c_scanRecordPool.getPtr(scanptr);
11309 
11310   Uint32 rows = scanptr.p->m_curr_batch_size_rows;
11311   Uint32 accOpPtr= get_acc_ptr_from_scan_record(scanptr.p, rows, false);
11312   if (accOpPtr != (Uint32)-1)
11313   {
11314     c_acc->execACCKEY_ORD(signal, accOpPtr);
11315   }
11316   else
11317   {
11318     ndbassert(refToBlock(scanptr.p->scanBlockref) != DBACC);
11319   }
11320 
11321   if (scanptr.p->scanCompletedStatus == ZTRUE) {
11322     /* ---------------------------------------------------------------------
11323      *       STOP THE SCAN PROCESS IF THIS HAS BEEN REQUESTED.
11324      * --------------------------------------------------------------------- */
11325     if ((scanptr.p->scanLockHold == ZTRUE) && rows)
11326     {
11327       jam();
11328       scanptr.p->scanReleaseCounter = 1;
11329       scanReleaseLocksLab(signal);
11330       return;
11331     }//if
11332     jam();
11333     closeScanLab(signal);
11334     return;
11335   }//if
11336   if ((terrorCode != ZSEARCH_CONDITION_FALSE) &&
11337       (terrorCode != ZNO_TUPLE_FOUND) &&
11338       (terrorCode >= ZUSER_ERROR_CODE_LIMIT)) {
11339     scanptr.p->scanErrorCounter++;
11340     tcConnectptr.p->errorCode = terrorCode;
11341 
11342     if (scanptr.p->scanLockHold == ZTRUE) {
11343       jam();
11344       scanptr.p->scanReleaseCounter = 1;
11345     } else {
11346       jam();
11347       scanptr.p->m_curr_batch_size_rows = rows + 1;
11348       scanptr.p->scanReleaseCounter = rows + 1;
11349     }//if
11350     /* --------------------------------------------------------------------
11351      *       WE NEED TO RELEASE ALL LOCKS CURRENTLY
11352      *       HELD BY THIS SCAN.
11353      * -------------------------------------------------------------------- */
11354     scanReleaseLocksLab(signal);
11355     return;
11356   }//if
11357   Uint32 time_passed= tcConnectptr.p->tcTimer - cLqhTimeOutCount;
11358   if (rows)
11359   {
11360     if (time_passed > 1)
11361     {
11362   /* -----------------------------------------------------------------------
11363    *  WE NEED TO ENSURE THAT WE DO NOT SEARCH FOR THE NEXT TUPLE FOR A
11364    *  LONG TIME WHILE WE KEEP A LOCK ON A FOUND TUPLE. WE RATHER REPORT
11365    *  THE FOUND TUPLE IF FOUND TUPLES ARE RARE. If more than 10 ms passed we
11366    *  send the found tuples to the API.
11367    * ----------------------------------------------------------------------- */
11368       scanptr.p->scanReleaseCounter = rows + 1;
11369       scanReleaseLocksLab(signal);
11370       return;
11371     }
11372   }
11373 
11374   scanptr.p->scanFlag = NextScanReq::ZSCAN_NEXT_ABORT;
11375   scanNextLoopLab(signal);
11376 }//Dblqh::scanTupkeyRefLab()
11377 
11378 /* -------------------------------------------------------------------------
11379  *   THE SCAN HAS BEEN COMPLETED. EITHER BY REACHING THE END OR BY COMMAND
11380  *   FROM THE APPLICATION OR BY SOME SORT OF ERROR CONDITION.
11381  * ------------------------------------------------------------------------- */
closeScanLab(Signal * signal)11382 void Dblqh::closeScanLab(Signal* signal)
11383 {
11384   fragptr.i = tcConnectptr.p->fragmentptr;
11385   c_fragment_pool.getPtr(fragptr);
11386   switch (fragptr.p->fragStatus) {
11387   case Fragrecord::FSACTIVE:
11388     jam();
11389     break;
11390   case Fragrecord::BLOCKED:
11391     jam();
11392     linkFragQueue(signal);
11393     tcConnectptr.p->transactionState = TcConnectionrec::SCAN_CLOSE_STOPPED;
11394     return;
11395     break;
11396   case Fragrecord::FREE:
11397     jam();
11398   case Fragrecord::ACTIVE_CREATION:
11399     jam();
11400   case Fragrecord::CRASH_RECOVERING:
11401     jam();
11402   case Fragrecord::DEFINED:
11403     jam();
11404   case Fragrecord::REMOVING:
11405     jam();
11406   default:
11407     ndbrequire(false);
11408   }//switch
11409   continueCloseScanAfterBlockedLab(signal);
11410 }//Dblqh::closeScanLab()
11411 
continueCloseScanAfterBlockedLab(Signal * signal)11412 void Dblqh::continueCloseScanAfterBlockedLab(Signal* signal)
11413 {
11414   tcConnectptr.p->transactionState = TcConnectionrec::SCAN_STATE_USED;
11415   scanptr.i = tcConnectptr.p->tcScanRec;
11416   c_scanRecordPool.getPtr(scanptr);
11417   scanptr.p->scanState = ScanRecord::WAIT_CLOSE_SCAN;
11418   signal->theData[0] = scanptr.p->scanAccPtr;
11419   signal->theData[1] = RNIL;
11420   signal->theData[2] = NextScanReq::ZSCAN_CLOSE;
11421   sendSignal(scanptr.p->scanBlockref, GSN_NEXT_SCANREQ, signal, 3, JBB);
11422 }//Dblqh::continueCloseScanAfterBlockedLab()
11423 
11424 /* -------------------------------------------------------------------------
11425  *       ENTER NEXT_SCANCONF
11426  * -------------------------------------------------------------------------
11427  *       PRECONDITION: SCAN_STATE = WAIT_CLOSE_SCAN
11428  * ------------------------------------------------------------------------- */
accScanCloseConfLab(Signal * signal)11429 void Dblqh::accScanCloseConfLab(Signal* signal)
11430 {
11431   tcConnectptr.i = scanptr.p->scanTcrec;
11432   ptrCheckGuard(tcConnectptr, ctcConnectrecFileSize, tcConnectionrec);
11433 
11434   /* Do we have another range to scan? */
11435   if((tcConnectptr.p->primKeyLen > 0) &&
11436      (scanptr.p->scanCompletedStatus != ZTRUE))
11437   {
11438     jam();
11439     /* Start next range scan...*/
11440     continueAfterReceivingAllAiLab(signal);
11441     return;
11442   }
11443 
11444   scanptr.p->scanState = ScanRecord::WAIT_DELETE_STORED_PROC_ID_SCAN;
11445   signal->theData[0] = tcConnectptr.p->tupConnectrec;
11446   signal->theData[1] = tcConnectptr.p->tableref;
11447   signal->theData[2] = scanptr.p->scanSchemaVersion;
11448   signal->theData[3] = ZDELETE_STORED_PROC_ID;
11449   signal->theData[4] = scanptr.p->scanStoredProcId;
11450   signal->theData[5] = scanptr.p->scanApiBlockref;
11451   sendSignal(tcConnectptr.p->tcTupBlockref,
11452              GSN_STORED_PROCREQ, signal, 6, JBB);
11453 }//Dblqh::accScanCloseConfLab()
11454 
11455 /* -------------------------------------------------------------------------
11456  *       ENTER STORED_PROCCONF WITH
11457  * -------------------------------------------------------------------------
11458  * PRECONDITION: SCAN_STATE = WAIT_DELETE_STORED_PROC_ID_SCAN
11459  * ------------------------------------------------------------------------- */
tupScanCloseConfLab(Signal * signal)11460 void Dblqh::tupScanCloseConfLab(Signal* signal)
11461 {
11462   fragptr.i = tcConnectptr.p->fragmentptr;
11463   c_fragment_pool.getPtr(fragptr);
11464   if (tcConnectptr.p->abortState == TcConnectionrec::NEW_FROM_TC) {
11465     jam();
11466     tcNodeFailptr.i = tcConnectptr.p->tcNodeFailrec;
11467     ptrCheckGuard(tcNodeFailptr, ctcNodeFailrecFileSize, tcNodeFailRecord);
11468     tcNodeFailptr.p->tcRecNow = tcConnectptr.i + 1;
11469     signal->theData[0] = ZLQH_TRANS_NEXT;
11470     signal->theData[1] = tcNodeFailptr.i;
11471     sendSignal(cownref, GSN_CONTINUEB, signal, 2, JBB);
11472   } else if (tcConnectptr.p->errorCode != 0) {
11473     jam();
11474     ScanFragRef * ref = (ScanFragRef*)&signal->theData[0];
11475     ref->senderData = tcConnectptr.p->clientConnectrec;
11476     ref->transId1 = tcConnectptr.p->transid[0];
11477     ref->transId2 = tcConnectptr.p->transid[1];
11478     ref->errorCode = tcConnectptr.p->errorCode;
11479     sendSignal(tcConnectptr.p->clientBlockref, GSN_SCAN_FRAGREF, signal,
11480 	 ScanFragRef::SignalLength, JBB);
11481   } else {
11482     jam();
11483     sendScanFragConf(signal, ZSCAN_FRAG_CLOSED);
11484   }//if
11485   finishScanrec(signal);
11486   releaseScanrec(signal);
11487   tcConnectptr.p->tcScanRec = RNIL;
11488   deleteTransidHash(signal);
11489   releaseOprec(signal);
11490   releaseTcrec(signal, tcConnectptr);
11491 }//Dblqh::tupScanCloseConfLab()
11492 
11493 /* =========================================================================
11494  * =======              INITIATE SCAN RECORD                         =======
11495  *
11496  *       SUBROUTINE SHORT NAME = ISC
11497  * ========================================================================= */
initScanrec(const ScanFragReq * scanFragReq,Uint32 aiLen)11498 Uint32 Dblqh::initScanrec(const ScanFragReq* scanFragReq,
11499                           Uint32 aiLen)
11500 {
11501   const Uint32 reqinfo = scanFragReq->requestInfo;
11502   const Uint32 max_rows = scanFragReq->batch_size_rows;
11503   const Uint32 max_bytes = scanFragReq->batch_size_bytes;
11504   const Uint32 scanLockMode = ScanFragReq::getLockMode(reqinfo);
11505   const Uint32 scanLockHold = ScanFragReq::getHoldLockFlag(reqinfo);
11506   const Uint32 keyinfo = ScanFragReq::getKeyinfoFlag(reqinfo);
11507   const Uint32 readCommitted = ScanFragReq::getReadCommittedFlag(reqinfo);
11508   const Uint32 rangeScan = ScanFragReq::getRangeScanFlag(reqinfo);
11509   const Uint32 descending = ScanFragReq::getDescendingFlag(reqinfo);
11510   Uint32 tupScan = ScanFragReq::getTupScanFlag(reqinfo);
11511   const Uint32 scanPrio = ScanFragReq::getScanPrio(reqinfo);
11512   const Uint32 accScan = (rangeScan == 0) && (tupScan == 0);
11513 
11514   scanptr.p->scanKeyinfoFlag = keyinfo;
11515   scanptr.p->scanLockHold = scanLockHold;
11516   scanptr.p->scanCompletedStatus = ZFALSE;
11517   scanptr.p->scanType = ScanRecord::SCAN;
11518   scanptr.p->scanApiBlockref = scanFragReq->resultRef;
11519   scanptr.p->scanAiLength = aiLen;
11520   scanptr.p->scanTcrec = tcConnectptr.i;
11521   scanptr.p->scanSchemaVersion = scanFragReq->schemaVersion;
11522 
11523   scanptr.p->m_curr_batch_size_rows = 0;
11524   scanptr.p->m_curr_batch_size_bytes= 0;
11525   scanptr.p->m_max_batch_size_rows = max_rows;
11526   scanptr.p->m_max_batch_size_bytes = max_bytes;
11527 
11528   if (accScan)
11529     scanptr.p->scanBlockref = tcConnectptr.p->tcAccBlockref;
11530   else if (! tupScan)
11531     scanptr.p->scanBlockref = tcConnectptr.p->tcTuxBlockref;
11532   else
11533     scanptr.p->scanBlockref = tcConnectptr.p->tcTupBlockref;
11534 
11535   scanptr.p->scanErrorCounter = 0;
11536   scanptr.p->scanLockMode = scanLockMode;
11537   scanptr.p->readCommitted = readCommitted;
11538   scanptr.p->rangeScan = rangeScan;
11539   scanptr.p->descending = descending;
11540   scanptr.p->tupScan = tupScan;
11541   scanptr.p->lcpScan = ScanFragReq::getLcpScanFlag(reqinfo);
11542   scanptr.p->statScan = ScanFragReq::getStatScanFlag(reqinfo);
11543   scanptr.p->scanState = ScanRecord::SCAN_FREE;
11544   scanptr.p->scanFlag = ZFALSE;
11545   scanptr.p->m_row_id.setNull();
11546   scanptr.p->scanTcWaiting = cLqhTimeOutCount;
11547   scanptr.p->scanNumber = ~0;
11548   scanptr.p->scanApiOpPtr = scanFragReq->clientOpPtr;
11549   scanptr.p->m_last_row = 0;
11550   scanptr.p->scanStoredProcId = RNIL;
11551   scanptr.p->copyPtr = RNIL;
11552   if (max_rows == 0 || (max_bytes > 0 && max_rows > max_bytes)){
11553     jam();
11554     return ScanFragRef::ZWRONG_BATCH_SIZE;
11555   }
11556 
11557   if (ERROR_INSERTED(5057))
11558   {
11559     CLEAR_ERROR_INSERT_VALUE;
11560     return ScanFragRef::ZTOO_MANY_ACTIVE_SCAN_ERROR;
11561   }
11562 
11563   scanptr.p->scan_acc_segments = 0;
11564   if (!seize_acc_ptr_list(scanptr.p, 0, max_rows)){
11565     jam();
11566     return ScanFragRef::ZTOO_MANY_ACTIVE_SCAN_ERROR;
11567   }
11568   init_acc_ptr_list(scanptr.p);
11569 
11570   /**
11571    * Used for scan take over
11572    */
11573   FragrecordPtr tFragPtr;
11574   tFragPtr.i = fragptr.p->tableFragptr;
11575   c_fragment_pool.getPtr(tFragPtr);
11576   scanptr.p->fragPtrI = fragptr.p->tableFragptr;
11577 
11578   /**
11579    * !idx uses 1 - (MAX_PARALLEL_SCANS_PER_FRAG - 1)  =  1-11
11580    *  idx uses from MAX_PARALLEL_SCANS_PER_FRAG - MAX = 12-42)
11581    */
11582 
11583   /**
11584    * ACC only supports 12 parallel scans per fragment (hard limit)
11585    * TUP/TUX does not have any such limit...but when scanning with keyinfo
11586    *         (for take-over) no more than 255 such scans can be active
11587    *         at a fragment (dur to 8 bit number in scan-keyinfo protocol)
11588    *
11589    * TODO: Make TUP/TUX limits depend on scanKeyinfoFlag (possibly with
11590    *       other config limit too)
11591    */
11592 
11593   Uint32 start, stop;
11594   Uint32 max_parallel_scans_per_frag = c_max_parallel_scans_per_frag;
11595   if (accScan)
11596   {
11597     start = 1;
11598     stop = MAX_PARALLEL_SCANS_PER_FRAG - 1;
11599   }
11600   else if (rangeScan)
11601   {
11602     start = MAX_PARALLEL_SCANS_PER_FRAG;
11603     stop = start + max_parallel_scans_per_frag - 1;
11604   }
11605   else
11606   {
11607     ndbassert(tupScan);
11608     start = MAX_PARALLEL_SCANS_PER_FRAG + max_parallel_scans_per_frag;
11609     stop = start + max_parallel_scans_per_frag - 1;
11610   }
11611   ndbrequire((start < 32 * tFragPtr.p->m_scanNumberMask.Size) &&
11612              (stop < 32 * tFragPtr.p->m_scanNumberMask.Size));
11613   Uint32 free = tFragPtr.p->m_scanNumberMask.find(start);
11614 
11615   if(free == Fragrecord::ScanNumberMask::NotFound || free >= stop){
11616     jam();
11617 
11618     if(scanPrio == 0){
11619       jam();
11620       return ScanFragRef::ZTOO_MANY_ACTIVE_SCAN_ERROR;
11621     }
11622 
11623     /**
11624      * Put on queue
11625      */
11626     scanptr.p->scanState = ScanRecord::IN_QUEUE;
11627     LocalDLFifoList<ScanRecord> queue(c_scanRecordPool,
11628 				      tupScan == 0 ?
11629                                       fragptr.p->m_queuedScans :
11630                                       fragptr.p->m_queuedTupScans);
11631     queue.add(scanptr);
11632     return ZOK;
11633   }
11634 
11635   scanptr.p->scanNumber = free;
11636   tFragPtr.p->m_scanNumberMask.clear(free);// Update mask
11637 
11638   LocalDLList<ScanRecord> active(c_scanRecordPool, fragptr.p->m_activeScans);
11639   active.add(scanptr);
11640   if(scanptr.p->scanKeyinfoFlag){
11641     jam();
11642 #if defined VM_TRACE || defined ERROR_INSERT
11643     ScanRecordPtr tmp;
11644     ndbrequire(!c_scanTakeOverHash.find(tmp, * scanptr.p));
11645 #endif
11646 #ifdef TRACE_SCAN_TAKEOVER
11647     ndbout_c("adding (%d %d) table: %d fragId: %d frag.i: %d tableFragptr: %d",
11648 	     scanptr.p->scanNumber, scanptr.p->fragPtrI,
11649 	     tabptr.i, scanFragReq->fragmentNoKeyLen & 0xFFFF,
11650 	     fragptr.i, fragptr.p->tableFragptr);
11651 #endif
11652     c_scanTakeOverHash.add(scanptr);
11653   }
11654   return ZOK;
11655 }
11656 
11657 /* =========================================================================
11658  * =======             INITIATE TC RECORD AT SCAN                    =======
11659  *
11660  *       SUBROUTINE SHORT NAME = IST
11661  * ========================================================================= */
initScanTc(const ScanFragReq * req,Uint32 transid1,Uint32 transid2,Uint32 fragId,Uint32 nodeId,Uint32 hashHi)11662 void Dblqh::initScanTc(const ScanFragReq* req,
11663                        Uint32 transid1,
11664                        Uint32 transid2,
11665                        Uint32 fragId,
11666                        Uint32 nodeId,
11667                        Uint32 hashHi)
11668 {
11669   tcConnectptr.p->transid[0] = transid1;
11670   tcConnectptr.p->transid[1] = transid2;
11671   tcConnectptr.p->tcScanRec = scanptr.i;
11672   tcConnectptr.p->tableref = tabptr.i;
11673   tcConnectptr.p->fragmentid = fragId;
11674   tcConnectptr.p->fragmentptr = fragptr.i;
11675   tcConnectptr.p->tcOprec = tcConnectptr.p->clientConnectrec;
11676   tcConnectptr.p->tcHashKeyHi = hashHi;
11677   tcConnectptr.p->tcBlockref = tcConnectptr.p->clientBlockref;
11678   tcConnectptr.p->errorCode = 0;
11679   tcConnectptr.p->reclenAiLqhkey = 0;
11680   tcConnectptr.p->abortState = TcConnectionrec::ABORT_IDLE;
11681   tcConnectptr.p->nextReplica = nodeId;
11682   tcConnectptr.p->currTupAiLen = 0;
11683   tcConnectptr.p->opExec = 1;
11684   tcConnectptr.p->operation = ZREAD;
11685   tcConnectptr.p->listState = TcConnectionrec::NOT_IN_LIST;
11686   tcConnectptr.p->commitAckMarker = RNIL;
11687   tcConnectptr.p->m_scan_curr_range_no = 0;
11688   tcConnectptr.p->m_dealloc = 0;
11689   tcConnectptr.p->activeCreat = Fragrecord::AC_NORMAL;
11690   // set TcConnectionrec::OP_SAVEATTRINFO so that a
11691   // "old" scan (short signals) update currTupAiLen which is checked
11692   // in scanAttrinfoLab
11693   tcConnectptr.p->m_flags = TcConnectionrec::OP_SAVEATTRINFO;
11694   TablerecPtr tTablePtr;
11695   tTablePtr.i = tabptr.p->primaryTableId;
11696   ptrCheckGuard(tTablePtr, ctabrecFileSize, tablerec);
11697   tcConnectptr.p->m_disk_table = tTablePtr.p->m_disk_table &&
11698     (!req || !ScanFragReq::getNoDiskFlag(req->requestInfo));
11699   tcConnectptr.p->m_reorg =
11700     req ? ScanFragReq::getReorgFlag(req->requestInfo) : 0;
11701 
11702   tabptr.p->usageCountR++;
11703 }//Dblqh::initScanTc()
11704 
11705 /* =========================================================================
11706  * =======                       FINISH  SCAN RECORD                 =======
11707  *
11708  *       REMOVE SCAN RECORD FROM PER FRAGMENT LIST.
11709  * ========================================================================= */
finishScanrec(Signal * signal)11710 void Dblqh::finishScanrec(Signal* signal)
11711 {
11712   release_acc_ptr_list(scanptr.p);
11713 
11714   Uint32 tupScan = scanptr.p->tupScan;
11715   LocalDLFifoList<ScanRecord> queue(c_scanRecordPool,
11716                                     tupScan == 0 ?
11717                                     fragptr.p->m_queuedScans :
11718                                     fragptr.p->m_queuedTupScans);
11719 
11720   if (scanptr.p->scanState == ScanRecord::IN_QUEUE)
11721   {
11722     jam();
11723     if (scanptr.p->m_reserved == 0)
11724     {
11725       jam();
11726       queue.release(scanptr);
11727     }
11728     else
11729     {
11730       jam();
11731       queue.remove(scanptr);
11732       m_reserved_scans.add(scanptr);
11733     }
11734 
11735     return;
11736   }
11737 
11738   if(scanptr.p->scanKeyinfoFlag){
11739     jam();
11740     ScanRecordPtr tmp;
11741 #ifdef TRACE_SCAN_TAKEOVER
11742     ndbout_c("removing (%d %d)", scanptr.p->scanNumber, scanptr.p->fragPtrI);
11743 #endif
11744     c_scanTakeOverHash.remove(tmp, * scanptr.p);
11745     ndbrequire(tmp.p == scanptr.p);
11746   }
11747 
11748   LocalDLList<ScanRecord> scans(c_scanRecordPool, fragptr.p->m_activeScans);
11749   if (scanptr.p->m_reserved == 0)
11750   {
11751     jam();
11752     scans.release(scanptr);
11753   }
11754   else
11755   {
11756     jam();
11757     scans.remove(scanptr);
11758     m_reserved_scans.add(scanptr);
11759   }
11760 
11761   FragrecordPtr tFragPtr;
11762   tFragPtr.i = scanptr.p->fragPtrI;
11763   c_fragment_pool.getPtr(tFragPtr);
11764 
11765   const Uint32 scanNumber = scanptr.p->scanNumber;
11766   ndbrequire(!tFragPtr.p->m_scanNumberMask.get(scanNumber));
11767   ScanRecordPtr restart;
11768 
11769   /**
11770    * Start on of queued scans
11771    */
11772   if(scanNumber == NR_ScanNo || !queue.first(restart)){
11773     jam();
11774     tFragPtr.p->m_scanNumberMask.set(scanNumber);
11775     return;
11776   }
11777 
11778   if(ERROR_INSERTED(5034)){
11779     jam();
11780     tFragPtr.p->m_scanNumberMask.set(scanNumber);
11781     return;
11782   }
11783 
11784   ndbrequire(restart.p->scanState == ScanRecord::IN_QUEUE);
11785 
11786   ScanRecordPtr tmpScan = scanptr;
11787   TcConnectionrecPtr tmpTc = tcConnectptr;
11788 
11789   tcConnectptr.i = restart.p->scanTcrec;
11790   ptrCheckGuard(tcConnectptr, ctcConnectrecFileSize, tcConnectionrec);
11791   restart.p->scanNumber = scanNumber;
11792 
11793   queue.remove(restart);
11794   scans.add(restart);
11795   if(restart.p->scanKeyinfoFlag){
11796     jam();
11797 #if defined VM_TRACE || defined ERROR_INSERT
11798     ScanRecordPtr tmp;
11799     ndbrequire(!c_scanTakeOverHash.find(tmp, * restart.p));
11800 #endif
11801     c_scanTakeOverHash.add(restart);
11802 #ifdef TRACE_SCAN_TAKEOVER
11803     ndbout_c("adding-r (%d %d)", restart.p->scanNumber, restart.p->fragPtrI);
11804 #endif
11805   }
11806 
11807   /**
11808    * This state is a bit weird, but that what set in initScanRec
11809    */
11810   restart.p->scanState = ScanRecord::SCAN_FREE;
11811   if(tcConnectptr.p->transactionState == TcConnectionrec::SCAN_STATE_USED)
11812   {
11813     scanptr = restart;
11814     continueAfterReceivingAllAiLab(signal);
11815   }
11816   else
11817   {
11818     ndbrequire(tcConnectptr.p->transactionState == TcConnectionrec::WAIT_SCAN_AI);
11819   }
11820 
11821   scanptr = tmpScan;
11822   tcConnectptr = tmpTc;
11823 }//Dblqh::finishScanrec()
11824 
11825 /* =========================================================================
11826  * =======                       RELEASE SCAN RECORD                 =======
11827  *
11828  *       RELEASE A SCAN RECORD TO THE FREELIST.
11829  * ========================================================================= */
releaseScanrec(Signal * signal)11830 void Dblqh::releaseScanrec(Signal* signal)
11831 {
11832   scanptr.p->scanState = ScanRecord::SCAN_FREE;
11833   scanptr.p->scanType = ScanRecord::ST_IDLE;
11834   scanptr.p->scanTcWaiting = 0;
11835   cbookedAccOps -= scanptr.p->m_max_batch_size_rows;
11836 }//Dblqh::releaseScanrec()
11837 
11838 /* ------------------------------------------------------------------------
11839  * -------              SEND KEYINFO20 TO API                       -------
11840  *
11841  * ------------------------------------------------------------------------  */
sendKeyinfo20(Signal * signal,ScanRecord * scanP,TcConnectionrec * tcConP)11842 Uint32 Dblqh::sendKeyinfo20(Signal* signal,
11843 			    ScanRecord * scanP,
11844 			    TcConnectionrec * tcConP)
11845 {
11846   ndbrequire(scanP->m_curr_batch_size_rows < MAX_PARALLEL_OP_PER_SCAN);
11847   KeyInfo20 * keyInfo = (KeyInfo20 *)&signal->theData[0];
11848 
11849   /**
11850    * Note that this code requires signal->theData to be big enough for
11851    * a entire key
11852    */
11853   const BlockReference ref = scanP->scanApiBlockref;
11854   const Uint32 scanOp = scanP->m_curr_batch_size_rows;
11855   Uint32 nodeId = refToNode(ref);
11856   const bool connectedToNode = getNodeInfo(nodeId).m_connected;
11857 #ifdef NOT_USED
11858   const Uint32 type = getNodeInfo(nodeId).m_type;
11859   const bool is_api= (type >= NodeInfo::API && type <= NodeInfo::REP);
11860   const bool old_dest= (getNodeInfo(nodeId).m_version < MAKE_VERSION(3,5,0));
11861 #endif
11862   const bool longable = true; // TODO is_api && !old_dest;
11863 
11864   Uint32 * dst = keyInfo->keyData;
11865   dst += nodeId == getOwnNodeId() ? 0 : KeyInfo20::DataLength;
11866 
11867   /**
11868    * This is ugly :-(
11869    *  currently only SUMA receives KEYINFO20 inside kernel..
11870    *  and it's not really interested in the actual keyinfo,
11871    *  only the scanInfo_Node...so send only that and avoid
11872    *  messing with if's below...
11873    */
11874   Uint32 keyLen ;
11875   if (refToMain(ref) == SUMA && nodeId == getOwnNodeId())
11876   {
11877     keyLen = 0;
11878   }
11879   else
11880   {
11881     keyLen = readPrimaryKeys(scanP, tcConP, dst);
11882   }
11883 
11884   Uint32 fragId = tcConP->fragmentid;
11885   keyInfo->clientOpPtr   = scanP->scanApiOpPtr;
11886   keyInfo->keyLen        = keyLen;
11887   keyInfo->scanInfo_Node =
11888     KeyInfo20::setScanInfo(scanOp, scanP->scanNumber) + (fragId << 20);
11889   keyInfo->transId1 = tcConP->transid[0];
11890   keyInfo->transId2 = tcConP->transid[1];
11891 
11892   Uint32 * src = signal->theData+25;
11893   if(connectedToNode)
11894   {
11895     jam();
11896 
11897     if (isNdbMtLqh() && instance() != refToInstance(ref))
11898     {
11899       jam();
11900       nodeId = 0; // prevent execute direct
11901     }
11902     if (nodeId == getOwnNodeId())
11903     {
11904       EXECUTE_DIRECT(refToBlock(ref), GSN_KEYINFO20, signal,
11905                      KeyInfo20::HeaderLength + keyLen);
11906       jamEntry();
11907       return keyLen;
11908     }
11909     else
11910     {
11911       if(keyLen <= KeyInfo20::DataLength || !longable) {
11912 	while(keyLen > KeyInfo20::DataLength){
11913 	  jam();
11914 	  MEMCOPY_NO_WORDS(keyInfo->keyData, src, KeyInfo20::DataLength);
11915 	  sendSignal(ref, GSN_KEYINFO20, signal, 25, JBB);
11916 	  src += KeyInfo20::DataLength;;
11917 	  keyLen -= KeyInfo20::DataLength;
11918 	}
11919 
11920 	MEMCOPY_NO_WORDS(keyInfo->keyData, src, keyLen);
11921 	sendSignal(ref, GSN_KEYINFO20, signal,
11922 		   KeyInfo20::HeaderLength+keyLen, JBB);
11923 	return keyLen;
11924       }
11925 
11926       LinearSectionPtr ptr[3];
11927       ptr[0].p = src;
11928       ptr[0].sz = keyLen;
11929       sendSignal(ref, GSN_KEYINFO20, signal, KeyInfo20::HeaderLength,
11930 		 JBB, ptr, 1);
11931       return keyLen;
11932     }
11933   }
11934 
11935   /**
11936    * If this node does not have a direct connection
11937    * to the receiving node we want to send the signals
11938    * routed via the node that controls this read
11939    */
11940   Uint32 routeBlockref = tcConP->clientBlockref;
11941 
11942   if(keyLen < KeyInfo20::DataLength || !longable){
11943     jam();
11944 
11945     while (keyLen > (KeyInfo20::DataLength - 1)) {
11946       jam();
11947       MEMCOPY_NO_WORDS(keyInfo->keyData, src, KeyInfo20::DataLength - 1);
11948       keyInfo->keyData[KeyInfo20::DataLength-1] = ref;
11949       sendSignal(routeBlockref, GSN_KEYINFO20_R, signal, 25, JBB);
11950       src += KeyInfo20::DataLength - 1;
11951       keyLen -= KeyInfo20::DataLength - 1;
11952     }
11953 
11954     MEMCOPY_NO_WORDS(keyInfo->keyData, src, keyLen);
11955     keyInfo->keyData[keyLen] = ref;
11956     sendSignal(routeBlockref, GSN_KEYINFO20_R, signal,
11957 	       KeyInfo20::HeaderLength+keyLen+1, JBB);
11958     return keyLen;
11959   }
11960 
11961   keyInfo->keyData[0] = ref;
11962   LinearSectionPtr ptr[3];
11963   ptr[0].p = src;
11964   ptr[0].sz = keyLen;
11965   sendSignal(routeBlockref, GSN_KEYINFO20_R, signal,
11966 	     KeyInfo20::HeaderLength+1, JBB, ptr, 1);
11967   return keyLen;
11968 }
11969 
11970 /* ------------------------------------------------------------------------
11971  * -------        SEND SCAN_FRAGCONF TO TC THAT CONTROLS THE SCAN   -------
11972  *
11973  * ------------------------------------------------------------------------ */
sendScanFragConf(Signal * signal,Uint32 scanCompleted)11974 void Dblqh::sendScanFragConf(Signal* signal, Uint32 scanCompleted)
11975 {
11976   Uint32 completed_ops= scanptr.p->m_curr_batch_size_rows;
11977   Uint32 total_len= scanptr.p->m_curr_batch_size_bytes;
11978   scanptr.p->scanTcWaiting = 0;
11979 
11980   if(ERROR_INSERTED(5037)){
11981     CLEAR_ERROR_INSERT_VALUE;
11982     return;
11983   }
11984   ScanFragConf * conf = (ScanFragConf*)&signal->theData[0];
11985 #ifdef NOT_USED
11986   NodeId tc_node_id= refToNode(tcConnectptr.p->clientBlockref);
11987 #endif
11988   Uint32 trans_id1= tcConnectptr.p->transid[0];
11989   Uint32 trans_id2= tcConnectptr.p->transid[1];
11990 
11991   conf->senderData = tcConnectptr.p->clientConnectrec;
11992   conf->completedOps = completed_ops;
11993   conf->fragmentCompleted = scanCompleted;
11994   conf->transId1 = trans_id1;
11995   conf->transId2 = trans_id2;
11996   conf->total_len= total_len;
11997   sendSignal(tcConnectptr.p->clientBlockref, GSN_SCAN_FRAGCONF,
11998              signal, ScanFragConf::SignalLength, JBB);
11999 
12000   if(!scanptr.p->scanLockHold)
12001   {
12002     jam();
12003     scanptr.p->m_curr_batch_size_rows = 0;
12004     scanptr.p->m_curr_batch_size_bytes= 0;
12005   }
12006 }//Dblqh::sendScanFragConf()
12007 
12008 /* ######################################################################### */
12009 /* #######                NODE RECOVERY MODULE                       ####### */
12010 /*                                                                           */
12011 /* ######################################################################### */
12012 /*---------------------------------------------------------------------------*/
12013 /*                                                                           */
12014 /*   THIS MODULE IS USED WHEN A NODE HAS FAILED. IT PERFORMS A COPY OF A     */
12015 /*   FRAGMENT TO A NEW REPLICA OF THE FRAGMENT. IT DOES ALSO SHUT DOWN ALL   */
12016 /*   CONNECTIONS TO THE FAILED NODE.                                         */
12017 /*---------------------------------------------------------------------------*/
12018 Uint32
calculateHash(Uint32 tableId,const Uint32 * src)12019 Dblqh::calculateHash(Uint32 tableId, const Uint32* src)
12020 {
12021   jam();
12022   Uint64 Tmp[(MAX_KEY_SIZE_IN_WORDS*MAX_XFRM_MULTIPLY) >> 1];
12023   Uint32 keyPartLen[MAX_ATTRIBUTES_IN_INDEX];
12024   Uint32 keyLen = xfrm_key(tableId, src, (Uint32*)Tmp, sizeof(Tmp) >> 2,
12025 			   keyPartLen);
12026   ndbrequire(keyLen);
12027 
12028   return md5_hash(Tmp, keyLen);
12029 }//Dblqh::calculateHash()
12030 
12031 /**
12032  * PREPARE COPY FRAG REQ
12033  */
12034 void
execPREPARE_COPY_FRAG_REQ(Signal * signal)12035 Dblqh::execPREPARE_COPY_FRAG_REQ(Signal* signal)
12036 {
12037   jamEntry();
12038   PrepareCopyFragReq req = *(PrepareCopyFragReq*)signal->getDataPtr();
12039 
12040   CRASH_INSERTION(5045);
12041 
12042   tabptr.i = req.tableId;
12043   ptrCheckGuard(tabptr, ctabrecFileSize, tablerec);
12044 
12045   Uint32 max_page = RNIL;
12046 
12047   if (getOwnNodeId() != req.startingNodeId)
12048   {
12049     jam();
12050     /**
12051      * This is currently dead code...
12052      *   but is provided so we can impl. a better scan+delete on
12053      *   starting node wo/ having to change running node
12054      */
12055     ndbrequire(getOwnNodeId() == req.copyNodeId);
12056     c_tup->get_frag_info(req.tableId, req.fragId, &max_page);
12057 
12058     PrepareCopyFragConf* conf = (PrepareCopyFragConf*)signal->getDataPtrSend();
12059     conf->senderData = req.senderData;
12060     conf->senderRef = reference();
12061     conf->tableId = req.tableId;
12062     conf->fragId = req.fragId;
12063     conf->copyNodeId = req.copyNodeId;
12064     conf->startingNodeId = req.startingNodeId;
12065     conf->maxPageNo = max_page;
12066     sendSignal(req.senderRef, GSN_PREPARE_COPY_FRAG_CONF,
12067                signal, PrepareCopyFragConf::SignalLength, JBB);
12068 
12069     return;
12070   }
12071 
12072   if (! DictTabInfo::isOrderedIndex(tabptr.p->tableType))
12073   {
12074     jam();
12075     ndbrequire(getFragmentrec(signal, req.fragId));
12076 
12077     /**
12078      *
12079      */
12080     if (cstartType == NodeState::ST_SYSTEM_RESTART)
12081     {
12082       jam();
12083       signal->theData[0] = fragptr.p->tabRef;
12084       signal->theData[1] = fragptr.p->fragId;
12085       BlockReference accRef = calcInstanceBlockRef(DBACC);
12086       sendSignal(accRef, GSN_EXPANDCHECK2, signal, 2, JBB);
12087     }
12088 
12089 
12090     /**
12091      *
12092      */
12093     fragptr.p->m_copy_started_state = Fragrecord::AC_IGNORED;
12094     fragptr.p->fragStatus = Fragrecord::ACTIVE_CREATION;
12095     fragptr.p->logFlag = Fragrecord::STATE_FALSE;
12096 
12097     c_tup->get_frag_info(req.tableId, req.fragId, &max_page);
12098   }
12099 
12100   PrepareCopyFragConf* conf = (PrepareCopyFragConf*)signal->getDataPtrSend();
12101   conf->senderData = req.senderData;
12102   conf->senderRef = reference();
12103   conf->tableId = req.tableId;
12104   conf->fragId = req.fragId;
12105   conf->copyNodeId = req.copyNodeId;
12106   conf->startingNodeId = req.startingNodeId;
12107   conf->maxPageNo = max_page;
12108   sendSignal(req.senderRef, GSN_PREPARE_COPY_FRAG_CONF,
12109              signal, PrepareCopyFragConf::SignalLength, JBB);
12110 }
12111 
12112 /* *************************************** */
12113 /*  COPY_FRAGREQ: Start copying a fragment */
12114 /* *************************************** */
execCOPY_FRAGREQ(Signal * signal)12115 void Dblqh::execCOPY_FRAGREQ(Signal* signal)
12116 {
12117   jamEntry();
12118   const CopyFragReq * const copyFragReq = (CopyFragReq *)&signal->theData[0];
12119   tabptr.i = copyFragReq->tableId;
12120   ptrCheckGuard(tabptr, ctabrecFileSize, tablerec);
12121   Uint32 i;
12122   const Uint32 fragId = copyFragReq->fragId;
12123   const Uint32 copyPtr = copyFragReq->userPtr;
12124   const Uint32 userRef = copyFragReq->userRef;
12125   const Uint32 nodeId = copyFragReq->nodeId;
12126   const Uint32 gci = copyFragReq->gci;
12127 
12128   ndbrequire(cnoActiveCopy < 3);
12129   ndbrequire(getFragmentrec(signal, fragId));
12130   ndbrequire(fragptr.p->copyFragState == ZIDLE);
12131   ndbrequire(cfirstfreeTcConrec != RNIL);
12132   ndbrequire(fragptr.p->m_scanNumberMask.get(NR_ScanNo));
12133 
12134   Uint32 checkversion = NDB_VERSION >= MAKE_VERSION(5,1,0) ?
12135     NDBD_UPDATE_FRAG_DIST_KEY_51 :  NDBD_UPDATE_FRAG_DIST_KEY_50;
12136 
12137   Uint32 nodeCount = copyFragReq->nodeCount;
12138   NdbNodeBitmask nodemask;
12139   if (getNodeInfo(refToNode(userRef)).m_version >= checkversion)
12140   {
12141     ndbrequire(nodeCount <= MAX_REPLICAS);
12142     for (i = 0; i<nodeCount; i++)
12143       nodemask.set(copyFragReq->nodeList[i]);
12144   }
12145   Uint32 maxPage = copyFragReq->nodeList[nodeCount];
12146   Uint32 version = getNodeInfo(refToNode(userRef)).m_version;
12147   Uint32 requestInfo = copyFragReq->nodeList[nodeCount + 1];
12148   if (ndb_check_prep_copy_frag_version(version) < 2)
12149   {
12150     jam();
12151     maxPage = RNIL;
12152   }
12153 
12154   if (signal->getLength() < CopyFragReq::SignalLength + nodeCount)
12155   {
12156     jam();
12157     requestInfo = CopyFragReq::CFR_TRANSACTIONAL;
12158   }
12159 
12160   if (requestInfo == CopyFragReq::CFR_NON_TRANSACTIONAL)
12161   {
12162     jam();
12163   }
12164   else
12165   {
12166     fragptr.p->fragDistributionKey = copyFragReq->distributionKey;
12167   }
12168   Uint32 key = fragptr.p->fragDistributionKey;
12169 
12170   if (DictTabInfo::isOrderedIndex(tabptr.p->tableType)) {
12171     jam();
12172     /**
12173      * Ordered index doesn't need to be copied
12174      */
12175     CopyFragConf * const conf = (CopyFragConf *)&signal->theData[0];
12176     conf->userPtr = copyPtr;
12177     conf->sendingNodeId = cownNodeid;
12178     conf->startingNodeId = nodeId;
12179     conf->tableId = tabptr.i;
12180     conf->fragId = fragId;
12181     sendSignal(userRef, GSN_COPY_FRAGCONF, signal,
12182 	       CopyFragConf::SignalLength, JBB);
12183     return;
12184   }//if
12185 
12186   LocalDLList<ScanRecord> scans(c_scanRecordPool, fragptr.p->m_activeScans);
12187   ndbrequire(m_reserved_scans.first(scanptr));
12188   m_reserved_scans.remove(scanptr);
12189   scans.add(scanptr);
12190 
12191 /* ------------------------------------------------------------------------- */
12192 // We keep track of how many operation records in ACC that has been booked.
12193 // Copy fragment has records always booked and thus need not book any. The
12194 // most operations in parallel use is the m_max_batch_size_rows.
12195 // This variable has to be set-up here since it is used by releaseScanrec
12196 // to unbook operation records in ACC.
12197 /* ------------------------------------------------------------------------- */
12198   scanptr.p->m_max_batch_size_rows = 0;
12199   scanptr.p->rangeScan = 0;
12200   scanptr.p->tupScan = 0;
12201   seizeTcrec();
12202   tcConnectptr.p->clientBlockref = userRef;
12203 
12204   /**
12205    * Remove implicit cast/usage of CopyFragReq
12206    */
12207   //initCopyrec(signal);
12208   scanptr.p->copyPtr = copyPtr;
12209   scanptr.p->scanType = ScanRecord::COPY;
12210   scanptr.p->scanNodeId = nodeId;
12211   scanptr.p->scanTcrec = tcConnectptr.i;
12212   scanptr.p->scanSchemaVersion = copyFragReq->schemaVersion;
12213   scanptr.p->scanCompletedStatus = ZFALSE;
12214   scanptr.p->scanErrorCounter = 0;
12215   scanptr.p->scanNumber = NR_ScanNo;
12216   scanptr.p->scanKeyinfoFlag = 0; // Don't put into hash
12217   scanptr.p->fragPtrI = fragptr.i;
12218   scanptr.p->scanApiOpPtr = tcConnectptr.i;
12219   scanptr.p->scanApiBlockref = reference();
12220   fragptr.p->m_scanNumberMask.clear(NR_ScanNo);
12221   scanptr.p->scanBlockref = ctupBlockref;
12222   scanptr.p->scanLockHold = ZFALSE;
12223   scanptr.p->m_curr_batch_size_rows = 0;
12224   scanptr.p->m_curr_batch_size_bytes= 0;
12225   scanptr.p->readCommitted = 0;
12226 
12227   initScanTc(0,
12228              0,
12229              (DBLQH << 20) + (cownNodeid << 8),
12230              fragId,
12231              copyFragReq->nodeId,
12232              0);
12233   cactiveCopy[cnoActiveCopy] = fragptr.i;
12234   cnoActiveCopy++;
12235 
12236   tcConnectptr.p->copyCountWords = 0;
12237   tcConnectptr.p->tcOprec = tcConnectptr.i;
12238   tcConnectptr.p->tcHashKeyHi = 0;
12239   tcConnectptr.p->schemaVersion = scanptr.p->scanSchemaVersion;
12240   tcConnectptr.p->savePointId = gci;
12241   tcConnectptr.p->applRef = 0;
12242   tcConnectptr.p->transactionState = TcConnectionrec::SCAN_STATE_USED;
12243 
12244   scanptr.p->scanState = ScanRecord::WAIT_ACC_COPY;
12245   AccScanReq * req = (AccScanReq*)&signal->theData[0];
12246   req->senderData = scanptr.i;
12247   req->senderRef = cownref;
12248   req->tableId = tabptr.i;
12249   req->fragmentNo = fragId;
12250   req->requestInfo = 0;
12251 
12252   if (requestInfo == CopyFragReq::CFR_TRANSACTIONAL)
12253   {
12254     jam();
12255     /**
12256      * An node-recovery scan, is shared lock
12257      *   and may not perform disk-scan (as it then can miss uncomitted inserts)
12258      */
12259     AccScanReq::setLockMode(req->requestInfo, 0);
12260     AccScanReq::setReadCommittedFlag(req->requestInfo, 0);
12261     AccScanReq::setNRScanFlag(req->requestInfo, 1);
12262     AccScanReq::setNoDiskScanFlag(req->requestInfo, 1);
12263   }
12264   else
12265   {
12266     jam();
12267     /**
12268      * The non-transaction scan is really only a "normal" tup scan
12269      *   committed read, and don't disable disk-scan
12270      */
12271     AccScanReq::setLockMode(req->requestInfo, 0);
12272     AccScanReq::setReadCommittedFlag(req->requestInfo, 1);
12273     scanptr.p->readCommitted = 1;
12274   }
12275 
12276   req->transId1 = tcConnectptr.p->transid[0];
12277   req->transId2 = tcConnectptr.p->transid[1];
12278   req->savePointId = tcConnectptr.p->savePointId;
12279   req->maxPage = maxPage;
12280   sendSignal(scanptr.p->scanBlockref, GSN_ACC_SCANREQ, signal,
12281 	     AccScanReq::SignalLength + 1, JBB);
12282 
12283   if (! nodemask.isclear())
12284   {
12285     ndbrequire(nodemask.get(getOwnNodeId()));
12286     ndbrequire(nodemask.get(nodeId)); // cpy dest
12287     nodemask.clear(getOwnNodeId());
12288     nodemask.clear(nodeId);
12289 
12290     UpdateFragDistKeyOrd*
12291       ord = (UpdateFragDistKeyOrd*)signal->getDataPtrSend();
12292     ord->tableId = tabptr.i;
12293     ord->fragId = fragId;
12294     ord->fragDistributionKey = key;
12295     i = 0;
12296     while ((i = nodemask.find(i+1)) != NdbNodeBitmask::NotFound)
12297     {
12298       if (getNodeInfo(i).m_version >=  checkversion)
12299 	sendSignal(calcInstanceBlockRef(number(), i),
12300                    GSN_UPDATE_FRAG_DIST_KEY_ORD,
12301 		   signal, UpdateFragDistKeyOrd::SignalLength, JBB);
12302     }
12303   }
12304   return;
12305 }//Dblqh::execCOPY_FRAGREQ()
12306 
12307 void
execUPDATE_FRAG_DIST_KEY_ORD(Signal * signal)12308 Dblqh::execUPDATE_FRAG_DIST_KEY_ORD(Signal * signal)
12309 {
12310   jamEntry();
12311   UpdateFragDistKeyOrd* ord =(UpdateFragDistKeyOrd*)signal->getDataPtr();
12312 
12313   tabptr.i = ord->tableId;
12314   ptrCheckGuard(tabptr, ctabrecFileSize, tablerec);
12315   ndbrequire(getFragmentrec(signal, ord->fragId));
12316   fragptr.p->fragDistributionKey = ord->fragDistributionKey;
12317 }
12318 
accScanConfCopyLab(Signal * signal)12319 void Dblqh::accScanConfCopyLab(Signal* signal)
12320 {
12321   AccScanConf * const accScanConf = (AccScanConf *)&signal->theData[0];
12322   tcConnectptr.i = scanptr.p->scanTcrec;
12323   ptrCheckGuard(tcConnectptr, ctcConnectrecFileSize, tcConnectionrec);
12324 /*--------------------------------------------------------------------------*/
12325 /*  PRECONDITION: SCAN_STATE = WAIT_ACC_COPY                                */
12326 /*--------------------------------------------------------------------------*/
12327   if (accScanConf->flag == AccScanConf::ZEMPTY_FRAGMENT) {
12328     jam();
12329 /*---------------------------------------------------------------------------*/
12330 /*   THE FRAGMENT WAS EMPTY.                                                 */
12331 /*   REPORT SUCCESSFUL COPYING.                                              */
12332 /*---------------------------------------------------------------------------*/
12333     tupCopyCloseConfLab(signal);
12334     return;
12335   }//if
12336   scanptr.p->scanAccPtr = accScanConf->accPtr;
12337   scanptr.p->scanState = ScanRecord::WAIT_STORED_PROC_COPY;
12338   signal->theData[0] = tcConnectptr.p->tupConnectrec;
12339   signal->theData[1] = tcConnectptr.p->tableref;
12340   signal->theData[2] = scanptr.p->scanSchemaVersion;
12341   signal->theData[3] = ZSTORED_PROC_COPY;
12342 // theData[4] is not used in TUP with ZSTORED_PROC_COPY
12343   signal->theData[5] = scanptr.p->scanApiBlockref;
12344   sendSignal(scanptr.p->scanBlockref, GSN_STORED_PROCREQ, signal, 6, JBB);
12345   return;
12346 }//Dblqh::accScanConfCopyLab()
12347 
12348 /*---------------------------------------------------------------------------*/
12349 /*   ENTER STORED_PROCCONF WITH                                              */
12350 /*     TC_CONNECTPTR,                                                        */
12351 /*     TSTORED_PROC_ID                                                       */
12352 /*---------------------------------------------------------------------------*/
storedProcConfCopyLab(Signal * signal)12353 void Dblqh::storedProcConfCopyLab(Signal* signal)
12354 {
12355 /*---------------------------------------------------------------------------*/
12356 /*   PRECONDITION: SCAN_STATE = WAIT_STORED_PROC_COPY                        */
12357 /*---------------------------------------------------------------------------*/
12358   fragptr.i = tcConnectptr.p->fragmentptr;
12359   c_fragment_pool.getPtr(fragptr);
12360   if (scanptr.p->scanCompletedStatus == ZTRUE) {
12361     jam();
12362 /*---------------------------------------------------------------------------*/
12363 /*   THE COPY PROCESS HAVE BEEN COMPLETED, MOST LIKELY DUE TO A NODE FAILURE.*/
12364 /*---------------------------------------------------------------------------*/
12365     closeCopyLab(signal);
12366     return;
12367   }//if
12368   scanptr.i = tcConnectptr.p->tcScanRec;
12369   c_scanRecordPool.getPtr(scanptr);
12370   scanptr.p->scanState = ScanRecord::WAIT_NEXT_SCAN_COPY;
12371   switch (fragptr.p->fragStatus) {
12372   case Fragrecord::FSACTIVE:
12373     jam();
12374     break;
12375   case Fragrecord::BLOCKED:
12376     jam();
12377     linkFragQueue(signal);
12378     tcConnectptr.p->transactionState = TcConnectionrec::COPY_FIRST_STOPPED;
12379     return;
12380     break;
12381   case Fragrecord::FREE:
12382     jam();
12383   case Fragrecord::ACTIVE_CREATION:
12384     jam();
12385   case Fragrecord::CRASH_RECOVERING:
12386     jam();
12387   case Fragrecord::DEFINED:
12388     jam();
12389   case Fragrecord::REMOVING:
12390     jam();
12391   default:
12392     jam();
12393     systemErrorLab(signal, __LINE__);
12394     return;
12395     break;
12396   }//switch
12397   continueFirstCopyAfterBlockedLab(signal);
12398   return;
12399 }//Dblqh::storedProcConfCopyLab()
12400 
continueFirstCopyAfterBlockedLab(Signal * signal)12401 void Dblqh::continueFirstCopyAfterBlockedLab(Signal* signal)
12402 {
12403   /**
12404    * Start sending ROWID for all operations from now on
12405    */
12406   fragptr.p->m_copy_started_state = Fragrecord::AC_NR_COPY;
12407   if (ERROR_INSERTED(5714))
12408   {
12409     ndbout_c("Starting copy of tab: %u frag: %u",
12410              fragptr.p->tabRef, fragptr.p->fragId);
12411   }
12412 
12413   scanptr.i = tcConnectptr.p->tcScanRec;
12414   c_scanRecordPool.getPtr(scanptr);
12415 
12416   if (false && fragptr.p->tabRef > 4)
12417   {
12418     ndbout_c("STOPPING COPY X = [ %d %d %d %d ]",
12419 	     refToBlock(scanptr.p->scanBlockref),
12420 	     scanptr.p->scanAccPtr, RNIL, NextScanReq::ZSCAN_NEXT);
12421 
12422     /**
12423      * RESTART: > DUMP 7020 332 X
12424      */
12425     return;
12426   }
12427 
12428   signal->theData[0] = scanptr.p->scanAccPtr;
12429   signal->theData[1] = RNIL;
12430   signal->theData[2] = NextScanReq::ZSCAN_NEXT;
12431   sendSignal(scanptr.p->scanBlockref, GSN_NEXT_SCANREQ, signal, 3, JBB);
12432   return;
12433 }//Dblqh::continueFirstCopyAfterBlockedLab()
12434 
12435 /*---------------------------------------------------------------------------*/
12436 /*       ENTER NEXT_SCANCONF WITH                                            */
12437 /*         SCANPTR,                                                          */
12438 /*         TFRAGID,                                                          */
12439 /*         TACC_OPPTR,                                                       */
12440 /*         TLOCAL_KEY1,                                                      */
12441 /*         TLOCAL_KEY2,                                                      */
12442 /*         TKEY_LENGTH,                                                      */
12443 /*         TKEY1,                                                            */
12444 /*         TKEY2,                                                            */
12445 /*         TKEY3,                                                            */
12446 /*         TKEY4                                                             */
12447 /*---------------------------------------------------------------------------*/
12448 /*       PRECONDITION: SCAN_STATE = WAIT_NEXT_SCAN_COPY                      */
12449 /*---------------------------------------------------------------------------*/
nextScanConfCopyLab(Signal * signal)12450 void Dblqh::nextScanConfCopyLab(Signal* signal)
12451 {
12452   NextScanConf * const nextScanConf = (NextScanConf *)&signal->theData[0];
12453   tcConnectptr.i = scanptr.p->scanTcrec;
12454   ptrCheckGuard(tcConnectptr, ctcConnectrecFileSize, tcConnectionrec);
12455   if (nextScanConf->fragId == RNIL) {
12456     jam();
12457 /*---------------------------------------------------------------------------*/
12458 /*   THERE ARE NO MORE TUPLES TO FETCH. WE NEED TO CLOSE                     */
12459 /*   THE COPY IN ACC AND DELETE THE STORED PROCEDURE IN TUP                  */
12460 /*---------------------------------------------------------------------------*/
12461     if (tcConnectptr.p->copyCountWords == 0) {
12462       closeCopyLab(signal);
12463       return;
12464     }//if
12465 /*---------------------------------------------------------------------------*/
12466 // Wait until copying is completed also at the starting node before reporting
12467 // completion. Signal completion through scanCompletedStatus-flag.
12468 /*---------------------------------------------------------------------------*/
12469     scanptr.p->scanCompletedStatus = ZTRUE;
12470     scanptr.p->scanState = ScanRecord::WAIT_LQHKEY_COPY;
12471     if (ERROR_INSERTED(5043))
12472     {
12473       CLEAR_ERROR_INSERT_VALUE;
12474       tcConnectptr.p->copyCountWords = ~0;
12475       signal->theData[0] = 9999;
12476       sendSignal(numberToRef(CMVMI, scanptr.p->scanNodeId),
12477 		 GSN_NDB_TAMPER, signal, 1, JBA);
12478     }
12479     return;
12480   }//if
12481 
12482   TcConnectionrec * tcConP = tcConnectptr.p;
12483 
12484   tcConP->m_use_rowid = true;
12485   tcConP->m_row_id = scanptr.p->m_row_id;
12486 
12487   scanptr.p->m_curr_batch_size_rows++;
12488 
12489   if (signal->getLength() == NextScanConf::SignalLengthNoKeyInfo)
12490   {
12491     jam();
12492     ndbrequire(nextScanConf->accOperationPtr == RNIL);
12493     initCopyTc(signal, ZDELETE);
12494     set_acc_ptr_in_scan_record(scanptr.p, 0, RNIL);
12495     tcConP->gci_hi = nextScanConf->gci;
12496     tcConP->gci_lo = 0;
12497 
12498     tcConP->primKeyLen = 0;
12499     tcConP->totSendlenAi = 0;
12500     tcConP->connectState = TcConnectionrec::COPY_CONNECTED;
12501 
12502 /*---------------------------------------------------------------------------*/
12503 // To avoid using up to many operation records in ACC we will increase the
12504 // constant to ensure that we never send more than 40 records at a time.
12505 // This is where the constant 56 comes from. For long records this constant
12506 // will not matter that much. The current maximum is 6000 words outstanding
12507 // (including a number of those 56 words not really sent). We also have to
12508 // ensure that there are never more simultaneous usage of these operation
12509 // records to ensure that node recovery does not fail because of simultaneous
12510 // scanning.
12511 /*---------------------------------------------------------------------------*/
12512     UintR TnoOfWords = 8;
12513     TnoOfWords = TnoOfWords + MAGIC_CONSTANT;
12514     TnoOfWords = TnoOfWords + (TnoOfWords >> 2);
12515 
12516     /*-----------------------------------------------------------------
12517      * NOTE for transid1!
12518      * Transid1 in the tcConnection record is used load regulate the
12519      * copy(node recovery) process.
12520      * The number of outstanding words are written in the transid1
12521      * variable. This will be sent to the starting node in the
12522      * LQHKEYREQ signal and when the answer is returned in the LQHKEYCONF
12523      * we can reduce the number of outstanding words and check to see
12524      * if more LQHKEYREQ signals should be sent.
12525      *
12526      * However efficient this method is rather unsafe in such way that
12527      * it overwrites the transid1 original data.
12528      *
12529      * Also see TR 587.
12530      *----------------------------------------------------------------*/
12531     tcConP->transid[0] = TnoOfWords; // Data overload, see note!
12532     packLqhkeyreqLab(signal);
12533     tcConP->copyCountWords += TnoOfWords;
12534     scanptr.p->scanState = ScanRecord::WAIT_LQHKEY_COPY;
12535     if (tcConP->copyCountWords < cmaxWordsAtNodeRec) {
12536       nextRecordCopy(signal);
12537     }
12538     return;
12539   }
12540   else
12541   {
12542     // If accOperationPtr == RNIL no record was returned by ACC
12543     if (nextScanConf->accOperationPtr == RNIL) {
12544       jam();
12545       signal->theData[0] = scanptr.p->scanAccPtr;
12546       signal->theData[1] = AccCheckScan::ZCHECK_LCP_STOP;
12547       sendSignal(scanptr.p->scanBlockref, GSN_ACC_CHECK_SCAN, signal, 2, JBB);
12548       return;
12549     }
12550 
12551     initCopyTc(signal, ZINSERT);
12552     set_acc_ptr_in_scan_record(scanptr.p, 0, nextScanConf->accOperationPtr);
12553 
12554     Fragrecord* fragPtrP= fragptr.p;
12555     scanptr.p->scanState = ScanRecord::WAIT_TUPKEY_COPY;
12556     tcConP->transactionState = TcConnectionrec::COPY_TUPKEY;
12557     if(tcConP->m_disk_table)
12558     {
12559       next_scanconf_load_diskpage(signal, scanptr, tcConnectptr,fragPtrP);
12560     }
12561     else
12562     {
12563       next_scanconf_tupkeyreq(signal, scanptr, tcConP, fragPtrP, RNIL);
12564     }
12565   }
12566 }//Dblqh::nextScanConfCopyLab()
12567 
12568 
12569 /*---------------------------------------------------------------------------*/
12570 /*   USED IN COPYING OPERATION TO RECEIVE ATTRINFO FROM TUP.                 */
12571 /*---------------------------------------------------------------------------*/
12572 /* ************>> */
12573 /*  TRANSID_AI  > */
12574 /* ************>> */
execTRANSID_AI(Signal * signal)12575 void Dblqh::execTRANSID_AI(Signal* signal)
12576 {
12577   jamEntry();
12578   /* TransID_AI received from local TUP, data is linear inline in
12579    * signal buff
12580    */
12581   tcConnectptr.i = signal->theData[0];
12582   ptrCheckGuard(tcConnectptr, ctcConnectrecFileSize, tcConnectionrec);
12583   Uint32 length = signal->length() - TransIdAI::HeaderLength;
12584   ndbrequire(tcConnectptr.p->transactionState == TcConnectionrec::COPY_TUPKEY);
12585   Uint32 * src = &signal->theData[ TransIdAI::HeaderLength ];
12586   bool ok= appendToSection(tcConnectptr.p->attrInfoIVal,
12587                            src,
12588                            length);
12589   if (unlikely(! ok))
12590   {
12591     jam();
12592     tcConnectptr.p->errorCode = ZGET_ATTRINBUF_ERROR;
12593   }
12594 }//Dblqh::execTRANSID_AI()
12595 
12596 /*--------------------------------------------------------------------------*/
12597 /*     ENTER TUPKEYCONF WITH                                                */
12598 /*          TC_CONNECTPTR,                                                  */
12599 /*          TDATA2,                                                         */
12600 /*          TDATA3,                                                         */
12601 /*          TDATA4,                                                         */
12602 /*          TDATA5                                                          */
12603 /*--------------------------------------------------------------------------*/
12604 /*  PRECONDITION:   TRANSACTION_STATE = COPY_TUPKEY                         */
12605 /*--------------------------------------------------------------------------*/
copyTupkeyRefLab(Signal * signal)12606 void Dblqh::copyTupkeyRefLab(Signal* signal)
12607 {
12608   //const TupKeyRef * tupKeyRef = (TupKeyRef *)signal->getDataPtr();
12609 
12610   scanptr.i = tcConnectptr.p->tcScanRec;
12611   c_scanRecordPool.getPtr(scanptr);
12612   ScanRecord* scanP = scanptr.p;
12613 
12614   if (scanP->readCommitted == 0)
12615   {
12616     jam();
12617     ndbrequire(false); // Should not be possibe...we read with lock
12618   }
12619   else
12620   {
12621     jam();
12622     /**
12623      * Any readCommitted scan, can get 626 if it finds a candidate record
12624      *   that is not visible to the scan (i.e uncommitted inserts)
12625      *   if scanning with locks (shared/exclusive) this is not visible
12626      *   to LQH as lock is taken earlier
12627      */
12628     ndbrequire(terrorCode == 626);
12629   }
12630 
12631   ndbrequire(scanptr.p->scanState == ScanRecord::WAIT_TUPKEY_COPY);
12632   if (tcConnectptr.p->errorCode != 0)
12633   {
12634     jam();
12635     closeCopyLab(signal);
12636     return;
12637   }
12638 
12639   if (scanptr.p->scanCompletedStatus == ZTRUE)
12640   {
12641     jam();
12642     closeCopyLab(signal);
12643     return;
12644   }
12645 
12646   ndbrequire(tcConnectptr.p->copyCountWords < cmaxWordsAtNodeRec);
12647   scanptr.p->scanState = ScanRecord::WAIT_LQHKEY_COPY;
12648   nextRecordCopy(signal);
12649 }
12650 
copyTupkeyConfLab(Signal * signal)12651 void Dblqh::copyTupkeyConfLab(Signal* signal)
12652 {
12653   const TupKeyConf * const tupKeyConf = (TupKeyConf *)signal->getDataPtr();
12654 
12655   UintR readLength = tupKeyConf->readLength;
12656   Uint32 tableId = tcConnectptr.p->tableref;
12657   scanptr.i = tcConnectptr.p->tcScanRec;
12658   c_scanRecordPool.getPtr(scanptr);
12659   ScanRecord* scanP = scanptr.p;
12660 
12661   if (scanP->readCommitted == 0)
12662   {
12663     jam();
12664     Uint32 accOpPtr= get_acc_ptr_from_scan_record(scanP, 0, false);
12665     ndbassert(accOpPtr != (Uint32)-1);
12666     c_acc->execACCKEY_ORD(signal, accOpPtr);
12667   }
12668 
12669   if (tcConnectptr.p->errorCode != 0) {
12670     jam();
12671     closeCopyLab(signal);
12672     return;
12673   }//if
12674   if (scanptr.p->scanCompletedStatus == ZTRUE) {
12675     jam();
12676 /*---------------------------------------------------------------------------*/
12677 /*   THE COPY PROCESS HAVE BEEN CLOSED. MOST LIKELY A NODE FAILURE.          */
12678 /*---------------------------------------------------------------------------*/
12679     closeCopyLab(signal);
12680     return;
12681   }//if
12682   TcConnectionrec * tcConP = tcConnectptr.p;
12683   tcConnectptr.p->totSendlenAi = readLength;
12684   tcConnectptr.p->connectState = TcConnectionrec::COPY_CONNECTED;
12685 
12686   /* Read primary keys from TUP into signal buffer space
12687    * (used to get here via scan keyinfo)
12688    */
12689   Uint32* tmp = signal->getDataPtrSend()+24;
12690   Uint32 len= tcConnectptr.p->primKeyLen = readPrimaryKeys(scanP, tcConP, tmp);
12691 
12692   tcConP->gci_hi = tmp[len];
12693   tcConP->gci_lo = 0;
12694   // Calculate hash (no need to linearise key)
12695   if (g_key_descriptor_pool.getPtr(tableId)->hasCharAttr)
12696   {
12697     tcConnectptr.p->hashValue = calculateHash(tableId, tmp);
12698   }
12699   else
12700   {
12701     tcConnectptr.p->hashValue = md5_hash((Uint64*)tmp, len);
12702   }
12703 
12704   // Copy keyinfo into long section for LQHKEYREQ below
12705   if (unlikely(!keyinfoLab(tmp, len)))
12706   {
12707     /* Failed to store keyInfo, fail copy
12708      * This will result in a COPY_FRAGREF being sent to
12709      * the starting node, which will cause it to fail
12710      */
12711     scanptr.p->scanErrorCounter++;
12712     tcConP->errorCode= ZGET_DATAREC_ERROR;
12713     scanptr.p->scanCompletedStatus= ZTRUE;
12714 
12715     closeCopyLab(signal);
12716     return;
12717   }
12718 
12719   LqhKeyReq::setKeyLen(tcConP->reqinfo, len);
12720 
12721 /*---------------------------------------------------------------------------*/
12722 // To avoid using up to many operation records in ACC we will increase the
12723 // constant to ensure that we never send more than 40 records at a time.
12724 // This is where the constant 56 comes from. For long records this constant
12725 // will not matter that much. The current maximum is 6000 words outstanding
12726 // (including a number of those 56 words not really sent). We also have to
12727 // ensure that there are never more simultaneous usage of these operation
12728 // records to ensure that node recovery does not fail because of simultaneous
12729 // scanning.
12730 /*---------------------------------------------------------------------------*/
12731   UintR TnoOfWords = readLength + len;
12732   scanP->m_curr_batch_size_bytes += 4 * TnoOfWords;
12733   TnoOfWords = TnoOfWords + MAGIC_CONSTANT;
12734   TnoOfWords = TnoOfWords + (TnoOfWords >> 2);
12735 
12736   /*-----------------------------------------------------------------
12737    * NOTE for transid1!
12738    * Transid1 in the tcConnection record is used load regulate the
12739    * copy(node recovery) process.
12740    * The number of outstanding words are written in the transid1
12741    * variable. This will be sent to the starting node in the
12742    * LQHKEYREQ signal and when the answer is returned in the LQHKEYCONF
12743    * we can reduce the number of outstanding words and check to see
12744    * if more LQHKEYREQ signals should be sent.
12745    *
12746    * However efficient this method is rather unsafe in such way that
12747    * it overwrites the transid1 original data.
12748    *
12749    * Also see TR 587.
12750    *----------------------------------------------------------------*/
12751   tcConnectptr.p->transid[0] = TnoOfWords; // Data overload, see note!
12752   packLqhkeyreqLab(signal);
12753   tcConnectptr.p->copyCountWords += TnoOfWords;
12754   scanptr.p->scanState = ScanRecord::WAIT_LQHKEY_COPY;
12755   if (tcConnectptr.p->copyCountWords < cmaxWordsAtNodeRec) {
12756     nextRecordCopy(signal);
12757     return;
12758   }//if
12759   return;
12760 }//Dblqh::copyTupkeyConfLab()
12761 
12762 /*---------------------------------------------------------------------------*/
12763 /*     ENTER LQHKEYCONF                                                      */
12764 /*---------------------------------------------------------------------------*/
12765 /*   PRECONDITION: CONNECT_STATE = COPY_CONNECTED                            */
12766 /*---------------------------------------------------------------------------*/
copyCompletedLab(Signal * signal)12767 void Dblqh::copyCompletedLab(Signal* signal)
12768 {
12769   const LqhKeyConf * const lqhKeyConf = (LqhKeyConf *)signal->getDataPtr();
12770 
12771   ndbrequire(tcConnectptr.p->transid[1] == lqhKeyConf->transId2);
12772   scanptr.i = tcConnectptr.p->tcScanRec;
12773   c_scanRecordPool.getPtr(scanptr);
12774   if (tcConnectptr.p->copyCountWords >= cmaxWordsAtNodeRec) {
12775     tcConnectptr.p->copyCountWords -= lqhKeyConf->transId1; // Data overload, see note!
12776     if (scanptr.p->scanCompletedStatus == ZTRUE) {
12777       jam();
12778 /*---------------------------------------------------------------------------*/
12779 // Copy to complete, we will not start any new copying.
12780 /*---------------------------------------------------------------------------*/
12781       closeCopyLab(signal);
12782       return;
12783     }//if
12784     if (tcConnectptr.p->copyCountWords < cmaxWordsAtNodeRec) {
12785       jam();
12786       nextRecordCopy(signal);
12787     }//if
12788     return;
12789   }//if
12790   tcConnectptr.p->copyCountWords -= lqhKeyConf->transId1; // Data overload, see note!
12791   ndbrequire(tcConnectptr.p->copyCountWords <= cmaxWordsAtNodeRec);
12792   if (tcConnectptr.p->copyCountWords > 0) {
12793     jam();
12794     return;
12795   }//if
12796 /*---------------------------------------------------------------------------*/
12797 // No more outstanding copies. We will only start new ones from here if it was
12798 // stopped before and this only happens when copyCountWords is bigger than the
12799 // threshold value. Since this did not occur we must be waiting for completion.
12800 // Check that this is so. If not we crash to find out what is going on.
12801 /*---------------------------------------------------------------------------*/
12802   if (scanptr.p->scanCompletedStatus == ZTRUE) {
12803     jam();
12804     closeCopyLab(signal);
12805     return;
12806   }//if
12807 
12808   if (scanptr.p->scanState == ScanRecord::WAIT_LQHKEY_COPY &&
12809       scanptr.p->scanErrorCounter)
12810   {
12811     jam();
12812     closeCopyLab(signal);
12813     return;
12814   }
12815 
12816   if (scanptr.p->scanState == ScanRecord::WAIT_LQHKEY_COPY) {
12817     jam();
12818 /*---------------------------------------------------------------------------*/
12819 // Make sure that something is in progress. Otherwise we will simply stop
12820 // and nothing more will happen.
12821 /*---------------------------------------------------------------------------*/
12822     systemErrorLab(signal, __LINE__);
12823     return;
12824   }//if
12825   return;
12826 }//Dblqh::copyCompletedLab()
12827 
nextRecordCopy(Signal * signal)12828 void Dblqh::nextRecordCopy(Signal* signal)
12829 {
12830   fragptr.i = tcConnectptr.p->fragmentptr;
12831   c_fragment_pool.getPtr(fragptr);
12832   scanptr.i = tcConnectptr.p->tcScanRec;
12833   c_scanRecordPool.getPtr(scanptr);
12834   if (scanptr.p->scanState != ScanRecord::WAIT_LQHKEY_COPY) {
12835     jam();
12836 /*---------------------------------------------------------------------------*/
12837 // Make sure that nothing is in progress. Otherwise we will have to simultaneous
12838 // scans on the same record and this will certainly lead to unexpected
12839 // behaviour.
12840 /*---------------------------------------------------------------------------*/
12841     systemErrorLab(signal, __LINE__);
12842     return;
12843   }//if
12844   scanptr.p->scanState = ScanRecord::WAIT_NEXT_SCAN_COPY;
12845   switch (fragptr.p->fragStatus) {
12846   case Fragrecord::FSACTIVE:
12847     jam();
12848     break;
12849   case Fragrecord::BLOCKED:
12850     jam();
12851     linkFragQueue(signal);
12852     tcConnectptr.p->transactionState = TcConnectionrec::COPY_STOPPED;
12853     return;
12854     break;
12855   case Fragrecord::FREE:
12856     jam();
12857   case Fragrecord::ACTIVE_CREATION:
12858     jam();
12859   case Fragrecord::CRASH_RECOVERING:
12860     jam();
12861   case Fragrecord::DEFINED:
12862     jam();
12863   case Fragrecord::REMOVING:
12864     jam();
12865   default:
12866     jam();
12867     systemErrorLab(signal, __LINE__);
12868     return;
12869     break;
12870   }//switch
12871   continueCopyAfterBlockedLab(signal);
12872   return;
12873 }//Dblqh::nextRecordCopy()
12874 
continueCopyAfterBlockedLab(Signal * signal)12875 void Dblqh::continueCopyAfterBlockedLab(Signal* signal)
12876 {
12877   scanptr.i = tcConnectptr.p->tcScanRec;
12878   c_scanRecordPool.getPtr(scanptr);
12879   tcConnectptr.p->errorCode = 0;
12880   Uint32 acc_op_ptr= get_acc_ptr_from_scan_record(scanptr.p, 0, false);
12881   if (acc_op_ptr != RNIL)
12882   {
12883     signal->theData[0] = scanptr.p->scanAccPtr;
12884     signal->theData[1] = acc_op_ptr;
12885     signal->theData[2] = NextScanReq::ZSCAN_NEXT_COMMIT;
12886     sendSignal(scanptr.p->scanBlockref, GSN_NEXT_SCANREQ, signal, 3, JBB);
12887   }
12888   else
12889   {
12890     /**
12891      * No need to commit (unlock)
12892      */
12893     signal->theData[0] = scanptr.p->scanAccPtr;
12894     signal->theData[1] = RNIL;
12895     signal->theData[2] = NextScanReq::ZSCAN_NEXT;
12896     sendSignal(scanptr.p->scanBlockref, GSN_NEXT_SCANREQ, signal, 3, JBB);
12897   }
12898   return;
12899 }//Dblqh::continueCopyAfterBlockedLab()
12900 
copyLqhKeyRefLab(Signal * signal)12901 void Dblqh::copyLqhKeyRefLab(Signal* signal)
12902 {
12903   ndbrequire(tcConnectptr.p->transid[1] == signal->theData[4]);
12904   Uint32 copyWords = signal->theData[3];
12905   scanptr.i = tcConnectptr.p->tcScanRec;
12906   c_scanRecordPool.getPtr(scanptr);
12907   scanptr.p->scanErrorCounter++;
12908   tcConnectptr.p->errorCode = terrorCode;
12909 
12910   LqhKeyConf* conf = (LqhKeyConf*)signal->getDataPtrSend();
12911   conf->transId1 = copyWords;
12912   conf->transId2 = tcConnectptr.p->transid[1];
12913   copyCompletedLab(signal);
12914 }//Dblqh::copyLqhKeyRefLab()
12915 
closeCopyLab(Signal * signal)12916 void Dblqh::closeCopyLab(Signal* signal)
12917 {
12918   if (tcConnectptr.p->copyCountWords > 0) {
12919 /*---------------------------------------------------------------------------*/
12920 // We are still waiting for responses from the starting node.
12921 // Wait until all of those have arrived until we start the
12922 // close process.
12923 /*---------------------------------------------------------------------------*/
12924     scanptr.p->scanState = ScanRecord::WAIT_LQHKEY_COPY;
12925     jam();
12926     return;
12927   }//if
12928   tcConnectptr.p->transid[0] = 0;
12929   tcConnectptr.p->transid[1] = 0;
12930   fragptr.i = tcConnectptr.p->fragmentptr;
12931   c_fragment_pool.getPtr(fragptr);
12932 
12933   /**
12934    * Stop sending ROWID for all operations from now on
12935    */
12936   fragptr.p->m_copy_started_state = Fragrecord::AC_NORMAL;
12937   if (ERROR_INSERTED(5714))
12938   {
12939     ndbout_c("Copy of tab: %u frag: %u complete",
12940              fragptr.p->tabRef, fragptr.p->fragId);
12941   }
12942 
12943   scanptr.i = tcConnectptr.p->tcScanRec;
12944   c_scanRecordPool.getPtr(scanptr);
12945   scanptr.p->scanState = ScanRecord::WAIT_CLOSE_COPY;
12946   switch (fragptr.p->fragStatus) {
12947   case Fragrecord::FSACTIVE:
12948     jam();
12949     break;
12950   case Fragrecord::BLOCKED:
12951     jam();
12952     linkFragQueue(signal);
12953     tcConnectptr.p->transactionState = TcConnectionrec::COPY_CLOSE_STOPPED;
12954     return;
12955     break;
12956   case Fragrecord::FREE:
12957     jam();
12958   case Fragrecord::ACTIVE_CREATION:
12959     jam();
12960   case Fragrecord::CRASH_RECOVERING:
12961     jam();
12962   case Fragrecord::DEFINED:
12963     jam();
12964   case Fragrecord::REMOVING:
12965     jam();
12966   default:
12967     jam();
12968     systemErrorLab(signal, __LINE__);
12969     return;
12970     break;
12971   }//switch
12972   continueCloseCopyAfterBlockedLab(signal);
12973   return;
12974 }//Dblqh::closeCopyLab()
12975 
continueCloseCopyAfterBlockedLab(Signal * signal)12976 void Dblqh::continueCloseCopyAfterBlockedLab(Signal* signal)
12977 {
12978   scanptr.i = tcConnectptr.p->tcScanRec;
12979   c_scanRecordPool.getPtr(scanptr);
12980   signal->theData[0] = scanptr.p->scanAccPtr;
12981   signal->theData[1] = RNIL;
12982   signal->theData[2] = NextScanReq::ZSCAN_CLOSE;
12983   sendSignal(scanptr.p->scanBlockref, GSN_NEXT_SCANREQ, signal, 3, JBB);
12984   return;
12985 }//Dblqh::continueCloseCopyAfterBlockedLab()
12986 
12987 /*---------------------------------------------------------------------------*/
12988 /*   ENTER NEXT_SCANCONF WITH                                                */
12989 /*     SCANPTR,                                                              */
12990 /*     TFRAGID,                                                              */
12991 /*     TACC_OPPTR,                                                           */
12992 /*     TLOCAL_KEY1,                                                          */
12993 /*     TLOCAL_KEY2,                                                          */
12994 /*     TKEY_LENGTH,                                                          */
12995 /*     TKEY1,                                                                */
12996 /*     TKEY2,                                                                */
12997 /*     TKEY3,                                                                */
12998 /*     TKEY4                                                                 */
12999 /*---------------------------------------------------------------------------*/
13000 /*   PRECONDITION: SCAN_STATE = WAIT_CLOSE_COPY                              */
13001 /*---------------------------------------------------------------------------*/
accCopyCloseConfLab(Signal * signal)13002 void Dblqh::accCopyCloseConfLab(Signal* signal)
13003 {
13004   tcConnectptr.i = scanptr.p->scanTcrec;
13005   scanptr.p->scanState = ScanRecord::WAIT_DELETE_STORED_PROC_ID_COPY;
13006   ptrCheckGuard(tcConnectptr, ctcConnectrecFileSize, tcConnectionrec);
13007   signal->theData[0] = tcConnectptr.p->tupConnectrec;
13008   signal->theData[1] = tcConnectptr.p->tableref;
13009   signal->theData[2] = scanptr.p->scanSchemaVersion;
13010   signal->theData[3] = ZDELETE_STORED_PROC_ID;
13011   signal->theData[4] = scanptr.p->scanStoredProcId;
13012   signal->theData[5] = scanptr.p->scanApiBlockref;
13013   sendSignal(tcConnectptr.p->tcTupBlockref, GSN_STORED_PROCREQ, signal, 6, JBB);
13014   return;
13015 }//Dblqh::accCopyCloseConfLab()
13016 
13017 /*---------------------------------------------------------------------------*/
13018 /*   ENTER STORED_PROCCONF WITH                                              */
13019 /*     TC_CONNECTPTR,                                                        */
13020 /*     TSTORED_PROC_ID                                                       */
13021 /*---------------------------------------------------------------------------*/
13022 /* PRECONDITION: SCAN_STATE = WAIT_DELETE_STORED_PROC_ID_COPY                */
13023 /*---------------------------------------------------------------------------*/
tupCopyCloseConfLab(Signal * signal)13024 void Dblqh::tupCopyCloseConfLab(Signal* signal)
13025 {
13026   fragptr.i = tcConnectptr.p->fragmentptr;
13027   c_fragment_pool.getPtr(fragptr);
13028   fragptr.p->copyFragState = ZIDLE;
13029 
13030   if (tcConnectptr.p->abortState == TcConnectionrec::NEW_FROM_TC) {
13031     jam();
13032     tcNodeFailptr.i = tcConnectptr.p->tcNodeFailrec;
13033     ptrCheckGuard(tcNodeFailptr, ctcNodeFailrecFileSize, tcNodeFailRecord);
13034     tcNodeFailptr.p->tcRecNow = tcConnectptr.i + 1;
13035     signal->theData[0] = ZLQH_TRANS_NEXT;
13036     signal->theData[1] = tcNodeFailptr.i;
13037     sendSignal(cownref, GSN_CONTINUEB, signal, 2, JBB);
13038 
13039     CopyFragRef * const ref = (CopyFragRef *)&signal->theData[0];
13040     ref->userPtr = scanptr.p->copyPtr;
13041     ref->sendingNodeId = cownNodeid;
13042     ref->startingNodeId = scanptr.p->scanNodeId;
13043     ref->tableId = fragptr.p->tabRef;
13044     ref->fragId = fragptr.p->fragId;
13045     ref->errorCode = ZNODE_FAILURE_ERROR;
13046     sendSignal(tcConnectptr.p->clientBlockref, GSN_COPY_FRAGREF, signal,
13047                CopyFragRef::SignalLength, JBB);
13048   } else {
13049     if (scanptr.p->scanErrorCounter > 0) {
13050       jam();
13051       CopyFragRef * const ref = (CopyFragRef *)&signal->theData[0];
13052       ref->userPtr = scanptr.p->copyPtr;
13053       ref->sendingNodeId = cownNodeid;
13054       ref->startingNodeId = scanptr.p->scanNodeId;
13055       ref->tableId = fragptr.p->tabRef;
13056       ref->fragId = fragptr.p->fragId;
13057       ref->errorCode = tcConnectptr.p->errorCode;
13058       sendSignal(tcConnectptr.p->clientBlockref, GSN_COPY_FRAGREF, signal,
13059                  CopyFragRef::SignalLength, JBB);
13060     } else {
13061       jam();
13062       CopyFragConf * const conf = (CopyFragConf *)&signal->theData[0];
13063       conf->userPtr = scanptr.p->copyPtr;
13064       conf->sendingNodeId = cownNodeid;
13065       conf->startingNodeId = scanptr.p->scanNodeId;
13066       conf->tableId = tcConnectptr.p->tableref;
13067       conf->fragId = tcConnectptr.p->fragmentid;
13068       conf->rows_lo = scanptr.p->m_curr_batch_size_rows;
13069       conf->bytes_lo = scanptr.p->m_curr_batch_size_bytes;
13070       sendSignal(tcConnectptr.p->clientBlockref, GSN_COPY_FRAGCONF, signal,
13071 		 CopyFragConf::SignalLength, JBB);
13072     }//if
13073   }//if
13074   releaseActiveCopy(signal);
13075   tcConnectptr.p->tcScanRec = RNIL;
13076   finishScanrec(signal);
13077   releaseOprec(signal);
13078   releaseTcrec(signal, tcConnectptr);
13079   releaseScanrec(signal);
13080 }//Dblqh::tupCopyCloseConfLab()
13081 
13082 /*---------------------------------------------------------------------------*/
13083 /*   A NODE FAILURE OCCURRED DURING THE COPY PROCESS. WE NEED TO CLOSE THE   */
13084 /*   COPY PROCESS SINCE A NODE FAILURE DURING THE COPY PROCESS WILL ALSO     */
13085 /*   FAIL THE NODE THAT IS TRYING TO START-UP.                               */
13086 /*---------------------------------------------------------------------------*/
closeCopyRequestLab(Signal * signal)13087 void Dblqh::closeCopyRequestLab(Signal* signal)
13088 {
13089   scanptr.p->scanErrorCounter++;
13090   if (0) ndbout_c("closeCopyRequestLab: scanState: %d", scanptr.p->scanState);
13091   switch (scanptr.p->scanState) {
13092   case ScanRecord::WAIT_TUPKEY_COPY:
13093   case ScanRecord::WAIT_NEXT_SCAN_COPY:
13094     jam();
13095 /*---------------------------------------------------------------------------*/
13096 /*   SET COMPLETION STATUS AND WAIT FOR OPPORTUNITY TO STOP THE SCAN.        */
13097 //   ALSO SET NO OF WORDS OUTSTANDING TO ZERO TO AVOID ETERNAL WAIT.
13098 /*---------------------------------------------------------------------------*/
13099     scanptr.p->scanCompletedStatus = ZTRUE;
13100     tcConnectptr.p->copyCountWords = 0;
13101     break;
13102   case ScanRecord::WAIT_ACC_COPY:
13103   case ScanRecord::WAIT_STORED_PROC_COPY:
13104     jam();
13105 /*---------------------------------------------------------------------------*/
13106 /*   WE ARE CURRENTLY STARTING UP THE SCAN. SET COMPLETED STATUS AND WAIT FOR*/
13107 /*   COMPLETION OF STARTUP.                                                  */
13108 /*---------------------------------------------------------------------------*/
13109     scanptr.p->scanCompletedStatus = ZTRUE;
13110     break;
13111   case ScanRecord::WAIT_CLOSE_COPY:
13112   case ScanRecord::WAIT_DELETE_STORED_PROC_ID_COPY:
13113     jam();
13114 /*---------------------------------------------------------------------------*/
13115 /*   CLOSE IS ALREADY ONGOING. WE NEED NOT DO ANYTHING.                      */
13116 /*---------------------------------------------------------------------------*/
13117     break;
13118   case ScanRecord::WAIT_LQHKEY_COPY:
13119     jam();
13120 /*---------------------------------------------------------------------------*/
13121 /*   WE ARE WAITING FOR THE FAILED NODE. THE NODE WILL NEVER COME BACK.      */
13122 //   WE NEED TO START THE FAILURE HANDLING IMMEDIATELY.
13123 //   ALSO SET NO OF WORDS OUTSTANDING TO ZERO TO AVOID ETERNAL WAIT.
13124 /*---------------------------------------------------------------------------*/
13125     tcConnectptr.p->copyCountWords = 0;
13126     closeCopyLab(signal);
13127     break;
13128   default:
13129     ndbrequire(false);
13130     break;
13131   }//switch
13132   return;
13133 }//Dblqh::closeCopyRequestLab()
13134 
13135 /* ****************************************************** */
13136 /*  COPY_ACTIVEREQ: Change state of a fragment to ACTIVE. */
13137 /* ****************************************************** */
execCOPY_ACTIVEREQ(Signal * signal)13138 void Dblqh::execCOPY_ACTIVEREQ(Signal* signal)
13139 {
13140   CRASH_INSERTION(5026);
13141 
13142   const CopyActiveReq * const req = (CopyActiveReq *)&signal->theData[0];
13143   jamEntry();
13144   Uint32 masterPtr = req->userPtr;
13145   BlockReference masterRef = req->userRef;
13146   tabptr.i = req->tableId;
13147   ptrCheckGuard(tabptr, ctabrecFileSize, tablerec);
13148   Uint32 fragId = req->fragId;
13149   Uint32 flags = req->flags;
13150   if (unlikely(signal->getLength() < CopyActiveReq::SignalLength))
13151   {
13152     jam();
13153     flags = 0;
13154   }
13155 
13156   ndbrequire(getFragmentrec(signal, fragId));
13157 
13158   fragptr.p->fragStatus = Fragrecord::FSACTIVE;
13159   fragptr.p->fragDistributionKey = req->distributionKey;
13160 
13161   if (TRACENR_FLAG)
13162     TRACENR("tab: " << tabptr.i
13163 	    << " frag: " << fragId
13164 	    << " COPY ACTIVE"
13165             << " flags: " << hex << flags << endl);
13166 
13167   ndbrequire(cnoActiveCopy < 3);
13168   cactiveCopy[cnoActiveCopy] = fragptr.i;
13169   cnoActiveCopy++;
13170   fragptr.p->masterBlockref = masterRef;
13171   fragptr.p->masterPtr = masterPtr;
13172 
13173   if ((flags & CopyActiveReq::CAR_NO_LOGGING) == 0)
13174   {
13175     jam();
13176     if (fragptr.p->lcpFlag == Fragrecord::LCP_STATE_TRUE)
13177     {
13178       jam();
13179       fragptr.p->logFlag = Fragrecord::STATE_TRUE;
13180     }
13181   }
13182 
13183   if (flags & CopyActiveReq::CAR_NO_WAIT)
13184   {
13185     jam();
13186     ndbrequire(fragptr.p->activeTcCounter == 0);
13187     Uint32 save = fragptr.p->startGci;
13188     fragptr.p->startGci = 0;
13189     sendCopyActiveConf(signal, tabptr.i);
13190     fragptr.p->startGci = save;
13191     return;
13192   }
13193 
13194   fragptr.p->activeTcCounter = 1;
13195 /*------------------------------------------------------*/
13196 /*       SET IT TO ONE TO ENSURE THAT IT IS NOT POSSIBLE*/
13197 /*       TO DECREASE IT TO ZERO UNTIL WE HAVE COMPLETED */
13198 /*       THE SCAN.                                      */
13199 /*------------------------------------------------------*/
13200   signal->theData[0] = ZSCAN_TC_CONNECT;
13201   signal->theData[1] = 0;
13202   signal->theData[2] = tabptr.i;
13203   signal->theData[3] = fragId;
13204   sendSignal(cownref, GSN_CONTINUEB, signal, 4, JBB);
13205   return;
13206 }//Dblqh::execCOPY_ACTIVEREQ()
13207 
scanTcConnectLab(Signal * signal,Uint32 tstartTcConnect,Uint32 fragId)13208 void Dblqh::scanTcConnectLab(Signal* signal, Uint32 tstartTcConnect, Uint32 fragId)
13209 {
13210   Uint32 tendTcConnect;
13211 
13212   ndbrequire(getFragmentrec(signal, fragId));
13213   if ((tstartTcConnect + 200) >= ctcConnectrecFileSize) {
13214     jam();
13215     tendTcConnect = ctcConnectrecFileSize - 1;
13216   } else {
13217     jam();
13218     tendTcConnect = tstartTcConnect + 200;
13219   }//if
13220   for (tcConnectptr.i = tstartTcConnect;
13221        tcConnectptr.i <= tendTcConnect;
13222        tcConnectptr.i++) {
13223     jam();
13224     ptrCheckGuard(tcConnectptr, ctcConnectrecFileSize, tcConnectionrec);
13225     if (tcConnectptr.p->transactionState != TcConnectionrec::IDLE) {
13226       switch (tcConnectptr.p->logWriteState) {
13227       case TcConnectionrec::NOT_WRITTEN:
13228         jam();
13229         if (fragptr.i == tcConnectptr.p->fragmentptr) {
13230           jam();
13231           fragptr.p->activeTcCounter = fragptr.p->activeTcCounter + 1;
13232           tcConnectptr.p->logWriteState = TcConnectionrec::NOT_WRITTEN_WAIT;
13233         }//if
13234         break;
13235       default:
13236         jam();
13237         /*empty*/;
13238         break;
13239       }//switch
13240     }//if
13241   }//for
13242   if (tendTcConnect < (ctcConnectrecFileSize - 1)) {
13243     jam();
13244     signal->theData[0] = ZSCAN_TC_CONNECT;
13245     signal->theData[1] = tendTcConnect + 1;
13246     signal->theData[2] = tabptr.i;
13247     signal->theData[3] = fragId;
13248     sendSignal(cownref, GSN_CONTINUEB, signal, 4, JBB);
13249   } else {
13250     jam();
13251 /*------------------------------------------------------*/
13252 /*       THE SCAN HAVE BEEN COMPLETED. WE CHECK IF ALL  */
13253 /*       OPERATIONS HAVE ALREADY BEEN COMPLETED.        */
13254 /*------------------------------------------------------*/
13255     ndbrequire(fragptr.p->activeTcCounter > 0);
13256     fragptr.p->activeTcCounter--;
13257     if (fragptr.p->activeTcCounter == 0) {
13258       jam();
13259 /*------------------------------------------------------*/
13260 /*       SET START GLOBAL CHECKPOINT TO THE NEXT        */
13261 /*       CHECKPOINT WE HAVE NOT YET HEARD ANYTHING ABOUT*/
13262 /*       THIS GCP WILL BE COMPLETELY COVERED BY THE LOG.*/
13263 /*------------------------------------------------------*/
13264       fragptr.p->startGci = cnewestGci + 1;
13265       sendCopyActiveConf(signal, tabptr.i);
13266     }//if
13267   }//if
13268   return;
13269 }//Dblqh::scanTcConnectLab()
13270 
13271 /*---------------------------------------------------------------------------*/
13272 /*   A NEW MASTER IS REQUESTING THE STATE IN LQH OF THE COPY FRAGMENT PARTS. */
13273 /*---------------------------------------------------------------------------*/
13274 /* ***************>> */
13275 /*  COPY_STATEREQ  > */
13276 /* ***************>> */
execCOPY_STATEREQ(Signal * signal)13277 void Dblqh::execCOPY_STATEREQ(Signal* signal)
13278 {
13279   jamEntry();
13280   ndbrequire(0)
13281 #if 0
13282   Uint32* dataPtr = &signal->theData[2];
13283   BlockReference tmasterBlockref = signal->theData[0];
13284   Uint32 tnoCopy = 0;
13285   do {
13286     jam();
13287     arrGuard(tnoCopy, 4);
13288     fragptr.i = cactiveCopy[tnoCopy];
13289     if (fragptr.i == RNIL) {
13290       jam();
13291       break;
13292     }//if
13293     c_fragment_pool.getPtr(fragptr);
13294     if (fragptr.p->copyFragState != ZIDLE) {
13295       jam();
13296 /*---------------------------------------------------------------------------*/
13297 /*   THIS FRAGMENT IS CURRENTLY ACTIVE IN COPYING THE FRAGMENT.              */
13298 /*---------------------------------------------------------------------------*/
13299       scanptr.i = fragptr.p->fragScanRec[NR_ScanNo];
13300       c_scanRecordPool.getPtr(scanptr);
13301       if (scanptr.p->scanCompletedStatus == ZTRUE) {
13302         jam();
13303         dataPtr[3 + (tnoCopy << 2)] = ZCOPY_CLOSING;
13304       } else {
13305         jam();
13306         dataPtr[3 + (tnoCopy << 2)] = ZCOPY_ONGOING;
13307       }//if
13308       dataPtr[2 + (tnoCopy << 2)] = scanptr.p->scanSchemaVersion;
13309       scanptr.p->scanApiBlockref = tmasterBlockref;
13310     } else {
13311       ndbrequire(fragptr.p->activeTcCounter != 0);
13312 /*---------------------------------------------------------------------------*/
13313 /*   COPY FRAGMENT IS COMPLETED AND WE ARE CURRENTLY GETTING THE STARTING    */
13314 /*   GCI OF THE NEW REPLICA OF THIS FRAGMENT.                                */
13315 /*---------------------------------------------------------------------------*/
13316       fragptr.p->masterBlockref = tmasterBlockref;
13317       dataPtr[3 + (tnoCopy << 2)] = ZCOPY_ACTIVATION;
13318     }//if
13319     dataPtr[tnoCopy << 2] = fragptr.p->tabRef;
13320     dataPtr[1 + (tnoCopy << 2)] = fragptr.p->fragId;
13321     tnoCopy++;
13322   } while (tnoCopy < cnoActiveCopy);
13323   signal->theData[0] = cownNodeid;
13324   signal->theData[1] = tnoCopy;
13325   sendSignal(tmasterBlockref, GSN_COPY_STATECONF, signal, 18, JBB);
13326 #endif
13327   return;
13328 }//Dblqh::execCOPY_STATEREQ()
13329 
13330 /* ========================================================================= */
13331 /* =======              INITIATE TC RECORD AT COPY FRAGMENT          ======= */
13332 /*                                                                           */
13333 /*       SUBROUTINE SHORT NAME = ICT                                         */
13334 /* ========================================================================= */
initCopyTc(Signal * signal,Operation_t op)13335 void Dblqh::initCopyTc(Signal* signal, Operation_t op)
13336 {
13337   tcConnectptr.p->operation = ZREAD;
13338   tcConnectptr.p->apiVersionNo = 0;
13339   tcConnectptr.p->opExec = 0;	/* NOT INTERPRETED MODE */
13340   tcConnectptr.p->schemaVersion = scanptr.p->scanSchemaVersion;
13341   Uint32 reqinfo = 0;
13342   LqhKeyReq::setDirtyFlag(reqinfo, 1);
13343   LqhKeyReq::setSimpleFlag(reqinfo, 1);
13344   LqhKeyReq::setOperation(reqinfo, op);
13345   LqhKeyReq::setGCIFlag(reqinfo, 1);
13346   LqhKeyReq::setNrCopyFlag(reqinfo, 1);
13347                                         /* AILen in LQHKEYREQ  IS ZERO */
13348   tcConnectptr.p->reqinfo = reqinfo;
13349 /* ------------------------------------------------------------------------ */
13350 /* THE RECEIVING NODE WILL EXPECT THAT IT IS THE LAST NODE AND WILL         */
13351 /* SEND COMPLETED AS THE RESPONSE SIGNAL SINCE DIRTY_OP BIT IS SET.         */
13352 /* ------------------------------------------------------------------------ */
13353   tcConnectptr.p->nodeAfterNext[0] = ZNIL;
13354   tcConnectptr.p->nodeAfterNext[1] = ZNIL;
13355   tcConnectptr.p->tcBlockref = cownref;
13356   tcConnectptr.p->readlenAi = 0;
13357   tcConnectptr.p->storedProcId = ZNIL;
13358   tcConnectptr.p->opExec = 0;
13359   tcConnectptr.p->nextSeqNoReplica = 0;
13360   tcConnectptr.p->dirtyOp = ZFALSE;
13361   tcConnectptr.p->lastReplicaNo = 0;
13362   tcConnectptr.p->currTupAiLen = 0;
13363   tcConnectptr.p->tcTimer = cLqhTimeOutCount;
13364 }//Dblqh::initCopyTc()
13365 
13366 /* ------------------------------------------------------------------------- */
13367 /* -------               SEND COPY_ACTIVECONF TO MASTER DIH          ------- */
13368 /*                                                                           */
13369 /* ------------------------------------------------------------------------- */
sendCopyActiveConf(Signal * signal,Uint32 tableId)13370 void Dblqh::sendCopyActiveConf(Signal* signal, Uint32 tableId)
13371 {
13372   releaseActiveCopy(signal);
13373   CopyActiveConf * const conf = (CopyActiveConf *)&signal->theData[0];
13374   conf->userPtr = fragptr.p->masterPtr;
13375   conf->tableId = tableId;
13376   conf->fragId = fragptr.p->fragId;
13377   conf->startingNodeId = cownNodeid;
13378   conf->startGci = fragptr.p->startGci;
13379   sendSignal(fragptr.p->masterBlockref, GSN_COPY_ACTIVECONF, signal,
13380              CopyActiveConf::SignalLength, JBB);
13381 }//Dblqh::sendCopyActiveConf()
13382 
13383 /* ##########################################################################
13384  * #######                       LOCAL CHECKPOINT MODULE              #######
13385  *
13386  * ##########################################################################
13387  * --------------------------------------------------------------------------
13388  *  THIS MODULE HANDLES THE EXECUTION AND CONTROL OF LOCAL CHECKPOINTS
13389  *  IT CONTROLS THE LOCAL CHECKPOINTS IN TUP AND ACC. IT DOES ALSO INTERACT
13390  *  WITH DIH TO CONTROL WHICH GLOBAL CHECKPOINTS THAT ARE RECOVERABLE
13391  * ------------------------------------------------------------------------- */
execEMPTY_LCP_REQ(Signal * signal)13392 void Dblqh::execEMPTY_LCP_REQ(Signal* signal)
13393 {
13394   jamEntry();
13395   CRASH_INSERTION(5008);
13396   EmptyLcpReq * const emptyLcpOrd = (EmptyLcpReq*)&signal->theData[0];
13397 
13398   ndbrequire(!isNdbMtLqh()); // Handled by DblqhProxy
13399 
13400   lcpPtr.i = 0;
13401   ptrAss(lcpPtr, lcpRecord);
13402 
13403   Uint32 nodeId = refToNode(emptyLcpOrd->senderRef);
13404 
13405   lcpPtr.p->m_EMPTY_LCP_REQ.set(nodeId);
13406   lcpPtr.p->reportEmpty = true;
13407 
13408   if (lcpPtr.p->lcpState == LcpRecord::LCP_IDLE){
13409     jam();
13410     bool ok = false;
13411     switch(clcpCompletedState){
13412     case LCP_IDLE:
13413       ok = true;
13414       sendEMPTY_LCP_CONF(signal, true);
13415       break;
13416     case LCP_RUNNING:
13417       ok = true;
13418       sendEMPTY_LCP_CONF(signal, false);
13419       break;
13420     case LCP_CLOSE_STARTED:
13421       jam();
13422     case ACC_LCP_CLOSE_COMPLETED:
13423       jam();
13424     case TUP_LCP_CLOSE_COMPLETED:
13425       jam();
13426       ok = true;
13427       break;
13428     }
13429     ndbrequire(ok);
13430 
13431   }//if
13432 
13433   return;
13434 }//Dblqh::execEMPTY_LCPREQ()
13435 
13436 #ifdef NDB_DEBUG_FULL
13437 static struct TraceLCP {
13438   void sendSignal(Uint32 ref, Uint32 gsn, Signal* signal,
13439 		  Uint32 len, Uint32 prio);
13440   void save(Signal*);
13441   void restore(SimulatedBlock&, Signal* sig);
13442   struct Sig {
13443     enum {
13444       Sig_save = 0,
13445       Sig_send = 1
13446     } type;
13447     SignalHeader header;
13448     Uint32 theData[25];
13449   };
13450   Vector<Sig> m_signals;
13451 } g_trace_lcp;
13452 template class Vector<TraceLCP::Sig>;
13453 #else
13454 #endif
13455 
13456 void
force_lcp(Signal * signal)13457 Dblqh::force_lcp(Signal* signal)
13458 {
13459   if (cLqhTimeOutCount == c_last_force_lcp_time)
13460   {
13461     jam();
13462     return;
13463   }
13464 
13465   c_last_force_lcp_time = cLqhTimeOutCount;
13466   signal->theData[0] = 7099;
13467   sendSignal(DBDIH_REF, GSN_DUMP_STATE_ORD, signal, 1, JBB);
13468 }
13469 
execLCP_FRAG_ORD(Signal * signal)13470 void Dblqh::execLCP_FRAG_ORD(Signal* signal)
13471 {
13472   jamEntry();
13473   CRASH_INSERTION(5010);
13474 
13475   LcpFragOrd lcpFragOrdCopy = * (LcpFragOrd *)&signal->theData[0];
13476   LcpFragOrd * lcpFragOrd = &lcpFragOrdCopy;
13477 
13478   Uint32 lcpId = lcpFragOrd->lcpId;
13479 
13480   lcpPtr.i = 0;
13481   ptrAss(lcpPtr, lcpRecord);
13482 
13483   lcpPtr.p->lastFragmentFlag = lcpFragOrd->lastFragmentFlag;
13484   if (lcpFragOrd->lastFragmentFlag)
13485   {
13486     jam();
13487     CRASH_INSERTION(5054);
13488     if (lcpPtr.p->lcpState == LcpRecord::LCP_IDLE) {
13489       jam();
13490       /* ----------------------------------------------------------
13491        *       NOW THE COMPLETE LOCAL CHECKPOINT ROUND IS COMPLETED.
13492        * -------------------------------------------------------- */
13493       if (cnoOfFragsCheckpointed > 0) {
13494         jam();
13495         completeLcpRoundLab(signal, lcpId);
13496       } else {
13497         jam();
13498         clcpCompletedState = LCP_IDLE;
13499         sendLCP_COMPLETE_REP(signal, lcpId);
13500       }//if
13501     }
13502     return;
13503   }//if
13504   tabptr.i = lcpFragOrd->tableId;
13505   ptrCheckGuard(tabptr, ctabrecFileSize, tablerec);
13506 
13507   lcpPtr.i = 0;
13508   ptrAss(lcpPtr, lcpRecord);
13509   ndbrequire(!lcpPtr.p->lcpQueued);
13510 
13511   if (c_lcpId < lcpFragOrd->lcpId)
13512   {
13513     jam();
13514 
13515     lcpPtr.p->firstFragmentFlag= true;
13516 
13517 #ifdef ERROR_INSERT
13518     if (check_ndb_versions())
13519     {
13520       /**
13521        * Only (so-far) in error insert
13522        *   check that keepGci (tail of REDO) is smaller than of head of REDO
13523        *
13524        */
13525       if (! ((cnewestCompletedGci >= lcpFragOrd->keepGci) &&
13526              (cnewestGci >= lcpFragOrd->keepGci)))
13527       {
13528         ndbout_c("lcpFragOrd->keepGci: %u cnewestCompletedGci: %u cnewestGci: %u",
13529                  lcpFragOrd->keepGci, cnewestCompletedGci, cnewestGci);
13530       }
13531       ndbrequire(cnewestCompletedGci >= lcpFragOrd->keepGci);
13532       ndbrequire(cnewestGci >= lcpFragOrd->keepGci);
13533     }
13534 #endif
13535 
13536     c_lcpId = lcpFragOrd->lcpId;
13537     ndbrequire(lcpPtr.p->lcpState == LcpRecord::LCP_IDLE);
13538     setLogTail(signal, lcpFragOrd->keepGci);
13539     ndbrequire(clcpCompletedState == LCP_IDLE);
13540     clcpCompletedState = LCP_RUNNING;
13541   }
13542 
13543   if (! (tabptr.p->tableStatus == Tablerec::TABLE_DEFINED || tabptr.p->tableStatus == Tablerec::TABLE_READ_ONLY))
13544   {
13545     jam();
13546     LcpRecord::FragOrd fragOrd;
13547     fragOrd.fragPtrI = RNIL;
13548     fragOrd.lcpFragOrd = * lcpFragOrd;
13549 
13550     Fragrecord tmp;
13551     tmp.maxGciInLcp = cnewestGci;
13552     tmp.maxGciCompletedInLcp = cnewestCompletedGci;
13553     sendLCP_FRAG_REP(signal, fragOrd, &tmp);
13554     return;
13555   }
13556 
13557   cnoOfFragsCheckpointed++;
13558   ndbrequire(getFragmentrec(signal, lcpFragOrd->fragmentId));
13559 
13560   if (lcpPtr.p->lcpState != LcpRecord::LCP_IDLE)
13561   {
13562     ndbrequire(lcpPtr.p->lcpQueued == false);
13563     lcpPtr.p->lcpQueued = true;
13564     lcpPtr.p->queuedFragment.fragPtrI = fragptr.i;
13565     lcpPtr.p->queuedFragment.lcpFragOrd = * lcpFragOrd;
13566     return;
13567   }//if
13568 
13569   lcpPtr.p->currentFragment.fragPtrI = fragptr.i;
13570   lcpPtr.p->currentFragment.lcpFragOrd = * lcpFragOrd;
13571 
13572   sendLCP_FRAGIDREQ(signal);
13573 }//Dblqh::execLCP_FRAGORD()
13574 
execLCP_PREPARE_REF(Signal * signal)13575 void Dblqh::execLCP_PREPARE_REF(Signal* signal)
13576 {
13577   jamEntry();
13578 
13579   LcpPrepareRef* ref= (LcpPrepareRef*)signal->getDataPtr();
13580 
13581   lcpPtr.i = ref->senderData;
13582   ptrCheckGuard(lcpPtr, clcpFileSize, lcpRecord);
13583   ndbrequire(lcpPtr.p->lcpState == LcpRecord::LCP_WAIT_FRAGID);
13584 
13585   fragptr.i = lcpPtr.p->currentFragment.fragPtrI;
13586   c_fragment_pool.getPtr(fragptr);
13587 
13588   ndbrequire(ref->tableId == fragptr.p->tabRef);
13589   ndbrequire(ref->fragmentId == fragptr.p->fragId);
13590 
13591   tabptr.i = ref->tableId;
13592   ptrCheckGuard(tabptr, ctabrecFileSize, tablerec);
13593 
13594   ndbrequire(lcpPtr.p->m_outstanding);
13595   lcpPtr.p->m_outstanding--;
13596 
13597   /**
13598    * Only BACKUP is allowed to ref LCP_PREPARE
13599    */
13600   ndbrequire(refToMain(signal->getSendersBlockRef()) == BACKUP);
13601   lcpPtr.p->m_error = ref->errorCode;
13602 
13603   if (lcpPtr.p->m_outstanding == 0)
13604   {
13605     jam();
13606 
13607     if(lcpPtr.p->firstFragmentFlag)
13608     {
13609       jam();
13610       LcpFragOrd *ord= (LcpFragOrd*)signal->getDataPtrSend();
13611       lcpPtr.p->firstFragmentFlag= false;
13612 
13613       if (!isNdbMtLqh())
13614       {
13615         jam();
13616         *ord = lcpPtr.p->currentFragment.lcpFragOrd;
13617         EXECUTE_DIRECT(PGMAN, GSN_LCP_FRAG_ORD, signal, signal->length());
13618         jamEntry();
13619 
13620         /**
13621          * First fragment mean that last LCP is complete :-)
13622          */
13623         jam();
13624         *ord = lcpPtr.p->currentFragment.lcpFragOrd;
13625         EXECUTE_DIRECT(TSMAN, GSN_LCP_FRAG_ORD,
13626                        signal, signal->length(), 0);
13627         jamEntry();
13628       }
13629       else
13630       {
13631         /**
13632          * Handle by LqhProxy
13633          */
13634       }
13635     }
13636 
13637     lcpPtr.p->lcpState = LcpRecord::LCP_COMPLETED;
13638     contChkpNextFragLab(signal);
13639   }
13640 }
13641 
13642 /* --------------------------------------------------------------------------
13643  *       PRECONDITION: LCP_PTR:LCP_STATE = WAIT_FRAGID
13644  * --------------------------------------------------------------------------
13645  *       WE NOW HAVE THE LOCAL FRAGMENTS THAT THE LOCAL CHECKPOINT WILL USE.
13646  * -------------------------------------------------------------------------- */
execLCP_PREPARE_CONF(Signal * signal)13647 void Dblqh::execLCP_PREPARE_CONF(Signal* signal)
13648 {
13649   jamEntry();
13650 
13651   LcpPrepareConf* conf= (LcpPrepareConf*)signal->getDataPtr();
13652 
13653   lcpPtr.i = conf->senderData;
13654   ptrCheckGuard(lcpPtr, clcpFileSize, lcpRecord);
13655   ndbrequire(lcpPtr.p->lcpState == LcpRecord::LCP_WAIT_FRAGID);
13656 
13657   fragptr.i = lcpPtr.p->currentFragment.fragPtrI;
13658   c_fragment_pool.getPtr(fragptr);
13659 
13660   // wl4391_todo obsolete
13661   if (refToBlock(signal->getSendersBlockRef()) != PGMAN)
13662   {
13663     ndbrequire(conf->tableId == fragptr.p->tabRef);
13664     ndbrequire(conf->fragmentId == fragptr.p->fragId);
13665   }
13666 
13667   ndbrequire(lcpPtr.p->m_outstanding);
13668   lcpPtr.p->m_outstanding--;
13669   if (lcpPtr.p->m_outstanding == 0)
13670   {
13671     jam();
13672 
13673     if(lcpPtr.p->firstFragmentFlag)
13674     {
13675       jam();
13676       LcpFragOrd *ord= (LcpFragOrd*)signal->getDataPtrSend();
13677       lcpPtr.p->firstFragmentFlag= false;
13678 
13679       // proxy is used in MT LQH to handle also the extra pgman worker
13680       if (!isNdbMtLqh())
13681       {
13682         jam();
13683         *ord = lcpPtr.p->currentFragment.lcpFragOrd;
13684         EXECUTE_DIRECT(PGMAN, GSN_LCP_FRAG_ORD, signal, signal->length());
13685         jamEntry();
13686 
13687         /**
13688          * First fragment mean that last LCP is complete :-)
13689          */
13690         jam();
13691         *ord = lcpPtr.p->currentFragment.lcpFragOrd;
13692         EXECUTE_DIRECT(TSMAN, GSN_LCP_FRAG_ORD,
13693                        signal, signal->length(), 0);
13694         jamEntry();
13695       }
13696       else
13697       {
13698         /**
13699          * Handled by proxy
13700          */
13701       }
13702     }
13703 
13704     if (lcpPtr.p->m_error)
13705     {
13706       jam();
13707 
13708       lcpPtr.p->lcpState = LcpRecord::LCP_COMPLETED;
13709       contChkpNextFragLab(signal);
13710       return;
13711     }
13712 
13713     lcpPtr.p->lcpState = LcpRecord::LCP_WAIT_HOLDOPS;
13714     lcpPtr.p->lcpState = LcpRecord::LCP_START_CHKP;
13715 
13716     /* ----------------------------------------------------------------------
13717      *    UPDATE THE MAX_GCI_IN_LCP AND MAX_GCI_COMPLETED_IN_LCP NOW BEFORE
13718      *    ACTIVATING THE FRAGMENT AGAIN.
13719      * --------------------------------------------------------------------- */
13720     ndbrequire(lcpPtr.p->currentFragment.lcpFragOrd.lcpNo < MAX_LCP_STORED);
13721     fragptr.p->maxGciInLcp = fragptr.p->newestGci;
13722     fragptr.p->maxGciCompletedInLcp = cnewestCompletedGci;
13723 
13724     {
13725       LcpFragOrd *ord= (LcpFragOrd*)signal->getDataPtrSend();
13726       *ord = lcpPtr.p->currentFragment.lcpFragOrd;
13727       Logfile_client lgman(this, c_lgman, 0);
13728       lgman.exec_lcp_frag_ord(signal);
13729       jamEntry();
13730 
13731       *ord = lcpPtr.p->currentFragment.lcpFragOrd;
13732       EXECUTE_DIRECT(DBTUP, GSN_LCP_FRAG_ORD, signal, signal->length());
13733       jamEntry();
13734     }
13735 
13736     BackupFragmentReq* req= (BackupFragmentReq*)signal->getDataPtr();
13737     req->tableId = lcpPtr.p->currentFragment.lcpFragOrd.tableId;
13738     req->fragmentNo = 0;
13739     req->backupPtr = m_backup_ptr;
13740     req->backupId = lcpPtr.p->currentFragment.lcpFragOrd.lcpId;
13741     req->count = 0;
13742 
13743 #ifdef NDB_DEBUG_FULL
13744     if(ERROR_INSERTED(5904))
13745     {
13746     g_trace_lcp.sendSignal(BACKUP_REF, GSN_BACKUP_FRAGMENT_REQ, signal,
13747 			   BackupFragmentReq::SignalLength, JBB);
13748     }
13749     else
13750 #endif
13751     {
13752       if (ERROR_INSERTED(5044) &&
13753 	  (fragptr.p->tabRef == c_error_insert_table_id) &&
13754 	  fragptr.p->fragId) // Not first frag
13755       {
13756 	/**
13757 	 * Force CRASH_INSERTION in 10s
13758 	 */
13759 	ndbout_c("table: %d frag: %d", fragptr.p->tabRef, fragptr.p->fragId);
13760 	SET_ERROR_INSERT_VALUE(5027);
13761 	sendSignalWithDelay(reference(), GSN_START_RECREQ, signal, 10000, 1);
13762       }
13763       else if (ERROR_INSERTED(5053))
13764       {
13765         BlockReference backupRef = calcInstanceBlockRef(BACKUP);
13766         sendSignalWithDelay(backupRef, GSN_BACKUP_FRAGMENT_REQ, signal,
13767                             150, BackupFragmentReq::SignalLength);
13768       }
13769       else
13770       {
13771         BlockReference backupRef = calcInstanceBlockRef(BACKUP);
13772 	sendSignal(backupRef, GSN_BACKUP_FRAGMENT_REQ, signal,
13773 		   BackupFragmentReq::SignalLength, JBB);
13774       }
13775     }
13776   }
13777 }
13778 
execBACKUP_FRAGMENT_REF(Signal * signal)13779 void Dblqh::execBACKUP_FRAGMENT_REF(Signal* signal)
13780 {
13781   BackupFragmentRef *ref= (BackupFragmentRef*)signal->getDataPtr();
13782   char buf[100];
13783   BaseString::snprintf(buf,sizeof(buf),
13784                        "Unable to store fragment during LCP. NDBFS Error: %u",
13785                        ref->errorCode);
13786 
13787   progError(__LINE__,
13788             (ref->errorCode & FsRef::FS_ERR_BIT)?
13789             NDBD_EXIT_AFS_UNKNOWN
13790             : ref->errorCode,
13791             buf);
13792 }
13793 
execBACKUP_FRAGMENT_CONF(Signal * signal)13794 void Dblqh::execBACKUP_FRAGMENT_CONF(Signal* signal)
13795 {
13796   jamEntry();
13797   //BackupFragmentConf* conf= (BackupFragmentConf*)signal->getDataPtr();
13798 
13799   lcpPtr.i = 0;
13800   ptrCheckGuard(lcpPtr, clcpFileSize, lcpRecord);
13801   ndbrequire(lcpPtr.p->lcpState == LcpRecord::LCP_START_CHKP);
13802   lcpPtr.p->lcpState = LcpRecord::LCP_COMPLETED;
13803 
13804   /* ------------------------------------------------------------------------
13805    *   THE LOCAL CHECKPOINT HAS BEEN COMPLETED. IT IS NOW TIME TO START
13806    *   A LOCAL CHECKPOINT ON THE NEXT FRAGMENT OR COMPLETE THIS LCP ROUND.
13807    * ------------------------------------------------------------------------
13808    *   WE START BY SENDING LCP_REPORT TO DIH TO REPORT THE COMPLETED LCP.
13809    *   TO CATER FOR NODE CRASHES WE SEND IT IN PARALLEL TO ALL NODES.
13810    * ----------------------------------------------------------------------- */
13811   fragptr.i = lcpPtr.p->currentFragment.fragPtrI;
13812   c_fragment_pool.getPtr(fragptr);
13813 
13814   /**
13815    * Update maxGciInLcp after scan has been performed
13816    */
13817 #if defined VM_TRACE || defined ERROR_INSERT
13818   if (fragptr.p->newestGci != fragptr.p->maxGciInLcp)
13819   {
13820     ndbout_c("tab: %u frag: %u increasing maxGciInLcp from %u to %u",
13821              fragptr.p->tabRef,
13822              fragptr.p->fragId,
13823              fragptr.p->maxGciInLcp, fragptr.p->newestGci);
13824   }
13825 #endif
13826 
13827   fragptr.p->maxGciInLcp = fragptr.p->newestGci;
13828 
13829   contChkpNextFragLab(signal);
13830   return;
13831 }//Dblqh::lcpCompletedLab()
13832 
13833 void
sendLCP_FRAG_REP(Signal * signal,const LcpRecord::FragOrd & fragOrd,const Fragrecord * fragPtrP) const13834 Dblqh::sendLCP_FRAG_REP(Signal * signal,
13835 			const LcpRecord::FragOrd & fragOrd,
13836                         const Fragrecord * fragPtrP) const
13837 {
13838   ndbrequire(fragOrd.lcpFragOrd.lcpNo < MAX_LCP_STORED);
13839   LcpFragRep * const lcpReport = (LcpFragRep *)&signal->theData[0];
13840   lcpReport->nodeId = cownNodeid;
13841   lcpReport->lcpId = fragOrd.lcpFragOrd.lcpId;
13842   lcpReport->lcpNo = fragOrd.lcpFragOrd.lcpNo;
13843   lcpReport->tableId = fragOrd.lcpFragOrd.tableId;
13844   lcpReport->fragId = fragOrd.lcpFragOrd.fragmentId;
13845   lcpReport->maxGciCompleted = fragPtrP->maxGciCompletedInLcp;
13846   lcpReport->maxGciStarted = fragPtrP->maxGciInLcp;
13847 
13848   Uint32 ref = DBDIH_REF;
13849   if (isNdbMtLqh())
13850   {
13851     jam();
13852     ref = DBLQH_REF;
13853   }
13854   lcpReport->nodeId = LcpFragRep::BROADCAST_REQ;
13855   sendSignal(ref, GSN_LCP_FRAG_REP, signal,
13856              LcpFragRep::SignalLength, JBB);
13857 }
13858 
contChkpNextFragLab(Signal * signal)13859 void Dblqh::contChkpNextFragLab(Signal* signal)
13860 {
13861   /* ------------------------------------------------------------------------
13862    *       UPDATE THE LATEST LOCAL CHECKPOINT COMPLETED ON FRAGMENT.
13863    *       UPDATE THE LCP_ID OF THIS CHECKPOINT.
13864    *       REMOVE THE LINK BETWEEN THE FRAGMENT RECORD AND THE LCP RECORD.
13865    * ----------------------------------------------------------------------- */
13866   if (fragptr.p->fragStatus == Fragrecord::BLOCKED) {
13867     jam();
13868     /**
13869      * LCP of fragment complete
13870      *   but restarting of operations isn't
13871      */
13872     lcpPtr.p->lcpState = LcpRecord::LCP_BLOCKED_COMP;
13873     return;
13874   }//if
13875 
13876   /**
13877    * Send rep when fragment is done + unblocked
13878    */
13879   sendLCP_FRAG_REP(signal, lcpPtr.p->currentFragment,
13880                    c_fragment_pool.getPtr(lcpPtr.p->currentFragment.fragPtrI));
13881 
13882   /* ------------------------------------------------------------------------
13883    *       WE ALSO RELEASE THE LOCAL LCP RECORDS.
13884    * ----------------------------------------------------------------------- */
13885   if (lcpPtr.p->lcpQueued) {
13886     jam();
13887     /* ----------------------------------------------------------------------
13888      *  Transfer the state from the queued to the active LCP.
13889      * --------------------------------------------------------------------- */
13890     lcpPtr.p->lcpQueued = false;
13891     lcpPtr.p->currentFragment = lcpPtr.p->queuedFragment;
13892 
13893     /* ----------------------------------------------------------------------
13894      *       START THE QUEUED LOCAL CHECKPOINT.
13895      * --------------------------------------------------------------------- */
13896     sendLCP_FRAGIDREQ(signal);
13897     return;
13898   }//if
13899 
13900   lcpPtr.p->lcpState = LcpRecord::LCP_IDLE;
13901   if (lcpPtr.p->lastFragmentFlag){
13902     jam();
13903     /* ----------------------------------------------------------------------
13904      *       NOW THE COMPLETE LOCAL CHECKPOINT ROUND IS COMPLETED.
13905      * --------------------------------------------------------------------- */
13906     completeLcpRoundLab(signal, lcpPtr.p->currentFragment.lcpFragOrd.lcpId);
13907     return;
13908   }//if
13909 
13910   if (lcpPtr.p->reportEmpty) {
13911     jam();
13912     sendEMPTY_LCP_CONF(signal, false);
13913   }//if
13914   return;
13915 }//Dblqh::contChkpNextFragLab()
13916 
sendLCP_FRAGIDREQ(Signal * signal)13917 void Dblqh::sendLCP_FRAGIDREQ(Signal* signal)
13918 {
13919   TablerecPtr tabPtr;
13920   tabPtr.i = lcpPtr.p->currentFragment.lcpFragOrd.tableId;
13921   ptrAss(tabPtr, tablerec);
13922 
13923   if(tabPtr.p->tableStatus != Tablerec::TABLE_DEFINED)
13924   {
13925     jam();
13926     /**
13927      * Fake that the fragment is done
13928      */
13929     contChkpNextFragLab(signal);
13930     return;
13931   }
13932 
13933   lcpPtr.p->m_error = 0;
13934   lcpPtr.p->m_outstanding = 1;
13935 
13936   ndbrequire(tabPtr.p->tableStatus == Tablerec::TABLE_DEFINED ||
13937              tabPtr.p->tableStatus == Tablerec::TABLE_READ_ONLY);
13938 
13939   lcpPtr.p->lcpState = LcpRecord::LCP_WAIT_FRAGID;
13940   LcpPrepareReq* req= (LcpPrepareReq*)signal->getDataPtr();
13941   req->senderData = lcpPtr.i;
13942   req->senderRef = reference();
13943   req->lcpNo = lcpPtr.p->currentFragment.lcpFragOrd.lcpNo;
13944   req->tableId = lcpPtr.p->currentFragment.lcpFragOrd.tableId;
13945   req->fragmentId = lcpPtr.p->currentFragment.lcpFragOrd.fragmentId;
13946   req->lcpId = lcpPtr.p->currentFragment.lcpFragOrd.lcpId % MAX_LCP_STORED;
13947   req->backupPtr = m_backup_ptr;
13948   req->backupId = lcpPtr.p->currentFragment.lcpFragOrd.lcpId;
13949   BlockReference backupRef = calcInstanceBlockRef(BACKUP);
13950   sendSignal(backupRef, GSN_LCP_PREPARE_REQ, signal,
13951 	     LcpPrepareReq::SignalLength, JBB);
13952 
13953 }//Dblqh::sendLCP_FRAGIDREQ()
13954 
sendEMPTY_LCP_CONF(Signal * signal,bool idle)13955 void Dblqh::sendEMPTY_LCP_CONF(Signal* signal, bool idle)
13956 {
13957   EmptyLcpRep * sig = (EmptyLcpRep*)signal->getDataPtrSend();
13958   EmptyLcpConf * rep = (EmptyLcpConf*)sig->conf;
13959 
13960   /* ----------------------------------------------------------------------
13961    *       We have been requested to report when there are no more local
13962    *       waiting to be started or ongoing. In this signal we also report
13963    *       the last completed fragments state.
13964    * ---------------------------------------------------------------------- */
13965   rep->senderNodeId = getOwnNodeId();
13966   if(!idle){
13967     jam();
13968     rep->idle = 0 ;
13969     rep->tableId = lcpPtr.p->currentFragment.lcpFragOrd.tableId;
13970     rep->fragmentId = lcpPtr.p->currentFragment.lcpFragOrd.fragmentId;
13971     rep->lcpNo = lcpPtr.p->currentFragment.lcpFragOrd.lcpNo;
13972     rep->lcpId = lcpPtr.p->currentFragment.lcpFragOrd.lcpId;
13973   } else {
13974     jam();
13975     rep->idle = 1;
13976     rep->tableId = ~0;
13977     rep->fragmentId = ~0;
13978     rep->lcpNo = ~0;
13979     rep->lcpId = c_lcpId;
13980   }
13981 
13982   lcpPtr.p->m_EMPTY_LCP_REQ.copyto(NdbNodeBitmask::Size, sig->receiverGroup);
13983   sendSignal(DBDIH_REF, GSN_EMPTY_LCP_REP, signal,
13984              EmptyLcpRep::SignalLength + EmptyLcpConf::SignalLength, JBB);
13985 
13986   lcpPtr.p->reportEmpty = false;
13987   lcpPtr.p->m_EMPTY_LCP_REQ.clear();
13988 }//Dblqh::sendEMPTY_LCPCONF()
13989 
13990 /* --------------------------------------------------------------------------
13991  *       THE LOCAL CHECKPOINT ROUND IS NOW COMPLETED. SEND COMPLETED MESSAGE
13992  *       TO THE MASTER DIH.
13993  * ------------------------------------------------------------------------- */
completeLcpRoundLab(Signal * signal,Uint32 lcpId)13994 void Dblqh::completeLcpRoundLab(Signal* signal, Uint32 lcpId)
13995 {
13996   clcpCompletedState = LCP_CLOSE_STARTED;
13997 
13998   lcpPtr.i = 0;
13999   ptrAss(lcpPtr, lcpRecord);
14000   lcpPtr.p->m_outstanding = 0;
14001 
14002   EndLcpReq* req= (EndLcpReq*)signal->getDataPtr();
14003   req->senderData= lcpPtr.i;
14004   req->senderRef= reference();
14005   req->backupPtr= m_backup_ptr;
14006   req->backupId= lcpId;
14007 
14008   BlockReference backupRef = calcInstanceBlockRef(BACKUP);
14009 
14010   lcpPtr.p->m_outstanding++;
14011   sendSignal(backupRef, GSN_END_LCP_REQ, signal,
14012 	     EndLcpReq::SignalLength, JBB);
14013 
14014   if (!isNdbMtLqh())
14015   {
14016     jam();
14017     lcpPtr.p->m_outstanding++;
14018     sendSignal(PGMAN_REF, GSN_END_LCP_REQ, signal,
14019                EndLcpReq::SignalLength, JBB);
14020 
14021     lcpPtr.p->m_outstanding++;
14022     sendSignal(LGMAN_REF, GSN_END_LCP_REQ, signal,
14023                EndLcpReq::SignalLength, JBB);
14024 
14025     EXECUTE_DIRECT(TSMAN, GSN_END_LCP_REQ,
14026                    signal, EndLcpReq::SignalLength, 0);
14027   }
14028   else
14029   {
14030     /**
14031      * This is all handled by LqhProxy
14032      */
14033   }
14034   return;
14035 }//Dblqh::completeLcpRoundLab()
14036 
execEND_LCPCONF(Signal * signal)14037 void Dblqh::execEND_LCPCONF(Signal* signal)
14038 {
14039   jamEntry();
14040   lcpPtr.i = 0;
14041   ptrAss(lcpPtr, lcpRecord);
14042 
14043   ndbrequire(clcpCompletedState == LCP_CLOSE_STARTED);
14044   ndbrequire(lcpPtr.p->m_outstanding);
14045 
14046   lcpPtr.p->m_outstanding--;
14047   if(lcpPtr.p->m_outstanding == 0)
14048   {
14049     jam();
14050     clcpCompletedState = LCP_IDLE;
14051     sendLCP_COMPLETE_REP(signal, lcpPtr.p->currentFragment.lcpFragOrd.lcpId);
14052 
14053     CRASH_INSERTION(5056);
14054   }
14055 }//Dblqh::execEND_LCPCONF()
14056 
sendLCP_COMPLETE_REP(Signal * signal,Uint32 lcpId)14057 void Dblqh::sendLCP_COMPLETE_REP(Signal* signal, Uint32 lcpId)
14058 {
14059   cnoOfFragsCheckpointed = 0;
14060   ndbrequire((cnoOfNodes - 1) < (MAX_NDB_NODES - 1));
14061   /* ------------------------------------------------------------------------
14062    *       WE SEND COMP_LCP_ROUND TO ALL NODES TO PREPARE FOR NODE CRASHES.
14063    * ----------------------------------------------------------------------- */
14064   lcpPtr.i = 0;
14065   ptrAss(lcpPtr, lcpRecord);
14066   lcpPtr.p->lastFragmentFlag = false;
14067   lcpPtr.p->firstFragmentFlag = false;
14068 
14069   LcpCompleteRep* rep = (LcpCompleteRep*)signal->getDataPtrSend();
14070   rep->nodeId = getOwnNodeId();
14071   rep->lcpId = lcpId;
14072   rep->blockNo = DBLQH;
14073 
14074   Uint32 ref = DBDIH_REF;
14075   if (isNdbMtLqh())
14076   {
14077     jam();
14078     ref = DBLQH_REF;
14079   }
14080   rep->nodeId = LcpFragRep::BROADCAST_REQ;
14081 
14082   sendSignal(ref, GSN_LCP_COMPLETE_REP, signal,
14083              LcpCompleteRep::SignalLength, JBB);
14084 
14085   if(lcpPtr.p->reportEmpty){
14086     jam();
14087     sendEMPTY_LCP_CONF(signal, true);
14088   }
14089 
14090   if (cstartRecReq < SRR_FIRST_LCP_DONE)
14091   {
14092     jam();
14093     ndbrequire(cstartRecReq == SRR_REDO_COMPLETE);
14094     cstartRecReq = SRR_FIRST_LCP_DONE;
14095   }
14096   return;
14097 
14098 }//Dblqh::sendCOMP_LCP_ROUND()
14099 
14100 #if NOT_YET
14101 void
execLCP_COMPLETE_REP(Signal * signal)14102 Dblqh::execLCP_COMPLETE_REP(Signal* signal)
14103 {
14104   /**
14105    * This is sent when last LCP is restorable
14106    */
14107   LcpCompleteRep * rep = (LcpCompleteRep*)signal->getDataPtr();
14108   Uint32 keepGci = rep->keepGci;
14109   setLogTail(signal, keepGci);
14110 }
14111 #endif
14112 
14113 /* ------------------------------------------------------------------------- */
14114 /* -------               SEND ACC_LCPREQ AND TUP_LCPREQ              ------- */
14115 /*                                                                           */
14116 /*       INPUT:          LCP_PTR             LOCAL CHECKPOINT RECORD         */
14117 /*                       FRAGPTR             FRAGMENT RECORD                 */
14118 /*       SUBROUTINE SHORT NAME = STL                                         */
14119 /* ------------------------------------------------------------------------- */
sendStartLcp(Signal * signal)14120 void Dblqh::sendStartLcp(Signal* signal)
14121 {
14122 }//Dblqh::sendStartLcp()
14123 
14124 /* ------------------------------------------------------------------------- */
14125 /* -------               SET THE LOG TAIL IN THE LOG FILES           ------- */
14126 /*                                                                           */
14127 /*THIS SUBROUTINE HAVE BEEN BUGGY AND IS RATHER COMPLEX. IT IS IMPORTANT TO  */
14128 /*REMEMBER THAT WE SEARCH FROM THE TAIL UNTIL WE REACH THE HEAD (CURRENT).   */
14129 /*THE TAIL AND HEAD CAN BE ON THE SAME MBYTE. WE SEARCH UNTIL WE FIND A MBYTE*/
14130 /*THAT WE NEED TO KEEP. WE THEN SET THE TAIL TO BE THE PREVIOUS. IF WE DO    */
14131 /*NOT FIND A MBYTE THAT WE NEED TO KEEP UNTIL WE REACH THE HEAD THEN WE USE  */
14132 /*THE HEAD AS TAIL. FINALLY WE HAVE TO MOVE BACK THE TAIL TO ALSO INCLUDE    */
14133 /*ALL PREPARE RECORDS. THIS MEANS THAT LONG-LIVED TRANSACTIONS ARE DANGEROUS */
14134 /*FOR SHORT LOGS.                                                            */
14135 /* ------------------------------------------------------------------------- */
14136 
setLogTail(Signal * signal,Uint32 keepGci)14137 void Dblqh::setLogTail(Signal* signal, Uint32 keepGci)
14138 {
14139   LogPartRecordPtr sltLogPartPtr;
14140   LogFileRecordPtr sltLogFilePtr;
14141   UintR tsltMbyte;
14142   UintR tsltStartMbyte;
14143   UintR tsltIndex;
14144   UintR tsltFlag;
14145 
14146   for (sltLogPartPtr.i = 0; sltLogPartPtr.i < clogPartFileSize; sltLogPartPtr.i++) {
14147     jam();
14148     bool TchangeMB = false;
14149 retry:
14150     ptrAss(sltLogPartPtr, logPartRecord);
14151     findLogfile(signal, sltLogPartPtr.p->logTailFileNo,
14152                 sltLogPartPtr, &sltLogFilePtr);
14153 
14154     tsltMbyte = sltLogPartPtr.p->logTailMbyte;
14155     tsltStartMbyte = tsltMbyte;
14156     tsltFlag = ZFALSE;
14157     if (sltLogFilePtr.i == sltLogPartPtr.p->currentLogfile) {
14158 /* ------------------------------------------------------------------------- */
14159 /*THE LOG AND THE TAIL IS ALREADY IN THE SAME FILE.                          */
14160 /* ------------------------------------------------------------------------- */
14161       if (sltLogFilePtr.p->currentMbyte >= sltLogPartPtr.p->logTailMbyte) {
14162         jam();
14163 /* ------------------------------------------------------------------------- */
14164 /*THE CURRENT MBYTE IS AHEAD OF OR AT THE TAIL. THUS WE WILL ONLY LOOK FOR   */
14165 /*THE TAIL UNTIL WE REACH THE CURRENT MBYTE WHICH IS IN THIS LOG FILE.       */
14166 /*IF THE LOG TAIL IS AHEAD OF THE CURRENT MBYTE BUT IN THE SAME LOG FILE     */
14167 /*THEN WE HAVE TO SEARCH THROUGH ALL FILES BEFORE WE COME TO THE CURRENT     */
14168 /*MBYTE. WE ALWAYS STOP WHEN WE COME TO THE CURRENT MBYTE SINCE THE TAIL     */
14169 /*CAN NEVER BE BEFORE THE HEAD.                                              */
14170 /* ------------------------------------------------------------------------- */
14171         tsltFlag = ZTRUE;
14172       }//if
14173     }//if
14174 
14175 /* ------------------------------------------------------------------------- */
14176 /*NOW START SEARCHING FOR THE NEW TAIL, STARTING AT THE CURRENT TAIL AND     */
14177 /*PROCEEDING UNTIL WE FIND A MBYTE WHICH IS NEEDED TO KEEP OR UNTIL WE REACH */
14178 /*CURRENT MBYTE (THE HEAD).                                                  */
14179 /* ------------------------------------------------------------------------- */
14180   SLT_LOOP:
14181     for (tsltIndex = tsltStartMbyte;
14182 	 tsltIndex <= clogFileSize - 1;
14183 	 tsltIndex++) {
14184       if (sltLogFilePtr.p->logMaxGciStarted[tsltIndex] >= keepGci) {
14185 /* ------------------------------------------------------------------------- */
14186 /*WE ARE NOT ALLOWED TO STEP THE LOG ANY FURTHER AHEAD                       */
14187 /*SET THE NEW LOG TAIL AND CONTINUE WITH NEXT LOG PART.                      */
14188 /*THIS MBYTE IS NOT TO BE INCLUDED SO WE NEED TO STEP BACK ONE MBYTE.        */
14189 /* ------------------------------------------------------------------------- */
14190         if (tsltIndex != 0) {
14191           jam();
14192           tsltMbyte = tsltIndex - 1;
14193         } else {
14194           jam();
14195 /* ------------------------------------------------------------------------- */
14196 /*STEPPING BACK INCLUDES ALSO STEPPING BACK TO THE PREVIOUS LOG FILE.        */
14197 /* ------------------------------------------------------------------------- */
14198           tsltMbyte = clogFileSize - 1;
14199           sltLogFilePtr.i = sltLogFilePtr.p->prevLogFile;
14200           ptrCheckGuard(sltLogFilePtr, clogFileFileSize, logFileRecord);
14201         }//if
14202         goto SLT_BREAK;
14203       } else {
14204         jam();
14205         if (tsltFlag == ZTRUE) {
14206 /* ------------------------------------------------------------------------- */
14207 /*WE ARE IN THE SAME FILE AS THE CURRENT MBYTE AND WE CAN REACH THE CURRENT  */
14208 /*MBYTE BEFORE WE REACH A NEW TAIL.                                          */
14209 /* ------------------------------------------------------------------------- */
14210           if (tsltIndex == sltLogFilePtr.p->currentMbyte) {
14211             jam();
14212 /* ------------------------------------------------------------------------- */
14213 /*THE TAIL OF THE LOG IS ACTUALLY WITHIN THE CURRENT MBYTE. THUS WE SET THE  */
14214 /*LOG TAIL TO BE THE CURRENT MBYTE.                                          */
14215 /* ------------------------------------------------------------------------- */
14216             tsltMbyte = sltLogFilePtr.p->currentMbyte;
14217             goto SLT_BREAK;
14218           }//if
14219         }//if
14220       }//if
14221     }//for
14222     sltLogFilePtr.i = sltLogFilePtr.p->nextLogFile;
14223     ptrCheckGuard(sltLogFilePtr, clogFileFileSize, logFileRecord);
14224     if (sltLogFilePtr.i == sltLogPartPtr.p->currentLogfile) {
14225       jam();
14226       tsltFlag = ZTRUE;
14227     }//if
14228     tsltStartMbyte = 0;
14229     goto SLT_LOOP;
14230   SLT_BREAK:
14231     jam();
14232     {
14233       UintR ToldTailFileNo = sltLogPartPtr.p->logTailFileNo;
14234       UintR ToldTailMByte = sltLogPartPtr.p->logTailMbyte;
14235 
14236 /* ------------------------------------------------------------------------- */
14237 /*SINCE LOG_MAX_GCI_STARTED ONLY KEEP TRACK OF COMMIT LOG RECORDS WE ALSO    */
14238 /*HAVE TO STEP BACK THE TAIL SO THAT WE INCLUDE ALL PREPARE RECORDS          */
14239 /*NEEDED FOR THOSE COMMIT RECORDS IN THIS MBYTE. THIS IS A RATHER            */
14240 /*CONSERVATIVE APPROACH BUT IT WORKS.                                        */
14241 /* ------------------------------------------------------------------------- */
14242       arrGuard(tsltMbyte, clogFileSize);
14243       sltLogPartPtr.p->logTailFileNo =
14244         sltLogFilePtr.p->logLastPrepRef[tsltMbyte] >> 16;
14245       sltLogPartPtr.p->logTailMbyte =
14246         sltLogFilePtr.p->logLastPrepRef[tsltMbyte] & 65535;
14247 
14248       if (DEBUG_REDO)
14249       {
14250         ndbout_c("part: %u setLogTail(gci: %u): file: %u mb: %u",
14251                  sltLogPartPtr.p->logPartNo,
14252                  keepGci,
14253                  sltLogPartPtr.p->logTailFileNo,
14254                  sltLogPartPtr.p->logTailMbyte);
14255       }
14256 
14257       bool tailmoved = !(ToldTailFileNo == sltLogPartPtr.p->logTailFileNo &&
14258                          ToldTailMByte == sltLogPartPtr.p->logTailMbyte);
14259 
14260       LogFileRecordPtr tmpfile;
14261       tmpfile.i = sltLogPartPtr.p->currentLogfile;
14262       ptrCheckGuard(tmpfile, clogFileFileSize, logFileRecord);
14263 
14264       LogPosition head = { tmpfile.p->fileNo, tmpfile.p->currentMbyte };
14265       LogPosition tail = { sltLogPartPtr.p->logTailFileNo,
14266                            sltLogPartPtr.p->logTailMbyte};
14267       Uint64 mb = free_log(head, tail, sltLogPartPtr.p->noLogFiles,
14268                            clogFileSize);
14269 
14270       if (mb <= c_free_mb_force_lcp_limit)
14271       {
14272         /**
14273          * Force a new LCP
14274          */
14275         force_lcp(signal);
14276       }
14277 
14278       if (tailmoved && mb > c_free_mb_tail_problem_limit)
14279       {
14280         jam();
14281         update_log_problem(signal, sltLogPartPtr,
14282                            LogPartRecord::P_TAIL_PROBLEM, false);
14283       }
14284       else if (!tailmoved && mb <= c_free_mb_force_lcp_limit)
14285       {
14286         jam();
14287         /**
14288          * Tail didn't move...and we forced a new LCP
14289          *   This could be as currentMb, contains backreferences making it
14290          *   Check if changing mb forward will help situation
14291          */
14292         if (mb < 2)
14293         {
14294           /**
14295            * 0 or 1 mb free, no point in trying to changeMbyte forward...
14296            */
14297           jam();
14298           goto next;
14299         }
14300 
14301         if (TchangeMB)
14302         {
14303           jam();
14304           /**
14305            * We already did move forward...
14306            */
14307           goto next;
14308         }
14309 
14310         TcConnectionrecPtr tmp;
14311         tmp.i = sltLogPartPtr.p->firstLogTcrec;
14312         if (tmp.i != RNIL)
14313         {
14314           jam();
14315           ptrCheckGuard(tmp, ctcConnectrecFileSize, tcConnectionrec);
14316           Uint32 fileNo = tmp.p->logStartFileNo;
14317           Uint32 mbyte = tmp.p->logStartPageNo >> ZTWOLOG_NO_PAGES_IN_MBYTE;
14318 
14319           if (fileNo == sltLogPartPtr.p->logTailFileNo &&
14320               mbyte == sltLogPartPtr.p->logTailMbyte)
14321           {
14322             jam();
14323             /**
14324              * An uncommitted operation...still pending...
14325              *   with back-reference to tail...not much to do
14326              *   (theoretically we could rewrite log-entry here...
14327              *    but this is for future)
14328              * skip to next
14329              */
14330             goto next;
14331           }
14332         }
14333 
14334         {
14335           /**
14336            * Try forcing a changeMbyte
14337            */
14338           jam();
14339           logPartPtr = sltLogPartPtr;
14340           logFilePtr.i = logPartPtr.p->currentLogfile;
14341           ptrCheckGuard(logFilePtr, clogFileFileSize, logFileRecord);
14342           logPagePtr.i = logFilePtr.p->currentLogpage;
14343           ptrCheckGuard(logPagePtr, clogPageFileSize, logPageRecord);
14344           changeMbyte(signal);
14345           TchangeMB = true; // don't try this twice...
14346           goto retry;
14347         }
14348       }
14349     }
14350 next:
14351     (void)1;
14352   }//for
14353 }//Dblqh::setLogTail()
14354 
14355 /* ######################################################################### */
14356 /* #######                       GLOBAL CHECKPOINT MODULE            ####### */
14357 /*                                                                           */
14358 /* ######################################################################### */
14359 /*---------------------------------------------------------------------------*/
14360 /* THIS MODULE HELPS DIH IN DISCOVERING WHEN GLOBAL CHECKPOINTS ARE          */
14361 /* RECOVERABLE. IT HANDLES THE REQUEST GCP_SAVEREQ THAT REQUESTS LQH TO      */
14362 /* SAVE A PARTICULAR GLOBAL CHECKPOINT TO DISK AND RESPOND WHEN COMPLETED.   */
14363 /*---------------------------------------------------------------------------*/
14364 /* *************** */
14365 /*  GCP_SAVEREQ  > */
14366 /* *************** */
14367 
14368 #if defined VM_TRACE || defined ERROR_INSERT
14369 static Uint32 m_gcp_monitor = 0;
14370 #endif
14371 
execGCP_SAVEREQ(Signal * signal)14372 void Dblqh::execGCP_SAVEREQ(Signal* signal)
14373 {
14374   jamEntry();
14375   const GCPSaveReq * const saveReq = (GCPSaveReq *)&signal->theData[0];
14376 
14377   CRASH_INSERTION(5000);
14378 
14379   if (ERROR_INSERTED(5007)){
14380     CLEAR_ERROR_INSERT_VALUE;
14381     sendSignalWithDelay(cownref, GSN_GCP_SAVEREQ, signal, 10000,
14382 			signal->length());
14383     return;
14384   }
14385 
14386   if (unlikely(refToNode(signal->getSendersBlockRef()) != getOwnNodeId()))
14387   {
14388     /**
14389      * This code is only run during upgrade from pre-micro-gcp version.
14390      *
14391      * During startup, we make sure not to allow starting multi-threaded
14392      * NDBD while such an upgrade is taking place. So the EXECUTE_DIRECT()
14393      * below, which would be cross-thread in multi-threaded NDBD, is thus
14394      * safe since it never runs in the non-safe case.
14395      */
14396     ndbassert(!isMultiThreaded());
14397     jam();
14398     ndbassert(!ndb_check_micro_gcp
14399               (getNodeInfo(refToNode
14400                            (signal->getSendersBlockRef())).m_version));
14401     EXECUTE_DIRECT(DBDIH, GSN_GCP_SAVEREQ, signal, signal->getLength());
14402     return;
14403   }
14404 
14405   const Uint32 dihBlockRef = saveReq->dihBlockRef;
14406   const Uint32 dihPtr = saveReq->dihPtr;
14407   const Uint32 gci = saveReq->gci;
14408 
14409 #if defined VM_TRACE || defined ERROR_INSERT
14410   if (!isNdbMtLqh()) { // wl4391_todo mt-safe
14411   ndbrequire(m_gcp_monitor == 0 ||
14412              (m_gcp_monitor == gci) ||
14413              (m_gcp_monitor + 1) == gci);
14414   }
14415   m_gcp_monitor = gci;
14416 #endif
14417 
14418   if(getNodeState().startLevel >= NodeState::SL_STOPPING_4){
14419     GCPSaveRef * const saveRef = (GCPSaveRef*)&signal->theData[0];
14420     saveRef->dihPtr = dihPtr;
14421     saveRef->nodeId = getOwnNodeId();
14422     saveRef->gci    = gci;
14423     saveRef->errorCode = GCPSaveRef::NodeShutdownInProgress;
14424     sendSignal(dihBlockRef, GSN_GCP_SAVEREF, signal,
14425 	       GCPSaveRef::SignalLength, JBB);
14426     return;
14427   }
14428 
14429   Uint32 saveNewestCompletedGci = cnewestCompletedGci;
14430   cnewestCompletedGci = gci;
14431 
14432   if (cstartRecReq < SRR_REDO_COMPLETE)
14433   {
14434     /**
14435      * REDO running is not complete
14436      */
14437     GCPSaveRef * const saveRef = (GCPSaveRef*)&signal->theData[0];
14438     saveRef->dihPtr = dihPtr;
14439     saveRef->nodeId = getOwnNodeId();
14440     saveRef->gci    = gci;
14441     saveRef->errorCode = GCPSaveRef::NodeRestartInProgress;
14442     sendSignal(dihBlockRef, GSN_GCP_SAVEREF, signal,
14443 	       GCPSaveRef::SignalLength, JBB);
14444     return;
14445   }
14446 
14447   ndbrequire(gci >= saveNewestCompletedGci);
14448 
14449   if (gci == saveNewestCompletedGci)
14450   {
14451 /*---------------------------------------------------------------------------*/
14452 /* GLOBAL CHECKPOINT HAVE ALREADY BEEN HANDLED. REQUEST MUST HAVE BEEN SENT  */
14453 /* FROM NEW MASTER DIH.                                                      */
14454 /*---------------------------------------------------------------------------*/
14455     if (ccurrentGcprec == RNIL) {
14456       jam();
14457 /*---------------------------------------------------------------------------*/
14458 /* THIS INDICATES THAT WE HAVE ALREADY SENT GCP_SAVECONF TO PREVIOUS MASTER. */
14459 /* WE SIMPLY SEND IT ALSO TO THE NEW MASTER.                                 */
14460 /*---------------------------------------------------------------------------*/
14461       GCPSaveConf * const saveConf = (GCPSaveConf*)&signal->theData[0];
14462       saveConf->dihPtr = dihPtr;
14463       saveConf->nodeId = getOwnNodeId();
14464       saveConf->gci    = cnewestCompletedGci;
14465       sendSignal(dihBlockRef, GSN_GCP_SAVECONF, signal,
14466 		 GCPSaveConf::SignalLength, JBA);
14467       return;
14468     }
14469     jam();
14470 /*---------------------------------------------------------------------------*/
14471 /* WE HAVE NOT YET SENT THE RESPONSE TO THE OLD MASTER. WE WILL SET THE NEW  */
14472 /* RECEIVER OF THE RESPONSE AND THEN EXIT SINCE THE PROCESS IS ALREADY       */
14473 /* STARTED.                                                                  */
14474 /*---------------------------------------------------------------------------*/
14475     gcpPtr.i = ccurrentGcprec;
14476     ptrCheckGuard(gcpPtr, cgcprecFileSize, gcpRecord);
14477     gcpPtr.p->gcpUserptr = dihPtr;
14478     gcpPtr.p->gcpBlockref = dihBlockRef;
14479     return;
14480   }//if
14481 
14482   ndbrequire(ccurrentGcprec == RNIL);
14483   cnewestCompletedGci = gci;
14484   if (gci > cnewestGci) {
14485     jam();
14486     cnewestGci = gci;
14487   }//if
14488 
14489   if(cstartRecReq < SRR_FIRST_LCP_DONE)
14490   {
14491     /**
14492      * First LCP has not been done
14493      */
14494     GCPSaveRef * const saveRef = (GCPSaveRef*)&signal->theData[0];
14495     saveRef->dihPtr = dihPtr;
14496     saveRef->nodeId = getOwnNodeId();
14497     saveRef->gci    = gci;
14498     saveRef->errorCode = GCPSaveRef::NodeRestartInProgress;
14499     sendSignal(dihBlockRef, GSN_GCP_SAVEREF, signal,
14500 	       GCPSaveRef::SignalLength, JBB);
14501 
14502     if (ERROR_INSERTED(5052))
14503     {
14504       jam();
14505       signal->theData[0] = 9999;
14506       sendSignalWithDelay(CMVMI_REF, GSN_NDB_TAMPER, signal, 300, 1);
14507     }
14508     return;
14509   }
14510 
14511   CRASH_INSERTION(5052);
14512 
14513 #ifdef GCP_TIMER_HACK
14514   NdbTick_getMicroTimer(&globalData.gcp_timer_save[0]);
14515 #endif
14516 
14517   ccurrentGcprec = 0;
14518   gcpPtr.i = ccurrentGcprec;
14519   ptrCheckGuard(gcpPtr, cgcprecFileSize, gcpRecord);
14520 
14521   gcpPtr.p->gcpBlockref = dihBlockRef;
14522   gcpPtr.p->gcpUserptr = dihPtr;
14523   gcpPtr.p->gcpId = gci;
14524   bool tlogActive = false;
14525   for (logPartPtr.i = 0; logPartPtr.i < clogPartFileSize; logPartPtr.i++) {
14526     ptrAss(logPartPtr, logPartRecord);
14527     if (logPartPtr.p->logPartState == LogPartRecord::ACTIVE) {
14528       jam();
14529       logPartPtr.p->waitWriteGciLog = LogPartRecord::WWGL_TRUE;
14530       tlogActive = true;
14531       if (logPartPtr.p->LogLqhKeyReqSent == ZFALSE)
14532       {
14533         jam();
14534         logPartPtr.p->LogLqhKeyReqSent = ZTRUE;
14535         signal->theData[0] = ZLOG_LQHKEYREQ;
14536         signal->theData[1] = logPartPtr.i;
14537         sendSignal(cownref, GSN_CONTINUEB, signal, 2, JBB);
14538       }
14539     } else {
14540       jam();
14541       logPartPtr.p->waitWriteGciLog = LogPartRecord::WWGL_FALSE;
14542       logFilePtr.i = logPartPtr.p->currentLogfile;
14543       ptrCheckGuard(logFilePtr, clogFileFileSize, logFileRecord);
14544       logPagePtr.i = logFilePtr.p->currentLogpage;
14545       ptrCheckGuard(logPagePtr, clogPageFileSize, logPageRecord);
14546       writeCompletedGciLog(signal);
14547     }//if
14548   }//for
14549   if (tlogActive == true) {
14550     jam();
14551     return;
14552   }//if
14553   initGcpRecLab(signal);
14554   startTimeSupervision(signal);
14555   return;
14556 }//Dblqh::execGCP_SAVEREQ()
14557 
14558 /**
14559  * This is needed for ndbmtd to serialize
14560  * SUB_GCP_COMPLETE_REP vs FIRE_TRIG_ORD
14561  */
14562 void
execSUB_GCP_COMPLETE_REP(Signal * signal)14563 Dblqh::execSUB_GCP_COMPLETE_REP(Signal* signal)
14564 {
14565   jamEntry();
14566   Uint32 len = signal->getLength();
14567   EXECUTE_DIRECT(DBTUP, GSN_SUB_GCP_COMPLETE_REP, signal, len);
14568   sendSignal(SUMA_REF, GSN_SUB_GCP_COMPLETE_REP, signal, len, JBB);
14569 }
14570 
14571 /* ------------------------------------------------------------------------- */
14572 /*  START TIME SUPERVISION OF THE LOG PARTS.                                 */
14573 /* ------------------------------------------------------------------------- */
startTimeSupervision(Signal * signal)14574 void Dblqh::startTimeSupervision(Signal* signal)
14575 {
14576   for (logPartPtr.i = 0; logPartPtr.i < clogPartFileSize; logPartPtr.i++) {
14577     jam();
14578     ptrAss(logPartPtr, logPartRecord);
14579 /* +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ */
14580 /* WE HAVE TO START CHECKING IF THE LOG IS TO BE WRITTEN EVEN IF PAGES ARE   */
14581 /* FULL. INITIALISE THE VALUES OF WHERE WE ARE IN THE LOG CURRENTLY.         */
14582 /* +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ */
14583     logPartPtr.p->logPartTimer = 0;
14584     logPartPtr.p->logTimer = 1;
14585     signal->theData[0] = ZTIME_SUPERVISION;
14586     signal->theData[1] = logPartPtr.i;
14587     sendSignal(cownref, GSN_CONTINUEB, signal, 2, JBB);
14588   }//for
14589 }//Dblqh::startTimeSupervision()
14590 
14591 /*---------------------------------------------------------------------------*/
14592 /* WE SET THE GLOBAL CHECKPOINT VARIABLES AFTER WRITING THE COMPLETED GCI LOG*/
14593 /* RECORD. THIS ENSURES THAT WE WILL ENCOUNTER THE COMPLETED GCI RECORD WHEN */
14594 /* WE EXECUTE THE FRAGMENT LOG.                                              */
14595 /*---------------------------------------------------------------------------*/
initGcpRecLab(Signal * signal)14596 void Dblqh::initGcpRecLab(Signal* signal)
14597 {
14598 /* ======================================================================== */
14599 /* =======               INITIATE GCP RECORD                        ======= */
14600 /*                                                                          */
14601 /*       SUBROUTINE SHORT NAME = IGR                                        */
14602 /* ======================================================================== */
14603   for (logPartPtr.i = 0; logPartPtr.i < clogPartFileSize; logPartPtr.i++) {
14604     jam();
14605     ptrAss(logPartPtr, logPartRecord);
14606 /*--------------------------------------------------*/
14607 /*       BY SETTING THE GCPREC = 0 WE START THE     */
14608 /*       CHECKING BY CHECK_GCP_COMPLETED. THIS      */
14609 /*       CHECKING MUST NOT BE STARTED UNTIL WE HAVE */
14610 /*       INSERTED ALL COMPLETE GCI LOG RECORDS IN   */
14611 /*       ALL LOG PARTS.                             */
14612 /*--------------------------------------------------*/
14613     logPartPtr.p->gcprec = 0;
14614     gcpPtr.p->gcpLogPartState[logPartPtr.i] = ZWAIT_DISK;
14615     gcpPtr.p->gcpSyncReady[logPartPtr.i] = ZFALSE;
14616     logFilePtr.i = logPartPtr.p->currentLogfile;
14617     ptrCheckGuard(logFilePtr, clogFileFileSize, logFileRecord);
14618     gcpPtr.p->gcpFilePtr[logPartPtr.i] = logFilePtr.i;
14619     logPagePtr.i = logFilePtr.p->currentLogpage;
14620     ptrCheckGuard(logPagePtr, clogPageFileSize, logPageRecord);
14621     if (logPagePtr.p->logPageWord[ZCURR_PAGE_INDEX] == ZPAGE_HEADER_SIZE) {
14622       jam();
14623 /*--------------------------------------------------*/
14624 /*       SINCE THE CURRENT FILEPAGE POINTS AT THE   */
14625 /*       NEXT WORD TO BE WRITTEN WE HAVE TO ADJUST  */
14626 /*       FOR THIS BY DECREASING THE FILE PAGE BY ONE*/
14627 /*       IF NO WORD HAS BEEN WRITTEN ON THE CURRENT */
14628 /*       FILEPAGE.                                  */
14629 /*--------------------------------------------------*/
14630       gcpPtr.p->gcpPageNo[logPartPtr.i] = logFilePtr.p->currentFilepage - 1;
14631       gcpPtr.p->gcpWordNo[logPartPtr.i] = ZPAGE_SIZE - 1;
14632     } else {
14633       jam();
14634       gcpPtr.p->gcpPageNo[logPartPtr.i] = logFilePtr.p->currentFilepage;
14635       gcpPtr.p->gcpWordNo[logPartPtr.i] =
14636 	logPagePtr.p->logPageWord[ZCURR_PAGE_INDEX] - 1;
14637     }//if
14638   }//for
14639   // initialize un-used part
14640   Uint32 Ti;
14641   for (Ti = clogPartFileSize; Ti < ZLOG_PART_FILE_SIZE; Ti++) {
14642     gcpPtr.p->gcpFilePtr[Ti] = ZNIL;
14643     gcpPtr.p->gcpPageNo[Ti] = ZNIL;
14644     gcpPtr.p->gcpSyncReady[Ti] = FALSE;
14645     gcpPtr.p->gcpWordNo[Ti] = ZNIL;
14646   }
14647   return;
14648 }//Dblqh::initGcpRecLab()
14649 
14650 /* ========================================================================= */
14651 /* ==== CHECK IF ANY GLOBAL CHECKPOINTS ARE COMPLETED AFTER A COMPLETED===== */
14652 /*      DISK WRITE.                                                          */
14653 /*                                                                           */
14654 /*       SUBROUTINE SHORT NAME = CGC                                         */
14655 /* return: true if gcp was completed */
14656 /* ========================================================================= */
14657 bool
checkGcpCompleted(Signal * signal,Uint32 tcgcPageWritten,Uint32 tcgcWordWritten)14658 Dblqh::checkGcpCompleted(Signal* signal,
14659                          Uint32 tcgcPageWritten,
14660                          Uint32 tcgcWordWritten)
14661 {
14662   UintR tcgcFlag;
14663   UintR tcgcJ;
14664 
14665   gcpPtr.i = logPartPtr.p->gcprec;
14666   if (gcpPtr.i != RNIL)
14667   {
14668     jam();
14669 /* ------------------------------------------------------------------------- */
14670 /* IF THE GLOBAL CHECKPOINT IS NOT WAITING FOR COMPLETION THEN WE CAN QUIT   */
14671 /* THE SEARCH IMMEDIATELY.                                                   */
14672 /* ------------------------------------------------------------------------- */
14673     ptrCheckGuard(gcpPtr, cgcprecFileSize, gcpRecord);
14674     if (gcpPtr.p->gcpFilePtr[logPartPtr.i] == logFilePtr.i) {
14675 /* ------------------------------------------------------------------------- */
14676 /* IF THE COMPLETED DISK OPERATION WAS ON ANOTHER FILE THAN THE ONE WE ARE   */
14677 /* WAITING FOR, THEN WE CAN ALSO QUIT THE SEARCH IMMEDIATELY.                */
14678 /* ------------------------------------------------------------------------- */
14679       if (tcgcPageWritten < gcpPtr.p->gcpPageNo[logPartPtr.i]) {
14680         jam();
14681 /* ------------------------------------------------------------------------- */
14682 /* THIS LOG PART HAVE NOT YET WRITTEN THE GLOBAL CHECKPOINT TO DISK.         */
14683 /* ------------------------------------------------------------------------- */
14684         return false;
14685       } else {
14686         if (tcgcPageWritten == gcpPtr.p->gcpPageNo[logPartPtr.i]) {
14687           if (tcgcWordWritten < gcpPtr.p->gcpWordNo[logPartPtr.i]) {
14688             jam();
14689 /* ------------------------------------------------------------------------- */
14690 /* THIS LOG PART HAVE NOT YET WRITTEN THE GLOBAL CHECKPOINT TO DISK.         */
14691 /* ------------------------------------------------------------------------- */
14692             return false;
14693           }//if
14694         }//if
14695       }//if
14696 /* ------------------------------------------------------------------------- */
14697 /* THIS LOG PART HAVE WRITTEN THE GLOBAL CHECKPOINT TO DISK.                 */
14698 /* ------------------------------------------------------------------------- */
14699       logPartPtr.p->gcprec = RNIL;
14700       gcpPtr.p->gcpLogPartState[logPartPtr.i] = ZON_DISK;
14701       tcgcFlag = ZTRUE;
14702       for (tcgcJ = 0; tcgcJ < clogPartFileSize; tcgcJ++)
14703       {
14704         jam();
14705         if (gcpPtr.p->gcpLogPartState[tcgcJ] != ZON_DISK) {
14706           jam();
14707 /* ------------------------------------------------------------------------- */
14708 /*ALL LOG PARTS HAVE NOT SAVED THIS GLOBAL CHECKPOINT TO DISK YET. WAIT FOR  */
14709 /*THEM TO COMPLETE.                                                          */
14710 /* ------------------------------------------------------------------------- */
14711           tcgcFlag = ZFALSE;
14712         }//if
14713       }//for
14714       if (tcgcFlag == ZFALSE)
14715       {
14716         return false;
14717       }
14718 
14719       if (tcgcFlag == ZTRUE)
14720       {
14721         jam();
14722 /* ------------------------------------------------------------------------- */
14723 /*WE HAVE FOUND A COMPLETED GLOBAL CHECKPOINT OPERATION. WE NOW NEED TO SEND */
14724 /*GCP_SAVECONF, REMOVE THE GCP RECORD FROM THE LIST OF WAITING GCP RECORDS   */
14725 /*ON THIS LOG PART AND RELEASE THE GCP RECORD.                               */
14726 // After changing the log implementation we need to perform a FSSYNCREQ on all
14727 // log files where the last log word resided first before proceeding.
14728 /* ------------------------------------------------------------------------- */
14729         UintR Ti;
14730         for (Ti = 0; Ti < clogPartFileSize; Ti++) {
14731           LogFileRecordPtr loopLogFilePtr;
14732           loopLogFilePtr.i = gcpPtr.p->gcpFilePtr[Ti];
14733           ptrCheckGuard(loopLogFilePtr, clogFileFileSize, logFileRecord);
14734           if (loopLogFilePtr.p->logFileStatus == LogFileRecord::OPEN) {
14735             jam();
14736             signal->theData[0] = loopLogFilePtr.p->fileRef;
14737             signal->theData[1] = cownref;
14738             signal->theData[2] = gcpPtr.p->gcpFilePtr[Ti];
14739             sendSignal(NDBFS_REF, GSN_FSSYNCREQ, signal, 3, JBA);
14740           } else {
14741             ndbrequire((loopLogFilePtr.p->logFileStatus ==
14742                         LogFileRecord::CLOSED) ||
14743                         (loopLogFilePtr.p->logFileStatus ==
14744                          LogFileRecord::CLOSING_WRITE_LOG) ||
14745                         (loopLogFilePtr.p->logFileStatus ==
14746                          LogFileRecord::OPENING_WRITE_LOG));
14747             signal->theData[0] = loopLogFilePtr.i;
14748             execFSSYNCCONF(signal);
14749           }//if
14750         }//for
14751       }//if
14752     }//if
14753     return true;
14754   }//if
14755   return false;
14756 }//Dblqh::checkGcpCompleted()
14757 
14758 void
execFSSYNCCONF(Signal * signal)14759 Dblqh::execFSSYNCCONF(Signal* signal)
14760 {
14761   GcpRecordPtr localGcpPtr;
14762   LogFileRecordPtr localLogFilePtr;
14763   LogPartRecordPtr localLogPartPtr;
14764   localLogFilePtr.i = signal->theData[0];
14765   ptrCheckGuard(localLogFilePtr, clogFileFileSize, logFileRecord);
14766   localLogPartPtr.i = localLogFilePtr.p->logPartRec;
14767   ptrCheckGuard(localLogPartPtr, clogPartFileSize, logPartRecord);
14768   localGcpPtr.i = ccurrentGcprec;
14769   ptrCheckGuard(localGcpPtr, cgcprecFileSize, gcpRecord);
14770   localGcpPtr.p->gcpSyncReady[localLogPartPtr.i] = ZTRUE;
14771   UintR Ti;
14772 
14773   if (DEBUG_REDO)
14774   {
14775     ndbout_c("part: %u file: %u gci: %u SYNC CONF",
14776              localLogPartPtr.p->logPartNo,
14777              localLogFilePtr.p->fileNo,
14778              localGcpPtr.p->gcpId);
14779   }
14780   for (Ti = 0; Ti < clogPartFileSize; Ti++) {
14781     jam();
14782     if (localGcpPtr.p->gcpSyncReady[Ti] == ZFALSE) {
14783       jam();
14784       return;
14785     }//if
14786   }//for
14787 
14788 #ifdef GCP_TIMER_HACK
14789   NdbTick_getMicroTimer(&globalData.gcp_timer_save[1]);
14790 #endif
14791 
14792   GCPSaveConf * const saveConf = (GCPSaveConf *)&signal->theData[0];
14793   saveConf->dihPtr = localGcpPtr.p->gcpUserptr;
14794   saveConf->nodeId = getOwnNodeId();
14795   saveConf->gci    = localGcpPtr.p->gcpId;
14796   sendSignal(localGcpPtr.p->gcpBlockref, GSN_GCP_SAVECONF, signal,
14797 	     GCPSaveConf::SignalLength, JBA);
14798   ccurrentGcprec = RNIL;
14799 }//Dblqh::execFSSYNCCONF()
14800 
14801 
14802 /* ######################################################################### */
14803 /* #######                            FILE HANDLING MODULE           ####### */
14804 /*                                                                           */
14805 /* ######################################################################### */
14806 /*       THIS MODULE HANDLES RESPONSE MESSAGES FROM THE FILE SYSTEM          */
14807 /* ######################################################################### */
14808 /* ######################################################################### */
14809 /*       SIGNAL RECEPTION MODULE                                             */
14810 /*       THIS MODULE IS A SUB-MODULE OF THE FILE SYSTEM HANDLING.            */
14811 /*                                                                           */
14812 /*  THIS MODULE CHECKS THE STATE AND JUMPS TO THE PROPER PART OF THE FILE    */
14813 /*  HANDLING MODULE.                                                         */
14814 /* ######################################################################### */
14815 /* *************** */
14816 /*  FSCLOSECONF  > */
14817 /* *************** */
execFSCLOSECONF(Signal * signal)14818 void Dblqh::execFSCLOSECONF(Signal* signal)
14819 {
14820   jamEntry();
14821   logFilePtr.i = signal->theData[0];
14822   ptrCheckGuard(logFilePtr, clogFileFileSize, logFileRecord);
14823   logFilePtr.p->fileRef = RNIL;
14824 
14825   if (DEBUG_REDO)
14826   {
14827     logPartPtr.i = logFilePtr.p->logPartRec;
14828     ptrCheckGuard(logPartPtr, clogPartFileSize, logPartRecord);
14829     ndbout_c("part: %u file: %u CLOSE CONF",
14830              logPartPtr.p->logPartNo,
14831              logFilePtr.p->fileNo);
14832   }
14833 
14834   switch (logFilePtr.p->logFileStatus) {
14835   case LogFileRecord::CLOSE_SR_READ_INVALIDATE_PAGES:
14836     jam();
14837     logFilePtr.p->logFileStatus = LogFileRecord::CLOSED;
14838 
14839     logPartPtr.i = logFilePtr.p->logPartRec;
14840     ptrCheckGuard(logPartPtr, clogPartFileSize, logPartRecord);
14841 
14842     readFileInInvalidate(signal, 2);
14843     return;
14844 
14845   case LogFileRecord::CLOSE_SR_READ_INVALIDATE_SEARCH_FILES:
14846     jam();
14847     logFilePtr.p->logFileStatus = LogFileRecord::CLOSED;
14848 
14849     logPartPtr.i = logFilePtr.p->logPartRec;
14850     ptrCheckGuard(logPartPtr, clogPartFileSize, logPartRecord);
14851 
14852     readFileInInvalidate(signal, 4);
14853     return;
14854   case LogFileRecord::CLOSE_SR_READ_INVALIDATE_SEARCH_LAST_FILE:
14855     logFilePtr.p->logFileStatus = LogFileRecord::CLOSED;
14856 
14857     logPartPtr.i = logFilePtr.p->logPartRec;
14858     ptrCheckGuard(logPartPtr, clogPartFileSize, logPartRecord);
14859 
14860     readFileInInvalidate(signal, 7);
14861     return;
14862   case LogFileRecord::CLOSE_SR_WRITE_INVALIDATE_PAGES:
14863     jam();
14864     logFilePtr.p->logFileStatus = LogFileRecord::CLOSED;
14865 
14866     logPartPtr.i = logFilePtr.p->logPartRec;
14867     ptrCheckGuard(logPartPtr, clogPartFileSize, logPartRecord);
14868 
14869     writeFileInInvalidate(signal, 1);
14870     return;
14871   case LogFileRecord::CLOSING_INIT:
14872     jam();
14873     logFileInitDone++ ;
14874     closingInitLab(signal);
14875     return;
14876   case LogFileRecord::CLOSING_SR:
14877     jam();
14878     closingSrLab(signal);
14879     return;
14880   case LogFileRecord::CLOSING_EXEC_SR:
14881     jam();
14882     closeExecSrLab(signal);
14883     return;
14884   case LogFileRecord::CLOSING_EXEC_SR_COMPLETED:
14885     jam();
14886     closeExecSrCompletedLab(signal);
14887     return;
14888   case LogFileRecord::CLOSING_WRITE_LOG:
14889     jam();
14890     closeWriteLogLab(signal);
14891     return;
14892   case LogFileRecord::CLOSING_EXEC_LOG:
14893     jam();
14894     closeExecLogLab(signal);
14895     return;
14896 #ifndef NO_REDO_OPEN_FILE_CACHE
14897   case LogFileRecord::CLOSING_EXEC_LOG_CACHED:
14898     jam();
14899     logFilePtr.p->logFileStatus = LogFileRecord::CLOSED;
14900     release(signal, m_redo_open_file_cache);
14901     return;
14902 #endif
14903   default:
14904     jam();
14905     systemErrorLab(signal, __LINE__);
14906     return;
14907   }//switch
14908 }//Dblqh::execFSCLOSECONF()
14909 
14910 
14911 /* ************>> */
14912 /*  FSOPENCONF  > */
14913 /* ************>> */
execFSOPENCONF(Signal * signal)14914 void Dblqh::execFSOPENCONF(Signal* signal)
14915 {
14916   jamEntry();
14917   initFsopenconf(signal);
14918   switch (logFilePtr.p->logFileStatus) {
14919   case LogFileRecord::OPEN_SR_READ_INVALIDATE_PAGES:
14920     jam();
14921     logFilePtr.p->logFileStatus = LogFileRecord::OPEN;
14922     readFileInInvalidate(signal, 0);
14923     return;
14924   case LogFileRecord::OPEN_SR_READ_INVALIDATE_SEARCH_FILES:
14925     jam();
14926     logFilePtr.p->logFileStatus = LogFileRecord::OPEN;
14927     readFileInInvalidate(signal, 5);
14928     return;
14929   case LogFileRecord::OPEN_SR_WRITE_INVALIDATE_PAGES:
14930     jam();
14931     logFilePtr.p->logFileStatus = LogFileRecord::OPEN;
14932     writeFileInInvalidate(signal, 0);
14933     return;
14934   case LogFileRecord::OPENING_INIT:
14935     jam();
14936     logFilePtr.p->logFileStatus = LogFileRecord::OPEN;
14937     openFileInitLab(signal);
14938     return;
14939   case LogFileRecord::OPEN_SR_FRONTPAGE:
14940     jam();
14941     logFilePtr.p->logFileStatus = LogFileRecord::OPEN;
14942     openSrFrontpageLab(signal);
14943     return;
14944   case LogFileRecord::OPEN_SR_LAST_FILE:
14945     jam();
14946     logFilePtr.p->logFileStatus = LogFileRecord::OPEN;
14947     openSrLastFileLab(signal);
14948     return;
14949   case LogFileRecord::OPEN_SR_NEXT_FILE:
14950     jam();
14951     logFilePtr.p->logFileStatus = LogFileRecord::OPEN;
14952     openSrNextFileLab(signal);
14953     return;
14954   case LogFileRecord::OPEN_EXEC_SR_START:
14955     jam();
14956     logFilePtr.p->logFileStatus = LogFileRecord::OPEN;
14957     openExecSrStartLab(signal);
14958     return;
14959   case LogFileRecord::OPEN_EXEC_SR_NEW_MBYTE:
14960     jam();
14961     logFilePtr.p->logFileStatus = LogFileRecord::OPEN;
14962     openExecSrNewMbyteLab(signal);
14963     return;
14964   case LogFileRecord::OPEN_SR_FOURTH_PHASE:
14965     jam();
14966     logFilePtr.p->logFileStatus = LogFileRecord::OPEN;
14967     openSrFourthPhaseLab(signal);
14968     return;
14969   case LogFileRecord::OPEN_SR_FOURTH_NEXT:
14970     jam();
14971     logFilePtr.p->logFileStatus = LogFileRecord::OPEN;
14972     openSrFourthNextLab(signal);
14973     return;
14974   case LogFileRecord::OPEN_SR_FOURTH_ZERO:
14975     jam();
14976     logFilePtr.p->logFileStatus = LogFileRecord::OPEN;
14977     openSrFourthZeroLab(signal);
14978     return;
14979   case LogFileRecord::OPENING_WRITE_LOG:
14980     jam();
14981     logFilePtr.p->logFileStatus = LogFileRecord::OPEN;
14982     return;
14983   case LogFileRecord::OPEN_EXEC_LOG:
14984     jam();
14985     logFilePtr.p->logFileStatus = LogFileRecord::OPEN;
14986 #ifndef NO_REDO_OPEN_FILE_CACHE
14987     {
14988       jam();
14989       m_redo_open_file_cache.m_lru.addFirst(logFilePtr);
14990     }
14991     // Fall through
14992   case LogFileRecord::OPEN_EXEC_LOG_CACHED:
14993     jam();
14994 #endif
14995     openExecLogLab(signal);
14996     return;
14997   default:
14998     jam();
14999     systemErrorLab(signal, __LINE__);
15000     return;
15001   }//switch
15002 }//Dblqh::execFSOPENCONF()
15003 
15004 void
execFSOPENREF(Signal * signal)15005 Dblqh::execFSOPENREF(Signal* signal)
15006 {
15007   jamEntry();
15008   FsRef* ref = (FsRef*)signal->getDataPtr();
15009   Uint32 err = ref->errorCode;
15010   if (err == FsRef::fsErrInvalidFileSize)
15011   {
15012     char buf[256];
15013     BaseString::snprintf(buf, sizeof(buf),
15014                          "Invalid file size for redo logfile, "
15015                          " size only changable with --initial");
15016     progError(__LINE__,
15017               NDBD_EXIT_INVALID_CONFIG,
15018               buf);
15019     return;
15020   }
15021 
15022   SimulatedBlock::execFSOPENREF(signal);
15023 }
15024 
15025 /* ************>> */
15026 /*  FSREADCONF  > */
15027 /* ************>> */
execFSREADCONF(Signal * signal)15028 void Dblqh::execFSREADCONF(Signal* signal)
15029 {
15030   jamEntry();
15031   initFsrwconf(signal, false);
15032 
15033   switch (lfoPtr.p->lfoState) {
15034   case LogFileOperationRecord::READ_SR_LAST_MBYTE:
15035     jam();
15036     releaseLfo(signal);
15037     readSrLastMbyteLab(signal);
15038     return;
15039   case LogFileOperationRecord::READ_SR_FRONTPAGE:
15040     jam();
15041     releaseLfo(signal);
15042     readSrFrontpageLab(signal);
15043     return;
15044   case LogFileOperationRecord::READ_SR_LAST_FILE:
15045     jam();
15046     releaseLfo(signal);
15047     readSrLastFileLab(signal);
15048     return;
15049   case LogFileOperationRecord::READ_SR_NEXT_FILE:
15050     jam();
15051     releaseLfo(signal);
15052     readSrNextFileLab(signal);
15053     return;
15054   case LogFileOperationRecord::READ_EXEC_SR:
15055     jam();
15056     readExecSrLab(signal);
15057     return;
15058   case LogFileOperationRecord::READ_EXEC_LOG:
15059     jam();
15060     readExecLogLab(signal);
15061     return;
15062   case LogFileOperationRecord::READ_SR_INVALIDATE_PAGES:
15063     jam();
15064     invalidateLogAfterLastGCI(signal);
15065     return;
15066   case LogFileOperationRecord::READ_SR_INVALIDATE_SEARCH_FILES:
15067     jam();
15068     invalidateLogAfterLastGCI(signal);
15069     return;
15070   case LogFileOperationRecord::READ_SR_FOURTH_PHASE:
15071     jam();
15072     releaseLfo(signal);
15073     readSrFourthPhaseLab(signal);
15074     return;
15075   case LogFileOperationRecord::READ_SR_FOURTH_ZERO:
15076     jam();
15077     releaseLfo(signal);
15078     readSrFourthZeroLab(signal);
15079     return;
15080   default:
15081     jam();
15082     systemErrorLab(signal, __LINE__);
15083     return;
15084   }//switch
15085 }//Dblqh::execFSREADCONF()
15086 
15087 /* ************>> */
15088 /*  FSREADCONF  > */
15089 /* ************>> */
execFSREADREF(Signal * signal)15090 void Dblqh::execFSREADREF(Signal* signal)
15091 {
15092   jamEntry();
15093   lfoPtr.i = signal->theData[0];
15094   ptrCheckGuard(lfoPtr, clfoFileSize, logFileOperationRecord);
15095   switch (lfoPtr.p->lfoState) {
15096   case LogFileOperationRecord::READ_SR_LAST_MBYTE:
15097     jam();
15098     break;
15099   case LogFileOperationRecord::READ_SR_FRONTPAGE:
15100     jam();
15101     break;
15102   case LogFileOperationRecord::READ_SR_LAST_FILE:
15103     jam();
15104     break;
15105   case LogFileOperationRecord::READ_SR_NEXT_FILE:
15106     jam();
15107     break;
15108   case LogFileOperationRecord::READ_EXEC_SR:
15109     jam();
15110     break;
15111   case LogFileOperationRecord::READ_EXEC_LOG:
15112     jam();
15113     break;
15114   case LogFileOperationRecord::READ_SR_FOURTH_PHASE:
15115     jam();
15116     break;
15117   case LogFileOperationRecord::READ_SR_FOURTH_ZERO:
15118     jam();
15119     break;
15120   case LogFileOperationRecord::READ_SR_INVALIDATE_PAGES:
15121     jam();
15122     break;
15123   default:
15124     jam();
15125     break;
15126   }//switch
15127   {
15128     char msg[100];
15129     sprintf(msg, "File system read failed during LogFileOperationRecord state %d", (Uint32)lfoPtr.p->lfoState);
15130     fsRefError(signal,__LINE__,msg);
15131   }
15132 }//Dblqh::execFSREADREF()
15133 
15134 /* *************** */
15135 /*  FSWRITECONF  > */
15136 /* *************** */
execFSWRITECONF(Signal * signal)15137 void Dblqh::execFSWRITECONF(Signal* signal)
15138 {
15139   jamEntry();
15140   initFsrwconf(signal, true);
15141   switch (lfoPtr.p->lfoState) {
15142   case LogFileOperationRecord::WRITE_SR_INVALIDATE_PAGES:
15143     jam();
15144     invalidateLogAfterLastGCI(signal);
15145     CRASH_INSERTION(5047);
15146     return;
15147   case LogFileOperationRecord::WRITE_PAGE_ZERO:
15148     jam();
15149     writePageZeroLab(signal, __LINE__);
15150     releaseLfo(signal);
15151     return;
15152   case LogFileOperationRecord::LAST_WRITE_IN_FILE:
15153     jam();
15154     lastWriteInFileLab(signal);
15155     return;
15156   case LogFileOperationRecord::INIT_WRITE_AT_END:
15157     jam();
15158     initWriteEndLab(signal);
15159     return;
15160   case LogFileOperationRecord::INIT_FIRST_PAGE:
15161     jam();
15162     logMBytesInitDone++;
15163     initFirstPageLab(signal);
15164     return;
15165   case LogFileOperationRecord::WRITE_GCI_ZERO:
15166     jam();
15167     writeGciZeroLab(signal);
15168     return;
15169   case LogFileOperationRecord::WRITE_DIRTY:
15170     jam();
15171     writeDirtyLab(signal);
15172     return;
15173   case LogFileOperationRecord::WRITE_INIT_MBYTE:
15174     jam();
15175     logMBytesInitDone++;
15176     writeInitMbyteLab(signal);
15177     return;
15178   case LogFileOperationRecord::ACTIVE_WRITE_LOG:
15179     jam();
15180     writeLogfileLab(signal);
15181     return;
15182   case LogFileOperationRecord::FIRST_PAGE_WRITE_IN_LOGFILE:
15183     jam();
15184     firstPageWriteLab(signal);
15185     return;
15186   case LogFileOperationRecord::WRITE_SR_INVALIDATE_PAGES_UPDATE_PAGE0:
15187     jam();
15188     // We are done...send completed signal and exit this phase.
15189     releaseLfo(signal);
15190     signal->theData[0] = ZSR_FOURTH_COMP;
15191     signal->theData[1] = logPartPtr.i;
15192     sendSignal(cownref, GSN_CONTINUEB, signal, 2, JBB);
15193     return;
15194   default:
15195     jam();
15196     systemErrorLab(signal, __LINE__);
15197     return;
15198   }//switch
15199 }//Dblqh::execFSWRITECONF()
15200 
15201 /* ************>> */
15202 /*  FSWRITEREF  > */
15203 /* ************>> */
execFSWRITEREF(Signal * signal)15204 void Dblqh::execFSWRITEREF(Signal* signal)
15205 {
15206   jamEntry();
15207   lfoPtr.i = signal->theData[0];
15208   ptrCheckGuard(lfoPtr, clfoFileSize, logFileOperationRecord);
15209   terrorCode = signal->theData[1];
15210   switch (lfoPtr.p->lfoState) {
15211   case LogFileOperationRecord::WRITE_PAGE_ZERO:
15212     jam();
15213     break;
15214   case LogFileOperationRecord::LAST_WRITE_IN_FILE:
15215     jam();
15216     break;
15217   case LogFileOperationRecord::INIT_WRITE_AT_END:
15218     jam();
15219     break;
15220   case LogFileOperationRecord::INIT_FIRST_PAGE:
15221     jam();
15222     break;
15223   case LogFileOperationRecord::WRITE_GCI_ZERO:
15224     jam();
15225     break;
15226   case LogFileOperationRecord::WRITE_DIRTY:
15227     jam();
15228     break;
15229   case LogFileOperationRecord::WRITE_INIT_MBYTE:
15230     jam();
15231     break;
15232   case LogFileOperationRecord::ACTIVE_WRITE_LOG:
15233     jam();
15234     break;
15235   case LogFileOperationRecord::FIRST_PAGE_WRITE_IN_LOGFILE:
15236     jam();
15237     break;
15238   case LogFileOperationRecord::WRITE_SR_INVALIDATE_PAGES:
15239     jam();
15240     systemErrorLab(signal, __LINE__);
15241   default:
15242     jam();
15243     break;
15244   }//switch
15245   {
15246     char msg[100];
15247     sprintf(msg, "File system write failed during LogFileOperationRecord state %d", (Uint32)lfoPtr.p->lfoState);
15248     fsRefError(signal,__LINE__,msg);
15249   }
15250 }//Dblqh::execFSWRITEREF()
15251 
15252 
15253 /* ========================================================================= */
15254 /* =======              INITIATE WHEN RECEIVING FSOPENCONF           ======= */
15255 /*                                                                           */
15256 /* ========================================================================= */
initFsopenconf(Signal * signal)15257 void Dblqh::initFsopenconf(Signal* signal)
15258 {
15259   logFilePtr.i = signal->theData[0];
15260   ptrCheckGuard(logFilePtr, clogFileFileSize, logFileRecord);
15261   logFilePtr.p->fileRef = signal->theData[1];
15262   logPartPtr.i = logFilePtr.p->logPartRec;
15263   ptrCheckGuard(logPartPtr, clogPartFileSize, logPartRecord);
15264   logFilePtr.p->currentMbyte = 0;
15265   logFilePtr.p->filePosition = 0;
15266 }//Dblqh::initFsopenconf()
15267 
15268 /* ========================================================================= */
15269 /* =======       INITIATE WHEN RECEIVING FSREADCONF AND FSWRITECONF  ======= */
15270 /*                                                                           */
15271 /* ========================================================================= */
initFsrwconf(Signal * signal,bool write)15272 void Dblqh::initFsrwconf(Signal* signal, bool write)
15273 {
15274   LogPageRecordPtr logP;
15275   Uint32 noPages, totPages;
15276   lfoPtr.i = signal->theData[0];
15277   ptrCheckGuard(lfoPtr, clfoFileSize, logFileOperationRecord);
15278   totPages= lfoPtr.p->noPagesRw;
15279   logFilePtr.i = lfoPtr.p->logFileRec;
15280   ptrCheckGuard(logFilePtr, clogFileFileSize, logFileRecord);
15281   logPartPtr.i = logFilePtr.p->logPartRec;
15282   ptrCheckGuard(logPartPtr, clogPartFileSize, logPartRecord);
15283   logPagePtr.i = lfoPtr.p->firstLfoPage;
15284   ptrCheckGuard(logPagePtr, clogPageFileSize, logPageRecord);
15285   logP= logPagePtr;
15286   noPages= 1;
15287   ndbassert(totPages > 0);
15288 
15289   if (write)
15290   {
15291     Uint32 bytesWritten = totPages * 32768;
15292     logPartPtr.p->m_io_tracker.complete_io(bytesWritten);
15293   }
15294 
15295   for (;;)
15296   {
15297     logP.p->logPageWord[ZPOS_IN_WRITING]= 0;
15298     logP.p->logPageWord[ZPOS_IN_FREE_LIST]= 0;
15299     if (noPages == totPages)
15300       return;
15301     if (write)
15302       logP.i= logP.p->logPageWord[ZNEXT_PAGE];
15303     else
15304       logP.i= lfoPtr.p->logPageArray[noPages];
15305     ptrCheckGuard(logP, clogPageFileSize, logPageRecord);
15306     noPages++;
15307   }
15308 
15309 }//Dblqh::initFsrwconf()
15310 
15311 /* ######################################################################### */
15312 /*       NORMAL OPERATION MODULE                                             */
15313 /*       THIS MODULE IS A SUB-MODULE OF THE FILE SYSTEM HANDLING.            */
15314 /*                                                                           */
15315 /*   THIS PART HANDLES THE NORMAL OPENING, CLOSING AND WRITING OF LOG FILES  */
15316 /*   DURING NORMAL OPERATION.                                                */
15317 /* ######################################################################### */
15318 /*---------------------------------------------------------------------------*/
15319 /* THIS SIGNAL IS USED TO SUPERVISE THAT THE LOG RECORDS ARE NOT KEPT IN MAIN*/
15320 /* MEMORY FOR MORE THAN 1 SECOND TO ACHIEVE THE PROPER RELIABILITY.          */
15321 /*---------------------------------------------------------------------------*/
timeSup(Signal * signal)15322 void Dblqh::timeSup(Signal* signal)
15323 {
15324   LogPageRecordPtr origLogPagePtr;
15325   Uint32 wordWritten;
15326 
15327   jamEntry();
15328   logPartPtr.i = signal->theData[0];
15329   ptrCheckGuard(logPartPtr, clogPartFileSize, logPartRecord);
15330   logFilePtr.i = logPartPtr.p->currentLogfile;
15331   ptrCheckGuard(logFilePtr, clogFileFileSize, logFileRecord);
15332   logPagePtr.i = logFilePtr.p->currentLogpage;
15333   ptrCheckGuard(logPagePtr, clogPageFileSize, logPageRecord);
15334   if (logPartPtr.p->logPartTimer != logPartPtr.p->logTimer) {
15335     jam();
15336     if (true) // less merge conflicts
15337     {
15338 /*---------------------------------------------------------------------------*/
15339 /* IDLE AND NOT WRITTEN TO DISK IN A SECOND. ALSO WHEN WE HAVE A TAIL PROBLEM*/
15340 /* WE HAVE TO WRITE TO DISK AT TIMES. WE WILL FIRST CHECK WHETHER ANYTHING   */
15341 /* AT ALL HAVE BEEN WRITTEN TO THE PAGES BEFORE WRITING TO DISK.             */
15342 /*---------------------------------------------------------------------------*/
15343 /* WE HAVE TO WRITE TO DISK IN ALL CASES SINCE THERE COULD BE INFORMATION    */
15344 /* STILL IN THE LOG THAT WAS GENERATED BEFORE THE PREVIOUS TIME SUPERVISION  */
15345 /* BUT AFTER THE LAST DISK WRITE. THIS PREVIOUSLY STOPPED ALL DISK WRITES    */
15346 /* WHEN NO MORE LOG WRITES WERE PERFORMED (THIS HAPPENED WHEN LOG GOT FULL   */
15347 /* AND AFTER LOADING THE INITIAL RECORDS IN INITIAL START).                  */
15348 /*---------------------------------------------------------------------------*/
15349       if (((logFilePtr.p->currentFilepage + 1) & (ZPAGES_IN_MBYTE -1)) == 0) {
15350         jam();
15351 /*---------------------------------------------------------------------------*/
15352 /* THIS IS THE LAST PAGE IN THIS MBYTE. WRITE NEXT LOG AND SWITCH TO NEXT    */
15353 /* MBYTE.                                                                    */
15354 /*---------------------------------------------------------------------------*/
15355         changeMbyte(signal);
15356       } else {
15357 /*---------------------------------------------------------------------------*/
15358 /* WRITE THE LOG PAGE TO DISK EVEN IF IT IS NOT FULL. KEEP PAGE AND WRITE A  */
15359 /* COPY. THE ORIGINAL PAGE WILL BE WRITTEN AGAIN LATER ON.                   */
15360 /*---------------------------------------------------------------------------*/
15361         wordWritten = logPagePtr.p->logPageWord[ZCURR_PAGE_INDEX] - 1;
15362         origLogPagePtr.i = logPagePtr.i;
15363         origLogPagePtr.p = logPagePtr.p;
15364         seizeLogpage(signal);
15365         MEMCOPY_NO_WORDS(&logPagePtr.p->logPageWord[0],
15366                          &origLogPagePtr.p->logPageWord[0],
15367                          wordWritten + 1);
15368         ndbrequire(wordWritten < ZPAGE_SIZE);
15369         if (logFilePtr.p->noLogpagesInBuffer > 0) {
15370           jam();
15371           completedLogPage(signal, ZENFORCE_WRITE, __LINE__);
15372 /*---------------------------------------------------------------------------*/
15373 /*SINCE WE ARE ONLY WRITING PART OF THE LAST PAGE WE HAVE TO UPDATE THE WORD */
15374 /*WRITTEN TO REFLECT THE REAL LAST WORD WRITTEN. WE ALSO HAVE TO MOVE THE    */
15375 /*FILE POSITION ONE STEP BACKWARDS SINCE WE ARE NOT WRITING THE LAST PAGE    */
15376 /*COMPLETELY. IT WILL BE WRITTEN AGAIN.                                      */
15377 /*---------------------------------------------------------------------------*/
15378           lfoPtr.p->lfoWordWritten = wordWritten;
15379           logFilePtr.p->filePosition = logFilePtr.p->filePosition - 1;
15380         } else {
15381           if (wordWritten == (ZPAGE_HEADER_SIZE - 1)) {
15382 /*---------------------------------------------------------------------------*/
15383 /*THIS IS POSSIBLE BUT VERY UNLIKELY. IF THE PAGE WAS COMPLETED AFTER THE LAST*/
15384 /*WRITE TO DISK THEN NO_LOG_PAGES_IN_BUFFER > 0 AND IF NOT WRITTEN SINCE LAST*/
15385 /*WRITE TO DISK THEN THE PREVIOUS PAGE MUST HAVE BEEN WRITTEN BY SOME        */
15386 /*OPERATION AND THAT BECAME COMPLETELY FULL. IN ANY CASE WE NEED NOT WRITE AN*/
15387 /*EMPTY PAGE TO DISK.                                                        */
15388 /*---------------------------------------------------------------------------*/
15389             jam();
15390             releaseLogpage(signal);
15391           } else {
15392             jam();
15393             writeSinglePage(signal, logFilePtr.p->currentFilepage,
15394                             wordWritten, __LINE__);
15395             lfoPtr.p->lfoState = LogFileOperationRecord::ACTIVE_WRITE_LOG;
15396           }//if
15397         }//if
15398       }//if
15399     }
15400   }
15401 
15402   logPartPtr.p->logTimer++;
15403   return;
15404 }//Dblqh::timeSup()
15405 
writeLogfileLab(Signal * signal)15406 void Dblqh::writeLogfileLab(Signal* signal)
15407 {
15408 /*---------------------------------------------------------------------------*/
15409 /* CHECK IF ANY GLOBAL CHECKPOINTS ARE COMPLETED DUE TO THIS COMPLETED DISK  */
15410 /* WRITE.                                                                    */
15411 /*---------------------------------------------------------------------------*/
15412   switch (logFilePtr.p->fileChangeState) {
15413   case LogFileRecord::NOT_ONGOING:
15414     jam();
15415     checkGcpCompleted(signal,
15416                       ((lfoPtr.p->lfoPageNo + lfoPtr.p->noPagesRw) - 1),
15417                       lfoPtr.p->lfoWordWritten);
15418     break;
15419 #if 0
15420   case LogFileRecord::BOTH_WRITES_ONGOING:
15421     jam();
15422     ndbout_c("not crashing!!");
15423     // Fall-through
15424 #endif
15425   case LogFileRecord::WRITE_PAGE_ZERO_ONGOING:
15426   case LogFileRecord::LAST_WRITE_ONGOING:
15427     jam();
15428     logFilePtr.p->lastPageWritten = (lfoPtr.p->lfoPageNo + lfoPtr.p->noPagesRw) - 1;
15429     logFilePtr.p->lastWordWritten = lfoPtr.p->lfoWordWritten;
15430     break;
15431   default:
15432     jam();
15433     systemErrorLab(signal, __LINE__);
15434     return;
15435     break;
15436   }//switch
15437   releaseLfoPages(signal);
15438   releaseLfo(signal);
15439   return;
15440 }//Dblqh::writeLogfileLab()
15441 
closeWriteLogLab(Signal * signal)15442 void Dblqh::closeWriteLogLab(Signal* signal)
15443 {
15444   logFilePtr.p->logFileStatus = LogFileRecord::CLOSED;
15445   return;
15446 }//Dblqh::closeWriteLogLab()
15447 
15448 /* ######################################################################### */
15449 /*       FILE CHANGE MODULE                                                  */
15450 /*       THIS MODULE IS A SUB-MODULE OF THE FILE SYSTEM HANDLING.            */
15451 /*                                                                           */
15452 /*THIS PART OF THE FILE MODULE HANDLES WHEN WE ARE CHANGING LOG FILE DURING  */
15453 /*NORMAL OPERATION. WE HAVE TO BE CAREFUL WHEN WE ARE CHANGING LOG FILE SO   */
15454 /*THAT WE DO NOT COMPLICATE THE SYSTEM RESTART PROCESS TOO MUCH.             */
15455 /*THE IDEA IS THAT WE START BY WRITING THE LAST WRITE IN THE OLD FILE AND WE */
15456 /*ALSO WRITE THE FIRST PAGE OF THE NEW FILE CONCURRENT WITH THAT. THIS FIRST */
15457 /*PAGE IN THE NEW FILE DO NOT CONTAIN ANY LOG RECORDS OTHER THAN A DESCRIPTOR*/
15458 /*CONTAINING INFORMATION ABOUT GCI'S NEEDED AT SYSTEM RESTART AND A NEXT LOG */
15459 /*RECORD.                                                                    */
15460 /*                                                                           */
15461 /*WHEN BOTH OF THOSE WRITES HAVE COMPLETED WE ALSO WRITE PAGE ZERO IN FILE   */
15462 /*ZERO. THE ONLY INFORMATION WHICH IS INTERESTING HERE IS THE NEW FILE NUMBER*/
15463 /*                                                                           */
15464 /*IF OPTIMISATIONS ARE NEEDED OF THE LOG HANDLING THEN IT IS POSSIBLE TO     */
15465 /*AVOID WRITING THE FIRST PAGE OF THE NEW PAGE IMMEDIATELY. THIS COMPLICATES */
15466 /*THE SYSTEM RESTART AND ONE HAS TO TAKE SPECIAL CARE WITH FILE ZERO. IT IS  */
15467 /*HOWEVER NO LARGE PROBLEM TO CHANGE INTO THIS SCENARIO. TO AVOID ALSO THE   */
15468 /*WRITING OF PAGE ZERO IS ALSO POSSIBLE BUT COMPLICATES THE DESIGN EVEN      */
15469 /*FURTHER. IT GETS FAIRLY COMPLEX TO FIND THE END OF THE LOG. SOME SORT OF   */
15470 /*BINARY SEARCH IS HOWEVER MOST LIKELY A GOOD METHODOLOGY FOR THIS.          */
15471 /* ######################################################################### */
firstPageWriteLab(Signal * signal)15472 void Dblqh::firstPageWriteLab(Signal* signal)
15473 {
15474   releaseLfo(signal);
15475 /*---------------------------------------------------------------------------*/
15476 /*       RELEASE PAGE ZERO IF THE FILE IS NOT FILE 0.                        */
15477 /*---------------------------------------------------------------------------*/
15478   Uint32 fileNo = logFilePtr.p->fileNo;
15479   if (fileNo != 0) {
15480     jam();
15481     releaseLogpage(signal);
15482   }//if
15483 /*---------------------------------------------------------------------------*/
15484 /* IF A NEW FILE HAS BEEN OPENED WE SHALL ALWAYS ALSO WRITE TO PAGE O IN     */
15485 /* FILE 0. THE AIM IS TO MAKE RESTARTS EASIER BY SPECIFYING WHICH IS THE     */
15486 /* LAST FILE WHERE LOGGING HAS STARTED.                                      */
15487 /*---------------------------------------------------------------------------*/
15488 /* FIRST CHECK WHETHER THE LAST WRITE IN THE PREVIOUS FILE HAVE COMPLETED    */
15489 /*---------------------------------------------------------------------------*/
15490   if (logFilePtr.p->fileChangeState == LogFileRecord::BOTH_WRITES_ONGOING) {
15491     jam();
15492 /*---------------------------------------------------------------------------*/
15493 /* THE LAST WRITE WAS STILL ONGOING.                                         */
15494 /*---------------------------------------------------------------------------*/
15495     logFilePtr.p->fileChangeState = LogFileRecord::LAST_WRITE_ONGOING;
15496     return;
15497   } else {
15498     jam();
15499     ndbrequire(logFilePtr.p->fileChangeState == LogFileRecord::FIRST_WRITE_ONGOING);
15500 /*---------------------------------------------------------------------------*/
15501 /* WRITE TO PAGE 0 IN IN FILE 0 NOW.                                         */
15502 /*---------------------------------------------------------------------------*/
15503     logFilePtr.p->fileChangeState = LogFileRecord::WRITE_PAGE_ZERO_ONGOING;
15504     if (fileNo == 0) {
15505       jam();
15506 /*---------------------------------------------------------------------------*/
15507 /* IF THE NEW FILE WAS 0 THEN WE HAVE ALREADY WRITTEN PAGE ZERO IN FILE 0.   */
15508 /*---------------------------------------------------------------------------*/
15509       // use writePageZeroLab to make sure that same code as normal is run
15510       writePageZeroLab(signal, __LINE__);
15511       return;
15512     } else {
15513       jam();
15514 /*---------------------------------------------------------------------------*/
15515 /* WRITE PAGE ZERO IN FILE ZERO. LOG_FILE_REC WILL REFER TO THE LOG FILE WE  */
15516 /* HAVE JUST WRITTEN PAGE ZERO IN TO GET HOLD OF LOG_FILE_PTR FOR THIS       */
15517 /* RECORD QUICKLY. THIS IS NEEDED TO GET HOLD OF THE FILE_CHANGE_STATE.      */
15518 /* THE ONLY INFORMATION WE WANT TO CHANGE IS THE LAST FILE NUMBER IN THE     */
15519 /* FILE DESCRIPTOR. THIS IS USED AT SYSTEM RESTART TO FIND THE END OF THE    */
15520 /* LOG PART.                                                                 */
15521 /*---------------------------------------------------------------------------*/
15522       Uint32 currLogFile = logFilePtr.i;
15523       logFilePtr.i = logPartPtr.p->firstLogfile;
15524       ptrCheckGuard(logFilePtr, clogFileFileSize, logFileRecord);
15525       logPagePtr.i = logFilePtr.p->logPageZero;
15526       ptrCheckGuard(logPagePtr, clogPageFileSize, logPageRecord);
15527       logPagePtr.p->logPageWord[ZPAGE_HEADER_SIZE + ZPOS_FILE_NO] = fileNo;
15528       writeSinglePage(signal, 0, ZPAGE_SIZE - 1, __LINE__);
15529       lfoPtr.p->logFileRec = currLogFile;
15530       lfoPtr.p->lfoState = LogFileOperationRecord::WRITE_PAGE_ZERO;
15531       return;
15532     }//if
15533   }//if
15534 }//Dblqh::firstPageWriteLab()
15535 
lastWriteInFileLab(Signal * signal)15536 void Dblqh::lastWriteInFileLab(Signal* signal)
15537 {
15538   LogFileRecordPtr locLogFilePtr;
15539 /*---------------------------------------------------------------------------*/
15540 /* CHECK IF ANY GLOBAL CHECKPOINTS ARE COMPLETED DUE TO THIS COMPLETED DISK  */
15541 /* WRITE.                                                                    */
15542 /*---------------------------------------------------------------------------*/
15543   checkGcpCompleted(signal,
15544                     ((lfoPtr.p->lfoPageNo + lfoPtr.p->noPagesRw) - 1),
15545                     (ZPAGE_SIZE - 1));
15546   releaseLfoPages(signal);
15547   releaseLfo(signal);
15548 /*---------------------------------------------------------------------------*/
15549 /* IF THE FILE IS NOT IN USE OR THE NEXT FILE TO BE USED WE WILL CLOSE IT.   */
15550 /*---------------------------------------------------------------------------*/
15551   locLogFilePtr.i = logPartPtr.p->currentLogfile;
15552   ptrCheckGuard(locLogFilePtr, clogFileFileSize, logFileRecord);
15553   if (logFilePtr.i != locLogFilePtr.i) {
15554     if (logFilePtr.i != locLogFilePtr.p->nextLogFile) {
15555       if (logFilePtr.p->fileNo != 0) {
15556         jam();
15557 /*---------------------------------------------------------------------------*/
15558 /* THE FILE IS NOT FILE ZERO EITHER. WE WILL NOT CLOSE FILE ZERO SINCE WE    */
15559 /* USE IT TO KEEP TRACK OF THE CURRENT LOG FILE BY WRITING PAGE ZERO IN      */
15560 /* FILE ZERO.                                                                */
15561 /*---------------------------------------------------------------------------*/
15562 /* WE WILL CLOSE THE FILE.                                                   */
15563 /*---------------------------------------------------------------------------*/
15564         logFilePtr.p->logFileStatus = LogFileRecord::CLOSING_WRITE_LOG;
15565         closeFile(signal, logFilePtr, __LINE__);
15566       }//if
15567     }//if
15568   }//if
15569 /*---------------------------------------------------------------------------*/
15570 /* IF A NEW FILE HAS BEEN OPENED WE SHALL ALWAYS ALSO WRITE TO PAGE O IN     */
15571 /* FILE 0. THE AIM IS TO MAKE RESTARTS EASIER BY SPECIFYING WHICH IS THE     */
15572 /* LAST FILE WHERE LOGGING HAS STARTED.                                      */
15573 /*---------------------------------------------------------------------------*/
15574 /* FIRST CHECK WHETHER THE FIRST WRITE IN THE NEW FILE HAVE COMPLETED        */
15575 /* THIS STATE INFORMATION IS IN THE NEW LOG FILE AND THUS WE HAVE TO MOVE    */
15576 /* THE LOG FILE POINTER TO THIS LOG FILE.                                    */
15577 /*---------------------------------------------------------------------------*/
15578   logFilePtr.i = logFilePtr.p->nextLogFile;
15579   ptrCheckGuard(logFilePtr, clogFileFileSize, logFileRecord);
15580   if (logFilePtr.p->fileChangeState == LogFileRecord::BOTH_WRITES_ONGOING) {
15581     jam();
15582 /*---------------------------------------------------------------------------*/
15583 /* THE FIRST WRITE WAS STILL ONGOING.                                        */
15584 /*---------------------------------------------------------------------------*/
15585     logFilePtr.p->fileChangeState = LogFileRecord::FIRST_WRITE_ONGOING;
15586     return;
15587   } else {
15588     ndbrequire(logFilePtr.p->fileChangeState == LogFileRecord::LAST_WRITE_ONGOING);
15589 /*---------------------------------------------------------------------------*/
15590 /* WRITE TO PAGE 0 IN IN FILE 0 NOW.                                         */
15591 /*---------------------------------------------------------------------------*/
15592     logFilePtr.p->fileChangeState = LogFileRecord::WRITE_PAGE_ZERO_ONGOING;
15593     Uint32 fileNo = logFilePtr.p->fileNo;
15594     if (fileNo == 0) {
15595       jam();
15596 /*---------------------------------------------------------------------------*/
15597 /* IF THE NEW FILE WAS 0 THEN WE HAVE ALREADY WRITTEN PAGE ZERO IN FILE 0.   */
15598 /*---------------------------------------------------------------------------*/
15599       // use writePageZeroLab to make sure that same code as normal is run
15600       writePageZeroLab(signal, __LINE__);
15601       return;
15602     } else {
15603       jam();
15604 /*---------------------------------------------------------------------------*/
15605 /* WRITE PAGE ZERO IN FILE ZERO. LOG_FILE_REC WILL REFER TO THE LOG FILE WE  */
15606 /* HAVE JUST WRITTEN PAGE ZERO IN TO GET HOLD OF LOG_FILE_PTR FOR THIS       */
15607 /* RECORD QUICKLY. THIS IS NEEDED TO GET HOLD OF THE FILE_CHANGE_STATE.      */
15608 /* THE ONLY INFORMATION WE WANT TO CHANGE IS THE LAST FILE NUMBER IN THE     */
15609 /* FILE DESCRIPTOR. THIS IS USED AT SYSTEM RESTART TO FIND THE END OF THE    */
15610 /* LOG PART.                                                                 */
15611 /*---------------------------------------------------------------------------*/
15612       Uint32 currLogFile = logFilePtr.i;
15613       logFilePtr.i = logPartPtr.p->firstLogfile;
15614       ptrCheckGuard(logFilePtr, clogFileFileSize, logFileRecord);
15615       logPagePtr.i = logFilePtr.p->logPageZero;
15616       ptrCheckGuard(logPagePtr, clogPageFileSize, logPageRecord);
15617       logPagePtr.p->logPageWord[ZPAGE_HEADER_SIZE + ZPOS_FILE_NO] = fileNo;
15618       writeSinglePage(signal, 0, ZPAGE_SIZE - 1, __LINE__);
15619       lfoPtr.p->logFileRec = currLogFile;
15620       lfoPtr.p->lfoState = LogFileOperationRecord::WRITE_PAGE_ZERO;
15621       return;
15622     }//if
15623   }//if
15624 }//Dblqh::lastWriteInFileLab()
15625 
writePageZeroLab(Signal * signal,Uint32 from)15626 void Dblqh::writePageZeroLab(Signal* signal, Uint32 from)
15627 {
15628   if ((logPartPtr.p->m_log_problems & LogPartRecord::P_FILE_CHANGE_PROBLEM)!= 0)
15629   {
15630     jam();
15631     update_log_problem(signal, logPartPtr,
15632                        LogPartRecord::P_FILE_CHANGE_PROBLEM,
15633                        /* clear */ false);
15634   }
15635 
15636   logFilePtr.p->fileChangeState = LogFileRecord::NOT_ONGOING;
15637 
15638 /*---------------------------------------------------------------------------*/
15639 /* IT COULD HAVE ARRIVED PAGE WRITES TO THE CURRENT FILE WHILE WE WERE       */
15640 /* WAITING FOR THIS DISK WRITE TO COMPLETE. THEY COULD NOT CHECK FOR         */
15641 /* COMPLETED GLOBAL CHECKPOINTS. THUS WE SHOULD DO THAT NOW INSTEAD.         */
15642 /*---------------------------------------------------------------------------*/
15643   bool res = checkGcpCompleted(signal,
15644                                logFilePtr.p->lastPageWritten,
15645                                logFilePtr.p->lastWordWritten);
15646   if (res && false)
15647   {
15648     gcpPtr.i = ccurrentGcprec;
15649     ptrCheckGuard(gcpPtr, cgcprecFileSize, gcpRecord);
15650 
15651     infoEvent("KESO completing GCP %u in writePageZeroLab from %u",
15652               gcpPtr.p->gcpId, from);
15653   }
15654   return;
15655 }//Dblqh::writePageZeroLab()
15656 
15657 /* ######################################################################### */
15658 /*       INITIAL START MODULE                                                */
15659 /*       THIS MODULE IS A SUB-MODULE OF THE FILE SYSTEM HANDLING.            */
15660 /*                                                                           */
15661 /*THIS MODULE INITIALISES ALL THE LOG FILES THAT ARE NEEDED AT A SYSTEM      */
15662 /*RESTART AND WHICH ARE USED DURING NORMAL OPERATIONS. IT CREATES THE FILES  */
15663 /*AND SETS A PROPER SIZE OF THEM AND INITIALISES THE FIRST PAGE IN EACH FILE */
15664 /* ######################################################################### */
openFileInitLab(Signal * signal)15665 void Dblqh::openFileInitLab(Signal* signal)
15666 {
15667   logFilePtr.p->logFileStatus = LogFileRecord::OPEN_INIT;
15668   seizeLogpage(signal);
15669   if (m_use_om_init == 0)
15670   {
15671     jam();
15672     initLogpage(signal);
15673     writeSinglePage(signal, (clogFileSize * ZPAGES_IN_MBYTE) - 1,
15674                     ZPAGE_SIZE - 1, __LINE__, false);
15675     lfoPtr.p->lfoState = LogFileOperationRecord::INIT_WRITE_AT_END;
15676   }
15677   else
15678   {
15679     jam();
15680     seizeLfo(signal);
15681     initWriteEndLab(signal);
15682   }
15683   return;
15684 }//Dblqh::openFileInitLab()
15685 
initWriteEndLab(Signal * signal)15686 void Dblqh::initWriteEndLab(Signal* signal)
15687 {
15688   releaseLfo(signal);
15689   initLogpage(signal);
15690   if (logFilePtr.p->fileNo == 0) {
15691     jam();
15692 /*---------------------------------------------------------------------------*/
15693 /* PAGE ZERO IN FILE ZERO MUST SET LOG LAP TO ONE SINCE IT HAS STARTED       */
15694 /* WRITING TO THE LOG, ALSO GLOBAL CHECKPOINTS ARE SET TO ZERO.              */
15695 /*---------------------------------------------------------------------------*/
15696     logPagePtr.p->logPageWord[ZPOS_LOG_LAP] = 1;
15697     logPagePtr.p->logPageWord[ZPOS_MAX_GCI_STARTED] = 0;
15698     logPagePtr.p->logPageWord[ZPOS_MAX_GCI_COMPLETED] = 0;
15699     logFilePtr.p->logMaxGciStarted[0] = 0;
15700     logFilePtr.p->logMaxGciCompleted[0] = 0;
15701   }//if
15702 /*---------------------------------------------------------------------------*/
15703 /* REUSE CODE FOR INITIALISATION OF FIRST PAGE IN ALL LOG FILES.             */
15704 /*---------------------------------------------------------------------------*/
15705   writeFileHeaderOpen(signal, ZINIT);
15706   return;
15707 }//Dblqh::initWriteEndLab()
15708 
initFirstPageLab(Signal * signal)15709 void Dblqh::initFirstPageLab(Signal* signal)
15710 {
15711   releaseLfo(signal);
15712   if (logFilePtr.p->fileNo == 0) {
15713     jam();
15714 /*---------------------------------------------------------------------------*/
15715 /* IN FILE ZERO WE WILL INSERT A PAGE ONE WHERE WE WILL INSERT A COMPLETED   */
15716 /* GCI RECORD FOR GCI = 0.                                                   */
15717 /*---------------------------------------------------------------------------*/
15718     initLogpage(signal);
15719     logPagePtr.p->logPageWord[ZPOS_LOG_LAP] = 1;
15720     logPagePtr.p->logPageWord[ZPAGE_HEADER_SIZE] = ZCOMPLETED_GCI_TYPE;
15721     logPagePtr.p->logPageWord[ZPAGE_HEADER_SIZE + 1] = 1;
15722     writeSinglePage(signal, 1, ZPAGE_SIZE - 1, __LINE__, false);
15723     lfoPtr.p->lfoState = LogFileOperationRecord::WRITE_GCI_ZERO;
15724     return;
15725   }//if
15726   logFilePtr.p->currentMbyte = 1;
15727   writeInitMbyte(signal);
15728   return;
15729 }//Dblqh::initFirstPageLab()
15730 
writeGciZeroLab(Signal * signal)15731 void Dblqh::writeGciZeroLab(Signal* signal)
15732 {
15733   releaseLfo(signal);
15734   logFilePtr.p->currentMbyte = 1;
15735   writeInitMbyte(signal);
15736   return;
15737 }//Dblqh::writeGciZeroLab()
15738 
writeInitMbyteLab(Signal * signal)15739 void Dblqh::writeInitMbyteLab(Signal* signal)
15740 {
15741   releaseLfo(signal);
15742   logFilePtr.p->currentMbyte = logFilePtr.p->currentMbyte + 1;
15743   if (logFilePtr.p->currentMbyte == clogFileSize) {
15744     jam();
15745     releaseLogpage(signal);
15746     logFilePtr.p->logFileStatus = LogFileRecord::CLOSING_INIT;
15747     closeFile(signal, logFilePtr, __LINE__);
15748     return;
15749   }//if
15750   writeInitMbyte(signal);
15751   return;
15752 }//Dblqh::writeInitMbyteLab()
15753 
closingInitLab(Signal * signal)15754 void Dblqh::closingInitLab(Signal* signal)
15755 {
15756   logFilePtr.p->logFileStatus = LogFileRecord::CLOSED;
15757   logPartPtr.i = logFilePtr.p->logPartRec;
15758   ptrCheckGuard(logPartPtr, clogPartFileSize, logPartRecord);
15759   if (logFilePtr.p->nextLogFile == logPartPtr.p->firstLogfile) {
15760     jam();
15761     checkInitCompletedLab(signal);
15762     return;
15763   } else {
15764     jam();
15765     logFilePtr.i = logFilePtr.p->nextLogFile;
15766     ptrCheckGuard(logFilePtr, clogFileFileSize, logFileRecord);
15767     openLogfileInit(signal);
15768   }//if
15769   return;
15770 }//Dblqh::closingInitLab()
15771 
checkInitCompletedLab(Signal * signal)15772 void Dblqh::checkInitCompletedLab(Signal* signal)
15773 {
15774   logPartPtr.p->logPartState = LogPartRecord::SR_FIRST_PHASE_COMPLETED;
15775 /*---------------------------------------------------------------------------*/
15776 /* WE HAVE NOW INITIALISED ALL FILES IN THIS LOG PART. WE CAN NOW SET THE    */
15777 /* THE LOG LAP TO ONE SINCE WE WILL START WITH LOG LAP ONE. LOG LAP = ZERO   */
15778 /* MEANS THIS PART OF THE LOG IS NOT WRITTEN YET.                            */
15779 /*---------------------------------------------------------------------------*/
15780   logPartPtr.p->logLap = 1;
15781 
15782   if (m_use_om_init && ++logPartPtr.i != clogPartFileSize)
15783   {
15784     jam();
15785     ptrAss(logPartPtr, logPartRecord);
15786     logFilePtr.i = logPartPtr.p->firstLogfile;
15787     ptrCheckGuard(logFilePtr, clogFileFileSize, logFileRecord);
15788     openLogfileInit(signal);
15789     return;
15790   }
15791 
15792   for (logPartPtr.i = 0; logPartPtr.i < clogPartFileSize; logPartPtr.i++)
15793   {
15794     jam();
15795     ptrAss(logPartPtr, logPartRecord);
15796     if (logPartPtr.p->logPartState != LogPartRecord::SR_FIRST_PHASE_COMPLETED)
15797     {
15798       jam();
15799 /*---------------------------------------------------------------------------*/
15800 /* THIS PART HAS STILL NOT COMPLETED. WAIT FOR THIS TO OCCUR.                */
15801 /*---------------------------------------------------------------------------*/
15802       return;
15803     }//if
15804   }
15805 
15806 #ifdef VM_TRACE
15807   enable_global_variables();
15808 #endif
15809   logfileInitCompleteReport(signal);
15810   sendNdbSttorryLab(signal);
15811 }
15812 
15813 /* ========================================================================= */
15814 /* =======       INITIATE LOG FILE OPERATION RECORD WHEN ALLOCATED   ======= */
15815 /*                                                                           */
15816 /* ========================================================================= */
initLfo(Signal * signal)15817 void Dblqh::initLfo(Signal* signal)
15818 {
15819   lfoPtr.p->firstLfoPage = RNIL;
15820   lfoPtr.p->lfoState = LogFileOperationRecord::IDLE;
15821   lfoPtr.p->logFileRec = logFilePtr.i;
15822   lfoPtr.p->noPagesRw = 0;
15823   lfoPtr.p->lfoPageNo = ZNIL;
15824 }//Dblqh::initLfo()
15825 
15826 /* ========================================================================= */
15827 /* =======              INITIATE LOG FILE WHEN ALLOCATED             ======= */
15828 /*                                                                           */
15829 /*       INPUT:  TFILE_NO        NUMBER OF THE FILE INITIATED                */
15830 /*               LOG_PART_PTR    NUMBER OF LOG PART                          */
15831 /*       SUBROUTINE SHORT NAME = IL                                          */
15832 /* ========================================================================= */
initLogfile(Signal * signal,Uint32 fileNo)15833 void Dblqh::initLogfile(Signal* signal, Uint32 fileNo)
15834 {
15835   UintR tilTmp;
15836   UintR tilIndex;
15837 
15838   logFilePtr.p->currentFilepage = 0;
15839   logFilePtr.p->currentLogpage = RNIL;
15840   logFilePtr.p->fileName[0] = (UintR)-1;
15841   logFilePtr.p->fileName[1] = (UintR)-1;	/* = H'FFFFFFFF = -1 */
15842   logFilePtr.p->fileName[2] = fileNo;	        /* Sfile_no */
15843   tilTmp = 1;	                        /* VERSION 1 OF FILE NAME */
15844   tilTmp = (tilTmp << 8) + 1;	    /* FRAGMENT LOG => .FRAGLOG AS EXTENSION */
15845   tilTmp = (tilTmp << 8) + (8 + logPartPtr.p->logPartNo); /* DIRECTORY = D(8+Part)/DBLQH */
15846   tilTmp = (tilTmp << 8) + 255;	              /* IGNORE Pxx PART OF FILE NAME */
15847   logFilePtr.p->fileName[3] = tilTmp;
15848 /* ========================================================================= */
15849 /*       FILE NAME BECOMES /D2/DBLQH/Tpart_no/Sfile_no.FRAGLOG               */
15850 /* ========================================================================= */
15851   logFilePtr.p->fileNo = fileNo;
15852   logFilePtr.p->filePosition = 0;
15853   logFilePtr.p->firstLfo = RNIL;
15854   logFilePtr.p->lastLfo = RNIL;
15855   logFilePtr.p->logFileStatus = LogFileRecord::CLOSED;
15856   logFilePtr.p->logPartRec = logPartPtr.i;
15857   logFilePtr.p->noLogpagesInBuffer = 0;
15858   logFilePtr.p->firstFilledPage = RNIL;
15859   logFilePtr.p->lastFilledPage = RNIL;
15860   logFilePtr.p->lastPageWritten = 0;
15861   logFilePtr.p->logPageZero = RNIL;
15862   logFilePtr.p->currentMbyte = 0;
15863   for (tilIndex = 0; tilIndex < clogFileSize; tilIndex++) {
15864     logFilePtr.p->logMaxGciCompleted[tilIndex] = (UintR)-1;
15865     logFilePtr.p->logMaxGciStarted[tilIndex] = (UintR)-1;
15866     logFilePtr.p->logLastPrepRef[tilIndex] = 0;
15867   }//for
15868 }//Dblqh::initLogfile()
15869 
15870 /* ========================================================================= */
15871 /* =======              INITIATE LOG PAGE WHEN ALLOCATED             ======= */
15872 /*                                                                           */
15873 /* ========================================================================= */
initLogpage(Signal * signal)15874 void Dblqh::initLogpage(Signal* signal)
15875 {
15876   TcConnectionrecPtr ilpTcConnectptr;
15877 
15878   logPagePtr.p->logPageWord[ZPOS_LOG_LAP] = logPartPtr.p->logLap;
15879   logPagePtr.p->logPageWord[ZPOS_MAX_GCI_COMPLETED] =
15880         logPartPtr.p->logPartNewestCompletedGCI;
15881   logPagePtr.p->logPageWord[ZPOS_MAX_GCI_STARTED] = cnewestGci;
15882   logPagePtr.p->logPageWord[ZPOS_VERSION] = NDB_VERSION;
15883   logPagePtr.p->logPageWord[ZPOS_NO_LOG_FILES] = logPartPtr.p->noLogFiles;
15884   logPagePtr.p->logPageWord[ZCURR_PAGE_INDEX] = ZPAGE_HEADER_SIZE;
15885   ilpTcConnectptr.i = logPartPtr.p->firstLogTcrec;
15886   if (ilpTcConnectptr.i != RNIL) {
15887     jam();
15888     ptrCheckGuard(ilpTcConnectptr, ctcConnectrecFileSize, tcConnectionrec);
15889     logPagePtr.p->logPageWord[ZLAST_LOG_PREP_REF] =
15890       (ilpTcConnectptr.p->logStartFileNo << 16) +
15891       (ilpTcConnectptr.p->logStartPageNo >> ZTWOLOG_NO_PAGES_IN_MBYTE);
15892   } else {
15893     jam();
15894     logPagePtr.p->logPageWord[ZLAST_LOG_PREP_REF] =
15895       (logFilePtr.p->fileNo << 16) +
15896       (logFilePtr.p->currentFilepage >> ZTWOLOG_NO_PAGES_IN_MBYTE);
15897   }//if
15898 }//Dblqh::initLogpage()
15899 
15900 /* ------------------------------------------------------------------------- */
15901 /* -------               OPEN LOG FILE FOR READ AND WRITE            ------- */
15902 /*                                                                           */
15903 /*       SUBROUTINE SHORT NAME = OFR                                         */
15904 /* ------------------------------------------------------------------------- */
openFileRw(Signal * signal,LogFileRecordPtr olfLogFilePtr,bool writeBuffer)15905 void Dblqh::openFileRw(Signal* signal,
15906                        LogFileRecordPtr olfLogFilePtr,
15907                        bool writeBuffer)
15908 {
15909   FsOpenReq* req = (FsOpenReq*)signal->getDataPtrSend();
15910   signal->theData[0] = cownref;
15911   signal->theData[1] = olfLogFilePtr.i;
15912   signal->theData[2] = olfLogFilePtr.p->fileName[0];
15913   signal->theData[3] = olfLogFilePtr.p->fileName[1];
15914   signal->theData[4] = olfLogFilePtr.p->fileName[2];
15915   signal->theData[5] = olfLogFilePtr.p->fileName[3];
15916   signal->theData[6] = FsOpenReq::OM_READWRITE | FsOpenReq::OM_AUTOSYNC | FsOpenReq::OM_CHECK_SIZE;
15917   if (c_o_direct)
15918     signal->theData[6] |= FsOpenReq::OM_DIRECT;
15919   if (writeBuffer)
15920     signal->theData[6] |= FsOpenReq::OM_WRITE_BUFFER;
15921 
15922   req->auto_sync_size = MAX_REDO_PAGES_WITHOUT_SYNCH * sizeof(LogPageRecord);
15923   Uint64 sz = clogFileSize;
15924   sz *= 1024; sz *= 1024;
15925   req->file_size_hi = (Uint32)(sz >> 32);
15926   req->file_size_lo = (Uint32)(sz & 0xFFFFFFFF);
15927   sendSignal(NDBFS_REF, GSN_FSOPENREQ, signal, FsOpenReq::SignalLength, JBA);
15928 }//Dblqh::openFileRw()
15929 
15930 /* ------------------------------------------------------------------------- */
15931 /* -------               OPEN LOG FILE DURING INITIAL START          ------- */
15932 /*                                                                           */
15933 /*       SUBROUTINE SHORT NAME = OLI                                         */
15934 /* ------------------------------------------------------------------------- */
openLogfileInit(Signal * signal)15935 void Dblqh::openLogfileInit(Signal* signal)
15936 {
15937   logFilePtr.p->logFileStatus = LogFileRecord::OPENING_INIT;
15938   FsOpenReq* req = (FsOpenReq*)signal->getDataPtrSend();
15939   signal->theData[0] = cownref;
15940   signal->theData[1] = logFilePtr.i;
15941   signal->theData[2] = logFilePtr.p->fileName[0];
15942   signal->theData[3] = logFilePtr.p->fileName[1];
15943   signal->theData[4] = logFilePtr.p->fileName[2];
15944   signal->theData[5] = logFilePtr.p->fileName[3];
15945   signal->theData[6] = FsOpenReq::OM_READWRITE | FsOpenReq::OM_TRUNCATE | FsOpenReq::OM_CREATE | FsOpenReq::OM_AUTOSYNC | FsOpenReq::OM_WRITE_BUFFER;
15946   if (c_o_direct)
15947     signal->theData[6] |= FsOpenReq::OM_DIRECT;
15948 
15949   Uint64 sz = Uint64(clogFileSize) * 1024 * 1024;
15950   req->file_size_hi = Uint32(sz >> 32);
15951   req->file_size_lo = Uint32(sz);
15952   req->page_size = File_formats::NDB_PAGE_SIZE;
15953   if (m_use_om_init)
15954   {
15955     jam();
15956     signal->theData[6] |= FsOpenReq::OM_INIT;
15957   }
15958 
15959   req->auto_sync_size = MAX_REDO_PAGES_WITHOUT_SYNCH * sizeof(LogPageRecord);
15960   sendSignal(NDBFS_REF, GSN_FSOPENREQ, signal, FsOpenReq::SignalLength, JBA);
15961 }//Dblqh::openLogfileInit()
15962 
15963 void
execFSWRITEREQ(Signal * signal)15964 Dblqh::execFSWRITEREQ(Signal* signal)
15965 {
15966   /**
15967    * This is currently run in other thread -> no jam
15968    *   and no global variables
15969    */
15970   Ptr<GlobalPage> page_ptr;
15971   FsReadWriteReq* req= (FsReadWriteReq*)signal->getDataPtr();
15972   m_shared_page_pool.getPtr(page_ptr, req->data.pageData[0]);
15973 
15974   LogFileRecordPtr currLogFilePtr;
15975   currLogFilePtr.i = req->userPointer;
15976   ptrCheckGuard(currLogFilePtr, clogFileFileSize, logFileRecord);
15977 
15978   LogPartRecordPtr currLogPartPtr;
15979   currLogPartPtr.i = currLogFilePtr.p->logPartRec;
15980   ptrCheckGuard(currLogPartPtr, clogPartFileSize, logPartRecord);
15981 
15982   Uint32 page_no = req->varIndex;
15983   LogPageRecordPtr currLogPagePtr;
15984   currLogPagePtr.p = (LogPageRecord*)page_ptr.p;
15985 
15986   bzero(page_ptr.p, sizeof(LogPageRecord));
15987   if (page_no == 0)
15988   {
15989     // keep writing these afterwards
15990   }
15991   else if (((page_no % ZPAGES_IN_MBYTE) == 0) ||
15992            (page_no == ((clogFileSize * ZPAGES_IN_MBYTE) - 1)))
15993   {
15994     currLogPagePtr.p->logPageWord[ZPOS_LOG_LAP] = currLogPartPtr.p->logLap;
15995     currLogPagePtr.p->logPageWord[ZPOS_MAX_GCI_COMPLETED] =
15996       currLogPartPtr.p->logPartNewestCompletedGCI;
15997     currLogPagePtr.p->logPageWord[ZPOS_MAX_GCI_STARTED] = cnewestGci;
15998     currLogPagePtr.p->logPageWord[ZPOS_VERSION] = NDB_VERSION;
15999     currLogPagePtr.p->logPageWord[ZPOS_NO_LOG_FILES] =
16000       currLogPartPtr.p->noLogFiles;
16001     currLogPagePtr.p->logPageWord[ZCURR_PAGE_INDEX] = ZPAGE_HEADER_SIZE;
16002     currLogPagePtr.p->logPageWord[ZLAST_LOG_PREP_REF] =
16003       (currLogFilePtr.p->fileNo << 16) +
16004       (currLogFilePtr.p->currentFilepage >> ZTWOLOG_NO_PAGES_IN_MBYTE);
16005 
16006     currLogPagePtr.p->logPageWord[ZNEXT_PAGE] = RNIL;
16007     currLogPagePtr.p->logPageWord[ZPOS_CHECKSUM] =
16008       calcPageCheckSum(currLogPagePtr);
16009   }
16010   else if (0)
16011   {
16012     currLogPagePtr.p->logPageWord[ZNEXT_PAGE] = RNIL;
16013     currLogPagePtr.p->logPageWord[ZPOS_CHECKSUM] =
16014       calcPageCheckSum(currLogPagePtr);
16015   }
16016 }
16017 
16018 /* OPEN FOR READ/WRITE, DO CREATE AND DO TRUNCATE FILE */
16019 /* ------------------------------------------------------------------------- */
16020 /* -------               OPEN NEXT LOG FILE                          ------- */
16021 /*                                                                           */
16022 /*       SUBROUTINE SHORT NAME = ONL                                         */
16023 /* ------------------------------------------------------------------------- */
openNextLogfile(Signal * signal)16024 void Dblqh::openNextLogfile(Signal* signal)
16025 {
16026   LogFileRecordPtr onlLogFilePtr;
16027 
16028   if (logPartPtr.p->noLogFiles > 2) {
16029     jam();
16030 /* -------------------------------------------------- */
16031 /*       IF ONLY 1 OR 2 LOG FILES EXIST THEN THEY ARE */
16032 /*       ALWAYS OPEN AND THUS IT IS NOT NECESSARY TO  */
16033 /*       OPEN THEM NOW.                               */
16034 /* -------------------------------------------------- */
16035     onlLogFilePtr.i = logFilePtr.p->nextLogFile;
16036     ptrCheckGuard(onlLogFilePtr, clogFileFileSize, logFileRecord);
16037     if (onlLogFilePtr.p->logFileStatus != LogFileRecord::CLOSED) {
16038       ndbrequire(onlLogFilePtr.p->fileNo == 0);
16039       return;
16040     }//if
16041     onlLogFilePtr.p->logFileStatus = LogFileRecord::OPENING_WRITE_LOG;
16042     FsOpenReq* req = (FsOpenReq*)signal->getDataPtrSend();
16043     signal->theData[0] = cownref;
16044     signal->theData[1] = onlLogFilePtr.i;
16045     signal->theData[2] = onlLogFilePtr.p->fileName[0];
16046     signal->theData[3] = onlLogFilePtr.p->fileName[1];
16047     signal->theData[4] = onlLogFilePtr.p->fileName[2];
16048     signal->theData[5] = onlLogFilePtr.p->fileName[3];
16049     signal->theData[6] = FsOpenReq::OM_READWRITE | FsOpenReq::OM_AUTOSYNC | FsOpenReq::OM_CHECK_SIZE | FsOpenReq::OM_WRITE_BUFFER;
16050     if (c_o_direct)
16051       signal->theData[6] |= FsOpenReq::OM_DIRECT;
16052     req->auto_sync_size = MAX_REDO_PAGES_WITHOUT_SYNCH * sizeof(LogPageRecord);
16053     Uint64 sz = clogFileSize;
16054     sz *= 1024; sz *= 1024;
16055     req->file_size_hi = (Uint32)(sz >> 32);
16056     req->file_size_lo = (Uint32)(sz & 0xFFFFFFFF);
16057     sendSignal(NDBFS_REF, GSN_FSOPENREQ, signal, FsOpenReq::SignalLength, JBA);
16058   }//if
16059 }//Dblqh::openNextLogfile()
16060 
16061         /* OPEN FOR READ/WRITE, DON'T CREATE AND DON'T TRUNCATE FILE */
16062 /* ------------------------------------------------------------------------- */
16063 /* -------                       RELEASE LFO RECORD                  ------- */
16064 /*                                                                           */
16065 /* ------------------------------------------------------------------------- */
releaseLfo(Signal * signal)16066 void Dblqh::releaseLfo(Signal* signal)
16067 {
16068 #ifdef VM_TRACE
16069   // Check that lfo record isn't already in free list
16070   LogFileOperationRecordPtr TlfoPtr;
16071   TlfoPtr.i = cfirstfreeLfo;
16072   while (TlfoPtr.i != RNIL){
16073     ptrCheckGuard(TlfoPtr, clfoFileSize, logFileOperationRecord);
16074     ndbrequire(TlfoPtr.i != lfoPtr.i);
16075     TlfoPtr.i = TlfoPtr.p->nextLfo;
16076   }
16077 #endif
16078   lfoPtr.p->nextLfo = cfirstfreeLfo;
16079   lfoPtr.p->lfoTimer = 0;
16080   cfirstfreeLfo = lfoPtr.i;
16081   lfoPtr.p->lfoState = LogFileOperationRecord::IDLE;
16082 }//Dblqh::releaseLfo()
16083 
16084 /* ------------------------------------------------------------------------- */
16085 /* ------- RELEASE ALL LOG PAGES CONNECTED TO A LFO RECORD           ------- */
16086 /*                                                                           */
16087 /*       SUBROUTINE SHORT NAME = RLP                                         */
16088 /* ------------------------------------------------------------------------- */
releaseLfoPages(Signal * signal)16089 void Dblqh::releaseLfoPages(Signal* signal)
16090 {
16091   logPagePtr.i = lfoPtr.p->firstLfoPage;
16092   while (logPagePtr.i != RNIL)
16093   {
16094     ptrCheckGuard(logPagePtr, clogPageFileSize, logPageRecord);
16095     Uint32 tmp = logPagePtr.p->logPageWord[ZNEXT_PAGE];
16096     releaseLogpage(signal);
16097     logPagePtr.i = tmp;
16098   }
16099   lfoPtr.p->firstLfoPage = RNIL;
16100 }//Dblqh::releaseLfoPages()
16101 
16102 /* ------------------------------------------------------------------------- */
16103 /* -------                       RELEASE LOG PAGE                    ------- */
16104 /*                                                                           */
16105 /* ------------------------------------------------------------------------- */
releaseLogpage(Signal * signal)16106 void Dblqh::releaseLogpage(Signal* signal)
16107 {
16108 #ifdef VM_TRACE
16109   // Check that log page isn't already in free list
16110   ndbrequire(logPagePtr.p->logPageWord[ZPOS_IN_FREE_LIST] == 0);
16111 #endif
16112 
16113   cnoOfLogPages++;
16114   logPagePtr.p->logPageWord[ZNEXT_PAGE] = cfirstfreeLogPage;
16115   logPagePtr.p->logPageWord[ZPOS_IN_WRITING]= 0;
16116   logPagePtr.p->logPageWord[ZPOS_IN_FREE_LIST]= 1;
16117   cfirstfreeLogPage = logPagePtr.i;
16118 }//Dblqh::releaseLogpage()
16119 
16120 /* ------------------------------------------------------------------------- */
16121 /* -------       SEIZE LFO RECORD                                    ------- */
16122 /*                                                                           */
16123 /* ------------------------------------------------------------------------- */
seizeLfo(Signal * signal)16124 void Dblqh::seizeLfo(Signal* signal)
16125 {
16126   lfoPtr.i = cfirstfreeLfo;
16127   ptrCheckGuard(lfoPtr, clfoFileSize, logFileOperationRecord);
16128   cfirstfreeLfo = lfoPtr.p->nextLfo;
16129   lfoPtr.p->nextLfo = RNIL;
16130   lfoPtr.p->lfoTimer = cLqhTimeOutCount;
16131 }//Dblqh::seizeLfo()
16132 
16133 /* ------------------------------------------------------------------------- */
16134 /* -------       SEIZE LOG FILE RECORD                               ------- */
16135 /*                                                                           */
16136 /* ------------------------------------------------------------------------- */
seizeLogfile(Signal * signal)16137 void Dblqh::seizeLogfile(Signal* signal)
16138 {
16139   logFilePtr.i = cfirstfreeLogFile;
16140   ptrCheckGuard(logFilePtr, clogFileFileSize, logFileRecord);
16141 /* ------------------------------------------------------------------------- */
16142 /*IF LIST IS EMPTY THEN A SYSTEM CRASH IS INVOKED SINCE LOG_FILE_PTR = RNIL  */
16143 /* ------------------------------------------------------------------------- */
16144   cfirstfreeLogFile = logFilePtr.p->nextLogFile;
16145   logFilePtr.p->nextLogFile = RNIL;
16146 }//Dblqh::seizeLogfile()
16147 
16148 /* ------------------------------------------------------------------------- */
16149 /* -------       SEIZE LOG PAGE RECORD                               ------- */
16150 /*                                                                           */
16151 /* ------------------------------------------------------------------------- */
seizeLogpage(Signal * signal)16152 void Dblqh::seizeLogpage(Signal* signal)
16153 {
16154   cnoOfLogPages--;
16155   logPagePtr.i = cfirstfreeLogPage;
16156   ptrCheckGuard(logPagePtr, clogPageFileSize, logPageRecord);
16157 /* ------------------------------------------------------------------------- */
16158 /*IF LIST IS EMPTY THEN A SYSTEM CRASH IS INVOKED SINCE LOG_PAGE_PTR = RNIL  */
16159 /* ------------------------------------------------------------------------- */
16160   cfirstfreeLogPage = logPagePtr.p->logPageWord[ZNEXT_PAGE];
16161 #ifdef VM_TRACE
16162   bzero(logPagePtr.p, sizeof(LogPageRecord));
16163 #endif
16164   logPagePtr.p->logPageWord[ZNEXT_PAGE] = RNIL;
16165   logPagePtr.p->logPageWord[ZPOS_IN_FREE_LIST] = 0;
16166 }//Dblqh::seizeLogpage()
16167 
16168 /* ------------------------------------------------------------------------- */
16169 /* -------               WRITE FILE DESCRIPTOR INFORMATION           ------- */
16170 /*                                                                           */
16171 /*       SUBROUTINE SHORT NAME: WFD                                          */
16172 // Pointer handling:
16173 // logFilePtr in
16174 // logPartPtr in
16175 /* ------------------------------------------------------------------------- */
writeFileDescriptor(Signal * signal)16176 void Dblqh::writeFileDescriptor(Signal* signal)
16177 {
16178   TcConnectionrecPtr wfdTcConnectptr;
16179   UintR twfdFileNo;
16180   UintR twfdMbyte;
16181 
16182 /* -------------------------------------------------- */
16183 /*       START BY WRITING TO LOG FILE RECORD          */
16184 /* -------------------------------------------------- */
16185   arrGuard(logFilePtr.p->currentMbyte, clogFileSize);
16186   if (DEBUG_REDO)
16187   {
16188     printf("part: %u file: %u setting logMaxGciCompleted[%u] = %u logMaxGciStarted[%u]: %u lastPrepRef[%u]: ",
16189            logPartPtr.p->logPartNo,
16190            logFilePtr.p->fileNo,
16191            logFilePtr.p->currentMbyte,
16192            logPartPtr.p->logPartNewestCompletedGCI,
16193            logFilePtr.p->currentMbyte,
16194            cnewestGci,
16195            logFilePtr.p->currentMbyte);
16196     if (logPartPtr.p->firstLogTcrec == RNIL)
16197     {
16198       ndbout_c("file: %u mb: %u (RNIL)",
16199                logFilePtr.p->fileNo,
16200                logFilePtr.p->currentMbyte);
16201     }
16202     else
16203     {
16204       wfdTcConnectptr.i = logPartPtr.p->firstLogTcrec;
16205       ptrCheckGuard(wfdTcConnectptr, ctcConnectrecFileSize, tcConnectionrec);
16206       ndbout_c("file: %u mb: %u",
16207                wfdTcConnectptr.p->logStartFileNo,
16208                wfdTcConnectptr.p->logStartPageNo >> ZTWOLOG_NO_PAGES_IN_MBYTE);
16209     }
16210   }
16211   logFilePtr.p->logMaxGciCompleted[logFilePtr.p->currentMbyte] =
16212     logPartPtr.p->logPartNewestCompletedGCI;
16213   logFilePtr.p->logMaxGciStarted[logFilePtr.p->currentMbyte] = cnewestGci;
16214   wfdTcConnectptr.i = logPartPtr.p->firstLogTcrec;
16215   if (wfdTcConnectptr.i != RNIL) {
16216     jam();
16217     ptrCheckGuard(wfdTcConnectptr, ctcConnectrecFileSize, tcConnectionrec);
16218     twfdFileNo = wfdTcConnectptr.p->logStartFileNo;
16219     twfdMbyte = wfdTcConnectptr.p->logStartPageNo >> ZTWOLOG_NO_PAGES_IN_MBYTE;
16220     logFilePtr.p->logLastPrepRef[logFilePtr.p->currentMbyte] =
16221       (twfdFileNo << 16) + twfdMbyte;
16222   } else {
16223     jam();
16224     logFilePtr.p->logLastPrepRef[logFilePtr.p->currentMbyte] =
16225       (logFilePtr.p->fileNo << 16) + logFilePtr.p->currentMbyte;
16226   }//if
16227 }//Dblqh::writeFileDescriptor()
16228 
16229 /* ------------------------------------------------------------------------- */
16230 /* -------               WRITE THE HEADER PAGE OF A NEW FILE         ------- */
16231 /*                                                                           */
16232 /*       SUBROUTINE SHORT NAME:  WMO                                         */
16233 /* ------------------------------------------------------------------------- */
writeFileHeaderOpen(Signal * signal,Uint32 wmoType)16234 void Dblqh::writeFileHeaderOpen(Signal* signal, Uint32 wmoType)
16235 {
16236   UintR twmoNoLogDescriptors;
16237 
16238 /* -------------------------------------------------- */
16239 /*       WRITE HEADER INFORMATION IN THE NEW FILE.    */
16240 /* -------------------------------------------------- */
16241   logPagePtr.p->logPageWord[ZPAGE_HEADER_SIZE + ZPOS_LOG_TYPE] = ZFD_TYPE;
16242   logPagePtr.p->logPageWord[ZPAGE_HEADER_SIZE + ZPOS_FILE_NO] =
16243     logFilePtr.p->fileNo;
16244   if (logPartPtr.p->noLogFiles > cmaxLogFilesInPageZero) {
16245     jam();
16246     twmoNoLogDescriptors = cmaxLogFilesInPageZero;
16247   } else {
16248     jam();
16249     twmoNoLogDescriptors = logPartPtr.p->noLogFiles;
16250   }//if
16251   logPagePtr.p->logPageWord[ZPAGE_HEADER_SIZE + ZPOS_NO_FD] =
16252     twmoNoLogDescriptors;
16253 
16254   {
16255     Uint32 pos = ZPAGE_HEADER_SIZE + ZFD_HEADER_SIZE;
16256     LogFileRecordPtr filePtr = logFilePtr;
16257     for (Uint32 fd = 0; fd < twmoNoLogDescriptors; fd++)
16258     {
16259       jam();
16260       ptrCheckGuard(filePtr, clogFileFileSize, logFileRecord);
16261       for (Uint32 mb = 0; mb < clogFileSize; mb ++)
16262       {
16263         jam();
16264         Uint32 pos0 = pos + fd * (ZFD_MBYTE_SIZE * clogFileSize) + mb;
16265         Uint32 pos1 = pos0 + clogFileSize;
16266         Uint32 pos2 = pos1 + clogFileSize;
16267         arrGuard(pos0, ZPAGE_SIZE);
16268         arrGuard(pos1, ZPAGE_SIZE);
16269         arrGuard(pos2, ZPAGE_SIZE);
16270         logPagePtr.p->logPageWord[pos0] = filePtr.p->logMaxGciCompleted[mb];
16271         logPagePtr.p->logPageWord[pos1] = filePtr.p->logMaxGciStarted[mb];
16272         logPagePtr.p->logPageWord[pos2] = filePtr.p->logLastPrepRef[mb];
16273       }
16274       filePtr.i = filePtr.p->prevLogFile;
16275     }
16276     pos += (twmoNoLogDescriptors * ZFD_MBYTE_SIZE * clogFileSize);
16277     arrGuard(pos, ZPAGE_SIZE);
16278     logPagePtr.p->logPageWord[ZCURR_PAGE_INDEX] = pos;
16279     logPagePtr.p->logPageWord[pos] = ZNEXT_LOG_RECORD_TYPE;
16280   }
16281 
16282 /* ------------------------------------------------------- */
16283 /*       THIS IS A SPECIAL WRITE OF THE FIRST PAGE IN THE  */
16284 /*       LOG FILE. THIS HAS SPECIAL SIGNIFANCE TO FIND     */
16285 /*       THE END OF THE LOG AT SYSTEM RESTART.             */
16286 /* ------------------------------------------------------- */
16287   if (wmoType == ZINIT) {
16288     jam();
16289     writeSinglePage(signal, 0, ZPAGE_SIZE - 1, __LINE__, false);
16290     lfoPtr.p->lfoState = LogFileOperationRecord::INIT_FIRST_PAGE;
16291   } else {
16292     jam();
16293     writeSinglePage(signal, 0, ZPAGE_SIZE - 1, __LINE__, true);
16294     lfoPtr.p->lfoState = LogFileOperationRecord::FIRST_PAGE_WRITE_IN_LOGFILE;
16295   }//if
16296   logFilePtr.p->filePosition = 1;
16297   if (wmoType == ZNORMAL) {
16298     jam();
16299 /* -------------------------------------------------- */
16300 /*       ALLOCATE A NEW PAGE SINCE THE CURRENT IS     */
16301 /*       WRITTEN.                                     */
16302 /* -------------------------------------------------- */
16303     seizeLogpage(signal);
16304     initLogpage(signal);
16305     logFilePtr.p->currentLogpage = logPagePtr.i;
16306     logFilePtr.p->currentFilepage = logFilePtr.p->currentFilepage + 1;
16307   }//if
16308 }//Dblqh::writeFileHeaderOpen()
16309 
16310 /* -------------------------------------------------- */
16311 /*       THE NEW FILE POSITION WILL ALWAYS BE 1 SINCE */
16312 /*       WE JUST WROTE THE FIRST PAGE IN THE LOG FILE */
16313 /* -------------------------------------------------- */
16314 /* ------------------------------------------------------------------------- */
16315 /* -------               WRITE A MBYTE HEADER DURING INITIAL START   ------- */
16316 /*                                                                           */
16317 /*       SUBROUTINE SHORT NAME: WIM                                          */
16318 /* ------------------------------------------------------------------------- */
writeInitMbyte(Signal * signal)16319 void Dblqh::writeInitMbyte(Signal* signal)
16320 {
16321   if (m_use_om_init == 0)
16322   {
16323     jam();
16324     initLogpage(signal);
16325     writeSinglePage(signal, logFilePtr.p->currentMbyte * ZPAGES_IN_MBYTE,
16326                     ZPAGE_SIZE - 1, __LINE__, false);
16327     lfoPtr.p->lfoState = LogFileOperationRecord::WRITE_INIT_MBYTE;
16328     checkReportStatus(signal);
16329   }
16330   else
16331   {
16332     jam();
16333     seizeLfo(signal);
16334     logFilePtr.p->currentMbyte = clogFileSize - 1;
16335     writeInitMbyteLab(signal);
16336   }
16337 }//Dblqh::writeInitMbyte()
16338 
16339 /* ------------------------------------------------------------------------- */
16340 /* -------               WRITE A SINGLE PAGE INTO A FILE             ------- */
16341 /*                                                                           */
16342 /*       INPUT:          TWSP_PAGE_NO    THE PAGE NUMBER WRITTEN             */
16343 /*       SUBROUTINE SHORT NAME:  WSP                                         */
16344 /* ------------------------------------------------------------------------- */
writeSinglePage(Signal * signal,Uint32 pageNo,Uint32 wordWritten,Uint32 place,bool sync)16345 void Dblqh::writeSinglePage(Signal* signal, Uint32 pageNo,
16346                             Uint32 wordWritten, Uint32 place,
16347                             bool sync)
16348 {
16349   seizeLfo(signal);
16350   initLfo(signal);
16351   lfoPtr.p->firstLfoPage = logPagePtr.i;
16352   logPagePtr.p->logPageWord[ZNEXT_PAGE] = RNIL;
16353 
16354   writeDbgInfoPageHeader(logPagePtr, place, pageNo, wordWritten);
16355   // Calculate checksum for page
16356   logPagePtr.p->logPageWord[ZPOS_CHECKSUM] = calcPageCheckSum(logPagePtr);
16357 
16358   lfoPtr.p->lfoPageNo = pageNo;
16359   lfoPtr.p->lfoWordWritten = wordWritten;
16360   lfoPtr.p->noPagesRw = 1;
16361 /* -------------------------------------------------- */
16362 /*       SET TIMER ON THIS LOG PART TO SIGNIFY THAT A */
16363 /*       LOG RECORD HAS BEEN SENT AT THIS TIME.       */
16364 /* -------------------------------------------------- */
16365   logPartPtr.p->logPartTimer = logPartPtr.p->logTimer;
16366   signal->theData[0] = logFilePtr.p->fileRef;
16367   signal->theData[1] = cownref;
16368   signal->theData[2] = lfoPtr.i;
16369   signal->theData[3] = sync ? ZLIST_OF_PAIRS_SYNCH : ZLIST_OF_PAIRS;
16370   signal->theData[4] = ZVAR_NO_LOG_PAGE_WORD;
16371   signal->theData[5] = 1;                     /* ONE PAGE WRITTEN */
16372   signal->theData[6] = logPagePtr.i;
16373   signal->theData[7] = pageNo;
16374   sendSignal(NDBFS_REF, GSN_FSWRITEREQ, signal, 8, JBA);
16375 
16376   ndbrequire(logFilePtr.p->fileRef != RNIL);
16377 
16378   logPartPtr.p->m_io_tracker.send_io(32768);
16379 
16380   if (DEBUG_REDO)
16381   {
16382     ndbout_c("writeSingle 1 page at part: %u file: %u page: %u (mb: %u)",
16383              logPartPtr.p->logPartNo,
16384              logFilePtr.p->fileNo,
16385              pageNo,
16386              pageNo >> ZTWOLOG_NO_PAGES_IN_MBYTE);
16387   }
16388 }//Dblqh::writeSinglePage()
16389 
16390 /* ##########################################################################
16391  *     SYSTEM RESTART PHASE ONE MODULE
16392  *     THIS MODULE IS A SUB-MODULE OF THE FILE SYSTEM HANDLING.
16393  *
16394  *     THIS MODULE CONTAINS THE CODE FOR THE FIRST PHASE OF THE SYSTEM RESTART.
16395  *     THE AIM OF THIS PHASE IS TO FIND THE END OF THE LOG AND TO FIND
16396  *     INFORMATION ABOUT WHERE GLOBAL CHECKPOINTS ARE COMPLETED AND STARTED
16397  *     IN THE LOG. THIS INFORMATION IS NEEDED TO START PHASE THREE OF
16398  *     THE SYSTEM RESTART.
16399  * ########################################################################## */
16400 /* --------------------------------------------------------------------------
16401  *     A SYSTEM RESTART OR NODE RESTART IS ONGOING. WE HAVE NOW OPENED FILE 0
16402  *     NOW WE NEED TO READ PAGE 0 TO FIND WHICH LOG FILE THAT WAS OPEN AT
16403  *     CRASH TIME.
16404  * -------------------------------------------------------------------------- */
openSrFrontpageLab(Signal * signal)16405 void Dblqh::openSrFrontpageLab(Signal* signal)
16406 {
16407   readSinglePage(signal, 0);
16408   lfoPtr.p->lfoState = LogFileOperationRecord::READ_SR_FRONTPAGE;
16409   return;
16410 }//Dblqh::openSrFrontpageLab()
16411 
16412 /* -------------------------------------------------------------------------
16413  * WE HAVE NOW READ PAGE 0 IN FILE 0. CHECK THE LAST OPEN FILE. ACTUALLY THE
16414  * LAST OPEN FILE COULD BE THE NEXT AFTER THAT. CHECK THAT FIRST. WHEN THE
16415  * LAST WAS FOUND WE CAN FIND ALL THE NEEDED INFORMATION WHERE TO START AND
16416  * STOP READING THE LOG.
16417  * -------------------------------------------------------------------------- */
readSrFrontpageLab(Signal * signal)16418 void Dblqh::readSrFrontpageLab(Signal* signal)
16419 {
16420   Uint32 fileNo = logPagePtr.p->logPageWord[ZPAGE_HEADER_SIZE + ZPOS_FILE_NO];
16421   if (fileNo == 0) {
16422     jam();
16423     /* ----------------------------------------------------------------------
16424      *       FILE 0 WAS ALSO LAST FILE SO WE DO NOT NEED TO READ IT AGAIN.
16425      * ---------------------------------------------------------------------- */
16426     readSrLastFileLab(signal);
16427     return;
16428   }//if
16429   /* ------------------------------------------------------------------------
16430    *    CLOSE FILE 0 SO THAT WE HAVE CLOSED ALL FILES WHEN STARTING TO READ
16431    *    THE FRAGMENT LOG. ALSO RELEASE PAGE ZERO.
16432    * ------------------------------------------------------------------------ */
16433   releaseLogpage(signal);
16434   logFilePtr.p->logFileStatus = LogFileRecord::CLOSING_SR;
16435   closeFile(signal, logFilePtr, __LINE__);
16436   LogFileRecordPtr locLogFilePtr;
16437   findLogfile(signal, fileNo, logPartPtr, &locLogFilePtr);
16438   locLogFilePtr.p->logFileStatus = LogFileRecord::OPEN_SR_LAST_FILE;
16439   openFileRw(signal, locLogFilePtr);
16440   return;
16441 }//Dblqh::readSrFrontpageLab()
16442 
openSrLastFileLab(Signal * signal)16443 void Dblqh::openSrLastFileLab(Signal* signal)
16444 {
16445   readSinglePage(signal, 0);
16446   lfoPtr.p->lfoState = LogFileOperationRecord::READ_SR_LAST_FILE;
16447   return;
16448 }//Dblqh::openSrLastFileLab()
16449 
readSrLastFileLab(Signal * signal)16450 void Dblqh::readSrLastFileLab(Signal* signal)
16451 {
16452   logPartPtr.p->logLap = logPagePtr.p->logPageWord[ZPOS_LOG_LAP];
16453   if (DEBUG_REDO)
16454   {
16455     ndbout_c("readSrLastFileLab part: %u logExecState: %u logPartState: %u logLap: %u",
16456              logPartPtr.p->logPartNo,
16457              logPartPtr.p->logExecState,
16458              logPartPtr.p->logPartState,
16459              logPartPtr.p->logLap);
16460   }
16461   if (logPartPtr.p->noLogFiles > cmaxLogFilesInPageZero) {
16462     jam();
16463     initGciInLogFileRec(signal, cmaxLogFilesInPageZero);
16464   } else {
16465     jam();
16466     initGciInLogFileRec(signal, logPartPtr.p->noLogFiles);
16467   }//if
16468   releaseLogpage(signal);
16469   /* ------------------------------------------------------------------------
16470    *    NOW WE HAVE FOUND THE LAST LOG FILE. WE ALSO NEED TO FIND THE LAST
16471    *    MBYTE THAT WAS LAST WRITTEN BEFORE THE SYSTEM CRASH.
16472    * ------------------------------------------------------------------------ */
16473   logPartPtr.p->lastLogfile = logFilePtr.i;
16474   readSinglePage(signal, 0);
16475   lfoPtr.p->lfoState = LogFileOperationRecord::READ_SR_LAST_MBYTE;
16476   logFilePtr.p->currentMbyte = 0;
16477   return;
16478 }//Dblqh::readSrLastFileLab()
16479 
readSrLastMbyteLab(Signal * signal)16480 void Dblqh::readSrLastMbyteLab(Signal* signal)
16481 {
16482   if (logPartPtr.p->lastMbyte == ZNIL)
16483   {
16484     if (logPagePtr.p->logPageWord[ZPOS_LOG_LAP] < logPartPtr.p->logLap) {
16485       jam();
16486       logPartPtr.p->lastMbyte = logFilePtr.p->currentMbyte - 1;
16487       if (DEBUG_REDO)
16488       {
16489         ndbout_c("readSrLastMbyteLab part: %u file: %u lastMbyte: %u",
16490                  logPartPtr.p->logPartNo,
16491                  logFilePtr.p->fileNo,
16492                  logPartPtr.p->lastMbyte);
16493       }
16494     }//if
16495   }//if
16496   arrGuard(logFilePtr.p->currentMbyte, clogFileSize);
16497   logFilePtr.p->logMaxGciCompleted[logFilePtr.p->currentMbyte] =
16498     logPagePtr.p->logPageWord[ZPOS_MAX_GCI_COMPLETED];
16499   logFilePtr.p->logMaxGciStarted[logFilePtr.p->currentMbyte] =
16500     logPagePtr.p->logPageWord[ZPOS_MAX_GCI_STARTED];
16501   logFilePtr.p->logLastPrepRef[logFilePtr.p->currentMbyte] =
16502     logPagePtr.p->logPageWord[ZLAST_LOG_PREP_REF];
16503   releaseLogpage(signal);
16504   if (logFilePtr.p->currentMbyte < (clogFileSize - 1)) {
16505     jam();
16506     logFilePtr.p->currentMbyte++;
16507     readSinglePage(signal, ZPAGES_IN_MBYTE * logFilePtr.p->currentMbyte);
16508     lfoPtr.p->lfoState = LogFileOperationRecord::READ_SR_LAST_MBYTE;
16509     return;
16510   } else {
16511     jam();
16512     /* ----------------------------------------------------------------------
16513      *    THE LOG WAS IN THE LAST MBYTE WHEN THE CRASH OCCURRED SINCE ALL
16514      *    LOG LAPS ARE EQUAL TO THE CURRENT LOG LAP.
16515      * ---------------------------------------------------------------------- */
16516     if (logPartPtr.p->lastMbyte == ZNIL) {
16517       jam();
16518       logPartPtr.p->lastMbyte = clogFileSize - 1;
16519     }//if
16520   }//if
16521   logFilePtr.p->logFileStatus = LogFileRecord::CLOSING_SR;
16522   closeFile(signal, logFilePtr, __LINE__);
16523   if (logPartPtr.p->noLogFiles > cmaxLogFilesInPageZero) {
16524     Uint32 fileNo;
16525     if (logFilePtr.p->fileNo >= cmaxLogFilesInPageZero) {
16526       jam();
16527       fileNo = logFilePtr.p->fileNo - cmaxLogFilesInPageZero;
16528     } else {
16529       jam();
16530       fileNo =
16531 	(logPartPtr.p->noLogFiles + logFilePtr.p->fileNo) -
16532 	cmaxLogFilesInPageZero;
16533     }//if
16534     if (fileNo == 0) {
16535       jam();
16536       /* --------------------------------------------------------------------
16537        *  AVOID USING FILE 0 AGAIN SINCE THAT IS PROBABLY CLOSING AT THE
16538        *  MOMENT.
16539        * -------------------------------------------------------------------- */
16540       fileNo = 1;
16541       logPartPtr.p->srRemainingFiles =
16542 	logPartPtr.p->noLogFiles - (cmaxLogFilesInPageZero - 1);
16543     } else {
16544       jam();
16545       logPartPtr.p->srRemainingFiles =
16546 	logPartPtr.p->noLogFiles - cmaxLogFilesInPageZero;
16547     }//if
16548     LogFileRecordPtr locLogFilePtr;
16549     findLogfile(signal, fileNo, logPartPtr, &locLogFilePtr);
16550     locLogFilePtr.p->logFileStatus = LogFileRecord::OPEN_SR_NEXT_FILE;
16551     openFileRw(signal, locLogFilePtr);
16552     return;
16553   }//if
16554   /* ------------------------------------------------------------------------
16555    *   THERE WERE NO NEED TO READ ANY MORE PAGE ZERO IN OTHER FILES.
16556    *   WE NOW HAVE ALL THE NEEDED INFORMATION ABOUT THE GCI'S THAT WE NEED.
16557    *   NOW JUST WAIT FOR CLOSE OPERATIONS TO COMPLETE.
16558    * ------------------------------------------------------------------------ */
16559   return;
16560 }//Dblqh::readSrLastMbyteLab()
16561 
openSrNextFileLab(Signal * signal)16562 void Dblqh::openSrNextFileLab(Signal* signal)
16563 {
16564   readSinglePage(signal, 0);
16565   lfoPtr.p->lfoState = LogFileOperationRecord::READ_SR_NEXT_FILE;
16566   return;
16567 }//Dblqh::openSrNextFileLab()
16568 
readSrNextFileLab(Signal * signal)16569 void Dblqh::readSrNextFileLab(Signal* signal)
16570 {
16571   if (logPartPtr.p->srRemainingFiles > cmaxLogFilesInPageZero) {
16572     jam();
16573     initGciInLogFileRec(signal, cmaxLogFilesInPageZero);
16574   } else {
16575     jam();
16576     initGciInLogFileRec(signal, logPartPtr.p->srRemainingFiles);
16577   }//if
16578   releaseLogpage(signal);
16579   logFilePtr.p->logFileStatus = LogFileRecord::CLOSING_SR;
16580   closeFile(signal, logFilePtr, __LINE__);
16581   if (logPartPtr.p->srRemainingFiles > cmaxLogFilesInPageZero) {
16582     Uint32 fileNo;
16583     if (logFilePtr.p->fileNo >= cmaxLogFilesInPageZero) {
16584       jam();
16585       fileNo = logFilePtr.p->fileNo - cmaxLogFilesInPageZero;
16586     } else {
16587       jam();
16588       fileNo =
16589 	(logPartPtr.p->noLogFiles + logFilePtr.p->fileNo) -
16590 	cmaxLogFilesInPageZero;
16591     }//if
16592     if (fileNo == 0) {
16593       jam();
16594       /* --------------------------------------------------------------------
16595        * AVOID USING FILE 0 AGAIN SINCE THAT IS PROBABLY CLOSING AT THE MOMENT.
16596        * -------------------------------------------------------------------- */
16597       fileNo = 1;
16598       logPartPtr.p->srRemainingFiles =
16599 	logPartPtr.p->srRemainingFiles - (cmaxLogFilesInPageZero - 1);
16600     } else {
16601       jam();
16602       logPartPtr.p->srRemainingFiles =
16603 	logPartPtr.p->srRemainingFiles - cmaxLogFilesInPageZero;
16604     }//if
16605     LogFileRecordPtr locLogFilePtr;
16606     findLogfile(signal, fileNo, logPartPtr, &locLogFilePtr);
16607     locLogFilePtr.p->logFileStatus = LogFileRecord::OPEN_SR_NEXT_FILE;
16608     openFileRw(signal, locLogFilePtr);
16609   }//if
16610   /* ------------------------------------------------------------------------
16611    *   THERE WERE NO NEED TO READ ANY MORE PAGE ZERO IN OTHER FILES.
16612    *   WE NOW HAVE ALL THE NEEDED INFORMATION ABOUT THE GCI'S THAT WE NEED.
16613    *   NOW JUST WAIT FOR CLOSE OPERATIONS TO COMPLETE.
16614    * ------------------------------------------------------------------------ */
16615   return;
16616 }//Dblqh::readSrNextFileLab()
16617 
closingSrLab(Signal * signal)16618 void Dblqh::closingSrLab(Signal* signal)
16619 {
16620   logFilePtr.p->logFileStatus = LogFileRecord::CLOSED;
16621   logPartPtr.i = logFilePtr.p->logPartRec;
16622   ptrCheckGuard(logPartPtr, clogPartFileSize, logPartRecord);
16623   logFilePtr.i = logPartPtr.p->firstLogfile;
16624   do {
16625     jam();
16626     ptrCheckGuard(logFilePtr, clogFileFileSize, logFileRecord);
16627     if (logFilePtr.p->logFileStatus != LogFileRecord::CLOSED) {
16628       jam();
16629       /* --------------------------------------------------------------------
16630        *  EXIT AND WAIT FOR REMAINING LOG FILES TO COMPLETE THEIR WORK.
16631        * -------------------------------------------------------------------- */
16632       return;
16633     }//if
16634     logFilePtr.i = logFilePtr.p->nextLogFile;
16635   } while (logFilePtr.i != logPartPtr.p->firstLogfile);
16636   /* ------------------------------------------------------------------------
16637    *  ALL FILES IN THIS PART HAVE BEEN CLOSED. THIS INDICATES THAT THE FIRST
16638    *  PHASE OF THE SYSTEM RESTART HAVE BEEN CONCLUDED FOR THIS LOG PART.
16639    *  CHECK IF ALL OTHER LOG PARTS ARE ALSO COMPLETED.
16640    * ------------------------------------------------------------------------ */
16641   logPartPtr.p->logPartState = LogPartRecord::SR_FIRST_PHASE_COMPLETED;
16642   for (logPartPtr.i = 0; logPartPtr.i < clogPartFileSize; logPartPtr.i++) {
16643     jam();
16644     ptrAss(logPartPtr, logPartRecord);
16645     if (logPartPtr.p->logPartState != LogPartRecord::SR_FIRST_PHASE_COMPLETED) {
16646       jam();
16647       /* --------------------------------------------------------------------
16648        * EXIT AND WAIT FOR THE REST OF THE LOG PARTS TO COMPLETE.
16649        * -------------------------------------------------------------------- */
16650       return;
16651     }//if
16652   }//for
16653   /* ------------------------------------------------------------------------
16654    *       THE FIRST PHASE HAVE BEEN COMPLETED.
16655    * ------------------------------------------------------------------------ */
16656   signal->theData[0] = ZSR_PHASE3_START;
16657   signal->theData[1] = ZSR_PHASE1_COMPLETED;
16658   sendSignal(cownref, GSN_CONTINUEB, signal, 2, JBB);
16659   return;
16660 }//Dblqh::closingSrLab()
16661 
16662 /* ##########################################################################
16663  * #######                  SYSTEM RESTART PHASE TWO MODULE           #######
16664  *
16665  *  THIS MODULE HANDLES THE SYSTEM RESTART WHERE LQH CONTROLS TUP AND ACC TO
16666  *  ENSURE THAT THEY HAVE KNOWLEDGE OF ALL FRAGMENTS AND HAVE DONE THE NEEDED
16667  *  READING OF DATA FROM FILE AND EXECUTION OF LOCAL LOGS. THIS PROCESS
16668  *  EXECUTES CONCURRENTLY WITH PHASE ONE OF THE SYSTEM RESTART. THIS PHASE
16669  *  FINDS THE INFORMATION ABOUT THE FRAGMENT LOG NEEDED TO EXECUTE THE FRAGMENT
16670  *  LOG.
16671  *  WHEN TUP AND ACC HAVE PREPARED ALL FRAGMENTS THEN LQH ORDERS THOSE LQH'S
16672  *  THAT ARE RESPONSIBLE TO EXECUTE THE FRAGMENT LOGS TO DO SO. IT IS POSSIBLE
16673  *  THAT ANOTHER NODE EXECUTES THE LOG FOR A FRAGMENT RESIDING AT THIS NODE.
16674  * ########################################################################## */
16675 /* ***************>> */
16676 /*  START_FRAGREQ  > */
16677 /* ***************>> */
execSTART_FRAGREQ(Signal * signal)16678 void Dblqh::execSTART_FRAGREQ(Signal* signal)
16679 {
16680   const StartFragReq * const startFragReq = (StartFragReq *)&signal->theData[0];
16681   jamEntry();
16682 
16683   tabptr.i = startFragReq->tableId;
16684   Uint32 fragId = startFragReq->fragId;
16685 
16686   ptrCheckGuard(tabptr, ctabrecFileSize, tablerec);
16687   if (!getFragmentrec(signal, fragId)) {
16688     startFragRefLab(signal);
16689     return;
16690   }//if
16691   tabptr.p->tableStatus = Tablerec::TABLE_DEFINED;
16692 
16693   Uint32 lcpNo = startFragReq->lcpNo;
16694   Uint32 noOfLogNodes = startFragReq->noOfLogNodes;
16695   Uint32 lcpId = startFragReq->lcpId;
16696   Uint32 requestInfo = startFragReq->requestInfo;
16697   if (signal->getLength() < StartFragReq::SignalLength)
16698   {
16699     jam();
16700     requestInfo = StartFragReq::SFR_RESTORE_LCP;
16701   }
16702 
16703   bool doprint = false;
16704 #ifdef ERROR_INSERT
16705   /**
16706    * Always printSTART_FRAG_REQ (for debugging) if ERROR_INSERT is set
16707    */
16708   doprint = true;
16709 #endif
16710   if (doprint || noOfLogNodes > 1)
16711   {
16712     printSTART_FRAG_REQ(stdout, signal->getDataPtr(), signal->getLength(),
16713                         number());
16714   }
16715 
16716   ndbrequire(noOfLogNodes <= MAX_LOG_EXEC);
16717   fragptr.p->fragStatus = Fragrecord::CRASH_RECOVERING;
16718   fragptr.p->srBlockref = startFragReq->userRef;
16719   fragptr.p->srUserptr = startFragReq->userPtr;
16720   fragptr.p->srChkpnr = lcpNo;
16721   if (lcpNo == (MAX_LCP_STORED - 1)) {
16722     jam();
16723     fragptr.p->lcpId[lcpNo] = lcpId;
16724   } else if (lcpNo < (MAX_LCP_STORED - 1)) {
16725     jam();
16726     fragptr.p->lcpId[lcpNo] = lcpId;
16727   } else {
16728     ndbrequire(lcpNo == ZNIL);
16729     jam();
16730   }//if
16731   fragptr.p->srNoLognodes = noOfLogNodes;
16732   fragptr.p->logFlag = Fragrecord::STATE_FALSE;
16733   fragptr.p->srStatus = Fragrecord::SS_IDLE;
16734 
16735   if (requestInfo == StartFragReq::SFR_COPY_FRAG)
16736   {
16737     ndbrequire(lcpNo == ZNIL);
16738     Uint32 n = fragptr.p->srLqhLognode[0] = startFragReq->lqhLogNode[0]; // src
16739     ndbrequire(ndbd_non_trans_copy_frag_req(getNodeInfo(n).m_version));
16740 
16741     // Magic no, meaning to COPY_FRAGREQ instead of read from disk
16742     fragptr.p->srChkpnr = Z8NIL;
16743   }
16744 
16745   if (noOfLogNodes > 0)
16746   {
16747     jam();
16748     for (Uint32 i = 0; i < noOfLogNodes; i++) {
16749       jam();
16750       fragptr.p->srStartGci[i] = startFragReq->startGci[i];
16751       fragptr.p->srLastGci[i] = startFragReq->lastGci[i];
16752       fragptr.p->srLqhLognode[i] = startFragReq->lqhLogNode[i];
16753     }//for
16754     fragptr.p->newestGci = startFragReq->lastGci[noOfLogNodes - 1];
16755   }
16756   else
16757   {
16758     jam();
16759     /**
16760      * This is a really weird piece of code
16761      *   it's probably incorrect, but seems to mask problems...
16762      */
16763     if (cnewestGci > fragptr.p->newestGci)
16764     {
16765       jam();
16766       fragptr.p->newestGci = cnewestGci;
16767     }
16768   }//if
16769 
16770   if (requestInfo == StartFragReq::SFR_COPY_FRAG)
16771   {
16772     jam();
16773   }
16774   else if (lcpNo == ZNIL)
16775   {
16776     jam();
16777     /**
16778      *  THERE WAS NO LOCAL CHECKPOINT AVAILABLE FOR THIS FRAGMENT. WE DO
16779      *  NOT NEED TO READ IN THE LOCAL FRAGMENT.
16780      */
16781     /**
16782      * Or this is not "first" fragment in table
16783      *   RESTORE_LCP_REQ will currently restore all fragments
16784      */
16785     c_lcp_complete_fragments.add(fragptr);
16786 
16787     signal->theData[0] = tabptr.i;
16788     signal->theData[1] = fragId;
16789     BlockReference accRef = calcInstanceBlockRef(DBACC);
16790     sendSignal(accRef, GSN_EXPANDCHECK2, signal, 2, JBB);
16791     c_tup->disk_restart_lcp_id(tabptr.i, fragId, RNIL);
16792     jamEntry();
16793     return;
16794   }
16795   else
16796   {
16797     jam();
16798     c_tup->disk_restart_lcp_id(tabptr.i, fragId, lcpId);
16799     jamEntry();
16800 
16801     if (ERROR_INSERTED(5055))
16802     {
16803       ndbrequire(c_lcpId == 0 || lcpId == 0 || c_lcpId == lcpId);
16804     }
16805 
16806     /**
16807      * Keep track of minimal lcp-id
16808      */
16809     c_lcpId = (c_lcpId == 0 ? lcpId : c_lcpId);
16810     c_lcpId = (c_lcpId < lcpId ? c_lcpId : lcpId);
16811   }
16812 
16813   c_lcp_waiting_fragments.add(fragptr);
16814   if(c_lcp_restoring_fragments.isEmpty())
16815     send_restore_lcp(signal);
16816 }//Dblqh::execSTART_FRAGREQ()
16817 
16818 void
send_restore_lcp(Signal * signal)16819 Dblqh::send_restore_lcp(Signal * signal)
16820 {
16821   c_lcp_waiting_fragments.first(fragptr);
16822   c_lcp_waiting_fragments.remove(fragptr);
16823   c_lcp_restoring_fragments.add(fragptr);
16824 
16825   if (fragptr.p->srChkpnr != Z8NIL)
16826   {
16827     jam();
16828     RestoreLcpReq* req= (RestoreLcpReq*)signal->getDataPtrSend();
16829     req->senderData = fragptr.i;
16830     req->senderRef = reference();
16831     req->tableId = fragptr.p->tabRef;
16832     req->fragmentId = fragptr.p->fragId;
16833     req->lcpNo = fragptr.p->srChkpnr;
16834     req->lcpId = fragptr.p->lcpId[fragptr.p->srChkpnr];
16835     BlockReference restoreRef = calcInstanceBlockRef(RESTORE);
16836     sendSignal(restoreRef, GSN_RESTORE_LCP_REQ, signal,
16837                RestoreLcpReq::SignalLength, JBB);
16838   }
16839   else
16840   {
16841     jam();
16842 
16843     tabptr.i = fragptr.p->tabRef;
16844     ptrCheckGuard(tabptr, ctabrecFileSize, tablerec);
16845 
16846     fragptr.p->fragStatus = Fragrecord::ACTIVE_CREATION;
16847     CopyFragReq * req = CAST_PTR(CopyFragReq, signal->getDataPtrSend());
16848     req->senderData = fragptr.i;
16849     req->senderRef = reference();
16850     req->tableId = fragptr.p->tabRef;
16851     req->fragId = fragptr.p->fragId;
16852     req->nodeId = getOwnNodeId();
16853     req->schemaVersion = tabptr.p->schemaVersion;
16854     req->distributionKey = 0;
16855     req->gci = fragptr.p->lcpId[0];
16856     req->nodeCount = 0;
16857     req->nodeList[1] = CopyFragReq::CFR_NON_TRANSACTIONAL;
16858     Uint32 instanceKey = fragptr.p->lqhInstanceKey;
16859     BlockReference ref = numberToRef(DBLQH, instanceKey,
16860                                      fragptr.p->srLqhLognode[0]);
16861 
16862     sendSignal(ref, GSN_COPY_FRAGREQ, signal,
16863                CopyFragReq::SignalLength, JBB);
16864   }
16865 }
16866 
16867 void
execCOPY_FRAGREF(Signal * signal)16868 Dblqh::execCOPY_FRAGREF(Signal* signal)
16869 {
16870   jamEntry();
16871 
16872   const CopyFragRef * ref = CAST_CONSTPTR(CopyFragRef, signal->getDataPtr());
16873   Uint32 errorCode = ref->errorCode;
16874 
16875   SystemError * sysErr = (SystemError*)&signal->theData[0];
16876   sysErr->errorCode = SystemError::CopyFragRefError;
16877   sysErr->errorRef = reference();
16878   sysErr->data[0] = errorCode;
16879   sysErr->data[1] = 0;
16880   sendSignal(NDBCNTR_REF, GSN_SYSTEM_ERROR, signal,
16881              SystemError::SignalLength, JBB);
16882 }
16883 
16884 void
execCOPY_FRAGCONF(Signal * signal)16885 Dblqh::execCOPY_FRAGCONF(Signal* signal)
16886 {
16887   jamEntry();
16888   {
16889     const CopyFragConf* conf = CAST_CONSTPTR(CopyFragConf,
16890                                              signal->getDataPtr());
16891     c_fragment_pool.getPtr(fragptr, conf->senderData);
16892     fragptr.p->fragStatus = Fragrecord::CRASH_RECOVERING;
16893 
16894     Uint32 rows_lo = conf->rows_lo;
16895     Uint32 bytes_lo = conf->bytes_lo;
16896     signal->theData[0] = NDB_LE_NR_CopyFragDone;
16897     signal->theData[1] = getOwnNodeId();
16898     signal->theData[2] = fragptr.p->tabRef;
16899     signal->theData[3] = fragptr.p->fragId;
16900     signal->theData[4] = rows_lo;
16901     signal->theData[5] = 0;
16902     signal->theData[6] = bytes_lo;
16903     signal->theData[7] = 0;
16904     sendSignal(CMVMI_REF, GSN_EVENT_REP, signal, 8, JBB);
16905   }
16906 
16907   {
16908     RestoreLcpConf* conf= (RestoreLcpConf*)signal->getDataPtr();
16909     conf->senderData = fragptr.i;
16910     execRESTORE_LCP_CONF(signal);
16911   }
16912 }
16913 
startFragRefLab(Signal * signal)16914 void Dblqh::startFragRefLab(Signal* signal)
16915 {
16916   const StartFragReq * const startFragReq = (StartFragReq *)&signal->theData[0];
16917   BlockReference userRef = startFragReq->userRef;
16918   Uint32 userPtr = startFragReq->userPtr;
16919   signal->theData[0] = userPtr;
16920   signal->theData[1] = terrorCode;
16921   signal->theData[2] = cownNodeid;
16922   sendSignal(userRef, GSN_START_FRAGREF, signal, 3, JBB);
16923   return;
16924 }//Dblqh::startFragRefLab()
16925 
execRESTORE_LCP_REF(Signal * signal)16926 void Dblqh::execRESTORE_LCP_REF(Signal* signal)
16927 {
16928   jamEntry();
16929   ndbrequire(false);
16930   return;
16931 }
16932 
execRESTORE_LCP_CONF(Signal * signal)16933 void Dblqh::execRESTORE_LCP_CONF(Signal* signal)
16934 {
16935   jamEntry();
16936   RestoreLcpConf* conf= (RestoreLcpConf*)signal->getDataPtr();
16937   fragptr.i = conf->senderData;
16938   c_fragment_pool.getPtr(fragptr);
16939 
16940   c_lcp_restoring_fragments.remove(fragptr);
16941   c_lcp_complete_fragments.add(fragptr);
16942 
16943   /**
16944    * Disable expand check in ACC
16945    *   before running REDO
16946    */
16947   tabptr.i = fragptr.p->tabRef;
16948   ptrCheckGuard(tabptr, ctabrecFileSize, tablerec);
16949 
16950   signal->theData[0] = fragptr.p->tabRef;
16951   signal->theData[1] = fragptr.p->fragId;
16952   BlockReference accRef = calcInstanceBlockRef(DBACC);
16953   sendSignal(accRef, GSN_EXPANDCHECK2, signal, 2, JBB);
16954 
16955   if (!c_lcp_waiting_fragments.isEmpty())
16956   {
16957     send_restore_lcp(signal);
16958     return;
16959   }
16960 
16961   if (c_lcp_restoring_fragments.isEmpty() &&
16962       cstartRecReq == SRR_START_REC_REQ_ARRIVED)
16963   {
16964     jam();
16965     /* ----------------------------------------------------------------
16966      *  WE HAVE ALSO RECEIVED AN INDICATION THAT NO MORE FRAGMENTS
16967      *  NEEDS RESTART.
16968      *  NOW IT IS TIME TO START EXECUTING THE UNDO LOG.
16969      * ----------------------------------------------------------------
16970      *  WE ARE NOW IN A POSITION TO ORDER TUP AND ACC TO START
16971      *  EXECUTING THEIR UNDO LOGS. THIS MUST BE DONE BEFORE THE
16972      *  FRAGMENT LOGS CAN BE EXECUTED.
16973      * ---------------------------------------------------------------- */
16974     csrExecUndoLogState = EULS_STARTED;
16975     lcpPtr.i = 0;
16976     ptrAss(lcpPtr, lcpRecord);
16977     lcpPtr.p->m_outstanding = 1;
16978 
16979     if (cstartType == NodeState::ST_INITIAL_NODE_RESTART)
16980     {
16981       jam();
16982       /**
16983        * Skip lgman undo...
16984        */
16985       signal->theData[0] = LGMAN_REF;
16986       sendSignal(reference(), GSN_START_RECCONF, signal, 1, JBB);
16987       return;
16988     }
16989 
16990     if (!isNdbMtLqh())
16991     {
16992       jam();
16993       signal->theData[0] = c_lcpId;
16994       sendSignal(LGMAN_REF, GSN_START_RECREQ, signal, 1, JBB);
16995     }
16996     else
16997     {
16998       jam();
16999       signal->theData[0] = c_lcpId;
17000       signal->theData[1] = LGMAN;
17001       sendSignal(DBLQH_REF, GSN_START_RECREQ, signal, 2, JBB);
17002     }
17003     return;
17004   }
17005 }
17006 
17007 /* ***************> */
17008 /*  START_RECREQ  > */
17009 /* ***************> */
execSTART_RECREQ(Signal * signal)17010 void Dblqh::execSTART_RECREQ(Signal* signal)
17011 {
17012   CRASH_INSERTION(5027);
17013 
17014   jamEntry();
17015   StartRecReq * const req = (StartRecReq*)&signal->theData[0];
17016   cmasterDihBlockref = req->senderRef;
17017 
17018   crestartOldestGci = req->keepGci;
17019   crestartNewestGci = req->lastCompletedGci;
17020   cnewestGci = req->newestGci;
17021   cstartRecReqData = req->senderData;
17022 
17023   if (check_ndb_versions())
17024   {
17025     ndbrequire(crestartOldestGci <= crestartNewestGci);
17026   }
17027 
17028   ndbrequire(req->receivingNodeId == cownNodeid);
17029 
17030   cnewestCompletedGci = cnewestGci;
17031   cstartRecReq = SRR_START_REC_REQ_ARRIVED; // StartRecReq has arrived
17032 
17033   if (signal->getLength() == StartRecReq::SignalLength)
17034   {
17035     jam();
17036     NdbNodeBitmask tmp;
17037     tmp.assign(NdbNodeBitmask::Size, req->sr_nodes);
17038     if (!tmp.equal(m_sr_nodes))
17039     {
17040       char buf0[100], buf1[100];
17041       ndbout_c("execSTART_RECREQ chaning srnodes from %s to %s",
17042                m_sr_nodes.getText(buf0),
17043                tmp.getText(buf1));
17044 
17045     }
17046     m_sr_nodes.assign(NdbNodeBitmask::Size, req->sr_nodes);
17047   }
17048   else
17049   {
17050     jam();
17051     cstartRecReqData = RNIL;
17052   }
17053 
17054   for (logPartPtr.i = 0; logPartPtr.i < clogPartFileSize; logPartPtr.i++) {
17055     ptrAss(logPartPtr, logPartRecord);
17056     logPartPtr.p->logPartNewestCompletedGCI = cnewestCompletedGci;
17057   }//for
17058   /* ------------------------------------------------------------------------
17059    *   WE HAVE TO SET THE OLDEST AND THE NEWEST GLOBAL CHECKPOINT IDENTITY
17060    *   THAT WILL SURVIVE THIS SYSTEM RESTART. THIS IS NEEDED SO THAT WE CAN
17061    *   SET THE LOG HEAD AND LOG TAIL PROPERLY BEFORE STARTING THE SYSTEM AGAIN.
17062    *   WE ALSO NEED TO SET CNEWEST_GCI TO ENSURE THAT LOG RECORDS ARE EXECUTED
17063    *   WITH A PROPER GCI.
17064    *------------------------------------------------------------------------ */
17065 
17066   if (c_lcp_restoring_fragments.isEmpty())
17067   {
17068     jam();
17069     csrExecUndoLogState = EULS_STARTED;
17070 
17071     lcpPtr.i = 0;
17072     ptrAss(lcpPtr, lcpRecord);
17073     lcpPtr.p->m_outstanding = 1;
17074 
17075     if (cstartType == NodeState::ST_INITIAL_NODE_RESTART)
17076     {
17077       jam();
17078       /**
17079        * Skip lgman undo...
17080        */
17081       signal->theData[0] = LGMAN_REF;
17082       sendSignal(reference(), GSN_START_RECCONF, signal, 1, JBB);
17083       return;
17084     }
17085 
17086     if (!isNdbMtLqh())
17087     {
17088       jam();
17089       signal->theData[0] = c_lcpId;
17090       sendSignal(LGMAN_REF, GSN_START_RECREQ, signal, 1, JBB);
17091     }
17092     else
17093     {
17094       jam();
17095       signal->theData[0] = c_lcpId;
17096       signal->theData[1] = LGMAN;
17097       sendSignal(DBLQH_REF, GSN_START_RECREQ, signal, 2, JBB);
17098     }
17099   }//if
17100 }//Dblqh::execSTART_RECREQ()
17101 
17102 /* ***************>> */
17103 /*  START_RECCONF  > */
17104 /* ***************>> */
execSTART_RECCONF(Signal * signal)17105 void Dblqh::execSTART_RECCONF(Signal* signal)
17106 {
17107   jamEntry();
17108   lcpPtr.i = 0;
17109   ptrAss(lcpPtr, lcpRecord);
17110   ndbrequire(csrExecUndoLogState == EULS_STARTED);
17111   ndbrequire(lcpPtr.p->m_outstanding);
17112 
17113   Uint32 sender= signal->theData[0];
17114 
17115   if (ERROR_INSERTED(5055))
17116   {
17117     CLEAR_ERROR_INSERT_VALUE;
17118   }
17119 
17120   lcpPtr.p->m_outstanding--;
17121   if(lcpPtr.p->m_outstanding)
17122   {
17123     jam();
17124     return;
17125   }
17126 
17127   switch(refToBlock(sender)){
17128   case TSMAN:
17129     jam();
17130     break;
17131   case LGMAN:
17132     jam();
17133     lcpPtr.p->m_outstanding++;
17134     if (!isNdbMtLqh())
17135     {
17136       jam();
17137       signal->theData[0] = c_lcpId;
17138       sendSignal(TSMAN_REF, GSN_START_RECREQ, signal, 1, JBB);
17139     }
17140     else
17141     {
17142       jam();
17143       signal->theData[0] = c_lcpId;
17144       signal->theData[1] = TSMAN;
17145       sendSignal(DBLQH_REF, GSN_START_RECREQ, signal, 2, JBB);
17146     }
17147     return;
17148     break;
17149   default:
17150     ndbrequire(false);
17151   }
17152 
17153   jam();
17154   csrExecUndoLogState = EULS_COMPLETED;
17155 
17156   if(cstartType == NodeState::ST_INITIAL_NODE_RESTART)
17157   {
17158     jam();
17159     cstartRecReq = SRR_REDO_COMPLETE; // REDO complete
17160 
17161     rebuildOrderedIndexes(signal, 0);
17162     return;
17163   }
17164 
17165   startExecSr(signal);
17166 }
17167 
17168 /* ***************> */
17169 /*  START_RECREF  > */
17170 /* ***************> */
execSTART_RECREF(Signal * signal)17171 void Dblqh::execSTART_RECREF(Signal* signal)
17172 {
17173   jamEntry();
17174   ndbrequire(false);
17175 }//Dblqh::execSTART_RECREF()
17176 
17177 void
rebuildOrderedIndexes(Signal * signal,Uint32 tableId)17178 Dblqh::rebuildOrderedIndexes(Signal* signal, Uint32 tableId)
17179 {
17180   jamEntry();
17181 
17182   if (tableId == 0)
17183   {
17184     jam();
17185     infoEvent("LQH: Starting to rebuild ordered indexes");
17186   }
17187 
17188   if (tableId >= ctabrecFileSize)
17189   {
17190     jam();
17191 
17192     for (logPartPtr.i = 0; logPartPtr.i < clogPartFileSize; logPartPtr.i++)
17193     {
17194       jam();
17195       ptrCheckGuard(logPartPtr, clogPartFileSize, logPartRecord);
17196       LogFileRecordPtr logFile;
17197       logFile.i = logPartPtr.p->currentLogfile;
17198       ptrCheckGuard(logFile, clogFileFileSize, logFileRecord);
17199 
17200       LogPosition head = { logFile.p->fileNo, logFile.p->currentMbyte };
17201       LogPosition tail = { logPartPtr.p->logTailFileNo,
17202                            logPartPtr.p->logTailMbyte};
17203       Uint64 mb = free_log(head, tail, logPartPtr.p->noLogFiles, clogFileSize);
17204       if (mb <= c_free_mb_tail_problem_limit)
17205       {
17206         jam();
17207         update_log_problem(signal, logPartPtr,
17208                            LogPartRecord::P_TAIL_PROBLEM, true);
17209       }
17210     }
17211 
17212     if (!isNdbMtLqh())
17213     {
17214       /**
17215        * There should be no disk-ops in flight here...check it
17216        */
17217       signal->theData[0] = 12003;
17218       sendSignal(LGMAN_REF, GSN_DUMP_STATE_ORD, signal, 1, JBB);
17219     }
17220 
17221     StartRecConf * conf = (StartRecConf*)signal->getDataPtrSend();
17222     conf->startingNodeId = getOwnNodeId();
17223     conf->senderData = cstartRecReqData;
17224     sendSignal(cmasterDihBlockref, GSN_START_RECCONF, signal,
17225                StartRecConf::SignalLength, JBB);
17226 
17227     infoEvent("LQH: Rebuild ordered indexes complete");
17228     return;
17229   }
17230 
17231   tabptr.i = tableId;
17232   ptrCheckGuard(tabptr, ctabrecFileSize, tablerec);
17233   if (! (DictTabInfo::isOrderedIndex(tabptr.p->tableType) &&
17234          tabptr.p->tableStatus == Tablerec::TABLE_DEFINED))
17235   {
17236     jam();
17237     signal->theData[0] = ZREBUILD_ORDERED_INDEXES;
17238     signal->theData[1] = tableId + 1;
17239     sendSignal(reference(), GSN_CONTINUEB, signal, 2, JBB);
17240     return;
17241   }
17242 
17243   signal->theData[0] = NDB_LE_RebuildIndex;
17244   signal->theData[1] = instance();
17245   signal->theData[2] = tableId;
17246   sendSignal(CMVMI_REF, GSN_EVENT_REP, signal, 3, JBB);
17247 
17248   BuildIndxImplReq* const req = (BuildIndxImplReq*)signal->getDataPtrSend();
17249   req->senderRef = reference();
17250   req->senderData = tableId;
17251   req->requestType = BuildIndxImplReq::RF_BUILD_OFFLINE;
17252   req->buildId = 0;     // not yet..
17253   req->buildKey = 0;    // ..in use
17254   req->transId = 0;
17255   req->indexType = tabptr.p->tableType;
17256   req->indexId = tableId;
17257   req->tableId = tabptr.p->primaryTableId;
17258   req->parallelism = 0;
17259   sendSignal(calcInstanceBlockRef(DBTUP), GSN_BUILD_INDX_IMPL_REQ, signal,
17260              BuildIndxImplReq::SignalLength, JBB);
17261 }
17262 
17263 void
execBUILD_INDX_IMPL_REF(Signal * signal)17264 Dblqh::execBUILD_INDX_IMPL_REF(Signal * signal)
17265 {
17266   jamEntry();
17267   ndbrequire(false); // TODO error message
17268 }
17269 
17270 void
execBUILD_INDX_IMPL_CONF(Signal * signal)17271 Dblqh::execBUILD_INDX_IMPL_CONF(Signal* signal)
17272 {
17273   jamEntry();
17274   BuildIndxImplConf * conf = (BuildIndxImplConf*)signal->getDataPtr();
17275   Uint32 tableId = conf->senderData;
17276   rebuildOrderedIndexes(signal, tableId + 1);
17277   infoEvent("LQH: index %u rebuild done", tableId);
17278 }
17279 
17280 /* ***************>> */
17281 /*  START_EXEC_SR  > */
17282 /* ***************>> */
execSTART_EXEC_SR(Signal * signal)17283 void Dblqh::execSTART_EXEC_SR(Signal* signal)
17284 {
17285   jamEntry();
17286   fragptr.i = signal->theData[0];
17287   Uint32 next = RNIL;
17288 
17289   if (fragptr.i == RNIL)
17290   {
17291     jam();
17292     /* ----------------------------------------------------------------------
17293      *    NO MORE FRAGMENTS TO START EXECUTING THE LOG ON.
17294      *    SEND EXEC_SRREQ TO ALL LQH TO INDICATE THAT THIS NODE WILL
17295      *    NOT REQUEST ANY MORE FRAGMENTS TO EXECUTE THE FRAGMENT LOG ON.
17296      * ----------------------------------------------------------------------
17297      *    WE NEED TO SEND THOSE SIGNALS EVEN IF WE HAVE NOT REQUESTED
17298      *    ANY FRAGMENTS PARTICIPATE IN THIS PHASE.
17299      * --------------------------------------------------------------------- */
17300     signal->theData[0] = cownNodeid;
17301     if (!isNdbMtLqh())
17302     {
17303       jam();
17304       NodeReceiverGroup rg(DBLQH, m_sr_nodes);
17305       sendSignal(rg, GSN_EXEC_SRREQ, signal, 1, JBB);
17306     }
17307     else
17308     {
17309       jam();
17310       const Uint32 sz = NdbNodeBitmask::Size;
17311       m_sr_nodes.copyto(sz, &signal->theData[1]);
17312       sendSignal(DBLQH_REF, GSN_EXEC_SRREQ, signal, 1 + sz, JBB);
17313     }
17314     return;
17315   } else {
17316     jam();
17317     c_lcp_complete_fragments.getPtr(fragptr);
17318     next = fragptr.p->nextList;
17319 
17320     if (fragptr.p->srNoLognodes > csrPhasesCompleted)
17321     {
17322       jam();
17323       cnoOutstandingExecFragReq++;
17324 
17325       Uint32 index = csrPhasesCompleted;
17326       arrGuard(index, MAX_LOG_EXEC);
17327       Uint32 Tnode = fragptr.p->srLqhLognode[index];
17328       Uint32 instanceKey = fragptr.p->lqhInstanceKey;
17329       BlockReference ref = numberToRef(DBLQH, instanceKey, Tnode);
17330       fragptr.p->srStatus = Fragrecord::SS_STARTED;
17331 
17332       /* --------------------------------------------------------------------
17333        *  SINCE WE CAN HAVE SEVERAL LQH NODES PER FRAGMENT WE CALCULATE
17334        *  THE LQH POINTER IN SUCH A WAY THAT WE CAN DEDUCE WHICH OF THE
17335        *  LQH NODES THAT HAS RESPONDED WHEN EXEC_FRAGCONF IS RECEIVED.
17336        * ------------------------------------------------------------------- */
17337       ExecFragReq * const execFragReq = (ExecFragReq *)&signal->theData[0];
17338       execFragReq->userPtr = fragptr.i;
17339       execFragReq->userRef = cownref;
17340       execFragReq->tableId = fragptr.p->tabRef;
17341       execFragReq->fragId = fragptr.p->fragId;
17342       execFragReq->startGci = fragptr.p->srStartGci[index];
17343       execFragReq->lastGci = fragptr.p->srLastGci[index];
17344       execFragReq->dst = ref;
17345 
17346       if (isNdbMtLqh())
17347       {
17348         jam();
17349         // send via local proxy
17350         sendSignal(DBLQH_REF, GSN_EXEC_FRAGREQ, signal,
17351                    ExecFragReq::SignalLength, JBB);
17352       }
17353       else if (ndb_route_exec_frag(getNodeInfo(refToNode(ref)).m_version))
17354       {
17355         jam();
17356         // send via remote proxy
17357         sendSignal(numberToRef(DBLQH, refToNode(ref)), GSN_EXEC_FRAGREQ, signal,
17358                    ExecFragReq::SignalLength, JBB);
17359       }
17360       else
17361       {
17362         jam();
17363         // send direct
17364         sendSignal(ref, GSN_EXEC_FRAGREQ, signal,
17365                    ExecFragReq::SignalLength, JBB);
17366       }
17367     }
17368     signal->theData[0] = next;
17369     sendSignal(cownref, GSN_START_EXEC_SR, signal, 1, JBB);
17370   }//if
17371   return;
17372 }//Dblqh::execSTART_EXEC_SR()
17373 
17374 /* ***************> */
17375 /*  EXEC_FRAGREQ  > */
17376 /* ***************> */
17377 /* --------------------------------------------------------------------------
17378  *  THIS SIGNAL IS USED TO REQUEST THAT A FRAGMENT PARTICIPATES IN EXECUTING
17379  *  THE LOG IN THIS NODE.
17380  * ------------------------------------------------------------------------- */
execEXEC_FRAGREQ(Signal * signal)17381 void Dblqh::execEXEC_FRAGREQ(Signal* signal)
17382 {
17383   ExecFragReq * const execFragReq = (ExecFragReq *)&signal->theData[0];
17384   jamEntry();
17385   tabptr.i = execFragReq->tableId;
17386   Uint32 fragId = execFragReq->fragId;
17387   ptrCheckGuard(tabptr, ctabrecFileSize, tablerec);
17388   ndbrequire(getFragmentrec(signal, fragId));
17389 
17390   ndbrequire(fragptr.p->execSrNoReplicas < MAX_REPLICAS);
17391   fragptr.p->execSrBlockref[fragptr.p->execSrNoReplicas] = execFragReq->userRef;
17392   fragptr.p->execSrUserptr[fragptr.p->execSrNoReplicas] = execFragReq->userPtr;
17393   fragptr.p->execSrStartGci[fragptr.p->execSrNoReplicas] = execFragReq->startGci;
17394   fragptr.p->execSrLastGci[fragptr.p->execSrNoReplicas] = execFragReq->lastGci;
17395   fragptr.p->execSrStatus = Fragrecord::ACTIVE;
17396   fragptr.p->execSrNoReplicas++;
17397   cnoFragmentsExecSr++;
17398   return;
17399 }//Dblqh::execEXEC_FRAGREQ()
17400 
sendExecFragRefLab(Signal * signal)17401 void Dblqh::sendExecFragRefLab(Signal* signal)
17402 {
17403   ExecFragReq * const execFragReq = (ExecFragReq *)&signal->theData[0];
17404   BlockReference retRef = execFragReq->userRef;
17405   Uint32 retPtr = execFragReq->userPtr;
17406 
17407   signal->theData[0] = retPtr;
17408   signal->theData[1] = terrorCode;
17409   sendSignal(retRef, GSN_EXEC_FRAGREF, signal, 2, JBB);
17410   return;
17411 }//Dblqh::sendExecFragRefLab()
17412 
17413 /* ***************>> */
17414 /*  EXEC_FRAGCONF  > */
17415 /* ***************>> */
execEXEC_FRAGCONF(Signal * signal)17416 void Dblqh::execEXEC_FRAGCONF(Signal* signal)
17417 {
17418   jamEntry();
17419   fragptr.i = signal->theData[0];
17420   c_fragment_pool.getPtr(fragptr);
17421   fragptr.p->srStatus = Fragrecord::SS_COMPLETED;
17422 
17423   ndbrequire(cnoOutstandingExecFragReq);
17424   cnoOutstandingExecFragReq--;
17425   if (fragptr.p->srNoLognodes == csrPhasesCompleted + 1)
17426   {
17427     jam();
17428 
17429     fragptr.p->logFlag = Fragrecord::STATE_TRUE;
17430     fragptr.p->fragStatus = Fragrecord::FSACTIVE;
17431 
17432     signal->theData[0] = fragptr.p->srUserptr;
17433     signal->theData[1] = cownNodeid;
17434     sendSignal(fragptr.p->srBlockref, GSN_START_FRAGCONF, signal, 2, JBB);
17435   }
17436 
17437   return;
17438 }//Dblqh::execEXEC_FRAGCONF()
17439 
17440 /* ***************> */
17441 /*  EXEC_FRAGREF  > */
17442 /* ***************> */
execEXEC_FRAGREF(Signal * signal)17443 void Dblqh::execEXEC_FRAGREF(Signal* signal)
17444 {
17445   jamEntry();
17446   terrorCode = signal->theData[1];
17447   systemErrorLab(signal, __LINE__);
17448   return;
17449 }//Dblqh::execEXEC_FRAGREF()
17450 
17451 /* *************** */
17452 /*  EXEC_SRCONF  > */
17453 /* *************** */
execEXEC_SRCONF(Signal * signal)17454 void Dblqh::execEXEC_SRCONF(Signal* signal)
17455 {
17456   jamEntry();
17457   Uint32 nodeId = signal->theData[0];
17458   arrGuard(nodeId, MAX_NDB_NODES);
17459   m_sr_exec_sr_conf.set(nodeId);
17460 
17461   if (!m_sr_nodes.equal(m_sr_exec_sr_conf))
17462   {
17463     jam();
17464     /* ------------------------------------------------------------------
17465      *  ALL NODES HAVE NOT REPORTED COMPLETION OF EXECUTING FRAGMENT
17466      *  LOGS YET.
17467      * ----------------------------------------------------------------- */
17468     return;
17469   }
17470 
17471   if (cnoOutstandingExecFragReq != 0)
17472   {
17473     /**
17474      * This should now have been fixed!
17475      *   but could occur during upgrade
17476      * old: wl4391_todo workaround until timing fixed
17477      */
17478     jam();
17479     ndbassert(false);
17480     m_sr_exec_sr_conf.clear(nodeId);
17481     ndbout << "delay: reqs=" << cnoOutstandingExecFragReq << endl;
17482     sendSignalWithDelay(reference(), GSN_EXEC_SRCONF,
17483                         signal, 10, signal->getLength());
17484     return;
17485   }
17486 
17487   /* ------------------------------------------------------------------------
17488    *  CLEAR NODE SYSTEM RESTART EXECUTION STATE TO PREPARE FOR NEXT PHASE OF
17489    *  LOG EXECUTION.
17490    * ----------------------------------------------------------------------- */
17491   m_sr_exec_sr_conf.clear();
17492   cnoFragmentsExecSr = 0;
17493 
17494   /* ------------------------------------------------------------------------
17495    *  NOW CHECK IF ALL FRAGMENTS IN THIS PHASE HAVE COMPLETED. IF SO START THE
17496    *  NEXT PHASE.
17497    * ----------------------------------------------------------------------- */
17498   ndbrequire(cnoOutstandingExecFragReq == 0);
17499 
17500   execSrCompletedLab(signal);
17501   return;
17502 }//Dblqh::execEXEC_SRCONF()
17503 
execSrCompletedLab(Signal * signal)17504 void Dblqh::execSrCompletedLab(Signal* signal)
17505 {
17506   csrPhasesCompleted++;
17507   /* ------------------------------------------------------------------------
17508    *  ALL FRAGMENTS WERE COMPLETED. THIS PHASE IS COMPLETED. IT IS NOW TIME TO
17509    *  START THE NEXT PHASE.
17510    * ----------------------------------------------------------------------- */
17511   if (csrPhasesCompleted >= MAX_LOG_EXEC) {
17512     jam();
17513     /* ----------------------------------------------------------------------
17514      *  THIS WAS THE LAST PHASE. WE HAVE NOW COMPLETED THE EXECUTION THE
17515      *  FRAGMENT LOGS IN ALL NODES. BEFORE WE SEND START_RECCONF TO THE
17516      *  MASTER DIH TO INDICATE A COMPLETED SYSTEM RESTART IT IS NECESSARY
17517      *  TO FIND THE HEAD AND THE TAIL OF THE LOG WHEN NEW OPERATIONS START
17518      *  TO COME AGAIN.
17519      *
17520      * THE FIRST STEP IS TO FIND THE HEAD AND TAIL MBYTE OF EACH LOG PART.
17521      * TO DO THIS WE REUSE THE CONTINUEB SIGNAL SR_LOG_LIMITS. THEN WE
17522      * HAVE TO FIND THE ACTUAL PAGE NUMBER AND PAGE INDEX WHERE TO
17523      * CONTINUE WRITING THE LOG AFTER THE SYSTEM RESTART.
17524      * --------------------------------------------------------------------- */
17525     for (logPartPtr.i = 0; logPartPtr.i < clogPartFileSize; logPartPtr.i++) {
17526       jam();
17527       ptrAss(logPartPtr, logPartRecord);
17528       logPartPtr.p->logPartState = LogPartRecord::SR_FOURTH_PHASE_STARTED;
17529       logPartPtr.p->logLastGci = crestartNewestGci;
17530       logPartPtr.p->logStartGci = crestartOldestGci;
17531       logPartPtr.p->logExecState = LogPartRecord::LES_SEARCH_STOP;
17532       if (logPartPtr.p->headFileNo == ZNIL) {
17533         jam();
17534 	/* -----------------------------------------------------------------
17535 	 *  IF WE HAVEN'T FOUND ANY HEAD OF THE LOG THEN WE ARE IN SERIOUS
17536 	 *  PROBLEM.  THIS SHOULD NOT OCCUR. IF IT OCCURS ANYWAY THEN WE
17537 	 *  HAVE TO FIND A CURE FOR THIS PROBLEM.
17538 	 * ----------------------------------------------------------------- */
17539         systemErrorLab(signal, __LINE__);
17540         return;
17541       }//if
17542 
17543       if (DEBUG_REDO)
17544       {
17545         ndbout_c("part: %u srLogLimits SR_FOURTH_PHASE %u-%u (file: %u mb: %u)",
17546                  logPartPtr.p->logPartNo,
17547                  logPartPtr.p->logStartGci,
17548                  logPartPtr.p->logLastGci,
17549                  logPartPtr.p->lastLogfile,
17550                  logPartPtr.p->lastMbyte);
17551       }
17552 
17553       signal->theData[0] = ZSR_LOG_LIMITS;
17554       signal->theData[1] = logPartPtr.i;
17555       signal->theData[2] = logPartPtr.p->lastLogfile;
17556       signal->theData[3] = logPartPtr.p->lastMbyte;
17557       sendSignal(cownref, GSN_CONTINUEB, signal, 4, JBB);
17558     }//for
17559     return;
17560   } else {
17561     jam();
17562     /* ----------------------------------------------------------------------
17563      *   THERE ARE YET MORE PHASES TO RESTART.
17564      *   WE MUST INITIALISE DATA FOR NEXT PHASE AND SEND START SIGNAL.
17565      * --------------------------------------------------------------------- */
17566     csrPhaseStarted = ZSR_PHASE1_COMPLETED; // Set correct state first...
17567     startExecSr(signal);
17568   }//if
17569   return;
17570 }//Dblqh::execSrCompletedLab()
17571 
17572 /* ************>> */
17573 /*  EXEC_SRREQ  > */
17574 /* ************>> */
execEXEC_SRREQ(Signal * signal)17575 void Dblqh::execEXEC_SRREQ(Signal* signal)
17576 {
17577   jamEntry();
17578   Uint32 nodeId = signal->theData[0];
17579   ndbrequire(nodeId < MAX_NDB_NODES);
17580   m_sr_exec_sr_req.set(nodeId);
17581   if (!m_sr_exec_sr_req.equal(m_sr_nodes))
17582   {
17583     jam();
17584     return;
17585   }
17586 
17587   /* ------------------------------------------------------------------------
17588    *  CLEAR NODE SYSTEM RESTART STATE TO PREPARE FOR NEXT PHASE OF LOG
17589    *  EXECUTION
17590    * ----------------------------------------------------------------------- */
17591   m_sr_exec_sr_req.clear();
17592 
17593   if (csrPhasesCompleted != 0) {
17594     /* ----------------------------------------------------------------------
17595      *       THE FIRST PHASE MUST ALWAYS EXECUTE THE LOG.
17596      * --------------------------------------------------------------------- */
17597     if (cnoFragmentsExecSr == 0) {
17598       jam();
17599       /* --------------------------------------------------------------------
17600        *  THERE WERE NO FRAGMENTS THAT NEEDED TO EXECUTE THE LOG IN THIS PHASE.
17601        * ------------------------------------------------------------------- */
17602       srPhase3Comp(signal);
17603       return;
17604     }//if
17605   }//if
17606   /* ------------------------------------------------------------------------
17607    *  NOW ALL NODES HAVE SENT ALL EXEC_FRAGREQ. NOW WE CAN START EXECUTING THE
17608    *  LOG FROM THE MINIMUM GCI NEEDED UNTIL THE MAXIMUM GCI NEEDED.
17609    *
17610    *  WE MUST FIRST CHECK IF THE FIRST PHASE OF THE SYSTEM RESTART HAS BEEN
17611    *  COMPLETED. THIS HANDLING IS PERFORMED IN THE FILE SYSTEM MODULE
17612    * ----------------------------------------------------------------------- */
17613   signal->theData[0] = ZSR_PHASE3_START;
17614   signal->theData[1] = ZSR_PHASE2_COMPLETED;
17615   sendSignal(cownref, GSN_CONTINUEB, signal, 2, JBB);
17616   return;
17617 }//Dblqh::execEXEC_SRREQ()
17618 
17619 /* ######################################################################### */
17620 /*       SYSTEM RESTART PHASE THREE MODULE                                   */
17621 /*       THIS MODULE IS A SUB-MODULE OF THE FILE SYSTEM HANDLING.            */
17622 /*                                                                           */
17623 /* THIS MODULE IS CONCERNED WITH EXECUTING THE FRAGMENT LOG. IT DOES ALSO    */
17624 /* CONTAIN SIGNAL RECEPTIONS LQHKEYCONF AND LQHKEYREF SINCE LQHKEYREQ IS USED*/
17625 /* TO EXECUTE THE LOG RECORDS.                                               */
17626 /*                                                                           */
17627 /* BEFORE IT STARTS IT HAS BEEN DECIDED WHERE TO START AND WHERE TO STOP     */
17628 /* READING THE FRAGMENT LOG BY USING THE INFORMATION ABOUT GCI DISCOVERED IN */
17629 /* PHASE ONE OF THE SYSTEM RESTART.                                          */
17630 /* ######################################################################### */
17631 /*---------------------------------------------------------------------------*/
17632 /* PHASE THREE OF THE SYSTEM RESTART CAN NOW START. ONE OF THE PHASES HAVE   */
17633 /* COMPLETED.                                                                */
17634 /*---------------------------------------------------------------------------*/
srPhase3Start(Signal * signal)17635 void Dblqh::srPhase3Start(Signal* signal)
17636 {
17637   UintR tsrPhaseStarted;
17638 
17639   jamEntry();
17640 
17641   tsrPhaseStarted = signal->theData[1];
17642   if (csrPhaseStarted == ZSR_NO_PHASE_STARTED) {
17643     jam();
17644     csrPhaseStarted = tsrPhaseStarted;
17645     return;
17646   }//if
17647   ndbrequire(csrPhaseStarted != tsrPhaseStarted);
17648   ndbrequire(csrPhaseStarted != ZSR_BOTH_PHASES_STARTED);
17649 
17650   csrPhaseStarted = ZSR_BOTH_PHASES_STARTED;
17651   for (logPartPtr.i = 0; logPartPtr.i < clogPartFileSize; logPartPtr.i++) {
17652     jam();
17653     ptrAss(logPartPtr, logPartRecord);
17654     logPartPtr.p->logPartState = LogPartRecord::SR_THIRD_PHASE_STARTED;
17655     logPartPtr.p->logStartGci = (UintR)-1;
17656     if (csrPhasesCompleted == 0) {
17657       jam();
17658       /* --------------------------------------------------------------------
17659        *  THE FIRST PHASE WE MUST ENSURE THAT IT REACHES THE END OF THE LOG.
17660        * ------------------------------------------------------------------- */
17661       logPartPtr.p->logLastGci = crestartNewestGci;
17662     } else {
17663       jam();
17664       logPartPtr.p->logLastGci = 2;
17665     }//if
17666   }//for
17667 
17668   jam();
17669   c_lcp_complete_fragments.first(fragptr);
17670   signal->theData[0] = ZSR_GCI_LIMITS;
17671   signal->theData[1] = fragptr.i;
17672   sendSignal(cownref, GSN_CONTINUEB, signal, 2, JBB);
17673   return;
17674 }//Dblqh::srPhase3Start()
17675 
17676 /* --------------------------------------------------------------------------
17677  *   WE NOW WE NEED TO FIND THE LIMITS WITHIN WHICH TO EXECUTE
17678  *   THE FRAGMENT LOG
17679  * ------------------------------------------------------------------------- */
srGciLimits(Signal * signal)17680 void Dblqh::srGciLimits(Signal* signal)
17681 {
17682   jamEntry();
17683   fragptr.i = signal->theData[0];
17684   Uint32 loopCount = 0;
17685   logPartPtr.i = 0;
17686   ptrAss(logPartPtr, logPartRecord);
17687   while (fragptr.i != RNIL){
17688     jam();
17689     c_lcp_complete_fragments.getPtr(fragptr);
17690     ndbrequire(fragptr.p->execSrNoReplicas - 1 < MAX_REPLICAS);
17691     for (Uint32 i = 0; i < fragptr.p->execSrNoReplicas; i++) {
17692       jam();
17693       if (fragptr.p->execSrStartGci[i] < logPartPtr.p->logStartGci) {
17694 	jam();
17695 	logPartPtr.p->logStartGci = fragptr.p->execSrStartGci[i];
17696       }//if
17697       if (fragptr.p->execSrLastGci[i] > logPartPtr.p->logLastGci) {
17698 	jam();
17699 	logPartPtr.p->logLastGci = fragptr.p->execSrLastGci[i];
17700       }
17701     }
17702 
17703     loopCount++;
17704     if (loopCount > 20) {
17705       jam();
17706       signal->theData[0] = ZSR_GCI_LIMITS;
17707       signal->theData[1] = fragptr.p->nextList;
17708       sendSignal(cownref, GSN_CONTINUEB, signal, 2, JBB);
17709       return;
17710     } else {
17711       jam();
17712       fragptr.i = fragptr.p->nextList;
17713     }//if
17714   }
17715 
17716   if (logPartPtr.p->logStartGci == (UintR)-1) {
17717     jam();
17718       /* --------------------------------------------------------------------
17719        *  THERE WERE NO FRAGMENTS TO INSTALL WE WILL EXECUTE THE LOG AS
17720        *  SHORT AS POSSIBLE TO REACH THE END OF THE LOG. THIS WE DO BY
17721        *  STARTING AT THE STOP GCI.
17722        * ------------------------------------------------------------------- */
17723     logPartPtr.p->logStartGci = logPartPtr.p->logLastGci;
17724   }//if
17725 
17726   for(Uint32 i = 1; i < clogPartFileSize; i++)
17727   {
17728     LogPartRecordPtr tmp;
17729     tmp.i = i;
17730     ptrAss(tmp, logPartRecord);
17731     tmp.p->logStartGci = logPartPtr.p->logStartGci;
17732     tmp.p->logLastGci = logPartPtr.p->logLastGci;
17733   }
17734 
17735   for (logPartPtr.i = 0; logPartPtr.i < clogPartFileSize; logPartPtr.i++) {
17736     jam();
17737     ptrAss(logPartPtr, logPartRecord);
17738     logPartPtr.p->logExecState = LogPartRecord::LES_SEARCH_STOP;
17739     if (DEBUG_REDO)
17740     {
17741       ndbout_c("part: %u srLogLimits (srGciLimits) %u-%u (file: %u mb: %u)",
17742                logPartPtr.p->logPartNo,
17743                logPartPtr.p->logStartGci,
17744                logPartPtr.p->logLastGci,
17745                logPartPtr.p->lastLogfile,
17746                logPartPtr.p->lastMbyte);
17747     }
17748     signal->theData[0] = ZSR_LOG_LIMITS;
17749     signal->theData[1] = logPartPtr.i;
17750     signal->theData[2] = logPartPtr.p->lastLogfile;
17751     signal->theData[3] = logPartPtr.p->lastMbyte;
17752     sendSignal(cownref, GSN_CONTINUEB, signal, 4, JBB);
17753   }//for
17754 }//Dblqh::srGciLimits()
17755 
17756 /* --------------------------------------------------------------------------
17757  *       IT IS NOW TIME TO FIND WHERE TO START EXECUTING THE LOG.
17758  *       THIS SIGNAL IS SENT FOR EACH LOG PART AND STARTS THE EXECUTION
17759  *       OF THE LOG FOR THIS PART.
17760  *-------------------------------------------------------------------------- */
srLogLimits(Signal * signal)17761 void Dblqh::srLogLimits(Signal* signal)
17762 {
17763   Uint32 tlastPrepRef;
17764   Uint32 tmbyte;
17765 
17766   jamEntry();
17767   logPartPtr.i = signal->theData[0];
17768   ptrCheckGuard(logPartPtr, clogPartFileSize, logPartRecord);
17769   logFilePtr.i = signal->theData[1];
17770   ptrCheckGuard(logFilePtr, clogFileFileSize, logFileRecord);
17771   tmbyte = signal->theData[2];
17772   Uint32 loopCount = 0;
17773   /* ------------------------------------------------------------------------
17774    *   WE ARE SEARCHING FOR THE START AND STOP MBYTE OF THE LOG THAT IS TO BE
17775    *   EXECUTED.
17776    * ----------------------------------------------------------------------- */
17777   while(true) {
17778     ndbrequire(tmbyte < clogFileSize);
17779     if (logPartPtr.p->logExecState == LogPartRecord::LES_SEARCH_STOP)
17780     {
17781       if (logFilePtr.p->logMaxGciCompleted[tmbyte] <= logPartPtr.p->logLastGci)
17782       {
17783         jam();
17784         /* --------------------------------------------------------------------
17785          *  WE ARE STEPPING BACKWARDS FROM MBYTE TO MBYTE. THIS IS THE FIRST
17786          *  MBYTE WHICH IS TO BE INCLUDED IN THE LOG EXECUTION. THE STOP GCI
17787          *  HAS NOT BEEN COMPLETED BEFORE THIS MBYTE. THUS THIS MBYTE HAVE
17788          *  TO BE EXECUTED.
17789          * ------------------------------------------------------------------ */
17790         logPartPtr.p->stopLogfile = logFilePtr.i;
17791         logPartPtr.p->stopMbyte = tmbyte;
17792         logPartPtr.p->logExecState = LogPartRecord::LES_SEARCH_START;
17793         if (DEBUG_REDO)
17794         {
17795           ndbout_c("part: %u srLogLimits found stop pos file: %u mb: %u logMaxGciCompleted[tmbyte]: %u (lastGci: %u)",
17796                    logPartPtr.p->logPartNo,
17797                    logFilePtr.p->fileNo,
17798                    tmbyte,
17799                    logFilePtr.p->logMaxGciCompleted[tmbyte],
17800                    logPartPtr.p->logLastGci);
17801         }
17802       }//if
17803       else if (DEBUG_REDO)
17804       {
17805         ndbout_c("SEARCH STOP SKIP part: %u file: %u mb: %u "
17806                  "logMaxGciCompleted: %u > %u",
17807                  logPartPtr.p->logPartNo,
17808                  logFilePtr.p->fileNo,
17809                  tmbyte,
17810                  logFilePtr.p->logMaxGciCompleted[tmbyte],
17811                  logPartPtr.p->logLastGci);
17812       }
17813     }//if
17814     /* ------------------------------------------------------------------------
17815      *  WHEN WE HAVEN'T FOUND THE STOP MBYTE IT IS NOT NECESSARY TO LOOK FOR THE
17816      *  START MBYTE. THE REASON IS THE FOLLOWING LOGIC CHAIN:
17817      *    MAX_GCI_STARTED >= MAX_GCI_COMPLETED >= LAST_GCI >= START_GCI
17818      *  THUS MAX_GCI_STARTED >= START_GCI. THUS MAX_GCI_STARTED < START_GCI CAN
17819      *  NOT BE TRUE AS WE WILL CHECK OTHERWISE.
17820      * ---------------------------------------------------------------------- */
17821     if (logPartPtr.p->logExecState == LogPartRecord::LES_SEARCH_START)
17822     {
17823       if (logFilePtr.p->logMaxGciStarted[tmbyte] < logPartPtr.p->logStartGci)
17824       {
17825         jam();
17826         /* --------------------------------------------------------------------
17827          *  WE HAVE NOW FOUND THE START OF THE EXECUTION OF THE LOG.
17828          *  WE STILL HAVE TO MOVE IT BACKWARDS TO ALSO INCLUDE THE
17829          *  PREPARE RECORDS WHICH WERE STARTED IN A PREVIOUS MBYTE.
17830          * ------------------------------------------------------------------ */
17831         if (DEBUG_REDO)
17832         {
17833           ndbout_c("part: %u srLogLimits found start pos file: %u mb: %u logMaxGciStarted[tmbyte]: %u (startGci: %u)",
17834                    logPartPtr.p->logPartNo,
17835                    logFilePtr.p->fileNo,
17836                    tmbyte,
17837                    logFilePtr.p->logMaxGciCompleted[tmbyte],
17838                    logPartPtr.p->logStartGci);
17839           ndbout_c("part: %u srLogLimits lastPrepRef => file: %u mb: %u",
17840                    logPartPtr.p->logPartNo,
17841                    logFilePtr.p->logLastPrepRef[tmbyte] >> 16,
17842                    logFilePtr.p->logLastPrepRef[tmbyte] & 65535);
17843         }
17844         tlastPrepRef = logFilePtr.p->logLastPrepRef[tmbyte];
17845         logPartPtr.p->startMbyte = tlastPrepRef & 65535;
17846         LogFileRecordPtr locLogFilePtr;
17847         findLogfile(signal, tlastPrepRef >> 16, logPartPtr, &locLogFilePtr);
17848         logPartPtr.p->startLogfile = locLogFilePtr.i;
17849         logPartPtr.p->logExecState = LogPartRecord::LES_EXEC_LOG;
17850       }
17851       else if (DEBUG_REDO)
17852       {
17853         ndbout_c("SEARCH START SKIP part: %u file: %u mb: %u "
17854                  "logMaxGciCompleted: %u >= %u",
17855                  logPartPtr.p->logPartNo,
17856                  logFilePtr.p->fileNo,
17857                  tmbyte,
17858                  logFilePtr.p->logMaxGciStarted[tmbyte],
17859                  logPartPtr.p->logStartGci);
17860       }
17861     }//if
17862     if (logPartPtr.p->logExecState != LogPartRecord::LES_EXEC_LOG) {
17863       if (tmbyte == 0) {
17864         jam();
17865         tmbyte = clogFileSize - 1;
17866         logFilePtr.i = logFilePtr.p->prevLogFile;
17867         ptrCheckGuard(logFilePtr, clogFileFileSize, logFileRecord);
17868       } else {
17869         jam();
17870         tmbyte--;
17871       }//if
17872       if (logPartPtr.p->lastLogfile == logFilePtr.i) {
17873         ndbrequire(logPartPtr.p->lastMbyte != tmbyte);
17874       }//if
17875       if (loopCount > 20) {
17876         jam();
17877         signal->theData[0] = ZSR_LOG_LIMITS;
17878         signal->theData[1] = logPartPtr.i;
17879         signal->theData[2] = logFilePtr.i;
17880         signal->theData[3] = tmbyte;
17881         sendSignal(cownref, GSN_CONTINUEB, signal, 4, JBB);
17882         return;
17883       }//if
17884       loopCount++;
17885     } else {
17886       jam();
17887       break;
17888     }//if
17889   }//while
17890 
17891   if (DEBUG_REDO)
17892   {
17893     LogFileRecordPtr tmp;
17894     tmp.i = logPartPtr.p->stopLogfile;
17895     ptrCheckGuard(tmp, clogFileFileSize, logFileRecord);
17896     ndbout_c("srLogLimits part: %u gci: %u-%u start file: %u mb: %u stop file: %u mb: %u",
17897              logPartPtr.p->logPartNo,
17898              logPartPtr.p->logStartGci,
17899              logPartPtr.p->logLastGci,
17900              tlastPrepRef >> 16,
17901              tlastPrepRef & 65535,
17902              tmp.p->fileNo,
17903              logPartPtr.p->stopMbyte);
17904   }
17905 
17906 
17907 
17908   /* ------------------------------------------------------------------------
17909    *  WE HAVE NOW FOUND BOTH THE START AND THE STOP OF THE LOG. NOW START
17910    *  EXECUTING THE LOG. THE FIRST ACTION IS TO OPEN THE LOG FILE WHERE TO
17911    *  START EXECUTING THE LOG.
17912    * ----------------------------------------------------------------------- */
17913   if (logPartPtr.p->logPartState == LogPartRecord::SR_THIRD_PHASE_STARTED) {
17914     jam();
17915     logFilePtr.i = logPartPtr.p->startLogfile;
17916     ptrCheckGuard(logFilePtr, clogFileFileSize, logFileRecord);
17917     logFilePtr.p->logFileStatus = LogFileRecord::OPEN_EXEC_SR_START;
17918     openFileRw(signal, logFilePtr);
17919     send_runredo_event(signal, logPartPtr.p, logPartPtr.p->logStartGci);
17920   } else {
17921     jam();
17922     ndbrequire(logPartPtr.p->logPartState == LogPartRecord::SR_FOURTH_PHASE_STARTED);
17923       /* --------------------------------------------------------------------
17924        *  WE HAVE NOW FOUND THE TAIL MBYTE IN THE TAIL FILE.
17925        *  SET THOSE PARAMETERS IN THE LOG PART.
17926        *  WE HAVE ALSO FOUND THE HEAD MBYTE. WE STILL HAVE TO SEARCH
17927        *  FOR THE PAGE NUMBER AND PAGE INDEX WHERE TO SET THE HEAD.
17928        * ------------------------------------------------------------------- */
17929     logFilePtr.i = logPartPtr.p->startLogfile;
17930     ptrCheckGuard(logFilePtr, clogFileFileSize, logFileRecord);
17931     logPartPtr.p->logTailFileNo = logFilePtr.p->fileNo;
17932     logPartPtr.p->logTailMbyte = logPartPtr.p->startMbyte;
17933       /* --------------------------------------------------------------------
17934        *  THE HEAD WE ACTUALLY FOUND DURING EXECUTION OF LOG SO WE USE
17935        *  THIS INFO HERE RATHER THAN THE MBYTE WE FOUND TO BE THE HEADER.
17936        * ------------------------------------------------------------------- */
17937     LogFileRecordPtr locLogFilePtr;
17938     findLogfile(signal, logPartPtr.p->headFileNo, logPartPtr, &locLogFilePtr);
17939     locLogFilePtr.p->logFileStatus = LogFileRecord::OPEN_SR_FOURTH_PHASE;
17940     openFileRw(signal, locLogFilePtr);
17941   }//if
17942   return;
17943 }//Dblqh::srLogLimits()
17944 
openExecSrStartLab(Signal * signal)17945 void Dblqh::openExecSrStartLab(Signal* signal)
17946 {
17947   logPartPtr.p->currentLogfile = logFilePtr.i;
17948   logFilePtr.p->currentMbyte = logPartPtr.p->startMbyte;
17949   /* ------------------------------------------------------------------------
17950    *     WE NEED A TC CONNECT RECORD TO HANDLE EXECUTION OF LOG RECORDS.
17951    * ------------------------------------------------------------------------ */
17952   seizeTcrec();
17953   logPartPtr.p->logTcConrec = tcConnectptr.i;
17954   /* ------------------------------------------------------------------------
17955    *   THE FIRST LOG RECORD TO EXECUTE IS ALWAYS AT A NEW MBYTE.
17956    *   SET THE NUMBER OF PAGES IN THE MAIN MEMORY BUFFER TO ZERO AS AN INITIAL
17957    *   VALUE. THIS VALUE WILL BE UPDATED AND ENSURED THAT IT RELEASES PAGES IN
17958    *   THE SUBROUTINE READ_EXEC_SR.
17959    * ----------------------------------------------------------------------- */
17960   logPartPtr.p->mmBufferSize = 0;
17961   readExecSrNewMbyte(signal);
17962   return;
17963 }//Dblqh::openExecSrStartLab()
17964 
17965 /* ---------------------------------------------------------------------------
17966  *  WE WILL ALWAYS ENSURE THAT WE HAVE AT LEAST 16 KBYTE OF LOG PAGES WHEN WE
17967  *  START READING A LOG RECORD. THE ONLY EXCEPTION IS WHEN WE COME CLOSE TO A
17968  *  MBYTE BOUNDARY. SINCE WE KNOW THAT LOG RECORDS ARE NEVER WRITTEN ACROSS A
17969  *  MBYTE BOUNDARY THIS IS NOT A PROBLEM.
17970  *
17971  *  WE START BY READING 64 KBYTE BEFORE STARTING TO EXECUTE THE LOG RECORDS.
17972  *  WHEN WE COME BELOW 64 KBYTE WE READ ANOTHER SET OF LOG PAGES. WHEN WE
17973  *  GO BELOW 16 KBYTE WE WAIT UNTIL THE READ PAGES HAVE ENTERED THE BLOCK.
17974  * ------------------------------------------------------------------------- */
17975 /* --------------------------------------------------------------------------
17976  *       NEW PAGES FROM LOG FILE DURING EXECUTION OF LOG HAS ARRIVED.
17977  * ------------------------------------------------------------------------- */
readExecSrLab(Signal * signal)17978 void Dblqh::readExecSrLab(Signal* signal)
17979 {
17980   buildLinkedLogPageList(signal);
17981   /* ------------------------------------------------------------------------
17982    *   WE NEED TO SET THE CURRENT PAGE INDEX OF THE FIRST PAGE SINCE IT CAN BE
17983    *   USED IMMEDIATELY WITHOUT ANY OTHER INITIALISATION. THE REST OF THE PAGES
17984    *   WILL BE INITIALISED BY READ_LOGWORD.
17985    * ----------------------------------------------------------------------- */
17986   logPagePtr.p->logPageWord[ZCURR_PAGE_INDEX] = ZPAGE_HEADER_SIZE;
17987   if (logPartPtr.p->logExecState ==
17988       LogPartRecord::LES_WAIT_READ_EXEC_SR_NEW_MBYTE) {
17989     jam();
17990     /* ----------------------------------------------------------------------
17991      *  THIS IS THE FIRST READ DURING THE EXECUTION OF THIS MBYTE. SET THE
17992      *  NEW CURRENT LOG PAGE TO THE FIRST OF THESE PAGES. CHANGE
17993      *  LOG_EXEC_STATE TO ENSURE THAT WE START EXECUTION OF THE LOG.
17994      * --------------------------------------------------------------------- */
17995     logFilePtr.p->currentFilepage = logFilePtr.p->currentMbyte *
17996                                     ZPAGES_IN_MBYTE;
17997     logPartPtr.p->prevFilepage = logFilePtr.p->currentFilepage;
17998     logFilePtr.p->currentLogpage = lfoPtr.p->firstLfoPage;
17999     logPartPtr.p->prevLogpage = logFilePtr.p->currentLogpage;
18000   }//if
18001   moveToPageRef(signal);
18002   releaseLfo(signal);
18003   /* ------------------------------------------------------------------------
18004    *  NOW WE HAVE COMPLETED THE RECEPTION OF THESE PAGES.
18005    *  NOW CHECK IF WE NEED TO READ MORE PAGES.
18006    * ----------------------------------------------------------------------- */
18007   checkReadExecSr(signal);
18008   if (logPartPtr.p->logExecState == LogPartRecord::LES_EXEC_LOG) {
18009     jam();
18010     signal->theData[0] = ZEXEC_SR;
18011     signal->theData[1] = logPartPtr.i;
18012     sendSignal(cownref, GSN_CONTINUEB, signal, 2, JBB);
18013     return;
18014   }//if
18015   return;
18016 }//Dblqh::readExecSrLab()
18017 
openExecSrNewMbyteLab(Signal * signal)18018 void Dblqh::openExecSrNewMbyteLab(Signal* signal)
18019 {
18020   readExecSrNewMbyte(signal);
18021   return;
18022 }//Dblqh::openExecSrNewMbyteLab()
18023 
closeExecSrLab(Signal * signal)18024 void Dblqh::closeExecSrLab(Signal* signal)
18025 {
18026   LogFileRecordPtr locLogFilePtr;
18027   logFilePtr.p->logFileStatus = LogFileRecord::CLOSED;
18028   logPartPtr.i = logFilePtr.p->logPartRec;
18029   ptrCheckGuard(logPartPtr, clogPartFileSize, logPartRecord);
18030   locLogFilePtr.i = logPartPtr.p->currentLogfile;
18031   ptrCheckGuard(locLogFilePtr, clogFileFileSize, logFileRecord);
18032   locLogFilePtr.p->logFileStatus = LogFileRecord::OPEN_EXEC_SR_NEW_MBYTE;
18033   openFileRw(signal, locLogFilePtr);
18034   return;
18035 }//Dblqh::closeExecSrLab()
18036 
writeDirtyLab(Signal * signal)18037 void Dblqh::writeDirtyLab(Signal* signal)
18038 {
18039   releaseLfo(signal);
18040   signal->theData[0] = logPartPtr.i;
18041   execSr(signal);
18042   return;
18043 }//Dblqh::writeDirtyLab()
18044 
18045 /* --------------------------------------------------------------------------
18046  *       EXECUTE A LOG RECORD WITHIN THE CURRENT MBYTE.
18047  * ------------------------------------------------------------------------- */
execSr(Signal * signal)18048 void Dblqh::execSr(Signal* signal)
18049 {
18050   LogFileRecordPtr nextLogFilePtr;
18051   LogPageRecordPtr tmpLogPagePtr;
18052   Uint32 logWord;
18053   Uint32 line;
18054   const char * crash_msg = 0;
18055 
18056   jamEntry();
18057   logPartPtr.i = signal->theData[0];
18058   ptrCheckGuard(logPartPtr, clogPartFileSize, logPartRecord);
18059 
18060   do {
18061     jam();
18062     logFilePtr.i = logPartPtr.p->currentLogfile;
18063     ptrCheckGuard(logFilePtr, clogFileFileSize, logFileRecord);
18064     logPagePtr.i = logPartPtr.p->prevLogpage;
18065     ptrCheckGuard(logPagePtr, clogPageFileSize, logPageRecord);
18066     if (logPagePtr.p->logPageWord[ZPOS_DIRTY] == ZDIRTY) {
18067       jam();
18068       switch (logPartPtr.p->logExecState) {
18069       case LogPartRecord::LES_EXEC_LOG_COMPLETED:
18070       case LogPartRecord::LES_EXEC_LOG_NEW_FILE:
18071       case LogPartRecord::LES_EXEC_LOG_NEW_MBYTE:
18072         jam();
18073 	/* ------------------------------------------------------------------
18074 	 *  IN THIS WE HAVE COMPLETED EXECUTION OF THE CURRENT LOG PAGE
18075 	 *  AND CAN WRITE IT TO DISK SINCE IT IS DIRTY.
18076 	 * ----------------------------------------------------------------- */
18077         writeDirty(signal, __LINE__);
18078         return;
18079         break;
18080       case LogPartRecord::LES_EXEC_LOG:
18081       jam();
18082       /* --------------------------------------------------------------------
18083        *  IN THIS CASE WE ONLY WRITE THE PAGE TO DISK IF WE HAVE COMPLETED
18084        *  EXECUTION OF LOG RECORDS BELONGING TO THIS LOG PAGE.
18085        * ------------------------------------------------------------------- */
18086         if (logFilePtr.p->currentLogpage != logPartPtr.p->prevLogpage) {
18087           jam();
18088           writeDirty(signal, __LINE__);
18089           return;
18090         }//if
18091         break;
18092       default:
18093         ndbrequire(false);
18094         break;
18095       }//switch
18096     }//if
18097     if (logFilePtr.p->currentLogpage != logPartPtr.p->prevLogpage) {
18098       jam();
18099       logPartPtr.p->prevLogpage = logPagePtr.p->logPageWord[ZNEXT_PAGE];
18100       logPartPtr.p->prevFilepage++;
18101       continue;
18102     }//if
18103     switch (logPartPtr.p->logExecState) {
18104     case LogPartRecord::LES_EXEC_LOG_COMPLETED:
18105       jam();
18106       releaseMmPages(signal);
18107       logFilePtr.p->logFileStatus = LogFileRecord::CLOSING_EXEC_SR_COMPLETED;
18108       closeFile(signal, logFilePtr, __LINE__);
18109       return;
18110       break;
18111     case LogPartRecord::LES_EXEC_LOG_NEW_MBYTE:
18112       jam();
18113       logFilePtr.p->currentMbyte++;
18114       readExecSrNewMbyte(signal);
18115       return;
18116       break;
18117     case LogPartRecord::LES_EXEC_LOG_NEW_FILE:
18118       jam();
18119       nextLogFilePtr.i = logFilePtr.p->nextLogFile;
18120       logPartPtr.p->currentLogfile = nextLogFilePtr.i;
18121       ptrCheckGuard(nextLogFilePtr, clogFileFileSize, logFileRecord);
18122       nextLogFilePtr.p->currentMbyte = 0;
18123       logFilePtr.p->logFileStatus = LogFileRecord::CLOSING_EXEC_SR;
18124       closeFile(signal, logFilePtr, __LINE__);
18125       return;
18126       break;
18127     case LogPartRecord::LES_EXEC_LOG:
18128       jam();
18129       /*empty*/;
18130       break;
18131     default:
18132       jam();
18133       systemErrorLab(signal, __LINE__);
18134       return;
18135       break;
18136     }//switch
18137     logPagePtr.i = logFilePtr.p->currentLogpage;
18138     ptrCheckGuard(logPagePtr, clogPageFileSize, logPageRecord);
18139     logPartPtr.p->savePageIndex = logPagePtr.p->logPageWord[ZCURR_PAGE_INDEX];
18140     if (logPartPtr.p->execSrPagesRead < ZMIN_READ_BUFFER_SIZE) {
18141       /* --------------------------------------------------------------------
18142        *  THERE WERE LESS THAN 16 KBYTE OF LOG PAGES REMAINING. WE WAIT UNTIL
18143        *  THE NEXT 64 KBYTE ARRIVES UNTIL WE CONTINUE AGAIN.
18144        * ------------------------------------------------------------------- */
18145       if ((logPartPtr.p->execSrPagesRead +
18146 	   logPartPtr.p->execSrPagesExecuted) < ZPAGES_IN_MBYTE) {
18147         jam();
18148 	/* ------------------------------------------------------------------
18149 	 *  WE ONLY STOP AND WAIT IF THERE MORE PAGES TO READ. IF IT IS NOT
18150 	 *  THEN IT IS THE END OF THE MBYTE AND WE WILL CONTINUE. IT IS NO
18151 	 *  RISK THAT A LOG RECORD WE FIND WILL NOT BE READ AT THIS TIME
18152 	 *  SINCE THE LOG RECORDS NEVER SPAN OVER A MBYTE BOUNDARY.
18153 	 * ----------------------------------------------------------------- */
18154         readExecSr(signal);
18155         logPartPtr.p->logExecState = LogPartRecord::LES_WAIT_READ_EXEC_SR;
18156         return;
18157       }//if
18158     }//if
18159     logWord = readLogword(signal);
18160     switch (logWord) {
18161 /* ========================================================================= */
18162 /* ========================================================================= */
18163     case ZPREP_OP_TYPE:
18164     {
18165       logWord = readLogword(signal);
18166       stepAhead(signal, logWord - 2);
18167       break;
18168     }
18169 /* ========================================================================= */
18170 /* ========================================================================= */
18171     case ZINVALID_COMMIT_TYPE:
18172       jam();
18173       stepAhead(signal, ZCOMMIT_LOG_SIZE - 1);
18174       break;
18175 /* ========================================================================= */
18176 /* ========================================================================= */
18177     case ZCOMMIT_TYPE:
18178     {
18179       CommitLogRecord commitLogRecord;
18180       jam();
18181       tcConnectptr.i = logPartPtr.p->logTcConrec;
18182       ptrCheckGuard(tcConnectptr, ctcConnectrecFileSize, tcConnectionrec);
18183       readCommitLog(signal, &commitLogRecord);
18184       if (tcConnectptr.p->gci_hi > crestartNewestGci) {
18185         jam();
18186 /*---------------------------------------------------------------------------*/
18187 /* THIS LOG RECORD MUST BE IGNORED. IT IS PART OF A GLOBAL CHECKPOINT WHICH  */
18188 /* WILL BE INVALIDATED BY THE SYSTEM RESTART. IF NOT INVALIDATED IT MIGHT BE */
18189 /* EXECUTED IN A FUTURE SYSTEM RESTART.                                      */
18190 /*---------------------------------------------------------------------------*/
18191         tmpLogPagePtr.i = logPartPtr.p->prevLogpage;
18192         ptrCheckGuard(tmpLogPagePtr, clogPageFileSize, logPageRecord);
18193         arrGuard(logPartPtr.p->savePageIndex, ZPAGE_SIZE);
18194         tmpLogPagePtr.p->logPageWord[logPartPtr.p->savePageIndex] =
18195                                                   ZINVALID_COMMIT_TYPE;
18196         tmpLogPagePtr.p->logPageWord[ZPOS_DIRTY] = ZDIRTY;
18197       } else {
18198         jam();
18199 /*---------------------------------------------------------------------------*/
18200 /* CHECK IF I AM SUPPOSED TO EXECUTE THIS LOG RECORD. IF I AM THEN SAVE PAGE */
18201 /* INDEX IN CURRENT LOG PAGE SINCE IT WILL BE OVERWRITTEN WHEN EXECUTING THE */
18202 /* LOG RECORD.                                                               */
18203 /*---------------------------------------------------------------------------*/
18204         logPartPtr.p->execSrExecuteIndex = 0;
18205         Uint32 result = checkIfExecLog(signal);
18206         if (result == ZOK) {
18207           jam();
18208 //*---------------------------------------------------------------------------*/
18209 /* IN A NODE RESTART WE WILL NEVER END UP HERE SINCE NO FRAGMENTS HAVE BEEN  */
18210 /* DEFINED YET. THUS NO EXTRA CHECKING FOR NODE RESTART IS NECESSARY.        */
18211 /*---------------------------------------------------------------------------*/
18212           logPartPtr.p->savePageIndex =
18213              logPagePtr.p->logPageWord[ZCURR_PAGE_INDEX];
18214           tcConnectptr.p->fragmentptr = fragptr.i;
18215           findPageRef(signal, &commitLogRecord);
18216           logPartPtr.p->execSrLogPageIndex = commitLogRecord.startPageIndex;
18217           if (logPagePtr.i != RNIL) {
18218             jam();
18219             logPagePtr.p->logPageWord[ZCURR_PAGE_INDEX] = commitLogRecord.startPageIndex;
18220             logPartPtr.p->execSrLogPage = logPagePtr.i;
18221             execLogRecord(signal);
18222             return;
18223           }//if
18224           logPartPtr.p->execSrStartPageNo = commitLogRecord.startPageNo;
18225           logPartPtr.p->execSrStopPageNo = commitLogRecord.stopPageNo;
18226           findLogfile(signal, commitLogRecord.fileNo, logPartPtr, &logFilePtr);
18227           logPartPtr.p->execSrExecLogFile = logFilePtr.i;
18228           if (logFilePtr.i == logPartPtr.p->currentLogfile) {
18229             jam();
18230 #ifndef NO_REDO_PAGE_CACHE
18231             Uint32 cnt = 1 +
18232               logPartPtr.p->execSrStopPageNo - logPartPtr.p->execSrStartPageNo;
18233             evict(m_redo_page_cache, cnt);
18234 #endif
18235             readExecLog(signal);
18236             lfoPtr.p->lfoState = LogFileOperationRecord::READ_EXEC_LOG;
18237             return;
18238           } else {
18239             jam();
18240 /*---------------------------------------------------------------------------*/
18241 /* THE FILE IS CURRENTLY NOT OPEN. WE MUST OPEN IT BEFORE WE CAN READ FROM   */
18242 /* THE FILE.                                                                 */
18243 /*---------------------------------------------------------------------------*/
18244 #ifndef NO_REDO_OPEN_FILE_CACHE
18245             openFileRw_cache(signal, logFilePtr);
18246 #else
18247             logFilePtr.p->logFileStatus = LogFileRecord::OPEN_EXEC_LOG;
18248             openFileRw(signal, logFilePtr);
18249 #endif
18250             return;
18251           }//if
18252         }//if
18253       }//if
18254       break;
18255     }
18256 /* ========================================================================= */
18257 /* ========================================================================= */
18258     case ZABORT_TYPE:
18259       jam();
18260       stepAhead(signal, ZABORT_LOG_SIZE - 1);
18261       break;
18262 /* ========================================================================= */
18263 /* ========================================================================= */
18264     case ZFD_TYPE:
18265       jam();
18266 /*---------------------------------------------------------------------------*/
18267 /* THIS IS THE FIRST ITEM WE ENCOUNTER IN A NEW FILE. AT THIS MOMENT WE SHALL*/
18268 /* SIMPLY BYPASS IT. IT HAS NO SIGNIFANCE WHEN EXECUTING THE LOG. IT HAS ITS */
18269 /* SIGNIFANCE WHEN FINDING THE START END THE END OF THE LOG.                 */
18270 /* WE HARDCODE THE PAGE INDEX SINCE THIS SHOULD NEVER BE FOUND AT ANY OTHER  */
18271 /* PLACE THAN IN THE FIRST PAGE OF A NEW FILE IN THE FIRST POSITION AFTER THE*/
18272 /* HEADER.                                                                   */
18273 /*---------------------------------------------------------------------------*/
18274       if (unlikely(logPagePtr.p->logPageWord[ZCURR_PAGE_INDEX] !=
18275 		   (ZPAGE_HEADER_SIZE + ZPOS_NO_FD)))
18276       {
18277 	line = __LINE__;
18278 	logWord = logPagePtr.p->logPageWord[ZCURR_PAGE_INDEX];
18279 	crash_msg = "ZFD_TYPE at incorrect position!";
18280 	goto crash;
18281       }
18282       {
18283         Uint32 noFdDescriptors =
18284 	  logPagePtr.p->logPageWord[ZPAGE_HEADER_SIZE + ZPOS_NO_FD];
18285           logPagePtr.p->logPageWord[ZCURR_PAGE_INDEX] =
18286 	      (ZPAGE_HEADER_SIZE + ZFD_HEADER_SIZE) +
18287 	      (noFdDescriptors * ZFD_MBYTE_SIZE * clogFileSize);
18288       }
18289       break;
18290 /* ========================================================================= */
18291 /* ========================================================================= */
18292     case ZNEXT_LOG_RECORD_TYPE:
18293       jam();
18294       stepAhead(signal, ZPAGE_SIZE - logPagePtr.p->logPageWord[ZCURR_PAGE_INDEX]);
18295       break;
18296 /* ========================================================================= */
18297 /* ========================================================================= */
18298     case ZNEXT_MBYTE_TYPE:
18299 /*---------------------------------------------------------------------------*/
18300 /* WE WILL SKIP A PART OF THE LOG FILE. ACTUALLY THE NEXT POINTER IS TO      */
18301 /* A NEW MBYTE. THEREFORE WE WILL START UP A NEW MBYTE. THIS NEW MBYTE IS    */
18302 /* HOWEVER ONLY STARTED IF IT IS NOT AFTER THE STOP MBYTE.                   */
18303 /* IF WE HAVE REACHED THE END OF THE STOP MBYTE THEN THE EXECUTION OF THE LOG*/
18304 /* IS COMPLETED.                                                             */
18305 /*---------------------------------------------------------------------------*/
18306       if (logPartPtr.p->currentLogfile == logPartPtr.p->stopLogfile) {
18307         if (logFilePtr.p->currentMbyte == logPartPtr.p->stopMbyte) {
18308           jam();
18309 /*---------------------------------------------------------------------------*/
18310 /* THIS WAS THE LAST MBYTE TO EXECUTE IN THIS LOG PART. WE SHOULD HAVE FOUND */
18311 /* A COMPLETED GCI RECORD OF THE LAST GCI BEFORE THIS. FOR SOME REASON THIS  */
18312 /* RECORD WAS NOT AVAILABLE ON THE LOG. CRASH THE SYSTEM, A VERY SERIOUS     */
18313 /* ERROR WHICH WE MUST REALLY WORK HARD TO AVOID.                            */
18314 /*---------------------------------------------------------------------------*/
18315 /*---------------------------------------------------------------------------*/
18316 /* SEND A SIGNAL TO THE SIGNAL LOG AND THEN CRASH THE SYSTEM.                */
18317 /*---------------------------------------------------------------------------*/
18318 	  line = __LINE__;
18319 	  logWord = ZNEXT_MBYTE_TYPE;
18320 	  crash_msg = "end of log wo/ having found last GCI";
18321 	  goto crash;
18322         }//if
18323       }//if
18324 /*---------------------------------------------------------------------------*/
18325 /* START EXECUTION OF A NEW MBYTE IN THE LOG.                                */
18326 /*---------------------------------------------------------------------------*/
18327       if (logFilePtr.p->currentMbyte < (clogFileSize - 1)) {
18328         jam();
18329         logPartPtr.p->logExecState = LogPartRecord::LES_EXEC_LOG_NEW_MBYTE;
18330       } else {
18331         ndbrequire(logFilePtr.p->currentMbyte == (clogFileSize - 1));
18332         jam();
18333 /*---------------------------------------------------------------------------*/
18334 /* WE HAVE TO CHANGE FILE. CLOSE THIS ONE AND THEN OPEN THE NEXT.            */
18335 /*---------------------------------------------------------------------------*/
18336         logPartPtr.p->logExecState = LogPartRecord::LES_EXEC_LOG_NEW_FILE;
18337       }//if
18338       break;
18339 /* ========================================================================= */
18340 /* ========================================================================= */
18341     case ZCOMPLETED_GCI_TYPE:
18342       jam();
18343       logWord = readLogword(signal);
18344       if (DEBUG_REDO)
18345       {
18346         ndbout_c("found gci: %u part: %u file: %u page: %u (mb: %u)",
18347                  logWord,
18348                  logPartPtr.p->logPartNo,
18349                  logFilePtr.p->fileNo,
18350                  logFilePtr.p->currentFilepage,
18351                  logFilePtr.p->currentFilepage >> ZTWOLOG_NO_PAGES_IN_MBYTE);
18352       }
18353       if (logWord == logPartPtr.p->logLastGci)
18354       {
18355         jam();
18356 /*---------------------------------------------------------------------------*/
18357 /* IF IT IS THE LAST GCI TO LIVE AFTER SYSTEM RESTART THEN WE RECORD THE NEXT*/
18358 /* WORD AS THE NEW HEADER OF THE LOG FILE. OTHERWISE WE SIMPLY IGNORE THIS   */
18359 /* LOG RECORD.                                                               */
18360 /*---------------------------------------------------------------------------*/
18361         if (csrPhasesCompleted == 0) {
18362           jam();
18363 /*---------------------------------------------------------------------------*/
18364 /*WE ONLY RECORD THE HEAD OF THE LOG IN THE FIRST LOG ROUND OF LOG EXECUTION.*/
18365 /*---------------------------------------------------------------------------*/
18366           logPartPtr.p->headFileNo = logFilePtr.p->fileNo;
18367           logPartPtr.p->headPageNo = logFilePtr.p->currentFilepage;
18368           logPartPtr.p->headPageIndex =
18369                   logPagePtr.p->logPageWord[ZCURR_PAGE_INDEX];
18370 	  logPartPtr.p->logLap = logPagePtr.p->logPageWord[ZPOS_LOG_LAP];
18371           if (DEBUG_REDO)
18372           {
18373             ndbout_c("execSr part: %u logLap: %u",
18374                      logPartPtr.p->logPartNo, logPartPtr.p->logLap);
18375           }
18376         }//if
18377 /*---------------------------------------------------------------------------*/
18378 /* THERE IS NO NEED OF EXECUTING PAST THIS LINE SINCE THERE WILL ONLY BE LOG */
18379 /* RECORDS THAT WILL BE OF NO INTEREST. THUS CLOSE THE FILE AND START THE    */
18380 /* NEXT PHASE OF THE SYSTEM RESTART.                                         */
18381 /*---------------------------------------------------------------------------*/
18382         logPartPtr.p->logExecState = LogPartRecord::LES_EXEC_LOG_COMPLETED;
18383         send_runredo_event(signal, logPartPtr.p, logPartPtr.p->logLastGci);
18384       }//if
18385       break;
18386     default:
18387       jam();
18388 /* ========================================================================= */
18389 /* ========================================================================= */
18390 /*---------------------------------------------------------------------------*/
18391 /* SEND A SIGNAL TO THE SIGNAL LOG AND THEN CRASH THE SYSTEM.                */
18392 /*---------------------------------------------------------------------------*/
18393       line = __LINE__;
18394       crash_msg = "Invalid logword";
18395       goto crash;
18396       break;
18397     }//switch
18398 /*---------------------------------------------------------------------------*/
18399 // We continue to execute log records until we find a proper one to execute or
18400 // that we reach a new page.
18401 /*---------------------------------------------------------------------------*/
18402   } while (1);
18403   return;
18404 
18405 crash:
18406   signal->theData[0] = RNIL;
18407   signal->theData[1] = logPartPtr.i;
18408   Uint32 tmp = logFilePtr.p->fileName[3];
18409   tmp = (tmp >> 8) & 0xff;// To get the Directory, DXX.
18410   signal->theData[2] = tmp;
18411   signal->theData[3] = logFilePtr.p->fileNo;
18412   signal->theData[4] = logFilePtr.p->currentMbyte;
18413   signal->theData[5] = logFilePtr.p->currentFilepage;
18414   signal->theData[6] = logPagePtr.p->logPageWord[ZCURR_PAGE_INDEX];
18415   signal->theData[7] = logWord;
18416   signal->theData[8] = line;
18417 
18418   char buf[255];
18419   BaseString::snprintf(buf, sizeof(buf),
18420 		       "Error while reading REDO log. from %d\n"
18421 		       "part: %u D=%d, F=%d Mb=%d FP=%d W1=%d W2=%d : %s gci: %u",
18422 		       signal->theData[8],
18423                        logPartPtr.p->logPartNo,
18424 		       signal->theData[2],
18425 		       signal->theData[3],
18426 		       signal->theData[4],
18427 		       signal->theData[5],
18428 		       signal->theData[6],
18429 		       signal->theData[7],
18430 		       crash_msg ? crash_msg : "",
18431 		       logPartPtr.p->logLastGci);
18432 
18433   ndbout_c("%s", buf);
18434   ndbout_c("logPartPtr.p->logExecState: %u", logPartPtr.p->logExecState);
18435   ndbout_c("crestartOldestGci: %u", crestartOldestGci);
18436   ndbout_c("crestartNewestGci: %u", crestartNewestGci);
18437   ndbout_c("csrPhasesCompleted: %u", csrPhasesCompleted);
18438   ndbout_c("logPartPtr.p->logStartGci: %u", logPartPtr.p->logStartGci);
18439   ndbout_c("logPartPtr.p->logLastGci: %u", logPartPtr.p->logLastGci);
18440 
18441   progError(__LINE__, NDBD_EXIT_SR_REDOLOG, buf);
18442 }//Dblqh::execSr()
18443 
18444 /*---------------------------------------------------------------------------*/
18445 /* THIS SIGNAL IS ONLY RECEIVED TO BE CAPTURED IN THE SIGNAL LOG. IT IS      */
18446 /* ALSO USED TO CRASH THE SYSTEM AFTER SENDING A SIGNAL TO THE LOG.          */
18447 /*---------------------------------------------------------------------------*/
execDEBUG_SIG(Signal * signal)18448 void Dblqh::execDEBUG_SIG(Signal* signal)
18449 {
18450 /*
18451 2.5 TEMPORARY VARIABLES
18452 -----------------------
18453 */
18454   jamEntry();
18455   //logPagePtr.i = signal->theData[0];
18456   //tdebug = logPagePtr.p->logPageWord[0];
18457 
18458   char buf[100];
18459   BaseString::snprintf(buf, 100,
18460 	   "Error while reading REDO log. from %d\n"
18461 	   "D=%d, F=%d Mb=%d FP=%d W1=%d W2=%d",
18462 	   signal->theData[8],
18463 	   signal->theData[2], signal->theData[3], signal->theData[4],
18464 	   signal->theData[5], signal->theData[6], signal->theData[7]);
18465 
18466   progError(__LINE__, NDBD_EXIT_SR_REDOLOG, buf);
18467 
18468   return;
18469 }//Dblqh::execDEBUG_SIG()
18470 
18471 /*---------------------------------------------------------------------------*/
18472 /*---------------------------------------------------------------------------*/
closeExecLogLab(Signal * signal)18473 void Dblqh::closeExecLogLab(Signal* signal)
18474 {
18475   logFilePtr.p->logFileStatus = LogFileRecord::CLOSED;
18476   signal->theData[0] = ZEXEC_SR;
18477   signal->theData[1] = logFilePtr.p->logPartRec;
18478   sendSignal(cownref, GSN_CONTINUEB, signal, 2, JBB);
18479   return;
18480 }//Dblqh::closeExecLogLab()
18481 
openExecLogLab(Signal * signal)18482 void Dblqh::openExecLogLab(Signal* signal)
18483 {
18484 #ifndef NO_REDO_PAGE_CACHE
18485   Uint32 cnt = 1 +
18486     logPartPtr.p->execSrStopPageNo - logPartPtr.p->execSrStartPageNo;
18487 
18488 #if 0
18489   Uint32 MAX_EXTRA_READ = 9; // can be max 9 due to FSREADREQ formatting
18490   while (cnt < maxextraread && (logPartPtr.p->execSrStopPageNo % 32) != 31)
18491   {
18492     jam();
18493     cnt++;
18494     logPartPtr.p->execSrStopPageNo++;
18495   }
18496 #endif
18497 
18498   evict(m_redo_page_cache, cnt);
18499 #endif
18500 
18501   readExecLog(signal);
18502   lfoPtr.p->lfoState = LogFileOperationRecord::READ_EXEC_LOG;
18503   return;
18504 }//Dblqh::openExecLogLab()
18505 
readExecLogLab(Signal * signal)18506 void Dblqh::readExecLogLab(Signal* signal)
18507 {
18508   buildLinkedLogPageList(signal);
18509 #ifndef NO_REDO_PAGE_CACHE
18510   addCachePages(m_redo_page_cache,
18511                 logPartPtr.p->logPartNo,
18512                 logPartPtr.p->execSrStartPageNo,
18513                 lfoPtr.p);
18514 #endif
18515   logPartPtr.p->logExecState = LogPartRecord::LES_EXEC_LOGREC_FROM_FILE;
18516   logPartPtr.p->execSrLfoRec = lfoPtr.i;
18517   logPartPtr.p->execSrLogPage = logPagePtr.i;
18518   logPagePtr.p->logPageWord[ZCURR_PAGE_INDEX] =
18519     logPartPtr.p->execSrLogPageIndex;
18520   execLogRecord(signal);
18521   return;
18522 }//Dblqh::readExecLogLab()
18523 
18524 /*---------------------------------------------------------------------------*/
18525 /* THIS CODE IS USED TO EXECUTE A LOG RECORD WHEN IT'S DATA HAVE BEEN LOCATED*/
18526 /* AND TRANSFERRED INTO MEMORY.                                              */
18527 /*---------------------------------------------------------------------------*/
execLogRecord(Signal * signal)18528 void Dblqh::execLogRecord(Signal* signal)
18529 {
18530   jamEntry();
18531 
18532   tcConnectptr.i = logPartPtr.p->logTcConrec;
18533   ptrCheckGuard(tcConnectptr, ctcConnectrecFileSize, tcConnectionrec);
18534   fragptr.i = tcConnectptr.p->fragmentptr;
18535   c_fragment_pool.getPtr(fragptr);
18536   tcConnectptr.p->m_log_part_ptr_i = fragptr.p->m_log_part_ptr_i;
18537 
18538   // Read a log record and prepare it for execution
18539   readLogHeader(signal);
18540   readKey(signal);
18541   readAttrinfo(signal);
18542   initReqinfoExecSr(signal);
18543   arrGuard(logPartPtr.p->execSrExecuteIndex, MAX_REPLICAS);
18544   BlockReference ref = fragptr.p->execSrBlockref[logPartPtr.p->execSrExecuteIndex];
18545   tcConnectptr.p->nextReplica = refToNode(ref);
18546   tcConnectptr.p->connectState = TcConnectionrec::LOG_CONNECTED;
18547   tcConnectptr.p->tcOprec = tcConnectptr.i;
18548   tcConnectptr.p->tcHashKeyHi = 0;
18549   packLqhkeyreqLab(signal);
18550   return;
18551 }//Dblqh::execLogRecord()
18552 
18553 //----------------------------------------------------------------------------
18554 // This function invalidates log pages after the last GCI record in a
18555 // system/node restart. This is to ensure that the end of the log is
18556 // consistent. This function is executed last in start phase 3.
18557 // RT 450. EDTJAMO.
18558 //----------------------------------------------------------------------------
18559 Uint32
nextLogFilePtr(Uint32 logFilePtrI)18560 Dblqh::nextLogFilePtr(Uint32 logFilePtrI)
18561 {
18562   LogFileRecordPtr tmp;
18563   tmp.i = logFilePtrI;
18564   ptrCheckGuard(tmp, clogFileFileSize, logFileRecord);
18565   return tmp.p->nextLogFile;
18566 }
18567 
18568 void
invalidateLogAfterLastGCI(Signal * signal)18569 Dblqh::invalidateLogAfterLastGCI(Signal* signal)
18570 {
18571   jam();
18572   if (logPartPtr.p->logExecState != LogPartRecord::LES_EXEC_LOG_INVALIDATE) {
18573     jam();
18574     systemError(signal, __LINE__);
18575   }
18576 
18577   if (logFilePtr.p->fileNo != logPartPtr.p->invalidateFileNo) {
18578     jam();
18579     systemError(signal, __LINE__);
18580   }
18581 
18582   switch (lfoPtr.p->lfoState) {
18583   case LogFileOperationRecord::READ_SR_INVALIDATE_SEARCH_FILES:
18584   {
18585     jam();
18586     // Check if this file contains pages needing to be invalidated
18587     ndbrequire(logPartPtr.p->invalidatePageNo == 1);
18588     bool ok = logPagePtr.p->logPageWord[ZPOS_LOG_LAP] == logPartPtr.p->logLap;
18589     releaseLfo(signal);
18590     releaseLogpage(signal);
18591     if (ok)
18592     {
18593       jam();
18594       // This page must be invalidated.
18595       // We search next file
18596       readFileInInvalidate(signal, 3);
18597       return;
18598     }
18599     else
18600     {
18601       jam();
18602       /**
18603        * This file doest not need to be invalidated...move to previous
18604        *   file and search forward linear
18605        */
18606       readFileInInvalidate(signal, 6);
18607       return;
18608     }
18609     break;
18610   }
18611   case LogFileOperationRecord::READ_SR_INVALIDATE_PAGES:
18612     jam();
18613     // Check if this page must be invalidated.
18614     // If the log lap number on a page after the head of the tail is the same
18615     // as the actual log lap number we must invalidate this page. Otherwise it
18616     // could be impossible to find the end of the log in a later system/node
18617     // restart.
18618     if (logPagePtr.p->logPageWord[ZPOS_LOG_LAP] == logPartPtr.p->logLap)
18619     {
18620       jam();
18621       // This page must be invalidated.
18622       // We search for end
18623       // read next
18624       releaseLfo(signal);
18625       releaseLogpage(signal);
18626       readFileInInvalidate(signal, 1);
18627       return;
18628     }
18629 
18630     /**
18631      * We found the "last" page to invalidate...
18632      *   Invalidate backwards until head...
18633      */
18634 
18635     // Fall through...
18636   case LogFileOperationRecord::WRITE_SR_INVALIDATE_PAGES:
18637     jam();
18638 
18639     releaseLfo(signal);
18640     releaseLogpage(signal);
18641 
18642     // Step backwards...
18643     logPartPtr.p->invalidatePageNo--;
18644 
18645     if (logPartPtr.p->invalidatePageNo == 0)
18646     {
18647       jam();
18648 
18649       if (logFilePtr.p->fileNo == 0)
18650       {
18651         jam();
18652         /**
18653          * We're wrapping in the log...
18654          *   update logLap
18655          */
18656         logPartPtr.p->logLap--;
18657 	ndbrequire(logPartPtr.p->logLap); // Should always be > 0
18658         if (DEBUG_REDO)
18659         {
18660           ndbout_c("invalidateLogAfterLastGCI part: %u wrap from file 0 -> logLap: %u",
18661                    logPartPtr.p->logPartNo, logPartPtr.p->logLap);
18662         }
18663       }
18664 
18665       if (invalidateCloseFile(signal, logPartPtr, logFilePtr,
18666                               LogFileRecord::CLOSE_SR_WRITE_INVALIDATE_PAGES))
18667       {
18668         jam();
18669         return;
18670       }
18671       writeFileInInvalidate(signal, 1); // step prev
18672       return;
18673     }
18674     writeFileInInvalidate(signal, 0);
18675     return;
18676   default:
18677     jamLine(lfoPtr.p->lfoState);
18678     ndbrequire(false);
18679   }
18680 }
18681 
18682 void
writeFileInInvalidate(Signal * signal,int stepPrev)18683 Dblqh::writeFileInInvalidate(Signal* signal, int stepPrev)
18684 {
18685   /**
18686    * Move to prev file
18687    */
18688   if (stepPrev == 1)
18689   {
18690     jam();
18691     logFilePtr.i = logFilePtr.p->prevLogFile;
18692     ptrCheckGuard(logFilePtr, clogFileFileSize, logFileRecord);
18693     logPartPtr.p->invalidateFileNo = logFilePtr.p->fileNo;
18694     logPartPtr.p->invalidatePageNo = clogFileSize * ZPAGES_IN_MBYTE - 1;
18695   }
18696 
18697   if (logPartPtr.p->invalidateFileNo == logPartPtr.p->headFileNo &&
18698       logPartPtr.p->invalidatePageNo == logPartPtr.p->headPageNo)
18699   {
18700     jam();
18701     /**
18702      * Done...
18703      */
18704     logFilePtr.i = logPartPtr.p->currentLogfile;
18705     ptrCheckGuard(logFilePtr, clogFileFileSize, logFileRecord);
18706 
18707     logFilePtr.i = logFilePtr.p->nextLogFile;
18708     ptrCheckGuard(logFilePtr, clogFileFileSize, logFileRecord);
18709 
18710     exitFromInvalidate(signal);
18711     return;
18712   }
18713 
18714   if (stepPrev == 1 && logFilePtr.p->logFileStatus != LogFileRecord::OPEN)
18715   {
18716     jam();
18717     if (DEBUG_REDO)
18718     {
18719       ndbout_c("invalidate part: %u open for write %u",
18720                logPartPtr.p->logPartNo, logFilePtr.p->fileNo);
18721     }
18722     logFilePtr.p->logFileStatus =LogFileRecord::OPEN_SR_WRITE_INVALIDATE_PAGES;
18723     openFileRw(signal, logFilePtr);
18724     return;
18725   }
18726 
18727   seizeLogpage(signal);
18728 
18729   /**
18730    * Make page really empty
18731    */
18732   bzero(logPagePtr.p, sizeof(LogPageRecord));
18733   writeSinglePage(signal, logPartPtr.p->invalidatePageNo,
18734                   ZPAGE_SIZE - 1, __LINE__);
18735 
18736   lfoPtr.p->lfoState = LogFileOperationRecord::WRITE_SR_INVALIDATE_PAGES;
18737   return;
18738 }//Dblqh::invalidateLogAfterLastGCI
18739 
18740 bool
invalidateCloseFile(Signal * signal,Ptr<LogPartRecord> partPtr,Ptr<LogFileRecord> filePtr,LogFileRecord::LogFileStatus status)18741 Dblqh::invalidateCloseFile(Signal* signal,
18742                            Ptr<LogPartRecord> partPtr,
18743                            Ptr<LogFileRecord> filePtr,
18744                            LogFileRecord::LogFileStatus status)
18745 {
18746   jam();
18747   if (filePtr.p->fileNo != 0 &&
18748       filePtr.i != partPtr.p->currentLogfile &&
18749       filePtr.i != nextLogFilePtr(logPartPtr.p->currentLogfile))
18750   {
18751     jam();
18752     if (DEBUG_REDO)
18753     {
18754       ndbout_c("invalidate part: %u close %u(%u) state: %u (%u)",
18755                logPartPtr.p->logPartNo,
18756                logFilePtr.p->fileNo,
18757                logFilePtr.i,
18758                (Uint32)status,
18759                logPartPtr.p->currentLogfile);
18760     }
18761     filePtr.p->logFileStatus = status;
18762     closeFile(signal, filePtr, __LINE__);
18763     return true;
18764   }
18765   return false;
18766 }
18767 
readFileInInvalidate(Signal * signal,int stepNext)18768 void Dblqh::readFileInInvalidate(Signal* signal, int stepNext)
18769 {
18770   jam();
18771 
18772   if (DEBUG_REDO)
18773   {
18774     ndbout_c("readFileInInvalidate part: %u file: %u stepNext: %u",
18775              logPartPtr.p->logPartNo, logFilePtr.p->fileNo, stepNext);
18776   }
18777 
18778   if (stepNext == 0)
18779   {
18780     jam();
18781     // Contact NDBFS. Real time break.
18782     readSinglePage(signal, logPartPtr.p->invalidatePageNo);
18783     lfoPtr.p->lfoState = LogFileOperationRecord::READ_SR_INVALIDATE_PAGES;
18784     return;
18785   }
18786 
18787   if (stepNext == 1)
18788   {
18789     jam();
18790     logPartPtr.p->invalidatePageNo++;
18791     if (logPartPtr.p->invalidatePageNo == (clogFileSize * ZPAGES_IN_MBYTE))
18792     {
18793       if (invalidateCloseFile(signal, logPartPtr, logFilePtr,
18794                               LogFileRecord::CLOSE_SR_READ_INVALIDATE_PAGES))
18795       {
18796         jam();
18797         return;
18798       }
18799       else
18800       {
18801         jam();
18802         stepNext = 2; // After close
18803       }
18804     }
18805     else
18806     {
18807       jam();
18808       // Contact NDBFS. Real time break.
18809       readSinglePage(signal, logPartPtr.p->invalidatePageNo);
18810       lfoPtr.p->lfoState = LogFileOperationRecord::READ_SR_INVALIDATE_PAGES;
18811       return;
18812     }
18813   }
18814 
18815   if (stepNext == 2)
18816   {
18817     jam();
18818     // We continue in the next file.
18819     logFilePtr.i = logFilePtr.p->nextLogFile;
18820     ptrCheckGuard(logFilePtr, clogFileFileSize, logFileRecord);
18821     logPartPtr.p->invalidateFileNo = logFilePtr.p->fileNo;
18822     // Page 0 is used for file descriptors.
18823     logPartPtr.p->invalidatePageNo = 1;
18824 
18825     if (logFilePtr.p->fileNo == 0)
18826     {
18827       /**
18828        * We're wrapping in the log...
18829        *   update logLap
18830        */
18831       logPartPtr.p->logLap++;
18832       if (DEBUG_REDO)
18833       {
18834         ndbout_c("readFileInInvalidate part: %u step: %u wrap to file 0 -> logLap: %u",
18835                  logPartPtr.p->logPartNo, stepNext, logPartPtr.p->logLap);
18836       }
18837     }
18838 
18839 stepNext_2:
18840     if (logFilePtr.p->logFileStatus != LogFileRecord::OPEN)
18841     {
18842       jam();
18843       if (DEBUG_REDO)
18844       {
18845         ndbout_c("invalidate part: %u step: %u open for read %u",
18846                  logPartPtr.p->logPartNo, stepNext, logFilePtr.p->fileNo);
18847       }
18848       logFilePtr.p->logFileStatus =LogFileRecord::OPEN_SR_READ_INVALIDATE_PAGES;
18849       openFileRw(signal, logFilePtr);
18850       return;
18851     }
18852 
18853     // Contact NDBFS. Real time break.
18854     readSinglePage(signal, logPartPtr.p->invalidatePageNo);
18855     lfoPtr.p->lfoState = LogFileOperationRecord::READ_SR_INVALIDATE_PAGES;
18856     return;
18857   }
18858 
18859   if (stepNext == 3)
18860   {
18861     jam();
18862     if (invalidateCloseFile
18863         (signal, logPartPtr, logFilePtr,
18864          LogFileRecord::CLOSE_SR_READ_INVALIDATE_SEARCH_FILES))
18865     {
18866       jam();
18867       return;
18868     }
18869     stepNext = 4;
18870   }
18871 
18872   if (stepNext == 4)
18873   {
18874     jam();
18875     logFilePtr.i = logFilePtr.p->nextLogFile;
18876     ptrCheckGuard(logFilePtr, clogFileFileSize, logFileRecord);
18877     logPartPtr.p->invalidateFileNo = logFilePtr.p->fileNo;
18878     // Page 0 is used for file descriptors.
18879     logPartPtr.p->invalidatePageNo = 1;
18880 
18881     if (logFilePtr.p->fileNo == 0)
18882     {
18883       /**
18884        * We're wrapping in the log...
18885        *   update logLap
18886        */
18887       logPartPtr.p->logLap++;
18888       if (DEBUG_REDO)
18889       {
18890         ndbout_c("readFileInInvalidate part: %u step: %u wrap to file 0 -> logLap: %u",
18891                  logPartPtr.p->logPartNo, stepNext, logPartPtr.p->logLap);
18892       }
18893     }
18894 
18895     if (logFilePtr.p->logFileStatus != LogFileRecord::OPEN)
18896     {
18897       jam();
18898       if (DEBUG_REDO)
18899       {
18900         ndbout_c("invalidate part: %u step: %u open for read %u",
18901                  logPartPtr.p->logPartNo, stepNext, logFilePtr.p->fileNo);
18902       }
18903       logFilePtr.p->logFileStatus =
18904         LogFileRecord::OPEN_SR_READ_INVALIDATE_SEARCH_FILES;
18905       openFileRw(signal, logFilePtr);
18906       return;
18907     }
18908     stepNext = 5;
18909   }
18910 
18911   if (stepNext == 5)
18912   {
18913     jam();
18914     // Contact NDBFS. Real time break.
18915     readSinglePage(signal, logPartPtr.p->invalidatePageNo);
18916     lfoPtr.p->lfoState =
18917       LogFileOperationRecord::READ_SR_INVALIDATE_SEARCH_FILES;
18918     return;
18919   }
18920 
18921   if (stepNext == 6)
18922   {
18923     jam();
18924     if (invalidateCloseFile
18925         (signal, logPartPtr, logFilePtr,
18926          LogFileRecord::CLOSE_SR_READ_INVALIDATE_SEARCH_LAST_FILE))
18927     {
18928       jam();
18929       return;
18930     }
18931     stepNext = 7;
18932   }
18933 
18934   if (stepNext == 7)
18935   {
18936     jam();
18937 
18938     if (logFilePtr.p->fileNo == 0)
18939     {
18940       jam();
18941       /**
18942        * We're wrapping in the log...
18943        *   update logLap
18944        */
18945       logPartPtr.p->logLap--;
18946       ndbrequire(logPartPtr.p->logLap); // Should always be > 0
18947       if (DEBUG_REDO)
18948       {
18949         ndbout_c("invalidateLogAfterLastGCI part: %u step: %u wrap from file 0 -> logLap: %u",
18950                  logPartPtr.p->logPartNo, stepNext, logPartPtr.p->logLap);
18951       }
18952     }
18953 
18954     logFilePtr.i = logFilePtr.p->prevLogFile;
18955     ptrCheckGuard(logFilePtr, clogFileFileSize, logFileRecord);
18956 
18957     logPartPtr.p->invalidateFileNo = logFilePtr.p->fileNo;
18958     // Page 0 is used for file descriptors.
18959     logPartPtr.p->invalidatePageNo = 1;
18960 
18961     if (logPartPtr.p->invalidateFileNo == logPartPtr.p->headFileNo)
18962     {
18963       jam();
18964       logPartPtr.p->invalidatePageNo = logPartPtr.p->headPageNo;
18965 
18966       if (! ((cstartType == NodeState::ST_INITIAL_START) ||
18967              (cstartType == NodeState::ST_INITIAL_NODE_RESTART)))
18968       {
18969         jam();
18970         if (logFilePtr.i == logPartPtr.p->lastLogfile)
18971         {
18972           jam();
18973           Uint32 lastMbytePageNo =
18974             logPartPtr.p->lastMbyte << ZTWOLOG_NO_PAGES_IN_MBYTE;
18975           if (logPartPtr.p->invalidatePageNo < lastMbytePageNo)
18976           {
18977             jam();
18978             if (DEBUG_REDO)
18979             {
18980               ndbout_c("readFileInInvalidate part: %u step: %u moving invalidatePageNo from %u to %u (lastMbyte)",
18981                        logPartPtr.p->logPartNo, stepNext,
18982                        logPartPtr.p->invalidatePageNo,
18983                        lastMbytePageNo);
18984             }
18985             logPartPtr.p->invalidatePageNo = lastMbytePageNo;
18986           }
18987         }
18988       }
18989       readFileInInvalidate(signal, 1);
18990       return;
18991     }
18992 
18993     goto stepNext_2;
18994   }
18995   ndbrequire(false);
18996 }
18997 
exitFromInvalidate(Signal * signal)18998 void Dblqh::exitFromInvalidate(Signal* signal)
18999 {
19000   jam();
19001 
19002   if (DEBUG_REDO)
19003   {
19004     jam();
19005     printf("exitFromInvalidate part: %u head file: %u page: %u open: ",
19006            logPartPtr.p->logPartNo,
19007            logPartPtr.p->headFileNo,
19008            logPartPtr.p->headPageNo);
19009 
19010     LogFileRecordPtr tmp;
19011     tmp.i = logPartPtr.p->currentLogfile;
19012     do
19013     {
19014       jam();
19015       ptrCheckGuard(tmp, clogFileFileSize, logFileRecord);
19016       if (tmp.p->logFileStatus != LogFileRecord::LFS_IDLE &&
19017           tmp.p->logFileStatus != LogFileRecord::CLOSED)
19018       {
19019         jam();
19020         printf("%u ", tmp.p->fileNo);
19021       }
19022       tmp.i = tmp.p->nextLogFile;
19023     } while (tmp.i != logPartPtr.p->currentLogfile && tmp.i != RNIL);
19024     printf("\n");
19025 
19026     tmp.i = logPartPtr.p->currentLogfile;
19027     ptrCheckGuard(tmp, clogFileFileSize, logFileRecord);
19028 
19029     LogPosition head = { tmp.p->fileNo, tmp.p->currentMbyte };
19030     LogPosition tail = { logPartPtr.p->logTailFileNo,
19031                          logPartPtr.p->logTailMbyte};
19032     Uint64 mb = free_log(head, tail, logPartPtr.p->noLogFiles, clogFileSize);
19033     Uint64 total = logPartPtr.p->noLogFiles * Uint64(clogFileSize);
19034     ndbout_c("head: [ %u %u ] tail: [ %u %u ] free: %llu total: %llu",
19035              head.m_file_no, head.m_mbyte,
19036              tail.m_file_no, tail.m_mbyte,
19037              mb, total);
19038   }
19039 
19040   logFilePtr.i = logPartPtr.p->firstLogfile;
19041   ptrCheckGuard(logFilePtr, clogFileFileSize, logFileRecord);
19042   logPagePtr.i = logFilePtr.p->logPageZero;
19043   ptrCheckGuard(logPagePtr, clogPageFileSize, logPageRecord);
19044   logPagePtr.p->logPageWord[ZPAGE_HEADER_SIZE + ZPOS_FILE_NO] =
19045     logPartPtr.p->headFileNo;
19046   writeSinglePage(signal, 0, ZPAGE_SIZE - 1, __LINE__);
19047 
19048   lfoPtr.p->logFileRec = logFilePtr.i;
19049   lfoPtr.p->lfoState = LogFileOperationRecord::WRITE_SR_INVALIDATE_PAGES_UPDATE_PAGE0;
19050   return;
19051 }
19052 
19053 /*---------------------------------------------------------------------------*/
19054 /* THE EXECUTION OF A LOG RECORD IS COMPLETED. RELEASE PAGES IF THEY WERE    */
19055 /* READ FROM DISK FOR THIS PARTICULAR OPERATION.                             */
19056 /*---------------------------------------------------------------------------*/
completedLab(Signal * signal)19057 void Dblqh::completedLab(Signal* signal)
19058 {
19059   Uint32 result = returnExecLog(signal);
19060 /*---------------------------------------------------------------------------*/
19061 /*       ENTER COMPLETED WITH                                                */
19062 /*         LQH_CONNECTPTR                                                    */
19063 /*---------------------------------------------------------------------------*/
19064   if (result == ZOK) {
19065     jam();
19066     execLogRecord(signal);
19067     return;
19068   } else if (result == ZNOT_OK) {
19069     jam();
19070     signal->theData[0] = ZEXEC_SR;
19071     signal->theData[1] = logPartPtr.i;
19072     sendSignal(cownref, GSN_CONTINUEB, signal, 2, JBB);
19073   } else {
19074     jam();
19075     /*empty*/;
19076   }//if
19077 /*---------------------------------------------------------------------------*/
19078 /* WE HAVE TO WAIT FOR CLOSING OF THE EXECUTED LOG FILE BEFORE PROCEEDING IN */
19079 /* RARE CASES.                                                               */
19080 /*---------------------------------------------------------------------------*/
19081   return;
19082 }//Dblqh::completedLab()
19083 
19084 /*---------------------------------------------------------------------------*/
19085 /* EXECUTION OF LOG RECORD WAS NOT SUCCESSFUL. CHECK IF IT IS OK ANYWAY,     */
19086 /* THEN EXECUTE THE NEXT LOG RECORD.                                         */
19087 /*---------------------------------------------------------------------------*/
logLqhkeyrefLab(Signal * signal)19088 void Dblqh::logLqhkeyrefLab(Signal* signal)
19089 {
19090   Uint32 result = returnExecLog(signal);
19091   switch (tcConnectptr.p->operation) {
19092   case ZUPDATE:
19093   case ZDELETE:
19094     jam();
19095     if (unlikely(terrorCode != ZNO_TUPLE_FOUND))
19096       goto error;
19097     break;
19098   case ZINSERT:
19099     jam();
19100     if (unlikely(terrorCode != ZTUPLE_ALREADY_EXIST && terrorCode != 899))
19101       goto error;
19102 
19103     break;
19104   default:
19105     goto error;
19106   }
19107 
19108   if (result == ZOK) {
19109     jam();
19110     execLogRecord(signal);
19111     return;
19112   } else if (result == ZNOT_OK) {
19113     jam();
19114     signal->theData[0] = ZEXEC_SR;
19115     signal->theData[1] = logPartPtr.i;
19116     sendSignal(cownref, GSN_CONTINUEB, signal, 2, JBB);
19117   } else {
19118     jam();
19119     /*empty*/;
19120   }//if
19121   /* ------------------------------------------------------------------------
19122    *  WE HAVE TO WAIT FOR CLOSING OF THE EXECUTED LOG FILE BEFORE
19123    *  PROCEEDING IN RARE CASES.
19124    * ----------------------------------------------------------------------- */
19125   return;
19126 error:
19127   BaseString tmp;
19128   tmp.appfmt("You have found a bug!"
19129 	     " Failed op (%s) during REDO table: %d fragment: %d err: %d",
19130 	     tcConnectptr.p->operation == ZINSERT ? "INSERT" :
19131 	     tcConnectptr.p->operation == ZUPDATE ? "UPDATE" :
19132 	     tcConnectptr.p->operation == ZDELETE ? "DELETE" :
19133 	     tcConnectptr.p->operation == ZWRITE ? "WRITE" : "<unknown>",
19134 	     tcConnectptr.p->tableref,
19135 	     tcConnectptr.p->fragmentid,
19136 	     terrorCode);
19137   progError(__LINE__, NDBD_EXIT_SYSTEM_ERROR,
19138 	    tmp.c_str());
19139 }//Dblqh::logLqhkeyrefLab()
19140 
closeExecSrCompletedLab(Signal * signal)19141 void Dblqh::closeExecSrCompletedLab(Signal* signal)
19142 {
19143   logFilePtr.p->logFileStatus = LogFileRecord::CLOSED;
19144   signal->theData[0] = logFilePtr.p->logPartRec;
19145   execLogComp(signal);
19146   return;
19147 }//Dblqh::closeExecSrCompletedLab()
19148 
19149 /* --------------------------------------------------------------------------
19150  *  ONE OF THE LOG PARTS HAVE COMPLETED EXECUTING THE LOG. CHECK IF ALL LOG
19151  *  PARTS ARE COMPLETED. IF SO START SENDING EXEC_FRAGCONF AND EXEC_SRCONF.
19152  * ------------------------------------------------------------------------- */
execLogComp(Signal * signal)19153 void Dblqh::execLogComp(Signal* signal)
19154 {
19155   logPartPtr.i = signal->theData[0];
19156   ptrCheckGuard(logPartPtr, clogPartFileSize, logPartRecord);
19157   logPartPtr.p->logPartState = LogPartRecord::SR_THIRD_PHASE_COMPLETED;
19158   /* ------------------------------------------------------------------------
19159    *  WE MUST RELEASE THE TC CONNECT RECORD HERE SO THAT IT CAN BE REUSED.
19160    * ----------------------------------------------------------------------- */
19161   tcConnectptr.i = logPartPtr.p->logTcConrec;
19162   ptrCheckGuard(tcConnectptr, ctcConnectrecFileSize, tcConnectionrec);
19163   logPartPtr.p->logTcConrec = RNIL;
19164   releaseTcrecLog(signal, tcConnectptr);
19165   for (logPartPtr.i = 0; logPartPtr.i < clogPartFileSize; logPartPtr.i++) {
19166     jam();
19167     ptrAss(logPartPtr, logPartRecord);
19168     if (logPartPtr.p->logPartState != LogPartRecord::SR_THIRD_PHASE_COMPLETED) {
19169       if (logPartPtr.p->logPartState != LogPartRecord::SR_THIRD_PHASE_STARTED) {
19170         jam();
19171         systemErrorLab(signal, __LINE__);
19172         return;
19173       } else {
19174         jam();
19175 	/* ------------------------------------------------------------------
19176 	 *  THIS LOG PART WAS NOT COMPLETED YET. EXIT AND WAIT FOR IT
19177 	 *  TO COMPLETE
19178 	 * ----------------------------------------------------------------- */
19179         return;
19180       }//if
19181     }//if
19182   }//for
19183   /* ------------------------------------------------------------------------
19184    *   ALL LOG PARTS HAVE COMPLETED THE EXECUTION OF THE LOG. WE CAN NOW START
19185    *   SENDING THE EXEC_FRAGCONF SIGNALS TO ALL INVOLVED FRAGMENTS.
19186    * ----------------------------------------------------------------------- */
19187   jam();
19188 
19189 #ifndef NO_REDO_PAGE_CACHE
19190   release(m_redo_page_cache);
19191 #endif
19192 
19193 #ifndef NO_REDO_OPEN_FILE_CACHE
19194   release(signal, m_redo_open_file_cache);
19195 #else
19196   execLogComp_extra_files_closed(signal);
19197 #endif
19198 }
19199 
19200 void
execLogComp_extra_files_closed(Signal * signal)19201 Dblqh::execLogComp_extra_files_closed(Signal * signal)
19202 {
19203   c_lcp_complete_fragments.first(fragptr);
19204   signal->theData[0] = ZSEND_EXEC_CONF;
19205   signal->theData[1] = fragptr.i;
19206   sendSignal(cownref, GSN_CONTINUEB, signal, 2, JBB);
19207   return;
19208 }
19209 
19210 /* --------------------------------------------------------------------------
19211  *  GO THROUGH THE FRAGMENT RECORDS TO DEDUCE TO WHICH SHALL BE SENT
19212  *  EXEC_FRAGCONF AFTER COMPLETING THE EXECUTION OF THE LOG.
19213  * ------------------------------------------------------------------------- */
sendExecConf(Signal * signal)19214 void Dblqh::sendExecConf(Signal* signal)
19215 {
19216   jamEntry();
19217   fragptr.i = signal->theData[0];
19218   Uint32 loopCount = 0;
19219   while (fragptr.i != RNIL) {
19220     c_lcp_complete_fragments.getPtr(fragptr);
19221     Uint32 next = fragptr.p->nextList;
19222     if (fragptr.p->execSrStatus != Fragrecord::IDLE) {
19223       jam();
19224       ndbrequire(fragptr.p->execSrNoReplicas - 1 < MAX_REPLICAS);
19225       for (Uint32 i = 0; i < fragptr.p->execSrNoReplicas; i++) {
19226         jam();
19227         Uint32 ref = fragptr.p->execSrBlockref[i];
19228         signal->theData[0] = fragptr.p->execSrUserptr[i];
19229 
19230         if (isNdbMtLqh())
19231         {
19232           jam();
19233           // send via own proxy
19234           signal->theData[1] = ref;
19235           sendSignal(DBLQH_REF, GSN_EXEC_FRAGCONF, signal, 2, JBB);
19236         }
19237         else if (refToInstance(ref) != 0 &&
19238                  ndb_route_exec_frag(getNodeInfo(refToNode(ref)).m_version))
19239         {
19240           jam();
19241           // send via remote proxy
19242           signal->theData[1] = ref;
19243           sendSignal(numberToRef(refToMain(ref), refToNode(ref)),
19244                      GSN_EXEC_FRAGCONF, signal, 2, JBB);
19245         }
19246         else
19247         {
19248           jam();
19249           // send direct
19250           sendSignal(ref, GSN_EXEC_FRAGCONF, signal, 1, JBB);
19251         }
19252       }//for
19253       fragptr.p->execSrNoReplicas = 0;
19254     }//if
19255     loopCount++;
19256     if (loopCount > 20) {
19257       jam();
19258       signal->theData[0] = ZSEND_EXEC_CONF;
19259       signal->theData[1] = next;
19260       sendSignal(cownref, GSN_CONTINUEB, signal, 2, JBB);
19261       return;
19262     } else {
19263       jam();
19264       fragptr.i = next;
19265     }//if
19266   }//while
19267   /* ----------------------------------------------------------------------
19268    *  WE HAVE NOW SENT ALL EXEC_FRAGCONF. NOW IT IS TIME TO SEND
19269    *  EXEC_SRCONF TO ALL NODES.
19270    * --------------------------------------------------------------------- */
19271   srPhase3Comp(signal);
19272 }//Dblqh::sendExecConf()
19273 
19274 /* --------------------------------------------------------------------------
19275  *       PHASE 3 HAS NOW COMPLETED. INFORM ALL OTHER NODES OF THIS EVENT.
19276  * ------------------------------------------------------------------------- */
srPhase3Comp(Signal * signal)19277 void Dblqh::srPhase3Comp(Signal* signal)
19278 {
19279   jamEntry();
19280 
19281   signal->theData[0] = cownNodeid;
19282   if (!isNdbMtLqh())
19283   {
19284     jam();
19285     NodeReceiverGroup rg(DBLQH, m_sr_nodes);
19286     sendSignal(rg, GSN_EXEC_SRCONF, signal, 1, JBB);
19287   }
19288   else
19289   {
19290     jam();
19291     const Uint32 sz = NdbNodeBitmask::Size;
19292     m_sr_nodes.copyto(sz, &signal->theData[1]);
19293     sendSignal(DBLQH_REF, GSN_EXEC_SRCONF, signal, 1 + sz, JBB);
19294   }
19295   return;
19296 }//Dblqh::srPhase3Comp()
19297 
19298 /* ##########################################################################
19299  *    SYSTEM RESTART PHASE FOUR MODULE
19300  *    THIS MODULE IS A SUB-MODULE OF THE FILE SYSTEM HANDLING.
19301  *
19302  *    THIS MODULE SETS UP THE HEAD AND TAIL POINTERS OF THE LOG PARTS IN THE
19303  *    FRAGMENT LOG. WHEN IT IS COMPLETED IT REPORTS TO THE MASTER DIH THAT
19304  *    IT HAS COMPLETED THE PART OF THE SYSTEM RESTART WHERE THE DATABASE IS
19305  *    LOADED.
19306  *    IT ALSO OPENS THE CURRENT LOG FILE AND THE NEXT AND SETS UP THE FIRST
19307  *    LOG PAGE WHERE NEW LOG DATA IS TO BE INSERTED WHEN THE SYSTEM STARTS
19308  *    AGAIN.
19309  *
19310  *    THIS PART IS ACTUALLY EXECUTED FOR ALL RESTART TYPES.
19311  * ######################################################################### */
initFourth(Signal * signal)19312 void Dblqh::initFourth(Signal* signal)
19313 {
19314   LogFileRecordPtr locLogFilePtr;
19315   jamEntry();
19316   logPartPtr.i = signal->theData[0];
19317   ptrCheckGuard(logPartPtr, clogPartFileSize, logPartRecord);
19318   crestartNewestGci = 1;
19319   crestartOldestGci = 1;
19320   /* ------------------------------------------------------------------------
19321    *       INITIALISE LOG PART AND LOG FILES AS NEEDED.
19322    * ----------------------------------------------------------------------- */
19323   logPartPtr.p->headFileNo = 0;
19324   logPartPtr.p->headPageNo = 1;
19325   logPartPtr.p->headPageIndex = ZPAGE_HEADER_SIZE + 2;
19326   logPartPtr.p->logPartState = LogPartRecord::SR_FOURTH_PHASE_STARTED;
19327   logPartPtr.p->logTailFileNo = 0;
19328   logPartPtr.p->logTailMbyte = 0;
19329   locLogFilePtr.i = logPartPtr.p->firstLogfile;
19330   ptrCheckGuard(locLogFilePtr, clogFileFileSize, logFileRecord);
19331   locLogFilePtr.p->logFileStatus = LogFileRecord::OPEN_SR_FOURTH_PHASE;
19332   openFileRw(signal, locLogFilePtr);
19333   return;
19334 }//Dblqh::initFourth()
19335 
openSrFourthPhaseLab(Signal * signal)19336 void Dblqh::openSrFourthPhaseLab(Signal* signal)
19337 {
19338   /* ------------------------------------------------------------------------
19339    *  WE HAVE NOW OPENED THE HEAD LOG FILE WE WILL NOW START READING IT
19340    *  FROM THE HEAD MBYTE TO FIND THE NEW HEAD OF THE LOG.
19341    * ----------------------------------------------------------------------- */
19342   readSinglePage(signal, logPartPtr.p->headPageNo);
19343   lfoPtr.p->lfoState = LogFileOperationRecord::READ_SR_FOURTH_PHASE;
19344   return;
19345 }//Dblqh::openSrFourthPhaseLab()
19346 
readSrFourthPhaseLab(Signal * signal)19347 void Dblqh::readSrFourthPhaseLab(Signal* signal)
19348 {
19349   if(c_diskless){
19350     jam();
19351     logPagePtr.p->logPageWord[ZPOS_LOG_LAP] = 1;
19352   }
19353 
19354   /* ------------------------------------------------------------------------
19355    *  INITIALISE ALL LOG PART INFO AND LOG FILE INFO THAT IS NEEDED TO
19356    *  START UP THE SYSTEM.
19357    * ------------------------------------------------------------------------
19358    *  INITIALISE THE NEWEST GLOBAL CHECKPOINT IDENTITY AND THE NEWEST
19359    *  COMPLETED GLOBAL CHECKPOINT IDENITY AS THE NEWEST THAT WAS RESTARTED.
19360    * ------------------------------------------------------------------------
19361    *  INITIALISE THE HEAD PAGE INDEX IN THIS PAGE.
19362    *  ASSIGN IT AS THE CURRENT LOGPAGE.
19363    *  ASSIGN THE FILE AS THE CURRENT LOG FILE.
19364    *  ASSIGN THE CURRENT FILE NUMBER FROM THE CURRENT LOG FILE AND THE NEXT
19365    *  FILE NUMBER FROM THE NEXT LOG FILE.
19366    *  ASSIGN THE CURRENT FILEPAGE FROM HEAD PAGE NUMBER.
19367    *  ASSIGN THE CURRENT MBYTE BY DIVIDING PAGE NUMBER BY 128.
19368    *  INITIALISE LOG LAP TO BE THE LOG LAP AS FOUND IN THE HEAD PAGE.
19369    *  WE HAVE TO CALCULATE THE NUMBER OF REMAINING WORDS IN THIS MBYTE.
19370    * ----------------------------------------------------------------------- */
19371   Uint32 gci = crestartNewestGci;
19372   if (crestartOldestGci > gci)
19373   {
19374     jam();
19375     /**
19376      * If "keepGci" is bigger than latest-completed-gci
19377      *   move cnewest/cnewestCompletedGci forward
19378      */
19379     ndbout_c("readSrFourthPhaseLab: gci %u => %u",
19380              gci, crestartOldestGci);
19381     gci = crestartOldestGci;
19382   }
19383   cnewestGci = gci;
19384   cnewestCompletedGci = gci;
19385   logPartPtr.p->logPartNewestCompletedGCI = cnewestCompletedGci;
19386   logPartPtr.p->currentLogfile = logFilePtr.i;
19387   logFilePtr.p->filePosition = logPartPtr.p->headPageNo;
19388   logFilePtr.p->currentMbyte =
19389                   logPartPtr.p->headPageNo >> ZTWOLOG_NO_PAGES_IN_MBYTE;
19390   logFilePtr.p->fileChangeState = LogFileRecord::NOT_ONGOING;
19391   logPartPtr.p->logLap = logPagePtr.p->logPageWord[ZPOS_LOG_LAP];
19392   logFilePtr.p->currentFilepage = logPartPtr.p->headPageNo;
19393   logFilePtr.p->currentLogpage = logPagePtr.i;
19394 
19395   initLogpage(signal);
19396   logPagePtr.p->logPageWord[ZCURR_PAGE_INDEX] = logPartPtr.p->headPageIndex;
19397   logFilePtr.p->remainingWordsInMbyte =
19398     ((
19399       ((logFilePtr.p->currentMbyte + 1) * ZPAGES_IN_MBYTE) -
19400      logFilePtr.p->currentFilepage) *
19401     (ZPAGE_SIZE - ZPAGE_HEADER_SIZE)) -
19402       (logPartPtr.p->headPageIndex - ZPAGE_HEADER_SIZE);
19403   /* ------------------------------------------------------------------------
19404    *     THE NEXT STEP IS TO OPEN THE NEXT LOG FILE (IF THERE IS ONE).
19405    * ----------------------------------------------------------------------- */
19406   if (logFilePtr.p->nextLogFile != logFilePtr.i) {
19407     LogFileRecordPtr locLogFilePtr;
19408     jam();
19409     locLogFilePtr.i = logFilePtr.p->nextLogFile;
19410     ptrCheckGuard(locLogFilePtr, clogFileFileSize, logFileRecord);
19411     locLogFilePtr.p->logFileStatus = LogFileRecord::OPEN_SR_FOURTH_NEXT;
19412     openFileRw(signal, locLogFilePtr);
19413   } else {
19414     jam();
19415     /* ----------------------------------------------------------------------
19416      *  THIS CAN ONLY OCCUR IF WE HAVE ONLY ONE LOG FILE. THIS LOG FILE MUST
19417      *  BE LOG FILE ZERO AND THAT IS THE FILE WE CURRENTLY HAVE READ.
19418      *  THUS WE CAN CONTINUE IMMEDIATELY TO READ PAGE ZERO IN FILE ZERO.
19419      * --------------------------------------------------------------------- */
19420     openSrFourthZeroSkipInitLab(signal);
19421     return;
19422   }//if
19423   return;
19424 }//Dblqh::readSrFourthPhaseLab()
19425 
openSrFourthNextLab(Signal * signal)19426 void Dblqh::openSrFourthNextLab(Signal* signal)
19427 {
19428   /* ------------------------------------------------------------------------
19429    *       WE MUST ALSO HAVE FILE 0 OPEN ALL THE TIME.
19430    * ----------------------------------------------------------------------- */
19431   logFilePtr.i = logPartPtr.p->firstLogfile;
19432   ptrCheckGuard(logFilePtr, clogFileFileSize, logFileRecord);
19433   if (logFilePtr.p->logFileStatus == LogFileRecord::OPEN) {
19434     jam();
19435     openSrFourthZeroSkipInitLab(signal);
19436     return;
19437   } else {
19438     jam();
19439     logFilePtr.p->logFileStatus = LogFileRecord::OPEN_SR_FOURTH_ZERO;
19440     openFileRw(signal, logFilePtr);
19441   }//if
19442   return;
19443 }//Dblqh::openSrFourthNextLab()
19444 
openSrFourthZeroLab(Signal * signal)19445 void Dblqh::openSrFourthZeroLab(Signal* signal)
19446 {
19447   openSrFourthZeroSkipInitLab(signal);
19448   return;
19449 }//Dblqh::openSrFourthZeroLab()
19450 
openSrFourthZeroSkipInitLab(Signal * signal)19451 void Dblqh::openSrFourthZeroSkipInitLab(Signal* signal)
19452 {
19453   if (logFilePtr.i == logPartPtr.p->currentLogfile) {
19454     if (logFilePtr.p->currentFilepage == 0) {
19455       jam();
19456       /* -------------------------------------------------------------------
19457        *  THE HEADER PAGE IN THE LOG IS PAGE ZERO IN FILE ZERO.
19458        *  THIS SHOULD NEVER OCCUR.
19459        * ------------------------------------------------------------------- */
19460       systemErrorLab(signal, __LINE__);
19461       return;
19462     }//if
19463   }//if
19464   readSinglePage(signal, 0);
19465   lfoPtr.p->lfoState = LogFileOperationRecord::READ_SR_FOURTH_ZERO;
19466   return;
19467 }//Dblqh::openSrFourthZeroSkipInitLab()
19468 
readSrFourthZeroLab(Signal * signal)19469 void Dblqh::readSrFourthZeroLab(Signal* signal)
19470 {
19471   logFilePtr.p->logPageZero = logPagePtr.i;
19472   // --------------------------------------------------------------------
19473   //   This is moved to invalidateLogAfterLastGCI(), RT453.
19474   //   signal->theData[0] = ZSR_FOURTH_COMP;
19475   //   signal->theData[1] = logPartPtr.i;
19476   //   sendSignal(cownref, GSN_CONTINUEB, signal, 2, JBB);
19477   // --------------------------------------------------------------------
19478 
19479   // Need to invalidate log pages after the head of the log. RT 453. EDTJAMO.
19480   // Set the start of the invalidation.
19481   logFilePtr.i = logPartPtr.p->currentLogfile;
19482   ptrCheckGuard(logFilePtr, clogFileFileSize, logFileRecord);
19483   logPartPtr.p->invalidateFileNo = logPartPtr.p->headFileNo;
19484   logPartPtr.p->invalidatePageNo = logPartPtr.p->headPageNo;
19485   logPartPtr.p->logExecState = LogPartRecord::LES_EXEC_LOG_INVALIDATE;
19486 
19487   readFileInInvalidate(signal, 3);
19488   return;
19489 }//Dblqh::readSrFourthZeroLab()
19490 
19491 /* --------------------------------------------------------------------------
19492  *     ONE OF THE LOG PARTS HAVE COMPLETED PHASE FOUR OF THE SYSTEM RESTART.
19493  *     CHECK IF ALL LOG PARTS ARE COMPLETED. IF SO SEND START_RECCONF
19494  * ------------------------------------------------------------------------- */
srFourthComp(Signal * signal)19495 void Dblqh::srFourthComp(Signal* signal)
19496 {
19497   jamEntry();
19498   logPartPtr.i = signal->theData[0];
19499   ptrCheckGuard(logPartPtr, clogPartFileSize, logPartRecord);
19500   logPartPtr.p->logPartState = LogPartRecord::SR_FOURTH_PHASE_COMPLETED;
19501   for (logPartPtr.i = 0; logPartPtr.i < clogPartFileSize; logPartPtr.i++) {
19502     jam();
19503     ptrAss(logPartPtr, logPartRecord);
19504     if (logPartPtr.p->logPartState != LogPartRecord::SR_FOURTH_PHASE_COMPLETED) {
19505       if (logPartPtr.p->logPartState != LogPartRecord::SR_FOURTH_PHASE_STARTED) {
19506         jam();
19507         systemErrorLab(signal, __LINE__);
19508         return;
19509       } else {
19510         jam();
19511 	/* ------------------------------------------------------------------
19512 	 *  THIS LOG PART WAS NOT COMPLETED YET.
19513 	 *  EXIT AND WAIT FOR IT TO COMPLETE
19514 	 * ----------------------------------------------------------------- */
19515         return;
19516       }//if
19517     }//if
19518   }//for
19519   /* ------------------------------------------------------------------------
19520    *  ALL LOG PARTS HAVE COMPLETED PHASE FOUR OF THE SYSTEM RESTART.
19521    *  WE CAN NOW SEND START_RECCONF TO THE MASTER DIH IF IT WAS A
19522    *  SYSTEM RESTART. OTHERWISE WE WILL CONTINUE WITH AN INITIAL START.
19523    *  SET LOG PART STATE TO IDLE TO
19524    *  INDICATE THAT NOTHING IS GOING ON IN THE LOG PART.
19525    * ----------------------------------------------------------------------- */
19526   for (logPartPtr.i = 0; logPartPtr.i < clogPartFileSize; logPartPtr.i++) {
19527     ptrAss(logPartPtr, logPartRecord);
19528     logPartPtr.p->logPartState = LogPartRecord::IDLE;
19529   }//for
19530 
19531   if ((cstartType == NodeState::ST_INITIAL_START) ||
19532       (cstartType == NodeState::ST_INITIAL_NODE_RESTART)) {
19533     jam();
19534 
19535     ndbrequire(cinitialStartOngoing == ZTRUE);
19536     cinitialStartOngoing = ZFALSE;
19537     cstartRecReq = SRR_REDO_COMPLETE;
19538     checkStartCompletedLab(signal);
19539     return;
19540   } else if ((cstartType == NodeState::ST_NODE_RESTART) ||
19541              (cstartType == NodeState::ST_SYSTEM_RESTART)) {
19542     jam();
19543 
19544     if(cstartType == NodeState::ST_SYSTEM_RESTART)
19545     {
19546       jam();
19547       if (c_lcp_complete_fragments.first(fragptr))
19548       {
19549 	jam();
19550         signal->theData[0] = ZENABLE_EXPAND_CHECK;
19551         signal->theData[1] = fragptr.i;
19552         sendSignal(reference(), GSN_CONTINUEB, signal, 2, JBB);
19553 	return;
19554       }
19555     }
19556 
19557     cstartRecReq = SRR_REDO_COMPLETE; // REDO complete
19558 
19559     rebuildOrderedIndexes(signal, 0);
19560     return;
19561   } else {
19562     ndbrequire(false);
19563   }//if
19564   return;
19565 }//Dblqh::srFourthComp()
19566 
19567 /* ######################################################################### */
19568 /* #######                            ERROR MODULE                   ####### */
19569 /*                                                                           */
19570 /* ######################################################################### */
19571 
19572 /*---------------------------------------------------------------------------*/
19573 /* AN ERROR OCCURRED THAT WE WILL NOT TREAT AS SYSTEM ERROR. MOST OFTEN THIS */
19574 /* WAS CAUSED BY AN ERRONEUS SIGNAL SENT BY ANOTHER NODE. WE DO NOT WISH TO  */
19575 /* CRASH BECAUSE OF FAULTS IN OTHER NODES. THUS WE ONLY REPORT A WARNING.    */
19576 /* THIS IS CURRENTLY NOT IMPLEMENTED AND FOR THE MOMENT WE GENERATE A SYSTEM */
19577 /* ERROR SINCE WE WANT TO FIND FAULTS AS QUICKLY AS POSSIBLE IN A TEST PHASE.*/
19578 /* IN A LATER PHASE WE WILL CHANGE THIS TO BE A WARNING MESSAGE INSTEAD.     */
19579 /*---------------------------------------------------------------------------*/
19580 /*---------------------------------------------------------------------------*/
19581 /*      THIS TYPE OF ERROR SHOULD NOT GENERATE A SYSTEM ERROR IN A PRODUCT   */
19582 /*      RELEASE. THIS IS A TEMPORARY SOLUTION DURING TEST PHASE TO QUICKLY   */
19583 /*      FIND ERRORS. NORMALLY THIS SHOULD GENERATE A WARNING MESSAGE ONTO    */
19584 /*      SOME ERROR LOGGER. THIS WILL LATER BE IMPLEMENTED BY SOME SIGNAL.    */
19585 /*---------------------------------------------------------------------------*/
19586 /* ------ SYSTEM ERROR SITUATIONS ------- */
19587 /*      IN SITUATIONS WHERE THE STATE IS ERRONEOUS OR IF THE ERROR OCCURS IN */
19588 /*      THE COMMIT, COMPLETE OR ABORT PHASE, WE PERFORM A CRASH OF THE AXE VM*/
19589 /*---------------------------------------------------------------------------*/
19590 
systemErrorLab(Signal * signal,int line)19591 void Dblqh::systemErrorLab(Signal* signal, int line)
19592 {
19593   systemError(signal, line);
19594   progError(line, NDBD_EXIT_NDBREQUIRE);
19595 /*************************************************************************>*/
19596 /*       WE WANT TO INVOKE AN IMMEDIATE ERROR HERE SO WE GET THAT BY       */
19597 /*       INSERTING A CERTAIN POINTER OUT OF RANGE.                         */
19598 /*************************************************************************>*/
19599 }//Dblqh::systemErrorLab()
19600 
19601 /* ------- ERROR SITUATIONS ------- */
19602 
aiStateErrorCheckLab(Signal * signal,Uint32 * dataPtr,Uint32 length)19603 void Dblqh::aiStateErrorCheckLab(Signal* signal, Uint32* dataPtr, Uint32 length)
19604 {
19605   ndbrequire(tcConnectptr.p->abortState != TcConnectionrec::ABORT_IDLE);
19606   if (tcConnectptr.p->transactionState != TcConnectionrec::IDLE) {
19607       jam();
19608 /*************************************************************************>*/
19609 /*       TRANSACTION ABORT IS ONGOING. IT CAN STILL BE A PART OF AN        */
19610 /*       OPERATION THAT SHOULD CONTINUE SINCE THE TUPLE HAS NOT ARRIVED    */
19611 /*       YET. THIS IS POSSIBLE IF ACTIVE CREATION OF THE FRAGMENT IS       */
19612 /*       ONGOING.                                                          */
19613 /*************************************************************************>*/
19614     if (tcConnectptr.p->activeCreat == Fragrecord::AC_IGNORED) {
19615         jam();
19616 /*************************************************************************>*/
19617 /*       ONGOING ABORTS DURING ACTIVE CREATION MUST SAVE THE ATTRIBUTE INFO*/
19618 /*       SO THAT IT CAN BE SENT TO THE NEXT NODE IN THE COMMIT CHAIN. THIS */
19619 /*       IS NEEDED SINCE ALL ABORTS DURING CREATION OF A FRAGMENT ARE NOT  */
19620 /*       REALLY ERRORS. A MISSING TUPLE TO BE UPDATED SIMPLY MEANS THAT    */
19621 /*       IT HASN'T BEEN TRANSFERRED TO THE NEW REPLICA YET.                */
19622 /*************************************************************************>*/
19623 /*************************************************************************>*/
19624 /*       AFTER THIS ERROR THE ABORT MUST BE COMPLETED. TO ENSURE THIS SET  */
19625 /*       ACTIVE CREATION TO FALSE. THIS WILL ENSURE THAT THE ABORT IS      */
19626 /*       COMPLETED.                                                        */
19627 /*************************************************************************>*/
19628       if (saveAttrInfoInSection(dataPtr, length) == ZOK) {
19629         jam();
19630         if (tcConnectptr.p->transactionState ==
19631             TcConnectionrec::WAIT_AI_AFTER_ABORT) {
19632           if (tcConnectptr.p->currTupAiLen == tcConnectptr.p->totReclenAi) {
19633             jam();
19634 /*************************************************************************>*/
19635 /*       WE WERE WAITING FOR MORE ATTRIBUTE INFO AFTER A SUCCESSFUL ABORT  */
19636 /*       IN ACTIVE CREATION STATE. THE TRANSACTION SHOULD CONTINUE AS IF   */
19637 /*       IT WAS COMMITTED. NOW ALL INFO HAS ARRIVED AND WE CAN CONTINUE    */
19638 /*       WITH NORMAL PROCESSING AS IF THE TRANSACTION WAS PREPARED.        */
19639 /*       SINCE THE FRAGMENT IS UNDER CREATION WE KNOW THAT LOGGING IS      */
19640 /*       DISABLED. WE STILL HAVE TO CATER FOR DIRTY OPERATION OR NOT.      */
19641 /*************************************************************************>*/
19642             tcConnectptr.p->abortState = TcConnectionrec::ABORT_IDLE;
19643             rwConcludedAiLab(signal);
19644             return;
19645           } else {
19646             ndbrequire(tcConnectptr.p->currTupAiLen < tcConnectptr.p->totReclenAi);
19647             jam();
19648             return;	/* STILL WAITING FOR MORE ATTRIBUTE INFO */
19649           }//if
19650         }//if
19651       } else {
19652         jam();
19653 /*************************************************************************>*/
19654 /*       AFTER THIS ERROR THE ABORT MUST BE COMPLETED. TO ENSURE THIS SET  */
19655 /*       ACTIVE CREATION TO ABORT. THIS WILL ENSURE THAT THE ABORT IS      */
19656 /*       COMPLETED AND THAT THE ERROR CODE IS PROPERLY SET                 */
19657 /*************************************************************************>*/
19658         tcConnectptr.p->errorCode = terrorCode;
19659         tcConnectptr.p->activeCreat = Fragrecord::AC_NORMAL;
19660         if (tcConnectptr.p->transactionState ==
19661 	    TcConnectionrec::WAIT_AI_AFTER_ABORT) {
19662           jam();
19663 /*************************************************************************>*/
19664 /*       ABORT IS ALREADY COMPLETED. WE NEED TO RESTART IT FROM WHERE IT   */
19665 /*       WAS INTERRUPTED.                                                  */
19666 /*************************************************************************>*/
19667           continueAbortLab(signal);
19668           return;
19669         } else {
19670           jam();
19671           return;
19672 /*************************************************************************>*/
19673 // Abort is ongoing. It will complete since we set the activeCreat = ZFALSE
19674 /*************************************************************************>*/
19675         }//if
19676       }//if
19677     }//if
19678   }//if
19679 /*************************************************************************>*/
19680 /* TRANSACTION HAVE BEEN ABORTED. THUS IGNORE ALL SIGNALS BELONGING TO IT. */
19681 /*************************************************************************>*/
19682   return;
19683 }//Dblqh::aiStateErrorCheckLab()
19684 
takeOverErrorLab(Signal * signal)19685 void Dblqh::takeOverErrorLab(Signal* signal)
19686 {
19687   terrorCode = ZTAKE_OVER_ERROR;
19688   abortErrorLab(signal);
19689   return;
19690 }//Dblqh::takeOverErrorLab()
19691 
19692 /* ##########################################################################
19693  *               TEST MODULE
19694  * ######################################################################### */
19695 #ifdef VM_TRACE
execTESTSIG(Signal * signal)19696 void Dblqh::execTESTSIG(Signal* signal)
19697 {
19698   jamEntry();
19699   Uint32 userpointer = signal->theData[0];
19700   BlockReference userblockref = signal->theData[1];
19701   Uint32 testcase = signal->theData[2];
19702 
19703   signal->theData[0] = userpointer;
19704   signal->theData[1] = cownref;
19705   signal->theData[2] = testcase;
19706   sendSignal(userblockref, GSN_TESTSIG, signal, 25, JBB);
19707   return;
19708 }//Dblqh::execTESTSIG()
19709 
19710 /* *************** */
19711 /*  MEMCHECKREQ  > */
19712 /* *************** */
19713 /* ************************************************************************>>
19714  * THIS SIGNAL IS PURELY FOR TESTING PURPOSES. IT CHECKS THE FREE LIST
19715  * AND REPORTS THE NUMBER OF FREE RECORDS.
19716  * THIS CAN BE DONE TO ENSURE THAT NO RECORDS HAS BEEN LOST
19717  * ************************************************************************> */
execMEMCHECKREQ(Signal * signal)19718 void Dblqh::execMEMCHECKREQ(Signal* signal)
19719 {
19720   Uint32* dataPtr = &signal->theData[0];
19721   jamEntry();
19722   BlockReference userblockref = signal->theData[0];
19723   Uint32 index = 0;
19724   for (Uint32 i = 0; i < 7; i++)
19725     dataPtr[i] = 0;
19726   addfragptr.i = cfirstfreeAddfragrec;
19727   while (addfragptr.i != RNIL) {
19728     ptrCheckGuard(addfragptr, caddfragrecFileSize, addFragRecord);
19729     addfragptr.i = addfragptr.p->nextAddfragrec;
19730     dataPtr[index]++;
19731   }//while
19732   index++;
19733   dataPtr[index]= 0;
19734   index++;
19735   dataPtr[index]= 0;
19736   index++;
19737   for (tabptr.i = 0;
19738        tabptr.i < ctabrecFileSize;
19739        tabptr.i++) {
19740     ptrAss(tabptr, tablerec);
19741     if (tabptr.p->tableStatus == Tablerec::NOT_DEFINED) {
19742       dataPtr[index]++;
19743     }//if
19744   }//for
19745   index++;
19746   tcConnectptr.i = cfirstfreeTcConrec;
19747   while (tcConnectptr.i != RNIL) {
19748     ptrCheckGuard(tcConnectptr, ctcConnectrecFileSize, tcConnectionrec);
19749     tcConnectptr.i = tcConnectptr.p->nextTcConnectrec;
19750     dataPtr[index]++;
19751   }//while
19752   sendSignal(userblockref, GSN_MEMCHECKCONF, signal, 10, JBB);
19753   return;
19754 }//Dblqh::execMEMCHECKREQ()
19755 
19756 #endif
19757 
19758 /* ************************************************************************* */
19759 /* ************************* STATEMENT BLOCKS ****************************** */
19760 /* ************************************************************************* */
19761 /* ========================================================================= */
19762 /* ====== BUILD LINKED LIST OF LOG PAGES AFTER RECEIVING FSREADCONF  ======= */
19763 /*                                                                           */
19764 /* ========================================================================= */
buildLinkedLogPageList(Signal * signal)19765 void Dblqh::buildLinkedLogPageList(Signal* signal)
19766 {
19767   LogPageRecordPtr bllLogPagePtr;
19768 
19769   arrGuard(lfoPtr.p->noPagesRw - 1, 16);
19770   arrGuard(lfoPtr.p->noPagesRw, 16);
19771   Uint32 prev = RNIL;
19772   for (UintR tbllIndex = 0; tbllIndex < lfoPtr.p->noPagesRw; tbllIndex++) {
19773     jam();
19774     /* ----------------------------------------------------------------------
19775      *  BUILD LINKED LIST BUT ALSO ENSURE THAT PAGE IS NOT SEEN AS DIRTY
19776      *  INITIALLY.
19777      * --------------------------------------------------------------------- */
19778     bllLogPagePtr.i = lfoPtr.p->logPageArray[tbllIndex];
19779     ptrCheckGuard(bllLogPagePtr, clogPageFileSize, logPageRecord);
19780 
19781 // #if VM_TRACE
19782 //     // Check logPage checksum before modifying it
19783 //     Uint32 calcCheckSum = calcPageCheckSum(bllLogPagePtr);
19784 //     Uint32 checkSum = bllLogPagePtr.p->logPageWord[ZPOS_CHECKSUM];
19785 //     if (checkSum != calcCheckSum) {
19786 //       ndbout << "Redolog: Checksum failure." << endl;
19787 //       progError(__LINE__, NDBD_EXIT_NDBREQUIRE, "Redolog: Checksum failure.");
19788 //     }
19789 // #endif
19790 
19791     bllLogPagePtr.p->logPageWord[ZPREV_PAGE] = prev;
19792     bllLogPagePtr.p->logPageWord[ZNEXT_PAGE] =
19793       lfoPtr.p->logPageArray[tbllIndex + 1];
19794     bllLogPagePtr.p->logPageWord[ZPOS_DIRTY] = ZNOT_DIRTY;
19795     prev = bllLogPagePtr.i;
19796   }//for
19797   bllLogPagePtr.i = lfoPtr.p->logPageArray[lfoPtr.p->noPagesRw - 1];
19798   ptrCheckGuard(bllLogPagePtr, clogPageFileSize, logPageRecord);
19799   bllLogPagePtr.p->logPageWord[ZNEXT_PAGE] = RNIL;
19800 }//Dblqh::buildLinkedLogPageList()
19801 
19802 /* =========================================================================
19803  * =======                      CHANGE TO NEXT MBYTE IN LOG           =======
19804  *
19805  * ========================================================================= */
changeMbyte(Signal * signal)19806 void Dblqh::changeMbyte(Signal* signal)
19807 {
19808   writeNextLog(signal);
19809   writeFileDescriptor(signal);
19810 }//Dblqh::changeMbyte()
19811 
19812 /* ========================================================================= */
19813 /* ======       CHECK IF THIS COMMIT LOG RECORD IS TO BE EXECUTED    ======= */
19814 /*                                                                           */
19815 /*      SUBROUTINE SHORT NAME = CEL                                          */
19816 /* ========================================================================= */
checkIfExecLog(Signal * signal)19817 Uint32 Dblqh::checkIfExecLog(Signal* signal)
19818 {
19819   tabptr.i = tcConnectptr.p->tableref;
19820   ptrCheckGuard(tabptr, ctabrecFileSize, tablerec);
19821   if (getFragmentrec(signal, tcConnectptr.p->fragmentid) &&
19822       (table_version_major(tabptr.p->schemaVersion) == table_version_major(tcConnectptr.p->schemaVersion))) {
19823     if (fragptr.p->execSrStatus != Fragrecord::IDLE) {
19824       if (fragptr.p->execSrNoReplicas > logPartPtr.p->execSrExecuteIndex) {
19825         ndbrequire((fragptr.p->execSrNoReplicas - 1) < MAX_REPLICAS);
19826         for (Uint32 i = logPartPtr.p->execSrExecuteIndex;
19827 	     i < fragptr.p->execSrNoReplicas;
19828 	     i++) {
19829           jam();
19830           if (tcConnectptr.p->gci_hi >= fragptr.p->execSrStartGci[i]) {
19831             if (tcConnectptr.p->gci_hi <= fragptr.p->execSrLastGci[i]) {
19832               jam();
19833               logPartPtr.p->execSrExecuteIndex = i;
19834               return ZOK;
19835             }//if
19836           }//if
19837         }//for
19838       }//if
19839     }//if
19840   }//if
19841   return ZNOT_OK;
19842 }//Dblqh::checkIfExecLog()
19843 
19844 /* ========================================================================= */
19845 /* == CHECK IF THERE IS LESS THAN 192 KBYTE IN THE BUFFER PLUS INCOMING  === */
19846 /*      READS ALREADY STARTED. IF SO IS THE CASE THEN START ANOTHER READ IF  */
19847 /*      THERE ARE MORE PAGES IN THIS MBYTE.                                  */
19848 /*                                                                           */
19849 /* ========================================================================= */
checkReadExecSr(Signal * signal)19850 void Dblqh::checkReadExecSr(Signal* signal)
19851 {
19852   logPartPtr.p->logExecState = LogPartRecord::LES_EXEC_LOG;
19853   logPartPtr.p->execSrPagesRead = logPartPtr.p->execSrPagesRead + 8;
19854   logPartPtr.p->execSrPagesReading = logPartPtr.p->execSrPagesReading - 8;
19855   if ((logPartPtr.p->execSrPagesRead + logPartPtr.p->execSrPagesReading) <
19856       ZREAD_AHEAD_SIZE) {
19857     jam();
19858     /* ----------------------------------------------------------------------
19859      *  WE HAVE LESS THAN 64 KBYTE OF LOG PAGES REMAINING IN MEMORY OR ON
19860      *  ITS WAY TO MAIN MEMORY. READ IN 8 MORE PAGES.
19861      * --------------------------------------------------------------------- */
19862     if ((logPartPtr.p->execSrPagesRead + logPartPtr.p->execSrPagesExecuted) <
19863 	ZPAGES_IN_MBYTE) {
19864       jam();
19865       /* --------------------------------------------------------------------
19866        *  THERE ARE MORE PAGES TO READ IN THIS MBYTE. READ THOSE FIRST
19867        *  IF >= ZPAGES_IN_MBYTE THEN THERE ARE NO MORE PAGES TO READ. THUS
19868        *  WE PROCEED WITH EXECUTION OF THE LOG.
19869        * ------------------------------------------------------------------- */
19870       readExecSr(signal);
19871       logPartPtr.p->logExecState = LogPartRecord::LES_WAIT_READ_EXEC_SR;
19872     }//if
19873   }//if
19874 }//Dblqh::checkReadExecSr()
19875 
19876 /* ========================================================================= */
19877 /* ==== CHECK IF START OF NEW FRAGMENT IS COMPLETED AND WE CAN       ======= */
19878 /* ==== GET THE START GCI                                            ======= */
19879 /*                                                                           */
19880 /*      SUBROUTINE SHORT NAME = CTC                                          */
19881 /* ========================================================================= */
checkScanTcCompleted(Signal * signal)19882 void Dblqh::checkScanTcCompleted(Signal* signal)
19883 {
19884   tcConnectptr.p->logWriteState = TcConnectionrec::NOT_STARTED;
19885   fragptr.i = tcConnectptr.p->fragmentptr;
19886   c_fragment_pool.getPtr(fragptr);
19887   fragptr.p->activeTcCounter = fragptr.p->activeTcCounter - 1;
19888   if (fragptr.p->activeTcCounter == 0) {
19889     jam();
19890     fragptr.p->startGci = cnewestGci + 1;
19891     tabptr.i = tcConnectptr.p->tableref;
19892     ptrCheckGuard(tabptr, ctabrecFileSize, tablerec);
19893     sendCopyActiveConf(signal, tcConnectptr.p->tableref);
19894   }//if
19895 }//Dblqh::checkScanTcCompleted()
19896 
19897 /* ------------------------------------------------------------------------- */
19898 /* ------       CLOSE A FILE DURING EXECUTION OF FRAGMENT LOG        ------- */
19899 /*                                                                           */
19900 /* ------------------------------------------------------------------------- */
closeFile(Signal * signal,LogFileRecordPtr clfLogFilePtr,Uint32 line)19901 void Dblqh::closeFile(Signal* signal,
19902 		      LogFileRecordPtr clfLogFilePtr, Uint32 line)
19903 {
19904   signal->theData[0] = clfLogFilePtr.p->fileRef;
19905   signal->theData[1] = cownref;
19906   signal->theData[2] = clfLogFilePtr.i;
19907   signal->theData[3] = ZCLOSE_NO_DELETE;
19908   signal->theData[4] = line;
19909   sendSignal(NDBFS_REF, GSN_FSCLOSEREQ, signal, 5, JBA);
19910 }//Dblqh::closeFile()
19911 
19912 
19913 /* ---------------------------------------------------------------- */
19914 /* ---------------- A LOG PAGE HAVE BEEN COMPLETED ---------------- */
19915 /*                                                                  */
19916 /*       SUBROUTINE SHORT NAME = CLP                                */
19917 // Input Pointers:
19918 // logFilePtr
19919 // logPagePtr
19920 // logPartPtr
19921 // Defines lfoPtr
19922 /* ---------------------------------------------------------------- */
completedLogPage(Signal * signal,Uint32 clpType,Uint32 place)19923 void Dblqh::completedLogPage(Signal* signal, Uint32 clpType, Uint32 place)
19924 {
19925   LogPageRecordPtr clpLogPagePtr;
19926   LogPageRecordPtr wlpLogPagePtr;
19927   UintR twlpNoPages;
19928   UintR twlpType;
19929 
19930   if (logFilePtr.p->firstFilledPage == RNIL) {
19931     jam();
19932     logFilePtr.p->firstFilledPage = logPagePtr.i;
19933   } else {
19934     jam();
19935     clpLogPagePtr.i = logFilePtr.p->lastFilledPage;
19936     ptrCheckGuard(clpLogPagePtr, clogPageFileSize, logPageRecord);
19937     clpLogPagePtr.p->logPageWord[ZNEXT_PAGE] = logPagePtr.i;
19938   }//if
19939   logFilePtr.p->lastFilledPage = logPagePtr.i;
19940   logPagePtr.p->logPageWord[ZNEXT_PAGE] = RNIL;
19941   logFilePtr.p->noLogpagesInBuffer = logFilePtr.p->noLogpagesInBuffer + 1;
19942   if (logFilePtr.p->noLogpagesInBuffer != ZMAX_PAGES_WRITTEN) {
19943     if (clpType != ZLAST_WRITE_IN_FILE) {
19944       if (clpType != ZENFORCE_WRITE) {
19945         jam();
19946         return;
19947       }//if
19948     }//if
19949   }//if
19950   twlpType = clpType;
19951 /* ------------------------------------------------------------------------- */
19952 /* ------               WRITE A SET OF LOG PAGES TO DISK             ------- */
19953 /*                                                                           */
19954 /*      SUBROUTINE SHORT NAME: WLP                                           */
19955 /* ------------------------------------------------------------------------- */
19956   seizeLfo(signal);
19957   initLfo(signal);
19958   Uint32* dataPtr = &signal->theData[6];
19959   twlpNoPages = 0;
19960   wlpLogPagePtr.i = logFilePtr.p->firstFilledPage;
19961   do {
19962     dataPtr[twlpNoPages] = wlpLogPagePtr.i;
19963     twlpNoPages++;
19964     ptrCheckGuard(wlpLogPagePtr, clogPageFileSize, logPageRecord);
19965 
19966     writeDbgInfoPageHeader(wlpLogPagePtr, place,
19967                            logFilePtr.p->filePosition + twlpNoPages - 1,
19968                            ZPAGE_SIZE);
19969     // Calculate checksum for page
19970     wlpLogPagePtr.p->logPageWord[ZPOS_CHECKSUM] = calcPageCheckSum(wlpLogPagePtr);
19971     wlpLogPagePtr.i = wlpLogPagePtr.p->logPageWord[ZNEXT_PAGE];
19972   } while (wlpLogPagePtr.i != RNIL);
19973   ndbrequire(twlpNoPages < 9);
19974   dataPtr[twlpNoPages] = logFilePtr.p->filePosition;
19975 /* -------------------------------------------------- */
19976 /*       SET TIMER ON THIS LOG PART TO SIGNIFY THAT A */
19977 /*       LOG RECORD HAS BEEN SENT AT THIS TIME.       */
19978 /* -------------------------------------------------- */
19979   logPartPtr.p->logPartTimer = logPartPtr.p->logTimer;
19980   signal->theData[0] = logFilePtr.p->fileRef;
19981   signal->theData[1] = cownref;
19982   signal->theData[2] = lfoPtr.i;
19983   if (twlpType == ZLAST_WRITE_IN_FILE) {
19984     jam();
19985     signal->theData[3] = ZLIST_OF_MEM_PAGES_SYNCH;
19986   } else {
19987     jam();
19988     signal->theData[3] = ZLIST_OF_MEM_PAGES;
19989   }//if
19990   signal->theData[4] = ZVAR_NO_LOG_PAGE_WORD;
19991   signal->theData[5] = twlpNoPages;
19992   sendSignal(NDBFS_REF, GSN_FSWRITEREQ, signal, 15, JBA);
19993 
19994   ndbrequire(logFilePtr.p->fileRef != RNIL);
19995 
19996   logPartPtr.p->m_io_tracker.send_io(32768*twlpNoPages);
19997 
19998   if (DEBUG_REDO)
19999   {
20000     ndbout_c("writing %d pages at part: %u file: %u page: %u (mb: %u)",
20001              twlpNoPages,
20002              logPartPtr.p->logPartNo,
20003              logFilePtr.p->fileNo,
20004              logFilePtr.p->filePosition,
20005              logFilePtr.p->filePosition >> ZTWOLOG_NO_PAGES_IN_MBYTE);
20006   }
20007 
20008   if (twlpType == ZNORMAL) {
20009     jam();
20010     lfoPtr.p->lfoState = LogFileOperationRecord::ACTIVE_WRITE_LOG;
20011   } else if (twlpType == ZLAST_WRITE_IN_FILE) {
20012     jam();
20013     lfoPtr.p->lfoState = LogFileOperationRecord::LAST_WRITE_IN_FILE;
20014   } else {
20015     ndbrequire(twlpType == ZENFORCE_WRITE);
20016     jam();
20017     lfoPtr.p->lfoState = LogFileOperationRecord::ACTIVE_WRITE_LOG;
20018   }//if
20019   /* ----------------------------------------------------------------------- */
20020   /* ------       MOVE PAGES FROM LOG FILE TO LFO RECORD             ------- */
20021   /*                                                                         */
20022   /* ----------------------------------------------------------------------- */
20023   /* -------------------------------------------------- */
20024   /*       MOVE PAGES TO LFO RECORD AND REMOVE THEM     */
20025   /*       FROM LOG FILE RECORD.                        */
20026   /* -------------------------------------------------- */
20027   lfoPtr.p->firstLfoPage = logFilePtr.p->firstFilledPage;
20028   logFilePtr.p->firstFilledPage = RNIL;
20029   logFilePtr.p->lastFilledPage = RNIL;
20030   logFilePtr.p->noLogpagesInBuffer = 0;
20031 
20032   lfoPtr.p->noPagesRw = twlpNoPages;
20033   lfoPtr.p->lfoPageNo = logFilePtr.p->filePosition;
20034   lfoPtr.p->lfoWordWritten = ZPAGE_SIZE - 1;
20035   logFilePtr.p->filePosition += twlpNoPages;
20036 }//Dblqh::completedLogPage()
20037 
20038 /* ---------------------------------------------------------------- */
20039 /* ---------------- DELETE FRAGMENT RECORD ------------------------ */
20040 /*                                                                  */
20041 /*       SUBROUTINE SHORT NAME = DFR                                */
20042 /* ---------------------------------------------------------------- */
deleteFragrec(Uint32 fragId)20043 void Dblqh::deleteFragrec(Uint32 fragId)
20044 {
20045   Uint32 indexFound= RNIL;
20046   fragptr.i = RNIL;
20047   for (Uint32 i = 0; i < MAX_FRAG_PER_NODE; i++) {
20048     jam();
20049     if (tabptr.p->fragid[i] == fragId) {
20050       fragptr.i = tabptr.p->fragrec[i];
20051       indexFound = i;
20052       break;
20053     }//if
20054   }//for
20055   if (fragptr.i != RNIL) {
20056     jam();
20057     c_fragment_pool.getPtr(fragptr);
20058     tabptr.p->fragid[indexFound] = ZNIL;
20059     tabptr.p->fragrec[indexFound] = RNIL;
20060     fragptr.p->fragStatus = Fragrecord::FREE;
20061     c_fragment_pool.release(fragptr);
20062   }//if
20063 }//Dblqh::deleteFragrec()
20064 
20065 /* ------------------------------------------------------------------------- */
20066 /* -------          FIND LOG FILE RECORD GIVEN FILE NUMBER           ------- */
20067 /*                                                                           */
20068 /*       INPUT:          TFLF_FILE_NO    THE FILE NUMBER                     */
20069 /*                       FLF_LOG_PART_PTR THE LOG PART RECORD                */
20070 /*       OUTPUT:         FLF_LOG_FILE_PTR THE FOUND LOG FILE RECORD          */
20071 /*       SUBROUTINE SHORT NAME = FLF                                         */
20072 /* ------------------------------------------------------------------------- */
findLogfile(Signal * signal,Uint32 fileNo,LogPartRecordPtr flfLogPartPtr,LogFileRecordPtr * parLogFilePtr)20073 void Dblqh::findLogfile(Signal* signal,
20074                         Uint32 fileNo,
20075                         LogPartRecordPtr flfLogPartPtr,
20076                         LogFileRecordPtr* parLogFilePtr)
20077 {
20078   LogFileRecordPtr locLogFilePtr;
20079   locLogFilePtr.i = flfLogPartPtr.p->firstLogfile;
20080   Uint32 loopCount = 0;
20081   while (true) {
20082     ptrCheckGuard(locLogFilePtr, clogFileFileSize, logFileRecord);
20083     if (locLogFilePtr.p->fileNo == fileNo) {
20084       jam();
20085       ndbrequire(loopCount == fileNo);
20086       parLogFilePtr->i = locLogFilePtr.i;
20087       parLogFilePtr->p = locLogFilePtr.p;
20088       return;
20089     }//if
20090     locLogFilePtr.i = locLogFilePtr.p->nextLogFile;
20091     loopCount++;
20092     if (loopCount >= flfLogPartPtr.p->noLogFiles &&
20093 	getNodeState().startLevel != NodeState::SL_STARTED)
20094     {
20095       goto error;
20096     }
20097     ndbrequire(loopCount < flfLogPartPtr.p->noLogFiles);
20098   }//while
20099 
20100 error:
20101   char buf[255];
20102   BaseString::snprintf(buf, sizeof(buf),
20103 		       "Unable to restart, failed while reading redo."
20104 		       " Likely invalid change of configuration");
20105   progError(__LINE__,
20106 	    NDBD_EXIT_INVALID_CONFIG,
20107 	    buf);
20108 }//Dblqh::findLogfile()
20109 
20110 /* ------------------------------------------------------------------------- */
20111 /* ------     FIND PAGE REFERENCE IN MEMORY BUFFER AT LOG EXECUTION  ------- */
20112 /*                                                                           */
20113 /* ------------------------------------------------------------------------- */
findPageRef(Signal * signal,CommitLogRecord * commitLogRecord)20114 void Dblqh::findPageRef(Signal* signal, CommitLogRecord* commitLogRecord)
20115 {
20116   UintR tfprIndex;
20117 
20118   logPagePtr.i = RNIL;
20119   if (ERROR_INSERTED(5020)) {
20120     // Force system to read page from disk
20121     return;
20122   }
20123   pageRefPtr.i = logPartPtr.p->lastPageRef;
20124   do {
20125     ptrCheckGuard(pageRefPtr, cpageRefFileSize, pageRefRecord);
20126     if (commitLogRecord->fileNo == pageRefPtr.p->prFileNo) {
20127       if (commitLogRecord->startPageNo >= pageRefPtr.p->prPageNo) {
20128         if (commitLogRecord->startPageNo < (Uint16) (pageRefPtr.p->prPageNo + 8)) {
20129           jam();
20130           tfprIndex = commitLogRecord->startPageNo - pageRefPtr.p->prPageNo;
20131           logPagePtr.i = pageRefPtr.p->pageRef[tfprIndex];
20132           ptrCheckGuard(logPagePtr, clogPageFileSize, logPageRecord);
20133           return;
20134         }//if
20135       }//if
20136     }//if
20137     pageRefPtr.i = pageRefPtr.p->prPrev;
20138   } while (pageRefPtr.i != RNIL);
20139 
20140 #ifndef NO_REDO_PAGE_CACHE
20141   RedoPageCache& cache = m_redo_page_cache;
20142   RedoCacheLogPageRecord key;
20143   key.m_part_no = logPartPtr.p->logPartNo;
20144   key.m_file_no = commitLogRecord->fileNo;
20145   key.m_page_no = commitLogRecord->startPageNo;
20146   Ptr<RedoCacheLogPageRecord> pagePtr;
20147   if (cache.m_hash.find(pagePtr, key))
20148   {
20149     jam();
20150     if (cache.m_lru.hasPrev(pagePtr))
20151     {
20152       jam();
20153       cache.m_lru.remove(pagePtr);
20154       cache.m_lru.addFirst(pagePtr);
20155     }
20156     logPagePtr.i = pagePtr.i;
20157     ptrCheckGuard(logPagePtr, clogPageFileSize, logPageRecord);
20158 
20159     Ptr<LogPageRecord> loopPtr = logPagePtr;
20160     Uint32 extra = commitLogRecord->stopPageNo - commitLogRecord->startPageNo;
20161     for (Uint32 i = 0; i<extra; i++)
20162     {
20163       jam();
20164       Uint32 prevPtrI = loopPtr.i;
20165       loopPtr.i = loopPtr.p->logPageWord[ZNEXT_PAGE];
20166       if (loopPtr.i == RNIL)
20167       {
20168         jam();
20169         /**
20170          * next page is not linked
20171          *   check if it's added as a "single" page
20172          */
20173         key.m_page_no = commitLogRecord->startPageNo + i + 1;
20174         if (cache.m_hash.find(pagePtr, key))
20175         {
20176           jam();
20177           /**
20178            * Yes it is...link them
20179            */
20180           Ptr<LogPageRecord> tmp;
20181           tmp.i = pagePtr.i;
20182           tmp.p = reinterpret_cast<LogPageRecord*>(pagePtr.p);
20183           tmp.p->logPageWord[ZPREV_PAGE] = prevPtrI;
20184           loopPtr.p->logPageWord[ZNEXT_PAGE] = tmp.i;
20185           loopPtr.i = tmp.i;
20186         }
20187         else
20188         {
20189           jam();
20190           logPagePtr.i = RNIL;
20191           cache.m_multi_miss++;
20192           if (0)
20193           ndbout_c("Found part: %u file: %u page: %u but not next page(%u) %u",
20194                    key.m_part_no,
20195                    commitLogRecord->fileNo,
20196                    commitLogRecord->startPageNo,
20197                    (i + 1),
20198                    commitLogRecord->startPageNo + i + 1);
20199           return;
20200         }
20201       }
20202 
20203       ptrCheckGuard(loopPtr, clogPageFileSize, logPageRecord);
20204       pagePtr.i = loopPtr.i;
20205       pagePtr.p = reinterpret_cast<RedoCacheLogPageRecord*>(loopPtr.p);
20206       if (cache.m_lru.hasPrev(pagePtr))
20207       {
20208         jam();
20209         cache.m_lru.remove(pagePtr);
20210         cache.m_lru.addFirst(pagePtr);
20211       }
20212     }
20213     cache.m_hits++;
20214     if (extra)
20215     {
20216       jam();
20217       cache.m_multi_page++;
20218     }
20219   }
20220 #endif
20221 }//Dblqh::findPageRef()
20222 
20223 /* ------------------------------------------------------------------------- */
20224 /* ------         GET FIRST OPERATION QUEUED FOR LOGGING             ------- */
20225 /*                                                                           */
20226 /*      SUBROUTINE SHORT NAME = GFL                                          */
20227 /* ------------------------------------------------------------------------- */
20228 void
getFirstInLogQueue(Signal * signal,Ptr<TcConnectionrec> & dst)20229 Dblqh::getFirstInLogQueue(Signal* signal,
20230                           Ptr<TcConnectionrec> & dst)
20231 {
20232   TcConnectionrecPtr tmp;
20233 /* -------------------------------------------------- */
20234 /*       GET THE FIRST FROM THE LOG QUEUE AND REMOVE  */
20235 /*       IT FROM THE QUEUE.                           */
20236 /* -------------------------------------------------- */
20237   LogPartRecord::OperationQueue * queue = &logPartPtr.p->m_log_complete_queue;
20238   tmp.i = queue->firstElement;
20239   if (tmp.i == RNIL)
20240   {
20241     jam();
20242     queue = &logPartPtr.p->m_log_prepare_queue;
20243     tmp.i = queue->firstElement;
20244   }
20245   ptrCheckGuard(tmp, ctcConnectrecFileSize, tcConnectionrec);
20246   queue->firstElement = tmp.p->nextTcLogQueue;
20247   if (queue->firstElement == RNIL) {
20248     jam();
20249     queue->lastElement = RNIL;
20250   }//if
20251   dst = tmp;
20252 }//Dblqh::getFirstInLogQueue()
20253 
20254 /* ---------------------------------------------------------------- */
20255 /* ---------------- GET FRAGMENT RECORD --------------------------- */
20256 /*       INPUT:          TFRAGID         FRAGMENT ID LOOKING FOR    */
20257 /*                       TABPTR          TABLE ID                   */
20258 /*       SUBROUTINE SHORT NAME = GFR                                */
20259 /* ---------------------------------------------------------------- */
getFragmentrec(Signal * signal,Uint32 fragId)20260 bool Dblqh::getFragmentrec(Signal* signal, Uint32 fragId)
20261 {
20262   for (Uint32 i = 0; i < MAX_FRAG_PER_NODE; i++) {
20263     jam();
20264     if (tabptr.p->fragid[i] == fragId) {
20265       fragptr.i = tabptr.p->fragrec[i];
20266       c_fragment_pool.getPtr(fragptr);
20267       return true;
20268     }//if
20269   }//for
20270   return false;
20271 }//Dblqh::getFragmentrec()
20272 
20273 /* ========================================================================= */
20274 /* ======                      INITIATE FRAGMENT RECORD              ======= */
20275 /*                                                                           */
20276 /* ========================================================================= */
initialiseAddfragrec(Signal * signal)20277 void Dblqh::initialiseAddfragrec(Signal* signal)
20278 {
20279   if (caddfragrecFileSize != 0) {
20280     for (addfragptr.i = 0; addfragptr.i < caddfragrecFileSize; addfragptr.i++) {
20281       ptrAss(addfragptr, addFragRecord);
20282       addfragptr.p->addfragStatus = AddFragRecord::FREE;
20283       addfragptr.p->nextAddfragrec = addfragptr.i + 1;
20284     }//for
20285     addfragptr.i = caddfragrecFileSize - 1;
20286     ptrAss(addfragptr, addFragRecord);
20287     addfragptr.p->nextAddfragrec = RNIL;
20288     cfirstfreeAddfragrec = 0;
20289   } else {
20290     jam();
20291     cfirstfreeAddfragrec = RNIL;
20292   }//if
20293 }//Dblqh::initialiseAddfragrec()
20294 
20295 /* ========================================================================= */
20296 /* ======                INITIATE FRAGMENT RECORD                    ======= */
20297 /*                                                                           */
20298 /* ========================================================================= */
initialiseFragrec(Signal * signal)20299 void Dblqh::initialiseFragrec(Signal* signal)
20300 {
20301 
20302   SLList<Fragrecord> tmp(c_fragment_pool);
20303   while(tmp.seize(fragptr))
20304   {
20305     refresh_watch_dog();
20306     new (fragptr.p) Fragrecord();
20307     fragptr.p->fragStatus = Fragrecord::FREE;
20308     fragptr.p->execSrStatus = Fragrecord::IDLE;
20309     fragptr.p->srStatus = Fragrecord::SS_IDLE;
20310   }
20311   tmp.release();
20312 }//Dblqh::initialiseFragrec()
20313 
20314 /* ========================================================================= */
20315 /* ======                INITIATE FRAGMENT RECORD                    ======= */
20316 /*                                                                           */
20317 /* ========================================================================= */
initialiseGcprec(Signal * signal)20318 void Dblqh::initialiseGcprec(Signal* signal)
20319 {
20320   UintR tigpIndex;
20321 
20322   if (cgcprecFileSize != 0) {
20323     for (gcpPtr.i = 0; gcpPtr.i < cgcprecFileSize; gcpPtr.i++) {
20324       ptrAss(gcpPtr, gcpRecord);
20325       for (tigpIndex = 0; tigpIndex < ZLOG_PART_FILE_SIZE; tigpIndex++) {
20326         gcpPtr.p->gcpLogPartState[tigpIndex] = ZIDLE;
20327         gcpPtr.p->gcpSyncReady[tigpIndex] = ZFALSE;
20328       }//for
20329     }//for
20330   }//if
20331 }//Dblqh::initialiseGcprec()
20332 
20333 /* ========================================================================= */
20334 /* ======                INITIATE LCP RECORD                         ======= */
20335 /*                                                                           */
20336 /* ========================================================================= */
initialiseLcpRec(Signal * signal)20337 void Dblqh::initialiseLcpRec(Signal* signal)
20338 {
20339   if (clcpFileSize != 0) {
20340     for (lcpPtr.i = 0; lcpPtr.i < clcpFileSize; lcpPtr.i++) {
20341       ptrAss(lcpPtr, lcpRecord);
20342       lcpPtr.p->lcpState = LcpRecord::LCP_IDLE;
20343       lcpPtr.p->lcpQueued = false;
20344       lcpPtr.p->reportEmpty = false;
20345       lcpPtr.p->firstFragmentFlag = false;
20346       lcpPtr.p->lastFragmentFlag = false;
20347     }//for
20348   }//if
20349 }//Dblqh::initialiseLcpRec()
20350 
20351 /* ========================================================================= */
20352 /* ======         INITIATE LOG FILE OPERATION RECORD                 ======= */
20353 /*                                                                           */
20354 /* ========================================================================= */
initialiseLfo(Signal * signal)20355 void Dblqh::initialiseLfo(Signal* signal)
20356 {
20357   if (clfoFileSize != 0) {
20358     for (lfoPtr.i = 0; lfoPtr.i < clfoFileSize; lfoPtr.i++) {
20359       ptrAss(lfoPtr, logFileOperationRecord);
20360       lfoPtr.p->lfoState = LogFileOperationRecord::IDLE;
20361       lfoPtr.p->lfoTimer = 0;
20362       lfoPtr.p->nextLfo = lfoPtr.i + 1;
20363     }//for
20364     lfoPtr.i = clfoFileSize - 1;
20365     ptrAss(lfoPtr, logFileOperationRecord);
20366     lfoPtr.p->nextLfo = RNIL;
20367     cfirstfreeLfo = 0;
20368   } else {
20369     jam();
20370     cfirstfreeLfo = RNIL;
20371   }//if
20372 }//Dblqh::initialiseLfo()
20373 
20374 /* ========================================================================= */
20375 /* ======                 INITIATE LOG FILE RECORD                   ======= */
20376 /*                                                                           */
20377 /* ========================================================================= */
initialiseLogFile(Signal * signal)20378 void Dblqh::initialiseLogFile(Signal* signal)
20379 {
20380   if (clogFileFileSize != 0) {
20381     for (logFilePtr.i = 0; logFilePtr.i < clogFileFileSize; logFilePtr.i++) {
20382       ptrAss(logFilePtr, logFileRecord);
20383       logFilePtr.p->nextLogFile = logFilePtr.i + 1;
20384       logFilePtr.p->logFileStatus = LogFileRecord::LFS_IDLE;
20385 
20386       logFilePtr.p->logLastPrepRef = new Uint32[clogFileSize];
20387       logFilePtr.p->logMaxGciCompleted = new Uint32[clogFileSize];
20388       logFilePtr.p->logMaxGciStarted = new Uint32[clogFileSize];
20389 
20390       if (logFilePtr.p->logLastPrepRef == 0 ||
20391           logFilePtr.p->logMaxGciCompleted == 0 ||
20392           logFilePtr.p->logMaxGciStarted == 0)
20393       {
20394         char buf[256];
20395         BaseString::snprintf(buf, sizeof(buf),
20396                              "Failed to alloc mbyte(%u) arrays for logfile %u",
20397                              clogFileSize, logFilePtr.i);
20398         progError(__LINE__, NDBD_EXIT_MEMALLOC, buf);
20399       }
20400 
20401     }//for
20402     logFilePtr.i = clogFileFileSize - 1;
20403     ptrAss(logFilePtr, logFileRecord);
20404     logFilePtr.p->nextLogFile = RNIL;
20405     cfirstfreeLogFile = 0;
20406   } else {
20407     jam();
20408     cfirstfreeLogFile = RNIL;
20409   }//if
20410 }//Dblqh::initialiseLogFile()
20411 
20412 /* ========================================================================= */
20413 /* ======                  INITIATE LOG PAGES                        ======= */
20414 /*                                                                           */
20415 /* ========================================================================= */
initialiseLogPage(Signal * signal)20416 void Dblqh::initialiseLogPage(Signal* signal)
20417 {
20418   /**
20419    * Moved into initRecords()
20420    */
20421 }//Dblqh::initialiseLogPage()
20422 
20423 /* =========================================================================
20424  * ======                       INITIATE LOG PART RECORD             =======
20425  *
20426  * ========================================================================= */
initialiseLogPart(Signal * signal)20427 void Dblqh::initialiseLogPart(Signal* signal)
20428 {
20429   for (logPartPtr.i = 0; logPartPtr.i < clogPartFileSize; logPartPtr.i++) {
20430     ptrAss(logPartPtr, logPartRecord);
20431     logPartPtr.p->waitWriteGciLog = LogPartRecord::WWGL_FALSE;
20432     logPartPtr.p->LogLqhKeyReqSent = ZFALSE;
20433     logPartPtr.p->logPartNewestCompletedGCI = (UintR)-1;
20434     logPartPtr.p->logTcConrec = RNIL;
20435   }//for
20436 }//Dblqh::initialiseLogPart()
20437 
initialisePageRef(Signal * signal)20438 void Dblqh::initialisePageRef(Signal* signal)
20439 {
20440   if (cpageRefFileSize != 0) {
20441     for (pageRefPtr.i = 0;
20442 	 pageRefPtr.i < cpageRefFileSize;
20443 	 pageRefPtr.i++) {
20444       ptrAss(pageRefPtr, pageRefRecord);
20445       pageRefPtr.p->prNext = pageRefPtr.i + 1;
20446     }//for
20447     pageRefPtr.i = cpageRefFileSize - 1;
20448     ptrAss(pageRefPtr, pageRefRecord);
20449     pageRefPtr.p->prNext = RNIL;
20450     cfirstfreePageRef = 0;
20451   } else {
20452     jam();
20453     cfirstfreePageRef = RNIL;
20454   }//if
20455 }//Dblqh::initialisePageRef()
20456 
20457 /* ==========================================================================
20458  * =======                        INITIATE RECORDS                    =======
20459  *
20460  *       TAKES CARE OF INITIATION OF ALL RECORDS IN THIS BLOCK.
20461  * ========================================================================= */
initialiseRecordsLab(Signal * signal,Uint32 data,Uint32 retRef,Uint32 retData)20462 void Dblqh::initialiseRecordsLab(Signal* signal, Uint32 data,
20463 				 Uint32 retRef, Uint32 retData)
20464 {
20465   Uint32 i;
20466   switch (data) {
20467   case 0:
20468     jam();
20469     m_sr_nodes.clear();
20470     m_sr_exec_sr_req.clear();
20471     m_sr_exec_sr_conf.clear();
20472     for (i = 0; i < 4; i++) {
20473       cactiveCopy[i] = RNIL;
20474     }//for
20475     cnoActiveCopy = 0;
20476     ccurrentGcprec = RNIL;
20477     caddNodeState = ZFALSE;
20478     cstartRecReq = SRR_INITIAL; // Initial
20479     cnewestGci = 0;
20480     cnewestCompletedGci = 0;
20481     crestartOldestGci = 0;
20482     crestartNewestGci = 0;
20483     csrPhaseStarted = ZSR_NO_PHASE_STARTED;
20484     csrPhasesCompleted = 0;
20485     cmasterDihBlockref = 0;
20486     cnoFragmentsExecSr = 0;
20487     cnoOutstandingExecFragReq = 0;
20488     clcpCompletedState = LCP_IDLE;
20489     csrExecUndoLogState = EULS_IDLE;
20490     c_lcpId = 0;
20491     cnoOfFragsCheckpointed = 0;
20492     break;
20493   case 1:
20494     jam();
20495     initialiseAddfragrec(signal);
20496     break;
20497   case 2:
20498     jam();
20499     /* Unused */
20500     break;
20501   case 3:
20502     jam();
20503     /* Unused */
20504     break;
20505   case 4:
20506     jam();
20507     initialiseFragrec(signal);
20508     break;
20509   case 5:
20510     jam();
20511     initialiseGcprec(signal);
20512     initialiseLcpRec(signal);
20513     break;
20514   case 6:
20515     jam();
20516     initialiseLogPage(signal);
20517     break;
20518   case 7:
20519     jam();
20520     initialiseLfo(signal);
20521     break;
20522   case 8:
20523     jam();
20524     initialiseLogFile(signal);
20525     initialiseLogPart(signal);
20526     break;
20527   case 9:
20528     jam();
20529     initialisePageRef(signal);
20530     break;
20531   case 10:
20532     jam();
20533     initialiseScanrec(signal);
20534     break;
20535   case 11:
20536     jam();
20537     initialiseTabrec(signal);
20538     break;
20539   case 12:
20540     jam();
20541     initialiseTcNodeFailRec(signal);
20542     initialiseTcrec(signal);
20543     {
20544       ReadConfigConf * conf = (ReadConfigConf*)signal->getDataPtrSend();
20545       conf->senderRef = reference();
20546       conf->senderData = retData;
20547       sendSignal(retRef, GSN_READ_CONFIG_CONF, signal,
20548 		 ReadConfigConf::SignalLength, JBB);
20549     }
20550     return;
20551     break;
20552   default:
20553     ndbrequire(false);
20554     break;
20555   }//switch
20556 
20557   signal->theData[0] = ZINITIALISE_RECORDS;
20558   signal->theData[1] = data + 1;
20559   signal->theData[2] = 0;
20560   signal->theData[3] = retRef;
20561   signal->theData[4] = retData;
20562   sendSignal(reference(), GSN_CONTINUEB, signal, 5, JBB);
20563 
20564   return;
20565 }//Dblqh::initialiseRecordsLab()
20566 
20567 /* ==========================================================================
20568  * =======                      INITIATE TC CONNECTION RECORD         =======
20569  *
20570  * ========================================================================= */
initialiseScanrec(Signal * signal)20571 void Dblqh::initialiseScanrec(Signal* signal)
20572 {
20573   ndbrequire(cscanrecFileSize > 1);
20574   DLList<ScanRecord> tmp(c_scanRecordPool);
20575   while (tmp.seize(scanptr)){
20576     //new (scanptr.p) ScanRecord();
20577     refresh_watch_dog();
20578     scanptr.p->scanType = ScanRecord::ST_IDLE;
20579     scanptr.p->scanState = ScanRecord::SCAN_FREE;
20580     scanptr.p->scanTcWaiting = 0;
20581     scanptr.p->nextHash = RNIL;
20582     scanptr.p->prevHash = RNIL;
20583     scanptr.p->scan_acc_index= 0;
20584     scanptr.p->scan_acc_segments= 0;
20585     scanptr.p->m_reserved = 0;
20586   }
20587   tmp.release();
20588 
20589   /**
20590    * just seize records from pool and put into
20591    *   dedicated list
20592    */
20593   m_reserved_scans.seize(scanptr); // LCP
20594   scanptr.p->m_reserved = 1;
20595   m_reserved_scans.seize(scanptr); // NR
20596   scanptr.p->m_reserved = 1;
20597 
20598 }//Dblqh::initialiseScanrec()
20599 
20600 /* ==========================================================================
20601  * =======                      INITIATE TABLE RECORD                 =======
20602  *
20603  * ========================================================================= */
initialiseTabrec(Signal * signal)20604 void Dblqh::initialiseTabrec(Signal* signal)
20605 {
20606   if (ctabrecFileSize != 0) {
20607     for (tabptr.i = 0; tabptr.i < ctabrecFileSize; tabptr.i++) {
20608       refresh_watch_dog();
20609       ptrAss(tabptr, tablerec);
20610       tabptr.p->tableStatus = Tablerec::NOT_DEFINED;
20611       tabptr.p->usageCountR = 0;
20612       tabptr.p->usageCountW = 0;
20613       for (Uint32 i = 0; i < MAX_FRAG_PER_NODE; i++) {
20614         tabptr.p->fragid[i] = ZNIL;
20615         tabptr.p->fragrec[i] = RNIL;
20616       }//for
20617     }//for
20618   }//if
20619 }//Dblqh::initialiseTabrec()
20620 
20621 /* ==========================================================================
20622  * =======                      INITIATE TC CONNECTION RECORD         =======
20623  *
20624  * ========================================================================= */
initialiseTcrec(Signal * signal)20625 void Dblqh::initialiseTcrec(Signal* signal)
20626 {
20627   if (ctcConnectrecFileSize != 0) {
20628     for (tcConnectptr.i = 0;
20629 	 tcConnectptr.i < ctcConnectrecFileSize;
20630 	 tcConnectptr.i++) {
20631       refresh_watch_dog();
20632       ptrAss(tcConnectptr, tcConnectionrec);
20633       tcConnectptr.p->transactionState = TcConnectionrec::TC_NOT_CONNECTED;
20634       tcConnectptr.p->tcScanRec = RNIL;
20635       tcConnectptr.p->logWriteState = TcConnectionrec::NOT_STARTED;
20636       tcConnectptr.p->keyInfoIVal = RNIL;
20637       tcConnectptr.p->attrInfoIVal = RNIL;
20638       tcConnectptr.p->m_flags= 0;
20639       tcConnectptr.p->tcTimer = 0;
20640       tcConnectptr.p->nextTcConnectrec = tcConnectptr.i + 1;
20641     }//for
20642     tcConnectptr.i = ctcConnectrecFileSize - 1;
20643     ptrAss(tcConnectptr, tcConnectionrec);
20644     tcConnectptr.p->nextTcConnectrec = RNIL;
20645     cfirstfreeTcConrec = 0;
20646   } else {
20647     jam();
20648     cfirstfreeTcConrec = RNIL;
20649   }//if
20650 }//Dblqh::initialiseTcrec()
20651 
20652 /* ==========================================================================
20653  * =======                      INITIATE TC CONNECTION RECORD         =======
20654  *
20655  * ========================================================================= */
initialiseTcNodeFailRec(Signal * signal)20656 void Dblqh::initialiseTcNodeFailRec(Signal* signal)
20657 {
20658   if (ctcNodeFailrecFileSize != 0) {
20659     for (tcNodeFailptr.i = 0;
20660 	 tcNodeFailptr.i < ctcNodeFailrecFileSize;
20661 	 tcNodeFailptr.i++) {
20662       ptrAss(tcNodeFailptr, tcNodeFailRecord);
20663       tcNodeFailptr.p->tcFailStatus = TcNodeFailRecord::TC_STATE_FALSE;
20664     }//for
20665   }//if
20666 }//Dblqh::initialiseTcNodeFailRec()
20667 
20668 /* ==========================================================================
20669  * =======              INITIATE FRAGMENT RECORD                      =======
20670  *
20671  *       SUBROUTINE SHORT NAME = IF
20672  * ========================================================================= */
initFragrec(Signal * signal,Uint32 tableId,Uint32 fragId,Uint32 copyType)20673 void Dblqh::initFragrec(Signal* signal,
20674                         Uint32 tableId,
20675                         Uint32 fragId,
20676                         Uint32 copyType)
20677 {
20678   new (fragptr.p) Fragrecord();
20679   fragptr.p->m_scanNumberMask.set(); // All is free
20680   fragptr.p->accBlockref = caccBlockref;
20681   fragptr.p->firstWaitQueue = RNIL;
20682   fragptr.p->lastWaitQueue = RNIL;
20683   fragptr.p->fragStatus = Fragrecord::DEFINED;
20684   fragptr.p->fragCopy = copyType;
20685   fragptr.p->tupBlockref = ctupBlockref;
20686   fragptr.p->tuxBlockref = ctuxBlockref;
20687   fragptr.p->logFlag = Fragrecord::STATE_TRUE;
20688   fragptr.p->lcpFlag = Fragrecord::LCP_STATE_TRUE;
20689   for (Uint32 i = 0; i < MAX_LCP_STORED; i++) {
20690     fragptr.p->lcpId[i] = 0;
20691   }//for
20692   fragptr.p->maxGciCompletedInLcp = 0;
20693   fragptr.p->maxGciInLcp = 0;
20694   fragptr.p->copyFragState = ZIDLE;
20695   fragptr.p->newestGci = cnewestGci;
20696   fragptr.p->tabRef = tableId;
20697   fragptr.p->fragId = fragId;
20698   fragptr.p->srStatus = Fragrecord::SS_IDLE;
20699   fragptr.p->execSrStatus = Fragrecord::IDLE;
20700   fragptr.p->execSrNoReplicas = 0;
20701   fragptr.p->fragDistributionKey = 0;
20702   fragptr.p->activeTcCounter = 0;
20703   fragptr.p->tableFragptr = RNIL;
20704   fragptr.p->m_copy_started_state = 0;
20705 }//Dblqh::initFragrec()
20706 
20707 /* ==========================================================================
20708  * =======       INITIATE FRAGMENT RECORD FOR SYSTEM RESTART          =======
20709  *
20710  *       SUBROUTINE SHORT NAME = IFS
20711  * ========================================================================= */
20712 
20713 /* ==========================================================================
20714  * =======       INITIATE INFORMATION ABOUT GLOBAL CHECKPOINTS        =======
20715  *               IN LOG FILE RECORDS
20716  *
20717  *       INPUT:     LOG_FILE_PTR            CURRENT LOG FILE
20718  *                  TNO_FD_DESCRIPTORS      THE NUMBER OF FILE DESCRIPTORS
20719  *                                          TO READ FROM THE LOG PAGE
20720  *                  LOG_PAGE_PTR            PAGE ZERO IN LOG FILE
20721  *       SUBROUTINE SHORT NAME = IGL
20722  * ========================================================================= */
initGciInLogFileRec(Signal * signal,Uint32 noFdDescriptors)20723 void Dblqh::initGciInLogFileRec(Signal* signal, Uint32 noFdDescriptors)
20724 {
20725   LogFileRecordPtr filePtr = logFilePtr;
20726   Uint32 pos = ZPAGE_HEADER_SIZE + ZFD_HEADER_SIZE;
20727   for (Uint32 fd = 0; fd < noFdDescriptors; fd++)
20728   {
20729     jam();
20730     for (Uint32 mb = 0; mb < clogFileSize; mb++)
20731     {
20732       jam();
20733       Uint32 pos0 = pos + fd * (ZFD_MBYTE_SIZE * clogFileSize) + mb;
20734       Uint32 pos1 = pos0 + clogFileSize;
20735       Uint32 pos2 = pos1 + clogFileSize;
20736       arrGuard(pos0, ZPAGE_SIZE);
20737       arrGuard(pos1, ZPAGE_SIZE);
20738       arrGuard(pos2, ZPAGE_SIZE);
20739       filePtr.p->logMaxGciCompleted[mb] = logPagePtr.p->logPageWord[pos0];
20740       filePtr.p->logMaxGciStarted[mb] = logPagePtr.p->logPageWord[pos1];
20741       filePtr.p->logLastPrepRef[mb] = logPagePtr.p->logPageWord[pos2];
20742     }
20743     if (fd + 1 < noFdDescriptors)
20744     {
20745       jam();
20746       filePtr.i = filePtr.p->prevLogFile;
20747       ptrCheckGuard(filePtr, clogFileFileSize, logFileRecord);
20748     }
20749   }
20750 }//Dblqh::initGciInLogFileRec()
20751 
20752 /* ==========================================================================
20753  * =======        INITIATE LCP RECORD WHEN USED FOR SYSTEM RESTART    =======
20754  *
20755  *       SUBROUTINE SHORT NAME = ILS
20756  * ========================================================================= */
initLcpSr(Signal * signal,Uint32 lcpNo,Uint32 lcpId,Uint32 tableId,Uint32 fragId,Uint32 fragPtr)20757 void Dblqh::initLcpSr(Signal* signal,
20758                       Uint32 lcpNo,
20759                       Uint32 lcpId,
20760                       Uint32 tableId,
20761                       Uint32 fragId,
20762                       Uint32 fragPtr)
20763 {
20764   lcpPtr.p->lcpQueued = false;
20765   lcpPtr.p->currentFragment.fragPtrI = fragPtr;
20766   lcpPtr.p->currentFragment.lcpFragOrd.lcpNo = lcpNo;
20767   lcpPtr.p->currentFragment.lcpFragOrd.lcpId = lcpId;
20768   lcpPtr.p->currentFragment.lcpFragOrd.tableId = tableId;
20769   lcpPtr.p->currentFragment.lcpFragOrd.fragmentId = fragId;
20770   lcpPtr.p->lcpState = LcpRecord::LCP_SR_WAIT_FRAGID;
20771 }//Dblqh::initLcpSr()
20772 
20773 /* ==========================================================================
20774  * =======              INITIATE LOG PART                             =======
20775  *
20776  * ========================================================================= */
initLogpart(Signal * signal)20777 void Dblqh::initLogpart(Signal* signal)
20778 {
20779   logPartPtr.p->execSrLogPage = RNIL;
20780   logPartPtr.p->execSrLogPageIndex = ZNIL;
20781   logPartPtr.p->execSrExecuteIndex = 0;
20782   logPartPtr.p->noLogFiles = cnoLogFiles;
20783   logPartPtr.p->logLap = 0;
20784   logPartPtr.p->logTailFileNo = 0;
20785   logPartPtr.p->logTailMbyte = 0;
20786   logPartPtr.p->lastMbyte = ZNIL;
20787   logPartPtr.p->logPartState = LogPartRecord::SR_FIRST_PHASE;
20788   logPartPtr.p->logExecState = LogPartRecord::LES_IDLE;
20789   logPartPtr.p->firstLogTcrec = RNIL;
20790   logPartPtr.p->lastLogTcrec = RNIL;
20791   logPartPtr.p->gcprec = RNIL;
20792   logPartPtr.p->firstPageRef = RNIL;
20793   logPartPtr.p->lastPageRef = RNIL;
20794   logPartPtr.p->headFileNo = ZNIL;
20795   logPartPtr.p->headPageNo = ZNIL;
20796   logPartPtr.p->headPageIndex = ZNIL;
20797   logPartPtr.p->m_log_problems = 0;
20798   NdbLogPartInfo lpinfo(instance());
20799   ndbrequire(lpinfo.partCount == clogPartFileSize);
20800   logPartPtr.p->logPartNo = lpinfo.partNo[logPartPtr.i];
20801   logPartPtr.p->m_io_tracker.init(logPartPtr.p->logPartNo);
20802   logPartPtr.p->m_log_prepare_queue.init();
20803   logPartPtr.p->m_log_complete_queue.init();
20804 }//Dblqh::initLogpart()
20805 
20806 /* ==========================================================================
20807  * =======              INITIATE LOG POINTERS                         =======
20808  *
20809  * ========================================================================= */
initLogPointers(Signal * signal)20810 void Dblqh::initLogPointers(Signal* signal)
20811 {
20812   logPartPtr.i = tcConnectptr.p->m_log_part_ptr_i;
20813   ptrCheckGuard(logPartPtr, clogPartFileSize, logPartRecord);
20814   logFilePtr.i = logPartPtr.p->currentLogfile;
20815   ptrCheckGuard(logFilePtr, clogFileFileSize, logFileRecord);
20816   logPagePtr.i = logFilePtr.p->currentLogpage;
20817   ptrCheckGuard(logPagePtr, clogPageFileSize, logPageRecord);
20818 }//Dblqh::initLogPointers()
20819 
20820 /* ------------------------------------------------------------------------- */
20821 /* -------    INIT REQUEST INFO BEFORE EXECUTING A LOG RECORD        ------- */
20822 /*                                                                           */
20823 /* ------------------------------------------------------------------------- */
initReqinfoExecSr(Signal * signal)20824 void Dblqh::initReqinfoExecSr(Signal* signal)
20825 {
20826   UintR Treqinfo = 0;
20827   TcConnectionrec * const regTcPtr = tcConnectptr.p;
20828   LqhKeyReq::setKeyLen(Treqinfo, regTcPtr->primKeyLen);
20829 /* ------------------------------------------------------------------------- */
20830 /* NUMBER OF BACKUPS AND STANDBYS ARE ZERO AND NEED NOT BE SET.              */
20831 /* REPLICA TYPE IS CLEARED BY SEND_LQHKEYREQ.                                */
20832 /* ------------------------------------------------------------------------- */
20833 /* ------------------------------------------------------------------------- */
20834 /*       SET LAST REPLICA NUMBER TO ZERO (BIT 10-11)                         */
20835 /* ------------------------------------------------------------------------- */
20836 /* ------------------------------------------------------------------------- */
20837 /*       SET DIRTY FLAG                                                      */
20838 /* ------------------------------------------------------------------------- */
20839   LqhKeyReq::setDirtyFlag(Treqinfo, 1);
20840 /* ------------------------------------------------------------------------- */
20841 /*       SET SIMPLE TRANSACTION                                              */
20842 /* ------------------------------------------------------------------------- */
20843   LqhKeyReq::setSimpleFlag(Treqinfo, 1);
20844   LqhKeyReq::setGCIFlag(Treqinfo, 1);
20845 /* ------------------------------------------------------------------------- */
20846 /* SET OPERATION TYPE AND LOCK MODE (NEVER READ OPERATION OR SCAN IN LOG)    */
20847 /* ------------------------------------------------------------------------- */
20848   LqhKeyReq::setOperation(Treqinfo, regTcPtr->operation);
20849   regTcPtr->reqinfo = Treqinfo;
20850 /* ------------------------------------------------------------------------ */
20851 /* NO OF BACKUP IS SET TO ONE AND NUMBER OF STANDBY NODES IS SET TO ZERO.   */
20852 /* THUS THE RECEIVING NODE WILL EXPECT THAT IT IS THE LAST NODE AND WILL    */
20853 /* SEND COMPLETED AS THE RESPONSE SIGNAL SINCE DIRTY_OP BIT IS SET.         */
20854 /* ------------------------------------------------------------------------ */
20855 /* ------------------------------------------------------------------------- */
20856 /*       SET REPLICA TYPE TO PRIMARY AND NUMBER OF REPLICA TO ONE            */
20857 /* ------------------------------------------------------------------------- */
20858   regTcPtr->lastReplicaNo = 0;
20859   regTcPtr->apiVersionNo = 0;
20860   regTcPtr->nextSeqNoReplica = 0;
20861   regTcPtr->opExec = 0;
20862   regTcPtr->storedProcId = ZNIL;
20863   regTcPtr->readlenAi = 0;
20864   regTcPtr->nodeAfterNext[0] = ZNIL;
20865   regTcPtr->nodeAfterNext[1] = ZNIL;
20866   regTcPtr->dirtyOp = ZFALSE;
20867   regTcPtr->tcBlockref = cownref;
20868   regTcPtr->m_reorg = 0;
20869 }//Dblqh::initReqinfoExecSr()
20870 
20871 /* --------------------------------------------------------------------------
20872  * -------               INSERT FRAGMENT                              -------
20873  *
20874  * ------------------------------------------------------------------------- */
insertFragrec(Signal * signal,Uint32 fragId)20875 bool Dblqh::insertFragrec(Signal* signal, Uint32 fragId)
20876 {
20877   terrorCode = ZOK;
20878   if(c_fragment_pool.seize(fragptr) == false)
20879   {
20880     terrorCode = ZNO_FREE_FRAGMENTREC;
20881     return false;
20882   }
20883   for (Uint32 i = 0; i < MAX_FRAG_PER_NODE; i++) {
20884     jam();
20885     if (tabptr.p->fragid[i] == ZNIL) {
20886       jam();
20887       tabptr.p->fragid[i] = fragId;
20888       tabptr.p->fragrec[i] = fragptr.i;
20889       return true;
20890     }//if
20891   }//for
20892   c_fragment_pool.release(fragptr);
20893   terrorCode = ZTOO_MANY_FRAGMENTS;
20894   return false;
20895 }//Dblqh::insertFragrec()
20896 
20897 /* --------------------------------------------------------------------------
20898  * -------               LINK OPERATION IN ACTIVE LIST ON FRAGMENT    -------
20899  *
20900  *       SUBROUTINE SHORT NAME: LFQ
20901 // Input Pointers:
20902 // tcConnectptr
20903 // fragptr
20904 * ------------------------------------------------------------------------- */
linkFragQueue(Signal * signal)20905 void Dblqh::linkFragQueue(Signal* signal)
20906 {
20907   TcConnectionrecPtr lfqTcConnectptr;
20908   TcConnectionrec * const regTcPtr = tcConnectptr.p;
20909   Fragrecord * const regFragPtr = fragptr.p;
20910   Uint32 tcIndex = tcConnectptr.i;
20911 
20912   lfqTcConnectptr.i = regFragPtr->lastWaitQueue;
20913   regTcPtr->nextTc = RNIL;
20914   regFragPtr->lastWaitQueue = tcIndex;
20915   regTcPtr->prevTc = lfqTcConnectptr.i;
20916   ndbrequire(regTcPtr->listState == TcConnectionrec::NOT_IN_LIST);
20917   regTcPtr->listState = TcConnectionrec::WAIT_QUEUE_LIST;
20918   if (lfqTcConnectptr.i != RNIL) {
20919     jam();
20920     ptrCheckGuard(lfqTcConnectptr, ctcConnectrecFileSize, tcConnectionrec);
20921     lfqTcConnectptr.p->nextTc = tcIndex;
20922   } else {
20923     regFragPtr->firstWaitQueue = tcIndex;
20924   }//if
20925   return;
20926 }//Dblqh::linkFragQueue()
20927 
20928 /* -------------------------------------------------------------------------
20929  * -------               LINK OPERATION INTO WAITING FOR LOGGING     -------
20930  *
20931  *       SUBROUTINE SHORT NAME = LWL
20932 // Input Pointers:
20933 // tcConnectptr
20934 // logPartPtr
20935  * ------------------------------------------------------------------------- */
20936 void
linkWaitLog(Signal * signal,LogPartRecordPtr regLogPartPtr,LogPartRecord::OperationQueue & queue)20937 Dblqh::linkWaitLog(Signal* signal,
20938                    LogPartRecordPtr regLogPartPtr,
20939                    LogPartRecord::OperationQueue & queue)
20940 {
20941   TcConnectionrecPtr lwlTcConnectptr;
20942 /* -------------------------------------------------- */
20943 /*       LINK ACTIVE OPERATION INTO QUEUE WAITING FOR */
20944 /*       ACCESS TO THE LOG PART.                      */
20945 /* -------------------------------------------------- */
20946   lwlTcConnectptr.i = queue.lastElement;
20947   if (lwlTcConnectptr.i == RNIL) {
20948     jam();
20949     queue.firstElement = tcConnectptr.i;
20950   } else {
20951     jam();
20952     ptrCheckGuard(lwlTcConnectptr, ctcConnectrecFileSize, tcConnectionrec);
20953     lwlTcConnectptr.p->nextTcLogQueue = tcConnectptr.i;
20954   }//if
20955   queue.lastElement = tcConnectptr.i;
20956   tcConnectptr.p->nextTcLogQueue = RNIL;
20957   regLogPartPtr.p->logPartState = LogPartRecord::ACTIVE;
20958   if (regLogPartPtr.p->LogLqhKeyReqSent == ZFALSE)
20959   {
20960     jam();
20961     regLogPartPtr.p->LogLqhKeyReqSent = ZTRUE;
20962     signal->theData[0] = ZLOG_LQHKEYREQ;
20963     signal->theData[1] = regLogPartPtr.i;
20964     sendSignal(cownref, GSN_CONTINUEB, signal, 2, JBB);
20965   }//if
20966 }//Dblqh::linkWaitLog()
20967 
20968 /* --------------------------------------------------------------------------
20969  * -------          START THE NEXT OPERATION ON THIS LOG PART IF ANY  -------
20970  * -------               OPERATIONS ARE QUEUED.                       -------
20971  *
20972  *       SUBROUTINE SHORT NAME = LNS
20973 // Input Pointers:
20974 // tcConnectptr
20975 // logPartPtr
20976  * ------------------------------------------------------------------------- */
logNextStart(Signal * signal)20977 void Dblqh::logNextStart(Signal* signal)
20978 {
20979   LogPartRecordPtr lnsLogPartPtr;
20980   UintR tlnsStillWaiting;
20981   LogPartRecord * const regLogPartPtr = logPartPtr.p;
20982 
20983   if (regLogPartPtr->m_log_prepare_queue.isEmpty() &&
20984       regLogPartPtr->m_log_complete_queue.isEmpty() &&
20985       (regLogPartPtr->waitWriteGciLog != LogPartRecord::WWGL_TRUE))
20986   {
20987 // --------------------------------------------------------------------------
20988 // Optimised route for the common case
20989 // --------------------------------------------------------------------------
20990     return;
20991   }//if
20992 
20993   if (!regLogPartPtr->m_log_prepare_queue.isEmpty() ||
20994       !regLogPartPtr->m_log_complete_queue.isEmpty())
20995   {
20996     jam();
20997     regLogPartPtr->logPartState = LogPartRecord::ACTIVE;
20998     if (regLogPartPtr->LogLqhKeyReqSent == ZFALSE)
20999     {
21000       jam();
21001       regLogPartPtr->LogLqhKeyReqSent = ZTRUE;
21002       signal->theData[0] = ZLOG_LQHKEYREQ;
21003       signal->theData[1] = logPartPtr.i;
21004       sendSignal(cownref, GSN_CONTINUEB, signal, 2, JBB);
21005     }//if
21006   }
21007 
21008   if (regLogPartPtr->waitWriteGciLog != LogPartRecord::WWGL_TRUE)
21009   {
21010     jam();
21011     return;
21012   }
21013   else
21014   {
21015     jam();
21016 /* --------------------------------------------------------------------------
21017  *   A COMPLETE GCI LOG RECORD IS WAITING TO BE WRITTEN. WE GIVE THIS HIGHEST
21018  *   PRIORITY AND WRITE IT IMMEDIATELY. AFTER WRITING IT WE CHECK IF ANY MORE
21019  *   LOG PARTS ARE WAITING. IF NOT WE SEND A SIGNAL THAT INITIALISES THE GCP
21020  *   RECORD TO WAIT UNTIL ALL COMPLETE GCI LOG RECORDS HAVE REACHED TO DISK.
21021  * -------------------------------------------------------------------------- */
21022     writeCompletedGciLog(signal);
21023     logPartPtr.p->waitWriteGciLog = LogPartRecord::WWGL_FALSE;
21024     tlnsStillWaiting = ZFALSE;
21025     for (lnsLogPartPtr.i = 0; lnsLogPartPtr.i < clogPartFileSize; lnsLogPartPtr.i++) {
21026       jam();
21027       ptrAss(lnsLogPartPtr, logPartRecord);
21028       if (lnsLogPartPtr.p->waitWriteGciLog == LogPartRecord::WWGL_TRUE) {
21029         jam();
21030         tlnsStillWaiting = ZTRUE;
21031       }//if
21032     }//for
21033     if (tlnsStillWaiting == ZFALSE) {
21034       jam();
21035       signal->theData[0] = ZINIT_GCP_REC;
21036       sendSignal(cownref, GSN_CONTINUEB, signal, 1, JBB);
21037     }//if
21038   }//if
21039 }//Dblqh::logNextStart()
21040 
21041 /* --------------------------------------------------------------------------
21042  * -------       MOVE PAGES FROM LFO RECORD TO PAGE REFERENCE RECORD  -------
21043  *               WILL ALWAYS MOVE 8 PAGES TO A PAGE REFERENCE RECORD.
21044  *
21045  *       SUBROUTINE SHORT NAME = MPR
21046  * ------------------------------------------------------------------------- */
moveToPageRef(Signal * signal)21047 void Dblqh::moveToPageRef(Signal* signal)
21048 {
21049   LogPageRecordPtr mprLogPagePtr;
21050   PageRefRecordPtr mprPageRefPtr;
21051   UintR tmprIndex;
21052 
21053 /* --------------------------------------------------------------------------
21054  * -------       INSERT PAGE REFERENCE RECORD                         -------
21055  *
21056  *       INPUT:  LFO_PTR         LOG FILE OPERATION RECORD
21057  *               LOG_PART_PTR    LOG PART RECORD
21058  *               PAGE_REF_PTR    THE PAGE REFERENCE RECORD TO BE INSERTED.
21059  * ------------------------------------------------------------------------- */
21060   PageRefRecordPtr iprPageRefPtr;
21061 
21062   if ((logPartPtr.p->mmBufferSize + 8) >= ZMAX_MM_BUFFER_SIZE) {
21063     jam();
21064     pageRefPtr.i = logPartPtr.p->firstPageRef;
21065     ptrCheckGuard(pageRefPtr, cpageRefFileSize, pageRefRecord);
21066     releasePrPages(signal);
21067     removePageRef(signal);
21068   } else {
21069     jam();
21070     logPartPtr.p->mmBufferSize = logPartPtr.p->mmBufferSize + 8;
21071   }//if
21072   seizePageRef(signal);
21073   if (logPartPtr.p->firstPageRef == RNIL) {
21074     jam();
21075     logPartPtr.p->firstPageRef = pageRefPtr.i;
21076   } else {
21077     jam();
21078     iprPageRefPtr.i = logPartPtr.p->lastPageRef;
21079     ptrCheckGuard(iprPageRefPtr, cpageRefFileSize, pageRefRecord);
21080     iprPageRefPtr.p->prNext = pageRefPtr.i;
21081   }//if
21082   pageRefPtr.p->prPrev = logPartPtr.p->lastPageRef;
21083   logPartPtr.p->lastPageRef = pageRefPtr.i;
21084 
21085   pageRefPtr.p->prFileNo = logFilePtr.p->fileNo;
21086   pageRefPtr.p->prPageNo = lfoPtr.p->lfoPageNo;
21087   tmprIndex = 0;
21088   mprLogPagePtr.i = lfoPtr.p->firstLfoPage;
21089 MPR_LOOP:
21090   arrGuard(tmprIndex, 8);
21091   pageRefPtr.p->pageRef[tmprIndex] = mprLogPagePtr.i;
21092   tmprIndex = tmprIndex + 1;
21093   ptrCheckGuard(mprLogPagePtr, clogPageFileSize, logPageRecord);
21094   mprLogPagePtr.i = mprLogPagePtr.p->logPageWord[ZNEXT_PAGE];
21095   if (mprLogPagePtr.i != RNIL) {
21096     jam();
21097     goto MPR_LOOP;
21098   }//if
21099   mprPageRefPtr.i = pageRefPtr.p->prPrev;
21100   if (mprPageRefPtr.i != RNIL) {
21101     jam();
21102     ptrCheckGuard(mprPageRefPtr, cpageRefFileSize, pageRefRecord);
21103     mprLogPagePtr.i = mprPageRefPtr.p->pageRef[7];
21104     ptrCheckGuard(mprLogPagePtr, clogPageFileSize, logPageRecord);
21105     mprLogPagePtr.p->logPageWord[ZNEXT_PAGE] = pageRefPtr.p->pageRef[0];
21106   }//if
21107 }//Dblqh::moveToPageRef()
21108 
21109 /* ------------------------------------------------------------------------- */
21110 /* -------               READ THE ATTRINFO FROM THE LOG              ------- */
21111 /*                                                                           */
21112 /*       SUBROUTINE SHORT NAME = RA                                          */
21113 /* ------------------------------------------------------------------------- */
readAttrinfo(Signal * signal)21114 void Dblqh::readAttrinfo(Signal* signal)
21115 {
21116   Uint32 remainingLen = tcConnectptr.p->totSendlenAi;
21117   tcConnectptr.p->reclenAiLqhkey = 0;
21118   if (remainingLen == 0) {
21119     jam();
21120     return;
21121   }//if
21122 
21123   readLogData(signal, remainingLen, tcConnectptr.p->attrInfoIVal);
21124 }//Dblqh::readAttrinfo()
21125 
21126 /* ------------------------------------------------------------------------- */
21127 /* -------               READ COMMIT LOG                             ------- */
21128 /*                                                                           */
21129 /*       SUBROUTINE SHORT NAME = RCL                                         */
21130 /* ------------------------------------------------------------------------- */
readCommitLog(Signal * signal,CommitLogRecord * commitLogRecord)21131 void Dblqh::readCommitLog(Signal* signal, CommitLogRecord* commitLogRecord)
21132 {
21133   Uint32 trclPageIndex = logPagePtr.p->logPageWord[ZCURR_PAGE_INDEX];
21134   if ((trclPageIndex + (ZCOMMIT_LOG_SIZE - 1)) < ZPAGE_SIZE) {
21135     jam();
21136     tcConnectptr.p->tableref = logPagePtr.p->logPageWord[trclPageIndex + 0];
21137     tcConnectptr.p->schemaVersion = logPagePtr.p->logPageWord[trclPageIndex + 1];
21138     tcConnectptr.p->fragmentid = logPagePtr.p->logPageWord[trclPageIndex + 2];
21139     commitLogRecord->fileNo = logPagePtr.p->logPageWord[trclPageIndex + 3];
21140     commitLogRecord->startPageNo = logPagePtr.p->logPageWord[trclPageIndex + 4];
21141     commitLogRecord->startPageIndex = logPagePtr.p->logPageWord[trclPageIndex + 5];
21142     commitLogRecord->stopPageNo = logPagePtr.p->logPageWord[trclPageIndex + 6];
21143     tcConnectptr.p->gci_hi = logPagePtr.p->logPageWord[trclPageIndex + 7];
21144     tcConnectptr.p->gci_lo = 0;
21145     logPagePtr.p->logPageWord[ZCURR_PAGE_INDEX] =
21146                             (trclPageIndex + ZCOMMIT_LOG_SIZE) - 1;
21147   } else {
21148     jam();
21149     tcConnectptr.p->tableref = readLogword(signal);
21150     tcConnectptr.p->schemaVersion = readLogword(signal);
21151     tcConnectptr.p->fragmentid = readLogword(signal);
21152     commitLogRecord->fileNo = readLogword(signal);
21153     commitLogRecord->startPageNo = readLogword(signal);
21154     commitLogRecord->startPageIndex = readLogword(signal);
21155     commitLogRecord->stopPageNo = readLogword(signal);
21156     tcConnectptr.p->gci_hi = readLogword(signal);
21157     tcConnectptr.p->gci_lo = 0;
21158   }//if
21159   tcConnectptr.p->transid[0] = logPartPtr.i + 65536;
21160   tcConnectptr.p->transid[1] = (DBLQH << 20) + (cownNodeid << 8);
21161 }//Dblqh::readCommitLog()
21162 
21163 /* ------------------------------------------------------------------------- */
21164 /* -------        READ LOG PAGES FROM DISK IN ORDER TO EXECUTE A LOG ------- */
21165 /*                RECORD WHICH WAS NOT FOUND IN MAIN MEMORY.                 */
21166 /*                                                                           */
21167 /*       SUBROUTINE SHORT NAME = REL                                         */
21168 /* ------------------------------------------------------------------------- */
readExecLog(Signal * signal)21169 void Dblqh::readExecLog(Signal* signal)
21170 {
21171   UintR trelIndex;
21172   UintR trelI;
21173 
21174   seizeLfo(signal);
21175   initLfo(signal);
21176   trelI = logPartPtr.p->execSrStopPageNo - logPartPtr.p->execSrStartPageNo;
21177   arrGuard(trelI + 1, 16);
21178   lfoPtr.p->logPageArray[trelI + 1] = logPartPtr.p->execSrStartPageNo;
21179   for (trelIndex = logPartPtr.p->execSrStopPageNo; (trelIndex >= logPartPtr.p->execSrStartPageNo) &&
21180        (UintR)~trelIndex; trelIndex--) {
21181     jam();
21182     seizeLogpage(signal);
21183     arrGuard(trelI, 16);
21184     lfoPtr.p->logPageArray[trelI] = logPagePtr.i;
21185     trelI--;
21186   }//for
21187   lfoPtr.p->lfoPageNo = logPartPtr.p->execSrStartPageNo;
21188   lfoPtr.p->noPagesRw = (logPartPtr.p->execSrStopPageNo -
21189 			 logPartPtr.p->execSrStartPageNo) + 1;
21190   lfoPtr.p->firstLfoPage = lfoPtr.p->logPageArray[0];
21191   signal->theData[0] = logFilePtr.p->fileRef;
21192   signal->theData[1] = cownref;
21193   signal->theData[2] = lfoPtr.i;
21194   signal->theData[3] = ZLIST_OF_MEM_PAGES; // edtjamo TR509 //ZLIST_OF_PAIRS;
21195   signal->theData[4] = ZVAR_NO_LOG_PAGE_WORD;
21196   signal->theData[5] = lfoPtr.p->noPagesRw;
21197   signal->theData[6] = lfoPtr.p->logPageArray[0];
21198   signal->theData[7] = lfoPtr.p->logPageArray[1];
21199   signal->theData[8] = lfoPtr.p->logPageArray[2];
21200   signal->theData[9] = lfoPtr.p->logPageArray[3];
21201   signal->theData[10] = lfoPtr.p->logPageArray[4];
21202   signal->theData[11] = lfoPtr.p->logPageArray[5];
21203   signal->theData[12] = lfoPtr.p->logPageArray[6];
21204   signal->theData[13] = lfoPtr.p->logPageArray[7];
21205   signal->theData[14] = lfoPtr.p->logPageArray[8];
21206   signal->theData[15] = lfoPtr.p->logPageArray[9];
21207   sendSignal(NDBFS_REF, GSN_FSREADREQ, signal, 16, JBA);
21208 
21209   if (DEBUG_REDO)
21210   {
21211     ndbout_c("readExecLog %u page at part: %u file: %u page: %u (mb: %u)",
21212              lfoPtr.p->noPagesRw,
21213              logPartPtr.p->logPartNo,
21214              logFilePtr.p->fileNo,
21215              logPartPtr.p->execSrStartPageNo,
21216              logPartPtr.p->execSrStartPageNo >> ZTWOLOG_NO_PAGES_IN_MBYTE);
21217   }
21218 }//Dblqh::readExecLog()
21219 
21220 /* ------------------------------------------------------------------------- */
21221 /* -------        READ 64 KBYTES WHEN EXECUTING THE FRAGMENT LOG     ------- */
21222 /*                                                                           */
21223 /*       SUBROUTINE SHORT NAME = RES                                         */
21224 /* ------------------------------------------------------------------------- */
readExecSrNewMbyte(Signal * signal)21225 void Dblqh::readExecSrNewMbyte(Signal* signal)
21226 {
21227   logFilePtr.p->currentFilepage = logFilePtr.p->currentMbyte * ZPAGES_IN_MBYTE;
21228   logFilePtr.p->filePosition = logFilePtr.p->currentMbyte * ZPAGES_IN_MBYTE;
21229   logPartPtr.p->execSrPagesRead = 0;
21230   logPartPtr.p->execSrPagesReading = 0;
21231   logPartPtr.p->execSrPagesExecuted = 0;
21232   readExecSr(signal);
21233   logPartPtr.p->logExecState = LogPartRecord::LES_WAIT_READ_EXEC_SR_NEW_MBYTE;
21234 }//Dblqh::readExecSrNewMbyte()
21235 
21236 /* ------------------------------------------------------------------------- */
21237 /* -------        READ 64 KBYTES WHEN EXECUTING THE FRAGMENT LOG     ------- */
21238 /*                                                                           */
21239 /*       SUBROUTINE SHORT NAME = RES                                         */
21240 /* ------------------------------------------------------------------------- */
readExecSr(Signal * signal)21241 void Dblqh::readExecSr(Signal* signal)
21242 {
21243   UintR tresPageid;
21244   UintR tresIndex;
21245 
21246   tresPageid = logFilePtr.p->filePosition;
21247   seizeLfo(signal);
21248   initLfo(signal);
21249   for (tresIndex = 7; (UintR)~tresIndex; tresIndex--) {
21250     jam();
21251 /* ------------------------------------------------------------------------- */
21252 /* GO BACKWARDS SINCE WE INSERT AT THE BEGINNING AND WE WANT THAT FIRST PAGE */
21253 /* SHALL BE FIRST AND LAST PAGE LAST.                                        */
21254 /* ------------------------------------------------------------------------- */
21255     seizeLogpage(signal);
21256     lfoPtr.p->logPageArray[tresIndex] = logPagePtr.i;
21257   }//for
21258   lfoPtr.p->lfoState = LogFileOperationRecord::READ_EXEC_SR;
21259   lfoPtr.p->lfoPageNo = tresPageid;
21260   logFilePtr.p->filePosition = logFilePtr.p->filePosition + 8;
21261   logPartPtr.p->execSrPagesReading = logPartPtr.p->execSrPagesReading + 8;
21262   lfoPtr.p->noPagesRw = 8;
21263   lfoPtr.p->firstLfoPage = lfoPtr.p->logPageArray[0];
21264   signal->theData[0] = logFilePtr.p->fileRef;
21265   signal->theData[1] = cownref;
21266   signal->theData[2] = lfoPtr.i;
21267   signal->theData[3] = ZLIST_OF_MEM_PAGES;
21268   signal->theData[4] = ZVAR_NO_LOG_PAGE_WORD;
21269   signal->theData[5] = 8;
21270   signal->theData[6] = lfoPtr.p->logPageArray[0];
21271   signal->theData[7] = lfoPtr.p->logPageArray[1];
21272   signal->theData[8] = lfoPtr.p->logPageArray[2];
21273   signal->theData[9] = lfoPtr.p->logPageArray[3];
21274   signal->theData[10] = lfoPtr.p->logPageArray[4];
21275   signal->theData[11] = lfoPtr.p->logPageArray[5];
21276   signal->theData[12] = lfoPtr.p->logPageArray[6];
21277   signal->theData[13] = lfoPtr.p->logPageArray[7];
21278   signal->theData[14] = tresPageid;
21279   sendSignal(NDBFS_REF, GSN_FSREADREQ, signal, 15, JBA);
21280 
21281   if (DEBUG_REDO)
21282   {
21283     ndbout_c("readExecSr %u page at part: %u file: %u page: %u (mb: %u)",
21284              8,
21285              logPartPtr.p->logPartNo,
21286              logFilePtr.p->fileNo,
21287              tresPageid,
21288              tresPageid >> ZTWOLOG_NO_PAGES_IN_MBYTE);
21289   }
21290 }//Dblqh::readExecSr()
21291 
21292 /* ------------------------------------------------------------------------- */
21293 /* ------------ READ THE PRIMARY KEY FROM THE LOG           ---------------- */
21294 /*                                                                           */
21295 /*       SUBROUTINE SHORT NAME = RK                                          */
21296 /* --------------------------------------------------------------------------*/
readKey(Signal * signal)21297 void Dblqh::readKey(Signal* signal)
21298 {
21299   Uint32 remainingLen = tcConnectptr.p->primKeyLen;
21300   ndbrequire(remainingLen != 0);
21301 
21302   readLogData(signal, remainingLen, tcConnectptr.p->keyInfoIVal);
21303 }//Dblqh::readKey()
21304 
21305 /* ------------------------------------------------------------------------- */
21306 /* ------------ READ A NUMBER OF WORDS FROM LOG INTO CDATA  ---------------- */
21307 /*                                                                           */
21308 /*       SUBROUTINE SHORT NAME = RLD                                         */
21309 /* --------------------------------------------------------------------------*/
readLogData(Signal * signal,Uint32 noOfWords,Uint32 & sectionIVal)21310 void Dblqh::readLogData(Signal* signal, Uint32 noOfWords, Uint32& sectionIVal)
21311 {
21312   Uint32 logPos = logPagePtr.p->logPageWord[ZCURR_PAGE_INDEX];
21313   if ((logPos + noOfWords) >= ZPAGE_SIZE) {
21314     for (Uint32 i = 0; i < noOfWords; i++)
21315     {
21316       /* Todo : Consider reading > 1 word at a time */
21317       Uint32 word= readLogwordExec(signal);
21318       bool ok= appendToSection(sectionIVal,
21319                                &word,
21320                                1);
21321       ndbrequire(ok);
21322     }
21323   } else {
21324     /* In one bite */
21325     bool ok= appendToSection(sectionIVal,
21326                              &logPagePtr.p->logPageWord[logPos],
21327                              noOfWords);
21328     ndbrequire(ok);
21329     logPagePtr.p->logPageWord[ZCURR_PAGE_INDEX] = logPos + noOfWords;
21330   }//if
21331 }//Dblqh::readLogData()
21332 
21333 /* ------------------------------------------------------------------------- */
21334 /* ------------ READ THE LOG HEADER OF A PREPARE LOG HEADER ---------------- */
21335 /*                                                                           */
21336 /*       SUBROUTINE SHORT NAME = RLH                                         */
21337 /* --------------------------------------------------------------------------*/
readLogHeader(Signal * signal)21338 void Dblqh::readLogHeader(Signal* signal)
21339 {
21340   Uint32 logPos = logPagePtr.p->logPageWord[ZCURR_PAGE_INDEX];
21341   if ((logPos + ZLOG_HEAD_SIZE) < ZPAGE_SIZE) {
21342     jam();
21343     tcConnectptr.p->hashValue = logPagePtr.p->logPageWord[logPos + 2];
21344     tcConnectptr.p->operation = logPagePtr.p->logPageWord[logPos + 3];
21345     tcConnectptr.p->totSendlenAi = logPagePtr.p->logPageWord[logPos + 4];
21346     tcConnectptr.p->primKeyLen = logPagePtr.p->logPageWord[logPos + 5];
21347     tcConnectptr.p->m_row_id.m_page_no = logPagePtr.p->logPageWord[logPos + 6];
21348     tcConnectptr.p->m_row_id.m_page_idx = logPagePtr.p->logPageWord[logPos+ 7];
21349     logPagePtr.p->logPageWord[ZCURR_PAGE_INDEX] = logPos + ZLOG_HEAD_SIZE;
21350   } else {
21351     jam();
21352     readLogwordExec(signal);	/* IGNORE PREPARE LOG RECORD TYPE */
21353     readLogwordExec(signal);	/* IGNORE LOG RECORD SIZE         */
21354     tcConnectptr.p->hashValue = readLogwordExec(signal);
21355     tcConnectptr.p->operation = readLogwordExec(signal);
21356     tcConnectptr.p->totSendlenAi = readLogwordExec(signal);
21357     tcConnectptr.p->primKeyLen = readLogwordExec(signal);
21358     tcConnectptr.p->m_row_id.m_page_no = readLogwordExec(signal);
21359     tcConnectptr.p->m_row_id.m_page_idx = readLogwordExec(signal);
21360   }//if
21361 
21362   tcConnectptr.p->m_use_rowid = (tcConnectptr.p->operation == ZINSERT);
21363 }//Dblqh::readLogHeader()
21364 
21365 /* ------------------------------------------------------------------------- */
21366 /* -------               READ A WORD FROM THE LOG                    ------- */
21367 /*                                                                           */
21368 /*       OUTPUT:         TLOG_WORD                                           */
21369 /*       SUBROUTINE SHORT NAME = RLW                                         */
21370 /* ------------------------------------------------------------------------- */
readLogword(Signal * signal)21371 Uint32 Dblqh::readLogword(Signal* signal)
21372 {
21373   Uint32 logPos = logPagePtr.p->logPageWord[ZCURR_PAGE_INDEX];
21374   ndbrequire(logPos < ZPAGE_SIZE);
21375   Uint32 logWord = logPagePtr.p->logPageWord[logPos];
21376   logPos++;
21377   logPagePtr.p->logPageWord[ZCURR_PAGE_INDEX] = logPos;
21378   if (logPos >= ZPAGE_SIZE) {
21379     jam();
21380     logPagePtr.i = logPagePtr.p->logPageWord[ZNEXT_PAGE];
21381     ptrCheckGuard(logPagePtr, clogPageFileSize, logPageRecord);
21382     logPagePtr.p->logPageWord[ZCURR_PAGE_INDEX] = ZPAGE_HEADER_SIZE;
21383     logFilePtr.p->currentLogpage = logPagePtr.i;
21384     logFilePtr.p->currentFilepage++;
21385     logPartPtr.p->execSrPagesRead--;
21386     logPartPtr.p->execSrPagesExecuted++;
21387   }//if
21388   return logWord;
21389 }//Dblqh::readLogword()
21390 
21391 /* ------------------------------------------------------------------------- */
21392 /* -------   READ A WORD FROM THE LOG WHEN EXECUTING A LOG RECORD    ------- */
21393 /*                                                                           */
21394 /*       OUTPUT:         TLOG_WORD                                           */
21395 /*       SUBROUTINE SHORT NAME = RWE                                         */
21396 /* ------------------------------------------------------------------------- */
readLogwordExec(Signal * signal)21397 Uint32 Dblqh::readLogwordExec(Signal* signal)
21398 {
21399   Uint32 logPos = logPagePtr.p->logPageWord[ZCURR_PAGE_INDEX];
21400   ndbrequire(logPos < ZPAGE_SIZE);
21401   Uint32 logWord = logPagePtr.p->logPageWord[logPos];
21402   logPos++;
21403   logPagePtr.p->logPageWord[ZCURR_PAGE_INDEX] = logPos;
21404   if (logPos >= ZPAGE_SIZE) {
21405     jam();
21406     logPagePtr.i = logPagePtr.p->logPageWord[ZNEXT_PAGE];
21407     if (logPagePtr.i != RNIL){
21408       ptrCheckGuard(logPagePtr, clogPageFileSize, logPageRecord);
21409       logPagePtr.p->logPageWord[ZCURR_PAGE_INDEX] = ZPAGE_HEADER_SIZE;
21410     } else {
21411       // Reading word at the last pos in the last page
21412       // Don't step forward to next page!
21413       jam();
21414       logPagePtr.p->logPageWord[ZCURR_PAGE_INDEX]++;
21415     }
21416   }//if
21417   return logWord;
21418 }//Dblqh::readLogwordExec()
21419 
21420 /* ------------------------------------------------------------------------- */
21421 /* -------               READ A SINGLE PAGE FROM THE LOG             ------- */
21422 /*                                                                           */
21423 /*       INPUT:          TRSP_PAGE_NO                                        */
21424 /*       SUBROUTINE SHORT NAME = RSP                                         */
21425 /* ------------------------------------------------------------------------- */
readSinglePage(Signal * signal,Uint32 pageNo)21426 void Dblqh::readSinglePage(Signal* signal, Uint32 pageNo)
21427 {
21428   seizeLfo(signal);
21429   initLfo(signal);
21430   seizeLogpage(signal);
21431   lfoPtr.p->firstLfoPage = logPagePtr.i;
21432   lfoPtr.p->lfoPageNo = pageNo;
21433   lfoPtr.p->noPagesRw = 1;
21434   signal->theData[0] = logFilePtr.p->fileRef;
21435   signal->theData[1] = cownref;
21436   signal->theData[2] = lfoPtr.i;
21437   signal->theData[3] = ZLIST_OF_PAIRS;
21438   signal->theData[4] = ZVAR_NO_LOG_PAGE_WORD;
21439   signal->theData[5] = 1;
21440   signal->theData[6] = logPagePtr.i;
21441   signal->theData[7] = pageNo;
21442   sendSignal(NDBFS_REF, GSN_FSREADREQ, signal, 8, JBA);
21443 
21444   if (DEBUG_REDO)
21445   {
21446     ndbout_c("readSinglePage 1 page at part: %u file: %u page: %u (mb: %u)",
21447              logPartPtr.p->logPartNo,
21448              logFilePtr.p->fileNo,
21449              pageNo,
21450              pageNo >> ZTWOLOG_NO_PAGES_IN_MBYTE);
21451   }
21452 }//Dblqh::readSinglePage()
21453 
21454 /* --------------------------------------------------------------------------
21455  * -------       REMOVE COPY FRAGMENT FROM ACTIVE COPY LIST           -------
21456  *
21457  * ------------------------------------------------------------------------- */
releaseActiveCopy(Signal * signal)21458 void Dblqh::releaseActiveCopy(Signal* signal)
21459 {
21460                                                 /* MUST BE 8 BIT */
21461   UintR tracFlag;
21462   UintR tracIndex;
21463 
21464   tracFlag = ZFALSE;
21465   for (tracIndex = 0; tracIndex < 4; tracIndex++) {
21466     if (tracFlag == ZFALSE) {
21467       jam();
21468       if (cactiveCopy[tracIndex] == fragptr.i) {
21469         jam();
21470         tracFlag = ZTRUE;
21471       }//if
21472     } else {
21473       if (tracIndex < 3) {
21474         jam();
21475         cactiveCopy[tracIndex - 1] = cactiveCopy[tracIndex];
21476       } else {
21477         jam();
21478         cactiveCopy[3] = RNIL;
21479       }//if
21480     }//if
21481   }//for
21482   ndbrequire(tracFlag == ZTRUE);
21483   cnoActiveCopy--;
21484 }//Dblqh::releaseActiveCopy()
21485 
21486 
21487 /* --------------------------------------------------------------------------
21488  * -------       RELEASE ADD FRAGMENT RECORD                          -------
21489  *
21490  * ------------------------------------------------------------------------- */
releaseAddfragrec(Signal * signal)21491 void Dblqh::releaseAddfragrec(Signal* signal)
21492 {
21493   addfragptr.p->addfragStatus = AddFragRecord::FREE;
21494   addfragptr.p->nextAddfragrec = cfirstfreeAddfragrec;
21495   cfirstfreeAddfragrec = addfragptr.i;
21496 }//Dblqh::releaseAddfragrec()
21497 
21498 /* --------------------------------------------------------------------------
21499  * -------     RELEASE A PAGE REFERENCE RECORD.                       -------
21500  *
21501  * ------------------------------------------------------------------------- */
releasePageRef(Signal * signal)21502 void Dblqh::releasePageRef(Signal* signal)
21503 {
21504   pageRefPtr.p->prNext = cfirstfreePageRef;
21505   cfirstfreePageRef = pageRefPtr.i;
21506 }//Dblqh::releasePageRef()
21507 
21508 /* --------------------------------------------------------------------------
21509  * --- RELEASE ALL PAGES IN THE MM BUFFER AFTER EXECUTING THE LOG ON IT. ----
21510  *
21511  * ------------------------------------------------------------------------- */
releaseMmPages(Signal * signal)21512 void Dblqh::releaseMmPages(Signal* signal)
21513 {
21514 RMP_LOOP:
21515   jam();
21516   pageRefPtr.i = logPartPtr.p->firstPageRef;
21517   if (pageRefPtr.i != RNIL) {
21518     jam();
21519     ptrCheckGuard(pageRefPtr, cpageRefFileSize, pageRefRecord);
21520     releasePrPages(signal);
21521     removePageRef(signal);
21522     goto RMP_LOOP;
21523   }//if
21524 }//Dblqh::releaseMmPages()
21525 
21526 /* --------------------------------------------------------------------------
21527  * -------     RELEASE A SET OF PAGES AFTER EXECUTING THE LOG ON IT.  -------
21528  *
21529  * ------------------------------------------------------------------------- */
releasePrPages(Signal * signal)21530 void Dblqh::releasePrPages(Signal* signal)
21531 {
21532   UintR trppIndex;
21533 
21534   for (trppIndex = 0; trppIndex <= 7; trppIndex++) {
21535     jam();
21536     logPagePtr.i = pageRefPtr.p->pageRef[trppIndex];
21537     ptrCheckGuard(logPagePtr, clogPageFileSize, logPageRecord);
21538     releaseLogpage(signal);
21539   }//for
21540 }//Dblqh::releasePrPages()
21541 
21542 /* --------------------------------------------------------------------------
21543  * -------  RELEASE OPERATION FROM WAIT QUEUE LIST ON FRAGMENT        -------
21544  *
21545  *       SUBROUTINE SHORT NAME : RWA
21546  * ------------------------------------------------------------------------- */
releaseWaitQueue(Signal * signal)21547 void Dblqh::releaseWaitQueue(Signal* signal)
21548 {
21549   TcConnectionrecPtr rwaTcNextConnectptr;
21550   TcConnectionrecPtr rwaTcPrevConnectptr;
21551 
21552   fragptr.i = tcConnectptr.p->fragmentptr;
21553   c_fragment_pool.getPtr(fragptr);
21554   rwaTcPrevConnectptr.i = tcConnectptr.p->prevTc;
21555   rwaTcNextConnectptr.i = tcConnectptr.p->nextTc;
21556   if (tcConnectptr.p->listState != TcConnectionrec::WAIT_QUEUE_LIST) {
21557     jam();
21558     systemError(signal, __LINE__);
21559   }//if
21560   tcConnectptr.p->listState = TcConnectionrec::NOT_IN_LIST;
21561   if (rwaTcNextConnectptr.i != RNIL) {
21562     jam();
21563     ptrCheckGuard(rwaTcNextConnectptr, ctcConnectrecFileSize, tcConnectionrec);
21564     rwaTcNextConnectptr.p->prevTc = rwaTcPrevConnectptr.i;
21565   } else {
21566     jam();
21567     fragptr.p->lastWaitQueue = rwaTcPrevConnectptr.i;
21568   }//if
21569   if (rwaTcPrevConnectptr.i != RNIL) {
21570     jam();
21571     ptrCheckGuard(rwaTcPrevConnectptr, ctcConnectrecFileSize, tcConnectionrec);
21572     rwaTcPrevConnectptr.p->nextTc = rwaTcNextConnectptr.i;
21573   } else {
21574     jam();
21575     fragptr.p->firstWaitQueue = rwaTcNextConnectptr.i;
21576   }//if
21577 }//Dblqh::releaseWaitQueue()
21578 
21579 /* --------------------------------------------------------------------------
21580  * -------  REMOVE OPERATION RECORD FROM LIST ON LOG PART OF NOT      -------
21581  *               COMPLETED OPERATIONS IN THE LOG.
21582  *
21583  *       SUBROUTINE SHORT NAME = RLO
21584  * ------------------------------------------------------------------------- */
removeLogTcrec(Signal * signal)21585 void Dblqh::removeLogTcrec(Signal* signal)
21586 {
21587   TcConnectionrecPtr rloTcNextConnectptr;
21588   TcConnectionrecPtr rloTcPrevConnectptr;
21589   rloTcPrevConnectptr.i = tcConnectptr.p->prevLogTcrec;
21590   rloTcNextConnectptr.i = tcConnectptr.p->nextLogTcrec;
21591   if (rloTcNextConnectptr.i != RNIL) {
21592     jam();
21593     ptrCheckGuard(rloTcNextConnectptr, ctcConnectrecFileSize, tcConnectionrec);
21594     rloTcNextConnectptr.p->prevLogTcrec = rloTcPrevConnectptr.i;
21595   } else {
21596     jam();
21597     logPartPtr.p->lastLogTcrec = rloTcPrevConnectptr.i;
21598   }//if
21599   if (rloTcPrevConnectptr.i != RNIL) {
21600     jam();
21601     ptrCheckGuard(rloTcPrevConnectptr, ctcConnectrecFileSize, tcConnectionrec);
21602     rloTcPrevConnectptr.p->nextLogTcrec = rloTcNextConnectptr.i;
21603   } else {
21604     jam();
21605     logPartPtr.p->firstLogTcrec = rloTcNextConnectptr.i;
21606   }//if
21607 }//Dblqh::removeLogTcrec()
21608 
21609 /* --------------------------------------------------------------------------
21610  * -------  REMOVE PAGE REFERENCE RECORD FROM LIST IN THIS LOG PART   -------
21611  *
21612  *       SUBROUTINE SHORT NAME = RPR
21613  * ------------------------------------------------------------------------- */
removePageRef(Signal * signal)21614 void Dblqh::removePageRef(Signal* signal)
21615 {
21616   PageRefRecordPtr rprPageRefPtr;
21617 
21618   pageRefPtr.i = logPartPtr.p->firstPageRef;
21619   if (pageRefPtr.i != RNIL) {
21620     jam();
21621     ptrCheckGuard(pageRefPtr, cpageRefFileSize, pageRefRecord);
21622     if (pageRefPtr.p->prNext == RNIL) {
21623       jam();
21624       logPartPtr.p->lastPageRef = RNIL;
21625       logPartPtr.p->firstPageRef = RNIL;
21626     } else {
21627       jam();
21628       logPartPtr.p->firstPageRef = pageRefPtr.p->prNext;
21629       rprPageRefPtr.i = pageRefPtr.p->prNext;
21630       ptrCheckGuard(rprPageRefPtr, cpageRefFileSize, pageRefRecord);
21631       rprPageRefPtr.p->prPrev = RNIL;
21632     }//if
21633     releasePageRef(signal);
21634   }//if
21635 }//Dblqh::removePageRef()
21636 
21637 /* ------------------------------------------------------------------------- */
21638 /* -------       RETURN FROM EXECUTION OF LOG                        ------- */
21639 /*                                                                           */
21640 /* ------------------------------------------------------------------------- */
returnExecLog(Signal * signal)21641 Uint32 Dblqh::returnExecLog(Signal* signal)
21642 {
21643   tcConnectptr.p->connectState = TcConnectionrec::CONNECTED;
21644   initLogPointers(signal);
21645   logPartPtr.p->execSrExecuteIndex++;
21646   Uint32 result = checkIfExecLog(signal);
21647   if (result == ZOK) {
21648     jam();
21649 /* ------------------------------------------------------------------------- */
21650 /* THIS LOG RECORD WILL BE EXECUTED AGAIN TOWARDS ANOTHER NODE.              */
21651 /* ------------------------------------------------------------------------- */
21652     logPagePtr.i = logPartPtr.p->execSrLogPage;
21653     ptrCheckGuard(logPagePtr, clogPageFileSize, logPageRecord);
21654     logPagePtr.p->logPageWord[ZCURR_PAGE_INDEX] =
21655                   logPartPtr.p->execSrLogPageIndex;
21656   } else {
21657     jam();
21658 /* ------------------------------------------------------------------------- */
21659 /*       NO MORE EXECUTION OF THIS LOG RECORD.                               */
21660 /* ------------------------------------------------------------------------- */
21661     if (logPartPtr.p->logExecState ==
21662 	LogPartRecord::LES_EXEC_LOGREC_FROM_FILE) {
21663       jam();
21664 /* ------------------------------------------------------------------------- */
21665 /* THE LOG RECORD WAS READ FROM DISK. RELEASE ITS PAGES IMMEDIATELY.         */
21666 /* ------------------------------------------------------------------------- */
21667       lfoPtr.i = logPartPtr.p->execSrLfoRec;
21668       ptrCheckGuard(lfoPtr, clfoFileSize, logFileOperationRecord);
21669       releaseLfoPages(signal);
21670       releaseLfo(signal);
21671       logPartPtr.p->logExecState = LogPartRecord::LES_EXEC_LOG;
21672       if (logPartPtr.p->execSrExecLogFile != logPartPtr.p->currentLogfile) {
21673         jam();
21674         LogFileRecordPtr clfLogFilePtr;
21675         clfLogFilePtr.i = logPartPtr.p->execSrExecLogFile;
21676         ptrCheckGuard(clfLogFilePtr, clogFileFileSize, logFileRecord);
21677 #ifndef NO_REDO_OPEN_FILE_CACHE
21678         closeFile_cache(signal, clfLogFilePtr, __LINE__);
21679 #else
21680         clfLogFilePtr.p->logFileStatus = LogFileRecord::CLOSING_EXEC_LOG;
21681         closeFile(signal, clfLogFilePtr, __LINE__);
21682 #endif
21683         result = ZCLOSE_FILE;
21684       }//if
21685     }//if
21686     logPartPtr.p->execSrExecuteIndex = 0;
21687     logPartPtr.p->execSrLogPage = RNIL;
21688     logPartPtr.p->execSrLogPageIndex = ZNIL;
21689     logPagePtr.i = logFilePtr.p->currentLogpage;
21690     ptrCheckGuard(logPagePtr, clogPageFileSize, logPageRecord);
21691     logPagePtr.p->logPageWord[ZCURR_PAGE_INDEX] = logPartPtr.p->savePageIndex;
21692   }//if
21693   return result;
21694 }//Dblqh::returnExecLog()
21695 
21696 /* --------------------------------------------------------------------------
21697  * -------       SEIZE ADD FRAGMENT RECORD                             ------
21698  *
21699  * ------------------------------------------------------------------------- */
seizeAddfragrec(Signal * signal)21700 void Dblqh::seizeAddfragrec(Signal* signal)
21701 {
21702   addfragptr.i = cfirstfreeAddfragrec;
21703   ptrCheckGuard(addfragptr, caddfragrecFileSize, addFragRecord);
21704   cfirstfreeAddfragrec = addfragptr.p->nextAddfragrec;
21705 
21706   addfragptr.p->accConnectptr = RNIL;
21707   addfragptr.p->tupConnectptr = RNIL;
21708   addfragptr.p->tuxConnectptr = RNIL;
21709   addfragptr.p->defValSectionI = RNIL;
21710   addfragptr.p->defValNextPos = 0;
21711   bzero(&addfragptr.p->m_createTabReq, sizeof(addfragptr.p->m_createTabReq));
21712   bzero(&addfragptr.p->m_lqhFragReq, sizeof(addfragptr.p->m_lqhFragReq));
21713   bzero(&addfragptr.p->m_addAttrReq, sizeof(addfragptr.p->m_addAttrReq));
21714   bzero(&addfragptr.p->m_dropFragReq, sizeof(addfragptr.p->m_dropFragReq));
21715   bzero(&addfragptr.p->m_dropTabReq, sizeof(addfragptr.p->m_dropTabReq));
21716   addfragptr.p->addfragErrorCode = 0;
21717   addfragptr.p->attrSentToTup = 0;
21718   addfragptr.p->attrReceived = 0;
21719   addfragptr.p->totalAttrReceived = 0;
21720 }//Dblqh::seizeAddfragrec()
21721 
21722 /* --------------------------------------------------------------------------
21723  * -------       SEIZE FRAGMENT RECORD                                -------
21724  *
21725  * ------------------------------------------------------------------------- */
21726 /* ------------------------------------------------------------------------- */
21727 /* -------     SEIZE A PAGE REFERENCE RECORD.                        ------- */
21728 /*                                                                           */
21729 /* ------------------------------------------------------------------------- */
seizePageRef(Signal * signal)21730 void Dblqh::seizePageRef(Signal* signal)
21731 {
21732   pageRefPtr.i = cfirstfreePageRef;
21733   ptrCheckGuard(pageRefPtr, cpageRefFileSize, pageRefRecord);
21734   cfirstfreePageRef = pageRefPtr.p->prNext;
21735   pageRefPtr.p->prNext = RNIL;
21736 }//Dblqh::seizePageRef()
21737 
21738 /* --------------------------------------------------------------------------
21739  * -------               SEND ABORTED                                 -------
21740  *
21741  * ------------------------------------------------------------------------- */
sendAborted(Signal * signal)21742 void Dblqh::sendAborted(Signal* signal)
21743 {
21744   UintR TlastInd;
21745   if (tcConnectptr.p->nextReplica == ZNIL) {
21746     TlastInd = ZTRUE;
21747   } else {
21748     TlastInd = ZFALSE;
21749   }//if
21750   signal->theData[0] = tcConnectptr.p->tcOprec;
21751   signal->theData[1] = tcConnectptr.p->transid[0];
21752   signal->theData[2] = tcConnectptr.p->transid[1];
21753   signal->theData[3] = cownNodeid;
21754   signal->theData[4] = TlastInd;
21755   sendSignal(tcConnectptr.p->tcBlockref, GSN_ABORTED, signal, 5, JBB);
21756   return;
21757 }//Dblqh::sendAborted()
21758 
21759 /* --------------------------------------------------------------------------
21760  * -------               SEND LQH_TRANSCONF                           -------
21761  *
21762  * ------------------------------------------------------------------------- */
sendLqhTransconf(Signal * signal,LqhTransConf::OperationStatus stat)21763 void Dblqh::sendLqhTransconf(Signal* signal, LqhTransConf::OperationStatus stat)
21764 {
21765   tcNodeFailptr.i = tcConnectptr.p->tcNodeFailrec;
21766   ptrCheckGuard(tcNodeFailptr, ctcNodeFailrecFileSize, tcNodeFailRecord);
21767 
21768   Uint32 reqInfo = 0;
21769   LqhTransConf::setReplicaType(reqInfo, tcConnectptr.p->replicaType);
21770   LqhTransConf::setReplicaNo(reqInfo, tcConnectptr.p->seqNoReplica);
21771   LqhTransConf::setLastReplicaNo(reqInfo, tcConnectptr.p->lastReplicaNo);
21772   LqhTransConf::setSimpleFlag(reqInfo, tcConnectptr.p->opSimple);
21773   LqhTransConf::setDirtyFlag(reqInfo, tcConnectptr.p->dirtyOp);
21774   LqhTransConf::setOperation(reqInfo, tcConnectptr.p->operation);
21775 
21776   LqhTransConf * const lqhTransConf = (LqhTransConf *)&signal->theData[0];
21777   lqhTransConf->tcRef           = tcNodeFailptr.p->newTcRef;
21778   lqhTransConf->lqhNodeId       = cownNodeid;
21779   lqhTransConf->operationStatus = stat;
21780   lqhTransConf->lqhConnectPtr   = tcConnectptr.i;
21781   lqhTransConf->transId1        = tcConnectptr.p->transid[0];
21782   lqhTransConf->transId2        = tcConnectptr.p->transid[1];
21783   lqhTransConf->oldTcOpRec      = tcConnectptr.p->tcOprec;
21784   lqhTransConf->requestInfo     = reqInfo;
21785   lqhTransConf->gci_hi          = tcConnectptr.p->gci_hi;
21786   lqhTransConf->nextNodeId1     = tcConnectptr.p->nextReplica;
21787   lqhTransConf->nextNodeId2     = tcConnectptr.p->nodeAfterNext[0];
21788   lqhTransConf->nextNodeId3     = tcConnectptr.p->nodeAfterNext[1];
21789   lqhTransConf->apiRef          = tcConnectptr.p->applRef;
21790   lqhTransConf->apiOpRec        = tcConnectptr.p->applOprec;
21791   lqhTransConf->tableId         = tcConnectptr.p->tableref;
21792   lqhTransConf->gci_lo          = tcConnectptr.p->gci_lo;
21793   lqhTransConf->fragId          = tcConnectptr.p->fragmentid;
21794   sendSignal(tcNodeFailptr.p->newTcBlockref, GSN_LQH_TRANSCONF,
21795 	     signal, LqhTransConf::SignalLength, JBB);
21796   tcNodeFailptr.p->tcRecNow = tcConnectptr.i + 1;
21797   signal->theData[0] = ZLQH_TRANS_NEXT;
21798   signal->theData[1] = tcNodeFailptr.i;
21799   sendSignal(cownref, GSN_CONTINUEB, signal, 2, JBB);
21800 
21801   if (0)
21802   {
21803     ndbout_c("sending LQH_TRANSCONF %u transid: H'%.8x, H'%.8x op: %u state: %u(%u) marker: %u",
21804              tcConnectptr.i,
21805              tcConnectptr.p->transid[0],
21806              tcConnectptr.p->transid[1],
21807              tcConnectptr.p->operation,
21808              tcConnectptr.p->transactionState,
21809              stat,
21810              tcConnectptr.p->commitAckMarker);
21811   }
21812 }//Dblqh::sendLqhTransconf()
21813 
21814 /* --------------------------------------------------------------------------
21815  * -------               START ANOTHER PHASE OF LOG EXECUTION         -------
21816  *       RESET THE VARIABLES NEEDED BY THIS PROCESS AND SEND THE START SIGNAL
21817  *
21818  * ------------------------------------------------------------------------- */
startExecSr(Signal * signal)21819 void Dblqh::startExecSr(Signal* signal)
21820 {
21821   c_lcp_complete_fragments.first(fragptr);
21822   signal->theData[0] = fragptr.i;
21823   sendSignal(cownref, GSN_START_EXEC_SR, signal, 1, JBB);
21824 }//Dblqh::startExecSr()
21825 
21826 /* ¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤
21827  * ¤¤¤¤¤¤¤                            LOG MODULE                      ¤¤¤¤¤¤¤
21828  * ¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤ */
21829 /* --------------------------------------------------------------------------
21830  * -------       STEP FORWARD IN FRAGMENT LOG DURING LOG EXECUTION    -------
21831  *
21832  * ------------------------------------------------------------------------- */
stepAhead(Signal * signal,Uint32 stepAheadWords)21833 void Dblqh::stepAhead(Signal* signal, Uint32 stepAheadWords)
21834 {
21835   UintR tsaPos;
21836 
21837   tsaPos = logPagePtr.p->logPageWord[ZCURR_PAGE_INDEX];
21838   while ((stepAheadWords + tsaPos) >= ZPAGE_SIZE) {
21839     jam();
21840     logPagePtr.p->logPageWord[ZCURR_PAGE_INDEX] = ZPAGE_SIZE;
21841     stepAheadWords = stepAheadWords - (ZPAGE_SIZE - tsaPos);
21842     logFilePtr.p->currentLogpage = logPagePtr.p->logPageWord[ZNEXT_PAGE];
21843     logPagePtr.i = logPagePtr.p->logPageWord[ZNEXT_PAGE];
21844     logFilePtr.p->currentFilepage++;
21845     ptrCheckGuardErr(logPagePtr, clogPageFileSize, logPageRecord,
21846                      NDBD_EXIT_SR_REDOLOG);
21847     logPagePtr.p->logPageWord[ZCURR_PAGE_INDEX] = ZPAGE_HEADER_SIZE;
21848     logPartPtr.p->execSrPagesRead--;
21849     logPartPtr.p->execSrPagesExecuted++;
21850     tsaPos = ZPAGE_HEADER_SIZE;
21851   }//while
21852   logPagePtr.p->logPageWord[ZCURR_PAGE_INDEX] = stepAheadWords + tsaPos;
21853 }//Dblqh::stepAhead()
21854 
21855 /* --------------------------------------------------------------------------
21856  * -------               WRITE A ABORT LOG RECORD                     -------
21857  *
21858  *       SUBROUTINE SHORT NAME: WAL
21859  * ------------------------------------------------------------------------- */
writeAbortLog(Signal * signal)21860 void Dblqh::writeAbortLog(Signal* signal)
21861 {
21862   if ((ZABORT_LOG_SIZE + ZNEXT_LOG_SIZE) >
21863       logFilePtr.p->remainingWordsInMbyte) {
21864     jam();
21865     changeMbyte(signal);
21866   }//if
21867   logFilePtr.p->remainingWordsInMbyte =
21868     logFilePtr.p->remainingWordsInMbyte - ZABORT_LOG_SIZE;
21869   writeLogWord(signal, ZABORT_TYPE);
21870   writeLogWord(signal, tcConnectptr.p->transid[0]);
21871   writeLogWord(signal, tcConnectptr.p->transid[1]);
21872 }//Dblqh::writeAbortLog()
21873 
21874 /* --------------------------------------------------------------------------
21875  * -------               WRITE A COMMIT LOG RECORD                    -------
21876  *
21877  *       SUBROUTINE SHORT NAME: WCL
21878  * ------------------------------------------------------------------------- */
writeCommitLog(Signal * signal,LogPartRecordPtr regLogPartPtr)21879 void Dblqh::writeCommitLog(Signal* signal, LogPartRecordPtr regLogPartPtr)
21880 {
21881   LogFileRecordPtr regLogFilePtr;
21882   LogPageRecordPtr regLogPagePtr;
21883   TcConnectionrec * const regTcPtr = tcConnectptr.p;
21884   regLogFilePtr.i = regLogPartPtr.p->currentLogfile;
21885   ptrCheckGuard(regLogFilePtr, clogFileFileSize, logFileRecord);
21886   regLogPagePtr.i = regLogFilePtr.p->currentLogpage;
21887   Uint32 twclTmp = regLogFilePtr.p->remainingWordsInMbyte;
21888   ptrCheckGuard(regLogPagePtr, clogPageFileSize, logPageRecord);
21889   logPartPtr = regLogPartPtr;
21890   logFilePtr = regLogFilePtr;
21891   logPagePtr = regLogPagePtr;
21892   if ((ZCOMMIT_LOG_SIZE + ZNEXT_LOG_SIZE) > twclTmp) {
21893     jam();
21894     changeMbyte(signal);
21895     twclTmp = logFilePtr.p->remainingWordsInMbyte;
21896   }//if
21897 
21898   Uint32 twclLogPos = logPagePtr.p->logPageWord[ZCURR_PAGE_INDEX];
21899   Uint32 tableId = regTcPtr->tableref;
21900   Uint32 schemaVersion = regTcPtr->schemaVersion;
21901   Uint32 fragId = regTcPtr->fragmentid;
21902   Uint32 fileNo = regTcPtr->logStartFileNo;
21903   Uint32 startPageNo = regTcPtr->logStartPageNo;
21904   Uint32 pageIndex = regTcPtr->logStartPageIndex;
21905   Uint32 stopPageNo = regTcPtr->logStopPageNo;
21906   Uint32 gci = regTcPtr->gci_hi;
21907   logFilePtr.p->remainingWordsInMbyte = twclTmp - ZCOMMIT_LOG_SIZE;
21908 
21909   if ((twclLogPos + ZCOMMIT_LOG_SIZE) >= ZPAGE_SIZE) {
21910     writeLogWord(signal, ZCOMMIT_TYPE);
21911     writeLogWord(signal, tableId);
21912     writeLogWord(signal, schemaVersion);
21913     writeLogWord(signal, fragId);
21914     writeLogWord(signal, fileNo);
21915     writeLogWord(signal, startPageNo);
21916     writeLogWord(signal, pageIndex);
21917     writeLogWord(signal, stopPageNo);
21918     writeLogWord(signal, gci);
21919   } else {
21920     Uint32* dataPtr = &logPagePtr.p->logPageWord[twclLogPos];
21921     logPagePtr.p->logPageWord[ZCURR_PAGE_INDEX] = twclLogPos + ZCOMMIT_LOG_SIZE;
21922     dataPtr[0] = ZCOMMIT_TYPE;
21923     dataPtr[1] = tableId;
21924     dataPtr[2] = schemaVersion;
21925     dataPtr[3] = fragId;
21926     dataPtr[4] = fileNo;
21927     dataPtr[5] = startPageNo;
21928     dataPtr[6] = pageIndex;
21929     dataPtr[7] = stopPageNo;
21930     dataPtr[8] = gci;
21931   }//if
21932   TcConnectionrecPtr rloTcNextConnectptr;
21933   TcConnectionrecPtr rloTcPrevConnectptr;
21934   rloTcPrevConnectptr.i = regTcPtr->prevLogTcrec;
21935   rloTcNextConnectptr.i = regTcPtr->nextLogTcrec;
21936   if (rloTcNextConnectptr.i != RNIL) {
21937     jam();
21938     ptrCheckGuard(rloTcNextConnectptr, ctcConnectrecFileSize, tcConnectionrec);
21939     rloTcNextConnectptr.p->prevLogTcrec = rloTcPrevConnectptr.i;
21940   } else {
21941     regLogPartPtr.p->lastLogTcrec = rloTcPrevConnectptr.i;
21942   }//if
21943   if (rloTcPrevConnectptr.i != RNIL) {
21944     jam();
21945     ptrCheckGuard(rloTcPrevConnectptr, ctcConnectrecFileSize, tcConnectionrec);
21946     rloTcPrevConnectptr.p->nextLogTcrec = rloTcNextConnectptr.i;
21947   } else {
21948     regLogPartPtr.p->firstLogTcrec = rloTcNextConnectptr.i;
21949   }//if
21950 }//Dblqh::writeCommitLog()
21951 
21952 /* --------------------------------------------------------------------------
21953  * -------               WRITE A COMPLETED GCI LOG RECORD             -------
21954  *
21955  *       SUBROUTINE SHORT NAME: WCG
21956 // Input Pointers:
21957 // logFilePtr
21958 // logPartPtr
21959  * ------------------------------------------------------------------------- */
writeCompletedGciLog(Signal * signal)21960 void Dblqh::writeCompletedGciLog(Signal* signal)
21961 {
21962   if ((ZCOMPLETED_GCI_LOG_SIZE + ZNEXT_LOG_SIZE) >
21963       logFilePtr.p->remainingWordsInMbyte) {
21964     jam();
21965     changeMbyte(signal);
21966   }//if
21967 
21968   if (ERROR_INSERTED(5051) && (logFilePtr.p->currentFilepage > 0) &&
21969       (logFilePtr.p->currentFilepage % 32) == 0)
21970   {
21971     SET_ERROR_INSERT_VALUE(5000);
21972   }
21973 
21974   logFilePtr.p->remainingWordsInMbyte =
21975     logFilePtr.p->remainingWordsInMbyte - ZCOMPLETED_GCI_LOG_SIZE;
21976 
21977   if (DEBUG_REDO)
21978   {
21979     ndbout_c("writeCompletedGciLog gci: %u part: %u file: %u page: %u (mb: %u)",
21980              cnewestCompletedGci,
21981              logPartPtr.p->logPartNo,
21982              logFilePtr.p->fileNo,
21983              logFilePtr.p->currentFilepage,
21984              logFilePtr.p->currentFilepage >> ZTWOLOG_NO_PAGES_IN_MBYTE);
21985   }
21986 
21987   writeLogWord(signal, ZCOMPLETED_GCI_TYPE);
21988   writeLogWord(signal, cnewestCompletedGci);
21989   logPartPtr.p->logPartNewestCompletedGCI = cnewestCompletedGci;
21990 }//Dblqh::writeCompletedGciLog()
21991 
21992 /* --------------------------------------------------------------------------
21993  * -------         WRITE A DIRTY PAGE DURING LOG EXECUTION            -------
21994  *
21995  *     SUBROUTINE SHORT NAME: WD
21996  * ------------------------------------------------------------------------- */
writeDirty(Signal * signal,Uint32 place)21997 void Dblqh::writeDirty(Signal* signal, Uint32 place)
21998 {
21999   logPagePtr.p->logPageWord[ZPOS_DIRTY] = ZNOT_DIRTY;
22000 
22001   ndbassert(logPartPtr.p->prevFilepage ==
22002             logPagePtr.p->logPageWord[ZPOS_PAGE_NO]);
22003   writeDbgInfoPageHeader(logPagePtr, place, logPartPtr.p->prevFilepage,
22004                          ZPAGE_SIZE);
22005   // Calculate checksum for page
22006   logPagePtr.p->logPageWord[ZPOS_CHECKSUM] = calcPageCheckSum(logPagePtr);
22007 
22008   seizeLfo(signal);
22009   initLfo(signal);
22010   lfoPtr.p->lfoPageNo = logPartPtr.p->prevFilepage;
22011   lfoPtr.p->noPagesRw = 1;
22012   lfoPtr.p->lfoState = LogFileOperationRecord::WRITE_DIRTY;
22013   lfoPtr.p->firstLfoPage = logPagePtr.i;
22014   signal->theData[0] = logFilePtr.p->fileRef;
22015   signal->theData[1] = cownref;
22016   signal->theData[2] = lfoPtr.i;
22017   signal->theData[3] = ZLIST_OF_PAIRS_SYNCH;
22018   signal->theData[4] = ZVAR_NO_LOG_PAGE_WORD;
22019   signal->theData[5] = 1;
22020   signal->theData[6] = logPagePtr.i;
22021   signal->theData[7] = logPartPtr.p->prevFilepage;
22022   sendSignal(NDBFS_REF, GSN_FSWRITEREQ, signal, 8, JBA);
22023 
22024   ndbrequire(logFilePtr.p->fileRef != RNIL);
22025 
22026   logPartPtr.p->m_io_tracker.send_io(32768);
22027 
22028   if (DEBUG_REDO)
22029   {
22030     ndbout_c("writeDirty 1 page at part: %u file: %u page: %u (mb: %u)",
22031              logPartPtr.p->logPartNo,
22032              logFilePtr.p->fileNo,
22033              logPartPtr.p->prevFilepage,
22034              logPartPtr.p->prevFilepage >> ZTWOLOG_NO_PAGES_IN_MBYTE);
22035   }
22036 }//Dblqh::writeDirty()
22037 
22038 /* --------------------------------------------------------------------------
22039  * -------          WRITE A WORD INTO THE LOG, CHECK FOR NEW PAGE     -------
22040  *
22041  *       SUBROUTINE SHORT NAME:  WLW
22042  * ------------------------------------------------------------------------- */
writeLogWord(Signal * signal,Uint32 data)22043 void Dblqh::writeLogWord(Signal* signal, Uint32 data)
22044 {
22045   Uint32 logPos = logPagePtr.p->logPageWord[ZCURR_PAGE_INDEX];
22046   ndbrequire(logPos < ZPAGE_SIZE);
22047   logPagePtr.p->logPageWord[logPos] = data;
22048   logPagePtr.p->logPageWord[ZCURR_PAGE_INDEX] = logPos + 1;
22049   if ((logPos + 1) == ZPAGE_SIZE) {
22050     jam();
22051     completedLogPage(signal, ZNORMAL, __LINE__);
22052     seizeLogpage(signal);
22053     initLogpage(signal);
22054     logFilePtr.p->currentLogpage = logPagePtr.i;
22055     logFilePtr.p->currentFilepage++;
22056   }//if
22057 }//Dblqh::writeLogWord()
22058 
22059 /* --------------------------------------------------------------------------
22060  * -------   WRITE MULTIPLE WORDS INTO THE LOG, CHECK FOR NEW PAGES   -------
22061  *
22062  * ------------------------------------------------------------------------- */
22063 
writeLogWords(Signal * signal,const Uint32 * data,Uint32 len)22064 void Dblqh::writeLogWords(Signal* signal, const Uint32* data, Uint32 len)
22065 {
22066   Uint32 logPos = logPagePtr.p->logPageWord[ZCURR_PAGE_INDEX];
22067   ndbrequire(logPos < ZPAGE_SIZE);
22068   Uint32 wordsThisPage= ZPAGE_SIZE - logPos;
22069 
22070   while (len >= wordsThisPage)
22071   {
22072     /* Fill rest of the log page */
22073     MEMCOPY_NO_WORDS(&logPagePtr.p->logPageWord[logPos],
22074                      data,
22075                      wordsThisPage);
22076     logPagePtr.p->logPageWord[ZCURR_PAGE_INDEX] = ZPAGE_SIZE;
22077     data+= wordsThisPage;
22078     len-= wordsThisPage;
22079 
22080     /* Mark page completed and get a new one */
22081     jam();
22082     completedLogPage(signal, ZNORMAL, __LINE__);
22083     seizeLogpage(signal);
22084     initLogpage(signal);
22085     logFilePtr.p->currentLogpage = logPagePtr.i;
22086     logFilePtr.p->currentFilepage++;
22087 
22088     logPos = logPagePtr.p->logPageWord[ZCURR_PAGE_INDEX];
22089     ndbrequire(logPos < ZPAGE_SIZE);
22090     wordsThisPage= ZPAGE_SIZE - logPos;
22091   }
22092 
22093   if (len > 0)
22094   {
22095     /* No need to worry about next page */
22096     ndbassert( len < wordsThisPage );
22097     /* Write partial log page */
22098     MEMCOPY_NO_WORDS(&logPagePtr.p->logPageWord[logPos],
22099                      data,
22100                      len);
22101     logPagePtr.p->logPageWord[ZCURR_PAGE_INDEX] = logPos + len;
22102   }
22103 
22104   ndbassert( logPagePtr.p->logPageWord[ZCURR_PAGE_INDEX] < ZPAGE_SIZE );
22105 }
22106 
22107 /* --------------------------------------------------------------------------
22108  * -------         WRITE A NEXT LOG RECORD AND CHANGE TO NEXT MBYTE   -------
22109  *
22110  *       SUBROUTINE SHORT NAME:  WNL
22111 // Input Pointers:
22112 // logFilePtr(Redefines)
22113 // logPagePtr (Redefines)
22114 // logPartPtr
22115  * ------------------------------------------------------------------------- */
writeNextLog(Signal * signal)22116 void Dblqh::writeNextLog(Signal* signal)
22117 {
22118   LogFileRecordPtr wnlNextLogFilePtr;
22119   UintR twnlNextFileNo;
22120   UintR twnlNewMbyte;
22121   UintR twnlRemWords;
22122   UintR twnlNextMbyte;
22123 
22124 /* -------------------------------------------------- */
22125 /*       CALCULATE THE NEW NUMBER OF REMAINING WORDS  */
22126 /*       AS 128*2036 WHERE 128 * 8 KBYTE = 1 MBYTE    */
22127 /*       AND 2036 IS THE NUMBER OF WORDS IN A PAGE    */
22128 /*       THAT IS USED FOR LOG INFORMATION.            */
22129 /* -------------------------------------------------- */
22130   twnlRemWords = ZPAGE_SIZE - ZPAGE_HEADER_SIZE;
22131   twnlRemWords = twnlRemWords * ZPAGES_IN_MBYTE;
22132   wnlNextLogFilePtr.i = logFilePtr.p->nextLogFile;
22133   ptrCheckGuard(wnlNextLogFilePtr, clogFileFileSize, logFileRecord);
22134 /* -------------------------------------------------- */
22135 /*       WRITE THE NEXT LOG RECORD.                   */
22136 /* -------------------------------------------------- */
22137   ndbrequire(logPagePtr.p->logPageWord[ZCURR_PAGE_INDEX] < ZPAGE_SIZE);
22138   logPagePtr.p->logPageWord[logPagePtr.p->logPageWord[ZCURR_PAGE_INDEX]] =
22139     ZNEXT_MBYTE_TYPE;
22140   if (logFilePtr.p->currentMbyte == (clogFileSize - 1)) {
22141     jam();
22142 /* -------------------------------------------------- */
22143 /*       CALCULATE THE NEW REMAINING WORDS WHEN       */
22144 /*       CHANGING LOG FILE IS PERFORMED               */
22145 /* -------------------------------------------------- */
22146     twnlRemWords = twnlRemWords - (ZPAGE_SIZE - ZPAGE_HEADER_SIZE);
22147 /* -------------------------------------------------- */
22148 /*       ENSURE THAT THE LOG PAGES ARE WRITTEN AFTER  */
22149 /*       WE HAVE CHANGED MBYTE.                       */
22150 /* -------------------------------------------------- */
22151 /*       ENSURE LAST PAGE IN PREVIOUS MBYTE IS        */
22152 /*       WRITTEN AND THAT THE STATE OF THE WRITE IS   */
22153 /*       PROPERLY SET.                                */
22154 /* -------------------------------------------------- */
22155 /*       WE HAVE TO CHANGE LOG FILE                   */
22156 /* -------------------------------------------------- */
22157     completedLogPage(signal, ZLAST_WRITE_IN_FILE, __LINE__);
22158     if (wnlNextLogFilePtr.p->fileNo == 0) {
22159       jam();
22160 /* -------------------------------------------------- */
22161 /*       WE HAVE FINALISED A LOG LAP, START FROM LOG  */
22162 /*       FILE 0 AGAIN                                 */
22163 /* -------------------------------------------------- */
22164       logPartPtr.p->logLap++;
22165     }//if
22166     logPartPtr.p->currentLogfile = wnlNextLogFilePtr.i;
22167     logFilePtr.i = wnlNextLogFilePtr.i;
22168     logFilePtr.p = wnlNextLogFilePtr.p;
22169     twnlNewMbyte = 0;
22170   } else {
22171     jam();
22172 /* -------------------------------------------------- */
22173 /*       INCREMENT THE CURRENT MBYTE                  */
22174 /*       SET PAGE INDEX TO PAGE HEADER SIZE           */
22175 /* -------------------------------------------------- */
22176     completedLogPage(signal, ZENFORCE_WRITE, __LINE__);
22177     twnlNewMbyte = logFilePtr.p->currentMbyte + 1;
22178   }//if
22179 /* -------------------------------------------------- */
22180 /*       CHANGE TO NEW LOG FILE IF NECESSARY          */
22181 /*       UPDATE THE FILE POSITION TO THE NEW MBYTE    */
22182 /*       FOUND IN PAGE PART OF TNEXT_LOG_PTR          */
22183 /*       ALLOCATE AND INITIATE A NEW PAGE SINCE WE    */
22184 /*       HAVE SENT THE PREVIOUS PAGE TO DISK.         */
22185 /*       SET THE NEW NUMBER OF REMAINING WORDS IN THE */
22186 /*       NEW MBYTE ALLOCATED.                         */
22187 /* -------------------------------------------------- */
22188   logFilePtr.p->currentMbyte = twnlNewMbyte;
22189   logFilePtr.p->filePosition = twnlNewMbyte * ZPAGES_IN_MBYTE;
22190   logFilePtr.p->currentFilepage = twnlNewMbyte * ZPAGES_IN_MBYTE;
22191   logFilePtr.p->remainingWordsInMbyte = twnlRemWords;
22192   seizeLogpage(signal);
22193   if (logFilePtr.p->currentMbyte == 0) {
22194     jam();
22195     logFilePtr.p->lastPageWritten = 0;
22196     if (logFilePtr.p->fileNo == 0) {
22197       jam();
22198       releaseLogpage(signal);
22199       logPagePtr.i = logFilePtr.p->logPageZero;
22200       ptrCheckGuard(logPagePtr, clogPageFileSize, logPageRecord);
22201     }//if
22202   }//if
22203   initLogpage(signal);
22204   logFilePtr.p->currentLogpage = logPagePtr.i;
22205   if (logFilePtr.p->currentMbyte == 0) {
22206     jam();
22207 /* -------------------------------------------------- */
22208 /*       THIS IS A NEW FILE, WRITE THE FILE DESCRIPTOR*/
22209 /*       ALSO OPEN THE NEXT LOG FILE TO ENSURE THAT   */
22210 /*       THIS FILE IS OPEN WHEN ITS TURN COMES.       */
22211 /* -------------------------------------------------- */
22212     writeFileHeaderOpen(signal, ZNORMAL);
22213     openNextLogfile(signal);
22214     logFilePtr.p->fileChangeState = LogFileRecord::BOTH_WRITES_ONGOING;
22215   }//if
22216   if (logFilePtr.p->fileNo == logPartPtr.p->logTailFileNo)
22217   {
22218     if (logFilePtr.p->currentMbyte == logPartPtr.p->logTailMbyte)
22219     {
22220       jam();
22221 /* -------------------------------------------------- */
22222 /*       THE HEAD AND TAIL HAS MET. THIS SHOULD NEVER */
22223 /*       OCCUR. CAN HAPPEN IF THE LOCAL CHECKPOINTS   */
22224 /*       TAKE FAR TOO LONG TIME. SO TIMING PROBLEMS   */
22225 /*       CAN INVOKE THIS SYSTEM CRASH. HOWEVER ONLY   */
22226 /*       VERY SERIOUS TIMING PROBLEMS.                */
22227 /* -------------------------------------------------- */
22228       char buf[100];
22229       BaseString::snprintf(buf, sizeof(buf),
22230                            "Head/Tail met in REDO log, logpart: %u"
22231                            " file: %u mbyte: %u state: %u log-problem: %u",
22232                            logPartPtr.p->logPartNo,
22233                            logFilePtr.p->fileNo,
22234                            logFilePtr.p->currentMbyte,
22235                            logPartPtr.p->logPartState,
22236                            logPartPtr.p->m_log_problems);
22237 
22238 
22239       signal->theData[0] = 2398;
22240       execDUMP_STATE_ORD(signal);
22241       progError(__LINE__, NDBD_EXIT_NO_MORE_REDOLOG, buf);
22242       systemError(signal, __LINE__);
22243     }//if
22244   }//if
22245   if (logFilePtr.p->currentMbyte == (clogFileSize - 1)) {
22246     jam();
22247     twnlNextMbyte = 0;
22248     if (logFilePtr.p->fileChangeState != LogFileRecord::NOT_ONGOING)
22249     {
22250       jam();
22251       update_log_problem(signal, logPartPtr,
22252                          LogPartRecord::P_FILE_CHANGE_PROBLEM,
22253                          /* set */ true);
22254     }//if
22255     twnlNextFileNo = wnlNextLogFilePtr.p->fileNo;
22256   } else {
22257     jam();
22258     twnlNextMbyte = logFilePtr.p->currentMbyte + 1;
22259     twnlNextFileNo = logFilePtr.p->fileNo;
22260   }//if
22261 
22262   LogPosition head = { twnlNextFileNo, twnlNextMbyte };
22263   LogPosition tail = { logPartPtr.p->logTailFileNo, logPartPtr.p->logTailMbyte};
22264   Uint64 free_mb = free_log(head, tail, logPartPtr.p->noLogFiles, clogFileSize);
22265   if (free_mb <= c_free_mb_force_lcp_limit)
22266   {
22267     jam();
22268     force_lcp(signal);
22269   }
22270 
22271   if (free_mb <= c_free_mb_tail_problem_limit)
22272   {
22273     jam();
22274     update_log_problem(signal, logPartPtr, LogPartRecord::P_TAIL_PROBLEM, true);
22275   }
22276 
22277   if (ERROR_INSERTED(5058) &&
22278       (twnlNextMbyte + 3 >= clogFileSize) &&
22279       logFilePtr.p->fileNo != 0 &&
22280       logFilePtr.p->nextLogFile != logPartPtr.p->firstLogfile)
22281   {
22282     jam();
22283     srand((int)time(0));
22284     Uint32 wait = 3 + (rand() % 5);
22285 
22286     suspendFile(signal, logFilePtr, /* forever */ 0);
22287     suspendFile(signal, logPartPtr.p->firstLogfile, /* forever */ 0);
22288     signal->theData[0] = 9999;
22289     sendSignalWithDelay(CMVMI_REF, GSN_NDB_TAMPER, signal, wait * 1000, 1);
22290     CLEAR_ERROR_INSERT_VALUE;
22291   }
22292 
22293   if (ERROR_INSERTED(5059) &&
22294       twnlNextMbyte == 4 &&
22295       logFilePtr.p->fileNo != 0)
22296   {
22297     signal->theData[0] = 9999;
22298     sendSignal(CMVMI_REF, GSN_NDB_TAMPER, signal, 1, JBA);
22299   }
22300 
22301 }//Dblqh::writeNextLog()
22302 
22303 bool
validate_filter(Signal * signal)22304 Dblqh::validate_filter(Signal* signal)
22305 {
22306   Uint32 * start = signal->theData + 1;
22307   Uint32 * end = signal->theData + signal->getLength();
22308   if (start == end)
22309   {
22310     infoEvent("No filter specified, not listing...");
22311     if (!ERROR_INSERTED(4002))
22312       return false;
22313     else
22314       return true;
22315   }
22316 
22317   while(start < end)
22318   {
22319     switch(* start){
22320     case 0: // Table
22321     case 1: // API Node
22322     case 3: // TC Node
22323       start += 2;
22324       break;
22325     case 2: // Transid
22326       start += 3;
22327       break;
22328     default:
22329       infoEvent("Invalid filter op: 0x%x pos: %ld",
22330 		* start,
22331 		(long int)(start - (signal->theData + 1)));
22332       return false;
22333     }
22334   }
22335 
22336   if (start != end)
22337   {
22338     infoEvent("Invalid filter, unexpected end");
22339     return false;
22340   }
22341 
22342   return true;
22343 }
22344 
22345 bool
match_and_print(Signal * signal,Ptr<TcConnectionrec> tcRec)22346 Dblqh::match_and_print(Signal* signal, Ptr<TcConnectionrec> tcRec)
22347 {
22348   Uint32 len = signal->getLength();
22349   Uint32* start = signal->theData + 3;
22350   Uint32* end = signal->theData + len;
22351   while (start < end)
22352   {
22353     switch(* start){
22354     case 0:
22355       if (tcRec.p->tableref != * (start + 1))
22356 	return false;
22357       start += 2;
22358       break;
22359     case 1:
22360       if (refToNode(tcRec.p->applRef) != * (start + 1))
22361 	return false;
22362       start += 2;
22363       break;
22364     case 2:
22365       if (tcRec.p->transid[0] != * (start + 1) ||
22366 	  tcRec.p->transid[1] != * (start + 2))
22367 	return false;
22368       start += 3;
22369       break;
22370     case 3:
22371       if (refToNode(tcRec.p->tcBlockref) != * (start + 1))
22372 	return false;
22373       start += 2;
22374       break;
22375     default:
22376       ndbassert(false);
22377       return false;
22378     }
22379   }
22380 
22381   if (start != end)
22382   {
22383     ndbassert(false);
22384     return false;
22385   }
22386 
22387   /**
22388    * Do print
22389    */
22390   Uint32 *temp = signal->theData + 25;
22391   memcpy(temp, signal->theData, 4 * len);
22392 
22393   char state[20];
22394   const char* op = "<Unknown>";
22395   if (tcRec.p->tcScanRec != RNIL)
22396   {
22397     ScanRecordPtr sp;
22398     sp.i = tcRec.p->tcScanRec;
22399     c_scanRecordPool.getPtr(sp);
22400 
22401     if (sp.p->scanLockMode)
22402       op = "SCAN-EX";
22403     else if(sp.p->scanLockHold)
22404       op = "SCAN-SH";
22405     else
22406       op = "SCAN";
22407 
22408     switch(sp.p->scanState){
22409     case ScanRecord::WAIT_NEXT_SCAN:
22410       BaseString::snprintf(state, sizeof(state), "WaitNextScan");
22411       break;
22412     case ScanRecord::IN_QUEUE:
22413       BaseString::snprintf(state, sizeof(state), "InQueue");
22414       break;
22415     case ScanRecord::SCAN_FREE:
22416     case ScanRecord::WAIT_STORED_PROC_COPY:
22417     case ScanRecord::WAIT_STORED_PROC_SCAN:
22418     case ScanRecord::WAIT_NEXT_SCAN_COPY:
22419     case ScanRecord::WAIT_DELETE_STORED_PROC_ID_SCAN:
22420     case ScanRecord::WAIT_DELETE_STORED_PROC_ID_COPY:
22421     case ScanRecord::WAIT_ACC_COPY:
22422     case ScanRecord::WAIT_ACC_SCAN:
22423     case ScanRecord::WAIT_SCAN_NEXTREQ:
22424     case ScanRecord::WAIT_CLOSE_SCAN:
22425     case ScanRecord::WAIT_CLOSE_COPY:
22426     case ScanRecord::WAIT_RELEASE_LOCK:
22427     case ScanRecord::WAIT_TUPKEY_COPY:
22428     case ScanRecord::WAIT_LQHKEY_COPY:
22429       BaseString::snprintf(state, sizeof(state), "%u", sp.p->scanState);
22430     }
22431   }
22432   else
22433   {
22434     switch(tcRec.p->operation){
22435     case ZREAD:
22436       if (tcRec.p->lockType)
22437 	op = "READ-EX";
22438       else if(!tcRec.p->dirtyOp)
22439 	op = "READ-SH";
22440       else
22441 	op = "READ";
22442       break;
22443     case ZINSERT: op = "INSERT"; break;
22444     case ZUPDATE: op = "UPDATE"; break;
22445     case ZDELETE: op = "DELETE"; break;
22446     case ZWRITE: op = "WRITE"; break;
22447     case ZUNLOCK: op = "UNLOCK"; break;
22448     }
22449 
22450     switch(tcRec.p->transactionState){
22451     case TcConnectionrec::IDLE:
22452     case TcConnectionrec::WAIT_ACC:
22453       BaseString::snprintf(state, sizeof(state), "In lock queue");
22454       break;
22455     case TcConnectionrec::WAIT_TUPKEYINFO:
22456     case TcConnectionrec::WAIT_ATTR:
22457       BaseString::snprintf(state, sizeof(state), "WaitData");
22458       break;
22459     case TcConnectionrec::WAIT_TUP:
22460       BaseString::snprintf(state, sizeof(state), "Running");
22461       break;
22462     case TcConnectionrec::WAIT_TUP_COMMIT:
22463       BaseString::snprintf(state, sizeof(state), "Committing");
22464       break;
22465     case TcConnectionrec::PREPARED:
22466       BaseString::snprintf(state, sizeof(state), "Prepared");
22467       break;
22468     case TcConnectionrec::COMMITTED:
22469       BaseString::snprintf(state, sizeof(state), "Committed");
22470       break;
22471     case TcConnectionrec::STOPPED:
22472     case TcConnectionrec::LOG_QUEUED:
22473     case TcConnectionrec::LOG_COMMIT_WRITTEN_WAIT_SIGNAL:
22474     case TcConnectionrec::LOG_COMMIT_QUEUED_WAIT_SIGNAL:
22475     case TcConnectionrec::COMMIT_STOPPED:
22476     case TcConnectionrec::LOG_COMMIT_QUEUED:
22477     case TcConnectionrec::COMMIT_QUEUED:
22478     case TcConnectionrec::WAIT_ACC_ABORT:
22479     case TcConnectionrec::ABORT_QUEUED:
22480     case TcConnectionrec::ABORT_STOPPED:
22481     case TcConnectionrec::WAIT_AI_AFTER_ABORT:
22482     case TcConnectionrec::LOG_ABORT_QUEUED:
22483     case TcConnectionrec::WAIT_TUP_TO_ABORT:
22484     case TcConnectionrec::WAIT_SCAN_AI:
22485     case TcConnectionrec::SCAN_STATE_USED:
22486     case TcConnectionrec::SCAN_FIRST_STOPPED:
22487     case TcConnectionrec::SCAN_CHECK_STOPPED:
22488     case TcConnectionrec::SCAN_STOPPED:
22489     case TcConnectionrec::SCAN_RELEASE_STOPPED:
22490     case TcConnectionrec::SCAN_CLOSE_STOPPED:
22491     case TcConnectionrec::COPY_CLOSE_STOPPED:
22492     case TcConnectionrec::COPY_FIRST_STOPPED:
22493     case TcConnectionrec::COPY_STOPPED:
22494     case TcConnectionrec::SCAN_TUPKEY:
22495     case TcConnectionrec::COPY_TUPKEY:
22496     case TcConnectionrec::TC_NOT_CONNECTED:
22497     case TcConnectionrec::PREPARED_RECEIVED_COMMIT:
22498     case TcConnectionrec::LOG_COMMIT_WRITTEN:
22499       BaseString::snprintf(state, sizeof(state), "%u",
22500 			   tcRec.p->transactionState);
22501     }
22502   }
22503 
22504   char buf[100];
22505   BaseString::snprintf(buf, sizeof(buf),
22506 		       "OP[%u]: Tab: %d frag: %d TC: %u API: %d(0x%x)"
22507 		       "transid: H'%.8x H'%.8x op: %s state: %s",
22508 		       tcRec.i,
22509 		       tcRec.p->tableref,
22510 		       tcRec.p->fragmentid,
22511 		       refToNode(tcRec.p->tcBlockref),
22512 		       refToNode(tcRec.p->applRef),
22513 		       refToBlock(tcRec.p->applRef),
22514 		       tcRec.p->transid[0], tcRec.p->transid[1],
22515 		       op,
22516 		       state);
22517 
22518   if (!ERROR_INSERTED(4002))
22519     infoEvent("%s", buf);
22520   else
22521     ndbout_c("%s", buf);
22522 
22523   memcpy(signal->theData, temp, 4*len);
22524   return true;
22525 }
22526 
22527 void
execDUMP_STATE_ORD(Signal * signal)22528 Dblqh::execDUMP_STATE_ORD(Signal* signal)
22529 {
22530   jamEntry();
22531   DumpStateOrd * const dumpState = (DumpStateOrd *)&signal->theData[0];
22532   Uint32 arg= dumpState->args[0];
22533   if(dumpState->args[0] == DumpStateOrd::CommitAckMarkersSize){
22534     infoEvent("LQH: m_commitAckMarkerPool: %d free size: %d",
22535 	      m_commitAckMarkerPool.getNoOfFree(),
22536 	      m_commitAckMarkerPool.getSize());
22537   }
22538   if(dumpState->args[0] == DumpStateOrd::CommitAckMarkersDump){
22539     infoEvent("LQH: m_commitAckMarkerPool: %d free size: %d",
22540 	      m_commitAckMarkerPool.getNoOfFree(),
22541 	      m_commitAckMarkerPool.getSize());
22542 
22543     CommitAckMarkerIterator iter;
22544     for(m_commitAckMarkerHash.first(iter); iter.curr.i != RNIL;
22545 	m_commitAckMarkerHash.next(iter)){
22546       infoEvent("CommitAckMarker: i = %d (H'%.8x, H'%.8x)"
22547 		" ApiRef: 0x%x apiOprec: 0x%x TcNodeId: %d, ref_count: %u",
22548 		iter.curr.i,
22549 		iter.curr.p->transid1,
22550 		iter.curr.p->transid2,
22551 		iter.curr.p->apiRef,
22552 		iter.curr.p->apiOprec,
22553 		iter.curr.p->tcNodeId,
22554                 iter.curr.p->reference_count);
22555     }
22556   }
22557 
22558   // Dump info about number of log pages
22559   if(dumpState->args[0] == DumpStateOrd::LqhDumpNoLogPages){
22560     infoEvent("LQH: Log pages : %d Free: %d",
22561 	      clogPageFileSize,
22562 	      cnoOfLogPages);
22563   }
22564 
22565   // Dump all defined tables that LQH knowns about
22566   if(dumpState->args[0] == DumpStateOrd::LqhDumpAllDefinedTabs){
22567     for(Uint32 i = 0; i<ctabrecFileSize; i++){
22568       TablerecPtr tabPtr;
22569       tabPtr.i = i;
22570       ptrAss(tabPtr, tablerec);
22571       if(tabPtr.p->tableStatus != Tablerec::NOT_DEFINED){
22572 	infoEvent("Table %d Status: %d Usage: [ r: %u w: %u ]",
22573 		  i, tabPtr.p->tableStatus,
22574                   tabPtr.p->usageCountR, tabPtr.p->usageCountW);
22575 
22576 	for (Uint32 j = 0; j<MAX_FRAG_PER_NODE; j++)
22577 	{
22578 	  FragrecordPtr fragPtr;
22579 	  if ((fragPtr.i = tabPtr.p->fragrec[j]) != RNIL)
22580 	  {
22581 	    c_fragment_pool.getPtr(fragPtr);
22582 	    infoEvent("  frag: %d distKey: %u",
22583 		      tabPtr.p->fragid[j],
22584 		      fragPtr.p->fragDistributionKey);
22585 	  }
22586 	}
22587       }
22588     }
22589     return;
22590   }
22591 
22592   // Dump all ScanRecords
22593   if (dumpState->args[0] == DumpStateOrd::LqhDumpAllScanRec){
22594     Uint32 recordNo = 0;
22595     if (signal->length() == 1)
22596       infoEvent("LQH: Dump all ScanRecords - size: %d",
22597 		cscanrecFileSize);
22598     else if (signal->length() == 2)
22599       recordNo = dumpState->args[1];
22600     else
22601       return;
22602 
22603     dumpState->args[0] = DumpStateOrd::LqhDumpOneScanRec;
22604     dumpState->args[1] = recordNo;
22605     execDUMP_STATE_ORD(signal);
22606 
22607     if (recordNo < cscanrecFileSize-1){
22608       dumpState->args[0] = DumpStateOrd::LqhDumpAllScanRec;
22609       dumpState->args[1] = recordNo+1;
22610       sendSignal(reference(), GSN_DUMP_STATE_ORD, signal, 2, JBB);
22611     }
22612     return;
22613   }
22614 
22615   // Dump all active ScanRecords
22616   if (dumpState->args[0] == DumpStateOrd::LqhDumpAllActiveScanRec){
22617     Uint32 recordNo = 0;
22618     if (signal->length() == 1)
22619       infoEvent("LQH: Dump active ScanRecord - size: %d",
22620 		cscanrecFileSize);
22621     else if (signal->length() == 2)
22622       recordNo = dumpState->args[1];
22623     else
22624       return;
22625 
22626     ScanRecordPtr sp;
22627     sp.i = recordNo;
22628     c_scanRecordPool.getPtr(sp);
22629     if (sp.p->scanState != ScanRecord::SCAN_FREE){
22630       dumpState->args[0] = DumpStateOrd::LqhDumpOneScanRec;
22631       dumpState->args[1] = recordNo;
22632       execDUMP_STATE_ORD(signal);
22633     }
22634 
22635     if (recordNo < cscanrecFileSize-1){
22636       dumpState->args[0] = DumpStateOrd::LqhDumpAllActiveScanRec;
22637       dumpState->args[1] = recordNo+1;
22638       sendSignal(reference(), GSN_DUMP_STATE_ORD, signal, 2, JBB);
22639     }
22640     return;
22641   }
22642 
22643   if(dumpState->args[0] == DumpStateOrd::LqhDumpOneScanRec){
22644     Uint32 recordNo = RNIL;
22645     if (signal->length() == 2)
22646       recordNo = dumpState->args[1];
22647     else
22648       return;
22649 
22650     if (recordNo >= cscanrecFileSize)
22651       return;
22652 
22653     ScanRecordPtr sp;
22654     sp.i = recordNo;
22655     c_scanRecordPool.getPtr(sp);
22656     infoEvent("Dblqh::ScanRecord[%d]: state=%d, type=%d, "
22657 	      "complStatus=%d, scanNodeId=%d",
22658 	      sp.i,
22659 	      sp.p->scanState,
22660 	      sp.p->scanType,
22661 	      sp.p->scanCompletedStatus,
22662 	      sp.p->scanNodeId);
22663     infoEvent(" apiBref=0x%x, scanAccPtr=%d",
22664 	      sp.p->scanApiBlockref,
22665 	      sp.p->scanAccPtr);
22666     infoEvent(" copyptr=%d, ailen=%d, complOps=%d, concurrOps=%d",
22667 	      sp.p->copyPtr,
22668 	      sp.p->scanAiLength,
22669 	      sp.p->m_curr_batch_size_rows,
22670 	      sp.p->m_max_batch_size_rows);
22671     infoEvent(" errCnt=%d, schV=%d",
22672 	      sp.p->scanErrorCounter,
22673 	      sp.p->scanSchemaVersion);
22674     infoEvent(" stpid=%d, flag=%d, lhold=%d, lmode=%d, num=%d",
22675 	      sp.p->scanStoredProcId,
22676 	      sp.p->scanFlag,
22677 	      sp.p->scanLockHold,
22678 	      sp.p->scanLockMode,
22679 	      sp.p->scanNumber);
22680     infoEvent(" relCount=%d, TCwait=%d, TCRec=%d, KIflag=%d",
22681 	      sp.p->scanReleaseCounter,
22682 	      sp.p->scanTcWaiting,
22683 	      sp.p->scanTcrec,
22684 	      sp.p->scanKeyinfoFlag);
22685     return;
22686   }
22687   if(dumpState->args[0] == DumpStateOrd::LqhDumpLcpState){
22688 
22689     infoEvent("== LQH LCP STATE ==");
22690     infoEvent(" clcpCompletedState=%d, c_lcpId=%d, cnoOfFragsCheckpointed=%d",
22691 	      clcpCompletedState,
22692 	      c_lcpId,
22693 	      cnoOfFragsCheckpointed);
22694 
22695     LcpRecordPtr TlcpPtr;
22696     // Print information about the current local checkpoint
22697     TlcpPtr.i = 0;
22698     ptrAss(TlcpPtr, lcpRecord);
22699     infoEvent(" lcpState=%d lastFragmentFlag=%d",
22700 	      TlcpPtr.p->lcpState, TlcpPtr.p->lastFragmentFlag);
22701     infoEvent("currentFragment.fragPtrI=%d",
22702 	      TlcpPtr.p->currentFragment.fragPtrI);
22703     infoEvent("currentFragment.lcpFragOrd.tableId=%d",
22704 	      TlcpPtr.p->currentFragment.lcpFragOrd.tableId);
22705     infoEvent(" lcpQueued=%d reportEmpty=%d",
22706 	      TlcpPtr.p->lcpQueued,
22707 	      TlcpPtr.p->reportEmpty);
22708     char buf[8*_NDB_NODE_BITMASK_SIZE+1];
22709     infoEvent(" m_EMPTY_LCP_REQ=%s",
22710 	      TlcpPtr.p->m_EMPTY_LCP_REQ.getText(buf));
22711 
22712     return;
22713   }
22714   if (dumpState->args[0] == DumpStateOrd::LQHLogFileInitStatus){
22715      reportStatus(signal);
22716      return;
22717   }
22718 
22719 #ifdef ERROR_INSERT
22720 #ifdef NDB_DEBUG_FULL
22721   if(dumpState->args[0] == DumpStateOrd::LCPContinue){
22722     switch(cerrorInsert){
22723     case 5904:
22724       CLEAR_ERROR_INSERT_VALUE;
22725       g_trace_lcp.restore(*globalData.getBlock(BACKUP), signal);
22726       return;
22727     default:
22728       return;
22729     }
22730   }
22731 #endif
22732 #endif
22733 
22734   if(arg == 2304 || arg == 2305)
22735   {
22736     jam();
22737     Uint32 i;
22738     void * logPartPtr = 0;
22739     (void)logPartPtr;
22740     GcpRecordPtr gcp; gcp.i = RNIL;
22741     for(i = 0; i < clogPartFileSize; i++)
22742     {
22743       Ptr<LogPartRecord> lp;
22744       lp.i = i;
22745       ptrCheckGuard(lp, clogPartFileSize, logPartRecord);
22746       ndbout_c("LP %d blockInstance: %d partNo: %d state: %d WW_Gci: %d gcprec: %d flq: %u %u currfile: %d tailFileNo: %d logTailMbyte: %d cnoOfLogPages: %u problems: 0x%x",
22747                i,
22748                instance(),
22749                lp.p->logPartNo,
22750 	       lp.p->logPartState,
22751 	       lp.p->waitWriteGciLog,
22752 	       lp.p->gcprec,
22753 	       lp.p->m_log_prepare_queue.firstElement,
22754 	       lp.p->m_log_complete_queue.firstElement,
22755 	       lp.p->currentLogfile,
22756 	       lp.p->logTailFileNo,
22757 	       lp.p->logTailMbyte,
22758                cnoOfLogPages,
22759                lp.p->m_log_problems);
22760 
22761       if(gcp.i == RNIL && lp.p->gcprec != RNIL)
22762 	gcp.i = lp.p->gcprec;
22763 
22764       LogFileRecordPtr logFilePtr;
22765       Uint32 first= logFilePtr.i= lp.p->firstLogfile;
22766       do
22767       {
22768 	ptrCheckGuard(logFilePtr, clogFileFileSize, logFileRecord);
22769 	ndbout_c("  file %d(%d)  FileChangeState: %d  logFileStatus: %d  currentMbyte: %d  currentFilepage %d",
22770 		 logFilePtr.p->fileNo,
22771 		 logFilePtr.i,
22772 		 logFilePtr.p->fileChangeState,
22773 		 logFilePtr.p->logFileStatus,
22774 		 logFilePtr.p->currentMbyte,
22775 		 logFilePtr.p->currentFilepage);
22776 	logFilePtr.i = logFilePtr.p->nextLogFile;
22777       } while(logFilePtr.i != first);
22778     }
22779 
22780     if(gcp.i != RNIL)
22781     {
22782       ptrCheckGuard(gcp, cgcprecFileSize, gcpRecord);
22783       for(i = 0; i<4; i++)
22784       {
22785 	ndbout_c("  GCP %d file: %d state: %d sync: %d page: %d word: %d",
22786 		 i, gcp.p->gcpFilePtr[i], gcp.p->gcpLogPartState[i],
22787 		 gcp.p->gcpSyncReady[i],
22788 		 gcp.p->gcpPageNo[i],
22789 		 gcp.p->gcpWordNo[i]);
22790       }
22791     }
22792 
22793     if(arg== 2305)
22794     {
22795       progError(__LINE__, NDBD_EXIT_SYSTEM_ERROR,
22796 		"Please report this as a bug. "
22797 		"Provide as much info as possible, expecially all the "
22798 		"ndb_*_out.log files, Thanks. "
22799 		"Shutting down node due to failed handling of GCP_SAVEREQ");
22800 
22801     }
22802   }
22803 
22804   if (dumpState->args[0] == DumpStateOrd::LqhErrorInsert5042 && (signal->getLength() >= 2))
22805   {
22806     c_error_insert_table_id = dumpState->args[1];
22807     if (signal->getLength() == 2)
22808     {
22809       SET_ERROR_INSERT_VALUE(5042);
22810     }
22811     else
22812     {
22813       SET_ERROR_INSERT_VALUE(dumpState->args[2]);
22814     }
22815   }
22816 
22817   TcConnectionrec *regTcConnectionrec = tcConnectionrec;
22818   Uint32 ttcConnectrecFileSize = ctcConnectrecFileSize;
22819   if(arg == 2306)
22820   {
22821     for(Uint32 i = 0; i<1024; i++)
22822     {
22823       TcConnectionrecPtr tcRec;
22824       tcRec.i = ctransidHash[i];
22825       while(tcRec.i != RNIL)
22826       {
22827 	ptrCheckGuard(tcRec, ttcConnectrecFileSize, regTcConnectionrec);
22828 	ndbout << "TcConnectionrec " << tcRec.i;
22829 	signal->theData[0] = 2307;
22830 	signal->theData[1] = tcRec.i;
22831 	execDUMP_STATE_ORD(signal);
22832 	tcRec.i = tcRec.p->nextHashRec;
22833       }
22834     }
22835   }
22836 
22837   if(arg == 2307 || arg == 2308)
22838   {
22839     TcConnectionrecPtr tcRec;
22840     tcRec.i = signal->theData[1];
22841     ptrCheckGuard(tcRec, ttcConnectrecFileSize, regTcConnectionrec);
22842 
22843     ndbout << " transactionState = " << tcRec.p->transactionState<<endl;
22844     ndbout << " operation = " << tcRec.p->operation<<endl;
22845     ndbout << " tcNodeFailrec = " << tcRec.p->tcNodeFailrec
22846 	   << " seqNoReplica = " << tcRec.p->seqNoReplica
22847 	   << endl;
22848     ndbout << " replicaType = " << tcRec.p->replicaType
22849 	   << " reclenAiLqhkey = " << tcRec.p->reclenAiLqhkey
22850 	   << " opExec = " << tcRec.p->opExec
22851 	   << endl;
22852     ndbout << " opSimple = " << tcRec.p->opSimple
22853 	   << " nextSeqNoReplica = " << tcRec.p->nextSeqNoReplica
22854 	   << " lockType = " << tcRec.p->lockType
22855 	   << endl;
22856     ndbout << " lastReplicaNo = " << tcRec.p->lastReplicaNo
22857 	   << " indTakeOver = " << tcRec.p->indTakeOver
22858 	   << " dirtyOp = " << tcRec.p->dirtyOp
22859 	   << endl;
22860     ndbout << " activeCreat = " << tcRec.p->activeCreat
22861 	   << " tcBlockref = " << hex << tcRec.p->tcBlockref
22862 	   << " reqBlockref = " << hex << tcRec.p->reqBlockref
22863 	   << " primKeyLen = " << tcRec.p->primKeyLen
22864 	   << " nrcopyflag = " << LqhKeyReq::getNrCopyFlag(tcRec.p->reqinfo)
22865 	   << endl;
22866     ndbout << " nextReplica = " << tcRec.p->nextReplica
22867 	   << " tcBlockref = " << hex << tcRec.p->tcBlockref
22868 	   << " reqBlockref = " << hex << tcRec.p->reqBlockref
22869 	   << " primKeyLen = " << tcRec.p->primKeyLen
22870 	   << endl;
22871     ndbout << " logStopPageNo = " << tcRec.p->logStopPageNo
22872 	   << " logStartPageNo = " << tcRec.p->logStartPageNo
22873 	   << " logStartPageIndex = " << tcRec.p->logStartPageIndex
22874 	   << endl;
22875     ndbout << " errorCode = " << tcRec.p->errorCode
22876 	   << " clientBlockref = " << hex << tcRec.p->clientBlockref
22877 	   << " applRef = " << hex << tcRec.p->applRef
22878 	   << " totSendlenAi = " << tcRec.p->totSendlenAi
22879 	   << endl;
22880     ndbout << " totReclenAi = " << tcRec.p->totReclenAi
22881 	   << " tcScanRec = " << tcRec.p->tcScanRec
22882 	   << " tcScanInfo = " << tcRec.p->tcScanInfo
22883 	   << " tcOprec = " << hex << tcRec.p->tcOprec
22884 	   << endl;
22885     ndbout << " tableref = " << tcRec.p->tableref
22886 	   << " simpleTcConnect = " << tcRec.p->simpleTcConnect
22887 	   << " storedProcId = " << tcRec.p->storedProcId
22888 	   << " schemaVersion = " << tcRec.p->schemaVersion
22889 	   << endl;
22890     ndbout << " reqinfo = " << tcRec.p->reqinfo
22891 	   << " reqRef = " << tcRec.p->reqRef
22892 	   << " readlenAi = " << tcRec.p->readlenAi
22893 	   << " prevTc = " << tcRec.p->prevTc
22894 	   << endl;
22895     ndbout << " prevLogTcrec = " << tcRec.p->prevLogTcrec
22896 	   << " prevHashRec = " << tcRec.p->prevHashRec
22897 	   << " nodeAfterNext0 = " << tcRec.p->nodeAfterNext[0]
22898 	   << " nodeAfterNext1 = " << tcRec.p->nodeAfterNext[1]
22899 	   << endl;
22900     ndbout << " nextTcConnectrec = " << tcRec.p->nextTcConnectrec
22901 	   << " nextTc = " << tcRec.p->nextTc
22902 	   << " nextTcLogQueue = " << tcRec.p->nextTcLogQueue
22903 	   << " nextLogTcrec = " << tcRec.p->nextLogTcrec
22904 	   << endl;
22905     ndbout << " nextHashRec = " << tcRec.p->nextHashRec
22906 	   << " logWriteState = " << tcRec.p->logWriteState
22907 	   << " logStartFileNo = " << tcRec.p->logStartFileNo
22908 	   << " listState = " << tcRec.p->listState
22909 	   << endl;
22910     ndbout << " gci_hi = " << tcRec.p->gci_hi
22911            << " gci_lo = " << tcRec.p->gci_lo
22912 	   << " fragmentptr = " << tcRec.p->fragmentptr
22913 	   << " fragmentid = " << tcRec.p->fragmentid
22914 	   << endl;
22915     ndbout << " hashValue = " << tcRec.p->hashValue
22916            << " currTupAiLen = " << tcRec.p->currTupAiLen
22917 	   << " currReclenAi = " << tcRec.p->currReclenAi
22918 	   << endl;
22919     ndbout << " tcTimer = " << tcRec.p->tcTimer
22920 	   << " clientConnectrec = " << tcRec.p->clientConnectrec
22921 	   << " applOprec = " << hex << tcRec.p->applOprec
22922 	   << " abortState = " << tcRec.p->abortState
22923 	   << endl;
22924     ndbout << " transid0 = " << hex << tcRec.p->transid[0]
22925 	   << " transid1 = " << hex << tcRec.p->transid[1]
22926 	   << " key[0] = " << getKeyInfoWordOrZero(tcRec.p, 0)
22927 	   << " key[1] = " << getKeyInfoWordOrZero(tcRec.p, 1)
22928 	   << endl;
22929     ndbout << " key[2] = " << getKeyInfoWordOrZero(tcRec.p, 2)
22930 	   << " key[3] = " << getKeyInfoWordOrZero(tcRec.p, 3)
22931 	   << " m_nr_delete.m_cnt = " << tcRec.p->m_nr_delete.m_cnt
22932 	   << endl;
22933     switch (tcRec.p->transactionState) {
22934 
22935     case TcConnectionrec::SCAN_STATE_USED:
22936       if (tcRec.p->tcScanRec < cscanrecFileSize){
22937 	ScanRecordPtr TscanPtr;
22938 	c_scanRecordPool.getPtr(TscanPtr, tcRec.p->tcScanRec);
22939 	ndbout << " scanState = " << TscanPtr.p->scanState << endl;
22940 	//TscanPtr.p->scanLocalref[2];
22941 	ndbout << " copyPtr="<<TscanPtr.p->copyPtr
22942 	       << " scanAccPtr="<<TscanPtr.p->scanAccPtr
22943 	       << " scanAiLength="<<TscanPtr.p->scanAiLength
22944 	       << endl;
22945 	ndbout << " m_curr_batch_size_rows="<<
22946 	  TscanPtr.p->m_curr_batch_size_rows
22947 	       << " m_max_batch_size_rows="<<
22948 	  TscanPtr.p->m_max_batch_size_rows
22949 	       << " scanErrorCounter="<<TscanPtr.p->scanErrorCounter
22950 	       << endl;
22951 	ndbout << " scanSchemaVersion="<<TscanPtr.p->scanSchemaVersion
22952 	       << "  scanStoredProcId="<<TscanPtr.p->scanStoredProcId
22953 	       << "  scanTcrec="<<TscanPtr.p->scanTcrec
22954 	       << endl;
22955 	ndbout << "  scanType="<<TscanPtr.p->scanType
22956 	       << "  scanApiBlockref="<<TscanPtr.p->scanApiBlockref
22957 	       << "  scanNodeId="<<TscanPtr.p->scanNodeId
22958 	       << "  scanCompletedStatus="<<TscanPtr.p->scanCompletedStatus
22959 	       << endl;
22960 	ndbout << "  scanFlag="<<TscanPtr.p->scanFlag
22961 	       << "  scanLockHold="<<TscanPtr.p->scanLockHold
22962 	       << "  scanLockMode="<<TscanPtr.p->scanLockMode
22963 	       << "  scanNumber="<<TscanPtr.p->scanNumber
22964 	       << endl;
22965 	ndbout << "  scanReleaseCounter="<<TscanPtr.p->scanReleaseCounter
22966 	       << "  scanTcWaiting="<<TscanPtr.p->scanTcWaiting
22967 	       << "  scanKeyinfoFlag="<<TscanPtr.p->scanKeyinfoFlag
22968 	       << endl;
22969       } else{
22970 	ndbout << "No connected scan record found" << endl;
22971       }
22972       break;
22973     default:
22974       break;
22975     }
22976     ndbrequire(arg != 2308);
22977   }
22978 
22979 #ifdef NDBD_TRACENR
22980   if (arg == 5712 || arg == 5713)
22981   {
22982     if (arg == 5712)
22983     {
22984       traceopout = &ndbout;
22985     }
22986     else if (arg == 5713)
22987     {
22988       traceopout = tracenrout;
22989     }
22990     SET_ERROR_INSERT_VALUE(arg);
22991   }
22992 #endif
22993 
22994   if (arg == 2350)
22995   {
22996     jam();
22997     Uint32 len = signal->getLength() - 1;
22998     if (len + 3 > 25)
22999     {
23000       jam();
23001       infoEvent("Too long filter");
23002       return;
23003     }
23004     if (validate_filter(signal))
23005     {
23006       jam();
23007       memmove(signal->theData + 3, signal->theData + 1, 4 * len);
23008       signal->theData[0] = 2351;
23009       signal->theData[1] = 0;    // Bucket
23010       signal->theData[2] = RNIL; // Record
23011       sendSignal(reference(), GSN_DUMP_STATE_ORD, signal, len + 3, JBB);
23012 
23013       infoEvent("Starting dump of operations");
23014     }
23015     return;
23016   }
23017 
23018   if (arg == 2351)
23019   {
23020     jam();
23021     Uint32 bucket = signal->theData[1];
23022     Uint32 record = signal->theData[2];
23023     Uint32 len = signal->getLength();
23024     TcConnectionrecPtr tcRec;
23025     if (record != RNIL)
23026     {
23027       jam();
23028       /**
23029        * Check that record is still in use...
23030        */
23031       tcRec.i = record;
23032       ptrCheckGuard(tcRec, ttcConnectrecFileSize, regTcConnectionrec);
23033 
23034       Uint32 hashIndex = (tcRec.p->transid[0] ^ tcRec.p->tcOprec) & 1023;
23035       if (hashIndex != bucket)
23036       {
23037 	jam();
23038 	record = RNIL;
23039       }
23040       else
23041       {
23042 	jam();
23043 	if (tcRec.p->nextHashRec == RNIL &&
23044 	    tcRec.p->prevHashRec == RNIL &&
23045 	    ctransidHash[hashIndex] != record)
23046 	{
23047 	  jam();
23048 	  record = RNIL;
23049 	}
23050       }
23051 
23052       if (record == RNIL)
23053       {
23054 	jam();
23055 	signal->theData[2] = RNIL;
23056 	sendSignal(reference(), GSN_DUMP_STATE_ORD, signal,
23057 		   signal->getLength(), JBB);
23058 	return;
23059       }
23060     }
23061     else if ((record = ctransidHash[bucket]) == RNIL)
23062     {
23063       jam();
23064       bucket++;
23065       if (bucket < 1024)
23066       {
23067 	jam();
23068 	signal->theData[1] = bucket;
23069 	signal->theData[2] = RNIL;
23070 	sendSignal(reference(), GSN_DUMP_STATE_ORD, signal,
23071 		   signal->getLength(), JBB);
23072       }
23073       else
23074       {
23075 	jam();
23076         infoEvent("End of operation dump");
23077         if (ERROR_INSERTED(4002))
23078         {
23079           ndbrequire(false);
23080         }
23081       }
23082 
23083       return;
23084     }
23085     else
23086     {
23087       jam();
23088       tcRec.i = record;
23089       ptrCheckGuard(tcRec, ttcConnectrecFileSize, regTcConnectionrec);
23090     }
23091 
23092     for (Uint32 i = 0; i<32; i++)
23093     {
23094       jam();
23095       bool print = match_and_print(signal, tcRec);
23096 
23097       tcRec.i = tcRec.p->nextHashRec;
23098       if (tcRec.i == RNIL || print)
23099       {
23100 	jam();
23101 	break;
23102       }
23103 
23104       ptrCheckGuard(tcRec, ttcConnectrecFileSize, regTcConnectionrec);
23105     }
23106 
23107     if (tcRec.i == RNIL)
23108     {
23109       jam();
23110       bucket++;
23111       if (bucket < 1024)
23112       {
23113 	jam();
23114 	signal->theData[1] = bucket;
23115 	signal->theData[2] = RNIL;
23116 	sendSignal(reference(), GSN_DUMP_STATE_ORD, signal, len, JBB);
23117       }
23118       else
23119       {
23120 	jam();
23121         infoEvent("End of operation dump");
23122         if (ERROR_INSERTED(4002))
23123         {
23124           ndbrequire(false);
23125         }
23126       }
23127 
23128       return;
23129     }
23130     else
23131     {
23132       jam();
23133       signal->theData[2] = tcRec.i;
23134       sendSignalWithDelay(reference(), GSN_DUMP_STATE_ORD, signal, 200, len);
23135       return;
23136     }
23137   }
23138 
23139   if (arg == 2352 && signal->getLength() == 2)
23140   {
23141     jam();
23142     Uint32 opNo = signal->theData[1];
23143     TcConnectionrecPtr tcRec;
23144     if (opNo < ttcConnectrecFileSize)
23145     {
23146       jam();
23147       tcRec.i = opNo;
23148       ptrCheckGuard(tcRec, ttcConnectrecFileSize, regTcConnectionrec);
23149 
23150       BaseString key;
23151       if (tcRec.p->keyInfoIVal != RNIL)
23152       {
23153         jam();
23154         SectionReader keyInfoReader(tcRec.p->keyInfoIVal,
23155                                     g_sectionSegmentPool);
23156 
23157         Uint32 keyWord;
23158         while (keyInfoReader.getWord(&keyWord))
23159           key.appfmt("0x%x ", keyWord);
23160       }
23161 
23162       char buf[100];
23163       BaseString::snprintf(buf, sizeof(buf),
23164 			   "OP[%u]: transid: 0x%x 0x%x key: %s",
23165 			   tcRec.i,
23166 			   tcRec.p->transid[0], tcRec.p->transid[1], key.c_str());
23167       infoEvent("%s", buf);
23168     }
23169   }
23170 
23171   if (arg == DumpStateOrd::SchemaResourceSnapshot)
23172   {
23173     RSS_AP_SNAPSHOT_SAVE(c_fragment_pool);
23174     return;
23175   }
23176 
23177   if (arg == DumpStateOrd::SchemaResourceCheckLeak)
23178   {
23179     RSS_AP_SNAPSHOT_CHECK(c_fragment_pool);
23180     return;
23181   }
23182 
23183   if (arg == 4002)
23184   {
23185     bool ops = false;
23186     for (Uint32 i = 0; i<1024; i++)
23187     {
23188       if (ctransidHash[i] != RNIL)
23189       {
23190         jam();
23191         ops = true;
23192         break;
23193       }
23194     }
23195 
23196     bool markers = m_commitAckMarkerPool.getNoOfFree() !=
23197       m_commitAckMarkerPool.getSize();
23198     if (unlikely(ops || markers))
23199     {
23200 
23201       if (markers)
23202       {
23203         ndbout_c("LQH: m_commitAckMarkerPool: %d free size: %d",
23204                  m_commitAckMarkerPool.getNoOfFree(),
23205                  m_commitAckMarkerPool.getSize());
23206 
23207         CommitAckMarkerIterator iter;
23208         for(m_commitAckMarkerHash.first(iter); iter.curr.i != RNIL;
23209             m_commitAckMarkerHash.next(iter))
23210         {
23211           ndbout_c("CommitAckMarker: i = %d (H'%.8x, H'%.8x)"
23212                    " ApiRef: 0x%x apiOprec: 0x%x TcNodeId: %d ref_count: %u",
23213                    iter.curr.i,
23214                    iter.curr.p->transid1,
23215                    iter.curr.p->transid2,
23216                    iter.curr.p->apiRef,
23217                    iter.curr.p->apiOprec,
23218                    iter.curr.p->tcNodeId,
23219                    iter.curr.p->reference_count);
23220         }
23221       }
23222       SET_ERROR_INSERT_VALUE(4002);
23223       signal->theData[0] = 2350;
23224       EXECUTE_DIRECT(DBLQH, GSN_DUMP_STATE_ORD, signal, 1);
23225     }
23226   }
23227 
23228   if(arg == 2399)
23229   {
23230     jam();
23231 
23232     if (cstartRecReq < SRR_REDO_COMPLETE)
23233     {
23234       jam();
23235       return;
23236     }
23237 
23238     for(Uint32 i = 0; i<4; i++)
23239     {
23240       logPartPtr.i = i;
23241       ptrCheckGuard(logPartPtr, clogPartFileSize, logPartRecord);
23242       LogFileRecordPtr logFile;
23243       logFile.i = logPartPtr.p->currentLogfile;
23244       ptrCheckGuard(logFile, clogFileFileSize, logFileRecord);
23245 
23246       LogPosition head = { logFile.p->fileNo, logFile.p->currentMbyte };
23247       LogPosition tail = { logPartPtr.p->logTailFileNo,
23248                            logPartPtr.p->logTailMbyte};
23249       Uint64 mb = free_log(head, tail, logPartPtr.p->noLogFiles, clogFileSize);
23250       Uint64 total = logPartPtr.p->noLogFiles * Uint64(clogFileSize);
23251       signal->theData[0] = NDB_LE_RedoStatus;
23252       signal->theData[1] = i;
23253       signal->theData[2] = head.m_file_no;
23254       signal->theData[3] = head.m_mbyte;
23255       signal->theData[4] = tail.m_file_no;
23256       signal->theData[5] = tail.m_mbyte;
23257       signal->theData[6] = Uint32(total >> 32);
23258       signal->theData[7] = Uint32(total);
23259       signal->theData[8] = Uint32(mb >> 32);
23260       signal->theData[9] = Uint32(mb);
23261       sendSignal(CMVMI_REF, GSN_EVENT_REP, signal, 10, JBB);
23262     }
23263   }
23264 
23265   if(arg == 2398)
23266   {
23267     jam();
23268 
23269     if (cstartRecReq < SRR_REDO_COMPLETE)
23270     {
23271       jam();
23272       return;
23273     }
23274 
23275     for(Uint32 i = 0; i<clogPartFileSize; i++)
23276     {
23277       logPartPtr.i = i;
23278       ptrCheckGuard(logPartPtr, clogPartFileSize, logPartRecord);
23279       LogFileRecordPtr logFile;
23280       logFile.i = logPartPtr.p->currentLogfile;
23281       ptrCheckGuard(logFile, clogFileFileSize, logFileRecord);
23282 
23283       LogPosition head = { logFile.p->fileNo, logFile.p->currentMbyte };
23284       LogPosition tail = { logPartPtr.p->logTailFileNo,
23285                            logPartPtr.p->logTailMbyte};
23286       Uint64 mb = free_log(head, tail, logPartPtr.p->noLogFiles, clogFileSize);
23287       Uint64 total = logPartPtr.p->noLogFiles * Uint64(clogFileSize);
23288       ndbout_c("REDO part: %u HEAD: file: %u mbyte: %u TAIL: file: %u mbyte: %u total: %llu free: %llu (mb)",
23289                logPartPtr.p->logPartNo,
23290                head.m_file_no, head.m_mbyte,
23291                tail.m_file_no, tail.m_mbyte,
23292                total, mb);
23293     }
23294   }
23295 
23296 }//Dblqh::execDUMP_STATE_ORD()
23297 
23298 
execDBINFO_SCANREQ(Signal * signal)23299 void Dblqh::execDBINFO_SCANREQ(Signal *signal)
23300 {
23301   DbinfoScanReq req= *(DbinfoScanReq*)signal->theData;
23302   const Ndbinfo::ScanCursor* cursor =
23303     CAST_CONSTPTR(Ndbinfo::ScanCursor, DbinfoScan::getCursorPtr(&req));
23304   Ndbinfo::Ratelimit rl;
23305 
23306   jamEntry();
23307 
23308   switch(req.tableId){
23309   case Ndbinfo::LOGSPACES_TABLEID:
23310   {
23311     Uint32 logpart = cursor->data[0];
23312     while(logpart < clogPartFileSize)
23313     {
23314       jam();
23315 
23316       logPartPtr.i = logpart;
23317       ptrCheckGuard(logPartPtr, clogPartFileSize, logPartRecord);
23318 
23319       LogFileRecordPtr logFile;
23320       logFile.i = logPartPtr.p->currentLogfile;
23321       ptrCheckGuard(logFile, clogFileFileSize, logFileRecord);
23322 
23323       LogPosition head = { logFile.p->fileNo, logFile.p->currentMbyte };
23324       LogPosition tail = { logPartPtr.p->logTailFileNo,
23325                            logPartPtr.p->logTailMbyte};
23326       Uint64 mb = free_log(head, tail, logPartPtr.p->noLogFiles, clogFileSize);
23327       Uint64 total = logPartPtr.p->noLogFiles * Uint64(clogFileSize);
23328       Uint64 high = 0; // TODO
23329 
23330       Ndbinfo::Row row(signal, req);
23331       row.write_uint32(getOwnNodeId());
23332       row.write_uint32(0);              // log type, 0 = REDO
23333       row.write_uint32(0);              // log id, always 0 in LQH
23334       row.write_uint32(logpart);        // log part
23335 
23336       row.write_uint64(total*1024*1024);          // total allocated
23337       row.write_uint64((total-mb)*1024*1024);     // currently in use
23338       row.write_uint64(high*1024*1024);           // in use high water mark
23339       ndbinfo_send_row(signal, req, row, rl);
23340       logpart++;
23341       if (rl.need_break(req))
23342       {
23343         jam();
23344         ndbinfo_send_scan_break(signal, req, rl, logpart);
23345         return;
23346       }
23347     }
23348     break;
23349   }
23350 
23351   case Ndbinfo::LOGBUFFERS_TABLEID:
23352   {
23353     const size_t entry_size = sizeof(LogPageRecord);
23354     const Uint64 free = cnoOfLogPages;
23355     const Uint64 total = clogPageCount;
23356     const Uint64 high = 0; // TODO
23357 
23358     Ndbinfo::Row row(signal, req);
23359     row.write_uint32(getOwnNodeId());
23360     row.write_uint32(0);              // log type, 0 = REDO
23361     row.write_uint32(0);              // log id, always 0 in LQH
23362     row.write_uint32(instance());     // log part, instance for ndbmtd
23363 
23364     row.write_uint64(total*entry_size);        // total allocated
23365     row.write_uint64((total-free)*entry_size); // currently in use
23366     row.write_uint64(high*entry_size);         // in use high water mark
23367     ndbinfo_send_row(signal, req, row, rl);
23368 
23369     break;
23370   }
23371 
23372   case Ndbinfo::COUNTERS_TABLEID:
23373   {
23374     Ndbinfo::counter_entry counters[] = {
23375       { Ndbinfo::OPERATIONS_COUNTER, c_Counters.operations }
23376     };
23377     const size_t num_counters = sizeof(counters) / sizeof(counters[0]);
23378 
23379     Uint32 i = cursor->data[0];
23380     BlockNumber bn = blockToMain(number());
23381     while(i < num_counters)
23382     {
23383       jam();
23384       Ndbinfo::Row row(signal, req);
23385       row.write_uint32(getOwnNodeId());
23386       row.write_uint32(bn);           // block number
23387       row.write_uint32(instance());   // block instance
23388       row.write_uint32(counters[i].id);
23389 
23390       row.write_uint64(counters[i].val);
23391       ndbinfo_send_row(signal, req, row, rl);
23392       i++;
23393       if (rl.need_break(req))
23394       {
23395         jam();
23396         ndbinfo_send_scan_break(signal, req, rl, i);
23397         return;
23398       }
23399     }
23400     break;
23401   }
23402 
23403   default:
23404     break;
23405   }
23406 
23407   ndbinfo_send_scan_conf(signal, req, rl);
23408 }
23409 
23410 
23411 /* **************************************************************** */
23412 /* ---------------------------------------------------------------- */
23413 /* ---------------------- TRIGGER HANDLING ------------------------ */
23414 /* ---------------------------------------------------------------- */
23415 /*                                                                  */
23416 /*      All trigger signals from TRIX are forwarded top TUP         */
23417 /* ---------------------------------------------------------------- */
23418 /* **************************************************************** */
23419 
23420 // Trigger signals
23421 void
execCREATE_TRIG_IMPL_REQ(Signal * signal)23422 Dblqh::execCREATE_TRIG_IMPL_REQ(Signal* signal)
23423 {
23424   jamEntry();
23425 
23426   if (!assembleFragments(signal))
23427   {
23428     jam();
23429     return;
23430   }
23431 
23432   CreateTrigImplReq* req = (CreateTrigImplReq*)signal->getDataPtrSend();
23433   SectionHandle handle(this, signal);
23434   req->senderRef = reference();
23435   BlockReference tupRef = calcInstanceBlockRef(DBTUP);
23436   sendSignal(tupRef, GSN_CREATE_TRIG_IMPL_REQ, signal,
23437              signal->getLength(), JBB, &handle);
23438 }
23439 
23440 void
execCREATE_TRIG_IMPL_CONF(Signal * signal)23441 Dblqh::execCREATE_TRIG_IMPL_CONF(Signal* signal)
23442 {
23443   jamEntry();
23444 
23445   BlockReference dictRef = !isNdbMtLqh() ? DBDICT_REF : DBLQH_REF;
23446   sendSignal(dictRef, GSN_CREATE_TRIG_IMPL_CONF, signal,
23447              CreateTrigImplConf::SignalLength, JBB);
23448 }
23449 
23450 void
execCREATE_TRIG_IMPL_REF(Signal * signal)23451 Dblqh::execCREATE_TRIG_IMPL_REF(Signal* signal)
23452 {
23453   jamEntry();
23454 
23455   BlockReference dictRef = !isNdbMtLqh() ? DBDICT_REF : DBLQH_REF;
23456   sendSignal(dictRef, GSN_CREATE_TRIG_IMPL_REF, signal,
23457              CreateTrigImplRef::SignalLength, JBB);
23458 }
23459 
23460 void
execDROP_TRIG_IMPL_REQ(Signal * signal)23461 Dblqh::execDROP_TRIG_IMPL_REQ(Signal* signal)
23462 {
23463   jamEntry();
23464 
23465   DropTrigImplReq* req = (DropTrigImplReq*)signal->getDataPtrSend();
23466   req->senderRef = reference();
23467   BlockReference tupRef = calcInstanceBlockRef(DBTUP);
23468   sendSignal(tupRef, GSN_DROP_TRIG_IMPL_REQ, signal,
23469              DropTrigImplReq::SignalLength, JBB);
23470 }
23471 
23472 void
execDROP_TRIG_IMPL_CONF(Signal * signal)23473 Dblqh::execDROP_TRIG_IMPL_CONF(Signal* signal)
23474 {
23475   jamEntry();
23476 
23477   BlockReference dictRef = !isNdbMtLqh() ? DBDICT_REF : DBLQH_REF;
23478   sendSignal(dictRef, GSN_DROP_TRIG_IMPL_CONF, signal,
23479              DropTrigImplConf::SignalLength, JBB);
23480 }
23481 
23482 void
execDROP_TRIG_IMPL_REF(Signal * signal)23483 Dblqh::execDROP_TRIG_IMPL_REF(Signal* signal)
23484 {
23485   jamEntry();
23486 
23487   BlockReference dictRef = !isNdbMtLqh() ? DBDICT_REF : DBLQH_REF;
23488   sendSignal(dictRef, GSN_DROP_TRIG_IMPL_REF, signal,
23489              DropTrigImplRef::SignalLength, JBB);
23490 }
23491 
calcPageCheckSum(LogPageRecordPtr logP)23492 Uint32 Dblqh::calcPageCheckSum(LogPageRecordPtr logP){
23493     Uint32 checkSum = 37;
23494 #ifdef VM_TRACE
23495     for (Uint32 i = (ZPOS_CHECKSUM+1); i<ZPAGE_SIZE; i++)
23496       checkSum = logP.p->logPageWord[i] ^ checkSum;
23497 #endif
23498     return checkSum;
23499   }
23500 
23501 #ifdef NDB_DEBUG_FULL
23502 #ifdef ERROR_INSERT
23503 void
sendSignal(Uint32 ref,Uint32 gsn,Signal * signal,Uint32 len,Uint32 prio)23504 TraceLCP::sendSignal(Uint32 ref, Uint32 gsn, Signal* signal,
23505 		     Uint32 len, Uint32 prio)
23506 {
23507   Sig s;
23508   s.type = Sig::Sig_send;
23509   s.header = signal->header;
23510   s.header.theVerId_signalNumber = gsn;
23511   s.header.theReceiversBlockNumber = ref;
23512   s.header.theLength = len;
23513   memcpy(s.theData, signal->theData, 4 * len);
23514   m_signals.push_back(s);
23515   assert(signal->getNoOfSections() == 0);
23516 }
23517 
23518 void
save(Signal * signal)23519 TraceLCP::save(Signal* signal){
23520   Sig s;
23521   s.type = Sig::Sig_save;
23522   s.header = signal->header;
23523   memcpy(s.theData, signal->theData, 4 * signal->getLength());
23524   m_signals.push_back(s);
23525   assert(signal->getNoOfSections() == 0);
23526 }
23527 
23528 void
restore(SimulatedBlock & lqh,Signal * sig)23529 TraceLCP::restore(SimulatedBlock& lqh, Signal* sig){
23530   Uint32 cnt = m_signals.size();
23531   for(Uint32 i = 0; i<cnt; i++){
23532     sig->header = m_signals[i].header;
23533     memcpy(sig->theData, m_signals[i].theData, 4 * sig->getLength());
23534     switch(m_signals[i].type){
23535     case Sig::Sig_send:
23536       lqh.sendSignal(sig->header.theReceiversBlockNumber,
23537 		     sig->header.theVerId_signalNumber,
23538 		     sig,
23539 		     sig->header.theLength,
23540 		     JBB);
23541       break;
23542     case Sig::Sig_save:
23543       lqh.executeFunction(sig->header.theVerId_signalNumber, sig);
23544       break;
23545     }
23546   }
23547   m_signals.clear();
23548 }
23549 #endif
23550 #endif
23551 
writeDbgInfoPageHeader(LogPageRecordPtr logP,Uint32 place,Uint32 pageNo,Uint32 wordWritten)23552 void Dblqh::writeDbgInfoPageHeader(LogPageRecordPtr logP, Uint32 place,
23553                                    Uint32 pageNo, Uint32 wordWritten)
23554 {
23555   logP.p->logPageWord[ZPOS_LOG_TIMER]= logPartPtr.p->logTimer;
23556   logP.p->logPageWord[ZPOS_PREV_PAGE_NO]= logP.p->logPageWord[ZPOS_PAGE_NO];
23557   logP.p->logPageWord[ZPOS_PAGE_I]= logP.i;
23558   logP.p->logPageWord[ZPOS_PLACE_WRITTEN_FROM]= place;
23559   logP.p->logPageWord[ZPOS_PAGE_NO]= pageNo;
23560   logP.p->logPageWord[ZPOS_PAGE_FILE_NO]= logFilePtr.p->fileNo;
23561   logP.p->logPageWord[ZPOS_WORD_WRITTEN]= wordWritten;
23562   logP.p->logPageWord[ZPOS_IN_WRITING]= 1;
23563 }
23564 
initReportStatus(Signal * signal)23565 void Dblqh::initReportStatus(Signal* signal){
23566   NDB_TICKS current_time = NdbTick_CurrentMillisecond();
23567   m_next_report_time = current_time +
23568                        ((NDB_TICKS)m_startup_report_frequency) * ((NDB_TICKS)1000);
23569 }
23570 
checkReportStatus(Signal * signal)23571 void Dblqh::checkReportStatus(Signal* signal){
23572   if (m_startup_report_frequency == 0)
23573     return;
23574 
23575   NDB_TICKS current_time = NdbTick_CurrentMillisecond();
23576   if (current_time > m_next_report_time)
23577   {
23578     reportStatus(signal);
23579     m_next_report_time = current_time +
23580                          ((NDB_TICKS)m_startup_report_frequency) * ((NDB_TICKS)1000);
23581   }
23582 }
23583 
reportStatus(Signal * signal)23584 void Dblqh::reportStatus(Signal* signal){
23585   const int signal_length = 6;
23586 
23587   signal->theData[0] = NDB_LE_LogFileInitStatus;
23588   signal->theData[1] = reference();
23589   for (int i = 2; i < signal_length; i++)
23590     signal->theData[i] = 0;
23591   if (getNodeState().startLevel < NodeState::SL_STARTED){
23592     signal->theData[2] = totalLogFiles;
23593     signal->theData[3] = logFileInitDone;
23594     signal->theData[4] = totallogMBytes;
23595     signal->theData[5] = logMBytesInitDone;
23596   }
23597   sendSignal(CMVMI_REF, GSN_EVENT_REP, signal, signal_length, JBB);
23598 }
23599 
logfileInitCompleteReport(Signal * signal)23600 void Dblqh::logfileInitCompleteReport(Signal* signal){
23601   const int signal_length = 6;
23602 
23603   signal->theData[0] = NDB_LE_LogFileInitCompStatus;
23604   signal->theData[1] = reference();
23605   signal->theData[2] = totalLogFiles;
23606   signal->theData[3] = logFileInitDone;
23607   signal->theData[4] = totallogMBytes;
23608   signal->theData[5] = logMBytesInitDone;
23609   sendSignal(CMVMI_REF, GSN_EVENT_REP, signal, signal_length, JBB);
23610 }
23611 
23612 #ifdef NDBD_TRACENR
23613 void
TRACE_OP_DUMP(const Dblqh::TcConnectionrec * regTcPtr,const char * pos)23614 Dblqh::TRACE_OP_DUMP(const Dblqh::TcConnectionrec* regTcPtr, const char * pos)
23615 {
23616   (* traceopout)
23617     << "[ " << hex << regTcPtr->transid[0]
23618     << " " << hex << regTcPtr->transid[1] << " ] " << dec
23619     << pos
23620     << " " << (Operation_t)regTcPtr->operation
23621     << " " << regTcPtr->tableref
23622     << "(" << regTcPtr->fragmentid << ")"
23623     << "(" << (regTcPtr->seqNoReplica == 0 ? "P" : "B") << ")" ;
23624 
23625   {
23626     (* traceopout) << "key=[" << hex;
23627     if (regTcPtr->keyInfoIVal != RNIL)
23628     {
23629       SectionReader keyInfoReader(regTcPtr->keyInfoIVal,
23630                                   g_sectionSegmentPool);
23631 
23632       Uint32 keyWord;
23633       while (keyInfoReader.getWord(&keyWord))
23634         (* traceopout) << hex << keyWord << " ";
23635     }
23636     (* traceopout) << "] ";
23637   }
23638 
23639   if (regTcPtr->m_use_rowid)
23640     (* traceopout) << " " << regTcPtr->m_row_id;
23641   (* traceopout) << endl;
23642 }
23643 #endif
23644 
23645 Uint32
get_node_status(Uint32 nodeId) const23646 Dblqh::get_node_status(Uint32 nodeId) const
23647 {
23648   HostRecordPtr Thostptr;
23649   Thostptr.i = nodeId;
23650   ptrCheckGuard(Thostptr, chostFileSize, hostRecord);
23651   return Thostptr.p->nodestatus;
23652 }
23653 
23654 #ifndef NO_REDO_PAGE_CACHE
23655 /**
23656  * Don't cache pages if less then 64 pages are free
23657  */
23658 #define MIN_REDO_PAGES_FREE 64
23659 
23660 void
do_evict(RedoPageCache & cache,Ptr<RedoCacheLogPageRecord> pagePtr)23661 Dblqh::do_evict(RedoPageCache& cache, Ptr<RedoCacheLogPageRecord> pagePtr)
23662 {
23663   LogPageRecordPtr save = logPagePtr;
23664   cache.m_lru.remove(pagePtr);
23665   cache.m_hash.remove(pagePtr);
23666   if (0)
23667   ndbout_c("evict part: %u file: %u page: %u cnoOfLogPages: %u",
23668            pagePtr.p->m_part_no,
23669            pagePtr.p->m_file_no,
23670            pagePtr.p->m_page_no,
23671            cnoOfLogPages);
23672 
23673   logPagePtr.i = pagePtr.i;
23674   ptrCheckGuard(logPagePtr, clogPageFileSize, logPageRecord);
23675 
23676   Ptr<LogPageRecord> prevPagePtr, nextPagePtr;
23677   prevPagePtr.i = logPagePtr.p->logPageWord[ZPREV_PAGE];
23678   nextPagePtr.i = logPagePtr.p->logPageWord[ZNEXT_PAGE];
23679   if (prevPagePtr.i != RNIL)
23680   {
23681     jam();
23682     /**
23683      * Remove ZNEXT pointer from prevPagePtr
23684      *   so we don't try to "serve" multi-page request
23685      *   if next-page has been evicted
23686      */
23687     ptrCheckGuard(prevPagePtr, clogPageFileSize, logPageRecord);
23688     ndbrequire(prevPagePtr.p->logPageWord[ZNEXT_PAGE] == logPagePtr.i);
23689     prevPagePtr.p->logPageWord[ZNEXT_PAGE] = RNIL;
23690   }
23691 
23692   if (nextPagePtr.i != RNIL)
23693   {
23694     jam();
23695     /**
23696      * Remove ZPREV pointer from nextPagePtr
23697      *   so don't try to do above if prev has been evicted
23698      */
23699     ptrCheckGuard(nextPagePtr, clogPageFileSize, logPageRecord);
23700     ndbrequire(nextPagePtr.p->logPageWord[ZPREV_PAGE] == logPagePtr.i);
23701     nextPagePtr.p->logPageWord[ZPREV_PAGE] = RNIL;
23702   }
23703 
23704   releaseLogpage(0);
23705   logPagePtr = save;
23706 }
23707 
23708 void
evict(RedoPageCache & cache,Uint32 cnt)23709 Dblqh::evict(RedoPageCache& cache, Uint32 cnt)
23710 {
23711   while (cnoOfLogPages < (cnt + MIN_REDO_PAGES_FREE) && !cache.m_lru.isEmpty())
23712   {
23713     jam();
23714     Ptr<RedoCacheLogPageRecord> pagePtr;
23715     cache.m_lru.last(pagePtr);
23716     do_evict(cache, pagePtr);
23717   }
23718 }
23719 
23720 void
addCachePages(RedoPageCache & cache,Uint32 partNo,Uint32 startPageNo,LogFileOperationRecord * lfoPtrP)23721 Dblqh::addCachePages(RedoPageCache& cache,
23722                      Uint32 partNo,
23723                      Uint32 startPageNo,
23724                      LogFileOperationRecord* lfoPtrP)
23725 {
23726   Uint32 cnt = lfoPtrP->noPagesRw;
23727   Ptr<LogFileRecord> filePtr;
23728   filePtr.i = lfoPtrP->logFileRec;
23729   ptrCheckGuard(filePtr, clogFileFileSize, logFileRecord);
23730 
23731   evict(cache, 0);
23732 
23733   if (cnoOfLogPages < cnt + MIN_REDO_PAGES_FREE)
23734   {
23735     /**
23736      * Don't cache if low on redo-buffer
23737      */
23738     return;
23739   }
23740 
23741   for (Uint32 i = 0; i<cnt ; i++)
23742   {
23743     Ptr<RedoCacheLogPageRecord> pagePtr;
23744     pagePtr.i = lfoPtrP->logPageArray[i];
23745     cache.m_pool.getPtr(pagePtr);
23746     pagePtr.p->m_part_no = partNo;
23747     pagePtr.p->m_page_no = startPageNo + i;
23748     pagePtr.p->m_file_no = filePtr.p->fileNo;
23749 
23750     bool found = false;
23751     {
23752       RedoCacheLogPageRecord key;
23753       key.m_part_no = partNo;
23754       key.m_page_no = startPageNo + i;
23755       key.m_file_no = filePtr.p->fileNo;
23756       Ptr<RedoCacheLogPageRecord> tmp;
23757       if (cache.m_hash.find(tmp, key))
23758       {
23759         jam();
23760         found = true;
23761         do_evict(cache, tmp);
23762       }
23763     }
23764 
23765     cache.m_hash.add(pagePtr);
23766     cache.m_lru.addFirst(pagePtr);
23767     if (0)
23768     ndbout_c("adding(%u) part: %u file: %u page: %u cnoOfLogPages: %u cnt: %u",
23769              found,
23770              pagePtr.p->m_part_no,
23771              pagePtr.p->m_file_no,
23772              pagePtr.p->m_page_no,
23773              cnoOfLogPages,
23774              cnt);
23775   }
23776 
23777   /**
23778    * Make sure pages are not released when prepare-record is executed
23779    * @see releaseLfoPages
23780    */
23781   lfoPtrP->firstLfoPage = RNIL;
23782 }
23783 
23784 void
release(RedoPageCache & cache)23785 Dblqh::release(RedoPageCache& cache)
23786 {
23787   while (!cache.m_lru.isEmpty())
23788   {
23789     jam();
23790     Ptr<RedoCacheLogPageRecord> pagePtr;
23791     cache.m_lru.last(pagePtr);
23792     cache.m_lru.remove(pagePtr);
23793 
23794     logPagePtr.i = pagePtr.i;
23795     ptrCheckGuard(logPagePtr, clogPageFileSize, logPageRecord);
23796     releaseLogpage(0);
23797   }
23798   cache.m_hash.removeAll();
23799 
23800 #if defined VM_TRACE || defined ERROR_INSERT || 1
23801   ndbout_c("RedoPageCache: avoided %u (%u/%u) page-reads",
23802            cache.m_hits, cache.m_multi_page, cache.m_multi_miss);
23803 #endif
23804   cache.m_hits = 0;
23805   cache.m_multi_page = 0;
23806   cache.m_multi_miss = 0;
23807 }
23808 #endif
23809 
23810 #ifndef NO_REDO_OPEN_FILE_CACHE
23811 
23812 #define MAX_CACHED_OPEN_FILES 4
23813 
23814 void
openFileRw_cache(Signal * signal,LogFileRecordPtr filePtr)23815 Dblqh::openFileRw_cache(Signal* signal,
23816                         LogFileRecordPtr filePtr)
23817 {
23818   jam();
23819 
23820   LogFileRecord::LogFileStatus state = filePtr.p->logFileStatus;
23821   if (state != LogFileRecord::CLOSED)
23822   {
23823     jam();
23824 
23825     m_redo_open_file_cache.m_hits++;
23826 
23827     if (m_redo_open_file_cache.m_lru.hasPrev(filePtr))
23828     {
23829       jam();
23830       m_redo_open_file_cache.m_lru.remove(filePtr);
23831       m_redo_open_file_cache.m_lru.addFirst(filePtr);
23832     }
23833 
23834     filePtr.p->logFileStatus = LogFileRecord::OPEN_EXEC_LOG_CACHED;
23835 
23836     signal->theData[0] = filePtr.i;
23837     signal->theData[1] = filePtr.p->fileRef;
23838     sendSignal(reference(), GSN_FSOPENCONF, signal, 2, JBB);
23839     return;
23840   }
23841 
23842   filePtr.p->logFileStatus = LogFileRecord::OPEN_EXEC_LOG;
23843   openFileRw(signal, filePtr, false);
23844 }
23845 
23846 void
closeFile_cache(Signal * signal,LogFileRecordPtr filePtr,Uint32 line)23847 Dblqh::closeFile_cache(Signal* signal,
23848                        LogFileRecordPtr filePtr,
23849                        Uint32 line)
23850 {
23851   jam();
23852 
23853   filePtr.p->logFileStatus = LogFileRecord::CLOSING_EXEC_LOG_CACHED;
23854   if (m_redo_open_file_cache.m_lru.count() >= MAX_CACHED_OPEN_FILES)
23855   {
23856     jam();
23857     Ptr<LogFileRecord> evictPtr;
23858     Uint32 logPartRec = filePtr.p->logPartRec;
23859     /**
23860      * Only evict file with same log-part, other redo-execution will continue
23861      *   for the log-part once file is closed
23862      *
23863      * Note: 1) loop is guaranteed to terminate as filePtr must be in list
23864      *       2) loop is ok as MAX_CACHED_OPEN_FILES is "small"
23865      *          (if it was big, the m_lru should be split per log-part)
23866      */
23867     m_redo_open_file_cache.m_lru.last(evictPtr);
23868     while (evictPtr.p->logPartRec != logPartRec)
23869     {
23870       jam();
23871       ndbrequire(m_redo_open_file_cache.m_lru.prev(evictPtr));
23872     }
23873     m_redo_open_file_cache.m_lru.remove(evictPtr);
23874     evictPtr.p->logFileStatus = LogFileRecord::CLOSING_EXEC_LOG;
23875     closeFile(signal, evictPtr, line);
23876   }
23877   else
23878   {
23879     jam();
23880     signal->theData[0] = ZEXEC_SR;
23881     signal->theData[1] = filePtr.p->logPartRec;
23882     sendSignal(cownref, GSN_CONTINUEB, signal, 2, JBB);
23883   }
23884 }
23885 
23886 void
release(Signal * signal,RedoOpenFileCache & cache)23887 Dblqh::release(Signal* signal, RedoOpenFileCache & cache)
23888 {
23889   Ptr<LogFileRecord> closePtr;
23890 
23891   while (m_redo_open_file_cache.m_lru.first(closePtr))
23892   {
23893     jam();
23894     m_redo_open_file_cache.m_lru.remove(closePtr);
23895     if (closePtr.p->logFileStatus == LogFileRecord::CLOSING_EXEC_LOG_CACHED)
23896     {
23897       jam();
23898       closePtr.p->logFileStatus = LogFileRecord::CLOSING_EXEC_LOG_CACHED;
23899       m_redo_open_file_cache.m_close_cnt ++;
23900       signal->theData[0] = closePtr.p->fileRef;
23901       signal->theData[1] = reference();
23902       signal->theData[2] = closePtr.i;
23903       signal->theData[3] = ZCLOSE_NO_DELETE;
23904       signal->theData[4] = __LINE__;
23905       sendSignal(NDBFS_REF, GSN_FSCLOSEREQ, signal, 5, JBA);
23906       return;
23907     }
23908     else
23909     {
23910       ndbout_c("Found file with state: %u",
23911                closePtr.p->logFileStatus);
23912     }
23913   }
23914 
23915   ndbout_c("RedoOpenFileCache: Avoided %u file-open/close closed: %u",
23916            m_redo_open_file_cache.m_hits,
23917            m_redo_open_file_cache.m_close_cnt);
23918   m_redo_open_file_cache.m_hits = 0;
23919   m_redo_open_file_cache.m_close_cnt = 0;
23920   execLogComp_extra_files_closed(signal);
23921 }
23922 
23923 #endif
23924 
23925 bool
check_ndb_versions() const23926 Dblqh::check_ndb_versions() const
23927 {
23928   Uint32 version = getNodeInfo(getOwnNodeId()).m_version;
23929   for (Uint32 i = 0; i < cnoOfNodes; i++)
23930   {
23931     Uint32 node = cnodeData[i];
23932     if (cnodeStatus[i] == ZNODE_UP)
23933     {
23934       if(getNodeInfo(node).m_version != version)
23935       {
23936         return false;
23937       }
23938     }
23939   }
23940   return true;
23941 }
23942 
23943 void
suspendFile(Signal * signal,Uint32 filePtrI,Uint32 millis)23944 Dblqh::suspendFile(Signal* signal, Uint32 filePtrI, Uint32 millis)
23945 {
23946   Ptr<LogFileRecord> tmp;
23947   tmp.i = filePtrI;
23948   ptrCheckGuard(tmp, clogFileFileSize, logFileRecord);
23949   suspendFile(signal, tmp, millis);
23950 }
23951 
23952 void
suspendFile(Signal * signal,Ptr<LogFileRecord> logFilePtr,Uint32 millis)23953 Dblqh::suspendFile(Signal* signal, Ptr<LogFileRecord> logFilePtr, Uint32 millis)
23954 {
23955   SaveSignal<FsSuspendOrd::SignalLength> tmp(signal);
23956   signal->theData[0] = logFilePtr.p->fileRef;
23957   signal->theData[1] = millis;
23958   sendSignal(NDBFS_REF, GSN_FSSUSPENDORD, signal, 2, JBA);
23959 }
23960 
23961 void
send_runredo_event(Signal * signal,LogPartRecord * lp,Uint32 gci)23962 Dblqh::send_runredo_event(Signal* signal, LogPartRecord * lp, Uint32 gci)
23963 {
23964   signal->theData[0] = NDB_LE_RunRedo;
23965   signal->theData[1] = lp->logPartNo;
23966   signal->theData[2] = csrPhasesCompleted;
23967   signal->theData[3] = lp->logStartGci;
23968   signal->theData[4] = gci;
23969   signal->theData[5] = lp->logLastGci;
23970 
23971 
23972   LogFileRecordPtr filePtr;
23973   filePtr.i = lp->startLogfile;
23974   ptrCheckGuard(filePtr, clogFileFileSize, logFileRecord);
23975   signal->theData[6] = filePtr.p->fileNo;
23976   signal->theData[7] = lp->startMbyte;
23977 
23978   filePtr.i = lp->currentLogfile;
23979   ptrCheckGuard(filePtr, clogFileFileSize, logFileRecord);
23980   signal->theData[8] = filePtr.p->fileNo;
23981   signal->theData[9] = filePtr.p->currentMbyte;
23982 
23983   filePtr.i = lp->stopLogfile;
23984   ptrCheckGuard(filePtr, clogFileFileSize, logFileRecord);
23985   signal->theData[10] = filePtr.p->fileNo;
23986   signal->theData[11] = lp->stopMbyte;
23987   sendSignal(CMVMI_REF, GSN_EVENT_REP, signal, 12, JBB);
23988 }
23989 
23990 void
init(Uint32 partNo)23991 Dblqh::IOTracker::init(Uint32 partNo)
23992 {
23993   bzero(this, sizeof(* this));
23994   m_log_part_no = partNo;
23995 }
23996 
23997 int
tick(Uint32 now,Uint32 maxlag,Uint32 maxlag_cnt)23998 Dblqh::IOTracker::tick(Uint32 now, Uint32 maxlag, Uint32 maxlag_cnt)
23999 {
24000   Uint32 t = m_current_time;
24001 
24002   if ((t / SAMPLE_TIME) == (now / SAMPLE_TIME))
24003     return 0;
24004 
24005   m_current_time = now;
24006   if (m_sample_completed_bytes >= m_sample_sent_bytes)
24007   {
24008     /**
24009      * If we completed all io we sent during current sample...
24010      *   we can't have any problem...and
24011      *   we can't measure io throughput, so don't add measurement
24012      *
24013      */
24014     m_sample_sent_bytes = 0;
24015     m_sample_completed_bytes = 0;
24016   }
24017   else
24018   {
24019     // io maxed out...
24020     Uint32 elapsed = now - t;
24021     m_save_written_bytes[m_save_pos] += m_sample_completed_bytes;
24022     m_save_elapsed_millis[m_save_pos] += elapsed;
24023 
24024     m_curr_written_bytes += m_sample_completed_bytes;
24025     m_curr_elapsed_millis += elapsed;
24026 
24027     Uint32 bps = (1000 * m_sample_completed_bytes) / elapsed;
24028     Uint32 lag = bps ? m_sum_outstanding_bytes / bps : 30;
24029     if (false && lag >= 30)
24030     {
24031       g_eventLogger->info("part: %u tick(%u) m_sample_completed_bytes: %u m_sample_sent_bytes: %u elapsed: %u kbps: %u lag: %u",
24032                           m_log_part_no,
24033                           now, m_sample_completed_bytes, m_sample_sent_bytes,
24034                           elapsed, bps/1000, lag);
24035     }
24036 
24037     m_sample_sent_bytes -= m_sample_completed_bytes;
24038     m_sample_completed_bytes = 0;
24039   }
24040 
24041   int retVal = 0;
24042   Uint32 save_lag_cnt = m_lag_cnt;
24043   if ((now / SLIDING_WINDOW_LEN) != (t / SLIDING_WINDOW_LEN))
24044   {
24045     Uint32 lag = m_curr_written_bytes ?
24046       ((Uint64(m_sum_outstanding_bytes) / 1000) * Uint64(m_curr_elapsed_millis)) / m_curr_written_bytes:
24047       0;
24048 
24049     if (lag > maxlag)
24050     {
24051       /**
24052        * We did have lag last second...
24053        *   increase m_lag_cnt and check if it has reached maxlag_cnt
24054        */
24055       Uint32 tmp = m_lag_cnt;
24056       m_lag_cnt += (lag / maxlag);
24057       if (tmp < maxlag_cnt && m_lag_cnt >= maxlag_cnt)
24058       {
24059         retVal = -1; // start aborting transaction
24060       }
24061     }
24062     else
24063     {
24064       /**
24065        * We did not have lag...reset m_lag_cnt
24066        */
24067       if (m_lag_cnt >= maxlag_cnt)
24068       {
24069         // stop aborting transcation
24070         retVal = 1;
24071       }
24072       m_lag_cnt = 0;
24073     }
24074 
24075 #if 1
24076     if (m_lag_cnt == 0 && lag == 0)
24077     {
24078     }
24079     else if (lag > 0 && m_lag_cnt == 0)
24080     {
24081       g_eventLogger->info("part: %u : time to complete: %u",
24082                           m_log_part_no, lag);
24083     }
24084     else if (m_lag_cnt < maxlag_cnt && m_lag_cnt == save_lag_cnt)
24085     {
24086       g_eventLogger->info("part: %u : time to complete: %u lag_cnt: %u => %u => retVal: %d",
24087                           m_log_part_no,
24088                           lag,
24089                           save_lag_cnt,
24090                           m_lag_cnt,
24091                           retVal);
24092     }
24093     else
24094     {
24095       g_eventLogger->info("part: %u : sum_outstanding: %ukb avg_written: %ukb avg_elapsed: %ums time to complete: %u lag_cnt: %u => %u retVal: %d",
24096                           m_log_part_no, m_sum_outstanding_bytes / 1024, m_curr_written_bytes/1024, m_curr_elapsed_millis,
24097              lag, save_lag_cnt, m_lag_cnt, retVal);
24098     }
24099 #endif
24100 
24101     /**
24102      * And finally rotate sliding window
24103      */
24104     Uint32 last = (m_save_pos + 1) % SLIDING_WINDOW_HISTORY_LEN;
24105     assert(m_curr_written_bytes >= m_save_written_bytes[last]);
24106     assert(m_curr_elapsed_millis >= m_save_elapsed_millis[last]);
24107     m_curr_written_bytes -= m_save_written_bytes[last];
24108     m_curr_elapsed_millis -= m_save_elapsed_millis[last];
24109     m_save_written_bytes[last] = 0;
24110     m_save_elapsed_millis[last] = 0;
24111     m_save_pos = last;
24112   }
24113   return retVal;
24114 }
24115 
24116 void
send_io(Uint32 bytes)24117 Dblqh::IOTracker::send_io(Uint32 bytes)
24118 {
24119   m_sum_outstanding_bytes += bytes;
24120   m_sample_sent_bytes += bytes;
24121 }
24122 
24123 void
complete_io(Uint32 bytes)24124 Dblqh::IOTracker::complete_io(Uint32 bytes)
24125 {
24126   assert(m_sum_outstanding_bytes >= bytes);
24127 
24128   m_sum_outstanding_bytes -= bytes;
24129   m_sample_completed_bytes += bytes;
24130 }
24131