MySQL 5.6.14 Source Code Document
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
DblqhMain.cpp
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 as published by
6  the Free Software Foundation; version 2 of the License.
7 
8  This program is distributed in the hope that it will be useful,
9  but WITHOUT ANY WARRANTY; without even the implied warranty of
10  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11  GNU General Public License for more details.
12 
13  You should have received a copy of the GNU General Public License
14  along with this program; if not, write to the Free Software
15  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
16 */
17 
18 #define DBLQH_C
19 #include "Dblqh.hpp"
20 #include <ndb_limits.h>
21 #include <md5_hash.hpp>
22 
23 #include <ndb_version.h>
24 #include <signaldata/TuxBound.hpp>
25 #include <signaldata/AccScan.hpp>
26 #include <signaldata/CopyActive.hpp>
27 #include <signaldata/CopyFrag.hpp>
28 #include <signaldata/CreateTrigImpl.hpp>
29 #include <signaldata/DropTrigImpl.hpp>
30 #include <signaldata/EmptyLcp.hpp>
31 #include <signaldata/EventReport.hpp>
32 #include <signaldata/ExecFragReq.hpp>
33 #include <signaldata/GCP.hpp>
34 #include <signaldata/TcKeyRef.hpp>
35 #include <signaldata/LqhKey.hpp>
36 #include <signaldata/NextScan.hpp>
37 #include <signaldata/NFCompleteRep.hpp>
38 #include <signaldata/NodeFailRep.hpp>
39 #include <signaldata/ReadNodesConf.hpp>
40 #include <signaldata/RelTabMem.hpp>
41 #include <signaldata/ScanFrag.hpp>
42 #include <signaldata/SrFragidConf.hpp>
43 #include <signaldata/StartFragReq.hpp>
44 #include <signaldata/StartRec.hpp>
45 #include <signaldata/TupKey.hpp>
46 #include <signaldata/TupCommit.hpp>
47 #include <signaldata/LqhFrag.hpp>
48 #include <signaldata/AccFrag.hpp>
49 #include <signaldata/TupFrag.hpp>
50 #include <signaldata/DumpStateOrd.hpp>
51 #include <signaldata/PackedSignal.hpp>
52 
53 #include <signaldata/CreateTab.hpp>
54 #include <signaldata/CreateTable.hpp>
55 #include <signaldata/PrepDropTab.hpp>
56 #include <signaldata/DropTab.hpp>
57 
58 #include <signaldata/AlterTab.hpp>
59 #include <signaldata/AlterTable.hpp>
60 #include <signaldata/DictTabInfo.hpp>
61 
62 #include <signaldata/LCP.hpp>
63 #include <DebuggerNames.hpp>
64 #include <signaldata/BackupImpl.hpp>
65 #include <signaldata/RestoreImpl.hpp>
66 #include <signaldata/KeyInfo.hpp>
67 #include <signaldata/AttrInfo.hpp>
68 #include <signaldata/TransIdAI.hpp>
69 #include <KeyDescriptor.hpp>
70 #include <signaldata/RouteOrd.hpp>
71 #include <signaldata/FsRef.hpp>
72 #include <SectionReader.hpp>
73 #include <signaldata/SignalDroppedRep.hpp>
74 #include <signaldata/FsReadWriteReq.hpp>
75 #include <signaldata/DbinfoScan.hpp>
76 #include <signaldata/SystemError.hpp>
77 #include <signaldata/FireTrigOrd.hpp>
78 #include <NdbEnv.h>
79 
80 #include "../suma/Suma.hpp"
81 #include "DblqhCommon.hpp"
82 
83 #include <EventLogger.hpp>
84 extern EventLogger * g_eventLogger;
85 
86 // Use DEBUG to print messages that should be
87 // seen only when we debug the product
88 #ifdef VM_TRACE
89 #define DEBUG(x) ndbout << "DBLQH: "<< x << endl;
90 static
91 NdbOut &
92 operator<<(NdbOut& out, Dblqh::TcConnectionrec::TransactionState state){
93  out << (int)state;
94  return out;
95 }
96 
97 static
98 NdbOut &
99 operator<<(NdbOut& out, Dblqh::TcConnectionrec::LogWriteState state){
100  out << (int)state;
101  return out;
102 }
103 
104 static
105 NdbOut &
106 operator<<(NdbOut& out, Dblqh::TcConnectionrec::ListState state){
107  out << (int)state;
108  return out;
109 }
110 
111 static
112 NdbOut &
113 operator<<(NdbOut& out, Dblqh::TcConnectionrec::AbortState state){
114  out << (int)state;
115  return out;
116 }
117 
118 static
119 NdbOut &
120 operator<<(NdbOut& out, Dblqh::ScanRecord::ScanState state){
121  out << (int)state;
122  return out;
123 }
124 
125 static
126 NdbOut &
127 operator<<(NdbOut& out, Dblqh::LogFileOperationRecord::LfoState state){
128  out << (int)state;
129  return out;
130 }
131 
132 static
133 NdbOut &
134 operator<<(NdbOut& out, Dblqh::ScanRecord::ScanType state){
135  out << (int)state;
136  return out;
137 }
138 
139 static
140 NdbOut &
141 operator<<(NdbOut& out, Operation_t op)
142 {
143  switch(op){
144  case ZREAD: out << "READ"; break;
145  case ZREAD_EX: out << "READ-EX"; break;
146  case ZINSERT: out << "INSERT"; break;
147  case ZUPDATE: out << "UPDATE"; break;
148  case ZDELETE: out << "DELETE"; break;
149  case ZWRITE: out << "WRITE"; break;
150  case ZUNLOCK: out << "UNLOCK"; break;
151  case ZREFRESH: out << "REFRESH"; break;
152  }
153  return out;
154 }
155 
156 #else
157 #define DEBUG(x)
158 #endif
159 
160 //#define MARKER_TRACE 0
161 //#define TRACE_SCAN_TAKEOVER 1
162 
163 #ifdef VM_TRACE
164 #ifndef NDB_DEBUG_REDO
165 #define NDB_DEBUG_REDO
166 #endif
167 #endif
168 
169 #ifdef NDB_DEBUG_REDO
170 static int DEBUG_REDO = 0;
171 #else
172 #define DEBUG_REDO 0
173 #endif
174 
175 const Uint32 NR_ScanNo = 0;
176 
177 #ifndef NDBD_TRACENR
178 #if defined VM_TRACE
179 #define NDBD_TRACENR
180 #endif
181 #endif
182 
183 #ifdef NDBD_TRACENR
184 #include <NdbConfig.h>
185 static NdbOut * tracenrout = 0;
186 static int TRACENR_FLAG = 0;
187 #define TRACENR(x) (* tracenrout) << x
188 #define SET_TRACENR_FLAG TRACENR_FLAG = 1
189 #define CLEAR_TRACENR_FLAG TRACENR_FLAG = 0
190 #else
191 #define TRACENR_FLAG 0
192 #define TRACENR(x) do { } while(0)
193 #define SET_TRACENR_FLAG
194 #define CLEAR_TRACENR_FLAG
195 #endif
196 
197 #ifdef NDBD_TRACENR
198 static NdbOut * traceopout = 0;
199 #define TRACE_OP(regTcPtr, place) do { if (TRACE_OP_CHECK(regTcPtr)) TRACE_OP_DUMP(regTcPtr, place); } while(0)
200 #else
201 #define TRACE_OP(x, y) { (void)x;}
202 #endif
203 
205 {
206  Uint32 m_file_no;
207  Uint32 m_mbyte;
208 };
209 
210 int
211 cmp(const LogPosition& pos1, const LogPosition& pos2)
212 {
213  if (pos1.m_file_no > pos2.m_file_no)
214  return 1;
215  if (pos1.m_file_no < pos2.m_file_no)
216  return -1;
217  if (pos1.m_mbyte > pos2.m_mbyte)
218  return 1;
219  if (pos1.m_mbyte < pos2.m_mbyte)
220  return -1;
221 
222  return 0;
223 }
224 
228 static
229 Uint64
230 free_log(const LogPosition& head, const LogPosition& tail,
231  Uint32 cnt, Uint32 size)
232 {
233  Uint64 headmb = head.m_file_no*Uint64(size) + head.m_mbyte;
234  Uint64 tailmb = tail.m_file_no*Uint64(size) + tail.m_mbyte;
235  if (headmb >= tailmb)
236  {
237  return (cnt * Uint64(size)) - headmb + tailmb;
238  }
239  else
240  {
241  return tailmb - headmb;
242  }
243 }
244 
245 /* ------------------------------------------------------------------------- */
246 /* ------- SEND SYSTEM ERROR ------- */
247 /* */
248 /* ------------------------------------------------------------------------- */
249 void Dblqh::systemError(Signal* signal, int line)
250 {
251  signal->theData[0] = 2304;
252  execDUMP_STATE_ORD(signal);
253  progError(line, NDBD_EXIT_NDBREQUIRE);
254 }//Dblqh::systemError()
255 
256 /* *************** */
257 /* ACCSEIZEREF > */
258 /* *************** */
259 void Dblqh::execACCSEIZEREF(Signal* signal)
260 {
261  jamEntry();
262  ndbrequire(false);
263 }//Dblqh::execACCSEIZEREF()
264 
265 /* ******************************************************>> */
266 /* THIS SIGNAL IS USED TO HANDLE REAL-TIME */
267 /* BREAKS THAT ARE NECESSARY TO ENSURE REAL-TIME */
268 /* OPERATION OF LQH. */
269 /* This signal is also used for signal loops, for example */
270 /* the timeout handling for writing logs every second. */
271 /* ******************************************************>> */
272 void Dblqh::execCONTINUEB(Signal* signal)
273 {
274  jamEntry();
275  Uint32 tcase = signal->theData[0];
276  Uint32 data0 = signal->theData[1];
277  Uint32 data1 = signal->theData[2];
278  Uint32 data2 = signal->theData[3];
279 #if 0
280  if (tcase == RNIL) {
281  tcConnectptr.i = data0;
282  ptrCheckGuard(tcConnectptr, ctcConnectrecFileSize, tcConnectionrec);
283  ndbout << "State = " << tcConnectptr.p->transactionState;
284  ndbout << " seqNoReplica = " << tcConnectptr.p->seqNoReplica;
285  ndbout << " tcNodeFailrec = " << tcConnectptr.p->tcNodeFailrec;
286  ndbout << " activeCreat = " << tcConnectptr.p->activeCreat;
287  ndbout << endl;
288  ndbout << "abortState = " << tcConnectptr.p->abortState;
289  ndbout << "listState = " << tcConnectptr.p->listState;
290  ndbout << endl;
291  return;
292  }//if
293 #endif
294  LogPartRecordPtr save;
295  switch (tcase) {
296  case ZLOG_LQHKEYREQ:
297  if (cnoOfLogPages == 0) {
298  jam();
299  busywait:
300  sendSignalWithDelay(cownref, GSN_CONTINUEB, signal, 10, 2);
301  return;
302  }//if
303  logPartPtr.i = data0;
304  ptrCheckGuard(logPartPtr, clogPartFileSize, logPartRecord);
305  save = logPartPtr;
306 
307  logPartPtr.p->LogLqhKeyReqSent = ZFALSE;
308 
309  if (logPartPtr.p->waitWriteGciLog == LogPartRecord::WWGL_TRUE)
310  {
311  jam();
312  goto startnext;
313  }
314  if (logPartPtr.p->m_log_complete_queue.isEmpty())
315  {
316  jam();
320  if (logPartPtr.p->m_log_problems != 0)
321  {
325  jam();
326  return;
327  }
328 
329  if (cnoOfLogPages < ZMIN_LOG_PAGES_OPERATION)
330  {
331  jam();
332  logPartPtr.p->LogLqhKeyReqSent = ZTRUE;
333  goto busywait;
334  }
335  }
336 
337  logFilePtr.i = logPartPtr.p->currentLogfile;
338  ptrCheckGuard(logFilePtr, clogFileFileSize, logFileRecord);
339  logPagePtr.i = logFilePtr.p->currentLogpage;
340  ptrCheckGuard(logPagePtr, clogPageFileSize, logPageRecord);
341 
342  getFirstInLogQueue(signal, tcConnectptr);
343  fragptr.i = tcConnectptr.p->fragmentptr;
344  c_fragment_pool.getPtr(fragptr);
345 
346  // so that operation can continue...
347  ndbrequire(logPartPtr.p->logPartState == LogPartRecord::ACTIVE);
348  logPartPtr.p->logPartState = LogPartRecord::IDLE;
349  switch (tcConnectptr.p->transactionState) {
350  case TcConnectionrec::LOG_QUEUED:
351  if (tcConnectptr.p->abortState != TcConnectionrec::ABORT_IDLE)
352  {
353  jam();
354  abortCommonLab(signal);
355  }
356  else
357  {
358  jam();
359  logLqhkeyreqLab(signal);
360  }
361  break;
362  case TcConnectionrec::LOG_ABORT_QUEUED:
363  jam();
364  writeAbortLog(signal);
365  removeLogTcrec(signal);
366  continueAfterLogAbortWriteLab(signal);
367  break;
368  case TcConnectionrec::LOG_COMMIT_QUEUED:
369  case TcConnectionrec::LOG_COMMIT_QUEUED_WAIT_SIGNAL:
370  jam();
371  writeCommitLog(signal, logPartPtr);
372  if (tcConnectptr.p->transactionState == TcConnectionrec::LOG_COMMIT_QUEUED) {
373  if (tcConnectptr.p->seqNoReplica == 0 ||
374  tcConnectptr.p->activeCreat == Fragrecord::AC_NR_COPY)
375  {
376  jam();
377  localCommitLab(signal);
378  }
379  else
380  {
381  jam();
382  commitReplyLab(signal);
383  }
384  }
385  else
386  {
387  jam();
388  tcConnectptr.p->transactionState = TcConnectionrec::LOG_COMMIT_WRITTEN_WAIT_SIGNAL;
389  }
390  break;
391  case TcConnectionrec::COMMIT_QUEUED:
392  jam();
393  localCommitLab(signal);
394  break;
395  case TcConnectionrec::ABORT_QUEUED:
396  jam();
397  abortCommonLab(signal);
398  break;
399  default:
400  ndbrequire(false);
401  break;
402  }//switch
403 
407  startnext:
408  logPartPtr = save;
409  logFilePtr.i = logPartPtr.p->currentLogfile;
410  ptrCheckGuard(logFilePtr, clogFileFileSize, logFileRecord);
411  logPagePtr.i = logFilePtr.p->currentLogpage;
412  ptrCheckGuard(logPagePtr, clogPageFileSize, logPageRecord);
413  logNextStart(signal);
414  return;
415  break;
416  case ZSR_GCI_LIMITS:
417  jam();
418  signal->theData[0] = data0;
419  srGciLimits(signal);
420  return;
421  break;
422  case ZSR_LOG_LIMITS:
423  jam();
424  signal->theData[0] = data0;
425  signal->theData[1] = data1;
426  signal->theData[2] = data2;
427  srLogLimits(signal);
428  return;
429  break;
430  case ZSEND_EXEC_CONF:
431  jam();
432  signal->theData[0] = data0;
433  sendExecConf(signal);
434  return;
435  break;
436  case ZEXEC_SR:
437  jam();
438  signal->theData[0] = data0;
439  execSr(signal);
440  return;
441  break;
442  case ZSR_FOURTH_COMP:
443  jam();
444  signal->theData[0] = data0;
445  srFourthComp(signal);
446  return;
447  break;
448  case ZINIT_FOURTH:
449  jam();
450  signal->theData[0] = data0;
451  initFourth(signal);
452  return;
453  break;
454  case ZTIME_SUPERVISION:
455  jam();
456  signal->theData[0] = data0;
457  timeSup(signal);
458  return;
459  break;
460  case ZSR_PHASE3_START:
461  jam();
462  srPhase3Start(signal);
463  return;
464  break;
465  case ZLQH_TRANS_NEXT:
466  jam();
467  tcNodeFailptr.i = data0;
468  ptrCheckGuard(tcNodeFailptr, ctcNodeFailrecFileSize, tcNodeFailRecord);
469  lqhTransNextLab(signal);
470  return;
471  break;
472  case ZSCAN_TC_CONNECT:
473  jam();
474  tabptr.i = data1;
475  ptrCheckGuard(tabptr, ctabrecFileSize, tablerec);
476  scanTcConnectLab(signal, data0, data2);
477  return;
478  break;
479  case ZINITIALISE_RECORDS:
480  jam();
481  initialiseRecordsLab(signal, data0, data2, signal->theData[4]);
482  return;
483  break;
484  case ZINIT_GCP_REC:
485  jam();
486  gcpPtr.i = 0;
487  ptrAss(gcpPtr, gcpRecord);
488  initGcpRecLab(signal);
489  startTimeSupervision(signal);
490  return;
491  break;
492  case ZCHECK_LCP_STOP_BLOCKED:
493  jam();
494  c_scanRecordPool.getPtr(scanptr, data0);
495  tcConnectptr.i = scanptr.p->scanTcrec;
496  ptrCheckGuard(tcConnectptr, ctcConnectrecFileSize, tcConnectionrec);
497  fragptr.i = tcConnectptr.p->fragmentptr;
498  c_fragment_pool.getPtr(fragptr);
499  checkLcpStopBlockedLab(signal);
500  return;
501  case ZSCAN_MARKERS:
502  jam();
503  scanMarkers(signal, data0, data1, data2);
504  return;
505  break;
506 
507  case ZOPERATION_EVENT_REP:
508  jam();
509  /* Send counter event report */
510  {
511  const Uint32 len = c_Counters.build_event_rep(signal);
512  sendSignal(CMVMI_REF, GSN_EVENT_REP, signal, len, JBB);
513  }
514 
515  {
516  const Uint32 report_interval = 5000;
517  const Uint32 len = c_Counters.build_continueB(signal);
518  signal->theData[0] = ZOPERATION_EVENT_REP;
519  sendSignalWithDelay(cownref, GSN_CONTINUEB, signal,
520  report_interval, len);
521  }
522  break;
523  case ZDROP_TABLE_WAIT_USAGE:
524  jam();
525  dropTab_wait_usage(signal);
526  return;
527  break;
528  case ZENABLE_EXPAND_CHECK:
529  {
530  jam();
531  fragptr.i = signal->theData[1];
532  if (fragptr.i != RNIL)
533  {
534  jam();
535  c_lcp_complete_fragments.getPtr(fragptr);
536  signal->theData[0] = fragptr.p->tabRef;
537  signal->theData[1] = fragptr.p->fragId;
538  BlockReference accRef = calcInstanceBlockRef(DBACC);
539  sendSignal(accRef, GSN_EXPANDCHECK2, signal, 2, JBB);
540  Ptr<Fragrecord> save = fragptr;
541 
542  c_lcp_complete_fragments.next(fragptr);
543  signal->theData[0] = ZENABLE_EXPAND_CHECK;
544  signal->theData[1] = fragptr.i;
545  sendSignal(reference(), GSN_CONTINUEB, signal, 2, JBB);
546 
547  c_lcp_complete_fragments.remove(save);
548  return;
549  }
550  else
551  {
552  jam();
553  cstartRecReq = SRR_REDO_COMPLETE;
554  ndbrequire(c_lcp_complete_fragments.isEmpty());
555 
556  rebuildOrderedIndexes(signal, 0);
557  return;
558  }
559  }
560  case ZRETRY_TCKEYREF:
561  {
562  jam();
563  Uint32 cnt = signal->theData[1];
564  Uint32 ref = signal->theData[2];
565  if (cnt < (10 * 60 * 5))
566  {
567  jam();
571  memmove(signal->theData, signal->theData+3, 4*TcKeyRef::SignalLength);
572  sendTCKEYREF(signal, ref, 0, cnt);
573  }
574  return;
575  }
576  case ZWAIT_REORG_SUMA_FILTER_ENABLED:
577  jam();
578  wait_reorg_suma_filter_enabled(signal);
579  return;
580  case ZREBUILD_ORDERED_INDEXES:
581  {
582  Uint32 tableId = signal->theData[1];
583  rebuildOrderedIndexes(signal, tableId);
584  return;
585  }
586  case ZWAIT_READONLY:
587  {
588  jam();
589  wait_readonly(signal);
590  return;
591  }
592  default:
593  ndbrequire(false);
594  break;
595  }//switch
596 }//Dblqh::execCONTINUEB()
597 
598 /* *********************************************************> */
599 /* Request from DBDIH to include a new node in the node list */
600 /* and so forth. */
601 /* *********************************************************> */
602 void Dblqh::execINCL_NODEREQ(Signal* signal)
603 {
604  jamEntry();
605  BlockReference retRef = signal->theData[0];
606  Uint32 nodeId = signal->theData[1];
607  cnewestGci = signal->theData[2];
608  cnewestCompletedGci = signal->theData[2] - 1;
609  ndbrequire(cnoOfNodes < MAX_NDB_NODES);
610  for (Uint32 i = 0; i < cnoOfNodes; i++) {
611  jam();
612  if (cnodeData[i] == nodeId) {
613  jam();
614  cnodeStatus[i] = ZNODE_UP;
615  }//if
616  }//for
617 
618  {
619  HostRecordPtr Thostptr;
620  Thostptr.i = nodeId;
621  ptrCheckGuard(Thostptr, chostFileSize, hostRecord);
622  Thostptr.p->nodestatus = ZNODE_UP;
623  }
624 
625  signal->theData[0] = nodeId;
626  signal->theData[1] = cownref;
627  sendSignal(retRef, GSN_INCL_NODECONF, signal, 2, JBB);
628  return;
629 }//Dblqh::execINCL_NODEREQ()
630 
631 void Dblqh::execTUPSEIZEREF(Signal* signal)
632 {
633  jamEntry();
634  ndbrequire(false);
635 }//Dblqh::execTUPSEIZEREF()
636 
637 /* ########################################################################## */
638 /* ####### START / RESTART MODULE ####### */
639 /* ########################################################################## */
640 /* ************************************************************************>> */
641 /* This is first signal that arrives in a start / restart. Sender is NDBCNTR_REF. */
642 /* ************************************************************************>> */
643 void Dblqh::execSTTOR(Signal* signal)
644 {
645  UintR tstartPhase;
646 
647  jamEntry();
648  /* START CASE */
649  tstartPhase = signal->theData[1];
650  /* SYSTEM RESTART RANK */
651  csignalKey = signal->theData[6];
652 #if defined VM_TRACE || defined ERROR_INSERT || defined NDBD_TRACENR
653  char *name;
654  FILE *out = 0;
655 #endif
656  switch (tstartPhase) {
657  case ZSTART_PHASE1:
658  jam();
659  cstartPhase = tstartPhase;
660  c_tup = (Dbtup*)globalData.getBlock(DBTUP, instance());
661  c_acc = (Dbacc*)globalData.getBlock(DBACC, instance());
662  c_lgman = (Lgman*)globalData.getBlock(LGMAN);
663  ndbrequire(c_tup != 0 && c_acc != 0 && c_lgman != 0);
664  sendsttorryLab(signal);
665 
666 #ifdef NDBD_TRACENR
667 #ifdef VM_TRACE
668  out = globalSignalLoggers.getOutputStream();
669 #endif
670  if (out == 0) {
671  name = NdbConfig_SignalLogFileName(getOwnNodeId());
672  out = fopen(name, "a");
673  }
674  tracenrout = new NdbOut(* new FileOutputStream(out));
675 #endif
676 
677 #ifdef NDBD_TRACENR
678  traceopout = &ndbout;
679 #endif
680 
681 #ifdef NDB_DEBUG_REDO
682  {
683  char buf[100];
684  if (NdbEnv_GetEnv("NDB_DEBUG_REDO", buf, sizeof(buf)))
685  {
686  DEBUG_REDO = 1;
687  }
688  }
689 #endif
690  return;
691  break;
692  case 4:
693  jam();
694  define_backup(signal);
695  break;
696  default:
697  jam();
698  /*empty*/;
699  sendsttorryLab(signal);
700  return;
701  break;
702  }//switch
703 }//Dblqh::execSTTOR()
704 
705 void
706 Dblqh::define_backup(Signal* signal)
707 {
708  DefineBackupReq * req = (DefineBackupReq*)signal->getDataPtrSend();
709  req->backupId = 0;
710  req->clientRef = 0;
711  req->clientData = 0;
712  req->senderRef = reference();
713  req->backupPtr = 0;
714  req->backupKey[0] = 0;
715  req->backupKey[1] = 0;
716  req->nodes.clear();
717  req->nodes.set(getOwnNodeId());
718  req->backupDataLen = ~0;
719 
720  BlockReference backupRef = calcInstanceBlockRef(BACKUP);
721  sendSignal(backupRef, GSN_DEFINE_BACKUP_REQ, signal,
722  DefineBackupReq::SignalLength, JBB);
723 }
724 
725 void
726 Dblqh::execDEFINE_BACKUP_REF(Signal* signal)
727 {
728  jamEntry();
729  m_backup_ptr = RNIL;
730  DefineBackupRef* ref = (DefineBackupRef*)signal->getDataPtrSend();
731  int err_code = 0;
732  char * extra_msg = NULL;
733 
734  switch(ref->errorCode){
735  case DefineBackupRef::Undefined:
736  case DefineBackupRef::FailedToSetupFsBuffers:
737  case DefineBackupRef::FailedToAllocateBuffers:
738  case DefineBackupRef::FailedToAllocateTables:
739  case DefineBackupRef::FailedAllocateTableMem:
740  case DefineBackupRef::FailedToAllocateFileRecord:
741  case DefineBackupRef::FailedToAllocateAttributeRecord:
742  case DefineBackupRef::FailedInsertFileHeader:
743  case DefineBackupRef::FailedInsertTableList:
744  jam();
745  err_code = NDBD_EXIT_INVALID_CONFIG;
746  extra_msg = (char*) "Probably Backup parameters configuration error, Please consult the manual";
747  progError(__LINE__, err_code, extra_msg);
748  }
749 
750  sendsttorryLab(signal);
751 }
752 
753 void
754 Dblqh::execDEFINE_BACKUP_CONF(Signal* signal)
755 {
756  jamEntry();
757  DefineBackupConf * conf = (DefineBackupConf*)signal->getDataPtrSend();
758  m_backup_ptr = conf->backupPtr;
759  sendsttorryLab(signal);
760 }
761 
762 /* ***************************************> */
763 /* Restart phases 1 - 6, sender is Ndbcntr */
764 /* ***************************************> */
765 void Dblqh::execNDB_STTOR(Signal* signal)
766 {
767  jamEntry();
768  Uint32 ownNodeId = signal->theData[1]; /* START PHASE*/
769  cstartPhase = signal->theData[2]; /* MY NODE ID */
770  cstartType = signal->theData[3]; /* START TYPE */
771 
772  switch (cstartPhase) {
773  case ZSTART_PHASE1:
774  jam();
775  preComputedRequestInfoMask = 0;
776  LqhKeyReq::setKeyLen(preComputedRequestInfoMask, RI_KEYLEN_MASK);
777  LqhKeyReq::setLastReplicaNo(preComputedRequestInfoMask, RI_LAST_REPL_MASK);
778  // Dont LqhKeyReq::setApplicationAddressFlag
779  LqhKeyReq::setDirtyFlag(preComputedRequestInfoMask, 1);
780  // Dont LqhKeyReq::setInterpretedFlag
781  LqhKeyReq::setSimpleFlag(preComputedRequestInfoMask, 1);
782  LqhKeyReq::setOperation(preComputedRequestInfoMask, RI_OPERATION_MASK);
783  LqhKeyReq::setGCIFlag(preComputedRequestInfoMask, 1);
784  LqhKeyReq::setNrCopyFlag(preComputedRequestInfoMask, 1);
785  // Dont setAIInLqhKeyReq
786  // Dont setSeqNoReplica
787  // Dont setSameClientAndTcFlag
788  // Dont setReturnedReadLenAIFlag
789  // Dont setAPIVersion
790  LqhKeyReq::setMarkerFlag(preComputedRequestInfoMask, 1);
791  LqhKeyReq::setQueueOnRedoProblemFlag(preComputedRequestInfoMask, 1);
792  //preComputedRequestInfoMask = 0x003d7fff;
793  startphase1Lab(signal, /* dummy */ ~0, ownNodeId);
794 
795  {
796  /* Start counter activity event reporting. */
797  const Uint32 len = c_Counters.build_continueB(signal);
798  signal->theData[0] = ZOPERATION_EVENT_REP;
799  sendSignalWithDelay(cownref, GSN_CONTINUEB, signal, 10, len);
800  }
801  return;
802  break;
803  case ZSTART_PHASE2:
804  jam();
805  startphase2Lab(signal, /* dummy */ ~0);
806  return;
807  break;
808  case ZSTART_PHASE3:
809  jam();
810  startphase3Lab(signal);
811  return;
812  break;
813  case ZSTART_PHASE4:
814  jam();
815  startphase4Lab(signal);
816  return;
817  break;
818  case ZSTART_PHASE6:
819  jam();
820  startphase6Lab(signal);
821  return;
822  break;
823  default:
824  jam();
825  /*empty*/;
826  sendNdbSttorryLab(signal);
827  return;
828  break;
829  }//switch
830 }//Dblqh::execNDB_STTOR()
831 
832 /* ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ */
833 /* +++++++ START PHASE 2 +++++++ */
834 /* */
835 /* INITIATE ALL RECORDS WITHIN THE BLOCK */
836 /* ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ */
837 void Dblqh::startphase1Lab(Signal* signal, Uint32 _dummy, Uint32 ownNodeId)
838 {
839  UintR Ti;
840  HostRecordPtr ThostPtr;
841 
842 /* ------- INITIATE ALL RECORDS ------- */
843  cownNodeid = ownNodeId;
844  caccBlockref = calcInstanceBlockRef(DBACC);
845  ctupBlockref = calcInstanceBlockRef(DBTUP);
846  ctuxBlockref = calcInstanceBlockRef(DBTUX);
847  cownref = calcInstanceBlockRef(DBLQH);
848  ndbassert(cownref == reference());
849  for (Ti = 0; Ti < chostFileSize; Ti++) {
850  ThostPtr.i = Ti;
851  ptrCheckGuard(ThostPtr, chostFileSize, hostRecord);
852  /*
853  * Valid only if receiver has same number of LQH workers.
854  * In general full instance key of fragment must be used.
855  */
856  ThostPtr.p->hostLqhBlockRef = calcInstanceBlockRef(DBLQH, ThostPtr.i);
857  ThostPtr.p->hostTcBlockRef = calcTcBlockRef(ThostPtr.i);
858  ThostPtr.p->inPackedList = false;
859  ThostPtr.p->noOfPackedWordsLqh = 0;
860  ThostPtr.p->noOfPackedWordsTc = 0;
861  ThostPtr.p->nodestatus = ZNODE_DOWN;
862  }//for
863  cpackedListIndex = 0;
864 
865  bool do_init =
866  (cstartType == NodeState::ST_INITIAL_START) ||
867  (cstartType == NodeState::ST_INITIAL_NODE_RESTART);
868 
869  LogFileRecordPtr prevLogFilePtr;
870  LogFileRecordPtr zeroLogFilePtr;
871 
872  ndbrequire(cnoLogFiles != 0);
873  for (logPartPtr.i = 0; logPartPtr.i < clogPartFileSize; logPartPtr.i++)
874  {
875  jam();
876  ptrAss(logPartPtr, logPartRecord);
877  initLogpart(signal);
878  for (Uint32 fileNo = 0; fileNo < cnoLogFiles; fileNo++)
879  {
880  seizeLogfile(signal);
881  if (fileNo != 0)
882  {
883  jam();
884  prevLogFilePtr.p->nextLogFile = logFilePtr.i;
885  logFilePtr.p->prevLogFile = prevLogFilePtr.i;
886  }
887  else
888  {
889  jam();
890  logPartPtr.p->firstLogfile = logFilePtr.i;
891  logPartPtr.p->currentLogfile = logFilePtr.i;
892  zeroLogFilePtr.i = logFilePtr.i;
893  zeroLogFilePtr.p = logFilePtr.p;
894  }//if
895  prevLogFilePtr.i = logFilePtr.i;
896  prevLogFilePtr.p = logFilePtr.p;
897  initLogfile(signal, fileNo);
898  if (do_init)
899  {
900  jam();
901  if (logFilePtr.i == zeroLogFilePtr.i)
902  {
903  jam();
904 /* ------------------------------------------------------------------------- */
905 /*IN AN INITIAL START WE START BY CREATING ALL LOG FILES AND SETTING THEIR */
906 /*PROPER SIZE AND INITIALISING PAGE ZERO IN ALL FILES. */
907 /*WE START BY CREATING FILE ZERO IN EACH LOG PART AND THEN PROCEED */
908 /*SEQUENTIALLY THROUGH ALL LOG FILES IN THE LOG PART. */
909 /* ------------------------------------------------------------------------- */
910  if (m_use_om_init == 0 || logPartPtr.i == 0)
911  {
915  jam();
916 #ifdef VM_TRACE
917  if (m_use_om_init)
918  {
919  jam();
925  disable_global_variables();
926  }
927 #endif
928  openLogfileInit(signal);
929  }
930  }//if
931  }//if
932  }//for
933  zeroLogFilePtr.p->prevLogFile = logFilePtr.i;
934  logFilePtr.p->nextLogFile = zeroLogFilePtr.i;
935  }
936 
937  initReportStatus(signal);
938  if (!do_init)
939  {
940  jam();
941  sendNdbSttorryLab(signal);
942  }
943  else
944  {
945  reportStatus(signal);
946  }
947 
948  return;
949 }//Dblqh::startphase1Lab()
950 
951 /* ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ */
952 /* +++++++ START PHASE 2 +++++++ */
953 /* */
954 /* CONNECT LQH WITH ACC AND TUP. */
955 /* EVERY CONNECTION RECORD IN LQH IS ASSIGNED TO ONE ACC CONNECTION RECORD */
956 /* AND ONE TUP CONNECTION RECORD. */
957 /* ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ */
958 void Dblqh::startphase2Lab(Signal* signal, Uint32 _dummy)
959 {
960  cmaxWordsAtNodeRec = MAX_NO_WORDS_OUTSTANDING_COPY_FRAGMENT;
961 /* -- ACC AND TUP CONNECTION PROCESS -- */
962  tcConnectptr.i = 0;
963  ptrAss(tcConnectptr, tcConnectionrec);
964  moreconnectionsLab(signal);
965  return;
966 }//Dblqh::startphase2Lab()
967 
968 void Dblqh::moreconnectionsLab(Signal* signal)
969 {
970  tcConnectptr.p->tcAccBlockref = caccBlockref;
971  // set TUX block here (no operation is seized in TUX)
972  tcConnectptr.p->tcTuxBlockref = ctuxBlockref;
973 /* NO STATE CHECKING IS PERFORMED, ASSUMED TO WORK */
974 /* *************** */
975 /* ACCSEIZEREQ < */
976 /* *************** */
977  signal->theData[0] = tcConnectptr.i;
978  signal->theData[1] = cownref;
979  sendSignal(caccBlockref, GSN_ACCSEIZEREQ, signal, 2, JBB);
980  return;
981 }//Dblqh::moreconnectionsLab()
982 
983 /* ***************> */
984 /* ACCSEIZECONF > */
985 /* ***************> */
986 void Dblqh::execACCSEIZECONF(Signal* signal)
987 {
988  jamEntry();
989  tcConnectptr.i = signal->theData[0];
990  ptrCheckGuard(tcConnectptr, ctcConnectrecFileSize, tcConnectionrec);
991  tcConnectptr.p->accConnectrec = signal->theData[1];
992 /* *************** */
993 /* TUPSEIZEREQ < */
994 /* *************** */
995  tcConnectptr.p->tcTupBlockref = ctupBlockref;
996  signal->theData[0] = tcConnectptr.i;
997  signal->theData[1] = cownref;
998  sendSignal(ctupBlockref, GSN_TUPSEIZEREQ, signal, 2, JBB);
999  return;
1000 }//Dblqh::execACCSEIZECONF()
1001 
1002 /* ***************> */
1003 /* TUPSEIZECONF > */
1004 /* ***************> */
1005 void Dblqh::execTUPSEIZECONF(Signal* signal)
1006 {
1007  jamEntry();
1008  tcConnectptr.i = signal->theData[0];
1009  ptrCheckGuard(tcConnectptr, ctcConnectrecFileSize, tcConnectionrec);
1010  tcConnectptr.p->tupConnectrec = signal->theData[1];
1011 /* ------- CHECK IF THERE ARE MORE CONNECTIONS TO BE CONNECTED ------- */
1012  tcConnectptr.i = tcConnectptr.p->nextTcConnectrec;
1013  if (tcConnectptr.i != RNIL) {
1014  jam();
1015  ptrCheckGuard(tcConnectptr, ctcConnectrecFileSize, tcConnectionrec);
1016  moreconnectionsLab(signal);
1017  return;
1018  }//if
1019 /* ALL LQH_CONNECT RECORDS ARE CONNECTED TO ACC AND TUP ---- */
1020  sendNdbSttorryLab(signal);
1021  return;
1022 }//Dblqh::execTUPSEIZECONF()
1023 
1024 /* +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ */
1025 /* +++++++ START PHASE 4 +++++++ */
1026 /* */
1027 /* CONNECT LQH WITH LQH. */
1028 /* CONNECT EACH LQH WITH EVERY LQH IN THE DATABASE SYSTEM. */
1029 /* IF INITIAL START THEN CREATE THE FRAGMENT LOG FILES */
1030 /*IF SYSTEM RESTART OR NODE RESTART THEN OPEN THE FRAGMENT LOG FILES AND */
1031 /*FIND THE END OF THE LOG FILES. */
1032 /* +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ */
1033 /* WAIT UNTIL ADD NODE PROCESSES ARE COMPLETED */
1034 /* IF INITIAL START ALSO WAIT FOR LOG FILES TO INITIALISED */
1035 /*START TIME SUPERVISION OF LOG FILES. WE HAVE TO WRITE LOG PAGES TO DISK */
1036 /*EVEN IF THE PAGES ARE NOT FULL TO ENSURE THAT THEY COME TO DISK ASAP. */
1037 /* +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ */
1038 void Dblqh::startphase3Lab(Signal* signal)
1039 {
1040  caddNodeState = ZTRUE;
1041 /* ***************<< */
1042 /* READ_NODESREQ < */
1043 /* ***************<< */
1044  cinitialStartOngoing = ZTRUE;
1045 
1046  switch(cstartType){
1047  case NodeState::ST_NODE_RESTART:
1048  case NodeState::ST_SYSTEM_RESTART:
1049  jam();
1050  for (logPartPtr.i = 0; logPartPtr.i < clogPartFileSize; logPartPtr.i++)
1051  {
1052  jam();
1053  LogFileRecordPtr locLogFilePtr;
1054  ptrAss(logPartPtr, logPartRecord);
1055  locLogFilePtr.i = logPartPtr.p->firstLogfile;
1056  ptrCheckGuard(locLogFilePtr, clogFileFileSize, logFileRecord);
1057  locLogFilePtr.p->logFileStatus = LogFileRecord::OPEN_SR_FRONTPAGE;
1058  openFileRw(signal, locLogFilePtr);
1059  }//for
1060  break;
1061  case NodeState::ST_INITIAL_START:
1062  case NodeState::ST_INITIAL_NODE_RESTART:
1063  jam();
1064  for (logPartPtr.i = 0; logPartPtr.i < clogPartFileSize; logPartPtr.i++)
1065  {
1066  jam();
1067  signal->theData[0] = ZINIT_FOURTH;
1068  signal->theData[1] = logPartPtr.i;
1069  sendSignal(cownref, GSN_CONTINUEB, signal, 2, JBB);
1070  }
1071  break;
1072  }
1073 
1074  signal->theData[0] = cownref;
1075  sendSignal(NDBCNTR_REF, GSN_READ_NODESREQ, signal, 1, JBB);
1076  return;
1077 }//Dblqh::startphase3Lab()
1078 
1079 /* ****************** */
1080 /* READ_NODESCONF > */
1081 /* ****************** */
1082 void Dblqh::execREAD_NODESCONF(Signal* signal)
1083 {
1084  jamEntry();
1085 
1086  ReadNodesConf * const readNodes = (ReadNodesConf *)&signal->theData[0];
1087  cnoOfNodes = readNodes->noOfNodes;
1088 
1089  unsigned ind = 0;
1090  unsigned i = 0;
1091  for (i = 1; i < MAX_NDB_NODES; i++) {
1092  jam();
1093  if (NdbNodeBitmask::get(readNodes->allNodes, i)) {
1094  jam();
1095  cnodeData[ind] = i;
1096  cnodeStatus[ind] = NdbNodeBitmask::get(readNodes->inactiveNodes, i);
1097 
1098  {
1099  HostRecordPtr Thostptr;
1100  Thostptr.i = i;
1101  ptrCheckGuard(Thostptr, chostFileSize, hostRecord);
1102  Thostptr.p->nodestatus = cnodeStatus[ind];
1103  }
1104 
1105  //readNodes->getVersionId(i, readNodes->theVersionIds) not used
1106  if (!NodeBitmask::get(readNodes->inactiveNodes, i))
1107  {
1108  jam();
1109  m_sr_nodes.set(i);
1110  }
1111  ind++;
1112  }//if
1113  }//for
1114  ndbrequire(ind == cnoOfNodes);
1115  ndbrequire(cnoOfNodes >= 1 && cnoOfNodes < MAX_NDB_NODES);
1116  ndbrequire(!(cnoOfNodes == 1 && cstartType == NodeState::ST_NODE_RESTART));
1117 
1118 #ifdef ERROR_INSERT
1119  c_master_node_id = readNodes->masterNodeId;
1120 #endif
1121 
1122  caddNodeState = ZFALSE;
1123  if (cstartType == NodeState::ST_SYSTEM_RESTART)
1124  {
1125  jam();
1126  sendNdbSttorryLab(signal);
1127  return;
1128  }
1129  else if (cstartType == NodeState::ST_NODE_RESTART)
1130  {
1131  jam();
1132  SET_TRACENR_FLAG;
1133  m_sr_nodes.clear();
1134  m_sr_nodes.set(getOwnNodeId());
1135  sendNdbSttorryLab(signal);
1136  return;
1137  }
1138  SET_TRACENR_FLAG;
1139 
1140  checkStartCompletedLab(signal);
1141  return;
1142 }//Dblqh::execREAD_NODESCONF()
1143 
1144 void Dblqh::checkStartCompletedLab(Signal* signal)
1145 {
1146  if (caddNodeState == ZFALSE) {
1147  if (cinitialStartOngoing == ZFALSE) {
1148  jam();
1149  sendNdbSttorryLab(signal);
1150  return;
1151  }//if
1152  }//if
1153  return;
1154 }//Dblqh::checkStartCompletedLab()
1155 
1156 void Dblqh::startphase4Lab(Signal* signal)
1157 {
1158  sendNdbSttorryLab(signal);
1159  return;
1160 }//Dblqh::startphase4Lab()
1161 
1162 /* ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ */
1163 /* SET CONCURRENCY OF LOCAL CHECKPOINTS TO BE USED AFTER SYSTEM RESTART. */
1164 /* ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ */
1165 void Dblqh::startphase6Lab(Signal* signal)
1166 {
1167  cstartPhase = ZNIL;
1168  cstartType = ZNIL;
1169  CLEAR_TRACENR_FLAG;
1170  sendNdbSttorryLab(signal);
1171  return;
1172 }//Dblqh::startphase6Lab()
1173 
1174 void Dblqh::sendNdbSttorryLab(Signal* signal)
1175 {
1176  signal->theData[0] = cownref;
1177  BlockReference cntrRef = !isNdbMtLqh() ? NDBCNTR_REF : DBLQH_REF;
1178  sendSignal(cntrRef, GSN_NDB_STTORRY, signal, 1, JBB);
1179  return;
1180 }//Dblqh::sendNdbSttorryLab()
1181 
1182 void Dblqh::sendsttorryLab(Signal* signal)
1183 {
1184 /* *********<< */
1185 /* STTORRY < */
1186 /* *********<< */
1187  signal->theData[0] = csignalKey; /* SIGNAL KEY */
1188  signal->theData[1] = 3; /* BLOCK CATEGORY */
1189  signal->theData[2] = 2; /* SIGNAL VERSION NUMBER */
1190  signal->theData[3] = ZSTART_PHASE1;
1191  signal->theData[4] = 4;
1192  signal->theData[5] = 255;
1193  BlockReference cntrRef = !isNdbMtLqh() ? NDBCNTR_REF : DBLQH_REF;
1194  sendSignal(cntrRef, GSN_STTORRY, signal, 6, JBB);
1195  return;
1196 }//Dblqh::sendsttorryLab()
1197 
1198 /* ***************>> */
1199 /* READ_NODESREF > */
1200 /* ***************>> */
1201 void Dblqh::execREAD_NODESREF(Signal* signal)
1202 {
1203  jamEntry();
1204  ndbrequire(false);
1205 }//Dblqh::execREAD_NODESREF()
1206 
1207 /* *************** */
1208 /* SIZEALT_REP > */
1209 /* *************** */
1210 void Dblqh::execREAD_CONFIG_REQ(Signal* signal)
1211 {
1212  const ReadConfigReq * req = (ReadConfigReq*)signal->getDataPtr();
1213  Uint32 ref = req->senderRef;
1214  Uint32 senderData = req->senderData;
1215  ndbrequire(req->noOfParameters == 0);
1216 
1217  jamEntry();
1218 
1219  const ndb_mgm_configuration_iterator * p =
1220  m_ctx.m_config.getOwnConfigIterator();
1221  ndbrequire(p != 0);
1222 
1223  cnoLogFiles = 8;
1224  ndbrequire(!ndb_mgm_get_int_parameter(p, CFG_DB_NO_REDOLOG_FILES,
1225  &cnoLogFiles));
1226  ndbrequire(cnoLogFiles > 0);
1227 
1228  Uint32 log_page_size= 0;
1229  ndb_mgm_get_int_parameter(p, CFG_DB_REDO_BUFFER,
1230  &log_page_size);
1231 
1235  clogPageFileSize= (log_page_size / sizeof(LogPageRecord));
1236  Uint32 mega_byte_part= clogPageFileSize & 15;
1237  if (mega_byte_part != 0) {
1238  jam();
1239  clogPageFileSize+= (16 - mega_byte_part);
1240  }
1241 
1242  /* maximum number of log file operations */
1243  clfoFileSize = clogPageFileSize;
1244  if (clfoFileSize < ZLFO_MIN_FILE_SIZE)
1245  clfoFileSize = ZLFO_MIN_FILE_SIZE;
1246 
1247  ndbrequire(!ndb_mgm_get_int_parameter(p, CFG_LQH_TABLE, &ctabrecFileSize));
1248  ndbrequire(!ndb_mgm_get_int_parameter(p, CFG_LQH_TC_CONNECT,
1249  &ctcConnectrecFileSize));
1250  clogFileFileSize = 4 * cnoLogFiles;
1251  ndbrequire(!ndb_mgm_get_int_parameter(p, CFG_LQH_SCAN, &cscanrecFileSize));
1252  cmaxAccOps = cscanrecFileSize * MAX_PARALLEL_OP_PER_SCAN;
1253 
1254  ndbrequire(!ndb_mgm_get_int_parameter(p, CFG_DB_DISCLESS, &c_diskless));
1255  c_o_direct = true;
1256  ndb_mgm_get_int_parameter(p, CFG_DB_O_DIRECT, &c_o_direct);
1257 
1258  m_use_om_init = 0;
1259  {
1260  const char * conf = 0;
1261  if (!ndb_mgm_get_string_parameter(p, CFG_DB_INIT_REDO, &conf) && conf)
1262  {
1263  jam();
1264  if (strcasecmp(conf, "sparse") == 0)
1265  {
1266  jam();
1267  m_use_om_init = 0;
1268  }
1269  else if (strcasecmp(conf, "full") == 0)
1270  {
1271  jam();
1272  m_use_om_init = 1;
1273  }
1274  }
1275  }
1276 
1277  Uint32 tmp= 0;
1278  ndbrequire(!ndb_mgm_get_int_parameter(p, CFG_LQH_FRAG, &tmp));
1279  c_fragment_pool.setSize(tmp);
1280 
1281  if (!ndb_mgm_get_int_parameter(p, CFG_DB_REDOLOG_FILE_SIZE,
1282  &clogFileSize))
1283  {
1284  // convert to mbyte
1285  clogFileSize = (clogFileSize + 1024*1024 - 1) / (1024 * 1024);
1286  ndbrequire(clogFileSize >= 4 && clogFileSize <= 1024);
1287  }
1288 
1289  m_startup_report_frequency = 0;
1290  ndb_mgm_get_int_parameter(p,CFG_DB_STARTUP_REPORT_FREQUENCY,
1291  &m_startup_report_frequency);
1292  totalLogFiles = 4 * cnoLogFiles;
1293  totallogMBytes = totalLogFiles * clogFileSize;
1294 
1295  cmaxLogFilesInPageZero = (ZPAGE_SIZE - ZPAGE_HEADER_SIZE - 128) /
1296  (ZFD_MBYTE_SIZE * clogFileSize);
1297 
1305  if (cmaxLogFilesInPageZero > 40)
1306  {
1307  jam();
1308  cmaxLogFilesInPageZero = 40;
1309  }
1310  else
1311  {
1312  ndbrequire(cmaxLogFilesInPageZero);
1313  }
1314 
1315  {
1316  Uint32 config_val = 20;
1317  ndb_mgm_get_int_parameter(p, CFG_DB_LCP_INTERVAL, &config_val);
1318  config_val = config_val > 31 ? 31 : config_val;
1319 
1320  const Uint32 mb = 1024 * 1024;
1321 
1322  // perform LCP after this amout of mbytes written
1323  const Uint64 config_mbytes = ((Uint64(4) << config_val) + mb - 1) / mb;
1324  const Uint64 totalmb = Uint64(cnoLogFiles) * Uint64(clogFileSize);
1325  if (totalmb > config_mbytes)
1326  {
1327  c_free_mb_force_lcp_limit = Uint32(totalmb - config_mbytes);
1328  }
1329  else
1330  {
1331  c_free_mb_force_lcp_limit = 0;
1332  }
1333 
1334  // No less than 33%
1335  Uint32 limit = Uint32(totalmb / 3);
1336  if (c_free_mb_force_lcp_limit < limit)
1337  {
1338  c_free_mb_force_lcp_limit = limit;
1339  }
1340  }
1341  c_free_mb_tail_problem_limit = 4; // If less than 4Mb set TAIL_PROBLEM
1342 
1343  ndb_mgm_get_int_parameter(p, CFG_DB_TRANSACTION_DEADLOCK_TIMEOUT,
1344  &cTransactionDeadlockDetectionTimeout);
1345 
1346  initRecords();
1347  initialiseRecordsLab(signal, 0, ref, senderData);
1348 
1349  c_max_redo_lag = 30;
1350  ndb_mgm_get_int_parameter(p, CFG_DB_REDO_OVERCOMMIT_LIMIT,
1351  &c_max_redo_lag);
1352 
1353  c_max_redo_lag_counter = 3;
1354  ndb_mgm_get_int_parameter(p, CFG_DB_REDO_OVERCOMMIT_COUNTER,
1355  &c_max_redo_lag_counter);
1356 
1357  c_max_parallel_scans_per_frag = 32;
1358  ndb_mgm_get_int_parameter(p, CFG_DB_PARALLEL_SCANS_PER_FRAG,
1359  &c_max_parallel_scans_per_frag);
1360 
1361  if (c_max_parallel_scans_per_frag > (256 - MAX_PARALLEL_SCANS_PER_FRAG) / 2)
1362  {
1363  jam();
1364  c_max_parallel_scans_per_frag = (256 - MAX_PARALLEL_SCANS_PER_FRAG) / 2;
1365  }
1366  return;
1367 }//Dblqh::execSIZEALT_REP()
1368 
1369 /* ########################################################################## */
1370 /* ####### ADD/DELETE FRAGMENT MODULE ####### */
1371 /* THIS MODULE IS USED BY DICTIONARY TO CREATE NEW FRAGMENTS AND DELETE */
1372 /* OLD FRAGMENTS. */
1373 /* */
1374 /* ########################################################################## */
1375 /* -------------------------------------------------------------- */
1376 /* FRAG REQ */
1377 /* -------------------------------------------------------------- */
1378 /* *********************************************************> */
1379 /* LQHFRAGREQ: Create new fragments for a table. Sender DICT */
1380 /* *********************************************************> */
1381 
1382 // this unbelievable mess could be replaced by one signal to LQH
1383 // and execute direct to local DICT to get everything at once
1384 void
1385 Dblqh::execCREATE_TAB_REQ(Signal* signal)
1386 {
1387  CreateTabReq* req = (CreateTabReq*)signal->getDataPtr();
1388  tabptr.i = req->tableId;
1389  ptrCheckGuard(tabptr, ctabrecFileSize, tablerec);
1390 
1391  Uint32 senderRef = req->senderRef;
1392  Uint32 senderData = req->senderData;
1393 
1394  if (tabptr.p->tableStatus != Tablerec::NOT_DEFINED)
1395  {
1396  jam();
1397  CreateTabRef* ref = (CreateTabRef*)signal->getDataPtrSend();
1398  ref->senderData = senderData;
1399  ref->senderRef = reference();
1400  ref->errorCode = CreateTableRef::TableAlreadyExist;
1401  sendSignal(senderRef, GSN_CREATE_TAB_REF, signal,
1402  CreateTabRef::SignalLength, JBB);
1403  return;
1404  }
1405 
1406  seizeAddfragrec(signal);
1407  addfragptr.p->m_createTabReq = *req;
1408  req = &addfragptr.p->m_createTabReq;
1409 
1410  tabptr.p->tableStatus = Tablerec::ADD_TABLE_ONGOING;
1411  tabptr.p->tableType = req->tableType;
1412  tabptr.p->primaryTableId = (req->primaryTableId == RNIL ? tabptr.i :
1413  req->primaryTableId);
1414  tabptr.p->schemaVersion = req->tableVersion;
1415  tabptr.p->m_disk_table= 0;
1416 
1417  addfragptr.p->addfragStatus = AddFragRecord::WAIT_TUP;
1418  sendCreateTabReq(signal, addfragptr);
1419 }
1420 
1421 void
1422 Dblqh::sendCreateTabReq(Signal* signal, AddFragRecordPtr addfragptr)
1423 {
1424  TablerecPtr tabPtr;
1425  tabPtr.i = addfragptr.p->m_createTabReq.tableId;
1426  ptrCheckGuard(tabPtr, ctabrecFileSize, tablerec);
1427 
1428  CreateTabReq* req = (CreateTabReq*)signal->getDataPtrSend();
1429  * req = addfragptr.p->m_createTabReq;
1430 
1431  req->senderRef = reference();
1432  req->senderData = addfragptr.i;
1433 
1434  Uint32 ref = calcInstanceBlockRef(DBTUP);
1435  switch(addfragptr.p->addfragStatus){
1436  case AddFragRecord::WAIT_TUP:
1437  if (DictTabInfo::isOrderedIndex(tabPtr.p->tableType))
1438  {
1439  jam();
1440  req->noOfAttributes = 1;
1441  req->noOfKeyAttr = 1;
1442  req->noOfNullAttributes = 0;
1443  }
1444  break;
1445  case AddFragRecord::WAIT_TUX:
1446  jam();
1447  ndbrequire(req->noOfAttributes >= 2);
1448  req->noOfAttributes--;
1449  ref = calcInstanceBlockRef(DBTUX);
1450  break;
1451  default:
1452  jamLine(addfragptr.p->addfragStatus);
1453  ndbrequire(false);
1454  }
1455 
1456  sendSignal(ref, GSN_CREATE_TAB_REQ, signal,
1457  CreateTabReq::SignalLengthLDM, JBB);
1458 }
1459 
1460 void
1461 Dblqh::execCREATE_TAB_REF(Signal* signal)
1462 {
1463  jamEntry();
1464 
1465  CreateTabRef * ref = (CreateTabRef*)signal->getDataPtr();
1466  addfragptr.i = ref->senderData;
1467  ptrCheckGuard(addfragptr, caddfragrecFileSize, addFragRecord);
1468 
1469  abortAddFragOps(signal);
1470 
1471  ref->senderRef = reference();
1472  ref->senderData = addfragptr.p->m_createTabReq.senderData;
1473  sendSignal(addfragptr.p->m_createTabReq.senderRef,
1474  GSN_CREATE_TAB_REF, signal, CreateTabConf::SignalLength, JBB);
1475 
1476  releaseAddfragrec(signal);
1477 }
1478 
1479 void
1480 Dblqh::execCREATE_TAB_CONF(Signal* signal)
1481 {
1482  jamEntry();
1483  CreateTabConf* conf = (CreateTabConf*)signal->getDataPtr();
1484  addfragptr.i = conf->senderData;
1485  ptrCheckGuard(addfragptr, caddfragrecFileSize, addFragRecord);
1486 
1487  TablerecPtr tabPtr;
1488  tabPtr.i = addfragptr.p->m_createTabReq.tableId;
1489  ptrCheckGuard(tabPtr, ctabrecFileSize, tablerec);
1490 
1491  switch(addfragptr.p->addfragStatus){
1492  case AddFragRecord::WAIT_TUP:
1493  jam();
1494  addfragptr.p->tupConnectptr = conf->tupConnectPtr;
1495  if (DictTabInfo::isOrderedIndex(tabPtr.p->tableType))
1496  {
1497  jam();
1498  addfragptr.p->addfragStatus = AddFragRecord::WAIT_TUX;
1499  sendCreateTabReq(signal, addfragptr);
1500  return;
1501  }
1502  break;
1503  case AddFragRecord::WAIT_TUX:
1504  jam();
1505  addfragptr.p->tuxConnectptr = conf->tuxConnectPtr;
1506  break;
1507  default:
1508  jamLine(addfragptr.p->addfragStatus);
1509  ndbrequire(false);
1510  }
1511 
1512  addfragptr.p->addfragStatus = AddFragRecord::WAIT_ADD_ATTR;
1513 
1514  conf->senderRef = reference();
1515  conf->senderData = addfragptr.p->m_createTabReq.senderData;
1516  conf->lqhConnectPtr = addfragptr.i;
1517  sendSignal(addfragptr.p->m_createTabReq.senderRef,
1518  GSN_CREATE_TAB_CONF, signal, CreateTabConf::SignalLength, JBB);
1519 }
1520 
1521 /* ************************************************************************> */
1522 /* LQHADDATTRREQ: Request from DICT to create attributes for the new table. */
1523 /* ************************************************************************> */
1524 void Dblqh::execLQHADDATTREQ(Signal* signal)
1525 {
1526  jamEntry();
1527  LqhAddAttrReq * req = (LqhAddAttrReq*)signal->getDataPtr();
1528 
1529  addfragptr.i = req->lqhFragPtr;
1530  ptrCheckGuard(addfragptr, caddfragrecFileSize, addFragRecord);
1531 
1532  addfragptr.p->m_addAttrReq = * req;
1533 
1534  const Uint32 tnoOfAttr = req->noOfAttributes;
1535  const Uint32 numSections = signal->getNoOfSections();
1536  bool isLongReq= ( numSections != 0 );
1537  addfragptr.p->defValSectionI = RNIL;
1538  addfragptr.p->defValNextPos = 0;
1539 
1540  if (isLongReq)
1541  {
1542  SectionHandle handle(this, signal);
1543  SegmentedSectionPtr defValSection;
1544  handle.getSection(defValSection, LqhAddAttrReq::DEFAULT_VALUE_SECTION_NUM);
1545  addfragptr.p->defValSectionI = defValSection.i;
1546  addfragptr.p->defValNextPos = 0;
1547  //Don't free Section here. Section is freed after default values are trasfered to TUP
1548  handle.clear();
1549  }
1550 
1551  ndbrequire(addfragptr.p->addfragStatus == AddFragRecord::WAIT_ADD_ATTR);
1552  ndbrequire((tnoOfAttr != 0) && (tnoOfAttr <= LqhAddAttrReq::MAX_ATTRIBUTES));
1553  addfragptr.p->totalAttrReceived += tnoOfAttr;
1554  ndbrequire(addfragptr.p->totalAttrReceived <=
1555  addfragptr.p->m_createTabReq.noOfAttributes);
1556 
1557  addfragptr.p->attrReceived = tnoOfAttr;
1558 
1559  TablerecPtr tabPtr;
1560  tabPtr.i = addfragptr.p->m_createTabReq.tableId;
1561  ptrCheckGuard(tabPtr, ctabrecFileSize, tablerec);
1562 
1563  for (Uint32 i = 0; i < tnoOfAttr; i++)
1564  {
1565  if(AttributeDescriptor::getDiskBased(req->attributes[i].attrDescriptor))
1566  {
1567  jam();
1568  tabPtr.p->m_disk_table = 1;
1569  }
1570  }//for
1571 
1572  addfragptr.p->attrSentToTup = 0;
1573  addfragptr.p->addfragStatus = AddFragRecord::TUP_ATTR_WAIT;
1574  sendAddAttrReq(signal);
1575 }//Dblqh::execLQHADDATTREQ()
1576 
1577 /* *********************>> */
1578 /* TUP_ADD_ATTCONF > */
1579 /* *********************>> */
1580 void Dblqh::execTUP_ADD_ATTCONF(Signal* signal)
1581 {
1582  jamEntry();
1583  addfragptr.i = signal->theData[0];
1584  // implies that operation was released on the other side
1585  const bool lastAttr = signal->theData[1];
1586  ptrCheckGuard(addfragptr, caddfragrecFileSize, addFragRecord);
1587 
1588  tabptr.i = addfragptr.p->m_createTabReq.tableId;
1589  ptrCheckGuard(tabptr, ctabrecFileSize, tablerec);
1590 
1591  Uint32 noOfAttr = addfragptr.p->m_createTabReq.noOfAttributes;
1592 
1593  switch (addfragptr.p->addfragStatus) {
1594  case AddFragRecord::TUP_ATTR_WAIT:
1595  if (DictTabInfo::isOrderedIndex(tabptr.p->tableType))
1596  {
1597  addfragptr.p->addfragStatus = AddFragRecord::TUX_ATTR_WAIT;
1598  sendAddAttrReq(signal);
1599  break;
1600  }
1601  goto done_with_attr;
1602  break;
1603  case AddFragRecord::TUX_ATTR_WAIT:
1604  jam();
1605  if (lastAttr)
1606  addfragptr.p->tuxConnectptr = RNIL;
1607  goto done_with_attr;
1608  break;
1609  done_with_attr:
1610  addfragptr.p->attrSentToTup = addfragptr.p->attrSentToTup + 1;
1611  ndbrequire(addfragptr.p->attrSentToTup <= addfragptr.p->attrReceived);
1612  ndbrequire(addfragptr.p->totalAttrReceived <= noOfAttr);
1613  if (addfragptr.p->attrSentToTup < addfragptr.p->attrReceived)
1614  {
1615  // more in this batch
1616  jam();
1617  addfragptr.p->addfragStatus = AddFragRecord::TUP_ATTR_WAIT;
1618  sendAddAttrReq(signal);
1619  return;
1620  }
1621 
1622  if (addfragptr.p->defValSectionI != RNIL)
1623  {
1624  releaseSection(addfragptr.p->defValSectionI);
1625  addfragptr.p->defValNextPos = 0;
1626  addfragptr.p->defValSectionI = RNIL;
1627  }
1628 
1629  { // Reply
1630  LqhAddAttrConf *const conf = (LqhAddAttrConf*)signal->getDataPtrSend();
1631  conf->senderData = addfragptr.p->m_addAttrReq.senderData;
1632  conf->senderAttrPtr = addfragptr.p->m_addAttrReq.senderAttrPtr;
1633  sendSignal(addfragptr.p->m_createTabReq.senderRef,
1634  GSN_LQHADDATTCONF, signal, LqhAddAttrConf::SignalLength, JBB);
1635  }
1636  if (addfragptr.p->totalAttrReceived < noOfAttr)
1637  {
1638  jam();
1639  addfragptr.p->addfragStatus = AddFragRecord::WAIT_ADD_ATTR;
1640  }
1641  else
1642  {
1643  jam();
1644  releaseAddfragrec(signal);
1645  }
1646  break;
1647  default:
1648  ndbrequire(false);
1649  break;
1650  }
1651 }
1652 
1653 /* **********************>> */
1654 /* TUX_ADD_ATTRCONF > */
1655 /* **********************>> */
1656 void Dblqh::execTUX_ADD_ATTRCONF(Signal* signal)
1657 {
1658  jamEntry();
1659  execTUP_ADD_ATTCONF(signal);
1660 }//Dblqh::execTUX_ADD_ATTRCONF
1661 
1662 /* *********************> */
1663 /* TUP_ADD_ATTREF > */
1664 /* *********************> */
1665 void Dblqh::execTUP_ADD_ATTRREF(Signal* signal)
1666 {
1667  jamEntry();
1668  addfragptr.i = signal->theData[0];
1669  ptrCheckGuard(addfragptr, caddfragrecFileSize, addFragRecord);
1670  Uint32 errorCode = terrorCode = signal->theData[1];
1671 
1672  abortAddFragOps(signal);
1673 
1674  // operation was released on the other side
1675  switch (addfragptr.p->addfragStatus) {
1676  case AddFragRecord::TUP_ATTR_WAIT:
1677  jam();
1678  break;
1679  case AddFragRecord::TUX_ATTR_WAIT:
1680  jam();
1681  break;
1682  default:
1683  ndbrequire(false);
1684  break;
1685  }
1686 
1687  if (addfragptr.p->defValSectionI != RNIL)
1688  {
1689  releaseSection(addfragptr.p->defValSectionI);
1690  addfragptr.p->defValNextPos = 0;
1691  addfragptr.p->defValSectionI = RNIL;
1692  }
1693 
1694  const Uint32 Ref = addfragptr.p->m_createTabReq.senderRef;
1695  const Uint32 senderData = addfragptr.p->m_addAttrReq.senderData;
1696 
1697  releaseAddfragrec(signal);
1698 
1699  LqhAddAttrRef *const ref = (LqhAddAttrRef*)signal->getDataPtrSend();
1700  ref->senderData = senderData;
1701  ref->errorCode = errorCode;
1702  sendSignal(Ref, GSN_LQHADDATTREF, signal,
1703  LqhAddAttrRef::SignalLength, JBB);
1704 }//Dblqh::execTUP_ADD_ATTRREF()
1705 
1706 /* **********************> */
1707 /* TUX_ADD_ATTRREF > */
1708 /* **********************> */
1709 void Dblqh::execTUX_ADD_ATTRREF(Signal* signal)
1710 {
1711  jamEntry();
1712  execTUP_ADD_ATTRREF(signal);
1713 }//Dblqh::execTUX_ADD_ATTRREF
1714 
1715 /*
1716  * Add attribute in TUP or TUX. Called up to 4 times.
1717  */
1718 void
1719 Dblqh::sendAddAttrReq(Signal* signal)
1720 {
1721  arrGuard(addfragptr.p->attrSentToTup, LqhAddAttrReq::MAX_ATTRIBUTES);
1723  addfragptr.p->m_addAttrReq.attributes[addfragptr.p->attrSentToTup];
1724 
1725  const Uint32 attrId = entry.attrId & 0xffff;
1726  const Uint32 primaryAttrId = entry.attrId >> 16;
1727 
1728  tabptr.i = addfragptr.p->m_createTabReq.tableId;
1729  ptrCheckGuard(tabptr, ctabrecFileSize, tablerec);
1730 
1731  if (addfragptr.p->addfragStatus == AddFragRecord::TUP_ATTR_WAIT)
1732  {
1733  if (DictTabInfo::isTable(tabptr.p->tableType) ||
1734  DictTabInfo::isHashIndex(tabptr.p->tableType) ||
1735  (DictTabInfo::isOrderedIndex(tabptr.p->tableType) &&
1736  primaryAttrId == ZNIL)) {
1737  jam();
1738  TupAddAttrReq* const tupreq = (TupAddAttrReq*)signal->getDataPtrSend();
1739  tupreq->tupConnectPtr = addfragptr.p->tupConnectptr;
1740  tupreq->attrId = attrId;
1741  tupreq->attrDescriptor = entry.attrDescriptor;
1742  tupreq->extTypeInfo = entry.extTypeInfo;
1743  BlockReference tupRef = calcInstanceBlockRef(DBTUP);
1744 
1745  Uint32 sectionLen = 0;
1746  Uint32 startIndex = TupAddAttrReq::SignalLength;
1747  if (addfragptr.p->defValSectionI != RNIL)
1748  {
1749  SegmentedSectionPtr defValSection;
1750  getSection(defValSection, addfragptr.p->defValSectionI);
1751 
1752  SectionReader defValueReader(defValSection, getSectionSegmentPool());
1753  Uint32 defSectionWords = defValueReader.getSize();
1754 
1755  ndbrequire(defValueReader.step(addfragptr.p->defValNextPos));
1756 
1757  Uint32 defValueHeader;
1758  ndbrequire(defValueReader.peekWord(&defValueHeader));
1759 
1760  AttributeHeader ah(defValueHeader);
1761  Uint32 defValueLen = ah.getByteSize();
1762  Uint32 defValueWords = ((defValueLen +3)/4) + 1;
1763  Uint32 *dst = &signal->theData[startIndex];
1764  ndbassert(defSectionWords >= (addfragptr.p->defValNextPos + defValueWords));
1765  ndbrequire(defValueReader.getWords(dst, defValueWords));
1766  addfragptr.p->defValNextPos += defValueWords;
1767  sectionLen = defValueWords;
1768  }
1769 
1770  //A long section is attached when a default value is sent.
1771  if (sectionLen != 0)
1772  {
1773  LinearSectionPtr ptr[3];
1774  ptr[0].p= &signal->theData[startIndex];
1775  ptr[0].sz= sectionLen;
1776  sendSignal(tupRef, GSN_TUP_ADD_ATTRREQ,
1777  signal, TupAddAttrReq::SignalLength, JBB, ptr, 1);
1778  }
1779  else
1780  sendSignal(tupRef, GSN_TUP_ADD_ATTRREQ,
1781  signal, TupAddAttrReq::SignalLength, JBB);
1782 
1783  return;
1784  }
1785  if (DictTabInfo::isOrderedIndex(tabptr.p->tableType) &&
1786  primaryAttrId != ZNIL) {
1787  // this attribute is not for TUP
1788  jam();
1789  TupAddAttrConf* tupconf = (TupAddAttrConf*)signal->getDataPtrSend();
1790  tupconf->userPtr = addfragptr.i;
1791  tupconf->lastAttr = false;
1792  sendSignal(reference(), GSN_TUP_ADD_ATTCONF,
1793  signal, TupAddAttrConf::SignalLength, JBB);
1794  return;
1795  }
1796  }
1797 
1798  if (addfragptr.p->addfragStatus == AddFragRecord::TUX_ATTR_WAIT)
1799  {
1800  jam();
1801  if (DictTabInfo::isOrderedIndex(tabptr.p->tableType) &&
1802  primaryAttrId != ZNIL) {
1803  jam();
1804  TuxAddAttrReq* const tuxreq = (TuxAddAttrReq*)signal->getDataPtrSend();
1805  tuxreq->tuxConnectPtr = addfragptr.p->tuxConnectptr;
1806  tuxreq->notused1 = 0;
1807  tuxreq->attrId = attrId;
1808  tuxreq->attrDescriptor = entry.attrDescriptor;
1809  tuxreq->extTypeInfo = entry.extTypeInfo;
1810  tuxreq->primaryAttrId = primaryAttrId;
1811  BlockReference tuxRef = calcInstanceBlockRef(DBTUX);
1812  sendSignal(tuxRef, GSN_TUX_ADD_ATTRREQ,
1813  signal, TuxAddAttrReq::SignalLength, JBB);
1814  return;
1815  }
1816  if (DictTabInfo::isOrderedIndex(tabptr.p->tableType) &&
1817  primaryAttrId == ZNIL) {
1818  // this attribute is not for TUX
1819  jam();
1820  TuxAddAttrConf* tuxconf = (TuxAddAttrConf*)signal->getDataPtrSend();
1821  tuxconf->userPtr = addfragptr.i;
1822  tuxconf->lastAttr = false;
1823  sendSignal(reference(), GSN_TUX_ADD_ATTRCONF,
1824  signal, TuxAddAttrConf::SignalLength, JBB);
1825  return;
1826  }
1827  }
1828  ndbrequire(false);
1829 }//Dblqh::sendAddAttrReq
1830 
1831 void Dblqh::execLQHFRAGREQ(Signal* signal)
1832 {
1833  jamEntry();
1834  LqhFragReq copy = *(LqhFragReq*)signal->getDataPtr();
1835  LqhFragReq * req = &copy;
1836 
1837  tabptr.i = req->tableId;
1838  ptrCheckGuard(tabptr, ctabrecFileSize, tablerec);
1839 
1840  if (tabptr.p->tableStatus != Tablerec::ADD_TABLE_ONGOING &&
1841  (AlterTableReq::getAddFragFlag(req->changeMask) == 0))
1842  {
1843  jam();
1844  fragrefLab(signal, ZTAB_STATE_ERROR, req);
1845  return;
1846  }//if
1847 
1848  if (getFragmentrec(signal, req->fragId))
1849  {
1850  jam();
1851  fragrefLab(signal, terrorCode, req);
1852  return;
1853  }//if
1854 
1855  if (!insertFragrec(signal, req->fragId))
1856  {
1857  jam();
1858  fragrefLab(signal, terrorCode, req);
1859  return;
1860  }//if
1861 
1862  Uint32 copyType = req->requestInfo & 3;
1863  bool tempTable = ((req->requestInfo & LqhFragReq::TemporaryTable) != 0);
1864  initFragrec(signal, tabptr.i, req->fragId, copyType);
1865  fragptr.p->startGci = req->startGci;
1866  fragptr.p->newestGci = req->startGci;
1867  ndbrequire(tabptr.p->tableType < 256);
1868  fragptr.p->tableType = (Uint8)tabptr.p->tableType;
1869 
1870  {
1871  NdbLogPartInfo lpinfo(instance());
1872  Uint32 logPartNo = lpinfo.partNoFromId(req->logPartId);
1873  ndbrequire(lpinfo.partNoOwner(logPartNo));
1874 
1875  LogPartRecordPtr ptr;
1876  ptr.i = lpinfo.partNoIndex(logPartNo);
1877  ptrCheckGuard(ptr, clogPartFileSize, logPartRecord);
1878  ndbrequire(ptr.p->logPartNo == logPartNo);
1879 
1880  fragptr.p->m_log_part_ptr_i = ptr.i;
1881  fragptr.p->lqhInstanceKey = lpinfo.instanceKey(logPartNo);
1882  }
1883 
1884  if (DictTabInfo::isOrderedIndex(tabptr.p->tableType)) {
1885  jam();
1886  // find corresponding primary table fragment
1887  TablerecPtr tTablePtr;
1888  tTablePtr.i = tabptr.p->primaryTableId;
1889  ptrCheckGuard(tTablePtr, ctabrecFileSize, tablerec);
1890  FragrecordPtr tFragPtr;
1891  tFragPtr.i = RNIL;
1892  for (Uint32 i = 0; i < MAX_FRAG_PER_NODE; i++) {
1893  if (tTablePtr.p->fragid[i] == fragptr.p->fragId) {
1894  jam();
1895  tFragPtr.i = tTablePtr.p->fragrec[i];
1896  break;
1897  }
1898  }
1899  ndbrequire(tFragPtr.i != RNIL);
1900  // store it
1901  fragptr.p->tableFragptr = tFragPtr.i;
1902  }
1903  else
1904  {
1905  jam();
1906  fragptr.p->tableFragptr = fragptr.i;
1907  }
1908 
1909  if (tempTable)
1910  {
1911 //--------------------------------------------
1912 // reqinfo bit 3-4 = 2 means temporary table
1913 // without logging or checkpointing.
1914 //--------------------------------------------
1915  jam();
1916  fragptr.p->logFlag = Fragrecord::STATE_FALSE;
1917  fragptr.p->lcpFlag = Fragrecord::LCP_STATE_FALSE;
1918  }//if
1919 
1920  seizeAddfragrec(signal);
1921  addfragptr.p->m_lqhFragReq = * req;
1922  addfragptr.p->fragmentPtr = fragptr.i;
1923 
1924  if (DictTabInfo::isTable(tabptr.p->tableType) ||
1925  DictTabInfo::isHashIndex(tabptr.p->tableType)) {
1926  jam();
1927  AccFragReq* const accreq = (AccFragReq*)signal->getDataPtrSend();
1928  accreq->userPtr = addfragptr.i;
1929  accreq->userRef = cownref;
1930  accreq->tableId = tabptr.i;
1931  accreq->reqInfo = 0;
1932  accreq->fragId = req->fragId;
1933  accreq->localKeyLen = addfragptr.p->m_lqhFragReq.localKeyLength;
1934  accreq->maxLoadFactor = addfragptr.p->m_lqhFragReq.maxLoadFactor;
1935  accreq->minLoadFactor = addfragptr.p->m_lqhFragReq.minLoadFactor;
1936  accreq->kValue = addfragptr.p->m_lqhFragReq.kValue;
1937  accreq->lhFragBits = addfragptr.p->m_lqhFragReq.lh3DistrBits;
1938  accreq->lhDirBits = addfragptr.p->m_lqhFragReq.lh3PageBits;
1939  accreq->keyLength = addfragptr.p->m_lqhFragReq.keyLength;
1940  /* --------------------------------------------------------------------- */
1941  /* Send ACCFRAGREQ, when confirmation is received send 2 * TUPFRAGREQ to */
1942  /* create 2 tuple fragments on this node. */
1943  /* --------------------------------------------------------------------- */
1944  addfragptr.p->addfragStatus = AddFragRecord::ACC_ADDFRAG;
1945  sendSignal(fragptr.p->accBlockref, GSN_ACCFRAGREQ,
1946  signal, AccFragReq::SignalLength, JBB);
1947  return;
1948  }
1949  if (DictTabInfo::isOrderedIndex(tabptr.p->tableType)) {
1950  jam();
1951  addfragptr.p->addfragStatus = AddFragRecord::WAIT_TUP;
1952  sendAddFragReq(signal);
1953  return;
1954  }
1955  ndbrequire(false);
1956 }//Dblqh::execLQHFRAGREQ()
1957 
1958 /* *************** */
1959 /* ACCFRAGCONF > */
1960 /* *************** */
1961 void Dblqh::execACCFRAGCONF(Signal* signal)
1962 {
1963  jamEntry();
1964  addfragptr.i = signal->theData[0];
1965  Uint32 taccConnectptr = signal->theData[1];
1966  //Uint32 fragId1 = signal->theData[2];
1967  Uint32 accFragPtr1 = signal->theData[4];
1968  ptrCheckGuard(addfragptr, caddfragrecFileSize, addFragRecord);
1969  ndbrequire(addfragptr.p->addfragStatus == AddFragRecord::ACC_ADDFRAG);
1970 
1971  addfragptr.p->accConnectptr = taccConnectptr;
1972  fragptr.i = addfragptr.p->fragmentPtr;
1973  c_fragment_pool.getPtr(fragptr);
1974  fragptr.p->accFragptr = accFragPtr1;
1975 
1976  addfragptr.p->addfragStatus = AddFragRecord::WAIT_TUP;
1977  sendAddFragReq(signal);
1978 }//Dblqh::execACCFRAGCONF()
1979 
1980 /* *************** */
1981 /* TUPFRAGCONF > */
1982 /* *************** */
1983 void Dblqh::execTUPFRAGCONF(Signal* signal)
1984 {
1985  jamEntry();
1986  addfragptr.i = signal->theData[0];
1987  Uint32 tupConnectptr = signal->theData[1];
1988  Uint32 tupFragPtr = signal->theData[2]; /* TUP FRAGMENT POINTER */
1989  //Uint32 localFragId = signal->theData[3]; /* LOCAL FRAGMENT ID */
1990  ptrCheckGuard(addfragptr, caddfragrecFileSize, addFragRecord);
1991  fragptr.i = addfragptr.p->fragmentPtr;
1992  c_fragment_pool.getPtr(fragptr);
1993  tabptr.i = fragptr.p->tabRef;
1994  ptrCheckGuard(tabptr, ctabrecFileSize, tablerec);
1995  fragptr.p->tupFragptr = tupFragPtr;
1996  switch (addfragptr.p->addfragStatus) {
1997  case AddFragRecord::WAIT_TUP:
1998  jam();
1999  fragptr.p->tupFragptr = tupFragPtr;
2000  addfragptr.p->tupConnectptr = tupConnectptr;
2001  if (DictTabInfo::isOrderedIndex(tabptr.p->tableType))
2002  {
2003  addfragptr.p->addfragStatus = AddFragRecord::WAIT_TUX;
2004  sendAddFragReq(signal);
2005  break;
2006  }
2007  goto done_with_frag;
2008  break;
2009  case AddFragRecord::WAIT_TUX:
2010  jam();
2011  fragptr.p->tuxFragptr = tupFragPtr;
2012  addfragptr.p->tuxConnectptr = tupConnectptr;
2013  goto done_with_frag;
2014  break;
2015  done_with_frag:
2016  /* ---------------------------------------------------------------- */
2017  /* Finished create of fragments. Now ready for creating attributes. */
2018  /* ---------------------------------------------------------------- */
2019  fragptr.p->fragStatus = Fragrecord::FSACTIVE;
2020  {
2021  LqhFragConf* conf = (LqhFragConf*)signal->getDataPtrSend();
2022  conf->senderData = addfragptr.p->m_lqhFragReq.senderData;
2023  conf->lqhFragPtr = RNIL;
2024  conf->tableId = addfragptr.p->m_lqhFragReq.tableId;
2025  conf->fragId = fragptr.p->fragId;
2026  conf->changeMask = addfragptr.p->m_lqhFragReq.changeMask;
2027  sendSignal(addfragptr.p->m_lqhFragReq.senderRef, GSN_LQHFRAGCONF,
2028  signal, LqhFragConf::SignalLength, JBB);
2029  }
2030  releaseAddfragrec(signal);
2031  break;
2032  default:
2033  ndbrequire(false);
2034  break;
2035  }
2036 }//Dblqh::execTUPFRAGCONF()
2037 
2038 /* *************** */
2039 /* TUXFRAGCONF > */
2040 /* *************** */
2041 void Dblqh::execTUXFRAGCONF(Signal* signal)
2042 {
2043  jamEntry();
2044  execTUPFRAGCONF(signal);
2045 }//Dblqh::execTUXFRAGCONF
2046 
2047 /*
2048  * Add fragment in TUP or TUX. Called up to 4 times.
2049  */
2050 void
2051 Dblqh::sendAddFragReq(Signal* signal)
2052 {
2053  fragptr.i = addfragptr.p->fragmentPtr;
2054  c_fragment_pool.getPtr(fragptr);
2055  tabptr.i = fragptr.p->tabRef;
2056  ptrCheckGuard(tabptr, ctabrecFileSize, tablerec);
2057  if (addfragptr.p->addfragStatus == AddFragRecord::WAIT_TUP)
2058  {
2059  TupFragReq* const tupFragReq = (TupFragReq*)signal->getDataPtrSend();
2060  tupFragReq->userPtr = addfragptr.i;
2061  tupFragReq->userRef = cownref;
2062  tupFragReq->reqInfo = 0; /* ADD TABLE */
2063  tupFragReq->tableId = tabptr.i;
2064  tupFragReq->fragId = addfragptr.p->m_lqhFragReq.fragId;
2065  tupFragReq->tablespaceid = addfragptr.p->m_lqhFragReq.tablespace_id;
2066  tupFragReq->maxRowsHigh = addfragptr.p->m_lqhFragReq.maxRowsHigh;
2067  tupFragReq->maxRowsLow = addfragptr.p->m_lqhFragReq.maxRowsLow;
2068  tupFragReq->minRowsHigh = addfragptr.p->m_lqhFragReq.minRowsHigh;
2069  tupFragReq->minRowsLow = addfragptr.p->m_lqhFragReq.minRowsLow;
2070  tupFragReq->changeMask = addfragptr.p->m_lqhFragReq.changeMask;
2071  sendSignal(fragptr.p->tupBlockref, GSN_TUPFRAGREQ,
2072  signal, TupFragReq::SignalLength, JBB);
2073  return;
2074  }
2075  if (addfragptr.p->addfragStatus == AddFragRecord::WAIT_TUX)
2076  {
2077  jam();
2078  ndbrequire(DictTabInfo::isOrderedIndex(tabptr.p->tableType));
2079  TuxFragReq* const tuxreq = (TuxFragReq*)signal->getDataPtrSend();
2080  tuxreq->userPtr = addfragptr.i;
2081  tuxreq->userRef = cownref;
2082  tuxreq->reqInfo = 0; /* ADD TABLE */
2083  tuxreq->tableId = tabptr.i;
2084  tuxreq->fragId = addfragptr.p->m_lqhFragReq.fragId;
2085  tuxreq->primaryTableId = tabptr.p->primaryTableId;
2086  // pointer to index fragment in TUP
2087  tuxreq->tupIndexFragPtrI = fragptr.p->tupFragptr;
2088  // pointers to table fragments in TUP and ACC
2089  FragrecordPtr tFragPtr;
2090  tFragPtr.i = fragptr.p->tableFragptr;
2091  c_fragment_pool.getPtr(tFragPtr);
2092  tuxreq->tupTableFragPtrI = tFragPtr.p->tupFragptr;
2093  tuxreq->accTableFragPtrI = tFragPtr.p->accFragptr;
2094  sendSignal(fragptr.p->tuxBlockref, GSN_TUXFRAGREQ,
2095  signal, TuxFragReq::SignalLength, JBB);
2096  return;
2097  }
2098 }//Dblqh::sendAddFragReq
2099 
2100 
2101 /* ************************************************************************>> */
2102 /* TAB_COMMITREQ: Commit the new table for use in transactions. Sender DICT. */
2103 /* ************************************************************************>> */
2104 void Dblqh::execTAB_COMMITREQ(Signal* signal)
2105 {
2106  jamEntry();
2107  Uint32 dihPtr = signal->theData[0];
2108  BlockReference dihBlockref = signal->theData[1];
2109  tabptr.i = signal->theData[2];
2110 
2111  if (tabptr.i >= ctabrecFileSize) {
2112  jam();
2113  terrorCode = ZTAB_FILE_SIZE;
2114  signal->theData[0] = dihPtr;
2115  signal->theData[1] = cownNodeid;
2116  signal->theData[2] = tabptr.i;
2117  signal->theData[3] = terrorCode;
2118  sendSignal(dihBlockref, GSN_TAB_COMMITREF, signal, 4, JBB);
2119  return;
2120  }//if
2121  ptrAss(tabptr, tablerec);
2122  if (tabptr.p->tableStatus != Tablerec::ADD_TABLE_ONGOING) {
2123  jam();
2124  terrorCode = ZTAB_STATE_ERROR;
2125  signal->theData[0] = dihPtr;
2126  signal->theData[1] = cownNodeid;
2127  signal->theData[2] = tabptr.i;
2128  signal->theData[3] = terrorCode;
2129  signal->theData[4] = tabptr.p->tableStatus;
2130  sendSignal(dihBlockref, GSN_TAB_COMMITREF, signal, 5, JBB);
2131  ndbrequire(false);
2132  return;
2133  }//if
2134  tabptr.p->usageCountR = 0;
2135  tabptr.p->usageCountW = 0;
2136  tabptr.p->tableStatus = Tablerec::TABLE_DEFINED;
2137  signal->theData[0] = dihPtr;
2138  signal->theData[1] = cownNodeid;
2139  signal->theData[2] = tabptr.i;
2140  sendSignal(dihBlockref, GSN_TAB_COMMITCONF, signal, 3, JBB);
2141 
2142  return;
2143 }//Dblqh::execTAB_COMMITREQ()
2144 
2145 
2146 void Dblqh::fragrefLab(Signal* signal,
2147  Uint32 errorCode,
2148  const LqhFragReq* req)
2149 {
2150  LqhFragRef * ref = (LqhFragRef*)signal->getDataPtrSend();
2151  ref->senderData = req->senderData;
2152  ref->errorCode = errorCode;
2153  ref->requestInfo = req->requestInfo;
2154  ref->tableId = req->tableId;
2155  ref->fragId = req->fragId;
2156  ref->changeMask = req->changeMask;
2157  sendSignal(req->senderRef, GSN_LQHFRAGREF, signal,
2158  LqhFragRef::SignalLength, JBB);
2159  return;
2160 }//Dblqh::fragrefLab()
2161 
2162 /*
2163  * Abort on-going ops.
2164  */
2165 void Dblqh::abortAddFragOps(Signal* signal)
2166 {
2167  if (addfragptr.p->tupConnectptr != RNIL) {
2168  jam();
2169  TupFragReq* const tupFragReq = (TupFragReq*)signal->getDataPtrSend();
2170  tupFragReq->userPtr = (Uint32)-1;
2171  tupFragReq->userRef = addfragptr.p->tupConnectptr;
2172  sendSignal(ctupBlockref, GSN_TUPFRAGREQ, signal, 2, JBB);
2173  addfragptr.p->tupConnectptr = RNIL;
2174  }
2175  if (addfragptr.p->tuxConnectptr != RNIL) {
2176  jam();
2177  TuxFragReq* const tuxFragReq = (TuxFragReq*)signal->getDataPtrSend();
2178  tuxFragReq->userPtr = (Uint32)-1;
2179  tuxFragReq->userRef = addfragptr.p->tuxConnectptr;
2180  sendSignal(ctuxBlockref, GSN_TUXFRAGREQ, signal, 2, JBB);
2181  addfragptr.p->tuxConnectptr = RNIL;
2182  }
2183 }
2184 
2185 /* ************>> */
2186 /* ACCFRAGREF > */
2187 /* ************>> */
2188 void Dblqh::execACCFRAGREF(Signal* signal)
2189 {
2190  jamEntry();
2191  addfragptr.i = signal->theData[0];
2192  ptrCheckGuard(addfragptr, caddfragrecFileSize, addFragRecord);
2193  Uint32 errorCode = terrorCode = signal->theData[1];
2194  ndbrequire(addfragptr.p->addfragStatus == AddFragRecord::ACC_ADDFRAG);
2195 
2196  fragrefLab(signal, errorCode, &addfragptr.p->m_lqhFragReq);
2197  releaseAddfragrec(signal);
2198 
2199  return;
2200 }//Dblqh::execACCFRAGREF()
2201 
2202 /* ************>> */
2203 /* TUPFRAGREF > */
2204 /* ************>> */
2205 void Dblqh::execTUPFRAGREF(Signal* signal)
2206 {
2207  jamEntry();
2208  addfragptr.i = signal->theData[0];
2209  ptrCheckGuard(addfragptr, caddfragrecFileSize, addFragRecord);
2210  Uint32 errorCode = terrorCode = signal->theData[1];
2211  fragptr.i = addfragptr.p->fragmentPtr;
2212  c_fragment_pool.getPtr(fragptr);
2213 
2214  // no operation to release, just add some jams
2215  switch (addfragptr.p->addfragStatus) {
2216  case AddFragRecord::WAIT_TUP:
2217  jam();
2218  break;
2219  case AddFragRecord::WAIT_TUX:
2220  jam();
2221  break;
2222  default:
2223  ndbrequire(false);
2224  break;
2225  }
2226 
2227  fragrefLab(signal, errorCode, &addfragptr.p->m_lqhFragReq);
2228  releaseAddfragrec(signal);
2229 
2230 }//Dblqh::execTUPFRAGREF()
2231 
2232 void
2233 Dblqh::execDROP_FRAG_REQ(Signal* signal)
2234 {
2235  DropFragReq *req = (DropFragReq*)signal->getDataPtr();
2236  seizeAddfragrec(signal);
2237  addfragptr.p->m_dropFragReq = *req;
2238 
2245  tabptr.i = req->tableId;
2246  ptrCheckGuard(tabptr, ctabrecFileSize, tablerec);
2247 
2248  deleteFragrec(req->fragId);
2249 
2250  Uint32 ref = calcInstanceBlockRef(DBACC);
2251  if (DictTabInfo::isOrderedIndex(tabptr.p->tableType))
2252  {
2253  jam();
2254  ref = calcInstanceBlockRef(DBTUP);
2255  }
2256 
2257  req->senderRef = reference();
2258  req->senderData = addfragptr.i;
2259  sendSignal(ref, GSN_DROP_FRAG_REQ, signal, DropFragReq::SignalLength, JBB);
2260 }
2261 
2262 void
2263 Dblqh::execDROP_FRAG_REF(Signal* signal)
2264 {
2265  ndbrequire(false);
2266 }
2267 
2268 void
2269 Dblqh::execDROP_FRAG_CONF(Signal* signal)
2270 {
2271  DropFragConf* conf = (DropFragConf*)signal->getDataPtr();
2272  addfragptr.i = conf->senderData;
2273  ptrCheckGuard(addfragptr, caddfragrecFileSize, addFragRecord);
2274 
2275  Uint32 ref = RNIL;
2276  switch(refToMain(conf->senderRef)){
2277  case DBACC:
2278  jam();
2279  ref = calcInstanceBlockRef(DBTUP);
2280  break;
2281  case DBTUP:
2282  {
2283  tabptr.i = addfragptr.p->m_dropFragReq.tableId;
2284  ptrCheckGuard(tabptr, ctabrecFileSize, tablerec);
2285  if (DictTabInfo::isOrderedIndex(tabptr.p->tableType))
2286  {
2287  jam();
2288  ref = calcInstanceBlockRef(DBTUX);
2289  }
2290  break;
2291  }
2292  case DBTUX:
2293  break;
2294  default:
2295  ndbrequire(false);
2296  }
2297 
2298  if (ref != RNIL)
2299  {
2300  DropFragReq* req = (DropFragReq*)signal->getDataPtrSend();
2301  * req = addfragptr.p->m_dropFragReq;
2302  req->senderRef = reference();
2303  req->senderData = addfragptr.i;
2304  sendSignal(ref, GSN_DROP_FRAG_REQ, signal, DropFragReq::SignalLength,
2305  JBB);
2306  return;
2307  }
2308 
2309  conf->senderRef = reference();
2310  conf->senderData = addfragptr.p->m_dropFragReq.senderData;
2311  conf->tableId = addfragptr.p->m_dropFragReq.tableId;
2312  conf->fragId = addfragptr.p->m_dropFragReq.fragId;
2313  sendSignal(addfragptr.p->m_dropFragReq.senderRef, GSN_DROP_FRAG_CONF,
2314  signal, DropFragConf::SignalLength, JBB);
2315 
2316  releaseAddfragrec(signal);
2317 }
2318 
2319 /* ************>> */
2320 /* TUXFRAGREF > */
2321 /* ************>> */
2322 void Dblqh::execTUXFRAGREF(Signal* signal)
2323 {
2324  jamEntry();
2325  execTUPFRAGREF(signal);
2326 }//Dblqh::execTUXFRAGREF
2327 
2328 void
2329 Dblqh::execPREP_DROP_TAB_REQ(Signal* signal){
2330  jamEntry();
2331 
2332  PrepDropTabReq* req = (PrepDropTabReq*)signal->getDataPtr();
2333 
2334  Uint32 senderRef = req->senderRef;
2335  Uint32 senderData = req->senderData;
2336 
2337  TablerecPtr tabPtr;
2338  tabPtr.i = req->tableId;
2339  ptrCheckGuard(tabPtr, ctabrecFileSize, tablerec);
2340 
2341  Uint32 errCode = 0;
2342  switch(tabPtr.p->tableStatus) {
2343  case Tablerec::TABLE_DEFINED:
2344  jam();
2345  break;
2346  case Tablerec::NOT_DEFINED:
2347  jam();
2348  // Fall through
2349  case Tablerec::ADD_TABLE_ONGOING:
2350  jam();
2351  errCode = PrepDropTabRef::NoSuchTable;
2352  break;
2353  case Tablerec::PREP_DROP_TABLE_DONE:
2354  jam();
2355  errCode = PrepDropTabRef::DropInProgress;
2356  break;
2357  case Tablerec::DROP_TABLE_WAIT_USAGE:
2358  case Tablerec::DROP_TABLE_WAIT_DONE:
2359  case Tablerec::DROP_TABLE_ACC:
2360  case Tablerec::DROP_TABLE_TUP:
2361  case Tablerec::DROP_TABLE_TUX:
2362  jam();
2363  errCode = PrepDropTabRef::DropInProgress;
2364  case Tablerec::TABLE_READ_ONLY:
2365  jam();
2366  errCode = PrepDropTabRef::InvalidTableState;
2367  break;
2368  }
2369 
2370  if(errCode != 0)
2371  {
2372  jam();
2373 
2374  PrepDropTabRef* ref = (PrepDropTabRef*)signal->getDataPtrSend();
2375  ref->senderRef = reference();
2376  ref->senderData = senderData;
2377  ref->tableId = tabPtr.i;
2378  ref->errorCode = errCode;
2379  sendSignal(senderRef, GSN_PREP_DROP_TAB_REF, signal,
2380  PrepDropTabRef::SignalLength, JBB);
2381  return;
2382  }
2383 
2384  tabPtr.p->tableStatus = Tablerec::PREP_DROP_TABLE_DONE;
2385 
2386  PrepDropTabConf * conf = (PrepDropTabConf*)signal->getDataPtrSend();
2387  conf->tableId = tabPtr.i;
2388  conf->senderRef = reference();
2389  conf->senderData = senderData;
2390  sendSignal(senderRef, GSN_PREP_DROP_TAB_CONF, signal,
2391  PrepDropTabConf::SignalLength, JBB);
2392 }
2393 
2394 void
2395 Dblqh::dropTab_wait_usage(Signal* signal){
2396 
2397  TablerecPtr tabPtr;
2398  tabPtr.i = signal->theData[1];
2399  ptrCheckGuard(tabPtr, ctabrecFileSize, tablerec);
2400 
2401  Uint32 senderRef = signal->theData[2];
2402  Uint32 senderData = signal->theData[3];
2403 
2404  ndbrequire(tabPtr.p->tableStatus == Tablerec::DROP_TABLE_WAIT_USAGE);
2405 
2406  if (tabPtr.p->usageCountR > 0 || tabPtr.p->usageCountW > 0)
2407  {
2408  jam();
2409  sendSignalWithDelay(reference(), GSN_CONTINUEB, signal, 100, 4);
2410  return;
2411  }
2412 
2413  bool lcpDone = true;
2414  lcpPtr.i = 0;
2415  ptrAss(lcpPtr, lcpRecord);
2416  if(lcpPtr.p->lcpState != LcpRecord::LCP_IDLE)
2417  {
2418  jam();
2419 
2420  if(lcpPtr.p->currentFragment.lcpFragOrd.tableId == tabPtr.i)
2421  {
2422  jam();
2423  lcpDone = false;
2424  }
2425 
2426  if(lcpPtr.p->lcpQueued &&
2427  lcpPtr.p->queuedFragment.lcpFragOrd.tableId == tabPtr.i)
2428  {
2429  jam();
2430  lcpDone = false;
2431  }
2432  }
2433 
2434  if(!lcpDone)
2435  {
2436  jam();
2437  sendSignalWithDelay(reference(), GSN_CONTINUEB, signal, 100, 4);
2438  return;
2439  }
2440 
2441  tabPtr.p->tableStatus = Tablerec::DROP_TABLE_WAIT_DONE;
2442 
2443  DropTabConf * conf = (DropTabConf*)signal->getDataPtrSend();
2444  conf->tableId = tabPtr.i;
2445  conf->senderRef = reference();
2446  conf->senderData = senderData;
2447  sendSignal(senderRef, GSN_DROP_TAB_CONF, signal,
2448  DropTabConf::SignalLength, JBB);
2449 }
2450 
2451 void
2452 Dblqh::execDROP_TAB_REQ(Signal* signal){
2453  jamEntry();
2454 
2455  DropTabReq reqCopy = * (DropTabReq*)signal->getDataPtr();
2456  DropTabReq* req = &reqCopy;
2457 
2458  TablerecPtr tabPtr;
2459  tabPtr.i = req->tableId;
2460  ptrCheckGuard(tabPtr, ctabrecFileSize, tablerec);
2461 
2462  Uint32 errCode = 0;
2463  switch((DropTabReq::RequestType)req->requestType) {
2464  case DropTabReq::RestartDropTab:
2465  jam();
2466  tabPtr.p->tableStatus = Tablerec::DROP_TABLE_WAIT_DONE;
2467  break;
2468  case DropTabReq::CreateTabDrop:
2469  jam();
2470  tabPtr.p->tableStatus = Tablerec::DROP_TABLE_WAIT_DONE;
2471  break;
2472  case DropTabReq::OnlineDropTab:
2473  jam();
2474  switch(tabPtr.p->tableStatus) {
2475  case Tablerec::TABLE_DEFINED:
2476  jam();
2477  errCode = DropTabRef::DropWoPrep;
2478  break;
2479  case Tablerec::NOT_DEFINED:
2480  jam();
2481  errCode = DropTabRef::NoSuchTable;
2482  break;
2483  case Tablerec::ADD_TABLE_ONGOING:
2484  jam();
2485  ndbassert(false);
2486  case Tablerec::PREP_DROP_TABLE_DONE:
2487  jam();
2488  tabPtr.p->tableStatus = Tablerec::DROP_TABLE_WAIT_USAGE;
2489  signal->theData[0] = ZDROP_TABLE_WAIT_USAGE;
2490  signal->theData[1] = tabPtr.i;
2491  signal->theData[2] = req->senderRef;
2492  signal->theData[3] = req->senderData;
2493  dropTab_wait_usage(signal);
2494  return;
2495  break;
2496  case Tablerec::DROP_TABLE_WAIT_USAGE:
2497  case Tablerec::DROP_TABLE_ACC:
2498  case Tablerec::DROP_TABLE_TUP:
2499  case Tablerec::DROP_TABLE_TUX:
2500  ndbrequire(false);
2501  case Tablerec::DROP_TABLE_WAIT_DONE:
2502  jam();
2503  break;
2504  case Tablerec::TABLE_READ_ONLY:
2505  jam();
2506  errCode = DropTabRef::InvalidTableState;
2507  break;
2508  }
2509  }
2510 
2511  if (errCode)
2512  {
2513  jam();
2514  DropTabRef * ref = (DropTabRef*)signal->getDataPtrSend();
2515  ref->tableId = tabPtr.i;
2516  ref->senderRef = reference();
2517  ref->senderData = req->senderData;
2518  ref->errorCode = errCode;
2519  sendSignal(req->senderRef, GSN_DROP_TAB_REF, signal,
2520  DropTabRef::SignalLength, JBB);
2521  return;
2522  }
2523 
2524  ndbrequire(tabPtr.p->usageCountR == 0 && tabPtr.p->usageCountW == 0);
2525  seizeAddfragrec(signal);
2526  addfragptr.p->m_dropTabReq = * req;
2527  dropTable_nextStep(signal, addfragptr);
2528 }
2529 
2530 void
2531 Dblqh::execDROP_TAB_REF(Signal* signal)
2532 {
2533  jamEntry();
2534  DropTabRef * ref = (DropTabRef*)signal->getDataPtr();
2535 
2536 #if defined ERROR_INSERT || defined VM_TRACE
2537  jamLine(ref->errorCode);
2538  ndbrequire(false);
2539 #endif
2540 
2541  Ptr<AddFragRecord> addFragPtr;
2542  addFragPtr.i = ref->senderData;
2543  ptrCheckGuard(addFragPtr, caddfragrecFileSize, addFragRecord);
2544  dropTable_nextStep(signal, addFragPtr);
2545 }
2546 
2547 void
2548 Dblqh::execDROP_TAB_CONF(Signal* signal)
2549 {
2550  jamEntry();
2551  DropTabConf * conf = (DropTabConf*)signal->getDataPtr();
2552 
2553  Ptr<AddFragRecord> addFragPtr;
2554  addFragPtr.i = conf->senderData;
2555  ptrCheckGuard(addFragPtr, caddfragrecFileSize, addFragRecord);
2556  dropTable_nextStep(signal, addFragPtr);
2557 }
2558 
2559 void
2560 Dblqh::dropTable_nextStep(Signal* signal, Ptr<AddFragRecord> addFragPtr)
2561 {
2562  jam();
2563 
2564  TablerecPtr tabPtr;
2565  tabPtr.i = addFragPtr.p->m_dropTabReq.tableId;
2566  ptrCheckGuard(tabPtr, ctabrecFileSize, tablerec);
2567 
2568  Uint32 ref = 0;
2569  if (tabPtr.p->tableStatus == Tablerec::DROP_TABLE_WAIT_DONE)
2570  {
2571  jam();
2572  if (DictTabInfo::isTable(tabPtr.p->tableType) ||
2573  DictTabInfo::isHashIndex(tabPtr.p->tableType))
2574  {
2575  jam();
2576  ref = calcInstanceBlockRef(DBACC);
2577  tabPtr.p->tableStatus = Tablerec::DROP_TABLE_ACC;
2578  }
2579  else
2580  {
2581  jam();
2582  ref = calcInstanceBlockRef(DBTUP);
2583  tabPtr.p->tableStatus = Tablerec::DROP_TABLE_TUP;
2584  }
2585  }
2586  else if (tabPtr.p->tableStatus == Tablerec::DROP_TABLE_ACC)
2587  {
2588  jam();
2589  ref = calcInstanceBlockRef(DBTUP);
2590  tabPtr.p->tableStatus = Tablerec::DROP_TABLE_TUP;
2591  }
2592  else if (tabPtr.p->tableStatus == Tablerec::DROP_TABLE_TUP)
2593  {
2594  jam();
2595  if (DictTabInfo::isOrderedIndex(tabPtr.p->tableType))
2596  {
2597  jam();
2598  ref = calcInstanceBlockRef(DBTUX);
2599  tabPtr.p->tableStatus = Tablerec::DROP_TABLE_TUX;
2600  }
2601  }
2602 
2603  if (ref)
2604  {
2605  jam();
2606  DropTabReq* req = (DropTabReq*)signal->getDataPtrSend();
2607  req->senderData = addFragPtr.i;
2608  req->senderRef = reference();
2609  req->tableId = tabPtr.i;
2610  req->tableVersion = tabPtr.p->schemaVersion;
2611  req->requestType = addFragPtr.p->m_dropTabReq.requestType;
2612  sendSignal(ref, GSN_DROP_TAB_REQ, signal,
2613  DropTabReq::SignalLength, JBB);
2614  return;
2615  }
2616 
2617  removeTable(tabPtr.i);
2618  tabPtr.p->tableStatus = Tablerec::NOT_DEFINED;
2619 
2620  DropTabConf* conf = (DropTabConf*)signal->getDataPtrSend();
2621  conf->senderRef = reference();
2622  conf->senderData = addFragPtr.p->m_dropTabReq.senderData;
2623  conf->tableId = tabPtr.i;
2624  sendSignal(addFragPtr.p->m_dropTabReq.senderRef, GSN_DROP_TAB_CONF, signal,
2625  DropTabConf::SignalLength, JBB);
2626 
2627  addfragptr = addFragPtr;
2628  releaseAddfragrec(signal);
2629 }
2630 
2631 void Dblqh::removeTable(Uint32 tableId)
2632 {
2633  tabptr.i = tableId;
2634  ptrCheckGuard(tabptr, ctabrecFileSize, tablerec);
2635 
2636  for (Uint32 i = 0; i < MAX_FRAG_PER_NODE; i++) {
2637  jam();
2638  if (tabptr.p->fragid[i] != ZNIL) {
2639  jam();
2640  deleteFragrec(tabptr.p->fragid[i]);
2641  }//if
2642  }//for
2643 }//Dblqh::removeTable()
2644 
2645 void
2646 Dblqh::execALTER_TAB_REQ(Signal* signal)
2647 {
2648  jamEntry();
2649 
2650  if(!assembleFragments(signal))
2651  return;
2652 
2653  AlterTabReq copy = *(AlterTabReq*)signal->getDataPtr();
2654  const AlterTabReq* req = &copy;
2655  const Uint32 senderRef = req->senderRef;
2656  const Uint32 senderData = req->senderData;
2657  const Uint32 tableId = req->tableId;
2658  const Uint32 tableVersion = req->tableVersion;
2659  const Uint32 newTableVersion = req->newTableVersion;
2660  AlterTabReq::RequestType requestType =
2661  (AlterTabReq::RequestType) req->requestType;
2662 
2663  TablerecPtr tablePtr;
2664  tablePtr.i = tableId;
2665  ptrCheckGuard(tablePtr, ctabrecFileSize, tablerec);
2666 
2667  Uint32 len = signal->getLength();
2668  switch (requestType) {
2669  case AlterTabReq::AlterTablePrepare:
2670  jam();
2671  break;
2672  case AlterTabReq::AlterTableRevert:
2673  jam();
2674  tablePtr.p->schemaVersion = tableVersion;
2675  break;
2676  case AlterTabReq::AlterTableCommit:
2677  jam();
2678  tablePtr.p->schemaVersion = newTableVersion;
2679  if (AlterTableReq::getReorgFragFlag(req->changeMask))
2680  {
2681  jam();
2682  commit_reorg(tablePtr);
2683  }
2684  break;
2685  case AlterTabReq::AlterTableComplete:
2686  jam();
2687  break;
2688  case AlterTabReq::AlterTableSumaEnable:
2689  jam();
2690  break;
2691  case AlterTabReq::AlterTableSumaFilter:
2692  jam();
2693  signal->theData[len++] = cnewestGci + 3;
2694  break;
2695  case AlterTabReq::AlterTableReadOnly:
2696  jam();
2697  ndbrequire(tablePtr.p->tableStatus == Tablerec::TABLE_DEFINED);
2698  tablePtr.p->tableStatus = Tablerec::TABLE_READ_ONLY;
2699  signal->theData[0] = ZWAIT_READONLY;
2700  signal->theData[1] = tablePtr.i;
2701  signal->theData[2] = senderRef;
2702  signal->theData[3] = senderData;
2703  sendSignal(reference(), GSN_CONTINUEB, signal, 4, JBB);
2704  return;
2705  case AlterTabReq::AlterTableReadWrite:
2706  jam();
2707  ndbrequire(tablePtr.p->tableStatus == Tablerec::TABLE_READ_ONLY);
2708  tablePtr.p->tableStatus = Tablerec::TABLE_DEFINED;
2709  break;
2710  default:
2711  ndbrequire(false);
2712  break;
2713  }
2714 
2715  EXECUTE_DIRECT(DBTUP, GSN_ALTER_TAB_REQ, signal, len);
2716  jamEntry();
2717 
2718  Uint32 errCode = signal->theData[0];
2719  Uint32 connectPtr = signal->theData[1];
2720  if (errCode == 0)
2721  {
2722  // Request handled successfully
2723  AlterTabConf* conf = (AlterTabConf*)signal->getDataPtrSend();
2724  conf->senderRef = reference();
2725  conf->senderData = senderData;
2726  conf->connectPtr = connectPtr;
2727  sendSignal(senderRef, GSN_ALTER_TAB_CONF, signal,
2728  AlterTabConf::SignalLength, JBB);
2729  }
2730  else if (errCode == ~Uint32(0))
2731  {
2735  ndbrequire(requestType == AlterTabReq::AlterTableSumaFilter);
2736  signal->theData[0] = ZWAIT_REORG_SUMA_FILTER_ENABLED;
2737  signal->theData[1] = cnewestGci + 3;
2738  signal->theData[2] = senderData;
2739  signal->theData[3] = connectPtr;
2740  signal->theData[4] = senderRef;
2741  wait_reorg_suma_filter_enabled(signal);
2742  return;
2743  }
2744  else
2745  {
2746  jam();
2747  AlterTabRef* ref = (AlterTabRef*)signal->getDataPtrSend();
2748  ref->senderRef = reference();
2749  ref->senderData = senderData;
2750  ref->connectPtr = connectPtr;
2751  ref->errorCode = errCode;
2752  sendSignal(senderRef, GSN_ALTER_TAB_REF, signal,
2753  AlterTabRef::SignalLength, JBB);
2754  }
2755 }
2756 
2757 void
2758 Dblqh::wait_reorg_suma_filter_enabled(Signal* signal)
2759 {
2760  if (cnewestCompletedGci >= signal->theData[1])
2761  {
2762  jam();
2763  Uint32 senderData = signal->theData[2];
2764  Uint32 connectPtr = signal->theData[3];
2765  Uint32 senderRef = signal->theData[4];
2766 
2767  AlterTabConf* conf = (AlterTabConf*)signal->getDataPtrSend();
2768  conf->senderRef = reference();
2769  conf->senderData = senderData;
2770  conf->connectPtr = connectPtr;
2771  sendSignal(senderRef, GSN_ALTER_TAB_CONF, signal,
2772  AlterTabConf::SignalLength, JBB);
2773  return;
2774  }
2775  sendSignalWithDelay(reference(), GSN_CONTINUEB, signal, 500, 5);
2776 }
2777 
2778 void
2779 Dblqh::commit_reorg(TablerecPtr tablePtr)
2780 {
2781  for (Uint32 i = 0; i < MAX_FRAG_PER_NODE; i++)
2782  {
2783  jam();
2784  Ptr<Fragrecord> fragPtr;
2785  if ((fragPtr.i = tablePtr.p->fragrec[i]) != RNIL)
2786  {
2787  jam();
2788  c_fragment_pool.getPtr(fragPtr);
2789  fragPtr.p->fragDistributionKey = (fragPtr.p->fragDistributionKey+1)&0xFF;
2790  }
2791  }
2792 }
2793 
2794 void
2795 Dblqh::wait_readonly(Signal* signal)
2796 {
2797  jam();
2798 
2799  Uint32 tableId = signal->theData[1];
2800 
2801  TablerecPtr tablePtr;
2802  tablePtr.i = tableId;
2803  ptrCheckGuard(tablePtr, ctabrecFileSize, tablerec);
2804  ndbrequire(tablePtr.p->tableStatus == Tablerec::TABLE_READ_ONLY);
2805 
2806  if (tablePtr.p->usageCountW > 0)
2807  {
2808  jam();
2809  sendSignalWithDelay(reference(), GSN_CONTINUEB, signal, 3000,
2810  signal->getLength());
2811  return;
2812  }
2813 
2814  Uint32 senderRef = signal->theData[2];
2815  Uint32 senderData = signal->theData[3];
2816 
2817  // Request handled successfully
2818  AlterTabConf * conf = (AlterTabConf*)signal->getDataPtrSend();
2819  conf->senderRef = reference();
2820  conf->senderData = senderData;
2821  sendSignal(senderRef, GSN_ALTER_TAB_CONF, signal,
2822  AlterTabConf::SignalLength, JBB);
2823 }
2824 
2825 /* ************************************************************************>>
2826  * TIME_SIGNAL: Handles time-out of local operations. This is a clean-up
2827  * handler. If no other measure has succeeded in cleaning up after time-outs
2828  * or else then this routine will remove the transaction after 120 seconds of
2829  * inactivity. The check is performed once per 10 second. Sender is QMGR.
2830  * ************************************************************************>> */
2831 void Dblqh::execTIME_SIGNAL(Signal* signal)
2832 {
2833  jamEntry();
2834 
2835  cLqhTimeOutCount ++;
2836  cLqhTimeOutCheckCount ++;
2837 
2838  for (logPartPtr.i = 0; logPartPtr.i < clogPartFileSize; logPartPtr.i++)
2839  {
2840  jam();
2841  ptrCheckGuard(logPartPtr, clogPartFileSize, logPartRecord);
2842  int ret = logPartPtr.p->m_io_tracker.tick(10 * cLqhTimeOutCount,
2843  c_max_redo_lag,
2844  c_max_redo_lag_counter);
2845  if (ret < 0)
2846  {
2850  update_log_problem(signal, logPartPtr,
2851  LogPartRecord::P_REDO_IO_PROBLEM, true);
2852  }
2853  else if (ret > 0)
2854  {
2858  update_log_problem(signal, logPartPtr,
2859  LogPartRecord::P_REDO_IO_PROBLEM, false);
2860  }
2861  }
2862 
2863  if (cLqhTimeOutCheckCount < 1000) {
2864  jam();
2865  return;
2866  }//if
2867 
2868  cLqhTimeOutCheckCount = 0;
2869 #ifdef VM_TRACE
2870  TcConnectionrecPtr tTcConptr;
2871 
2872  for (tTcConptr.i = 0; tTcConptr.i < ctcConnectrecFileSize;
2873  tTcConptr.i++) {
2874  jam();
2875  ptrAss(tTcConptr, tcConnectionrec);
2876  if ((tTcConptr.p->tcTimer != 0) &&
2877  ((tTcConptr.p->tcTimer + 12000) < cLqhTimeOutCount)) {
2878  ndbout << "Dblqh::execTIME_SIGNAL"<<endl
2879  << "Timeout found in tcConnectRecord " <<tTcConptr.i<<endl
2880  << " cLqhTimeOutCount = " << cLqhTimeOutCount << endl
2881  << " tcTimer="<<tTcConptr.p->tcTimer<<endl
2882  << " tcTimer+12000="<<tTcConptr.p->tcTimer + 12000<<endl;
2883 
2884  signal->theData[0] = 2307;
2885  signal->theData[1] = tTcConptr.i;
2886  execDUMP_STATE_ORD(signal);
2887 
2888  // Reset the timer
2889  tTcConptr.p->tcTimer = 0;
2890  }//if
2891  }//for
2892 #endif
2893 #ifdef VM_TRACE
2894  for (lfoPtr.i = 0; lfoPtr.i < clfoFileSize; lfoPtr.i++) {
2895  ptrAss(lfoPtr, logFileOperationRecord);
2896  if ((lfoPtr.p->lfoTimer != 0) &&
2897  ((lfoPtr.p->lfoTimer + 12000) < cLqhTimeOutCount)) {
2898  ndbout << "We have lost LFO record" << endl;
2899  ndbout << "index = " << lfoPtr.i;
2900  ndbout << "State = " << lfoPtr.p->lfoState;
2901  ndbout << " Page No = " << lfoPtr.p->lfoPageNo;
2902  ndbout << " noPagesRw = " << lfoPtr.p->noPagesRw;
2903  ndbout << "lfoWordWritten = " << lfoPtr.p->lfoWordWritten << endl;
2904  lfoPtr.p->lfoTimer = cLqhTimeOutCount;
2905  }//if
2906  }//for
2907 
2908 #endif
2909 
2910 #if 0
2911  LcpRecordPtr TlcpPtr;
2912  // Print information about the current local checkpoint
2913  TlcpPtr.i = 0;
2914  ptrAss(TlcpPtr, lcpRecord);
2915  ndbout << "Information about LCP in this LQH" << endl
2916  << " lcpState="<<TlcpPtr.p->lcpState<<endl
2917  << " firstLcpLocAcc="<<TlcpPtr.p->firstLcpLocAcc<<endl
2918  << " firstLcpLocTup="<<TlcpPtr.p->firstLcpLocTup<<endl
2919  << " lcpAccptr="<<TlcpPtr.p->lcpAccptr<<endl
2920  << " lastFragmentFlag="<<TlcpPtr.p->lastFragmentFlag<<endl
2921  << " lcpQueued="<<TlcpPtr.p->lcpQueued<<endl
2922  << " reportEmptyref="<< TlcpPtr.p->reportEmptyRef<<endl
2923  << " reportEmpty="<<TlcpPtr.p->reportEmpty<<endl;
2924 #endif
2925 }//Dblqh::execTIME_SIGNAL()
2926 
2927 /* ######################################################################### */
2928 /* ####### EXECUTION MODULE ####### */
2929 /* THIS MODULE HANDLES THE RECEPTION OF LQHKEYREQ AND ALL PROCESSING */
2930 /* OF OPERATIONS ON BEHALF OF THIS REQUEST. THIS DOES ALSO INVOLVE */
2931 /* RECEPTION OF VARIOUS TYPES OF ATTRINFO AND KEYINFO. IT DOES ALSO */
2932 /* INVOLVE COMMUNICATION WITH ACC AND TUP. */
2933 /* ######################################################################### */
2934 
2935 void Dblqh::noFreeRecordLab(Signal* signal,
2936  const LqhKeyReq * lqhKeyReq,
2937  Uint32 errCode)
2938 {
2939  jamEntry();
2940  const Uint32 transid1 = lqhKeyReq->transId1;
2941  const Uint32 transid2 = lqhKeyReq->transId2;
2942  const Uint32 reqInfo = lqhKeyReq->requestInfo;
2943 
2944  if(errCode == ZNO_FREE_MARKER_RECORDS_ERROR ||
2945  errCode == ZNODE_SHUTDOWN_IN_PROGESS ||
2946  errCode == ZNODE_FAILURE_ERROR){
2947  jam();
2948  releaseTcrec(signal, tcConnectptr);
2949  }
2950 
2951  if (LqhKeyReq::getDirtyFlag(reqInfo) &&
2952  LqhKeyReq::getOperation(reqInfo) == ZREAD &&
2953  !LqhKeyReq::getNormalProtocolFlag(reqInfo)){
2954  jam();
2955  /* Dirty read sends TCKEYREF direct to client, and nothing to TC */
2956  ndbrequire(LqhKeyReq::getApplicationAddressFlag(reqInfo));
2957  const Uint32 apiRef = lqhKeyReq->variableData[0];
2958  const Uint32 apiOpRec = lqhKeyReq->variableData[1];
2959 
2960  TcKeyRef * const tcKeyRef = (TcKeyRef *) signal->getDataPtrSend();
2961 
2962  tcKeyRef->connectPtr = apiOpRec;
2963  tcKeyRef->transId[0] = transid1;
2964  tcKeyRef->transId[1] = transid2;
2965  tcKeyRef->errorCode = errCode;
2966  sendTCKEYREF(signal, apiRef, signal->getSendersBlockRef(), 0);
2967  } else {
2968  jam();
2969  /* All ops apart from dirty read send LQHKEYREF to TC
2970  * (This includes simple read)
2971  */
2972 
2973  const Uint32 clientPtr = lqhKeyReq->clientConnectPtr;
2974  Uint32 TcOprec = clientPtr;
2975  if(LqhKeyReq::getSameClientAndTcFlag(reqInfo) == 1){
2976  if(LqhKeyReq::getApplicationAddressFlag(reqInfo))
2977  TcOprec = lqhKeyReq->variableData[2];
2978  else
2979  TcOprec = lqhKeyReq->variableData[0];
2980  }
2981 
2982  LqhKeyRef * const ref = (LqhKeyRef*)signal->getDataPtrSend();
2983  ref->userRef = clientPtr;
2984  ref->connectPtr = TcOprec;
2985  ref->errorCode = errCode;
2986  ref->transId1 = transid1;
2987  ref->transId2 = transid2;
2988  sendSignal(signal->senderBlockRef(), GSN_LQHKEYREF, signal,
2989  LqhKeyRef::SignalLength, JBB);
2990  }//if
2991  return;
2992 }//Dblqh::noFreeRecordLab()
2993 
2994 Uint32
2995 Dblqh::get_table_state_error(Ptr<Tablerec> tabPtr) const
2996 {
2997  switch(tabPtr.p->tableStatus){
2998  case Tablerec::NOT_DEFINED:
2999  jam();
3000  return ZTABLE_NOT_DEFINED;
3001  break;
3002  case Tablerec::ADD_TABLE_ONGOING:
3003  jam();
3004  case Tablerec::PREP_DROP_TABLE_DONE:
3005  jam();
3006  case Tablerec::DROP_TABLE_WAIT_USAGE:
3007  jam();
3008  case Tablerec::DROP_TABLE_WAIT_DONE:
3009  jam();
3010  case Tablerec::DROP_TABLE_ACC:
3011  jam();
3012  case Tablerec::DROP_TABLE_TUP:
3013  jam();
3014  case Tablerec::DROP_TABLE_TUX:
3015  jam();
3016  return PrepDropTabRef::DropInProgress;
3017  break;
3018  case Tablerec::TABLE_DEFINED:
3019  case Tablerec::TABLE_READ_ONLY:
3020  ndbassert(0);
3021  return ZTABLE_NOT_DEFINED;
3022  break;
3023  }
3024  ndbassert(0);
3025  return ~Uint32(0);
3026 }
3027 
3028 int
3029 Dblqh::check_tabstate(Signal * signal, const Tablerec * tablePtrP, Uint32 op)
3030 {
3031  if (tabptr.p->tableStatus == Tablerec::TABLE_READ_ONLY)
3032  {
3033  jam();
3034  if (op == ZREAD || op == ZREAD_EX || op == ZUNLOCK)
3035  {
3036  jam();
3037  return 0;
3038  }
3039  terrorCode = ZTABLE_READ_ONLY;
3040  }
3041  else
3042  {
3043  jam();
3044  terrorCode = get_table_state_error(tabptr);
3045  }
3046  abortErrorLab(signal);
3047  return 1;
3048 }
3049 
3050 void Dblqh::LQHKEY_abort(Signal* signal, int errortype)
3051 {
3052  switch (errortype) {
3053  case 0:
3054  jam();
3055  terrorCode = ZCOPY_NODE_ERROR;
3056  break;
3057  case 1:
3058  jam();
3059  terrorCode = ZNO_FREE_LQH_CONNECTION;
3060  break;
3061  case 2:
3062  jam();
3063  terrorCode = signal->theData[1];
3064  break;
3065  case 3:
3066  jam();
3067  ndbrequire((tcConnectptr.p->transactionState == TcConnectionrec::WAIT_ACC_ABORT) ||
3068  (tcConnectptr.p->transactionState == TcConnectionrec::ABORT_STOPPED) ||
3069  (tcConnectptr.p->transactionState == TcConnectionrec::ABORT_QUEUED));
3070  return;
3071  break;
3072  case 4:
3073  jam();
3074  terrorCode = get_table_state_error(tabptr);
3075  break;
3076  case 5:
3077  jam();
3078  terrorCode = ZINVALID_SCHEMA_VERSION;
3079  break;
3080  default:
3081  ndbrequire(false);
3082  break;
3083  }//switch
3084  abortErrorLab(signal);
3085 }//Dblqh::LQHKEY_abort()
3086 
3087 void Dblqh::LQHKEY_error(Signal* signal, int errortype)
3088 {
3089  switch (errortype) {
3090  case 0:
3091  jam();
3092  break;
3093  case 1:
3094  jam();
3095  break;
3096  case 2:
3097  jam();
3098  break;
3099  case 3:
3100  jam();
3101  break;
3102  case 4:
3103  jam();
3104  break;
3105  case 5:
3106  jam();
3107  break;
3108  case 6:
3109  jam();
3110  break;
3111  default:
3112  jam();
3113  break;
3114  }//switch
3115  ndbrequire(false);
3116 }//Dblqh::LQHKEY_error()
3117 
3118 void Dblqh::execLQHKEYREF(Signal* signal)
3119 {
3120  jamEntry();
3121  tcConnectptr.i = signal->theData[0];
3122  Uint32 tcOprec = signal->theData[1];
3123  terrorCode = signal->theData[2];
3124  Uint32 transid1 = signal->theData[3];
3125  Uint32 transid2 = signal->theData[4];
3126  if (tcConnectptr.i >= ctcConnectrecFileSize) {
3127  errorReport(signal, 3);
3128  return;
3129  }//if
3130 
3131  ptrAss(tcConnectptr, tcConnectionrec);
3132  TcConnectionrec * const regTcPtr = tcConnectptr.p;
3133 
3134  if (likely(! ((regTcPtr->connectState == TcConnectionrec::LOG_CONNECTED) ||
3135  (regTcPtr->connectState == TcConnectionrec::COPY_CONNECTED))))
3136  {
3151  if (findTransaction(transid1, transid2, tcOprec, 0) != ZOK)
3152  {
3153  jam();
3154  warningReport(signal, 14);
3155  return;
3156  }
3157  }
3158 
3159  switch (regTcPtr->connectState) {
3160  case TcConnectionrec::CONNECTED:
3161  jam();
3162  if (regTcPtr->abortState != TcConnectionrec::ABORT_IDLE) {
3163  warningReport(signal, 15);
3164  return;
3165  }//if
3166  abortErrorLab(signal);
3167  return;
3168  break;
3169  case TcConnectionrec::LOG_CONNECTED:
3170  jam();
3171  logLqhkeyrefLab(signal);
3172  return;
3173  break;
3174  case TcConnectionrec::COPY_CONNECTED:
3175  jam();
3176  copyLqhKeyRefLab(signal);
3177  return;
3178  break;
3179  default:
3180  warningReport(signal, 16);
3181  return;
3182  break;
3183  }//switch
3184 }//Dblqh::execLQHKEYREF()
3185 
3186 /* -------------------------------------------------------------------------- */
3187 /* ------- ENTER PACKED_SIGNAL ------- */
3188 /* Execution of packed signal. The packed signal can contain COMMIT, COMPLETE */
3189 /* or LQHKEYCONF signals. These signals will be executed by their resp. exec */
3190 /* functions. */
3191 /* -------------------------------------------------------------------------- */
3192 void Dblqh::execPACKED_SIGNAL(Signal* signal)
3193 {
3194  Uint32 Tstep = 0;
3195  Uint32 Tlength;
3196  Uint32 TpackedData[28];
3197  Uint32 sig0, sig1, sig2, sig3 ,sig4, sig5, sig6;
3198 
3199  jamEntry();
3200  Tlength = signal->length();
3201  Uint32 TsenderRef = signal->getSendersBlockRef();
3202  Uint32 TcommitLen = 5;
3203  Uint32 Tgci_lo_mask = ~(Uint32)0;
3204 
3205  if (unlikely(!ndb_check_micro_gcp(getNodeInfo(refToNode(signal->getSendersBlockRef())).m_version)))
3206  {
3207  jam();
3208  TcommitLen = 4;
3209  Tgci_lo_mask = 0;
3210  }
3211 
3212 #ifdef ERROR_INSERT
3213  Uint32 senderBlockRef = signal->getSendersBlockRef();
3214 #endif
3215 
3216  ndbrequire(Tlength <= 25);
3217  MEMCOPY_NO_WORDS(&TpackedData[0], &signal->theData[0], Tlength);
3218  while (Tlength > Tstep) {
3219  switch (TpackedData[Tstep] >> 28) {
3220  case ZCOMMIT:
3221  jam();
3222  sig0 = TpackedData[Tstep + 0] & 0x0FFFFFFF;
3223  sig1 = TpackedData[Tstep + 1];
3224  sig2 = TpackedData[Tstep + 2];
3225  sig3 = TpackedData[Tstep + 3];
3226  sig4 = TpackedData[Tstep + 4];
3227  signal->theData[0] = sig0;
3228  signal->theData[1] = sig1;
3229  signal->theData[2] = sig2;
3230  signal->theData[3] = sig3;
3231  signal->theData[4] = sig4 & Tgci_lo_mask;
3232  signal->header.theLength = TcommitLen;
3233  execCOMMIT(signal);
3234  Tstep += TcommitLen;
3235  break;
3236  case ZCOMPLETE:
3237  jam();
3238  sig0 = TpackedData[Tstep + 0] & 0x0FFFFFFF;
3239  sig1 = TpackedData[Tstep + 1];
3240  sig2 = TpackedData[Tstep + 2];
3241  signal->theData[0] = sig0;
3242  signal->theData[1] = sig1;
3243  signal->theData[2] = sig2;
3244  signal->header.theLength = 3;
3245  execCOMPLETE(signal);
3246  Tstep += 3;
3247  break;
3248  case ZLQHKEYCONF: {
3249  jam();
3250  LqhKeyConf * lqhKeyConf = CAST_PTR(LqhKeyConf, signal->theData);
3251  sig0 = TpackedData[Tstep + 0] & 0x0FFFFFFF;
3252  sig1 = TpackedData[Tstep + 1];
3253  sig2 = TpackedData[Tstep + 2];
3254  sig3 = TpackedData[Tstep + 3];
3255  sig4 = TpackedData[Tstep + 4];
3256  sig5 = TpackedData[Tstep + 5];
3257  sig6 = TpackedData[Tstep + 6];
3258  lqhKeyConf->connectPtr = sig0;
3259  lqhKeyConf->opPtr = sig1;
3260  lqhKeyConf->userRef = sig2;
3261  lqhKeyConf->readLen = sig3;
3262  lqhKeyConf->transId1 = sig4;
3263  lqhKeyConf->transId2 = sig5;
3264  lqhKeyConf->noFiredTriggers = sig6;
3265  execLQHKEYCONF(signal);
3266  Tstep += LqhKeyConf::SignalLength;
3267  break;
3268  }
3269  case ZREMOVE_MARKER:
3270  jam();
3271  sig0 = TpackedData[Tstep + 1];
3272  sig1 = TpackedData[Tstep + 2];
3273  signal->theData[0] = sig0;
3274  signal->theData[1] = sig1;
3275  signal->header.theLength = 2;
3276  execREMOVE_MARKER_ORD(signal);
3277  Tstep += 3;
3278  break;
3279  case ZFIRE_TRIG_REQ:
3280  jam();
3281  ndbassert(FireTrigReq::SignalLength == 4);
3282  sig0 = TpackedData[Tstep + 0] & 0x0FFFFFFF;
3283  sig1 = TpackedData[Tstep + 1];
3284  sig2 = TpackedData[Tstep + 2];
3285  sig3 = TpackedData[Tstep + 3];
3286  signal->theData[0] = sig0;
3287  signal->theData[1] = sig1;
3288  signal->theData[2] = sig2;
3289  signal->theData[3] = sig3;
3290  signal->header.theLength = FireTrigReq::SignalLength;
3291  signal->header.theSendersBlockRef = TsenderRef;
3292  execFIRE_TRIG_REQ(signal);
3293  Tstep += FireTrigReq::SignalLength;
3294  break;
3295  default:
3296  ndbrequire(false);
3297  return;
3298  }//switch
3299 #ifdef ERROR_INSERT
3300  signal->header.theSendersBlockRef = senderBlockRef;
3301 #endif
3302  }//while
3303  ndbrequire(Tlength == Tstep);
3304  return;
3305 }//Dblqh::execPACKED_SIGNAL()
3306 
3307 void
3308 Dblqh::execREMOVE_MARKER_ORD(Signal* signal)
3309 {
3310  CommitAckMarker key;
3311  key.transid1 = signal->theData[0];
3312  key.transid2 = signal->theData[1];
3313  jamEntry();
3314 
3315  CommitAckMarkerPtr removedPtr;
3316  m_commitAckMarkerHash.remove(removedPtr, key);
3317 #if (defined VM_TRACE || defined ERROR_INSERT) && defined(wl4391_todo)
3318  ndbrequire(removedPtr.i != RNIL);
3319  m_commitAckMarkerPool.release(removedPtr);
3320 #else
3321  if (removedPtr.i != RNIL)
3322  {
3323  jam();
3324  m_commitAckMarkerPool.release(removedPtr);
3325  }
3326 #endif
3327 #ifdef MARKER_TRACE
3328  ndbout_c("%u Rem marker[%.8x %.8x]", instance(), key.transid1, key.transid2);
3329 #endif
3330 }
3331 
3332 
3333 /* -------------------------------------------------------------------------- */
3334 /* ------- ENTER SEND_PACKED ------- */
3335 /* Used to force a packed signal to be sent if local signal buffer is not */
3336 /* empty. */
3337 /* -------------------------------------------------------------------------- */
3338 void Dblqh::execSEND_PACKED(Signal* signal)
3339 {
3340  HostRecordPtr Thostptr;
3341  UintR i;
3342  UintR TpackedListIndex = cpackedListIndex;
3343  jamEntry();
3344  for (i = 0; i < TpackedListIndex; i++) {
3345  Thostptr.i = cpackedList[i];
3346  ptrAss(Thostptr, hostRecord);
3347  jam();
3348  ndbrequire(Thostptr.i - 1 < MAX_NDB_NODES - 1);
3349  if (Thostptr.p->noOfPackedWordsLqh > 0) {
3350  jam();
3351  sendPackedSignalLqh(signal, Thostptr.p);
3352  }//if
3353  if (Thostptr.p->noOfPackedWordsTc > 0) {
3354  jam();
3355  sendPackedSignalTc(signal, Thostptr.p);
3356  }//if
3357  Thostptr.p->inPackedList = false;
3358  }//for
3359  cpackedListIndex = 0;
3360  return;
3361 }//Dblqh::execSEND_PACKED()
3362 
3363 void
3364 Dblqh::updatePackedList(Signal* signal, HostRecord * ahostptr, Uint16 hostId)
3365 {
3366  Uint32 TpackedListIndex = cpackedListIndex;
3367  if (ahostptr->inPackedList == false) {
3368  jam();
3369  ahostptr->inPackedList = true;
3370  cpackedList[TpackedListIndex] = hostId;
3371  cpackedListIndex = TpackedListIndex + 1;
3372  }//if
3373 }//Dblqh::updatePackedList()
3374 
3375 void
3376 Dblqh::execREAD_PSEUDO_REQ(Signal* signal){
3377  jamEntry();
3378  TcConnectionrecPtr regTcPtr;
3379  regTcPtr.i = signal->theData[0];
3380  ptrCheckGuard(regTcPtr, ctcConnectrecFileSize, tcConnectionrec);
3381 
3382  switch(signal->theData[1])
3383  {
3384  case AttributeHeader::RANGE_NO:
3385  signal->theData[0] = regTcPtr.p->m_scan_curr_range_no;
3386  break;
3387  case AttributeHeader::ROW_COUNT:
3388  case AttributeHeader::COMMIT_COUNT:
3389  {
3390  jam();
3391  FragrecordPtr regFragptr;
3392  regFragptr.i = regTcPtr.p->fragmentptr;
3393  c_fragment_pool.getPtr(regFragptr);
3394 
3395  signal->theData[0] = regFragptr.p->accFragptr;
3396  EXECUTE_DIRECT(DBACC, GSN_READ_PSEUDO_REQ, signal, 2);
3397  break;
3398  }
3399  case AttributeHeader::RECORDS_IN_RANGE:
3400  case AttributeHeader::INDEX_STAT_KEY:
3401  case AttributeHeader::INDEX_STAT_VALUE:
3402  {
3403  jam();
3404  // scanptr gets reset somewhere within the timeslice
3405  ScanRecordPtr tmp;
3406  tmp.i = regTcPtr.p->tcScanRec;
3407  c_scanRecordPool.getPtr(tmp);
3408  signal->theData[0] = tmp.p->scanAccPtr;
3409  EXECUTE_DIRECT(DBTUX, GSN_READ_PSEUDO_REQ, signal, 2);
3410  break;
3411  }
3412  case AttributeHeader::LOCK_REF:
3413  {
3414  /* Return 3x 32-bit words
3415  * - LQH instance info
3416  * - TC operation index
3417  * - Bottom 32-bits of LQH-local key-request id (for uniqueness)
3418  */
3419  jam();
3420  signal->theData[0] = (getOwnNodeId() << 16) | regTcPtr.p->fragmentid;
3421  signal->theData[1] = regTcPtr.p->tcOprec;
3422  signal->theData[2] = (Uint32) regTcPtr.p->lqhKeyReqId;
3423  break;
3424  }
3425  case AttributeHeader::OP_ID:
3426  {
3427  jam();
3428  memcpy(signal->theData, &regTcPtr.p->lqhKeyReqId, 8);
3429  break;
3430  }
3431  case AttributeHeader::CORR_FACTOR64:
3432  {
3433  Uint32 add = 0;
3434  ScanRecordPtr tmp;
3435  tmp.i = regTcPtr.p->tcScanRec;
3436  if (tmp.i != RNIL)
3437  {
3438  c_scanRecordPool.getPtr(tmp);
3439  add = tmp.p->m_curr_batch_size_rows;
3440  }
3441 
3442  signal->theData[0] = regTcPtr.p->m_corrFactorLo + add;
3443  signal->theData[1] = regTcPtr.p->m_corrFactorHi;
3444  break;
3445  }
3446  default:
3447  ndbrequire(false);
3448  }
3449 }
3450 
3451 /* ************>> */
3452 /* TUPKEYCONF > */
3453 /* ************>> */
3454 void Dblqh::execTUPKEYCONF(Signal* signal)
3455 {
3456  TcConnectionrec *regTcConnectionrec = tcConnectionrec;
3457  Uint32 ttcConnectrecFileSize = ctcConnectrecFileSize;
3458  const TupKeyConf * const tupKeyConf = (TupKeyConf *)signal->getDataPtr();
3459  Uint32 tcIndex = tupKeyConf->userPtr;
3460  jamEntry();
3461  tcConnectptr.i = tcIndex;
3462  ptrCheckGuard(tcConnectptr, ttcConnectrecFileSize, regTcConnectionrec);
3463  TcConnectionrec * regTcPtr = tcConnectptr.p;
3464  Uint32 activeCreat = regTcPtr->activeCreat;
3465 
3466  FragrecordPtr regFragptr;
3467  regFragptr.i = tcConnectptr.p->fragmentptr;
3468  c_fragment_pool.getPtr(regFragptr);
3469  fragptr = regFragptr;
3470 
3471  switch (tcConnectptr.p->transactionState) {
3472  case TcConnectionrec::WAIT_TUP:
3473  jam();
3474  if (tcConnectptr.p->seqNoReplica == 0) // Primary replica
3475  tcConnectptr.p->noFiredTriggers = tupKeyConf->noFiredTriggers;
3476  tupkeyConfLab(signal);
3477  break;
3478  case TcConnectionrec::COPY_TUPKEY:
3479  jam();
3480  copyTupkeyConfLab(signal);
3481  break;
3482  case TcConnectionrec::SCAN_TUPKEY:
3483  jam();
3484  scanTupkeyConfLab(signal);
3485  break;
3486  case TcConnectionrec::WAIT_TUP_TO_ABORT:
3487  jam();
3488 /* ------------------------------------------------------------------------- */
3489 // Abort was not ready to start until this signal came back. Now we are ready
3490 // to start the abort.
3491 /* ------------------------------------------------------------------------- */
3492  if (unlikely(activeCreat == Fragrecord::AC_NR_COPY))
3493  {
3494  jam();
3495  ndbrequire(regTcPtr->m_nr_delete.m_cnt);
3496  regTcPtr->m_nr_delete.m_cnt--;
3497  if (regTcPtr->m_nr_delete.m_cnt)
3498  {
3499  jam();
3505 #ifdef VM_TRACE
3506 
3509  TablerecPtr tablePtr;
3510  tablePtr.i = regTcPtr->tableref;
3511  ptrCheckGuard(tablePtr, ctabrecFileSize, tablerec);
3512  ndbrequire(tablePtr.p->m_disk_table);
3513 #endif
3514  return;
3515  }
3516  }
3517 
3518  abortCommonLab(signal);
3519  break;
3520  case TcConnectionrec::WAIT_ACC_ABORT:
3521  case TcConnectionrec::ABORT_QUEUED:
3522  jam();
3523 /* ------------------------------------------------------------------------- */
3524 /* IGNORE SINCE ABORT OF THIS OPERATION IS ONGOING ALREADY. */
3525 /* ------------------------------------------------------------------------- */
3526  break;
3527  default:
3528  ndbrequire(false);
3529  break;
3530  }//switch
3531 
3532 }//Dblqh::execTUPKEYCONF()
3533 
3534 /* ************> */
3535 /* TUPKEYREF > */
3536 /* ************> */
3537 void Dblqh::execTUPKEYREF(Signal* signal)
3538 {
3539  const TupKeyRef * const tupKeyRef = (TupKeyRef *)signal->getDataPtr();
3540 
3541  jamEntry();
3542  tcConnectptr.i = tupKeyRef->userRef;
3543  terrorCode = tupKeyRef->errorCode;
3544  ptrCheckGuard(tcConnectptr, ctcConnectrecFileSize, tcConnectionrec);
3545  TcConnectionrec* regTcPtr = tcConnectptr.p;
3546  Uint32 activeCreat = regTcPtr->activeCreat;
3547 
3548  FragrecordPtr regFragptr;
3549  regFragptr.i = regTcPtr->fragmentptr;
3550  c_fragment_pool.getPtr(regFragptr);
3551  fragptr = regFragptr;
3552 
3553  TRACE_OP(regTcPtr, "TUPKEYREF");
3554 
3555  if (unlikely(activeCreat == Fragrecord::AC_NR_COPY))
3556  {
3557  jam();
3558  ndbrequire(regTcPtr->m_nr_delete.m_cnt);
3559  regTcPtr->m_nr_delete.m_cnt--;
3560  ndbassert(regTcPtr->transactionState == TcConnectionrec::WAIT_TUP ||
3561  regTcPtr->transactionState ==TcConnectionrec::WAIT_TUP_TO_ABORT);
3562  }
3563 
3564  switch (tcConnectptr.p->transactionState) {
3565  case TcConnectionrec::WAIT_TUP:
3566  jam();
3567  abortErrorLab(signal);
3568  break;
3569  case TcConnectionrec::COPY_TUPKEY:
3570  copyTupkeyRefLab(signal);
3571  break;
3572  case TcConnectionrec::SCAN_TUPKEY:
3573  jam();
3574  scanTupkeyRefLab(signal);
3575  break;
3576  case TcConnectionrec::WAIT_TUP_TO_ABORT:
3577  jam();
3578 /* ------------------------------------------------------------------------- */
3579 // Abort was not ready to start until this signal came back. Now we are ready
3580 // to start the abort.
3581 /* ------------------------------------------------------------------------- */
3582  abortCommonLab(signal);
3583  break;
3584  case TcConnectionrec::WAIT_ACC_ABORT:
3585  case TcConnectionrec::ABORT_QUEUED:
3586  jam();
3587 /* ------------------------------------------------------------------------- */
3588 /* IGNORE SINCE ABORT OF THIS OPERATION IS ONGOING ALREADY. */
3589 /* ------------------------------------------------------------------------- */
3590  break;
3591  default:
3592  jamLine(tcConnectptr.p->transactionState);
3593  ndbrequire(false);
3594  break;
3595  }//switch
3596 }//Dblqh::execTUPKEYREF()
3597 
3598 void Dblqh::sendPackedSignalLqh(Signal* signal, HostRecord * ahostptr)
3599 {
3600  Uint32 noOfWords = ahostptr->noOfPackedWordsLqh;
3601  BlockReference hostRef = ahostptr->hostLqhBlockRef;
3602  MEMCOPY_NO_WORDS(&signal->theData[0],
3603  &ahostptr->packedWordsLqh[0],
3604  noOfWords);
3605  sendSignal(hostRef, GSN_PACKED_SIGNAL, signal, noOfWords, JBB);
3606  ahostptr->noOfPackedWordsLqh = 0;
3607 }//Dblqh::sendPackedSignalLqh()
3608 
3609 void Dblqh::sendPackedSignalTc(Signal* signal, HostRecord * ahostptr)
3610 {
3611  Uint32 noOfWords = ahostptr->noOfPackedWordsTc;
3612  BlockReference hostRef = ahostptr->hostTcBlockRef;
3613  MEMCOPY_NO_WORDS(&signal->theData[0],
3614  &ahostptr->packedWordsTc[0],
3615  noOfWords);
3616  sendSignal(hostRef, GSN_PACKED_SIGNAL, signal, noOfWords, JBB);
3617  ahostptr->noOfPackedWordsTc = 0;
3618 }//Dblqh::sendPackedSignalTc()
3619 
3620 void Dblqh::sendCommitLqh(Signal* signal, BlockReference alqhBlockref)
3621 {
3622  HostRecordPtr Thostptr;
3623  Thostptr.i = refToNode(alqhBlockref);
3624  ptrCheckGuard(Thostptr, chostFileSize, hostRecord);
3625 
3626  Uint32 Tdata[5];
3627  Tdata[0] = tcConnectptr.p->clientConnectrec;
3628  Tdata[1] = tcConnectptr.p->gci_hi;
3629  Tdata[2] = tcConnectptr.p->transid[0];
3630  Tdata[3] = tcConnectptr.p->transid[1];
3631  Tdata[4] = tcConnectptr.p->gci_lo;
3632  Uint32 len = 5;
3633 
3634  if (unlikely(!ndb_check_micro_gcp(getNodeInfo(Thostptr.i).m_version)))
3635  {
3636  jam();
3637  ndbassert(Tdata[4] == 0 || getNodeInfo(Thostptr.i).m_version == 0);
3638  len = 4;
3639  }
3640 
3641  // currently packed signal cannot address specific instance
3642  const bool send_unpacked = getNodeInfo(Thostptr.i).m_lqh_workers != 0;
3643  if (send_unpacked) {
3644  jam();
3645  FragrecordPtr Tfragptr;
3646  Tfragptr.i = tcConnectptr.p->fragmentptr;
3647  c_fragment_pool.getPtr(Tfragptr);
3648  memcpy(&signal->theData[0], &Tdata[0], len << 2);
3649  Uint32 Tnode = Thostptr.i;
3650  Uint32 instanceKey = Tfragptr.p->lqhInstanceKey;
3651  BlockReference lqhRef = numberToRef(DBLQH, instanceKey, Tnode);
3652  sendSignal(lqhRef, GSN_COMMIT, signal, len, JBB);
3653  return;
3654  }
3655 
3656  if (Thostptr.p->noOfPackedWordsLqh > 25 - 5) {
3657  jam();
3658  sendPackedSignalLqh(signal, Thostptr.p);
3659  } else {
3660  jam();
3661  updatePackedList(signal, Thostptr.p, Thostptr.i);
3662  }
3663 
3664  Tdata[0] |= (ZCOMMIT << 28);
3665  Uint32 pos = Thostptr.p->noOfPackedWordsLqh;
3666  memcpy(&Thostptr.p->packedWordsLqh[pos], &Tdata[0], len << 2);
3667  Thostptr.p->noOfPackedWordsLqh = pos + len;
3668 }
3669 
3670 void Dblqh::sendCompleteLqh(Signal* signal, BlockReference alqhBlockref)
3671 {
3672  HostRecordPtr Thostptr;
3673  Thostptr.i = refToNode(alqhBlockref);
3674  ptrCheckGuard(Thostptr, chostFileSize, hostRecord);
3675 
3676  Uint32 Tdata[3];
3677  Tdata[0] = tcConnectptr.p->clientConnectrec;
3678  Tdata[1] = tcConnectptr.p->transid[0];
3679  Tdata[2] = tcConnectptr.p->transid[1];
3680  Uint32 len = 3;
3681 
3682  // currently packed signal cannot address specific instance
3683  const bool send_unpacked = getNodeInfo(Thostptr.i).m_lqh_workers != 0;
3684  if (send_unpacked) {
3685  jam();
3686  FragrecordPtr Tfragptr;
3687  Tfragptr.i = tcConnectptr.p->fragmentptr;
3688  c_fragment_pool.getPtr(Tfragptr);
3689  memcpy(&signal->theData[0], &Tdata[0], len << 2);
3690  Uint32 Tnode = Thostptr.i;
3691  Uint32 instanceKey = Tfragptr.p->lqhInstanceKey;
3692  BlockReference lqhRef = numberToRef(DBLQH, instanceKey, Tnode);
3693  sendSignal(lqhRef, GSN_COMPLETE, signal, len, JBB);
3694  return;
3695  }
3696 
3697  if (Thostptr.p->noOfPackedWordsLqh > 22) {
3698  jam();
3699  sendPackedSignalLqh(signal, Thostptr.p);
3700  } else {
3701  jam();
3702  updatePackedList(signal, Thostptr.p, Thostptr.i);
3703  }
3704 
3705  Tdata[0] |= (ZCOMPLETE << 28);
3706  Uint32 pos = Thostptr.p->noOfPackedWordsLqh;
3707  memcpy(&Thostptr.p->packedWordsLqh[pos], &Tdata[0], len << 2);
3708  Thostptr.p->noOfPackedWordsLqh = pos + len;
3709 }
3710 
3711 void Dblqh::sendCommittedTc(Signal* signal, BlockReference atcBlockref)
3712 {
3713  if (refToInstance(atcBlockref))
3714  {
3715  jam();
3716  signal->theData[0] = tcConnectptr.p->clientConnectrec;
3717  signal->theData[1] = tcConnectptr.p->transid[0];
3718  signal->theData[2] = tcConnectptr.p->transid[1];
3719  sendSignal(atcBlockref, GSN_COMMITTED, signal, 3, JBB);
3720  return;
3721  }
3722 
3723  HostRecordPtr Thostptr;
3724  Thostptr.i = refToNode(atcBlockref);
3725  ptrCheckGuard(Thostptr, chostFileSize, hostRecord);
3726 
3727  Uint32 Tdata[3];
3728  Tdata[0] = tcConnectptr.p->clientConnectrec;
3729  Tdata[1] = tcConnectptr.p->transid[0];
3730  Tdata[2] = tcConnectptr.p->transid[1];
3731  Uint32 len = 3;
3732 
3733  // currently TC is single-threaded
3734  const bool send_unpacked = false;
3735  if (send_unpacked) {
3736  jam();
3737  memcpy(&signal->theData[0], &Tdata[0], len << 2);
3738  BlockReference tcRef = Thostptr.p->hostTcBlockRef;
3739  sendSignal(tcRef, GSN_COMMITTED, signal, len, JBB);
3740  return;
3741  }
3742 
3743  if (Thostptr.p->noOfPackedWordsTc > 22) {
3744  jam();
3745  sendPackedSignalTc(signal, Thostptr.p);
3746  } else {
3747  jam();
3748  updatePackedList(signal, Thostptr.p, Thostptr.i);
3749  }
3750 
3751  Tdata[0] |= (ZCOMMITTED << 28);
3752  Uint32 pos = Thostptr.p->noOfPackedWordsTc;
3753  memcpy(&Thostptr.p->packedWordsTc[pos], &Tdata[0], len << 2);
3754  Thostptr.p->noOfPackedWordsTc = pos + len;
3755 }
3756 
3757 void Dblqh::sendCompletedTc(Signal* signal, BlockReference atcBlockref)
3758 {
3759  if (refToInstance(atcBlockref))
3760  {
3761  jam();
3762  signal->theData[0] = tcConnectptr.p->clientConnectrec;
3763  signal->theData[1] = tcConnectptr.p->transid[0];
3764  signal->theData[2] = tcConnectptr.p->transid[1];
3765  sendSignal(atcBlockref, GSN_COMPLETED, signal, 3, JBB);
3766  return;
3767  }
3768 
3769  HostRecordPtr Thostptr;
3770  Thostptr.i = refToNode(atcBlockref);
3771  ptrCheckGuard(Thostptr, chostFileSize, hostRecord);
3772 
3773  Uint32 Tdata[3];
3774  Tdata[0] = tcConnectptr.p->clientConnectrec;
3775  Tdata[1] = tcConnectptr.p->transid[0];
3776  Tdata[2] = tcConnectptr.p->transid[1];
3777  Uint32 len = 3;
3778 
3779  // currently TC is single-threaded
3780  const bool send_unpacked = false;
3781  if (send_unpacked) {
3782  jam();
3783  memcpy(&signal->theData[0], &Tdata[0], len << 2);
3784  BlockReference tcRef = Thostptr.p->hostTcBlockRef;
3785  sendSignal(tcRef, GSN_COMMITTED, signal, len, JBB);
3786  return;
3787  }
3788 
3789  if (Thostptr.p->noOfPackedWordsTc > 22) {
3790  jam();
3791  sendPackedSignalTc(signal, Thostptr.p);
3792  } else {
3793  jam();
3794  updatePackedList(signal, Thostptr.p, Thostptr.i);
3795  }
3796 
3797  Tdata[0] |= (ZCOMPLETED << 28);
3798  Uint32 pos = Thostptr.p->noOfPackedWordsTc;
3799  memcpy(&Thostptr.p->packedWordsTc[pos], &Tdata[0], len << 2);
3800  Thostptr.p->noOfPackedWordsTc = pos + len;
3801 }
3802 
3803 void Dblqh::sendLqhkeyconfTc(Signal* signal, BlockReference atcBlockref)
3804 {
3805  LqhKeyConf* lqhKeyConf;
3806  HostRecordPtr Thostptr;
3807 
3808  bool packed= true;
3809  Thostptr.i = refToNode(atcBlockref);
3810  ptrCheckGuard(Thostptr, chostFileSize, hostRecord);
3811  if (refToBlock(atcBlockref) == DBTC) {
3812  jam();
3813 /*******************************************************************
3814 // This signal was intended for DBTC as part of the normal transaction
3815 // execution.
3816 ********************************************************************/
3817  if (Thostptr.p->noOfPackedWordsTc > (25 - LqhKeyConf::SignalLength)) {
3818  jam();
3819  sendPackedSignalTc(signal, Thostptr.p);
3820  } else {
3821  jam();
3822  updatePackedList(signal, Thostptr.p, Thostptr.i);
3823  }//if
3824  lqhKeyConf = (LqhKeyConf *)
3825  &Thostptr.p->packedWordsTc[Thostptr.p->noOfPackedWordsTc];
3826  Thostptr.p->noOfPackedWordsTc += LqhKeyConf::SignalLength;
3827  } else if(refToMain(atcBlockref) == DBLQH &&
3828  refToInstance(atcBlockref) == instance()) {
3829  //wl4391_todo check
3830  jam();
3831 /*******************************************************************
3832 // This signal was intended for DBLQH as part of log execution or
3833 // node recovery.
3834 ********************************************************************/
3835  if (Thostptr.p->noOfPackedWordsLqh > (25 - LqhKeyConf::SignalLength)) {
3836  jam();
3837  sendPackedSignalLqh(signal, Thostptr.p);
3838  } else {
3839  jam();
3840  updatePackedList(signal, Thostptr.p, Thostptr.i);
3841  }//if
3842  lqhKeyConf = (LqhKeyConf *)
3843  &Thostptr.p->packedWordsLqh[Thostptr.p->noOfPackedWordsLqh];
3844  Thostptr.p->noOfPackedWordsLqh += LqhKeyConf::SignalLength;
3845  } else {
3846  packed= false;
3847  lqhKeyConf = (LqhKeyConf *)signal->getDataPtrSend();
3848  }
3849  Uint32 ptrAndType = tcConnectptr.i | (ZLQHKEYCONF << 28);
3850  Uint32 tcOprec = tcConnectptr.p->tcOprec;
3851  Uint32 ownRef = cownref;
3852  Uint32 readlenAi = tcConnectptr.p->readlenAi;
3853  Uint32 transid1 = tcConnectptr.p->transid[0];
3854  Uint32 transid2 = tcConnectptr.p->transid[1];
3855  Uint32 noFiredTriggers = tcConnectptr.p->noFiredTriggers;
3856  lqhKeyConf->connectPtr = ptrAndType;
3857  lqhKeyConf->opPtr = tcOprec;
3858  lqhKeyConf->userRef = ownRef;
3859  lqhKeyConf->readLen = readlenAi;
3860  lqhKeyConf->transId1 = transid1;
3861  lqhKeyConf->transId2 = transid2;
3862  lqhKeyConf->noFiredTriggers = noFiredTriggers;
3863 
3864  if(!packed)
3865  {
3866  lqhKeyConf->connectPtr = tcConnectptr.i;
3867  if (instance() == refToInstance(atcBlockref) &&
3868  (Thostptr.i == 0 || Thostptr.i == getOwnNodeId()))
3869  {
3874  EXECUTE_DIRECT(refToMain(atcBlockref), GSN_LQHKEYCONF,
3875  signal, LqhKeyConf::SignalLength);
3876  }
3877  else
3878  {
3879  sendSignal(atcBlockref, GSN_LQHKEYCONF,
3880  signal, LqhKeyConf::SignalLength, JBB);
3881  }
3882  }
3883 }//Dblqh::sendLqhkeyconfTc()
3884 
3885 /* ************************************************************************>>
3886  * KEYINFO: Get tuple request from DBTC. Next step is to contact DBACC to get
3887  * key to tuple if all key/attrinfo has been received, else for more attrinfo
3888  * signals.
3889  * ************************************************************************>> */
3890 void Dblqh::execKEYINFO(Signal* signal)
3891 {
3892  Uint32 tcOprec = signal->theData[0];
3893  Uint32 transid1 = signal->theData[1];
3894  Uint32 transid2 = signal->theData[2];
3895  jamEntry();
3896  if (findTransaction(transid1, transid2, tcOprec, 0) != ZOK) {
3897  jam();
3898  return;
3899  }//if
3900 
3901  receive_keyinfo(signal,
3902  signal->theData+KeyInfo::HeaderLength,
3903  signal->getLength()-KeyInfo::HeaderLength);
3904 }
3905 
3906 void
3907 Dblqh::receive_keyinfo(Signal* signal,
3908  Uint32 * data, Uint32 len)
3909 {
3910  TcConnectionrec * const regTcPtr = tcConnectptr.p;
3911  TcConnectionrec::TransactionState state = regTcPtr->transactionState;
3912  if (state != TcConnectionrec::WAIT_TUPKEYINFO &&
3913  state != TcConnectionrec::WAIT_SCAN_AI)
3914  {
3915  jam();
3916 /*****************************************************************************/
3917 /* TRANSACTION WAS ABORTED, THIS IS MOST LIKELY A SIGNAL BELONGING TO THE */
3918 /* ABORTED TRANSACTION. THUS IGNORE THE SIGNAL. */
3919 /*****************************************************************************/
3920  return;
3921  }//if
3922 
3923  Uint32 errorCode =
3924  handleLongTupKey(signal, data, len);
3925 
3926  if (errorCode != 0) {
3927  if (errorCode == 1) {
3928  jam();
3929  return;
3930  }//if
3931  jam();
3932  terrorCode = errorCode;
3933  if(state == TcConnectionrec::WAIT_TUPKEYINFO)
3934  abortErrorLab(signal);
3935  else
3936  abort_scan(signal, regTcPtr->tcScanRec, errorCode);
3937  return;
3938  }//if
3939  if(state == TcConnectionrec::WAIT_TUPKEYINFO)
3940  {
3941  FragrecordPtr regFragptr;
3942  regFragptr.i = regTcPtr->fragmentptr;
3943  c_fragment_pool.getPtr(regFragptr);
3944  fragptr = regFragptr;
3945  endgettupkeyLab(signal);
3946  }
3947  return;
3948 }//Dblqh::execKEYINFO()
3949 
3950 /* ------------------------------------------------------------------------- */
3951 /* FILL IN KEY DATA INTO DATA BUFFERS. */
3952 /* ------------------------------------------------------------------------- */
3953 Uint32 Dblqh::handleLongTupKey(Signal* signal,
3954  Uint32* dataPtr,
3955  Uint32 len)
3956 {
3957  TcConnectionrec * const regTcPtr = tcConnectptr.p;
3958  Uint32 total = regTcPtr->save1 + len;
3959  Uint32 primKeyLen = regTcPtr->primKeyLen;
3960 
3961  if (unlikely(total > primKeyLen))
3962  {
3967  Uint32 extra = total - primKeyLen;
3968  ndbrequire(extra <= 3);
3969  ndbrequire(len > extra);
3970  len -= extra;
3971  }
3972 
3973  bool ok= appendToSection(regTcPtr->keyInfoIVal,
3974  dataPtr,
3975  len);
3976  if (unlikely(!ok))
3977  {
3978  jam();
3979  return ZGET_DATAREC_ERROR;
3980  }
3981 
3982  regTcPtr->save1 = total;
3983  return (total >= primKeyLen ? 0 : 1);
3984 }//Dblqh::handleLongTupKey()
3985 
3986 /* ------------------------------------------------------------------------- */
3987 /* ------- HANDLE ATTRINFO SIGNALS ------- */
3988 /* */
3989 /* ------------------------------------------------------------------------- */
3990 /* ************************************************************************>> */
3991 /* ATTRINFO: Continuation of KEYINFO signal (except for scans that do not use*/
3992 /* any KEYINFO). When all key and attribute info is received we contact DBACC*/
3993 /* for index handling. */
3994 /* ************************************************************************>> */
3995 void Dblqh::execATTRINFO(Signal* signal)
3996 {
3997  Uint32 tcOprec = signal->theData[0];
3998  Uint32 transid1 = signal->theData[1];
3999  Uint32 transid2 = signal->theData[2];
4000  jamEntry();
4001  if (findTransaction(transid1,
4002  transid2,
4003  tcOprec, 0) != ZOK) {
4004  jam();
4005  return;
4006  }//if
4007 
4008  receive_attrinfo(signal,
4009  signal->getDataPtrSend()+AttrInfo::HeaderLength,
4010  signal->getLength()-AttrInfo::HeaderLength);
4011 }//Dblqh::execATTRINFO()
4012 
4013 void
4014 Dblqh::receive_attrinfo(Signal* signal, Uint32 * dataPtr, Uint32 length)
4015 {
4016  TcConnectionrec * const regTcPtr = tcConnectptr.p;
4017  Uint32 totReclenAi = regTcPtr->totReclenAi;
4018  Uint32 currReclenAi = regTcPtr->currReclenAi + length;
4019  regTcPtr->currReclenAi = currReclenAi;
4020  if (totReclenAi == currReclenAi) {
4021  switch (regTcPtr->transactionState) {
4022  case TcConnectionrec::WAIT_ATTR:
4023  {
4024  jam();
4025  fragptr.i = regTcPtr->fragmentptr;
4026  c_fragment_pool.getPtr(fragptr);
4027  lqhAttrinfoLab(signal, dataPtr, length);
4028  endgettupkeyLab(signal);
4029  return;
4030  break;
4031  }
4032  case TcConnectionrec::WAIT_SCAN_AI:
4033  jam();
4034  scanAttrinfoLab(signal, dataPtr, length);
4035  return;
4036  break;
4037  case TcConnectionrec::WAIT_TUP_TO_ABORT:
4038  case TcConnectionrec::LOG_ABORT_QUEUED:
4039  case TcConnectionrec::ABORT_QUEUED:
4040  case TcConnectionrec::ABORT_STOPPED:
4041  case TcConnectionrec::WAIT_ACC_ABORT:
4042  case TcConnectionrec::WAIT_AI_AFTER_ABORT:
4043  jam();
4044  aiStateErrorCheckLab(signal, dataPtr,length);
4045  return;
4046  break;
4047  default:
4048  jam();
4049  ndbrequire(regTcPtr->abortState != TcConnectionrec::ABORT_IDLE);
4050  break;
4051  }//switch
4052  } else if (currReclenAi < totReclenAi) {
4053  jam();
4054  switch (regTcPtr->transactionState) {
4055  case TcConnectionrec::WAIT_ATTR:
4056  jam();
4057  lqhAttrinfoLab(signal, dataPtr, length);
4058  return;
4059  break;
4060  case TcConnectionrec::WAIT_SCAN_AI:
4061  jam();
4062  scanAttrinfoLab(signal, dataPtr, length);
4063  return;
4064  break;
4065  case TcConnectionrec::WAIT_TUP_TO_ABORT:
4066  case TcConnectionrec::LOG_ABORT_QUEUED:
4067  case TcConnectionrec::ABORT_QUEUED:
4068  case TcConnectionrec::ABORT_STOPPED:
4069  case TcConnectionrec::WAIT_ACC_ABORT:
4070  case TcConnectionrec::WAIT_AI_AFTER_ABORT:
4071  jam();
4072  aiStateErrorCheckLab(signal, dataPtr, length);
4073  return;
4074  break;
4075  default:
4076  jam();
4077  ndbrequire(regTcPtr->abortState != TcConnectionrec::ABORT_IDLE);
4078  break;
4079  }//switch
4080  } else {
4081  switch (regTcPtr->transactionState) {
4082  case TcConnectionrec::WAIT_SCAN_AI:
4083  jam();
4084  scanAttrinfoLab(signal, dataPtr, length);
4085  return;
4086  break;
4087  default:
4088  ndbout_c("%d", regTcPtr->transactionState);
4089  ndbrequire(false);
4090  break;
4091  }//switch
4092  }//if
4093  return;
4094 }
4095 
4096 /* ************************************************************************>> */
4097 /* TUP_ATTRINFO: Interpreted execution in DBTUP generates redo-log info */
4098 /* which is sent back to DBLQH for logging. This is because the decision */
4099 /* to execute or not is made in DBTUP and thus we cannot start logging until */
4100 /* DBTUP part has been run. */
4101 /* ************************************************************************>> */
4102 void Dblqh::execTUP_ATTRINFO(Signal* signal)
4103 {
4104  TcConnectionrec *regTcConnectionrec = tcConnectionrec;
4105  Uint32 tcIndex = signal->theData[0];
4106  Uint32 ttcConnectrecFileSize = ctcConnectrecFileSize;
4107  jamEntry();
4108  tcConnectptr.i = tcIndex;
4109  ptrCheckGuard(tcConnectptr, ttcConnectrecFileSize, regTcConnectionrec);
4110  TcConnectionrec * const regTcPtr = tcConnectptr.p;
4111 
4112  ndbrequire(regTcPtr->transactionState == TcConnectionrec::WAIT_TUP);
4113 
4114  /* TUP_ATTRINFO signal is unrelated to ATTRINFO
4115  * It just transports a section IVAL from TUP back to
4116  * LQH
4117  */
4118  ndbrequire(signal->header.theLength == 3);
4119  Uint32 tupAttrInfoWords= signal->theData[1];
4120  Uint32 tupAttrInfoIVal= signal->theData[2];
4121 
4122  ndbassert(tupAttrInfoWords > 0);
4123  ndbassert(tupAttrInfoIVal != RNIL);
4124 
4125  /* If we have stored ATTRINFO that we sent to TUP,
4126  * free it now
4127  */
4128  if (regTcPtr->attrInfoIVal != RNIL)
4129  {
4130  /* We should be expecting to receive attrInfo back */
4131  ndbassert( !(regTcPtr->m_flags &
4132  TcConnectionrec::OP_SAVEATTRINFO) );
4133  releaseSection( regTcPtr->attrInfoIVal );
4134  regTcPtr->attrInfoIVal= RNIL;
4135  }
4136 
4137  /* Store reference to ATTRINFO from TUP */
4138  regTcPtr->attrInfoIVal= tupAttrInfoIVal;
4139  regTcPtr->currTupAiLen= tupAttrInfoWords;
4140 
4141 }//Dblqh::execTUP_ATTRINFO()
4142 
4143 /* ------------------------------------------------------------------------- */
4144 /* ------- HANDLE ATTRINFO FROM LQH ------- */
4145 /* */
4146 /* ------------------------------------------------------------------------- */
4147 void Dblqh::lqhAttrinfoLab(Signal* signal, Uint32* dataPtr, Uint32 length)
4148 {
4149  /* Store received AttrInfo in a long section */
4150  jam();
4151  if (saveAttrInfoInSection(dataPtr, length) == ZOK) {
4152  ;
4153  } else {
4154  jam();
4155 /* ------------------------------------------------------------------------- */
4156 /* WE MIGHT BE WAITING FOR RESPONSE FROM SOME BLOCK HERE. THUS WE NEED TO */
4157 /* GO THROUGH THE STATE MACHINE FOR THE OPERATION. */
4158 /* ------------------------------------------------------------------------- */
4159  localAbortStateHandlerLab(signal);
4160  return;
4161  }//if
4162 }//Dblqh::lqhAttrinfoLab()
4163 
4164 /* ------------------------------------------------------------------------- */
4165 /* ------ FIND TRANSACTION BY USING HASH TABLE ------- */
4166 /* */
4167 /* ------------------------------------------------------------------------- */
4168 int Dblqh::findTransaction(UintR Transid1, UintR Transid2, UintR TcOprec,
4169  Uint32 hi)
4170 {
4171  TcConnectionrec *regTcConnectionrec = tcConnectionrec;
4172  Uint32 ttcConnectrecFileSize = ctcConnectrecFileSize;
4173  TcConnectionrecPtr locTcConnectptr;
4174 
4175  Uint32 ThashIndex = (Transid1 ^ TcOprec) & 1023;
4176  locTcConnectptr.i = ctransidHash[ThashIndex];
4177  while (locTcConnectptr.i != RNIL) {
4178  ptrCheckGuard(locTcConnectptr, ttcConnectrecFileSize, regTcConnectionrec);
4179  if ((locTcConnectptr.p->transid[0] == Transid1) &&
4180  (locTcConnectptr.p->transid[1] == Transid2) &&
4181  (locTcConnectptr.p->tcOprec == TcOprec) &&
4182  (locTcConnectptr.p->tcHashKeyHi == hi)) {
4183 /* FIRST PART OF TRANSACTION CORRECT */
4184 /* SECOND PART ALSO CORRECT */
4185 /* THE OPERATION RECORD POINTER IN TC WAS ALSO CORRECT */
4186  jam();
4187  tcConnectptr.i = locTcConnectptr.i;
4188  tcConnectptr.p = locTcConnectptr.p;
4189  return (int)ZOK;
4190  }//if
4191  jam();
4192 /* THIS WAS NOT THE TRANSACTION WHICH WAS SOUGHT */
4193  locTcConnectptr.i = locTcConnectptr.p->nextHashRec;
4194  }//while
4195 /* WE DID NOT FIND THE TRANSACTION, REPORT NOT FOUND */
4196  return (int)ZNOT_FOUND;
4197 }//Dblqh::findTransaction()
4198 
4199 /* ------------------------------------------------------------------------- */
4200 /* ------- SAVE ATTRINFO INTO ATTR SECTION ------- */
4201 /* */
4202 /* ------------------------------------------------------------------------- */
4203 int Dblqh::saveAttrInfoInSection(const Uint32* dataPtr, Uint32 len)
4204 {
4205  TcConnectionrec * const regTcPtr = tcConnectptr.p;
4206 
4207  bool ok= appendToSection(regTcPtr->attrInfoIVal,
4208  dataPtr,
4209  len);
4210 
4211  if (unlikely(!ok))
4212  {
4213  jam();
4214  terrorCode = ZGET_ATTRINBUF_ERROR;
4215  return ZGET_ATTRINBUF_ERROR;
4216  }//if
4217 
4218  if (regTcPtr->m_flags & TcConnectionrec::OP_SAVEATTRINFO)
4219  regTcPtr->currTupAiLen += len;
4220 
4221  return ZOK;
4222 } // saveAttrInfoInSection
4223 
4224 
4225 /* ==========================================================================
4226  * ======= SEIZE TC CONNECT RECORD =======
4227  *
4228  * GETS A NEW TC CONNECT RECORD FROM FREELIST.
4229  * ========================================================================= */
4230 void Dblqh::seizeTcrec()
4231 {
4232  TcConnectionrecPtr locTcConnectptr;
4233 
4234  locTcConnectptr.i = cfirstfreeTcConrec;
4235  ptrCheckGuard(locTcConnectptr, ctcConnectrecFileSize, tcConnectionrec);
4236  Uint32 nextTc = locTcConnectptr.p->nextTcConnectrec;
4237  locTcConnectptr.p->nextTcConnectrec = RNIL;
4238  locTcConnectptr.p->clientConnectrec = RNIL;
4239  locTcConnectptr.p->clientBlockref = RNIL;
4240  locTcConnectptr.p->abortState = TcConnectionrec::ABORT_IDLE;
4241  locTcConnectptr.p->tcTimer = cLqhTimeOutCount;
4242  locTcConnectptr.p->tableref = RNIL;
4243  locTcConnectptr.p->savePointId = 0;
4244  locTcConnectptr.p->gci_hi = 0;
4245  locTcConnectptr.p->gci_lo = 0;
4246  cfirstfreeTcConrec = nextTc;
4247  tcConnectptr = locTcConnectptr;
4248  locTcConnectptr.p->connectState = TcConnectionrec::CONNECTED;
4249 }//Dblqh::seizeTcrec()
4250 
4251 bool Dblqh::checkTransporterOverloaded(Signal* signal,
4252  const NodeBitmask& all,
4253  const LqhKeyReq* req)
4254 {
4255  // nodes likely to be affected by this op
4256  NodeBitmask mask;
4257  // tc
4258  Uint32 tc_node = refToNode(req->tcBlockref);
4259  if (tc_node < MAX_NODES) // not worth to crash here
4260  mask.set(tc_node);
4261  const Uint8 op = LqhKeyReq::getOperation(req->requestInfo);
4262  if (op == ZREAD || op == ZREAD_EX || op == ZUNLOCK) {
4263  // the receiver
4264  Uint32 api_node = refToNode(req->variableData[0]);
4265  if (api_node < MAX_NODES) // not worth to crash here
4266  mask.set(api_node);
4267  } else {
4268  // next replica
4269  Uint32 replica_node = LqhKeyReq::getNextReplicaNodeId(req->fragmentData);
4270  if (replica_node < MAX_NODES) // could be ZNIL
4271  mask.set(replica_node);
4272  // event subscribers
4273  const Suma* suma = (Suma*)globalData.getBlock(SUMA);
4274  mask.bitOR(suma->getSubscriberNodes());
4275  }
4276  mask.bitAND(all);
4277  return !mask.isclear();
4278 }
4279 
4280 void Dblqh::execSIGNAL_DROPPED_REP(Signal* signal)
4281 {
4282  /* An incoming signal was dropped, handle it
4283  * Dropped signal really means that we ran out of
4284  * long signal buffering to store its sections
4285  */
4286  jamEntry();
4287 
4288  if (!assembleDroppedFragments(signal))
4289  {
4290  jam();
4291  return;
4292  }
4293 
4294  const SignalDroppedRep* rep = (SignalDroppedRep*) &signal->theData[0];
4295  Uint32 originalGSN= rep->originalGsn;
4296 
4297  DEBUG("SignalDroppedRep received for GSN " << originalGSN);
4298 
4299  switch(originalGSN) {
4300  case GSN_LQHKEYREQ:
4301  {
4302  jam();
4303  /* Get original signal data - unfortunately it may
4304  * have been truncated. We must not read beyond
4305  * word # 22
4306  * We will notify the client that their LQHKEYREQ
4307  * failed
4308  */
4309  const LqhKeyReq * const truncatedLqhKeyReq =
4310  (LqhKeyReq *) &rep->originalData[0];
4311 
4312  noFreeRecordLab(signal, truncatedLqhKeyReq, ZGET_DATAREC_ERROR);
4313 
4314  break;
4315  }
4316  case GSN_SCAN_FRAGREQ:
4317  {
4318  jam();
4319  /* Get original signal data - unfortunately it may
4320  * have been truncated. We must not read beyond
4321  * word # 22
4322  * We will notify the client that their SCAN_FRAGREQ
4323  * failed
4324  */
4325  // TODO : Handle fragmented failure
4326  const ScanFragReq* const truncatedScanFragReq =
4327  (ScanFragReq*) &rep->originalData[0];
4328  const Uint32 senderData= truncatedScanFragReq->senderData;
4329  const Uint32 transid1= truncatedScanFragReq->transId1;
4330  const Uint32 transid2= truncatedScanFragReq->transId2;
4331 
4332  /* Send SCAN_FRAGREF back to the client */
4333  ScanFragRef* ref= (ScanFragRef*)&signal->theData[0];
4334  ref->senderData= senderData;
4335  ref->transId1= transid1;
4336  ref->transId2= transid2;
4337  ref->errorCode= ZGET_ATTRINBUF_ERROR;
4338 
4339  sendSignal(signal->senderBlockRef(), GSN_SCAN_FRAGREF, signal,
4340  ScanFragRef::SignalLength, JBB);
4341  break;
4342  }
4343  default:
4344  jam();
4345  /* Don't expect dropped signals for other GSNs,
4346  * default handling
4347  */
4348  SimulatedBlock::execSIGNAL_DROPPED_REP(signal);
4349  };
4350 
4351  return;
4352 }
4353 
4354 /* ------------------------------------------------------------------------- */
4355 /* ------- TAKE CARE OF LQHKEYREQ ------- */
4356 /* LQHKEYREQ IS THE SIGNAL THAT STARTS ALL OPERATIONS IN THE LQH BLOCK */
4357 /* THIS SIGNAL CONTAINS A LOT OF INFORMATION ABOUT WHAT TYPE OF OPERATION, */
4358 /* KEY INFORMATION, ATTRIBUTE INFORMATION, NODE INFORMATION AND A LOT MORE */
4359 /* ------------------------------------------------------------------------- */
4360 void Dblqh::execLQHKEYREQ(Signal* signal)
4361 {
4362  UintR sig0, sig1, sig2, sig3, sig4, sig5;
4363  Uint8 tfragDistKey;
4364 
4365  const LqhKeyReq * const lqhKeyReq = (LqhKeyReq *)signal->getDataPtr();
4366  SectionHandle handle(this, signal);
4367 
4368  {
4369  const NodeBitmask& all = globalTransporterRegistry.get_status_overloaded();
4370  if (unlikely((!all.isclear() &&
4371  checkTransporterOverloaded(signal, all, lqhKeyReq))) ||
4372  ERROR_INSERTED_CLEAR(5047)) {
4373  jam();
4374  releaseSections(handle);
4375  noFreeRecordLab(signal, lqhKeyReq, ZTRANSPORTER_OVERLOADED_ERROR);
4376  return;
4377  }
4378  }
4379 
4380  sig0 = lqhKeyReq->clientConnectPtr;
4381  if (cfirstfreeTcConrec != RNIL && !ERROR_INSERTED_CLEAR(5031)) {
4382  jamEntry();
4383  seizeTcrec();
4384  } else {
4385 /* ------------------------------------------------------------------------- */
4386 /* NO FREE TC RECORD AVAILABLE, THUS WE CANNOT HANDLE THE REQUEST. */
4387 /* ------------------------------------------------------------------------- */
4388  releaseSections(handle);
4389  noFreeRecordLab(signal, lqhKeyReq, ZNO_TC_CONNECT_ERROR);
4390  return;
4391  }//if
4392 
4393  if(ERROR_INSERTED(5038) &&
4394  refToNode(signal->getSendersBlockRef()) != getOwnNodeId()){
4395  jam();
4396  releaseSections(handle);
4397  SET_ERROR_INSERT_VALUE(5039);
4398  return;
4399  }
4400 
4401  cTotalLqhKeyReqCount++;
4402  c_Counters.operations++;
4403 
4404  TcConnectionrec * const regTcPtr = tcConnectptr.p;
4405  Uint32 senderRef = regTcPtr->clientBlockref = signal->senderBlockRef();
4406  regTcPtr->clientConnectrec = sig0;
4407  regTcPtr->tcOprec = sig0;
4408  regTcPtr->tcHashKeyHi = 0;
4409  regTcPtr->storedProcId = ZNIL;
4410  regTcPtr->lqhKeyReqId = cTotalLqhKeyReqCount;
4411  regTcPtr->m_flags= 0;
4412  bool isLongReq= false;
4413  if (handle.m_cnt > 0)
4414  {
4415  isLongReq= true;
4416  regTcPtr->m_flags|= TcConnectionrec::OP_ISLONGREQ;
4417  }
4418 
4419  UintR attrLenFlags = lqhKeyReq->attrLen;
4420  sig1 = lqhKeyReq->savePointId;
4421  sig2 = lqhKeyReq->hashValue;
4422  UintR Treqinfo = lqhKeyReq->requestInfo;
4423  sig4 = lqhKeyReq->tableSchemaVersion;
4424  sig5 = lqhKeyReq->tcBlockref;
4425 
4426  regTcPtr->savePointId = sig1;
4427  regTcPtr->hashValue = sig2;
4428  const Uint32 schemaVersion = regTcPtr->schemaVersion = LqhKeyReq::getSchemaVersion(sig4);
4429  tabptr.i = LqhKeyReq::getTableId(sig4);
4430  regTcPtr->tcBlockref = sig5;
4431 
4432  const Uint8 op = LqhKeyReq::getOperation(Treqinfo);
4433  if ((op == ZREAD || op == ZREAD_EX) && !getAllowRead()){
4434  releaseSections(handle);
4435  noFreeRecordLab(signal, lqhKeyReq, ZNODE_SHUTDOWN_IN_PROGESS);
4436  return;
4437  }
4438 
4439  if (unlikely(get_node_status(refToNode(sig5)) != ZNODE_UP))
4440  {
4441  releaseSections(handle);
4442  noFreeRecordLab(signal, lqhKeyReq, ZNODE_FAILURE_ERROR);
4443  return;
4444  }
4445 
4446  Uint32 senderVersion = getNodeInfo(refToNode(senderRef)).m_version;
4447 
4448  regTcPtr->tcScanInfo = lqhKeyReq->scanInfo;
4449  regTcPtr->indTakeOver = LqhKeyReq::getScanTakeOverFlag(attrLenFlags);
4450  regTcPtr->m_reorg = LqhKeyReq::getReorgFlag(attrLenFlags);
4451 
4452  regTcPtr->readlenAi = 0;
4453  regTcPtr->currTupAiLen = 0;
4454  regTcPtr->listState = TcConnectionrec::NOT_IN_LIST;
4455  regTcPtr->logWriteState = TcConnectionrec::NOT_STARTED;
4456  regTcPtr->fragmentptr = RNIL;
4457 
4458  sig0 = lqhKeyReq->fragmentData;
4459  sig1 = lqhKeyReq->transId1;
4460  sig2 = lqhKeyReq->transId2;
4461  sig3 = lqhKeyReq->variableData[0];
4462  sig4 = lqhKeyReq->variableData[1];
4463 
4464  regTcPtr->fragmentid = LqhKeyReq::getFragmentId(sig0);
4465  regTcPtr->nextReplica = LqhKeyReq::getNextReplicaNodeId(sig0);
4466  regTcPtr->transid[0] = sig1;
4467  regTcPtr->transid[1] = sig2;
4468  regTcPtr->applRef = sig3;
4469  regTcPtr->applOprec = sig4;
4470 
4471  regTcPtr->commitAckMarker = RNIL;
4472  if (LqhKeyReq::getMarkerFlag(Treqinfo))
4473  {
4474  struct CommitAckMarker check;
4475  CommitAckMarkerPtr markerPtr;
4476  jam();
4477  check.transid1 = regTcPtr->transid[0];
4478  check.transid2 = regTcPtr->transid[1];
4479 
4480  if (m_commitAckMarkerHash.find(markerPtr, check))
4481  {
4482  /*
4483  A commit ack marker was already placed here for this transaction.
4484  We increase the reference count to ensure we don't remove the
4485  commit ack marker prematurely.
4486  */
4487  markerPtr.p->reference_count++;
4488 #ifdef MARKER_TRACE
4489  ndbout_c("Inc marker[%.8x %.8x] op: %u ref: %u",
4490  markerPtr.p->transid1, markerPtr.p->transid2,
4491  tcConnectptr.i, markerPtr.p->reference_count);
4492 #endif
4493  }
4494  else
4495  {
4496  m_commitAckMarkerHash.seize(markerPtr);
4497  if (markerPtr.i == RNIL)
4498  {
4499  releaseSections(handle);
4500  noFreeRecordLab(signal, lqhKeyReq, ZNO_FREE_MARKER_RECORDS_ERROR);
4501  return;
4502  }
4503  markerPtr.p->transid1 = sig1;
4504  markerPtr.p->transid2 = sig2;
4505  markerPtr.p->apiRef = sig3;
4506  markerPtr.p->apiOprec = sig4;
4507  const NodeId tcNodeId = refToNode(sig5);
4508  markerPtr.p->tcNodeId = tcNodeId;
4509  markerPtr.p->reference_count = 1;
4510  m_commitAckMarkerHash.add(markerPtr);
4511 
4512 #ifdef MARKER_TRACE
4513  ndbout_c("%u Add marker[%.8x %.8x] op: %u", instance(), markerPtr.p->transid1, markerPtr.p->transid2, tcConnectptr.i);
4514 #endif
4515  }
4516  regTcPtr->commitAckMarker = markerPtr.i;
4517  }
4518 
4519  regTcPtr->reqinfo = Treqinfo;
4520  regTcPtr->lastReplicaNo = LqhKeyReq::getLastReplicaNo(Treqinfo);
4521  regTcPtr->dirtyOp = LqhKeyReq::getDirtyFlag(Treqinfo);
4522  regTcPtr->opExec = LqhKeyReq::getInterpretedFlag(Treqinfo);
4523  regTcPtr->opSimple = LqhKeyReq::getSimpleFlag(Treqinfo);
4524  regTcPtr->seqNoReplica = LqhKeyReq::getSeqNoReplica(Treqinfo);
4525  regTcPtr->apiVersionNo = 0;
4526  regTcPtr->m_use_rowid = LqhKeyReq::getRowidFlag(Treqinfo);
4527  regTcPtr->m_dealloc = 0;
4528  if (unlikely(senderVersion < NDBD_ROWID_VERSION))
4529  {
4530  regTcPtr->operation = op;
4531  regTcPtr->lockType = LqhKeyReq::getLockType(Treqinfo);
4532  }
4533  else
4534  {
4535  regTcPtr->operation = (Operation_t) op == ZREAD_EX ? ZREAD : (Operation_t) op;
4536  regTcPtr->lockType =
4537  op == ZREAD_EX ? ZUPDATE :
4538  (Operation_t) op == ZWRITE ? ZINSERT :
4539  (Operation_t) op == ZREFRESH ? ZINSERT :
4540  (Operation_t) op == ZUNLOCK ? ZREAD : // lockType not relevant for unlock req
4541  (Operation_t) op;
4542  }
4543 
4544  if (regTcPtr->dirtyOp)
4545  {
4546  ndbrequire(regTcPtr->opSimple);
4547  }
4548 
4549  CRASH_INSERTION2(5041, (op == ZREAD &&
4550  (regTcPtr->opSimple || regTcPtr->dirtyOp) &&
4551  refToNode(signal->senderBlockRef()) != cownNodeid));
4552 
4553  regTcPtr->noFiredTriggers = lqhKeyReq->noFiredTriggers;
4554 
4555  UintR TapplAddressInd = LqhKeyReq::getApplicationAddressFlag(Treqinfo);
4556  UintR nextPos = (TapplAddressInd << 1);
4557  UintR TsameClientAndTcOprec = LqhKeyReq::getSameClientAndTcFlag(Treqinfo);
4558  if (TsameClientAndTcOprec == 1) {
4559  regTcPtr->tcOprec = lqhKeyReq->variableData[nextPos];
4560  nextPos++;
4561  }//if
4562  UintR TnextReplicasIndicator = regTcPtr->lastReplicaNo -
4563  regTcPtr->seqNoReplica;
4564  if (TnextReplicasIndicator > 1) {
4565  regTcPtr->nodeAfterNext[0] = lqhKeyReq->variableData[nextPos] & 0xFFFF;
4566  regTcPtr->nodeAfterNext[1] = lqhKeyReq->variableData[nextPos] >> 16;
4567  nextPos++;
4568  }//if
4569  UintR TstoredProcIndicator = LqhKeyReq::getStoredProcFlag(attrLenFlags);
4570  if (TstoredProcIndicator == 1) {
4571  regTcPtr->storedProcId = lqhKeyReq->variableData[nextPos] & ZNIL;
4572  nextPos++;
4573  }//if
4574  UintR TreadLenAiIndicator = LqhKeyReq::getReturnedReadLenAIFlag(Treqinfo);
4575  if (TreadLenAiIndicator == 1) {
4576  regTcPtr->readlenAi = lqhKeyReq->variableData[nextPos] & ZNIL;
4577  nextPos++;
4578  }//if
4579 
4580  Uint32 TanyValueFlag = LqhKeyReq::getCorrFactorFlag(Treqinfo);
4581  if (isLongReq && TanyValueFlag == 1)
4582  {
4586  regTcPtr->m_corrFactorLo = lqhKeyReq->variableData[nextPos + 0];
4587  regTcPtr->m_corrFactorHi = lqhKeyReq->variableData[nextPos + 1];
4588  nextPos += 2;
4589  }
4590 
4591  Uint32 Tdeferred = LqhKeyReq::getDeferredConstraints(Treqinfo);
4592  if (isLongReq && Tdeferred)
4593  {
4594  regTcPtr->m_flags |= TcConnectionrec::OP_DEFERRED_CONSTRAINTS;
4595  regTcPtr->m_fire_trig_pass = 0;
4596  }
4597 
4598  UintR TitcKeyLen = 0;
4599  Uint32 keyLenWithLQHReq = 0;
4600  UintR TreclenAiLqhkey = 0;
4601 
4602  if (isLongReq)
4603  {
4604  /* Long LQHKEYREQ indicates Key and AttrInfo presence and
4605  * size via section lengths
4606  */
4607  SegmentedSectionPtr keyInfoSection, attrInfoSection;
4608 
4609  handle.getSection(keyInfoSection,
4610  LqhKeyReq::KeyInfoSectionNum);
4611 
4612  ndbassert(keyInfoSection.i != RNIL);
4613 
4614  regTcPtr->keyInfoIVal= keyInfoSection.i;
4615  TitcKeyLen= keyInfoSection.sz;
4616  keyLenWithLQHReq= TitcKeyLen;
4617 
4618  Uint32 totalAttrInfoLen= 0;
4619  if (handle.getSection(attrInfoSection,
4620  LqhKeyReq::AttrInfoSectionNum))
4621  {
4622  regTcPtr->attrInfoIVal= attrInfoSection.i;
4623  totalAttrInfoLen= attrInfoSection.sz;
4624  }
4625 
4626  regTcPtr->reclenAiLqhkey = 0;
4627  regTcPtr->currReclenAi = totalAttrInfoLen;
4628  regTcPtr->totReclenAi = totalAttrInfoLen;
4629 
4630  /* Detach sections from the handle, we are now responsible
4631  * for freeing them when appropriate
4632  */
4633  handle.clear();
4634  }
4635  else
4636  {
4637  /* Short LQHKEYREQ, Key and Attr sizes are in
4638  * signal, along with some data
4639  */
4640  TreclenAiLqhkey= LqhKeyReq::getAIInLqhKeyReq(Treqinfo);
4641  regTcPtr->reclenAiLqhkey = TreclenAiLqhkey;
4642  regTcPtr->currReclenAi = TreclenAiLqhkey;
4643  TitcKeyLen = LqhKeyReq::getKeyLen(Treqinfo);
4644  regTcPtr->totReclenAi = LqhKeyReq::getAttrLen(attrLenFlags);
4645 
4646  /* Note key can be length zero for NR when Rowid used */
4647  keyLenWithLQHReq= MIN(TitcKeyLen, LqhKeyReq::MaxKeyInfo);
4648 
4649  bool ok= appendToSection(regTcPtr->keyInfoIVal,
4650  &lqhKeyReq->variableData[ nextPos ],
4651  keyLenWithLQHReq);
4652  if (unlikely(!ok))
4653  {
4654  jam();
4655  terrorCode= ZGET_DATAREC_ERROR;
4656  abortErrorLab(signal);
4657  return;
4658  }
4659 
4660  nextPos+= keyLenWithLQHReq;
4661  }
4662 
4663  regTcPtr->primKeyLen = TitcKeyLen;
4664 
4665  /* Only node restart copy allowed to send no KeyInfo */
4666  if (unlikely(keyLenWithLQHReq == 0))
4667  {
4668  if (refToMain(senderRef) == DBSPJ)
4669  {
4670  jam();
4671  ndbassert(! LqhKeyReq::getNrCopyFlag(Treqinfo));
4672  terrorCode = ZNO_TUPLE_FOUND;
4673  abortErrorLab(signal);
4674  return;
4675  }
4676 
4677  if (! LqhKeyReq::getNrCopyFlag(Treqinfo))
4678  {
4679  LQHKEY_error(signal, 3);
4680  return;
4681  }//if
4682  }
4683 
4684  sig0 = lqhKeyReq->variableData[nextPos + 0];
4685  sig1 = lqhKeyReq->variableData[nextPos + 1];
4686  regTcPtr->m_row_id.m_page_no = sig0;
4687  regTcPtr->m_row_id.m_page_idx = sig1;
4688  nextPos += 2 * LqhKeyReq::getRowidFlag(Treqinfo);
4689 
4690  sig2 = lqhKeyReq->variableData[nextPos + 0];
4691  sig3 = cnewestGci;
4692  /* If gci_hi provided, take it and set gci_lo to max value
4693  * Otherwise, it will be decided by TUP at commit time as normal
4694  */
4695  regTcPtr->gci_hi = LqhKeyReq::getGCIFlag(Treqinfo) ? sig2 : sig3;
4696  regTcPtr->gci_lo = LqhKeyReq::getGCIFlag(Treqinfo) ? ~Uint32(0) : 0;
4697  nextPos += LqhKeyReq::getGCIFlag(Treqinfo);
4698 
4699  if (LqhKeyReq::getRowidFlag(Treqinfo))
4700  {
4701  ndbassert(refToMain(senderRef) != DBTC);
4702  }
4703  else if(op == ZINSERT)
4704  {
4705  ndbassert(refToMain(senderRef) == DBTC);
4706  }
4707 
4708  if ((LqhKeyReq::FixedSignalLength + nextPos + TreclenAiLqhkey) !=
4709  signal->length()) {
4710  LQHKEY_error(signal, 2);
4711  return;
4712  }//if
4713  UintR TseqNoReplica = regTcPtr->seqNoReplica;
4714  UintR TlastReplicaNo = regTcPtr->lastReplicaNo;
4715  if (TseqNoReplica == TlastReplicaNo) {
4716  jam();
4717  regTcPtr->nextReplica = ZNIL;
4718  } else {
4719  if (TseqNoReplica < TlastReplicaNo) {
4720  jam();
4721  regTcPtr->nextSeqNoReplica = TseqNoReplica + 1;
4722  if ((regTcPtr->nextReplica == 0) ||
4723  (regTcPtr->nextReplica == cownNodeid)) {
4724  LQHKEY_error(signal, 0);
4725  }//if
4726  } else {
4727  LQHKEY_error(signal, 4);
4728  return;
4729  }//if
4730  }//if
4731  TcConnectionrecPtr localNextTcConnectptr;
4732  Uint32 hashIndex = (regTcPtr->transid[0] ^ regTcPtr->tcOprec) & 1023;
4733  localNextTcConnectptr.i = ctransidHash[hashIndex];
4734  ctransidHash[hashIndex] = tcConnectptr.i;
4735  regTcPtr->prevHashRec = RNIL;
4736  regTcPtr->nextHashRec = localNextTcConnectptr.i;
4737  if (localNextTcConnectptr.i != RNIL) {
4738 /* -------------------------------------------------------------------------- */
4739 /* ENSURE THAT THE NEXT RECORD HAS SET PREVIOUS TO OUR RECORD IF IT EXISTS */
4740 /* -------------------------------------------------------------------------- */
4741  ptrCheckGuard(localNextTcConnectptr,
4742  ctcConnectrecFileSize, tcConnectionrec);
4743  jam();
4744  localNextTcConnectptr.p->prevHashRec = tcConnectptr.i;
4745  }//if
4746  if (tabptr.i >= ctabrecFileSize) {
4747  LQHKEY_error(signal, 5);
4748  return;
4749  }//if
4750  ptrAss(tabptr, tablerec);
4751  if(table_version_major_lqhkeyreq(tabptr.p->schemaVersion) !=
4752  table_version_major_lqhkeyreq(schemaVersion)){
4753  LQHKEY_abort(signal, 5);
4754  return;
4755  }
4756 
4757  if (unlikely(tabptr.p->tableStatus != Tablerec::TABLE_DEFINED))
4758  {
4759  if (check_tabstate(signal, tabptr.p, op))
4760  return;
4761  }
4762 
4763  regTcPtr->tableref = tabptr.i;
4764  regTcPtr->m_disk_table = tabptr.p->m_disk_table;
4765  if(refToMain(signal->senderBlockRef()) == RESTORE)
4766  regTcPtr->m_disk_table &= !LqhKeyReq::getNoDiskFlag(Treqinfo);
4767  else if(op == ZREAD || op == ZREAD_EX || op == ZUPDATE)
4768  regTcPtr->m_disk_table &= !LqhKeyReq::getNoDiskFlag(Treqinfo);
4769 
4770  if (op == ZREAD || op == ZREAD_EX || op == ZUNLOCK)
4771  tabptr.p->usageCountR++;
4772  else
4773  tabptr.p->usageCountW++;
4774 
4775  if (!getFragmentrec(signal, regTcPtr->fragmentid)) {
4776  LQHKEY_error(signal, 6);
4777  return;
4778  }//if
4779 
4780  if (LqhKeyReq::getNrCopyFlag(Treqinfo))
4781  {
4782  ndbassert(refToMain(senderRef) == DBLQH);
4783  ndbassert(LqhKeyReq::getRowidFlag(Treqinfo));
4784  if (! (fragptr.p->fragStatus == Fragrecord::ACTIVE_CREATION))
4785  {
4786  ndbout_c("fragptr.p->fragStatus: %d",
4787  fragptr.p->fragStatus);
4788  CRASH_INSERTION(5046);
4789  }
4790  ndbassert(fragptr.p->fragStatus == Fragrecord::ACTIVE_CREATION);
4791  fragptr.p->m_copy_started_state = Fragrecord::AC_NR_COPY;
4792  }
4793 
4794  Uint8 TcopyType = fragptr.p->fragCopy;
4795  Uint32 logPart = fragptr.p->m_log_part_ptr_i;
4796  tfragDistKey = fragptr.p->fragDistributionKey;
4797  if (fragptr.p->fragStatus == Fragrecord::ACTIVE_CREATION) {
4798  jam();
4799  regTcPtr->activeCreat = fragptr.p->m_copy_started_state;
4800  CRASH_INSERTION(5002);
4801  CRASH_INSERTION2(5042, tabptr.i == c_error_insert_table_id);
4802  } else {
4803  regTcPtr->activeCreat = Fragrecord::AC_NORMAL;
4804  }//if
4805  regTcPtr->replicaType = TcopyType;
4806  regTcPtr->fragmentptr = fragptr.i;
4807  regTcPtr->m_log_part_ptr_i = logPart;
4808  Uint8 TdistKey = LqhKeyReq::getDistributionKey(attrLenFlags);
4809  if ((tfragDistKey != TdistKey) &&
4810  (regTcPtr->seqNoReplica == 0) &&
4811  (regTcPtr->dirtyOp == ZFALSE))
4812  {
4813  /* ----------------------------------------------------------------------
4814  * WE HAVE DIFFERENT OPINION THAN THE DIH THAT STARTED THE TRANSACTION.
4815  * THE REASON COULD BE THAT THIS IS AN OLD DISTRIBUTION WHICH IS NO LONGER
4816  * VALID TO USE. THIS MUST BE CHECKED.
4817  * ONE IS ADDED TO THE DISTRIBUTION KEY EVERY TIME WE ADD A NEW REPLICA.
4818  * FAILED REPLICAS DO NOT AFFECT THE DISTRIBUTION KEY. THIS MEANS THAT THE
4819  * MAXIMUM DEVIATION CAN BE ONE BETWEEN THOSE TWO VALUES.
4820  * --------------------------------------------------------------------- */
4821  Int8 tmp = (TdistKey - tfragDistKey);
4822  tmp = (tmp < 0 ? - tmp : tmp);
4823  if ((tmp <= 1) || (tfragDistKey == 0)) {
4824  LQHKEY_abort(signal, 0);
4825  return;
4826  }//if
4827  LQHKEY_error(signal, 1);
4828  // Never get here
4829  }//if
4830 
4831  /*
4832  * Interpreted updates and deletes may require different AttrInfo in
4833  * different replicas, as only the primary executes the interpreted
4834  * program, and the effect of the program rather than the program
4835  * should be logged.
4836  * Non interpreted inserts, updates, writes and deletes use the same
4837  * AttrInfo in all replicas.
4838  * All reads only run on one replica, and are not logged.
4839  * The AttrInfo section is passed to TUP attached to the TUPKEYREQ
4840  * signal below.
4841  *
4842  * Normal processing :
4843  * - LQH passes ATTRINFO section to TUP attached to direct TUPKEYREQ
4844  * signal
4845  * - TUP processes request and sends direct TUPKEYCONF back to LQH
4846  * - LQH continues processing (logging, forwarding LQHKEYREQ to other
4847  * replicas as necessary)
4848  * - LQH frees ATTRINFO section
4849  * Note that TUP is not responsible for freeing the passed ATTRINFO
4850  * section, LQH is.
4851  *
4852  * Interpreted Update / Delete processing
4853  * - LQH passes ATTRINFO section to TUP attached to direct TUPKEYREQ
4854  * signal
4855  * - TUP processes request, generating new ATTRINFO data
4856  * - If new AttrInfo data is > 0 words, TUP sends it back to LQH as
4857  * a long section attached to a single ATTRINFO signal.
4858  * - LQH frees the original AttrInfo section and stores a ref to
4859  * the new section
4860  * - TUP sends direct TUPKEYCONF back to LQH with new ATTRINFO length
4861  * - If the new ATTRINFO is > 0 words,
4862  * - LQH continues processing with it (logging, forwarding
4863  * LQHKEYREQ to other replicas as necessary)
4864  * - LQH frees the new ATTRINFO section
4865  * - If the new ATTRINFO is 0 words, LQH frees the original ATTRINFO
4866  * section and continues processing (logging, forwarding LQHKEYREQ
4867  * to other replicas as necessary)
4868  *
4869  */
4870  bool attrInfoToPropagate=
4871  (regTcPtr->totReclenAi != 0) &&
4872  (regTcPtr->operation != ZREAD) &&
4873  (regTcPtr->operation != ZDELETE) &&
4874  (regTcPtr->operation != ZUNLOCK);
4875  bool tupCanChangePropagatedAttrInfo= (regTcPtr->opExec == 1);
4876 
4877  bool saveAttrInfo=
4878  attrInfoToPropagate &&
4879  (! tupCanChangePropagatedAttrInfo);
4880 
4881  if (saveAttrInfo)
4882  regTcPtr->m_flags|= TcConnectionrec::OP_SAVEATTRINFO;
4883 
4884  /* Handle any AttrInfo we received with the LQHKEYREQ */
4885  if (regTcPtr->currReclenAi != 0)
4886  {
4887  jam();
4888  if (isLongReq)
4889  {
4890  /* Long LQHKEYREQ */
4891  jam();
4892 
4893  regTcPtr->currTupAiLen= saveAttrInfo ?
4894  regTcPtr->totReclenAi :
4895  0;
4896  }
4897  else
4898  {
4899  /* Short LQHKEYREQ */
4900  jam();
4901 
4902  /* Lets put the AttrInfo into a segmented section */
4903  bool ok= appendToSection(regTcPtr->attrInfoIVal,
4904  lqhKeyReq->variableData + nextPos,
4905  TreclenAiLqhkey);
4906  if (unlikely(!ok))
4907  {
4908  jam();
4909  terrorCode= ZGET_DATAREC_ERROR;
4910  abortErrorLab(signal);
4911  return;
4912  }
4913 
4914  if (saveAttrInfo)
4915  regTcPtr->currTupAiLen= TreclenAiLqhkey;
4916  }
4917  }//if
4918 
4919  /* If we've received all KeyInfo, proceed with processing,
4920  * otherwise wait for discrete KeyInfo signals
4921  */
4922  if (regTcPtr->primKeyLen == keyLenWithLQHReq) {
4923  endgettupkeyLab(signal);
4924  return;
4925  } else {
4926  jam();
4927  ndbassert(!isLongReq);
4928  /* Wait for remaining KeyInfo */
4929  regTcPtr->save1 = keyLenWithLQHReq;
4930  regTcPtr->transactionState = TcConnectionrec::WAIT_TUPKEYINFO;
4931  return;
4932  }//if
4933  return;
4934 }//Dblqh::execLQHKEYREQ()
4935 
4936 
4937 
4943 void Dblqh::endgettupkeyLab(Signal* signal)
4944 {
4945  TcConnectionrec * const regTcPtr = tcConnectptr.p;
4946  if (regTcPtr->totReclenAi == regTcPtr->currReclenAi) {
4947  ;
4948  } else {
4949  jam();
4950  /* Wait for discrete AttrInfo signals */
4951  ndbrequire(regTcPtr->currReclenAi < regTcPtr->totReclenAi);
4952  ndbassert( !(regTcPtr->m_flags &
4953  TcConnectionrec::OP_ISLONGREQ) );
4954  regTcPtr->transactionState = TcConnectionrec::WAIT_ATTR;
4955  return;
4956  }//if
4957 
4958 /* ---------------------------------------------------------------------- */
4959 /* NOW RECEPTION OF LQHKEYREQ IS COMPLETED THE NEXT STEP IS TO START*/
4960 /* PROCESSING THE MESSAGE. IF THE MESSAGE IS TO A STAND-BY NODE */
4961 /* WITHOUT NETWORK REDUNDANCY OR PREPARE-TO-COMMIT ACTIVATED THE */
4962 /* PREPARATION TO SEND TO THE NEXT NODE WILL START IMMEDIATELY. */
4963 /* */
4964 /* OTHERWISE THE PROCESSING WILL START AFTER SETTING THE PROPER */
4965 /* STATE. HOWEVER BEFORE PROCESSING THE MESSAGE */
4966 /* IT IS NECESSARY TO CHECK THAT THE FRAGMENT IS NOT PERFORMING */
4967 /* A CHECKPOINT. THE OPERATION SHALL ALSO BE LINKED INTO THE */
4968 /* FRAGMENT QUEUE OR LIST OF ACTIVE OPERATIONS. */
4969 /* */
4970 /* THE FIRST STEP IN PROCESSING THE MESSAGE IS TO CONTACT DBACC. */
4971 /*------------------------------------------------------------------------*/
4972  switch (fragptr.p->fragStatus) {
4973  case Fragrecord::FSACTIVE:
4976  prepareContinueAfterBlockedLab(signal);
4977  return;
4978  break;
4979  case Fragrecord::BLOCKED:
4980  jam();
4981  linkFragQueue(signal);
4982  regTcPtr->transactionState = TcConnectionrec::STOPPED;
4983  return;
4984  break;
4985  case Fragrecord::FREE:
4986  jam();
4987  case Fragrecord::DEFINED:
4988  jam();
4989  case Fragrecord::REMOVING:
4990  jam();
4991  default:
4992  ndbrequire(false);
4993  break;
4994  }//switch
4995  return;
4996 }//Dblqh::endgettupkeyLab()
4997 
4998 void Dblqh::prepareContinueAfterBlockedLab(Signal* signal)
4999 {
5000  UintR ttcScanOp;
5001 
5002 /* -------------------------------------------------------------------------- */
5003 /* INPUT: TC_CONNECTPTR ACTIVE CONNECTION RECORD */
5004 /* FRAGPTR FRAGMENT RECORD */
5005 /* -------------------------------------------------------------------------- */
5006 /* -------------------------------------------------------------------------- */
5007 /* CONTINUE HERE AFTER BEING BLOCKED FOR A WHILE DURING LOCAL CHECKPOINT. */
5008 /* -------------------------------------------------------------------------- */
5009 /* ALSO AFTER NORMAL PROCEDURE WE CONTINUE HERE */
5010 /* -------------------------------------------------------------------------- */
5011  Uint32 tc_ptr_i = tcConnectptr.i;
5012  TcConnectionrec * const regTcPtr = tcConnectptr.p;
5013  Uint32 activeCreat = regTcPtr->activeCreat;
5014  if (regTcPtr->operation == ZUNLOCK)
5015  {
5016  jam();
5017  handleUserUnlockRequest(signal);
5018  return;
5019  }
5020 
5021  if (regTcPtr->indTakeOver == ZTRUE) {
5022  jam();
5023  ttcScanOp = KeyInfo20::getScanOp(regTcPtr->tcScanInfo);
5024  scanptr.i = RNIL;
5025  {
5026  ScanRecord key;
5027  key.scanNumber = KeyInfo20::getScanNo(regTcPtr->tcScanInfo);
5028  key.fragPtrI = fragptr.i;
5029  c_scanTakeOverHash.find(scanptr, key);
5030 #ifdef TRACE_SCAN_TAKEOVER
5031  if(scanptr.i == RNIL)
5032  ndbout_c("not finding (%d %d)", key.scanNumber, key.fragPtrI);
5033 #endif
5034  }
5035  if (scanptr.i == RNIL) {
5036  jam();
5037  takeOverErrorLab(signal);
5038  return;
5039  }//if
5040  Uint32 accOpPtr= get_acc_ptr_from_scan_record(scanptr.p,
5041  ttcScanOp,
5042  true);
5043  if (accOpPtr == RNIL) {
5044  jam();
5045  takeOverErrorLab(signal);
5046  return;
5047  }//if
5048  signal->theData[1] = accOpPtr;
5049  signal->theData[2] = regTcPtr->transid[0];
5050  signal->theData[3] = regTcPtr->transid[1];
5051  EXECUTE_DIRECT(refToMain(regTcPtr->tcAccBlockref), GSN_ACC_TO_REQ,
5052  signal, 4);
5053  if (signal->theData[0] == (UintR)-1) {
5054  execACC_TO_REF(signal);
5055  return;
5056  }//if
5057  jamEntry();
5058  }//if
5059 /*-------------------------------------------------------------------*/
5060 /* IT IS NOW TIME TO CONTACT ACC. THE TUPLE KEY WILL BE SENT */
5061 /* AND THIS WILL BE TRANSLATED INTO A LOCAL KEY BY USING THE */
5062 /* LOCAL PART OF THE LH3-ALGORITHM. ALSO PROPER LOCKS ON THE */
5063 /* TUPLE WILL BE SET. FOR INSERTS AND DELETES THE MESSAGE WILL */
5064 /* START AN INSERT/DELETE INTO THE HASH TABLE. */
5065 /* */
5066 /* BEFORE SENDING THE MESSAGE THE REQUEST INFORMATION IS SET */
5067 /* PROPERLY. */
5068 /* ----------------------------------------------------------------- */
5069  if (TRACENR_FLAG)
5070  {
5071  TRACE_OP(regTcPtr, "RECEIVED");
5072  switch (regTcPtr->operation) {
5073  case ZREAD: TRACENR("READ"); break;
5074  case ZUPDATE: TRACENR("UPDATE"); break;
5075  case ZWRITE: TRACENR("WRITE"); break;
5076  case ZINSERT: TRACENR("INSERT"); break;
5077  case ZDELETE: TRACENR("DELETE"); break;
5078  case ZUNLOCK: TRACENR("UNLOCK"); break;
5079  case ZREFRESH: TRACENR("REFRESH"); break;
5080  default: TRACENR("<Unknown: " << regTcPtr->operation << ">"); break;
5081  }
5082 
5083  TRACENR(" tab: " << regTcPtr->tableref
5084  << " frag: " << regTcPtr->fragmentid
5085  << " activeCreat: " << (Uint32)activeCreat);
5086  if (LqhKeyReq::getNrCopyFlag(regTcPtr->reqinfo))
5087  TRACENR(" NrCopy");
5088  if (LqhKeyReq::getRowidFlag(regTcPtr->reqinfo))
5089  TRACENR(" rowid: " << regTcPtr->m_row_id);
5090  TRACENR(" key: " << getKeyInfoWordOrZero(regTcPtr, 0));
5091  }
5092 
5093  if (likely(activeCreat == Fragrecord::AC_NORMAL))
5094  {
5095  if (TRACENR_FLAG)
5096  TRACENR(endl);
5097  ndbassert(!LqhKeyReq::getNrCopyFlag(regTcPtr->reqinfo));
5098  exec_acckeyreq(signal, tcConnectptr);
5099  }
5100  else if (activeCreat == Fragrecord::AC_NR_COPY)
5101  {
5102  regTcPtr->totSendlenAi = regTcPtr->totReclenAi;
5103  handle_nr_copy(signal, tcConnectptr);
5104  }
5105  else
5106  {
5107  ndbassert(activeCreat == Fragrecord::AC_IGNORED);
5108  if (TRACENR_FLAG)
5109  TRACENR(" IGNORING (activeCreat == 2)" << endl);
5110 
5111  signal->theData[0] = tc_ptr_i;
5112  regTcPtr->transactionState = TcConnectionrec::WAIT_ACC_ABORT;
5113 
5114  signal->theData[0] = regTcPtr->tupConnectrec;
5115  EXECUTE_DIRECT(DBTUP, GSN_TUP_ABORTREQ, signal, 1);
5116  jamEntry();
5117 
5118  regTcPtr->totSendlenAi = regTcPtr->totReclenAi;
5119  packLqhkeyreqLab(signal);
5120  }
5121 }
5122 
5123 void
5124 Dblqh::exec_acckeyreq(Signal* signal, TcConnectionrecPtr regTcPtr)
5125 {
5126  Uint32 taccreq;
5127  regTcPtr.p->transactionState = TcConnectionrec::WAIT_ACC;
5128  taccreq = regTcPtr.p->operation;
5129  taccreq = taccreq + (regTcPtr.p->lockType << 4);
5130  taccreq = taccreq + (regTcPtr.p->dirtyOp << 6);
5131  taccreq = taccreq + (regTcPtr.p->replicaType << 7);
5132  taccreq = taccreq + (regTcPtr.p->apiVersionNo << 9);
5133 /* ************ */
5134 /* ACCKEYREQ < */
5135 /* ************ */
5136  Uint32 sig0, sig1, sig2, sig3, sig4;
5137  sig0 = regTcPtr.p->accConnectrec;
5138  sig1 = fragptr.p->accFragptr;
5139  sig2 = regTcPtr.p->hashValue;
5140  sig3 = regTcPtr.p->primKeyLen;
5141  sig4 = regTcPtr.p->transid[0];
5142  signal->theData[0] = sig0;
5143  signal->theData[1] = sig1;
5144  signal->theData[2] = taccreq;
5145  signal->theData[3] = sig2;
5146  signal->theData[4] = sig3;
5147  signal->theData[5] = sig4;
5148 
5149  sig0 = regTcPtr.p->transid[1];
5150  signal->theData[6] = sig0;
5151 
5152  /* Copy KeyInfo to end of ACCKEYREQ signal, starting at offset 7 */
5153  sendKeyinfoAcc(signal, 7);
5154 
5155  TRACE_OP(regTcPtr.p, "ACC");
5156 
5157  EXECUTE_DIRECT(refToMain(regTcPtr.p->tcAccBlockref), GSN_ACCKEYREQ,
5158  signal, 7 + regTcPtr.p->primKeyLen);
5159  if (signal->theData[0] < RNIL) {
5160  signal->theData[0] = regTcPtr.i;
5161  execACCKEYCONF(signal);
5162  return;
5163  } else if (signal->theData[0] == RNIL) {
5164  ;
5165  } else {
5166  ndbrequire(signal->theData[0] == (UintR)-1);
5167  signal->theData[0] = regTcPtr.i;
5168  execACCKEYREF(signal);
5169  }//if
5170  return;
5171 }//Dblqh::prepareContinueAfterBlockedLab()
5172 
5173 void
5174 Dblqh::handle_nr_copy(Signal* signal, Ptr<TcConnectionrec> regTcPtr)
5175 {
5176  jam();
5177  Uint32 fragPtr = fragptr.p->tupFragptr;
5178  Uint32 op = regTcPtr.p->operation;
5179 
5180  const bool copy = LqhKeyReq::getNrCopyFlag(regTcPtr.p->reqinfo);
5181 
5182  if (!LqhKeyReq::getRowidFlag(regTcPtr.p->reqinfo))
5183  {
5187  jam();
5188  if (TRACENR_FLAG)
5189  TRACENR(" Waiting for COPY_ACTIVEREQ" << endl);
5190  ndbassert(!LqhKeyReq::getNrCopyFlag(regTcPtr.p->reqinfo));
5191  regTcPtr.p->activeCreat = Fragrecord::AC_NORMAL;
5192  exec_acckeyreq(signal, regTcPtr);
5193  return;
5194  }
5195 
5196  regTcPtr.p->m_nr_delete.m_cnt = 1; // Wait for real op aswell
5197  Uint32* dst = signal->theData+24;
5198  bool uncommitted;
5199  const int len = c_tup->nr_read_pk(fragPtr, &regTcPtr.p->m_row_id, dst,
5200  uncommitted);
5201  const bool match = (len>0) ? compare_key(regTcPtr.p, dst, len) == 0 : false;
5202 
5203  if (TRACENR_FLAG)
5204  TRACENR(" len: " << len << " match: " << match
5205  << " uncommitted: " << uncommitted);
5206 
5207  if (copy)
5208  {
5209  ndbassert(LqhKeyReq::getGCIFlag(regTcPtr.p->reqinfo));
5210  if (match)
5211  {
5215  jam();
5216  ndbassert(op == ZINSERT);
5217  if (TRACENR_FLAG)
5218  TRACENR(" Changing from INSERT to ZUPDATE" << endl);
5219  regTcPtr.p->operation = ZUPDATE;
5220  goto run;
5221  }
5222  else if (len > 0 && op == ZDELETE)
5223  {
5230  jam();
5231  ndbassert(regTcPtr.p->primKeyLen == 0);
5232  if (TRACENR_FLAG)
5233  TRACENR(" performing DELETE key: "
5234  << dst[0] << endl);
5235 
5236  nr_copy_delete_row(signal, regTcPtr, &regTcPtr.p->m_row_id, len);
5237  ndbassert(regTcPtr.p->m_nr_delete.m_cnt);
5238  regTcPtr.p->m_nr_delete.m_cnt--; // No real op is run
5239  if (regTcPtr.p->m_nr_delete.m_cnt)
5240  {
5241  jam();
5242  return;
5243  }
5244  packLqhkeyreqLab(signal);
5245  return;
5246  }
5247  else if (len == 0 && op == ZDELETE)
5248  {
5252  jam();
5253  if (TRACENR_FLAG)
5254  TRACENR(" UPDATE_GCI" << endl);
5255  c_tup->nr_update_gci(fragPtr, &regTcPtr.p->m_row_id, regTcPtr.p->gci_hi);
5256  goto update_gci_ignore;
5257  }
5258 
5264  if (len > 0)
5265  {
5269  jam();
5270  nr_copy_delete_row(signal, regTcPtr, &regTcPtr.p->m_row_id, len);
5271  }
5275  jam();
5276  nr_copy_delete_row(signal, regTcPtr, 0, 0);
5277  if (TRACENR_FLAG)
5278  TRACENR(" RUN INSERT" << endl);
5279  goto run;
5280  }
5281  else
5282  {
5283  if (!match && op != ZINSERT)
5284  {
5285  jam();
5286  if (TRACENR_FLAG)
5287  TRACENR(" IGNORE " << endl);
5288  goto ignore;
5289  }
5290  if (match)
5291  {
5292  jam();
5293  if (op != ZDELETE && op != ZREFRESH)
5294  {
5295  if (TRACENR_FLAG)
5296  TRACENR(" Changing from INSERT/UPDATE to ZWRITE" << endl);
5297  regTcPtr.p->operation = ZWRITE;
5298  }
5299  goto run;
5300  }
5301 
5302  ndbassert(!match && op == ZINSERT);
5303 
5309  if (len > 0)
5310  {
5314  jam();
5315  nr_copy_delete_row(signal, regTcPtr, &regTcPtr.p->m_row_id, len);
5316  }
5317 
5321  jam();
5322  nr_copy_delete_row(signal, regTcPtr, 0, 0);
5323  if (TRACENR_FLAG)
5324  TRACENR(" RUN op: " << op << endl);
5325  goto run;
5326  }
5327 
5328 run:
5329  jam();
5330  exec_acckeyreq(signal, regTcPtr);
5331  return;
5332 
5333 ignore:
5334  jam();
5335  ndbassert(!LqhKeyReq::getNrCopyFlag(regTcPtr.p->reqinfo));
5336 update_gci_ignore:
5337  regTcPtr.p->activeCreat = Fragrecord::AC_IGNORED;
5338  signal->theData[0] = regTcPtr.p->tupConnectrec;
5339  EXECUTE_DIRECT(DBTUP, GSN_TUP_ABORTREQ, signal, 1);
5340 
5341  packLqhkeyreqLab(signal);
5342 }
5343 
5348 int
5349 Dblqh::compare_key(const TcConnectionrec* regTcPtr,
5350  const Uint32 * ptr, Uint32 len)
5351 {
5352  if (regTcPtr->primKeyLen != len)
5353  return 1;
5354 
5355  ndbassert( regTcPtr->keyInfoIVal != RNIL );
5356 
5357  SectionReader keyInfoReader(regTcPtr->keyInfoIVal,
5358  getSectionSegmentPool());
5359 
5360  ndbassert(regTcPtr->primKeyLen == keyInfoReader.getSize());
5361 
5362  while (len != 0)
5363  {
5364  const Uint32* keyChunk= NULL;
5365  Uint32 chunkSize= 0;
5366 
5367  /* Get a ptr to a chunk of contiguous words to compare */
5368  bool ok= keyInfoReader.getWordsPtr(len, keyChunk, chunkSize);
5369 
5370  ndbrequire(ok);
5371 
5372  if ( memcmp(ptr, keyChunk, chunkSize << 2))
5373  return 1;
5374 
5375  ptr+= chunkSize;
5376  len-= chunkSize;
5377  }
5378 
5379  return 0;
5380 }
5381 
5382 void
5383 Dblqh::nr_copy_delete_row(Signal* signal,
5384  Ptr<TcConnectionrec> regTcPtr,
5385  Local_key* rowid, Uint32 len)
5386 {
5387  Ptr<Fragrecord> fragPtr = fragptr;
5388 
5389  Uint32 keylen;
5390  Uint32 tableId = regTcPtr.p->tableref;
5391  Uint32 accPtr = regTcPtr.p->accConnectrec;
5392 
5393  signal->theData[0] = accPtr;
5394  signal->theData[1] = fragptr.p->accFragptr;
5395  signal->theData[2] = ZDELETE + (ZDELETE << 4);
5396  signal->theData[5] = regTcPtr.p->transid[0];
5397  signal->theData[6] = regTcPtr.p->transid[1];
5398 
5399  if (rowid)
5400  {
5401  jam();
5402  keylen = 2;
5403  if (g_key_descriptor_pool.getPtr(tableId)->hasCharAttr)
5404  {
5405  signal->theData[3] = calculateHash(tableId, signal->theData+24);
5406  }
5407  else
5408  {
5409  signal->theData[3] = md5_hash((Uint64*)(signal->theData+24), len);
5410  }
5411  signal->theData[4] = 0; // seach by local key
5412  signal->theData[7] = rowid->m_page_no;
5413  signal->theData[8] = rowid->m_page_idx;
5414  }
5415  else
5416  {
5417  jam();
5418  keylen = regTcPtr.p->primKeyLen;
5419  signal->theData[3] = regTcPtr.p->hashValue;
5420  signal->theData[4] = keylen;
5421 
5422  /* Copy KeyInfo inline into the ACCKEYREQ signal,
5423  * starting at word 7
5424  */
5425  sendKeyinfoAcc(signal, 7);
5426  }
5427  const Uint32 ref = refToMain(regTcPtr.p->tcAccBlockref);
5428  EXECUTE_DIRECT(ref, GSN_ACCKEYREQ, signal, 7 + keylen);
5429  jamEntry();
5430 
5431  Uint32 retValue = signal->theData[0];
5432  ndbrequire(retValue != RNIL); // This should never block...
5433  ndbrequire(retValue != (Uint32)-1 || rowid == 0); // rowid should never fail
5434 
5435  if (retValue == (Uint32)-1)
5436  {
5440  jam();
5441  ndbrequire(rowid == 0);
5442  signal->theData[0] = accPtr;
5443  signal->theData[1] = 0;
5444  EXECUTE_DIRECT(ref, GSN_ACC_ABORTREQ, signal, 2);
5445  jamEntry();
5446  return;
5447  }
5448 
5452  ndbrequire(regTcPtr.p->m_dealloc == 0);
5453  Local_key save = regTcPtr.p->m_row_id;
5454 
5455  c_acc->execACCKEY_ORD(signal, accPtr);
5456  signal->theData[0] = accPtr;
5457  EXECUTE_DIRECT(ref, GSN_ACC_COMMITREQ, signal, 1);
5458  jamEntry();
5459 
5460  ndbrequire(regTcPtr.p->m_dealloc == 1);
5461  int ret = c_tup->nr_delete(signal, regTcPtr.i,
5462  fragPtr.p->tupFragptr, &regTcPtr.p->m_row_id,
5463  regTcPtr.p->gci_hi);
5464  jamEntry();
5465 
5466  if (ret)
5467  {
5468  ndbassert(ret == 1);
5469  Uint32 pos = regTcPtr.p->m_nr_delete.m_cnt - 1;
5470  memcpy(regTcPtr.p->m_nr_delete.m_disk_ref + pos,
5471  signal->theData, sizeof(Local_key));
5472  regTcPtr.p->m_nr_delete.m_page_id[pos] = RNIL;
5473  regTcPtr.p->m_nr_delete.m_cnt = pos + 2;
5474  if (0) ndbout << "PENDING DISK DELETE: " <<
5475  regTcPtr.p->m_nr_delete.m_disk_ref[pos] << endl;
5476  }
5477 
5478  TRACENR("DELETED: " << regTcPtr.p->m_row_id << endl);
5479 
5480  regTcPtr.p->m_dealloc = 0;
5481  regTcPtr.p->m_row_id = save;
5482  fragptr = fragPtr;
5483  tcConnectptr = regTcPtr;
5484 }
5485 
5486 void
5487 Dblqh::get_nr_op_info(Nr_op_info* op, Uint32 page_id)
5488 {
5489  Ptr<TcConnectionrec> tcPtr;
5490  tcPtr.i = op->m_ptr_i;
5491  ptrCheckGuard(tcPtr, ctcConnectrecFileSize, tcConnectionrec);
5492 
5493  Ptr<Fragrecord> fragPtr;
5494  c_fragment_pool.getPtr(fragPtr, tcPtr.p->fragmentptr);
5495 
5496  op->m_gci_hi = tcPtr.p->gci_hi;
5497  op->m_gci_lo = tcPtr.p->gci_lo;
5498  op->m_tup_frag_ptr_i = fragPtr.p->tupFragptr;
5499 
5500  ndbrequire(tcPtr.p->activeCreat == Fragrecord::AC_NR_COPY);
5501  ndbrequire(tcPtr.p->m_nr_delete.m_cnt);
5502 
5503 
5504  if (page_id == RNIL)
5505  {
5506  // get log buffer callback
5507  for (Uint32 i = 0; i<2; i++)
5508  {
5509  if (tcPtr.p->m_nr_delete.m_page_id[i] != RNIL)
5510  {
5511  op->m_page_id = tcPtr.p->m_nr_delete.m_page_id[i];
5512  op->m_disk_ref = tcPtr.p->m_nr_delete.m_disk_ref[i];
5513  return;
5514  }
5515  }
5516  }
5517  else
5518  {
5519  // get page callback
5520  for (Uint32 i = 0; i<2; i++)
5521  {
5522  Local_key key = tcPtr.p->m_nr_delete.m_disk_ref[i];
5523  if (op->m_disk_ref.m_page_no == key.m_page_no &&
5524  op->m_disk_ref.m_file_no == key.m_file_no &&
5525  tcPtr.p->m_nr_delete.m_page_id[i] == RNIL)
5526  {
5527  op->m_disk_ref = key;
5528  tcPtr.p->m_nr_delete.m_page_id[i] = page_id;
5529  return;
5530  }
5531  }
5532  }
5533  ndbrequire(false);
5534 }
5535 
5536 void
5538 {
5539  jamEntry();
5540  Ptr<TcConnectionrec> tcPtr;
5541  tcPtr.i = op->m_ptr_i;
5542  ptrCheckGuard(tcPtr, ctcConnectrecFileSize, tcConnectionrec);
5543 
5544  ndbrequire(tcPtr.p->activeCreat == Fragrecord::AC_NR_COPY);
5545  ndbrequire(tcPtr.p->m_nr_delete.m_cnt);
5546 
5547  tcPtr.p->m_nr_delete.m_cnt--;
5548  if (tcPtr.p->m_nr_delete.m_cnt == 0)
5549  {
5550  jam();
5551  tcConnectptr = tcPtr;
5552  c_fragment_pool.getPtr(fragptr, tcPtr.p->fragmentptr);
5553 
5554  if (tcPtr.p->abortState != TcConnectionrec::ABORT_IDLE)
5555  {
5556  jam();
5557  tcPtr.p->activeCreat = Fragrecord::AC_NORMAL;
5558  abortCommonLab(signal);
5559  }
5560  else if (tcPtr.p->operation == ZDELETE &&
5561  LqhKeyReq::getNrCopyFlag(tcPtr.p->reqinfo))
5562  {
5566  jam();
5567  packLqhkeyreqLab(signal);
5568  }
5569  else
5570  {
5571  jam();
5572  rwConcludedLab(signal);
5573  }
5574  return;
5575  }
5576 
5577  if (memcmp(&tcPtr.p->m_nr_delete.m_disk_ref[0],
5578  &op->m_disk_ref, sizeof(Local_key)) == 0)
5579  {
5580  jam();
5581  ndbassert(tcPtr.p->m_nr_delete.m_page_id[0] != RNIL);
5582  tcPtr.p->m_nr_delete.m_page_id[0] = tcPtr.p->m_nr_delete.m_page_id[1];
5583  tcPtr.p->m_nr_delete.m_disk_ref[0] = tcPtr.p->m_nr_delete.m_disk_ref[1];
5584  }
5585 }
5586 
5587 Uint32
5588 Dblqh::readPrimaryKeys(Uint32 opPtrI, Uint32 * dst, bool xfrm)
5589 {
5590  TcConnectionrecPtr regTcPtr;
5591  Uint64 Tmp[MAX_KEY_SIZE_IN_WORDS >> 1];
5592 
5593  jamEntry();
5594  regTcPtr.i = opPtrI;
5595  ptrCheckGuard(regTcPtr, ctcConnectrecFileSize, tcConnectionrec);
5596 
5597  Uint32 tableId = regTcPtr.p->tableref;
5598  Uint32 keyLen = regTcPtr.p->primKeyLen;
5599  Uint32 * tmp = xfrm ? (Uint32*)Tmp : dst;
5600 
5601  copy(tmp, regTcPtr.p->keyInfoIVal);
5602 
5603  if (xfrm)
5604  {
5605  jam();
5606  Uint32 keyPartLen[MAX_ATTRIBUTES_IN_INDEX];
5607  return xfrm_key(tableId, (Uint32*)Tmp, dst, ~0, keyPartLen);
5608  }
5609 
5610  return keyLen;
5611 }
5612 
5618 Uint32
5619 Dblqh::getKeyInfoWordOrZero(const TcConnectionrec* regTcPtr,
5620  Uint32 offset)
5621 {
5622  if (regTcPtr->keyInfoIVal != RNIL)
5623  {
5624  SectionReader keyInfoReader(regTcPtr->keyInfoIVal,
5625  g_sectionSegmentPool);
5626 
5627  if (keyInfoReader.getSize() > offset)
5628  {
5629  if (offset)
5630  keyInfoReader.step(offset);
5631 
5632  Uint32 word;
5633  keyInfoReader.getWord(&word);
5634  return word;
5635  }
5636  }
5637  return 0;
5638 }
5639 
5640 void Dblqh::unlockError(Signal* signal, Uint32 error)
5641 {
5642  terrorCode = error;
5643  abortErrorLab(signal);
5644 }
5645 
5652 void Dblqh::handleUserUnlockRequest(Signal* signal)
5653 {
5654  jam();
5655  TcConnectionrec * const regTcPtr = tcConnectptr.p;
5656  Uint32 tcPtrI = tcConnectptr.i;
5657 
5658  /* Request to unlock (abort) an existing read operation
5659  *
5660  * 1) Get user's LOCK_REF from KeyInfo
5661  *
5662  * 2) Lookup TC_OP_REF in hash
5663  *
5664  * 3) Check state of found op : TransId, state, type, lock
5665  *
5666  * 4) Check op_id portion
5667  *
5668  * 5) Abort locking op in ACC
5669  *
5670  * 6) Clean up locking op in LQH
5671  *
5672  * 7) Send LQHKEYCONF to TC for user unlock op
5673  *
5674  * 8) Clean up user unlock op
5675  */
5676  if (unlikely( regTcPtr->primKeyLen != LqhKeyReq::UnlockKeyLen ))
5677  {
5678  jam();
5679  unlockError(signal, 4109); /* Faulty primary key attribute length */
5680  return;
5681  }
5682 
5683  SectionReader keyInfoReader(regTcPtr->keyInfoIVal,
5684  getSectionSegmentPool());
5685 
5686  ndbrequire( keyInfoReader.getSize() == regTcPtr->primKeyLen );
5687 
5688  /* Extract components of user lock reference */
5689  Uint32 tcOpRecIndex;
5690  Uint32 lqhOpIdWord;
5691  ndbrequire( keyInfoReader.getWord( &tcOpRecIndex ) ); // Locking op TC index
5692  ndbrequire( keyInfoReader.getWord( &lqhOpIdWord ) ); // Part of Locking op LQH id
5693 
5694  /* Use TC operation record index to find the operation record
5695  * This requires that this operation and the referenced
5696  * operation are part of the same transaction.
5697  * On success this sets tcConnectptr.i and .p to the
5698  * operation-to-unlock's record.
5699  */
5700  if (unlikely( findTransaction(regTcPtr->transid[0],
5701  regTcPtr->transid[1],
5702  tcOpRecIndex,
5703  0) != ZOK))
5704  {
5705  jam();
5706  unlockError(signal, ZBAD_OP_REF);
5707  return;
5708  }
5709 
5710  TcConnectionrec * const regLockTcPtr = tcConnectptr.p;
5711 
5712  /* Validate that the bottom 32-bits of the operation id reference
5713  * we were given are in alignment
5714  */
5715  Uint32 lockOpKeyReqId = (Uint32) regLockTcPtr->lqhKeyReqId;
5716  if (unlikely( lockOpKeyReqId != lqhOpIdWord ))
5717  {
5718  jam();
5719  unlockError(signal, ZBAD_OP_REF);
5720  return;
5721  }
5722 
5723  /* Validate the state of the locking operation */
5724  bool lockingOpValid =
5725  (( regLockTcPtr->operation == ZREAD ) &&
5726  // ZREAD_EX mapped to ZREAD above
5727  ( ! regLockTcPtr->dirtyOp ) &&
5728  ( ! regLockTcPtr->opSimple ) &&
5729  ( (regLockTcPtr->lockType == ZREAD) || // LM_Read
5730  (regLockTcPtr->lockType == ZUPDATE) ) // LM_Exclusive
5731  &&
5732  ( regLockTcPtr->transactionState == TcConnectionrec::PREPARED ) &&
5733  ( regLockTcPtr->commitAckMarker == RNIL ) &&
5734  // No commit ack marker
5735  ( regLockTcPtr->logWriteState ==
5736  TcConnectionrec::NOT_STARTED )); // No log written
5737 
5738  if (unlikely(! lockingOpValid))
5739  {
5740  jam();
5741  unlockError(signal, ZBAD_UNLOCK_STATE);
5742  return;
5743  }
5744 
5745  /* Ok, now we're ready to start 'aborting' this operation, to get the
5746  * effect of unlocking it
5747  */
5748  signal->theData[0] = regLockTcPtr->accConnectrec;
5749  signal->theData[1] = 0; // For Execute_Direct
5750  EXECUTE_DIRECT(refToMain(regLockTcPtr->tcAccBlockref),
5751  GSN_ACC_ABORTREQ,
5752  signal,
5753  2);
5754  jamEntry();
5755 
5756  /* Would be nice to handle non-success case somehow */
5757  ndbrequire(signal->theData[1] == 0);
5758 
5759  /* Now we want to release LQH resources associated with the
5760  * locking operation
5761  */
5762  cleanUp(signal);
5763 
5764  /* Now that the locking operation has been 'disappeared', we need to
5765  * send an LQHKEYCONF for the unlock operation and then 'disappear' it
5766  * as well
5767  */
5768  tcConnectptr.i = tcPtrI;
5769  ptrCheckGuard(tcConnectptr, ctcConnectrecFileSize, tcConnectionrec);
5770 
5771  ndbrequire( regTcPtr == tcConnectptr.p );
5772 
5773  /* Set readlenAi to the unlocked operation's TC operation ref */
5774  regTcPtr->readlenAi = tcOpRecIndex;
5775 
5776  /* Clear number of fired triggers */
5777  regTcPtr->noFiredTriggers = 0;
5778 
5779  /* Now send the LQHKEYCONF to TC */
5780  sendLqhkeyconfTc(signal, regTcPtr->tcBlockref);
5781 
5782  /* Finally, clean up the unlock operation itself */
5783  cleanUp(signal);
5784 
5785  return;
5786 }
5787 
5788 /* =*======================================================================= */
5789 /* ======= SEND KEYINFO TO ACC ======= */
5790 /* */
5791 /* ========================================================================= */
5792 void Dblqh::sendKeyinfoAcc(Signal* signal, Uint32 Ti)
5793 {
5794  /* Copy all KeyInfo into the signal at offset Ti */
5795  copy(&signal->theData[Ti],
5796  tcConnectptr.p->keyInfoIVal);
5797 }//Dblqh::sendKeyinfoAcc()
5798 
5799 void Dblqh::execLQH_ALLOCREQ(Signal* signal)
5800 {
5801  TcConnectionrecPtr regTcPtr;
5802  FragrecordPtr regFragptr;
5803 
5804  jamEntry();
5805  regTcPtr.i = signal->theData[0];
5806  ptrCheckGuard(regTcPtr, ctcConnectrecFileSize, tcConnectionrec);
5807 
5808  regFragptr.i = regTcPtr.p->fragmentptr;
5809  c_fragment_pool.getPtr(regFragptr);
5810 
5811  signal->theData[0] = regTcPtr.p->tupConnectrec;
5812  signal->theData[1] = regFragptr.p->tupFragptr;
5813  signal->theData[2] = regTcPtr.p->tableref;
5814  Uint32 tup = refToMain(regTcPtr.p->tcTupBlockref);
5815  EXECUTE_DIRECT(tup, GSN_TUP_ALLOCREQ, signal, 3);
5816 }//Dblqh::execTUP_ALLOCREQ()
5817 
5818 void Dblqh::execTUP_DEALLOCREQ(Signal* signal)
5819 {
5820  TcConnectionrecPtr regTcPtr;
5821 
5822  jamEntry();
5823  regTcPtr.i = signal->theData[4];
5824 
5825  if (TRACENR_FLAG)
5826  {
5827  Local_key tmp;
5828  tmp.m_page_no = signal->theData[2];
5829  tmp.m_page_idx = signal->theData[3];
5830  TRACENR("TUP_DEALLOC: " << tmp <<
5831  (signal->theData[5] ? " DIRECT " : " DELAYED") << endl);
5832  }
5833 
5834  if (signal->theData[5])
5835  {
5836  jam();
5837  Local_key tmp;
5838 
5839  tmp.m_page_no = signal->theData[2];
5840  tmp.m_page_idx = signal->theData[3];
5841 
5842  if (ERROR_INSERTED(5712))
5843  {
5844  ndbout << "TUP_DEALLOC: " << tmp << endl;
5845  }
5846 
5847  EXECUTE_DIRECT(DBTUP, GSN_TUP_DEALLOCREQ, signal, signal->getLength());
5848  return;
5849  }
5850  else
5851  {
5852  jam();
5853  ptrCheckGuard(regTcPtr, ctcConnectrecFileSize, tcConnectionrec);
5854  regTcPtr.p->m_row_id.m_page_no = signal->theData[2];
5855  regTcPtr.p->m_row_id.m_page_idx = signal->theData[3];
5856 
5857  TRACE_OP(regTcPtr.p, "SET DEALLOC");
5858 
5859  ndbrequire(regTcPtr.p->m_dealloc == 0);
5860  regTcPtr.p->m_dealloc = 1;
5861  }
5862 }//Dblqh::execTUP_ALLOCREQ()
5863 
5864 /* ************>> */
5865 /* ACCKEYCONF > */
5866 /* ************>> */
5867 void Dblqh::execACCKEYCONF(Signal* signal)
5868 {
5869  TcConnectionrec *regTcConnectionrec = tcConnectionrec;
5870  Uint32 ttcConnectrecFileSize = ctcConnectrecFileSize;
5871  Uint32 tcIndex = signal->theData[0];
5872  Uint32 localKey1 = signal->theData[3];
5873  Uint32 localKey2 = signal->theData[4];
5874  jamEntry();
5875 
5876  tcConnectptr.i = tcIndex;
5877  ptrCheckGuard(tcConnectptr, ttcConnectrecFileSize, regTcConnectionrec);
5878  TcConnectionrec * const regTcPtr = tcConnectptr.p;
5879  if (regTcPtr->transactionState != TcConnectionrec::WAIT_ACC) {
5880  LQHKEY_abort(signal, 3);
5881  return;
5882  }//if
5883 
5884  /* ------------------------------------------------------------------------
5885  * IT IS NOW TIME TO CONTACT THE TUPLE MANAGER. THE TUPLE MANAGER NEEDS THE
5886  * INFORMATION ON WHICH TABLE AND FRAGMENT, THE LOCAL KEY AND IT NEEDS TO
5887  * KNOW THE TYPE OF OPERATION TO PERFORM. TUP CAN SEND THE ATTRINFO DATA
5888  * EITHER TO THE TC BLOCK OR DIRECTLY TO THE APPLICATION. THE SCHEMA VERSION
5889  * IS NEEDED SINCE TWO SCHEMA VERSIONS CAN BE ACTIVE SIMULTANEOUSLY ON A
5890  * TABLE.
5891  * ----------------------------------------------------------------------- */
5892  if (regTcPtr->operation == ZWRITE)
5893  {
5894  ndbassert(regTcPtr->seqNoReplica == 0 ||
5895  regTcPtr->activeCreat == Fragrecord::AC_NR_COPY);
5896  Uint32 op= signal->theData[1];
5897  Uint32 requestInfo = regTcPtr->reqinfo;
5898  if(likely(op == ZINSERT || op == ZUPDATE))
5899  {
5900  jam();
5901  regTcPtr->operation = op;
5902  }
5903  else
5904  {
5905  jam();
5906  warningEvent("Convering %d to ZUPDATE", op);
5907  op = regTcPtr->operation = ZUPDATE;
5908  }
5909  if (regTcPtr->seqNoReplica == 0)
5910  {
5911  jam();
5912  requestInfo &= ~(RI_OPERATION_MASK << RI_OPERATION_SHIFT);
5913  LqhKeyReq::setOperation(requestInfo, op);
5914  regTcPtr->reqinfo = requestInfo;
5915  }
5916  }//if
5917 
5918  /* ------------------------------------------------------------------------
5919  * IT IS NOW TIME TO CONTACT THE TUPLE MANAGER. THE TUPLE MANAGER NEEDS THE
5920  * INFORMATION ON WHICH TABLE AND FRAGMENT, THE LOCAL KEY AND IT NEEDS TO
5921  * KNOW THE TYPE OF OPERATION TO PERFORM. TUP CAN SEND THE ATTRINFO DATA
5922  * EITHER TO THE TC BLOCK OR DIRECTLY TO THE APPLICATION. THE SCHEMA VERSION
5923  * IS NEEDED SINCE TWO SCHEMA VERSIONS CAN BE ACTIVE SIMULTANEOUSLY ON A
5924  * TABLE.
5925  * ----------------------------------------------------------------------- */
5926  FragrecordPtr regFragptr;
5927  regFragptr.i = regTcPtr->fragmentptr;
5928  c_fragment_pool.getPtr(regFragptr);
5929 
5930  if(!regTcPtr->m_disk_table)
5931  acckeyconf_tupkeyreq(signal, regTcPtr, regFragptr.p,
5932  localKey1, localKey2, RNIL);
5933  else
5934  acckeyconf_load_diskpage(signal, tcConnectptr, regFragptr.p,
5935  localKey1, localKey2);
5936 }
5937 
5938 void
5939 Dblqh::acckeyconf_tupkeyreq(Signal* signal, TcConnectionrec* regTcPtr,
5940  Fragrecord* regFragptrP,
5941  Uint32 lkey1, Uint32 lkey2,
5942  Uint32 disk_page)
5943 {
5944  Uint32 op = regTcPtr->operation;
5945  regTcPtr->transactionState = TcConnectionrec::WAIT_TUP;
5946  /* ------------------------------------------------------------------------
5947  * IT IS NOW TIME TO CONTACT THE TUPLE MANAGER. THE TUPLE MANAGER NEEDS THE
5948  * INFORMATION ON WHICH TABLE AND FRAGMENT, THE LOCAL KEY AND IT NEEDS TO
5949  * KNOW THE TYPE OF OPERATION TO PERFORM. TUP CAN SEND THE ATTRINFO DATA
5950  * EITHER TO THE TC BLOCK OR DIRECTLY TO THE APPLICATION. THE SCHEMA VERSION
5951  * IS NEEDED SINCE TWO SCHEMA VERSIONS CAN BE ACTIVE SIMULTANEOUSLY ON A
5952  * TABLE.
5953  * ----------------------------------------------------------------------- */
5954  Uint32 page_idx = lkey2;
5955  Uint32 page_no = lkey1;
5956  Uint32 Ttupreq = regTcPtr->dirtyOp;
5957  Uint32 flags = regTcPtr->m_flags;
5958  Ttupreq = Ttupreq + (regTcPtr->opSimple << 1);
5959  Ttupreq = Ttupreq + (op << 6);
5960  Ttupreq = Ttupreq + (regTcPtr->opExec << 10);
5961  Ttupreq = Ttupreq + (regTcPtr->apiVersionNo << 11);
5962  Ttupreq = Ttupreq + (regTcPtr->m_use_rowid << 11);
5963  Ttupreq = Ttupreq + (regTcPtr->m_reorg << 12);
5964 
5965  /* ---------------------------------------------------------------------
5966  * Clear interpreted mode bit since we do not want the next replica to
5967  * use interpreted mode. The next replica will receive a normal write.
5968  * --------------------------------------------------------------------- */
5969  regTcPtr->opExec = 0;
5970  /* ************< */
5971  /* TUPKEYREQ < */
5972  /* ************< */
5973  Uint32 sig0, sig1, sig2, sig3;
5974  sig0 = regTcPtr->tupConnectrec;
5975 
5976  TupKeyReq * const tupKeyReq = (TupKeyReq *)signal->getDataPtrSend();
5977  tupKeyReq->connectPtr = sig0;
5978  tupKeyReq->request = Ttupreq;
5979  tupKeyReq->keyRef1 = page_no;
5980  tupKeyReq->keyRef2 = page_idx;
5981 
5982  sig0 = regTcPtr->totReclenAi;
5983  sig1 = regTcPtr->applOprec;
5984  sig2 = regTcPtr->applRef;
5985 
5986  tupKeyReq->attrBufLen = sig0;
5987  tupKeyReq->opRef = sig1;
5988  tupKeyReq->applRef = sig2;
5989 
5990  sig0 = regTcPtr->storedProcId;
5991  sig1 = regTcPtr->transid[0];
5992  sig2 = regTcPtr->transid[1];
5993  sig3 = regFragptrP->tupFragptr;
5994  Uint32 tup = refToMain(regTcPtr->tcTupBlockref);
5995 
5996  tupKeyReq->storedProcedure = sig0;
5997  tupKeyReq->transId1 = sig1;
5998  tupKeyReq->transId2 = sig2;
5999  tupKeyReq->fragPtr = sig3;
6000 
6001  sig0 = regTcPtr->m_row_id.m_page_no;
6002  sig1 = regTcPtr->m_row_id.m_page_idx;
6003 
6004  tupKeyReq->primaryReplica = (tcConnectptr.p->seqNoReplica == 0)?true:false;
6005  tupKeyReq->coordinatorTC = tcConnectptr.p->tcBlockref;
6006  tupKeyReq->tcOpIndex = tcConnectptr.p->tcOprec;
6007  tupKeyReq->savePointId = tcConnectptr.p->savePointId;
6008  tupKeyReq->disk_page= disk_page;
6009 
6010  tupKeyReq->m_row_id_page_no = sig0;
6011  tupKeyReq->m_row_id_page_idx = sig1;
6012 
6013  TRACE_OP(regTcPtr, "TUPKEYREQ");
6014 
6015  regTcPtr->m_use_rowid |= (op == ZINSERT || op == ZREFRESH);
6016  regTcPtr->m_row_id.m_page_no = page_no;
6017  regTcPtr->m_row_id.m_page_idx = page_idx;
6018 
6019  tupKeyReq->attrInfoIVal= RNIL;
6020  tupKeyReq->deferred_constraints =
6021  (flags & TcConnectionrec::OP_DEFERRED_CONSTRAINTS) != 0;
6022 
6023  /* Pass AttrInfo section if available in the TupKeyReq signal
6024  * We are still responsible for releasing it, TUP is just
6025  * borrowing it
6026  */
6027  if (tupKeyReq->attrBufLen > 0)
6028  {
6029  ndbassert( regTcPtr->attrInfoIVal != RNIL );
6030  tupKeyReq->attrInfoIVal= regTcPtr->attrInfoIVal;
6031  }
6032 
6033  EXECUTE_DIRECT(tup, GSN_TUPKEYREQ, signal, TupKeyReq::SignalLength);
6034 }//Dblqh::execACCKEYCONF()
6035 
6036 void
6037 Dblqh::acckeyconf_load_diskpage(Signal* signal, TcConnectionrecPtr regTcPtr,
6038  Fragrecord* regFragptrP,
6039  Uint32 lkey1, Uint32 lkey2)
6040 {
6041  int res;
6042  if((res= c_tup->load_diskpage(signal,
6043  regTcPtr.p->tupConnectrec,
6044  regFragptrP->tupFragptr,
6045  lkey1, lkey2,
6046  regTcPtr.p->operation)) > 0)
6047  {
6048  acckeyconf_tupkeyreq(signal, regTcPtr.p, regFragptrP, lkey1, lkey2, res);
6049  }
6050  else if(res == 0)
6051  {
6052  regTcPtr.p->transactionState = TcConnectionrec::WAIT_TUP;
6053  regTcPtr.p->m_row_id.m_page_no = lkey1;
6054  regTcPtr.p->m_row_id.m_page_idx = lkey2;
6055  }
6056  else
6057  {
6058  regTcPtr.p->transactionState = TcConnectionrec::WAIT_TUP;
6059  TupKeyRef * ref = (TupKeyRef *)signal->getDataPtr();
6060  ref->userRef= regTcPtr.i;
6061  ref->errorCode= ~0;
6062  execTUPKEYREF(signal);
6063  }
6064 }
6065 
6066 void
6067 Dblqh::acckeyconf_load_diskpage_callback(Signal* signal,
6068  Uint32 callbackData,
6069  Uint32 disk_page)
6070 {
6071  jamEntry();
6072  tcConnectptr.i = callbackData;
6073  ptrCheckGuard(tcConnectptr, ctcConnectrecFileSize, tcConnectionrec);
6074  TcConnectionrec * const regTcPtr = tcConnectptr.p;
6075 
6076  TcConnectionrec::TransactionState state = regTcPtr->transactionState;
6077  if (likely(disk_page > 0 && state == TcConnectionrec::WAIT_TUP))
6078  {
6079  FragrecordPtr fragPtr;
6080  c_fragment_pool.getPtr(fragPtr, regTcPtr->fragmentptr);
6081 
6082  acckeyconf_tupkeyreq(signal, regTcPtr, fragPtr.p,
6083  regTcPtr->m_row_id.m_page_no,
6084  regTcPtr->m_row_id.m_page_idx,
6085  disk_page);
6086  }
6087  else if (state != TcConnectionrec::WAIT_TUP)
6088  {
6089  ndbrequire(state == TcConnectionrec::WAIT_TUP_TO_ABORT);
6090  abortCommonLab(signal);
6091  return;
6092  }
6093  else
6094  {
6095  regTcPtr->transactionState = TcConnectionrec::WAIT_TUP;
6096  TupKeyRef * ref = (TupKeyRef *)signal->getDataPtr();
6097  ref->userRef= callbackData;
6098  ref->errorCode= disk_page;
6099  execTUPKEYREF(signal);
6100  }
6101 }
6102 
6103 /* --------------------------------------------------------------------------
6104  * ------- ENTER TUP... -------
6105  * ENTER TUPKEYCONF WITH
6106  * TC_CONNECTPTR,
6107  * TDATA2, LOCAL KEY REFERENCE 1, ONLY INTERESTING AFTER INSERT
6108  * TDATA3, LOCAL KEY REFERENCE 1, ONLY INTERESTING AFTER INSERT
6109  * TDATA4, TOTAL LENGTH OF READ DATA SENT TO TC/APPLICATION
6110  * TDATA5 TOTAL LENGTH OF UPDATE DATA SENT TO/FROM TUP
6111  * GOTO TUPKEY_CONF
6112  *
6113  * TAKE CARE OF RESPONSES FROM TUPLE MANAGER.
6114  * -------------------------------------------------------------------------- */
6115 void Dblqh::tupkeyConfLab(Signal* signal)
6116 {
6117 /* ---- GET OPERATION TYPE AND CHECK WHAT KIND OF OPERATION IS REQUESTED --- */
6118  const TupKeyConf * const tupKeyConf = (TupKeyConf *)&signal->theData[0];
6119  TcConnectionrec * const regTcPtr = tcConnectptr.p;
6120  Uint32 activeCreat = regTcPtr->activeCreat;
6121  Uint32 readLen = tupKeyConf->readLength;
6122  Uint32 writeLen = tupKeyConf->writeLength;
6123 
6124  TRACE_OP(regTcPtr, "TUPKEYCONF");
6125 
6126  Uint32 accOp = regTcPtr->accConnectrec;
6127  c_acc->execACCKEY_ORD(signal, accOp);
6128 
6129  if (readLen != 0)
6130  {
6131  jam();
6132 
6133  /* SET BIT 15 IN REQINFO */
6134  LqhKeyReq::setApplicationAddressFlag(regTcPtr->reqinfo, 1);
6135  regTcPtr->readlenAi = readLen;
6136  }//if
6137 
6138  if (regTcPtr->operation == ZREAD &&
6139  (regTcPtr->opSimple || regTcPtr->dirtyOp))
6140  {
6141  jam();
6142  /* ----------------------------------------------------------------------
6143  * THE OPERATION IS A SIMPLE READ.
6144  * WE WILL IMMEDIATELY COMMIT THE OPERATION.
6145  * SINCE WE HAVE NOT RELEASED THE FRAGMENT LOCK
6146  * (FOR LOCAL CHECKPOINTS) YET
6147  * WE CAN GO IMMEDIATELY TO COMMIT_CONTINUE_AFTER_BLOCKED.
6148  * WE HAVE ALREADY SENT THE RESPONSE SO WE ARE NOT INTERESTED IN
6149  * READ LENGTH
6150  * --------------------------------------------------------------------- */
6151  commitContinueAfterBlockedLab(signal);
6152  return;
6153  }//if
6154 
6155  regTcPtr->totSendlenAi = writeLen;
6156  /* We will propagate / log writeLen words
6157  * Check that that is how many we have available to
6158  * propagate
6159  */
6160  ndbrequire(regTcPtr->totSendlenAi == regTcPtr->currTupAiLen);
6161 
6162  if (unlikely(activeCreat == Fragrecord::AC_NR_COPY))
6163  {
6164  jam();
6165  ndbrequire(regTcPtr->m_nr_delete.m_cnt);
6166  regTcPtr->m_nr_delete.m_cnt--;
6167  if (regTcPtr->m_nr_delete.m_cnt)
6168  {
6169  jam();
6175 #ifdef VM_TRACE
6176 
6179  TablerecPtr tablePtr;
6180  tablePtr.i = regTcPtr->tableref;
6181  ptrCheckGuard(tablePtr, ctabrecFileSize, tablerec);
6182  ndbrequire(tablePtr.p->m_disk_table);
6183 #endif
6184 
6185  return;
6186  }
6187  }
6188 
6189  rwConcludedLab(signal);
6190  return;
6191 }//Dblqh::tupkeyConfLab()
6192 
6193 /* --------------------------------------------------------------------------
6194  * THE CODE IS FOUND IN THE SIGNAL RECEPTION PART OF LQH
6195  * -------------------------------------------------------------------------- */
6196 void Dblqh::rwConcludedLab(Signal* signal)
6197 {
6198  TcConnectionrec * const regTcPtr = tcConnectptr.p;
6199  /* ------------------------------------------------------------------------
6200  * WE HAVE NOW CONCLUDED READING/WRITING IN ACC AND TUP FOR THIS OPERATION.
6201  * IT IS NOW TIME TO LOG THE OPERATION, SEND REQUEST TO NEXT NODE OR TC AND
6202  * FOR SOME TYPES OF OPERATIONS IT IS EVEN TIME TO COMMIT THE OPERATION.
6203  * ------------------------------------------------------------------------ */
6204  if (regTcPtr->operation == ZREAD) {
6205  jam();
6206  /* ----------------------------------------------------------------------
6207  * A NORMAL READ OPERATION IS NOT LOGGED BUT IS NOT COMMITTED UNTIL THE
6208  * COMMIT SIGNAL ARRIVES. THUS WE CONTINUE PACKING THE RESPONSE.
6209  * ---------------------------------------------------------------------- */
6210  packLqhkeyreqLab(signal);
6211  return;
6212  } else {
6213  FragrecordPtr regFragptr = fragptr;
6214  if (regFragptr.p->logFlag == Fragrecord::STATE_FALSE){
6215  if (regTcPtr->dirtyOp == ZTRUE) {
6216  jam();
6217  /* ------------------------------------------------------------------
6218  * THIS OPERATION WAS A WRITE OPERATION THAT DO NOT NEED LOGGING AND
6219  * THAT CAN CAN BE COMMITTED IMMEDIATELY.
6220  * ----------------------------------------------------------------- */
6221  commitContinueAfterBlockedLab(signal);
6222  return;
6223  } else {
6224  jam();
6225  /* ------------------------------------------------------------------
6226  * A NORMAL WRITE OPERATION ON A FRAGMENT WHICH DO NOT NEED LOGGING.
6227  * WE WILL PACK THE REQUEST/RESPONSE TO THE NEXT NODE/TO TC.
6228  * ------------------------------------------------------------------ */
6229  regTcPtr->logWriteState = TcConnectionrec::NOT_WRITTEN;
6230  packLqhkeyreqLab(signal);
6231  return;
6232  }//if
6233  } else {
6234  jam();
6235  /* --------------------------------------------------------------------
6236  * A DIRTY OPERATION WHICH NEEDS LOGGING. WE START BY LOGGING THE
6237  * REQUEST. IN THIS CASE WE WILL RELEASE THE FRAGMENT LOCK FIRST.
6238  * --------------------------------------------------------------------
6239  * A NORMAL WRITE OPERATION THAT NEEDS LOGGING AND WILL NOT BE
6240  * PREMATURELY COMMITTED.
6241  * -------------------------------------------------------------------- */
6242  logLqhkeyreqLab(signal);
6243  return;
6244  }//if
6245  }//if
6246 }//Dblqh::rwConcludedLab()
6247 
6248 void Dblqh::rwConcludedAiLab(Signal* signal)
6249 {
6250  TcConnectionrec * const regTcPtr = tcConnectptr.p;
6251  fragptr.i = regTcPtr->fragmentptr;
6252  /* ------------------------------------------------------------------------
6253  * WE HAVE NOW CONCLUDED READING/WRITING IN ACC AND TUP FOR THIS OPERATION.
6254  * IT IS NOW TIME TO LOG THE OPERATION, SEND REQUEST TO NEXT NODE OR TC AND
6255  * FOR SOME TYPES OF OPERATIONS IT IS EVEN TIME TO COMMIT THE OPERATION.
6256  * IN THIS CASE WE HAVE ALREADY RELEASED THE FRAGMENT LOCK.
6257  * ERROR CASES AT FRAGMENT CREATION AND STAND-BY NODES ARE THE REASONS FOR
6258  * COMING HERE.
6259  * ------------------------------------------------------------------------ */
6260  if (regTcPtr->operation == ZREAD) {
6261  if (regTcPtr->opSimple == 1) {
6262  jam();
6263  /* --------------------------------------------------------------------
6264  * THE OPERATION IS A SIMPLE READ. WE WILL IMMEDIATELY COMMIT THE
6265  * OPERATION.
6266  * -------------------------------------------------------------------- */
6267  localCommitLab(signal);
6268  return;
6269  } else {
6270  jam();
6271  /* --------------------------------------------------------------------
6272  * A NORMAL READ OPERATION IS NOT LOGGED BUT IS NOT COMMITTED UNTIL
6273  * THE COMMIT SIGNAL ARRIVES. THUS WE CONTINUE PACKING THE RESPONSE.
6274  * -------------------------------------------------------------------- */
6275  c_fragment_pool.getPtr(fragptr);
6276  packLqhkeyreqLab(signal);
6277  return;
6278  }//if
6279  } else {
6280  jam();
6281  c_fragment_pool.getPtr(fragptr);
6282  if (fragptr.p->logFlag == Fragrecord::STATE_FALSE) {
6283  if (regTcPtr->dirtyOp == ZTRUE) {
6284  /* ------------------------------------------------------------------
6285  * THIS OPERATION WAS A WRITE OPERATION THAT DO NOT NEED LOGGING AND
6286  * THAT CAN CAN BE COMMITTED IMMEDIATELY.
6287  * ----------------------------------------------------------------- */
6288  jam();
6289  /* ----------------------------------------------------------------
6290  * IT MUST BE ACTIVE CREATION OF A FRAGMENT.
6291  * ---------------------------------------------------------------- */
6292  localCommitLab(signal);
6293  return;
6294  } else {
6295  /* ------------------------------------------------------------------
6296  * A NORMAL WRITE OPERATION ON A FRAGMENT WHICH DO NOT NEED LOGGING.
6297  * WE WILL PACK THE REQUEST/RESPONSE TO THE NEXT NODE/TO TC.
6298  * ------------------------------------------------------------------ */
6299  jam();
6300  /* ---------------------------------------------------------------
6301  * IT MUST BE ACTIVE CREATION OF A FRAGMENT.
6302  * NOT A DIRTY OPERATION THUS PACK REQUEST/RESPONSE.
6303  * ---------------------------------------------------------------- */
6304  regTcPtr->logWriteState = TcConnectionrec::NOT_WRITTEN;
6305  packLqhkeyreqLab(signal);
6306  return;
6307  }//if
6308  } else {
6309  jam();
6310  /* --------------------------------------------------------------------
6311  * A DIRTY OPERATION WHICH NEEDS LOGGING. WE START BY LOGGING THE
6312  * REQUEST. IN THIS CASE WE WILL RELEASE THE FRAGMENT LOCK FIRST.
6313  * -------------------------------------------------------------------- */
6314  /* A NORMAL WRITE OPERATION THAT NEEDS LOGGING AND WILL NOT BE
6315  * PREMATURELY COMMITTED.
6316  * -------------------------------------------------------------------- */
6317  logLqhkeyreqLab(signal);
6318  return;
6319  }//if
6320  }//if
6321 }//Dblqh::rwConcludedAiLab()
6322 
6323 /* ##########################################################################
6324  * ####### LOG MODULE #######
6325  *
6326  * ##########################################################################
6327  * --------------------------------------------------------------------------
6328  * THE LOG MODULE HANDLES THE READING AND WRITING OF THE LOG
6329  * IT IS ALSO RESPONSIBLE FOR HANDLING THE SYSTEM RESTART.
6330  * IT CONTROLS THE SYSTEM RESTART IN TUP AND ACC AS WELL.
6331  * -------------------------------------------------------------------------- */
6332 void Dblqh::logLqhkeyreqLab(Signal* signal)
6333 {
6334  UintR tcurrentFilepage;
6335  TcConnectionrecPtr tmpTcConnectptr;
6336 
6337  const bool out_of_log_buffer = cnoOfLogPages < ZMIN_LOG_PAGES_OPERATION;
6338 
6339  TcConnectionrec * const regTcPtr = tcConnectptr.p;
6340  logPartPtr.i = regTcPtr->m_log_part_ptr_i;
6341  ptrCheckGuard(logPartPtr, clogPartFileSize, logPartRecord);
6342  bool abort_on_redo_problems =
6343  (LqhKeyReq::getQueueOnRedoProblemFlag(regTcPtr->reqinfo) == 0);
6344 
6345 /* -------------------------------------------------- */
6346 /* THIS PART IS USED TO WRITE THE LOG */
6347 /* -------------------------------------------------- */
6348 /* -------------------------------------------------- */
6349 /* CHECK IF A LOG OPERATION IS ONGOING ALREADY. */
6350 /* IF SO THEN QUEUE THE OPERATION FOR LATER */
6351 /* RESTART WHEN THE LOG PART IS FREE AGAIN. */
6352 /* -------------------------------------------------- */
6353  LogPartRecord * const regLogPartPtr = logPartPtr.p;
6354  const bool problem = out_of_log_buffer || regLogPartPtr->m_log_problems != 0;
6355  if (unlikely(problem))
6356  {
6357  if (abort_on_redo_problems)
6358  {
6359  logLqhkeyreqLab_problems(signal);
6360  return;
6361  }
6362  else
6363  {
6364  goto queueop;
6365  }
6366  }
6367 
6368  if (regLogPartPtr->logPartState == LogPartRecord::IDLE)
6369  {
6370  ;
6371  }
6372  else if (regLogPartPtr->logPartState == LogPartRecord::ACTIVE)
6373  {
6374 queueop:
6375  jam();
6376  linkWaitLog(signal, logPartPtr, logPartPtr.p->m_log_prepare_queue);
6377  regTcPtr->transactionState = TcConnectionrec::LOG_QUEUED;
6378  return;
6379  }
6380  else
6381  {
6382  ndbrequire(false);
6383  return;
6384  }//if
6385 
6386  logFilePtr.i = regLogPartPtr->currentLogfile;
6387  ptrCheckGuard(logFilePtr, clogFileFileSize, logFileRecord);
6388 /* -------------------------------------------------- */
6389 /* CHECK IF A NEW MBYTE IS TO BE STARTED. IF */
6390 /* SO INSERT A NEXT LOG RECORD, WRITE THE LOG */
6391 /* AND PLACE THE LOG POINTER ON THE NEW POSITION*/
6392 /* IF A NEW FILE IS TO BE USED, CHANGE FILE AND */
6393 /* ALSO START OPENING THE NEXT LOG FILE. IF A */
6394 /* LAP HAS BEEN COMPLETED THEN ADD ONE TO LAP */
6395 /* COUNTER. */
6396 /* -------------------------------------------------- */
6397  checkNewMbyte(signal);
6398 /* -------------------------------------------------- */
6399 /* INSERT THE OPERATION RECORD LAST IN THE LIST */
6400 /* OF NOT COMPLETED OPERATIONS. ALSO RECORD THE */
6401 /* FILE NO, PAGE NO AND PAGE INDEX OF THE START */
6402 /* OF THIS LOG RECORD. */
6403 /* IT IS NOT ALLOWED TO INSERT IT INTO THE LIST */
6404 /* BEFORE CHECKING THE NEW MBYTE SINCE THAT WILL*/
6405 /* CAUSE THE OLD VALUES OF TC_CONNECTPTR TO BE */
6406 /* USED IN WRITE_FILE_DESCRIPTOR. */
6407 /* -------------------------------------------------- */
6408  Uint32 tcIndex = tcConnectptr.i;
6409  tmpTcConnectptr.i = regLogPartPtr->lastLogTcrec;
6410  regLogPartPtr->lastLogTcrec = tcIndex;
6411  if (tmpTcConnectptr.i == RNIL) {
6412  jam();
6413  regLogPartPtr->firstLogTcrec = tcIndex;
6414  } else {
6415  ptrCheckGuard(tmpTcConnectptr, ctcConnectrecFileSize, tcConnectionrec);
6416  tmpTcConnectptr.p->nextLogTcrec = tcIndex;
6417  }//if
6418  Uint32 fileNo = logFilePtr.p->fileNo;
6419  tcurrentFilepage = logFilePtr.p->currentFilepage;
6420  logPagePtr.i = logFilePtr.p->currentLogpage;
6421  regTcPtr->nextLogTcrec = RNIL;
6422  regTcPtr->prevLogTcrec = tmpTcConnectptr.i;
6423  ptrCheckGuard(logPagePtr, clogPageFileSize, logPageRecord);
6424  Uint32 pageIndex = logPagePtr.p->logPageWord[ZCURR_PAGE_INDEX];
6425  regTcPtr->logStartFileNo = fileNo;
6426  regTcPtr->logStartPageNo = tcurrentFilepage;
6427  regTcPtr->logStartPageIndex = pageIndex;
6428 /* -------------------------------------------------- */
6429 /* WRITE THE LOG HEADER OF THIS OPERATION. */
6430 /* -------------------------------------------------- */
6431  writeLogHeader(signal);
6432 /* -------------------------------------------------- */
6433 /* WRITE THE TUPLE KEY OF THIS OPERATION. */
6434 /* -------------------------------------------------- */
6435  writeKey(signal);
6436 /* -------------------------------------------------- */
6437 /* WRITE THE ATTRIBUTE INFO OF THIS OPERATION. */
6438 /* -------------------------------------------------- */
6439  writeAttrinfoLab(signal);
6440 
6441 /* -------------------------------------------------- */
6442 /* RESET THE STATE OF THE LOG PART. IF ANY */
6443 /* OPERATIONS HAVE QUEUED THEN START THE FIRST */
6444 /* OF THESE. */
6445 /* -------------------------------------------------- */
6446 /* -------------------------------------------------- */
6447 /* CONTINUE WITH PACKING OF LQHKEYREQ */
6448 /* -------------------------------------------------- */
6449  tcurrentFilepage = logFilePtr.p->currentFilepage;
6450  if (logPagePtr.p->logPageWord[ZCURR_PAGE_INDEX] == ZPAGE_HEADER_SIZE) {
6451  jam();
6452  tcurrentFilepage--;
6453  }//if
6454  regTcPtr->logStopPageNo = tcurrentFilepage;
6455  regTcPtr->logWriteState = TcConnectionrec::WRITTEN;
6456  if (regTcPtr->abortState != TcConnectionrec::ABORT_IDLE) {
6457 /* -------------------------------------------------- */
6458 /* AN ABORT HAVE BEEN ORDERED. THE ABORT WAITED */
6459 /* FOR THE LOG WRITE TO BE COMPLETED. NOW WE */
6460 /* CAN PROCEED WITH THE NORMAL ABORT HANDLING. */
6461 /* -------------------------------------------------- */
6462  abortCommonLab(signal);
6463  return;
6464  }//if
6465  if (regTcPtr->dirtyOp != ZTRUE) {
6466  packLqhkeyreqLab(signal);
6467  } else {
6468  /* ----------------------------------------------------------------------
6469  * I NEED TO INSERT A COMMIT LOG RECORD SINCE WE ARE WRITING LOG IN THIS
6470  * TRANSACTION. SINCE WE RELEASED THE LOG LOCK JUST NOW NO ONE ELSE CAN BE
6471  * ACTIVE IN WRITING THE LOG. WE THUS WRITE THE LOG WITHOUT GETTING A LOCK
6472  * SINCE WE ARE ONLY WRITING A COMMIT LOG RECORD.
6473  * ---------------------------------------------------------------------- */
6474  writeCommitLog(signal, logPartPtr);
6475  /* ----------------------------------------------------------------------
6476  * DIRTY OPERATIONS SHOULD COMMIT BEFORE THEY PACK THE REQUEST/RESPONSE.
6477  * ---------------------------------------------------------------------- */
6478  localCommitLab(signal);
6479  }//if
6480 }//Dblqh::logLqhkeyreqLab()
6481 
6482 void
6483 Dblqh::logLqhkeyreqLab_problems(Signal * signal)
6484 {
6485  jam();
6486  LogPartRecord * const regLogPartPtr = logPartPtr.p;
6487  Uint32 problems = regLogPartPtr->m_log_problems;
6488 
6489  if (cnoOfLogPages < ZMIN_LOG_PAGES_OPERATION)
6490  {
6491  jam();
6492  terrorCode = ZTEMPORARY_REDO_LOG_FAILURE;
6493  }
6494  else if ((problems & LogPartRecord::P_TAIL_PROBLEM) != 0)
6495  {
6496  jam();
6497  terrorCode = ZTAIL_PROBLEM_IN_LOG_ERROR;
6498  }
6499  else if ((problems & LogPartRecord::P_REDO_IO_PROBLEM) != 0)
6500  {
6501  jam();
6502  terrorCode = ZREDO_IO_PROBLEM;
6503  }
6504  else if ((problems & LogPartRecord::P_FILE_CHANGE_PROBLEM) != 0)
6505  {
6506  jam();
6507  terrorCode = ZFILE_CHANGE_PROBLEM_IN_LOG_ERROR;
6508  }
6509  abortErrorLab(signal);
6510 }
6511 
6512 void
6513 Dblqh::update_log_problem(Signal* signal, Ptr<LogPartRecord> partPtr,
6514  Uint32 problem, bool value)
6515 {
6516  Uint32 problems = partPtr.p->m_log_problems;
6517  if (value)
6518  {
6522  jam();
6523  if ((problems & problem) == 0)
6524  {
6525  jam();
6526  problems |= problem;
6527  }
6528  }
6529  else
6530  {
6534  jam();
6535  if ((problems & problem) != 0)
6536  {
6537  jam();
6538  problems &= ~(Uint32)problem;
6539 
6540  if (partPtr.p->LogLqhKeyReqSent == ZFALSE &&
6541  (!partPtr.p->m_log_prepare_queue.isEmpty() ||
6542  !partPtr.p->m_log_complete_queue.isEmpty()))
6543  {
6544  jam();
6545 
6546  partPtr.p->LogLqhKeyReqSent = ZTRUE;
6547  signal->theData[0] = ZLOG_LQHKEYREQ;
6548  signal->theData[1] = partPtr.i;
6549  sendSignal(cownref, GSN_CONTINUEB, signal, 2, JBB);
6550  }
6551  }
6552  }
6553  partPtr.p->m_log_problems = problems;
6554 }
6555 
6556 /* ------------------------------------------------------------------------- */
6557 /* ------- SEND LQHKEYREQ */
6558 /* */
6559 /* NO STATE CHECKING SINCE THE SIGNAL IS A LOCAL SIGNAL. THE EXECUTION OF */
6560 /* THE OPERATION IS COMPLETED. IT IS NOW TIME TO SEND THE OPERATION TO THE */
6561 /* NEXT REPLICA OR TO TC. */
6562 /* ------------------------------------------------------------------------- */
6563 void Dblqh::packLqhkeyreqLab(Signal* signal)
6564 {
6565  TcConnectionrec * const regTcPtr = tcConnectptr.p;
6566  if (regTcPtr->nextReplica == ZNIL) {
6567 /* ------------------------------------------------------------------------- */
6568 /* ------- SEND LQHKEYCONF ------- */
6569 /* */
6570 /* ------------------------------------------------------------------------- */
6571  sendLqhkeyconfTc(signal, regTcPtr->tcBlockref);
6572  if (! (regTcPtr->dirtyOp ||
6573  (regTcPtr->operation == ZREAD && regTcPtr->opSimple)))
6574  {
6575  jam();
6576  regTcPtr->transactionState = TcConnectionrec::PREPARED;
6577  releaseOprec(signal);
6578  } else {
6579  jam();
6580 
6581 /*************************************************************>*/
6582 /* DIRTY WRITES ARE USED IN TWO SITUATIONS. THE FIRST */
6583 /* SITUATION IS WHEN THEY ARE USED TO UPDATE COUNTERS AND*/
6584 /* OTHER ATTRIBUTES WHICH ARE NOT SENSITIVE TO CONSISTE- */
6585 /* NCY. THE SECOND SITUATION IS BY OPERATIONS THAT ARE */
6586 /* SENT AS PART OF A COPY FRAGMENT PROCESS. */
6587 /* */
6588 /* DURING A COPY FRAGMENT PROCESS THERE IS NO LOGGING */
6589 /* ONGOING SINCE THE FRAGMENT IS NOT COMPLETE YET. THE */
6590 /* LOGGING STARTS AFTER COMPLETING THE LAST COPY TUPLE */
6591 /* OPERATION. THE EXECUTION OF THE LAST COPY TUPLE DOES */
6592 /* ALSO START A LOCAL CHECKPOINT SO THAT THE FRAGMENT */
6593 /* REPLICA IS RECOVERABLE. THUS GLOBAL CHECKPOINT ID FOR */
6594 /* THOSE OPERATIONS ARE NOT INTERESTING. */
6595 /* */
6596 /* A DIRTY WRITE IS BY DEFINITION NOT CONSISTENT. THUS */
6597 /* IT CAN USE ANY GLOBAL CHECKPOINT. THE IDEA HERE IS TO */
6598 /* ALWAYS USE THE LATEST DEFINED GLOBAL CHECKPOINT ID IN */
6599 /* THIS NODE. */
6600 /*************************************************************>*/
6601  cleanUp(signal);
6602  }//if
6603  return;
6604  }//if
6605 /* ------------------------------------------------------------------------- */
6606 /* ------- SEND LQHKEYREQ ------- */
6607 /* */
6608 /* ------------------------------------------------------------------------- */
6609 /* ------------------------------------------------------------------------- */
6610 /* THERE ARE MORE REPLICAS TO SEND THE OPERATION TO. A NEW LQHKEYREQ WILL BE */
6611 /* PREPARED FOR THE NEXT REPLICA. */
6612 /* ------------------------------------------------------------------------- */
6613 /* CLEAR REPLICA TYPE, ATTRINFO INDICATOR (IN LQHKEYREQ), */
6614 /* INTERPRETED EXECUTION, SEQUENTIAL NUMBER OF REPLICA. */
6615 // Set bit indicating Client and TC record not the same.
6616 // Set readlenAi indicator if readlenAi != 0
6617 // Stored Procedure Indicator not set.
6618 /* ------------------------------------------------------------------------- */
6619  LqhKeyReq * const lqhKeyReq = (LqhKeyReq *)&signal->theData[0];
6620 
6621  UintR Treqinfo;
6622  UintR sig0, sig1, sig2, sig3, sig4, sig5, sig6;
6623  Treqinfo = preComputedRequestInfoMask & regTcPtr->reqinfo;
6624 
6625  Uint32 nextNodeId = regTcPtr->nextReplica;
6626  Uint32 nextVersion = getNodeInfo(nextNodeId).m_version;
6627 
6628  /* Send long LqhKeyReq to next replica if it can support it */
6629  bool sendLongReq= ! ((nextVersion < NDBD_LONG_LQHKEYREQ) ||
6630  ERROR_INSERTED(5051));
6631 
6632  UintR TAiLen = sendLongReq ?
6633  0 :
6634  MIN(regTcPtr->totSendlenAi, LqhKeyReq::MaxAttrInfo);
6635 
6636  /* Long LQHKeyReq uses section size for key length */
6637  Uint32 lqhKeyLen= sendLongReq?
6638  0 :
6639  regTcPtr->primKeyLen;
6640 
6641  UintR TapplAddressIndicator = (regTcPtr->nextSeqNoReplica == 0 ? 0 : 1);
6642  LqhKeyReq::setApplicationAddressFlag(Treqinfo, TapplAddressIndicator);
6643  LqhKeyReq::setInterpretedFlag(Treqinfo, regTcPtr->opExec);
6644  LqhKeyReq::setSeqNoReplica(Treqinfo, regTcPtr->nextSeqNoReplica);
6645  LqhKeyReq::setAIInLqhKeyReq(Treqinfo, TAiLen);
6646  LqhKeyReq::setKeyLen(Treqinfo,lqhKeyLen);
6647 
6648  if (unlikely(nextVersion < NDBD_ROWID_VERSION))
6649  {
6650  LqhKeyReq::setLockType(Treqinfo, regTcPtr->lockType);
6651  }
6652  else
6653  {
6654  regTcPtr->m_use_rowid |=
6655  fragptr.p->m_copy_started_state == Fragrecord::AC_NR_COPY;
6656  LqhKeyReq::setRowidFlag(Treqinfo, regTcPtr->m_use_rowid);
6657  }
6658 
6659  if (LqhKeyReq::getRowidFlag(Treqinfo))
6660  {
6661  //ndbassert(LqhKeyReq::getOperation(Treqinfo) == ZINSERT);
6662  }
6663  else
6664  {
6665  if (fragptr.p->m_copy_started_state != Fragrecord::AC_IGNORED)
6666  {
6667  ndbassert(LqhKeyReq::getOperation(Treqinfo) != ZINSERT ||
6668  get_node_status(nextNodeId) != ZNODE_UP);
6669  }
6670  }
6671 
6672  UintR TreadLenAiInd = (regTcPtr->readlenAi == 0 ? 0 : 1);
6673  UintR TsameLqhAndClient = (tcConnectptr.i ==
6674  regTcPtr->tcOprec ? 0 : 1);
6675  LqhKeyReq::setSameClientAndTcFlag(Treqinfo, TsameLqhAndClient);
6676  LqhKeyReq::setReturnedReadLenAIFlag(Treqinfo, TreadLenAiInd);
6677 
6678  /* Long LQHKeyReq uses section size for AttrInfo length */
6679  UintR TotReclenAi = sendLongReq ?
6680  0 :
6681  regTcPtr->totSendlenAi;
6682 
6683  LqhKeyReq::setReorgFlag(TotReclenAi, regTcPtr->m_reorg);
6684 
6685 /* ------------------------------------------------------------------------- */
6686 /* WE ARE NOW PREPARED TO SEND THE LQHKEYREQ. WE HAVE TO DECIDE IF ATTRINFO */
6687 /* IS INCLUDED IN THE LQHKEYREQ SIGNAL AND THEN SEND IT. */
6688 /* TAKE OVER SCAN OPERATION IS NEVER USED ON BACKUPS, LOG RECORDS AND START-UP*/
6689 /* OF NEW REPLICA AND THUS ONLY TOT_SENDLEN_AI IS USED THE UPPER 16 BITS ARE */
6690 /* ZERO. */
6691 /* ------------------------------------------------------------------------- */
6692  sig0 = tcConnectptr.i;
6693  sig1 = regTcPtr->savePointId;
6694  sig2 = regTcPtr->hashValue;
6695  sig4 = regTcPtr->tcBlockref;
6696 
6697  lqhKeyReq->clientConnectPtr = sig0;
6698  lqhKeyReq->attrLen = TotReclenAi;
6699  lqhKeyReq->savePointId = sig1;
6700  lqhKeyReq->hashValue = sig2;
6701  lqhKeyReq->requestInfo = Treqinfo;
6702  lqhKeyReq->tcBlockref = sig4;
6703 
6704  sig0 = regTcPtr->tableref + ((regTcPtr->schemaVersion << 16) & 0xFFFF0000);
6705  sig1 = regTcPtr->fragmentid + (regTcPtr->nodeAfterNext[0] << 16);
6706  sig2 = regTcPtr->transid[0];
6707  sig3 = regTcPtr->transid[1];
6708  sig4 = regTcPtr->applRef;
6709  sig5 = regTcPtr->applOprec;
6710  sig6 = regTcPtr->tcOprec;
6711  UintR nextPos = (TapplAddressIndicator << 1);
6712 
6713  lqhKeyReq->tableSchemaVersion = sig0;
6714  lqhKeyReq->fragmentData = sig1;
6715  lqhKeyReq->transId1 = sig2;
6716  lqhKeyReq->transId2 = sig3;
6717  lqhKeyReq->noFiredTriggers = regTcPtr->noFiredTriggers;
6718  lqhKeyReq->variableData[0] = sig4;
6719  lqhKeyReq->variableData[1] = sig5;
6720  lqhKeyReq->variableData[2] = sig6;
6721 
6722  nextPos += TsameLqhAndClient;
6723 
6724  if ((regTcPtr->lastReplicaNo - regTcPtr->nextSeqNoReplica) > 1) {
6725  sig0 = (UintR)regTcPtr->nodeAfterNext[1] +
6726  (UintR)(regTcPtr->nodeAfterNext[2] << 16);
6727  lqhKeyReq->variableData[nextPos] = sig0;
6728  nextPos++;
6729  }//if
6730  sig0 = regTcPtr->readlenAi;
6731  lqhKeyReq->variableData[nextPos] = sig0;
6732  nextPos += TreadLenAiInd;
6733 
6734  if (!sendLongReq)
6735  {
6736  /* Short LQHKEYREQ to older LQH
6737  * First few words of KeyInfo go into LQHKEYREQ
6738  * Sometimes have no Keyinfo
6739  */
6740  if (regTcPtr->primKeyLen != 0)
6741  {
6742  SegmentedSectionPtr keyInfoSection;
6743 
6744  ndbassert(regTcPtr->keyInfoIVal != RNIL);
6745 
6746  getSection(keyInfoSection, regTcPtr->keyInfoIVal);
6747  SectionReader keyInfoReader(keyInfoSection, g_sectionSegmentPool);
6748 
6749  UintR keyLenInLqhKeyReq= MIN(LqhKeyReq::MaxKeyInfo,
6750  regTcPtr->primKeyLen);
6751 
6752  keyInfoReader.getWords(&lqhKeyReq->variableData[nextPos],
6753  keyLenInLqhKeyReq);
6754 
6755  nextPos+= keyLenInLqhKeyReq;
6756  }
6757  }
6758 
6759  sig0 = regTcPtr->gci_hi;
6760  Local_key tmp = regTcPtr->m_row_id;
6761 
6762  lqhKeyReq->variableData[nextPos + 0] = tmp.m_page_no;
6763  lqhKeyReq->variableData[nextPos + 1] = tmp.m_page_idx;
6764  nextPos += 2*LqhKeyReq::getRowidFlag(Treqinfo);
6765 
6766  lqhKeyReq->variableData[nextPos + 0] = sig0;
6767  nextPos += LqhKeyReq::getGCIFlag(Treqinfo);
6768 
6769  // pass full instance key for remote to map to real instance
6770  BlockReference lqhRef = numberToRef(DBLQH,
6771  fragptr.p->lqhInstanceKey,
6772  regTcPtr->nextReplica);
6773 
6774  if (likely(sendLongReq))
6775  {
6776  /* Long LQHKEYREQ, attach KeyInfo and AttrInfo
6777  * sections to signal
6778  */
6779  SectionHandle handle(this);
6780  handle.m_cnt= 0;
6781 
6782  if (regTcPtr->primKeyLen > 0)
6783  {
6784  SegmentedSectionPtr keyInfoSection;
6785 
6786  ndbassert(regTcPtr->keyInfoIVal != RNIL);
6787  getSection(keyInfoSection, regTcPtr->keyInfoIVal);
6788 
6789  handle.m_ptr[ LqhKeyReq::KeyInfoSectionNum ]= keyInfoSection;
6790  handle.m_cnt= 1;
6791 
6792  if (regTcPtr->totSendlenAi > 0)
6793  {
6794  SegmentedSectionPtr attrInfoSection;
6795 
6796  ndbassert(regTcPtr->attrInfoIVal != RNIL);
6797  getSection(attrInfoSection, regTcPtr->attrInfoIVal);
6798 
6799  handle.m_ptr[ LqhKeyReq::AttrInfoSectionNum ]= attrInfoSection;
6800  handle.m_cnt= 2;
6801  }
6802  else
6803  {
6804  /* No AttrInfo to be sent on. This can occur for delete
6805  * or with an interpreted update when no actual update
6806  * is made
6807  * In this case, we free any attrInfo section now.
6808  */
6809  if (regTcPtr->attrInfoIVal != RNIL)
6810  {
6811  ndbassert(!( regTcPtr->m_flags &
6812  TcConnectionrec::OP_SAVEATTRINFO));
6813  releaseSection(regTcPtr->attrInfoIVal);
6814  regTcPtr->attrInfoIVal= RNIL;
6815  }
6816  }
6817  }
6818  else
6819  {
6820  /* Zero-length primary key, better not have any
6821  * AttrInfo
6822  */
6823  ndbrequire(regTcPtr->totSendlenAi == 0);
6824  ndbassert(regTcPtr->keyInfoIVal == RNIL);
6825  ndbassert(regTcPtr->attrInfoIVal == RNIL);
6826  }
6827 
6828  sendSignal(lqhRef, GSN_LQHKEYREQ, signal,
6829  LqhKeyReq::FixedSignalLength + nextPos,
6830  JBB,
6831  &handle);
6832 
6833  /* Long sections were freed as part of sendSignal */
6834  ndbassert( handle.m_cnt == 0);
6835  regTcPtr->keyInfoIVal= RNIL;
6836  regTcPtr->attrInfoIVal= RNIL;
6837  }
6838  else
6839  {
6840  /* Short LQHKEYREQ to older LQH
6841  * First few words of ATTRINFO go into LQHKEYREQ
6842  * (if they fit)
6843  */
6844  if (TAiLen > 0)
6845  {
6846  if (likely(nextPos + TAiLen + LqhKeyReq::FixedSignalLength <= 25))
6847  {
6848  jam();
6849  SegmentedSectionPtr attrInfoSection;
6850 
6851  ndbassert(regTcPtr->attrInfoIVal != RNIL);
6852 
6853  getSection(attrInfoSection, regTcPtr->attrInfoIVal);
6854  SectionReader attrInfoReader(attrInfoSection, getSectionSegmentPool());
6855 
6856  attrInfoReader.getWords(&lqhKeyReq->variableData[nextPos],
6857  TAiLen);
6858 
6859  nextPos+= TAiLen;
6860  }
6861  else
6862  {
6863  /* Not enough space in LQHKEYREQ, we'll send everything in
6864  * separate ATTRINFO signals
6865  */
6866  Treqinfo &= ~(Uint32)(RI_AI_IN_THIS_MASK << RI_AI_IN_THIS_SHIFT);
6867  lqhKeyReq->requestInfo = Treqinfo;
6868  TAiLen= 0;
6869  }
6870  }
6871 
6872  sendSignal(lqhRef, GSN_LQHKEYREQ, signal,
6873  nextPos + LqhKeyReq::FixedSignalLength, JBB);
6874 
6875  /* Send extra KeyInfo signals if necessary... */
6876  if (regTcPtr->primKeyLen > LqhKeyReq::MaxKeyInfo) {
6877  jam();
6878  sendTupkey(signal);
6879  }//if
6880 
6881  /* Send extra AttrInfo signals if necessary... */
6882  Uint32 remainingAiLen= regTcPtr->totSendlenAi - TAiLen;
6883 
6884  if (remainingAiLen != 0)
6885  {
6886  sig0 = regTcPtr->tcOprec;
6887  sig1 = regTcPtr->transid[0];
6888  sig2 = regTcPtr->transid[1];
6889  signal->theData[0] = sig0;
6890  signal->theData[1] = sig1;
6891  signal->theData[2] = sig2;
6892 
6893  SectionReader attrInfoReader(regTcPtr->attrInfoIVal,
6894  g_sectionSegmentPool);
6895 
6896  ndbassert(attrInfoReader.getSize() == regTcPtr->totSendlenAi);
6897 
6898  /* Step over words already sent in LQHKEYREQ above */
6899  attrInfoReader.step(TAiLen);
6900 
6901  while (remainingAiLen != 0)
6902  {
6903  Uint32 dataInSignal= MIN(AttrInfo::DataLength, remainingAiLen);
6904  attrInfoReader.getWords(&signal->theData[3],
6905  dataInSignal);
6906  remainingAiLen-= dataInSignal;
6907  sendSignal(lqhRef, GSN_ATTRINFO, signal,
6908  AttrInfo::HeaderLength + dataInSignal, JBB);
6909  }
6910  }
6911  }
6912 
6913  /* LQHKEYREQ sent */
6914 
6915  regTcPtr->transactionState = TcConnectionrec::PREPARED;
6916  if (regTcPtr->dirtyOp == ZTRUE) {
6917  jam();
6918 /*************************************************************>*/
6919 /* DIRTY WRITES ARE USED IN TWO SITUATIONS. THE FIRST */
6920 /* SITUATION IS WHEN THEY ARE USED TO UPDATE COUNTERS AND*/
6921 /* OTHER ATTRIBUTES WHICH ARE NOT SENSITIVE TO CONSISTE- */
6922 /* NCY. THE SECOND SITUATION IS BY OPERATIONS THAT ARE */
6923 /* SENT AS PART OF A COPY FRAGMENT PROCESS. */
6924 /* */
6925 /* DURING A COPY FRAGMENT PROCESS THERE IS NO LOGGING */
6926 /* ONGOING SINCE THE FRAGMENT IS NOT COMPLETE YET. THE */
6927 /* LOGGING STARTS AFTER COMPLETING THE LAST COPY TUPLE */
6928 /* OPERATION. THE EXECUTION OF THE LAST COPY TUPLE DOES */
6929 /* ALSO START A LOCAL CHECKPOINT SO THAT THE FRAGMENT */
6930 /* REPLICA IS RECOVERABLE. THUS GLOBAL CHECKPOINT ID FOR */
6931 /* THOSE OPERATIONS ARE NOT INTERESTING. */
6932 /* */
6933 /* A DIRTY WRITE IS BY DEFINITION NOT CONSISTENT. THUS */
6934 /* IT CAN USE ANY GLOBAL CHECKPOINT. THE IDEA HERE IS TO */
6935 /* ALWAYS USE THE LATEST DEFINED GLOBAL CHECKPOINT ID IN */
6936 /* THIS NODE. */
6937 /*************************************************************>*/
6938  cleanUp(signal);
6939  return;
6940  }//if
6941  /* ------------------------------------------------------------------------
6942  * ALL INFORMATION NEEDED BY THE COMMIT PHASE AND COMPLETE PHASE IS
6943  * KEPT IN THE TC_CONNECT RECORD. TO ENSURE PROPER USE OF MEMORY
6944  * RESOURCES WE DEALLOCATE THE ATTRINFO RECORD AND KEY RECORDS
6945  * AS SOON AS POSSIBLE.
6946  * ------------------------------------------------------------------------ */
6947  releaseOprec(signal);
6948 }//Dblqh::packLqhkeyreqLab()
6949 
6950 /* ========================================================================= */
6951 /* ==== CHECK IF THE LOG RECORD FITS INTO THE CURRENT MBYTE, ======= */
6952 /* OTHERWISE SWITCH TO NEXT MBYTE. */
6953 /* */
6954 /* ========================================================================= */
6955 void Dblqh::checkNewMbyte(Signal* signal)
6956 {
6957  UintR tcnmTmp;
6958  UintR ttotalLogSize;
6959 
6960 /* -------------------------------------------------- */
6961 /* CHECK IF A NEW MBYTE OF LOG RECORD IS TO BE */
6962 /* OPENED BEFORE WRITING THE LOG RECORD. NO LOG */
6963 /* RECORDS ARE ALLOWED TO SPAN A MBYTE BOUNDARY */
6964 /* */
6965 /* INPUT: TC_CONNECTPTR THE OPERATION */
6966 /* LOG_FILE_PTR THE LOG FILE */
6967 /* OUTPUT: LOG_FILE_PTR THE NEW LOG FILE */
6968 /* -------------------------------------------------- */
6969  ttotalLogSize = ZLOG_HEAD_SIZE + tcConnectptr.p->currTupAiLen;
6970  ttotalLogSize = ttotalLogSize + tcConnectptr.p->primKeyLen;
6971  tcnmTmp = logFilePtr.p->remainingWordsInMbyte;
6972  if ((ttotalLogSize + ZNEXT_LOG_SIZE) <= tcnmTmp) {
6973  ndbrequire(tcnmTmp >= ttotalLogSize);
6974  logFilePtr.p->remainingWordsInMbyte = tcnmTmp - ttotalLogSize;
6975  return;
6976  } else {
6977  jam();
6978 /* -------------------------------------------------- */
6979 /* IT WAS NOT ENOUGH SPACE IN THIS MBYTE FOR */
6980 /* THIS LOG RECORD. MOVE TO NEXT MBYTE */
6981 /* THIS MIGHT INCLUDE CHANGING LOG FILE */
6982 /* -------------------------------------------------- */
6983 /* WE HAVE TO INSERT A NEXT LOG RECORD FIRST */
6984 /* -------------------------------------------------- */
6985 /* THEN CONTINUE BY WRITING THE FILE DESCRIPTORS*/
6986 /* -------------------------------------------------- */
6987  logPagePtr.i = logFilePtr.p->currentLogpage;
6988  ptrCheckGuard(logPagePtr, clogPageFileSize, logPageRecord);
6989  changeMbyte(signal);
6990  tcnmTmp = logFilePtr.p->remainingWordsInMbyte;
6991  }//if
6992  ndbrequire(tcnmTmp >= ttotalLogSize);
6993  logFilePtr.p->remainingWordsInMbyte = tcnmTmp - ttotalLogSize;
6994 }//Dblqh::checkNewMbyte()
6995 
6996 /* --------------------------------------------------------------------------
6997  * ------- WRITE OPERATION HEADER TO LOG -------
6998  *
6999  * SUBROUTINE SHORT NAME: WLH
7000  * ------------------------------------------------------------------------- */
7001 void Dblqh::writeLogHeader(Signal* signal)
7002 {
7003  Uint32 logPos = logPagePtr.p->logPageWord[ZCURR_PAGE_INDEX];
7004  Uint32 hashValue = tcConnectptr.p->hashValue;
7005  Uint32 operation = tcConnectptr.p->operation;
7006  Uint32 keyLen = tcConnectptr.p->primKeyLen;
7007  Uint32 aiLen = tcConnectptr.p->currTupAiLen;
7008  Local_key rowid = tcConnectptr.p->m_row_id;
7009  Uint32 totLogLen = ZLOG_HEAD_SIZE + aiLen + keyLen;
7010 
7011  if ((logPos + ZLOG_HEAD_SIZE) < ZPAGE_SIZE) {
7012  Uint32* dataPtr = &logPagePtr.p->logPageWord[logPos];
7013  logPagePtr.p->logPageWord[ZCURR_PAGE_INDEX] = logPos + ZLOG_HEAD_SIZE;
7014  dataPtr[0] = ZPREP_OP_TYPE;
7015  dataPtr[1] = totLogLen;
7016  dataPtr[2] = hashValue;
7017  dataPtr[3] = operation;
7018  dataPtr[4] = aiLen;
7019  dataPtr[5] = keyLen;
7020  dataPtr[6] = rowid.m_page_no;
7021  dataPtr[7] = rowid.m_page_idx;
7022  } else {
7023  writeLogWord(signal, ZPREP_OP_TYPE);
7024  writeLogWord(signal, totLogLen);
7025  writeLogWord(signal, hashValue);
7026  writeLogWord(signal, operation);
7027  writeLogWord(signal, aiLen);
7028  writeLogWord(signal, keyLen);
7029  writeLogWord(signal, rowid.m_page_no);
7030  writeLogWord(signal, rowid.m_page_idx);
7031  }//if
7032 }//Dblqh::writeLogHeader()
7033 
7034 /* --------------------------------------------------------------------------
7035  * ------- WRITE TUPLE KEY TO LOG -------
7036  *
7037  * SUBROUTINE SHORT NAME: WK
7038  * ------------------------------------------------------------------------- */
7039 void Dblqh::writeKey(Signal* signal)
7040 {
7041  TcConnectionrec * const regTcPtr = tcConnectptr.p;
7042  jam();
7043  SectionReader keyInfoReader(regTcPtr->keyInfoIVal,
7044  g_sectionSegmentPool);
7045  const Uint32* srcPtr;
7046  Uint32 length;
7047  Uint32 wordsWritten= 0;
7048 
7049  /* Write contiguous chunks of words from the KeyInfo
7050  * section to the log
7051  */
7052  while (keyInfoReader.getWordsPtr(srcPtr,
7053  length))
7054  {
7055  writeLogWords(signal, srcPtr, length);
7056  wordsWritten+= length;
7057  }
7058 
7059  ndbassert( wordsWritten == regTcPtr->primKeyLen );
7060 }//Dblqh::writeKey()
7061 
7062 /* --------------------------------------------------------------------------
7063  * ------- WRITE ATTRINFO TO LOG -------
7064  *
7065  * SUBROUTINE SHORT NAME: WA
7066  * ------------------------------------------------------------------------- */
7067 void Dblqh::writeAttrinfoLab(Signal* signal)
7068 {
7069  TcConnectionrec * const regTcPtr = tcConnectptr.p;
7070  Uint32 totLen = regTcPtr->currTupAiLen;
7071  if (totLen == 0)
7072  return;
7073 
7074  jam();
7075  ndbassert( regTcPtr->attrInfoIVal != RNIL );
7076  SectionReader attrInfoReader(regTcPtr->attrInfoIVal,
7077  g_sectionSegmentPool);
7078  const Uint32* srcPtr;
7079  Uint32 length;
7080  Uint32 wordsWritten= 0;
7081 
7082  /* Write contiguous chunks of words from the
7083  * AttrInfo section to the log
7084  */
7085  while (attrInfoReader.getWordsPtr(srcPtr,
7086  length))
7087  {
7088  writeLogWords(signal, srcPtr, length);
7089  wordsWritten+= length;
7090  }
7091 
7092  ndbassert( wordsWritten == totLen );
7093 }//Dblqh::writeAttrinfoLab()
7094 
7095 /* ------------------------------------------------------------------------- */
7096 /* ------- SEND TUPLE KEY IN KEYINFO SIGNAL(S) ------- */
7097 /* */
7098 /* SUBROUTINE SHORT NAME: STU */
7099 /* ------------------------------------------------------------------------- */
7100 void Dblqh::sendTupkey(Signal* signal)
7101 {
7102  BlockReference lqhRef = 0;
7103  {
7104  // wl4391_todo fragptr
7105  FragrecordPtr Tfragptr;
7106  Tfragptr.i = tcConnectptr.p->fragmentptr;
7107  c_fragment_pool.getPtr(Tfragptr);
7108  Uint32 Tnode = tcConnectptr.p->nextReplica;
7109  Uint32 instanceKey = Tfragptr.p->lqhInstanceKey;
7110  lqhRef = numberToRef(DBLQH, instanceKey, Tnode);
7111  }
7112 
7113  signal->theData[0] = tcConnectptr.p->tcOprec;
7114  signal->theData[1] = tcConnectptr.p->transid[0];
7115  signal->theData[2] = tcConnectptr.p->transid[1];
7116 
7117  Uint32 remainingLen= tcConnectptr.p->primKeyLen -
7118  LqhKeyReq::MaxKeyInfo;
7119 
7120  SectionReader keyInfoReader(tcConnectptr.p->keyInfoIVal,
7121  g_sectionSegmentPool);
7122 
7123  ndbassert(keyInfoReader.getSize() > LqhKeyReq::MaxKeyInfo);
7124 
7125  /* Step over the words already sent in LQHKEYREQ */
7126  keyInfoReader.step(LqhKeyReq::MaxKeyInfo);
7127 
7128  while (remainingLen != 0)
7129  {
7130  Uint32 dataInSignal= MIN(KeyInfo::DataLength, remainingLen);
7131  keyInfoReader.getWords(&signal->theData[3],
7132  dataInSignal);
7133  remainingLen-= dataInSignal;
7134  sendSignal(lqhRef, GSN_KEYINFO, signal,
7135  KeyInfo::HeaderLength + dataInSignal, JBB);
7136  }
7137 }//Dblqh::sendTupkey()
7138 
7139 void Dblqh::cleanUp(Signal* signal)
7140 {
7141  releaseOprec(signal);
7142  deleteTransidHash(signal);
7143  releaseTcrec(signal, tcConnectptr);
7144 }//Dblqh::cleanUp()
7145 
7146 /* --------------------------------------------------------------------------
7147  * ---- RELEASE ALL RECORDS CONNECTED TO THE OPERATION RECORD AND THE ----
7148  * OPERATION RECORD ITSELF
7149  * ------------------------------------------------------------------------- */
7150 void Dblqh::releaseOprec(Signal* signal)
7151 {
7152  TcConnectionrec * const regTcPtr = tcConnectptr.p;
7153 
7154  /* Release long sections if present */
7155  releaseSection(regTcPtr->keyInfoIVal);
7156  regTcPtr->keyInfoIVal = RNIL;
7157  releaseSection(regTcPtr->attrInfoIVal);
7158  regTcPtr->attrInfoIVal = RNIL;
7159 
7160  if (regTcPtr->m_dealloc)
7161  {
7162  jam();
7163  regTcPtr->m_dealloc = 0;
7164 
7165  if (TRACENR_FLAG)
7166  TRACENR("DELETED: " << regTcPtr->m_row_id << endl);
7167 
7168  TRACE_OP(regTcPtr, "DO DEALLOC");
7169 
7170  signal->theData[0] = regTcPtr->fragmentid;
7171  signal->theData[1] = regTcPtr->tableref;
7172  signal->theData[2] = regTcPtr->m_row_id.m_page_no;
7173  signal->theData[3] = regTcPtr->m_row_id.m_page_idx;
7174  signal->theData[4] = RNIL;
7175  EXECUTE_DIRECT(DBTUP, GSN_TUP_DEALLOCREQ, signal, 5);
7176  }
7177 }//Dblqh::releaseOprec()
7178 
7179 /* ------------------------------------------------------------------------- */
7180 /* ------ DELETE TRANSACTION ID FROM HASH TABLE ------- */
7181 /* */
7182 /* ------------------------------------------------------------------------- */
7183 void Dblqh::deleteTransidHash(Signal* signal)
7184 {
7185  TcConnectionrec * const regTcPtr = tcConnectptr.p;
7186  TcConnectionrecPtr prevHashptr;
7187  TcConnectionrecPtr nextHashptr;
7188 
7189  prevHashptr.i = regTcPtr->prevHashRec;
7190  nextHashptr.i = regTcPtr->nextHashRec;
7191  if (prevHashptr.i != RNIL) {
7192  jam();
7193  ptrCheckGuard(prevHashptr, ctcConnectrecFileSize, tcConnectionrec);
7194  prevHashptr.p->nextHashRec = nextHashptr.i;
7195  } else {
7196  jam();
7197 /* ------------------------------------------------------------------------- */
7198 /* THE OPERATION WAS PLACED FIRST IN THE LIST OF THE HASH TABLE. NEED TO SET */
7199 /* A NEW LEADER OF THE LIST. */
7200 /* ------------------------------------------------------------------------- */
7201  Uint32 hashIndex = (regTcPtr->transid[0] ^ regTcPtr->tcOprec) & 1023;
7202  ctransidHash[hashIndex] = nextHashptr.i;
7203  }//if
7204  if (nextHashptr.i != RNIL) {
7205  jam();
7206  ptrCheckGuard(nextHashptr, ctcConnectrecFileSize, tcConnectionrec);
7207  nextHashptr.p->prevHashRec = prevHashptr.i;
7208  }//if
7209 
7210  regTcPtr->prevHashRec = regTcPtr->nextHashRec = RNIL;
7211 }//Dblqh::deleteTransidHash()
7212 
7213 /* -------------------------------------------------------------------------
7214  * ------- RELEASE OPERATION FROM ACTIVE LIST ON FRAGMENT -------
7215  *
7216  * SUBROUTINE SHORT NAME = RAF
7217  * ------------------------------------------------------------------------- */
7218 /* ######################################################################### */
7219 /* ####### TRANSACTION MODULE ####### */
7220 /* THIS MODULE HANDLES THE COMMIT AND THE COMPLETE PHASE. */
7221 /* ######################################################################### */
7222 void Dblqh::warningReport(Signal* signal, int place)
7223 {
7224  switch (place) {
7225  case 0:
7226  jam();
7227 #ifdef ABORT_TRACE
7228  ndbout << "W: Received COMMIT in wrong state in Dblqh" << endl;
7229 #endif
7230  break;
7231  case 1:
7232  jam();
7233 #ifdef ABORT_TRACE
7234  ndbout << "W: Received COMMIT with wrong transid in Dblqh" << endl;
7235 #endif
7236  break;
7237  case 2:
7238  jam();
7239 #ifdef ABORT_TRACE
7240  ndbout << "W: Received COMPLETE in wrong state in Dblqh" << endl;
7241 #endif
7242  break;
7243  case 3:
7244  jam();
7245 #ifdef ABORT_TRACE
7246  ndbout << "W: Received COMPLETE with wrong transid in Dblqh" << endl;
7247 #endif
7248  break;
7249  case 4:
7250  jam();
7251 #ifdef ABORT_TRACE
7252  ndbout << "W: Received COMMITREQ in wrong state in Dblqh" << endl;
7253 #endif
7254  break;
7255  case 5:
7256  jam();
7257 #ifdef ABORT_TRACE
7258  ndbout << "W: Received COMMITREQ with wrong transid in Dblqh" << endl;
7259 #endif
7260  break;
7261  case 6:
7262  jam();
7263 #ifdef ABORT_TRACE
7264  ndbout << "W: Received COMPLETEREQ in wrong state in Dblqh" << endl;
7265 #endif
7266  break;
7267  case 7:
7268  jam();
7269 #ifdef ABORT_TRACE
7270  ndbout << "W: Received COMPLETEREQ with wrong transid in Dblqh" << endl;
7271 #endif
7272  break;
7273  case 8:
7274  jam();
7275 #ifdef ABORT_TRACE
7276  ndbout << "W: Received ABORT with non-existing transid in Dblqh" << endl;
7277 #endif
7278  break;
7279  case 9:
7280  jam();
7281 #ifdef ABORT_TRACE
7282  ndbout << "W: Received ABORTREQ with non-existing transid in Dblqh" << endl;
7283 #endif
7284  break;
7285  case 10:
7286  jam();
7287 #ifdef ABORT_TRACE
7288  ndbout << "W: Received ABORTREQ in wrong state in Dblqh" << endl;
7289 #endif
7290  break;
7291  case 11:
7292  jam();
7293 #ifdef ABORT_TRACE
7294  ndbout << "W: Received COMMIT when tc-rec released in Dblqh" << endl;
7295 #endif
7296  break;
7297  case 12:
7298  jam();
7299 #ifdef ABORT_TRACE
7300  ndbout << "W: Received COMPLETE when tc-rec released in Dblqh" << endl;
7301 #endif
7302  break;
7303  case 13:
7304  jam();
7305 #ifdef ABORT_TRACE
7306  ndbout << "W: Received LQHKEYREF when tc-rec released in Dblqh" << endl;
7307 #endif
7308  break;
7309  case 14:
7310  jam();
7311 #ifdef ABORT_TRACE
7312  ndbout << "W: Received LQHKEYREF with wrong transid in Dblqh" << endl;
7313 #endif
7314  break;
7315  case 15:
7316  jam();
7317 #ifdef ABORT_TRACE
7318  ndbout << "W: Received LQHKEYREF when already aborting in Dblqh" << endl;
7319 #endif
7320  break;
7321  case 16:
7322  jam();
7323  ndbrequire(cstartPhase == ZNIL);
7324 #ifdef ABORT_TRACE
7325  ndbout << "W: Received LQHKEYREF in wrong state in Dblqh" << endl;
7326 #endif
7327  break;
7328  default:
7329  jam();
7330  break;
7331  }//switch
7332  return;
7333 }//Dblqh::warningReport()
7334 
7335 void Dblqh::errorReport(Signal* signal, int place)
7336 {
7337  switch (place) {
7338  case 0:
7339  jam();
7340  break;
7341  case 1:
7342  jam();
7343  break;
7344  case 2:
7345  jam();
7346  break;
7347  case 3:
7348  jam();
7349  break;
7350  default:
7351  jam();
7352  break;
7353  }//switch
7354  systemErrorLab(signal, __LINE__);
7355  return;
7356 }//Dblqh::errorReport()
7357 
7358 void
7359 Dblqh::execFIRE_TRIG_REQ(Signal* signal)
7360 {
7361  Uint32 tcOprec = signal->theData[0];
7362  Uint32 transid1 = signal->theData[1];
7363  Uint32 transid2 = signal->theData[2];
7364  Uint32 pass = signal->theData[3];
7365  Uint32 senderRef = signal->getSendersBlockRef();
7366 
7367  jamEntry();
7368 
7369  if (ERROR_INSERTED_CLEAR(5064))
7370  {
7371  // throw away...should cause timeout in TC
7372  return;
7373  }
7374 
7375  CRASH_INSERTION(5072);
7376 
7377  Uint32 err;
7378  if (findTransaction(transid1, transid2, tcOprec, 0) == ZOK &&
7379  !ERROR_INSERTED_CLEAR(5065) &&
7380  !ERROR_INSERTED(5070) &&
7381  !ERROR_INSERTED(5071))
7382  {
7383  TcConnectionrec * const regTcPtr = tcConnectptr.p;
7384 
7385  if (unlikely(regTcPtr->transactionState != TcConnectionrec::PREPARED ||
7386  ERROR_INSERTED_CLEAR(5067)))
7387  {
7388  err = FireTrigRef::FTR_IncorrectState;
7389  goto do_err;
7390  }
7391 
7395  signal->theData[0] = regTcPtr->tupConnectrec;
7396  signal->theData[1] = regTcPtr->tcBlockref;
7397  signal->theData[2] = regTcPtr->tcOprec;
7398  signal->theData[3] = transid1;
7399  signal->theData[4] = transid2;
7400  signal->theData[5] = pass;
7401  Uint32 tup = refToMain(regTcPtr->tcTupBlockref);
7402  EXECUTE_DIRECT(tup, GSN_FIRE_TRIG_REQ, signal, 6);
7403 
7404  err = signal->theData[0];
7405  Uint32 cnt = signal->theData[1];
7406 
7407  if (ERROR_INSERTED_CLEAR(5066))
7408  {
7409  err = 5066;
7410  }
7411 
7412  if (ERROR_INSERTED_CLEAR(5068))
7413  tcOprec++;
7414  if (ERROR_INSERTED_CLEAR(5069))
7415  transid1++;
7416 
7417  if (err == 0)
7418  {
7419  jam();
7420  Uint32 Tdata[FireTrigConf::SignalLength];
7421  FireTrigConf * conf = CAST_PTR(FireTrigConf, Tdata);
7422  conf->tcOpRec = tcOprec;
7423  conf->transId[0] = transid1;
7424  conf->transId[1] = transid2;
7425  conf->noFiredTriggers = cnt;
7426  sendFireTrigConfTc(signal, regTcPtr->tcBlockref, Tdata);
7427  return;
7428  }
7429  }
7430  else
7431  {
7432  jam();
7433  err = FireTrigRef::FTR_UnknownOperation;
7434  }
7435 
7436 do_err:
7437  if (ERROR_INSERTED_CLEAR(5070))
7438  tcOprec++;
7439 
7440  if (ERROR_INSERTED_CLEAR(5071))
7441  transid1++;
7442 
7443  FireTrigRef * ref = CAST_PTR(FireTrigRef, signal->getDataPtrSend());
7444  ref->tcOpRec = tcOprec;
7445  ref->transId[0] = transid1;
7446  ref->transId[1] = transid2;
7447  ref->errCode = err;
7448  sendSignal(senderRef, GSN_FIRE_TRIG_REF,
7449  signal, FireTrigRef::SignalLength, JBB);
7450 
7451  return;
7452 }
7453 
7454 void
7455 Dblqh::sendFireTrigConfTc(Signal* signal,
7456  BlockReference atcBlockref,
7457  Uint32 Tdata[])
7458 {
7459  if (refToInstance(atcBlockref) != 0)
7460  {
7461  jam();
7462  memcpy(signal->theData, Tdata, 4 * FireTrigConf::SignalLength);
7463  sendSignal(atcBlockref, GSN_FIRE_TRIG_CONF,
7464  signal, FireTrigConf::SignalLength, JBB);
7465  return;
7466  }
7467 
7468  HostRecordPtr Thostptr;
7469  Uint32 len = FireTrigConf::SignalLength;
7470 
7471  Thostptr.i = refToNode(atcBlockref);
7472  ptrCheckGuard(Thostptr, chostFileSize, hostRecord);
7473 
7474  if (Thostptr.p->noOfPackedWordsTc > (25 - len))
7475  {
7476  jam();
7477  sendPackedSignalTc(signal, Thostptr.p);
7478  }
7479  else
7480  {
7481  jam();
7482  updatePackedList(signal, Thostptr.p, Thostptr.i);
7483  }
7484 
7485  ndbassert(FireTrigConf::SignalLength == 4);
7486  Uint32 * dst = &Thostptr.p->packedWordsTc[Thostptr.p->noOfPackedWordsTc];
7487  Thostptr.p->noOfPackedWordsTc += len;
7488  dst[0] = Tdata[0] | (ZFIRE_TRIG_CONF << 28);
7489  dst[1] = Tdata[1];
7490  dst[2] = Tdata[2];
7491  dst[3] = Tdata[3];
7492 }
7493 
7494 bool
7495 Dblqh::check_fire_trig_pass(Uint32 opId, Uint32 pass)
7496 {
7501  TcConnectionrecPtr regTcPtr;
7502  regTcPtr.i= opId;
7503  ptrCheckGuard(regTcPtr, ctcConnectrecFileSize, tcConnectionrec);
7504  if (regTcPtr.p->m_fire_trig_pass <= pass)
7505  {
7506  regTcPtr.p->m_fire_trig_pass = pass + 1;
7507  return true;
7508  }
7509  return false;
7510 }
7511 
7512 /* ************************************************************************>>
7513  * COMMIT: Start commit request from TC. This signal is originally sent as a
7514  * packed signal and this function is called from execPACKED_SIGNAL.
7515  * This is the normal commit protocol where TC first send this signal to the
7516  * backup node which then will send COMMIT to the primary node. If
7517  * everything is ok the primary node send COMMITTED back to TC.
7518  * ************************************************************************>> */
7519 void Dblqh::execCOMMIT(Signal* signal)
7520 {
7521  TcConnectionrec *regTcConnectionrec = tcConnectionrec;
7522  Uint32 ttcConnectrecFileSize = ctcConnectrecFileSize;
7523  Uint32 tcIndex = signal->theData[0];
7524  Uint32 gci_hi = signal->theData[1];
7525  Uint32 transid1 = signal->theData[2];
7526  Uint32 transid2 = signal->theData[3];
7527  Uint32 gci_lo = signal->theData[4];
7528  jamEntry();
7529  if (tcIndex >= ttcConnectrecFileSize) {
7530  errorReport(signal, 0);
7531  return;
7532  }//if
7533  if (ERROR_INSERTED(5011)) {
7534  CLEAR_ERROR_INSERT_VALUE;
7535  sendSignalWithDelay(cownref, GSN_COMMIT, signal, 2000,signal->getLength());
7536  return;
7537  }//if
7538  if (ERROR_INSERTED(5012)) {
7539  SET_ERROR_INSERT_VALUE(5017);
7540  sendSignalWithDelay(cownref, GSN_COMMIT, signal, 2000,signal->getLength());
7541  return;
7542  }//if
7543  if (ERROR_INSERTED(5062) &&
7544  ((refToMain(signal->getSendersBlockRef()) == DBTC) ||
7545  signal->getSendersBlockRef() == reference()))
7546  {
7547  Uint32 save = signal->getSendersBlockRef();
7548  ndbout_c("Delaying execCOMMIT");
7549  sendSignalWithDelay(cownref, GSN_COMMIT, signal, 2000, signal->getLength());
7550 
7551  if (refToMain(save) == DBTC)
7552  {
7553  ndbout_c("killing %u", refToNode(save));
7554  signal->theData[0] = 9999;
7555  sendSignal(numberToRef(CMVMI, refToNode(save)),
7556  GSN_NDB_TAMPER, signal, 1, JBB);
7557  }
7558  return;
7559  }
7560 
7561  tcConnectptr.i = tcIndex;
7562  ptrAss(tcConnectptr, regTcConnectionrec);
7563  if ((tcConnectptr.p->transid[0] == transid1) &&
7564  (tcConnectptr.p->transid[1] == transid2)) {
7565 
7566  TcConnectionrec * const regTcPtr = tcConnectptr.p;
7567  TRACE_OP(regTcPtr, "COMMIT");
7568 
7569  CRASH_INSERTION(5048);
7570  if (ERROR_INSERTED(5049))
7571  {
7572  SET_ERROR_INSERT_VALUE(5048);
7573  }
7574 
7575  commitReqLab(signal, gci_hi, gci_lo);
7576  return;
7577  }//if
7578  warningReport(signal, 1);
7579  return;
7580 }//Dblqh::execCOMMIT()
7581 
7582 /* ************************************************************************>>
7583  * COMMITREQ: Commit request from TC. This is the commit protocol used if
7584  * one of the nodes is not behaving correctly. TC explicitly sends COMMITREQ
7585  * to both the backup and primary node and gets a COMMITCONF back if the
7586  * COMMIT was ok.
7587  * ************************************************************************>> */
7588 void Dblqh::execCOMMITREQ(Signal* signal)
7589 {
7590  jamEntry();
7591  Uint32 reqPtr = signal->theData[0];
7592  BlockReference reqBlockref = signal->theData[1];
7593  Uint32 gci_hi = signal->theData[2];
7594  Uint32 transid1 = signal->theData[3];
7595  Uint32 transid2 = signal->theData[4];
7596  Uint32 tcOprec = signal->theData[6];
7597  Uint32 gci_lo = signal->theData[7];
7598 
7599  if (unlikely(signal->getLength() < 8))
7600  {
7601  jam();
7602  gci_lo = 0;
7603  ndbassert(!ndb_check_micro_gcp(getNodeInfo(refToNode(signal->getSendersBlockRef())).m_version));
7604  }
7605 
7606  if (ERROR_INSERTED(5004)) {
7607  systemErrorLab(signal, __LINE__);
7608  }
7609  if (ERROR_INSERTED(5017)) {
7610  CLEAR_ERROR_INSERT_VALUE;
7611  sendSignalWithDelay(cownref, GSN_COMMITREQ, signal, 2000,
7612  signal->getLength());
7613  return;
7614  }//if
7615  if (findTransaction(transid1,
7616  transid2,
7617  tcOprec, 0) != ZOK) {
7618  warningReport(signal, 5);
7619  return;
7620  }//if
7621  TcConnectionrec * const regTcPtr = tcConnectptr.p;
7622  switch (regTcPtr->transactionState) {
7623  case TcConnectionrec::PREPARED:
7624  case TcConnectionrec::LOG_COMMIT_QUEUED_WAIT_SIGNAL:
7625  case TcConnectionrec::LOG_COMMIT_WRITTEN_WAIT_SIGNAL:
7626  jam();
7627 /*-------------------------------------------------------*/
7628 /* THE NORMAL CASE. */
7629 /*-------------------------------------------------------*/
7630  regTcPtr->reqBlockref = reqBlockref;
7631  regTcPtr->reqRef = reqPtr;
7632  regTcPtr->abortState = TcConnectionrec::REQ_FROM_TC;
7633  commitReqLab(signal, gci_hi, gci_lo);
7634  return;
7635  break;
7636  case TcConnectionrec::COMMITTED:
7637  jam();
7638 /*---------------------------------------------------------*/
7639 /* FOR SOME REASON THE COMMIT PHASE HAVE BEEN */
7640 /* FINISHED AFTER A TIME OUT. WE NEED ONLY SEND A */
7641 /* COMMITCONF SIGNAL. */
7642 /*---------------------------------------------------------*/
7643  regTcPtr->reqBlockref = reqBlockref;
7644  regTcPtr->reqRef = reqPtr;
7645  regTcPtr->abortState = TcConnectionrec::REQ_FROM_TC;
7646  signal->theData[0] = regTcPtr->reqRef;
7647  signal->theData[1] = cownNodeid;
7648  signal->theData[2] = regTcPtr->transid[0];
7649  signal->theData[3] = regTcPtr->transid[1];
7650  sendSignal(regTcPtr->reqBlockref, GSN_COMMITCONF, signal, 4, JBB);
7651  break;
7652  case TcConnectionrec::COMMIT_STOPPED:
7653  case TcConnectionrec::WAIT_TUP_COMMIT:
7654  jam();
7655  regTcPtr->reqBlockref = reqBlockref;
7656  regTcPtr->reqRef = reqPtr;
7657  regTcPtr->abortState = TcConnectionrec::REQ_FROM_TC;
7658  /*empty*/;
7659  break;
7660  default:
7661  jam();
7662  warningReport(signal, 4);
7663  return;
7664  break;
7665  }//switch
7666  return;
7667 }//Dblqh::execCOMMITREQ()
7668 
7669 /* ************************************************************************>>
7670  * COMPLETE : Complete the transaction. Sent as a packed signal from TC.
7671  * Works the same way as COMMIT protocol. This is the normal case with both
7672  * primary and backup working (See COMMIT).
7673  * ************************************************************************>> */
7674 void Dblqh::execCOMPLETE(Signal* signal)
7675 {
7676  TcConnectionrec *regTcConnectionrec = tcConnectionrec;
7677  Uint32 ttcConnectrecFileSize = ctcConnectrecFileSize;
7678  Uint32 tcIndex = signal->theData[0];
7679  Uint32 transid1 = signal->theData[1];
7680  Uint32 transid2 = signal->theData[2];
7681  jamEntry();
7682  if (tcIndex >= ttcConnectrecFileSize) {
7683  errorReport(signal, 1);
7684  return;
7685  }//if
7686  CRASH_INSERTION(5042);
7687 
7688  if (ERROR_INSERTED(5013)) {
7689  CLEAR_ERROR_INSERT_VALUE;
7690  sendSignalWithDelay(cownref, GSN_COMPLETE, signal, 2000, 3);
7691  return;
7692  }//if
7693  if (ERROR_INSERTED(5014)) {
7694  SET_ERROR_INSERT_VALUE(5018);
7695  sendSignalWithDelay(cownref, GSN_COMPLETE, signal, 2000, 3);
7696  return;
7697  }//if
7698  if (ERROR_INSERTED(5063) &&
7699  ((refToMain(signal->getSendersBlockRef()) == DBTC) ||
7700  signal->getSendersBlockRef() == reference()))
7701  {
7702  Uint32 save = signal->getSendersBlockRef();
7703  ndbout_c("Delaying execCOMPLETE");
7704  sendSignalWithDelay(cownref, GSN_COMPLETE,signal, 2000,signal->getLength());
7705 
7706  if (refToMain(save) == DBTC)
7707  {
7708  ndbout_c("killing %u", refToNode(save));
7709  signal->theData[0] = 9999;
7710  sendSignal(numberToRef(CMVMI, refToNode(save)),
7711  GSN_NDB_TAMPER, signal, 1, JBB);
7712  }
7713  return;
7714  }
7715 
7716  tcConnectptr.i = tcIndex;
7717  ptrAss(tcConnectptr, regTcConnectionrec);
7718  if ((tcConnectptr.p->transactionState == TcConnectionrec::COMMITTED) &&
7719  (tcConnectptr.p->transid[0] == transid1) &&
7720  (tcConnectptr.p->transid[1] == transid2)) {
7721 
7722  TcConnectionrec * const regTcPtr = tcConnectptr.p;
7723  TRACE_OP(regTcPtr, "COMPLETE");
7724 
7725  if (tcConnectptr.p->seqNoReplica != 0 &&
7726  tcConnectptr.p->activeCreat == Fragrecord::AC_NORMAL) {
7727  jam();
7728  localCommitLab(signal);
7729  return;
7730  }
7731  else if (tcConnectptr.p->seqNoReplica == 0)
7732  {
7733  jam();
7734  completeTransLastLab(signal);
7735  return;
7736  }
7737  else
7738  {
7739  jam();
7740  completeTransNotLastLab(signal);
7741  return;
7742  }
7743  }//if
7744  if (tcConnectptr.p->transactionState != TcConnectionrec::COMMITTED) {
7745  warningReport(signal, 2);
7746  } else {
7747  warningReport(signal, 3);
7748  }//if
7749 }//Dblqh::execCOMPLETE()
7750 
7751 /* ************************************************************************>>
7752  * COMPLETEREQ: Complete request from TC. Same as COMPLETE but used if one
7753  * node is not working ok (See COMMIT).
7754  * ************************************************************************>> */
7755 void Dblqh::execCOMPLETEREQ(Signal* signal)
7756 {
7757  jamEntry();
7758  Uint32 reqPtr = signal->theData[0];
7759  BlockReference reqBlockref = signal->theData[1];
7760  Uint32 transid1 = signal->theData[2];
7761  Uint32 transid2 = signal->theData[3];
7762  Uint32 tcOprec = signal->theData[5];
7763  if (ERROR_INSERTED(5005)) {
7764  systemErrorLab(signal, __LINE__);
7765  }
7766  if (ERROR_INSERTED(5018)) {
7767  CLEAR_ERROR_INSERT_VALUE;
7768  sendSignalWithDelay(cownref, GSN_COMPLETEREQ, signal, 2000, 6);
7769  return;
7770  }//if
7771  if (findTransaction(transid1,
7772  transid2,
7773  tcOprec, 0) != ZOK) {
7774  jam();
7775 /*---------------------------------------------------------*/
7776 /* FOR SOME REASON THE COMPLETE PHASE STARTED AFTER */
7777 /* A TIME OUT. THE TRANSACTION IS GONE. WE NEED TO */
7778 /* REPORT COMPLETION ANYWAY. */
7779 /*---------------------------------------------------------*/
7780  signal->theData[0] = reqPtr;
7781  signal->theData[1] = cownNodeid;
7782  signal->theData[2] = transid1;
7783  signal->theData[3] = transid2;
7784  sendSignal(reqBlockref, GSN_COMPLETECONF, signal, 4, JBB);
7785  warningReport(signal, 7);
7786  return;
7787  }//if
7788  TcConnectionrec * const regTcPtr = tcConnectptr.p;
7789  switch (regTcPtr->transactionState) {
7790  case TcConnectionrec::COMMITTED:
7791  jam();
7792  regTcPtr->reqBlockref = reqBlockref;
7793  regTcPtr->reqRef = reqPtr;
7794  regTcPtr->abortState = TcConnectionrec::REQ_FROM_TC;
7795  /*empty*/;
7796  break;
7797 /*---------------------------------------------------------*/
7798 /* THE NORMAL CASE. */
7799 /*---------------------------------------------------------*/
7800  case TcConnectionrec::COMMIT_STOPPED:
7801  case TcConnectionrec::WAIT_TUP_COMMIT:
7802  jam();
7803 /*---------------------------------------------------------*/
7804 /* FOR SOME REASON THE COMPLETE PHASE STARTED AFTER */
7805 /* A TIME OUT. WE HAVE SET THE PROPER VARIABLES SUCH */
7806 /* THAT A COMPLETECONF WILL BE SENT WHEN COMPLETE IS */
7807 /* FINISHED. */
7808 /*---------------------------------------------------------*/
7809  regTcPtr->reqBlockref = reqBlockref;
7810  regTcPtr->reqRef = reqPtr;
7811  regTcPtr->abortState = TcConnectionrec::REQ_FROM_TC;
7812  return;
7813  break;
7814  default:
7815  jam();
7816  warningReport(signal, 6);
7817  return;
7818  break;
7819  }//switch
7820  if (regTcPtr->seqNoReplica != 0 &&
7821  regTcPtr->activeCreat != Fragrecord::AC_NR_COPY) {
7822  jam();
7823  localCommitLab(signal);
7824  }
7825  else if (regTcPtr->seqNoReplica == 0)
7826  {
7827  jam();
7828  completeTransLastLab(signal);
7829  }
7830  else
7831  {
7832  jam();
7833  completeTransNotLastLab(signal);
7834  }
7835 }//Dblqh::execCOMPLETEREQ()
7836 
7837 /* ************> */
7838 /* COMPLETED > */
7839 /* ************> */
7840 void Dblqh::execLQHKEYCONF(Signal* signal)
7841 {
7842  LqhKeyConf * const lqhKeyConf = (LqhKeyConf *)signal->getDataPtr();
7843  Uint32 tcIndex = lqhKeyConf->opPtr;
7844  Uint32 ttcConnectrecFileSize = ctcConnectrecFileSize;
7845  TcConnectionrec *regTcConnectionrec = tcConnectionrec;
7846  jamEntry();
7847  if (tcIndex >= ttcConnectrecFileSize) {
7848  errorReport(signal, 2);
7849  return;
7850  }//if
7851  tcConnectptr.i = tcIndex;
7852  ptrAss(tcConnectptr, regTcConnectionrec);
7853  switch (tcConnectptr.p->connectState) {
7854  case TcConnectionrec::LOG_CONNECTED:
7855  jam();
7856  completedLab(signal);
7857  return;
7858  break;
7859  case TcConnectionrec::COPY_CONNECTED:
7860  jam();
7861  copyCompletedLab(signal);
7862  return;
7863  break;
7864  default:
7865  jamLine(tcConnectptr.p->connectState);
7866  ndbrequire(false);
7867  break;
7868  }//switch
7869  return;
7870 }//Dblqh::execLQHKEYCONF()
7871 
7872 /* ------------------------------------------------------------------------- */
7873 /* ------- COMMIT PHASE ------- */
7874 /* */
7875 /* ------------------------------------------------------------------------- */
7876 void Dblqh::commitReqLab(Signal* signal, Uint32 gci_hi, Uint32 gci_lo)
7877 {
7878  TcConnectionrec * const regTcPtr = tcConnectptr.p;
7879  TcConnectionrec::LogWriteState logWriteState = regTcPtr->logWriteState;
7880  TcConnectionrec::TransactionState transState = regTcPtr->transactionState;
7881  regTcPtr->gci_hi = gci_hi;
7882  regTcPtr->gci_lo = gci_lo;
7883  if (transState == TcConnectionrec::PREPARED) {
7884  if (logWriteState == TcConnectionrec::WRITTEN) {
7885  jam();
7886  regTcPtr->transactionState = TcConnectionrec::PREPARED_RECEIVED_COMMIT;
7887  TcConnectionrecPtr saveTcPtr = tcConnectptr;
7888  Uint32 blockNo = refToMain(regTcPtr->tcTupBlockref);
7889  signal->theData[0] = regTcPtr->tupConnectrec;
7890  signal->theData[1] = gci_hi;
7891  signal->theData[2] = gci_lo;
7892  EXECUTE_DIRECT(blockNo, GSN_TUP_WRITELOG_REQ, signal, 3);
7893  jamEntry();
7894  if (regTcPtr->transactionState == TcConnectionrec::LOG_COMMIT_QUEUED) {
7895  jam();
7896  return;
7897  }//if
7898  ndbrequire(regTcPtr->transactionState == TcConnectionrec::LOG_COMMIT_WRITTEN);
7899  tcConnectptr = saveTcPtr;
7900  } else if (logWriteState == TcConnectionrec::NOT_STARTED) {
7901  jam();
7902  } else if (logWriteState == TcConnectionrec::NOT_WRITTEN) {
7903  jam();
7904 /*---------------------------------------------------------------------------*/
7905 /* IT IS A READ OPERATION OR OTHER OPERATION THAT DO NOT USE THE LOG. */
7906 /*---------------------------------------------------------------------------*/
7907 /*---------------------------------------------------------------------------*/
7908 /* THE LOG HAS NOT BEEN WRITTEN SINCE THE LOG FLAG WAS FALSE. THIS CAN OCCUR */
7909 /* WHEN WE ARE STARTING A NEW FRAGMENT. */
7910 /*---------------------------------------------------------------------------*/
7911  regTcPtr->logWriteState = TcConnectionrec::NOT_STARTED;
7912  } else {
7913  ndbrequire(logWriteState == TcConnectionrec::NOT_WRITTEN_WAIT);
7914  jam();
7915 /*---------------------------------------------------------------------------*/
7916 /* THE STATE WAS SET TO NOT_WRITTEN BY THE OPERATION BUT LATER A SCAN OF ALL */
7917 /* OPERATION RECORD CHANGED IT INTO NOT_WRITTEN_WAIT. THIS INDICATES THAT WE */
7918 /* ARE WAITING FOR THIS OPERATION TO COMMIT OR ABORT SO THAT WE CAN FIND THE */
7919 /* STARTING GLOBAL CHECKPOINT OF THIS NEW FRAGMENT. */
7920 /*---------------------------------------------------------------------------*/
7921  checkScanTcCompleted(signal);
7922  }//if
7923  } else if (transState == TcConnectionrec::LOG_COMMIT_QUEUED_WAIT_SIGNAL) {
7924  jam();
7925  regTcPtr->transactionState = TcConnectionrec::LOG_COMMIT_QUEUED;
7926  return;
7927  } else if (transState == TcConnectionrec::LOG_COMMIT_WRITTEN_WAIT_SIGNAL) {
7928  jam();
7929  } else {
7930  warningReport(signal, 0);
7931  return;
7932  }//if
7933  if (regTcPtr->seqNoReplica == 0 ||
7934  regTcPtr->activeCreat == Fragrecord::AC_NR_COPY) {
7935  jam();
7936  localCommitLab(signal);
7937  return;
7938  }//if
7939  commitReplyLab(signal);
7940  return;
7941 }//Dblqh::commitReqLab()
7942 
7943 void Dblqh::execLQH_WRITELOG_REQ(Signal* signal)
7944 {
7945  jamEntry();
7946  tcConnectptr.i = signal->theData[0];
7947  ptrCheckGuard(tcConnectptr, ctcConnectrecFileSize, tcConnectionrec);
7948  TcConnectionrec * const regTcPtr = tcConnectptr.p;
7949  Uint32 gci_hi = signal->theData[1];
7950  Uint32 gci_lo = signal->theData[2];
7951  Uint32 newestGci = cnewestGci;
7952  TcConnectionrec::LogWriteState logWriteState = regTcPtr->logWriteState;
7953  TcConnectionrec::TransactionState transState = regTcPtr->transactionState;
7954  regTcPtr->gci_hi = gci_hi;
7955  regTcPtr->gci_lo = gci_lo;
7956  if (gci_hi > newestGci) {
7957  jam();
7958 /* ------------------------------------------------------------------------- */
7959 /* KEEP TRACK OF NEWEST GLOBAL CHECKPOINT THAT LQH HAS HEARD OF. */
7960 /* ------------------------------------------------------------------------- */
7961  cnewestGci = gci_hi;
7962  }//if
7963  if (logWriteState == TcConnectionrec::WRITTEN) {
7964 /*---------------------------------------------------------------------------*/
7965 /* I NEED TO INSERT A COMMIT LOG RECORD SINCE WE ARE WRITING LOG IN THIS */
7966 /* TRANSACTION. */
7967 /*---------------------------------------------------------------------------*/
7968  jam();
7969  LogPartRecordPtr regLogPartPtr;
7970  Uint32 noOfLogPages = cnoOfLogPages;
7971  jam();
7972  regLogPartPtr.i = regTcPtr->m_log_part_ptr_i;
7973  ptrCheckGuard(regLogPartPtr, clogPartFileSize, logPartRecord);
7974  if (!regLogPartPtr.p->m_log_complete_queue.isEmpty() ||
7975  (noOfLogPages == 0))
7976  {
7977  jam();
7978 /*---------------------------------------------------------------------------*/
7979 /* THIS LOG PART WAS CURRENTLY ACTIVE WRITING ANOTHER LOG RECORD. WE MUST */
7980 /* WAIT UNTIL THIS PART HAS COMPLETED ITS OPERATION. */
7981 /*---------------------------------------------------------------------------*/
7982 // We must delay the write of commit info to the log to safe-guard against
7983 // a crash due to lack of log pages. We temporary stop all log writes to this
7984 // log part to ensure that we don't get a buffer explosion in the delayed
7985 // signal buffer instead.
7986 /*---------------------------------------------------------------------------*/
7987  linkWaitLog(signal, regLogPartPtr, regLogPartPtr.p->m_log_complete_queue);
7988  if (transState == TcConnectionrec::PREPARED) {
7989  jam();
7990  regTcPtr->transactionState = TcConnectionrec::LOG_COMMIT_QUEUED_WAIT_SIGNAL;
7991  } else {
7992  jam();
7993  ndbrequire(transState == TcConnectionrec::PREPARED_RECEIVED_COMMIT);
7994  regTcPtr->transactionState = TcConnectionrec::LOG_COMMIT_QUEUED;
7995  }//if
7996  return;
7997  }//if
7998  writeCommitLog(signal, regLogPartPtr);
7999  if (transState == TcConnectionrec::PREPARED) {
8000  jam();
8001  regTcPtr->transactionState = TcConnectionrec::LOG_COMMIT_WRITTEN_WAIT_SIGNAL;
8002  } else {
8003  jam();
8004  ndbrequire(transState == TcConnectionrec::PREPARED_RECEIVED_COMMIT);
8005  regTcPtr->transactionState = TcConnectionrec::LOG_COMMIT_WRITTEN;
8006  }//if
8007  }//if
8008 }//Dblqh::execLQH_WRITELOG_REQ()
8009 
8010 void Dblqh::localCommitLab(Signal* signal)
8011 {
8012  FragrecordPtr regFragptr;
8013  regFragptr.i = tcConnectptr.p->fragmentptr;
8014  c_fragment_pool.getPtr(regFragptr);
8015  Fragrecord::FragStatus status = regFragptr.p->fragStatus;
8016  fragptr = regFragptr;
8017  switch (status) {
8018  case Fragrecord::FSACTIVE:
8021  jam();
8022  commitContinueAfterBlockedLab(signal);
8023  return;
8024  break;
8025  case Fragrecord::BLOCKED:
8026  jam();
8027  linkFragQueue(signal);
8028  tcConnectptr.p->transactionState = TcConnectionrec::COMMIT_STOPPED;
8029  break;
8030  case Fragrecord::FREE:
8031  jam();
8032  case Fragrecord::DEFINED:
8033  jam();
8034  case Fragrecord::REMOVING:
8035  jam();
8036  default:
8037  ndbrequire(false);
8038  break;
8039  }//switch
8040 }//Dblqh::localCommitLab()
8041 
8042 void Dblqh::commitContinueAfterBlockedLab(Signal* signal)
8043 {
8044 /* ------------------------------------------------------------------------- */
8045 /*INPUT: TC_CONNECTPTR ACTIVE OPERATION RECORD */
8046 /* ------------------------------------------------------------------------- */
8047 /* ------------------------------------------------------------------------- */
8048 /*CONTINUE HERE AFTER BEING BLOCKED FOR A WHILE DURING LOCAL CHECKPOINT. */
8049 /*The operation is already removed from the active list since there is no */
8050 /*chance for any real-time breaks before we need to release it. */
8051 /* ------------------------------------------------------------------------- */
8052 /*ALSO AFTER NORMAL PROCEDURE WE CONTINUE */
8053 /*WE MUST COMMIT TUP BEFORE ACC TO ENSURE THAT NO ONE RACES IN AND SEES A */
8054 /*DIRTY STATE IN TUP. */
8055 /* ------------------------------------------------------------------------- */
8056  Ptr<TcConnectionrec> regTcPtr = tcConnectptr;
8057  Ptr<Fragrecord> regFragptr = fragptr;
8058  Uint32 operation = regTcPtr.p->operation;
8059  Uint32 dirtyOp = regTcPtr.p->dirtyOp;
8060  Uint32 opSimple = regTcPtr.p->opSimple;
8061  Uint32 normalProtocol = LqhKeyReq::getNormalProtocolFlag(regTcPtr.p->reqinfo);
8062 
8063  if (regTcPtr.p->activeCreat != Fragrecord::AC_IGNORED) {
8064  if (operation != ZREAD) {
8065  TupCommitReq * const tupCommitReq =
8066  (TupCommitReq *)signal->getDataPtrSend();
8067  Uint32 sig0 = regTcPtr.p->tupConnectrec;
8068  Uint32 tup = refToMain(regTcPtr.p->tcTupBlockref);
8069  jam();
8070  tupCommitReq->opPtr = sig0;
8071  tupCommitReq->gci_hi = regTcPtr.p->gci_hi;
8072  tupCommitReq->hashValue = regTcPtr.p->hashValue;
8073  tupCommitReq->diskpage = RNIL;
8074  tupCommitReq->gci_lo = regTcPtr.p->gci_lo;
8075  tupCommitReq->transId1 = regTcPtr.p->transid[0];
8076  tupCommitReq->transId2 = regTcPtr.p->transid[1];
8077  EXECUTE_DIRECT(tup, GSN_TUP_COMMITREQ, signal,
8078  TupCommitReq::SignalLength);
8079 
8080  if (TRACENR_FLAG)
8081  {
8082  TRACENR("COMMIT: ");
8083  switch (regTcPtr.p->operation) {
8084  case ZREAD: TRACENR("READ"); break;
8085  case ZUPDATE: TRACENR("UPDATE"); break;
8086  case ZWRITE: TRACENR("WRITE"); break;
8087  case ZINSERT: TRACENR("INSERT"); break;
8088  case ZDELETE: TRACENR("DELETE"); break;
8089  case ZUNLOCK: TRACENR("UNLOCK"); break;
8090  }
8091 
8092  TRACENR(" tab: " << regTcPtr.p->tableref
8093  << " frag: " << regTcPtr.p->fragmentid
8094  << " activeCreat: " << (Uint32)regTcPtr.p->activeCreat);
8095  if (LqhKeyReq::getNrCopyFlag(regTcPtr.p->reqinfo))
8096  TRACENR(" NrCopy");
8097  if (LqhKeyReq::getRowidFlag(regTcPtr.p->reqinfo))
8098  TRACENR(" rowid: " << regTcPtr.p->m_row_id);
8099  TRACENR(" key: " << getKeyInfoWordOrZero(regTcPtr.p, 0));
8100 
8101  if (signal->theData[0] != 0)
8102  TRACENR(" TIMESLICE");
8103  TRACENR(endl);
8104  }
8105 
8106  if(signal->theData[0] != 0)
8107  {
8108  regTcPtr.p->transactionState = TcConnectionrec::WAIT_TUP_COMMIT;
8109  return; // TUP_COMMIT was timesliced
8110  }
8111 
8112  TRACE_OP(regTcPtr.p, "ACC_COMMITREQ");
8113 
8114  Uint32 acc = refToMain(regTcPtr.p->tcAccBlockref);
8115  signal->theData[0] = regTcPtr.p->accConnectrec;
8116  EXECUTE_DIRECT(acc, GSN_ACC_COMMITREQ, signal, 1);
8117 
8118  } else {
8119  if(!dirtyOp){
8120  TRACE_OP(regTcPtr.p, "ACC_COMMITREQ");
8121 
8122  Uint32 acc = refToMain(regTcPtr.p->tcAccBlockref);
8123  signal->theData[0] = regTcPtr.p->accConnectrec;
8124  EXECUTE_DIRECT(acc, GSN_ACC_COMMITREQ, signal, 1);
8125  }
8126 
8127  if (dirtyOp && normalProtocol == 0)
8128  {
8129  jam();
8133  fragptr = regFragptr;
8134  tcConnectptr = regTcPtr;
8135  cleanUp(signal);
8136  return;
8137  }
8138 
8143  if (opSimple)
8144  {
8145  fragptr = regFragptr;
8146  tcConnectptr = regTcPtr;
8147  packLqhkeyreqLab(signal);
8148  return;
8149  }
8150  }
8151  }//if
8152  jamEntry();
8153  fragptr = regFragptr;
8154  tcConnectptr = regTcPtr;
8155  tupcommit_conf(signal, regTcPtr.p, regFragptr.p);
8156 }
8157 
8158 void
8159 Dblqh::tupcommit_conf_callback(Signal* signal, Uint32 tcPtrI)
8160 {
8161  jamEntry();
8162 
8163  tcConnectptr.i = tcPtrI;
8164  ptrCheckGuard(tcConnectptr, ctcConnectrecFileSize, tcConnectionrec);
8165  TcConnectionrec * tcPtr = tcConnectptr.p;
8166 
8167  ndbrequire(tcPtr->transactionState == TcConnectionrec::WAIT_TUP_COMMIT);
8168 
8169  FragrecordPtr regFragptr;
8170  regFragptr.i = tcPtr->fragmentptr;
8171  c_fragment_pool.getPtr(regFragptr);
8172  fragptr = regFragptr;
8173 
8174  TRACE_OP(tcPtr, "ACC_COMMITREQ");
8175 
8176  Uint32 acc = refToMain(tcPtr->tcAccBlockref);
8177  signal->theData[0] = tcPtr->accConnectrec;
8178  EXECUTE_DIRECT(acc, GSN_ACC_COMMITREQ, signal, 1);
8179  jamEntry();
8180 
8181  tcConnectptr.i = tcPtrI;
8182  tcConnectptr.p = tcPtr;
8183  tupcommit_conf(signal, tcPtr, regFragptr.p);
8184 }
8185 
8186 void
8187 Dblqh::tupcommit_conf(Signal* signal,
8188  TcConnectionrec * tcPtrP,
8189  Fragrecord * regFragptr)
8190 {
8191  Uint32 dirtyOp = tcPtrP->dirtyOp;
8192  Uint32 seqNoReplica = tcPtrP->seqNoReplica;
8193  Uint32 activeCreat = tcPtrP->activeCreat;
8194  if (tcPtrP->gci_hi > regFragptr->newestGci) {
8195  jam();
8196 /* ------------------------------------------------------------------------- */
8197 /*IT IS THE FIRST TIME THIS GLOBAL CHECKPOINT IS INVOLVED IN UPDATING THIS */
8198 /*FRAGMENT. UPDATE THE VARIABLE THAT KEEPS TRACK OF NEWEST GCI IN FRAGMENT */
8199 /* ------------------------------------------------------------------------- */
8200  regFragptr->newestGci = tcPtrP->gci_hi;
8201  }//if
8202  if (dirtyOp != ZTRUE)
8203  {
8204  if (seqNoReplica == 0 || activeCreat == Fragrecord::AC_NR_COPY)
8205  {
8206  jam();
8207  commitReplyLab(signal);
8208  return;
8209  }//if
8210  if (seqNoReplica == 0)
8211  {
8212  jam();
8213  completeTransLastLab(signal);
8214  }
8215  else
8216  {
8217  jam();
8218  completeTransNotLastLab(signal);
8219  }
8220  return;
8221  } else {
8222 /* ------------------------------------------------------------------------- */
8223 /*WE MUST HANDLE DIRTY WRITES IN A SPECIAL WAY. THESE OPERATIONS WILL NOT */
8224 /*SEND ANY COMMIT OR COMPLETE MESSAGES TO OTHER NODES. THEY WILL MERELY SEND */
8225 /*THOSE SIGNALS INTERNALLY. */
8226 /* ------------------------------------------------------------------------- */
8227  if (tcPtrP->abortState == TcConnectionrec::ABORT_IDLE)
8228  {
8229  jam();
8230  if (activeCreat == Fragrecord::AC_NR_COPY)
8231  {
8232  jam();
8233  ndbrequire(LqhKeyReq::getNrCopyFlag(tcPtrP->reqinfo));
8234  ndbrequire(tcPtrP->m_nr_delete.m_cnt == 0);
8235  }
8236  packLqhkeyreqLab(signal);
8237  }
8238  else
8239  {
8240  ndbrequire(tcPtrP->abortState != TcConnectionrec::NEW_FROM_TC);
8241  jam();
8242  sendLqhTransconf(signal, LqhTransConf::Committed);
8243  cleanUp(signal);
8244  }//if
8245  }//if
8246 }//Dblqh::commitContinueAfterBlockedLab()
8247 
8248 void Dblqh::commitReplyLab(Signal* signal)
8249 {
8250 /* -------------------------------------------------------------- */
8251 /* BACKUP AND STAND-BY REPLICAS ONLY UPDATE THE TRANSACTION STATE */
8252 /* -------------------------------------------------------------- */
8253  TcConnectionrec * const regTcPtr = tcConnectptr.p;
8254  TcConnectionrec::AbortState abortState = regTcPtr->abortState;
8255  regTcPtr->transactionState = TcConnectionrec::COMMITTED;
8256  if (abortState == TcConnectionrec::ABORT_IDLE) {
8257  Uint32 clientBlockref = regTcPtr->clientBlockref;
8258  if (regTcPtr->seqNoReplica == 0) {
8259  jam();
8260  sendCommittedTc(signal, clientBlockref);
8261  return;
8262  } else {
8263  jam();
8264  sendCommitLqh(signal, clientBlockref);
8265  return;
8266  }//if
8267  } else if (regTcPtr->abortState == TcConnectionrec::REQ_FROM_TC) {
8268  jam();
8269  signal->theData[0] = regTcPtr->reqRef;
8270  signal->theData[1] = cownNodeid;
8271  signal->theData[2] = regTcPtr->transid[0];
8272  signal->theData[3] = regTcPtr->transid[1];
8273  sendSignal(tcConnectptr.p->reqBlockref, GSN_COMMITCONF, signal, 4, JBB);
8274  } else {
8275  ndbrequire(regTcPtr->abortState == TcConnectionrec::NEW_FROM_TC);
8276  }//if
8277  return;
8278 }//Dblqh::commitReplyLab()
8279 
8280 /* ------------------------------------------------------------------------- */
8281 /* ------- COMPLETE PHASE ------- */
8282 /* */
8283 /* ------------------------------------------------------------------------- */
8284 void Dblqh::completeTransNotLastLab(Signal* signal)
8285 {
8286  TcConnectionrec * const regTcPtr = tcConnectptr.p;
8287  if (regTcPtr->abortState == TcConnectionrec::ABORT_IDLE) {
8288  Uint32 clientBlockref = regTcPtr->clientBlockref;
8289  jam();
8290  sendCompleteLqh(signal, clientBlockref);
8291  cleanUp(signal);
8292  return;
8293  } else {
8294  jam();
8295  completeUnusualLab(signal);
8296  return;
8297  }//if
8298 }//Dblqh::completeTransNotLastLab()
8299 
8300 void Dblqh::completeTransLastLab(Signal* signal)
8301 {
8302  TcConnectionrec * const regTcPtr = tcConnectptr.p;
8303  if (regTcPtr->abortState == TcConnectionrec::ABORT_IDLE) {
8304  Uint32 clientBlockref = regTcPtr->clientBlockref;
8305  jam();
8306 /* ------------------------------------------------------------------------- */
8307 /*DIRTY WRITES WHICH ARE LAST IN THE CHAIN OF REPLICAS WILL SEND COMPLETED */
8308 /*INSTEAD OF SENDING PREPARED TO THE TC (OR OTHER INITIATOR OF OPERATION). */
8309 /* ------------------------------------------------------------------------- */
8310  sendCompletedTc(signal, clientBlockref);
8311  cleanUp(signal);
8312  return;
8313  } else {
8314  jam();
8315  completeUnusualLab(signal);
8316  return;
8317  }//if
8318 }//Dblqh::completeTransLastLab()
8319 
8320 void Dblqh::completeUnusualLab(Signal* signal)
8321 {
8322  TcConnectionrec * const regTcPtr = tcConnectptr.p;
8323  if (regTcPtr->abortState == TcConnectionrec::ABORT_FROM_TC) {
8324  jam();
8325  sendAborted(signal);
8326  } else if (regTcPtr->abortState == TcConnectionrec::NEW_FROM_TC) {
8327  jam();
8328  } else {
8329  ndbrequire(regTcPtr->abortState == TcConnectionrec::REQ_FROM_TC);
8330  jam();
8331  signal->theData[0] = regTcPtr->reqRef;
8332  signal->theData[1] = cownNodeid;
8333  signal->theData[2] = regTcPtr->transid[0];
8334  signal->theData[3] = regTcPtr->transid[1];
8335  sendSignal(regTcPtr->reqBlockref,
8336  GSN_COMPLETECONF, signal, 4, JBB);
8337  }//if
8338  cleanUp(signal);
8339  return;
8340 }//Dblqh::completeUnusualLab()
8341 
8342 /* ========================================================================= */
8343 /* ======= RELEASE TC CONNECT RECORD ======= */
8344 /* */
8345 /* RELEASE A TC CONNECT RECORD TO THE FREELIST. */
8346 /* ========================================================================= */
8347 void Dblqh::releaseTcrec(Signal* signal, TcConnectionrecPtr locTcConnectptr)
8348 {
8349  jam();
8350  Uint32 op = locTcConnectptr.p->operation;
8351  locTcConnectptr.p->tcTimer = 0;
8352  locTcConnectptr.p->transactionState = TcConnectionrec::TC_NOT_CONNECTED;
8353  locTcConnectptr.p->nextTcConnectrec = cfirstfreeTcConrec;
8354  cfirstfreeTcConrec = locTcConnectptr.i;
8355 
8356  ndbassert(locTcConnectptr.p->tcScanRec == RNIL);
8357 
8358  TablerecPtr tabPtr;
8359  tabPtr.i = locTcConnectptr.p->tableref;
8360  if(tabPtr.i == RNIL)
8361  return;
8362 
8363  ptrCheckGuard(tabPtr, ctabrecFileSize, tablerec);
8364 
8368  if (op == ZREAD || op == ZUNLOCK)
8369  {
8370  ndbrequire(tabPtr.p->usageCountR > 0);
8371  tabPtr.p->usageCountR--;
8372  }
8373  else
8374  {
8375  ndbrequire(tabPtr.p->usageCountW > 0);
8376  tabPtr.p->usageCountW--;
8377  }
8378 }//Dblqh::releaseTcrec()
8379 
8380 void Dblqh::releaseTcrecLog(Signal* signal, TcConnectionrecPtr locTcConnectptr)
8381 {
8382  jam();
8383  locTcConnectptr.p->tcTimer = 0;
8384  locTcConnectptr.p->transactionState = TcConnectionrec::TC_NOT_CONNECTED;
8385  locTcConnectptr.p->nextTcConnectrec = cfirstfreeTcConrec;
8386  cfirstfreeTcConrec = locTcConnectptr.i;
8387 
8388  TablerecPtr tabPtr;
8389  tabPtr.i = locTcConnectptr.p->tableref;
8390  if(tabPtr.i == RNIL)
8391  return;
8392 
8393 }//Dblqh::releaseTcrecLog()
8394 
8395 /* ------------------------------------------------------------------------- */
8396 /* ------- ABORT PHASE ------- */
8397 /* */
8398 /*THIS PART IS USED AT ERRORS THAT CAUSE ABORT OF TRANSACTION. */
8399 /* ------------------------------------------------------------------------- */
8400 void
8401 Dblqh::remove_commit_marker(TcConnectionrec * const regTcPtr)
8402 {
8404  Uint32 commitAckMarker = regTcPtr->commitAckMarker;
8405  regTcPtr->commitAckMarker = RNIL;
8406  if (commitAckMarker == RNIL)
8407  return;
8408  jam();
8409  m_commitAckMarkerHash.getPtr(tmp, commitAckMarker);
8410 #ifdef MARKER_TRACE
8411  ndbout_c("%u remove marker[%.8x %.8x] op: %u ref: %u",
8412  instance(), tmp.p->transid1, tmp.p->transid2,
8413  Uint32(regTcPtr - tcConnectionrec), tmp.p->reference_count);
8414 #endif
8415  ndbrequire(tmp.p->reference_count > 0);
8416  tmp.p->reference_count--;
8417  if (tmp.p->reference_count == 0)
8418  {
8419  jam();
8420  m_commitAckMarkerHash.release(tmp);
8421  }
8422 }
8423 
8424 /* ***************************************************>> */
8425 /* ABORT: Abort transaction in connection. Sender TC. */
8426 /* This is the normal protocol (See COMMIT) */
8427 /* ***************************************************>> */
8428 void Dblqh::execABORT(Signal* signal)
8429 {
8430  jamEntry();
8431  Uint32 tcOprec = signal->theData[0];
8432  BlockReference tcBlockref = signal->theData[1];
8433  Uint32 transid1 = signal->theData[2];
8434  Uint32 transid2 = signal->theData[3];
8435  CRASH_INSERTION(5003);
8436  if (ERROR_INSERTED(5015)) {
8437  CLEAR_ERROR_INSERT_VALUE;
8438  sendSignalWithDelay(cownref, GSN_ABORT, signal, 2000, 4);
8439  return;
8440  }//if
8441  if (findTransaction(transid1,
8442  transid2,
8443  tcOprec, 0) != ZOK) {
8444  jam();
8445 
8446  if(ERROR_INSERTED(5039) &&
8447  refToNode(signal->getSendersBlockRef()) != getOwnNodeId()){
8448  jam();
8449  SET_ERROR_INSERT_VALUE(5040);
8450  return;
8451  }
8452 
8453  if(ERROR_INSERTED(5040) &&
8454  refToNode(signal->getSendersBlockRef()) != getOwnNodeId()){
8455  jam();
8456  SET_ERROR_INSERT_VALUE(5003);
8457  return;
8458  }
8459 
8460 /* ------------------------------------------------------------------------- */
8461 // SEND ABORTED EVEN IF NOT FOUND.
8462 //THE TRANSACTION MIGHT NEVER HAVE ARRIVED HERE.
8463 /* ------------------------------------------------------------------------- */
8464  signal->theData[0] = tcOprec;
8465  signal->theData[1] = transid1;
8466  signal->theData[2] = transid2;
8467  signal->theData[3] = cownNodeid;
8468  signal->theData[4] = ZTRUE;
8469  sendSignal(tcBlockref, GSN_ABORTED, signal, 5, JBB);
8470  warningReport(signal, 8);
8471  return;
8472  }//if
8473 
8474  TcConnectionrec * const regTcPtr = tcConnectptr.p;
8475  if (ERROR_INSERTED(5100))
8476  {
8477  SET_ERROR_INSERT_VALUE(5101);
8478  return;
8479  }
8480  CRASH_INSERTION2(5101, regTcPtr->nextReplica != ZNIL);
8481 
8482 /* ------------------------------------------------------------------------- */
8483 /*A GUIDING DESIGN PRINCIPLE IN HANDLING THESE ERROR SITUATIONS HAVE BEEN */
8484 /*KEEP IT SIMPLE. THUS WE RATHER INSERT A WAIT AND SET THE ABORT_STATE TO */
8485 /*ACTIVE RATHER THAN WRITE NEW CODE TO HANDLE EVERY SPECIAL SITUATION. */
8486 /* ------------------------------------------------------------------------- */
8487  if (regTcPtr->nextReplica != ZNIL) {
8488 /* ------------------------------------------------------------------------- */
8489 // We will immediately send the ABORT message also to the next LQH node in line.
8490 /* ------------------------------------------------------------------------- */
8491  FragrecordPtr Tfragptr;
8492  Tfragptr.i = regTcPtr->fragmentptr;
8493  c_fragment_pool.getPtr(Tfragptr);
8494  Uint32 Tnode = regTcPtr->nextReplica;
8495  Uint32 instanceKey = Tfragptr.p->lqhInstanceKey;
8496  BlockReference TLqhRef = numberToRef(DBLQH, instanceKey, Tnode);
8497  signal->theData[0] = regTcPtr->tcOprec;
8498  signal->theData[1] = regTcPtr->tcBlockref;
8499  signal->theData[2] = regTcPtr->transid[0];
8500  signal->theData[3] = regTcPtr->transid[1];
8501  sendSignal(TLqhRef, GSN_ABORT, signal, 4, JBB);
8502  }//if
8503  regTcPtr->abortState = TcConnectionrec::ABORT_FROM_TC;
8504 
8505  remove_commit_marker(regTcPtr);
8506  TRACE_OP(regTcPtr, "ABORT");
8507 
8508  abortStateHandlerLab(signal);
8509 
8510  return;
8511 }//Dblqh::execABORT()
8512 
8513 /* ************************************************************************>>
8514  * ABORTREQ: Same as ABORT but used in case one node isn't working ok.
8515  * (See COMMITREQ)
8516  * ************************************************************************>> */
8517 void Dblqh::execABORTREQ(Signal* signal)
8518 {
8519  jamEntry();
8520  Uint32 reqPtr = signal->theData[0];
8521  BlockReference reqBlockref = signal->theData[1];
8522  Uint32 transid1 = signal->theData[2];
8523  Uint32 transid2 = signal->theData[3];
8524  Uint32 tcOprec = signal->theData[5];
8525  if (ERROR_INSERTED(5006)) {
8526  systemErrorLab(signal, __LINE__);
8527  }
8528  if (ERROR_INSERTED(5016)) {
8529  CLEAR_ERROR_INSERT_VALUE;
8530  sendSignalWithDelay(cownref, GSN_ABORTREQ, signal, 2000, 6);
8531  return;
8532  }//if
8533  if (findTransaction(transid1,
8534  transid2,
8535  tcOprec, 0) != ZOK) {
8536  signal->theData[0] = reqPtr;
8537  signal->theData[2] = cownNodeid;
8538  signal->theData[3] = transid1;
8539  signal->theData[4] = transid2;
8540  sendSignal(reqBlockref, GSN_ABORTCONF, signal, 5, JBB);
8541  warningReport(signal, 9);
8542  return;
8543  }//if
8544  TcConnectionrec * const regTcPtr = tcConnectptr.p;
8545  if (regTcPtr->transactionState != TcConnectionrec::PREPARED) {
8546  warningReport(signal, 10);
8547  return;
8548  }//if
8549  regTcPtr->reqBlockref = reqBlockref;
8550  regTcPtr->reqRef = reqPtr;
8551  regTcPtr->abortState = TcConnectionrec::REQ_FROM_TC;
8552 
8553  abortCommonLab(signal);
8554  return;
8555 }//Dblqh::execABORTREQ()
8556 
8557 /* ************>> */
8558 /* ACC_TO_REF > */
8559 /* ************>> */
8560 void Dblqh::execACC_TO_REF(Signal* signal)
8561 {
8562  jamEntry();
8563  terrorCode = signal->theData[1];
8564  abortErrorLab(signal);
8565  return;
8566 }//Dblqh::execACC_TO_REF()
8567 
8568 /* ************> */
8569 /* ACCKEYREF > */
8570 /* ************> */
8571 void Dblqh::execACCKEYREF(Signal* signal)
8572 {
8573  jamEntry();
8574  tcConnectptr.i = signal->theData[0];
8575  terrorCode = signal->theData[1];
8576  ptrCheckGuard(tcConnectptr, ctcConnectrecFileSize, tcConnectionrec);
8577  TcConnectionrec * const tcPtr = tcConnectptr.p;
8578  switch (tcPtr->transactionState) {
8579  case TcConnectionrec::WAIT_ACC:
8580  jam();
8581  break;
8582  case TcConnectionrec::WAIT_ACC_ABORT:
8583  case TcConnectionrec::ABORT_STOPPED:
8584  case TcConnectionrec::ABORT_QUEUED:
8585  jam();
8586 /* ------------------------------------------------------------------------- */
8587 /*IGNORE SINCE ABORT OF THIS OPERATION IS ONGOING ALREADY. */
8588 /* ------------------------------------------------------------------------- */
8589  return;
8590  break;
8591  default:
8592  ndbrequire(false);
8593  break;
8594  }//switch
8595  const Uint32 errCode = terrorCode;
8596  tcPtr->errorCode = errCode;
8597 
8598  if (TRACENR_FLAG)
8599  {
8600  TRACENR("ACCKEYREF: " << errCode << " ");
8601  switch (tcPtr->operation) {
8602  case ZREAD: TRACENR("READ"); break;
8603  case ZUPDATE: TRACENR("UPDATE"); break;
8604  case ZWRITE: TRACENR("WRITE"); break;
8605  case ZINSERT: TRACENR("INSERT"); break;
8606  case ZDELETE: TRACENR("DELETE"); break;
8607  case ZUNLOCK: TRACENR("UNLOCK"); break;
8608  default: TRACENR("<Unknown: " << tcPtr->operation << ">"); break;
8609  }
8610 
8611  TRACENR(" tab: " << tcPtr->tableref
8612  << " frag: " << tcPtr->fragmentid
8613  << " activeCreat: " << (Uint32)tcPtr->activeCreat);
8614  if (LqhKeyReq::getNrCopyFlag(tcPtr->reqinfo))
8615  TRACENR(" NrCopy");
8616  if (LqhKeyReq::getRowidFlag(tcPtr->reqinfo))
8617  TRACENR(" rowid: " << tcPtr->m_row_id);
8618  TRACENR(" key: " << getKeyInfoWordOrZero(tcPtr, 0));
8619  TRACENR(endl);
8620 
8621  }
8622 
8623  ndbrequire(tcPtr->activeCreat == Fragrecord::AC_NORMAL);
8624  ndbrequire(!LqhKeyReq::getNrCopyFlag(tcPtr->reqinfo));
8625 
8643  tcPtr->abortState = TcConnectionrec::ABORT_FROM_LQH;
8644  abortCommonLab(signal);
8645  return;
8646 }//Dblqh::execACCKEYREF()
8647 
8648 void Dblqh::localAbortStateHandlerLab(Signal* signal)
8649 {
8650  TcConnectionrec * const regTcPtr = tcConnectptr.p;
8651  if (regTcPtr->abortState != TcConnectionrec::ABORT_IDLE) {
8652  jam();
8653  return;
8654  }//if
8655  regTcPtr->abortState = TcConnectionrec::ABORT_FROM_LQH;
8656  regTcPtr->errorCode = terrorCode;
8657  abortStateHandlerLab(signal);
8658  return;
8659 }//Dblqh::localAbortStateHandlerLab()
8660 
8661 void Dblqh::abortStateHandlerLab(Signal* signal)
8662 {
8663  TcConnectionrec * const regTcPtr = tcConnectptr.p;
8664  switch (regTcPtr->transactionState) {
8665  case TcConnectionrec::PREPARED:
8666  jam();
8667 /* ------------------------------------------------------------------------- */
8668 /*THE OPERATION IS ALREADY PREPARED AND SENT TO THE NEXT LQH OR BACK TO TC. */
8669 /*WE CAN SIMPLY CONTINUE WITH THE ABORT PROCESS. */
8670 /*IF IT WAS A CHECK FOR TRANSACTION STATUS THEN WE REPORT THE STATUS TO THE */
8671 /*NEW TC AND CONTINUE WITH THE NEXT OPERATION IN LQH. */
8672 /* ------------------------------------------------------------------------- */
8673  if (regTcPtr->abortState == TcConnectionrec::NEW_FROM_TC) {
8674  jam();
8675  sendLqhTransconf(signal, LqhTransConf::Prepared);
8676  return;
8677  }//if
8678  break;
8679  case TcConnectionrec::LOG_COMMIT_WRITTEN_WAIT_SIGNAL:
8680  case TcConnectionrec::LOG_COMMIT_QUEUED_WAIT_SIGNAL:
8681  jam();
8682 /* ------------------------------------------------------------------------- */
8683 // We can only reach these states for multi-updates on a record in a transaction.
8684 // We know that at least one of those has received the COMMIT signal, thus we
8685 // declare us only prepared since we then receive the expected COMMIT signal.
8686 /* ------------------------------------------------------------------------- */
8687  ndbrequire(regTcPtr->abortState == TcConnectionrec::NEW_FROM_TC);
8688  sendLqhTransconf(signal, LqhTransConf::Prepared);
8689  return;
8690  case TcConnectionrec::WAIT_TUPKEYINFO:
8691  case TcConnectionrec::WAIT_ATTR:
8692  jam();
8693 /* ------------------------------------------------------------------------- */
8694 /* WE ARE CURRENTLY WAITING FOR MORE INFORMATION. WE CAN START THE ABORT */
8695 /* PROCESS IMMEDIATELY. THE KEYINFO AND ATTRINFO SIGNALS WILL BE DROPPED */
8696 /* SINCE THE ABORT STATE WILL BE SET. */
8697 /* ------------------------------------------------------------------------- */
8698  break;
8699  case TcConnectionrec::WAIT_TUP:
8700  jam();
8701 /* ------------------------------------------------------------------------- */
8702 // TUP is currently active. We have to wait for the TUPKEYREF or TUPKEYCONF
8703 // to arrive since we might otherwise jeopardise the local checkpoint
8704 // consistency in overload situations.
8705 /* ------------------------------------------------------------------------- */
8706  regTcPtr->transactionState = TcConnectionrec::WAIT_TUP_TO_ABORT;
8707  return;
8708  case TcConnectionrec::WAIT_ACC:
8709  jam();
8710  abortContinueAfterBlockedLab(signal);
8711  return;
8712  break;
8713  case TcConnectionrec::LOG_QUEUED:
8714  jam();
8715 /* ------------------------------------------------------------------------- */
8716 /*CURRENTLY QUEUED FOR LOGGING. WAIT UNTIL THE LOG RECORD HAVE BEEN INSERTED */
8717 /*AND THEN CONTINUE THE ABORT PROCESS. */
8718 //Could also be waiting for an overloaded log disk. In this case it is easy
8719 //to abort when CONTINUEB arrives.
8720 /* ------------------------------------------------------------------------- */
8721  return;
8722  break;
8723  case TcConnectionrec::STOPPED:
8724  jam();
8725  /* ---------------------------------------------------------------------
8726  * WE ARE CURRENTLY QUEUED FOR ACCESS TO THE FRAGMENT BY A LCP
8727  * Since nothing has been done, just release operation
8728  * i.e. no prepare log record has been written
8729  * so no abort log records needs to be written
8730  */
8731  releaseWaitQueue(signal);
8732  continueAfterLogAbortWriteLab(signal);
8733  return;
8734  break;
8735  case TcConnectionrec::WAIT_AI_AFTER_ABORT:
8736  jam();
8737 /* ------------------------------------------------------------------------- */
8738 /* ABORT OF ACC AND TUP ALREADY COMPLETED. THIS STATE IS ONLY USED WHEN */
8739 /* CREATING A NEW FRAGMENT. */
8740 /* ------------------------------------------------------------------------- */
8741  continueAbortLab(signal);
8742  return;
8743  break;
8744  case TcConnectionrec::WAIT_TUP_TO_ABORT:
8745  case TcConnectionrec::ABORT_STOPPED:
8746  case TcConnectionrec::LOG_ABORT_QUEUED:
8747  case TcConnectionrec::WAIT_ACC_ABORT:
8748  case TcConnectionrec::ABORT_QUEUED:
8749  jam();
8750 /* ------------------------------------------------------------------------- */
8751 /*ABORT IS ALREADY ONGOING DUE TO SOME ERROR. WE HAVE ALREADY SET THE STATE */
8752 /*OF THE ABORT SO THAT WE KNOW THAT TC EXPECTS A REPORT. WE CAN THUS SIMPLY */
8753 /*EXIT. */
8754 /* ------------------------------------------------------------------------- */
8755  return;
8756  break;
8757  case TcConnectionrec::WAIT_TUP_COMMIT:
8758  case TcConnectionrec::COMMIT_STOPPED:
8759  case TcConnectionrec::LOG_COMMIT_QUEUED:
8760  case TcConnectionrec::COMMIT_QUEUED:
8761  jam();
8762 /* ------------------------------------------------------------------------- */
8763 /*THIS IS ONLY AN ALLOWED STATE IF A DIRTY WRITE OR SIMPLE READ IS PERFORMED.*/
8764 /*IF WE ARE MERELY CHECKING THE TRANSACTION STATE IT IS ALSO AN ALLOWED STATE*/
8765 /* ------------------------------------------------------------------------- */
8766  if (regTcPtr->dirtyOp == ZTRUE) {
8767  jam();
8768 /* ------------------------------------------------------------------------- */
8769 /*COMPLETE THE DIRTY WRITE AND THEN REPORT COMPLETED BACK TO TC. SINCE IT IS */
8770 /*A DIRTY WRITE IT IS ALLOWED TO COMMIT EVEN IF THE TRANSACTION ABORTS. */
8771 /* ------------------------------------------------------------------------- */
8772  return;
8773  }//if
8774  if (regTcPtr->opSimple) {
8775  jam();
8776 /* ------------------------------------------------------------------------- */
8777 /*A SIMPLE READ IS CURRENTLY RELEASING THE LOCKS OR WAITING FOR ACCESS TO */
8778 /*ACC TO CLEAR THE LOCKS. COMPLETE THIS PROCESS AND THEN RETURN AS NORMAL. */
8779 /*NO DATA HAS CHANGED DUE TO THIS SIMPLE READ ANYWAY. */
8780 /* ------------------------------------------------------------------------- */
8781  return;
8782  }//if
8783  ndbrequire(regTcPtr->abortState == TcConnectionrec::NEW_FROM_TC);
8784  jam();
8785 /* ------------------------------------------------------------------------- */
8786 /*WE ARE ONLY CHECKING THE STATUS OF THE TRANSACTION. IT IS COMMITTING. */
8787 /*COMPLETE THE COMMIT LOCALLY AND THEN SEND REPORT OF COMMITTED TO THE NEW TC*/
8788 /* ------------------------------------------------------------------------- */
8789  sendLqhTransconf(signal, LqhTransConf::Committed);
8790  return;
8791  break;
8792  case TcConnectionrec::COMMITTED:
8793  jam();
8794  ndbrequire(regTcPtr->abortState == TcConnectionrec::NEW_FROM_TC);
8795 /* ------------------------------------------------------------------------- */
8796 /*WE ARE CHECKING TRANSACTION STATUS. REPORT COMMITTED AND CONTINUE WITH THE */
8797 /*NEXT OPERATION. */
8798 /* ------------------------------------------------------------------------- */
8799  sendLqhTransconf(signal, LqhTransConf::Committed);
8800  return;
8801  break;
8802  default:
8803  ndbrequire(false);
8804 /* ------------------------------------------------------------------------- */
8805 /*THE STATE WAS NOT AN ALLOWED STATE ON A NORMAL OPERATION. SCANS AND COPY */
8806 /*FRAGMENT OPERATIONS SHOULD HAVE EXECUTED IN ANOTHER PATH. */
8807 /* ------------------------------------------------------------------------- */
8808  break;
8809  }//switch
8810  abortCommonLab(signal);
8811  return;
8812 }//Dblqh::abortStateHandlerLab()
8813 
8814 void Dblqh::abortErrorLab(Signal* signal)
8815 {
8816  ptrCheckGuard(tcConnectptr, ctcConnectrecFileSize, tcConnectionrec);
8817  TcConnectionrec * const regTcPtr = tcConnectptr.p;
8818  if (regTcPtr->abortState == TcConnectionrec::ABORT_IDLE) {
8819  jam();
8820  regTcPtr->abortState = TcConnectionrec::ABORT_FROM_LQH;
8821  regTcPtr->errorCode = terrorCode;
8822  }//if
8823  abortCommonLab(signal);
8824  return;
8825 }//Dblqh::abortErrorLab()
8826 
8827 void Dblqh::abortCommonLab(Signal* signal)
8828 {
8829  TcConnectionrec * const regTcPtr = tcConnectptr.p;
8830  const Uint32 activeCreat = regTcPtr->activeCreat;
8831 
8832  remove_commit_marker(regTcPtr);
8833 
8834  if (unlikely(activeCreat == Fragrecord::AC_NR_COPY))
8835  {
8836  jam();
8837  if (regTcPtr->m_nr_delete.m_cnt)
8838  {
8839  jam();
8844 #ifdef VM_TRACE
8845 
8848  TablerecPtr tablePtr;
8849  tablePtr.i = regTcPtr->tableref;
8850  ptrCheckGuard(tablePtr, ctabrecFileSize, tablerec);
8851  ndbrequire(tablePtr.p->m_disk_table);
8852 #endif
8853  return;
8854  }
8855  }
8856 
8857  fragptr.i = regTcPtr->fragmentptr;
8858  if (fragptr.i != RNIL) {
8859  jam();
8860  c_fragment_pool.getPtr(fragptr);
8861  switch (fragptr.p->fragStatus) {
8862  case Fragrecord::FSACTIVE:
8865  jam();
8866  abortContinueAfterBlockedLab(signal);
8867  return;
8868  break;
8869  case Fragrecord::BLOCKED:
8870  jam();
8871  linkFragQueue(signal);
8872  regTcPtr->transactionState = TcConnectionrec::ABORT_STOPPED;
8873  return;
8874  break;
8875  case Fragrecord::FREE:
8876  jam();
8877  case Fragrecord::DEFINED:
8878  jam();
8879  case Fragrecord::REMOVING:
8880  jam();
8881  default:
8882  ndbrequire(false);
8883  break;
8884  }//switch
8885  } else {
8886  jam();
8887  continueAbortLab(signal);
8888  }//if
8889 }//Dblqh::abortCommonLab()
8890 
8891 void Dblqh::abortContinueAfterBlockedLab(Signal* signal)
8892 {
8893  /* ------------------------------------------------------------------------
8894  * INPUT: TC_CONNECTPTR ACTIVE OPERATION RECORD
8895  * ------------------------------------------------------------------------
8896  * ------------------------------------------------------------------------
8897  * CAN COME HERE AS RESTART AFTER BEING BLOCKED BY A LOCAL CHECKPOINT.
8898  * ------------------------------------------------------------------------
8899  * ALSO AS PART OF A NORMAL ABORT WITHOUT BLOCKING.
8900  * WE MUST ABORT TUP BEFORE ACC TO ENSURE THAT NO ONE RACES IN
8901  * AND SEES A STATE IN TUP.
8902  * ----------------------------------------------------------------------- */
8903  TcConnectionrec * const regTcPtr = tcConnectptr.p;
8904 
8905  TRACE_OP(regTcPtr, "ACC ABORT");
8906  Uint32 canBlock = 2; // 2, block if needed
8907  switch(regTcPtr->transactionState){
8908  case TcConnectionrec::WAIT_TUP:
8909  jam();
8915  canBlock = 0;
8916  break;
8917  default:
8918  break;
8919  }
8920 
8921  regTcPtr->transactionState = TcConnectionrec::WAIT_ACC_ABORT;
8922  signal->theData[0] = regTcPtr->accConnectrec;
8923  signal->theData[1] = canBlock;
8924  EXECUTE_DIRECT(DBACC, GSN_ACC_ABORTREQ, signal, 2);
8925 
8926  if (signal->theData[1] == RNIL)
8927  {
8928  jam();
8929  /* ------------------------------------------------------------------------
8930  * We need to insert a real-time break by sending ACC_ABORTCONF through the
8931  * job buffer to ensure that we catch any ACCKEYCONF or TUPKEYCONF or
8932  * TUPKEYREF that are in the job buffer but not yet processed. Doing
8933  * everything without that would race and create a state error when they
8934  * are executed.
8935  * --------------------------------------------------------------------- */
8936  return;
8937  }
8938 
8939  execACC_ABORTCONF(signal);
8940  return;
8941 }//Dblqh::abortContinueAfterBlockedLab()
8942 
8943 /* ******************>> */
8944 /* ACC_ABORTCONF > */
8945 /* ******************>> */
8946 void Dblqh::execACC_ABORTCONF(Signal* signal)
8947 {
8948  jamEntry();
8949  tcConnectptr.i = signal->theData[0];
8950  ptrCheckGuard(tcConnectptr, ctcConnectrecFileSize, tcConnectionrec);
8951  TcConnectionrec * const regTcPtr = tcConnectptr.p;
8952  ndbrequire(regTcPtr->transactionState == TcConnectionrec::WAIT_ACC_ABORT);
8953 
8954  TRACE_OP(regTcPtr, "ACC_ABORTCONF");
8955  signal->theData[0] = regTcPtr->tupConnectrec;
8956  EXECUTE_DIRECT(DBTUP, GSN_TUP_ABORTREQ, signal, 1);
8957 
8958  jamEntry();
8959  continueAbortLab(signal);
8960  return;
8961 }//Dblqh::execACC_ABORTCONF()
8962 
8963 void Dblqh::continueAbortLab(Signal* signal)
8964 {
8965  TcConnectionrec * const regTcPtr = tcConnectptr.p;
8966  /* ------------------------------------------------------------------------
8967  * AN ERROR OCCURED IN THE ACTIVE CREATION AFTER THE ABORT PHASE.
8968  * WE NEED TO CONTINUE WITH A NORMAL ABORT.
8969  * ------------------------------------------------------------------------
8970  * ALSO USED FOR NORMAL CLEAN UP AFTER A NORMAL ABORT.
8971  * ------------------------------------------------------------------------
8972  * ALSO USED WHEN NO FRAGMENT WAS SET UP ON OPERATION.
8973  * ------------------------------------------------------------------------ */
8974  if (regTcPtr->logWriteState == TcConnectionrec::WRITTEN) {
8975  jam();
8976  /* ----------------------------------------------------------------------
8977  * I NEED TO INSERT A ABORT LOG RECORD SINCE WE ARE WRITING LOG IN THIS
8978  * TRANSACTION.
8979  * ---------------------------------------------------------------------- */
8980  initLogPointers(signal);
8981  if (cnoOfLogPages == 0 ||
8982  !logPartPtr.p->m_log_complete_queue.isEmpty())
8983  {
8984  jam();
8985  /* --------------------------------------------------------------------
8986  * A PREPARE OPERATION IS CURRENTLY WRITING IN THE LOG.
8987  * WE MUST WAIT ON OUR TURN TO WRITE THE LOG.
8988  * IT IS NECESSARY TO WRITE ONE LOG RECORD COMPLETELY
8989  * AT A TIME OTHERWISE WE WILL SCRAMBLE THE LOG.
8990  * -------------------------------------------------------------------- */
8991  linkWaitLog(signal, logPartPtr, logPartPtr.p->m_log_complete_queue);
8992  regTcPtr->transactionState = TcConnectionrec::LOG_ABORT_QUEUED;
8993  return;
8994  }//if
8995  writeAbortLog(signal);
8996  removeLogTcrec(signal);
8997  } else if (regTcPtr->logWriteState == TcConnectionrec::NOT_STARTED) {
8998  jam();
8999  } else if (regTcPtr->logWriteState == TcConnectionrec::NOT_WRITTEN) {
9000  jam();
9001  /* ------------------------------------------------------------------
9002  * IT IS A READ OPERATION OR OTHER OPERATION THAT DO NOT USE THE LOG.
9003  * ------------------------------------------------------------------ */
9004  /* ------------------------------------------------------------------
9005  * THE LOG HAS NOT BEEN WRITTEN SINCE THE LOG FLAG WAS FALSE.
9006  * THIS CAN OCCUR WHEN WE ARE STARTING A NEW FRAGMENT.
9007  * ------------------------------------------------------------------ */
9008  regTcPtr->logWriteState = TcConnectionrec::NOT_STARTED;
9009  } else {
9010  ndbrequire(regTcPtr->logWriteState == TcConnectionrec::NOT_WRITTEN_WAIT);
9011  jam();
9012  /* ----------------------------------------------------------------
9013  * THE STATE WAS SET TO NOT_WRITTEN BY THE OPERATION BUT LATER
9014  * A SCAN OF ALL OPERATION RECORD CHANGED IT INTO NOT_WRITTEN_WAIT.
9015  * THIS INDICATES THAT WE ARE WAITING FOR THIS OPERATION TO COMMIT
9016  * OR ABORT SO THAT WE CAN FIND THE
9017  * STARTING GLOBAL CHECKPOINT OF THIS NEW FRAGMENT.
9018  * ---------------------------------------------------------------- */
9019  checkScanTcCompleted(signal);
9020  }//if
9021  continueAfterLogAbortWriteLab(signal);
9022  return;
9023 }//Dblqh::continueAbortLab()
9024 
9025 void Dblqh::continueAfterLogAbortWriteLab(Signal* signal)
9026 {
9027  TcConnectionrec * const regTcPtr = tcConnectptr.p;
9028 
9029  remove_commit_marker(regTcPtr);
9030 
9031  if (regTcPtr->operation == ZREAD && regTcPtr->dirtyOp &&
9032  !LqhKeyReq::getNormalProtocolFlag(regTcPtr->reqinfo))
9033  {
9034  jam();
9035  TcKeyRef * const tcKeyRef = (TcKeyRef *) signal->getDataPtrSend();
9036 
9037  tcKeyRef->connectPtr = regTcPtr->applOprec;
9038  tcKeyRef->transId[0] = regTcPtr->transid[0];
9039  tcKeyRef->transId[1] = regTcPtr->transid[1];
9040  tcKeyRef->errorCode = regTcPtr->errorCode;
9041  sendTCKEYREF(signal, regTcPtr->applRef, regTcPtr->tcBlockref, 0);
9042  cleanUp(signal);
9043  return;
9044  }//if
9045  if (regTcPtr->abortState == TcConnectionrec::ABORT_FROM_LQH) {
9046  LqhKeyRef * const lqhKeyRef = (LqhKeyRef *)signal->getDataPtrSend();
9047 
9048  jam();
9049  lqhKeyRef->userRef = regTcPtr->clientConnectrec;
9050  lqhKeyRef->connectPtr = regTcPtr->tcOprec;
9051  lqhKeyRef->errorCode = regTcPtr->errorCode;
9052  lqhKeyRef->transId1 = regTcPtr->transid[0];
9053  lqhKeyRef->transId2 = regTcPtr->transid[1];
9054  sendSignal(regTcPtr->clientBlockref, GSN_LQHKEYREF, signal,
9055  LqhKeyRef::SignalLength, JBB);
9056  } else if (regTcPtr->abortState == TcConnectionrec::ABORT_FROM_TC) {
9057  jam();
9058  sendAborted(signal);
9059  } else if (regTcPtr->abortState == TcConnectionrec::NEW_FROM_TC) {
9060  jam();
9061  sendLqhTransconf(signal, LqhTransConf::Aborted);
9062  } else {
9063  ndbrequire(regTcPtr->abortState == TcConnectionrec::REQ_FROM_TC);
9064  jam();
9065  signal->theData[0] = regTcPtr->reqRef;
9066  signal->theData[1] = tcConnectptr.i;
9067  signal->theData[2] = cownNodeid;
9068  signal->theData[3] = regTcPtr->transid[0];
9069  signal->theData[4] = regTcPtr->transid[1];
9070  sendSignal(regTcPtr->reqBlockref, GSN_ABORTCONF,
9071  signal, 5, JBB);
9072  }//if
9073  cleanUp(signal);
9074 }//Dblqh::continueAfterLogAbortWriteLab()
9075 
9076 void
9077 Dblqh::sendTCKEYREF(Signal* signal, Uint32 ref, Uint32 routeRef, Uint32 cnt)
9078 {
9079  const Uint32 nodeId = refToNode(ref);
9080  const bool connectedToNode = getNodeInfo(nodeId).m_connected;
9081 
9082  if (likely(connectedToNode))
9083  {
9084  jam();
9085  sendSignal(ref, GSN_TCKEYREF, signal, TcKeyRef::SignalLength, JBB);
9086  }
9087  else
9088  {
9089  if (routeRef &&
9090  getNodeInfo(refToNode(routeRef)).m_version >= MAKE_VERSION(5,1,14))
9091  {
9092  jam();
9093  memmove(signal->theData+25, signal->theData, 4*TcKeyRef::SignalLength);
9094  RouteOrd* ord = (RouteOrd*)signal->getDataPtrSend();
9095  ord->dstRef = ref;
9096  ord->srcRef = reference();
9097  ord->gsn = GSN_TCKEYREF;
9098  ord->cnt = 0;
9099  LinearSectionPtr ptr[3];
9100  ptr[0].p = signal->theData+25;
9101  ptr[0].sz = TcKeyRef::SignalLength;
9102  sendSignal(routeRef, GSN_ROUTE_ORD, signal, RouteOrd::SignalLength, JBB,
9103  ptr, 1);
9104  }
9105  else
9106  {
9107  jam();
9108  memmove(signal->theData + 3, signal->theData, 4*TcKeyRef::SignalLength);
9109  signal->theData[0] = ZRETRY_TCKEYREF;
9110  signal->theData[1] = cnt + 1;
9111  signal->theData[2] = ref;
9112  sendSignalWithDelay(reference(), GSN_CONTINUEB, signal, 100,
9113  TcKeyRef::SignalLength + 3);
9114  }
9115  }
9116 }
9117 
9118 /* ##########################################################################
9119  * ####### MODULE TO HANDLE TC FAILURE #######
9120  *
9121  * ########################################################################## */
9122 
9123 /* ************************************************************************>>
9124  * NODE_FAILREP: Node failure report. Sender Ndbcntr. Set status of failed
9125  * node to down and reply with NF_COMPLETEREP to DIH which will report that
9126  * LQH has completed failure handling.
9127  * ************************************************************************>> */
9128 void Dblqh::execNODE_FAILREP(Signal* signal)
9129 {
9130  UintR TfoundNodes = 0;
9131  UintR TnoOfNodes;
9132  UintR Tdata[MAX_NDB_NODES];
9133  Uint32 i;
9134 
9135  NodeFailRep * const nodeFail = (NodeFailRep *)&signal->theData[0];
9136 
9137  TnoOfNodes = nodeFail->noOfNodes;
9138  UintR index = 0;
9139  for (i = 1; i < MAX_NDB_NODES; i++) {
9140  jam();
9141  if(NdbNodeBitmask::get(nodeFail->theNodes, i)){
9142  jam();
9143  Tdata[index] = i;
9144  index++;
9145  }//if
9146  }//for
9147 
9148 #ifdef ERROR_INSERT
9149  c_master_node_id = nodeFail->masterNodeId;
9150 #endif
9151 
9152  lcpPtr.i = 0;
9153  ptrAss(lcpPtr, lcpRecord);
9154 
9155  ndbrequire(index == TnoOfNodes);
9156  ndbrequire(cnoOfNodes - 1 < MAX_NDB_NODES);
9157  for (i = 0; i < TnoOfNodes; i++) {
9158  const Uint32 nodeId = Tdata[i];
9159 
9160  {
9161  HostRecordPtr Thostptr;
9162  Thostptr.i = nodeId;
9163  ptrCheckGuard(Thostptr, chostFileSize, hostRecord);
9164  Thostptr.p->nodestatus = ZNODE_DOWN;
9165  }
9166 
9167  lcpPtr.p->m_EMPTY_LCP_REQ.clear(nodeId);
9168 
9169  for (Uint32 j = 0; j < cnoOfNodes; j++) {
9170  jam();
9171  if (cnodeData[j] == nodeId){
9172  jam();
9173  cnodeStatus[j] = ZNODE_DOWN;
9174 
9175  TfoundNodes++;
9176  }//if
9177  }//for
9178 
9179  /* Perform block-level ndbd failure handling */
9180  Callback cb = { safe_cast(&Dblqh::ndbdFailBlockCleanupCallback),
9181  Tdata[i] };
9182  simBlockNodeFailure(signal, Tdata[i], cb);
9183  }//for
9184  ndbrequire(TnoOfNodes == TfoundNodes);
9185 }//Dblqh::execNODE_FAILREP()
9186 
9187 
9188 void
9189 Dblqh::ndbdFailBlockCleanupCallback(Signal* signal,
9190  Uint32 failedNodeId,
9191  Uint32 ignoredRc)
9192 {
9193  jamEntry();
9194 
9195  NFCompleteRep * const nfCompRep = (NFCompleteRep *)&signal->theData[0];
9196  nfCompRep->blockNo = DBLQH;
9197  nfCompRep->nodeId = cownNodeid;
9198  nfCompRep->failedNodeId = failedNodeId;
9199  BlockReference dihRef = !isNdbMtLqh() ? DBDIH_REF : DBLQH_REF;
9200  sendSignal(dihRef, GSN_NF_COMPLETEREP, signal,
9201  NFCompleteRep::SignalLength, JBB);
9202 }
9203 
9204 /* ************************************************************************>>
9205  * LQH_TRANSREQ: Report status of all transactions where TC was coordinated
9206  * by a crashed TC
9207  * ************************************************************************>> */
9208 /* ************************************************************************>>
9209  * THIS SIGNAL IS RECEIVED AFTER A NODE CRASH.
9210  * THE NODE HAD A TC AND COORDINATED A NUMBER OF TRANSACTIONS.
9211  * NOW THE MASTER NODE IS PICKING UP THOSE TRANSACTIONS
9212  * TO COMPLETE THEM. EITHER ABORT THEM OR COMMIT THEM.
9213  * ************************************************************************>> */
9214 void Dblqh::execLQH_TRANSREQ(Signal* signal)
9215 {
9216  jamEntry();
9217 
9218  if (!checkNodeFailSequence(signal))
9219  {
9220  jam();
9221  return;
9222  }
9223  Uint32 newTcPtr = signal->theData[0];
9224  BlockReference newTcBlockref = signal->theData[1];
9225  Uint32 oldNodeId = signal->theData[2];
9226  tcNodeFailptr.i = oldNodeId;
9227  ptrCheckGuard(tcNodeFailptr, ctcNodeFailrecFileSize, tcNodeFailRecord);
9228  if ((tcNodeFailptr.p->tcFailStatus == TcNodeFailRecord::TC_STATE_TRUE) ||
9229  (tcNodeFailptr.p->tcFailStatus == TcNodeFailRecord::TC_STATE_BREAK)) {
9230  jam();
9231  tcNodeFailptr.p->lastNewTcBlockref = newTcBlockref;
9232  /* ------------------------------------------------------------------------
9233  * WE HAVE RECEIVED A SIGNAL SPECIFYING THAT WE NEED TO HANDLE THE FAILURE
9234  * OF A TC. NOW WE RECEIVE ANOTHER SIGNAL WITH THE SAME ORDER. THIS CAN
9235  * OCCUR IF THE NEW TC FAILS. WE MUST BE CAREFUL IN THIS CASE SO THAT WE DO
9236  * NOT START PARALLEL ACTIVITIES TRYING TO DO THE SAME THING. WE SAVE THE
9237  * NEW BLOCK REFERENCE TO THE LAST NEW TC IN A VARIABLE AND ASSIGN TO IT TO
9238  * NEW_TC_BLOCKREF WHEN THE OLD PROCESS RETURNS TO LQH_TRANS_NEXT. IT IS
9239  * CERTAIN TO COME THERE SINCE THIS IS THE ONLY PATH TO TAKE CARE OF THE
9240  * NEXT TC CONNECT RECORD. WE SET THE STATUS TO BREAK TO INDICATE TO THE OLD
9241  * PROCESS WHAT IS HAPPENING.
9242  * ------------------------------------------------------------------------ */
9243  tcNodeFailptr.p->lastNewTcRef = newTcPtr;
9244  tcNodeFailptr.p->tcFailStatus = TcNodeFailRecord::TC_STATE_BREAK;
9245  return;
9246  }//if
9247  tcNodeFailptr.p->oldNodeId = oldNodeId;
9248  tcNodeFailptr.p->newTcBlockref = newTcBlockref;
9249  tcNodeFailptr.p->newTcRef = newTcPtr;
9250  tcNodeFailptr.p->tcRecNow = 0;
9251  tcNodeFailptr.p->tcFailStatus = TcNodeFailRecord::TC_STATE_TRUE;
9252  signal->theData[0] = ZLQH_TRANS_NEXT;
9253  signal->theData[1] = tcNodeFailptr.i;
9254  sendSignal(cownref, GSN_CONTINUEB, signal, 2, JBB);
9255  return;
9256 }//Dblqh::execLQH_TRANSREQ()
9257 
9258 void Dblqh::lqhTransNextLab(Signal* signal)
9259 {
9260  UintR tend;
9261  UintR tstart;
9262  UintR guard0;
9263 
9264  if (tcNodeFailptr.p->tcFailStatus == TcNodeFailRecord::TC_STATE_BREAK) {
9265  jam();
9266  /* ----------------------------------------------------------------------
9267  * AN INTERRUPTION TO THIS NODE FAIL HANDLING WAS RECEIVED AND A NEW
9268  * TC HAVE BEEN ASSIGNED TO TAKE OVER THE FAILED TC. PROBABLY THE OLD
9269  * NEW TC HAVE FAILED.
9270  * ---------------------------------------------------------------------- */
9271  tcNodeFailptr.p->newTcBlockref = tcNodeFailptr.p->lastNewTcBlockref;
9272  tcNodeFailptr.p->newTcRef = tcNodeFailptr.p->lastNewTcRef;
9273  tcNodeFailptr.p->tcRecNow = 0;
9274  tcNodeFailptr.p->tcFailStatus = TcNodeFailRecord::TC_STATE_TRUE;
9275  }//if
9276  tstart = tcNodeFailptr.p->tcRecNow;
9277  tend = tstart + 200;
9278  guard0 = tend;
9279  for (tcConnectptr.i = tstart; tcConnectptr.i <= guard0; tcConnectptr.i++) {
9280  jam();
9281  if (tcConnectptr.i >= ctcConnectrecFileSize) {
9282  jam();
9288 #ifdef ERROR_INSERT
9289  if (ERROR_INSERTED(5061))
9290  {
9291  CLEAR_ERROR_INSERT_VALUE;
9292  for (Uint32 i = 0; i < cnoOfNodes; i++)
9293  {
9294  Uint32 node = cnodeData[i];
9295  if (node != getOwnNodeId() && cnodeStatus[i] == ZNODE_UP)
9296  {
9297  ndbout_c("clearing ERROR_INSERT in LQH:%u", node);
9298  signal->theData[0] = 0;
9299  sendSignal(numberToRef(DBLQH, node), GSN_NDB_TAMPER,
9300  signal, 1, JBB);
9301  }
9302  }
9303 
9304  signal->theData[0] = ZSCAN_MARKERS;
9305  signal->theData[1] = tcNodeFailptr.i;
9306  signal->theData[2] = 0;
9307  signal->theData[3] = RNIL;
9308  sendSignalWithDelay(cownref, GSN_CONTINUEB, signal, 5000, 4);
9309  return;
9310  }
9311 
9312  if (ERROR_INSERTED(5050))
9313  {
9314  ndbout_c("send ZSCAN_MARKERS with 5s delay and killing master");
9315  CLEAR_ERROR_INSERT_VALUE;
9316  signal->theData[0] = ZSCAN_MARKERS;
9317  signal->theData[1] = tcNodeFailptr.i;
9318  signal->theData[2] = 0;
9319  signal->theData[3] = RNIL;
9320  sendSignalWithDelay(cownref, GSN_CONTINUEB, signal, 5000, 4);
9321 
9322  signal->theData[0] = 9999;
9323  sendSignal(numberToRef(CMVMI, c_master_node_id),
9324  GSN_NDB_TAMPER, signal, 1, JBB);
9325  return;
9326  }
9327 #endif
9328  scanMarkers(signal, tcNodeFailptr.i, 0, RNIL);
9329  return;
9330  }//if
9331  ptrCheckGuard(tcConnectptr, ctcConnectrecFileSize, tcConnectionrec);
9332  if (tcConnectptr.p->transactionState != TcConnectionrec::IDLE) {
9333  if (tcConnectptr.p->transactionState != TcConnectionrec::TC_NOT_CONNECTED) {
9334  if (tcConnectptr.p->tcScanRec == RNIL) {
9335  if (refToNode(tcConnectptr.p->tcBlockref) == tcNodeFailptr.p->oldNodeId) {
9336  switch( tcConnectptr.p->operation ) {
9337  case ZUNLOCK :
9338  jam(); /* Skip over */
9339  break;
9340  case ZREAD :
9341  jam();
9342  if (tcConnectptr.p->opSimple == ZTRUE) {
9343  jam();
9344  break; /* Skip over */
9345  }
9346  /* Fall through */
9347  default :
9348  jam();
9349  tcConnectptr.p->tcNodeFailrec = tcNodeFailptr.i;
9350  tcConnectptr.p->abortState = TcConnectionrec::NEW_FROM_TC;
9351  abortStateHandlerLab(signal);
9352  return;
9353  } // switch
9354  }//if
9355  } else {
9356  scanptr.i = tcConnectptr.p->tcScanRec;
9357  c_scanRecordPool.getPtr(scanptr);
9358  switch(scanptr.p->scanType){
9359  case ScanRecord::COPY:
9360  {
9361  jam();
9362  if (scanptr.p->scanNodeId == tcNodeFailptr.p->oldNodeId) {
9363  jam();
9364  /* ------------------------------------------------------------
9365  * THE RECEIVER OF THE COPY HAVE FAILED.
9366  * WE HAVE TO CLOSE THE COPY PROCESS.
9367  * ----------------------------------------------------------- */
9368  if (0) ndbout_c("close copy");
9369  tcConnectptr.p->tcNodeFailrec = tcNodeFailptr.i;
9370  tcConnectptr.p->abortState = TcConnectionrec::NEW_FROM_TC;
9371  closeCopyRequestLab(signal);
9372  return;
9373  }
9374  break;
9375  }
9376  case ScanRecord::SCAN:
9377  {
9378  jam();
9379  if (refToNode(tcConnectptr.p->tcBlockref) ==
9380  tcNodeFailptr.p->oldNodeId) {
9381  jam();
9382  tcConnectptr.p->tcNodeFailrec = tcNodeFailptr.i;
9383  tcConnectptr.p->abortState = TcConnectionrec::NEW_FROM_TC;
9384  closeScanRequestLab(signal);
9385  return;
9386  }//if
9387  break;
9388  }
9389  default:
9390  ndbout_c("scanptr.p->scanType: %u", scanptr.p->scanType);
9391  ndbout_c("tcConnectptr.p->transactionState: %u",
9392  tcConnectptr.p->transactionState);
9393  ndbrequire(false);
9394  }
9395  }
9396  }
9397  else
9398  {
9399 #if defined VM_TRACE || defined ERROR_INSERT
9400  jam();
9401  ndbrequire(tcConnectptr.p->tcScanRec == RNIL);
9402 #endif
9403  }
9404  }
9405  else
9406  {
9407 #if defined VM_TRACE || defined ERROR_INSERT
9408  jam();
9409  ndbrequire(tcConnectptr.p->tcScanRec == RNIL);
9410 #endif
9411  }
9412  }//for
9413  tcNodeFailptr.p->tcRecNow = tend + 1;
9414  signal->theData[0] = ZLQH_TRANS_NEXT;
9415  signal->theData[1] = tcNodeFailptr.i;
9416  sendSignal(cownref, GSN_CONTINUEB, signal, 2, JBB);
9417  return;
9418 }//Dblqh::lqhTransNextLab()
9419 
9420 void
9422  Uint32 tcNodeFail,
9423  Uint32 startBucket,
9424  Uint32 i){
9425 
9426  jam();
9427 
9428  TcNodeFailRecordPtr tcNodeFailPtr;
9429  tcNodeFailPtr.i = tcNodeFail;
9430  ptrCheckGuard(tcNodeFailPtr, ctcNodeFailrecFileSize, tcNodeFailRecord);
9431  const Uint32 crashedTcNodeId = tcNodeFailPtr.p->oldNodeId;
9432 
9433  if (tcNodeFailPtr.p->tcFailStatus == TcNodeFailRecord::TC_STATE_BREAK)
9434  {
9435  jam();
9436 
9437  /* ----------------------------------------------------------------------
9438  * AN INTERRUPTION TO THIS NODE FAIL HANDLING WAS RECEIVED AND A NEW
9439  * TC HAVE BEEN ASSIGNED TO TAKE OVER THE FAILED TC. PROBABLY THE OLD
9440  * NEW TC HAVE FAILED.
9441  * ---------------------------------------------------------------------- */
9442  tcNodeFailptr = tcNodeFailPtr;
9443  lqhTransNextLab(signal);
9444  return;
9445  }
9446 
9447  CommitAckMarkerIterator iter;
9448  if(i == RNIL){
9449  m_commitAckMarkerHash.next(startBucket, iter);
9450  } else {
9451  jam();
9452  iter.curr.i = i;
9453  iter.bucket = startBucket;
9454  m_commitAckMarkerHash.getPtr(iter.curr);
9455  m_commitAckMarkerHash.next(iter);
9456  }
9457 
9458  const Uint32 RT_BREAK = 256;
9459  for(i = 0; i<RT_BREAK || iter.bucket == startBucket; i++){
9460  jam();
9461 
9462  if(iter.curr.i == RNIL){
9466  jam();
9467 
9468  tcNodeFailPtr.p->tcFailStatus = TcNodeFailRecord::TC_STATE_FALSE;
9469  signal->theData[0] = tcNodeFailPtr.p->newTcRef;
9470  signal->theData[1] = cownNodeid;
9471  signal->theData[2] = LqhTransConf::LastTransConf;
9472  sendSignal(tcNodeFailPtr.p->newTcBlockref, GSN_LQH_TRANSCONF,
9473  signal, 3, JBB);
9474  return;
9475  }
9476 
9477  if(iter.curr.p->tcNodeId == crashedTcNodeId){
9478  jam();
9479 
9483  LqhTransConf * const lqhTransConf = (LqhTransConf *)&signal->theData[0];
9484  lqhTransConf->tcRef = tcNodeFailPtr.p->newTcRef;
9485  lqhTransConf->lqhNodeId = cownNodeid;
9486  lqhTransConf->operationStatus = LqhTransConf::Marker;
9487  lqhTransConf->transId1 = iter.curr.p->transid1;
9488  lqhTransConf->transId2 = iter.curr.p->transid2;
9489  lqhTransConf->apiRef = iter.curr.p->apiRef;
9490  lqhTransConf->apiOpRec = iter.curr.p->apiOprec;
9491  sendSignal(tcNodeFailPtr.p->newTcBlockref, GSN_LQH_TRANSCONF,
9492  signal, 7, JBB);
9493 
9494  signal->theData[0] = ZSCAN_MARKERS;
9495  signal->theData[1] = tcNodeFailPtr.i;
9496  signal->theData[2] = iter.bucket;
9497  signal->theData[3] = iter.curr.i;
9498  sendSignal(cownref, GSN_CONTINUEB, signal, 4, JBB);
9499  return;
9500  }
9501 
9502  m_commitAckMarkerHash.next(iter);
9503  }
9504 
9505  signal->theData[0] = ZSCAN_MARKERS;
9506  signal->theData[1] = tcNodeFailPtr.i;
9507  signal->theData[2] = iter.bucket;
9508  signal->theData[3] = RNIL;
9509  sendSignal(cownref, GSN_CONTINUEB, signal, 4, JBB);
9510 }
9511 
9512 /* #########################################################################
9513  * ####### SCAN MODULE #######
9514  *
9515  * #########################################################################
9516  * -------------------------------------------------------------------------
9517  * THIS MODULE CONTAINS THE CODE THAT HANDLES A SCAN OF A PARTICULAR FRAGMENT
9518  * IT OPERATES UNDER THE CONTROL OF TC AND ORDERS ACC TO PERFORM A SCAN OF
9519  * ALL TUPLES IN THE FRAGMENT. TUP PERFORMS THE NECESSARY SEARCH CONDITIONS
9520  * TO ENSURE THAT ONLY VALID TUPLES ARE RETURNED TO THE APPLICATION.
9521  * ------------------------------------------------------------------------- */
9522 /* *************** */
9523 /* ACC_SCANCONF > */
9524 /* *************** */
9525 void Dblqh::execACC_SCANCONF(Signal* signal)
9526 {
9527  AccScanConf * const accScanConf = (AccScanConf *)&signal->theData[0];
9528  jamEntry();
9529  scanptr.i = accScanConf->scanPtr;
9530  c_scanRecordPool.getPtr(scanptr);
9531  if (scanptr.p->scanState == ScanRecord::WAIT_ACC_SCAN) {
9532  accScanConfScanLab(signal);
9533  } else {
9534  ndbrequire(scanptr.p->scanState == ScanRecord::WAIT_ACC_COPY);
9535  accScanConfCopyLab(signal);
9536  }//if
9537 }//Dblqh::execACC_SCANCONF()
9538 
9539 /* ************>> */
9540 /* ACC_SCANREF > */
9541 /* ************>> */
9542 void Dblqh::execACC_SCANREF(Signal* signal)
9543 {
9544  jamEntry();
9545  ndbrequire(refToMain(signal->getSendersBlockRef()) == DBTUX);
9546  const AccScanRef refCopy = *(const AccScanRef*)signal->getDataPtr();
9547  const AccScanRef* ref = &refCopy;
9548  ndbrequire(ref->errorCode != 0);
9549 
9550  scanptr.i = ref->scanPtr;
9551  c_scanRecordPool.getPtr(scanptr);
9552  tcConnectptr.i = scanptr.p->scanTcrec;
9553  ptrCheckGuard(tcConnectptr, ctcConnectrecFileSize, tcConnectionrec);
9554  tcConnectptr.p->errorCode = ref->errorCode;
9555 
9556  /*
9557  * MRR scan can hit this between 2 DBTUX scans. Previous range has
9558  * terminated via last NEXT_SCANCONF, then index is set to Dropping,
9559  * and then next range is started and returns ACC_SCANREF.
9560  */
9561  if (scanptr.p->scanStoredProcId != RNIL) {
9562  jam();
9563  scanptr.p->scanCompletedStatus = ZTRUE;
9564  accScanCloseConfLab(signal);
9565  return;
9566  }
9567  tupScanCloseConfLab(signal);
9568 }//Dblqh::execACC_SCANREF()
9569 
9570 /* ***************>> */
9571 /* NEXT_SCANCONF > */
9572 /* ***************>> */
9573 void Dblqh::execNEXT_SCANCONF(Signal* signal)
9574 {
9575  NextScanConf * const nextScanConf = (NextScanConf *)&signal->theData[0];
9576  jamEntry();
9577  scanptr.i = nextScanConf->scanPtr;
9578  c_scanRecordPool.getPtr(scanptr);
9579  scanptr.p->m_row_id.m_page_no = nextScanConf->localKey[0];
9580  scanptr.p->m_row_id.m_page_idx = nextScanConf->localKey[1];
9581 
9582 #ifdef VM_TRACE
9583  if (signal->getLength() > 2 && nextScanConf->accOperationPtr != RNIL)
9584  {
9585  Ptr<TcConnectionrec> regTcPtr;
9586  regTcPtr.i = scanptr.p->scanTcrec;
9587  ptrCheckGuard(regTcPtr, ctcConnectrecFileSize, tcConnectionrec);
9588  ndbassert(regTcPtr.p->fragmentid == nextScanConf->fragId);
9589  }
9590 #endif
9591 
9592  fragptr.i = scanptr.p->fragPtrI;
9593  c_fragment_pool.getPtr(fragptr);
9594  switch (scanptr.p->scanState) {
9595  case ScanRecord::WAIT_CLOSE_SCAN:
9596  jam();
9597  accScanCloseConfLab(signal);
9598  break;
9599  case ScanRecord::WAIT_CLOSE_COPY:
9600  jam();
9601  accCopyCloseConfLab(signal);
9602  break;
9603  case ScanRecord::WAIT_NEXT_SCAN:
9604  jam();
9605  nextScanConfScanLab(signal);
9606  break;
9607  case ScanRecord::WAIT_NEXT_SCAN_COPY:
9608  jam();
9609  nextScanConfCopyLab(signal);
9610  break;
9611  case ScanRecord::WAIT_RELEASE_LOCK:
9612  jam();
9613  ndbrequire(signal->length() == 1);
9614  scanLockReleasedLab(signal);
9615  break;
9616  default:
9617  ndbout_c("%d", scanptr.p->scanState);
9618  ndbrequire(false);
9619  }//switch
9620 }//Dblqh::execNEXT_SCANCONF()
9621 
9622 /* ***************> */
9623 /* NEXT_SCANREF > */
9624 /* ***************> */
9625 void Dblqh::execNEXT_SCANREF(Signal* signal)
9626 {
9627  jamEntry();
9628  ndbrequire(refToMain(signal->getSendersBlockRef()) == DBTUX);
9629  const NextScanRef refCopy = *(const NextScanRef*)signal->getDataPtr();
9630  const NextScanRef* ref = &refCopy;
9631  ndbrequire(ref->errorCode != 0);
9632 
9633  scanptr.i = ref->scanPtr;
9634  c_scanRecordPool.getPtr(scanptr);
9635  tcConnectptr.i = scanptr.p->scanTcrec;
9636  ptrCheckGuard(tcConnectptr, ctcConnectrecFileSize, tcConnectionrec);
9637  tcConnectptr.p->errorCode = ref->errorCode;
9638 
9639  /*
9640  * MRR scan may have other ranges left. But the scan has already
9641  * failed. Terminate the scan now.
9642  */
9643  scanptr.p->scanCompletedStatus = ZTRUE;
9644  accScanCloseConfLab(signal);
9645 }//Dblqh::execNEXT_SCANREF()
9646 
9647 /* ******************> */
9648 /* STORED_PROCCONF > */
9649 /* ******************> */
9650 void Dblqh::execSTORED_PROCCONF(Signal* signal)
9651 {
9652  jamEntry();
9653  tcConnectptr.i = signal->theData[0];
9654  Uint32 storedProcId = signal->theData[1];
9655  ptrCheckGuard(tcConnectptr, ctcConnectrecFileSize, tcConnectionrec);
9656  scanptr.i = tcConnectptr.p->tcScanRec;
9657  c_scanRecordPool.getPtr(scanptr);
9658  switch (scanptr.p->scanState) {
9659  case ScanRecord::WAIT_STORED_PROC_SCAN:
9660  jam();
9661  scanptr.p->scanStoredProcId = storedProcId;
9662  storedProcConfScanLab(signal);
9663  break;
9664  case ScanRecord::WAIT_DELETE_STORED_PROC_ID_SCAN:
9665  jam();
9666  tupScanCloseConfLab(signal);
9667  break;
9668  case ScanRecord::WAIT_STORED_PROC_COPY:
9669  jam();
9670  scanptr.p->scanStoredProcId = storedProcId;
9671  storedProcConfCopyLab(signal);
9672  break;
9673  case ScanRecord::WAIT_DELETE_STORED_PROC_ID_COPY:
9674  jam();
9675  tupCopyCloseConfLab(signal);
9676  break;
9677  default:
9678  ndbrequire(false);
9679  }//switch
9680 }//Dblqh::execSTORED_PROCCONF()
9681 
9682 /* ****************** */
9683 /* STORED_PROCREF > */
9684 /* ****************** */
9685 void Dblqh::execSTORED_PROCREF(Signal* signal)
9686 {
9687  jamEntry();
9688  tcConnectptr.i = signal->theData[0];
9689  Uint32 errorCode = signal->theData[1];
9690  ptrCheckGuard(tcConnectptr, ctcConnectrecFileSize, tcConnectionrec);
9691  scanptr.i = tcConnectptr.p->tcScanRec;
9692  c_scanRecordPool.getPtr(scanptr);
9693  switch (scanptr.p->scanState) {
9694  case ScanRecord::WAIT_STORED_PROC_SCAN:
9695  jam();
9696  scanptr.p->scanCompletedStatus = ZTRUE;
9697  scanptr.p->scanStoredProcId = signal->theData[2];
9698  tcConnectptr.p->errorCode = errorCode;
9699  closeScanLab(signal);
9700  break;
9701  default:
9702  ndbrequire(false);
9703  }//switch
9704 }//Dblqh::execSTORED_PROCREF()
9705 
9706 /* --------------------------------------------------------------------------
9707  * ENTER SCAN_NEXTREQ
9708  * --------------------------------------------------------------------------
9709  * PRECONDITION:
9710  * TRANSACTION_STATE = SCAN_STATE
9711  * SCAN_STATE = WAIT_SCAN_NEXTREQ
9712  *
9713  * Case scanLockHold: ZTRUE = Unlock previous round of
9714  * scanned row(s) and fetch next set of rows.
9715  * ZFALSE = Fetch new set of rows.
9716  * Number of rows to read depends on parallelism and how many rows
9717  * left to scan in the fragment. SCAN_NEXTREQ can also be sent with
9718  * closeFlag == ZTRUE to close the scan.
9719  * ------------------------------------------------------------------------- */
9720 void Dblqh::execSCAN_NEXTREQ(Signal* signal)
9721 {
9722  jamEntry();
9723  const ScanFragNextReq * const nextReq =
9724  (ScanFragNextReq*)&signal->theData[0];
9725  const Uint32 transid1 = nextReq->transId1;
9726  const Uint32 transid2 = nextReq->transId2;
9727  const Uint32 senderData = nextReq->senderData;
9728  Uint32 hashHi = signal->getSendersBlockRef();
9729 
9730  if (findTransaction(transid1, transid2, senderData, hashHi) != ZOK){
9731  jam();
9732  DEBUG(senderData <<
9733  " Received SCAN_NEXTREQ in LQH with close flag when closed");
9734  ndbrequire(nextReq->requestInfo == ScanFragNextReq::ZCLOSE);
9735  return;
9736  }
9737 
9738  // Crash node if signal sender is same node
9739  CRASH_INSERTION2(5021, refToNode(signal->senderBlockRef()) == cownNodeid);
9740  // Crash node if signal sender is NOT same node
9741  CRASH_INSERTION2(5022, refToNode(signal->senderBlockRef()) != cownNodeid);
9742 
9743  if (ERROR_INSERTED(5023)){
9744  // Drop signal if sender is same node
9745  if (refToNode(signal->senderBlockRef()) == cownNodeid) {
9746  CLEAR_ERROR_INSERT_VALUE;
9747  return;
9748  }
9749  }//if
9750  if (ERROR_INSERTED(5024)){
9751  // Drop signal if sender is NOT same node
9752  if (refToNode(signal->senderBlockRef()) != cownNodeid) {
9753  CLEAR_ERROR_INSERT_VALUE;
9754  return;
9755  }
9756  }//if
9757  if (ERROR_INSERTED(5025))
9758  {
9764  CLEAR_ERROR_INSERT_VALUE;
9765  }
9766 
9767  if (ERROR_INSERTED(5030)){
9768  ndbout << "ERROR 5030" << endl;
9769  CLEAR_ERROR_INSERT_VALUE;
9770  // Drop signal
9771  return;
9772  }//if
9773 
9774  if(ERROR_INSERTED(5036)){
9775  return;
9776  }
9777 
9778  Uint32 pos = 0;
9779  if (ScanFragNextReq::getCorrFactorFlag(nextReq->requestInfo))
9780  {
9781  jam();
9782  Uint32 corrFactorLo = nextReq->variableData[pos++];
9783  tcConnectptr.p->m_corrFactorLo &= 0xFFFF0000;
9784  tcConnectptr.p->m_corrFactorLo |= corrFactorLo;
9785  }
9786 
9787  scanptr.i = tcConnectptr.p->tcScanRec;
9788  ndbrequire(scanptr.i != RNIL);
9789  c_scanRecordPool.getPtr(scanptr);
9790  scanptr.p->scanTcWaiting = cLqhTimeOutCount;
9791 
9792  /* ------------------------------------------------------------------
9793  * If close flag is set this scan should be closed
9794  * If we are waiting for SCAN_NEXTREQ set flag to stop scanning and
9795  * continue execution else set flags and wait until the scan
9796  * completes itself
9797  * ------------------------------------------------------------------ */
9798  if (nextReq->requestInfo == ScanFragNextReq::ZCLOSE)
9799  {
9800  jam();
9801  if(ERROR_INSERTED(5034)){
9802  CLEAR_ERROR_INSERT_VALUE;
9803  }
9804  if(ERROR_INSERTED(5036)){
9805  CLEAR_ERROR_INSERT_VALUE;
9806  return;
9807  }
9808  closeScanRequestLab(signal);
9809  return;
9810  }//if
9811 
9812  fragptr.i = tcConnectptr.p->fragmentptr;
9813  c_fragment_pool.getPtr(fragptr);
9814 
9819  const Uint32 max_rows = nextReq->batch_size_rows;
9820  const Uint32 max_bytes = nextReq->batch_size_bytes;
9821  scanptr.p->m_max_batch_size_bytes = max_bytes;
9822 
9823  if (max_rows > scanptr.p->m_max_batch_size_rows)
9824  {
9825  jam();
9829  if (!seize_acc_ptr_list(scanptr.p,
9830  scanptr.p->m_max_batch_size_rows, max_rows))
9831  {
9832  jam();
9833  tcConnectptr.p->errorCode = ScanFragRef::ZTOO_MANY_ACTIVE_SCAN_ERROR;
9834  closeScanRequestLab(signal);
9835  return;
9836  }
9837  cbookedAccOps += (max_rows - scanptr.p->m_max_batch_size_rows);
9838  scanptr.p->m_max_batch_size_rows = max_rows;
9839  }
9840  else if (unlikely(max_rows < scanptr.p->m_max_batch_size_rows))
9841  {
9842  jam();
9843  cbookedAccOps -= (scanptr.p->m_max_batch_size_rows - max_rows);
9844  scanptr.p->m_max_batch_size_rows = max_rows;
9845  }
9846 
9847  /* --------------------------------------------------------------------
9848  * If scanLockHold = TRUE we need to unlock previous round of
9849  * scanned records.
9850  * scanReleaseLocks will set states for this and send a NEXT_SCANREQ.
9851  * When confirm signal NEXT_SCANCONF arrives we call
9852  * continueScanNextReqLab to continue scanning new rows and
9853  * acquiring new locks.
9854  * -------------------------------------------------------------------- */
9855  if ((scanptr.p->scanLockHold == ZTRUE) &&
9856  (scanptr.p->m_curr_batch_size_rows > 0)) {
9857  jam();
9858  scanptr.p->scanReleaseCounter = 1;
9859  scanReleaseLocksLab(signal);
9860  return;
9861  }//if
9862 
9863  /* -----------------------------------------------------------------------
9864  * We end up here when scanLockHold = FALSE or no rows was locked from
9865  * previous round.
9866  * Simply continue scanning.
9867  * ----------------------------------------------------------------------- */
9868  continueScanNextReqLab(signal);
9869 }//Dblqh::execSCAN_NEXTREQ()
9870 
9871 void Dblqh::continueScanNextReqLab(Signal* signal)
9872 {
9873  if (scanptr.p->scanCompletedStatus == ZTRUE) {
9874  jam();
9875  closeScanLab(signal);
9876  return;
9877  }//if
9878 
9879  if(scanptr.p->m_last_row){
9880  jam();
9881  scanptr.p->scanCompletedStatus = ZTRUE;
9882  scanptr.p->scanState = ScanRecord::WAIT_SCAN_NEXTREQ;
9883  sendScanFragConf(signal, ZFALSE);
9884  return;
9885  }
9886 
9887  // Update timer on tcConnectRecord
9888  tcConnectptr.p->tcTimer = cLqhTimeOutCount;
9889  init_acc_ptr_list(scanptr.p);
9890  scanptr.p->scanFlag = NextScanReq::ZSCAN_NEXT;
9891  scanNextLoopLab(signal);
9892 }//Dblqh::continueScanNextReqLab()
9893 
9894 /* -------------------------------------------------------------------------
9895  * WE NEED TO RELEASE LOCKS BEFORE CONTINUING
9896  * ------------------------------------------------------------------------- */
9897 void Dblqh::scanReleaseLocksLab(Signal* signal)
9898 {
9899  switch (fragptr.p->fragStatus) {
9900  case Fragrecord::FSACTIVE:
9901  jam();
9902  break;
9903  case Fragrecord::BLOCKED:
9904  jam();
9905  linkFragQueue(signal);
9906  tcConnectptr.p->transactionState = TcConnectionrec::SCAN_RELEASE_STOPPED;
9907  return;
9908  break;
9909  case Fragrecord::FREE:
9910  jam();
9912  jam();
9914  jam();
9915  case Fragrecord::DEFINED:
9916  jam();
9917  case Fragrecord::REMOVING:
9918  jam();
9919  default:
9920  ndbrequire(false);
9921  }//switch
9922  continueScanReleaseAfterBlockedLab(signal);
9923 }//Dblqh::scanReleaseLocksLab()
9924 
9925 void Dblqh::continueScanReleaseAfterBlockedLab(Signal* signal)
9926 {
9927  scanptr.i = tcConnectptr.p->tcScanRec;
9928  c_scanRecordPool.getPtr(scanptr);
9929  scanptr.p->scanState = ScanRecord::WAIT_RELEASE_LOCK;
9930  signal->theData[0] = scanptr.p->scanAccPtr;
9931  signal->theData[1]=
9932  get_acc_ptr_from_scan_record(scanptr.p,
9933  scanptr.p->scanReleaseCounter -1,
9934  false);
9935  signal->theData[2] = NextScanReq::ZSCAN_COMMIT;
9936  sendSignal(scanptr.p->scanBlockref, GSN_NEXT_SCANREQ, signal, 3, JBB);
9937 }//Dblqh::continueScanReleaseAfterBlockedLab()
9938 
9939 /* -------------------------------------------------------------------------
9940  * ENTER SCAN_NEXTREQ
9941  * -------------------------------------------------------------------------
9942  * SCAN_NEXT_REQ SIGNAL ARRIVED IN THE MIDDLE OF EXECUTION OF THE SCAN.
9943  * IT WAS A REQUEST TO CLOSE THE SCAN. WE WILL CLOSE THE SCAN IN A
9944  * CAREFUL MANNER TO ENSURE THAT NO ERROR OCCURS.
9945  * -------------------------------------------------------------------------
9946  * PRECONDITION:
9947  * TRANSACTION_STATE = SCAN_STATE_USED
9948  * TSCAN_COMPLETED = ZTRUE
9949  * -------------------------------------------------------------------------
9950  * WE CAN ALSO ARRIVE AT THIS LABEL AFTER A NODE CRASH OF THE SCAN
9951  * COORDINATOR.
9952  * ------------------------------------------------------------------------- */
9953 void Dblqh::closeScanRequestLab(Signal* signal)
9954 {
9955  DEBUG("transactionState = " << tcConnectptr.p->transactionState);
9956  switch (tcConnectptr.p->transactionState) {
9957  case TcConnectionrec::SCAN_STATE_USED:
9958  DEBUG("scanState = " << scanptr.p->scanState);
9959  switch (scanptr.p->scanState) {
9960  case ScanRecord::IN_QUEUE:
9961  jam();
9962  tupScanCloseConfLab(signal);
9963  break;
9964  case ScanRecord::WAIT_NEXT_SCAN:
9965  jam();
9966  /* -------------------------------------------------------------------
9967  * SET COMPLETION STATUS AND WAIT FOR OPPORTUNITY TO STOP THE SCAN.
9968  * ------------------------------------------------------------------- */
9969  scanptr.p->scanCompletedStatus = ZTRUE;
9970  break;
9971  case ScanRecord::WAIT_ACC_SCAN:
9972  case ScanRecord::WAIT_STORED_PROC_SCAN:
9973  jam();
9974  /* -------------------------------------------------------------------
9975  * WE ARE CURRENTLY STARTING UP THE SCAN. SET COMPLETED STATUS
9976  * AND WAIT FOR COMPLETION OF STARTUP.
9977  * ------------------------------------------------------------------- */
9978  scanptr.p->scanCompletedStatus = ZTRUE;
9979  break;
9980  case ScanRecord::WAIT_CLOSE_SCAN:
9981  jam();
9982  scanptr.p->scanCompletedStatus = ZTRUE;
9983  case ScanRecord::WAIT_DELETE_STORED_PROC_ID_SCAN:
9984  jam();
9985  /*empty*/;
9986  break;
9987  /* -------------------------------------------------------------------
9988  * CLOSE IS ALREADY ONGOING. WE NEED NOT DO ANYTHING.
9989  * ------------------------------------------------------------------- */
9990  case ScanRecord::WAIT_RELEASE_LOCK:
9991  jam();
9992  /* -------------------------------------------------------------------
9993  * WE ARE CURRENTLY RELEASING RECORD LOCKS. AFTER COMPLETING THIS
9994  * WE WILL START TO CLOSE THE SCAN.
9995  * ------------------------------------------------------------------- */
9996  scanptr.p->scanCompletedStatus = ZTRUE;
9997  break;
9998  case ScanRecord::WAIT_SCAN_NEXTREQ:
9999  jam();
10000  /* -------------------------------------------------------------------
10001  * WE ARE WAITING FOR A SCAN_NEXTREQ FROM SCAN COORDINATOR(TC)
10002  * WICH HAVE CRASHED. CLOSE THE SCAN
10003  * ------------------------------------------------------------------- */
10004  scanptr.p->scanCompletedStatus = ZTRUE;
10005 
10006  fragptr.i = tcConnectptr.p->fragmentptr;
10007  c_fragment_pool.getPtr(fragptr);
10008 
10009  if (scanptr.p->scanLockHold == ZTRUE) {
10010  if (scanptr.p->m_curr_batch_size_rows > 0) {
10011  jam();
10012  scanptr.p->scanReleaseCounter = 1;
10013  scanReleaseLocksLab(signal);
10014  return;
10015  }//if
10016  }//if
10017  closeScanLab(signal);
10018  break;
10019  default:
10020  ndbrequire(false);
10021  }//switch
10022  break;
10023  case TcConnectionrec::WAIT_SCAN_AI:
10024  jam();
10025  /* ---------------------------------------------------------------------
10026  * WE ARE STILL WAITING FOR THE ATTRIBUTE INFORMATION THAT
10027  * OBVIOUSLY WILL NOT ARRIVE. WE CAN QUIT IMMEDIATELY HERE.
10028  * --------------------------------------------------------------------- */
10029  tupScanCloseConfLab(signal);
10030  return;
10031  break;
10032  case TcConnectionrec::SCAN_TUPKEY:
10033  case TcConnectionrec::SCAN_FIRST_STOPPED:
10034  case TcConnectionrec::SCAN_CHECK_STOPPED:
10035  case TcConnectionrec::SCAN_STOPPED:
10036  jam();
10037  /* ---------------------------------------------------------------------
10038  * SET COMPLETION STATUS AND WAIT FOR OPPORTUNITY TO STOP THE SCAN.
10039  * --------------------------------------------------------------------- */
10040  scanptr.p->scanCompletedStatus = ZTRUE;
10041  break;
10042  case TcConnectionrec::SCAN_RELEASE_STOPPED:
10043  jam();
10044  /* ---------------------------------------------------------------------
10045  * WE ARE CURRENTLY RELEASING RECORD LOCKS. AFTER COMPLETING
10046  * THIS WE WILL START TO CLOSE THE SCAN.
10047  * --------------------------------------------------------------------- */
10048  scanptr.p->scanCompletedStatus = ZTRUE;
10049  break;
10050  case TcConnectionrec::SCAN_CLOSE_STOPPED:
10051  jam();
10052  /* ---------------------------------------------------------------------
10053  * CLOSE IS ALREADY ONGOING. WE NEED NOT DO ANYTHING.
10054  * --------------------------------------------------------------------- */
10055  /*empty*/;
10056  break;
10057  default:
10058  ndbrequire(false);
10059  }//switch
10060 }//Dblqh::closeScanRequestLab()
10061 
10062 /* -------------------------------------------------------------------------
10063  * ENTER NEXT_SCANCONF
10064  * -------------------------------------------------------------------------
10065  * PRECONDITION: SCAN_STATE = WAIT_RELEASE_LOCK
10066  * ------------------------------------------------------------------------- */
10067 void Dblqh::scanLockReleasedLab(Signal* signal)
10068 {
10069  tcConnectptr.i = scanptr.p->scanTcrec;
10070  ptrCheckGuard(tcConnectptr, ctcConnectrecFileSize, tcConnectionrec);
10071 
10072  check_send_scan_hb_rep(signal, scanptr.p, tcConnectptr.p);
10073 
10074  if (scanptr.p->scanReleaseCounter == scanptr.p->m_curr_batch_size_rows) {
10075  if ((scanptr.p->scanErrorCounter > 0) ||
10076  (scanptr.p->scanCompletedStatus == ZTRUE)) {
10077  jam();
10078  scanptr.p->m_curr_batch_size_rows = 0;
10079  scanptr.p->m_curr_batch_size_bytes = 0;
10080  closeScanLab(signal);
10081  } else if (scanptr.p->m_last_row && !scanptr.p->scanLockHold) {
10082  jam();
10083  closeScanLab(signal);
10084  return;
10085  } else if (scanptr.p->check_scan_batch_completed() &&
10086  scanptr.p->scanLockHold != ZTRUE) {
10087  jam();
10088  scanptr.p->scanState = ScanRecord::WAIT_SCAN_NEXTREQ;
10089  sendScanFragConf(signal, ZFALSE);
10090  } else {
10091  jam();
10092  /*
10093  * We came here after releasing locks after
10094  * receiving SCAN_NEXTREQ from TC. We only come here
10095  * when scanHoldLock == ZTRUE
10096  */
10097  scanptr.p->m_curr_batch_size_rows = 0;
10098  scanptr.p->m_curr_batch_size_bytes = 0;
10099  continueScanNextReqLab(signal);
10100  }//if
10101  } else if (scanptr.p->scanReleaseCounter < scanptr.p->m_curr_batch_size_rows) {
10102  jam();
10103  scanptr.p->scanReleaseCounter++;
10104  scanReleaseLocksLab(signal);
10105  }
10106  else if (scanptr.p->scanCompletedStatus != ZTRUE)
10107  {
10108  jam();
10109  /*
10110  We come here when we have been scanning for a long time and not been able
10111  to find m_max_batch_size_rows records to return. We needed to release
10112  the record we didn't want, but now we are returning all found records to
10113  the API.
10114  */
10115  scanptr.p->scanState = ScanRecord::WAIT_SCAN_NEXTREQ;
10116  sendScanFragConf(signal, ZFALSE);
10117  }
10118  else
10119  {
10120  jam();
10121  closeScanLab(signal);
10122  }
10123 }//Dblqh::scanLockReleasedLab()
10124 
10125 bool
10126 Dblqh::seize_acc_ptr_list(ScanRecord* scanP,
10127  Uint32 curr_batch_size,
10128  Uint32 new_batch_size)
10129 {
10130  /* 1 maps to 0 segments
10131  * >1 maps to enough segments to store
10132  */
10133  Uint32 segments= (new_batch_size + (SectionSegment::DataLength -2 )) /
10134  SectionSegment::DataLength;
10135 
10136  if (segments <= scanP->scan_acc_segments)
10137  {
10138  // No need to allocate more segments.
10139  return true;
10140  }
10141 
10142  if (new_batch_size > 1)
10143  {
10144  for (Uint32 i = 1 + scanP->scan_acc_segments; i <= segments; i++)
10145  {
10146  Uint32 seg= seizeSegment();
10147  if (unlikely(seg == RNIL))
10148  {
10149  jam();
10150  /* Cleanup any allocated segments and return */
10151  scanP->scan_acc_segments= (i-1);
10152  release_acc_ptr_list(scanP);
10153  return false;
10154  }
10155  scanP->scan_acc_op_ptr[i]= seg;
10156  }
10157  }
10158  scanP->scan_acc_segments= segments;
10159  return true;
10160 }
10161 
10162 void
10163 Dblqh::release_acc_ptr_list(ScanRecord* scanP)
10164 {
10165  Uint32 i, segments;
10166  segments= scanP->scan_acc_segments;
10167 
10168  for (i= 1; i <= segments; i++) {
10169  releaseSection(scanP->scan_acc_op_ptr[i]);
10170  }
10171  scanP->scan_acc_segments= 0;
10172  scanP->scan_acc_index = 0;
10173 }
10174 
10175 Uint32
10176 Dblqh::seizeSegment()
10177 {
10178  Uint32 junk= 0;
10179  Uint32 iVal= RNIL;
10180 
10181  /* Rather grungy way to grab a segment */
10182  if (!appendToSection(iVal, &junk, 1))
10183  return RNIL;
10184 
10185  return iVal;
10186 }
10187 
10188 void
10189 Dblqh::init_acc_ptr_list(ScanRecord* scanP)
10190 {
10191  scanP->scan_acc_index = 0;
10192 }
10193 
10194 Uint32
10195 Dblqh::get_acc_ptr_from_scan_record(ScanRecord* scanP,
10196  Uint32 index,
10197  bool crash_flag)
10198 {
10199  Uint32* acc_ptr;
10200  if (!((index < MAX_PARALLEL_OP_PER_SCAN) &&
10201  index < scanP->scan_acc_index)) {
10202  ndbrequire(crash_flag);
10203  return RNIL;
10204  }
10205  i_get_acc_ptr(scanP, acc_ptr, index);
10206  return *acc_ptr;
10207 }
10208 
10209 void
10210 Dblqh::set_acc_ptr_in_scan_record(ScanRecord* scanP,
10211  Uint32 index, Uint32 acc)
10212 {
10213  Uint32 *acc_ptr;
10214  ndbrequire((index == 0 || scanP->scan_acc_index == index) &&
10215  (index < MAX_PARALLEL_OP_PER_SCAN));
10216  scanP->scan_acc_index= index + 1;
10217  i_get_acc_ptr(scanP, acc_ptr, index);
10218  *acc_ptr= acc;
10219 }
10220 
10221 /* -------------------------------------------------------------------------
10222  * SCAN_FRAGREQ: Request to start scanning the specified fragment of a table.
10223  * ------------------------------------------------------------------------- */
10224 void Dblqh::execSCAN_FRAGREQ(Signal* signal)
10225 {
10226  jamEntry();
10227 
10228  /* Reassemble if the request was fragmented */
10229  if (!assembleFragments(signal)){
10230  jam();
10231  return;
10232  }
10233 
10234  ScanFragReq * const scanFragReq = (ScanFragReq *)&signal->theData[0];
10235  ScanFragRef * ref;
10236  const Uint32 transid1 = scanFragReq->transId1;
10237  const Uint32 transid2 = scanFragReq->transId2;
10238  Uint32 errorCode= 0;
10239  Uint32 senderData;
10240  Uint32 hashIndex;
10241  TcConnectionrecPtr nextHashptr;
10242  Uint32 senderHi = signal->getSendersBlockRef();
10243 
10244  const Uint32 reqinfo = scanFragReq->requestInfo;
10245 
10246  /* Short SCANFRAGREQ has no sections, Long SCANFRAGREQ has 1 or 2
10247  * Section 0 : Mandatory ATTRINFO section
10248  * Section 1 : Optional KEYINFO section
10249  */
10250  const Uint32 numSections= signal->getNoOfSections();
10251  bool isLongReq= ( numSections != 0 );
10252 
10253  SectionHandle handle(this, signal);
10254 
10255  SegmentedSectionPtr attrInfoPtr, keyInfoPtr;
10256  Uint32 aiLen= 0;
10257  Uint32 keyLen= 0;
10258 
10259  if (likely(isLongReq))
10260  {
10261  /* Long request, get Attr + Key len from section sizes */
10262  handle.getSection(attrInfoPtr, ScanFragReq::AttrInfoSectionNum);
10263  aiLen= attrInfoPtr.sz;
10264 
10265  if (numSections == 2)
10266  {
10267  handle.getSection(keyInfoPtr, ScanFragReq::KeyInfoSectionNum);
10268  keyLen= keyInfoPtr.sz;
10269  }
10270  }
10271  else
10272  {
10273  /* Short request, get Attr + Key len from signal */
10274  aiLen= ScanFragReq::getAttrLen(reqinfo);
10275  keyLen= (scanFragReq->fragmentNoKeyLen >> 16);
10276  }
10277 
10278  const Uint32 fragId = (scanFragReq->fragmentNoKeyLen & 0xFFFF);
10279  tabptr.i = scanFragReq->tableId;
10280  const Uint32 max_rows = scanFragReq->batch_size_rows;
10281  const Uint32 scanLockMode = ScanFragReq::getLockMode(reqinfo);
10282  const Uint8 keyinfo = ScanFragReq::getKeyinfoFlag(reqinfo);
10283  const Uint8 rangeScan = ScanFragReq::getRangeScanFlag(reqinfo);
10284 
10285  ptrCheckGuard(tabptr, ctabrecFileSize, tablerec);
10286  if (tabptr.p->tableStatus != Tablerec::TABLE_DEFINED &&
10287  tabptr.p->tableStatus != Tablerec::TABLE_READ_ONLY)
10288  {
10289  senderData = scanFragReq->senderData;
10290  goto error_handler_early_1;
10291  }
10292 
10293  if (cfirstfreeTcConrec != RNIL && !ERROR_INSERTED_CLEAR(5055)) {
10294  seizeTcrec();
10295  tcConnectptr.p->clientConnectrec = scanFragReq->senderData;
10296  tcConnectptr.p->clientBlockref = signal->senderBlockRef();
10297  tcConnectptr.p->savePointId = scanFragReq->savePointId;
10298  } else {
10299  jam();
10300  /* --------------------------------------------------------------------
10301  * NO FREE TC RECORD AVAILABLE, THUS WE CANNOT HANDLE THE REQUEST.
10302  * -------------------------------------------------------------------- */
10303  errorCode = ZNO_TC_CONNECT_ERROR;
10304  senderData = scanFragReq->senderData;
10305  goto error_handler_early;
10306  }//if
10310  ndbrequire(scanLockMode == 0 || keyinfo);
10311 
10312  ndbrequire(max_rows > 0 && max_rows <= MAX_PARALLEL_OP_PER_SCAN);
10313  if (!getFragmentrec(signal, fragId)) {
10314  errorCode = 1231;
10315  goto error_handler;
10316  }//if
10317 
10318  // Verify scan type vs table type (both sides are boolean)
10319  if (rangeScan != DictTabInfo::isOrderedIndex(fragptr.p->tableType)) {
10320  errorCode = 1232;
10321  goto error_handler;
10322  }//if
10323 
10324  // XXX adjust cmaxAccOps for range scans and remove this comment
10325  if ((cbookedAccOps + max_rows) > cmaxAccOps) {
10326  jam();
10327  errorCode = ScanFragRef::ZSCAN_BOOK_ACC_OP_ERROR;
10328  goto error_handler;
10329  }//if
10330 
10331  if (ScanFragReq::getLcpScanFlag(reqinfo))
10332  {
10333  jam();
10334  ndbrequire(m_reserved_scans.first(scanptr));
10335  m_reserved_scans.remove(scanptr);
10336  }
10337  else if (!c_scanRecordPool.seize(scanptr))
10338  {
10339  jam();
10340  errorCode = ScanFragRef::ZNO_FREE_SCANREC_ERROR;
10341  goto error_handler;
10342  }
10343 
10344  initScanTc(scanFragReq,
10345  transid1,
10346  transid2,
10347  fragId,
10348  ZNIL,
10349  senderHi);
10350  tcConnectptr.p->save1 = 0;
10351  tcConnectptr.p->primKeyLen = keyLen;
10352  tcConnectptr.p->applRef = scanFragReq->resultRef;
10353  if (likely(isLongReq))
10354  {
10355  tcConnectptr.p->attrInfoIVal= attrInfoPtr.i;
10356  if (keyLen)
10357  tcConnectptr.p->keyInfoIVal= keyInfoPtr.i;
10358  /* Scan state machine is now responsible for freeing
10359  * these sections, usually via releaseOprec()
10360  */
10361  handle.clear();
10362  }
10363 
10364  if (ScanFragReq::getCorrFactorFlag(reqinfo))
10365  {
10369  tcConnectptr.p->m_corrFactorLo = scanFragReq->variableData[0];
10370  tcConnectptr.p->m_corrFactorHi = scanFragReq->variableData[1];
10371  }
10372 
10373  errorCode = initScanrec(scanFragReq, aiLen);
10374  if (errorCode != ZOK) {
10375  jam();
10376  goto error_handler2;
10377  }//if
10378  cbookedAccOps += max_rows;
10379 
10380  hashIndex = (tcConnectptr.p->transid[0] ^ tcConnectptr.p->tcOprec) & 1023;
10381  nextHashptr.i = ctransidHash[hashIndex];
10382  ctransidHash[hashIndex] = tcConnectptr.i;
10383  tcConnectptr.p->prevHashRec = RNIL;
10384  tcConnectptr.p->nextHashRec = nextHashptr.i;
10385  if (nextHashptr.i != RNIL) {
10386  jam();
10387  /* ---------------------------------------------------------------------
10388  * ENSURE THAT THE NEXT RECORD HAS SET PREVIOUS TO OUR RECORD
10389  * IF IT EXISTS
10390  * --------------------------------------------------------------------- */
10391  ptrCheckGuard(nextHashptr, ctcConnectrecFileSize, tcConnectionrec);
10392  nextHashptr.p->prevHashRec = tcConnectptr.i;
10393  }//if
10394  if ((! isLongReq ) &&
10395  ( scanptr.p->scanAiLength > 0 )) {
10396  jam();
10397  tcConnectptr.p->transactionState = TcConnectionrec::WAIT_SCAN_AI;
10398  return;
10399  }//if
10400  continueAfterReceivingAllAiLab(signal);
10401  return;
10402 
10403 error_handler2:
10404  // no scan number allocated
10405  if (scanptr.p->m_reserved == 0)
10406  {
10407  jam();
10408  c_scanRecordPool.release(scanptr);
10409  }
10410  else
10411  {
10412  jam();
10413  m_reserved_scans.add(scanptr);
10414  }
10415 error_handler:
10416  ref = (ScanFragRef*)&signal->theData[0];
10417  tcConnectptr.p->abortState = TcConnectionrec::ABORT_ACTIVE;
10418  ref->senderData = tcConnectptr.p->clientConnectrec;
10419  ref->transId1 = transid1;
10420  ref->transId2 = transid2;
10421  ref->errorCode = errorCode;
10422  sendSignal(tcConnectptr.p->clientBlockref, GSN_SCAN_FRAGREF, signal,
10423  ScanFragRef::SignalLength, JBB);
10424  releaseSections(handle);
10425  tcConnectptr.p->tcScanRec = RNIL;
10426  releaseOprec(signal);
10427  releaseTcrec(signal, tcConnectptr);
10428  return;
10429 
10430  error_handler_early_1:
10431  errorCode = get_table_state_error(tabptr);
10432 
10433  error_handler_early:
10434  releaseSections(handle);
10435  ref = (ScanFragRef*)&signal->theData[0];
10436  ref->senderData = senderData;
10437  ref->transId1 = transid1;
10438  ref->transId2 = transid2;
10439  ref->errorCode = errorCode;
10440  sendSignal(signal->senderBlockRef(), GSN_SCAN_FRAGREF, signal,
10441  ScanFragRef::SignalLength, JBB);
10442 }//Dblqh::execSCAN_FRAGREQ()
10443 
10444 void Dblqh::continueAfterReceivingAllAiLab(Signal* signal)
10445 {
10446  tcConnectptr.p->transactionState = TcConnectionrec::SCAN_STATE_USED;
10447 
10448  if(scanptr.p->scanState == ScanRecord::IN_QUEUE){
10449  jam();
10450  return;
10451  }
10452 
10453  scanptr.p->scanState = ScanRecord::WAIT_ACC_SCAN;
10454  AccScanReq * req = (AccScanReq*)&signal->theData[0];
10455  req->senderData = scanptr.i;
10456  req->senderRef = cownref;
10457  req->tableId = tcConnectptr.p->tableref;
10458  req->fragmentNo = tcConnectptr.p->fragmentid;
10459  req->requestInfo = 0;
10460  AccScanReq::setLockMode(req->requestInfo, scanptr.p->scanLockMode);
10461  AccScanReq::setReadCommittedFlag(req->requestInfo, scanptr.p->readCommitted);
10462  AccScanReq::setDescendingFlag(req->requestInfo, scanptr.p->descending);
10463  AccScanReq::setStatScanFlag(req->requestInfo, scanptr.p->statScan);
10464 
10465  if (refToMain(tcConnectptr.p->clientBlockref) == BACKUP)
10466  {
10467  if (scanptr.p->lcpScan)
10468  {
10469  AccScanReq::setNoDiskScanFlag(req->requestInfo, 1);
10470  AccScanReq::setLcpScanFlag(req->requestInfo, 1);
10471  }
10472  else
10473  {
10474  /* If backup scan disktables in disk order */
10475  AccScanReq::setNoDiskScanFlag(req->requestInfo,
10476  !tcConnectptr.p->m_disk_table);
10477  AccScanReq::setLcpScanFlag(req->requestInfo, 0);
10478  }
10479  }
10480  else
10481  {
10482 #if BUG_27776_FIXED
10483  AccScanReq::setNoDiskScanFlag(req->requestInfo,
10484  !tcConnectptr.p->m_disk_table);
10485 #else
10486  AccScanReq::setNoDiskScanFlag(req->requestInfo, 1);
10487 #endif
10488  AccScanReq::setLcpScanFlag(req->requestInfo, 0);
10489  }
10490 
10491  req->transId1 = tcConnectptr.p->transid[0];
10492  req->transId2 = tcConnectptr.p->transid[1];
10493  req->savePointId = tcConnectptr.p->savePointId;
10494  sendSignal(scanptr.p->scanBlockref, GSN_ACC_SCANREQ, signal,
10495  AccScanReq::SignalLength, JBB);
10496 }//Dblqh::continueAfterReceivingAllAiLab()
10497 
10498 void Dblqh::scanAttrinfoLab(Signal* signal, Uint32* dataPtr, Uint32 length)
10499 {
10500  scanptr.i = tcConnectptr.p->tcScanRec;
10501  c_scanRecordPool.getPtr(scanptr);
10502  if (saveAttrInfoInSection(dataPtr, length) == ZOK) {
10503  if (tcConnectptr.p->currTupAiLen < scanptr.p->scanAiLength) {
10504  jam();
10505  } else {
10506  jam();
10507  ndbrequire(tcConnectptr.p->currTupAiLen == scanptr.p->scanAiLength);
10508  continueAfterReceivingAllAiLab(signal);
10509  }//if
10510  return;
10511  }//if
10512  abort_scan(signal, scanptr.i, ZGET_ATTRINBUF_ERROR);
10513 }
10514 
10515 void Dblqh::abort_scan(Signal* signal, Uint32 scan_ptr_i, Uint32 errcode){
10516  jam();
10517  scanptr.i = scan_ptr_i;
10518  c_scanRecordPool.getPtr(scanptr);
10519 
10520  tcConnectptr.p->errorCode = errcode;
10521  tupScanCloseConfLab(signal);
10522  return;
10523 }
10524 
10525 /*---------------------------------------------------------------------*/
10526 /* Send this 'I am alive' signal to TC when it is received from ACC */
10527 /* We include the scanPtr.i that comes from ACC in signalData[1], this */
10528 /* tells TC which fragment record to check for a timeout. */
10529 /*---------------------------------------------------------------------*/
10530 void
10531 Dblqh::check_send_scan_hb_rep(Signal* signal,
10532  ScanRecord* scanPtrP,
10533  TcConnectionrec* tcPtrP)
10534 {
10535  switch(scanPtrP->scanType){
10536  case ScanRecord::SCAN:
10537  break;
10538  case ScanRecord::COPY:
10539  return;
10540 #ifdef NDEBUG
10541  case ScanRecord::ST_IDLE:
10542  default:
10543  return;
10544 #else
10545  case ScanRecord::ST_IDLE:
10546  ndbrequire(false);
10547 #endif
10548  }
10549 
10550  Uint64 now = cLqhTimeOutCount; // measure in 10ms
10551  Uint64 last = scanPtrP->scanTcWaiting; // last time we reported to TC (10ms)
10552  Uint64 timeout = cTransactionDeadlockDetectionTimeout; // (ms)
10553  Uint64 limit = (3*timeout) / 4;
10554 
10555  bool alarm =
10556  now >= ((10 * last + limit) / 10) || now < last; // wrap
10557 
10558  if (alarm)
10559  {
10560  jam();
10561 
10562  scanPtrP->scanTcWaiting = Uint32(now);
10563  if (tcPtrP->tcTimer != 0)
10564  {
10565  tcPtrP->tcTimer = Uint32(now);
10566  }
10567 
10568  Uint32 save[3];
10569  save[0] = signal->theData[0];
10570  save[1] = signal->theData[1];
10571  save[2] = signal->theData[2];
10572 
10573  signal->theData[0] = tcPtrP->clientConnectrec;
10574  signal->theData[1] = tcPtrP->transid[0];
10575  signal->theData[2] = tcPtrP->transid[1];
10576  sendSignal(tcPtrP->clientBlockref,
10577  GSN_SCAN_HBREP, signal, 3, JBB);
10578 
10579  signal->theData[0] = save[0];
10580  signal->theData[1] = save[1];
10581  signal->theData[2] = save[2];
10582  }
10583 }
10584 
10585 void Dblqh::accScanConfScanLab(Signal* signal)
10586 {
10587  AccScanConf * const accScanConf = (AccScanConf *)&signal->theData[0];
10588  tcConnectptr.i = scanptr.p->scanTcrec;
10589  ptrCheckGuard(tcConnectptr, ctcConnectrecFileSize, tcConnectionrec);
10590 
10591  /* -----------------------------------------------------------------------
10592  * PRECONDITION: SCAN_STATE = WAIT_ACC_SCAN
10593  * ----------------------------------------------------------------------- */
10594  if (accScanConf->flag == AccScanConf::ZEMPTY_FRAGMENT) {
10595  jam();
10596  /* ---------------------------------------------------------------------
10597  * THE FRAGMENT WAS EMPTY.
10598  * REPORT SUCCESSFUL COPYING.
10599  * --------------------------------------------------------------------- */
10600  /*
10601  * MRR scan + delete can hit this when the fragment was not
10602  * initially empty, but has become empty after previous range.
10603  */
10604  if (scanptr.p->scanStoredProcId != RNIL) {
10605  jam();
10606  scanptr.p->scanCompletedStatus = ZTRUE;
10607  accScanCloseConfLab(signal);
10608  return;
10609  }
10610  tupScanCloseConfLab(signal);
10611  return;
10612  }//if
10613 
10614  check_send_scan_hb_rep(signal, scanptr.p, tcConnectptr.p);
10615 
10616  scanptr.p->scanAccPtr = accScanConf->accPtr;
10617  if (scanptr.p->rangeScan) {
10618  jam();
10619  TuxBoundInfo* req = (TuxBoundInfo*)signal->getDataPtrSend();
10620  req->errorCode = RNIL;
10621  req->tuxScanPtrI = scanptr.p->scanAccPtr;
10622  // TODO : Any improvements to be made on this block boundary?
10623  Uint32 len = req->boundAiLength = copyNextRange(req->data, tcConnectptr.p);
10624  EXECUTE_DIRECT(DBTUX, GSN_TUX_BOUND_INFO, signal,
10625  TuxBoundInfo::SignalLength + len);
10626 
10627  jamEntry();
10628  if (req->errorCode != 0) {
10629  jam();
10630  /*
10631  * Cannot use STORED_PROCREF to abort since even the REF
10632  * returns a stored proc id. So record error and continue.
10633  * The scan is already Invalid in TUX and returns empty set.
10634  */
10635  tcConnectptr.p->errorCode = req->errorCode;
10636  }
10637  }
10638 
10639  scanptr.p->scanState = ScanRecord::WAIT_STORED_PROC_SCAN;
10640  if(scanptr.p->scanStoredProcId == RNIL)
10641  {
10642  jam();
10643  /* Send AttrInfo to TUP to store as 'stored procedure'
10644  * and get storedProcId back for future reference
10645  */
10646  signal->theData[0] = tcConnectptr.p->tupConnectrec;
10647  signal->theData[1] = tcConnectptr.p->tableref;
10648  signal->theData[2] = scanptr.p->scanSchemaVersion;
10649  signal->theData[3] = ZSTORED_PROC_SCAN;
10650 // theData[4] is not used
10651  signal->theData[5] = scanptr.p->scanApiBlockref;
10652 
10653  /* Pass ATTRINFO as long section, we don't need
10654  * it after this
10655  */
10656  SectionHandle handle(this);
10657  handle.m_ptr[0].i= tcConnectptr.p->attrInfoIVal;
10658  handle.m_cnt= 1;
10659  tcConnectptr.p->attrInfoIVal= RNIL;
10660  getSections(handle.m_cnt, handle.m_ptr);
10661 
10662  sendSignal(tcConnectptr.p->tcTupBlockref,
10663  GSN_STORED_PROCREQ, signal, 6, JBB,
10664  &handle);
10665  }
10666  else
10667  {
10668  /* TUP already has the Stored procedure, continue */
10669  jam();
10670  storedProcConfScanLab(signal);
10671  }
10672 }//Dblqh::accScanConfScanLab()
10673 
10674 Uint32
10675 Dblqh::copyNextRange(Uint32 * dst, TcConnectionrec* tcPtrP)
10676 {
10686  Uint32 totalLen = tcPtrP->primKeyLen;
10687 
10688  if (totalLen)
10689  {
10690  ndbassert( tcPtrP->keyInfoIVal != RNIL );
10691  SectionReader keyInfoReader(tcPtrP->keyInfoIVal,
10692  g_sectionSegmentPool);
10693 
10694  if (tcPtrP->m_flags & TcConnectionrec::OP_SCANKEYINFOPOSSAVED)
10695  {
10696  /* Second or higher range in an MRR scan
10697  * Restore SectionReader to the last position it was in
10698  */
10699  bool ok= keyInfoReader.setPos(tcPtrP->scanKeyInfoPos);
10700  ndbrequire(ok);
10701  }
10702 
10703  /* Get first word of next range and extract range
10704  * length, number from it.
10705  * For non MRR, these will be zero.
10706  */
10707  Uint32 firstWord;
10708  ndbrequire( keyInfoReader.getWord(&firstWord) );
10709  const Uint32 rangeLen= (firstWord >> 16) ? (firstWord >> 16) : totalLen;
10710  Uint32 range_no = (firstWord & 0xFFF0) >> 4;
10711  tcPtrP->m_scan_curr_range_no= range_no;
10712  tcPtrP->m_corrFactorLo &= 0x0000FFFF;
10713  tcPtrP->m_corrFactorLo |= (range_no << 16);
10714  firstWord &= 0xF; // Remove length+range num from first word
10715 
10716  /* Write range info to dst */
10717  *(dst++)= firstWord;
10718  bool ok= keyInfoReader.getWords(dst, rangeLen - 1);
10719 
10720  ndbrequire(ok);
10721 
10722  tcPtrP->primKeyLen-= rangeLen;
10723 
10724  if (rangeLen == totalLen)
10725  {
10726  /* All range information has been copied, free the section */
10727  releaseSection(tcPtrP->keyInfoIVal);
10728  tcPtrP->keyInfoIVal= RNIL;
10729  }
10730  else
10731  {
10732  /* Save position of SectionReader for next range (if any) */
10733  tcPtrP->scanKeyInfoPos= keyInfoReader.getPos();
10734  tcPtrP->m_flags|= TcConnectionrec::OP_SCANKEYINFOPOSSAVED;
10735  }
10736 
10737  return rangeLen;
10738  }
10739 
10740  return totalLen;
10741 }
10742 
10743 /* -------------------------------------------------------------------------
10744  * ENTER STORED_PROCCONF WITH
10745  * TC_CONNECTPTR,
10746  * TSTORED_PROC_ID
10747  * -------------------------------------------------------------------------
10748  * PRECONDITION: SCAN_STATE = WAIT_STORED_PROC_SCAN
10749  * ------------------------------------------------------------------------- */
10750 void Dblqh::storedProcConfScanLab(Signal* signal)
10751 {
10752  fragptr.i = tcConnectptr.p->fragmentptr;
10753  c_fragment_pool.getPtr(fragptr);
10754  if (scanptr.p->scanCompletedStatus == ZTRUE) {
10755  jam();
10756  // STOP THE SCAN PROCESS IF THIS HAS BEEN REQUESTED.
10757  closeScanLab(signal);
10758  return;
10759  }//if
10760  switch (fragptr.p->fragStatus) {
10761  case Fragrecord::FSACTIVE:
10762  jam();
10763  break;
10764  case Fragrecord::BLOCKED:
10765  jam();
10766  linkFragQueue(signal);
10767  tcConnectptr.p->transactionState = TcConnectionrec::SCAN_FIRST_STOPPED;
10768  return;
10769  break;
10770  case Fragrecord::FREE:
10771  jam();
10773  jam();
10775  jam();
10776  case Fragrecord::DEFINED:
10777  jam();
10778  case Fragrecord::REMOVING:
10779  jam();
10780  default:
10781  jamLine(fragptr.p->fragStatus);
10782  ndbout_c("fragptr.p->fragStatus: %u",
10783  fragptr.p->fragStatus);
10784  // wl4391_todo SR 2-node CRASH_RECOVERING from BACKUP
10785  ndbrequire(false);
10786  break;
10787  }//switch
10788  continueFirstScanAfterBlockedLab(signal);
10789 }//Dblqh::storedProcConfScanLab()
10790 
10791 void Dblqh::continueFirstScanAfterBlockedLab(Signal* signal)
10792 {
10793  scanptr.i = tcConnectptr.p->tcScanRec;
10794  c_scanRecordPool.getPtr(scanptr);
10795  scanptr.p->scanState = ScanRecord::WAIT_NEXT_SCAN;
10796  signal->theData[0] = scanptr.p->scanAccPtr;
10797  signal->theData[1] = RNIL;
10798  signal->theData[2] = NextScanReq::ZSCAN_NEXT;
10799  sendSignal(scanptr.p->scanBlockref, GSN_NEXT_SCANREQ, signal, 3, JBB);
10800  return;
10801 }//Dblqh::continueFirstScanAfterBlockedLab()
10802 
10803 /* -------------------------------------------------------------------------
10804  * When executing a scan we must come up to the surface at times to make
10805  * sure we can quickly start local checkpoints.
10806  * ------------------------------------------------------------------------- */
10807 void Dblqh::execCHECK_LCP_STOP(Signal* signal)
10808 {
10809  jamEntry();
10810  scanptr.i = signal->theData[0];
10811  c_scanRecordPool.getPtr(scanptr);
10812  tcConnectptr.i = scanptr.p->scanTcrec;
10813  ptrCheckGuard(tcConnectptr, ctcConnectrecFileSize, tcConnectionrec);
10814  fragptr.i = tcConnectptr.p->fragmentptr;
10815 
10816  c_fragment_pool.getPtr(fragptr);
10817  if (signal->theData[1] == ZTRUE) {
10818  jam();
10819  signal->theData[0] = ZCHECK_LCP_STOP_BLOCKED;
10820  signal->theData[1] = scanptr.i;
10821  sendSignalWithDelay(cownref, GSN_CONTINUEB, signal, 10, 2);
10822  signal->theData[0] = RNIL;
10823  return;
10824  }//if
10825  if (fragptr.p->fragStatus != Fragrecord::FSACTIVE) {
10826  ndbrequire(fragptr.p->fragStatus == Fragrecord::BLOCKED);
10827  linkFragQueue(signal);
10828  tcConnectptr.p->transactionState = TcConnectionrec::SCAN_CHECK_STOPPED;
10829  signal->theData[0] = RNIL;
10830  }//if
10831 }//Dblqh::execCHECK_LCP_STOP()
10832 
10833 void Dblqh::checkLcpStopBlockedLab(Signal* signal)
10834 {
10835  switch (fragptr.p->fragStatus) {
10836  case Fragrecord::FSACTIVE:
10837  jam();
10838  continueAfterCheckLcpStopBlocked(signal);
10839  break;
10840  case Fragrecord::BLOCKED:
10841  jam();
10842  linkFragQueue(signal);
10843  tcConnectptr.p->transactionState = TcConnectionrec::SCAN_CHECK_STOPPED;
10844  return;
10845  break;
10846  case Fragrecord::FREE:
10847  jam();
10849  jam();
10851  jam();
10852  case Fragrecord::DEFINED:
10853  jam();
10854  case Fragrecord::REMOVING:
10855  jam();
10856  default:
10857  ndbrequire(false);
10858  }//switch
10859 }//Dblqh::checkLcpStopBlockedLab()
10860 
10861 void Dblqh::continueAfterCheckLcpStopBlocked(Signal* signal)
10862 {
10863  scanptr.i = tcConnectptr.p->tcScanRec;
10864  c_scanRecordPool.getPtr(scanptr);
10865  signal->theData[0] = scanptr.p->scanAccPtr;
10866  signal->theData[1] = AccCheckScan::ZNOT_CHECK_LCP_STOP;
10867  EXECUTE_DIRECT(refToMain(scanptr.p->scanBlockref), GSN_ACC_CHECK_SCAN,
10868  signal, 2);
10869 }//Dblqh::continueAfterCheckLcpStopBlocked()
10870 
10871 /* -------------------------------------------------------------------------
10872  * ENTER NEXT_SCANCONF
10873  * -------------------------------------------------------------------------
10874  * PRECONDITION: SCAN_STATE = WAIT_NEXT_SCAN
10875  * ------------------------------------------------------------------------- */
10876 void Dblqh::nextScanConfScanLab(Signal* signal)
10877 {
10878  NextScanConf * const nextScanConf = (NextScanConf *)&signal->theData[0];
10879  tcConnectptr.i = scanptr.p->scanTcrec;
10880  ptrCheckGuard(tcConnectptr, ctcConnectrecFileSize, tcConnectionrec);
10881 
10882  if (nextScanConf->fragId == RNIL) {
10883  jam();
10884  /* ---------------------------------------------------------------------
10885  * THERE ARE NO MORE TUPLES TO FETCH. IF WE HAVE ANY
10886  * OPERATIONS STILL NEEDING A LOCK WE REPORT TO THE
10887  * APPLICATION AND CLOSE THE SCAN WHEN THE NEXT SCAN
10888  * REQUEST IS RECEIVED. IF WE DO NOT HAVE ANY NEED FOR
10889  * LOCKS WE CAN CLOSE THE SCAN IMMEDIATELY.
10890  * --------------------------------------------------------------------- */
10891  /*************************************************************
10892  * STOP THE SCAN PROCESS IF THIS HAS BEEN REQUESTED.
10893  ************************************************************ */
10894  if (!scanptr.p->scanLockHold)
10895  {
10896  jam();
10897  closeScanLab(signal);
10898  return;
10899  }
10900 
10901  if (scanptr.p->scanCompletedStatus == ZTRUE) {
10902  if ((scanptr.p->scanLockHold == ZTRUE) &&
10903  (scanptr.p->m_curr_batch_size_rows > 0)) {
10904  jam();
10905  scanptr.p->scanReleaseCounter = 1;
10906  scanReleaseLocksLab(signal);
10907  return;
10908  }//if
10909  jam();
10910  closeScanLab(signal);
10911  return;
10912  }//if
10913 
10914  if (scanptr.p->m_curr_batch_size_rows > 0) {
10915  jam();
10916 
10917  if((tcConnectptr.p->primKeyLen) == 0)
10918  scanptr.p->scanCompletedStatus = ZTRUE;
10919 
10920  scanptr.p->scanState = ScanRecord::WAIT_SCAN_NEXTREQ;
10921  sendScanFragConf(signal, ZFALSE);
10922  return;
10923  }//if
10924  closeScanLab(signal);
10925  return;
10926  }//if
10927 
10928  // If accOperationPtr == RNIL no record was returned by ACC
10929  Uint32 accOpPtr = nextScanConf->accOperationPtr;
10930  if (accOpPtr == RNIL)
10931  {
10932  jam();
10933  /*************************************************************
10934  * STOP THE SCAN PROCESS IF THIS HAS BEEN REQUESTED.
10935  ************************************************************ */
10936  if (scanptr.p->scanCompletedStatus == ZTRUE) {
10937  if ((scanptr.p->scanLockHold == ZTRUE) &&
10938  (scanptr.p->m_curr_batch_size_rows > 0)) {
10939  jam();
10940  scanptr.p->scanReleaseCounter = 1;
10941  scanReleaseLocksLab(signal);
10942  return;
10943  }//if
10944  jam();
10945  closeScanLab(signal);
10946  return;
10947  }//if
10948 
10949  if (scanptr.p->m_curr_batch_size_rows > 0) {
10950  jam();
10951  scanptr.p->scanState = ScanRecord::WAIT_SCAN_NEXTREQ;
10952  sendScanFragConf(signal, ZFALSE);
10953  return;
10954  }//if
10955 
10956  signal->theData[0] = scanptr.p->scanAccPtr;
10957  signal->theData[1] = AccCheckScan::ZCHECK_LCP_STOP;
10958  sendSignal(scanptr.p->scanBlockref,
10959  GSN_ACC_CHECK_SCAN, signal, 2, JBB);
10960  return;
10961  }//if
10962 
10963  jam();
10964  check_send_scan_hb_rep(signal, scanptr.p, tcConnectptr.p);
10965  set_acc_ptr_in_scan_record(scanptr.p,
10966  scanptr.p->m_curr_batch_size_rows,
10967  accOpPtr);
10968 
10969  jam();
10970  nextScanConfLoopLab(signal);
10971 }//Dblqh::nextScanConfScanLab()
10972 
10973 void Dblqh::nextScanConfLoopLab(Signal* signal)
10974 {
10975  /* ----------------------------------------------------------------------
10976  * STOP THE SCAN PROCESS IF THIS HAS BEEN REQUESTED.
10977  * ---------------------------------------------------------------------- */
10978  if (scanptr.p->scanCompletedStatus == ZTRUE) {
10979  jam();
10980  if ((scanptr.p->scanLockHold == ZTRUE) &&
10981  (scanptr.p->m_curr_batch_size_rows > 0)) {
10982  jam();
10983  scanptr.p->scanReleaseCounter = 1;
10984  scanReleaseLocksLab(signal);
10985  return;
10986  }//if
10987  closeScanLab(signal);
10988  return;
10989  }//if
10990 
10991  Fragrecord* fragPtrP= fragptr.p;
10992  if (scanptr.p->rangeScan) {
10993  jam();
10994  // for ordered index use primary table
10995  fragPtrP= c_fragment_pool.getPtr(fragPtrP->tableFragptr);
10996  }
10997 
10998  tcConnectptr.p->transactionState = TcConnectionrec::SCAN_TUPKEY;
10999  if(tcConnectptr.p->m_disk_table)
11000  {
11001  next_scanconf_load_diskpage(signal, scanptr, tcConnectptr,fragPtrP);
11002  }
11003  else
11004  {
11005  next_scanconf_tupkeyreq(signal, scanptr, tcConnectptr.p, fragPtrP, RNIL);
11006  }
11007 }
11008 
11009 void
11010 Dblqh::next_scanconf_load_diskpage(Signal* signal,
11011  ScanRecordPtr scanPtr,
11012  Ptr<TcConnectionrec> regTcPtr,
11013  Fragrecord* fragPtrP)
11014 {
11015  jam();
11016 
11017  int res;
11018 
11019  if((res= c_tup->load_diskpage_scan(signal,
11020  regTcPtr.p->tupConnectrec,
11021  fragPtrP->tupFragptr,
11022  scanPtr.p->m_row_id.m_page_no,
11023  scanPtr.p->m_row_id.m_page_idx,
11024  0)) > 0)
11025  {
11026  next_scanconf_tupkeyreq(signal, scanptr, regTcPtr.p, fragPtrP, res);
11027  }
11028  else if(unlikely(res != 0))
11029  {
11030  jam();
11031  TupKeyRef * ref = (TupKeyRef *)signal->getDataPtr();
11032  ref->userRef= regTcPtr.i;
11033  ref->errorCode= ~0;
11034  execTUPKEYREF(signal);
11035  }
11036 }
11037 
11038 void
11039 Dblqh::next_scanconf_load_diskpage_callback(Signal* signal,
11040  Uint32 callbackData,
11041  Uint32 disk_page)
11042 {
11043  jamEntry();
11044 
11045  Ptr<TcConnectionrec> regTcPtr;
11046  regTcPtr.i= callbackData;
11047  ptrCheckGuard(regTcPtr, ctcConnectrecFileSize, tcConnectionrec);
11048 
11049  ScanRecordPtr scanPtr;
11050  c_scanRecordPool.getPtr(scanPtr, regTcPtr.p->tcScanRec);
11051 
11052  if(disk_page > 0)
11053  {
11054  FragrecordPtr fragPtr;
11055  c_fragment_pool.getPtr(fragPtr, regTcPtr.p->fragmentptr);
11056 
11057  if (scanPtr.p->rangeScan) {
11058  jam();
11059  // for ordered index use primary table
11060  fragPtr.p = c_fragment_pool.getPtr(fragPtr.p->tableFragptr);
11061  }
11062 
11063  next_scanconf_tupkeyreq(signal, scanPtr, regTcPtr.p, fragPtr.p, disk_page);
11064  }
11065  else
11066  {
11067  TupKeyRef * ref = (TupKeyRef *)signal->getDataPtr();
11068  ref->userRef= callbackData;
11069  ref->errorCode= disk_page;
11070  execTUPKEYREF(signal);
11071  }
11072 }
11073 
11074 void
11075 Dblqh::next_scanconf_tupkeyreq(Signal* signal,
11076  Ptr<ScanRecord> scanPtr,
11077  TcConnectionrec * regTcPtr,
11078  Fragrecord* fragPtrP,
11079  Uint32 disk_page)
11080 {
11081  jam();
11082  Uint32 reqinfo = (scanPtr.p->scanLockHold == ZFALSE);
11083  reqinfo = reqinfo + (regTcPtr->operation << 6);
11084  reqinfo = reqinfo + (regTcPtr->opExec << 10);
11085  reqinfo = reqinfo + (regTcPtr->m_reorg << 12);
11086 
11087  TupKeyReq * const tupKeyReq = (TupKeyReq *)signal->getDataPtrSend();
11088 
11089  tupKeyReq->connectPtr = regTcPtr->tupConnectrec;
11090  tupKeyReq->request = reqinfo;
11091  tupKeyReq->keyRef1 = scanPtr.p->m_row_id.m_page_no;
11092  tupKeyReq->keyRef2 = scanPtr.p->m_row_id.m_page_idx;
11093  tupKeyReq->attrBufLen = 0;
11094  tupKeyReq->opRef = scanPtr.p->scanApiOpPtr;
11095  tupKeyReq->applRef = scanPtr.p->scanApiBlockref;
11096  tupKeyReq->storedProcedure = scanPtr.p->scanStoredProcId;
11097  tupKeyReq->transId1 = regTcPtr->transid[0];
11098  tupKeyReq->transId2 = regTcPtr->transid[1];
11099  tupKeyReq->fragPtr = fragPtrP->tupFragptr;
11100  tupKeyReq->primaryReplica = (regTcPtr->seqNoReplica == 0)?true:false;
11101  tupKeyReq->coordinatorTC = regTcPtr->tcBlockref;
11102  tupKeyReq->tcOpIndex = regTcPtr->tcOprec;
11103  tupKeyReq->savePointId = regTcPtr->savePointId;
11104  tupKeyReq->disk_page= disk_page;
11105  /* No AttrInfo sent to TUP, it uses a stored procedure */
11106  tupKeyReq->attrInfoIVal= RNIL;
11107  Uint32 blockNo = refToMain(regTcPtr->tcTupBlockref);
11108  EXECUTE_DIRECT(blockNo, GSN_TUPKEYREQ, signal,
11109  TupKeyReq::SignalLength);
11110 }
11111 
11112 /* -------------------------------------------------------------------------
11113  * STORE KEYINFO IN A LONG SECTION PRIOR TO SENDING
11114  * -------------------------------------------------------------------------
11115  * PRECONDITION: SCAN_STATE = WAIT_SCAN_KEYINFO
11116  * ------------------------------------------------------------------------- */
11117 bool
11118 Dblqh::keyinfoLab(const Uint32 * src, Uint32 len)
11119 {
11120  ndbassert( tcConnectptr.p->keyInfoIVal == RNIL );
11121  ndbassert( len > 0 );
11122 
11123  if (ERROR_INSERTED(5052) || ERROR_INSERTED_CLEAR(5060))
11124  return false;
11125 
11126  return(appendToSection(tcConnectptr.p->keyInfoIVal,
11127  src,
11128  len));
11129 }//Dblqh::keyinfoLab()
11130 
11131 Uint32
11132 Dblqh::readPrimaryKeys(ScanRecord *scanP, TcConnectionrec *tcConP, Uint32 *dst)
11133 {
11134  Uint32 tableId = tcConP->tableref;
11135  Uint32 fragId = tcConP->fragmentid;
11136  Uint32 fragPageId = scanP->m_row_id.m_page_no;
11137  Uint32 pageIndex = scanP->m_row_id.m_page_idx;
11138 
11139  if(scanP->rangeScan)
11140  {
11141  jam();
11142  // for ordered index use primary table
11143  FragrecordPtr tFragPtr;
11144  tFragPtr.i = fragptr.p->tableFragptr;
11145  c_fragment_pool.getPtr(tFragPtr);
11146  tableId = tFragPtr.p->tabRef;
11147  }
11148 
11149  int ret = c_tup->accReadPk(tableId, fragId, fragPageId, pageIndex, dst, false);
11150  jamEntry();
11151  if(0)
11152  ndbout_c("readPrimaryKeys(table: %d fragment: %d [ %d %d ] -> %d",
11153  tableId, fragId, fragPageId, pageIndex, ret);
11154  ndbassert(ret > 0);
11155 
11156  return ret;
11157 }
11158 
11159 /* -------------------------------------------------------------------------
11160  * ENTER TUPKEYCONF
11161  * -------------------------------------------------------------------------
11162  * PRECONDITION: TRANSACTION_STATE = SCAN_TUPKEY
11163  * ------------------------------------------------------------------------- */
11164 void Dblqh::scanTupkeyConfLab(Signal* signal)
11165 {
11166  const TupKeyConf * conf = (TupKeyConf *)signal->getDataPtr();
11167  UintR tdata4 = conf->readLength;
11168  UintR tdata5 = conf->lastRow;
11169 
11170  tcConnectptr.p->transactionState = TcConnectionrec::SCAN_STATE_USED;
11171  scanptr.i = tcConnectptr.p->tcScanRec;
11172  c_scanRecordPool.getPtr(scanptr);
11173 
11174  Uint32 rows = scanptr.p->m_curr_batch_size_rows;
11175  Uint32 accOpPtr= get_acc_ptr_from_scan_record(scanptr.p, rows, false);
11176  if (accOpPtr != (Uint32)-1)
11177  {
11178  c_acc->execACCKEY_ORD(signal, accOpPtr);
11179  jamEntry();
11180  }
11181  else
11182  {
11183  ndbassert(refToBlock(scanptr.p->scanBlockref) != DBACC);
11184  }
11185 
11186  if (scanptr.p->scanCompletedStatus == ZTRUE) {
11187  /* ---------------------------------------------------------------------
11188  * STOP THE SCAN PROCESS IF THIS HAS BEEN REQUESTED.
11189  * --------------------------------------------------------------------- */
11190  if ((scanptr.p->scanLockHold == ZTRUE) && rows)
11191  {
11192  jam();
11193  scanptr.p->scanReleaseCounter = 1;
11194  scanReleaseLocksLab(signal);
11195  return;
11196  }//if
11197  jam();
11198  closeScanLab(signal);
11199  return;
11200  }//if
11201  if (scanptr.p->scanKeyinfoFlag) {
11202  jam();
11203  // Inform API about keyinfo len aswell
11204  tdata4 += sendKeyinfo20(signal, scanptr.p, tcConnectptr.p);
11205  }//if
11206  ndbrequire(scanptr.p->m_curr_batch_size_rows < MAX_PARALLEL_OP_PER_SCAN);
11207  scanptr.p->m_curr_batch_size_bytes+= tdata4;
11208  scanptr.p->m_curr_batch_size_rows = rows + 1;
11209  scanptr.p->m_last_row = tdata5;
11210  if (scanptr.p->check_scan_batch_completed() | tdata5){
11211  if (scanptr.p->scanLockHold == ZTRUE) {
11212  jam();
11213  scanptr.p->scanState = ScanRecord::WAIT_SCAN_NEXTREQ;
11214  sendScanFragConf(signal, ZFALSE);
11215  return;
11216  } else {
11217  jam();
11218  scanptr.p->scanReleaseCounter = rows + 1;
11219  scanReleaseLocksLab(signal);
11220  return;
11221  }
11222  } else {
11223  if (scanptr.p->scanLockHold == ZTRUE) {
11224  jam();
11225  scanptr.p->scanFlag = NextScanReq::ZSCAN_NEXT;
11226  } else {
11227  jam();
11228  scanptr.p->scanFlag = NextScanReq::ZSCAN_NEXT_COMMIT;
11229  }
11230  }
11231  scanNextLoopLab(signal);
11232 }//Dblqh::scanTupkeyConfLab()
11233 
11234 void Dblqh::scanNextLoopLab(Signal* signal)
11235 {
11236  switch (fragptr.p->fragStatus) {
11237  case Fragrecord::FSACTIVE:
11238  jam();
11239  break;
11240  case Fragrecord::BLOCKED:
11241  jam();
11242  linkFragQueue(signal);
11243  tcConnectptr.p->transactionState = TcConnectionrec::SCAN_STOPPED;
11244  return;
11245  break;
11246  case Fragrecord::FREE:
11247  jam();
11249  jam();
11251  jam();
11252  case Fragrecord::DEFINED:
11253  jam();
11254  case Fragrecord::REMOVING:
11255  jam();
11256  default:
11257  ndbrequire(false);
11258  }//switch
11259  continueScanAfterBlockedLab(signal);
11260 }//Dblqh::scanNextLoopLab()
11261 
11262 void Dblqh::continueScanAfterBlockedLab(Signal* signal)
11263 {
11264  scanptr.i = tcConnectptr.p->tcScanRec;
11265  c_scanRecordPool.getPtr(scanptr);
11266  Uint32 accOpPtr;
11267  if (scanptr.p->scanFlag == NextScanReq::ZSCAN_NEXT_ABORT) {
11268  jam();
11269  scanptr.p->scanFlag = NextScanReq::ZSCAN_NEXT_COMMIT;
11270  accOpPtr= get_acc_ptr_from_scan_record(scanptr.p,
11271  scanptr.p->m_curr_batch_size_rows,
11272  false);
11273  scanptr.p->scan_acc_index--;
11274  } else if (scanptr.p->scanFlag == NextScanReq::ZSCAN_NEXT_COMMIT) {
11275  jam();
11276  accOpPtr= get_acc_ptr_from_scan_record(scanptr.p,
11277  scanptr.p->m_curr_batch_size_rows-1,
11278  false);
11279  } else {
11280  jam();
11281  accOpPtr = RNIL; // The value is not used in ACC
11282  }//if
11283  scanptr.p->scanState = ScanRecord::WAIT_NEXT_SCAN;
11284  signal->theData[0] = scanptr.p->scanAccPtr;
11285  signal->theData[1] = accOpPtr;
11286  signal->theData[2] = scanptr.p->scanFlag;
11287  sendSignal(scanptr.p->scanBlockref, GSN_NEXT_SCANREQ, signal, 3, JBB);
11288 }//Dblqh::continueScanAfterBlockedLab()
11289 
11290 /* -------------------------------------------------------------------------
11291  * ENTER TUPKEYREF WITH
11292  * TC_CONNECTPTR,
11293  * TERROR_CODE
11294  * -------------------------------------------------------------------------
11295  * PRECONDITION: TRANSACTION_STATE = SCAN_TUPKEY
11296  * ------------------------------------------------------------------------- */
11297 void Dblqh::scanTupkeyRefLab(Signal* signal)
11298 {
11299  tcConnectptr.p->transactionState = TcConnectionrec::SCAN_STATE_USED;
11300  scanptr.i = tcConnectptr.p->tcScanRec;
11301  c_scanRecordPool.getPtr(scanptr);
11302 
11303  Uint32 rows = scanptr.p->m_curr_batch_size_rows;
11304  Uint32 accOpPtr= get_acc_ptr_from_scan_record(scanptr.p, rows, false);
11305  if (accOpPtr != (Uint32)-1)
11306  {
11307  c_acc->execACCKEY_ORD(signal, accOpPtr);
11308  }
11309  else
11310  {
11311  ndbassert(refToBlock(scanptr.p->scanBlockref) != DBACC);
11312  }
11313 
11314  if (scanptr.p->scanCompletedStatus == ZTRUE) {
11315  /* ---------------------------------------------------------------------
11316  * STOP THE SCAN PROCESS IF THIS HAS BEEN REQUESTED.
11317  * --------------------------------------------------------------------- */
11318  if ((scanptr.p->scanLockHold == ZTRUE) && rows)
11319  {
11320  jam();
11321  scanptr.p->scanReleaseCounter = 1;
11322  scanReleaseLocksLab(signal);
11323  return;
11324  }//if
11325  jam();
11326  closeScanLab(signal);
11327  return;
11328  }//if
11329  if ((terrorCode != ZSEARCH_CONDITION_FALSE) &&
11330  (terrorCode != ZNO_TUPLE_FOUND) &&
11331  (terrorCode >= ZUSER_ERROR_CODE_LIMIT)) {
11332  scanptr.p->scanErrorCounter++;
11333  tcConnectptr.p->errorCode = terrorCode;
11334 
11335  if (scanptr.p->scanLockHold == ZTRUE) {
11336  jam();
11337  scanptr.p->scanReleaseCounter = 1;
11338  } else {
11339  jam();
11340  scanptr.p->m_curr_batch_size_rows = rows + 1;
11341  scanptr.p->scanReleaseCounter = rows + 1;
11342  }//if
11343  /* --------------------------------------------------------------------
11344  * WE NEED TO RELEASE ALL LOCKS CURRENTLY
11345  * HELD BY THIS SCAN.
11346  * -------------------------------------------------------------------- */
11347  scanReleaseLocksLab(signal);
11348  return;
11349  }//if
11350  Uint32 time_passed= tcConnectptr.p->tcTimer - cLqhTimeOutCount;
11351  if (rows)
11352  {
11353  if (time_passed > 1)
11354  {
11355  /* -----------------------------------------------------------------------
11356  * WE NEED TO ENSURE THAT WE DO NOT SEARCH FOR THE NEXT TUPLE FOR A
11357  * LONG TIME WHILE WE KEEP A LOCK ON A FOUND TUPLE. WE RATHER REPORT
11358  * THE FOUND TUPLE IF FOUND TUPLES ARE RARE. If more than 10 ms passed we
11359  * send the found tuples to the API.
11360  * ----------------------------------------------------------------------- */
11361  scanptr.p->scanReleaseCounter = rows + 1;
11362  scanReleaseLocksLab(signal);
11363  return;
11364  }
11365  }
11366 
11367  scanptr.p->scanFlag = NextScanReq::ZSCAN_NEXT_ABORT;
11368  scanNextLoopLab(signal);
11369 }//Dblqh::scanTupkeyRefLab()
11370 
11371 /* -------------------------------------------------------------------------
11372  * THE SCAN HAS BEEN COMPLETED. EITHER BY REACHING THE END OR BY COMMAND
11373  * FROM THE APPLICATION OR BY SOME SORT OF ERROR CONDITION.
11374  * ------------------------------------------------------------------------- */
11375 void Dblqh::closeScanLab(Signal* signal)
11376 {
11377  fragptr.i = tcConnectptr.p->fragmentptr;
11378  c_fragment_pool.getPtr(fragptr);
11379  switch (fragptr.p->fragStatus) {
11380  case Fragrecord::FSACTIVE:
11381  jam();
11382  break;
11383  case Fragrecord::BLOCKED:
11384  jam();
11385  linkFragQueue(signal);
11386  tcConnectptr.p->transactionState = TcConnectionrec::SCAN_CLOSE_STOPPED;
11387  return;
11388  break;
11389  case Fragrecord::FREE:
11390  jam();
11392  jam();
11394  jam();
11395  case Fragrecord::DEFINED:
11396  jam();
11397  case Fragrecord::REMOVING:
11398  jam();
11399  default:
11400  ndbrequire(false);
11401  }//switch
11402  continueCloseScanAfterBlockedLab(signal);
11403 }//Dblqh::closeScanLab()
11404 
11405 void Dblqh::continueCloseScanAfterBlockedLab(Signal* signal)
11406 {
11407  tcConnectptr.p->transactionState = TcConnectionrec::SCAN_STATE_USED;
11408  scanptr.i = tcConnectptr.p->tcScanRec;
11409  c_scanRecordPool.getPtr(scanptr);
11410  scanptr.p->scanState = ScanRecord::WAIT_CLOSE_SCAN;
11411  signal->theData[0] = scanptr.p->scanAccPtr;
11412  signal->theData[1] = RNIL;
11413  signal->theData[2] = NextScanReq::ZSCAN_CLOSE;
11414  sendSignal(scanptr.p->scanBlockref, GSN_NEXT_SCANREQ, signal, 3, JBB);
11415 }//Dblqh::continueCloseScanAfterBlockedLab()
11416 
11417 /* -------------------------------------------------------------------------
11418  * ENTER NEXT_SCANCONF
11419  * -------------------------------------------------------------------------
11420  * PRECONDITION: SCAN_STATE = WAIT_CLOSE_SCAN
11421  * ------------------------------------------------------------------------- */
11422 void Dblqh::accScanCloseConfLab(Signal* signal)
11423 {
11424  tcConnectptr.i = scanptr.p->scanTcrec;
11425  ptrCheckGuard(tcConnectptr, ctcConnectrecFileSize, tcConnectionrec);
11426 
11427  /* Do we have another range to scan? */
11428  if((tcConnectptr.p->primKeyLen > 0) &&
11429  (scanptr.p->scanCompletedStatus != ZTRUE))
11430  {
11431  jam();
11432  /* Start next range scan...*/
11433  continueAfterReceivingAllAiLab(signal);
11434  return;
11435  }
11436 
11437  scanptr.p->scanState = ScanRecord::WAIT_DELETE_STORED_PROC_ID_SCAN;
11438  signal->theData[0] = tcConnectptr.p->tupConnectrec;
11439  signal->theData[1] = tcConnectptr.p->tableref;
11440  signal->theData[2] = scanptr.p->scanSchemaVersion;
11441  signal->theData[3] = ZDELETE_STORED_PROC_ID;
11442  signal->theData[4] = scanptr.p->scanStoredProcId;
11443  signal->theData[5] = scanptr.p->scanApiBlockref;
11444  sendSignal(tcConnectptr.p->tcTupBlockref,
11445  GSN_STORED_PROCREQ, signal, 6, JBB);
11446 }//Dblqh::accScanCloseConfLab()
11447 
11448 /* -------------------------------------------------------------------------
11449  * ENTER STORED_PROCCONF WITH
11450  * -------------------------------------------------------------------------
11451  * PRECONDITION: SCAN_STATE = WAIT_DELETE_STORED_PROC_ID_SCAN
11452  * ------------------------------------------------------------------------- */
11453 void Dblqh::tupScanCloseConfLab(Signal* signal)
11454 {
11455  fragptr.i = tcConnectptr.p->fragmentptr;
11456  c_fragment_pool.getPtr(fragptr);
11457  if (tcConnectptr.p->abortState == TcConnectionrec::NEW_FROM_TC) {
11458  jam();
11459  tcNodeFailptr.i = tcConnectptr.p->tcNodeFailrec;
11460  ptrCheckGuard(tcNodeFailptr, ctcNodeFailrecFileSize, tcNodeFailRecord);
11461  tcNodeFailptr.p->tcRecNow = tcConnectptr.i + 1;
11462  signal->theData[0] = ZLQH_TRANS_NEXT;
11463  signal->theData[1] = tcNodeFailptr.i;
11464  sendSignal(cownref, GSN_CONTINUEB, signal, 2, JBB);
11465  } else if (tcConnectptr.p->errorCode != 0) {
11466  jam();
11467  ScanFragRef * ref = (ScanFragRef*)&signal->theData[0];
11468  ref->senderData = tcConnectptr.p->clientConnectrec;
11469  ref->transId1 = tcConnectptr.p->transid[0];
11470  ref->transId2 = tcConnectptr.p->transid[1];
11471  ref->errorCode = tcConnectptr.p->errorCode;
11472  sendSignal(tcConnectptr.p->clientBlockref, GSN_SCAN_FRAGREF, signal,
11473  ScanFragRef::SignalLength, JBB);
11474  } else {
11475  jam();
11476  sendScanFragConf(signal, ZSCAN_FRAG_CLOSED);
11477  }//if
11478  finishScanrec(signal);
11479  releaseScanrec(signal);
11480  tcConnectptr.p->tcScanRec = RNIL;
11481  deleteTransidHash(signal);
11482  releaseOprec(signal);
11483  releaseTcrec(signal, tcConnectptr);
11484 }//Dblqh::tupScanCloseConfLab()
11485 
11486 /* =========================================================================
11487  * ======= INITIATE SCAN RECORD =======
11488  *
11489  * SUBROUTINE SHORT NAME = ISC
11490  * ========================================================================= */
11491 Uint32 Dblqh::initScanrec(const ScanFragReq* scanFragReq,
11492  Uint32 aiLen)
11493 {
11494  const Uint32 reqinfo = scanFragReq->requestInfo;
11495  const Uint32 max_rows = scanFragReq->batch_size_rows;
11496  const Uint32 max_bytes = scanFragReq->batch_size_bytes;
11497  const Uint32 scanLockMode = ScanFragReq::getLockMode(reqinfo);
11498  const Uint32 scanLockHold = ScanFragReq::getHoldLockFlag(reqinfo);
11499  const Uint32 keyinfo = ScanFragReq::getKeyinfoFlag(reqinfo);
11500  const Uint32 readCommitted = ScanFragReq::getReadCommittedFlag(reqinfo);
11501  const Uint32 rangeScan = ScanFragReq::getRangeScanFlag(reqinfo);
11502  const Uint32 descending = ScanFragReq::getDescendingFlag(reqinfo);
11503  Uint32 tupScan = ScanFragReq::getTupScanFlag(reqinfo);
11504  const Uint32 scanPrio = ScanFragReq::getScanPrio(reqinfo);
11505  const Uint32 accScan = (rangeScan == 0) && (tupScan == 0);
11506 
11507  scanptr.p->scanKeyinfoFlag = keyinfo;
11508  scanptr.p->scanLockHold = scanLockHold;
11509  scanptr.p->scanCompletedStatus = ZFALSE;
11510  scanptr.p->scanType = ScanRecord::SCAN;
11511  scanptr.p->scanApiBlockref = scanFragReq->resultRef;
11512  scanptr.p->scanAiLength = aiLen;
11513  scanptr.p->scanTcrec = tcConnectptr.i;
11514  scanptr.p->scanSchemaVersion = scanFragReq->schemaVersion;
11515 
11516  scanptr.p->m_curr_batch_size_rows = 0;
11517  scanptr.p->m_curr_batch_size_bytes= 0;
11518  scanptr.p->m_max_batch_size_rows = max_rows;
11519  scanptr.p->m_max_batch_size_bytes = max_bytes;
11520 
11521  if (accScan)
11522  scanptr.p->scanBlockref = tcConnectptr.p->tcAccBlockref;
11523  else if (! tupScan)
11524  scanptr.p->scanBlockref = tcConnectptr.p->tcTuxBlockref;
11525  else
11526  scanptr.p->scanBlockref = tcConnectptr.p->tcTupBlockref;
11527 
11528  scanptr.p->scanErrorCounter = 0;
11529  scanptr.p->scanLockMode = scanLockMode;
11530  scanptr.p->readCommitted = readCommitted;
11531  scanptr.p->rangeScan = rangeScan;
11532  scanptr.p->descending = descending;
11533  scanptr.p->tupScan = tupScan;
11534  scanptr.p->lcpScan = ScanFragReq::getLcpScanFlag(reqinfo);
11535  scanptr.p->statScan = ScanFragReq::getStatScanFlag(reqinfo);
11536  scanptr.p->scanState = ScanRecord::SCAN_FREE;
11537  scanptr.p->scanFlag = ZFALSE;
11538  scanptr.p->m_row_id.setNull();
11539  scanptr.p->scanTcWaiting = cLqhTimeOutCount;
11540  scanptr.p->scanNumber = ~0;
11541  scanptr.p->scanApiOpPtr = scanFragReq->clientOpPtr;
11542  scanptr.p->m_last_row = 0;
11543  scanptr.p->scanStoredProcId = RNIL;
11544  scanptr.p->copyPtr = RNIL;
11545  if (max_rows == 0 || (max_bytes > 0 && max_rows > max_bytes)){
11546  jam();
11547  return ScanFragRef::ZWRONG_BATCH_SIZE;
11548  }
11549 
11550  if (ERROR_INSERTED(5057))
11551  {
11552  CLEAR_ERROR_INSERT_VALUE;
11553  return ScanFragRef::ZTOO_MANY_ACTIVE_SCAN_ERROR;
11554  }
11555 
11556  scanptr.p->scan_acc_segments = 0;
11557  if (!seize_acc_ptr_list(scanptr.p, 0, max_rows)){
11558  jam();
11559  return ScanFragRef::ZTOO_MANY_ACTIVE_SCAN_ERROR;
11560  }
11561  init_acc_ptr_list(scanptr.p);
11562 
11566  FragrecordPtr tFragPtr;
11567  tFragPtr.i = fragptr.p->tableFragptr;
11568  c_fragment_pool.getPtr(tFragPtr);
11569  scanptr.p->fragPtrI = fragptr.p->tableFragptr;
11570 
11586  Uint32 start, stop;
11587  Uint32 max_parallel_scans_per_frag = c_max_parallel_scans_per_frag;
11588  if (accScan)
11589  {
11590  start = 1;
11591  stop = MAX_PARALLEL_SCANS_PER_FRAG - 1;
11592  }
11593  else if (rangeScan)
11594  {
11595  start = MAX_PARALLEL_SCANS_PER_FRAG;
11596  stop = start + max_parallel_scans_per_frag - 1;
11597  }
11598  else
11599  {
11600  ndbassert(tupScan);
11601  start = MAX_PARALLEL_SCANS_PER_FRAG + max_parallel_scans_per_frag;
11602  stop = start + max_parallel_scans_per_frag - 1;
11603  }
11604  ndbrequire((start < 32 * tFragPtr.p->m_scanNumberMask.Size) &&
11605  (stop < 32 * tFragPtr.p->m_scanNumberMask.Size));
11606  Uint32 free = tFragPtr.p->m_scanNumberMask.find(start);
11607 
11608  if(free == Fragrecord::ScanNumberMask::NotFound || free >= stop){
11609  jam();
11610 
11611  if(scanPrio == 0){
11612  jam();
11613  return ScanFragRef::ZTOO_MANY_ACTIVE_SCAN_ERROR;
11614  }
11615 
11619  scanptr.p->scanState = ScanRecord::IN_QUEUE;
11620  LocalDLFifoList<ScanRecord> queue(c_scanRecordPool,
11621  tupScan == 0 ?
11622  fragptr.p->m_queuedScans :
11623  fragptr.p->m_queuedTupScans);
11624  queue.add(scanptr);
11625  return ZOK;
11626  }
11627 
11628  scanptr.p->scanNumber = free;
11629  tFragPtr.p->m_scanNumberMask.clear(free);// Update mask
11630 
11631  LocalDLList<ScanRecord> active(c_scanRecordPool, fragptr.p->m_activeScans);
11632  active.add(scanptr);
11633  if(scanptr.p->scanKeyinfoFlag){
11634  jam();
11635 #if defined VM_TRACE || defined ERROR_INSERT
11636  ScanRecordPtr tmp;
11637  ndbrequire(!c_scanTakeOverHash.find(tmp, * scanptr.p));
11638 #endif
11639 #ifdef TRACE_SCAN_TAKEOVER
11640  ndbout_c("adding (%d %d) table: %d fragId: %d frag.i: %d tableFragptr: %d",
11641  scanptr.p->scanNumber, scanptr.p->fragPtrI,
11642  tabptr.i, scanFragReq->fragmentNoKeyLen & 0xFFFF,
11643  fragptr.i, fragptr.p->tableFragptr);
11644 #endif
11645  c_scanTakeOverHash.add(scanptr);
11646  }
11647  return ZOK;
11648 }
11649 
11650 /* =========================================================================
11651  * ======= INITIATE TC RECORD AT SCAN =======
11652  *
11653  * SUBROUTINE SHORT NAME = IST
11654  * ========================================================================= */
11655 void Dblqh::initScanTc(const ScanFragReq* req,
11656  Uint32 transid1,
11657  Uint32 transid2,
11658  Uint32 fragId,
11659  Uint32 nodeId,
11660  Uint32 hashHi)
11661 {
11662  tcConnectptr.p->transid[0] = transid1;
11663  tcConnectptr.p->transid[1] = transid2;
11664  tcConnectptr.p->tcScanRec = scanptr.i;
11665  tcConnectptr.p->tableref = tabptr.i;
11666  tcConnectptr.p->fragmentid = fragId;
11667  tcConnectptr.p->fragmentptr = fragptr.i;
11668  tcConnectptr.p->tcOprec = tcConnectptr.p->clientConnectrec;
11669  tcConnectptr.p->tcHashKeyHi = hashHi;
11670  tcConnectptr.p->tcBlockref = tcConnectptr.p->clientBlockref;
11671  tcConnectptr.p->errorCode = 0;
11672  tcConnectptr.p->reclenAiLqhkey = 0;
11673  tcConnectptr.p->abortState = TcConnectionrec::ABORT_IDLE;
11674  tcConnectptr.p->nextReplica = nodeId;
11675  tcConnectptr.p->currTupAiLen = 0;
11676  tcConnectptr.p->opExec = 1;
11677  tcConnectptr.p->operation = ZREAD;
11678  tcConnectptr.p->listState = TcConnectionrec::NOT_IN_LIST;
11679  tcConnectptr.p->commitAckMarker = RNIL;
11680  tcConnectptr.p->m_scan_curr_range_no = 0;
11681  tcConnectptr.p->m_dealloc = 0;
11682  tcConnectptr.p->activeCreat = Fragrecord::AC_NORMAL;
11683  // set TcConnectionrec::OP_SAVEATTRINFO so that a
11684  // "old" scan (short signals) update currTupAiLen which is checked
11685  // in scanAttrinfoLab
11686  tcConnectptr.p->m_flags = TcConnectionrec::OP_SAVEATTRINFO;
11687  TablerecPtr tTablePtr;
11688  tTablePtr.i = tabptr.p->primaryTableId;
11689  ptrCheckGuard(tTablePtr, ctabrecFileSize, tablerec);
11690  tcConnectptr.p->m_disk_table = tTablePtr.p->m_disk_table &&
11691  (!req || !ScanFragReq::getNoDiskFlag(req->requestInfo));
11692  tcConnectptr.p->m_reorg =
11693  req ? ScanFragReq::getReorgFlag(req->requestInfo) : 0;
11694 
11695  tabptr.p->usageCountR++;
11696 }//Dblqh::initScanTc()
11697 
11698 /* =========================================================================
11699  * ======= FINISH SCAN RECORD =======
11700  *
11701  * REMOVE SCAN RECORD FROM PER FRAGMENT LIST.
11702  * ========================================================================= */
11703 void Dblqh::finishScanrec(Signal* signal)
11704 {
11705  release_acc_ptr_list(scanptr.p);
11706 
11707  Uint32 tupScan = scanptr.p->tupScan;
11708  LocalDLFifoList<ScanRecord> queue(c_scanRecordPool,
11709  tupScan == 0 ?
11710  fragptr.p->m_queuedScans :
11711  fragptr.p->m_queuedTupScans);
11712 
11713  if (scanptr.p->scanState == ScanRecord::IN_QUEUE)
11714  {
11715  jam();
11716  if (scanptr.p->m_reserved == 0)
11717  {
11718  jam();
11719  queue.release(scanptr);
11720  }
11721  else
11722  {
11723  jam();
11724  queue.remove(scanptr);
11725  m_reserved_scans.add(scanptr);
11726  }
11727 
11728  return;
11729  }
11730 
11731  if(scanptr.p->scanKeyinfoFlag){
11732  jam();
11733  ScanRecordPtr tmp;
11734 #ifdef TRACE_SCAN_TAKEOVER
11735  ndbout_c("removing (%d %d)", scanptr.p->scanNumber, scanptr.p->fragPtrI);
11736 #endif
11737  c_scanTakeOverHash.remove(tmp, * scanptr.p);
11738  ndbrequire(tmp.p == scanptr.p);
11739  }
11740 
11741  LocalDLList<ScanRecord> scans(c_scanRecordPool, fragptr.p->m_activeScans);
11742  if (scanptr.p->m_reserved == 0)
11743  {
11744  jam();
11745  scans.release(scanptr);
11746  }
11747  else
11748  {
11749  jam();
11750  scans.remove(scanptr);
11751  m_reserved_scans.add(scanptr);
11752  }
11753 
11754  FragrecordPtr tFragPtr;
11755  tFragPtr.i = scanptr.p->fragPtrI;
11756  c_fragment_pool.getPtr(tFragPtr);
11757 
11758  const Uint32 scanNumber = scanptr.p->scanNumber;
11759  ndbrequire(!tFragPtr.p->m_scanNumberMask.get(scanNumber));
11760  ScanRecordPtr restart;
11761 
11765  if(scanNumber == NR_ScanNo || !queue.first(restart)){
11766  jam();
11767  tFragPtr.p->m_scanNumberMask.set(scanNumber);
11768  return;
11769  }
11770 
11771  if(ERROR_INSERTED(5034)){
11772  jam();
11773  tFragPtr.p->m_scanNumberMask.set(scanNumber);
11774  return;
11775  }
11776 
11777  ndbrequire(restart.p->scanState == ScanRecord::IN_QUEUE);
11778 
11779  ScanRecordPtr tmpScan = scanptr;
11780  TcConnectionrecPtr tmpTc = tcConnectptr;
11781 
11782  tcConnectptr.i = restart.p->scanTcrec;
11783  ptrCheckGuard(tcConnectptr, ctcConnectrecFileSize, tcConnectionrec);
11784  restart.p->scanNumber = scanNumber;
11785 
11786  queue.remove(restart);
11787  scans.add(restart);
11788  if(restart.p->scanKeyinfoFlag){
11789  jam();
11790 #if defined VM_TRACE || defined ERROR_INSERT
11791  ScanRecordPtr tmp;
11792  ndbrequire(!c_scanTakeOverHash.find(tmp, * restart.p));
11793 #endif
11794  c_scanTakeOverHash.add(restart);
11795 #ifdef TRACE_SCAN_TAKEOVER
11796  ndbout_c("adding-r (%d %d)", restart.p->scanNumber, restart.p->fragPtrI);
11797 #endif
11798  }
11799 
11803  restart.p->scanState = ScanRecord::SCAN_FREE;
11804  if(tcConnectptr.p->transactionState == TcConnectionrec::SCAN_STATE_USED)
11805  {
11806  scanptr = restart;
11807  continueAfterReceivingAllAiLab(signal);
11808  }
11809  else
11810  {
11811  ndbrequire(tcConnectptr.p->transactionState == TcConnectionrec::WAIT_SCAN_AI);
11812  }
11813 
11814  scanptr = tmpScan;
11815  tcConnectptr = tmpTc;
11816 }//Dblqh::finishScanrec()
11817 
11818 /* =========================================================================
11819  * ======= RELEASE SCAN RECORD =======
11820  *
11821  * RELEASE A SCAN RECORD TO THE FREELIST.
11822  * ========================================================================= */
11823 void Dblqh::releaseScanrec(Signal* signal)
11824 {
11825  scanptr.p->scanState = ScanRecord::SCAN_FREE;
11826  scanptr.p->scanType = ScanRecord::ST_IDLE;
11827  scanptr.p->scanTcWaiting = 0;
11828  cbookedAccOps -= scanptr.p->m_max_batch_size_rows;
11829 }//Dblqh::releaseScanrec()
11830 
11831 /* ------------------------------------------------------------------------
11832  * ------- SEND KEYINFO20 TO API -------
11833  *
11834  * ------------------------------------------------------------------------ */
11835 Uint32 Dblqh::sendKeyinfo20(Signal* signal,
11836  ScanRecord * scanP,
11837  TcConnectionrec * tcConP)
11838 {
11839  ndbrequire(scanP->m_curr_batch_size_rows < MAX_PARALLEL_OP_PER_SCAN);
11840  KeyInfo20 * keyInfo = (KeyInfo20 *)&signal->theData[0];
11841 
11846  const BlockReference ref = scanP->scanApiBlockref;
11847  const Uint32 scanOp = scanP->m_curr_batch_size_rows;
11848  Uint32 nodeId = refToNode(ref);
11849  const bool connectedToNode = getNodeInfo(nodeId).m_connected;
11850 #ifdef NOT_USED
11851  const Uint32 type = getNodeInfo(nodeId).m_type;
11852  const bool is_api= (type >= NodeInfo::API && type <= NodeInfo::REP);
11853  const bool old_dest= (getNodeInfo(nodeId).m_version < MAKE_VERSION(3,5,0));
11854 #endif
11855  const bool longable = true; // TODO is_api && !old_dest;
11856 
11857  Uint32 * dst = keyInfo->keyData;
11858  dst += nodeId == getOwnNodeId() ? 0 : KeyInfo20::DataLength;
11859 
11867  Uint32 keyLen ;
11868  if (refToMain(ref) == SUMA && nodeId == getOwnNodeId())
11869  {
11870  keyLen = 0;
11871  }
11872  else
11873  {
11874  keyLen = readPrimaryKeys(scanP, tcConP, dst);
11875  }
11876 
11877  Uint32 fragId = tcConP->fragmentid;
11878  keyInfo->clientOpPtr = scanP->scanApiOpPtr;
11879  keyInfo->keyLen = keyLen;
11880  keyInfo->scanInfo_Node =
11881  KeyInfo20::setScanInfo(scanOp, scanP->scanNumber) + (fragId << 20);
11882  keyInfo->transId1 = tcConP->transid[0];
11883  keyInfo->transId2 = tcConP->transid[1];
11884 
11885  Uint32 * src = signal->theData+25;
11886  if(connectedToNode)
11887  {
11888  jam();
11889 
11890  if (isNdbMtLqh() && instance() != refToInstance(ref))
11891  {
11892  jam();
11893  nodeId = 0; // prevent execute direct
11894  }
11895  if (nodeId == getOwnNodeId())
11896  {
11897  EXECUTE_DIRECT(refToBlock(ref), GSN_KEYINFO20, signal,
11898  KeyInfo20::HeaderLength + keyLen);
11899  jamEntry();
11900  return keyLen;
11901  }
11902  else
11903  {
11904  if(keyLen <= KeyInfo20::DataLength || !longable) {
11905  while(keyLen > KeyInfo20::DataLength){
11906  jam();
11907  MEMCOPY_NO_WORDS(keyInfo->keyData, src, KeyInfo20::DataLength);
11908  sendSignal(ref, GSN_KEYINFO20, signal, 25, JBB);
11909  src += KeyInfo20::DataLength;;
11910  keyLen -= KeyInfo20::DataLength;
11911  }
11912 
11913  MEMCOPY_NO_WORDS(keyInfo->keyData, src, keyLen);
11914  sendSignal(ref, GSN_KEYINFO20, signal,
11915  KeyInfo20::HeaderLength+keyLen, JBB);
11916  return keyLen;
11917  }
11918 
11919  LinearSectionPtr ptr[3];
11920  ptr[0].p = src;
11921  ptr[0].sz = keyLen;
11922  sendSignal(ref, GSN_KEYINFO20, signal, KeyInfo20::HeaderLength,
11923  JBB, ptr, 1);
11924  return keyLen;
11925  }
11926  }
11927 
11933  Uint32 routeBlockref = tcConP->clientBlockref;
11934 
11935  if(keyLen < KeyInfo20::DataLength || !longable){
11936  jam();
11937 
11938  while (keyLen > (KeyInfo20::DataLength - 1)) {
11939  jam();
11940  MEMCOPY_NO_WORDS(keyInfo->keyData, src, KeyInfo20::DataLength - 1);
11941  keyInfo->keyData[KeyInfo20::DataLength-1] = ref;
11942  sendSignal(routeBlockref, GSN_KEYINFO20_R, signal, 25, JBB);
11943  src += KeyInfo20::DataLength - 1;
11944  keyLen -= KeyInfo20::DataLength - 1;
11945  }
11946 
11947  MEMCOPY_NO_WORDS(keyInfo->keyData, src, keyLen);
11948  keyInfo->keyData[keyLen] = ref;
11949  sendSignal(routeBlockref, GSN_KEYINFO20_R, signal,
11950  KeyInfo20::HeaderLength+keyLen+1, JBB);
11951  return keyLen;
11952  }
11953 
11954  keyInfo->keyData[0] = ref;
11955  LinearSectionPtr ptr[3];
11956  ptr[0].p = src;
11957  ptr[0].sz = keyLen;
11958  sendSignal(routeBlockref, GSN_KEYINFO20_R, signal,
11959  KeyInfo20::HeaderLength+1, JBB, ptr, 1);
11960  return keyLen;
11961 }
11962 
11963 /* ------------------------------------------------------------------------
11964  * ------- SEND SCAN_FRAGCONF TO TC THAT CONTROLS THE SCAN -------
11965  *
11966  * ------------------------------------------------------------------------ */
11967 void Dblqh::sendScanFragConf(Signal* signal, Uint32 scanCompleted)
11968 {
11969  Uint32 completed_ops= scanptr.p->m_curr_batch_size_rows;
11970  Uint32 total_len= scanptr.p->m_curr_batch_size_bytes;
11971  scanptr.p->scanTcWaiting = 0;
11972 
11973  if(ERROR_INSERTED(5037)){
11974  CLEAR_ERROR_INSERT_VALUE;
11975  return;
11976  }
11977  ScanFragConf * conf = (ScanFragConf*)&signal->theData[0];
11978 #ifdef NOT_USED
11979  NodeId tc_node_id= refToNode(tcConnectptr.p->clientBlockref);
11980 #endif
11981  Uint32 trans_id1= tcConnectptr.p->transid[0];
11982  Uint32 trans_id2= tcConnectptr.p->transid[1];
11983 
11984  conf->senderData = tcConnectptr.p->clientConnectrec;
11985  conf->completedOps = completed_ops;
11986  conf->fragmentCompleted = scanCompleted;
11987  conf->transId1 = trans_id1;
11988  conf->transId2 = trans_id2;
11989  conf->total_len= total_len;
11990  sendSignal(tcConnectptr.p->clientBlockref, GSN_SCAN_FRAGCONF,
11991  signal, ScanFragConf::SignalLength, JBB);
11992 
11993  if(!scanptr.p->scanLockHold)
11994  {
11995  jam();
11996  scanptr.p->m_curr_batch_size_rows = 0;
11997  scanptr.p->m_curr_batch_size_bytes= 0;
11998  }
11999 }//Dblqh::sendScanFragConf()
12000 
12001 /* ######################################################################### */
12002 /* ####### NODE RECOVERY MODULE ####### */
12003 /* */
12004 /* ######################################################################### */
12005 /*---------------------------------------------------------------------------*/
12006 /* */
12007 /* THIS MODULE IS USED WHEN A NODE HAS FAILED. IT PERFORMS A COPY OF A */
12008 /* FRAGMENT TO A NEW REPLICA OF THE FRAGMENT. IT DOES ALSO SHUT DOWN ALL */
12009 /* CONNECTIONS TO THE FAILED NODE. */
12010 /*---------------------------------------------------------------------------*/
12011 Uint32
12012 Dblqh::calculateHash(Uint32 tableId, const Uint32* src)
12013 {
12014  jam();
12015  Uint64 Tmp[(MAX_KEY_SIZE_IN_WORDS*MAX_XFRM_MULTIPLY) >> 1];
12016  Uint32 keyPartLen[MAX_ATTRIBUTES_IN_INDEX];
12017  Uint32 keyLen = xfrm_key(tableId, src, (Uint32*)Tmp, sizeof(Tmp) >> 2,
12018  keyPartLen);
12019  ndbrequire(keyLen);
12020 
12021  return md5_hash(Tmp, keyLen);
12022 }//Dblqh::calculateHash()
12023 
12027 void
12028 Dblqh::execPREPARE_COPY_FRAG_REQ(Signal* signal)
12029 {
12030  jamEntry();
12031  PrepareCopyFragReq req = *(PrepareCopyFragReq*)signal->getDataPtr();
12032 
12033  CRASH_INSERTION(5045);
12034 
12035  tabptr.i = req.tableId;
12036  ptrCheckGuard(tabptr, ctabrecFileSize, tablerec);
12037 
12038  Uint32 max_page = RNIL;
12039 
12040  if (getOwnNodeId() != req.startingNodeId)
12041  {
12042  jam();
12048  ndbrequire(getOwnNodeId() == req.copyNodeId);
12049  c_tup->get_frag_info(req.tableId, req.fragId, &max_page);
12050 
12051  PrepareCopyFragConf* conf = (PrepareCopyFragConf*)signal->getDataPtrSend();
12052  conf->senderData = req.senderData;
12053  conf->senderRef = reference();
12054  conf->tableId = req.tableId;
12055  conf->fragId = req.fragId;
12056  conf->copyNodeId = req.copyNodeId;
12057  conf->startingNodeId = req.startingNodeId;
12058  conf->maxPageNo = max_page;
12059  sendSignal(req.senderRef, GSN_PREPARE_COPY_FRAG_CONF,
12060  signal, PrepareCopyFragConf::SignalLength, JBB);
12061 
12062  return;
12063  }
12064 
12065  if (! DictTabInfo::isOrderedIndex(tabptr.p->tableType))
12066  {
12067  jam();
12068  ndbrequire(getFragmentrec(signal, req.fragId));
12069 
12073  if (cstartType == NodeState::ST_SYSTEM_RESTART)
12074  {
12075  jam();
12076  signal->theData[0] = fragptr.p->tabRef;
12077  signal->theData[1] = fragptr.p->fragId;
12078  BlockReference accRef = calcInstanceBlockRef(DBACC);
12079  sendSignal(accRef, GSN_EXPANDCHECK2, signal, 2, JBB);
12080  }
12081 
12082 
12086  fragptr.p->m_copy_started_state = Fragrecord::AC_IGNORED;
12088  fragptr.p->logFlag = Fragrecord::STATE_FALSE;
12089 
12090  c_tup->get_frag_info(req.tableId, req.fragId, &max_page);
12091  }
12092 
12093  PrepareCopyFragConf* conf = (PrepareCopyFragConf*)signal->getDataPtrSend();
12094  conf->senderData = req.senderData;
12095  conf->senderRef = reference();
12096  conf->tableId = req.tableId;
12097  conf->fragId = req.fragId;
12098  conf->copyNodeId = req.copyNodeId;
12099  conf->startingNodeId = req.startingNodeId;
12100  conf->maxPageNo = max_page;
12101  sendSignal(req.senderRef, GSN_PREPARE_COPY_FRAG_CONF,
12102  signal, PrepareCopyFragConf::SignalLength, JBB);
12103 }
12104 
12105 /* *************************************** */
12106 /* COPY_FRAGREQ: Start copying a fragment */
12107 /* *************************************** */
12108 void Dblqh::execCOPY_FRAGREQ(Signal* signal)
12109 {
12110  jamEntry();
12111  const CopyFragReq * const copyFragReq = (CopyFragReq *)&signal->theData[0];
12112  tabptr.i = copyFragReq->tableId;
12113  ptrCheckGuard(tabptr, ctabrecFileSize, tablerec);
12114  Uint32 i;
12115  const Uint32 fragId = copyFragReq->fragId;
12116  const Uint32 copyPtr = copyFragReq->userPtr;
12117  const Uint32 userRef = copyFragReq->userRef;
12118  const Uint32 nodeId = copyFragReq->nodeId;
12119  const Uint32 gci = copyFragReq->gci;
12120 
12121  ndbrequire(cnoActiveCopy < 3);
12122  ndbrequire(getFragmentrec(signal, fragId));
12123  ndbrequire(fragptr.p->copyFragState == ZIDLE);
12124  ndbrequire(cfirstfreeTcConrec != RNIL);
12125  ndbrequire(fragptr.p->m_scanNumberMask.get(NR_ScanNo));
12126 
12127  Uint32 checkversion = NDB_VERSION >= MAKE_VERSION(5,1,0) ?
12128  NDBD_UPDATE_FRAG_DIST_KEY_51 : NDBD_UPDATE_FRAG_DIST_KEY_50;
12129 
12130  Uint32 nodeCount = copyFragReq->nodeCount;
12131  NdbNodeBitmask nodemask;
12132  if (getNodeInfo(refToNode(userRef)).m_version >= checkversion)
12133  {
12134  ndbrequire(nodeCount <= MAX_REPLICAS);
12135  for (i = 0; i<nodeCount; i++)
12136  nodemask.set(copyFragReq->nodeList[i]);
12137  }
12138  Uint32 maxPage = copyFragReq->nodeList[nodeCount];
12139  Uint32 version = getNodeInfo(refToNode(userRef)).m_version;
12140  Uint32 requestInfo = copyFragReq->nodeList[nodeCount + 1];
12141  if (ndb_check_prep_copy_frag_version(version) < 2)
12142  {
12143  jam();
12144  maxPage = RNIL;
12145  }
12146 
12147  if (signal->getLength() < CopyFragReq::SignalLength + nodeCount)
12148  {
12149  jam();
12150  requestInfo = CopyFragReq::CFR_TRANSACTIONAL;
12151  }
12152 
12153  if (requestInfo == CopyFragReq::CFR_NON_TRANSACTIONAL)
12154  {
12155  jam();
12156  }
12157  else
12158  {
12159  fragptr.p->fragDistributionKey = copyFragReq->distributionKey;
12160  }
12161  Uint32 key = fragptr.p->fragDistributionKey;
12162 
12163  if (DictTabInfo::isOrderedIndex(tabptr.p->tableType)) {
12164  jam();
12168  CopyFragConf * const conf = (CopyFragConf *)&signal->theData[0];
12169  conf->userPtr = copyPtr;
12170  conf->sendingNodeId = cownNodeid;
12171  conf->startingNodeId = nodeId;
12172  conf->tableId = tabptr.i;
12173  conf->fragId = fragId;
12174  sendSignal(userRef, GSN_COPY_FRAGCONF, signal,
12175  CopyFragConf::SignalLength, JBB);
12176  return;
12177  }//if
12178 
12179  LocalDLList<ScanRecord> scans(c_scanRecordPool, fragptr.p->m_activeScans);
12180  ndbrequire(m_reserved_scans.first(scanptr));
12181  m_reserved_scans.remove(scanptr);
12182  scans.add(scanptr);
12183 
12184 /* ------------------------------------------------------------------------- */
12185 // We keep track of how many operation records in ACC that has been booked.
12186 // Copy fragment has records always booked and thus need not book any. The
12187 // most operations in parallel use is the m_max_batch_size_rows.
12188 // This variable has to be set-up here since it is used by releaseScanrec
12189 // to unbook operation records in ACC.
12190 /* ------------------------------------------------------------------------- */
12191  scanptr.p->m_max_batch_size_rows = 0;
12192  scanptr.p->rangeScan = 0;
12193  scanptr.p->tupScan = 0;
12194  seizeTcrec();
12195  tcConnectptr.p->clientBlockref = userRef;
12196 
12200  //initCopyrec(signal);
12201  scanptr.p->copyPtr = copyPtr;
12202  scanptr.p->scanType = ScanRecord::COPY;
12203  scanptr.p->scanNodeId = nodeId;
12204  scanptr.p->scanTcrec = tcConnectptr.i;
12205  scanptr.p->scanSchemaVersion = copyFragReq->schemaVersion;
12206  scanptr.p->scanCompletedStatus = ZFALSE;
12207  scanptr.p->scanErrorCounter = 0;
12208  scanptr.p->scanNumber = NR_ScanNo;
12209  scanptr.p->scanKeyinfoFlag = 0; // Don't put into hash
12210  scanptr.p->fragPtrI = fragptr.i;
12211  scanptr.p->scanApiOpPtr = tcConnectptr.i;
12212  scanptr.p->scanApiBlockref = reference();
12213  fragptr.p->m_scanNumberMask.clear(NR_ScanNo);
12214  scanptr.p->scanBlockref = ctupBlockref;
12215  scanptr.p->scanLockHold = ZFALSE;
12216  scanptr.p->m_curr_batch_size_rows = 0;
12217  scanptr.p->m_curr_batch_size_bytes= 0;
12218  scanptr.p->readCommitted = 0;
12219 
12220  initScanTc(0,
12221  0,
12222  (DBLQH << 20) + (cownNodeid << 8),
12223  fragId,
12224  copyFragReq->nodeId,
12225  0);
12226  cactiveCopy[cnoActiveCopy] = fragptr.i;
12227  cnoActiveCopy++;
12228 
12229  tcConnectptr.p->copyCountWords = 0;
12230  tcConnectptr.p->tcOprec = tcConnectptr.i;
12231  tcConnectptr.p->tcHashKeyHi = 0;
12232  tcConnectptr.p->schemaVersion = scanptr.p->scanSchemaVersion;
12233  tcConnectptr.p->savePointId = gci;
12234  tcConnectptr.p->applRef = 0;
12235  tcConnectptr.p->transactionState = TcConnectionrec::SCAN_STATE_USED;
12236 
12237  scanptr.p->scanState = ScanRecord::WAIT_ACC_COPY;
12238  AccScanReq * req = (AccScanReq*)&signal->theData[0];
12239  req->senderData = scanptr.i;
12240  req->senderRef = cownref;
12241  req->tableId = tabptr.i;
12242  req->fragmentNo = fragId;
12243  req->requestInfo = 0;
12244 
12245  if (requestInfo == CopyFragReq::CFR_TRANSACTIONAL)
12246  {
12247  jam();
12252  AccScanReq::setLockMode(req->requestInfo, 0);
12253  AccScanReq::setReadCommittedFlag(req->requestInfo, 0);
12254  AccScanReq::setNRScanFlag(req->requestInfo, 1);
12255  AccScanReq::setNoDiskScanFlag(req->requestInfo, 1);
12256  }
12257  else
12258  {
12259  jam();
12264  AccScanReq::setLockMode(req->requestInfo, 0);
12265  AccScanReq::setReadCommittedFlag(req->requestInfo, 1);
12266  scanptr.p->readCommitted = 1;
12267  }
12268 
12269  req->transId1 = tcConnectptr.p->transid[0];
12270  req->transId2 = tcConnectptr.p->transid[1];
12271  req->savePointId = tcConnectptr.p->savePointId;
12272  req->maxPage = maxPage;
12273  sendSignal(scanptr.p->scanBlockref, GSN_ACC_SCANREQ, signal,
12274  AccScanReq::SignalLength + 1, JBB);
12275 
12276  if (! nodemask.isclear())
12277  {
12278  ndbrequire(nodemask.get(getOwnNodeId()));
12279  ndbrequire(nodemask.get(nodeId)); // cpy dest
12280  nodemask.clear(getOwnNodeId());
12281  nodemask.clear(nodeId);
12282 
12284  ord = (UpdateFragDistKeyOrd*)signal->getDataPtrSend();
12285  ord->tableId = tabptr.i;
12286  ord->fragId = fragId;
12287  ord->fragDistributionKey = key;
12288  i = 0;
12289  while ((i = nodemask.find(i+1)) != NdbNodeBitmask::NotFound)
12290  {
12291  if (getNodeInfo(i).m_version >= checkversion)
12292  sendSignal(calcInstanceBlockRef(number(), i),
12293  GSN_UPDATE_FRAG_DIST_KEY_ORD,
12294  signal, UpdateFragDistKeyOrd::SignalLength, JBB);
12295  }
12296  }
12297  return;
12298 }//Dblqh::execCOPY_FRAGREQ()
12299 
12300 void
12301 Dblqh::execUPDATE_FRAG_DIST_KEY_ORD(Signal * signal)
12302 {
12303  jamEntry();
12304  UpdateFragDistKeyOrd* ord =(UpdateFragDistKeyOrd*)signal->getDataPtr();
12305 
12306  tabptr.i = ord->tableId;
12307  ptrCheckGuard(tabptr, ctabrecFileSize, tablerec);
12308  ndbrequire(getFragmentrec(signal, ord->fragId));
12309  fragptr.p->fragDistributionKey = ord->fragDistributionKey;
12310 }
12311 
12312 void Dblqh::accScanConfCopyLab(Signal* signal)
12313 {
12314  AccScanConf * const accScanConf = (AccScanConf *)&signal->theData[0];
12315  tcConnectptr.i = scanptr.p->scanTcrec;
12316  ptrCheckGuard(tcConnectptr, ctcConnectrecFileSize, tcConnectionrec);
12317 /*--------------------------------------------------------------------------*/
12318 /* PRECONDITION: SCAN_STATE = WAIT_ACC_COPY */
12319 /*--------------------------------------------------------------------------*/
12320  if (accScanConf->flag == AccScanConf::ZEMPTY_FRAGMENT) {
12321  jam();
12322 /*---------------------------------------------------------------------------*/
12323 /* THE FRAGMENT WAS EMPTY. */
12324 /* REPORT SUCCESSFUL COPYING. */
12325 /*---------------------------------------------------------------------------*/
12326  tupCopyCloseConfLab(signal);
12327  return;
12328  }//if
12329  scanptr.p->scanAccPtr = accScanConf->accPtr;
12330  scanptr.p->scanState = ScanRecord::WAIT_STORED_PROC_COPY;
12331  signal->theData[0] = tcConnectptr.p->tupConnectrec;
12332  signal->theData[1] = tcConnectptr.p->tableref;
12333  signal->theData[2] = scanptr.p->scanSchemaVersion;
12334  signal->theData[3] = ZSTORED_PROC_COPY;
12335 // theData[4] is not used in TUP with ZSTORED_PROC_COPY
12336  signal->theData[5] = scanptr.p->scanApiBlockref;
12337  sendSignal(scanptr.p->scanBlockref, GSN_STORED_PROCREQ, signal, 6, JBB);
12338  return;
12339 }//Dblqh::accScanConfCopyLab()
12340 
12341 /*---------------------------------------------------------------------------*/
12342 /* ENTER STORED_PROCCONF WITH */
12343 /* TC_CONNECTPTR, */
12344 /* TSTORED_PROC_ID */
12345 /*---------------------------------------------------------------------------*/
12346 void Dblqh::storedProcConfCopyLab(Signal* signal)
12347 {
12348 /*---------------------------------------------------------------------------*/
12349 /* PRECONDITION: SCAN_STATE = WAIT_STORED_PROC_COPY */
12350 /*---------------------------------------------------------------------------*/
12351  fragptr.i = tcConnectptr.p->fragmentptr;
12352  c_fragment_pool.getPtr(fragptr);
12353  if (scanptr.p->scanCompletedStatus == ZTRUE) {
12354  jam();
12355 /*---------------------------------------------------------------------------*/
12356 /* THE COPY PROCESS HAVE BEEN COMPLETED, MOST LIKELY DUE TO A NODE FAILURE.*/
12357 /*---------------------------------------------------------------------------*/
12358  closeCopyLab(signal);
12359  return;
12360  }//if
12361  scanptr.i = tcConnectptr.p->tcScanRec;
12362  c_scanRecordPool.getPtr(scanptr);
12363  scanptr.p->scanState = ScanRecord::WAIT_NEXT_SCAN_COPY;
12364  switch (fragptr.p->fragStatus) {
12365  case Fragrecord::FSACTIVE:
12366  jam();
12367  break;
12368  case Fragrecord::BLOCKED:
12369  jam();
12370  linkFragQueue(signal);
12371  tcConnectptr.p->transactionState = TcConnectionrec::COPY_FIRST_STOPPED;
12372  return;
12373  break;
12374  case Fragrecord::FREE:
12375  jam();
12377  jam();
12379  jam();
12380  case Fragrecord::DEFINED:
12381  jam();
12382  case Fragrecord::REMOVING:
12383  jam();
12384  default:
12385  jam();
12386  systemErrorLab(signal, __LINE__);
12387  return;
12388  break;
12389  }//switch
12390  continueFirstCopyAfterBlockedLab(signal);
12391  return;
12392 }//Dblqh::storedProcConfCopyLab()
12393 
12394 void Dblqh::continueFirstCopyAfterBlockedLab(Signal* signal)
12395 {
12399  fragptr.p->m_copy_started_state = Fragrecord::AC_NR_COPY;
12400  if (ERROR_INSERTED(5714))
12401  {
12402  ndbout_c("Starting copy of tab: %u frag: %u",
12403  fragptr.p->tabRef, fragptr.p->fragId);
12404  }
12405 
12406  scanptr.i = tcConnectptr.p->tcScanRec;
12407  c_scanRecordPool.getPtr(scanptr);
12408 
12409  if (false && fragptr.p->tabRef > 4)
12410  {
12411  ndbout_c("STOPPING COPY X = [ %d %d %d %d ]",
12412  refToBlock(scanptr.p->scanBlockref),
12413  scanptr.p->scanAccPtr, RNIL, NextScanReq::ZSCAN_NEXT);
12414 
12418  return;
12419  }
12420 
12421  signal->theData[0] = scanptr.p->scanAccPtr;
12422  signal->theData[1] = RNIL;
12423  signal->theData[2] = NextScanReq::ZSCAN_NEXT;
12424  sendSignal(scanptr.p->scanBlockref, GSN_NEXT_SCANREQ, signal, 3, JBB);
12425  return;
12426 }//Dblqh::continueFirstCopyAfterBlockedLab()
12427 
12428 /*---------------------------------------------------------------------------*/
12429 /* ENTER NEXT_SCANCONF WITH */
12430 /* SCANPTR, */
12431 /* TFRAGID, */
12432 /* TACC_OPPTR, */
12433 /* TLOCAL_KEY1, */
12434 /* TLOCAL_KEY2, */
12435 /* TKEY_LENGTH, */
12436 /* TKEY1, */
12437 /* TKEY2, */
12438 /* TKEY3, */
12439 /* TKEY4 */
12440 /*---------------------------------------------------------------------------*/
12441 /* PRECONDITION: SCAN_STATE = WAIT_NEXT_SCAN_COPY */
12442 /*---------------------------------------------------------------------------*/
12443 void Dblqh::nextScanConfCopyLab(Signal* signal)
12444 {
12445  NextScanConf * const nextScanConf = (NextScanConf *)&signal->theData[0];
12446  tcConnectptr.i = scanptr.p->scanTcrec;
12447  ptrCheckGuard(tcConnectptr, ctcConnectrecFileSize, tcConnectionrec);
12448  if (nextScanConf->fragId == RNIL) {
12449  jam();
12450 /*---------------------------------------------------------------------------*/
12451 /* THERE ARE NO MORE TUPLES TO FETCH. WE NEED TO CLOSE */
12452 /* THE COPY IN ACC AND DELETE THE STORED PROCEDURE IN TUP */
12453 /*---------------------------------------------------------------------------*/
12454  if (tcConnectptr.p->copyCountWords == 0) {
12455  closeCopyLab(signal);
12456  return;
12457  }//if
12458 /*---------------------------------------------------------------------------*/
12459 // Wait until copying is completed also at the starting node before reporting
12460 // completion. Signal completion through scanCompletedStatus-flag.
12461 /*---------------------------------------------------------------------------*/
12462  scanptr.p->scanCompletedStatus = ZTRUE;
12463  scanptr.p->scanState = ScanRecord::WAIT_LQHKEY_COPY;
12464  if (ERROR_INSERTED(5043))
12465  {
12466  CLEAR_ERROR_INSERT_VALUE;
12467  tcConnectptr.p->copyCountWords = ~0;
12468  signal->theData[0] = 9999;
12469  sendSignal(numberToRef(CMVMI, scanptr.p->scanNodeId),
12470  GSN_NDB_TAMPER, signal, 1, JBA);
12471  }
12472  return;
12473  }//if
12474 
12475  TcConnectionrec * tcConP = tcConnectptr.p;
12476 
12477  tcConP->m_use_rowid = true;
12478  tcConP->m_row_id = scanptr.p->m_row_id;
12479 
12480  scanptr.p->m_curr_batch_size_rows++;
12481 
12482  if (signal->getLength() == NextScanConf::SignalLengthNoKeyInfo)
12483  {
12484  jam();
12485  ndbrequire(nextScanConf->accOperationPtr == RNIL);
12486  initCopyTc(signal, ZDELETE);
12487  set_acc_ptr_in_scan_record(scanptr.p, 0, RNIL);
12488  tcConP->gci_hi = nextScanConf->gci;
12489  tcConP->gci_lo = 0;
12490 
12491  tcConP->primKeyLen = 0;
12492  tcConP->totSendlenAi = 0;
12493  tcConP->connectState = TcConnectionrec::COPY_CONNECTED;
12494 
12495 /*---------------------------------------------------------------------------*/
12496 // To avoid using up to many operation records in ACC we will increase the
12497 // constant to ensure that we never send more than 40 records at a time.
12498 // This is where the constant 56 comes from. For long records this constant
12499 // will not matter that much. The current maximum is 6000 words outstanding
12500 // (including a number of those 56 words not really sent). We also have to
12501 // ensure that there are never more simultaneous usage of these operation
12502 // records to ensure that node recovery does not fail because of simultaneous
12503 // scanning.
12504 /*---------------------------------------------------------------------------*/
12505  UintR TnoOfWords = 8;
12506  TnoOfWords = TnoOfWords + MAGIC_CONSTANT;
12507  TnoOfWords = TnoOfWords + (TnoOfWords >> 2);
12508 
12509  /*-----------------------------------------------------------------
12510  * NOTE for transid1!
12511  * Transid1 in the tcConnection record is used load regulate the
12512  * copy(node recovery) process.
12513  * The number of outstanding words are written in the transid1
12514  * variable. This will be sent to the starting node in the
12515  * LQHKEYREQ signal and when the answer is returned in the LQHKEYCONF
12516  * we can reduce the number of outstanding words and check to see
12517  * if more LQHKEYREQ signals should be sent.
12518  *
12519  * However efficient this method is rather unsafe in such way that
12520  * it overwrites the transid1 original data.
12521  *
12522  * Also see TR 587.
12523  *----------------------------------------------------------------*/
12524  tcConP->transid[0] = TnoOfWords; // Data overload, see note!
12525  packLqhkeyreqLab(signal);
12526  tcConP->copyCountWords += TnoOfWords;
12527  scanptr.p->scanState = ScanRecord::WAIT_LQHKEY_COPY;
12528  if (tcConP->copyCountWords < cmaxWordsAtNodeRec) {
12529  nextRecordCopy(signal);
12530  }
12531  return;
12532  }
12533  else
12534  {
12535  // If accOperationPtr == RNIL no record was returned by ACC
12536  if (nextScanConf->accOperationPtr == RNIL) {
12537  jam();
12538  signal->theData[0] = scanptr.p->scanAccPtr;
12539  signal->theData[1] = AccCheckScan::ZCHECK_LCP_STOP;
12540  sendSignal(scanptr.p->scanBlockref, GSN_ACC_CHECK_SCAN, signal, 2, JBB);
12541  return;
12542  }
12543 
12544  initCopyTc(signal, ZINSERT);
12545  set_acc_ptr_in_scan_record(scanptr.p, 0, nextScanConf->accOperationPtr);
12546 
12547  Fragrecord* fragPtrP= fragptr.p;
12548  scanptr.p->scanState = ScanRecord::WAIT_TUPKEY_COPY;
12549  tcConP->transactionState = TcConnectionrec::COPY_TUPKEY;
12550  if(tcConP->m_disk_table)
12551  {
12552  next_scanconf_load_diskpage(signal, scanptr, tcConnectptr,fragPtrP);
12553  }
12554  else
12555  {
12556  next_scanconf_tupkeyreq(signal, scanptr, tcConP, fragPtrP, RNIL);
12557  }
12558  }
12559 }//Dblqh::nextScanConfCopyLab()
12560 
12561 
12562 /*---------------------------------------------------------------------------*/
12563 /* USED IN COPYING OPERATION TO RECEIVE ATTRINFO FROM TUP. */
12564 /*---------------------------------------------------------------------------*/
12565 /* ************>> */
12566 /* TRANSID_AI > */
12567 /* ************>> */
12568 void Dblqh::execTRANSID_AI(Signal* signal)
12569 {
12570  jamEntry();
12571  /* TransID_AI received from local TUP, data is linear inline in
12572  * signal buff
12573  */
12574  tcConnectptr.i = signal->theData[0];
12575  ptrCheckGuard(tcConnectptr, ctcConnectrecFileSize, tcConnectionrec);
12576  Uint32 length = signal->length() - TransIdAI::HeaderLength;
12577  ndbrequire(tcConnectptr.p->transactionState == TcConnectionrec::COPY_TUPKEY);
12578  Uint32 * src = &signal->theData[ TransIdAI::HeaderLength ];
12579  bool ok= appendToSection(tcConnectptr.p->attrInfoIVal,
12580  src,
12581  length);
12582  if (unlikely(! ok))
12583  {
12584  jam();
12585  tcConnectptr.p->errorCode = ZGET_ATTRINBUF_ERROR;
12586  }
12587 }//Dblqh::execTRANSID_AI()
12588 
12589 /*--------------------------------------------------------------------------*/
12590 /* ENTER TUPKEYCONF WITH */
12591 /* TC_CONNECTPTR, */
12592 /* TDATA2, */
12593 /* TDATA3, */
12594 /* TDATA4, */
12595 /* TDATA5 */
12596 /*--------------------------------------------------------------------------*/
12597 /* PRECONDITION: TRANSACTION_STATE = COPY_TUPKEY */
12598 /*--------------------------------------------------------------------------*/
12599 void Dblqh::copyTupkeyRefLab(Signal* signal)
12600 {
12601  //const TupKeyRef * tupKeyRef = (TupKeyRef *)signal->getDataPtr();
12602 
12603  scanptr.i = tcConnectptr.p->tcScanRec;
12604  c_scanRecordPool.getPtr(scanptr);
12605  ScanRecord* scanP = scanptr.p;
12606 
12607  if (scanP->readCommitted == 0)
12608  {
12609  jam();
12610  ndbrequire(false); // Should not be possibe...we read with lock
12611  }
12612  else
12613  {
12614  jam();
12621  ndbrequire(terrorCode == 626);
12622  }
12623 
12624  ndbrequire(scanptr.p->scanState == ScanRecord::WAIT_TUPKEY_COPY);
12625  if (tcConnectptr.p->errorCode != 0)
12626  {
12627  jam();
12628  closeCopyLab(signal);
12629  return;
12630  }
12631 
12632  if (scanptr.p->scanCompletedStatus == ZTRUE)
12633  {
12634  jam();
12635  closeCopyLab(signal);
12636  return;
12637  }
12638 
12639  ndbrequire(tcConnectptr.p->copyCountWords < cmaxWordsAtNodeRec);
12640  scanptr.p->scanState = ScanRecord::WAIT_LQHKEY_COPY;
12641  nextRecordCopy(signal);
12642 }
12643 
12644 void Dblqh::copyTupkeyConfLab(Signal* signal)
12645 {
12646  const TupKeyConf * const tupKeyConf = (TupKeyConf *)signal->getDataPtr();
12647 
12648  UintR readLength = tupKeyConf->readLength;
12649  Uint32 tableId = tcConnectptr.p->tableref;
12650  scanptr.i = tcConnectptr.p->tcScanRec;
12651  c_scanRecordPool.getPtr(scanptr);
12652  ScanRecord* scanP = scanptr.p;
12653 
12654  if (scanP->readCommitted == 0)
12655  {
12656  jam();
12657  Uint32 accOpPtr= get_acc_ptr_from_scan_record(scanP, 0, false);
12658  ndbassert(accOpPtr != (Uint32)-1);
12659  c_acc->execACCKEY_ORD(signal, accOpPtr);
12660  }
12661 
12662  if (tcConnectptr.p->errorCode != 0) {
12663  jam();
12664  closeCopyLab(signal);
12665  return;
12666  }//if
12667  if (scanptr.p->scanCompletedStatus == ZTRUE) {
12668  jam();
12669 /*---------------------------------------------------------------------------*/
12670 /* THE COPY PROCESS HAVE BEEN CLOSED. MOST LIKELY A NODE FAILURE. */
12671 /*---------------------------------------------------------------------------*/
12672  closeCopyLab(signal);
12673  return;
12674  }//if
12675  TcConnectionrec * tcConP = tcConnectptr.p;
12676  tcConnectptr.p->totSendlenAi = readLength;
12677  tcConnectptr.p->connectState = TcConnectionrec::COPY_CONNECTED;
12678 
12679  /* Read primary keys from TUP into signal buffer space
12680  * (used to get here via scan keyinfo)
12681  */
12682  Uint32* tmp = signal->getDataPtrSend()+24;
12683  Uint32 len= tcConnectptr.p->primKeyLen = readPrimaryKeys(scanP, tcConP, tmp);
12684 
12685  tcConP->gci_hi = tmp[len];
12686  tcConP->gci_lo = 0;
12687  // Calculate hash (no need to linearise key)
12688  if (g_key_descriptor_pool.getPtr(tableId)->hasCharAttr)
12689  {
12690  tcConnectptr.p->hashValue = calculateHash(tableId, tmp);
12691  }
12692  else
12693  {
12694  tcConnectptr.p->hashValue = md5_hash((Uint64*)tmp, len);
12695  }
12696 
12697  // Copy keyinfo into long section for LQHKEYREQ below
12698  if (unlikely(!keyinfoLab(tmp, len)))
12699  {
12700  /* Failed to store keyInfo, fail copy
12701  * This will result in a COPY_FRAGREF being sent to
12702  * the starting node, which will cause it to fail
12703  */
12704  scanptr.p->scanErrorCounter++;
12705  tcConP->errorCode= ZGET_DATAREC_ERROR;
12706  scanptr.p->scanCompletedStatus= ZTRUE;
12707 
12708  closeCopyLab(signal);
12709  return;
12710  }
12711 
12712  LqhKeyReq::setKeyLen(tcConP->reqinfo, len);
12713 
12714 /*---------------------------------------------------------------------------*/
12715 // To avoid using up to many operation records in ACC we will increase the
12716 // constant to ensure that we never send more than 40 records at a time.
12717 // This is where the constant 56 comes from. For long records this constant
12718 // will not matter that much. The current maximum is 6000 words outstanding
12719 // (including a number of those 56 words not really sent). We also have to
12720 // ensure that there are never more simultaneous usage of these operation
12721 // records to ensure that node recovery does not fail because of simultaneous
12722 // scanning.
12723 /*---------------------------------------------------------------------------*/
12724  UintR TnoOfWords = readLength + len;
12725  scanP->m_curr_batch_size_bytes += 4 * TnoOfWords;
12726  TnoOfWords = TnoOfWords + MAGIC_CONSTANT;
12727  TnoOfWords = TnoOfWords + (TnoOfWords >> 2);
12728 
12729  /*-----------------------------------------------------------------
12730  * NOTE for transid1!
12731  * Transid1 in the tcConnection record is used load regulate the
12732  * copy(node recovery) process.
12733  * The number of outstanding words are written in the transid1
12734  * variable. This will be sent to the starting node in the
12735  * LQHKEYREQ signal and when the answer is returned in the LQHKEYCONF
12736  * we can reduce the number of outstanding words and check to see
12737  * if more LQHKEYREQ signals should be sent.
12738  *
12739  * However efficient this method is rather unsafe in such way that
12740  * it overwrites the transid1 original data.
12741  *
12742  * Also see TR 587.
12743  *----------------------------------------------------------------*/
12744  tcConnectptr.p->transid[0] = TnoOfWords; // Data overload, see note!
12745  packLqhkeyreqLab(signal);
12746  tcConnectptr.p->copyCountWords += TnoOfWords;
12747  scanptr.p->scanState = ScanRecord::WAIT_LQHKEY_COPY;
12748  if (tcConnectptr.p->copyCountWords < cmaxWordsAtNodeRec) {
12749  nextRecordCopy(signal);
12750  return;
12751  }//if
12752  return;
12753 }//Dblqh::copyTupkeyConfLab()
12754 
12755 /*---------------------------------------------------------------------------*/
12756 /* ENTER LQHKEYCONF */
12757 /*---------------------------------------------------------------------------*/
12758 /* PRECONDITION: CONNECT_STATE = COPY_CONNECTED */
12759 /*---------------------------------------------------------------------------*/
12760 void Dblqh::copyCompletedLab(Signal* signal)
12761 {
12762  const LqhKeyConf * const lqhKeyConf = (LqhKeyConf *)signal->getDataPtr();
12763 
12764  ndbrequire(tcConnectptr.p->transid[1] == lqhKeyConf->transId2);
12765  scanptr.i = tcConnectptr.p->tcScanRec;
12766  c_scanRecordPool.getPtr(scanptr);
12767  if (tcConnectptr.p->copyCountWords >= cmaxWordsAtNodeRec) {
12768  tcConnectptr.p->copyCountWords -= lqhKeyConf->transId1; // Data overload, see note!
12769  if (scanptr.p->scanCompletedStatus == ZTRUE) {
12770  jam();
12771 /*---------------------------------------------------------------------------*/
12772 // Copy to complete, we will not start any new copying.
12773 /*---------------------------------------------------------------------------*/
12774  closeCopyLab(signal);
12775  return;
12776  }//if
12777  if (tcConnectptr.p->copyCountWords < cmaxWordsAtNodeRec) {
12778  jam();
12779  nextRecordCopy(signal);
12780  }//if
12781  return;
12782  }//if
12783  tcConnectptr.p->copyCountWords -= lqhKeyConf->transId1; // Data overload, see note!
12784  ndbrequire(tcConnectptr.p->copyCountWords <= cmaxWordsAtNodeRec);
12785  if (tcConnectptr.p->copyCountWords > 0) {
12786  jam();
12787  return;
12788  }//if
12789 /*---------------------------------------------------------------------------*/
12790 // No more outstanding copies. We will only start new ones from here if it was
12791 // stopped before and this only happens when copyCountWords is bigger than the
12792 // threshold value. Since this did not occur we must be waiting for completion.
12793 // Check that this is so. If not we crash to find out what is going on.
12794 /*---------------------------------------------------------------------------*/
12795  if (scanptr.p->scanCompletedStatus == ZTRUE) {
12796  jam();
12797  closeCopyLab(signal);
12798  return;
12799  }//if
12800 
12801  if (scanptr.p->scanState == ScanRecord::WAIT_LQHKEY_COPY &&
12802  scanptr.p->scanErrorCounter)
12803  {
12804  jam();
12805  closeCopyLab(signal);
12806  return;
12807  }
12808 
12809  if (scanptr.p->scanState == ScanRecord::WAIT_LQHKEY_COPY) {
12810  jam();
12811 /*---------------------------------------------------------------------------*/
12812 // Make sure that something is in progress. Otherwise we will simply stop
12813 // and nothing more will happen.
12814 /*---------------------------------------------------------------------------*/
12815  systemErrorLab(signal, __LINE__);
12816  return;
12817  }//if
12818  return;
12819 }//Dblqh::copyCompletedLab()
12820 
12821 void Dblqh::nextRecordCopy(Signal* signal)
12822 {
12823  fragptr.i = tcConnectptr.p->fragmentptr;
12824  c_fragment_pool.getPtr(fragptr);
12825  scanptr.i = tcConnectptr.p->tcScanRec;
12826  c_scanRecordPool.getPtr(scanptr);
12827  if (scanptr.p->scanState != ScanRecord::WAIT_LQHKEY_COPY) {
12828  jam();
12829 /*---------------------------------------------------------------------------*/
12830 // Make sure that nothing is in progress. Otherwise we will have to simultaneous
12831 // scans on the same record and this will certainly lead to unexpected
12832 // behaviour.
12833 /*---------------------------------------------------------------------------*/
12834  systemErrorLab(signal, __LINE__);
12835  return;
12836  }//if
12837  scanptr.p->scanState = ScanRecord::WAIT_NEXT_SCAN_COPY;
12838  switch (fragptr.p->fragStatus) {
12839  case Fragrecord::FSACTIVE:
12840  jam();
12841  break;
12842  case Fragrecord::BLOCKED:
12843  jam();
12844  linkFragQueue(signal);
12845  tcConnectptr.p->transactionState = TcConnectionrec::COPY_STOPPED;
12846  return;
12847  break;
12848  case Fragrecord::FREE:
12849  jam();
12851  jam();
12853  jam();
12854  case Fragrecord::DEFINED:
12855  jam();
12856  case Fragrecord::REMOVING:
12857  jam();
12858  default:
12859  jam();
12860  systemErrorLab(signal, __LINE__);
12861  return;
12862  break;
12863  }//switch
12864  continueCopyAfterBlockedLab(signal);
12865  return;
12866 }//Dblqh::nextRecordCopy()
12867 
12868 void Dblqh::continueCopyAfterBlockedLab(Signal* signal)
12869 {
12870  scanptr.i = tcConnectptr.p->tcScanRec;
12871  c_scanRecordPool.getPtr(scanptr);
12872  tcConnectptr.p->errorCode = 0;
12873  Uint32 acc_op_ptr= get_acc_ptr_from_scan_record(scanptr.p, 0, false);
12874  if (acc_op_ptr != RNIL)
12875  {
12876  signal->theData[0] = scanptr.p->scanAccPtr;
12877  signal->theData[1] = acc_op_ptr;
12878  signal->theData[2] = NextScanReq::ZSCAN_NEXT_COMMIT;
12879  sendSignal(scanptr.p->scanBlockref, GSN_NEXT_SCANREQ, signal, 3, JBB);
12880  }
12881  else
12882  {
12886  signal->theData[0] = scanptr.p->scanAccPtr;
12887  signal->theData[1] = RNIL;
12888  signal->theData[2] = NextScanReq::ZSCAN_NEXT;
12889  sendSignal(scanptr.p->scanBlockref, GSN_NEXT_SCANREQ, signal, 3, JBB);
12890  }
12891  return;
12892 }//Dblqh::continueCopyAfterBlockedLab()
12893 
12894 void Dblqh::copyLqhKeyRefLab(Signal* signal)
12895 {
12896  ndbrequire(tcConnectptr.p->transid[1] == signal->theData[4]);
12897  Uint32 copyWords = signal->theData[3];
12898  scanptr.i = tcConnectptr.p->tcScanRec;
12899  c_scanRecordPool.getPtr(scanptr);
12900  scanptr.p->scanErrorCounter++;
12901  tcConnectptr.p->errorCode = terrorCode;
12902 
12903  LqhKeyConf* conf = (LqhKeyConf*)signal->getDataPtrSend();
12904  conf->transId1 = copyWords;
12905  conf->transId2 = tcConnectptr.p->transid[1];
12906  copyCompletedLab(signal);
12907 }//Dblqh::copyLqhKeyRefLab()
12908 
12909 void Dblqh::closeCopyLab(Signal* signal)
12910 {
12911  if (tcConnectptr.p->copyCountWords > 0) {
12912 /*---------------------------------------------------------------------------*/
12913 // We are still waiting for responses from the starting node.
12914 // Wait until all of those have arrived until we start the
12915 // close process.
12916 /*---------------------------------------------------------------------------*/
12917  scanptr.p->scanState = ScanRecord::WAIT_LQHKEY_COPY;
12918  jam();
12919  return;
12920  }//if
12921  tcConnectptr.p->transid[0] = 0;
12922  tcConnectptr.p->transid[1] = 0;
12923  fragptr.i = tcConnectptr.p->fragmentptr;
12924  c_fragment_pool.getPtr(fragptr);
12925 
12929  fragptr.p->m_copy_started_state = Fragrecord::AC_NORMAL;
12930  if (ERROR_INSERTED(5714))
12931  {
12932  ndbout_c("Copy of tab: %u frag: %u complete",
12933  fragptr.p->tabRef, fragptr.p->fragId);
12934  }
12935 
12936  scanptr.i = tcConnectptr.p->tcScanRec;
12937  c_scanRecordPool.getPtr(scanptr);
12938  scanptr.p->scanState = ScanRecord::WAIT_CLOSE_COPY;
12939  switch (fragptr.p->fragStatus) {
12940  case Fragrecord::FSACTIVE:
12941  jam();
12942  break;
12943  case Fragrecord::BLOCKED:
12944  jam();
12945  linkFragQueue(signal);
12946  tcConnectptr.p->transactionState = TcConnectionrec::COPY_CLOSE_STOPPED;
12947  return;
12948  break;
12949  case Fragrecord::FREE:
12950  jam();
12952  jam();
12954  jam();
12955  case Fragrecord::DEFINED:
12956  jam();
12957  case Fragrecord::REMOVING:
12958  jam();
12959  default:
12960  jam();
12961  systemErrorLab(signal, __LINE__);
12962  return;
12963  break;
12964  }//switch
12965  continueCloseCopyAfterBlockedLab(signal);
12966  return;
12967 }//Dblqh::closeCopyLab()
12968 
12969 void Dblqh::continueCloseCopyAfterBlockedLab(Signal* signal)
12970 {
12971  scanptr.i = tcConnectptr.p->tcScanRec;
12972  c_scanRecordPool.getPtr(scanptr);
12973  signal->theData[0] = scanptr.p->scanAccPtr;
12974  signal->theData[1] = RNIL;
12975  signal->theData[2] = NextScanReq::ZSCAN_CLOSE;
12976  sendSignal(scanptr.p->scanBlockref, GSN_NEXT_SCANREQ, signal, 3, JBB);
12977  return;
12978 }//Dblqh::continueCloseCopyAfterBlockedLab()
12979 
12980 /*---------------------------------------------------------------------------*/
12981 /* ENTER NEXT_SCANCONF WITH */
12982 /* SCANPTR, */
12983 /* TFRAGID, */
12984 /* TACC_OPPTR, */
12985 /* TLOCAL_KEY1, */
12986 /* TLOCAL_KEY2, */
12987 /* TKEY_LENGTH, */
12988 /* TKEY1, */
12989 /* TKEY2, */
12990 /* TKEY3, */
12991 /* TKEY4 */
12992 /*---------------------------------------------------------------------------*/
12993 /* PRECONDITION: SCAN_STATE = WAIT_CLOSE_COPY */
12994 /*---------------------------------------------------------------------------*/
12995 void Dblqh::accCopyCloseConfLab(Signal* signal)
12996 {
12997  tcConnectptr.i = scanptr.p->scanTcrec;
12998  scanptr.p->scanState = ScanRecord::WAIT_DELETE_STORED_PROC_ID_COPY;
12999  ptrCheckGuard(tcConnectptr, ctcConnectrecFileSize, tcConnectionrec);
13000  signal->theData[0] = tcConnectptr.p->tupConnectrec;
13001  signal->theData[1] = tcConnectptr.p->tableref;
13002  signal->theData[2] = scanptr.p->scanSchemaVersion;
13003  signal->theData[3] = ZDELETE_STORED_PROC_ID;
13004  signal->theData[4] = scanptr.p->scanStoredProcId;
13005  signal->theData[5] = scanptr.p->scanApiBlockref;
13006  sendSignal(tcConnectptr.p->tcTupBlockref, GSN_STORED_PROCREQ, signal, 6, JBB);
13007  return;
13008 }//Dblqh::accCopyCloseConfLab()
13009 
13010 /*---------------------------------------------------------------------------*/
13011 /* ENTER STORED_PROCCONF WITH */
13012 /* TC_CONNECTPTR, */
13013 /* TSTORED_PROC_ID */
13014 /*---------------------------------------------------------------------------*/
13015 /* PRECONDITION: SCAN_STATE = WAIT_DELETE_STORED_PROC_ID_COPY */
13016 /*---------------------------------------------------------------------------*/
13017 void Dblqh::tupCopyCloseConfLab(Signal* signal)
13018 {
13019  fragptr.i = tcConnectptr.p->fragmentptr;
13020  c_fragment_pool.getPtr(fragptr);
13021  fragptr.p->copyFragState = ZIDLE;
13022 
13023  if (tcConnectptr.p->abortState == TcConnectionrec::NEW_FROM_TC) {
13024  jam();
13025  tcNodeFailptr.i = tcConnectptr.p->tcNodeFailrec;
13026  ptrCheckGuard(tcNodeFailptr, ctcNodeFailrecFileSize, tcNodeFailRecord);
13027  tcNodeFailptr.p->tcRecNow = tcConnectptr.i + 1;
13028  signal->theData[0] = ZLQH_TRANS_NEXT;
13029  signal->theData[1] = tcNodeFailptr.i;
13030  sendSignal(cownref, GSN_CONTINUEB, signal, 2, JBB);
13031 
13032  CopyFragRef * const ref = (CopyFragRef *)&signal->theData[0];
13033  ref->userPtr = scanptr.p->copyPtr;
13034  ref->sendingNodeId = cownNodeid;
13035  ref->startingNodeId = scanptr.p->scanNodeId;
13036  ref->tableId = fragptr.p->tabRef;
13037  ref->fragId = fragptr.p->fragId;
13038  ref->errorCode = ZNODE_FAILURE_ERROR;
13039  sendSignal(tcConnectptr.p->clientBlockref, GSN_COPY_FRAGREF, signal,
13040  CopyFragRef::SignalLength, JBB);
13041  } else {
13042  if (scanptr.p->scanErrorCounter > 0) {
13043  jam();
13044  CopyFragRef * const ref = (CopyFragRef *)&signal->theData[0];
13045  ref->userPtr = scanptr.p->copyPtr;
13046  ref->sendingNodeId = cownNodeid;
13047  ref->startingNodeId = scanptr.p->scanNodeId;
13048  ref->tableId = fragptr.p->tabRef;
13049  ref->fragId = fragptr.p->fragId;
13050  ref->errorCode = tcConnectptr.p->errorCode;
13051  sendSignal(tcConnectptr.p->clientBlockref, GSN_COPY_FRAGREF, signal,
13052  CopyFragRef::SignalLength, JBB);
13053  } else {
13054  jam();
13055  CopyFragConf * const conf = (CopyFragConf *)&signal->theData[0];
13056  conf->userPtr = scanptr.p->copyPtr;
13057  conf->sendingNodeId = cownNodeid;
13058  conf->startingNodeId = scanptr.p->scanNodeId;
13059  conf->tableId = tcConnectptr.p->tableref;
13060  conf->fragId = tcConnectptr.p->fragmentid;
13061  conf->rows_lo = scanptr.p->m_curr_batch_size_rows;
13062  conf->bytes_lo = scanptr.p->m_curr_batch_size_bytes;
13063  sendSignal(tcConnectptr.p->clientBlockref, GSN_COPY_FRAGCONF, signal,
13064  CopyFragConf::SignalLength, JBB);
13065  }//if
13066  }//if
13067  releaseActiveCopy(signal);
13068  tcConnectptr.p->tcScanRec = RNIL;
13069  finishScanrec(signal);
13070  releaseOprec(signal);
13071  releaseTcrec(signal, tcConnectptr);
13072  releaseScanrec(signal);
13073 }//Dblqh::tupCopyCloseConfLab()
13074 
13075 /*---------------------------------------------------------------------------*/
13076 /* A NODE FAILURE OCCURRED DURING THE COPY PROCESS. WE NEED TO CLOSE THE */
13077 /* COPY PROCESS SINCE A NODE FAILURE DURING THE COPY PROCESS WILL ALSO */
13078 /* FAIL THE NODE THAT IS TRYING TO START-UP. */
13079 /*---------------------------------------------------------------------------*/
13080 void Dblqh::closeCopyRequestLab(Signal* signal)
13081 {
13082  scanptr.p->scanErrorCounter++;
13083  if (0) ndbout_c("closeCopyRequestLab: scanState: %d", scanptr.p->scanState);
13084  switch (scanptr.p->scanState) {
13085  case ScanRecord::WAIT_TUPKEY_COPY:
13086  case ScanRecord::WAIT_NEXT_SCAN_COPY:
13087  jam();
13088 /*---------------------------------------------------------------------------*/
13089 /* SET COMPLETION STATUS AND WAIT FOR OPPORTUNITY TO STOP THE SCAN. */
13090 // ALSO SET NO OF WORDS OUTSTANDING TO ZERO TO AVOID ETERNAL WAIT.
13091 /*---------------------------------------------------------------------------*/
13092  scanptr.p->scanCompletedStatus = ZTRUE;
13093  tcConnectptr.p->copyCountWords = 0;
13094  break;
13095  case ScanRecord::WAIT_ACC_COPY:
13096  case ScanRecord::WAIT_STORED_PROC_COPY:
13097  jam();
13098 /*---------------------------------------------------------------------------*/
13099 /* WE ARE CURRENTLY STARTING UP THE SCAN. SET COMPLETED STATUS AND WAIT FOR*/
13100 /* COMPLETION OF STARTUP. */
13101 /*---------------------------------------------------------------------------*/
13102  scanptr.p->scanCompletedStatus = ZTRUE;
13103  break;
13104  case ScanRecord::WAIT_CLOSE_COPY:
13105  case ScanRecord::WAIT_DELETE_STORED_PROC_ID_COPY:
13106  jam();
13107 /*---------------------------------------------------------------------------*/
13108 /* CLOSE IS ALREADY ONGOING. WE NEED NOT DO ANYTHING. */
13109 /*---------------------------------------------------------------------------*/
13110  break;
13111  case ScanRecord::WAIT_LQHKEY_COPY:
13112  jam();
13113 /*---------------------------------------------------------------------------*/
13114 /* WE ARE WAITING FOR THE FAILED NODE. THE NODE WILL NEVER COME BACK. */
13115 // WE NEED TO START THE FAILURE HANDLING IMMEDIATELY.
13116 // ALSO SET NO OF WORDS OUTSTANDING TO ZERO TO AVOID ETERNAL WAIT.
13117 /*---------------------------------------------------------------------------*/
13118  tcConnectptr.p->copyCountWords = 0;
13119  closeCopyLab(signal);
13120  break;
13121  default:
13122  ndbrequire(false);
13123  break;
13124  }//switch
13125  return;
13126 }//Dblqh::closeCopyRequestLab()
13127 
13128 /* ****************************************************** */
13129 /* COPY_ACTIVEREQ: Change state of a fragment to ACTIVE. */
13130 /* ****************************************************** */
13131 void Dblqh::execCOPY_ACTIVEREQ(Signal* signal)
13132 {
13133  CRASH_INSERTION(5026);
13134 
13135  const CopyActiveReq * const req = (CopyActiveReq *)&signal->theData[0];
13136  jamEntry();
13137  Uint32 masterPtr = req->userPtr;
13138  BlockReference masterRef = req->userRef;
13139  tabptr.i = req->tableId;
13140  ptrCheckGuard(tabptr, ctabrecFileSize, tablerec);
13141  Uint32 fragId = req->fragId;
13142  Uint32 flags = req->flags;
13143  if (unlikely(signal->getLength() < CopyActiveReq::SignalLength))
13144  {
13145  jam();
13146  flags = 0;
13147  }
13148 
13149  ndbrequire(getFragmentrec(signal, fragId));
13150 
13151  fragptr.p->fragStatus = Fragrecord::FSACTIVE;
13152  fragptr.p->fragDistributionKey = req->distributionKey;
13153 
13154  if (TRACENR_FLAG)
13155  TRACENR("tab: " << tabptr.i
13156  << " frag: " << fragId
13157  << " COPY ACTIVE"
13158  << " flags: " << hex << flags << endl);
13159 
13160  ndbrequire(cnoActiveCopy < 3);
13161  cactiveCopy[cnoActiveCopy] = fragptr.i;
13162  cnoActiveCopy++;
13163  fragptr.p->masterBlockref = masterRef;
13164  fragptr.p->masterPtr = masterPtr;
13165 
13166  if ((flags & CopyActiveReq::CAR_NO_LOGGING) == 0)
13167  {
13168  jam();
13169  if (fragptr.p->lcpFlag == Fragrecord::LCP_STATE_TRUE)
13170  {
13171  jam();
13172  fragptr.p->logFlag = Fragrecord::STATE_TRUE;
13173  }
13174  }
13175 
13176  if (flags & CopyActiveReq::CAR_NO_WAIT)
13177  {
13178  jam();
13179  ndbrequire(fragptr.p->activeTcCounter == 0);
13180  Uint32 save = fragptr.p->startGci;
13181  fragptr.p->startGci = 0;
13182  sendCopyActiveConf(signal, tabptr.i);
13183  fragptr.p->startGci = save;
13184  return;
13185  }
13186 
13187  fragptr.p->activeTcCounter = 1;
13188 /*------------------------------------------------------*/
13189 /* SET IT TO ONE TO ENSURE THAT IT IS NOT POSSIBLE*/
13190 /* TO DECREASE IT TO ZERO UNTIL WE HAVE COMPLETED */
13191 /* THE SCAN. */
13192 /*------------------------------------------------------*/
13193  signal->theData[0] = ZSCAN_TC_CONNECT;
13194  signal->theData[1] = 0;
13195  signal->theData[2] = tabptr.i;
13196  signal->theData[3] = fragId;
13197  sendSignal(cownref, GSN_CONTINUEB, signal, 4, JBB);
13198  return;
13199 }//Dblqh::execCOPY_ACTIVEREQ()
13200 
13201 void Dblqh::scanTcConnectLab(Signal* signal, Uint32 tstartTcConnect, Uint32 fragId)
13202 {
13203  Uint32 tendTcConnect;
13204 
13205  ndbrequire(getFragmentrec(signal, fragId));
13206  if ((tstartTcConnect + 200) >= ctcConnectrecFileSize) {
13207  jam();
13208  tendTcConnect = ctcConnectrecFileSize - 1;
13209  } else {
13210  jam();
13211  tendTcConnect = tstartTcConnect + 200;
13212  }//if
13213  for (tcConnectptr.i = tstartTcConnect;
13214  tcConnectptr.i <= tendTcConnect;
13215  tcConnectptr.i++) {
13216  jam();
13217  ptrCheckGuard(tcConnectptr, ctcConnectrecFileSize, tcConnectionrec);
13218  if (tcConnectptr.p->transactionState != TcConnectionrec::IDLE) {
13219  switch (tcConnectptr.p->logWriteState) {
13220  case TcConnectionrec::NOT_WRITTEN:
13221  jam();
13222  if (fragptr.i == tcConnectptr.p->fragmentptr) {
13223  jam();
13224  fragptr.p->activeTcCounter = fragptr.p->activeTcCounter + 1;
13225  tcConnectptr.p->logWriteState = TcConnectionrec::NOT_WRITTEN_WAIT;
13226  }//if
13227  break;
13228  default:
13229  jam();
13230  /*empty*/;
13231  break;
13232  }//switch
13233  }//if
13234  }//for
13235  if (tendTcConnect < (ctcConnectrecFileSize - 1)) {
13236  jam();
13237  signal->theData[0] = ZSCAN_TC_CONNECT;
13238  signal->theData[1] = tendTcConnect + 1;
13239  signal->theData[2] = tabptr.i;
13240  signal->theData[3] = fragId;
13241  sendSignal(cownref, GSN_CONTINUEB, signal, 4, JBB);
13242  } else {
13243  jam();
13244 /*------------------------------------------------------*/
13245 /* THE SCAN HAVE BEEN COMPLETED. WE CHECK IF ALL */
13246 /* OPERATIONS HAVE ALREADY BEEN COMPLETED. */
13247 /*------------------------------------------------------*/
13248  ndbrequire(fragptr.p->activeTcCounter > 0);
13249  fragptr.p->activeTcCounter--;
13250  if (fragptr.p->activeTcCounter == 0) {
13251  jam();
13252 /*------------------------------------------------------*/
13253 /* SET START GLOBAL CHECKPOINT TO THE NEXT */
13254 /* CHECKPOINT WE HAVE NOT YET HEARD ANYTHING ABOUT*/
13255 /* THIS GCP WILL BE COMPLETELY COVERED BY THE LOG.*/
13256 /*------------------------------------------------------*/
13257  fragptr.p->startGci = cnewestGci + 1;
13258  sendCopyActiveConf(signal, tabptr.i);
13259  }//if
13260  }//if
13261  return;
13262 }//Dblqh::scanTcConnectLab()
13263 
13264 /*---------------------------------------------------------------------------*/
13265 /* A NEW MASTER IS REQUESTING THE STATE IN LQH OF THE COPY FRAGMENT PARTS. */
13266 /*---------------------------------------------------------------------------*/
13267 /* ***************>> */
13268 /* COPY_STATEREQ > */
13269 /* ***************>> */
13270 void Dblqh::execCOPY_STATEREQ(Signal* signal)
13271 {
13272  jamEntry();
13273  ndbrequire(0)
13274 #if 0
13275  Uint32* dataPtr = &signal->theData[2];
13276  BlockReference tmasterBlockref = signal->theData[0];
13277  Uint32 tnoCopy = 0;
13278  do {
13279  jam();
13280  arrGuard(tnoCopy, 4);
13281  fragptr.i = cactiveCopy[tnoCopy];
13282  if (fragptr.i == RNIL) {
13283  jam();
13284  break;
13285  }//if
13286  c_fragment_pool.getPtr(fragptr);
13287  if (fragptr.p->copyFragState != ZIDLE) {
13288  jam();
13289 /*---------------------------------------------------------------------------*/
13290 /* THIS FRAGMENT IS CURRENTLY ACTIVE IN COPYING THE FRAGMENT. */
13291 /*---------------------------------------------------------------------------*/
13292  scanptr.i = fragptr.p->fragScanRec[NR_ScanNo];
13293  c_scanRecordPool.getPtr(scanptr);
13294  if (scanptr.p->scanCompletedStatus == ZTRUE) {
13295  jam();
13296  dataPtr[3 + (tnoCopy << 2)] = ZCOPY_CLOSING;
13297  } else {
13298  jam();
13299  dataPtr[3 + (tnoCopy << 2)] = ZCOPY_ONGOING;
13300  }//if
13301  dataPtr[2 + (tnoCopy << 2)] = scanptr.p->scanSchemaVersion;
13302  scanptr.p->scanApiBlockref = tmasterBlockref;
13303  } else {
13304  ndbrequire(fragptr.p->activeTcCounter != 0);
13305 /*---------------------------------------------------------------------------*/
13306 /* COPY FRAGMENT IS COMPLETED AND WE ARE CURRENTLY GETTING THE STARTING */
13307 /* GCI OF THE NEW REPLICA OF THIS FRAGMENT. */
13308 /*---------------------------------------------------------------------------*/
13309  fragptr.p->masterBlockref = tmasterBlockref;
13310  dataPtr[3 + (tnoCopy << 2)] = ZCOPY_ACTIVATION;
13311  }//if
13312  dataPtr[tnoCopy << 2] = fragptr.p->tabRef;
13313  dataPtr[1 + (tnoCopy << 2)] = fragptr.p->fragId;
13314  tnoCopy++;
13315  } while (tnoCopy < cnoActiveCopy);
13316  signal->theData[0] = cownNodeid;
13317  signal->theData[1] = tnoCopy;
13318  sendSignal(tmasterBlockref, GSN_COPY_STATECONF, signal, 18, JBB);
13319 #endif
13320  return;
13321 }//Dblqh::execCOPY_STATEREQ()
13322 
13323 /* ========================================================================= */
13324 /* ======= INITIATE TC RECORD AT COPY FRAGMENT ======= */
13325 /* */
13326 /* SUBROUTINE SHORT NAME = ICT */
13327 /* ========================================================================= */
13328 void Dblqh::initCopyTc(Signal* signal, Operation_t op)
13329 {
13330  tcConnectptr.p->operation = ZREAD;
13331  tcConnectptr.p->apiVersionNo = 0;
13332  tcConnectptr.p->opExec = 0; /* NOT INTERPRETED MODE */
13333  tcConnectptr.p->schemaVersion = scanptr.p->scanSchemaVersion;
13334  Uint32 reqinfo = 0;
13335  LqhKeyReq::setDirtyFlag(reqinfo, 1);
13336  LqhKeyReq::setSimpleFlag(reqinfo, 1);
13337  LqhKeyReq::setOperation(reqinfo, op);
13338  LqhKeyReq::setGCIFlag(reqinfo, 1);
13339  LqhKeyReq::setNrCopyFlag(reqinfo, 1);
13340  /* AILen in LQHKEYREQ IS ZERO */
13341  tcConnectptr.p->reqinfo = reqinfo;
13342 /* ------------------------------------------------------------------------ */
13343 /* THE RECEIVING NODE WILL EXPECT THAT IT IS THE LAST NODE AND WILL */
13344 /* SEND COMPLETED AS THE RESPONSE SIGNAL SINCE DIRTY_OP BIT IS SET. */
13345 /* ------------------------------------------------------------------------ */
13346  tcConnectptr.p->nodeAfterNext[0] = ZNIL;
13347  tcConnectptr.p->nodeAfterNext[1] = ZNIL;
13348  tcConnectptr.p->tcBlockref = cownref;
13349  tcConnectptr.p->readlenAi = 0;
13350  tcConnectptr.p->storedProcId = ZNIL;
13351  tcConnectptr.p->opExec = 0;
13352  tcConnectptr.p->nextSeqNoReplica = 0;
13353  tcConnectptr.p->dirtyOp = ZFALSE;
13354  tcConnectptr.p->lastReplicaNo = 0;
13355  tcConnectptr.p->currTupAiLen = 0;
13356  tcConnectptr.p->tcTimer = cLqhTimeOutCount;
13357 }//Dblqh::initCopyTc()
13358 
13359 /* ------------------------------------------------------------------------- */
13360 /* ------- SEND COPY_ACTIVECONF TO MASTER DIH ------- */
13361 /* */
13362 /* ------------------------------------------------------------------------- */
13363 void Dblqh::sendCopyActiveConf(Signal* signal, Uint32 tableId)
13364 {
13365  releaseActiveCopy(signal);
13366  CopyActiveConf * const conf = (CopyActiveConf *)&signal->theData[0];
13367  conf->userPtr = fragptr.p->masterPtr;
13368  conf->tableId = tableId;
13369  conf->fragId = fragptr.p->fragId;
13370  conf->startingNodeId = cownNodeid;
13371  conf->startGci = fragptr.p->startGci;
13372  sendSignal(fragptr.p->masterBlockref, GSN_COPY_ACTIVECONF, signal,
13373  CopyActiveConf::SignalLength, JBB);
13374 }//Dblqh::sendCopyActiveConf()
13375 
13376 /* ##########################################################################
13377  * ####### LOCAL CHECKPOINT MODULE #######
13378  *
13379  * ##########################################################################
13380  * --------------------------------------------------------------------------
13381  * THIS MODULE HANDLES THE EXECUTION AND CONTROL OF LOCAL CHECKPOINTS
13382  * IT CONTROLS THE LOCAL CHECKPOINTS IN TUP AND ACC. IT DOES ALSO INTERACT
13383  * WITH DIH TO CONTROL WHICH GLOBAL CHECKPOINTS THAT ARE RECOVERABLE
13384  * ------------------------------------------------------------------------- */
13385 void Dblqh::execEMPTY_LCP_REQ(Signal* signal)
13386 {
13387  jamEntry();
13388  CRASH_INSERTION(5008);
13389  EmptyLcpReq * const emptyLcpOrd = (EmptyLcpReq*)&signal->theData[0];
13390 
13391  ndbrequire(!isNdbMtLqh()); // Handled by DblqhProxy
13392 
13393  lcpPtr.i = 0;
13394  ptrAss(lcpPtr, lcpRecord);
13395 
13396  Uint32 nodeId = refToNode(emptyLcpOrd->senderRef);
13397 
13398  lcpPtr.p->m_EMPTY_LCP_REQ.set(nodeId);
13399  lcpPtr.p->reportEmpty = true;
13400 
13401  if (lcpPtr.p->lcpState == LcpRecord::LCP_IDLE){
13402  jam();
13403  bool ok = false;
13404  switch(clcpCompletedState){
13405  case LCP_IDLE:
13406  ok = true;
13407  sendEMPTY_LCP_CONF(signal, true);
13408  break;
13409  case LCP_RUNNING:
13410  ok = true;
13411  sendEMPTY_LCP_CONF(signal, false);
13412  break;
13413  case LCP_CLOSE_STARTED:
13414  jam();
13415  case ACC_LCP_CLOSE_COMPLETED:
13416  jam();
13417  case TUP_LCP_CLOSE_COMPLETED:
13418  jam();
13419  ok = true;
13420  break;
13421  }
13422  ndbrequire(ok);
13423 
13424  }//if
13425 
13426  return;
13427 }//Dblqh::execEMPTY_LCPREQ()
13428 
13429 #ifdef NDB_DEBUG_FULL
13430 static struct TraceLCP {
13431  void sendSignal(Uint32 ref, Uint32 gsn, Signal* signal,
13432  Uint32 len, Uint32 prio);
13433  void save(Signal*);
13434  void restore(SimulatedBlock&, Signal* sig);
13435  struct Sig {
13436  enum {
13437  Sig_save = 0,
13438  Sig_send = 1
13439  } type;
13440  SignalHeader header;
13441  Uint32 theData[25];
13442  };
13443  Vector<Sig> m_signals;
13444 } g_trace_lcp;
13445 template class Vector<TraceLCP::Sig>;
13446 #else
13447 #endif
13448 
13449 void
13450 Dblqh::force_lcp(Signal* signal)
13451 {
13452  if (cLqhTimeOutCount == c_last_force_lcp_time)
13453  {
13454  jam();
13455  return;
13456  }
13457 
13458  c_last_force_lcp_time = cLqhTimeOutCount;
13459  signal->theData[0] = 7099;
13460  sendSignal(DBDIH_REF, GSN_DUMP_STATE_ORD, signal, 1, JBB);
13461 }
13462 
13463 void Dblqh::execLCP_FRAG_ORD(Signal* signal)
13464 {
13465  jamEntry();
13466  CRASH_INSERTION(5010);
13467 
13468  LcpFragOrd lcpFragOrdCopy = * (LcpFragOrd *)&signal->theData[0];
13469  LcpFragOrd * lcpFragOrd = &lcpFragOrdCopy;
13470 
13471  Uint32 lcpId = lcpFragOrd->lcpId;
13472 
13473  lcpPtr.i = 0;
13474  ptrAss(lcpPtr, lcpRecord);
13475 
13476  lcpPtr.p->lastFragmentFlag = lcpFragOrd->lastFragmentFlag;
13477  if (lcpFragOrd->lastFragmentFlag)
13478  {
13479  jam();
13480  CRASH_INSERTION(5054);
13481  if (lcpPtr.p->lcpState == LcpRecord::LCP_IDLE) {
13482  jam();
13483  /* ----------------------------------------------------------
13484  * NOW THE COMPLETE LOCAL CHECKPOINT ROUND IS COMPLETED.
13485  * -------------------------------------------------------- */
13486  if (cnoOfFragsCheckpointed > 0) {
13487  jam();
13488  completeLcpRoundLab(signal, lcpId);
13489  } else {
13490  jam();
13491  clcpCompletedState = LCP_IDLE;
13492  sendLCP_COMPLETE_REP(signal, lcpId);
13493  }//if
13494  }
13495  return;
13496  }//if
13497  tabptr.i = lcpFragOrd->tableId;
13498  ptrCheckGuard(tabptr, ctabrecFileSize, tablerec);
13499 
13500  lcpPtr.i = 0;
13501  ptrAss(lcpPtr, lcpRecord);
13502  ndbrequire(!lcpPtr.p->lcpQueued);
13503 
13504  if (c_lcpId < lcpFragOrd->lcpId)
13505  {
13506  jam();
13507 
13508  lcpPtr.p->firstFragmentFlag= true;
13509 
13510 #ifdef ERROR_INSERT
13511  if (check_ndb_versions())
13512  {
13518  if (! ((cnewestCompletedGci >= lcpFragOrd->keepGci) &&
13519  (cnewestGci >= lcpFragOrd->keepGci)))
13520  {
13521  ndbout_c("lcpFragOrd->keepGci: %u cnewestCompletedGci: %u cnewestGci: %u",
13522  lcpFragOrd->keepGci, cnewestCompletedGci, cnewestGci);
13523  }
13524  ndbrequire(cnewestCompletedGci >= lcpFragOrd->keepGci);
13525  ndbrequire(cnewestGci >= lcpFragOrd->keepGci);
13526  }
13527 #endif
13528 
13529  c_lcpId = lcpFragOrd->lcpId;
13530  ndbrequire(lcpPtr.p->lcpState == LcpRecord::LCP_IDLE);
13531  setLogTail(signal, lcpFragOrd->keepGci);
13532  ndbrequire(clcpCompletedState == LCP_IDLE);
13533  clcpCompletedState = LCP_RUNNING;
13534  }
13535 
13536  if (! (tabptr.p->tableStatus == Tablerec::TABLE_DEFINED || tabptr.p->tableStatus == Tablerec::TABLE_READ_ONLY))
13537  {
13538  jam();
13539  LcpRecord::FragOrd fragOrd;
13540  fragOrd.fragPtrI = RNIL;
13541  fragOrd.lcpFragOrd = * lcpFragOrd;
13542 
13543  Fragrecord tmp;
13544  tmp.maxGciInLcp = cnewestGci;
13545  tmp.maxGciCompletedInLcp = cnewestCompletedGci;
13546  sendLCP_FRAG_REP(signal, fragOrd, &tmp);
13547  return;
13548  }
13549 
13550  cnoOfFragsCheckpointed++;
13551  ndbrequire(getFragmentrec(signal, lcpFragOrd->fragmentId));
13552 
13553  if (lcpPtr.p->lcpState != LcpRecord::LCP_IDLE)
13554  {
13555  ndbrequire(lcpPtr.p->lcpQueued == false);
13556  lcpPtr.p->lcpQueued = true;
13557  lcpPtr.p->queuedFragment.fragPtrI = fragptr.i;
13558  lcpPtr.p->queuedFragment.lcpFragOrd = * lcpFragOrd;
13559  return;
13560  }//if
13561 
13562  lcpPtr.p->currentFragment.fragPtrI = fragptr.i;
13563  lcpPtr.p->currentFragment.lcpFragOrd = * lcpFragOrd;
13564 
13565  sendLCP_FRAGIDREQ(signal);
13566 }//Dblqh::execLCP_FRAGORD()
13567 
13568 void Dblqh::execLCP_PREPARE_REF(Signal* signal)
13569 {
13570  jamEntry();
13571 
13572  LcpPrepareRef* ref= (LcpPrepareRef*)signal->getDataPtr();
13573 
13574  lcpPtr.i = ref->senderData;
13575  ptrCheckGuard(lcpPtr, clcpFileSize, lcpRecord);
13576  ndbrequire(lcpPtr.p->lcpState == LcpRecord::LCP_WAIT_FRAGID);
13577 
13578  fragptr.i = lcpPtr.p->currentFragment.fragPtrI;
13579  c_fragment_pool.getPtr(fragptr);
13580 
13581  ndbrequire(ref->tableId == fragptr.p->tabRef);
13582  ndbrequire(ref->fragmentId == fragptr.p->fragId);
13583 
13584  tabptr.i = ref->tableId;
13585  ptrCheckGuard(tabptr, ctabrecFileSize, tablerec);
13586 
13587  ndbrequire(lcpPtr.p->m_outstanding);
13588  lcpPtr.p->m_outstanding--;
13589 
13593  ndbrequire(refToMain(signal->getSendersBlockRef()) == BACKUP);
13594  lcpPtr.p->m_error = ref->errorCode;
13595 
13596  if (lcpPtr.p->m_outstanding == 0)
13597  {
13598  jam();
13599 
13600  if(lcpPtr.p->firstFragmentFlag)
13601  {
13602  jam();
13603  LcpFragOrd *ord= (LcpFragOrd*)signal->getDataPtrSend();
13604  lcpPtr.p->firstFragmentFlag= false;
13605 
13606  if (!isNdbMtLqh())
13607  {
13608  jam();
13609  *ord = lcpPtr.p->currentFragment.lcpFragOrd;
13610  EXECUTE_DIRECT(PGMAN, GSN_LCP_FRAG_ORD, signal, signal->length());
13611  jamEntry();
13612 
13616  jam();
13617  *ord = lcpPtr.p->currentFragment.lcpFragOrd;
13618  EXECUTE_DIRECT(TSMAN, GSN_LCP_FRAG_ORD,
13619  signal, signal->length(), 0);
13620  jamEntry();
13621  }
13622  else
13623  {
13627  }
13628  }
13629 
13630  lcpPtr.p->lcpState = LcpRecord::LCP_COMPLETED;
13631  contChkpNextFragLab(signal);
13632  }
13633 }
13634 
13635 /* --------------------------------------------------------------------------
13636  * PRECONDITION: LCP_PTR:LCP_STATE = WAIT_FRAGID
13637  * --------------------------------------------------------------------------
13638  * WE NOW HAVE THE LOCAL FRAGMENTS THAT THE LOCAL CHECKPOINT WILL USE.
13639  * -------------------------------------------------------------------------- */
13640 void Dblqh::execLCP_PREPARE_CONF(Signal* signal)
13641 {
13642  jamEntry();
13643 
13644  LcpPrepareConf* conf= (LcpPrepareConf*)signal->getDataPtr();
13645 
13646  lcpPtr.i = conf->senderData;
13647  ptrCheckGuard(lcpPtr, clcpFileSize, lcpRecord);
13648  ndbrequire(lcpPtr.p->lcpState == LcpRecord::LCP_WAIT_FRAGID);
13649 
13650  fragptr.i = lcpPtr.p->currentFragment.fragPtrI;
13651  c_fragment_pool.getPtr(fragptr);
13652 
13653  // wl4391_todo obsolete
13654  if (refToBlock(signal->getSendersBlockRef()) != PGMAN)
13655  {
13656  ndbrequire(conf->tableId == fragptr.p->tabRef);
13657  ndbrequire(conf->fragmentId == fragptr.p->fragId);
13658  }
13659 
13660  ndbrequire(lcpPtr.p->m_outstanding);
13661  lcpPtr.p->m_outstanding--;
13662  if (lcpPtr.p->m_outstanding == 0)
13663  {
13664  jam();
13665 
13666  if(lcpPtr.p->firstFragmentFlag)
13667  {
13668  jam();
13669  LcpFragOrd *ord= (LcpFragOrd*)signal->getDataPtrSend();
13670  lcpPtr.p->firstFragmentFlag= false;
13671 
13672  // proxy is used in MT LQH to handle also the extra pgman worker
13673  if (!isNdbMtLqh())
13674  {
13675  jam();
13676  *ord = lcpPtr.p->currentFragment.lcpFragOrd;
13677  EXECUTE_DIRECT(PGMAN, GSN_LCP_FRAG_ORD, signal, signal->length());
13678  jamEntry();
13679 
13683  jam();
13684  *ord = lcpPtr.p->currentFragment.lcpFragOrd;
13685  EXECUTE_DIRECT(TSMAN, GSN_LCP_FRAG_ORD,
13686  signal, signal->length(), 0);
13687  jamEntry();
13688  }
13689  else
13690  {
13694  }
13695  }
13696 
13697  if (lcpPtr.p->m_error)
13698  {
13699  jam();
13700 
13701  lcpPtr.p->lcpState = LcpRecord::LCP_COMPLETED;
13702  contChkpNextFragLab(signal);
13703  return;
13704  }
13705 
13706  lcpPtr.p->lcpState = LcpRecord::LCP_WAIT_HOLDOPS;
13707  lcpPtr.p->lcpState = LcpRecord::LCP_START_CHKP;
13708 
13709  /* ----------------------------------------------------------------------
13710  * UPDATE THE MAX_GCI_IN_LCP AND MAX_GCI_COMPLETED_IN_LCP NOW BEFORE
13711  * ACTIVATING THE FRAGMENT AGAIN.
13712  * --------------------------------------------------------------------- */
13713  ndbrequire(lcpPtr.p->currentFragment.lcpFragOrd.lcpNo < MAX_LCP_STORED);
13714  fragptr.p->maxGciInLcp = fragptr.p->newestGci;
13715  fragptr.p->maxGciCompletedInLcp = cnewestCompletedGci;
13716 
13717  {
13718  LcpFragOrd *ord= (LcpFragOrd*)signal->getDataPtrSend();
13719  *ord = lcpPtr.p->currentFragment.lcpFragOrd;
13720  Logfile_client lgman(this, c_lgman, 0);
13721  lgman.exec_lcp_frag_ord(signal);
13722  jamEntry();
13723 
13724  *ord = lcpPtr.p->currentFragment.lcpFragOrd;
13725  EXECUTE_DIRECT(DBTUP, GSN_LCP_FRAG_ORD, signal, signal->length());
13726  jamEntry();
13727  }
13728 
13729  BackupFragmentReq* req= (BackupFragmentReq*)signal->getDataPtr();
13730  req->tableId = lcpPtr.p->currentFragment.lcpFragOrd.tableId;
13731  req->fragmentNo = 0;
13732  req->backupPtr = m_backup_ptr;
13733  req->backupId = lcpPtr.p->currentFragment.lcpFragOrd.lcpId;
13734  req->count = 0;
13735 
13736 #ifdef NDB_DEBUG_FULL
13737  if(ERROR_INSERTED(5904))
13738  {
13739  g_trace_lcp.sendSignal(BACKUP_REF, GSN_BACKUP_FRAGMENT_REQ, signal,
13740  BackupFragmentReq::SignalLength, JBB);
13741  }
13742  else
13743 #endif
13744  {
13745  if (ERROR_INSERTED(5044) &&
13746  (fragptr.p->tabRef == c_error_insert_table_id) &&
13747  fragptr.p->fragId) // Not first frag
13748  {
13752  ndbout_c("table: %d frag: %d", fragptr.p->tabRef, fragptr.p->fragId);
13753  SET_ERROR_INSERT_VALUE(5027);
13754  sendSignalWithDelay(reference(), GSN_START_RECREQ, signal, 10000, 1);
13755  }
13756  else if (ERROR_INSERTED(5053))
13757  {
13758  BlockReference backupRef = calcInstanceBlockRef(BACKUP);
13759  sendSignalWithDelay(backupRef, GSN_BACKUP_FRAGMENT_REQ, signal,
13760  150, BackupFragmentReq::SignalLength);
13761  }
13762  else
13763  {
13764  BlockReference backupRef = calcInstanceBlockRef(BACKUP);
13765  sendSignal(backupRef, GSN_BACKUP_FRAGMENT_REQ, signal,
13766  BackupFragmentReq::SignalLength, JBB);
13767  }
13768  }
13769  }
13770 }
13771 
13772 void Dblqh::execBACKUP_FRAGMENT_REF(Signal* signal)
13773 {
13774  BackupFragmentRef *ref= (BackupFragmentRef*)signal->getDataPtr();
13775  char buf[100];
13776  BaseString::snprintf(buf,sizeof(buf),
13777  "Unable to store fragment during LCP. NDBFS Error: %u",
13778  ref->errorCode);
13779 
13780  progError(__LINE__,
13781  (ref->errorCode & FsRef::FS_ERR_BIT)?
13782  NDBD_EXIT_AFS_UNKNOWN
13783  : ref->errorCode,
13784  buf);
13785 }
13786 
13787 void Dblqh::execBACKUP_FRAGMENT_CONF(Signal* signal)
13788 {
13789  jamEntry();
13790  //BackupFragmentConf* conf= (BackupFragmentConf*)signal->getDataPtr();
13791 
13792  lcpPtr.i = 0;
13793  ptrCheckGuard(lcpPtr, clcpFileSize, lcpRecord);
13794  ndbrequire(lcpPtr.p->lcpState == LcpRecord::LCP_START_CHKP);
13795  lcpPtr.p->lcpState = LcpRecord::LCP_COMPLETED;
13796 
13797  /* ------------------------------------------------------------------------
13798  * THE LOCAL CHECKPOINT HAS BEEN COMPLETED. IT IS NOW TIME TO START
13799  * A LOCAL CHECKPOINT ON THE NEXT FRAGMENT OR COMPLETE THIS LCP ROUND.
13800  * ------------------------------------------------------------------------
13801  * WE START BY SENDING LCP_REPORT TO DIH TO REPORT THE COMPLETED LCP.
13802  * TO CATER FOR NODE CRASHES WE SEND IT IN PARALLEL TO ALL NODES.
13803  * ----------------------------------------------------------------------- */
13804  fragptr.i = lcpPtr.p->currentFragment.fragPtrI;
13805  c_fragment_pool.getPtr(fragptr);
13806 
13810 #if defined VM_TRACE || defined ERROR_INSERT
13811  if (fragptr.p->newestGci != fragptr.p->maxGciInLcp)
13812  {
13813  ndbout_c("tab: %u frag: %u increasing maxGciInLcp from %u to %u",
13814  fragptr.p->tabRef,
13815  fragptr.p->fragId,
13816  fragptr.p->maxGciInLcp, fragptr.p->newestGci);
13817  }
13818 #endif
13819 
13820  fragptr.p->maxGciInLcp = fragptr.p->newestGci;
13821 
13822  contChkpNextFragLab(signal);
13823  return;
13824 }//Dblqh::lcpCompletedLab()
13825 
13826 void
13827 Dblqh::sendLCP_FRAG_REP(Signal * signal,
13828  const LcpRecord::FragOrd & fragOrd,
13829  const Fragrecord * fragPtrP) const
13830 {
13831  ndbrequire(fragOrd.lcpFragOrd.lcpNo < MAX_LCP_STORED);
13832  LcpFragRep * const lcpReport = (LcpFragRep *)&signal->theData[0];
13833  lcpReport->nodeId = cownNodeid;
13834  lcpReport->lcpId = fragOrd.lcpFragOrd.lcpId;
13835  lcpReport->lcpNo = fragOrd.lcpFragOrd.lcpNo;
13836  lcpReport->tableId = fragOrd.lcpFragOrd.tableId;
13837  lcpReport->fragId = fragOrd.lcpFragOrd.fragmentId;
13838  lcpReport->maxGciCompleted = fragPtrP->maxGciCompletedInLcp;
13839  lcpReport->maxGciStarted = fragPtrP->maxGciInLcp;
13840 
13841  Uint32 ref = DBDIH_REF;
13842  if (isNdbMtLqh())
13843  {
13844  jam();
13845  ref = DBLQH_REF;
13846  }
13847  lcpReport->nodeId = LcpFragRep::BROADCAST_REQ;
13848  sendSignal(ref, GSN_LCP_FRAG_REP, signal,
13849  LcpFragRep::SignalLength, JBB);
13850 }
13851 
13852 void Dblqh::contChkpNextFragLab(Signal* signal)
13853 {
13854  /* ------------------------------------------------------------------------
13855  * UPDATE THE LATEST LOCAL CHECKPOINT COMPLETED ON FRAGMENT.
13856  * UPDATE THE LCP_ID OF THIS CHECKPOINT.
13857  * REMOVE THE LINK BETWEEN THE FRAGMENT RECORD AND THE LCP RECORD.
13858  * ----------------------------------------------------------------------- */
13859  if (fragptr.p->fragStatus == Fragrecord::BLOCKED) {
13860  jam();
13865  lcpPtr.p->lcpState = LcpRecord::LCP_BLOCKED_COMP;
13866  return;
13867  }//if
13868 
13872  sendLCP_FRAG_REP(signal, lcpPtr.p->currentFragment,
13873  c_fragment_pool.getPtr(lcpPtr.p->currentFragment.fragPtrI));
13874 
13875  /* ------------------------------------------------------------------------
13876  * WE ALSO RELEASE THE LOCAL LCP RECORDS.
13877  * ----------------------------------------------------------------------- */
13878  if (lcpPtr.p->lcpQueued) {
13879  jam();
13880  /* ----------------------------------------------------------------------
13881  * Transfer the state from the queued to the active LCP.
13882  * --------------------------------------------------------------------- */
13883  lcpPtr.p->lcpQueued = false;
13884  lcpPtr.p->currentFragment = lcpPtr.p->queuedFragment;
13885 
13886  /* ----------------------------------------------------------------------
13887  * START THE QUEUED LOCAL CHECKPOINT.
13888  * --------------------------------------------------------------------- */
13889  sendLCP_FRAGIDREQ(signal);
13890  return;
13891  }//if
13892 
13893  lcpPtr.p->lcpState = LcpRecord::LCP_IDLE;
13894  if (lcpPtr.p->lastFragmentFlag){
13895  jam();
13896  /* ----------------------------------------------------------------------
13897  * NOW THE COMPLETE LOCAL CHECKPOINT ROUND IS COMPLETED.
13898  * --------------------------------------------------------------------- */
13899  completeLcpRoundLab(signal, lcpPtr.p->currentFragment.lcpFragOrd.lcpId);
13900  return;
13901  }//if
13902 
13903  if (lcpPtr.p->reportEmpty) {
13904  jam();
13905  sendEMPTY_LCP_CONF(signal, false);
13906  }//if
13907  return;
13908 }//Dblqh::contChkpNextFragLab()
13909 
13910 void Dblqh::sendLCP_FRAGIDREQ(Signal* signal)
13911 {
13912  TablerecPtr tabPtr;
13913  tabPtr.i = lcpPtr.p->currentFragment.lcpFragOrd.tableId;
13914  ptrAss(tabPtr, tablerec);
13915 
13916  if(tabPtr.p->tableStatus != Tablerec::TABLE_DEFINED)
13917  {
13918  jam();
13922  contChkpNextFragLab(signal);
13923  return;
13924  }
13925 
13926  lcpPtr.p->m_error = 0;
13927  lcpPtr.p->m_outstanding = 1;
13928 
13929  ndbrequire(tabPtr.p->tableStatus == Tablerec::TABLE_DEFINED ||
13930  tabPtr.p->tableStatus == Tablerec::TABLE_READ_ONLY);
13931 
13932  lcpPtr.p->lcpState = LcpRecord::LCP_WAIT_FRAGID;
13933  LcpPrepareReq* req= (LcpPrepareReq*)signal->getDataPtr();
13934  req->senderData = lcpPtr.i;
13935  req->senderRef = reference();
13936  req->lcpNo = lcpPtr.p->currentFragment.lcpFragOrd.lcpNo;
13937  req->tableId = lcpPtr.p->currentFragment.lcpFragOrd.tableId;
13938  req->fragmentId = lcpPtr.p->currentFragment.lcpFragOrd.fragmentId;
13939  req->lcpId = lcpPtr.p->currentFragment.lcpFragOrd.lcpId % MAX_LCP_STORED;
13940  req->backupPtr = m_backup_ptr;
13941  req->backupId = lcpPtr.p->currentFragment.lcpFragOrd.lcpId;
13942  BlockReference backupRef = calcInstanceBlockRef(BACKUP);
13943  sendSignal(backupRef, GSN_LCP_PREPARE_REQ, signal,
13944  LcpPrepareReq::SignalLength, JBB);
13945 
13946 }//Dblqh::sendLCP_FRAGIDREQ()
13947 
13948 void Dblqh::sendEMPTY_LCP_CONF(Signal* signal, bool idle)
13949 {
13950  EmptyLcpRep * sig = (EmptyLcpRep*)signal->getDataPtrSend();
13951  EmptyLcpConf * rep = (EmptyLcpConf*)sig->conf;
13952 
13953  /* ----------------------------------------------------------------------
13954  * We have been requested to report when there are no more local
13955  * waiting to be started or ongoing. In this signal we also report
13956  * the last completed fragments state.
13957  * ---------------------------------------------------------------------- */
13958  rep->senderNodeId = getOwnNodeId();
13959  if(!idle){
13960  jam();
13961  rep->idle = 0 ;
13962  rep->tableId = lcpPtr.p->currentFragment.lcpFragOrd.tableId;
13963  rep->fragmentId = lcpPtr.p->currentFragment.lcpFragOrd.fragmentId;
13964  rep->lcpNo = lcpPtr.p->currentFragment.lcpFragOrd.lcpNo;
13965  rep->lcpId = lcpPtr.p->currentFragment.lcpFragOrd.lcpId;
13966  } else {
13967  jam();
13968  rep->idle = 1;
13969  rep->tableId = ~0;
13970  rep->fragmentId = ~0;
13971  rep->lcpNo = ~0;
13972  rep->lcpId = c_lcpId;
13973  }
13974 
13975  lcpPtr.p->m_EMPTY_LCP_REQ.copyto(NdbNodeBitmask::Size, sig->receiverGroup);
13976  sendSignal(DBDIH_REF, GSN_EMPTY_LCP_REP, signal,
13977  EmptyLcpRep::SignalLength + EmptyLcpConf::SignalLength, JBB);
13978 
13979  lcpPtr.p->reportEmpty = false;
13980  lcpPtr.p->m_EMPTY_LCP_REQ.clear();
13981 }//Dblqh::sendEMPTY_LCPCONF()
13982 
13983 /* --------------------------------------------------------------------------
13984  * THE LOCAL CHECKPOINT ROUND IS NOW COMPLETED. SEND COMPLETED MESSAGE
13985  * TO THE MASTER DIH.
13986  * ------------------------------------------------------------------------- */
13987 void Dblqh::completeLcpRoundLab(Signal* signal, Uint32 lcpId)
13988 {
13989  clcpCompletedState = LCP_CLOSE_STARTED;
13990 
13991  lcpPtr.i = 0;
13992  ptrAss(lcpPtr, lcpRecord);
13993  lcpPtr.p->m_outstanding = 0;
13994 
13995  EndLcpReq* req= (EndLcpReq*)signal->getDataPtr();
13996  req->senderData= lcpPtr.i;
13997  req->senderRef= reference();
13998  req->backupPtr= m_backup_ptr;
13999  req->backupId= lcpId;
14000 
14001  BlockReference backupRef = calcInstanceBlockRef(BACKUP);
14002 
14003  lcpPtr.p->m_outstanding++;
14004  sendSignal(backupRef, GSN_END_LCP_REQ, signal,
14005  EndLcpReq::SignalLength, JBB);
14006 
14007  if (!isNdbMtLqh())
14008  {
14009  jam();
14010  lcpPtr.p->m_outstanding++;
14011  sendSignal(PGMAN_REF, GSN_END_LCP_REQ, signal,
14012  EndLcpReq::SignalLength, JBB);
14013 
14014  lcpPtr.p->m_outstanding++;
14015  sendSignal(LGMAN_REF, GSN_END_LCP_REQ, signal,
14016  EndLcpReq::SignalLength, JBB);
14017 
14018  EXECUTE_DIRECT(TSMAN, GSN_END_LCP_REQ,
14019  signal, EndLcpReq::SignalLength, 0);
14020  }
14021  else
14022  {
14026  }
14027  return;
14028 }//Dblqh::completeLcpRoundLab()
14029 
14030 void Dblqh::execEND_LCPCONF(Signal* signal)
14031 {
14032  jamEntry();
14033  lcpPtr.i = 0;
14034  ptrAss(lcpPtr, lcpRecord);
14035 
14036  ndbrequire(clcpCompletedState == LCP_CLOSE_STARTED);
14037  ndbrequire(lcpPtr.p->m_outstanding);
14038 
14039  lcpPtr.p->m_outstanding--;
14040  if(lcpPtr.p->m_outstanding == 0)
14041  {
14042  jam();
14043  clcpCompletedState = LCP_IDLE;
14044  sendLCP_COMPLETE_REP(signal, lcpPtr.p->currentFragment.lcpFragOrd.lcpId);
14045 
14046  CRASH_INSERTION(5056);
14047  }
14048 }//Dblqh::execEND_LCPCONF()
14049 
14050 void Dblqh::sendLCP_COMPLETE_REP(Signal* signal, Uint32 lcpId)
14051 {
14052  cnoOfFragsCheckpointed = 0;
14053  ndbrequire((cnoOfNodes - 1) < (MAX_NDB_NODES - 1));
14054  /* ------------------------------------------------------------------------
14055  * WE SEND COMP_LCP_ROUND TO ALL NODES TO PREPARE FOR NODE CRASHES.
14056  * ----------------------------------------------------------------------- */
14057  lcpPtr.i = 0;
14058  ptrAss(lcpPtr, lcpRecord);
14059  lcpPtr.p->lastFragmentFlag = false;
14060  lcpPtr.p->firstFragmentFlag = false;
14061 
14062  LcpCompleteRep* rep = (LcpCompleteRep*)signal->getDataPtrSend();
14063  rep->nodeId = getOwnNodeId();
14064  rep->lcpId = lcpId;
14065  rep->blockNo = DBLQH;
14066 
14067  Uint32 ref = DBDIH_REF;
14068  if (isNdbMtLqh())
14069  {
14070  jam();
14071  ref = DBLQH_REF;
14072  }
14073  rep->nodeId = LcpFragRep::BROADCAST_REQ;
14074 
14075  sendSignal(ref, GSN_LCP_COMPLETE_REP, signal,
14076  LcpCompleteRep::SignalLength, JBB);
14077 
14078  if(lcpPtr.p->reportEmpty){
14079  jam();
14080  sendEMPTY_LCP_CONF(signal, true);
14081  }
14082 
14083  if (cstartRecReq < SRR_FIRST_LCP_DONE)
14084  {
14085  jam();
14086  ndbrequire(cstartRecReq == SRR_REDO_COMPLETE);
14087  cstartRecReq = SRR_FIRST_LCP_DONE;
14088  }
14089  return;
14090 
14091 }//Dblqh::sendCOMP_LCP_ROUND()
14092 
14093 #if NOT_YET
14094 void
14095 Dblqh::execLCP_COMPLETE_REP(Signal* signal)
14096 {
14100  LcpCompleteRep * rep = (LcpCompleteRep*)signal->getDataPtr();
14101  Uint32 keepGci = rep->keepGci;
14102  setLogTail(signal, keepGci);
14103 }
14104 #endif
14105 
14106 /* ------------------------------------------------------------------------- */
14107 /* ------- SEND ACC_LCPREQ AND TUP_LCPREQ ------- */
14108 /* */
14109 /* INPUT: LCP_PTR LOCAL CHECKPOINT RECORD */
14110 /* FRAGPTR FRAGMENT RECORD */
14111 /* SUBROUTINE SHORT NAME = STL */
14112 /* ------------------------------------------------------------------------- */
14113 void Dblqh::sendStartLcp(Signal* signal)
14114 {
14115 }//Dblqh::sendStartLcp()
14116 
14117 /* ------------------------------------------------------------------------- */
14118 /* ------- SET THE LOG TAIL IN THE LOG FILES ------- */
14119 /* */
14120 /*THIS SUBROUTINE HAVE BEEN BUGGY AND IS RATHER COMPLEX. IT IS IMPORTANT TO */
14121 /*REMEMBER THAT WE SEARCH FROM THE TAIL UNTIL WE REACH THE HEAD (CURRENT). */
14122 /*THE TAIL AND HEAD CAN BE ON THE SAME MBYTE. WE SEARCH UNTIL WE FIND A MBYTE*/
14123 /*THAT WE NEED TO KEEP. WE THEN SET THE TAIL TO BE THE PREVIOUS. IF WE DO */
14124 /*NOT FIND A MBYTE THAT WE NEED TO KEEP UNTIL WE REACH THE HEAD THEN WE USE */
14125 /*THE HEAD AS TAIL. FINALLY WE HAVE TO MOVE BACK THE TAIL TO ALSO INCLUDE */
14126 /*ALL PREPARE RECORDS. THIS MEANS THAT LONG-LIVED TRANSACTIONS ARE DANGEROUS */
14127 /*FOR SHORT LOGS. */
14128 /* ------------------------------------------------------------------------- */
14129 
14130 void Dblqh::setLogTail(Signal* signal, Uint32 keepGci)
14131 {
14132  LogPartRecordPtr sltLogPartPtr;
14133  LogFileRecordPtr sltLogFilePtr;
14134  UintR tsltMbyte;
14135  UintR tsltStartMbyte;
14136  UintR tsltIndex;
14137  UintR tsltFlag;
14138 
14139  for (sltLogPartPtr.i = 0; sltLogPartPtr.i < clogPartFileSize; sltLogPartPtr.i++) {
14140  jam();
14141  bool TchangeMB = false;
14142 retry:
14143  ptrAss(sltLogPartPtr, logPartRecord);
14144  findLogfile(signal, sltLogPartPtr.p->logTailFileNo,
14145  sltLogPartPtr, &sltLogFilePtr);
14146 
14147  tsltMbyte = sltLogPartPtr.p->logTailMbyte;
14148  tsltStartMbyte = tsltMbyte;
14149  tsltFlag = ZFALSE;
14150  if (sltLogFilePtr.i == sltLogPartPtr.p->currentLogfile) {
14151 /* ------------------------------------------------------------------------- */
14152 /*THE LOG AND THE TAIL IS ALREADY IN THE SAME FILE. */
14153 /* ------------------------------------------------------------------------- */
14154  if (sltLogFilePtr.p->currentMbyte >= sltLogPartPtr.p->logTailMbyte) {
14155  jam();
14156 /* ------------------------------------------------------------------------- */
14157 /*THE CURRENT MBYTE IS AHEAD OF OR AT THE TAIL. THUS WE WILL ONLY LOOK FOR */
14158 /*THE TAIL UNTIL WE REACH THE CURRENT MBYTE WHICH IS IN THIS LOG FILE. */
14159 /*IF THE LOG TAIL IS AHEAD OF THE CURRENT MBYTE BUT IN THE SAME LOG FILE */
14160 /*THEN WE HAVE TO SEARCH THROUGH ALL FILES BEFORE WE COME TO THE CURRENT */
14161 /*MBYTE. WE ALWAYS STOP WHEN WE COME TO THE CURRENT MBYTE SINCE THE TAIL */
14162 /*CAN NEVER BE BEFORE THE HEAD. */
14163 /* ------------------------------------------------------------------------- */
14164  tsltFlag = ZTRUE;
14165  }//if
14166  }//if
14167 
14168 /* ------------------------------------------------------------------------- */
14169 /*NOW START SEARCHING FOR THE NEW TAIL, STARTING AT THE CURRENT TAIL AND */
14170 /*PROCEEDING UNTIL WE FIND A MBYTE WHICH IS NEEDED TO KEEP OR UNTIL WE REACH */
14171 /*CURRENT MBYTE (THE HEAD). */
14172 /* ------------------------------------------------------------------------- */
14173  SLT_LOOP:
14174  for (tsltIndex = tsltStartMbyte;
14175  tsltIndex <= clogFileSize - 1;
14176  tsltIndex++) {
14177  if (sltLogFilePtr.p->logMaxGciStarted[tsltIndex] >= keepGci) {
14178 /* ------------------------------------------------------------------------- */
14179 /*WE ARE NOT ALLOWED TO STEP THE LOG ANY FURTHER AHEAD */
14180 /*SET THE NEW LOG TAIL AND CONTINUE WITH NEXT LOG PART. */
14181 /*THIS MBYTE IS NOT TO BE INCLUDED SO WE NEED TO STEP BACK ONE MBYTE. */
14182 /* ------------------------------------------------------------------------- */
14183  if (tsltIndex != 0) {
14184  jam();
14185  tsltMbyte = tsltIndex - 1;
14186  } else {
14187  jam();
14188 /* ------------------------------------------------------------------------- */
14189 /*STEPPING BACK INCLUDES ALSO STEPPING BACK TO THE PREVIOUS LOG FILE. */
14190 /* ------------------------------------------------------------------------- */
14191  tsltMbyte = clogFileSize - 1;
14192  sltLogFilePtr.i = sltLogFilePtr.p->prevLogFile;
14193  ptrCheckGuard(sltLogFilePtr, clogFileFileSize, logFileRecord);
14194  }//if
14195  goto SLT_BREAK;
14196  } else {
14197  jam();
14198  if (tsltFlag == ZTRUE) {
14199 /* ------------------------------------------------------------------------- */
14200 /*WE ARE IN THE SAME FILE AS THE CURRENT MBYTE AND WE CAN REACH THE CURRENT */
14201 /*MBYTE BEFORE WE REACH A NEW TAIL. */
14202 /* ------------------------------------------------------------------------- */
14203  if (tsltIndex == sltLogFilePtr.p->currentMbyte) {
14204  jam();
14205 /* ------------------------------------------------------------------------- */
14206 /*THE TAIL OF THE LOG IS ACTUALLY WITHIN THE CURRENT MBYTE. THUS WE SET THE */
14207 /*LOG TAIL TO BE THE CURRENT MBYTE. */
14208 /* ------------------------------------------------------------------------- */
14209  tsltMbyte = sltLogFilePtr.p->currentMbyte;
14210  goto SLT_BREAK;
14211  }//if
14212  }//if
14213  }//if
14214  }//for
14215  sltLogFilePtr.i = sltLogFilePtr.p->nextLogFile;
14216  ptrCheckGuard(sltLogFilePtr, clogFileFileSize, logFileRecord);
14217  if (sltLogFilePtr.i == sltLogPartPtr.p->currentLogfile) {
14218  jam();
14219  tsltFlag = ZTRUE;
14220  }//if
14221  tsltStartMbyte = 0;
14222  goto SLT_LOOP;
14223  SLT_BREAK:
14224  jam();
14225  {
14226  UintR ToldTailFileNo = sltLogPartPtr.p->logTailFileNo;
14227  UintR ToldTailMByte = sltLogPartPtr.p->logTailMbyte;
14228 
14229 /* ------------------------------------------------------------------------- */
14230 /*SINCE LOG_MAX_GCI_STARTED ONLY KEEP TRACK OF COMMIT LOG RECORDS WE ALSO */
14231 /*HAVE TO STEP BACK THE TAIL SO THAT WE INCLUDE ALL PREPARE RECORDS */
14232 /*NEEDED FOR THOSE COMMIT RECORDS IN THIS MBYTE. THIS IS A RATHER */
14233 /*CONSERVATIVE APPROACH BUT IT WORKS. */
14234 /* ------------------------------------------------------------------------- */
14235  arrGuard(tsltMbyte, clogFileSize);
14236  sltLogPartPtr.p->logTailFileNo =
14237  sltLogFilePtr.p->logLastPrepRef[tsltMbyte] >> 16;
14238  sltLogPartPtr.p->logTailMbyte =
14239  sltLogFilePtr.p->logLastPrepRef[tsltMbyte] & 65535;
14240 
14241  if (DEBUG_REDO)
14242  {
14243  ndbout_c("part: %u setLogTail(gci: %u): file: %u mb: %u",
14244  sltLogPartPtr.p->logPartNo,
14245  keepGci,
14246  sltLogPartPtr.p->logTailFileNo,
14247  sltLogPartPtr.p->logTailMbyte);
14248  }
14249 
14250  bool tailmoved = !(ToldTailFileNo == sltLogPartPtr.p->logTailFileNo &&
14251  ToldTailMByte == sltLogPartPtr.p->logTailMbyte);
14252 
14253  LogFileRecordPtr tmpfile;
14254  tmpfile.i = sltLogPartPtr.p->currentLogfile;
14255  ptrCheckGuard(tmpfile, clogFileFileSize, logFileRecord);
14256 
14257  LogPosition head = { tmpfile.p->fileNo, tmpfile.p->currentMbyte };
14258  LogPosition tail = { sltLogPartPtr.p->logTailFileNo,
14259  sltLogPartPtr.p->logTailMbyte};
14260  Uint64 mb = free_log(head, tail, sltLogPartPtr.p->noLogFiles,
14261  clogFileSize);
14262 
14263  if (mb <= c_free_mb_force_lcp_limit)
14264  {
14268  force_lcp(signal);
14269  }
14270 
14271  if (tailmoved && mb > c_free_mb_tail_problem_limit)
14272  {
14273  jam();
14274  update_log_problem(signal, sltLogPartPtr,
14275  LogPartRecord::P_TAIL_PROBLEM, false);
14276  }
14277  else if (!tailmoved && mb <= c_free_mb_force_lcp_limit)
14278  {
14279  jam();
14285  if (mb < 2)
14286  {
14290  jam();
14291  goto next;
14292  }
14293 
14294  if (TchangeMB)
14295  {
14296  jam();
14300  goto next;
14301  }
14302 
14303  TcConnectionrecPtr tmp;
14304  tmp.i = sltLogPartPtr.p->firstLogTcrec;
14305  if (tmp.i != RNIL)
14306  {
14307  jam();
14308  ptrCheckGuard(tmp, ctcConnectrecFileSize, tcConnectionrec);
14309  Uint32 fileNo = tmp.p->logStartFileNo;
14310  Uint32 mbyte = tmp.p->logStartPageNo >> ZTWOLOG_NO_PAGES_IN_MBYTE;
14311 
14312  if (fileNo == sltLogPartPtr.p->logTailFileNo &&
14313  mbyte == sltLogPartPtr.p->logTailMbyte)
14314  {
14315  jam();
14323  goto next;
14324  }
14325  }
14326 
14327  {
14331  jam();
14332  logPartPtr = sltLogPartPtr;
14333  logFilePtr.i = logPartPtr.p->currentLogfile;
14334  ptrCheckGuard(logFilePtr, clogFileFileSize, logFileRecord);
14335  logPagePtr.i = logFilePtr.p->currentLogpage;
14336  ptrCheckGuard(logPagePtr, clogPageFileSize, logPageRecord);
14337  changeMbyte(signal);
14338  TchangeMB = true; // don't try this twice...
14339  goto retry;
14340  }
14341  }
14342  }
14343 next:
14344  (void)1;
14345  }//for
14346 }//Dblqh::setLogTail()
14347 
14348 /* ######################################################################### */
14349 /* ####### GLOBAL CHECKPOINT MODULE ####### */
14350 /* */
14351 /* ######################################################################### */
14352 /*---------------------------------------------------------------------------*/
14353 /* THIS MODULE HELPS DIH IN DISCOVERING WHEN GLOBAL CHECKPOINTS ARE */
14354 /* RECOVERABLE. IT HANDLES THE REQUEST GCP_SAVEREQ THAT REQUESTS LQH TO */
14355 /* SAVE A PARTICULAR GLOBAL CHECKPOINT TO DISK AND RESPOND WHEN COMPLETED. */
14356 /*---------------------------------------------------------------------------*/
14357 /* *************** */
14358 /* GCP_SAVEREQ > */
14359 /* *************** */
14360 
14361 #if defined VM_TRACE || defined ERROR_INSERT
14362 static Uint32 m_gcp_monitor = 0;
14363 #endif
14364 
14365 void Dblqh::execGCP_SAVEREQ(Signal* signal)
14366 {
14367  jamEntry();
14368  const GCPSaveReq * const saveReq = (GCPSaveReq *)&signal->theData[0];
14369 
14370  CRASH_INSERTION(5000);
14371 
14372  if (ERROR_INSERTED(5007)){
14373  CLEAR_ERROR_INSERT_VALUE;
14374  sendSignalWithDelay(cownref, GSN_GCP_SAVEREQ, signal, 10000,
14375  signal->length());
14376  return;
14377  }
14378 
14379  if (unlikely(refToNode(signal->getSendersBlockRef()) != getOwnNodeId()))
14380  {
14389  ndbassert(!isMultiThreaded());
14390  jam();
14391  ndbassert(!ndb_check_micro_gcp
14392  (getNodeInfo(refToNode
14393  (signal->getSendersBlockRef())).m_version));
14394  EXECUTE_DIRECT(DBDIH, GSN_GCP_SAVEREQ, signal, signal->getLength());
14395  return;
14396  }
14397 
14398  const Uint32 dihBlockRef = saveReq->dihBlockRef;
14399  const Uint32 dihPtr = saveReq->dihPtr;
14400  const Uint32 gci = saveReq->gci;
14401 
14402 #if defined VM_TRACE || defined ERROR_INSERT
14403  if (!isNdbMtLqh()) { // wl4391_todo mt-safe
14404  ndbrequire(m_gcp_monitor == 0 ||
14405  (m_gcp_monitor == gci) ||
14406  (m_gcp_monitor + 1) == gci);
14407  }
14408  m_gcp_monitor = gci;
14409 #endif
14410 
14411  if(getNodeState().startLevel >= NodeState::SL_STOPPING_4){
14412  GCPSaveRef * const saveRef = (GCPSaveRef*)&signal->theData[0];
14413  saveRef->dihPtr = dihPtr;
14414  saveRef->nodeId = getOwnNodeId();
14415  saveRef->gci = gci;
14416  saveRef->errorCode = GCPSaveRef::NodeShutdownInProgress;
14417  sendSignal(dihBlockRef, GSN_GCP_SAVEREF, signal,
14418  GCPSaveRef::SignalLength, JBB);
14419  return;
14420  }
14421 
14422  Uint32 saveNewestCompletedGci = cnewestCompletedGci;
14423  cnewestCompletedGci = gci;
14424 
14425  if (cstartRecReq < SRR_REDO_COMPLETE)
14426  {
14430  GCPSaveRef * const saveRef = (GCPSaveRef*)&signal->theData[0];
14431  saveRef->dihPtr = dihPtr;
14432  saveRef->nodeId = getOwnNodeId();
14433  saveRef->gci = gci;
14434  saveRef->errorCode = GCPSaveRef::NodeRestartInProgress;
14435  sendSignal(dihBlockRef, GSN_GCP_SAVEREF, signal,
14436  GCPSaveRef::SignalLength, JBB);
14437  return;
14438  }
14439 
14440  ndbrequire(gci >= saveNewestCompletedGci);
14441 
14442  if (gci == saveNewestCompletedGci)
14443  {
14444 /*---------------------------------------------------------------------------*/
14445 /* GLOBAL CHECKPOINT HAVE ALREADY BEEN HANDLED. REQUEST MUST HAVE BEEN SENT */
14446 /* FROM NEW MASTER DIH. */
14447 /*---------------------------------------------------------------------------*/
14448  if (ccurrentGcprec == RNIL) {
14449  jam();
14450 /*---------------------------------------------------------------------------*/
14451 /* THIS INDICATES THAT WE HAVE ALREADY SENT GCP_SAVECONF TO PREVIOUS MASTER. */
14452 /* WE SIMPLY SEND IT ALSO TO THE NEW MASTER. */
14453 /*---------------------------------------------------------------------------*/
14454  GCPSaveConf * const saveConf = (GCPSaveConf*)&signal->theData[0];
14455  saveConf->dihPtr = dihPtr;
14456  saveConf->nodeId = getOwnNodeId();
14457  saveConf->gci = cnewestCompletedGci;
14458  sendSignal(dihBlockRef, GSN_GCP_SAVECONF, signal,
14459  GCPSaveConf::SignalLength, JBA);
14460  return;
14461  }
14462  jam();
14463 /*---------------------------------------------------------------------------*/
14464 /* WE HAVE NOT YET SENT THE RESPONSE TO THE OLD MASTER. WE WILL SET THE NEW */
14465 /* RECEIVER OF THE RESPONSE AND THEN EXIT SINCE THE PROCESS IS ALREADY */
14466 /* STARTED. */
14467 /*---------------------------------------------------------------------------*/
14468  gcpPtr.i = ccurrentGcprec;
14469  ptrCheckGuard(gcpPtr, cgcprecFileSize, gcpRecord);
14470  gcpPtr.p->gcpUserptr = dihPtr;
14471  gcpPtr.p->gcpBlockref = dihBlockRef;
14472  return;
14473  }//if
14474 
14475  ndbrequire(ccurrentGcprec == RNIL);
14476  cnewestCompletedGci = gci;
14477  if (gci > cnewestGci) {
14478  jam();
14479  cnewestGci = gci;
14480  }//if
14481 
14482  if(cstartRecReq < SRR_FIRST_LCP_DONE)
14483  {
14487  GCPSaveRef * const saveRef = (GCPSaveRef*)&signal->theData[0];
14488  saveRef->dihPtr = dihPtr;
14489  saveRef->nodeId = getOwnNodeId();
14490  saveRef->gci = gci;
14491  saveRef->errorCode = GCPSaveRef::NodeRestartInProgress;
14492  sendSignal(dihBlockRef, GSN_GCP_SAVEREF, signal,
14493  GCPSaveRef::SignalLength, JBB);
14494 
14495  if (ERROR_INSERTED(5052))
14496  {
14497  jam();
14498  signal->theData[0] = 9999;
14499  sendSignalWithDelay(CMVMI_REF, GSN_NDB_TAMPER, signal, 300, 1);
14500  }
14501  return;
14502  }
14503 
14504  CRASH_INSERTION(5052);
14505 
14506 #ifdef GCP_TIMER_HACK
14507  NdbTick_getMicroTimer(&globalData.gcp_timer_save[0]);
14508 #endif
14509 
14510  ccurrentGcprec = 0;
14511  gcpPtr.i = ccurrentGcprec;
14512  ptrCheckGuard(gcpPtr, cgcprecFileSize, gcpRecord);
14513 
14514  gcpPtr.p->gcpBlockref = dihBlockRef;
14515  gcpPtr.p->gcpUserptr = dihPtr;
14516  gcpPtr.p->gcpId = gci;
14517  bool tlogActive = false;
14518  for (logPartPtr.i = 0; logPartPtr.i < clogPartFileSize; logPartPtr.i++) {
14519  ptrAss(logPartPtr, logPartRecord);
14520  if (logPartPtr.p->logPartState == LogPartRecord::ACTIVE) {
14521  jam();
14522  logPartPtr.p->waitWriteGciLog = LogPartRecord::WWGL_TRUE;
14523  tlogActive = true;
14524  if (logPartPtr.p->LogLqhKeyReqSent == ZFALSE)
14525  {
14526  jam();
14527  logPartPtr.p->LogLqhKeyReqSent = ZTRUE;
14528  signal->theData[0] = ZLOG_LQHKEYREQ;
14529  signal->theData[1] = logPartPtr.i;
14530  sendSignal(cownref, GSN_CONTINUEB, signal, 2, JBB);
14531  }
14532  } else {
14533  jam();
14534  logPartPtr.p->waitWriteGciLog = LogPartRecord::WWGL_FALSE;
14535  logFilePtr.i = logPartPtr.p->currentLogfile;
14536  ptrCheckGuard(logFilePtr, clogFileFileSize, logFileRecord);
14537  logPagePtr.i = logFilePtr.p->currentLogpage;
14538  ptrCheckGuard(logPagePtr, clogPageFileSize, logPageRecord);
14539  writeCompletedGciLog(signal);
14540  }//if
14541  }//for
14542  if (tlogActive == true) {
14543  jam();
14544  return;
14545  }//if
14546  initGcpRecLab(signal);
14547  startTimeSupervision(signal);
14548  return;
14549 }//Dblqh::execGCP_SAVEREQ()
14550 
14555 void
14556 Dblqh::execSUB_GCP_COMPLETE_REP(Signal* signal)
14557 {
14558  jamEntry();
14559  Uint32 len = signal->getLength();
14560  EXECUTE_DIRECT(DBTUP, GSN_SUB_GCP_COMPLETE_REP, signal, len);
14561  sendSignal(SUMA_REF, GSN_SUB_GCP_COMPLETE_REP, signal, len, JBB);
14562 }
14563 
14564 /* ------------------------------------------------------------------------- */
14565 /* START TIME SUPERVISION OF THE LOG PARTS. */
14566 /* ------------------------------------------------------------------------- */
14567 void Dblqh::startTimeSupervision(Signal* signal)
14568 {
14569  for (logPartPtr.i = 0; logPartPtr.i < clogPartFileSize; logPartPtr.i++) {
14570  jam();
14571  ptrAss(logPartPtr, logPartRecord);
14572 /* +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ */
14573 /* WE HAVE TO START CHECKING IF THE LOG IS TO BE WRITTEN EVEN IF PAGES ARE */
14574 /* FULL. INITIALISE THE VALUES OF WHERE WE ARE IN THE LOG CURRENTLY. */
14575 /* +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ */
14576  logPartPtr.p->logPartTimer = 0;
14577  logPartPtr.p->logTimer = 1;
14578  signal->theData[0] = ZTIME_SUPERVISION;
14579  signal->theData[1] = logPartPtr.i;
14580  sendSignal(cownref, GSN_CONTINUEB, signal, 2, JBB);
14581  }//for
14582 }//Dblqh::startTimeSupervision()
14583 
14584 /*---------------------------------------------------------------------------*/
14585 /* WE SET THE GLOBAL CHECKPOINT VARIABLES AFTER WRITING THE COMPLETED GCI LOG*/
14586 /* RECORD. THIS ENSURES THAT WE WILL ENCOUNTER THE COMPLETED GCI RECORD WHEN */
14587 /* WE EXECUTE THE FRAGMENT LOG. */
14588 /*---------------------------------------------------------------------------*/
14589 void Dblqh::initGcpRecLab(Signal* signal)
14590 {
14591 /* ======================================================================== */
14592 /* ======= INITIATE GCP RECORD ======= */
14593 /* */
14594 /* SUBROUTINE SHORT NAME = IGR */
14595 /* ======================================================================== */
14596  for (logPartPtr.i = 0; logPartPtr.i < clogPartFileSize; logPartPtr.i++) {
14597  jam();
14598  ptrAss(logPartPtr, logPartRecord);
14599 /*--------------------------------------------------*/
14600 /* BY SETTING THE GCPREC = 0 WE START THE */
14601 /* CHECKING BY CHECK_GCP_COMPLETED. THIS */
14602 /* CHECKING MUST NOT BE STARTED UNTIL WE HAVE */
14603 /* INSERTED ALL COMPLETE GCI LOG RECORDS IN */
14604 /* ALL LOG PARTS. */
14605 /*--------------------------------------------------*/
14606  logPartPtr.p->gcprec = 0;
14607  gcpPtr.p->gcpLogPartState[logPartPtr.i] = ZWAIT_DISK;
14608  gcpPtr.p->gcpSyncReady[logPartPtr.i] = ZFALSE;
14609  logFilePtr.i = logPartPtr.p->currentLogfile;
14610  ptrCheckGuard(logFilePtr, clogFileFileSize, logFileRecord);
14611  gcpPtr.p->gcpFilePtr[logPartPtr.i] = logFilePtr.i;
14612  logPagePtr.i = logFilePtr.p->currentLogpage;
14613  ptrCheckGuard(logPagePtr, clogPageFileSize, logPageRecord);
14614  if (logPagePtr.p->logPageWord[ZCURR_PAGE_INDEX] == ZPAGE_HEADER_SIZE) {
14615  jam();
14616 /*--------------------------------------------------*/
14617 /* SINCE THE CURRENT FILEPAGE POINTS AT THE */
14618 /* NEXT WORD TO BE WRITTEN WE HAVE TO ADJUST */
14619 /* FOR THIS BY DECREASING THE FILE PAGE BY ONE*/
14620 /* IF NO WORD HAS BEEN WRITTEN ON THE CURRENT */
14621 /* FILEPAGE. */
14622 /*--------------------------------------------------*/
14623  gcpPtr.p->gcpPageNo[logPartPtr.i] = logFilePtr.p->currentFilepage - 1;
14624  gcpPtr.p->gcpWordNo[logPartPtr.i] = ZPAGE_SIZE - 1;
14625  } else {
14626  jam();
14627  gcpPtr.p->gcpPageNo[logPartPtr.i] = logFilePtr.p->currentFilepage;
14628  gcpPtr.p->gcpWordNo[logPartPtr.i] =
14629  logPagePtr.p->logPageWord[ZCURR_PAGE_INDEX] - 1;
14630  }//if
14631  }//for
14632  // initialize un-used part
14633  Uint32 Ti;
14634  for (Ti = clogPartFileSize; Ti < ZLOG_PART_FILE_SIZE; Ti++) {
14635  gcpPtr.p->gcpFilePtr[Ti] = ZNIL;
14636  gcpPtr.p->gcpPageNo[Ti] = ZNIL;
14637  gcpPtr.p->gcpSyncReady[Ti] = FALSE;
14638  gcpPtr.p->gcpWordNo[Ti] = ZNIL;
14639  }
14640  return;
14641 }//Dblqh::initGcpRecLab()
14642 
14643 /* ========================================================================= */
14644 /* ==== CHECK IF ANY GLOBAL CHECKPOINTS ARE COMPLETED AFTER A COMPLETED===== */
14645 /* DISK WRITE. */
14646 /* */
14647 /* SUBROUTINE SHORT NAME = CGC */
14648 /* return: true if gcp was completed */
14649 /* ========================================================================= */
14650 bool
14651 Dblqh::checkGcpCompleted(Signal* signal,
14652  Uint32 tcgcPageWritten,
14653  Uint32 tcgcWordWritten)
14654 {
14655  UintR tcgcFlag;
14656  UintR tcgcJ;
14657 
14658  gcpPtr.i = logPartPtr.p->gcprec;
14659  if (gcpPtr.i != RNIL)
14660  {
14661  jam();
14662 /* ------------------------------------------------------------------------- */
14663 /* IF THE GLOBAL CHECKPOINT IS NOT WAITING FOR COMPLETION THEN WE CAN QUIT */
14664 /* THE SEARCH IMMEDIATELY. */
14665 /* ------------------------------------------------------------------------- */
14666  ptrCheckGuard(gcpPtr, cgcprecFileSize, gcpRecord);
14667  if (gcpPtr.p->gcpFilePtr[logPartPtr.i] == logFilePtr.i) {
14668 /* ------------------------------------------------------------------------- */
14669 /* IF THE COMPLETED DISK OPERATION WAS ON ANOTHER FILE THAN THE ONE WE ARE */
14670 /* WAITING FOR, THEN WE CAN ALSO QUIT THE SEARCH IMMEDIATELY. */
14671 /* ------------------------------------------------------------------------- */
14672  if (tcgcPageWritten < gcpPtr.p->gcpPageNo[logPartPtr.i]) {
14673  jam();
14674 /* ------------------------------------------------------------------------- */
14675 /* THIS LOG PART HAVE NOT YET WRITTEN THE GLOBAL CHECKPOINT TO DISK. */
14676 /* ------------------------------------------------------------------------- */
14677  return false;
14678  } else {
14679  if (tcgcPageWritten == gcpPtr.p->gcpPageNo[logPartPtr.i]) {
14680  if (tcgcWordWritten < gcpPtr.p->gcpWordNo[logPartPtr.i]) {
14681  jam();
14682 /* ------------------------------------------------------------------------- */
14683 /* THIS LOG PART HAVE NOT YET WRITTEN THE GLOBAL CHECKPOINT TO DISK. */
14684 /* ------------------------------------------------------------------------- */
14685  return false;
14686  }//if
14687  }//if
14688  }//if
14689 /* ------------------------------------------------------------------------- */
14690 /* THIS LOG PART HAVE WRITTEN THE GLOBAL CHECKPOINT TO DISK. */
14691 /* ------------------------------------------------------------------------- */
14692  logPartPtr.p->gcprec = RNIL;
14693  gcpPtr.p->gcpLogPartState[logPartPtr.i] = ZON_DISK;
14694  tcgcFlag = ZTRUE;
14695  for (tcgcJ = 0; tcgcJ < clogPartFileSize; tcgcJ++)
14696  {
14697  jam();
14698  if (gcpPtr.p->gcpLogPartState[tcgcJ] != ZON_DISK) {
14699  jam();
14700 /* ------------------------------------------------------------------------- */
14701 /*ALL LOG PARTS HAVE NOT SAVED THIS GLOBAL CHECKPOINT TO DISK YET. WAIT FOR */
14702 /*THEM TO COMPLETE. */
14703 /* ------------------------------------------------------------------------- */
14704  tcgcFlag = ZFALSE;
14705  }//if
14706  }//for
14707  if (tcgcFlag == ZFALSE)
14708  {
14709  return false;
14710  }
14711 
14712  if (tcgcFlag == ZTRUE)
14713  {
14714  jam();
14715 /* ------------------------------------------------------------------------- */
14716 /*WE HAVE FOUND A COMPLETED GLOBAL CHECKPOINT OPERATION. WE NOW NEED TO SEND */
14717 /*GCP_SAVECONF, REMOVE THE GCP RECORD FROM THE LIST OF WAITING GCP RECORDS */
14718 /*ON THIS LOG PART AND RELEASE THE GCP RECORD. */
14719 // After changing the log implementation we need to perform a FSSYNCREQ on all
14720 // log files where the last log word resided first before proceeding.
14721 /* ------------------------------------------------------------------------- */
14722  UintR Ti;
14723  for (Ti = 0; Ti < clogPartFileSize; Ti++) {
14724  LogFileRecordPtr loopLogFilePtr;
14725  loopLogFilePtr.i = gcpPtr.p->gcpFilePtr[Ti];
14726  ptrCheckGuard(loopLogFilePtr, clogFileFileSize, logFileRecord);
14727  if (loopLogFilePtr.p->logFileStatus == LogFileRecord::OPEN) {
14728  jam();
14729  signal->theData[0] = loopLogFilePtr.p->fileRef;
14730  signal->theData[1] = cownref;
14731  signal->theData[2] = gcpPtr.p->gcpFilePtr[Ti];
14732  sendSignal(NDBFS_REF, GSN_FSSYNCREQ, signal, 3, JBA);
14733  } else {
14734  ndbrequire((loopLogFilePtr.p->logFileStatus ==
14736  (loopLogFilePtr.p->logFileStatus ==
14738  (loopLogFilePtr.p->logFileStatus ==
14740  signal->theData[0] = loopLogFilePtr.i;
14741  execFSSYNCCONF(signal);
14742  }//if
14743  }//for
14744  }//if
14745  }//if
14746  return true;
14747  }//if
14748  return false;
14749 }//Dblqh::checkGcpCompleted()
14750 
14751 void
14752 Dblqh::execFSSYNCCONF(Signal* signal)
14753 {
14754  GcpRecordPtr localGcpPtr;
14755  LogFileRecordPtr localLogFilePtr;
14756  LogPartRecordPtr localLogPartPtr;
14757  localLogFilePtr.i = signal->theData[0];
14758  ptrCheckGuard(localLogFilePtr, clogFileFileSize, logFileRecord);
14759  localLogPartPtr.i = localLogFilePtr.p->logPartRec;
14760  ptrCheckGuard(localLogPartPtr, clogPartFileSize, logPartRecord);
14761  localGcpPtr.i = ccurrentGcprec;
14762  ptrCheckGuard(localGcpPtr, cgcprecFileSize, gcpRecord);
14763  localGcpPtr.p->gcpSyncReady[localLogPartPtr.i] = ZTRUE;
14764  UintR Ti;
14765 
14766  if (DEBUG_REDO)
14767  {
14768  ndbout_c("part: %u file: %u gci: %u SYNC CONF",
14769  localLogPartPtr.p->logPartNo,
14770  localLogFilePtr.p->fileNo,
14771  localGcpPtr.p->gcpId);
14772  }
14773  for (Ti = 0; Ti < clogPartFileSize; Ti++) {
14774  jam();
14775  if (localGcpPtr.p->gcpSyncReady[Ti] == ZFALSE) {
14776  jam();
14777  return;
14778  }//if
14779  }//for
14780 
14781 #ifdef GCP_TIMER_HACK
14782  NdbTick_getMicroTimer(&globalData.gcp_timer_save[1]);
14783 #endif
14784 
14785  GCPSaveConf * const saveConf = (GCPSaveConf *)&signal->theData[0];
14786  saveConf->dihPtr = localGcpPtr.p->gcpUserptr;
14787  saveConf->nodeId = getOwnNodeId();
14788  saveConf->gci = localGcpPtr.p->gcpId;
14789  sendSignal(localGcpPtr.p->gcpBlockref, GSN_GCP_SAVECONF, signal,
14790  GCPSaveConf::SignalLength, JBA);
14791  ccurrentGcprec = RNIL;
14792 }//Dblqh::execFSSYNCCONF()
14793 
14794 
14795 /* ######################################################################### */
14796 /* ####### FILE HANDLING MODULE ####### */
14797 /* */
14798 /* ######################################################################### */
14799 /* THIS MODULE HANDLES RESPONSE MESSAGES FROM THE FILE SYSTEM */
14800 /* ######################################################################### */
14801 /* ######################################################################### */
14802 /* SIGNAL RECEPTION MODULE */
14803 /* THIS MODULE IS A SUB-MODULE OF THE FILE SYSTEM HANDLING. */
14804 /* */
14805 /* THIS MODULE CHECKS THE STATE AND JUMPS TO THE PROPER PART OF THE FILE */
14806 /* HANDLING MODULE. */
14807 /* ######################################################################### */
14808 /* *************** */
14809 /* FSCLOSECONF > */
14810 /* *************** */
14811 void Dblqh::execFSCLOSECONF(Signal* signal)
14812 {
14813  jamEntry();
14814  logFilePtr.i = signal->theData[0];
14815  ptrCheckGuard(logFilePtr, clogFileFileSize, logFileRecord);
14816  logFilePtr.p->fileRef = RNIL;
14817 
14818  if (DEBUG_REDO)
14819  {
14820  logPartPtr.i = logFilePtr.p->logPartRec;
14821  ptrCheckGuard(logPartPtr, clogPartFileSize, logPartRecord);
14822  ndbout_c("part: %u file: %u CLOSE CONF",
14823  logPartPtr.p->logPartNo,
14824  logFilePtr.p->fileNo);
14825  }
14826 
14827  switch (logFilePtr.p->logFileStatus) {
14828  case LogFileRecord::CLOSE_SR_READ_INVALIDATE_PAGES:
14829  jam();
14830  logFilePtr.p->logFileStatus = LogFileRecord::CLOSED;
14831 
14832  logPartPtr.i = logFilePtr.p->logPartRec;
14833  ptrCheckGuard(logPartPtr, clogPartFileSize, logPartRecord);
14834 
14835  readFileInInvalidate(signal, 2);
14836  return;
14837 
14838  case LogFileRecord::CLOSE_SR_READ_INVALIDATE_SEARCH_FILES:
14839  jam();
14840  logFilePtr.p->logFileStatus = LogFileRecord::CLOSED;
14841 
14842  logPartPtr.i = logFilePtr.p->logPartRec;
14843  ptrCheckGuard(logPartPtr, clogPartFileSize, logPartRecord);
14844 
14845  readFileInInvalidate(signal, 4);
14846  return;
14847  case LogFileRecord::CLOSE_SR_READ_INVALIDATE_SEARCH_LAST_FILE:
14848  logFilePtr.p->logFileStatus = LogFileRecord::CLOSED;
14849 
14850  logPartPtr.i = logFilePtr.p->logPartRec;
14851  ptrCheckGuard(logPartPtr, clogPartFileSize, logPartRecord);
14852 
14853  readFileInInvalidate(signal, 7);
14854  return;
14855  case LogFileRecord::CLOSE_SR_WRITE_INVALIDATE_PAGES:
14856  jam();
14857  logFilePtr.p->logFileStatus = LogFileRecord::CLOSED;
14858 
14859  logPartPtr.i = logFilePtr.p->logPartRec;
14860  ptrCheckGuard(logPartPtr, clogPartFileSize, logPartRecord);
14861 
14862  writeFileInInvalidate(signal, 1);
14863  return;
14864  case LogFileRecord::CLOSING_INIT:
14865  jam();
14866  logFileInitDone++ ;
14867  closingInitLab(signal);
14868  return;
14870  jam();
14871  closingSrLab(signal);
14872  return;
14874  jam();
14875  closeExecSrLab(signal);
14876  return;
14877  case LogFileRecord::CLOSING_EXEC_SR_COMPLETED:
14878  jam();
14879  closeExecSrCompletedLab(signal);
14880  return;
14882  jam();
14883  closeWriteLogLab(signal);
14884  return;
14885  case LogFileRecord::CLOSING_EXEC_LOG:
14886  jam();
14887  closeExecLogLab(signal);
14888  return;
14889 #ifndef NO_REDO_OPEN_FILE_CACHE
14890  case LogFileRecord::CLOSING_EXEC_LOG_CACHED:
14891  jam();
14892  logFilePtr.p->logFileStatus = LogFileRecord::CLOSED;
14893  release(signal, m_redo_open_file_cache);
14894  return;
14895 #endif
14896  default:
14897  jam();
14898  systemErrorLab(signal, __LINE__);
14899  return;
14900  }//switch
14901 }//Dblqh::execFSCLOSECONF()
14902 
14903 
14904 /* ************>> */
14905 /* FSOPENCONF > */
14906 /* ************>> */
14907 void Dblqh::execFSOPENCONF(Signal* signal)
14908 {
14909  jamEntry();
14910  initFsopenconf(signal);
14911  switch (logFilePtr.p->logFileStatus) {
14912  case LogFileRecord::OPEN_SR_READ_INVALIDATE_PAGES:
14913  jam();
14914  logFilePtr.p->logFileStatus = LogFileRecord::OPEN;
14915  readFileInInvalidate(signal, 0);
14916  return;
14917  case LogFileRecord::OPEN_SR_READ_INVALIDATE_SEARCH_FILES:
14918  jam();
14919  logFilePtr.p->logFileStatus = LogFileRecord::OPEN;
14920  readFileInInvalidate(signal, 5);
14921  return;
14922  case LogFileRecord::OPEN_SR_WRITE_INVALIDATE_PAGES:
14923  jam();
14924  logFilePtr.p->logFileStatus = LogFileRecord::OPEN;
14925  writeFileInInvalidate(signal, 0);
14926  return;
14927  case LogFileRecord::OPENING_INIT:
14928  jam();
14929  logFilePtr.p->logFileStatus = LogFileRecord::OPEN;
14930  openFileInitLab(signal);
14931  return;
14933  jam();
14934  logFilePtr.p->logFileStatus = LogFileRecord::OPEN;
14935  openSrFrontpageLab(signal);
14936  return;
14938  jam();
14939  logFilePtr.p->logFileStatus = LogFileRecord::OPEN;
14940  openSrLastFileLab(signal);
14941  return;
14943  jam();
14944  logFilePtr.p->logFileStatus = LogFileRecord::OPEN;
14945  openSrNextFileLab(signal);
14946  return;
14948  jam();
14949  logFilePtr.p->logFileStatus = LogFileRecord::OPEN;
14950  openExecSrStartLab(signal);
14951  return;
14952  case LogFileRecord::OPEN_EXEC_SR_NEW_MBYTE:
14953  jam();
14954  logFilePtr.p->logFileStatus = LogFileRecord::OPEN;
14955  openExecSrNewMbyteLab(signal);
14956  return;
14957  case LogFileRecord::OPEN_SR_FOURTH_PHASE:
14958  jam();
14959  logFilePtr.p->logFileStatus = LogFileRecord::OPEN;
14960  openSrFourthPhaseLab(signal);
14961  return;
14962  case LogFileRecord::OPEN_SR_FOURTH_NEXT:
14963  jam();
14964  logFilePtr.p->logFileStatus = LogFileRecord::OPEN;
14965  openSrFourthNextLab(signal);
14966  return;
14967  case LogFileRecord::OPEN_SR_FOURTH_ZERO:
14968  jam();
14969  logFilePtr.p->logFileStatus = LogFileRecord::OPEN;
14970  openSrFourthZeroLab(signal);
14971  return;
14973  jam();
14974  logFilePtr.p->logFileStatus = LogFileRecord::OPEN;
14975  return;
14976  case LogFileRecord::OPEN_EXEC_LOG:
14977  jam();
14978  logFilePtr.p->logFileStatus = LogFileRecord::OPEN;
14979 #ifndef NO_REDO_OPEN_FILE_CACHE
14980  {
14981  jam();
14982  m_redo_open_file_cache.m_lru.addFirst(logFilePtr);
14983  }
14984  // Fall through
14985  case LogFileRecord::OPEN_EXEC_LOG_CACHED:
14986  jam();
14987 #endif
14988  openExecLogLab(signal);
14989  return;
14990  default:
14991  jam();
14992  systemErrorLab(signal, __LINE__);
14993  return;
14994  }//switch
14995 }//Dblqh::execFSOPENCONF()
14996 
14997 void
14998 Dblqh::execFSOPENREF(Signal* signal)
14999 {
15000  jamEntry();
15001  FsRef* ref = (FsRef*)signal->getDataPtr();
15002  Uint32 err = ref->errorCode;
15003  if (err == FsRef::fsErrInvalidFileSize)
15004  {
15005  char buf[256];
15006  BaseString::snprintf(buf, sizeof(buf),
15007  "Invalid file size for redo logfile, "
15008  " size only changable with --initial");
15009  progError(__LINE__,
15010  NDBD_EXIT_INVALID_CONFIG,
15011  buf);
15012  return;
15013  }
15014 
15015  SimulatedBlock::execFSOPENREF(signal);
15016 }
15017 
15018 /* ************>> */
15019 /* FSREADCONF > */
15020 /* ************>> */
15021 void Dblqh::execFSREADCONF(Signal* signal)
15022 {
15023  jamEntry();
15024  initFsrwconf(signal, false);
15025 
15026  switch (lfoPtr.p->lfoState) {
15027  case LogFileOperationRecord::READ_SR_LAST_MBYTE:
15028  jam();
15029  releaseLfo(signal);
15030  readSrLastMbyteLab(signal);
15031  return;
15033  jam();
15034  releaseLfo(signal);
15035  readSrFrontpageLab(signal);
15036  return;
15038  jam();
15039  releaseLfo(signal);
15040  readSrLastFileLab(signal);
15041  return;
15043  jam();
15044  releaseLfo(signal);
15045  readSrNextFileLab(signal);
15046  return;
15047  case LogFileOperationRecord::READ_EXEC_SR:
15048  jam();
15049  readExecSrLab(signal);
15050  return;
15051  case LogFileOperationRecord::READ_EXEC_LOG:
15052  jam();
15053  readExecLogLab(signal);
15054  return;
15055  case LogFileOperationRecord::READ_SR_INVALIDATE_PAGES:
15056  jam();
15057  invalidateLogAfterLastGCI(signal);
15058  return;
15059  case LogFileOperationRecord::READ_SR_INVALIDATE_SEARCH_FILES:
15060  jam();
15061  invalidateLogAfterLastGCI(signal);
15062  return;
15063  case LogFileOperationRecord::READ_SR_FOURTH_PHASE:
15064  jam();
15065  releaseLfo(signal);
15066  readSrFourthPhaseLab(signal);
15067  return;
15068  case LogFileOperationRecord::READ_SR_FOURTH_ZERO:
15069  jam();
15070  releaseLfo(signal);
15071  readSrFourthZeroLab(signal);
15072  return;
15073  default:
15074  jam();
15075  systemErrorLab(signal, __LINE__);
15076  return;
15077  }//switch
15078 }//Dblqh::execFSREADCONF()
15079 
15080 /* ************>> */
15081 /* FSREADCONF > */
15082 /* ************>> */
15083 void Dblqh::execFSREADREF(Signal* signal)
15084 {
15085  jamEntry();
15086  lfoPtr.i = signal->theData[0];
15087  ptrCheckGuard(lfoPtr, clfoFileSize, logFileOperationRecord);
15088  switch (lfoPtr.p->lfoState) {
15089  case LogFileOperationRecord::READ_SR_LAST_MBYTE:
15090  jam();
15091  break;
15093  jam();
15094  break;
15096  jam();
15097  break;
15099  jam();
15100  break;
15101  case LogFileOperationRecord::READ_EXEC_SR:
15102  jam();
15103  break;
15104  case LogFileOperationRecord::READ_EXEC_LOG:
15105  jam();
15106  break;
15107  case LogFileOperationRecord::READ_SR_FOURTH_PHASE:
15108  jam();
15109  break;
15110  case LogFileOperationRecord::READ_SR_FOURTH_ZERO:
15111  jam();
15112  break;
15113  case LogFileOperationRecord::READ_SR_INVALIDATE_PAGES:
15114  jam();
15115  break;
15116  default:
15117  jam();
15118  break;
15119  }//switch
15120  {
15121  char msg[100];
15122  sprintf(msg, "File system read failed during LogFileOperationRecord state %d", (Uint32)lfoPtr.p->lfoState);
15123  fsRefError(signal,__LINE__,msg);
15124  }
15125 }//Dblqh::execFSREADREF()
15126 
15127 /* *************** */
15128 /* FSWRITECONF > */
15129 /* *************** */
15130 void Dblqh::execFSWRITECONF(Signal* signal)
15131 {
15132  jamEntry();
15133  initFsrwconf(signal, true);
15134  switch (lfoPtr.p->lfoState) {
15135  case LogFileOperationRecord::WRITE_SR_INVALIDATE_PAGES:
15136  jam();
15137  invalidateLogAfterLastGCI(signal);
15138  CRASH_INSERTION(5047);
15139  return;
15140  case LogFileOperationRecord::WRITE_PAGE_ZERO:
15141  jam();
15142  writePageZeroLab(signal, __LINE__);
15143  releaseLfo(signal);
15144  return;
15145  case LogFileOperationRecord::LAST_WRITE_IN_FILE:
15146  jam();
15147  lastWriteInFileLab(signal);
15148  return;
15150  jam();
15151  initWriteEndLab(signal);
15152  return;
15154  jam();
15155  logMBytesInitDone++;
15156  initFirstPageLab(signal);
15157  return;
15158  case LogFileOperationRecord::WRITE_GCI_ZERO:
15159  jam();
15160  writeGciZeroLab(signal);
15161  return;
15162  case LogFileOperationRecord::WRITE_DIRTY:
15163  jam();
15164  writeDirtyLab(signal);
15165  return;
15166  case LogFileOperationRecord::WRITE_INIT_MBYTE:
15167  jam();
15168  logMBytesInitDone++;
15169  writeInitMbyteLab(signal);
15170  return;
15172  jam();
15173  writeLogfileLab(signal);
15174  return;
15175  case LogFileOperationRecord::FIRST_PAGE_WRITE_IN_LOGFILE:
15176  jam();
15177  firstPageWriteLab(signal);
15178  return;
15179  case LogFileOperationRecord::WRITE_SR_INVALIDATE_PAGES_UPDATE_PAGE0:
15180  jam();
15181  // We are done...send completed signal and exit this phase.
15182  releaseLfo(signal);
15183  signal->theData[0] = ZSR_FOURTH_COMP;
15184  signal->theData[1] = logPartPtr.i;
15185  sendSignal(cownref, GSN_CONTINUEB, signal, 2, JBB);
15186  return;
15187  default:
15188  jam();
15189  systemErrorLab(signal, __LINE__);
15190  return;
15191  }//switch
15192 }//Dblqh::execFSWRITECONF()
15193 
15194 /* ************>> */
15195 /* FSWRITEREF > */
15196 /* ************>> */
15197 void Dblqh::execFSWRITEREF(Signal* signal)
15198 {
15199  jamEntry();
15200  lfoPtr.i = signal->theData[0];
15201  ptrCheckGuard(lfoPtr, clfoFileSize, logFileOperationRecord);
15202  terrorCode = signal->theData[1];
15203  switch (lfoPtr.p->lfoState) {
15204  case LogFileOperationRecord::WRITE_PAGE_ZERO:
15205  jam();
15206  break;
15207  case LogFileOperationRecord::LAST_WRITE_IN_FILE:
15208  jam();
15209  break;
15211  jam();
15212  break;
15214  jam();
15215  break;
15216  case LogFileOperationRecord::WRITE_GCI_ZERO:
15217  jam();
15218  break;
15219  case LogFileOperationRecord::WRITE_DIRTY:
15220  jam();
15221  break;
15222  case LogFileOperationRecord::WRITE_INIT_MBYTE:
15223  jam();
15224  break;
15226  jam();
15227  break;
15228  case LogFileOperationRecord::FIRST_PAGE_WRITE_IN_LOGFILE:
15229  jam();
15230  break;
15231  case LogFileOperationRecord::WRITE_SR_INVALIDATE_PAGES:
15232  jam();
15233  systemErrorLab(signal, __LINE__);
15234  default:
15235  jam();
15236  break;
15237  }//switch
15238  {
15239  char msg[100];
15240  sprintf(msg, "File system write failed during LogFileOperationRecord state %d", (Uint32)lfoPtr.p->lfoState);
15241  fsRefError(signal,__LINE__,msg);
15242  }
15243 }//Dblqh::execFSWRITEREF()
15244 
15245 
15246 /* ========================================================================= */
15247 /* ======= INITIATE WHEN RECEIVING FSOPENCONF ======= */
15248 /* */
15249 /* ========================================================================= */
15250 void Dblqh::initFsopenconf(Signal* signal)
15251 {
15252  logFilePtr.i = signal->theData[0];
15253  ptrCheckGuard(logFilePtr, clogFileFileSize, logFileRecord);
15254  logFilePtr.p->fileRef = signal->theData[1];
15255  logPartPtr.i = logFilePtr.p->logPartRec;
15256  ptrCheckGuard(logPartPtr, clogPartFileSize, logPartRecord);
15257  logFilePtr.p->currentMbyte = 0;
15258  logFilePtr.p->filePosition = 0;
15259 }//Dblqh::initFsopenconf()
15260 
15261 /* ========================================================================= */
15262 /* ======= INITIATE WHEN RECEIVING FSREADCONF AND FSWRITECONF ======= */
15263 /* */
15264 /* ========================================================================= */
15265 void Dblqh::initFsrwconf(Signal* signal, bool write)
15266 {
15267  LogPageRecordPtr logP;
15268  Uint32 noPages, totPages;
15269  lfoPtr.i = signal->theData[0];
15270  ptrCheckGuard(lfoPtr, clfoFileSize, logFileOperationRecord);
15271  totPages= lfoPtr.p->noPagesRw;
15272  logFilePtr.i = lfoPtr.p->logFileRec;
15273  ptrCheckGuard(logFilePtr, clogFileFileSize, logFileRecord);
15274  logPartPtr.i = logFilePtr.p->logPartRec;
15275  ptrCheckGuard(logPartPtr, clogPartFileSize, logPartRecord);
15276  logPagePtr.i = lfoPtr.p->firstLfoPage;
15277  ptrCheckGuard(logPagePtr, clogPageFileSize, logPageRecord);
15278  logP= logPagePtr;
15279  noPages= 1;
15280  ndbassert(totPages > 0);
15281 
15282  if (write)
15283  {
15284  Uint32 bytesWritten = totPages * 32768;
15285  logPartPtr.p->m_io_tracker.complete_io(bytesWritten);
15286  }
15287 
15288  for (;;)
15289  {
15290  logP.p->logPageWord[ZPOS_IN_WRITING]= 0;
15291  logP.p->logPageWord[ZPOS_IN_FREE_LIST]= 0;
15292  if (noPages == totPages)
15293  return;
15294  if (write)
15295  logP.i= logP.p->logPageWord[ZNEXT_PAGE];
15296  else
15297  logP.i= lfoPtr.p->logPageArray[noPages];
15298  ptrCheckGuard(logP, clogPageFileSize, logPageRecord);
15299  noPages++;
15300  }
15301 
15302 }//Dblqh::initFsrwconf()
15303 
15304 /* ######################################################################### */
15305 /* NORMAL OPERATION MODULE */
15306 /* THIS MODULE IS A SUB-MODULE OF THE FILE SYSTEM HANDLING. */
15307 /* */
15308 /* THIS PART HANDLES THE NORMAL OPENING, CLOSING AND WRITING OF LOG FILES */
15309 /* DURING NORMAL OPERATION. */
15310 /* ######################################################################### */
15311 /*---------------------------------------------------------------------------*/
15312 /* THIS SIGNAL IS USED TO SUPERVISE THAT THE LOG RECORDS ARE NOT KEPT IN MAIN*/
15313 /* MEMORY FOR MORE THAN 1 SECOND TO ACHIEVE THE PROPER RELIABILITY. */
15314 /*---------------------------------------------------------------------------*/
15315 void Dblqh::timeSup(Signal* signal)
15316 {
15317  LogPageRecordPtr origLogPagePtr;
15318  Uint32 wordWritten;
15319 
15320  jamEntry();
15321  logPartPtr.i = signal->theData[0];
15322  ptrCheckGuard(logPartPtr, clogPartFileSize, logPartRecord);
15323  logFilePtr.i = logPartPtr.p->currentLogfile;
15324  ptrCheckGuard(logFilePtr, clogFileFileSize, logFileRecord);
15325  logPagePtr.i = logFilePtr.p->currentLogpage;
15326  ptrCheckGuard(logPagePtr, clogPageFileSize, logPageRecord);
15327  if (logPartPtr.p->logPartTimer != logPartPtr.p->logTimer) {
15328  jam();
15329  if (true) // less merge conflicts
15330  {
15331 /*---------------------------------------------------------------------------*/
15332 /* IDLE AND NOT WRITTEN TO DISK IN A SECOND. ALSO WHEN WE HAVE A TAIL PROBLEM*/
15333 /* WE HAVE TO WRITE TO DISK AT TIMES. WE WILL FIRST CHECK WHETHER ANYTHING */
15334 /* AT ALL HAVE BEEN WRITTEN TO THE PAGES BEFORE WRITING TO DISK. */
15335 /*---------------------------------------------------------------------------*/
15336 /* WE HAVE TO WRITE TO DISK IN ALL CASES SINCE THERE COULD BE INFORMATION */
15337 /* STILL IN THE LOG THAT WAS GENERATED BEFORE THE PREVIOUS TIME SUPERVISION */
15338 /* BUT AFTER THE LAST DISK WRITE. THIS PREVIOUSLY STOPPED ALL DISK WRITES */
15339 /* WHEN NO MORE LOG WRITES WERE PERFORMED (THIS HAPPENED WHEN LOG GOT FULL */
15340 /* AND AFTER LOADING THE INITIAL RECORDS IN INITIAL START). */
15341 /*---------------------------------------------------------------------------*/
15342  if (((logFilePtr.p->currentFilepage + 1) & (ZPAGES_IN_MBYTE -1)) == 0) {
15343  jam();
15344 /*---------------------------------------------------------------------------*/
15345 /* THIS IS THE LAST PAGE IN THIS MBYTE. WRITE NEXT LOG AND SWITCH TO NEXT */
15346 /* MBYTE. */
15347 /*---------------------------------------------------------------------------*/
15348  changeMbyte(signal);
15349  } else {
15350 /*---------------------------------------------------------------------------*/
15351 /* WRITE THE LOG PAGE TO DISK EVEN IF IT IS NOT FULL. KEEP PAGE AND WRITE A */
15352 /* COPY. THE ORIGINAL PAGE WILL BE WRITTEN AGAIN LATER ON. */
15353 /*---------------------------------------------------------------------------*/
15354  wordWritten = logPagePtr.p->logPageWord[ZCURR_PAGE_INDEX] - 1;
15355  origLogPagePtr.i = logPagePtr.i;
15356  origLogPagePtr.p = logPagePtr.p;
15357  seizeLogpage(signal);
15358  MEMCOPY_NO_WORDS(&logPagePtr.p->logPageWord[0],
15359  &origLogPagePtr.p->logPageWord[0],
15360  wordWritten + 1);
15361  ndbrequire(wordWritten < ZPAGE_SIZE);
15362  if (logFilePtr.p->noLogpagesInBuffer > 0) {
15363  jam();
15364  completedLogPage(signal, ZENFORCE_WRITE, __LINE__);
15365 /*---------------------------------------------------------------------------*/
15366 /*SINCE WE ARE ONLY WRITING PART OF THE LAST PAGE WE HAVE TO UPDATE THE WORD */
15367 /*WRITTEN TO REFLECT THE REAL LAST WORD WRITTEN. WE ALSO HAVE TO MOVE THE */
15368 /*FILE POSITION ONE STEP BACKWARDS SINCE WE ARE NOT WRITING THE LAST PAGE */
15369 /*COMPLETELY. IT WILL BE WRITTEN AGAIN. */
15370 /*---------------------------------------------------------------------------*/
15371  lfoPtr.p->lfoWordWritten = wordWritten;
15372  logFilePtr.p->filePosition = logFilePtr.p->filePosition - 1;
15373  } else {
15374  if (wordWritten == (ZPAGE_HEADER_SIZE - 1)) {
15375 /*---------------------------------------------------------------------------*/
15376 /*THIS IS POSSIBLE BUT VERY UNLIKELY. IF THE PAGE WAS COMPLETED AFTER THE LAST*/
15377 /*WRITE TO DISK THEN NO_LOG_PAGES_IN_BUFFER > 0 AND IF NOT WRITTEN SINCE LAST*/
15378 /*WRITE TO DISK THEN THE PREVIOUS PAGE MUST HAVE BEEN WRITTEN BY SOME */
15379 /*OPERATION AND THAT BECAME COMPLETELY FULL. IN ANY CASE WE NEED NOT WRITE AN*/
15380 /*EMPTY PAGE TO DISK. */
15381 /*---------------------------------------------------------------------------*/
15382  jam();
15383  releaseLogpage(signal);
15384  } else {
15385  jam();
15386  writeSinglePage(signal, logFilePtr.p->currentFilepage,
15387  wordWritten, __LINE__);
15389  }//if
15390  }//if
15391  }//if
15392  }
15393  }
15394 
15395  logPartPtr.p->logTimer++;
15396  return;
15397 }//Dblqh::timeSup()
15398 
15399 void Dblqh::writeLogfileLab(Signal* signal)
15400 {
15401 /*---------------------------------------------------------------------------*/
15402 /* CHECK IF ANY GLOBAL CHECKPOINTS ARE COMPLETED DUE TO THIS COMPLETED DISK */
15403 /* WRITE. */
15404 /*---------------------------------------------------------------------------*/
15405  switch (logFilePtr.p->fileChangeState) {
15406  case LogFileRecord::NOT_ONGOING:
15407  jam();
15408  checkGcpCompleted(signal,
15409  ((lfoPtr.p->lfoPageNo + lfoPtr.p->noPagesRw) - 1),
15410  lfoPtr.p->lfoWordWritten);
15411  break;
15412 #if 0
15413  case LogFileRecord::BOTH_WRITES_ONGOING:
15414  jam();
15415  ndbout_c("not crashing!!");
15416  // Fall-through
15417 #endif
15418  case LogFileRecord::WRITE_PAGE_ZERO_ONGOING:
15419  case LogFileRecord::LAST_WRITE_ONGOING:
15420  jam();
15421  logFilePtr.p->lastPageWritten = (lfoPtr.p->lfoPageNo + lfoPtr.p->noPagesRw) - 1;
15422  logFilePtr.p->lastWordWritten = lfoPtr.p->lfoWordWritten;
15423  break;
15424  default:
15425  jam();
15426  systemErrorLab(signal, __LINE__);
15427  return;
15428  break;
15429  }//switch
15430  releaseLfoPages(signal);
15431  releaseLfo(signal);
15432  return;
15433 }//Dblqh::writeLogfileLab()
15434 
15435 void Dblqh::closeWriteLogLab(Signal* signal)
15436 {
15437  logFilePtr.p->logFileStatus = LogFileRecord::CLOSED;
15438  return;
15439 }//Dblqh::closeWriteLogLab()
15440 
15441 /* ######################################################################### */
15442 /* FILE CHANGE MODULE */
15443 /* THIS MODULE IS A SUB-MODULE OF THE FILE SYSTEM HANDLING. */
15444 /* */
15445 /*THIS PART OF THE FILE MODULE HANDLES WHEN WE ARE CHANGING LOG FILE DURING */
15446 /*NORMAL OPERATION. WE HAVE TO BE CAREFUL WHEN WE ARE CHANGING LOG FILE SO */
15447 /*THAT WE DO NOT COMPLICATE THE SYSTEM RESTART PROCESS TOO MUCH. */
15448 /*THE IDEA IS THAT WE START BY WRITING THE LAST WRITE IN THE OLD FILE AND WE */
15449 /*ALSO WRITE THE FIRST PAGE OF THE NEW FILE CONCURRENT WITH THAT. THIS FIRST */
15450 /*PAGE IN THE NEW FILE DO NOT CONTAIN ANY LOG RECORDS OTHER THAN A DESCRIPTOR*/
15451 /*CONTAINING INFORMATION ABOUT GCI'S NEEDED AT SYSTEM RESTART AND A NEXT LOG */
15452 /*RECORD. */
15453 /* */
15454 /*WHEN BOTH OF THOSE WRITES HAVE COMPLETED WE ALSO WRITE PAGE ZERO IN FILE */
15455 /*ZERO. THE ONLY INFORMATION WHICH IS INTERESTING HERE IS THE NEW FILE NUMBER*/
15456 /* */
15457 /*IF OPTIMISATIONS ARE NEEDED OF THE LOG HANDLING THEN IT IS POSSIBLE TO */
15458 /*AVOID WRITING THE FIRST PAGE OF THE NEW PAGE IMMEDIATELY. THIS COMPLICATES */
15459 /*THE SYSTEM RESTART AND ONE HAS TO TAKE SPECIAL CARE WITH FILE ZERO. IT IS */
15460 /*HOWEVER NO LARGE PROBLEM TO CHANGE INTO THIS SCENARIO. TO AVOID ALSO THE */
15461 /*WRITING OF PAGE ZERO IS ALSO POSSIBLE BUT COMPLICATES THE DESIGN EVEN */
15462 /*FURTHER. IT GETS FAIRLY COMPLEX TO FIND THE END OF THE LOG. SOME SORT OF */
15463 /*BINARY SEARCH IS HOWEVER MOST LIKELY A GOOD METHODOLOGY FOR THIS. */
15464 /* ######################################################################### */
15465 void Dblqh::firstPageWriteLab(Signal* signal)
15466 {
15467  releaseLfo(signal);
15468 /*---------------------------------------------------------------------------*/
15469 /* RELEASE PAGE ZERO IF THE FILE IS NOT FILE 0. */
15470 /*---------------------------------------------------------------------------*/
15471  Uint32 fileNo = logFilePtr.p->fileNo;
15472  if (fileNo != 0) {
15473  jam();
15474  releaseLogpage(signal);
15475  }//if
15476 /*---------------------------------------------------------------------------*/
15477 /* IF A NEW FILE HAS BEEN OPENED WE SHALL ALWAYS ALSO WRITE TO PAGE O IN */
15478 /* FILE 0. THE AIM IS TO MAKE RESTARTS EASIER BY SPECIFYING WHICH IS THE */
15479 /* LAST FILE WHERE LOGGING HAS STARTED. */
15480 /*---------------------------------------------------------------------------*/
15481 /* FIRST CHECK WHETHER THE LAST WRITE IN THE PREVIOUS FILE HAVE COMPLETED */
15482 /*---------------------------------------------------------------------------*/
15483  if (logFilePtr.p->fileChangeState == LogFileRecord::BOTH_WRITES_ONGOING) {
15484  jam();
15485 /*---------------------------------------------------------------------------*/
15486 /* THE LAST WRITE WAS STILL ONGOING. */
15487 /*---------------------------------------------------------------------------*/
15488  logFilePtr.p->fileChangeState = LogFileRecord::LAST_WRITE_ONGOING;
15489  return;
15490  } else {
15491  jam();
15492  ndbrequire(logFilePtr.p->fileChangeState == LogFileRecord::FIRST_WRITE_ONGOING);
15493 /*---------------------------------------------------------------------------*/
15494 /* WRITE TO PAGE 0 IN IN FILE 0 NOW. */
15495 /*---------------------------------------------------------------------------*/
15496  logFilePtr.p->fileChangeState = LogFileRecord::WRITE_PAGE_ZERO_ONGOING;
15497  if (fileNo == 0) {
15498  jam();
15499 /*---------------------------------------------------------------------------*/
15500 /* IF THE NEW FILE WAS 0 THEN WE HAVE ALREADY WRITTEN PAGE ZERO IN FILE 0. */
15501 /*---------------------------------------------------------------------------*/
15502  // use writePageZeroLab to make sure that same code as normal is run
15503  writePageZeroLab(signal, __LINE__);
15504  return;
15505  } else {
15506  jam();
15507 /*---------------------------------------------------------------------------*/
15508 /* WRITE PAGE ZERO IN FILE ZERO. LOG_FILE_REC WILL REFER TO THE LOG FILE WE */
15509 /* HAVE JUST WRITTEN PAGE ZERO IN TO GET HOLD OF LOG_FILE_PTR FOR THIS */
15510 /* RECORD QUICKLY. THIS IS NEEDED TO GET HOLD OF THE FILE_CHANGE_STATE. */
15511 /* THE ONLY INFORMATION WE WANT TO CHANGE IS THE LAST FILE NUMBER IN THE */
15512 /* FILE DESCRIPTOR. THIS IS USED AT SYSTEM RESTART TO FIND THE END OF THE */
15513 /* LOG PART. */
15514 /*---------------------------------------------------------------------------*/
15515  Uint32 currLogFile = logFilePtr.i;
15516  logFilePtr.i = logPartPtr.p->firstLogfile;
15517  ptrCheckGuard(logFilePtr, clogFileFileSize, logFileRecord);
15518  logPagePtr.i = logFilePtr.p->logPageZero;
15519  ptrCheckGuard(logPagePtr, clogPageFileSize, logPageRecord);
15520  logPagePtr.p->logPageWord[ZPAGE_HEADER_SIZE + ZPOS_FILE_NO] = fileNo;
15521  writeSinglePage(signal, 0, ZPAGE_SIZE - 1, __LINE__);
15522  lfoPtr.p->logFileRec = currLogFile;
15523  lfoPtr.p->lfoState = LogFileOperationRecord::WRITE_PAGE_ZERO;
15524  return;
15525  }//if
15526  }//if
15527 }//Dblqh::firstPageWriteLab()
15528 
15529 void Dblqh::lastWriteInFileLab(Signal* signal)
15530 {
15531  LogFileRecordPtr locLogFilePtr;
15532 /*---------------------------------------------------------------------------*/
15533 /* CHECK IF ANY GLOBAL CHECKPOINTS ARE COMPLETED DUE TO THIS COMPLETED DISK */
15534 /* WRITE. */
15535 /*---------------------------------------------------------------------------*/
15536  checkGcpCompleted(signal,
15537  ((lfoPtr.p->lfoPageNo + lfoPtr.p->noPagesRw) - 1),
15538  (ZPAGE_SIZE - 1));
15539  releaseLfoPages(signal);
15540  releaseLfo(signal);
15541 /*---------------------------------------------------------------------------*/
15542 /* IF THE FILE IS NOT IN USE OR THE NEXT FILE TO BE USED WE WILL CLOSE IT. */
15543 /*---------------------------------------------------------------------------*/
15544  locLogFilePtr.i = logPartPtr.p->currentLogfile;
15545  ptrCheckGuard(locLogFilePtr, clogFileFileSize, logFileRecord);
15546  if (logFilePtr.i != locLogFilePtr.i) {
15547  if (logFilePtr.i != locLogFilePtr.p->nextLogFile) {
15548  if (logFilePtr.p->fileNo != 0) {
15549  jam();
15550 /*---------------------------------------------------------------------------*/
15551 /* THE FILE IS NOT FILE ZERO EITHER. WE WILL NOT CLOSE FILE ZERO SINCE WE */
15552 /* USE IT TO KEEP TRACK OF THE CURRENT LOG FILE BY WRITING PAGE ZERO IN */
15553 /* FILE ZERO. */
15554 /*---------------------------------------------------------------------------*/
15555 /* WE WILL CLOSE THE FILE. */
15556 /*---------------------------------------------------------------------------*/
15558  closeFile(signal, logFilePtr, __LINE__);
15559  }//if
15560  }//if
15561  }//if
15562 /*---------------------------------------------------------------------------*/
15563 /* IF A NEW FILE HAS BEEN OPENED WE SHALL ALWAYS ALSO WRITE TO PAGE O IN */
15564 /* FILE 0. THE AIM IS TO MAKE RESTARTS EASIER BY SPECIFYING WHICH IS THE */
15565 /* LAST FILE WHERE LOGGING HAS STARTED. */
15566 /*---------------------------------------------------------------------------*/
15567 /* FIRST CHECK WHETHER THE FIRST WRITE IN THE NEW FILE HAVE COMPLETED */
15568 /* THIS STATE INFORMATION IS IN THE NEW LOG FILE AND THUS WE HAVE TO MOVE */
15569 /* THE LOG FILE POINTER TO THIS LOG FILE. */
15570 /*---------------------------------------------------------------------------*/
15571  logFilePtr.i = logFilePtr.p->nextLogFile;
15572  ptrCheckGuard(logFilePtr, clogFileFileSize, logFileRecord);
15573  if (logFilePtr.p->fileChangeState == LogFileRecord::BOTH_WRITES_ONGOING) {
15574  jam();
15575 /*---------------------------------------------------------------------------*/
15576 /* THE FIRST WRITE WAS STILL ONGOING. */
15577 /*---------------------------------------------------------------------------*/
15578  logFilePtr.p->fileChangeState = LogFileRecord::FIRST_WRITE_ONGOING;
15579  return;
15580  } else {
15581  ndbrequire(logFilePtr.p->fileChangeState == LogFileRecord::LAST_WRITE_ONGOING);
15582 /*---------------------------------------------------------------------------*/
15583 /* WRITE TO PAGE 0 IN IN FILE 0 NOW. */
15584 /*---------------------------------------------------------------------------*/
15585  logFilePtr.p->fileChangeState = LogFileRecord::WRITE_PAGE_ZERO_ONGOING;
15586  Uint32 fileNo = logFilePtr.p->fileNo;
15587  if (fileNo == 0) {
15588  jam();
15589 /*---------------------------------------------------------------------------*/
15590 /* IF THE NEW FILE WAS 0 THEN WE HAVE ALREADY WRITTEN PAGE ZERO IN FILE 0. */
15591 /*---------------------------------------------------------------------------*/
15592  // use writePageZeroLab to make sure that same code as normal is run
15593  writePageZeroLab(signal, __LINE__);
15594  return;
15595  } else {
15596  jam();
15597 /*---------------------------------------------------------------------------*/
15598 /* WRITE PAGE ZERO IN FILE ZERO. LOG_FILE_REC WILL REFER TO THE LOG FILE WE */
15599 /* HAVE JUST WRITTEN PAGE ZERO IN TO GET HOLD OF LOG_FILE_PTR FOR THIS */
15600 /* RECORD QUICKLY. THIS IS NEEDED TO GET HOLD OF THE FILE_CHANGE_STATE. */
15601 /* THE ONLY INFORMATION WE WANT TO CHANGE IS THE LAST FILE NUMBER IN THE */
15602 /* FILE DESCRIPTOR. THIS IS USED AT SYSTEM RESTART TO FIND THE END OF THE */
15603 /* LOG PART. */
15604 /*---------------------------------------------------------------------------*/
15605  Uint32 currLogFile = logFilePtr.i;
15606  logFilePtr.i = logPartPtr.p->firstLogfile;
15607  ptrCheckGuard(logFilePtr, clogFileFileSize, logFileRecord);
15608  logPagePtr.i = logFilePtr.p->logPageZero;
15609  ptrCheckGuard(logPagePtr, clogPageFileSize, logPageRecord);
15610  logPagePtr.p->logPageWord[ZPAGE_HEADER_SIZE + ZPOS_FILE_NO] = fileNo;
15611  writeSinglePage(signal, 0, ZPAGE_SIZE - 1, __LINE__);
15612  lfoPtr.p->logFileRec = currLogFile;
15613  lfoPtr.p->lfoState = LogFileOperationRecord::WRITE_PAGE_ZERO;
15614  return;
15615  }//if
15616  }//if
15617 }//Dblqh::lastWriteInFileLab()
15618 
15619 void Dblqh::writePageZeroLab(Signal* signal, Uint32 from)
15620 {
15621  if ((logPartPtr.p->m_log_problems & LogPartRecord::P_FILE_CHANGE_PROBLEM)!= 0)
15622  {
15623  jam();
15624  update_log_problem(signal, logPartPtr,
15625  LogPartRecord::P_FILE_CHANGE_PROBLEM,
15626  /* clear */ false);
15627  }
15628 
15629  logFilePtr.p->fileChangeState = LogFileRecord::NOT_ONGOING;
15630 
15631 /*---------------------------------------------------------------------------*/
15632 /* IT COULD HAVE ARRIVED PAGE WRITES TO THE CURRENT FILE WHILE WE WERE */
15633 /* WAITING FOR THIS DISK WRITE TO COMPLETE. THEY COULD NOT CHECK FOR */
15634 /* COMPLETED GLOBAL CHECKPOINTS. THUS WE SHOULD DO THAT NOW INSTEAD. */
15635 /*---------------------------------------------------------------------------*/
15636  bool res = checkGcpCompleted(signal,
15637  logFilePtr.p->lastPageWritten,
15638  logFilePtr.p->lastWordWritten);
15639  if (res && false)
15640  {
15641  gcpPtr.i = ccurrentGcprec;
15642  ptrCheckGuard(gcpPtr, cgcprecFileSize, gcpRecord);
15643 
15644  infoEvent("KESO completing GCP %u in writePageZeroLab from %u",
15645  gcpPtr.p->gcpId, from);
15646  }
15647  return;
15648 }//Dblqh::writePageZeroLab()
15649 
15650 /* ######################################################################### */
15651 /* INITIAL START MODULE */
15652 /* THIS MODULE IS A SUB-MODULE OF THE FILE SYSTEM HANDLING. */
15653 /* */
15654 /*THIS MODULE INITIALISES ALL THE LOG FILES THAT ARE NEEDED AT A SYSTEM */
15655 /*RESTART AND WHICH ARE USED DURING NORMAL OPERATIONS. IT CREATES THE FILES */
15656 /*AND SETS A PROPER SIZE OF THEM AND INITIALISES THE FIRST PAGE IN EACH FILE */
15657 /* ######################################################################### */
15658 void Dblqh::openFileInitLab(Signal* signal)
15659 {
15660  logFilePtr.p->logFileStatus = LogFileRecord::OPEN_INIT;
15661  seizeLogpage(signal);
15662  if (m_use_om_init == 0)
15663  {
15664  jam();
15665  initLogpage(signal);
15666  writeSinglePage(signal, (clogFileSize * ZPAGES_IN_MBYTE) - 1,
15667  ZPAGE_SIZE - 1, __LINE__, false);
15669  }
15670  else
15671  {
15672  jam();
15673  seizeLfo(signal);
15674  initWriteEndLab(signal);
15675  }
15676  return;
15677 }//Dblqh::openFileInitLab()
15678 
15679 void Dblqh::initWriteEndLab(Signal* signal)
15680 {
15681  releaseLfo(signal);
15682  initLogpage(signal);
15683  if (logFilePtr.p->fileNo == 0) {
15684  jam();
15685 /*---------------------------------------------------------------------------*/
15686 /* PAGE ZERO IN FILE ZERO MUST SET LOG LAP TO ONE SINCE IT HAS STARTED */
15687 /* WRITING TO THE LOG, ALSO GLOBAL CHECKPOINTS ARE SET TO ZERO. */
15688 /*---------------------------------------------------------------------------*/
15689  logPagePtr.p->logPageWord[ZPOS_LOG_LAP] = 1;
15690  logPagePtr.p->logPageWord[ZPOS_MAX_GCI_STARTED] = 0;
15691  logPagePtr.p->logPageWord[ZPOS_MAX_GCI_COMPLETED] = 0;
15692  logFilePtr.p->logMaxGciStarted[0] = 0;
15693  logFilePtr.p->logMaxGciCompleted[0] = 0;
15694  }//if
15695 /*---------------------------------------------------------------------------*/
15696 /* REUSE CODE FOR INITIALISATION OF FIRST PAGE IN ALL LOG FILES. */
15697 /*---------------------------------------------------------------------------*/
15698  writeFileHeaderOpen(signal, ZINIT);
15699  return;
15700 }//Dblqh::initWriteEndLab()
15701 
15702 void Dblqh::initFirstPageLab(Signal* signal)
15703 {
15704  releaseLfo(signal);
15705  if (logFilePtr.p->fileNo == 0) {
15706  jam();
15707 /*---------------------------------------------------------------------------*/
15708 /* IN FILE ZERO WE WILL INSERT A PAGE ONE WHERE WE WILL INSERT A COMPLETED */
15709 /* GCI RECORD FOR GCI = 0. */
15710 /*---------------------------------------------------------------------------*/
15711  initLogpage(signal);
15712  logPagePtr.p->logPageWord[ZPOS_LOG_LAP] = 1;
15713  logPagePtr.p->logPageWord[ZPAGE_HEADER_SIZE] = ZCOMPLETED_GCI_TYPE;
15714  logPagePtr.p->logPageWord[ZPAGE_HEADER_SIZE + 1] = 1;
15715  writeSinglePage(signal, 1, ZPAGE_SIZE - 1, __LINE__, false);
15716  lfoPtr.p->lfoState = LogFileOperationRecord::WRITE_GCI_ZERO;
15717  return;
15718  }//if
15719  logFilePtr.p->currentMbyte = 1;
15720  writeInitMbyte(signal);
15721  return;
15722 }//Dblqh::initFirstPageLab()
15723 
15724 void Dblqh::writeGciZeroLab(Signal* signal)
15725 {
15726  releaseLfo(signal);
15727  logFilePtr.p->currentMbyte = 1;
15728  writeInitMbyte(signal);
15729  return;
15730 }//Dblqh::writeGciZeroLab()
15731 
15732 void Dblqh::writeInitMbyteLab(Signal* signal)
15733 {
15734  releaseLfo(signal);
15735  logFilePtr.p->currentMbyte = logFilePtr.p->currentMbyte + 1;
15736  if (logFilePtr.p->currentMbyte == clogFileSize) {
15737  jam();
15738  releaseLogpage(signal);
15739  logFilePtr.p->logFileStatus = LogFileRecord::CLOSING_INIT;
15740  closeFile(signal, logFilePtr, __LINE__);
15741  return;
15742  }//if
15743  writeInitMbyte(signal);
15744  return;
15745 }//Dblqh::writeInitMbyteLab()
15746 
15747 void Dblqh::closingInitLab(Signal* signal)
15748 {
15749  logFilePtr.p->logFileStatus = LogFileRecord::CLOSED;
15750  logPartPtr.i = logFilePtr.p->logPartRec;
15751  ptrCheckGuard(logPartPtr, clogPartFileSize, logPartRecord);
15752  if (logFilePtr.p->nextLogFile == logPartPtr.p->firstLogfile) {
15753  jam();
15754  checkInitCompletedLab(signal);
15755  return;
15756  } else {
15757  jam();
15758  logFilePtr.i = logFilePtr.p->nextLogFile;
15759  ptrCheckGuard(logFilePtr, clogFileFileSize, logFileRecord);
15760  openLogfileInit(signal);
15761  }//if
15762  return;
15763 }//Dblqh::closingInitLab()
15764 
15765 void Dblqh::checkInitCompletedLab(Signal* signal)
15766 {
15768 /*---------------------------------------------------------------------------*/
15769 /* WE HAVE NOW INITIALISED ALL FILES IN THIS LOG PART. WE CAN NOW SET THE */
15770 /* THE LOG LAP TO ONE SINCE WE WILL START WITH LOG LAP ONE. LOG LAP = ZERO */
15771 /* MEANS THIS PART OF THE LOG IS NOT WRITTEN YET. */
15772 /*---------------------------------------------------------------------------*/
15773  logPartPtr.p->logLap = 1;
15774 
15775  if (m_use_om_init && ++logPartPtr.i != clogPartFileSize)
15776  {
15777  jam();
15778  ptrAss(logPartPtr, logPartRecord);
15779  logFilePtr.i = logPartPtr.p->firstLogfile;
15780  ptrCheckGuard(logFilePtr, clogFileFileSize, logFileRecord);
15781  openLogfileInit(signal);
15782  return;
15783  }
15784 
15785  for (logPartPtr.i = 0; logPartPtr.i < clogPartFileSize; logPartPtr.i++)
15786  {
15787  jam();
15788  ptrAss(logPartPtr, logPartRecord);
15790  {
15791  jam();
15792 /*---------------------------------------------------------------------------*/
15793 /* THIS PART HAS STILL NOT COMPLETED. WAIT FOR THIS TO OCCUR. */
15794 /*---------------------------------------------------------------------------*/
15795  return;
15796  }//if
15797  }
15798 
15799 #ifdef VM_TRACE
15800  enable_global_variables();
15801 #endif
15802  logfileInitCompleteReport(signal);
15803  sendNdbSttorryLab(signal);
15804 }
15805 
15806 /* ========================================================================= */
15807 /* ======= INITIATE LOG FILE OPERATION RECORD WHEN ALLOCATED ======= */
15808 /* */
15809 /* ========================================================================= */
15810 void Dblqh::initLfo(Signal* signal)
15811 {
15812  lfoPtr.p->firstLfoPage = RNIL;
15814  lfoPtr.p->logFileRec = logFilePtr.i;
15815  lfoPtr.p->noPagesRw = 0;
15816  lfoPtr.p->lfoPageNo = ZNIL;
15817 }//Dblqh::initLfo()
15818 
15819 /* ========================================================================= */
15820 /* ======= INITIATE LOG FILE WHEN ALLOCATED ======= */
15821 /* */
15822 /* INPUT: TFILE_NO NUMBER OF THE FILE INITIATED */
15823 /* LOG_PART_PTR NUMBER OF LOG PART */
15824 /* SUBROUTINE SHORT NAME = IL */
15825 /* ========================================================================= */
15826 void Dblqh::initLogfile(Signal* signal, Uint32 fileNo)
15827 {
15828  UintR tilTmp;
15829  UintR tilIndex;
15830 
15831  logFilePtr.p->currentFilepage = 0;
15832  logFilePtr.p->currentLogpage = RNIL;
15833  logFilePtr.p->fileName[0] = (UintR)-1;
15834  logFilePtr.p->fileName[1] = (UintR)-1; /* = H'FFFFFFFF = -1 */
15835  logFilePtr.p->fileName[2] = fileNo; /* Sfile_no */
15836  tilTmp = 1; /* VERSION 1 OF FILE NAME */
15837  tilTmp = (tilTmp << 8) + 1; /* FRAGMENT LOG => .FRAGLOG AS EXTENSION */
15838  tilTmp = (tilTmp << 8) + (8 + logPartPtr.p->logPartNo); /* DIRECTORY = D(8+Part)/DBLQH */
15839  tilTmp = (tilTmp << 8) + 255; /* IGNORE Pxx PART OF FILE NAME */
15840  logFilePtr.p->fileName[3] = tilTmp;
15841 /* ========================================================================= */
15842 /* FILE NAME BECOMES /D2/DBLQH/Tpart_no/Sfile_no.FRAGLOG */
15843 /* ========================================================================= */
15844  logFilePtr.p->fileNo = fileNo;
15845  logFilePtr.p->filePosition = 0;
15846  logFilePtr.p->firstLfo = RNIL;
15847  logFilePtr.p->lastLfo = RNIL;
15848  logFilePtr.p->logFileStatus = LogFileRecord::CLOSED;
15849  logFilePtr.p->logPartRec = logPartPtr.i;
15850  logFilePtr.p->noLogpagesInBuffer = 0;
15851  logFilePtr.p->firstFilledPage = RNIL;
15852  logFilePtr.p->lastFilledPage = RNIL;
15853  logFilePtr.p->lastPageWritten = 0;
15854  logFilePtr.p->logPageZero = RNIL;
15855  logFilePtr.p->currentMbyte = 0;
15856  for (tilIndex = 0; tilIndex < clogFileSize; tilIndex++) {
15857  logFilePtr.p->logMaxGciCompleted[tilIndex] = (UintR)-1;
15858  logFilePtr.p->logMaxGciStarted[tilIndex] = (UintR)-1;
15859  logFilePtr.p->logLastPrepRef[tilIndex] = 0;
15860  }//for
15861 }//Dblqh::initLogfile()
15862 
15863 /* ========================================================================= */
15864 /* ======= INITIATE LOG PAGE WHEN ALLOCATED ======= */
15865 /* */
15866 /* ========================================================================= */
15867 void Dblqh::initLogpage(Signal* signal)
15868 {
15869  TcConnectionrecPtr ilpTcConnectptr;
15870 
15871  logPagePtr.p->logPageWord[ZPOS_LOG_LAP] = logPartPtr.p->logLap;
15872  logPagePtr.p->logPageWord[ZPOS_MAX_GCI_COMPLETED] =
15873  logPartPtr.p->logPartNewestCompletedGCI;
15874  logPagePtr.p->logPageWord[ZPOS_MAX_GCI_STARTED] = cnewestGci;
15875  logPagePtr.p->logPageWord[ZPOS_VERSION] = NDB_VERSION;
15876  logPagePtr.p->logPageWord[ZPOS_NO_LOG_FILES] = logPartPtr.p->noLogFiles;
15877  logPagePtr.p->logPageWord[ZCURR_PAGE_INDEX] = ZPAGE_HEADER_SIZE;
15878  ilpTcConnectptr.i = logPartPtr.p->firstLogTcrec;
15879  if (ilpTcConnectptr.i != RNIL) {
15880  jam();
15881  ptrCheckGuard(ilpTcConnectptr, ctcConnectrecFileSize, tcConnectionrec);
15882  logPagePtr.p->logPageWord[ZLAST_LOG_PREP_REF] =
15883  (ilpTcConnectptr.p->logStartFileNo << 16) +
15884  (ilpTcConnectptr.p->logStartPageNo >> ZTWOLOG_NO_PAGES_IN_MBYTE);
15885  } else {
15886  jam();
15887  logPagePtr.p->logPageWord[ZLAST_LOG_PREP_REF] =
15888  (logFilePtr.p->fileNo << 16) +
15889  (logFilePtr.p->currentFilepage >> ZTWOLOG_NO_PAGES_IN_MBYTE);
15890  }//if
15891 }//Dblqh::initLogpage()
15892 
15893 /* ------------------------------------------------------------------------- */
15894 /* ------- OPEN LOG FILE FOR READ AND WRITE ------- */
15895 /* */
15896 /* SUBROUTINE SHORT NAME = OFR */
15897 /* ------------------------------------------------------------------------- */
15898 void Dblqh::openFileRw(Signal* signal,
15899  LogFileRecordPtr olfLogFilePtr,
15900  bool writeBuffer)
15901 {
15902  FsOpenReq* req = (FsOpenReq*)signal->getDataPtrSend();
15903  signal->theData[0] = cownref;
15904  signal->theData[1] = olfLogFilePtr.i;
15905  signal->theData[2] = olfLogFilePtr.p->fileName[0];
15906  signal->theData[3] = olfLogFilePtr.p->fileName[1];
15907  signal->theData[4] = olfLogFilePtr.p->fileName[2];
15908  signal->theData[5] = olfLogFilePtr.p->fileName[3];
15909  signal->theData[6] = FsOpenReq::OM_READWRITE | FsOpenReq::OM_AUTOSYNC | FsOpenReq::OM_CHECK_SIZE;
15910  if (c_o_direct)
15911  signal->theData[6] |= FsOpenReq::OM_DIRECT;
15912  if (writeBuffer)
15913  signal->theData[6] |= FsOpenReq::OM_WRITE_BUFFER;
15914 
15915  req->auto_sync_size = MAX_REDO_PAGES_WITHOUT_SYNCH * sizeof(LogPageRecord);
15916  Uint64 sz = clogFileSize;
15917  sz *= 1024; sz *= 1024;
15918  req->file_size_hi = (Uint32)(sz >> 32);
15919  req->file_size_lo = (Uint32)(sz & 0xFFFFFFFF);
15920  sendSignal(NDBFS_REF, GSN_FSOPENREQ, signal, FsOpenReq::SignalLength, JBA);
15921 }//Dblqh::openFileRw()
15922 
15923 /* ------------------------------------------------------------------------- */
15924 /* ------- OPEN LOG FILE DURING INITIAL START ------- */
15925 /* */
15926 /* SUBROUTINE SHORT NAME = OLI */
15927 /* ------------------------------------------------------------------------- */
15928 void Dblqh::openLogfileInit(Signal* signal)
15929 {
15930  logFilePtr.p->logFileStatus = LogFileRecord::OPENING_INIT;
15931  FsOpenReq* req = (FsOpenReq*)signal->getDataPtrSend();
15932  signal->theData[0] = cownref;
15933  signal->theData[1] = logFilePtr.i;
15934  signal->theData[2] = logFilePtr.p->fileName[0];
15935  signal->theData[3] = logFilePtr.p->fileName[1];
15936  signal->theData[4] = logFilePtr.p->fileName[2];
15937  signal->theData[5] = logFilePtr.p->fileName[3];
15938  signal->theData[6] = FsOpenReq::OM_READWRITE | FsOpenReq::OM_TRUNCATE | FsOpenReq::OM_CREATE | FsOpenReq::OM_AUTOSYNC | FsOpenReq::OM_WRITE_BUFFER;
15939  if (c_o_direct)
15940  signal->theData[6] |= FsOpenReq::OM_DIRECT;
15941 
15942  Uint64 sz = Uint64(clogFileSize) * 1024 * 1024;
15943  req->file_size_hi = Uint32(sz >> 32);
15944  req->file_size_lo = Uint32(sz);
15945  req->page_size = File_formats::NDB_PAGE_SIZE;
15946  if (m_use_om_init)
15947  {
15948  jam();
15949  signal->theData[6] |= FsOpenReq::OM_INIT;
15950  }
15951 
15952  req->auto_sync_size = MAX_REDO_PAGES_WITHOUT_SYNCH * sizeof(LogPageRecord);
15953  sendSignal(NDBFS_REF, GSN_FSOPENREQ, signal, FsOpenReq::SignalLength, JBA);
15954 }//Dblqh::openLogfileInit()
15955 
15956 void
15957 Dblqh::execFSWRITEREQ(Signal* signal)
15958 {
15963  Ptr<GlobalPage> page_ptr;
15964  FsReadWriteReq* req= (FsReadWriteReq*)signal->getDataPtr();
15965  m_shared_page_pool.getPtr(page_ptr, req->data.pageData[0]);
15966 
15967  LogFileRecordPtr currLogFilePtr;
15968  currLogFilePtr.i = req->userPointer;
15969  ptrCheckGuard(currLogFilePtr, clogFileFileSize, logFileRecord);
15970 
15971  LogPartRecordPtr currLogPartPtr;
15972  currLogPartPtr.i = currLogFilePtr.p->logPartRec;
15973  ptrCheckGuard(currLogPartPtr, clogPartFileSize, logPartRecord);
15974 
15975  Uint32 page_no = req->varIndex;
15976  LogPageRecordPtr currLogPagePtr;
15977  currLogPagePtr.p = (LogPageRecord*)page_ptr.p;
15978 
15979  bzero(page_ptr.p, sizeof(LogPageRecord));
15980  if (page_no == 0)
15981  {
15982  // keep writing these afterwards
15983  }
15984  else if (((page_no % ZPAGES_IN_MBYTE) == 0) ||
15985  (page_no == ((clogFileSize * ZPAGES_IN_MBYTE) - 1)))
15986  {
15987  currLogPagePtr.p->logPageWord[ZPOS_LOG_LAP] = currLogPartPtr.p->logLap;
15988  currLogPagePtr.p->logPageWord[ZPOS_MAX_GCI_COMPLETED] =
15989  currLogPartPtr.p->logPartNewestCompletedGCI;
15990  currLogPagePtr.p->logPageWord[ZPOS_MAX_GCI_STARTED] = cnewestGci;
15991  currLogPagePtr.p->logPageWord[ZPOS_VERSION] = NDB_VERSION;
15992  currLogPagePtr.p->logPageWord[ZPOS_NO_LOG_FILES] =
15993  currLogPartPtr.p->noLogFiles;
15994  currLogPagePtr.p->logPageWord[ZCURR_PAGE_INDEX] = ZPAGE_HEADER_SIZE;
15995  currLogPagePtr.p->logPageWord[ZLAST_LOG_PREP_REF] =
15996  (currLogFilePtr.p->fileNo << 16) +
15997  (currLogFilePtr.p->currentFilepage >> ZTWOLOG_NO_PAGES_IN_MBYTE);
15998 
15999  currLogPagePtr.p->logPageWord[ZNEXT_PAGE] = RNIL;
16000  currLogPagePtr.p->logPageWord[ZPOS_CHECKSUM] =
16001  calcPageCheckSum(currLogPagePtr);
16002  }
16003  else if (0)
16004  {
16005  currLogPagePtr.p->logPageWord[ZNEXT_PAGE] = RNIL;
16006  currLogPagePtr.p->logPageWord[ZPOS_CHECKSUM] =
16007  calcPageCheckSum(currLogPagePtr);
16008  }
16009 }
16010 
16011 /* OPEN FOR READ/WRITE, DO CREATE AND DO TRUNCATE FILE */
16012 /* ------------------------------------------------------------------------- */
16013 /* ------- OPEN NEXT LOG FILE ------- */
16014 /* */
16015 /* SUBROUTINE SHORT NAME = ONL */
16016 /* ------------------------------------------------------------------------- */
16017 void Dblqh::openNextLogfile(Signal* signal)
16018 {
16019  LogFileRecordPtr onlLogFilePtr;
16020 
16021  if (logPartPtr.p->noLogFiles > 2) {
16022  jam();
16023 /* -------------------------------------------------- */
16024 /* IF ONLY 1 OR 2 LOG FILES EXIST THEN THEY ARE */
16025 /* ALWAYS OPEN AND THUS IT IS NOT NECESSARY TO */
16026 /* OPEN THEM NOW. */
16027 /* -------------------------------------------------- */
16028  onlLogFilePtr.i = logFilePtr.p->nextLogFile;
16029  ptrCheckGuard(onlLogFilePtr, clogFileFileSize, logFileRecord);
16030  if (onlLogFilePtr.p->logFileStatus != LogFileRecord::CLOSED) {
16031  ndbrequire(onlLogFilePtr.p->fileNo == 0);
16032  return;
16033  }//if
16034  onlLogFilePtr.p->logFileStatus = LogFileRecord::OPENING_WRITE_LOG;
16035  FsOpenReq* req = (FsOpenReq*)signal->getDataPtrSend();
16036  signal->theData[0] = cownref;
16037  signal->theData[1] = onlLogFilePtr.i;
16038  signal->theData[2] = onlLogFilePtr.p->fileName[0];
16039  signal->theData[3] = onlLogFilePtr.p->fileName[1];
16040  signal->theData[4] = onlLogFilePtr.p->fileName[2];
16041  signal->theData[5] = onlLogFilePtr.p->fileName[3];
16042  signal->theData[6] = FsOpenReq::OM_READWRITE | FsOpenReq::OM_AUTOSYNC | FsOpenReq::OM_CHECK_SIZE | FsOpenReq::OM_WRITE_BUFFER;
16043  if (c_o_direct)
16044  signal->theData[6] |= FsOpenReq::OM_DIRECT;
16045  req->auto_sync_size = MAX_REDO_PAGES_WITHOUT_SYNCH * sizeof(LogPageRecord);
16046  Uint64 sz = clogFileSize;
16047  sz *= 1024; sz *= 1024;
16048  req->file_size_hi = (Uint32)(sz >> 32);
16049  req->file_size_lo = (Uint32)(sz & 0xFFFFFFFF);
16050  sendSignal(NDBFS_REF, GSN_FSOPENREQ, signal, FsOpenReq::SignalLength, JBA);
16051  }//if
16052 }//Dblqh::openNextLogfile()
16053 
16054  /* OPEN FOR READ/WRITE, DON'T CREATE AND DON'T TRUNCATE FILE */
16055 /* ------------------------------------------------------------------------- */
16056 /* ------- RELEASE LFO RECORD ------- */
16057 /* */
16058 /* ------------------------------------------------------------------------- */
16059 void Dblqh::releaseLfo(Signal* signal)
16060 {
16061 #ifdef VM_TRACE
16062  // Check that lfo record isn't already in free list
16063  LogFileOperationRecordPtr TlfoPtr;
16064  TlfoPtr.i = cfirstfreeLfo;
16065  while (TlfoPtr.i != RNIL){
16066  ptrCheckGuard(TlfoPtr, clfoFileSize, logFileOperationRecord);
16067  ndbrequire(TlfoPtr.i != lfoPtr.i);
16068  TlfoPtr.i = TlfoPtr.p->nextLfo;
16069  }
16070 #endif
16071  lfoPtr.p->nextLfo = cfirstfreeLfo;
16072  lfoPtr.p->lfoTimer = 0;
16073  cfirstfreeLfo = lfoPtr.i;
16075 }//Dblqh::releaseLfo()
16076 
16077 /* ------------------------------------------------------------------------- */
16078 /* ------- RELEASE ALL LOG PAGES CONNECTED TO A LFO RECORD ------- */
16079 /* */
16080 /* SUBROUTINE SHORT NAME = RLP */
16081 /* ------------------------------------------------------------------------- */
16082 void Dblqh::releaseLfoPages(Signal* signal)
16083 {
16084  logPagePtr.i = lfoPtr.p->firstLfoPage;
16085  while (logPagePtr.i != RNIL)
16086  {
16087  ptrCheckGuard(logPagePtr, clogPageFileSize, logPageRecord);
16088  Uint32 tmp = logPagePtr.p->logPageWord[ZNEXT_PAGE];
16089  releaseLogpage(signal);
16090  logPagePtr.i = tmp;
16091  }
16092  lfoPtr.p->firstLfoPage = RNIL;
16093 }//Dblqh::releaseLfoPages()
16094 
16095 /* ------------------------------------------------------------------------- */
16096 /* ------- RELEASE LOG PAGE ------- */
16097 /* */
16098 /* ------------------------------------------------------------------------- */
16099 void Dblqh::releaseLogpage(Signal* signal)
16100 {
16101 #ifdef VM_TRACE
16102  // Check that log page isn't already in free list
16103  ndbrequire(logPagePtr.p->logPageWord[ZPOS_IN_FREE_LIST] == 0);
16104 #endif
16105 
16106  cnoOfLogPages++;
16107  logPagePtr.p->logPageWord[ZNEXT_PAGE] = cfirstfreeLogPage;
16108  logPagePtr.p->logPageWord[ZPOS_IN_WRITING]= 0;
16109  logPagePtr.p->logPageWord[ZPOS_IN_FREE_LIST]= 1;
16110  cfirstfreeLogPage = logPagePtr.i;
16111 }//Dblqh::releaseLogpage()
16112 
16113 /* ------------------------------------------------------------------------- */
16114 /* ------- SEIZE LFO RECORD ------- */
16115 /* */
16116 /* ------------------------------------------------------------------------- */
16117 void Dblqh::seizeLfo(Signal* signal)
16118 {
16119  lfoPtr.i = cfirstfreeLfo;
16120  ptrCheckGuard(lfoPtr, clfoFileSize, logFileOperationRecord);
16121  cfirstfreeLfo = lfoPtr.p->nextLfo;
16122  lfoPtr.p->nextLfo = RNIL;
16123  lfoPtr.p->lfoTimer = cLqhTimeOutCount;
16124 }//Dblqh::seizeLfo()
16125 
16126 /* ------------------------------------------------------------------------- */
16127 /* ------- SEIZE LOG FILE RECORD ------- */
16128 /* */
16129 /* ------------------------------------------------------------------------- */
16130 void Dblqh::seizeLogfile(Signal* signal)
16131 {
16132  logFilePtr.i = cfirstfreeLogFile;
16133  ptrCheckGuard(logFilePtr, clogFileFileSize, logFileRecord);
16134 /* ------------------------------------------------------------------------- */
16135 /*IF LIST IS EMPTY THEN A SYSTEM CRASH IS INVOKED SINCE LOG_FILE_PTR = RNIL */
16136 /* ------------------------------------------------------------------------- */
16137  cfirstfreeLogFile = logFilePtr.p->nextLogFile;
16138  logFilePtr.p->nextLogFile = RNIL;
16139 }//Dblqh::seizeLogfile()
16140 
16141 /* ------------------------------------------------------------------------- */
16142 /* ------- SEIZE LOG PAGE RECORD ------- */
16143 /* */
16144 /* ------------------------------------------------------------------------- */
16145 void Dblqh::seizeLogpage(Signal* signal)
16146 {
16147  cnoOfLogPages--;
16148  logPagePtr.i = cfirstfreeLogPage;
16149  ptrCheckGuard(logPagePtr, clogPageFileSize, logPageRecord);
16150 /* ------------------------------------------------------------------------- */
16151 /*IF LIST IS EMPTY THEN A SYSTEM CRASH IS INVOKED SINCE LOG_PAGE_PTR = RNIL */
16152 /* ------------------------------------------------------------------------- */
16153  cfirstfreeLogPage = logPagePtr.p->logPageWord[ZNEXT_PAGE];
16154 #ifdef VM_TRACE
16155  bzero(logPagePtr.p, sizeof(LogPageRecord));
16156 #endif
16157  logPagePtr.p->logPageWord[ZNEXT_PAGE] = RNIL;
16158  logPagePtr.p->logPageWord[ZPOS_IN_FREE_LIST] = 0;
16159 }//Dblqh::seizeLogpage()
16160 
16161 /* ------------------------------------------------------------------------- */
16162 /* ------- WRITE FILE DESCRIPTOR INFORMATION ------- */
16163 /* */
16164 /* SUBROUTINE SHORT NAME: WFD */
16165 // Pointer handling:
16166 // logFilePtr in
16167 // logPartPtr in
16168 /* ------------------------------------------------------------------------- */
16169 void Dblqh::writeFileDescriptor(Signal* signal)
16170 {
16171  TcConnectionrecPtr wfdTcConnectptr;
16172  UintR twfdFileNo;
16173  UintR twfdMbyte;
16174 
16175 /* -------------------------------------------------- */
16176 /* START BY WRITING TO LOG FILE RECORD */
16177 /* -------------------------------------------------- */
16178  arrGuard(logFilePtr.p->currentMbyte, clogFileSize);
16179  if (DEBUG_REDO)
16180  {
16181  printf("part: %u file: %u setting logMaxGciCompleted[%u] = %u logMaxGciStarted[%u]: %u lastPrepRef[%u]: ",
16182  logPartPtr.p->logPartNo,
16183  logFilePtr.p->fileNo,
16184  logFilePtr.p->currentMbyte,
16185  logPartPtr.p->logPartNewestCompletedGCI,
16186  logFilePtr.p->currentMbyte,
16187  cnewestGci,
16188  logFilePtr.p->currentMbyte);
16189  if (logPartPtr.p->firstLogTcrec == RNIL)
16190  {
16191  ndbout_c("file: %u mb: %u (RNIL)",
16192  logFilePtr.p->fileNo,
16193  logFilePtr.p->currentMbyte);
16194  }
16195  else
16196  {
16197  wfdTcConnectptr.i = logPartPtr.p->firstLogTcrec;
16198  ptrCheckGuard(wfdTcConnectptr, ctcConnectrecFileSize, tcConnectionrec);
16199  ndbout_c("file: %u mb: %u",
16200  wfdTcConnectptr.p->logStartFileNo,
16201  wfdTcConnectptr.p->logStartPageNo >> ZTWOLOG_NO_PAGES_IN_MBYTE);
16202  }
16203  }
16204  logFilePtr.p->logMaxGciCompleted[logFilePtr.p->currentMbyte] =
16205  logPartPtr.p->logPartNewestCompletedGCI;
16206  logFilePtr.p->logMaxGciStarted[logFilePtr.p->currentMbyte] = cnewestGci;
16207  wfdTcConnectptr.i = logPartPtr.p->firstLogTcrec;
16208  if (wfdTcConnectptr.i != RNIL) {
16209  jam();
16210  ptrCheckGuard(wfdTcConnectptr, ctcConnectrecFileSize, tcConnectionrec);
16211  twfdFileNo = wfdTcConnectptr.p->logStartFileNo;
16212  twfdMbyte = wfdTcConnectptr.p->logStartPageNo >> ZTWOLOG_NO_PAGES_IN_MBYTE;
16213  logFilePtr.p->logLastPrepRef[logFilePtr.p->currentMbyte] =
16214  (twfdFileNo << 16) + twfdMbyte;
16215  } else {
16216  jam();
16217  logFilePtr.p->logLastPrepRef[logFilePtr.p->currentMbyte] =
16218  (logFilePtr.p->fileNo << 16) + logFilePtr.p->currentMbyte;
16219  }//if
16220 }//Dblqh::writeFileDescriptor()
16221 
16222 /* ------------------------------------------------------------------------- */
16223 /* ------- WRITE THE HEADER PAGE OF A NEW FILE ------- */
16224 /* */
16225 /* SUBROUTINE SHORT NAME: WMO */
16226 /* ------------------------------------------------------------------------- */
16227 void Dblqh::writeFileHeaderOpen(Signal* signal, Uint32 wmoType)
16228 {
16229  UintR twmoNoLogDescriptors;
16230 
16231 /* -------------------------------------------------- */
16232 /* WRITE HEADER INFORMATION IN THE NEW FILE. */
16233 /* -------------------------------------------------- */
16234  logPagePtr.p->logPageWord[ZPAGE_HEADER_SIZE + ZPOS_LOG_TYPE] = ZFD_TYPE;
16235  logPagePtr.p->logPageWord[ZPAGE_HEADER_SIZE + ZPOS_FILE_NO] =
16236  logFilePtr.p->fileNo;
16237  if (logPartPtr.p->noLogFiles > cmaxLogFilesInPageZero) {
16238  jam();
16239  twmoNoLogDescriptors = cmaxLogFilesInPageZero;
16240  } else {
16241  jam();
16242  twmoNoLogDescriptors = logPartPtr.p->noLogFiles;
16243  }//if
16244  logPagePtr.p->logPageWord[ZPAGE_HEADER_SIZE + ZPOS_NO_FD] =
16245  twmoNoLogDescriptors;
16246 
16247  {
16248  Uint32 pos = ZPAGE_HEADER_SIZE + ZFD_HEADER_SIZE;
16249  LogFileRecordPtr filePtr = logFilePtr;
16250  for (Uint32 fd = 0; fd < twmoNoLogDescriptors; fd++)
16251  {
16252  jam();
16253  ptrCheckGuard(filePtr, clogFileFileSize, logFileRecord);
16254  for (Uint32 mb = 0; mb < clogFileSize; mb ++)
16255  {
16256  jam();
16257  Uint32 pos0 = pos + fd * (ZFD_MBYTE_SIZE * clogFileSize) + mb;
16258  Uint32 pos1 = pos0 + clogFileSize;
16259  Uint32 pos2 = pos1 + clogFileSize;
16260  arrGuard(pos0, ZPAGE_SIZE);
16261  arrGuard(pos1, ZPAGE_SIZE);
16262  arrGuard(pos2, ZPAGE_SIZE);
16263  logPagePtr.p->logPageWord[pos0] = filePtr.p->logMaxGciCompleted[mb];
16264  logPagePtr.p->logPageWord[pos1] = filePtr.p->logMaxGciStarted[mb];
16265  logPagePtr.p->logPageWord[pos2] = filePtr.p->logLastPrepRef[mb];
16266  }
16267  filePtr.i = filePtr.p->prevLogFile;
16268  }
16269  pos += (twmoNoLogDescriptors * ZFD_MBYTE_SIZE * clogFileSize);
16270  arrGuard(pos, ZPAGE_SIZE);
16271  logPagePtr.p->logPageWord[ZCURR_PAGE_INDEX] = pos;
16272  logPagePtr.p->logPageWord[pos] = ZNEXT_LOG_RECORD_TYPE;
16273  }
16274 
16275 /* ------------------------------------------------------- */
16276 /* THIS IS A SPECIAL WRITE OF THE FIRST PAGE IN THE */
16277 /* LOG FILE. THIS HAS SPECIAL SIGNIFANCE TO FIND */
16278 /* THE END OF THE LOG AT SYSTEM RESTART. */
16279 /* ------------------------------------------------------- */
16280  if (wmoType == ZINIT) {
16281  jam();
16282  writeSinglePage(signal, 0, ZPAGE_SIZE - 1, __LINE__, false);
16284  } else {
16285  jam();
16286  writeSinglePage(signal, 0, ZPAGE_SIZE - 1, __LINE__, true);
16287  lfoPtr.p->lfoState = LogFileOperationRecord::FIRST_PAGE_WRITE_IN_LOGFILE;
16288  }//if
16289  logFilePtr.p->filePosition = 1;
16290  if (wmoType == ZNORMAL) {
16291  jam();
16292 /* -------------------------------------------------- */
16293 /* ALLOCATE A NEW PAGE SINCE THE CURRENT IS */
16294 /* WRITTEN. */
16295 /* -------------------------------------------------- */
16296  seizeLogpage(signal);
16297  initLogpage(signal);
16298  logFilePtr.p->currentLogpage = logPagePtr.i;
16299  logFilePtr.p->currentFilepage = logFilePtr.p->currentFilepage + 1;
16300  }//if
16301 }//Dblqh::writeFileHeaderOpen()
16302 
16303 /* -------------------------------------------------- */
16304 /* THE NEW FILE POSITION WILL ALWAYS BE 1 SINCE */
16305 /* WE JUST WROTE THE FIRST PAGE IN THE LOG FILE */
16306 /* -------------------------------------------------- */
16307 /* ------------------------------------------------------------------------- */
16308 /* ------- WRITE A MBYTE HEADER DURING INITIAL START ------- */
16309 /* */
16310 /* SUBROUTINE SHORT NAME: WIM */
16311 /* ------------------------------------------------------------------------- */
16312 void Dblqh::writeInitMbyte(Signal* signal)
16313 {
16314  if (m_use_om_init == 0)
16315  {
16316  jam();
16317  initLogpage(signal);
16318  writeSinglePage(signal, logFilePtr.p->currentMbyte * ZPAGES_IN_MBYTE,
16319  ZPAGE_SIZE - 1, __LINE__, false);
16320  lfoPtr.p->lfoState = LogFileOperationRecord::WRITE_INIT_MBYTE;
16321  checkReportStatus(signal);
16322  }
16323  else
16324  {
16325  jam();
16326  seizeLfo(signal);
16327  logFilePtr.p->currentMbyte = clogFileSize - 1;
16328  writeInitMbyteLab(signal);
16329  }
16330 }//Dblqh::writeInitMbyte()
16331 
16332 /* ------------------------------------------------------------------------- */
16333 /* ------- WRITE A SINGLE PAGE INTO A FILE ------- */
16334 /* */
16335 /* INPUT: TWSP_PAGE_NO THE PAGE NUMBER WRITTEN */
16336 /* SUBROUTINE SHORT NAME: WSP */
16337 /* ------------------------------------------------------------------------- */
16338 void Dblqh::writeSinglePage(Signal* signal, Uint32 pageNo,
16339  Uint32 wordWritten, Uint32 place,
16340  bool sync)
16341 {
16342  seizeLfo(signal);
16343  initLfo(signal);
16344  lfoPtr.p->firstLfoPage = logPagePtr.i;
16345  logPagePtr.p->logPageWord[ZNEXT_PAGE] = RNIL;
16346 
16347  writeDbgInfoPageHeader(logPagePtr, place, pageNo, wordWritten);
16348  // Calculate checksum for page
16349  logPagePtr.p->logPageWord[ZPOS_CHECKSUM] = calcPageCheckSum(logPagePtr);
16350 
16351  lfoPtr.p->lfoPageNo = pageNo;
16352  lfoPtr.p->lfoWordWritten = wordWritten;
16353  lfoPtr.p->noPagesRw = 1;
16354 /* -------------------------------------------------- */
16355 /* SET TIMER ON THIS LOG PART TO SIGNIFY THAT A */
16356 /* LOG RECORD HAS BEEN SENT AT THIS TIME. */
16357 /* -------------------------------------------------- */
16358  logPartPtr.p->logPartTimer = logPartPtr.p->logTimer;
16359  signal->theData[0] = logFilePtr.p->fileRef;
16360  signal->theData[1] = cownref;
16361  signal->theData[2] = lfoPtr.i;
16362  signal->theData[3] = sync ? ZLIST_OF_PAIRS_SYNCH : ZLIST_OF_PAIRS;
16363  signal->theData[4] = ZVAR_NO_LOG_PAGE_WORD;
16364  signal->theData[5] = 1; /* ONE PAGE WRITTEN */
16365  signal->theData[6] = logPagePtr.i;
16366  signal->theData[7] = pageNo;
16367  sendSignal(NDBFS_REF, GSN_FSWRITEREQ, signal, 8, JBA);
16368 
16369  ndbrequire(logFilePtr.p->fileRef != RNIL);
16370 
16371  logPartPtr.p->m_io_tracker.send_io(32768);
16372 
16373  if (DEBUG_REDO)
16374  {
16375  ndbout_c("writeSingle 1 page at part: %u file: %u page: %u (mb: %u)",
16376  logPartPtr.p->logPartNo,
16377  logFilePtr.p->fileNo,
16378  pageNo,
16379  pageNo >> ZTWOLOG_NO_PAGES_IN_MBYTE);
16380  }
16381 }//Dblqh::writeSinglePage()
16382 
16383 /* ##########################################################################
16384  * SYSTEM RESTART PHASE ONE MODULE
16385  * THIS MODULE IS A SUB-MODULE OF THE FILE SYSTEM HANDLING.
16386  *
16387  * THIS MODULE CONTAINS THE CODE FOR THE FIRST PHASE OF THE SYSTEM RESTART.
16388  * THE AIM OF THIS PHASE IS TO FIND THE END OF THE LOG AND TO FIND
16389  * INFORMATION ABOUT WHERE GLOBAL CHECKPOINTS ARE COMPLETED AND STARTED
16390  * IN THE LOG. THIS INFORMATION IS NEEDED TO START PHASE THREE OF
16391  * THE SYSTEM RESTART.
16392  * ########################################################################## */
16393 /* --------------------------------------------------------------------------
16394  * A SYSTEM RESTART OR NODE RESTART IS ONGOING. WE HAVE NOW OPENED FILE 0
16395  * NOW WE NEED TO READ PAGE 0 TO FIND WHICH LOG FILE THAT WAS OPEN AT
16396  * CRASH TIME.
16397  * -------------------------------------------------------------------------- */
16398 void Dblqh::openSrFrontpageLab(Signal* signal)
16399 {
16400  readSinglePage(signal, 0);
16402  return;
16403 }//Dblqh::openSrFrontpageLab()
16404 
16405 /* -------------------------------------------------------------------------
16406  * WE HAVE NOW READ PAGE 0 IN FILE 0. CHECK THE LAST OPEN FILE. ACTUALLY THE
16407  * LAST OPEN FILE COULD BE THE NEXT AFTER THAT. CHECK THAT FIRST. WHEN THE
16408  * LAST WAS FOUND WE CAN FIND ALL THE NEEDED INFORMATION WHERE TO START AND
16409  * STOP READING THE LOG.
16410  * -------------------------------------------------------------------------- */
16411 void Dblqh::readSrFrontpageLab(Signal* signal)
16412 {
16413  Uint32 fileNo = logPagePtr.p->logPageWord[ZPAGE_HEADER_SIZE + ZPOS_FILE_NO];
16414  if (fileNo == 0) {
16415  jam();
16416  /* ----------------------------------------------------------------------
16417  * FILE 0 WAS ALSO LAST FILE SO WE DO NOT NEED TO READ IT AGAIN.
16418  * ---------------------------------------------------------------------- */
16419  readSrLastFileLab(signal);
16420  return;
16421  }//if
16422  /* ------------------------------------------------------------------------
16423  * CLOSE FILE 0 SO THAT WE HAVE CLOSED ALL FILES WHEN STARTING TO READ
16424  * THE FRAGMENT LOG. ALSO RELEASE PAGE ZERO.
16425  * ------------------------------------------------------------------------ */
16426  releaseLogpage(signal);
16427  logFilePtr.p->logFileStatus = LogFileRecord::CLOSING_SR;
16428  closeFile(signal, logFilePtr, __LINE__);
16429  LogFileRecordPtr locLogFilePtr;
16430  findLogfile(signal, fileNo, logPartPtr, &locLogFilePtr);
16431  locLogFilePtr.p->logFileStatus = LogFileRecord::OPEN_SR_LAST_FILE;
16432  openFileRw(signal, locLogFilePtr);
16433  return;
16434 }//Dblqh::readSrFrontpageLab()
16435 
16436 void Dblqh::openSrLastFileLab(Signal* signal)
16437 {
16438  readSinglePage(signal, 0);
16440  return;
16441 }//Dblqh::openSrLastFileLab()
16442 
16443 void Dblqh::readSrLastFileLab(Signal* signal)
16444 {
16445  logPartPtr.p->logLap = logPagePtr.p->logPageWord[ZPOS_LOG_LAP];
16446  if (DEBUG_REDO)
16447  {
16448  ndbout_c("readSrLastFileLab part: %u logExecState: %u logPartState: %u logLap: %u",
16449  logPartPtr.p->logPartNo,
16450  logPartPtr.p->logExecState,
16451  logPartPtr.p->logPartState,
16452  logPartPtr.p->logLap);
16453  }
16454  if (logPartPtr.p->noLogFiles > cmaxLogFilesInPageZero) {
16455  jam();
16456  initGciInLogFileRec(signal, cmaxLogFilesInPageZero);
16457  } else {
16458  jam();
16459  initGciInLogFileRec(signal, logPartPtr.p->noLogFiles);
16460  }//if
16461  releaseLogpage(signal);
16462  /* ------------------------------------------------------------------------
16463  * NOW WE HAVE FOUND THE LAST LOG FILE. WE ALSO NEED TO FIND THE LAST
16464  * MBYTE THAT WAS LAST WRITTEN BEFORE THE SYSTEM CRASH.
16465  * ------------------------------------------------------------------------ */
16466  logPartPtr.p->lastLogfile = logFilePtr.i;
16467  readSinglePage(signal, 0);
16468  lfoPtr.p->lfoState = LogFileOperationRecord::READ_SR_LAST_MBYTE;
16469  logFilePtr.p->currentMbyte = 0;
16470  return;
16471 }//Dblqh::readSrLastFileLab()
16472 
16473 void Dblqh::readSrLastMbyteLab(Signal* signal)
16474 {
16475  if (logPartPtr.p->lastMbyte == ZNIL)
16476  {
16477  if (logPagePtr.p->logPageWord[ZPOS_LOG_LAP] < logPartPtr.p->logLap) {
16478  jam();
16479  logPartPtr.p->lastMbyte = logFilePtr.p->currentMbyte - 1;
16480  if (DEBUG_REDO)
16481  {
16482  ndbout_c("readSrLastMbyteLab part: %u file: %u lastMbyte: %u",
16483  logPartPtr.p->logPartNo,
16484  logFilePtr.p->fileNo,
16485  logPartPtr.p->lastMbyte);
16486  }
16487  }//if
16488  }//if
16489  arrGuard(logFilePtr.p->currentMbyte, clogFileSize);
16490  logFilePtr.p->logMaxGciCompleted[logFilePtr.p->currentMbyte] =
16491  logPagePtr.p->logPageWord[ZPOS_MAX_GCI_COMPLETED];
16492  logFilePtr.p->logMaxGciStarted[logFilePtr.p->currentMbyte] =
16493  logPagePtr.p->logPageWord[ZPOS_MAX_GCI_STARTED];
16494  logFilePtr.p->logLastPrepRef[logFilePtr.p->currentMbyte] =
16495  logPagePtr.p->logPageWord[ZLAST_LOG_PREP_REF];
16496  releaseLogpage(signal);
16497  if (logFilePtr.p->currentMbyte < (clogFileSize - 1)) {
16498  jam();
16499  logFilePtr.p->currentMbyte++;
16500  readSinglePage(signal, ZPAGES_IN_MBYTE * logFilePtr.p->currentMbyte);
16501  lfoPtr.p->lfoState = LogFileOperationRecord::READ_SR_LAST_MBYTE;
16502  return;
16503  } else {
16504  jam();
16505  /* ----------------------------------------------------------------------
16506  * THE LOG WAS IN THE LAST MBYTE WHEN THE CRASH OCCURRED SINCE ALL
16507  * LOG LAPS ARE EQUAL TO THE CURRENT LOG LAP.
16508  * ---------------------------------------------------------------------- */
16509  if (logPartPtr.p->lastMbyte == ZNIL) {
16510  jam();
16511  logPartPtr.p->lastMbyte = clogFileSize - 1;
16512  }//if
16513  }//if
16514  logFilePtr.p->logFileStatus = LogFileRecord::CLOSING_SR;
16515  closeFile(signal, logFilePtr, __LINE__);
16516  if (logPartPtr.p->noLogFiles > cmaxLogFilesInPageZero) {
16517  Uint32 fileNo;
16518  if (logFilePtr.p->fileNo >= cmaxLogFilesInPageZero) {
16519  jam();
16520  fileNo = logFilePtr.p->fileNo - cmaxLogFilesInPageZero;
16521  } else {
16522  jam();
16523  fileNo =
16524  (logPartPtr.p->noLogFiles + logFilePtr.p->fileNo) -
16525  cmaxLogFilesInPageZero;
16526  }//if
16527  if (fileNo == 0) {
16528  jam();
16529  /* --------------------------------------------------------------------
16530  * AVOID USING FILE 0 AGAIN SINCE THAT IS PROBABLY CLOSING AT THE
16531  * MOMENT.
16532  * -------------------------------------------------------------------- */
16533  fileNo = 1;
16534  logPartPtr.p->srRemainingFiles =
16535  logPartPtr.p->noLogFiles - (cmaxLogFilesInPageZero - 1);
16536  } else {
16537  jam();
16538  logPartPtr.p->srRemainingFiles =
16539  logPartPtr.p->noLogFiles - cmaxLogFilesInPageZero;
16540  }//if
16541  LogFileRecordPtr locLogFilePtr;
16542  findLogfile(signal, fileNo, logPartPtr, &locLogFilePtr);
16543  locLogFilePtr.p->logFileStatus = LogFileRecord::OPEN_SR_NEXT_FILE;
16544  openFileRw(signal, locLogFilePtr);
16545  return;
16546  }//if
16547  /* ------------------------------------------------------------------------
16548  * THERE WERE NO NEED TO READ ANY MORE PAGE ZERO IN OTHER FILES.
16549  * WE NOW HAVE ALL THE NEEDED INFORMATION ABOUT THE GCI'S THAT WE NEED.
16550  * NOW JUST WAIT FOR CLOSE OPERATIONS TO COMPLETE.
16551  * ------------------------------------------------------------------------ */
16552  return;
16553 }//Dblqh::readSrLastMbyteLab()
16554 
16555 void Dblqh::openSrNextFileLab(Signal* signal)
16556 {
16557  readSinglePage(signal, 0);
16559  return;
16560 }//Dblqh::openSrNextFileLab()
16561 
16562 void Dblqh::readSrNextFileLab(Signal* signal)
16563 {
16564  if (logPartPtr.p->srRemainingFiles > cmaxLogFilesInPageZero) {
16565  jam();
16566  initGciInLogFileRec(signal, cmaxLogFilesInPageZero);
16567  } else {
16568  jam();
16569  initGciInLogFileRec(signal, logPartPtr.p->srRemainingFiles);
16570  }//if
16571  releaseLogpage(signal);
16572  logFilePtr.p->logFileStatus = LogFileRecord::CLOSING_SR;
16573  closeFile(signal, logFilePtr, __LINE__);
16574  if (logPartPtr.p->srRemainingFiles > cmaxLogFilesInPageZero) {
16575  Uint32 fileNo;
16576  if (logFilePtr.p->fileNo >= cmaxLogFilesInPageZero) {
16577  jam();
16578  fileNo = logFilePtr.p->fileNo - cmaxLogFilesInPageZero;
16579  } else {
16580  jam();
16581  fileNo =
16582  (logPartPtr.p->noLogFiles + logFilePtr.p->fileNo) -
16583  cmaxLogFilesInPageZero;
16584  }//if
16585  if (fileNo == 0) {
16586  jam();
16587  /* --------------------------------------------------------------------
16588  * AVOID USING FILE 0 AGAIN SINCE THAT IS PROBABLY CLOSING AT THE MOMENT.
16589  * -------------------------------------------------------------------- */
16590  fileNo = 1;
16591  logPartPtr.p->srRemainingFiles =
16592  logPartPtr.p->srRemainingFiles - (cmaxLogFilesInPageZero - 1);
16593  } else {
16594  jam();
16595  logPartPtr.p->srRemainingFiles =
16596  logPartPtr.p->srRemainingFiles - cmaxLogFilesInPageZero;
16597  }//if
16598  LogFileRecordPtr locLogFilePtr;
16599  findLogfile(signal, fileNo, logPartPtr, &locLogFilePtr);
16600  locLogFilePtr.p->logFileStatus = LogFileRecord::OPEN_SR_NEXT_FILE;
16601  openFileRw(signal, locLogFilePtr);
16602  }//if
16603  /* ------------------------------------------------------------------------
16604  * THERE WERE NO NEED TO READ ANY MORE PAGE ZERO IN OTHER FILES.
16605  * WE NOW HAVE ALL THE NEEDED INFORMATION ABOUT THE GCI'S THAT WE NEED.
16606  * NOW JUST WAIT FOR CLOSE OPERATIONS TO COMPLETE.
16607  * ------------------------------------------------------------------------ */
16608  return;
16609 }//Dblqh::readSrNextFileLab()
16610 
16611 void Dblqh::closingSrLab(Signal* signal)
16612 {
16613  logFilePtr.p->logFileStatus = LogFileRecord::CLOSED;
16614  logPartPtr.i = logFilePtr.p->logPartRec;
16615  ptrCheckGuard(logPartPtr, clogPartFileSize, logPartRecord);
16616  logFilePtr.i = logPartPtr.p->firstLogfile;
16617  do {
16618  jam();
16619  ptrCheckGuard(logFilePtr, clogFileFileSize, logFileRecord);
16620  if (logFilePtr.p->logFileStatus != LogFileRecord::CLOSED) {
16621  jam();
16622  /* --------------------------------------------------------------------
16623  * EXIT AND WAIT FOR REMAINING LOG FILES TO COMPLETE THEIR WORK.
16624  * -------------------------------------------------------------------- */
16625  return;
16626  }//if
16627  logFilePtr.i = logFilePtr.p->nextLogFile;
16628  } while (logFilePtr.i != logPartPtr.p->firstLogfile);
16629  /* ------------------------------------------------------------------------
16630  * ALL FILES IN THIS PART HAVE BEEN CLOSED. THIS INDICATES THAT THE FIRST
16631  * PHASE OF THE SYSTEM RESTART HAVE BEEN CONCLUDED FOR THIS LOG PART.
16632  * CHECK IF ALL OTHER LOG PARTS ARE ALSO COMPLETED.
16633  * ------------------------------------------------------------------------ */
16635  for (logPartPtr.i = 0; logPartPtr.i < clogPartFileSize; logPartPtr.i++) {
16636  jam();
16637  ptrAss(logPartPtr, logPartRecord);
16639  jam();
16640  /* --------------------------------------------------------------------
16641  * EXIT AND WAIT FOR THE REST OF THE LOG PARTS TO COMPLETE.
16642  * -------------------------------------------------------------------- */
16643  return;
16644  }//if
16645  }//for
16646  /* ------------------------------------------------------------------------
16647  * THE FIRST PHASE HAVE BEEN COMPLETED.
16648  * ------------------------------------------------------------------------ */
16649  signal->theData[0] = ZSR_PHASE3_START;
16650  signal->theData[1] = ZSR_PHASE1_COMPLETED;
16651  sendSignal(cownref, GSN_CONTINUEB, signal, 2, JBB);
16652  return;
16653 }//Dblqh::closingSrLab()
16654 
16655 /* ##########################################################################
16656  * ####### SYSTEM RESTART PHASE TWO MODULE #######
16657  *
16658  * THIS MODULE HANDLES THE SYSTEM RESTART WHERE LQH CONTROLS TUP AND ACC TO
16659  * ENSURE THAT THEY HAVE KNOWLEDGE OF ALL FRAGMENTS AND HAVE DONE THE NEEDED
16660  * READING OF DATA FROM FILE AND EXECUTION OF LOCAL LOGS. THIS PROCESS
16661  * EXECUTES CONCURRENTLY WITH PHASE ONE OF THE SYSTEM RESTART. THIS PHASE
16662  * FINDS THE INFORMATION ABOUT THE FRAGMENT LOG NEEDED TO EXECUTE THE FRAGMENT
16663  * LOG.
16664  * WHEN TUP AND ACC HAVE PREPARED ALL FRAGMENTS THEN LQH ORDERS THOSE LQH'S
16665  * THAT ARE RESPONSIBLE TO EXECUTE THE FRAGMENT LOGS TO DO SO. IT IS POSSIBLE
16666  * THAT ANOTHER NODE EXECUTES THE LOG FOR A FRAGMENT RESIDING AT THIS NODE.
16667  * ########################################################################## */
16668 /* ***************>> */
16669 /* START_FRAGREQ > */
16670 /* ***************>> */
16671 void Dblqh::execSTART_FRAGREQ(Signal* signal)
16672 {
16673  const StartFragReq * const startFragReq = (StartFragReq *)&signal->theData[0];
16674  jamEntry();
16675 
16676  tabptr.i = startFragReq->tableId;
16677  Uint32 fragId = startFragReq->fragId;
16678 
16679  ptrCheckGuard(tabptr, ctabrecFileSize, tablerec);
16680  if (!getFragmentrec(signal, fragId)) {
16681  startFragRefLab(signal);
16682  return;
16683  }//if
16684  tabptr.p->tableStatus = Tablerec::TABLE_DEFINED;
16685 
16686  Uint32 lcpNo = startFragReq->lcpNo;
16687  Uint32 noOfLogNodes = startFragReq->noOfLogNodes;
16688  Uint32 lcpId = startFragReq->lcpId;
16689  Uint32 requestInfo = startFragReq->requestInfo;
16690  if (signal->getLength() < StartFragReq::SignalLength)
16691  {
16692  jam();
16693  requestInfo = StartFragReq::SFR_RESTORE_LCP;
16694  }
16695 
16696  bool doprint = false;
16697 #ifdef ERROR_INSERT
16698 
16701  doprint = true;
16702 #endif
16703  if (doprint || noOfLogNodes > 1)
16704  {
16705  printSTART_FRAG_REQ(stdout, signal->getDataPtr(), signal->getLength(),
16706  number());
16707  }
16708 
16709  ndbrequire(noOfLogNodes <= MAX_LOG_EXEC);
16711  fragptr.p->srBlockref = startFragReq->userRef;
16712  fragptr.p->srUserptr = startFragReq->userPtr;
16713  fragptr.p->srChkpnr = lcpNo;
16714  if (lcpNo == (MAX_LCP_STORED - 1)) {
16715  jam();
16716  fragptr.p->lcpId[lcpNo] = lcpId;
16717  } else if (lcpNo < (MAX_LCP_STORED - 1)) {
16718  jam();
16719  fragptr.p->lcpId[lcpNo] = lcpId;
16720  } else {
16721  ndbrequire(lcpNo == ZNIL);
16722  jam();
16723  }//if
16724  fragptr.p->srNoLognodes = noOfLogNodes;
16725  fragptr.p->logFlag = Fragrecord::STATE_FALSE;
16726  fragptr.p->srStatus = Fragrecord::SS_IDLE;
16727 
16728  if (requestInfo == StartFragReq::SFR_COPY_FRAG)
16729  {
16730  ndbrequire(lcpNo == ZNIL);
16731  Uint32 n = fragptr.p->srLqhLognode[0] = startFragReq->lqhLogNode[0]; // src
16732  ndbrequire(ndbd_non_trans_copy_frag_req(getNodeInfo(n).m_version));
16733 
16734  // Magic no, meaning to COPY_FRAGREQ instead of read from disk
16735  fragptr.p->srChkpnr = Z8NIL;
16736  }
16737 
16738  if (noOfLogNodes > 0)
16739  {
16740  jam();
16741  for (Uint32 i = 0; i < noOfLogNodes; i++) {
16742  jam();
16743  fragptr.p->srStartGci[i] = startFragReq->startGci[i];
16744  fragptr.p->srLastGci[i] = startFragReq->lastGci[i];
16745  fragptr.p->srLqhLognode[i] = startFragReq->lqhLogNode[i];
16746  }//for
16747  fragptr.p->newestGci = startFragReq->lastGci[noOfLogNodes - 1];
16748  }
16749  else
16750  {
16751  jam();
16756  if (cnewestGci > fragptr.p->newestGci)
16757  {
16758  jam();
16759  fragptr.p->newestGci = cnewestGci;
16760  }
16761  }//if
16762 
16763  if (requestInfo == StartFragReq::SFR_COPY_FRAG)
16764  {
16765  jam();
16766  }
16767  else if (lcpNo == ZNIL)
16768  {
16769  jam();
16778  c_lcp_complete_fragments.add(fragptr);
16779 
16780  signal->theData[0] = tabptr.i;
16781  signal->theData[1] = fragId;
16782  BlockReference accRef = calcInstanceBlockRef(DBACC);
16783  sendSignal(accRef, GSN_EXPANDCHECK2, signal, 2, JBB);
16784  c_tup->disk_restart_lcp_id(tabptr.i, fragId, RNIL);
16785  jamEntry();
16786  return;
16787  }
16788  else
16789  {
16790  jam();
16791  c_tup->disk_restart_lcp_id(tabptr.i, fragId, lcpId);
16792  jamEntry();
16793 
16794  if (ERROR_INSERTED(5055))
16795  {
16796  ndbrequire(c_lcpId == 0 || lcpId == 0 || c_lcpId == lcpId);
16797  }
16798 
16802  c_lcpId = (c_lcpId == 0 ? lcpId : c_lcpId);
16803  c_lcpId = (c_lcpId < lcpId ? c_lcpId : lcpId);
16804  }
16805 
16806  c_lcp_waiting_fragments.add(fragptr);
16807  if(c_lcp_restoring_fragments.isEmpty())
16808  send_restore_lcp(signal);
16809 }//Dblqh::execSTART_FRAGREQ()
16810 
16811 void
16812 Dblqh::send_restore_lcp(Signal * signal)
16813 {
16814  c_lcp_waiting_fragments.first(fragptr);
16815  c_lcp_waiting_fragments.remove(fragptr);
16816  c_lcp_restoring_fragments.add(fragptr);
16817 
16818  if (fragptr.p->srChkpnr != Z8NIL)
16819  {
16820  jam();
16821  RestoreLcpReq* req= (RestoreLcpReq*)signal->getDataPtrSend();
16822  req->senderData = fragptr.i;
16823  req->senderRef = reference();
16824  req->tableId = fragptr.p->tabRef;
16825  req->fragmentId = fragptr.p->fragId;
16826  req->lcpNo = fragptr.p->srChkpnr;
16827  req->lcpId = fragptr.p->lcpId[fragptr.p->srChkpnr];
16828  BlockReference restoreRef = calcInstanceBlockRef(RESTORE);
16829  sendSignal(restoreRef, GSN_RESTORE_LCP_REQ, signal,
16830  RestoreLcpReq::SignalLength, JBB);
16831  }
16832  else
16833  {
16834  jam();
16835 
16836  tabptr.i = fragptr.p->tabRef;
16837  ptrCheckGuard(tabptr, ctabrecFileSize, tablerec);
16838 
16840  CopyFragReq * req = CAST_PTR(CopyFragReq, signal->getDataPtrSend());
16841  req->senderData = fragptr.i;
16842  req->senderRef = reference();
16843  req->tableId = fragptr.p->tabRef;
16844  req->fragId = fragptr.p->fragId;
16845  req->nodeId = getOwnNodeId();
16846  req->schemaVersion = tabptr.p->schemaVersion;
16847  req->distributionKey = 0;
16848  req->gci = fragptr.p->lcpId[0];
16849  req->nodeCount = 0;
16850  req->nodeList[1] = CopyFragReq::CFR_NON_TRANSACTIONAL;
16851  Uint32 instanceKey = fragptr.p->lqhInstanceKey;
16852  BlockReference ref = numberToRef(DBLQH, instanceKey,
16853  fragptr.p->srLqhLognode[0]);
16854 
16855  sendSignal(ref, GSN_COPY_FRAGREQ, signal,
16856  CopyFragReq::SignalLength, JBB);
16857  }
16858 }
16859 
16860 void
16861 Dblqh::execCOPY_FRAGREF(Signal* signal)
16862 {
16863  jamEntry();
16864 
16865  const CopyFragRef * ref = CAST_CONSTPTR(CopyFragRef, signal->getDataPtr());
16866  Uint32 errorCode = ref->errorCode;
16867 
16868  SystemError * sysErr = (SystemError*)&signal->theData[0];
16869  sysErr->errorCode = SystemError::CopyFragRefError;
16870  sysErr->errorRef = reference();
16871  sysErr->data[0] = errorCode;
16872  sysErr->data[1] = 0;
16873  sendSignal(NDBCNTR_REF, GSN_SYSTEM_ERROR, signal,
16874  SystemError::SignalLength, JBB);
16875 }
16876 
16877 void
16878 Dblqh::execCOPY_FRAGCONF(Signal* signal)
16879 {
16880  jamEntry();
16881  {
16882  const CopyFragConf* conf = CAST_CONSTPTR(CopyFragConf,
16883  signal->getDataPtr());
16884  c_fragment_pool.getPtr(fragptr, conf->senderData);
16886 
16887  Uint32 rows_lo = conf->rows_lo;
16888  Uint32 bytes_lo = conf->bytes_lo;
16889  signal->theData[0] = NDB_LE_NR_CopyFragDone;
16890  signal->theData[1] = getOwnNodeId();
16891  signal->theData[2] = fragptr.p->tabRef;
16892  signal->theData[3] = fragptr.p->fragId;
16893  signal->theData[4] = rows_lo;
16894  signal->theData[5] = 0;
16895  signal->theData[6] = bytes_lo;
16896  signal->theData[7] = 0;
16897  sendSignal(CMVMI_REF, GSN_EVENT_REP, signal, 8, JBB);
16898  }
16899 
16900  {
16901  RestoreLcpConf* conf= (RestoreLcpConf*)signal->getDataPtr();
16902  conf->senderData = fragptr.i;
16903  execRESTORE_LCP_CONF(signal);
16904  }
16905 }
16906 
16907 void Dblqh::startFragRefLab(Signal* signal)
16908 {
16909  const StartFragReq * const startFragReq = (StartFragReq *)&signal->theData[0];
16910  BlockReference userRef = startFragReq->userRef;
16911  Uint32 userPtr = startFragReq->userPtr;
16912  signal->theData[0] = userPtr;
16913  signal->theData[1] = terrorCode;
16914  signal->theData[2] = cownNodeid;
16915  sendSignal(userRef, GSN_START_FRAGREF, signal, 3, JBB);
16916  return;
16917 }//Dblqh::startFragRefLab()
16918 
16919 void Dblqh::execRESTORE_LCP_REF(Signal* signal)
16920 {
16921  jamEntry();
16922  ndbrequire(false);
16923  return;
16924 }
16925 
16926 void Dblqh::execRESTORE_LCP_CONF(Signal* signal)
16927 {
16928  jamEntry();
16929  RestoreLcpConf* conf= (RestoreLcpConf*)signal->getDataPtr();
16930  fragptr.i = conf->senderData;
16931  c_fragment_pool.getPtr(fragptr);
16932 
16933  c_lcp_restoring_fragments.remove(fragptr);
16934  c_lcp_complete_fragments.add(fragptr);
16935 
16940  tabptr.i = fragptr.p->tabRef;
16941  ptrCheckGuard(tabptr, ctabrecFileSize, tablerec);
16942 
16943  signal->theData[0] = fragptr.p->tabRef;
16944  signal->theData[1] = fragptr.p->fragId;
16945  BlockReference accRef = calcInstanceBlockRef(DBACC);
16946  sendSignal(accRef, GSN_EXPANDCHECK2, signal, 2, JBB);
16947 
16948  if (!c_lcp_waiting_fragments.isEmpty())
16949  {
16950  send_restore_lcp(signal);
16951  return;
16952  }
16953 
16954  if (c_lcp_restoring_fragments.isEmpty() &&
16955  cstartRecReq == SRR_START_REC_REQ_ARRIVED)
16956  {
16957  jam();
16958  /* ----------------------------------------------------------------
16959  * WE HAVE ALSO RECEIVED AN INDICATION THAT NO MORE FRAGMENTS
16960  * NEEDS RESTART.
16961  * NOW IT IS TIME TO START EXECUTING THE UNDO LOG.
16962  * ----------------------------------------------------------------
16963  * WE ARE NOW IN A POSITION TO ORDER TUP AND ACC TO START
16964  * EXECUTING THEIR UNDO LOGS. THIS MUST BE DONE BEFORE THE
16965  * FRAGMENT LOGS CAN BE EXECUTED.
16966  * ---------------------------------------------------------------- */
16967  csrExecUndoLogState = EULS_STARTED;
16968  lcpPtr.i = 0;
16969  ptrAss(lcpPtr, lcpRecord);
16970  lcpPtr.p->m_outstanding = 1;
16971 
16972  if (cstartType == NodeState::ST_INITIAL_NODE_RESTART)
16973  {
16974  jam();
16978  signal->theData[0] = LGMAN_REF;
16979  sendSignal(reference(), GSN_START_RECCONF, signal, 1, JBB);
16980  return;
16981  }
16982 
16983  if (!isNdbMtLqh())
16984  {
16985  jam();
16986  signal->theData[0] = c_lcpId;
16987  sendSignal(LGMAN_REF, GSN_START_RECREQ, signal, 1, JBB);
16988  }
16989  else
16990  {
16991  jam();
16992  signal->theData[0] = c_lcpId;
16993  signal->theData[1] = LGMAN;
16994  sendSignal(DBLQH_REF, GSN_START_RECREQ, signal, 2, JBB);
16995  }
16996  return;
16997  }
16998 }
16999 
17000 /* ***************> */
17001 /* START_RECREQ > */
17002 /* ***************> */
17003 void Dblqh::execSTART_RECREQ(Signal* signal)
17004 {
17005  CRASH_INSERTION(5027);
17006 
17007  jamEntry();
17008  StartRecReq * const req = (StartRecReq*)&signal->theData[0];
17009  cmasterDihBlockref = req->senderRef;
17010 
17011  crestartOldestGci = req->keepGci;
17012  crestartNewestGci = req->lastCompletedGci;
17013  cnewestGci = req->newestGci;
17014  cstartRecReqData = req->senderData;
17015 
17016  if (check_ndb_versions())
17017  {
17018  ndbrequire(crestartOldestGci <= crestartNewestGci);
17019  }
17020 
17021  ndbrequire(req->receivingNodeId == cownNodeid);
17022 
17023  cnewestCompletedGci = cnewestGci;
17024  cstartRecReq = SRR_START_REC_REQ_ARRIVED; // StartRecReq has arrived
17025 
17026  if (signal->getLength() == StartRecReq::SignalLength)
17027  {
17028  jam();
17029  NdbNodeBitmask tmp;
17030  tmp.assign(NdbNodeBitmask::Size, req->sr_nodes);
17031  if (!tmp.equal(m_sr_nodes))
17032  {
17033  char buf0[100], buf1[100];
17034  ndbout_c("execSTART_RECREQ chaning srnodes from %s to %s",
17035  m_sr_nodes.getText(buf0),
17036  tmp.getText(buf1));
17037 
17038  }
17039  m_sr_nodes.assign(NdbNodeBitmask::Size, req->sr_nodes);
17040  }
17041  else
17042  {
17043  jam();
17044  cstartRecReqData = RNIL;
17045  }
17046 
17047  for (logPartPtr.i = 0; logPartPtr.i < clogPartFileSize; logPartPtr.i++) {
17048  ptrAss(logPartPtr, logPartRecord);
17049  logPartPtr.p->logPartNewestCompletedGCI = cnewestCompletedGci;
17050  }//for
17051  /* ------------------------------------------------------------------------
17052  * WE HAVE TO SET THE OLDEST AND THE NEWEST GLOBAL CHECKPOINT IDENTITY
17053  * THAT WILL SURVIVE THIS SYSTEM RESTART. THIS IS NEEDED SO THAT WE CAN
17054  * SET THE LOG HEAD AND LOG TAIL PROPERLY BEFORE STARTING THE SYSTEM AGAIN.
17055  * WE ALSO NEED TO SET CNEWEST_GCI TO ENSURE THAT LOG RECORDS ARE EXECUTED
17056  * WITH A PROPER GCI.
17057  *------------------------------------------------------------------------ */
17058 
17059  if (c_lcp_restoring_fragments.isEmpty())
17060  {
17061  jam();
17062  csrExecUndoLogState = EULS_STARTED;
17063 
17064  lcpPtr.i = 0;
17065  ptrAss(lcpPtr, lcpRecord);
17066  lcpPtr.p->m_outstanding = 1;
17067 
17068  if (cstartType == NodeState::ST_INITIAL_NODE_RESTART)
17069  {
17070  jam();
17074  signal->theData[0] = LGMAN_REF;
17075  sendSignal(reference(), GSN_START_RECCONF, signal, 1, JBB);
17076  return;
17077  }
17078 
17079  if (!isNdbMtLqh())
17080  {
17081  jam();
17082  signal->theData[0] = c_lcpId;
17083  sendSignal(LGMAN_REF, GSN_START_RECREQ, signal, 1, JBB);
17084  }
17085  else
17086  {
17087  jam();
17088  signal->theData[0] = c_lcpId;
17089  signal->theData[1] = LGMAN;
17090  sendSignal(DBLQH_REF, GSN_START_RECREQ, signal, 2, JBB);
17091  }
17092  }//if
17093 }//Dblqh::execSTART_RECREQ()
17094 
17095 /* ***************>> */
17096 /* START_RECCONF > */
17097 /* ***************>> */
17098 void Dblqh::execSTART_RECCONF(Signal* signal)
17099 {
17100  jamEntry();
17101  lcpPtr.i = 0;
17102  ptrAss(lcpPtr, lcpRecord);
17103  ndbrequire(csrExecUndoLogState == EULS_STARTED);
17104  ndbrequire(lcpPtr.p->m_outstanding);
17105 
17106  Uint32 sender= signal->theData[0];
17107 
17108  if (ERROR_INSERTED(5055))
17109  {
17110  CLEAR_ERROR_INSERT_VALUE;
17111  }
17112 
17113  lcpPtr.p->m_outstanding--;
17114  if(lcpPtr.p->m_outstanding)
17115  {
17116  jam();
17117  return;
17118  }
17119 
17120  switch(refToBlock(sender)){
17121  case TSMAN:
17122  jam();
17123  break;
17124  case LGMAN:
17125  jam();
17126  lcpPtr.p->m_outstanding++;
17127  if (!isNdbMtLqh())
17128  {
17129  jam();
17130  signal->theData[0] = c_lcpId;
17131  sendSignal(TSMAN_REF, GSN_START_RECREQ, signal, 1, JBB);
17132  }
17133  else
17134  {
17135  jam();
17136  signal->theData[0] = c_lcpId;
17137  signal->theData[1] = TSMAN;
17138  sendSignal(DBLQH_REF, GSN_START_RECREQ, signal, 2, JBB);
17139  }
17140  return;
17141  break;
17142  default:
17143  ndbrequire(false);
17144  }
17145 
17146  jam();
17147  csrExecUndoLogState = EULS_COMPLETED;
17148 
17149  if(cstartType == NodeState::ST_INITIAL_NODE_RESTART)
17150  {
17151  jam();
17152  cstartRecReq = SRR_REDO_COMPLETE; // REDO complete
17153 
17154  rebuildOrderedIndexes(signal, 0);
17155  return;
17156  }
17157 
17158  startExecSr(signal);
17159 }
17160 
17161 /* ***************> */
17162 /* START_RECREF > */
17163 /* ***************> */
17164 void Dblqh::execSTART_RECREF(Signal* signal)
17165 {
17166  jamEntry();
17167  ndbrequire(false);
17168 }//Dblqh::execSTART_RECREF()
17169 
17170 void
17171 Dblqh::rebuildOrderedIndexes(Signal* signal, Uint32 tableId)
17172 {
17173  jamEntry();
17174 
17175  if (tableId == 0)
17176  {
17177  jam();
17178  infoEvent("LQH: Starting to rebuild ordered indexes");
17179  }
17180 
17181  if (tableId >= ctabrecFileSize)
17182  {
17183  jam();
17184 
17185  for (logPartPtr.i = 0; logPartPtr.i < clogPartFileSize; logPartPtr.i++)
17186  {
17187  jam();
17188  ptrCheckGuard(logPartPtr, clogPartFileSize, logPartRecord);
17189  LogFileRecordPtr logFile;
17190  logFile.i = logPartPtr.p->currentLogfile;
17191  ptrCheckGuard(logFile, clogFileFileSize, logFileRecord);
17192 
17193  LogPosition head = { logFile.p->fileNo, logFile.p->currentMbyte };
17194  LogPosition tail = { logPartPtr.p->logTailFileNo,
17195  logPartPtr.p->logTailMbyte};
17196  Uint64 mb = free_log(head, tail, logPartPtr.p->noLogFiles, clogFileSize);
17197  if (mb <= c_free_mb_tail_problem_limit)
17198  {
17199  jam();
17200  update_log_problem(signal, logPartPtr,
17201  LogPartRecord::P_TAIL_PROBLEM, true);
17202  }
17203  }
17204 
17205  if (!isNdbMtLqh())
17206  {
17210  signal->theData[0] = 12003;
17211  sendSignal(LGMAN_REF, GSN_DUMP_STATE_ORD, signal, 1, JBB);
17212  }
17213 
17214  StartRecConf * conf = (StartRecConf*)signal->getDataPtrSend();
17215  conf->startingNodeId = getOwnNodeId();
17216  conf->senderData = cstartRecReqData;
17217  sendSignal(cmasterDihBlockref, GSN_START_RECCONF, signal,
17218  StartRecConf::SignalLength, JBB);
17219 
17220  infoEvent("LQH: Rebuild ordered indexes complete");
17221  return;
17222  }
17223 
17224  tabptr.i = tableId;
17225  ptrCheckGuard(tabptr, ctabrecFileSize, tablerec);
17226  if (! (DictTabInfo::isOrderedIndex(tabptr.p->tableType) &&
17227  tabptr.p->tableStatus == Tablerec::TABLE_DEFINED))
17228  {
17229  jam();
17230  signal->theData[0] = ZREBUILD_ORDERED_INDEXES;
17231  signal->theData[1] = tableId + 1;
17232  sendSignal(reference(), GSN_CONTINUEB, signal, 2, JBB);
17233  return;
17234  }
17235 
17236  signal->theData[0] = NDB_LE_RebuildIndex;
17237  signal->theData[1] = instance();
17238  signal->theData[2] = tableId;
17239  sendSignal(CMVMI_REF, GSN_EVENT_REP, signal, 3, JBB);
17240 
17241  BuildIndxImplReq* const req = (BuildIndxImplReq*)signal->getDataPtrSend();
17242  req->senderRef = reference();
17243  req->senderData = tableId;
17244  req->requestType = BuildIndxImplReq::RF_BUILD_OFFLINE;
17245  req->buildId = 0; // not yet..
17246  req->buildKey = 0; // ..in use
17247  req->transId = 0;
17248  req->indexType = tabptr.p->tableType;
17249  req->indexId = tableId;
17250  req->tableId = tabptr.p->primaryTableId;
17251  req->parallelism = 0;
17252  sendSignal(calcInstanceBlockRef(DBTUP), GSN_BUILD_INDX_IMPL_REQ, signal,
17253  BuildIndxImplReq::SignalLength, JBB);
17254 }
17255 
17256 void
17257 Dblqh::execBUILD_INDX_IMPL_REF(Signal * signal)
17258 {
17259  jamEntry();
17260  ndbrequire(false); // TODO error message
17261 }
17262 
17263 void
17264 Dblqh::execBUILD_INDX_IMPL_CONF(Signal* signal)
17265 {
17266  jamEntry();
17267  BuildIndxImplConf * conf = (BuildIndxImplConf*)signal->getDataPtr();
17268  Uint32 tableId = conf->senderData;
17269  rebuildOrderedIndexes(signal, tableId + 1);
17270  infoEvent("LQH: index %u rebuild done", tableId);
17271 }
17272 
17273 /* ***************>> */
17274 /* START_EXEC_SR > */
17275 /* ***************>> */
17276 void Dblqh::execSTART_EXEC_SR(Signal* signal)
17277 {
17278  jamEntry();
17279  fragptr.i = signal->theData[0];
17280  Uint32 next = RNIL;
17281 
17282  if (fragptr.i == RNIL)
17283  {
17284  jam();
17285  /* ----------------------------------------------------------------------
17286  * NO MORE FRAGMENTS TO START EXECUTING THE LOG ON.
17287  * SEND EXEC_SRREQ TO ALL LQH TO INDICATE THAT THIS NODE WILL
17288  * NOT REQUEST ANY MORE FRAGMENTS TO EXECUTE THE FRAGMENT LOG ON.
17289  * ----------------------------------------------------------------------
17290  * WE NEED TO SEND THOSE SIGNALS EVEN IF WE HAVE NOT REQUESTED
17291  * ANY FRAGMENTS PARTICIPATE IN THIS PHASE.
17292  * --------------------------------------------------------------------- */
17293  signal->theData[0] = cownNodeid;
17294  if (!isNdbMtLqh())
17295  {
17296  jam();
17297  NodeReceiverGroup rg(DBLQH, m_sr_nodes);
17298  sendSignal(rg, GSN_EXEC_SRREQ, signal, 1, JBB);
17299  }
17300  else
17301  {
17302  jam();
17303  const Uint32 sz = NdbNodeBitmask::Size;
17304  m_sr_nodes.copyto(sz, &signal->theData[1]);
17305  sendSignal(DBLQH_REF, GSN_EXEC_SRREQ, signal, 1 + sz, JBB);
17306  }
17307  return;
17308  } else {
17309  jam();
17310  c_lcp_complete_fragments.getPtr(fragptr);
17311  next = fragptr.p->nextList;
17312 
17313  if (fragptr.p->srNoLognodes > csrPhasesCompleted)
17314  {
17315  jam();
17316  cnoOutstandingExecFragReq++;
17317 
17318  Uint32 index = csrPhasesCompleted;
17319  arrGuard(index, MAX_LOG_EXEC);
17320  Uint32 Tnode = fragptr.p->srLqhLognode[index];
17321  Uint32 instanceKey = fragptr.p->lqhInstanceKey;
17322  BlockReference ref = numberToRef(DBLQH, instanceKey, Tnode);
17323  fragptr.p->srStatus = Fragrecord::SS_STARTED;
17324 
17325  /* --------------------------------------------------------------------
17326  * SINCE WE CAN HAVE SEVERAL LQH NODES PER FRAGMENT WE CALCULATE
17327  * THE LQH POINTER IN SUCH A WAY THAT WE CAN DEDUCE WHICH OF THE
17328  * LQH NODES THAT HAS RESPONDED WHEN EXEC_FRAGCONF IS RECEIVED.
17329  * ------------------------------------------------------------------- */
17330  ExecFragReq * const execFragReq = (ExecFragReq *)&signal->theData[0];
17331  execFragReq->userPtr = fragptr.i;
17332  execFragReq->userRef = cownref;
17333  execFragReq->tableId = fragptr.p->tabRef;
17334  execFragReq->fragId = fragptr.p->fragId;
17335  execFragReq->startGci = fragptr.p->srStartGci[index];
17336  execFragReq->lastGci = fragptr.p->srLastGci[index];
17337  execFragReq->dst = ref;
17338 
17339  if (isNdbMtLqh())
17340  {
17341  jam();
17342  // send via local proxy
17343  sendSignal(DBLQH_REF, GSN_EXEC_FRAGREQ, signal,
17344  ExecFragReq::SignalLength, JBB);
17345  }
17346  else if (ndb_route_exec_frag(getNodeInfo(refToNode(ref)).m_version))
17347  {
17348  jam();
17349  // send via remote proxy
17350  sendSignal(numberToRef(DBLQH, refToNode(ref)), GSN_EXEC_FRAGREQ, signal,
17351  ExecFragReq::SignalLength, JBB);
17352  }
17353  else
17354  {
17355  jam();
17356  // send direct
17357  sendSignal(ref, GSN_EXEC_FRAGREQ, signal,
17358  ExecFragReq::SignalLength, JBB);
17359  }
17360  }
17361  signal->theData[0] = next;
17362  sendSignal(cownref, GSN_START_EXEC_SR, signal, 1, JBB);
17363  }//if
17364  return;
17365 }//Dblqh::execSTART_EXEC_SR()
17366 
17367 /* ***************> */
17368 /* EXEC_FRAGREQ > */
17369 /* ***************> */
17370 /* --------------------------------------------------------------------------
17371  * THIS SIGNAL IS USED TO REQUEST THAT A FRAGMENT PARTICIPATES IN EXECUTING
17372  * THE LOG IN THIS NODE.
17373  * ------------------------------------------------------------------------- */
17374 void Dblqh::execEXEC_FRAGREQ(Signal* signal)
17375 {
17376  ExecFragReq * const execFragReq = (ExecFragReq *)&signal->theData[0];
17377  jamEntry();
17378  tabptr.i = execFragReq->tableId;
17379  Uint32 fragId = execFragReq->fragId;
17380  ptrCheckGuard(tabptr, ctabrecFileSize, tablerec);
17381  ndbrequire(getFragmentrec(signal, fragId));
17382 
17383  ndbrequire(fragptr.p->execSrNoReplicas < MAX_REPLICAS);
17384  fragptr.p->execSrBlockref[fragptr.p->execSrNoReplicas] = execFragReq->userRef;
17385  fragptr.p->execSrUserptr[fragptr.p->execSrNoReplicas] = execFragReq->userPtr;
17386  fragptr.p->execSrStartGci[fragptr.p->execSrNoReplicas] = execFragReq->startGci;
17387  fragptr.p->execSrLastGci[fragptr.p->execSrNoReplicas] = execFragReq->lastGci;
17388  fragptr.p->execSrStatus = Fragrecord::ACTIVE;
17389  fragptr.p->execSrNoReplicas++;
17390  cnoFragmentsExecSr++;
17391  return;
17392 }//Dblqh::execEXEC_FRAGREQ()
17393 
17394 void Dblqh::sendExecFragRefLab(Signal* signal)
17395 {
17396  ExecFragReq * const execFragReq = (ExecFragReq *)&signal->theData[0];
17397  BlockReference retRef = execFragReq->userRef;
17398  Uint32 retPtr = execFragReq->userPtr;
17399 
17400  signal->theData[0] = retPtr;
17401  signal->theData[1] = terrorCode;
17402  sendSignal(retRef, GSN_EXEC_FRAGREF, signal, 2, JBB);
17403  return;
17404 }//Dblqh::sendExecFragRefLab()
17405 
17406 /* ***************>> */
17407 /* EXEC_FRAGCONF > */
17408 /* ***************>> */
17409 void Dblqh::execEXEC_FRAGCONF(Signal* signal)
17410 {
17411  jamEntry();
17412  fragptr.i = signal->theData[0];
17413  c_fragment_pool.getPtr(fragptr);
17414  fragptr.p->srStatus = Fragrecord::SS_COMPLETED;
17415 
17416  ndbrequire(cnoOutstandingExecFragReq);
17417  cnoOutstandingExecFragReq--;
17418  if (fragptr.p->srNoLognodes == csrPhasesCompleted + 1)
17419  {
17420  jam();
17421 
17422  fragptr.p->logFlag = Fragrecord::STATE_TRUE;
17423  fragptr.p->fragStatus = Fragrecord::FSACTIVE;
17424 
17425  signal->theData[0] = fragptr.p->srUserptr;
17426  signal->theData[1] = cownNodeid;
17427  sendSignal(fragptr.p->srBlockref, GSN_START_FRAGCONF, signal, 2, JBB);
17428  }
17429 
17430  return;
17431 }//Dblqh::execEXEC_FRAGCONF()
17432 
17433 /* ***************> */
17434 /* EXEC_FRAGREF > */
17435 /* ***************> */
17436 void Dblqh::execEXEC_FRAGREF(Signal* signal)
17437 {
17438  jamEntry();
17439  terrorCode = signal->theData[1];
17440  systemErrorLab(signal, __LINE__);
17441  return;
17442 }//Dblqh::execEXEC_FRAGREF()
17443 
17444 /* *************** */
17445 /* EXEC_SRCONF > */
17446 /* *************** */
17447 void Dblqh::execEXEC_SRCONF(Signal* signal)
17448 {
17449  jamEntry();
17450  Uint32 nodeId = signal->theData[0];
17451  arrGuard(nodeId, MAX_NDB_NODES);
17452  m_sr_exec_sr_conf.set(nodeId);
17453 
17454  if (!m_sr_nodes.equal(m_sr_exec_sr_conf))
17455  {
17456  jam();
17457  /* ------------------------------------------------------------------
17458  * ALL NODES HAVE NOT REPORTED COMPLETION OF EXECUTING FRAGMENT
17459  * LOGS YET.
17460  * ----------------------------------------------------------------- */
17461  return;
17462  }
17463 
17464  if (cnoOutstandingExecFragReq != 0)
17465  {
17471  jam();
17472  ndbassert(false);
17473  m_sr_exec_sr_conf.clear(nodeId);
17474  ndbout << "delay: reqs=" << cnoOutstandingExecFragReq << endl;
17475  sendSignalWithDelay(reference(), GSN_EXEC_SRCONF,
17476  signal, 10, signal->getLength());
17477  return;
17478  }
17479 
17480  /* ------------------------------------------------------------------------
17481  * CLEAR NODE SYSTEM RESTART EXECUTION STATE TO PREPARE FOR NEXT PHASE OF
17482  * LOG EXECUTION.
17483  * ----------------------------------------------------------------------- */
17484  m_sr_exec_sr_conf.clear();
17485  cnoFragmentsExecSr = 0;
17486 
17487  /* ------------------------------------------------------------------------
17488  * NOW CHECK IF ALL FRAGMENTS IN THIS PHASE HAVE COMPLETED. IF SO START THE
17489  * NEXT PHASE.
17490  * ----------------------------------------------------------------------- */
17491  ndbrequire(cnoOutstandingExecFragReq == 0);
17492 
17493  execSrCompletedLab(signal);
17494  return;
17495 }//Dblqh::execEXEC_SRCONF()
17496 
17497 void Dblqh::execSrCompletedLab(Signal* signal)
17498 {
17499  csrPhasesCompleted++;
17500  /* ------------------------------------------------------------------------
17501  * ALL FRAGMENTS WERE COMPLETED. THIS PHASE IS COMPLETED. IT IS NOW TIME TO
17502  * START THE NEXT PHASE.
17503  * ----------------------------------------------------------------------- */
17504  if (csrPhasesCompleted >= MAX_LOG_EXEC) {
17505  jam();
17506  /* ----------------------------------------------------------------------
17507  * THIS WAS THE LAST PHASE. WE HAVE NOW COMPLETED THE EXECUTION THE
17508  * FRAGMENT LOGS IN ALL NODES. BEFORE WE SEND START_RECCONF TO THE
17509  * MASTER DIH TO INDICATE A COMPLETED SYSTEM RESTART IT IS NECESSARY
17510  * TO FIND THE HEAD AND THE TAIL OF THE LOG WHEN NEW OPERATIONS START
17511  * TO COME AGAIN.
17512  *
17513  * THE FIRST STEP IS TO FIND THE HEAD AND TAIL MBYTE OF EACH LOG PART.
17514  * TO DO THIS WE REUSE THE CONTINUEB SIGNAL SR_LOG_LIMITS. THEN WE
17515  * HAVE TO FIND THE ACTUAL PAGE NUMBER AND PAGE INDEX WHERE TO
17516  * CONTINUE WRITING THE LOG AFTER THE SYSTEM RESTART.
17517  * --------------------------------------------------------------------- */
17518  for (logPartPtr.i = 0; logPartPtr.i < clogPartFileSize; logPartPtr.i++) {
17519  jam();
17520  ptrAss(logPartPtr, logPartRecord);
17522  logPartPtr.p->logLastGci = crestartNewestGci;
17523  logPartPtr.p->logStartGci = crestartOldestGci;
17524  logPartPtr.p->logExecState = LogPartRecord::LES_SEARCH_STOP;
17525  if (logPartPtr.p->headFileNo == ZNIL) {
17526  jam();
17527  /* -----------------------------------------------------------------
17528  * IF WE HAVEN'T FOUND ANY HEAD OF THE LOG THEN WE ARE IN SERIOUS
17529  * PROBLEM. THIS SHOULD NOT OCCUR. IF IT OCCURS ANYWAY THEN WE
17530  * HAVE TO FIND A CURE FOR THIS PROBLEM.
17531  * ----------------------------------------------------------------- */
17532  systemErrorLab(signal, __LINE__);
17533  return;
17534  }//if
17535 
17536  if (DEBUG_REDO)
17537  {
17538  ndbout_c("part: %u srLogLimits SR_FOURTH_PHASE %u-%u (file: %u mb: %u)",
17539  logPartPtr.p->logPartNo,
17540  logPartPtr.p->logStartGci,
17541  logPartPtr.p->logLastGci,
17542  logPartPtr.p->lastLogfile,
17543  logPartPtr.p->lastMbyte);
17544  }
17545 
17546  signal->theData[0] = ZSR_LOG_LIMITS;
17547  signal->theData[1] = logPartPtr.i;
17548  signal->theData[2] = logPartPtr.p->lastLogfile;
17549  signal->theData[3] = logPartPtr.p->lastMbyte;
17550  sendSignal(cownref, GSN_CONTINUEB, signal, 4, JBB);
17551  }//for
17552  return;
17553  } else {
17554  jam();
17555  /* ----------------------------------------------------------------------
17556  * THERE ARE YET MORE PHASES TO RESTART.
17557  * WE MUST INITIALISE DATA FOR NEXT PHASE AND SEND START SIGNAL.
17558  * --------------------------------------------------------------------- */
17559  csrPhaseStarted = ZSR_PHASE1_COMPLETED; // Set correct state first...
17560  startExecSr(signal);
17561  }//if
17562  return;
17563 }//Dblqh::execSrCompletedLab()
17564 
17565 /* ************>> */
17566 /* EXEC_SRREQ > */
17567 /* ************>> */
17568 void Dblqh::execEXEC_SRREQ(Signal* signal)
17569 {
17570  jamEntry();
17571  Uint32 nodeId = signal->theData[0];
17572  ndbrequire(nodeId < MAX_NDB_NODES);
17573  m_sr_exec_sr_req.set(nodeId);
17574  if (!m_sr_exec_sr_req.equal(m_sr_nodes))
17575  {
17576  jam();
17577  return;
17578  }
17579 
17580  /* ------------------------------------------------------------------------
17581  * CLEAR NODE SYSTEM RESTART STATE TO PREPARE FOR NEXT PHASE OF LOG
17582  * EXECUTION
17583  * ----------------------------------------------------------------------- */
17584  m_sr_exec_sr_req.clear();
17585 
17586  if (csrPhasesCompleted != 0) {
17587  /* ----------------------------------------------------------------------
17588  * THE FIRST PHASE MUST ALWAYS EXECUTE THE LOG.
17589  * --------------------------------------------------------------------- */
17590  if (cnoFragmentsExecSr == 0) {
17591  jam();
17592  /* --------------------------------------------------------------------
17593  * THERE WERE NO FRAGMENTS THAT NEEDED TO EXECUTE THE LOG IN THIS PHASE.
17594  * ------------------------------------------------------------------- */
17595  srPhase3Comp(signal);
17596  return;
17597  }//if
17598  }//if
17599  /* ------------------------------------------------------------------------
17600  * NOW ALL NODES HAVE SENT ALL EXEC_FRAGREQ. NOW WE CAN START EXECUTING THE
17601  * LOG FROM THE MINIMUM GCI NEEDED UNTIL THE MAXIMUM GCI NEEDED.
17602  *
17603  * WE MUST FIRST CHECK IF THE FIRST PHASE OF THE SYSTEM RESTART HAS BEEN
17604  * COMPLETED. THIS HANDLING IS PERFORMED IN THE FILE SYSTEM MODULE
17605  * ----------------------------------------------------------------------- */
17606  signal->theData[0] = ZSR_PHASE3_START;
17607  signal->theData[1] = ZSR_PHASE2_COMPLETED;
17608  sendSignal(cownref, GSN_CONTINUEB, signal, 2, JBB);
17609  return;
17610 }//Dblqh::execEXEC_SRREQ()
17611 
17612 /* ######################################################################### */
17613 /* SYSTEM RESTART PHASE THREE MODULE */
17614 /* THIS MODULE IS A SUB-MODULE OF THE FILE SYSTEM HANDLING. */
17615 /* */
17616 /* THIS MODULE IS CONCERNED WITH EXECUTING THE FRAGMENT LOG. IT DOES ALSO */
17617 /* CONTAIN SIGNAL RECEPTIONS LQHKEYCONF AND LQHKEYREF SINCE LQHKEYREQ IS USED*/
17618 /* TO EXECUTE THE LOG RECORDS. */
17619 /* */
17620 /* BEFORE IT STARTS IT HAS BEEN DECIDED WHERE TO START AND WHERE TO STOP */
17621 /* READING THE FRAGMENT LOG BY USING THE INFORMATION ABOUT GCI DISCOVERED IN */
17622 /* PHASE ONE OF THE SYSTEM RESTART. */
17623 /* ######################################################################### */
17624 /*---------------------------------------------------------------------------*/
17625 /* PHASE THREE OF THE SYSTEM RESTART CAN NOW START. ONE OF THE PHASES HAVE */
17626 /* COMPLETED. */
17627 /*---------------------------------------------------------------------------*/
17628 void Dblqh::srPhase3Start(Signal* signal)
17629 {
17630  UintR tsrPhaseStarted;
17631 
17632  jamEntry();
17633 
17634  tsrPhaseStarted = signal->theData[1];
17635  if (csrPhaseStarted == ZSR_NO_PHASE_STARTED) {
17636  jam();
17637  csrPhaseStarted = tsrPhaseStarted;
17638  return;
17639  }//if
17640  ndbrequire(csrPhaseStarted != tsrPhaseStarted);
17641  ndbrequire(csrPhaseStarted != ZSR_BOTH_PHASES_STARTED);
17642 
17643  csrPhaseStarted = ZSR_BOTH_PHASES_STARTED;
17644  for (logPartPtr.i = 0; logPartPtr.i < clogPartFileSize; logPartPtr.i++) {
17645  jam();
17646  ptrAss(logPartPtr, logPartRecord);
17648  logPartPtr.p->logStartGci = (UintR)-1;
17649  if (csrPhasesCompleted == 0) {
17650  jam();
17651  /* --------------------------------------------------------------------
17652  * THE FIRST PHASE WE MUST ENSURE THAT IT REACHES THE END OF THE LOG.
17653  * ------------------------------------------------------------------- */
17654  logPartPtr.p->logLastGci = crestartNewestGci;
17655  } else {
17656  jam();
17657  logPartPtr.p->logLastGci = 2;
17658  }//if
17659  }//for
17660 
17661  jam();
17662  c_lcp_complete_fragments.first(fragptr);
17663  signal->theData[0] = ZSR_GCI_LIMITS;
17664  signal->theData[1] = fragptr.i;
17665  sendSignal(cownref, GSN_CONTINUEB, signal, 2, JBB);
17666  return;
17667 }//Dblqh::srPhase3Start()
17668 
17669 /* --------------------------------------------------------------------------
17670  * WE NOW WE NEED TO FIND THE LIMITS WITHIN WHICH TO EXECUTE
17671  * THE FRAGMENT LOG
17672  * ------------------------------------------------------------------------- */
17673 void Dblqh::srGciLimits(Signal* signal)
17674 {
17675  jamEntry();
17676  fragptr.i = signal->theData[0];
17677  Uint32 loopCount = 0;
17678  logPartPtr.i = 0;
17679  ptrAss(logPartPtr, logPartRecord);
17680  while (fragptr.i != RNIL){
17681  jam();
17682  c_lcp_complete_fragments.getPtr(fragptr);
17683  ndbrequire(fragptr.p->execSrNoReplicas - 1 < MAX_REPLICAS);
17684  for (Uint32 i = 0; i < fragptr.p->execSrNoReplicas; i++) {
17685  jam();
17686  if (fragptr.p->execSrStartGci[i] < logPartPtr.p->logStartGci) {
17687  jam();
17688  logPartPtr.p->logStartGci = fragptr.p->execSrStartGci[i];
17689  }//if
17690  if (fragptr.p->execSrLastGci[i] > logPartPtr.p->logLastGci) {
17691  jam();
17692  logPartPtr.p->logLastGci = fragptr.p->execSrLastGci[i];
17693  }
17694  }
17695 
17696  loopCount++;
17697  if (loopCount > 20) {
17698  jam();
17699  signal->theData[0] = ZSR_GCI_LIMITS;
17700  signal->theData[1] = fragptr.p->nextList;
17701  sendSignal(cownref, GSN_CONTINUEB, signal, 2, JBB);
17702  return;
17703  } else {
17704  jam();
17705  fragptr.i = fragptr.p->nextList;
17706  }//if
17707  }
17708 
17709  if (logPartPtr.p->logStartGci == (UintR)-1) {
17710  jam();
17711  /* --------------------------------------------------------------------
17712  * THERE WERE NO FRAGMENTS TO INSTALL WE WILL EXECUTE THE LOG AS
17713  * SHORT AS POSSIBLE TO REACH THE END OF THE LOG. THIS WE DO BY
17714  * STARTING AT THE STOP GCI.
17715  * ------------------------------------------------------------------- */
17716  logPartPtr.p->logStartGci = logPartPtr.p->logLastGci;
17717  }//if
17718 
17719  for(Uint32 i = 1; i < clogPartFileSize; i++)
17720  {
17721  LogPartRecordPtr tmp;
17722  tmp.i = i;
17723  ptrAss(tmp, logPartRecord);
17724  tmp.p->logStartGci = logPartPtr.p->logStartGci;
17725  tmp.p->logLastGci = logPartPtr.p->logLastGci;
17726  }
17727 
17728  for (logPartPtr.i = 0; logPartPtr.i < clogPartFileSize; logPartPtr.i++) {
17729  jam();
17730  ptrAss(logPartPtr, logPartRecord);
17731  logPartPtr.p->logExecState = LogPartRecord::LES_SEARCH_STOP;
17732  if (DEBUG_REDO)
17733  {
17734  ndbout_c("part: %u srLogLimits (srGciLimits) %u-%u (file: %u mb: %u)",
17735  logPartPtr.p->logPartNo,
17736  logPartPtr.p->logStartGci,
17737  logPartPtr.p->logLastGci,
17738  logPartPtr.p->lastLogfile,
17739  logPartPtr.p->lastMbyte);
17740  }
17741  signal->theData[0] = ZSR_LOG_LIMITS;
17742  signal->theData[1] = logPartPtr.i;
17743  signal->theData[2] = logPartPtr.p->lastLogfile;
17744  signal->theData[3] = logPartPtr.p->lastMbyte;
17745  sendSignal(cownref, GSN_CONTINUEB, signal, 4, JBB);
17746  }//for
17747 }//Dblqh::srGciLimits()
17748 
17749 /* --------------------------------------------------------------------------
17750  * IT IS NOW TIME TO FIND WHERE TO START EXECUTING THE LOG.
17751  * THIS SIGNAL IS SENT FOR EACH LOG PART AND STARTS THE EXECUTION
17752  * OF THE LOG FOR THIS PART.
17753  *-------------------------------------------------------------------------- */
17754 void Dblqh::srLogLimits(Signal* signal)
17755 {
17756  Uint32 tlastPrepRef;
17757  Uint32 tmbyte;
17758 
17759  jamEntry();
17760  logPartPtr.i = signal->theData[0];
17761  ptrCheckGuard(logPartPtr, clogPartFileSize, logPartRecord);
17762  logFilePtr.i = signal->theData[1];
17763  ptrCheckGuard(logFilePtr, clogFileFileSize, logFileRecord);
17764  tmbyte = signal->theData[2];
17765  Uint32 loopCount = 0;
17766  /* ------------------------------------------------------------------------
17767  * WE ARE SEARCHING FOR THE START AND STOP MBYTE OF THE LOG THAT IS TO BE
17768  * EXECUTED.
17769  * ----------------------------------------------------------------------- */
17770  while(true) {
17771  ndbrequire(tmbyte < clogFileSize);
17772  if (logPartPtr.p->logExecState == LogPartRecord::LES_SEARCH_STOP)
17773  {
17774  if (logFilePtr.p->logMaxGciCompleted[tmbyte] <= logPartPtr.p->logLastGci)
17775  {
17776  jam();
17777  /* --------------------------------------------------------------------
17778  * WE ARE STEPPING BACKWARDS FROM MBYTE TO MBYTE. THIS IS THE FIRST
17779  * MBYTE WHICH IS TO BE INCLUDED IN THE LOG EXECUTION. THE STOP GCI
17780  * HAS NOT BEEN COMPLETED BEFORE THIS MBYTE. THUS THIS MBYTE HAVE
17781  * TO BE EXECUTED.
17782  * ------------------------------------------------------------------ */
17783  logPartPtr.p->stopLogfile = logFilePtr.i;
17784  logPartPtr.p->stopMbyte = tmbyte;
17785  logPartPtr.p->logExecState = LogPartRecord::LES_SEARCH_START;
17786  if (DEBUG_REDO)
17787  {
17788  ndbout_c("part: %u srLogLimits found stop pos file: %u mb: %u logMaxGciCompleted[tmbyte]: %u (lastGci: %u)",
17789  logPartPtr.p->logPartNo,
17790  logFilePtr.p->fileNo,
17791  tmbyte,
17792  logFilePtr.p->logMaxGciCompleted[tmbyte],
17793  logPartPtr.p->logLastGci);
17794  }
17795  }//if
17796  else if (DEBUG_REDO)
17797  {
17798  ndbout_c("SEARCH STOP SKIP part: %u file: %u mb: %u "
17799  "logMaxGciCompleted: %u > %u",
17800  logPartPtr.p->logPartNo,
17801  logFilePtr.p->fileNo,
17802  tmbyte,
17803  logFilePtr.p->logMaxGciCompleted[tmbyte],
17804  logPartPtr.p->logLastGci);
17805  }
17806  }//if
17807  /* ------------------------------------------------------------------------
17808  * WHEN WE HAVEN'T FOUND THE STOP MBYTE IT IS NOT NECESSARY TO LOOK FOR THE
17809  * START MBYTE. THE REASON IS THE FOLLOWING LOGIC CHAIN:
17810  * MAX_GCI_STARTED >= MAX_GCI_COMPLETED >= LAST_GCI >= START_GCI
17811  * THUS MAX_GCI_STARTED >= START_GCI. THUS MAX_GCI_STARTED < START_GCI CAN
17812  * NOT BE TRUE AS WE WILL CHECK OTHERWISE.
17813  * ---------------------------------------------------------------------- */
17814  if (logPartPtr.p->logExecState == LogPartRecord::LES_SEARCH_START)
17815  {
17816  if (logFilePtr.p->logMaxGciStarted[tmbyte] < logPartPtr.p->logStartGci)
17817  {
17818  jam();
17819  /* --------------------------------------------------------------------
17820  * WE HAVE NOW FOUND THE START OF THE EXECUTION OF THE LOG.
17821  * WE STILL HAVE TO MOVE IT BACKWARDS TO ALSO INCLUDE THE
17822  * PREPARE RECORDS WHICH WERE STARTED IN A PREVIOUS MBYTE.
17823  * ------------------------------------------------------------------ */
17824  if (DEBUG_REDO)
17825  {
17826  ndbout_c("part: %u srLogLimits found start pos file: %u mb: %u logMaxGciStarted[tmbyte]: %u (startGci: %u)",
17827  logPartPtr.p->logPartNo,
17828  logFilePtr.p->fileNo,
17829  tmbyte,
17830  logFilePtr.p->logMaxGciCompleted[tmbyte],
17831  logPartPtr.p->logStartGci);
17832  ndbout_c("part: %u srLogLimits lastPrepRef => file: %u mb: %u",
17833  logPartPtr.p->logPartNo,
17834  logFilePtr.p->logLastPrepRef[tmbyte] >> 16,
17835  logFilePtr.p->logLastPrepRef[tmbyte] & 65535);
17836  }
17837  tlastPrepRef = logFilePtr.p->logLastPrepRef[tmbyte];
17838  logPartPtr.p->startMbyte = tlastPrepRef & 65535;
17839  LogFileRecordPtr locLogFilePtr;
17840  findLogfile(signal, tlastPrepRef >> 16, logPartPtr, &locLogFilePtr);
17841  logPartPtr.p->startLogfile = locLogFilePtr.i;
17842  logPartPtr.p->logExecState = LogPartRecord::LES_EXEC_LOG;
17843  }
17844  else if (DEBUG_REDO)
17845  {
17846  ndbout_c("SEARCH START SKIP part: %u file: %u mb: %u "
17847  "logMaxGciCompleted: %u >= %u",
17848  logPartPtr.p->logPartNo,
17849  logFilePtr.p->fileNo,
17850  tmbyte,
17851  logFilePtr.p->logMaxGciStarted[tmbyte],
17852  logPartPtr.p->logStartGci);
17853  }
17854  }//if
17855  if (logPartPtr.p->logExecState != LogPartRecord::LES_EXEC_LOG) {
17856  if (tmbyte == 0) {
17857  jam();
17858  tmbyte = clogFileSize - 1;
17859  logFilePtr.i = logFilePtr.p->prevLogFile;
17860  ptrCheckGuard(logFilePtr, clogFileFileSize, logFileRecord);
17861  } else {
17862  jam();
17863  tmbyte--;
17864  }//if
17865  if (logPartPtr.p->lastLogfile == logFilePtr.i) {
17866  ndbrequire(logPartPtr.p->lastMbyte != tmbyte);
17867  }//if
17868  if (loopCount > 20) {
17869  jam();
17870  signal->theData[0] = ZSR_LOG_LIMITS;
17871  signal->theData[1] = logPartPtr.i;
17872  signal->theData[2] = logFilePtr.i;
17873  signal->theData[3] = tmbyte;
17874  sendSignal(cownref, GSN_CONTINUEB, signal, 4, JBB);
17875  return;
17876  }//if
17877  loopCount++;
17878  } else {
17879  jam();
17880  break;
17881  }//if
17882  }//while
17883 
17884  if (DEBUG_REDO)
17885  {
17886  LogFileRecordPtr tmp;
17887  tmp.i = logPartPtr.p->stopLogfile;
17888  ptrCheckGuard(tmp, clogFileFileSize, logFileRecord);
17889  ndbout_c("srLogLimits part: %u gci: %u-%u start file: %u mb: %u stop file: %u mb: %u",
17890  logPartPtr.p->logPartNo,
17891  logPartPtr.p->logStartGci,
17892  logPartPtr.p->logLastGci,
17893  tlastPrepRef >> 16,
17894  tlastPrepRef & 65535,
17895  tmp.p->fileNo,
17896  logPartPtr.p->stopMbyte);
17897  }
17898 
17899 
17900 
17901  /* ------------------------------------------------------------------------
17902  * WE HAVE NOW FOUND BOTH THE START AND THE STOP OF THE LOG. NOW START
17903  * EXECUTING THE LOG. THE FIRST ACTION IS TO OPEN THE LOG FILE WHERE TO
17904  * START EXECUTING THE LOG.
17905  * ----------------------------------------------------------------------- */
17906  if (logPartPtr.p->logPartState == LogPartRecord::SR_THIRD_PHASE_STARTED) {
17907  jam();
17908  logFilePtr.i = logPartPtr.p->startLogfile;
17909  ptrCheckGuard(logFilePtr, clogFileFileSize, logFileRecord);
17911  openFileRw(signal, logFilePtr);
17912  send_runredo_event(signal, logPartPtr.p, logPartPtr.p->logStartGci);
17913  } else {
17914  jam();
17915  ndbrequire(logPartPtr.p->logPartState == LogPartRecord::SR_FOURTH_PHASE_STARTED);
17916  /* --------------------------------------------------------------------
17917  * WE HAVE NOW FOUND THE TAIL MBYTE IN THE TAIL FILE.
17918  * SET THOSE PARAMETERS IN THE LOG PART.
17919  * WE HAVE ALSO FOUND THE HEAD MBYTE. WE STILL HAVE TO SEARCH
17920  * FOR THE PAGE NUMBER AND PAGE INDEX WHERE TO SET THE HEAD.
17921  * ------------------------------------------------------------------- */
17922  logFilePtr.i = logPartPtr.p->startLogfile;
17923  ptrCheckGuard(logFilePtr, clogFileFileSize, logFileRecord);
17924  logPartPtr.p->logTailFileNo = logFilePtr.p->fileNo;
17925  logPartPtr.p->logTailMbyte = logPartPtr.p->startMbyte;
17926  /* --------------------------------------------------------------------
17927  * THE HEAD WE ACTUALLY FOUND DURING EXECUTION OF LOG SO WE USE
17928  * THIS INFO HERE RATHER THAN THE MBYTE WE FOUND TO BE THE HEADER.
17929  * ------------------------------------------------------------------- */
17930  LogFileRecordPtr locLogFilePtr;
17931  findLogfile(signal, logPartPtr.p->headFileNo, logPartPtr, &locLogFilePtr);
17932  locLogFilePtr.p->logFileStatus = LogFileRecord::OPEN_SR_FOURTH_PHASE;
17933  openFileRw(signal, locLogFilePtr);
17934  }//if
17935  return;
17936 }//Dblqh::srLogLimits()
17937 
17938 void Dblqh::openExecSrStartLab(Signal* signal)
17939 {
17940  logPartPtr.p->currentLogfile = logFilePtr.i;
17941  logFilePtr.p->currentMbyte = logPartPtr.p->startMbyte;
17942  /* ------------------------------------------------------------------------
17943  * WE NEED A TC CONNECT RECORD TO HANDLE EXECUTION OF LOG RECORDS.
17944  * ------------------------------------------------------------------------ */
17945  seizeTcrec();
17946  logPartPtr.p->logTcConrec = tcConnectptr.i;
17947  /* ------------------------------------------------------------------------
17948  * THE FIRST LOG RECORD TO EXECUTE IS ALWAYS AT A NEW MBYTE.
17949  * SET THE NUMBER OF PAGES IN THE MAIN MEMORY BUFFER TO ZERO AS AN INITIAL
17950  * VALUE. THIS VALUE WILL BE UPDATED AND ENSURED THAT IT RELEASES PAGES IN
17951  * THE SUBROUTINE READ_EXEC_SR.
17952  * ----------------------------------------------------------------------- */
17953  logPartPtr.p->mmBufferSize = 0;
17954  readExecSrNewMbyte(signal);
17955  return;
17956 }//Dblqh::openExecSrStartLab()
17957 
17958 /* ---------------------------------------------------------------------------
17959  * WE WILL ALWAYS ENSURE THAT WE HAVE AT LEAST 16 KBYTE OF LOG PAGES WHEN WE
17960  * START READING A LOG RECORD. THE ONLY EXCEPTION IS WHEN WE COME CLOSE TO A
17961  * MBYTE BOUNDARY. SINCE WE KNOW THAT LOG RECORDS ARE NEVER WRITTEN ACROSS A
17962  * MBYTE BOUNDARY THIS IS NOT A PROBLEM.
17963  *
17964  * WE START BY READING 64 KBYTE BEFORE STARTING TO EXECUTE THE LOG RECORDS.
17965  * WHEN WE COME BELOW 64 KBYTE WE READ ANOTHER SET OF LOG PAGES. WHEN WE
17966  * GO BELOW 16 KBYTE WE WAIT UNTIL THE READ PAGES HAVE ENTERED THE BLOCK.
17967  * ------------------------------------------------------------------------- */
17968 /* --------------------------------------------------------------------------
17969  * NEW PAGES FROM LOG FILE DURING EXECUTION OF LOG HAS ARRIVED.
17970  * ------------------------------------------------------------------------- */
17971 void Dblqh::readExecSrLab(Signal* signal)
17972 {
17973  buildLinkedLogPageList(signal);
17974  /* ------------------------------------------------------------------------
17975  * WE NEED TO SET THE CURRENT PAGE INDEX OF THE FIRST PAGE SINCE IT CAN BE
17976  * USED IMMEDIATELY WITHOUT ANY OTHER INITIALISATION. THE REST OF THE PAGES
17977  * WILL BE INITIALISED BY READ_LOGWORD.
17978  * ----------------------------------------------------------------------- */
17979  logPagePtr.p->logPageWord[ZCURR_PAGE_INDEX] = ZPAGE_HEADER_SIZE;
17980  if (logPartPtr.p->logExecState ==
17981  LogPartRecord::LES_WAIT_READ_EXEC_SR_NEW_MBYTE) {
17982  jam();
17983  /* ----------------------------------------------------------------------
17984  * THIS IS THE FIRST READ DURING THE EXECUTION OF THIS MBYTE. SET THE
17985  * NEW CURRENT LOG PAGE TO THE FIRST OF THESE PAGES. CHANGE
17986  * LOG_EXEC_STATE TO ENSURE THAT WE START EXECUTION OF THE LOG.
17987  * --------------------------------------------------------------------- */
17988  logFilePtr.p->currentFilepage = logFilePtr.p->currentMbyte *
17989  ZPAGES_IN_MBYTE;
17990  logPartPtr.p->prevFilepage = logFilePtr.p->currentFilepage;
17991  logFilePtr.p->currentLogpage = lfoPtr.p->firstLfoPage;
17992  logPartPtr.p->prevLogpage = logFilePtr.p->currentLogpage;
17993  }//if
17994  moveToPageRef(signal);
17995  releaseLfo(signal);
17996  /* ------------------------------------------------------------------------
17997  * NOW WE HAVE COMPLETED THE RECEPTION OF THESE PAGES.
17998  * NOW CHECK IF WE NEED TO READ MORE PAGES.
17999  * ----------------------------------------------------------------------- */
18000  checkReadExecSr(signal);
18001  if (logPartPtr.p->logExecState == LogPartRecord::LES_EXEC_LOG) {
18002  jam();
18003  signal->theData[0] = ZEXEC_SR;
18004  signal->theData[1] = logPartPtr.i;
18005  sendSignal(cownref, GSN_CONTINUEB, signal, 2, JBB);
18006  return;
18007  }//if
18008  return;
18009 }//Dblqh::readExecSrLab()
18010 
18011 void Dblqh::openExecSrNewMbyteLab(Signal* signal)
18012 {
18013  readExecSrNewMbyte(signal);
18014  return;
18015 }//Dblqh::openExecSrNewMbyteLab()
18016 
18017 void Dblqh::closeExecSrLab(Signal* signal)
18018 {
18019  LogFileRecordPtr locLogFilePtr;
18020  logFilePtr.p->logFileStatus = LogFileRecord::CLOSED;
18021  logPartPtr.i = logFilePtr.p->logPartRec;
18022  ptrCheckGuard(logPartPtr, clogPartFileSize, logPartRecord);
18023  locLogFilePtr.i = logPartPtr.p->currentLogfile;
18024  ptrCheckGuard(locLogFilePtr, clogFileFileSize, logFileRecord);
18025  locLogFilePtr.p->logFileStatus = LogFileRecord::OPEN_EXEC_SR_NEW_MBYTE;
18026  openFileRw(signal, locLogFilePtr);
18027  return;
18028 }//Dblqh::closeExecSrLab()
18029 
18030 void Dblqh::writeDirtyLab(Signal* signal)
18031 {
18032  releaseLfo(signal);
18033  signal->theData[0] = logPartPtr.i;
18034  execSr(signal);
18035  return;
18036 }//Dblqh::writeDirtyLab()
18037 
18038 /* --------------------------------------------------------------------------
18039  * EXECUTE A LOG RECORD WITHIN THE CURRENT MBYTE.
18040  * ------------------------------------------------------------------------- */
18041 void Dblqh::execSr(Signal* signal)
18042 {
18043  LogFileRecordPtr nextLogFilePtr;
18044  LogPageRecordPtr tmpLogPagePtr;
18045  Uint32 logWord;
18046  Uint32 line;
18047  const char * crash_msg = 0;
18048 
18049  jamEntry();
18050  logPartPtr.i = signal->theData[0];
18051  ptrCheckGuard(logPartPtr, clogPartFileSize, logPartRecord);
18052 
18053  do {
18054  jam();
18055  logFilePtr.i = logPartPtr.p->currentLogfile;
18056  ptrCheckGuard(logFilePtr, clogFileFileSize, logFileRecord);
18057  logPagePtr.i = logPartPtr.p->prevLogpage;
18058  ptrCheckGuard(logPagePtr, clogPageFileSize, logPageRecord);
18059  if (logPagePtr.p->logPageWord[ZPOS_DIRTY] == ZDIRTY) {
18060  jam();
18061  switch (logPartPtr.p->logExecState) {
18062  case LogPartRecord::LES_EXEC_LOG_COMPLETED:
18063  case LogPartRecord::LES_EXEC_LOG_NEW_FILE:
18064  case LogPartRecord::LES_EXEC_LOG_NEW_MBYTE:
18065  jam();
18066  /* ------------------------------------------------------------------
18067  * IN THIS WE HAVE COMPLETED EXECUTION OF THE CURRENT LOG PAGE
18068  * AND CAN WRITE IT TO DISK SINCE IT IS DIRTY.
18069  * ----------------------------------------------------------------- */
18070  writeDirty(signal, __LINE__);
18071  return;
18072  break;
18073  case LogPartRecord::LES_EXEC_LOG:
18074  jam();
18075  /* --------------------------------------------------------------------
18076  * IN THIS CASE WE ONLY WRITE THE PAGE TO DISK IF WE HAVE COMPLETED
18077  * EXECUTION OF LOG RECORDS BELONGING TO THIS LOG PAGE.
18078  * ------------------------------------------------------------------- */
18079  if (logFilePtr.p->currentLogpage != logPartPtr.p->prevLogpage) {
18080  jam();
18081  writeDirty(signal, __LINE__);
18082  return;
18083  }//if
18084  break;
18085  default:
18086  ndbrequire(false);
18087  break;
18088  }//switch
18089  }//if
18090  if (logFilePtr.p->currentLogpage != logPartPtr.p->prevLogpage) {
18091  jam();
18092  logPartPtr.p->prevLogpage = logPagePtr.p->logPageWord[ZNEXT_PAGE];
18093  logPartPtr.p->prevFilepage++;
18094  continue;
18095  }//if
18096  switch (logPartPtr.p->logExecState) {
18097  case LogPartRecord::LES_EXEC_LOG_COMPLETED:
18098  jam();
18099  releaseMmPages(signal);
18100  logFilePtr.p->logFileStatus = LogFileRecord::CLOSING_EXEC_SR_COMPLETED;
18101  closeFile(signal, logFilePtr, __LINE__);
18102  return;
18103  break;
18104  case LogPartRecord::LES_EXEC_LOG_NEW_MBYTE:
18105  jam();
18106  logFilePtr.p->currentMbyte++;
18107  readExecSrNewMbyte(signal);
18108  return;
18109  break;
18110  case LogPartRecord::LES_EXEC_LOG_NEW_FILE:
18111  jam();
18112  nextLogFilePtr.i = logFilePtr.p->nextLogFile;
18113  logPartPtr.p->currentLogfile = nextLogFilePtr.i;
18114  ptrCheckGuard(nextLogFilePtr, clogFileFileSize, logFileRecord);
18115  nextLogFilePtr.p->currentMbyte = 0;
18117  closeFile(signal, logFilePtr, __LINE__);
18118  return;
18119  break;
18120  case LogPartRecord::LES_EXEC_LOG:
18121  jam();
18122  /*empty*/;
18123  break;
18124  default:
18125  jam();
18126  systemErrorLab(signal, __LINE__);
18127  return;
18128  break;
18129  }//switch
18130  logPagePtr.i = logFilePtr.p->currentLogpage;
18131  ptrCheckGuard(logPagePtr, clogPageFileSize, logPageRecord);
18132  logPartPtr.p->savePageIndex = logPagePtr.p->logPageWord[ZCURR_PAGE_INDEX];
18133  if (logPartPtr.p->execSrPagesRead < ZMIN_READ_BUFFER_SIZE) {
18134  /* --------------------------------------------------------------------
18135  * THERE WERE LESS THAN 16 KBYTE OF LOG PAGES REMAINING. WE WAIT UNTIL
18136  * THE NEXT 64 KBYTE ARRIVES UNTIL WE CONTINUE AGAIN.
18137  * ------------------------------------------------------------------- */
18138  if ((logPartPtr.p->execSrPagesRead +
18139  logPartPtr.p->execSrPagesExecuted) < ZPAGES_IN_MBYTE) {
18140  jam();
18141  /* ------------------------------------------------------------------
18142  * WE ONLY STOP AND WAIT IF THERE MORE PAGES TO READ. IF IT IS NOT
18143  * THEN IT IS THE END OF THE MBYTE AND WE WILL CONTINUE. IT IS NO
18144  * RISK THAT A LOG RECORD WE FIND WILL NOT BE READ AT THIS TIME
18145  * SINCE THE LOG RECORDS NEVER SPAN OVER A MBYTE BOUNDARY.
18146  * ----------------------------------------------------------------- */
18147  readExecSr(signal);
18148  logPartPtr.p->logExecState = LogPartRecord::LES_WAIT_READ_EXEC_SR;
18149  return;
18150  }//if
18151  }//if
18152  logWord = readLogword(signal);
18153  switch (logWord) {
18154 /* ========================================================================= */
18155 /* ========================================================================= */
18156  case ZPREP_OP_TYPE:
18157  {
18158  logWord = readLogword(signal);
18159  stepAhead(signal, logWord - 2);
18160  break;
18161  }
18162 /* ========================================================================= */
18163 /* ========================================================================= */
18164  case ZINVALID_COMMIT_TYPE:
18165  jam();
18166  stepAhead(signal, ZCOMMIT_LOG_SIZE - 1);
18167  break;
18168 /* ========================================================================= */
18169 /* ========================================================================= */
18170  case ZCOMMIT_TYPE:
18171  {
18172  CommitLogRecord commitLogRecord;
18173  jam();
18174  tcConnectptr.i = logPartPtr.p->logTcConrec;
18175  ptrCheckGuard(tcConnectptr, ctcConnectrecFileSize, tcConnectionrec);
18176  readCommitLog(signal, &commitLogRecord);
18177  if (tcConnectptr.p->gci_hi > crestartNewestGci) {
18178  jam();
18179 /*---------------------------------------------------------------------------*/
18180 /* THIS LOG RECORD MUST BE IGNORED. IT IS PART OF A GLOBAL CHECKPOINT WHICH */
18181 /* WILL BE INVALIDATED BY THE SYSTEM RESTART. IF NOT INVALIDATED IT MIGHT BE */
18182 /* EXECUTED IN A FUTURE SYSTEM RESTART. */
18183 /*---------------------------------------------------------------------------*/
18184  tmpLogPagePtr.i = logPartPtr.p->prevLogpage;
18185  ptrCheckGuard(tmpLogPagePtr, clogPageFileSize, logPageRecord);
18186  arrGuard(logPartPtr.p->savePageIndex, ZPAGE_SIZE);
18187  tmpLogPagePtr.p->logPageWord[logPartPtr.p->savePageIndex] =
18188  ZINVALID_COMMIT_TYPE;
18189  tmpLogPagePtr.p->logPageWord[ZPOS_DIRTY] = ZDIRTY;
18190  } else {
18191  jam();
18192 /*---------------------------------------------------------------------------*/
18193 /* CHECK IF I AM SUPPOSED TO EXECUTE THIS LOG RECORD. IF I AM THEN SAVE PAGE */
18194 /* INDEX IN CURRENT LOG PAGE SINCE IT WILL BE OVERWRITTEN WHEN EXECUTING THE */
18195 /* LOG RECORD. */
18196 /*---------------------------------------------------------------------------*/
18197  logPartPtr.p->execSrExecuteIndex = 0;
18198  Uint32 result = checkIfExecLog(signal);
18199  if (result == ZOK) {
18200  jam();
18201 //*---------------------------------------------------------------------------*/
18202 /* IN A NODE RESTART WE WILL NEVER END UP HERE SINCE NO FRAGMENTS HAVE BEEN */
18203 /* DEFINED YET. THUS NO EXTRA CHECKING FOR NODE RESTART IS NECESSARY. */
18204 /*---------------------------------------------------------------------------*/
18205  logPartPtr.p->savePageIndex =
18206  logPagePtr.p->logPageWord[ZCURR_PAGE_INDEX];
18207  tcConnectptr.p->fragmentptr = fragptr.i;
18208  findPageRef(signal, &commitLogRecord);
18209  logPartPtr.p->execSrLogPageIndex = commitLogRecord.startPageIndex;
18210  if (logPagePtr.i != RNIL) {
18211  jam();
18212  logPagePtr.p->logPageWord[ZCURR_PAGE_INDEX] = commitLogRecord.startPageIndex;
18213  logPartPtr.p->execSrLogPage = logPagePtr.i;
18214  execLogRecord(signal);
18215  return;
18216  }//if
18217  logPartPtr.p->execSrStartPageNo = commitLogRecord.startPageNo;
18218  logPartPtr.p->execSrStopPageNo = commitLogRecord.stopPageNo;
18219  findLogfile(signal, commitLogRecord.fileNo, logPartPtr, &logFilePtr);
18220  logPartPtr.p->execSrExecLogFile = logFilePtr.i;
18221  if (logFilePtr.i == logPartPtr.p->currentLogfile) {
18222  jam();
18223 #ifndef NO_REDO_PAGE_CACHE
18224  Uint32 cnt = 1 +
18225  logPartPtr.p->execSrStopPageNo - logPartPtr.p->execSrStartPageNo;
18226  evict(m_redo_page_cache, cnt);
18227 #endif
18228  readExecLog(signal);
18229  lfoPtr.p->lfoState = LogFileOperationRecord::READ_EXEC_LOG;
18230  return;
18231  } else {
18232  jam();
18233 /*---------------------------------------------------------------------------*/
18234 /* THE FILE IS CURRENTLY NOT OPEN. WE MUST OPEN IT BEFORE WE CAN READ FROM */
18235 /* THE FILE. */
18236 /*---------------------------------------------------------------------------*/
18237 #ifndef NO_REDO_OPEN_FILE_CACHE
18238  openFileRw_cache(signal, logFilePtr);
18239 #else
18240  logFilePtr.p->logFileStatus = LogFileRecord::OPEN_EXEC_LOG;
18241  openFileRw(signal, logFilePtr);
18242 #endif
18243  return;
18244  }//if
18245  }//if
18246  }//if
18247  break;
18248  }
18249 /* ========================================================================= */
18250 /* ========================================================================= */
18251  case ZABORT_TYPE:
18252  jam();
18253  stepAhead(signal, ZABORT_LOG_SIZE - 1);
18254  break;
18255 /* ========================================================================= */
18256 /* ========================================================================= */
18257  case ZFD_TYPE:
18258  jam();
18259 /*---------------------------------------------------------------------------*/
18260 /* THIS IS THE FIRST ITEM WE ENCOUNTER IN A NEW FILE. AT THIS MOMENT WE SHALL*/
18261 /* SIMPLY BYPASS IT. IT HAS NO SIGNIFANCE WHEN EXECUTING THE LOG. IT HAS ITS */
18262 /* SIGNIFANCE WHEN FINDING THE START END THE END OF THE LOG. */
18263 /* WE HARDCODE THE PAGE INDEX SINCE THIS SHOULD NEVER BE FOUND AT ANY OTHER */
18264 /* PLACE THAN IN THE FIRST PAGE OF A NEW FILE IN THE FIRST POSITION AFTER THE*/
18265 /* HEADER. */
18266 /*---------------------------------------------------------------------------*/
18267  if (unlikely(logPagePtr.p->logPageWord[ZCURR_PAGE_INDEX] !=
18268  (ZPAGE_HEADER_SIZE + ZPOS_NO_FD)))
18269  {
18270  line = __LINE__;
18271  logWord = logPagePtr.p->logPageWord[ZCURR_PAGE_INDEX];
18272  crash_msg = "ZFD_TYPE at incorrect position!";
18273  goto crash;
18274  }
18275  {
18276  Uint32 noFdDescriptors =
18277  logPagePtr.p->logPageWord[ZPAGE_HEADER_SIZE + ZPOS_NO_FD];
18278  logPagePtr.p->logPageWord[ZCURR_PAGE_INDEX] =
18279  (ZPAGE_HEADER_SIZE + ZFD_HEADER_SIZE) +
18280  (noFdDescriptors * ZFD_MBYTE_SIZE * clogFileSize);
18281  }
18282  break;
18283 /* ========================================================================= */
18284 /* ========================================================================= */
18285  case ZNEXT_LOG_RECORD_TYPE:
18286  jam();
18287  stepAhead(signal, ZPAGE_SIZE - logPagePtr.p->logPageWord[ZCURR_PAGE_INDEX]);
18288  break;
18289 /* ========================================================================= */
18290 /* ========================================================================= */
18291  case ZNEXT_MBYTE_TYPE:
18292 /*---------------------------------------------------------------------------*/
18293 /* WE WILL SKIP A PART OF THE LOG FILE. ACTUALLY THE NEXT POINTER IS TO */
18294 /* A NEW MBYTE. THEREFORE WE WILL START UP A NEW MBYTE. THIS NEW MBYTE IS */
18295 /* HOWEVER ONLY STARTED IF IT IS NOT AFTER THE STOP MBYTE. */
18296 /* IF WE HAVE REACHED THE END OF THE STOP MBYTE THEN THE EXECUTION OF THE LOG*/
18297 /* IS COMPLETED. */
18298 /*---------------------------------------------------------------------------*/
18299  if (logPartPtr.p->currentLogfile == logPartPtr.p->stopLogfile) {
18300  if (logFilePtr.p->currentMbyte == logPartPtr.p->stopMbyte) {
18301  jam();
18302 /*---------------------------------------------------------------------------*/
18303 /* THIS WAS THE LAST MBYTE TO EXECUTE IN THIS LOG PART. WE SHOULD HAVE FOUND */
18304 /* A COMPLETED GCI RECORD OF THE LAST GCI BEFORE THIS. FOR SOME REASON THIS */
18305 /* RECORD WAS NOT AVAILABLE ON THE LOG. CRASH THE SYSTEM, A VERY SERIOUS */
18306 /* ERROR WHICH WE MUST REALLY WORK HARD TO AVOID. */
18307 /*---------------------------------------------------------------------------*/
18308 /*---------------------------------------------------------------------------*/
18309 /* SEND A SIGNAL TO THE SIGNAL LOG AND THEN CRASH THE SYSTEM. */
18310 /*---------------------------------------------------------------------------*/
18311  line = __LINE__;
18312  logWord = ZNEXT_MBYTE_TYPE;
18313  crash_msg = "end of log wo/ having found last GCI";
18314  goto crash;
18315  }//if
18316  }//if
18317 /*---------------------------------------------------------------------------*/
18318 /* START EXECUTION OF A NEW MBYTE IN THE LOG. */
18319 /*---------------------------------------------------------------------------*/
18320  if (logFilePtr.p->currentMbyte < (clogFileSize - 1)) {
18321  jam();
18322  logPartPtr.p->logExecState = LogPartRecord::LES_EXEC_LOG_NEW_MBYTE;
18323  } else {
18324  ndbrequire(logFilePtr.p->currentMbyte == (clogFileSize - 1));
18325  jam();
18326 /*---------------------------------------------------------------------------*/
18327 /* WE HAVE TO CHANGE FILE. CLOSE THIS ONE AND THEN OPEN THE NEXT. */
18328 /*---------------------------------------------------------------------------*/
18329  logPartPtr.p->logExecState = LogPartRecord::LES_EXEC_LOG_NEW_FILE;
18330  }//if
18331  break;
18332 /* ========================================================================= */
18333 /* ========================================================================= */
18334  case ZCOMPLETED_GCI_TYPE:
18335  jam();
18336  logWord = readLogword(signal);
18337  if (DEBUG_REDO)
18338  {
18339  ndbout_c("found gci: %u part: %u file: %u page: %u (mb: %u)",
18340  logWord,
18341  logPartPtr.p->logPartNo,
18342  logFilePtr.p->fileNo,
18343  logFilePtr.p->currentFilepage,
18344  logFilePtr.p->currentFilepage >> ZTWOLOG_NO_PAGES_IN_MBYTE);
18345  }
18346  if (logWord == logPartPtr.p->logLastGci)
18347  {
18348  jam();
18349 /*---------------------------------------------------------------------------*/
18350 /* IF IT IS THE LAST GCI TO LIVE AFTER SYSTEM RESTART THEN WE RECORD THE NEXT*/
18351 /* WORD AS THE NEW HEADER OF THE LOG FILE. OTHERWISE WE SIMPLY IGNORE THIS */
18352 /* LOG RECORD. */
18353 /*---------------------------------------------------------------------------*/
18354  if (csrPhasesCompleted == 0) {
18355  jam();
18356 /*---------------------------------------------------------------------------*/
18357 /*WE ONLY RECORD THE HEAD OF THE LOG IN THE FIRST LOG ROUND OF LOG EXECUTION.*/
18358 /*---------------------------------------------------------------------------*/
18359  logPartPtr.p->headFileNo = logFilePtr.p->fileNo;
18360  logPartPtr.p->headPageNo = logFilePtr.p->currentFilepage;
18361  logPartPtr.p->headPageIndex =
18362  logPagePtr.p->logPageWord[ZCURR_PAGE_INDEX];
18363  logPartPtr.p->logLap = logPagePtr.p->logPageWord[ZPOS_LOG_LAP];
18364  if (DEBUG_REDO)
18365  {
18366  ndbout_c("execSr part: %u logLap: %u",
18367  logPartPtr.p->logPartNo, logPartPtr.p->logLap);
18368  }
18369  }//if
18370 /*---------------------------------------------------------------------------*/
18371 /* THERE IS NO NEED OF EXECUTING PAST THIS LINE SINCE THERE WILL ONLY BE LOG */
18372 /* RECORDS THAT WILL BE OF NO INTEREST. THUS CLOSE THE FILE AND START THE */
18373 /* NEXT PHASE OF THE SYSTEM RESTART. */
18374 /*---------------------------------------------------------------------------*/
18375  logPartPtr.p->logExecState = LogPartRecord::LES_EXEC_LOG_COMPLETED;
18376  send_runredo_event(signal, logPartPtr.p, logPartPtr.p->logLastGci);
18377  }//if
18378  break;
18379  default:
18380  jam();
18381 /* ========================================================================= */
18382 /* ========================================================================= */
18383 /*---------------------------------------------------------------------------*/
18384 /* SEND A SIGNAL TO THE SIGNAL LOG AND THEN CRASH THE SYSTEM. */
18385 /*---------------------------------------------------------------------------*/
18386  line = __LINE__;
18387  crash_msg = "Invalid logword";
18388  goto crash;
18389  break;
18390  }//switch
18391 /*---------------------------------------------------------------------------*/
18392 // We continue to execute log records until we find a proper one to execute or
18393 // that we reach a new page.
18394 /*---------------------------------------------------------------------------*/
18395  } while (1);
18396  return;
18397 
18398 crash:
18399  signal->theData[0] = RNIL;
18400  signal->theData[1] = logPartPtr.i;
18401  Uint32 tmp = logFilePtr.p->fileName[3];
18402  tmp = (tmp >> 8) & 0xff;// To get the Directory, DXX.
18403  signal->theData[2] = tmp;
18404  signal->theData[3] = logFilePtr.p->fileNo;
18405  signal->theData[4] = logFilePtr.p->currentMbyte;
18406  signal->theData[5] = logFilePtr.p->currentFilepage;
18407  signal->theData[6] = logPagePtr.p->logPageWord[ZCURR_PAGE_INDEX];
18408  signal->theData[7] = logWord;
18409  signal->theData[8] = line;
18410 
18411  char buf[255];
18412  BaseString::snprintf(buf, sizeof(buf),
18413  "Error while reading REDO log. from %d\n"
18414  "part: %u D=%d, F=%d Mb=%d FP=%d W1=%d W2=%d : %s gci: %u",
18415  signal->theData[8],
18416  logPartPtr.p->logPartNo,
18417  signal->theData[2],
18418  signal->theData[3],
18419  signal->theData[4],
18420  signal->theData[5],
18421  signal->theData[6],
18422  signal->theData[7],
18423  crash_msg ? crash_msg : "",
18424  logPartPtr.p->logLastGci);
18425 
18426  ndbout_c("%s", buf);
18427  ndbout_c("logPartPtr.p->logExecState: %u", logPartPtr.p->logExecState);
18428  ndbout_c("crestartOldestGci: %u", crestartOldestGci);
18429  ndbout_c("crestartNewestGci: %u", crestartNewestGci);
18430  ndbout_c("csrPhasesCompleted: %u", csrPhasesCompleted);
18431  ndbout_c("logPartPtr.p->logStartGci: %u", logPartPtr.p->logStartGci);
18432  ndbout_c("logPartPtr.p->logLastGci: %u", logPartPtr.p->logLastGci);
18433 
18434  progError(__LINE__, NDBD_EXIT_SR_REDOLOG, buf);
18435 }//Dblqh::execSr()
18436 
18437 /*---------------------------------------------------------------------------*/
18438 /* THIS SIGNAL IS ONLY RECEIVED TO BE CAPTURED IN THE SIGNAL LOG. IT IS */
18439 /* ALSO USED TO CRASH THE SYSTEM AFTER SENDING A SIGNAL TO THE LOG. */
18440 /*---------------------------------------------------------------------------*/
18441 void Dblqh::execDEBUG_SIG(Signal* signal)
18442 {
18443 /*
18444 2.5 TEMPORARY VARIABLES
18445 -----------------------
18446 */
18447  jamEntry();
18448  //logPagePtr.i = signal->theData[0];
18449  //tdebug = logPagePtr.p->logPageWord[0];
18450 
18451  char buf[100];
18452  BaseString::snprintf(buf, 100,
18453  "Error while reading REDO log. from %d\n"
18454  "D=%d, F=%d Mb=%d FP=%d W1=%d W2=%d",
18455  signal->theData[8],
18456  signal->theData[2], signal->theData[3], signal->theData[4],
18457  signal->theData[5], signal->theData[6], signal->theData[7]);
18458 
18459  progError(__LINE__, NDBD_EXIT_SR_REDOLOG, buf);
18460 
18461  return;
18462 }//Dblqh::execDEBUG_SIG()
18463 
18464 /*---------------------------------------------------------------------------*/
18465 /*---------------------------------------------------------------------------*/
18466 void Dblqh::closeExecLogLab(Signal* signal)
18467 {
18468  logFilePtr.p->logFileStatus = LogFileRecord::CLOSED;
18469  signal->theData[0] = ZEXEC_SR;
18470  signal->theData[1] = logFilePtr.p->logPartRec;
18471  sendSignal(cownref, GSN_CONTINUEB, signal, 2, JBB);
18472  return;
18473 }//Dblqh::closeExecLogLab()
18474 
18475 void Dblqh::openExecLogLab(Signal* signal)
18476 {
18477 #ifndef NO_REDO_PAGE_CACHE
18478  Uint32 cnt = 1 +
18479  logPartPtr.p->execSrStopPageNo - logPartPtr.p->execSrStartPageNo;
18480 
18481 #if 0
18482  Uint32 MAX_EXTRA_READ = 9; // can be max 9 due to FSREADREQ formatting
18483  while (cnt < maxextraread && (logPartPtr.p->execSrStopPageNo % 32) != 31)
18484  {
18485  jam();
18486  cnt++;
18487  logPartPtr.p->execSrStopPageNo++;
18488  }
18489 #endif
18490 
18491  evict(m_redo_page_cache, cnt);
18492 #endif
18493 
18494  readExecLog(signal);
18495  lfoPtr.p->lfoState = LogFileOperationRecord::READ_EXEC_LOG;
18496  return;
18497 }//Dblqh::openExecLogLab()
18498 
18499 void Dblqh::readExecLogLab(Signal* signal)
18500 {
18501  buildLinkedLogPageList(signal);
18502 #ifndef NO_REDO_PAGE_CACHE
18503  addCachePages(m_redo_page_cache,
18504  logPartPtr.p->logPartNo,
18505  logPartPtr.p->execSrStartPageNo,
18506  lfoPtr.p);
18507 #endif
18508  logPartPtr.p->logExecState = LogPartRecord::LES_EXEC_LOGREC_FROM_FILE;
18509  logPartPtr.p->execSrLfoRec = lfoPtr.i;
18510  logPartPtr.p->execSrLogPage = logPagePtr.i;
18511  logPagePtr.p->logPageWord[ZCURR_PAGE_INDEX] =
18512  logPartPtr.p->execSrLogPageIndex;
18513  execLogRecord(signal);
18514  return;
18515 }//Dblqh::readExecLogLab()
18516 
18517 /*---------------------------------------------------------------------------*/
18518 /* THIS CODE IS USED TO EXECUTE A LOG RECORD WHEN IT'S DATA HAVE BEEN LOCATED*/
18519 /* AND TRANSFERRED INTO MEMORY. */
18520 /*---------------------------------------------------------------------------*/
18521 void Dblqh::execLogRecord(Signal* signal)
18522 {
18523  jamEntry();
18524 
18525  tcConnectptr.i = logPartPtr.p->logTcConrec;
18526  ptrCheckGuard(tcConnectptr, ctcConnectrecFileSize, tcConnectionrec);
18527  fragptr.i = tcConnectptr.p->fragmentptr;
18528  c_fragment_pool.getPtr(fragptr);
18529  tcConnectptr.p->m_log_part_ptr_i = fragptr.p->m_log_part_ptr_i;
18530 
18531  // Read a log record and prepare it for execution
18532  readLogHeader(signal);
18533  readKey(signal);
18534  readAttrinfo(signal);
18535  initReqinfoExecSr(signal);
18536  arrGuard(logPartPtr.p->execSrExecuteIndex, MAX_REPLICAS);
18537  BlockReference ref = fragptr.p->execSrBlockref[logPartPtr.p->execSrExecuteIndex];
18538  tcConnectptr.p->nextReplica = refToNode(ref);
18539  tcConnectptr.p->connectState = TcConnectionrec::LOG_CONNECTED;
18540  tcConnectptr.p->tcOprec = tcConnectptr.i;
18541  tcConnectptr.p->tcHashKeyHi = 0;
18542  packLqhkeyreqLab(signal);
18543  return;
18544 }//Dblqh::execLogRecord()
18545 
18546 //----------------------------------------------------------------------------
18547 // This function invalidates log pages after the last GCI record in a
18548 // system/node restart. This is to ensure that the end of the log is
18549 // consistent. This function is executed last in start phase 3.
18550 // RT 450. EDTJAMO.
18551 //----------------------------------------------------------------------------
18552 Uint32
18553 Dblqh::nextLogFilePtr(Uint32 logFilePtrI)
18554 {
18555  LogFileRecordPtr tmp;
18556  tmp.i = logFilePtrI;
18557  ptrCheckGuard(tmp, clogFileFileSize, logFileRecord);
18558  return tmp.p->nextLogFile;
18559 }
18560 
18561 void
18562 Dblqh::invalidateLogAfterLastGCI(Signal* signal)
18563 {
18564  jam();
18565  if (logPartPtr.p->logExecState != LogPartRecord::LES_EXEC_LOG_INVALIDATE) {
18566  jam();
18567  systemError(signal, __LINE__);
18568  }
18569 
18570  if (logFilePtr.p->fileNo != logPartPtr.p->invalidateFileNo) {
18571  jam();
18572  systemError(signal, __LINE__);
18573  }
18574 
18575  switch (lfoPtr.p->lfoState) {
18576  case LogFileOperationRecord::READ_SR_INVALIDATE_SEARCH_FILES:
18577  {
18578  jam();
18579  // Check if this file contains pages needing to be invalidated
18580  ndbrequire(logPartPtr.p->invalidatePageNo == 1);
18581  bool ok = logPagePtr.p->logPageWord[ZPOS_LOG_LAP] == logPartPtr.p->logLap;
18582  releaseLfo(signal);
18583  releaseLogpage(signal);
18584  if (ok)
18585  {
18586  jam();
18587  // This page must be invalidated.
18588  // We search next file
18589  readFileInInvalidate(signal, 3);
18590  return;
18591  }
18592  else
18593  {
18594  jam();
18599  readFileInInvalidate(signal, 6);
18600  return;
18601  }
18602  break;
18603  }
18604  case LogFileOperationRecord::READ_SR_INVALIDATE_PAGES:
18605  jam();
18606  // Check if this page must be invalidated.
18607  // If the log lap number on a page after the head of the tail is the same
18608  // as the actual log lap number we must invalidate this page. Otherwise it
18609  // could be impossible to find the end of the log in a later system/node
18610  // restart.
18611  if (logPagePtr.p->logPageWord[ZPOS_LOG_LAP] == logPartPtr.p->logLap)
18612  {
18613  jam();
18614  // This page must be invalidated.
18615  // We search for end
18616  // read next
18617  releaseLfo(signal);
18618  releaseLogpage(signal);
18619  readFileInInvalidate(signal, 1);
18620  return;
18621  }
18622 
18628  // Fall through...
18629  case LogFileOperationRecord::WRITE_SR_INVALIDATE_PAGES:
18630  jam();
18631 
18632  releaseLfo(signal);
18633  releaseLogpage(signal);
18634 
18635  // Step backwards...
18636  logPartPtr.p->invalidatePageNo--;
18637 
18638  if (logPartPtr.p->invalidatePageNo == 0)
18639  {
18640  jam();
18641 
18642  if (logFilePtr.p->fileNo == 0)
18643  {
18644  jam();
18649  logPartPtr.p->logLap--;
18650  ndbrequire(logPartPtr.p->logLap); // Should always be > 0
18651  if (DEBUG_REDO)
18652  {
18653  ndbout_c("invalidateLogAfterLastGCI part: %u wrap from file 0 -> logLap: %u",
18654  logPartPtr.p->logPartNo, logPartPtr.p->logLap);
18655  }
18656  }
18657 
18658  if (invalidateCloseFile(signal, logPartPtr, logFilePtr,
18659  LogFileRecord::CLOSE_SR_WRITE_INVALIDATE_PAGES))
18660  {
18661  jam();
18662  return;
18663  }
18664  writeFileInInvalidate(signal, 1); // step prev
18665  return;
18666  }
18667  writeFileInInvalidate(signal, 0);
18668  return;
18669  default:
18670  jamLine(lfoPtr.p->lfoState);
18671  ndbrequire(false);
18672  }
18673 }
18674 
18675 void
18676 Dblqh::writeFileInInvalidate(Signal* signal, int stepPrev)
18677 {
18681  if (stepPrev == 1)
18682  {
18683  jam();
18684  logFilePtr.i = logFilePtr.p->prevLogFile;
18685  ptrCheckGuard(logFilePtr, clogFileFileSize, logFileRecord);
18686  logPartPtr.p->invalidateFileNo = logFilePtr.p->fileNo;
18687  logPartPtr.p->invalidatePageNo = clogFileSize * ZPAGES_IN_MBYTE - 1;
18688  }
18689 
18690  if (logPartPtr.p->invalidateFileNo == logPartPtr.p->headFileNo &&
18691  logPartPtr.p->invalidatePageNo == logPartPtr.p->headPageNo)
18692  {
18693  jam();
18697  logFilePtr.i = logPartPtr.p->currentLogfile;
18698  ptrCheckGuard(logFilePtr, clogFileFileSize, logFileRecord);
18699 
18700  logFilePtr.i = logFilePtr.p->nextLogFile;
18701  ptrCheckGuard(logFilePtr, clogFileFileSize, logFileRecord);
18702 
18703  exitFromInvalidate(signal);
18704  return;
18705  }
18706 
18707  if (stepPrev == 1 && logFilePtr.p->logFileStatus != LogFileRecord::OPEN)
18708  {
18709  jam();
18710  if (DEBUG_REDO)
18711  {
18712  ndbout_c("invalidate part: %u open for write %u",
18713  logPartPtr.p->logPartNo, logFilePtr.p->fileNo);
18714  }
18715  logFilePtr.p->logFileStatus =LogFileRecord::OPEN_SR_WRITE_INVALIDATE_PAGES;
18716  openFileRw(signal, logFilePtr);
18717  return;
18718  }
18719 
18720  seizeLogpage(signal);
18721 
18725  bzero(logPagePtr.p, sizeof(LogPageRecord));
18726  writeSinglePage(signal, logPartPtr.p->invalidatePageNo,
18727  ZPAGE_SIZE - 1, __LINE__);
18728 
18729  lfoPtr.p->lfoState = LogFileOperationRecord::WRITE_SR_INVALIDATE_PAGES;
18730  return;
18731 }//Dblqh::invalidateLogAfterLastGCI
18732 
18733 bool
18734 Dblqh::invalidateCloseFile(Signal* signal,
18735  Ptr<LogPartRecord> partPtr,
18736  Ptr<LogFileRecord> filePtr,
18737  LogFileRecord::LogFileStatus status)
18738 {
18739  jam();
18740  if (filePtr.p->fileNo != 0 &&
18741  filePtr.i != partPtr.p->currentLogfile &&
18742  filePtr.i != nextLogFilePtr(logPartPtr.p->currentLogfile))
18743  {
18744  jam();
18745  if (DEBUG_REDO)
18746  {
18747  ndbout_c("invalidate part: %u close %u(%u) state: %u (%u)",
18748  logPartPtr.p->logPartNo,
18749  logFilePtr.p->fileNo,
18750  logFilePtr.i,
18751  (Uint32)status,
18752  logPartPtr.p->currentLogfile);
18753  }
18754  filePtr.p->logFileStatus = status;
18755  closeFile(signal, filePtr, __LINE__);
18756  return true;
18757  }
18758  return false;
18759 }
18760 
18761 void Dblqh::readFileInInvalidate(Signal* signal, int stepNext)
18762 {
18763  jam();
18764 
18765  if (DEBUG_REDO)
18766  {
18767  ndbout_c("readFileInInvalidate part: %u file: %u stepNext: %u",
18768  logPartPtr.p->logPartNo, logFilePtr.p->fileNo, stepNext);
18769  }
18770 
18771  if (stepNext == 0)
18772  {
18773  jam();
18774  // Contact NDBFS. Real time break.
18775  readSinglePage(signal, logPartPtr.p->invalidatePageNo);
18776  lfoPtr.p->lfoState = LogFileOperationRecord::READ_SR_INVALIDATE_PAGES;
18777  return;
18778  }
18779 
18780  if (stepNext == 1)
18781  {
18782  jam();
18783  logPartPtr.p->invalidatePageNo++;
18784  if (logPartPtr.p->invalidatePageNo == (clogFileSize * ZPAGES_IN_MBYTE))
18785  {
18786  if (invalidateCloseFile(signal, logPartPtr, logFilePtr,
18787  LogFileRecord::CLOSE_SR_READ_INVALIDATE_PAGES))
18788  {
18789  jam();
18790  return;
18791  }
18792  else
18793  {
18794  jam();
18795  stepNext = 2; // After close
18796  }
18797  }
18798  else
18799  {
18800  jam();
18801  // Contact NDBFS. Real time break.
18802  readSinglePage(signal, logPartPtr.p->invalidatePageNo);
18803  lfoPtr.p->lfoState = LogFileOperationRecord::READ_SR_INVALIDATE_PAGES;
18804  return;
18805  }
18806  }
18807 
18808  if (stepNext == 2)
18809  {
18810  jam();
18811  // We continue in the next file.
18812  logFilePtr.i = logFilePtr.p->nextLogFile;
18813  ptrCheckGuard(logFilePtr, clogFileFileSize, logFileRecord);
18814  logPartPtr.p->invalidateFileNo = logFilePtr.p->fileNo;
18815  // Page 0 is used for file descriptors.
18816  logPartPtr.p->invalidatePageNo = 1;
18817 
18818  if (logFilePtr.p->fileNo == 0)
18819  {
18824  logPartPtr.p->logLap++;
18825  if (DEBUG_REDO)
18826  {
18827  ndbout_c("readFileInInvalidate part: %u step: %u wrap to file 0 -> logLap: %u",
18828  logPartPtr.p->logPartNo, stepNext, logPartPtr.p->logLap);
18829  }
18830  }
18831 
18832 stepNext_2:
18833  if (logFilePtr.p->logFileStatus != LogFileRecord::OPEN)
18834  {
18835  jam();
18836  if (DEBUG_REDO)
18837  {
18838  ndbout_c("invalidate part: %u step: %u open for read %u",
18839  logPartPtr.p->logPartNo, stepNext, logFilePtr.p->fileNo);
18840  }
18841  logFilePtr.p->logFileStatus =LogFileRecord::OPEN_SR_READ_INVALIDATE_PAGES;
18842  openFileRw(signal, logFilePtr);
18843  return;
18844  }
18845 
18846  // Contact NDBFS. Real time break.
18847  readSinglePage(signal, logPartPtr.p->invalidatePageNo);
18848  lfoPtr.p->lfoState = LogFileOperationRecord::READ_SR_INVALIDATE_PAGES;
18849  return;
18850  }
18851 
18852  if (stepNext == 3)
18853  {
18854  jam();
18855  if (invalidateCloseFile
18856  (signal, logPartPtr, logFilePtr,
18857  LogFileRecord::CLOSE_SR_READ_INVALIDATE_SEARCH_FILES))
18858  {
18859  jam();
18860  return;
18861  }
18862  stepNext = 4;
18863  }
18864 
18865  if (stepNext == 4)
18866  {
18867  jam();
18868  logFilePtr.i = logFilePtr.p->nextLogFile;
18869  ptrCheckGuard(logFilePtr, clogFileFileSize, logFileRecord);
18870  logPartPtr.p->invalidateFileNo = logFilePtr.p->fileNo;
18871  // Page 0 is used for file descriptors.
18872  logPartPtr.p->invalidatePageNo = 1;
18873 
18874  if (logFilePtr.p->fileNo == 0)
18875  {
18880  logPartPtr.p->logLap++;
18881  if (DEBUG_REDO)
18882  {
18883  ndbout_c("readFileInInvalidate part: %u step: %u wrap to file 0 -> logLap: %u",
18884  logPartPtr.p->logPartNo, stepNext, logPartPtr.p->logLap);
18885  }
18886  }
18887 
18888  if (logFilePtr.p->logFileStatus != LogFileRecord::OPEN)
18889  {
18890  jam();
18891  if (DEBUG_REDO)
18892  {
18893  ndbout_c("invalidate part: %u step: %u open for read %u",
18894  logPartPtr.p->logPartNo, stepNext, logFilePtr.p->fileNo);
18895  }
18896  logFilePtr.p->logFileStatus =
18897  LogFileRecord::OPEN_SR_READ_INVALIDATE_SEARCH_FILES;
18898  openFileRw(signal, logFilePtr);
18899  return;
18900  }
18901  stepNext = 5;
18902  }
18903 
18904  if (stepNext == 5)
18905  {
18906  jam();
18907  // Contact NDBFS. Real time break.
18908  readSinglePage(signal, logPartPtr.p->invalidatePageNo);
18909  lfoPtr.p->lfoState =
18910  LogFileOperationRecord::READ_SR_INVALIDATE_SEARCH_FILES;
18911  return;
18912  }
18913 
18914  if (stepNext == 6)
18915  {
18916  jam();
18917  if (invalidateCloseFile
18918  (signal, logPartPtr, logFilePtr,
18919  LogFileRecord::CLOSE_SR_READ_INVALIDATE_SEARCH_LAST_FILE))
18920  {
18921  jam();
18922  return;
18923  }
18924  stepNext = 7;
18925  }
18926 
18927  if (stepNext == 7)
18928  {
18929  jam();
18930 
18931  if (logFilePtr.p->fileNo == 0)
18932  {
18933  jam();
18938  logPartPtr.p->logLap--;
18939  ndbrequire(logPartPtr.p->logLap); // Should always be > 0
18940  if (DEBUG_REDO)
18941  {
18942  ndbout_c("invalidateLogAfterLastGCI part: %u step: %u wrap from file 0 -> logLap: %u",
18943  logPartPtr.p->logPartNo, stepNext, logPartPtr.p->logLap);
18944  }
18945  }
18946 
18947  logFilePtr.i = logFilePtr.p->prevLogFile;
18948  ptrCheckGuard(logFilePtr, clogFileFileSize, logFileRecord);
18949 
18950  logPartPtr.p->invalidateFileNo = logFilePtr.p->fileNo;
18951  // Page 0 is used for file descriptors.
18952  logPartPtr.p->invalidatePageNo = 1;
18953 
18954  if (logPartPtr.p->invalidateFileNo == logPartPtr.p->headFileNo)
18955  {
18956  jam();
18957  logPartPtr.p->invalidatePageNo = logPartPtr.p->headPageNo;
18958 
18959  if (! ((cstartType == NodeState::ST_INITIAL_START) ||
18960  (cstartType == NodeState::ST_INITIAL_NODE_RESTART)))
18961  {
18962  jam();
18963  if (logFilePtr.i == logPartPtr.p->lastLogfile)
18964  {
18965  jam();
18966  Uint32 lastMbytePageNo =
18967  logPartPtr.p->lastMbyte << ZTWOLOG_NO_PAGES_IN_MBYTE;
18968  if (logPartPtr.p->invalidatePageNo < lastMbytePageNo)
18969  {
18970  jam();
18971  if (DEBUG_REDO)
18972  {
18973  ndbout_c("readFileInInvalidate part: %u step: %u moving invalidatePageNo from %u to %u (lastMbyte)",
18974  logPartPtr.p->logPartNo, stepNext,
18975  logPartPtr.p->invalidatePageNo,
18976  lastMbytePageNo);
18977  }
18978  logPartPtr.p->invalidatePageNo = lastMbytePageNo;
18979  }
18980  }
18981  }
18982  readFileInInvalidate(signal, 1);
18983  return;
18984  }
18985 
18986  goto stepNext_2;
18987  }
18988  ndbrequire(false);
18989 }
18990 
18991 void Dblqh::exitFromInvalidate(Signal* signal)
18992 {
18993  jam();
18994 
18995  if (DEBUG_REDO)
18996  {
18997  jam();
18998  printf("exitFromInvalidate part: %u head file: %u page: %u open: ",
18999  logPartPtr.p->logPartNo,
19000  logPartPtr.p->headFileNo,
19001  logPartPtr.p->headPageNo);
19002 
19003  LogFileRecordPtr tmp;
19004  tmp.i = logPartPtr.p->currentLogfile;
19005  do
19006  {
19007  jam();
19008  ptrCheckGuard(tmp, clogFileFileSize, logFileRecord);
19009  if (tmp.p->logFileStatus != LogFileRecord::LFS_IDLE &&
19010  tmp.p->logFileStatus != LogFileRecord::CLOSED)
19011  {
19012  jam();
19013  printf("%u ", tmp.p->fileNo);
19014  }
19015  tmp.i = tmp.p->nextLogFile;
19016  } while (tmp.i != logPartPtr.p->currentLogfile && tmp.i != RNIL);
19017  printf("\n");
19018 
19019  tmp.i = logPartPtr.p->currentLogfile;
19020  ptrCheckGuard(tmp, clogFileFileSize, logFileRecord);
19021 
19022  LogPosition head = { tmp.p->fileNo, tmp.p->currentMbyte };
19023  LogPosition tail = { logPartPtr.p->logTailFileNo,
19024  logPartPtr.p->logTailMbyte};
19025  Uint64 mb = free_log(head, tail, logPartPtr.p->noLogFiles, clogFileSize);
19026  Uint64 total = logPartPtr.p->noLogFiles * Uint64(clogFileSize);
19027  ndbout_c("head: [ %u %u ] tail: [ %u %u ] free: %llu total: %llu",
19028  head.m_file_no, head.m_mbyte,
19029  tail.m_file_no, tail.m_mbyte,
19030  mb, total);
19031  }
19032 
19033  logFilePtr.i = logPartPtr.p->firstLogfile;
19034  ptrCheckGuard(logFilePtr, clogFileFileSize, logFileRecord);
19035  logPagePtr.i = logFilePtr.p->logPageZero;
19036  ptrCheckGuard(logPagePtr, clogPageFileSize, logPageRecord);
19037  logPagePtr.p->logPageWord[ZPAGE_HEADER_SIZE + ZPOS_FILE_NO] =
19038  logPartPtr.p->headFileNo;
19039  writeSinglePage(signal, 0, ZPAGE_SIZE - 1, __LINE__);
19040 
19041  lfoPtr.p->logFileRec = logFilePtr.i;
19042  lfoPtr.p->lfoState = LogFileOperationRecord::WRITE_SR_INVALIDATE_PAGES_UPDATE_PAGE0;
19043  return;
19044 }
19045 
19046 /*---------------------------------------------------------------------------*/
19047 /* THE EXECUTION OF A LOG RECORD IS COMPLETED. RELEASE PAGES IF THEY WERE */
19048 /* READ FROM DISK FOR THIS PARTICULAR OPERATION. */
19049 /*---------------------------------------------------------------------------*/
19050 void Dblqh::completedLab(Signal* signal)
19051 {
19052  Uint32 result = returnExecLog(signal);
19053 /*---------------------------------------------------------------------------*/
19054 /* ENTER COMPLETED WITH */
19055 /* LQH_CONNECTPTR */
19056 /*---------------------------------------------------------------------------*/
19057  if (result == ZOK) {
19058  jam();
19059  execLogRecord(signal);
19060  return;
19061  } else if (result == ZNOT_OK) {
19062  jam();
19063  signal->theData[0] = ZEXEC_SR;
19064  signal->theData[1] = logPartPtr.i;
19065  sendSignal(cownref, GSN_CONTINUEB, signal, 2, JBB);
19066  } else {
19067  jam();
19068  /*empty*/;
19069  }//if
19070 /*---------------------------------------------------------------------------*/
19071 /* WE HAVE TO WAIT FOR CLOSING OF THE EXECUTED LOG FILE BEFORE PROCEEDING IN */
19072 /* RARE CASES. */
19073 /*---------------------------------------------------------------------------*/
19074  return;
19075 }//Dblqh::completedLab()
19076 
19077 /*---------------------------------------------------------------------------*/
19078 /* EXECUTION OF LOG RECORD WAS NOT SUCCESSFUL. CHECK IF IT IS OK ANYWAY, */
19079 /* THEN EXECUTE THE NEXT LOG RECORD. */
19080 /*---------------------------------------------------------------------------*/
19081 void Dblqh::logLqhkeyrefLab(Signal* signal)
19082 {
19083  Uint32 result = returnExecLog(signal);
19084  switch (tcConnectptr.p->operation) {
19085  case ZUPDATE:
19086  case ZDELETE:
19087  jam();
19088  if (unlikely(terrorCode != ZNO_TUPLE_FOUND))
19089  goto error;
19090  break;
19091  case ZINSERT:
19092  jam();
19093  if (unlikely(terrorCode != ZTUPLE_ALREADY_EXIST && terrorCode != 899))
19094  goto error;
19095 
19096  break;
19097  default:
19098  goto error;
19099  }
19100 
19101  if (result == ZOK) {
19102  jam();
19103  execLogRecord(signal);
19104  return;
19105  } else if (result == ZNOT_OK) {
19106  jam();
19107  signal->theData[0] = ZEXEC_SR;
19108  signal->theData[1] = logPartPtr.i;
19109  sendSignal(cownref, GSN_CONTINUEB, signal, 2, JBB);
19110  } else {
19111  jam();
19112  /*empty*/;
19113  }//if
19114  /* ------------------------------------------------------------------------
19115  * WE HAVE TO WAIT FOR CLOSING OF THE EXECUTED LOG FILE BEFORE
19116  * PROCEEDING IN RARE CASES.
19117  * ----------------------------------------------------------------------- */
19118  return;
19119 error:
19120  BaseString tmp;
19121  tmp.appfmt("You have found a bug!"
19122  " Failed op (%s) during REDO table: %d fragment: %d err: %d",
19123  tcConnectptr.p->operation == ZINSERT ? "INSERT" :
19124  tcConnectptr.p->operation == ZUPDATE ? "UPDATE" :
19125  tcConnectptr.p->operation == ZDELETE ? "DELETE" :
19126  tcConnectptr.p->operation == ZWRITE ? "WRITE" : "<unknown>",
19127  tcConnectptr.p->tableref,
19128  tcConnectptr.p->fragmentid,
19129  terrorCode);
19130  progError(__LINE__, NDBD_EXIT_SYSTEM_ERROR,
19131  tmp.c_str());
19132 }//Dblqh::logLqhkeyrefLab()
19133 
19134 void Dblqh::closeExecSrCompletedLab(Signal* signal)
19135 {
19136  logFilePtr.p->logFileStatus = LogFileRecord::CLOSED;
19137  signal->theData[0] = logFilePtr.p->logPartRec;
19138  execLogComp(signal);
19139  return;
19140 }//Dblqh::closeExecSrCompletedLab()
19141 
19142 /* --------------------------------------------------------------------------
19143  * ONE OF THE LOG PARTS HAVE COMPLETED EXECUTING THE LOG. CHECK IF ALL LOG
19144  * PARTS ARE COMPLETED. IF SO START SENDING EXEC_FRAGCONF AND EXEC_SRCONF.
19145  * ------------------------------------------------------------------------- */
19146 void Dblqh::execLogComp(Signal* signal)
19147 {
19148  logPartPtr.i = signal->theData[0];
19149  ptrCheckGuard(logPartPtr, clogPartFileSize, logPartRecord);
19150  logPartPtr.p->logPartState = LogPartRecord::SR_THIRD_PHASE_COMPLETED;
19151  /* ------------------------------------------------------------------------
19152  * WE MUST RELEASE THE TC CONNECT RECORD HERE SO THAT IT CAN BE REUSED.
19153  * ----------------------------------------------------------------------- */
19154  tcConnectptr.i = logPartPtr.p->logTcConrec;
19155  ptrCheckGuard(tcConnectptr, ctcConnectrecFileSize, tcConnectionrec);
19156  logPartPtr.p->logTcConrec = RNIL;
19157  releaseTcrecLog(signal, tcConnectptr);
19158  for (logPartPtr.i = 0; logPartPtr.i < clogPartFileSize; logPartPtr.i++) {
19159  jam();
19160  ptrAss(logPartPtr, logPartRecord);
19161  if (logPartPtr.p->logPartState != LogPartRecord::SR_THIRD_PHASE_COMPLETED) {
19162  if (logPartPtr.p->logPartState != LogPartRecord::SR_THIRD_PHASE_STARTED) {
19163  jam();
19164  systemErrorLab(signal, __LINE__);
19165  return;
19166  } else {
19167  jam();
19168  /* ------------------------------------------------------------------
19169  * THIS LOG PART WAS NOT COMPLETED YET. EXIT AND WAIT FOR IT
19170  * TO COMPLETE
19171  * ----------------------------------------------------------------- */
19172  return;
19173  }//if
19174  }//if
19175  }//for
19176  /* ------------------------------------------------------------------------
19177  * ALL LOG PARTS HAVE COMPLETED THE EXECUTION OF THE LOG. WE CAN NOW START
19178  * SENDING THE EXEC_FRAGCONF SIGNALS TO ALL INVOLVED FRAGMENTS.
19179  * ----------------------------------------------------------------------- */
19180  jam();
19181 
19182 #ifndef NO_REDO_PAGE_CACHE
19183  release(m_redo_page_cache);
19184 #endif
19185 
19186 #ifndef NO_REDO_OPEN_FILE_CACHE
19187  release(signal, m_redo_open_file_cache);
19188 #else
19189  execLogComp_extra_files_closed(signal);
19190 #endif
19191 }
19192 
19193 void
19194 Dblqh::execLogComp_extra_files_closed(Signal * signal)
19195 {
19196  c_lcp_complete_fragments.first(fragptr);
19197  signal->theData[0] = ZSEND_EXEC_CONF;
19198  signal->theData[1] = fragptr.i;
19199  sendSignal(cownref, GSN_CONTINUEB, signal, 2, JBB);
19200  return;
19201 }
19202 
19203 /* --------------------------------------------------------------------------
19204  * GO THROUGH THE FRAGMENT RECORDS TO DEDUCE TO WHICH SHALL BE SENT
19205  * EXEC_FRAGCONF AFTER COMPLETING THE EXECUTION OF THE LOG.
19206  * ------------------------------------------------------------------------- */
19207 void Dblqh::sendExecConf(Signal* signal)
19208 {
19209  jamEntry();
19210  fragptr.i = signal->theData[0];
19211  Uint32 loopCount = 0;
19212  while (fragptr.i != RNIL) {
19213  c_lcp_complete_fragments.getPtr(fragptr);
19214  Uint32 next = fragptr.p->nextList;
19215  if (fragptr.p->execSrStatus != Fragrecord::IDLE) {
19216  jam();
19217  ndbrequire(fragptr.p->execSrNoReplicas - 1 < MAX_REPLICAS);
19218  for (Uint32 i = 0; i < fragptr.p->execSrNoReplicas; i++) {
19219  jam();
19220  Uint32 ref = fragptr.p->execSrBlockref[i];
19221  signal->theData[0] = fragptr.p->execSrUserptr[i];
19222 
19223  if (isNdbMtLqh())
19224  {
19225  jam();
19226  // send via own proxy
19227  signal->theData[1] = ref;
19228  sendSignal(DBLQH_REF, GSN_EXEC_FRAGCONF, signal, 2, JBB);
19229  }
19230  else if (refToInstance(ref) != 0 &&
19231  ndb_route_exec_frag(getNodeInfo(refToNode(ref)).m_version))
19232  {
19233  jam();
19234  // send via remote proxy
19235  signal->theData[1] = ref;
19236  sendSignal(numberToRef(refToMain(ref), refToNode(ref)),
19237  GSN_EXEC_FRAGCONF, signal, 2, JBB);
19238  }
19239  else
19240  {
19241  jam();
19242  // send direct
19243  sendSignal(ref, GSN_EXEC_FRAGCONF, signal, 1, JBB);
19244  }
19245  }//for
19246  fragptr.p->execSrNoReplicas = 0;
19247  }//if
19248  loopCount++;
19249  if (loopCount > 20) {
19250  jam();
19251  signal->theData[0] = ZSEND_EXEC_CONF;
19252  signal->theData[1] = next;
19253  sendSignal(cownref, GSN_CONTINUEB, signal, 2, JBB);
19254  return;
19255  } else {
19256  jam();
19257  fragptr.i = next;
19258  }//if
19259  }//while
19260  /* ----------------------------------------------------------------------
19261  * WE HAVE NOW SENT ALL EXEC_FRAGCONF. NOW IT IS TIME TO SEND
19262  * EXEC_SRCONF TO ALL NODES.
19263  * --------------------------------------------------------------------- */
19264  srPhase3Comp(signal);
19265 }//Dblqh::sendExecConf()
19266 
19267 /* --------------------------------------------------------------------------
19268  * PHASE 3 HAS NOW COMPLETED. INFORM ALL OTHER NODES OF THIS EVENT.
19269  * ------------------------------------------------------------------------- */
19270 void Dblqh::srPhase3Comp(Signal* signal)
19271 {
19272  jamEntry();
19273 
19274  signal->theData[0] = cownNodeid;
19275  if (!isNdbMtLqh())
19276  {
19277  jam();
19278  NodeReceiverGroup rg(DBLQH, m_sr_nodes);
19279  sendSignal(rg, GSN_EXEC_SRCONF, signal, 1, JBB);
19280  }
19281  else
19282  {
19283  jam();
19284  const Uint32 sz = NdbNodeBitmask::Size;
19285  m_sr_nodes.copyto(sz, &signal->theData[1]);
19286  sendSignal(DBLQH_REF, GSN_EXEC_SRCONF, signal, 1 + sz, JBB);
19287  }
19288  return;
19289 }//Dblqh::srPhase3Comp()
19290 
19291 /* ##########################################################################
19292  * SYSTEM RESTART PHASE FOUR MODULE
19293  * THIS MODULE IS A SUB-MODULE OF THE FILE SYSTEM HANDLING.
19294  *
19295  * THIS MODULE SETS UP THE HEAD AND TAIL POINTERS OF THE LOG PARTS IN THE
19296  * FRAGMENT LOG. WHEN IT IS COMPLETED IT REPORTS TO THE MASTER DIH THAT
19297  * IT HAS COMPLETED THE PART OF THE SYSTEM RESTART WHERE THE DATABASE IS
19298  * LOADED.
19299  * IT ALSO OPENS THE CURRENT LOG FILE AND THE NEXT AND SETS UP THE FIRST
19300  * LOG PAGE WHERE NEW LOG DATA IS TO BE INSERTED WHEN THE SYSTEM STARTS
19301  * AGAIN.
19302  *
19303  * THIS PART IS ACTUALLY EXECUTED FOR ALL RESTART TYPES.
19304  * ######################################################################### */
19305 void Dblqh::initFourth(Signal* signal)
19306 {
19307  LogFileRecordPtr locLogFilePtr;
19308  jamEntry();
19309  logPartPtr.i = signal->theData[0];
19310  ptrCheckGuard(logPartPtr, clogPartFileSize, logPartRecord);
19311  crestartNewestGci = 1;
19312  crestartOldestGci = 1;
19313  /* ------------------------------------------------------------------------
19314  * INITIALISE LOG PART AND LOG FILES AS NEEDED.
19315  * ----------------------------------------------------------------------- */
19316  logPartPtr.p->headFileNo = 0;
19317  logPartPtr.p->headPageNo = 1;
19318  logPartPtr.p->headPageIndex = ZPAGE_HEADER_SIZE + 2;
19320  logPartPtr.p->logTailFileNo = 0;
19321  logPartPtr.p->logTailMbyte = 0;
19322  locLogFilePtr.i = logPartPtr.p->firstLogfile;
19323  ptrCheckGuard(locLogFilePtr, clogFileFileSize, logFileRecord);
19324  locLogFilePtr.p->logFileStatus = LogFileRecord::OPEN_SR_FOURTH_PHASE;
19325  openFileRw(signal, locLogFilePtr);
19326  return;
19327 }//Dblqh::initFourth()
19328 
19329 void Dblqh::openSrFourthPhaseLab(Signal* signal)
19330 {
19331  /* ------------------------------------------------------------------------
19332  * WE HAVE NOW OPENED THE HEAD LOG FILE WE WILL NOW START READING IT
19333  * FROM THE HEAD MBYTE TO FIND THE NEW HEAD OF THE LOG.
19334  * ----------------------------------------------------------------------- */
19335  readSinglePage(signal, logPartPtr.p->headPageNo);
19336  lfoPtr.p->lfoState = LogFileOperationRecord::READ_SR_FOURTH_PHASE;
19337  return;
19338 }//Dblqh::openSrFourthPhaseLab()
19339 
19340 void Dblqh::readSrFourthPhaseLab(Signal* signal)
19341 {
19342  if(c_diskless){
19343  jam();
19344  logPagePtr.p->logPageWord[ZPOS_LOG_LAP] = 1;
19345  }
19346 
19347  /* ------------------------------------------------------------------------
19348  * INITIALISE ALL LOG PART INFO AND LOG FILE INFO THAT IS NEEDED TO
19349  * START UP THE SYSTEM.
19350  * ------------------------------------------------------------------------
19351  * INITIALISE THE NEWEST GLOBAL CHECKPOINT IDENTITY AND THE NEWEST
19352  * COMPLETED GLOBAL CHECKPOINT IDENITY AS THE NEWEST THAT WAS RESTARTED.
19353  * ------------------------------------------------------------------------
19354  * INITIALISE THE HEAD PAGE INDEX IN THIS PAGE.
19355  * ASSIGN IT AS THE CURRENT LOGPAGE.
19356  * ASSIGN THE FILE AS THE CURRENT LOG FILE.
19357  * ASSIGN THE CURRENT FILE NUMBER FROM THE CURRENT LOG FILE AND THE NEXT
19358  * FILE NUMBER FROM THE NEXT LOG FILE.
19359  * ASSIGN THE CURRENT FILEPAGE FROM HEAD PAGE NUMBER.
19360  * ASSIGN THE CURRENT MBYTE BY DIVIDING PAGE NUMBER BY 128.
19361  * INITIALISE LOG LAP TO BE THE LOG LAP AS FOUND IN THE HEAD PAGE.
19362  * WE HAVE TO CALCULATE THE NUMBER OF REMAINING WORDS IN THIS MBYTE.
19363  * ----------------------------------------------------------------------- */
19364  Uint32 gci = crestartNewestGci;
19365  if (crestartOldestGci > gci)
19366  {
19367  jam();
19372  ndbout_c("readSrFourthPhaseLab: gci %u => %u",
19373  gci, crestartOldestGci);
19374  gci = crestartOldestGci;
19375  }
19376  cnewestGci = gci;
19377  cnewestCompletedGci = gci;
19378  logPartPtr.p->logPartNewestCompletedGCI = cnewestCompletedGci;
19379  logPartPtr.p->currentLogfile = logFilePtr.i;
19380  logFilePtr.p->filePosition = logPartPtr.p->headPageNo;
19381  logFilePtr.p->currentMbyte =
19382  logPartPtr.p->headPageNo >> ZTWOLOG_NO_PAGES_IN_MBYTE;
19383  logFilePtr.p->fileChangeState = LogFileRecord::NOT_ONGOING;
19384  logPartPtr.p->logLap = logPagePtr.p->logPageWord[ZPOS_LOG_LAP];
19385  logFilePtr.p->currentFilepage = logPartPtr.p->headPageNo;
19386  logFilePtr.p->currentLogpage = logPagePtr.i;
19387 
19388  initLogpage(signal);
19389  logPagePtr.p->logPageWord[ZCURR_PAGE_INDEX] = logPartPtr.p->headPageIndex;
19390  logFilePtr.p->remainingWordsInMbyte =
19391  ((
19392  ((logFilePtr.p->currentMbyte + 1) * ZPAGES_IN_MBYTE) -
19393  logFilePtr.p->currentFilepage) *
19394  (ZPAGE_SIZE - ZPAGE_HEADER_SIZE)) -
19395  (logPartPtr.p->headPageIndex - ZPAGE_HEADER_SIZE);
19396  /* ------------------------------------------------------------------------
19397  * THE NEXT STEP IS TO OPEN THE NEXT LOG FILE (IF THERE IS ONE).
19398  * ----------------------------------------------------------------------- */
19399  if (logFilePtr.p->nextLogFile != logFilePtr.i) {
19400  LogFileRecordPtr locLogFilePtr;
19401  jam();
19402  locLogFilePtr.i = logFilePtr.p->nextLogFile;
19403  ptrCheckGuard(locLogFilePtr, clogFileFileSize, logFileRecord);
19404  locLogFilePtr.p->logFileStatus = LogFileRecord::OPEN_SR_FOURTH_NEXT;
19405  openFileRw(signal, locLogFilePtr);
19406  } else {
19407  jam();
19408  /* ----------------------------------------------------------------------
19409  * THIS CAN ONLY OCCUR IF WE HAVE ONLY ONE LOG FILE. THIS LOG FILE MUST
19410  * BE LOG FILE ZERO AND THAT IS THE FILE WE CURRENTLY HAVE READ.
19411  * THUS WE CAN CONTINUE IMMEDIATELY TO READ PAGE ZERO IN FILE ZERO.
19412  * --------------------------------------------------------------------- */
19413  openSrFourthZeroSkipInitLab(signal);
19414  return;
19415  }//if
19416  return;
19417 }//Dblqh::readSrFourthPhaseLab()
19418 
19419 void Dblqh::openSrFourthNextLab(Signal* signal)
19420 {
19421  /* ------------------------------------------------------------------------
19422  * WE MUST ALSO HAVE FILE 0 OPEN ALL THE TIME.
19423  * ----------------------------------------------------------------------- */
19424  logFilePtr.i = logPartPtr.p->firstLogfile;
19425  ptrCheckGuard(logFilePtr, clogFileFileSize, logFileRecord);
19426  if (logFilePtr.p->logFileStatus == LogFileRecord::OPEN) {
19427  jam();
19428  openSrFourthZeroSkipInitLab(signal);
19429  return;
19430  } else {
19431  jam();
19432  logFilePtr.p->logFileStatus = LogFileRecord::OPEN_SR_FOURTH_ZERO;
19433  openFileRw(signal, logFilePtr);
19434  }//if
19435  return;
19436 }//Dblqh::openSrFourthNextLab()
19437 
19438 void Dblqh::openSrFourthZeroLab(Signal* signal)
19439 {
19440  openSrFourthZeroSkipInitLab(signal);
19441  return;
19442 }//Dblqh::openSrFourthZeroLab()
19443 
19444 void Dblqh::openSrFourthZeroSkipInitLab(Signal* signal)
19445 {
19446  if (logFilePtr.i == logPartPtr.p->currentLogfile) {
19447  if (logFilePtr.p->currentFilepage == 0) {
19448  jam();
19449  /* -------------------------------------------------------------------
19450  * THE HEADER PAGE IN THE LOG IS PAGE ZERO IN FILE ZERO.
19451  * THIS SHOULD NEVER OCCUR.
19452  * ------------------------------------------------------------------- */
19453  systemErrorLab(signal, __LINE__);
19454  return;
19455  }//if
19456  }//if
19457  readSinglePage(signal, 0);
19458  lfoPtr.p->lfoState = LogFileOperationRecord::READ_SR_FOURTH_ZERO;
19459  return;
19460 }//Dblqh::openSrFourthZeroSkipInitLab()
19461 
19462 void Dblqh::readSrFourthZeroLab(Signal* signal)
19463 {
19464  logFilePtr.p->logPageZero = logPagePtr.i;
19465  // --------------------------------------------------------------------
19466  // This is moved to invalidateLogAfterLastGCI(), RT453.
19467  // signal->theData[0] = ZSR_FOURTH_COMP;
19468  // signal->theData[1] = logPartPtr.i;
19469  // sendSignal(cownref, GSN_CONTINUEB, signal, 2, JBB);
19470  // --------------------------------------------------------------------
19471 
19472  // Need to invalidate log pages after the head of the log. RT 453. EDTJAMO.
19473  // Set the start of the invalidation.
19474  logFilePtr.i = logPartPtr.p->currentLogfile;
19475  ptrCheckGuard(logFilePtr, clogFileFileSize, logFileRecord);
19476  logPartPtr.p->invalidateFileNo = logPartPtr.p->headFileNo;
19477  logPartPtr.p->invalidatePageNo = logPartPtr.p->headPageNo;
19478  logPartPtr.p->logExecState = LogPartRecord::LES_EXEC_LOG_INVALIDATE;
19479 
19480  readFileInInvalidate(signal, 3);
19481  return;
19482 }//Dblqh::readSrFourthZeroLab()
19483 
19484 /* --------------------------------------------------------------------------
19485  * ONE OF THE LOG PARTS HAVE COMPLETED PHASE FOUR OF THE SYSTEM RESTART.
19486  * CHECK IF ALL LOG PARTS ARE COMPLETED. IF SO SEND START_RECCONF
19487  * ------------------------------------------------------------------------- */
19488 void Dblqh::srFourthComp(Signal* signal)
19489 {
19490  jamEntry();
19491  logPartPtr.i = signal->theData[0];
19492  ptrCheckGuard(logPartPtr, clogPartFileSize, logPartRecord);
19493  logPartPtr.p->logPartState = LogPartRecord::SR_FOURTH_PHASE_COMPLETED;
19494  for (logPartPtr.i = 0; logPartPtr.i < clogPartFileSize; logPartPtr.i++) {
19495  jam();
19496  ptrAss(logPartPtr, logPartRecord);
19497  if (logPartPtr.p->logPartState != LogPartRecord::SR_FOURTH_PHASE_COMPLETED) {
19499  jam();
19500  systemErrorLab(signal, __LINE__);
19501  return;
19502  } else {
19503  jam();
19504  /* ------------------------------------------------------------------
19505  * THIS LOG PART WAS NOT COMPLETED YET.
19506  * EXIT AND WAIT FOR IT TO COMPLETE
19507  * ----------------------------------------------------------------- */
19508  return;
19509  }//if
19510  }//if
19511  }//for
19512  /* ------------------------------------------------------------------------
19513  * ALL LOG PARTS HAVE COMPLETED PHASE FOUR OF THE SYSTEM RESTART.
19514  * WE CAN NOW SEND START_RECCONF TO THE MASTER DIH IF IT WAS A
19515  * SYSTEM RESTART. OTHERWISE WE WILL CONTINUE WITH AN INITIAL START.
19516  * SET LOG PART STATE TO IDLE TO
19517  * INDICATE THAT NOTHING IS GOING ON IN THE LOG PART.
19518  * ----------------------------------------------------------------------- */
19519  for (logPartPtr.i = 0; logPartPtr.i < clogPartFileSize; logPartPtr.i++) {
19520  ptrAss(logPartPtr, logPartRecord);
19521  logPartPtr.p->logPartState = LogPartRecord::IDLE;
19522  }//for
19523 
19524  if ((cstartType == NodeState::ST_INITIAL_START) ||
19525  (cstartType == NodeState::ST_INITIAL_NODE_RESTART)) {
19526  jam();
19527 
19528  ndbrequire(cinitialStartOngoing == ZTRUE);
19529  cinitialStartOngoing = ZFALSE;
19530  cstartRecReq = SRR_REDO_COMPLETE;
19531  checkStartCompletedLab(signal);
19532  return;
19533  } else if ((cstartType == NodeState::ST_NODE_RESTART) ||
19534  (cstartType == NodeState::ST_SYSTEM_RESTART)) {
19535  jam();
19536 
19537  if(cstartType == NodeState::ST_SYSTEM_RESTART)
19538  {
19539  jam();
19540  if (c_lcp_complete_fragments.first(fragptr))
19541  {
19542  jam();
19543  signal->theData[0] = ZENABLE_EXPAND_CHECK;
19544  signal->theData[1] = fragptr.i;
19545  sendSignal(reference(), GSN_CONTINUEB, signal, 2, JBB);
19546  return;
19547  }
19548  }
19549 
19550  cstartRecReq = SRR_REDO_COMPLETE; // REDO complete
19551 
19552  rebuildOrderedIndexes(signal, 0);
19553  return;
19554  } else {
19555  ndbrequire(false);
19556  }//if
19557  return;
19558 }//Dblqh::srFourthComp()
19559 
19560 /* ######################################################################### */
19561 /* ####### ERROR MODULE ####### */
19562 /* */
19563 /* ######################################################################### */
19564 
19565 /*---------------------------------------------------------------------------*/
19566 /* AN ERROR OCCURRED THAT WE WILL NOT TREAT AS SYSTEM ERROR. MOST OFTEN THIS */
19567 /* WAS CAUSED BY AN ERRONEUS SIGNAL SENT BY ANOTHER NODE. WE DO NOT WISH TO */
19568 /* CRASH BECAUSE OF FAULTS IN OTHER NODES. THUS WE ONLY REPORT A WARNING. */
19569 /* THIS IS CURRENTLY NOT IMPLEMENTED AND FOR THE MOMENT WE GENERATE A SYSTEM */
19570 /* ERROR SINCE WE WANT TO FIND FAULTS AS QUICKLY AS POSSIBLE IN A TEST PHASE.*/
19571 /* IN A LATER PHASE WE WILL CHANGE THIS TO BE A WARNING MESSAGE INSTEAD. */
19572 /*---------------------------------------------------------------------------*/
19573 /*---------------------------------------------------------------------------*/
19574 /* THIS TYPE OF ERROR SHOULD NOT GENERATE A SYSTEM ERROR IN A PRODUCT */
19575 /* RELEASE. THIS IS A TEMPORARY SOLUTION DURING TEST PHASE TO QUICKLY */
19576 /* FIND ERRORS. NORMALLY THIS SHOULD GENERATE A WARNING MESSAGE ONTO */
19577 /* SOME ERROR LOGGER. THIS WILL LATER BE IMPLEMENTED BY SOME SIGNAL. */
19578 /*---------------------------------------------------------------------------*/
19579 /* ------ SYSTEM ERROR SITUATIONS ------- */
19580 /* IN SITUATIONS WHERE THE STATE IS ERRONEOUS OR IF THE ERROR OCCURS IN */
19581 /* THE COMMIT, COMPLETE OR ABORT PHASE, WE PERFORM A CRASH OF THE AXE VM*/
19582 /*---------------------------------------------------------------------------*/
19583 
19584 void Dblqh::systemErrorLab(Signal* signal, int line)
19585 {
19586  systemError(signal, line);
19587  progError(line, NDBD_EXIT_NDBREQUIRE);
19588 /*************************************************************************>*/
19589 /* WE WANT TO INVOKE AN IMMEDIATE ERROR HERE SO WE GET THAT BY */
19590 /* INSERTING A CERTAIN POINTER OUT OF RANGE. */
19591 /*************************************************************************>*/
19592 }//Dblqh::systemErrorLab()
19593 
19594 /* ------- ERROR SITUATIONS ------- */
19595 
19596 void Dblqh::aiStateErrorCheckLab(Signal* signal, Uint32* dataPtr, Uint32 length)
19597 {
19598  ndbrequire(tcConnectptr.p->abortState != TcConnectionrec::ABORT_IDLE);
19599  if (tcConnectptr.p->transactionState != TcConnectionrec::IDLE) {
19600  jam();
19601 /*************************************************************************>*/
19602 /* TRANSACTION ABORT IS ONGOING. IT CAN STILL BE A PART OF AN */
19603 /* OPERATION THAT SHOULD CONTINUE SINCE THE TUPLE HAS NOT ARRIVED */
19604 /* YET. THIS IS POSSIBLE IF ACTIVE CREATION OF THE FRAGMENT IS */
19605 /* ONGOING. */
19606 /*************************************************************************>*/
19607  if (tcConnectptr.p->activeCreat == Fragrecord::AC_IGNORED) {
19608  jam();
19609 /*************************************************************************>*/
19610 /* ONGOING ABORTS DURING ACTIVE CREATION MUST SAVE THE ATTRIBUTE INFO*/
19611 /* SO THAT IT CAN BE SENT TO THE NEXT NODE IN THE COMMIT CHAIN. THIS */
19612 /* IS NEEDED SINCE ALL ABORTS DURING CREATION OF A FRAGMENT ARE NOT */
19613 /* REALLY ERRORS. A MISSING TUPLE TO BE UPDATED SIMPLY MEANS THAT */
19614 /* IT HASN'T BEEN TRANSFERRED TO THE NEW REPLICA YET. */
19615 /*************************************************************************>*/
19616 /*************************************************************************>*/
19617 /* AFTER THIS ERROR THE ABORT MUST BE COMPLETED. TO ENSURE THIS SET */
19618 /* ACTIVE CREATION TO FALSE. THIS WILL ENSURE THAT THE ABORT IS */
19619 /* COMPLETED. */
19620 /*************************************************************************>*/
19621  if (saveAttrInfoInSection(dataPtr, length) == ZOK) {
19622  jam();
19623  if (tcConnectptr.p->transactionState ==
19624  TcConnectionrec::WAIT_AI_AFTER_ABORT) {
19625  if (tcConnectptr.p->currTupAiLen == tcConnectptr.p->totReclenAi) {
19626  jam();
19627 /*************************************************************************>*/
19628 /* WE WERE WAITING FOR MORE ATTRIBUTE INFO AFTER A SUCCESSFUL ABORT */
19629 /* IN ACTIVE CREATION STATE. THE TRANSACTION SHOULD CONTINUE AS IF */
19630 /* IT WAS COMMITTED. NOW ALL INFO HAS ARRIVED AND WE CAN CONTINUE */
19631 /* WITH NORMAL PROCESSING AS IF THE TRANSACTION WAS PREPARED. */
19632 /* SINCE THE FRAGMENT IS UNDER CREATION WE KNOW THAT LOGGING IS */
19633 /* DISABLED. WE STILL HAVE TO CATER FOR DIRTY OPERATION OR NOT. */
19634 /*************************************************************************>*/
19635  tcConnectptr.p->abortState = TcConnectionrec::ABORT_IDLE;
19636  rwConcludedAiLab(signal);
19637  return;
19638  } else {
19639  ndbrequire(tcConnectptr.p->currTupAiLen < tcConnectptr.p->totReclenAi);
19640  jam();
19641  return; /* STILL WAITING FOR MORE ATTRIBUTE INFO */
19642  }//if
19643  }//if
19644  } else {
19645  jam();
19646 /*************************************************************************>*/
19647 /* AFTER THIS ERROR THE ABORT MUST BE COMPLETED. TO ENSURE THIS SET */
19648 /* ACTIVE CREATION TO ABORT. THIS WILL ENSURE THAT THE ABORT IS */
19649 /* COMPLETED AND THAT THE ERROR CODE IS PROPERLY SET */
19650 /*************************************************************************>*/
19651  tcConnectptr.p->errorCode = terrorCode;
19652  tcConnectptr.p->activeCreat = Fragrecord::AC_NORMAL;
19653  if (tcConnectptr.p->transactionState ==
19654  TcConnectionrec::WAIT_AI_AFTER_ABORT) {
19655  jam();
19656 /*************************************************************************>*/
19657 /* ABORT IS ALREADY COMPLETED. WE NEED TO RESTART IT FROM WHERE IT */
19658 /* WAS INTERRUPTED. */
19659 /*************************************************************************>*/
19660  continueAbortLab(signal);
19661  return;
19662  } else {
19663  jam();
19664  return;
19665 /*************************************************************************>*/
19666 // Abort is ongoing. It will complete since we set the activeCreat = ZFALSE
19667 /*************************************************************************>*/
19668  }//if
19669  }//if
19670  }//if
19671  }//if
19672 /*************************************************************************>*/
19673 /* TRANSACTION HAVE BEEN ABORTED. THUS IGNORE ALL SIGNALS BELONGING TO IT. */
19674 /*************************************************************************>*/
19675  return;
19676 }//Dblqh::aiStateErrorCheckLab()
19677 
19678 void Dblqh::takeOverErrorLab(Signal* signal)
19679 {
19680  terrorCode = ZTAKE_OVER_ERROR;
19681  abortErrorLab(signal);
19682  return;
19683 }//Dblqh::takeOverErrorLab()
19684 
19685 /* ##########################################################################
19686  * TEST MODULE
19687  * ######################################################################### */
19688 #ifdef VM_TRACE
19689 void Dblqh::execTESTSIG(Signal* signal)
19690 {
19691  jamEntry();
19692  Uint32 userpointer = signal->theData[0];
19693  BlockReference userblockref = signal->theData[1];
19694  Uint32 testcase = signal->theData[2];
19695 
19696  signal->theData[0] = userpointer;
19697  signal->theData[1] = cownref;
19698  signal->theData[2] = testcase;
19699  sendSignal(userblockref, GSN_TESTSIG, signal, 25, JBB);
19700  return;
19701 }//Dblqh::execTESTSIG()
19702 
19703 /* *************** */
19704 /* MEMCHECKREQ > */
19705 /* *************** */
19706 /* ************************************************************************>>
19707  * THIS SIGNAL IS PURELY FOR TESTING PURPOSES. IT CHECKS THE FREE LIST
19708  * AND REPORTS THE NUMBER OF FREE RECORDS.
19709  * THIS CAN BE DONE TO ENSURE THAT NO RECORDS HAS BEEN LOST
19710  * ************************************************************************> */
19711 void Dblqh::execMEMCHECKREQ(Signal* signal)
19712 {
19713  Uint32* dataPtr = &signal->theData[0];
19714  jamEntry();
19715  BlockReference userblockref = signal->theData[0];
19716  Uint32 index = 0;
19717  for (Uint32 i = 0; i < 7; i++)
19718  dataPtr[i] = 0;
19719  addfragptr.i = cfirstfreeAddfragrec;
19720  while (addfragptr.i != RNIL) {
19721  ptrCheckGuard(addfragptr, caddfragrecFileSize, addFragRecord);
19722  addfragptr.i = addfragptr.p->nextAddfragrec;
19723  dataPtr[index]++;
19724  }//while
19725  index++;
19726  dataPtr[index]= 0;
19727  index++;
19728  dataPtr[index]= 0;
19729  index++;
19730  for (tabptr.i = 0;
19731  tabptr.i < ctabrecFileSize;
19732  tabptr.i++) {
19733  ptrAss(tabptr, tablerec);
19734  if (tabptr.p->tableStatus == Tablerec::NOT_DEFINED) {
19735  dataPtr[index]++;
19736  }//if
19737  }//for
19738  index++;
19739  tcConnectptr.i = cfirstfreeTcConrec;
19740  while (tcConnectptr.i != RNIL) {
19741  ptrCheckGuard(tcConnectptr, ctcConnectrecFileSize, tcConnectionrec);
19742  tcConnectptr.i = tcConnectptr.p->nextTcConnectrec;
19743  dataPtr[index]++;
19744  }//while
19745  sendSignal(userblockref, GSN_MEMCHECKCONF, signal, 10, JBB);
19746  return;
19747 }//Dblqh::execMEMCHECKREQ()
19748 
19749 #endif
19750 
19751 /* ************************************************************************* */
19752 /* ************************* STATEMENT BLOCKS ****************************** */
19753 /* ************************************************************************* */
19754 /* ========================================================================= */
19755 /* ====== BUILD LINKED LIST OF LOG PAGES AFTER RECEIVING FSREADCONF ======= */
19756 /* */
19757 /* ========================================================================= */
19758 void Dblqh::buildLinkedLogPageList(Signal* signal)
19759 {
19760  LogPageRecordPtr bllLogPagePtr;
19761 
19762  arrGuard(lfoPtr.p->noPagesRw - 1, 16);
19763  arrGuard(lfoPtr.p->noPagesRw, 16);
19764  Uint32 prev = RNIL;
19765  for (UintR tbllIndex = 0; tbllIndex < lfoPtr.p->noPagesRw; tbllIndex++) {
19766  jam();
19767  /* ----------------------------------------------------------------------
19768  * BUILD LINKED LIST BUT ALSO ENSURE THAT PAGE IS NOT SEEN AS DIRTY
19769  * INITIALLY.
19770  * --------------------------------------------------------------------- */
19771  bllLogPagePtr.i = lfoPtr.p->logPageArray[tbllIndex];
19772  ptrCheckGuard(bllLogPagePtr, clogPageFileSize, logPageRecord);
19773 
19774 // #if VM_TRACE
19775 // // Check logPage checksum before modifying it
19776 // Uint32 calcCheckSum = calcPageCheckSum(bllLogPagePtr);
19777 // Uint32 checkSum = bllLogPagePtr.p->logPageWord[ZPOS_CHECKSUM];
19778 // if (checkSum != calcCheckSum) {
19779 // ndbout << "Redolog: Checksum failure." << endl;
19780 // progError(__LINE__, NDBD_EXIT_NDBREQUIRE, "Redolog: Checksum failure.");
19781 // }
19782 // #endif
19783 
19784  bllLogPagePtr.p->logPageWord[ZPREV_PAGE] = prev;
19785  bllLogPagePtr.p->logPageWord[ZNEXT_PAGE] =
19786  lfoPtr.p->logPageArray[tbllIndex + 1];
19787  bllLogPagePtr.p->logPageWord[ZPOS_DIRTY] = ZNOT_DIRTY;
19788  prev = bllLogPagePtr.i;
19789  }//for
19790  bllLogPagePtr.i = lfoPtr.p->logPageArray[lfoPtr.p->noPagesRw - 1];
19791  ptrCheckGuard(bllLogPagePtr, clogPageFileSize, logPageRecord);
19792  bllLogPagePtr.p->logPageWord[ZNEXT_PAGE] = RNIL;
19793 }//Dblqh::buildLinkedLogPageList()
19794 
19795 /* =========================================================================
19796  * ======= CHANGE TO NEXT MBYTE IN LOG =======
19797  *
19798  * ========================================================================= */
19799 void Dblqh::changeMbyte(Signal* signal)
19800 {
19801  writeNextLog(signal);
19802  writeFileDescriptor(signal);
19803 }//Dblqh::changeMbyte()
19804 
19805 /* ========================================================================= */
19806 /* ====== CHECK IF THIS COMMIT LOG RECORD IS TO BE EXECUTED ======= */
19807 /* */
19808 /* SUBROUTINE SHORT NAME = CEL */
19809 /* ========================================================================= */
19810 Uint32 Dblqh::checkIfExecLog(Signal* signal)
19811 {
19812  tabptr.i = tcConnectptr.p->tableref;
19813  ptrCheckGuard(tabptr, ctabrecFileSize, tablerec);
19814  if (getFragmentrec(signal, tcConnectptr.p->fragmentid) &&
19815  (table_version_major(tabptr.p->schemaVersion) == table_version_major(tcConnectptr.p->schemaVersion))) {
19816  if (fragptr.p->execSrStatus != Fragrecord::IDLE) {
19817  if (fragptr.p->execSrNoReplicas > logPartPtr.p->execSrExecuteIndex) {
19818  ndbrequire((fragptr.p->execSrNoReplicas - 1) < MAX_REPLICAS);
19819  for (Uint32 i = logPartPtr.p->execSrExecuteIndex;
19820  i < fragptr.p->execSrNoReplicas;
19821  i++) {
19822  jam();
19823  if (tcConnectptr.p->gci_hi >= fragptr.p->execSrStartGci[i]) {
19824  if (tcConnectptr.p->gci_hi <= fragptr.p->execSrLastGci[i]) {
19825  jam();
19826  logPartPtr.p->execSrExecuteIndex = i;
19827  return ZOK;
19828  }//if
19829  }//if
19830  }//for
19831  }//if
19832  }//if
19833  }//if
19834  return ZNOT_OK;
19835 }//Dblqh::checkIfExecLog()
19836 
19837 /* ========================================================================= */
19838 /* == CHECK IF THERE IS LESS THAN 192 KBYTE IN THE BUFFER PLUS INCOMING === */
19839 /* READS ALREADY STARTED. IF SO IS THE CASE THEN START ANOTHER READ IF */
19840 /* THERE ARE MORE PAGES IN THIS MBYTE. */
19841 /* */
19842 /* ========================================================================= */
19843 void Dblqh::checkReadExecSr(Signal* signal)
19844 {
19845  logPartPtr.p->logExecState = LogPartRecord::LES_EXEC_LOG;
19846  logPartPtr.p->execSrPagesRead = logPartPtr.p->execSrPagesRead + 8;
19847  logPartPtr.p->execSrPagesReading = logPartPtr.p->execSrPagesReading - 8;
19848  if ((logPartPtr.p->execSrPagesRead + logPartPtr.p->execSrPagesReading) <
19849  ZREAD_AHEAD_SIZE) {
19850  jam();
19851  /* ----------------------------------------------------------------------
19852  * WE HAVE LESS THAN 64 KBYTE OF LOG PAGES REMAINING IN MEMORY OR ON
19853  * ITS WAY TO MAIN MEMORY. READ IN 8 MORE PAGES.
19854  * --------------------------------------------------------------------- */
19855  if ((logPartPtr.p->execSrPagesRead + logPartPtr.p->execSrPagesExecuted) <
19856  ZPAGES_IN_MBYTE) {
19857  jam();
19858  /* --------------------------------------------------------------------
19859  * THERE ARE MORE PAGES TO READ IN THIS MBYTE. READ THOSE FIRST
19860  * IF >= ZPAGES_IN_MBYTE THEN THERE ARE NO MORE PAGES TO READ. THUS
19861  * WE PROCEED WITH EXECUTION OF THE LOG.
19862  * ------------------------------------------------------------------- */
19863  readExecSr(signal);
19864  logPartPtr.p->logExecState = LogPartRecord::LES_WAIT_READ_EXEC_SR;
19865  }//if
19866  }//if
19867 }//Dblqh::checkReadExecSr()
19868 
19869 /* ========================================================================= */
19870 /* ==== CHECK IF START OF NEW FRAGMENT IS COMPLETED AND WE CAN ======= */
19871 /* ==== GET THE START GCI ======= */
19872 /* */
19873 /* SUBROUTINE SHORT NAME = CTC */
19874 /* ========================================================================= */
19875 void Dblqh::checkScanTcCompleted(Signal* signal)
19876 {
19877  tcConnectptr.p->logWriteState = TcConnectionrec::NOT_STARTED;
19878  fragptr.i = tcConnectptr.p->fragmentptr;
19879  c_fragment_pool.getPtr(fragptr);
19880  fragptr.p->activeTcCounter = fragptr.p->activeTcCounter - 1;
19881  if (fragptr.p->activeTcCounter == 0) {
19882  jam();
19883  fragptr.p->startGci = cnewestGci + 1;
19884  tabptr.i = tcConnectptr.p->tableref;
19885  ptrCheckGuard(tabptr, ctabrecFileSize, tablerec);
19886  sendCopyActiveConf(signal, tcConnectptr.p->tableref);
19887  }//if
19888 }//Dblqh::checkScanTcCompleted()
19889 
19890 /* ------------------------------------------------------------------------- */
19891 /* ------ CLOSE A FILE DURING EXECUTION OF FRAGMENT LOG ------- */
19892 /* */
19893 /* ------------------------------------------------------------------------- */
19894 void Dblqh::closeFile(Signal* signal,
19895  LogFileRecordPtr clfLogFilePtr, Uint32 line)
19896 {
19897  signal->theData[0] = clfLogFilePtr.p->fileRef;
19898  signal->theData[1] = cownref;
19899  signal->theData[2] = clfLogFilePtr.i;
19900  signal->theData[3] = ZCLOSE_NO_DELETE;
19901  signal->theData[4] = line;
19902  sendSignal(NDBFS_REF, GSN_FSCLOSEREQ, signal, 5, JBA);
19903 }//Dblqh::closeFile()
19904 
19905 
19906 /* ---------------------------------------------------------------- */
19907 /* ---------------- A LOG PAGE HAVE BEEN COMPLETED ---------------- */
19908 /* */
19909 /* SUBROUTINE SHORT NAME = CLP */
19910 // Input Pointers:
19911 // logFilePtr
19912 // logPagePtr
19913 // logPartPtr
19914 // Defines lfoPtr
19915 /* ---------------------------------------------------------------- */
19916 void Dblqh::completedLogPage(Signal* signal, Uint32 clpType, Uint32 place)
19917 {
19918  LogPageRecordPtr clpLogPagePtr;
19919  LogPageRecordPtr wlpLogPagePtr;
19920  UintR twlpNoPages;
19921  UintR twlpType;
19922 
19923  if (logFilePtr.p->firstFilledPage == RNIL) {
19924  jam();
19925  logFilePtr.p->firstFilledPage = logPagePtr.i;
19926  } else {
19927  jam();
19928  clpLogPagePtr.i = logFilePtr.p->lastFilledPage;
19929  ptrCheckGuard(clpLogPagePtr, clogPageFileSize, logPageRecord);
19930  clpLogPagePtr.p->logPageWord[ZNEXT_PAGE] = logPagePtr.i;
19931  }//if
19932  logFilePtr.p->lastFilledPage = logPagePtr.i;
19933  logPagePtr.p->logPageWord[ZNEXT_PAGE] = RNIL;
19934  logFilePtr.p->noLogpagesInBuffer = logFilePtr.p->noLogpagesInBuffer + 1;
19935  if (logFilePtr.p->noLogpagesInBuffer != ZMAX_PAGES_WRITTEN) {
19936  if (clpType != ZLAST_WRITE_IN_FILE) {
19937  if (clpType != ZENFORCE_WRITE) {
19938  jam();
19939  return;
19940  }//if
19941  }//if
19942  }//if
19943  twlpType = clpType;
19944 /* ------------------------------------------------------------------------- */
19945 /* ------ WRITE A SET OF LOG PAGES TO DISK ------- */
19946 /* */
19947 /* SUBROUTINE SHORT NAME: WLP */
19948 /* ------------------------------------------------------------------------- */
19949  seizeLfo(signal);
19950  initLfo(signal);
19951  Uint32* dataPtr = &signal->theData[6];
19952  twlpNoPages = 0;
19953  wlpLogPagePtr.i = logFilePtr.p->firstFilledPage;
19954  do {
19955  dataPtr[twlpNoPages] = wlpLogPagePtr.i;
19956  twlpNoPages++;
19957  ptrCheckGuard(wlpLogPagePtr, clogPageFileSize, logPageRecord);
19958 
19959  writeDbgInfoPageHeader(wlpLogPagePtr, place,
19960  logFilePtr.p->filePosition + twlpNoPages - 1,
19961  ZPAGE_SIZE);
19962  // Calculate checksum for page
19963  wlpLogPagePtr.p->logPageWord[ZPOS_CHECKSUM] = calcPageCheckSum(wlpLogPagePtr);
19964  wlpLogPagePtr.i = wlpLogPagePtr.p->logPageWord[ZNEXT_PAGE];
19965  } while (wlpLogPagePtr.i != RNIL);
19966  ndbrequire(twlpNoPages < 9);
19967  dataPtr[twlpNoPages] = logFilePtr.p->filePosition;
19968 /* -------------------------------------------------- */
19969 /* SET TIMER ON THIS LOG PART TO SIGNIFY THAT A */
19970 /* LOG RECORD HAS BEEN SENT AT THIS TIME. */
19971 /* -------------------------------------------------- */
19972  logPartPtr.p->logPartTimer = logPartPtr.p->logTimer;
19973  signal->theData[0] = logFilePtr.p->fileRef;
19974  signal->theData[1] = cownref;
19975  signal->theData[2] = lfoPtr.i;
19976  if (twlpType == ZLAST_WRITE_IN_FILE) {
19977  jam();
19978  signal->theData[3] = ZLIST_OF_MEM_PAGES_SYNCH;
19979  } else {
19980  jam();
19981  signal->theData[3] = ZLIST_OF_MEM_PAGES;
19982  }//if
19983  signal->theData[4] = ZVAR_NO_LOG_PAGE_WORD;
19984  signal->theData[5] = twlpNoPages;
19985  sendSignal(NDBFS_REF, GSN_FSWRITEREQ, signal, 15, JBA);
19986 
19987  ndbrequire(logFilePtr.p->fileRef != RNIL);
19988 
19989  logPartPtr.p->m_io_tracker.send_io(32768*twlpNoPages);
19990 
19991  if (DEBUG_REDO)
19992  {
19993  ndbout_c("writing %d pages at part: %u file: %u page: %u (mb: %u)",
19994  twlpNoPages,
19995  logPartPtr.p->logPartNo,
19996  logFilePtr.p->fileNo,
19997  logFilePtr.p->filePosition,
19998  logFilePtr.p->filePosition >> ZTWOLOG_NO_PAGES_IN_MBYTE);
19999  }
20000 
20001  if (twlpType == ZNORMAL) {
20002  jam();
20004  } else if (twlpType == ZLAST_WRITE_IN_FILE) {
20005  jam();
20006  lfoPtr.p->lfoState = LogFileOperationRecord::LAST_WRITE_IN_FILE;
20007  } else {
20008  ndbrequire(twlpType == ZENFORCE_WRITE);
20009  jam();
20011  }//if
20012  /* ----------------------------------------------------------------------- */
20013  /* ------ MOVE PAGES FROM LOG FILE TO LFO RECORD ------- */
20014  /* */
20015  /* ----------------------------------------------------------------------- */
20016  /* -------------------------------------------------- */
20017  /* MOVE PAGES TO LFO RECORD AND REMOVE THEM */
20018  /* FROM LOG FILE RECORD. */
20019  /* -------------------------------------------------- */
20020  lfoPtr.p->firstLfoPage = logFilePtr.p->firstFilledPage;
20021  logFilePtr.p->firstFilledPage = RNIL;
20022  logFilePtr.p->lastFilledPage = RNIL;
20023  logFilePtr.p->noLogpagesInBuffer = 0;
20024 
20025  lfoPtr.p->noPagesRw = twlpNoPages;
20026  lfoPtr.p->lfoPageNo = logFilePtr.p->filePosition;
20027  lfoPtr.p->lfoWordWritten = ZPAGE_SIZE - 1;
20028  logFilePtr.p->filePosition += twlpNoPages;
20029 }//Dblqh::completedLogPage()
20030 
20031 /* ---------------------------------------------------------------- */
20032 /* ---------------- DELETE FRAGMENT RECORD ------------------------ */
20033 /* */
20034 /* SUBROUTINE SHORT NAME = DFR */
20035 /* ---------------------------------------------------------------- */
20036 void Dblqh::deleteFragrec(Uint32 fragId)
20037 {
20038  Uint32 indexFound= RNIL;
20039  fragptr.i = RNIL;
20040  for (Uint32 i = 0; i < MAX_FRAG_PER_NODE; i++) {
20041  jam();
20042  if (tabptr.p->fragid[i] == fragId) {
20043  fragptr.i = tabptr.p->fragrec[i];
20044  indexFound = i;
20045  break;
20046  }//if
20047  }//for
20048  if (fragptr.i != RNIL) {
20049  jam();
20050  c_fragment_pool.getPtr(fragptr);
20051  tabptr.p->fragid[indexFound] = ZNIL;
20052  tabptr.p->fragrec[indexFound] = RNIL;
20053  fragptr.p->fragStatus = Fragrecord::FREE;
20054  c_fragment_pool.release(fragptr);
20055  }//if
20056 }//Dblqh::deleteFragrec()
20057 
20058 /* ------------------------------------------------------------------------- */
20059 /* ------- FIND LOG FILE RECORD GIVEN FILE NUMBER ------- */
20060 /* */
20061 /* INPUT: TFLF_FILE_NO THE FILE NUMBER */
20062 /* FLF_LOG_PART_PTR THE LOG PART RECORD */
20063 /* OUTPUT: FLF_LOG_FILE_PTR THE FOUND LOG FILE RECORD */
20064 /* SUBROUTINE SHORT NAME = FLF */
20065 /* ------------------------------------------------------------------------- */
20066 void Dblqh::findLogfile(Signal* signal,
20067  Uint32 fileNo,
20068  LogPartRecordPtr flfLogPartPtr,
20069  LogFileRecordPtr* parLogFilePtr)
20070 {
20071  LogFileRecordPtr locLogFilePtr;
20072  locLogFilePtr.i = flfLogPartPtr.p->firstLogfile;
20073  Uint32 loopCount = 0;
20074  while (true) {
20075  ptrCheckGuard(locLogFilePtr, clogFileFileSize, logFileRecord);
20076  if (locLogFilePtr.p->fileNo == fileNo) {
20077  jam();
20078  ndbrequire(loopCount == fileNo);
20079  parLogFilePtr->i = locLogFilePtr.i;
20080  parLogFilePtr->p = locLogFilePtr.p;
20081  return;
20082  }//if
20083  locLogFilePtr.i = locLogFilePtr.p->nextLogFile;
20084  loopCount++;
20085  if (loopCount >= flfLogPartPtr.p->noLogFiles &&
20086  getNodeState().startLevel != NodeState::SL_STARTED)
20087  {
20088  goto error;
20089  }
20090  ndbrequire(loopCount < flfLogPartPtr.p->noLogFiles);
20091  }//while
20092 
20093 error:
20094  char buf[255];
20095  BaseString::snprintf(buf, sizeof(buf),
20096  "Unable to restart, failed while reading redo."
20097  " Likely invalid change of configuration");
20098  progError(__LINE__,
20099  NDBD_EXIT_INVALID_CONFIG,
20100  buf);
20101 }//Dblqh::findLogfile()
20102 
20103 /* ------------------------------------------------------------------------- */
20104 /* ------ FIND PAGE REFERENCE IN MEMORY BUFFER AT LOG EXECUTION ------- */
20105 /* */
20106 /* ------------------------------------------------------------------------- */
20107 void Dblqh::findPageRef(Signal* signal, CommitLogRecord* commitLogRecord)
20108 {
20109  UintR tfprIndex;
20110 
20111  logPagePtr.i = RNIL;
20112  if (ERROR_INSERTED(5020)) {
20113  // Force system to read page from disk
20114  return;
20115  }
20116  pageRefPtr.i = logPartPtr.p->lastPageRef;
20117  do {
20118  ptrCheckGuard(pageRefPtr, cpageRefFileSize, pageRefRecord);
20119  if (commitLogRecord->fileNo == pageRefPtr.p->prFileNo) {
20120  if (commitLogRecord->startPageNo >= pageRefPtr.p->prPageNo) {
20121  if (commitLogRecord->startPageNo < (Uint16) (pageRefPtr.p->prPageNo + 8)) {
20122  jam();
20123  tfprIndex = commitLogRecord->startPageNo - pageRefPtr.p->prPageNo;
20124  logPagePtr.i = pageRefPtr.p->pageRef[tfprIndex];
20125  ptrCheckGuard(logPagePtr, clogPageFileSize, logPageRecord);
20126  return;
20127  }//if
20128  }//if
20129  }//if
20130  pageRefPtr.i = pageRefPtr.p->prPrev;
20131  } while (pageRefPtr.i != RNIL);
20132 
20133 #ifndef NO_REDO_PAGE_CACHE
20134  RedoPageCache& cache = m_redo_page_cache;
20135  RedoCacheLogPageRecord key;
20136  key.m_part_no = logPartPtr.p->logPartNo;
20137  key.m_file_no = commitLogRecord->fileNo;
20138  key.m_page_no = commitLogRecord->startPageNo;
20140  if (cache.m_hash.find(pagePtr, key))
20141  {
20142  jam();
20143  if (cache.m_lru.hasPrev(pagePtr))
20144  {
20145  jam();
20146  cache.m_lru.remove(pagePtr);
20147  cache.m_lru.addFirst(pagePtr);
20148  }
20149  logPagePtr.i = pagePtr.i;
20150  ptrCheckGuard(logPagePtr, clogPageFileSize, logPageRecord);
20151 
20152  Ptr<LogPageRecord> loopPtr = logPagePtr;
20153  Uint32 extra = commitLogRecord->stopPageNo - commitLogRecord->startPageNo;
20154  for (Uint32 i = 0; i<extra; i++)
20155  {
20156  jam();
20157  Uint32 prevPtrI = loopPtr.i;
20158  loopPtr.i = loopPtr.p->logPageWord[ZNEXT_PAGE];
20159  if (loopPtr.i == RNIL)
20160  {
20161  jam();
20166  key.m_page_no = commitLogRecord->startPageNo + i + 1;
20167  if (cache.m_hash.find(pagePtr, key))
20168  {
20169  jam();
20173  Ptr<LogPageRecord> tmp;
20174  tmp.i = pagePtr.i;
20175  tmp.p = reinterpret_cast<LogPageRecord*>(pagePtr.p);
20176  tmp.p->logPageWord[ZPREV_PAGE] = prevPtrI;
20177  loopPtr.p->logPageWord[ZNEXT_PAGE] = tmp.i;
20178  loopPtr.i = tmp.i;
20179  }
20180  else
20181  {
20182  jam();
20183  logPagePtr.i = RNIL;
20184  cache.m_multi_miss++;
20185  if (0)
20186  ndbout_c("Found part: %u file: %u page: %u but not next page(%u) %u",
20187  key.m_part_no,
20188  commitLogRecord->fileNo,
20189  commitLogRecord->startPageNo,
20190  (i + 1),
20191  commitLogRecord->startPageNo + i + 1);
20192  return;
20193  }
20194  }
20195 
20196  ptrCheckGuard(loopPtr, clogPageFileSize, logPageRecord);
20197  pagePtr.i = loopPtr.i;
20198  pagePtr.p = reinterpret_cast<RedoCacheLogPageRecord*>(loopPtr.p);
20199  if (cache.m_lru.hasPrev(pagePtr))
20200  {
20201  jam();
20202  cache.m_lru.remove(pagePtr);
20203  cache.m_lru.addFirst(pagePtr);
20204  }
20205  }
20206  cache.m_hits++;
20207  if (extra)
20208  {
20209  jam();
20210  cache.m_multi_page++;
20211  }
20212  }
20213 #endif
20214 }//Dblqh::findPageRef()
20215 
20216 /* ------------------------------------------------------------------------- */
20217 /* ------ GET FIRST OPERATION QUEUED FOR LOGGING ------- */
20218 /* */
20219 /* SUBROUTINE SHORT NAME = GFL */
20220 /* ------------------------------------------------------------------------- */
20221 void
20222 Dblqh::getFirstInLogQueue(Signal* signal,
20223  Ptr<TcConnectionrec> & dst)
20224 {
20225  TcConnectionrecPtr tmp;
20226 /* -------------------------------------------------- */
20227 /* GET THE FIRST FROM THE LOG QUEUE AND REMOVE */
20228 /* IT FROM THE QUEUE. */
20229 /* -------------------------------------------------- */
20230  LogPartRecord::OperationQueue * queue = &logPartPtr.p->m_log_complete_queue;
20231  tmp.i = queue->firstElement;
20232  if (tmp.i == RNIL)
20233  {
20234  jam();
20235  queue = &logPartPtr.p->m_log_prepare_queue;
20236  tmp.i = queue->firstElement;
20237  }
20238  ptrCheckGuard(tmp, ctcConnectrecFileSize, tcConnectionrec);
20239  queue->firstElement = tmp.p->nextTcLogQueue;
20240  if (queue->firstElement == RNIL) {
20241  jam();
20242  queue->lastElement = RNIL;
20243  }//if
20244  dst = tmp;
20245 }//Dblqh::getFirstInLogQueue()
20246 
20247 /* ---------------------------------------------------------------- */
20248 /* ---------------- GET FRAGMENT RECORD --------------------------- */
20249 /* INPUT: TFRAGID FRAGMENT ID LOOKING FOR */
20250 /* TABPTR TABLE ID */
20251 /* SUBROUTINE SHORT NAME = GFR */
20252 /* ---------------------------------------------------------------- */
20253 bool Dblqh::getFragmentrec(Signal* signal, Uint32 fragId)
20254 {
20255  for (Uint32 i = 0; i < MAX_FRAG_PER_NODE; i++) {
20256  jam();
20257  if (tabptr.p->fragid[i] == fragId) {
20258  fragptr.i = tabptr.p->fragrec[i];
20259  c_fragment_pool.getPtr(fragptr);
20260  return true;
20261  }//if
20262  }//for
20263  return false;
20264 }//Dblqh::getFragmentrec()
20265 
20266 /* ========================================================================= */
20267 /* ====== INITIATE FRAGMENT RECORD ======= */
20268 /* */
20269 /* ========================================================================= */
20270 void Dblqh::initialiseAddfragrec(Signal* signal)
20271 {
20272  if (caddfragrecFileSize != 0) {
20273  for (addfragptr.i = 0; addfragptr.i < caddfragrecFileSize; addfragptr.i++) {
20274  ptrAss(addfragptr, addFragRecord);
20275  addfragptr.p->addfragStatus = AddFragRecord::FREE;
20276  addfragptr.p->nextAddfragrec = addfragptr.i + 1;
20277  }//for
20278  addfragptr.i = caddfragrecFileSize - 1;
20279  ptrAss(addfragptr, addFragRecord);
20280  addfragptr.p->nextAddfragrec = RNIL;
20281  cfirstfreeAddfragrec = 0;
20282  } else {
20283  jam();
20284  cfirstfreeAddfragrec = RNIL;
20285  }//if
20286 }//Dblqh::initialiseAddfragrec()
20287 
20288 /* ========================================================================= */
20289 /* ====== INITIATE FRAGMENT RECORD ======= */
20290 /* */
20291 /* ========================================================================= */
20292 void Dblqh::initialiseFragrec(Signal* signal)
20293 {
20294 
20295  SLList<Fragrecord> tmp(c_fragment_pool);
20296  while(tmp.seize(fragptr))
20297  {
20299  new (fragptr.p) Fragrecord();
20300  fragptr.p->fragStatus = Fragrecord::FREE;
20301  fragptr.p->execSrStatus = Fragrecord::IDLE;
20302  fragptr.p->srStatus = Fragrecord::SS_IDLE;
20303  }
20304  tmp.release();
20305 }//Dblqh::initialiseFragrec()
20306 
20307 /* ========================================================================= */
20308 /* ====== INITIATE FRAGMENT RECORD ======= */
20309 /* */
20310 /* ========================================================================= */
20311 void Dblqh::initialiseGcprec(Signal* signal)
20312 {
20313  UintR tigpIndex;
20314 
20315  if (cgcprecFileSize != 0) {
20316  for (gcpPtr.i = 0; gcpPtr.i < cgcprecFileSize; gcpPtr.i++) {
20317  ptrAss(gcpPtr, gcpRecord);
20318  for (tigpIndex = 0; tigpIndex < ZLOG_PART_FILE_SIZE; tigpIndex++) {
20319  gcpPtr.p->gcpLogPartState[tigpIndex] = ZIDLE;
20320  gcpPtr.p->gcpSyncReady[tigpIndex] = ZFALSE;
20321  }//for
20322  }//for
20323  }//if
20324 }//Dblqh::initialiseGcprec()
20325 
20326 /* ========================================================================= */
20327 /* ====== INITIATE LCP RECORD ======= */
20328 /* */
20329 /* ========================================================================= */
20330 void Dblqh::initialiseLcpRec(Signal* signal)
20331 {
20332  if (clcpFileSize != 0) {
20333  for (lcpPtr.i = 0; lcpPtr.i < clcpFileSize; lcpPtr.i++) {
20334  ptrAss(lcpPtr, lcpRecord);
20335  lcpPtr.p->lcpState = LcpRecord::LCP_IDLE;
20336  lcpPtr.p->lcpQueued = false;
20337  lcpPtr.p->reportEmpty = false;
20338  lcpPtr.p->firstFragmentFlag = false;
20339  lcpPtr.p->lastFragmentFlag = false;
20340  }//for
20341  }//if
20342 }//Dblqh::initialiseLcpRec()
20343 
20344 /* ========================================================================= */
20345 /* ====== INITIATE LOG FILE OPERATION RECORD ======= */
20346 /* */
20347 /* ========================================================================= */
20348 void Dblqh::initialiseLfo(Signal* signal)
20349 {
20350  if (clfoFileSize != 0) {
20351  for (lfoPtr.i = 0; lfoPtr.i < clfoFileSize; lfoPtr.i++) {
20352  ptrAss(lfoPtr, logFileOperationRecord);
20354  lfoPtr.p->lfoTimer = 0;
20355  lfoPtr.p->nextLfo = lfoPtr.i + 1;
20356  }//for
20357  lfoPtr.i = clfoFileSize - 1;
20358  ptrAss(lfoPtr, logFileOperationRecord);
20359  lfoPtr.p->nextLfo = RNIL;
20360  cfirstfreeLfo = 0;
20361  } else {
20362  jam();
20363  cfirstfreeLfo = RNIL;
20364  }//if
20365 }//Dblqh::initialiseLfo()
20366 
20367 /* ========================================================================= */
20368 /* ====== INITIATE LOG FILE RECORD ======= */
20369 /* */
20370 /* ========================================================================= */
20371 void Dblqh::initialiseLogFile(Signal* signal)
20372 {
20373  if (clogFileFileSize != 0) {
20374  for (logFilePtr.i = 0; logFilePtr.i < clogFileFileSize; logFilePtr.i++) {
20375  ptrAss(logFilePtr, logFileRecord);
20376  logFilePtr.p->nextLogFile = logFilePtr.i + 1;
20377  logFilePtr.p->logFileStatus = LogFileRecord::LFS_IDLE;
20378 
20379  logFilePtr.p->logLastPrepRef = new Uint32[clogFileSize];
20380  logFilePtr.p->logMaxGciCompleted = new Uint32[clogFileSize];
20381  logFilePtr.p->logMaxGciStarted = new Uint32[clogFileSize];
20382 
20383  if (logFilePtr.p->logLastPrepRef == 0 ||
20384  logFilePtr.p->logMaxGciCompleted == 0 ||
20385  logFilePtr.p->logMaxGciStarted == 0)
20386  {
20387  char buf[256];
20388  BaseString::snprintf(buf, sizeof(buf),
20389  "Failed to alloc mbyte(%u) arrays for logfile %u",
20390  clogFileSize, logFilePtr.i);
20391  progError(__LINE__, NDBD_EXIT_MEMALLOC, buf);
20392  }
20393 
20394  }//for
20395  logFilePtr.i = clogFileFileSize - 1;
20396  ptrAss(logFilePtr, logFileRecord);
20397  logFilePtr.p->nextLogFile = RNIL;
20398  cfirstfreeLogFile = 0;
20399  } else {
20400  jam();
20401  cfirstfreeLogFile = RNIL;
20402  }//if
20403 }//Dblqh::initialiseLogFile()
20404 
20405 /* ========================================================================= */
20406 /* ====== INITIATE LOG PAGES ======= */
20407 /* */
20408 /* ========================================================================= */
20409 void Dblqh::initialiseLogPage(Signal* signal)
20410 {
20414 }//Dblqh::initialiseLogPage()
20415 
20416 /* =========================================================================
20417  * ====== INITIATE LOG PART RECORD =======
20418  *
20419  * ========================================================================= */
20420 void Dblqh::initialiseLogPart(Signal* signal)
20421 {
20422  for (logPartPtr.i = 0; logPartPtr.i < clogPartFileSize; logPartPtr.i++) {
20423  ptrAss(logPartPtr, logPartRecord);
20424  logPartPtr.p->waitWriteGciLog = LogPartRecord::WWGL_FALSE;
20425  logPartPtr.p->LogLqhKeyReqSent = ZFALSE;
20426  logPartPtr.p->logPartNewestCompletedGCI = (UintR)-1;
20427  logPartPtr.p->logTcConrec = RNIL;
20428  }//for
20429 }//Dblqh::initialiseLogPart()
20430 
20431 void Dblqh::initialisePageRef(Signal* signal)
20432 {
20433  if (cpageRefFileSize != 0) {
20434  for (pageRefPtr.i = 0;
20435  pageRefPtr.i < cpageRefFileSize;
20436  pageRefPtr.i++) {
20437  ptrAss(pageRefPtr, pageRefRecord);
20438  pageRefPtr.p->prNext = pageRefPtr.i + 1;
20439  }//for
20440  pageRefPtr.i = cpageRefFileSize - 1;
20441  ptrAss(pageRefPtr, pageRefRecord);
20442  pageRefPtr.p->prNext = RNIL;
20443  cfirstfreePageRef = 0;
20444  } else {
20445  jam();
20446  cfirstfreePageRef = RNIL;
20447  }//if
20448 }//Dblqh::initialisePageRef()
20449 
20450 /* ==========================================================================
20451  * ======= INITIATE RECORDS =======
20452  *
20453  * TAKES CARE OF INITIATION OF ALL RECORDS IN THIS BLOCK.
20454  * ========================================================================= */
20455 void Dblqh::initialiseRecordsLab(Signal* signal, Uint32 data,
20456  Uint32 retRef, Uint32 retData)
20457 {
20458  Uint32 i;
20459  switch (data) {
20460  case 0:
20461  jam();
20462  m_sr_nodes.clear();
20463  m_sr_exec_sr_req.clear();
20464  m_sr_exec_sr_conf.clear();
20465  for (i = 0; i < 4; i++) {
20466  cactiveCopy[i] = RNIL;
20467  }//for
20468  cnoActiveCopy = 0;
20469  ccurrentGcprec = RNIL;
20470  caddNodeState = ZFALSE;
20471  cstartRecReq = SRR_INITIAL; // Initial
20472  cnewestGci = 0;
20473  cnewestCompletedGci = 0;
20474  crestartOldestGci = 0;
20475  crestartNewestGci = 0;
20476  csrPhaseStarted = ZSR_NO_PHASE_STARTED;
20477  csrPhasesCompleted = 0;
20478  cmasterDihBlockref = 0;
20479  cnoFragmentsExecSr = 0;
20480  cnoOutstandingExecFragReq = 0;
20481  clcpCompletedState = LCP_IDLE;
20482  csrExecUndoLogState = EULS_IDLE;
20483  c_lcpId = 0;
20484  cnoOfFragsCheckpointed = 0;
20485  break;
20486  case 1:
20487  jam();
20488  initialiseAddfragrec(signal);
20489  break;
20490  case 2:
20491  jam();
20492  /* Unused */
20493  break;
20494  case 3:
20495  jam();
20496  /* Unused */
20497  break;
20498  case 4:
20499  jam();
20500  initialiseFragrec(signal);
20501  break;
20502  case 5:
20503  jam();
20504  initialiseGcprec(signal);
20505  initialiseLcpRec(signal);
20506  break;
20507  case 6:
20508  jam();
20509  initialiseLogPage(signal);
20510  break;
20511  case 7:
20512  jam();
20513  initialiseLfo(signal);
20514  break;
20515  case 8:
20516  jam();
20517  initialiseLogFile(signal);
20518  initialiseLogPart(signal);
20519  break;
20520  case 9:
20521  jam();
20522  initialisePageRef(signal);
20523  break;
20524  case 10:
20525  jam();
20526  initialiseScanrec(signal);
20527  break;
20528  case 11:
20529  jam();
20530  initialiseTabrec(signal);
20531  break;
20532  case 12:
20533  jam();
20534  initialiseTcNodeFailRec(signal);
20535  initialiseTcrec(signal);
20536  {
20537  ReadConfigConf * conf = (ReadConfigConf*)signal->getDataPtrSend();
20538  conf->senderRef = reference();
20539  conf->senderData = retData;
20540  sendSignal(retRef, GSN_READ_CONFIG_CONF, signal,
20541  ReadConfigConf::SignalLength, JBB);
20542  }
20543  return;
20544  break;
20545  default:
20546  ndbrequire(false);
20547  break;
20548  }//switch
20549 
20550  signal->theData[0] = ZINITIALISE_RECORDS;
20551  signal->theData[1] = data + 1;
20552  signal->theData[2] = 0;
20553  signal->theData[3] = retRef;
20554  signal->theData[4] = retData;
20555  sendSignal(reference(), GSN_CONTINUEB, signal, 5, JBB);
20556 
20557  return;
20558 }//Dblqh::initialiseRecordsLab()
20559 
20560 /* ==========================================================================
20561  * ======= INITIATE TC CONNECTION RECORD =======
20562  *
20563  * ========================================================================= */
20564 void Dblqh::initialiseScanrec(Signal* signal)
20565 {
20566  ndbrequire(cscanrecFileSize > 1);
20567  DLList<ScanRecord> tmp(c_scanRecordPool);
20568  while (tmp.seize(scanptr)){
20569  //new (scanptr.p) ScanRecord();
20571  scanptr.p->scanType = ScanRecord::ST_IDLE;
20572  scanptr.p->scanState = ScanRecord::SCAN_FREE;
20573  scanptr.p->scanTcWaiting = 0;
20574  scanptr.p->nextHash = RNIL;
20575  scanptr.p->prevHash = RNIL;
20576  scanptr.p->scan_acc_index= 0;
20577  scanptr.p->scan_acc_segments= 0;
20578  scanptr.p->m_reserved = 0;
20579  }
20580  tmp.release();
20581 
20586  m_reserved_scans.seize(scanptr); // LCP
20587  scanptr.p->m_reserved = 1;
20588  m_reserved_scans.seize(scanptr); // NR
20589  scanptr.p->m_reserved = 1;
20590 
20591 }//Dblqh::initialiseScanrec()
20592 
20593 /* ==========================================================================
20594  * ======= INITIATE TABLE RECORD =======
20595  *
20596  * ========================================================================= */
20597 void Dblqh::initialiseTabrec(Signal* signal)
20598 {
20599  if (ctabrecFileSize != 0) {
20600  for (tabptr.i = 0; tabptr.i < ctabrecFileSize; tabptr.i++) {
20602  ptrAss(tabptr, tablerec);
20603  tabptr.p->tableStatus = Tablerec::NOT_DEFINED;
20604  tabptr.p->usageCountR = 0;
20605  tabptr.p->usageCountW = 0;
20606  for (Uint32 i = 0; i < MAX_FRAG_PER_NODE; i++) {
20607  tabptr.p->fragid[i] = ZNIL;
20608  tabptr.p->fragrec[i] = RNIL;
20609  }//for
20610  }//for
20611  }//if
20612 }//Dblqh::initialiseTabrec()
20613 
20614 /* ==========================================================================
20615  * ======= INITIATE TC CONNECTION RECORD =======
20616  *
20617  * ========================================================================= */
20618 void Dblqh::initialiseTcrec(Signal* signal)
20619 {
20620  if (ctcConnectrecFileSize != 0) {
20621  for (tcConnectptr.i = 0;
20622  tcConnectptr.i < ctcConnectrecFileSize;
20623  tcConnectptr.i++) {
20625  ptrAss(tcConnectptr, tcConnectionrec);
20626  tcConnectptr.p->transactionState = TcConnectionrec::TC_NOT_CONNECTED;
20627  tcConnectptr.p->tcScanRec = RNIL;
20628  tcConnectptr.p->logWriteState = TcConnectionrec::NOT_STARTED;
20629  tcConnectptr.p->keyInfoIVal = RNIL;
20630  tcConnectptr.p->attrInfoIVal = RNIL;
20631  tcConnectptr.p->m_flags= 0;
20632  tcConnectptr.p->tcTimer = 0;
20633  tcConnectptr.p->nextTcConnectrec = tcConnectptr.i + 1;
20634  }//for
20635  tcConnectptr.i = ctcConnectrecFileSize - 1;
20636  ptrAss(tcConnectptr, tcConnectionrec);
20637  tcConnectptr.p->nextTcConnectrec = RNIL;
20638  cfirstfreeTcConrec = 0;
20639  } else {
20640  jam();
20641  cfirstfreeTcConrec = RNIL;
20642  }//if
20643 }//Dblqh::initialiseTcrec()
20644 
20645 /* ==========================================================================
20646  * ======= INITIATE TC CONNECTION RECORD =======
20647  *
20648  * ========================================================================= */
20649 void Dblqh::initialiseTcNodeFailRec(Signal* signal)
20650 {
20651  if (ctcNodeFailrecFileSize != 0) {
20652  for (tcNodeFailptr.i = 0;
20653  tcNodeFailptr.i < ctcNodeFailrecFileSize;
20654  tcNodeFailptr.i++) {
20655  ptrAss(tcNodeFailptr, tcNodeFailRecord);
20656  tcNodeFailptr.p->tcFailStatus = TcNodeFailRecord::TC_STATE_FALSE;
20657  }//for
20658  }//if
20659 }//Dblqh::initialiseTcNodeFailRec()
20660 
20661 /* ==========================================================================
20662  * ======= INITIATE FRAGMENT RECORD =======
20663  *
20664  * SUBROUTINE SHORT NAME = IF
20665  * ========================================================================= */
20666 void Dblqh::initFragrec(Signal* signal,
20667  Uint32 tableId,
20668  Uint32 fragId,
20669  Uint32 copyType)
20670 {
20671  new (fragptr.p) Fragrecord();
20672  fragptr.p->m_scanNumberMask.set(); // All is free
20673  fragptr.p->accBlockref = caccBlockref;
20674  fragptr.p->firstWaitQueue = RNIL;
20675  fragptr.p->lastWaitQueue = RNIL;
20676  fragptr.p->fragStatus = Fragrecord::DEFINED;
20677  fragptr.p->fragCopy = copyType;
20678  fragptr.p->tupBlockref = ctupBlockref;
20679  fragptr.p->tuxBlockref = ctuxBlockref;
20680  fragptr.p->logFlag = Fragrecord::STATE_TRUE;
20681  fragptr.p->lcpFlag = Fragrecord::LCP_STATE_TRUE;
20682  for (Uint32 i = 0; i < MAX_LCP_STORED; i++) {
20683  fragptr.p->lcpId[i] = 0;
20684  }//for
20685  fragptr.p->maxGciCompletedInLcp = 0;
20686  fragptr.p->maxGciInLcp = 0;
20687  fragptr.p->copyFragState = ZIDLE;
20688  fragptr.p->newestGci = cnewestGci;
20689  fragptr.p->tabRef = tableId;
20690  fragptr.p->fragId = fragId;
20691  fragptr.p->srStatus = Fragrecord::SS_IDLE;
20692  fragptr.p->execSrStatus = Fragrecord::IDLE;
20693  fragptr.p->execSrNoReplicas = 0;
20694  fragptr.p->fragDistributionKey = 0;
20695  fragptr.p->activeTcCounter = 0;
20696  fragptr.p->tableFragptr = RNIL;
20697  fragptr.p->m_copy_started_state = 0;
20698 }//Dblqh::initFragrec()
20699 
20700 /* ==========================================================================
20701  * ======= INITIATE FRAGMENT RECORD FOR SYSTEM RESTART =======
20702  *
20703  * SUBROUTINE SHORT NAME = IFS
20704  * ========================================================================= */
20705 
20706 /* ==========================================================================
20707  * ======= INITIATE INFORMATION ABOUT GLOBAL CHECKPOINTS =======
20708  * IN LOG FILE RECORDS
20709  *
20710  * INPUT: LOG_FILE_PTR CURRENT LOG FILE
20711  * TNO_FD_DESCRIPTORS THE NUMBER OF FILE DESCRIPTORS
20712  * TO READ FROM THE LOG PAGE
20713  * LOG_PAGE_PTR PAGE ZERO IN LOG FILE
20714  * SUBROUTINE SHORT NAME = IGL
20715  * ========================================================================= */
20716 void Dblqh::initGciInLogFileRec(Signal* signal, Uint32 noFdDescriptors)
20717 {
20718  LogFileRecordPtr filePtr = logFilePtr;
20719  Uint32 pos = ZPAGE_HEADER_SIZE + ZFD_HEADER_SIZE;
20720  for (Uint32 fd = 0; fd < noFdDescriptors; fd++)
20721  {
20722  jam();
20723  for (Uint32 mb = 0; mb < clogFileSize; mb++)
20724  {
20725  jam();
20726  Uint32 pos0 = pos + fd * (ZFD_MBYTE_SIZE * clogFileSize) + mb;
20727  Uint32 pos1 = pos0 + clogFileSize;
20728  Uint32 pos2 = pos1 + clogFileSize;
20729  arrGuard(pos0, ZPAGE_SIZE);
20730  arrGuard(pos1, ZPAGE_SIZE);
20731  arrGuard(pos2, ZPAGE_SIZE);
20732  filePtr.p->logMaxGciCompleted[mb] = logPagePtr.p->logPageWord[pos0];
20733  filePtr.p->logMaxGciStarted[mb] = logPagePtr.p->logPageWord[pos1];
20734  filePtr.p->logLastPrepRef[mb] = logPagePtr.p->logPageWord[pos2];
20735  }
20736  if (fd + 1 < noFdDescriptors)
20737  {
20738  jam();
20739  filePtr.i = filePtr.p->prevLogFile;
20740  ptrCheckGuard(filePtr, clogFileFileSize, logFileRecord);
20741  }
20742  }
20743 }//Dblqh::initGciInLogFileRec()
20744 
20745 /* ==========================================================================
20746  * ======= INITIATE LCP RECORD WHEN USED FOR SYSTEM RESTART =======
20747  *
20748  * SUBROUTINE SHORT NAME = ILS
20749  * ========================================================================= */
20750 void Dblqh::initLcpSr(Signal* signal,
20751  Uint32 lcpNo,
20752  Uint32 lcpId,
20753  Uint32 tableId,
20754  Uint32 fragId,
20755  Uint32 fragPtr)
20756 {
20757  lcpPtr.p->lcpQueued = false;
20758  lcpPtr.p->currentFragment.fragPtrI = fragPtr;
20759  lcpPtr.p->currentFragment.lcpFragOrd.lcpNo = lcpNo;
20760  lcpPtr.p->currentFragment.lcpFragOrd.lcpId = lcpId;
20761  lcpPtr.p->currentFragment.lcpFragOrd.tableId = tableId;
20762  lcpPtr.p->currentFragment.lcpFragOrd.fragmentId = fragId;
20763  lcpPtr.p->lcpState = LcpRecord::LCP_SR_WAIT_FRAGID;
20764 }//Dblqh::initLcpSr()
20765 
20766 /* ==========================================================================
20767  * ======= INITIATE LOG PART =======
20768  *
20769  * ========================================================================= */
20770 void Dblqh::initLogpart(Signal* signal)
20771 {
20772  logPartPtr.p->execSrLogPage = RNIL;
20773  logPartPtr.p->execSrLogPageIndex = ZNIL;
20774  logPartPtr.p->execSrExecuteIndex = 0;
20775  logPartPtr.p->noLogFiles = cnoLogFiles;
20776  logPartPtr.p->logLap = 0;
20777  logPartPtr.p->logTailFileNo = 0;
20778  logPartPtr.p->logTailMbyte = 0;
20779  logPartPtr.p->lastMbyte = ZNIL;
20781  logPartPtr.p->logExecState = LogPartRecord::LES_IDLE;
20782  logPartPtr.p->firstLogTcrec = RNIL;
20783  logPartPtr.p->lastLogTcrec = RNIL;
20784  logPartPtr.p->gcprec = RNIL;
20785  logPartPtr.p->firstPageRef = RNIL;
20786  logPartPtr.p->lastPageRef = RNIL;
20787  logPartPtr.p->headFileNo = ZNIL;
20788  logPartPtr.p->headPageNo = ZNIL;
20789  logPartPtr.p->headPageIndex = ZNIL;
20790  logPartPtr.p->m_log_problems = 0;
20791  NdbLogPartInfo lpinfo(instance());
20792  ndbrequire(lpinfo.partCount == clogPartFileSize);
20793  logPartPtr.p->logPartNo = lpinfo.partNo[logPartPtr.i];
20794  logPartPtr.p->m_io_tracker.init(logPartPtr.p->logPartNo);
20795  logPartPtr.p->m_log_prepare_queue.init();
20796  logPartPtr.p->m_log_complete_queue.init();
20797 }//Dblqh::initLogpart()
20798 
20799 /* ==========================================================================
20800  * ======= INITIATE LOG POINTERS =======
20801  *
20802  * ========================================================================= */
20803 void Dblqh::initLogPointers(Signal* signal)
20804 {
20805  logPartPtr.i = tcConnectptr.p->m_log_part_ptr_i;
20806  ptrCheckGuard(logPartPtr, clogPartFileSize, logPartRecord);
20807  logFilePtr.i = logPartPtr.p->currentLogfile;
20808  ptrCheckGuard(logFilePtr, clogFileFileSize, logFileRecord);
20809  logPagePtr.i = logFilePtr.p->currentLogpage;
20810  ptrCheckGuard(logPagePtr, clogPageFileSize, logPageRecord);
20811 }//Dblqh::initLogPointers()
20812 
20813 /* ------------------------------------------------------------------------- */
20814 /* ------- INIT REQUEST INFO BEFORE EXECUTING A LOG RECORD ------- */
20815 /* */
20816 /* ------------------------------------------------------------------------- */
20817 void Dblqh::initReqinfoExecSr(Signal* signal)
20818 {
20819  UintR Treqinfo = 0;
20820  TcConnectionrec * const regTcPtr = tcConnectptr.p;
20821  LqhKeyReq::setKeyLen(Treqinfo, regTcPtr->primKeyLen);
20822 /* ------------------------------------------------------------------------- */
20823 /* NUMBER OF BACKUPS AND STANDBYS ARE ZERO AND NEED NOT BE SET. */
20824 /* REPLICA TYPE IS CLEARED BY SEND_LQHKEYREQ. */
20825 /* ------------------------------------------------------------------------- */
20826 /* ------------------------------------------------------------------------- */
20827 /* SET LAST REPLICA NUMBER TO ZERO (BIT 10-11) */
20828 /* ------------------------------------------------------------------------- */
20829 /* ------------------------------------------------------------------------- */
20830 /* SET DIRTY FLAG */
20831 /* ------------------------------------------------------------------------- */
20832  LqhKeyReq::setDirtyFlag(Treqinfo, 1);
20833 /* ------------------------------------------------------------------------- */
20834 /* SET SIMPLE TRANSACTION */
20835 /* ------------------------------------------------------------------------- */
20836  LqhKeyReq::setSimpleFlag(Treqinfo, 1);
20837  LqhKeyReq::setGCIFlag(Treqinfo, 1);
20838 /* ------------------------------------------------------------------------- */
20839 /* SET OPERATION TYPE AND LOCK MODE (NEVER READ OPERATION OR SCAN IN LOG) */
20840 /* ------------------------------------------------------------------------- */
20841  LqhKeyReq::setOperation(Treqinfo, regTcPtr->operation);
20842  regTcPtr->reqinfo = Treqinfo;
20843 /* ------------------------------------------------------------------------ */
20844 /* NO OF BACKUP IS SET TO ONE AND NUMBER OF STANDBY NODES IS SET TO ZERO. */
20845 /* THUS THE RECEIVING NODE WILL EXPECT THAT IT IS THE LAST NODE AND WILL */
20846 /* SEND COMPLETED AS THE RESPONSE SIGNAL SINCE DIRTY_OP BIT IS SET. */
20847 /* ------------------------------------------------------------------------ */
20848 /* ------------------------------------------------------------------------- */
20849 /* SET REPLICA TYPE TO PRIMARY AND NUMBER OF REPLICA TO ONE */
20850 /* ------------------------------------------------------------------------- */
20851  regTcPtr->lastReplicaNo = 0;
20852  regTcPtr->apiVersionNo = 0;
20853  regTcPtr->nextSeqNoReplica = 0;
20854  regTcPtr->opExec = 0;
20855  regTcPtr->storedProcId = ZNIL;
20856  regTcPtr->readlenAi = 0;
20857  regTcPtr->nodeAfterNext[0] = ZNIL;
20858  regTcPtr->nodeAfterNext[1] = ZNIL;
20859  regTcPtr->dirtyOp = ZFALSE;
20860  regTcPtr->tcBlockref = cownref;
20861  regTcPtr->m_reorg = 0;
20862 }//Dblqh::initReqinfoExecSr()
20863 
20864 /* --------------------------------------------------------------------------
20865  * ------- INSERT FRAGMENT -------
20866  *
20867  * ------------------------------------------------------------------------- */
20868 bool Dblqh::insertFragrec(Signal* signal, Uint32 fragId)
20869 {
20870  terrorCode = ZOK;
20871  if(c_fragment_pool.seize(fragptr) == false)
20872  {
20873  terrorCode = ZNO_FREE_FRAGMENTREC;
20874  return false;
20875  }
20876  for (Uint32 i = 0; i < MAX_FRAG_PER_NODE; i++) {
20877  jam();
20878  if (tabptr.p->fragid[i] == ZNIL) {
20879  jam();
20880  tabptr.p->fragid[i] = fragId;
20881  tabptr.p->fragrec[i] = fragptr.i;
20882  return true;
20883  }//if
20884  }//for
20885  c_fragment_pool.release(fragptr);
20886  terrorCode = ZTOO_MANY_FRAGMENTS;
20887  return false;
20888 }//Dblqh::insertFragrec()
20889 
20890 /* --------------------------------------------------------------------------
20891  * ------- LINK OPERATION IN ACTIVE LIST ON FRAGMENT -------
20892  *
20893  * SUBROUTINE SHORT NAME: LFQ
20894 // Input Pointers:
20895 // tcConnectptr
20896 // fragptr
20897 * ------------------------------------------------------------------------- */
20898 void Dblqh::linkFragQueue(Signal* signal)
20899 {
20900  TcConnectionrecPtr lfqTcConnectptr;
20901  TcConnectionrec * const regTcPtr = tcConnectptr.p;
20902  Fragrecord * const regFragPtr = fragptr.p;
20903  Uint32 tcIndex = tcConnectptr.i;
20904 
20905  lfqTcConnectptr.i = regFragPtr->lastWaitQueue;
20906  regTcPtr->nextTc = RNIL;
20907  regFragPtr->lastWaitQueue = tcIndex;
20908  regTcPtr->prevTc = lfqTcConnectptr.i;
20909  ndbrequire(regTcPtr->listState == TcConnectionrec::NOT_IN_LIST);
20910  regTcPtr->listState = TcConnectionrec::WAIT_QUEUE_LIST;
20911  if (lfqTcConnectptr.i != RNIL) {
20912  jam();
20913  ptrCheckGuard(lfqTcConnectptr, ctcConnectrecFileSize, tcConnectionrec);
20914  lfqTcConnectptr.p->nextTc = tcIndex;
20915  } else {
20916  regFragPtr->firstWaitQueue = tcIndex;
20917  }//if
20918  return;
20919 }//Dblqh::linkFragQueue()
20920 
20921 /* -------------------------------------------------------------------------
20922  * ------- LINK OPERATION INTO WAITING FOR LOGGING -------
20923  *
20924  * SUBROUTINE SHORT NAME = LWL
20925 // Input Pointers:
20926 // tcConnectptr
20927 // logPartPtr
20928  * ------------------------------------------------------------------------- */
20929 void
20930 Dblqh::linkWaitLog(Signal* signal,
20931  LogPartRecordPtr regLogPartPtr,
20932  LogPartRecord::OperationQueue & queue)
20933 {
20934  TcConnectionrecPtr lwlTcConnectptr;
20935 /* -------------------------------------------------- */
20936 /* LINK ACTIVE OPERATION INTO QUEUE WAITING FOR */
20937 /* ACCESS TO THE LOG PART. */
20938 /* -------------------------------------------------- */
20939  lwlTcConnectptr.i = queue.lastElement;
20940  if (lwlTcConnectptr.i == RNIL) {
20941  jam();
20942  queue.firstElement = tcConnectptr.i;
20943  } else {
20944  jam();
20945  ptrCheckGuard(lwlTcConnectptr, ctcConnectrecFileSize, tcConnectionrec);
20946  lwlTcConnectptr.p->nextTcLogQueue = tcConnectptr.i;
20947  }//if
20948  queue.lastElement = tcConnectptr.i;
20949  tcConnectptr.p->nextTcLogQueue = RNIL;
20950  regLogPartPtr.p->logPartState = LogPartRecord::ACTIVE;
20951  if (regLogPartPtr.p->LogLqhKeyReqSent == ZFALSE)
20952  {
20953  jam();
20954  regLogPartPtr.p->LogLqhKeyReqSent = ZTRUE;
20955  signal->theData[0] = ZLOG_LQHKEYREQ;
20956  signal->theData[1] = regLogPartPtr.i;
20957  sendSignal(cownref, GSN_CONTINUEB, signal, 2, JBB);
20958  }//if
20959 }//Dblqh::linkWaitLog()
20960 
20961 /* --------------------------------------------------------------------------
20962  * ------- START THE NEXT OPERATION ON THIS LOG PART IF ANY -------
20963  * ------- OPERATIONS ARE QUEUED. -------
20964  *
20965  * SUBROUTINE SHORT NAME = LNS
20966 // Input Pointers:
20967 // tcConnectptr
20968 // logPartPtr
20969  * ------------------------------------------------------------------------- */
20970 void Dblqh::logNextStart(Signal* signal)
20971 {
20972  LogPartRecordPtr lnsLogPartPtr;
20973  UintR tlnsStillWaiting;
20974  LogPartRecord * const regLogPartPtr = logPartPtr.p;
20975 
20976  if (regLogPartPtr->m_log_prepare_queue.isEmpty() &&
20977  regLogPartPtr->m_log_complete_queue.isEmpty() &&
20978  (regLogPartPtr->waitWriteGciLog != LogPartRecord::WWGL_TRUE))
20979  {
20980 // --------------------------------------------------------------------------
20981 // Optimised route for the common case
20982 // --------------------------------------------------------------------------
20983  return;
20984  }//if
20985 
20986  if (!regLogPartPtr->m_log_prepare_queue.isEmpty() ||
20987  !regLogPartPtr->m_log_complete_queue.isEmpty())
20988  {
20989  jam();
20990  regLogPartPtr->logPartState = LogPartRecord::ACTIVE;
20991  if (regLogPartPtr->LogLqhKeyReqSent == ZFALSE)
20992  {
20993  jam();
20994  regLogPartPtr->LogLqhKeyReqSent = ZTRUE;
20995  signal->theData[0] = ZLOG_LQHKEYREQ;
20996  signal->theData[1] = logPartPtr.i;
20997  sendSignal(cownref, GSN_CONTINUEB, signal, 2, JBB);
20998  }//if
20999  }
21000 
21001  if (regLogPartPtr->waitWriteGciLog != LogPartRecord::WWGL_TRUE)
21002  {
21003  jam();
21004  return;
21005  }
21006  else
21007  {
21008  jam();
21009 /* --------------------------------------------------------------------------
21010  * A COMPLETE GCI LOG RECORD IS WAITING TO BE WRITTEN. WE GIVE THIS HIGHEST
21011  * PRIORITY AND WRITE IT IMMEDIATELY. AFTER WRITING IT WE CHECK IF ANY MORE
21012  * LOG PARTS ARE WAITING. IF NOT WE SEND A SIGNAL THAT INITIALISES THE GCP
21013  * RECORD TO WAIT UNTIL ALL COMPLETE GCI LOG RECORDS HAVE REACHED TO DISK.
21014  * -------------------------------------------------------------------------- */
21015  writeCompletedGciLog(signal);
21016  logPartPtr.p->waitWriteGciLog = LogPartRecord::WWGL_FALSE;
21017  tlnsStillWaiting = ZFALSE;
21018  for (lnsLogPartPtr.i = 0; lnsLogPartPtr.i < clogPartFileSize; lnsLogPartPtr.i++) {
21019  jam();
21020  ptrAss(lnsLogPartPtr, logPartRecord);
21021  if (lnsLogPartPtr.p->waitWriteGciLog == LogPartRecord::WWGL_TRUE) {
21022  jam();
21023  tlnsStillWaiting = ZTRUE;
21024  }//if
21025  }//for
21026  if (tlnsStillWaiting == ZFALSE) {
21027  jam();
21028  signal->theData[0] = ZINIT_GCP_REC;
21029  sendSignal(cownref, GSN_CONTINUEB, signal, 1, JBB);
21030  }//if
21031  }//if
21032 }//Dblqh::logNextStart()
21033 
21034 /* --------------------------------------------------------------------------
21035  * ------- MOVE PAGES FROM LFO RECORD TO PAGE REFERENCE RECORD -------
21036  * WILL ALWAYS MOVE 8 PAGES TO A PAGE REFERENCE RECORD.
21037  *
21038  * SUBROUTINE SHORT NAME = MPR
21039  * ------------------------------------------------------------------------- */
21040 void Dblqh::moveToPageRef(Signal* signal)
21041 {
21042  LogPageRecordPtr mprLogPagePtr;
21043  PageRefRecordPtr mprPageRefPtr;
21044  UintR tmprIndex;
21045 
21046 /* --------------------------------------------------------------------------
21047  * ------- INSERT PAGE REFERENCE RECORD -------
21048  *
21049  * INPUT: LFO_PTR LOG FILE OPERATION RECORD
21050  * LOG_PART_PTR LOG PART RECORD
21051  * PAGE_REF_PTR THE PAGE REFERENCE RECORD TO BE INSERTED.
21052  * ------------------------------------------------------------------------- */
21053  PageRefRecordPtr iprPageRefPtr;
21054 
21055  if ((logPartPtr.p->mmBufferSize + 8) >= ZMAX_MM_BUFFER_SIZE) {
21056  jam();
21057  pageRefPtr.i = logPartPtr.p->firstPageRef;
21058  ptrCheckGuard(pageRefPtr, cpageRefFileSize, pageRefRecord);
21059  releasePrPages(signal);
21060  removePageRef(signal);
21061  } else {
21062  jam();
21063  logPartPtr.p->mmBufferSize = logPartPtr.p->mmBufferSize + 8;
21064  }//if
21065  seizePageRef(signal);
21066  if (logPartPtr.p->firstPageRef == RNIL) {
21067  jam();
21068  logPartPtr.p->firstPageRef = pageRefPtr.i;
21069  } else {
21070  jam();
21071  iprPageRefPtr.i = logPartPtr.p->lastPageRef;
21072  ptrCheckGuard(iprPageRefPtr, cpageRefFileSize, pageRefRecord);
21073  iprPageRefPtr.p->prNext = pageRefPtr.i;
21074  }//if
21075  pageRefPtr.p->prPrev = logPartPtr.p->lastPageRef;
21076  logPartPtr.p->lastPageRef = pageRefPtr.i;
21077 
21078  pageRefPtr.p->prFileNo = logFilePtr.p->fileNo;
21079  pageRefPtr.p->prPageNo = lfoPtr.p->lfoPageNo;
21080  tmprIndex = 0;
21081  mprLogPagePtr.i = lfoPtr.p->firstLfoPage;
21082 MPR_LOOP:
21083  arrGuard(tmprIndex, 8);
21084  pageRefPtr.p->pageRef[tmprIndex] = mprLogPagePtr.i;
21085  tmprIndex = tmprIndex + 1;
21086  ptrCheckGuard(mprLogPagePtr, clogPageFileSize, logPageRecord);
21087  mprLogPagePtr.i = mprLogPagePtr.p->logPageWord[ZNEXT_PAGE];
21088  if (mprLogPagePtr.i != RNIL) {
21089  jam();
21090  goto MPR_LOOP;
21091  }//if
21092  mprPageRefPtr.i = pageRefPtr.p->prPrev;
21093  if (mprPageRefPtr.i != RNIL) {
21094  jam();
21095  ptrCheckGuard(mprPageRefPtr, cpageRefFileSize, pageRefRecord);
21096  mprLogPagePtr.i = mprPageRefPtr.p->pageRef[7];
21097  ptrCheckGuard(mprLogPagePtr, clogPageFileSize, logPageRecord);
21098  mprLogPagePtr.p->logPageWord[ZNEXT_PAGE] = pageRefPtr.p->pageRef[0];
21099  }//if
21100 }//Dblqh::moveToPageRef()
21101 
21102 /* ------------------------------------------------------------------------- */
21103 /* ------- READ THE ATTRINFO FROM THE LOG ------- */
21104 /* */
21105 /* SUBROUTINE SHORT NAME = RA */
21106 /* ------------------------------------------------------------------------- */
21107 void Dblqh::readAttrinfo(Signal* signal)
21108 {
21109  Uint32 remainingLen = tcConnectptr.p->totSendlenAi;
21110  tcConnectptr.p->reclenAiLqhkey = 0;
21111  if (remainingLen == 0) {
21112  jam();
21113  return;
21114  }//if
21115 
21116  readLogData(signal, remainingLen, tcConnectptr.p->attrInfoIVal);
21117 }//Dblqh::readAttrinfo()
21118 
21119 /* ------------------------------------------------------------------------- */
21120 /* ------- READ COMMIT LOG ------- */
21121 /* */
21122 /* SUBROUTINE SHORT NAME = RCL */
21123 /* ------------------------------------------------------------------------- */
21124 void Dblqh::readCommitLog(Signal* signal, CommitLogRecord* commitLogRecord)
21125 {
21126  Uint32 trclPageIndex = logPagePtr.p->logPageWord[ZCURR_PAGE_INDEX];
21127  if ((trclPageIndex + (ZCOMMIT_LOG_SIZE - 1)) < ZPAGE_SIZE) {
21128  jam();
21129  tcConnectptr.p->tableref = logPagePtr.p->logPageWord[trclPageIndex + 0];
21130  tcConnectptr.p->schemaVersion = logPagePtr.p->logPageWord[trclPageIndex + 1];
21131  tcConnectptr.p->fragmentid = logPagePtr.p->logPageWord[trclPageIndex + 2];
21132  commitLogRecord->fileNo = logPagePtr.p->logPageWord[trclPageIndex + 3];
21133  commitLogRecord->startPageNo = logPagePtr.p->logPageWord[trclPageIndex + 4];
21134  commitLogRecord->startPageIndex = logPagePtr.p->logPageWord[trclPageIndex + 5];
21135  commitLogRecord->stopPageNo = logPagePtr.p->logPageWord[trclPageIndex + 6];
21136  tcConnectptr.p->gci_hi = logPagePtr.p->logPageWord[trclPageIndex + 7];
21137  tcConnectptr.p->gci_lo = 0;
21138  logPagePtr.p->logPageWord[ZCURR_PAGE_INDEX] =
21139  (trclPageIndex + ZCOMMIT_LOG_SIZE) - 1;
21140  } else {
21141  jam();
21142  tcConnectptr.p->tableref = readLogword(signal);
21143  tcConnectptr.p->schemaVersion = readLogword(signal);
21144  tcConnectptr.p->fragmentid = readLogword(signal);
21145  commitLogRecord->fileNo = readLogword(signal);
21146  commitLogRecord->startPageNo = readLogword(signal);
21147  commitLogRecord->startPageIndex = readLogword(signal);
21148  commitLogRecord->stopPageNo = readLogword(signal);
21149  tcConnectptr.p->gci_hi = readLogword(signal);
21150  tcConnectptr.p->gci_lo = 0;
21151  }//if
21152  tcConnectptr.p->transid[0] = logPartPtr.i + 65536;
21153  tcConnectptr.p->transid[1] = (DBLQH << 20) + (cownNodeid << 8);
21154 }//Dblqh::readCommitLog()
21155 
21156 /* ------------------------------------------------------------------------- */
21157 /* ------- READ LOG PAGES FROM DISK IN ORDER TO EXECUTE A LOG ------- */
21158 /* RECORD WHICH WAS NOT FOUND IN MAIN MEMORY. */
21159 /* */
21160 /* SUBROUTINE SHORT NAME = REL */
21161 /* ------------------------------------------------------------------------- */
21162 void Dblqh::readExecLog(Signal* signal)
21163 {
21164  UintR trelIndex;
21165  UintR trelI;
21166 
21167  seizeLfo(signal);
21168  initLfo(signal);
21169  trelI = logPartPtr.p->execSrStopPageNo - logPartPtr.p->execSrStartPageNo;
21170  arrGuard(trelI + 1, 16);
21171  lfoPtr.p->logPageArray[trelI + 1] = logPartPtr.p->execSrStartPageNo;
21172  for (trelIndex = logPartPtr.p->execSrStopPageNo; (trelIndex >= logPartPtr.p->execSrStartPageNo) &&
21173  (UintR)~trelIndex; trelIndex--) {
21174  jam();
21175  seizeLogpage(signal);
21176  arrGuard(trelI, 16);
21177  lfoPtr.p->logPageArray[trelI] = logPagePtr.i;
21178  trelI--;
21179  }//for
21180  lfoPtr.p->lfoPageNo = logPartPtr.p->execSrStartPageNo;
21181  lfoPtr.p->noPagesRw = (logPartPtr.p->execSrStopPageNo -
21182  logPartPtr.p->execSrStartPageNo) + 1;
21183  lfoPtr.p->firstLfoPage = lfoPtr.p->logPageArray[0];
21184  signal->theData[0] = logFilePtr.p->fileRef;
21185  signal->theData[1] = cownref;
21186  signal->theData[2] = lfoPtr.i;
21187  signal->theData[3] = ZLIST_OF_MEM_PAGES; // edtjamo TR509 //ZLIST_OF_PAIRS;
21188  signal->theData[4] = ZVAR_NO_LOG_PAGE_WORD;
21189  signal->theData[5] = lfoPtr.p->noPagesRw;
21190  signal->theData[6] = lfoPtr.p->logPageArray[0];
21191  signal->theData[7] = lfoPtr.p->logPageArray[1];
21192  signal->theData[8] = lfoPtr.p->logPageArray[2];
21193  signal->theData[9] = lfoPtr.p->logPageArray[3];
21194  signal->theData[10] = lfoPtr.p->logPageArray[4];
21195  signal->theData[11] = lfoPtr.p->logPageArray[5];
21196  signal->theData[12] = lfoPtr.p->logPageArray[6];
21197  signal->theData[13] = lfoPtr.p->logPageArray[7];
21198  signal->theData[14] = lfoPtr.p->logPageArray[8];
21199  signal->theData[15] = lfoPtr.p->logPageArray[9];
21200  sendSignal(NDBFS_REF, GSN_FSREADREQ, signal, 16, JBA);
21201 
21202  if (DEBUG_REDO)
21203  {
21204  ndbout_c("readExecLog %u page at part: %u file: %u page: %u (mb: %u)",
21205  lfoPtr.p->noPagesRw,
21206  logPartPtr.p->logPartNo,
21207  logFilePtr.p->fileNo,
21208  logPartPtr.p->execSrStartPageNo,
21209  logPartPtr.p->execSrStartPageNo >> ZTWOLOG_NO_PAGES_IN_MBYTE);
21210  }
21211 }//Dblqh::readExecLog()
21212 
21213 /* ------------------------------------------------------------------------- */
21214 /* ------- READ 64 KBYTES WHEN EXECUTING THE FRAGMENT LOG ------- */
21215 /* */
21216 /* SUBROUTINE SHORT NAME = RES */
21217 /* ------------------------------------------------------------------------- */
21218 void Dblqh::readExecSrNewMbyte(Signal* signal)
21219 {
21220  logFilePtr.p->currentFilepage = logFilePtr.p->currentMbyte * ZPAGES_IN_MBYTE;
21221  logFilePtr.p->filePosition = logFilePtr.p->currentMbyte * ZPAGES_IN_MBYTE;
21222  logPartPtr.p->execSrPagesRead = 0;
21223  logPartPtr.p->execSrPagesReading = 0;
21224  logPartPtr.p->execSrPagesExecuted = 0;
21225  readExecSr(signal);
21226  logPartPtr.p->logExecState = LogPartRecord::LES_WAIT_READ_EXEC_SR_NEW_MBYTE;
21227 }//Dblqh::readExecSrNewMbyte()
21228 
21229 /* ------------------------------------------------------------------------- */
21230 /* ------- READ 64 KBYTES WHEN EXECUTING THE FRAGMENT LOG ------- */
21231 /* */
21232 /* SUBROUTINE SHORT NAME = RES */
21233 /* ------------------------------------------------------------------------- */
21234 void Dblqh::readExecSr(Signal* signal)
21235 {
21236  UintR tresPageid;
21237  UintR tresIndex;
21238 
21239  tresPageid = logFilePtr.p->filePosition;
21240  seizeLfo(signal);
21241  initLfo(signal);
21242  for (tresIndex = 7; (UintR)~tresIndex; tresIndex--) {
21243  jam();
21244 /* ------------------------------------------------------------------------- */
21245 /* GO BACKWARDS SINCE WE INSERT AT THE BEGINNING AND WE WANT THAT FIRST PAGE */
21246 /* SHALL BE FIRST AND LAST PAGE LAST. */
21247 /* ------------------------------------------------------------------------- */
21248  seizeLogpage(signal);
21249  lfoPtr.p->logPageArray[tresIndex] = logPagePtr.i;
21250  }//for
21251  lfoPtr.p->lfoState = LogFileOperationRecord::READ_EXEC_SR;
21252  lfoPtr.p->lfoPageNo = tresPageid;
21253  logFilePtr.p->filePosition = logFilePtr.p->filePosition + 8;
21254  logPartPtr.p->execSrPagesReading = logPartPtr.p->execSrPagesReading + 8;
21255  lfoPtr.p->noPagesRw = 8;
21256  lfoPtr.p->firstLfoPage = lfoPtr.p->logPageArray[0];
21257  signal->theData[0] = logFilePtr.p->fileRef;
21258  signal->theData[1] = cownref;
21259  signal->theData[2] = lfoPtr.i;
21260  signal->theData[3] = ZLIST_OF_MEM_PAGES;
21261  signal->theData[4] = ZVAR_NO_LOG_PAGE_WORD;
21262  signal->theData[5] = 8;
21263  signal->theData[6] = lfoPtr.p->logPageArray[0];
21264  signal->theData[7] = lfoPtr.p->logPageArray[1];
21265  signal->theData[8] = lfoPtr.p->logPageArray[2];
21266  signal->theData[9] = lfoPtr.p->logPageArray[3];
21267  signal->theData[10] = lfoPtr.p->logPageArray[4];
21268  signal->theData[11] = lfoPtr.p->logPageArray[5];
21269  signal->theData[12] = lfoPtr.p->logPageArray[6];
21270  signal->theData[13] = lfoPtr.p->logPageArray[7];
21271  signal->theData[14] = tresPageid;
21272  sendSignal(NDBFS_REF, GSN_FSREADREQ, signal, 15, JBA);
21273 
21274  if (DEBUG_REDO)
21275  {
21276  ndbout_c("readExecSr %u page at part: %u file: %u page: %u (mb: %u)",
21277  8,
21278  logPartPtr.p->logPartNo,
21279  logFilePtr.p->fileNo,
21280  tresPageid,
21281  tresPageid >> ZTWOLOG_NO_PAGES_IN_MBYTE);
21282  }
21283 }//Dblqh::readExecSr()
21284 
21285 /* ------------------------------------------------------------------------- */
21286 /* ------------ READ THE PRIMARY KEY FROM THE LOG ---------------- */
21287 /* */
21288 /* SUBROUTINE SHORT NAME = RK */
21289 /* --------------------------------------------------------------------------*/
21290 void Dblqh::readKey(Signal* signal)
21291 {
21292  Uint32 remainingLen = tcConnectptr.p->primKeyLen;
21293  ndbrequire(remainingLen != 0);
21294 
21295  readLogData(signal, remainingLen, tcConnectptr.p->keyInfoIVal);
21296 }//Dblqh::readKey()
21297 
21298 /* ------------------------------------------------------------------------- */
21299 /* ------------ READ A NUMBER OF WORDS FROM LOG INTO CDATA ---------------- */
21300 /* */
21301 /* SUBROUTINE SHORT NAME = RLD */
21302 /* --------------------------------------------------------------------------*/
21303 void Dblqh::readLogData(Signal* signal, Uint32 noOfWords, Uint32& sectionIVal)
21304 {
21305  Uint32 logPos = logPagePtr.p->logPageWord[ZCURR_PAGE_INDEX];
21306  if ((logPos + noOfWords) >= ZPAGE_SIZE) {
21307  for (Uint32 i = 0; i < noOfWords; i++)
21308  {
21309  /* Todo : Consider reading > 1 word at a time */
21310  Uint32 word= readLogwordExec(signal);
21311  bool ok= appendToSection(sectionIVal,
21312  &word,
21313  1);
21314  ndbrequire(ok);
21315  }
21316  } else {
21317  /* In one bite */
21318  bool ok= appendToSection(sectionIVal,
21319  &logPagePtr.p->logPageWord[logPos],
21320  noOfWords);
21321  ndbrequire(ok);
21322  logPagePtr.p->logPageWord[ZCURR_PAGE_INDEX] = logPos + noOfWords;
21323  }//if
21324 }//Dblqh::readLogData()
21325 
21326 /* ------------------------------------------------------------------------- */
21327 /* ------------ READ THE LOG HEADER OF A PREPARE LOG HEADER ---------------- */
21328 /* */
21329 /* SUBROUTINE SHORT NAME = RLH */
21330 /* --------------------------------------------------------------------------*/
21331 void Dblqh::readLogHeader(Signal* signal)
21332 {
21333  Uint32 logPos = logPagePtr.p->logPageWord[ZCURR_PAGE_INDEX];
21334  if ((logPos + ZLOG_HEAD_SIZE) < ZPAGE_SIZE) {
21335  jam();
21336  tcConnectptr.p->hashValue = logPagePtr.p->logPageWord[logPos + 2];
21337  tcConnectptr.p->operation = logPagePtr.p->logPageWord[logPos + 3];
21338  tcConnectptr.p->totSendlenAi = logPagePtr.p->logPageWord[logPos + 4];
21339  tcConnectptr.p->primKeyLen = logPagePtr.p->logPageWord[logPos + 5];
21340  tcConnectptr.p->m_row_id.m_page_no = logPagePtr.p->logPageWord[logPos + 6];
21341  tcConnectptr.p->m_row_id.m_page_idx = logPagePtr.p->logPageWord[logPos+ 7];
21342  logPagePtr.p->logPageWord[ZCURR_PAGE_INDEX] = logPos + ZLOG_HEAD_SIZE;
21343  } else {
21344  jam();
21345  readLogwordExec(signal); /* IGNORE PREPARE LOG RECORD TYPE */
21346  readLogwordExec(signal); /* IGNORE LOG RECORD SIZE */
21347  tcConnectptr.p->hashValue = readLogwordExec(signal);
21348  tcConnectptr.p->operation = readLogwordExec(signal);
21349  tcConnectptr.p->totSendlenAi = readLogwordExec(signal);
21350  tcConnectptr.p->primKeyLen = readLogwordExec(signal);
21351  tcConnectptr.p->m_row_id.m_page_no = readLogwordExec(signal);
21352  tcConnectptr.p->m_row_id.m_page_idx = readLogwordExec(signal);
21353  }//if
21354 
21355  tcConnectptr.p->m_use_rowid = (tcConnectptr.p->operation == ZINSERT);
21356 }//Dblqh::readLogHeader()
21357 
21358 /* ------------------------------------------------------------------------- */
21359 /* ------- READ A WORD FROM THE LOG ------- */
21360 /* */
21361 /* OUTPUT: TLOG_WORD */
21362 /* SUBROUTINE SHORT NAME = RLW */
21363 /* ------------------------------------------------------------------------- */
21364 Uint32 Dblqh::readLogword(Signal* signal)
21365 {
21366  Uint32 logPos = logPagePtr.p->logPageWord[ZCURR_PAGE_INDEX];
21367  ndbrequire(logPos < ZPAGE_SIZE);
21368  Uint32 logWord = logPagePtr.p->logPageWord[logPos];
21369  logPos++;
21370  logPagePtr.p->logPageWord[ZCURR_PAGE_INDEX] = logPos;
21371  if (logPos >= ZPAGE_SIZE) {
21372  jam();
21373  logPagePtr.i = logPagePtr.p->logPageWord[ZNEXT_PAGE];
21374  ptrCheckGuard(logPagePtr, clogPageFileSize, logPageRecord);
21375  logPagePtr.p->logPageWord[ZCURR_PAGE_INDEX] = ZPAGE_HEADER_SIZE;
21376  logFilePtr.p->currentLogpage = logPagePtr.i;
21377  logFilePtr.p->currentFilepage++;
21378  logPartPtr.p->execSrPagesRead--;
21379  logPartPtr.p->execSrPagesExecuted++;
21380  }//if
21381  return logWord;
21382 }//Dblqh::readLogword()
21383 
21384 /* ------------------------------------------------------------------------- */
21385 /* ------- READ A WORD FROM THE LOG WHEN EXECUTING A LOG RECORD ------- */
21386 /* */
21387 /* OUTPUT: TLOG_WORD */
21388 /* SUBROUTINE SHORT NAME = RWE */
21389 /* ------------------------------------------------------------------------- */
21390 Uint32 Dblqh::readLogwordExec(Signal* signal)
21391 {
21392  Uint32 logPos = logPagePtr.p->logPageWord[ZCURR_PAGE_INDEX];
21393  ndbrequire(logPos < ZPAGE_SIZE);
21394  Uint32 logWord = logPagePtr.p->logPageWord[logPos];
21395  logPos++;
21396  logPagePtr.p->logPageWord[ZCURR_PAGE_INDEX] = logPos;
21397  if (logPos >= ZPAGE_SIZE) {
21398  jam();
21399  logPagePtr.i = logPagePtr.p->logPageWord[ZNEXT_PAGE];
21400  if (logPagePtr.i != RNIL){
21401  ptrCheckGuard(logPagePtr, clogPageFileSize, logPageRecord);
21402  logPagePtr.p->logPageWord[ZCURR_PAGE_INDEX] = ZPAGE_HEADER_SIZE;
21403  } else {
21404  // Reading word at the last pos in the last page
21405  // Don't step forward to next page!
21406  jam();
21407  logPagePtr.p->logPageWord[ZCURR_PAGE_INDEX]++;
21408  }
21409  }//if
21410  return logWord;
21411 }//Dblqh::readLogwordExec()
21412 
21413 /* ------------------------------------------------------------------------- */
21414 /* ------- READ A SINGLE PAGE FROM THE LOG ------- */
21415 /* */
21416 /* INPUT: TRSP_PAGE_NO */
21417 /* SUBROUTINE SHORT NAME = RSP */
21418 /* ------------------------------------------------------------------------- */
21419 void Dblqh::readSinglePage(Signal* signal, Uint32 pageNo)
21420 {
21421  seizeLfo(signal);
21422  initLfo(signal);
21423  seizeLogpage(signal);
21424  lfoPtr.p->firstLfoPage = logPagePtr.i;
21425  lfoPtr.p->lfoPageNo = pageNo;
21426  lfoPtr.p->noPagesRw = 1;
21427  signal->theData[0] = logFilePtr.p->fileRef;
21428  signal->theData[1] = cownref;
21429  signal->theData[2] = lfoPtr.i;
21430  signal->theData[3] = ZLIST_OF_PAIRS;
21431  signal->theData[4] = ZVAR_NO_LOG_PAGE_WORD;
21432  signal->theData[5] = 1;
21433  signal->theData[6] = logPagePtr.i;
21434  signal->theData[7] = pageNo;
21435  sendSignal(NDBFS_REF, GSN_FSREADREQ, signal, 8, JBA);
21436 
21437  if (DEBUG_REDO)
21438  {
21439  ndbout_c("readSinglePage 1 page at part: %u file: %u page: %u (mb: %u)",
21440  logPartPtr.p->logPartNo,
21441  logFilePtr.p->fileNo,
21442  pageNo,
21443  pageNo >> ZTWOLOG_NO_PAGES_IN_MBYTE);
21444  }
21445 }//Dblqh::readSinglePage()
21446 
21447 /* --------------------------------------------------------------------------
21448  * ------- REMOVE COPY FRAGMENT FROM ACTIVE COPY LIST -------
21449  *
21450  * ------------------------------------------------------------------------- */
21451 void Dblqh::releaseActiveCopy(Signal* signal)
21452 {
21453  /* MUST BE 8 BIT */
21454  UintR tracFlag;
21455  UintR tracIndex;
21456 
21457  tracFlag = ZFALSE;
21458  for (tracIndex = 0; tracIndex < 4; tracIndex++) {
21459  if (tracFlag == ZFALSE) {
21460  jam();
21461  if (cactiveCopy[tracIndex] == fragptr.i) {
21462  jam();
21463  tracFlag = ZTRUE;
21464  }//if
21465  } else {
21466  if (tracIndex < 3) {
21467  jam();
21468  cactiveCopy[tracIndex - 1] = cactiveCopy[tracIndex];
21469  } else {
21470  jam();
21471  cactiveCopy[3] = RNIL;
21472  }//if
21473  }//if
21474  }//for
21475  ndbrequire(tracFlag == ZTRUE);
21476  cnoActiveCopy--;
21477 }//Dblqh::releaseActiveCopy()
21478 
21479 
21480 /* --------------------------------------------------------------------------
21481  * ------- RELEASE ADD FRAGMENT RECORD -------
21482  *
21483  * ------------------------------------------------------------------------- */
21484 void Dblqh::releaseAddfragrec(Signal* signal)
21485 {
21486  addfragptr.p->addfragStatus = AddFragRecord::FREE;
21487  addfragptr.p->nextAddfragrec = cfirstfreeAddfragrec;
21488  cfirstfreeAddfragrec = addfragptr.i;
21489 }//Dblqh::releaseAddfragrec()
21490 
21491 /* --------------------------------------------------------------------------
21492  * ------- RELEASE A PAGE REFERENCE RECORD. -------
21493  *
21494  * ------------------------------------------------------------------------- */
21495 void Dblqh::releasePageRef(Signal* signal)
21496 {
21497  pageRefPtr.p->prNext = cfirstfreePageRef;
21498  cfirstfreePageRef = pageRefPtr.i;
21499 }//Dblqh::releasePageRef()
21500 
21501 /* --------------------------------------------------------------------------
21502  * --- RELEASE ALL PAGES IN THE MM BUFFER AFTER EXECUTING THE LOG ON IT. ----
21503  *
21504  * ------------------------------------------------------------------------- */
21505 void Dblqh::releaseMmPages(Signal* signal)
21506 {
21507 RMP_LOOP:
21508  jam();
21509  pageRefPtr.i = logPartPtr.p->firstPageRef;
21510  if (pageRefPtr.i != RNIL) {
21511  jam();
21512  ptrCheckGuard(pageRefPtr, cpageRefFileSize, pageRefRecord);
21513  releasePrPages(signal);
21514  removePageRef(signal);
21515  goto RMP_LOOP;
21516  }//if
21517 }//Dblqh::releaseMmPages()
21518 
21519 /* --------------------------------------------------------------------------
21520  * ------- RELEASE A SET OF PAGES AFTER EXECUTING THE LOG ON IT. -------
21521  *
21522  * ------------------------------------------------------------------------- */
21523 void Dblqh::releasePrPages(Signal* signal)
21524 {
21525  UintR trppIndex;
21526 
21527  for (trppIndex = 0; trppIndex <= 7; trppIndex++) {
21528  jam();
21529  logPagePtr.i = pageRefPtr.p->pageRef[trppIndex];
21530  ptrCheckGuard(logPagePtr, clogPageFileSize, logPageRecord);
21531  releaseLogpage(signal);
21532  }//for
21533 }//Dblqh::releasePrPages()
21534 
21535 /* --------------------------------------------------------------------------
21536  * ------- RELEASE OPERATION FROM WAIT QUEUE LIST ON FRAGMENT -------
21537  *
21538  * SUBROUTINE SHORT NAME : RWA
21539  * ------------------------------------------------------------------------- */
21540 void Dblqh::releaseWaitQueue(Signal* signal)
21541 {
21542  TcConnectionrecPtr rwaTcNextConnectptr;
21543  TcConnectionrecPtr rwaTcPrevConnectptr;
21544 
21545  fragptr.i = tcConnectptr.p->fragmentptr;
21546  c_fragment_pool.getPtr(fragptr);
21547  rwaTcPrevConnectptr.i = tcConnectptr.p->prevTc;
21548  rwaTcNextConnectptr.i = tcConnectptr.p->nextTc;
21549  if (tcConnectptr.p->listState != TcConnectionrec::WAIT_QUEUE_LIST) {
21550  jam();
21551  systemError(signal, __LINE__);
21552  }//if
21553  tcConnectptr.p->listState = TcConnectionrec::NOT_IN_LIST;
21554  if (rwaTcNextConnectptr.i != RNIL) {
21555  jam();
21556  ptrCheckGuard(rwaTcNextConnectptr, ctcConnectrecFileSize, tcConnectionrec);
21557  rwaTcNextConnectptr.p->prevTc = rwaTcPrevConnectptr.i;
21558  } else {
21559  jam();
21560  fragptr.p->lastWaitQueue = rwaTcPrevConnectptr.i;
21561  }//if
21562  if (rwaTcPrevConnectptr.i != RNIL) {
21563  jam();
21564  ptrCheckGuard(rwaTcPrevConnectptr, ctcConnectrecFileSize, tcConnectionrec);
21565  rwaTcPrevConnectptr.p->nextTc = rwaTcNextConnectptr.i;
21566  } else {
21567  jam();
21568  fragptr.p->firstWaitQueue = rwaTcNextConnectptr.i;
21569  }//if
21570 }//Dblqh::releaseWaitQueue()
21571 
21572 /* --------------------------------------------------------------------------
21573  * ------- REMOVE OPERATION RECORD FROM LIST ON LOG PART OF NOT -------
21574  * COMPLETED OPERATIONS IN THE LOG.
21575  *
21576  * SUBROUTINE SHORT NAME = RLO
21577  * ------------------------------------------------------------------------- */
21578 void Dblqh::removeLogTcrec(Signal* signal)
21579 {
21580  TcConnectionrecPtr rloTcNextConnectptr;
21581  TcConnectionrecPtr rloTcPrevConnectptr;
21582  rloTcPrevConnectptr.i = tcConnectptr.p->prevLogTcrec;
21583  rloTcNextConnectptr.i = tcConnectptr.p->nextLogTcrec;
21584  if (rloTcNextConnectptr.i != RNIL) {
21585  jam();
21586  ptrCheckGuard(rloTcNextConnectptr, ctcConnectrecFileSize, tcConnectionrec);
21587  rloTcNextConnectptr.p->prevLogTcrec = rloTcPrevConnectptr.i;
21588  } else {
21589  jam();
21590  logPartPtr.p->lastLogTcrec = rloTcPrevConnectptr.i;
21591  }//if
21592  if (rloTcPrevConnectptr.i != RNIL) {
21593  jam();
21594  ptrCheckGuard(rloTcPrevConnectptr, ctcConnectrecFileSize, tcConnectionrec);
21595  rloTcPrevConnectptr.p->nextLogTcrec = rloTcNextConnectptr.i;
21596  } else {
21597  jam();
21598  logPartPtr.p->firstLogTcrec = rloTcNextConnectptr.i;
21599  }//if
21600 }//Dblqh::removeLogTcrec()
21601 
21602 /* --------------------------------------------------------------------------
21603  * ------- REMOVE PAGE REFERENCE RECORD FROM LIST IN THIS LOG PART -------
21604  *
21605  * SUBROUTINE SHORT NAME = RPR
21606  * ------------------------------------------------------------------------- */
21607 void Dblqh::removePageRef(Signal* signal)
21608 {
21609  PageRefRecordPtr rprPageRefPtr;
21610 
21611  pageRefPtr.i = logPartPtr.p->firstPageRef;
21612  if (pageRefPtr.i != RNIL) {
21613  jam();
21614  ptrCheckGuard(pageRefPtr, cpageRefFileSize, pageRefRecord);
21615  if (pageRefPtr.p->prNext == RNIL) {
21616  jam();
21617  logPartPtr.p->lastPageRef = RNIL;
21618  logPartPtr.p->firstPageRef = RNIL;
21619  } else {
21620  jam();
21621  logPartPtr.p->firstPageRef = pageRefPtr.p->prNext;
21622  rprPageRefPtr.i = pageRefPtr.p->prNext;
21623  ptrCheckGuard(rprPageRefPtr, cpageRefFileSize, pageRefRecord);
21624  rprPageRefPtr.p->prPrev = RNIL;
21625  }//if
21626  releasePageRef(signal);
21627  }//if
21628 }//Dblqh::removePageRef()
21629 
21630 /* ------------------------------------------------------------------------- */
21631 /* ------- RETURN FROM EXECUTION OF LOG ------- */
21632 /* */
21633 /* ------------------------------------------------------------------------- */
21634 Uint32 Dblqh::returnExecLog(Signal* signal)
21635 {
21636  tcConnectptr.p->connectState = TcConnectionrec::CONNECTED;
21637  initLogPointers(signal);
21638  logPartPtr.p->execSrExecuteIndex++;
21639  Uint32 result = checkIfExecLog(signal);
21640  if (result == ZOK) {
21641  jam();
21642 /* ------------------------------------------------------------------------- */
21643 /* THIS LOG RECORD WILL BE EXECUTED AGAIN TOWARDS ANOTHER NODE. */
21644 /* ------------------------------------------------------------------------- */
21645  logPagePtr.i = logPartPtr.p->execSrLogPage;
21646  ptrCheckGuard(logPagePtr, clogPageFileSize, logPageRecord);
21647  logPagePtr.p->logPageWord[ZCURR_PAGE_INDEX] =
21648  logPartPtr.p->execSrLogPageIndex;
21649  } else {
21650  jam();
21651 /* ------------------------------------------------------------------------- */
21652 /* NO MORE EXECUTION OF THIS LOG RECORD. */
21653 /* ------------------------------------------------------------------------- */
21654  if (logPartPtr.p->logExecState ==
21655  LogPartRecord::LES_EXEC_LOGREC_FROM_FILE) {
21656  jam();
21657 /* ------------------------------------------------------------------------- */
21658 /* THE LOG RECORD WAS READ FROM DISK. RELEASE ITS PAGES IMMEDIATELY. */
21659 /* ------------------------------------------------------------------------- */
21660  lfoPtr.i = logPartPtr.p->execSrLfoRec;
21661  ptrCheckGuard(lfoPtr, clfoFileSize, logFileOperationRecord);
21662  releaseLfoPages(signal);
21663  releaseLfo(signal);
21664  logPartPtr.p->logExecState = LogPartRecord::LES_EXEC_LOG;
21665  if (logPartPtr.p->execSrExecLogFile != logPartPtr.p->currentLogfile) {
21666  jam();
21667  LogFileRecordPtr clfLogFilePtr;
21668  clfLogFilePtr.i = logPartPtr.p->execSrExecLogFile;
21669  ptrCheckGuard(clfLogFilePtr, clogFileFileSize, logFileRecord);
21670 #ifndef NO_REDO_OPEN_FILE_CACHE
21671  closeFile_cache(signal, clfLogFilePtr, __LINE__);
21672 #else
21673  clfLogFilePtr.p->logFileStatus = LogFileRecord::CLOSING_EXEC_LOG;
21674  closeFile(signal, clfLogFilePtr, __LINE__);
21675 #endif
21676  result = ZCLOSE_FILE;
21677  }//if
21678  }//if
21679  logPartPtr.p->execSrExecuteIndex = 0;
21680  logPartPtr.p->execSrLogPage = RNIL;
21681  logPartPtr.p->execSrLogPageIndex = ZNIL;
21682  logPagePtr.i = logFilePtr.p->currentLogpage;
21683  ptrCheckGuard(logPagePtr, clogPageFileSize, logPageRecord);
21684  logPagePtr.p->logPageWord[ZCURR_PAGE_INDEX] = logPartPtr.p->savePageIndex;
21685  }//if
21686  return result;
21687 }//Dblqh::returnExecLog()
21688 
21689 /* --------------------------------------------------------------------------
21690  * ------- SEIZE ADD FRAGMENT RECORD ------
21691  *
21692  * ------------------------------------------------------------------------- */
21693 void Dblqh::seizeAddfragrec(Signal* signal)
21694 {
21695  addfragptr.i = cfirstfreeAddfragrec;
21696  ptrCheckGuard(addfragptr, caddfragrecFileSize, addFragRecord);
21697  cfirstfreeAddfragrec = addfragptr.p->nextAddfragrec;
21698 
21699  addfragptr.p->accConnectptr = RNIL;
21700  addfragptr.p->tupConnectptr = RNIL;
21701  addfragptr.p->tuxConnectptr = RNIL;
21702  addfragptr.p->defValSectionI = RNIL;
21703  addfragptr.p->defValNextPos = 0;
21704  bzero(&addfragptr.p->m_createTabReq, sizeof(addfragptr.p->m_createTabReq));
21705  bzero(&addfragptr.p->m_lqhFragReq, sizeof(addfragptr.p->m_lqhFragReq));
21706  bzero(&addfragptr.p->m_addAttrReq, sizeof(addfragptr.p->m_addAttrReq));
21707  bzero(&addfragptr.p->m_dropFragReq, sizeof(addfragptr.p->m_dropFragReq));
21708  bzero(&addfragptr.p->m_dropTabReq, sizeof(addfragptr.p->m_dropTabReq));
21709  addfragptr.p->addfragErrorCode = 0;
21710  addfragptr.p->attrSentToTup = 0;
21711  addfragptr.p->attrReceived = 0;
21712  addfragptr.p->totalAttrReceived = 0;
21713 }//Dblqh::seizeAddfragrec()
21714 
21715 /* --------------------------------------------------------------------------
21716  * ------- SEIZE FRAGMENT RECORD -------
21717  *
21718  * ------------------------------------------------------------------------- */
21719 /* ------------------------------------------------------------------------- */
21720 /* ------- SEIZE A PAGE REFERENCE RECORD. ------- */
21721 /* */
21722 /* ------------------------------------------------------------------------- */
21723 void Dblqh::seizePageRef(Signal* signal)
21724 {
21725  pageRefPtr.i = cfirstfreePageRef;
21726  ptrCheckGuard(pageRefPtr, cpageRefFileSize, pageRefRecord);
21727  cfirstfreePageRef = pageRefPtr.p->prNext;
21728  pageRefPtr.p->prNext = RNIL;
21729 }//Dblqh::seizePageRef()
21730 
21731 /* --------------------------------------------------------------------------
21732  * ------- SEND ABORTED -------
21733  *
21734  * ------------------------------------------------------------------------- */
21735 void Dblqh::sendAborted(Signal* signal)
21736 {
21737  UintR TlastInd;
21738  if (tcConnectptr.p->nextReplica == ZNIL) {
21739  TlastInd = ZTRUE;
21740  } else {
21741  TlastInd = ZFALSE;
21742  }//if
21743  signal->theData[0] = tcConnectptr.p->tcOprec;
21744  signal->theData[1] = tcConnectptr.p->transid[0];
21745  signal->theData[2] = tcConnectptr.p->transid[1];
21746  signal->theData[3] = cownNodeid;
21747  signal->theData[4] = TlastInd;
21748  sendSignal(tcConnectptr.p->tcBlockref, GSN_ABORTED, signal, 5, JBB);
21749  return;
21750 }//Dblqh::sendAborted()
21751 
21752 /* --------------------------------------------------------------------------
21753  * ------- SEND LQH_TRANSCONF -------
21754  *
21755  * ------------------------------------------------------------------------- */
21756 void Dblqh::sendLqhTransconf(Signal* signal, LqhTransConf::OperationStatus stat)
21757 {
21758  tcNodeFailptr.i = tcConnectptr.p->tcNodeFailrec;
21759  ptrCheckGuard(tcNodeFailptr, ctcNodeFailrecFileSize, tcNodeFailRecord);
21760 
21761  Uint32 reqInfo = 0;
21762  LqhTransConf::setReplicaType(reqInfo, tcConnectptr.p->replicaType);
21763  LqhTransConf::setReplicaNo(reqInfo, tcConnectptr.p->seqNoReplica);
21764  LqhTransConf::setLastReplicaNo(reqInfo, tcConnectptr.p->lastReplicaNo);
21765  LqhTransConf::setSimpleFlag(reqInfo, tcConnectptr.p->opSimple);
21766  LqhTransConf::setDirtyFlag(reqInfo, tcConnectptr.p->dirtyOp);
21767  LqhTransConf::setOperation(reqInfo, tcConnectptr.p->operation);
21768 
21769  LqhTransConf * const lqhTransConf = (LqhTransConf *)&signal->theData[0];
21770  lqhTransConf->tcRef = tcNodeFailptr.p->newTcRef;
21771  lqhTransConf->lqhNodeId = cownNodeid;
21772  lqhTransConf->operationStatus = stat;
21773  lqhTransConf->lqhConnectPtr = tcConnectptr.i;
21774  lqhTransConf->transId1 = tcConnectptr.p->transid[0];
21775  lqhTransConf->transId2 = tcConnectptr.p->transid[1];
21776  lqhTransConf->oldTcOpRec = tcConnectptr.p->tcOprec;
21777  lqhTransConf->requestInfo = reqInfo;
21778  lqhTransConf->gci_hi = tcConnectptr.p->gci_hi;
21779  lqhTransConf->nextNodeId1 = tcConnectptr.p->nextReplica;
21780  lqhTransConf->nextNodeId2 = tcConnectptr.p->nodeAfterNext[0];
21781  lqhTransConf->nextNodeId3 = tcConnectptr.p->nodeAfterNext[1];
21782  lqhTransConf->apiRef = tcConnectptr.p->applRef;
21783  lqhTransConf->apiOpRec = tcConnectptr.p->applOprec;
21784  lqhTransConf->tableId = tcConnectptr.p->tableref;
21785  lqhTransConf->gci_lo = tcConnectptr.p->gci_lo;
21786  lqhTransConf->fragId = tcConnectptr.p->fragmentid;
21787  sendSignal(tcNodeFailptr.p->newTcBlockref, GSN_LQH_TRANSCONF,
21788  signal, LqhTransConf::SignalLength, JBB);
21789  tcNodeFailptr.p->tcRecNow = tcConnectptr.i + 1;
21790  signal->theData[0] = ZLQH_TRANS_NEXT;
21791  signal->theData[1] = tcNodeFailptr.i;
21792  sendSignal(cownref, GSN_CONTINUEB, signal, 2, JBB);
21793 
21794  if (0)
21795  {
21796  ndbout_c("sending LQH_TRANSCONF %u transid: H'%.8x, H'%.8x op: %u state: %u(%u) marker: %u",
21797  tcConnectptr.i,
21798  tcConnectptr.p->transid[0],
21799  tcConnectptr.p->transid[1],
21800  tcConnectptr.p->operation,
21801  tcConnectptr.p->transactionState,
21802  stat,
21803  tcConnectptr.p->commitAckMarker);
21804  }
21805 }//Dblqh::sendLqhTransconf()
21806 
21807 /* --------------------------------------------------------------------------
21808  * ------- START ANOTHER PHASE OF LOG EXECUTION -------
21809  * RESET THE VARIABLES NEEDED BY THIS PROCESS AND SEND THE START SIGNAL
21810  *
21811  * ------------------------------------------------------------------------- */
21812 void Dblqh::startExecSr(Signal* signal)
21813 {
21814  c_lcp_complete_fragments.first(fragptr);
21815  signal->theData[0] = fragptr.i;
21816  sendSignal(cownref, GSN_START_EXEC_SR, signal, 1, JBB);
21817 }//Dblqh::startExecSr()
21818 
21819 /* ¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤
21820  * ¤¤¤¤¤¤¤ LOG MODULE ¤¤¤¤¤¤¤
21821  * ¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤ */
21822 /* --------------------------------------------------------------------------
21823  * ------- STEP FORWARD IN FRAGMENT LOG DURING LOG EXECUTION -------
21824  *
21825  * ------------------------------------------------------------------------- */
21826 void Dblqh::stepAhead(Signal* signal, Uint32 stepAheadWords)
21827 {
21828  UintR tsaPos;
21829 
21830  tsaPos = logPagePtr.p->logPageWord[ZCURR_PAGE_INDEX];
21831  while ((stepAheadWords + tsaPos) >= ZPAGE_SIZE) {
21832  jam();
21833  logPagePtr.p->logPageWord[ZCURR_PAGE_INDEX] = ZPAGE_SIZE;
21834  stepAheadWords = stepAheadWords - (ZPAGE_SIZE - tsaPos);
21835  logFilePtr.p->currentLogpage = logPagePtr.p->logPageWord[ZNEXT_PAGE];
21836  logPagePtr.i = logPagePtr.p->logPageWord[ZNEXT_PAGE];
21837  logFilePtr.p->currentFilepage++;
21838  ptrCheckGuardErr(logPagePtr, clogPageFileSize, logPageRecord,
21839  NDBD_EXIT_SR_REDOLOG);
21840  logPagePtr.p->logPageWord[ZCURR_PAGE_INDEX] = ZPAGE_HEADER_SIZE;
21841  logPartPtr.p->execSrPagesRead--;
21842  logPartPtr.p->execSrPagesExecuted++;
21843  tsaPos = ZPAGE_HEADER_SIZE;
21844  }//while
21845  logPagePtr.p->logPageWord[ZCURR_PAGE_INDEX] = stepAheadWords + tsaPos;
21846 }//Dblqh::stepAhead()
21847 
21848 /* --------------------------------------------------------------------------
21849  * ------- WRITE A ABORT LOG RECORD -------
21850  *
21851  * SUBROUTINE SHORT NAME: WAL
21852  * ------------------------------------------------------------------------- */
21853 void Dblqh::writeAbortLog(Signal* signal)
21854 {
21855  if ((ZABORT_LOG_SIZE + ZNEXT_LOG_SIZE) >
21856  logFilePtr.p->remainingWordsInMbyte) {
21857  jam();
21858  changeMbyte(signal);
21859  }//if
21860  logFilePtr.p->remainingWordsInMbyte =
21861  logFilePtr.p->remainingWordsInMbyte - ZABORT_LOG_SIZE;
21862  writeLogWord(signal, ZABORT_TYPE);
21863  writeLogWord(signal, tcConnectptr.p->transid[0]);
21864  writeLogWord(signal, tcConnectptr.p->transid[1]);
21865 }//Dblqh::writeAbortLog()
21866 
21867 /* --------------------------------------------------------------------------
21868  * ------- WRITE A COMMIT LOG RECORD -------
21869  *
21870  * SUBROUTINE SHORT NAME: WCL
21871  * ------------------------------------------------------------------------- */
21872 void Dblqh::writeCommitLog(Signal* signal, LogPartRecordPtr regLogPartPtr)
21873 {
21874  LogFileRecordPtr regLogFilePtr;
21875  LogPageRecordPtr regLogPagePtr;
21876  TcConnectionrec * const regTcPtr = tcConnectptr.p;
21877  regLogFilePtr.i = regLogPartPtr.p->currentLogfile;
21878  ptrCheckGuard(regLogFilePtr, clogFileFileSize, logFileRecord);
21879  regLogPagePtr.i = regLogFilePtr.p->currentLogpage;
21880  Uint32 twclTmp = regLogFilePtr.p->remainingWordsInMbyte;
21881  ptrCheckGuard(regLogPagePtr, clogPageFileSize, logPageRecord);
21882  logPartPtr = regLogPartPtr;
21883  logFilePtr = regLogFilePtr;
21884  logPagePtr = regLogPagePtr;
21885  if ((ZCOMMIT_LOG_SIZE + ZNEXT_LOG_SIZE) > twclTmp) {
21886  jam();
21887  changeMbyte(signal);
21888  twclTmp = logFilePtr.p->remainingWordsInMbyte;
21889  }//if
21890 
21891  Uint32 twclLogPos = logPagePtr.p->logPageWord[ZCURR_PAGE_INDEX];
21892  Uint32 tableId = regTcPtr->tableref;
21893  Uint32 schemaVersion = regTcPtr->schemaVersion;
21894  Uint32 fragId = regTcPtr->fragmentid;
21895  Uint32 fileNo = regTcPtr->logStartFileNo;
21896  Uint32 startPageNo = regTcPtr->logStartPageNo;
21897  Uint32 pageIndex = regTcPtr->logStartPageIndex;
21898  Uint32 stopPageNo = regTcPtr->logStopPageNo;
21899  Uint32 gci = regTcPtr->gci_hi;
21900  logFilePtr.p->remainingWordsInMbyte = twclTmp - ZCOMMIT_LOG_SIZE;
21901 
21902  if ((twclLogPos + ZCOMMIT_LOG_SIZE) >= ZPAGE_SIZE) {
21903  writeLogWord(signal, ZCOMMIT_TYPE);
21904  writeLogWord(signal, tableId);
21905  writeLogWord(signal, schemaVersion);
21906  writeLogWord(signal, fragId);
21907  writeLogWord(signal, fileNo);
21908  writeLogWord(signal, startPageNo);
21909  writeLogWord(signal, pageIndex);
21910  writeLogWord(signal, stopPageNo);
21911  writeLogWord(signal, gci);
21912  } else {
21913  Uint32* dataPtr = &logPagePtr.p->logPageWord[twclLogPos];
21914  logPagePtr.p->logPageWord[ZCURR_PAGE_INDEX] = twclLogPos + ZCOMMIT_LOG_SIZE;
21915  dataPtr[0] = ZCOMMIT_TYPE;
21916  dataPtr[1] = tableId;
21917  dataPtr[2] = schemaVersion;
21918  dataPtr[3] = fragId;
21919  dataPtr[4] = fileNo;
21920  dataPtr[5] = startPageNo;
21921  dataPtr[6] = pageIndex;
21922  dataPtr[7] = stopPageNo;
21923  dataPtr[8] = gci;
21924  }//if
21925  TcConnectionrecPtr rloTcNextConnectptr;
21926  TcConnectionrecPtr rloTcPrevConnectptr;
21927  rloTcPrevConnectptr.i = regTcPtr->prevLogTcrec;
21928  rloTcNextConnectptr.i = regTcPtr->nextLogTcrec;
21929  if (rloTcNextConnectptr.i != RNIL) {
21930  jam();
21931  ptrCheckGuard(rloTcNextConnectptr, ctcConnectrecFileSize, tcConnectionrec);
21932  rloTcNextConnectptr.p->prevLogTcrec = rloTcPrevConnectptr.i;
21933  } else {
21934  regLogPartPtr.p->lastLogTcrec = rloTcPrevConnectptr.i;
21935  }//if
21936  if (rloTcPrevConnectptr.i != RNIL) {
21937  jam();
21938  ptrCheckGuard(rloTcPrevConnectptr, ctcConnectrecFileSize, tcConnectionrec);
21939  rloTcPrevConnectptr.p->nextLogTcrec = rloTcNextConnectptr.i;
21940  } else {
21941  regLogPartPtr.p->firstLogTcrec = rloTcNextConnectptr.i;
21942  }//if
21943 }//Dblqh::writeCommitLog()
21944 
21945 /* --------------------------------------------------------------------------
21946  * ------- WRITE A COMPLETED GCI LOG RECORD -------
21947  *
21948  * SUBROUTINE SHORT NAME: WCG
21949 // Input Pointers:
21950 // logFilePtr
21951 // logPartPtr
21952  * ------------------------------------------------------------------------- */
21953 void Dblqh::writeCompletedGciLog(Signal* signal)
21954 {
21955  if ((ZCOMPLETED_GCI_LOG_SIZE + ZNEXT_LOG_SIZE) >
21956  logFilePtr.p->remainingWordsInMbyte) {
21957  jam();
21958  changeMbyte(signal);
21959  }//if
21960 
21961  if (ERROR_INSERTED(5051) && (logFilePtr.p->currentFilepage > 0) &&
21962  (logFilePtr.p->currentFilepage % 32) == 0)
21963  {
21964  SET_ERROR_INSERT_VALUE(5000);
21965  }
21966 
21967  logFilePtr.p->remainingWordsInMbyte =
21968  logFilePtr.p->remainingWordsInMbyte - ZCOMPLETED_GCI_LOG_SIZE;
21969 
21970  if (DEBUG_REDO)
21971  {
21972  ndbout_c("writeCompletedGciLog gci: %u part: %u file: %u page: %u (mb: %u)",
21973  cnewestCompletedGci,
21974  logPartPtr.p->logPartNo,
21975  logFilePtr.p->fileNo,
21976  logFilePtr.p->currentFilepage,
21977  logFilePtr.p->currentFilepage >> ZTWOLOG_NO_PAGES_IN_MBYTE);
21978  }
21979 
21980  writeLogWord(signal, ZCOMPLETED_GCI_TYPE);
21981  writeLogWord(signal, cnewestCompletedGci);
21982  logPartPtr.p->logPartNewestCompletedGCI = cnewestCompletedGci;
21983 }//Dblqh::writeCompletedGciLog()
21984 
21985 /* --------------------------------------------------------------------------
21986  * ------- WRITE A DIRTY PAGE DURING LOG EXECUTION -------
21987  *
21988  * SUBROUTINE SHORT NAME: WD
21989  * ------------------------------------------------------------------------- */
21990 void Dblqh::writeDirty(Signal* signal, Uint32 place)
21991 {
21992  logPagePtr.p->logPageWord[ZPOS_DIRTY] = ZNOT_DIRTY;
21993 
21994  ndbassert(logPartPtr.p->prevFilepage ==
21995  logPagePtr.p->logPageWord[ZPOS_PAGE_NO]);
21996  writeDbgInfoPageHeader(logPagePtr, place, logPartPtr.p->prevFilepage,
21997  ZPAGE_SIZE);
21998  // Calculate checksum for page
21999  logPagePtr.p->logPageWord[ZPOS_CHECKSUM] = calcPageCheckSum(logPagePtr);
22000 
22001  seizeLfo(signal);
22002  initLfo(signal);
22003  lfoPtr.p->lfoPageNo = logPartPtr.p->prevFilepage;
22004  lfoPtr.p->noPagesRw = 1;
22005  lfoPtr.p->lfoState = LogFileOperationRecord::WRITE_DIRTY;
22006  lfoPtr.p->firstLfoPage = logPagePtr.i;
22007  signal->theData[0] = logFilePtr.p->fileRef;
22008  signal->theData[1] = cownref;
22009  signal->theData[2] = lfoPtr.i;
22010  signal->theData[3] = ZLIST_OF_PAIRS_SYNCH;
22011  signal->theData[4] = ZVAR_NO_LOG_PAGE_WORD;
22012  signal->theData[5] = 1;
22013  signal->theData[6] = logPagePtr.i;
22014  signal->theData[7] = logPartPtr.p->prevFilepage;
22015  sendSignal(NDBFS_REF, GSN_FSWRITEREQ, signal, 8, JBA);
22016 
22017  ndbrequire(logFilePtr.p->fileRef != RNIL);
22018 
22019  logPartPtr.p->m_io_tracker.send_io(32768);
22020 
22021  if (DEBUG_REDO)
22022  {
22023  ndbout_c("writeDirty 1 page at part: %u file: %u page: %u (mb: %u)",
22024  logPartPtr.p->logPartNo,
22025  logFilePtr.p->fileNo,
22026  logPartPtr.p->prevFilepage,
22027  logPartPtr.p->prevFilepage >> ZTWOLOG_NO_PAGES_IN_MBYTE);
22028  }
22029 }//Dblqh::writeDirty()
22030 
22031 /* --------------------------------------------------------------------------
22032  * ------- WRITE A WORD INTO THE LOG, CHECK FOR NEW PAGE -------
22033  *
22034  * SUBROUTINE SHORT NAME: WLW
22035  * ------------------------------------------------------------------------- */
22036 void Dblqh::writeLogWord(Signal* signal, Uint32 data)
22037 {
22038  Uint32 logPos = logPagePtr.p->logPageWord[ZCURR_PAGE_INDEX];
22039  ndbrequire(logPos < ZPAGE_SIZE);
22040  logPagePtr.p->logPageWord[logPos] = data;
22041  logPagePtr.p->logPageWord[ZCURR_PAGE_INDEX] = logPos + 1;
22042  if ((logPos + 1) == ZPAGE_SIZE) {
22043  jam();
22044  completedLogPage(signal, ZNORMAL, __LINE__);
22045  seizeLogpage(signal);
22046  initLogpage(signal);
22047  logFilePtr.p->currentLogpage = logPagePtr.i;
22048  logFilePtr.p->currentFilepage++;
22049  }//if
22050 }//Dblqh::writeLogWord()
22051 
22052 /* --------------------------------------------------------------------------
22053  * ------- WRITE MULTIPLE WORDS INTO THE LOG, CHECK FOR NEW PAGES -------
22054  *
22055  * ------------------------------------------------------------------------- */
22056 
22057 void Dblqh::writeLogWords(Signal* signal, const Uint32* data, Uint32 len)
22058 {
22059  Uint32 logPos = logPagePtr.p->logPageWord[ZCURR_PAGE_INDEX];
22060  ndbrequire(logPos < ZPAGE_SIZE);
22061  Uint32 wordsThisPage= ZPAGE_SIZE - logPos;
22062 
22063  while (len >= wordsThisPage)
22064  {
22065  /* Fill rest of the log page */
22066  MEMCOPY_NO_WORDS(&logPagePtr.p->logPageWord[logPos],
22067  data,
22068  wordsThisPage);
22069  logPagePtr.p->logPageWord[ZCURR_PAGE_INDEX] = ZPAGE_SIZE;
22070  data+= wordsThisPage;
22071  len-= wordsThisPage;
22072 
22073  /* Mark page completed and get a new one */
22074  jam();
22075  completedLogPage(signal, ZNORMAL, __LINE__);
22076  seizeLogpage(signal);
22077  initLogpage(signal);
22078  logFilePtr.p->currentLogpage = logPagePtr.i;
22079  logFilePtr.p->currentFilepage++;
22080 
22081  logPos = logPagePtr.p->logPageWord[ZCURR_PAGE_INDEX];
22082  ndbrequire(logPos < ZPAGE_SIZE);
22083  wordsThisPage= ZPAGE_SIZE - logPos;
22084  }
22085 
22086  if (len > 0)
22087  {
22088  /* No need to worry about next page */
22089  ndbassert( len < wordsThisPage );
22090  /* Write partial log page */
22091  MEMCOPY_NO_WORDS(&logPagePtr.p->logPageWord[logPos],
22092  data,
22093  len);
22094  logPagePtr.p->logPageWord[ZCURR_PAGE_INDEX] = logPos + len;
22095  }
22096 
22097  ndbassert( logPagePtr.p->logPageWord[ZCURR_PAGE_INDEX] < ZPAGE_SIZE );
22098 }
22099 
22100 /* --------------------------------------------------------------------------
22101  * ------- WRITE A NEXT LOG RECORD AND CHANGE TO NEXT MBYTE -------
22102  *
22103  * SUBROUTINE SHORT NAME: WNL
22104 // Input Pointers:
22105 // logFilePtr(Redefines)
22106 // logPagePtr (Redefines)
22107 // logPartPtr
22108  * ------------------------------------------------------------------------- */
22109 void Dblqh::writeNextLog(Signal* signal)
22110 {
22111  LogFileRecordPtr wnlNextLogFilePtr;
22112  UintR twnlNextFileNo;
22113  UintR twnlNewMbyte;
22114  UintR twnlRemWords;
22115  UintR twnlNextMbyte;
22116 
22117 /* -------------------------------------------------- */
22118 /* CALCULATE THE NEW NUMBER OF REMAINING WORDS */
22119 /* AS 128*2036 WHERE 128 * 8 KBYTE = 1 MBYTE */
22120 /* AND 2036 IS THE NUMBER OF WORDS IN A PAGE */
22121 /* THAT IS USED FOR LOG INFORMATION. */
22122 /* -------------------------------------------------- */
22123  twnlRemWords = ZPAGE_SIZE - ZPAGE_HEADER_SIZE;
22124  twnlRemWords = twnlRemWords * ZPAGES_IN_MBYTE;
22125  wnlNextLogFilePtr.i = logFilePtr.p->nextLogFile;
22126  ptrCheckGuard(wnlNextLogFilePtr, clogFileFileSize, logFileRecord);
22127 /* -------------------------------------------------- */
22128 /* WRITE THE NEXT LOG RECORD. */
22129 /* -------------------------------------------------- */
22130  ndbrequire(logPagePtr.p->logPageWord[ZCURR_PAGE_INDEX] < ZPAGE_SIZE);
22131  logPagePtr.p->logPageWord[logPagePtr.p->logPageWord[ZCURR_PAGE_INDEX]] =
22132  ZNEXT_MBYTE_TYPE;
22133  if (logFilePtr.p->currentMbyte == (clogFileSize - 1)) {
22134  jam();
22135 /* -------------------------------------------------- */
22136 /* CALCULATE THE NEW REMAINING WORDS WHEN */
22137 /* CHANGING LOG FILE IS PERFORMED */
22138 /* -------------------------------------------------- */
22139  twnlRemWords = twnlRemWords - (ZPAGE_SIZE - ZPAGE_HEADER_SIZE);
22140 /* -------------------------------------------------- */
22141 /* ENSURE THAT THE LOG PAGES ARE WRITTEN AFTER */
22142 /* WE HAVE CHANGED MBYTE. */
22143 /* -------------------------------------------------- */
22144 /* ENSURE LAST PAGE IN PREVIOUS MBYTE IS */
22145 /* WRITTEN AND THAT THE STATE OF THE WRITE IS */
22146 /* PROPERLY SET. */
22147 /* -------------------------------------------------- */
22148 /* WE HAVE TO CHANGE LOG FILE */
22149 /* -------------------------------------------------- */
22150  completedLogPage(signal, ZLAST_WRITE_IN_FILE, __LINE__);
22151  if (wnlNextLogFilePtr.p->fileNo == 0) {
22152  jam();
22153 /* -------------------------------------------------- */
22154 /* WE HAVE FINALISED A LOG LAP, START FROM LOG */
22155 /* FILE 0 AGAIN */
22156 /* -------------------------------------------------- */
22157  logPartPtr.p->logLap++;
22158  }//if
22159  logPartPtr.p->currentLogfile = wnlNextLogFilePtr.i;
22160  logFilePtr.i = wnlNextLogFilePtr.i;
22161  logFilePtr.p = wnlNextLogFilePtr.p;
22162  twnlNewMbyte = 0;
22163  } else {
22164  jam();
22165 /* -------------------------------------------------- */
22166 /* INCREMENT THE CURRENT MBYTE */
22167 /* SET PAGE INDEX TO PAGE HEADER SIZE */
22168 /* -------------------------------------------------- */
22169  completedLogPage(signal, ZENFORCE_WRITE, __LINE__);
22170  twnlNewMbyte = logFilePtr.p->currentMbyte + 1;
22171  }//if
22172 /* -------------------------------------------------- */
22173 /* CHANGE TO NEW LOG FILE IF NECESSARY */
22174 /* UPDATE THE FILE POSITION TO THE NEW MBYTE */
22175 /* FOUND IN PAGE PART OF TNEXT_LOG_PTR */
22176 /* ALLOCATE AND INITIATE A NEW PAGE SINCE WE */
22177 /* HAVE SENT THE PREVIOUS PAGE TO DISK. */
22178 /* SET THE NEW NUMBER OF REMAINING WORDS IN THE */
22179 /* NEW MBYTE ALLOCATED. */
22180 /* -------------------------------------------------- */
22181  logFilePtr.p->currentMbyte = twnlNewMbyte;
22182  logFilePtr.p->filePosition = twnlNewMbyte * ZPAGES_IN_MBYTE;
22183  logFilePtr.p->currentFilepage = twnlNewMbyte * ZPAGES_IN_MBYTE;
22184  logFilePtr.p->remainingWordsInMbyte = twnlRemWords;
22185  seizeLogpage(signal);
22186  if (logFilePtr.p->currentMbyte == 0) {
22187  jam();
22188  logFilePtr.p->lastPageWritten = 0;
22189  if (logFilePtr.p->fileNo == 0) {
22190  jam();
22191  releaseLogpage(signal);
22192  logPagePtr.i = logFilePtr.p->logPageZero;
22193  ptrCheckGuard(logPagePtr, clogPageFileSize, logPageRecord);
22194  }//if
22195  }//if
22196  initLogpage(signal);
22197  logFilePtr.p->currentLogpage = logPagePtr.i;
22198  if (logFilePtr.p->currentMbyte == 0) {
22199  jam();
22200 /* -------------------------------------------------- */
22201 /* THIS IS A NEW FILE, WRITE THE FILE DESCRIPTOR*/
22202 /* ALSO OPEN THE NEXT LOG FILE TO ENSURE THAT */
22203 /* THIS FILE IS OPEN WHEN ITS TURN COMES. */
22204 /* -------------------------------------------------- */
22205  writeFileHeaderOpen(signal, ZNORMAL);
22206  openNextLogfile(signal);
22207  logFilePtr.p->fileChangeState = LogFileRecord::BOTH_WRITES_ONGOING;
22208  }//if
22209  if (logFilePtr.p->fileNo == logPartPtr.p->logTailFileNo)
22210  {
22211  if (logFilePtr.p->currentMbyte == logPartPtr.p->logTailMbyte)
22212  {
22213  jam();
22214 /* -------------------------------------------------- */
22215 /* THE HEAD AND TAIL HAS MET. THIS SHOULD NEVER */
22216 /* OCCUR. CAN HAPPEN IF THE LOCAL CHECKPOINTS */
22217 /* TAKE FAR TOO LONG TIME. SO TIMING PROBLEMS */
22218 /* CAN INVOKE THIS SYSTEM CRASH. HOWEVER ONLY */
22219 /* VERY SERIOUS TIMING PROBLEMS. */
22220 /* -------------------------------------------------- */
22221  char buf[100];
22222  BaseString::snprintf(buf, sizeof(buf),
22223  "Head/Tail met in REDO log, logpart: %u"
22224  " file: %u mbyte: %u state: %u log-problem: %u",
22225  logPartPtr.p->logPartNo,
22226  logFilePtr.p->fileNo,
22227  logFilePtr.p->currentMbyte,
22228  logPartPtr.p->logPartState,
22229  logPartPtr.p->m_log_problems);
22230 
22231 
22232  signal->theData[0] = 2398;
22233  execDUMP_STATE_ORD(signal);
22234  progError(__LINE__, NDBD_EXIT_NO_MORE_REDOLOG, buf);
22235  systemError(signal, __LINE__);
22236  }//if
22237  }//if
22238  if (logFilePtr.p->currentMbyte == (clogFileSize - 1)) {
22239  jam();
22240  twnlNextMbyte = 0;
22241  if (logFilePtr.p->fileChangeState != LogFileRecord::NOT_ONGOING)
22242  {
22243  jam();
22244  update_log_problem(signal, logPartPtr,
22245  LogPartRecord::P_FILE_CHANGE_PROBLEM,
22246  /* set */ true);
22247  }//if
22248  twnlNextFileNo = wnlNextLogFilePtr.p->fileNo;
22249  } else {
22250  jam();
22251  twnlNextMbyte = logFilePtr.p->currentMbyte + 1;
22252  twnlNextFileNo = logFilePtr.p->fileNo;
22253  }//if
22254 
22255  LogPosition head = { twnlNextFileNo, twnlNextMbyte };
22256  LogPosition tail = { logPartPtr.p->logTailFileNo, logPartPtr.p->logTailMbyte};
22257  Uint64 free_mb = free_log(head, tail, logPartPtr.p->noLogFiles, clogFileSize);
22258  if (free_mb <= c_free_mb_force_lcp_limit)
22259  {
22260  jam();
22261  force_lcp(signal);
22262  }
22263 
22264  if (free_mb <= c_free_mb_tail_problem_limit)
22265  {
22266  jam();
22267  update_log_problem(signal, logPartPtr, LogPartRecord::P_TAIL_PROBLEM, true);
22268  }
22269 
22270  if (ERROR_INSERTED(5058) &&
22271  (twnlNextMbyte + 3 >= clogFileSize) &&
22272  logFilePtr.p->fileNo != 0 &&
22273  logFilePtr.p->nextLogFile != logPartPtr.p->firstLogfile)
22274  {
22275  jam();
22276  srand((int)time(0));
22277  Uint32 wait = 3 + (rand() % 5);
22278 
22279  suspendFile(signal, logFilePtr, /* forever */ 0);
22280  suspendFile(signal, logPartPtr.p->firstLogfile, /* forever */ 0);
22281  signal->theData[0] = 9999;
22282  sendSignalWithDelay(CMVMI_REF, GSN_NDB_TAMPER, signal, wait * 1000, 1);
22283  CLEAR_ERROR_INSERT_VALUE;
22284  }
22285 
22286  if (ERROR_INSERTED(5059) &&
22287  twnlNextMbyte == 4 &&
22288  logFilePtr.p->fileNo != 0)
22289  {
22290  signal->theData[0] = 9999;
22291  sendSignal(CMVMI_REF, GSN_NDB_TAMPER, signal, 1, JBA);
22292  }
22293 
22294 }//Dblqh::writeNextLog()
22295 
22296 bool
22297 Dblqh::validate_filter(Signal* signal)
22298 {
22299  Uint32 * start = signal->theData + 1;
22300  Uint32 * end = signal->theData + signal->getLength();
22301  if (start == end)
22302  {
22303  infoEvent("No filter specified, not listing...");
22304  if (!ERROR_INSERTED(4002))
22305  return false;
22306  else
22307  return true;
22308  }
22309 
22310  while(start < end)
22311  {
22312  switch(* start){
22313  case 0: // Table
22314  case 1: // API Node
22315  case 3: // TC Node
22316  start += 2;
22317  break;
22318  case 2: // Transid
22319  start += 3;
22320  break;
22321  default:
22322  infoEvent("Invalid filter op: 0x%x pos: %ld",
22323  * start,
22324  (long int)(start - (signal->theData + 1)));
22325  return false;
22326  }
22327  }
22328 
22329  if (start != end)
22330  {
22331  infoEvent("Invalid filter, unexpected end");
22332  return false;
22333  }
22334 
22335  return true;
22336 }
22337 
22338 bool
22339 Dblqh::match_and_print(Signal* signal, Ptr<TcConnectionrec> tcRec)
22340 {
22341  Uint32 len = signal->getLength();
22342  Uint32* start = signal->theData + 3;
22343  Uint32* end = signal->theData + len;
22344  while (start < end)
22345  {
22346  switch(* start){
22347  case 0:
22348  if (tcRec.p->tableref != * (start + 1))
22349  return false;
22350  start += 2;
22351  break;
22352  case 1:
22353  if (refToNode(tcRec.p->applRef) != * (start + 1))
22354  return false;
22355  start += 2;
22356  break;
22357  case 2:
22358  if (tcRec.p->transid[0] != * (start + 1) ||
22359  tcRec.p->transid[1] != * (start + 2))
22360  return false;
22361  start += 3;
22362  break;
22363  case 3:
22364  if (refToNode(tcRec.p->tcBlockref) != * (start + 1))
22365  return false;
22366  start += 2;
22367  break;
22368  default:
22369  ndbassert(false);
22370  return false;
22371  }
22372  }
22373 
22374  if (start != end)
22375  {
22376  ndbassert(false);
22377  return false;
22378  }
22379 
22383  Uint32 *temp = signal->theData + 25;
22384  memcpy(temp, signal->theData, 4 * len);
22385 
22386  char state[20];
22387  const char* op = "<Unknown>";
22388  if (tcRec.p->tcScanRec != RNIL)
22389  {
22390  ScanRecordPtr sp;
22391  sp.i = tcRec.p->tcScanRec;
22392  c_scanRecordPool.getPtr(sp);
22393 
22394  if (sp.p->scanLockMode)
22395  op = "SCAN-EX";
22396  else if(sp.p->scanLockHold)
22397  op = "SCAN-SH";
22398  else
22399  op = "SCAN";
22400 
22401  switch(sp.p->scanState){
22402  case ScanRecord::WAIT_NEXT_SCAN:
22403  BaseString::snprintf(state, sizeof(state), "WaitNextScan");
22404  break;
22405  case ScanRecord::IN_QUEUE:
22406  BaseString::snprintf(state, sizeof(state), "InQueue");
22407  break;
22408  case ScanRecord::SCAN_FREE:
22409  case ScanRecord::WAIT_STORED_PROC_COPY:
22410  case ScanRecord::WAIT_STORED_PROC_SCAN:
22411  case ScanRecord::WAIT_NEXT_SCAN_COPY:
22412  case ScanRecord::WAIT_DELETE_STORED_PROC_ID_SCAN:
22413  case ScanRecord::WAIT_DELETE_STORED_PROC_ID_COPY:
22414  case ScanRecord::WAIT_ACC_COPY:
22415  case ScanRecord::WAIT_ACC_SCAN:
22416  case ScanRecord::WAIT_SCAN_NEXTREQ:
22417  case ScanRecord::WAIT_CLOSE_SCAN:
22418  case ScanRecord::WAIT_CLOSE_COPY:
22419  case ScanRecord::WAIT_RELEASE_LOCK:
22420  case ScanRecord::WAIT_TUPKEY_COPY:
22421  case ScanRecord::WAIT_LQHKEY_COPY:
22422  BaseString::snprintf(state, sizeof(state), "%u", sp.p->scanState);
22423  }
22424  }
22425  else
22426  {
22427  switch(tcRec.p->operation){
22428  case ZREAD:
22429  if (tcRec.p->lockType)
22430  op = "READ-EX";
22431  else if(!tcRec.p->dirtyOp)
22432  op = "READ-SH";
22433  else
22434  op = "READ";
22435  break;
22436  case ZINSERT: op = "INSERT"; break;
22437  case ZUPDATE: op = "UPDATE"; break;
22438  case ZDELETE: op = "DELETE"; break;
22439  case ZWRITE: op = "WRITE"; break;
22440  case ZUNLOCK: op = "UNLOCK"; break;
22441  }
22442 
22443  switch(tcRec.p->transactionState){
22444  case TcConnectionrec::IDLE:
22445  case TcConnectionrec::WAIT_ACC:
22446  BaseString::snprintf(state, sizeof(state), "In lock queue");
22447  break;
22448  case TcConnectionrec::WAIT_TUPKEYINFO:
22449  case TcConnectionrec::WAIT_ATTR:
22450  BaseString::snprintf(state, sizeof(state), "WaitData");
22451  break;
22452  case TcConnectionrec::WAIT_TUP:
22453  BaseString::snprintf(state, sizeof(state), "Running");
22454  break;
22455  case TcConnectionrec::WAIT_TUP_COMMIT:
22456  BaseString::snprintf(state, sizeof(state), "Committing");
22457  break;
22458  case TcConnectionrec::PREPARED:
22459  BaseString::snprintf(state, sizeof(state), "Prepared");
22460  break;
22461  case TcConnectionrec::COMMITTED:
22462  BaseString::snprintf(state, sizeof(state), "Committed");
22463  break;
22464  case TcConnectionrec::STOPPED:
22465  case TcConnectionrec::LOG_QUEUED:
22466  case TcConnectionrec::LOG_COMMIT_WRITTEN_WAIT_SIGNAL:
22467  case TcConnectionrec::LOG_COMMIT_QUEUED_WAIT_SIGNAL:
22468  case TcConnectionrec::COMMIT_STOPPED:
22469  case TcConnectionrec::LOG_COMMIT_QUEUED:
22470  case TcConnectionrec::COMMIT_QUEUED:
22471  case TcConnectionrec::WAIT_ACC_ABORT:
22472  case TcConnectionrec::ABORT_QUEUED:
22473  case TcConnectionrec::ABORT_STOPPED:
22474  case TcConnectionrec::WAIT_AI_AFTER_ABORT:
22475  case TcConnectionrec::LOG_ABORT_QUEUED:
22476  case TcConnectionrec::WAIT_TUP_TO_ABORT:
22477  case TcConnectionrec::WAIT_SCAN_AI:
22478  case TcConnectionrec::SCAN_STATE_USED:
22479  case TcConnectionrec::SCAN_FIRST_STOPPED:
22480  case TcConnectionrec::SCAN_CHECK_STOPPED:
22481  case TcConnectionrec::SCAN_STOPPED:
22482  case TcConnectionrec::SCAN_RELEASE_STOPPED:
22483  case TcConnectionrec::SCAN_CLOSE_STOPPED:
22484  case TcConnectionrec::COPY_CLOSE_STOPPED:
22485  case TcConnectionrec::COPY_FIRST_STOPPED:
22486  case TcConnectionrec::COPY_STOPPED:
22487  case TcConnectionrec::SCAN_TUPKEY:
22488  case TcConnectionrec::COPY_TUPKEY:
22489  case TcConnectionrec::TC_NOT_CONNECTED:
22490  case TcConnectionrec::PREPARED_RECEIVED_COMMIT:
22491  case TcConnectionrec::LOG_COMMIT_WRITTEN:
22492  BaseString::snprintf(state, sizeof(state), "%u",
22493  tcRec.p->transactionState);
22494  }
22495  }
22496 
22497  char buf[100];
22498  BaseString::snprintf(buf, sizeof(buf),
22499  "OP[%u]: Tab: %d frag: %d TC: %u API: %d(0x%x)"
22500  "transid: H'%.8x H'%.8x op: %s state: %s",
22501  tcRec.i,
22502  tcRec.p->tableref,
22503  tcRec.p->fragmentid,
22504  refToNode(tcRec.p->tcBlockref),
22505  refToNode(tcRec.p->applRef),
22506  refToBlock(tcRec.p->applRef),
22507  tcRec.p->transid[0], tcRec.p->transid[1],
22508  op,
22509  state);
22510 
22511  if (!ERROR_INSERTED(4002))
22512  infoEvent("%s", buf);
22513  else
22514  ndbout_c("%s", buf);
22515 
22516  memcpy(signal->theData, temp, 4*len);
22517  return true;
22518 }
22519 
22520 void
22521 Dblqh::execDUMP_STATE_ORD(Signal* signal)
22522 {
22523  jamEntry();
22524  DumpStateOrd * const dumpState = (DumpStateOrd *)&signal->theData[0];
22525  Uint32 arg= dumpState->args[0];
22526  if(dumpState->args[0] == DumpStateOrd::CommitAckMarkersSize){
22527  infoEvent("LQH: m_commitAckMarkerPool: %d free size: %d",
22528  m_commitAckMarkerPool.getNoOfFree(),
22529  m_commitAckMarkerPool.getSize());
22530  }
22531  if(dumpState->args[0] == DumpStateOrd::CommitAckMarkersDump){
22532  infoEvent("LQH: m_commitAckMarkerPool: %d free size: %d",
22533  m_commitAckMarkerPool.getNoOfFree(),
22534  m_commitAckMarkerPool.getSize());
22535 
22536  CommitAckMarkerIterator iter;
22537  for(m_commitAckMarkerHash.first(iter); iter.curr.i != RNIL;
22538  m_commitAckMarkerHash.next(iter)){
22539  infoEvent("CommitAckMarker: i = %d (H'%.8x, H'%.8x)"
22540  " ApiRef: 0x%x apiOprec: 0x%x TcNodeId: %d, ref_count: %u",
22541  iter.curr.i,
22542  iter.curr.p->transid1,
22543  iter.curr.p->transid2,
22544  iter.curr.p->apiRef,
22545  iter.curr.p->apiOprec,
22546  iter.curr.p->tcNodeId,
22547  iter.curr.p->reference_count);
22548  }
22549  }
22550 
22551  // Dump info about number of log pages
22552  if(dumpState->args[0] == DumpStateOrd::LqhDumpNoLogPages){
22553  infoEvent("LQH: Log pages : %d Free: %d",
22554  clogPageFileSize,
22555  cnoOfLogPages);
22556  }
22557 
22558  // Dump all defined tables that LQH knowns about
22559  if(dumpState->args[0] == DumpStateOrd::LqhDumpAllDefinedTabs){
22560  for(Uint32 i = 0; i<ctabrecFileSize; i++){
22561  TablerecPtr tabPtr;
22562  tabPtr.i = i;
22563  ptrAss(tabPtr, tablerec);
22564  if(tabPtr.p->tableStatus != Tablerec::NOT_DEFINED){
22565  infoEvent("Table %d Status: %d Usage: [ r: %u w: %u ]",
22566  i, tabPtr.p->tableStatus,
22567  tabPtr.p->usageCountR, tabPtr.p->usageCountW);
22568 
22569  for (Uint32 j = 0; j<MAX_FRAG_PER_NODE; j++)
22570  {
22571  FragrecordPtr fragPtr;
22572  if ((fragPtr.i = tabPtr.p->fragrec[j]) != RNIL)
22573  {
22574  c_fragment_pool.getPtr(fragPtr);
22575  infoEvent(" frag: %d distKey: %u",
22576  tabPtr.p->fragid[j],
22577  fragPtr.p->fragDistributionKey);
22578  }
22579  }
22580  }
22581  }
22582  return;
22583  }
22584 
22585  // Dump all ScanRecords
22586  if (dumpState->args[0] == DumpStateOrd::LqhDumpAllScanRec){
22587  Uint32 recordNo = 0;
22588  if (signal->length() == 1)
22589  infoEvent("LQH: Dump all ScanRecords - size: %d",
22590  cscanrecFileSize);
22591  else if (signal->length() == 2)
22592  recordNo = dumpState->args[1];
22593  else
22594  return;
22595 
22596  dumpState->args[0] = DumpStateOrd::LqhDumpOneScanRec;
22597  dumpState->args[1] = recordNo;
22598  execDUMP_STATE_ORD(signal);
22599 
22600  if (recordNo < cscanrecFileSize-1){
22601  dumpState->args[0] = DumpStateOrd::LqhDumpAllScanRec;
22602  dumpState->args[1] = recordNo+1;
22603  sendSignal(reference(), GSN_DUMP_STATE_ORD, signal, 2, JBB);
22604  }
22605  return;
22606  }
22607 
22608  // Dump all active ScanRecords
22609  if (dumpState->args[0] == DumpStateOrd::LqhDumpAllActiveScanRec){
22610  Uint32 recordNo = 0;
22611  if (signal->length() == 1)
22612  infoEvent("LQH: Dump active ScanRecord - size: %d",
22613  cscanrecFileSize);
22614  else if (signal->length() == 2)
22615  recordNo = dumpState->args[1];
22616  else
22617  return;
22618 
22619  ScanRecordPtr sp;
22620  sp.i = recordNo;
22621  c_scanRecordPool.getPtr(sp);
22622  if (sp.p->scanState != ScanRecord::SCAN_FREE){
22623  dumpState->args[0] = DumpStateOrd::LqhDumpOneScanRec;
22624  dumpState->args[1] = recordNo;
22625  execDUMP_STATE_ORD(signal);
22626  }
22627 
22628  if (recordNo < cscanrecFileSize-1){
22629  dumpState->args[0] = DumpStateOrd::LqhDumpAllActiveScanRec;
22630  dumpState->args[1] = recordNo+1;
22631  sendSignal(reference(), GSN_DUMP_STATE_ORD, signal, 2, JBB);
22632  }
22633  return;
22634  }
22635 
22636  if(dumpState->args[0] == DumpStateOrd::LqhDumpOneScanRec){
22637  Uint32 recordNo = RNIL;
22638  if (signal->length() == 2)
22639  recordNo = dumpState->args[1];
22640  else
22641  return;
22642 
22643  if (recordNo >= cscanrecFileSize)
22644  return;
22645 
22646  ScanRecordPtr sp;
22647  sp.i = recordNo;
22648  c_scanRecordPool.getPtr(sp);
22649  infoEvent("Dblqh::ScanRecord[%d]: state=%d, type=%d, "
22650  "complStatus=%d, scanNodeId=%d",
22651  sp.i,
22652  sp.p->scanState,
22653  sp.p->scanType,
22654  sp.p->scanCompletedStatus,
22655  sp.p->scanNodeId);
22656  infoEvent(" apiBref=0x%x, scanAccPtr=%d",
22657  sp.p->scanApiBlockref,
22658  sp.p->scanAccPtr);
22659  infoEvent(" copyptr=%d, ailen=%d, complOps=%d, concurrOps=%d",
22660  sp.p->copyPtr,
22661  sp.p->scanAiLength,
22662  sp.p->m_curr_batch_size_rows,
22663  sp.p->m_max_batch_size_rows);
22664  infoEvent(" errCnt=%d, schV=%d",
22665  sp.p->scanErrorCounter,
22666  sp.p->scanSchemaVersion);
22667  infoEvent(" stpid=%d, flag=%d, lhold=%d, lmode=%d, num=%d",
22668  sp.p->scanStoredProcId,
22669  sp.p->scanFlag,
22670  sp.p->scanLockHold,
22671  sp.p->scanLockMode,
22672  sp.p->scanNumber);
22673  infoEvent(" relCount=%d, TCwait=%d, TCRec=%d, KIflag=%d",
22674  sp.p->scanReleaseCounter,
22675  sp.p->scanTcWaiting,
22676  sp.p->scanTcrec,
22677  sp.p->scanKeyinfoFlag);
22678  return;
22679  }
22680  if(dumpState->args[0] == DumpStateOrd::LqhDumpLcpState){
22681 
22682  infoEvent("== LQH LCP STATE ==");
22683  infoEvent(" clcpCompletedState=%d, c_lcpId=%d, cnoOfFragsCheckpointed=%d",
22684  clcpCompletedState,
22685  c_lcpId,
22686  cnoOfFragsCheckpointed);
22687 
22688  LcpRecordPtr TlcpPtr;
22689  // Print information about the current local checkpoint
22690  TlcpPtr.i = 0;
22691  ptrAss(TlcpPtr, lcpRecord);
22692  infoEvent(" lcpState=%d lastFragmentFlag=%d",
22693  TlcpPtr.p->lcpState, TlcpPtr.p->lastFragmentFlag);
22694  infoEvent("currentFragment.fragPtrI=%d",
22695  TlcpPtr.p->currentFragment.fragPtrI);
22696  infoEvent("currentFragment.lcpFragOrd.tableId=%d",
22697  TlcpPtr.p->currentFragment.lcpFragOrd.tableId);
22698  infoEvent(" lcpQueued=%d reportEmpty=%d",
22699  TlcpPtr.p->lcpQueued,
22700  TlcpPtr.p->reportEmpty);
22701  char buf[8*_NDB_NODE_BITMASK_SIZE+1];
22702  infoEvent(" m_EMPTY_LCP_REQ=%s",
22703  TlcpPtr.p->m_EMPTY_LCP_REQ.getText(buf));
22704 
22705  return;
22706  }
22707  if (dumpState->args[0] == DumpStateOrd::LQHLogFileInitStatus){
22708  reportStatus(signal);
22709  return;
22710  }
22711 
22712 #ifdef ERROR_INSERT
22713 #ifdef NDB_DEBUG_FULL
22714  if(dumpState->args[0] == DumpStateOrd::LCPContinue){
22715  switch(cerrorInsert){
22716  case 5904:
22717  CLEAR_ERROR_INSERT_VALUE;
22718  g_trace_lcp.restore(*globalData.getBlock(BACKUP), signal);
22719  return;
22720  default:
22721  return;
22722  }
22723  }
22724 #endif
22725 #endif
22726 
22727  if(arg == 2304 || arg == 2305)
22728  {
22729  jam();
22730  Uint32 i;
22731  void * logPartPtr = 0;
22732  (void)logPartPtr;
22733  GcpRecordPtr gcp; gcp.i = RNIL;
22734  for(i = 0; i < clogPartFileSize; i++)
22735  {
22736  Ptr<LogPartRecord> lp;
22737  lp.i = i;
22738  ptrCheckGuard(lp, clogPartFileSize, logPartRecord);
22739  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",
22740  i,
22741  instance(),
22742  lp.p->logPartNo,
22743  lp.p->logPartState,
22744  lp.p->waitWriteGciLog,
22745  lp.p->gcprec,
22746  lp.p->m_log_prepare_queue.firstElement,
22747  lp.p->m_log_complete_queue.firstElement,
22748  lp.p->currentLogfile,
22749  lp.p->logTailFileNo,
22750  lp.p->logTailMbyte,
22751  cnoOfLogPages,
22752  lp.p->m_log_problems);
22753 
22754  if(gcp.i == RNIL && lp.p->gcprec != RNIL)
22755  gcp.i = lp.p->gcprec;
22756 
22757  LogFileRecordPtr logFilePtr;
22758  Uint32 first= logFilePtr.i= lp.p->firstLogfile;
22759  do
22760  {
22761  ptrCheckGuard(logFilePtr, clogFileFileSize, logFileRecord);
22762  ndbout_c(" file %d(%d) FileChangeState: %d logFileStatus: %d currentMbyte: %d currentFilepage %d",
22763  logFilePtr.p->fileNo,
22764  logFilePtr.i,
22765  logFilePtr.p->fileChangeState,
22766  logFilePtr.p->logFileStatus,
22767  logFilePtr.p->currentMbyte,
22768  logFilePtr.p->currentFilepage);
22769  logFilePtr.i = logFilePtr.p->nextLogFile;
22770  } while(logFilePtr.i != first);
22771  }
22772 
22773  if(gcp.i != RNIL)
22774  {
22775  ptrCheckGuard(gcp, cgcprecFileSize, gcpRecord);
22776  for(i = 0; i<4; i++)
22777  {
22778  ndbout_c(" GCP %d file: %d state: %d sync: %d page: %d word: %d",
22779  i, gcp.p->gcpFilePtr[i], gcp.p->gcpLogPartState[i],
22780  gcp.p->gcpSyncReady[i],
22781  gcp.p->gcpPageNo[i],
22782  gcp.p->gcpWordNo[i]);
22783  }
22784  }
22785 
22786  if(arg== 2305)
22787  {
22788  progError(__LINE__, NDBD_EXIT_SYSTEM_ERROR,
22789  "Please report this as a bug. "
22790  "Provide as much info as possible, expecially all the "
22791  "ndb_*_out.log files, Thanks. "
22792  "Shutting down node due to failed handling of GCP_SAVEREQ");
22793 
22794  }
22795  }
22796 
22797  if (dumpState->args[0] == DumpStateOrd::LqhErrorInsert5042 && (signal->getLength() >= 2))
22798  {
22799  c_error_insert_table_id = dumpState->args[1];
22800  if (signal->getLength() == 2)
22801  {
22802  SET_ERROR_INSERT_VALUE(5042);
22803  }
22804  else
22805  {
22806  SET_ERROR_INSERT_VALUE(dumpState->args[2]);
22807  }
22808  }
22809 
22810  TcConnectionrec *regTcConnectionrec = tcConnectionrec;
22811  Uint32 ttcConnectrecFileSize = ctcConnectrecFileSize;
22812  if(arg == 2306)
22813  {
22814  for(Uint32 i = 0; i<1024; i++)
22815  {
22816  TcConnectionrecPtr tcRec;
22817  tcRec.i = ctransidHash[i];
22818  while(tcRec.i != RNIL)
22819  {
22820  ptrCheckGuard(tcRec, ttcConnectrecFileSize, regTcConnectionrec);
22821  ndbout << "TcConnectionrec " << tcRec.i;
22822  signal->theData[0] = 2307;
22823  signal->theData[1] = tcRec.i;
22824  execDUMP_STATE_ORD(signal);
22825  tcRec.i = tcRec.p->nextHashRec;
22826  }
22827  }
22828  }
22829 
22830  if(arg == 2307 || arg == 2308)
22831  {
22832  TcConnectionrecPtr tcRec;
22833  tcRec.i = signal->theData[1];
22834  ptrCheckGuard(tcRec, ttcConnectrecFileSize, regTcConnectionrec);
22835 
22836  ndbout << " transactionState = " << tcRec.p->transactionState<<endl;
22837  ndbout << " operation = " << tcRec.p->operation<<endl;
22838  ndbout << " tcNodeFailrec = " << tcRec.p->tcNodeFailrec
22839  << " seqNoReplica = " << tcRec.p->seqNoReplica
22840  << endl;
22841  ndbout << " replicaType = " << tcRec.p->replicaType
22842  << " reclenAiLqhkey = " << tcRec.p->reclenAiLqhkey
22843  << " opExec = " << tcRec.p->opExec
22844  << endl;
22845  ndbout << " opSimple = " << tcRec.p->opSimple
22846  << " nextSeqNoReplica = " << tcRec.p->nextSeqNoReplica
22847  << " lockType = " << tcRec.p->lockType
22848  << endl;
22849  ndbout << " lastReplicaNo = " << tcRec.p->lastReplicaNo
22850  << " indTakeOver = " << tcRec.p->indTakeOver
22851  << " dirtyOp = " << tcRec.p->dirtyOp
22852  << endl;
22853  ndbout << " activeCreat = " << tcRec.p->activeCreat
22854  << " tcBlockref = " << hex << tcRec.p->tcBlockref
22855  << " reqBlockref = " << hex << tcRec.p->reqBlockref
22856  << " primKeyLen = " << tcRec.p->primKeyLen
22857  << " nrcopyflag = " << LqhKeyReq::getNrCopyFlag(tcRec.p->reqinfo)
22858  << endl;
22859  ndbout << " nextReplica = " << tcRec.p->nextReplica
22860  << " tcBlockref = " << hex << tcRec.p->tcBlockref
22861  << " reqBlockref = " << hex << tcRec.p->reqBlockref
22862  << " primKeyLen = " << tcRec.p->primKeyLen
22863  << endl;
22864  ndbout << " logStopPageNo = " << tcRec.p->logStopPageNo
22865  << " logStartPageNo = " << tcRec.p->logStartPageNo
22866  << " logStartPageIndex = " << tcRec.p->logStartPageIndex
22867  << endl;
22868  ndbout << " errorCode = " << tcRec.p->errorCode
22869  << " clientBlockref = " << hex << tcRec.p->clientBlockref
22870  << " applRef = " << hex << tcRec.p->applRef
22871  << " totSendlenAi = " << tcRec.p->totSendlenAi
22872  << endl;
22873  ndbout << " totReclenAi = " << tcRec.p->totReclenAi
22874  << " tcScanRec = " << tcRec.p->tcScanRec
22875  << " tcScanInfo = " << tcRec.p->tcScanInfo
22876  << " tcOprec = " << hex << tcRec.p->tcOprec
22877  << endl;
22878  ndbout << " tableref = " << tcRec.p->tableref
22879  << " simpleTcConnect = " << tcRec.p->simpleTcConnect
22880  << " storedProcId = " << tcRec.p->storedProcId
22881  << " schemaVersion = " << tcRec.p->schemaVersion
22882  << endl;
22883  ndbout << " reqinfo = " << tcRec.p->reqinfo
22884  << " reqRef = " << tcRec.p->reqRef
22885  << " readlenAi = " << tcRec.p->readlenAi
22886  << " prevTc = " << tcRec.p->prevTc
22887  << endl;
22888  ndbout << " prevLogTcrec = " << tcRec.p->prevLogTcrec
22889  << " prevHashRec = " << tcRec.p->prevHashRec
22890  << " nodeAfterNext0 = " << tcRec.p->nodeAfterNext[0]
22891  << " nodeAfterNext1 = " << tcRec.p->nodeAfterNext[1]
22892  << endl;
22893  ndbout << " nextTcConnectrec = " << tcRec.p->nextTcConnectrec
22894  << " nextTc = " << tcRec.p->nextTc
22895  << " nextTcLogQueue = " << tcRec.p->nextTcLogQueue
22896  << " nextLogTcrec = " << tcRec.p->nextLogTcrec
22897  << endl;
22898  ndbout << " nextHashRec = " << tcRec.p->nextHashRec
22899  << " logWriteState = " << tcRec.p->logWriteState
22900  << " logStartFileNo = " << tcRec.p->logStartFileNo
22901  << " listState = " << tcRec.p->listState
22902  << endl;
22903  ndbout << " gci_hi = " << tcRec.p->gci_hi
22904  << " gci_lo = " << tcRec.p->gci_lo
22905  << " fragmentptr = " << tcRec.p->fragmentptr
22906  << " fragmentid = " << tcRec.p->fragmentid
22907  << endl;
22908  ndbout << " hashValue = " << tcRec.p->hashValue
22909  << " currTupAiLen = " << tcRec.p->currTupAiLen
22910  << " currReclenAi = " << tcRec.p->currReclenAi
22911  << endl;
22912  ndbout << " tcTimer = " << tcRec.p->tcTimer
22913  << " clientConnectrec = " << tcRec.p->clientConnectrec
22914  << " applOprec = " << hex << tcRec.p->applOprec
22915  << " abortState = " << tcRec.p->abortState
22916  << endl;
22917  ndbout << " transid0 = " << hex << tcRec.p->transid[0]
22918  << " transid1 = " << hex << tcRec.p->transid[1]
22919  << " key[0] = " << getKeyInfoWordOrZero(tcRec.p, 0)
22920  << " key[1] = " << getKeyInfoWordOrZero(tcRec.p, 1)
22921  << endl;
22922  ndbout << " key[2] = " << getKeyInfoWordOrZero(tcRec.p, 2)
22923  << " key[3] = " << getKeyInfoWordOrZero(tcRec.p, 3)
22924  << " m_nr_delete.m_cnt = " << tcRec.p->m_nr_delete.m_cnt
22925  << endl;
22926  switch (tcRec.p->transactionState) {
22927 
22928  case TcConnectionrec::SCAN_STATE_USED:
22929  if (tcRec.p->tcScanRec < cscanrecFileSize){
22930  ScanRecordPtr TscanPtr;
22931  c_scanRecordPool.getPtr(TscanPtr, tcRec.p->tcScanRec);
22932  ndbout << " scanState = " << TscanPtr.p->scanState << endl;
22933  //TscanPtr.p->scanLocalref[2];
22934  ndbout << " copyPtr="<<TscanPtr.p->copyPtr
22935  << " scanAccPtr="<<TscanPtr.p->scanAccPtr
22936  << " scanAiLength="<<TscanPtr.p->scanAiLength
22937  << endl;
22938  ndbout << " m_curr_batch_size_rows="<<
22939  TscanPtr.p->m_curr_batch_size_rows
22940  << " m_max_batch_size_rows="<<
22941  TscanPtr.p->m_max_batch_size_rows
22942  << " scanErrorCounter="<<TscanPtr.p->scanErrorCounter
22943  << endl;
22944  ndbout << " scanSchemaVersion="<<TscanPtr.p->scanSchemaVersion
22945  << " scanStoredProcId="<<TscanPtr.p->scanStoredProcId
22946  << " scanTcrec="<<TscanPtr.p->scanTcrec
22947  << endl;
22948  ndbout << " scanType="<<TscanPtr.p->scanType
22949  << " scanApiBlockref="<<TscanPtr.p->scanApiBlockref
22950  << " scanNodeId="<<TscanPtr.p->scanNodeId
22951  << " scanCompletedStatus="<<TscanPtr.p->scanCompletedStatus
22952  << endl;
22953  ndbout << " scanFlag="<<TscanPtr.p->scanFlag
22954  << " scanLockHold="<<TscanPtr.p->scanLockHold
22955  << " scanLockMode="<<TscanPtr.p->scanLockMode
22956  << " scanNumber="<<TscanPtr.p->scanNumber
22957  << endl;
22958  ndbout << " scanReleaseCounter="<<TscanPtr.p->scanReleaseCounter
22959  << " scanTcWaiting="<<TscanPtr.p->scanTcWaiting
22960  << " scanKeyinfoFlag="<<TscanPtr.p->scanKeyinfoFlag
22961  << endl;
22962  } else{
22963  ndbout << "No connected scan record found" << endl;
22964  }
22965  break;
22966  default:
22967  break;
22968  }
22969  ndbrequire(arg != 2308);
22970  }
22971 
22972 #ifdef NDBD_TRACENR
22973  if (arg == 5712 || arg == 5713)
22974  {
22975  if (arg == 5712)
22976  {
22977  traceopout = &ndbout;
22978  }
22979  else if (arg == 5713)
22980  {
22981  traceopout = tracenrout;
22982  }
22983  SET_ERROR_INSERT_VALUE(arg);
22984  }
22985 #endif
22986 
22987  if (arg == 2350)
22988  {
22989  jam();
22990  Uint32 len = signal->getLength() - 1;
22991  if (len + 3 > 25)
22992  {
22993  jam();
22994  infoEvent("Too long filter");
22995  return;
22996  }
22997  if (validate_filter(signal))
22998  {
22999  jam();
23000  memmove(signal->theData + 3, signal->theData + 1, 4 * len);
23001  signal->theData[0] = 2351;
23002  signal->theData[1] = 0; // Bucket
23003  signal->theData[2] = RNIL; // Record
23004  sendSignal(reference(), GSN_DUMP_STATE_ORD, signal, len + 3, JBB);
23005 
23006  infoEvent("Starting dump of operations");
23007  }
23008  return;
23009  }
23010 
23011  if (arg == 2351)
23012  {
23013  jam();
23014  Uint32 bucket = signal->theData[1];
23015  Uint32 record = signal->theData[2];
23016  Uint32 len = signal->getLength();
23017  TcConnectionrecPtr tcRec;
23018  if (record != RNIL)
23019  {
23020  jam();
23024  tcRec.i = record;
23025  ptrCheckGuard(tcRec, ttcConnectrecFileSize, regTcConnectionrec);
23026 
23027  Uint32 hashIndex = (tcRec.p->transid[0] ^ tcRec.p->tcOprec) & 1023;
23028  if (hashIndex != bucket)
23029  {
23030  jam();
23031  record = RNIL;
23032  }
23033  else
23034  {
23035  jam();
23036  if (tcRec.p->nextHashRec == RNIL &&
23037  tcRec.p->prevHashRec == RNIL &&
23038  ctransidHash[hashIndex] != record)
23039  {
23040  jam();
23041  record = RNIL;
23042  }
23043  }
23044 
23045  if (record == RNIL)
23046  {
23047  jam();
23048  signal->theData[2] = RNIL;
23049  sendSignal(reference(), GSN_DUMP_STATE_ORD, signal,
23050  signal->getLength(), JBB);
23051  return;
23052  }
23053  }
23054  else if ((record = ctransidHash[bucket]) == RNIL)
23055  {
23056  jam();
23057  bucket++;
23058  if (bucket < 1024)
23059  {
23060  jam();
23061  signal->theData[1] = bucket;
23062  signal->theData[2] = RNIL;
23063  sendSignal(reference(), GSN_DUMP_STATE_ORD, signal,
23064  signal->getLength(), JBB);
23065  }
23066  else
23067  {
23068  jam();
23069  infoEvent("End of operation dump");
23070  if (ERROR_INSERTED(4002))
23071  {
23072  ndbrequire(false);
23073  }
23074  }
23075 
23076  return;
23077  }
23078  else
23079  {
23080  jam();
23081  tcRec.i = record;
23082  ptrCheckGuard(tcRec, ttcConnectrecFileSize, regTcConnectionrec);
23083  }
23084 
23085  for (Uint32 i = 0; i<32; i++)
23086  {
23087  jam();
23088  bool print = match_and_print(signal, tcRec);
23089 
23090  tcRec.i = tcRec.p->nextHashRec;
23091  if (tcRec.i == RNIL || print)
23092  {
23093  jam();
23094  break;
23095  }
23096 
23097  ptrCheckGuard(tcRec, ttcConnectrecFileSize, regTcConnectionrec);
23098  }
23099 
23100  if (tcRec.i == RNIL)
23101  {
23102  jam();
23103  bucket++;
23104  if (bucket < 1024)
23105  {
23106  jam();
23107  signal->theData[1] = bucket;
23108  signal->theData[2] = RNIL;
23109  sendSignal(reference(), GSN_DUMP_STATE_ORD, signal, len, JBB);
23110  }
23111  else
23112  {
23113  jam();
23114  infoEvent("End of operation dump");
23115  if (ERROR_INSERTED(4002))
23116  {
23117  ndbrequire(false);
23118  }
23119  }
23120 
23121  return;
23122  }
23123  else
23124  {
23125  jam();
23126  signal->theData[2] = tcRec.i;
23127  sendSignalWithDelay(reference(), GSN_DUMP_STATE_ORD, signal, 200, len);
23128  return;
23129  }
23130  }
23131 
23132  if (arg == 2352 && signal->getLength() == 2)
23133  {
23134  jam();
23135  Uint32 opNo = signal->theData[1];
23136  TcConnectionrecPtr tcRec;
23137  if (opNo < ttcConnectrecFileSize)
23138  {
23139  jam();
23140  tcRec.i = opNo;
23141  ptrCheckGuard(tcRec, ttcConnectrecFileSize, regTcConnectionrec);
23142 
23143  BaseString key;
23144  if (tcRec.p->keyInfoIVal != RNIL)
23145  {
23146  jam();
23147  SectionReader keyInfoReader(tcRec.p->keyInfoIVal,
23148  g_sectionSegmentPool);
23149 
23150  Uint32 keyWord;
23151  while (keyInfoReader.getWord(&keyWord))
23152  key.appfmt("0x%x ", keyWord);
23153  }
23154 
23155  char buf[100];
23156  BaseString::snprintf(buf, sizeof(buf),
23157  "OP[%u]: transid: 0x%x 0x%x key: %s",
23158  tcRec.i,
23159  tcRec.p->transid[0], tcRec.p->transid[1], key.c_str());
23160  infoEvent("%s", buf);
23161  }
23162  }
23163 
23164  if (arg == DumpStateOrd::SchemaResourceSnapshot)
23165  {
23166  RSS_AP_SNAPSHOT_SAVE(c_fragment_pool);
23167  return;
23168  }
23169 
23170  if (arg == DumpStateOrd::SchemaResourceCheckLeak)
23171  {
23172  RSS_AP_SNAPSHOT_CHECK(c_fragment_pool);
23173  return;
23174  }
23175 
23176  if (arg == 4002)
23177  {
23178  bool ops = false;
23179  for (Uint32 i = 0; i<1024; i++)
23180  {
23181  if (ctransidHash[i] != RNIL)
23182  {
23183  jam();
23184  ops = true;
23185  break;
23186  }
23187  }
23188 
23189  bool markers = m_commitAckMarkerPool.getNoOfFree() !=
23190  m_commitAckMarkerPool.getSize();
23191  if (unlikely(ops || markers))
23192  {
23193 
23194  if (markers)
23195  {
23196  ndbout_c("LQH: m_commitAckMarkerPool: %d free size: %d",
23197  m_commitAckMarkerPool.getNoOfFree(),
23198  m_commitAckMarkerPool.getSize());
23199 
23200  CommitAckMarkerIterator iter;
23201  for(m_commitAckMarkerHash.first(iter); iter.curr.i != RNIL;
23202  m_commitAckMarkerHash.next(iter))
23203  {
23204  ndbout_c("CommitAckMarker: i = %d (H'%.8x, H'%.8x)"
23205  " ApiRef: 0x%x apiOprec: 0x%x TcNodeId: %d ref_count: %u",
23206  iter.curr.i,
23207  iter.curr.p->transid1,
23208  iter.curr.p->transid2,
23209  iter.curr.p->apiRef,
23210  iter.curr.p->apiOprec,
23211  iter.curr.p->tcNodeId,
23212  iter.curr.p->reference_count);
23213  }
23214  }
23215  SET_ERROR_INSERT_VALUE(4002);
23216  signal->theData[0] = 2350;
23217  EXECUTE_DIRECT(DBLQH, GSN_DUMP_STATE_ORD, signal, 1);
23218  }
23219  }
23220 
23221  if(arg == 2399)
23222  {
23223  jam();
23224 
23225  if (cstartRecReq < SRR_REDO_COMPLETE)
23226  {
23227  jam();
23228  return;
23229  }
23230 
23231  for(Uint32 i = 0; i<4; i++)
23232  {
23233  logPartPtr.i = i;
23234  ptrCheckGuard(logPartPtr, clogPartFileSize, logPartRecord);
23235  LogFileRecordPtr logFile;
23236  logFile.i = logPartPtr.p->currentLogfile;
23237  ptrCheckGuard(logFile, clogFileFileSize, logFileRecord);
23238 
23239  LogPosition head = { logFile.p->fileNo, logFile.p->currentMbyte };
23240  LogPosition tail = { logPartPtr.p->logTailFileNo,
23241  logPartPtr.p->logTailMbyte};
23242  Uint64 mb = free_log(head, tail, logPartPtr.p->noLogFiles, clogFileSize);
23243  Uint64 total = logPartPtr.p->noLogFiles * Uint64(clogFileSize);
23244  signal->theData[0] = NDB_LE_RedoStatus;
23245  signal->theData[1] = i;
23246  signal->theData[2] = head.m_file_no;
23247  signal->theData[3] = head.m_mbyte;
23248  signal->theData[4] = tail.m_file_no;
23249  signal->theData[5] = tail.m_mbyte;
23250  signal->theData[6] = Uint32(total >> 32);
23251  signal->theData[7] = Uint32(total);
23252  signal->theData[8] = Uint32(mb >> 32);
23253  signal->theData[9] = Uint32(mb);
23254  sendSignal(CMVMI_REF, GSN_EVENT_REP, signal, 10, JBB);
23255  }
23256  }
23257 
23258  if(arg == 2398)
23259  {
23260  jam();
23261 
23262  if (cstartRecReq < SRR_REDO_COMPLETE)
23263  {
23264  jam();
23265  return;
23266  }
23267 
23268  for(Uint32 i = 0; i<clogPartFileSize; i++)
23269  {
23270  logPartPtr.i = i;
23271  ptrCheckGuard(logPartPtr, clogPartFileSize, logPartRecord);
23272  LogFileRecordPtr logFile;
23273  logFile.i = logPartPtr.p->currentLogfile;
23274  ptrCheckGuard(logFile, clogFileFileSize, logFileRecord);
23275 
23276  LogPosition head = { logFile.p->fileNo, logFile.p->currentMbyte };
23277  LogPosition tail = { logPartPtr.p->logTailFileNo,
23278  logPartPtr.p->logTailMbyte};
23279  Uint64 mb = free_log(head, tail, logPartPtr.p->noLogFiles, clogFileSize);
23280  Uint64 total = logPartPtr.p->noLogFiles * Uint64(clogFileSize);
23281  ndbout_c("REDO part: %u HEAD: file: %u mbyte: %u TAIL: file: %u mbyte: %u total: %llu free: %llu (mb)",
23282  logPartPtr.p->logPartNo,
23283  head.m_file_no, head.m_mbyte,
23284  tail.m_file_no, tail.m_mbyte,
23285  total, mb);
23286  }
23287  }
23288 
23289 }//Dblqh::execDUMP_STATE_ORD()
23290 
23291 
23292 void Dblqh::execDBINFO_SCANREQ(Signal *signal)
23293 {
23294  DbinfoScanReq req= *(DbinfoScanReq*)signal->theData;
23295  const Ndbinfo::ScanCursor* cursor =
23296  CAST_CONSTPTR(Ndbinfo::ScanCursor, DbinfoScan::getCursorPtr(&req));
23297  Ndbinfo::Ratelimit rl;
23298 
23299  jamEntry();
23300 
23301  switch(req.tableId){
23302  case Ndbinfo::LOGSPACES_TABLEID:
23303  {
23304  Uint32 logpart = cursor->data[0];
23305  while(logpart < clogPartFileSize)
23306  {
23307  jam();
23308 
23309  logPartPtr.i = logpart;
23310  ptrCheckGuard(logPartPtr, clogPartFileSize, logPartRecord);
23311 
23312  LogFileRecordPtr logFile;
23313  logFile.i = logPartPtr.p->currentLogfile;
23314  ptrCheckGuard(logFile, clogFileFileSize, logFileRecord);
23315 
23316  LogPosition head = { logFile.p->fileNo, logFile.p->currentMbyte };
23317  LogPosition tail = { logPartPtr.p->logTailFileNo,
23318  logPartPtr.p->logTailMbyte};
23319  Uint64 mb = free_log(head, tail, logPartPtr.p->noLogFiles, clogFileSize);
23320  Uint64 total = logPartPtr.p->noLogFiles * Uint64(clogFileSize);
23321  Uint64 high = 0; // TODO
23322 
23323  Ndbinfo::Row row(signal, req);
23324  row.write_uint32(getOwnNodeId());
23325  row.write_uint32(0); // log type, 0 = REDO
23326  row.write_uint32(0); // log id, always 0 in LQH
23327  row.write_uint32(logpart); // log part
23328 
23329  row.write_uint64(total*1024*1024); // total allocated
23330  row.write_uint64((total-mb)*1024*1024); // currently in use
23331  row.write_uint64(high*1024*1024); // in use high water mark
23332  ndbinfo_send_row(signal, req, row, rl);
23333  logpart++;
23334  if (rl.need_break(req))
23335  {
23336  jam();
23337  ndbinfo_send_scan_break(signal, req, rl, logpart);
23338  return;
23339  }
23340  }
23341  break;
23342  }
23343 
23344  case Ndbinfo::LOGBUFFERS_TABLEID:
23345  {
23346  const size_t entry_size = sizeof(LogPageRecord);
23347  const Uint64 free = cnoOfLogPages;
23348  const Uint64 total = clogPageCount;
23349  const Uint64 high = 0; // TODO
23350 
23351  Ndbinfo::Row row(signal, req);
23352  row.write_uint32(getOwnNodeId());
23353  row.write_uint32(0); // log type, 0 = REDO
23354  row.write_uint32(0); // log id, always 0 in LQH
23355  row.write_uint32(instance()); // log part, instance for ndbmtd
23356 
23357  row.write_uint64(total*entry_size); // total allocated
23358  row.write_uint64((total-free)*entry_size); // currently in use
23359  row.write_uint64(high*entry_size); // in use high water mark
23360  ndbinfo_send_row(signal, req, row, rl);
23361 
23362  break;
23363  }
23364 
23365  case Ndbinfo::COUNTERS_TABLEID:
23366  {
23367  Ndbinfo::counter_entry counters[] = {
23368  { Ndbinfo::OPERATIONS_COUNTER, c_Counters.operations }
23369  };
23370  const size_t num_counters = sizeof(counters) / sizeof(counters[0]);
23371 
23372  Uint32 i = cursor->data[0];
23373  BlockNumber bn = blockToMain(number());
23374  while(i < num_counters)
23375  {
23376  jam();
23377  Ndbinfo::Row row(signal, req);
23378  row.write_uint32(getOwnNodeId());
23379  row.write_uint32(bn); // block number
23380  row.write_uint32(instance()); // block instance
23381  row.write_uint32(counters[i].id);
23382 
23383  row.write_uint64(counters[i].val);
23384  ndbinfo_send_row(signal, req, row, rl);
23385  i++;
23386  if (rl.need_break(req))
23387  {
23388  jam();
23389  ndbinfo_send_scan_break(signal, req, rl, i);
23390  return;
23391  }
23392  }
23393  break;
23394  }
23395 
23396  default:
23397  break;
23398  }
23399 
23400  ndbinfo_send_scan_conf(signal, req, rl);
23401 }
23402 
23403 
23404 /* **************************************************************** */
23405 /* ---------------------------------------------------------------- */
23406 /* ---------------------- TRIGGER HANDLING ------------------------ */
23407 /* ---------------------------------------------------------------- */
23408 /* */
23409 /* All trigger signals from TRIX are forwarded top TUP */
23410 /* ---------------------------------------------------------------- */
23411 /* **************************************************************** */
23412 
23413 // Trigger signals
23414 void
23415 Dblqh::execCREATE_TRIG_IMPL_REQ(Signal* signal)
23416 {
23417  jamEntry();
23418 
23419  if (!assembleFragments(signal))
23420  {
23421  jam();
23422  return;
23423  }
23424 
23425  CreateTrigImplReq* req = (CreateTrigImplReq*)signal->getDataPtrSend();
23426  SectionHandle handle(this, signal);
23427  req->senderRef = reference();
23428  BlockReference tupRef = calcInstanceBlockRef(DBTUP);
23429  sendSignal(tupRef, GSN_CREATE_TRIG_IMPL_REQ, signal,
23430  signal->getLength(), JBB, &handle);
23431 }
23432 
23433 void
23434 Dblqh::execCREATE_TRIG_IMPL_CONF(Signal* signal)
23435 {
23436  jamEntry();
23437 
23438  BlockReference dictRef = !isNdbMtLqh() ? DBDICT_REF : DBLQH_REF;
23439  sendSignal(dictRef, GSN_CREATE_TRIG_IMPL_CONF, signal,
23440  CreateTrigImplConf::SignalLength, JBB);
23441 }
23442 
23443 void
23444 Dblqh::execCREATE_TRIG_IMPL_REF(Signal* signal)
23445 {
23446  jamEntry();
23447 
23448  BlockReference dictRef = !isNdbMtLqh() ? DBDICT_REF : DBLQH_REF;
23449  sendSignal(dictRef, GSN_CREATE_TRIG_IMPL_REF, signal,
23450  CreateTrigImplRef::SignalLength, JBB);
23451 }
23452 
23453 void
23454 Dblqh::execDROP_TRIG_IMPL_REQ(Signal* signal)
23455 {
23456  jamEntry();
23457 
23458  DropTrigImplReq* req = (DropTrigImplReq*)signal->getDataPtrSend();
23459  req->senderRef = reference();
23460  BlockReference tupRef = calcInstanceBlockRef(DBTUP);
23461  sendSignal(tupRef, GSN_DROP_TRIG_IMPL_REQ, signal,
23462  DropTrigImplReq::SignalLength, JBB);
23463 }
23464 
23465 void
23466 Dblqh::execDROP_TRIG_IMPL_CONF(Signal* signal)
23467 {
23468  jamEntry();
23469 
23470  BlockReference dictRef = !isNdbMtLqh() ? DBDICT_REF : DBLQH_REF;
23471  sendSignal(dictRef, GSN_DROP_TRIG_IMPL_CONF, signal,
23472  DropTrigImplConf::SignalLength, JBB);
23473 }
23474 
23475 void
23476 Dblqh::execDROP_TRIG_IMPL_REF(Signal* signal)
23477 {
23478  jamEntry();
23479 
23480  BlockReference dictRef = !isNdbMtLqh() ? DBDICT_REF : DBLQH_REF;
23481  sendSignal(dictRef, GSN_DROP_TRIG_IMPL_REF, signal,
23482  DropTrigImplRef::SignalLength, JBB);
23483 }
23484 
23485 Uint32 Dblqh::calcPageCheckSum(LogPageRecordPtr logP){
23486  Uint32 checkSum = 37;
23487 #ifdef VM_TRACE
23488  for (Uint32 i = (ZPOS_CHECKSUM+1); i<ZPAGE_SIZE; i++)
23489  checkSum = logP.p->logPageWord[i] ^ checkSum;
23490 #endif
23491  return checkSum;
23492  }
23493 
23494 #ifdef NDB_DEBUG_FULL
23495 #ifdef ERROR_INSERT
23496 void
23497 TraceLCP::sendSignal(Uint32 ref, Uint32 gsn, Signal* signal,
23498  Uint32 len, Uint32 prio)
23499 {
23500  Sig s;
23501  s.type = Sig::Sig_send;
23502  s.header = signal->header;
23503  s.header.theVerId_signalNumber = gsn;
23504  s.header.theReceiversBlockNumber = ref;
23505  s.header.theLength = len;
23506  memcpy(s.theData, signal->theData, 4 * len);
23507  m_signals.push_back(s);
23508  assert(signal->getNoOfSections() == 0);
23509 }
23510 
23511 void
23512 TraceLCP::save(Signal* signal){
23513  Sig s;
23514  s.type = Sig::Sig_save;
23515  s.header = signal->header;
23516  memcpy(s.theData, signal->theData, 4 * signal->getLength());
23517  m_signals.push_back(s);
23518  assert(signal->getNoOfSections() == 0);
23519 }
23520 
23521 void
23522 TraceLCP::restore(SimulatedBlock& lqh, Signal* sig){
23523  Uint32 cnt = m_signals.size();
23524  for(Uint32 i = 0; i<cnt; i++){
23525  sig->header = m_signals[i].header;
23526  memcpy(sig->theData, m_signals[i].theData, 4 * sig->getLength());
23527  switch(m_signals[i].type){
23528  case Sig::Sig_send:
23529  lqh.sendSignal(sig->header.theReceiversBlockNumber,
23530  sig->header.theVerId_signalNumber,
23531  sig,
23532  sig->header.theLength,
23533  JBB);
23534  break;
23535  case Sig::Sig_save:
23536  lqh.executeFunction(sig->header.theVerId_signalNumber, sig);
23537  break;
23538  }
23539  }
23540  m_signals.clear();
23541 }
23542 #endif
23543 #endif
23544 
23545 void Dblqh::writeDbgInfoPageHeader(LogPageRecordPtr logP, Uint32 place,
23546  Uint32 pageNo, Uint32 wordWritten)
23547 {
23548  logP.p->logPageWord[ZPOS_LOG_TIMER]= logPartPtr.p->logTimer;
23549  logP.p->logPageWord[ZPOS_PREV_PAGE_NO]= logP.p->logPageWord[ZPOS_PAGE_NO];
23550  logP.p->logPageWord[ZPOS_PAGE_I]= logP.i;
23551  logP.p->logPageWord[ZPOS_PLACE_WRITTEN_FROM]= place;
23552  logP.p->logPageWord[ZPOS_PAGE_NO]= pageNo;
23553  logP.p->logPageWord[ZPOS_PAGE_FILE_NO]= logFilePtr.p->fileNo;
23554  logP.p->logPageWord[ZPOS_WORD_WRITTEN]= wordWritten;
23555  logP.p->logPageWord[ZPOS_IN_WRITING]= 1;
23556 }
23557 
23558 void Dblqh::initReportStatus(Signal* signal){
23559  NDB_TICKS current_time = NdbTick_CurrentMillisecond();
23560  m_next_report_time = current_time +
23561  ((NDB_TICKS)m_startup_report_frequency) * ((NDB_TICKS)1000);
23562 }
23563 
23564 void Dblqh::checkReportStatus(Signal* signal){
23565  if (m_startup_report_frequency == 0)
23566  return;
23567 
23568  NDB_TICKS current_time = NdbTick_CurrentMillisecond();
23569  if (current_time > m_next_report_time)
23570  {
23571  reportStatus(signal);
23572  m_next_report_time = current_time +
23573  ((NDB_TICKS)m_startup_report_frequency) * ((NDB_TICKS)1000);
23574  }
23575 }
23576 
23577 void Dblqh::reportStatus(Signal* signal){
23578  const int signal_length = 6;
23579 
23580  signal->theData[0] = NDB_LE_LogFileInitStatus;
23581  signal->theData[1] = reference();
23582  for (int i = 2; i < signal_length; i++)
23583  signal->theData[i] = 0;
23584  if (getNodeState().startLevel < NodeState::SL_STARTED){
23585  signal->theData[2] = totalLogFiles;
23586  signal->theData[3] = logFileInitDone;
23587  signal->theData[4] = totallogMBytes;
23588  signal->theData[5] = logMBytesInitDone;
23589  }
23590  sendSignal(CMVMI_REF, GSN_EVENT_REP, signal, signal_length, JBB);
23591 }
23592 
23593 void Dblqh::logfileInitCompleteReport(Signal* signal){
23594  const int signal_length = 6;
23595 
23596  signal->theData[0] = NDB_LE_LogFileInitCompStatus;
23597  signal->theData[1] = reference();
23598  signal->theData[2] = totalLogFiles;
23599  signal->theData[3] = logFileInitDone;
23600  signal->theData[4] = totallogMBytes;
23601  signal->theData[5] = logMBytesInitDone;
23602  sendSignal(CMVMI_REF, GSN_EVENT_REP, signal, signal_length, JBB);
23603 }
23604 
23605 #ifdef NDBD_TRACENR
23606 void
23607 Dblqh::TRACE_OP_DUMP(const Dblqh::TcConnectionrec* regTcPtr, const char * pos)
23608 {
23609  (* traceopout)
23610  << "[ " << hex << regTcPtr->transid[0]
23611  << " " << hex << regTcPtr->transid[1] << " ] " << dec
23612  << pos
23613  << " " << (Operation_t)regTcPtr->operation
23614  << " " << regTcPtr->tableref
23615  << "(" << regTcPtr->fragmentid << ")"
23616  << "(" << (regTcPtr->seqNoReplica == 0 ? "P" : "B") << ")" ;
23617 
23618  {
23619  (* traceopout) << "key=[" << hex;
23620  if (regTcPtr->keyInfoIVal != RNIL)
23621  {
23622  SectionReader keyInfoReader(regTcPtr->keyInfoIVal,
23623  g_sectionSegmentPool);
23624 
23625  Uint32 keyWord;
23626  while (keyInfoReader.getWord(&keyWord))
23627  (* traceopout) << hex << keyWord << " ";
23628  }
23629  (* traceopout) << "] ";
23630  }
23631 
23632  if (regTcPtr->m_use_rowid)
23633  (* traceopout) << " " << regTcPtr->m_row_id;
23634  (* traceopout) << endl;
23635 }
23636 #endif
23637 
23638 Uint32
23639 Dblqh::get_node_status(Uint32 nodeId) const
23640 {
23641  HostRecordPtr Thostptr;
23642  Thostptr.i = nodeId;
23643  ptrCheckGuard(Thostptr, chostFileSize, hostRecord);
23644  return Thostptr.p->nodestatus;
23645 }
23646 
23647 #ifndef NO_REDO_PAGE_CACHE
23648 
23651 #define MIN_REDO_PAGES_FREE 64
23652 
23653 void
23654 Dblqh::do_evict(RedoPageCache& cache, Ptr<RedoCacheLogPageRecord> pagePtr)
23655 {
23656  LogPageRecordPtr save = logPagePtr;
23657  cache.m_lru.remove(pagePtr);
23658  cache.m_hash.remove(pagePtr);
23659  if (0)
23660  ndbout_c("evict part: %u file: %u page: %u cnoOfLogPages: %u",
23661  pagePtr.p->m_part_no,
23662  pagePtr.p->m_file_no,
23663  pagePtr.p->m_page_no,
23664  cnoOfLogPages);
23665 
23666  logPagePtr.i = pagePtr.i;
23667  ptrCheckGuard(logPagePtr, clogPageFileSize, logPageRecord);
23668 
23669  Ptr<LogPageRecord> prevPagePtr, nextPagePtr;
23670  prevPagePtr.i = logPagePtr.p->logPageWord[ZPREV_PAGE];
23671  nextPagePtr.i = logPagePtr.p->logPageWord[ZNEXT_PAGE];
23672  if (prevPagePtr.i != RNIL)
23673  {
23674  jam();
23680  ptrCheckGuard(prevPagePtr, clogPageFileSize, logPageRecord);
23681  ndbrequire(prevPagePtr.p->logPageWord[ZNEXT_PAGE] == logPagePtr.i);
23682  prevPagePtr.p->logPageWord[ZNEXT_PAGE] = RNIL;
23683  }
23684 
23685  if (nextPagePtr.i != RNIL)
23686  {
23687  jam();
23692  ptrCheckGuard(nextPagePtr, clogPageFileSize, logPageRecord);
23693  ndbrequire(nextPagePtr.p->logPageWord[ZPREV_PAGE] == logPagePtr.i);
23694  nextPagePtr.p->logPageWord[ZPREV_PAGE] = RNIL;
23695  }
23696 
23697  releaseLogpage(0);
23698  logPagePtr = save;
23699 }
23700 
23701 void
23702 Dblqh::evict(RedoPageCache& cache, Uint32 cnt)
23703 {
23704  while (cnoOfLogPages < (cnt + MIN_REDO_PAGES_FREE) && !cache.m_lru.isEmpty())
23705  {
23706  jam();
23708  cache.m_lru.last(pagePtr);
23709  do_evict(cache, pagePtr);
23710  }
23711 }
23712 
23713 void
23714 Dblqh::addCachePages(RedoPageCache& cache,
23715  Uint32 partNo,
23716  Uint32 startPageNo,
23717  LogFileOperationRecord* lfoPtrP)
23718 {
23719  Uint32 cnt = lfoPtrP->noPagesRw;
23720  Ptr<LogFileRecord> filePtr;
23721  filePtr.i = lfoPtrP->logFileRec;
23722  ptrCheckGuard(filePtr, clogFileFileSize, logFileRecord);
23723 
23724  evict(cache, 0);
23725 
23726  if (cnoOfLogPages < cnt + MIN_REDO_PAGES_FREE)
23727  {
23731  return;
23732  }
23733 
23734  for (Uint32 i = 0; i<cnt ; i++)
23735  {
23737  pagePtr.i = lfoPtrP->logPageArray[i];
23738  cache.m_pool.getPtr(pagePtr);
23739  pagePtr.p->m_part_no = partNo;
23740  pagePtr.p->m_page_no = startPageNo + i;
23741  pagePtr.p->m_file_no = filePtr.p->fileNo;
23742 
23743  bool found = false;
23744  {
23745  RedoCacheLogPageRecord key;
23746  key.m_part_no = partNo;
23747  key.m_page_no = startPageNo + i;
23748  key.m_file_no = filePtr.p->fileNo;
23750  if (cache.m_hash.find(tmp, key))
23751  {
23752  jam();
23753  found = true;
23754  do_evict(cache, tmp);
23755  }
23756  }
23757 
23758  cache.m_hash.add(pagePtr);
23759  cache.m_lru.addFirst(pagePtr);
23760  if (0)
23761  ndbout_c("adding(%u) part: %u file: %u page: %u cnoOfLogPages: %u cnt: %u",
23762  found,
23763  pagePtr.p->m_part_no,
23764  pagePtr.p->m_file_no,
23765  pagePtr.p->m_page_no,
23766  cnoOfLogPages,
23767  cnt);
23768  }
23769 
23774  lfoPtrP->firstLfoPage = RNIL;
23775 }
23776 
23777 void
23778 Dblqh::release(RedoPageCache& cache)
23779 {
23780  while (!cache.m_lru.isEmpty())
23781  {
23782  jam();
23784  cache.m_lru.last(pagePtr);
23785  cache.m_lru.remove(pagePtr);
23786 
23787  logPagePtr.i = pagePtr.i;
23788  ptrCheckGuard(logPagePtr, clogPageFileSize, logPageRecord);
23789  releaseLogpage(0);
23790  }
23791  cache.m_hash.removeAll();
23792 
23793 #if defined VM_TRACE || defined ERROR_INSERT || 1
23794  ndbout_c("RedoPageCache: avoided %u (%u/%u) page-reads",
23795  cache.m_hits, cache.m_multi_page, cache.m_multi_miss);
23796 #endif
23797  cache.m_hits = 0;
23798  cache.m_multi_page = 0;
23799  cache.m_multi_miss = 0;
23800 }
23801 #endif
23802 
23803 #ifndef NO_REDO_OPEN_FILE_CACHE
23804 
23805 #define MAX_CACHED_OPEN_FILES 4
23806 
23807 void
23808 Dblqh::openFileRw_cache(Signal* signal,
23809  LogFileRecordPtr filePtr)
23810 {
23811  jam();
23812 
23813  LogFileRecord::LogFileStatus state = filePtr.p->logFileStatus;
23814  if (state != LogFileRecord::CLOSED)
23815  {
23816  jam();
23817 
23818  m_redo_open_file_cache.m_hits++;
23819 
23820  if (m_redo_open_file_cache.m_lru.hasPrev(filePtr))
23821  {
23822  jam();
23823  m_redo_open_file_cache.m_lru.remove(filePtr);
23824  m_redo_open_file_cache.m_lru.addFirst(filePtr);
23825  }
23826 
23827  filePtr.p->logFileStatus = LogFileRecord::OPEN_EXEC_LOG_CACHED;
23828 
23829  signal->theData[0] = filePtr.i;
23830  signal->theData[1] = filePtr.p->fileRef;
23831  sendSignal(reference(), GSN_FSOPENCONF, signal, 2, JBB);
23832  return;
23833  }
23834 
23835  filePtr.p->logFileStatus = LogFileRecord::OPEN_EXEC_LOG;
23836  openFileRw(signal, filePtr, false);
23837 }
23838 
23839 void
23840 Dblqh::closeFile_cache(Signal* signal,
23841  LogFileRecordPtr filePtr,
23842  Uint32 line)
23843 {
23844  jam();
23845 
23846  filePtr.p->logFileStatus = LogFileRecord::CLOSING_EXEC_LOG_CACHED;
23847  if (m_redo_open_file_cache.m_lru.count() >= MAX_CACHED_OPEN_FILES)
23848  {
23849  jam();
23850  Ptr<LogFileRecord> evictPtr;
23851  Uint32 logPartRec = filePtr.p->logPartRec;
23860  m_redo_open_file_cache.m_lru.last(evictPtr);
23861  while (evictPtr.p->logPartRec != logPartRec)
23862  {
23863  jam();
23864  ndbrequire(m_redo_open_file_cache.m_lru.prev(evictPtr));
23865  }
23866  m_redo_open_file_cache.m_lru.remove(evictPtr);
23867  evictPtr.p->logFileStatus = LogFileRecord::CLOSING_EXEC_LOG;
23868  closeFile(signal, evictPtr, line);
23869  }
23870  else
23871  {
23872  jam();
23873  signal->theData[0] = ZEXEC_SR;
23874  signal->theData[1] = filePtr.p->logPartRec;
23875  sendSignal(cownref, GSN_CONTINUEB, signal, 2, JBB);
23876  }
23877 }
23878 
23879 void
23880 Dblqh::release(Signal* signal, RedoOpenFileCache & cache)
23881 {
23882  Ptr<LogFileRecord> closePtr;
23883 
23884  while (m_redo_open_file_cache.m_lru.first(closePtr))
23885  {
23886  jam();
23887  m_redo_open_file_cache.m_lru.remove(closePtr);
23888  if (closePtr.p->logFileStatus == LogFileRecord::CLOSING_EXEC_LOG_CACHED)
23889  {
23890  jam();
23891  closePtr.p->logFileStatus = LogFileRecord::CLOSING_EXEC_LOG_CACHED;
23892  m_redo_open_file_cache.m_close_cnt ++;
23893  signal->theData[0] = closePtr.p->fileRef;
23894  signal->theData[1] = reference();
23895  signal->theData[2] = closePtr.i;
23896  signal->theData[3] = ZCLOSE_NO_DELETE;
23897  signal->theData[4] = __LINE__;
23898  sendSignal(NDBFS_REF, GSN_FSCLOSEREQ, signal, 5, JBA);
23899  return;
23900  }
23901  else
23902  {
23903  ndbout_c("Found file with state: %u",
23904  closePtr.p->logFileStatus);
23905  }
23906  }
23907 
23908  ndbout_c("RedoOpenFileCache: Avoided %u file-open/close closed: %u",
23909  m_redo_open_file_cache.m_hits,
23910  m_redo_open_file_cache.m_close_cnt);
23911  m_redo_open_file_cache.m_hits = 0;
23912  m_redo_open_file_cache.m_close_cnt = 0;
23913  execLogComp_extra_files_closed(signal);
23914 }
23915 
23916 #endif
23917 
23918 bool
23919 Dblqh::check_ndb_versions() const
23920 {
23921  Uint32 version = getNodeInfo(getOwnNodeId()).m_version;
23922  for (Uint32 i = 0; i < cnoOfNodes; i++)
23923  {
23924  Uint32 node = cnodeData[i];
23925  if (cnodeStatus[i] == ZNODE_UP)
23926  {
23927  if(getNodeInfo(node).m_version != version)
23928  {
23929  return false;
23930  }
23931  }
23932  }
23933  return true;
23934 }
23935 
23936 void
23937 Dblqh::suspendFile(Signal* signal, Uint32 filePtrI, Uint32 millis)
23938 {
23939  Ptr<LogFileRecord> tmp;
23940  tmp.i = filePtrI;
23941  ptrCheckGuard(tmp, clogFileFileSize, logFileRecord);
23942  suspendFile(signal, tmp, millis);
23943 }
23944 
23945 void
23946 Dblqh::suspendFile(Signal* signal, Ptr<LogFileRecord> logFilePtr, Uint32 millis)
23947 {
23949  signal->theData[0] = logFilePtr.p->fileRef;
23950  signal->theData[1] = millis;
23951  sendSignal(NDBFS_REF, GSN_FSSUSPENDORD, signal, 2, JBA);
23952 }
23953 
23954 void
23955 Dblqh::send_runredo_event(Signal* signal, LogPartRecord * lp, Uint32 gci)
23956 {
23957  signal->theData[0] = NDB_LE_RunRedo;
23958  signal->theData[1] = lp->logPartNo;
23959  signal->theData[2] = csrPhasesCompleted;
23960  signal->theData[3] = lp->logStartGci;
23961  signal->theData[4] = gci;
23962  signal->theData[5] = lp->logLastGci;
23963 
23964 
23965  LogFileRecordPtr filePtr;
23966  filePtr.i = lp->startLogfile;
23967  ptrCheckGuard(filePtr, clogFileFileSize, logFileRecord);
23968  signal->theData[6] = filePtr.p->fileNo;
23969  signal->theData[7] = lp->startMbyte;
23970 
23971  filePtr.i = lp->currentLogfile;
23972  ptrCheckGuard(filePtr, clogFileFileSize, logFileRecord);
23973  signal->theData[8] = filePtr.p->fileNo;
23974  signal->theData[9] = filePtr.p->currentMbyte;
23975 
23976  filePtr.i = lp->stopLogfile;
23977  ptrCheckGuard(filePtr, clogFileFileSize, logFileRecord);
23978  signal->theData[10] = filePtr.p->fileNo;
23979  signal->theData[11] = lp->stopMbyte;
23980  sendSignal(CMVMI_REF, GSN_EVENT_REP, signal, 12, JBB);
23981 }
23982 
23983 void
23984 Dblqh::IOTracker::init(Uint32 partNo)
23985 {
23986  bzero(this, sizeof(* this));
23987  m_log_part_no = partNo;
23988 }
23989 
23990 int
23991 Dblqh::IOTracker::tick(Uint32 now, Uint32 maxlag, Uint32 maxlag_cnt)
23992 {
23993  Uint32 t = m_current_time;
23994 
23995  if ((t / SAMPLE_TIME) == (now / SAMPLE_TIME))
23996  return 0;
23997 
23998  m_current_time = now;
23999  if (m_sample_completed_bytes >= m_sample_sent_bytes)
24000  {
24007  m_sample_sent_bytes = 0;
24008  m_sample_completed_bytes = 0;
24009  }
24010  else
24011  {
24012  // io maxed out...
24013  Uint32 elapsed = now - t;
24014  m_save_written_bytes[m_save_pos] += m_sample_completed_bytes;
24015  m_save_elapsed_millis[m_save_pos] += elapsed;
24016 
24017  m_curr_written_bytes += m_sample_completed_bytes;
24018  m_curr_elapsed_millis += elapsed;
24019 
24020  Uint32 bps = (1000 * m_sample_completed_bytes) / elapsed;
24021  Uint32 lag = bps ? m_sum_outstanding_bytes / bps : 30;
24022  if (false && lag >= 30)
24023  {
24024  g_eventLogger->info("part: %u tick(%u) m_sample_completed_bytes: %u m_sample_sent_bytes: %u elapsed: %u kbps: %u lag: %u",
24025  m_log_part_no,
24026  now, m_sample_completed_bytes, m_sample_sent_bytes,
24027  elapsed, bps/1000, lag);
24028  }
24029 
24030  m_sample_sent_bytes -= m_sample_completed_bytes;
24031  m_sample_completed_bytes = 0;
24032  }
24033 
24034  int retVal = 0;
24035  Uint32 save_lag_cnt = m_lag_cnt;
24036  if ((now / SLIDING_WINDOW_LEN) != (t / SLIDING_WINDOW_LEN))
24037  {
24038  Uint32 lag = m_curr_written_bytes ?
24039  ((Uint64(m_sum_outstanding_bytes) / 1000) * Uint64(m_curr_elapsed_millis)) / m_curr_written_bytes:
24040  0;
24041 
24042  if (lag > maxlag)
24043  {
24048  Uint32 tmp = m_lag_cnt;
24049  m_lag_cnt += (lag / maxlag);
24050  if (tmp < maxlag_cnt && m_lag_cnt >= maxlag_cnt)
24051  {
24052  retVal = -1; // start aborting transaction
24053  }
24054  }
24055  else
24056  {
24060  if (m_lag_cnt >= maxlag_cnt)
24061  {
24062  // stop aborting transcation
24063  retVal = 1;
24064  }
24065  m_lag_cnt = 0;
24066  }
24067 
24068 #if 1
24069  if (m_lag_cnt == 0 && lag == 0)
24070  {
24071  }
24072  else if (lag > 0 && m_lag_cnt == 0)
24073  {
24074  g_eventLogger->info("part: %u : time to complete: %u",
24075  m_log_part_no, lag);
24076  }
24077  else if (m_lag_cnt < maxlag_cnt && m_lag_cnt == save_lag_cnt)
24078  {
24079  g_eventLogger->info("part: %u : time to complete: %u lag_cnt: %u => %u => retVal: %d",
24080  m_log_part_no,
24081  lag,
24082  save_lag_cnt,
24083  m_lag_cnt,
24084  retVal);
24085  }
24086  else
24087  {
24088  g_eventLogger->info("part: %u : sum_outstanding: %ukb avg_written: %ukb avg_elapsed: %ums time to complete: %u lag_cnt: %u => %u retVal: %d",
24089  m_log_part_no, m_sum_outstanding_bytes / 1024, m_curr_written_bytes/1024, m_curr_elapsed_millis,
24090  lag, save_lag_cnt, m_lag_cnt, retVal);
24091  }
24092 #endif
24093 
24097  Uint32 last = (m_save_pos + 1) % SLIDING_WINDOW_HISTORY_LEN;
24098  assert(m_curr_written_bytes >= m_save_written_bytes[last]);
24099  assert(m_curr_elapsed_millis >= m_save_elapsed_millis[last]);
24100  m_curr_written_bytes -= m_save_written_bytes[last];
24101  m_curr_elapsed_millis -= m_save_elapsed_millis[last];
24102  m_save_written_bytes[last] = 0;
24103  m_save_elapsed_millis[last] = 0;
24104  m_save_pos = last;
24105  }
24106  return retVal;
24107 }
24108 
24109 void
24110 Dblqh::IOTracker::send_io(Uint32 bytes)
24111 {
24112  m_sum_outstanding_bytes += bytes;
24113  m_sample_sent_bytes += bytes;
24114 }
24115 
24116 void
24117 Dblqh::IOTracker::complete_io(Uint32 bytes)
24118 {
24119  assert(m_sum_outstanding_bytes >= bytes);
24120 
24121  m_sum_outstanding_bytes -= bytes;
24122  m_sample_completed_bytes += bytes;
24123 }