2
Copyright (c) 2003, 2011, Oracle and/or its affiliates. All rights reserved.
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.
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.
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
20
#include <ndb_limits.h>
21
#include <md5_hash.hpp>
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>
53
#include <signaldata/CreateTab.hpp>
54
#include <signaldata/CreateTable.hpp>
55
#include <signaldata/PrepDropTab.hpp>
56
#include <signaldata/DropTab.hpp>
58
#include <signaldata/AlterTab.hpp>
59
#include <signaldata/AlterTable.hpp>
60
#include <signaldata/DictTabInfo.hpp>
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>
80
#include "../suma/Suma.hpp"
81
#include "DblqhCommon.hpp"
83
#include <EventLogger.hpp>
84
extern EventLogger * g_eventLogger;
86
// Use DEBUG to print messages that should be
87
// seen only when we debug the product
89
#define DEBUG(x) ndbout << "DBLQH: "<< x << endl;
92
operator<<(NdbOut& out, Dblqh::TcConnectionrec::TransactionState state){
99
operator<<(NdbOut& out, Dblqh::TcConnectionrec::LogWriteState state){
106
operator<<(NdbOut& out, Dblqh::TcConnectionrec::ListState state){
113
operator<<(NdbOut& out, Dblqh::TcConnectionrec::AbortState state){
120
operator<<(NdbOut& out, Dblqh::ScanRecord::ScanState state){
127
operator<<(NdbOut& out, Dblqh::LogFileOperationRecord::LfoState state){
134
operator<<(NdbOut& out, Dblqh::ScanRecord::ScanType state){
141
operator<<(NdbOut& out, Operation_t 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;
160
//#define MARKER_TRACE 0
161
//#define TRACE_SCAN_TAKEOVER 1
164
#ifndef NDB_DEBUG_REDO
165
#define NDB_DEBUG_REDO
169
#ifdef NDB_DEBUG_REDO
170
static int DEBUG_REDO = 0;
175
const Uint32 NR_ScanNo = 0;
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
191
#define TRACENR_FLAG 0
192
#define TRACENR(x) do { } while(0)
193
#define SET_TRACENR_FLAG
194
#define CLEAR_TRACENR_FLAG
198
static NdbOut * traceopout = 0;
199
#define TRACE_OP(regTcPtr, place) do { if (TRACE_OP_CHECK(regTcPtr)) TRACE_OP_DUMP(regTcPtr, place); } while(0)
201
#define TRACE_OP(x, y) { (void)x;}
211
cmp(const LogPosition& pos1, const LogPosition& pos2)
213
if (pos1.m_file_no > pos2.m_file_no)
215
if (pos1.m_file_no < pos2.m_file_no)
217
if (pos1.m_mbyte > pos2.m_mbyte)
219
if (pos1.m_mbyte < pos2.m_mbyte)
230
free_log(const LogPosition& head, const LogPosition& tail,
231
Uint32 cnt, Uint32 size)
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)
237
return (cnt * Uint64(size)) - headmb + tailmb;
241
return tailmb - headmb;
245
/* ------------------------------------------------------------------------- */
246
/* ------- SEND SYSTEM ERROR ------- */
248
/* ------------------------------------------------------------------------- */
249
void Dblqh::systemError(Signal* signal, int line)
251
signal->theData[0] = 2304;
252
execDUMP_STATE_ORD(signal);
253
progError(line, NDBD_EXIT_NDBREQUIRE);
254
}//Dblqh::systemError()
256
/* *************** */
258
/* *************** */
259
void Dblqh::execACCSEIZEREF(Signal* signal)
263
}//Dblqh::execACCSEIZEREF()
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)
275
Uint32 tcase = signal->theData[0];
276
Uint32 data0 = signal->theData[1];
277
Uint32 data1 = signal->theData[2];
278
Uint32 data2 = signal->theData[3];
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;
288
ndbout << "abortState = " << tcConnectptr.p->abortState;
289
ndbout << "listState = " << tcConnectptr.p->listState;
294
LogPartRecordPtr save;
297
if (cnoOfLogPages == 0) {
300
sendSignalWithDelay(cownref, GSN_CONTINUEB, signal, 10, 2);
303
logPartPtr.i = data0;
304
ptrCheckGuard(logPartPtr, clogPartFileSize, logPartRecord);
307
logPartPtr.p->LogLqhKeyReqSent = ZFALSE;
309
if (logPartPtr.p->waitWriteGciLog == LogPartRecord::WWGL_TRUE)
314
if (logPartPtr.p->m_log_complete_queue.isEmpty())
318
* prepare is first in queue...check that it's ok to rock'n'roll
320
if (logPartPtr.p->m_log_problems != 0)
323
* It will be restarted when problems are cleared...
329
if (cnoOfLogPages < ZMIN_LOG_PAGES_OPERATION)
332
logPartPtr.p->LogLqhKeyReqSent = ZTRUE;
337
logFilePtr.i = logPartPtr.p->currentLogfile;
338
ptrCheckGuard(logFilePtr, clogFileFileSize, logFileRecord);
339
logPagePtr.i = logFilePtr.p->currentLogpage;
340
ptrCheckGuard(logPagePtr, clogPageFileSize, logPageRecord);
342
getFirstInLogQueue(signal, tcConnectptr);
343
fragptr.i = tcConnectptr.p->fragmentptr;
344
c_fragment_pool.getPtr(fragptr);
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)
354
abortCommonLab(signal);
359
logLqhkeyreqLab(signal);
362
case TcConnectionrec::LOG_ABORT_QUEUED:
364
writeAbortLog(signal);
365
removeLogTcrec(signal);
366
continueAfterLogAbortWriteLab(signal);
368
case TcConnectionrec::LOG_COMMIT_QUEUED:
369
case TcConnectionrec::LOG_COMMIT_QUEUED_WAIT_SIGNAL:
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)
377
localCommitLab(signal);
382
commitReplyLab(signal);
388
tcConnectptr.p->transactionState = TcConnectionrec::LOG_COMMIT_WRITTEN_WAIT_SIGNAL;
391
case TcConnectionrec::COMMIT_QUEUED:
393
localCommitLab(signal);
395
case TcConnectionrec::ABORT_QUEUED:
397
abortCommonLab(signal);
405
* LogFile/LogPage could have altered due to above
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);
418
signal->theData[0] = data0;
424
signal->theData[0] = data0;
425
signal->theData[1] = data1;
426
signal->theData[2] = data2;
430
case ZSEND_EXEC_CONF:
432
signal->theData[0] = data0;
433
sendExecConf(signal);
438
signal->theData[0] = data0;
442
case ZSR_FOURTH_COMP:
444
signal->theData[0] = data0;
445
srFourthComp(signal);
450
signal->theData[0] = data0;
454
case ZTIME_SUPERVISION:
456
signal->theData[0] = data0;
460
case ZSR_PHASE3_START:
462
srPhase3Start(signal);
465
case ZLQH_TRANS_NEXT:
467
tcNodeFailptr.i = data0;
468
ptrCheckGuard(tcNodeFailptr, ctcNodeFailrecFileSize, tcNodeFailRecord);
469
lqhTransNextLab(signal);
472
case ZSCAN_TC_CONNECT:
475
ptrCheckGuard(tabptr, ctabrecFileSize, tablerec);
476
scanTcConnectLab(signal, data0, data2);
479
case ZINITIALISE_RECORDS:
481
initialiseRecordsLab(signal, data0, data2, signal->theData[4]);
487
ptrAss(gcpPtr, gcpRecord);
488
initGcpRecLab(signal);
489
startTimeSupervision(signal);
492
case ZCHECK_LCP_STOP_BLOCKED:
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);
503
scanMarkers(signal, data0, data1, data2);
507
case ZOPERATION_EVENT_REP:
509
/* Send counter event report */
511
const Uint32 len = c_Counters.build_event_rep(signal);
512
sendSignal(CMVMI_REF, GSN_EVENT_REP, signal, len, JBB);
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);
523
case ZDROP_TABLE_WAIT_USAGE:
525
dropTab_wait_usage(signal);
528
case ZENABLE_EXPAND_CHECK:
531
fragptr.i = signal->theData[1];
532
if (fragptr.i != RNIL)
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;
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);
547
c_lcp_complete_fragments.remove(save);
553
cstartRecReq = SRR_REDO_COMPLETE;
554
ndbrequire(c_lcp_complete_fragments.isEmpty());
556
rebuildOrderedIndexes(signal, 0);
560
case ZRETRY_TCKEYREF:
563
Uint32 cnt = signal->theData[1];
564
Uint32 ref = signal->theData[2];
565
if (cnt < (10 * 60 * 5))
569
* Only retry for 5 minutes...then hope that API has handled it..somehow
571
memmove(signal->theData, signal->theData+3, 4*TcKeyRef::SignalLength);
572
sendTCKEYREF(signal, ref, 0, cnt);
576
case ZWAIT_REORG_SUMA_FILTER_ENABLED:
578
wait_reorg_suma_filter_enabled(signal);
580
case ZREBUILD_ORDERED_INDEXES:
582
Uint32 tableId = signal->theData[1];
583
rebuildOrderedIndexes(signal, tableId);
589
wait_readonly(signal);
596
}//Dblqh::execCONTINUEB()
598
/* *********************************************************> */
599
/* Request from DBDIH to include a new node in the node list */
601
/* *********************************************************> */
602
void Dblqh::execINCL_NODEREQ(Signal* signal)
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++) {
612
if (cnodeData[i] == nodeId) {
614
cnodeStatus[i] = ZNODE_UP;
619
HostRecordPtr Thostptr;
621
ptrCheckGuard(Thostptr, chostFileSize, hostRecord);
622
Thostptr.p->nodestatus = ZNODE_UP;
625
signal->theData[0] = nodeId;
626
signal->theData[1] = cownref;
627
sendSignal(retRef, GSN_INCL_NODECONF, signal, 2, JBB);
629
}//Dblqh::execINCL_NODEREQ()
631
void Dblqh::execTUPSEIZEREF(Signal* signal)
635
}//Dblqh::execTUPSEIZEREF()
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)
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
656
switch (tstartPhase) {
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);
668
out = globalSignalLoggers.getOutputStream();
671
name = NdbConfig_SignalLogFileName(getOwnNodeId());
672
out = fopen(name, "a");
674
tracenrout = new NdbOut(* new FileOutputStream(out));
678
traceopout = &ndbout;
681
#ifdef NDB_DEBUG_REDO
684
if (NdbEnv_GetEnv("NDB_DEBUG_REDO", buf, sizeof(buf)))
694
define_backup(signal);
699
sendsttorryLab(signal);
703
}//Dblqh::execSTTOR()
706
Dblqh::define_backup(Signal* signal)
708
DefineBackupReq * req = (DefineBackupReq*)signal->getDataPtrSend();
712
req->senderRef = reference();
714
req->backupKey[0] = 0;
715
req->backupKey[1] = 0;
717
req->nodes.set(getOwnNodeId());
718
req->backupDataLen = ~0;
720
BlockReference backupRef = calcInstanceBlockRef(BACKUP);
721
sendSignal(backupRef, GSN_DEFINE_BACKUP_REQ, signal,
722
DefineBackupReq::SignalLength, JBB);
726
Dblqh::execDEFINE_BACKUP_REF(Signal* signal)
730
DefineBackupRef* ref = (DefineBackupRef*)signal->getDataPtrSend();
732
char * extra_msg = NULL;
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:
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);
750
sendsttorryLab(signal);
754
Dblqh::execDEFINE_BACKUP_CONF(Signal* signal)
757
DefineBackupConf * conf = (DefineBackupConf*)signal->getDataPtrSend();
758
m_backup_ptr = conf->backupPtr;
759
sendsttorryLab(signal);
762
/* ***************************************> */
763
/* Restart phases 1 - 6, sender is Ndbcntr */
764
/* ***************************************> */
765
void Dblqh::execNDB_STTOR(Signal* signal)
768
Uint32 ownNodeId = signal->theData[1]; /* START PHASE*/
769
cstartPhase = signal->theData[2]; /* MY NODE ID */
770
cstartType = signal->theData[3]; /* START TYPE */
772
switch (cstartPhase) {
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);
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);
805
startphase2Lab(signal, /* dummy */ ~0);
810
startphase3Lab(signal);
815
startphase4Lab(signal);
820
startphase6Lab(signal);
826
sendNdbSttorryLab(signal);
830
}//Dblqh::execNDB_STTOR()
832
/* ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ */
833
/* +++++++ START PHASE 2 +++++++ */
835
/* INITIATE ALL RECORDS WITHIN THE BLOCK */
836
/* ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ */
837
void Dblqh::startphase1Lab(Signal* signal, Uint32 _dummy, Uint32 ownNodeId)
840
HostRecordPtr ThostPtr;
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++) {
851
ptrCheckGuard(ThostPtr, chostFileSize, hostRecord);
853
* Valid only if receiver has same number of LQH workers.
854
* In general full instance key of fragment must be used.
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;
863
cpackedListIndex = 0;
866
(cstartType == NodeState::ST_INITIAL_START) ||
867
(cstartType == NodeState::ST_INITIAL_NODE_RESTART);
869
LogFileRecordPtr prevLogFilePtr;
870
LogFileRecordPtr zeroLogFilePtr;
872
ndbrequire(cnoLogFiles != 0);
873
for (logPartPtr.i = 0; logPartPtr.i < clogPartFileSize; logPartPtr.i++)
876
ptrAss(logPartPtr, logPartRecord);
878
for (Uint32 fileNo = 0; fileNo < cnoLogFiles; fileNo++)
880
seizeLogfile(signal);
884
prevLogFilePtr.p->nextLogFile = logFilePtr.i;
885
logFilePtr.p->prevLogFile = prevLogFilePtr.i;
890
logPartPtr.p->firstLogfile = logFilePtr.i;
891
logPartPtr.p->currentLogfile = logFilePtr.i;
892
zeroLogFilePtr.i = logFilePtr.i;
893
zeroLogFilePtr.p = logFilePtr.p;
895
prevLogFilePtr.i = logFilePtr.i;
896
prevLogFilePtr.p = logFilePtr.p;
897
initLogfile(signal, fileNo);
901
if (logFilePtr.i == zeroLogFilePtr.i)
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)
913
* initialize one file at a time if using OM_INIT
921
* FSWRITEREQ does cross-thread execute-direct
922
* which makes the clear_global_variables "unsafe"
923
* disable it until we're finished with init log-files
925
disable_global_variables();
928
openLogfileInit(signal);
933
zeroLogFilePtr.p->prevLogFile = logFilePtr.i;
934
logFilePtr.p->nextLogFile = zeroLogFilePtr.i;
937
initReportStatus(signal);
941
sendNdbSttorryLab(signal);
945
reportStatus(signal);
949
}//Dblqh::startphase1Lab()
951
/* ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ */
952
/* +++++++ START PHASE 2 +++++++ */
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)
960
cmaxWordsAtNodeRec = MAX_NO_WORDS_OUTSTANDING_COPY_FRAGMENT;
961
/* -- ACC AND TUP CONNECTION PROCESS -- */
963
ptrAss(tcConnectptr, tcConnectionrec);
964
moreconnectionsLab(signal);
966
}//Dblqh::startphase2Lab()
968
void Dblqh::moreconnectionsLab(Signal* signal)
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
/* *************** */
976
/* *************** */
977
signal->theData[0] = tcConnectptr.i;
978
signal->theData[1] = cownref;
979
sendSignal(caccBlockref, GSN_ACCSEIZEREQ, signal, 2, JBB);
981
}//Dblqh::moreconnectionsLab()
983
/* ***************> */
985
/* ***************> */
986
void Dblqh::execACCSEIZECONF(Signal* signal)
989
tcConnectptr.i = signal->theData[0];
990
ptrCheckGuard(tcConnectptr, ctcConnectrecFileSize, tcConnectionrec);
991
tcConnectptr.p->accConnectrec = signal->theData[1];
992
/* *************** */
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);
1000
}//Dblqh::execACCSEIZECONF()
1002
/* ***************> */
1003
/* TUPSEIZECONF > */
1004
/* ***************> */
1005
void Dblqh::execTUPSEIZECONF(Signal* signal)
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) {
1015
ptrCheckGuard(tcConnectptr, ctcConnectrecFileSize, tcConnectionrec);
1016
moreconnectionsLab(signal);
1019
/* ALL LQH_CONNECT RECORDS ARE CONNECTED TO ACC AND TUP ---- */
1020
sendNdbSttorryLab(signal);
1022
}//Dblqh::execTUPSEIZECONF()
1024
/* +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ */
1025
/* +++++++ START PHASE 4 +++++++ */
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)
1040
caddNodeState = ZTRUE;
1041
/* ***************<< */
1042
/* READ_NODESREQ < */
1043
/* ***************<< */
1044
cinitialStartOngoing = ZTRUE;
1047
case NodeState::ST_NODE_RESTART:
1048
case NodeState::ST_SYSTEM_RESTART:
1050
for (logPartPtr.i = 0; logPartPtr.i < clogPartFileSize; logPartPtr.i++)
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);
1061
case NodeState::ST_INITIAL_START:
1062
case NodeState::ST_INITIAL_NODE_RESTART:
1064
for (logPartPtr.i = 0; logPartPtr.i < clogPartFileSize; logPartPtr.i++)
1067
signal->theData[0] = ZINIT_FOURTH;
1068
signal->theData[1] = logPartPtr.i;
1069
sendSignal(cownref, GSN_CONTINUEB, signal, 2, JBB);
1074
signal->theData[0] = cownref;
1075
sendSignal(NDBCNTR_REF, GSN_READ_NODESREQ, signal, 1, JBB);
1077
}//Dblqh::startphase3Lab()
1079
/* ****************** */
1080
/* READ_NODESCONF > */
1081
/* ****************** */
1082
void Dblqh::execREAD_NODESCONF(Signal* signal)
1086
ReadNodesConf * const readNodes = (ReadNodesConf *)&signal->theData[0];
1087
cnoOfNodes = readNodes->noOfNodes;
1091
for (i = 1; i < MAX_NDB_NODES; i++) {
1093
if (NdbNodeBitmask::get(readNodes->allNodes, i)) {
1096
cnodeStatus[ind] = NdbNodeBitmask::get(readNodes->inactiveNodes, i);
1099
HostRecordPtr Thostptr;
1101
ptrCheckGuard(Thostptr, chostFileSize, hostRecord);
1102
Thostptr.p->nodestatus = cnodeStatus[ind];
1105
//readNodes->getVersionId(i, readNodes->theVersionIds) not used
1106
if (!NodeBitmask::get(readNodes->inactiveNodes, i))
1114
ndbrequire(ind == cnoOfNodes);
1115
ndbrequire(cnoOfNodes >= 1 && cnoOfNodes < MAX_NDB_NODES);
1116
ndbrequire(!(cnoOfNodes == 1 && cstartType == NodeState::ST_NODE_RESTART));
1119
c_master_node_id = readNodes->masterNodeId;
1122
caddNodeState = ZFALSE;
1123
if (cstartType == NodeState::ST_SYSTEM_RESTART)
1126
sendNdbSttorryLab(signal);
1129
else if (cstartType == NodeState::ST_NODE_RESTART)
1134
m_sr_nodes.set(getOwnNodeId());
1135
sendNdbSttorryLab(signal);
1140
checkStartCompletedLab(signal);
1142
}//Dblqh::execREAD_NODESCONF()
1144
void Dblqh::checkStartCompletedLab(Signal* signal)
1146
if (caddNodeState == ZFALSE) {
1147
if (cinitialStartOngoing == ZFALSE) {
1149
sendNdbSttorryLab(signal);
1154
}//Dblqh::checkStartCompletedLab()
1156
void Dblqh::startphase4Lab(Signal* signal)
1158
sendNdbSttorryLab(signal);
1160
}//Dblqh::startphase4Lab()
1162
/* ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ */
1163
/* SET CONCURRENCY OF LOCAL CHECKPOINTS TO BE USED AFTER SYSTEM RESTART. */
1164
/* ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ */
1165
void Dblqh::startphase6Lab(Signal* signal)
1170
sendNdbSttorryLab(signal);
1172
}//Dblqh::startphase6Lab()
1174
void Dblqh::sendNdbSttorryLab(Signal* signal)
1176
signal->theData[0] = cownref;
1177
BlockReference cntrRef = !isNdbMtLqh() ? NDBCNTR_REF : DBLQH_REF;
1178
sendSignal(cntrRef, GSN_NDB_STTORRY, signal, 1, JBB);
1180
}//Dblqh::sendNdbSttorryLab()
1182
void Dblqh::sendsttorryLab(Signal* signal)
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);
1196
}//Dblqh::sendsttorryLab()
1198
/* ***************>> */
1199
/* READ_NODESREF > */
1200
/* ***************>> */
1201
void Dblqh::execREAD_NODESREF(Signal* signal)
1205
}//Dblqh::execREAD_NODESREF()
1207
/* *************** */
1209
/* *************** */
1210
void Dblqh::execREAD_CONFIG_REQ(Signal* signal)
1212
const ReadConfigReq * req = (ReadConfigReq*)signal->getDataPtr();
1213
Uint32 ref = req->senderRef;
1214
Uint32 senderData = req->senderData;
1215
ndbrequire(req->noOfParameters == 0);
1219
const ndb_mgm_configuration_iterator * p =
1220
m_ctx.m_config.getOwnConfigIterator();
1224
ndbrequire(!ndb_mgm_get_int_parameter(p, CFG_DB_NO_REDOLOG_FILES,
1226
ndbrequire(cnoLogFiles > 0);
1228
Uint32 log_page_size= 0;
1229
ndb_mgm_get_int_parameter(p, CFG_DB_REDO_BUFFER,
1233
* Always set page size in half MBytes
1235
clogPageFileSize= (log_page_size / sizeof(LogPageRecord));
1236
Uint32 mega_byte_part= clogPageFileSize & 15;
1237
if (mega_byte_part != 0) {
1239
clogPageFileSize+= (16 - mega_byte_part);
1242
/* maximum number of log file operations */
1243
clfoFileSize = clogPageFileSize;
1244
if (clfoFileSize < ZLFO_MIN_FILE_SIZE)
1245
clfoFileSize = ZLFO_MIN_FILE_SIZE;
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;
1254
ndbrequire(!ndb_mgm_get_int_parameter(p, CFG_DB_DISCLESS, &c_diskless));
1256
ndb_mgm_get_int_parameter(p, CFG_DB_O_DIRECT, &c_o_direct);
1260
const char * conf = 0;
1261
if (!ndb_mgm_get_string_parameter(p, CFG_DB_INIT_REDO, &conf) && conf)
1264
if (strcasecmp(conf, "sparse") == 0)
1269
else if (strcasecmp(conf, "full") == 0)
1278
ndbrequire(!ndb_mgm_get_int_parameter(p, CFG_LQH_FRAG, &tmp));
1279
c_fragment_pool.setSize(tmp);
1281
if (!ndb_mgm_get_int_parameter(p, CFG_DB_REDOLOG_FILE_SIZE,
1285
clogFileSize = (clogFileSize + 1024*1024 - 1) / (1024 * 1024);
1286
ndbrequire(clogFileSize >= 4 && clogFileSize <= 1024);
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;
1295
cmaxLogFilesInPageZero = (ZPAGE_SIZE - ZPAGE_HEADER_SIZE - 128) /
1296
(ZFD_MBYTE_SIZE * clogFileSize);
1299
* "Old" cmaxLogFilesInPageZero was 40
1300
* Each FD need 3 words per mb, require that they can fit into 1 page
1302
* Is also checked in ConfigInfo.cpp (max FragmentLogFileSize = 1Gb)
1303
* 1Gb = 1024Mb => 3(ZFD_MBYTE_SIZE) * 1024 < 8192 (ZPAGE_SIZE)
1305
if (cmaxLogFilesInPageZero > 40)
1308
cmaxLogFilesInPageZero = 40;
1312
ndbrequire(cmaxLogFilesInPageZero);
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;
1320
const Uint32 mb = 1024 * 1024;
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)
1327
c_free_mb_force_lcp_limit = Uint32(totalmb - config_mbytes);
1331
c_free_mb_force_lcp_limit = 0;
1335
Uint32 limit = Uint32(totalmb / 3);
1336
if (c_free_mb_force_lcp_limit < limit)
1338
c_free_mb_force_lcp_limit = limit;
1341
c_free_mb_tail_problem_limit = 4; // If less than 4Mb set TAIL_PROBLEM
1343
ndb_mgm_get_int_parameter(p, CFG_DB_TRANSACTION_DEADLOCK_TIMEOUT,
1344
&cTransactionDeadlockDetectionTimeout);
1347
initialiseRecordsLab(signal, 0, ref, senderData);
1349
c_max_redo_lag = 30;
1350
ndb_mgm_get_int_parameter(p, CFG_DB_REDO_OVERCOMMIT_LIMIT,
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);
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);
1361
if (c_max_parallel_scans_per_frag > (256 - MAX_PARALLEL_SCANS_PER_FRAG) / 2)
1364
c_max_parallel_scans_per_frag = (256 - MAX_PARALLEL_SCANS_PER_FRAG) / 2;
1367
}//Dblqh::execSIZEALT_REP()
1369
/* ########################################################################## */
1370
/* ####### ADD/DELETE FRAGMENT MODULE ####### */
1371
/* THIS MODULE IS USED BY DICTIONARY TO CREATE NEW FRAGMENTS AND DELETE */
1372
/* OLD FRAGMENTS. */
1374
/* ########################################################################## */
1375
/* -------------------------------------------------------------- */
1377
/* -------------------------------------------------------------- */
1378
/* *********************************************************> */
1379
/* LQHFRAGREQ: Create new fragments for a table. Sender DICT */
1380
/* *********************************************************> */
1382
// this unbelievable mess could be replaced by one signal to LQH
1383
// and execute direct to local DICT to get everything at once
1385
Dblqh::execCREATE_TAB_REQ(Signal* signal)
1387
CreateTabReq* req = (CreateTabReq*)signal->getDataPtr();
1388
tabptr.i = req->tableId;
1389
ptrCheckGuard(tabptr, ctabrecFileSize, tablerec);
1391
Uint32 senderRef = req->senderRef;
1392
Uint32 senderData = req->senderData;
1394
if (tabptr.p->tableStatus != Tablerec::NOT_DEFINED)
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);
1406
seizeAddfragrec(signal);
1407
addfragptr.p->m_createTabReq = *req;
1408
req = &addfragptr.p->m_createTabReq;
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;
1417
addfragptr.p->addfragStatus = AddFragRecord::WAIT_TUP;
1418
sendCreateTabReq(signal, addfragptr);
1422
Dblqh::sendCreateTabReq(Signal* signal, AddFragRecordPtr addfragptr)
1425
tabPtr.i = addfragptr.p->m_createTabReq.tableId;
1426
ptrCheckGuard(tabPtr, ctabrecFileSize, tablerec);
1428
CreateTabReq* req = (CreateTabReq*)signal->getDataPtrSend();
1429
* req = addfragptr.p->m_createTabReq;
1431
req->senderRef = reference();
1432
req->senderData = addfragptr.i;
1434
Uint32 ref = calcInstanceBlockRef(DBTUP);
1435
switch(addfragptr.p->addfragStatus){
1436
case AddFragRecord::WAIT_TUP:
1437
if (DictTabInfo::isOrderedIndex(tabPtr.p->tableType))
1440
req->noOfAttributes = 1;
1441
req->noOfKeyAttr = 1;
1442
req->noOfNullAttributes = 0;
1445
case AddFragRecord::WAIT_TUX:
1447
ndbrequire(req->noOfAttributes >= 2);
1448
req->noOfAttributes--;
1449
ref = calcInstanceBlockRef(DBTUX);
1452
jamLine(addfragptr.p->addfragStatus);
1456
sendSignal(ref, GSN_CREATE_TAB_REQ, signal,
1457
CreateTabReq::SignalLengthLDM, JBB);
1461
Dblqh::execCREATE_TAB_REF(Signal* signal)
1465
CreateTabRef * ref = (CreateTabRef*)signal->getDataPtr();
1466
addfragptr.i = ref->senderData;
1467
ptrCheckGuard(addfragptr, caddfragrecFileSize, addFragRecord);
1469
abortAddFragOps(signal);
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);
1476
releaseAddfragrec(signal);
1480
Dblqh::execCREATE_TAB_CONF(Signal* signal)
1483
CreateTabConf* conf = (CreateTabConf*)signal->getDataPtr();
1484
addfragptr.i = conf->senderData;
1485
ptrCheckGuard(addfragptr, caddfragrecFileSize, addFragRecord);
1488
tabPtr.i = addfragptr.p->m_createTabReq.tableId;
1489
ptrCheckGuard(tabPtr, ctabrecFileSize, tablerec);
1491
switch(addfragptr.p->addfragStatus){
1492
case AddFragRecord::WAIT_TUP:
1494
addfragptr.p->tupConnectptr = conf->tupConnectPtr;
1495
if (DictTabInfo::isOrderedIndex(tabPtr.p->tableType))
1498
addfragptr.p->addfragStatus = AddFragRecord::WAIT_TUX;
1499
sendCreateTabReq(signal, addfragptr);
1503
case AddFragRecord::WAIT_TUX:
1505
addfragptr.p->tuxConnectptr = conf->tuxConnectPtr;
1508
jamLine(addfragptr.p->addfragStatus);
1512
addfragptr.p->addfragStatus = AddFragRecord::WAIT_ADD_ATTR;
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);
1521
/* ************************************************************************> */
1522
/* LQHADDATTRREQ: Request from DICT to create attributes for the new table. */
1523
/* ************************************************************************> */
1524
void Dblqh::execLQHADDATTREQ(Signal* signal)
1527
LqhAddAttrReq * req = (LqhAddAttrReq*)signal->getDataPtr();
1529
addfragptr.i = req->lqhFragPtr;
1530
ptrCheckGuard(addfragptr, caddfragrecFileSize, addFragRecord);
1532
addfragptr.p->m_addAttrReq = * req;
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;
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
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);
1557
addfragptr.p->attrReceived = tnoOfAttr;
1560
tabPtr.i = addfragptr.p->m_createTabReq.tableId;
1561
ptrCheckGuard(tabPtr, ctabrecFileSize, tablerec);
1563
for (Uint32 i = 0; i < tnoOfAttr; i++)
1565
if(AttributeDescriptor::getDiskBased(req->attributes[i].attrDescriptor))
1568
tabPtr.p->m_disk_table = 1;
1572
addfragptr.p->attrSentToTup = 0;
1573
addfragptr.p->addfragStatus = AddFragRecord::TUP_ATTR_WAIT;
1574
sendAddAttrReq(signal);
1575
}//Dblqh::execLQHADDATTREQ()
1577
/* *********************>> */
1578
/* TUP_ADD_ATTCONF > */
1579
/* *********************>> */
1580
void Dblqh::execTUP_ADD_ATTCONF(Signal* signal)
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);
1588
tabptr.i = addfragptr.p->m_createTabReq.tableId;
1589
ptrCheckGuard(tabptr, ctabrecFileSize, tablerec);
1591
Uint32 noOfAttr = addfragptr.p->m_createTabReq.noOfAttributes;
1593
switch (addfragptr.p->addfragStatus) {
1594
case AddFragRecord::TUP_ATTR_WAIT:
1595
if (DictTabInfo::isOrderedIndex(tabptr.p->tableType))
1597
addfragptr.p->addfragStatus = AddFragRecord::TUX_ATTR_WAIT;
1598
sendAddAttrReq(signal);
1601
goto done_with_attr;
1603
case AddFragRecord::TUX_ATTR_WAIT:
1606
addfragptr.p->tuxConnectptr = RNIL;
1607
goto 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)
1615
// more in this batch
1617
addfragptr.p->addfragStatus = AddFragRecord::TUP_ATTR_WAIT;
1618
sendAddAttrReq(signal);
1622
if (addfragptr.p->defValSectionI != RNIL)
1624
releaseSection(addfragptr.p->defValSectionI);
1625
addfragptr.p->defValNextPos = 0;
1626
addfragptr.p->defValSectionI = RNIL;
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);
1636
if (addfragptr.p->totalAttrReceived < noOfAttr)
1639
addfragptr.p->addfragStatus = AddFragRecord::WAIT_ADD_ATTR;
1644
releaseAddfragrec(signal);
1653
/* **********************>> */
1654
/* TUX_ADD_ATTRCONF > */
1655
/* **********************>> */
1656
void Dblqh::execTUX_ADD_ATTRCONF(Signal* signal)
1659
execTUP_ADD_ATTCONF(signal);
1660
}//Dblqh::execTUX_ADD_ATTRCONF
1662
/* *********************> */
1663
/* TUP_ADD_ATTREF > */
1664
/* *********************> */
1665
void Dblqh::execTUP_ADD_ATTRREF(Signal* signal)
1668
addfragptr.i = signal->theData[0];
1669
ptrCheckGuard(addfragptr, caddfragrecFileSize, addFragRecord);
1670
Uint32 errorCode = terrorCode = signal->theData[1];
1672
abortAddFragOps(signal);
1674
// operation was released on the other side
1675
switch (addfragptr.p->addfragStatus) {
1676
case AddFragRecord::TUP_ATTR_WAIT:
1679
case AddFragRecord::TUX_ATTR_WAIT:
1687
if (addfragptr.p->defValSectionI != RNIL)
1689
releaseSection(addfragptr.p->defValSectionI);
1690
addfragptr.p->defValNextPos = 0;
1691
addfragptr.p->defValSectionI = RNIL;
1694
const Uint32 Ref = addfragptr.p->m_createTabReq.senderRef;
1695
const Uint32 senderData = addfragptr.p->m_addAttrReq.senderData;
1697
releaseAddfragrec(signal);
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()
1706
/* **********************> */
1707
/* TUX_ADD_ATTRREF > */
1708
/* **********************> */
1709
void Dblqh::execTUX_ADD_ATTRREF(Signal* signal)
1712
execTUP_ADD_ATTRREF(signal);
1713
}//Dblqh::execTUX_ADD_ATTRREF
1716
* Add attribute in TUP or TUX. Called up to 4 times.
1719
Dblqh::sendAddAttrReq(Signal* signal)
1721
arrGuard(addfragptr.p->attrSentToTup, LqhAddAttrReq::MAX_ATTRIBUTES);
1722
LqhAddAttrReq::Entry& entry =
1723
addfragptr.p->m_addAttrReq.attributes[addfragptr.p->attrSentToTup];
1725
const Uint32 attrId = entry.attrId & 0xffff;
1726
const Uint32 primaryAttrId = entry.attrId >> 16;
1728
tabptr.i = addfragptr.p->m_createTabReq.tableId;
1729
ptrCheckGuard(tabptr, ctabrecFileSize, tablerec);
1731
if (addfragptr.p->addfragStatus == AddFragRecord::TUP_ATTR_WAIT)
1733
if (DictTabInfo::isTable(tabptr.p->tableType) ||
1734
DictTabInfo::isHashIndex(tabptr.p->tableType) ||
1735
(DictTabInfo::isOrderedIndex(tabptr.p->tableType) &&
1736
primaryAttrId == ZNIL)) {
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);
1745
Uint32 sectionLen = 0;
1746
Uint32 startIndex = TupAddAttrReq::SignalLength;
1747
if (addfragptr.p->defValSectionI != RNIL)
1749
SegmentedSectionPtr defValSection;
1750
getSection(defValSection, addfragptr.p->defValSectionI);
1752
SectionReader defValueReader(defValSection, getSectionSegmentPool());
1753
Uint32 defSectionWords = defValueReader.getSize();
1755
ndbrequire(defValueReader.step(addfragptr.p->defValNextPos));
1757
Uint32 defValueHeader;
1758
ndbrequire(defValueReader.peekWord(&defValueHeader));
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;
1770
//A long section is attached when a default value is sent.
1771
if (sectionLen != 0)
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);
1780
sendSignal(tupRef, GSN_TUP_ADD_ATTRREQ,
1781
signal, TupAddAttrReq::SignalLength, JBB);
1785
if (DictTabInfo::isOrderedIndex(tabptr.p->tableType) &&
1786
primaryAttrId != ZNIL) {
1787
// this attribute is not for TUP
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);
1798
if (addfragptr.p->addfragStatus == AddFragRecord::TUX_ATTR_WAIT)
1801
if (DictTabInfo::isOrderedIndex(tabptr.p->tableType) &&
1802
primaryAttrId != ZNIL) {
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);
1816
if (DictTabInfo::isOrderedIndex(tabptr.p->tableType) &&
1817
primaryAttrId == ZNIL) {
1818
// this attribute is not for TUX
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);
1829
}//Dblqh::sendAddAttrReq
1831
void Dblqh::execLQHFRAGREQ(Signal* signal)
1834
LqhFragReq copy = *(LqhFragReq*)signal->getDataPtr();
1835
LqhFragReq * req = ©
1837
tabptr.i = req->tableId;
1838
ptrCheckGuard(tabptr, ctabrecFileSize, tablerec);
1840
if (tabptr.p->tableStatus != Tablerec::ADD_TABLE_ONGOING &&
1841
(AlterTableReq::getAddFragFlag(req->changeMask) == 0))
1844
fragrefLab(signal, ZTAB_STATE_ERROR, req);
1848
if (getFragmentrec(signal, req->fragId))
1851
fragrefLab(signal, terrorCode, req);
1855
if (!insertFragrec(signal, req->fragId))
1858
fragrefLab(signal, terrorCode, req);
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;
1871
NdbLogPartInfo lpinfo(instance());
1872
Uint32 logPartNo = lpinfo.partNoFromId(req->logPartId);
1873
ndbrequire(lpinfo.partNoOwner(logPartNo));
1875
LogPartRecordPtr ptr;
1876
ptr.i = lpinfo.partNoIndex(logPartNo);
1877
ptrCheckGuard(ptr, clogPartFileSize, logPartRecord);
1878
ndbrequire(ptr.p->logPartNo == logPartNo);
1880
fragptr.p->m_log_part_ptr_i = ptr.i;
1881
fragptr.p->lqhInstanceKey = lpinfo.instanceKey(logPartNo);
1884
if (DictTabInfo::isOrderedIndex(tabptr.p->tableType)) {
1886
// find corresponding primary table fragment
1887
TablerecPtr tTablePtr;
1888
tTablePtr.i = tabptr.p->primaryTableId;
1889
ptrCheckGuard(tTablePtr, ctabrecFileSize, tablerec);
1890
FragrecordPtr tFragPtr;
1892
for (Uint32 i = 0; i < MAX_FRAG_PER_NODE; i++) {
1893
if (tTablePtr.p->fragid[i] == fragptr.p->fragId) {
1895
tFragPtr.i = tTablePtr.p->fragrec[i];
1899
ndbrequire(tFragPtr.i != RNIL);
1901
fragptr.p->tableFragptr = tFragPtr.i;
1906
fragptr.p->tableFragptr = fragptr.i;
1911
//--------------------------------------------
1912
// reqinfo bit 3-4 = 2 means temporary table
1913
// without logging or checkpointing.
1914
//--------------------------------------------
1916
fragptr.p->logFlag = Fragrecord::STATE_FALSE;
1917
fragptr.p->lcpFlag = Fragrecord::LCP_STATE_FALSE;
1920
seizeAddfragrec(signal);
1921
addfragptr.p->m_lqhFragReq = * req;
1922
addfragptr.p->fragmentPtr = fragptr.i;
1924
if (DictTabInfo::isTable(tabptr.p->tableType) ||
1925
DictTabInfo::isHashIndex(tabptr.p->tableType)) {
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);
1949
if (DictTabInfo::isOrderedIndex(tabptr.p->tableType)) {
1951
addfragptr.p->addfragStatus = AddFragRecord::WAIT_TUP;
1952
sendAddFragReq(signal);
1956
}//Dblqh::execLQHFRAGREQ()
1958
/* *************** */
1960
/* *************** */
1961
void Dblqh::execACCFRAGCONF(Signal* signal)
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);
1971
addfragptr.p->accConnectptr = taccConnectptr;
1972
fragptr.i = addfragptr.p->fragmentPtr;
1973
c_fragment_pool.getPtr(fragptr);
1974
fragptr.p->accFragptr = accFragPtr1;
1976
addfragptr.p->addfragStatus = AddFragRecord::WAIT_TUP;
1977
sendAddFragReq(signal);
1978
}//Dblqh::execACCFRAGCONF()
1980
/* *************** */
1982
/* *************** */
1983
void Dblqh::execTUPFRAGCONF(Signal* signal)
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:
1999
fragptr.p->tupFragptr = tupFragPtr;
2000
addfragptr.p->tupConnectptr = tupConnectptr;
2001
if (DictTabInfo::isOrderedIndex(tabptr.p->tableType))
2003
addfragptr.p->addfragStatus = AddFragRecord::WAIT_TUX;
2004
sendAddFragReq(signal);
2007
goto done_with_frag;
2009
case AddFragRecord::WAIT_TUX:
2011
fragptr.p->tuxFragptr = tupFragPtr;
2012
addfragptr.p->tuxConnectptr = tupConnectptr;
2013
goto done_with_frag;
2016
/* ---------------------------------------------------------------- */
2017
/* Finished create of fragments. Now ready for creating attributes. */
2018
/* ---------------------------------------------------------------- */
2019
fragptr.p->fragStatus = Fragrecord::FSACTIVE;
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);
2030
releaseAddfragrec(signal);
2036
}//Dblqh::execTUPFRAGCONF()
2038
/* *************** */
2040
/* *************** */
2041
void Dblqh::execTUXFRAGCONF(Signal* signal)
2044
execTUPFRAGCONF(signal);
2045
}//Dblqh::execTUXFRAGCONF
2048
* Add fragment in TUP or TUX. Called up to 4 times.
2051
Dblqh::sendAddFragReq(Signal* signal)
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)
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);
2075
if (addfragptr.p->addfragStatus == AddFragRecord::WAIT_TUX)
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);
2098
}//Dblqh::sendAddFragReq
2101
/* ************************************************************************>> */
2102
/* TAB_COMMITREQ: Commit the new table for use in transactions. Sender DICT. */
2103
/* ************************************************************************>> */
2104
void Dblqh::execTAB_COMMITREQ(Signal* signal)
2107
Uint32 dihPtr = signal->theData[0];
2108
BlockReference dihBlockref = signal->theData[1];
2109
tabptr.i = signal->theData[2];
2111
if (tabptr.i >= ctabrecFileSize) {
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);
2121
ptrAss(tabptr, tablerec);
2122
if (tabptr.p->tableStatus != Tablerec::ADD_TABLE_ONGOING) {
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);
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);
2143
}//Dblqh::execTAB_COMMITREQ()
2146
void Dblqh::fragrefLab(Signal* signal,
2148
const LqhFragReq* req)
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);
2160
}//Dblqh::fragrefLab()
2163
* Abort on-going ops.
2165
void Dblqh::abortAddFragOps(Signal* signal)
2167
if (addfragptr.p->tupConnectptr != RNIL) {
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;
2175
if (addfragptr.p->tuxConnectptr != RNIL) {
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;
2185
/* ************>> */
2187
/* ************>> */
2188
void Dblqh::execACCFRAGREF(Signal* signal)
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);
2196
fragrefLab(signal, errorCode, &addfragptr.p->m_lqhFragReq);
2197
releaseAddfragrec(signal);
2200
}//Dblqh::execACCFRAGREF()
2202
/* ************>> */
2204
/* ************>> */
2205
void Dblqh::execTUPFRAGREF(Signal* signal)
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);
2214
// no operation to release, just add some jams
2215
switch (addfragptr.p->addfragStatus) {
2216
case AddFragRecord::WAIT_TUP:
2219
case AddFragRecord::WAIT_TUX:
2227
fragrefLab(signal, errorCode, &addfragptr.p->m_lqhFragReq);
2228
releaseAddfragrec(signal);
2230
}//Dblqh::execTUPFRAGREF()
2233
Dblqh::execDROP_FRAG_REQ(Signal* signal)
2235
DropFragReq *req = (DropFragReq*)signal->getDataPtr();
2236
seizeAddfragrec(signal);
2237
addfragptr.p->m_dropFragReq = *req;
2243
* 4 - tux (optional)
2245
tabptr.i = req->tableId;
2246
ptrCheckGuard(tabptr, ctabrecFileSize, tablerec);
2248
deleteFragrec(req->fragId);
2250
Uint32 ref = calcInstanceBlockRef(DBACC);
2251
if (DictTabInfo::isOrderedIndex(tabptr.p->tableType))
2254
ref = calcInstanceBlockRef(DBTUP);
2257
req->senderRef = reference();
2258
req->senderData = addfragptr.i;
2259
sendSignal(ref, GSN_DROP_FRAG_REQ, signal, DropFragReq::SignalLength, JBB);
2263
Dblqh::execDROP_FRAG_REF(Signal* signal)
2269
Dblqh::execDROP_FRAG_CONF(Signal* signal)
2271
DropFragConf* conf = (DropFragConf*)signal->getDataPtr();
2272
addfragptr.i = conf->senderData;
2273
ptrCheckGuard(addfragptr, caddfragrecFileSize, addFragRecord);
2276
switch(refToMain(conf->senderRef)){
2279
ref = calcInstanceBlockRef(DBTUP);
2283
tabptr.i = addfragptr.p->m_dropFragReq.tableId;
2284
ptrCheckGuard(tabptr, ctabrecFileSize, tablerec);
2285
if (DictTabInfo::isOrderedIndex(tabptr.p->tableType))
2288
ref = calcInstanceBlockRef(DBTUX);
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,
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);
2316
releaseAddfragrec(signal);
2319
/* ************>> */
2321
/* ************>> */
2322
void Dblqh::execTUXFRAGREF(Signal* signal)
2325
execTUPFRAGREF(signal);
2326
}//Dblqh::execTUXFRAGREF
2329
Dblqh::execPREP_DROP_TAB_REQ(Signal* signal){
2332
PrepDropTabReq* req = (PrepDropTabReq*)signal->getDataPtr();
2334
Uint32 senderRef = req->senderRef;
2335
Uint32 senderData = req->senderData;
2338
tabPtr.i = req->tableId;
2339
ptrCheckGuard(tabPtr, ctabrecFileSize, tablerec);
2342
switch(tabPtr.p->tableStatus) {
2343
case Tablerec::TABLE_DEFINED:
2346
case Tablerec::NOT_DEFINED:
2349
case Tablerec::ADD_TABLE_ONGOING:
2351
errCode = PrepDropTabRef::NoSuchTable;
2353
case Tablerec::PREP_DROP_TABLE_DONE:
2355
errCode = PrepDropTabRef::DropInProgress;
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:
2363
errCode = PrepDropTabRef::DropInProgress;
2364
case Tablerec::TABLE_READ_ONLY:
2366
errCode = PrepDropTabRef::InvalidTableState;
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);
2384
tabPtr.p->tableStatus = Tablerec::PREP_DROP_TABLE_DONE;
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);
2395
Dblqh::dropTab_wait_usage(Signal* signal){
2398
tabPtr.i = signal->theData[1];
2399
ptrCheckGuard(tabPtr, ctabrecFileSize, tablerec);
2401
Uint32 senderRef = signal->theData[2];
2402
Uint32 senderData = signal->theData[3];
2404
ndbrequire(tabPtr.p->tableStatus == Tablerec::DROP_TABLE_WAIT_USAGE);
2406
if (tabPtr.p->usageCountR > 0 || tabPtr.p->usageCountW > 0)
2409
sendSignalWithDelay(reference(), GSN_CONTINUEB, signal, 100, 4);
2413
bool lcpDone = true;
2415
ptrAss(lcpPtr, lcpRecord);
2416
if(lcpPtr.p->lcpState != LcpRecord::LCP_IDLE)
2420
if(lcpPtr.p->currentFragment.lcpFragOrd.tableId == tabPtr.i)
2426
if(lcpPtr.p->lcpQueued &&
2427
lcpPtr.p->queuedFragment.lcpFragOrd.tableId == tabPtr.i)
2437
sendSignalWithDelay(reference(), GSN_CONTINUEB, signal, 100, 4);
2441
tabPtr.p->tableStatus = Tablerec::DROP_TABLE_WAIT_DONE;
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);
2452
Dblqh::execDROP_TAB_REQ(Signal* signal){
2455
DropTabReq reqCopy = * (DropTabReq*)signal->getDataPtr();
2456
DropTabReq* req = &reqCopy;
2459
tabPtr.i = req->tableId;
2460
ptrCheckGuard(tabPtr, ctabrecFileSize, tablerec);
2463
switch((DropTabReq::RequestType)req->requestType) {
2464
case DropTabReq::RestartDropTab:
2466
tabPtr.p->tableStatus = Tablerec::DROP_TABLE_WAIT_DONE;
2468
case DropTabReq::CreateTabDrop:
2470
tabPtr.p->tableStatus = Tablerec::DROP_TABLE_WAIT_DONE;
2472
case DropTabReq::OnlineDropTab:
2474
switch(tabPtr.p->tableStatus) {
2475
case Tablerec::TABLE_DEFINED:
2477
errCode = DropTabRef::DropWoPrep;
2479
case Tablerec::NOT_DEFINED:
2481
errCode = DropTabRef::NoSuchTable;
2483
case Tablerec::ADD_TABLE_ONGOING:
2486
case Tablerec::PREP_DROP_TABLE_DONE:
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);
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:
2501
case Tablerec::DROP_TABLE_WAIT_DONE:
2504
case Tablerec::TABLE_READ_ONLY:
2506
errCode = DropTabRef::InvalidTableState;
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);
2524
ndbrequire(tabPtr.p->usageCountR == 0 && tabPtr.p->usageCountW == 0);
2525
seizeAddfragrec(signal);
2526
addfragptr.p->m_dropTabReq = * req;
2527
dropTable_nextStep(signal, addfragptr);
2531
Dblqh::execDROP_TAB_REF(Signal* signal)
2534
DropTabRef * ref = (DropTabRef*)signal->getDataPtr();
2536
#if defined ERROR_INSERT || defined VM_TRACE
2537
jamLine(ref->errorCode);
2541
Ptr<AddFragRecord> addFragPtr;
2542
addFragPtr.i = ref->senderData;
2543
ptrCheckGuard(addFragPtr, caddfragrecFileSize, addFragRecord);
2544
dropTable_nextStep(signal, addFragPtr);
2548
Dblqh::execDROP_TAB_CONF(Signal* signal)
2551
DropTabConf * conf = (DropTabConf*)signal->getDataPtr();
2553
Ptr<AddFragRecord> addFragPtr;
2554
addFragPtr.i = conf->senderData;
2555
ptrCheckGuard(addFragPtr, caddfragrecFileSize, addFragRecord);
2556
dropTable_nextStep(signal, addFragPtr);
2560
Dblqh::dropTable_nextStep(Signal* signal, Ptr<AddFragRecord> addFragPtr)
2565
tabPtr.i = addFragPtr.p->m_dropTabReq.tableId;
2566
ptrCheckGuard(tabPtr, ctabrecFileSize, tablerec);
2569
if (tabPtr.p->tableStatus == Tablerec::DROP_TABLE_WAIT_DONE)
2572
if (DictTabInfo::isTable(tabPtr.p->tableType) ||
2573
DictTabInfo::isHashIndex(tabPtr.p->tableType))
2576
ref = calcInstanceBlockRef(DBACC);
2577
tabPtr.p->tableStatus = Tablerec::DROP_TABLE_ACC;
2582
ref = calcInstanceBlockRef(DBTUP);
2583
tabPtr.p->tableStatus = Tablerec::DROP_TABLE_TUP;
2586
else if (tabPtr.p->tableStatus == Tablerec::DROP_TABLE_ACC)
2589
ref = calcInstanceBlockRef(DBTUP);
2590
tabPtr.p->tableStatus = Tablerec::DROP_TABLE_TUP;
2592
else if (tabPtr.p->tableStatus == Tablerec::DROP_TABLE_TUP)
2595
if (DictTabInfo::isOrderedIndex(tabPtr.p->tableType))
2598
ref = calcInstanceBlockRef(DBTUX);
2599
tabPtr.p->tableStatus = Tablerec::DROP_TABLE_TUX;
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);
2617
removeTable(tabPtr.i);
2618
tabPtr.p->tableStatus = Tablerec::NOT_DEFINED;
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);
2627
addfragptr = addFragPtr;
2628
releaseAddfragrec(signal);
2631
void Dblqh::removeTable(Uint32 tableId)
2634
ptrCheckGuard(tabptr, ctabrecFileSize, tablerec);
2636
for (Uint32 i = 0; i < MAX_FRAG_PER_NODE; i++) {
2638
if (tabptr.p->fragid[i] != ZNIL) {
2640
deleteFragrec(tabptr.p->fragid[i]);
2643
}//Dblqh::removeTable()
2646
Dblqh::execALTER_TAB_REQ(Signal* signal)
2650
if(!assembleFragments(signal))
2653
AlterTabReq copy = *(AlterTabReq*)signal->getDataPtr();
2654
const AlterTabReq* req = ©
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;
2663
TablerecPtr tablePtr;
2664
tablePtr.i = tableId;
2665
ptrCheckGuard(tablePtr, ctabrecFileSize, tablerec);
2667
Uint32 len = signal->getLength();
2668
switch (requestType) {
2669
case AlterTabReq::AlterTablePrepare:
2672
case AlterTabReq::AlterTableRevert:
2674
tablePtr.p->schemaVersion = tableVersion;
2676
case AlterTabReq::AlterTableCommit:
2678
tablePtr.p->schemaVersion = newTableVersion;
2679
if (AlterTableReq::getReorgFragFlag(req->changeMask))
2682
commit_reorg(tablePtr);
2685
case AlterTabReq::AlterTableComplete:
2688
case AlterTabReq::AlterTableSumaEnable:
2691
case AlterTabReq::AlterTableSumaFilter:
2693
signal->theData[len++] = cnewestGci + 3;
2695
case AlterTabReq::AlterTableReadOnly:
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);
2705
case AlterTabReq::AlterTableReadWrite:
2707
ndbrequire(tablePtr.p->tableStatus == Tablerec::TABLE_READ_ONLY);
2708
tablePtr.p->tableStatus = Tablerec::TABLE_DEFINED;
2715
EXECUTE_DIRECT(DBTUP, GSN_ALTER_TAB_REQ, signal, len);
2718
Uint32 errCode = signal->theData[0];
2719
Uint32 connectPtr = signal->theData[1];
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);
2730
else if (errCode == ~Uint32(0))
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);
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);
2758
Dblqh::wait_reorg_suma_filter_enabled(Signal* signal)
2760
if (cnewestCompletedGci >= signal->theData[1])
2763
Uint32 senderData = signal->theData[2];
2764
Uint32 connectPtr = signal->theData[3];
2765
Uint32 senderRef = signal->theData[4];
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);
2775
sendSignalWithDelay(reference(), GSN_CONTINUEB, signal, 500, 5);
2779
Dblqh::commit_reorg(TablerecPtr tablePtr)
2781
for (Uint32 i = 0; i < MAX_FRAG_PER_NODE; i++)
2784
Ptr<Fragrecord> fragPtr;
2785
if ((fragPtr.i = tablePtr.p->fragrec[i]) != RNIL)
2788
c_fragment_pool.getPtr(fragPtr);
2789
fragPtr.p->fragDistributionKey = (fragPtr.p->fragDistributionKey+1)&0xFF;
2795
Dblqh::wait_readonly(Signal* signal)
2799
Uint32 tableId = signal->theData[1];
2801
TablerecPtr tablePtr;
2802
tablePtr.i = tableId;
2803
ptrCheckGuard(tablePtr, ctabrecFileSize, tablerec);
2804
ndbrequire(tablePtr.p->tableStatus == Tablerec::TABLE_READ_ONLY);
2806
if (tablePtr.p->usageCountW > 0)
2809
sendSignalWithDelay(reference(), GSN_CONTINUEB, signal, 3000,
2810
signal->getLength());
2814
Uint32 senderRef = signal->theData[2];
2815
Uint32 senderData = signal->theData[3];
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);
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)
2835
cLqhTimeOutCount ++;
2836
cLqhTimeOutCheckCount ++;
2838
for (logPartPtr.i = 0; logPartPtr.i < clogPartFileSize; logPartPtr.i++)
2841
ptrCheckGuard(logPartPtr, clogPartFileSize, logPartRecord);
2842
int ret = logPartPtr.p->m_io_tracker.tick(10 * cLqhTimeOutCount,
2844
c_max_redo_lag_counter);
2850
update_log_problem(signal, logPartPtr,
2851
LogPartRecord::P_REDO_IO_PROBLEM, true);
2858
update_log_problem(signal, logPartPtr,
2859
LogPartRecord::P_REDO_IO_PROBLEM, false);
2863
if (cLqhTimeOutCheckCount < 1000) {
2868
cLqhTimeOutCheckCount = 0;
2870
TcConnectionrecPtr tTcConptr;
2872
for (tTcConptr.i = 0; tTcConptr.i < ctcConnectrecFileSize;
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;
2884
signal->theData[0] = 2307;
2885
signal->theData[1] = tTcConptr.i;
2886
execDUMP_STATE_ORD(signal);
2889
tTcConptr.p->tcTimer = 0;
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;
2911
LcpRecordPtr TlcpPtr;
2912
// Print information about the current local checkpoint
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;
2925
}//Dblqh::execTIME_SIGNAL()
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
/* ######################################################################### */
2935
void Dblqh::noFreeRecordLab(Signal* signal,
2936
const LqhKeyReq * lqhKeyReq,
2940
const Uint32 transid1 = lqhKeyReq->transId1;
2941
const Uint32 transid2 = lqhKeyReq->transId2;
2942
const Uint32 reqInfo = lqhKeyReq->requestInfo;
2944
if(errCode == ZNO_FREE_MARKER_RECORDS_ERROR ||
2945
errCode == ZNODE_SHUTDOWN_IN_PROGESS ||
2946
errCode == ZNODE_FAILURE_ERROR){
2948
releaseTcrec(signal, tcConnectptr);
2951
if (LqhKeyReq::getDirtyFlag(reqInfo) &&
2952
LqhKeyReq::getOperation(reqInfo) == ZREAD &&
2953
!LqhKeyReq::getNormalProtocolFlag(reqInfo)){
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];
2960
TcKeyRef * const tcKeyRef = (TcKeyRef *) signal->getDataPtrSend();
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);
2969
/* All ops apart from dirty read send LQHKEYREF to TC
2970
* (This includes simple read)
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];
2979
TcOprec = lqhKeyReq->variableData[0];
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);
2992
}//Dblqh::noFreeRecordLab()
2995
Dblqh::get_table_state_error(Ptr<Tablerec> tabPtr) const
2997
switch(tabPtr.p->tableStatus){
2998
case Tablerec::NOT_DEFINED:
3000
return ZTABLE_NOT_DEFINED;
3002
case Tablerec::ADD_TABLE_ONGOING:
3004
case Tablerec::PREP_DROP_TABLE_DONE:
3006
case Tablerec::DROP_TABLE_WAIT_USAGE:
3008
case Tablerec::DROP_TABLE_WAIT_DONE:
3010
case Tablerec::DROP_TABLE_ACC:
3012
case Tablerec::DROP_TABLE_TUP:
3014
case Tablerec::DROP_TABLE_TUX:
3016
return PrepDropTabRef::DropInProgress;
3018
case Tablerec::TABLE_DEFINED:
3019
case Tablerec::TABLE_READ_ONLY:
3021
return ZTABLE_NOT_DEFINED;
3029
Dblqh::check_tabstate(Signal * signal, const Tablerec * tablePtrP, Uint32 op)
3031
if (tabptr.p->tableStatus == Tablerec::TABLE_READ_ONLY)
3034
if (op == ZREAD || op == ZREAD_EX || op == ZUNLOCK)
3039
terrorCode = ZTABLE_READ_ONLY;
3044
terrorCode = get_table_state_error(tabptr);
3046
abortErrorLab(signal);
3050
void Dblqh::LQHKEY_abort(Signal* signal, int errortype)
3052
switch (errortype) {
3055
terrorCode = ZCOPY_NODE_ERROR;
3059
terrorCode = ZNO_FREE_LQH_CONNECTION;
3063
terrorCode = signal->theData[1];
3067
ndbrequire((tcConnectptr.p->transactionState == TcConnectionrec::WAIT_ACC_ABORT) ||
3068
(tcConnectptr.p->transactionState == TcConnectionrec::ABORT_STOPPED) ||
3069
(tcConnectptr.p->transactionState == TcConnectionrec::ABORT_QUEUED));
3074
terrorCode = get_table_state_error(tabptr);
3078
terrorCode = ZINVALID_SCHEMA_VERSION;
3084
abortErrorLab(signal);
3085
}//Dblqh::LQHKEY_abort()
3087
void Dblqh::LQHKEY_error(Signal* signal, int errortype)
3089
switch (errortype) {
3116
}//Dblqh::LQHKEY_error()
3118
void Dblqh::execLQHKEYREF(Signal* signal)
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);
3131
ptrAss(tcConnectptr, tcConnectionrec);
3132
TcConnectionrec * const regTcPtr = tcConnectptr.p;
3134
if (likely(! ((regTcPtr->connectState == TcConnectionrec::LOG_CONNECTED) ||
3135
(regTcPtr->connectState == TcConnectionrec::COPY_CONNECTED))))
3138
* This...is unpleasant...
3139
* LOG_CONNECTED and COPY_CONNECTED will not release there tcConnectptr
3140
* before all outstanding is finished.
3142
* CONNECTED on the other hand can, (in ::execABORT)
3143
* which means that findTransaction *should* be used
3144
* to make sure that correct tcConnectptr is accessed.
3146
* However, as LOG_CONNECTED & COPY_CONNECTED only uses 1 tcConnectptr
3147
* (and fiddles) with transid and other stuff, I could
3148
* not find an easy way to modify the code so that findTransaction
3149
* is usable also for them
3151
if (findTransaction(transid1, transid2, tcOprec, 0) != ZOK)
3154
warningReport(signal, 14);
3159
switch (regTcPtr->connectState) {
3160
case TcConnectionrec::CONNECTED:
3162
if (regTcPtr->abortState != TcConnectionrec::ABORT_IDLE) {
3163
warningReport(signal, 15);
3166
abortErrorLab(signal);
3169
case TcConnectionrec::LOG_CONNECTED:
3171
logLqhkeyrefLab(signal);
3174
case TcConnectionrec::COPY_CONNECTED:
3176
copyLqhKeyRefLab(signal);
3180
warningReport(signal, 16);
3184
}//Dblqh::execLQHKEYREF()
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 */
3191
/* -------------------------------------------------------------------------- */
3192
void Dblqh::execPACKED_SIGNAL(Signal* signal)
3196
Uint32 TpackedData[28];
3197
Uint32 sig0, sig1, sig2, sig3 ,sig4, sig5, sig6;
3200
Tlength = signal->length();
3201
Uint32 TsenderRef = signal->getSendersBlockRef();
3202
Uint32 TcommitLen = 5;
3203
Uint32 Tgci_lo_mask = ~(Uint32)0;
3205
if (unlikely(!ndb_check_micro_gcp(getNodeInfo(refToNode(signal->getSendersBlockRef())).m_version)))
3213
Uint32 senderBlockRef = signal->getSendersBlockRef();
3216
ndbrequire(Tlength <= 25);
3217
MEMCOPY_NO_WORDS(&TpackedData[0], &signal->theData[0], Tlength);
3218
while (Tlength > Tstep) {
3219
switch (TpackedData[Tstep] >> 28) {
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;
3234
Tstep += TcommitLen;
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);
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;
3269
case ZREMOVE_MARKER:
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);
3279
case ZFIRE_TRIG_REQ:
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;
3300
signal->header.theSendersBlockRef = senderBlockRef;
3303
ndbrequire(Tlength == Tstep);
3305
}//Dblqh::execPACKED_SIGNAL()
3308
Dblqh::execREMOVE_MARKER_ORD(Signal* signal)
3310
CommitAckMarker key;
3311
key.transid1 = signal->theData[0];
3312
key.transid2 = signal->theData[1];
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);
3321
if (removedPtr.i != RNIL)
3324
m_commitAckMarkerPool.release(removedPtr);
3328
ndbout_c("%u Rem marker[%.8x %.8x]", instance(), key.transid1, key.transid2);
3333
/* -------------------------------------------------------------------------- */
3334
/* ------- ENTER SEND_PACKED ------- */
3335
/* Used to force a packed signal to be sent if local signal buffer is not */
3337
/* -------------------------------------------------------------------------- */
3338
void Dblqh::execSEND_PACKED(Signal* signal)
3340
HostRecordPtr Thostptr;
3342
UintR TpackedListIndex = cpackedListIndex;
3344
for (i = 0; i < TpackedListIndex; i++) {
3345
Thostptr.i = cpackedList[i];
3346
ptrAss(Thostptr, hostRecord);
3348
ndbrequire(Thostptr.i - 1 < MAX_NDB_NODES - 1);
3349
if (Thostptr.p->noOfPackedWordsLqh > 0) {
3351
sendPackedSignalLqh(signal, Thostptr.p);
3353
if (Thostptr.p->noOfPackedWordsTc > 0) {
3355
sendPackedSignalTc(signal, Thostptr.p);
3357
Thostptr.p->inPackedList = false;
3359
cpackedListIndex = 0;
3361
}//Dblqh::execSEND_PACKED()
3364
Dblqh::updatePackedList(Signal* signal, HostRecord * ahostptr, Uint16 hostId)
3366
Uint32 TpackedListIndex = cpackedListIndex;
3367
if (ahostptr->inPackedList == false) {
3369
ahostptr->inPackedList = true;
3370
cpackedList[TpackedListIndex] = hostId;
3371
cpackedListIndex = TpackedListIndex + 1;
3373
}//Dblqh::updatePackedList()
3376
Dblqh::execREAD_PSEUDO_REQ(Signal* signal){
3378
TcConnectionrecPtr regTcPtr;
3379
regTcPtr.i = signal->theData[0];
3380
ptrCheckGuard(regTcPtr, ctcConnectrecFileSize, tcConnectionrec);
3382
switch(signal->theData[1])
3384
case AttributeHeader::RANGE_NO:
3385
signal->theData[0] = regTcPtr.p->m_scan_curr_range_no;
3387
case AttributeHeader::ROW_COUNT:
3388
case AttributeHeader::COMMIT_COUNT:
3391
FragrecordPtr regFragptr;
3392
regFragptr.i = regTcPtr.p->fragmentptr;
3393
c_fragment_pool.getPtr(regFragptr);
3395
signal->theData[0] = regFragptr.p->accFragptr;
3396
EXECUTE_DIRECT(DBACC, GSN_READ_PSEUDO_REQ, signal, 2);
3399
case AttributeHeader::RECORDS_IN_RANGE:
3400
case AttributeHeader::INDEX_STAT_KEY:
3401
case AttributeHeader::INDEX_STAT_VALUE:
3404
// scanptr gets reset somewhere within the timeslice
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);
3412
case AttributeHeader::LOCK_REF:
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)
3420
signal->theData[0] = (getOwnNodeId() << 16) | regTcPtr.p->fragmentid;
3421
signal->theData[1] = regTcPtr.p->tcOprec;
3422
signal->theData[2] = (Uint32) regTcPtr.p->lqhKeyReqId;
3425
case AttributeHeader::OP_ID:
3428
memcpy(signal->theData, ®TcPtr.p->lqhKeyReqId, 8);
3431
case AttributeHeader::CORR_FACTOR64:
3435
tmp.i = regTcPtr.p->tcScanRec;
3438
c_scanRecordPool.getPtr(tmp);
3439
add = tmp.p->m_curr_batch_size_rows;
3442
signal->theData[0] = regTcPtr.p->m_corrFactorLo + add;
3443
signal->theData[1] = regTcPtr.p->m_corrFactorHi;
3451
/* ************>> */
3453
/* ************>> */
3454
void Dblqh::execTUPKEYCONF(Signal* signal)
3456
TcConnectionrec *regTcConnectionrec = tcConnectionrec;
3457
Uint32 ttcConnectrecFileSize = ctcConnectrecFileSize;
3458
const TupKeyConf * const tupKeyConf = (TupKeyConf *)signal->getDataPtr();
3459
Uint32 tcIndex = tupKeyConf->userPtr;
3461
tcConnectptr.i = tcIndex;
3462
ptrCheckGuard(tcConnectptr, ttcConnectrecFileSize, regTcConnectionrec);
3463
TcConnectionrec * regTcPtr = tcConnectptr.p;
3464
Uint32 activeCreat = regTcPtr->activeCreat;
3466
FragrecordPtr regFragptr;
3467
regFragptr.i = tcConnectptr.p->fragmentptr;
3468
c_fragment_pool.getPtr(regFragptr);
3469
fragptr = regFragptr;
3471
switch (tcConnectptr.p->transactionState) {
3472
case TcConnectionrec::WAIT_TUP:
3474
if (tcConnectptr.p->seqNoReplica == 0) // Primary replica
3475
tcConnectptr.p->noFiredTriggers = tupKeyConf->noFiredTriggers;
3476
tupkeyConfLab(signal);
3478
case TcConnectionrec::COPY_TUPKEY:
3480
copyTupkeyConfLab(signal);
3482
case TcConnectionrec::SCAN_TUPKEY:
3484
scanTupkeyConfLab(signal);
3486
case TcConnectionrec::WAIT_TUP_TO_ABORT:
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))
3495
ndbrequire(regTcPtr->m_nr_delete.m_cnt);
3496
regTcPtr->m_nr_delete.m_cnt--;
3497
if (regTcPtr->m_nr_delete.m_cnt)
3501
* Let operation wait for pending NR operations
3502
* even for before writing log...(as it's simpler)
3507
* Only disk table can have pending ops...
3509
TablerecPtr tablePtr;
3510
tablePtr.i = regTcPtr->tableref;
3511
ptrCheckGuard(tablePtr, ctabrecFileSize, tablerec);
3512
ndbrequire(tablePtr.p->m_disk_table);
3518
abortCommonLab(signal);
3520
case TcConnectionrec::WAIT_ACC_ABORT:
3521
case TcConnectionrec::ABORT_QUEUED:
3523
/* ------------------------------------------------------------------------- */
3524
/* IGNORE SINCE ABORT OF THIS OPERATION IS ONGOING ALREADY. */
3525
/* ------------------------------------------------------------------------- */
3532
}//Dblqh::execTUPKEYCONF()
3537
void Dblqh::execTUPKEYREF(Signal* signal)
3539
const TupKeyRef * const tupKeyRef = (TupKeyRef *)signal->getDataPtr();
3542
tcConnectptr.i = tupKeyRef->userRef;
3543
terrorCode = tupKeyRef->errorCode;
3544
ptrCheckGuard(tcConnectptr, ctcConnectrecFileSize, tcConnectionrec);
3545
TcConnectionrec* regTcPtr = tcConnectptr.p;
3546
Uint32 activeCreat = regTcPtr->activeCreat;
3548
FragrecordPtr regFragptr;
3549
regFragptr.i = regTcPtr->fragmentptr;
3550
c_fragment_pool.getPtr(regFragptr);
3551
fragptr = regFragptr;
3553
TRACE_OP(regTcPtr, "TUPKEYREF");
3555
if (unlikely(activeCreat == Fragrecord::AC_NR_COPY))
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);
3564
switch (tcConnectptr.p->transactionState) {
3565
case TcConnectionrec::WAIT_TUP:
3567
abortErrorLab(signal);
3569
case TcConnectionrec::COPY_TUPKEY:
3570
copyTupkeyRefLab(signal);
3572
case TcConnectionrec::SCAN_TUPKEY:
3574
scanTupkeyRefLab(signal);
3576
case TcConnectionrec::WAIT_TUP_TO_ABORT:
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);
3584
case TcConnectionrec::WAIT_ACC_ABORT:
3585
case TcConnectionrec::ABORT_QUEUED:
3587
/* ------------------------------------------------------------------------- */
3588
/* IGNORE SINCE ABORT OF THIS OPERATION IS ONGOING ALREADY. */
3589
/* ------------------------------------------------------------------------- */
3592
jamLine(tcConnectptr.p->transactionState);
3596
}//Dblqh::execTUPKEYREF()
3598
void Dblqh::sendPackedSignalLqh(Signal* signal, HostRecord * ahostptr)
3600
Uint32 noOfWords = ahostptr->noOfPackedWordsLqh;
3601
BlockReference hostRef = ahostptr->hostLqhBlockRef;
3602
MEMCOPY_NO_WORDS(&signal->theData[0],
3603
&ahostptr->packedWordsLqh[0],
3605
sendSignal(hostRef, GSN_PACKED_SIGNAL, signal, noOfWords, JBB);
3606
ahostptr->noOfPackedWordsLqh = 0;
3607
}//Dblqh::sendPackedSignalLqh()
3609
void Dblqh::sendPackedSignalTc(Signal* signal, HostRecord * ahostptr)
3611
Uint32 noOfWords = ahostptr->noOfPackedWordsTc;
3612
BlockReference hostRef = ahostptr->hostTcBlockRef;
3613
MEMCOPY_NO_WORDS(&signal->theData[0],
3614
&ahostptr->packedWordsTc[0],
3616
sendSignal(hostRef, GSN_PACKED_SIGNAL, signal, noOfWords, JBB);
3617
ahostptr->noOfPackedWordsTc = 0;
3618
}//Dblqh::sendPackedSignalTc()
3620
void Dblqh::sendCommitLqh(Signal* signal, BlockReference alqhBlockref)
3622
HostRecordPtr Thostptr;
3623
Thostptr.i = refToNode(alqhBlockref);
3624
ptrCheckGuard(Thostptr, chostFileSize, hostRecord);
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;
3634
if (unlikely(!ndb_check_micro_gcp(getNodeInfo(Thostptr.i).m_version)))
3637
ndbassert(Tdata[4] == 0 || getNodeInfo(Thostptr.i).m_version == 0);
3641
// currently packed signal cannot address specific instance
3642
const bool send_unpacked = getNodeInfo(Thostptr.i).m_lqh_workers != 0;
3643
if (send_unpacked) {
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);
3656
if (Thostptr.p->noOfPackedWordsLqh > 25 - 5) {
3658
sendPackedSignalLqh(signal, Thostptr.p);
3661
updatePackedList(signal, Thostptr.p, Thostptr.i);
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;
3670
void Dblqh::sendCompleteLqh(Signal* signal, BlockReference alqhBlockref)
3672
HostRecordPtr Thostptr;
3673
Thostptr.i = refToNode(alqhBlockref);
3674
ptrCheckGuard(Thostptr, chostFileSize, hostRecord);
3677
Tdata[0] = tcConnectptr.p->clientConnectrec;
3678
Tdata[1] = tcConnectptr.p->transid[0];
3679
Tdata[2] = tcConnectptr.p->transid[1];
3682
// currently packed signal cannot address specific instance
3683
const bool send_unpacked = getNodeInfo(Thostptr.i).m_lqh_workers != 0;
3684
if (send_unpacked) {
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);
3697
if (Thostptr.p->noOfPackedWordsLqh > 22) {
3699
sendPackedSignalLqh(signal, Thostptr.p);
3702
updatePackedList(signal, Thostptr.p, Thostptr.i);
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;
3711
void Dblqh::sendCommittedTc(Signal* signal, BlockReference atcBlockref)
3713
if (refToInstance(atcBlockref))
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);
3723
HostRecordPtr Thostptr;
3724
Thostptr.i = refToNode(atcBlockref);
3725
ptrCheckGuard(Thostptr, chostFileSize, hostRecord);
3728
Tdata[0] = tcConnectptr.p->clientConnectrec;
3729
Tdata[1] = tcConnectptr.p->transid[0];
3730
Tdata[2] = tcConnectptr.p->transid[1];
3733
// currently TC is single-threaded
3734
const bool send_unpacked = false;
3735
if (send_unpacked) {
3737
memcpy(&signal->theData[0], &Tdata[0], len << 2);
3738
BlockReference tcRef = Thostptr.p->hostTcBlockRef;
3739
sendSignal(tcRef, GSN_COMMITTED, signal, len, JBB);
3743
if (Thostptr.p->noOfPackedWordsTc > 22) {
3745
sendPackedSignalTc(signal, Thostptr.p);
3748
updatePackedList(signal, Thostptr.p, Thostptr.i);
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;
3757
void Dblqh::sendCompletedTc(Signal* signal, BlockReference atcBlockref)
3759
if (refToInstance(atcBlockref))
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);
3769
HostRecordPtr Thostptr;
3770
Thostptr.i = refToNode(atcBlockref);
3771
ptrCheckGuard(Thostptr, chostFileSize, hostRecord);
3774
Tdata[0] = tcConnectptr.p->clientConnectrec;
3775
Tdata[1] = tcConnectptr.p->transid[0];
3776
Tdata[2] = tcConnectptr.p->transid[1];
3779
// currently TC is single-threaded
3780
const bool send_unpacked = false;
3781
if (send_unpacked) {
3783
memcpy(&signal->theData[0], &Tdata[0], len << 2);
3784
BlockReference tcRef = Thostptr.p->hostTcBlockRef;
3785
sendSignal(tcRef, GSN_COMMITTED, signal, len, JBB);
3789
if (Thostptr.p->noOfPackedWordsTc > 22) {
3791
sendPackedSignalTc(signal, Thostptr.p);
3794
updatePackedList(signal, Thostptr.p, Thostptr.i);
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;
3803
void Dblqh::sendLqhkeyconfTc(Signal* signal, BlockReference atcBlockref)
3805
LqhKeyConf* lqhKeyConf;
3806
HostRecordPtr Thostptr;
3809
Thostptr.i = refToNode(atcBlockref);
3810
ptrCheckGuard(Thostptr, chostFileSize, hostRecord);
3811
if (refToBlock(atcBlockref) == DBTC) {
3813
/*******************************************************************
3814
// This signal was intended for DBTC as part of the normal transaction
3816
********************************************************************/
3817
if (Thostptr.p->noOfPackedWordsTc > (25 - LqhKeyConf::SignalLength)) {
3819
sendPackedSignalTc(signal, Thostptr.p);
3822
updatePackedList(signal, Thostptr.p, Thostptr.i);
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()) {
3831
/*******************************************************************
3832
// This signal was intended for DBLQH as part of log execution or
3834
********************************************************************/
3835
if (Thostptr.p->noOfPackedWordsLqh > (25 - LqhKeyConf::SignalLength)) {
3837
sendPackedSignalLqh(signal, Thostptr.p);
3840
updatePackedList(signal, Thostptr.p, Thostptr.i);
3842
lqhKeyConf = (LqhKeyConf *)
3843
&Thostptr.p->packedWordsLqh[Thostptr.p->noOfPackedWordsLqh];
3844
Thostptr.p->noOfPackedWordsLqh += LqhKeyConf::SignalLength;
3847
lqhKeyConf = (LqhKeyConf *)signal->getDataPtrSend();
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;
3866
lqhKeyConf->connectPtr = tcConnectptr.i;
3867
if (instance() == refToInstance(atcBlockref) &&
3868
(Thostptr.i == 0 || Thostptr.i == getOwnNodeId()))
3871
* This EXECUTE_DIRECT is multi-thread safe, as we only get here
3872
* for RESTORE block.
3874
EXECUTE_DIRECT(refToMain(atcBlockref), GSN_LQHKEYCONF,
3875
signal, LqhKeyConf::SignalLength);
3879
sendSignal(atcBlockref, GSN_LQHKEYCONF,
3880
signal, LqhKeyConf::SignalLength, JBB);
3883
}//Dblqh::sendLqhkeyconfTc()
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
3889
* ************************************************************************>> */
3890
void Dblqh::execKEYINFO(Signal* signal)
3892
Uint32 tcOprec = signal->theData[0];
3893
Uint32 transid1 = signal->theData[1];
3894
Uint32 transid2 = signal->theData[2];
3896
if (findTransaction(transid1, transid2, tcOprec, 0) != ZOK) {
3901
receive_keyinfo(signal,
3902
signal->theData+KeyInfo::HeaderLength,
3903
signal->getLength()-KeyInfo::HeaderLength);
3907
Dblqh::receive_keyinfo(Signal* signal,
3908
Uint32 * data, Uint32 len)
3910
TcConnectionrec * const regTcPtr = tcConnectptr.p;
3911
TcConnectionrec::TransactionState state = regTcPtr->transactionState;
3912
if (state != TcConnectionrec::WAIT_TUPKEYINFO &&
3913
state != TcConnectionrec::WAIT_SCAN_AI)
3916
/*****************************************************************************/
3917
/* TRANSACTION WAS ABORTED, THIS IS MOST LIKELY A SIGNAL BELONGING TO THE */
3918
/* ABORTED TRANSACTION. THUS IGNORE THE SIGNAL. */
3919
/*****************************************************************************/
3924
handleLongTupKey(signal, data, len);
3926
if (errorCode != 0) {
3927
if (errorCode == 1) {
3932
terrorCode = errorCode;
3933
if(state == TcConnectionrec::WAIT_TUPKEYINFO)
3934
abortErrorLab(signal);
3936
abort_scan(signal, regTcPtr->tcScanRec, errorCode);
3939
if(state == TcConnectionrec::WAIT_TUPKEYINFO)
3941
FragrecordPtr regFragptr;
3942
regFragptr.i = regTcPtr->fragmentptr;
3943
c_fragment_pool.getPtr(regFragptr);
3944
fragptr = regFragptr;
3945
endgettupkeyLab(signal);
3948
}//Dblqh::execKEYINFO()
3950
/* ------------------------------------------------------------------------- */
3951
/* FILL IN KEY DATA INTO DATA BUFFERS. */
3952
/* ------------------------------------------------------------------------- */
3953
Uint32 Dblqh::handleLongTupKey(Signal* signal,
3957
TcConnectionrec * const regTcPtr = tcConnectptr.p;
3958
Uint32 total = regTcPtr->save1 + len;
3959
Uint32 primKeyLen = regTcPtr->primKeyLen;
3961
if (unlikely(total > primKeyLen))
3964
* DBLQH 6.3 has the bad taste to send more KEYINFO than what is
3965
* really in the key...up to 3 words extra
3967
Uint32 extra = total - primKeyLen;
3968
ndbrequire(extra <= 3);
3969
ndbrequire(len > extra);
3973
bool ok= appendToSection(regTcPtr->keyInfoIVal,
3979
return ZGET_DATAREC_ERROR;
3982
regTcPtr->save1 = total;
3983
return (total >= primKeyLen ? 0 : 1);
3984
}//Dblqh::handleLongTupKey()
3986
/* ------------------------------------------------------------------------- */
3987
/* ------- HANDLE ATTRINFO SIGNALS ------- */
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)
3997
Uint32 tcOprec = signal->theData[0];
3998
Uint32 transid1 = signal->theData[1];
3999
Uint32 transid2 = signal->theData[2];
4001
if (findTransaction(transid1,
4003
tcOprec, 0) != ZOK) {
4008
receive_attrinfo(signal,
4009
signal->getDataPtrSend()+AttrInfo::HeaderLength,
4010
signal->getLength()-AttrInfo::HeaderLength);
4011
}//Dblqh::execATTRINFO()
4014
Dblqh::receive_attrinfo(Signal* signal, Uint32 * dataPtr, Uint32 length)
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:
4025
fragptr.i = regTcPtr->fragmentptr;
4026
c_fragment_pool.getPtr(fragptr);
4027
lqhAttrinfoLab(signal, dataPtr, length);
4028
endgettupkeyLab(signal);
4032
case TcConnectionrec::WAIT_SCAN_AI:
4034
scanAttrinfoLab(signal, dataPtr, length);
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:
4044
aiStateErrorCheckLab(signal, dataPtr,length);
4049
ndbrequire(regTcPtr->abortState != TcConnectionrec::ABORT_IDLE);
4052
} else if (currReclenAi < totReclenAi) {
4054
switch (regTcPtr->transactionState) {
4055
case TcConnectionrec::WAIT_ATTR:
4057
lqhAttrinfoLab(signal, dataPtr, length);
4060
case TcConnectionrec::WAIT_SCAN_AI:
4062
scanAttrinfoLab(signal, dataPtr, length);
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:
4072
aiStateErrorCheckLab(signal, dataPtr, length);
4077
ndbrequire(regTcPtr->abortState != TcConnectionrec::ABORT_IDLE);
4081
switch (regTcPtr->transactionState) {
4082
case TcConnectionrec::WAIT_SCAN_AI:
4084
scanAttrinfoLab(signal, dataPtr, length);
4088
ndbout_c("%d", regTcPtr->transactionState);
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)
4104
TcConnectionrec *regTcConnectionrec = tcConnectionrec;
4105
Uint32 tcIndex = signal->theData[0];
4106
Uint32 ttcConnectrecFileSize = ctcConnectrecFileSize;
4108
tcConnectptr.i = tcIndex;
4109
ptrCheckGuard(tcConnectptr, ttcConnectrecFileSize, regTcConnectionrec);
4110
TcConnectionrec * const regTcPtr = tcConnectptr.p;
4112
ndbrequire(regTcPtr->transactionState == TcConnectionrec::WAIT_TUP);
4114
/* TUP_ATTRINFO signal is unrelated to ATTRINFO
4115
* It just transports a section IVAL from TUP back to
4118
ndbrequire(signal->header.theLength == 3);
4119
Uint32 tupAttrInfoWords= signal->theData[1];
4120
Uint32 tupAttrInfoIVal= signal->theData[2];
4122
ndbassert(tupAttrInfoWords > 0);
4123
ndbassert(tupAttrInfoIVal != RNIL);
4125
/* If we have stored ATTRINFO that we sent to TUP,
4128
if (regTcPtr->attrInfoIVal != RNIL)
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;
4137
/* Store reference to ATTRINFO from TUP */
4138
regTcPtr->attrInfoIVal= tupAttrInfoIVal;
4139
regTcPtr->currTupAiLen= tupAttrInfoWords;
4141
}//Dblqh::execTUP_ATTRINFO()
4143
/* ------------------------------------------------------------------------- */
4144
/* ------- HANDLE ATTRINFO FROM LQH ------- */
4146
/* ------------------------------------------------------------------------- */
4147
void Dblqh::lqhAttrinfoLab(Signal* signal, Uint32* dataPtr, Uint32 length)
4149
/* Store received AttrInfo in a long section */
4151
if (saveAttrInfoInSection(dataPtr, length) == ZOK) {
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);
4162
}//Dblqh::lqhAttrinfoLab()
4164
/* ------------------------------------------------------------------------- */
4165
/* ------ FIND TRANSACTION BY USING HASH TABLE ------- */
4167
/* ------------------------------------------------------------------------- */
4168
int Dblqh::findTransaction(UintR Transid1, UintR Transid2, UintR TcOprec,
4171
TcConnectionrec *regTcConnectionrec = tcConnectionrec;
4172
Uint32 ttcConnectrecFileSize = ctcConnectrecFileSize;
4173
TcConnectionrecPtr locTcConnectptr;
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 */
4187
tcConnectptr.i = locTcConnectptr.i;
4188
tcConnectptr.p = locTcConnectptr.p;
4192
/* THIS WAS NOT THE TRANSACTION WHICH WAS SOUGHT */
4193
locTcConnectptr.i = locTcConnectptr.p->nextHashRec;
4195
/* WE DID NOT FIND THE TRANSACTION, REPORT NOT FOUND */
4196
return (int)ZNOT_FOUND;
4197
}//Dblqh::findTransaction()
4199
/* ------------------------------------------------------------------------- */
4200
/* ------- SAVE ATTRINFO INTO ATTR SECTION ------- */
4202
/* ------------------------------------------------------------------------- */
4203
int Dblqh::saveAttrInfoInSection(const Uint32* dataPtr, Uint32 len)
4205
TcConnectionrec * const regTcPtr = tcConnectptr.p;
4207
bool ok= appendToSection(regTcPtr->attrInfoIVal,
4214
terrorCode = ZGET_ATTRINBUF_ERROR;
4215
return ZGET_ATTRINBUF_ERROR;
4218
if (regTcPtr->m_flags & TcConnectionrec::OP_SAVEATTRINFO)
4219
regTcPtr->currTupAiLen += len;
4222
} // saveAttrInfoInSection
4225
/* ==========================================================================
4226
* ======= SEIZE TC CONNECT RECORD =======
4228
* GETS A NEW TC CONNECT RECORD FROM FREELIST.
4229
* ========================================================================= */
4230
void Dblqh::seizeTcrec()
4232
TcConnectionrecPtr locTcConnectptr;
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()
4251
bool Dblqh::checkTransporterOverloaded(Signal* signal,
4252
const NodeBitmask& all,
4253
const LqhKeyReq* req)
4255
// nodes likely to be affected by this op
4258
Uint32 tc_node = refToNode(req->tcBlockref);
4259
if (tc_node < MAX_NODES) // not worth to crash here
4261
const Uint8 op = LqhKeyReq::getOperation(req->requestInfo);
4262
if (op == ZREAD || op == ZREAD_EX || op == ZUNLOCK) {
4264
Uint32 api_node = refToNode(req->variableData[0]);
4265
if (api_node < MAX_NODES) // not worth to crash here
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());
4277
return !mask.isclear();
4280
void Dblqh::execSIGNAL_DROPPED_REP(Signal* signal)
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
4288
if (!assembleDroppedFragments(signal))
4294
const SignalDroppedRep* rep = (SignalDroppedRep*) &signal->theData[0];
4295
Uint32 originalGSN= rep->originalGsn;
4297
DEBUG("SignalDroppedRep received for GSN " << originalGSN);
4299
switch(originalGSN) {
4303
/* Get original signal data - unfortunately it may
4304
* have been truncated. We must not read beyond
4306
* We will notify the client that their LQHKEYREQ
4309
const LqhKeyReq * const truncatedLqhKeyReq =
4310
(LqhKeyReq *) &rep->originalData[0];
4312
noFreeRecordLab(signal, truncatedLqhKeyReq, ZGET_DATAREC_ERROR);
4316
case GSN_SCAN_FRAGREQ:
4319
/* Get original signal data - unfortunately it may
4320
* have been truncated. We must not read beyond
4322
* We will notify the client that their SCAN_FRAGREQ
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;
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;
4339
sendSignal(signal->senderBlockRef(), GSN_SCAN_FRAGREF, signal,
4340
ScanFragRef::SignalLength, JBB);
4345
/* Don't expect dropped signals for other GSNs,
4348
SimulatedBlock::execSIGNAL_DROPPED_REP(signal);
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)
4362
UintR sig0, sig1, sig2, sig3, sig4, sig5;
4365
const LqhKeyReq * const lqhKeyReq = (LqhKeyReq *)signal->getDataPtr();
4366
SectionHandle handle(this, signal);
4369
const NodeBitmask& all = globalTransporterRegistry.get_status_overloaded();
4370
if (unlikely((!all.isclear() &&
4371
checkTransporterOverloaded(signal, all, lqhKeyReq))) ||
4372
ERROR_INSERTED_CLEAR(5047)) {
4374
releaseSections(handle);
4375
noFreeRecordLab(signal, lqhKeyReq, ZTRANSPORTER_OVERLOADED_ERROR);
4380
sig0 = lqhKeyReq->clientConnectPtr;
4381
if (cfirstfreeTcConrec != RNIL && !ERROR_INSERTED_CLEAR(5031)) {
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);
4393
if(ERROR_INSERTED(5038) &&
4394
refToNode(signal->getSendersBlockRef()) != getOwnNodeId()){
4396
releaseSections(handle);
4397
SET_ERROR_INSERT_VALUE(5039);
4401
cTotalLqhKeyReqCount++;
4402
c_Counters.operations++;
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)
4416
regTcPtr->m_flags|= TcConnectionrec::OP_ISLONGREQ;
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;
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;
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);
4439
if (unlikely(get_node_status(refToNode(sig5)) != ZNODE_UP))
4441
releaseSections(handle);
4442
noFreeRecordLab(signal, lqhKeyReq, ZNODE_FAILURE_ERROR);
4446
Uint32 senderVersion = getNodeInfo(refToNode(senderRef)).m_version;
4448
regTcPtr->tcScanInfo = lqhKeyReq->scanInfo;
4449
regTcPtr->indTakeOver = LqhKeyReq::getScanTakeOverFlag(attrLenFlags);
4450
regTcPtr->m_reorg = LqhKeyReq::getReorgFlag(attrLenFlags);
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;
4458
sig0 = lqhKeyReq->fragmentData;
4459
sig1 = lqhKeyReq->transId1;
4460
sig2 = lqhKeyReq->transId2;
4461
sig3 = lqhKeyReq->variableData[0];
4462
sig4 = lqhKeyReq->variableData[1];
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;
4471
regTcPtr->commitAckMarker = RNIL;
4472
if (LqhKeyReq::getMarkerFlag(Treqinfo))
4474
struct CommitAckMarker check;
4475
CommitAckMarkerPtr markerPtr;
4477
check.transid1 = regTcPtr->transid[0];
4478
check.transid2 = regTcPtr->transid[1];
4480
if (m_commitAckMarkerHash.find(markerPtr, check))
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.
4487
markerPtr.p->reference_count++;
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);
4496
m_commitAckMarkerHash.seize(markerPtr);
4497
if (markerPtr.i == RNIL)
4499
releaseSections(handle);
4500
noFreeRecordLab(signal, lqhKeyReq, ZNO_FREE_MARKER_RECORDS_ERROR);
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);
4513
ndbout_c("%u Add marker[%.8x %.8x] op: %u", instance(), markerPtr.p->transid1, markerPtr.p->transid2, tcConnectptr.i);
4516
regTcPtr->commitAckMarker = markerPtr.i;
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))
4530
regTcPtr->operation = op;
4531
regTcPtr->lockType = LqhKeyReq::getLockType(Treqinfo);
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
4544
if (regTcPtr->dirtyOp)
4546
ndbrequire(regTcPtr->opSimple);
4549
CRASH_INSERTION2(5041, (op == ZREAD &&
4550
(regTcPtr->opSimple || regTcPtr->dirtyOp) &&
4551
refToNode(signal->senderBlockRef()) != cownNodeid));
4553
regTcPtr->noFiredTriggers = lqhKeyReq->noFiredTriggers;
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];
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;
4569
UintR TstoredProcIndicator = LqhKeyReq::getStoredProcFlag(attrLenFlags);
4570
if (TstoredProcIndicator == 1) {
4571
regTcPtr->storedProcId = lqhKeyReq->variableData[nextPos] & ZNIL;
4574
UintR TreadLenAiIndicator = LqhKeyReq::getReturnedReadLenAIFlag(Treqinfo);
4575
if (TreadLenAiIndicator == 1) {
4576
regTcPtr->readlenAi = lqhKeyReq->variableData[nextPos] & ZNIL;
4580
Uint32 TanyValueFlag = LqhKeyReq::getCorrFactorFlag(Treqinfo);
4581
if (isLongReq && TanyValueFlag == 1)
4584
* For short lqhkeyreq, ai-length in-signal is stored in same pos...
4586
regTcPtr->m_corrFactorLo = lqhKeyReq->variableData[nextPos + 0];
4587
regTcPtr->m_corrFactorHi = lqhKeyReq->variableData[nextPos + 1];
4591
Uint32 Tdeferred = LqhKeyReq::getDeferredConstraints(Treqinfo);
4592
if (isLongReq && Tdeferred)
4594
regTcPtr->m_flags |= TcConnectionrec::OP_DEFERRED_CONSTRAINTS;
4595
regTcPtr->m_fire_trig_pass = 0;
4598
UintR TitcKeyLen = 0;
4599
Uint32 keyLenWithLQHReq = 0;
4600
UintR TreclenAiLqhkey = 0;
4604
/* Long LQHKEYREQ indicates Key and AttrInfo presence and
4605
* size via section lengths
4607
SegmentedSectionPtr keyInfoSection, attrInfoSection;
4609
handle.getSection(keyInfoSection,
4610
LqhKeyReq::KeyInfoSectionNum);
4612
ndbassert(keyInfoSection.i != RNIL);
4614
regTcPtr->keyInfoIVal= keyInfoSection.i;
4615
TitcKeyLen= keyInfoSection.sz;
4616
keyLenWithLQHReq= TitcKeyLen;
4618
Uint32 totalAttrInfoLen= 0;
4619
if (handle.getSection(attrInfoSection,
4620
LqhKeyReq::AttrInfoSectionNum))
4622
regTcPtr->attrInfoIVal= attrInfoSection.i;
4623
totalAttrInfoLen= attrInfoSection.sz;
4626
regTcPtr->reclenAiLqhkey = 0;
4627
regTcPtr->currReclenAi = totalAttrInfoLen;
4628
regTcPtr->totReclenAi = totalAttrInfoLen;
4630
/* Detach sections from the handle, we are now responsible
4631
* for freeing them when appropriate
4637
/* Short LQHKEYREQ, Key and Attr sizes are in
4638
* signal, along with some data
4640
TreclenAiLqhkey= LqhKeyReq::getAIInLqhKeyReq(Treqinfo);
4641
regTcPtr->reclenAiLqhkey = TreclenAiLqhkey;
4642
regTcPtr->currReclenAi = TreclenAiLqhkey;
4643
TitcKeyLen = LqhKeyReq::getKeyLen(Treqinfo);
4644
regTcPtr->totReclenAi = LqhKeyReq::getAttrLen(attrLenFlags);
4646
/* Note key can be length zero for NR when Rowid used */
4647
keyLenWithLQHReq= MIN(TitcKeyLen, LqhKeyReq::MaxKeyInfo);
4649
bool ok= appendToSection(regTcPtr->keyInfoIVal,
4650
&lqhKeyReq->variableData[ nextPos ],
4655
terrorCode= ZGET_DATAREC_ERROR;
4656
abortErrorLab(signal);
4660
nextPos+= keyLenWithLQHReq;
4663
regTcPtr->primKeyLen = TitcKeyLen;
4665
/* Only node restart copy allowed to send no KeyInfo */
4666
if (unlikely(keyLenWithLQHReq == 0))
4668
if (refToMain(senderRef) == DBSPJ)
4671
ndbassert(! LqhKeyReq::getNrCopyFlag(Treqinfo));
4672
terrorCode = ZNO_TUPLE_FOUND;
4673
abortErrorLab(signal);
4677
if (! LqhKeyReq::getNrCopyFlag(Treqinfo))
4679
LQHKEY_error(signal, 3);
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);
4690
sig2 = lqhKeyReq->variableData[nextPos + 0];
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
4695
regTcPtr->gci_hi = LqhKeyReq::getGCIFlag(Treqinfo) ? sig2 : sig3;
4696
regTcPtr->gci_lo = LqhKeyReq::getGCIFlag(Treqinfo) ? ~Uint32(0) : 0;
4697
nextPos += LqhKeyReq::getGCIFlag(Treqinfo);
4699
if (LqhKeyReq::getRowidFlag(Treqinfo))
4701
ndbassert(refToMain(senderRef) != DBTC);
4703
else if(op == ZINSERT)
4705
ndbassert(refToMain(senderRef) == DBTC);
4708
if ((LqhKeyReq::FixedSignalLength + nextPos + TreclenAiLqhkey) !=
4710
LQHKEY_error(signal, 2);
4713
UintR TseqNoReplica = regTcPtr->seqNoReplica;
4714
UintR TlastReplicaNo = regTcPtr->lastReplicaNo;
4715
if (TseqNoReplica == TlastReplicaNo) {
4717
regTcPtr->nextReplica = ZNIL;
4719
if (TseqNoReplica < TlastReplicaNo) {
4721
regTcPtr->nextSeqNoReplica = TseqNoReplica + 1;
4722
if ((regTcPtr->nextReplica == 0) ||
4723
(regTcPtr->nextReplica == cownNodeid)) {
4724
LQHKEY_error(signal, 0);
4727
LQHKEY_error(signal, 4);
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);
4744
localNextTcConnectptr.p->prevHashRec = tcConnectptr.i;
4746
if (tabptr.i >= ctabrecFileSize) {
4747
LQHKEY_error(signal, 5);
4750
ptrAss(tabptr, tablerec);
4751
if(table_version_major_lqhkeyreq(tabptr.p->schemaVersion) !=
4752
table_version_major_lqhkeyreq(schemaVersion)){
4753
LQHKEY_abort(signal, 5);
4757
if (unlikely(tabptr.p->tableStatus != Tablerec::TABLE_DEFINED))
4759
if (check_tabstate(signal, tabptr.p, op))
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);
4770
if (op == ZREAD || op == ZREAD_EX || op == ZUNLOCK)
4771
tabptr.p->usageCountR++;
4773
tabptr.p->usageCountW++;
4775
if (!getFragmentrec(signal, regTcPtr->fragmentid)) {
4776
LQHKEY_error(signal, 6);
4780
if (LqhKeyReq::getNrCopyFlag(Treqinfo))
4782
ndbassert(refToMain(senderRef) == DBLQH);
4783
ndbassert(LqhKeyReq::getRowidFlag(Treqinfo));
4784
if (! (fragptr.p->fragStatus == Fragrecord::ACTIVE_CREATION))
4786
ndbout_c("fragptr.p->fragStatus: %d",
4787
fragptr.p->fragStatus);
4788
CRASH_INSERTION(5046);
4790
ndbassert(fragptr.p->fragStatus == Fragrecord::ACTIVE_CREATION);
4791
fragptr.p->m_copy_started_state = Fragrecord::AC_NR_COPY;
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) {
4799
regTcPtr->activeCreat = fragptr.p->m_copy_started_state;
4800
CRASH_INSERTION(5002);
4801
CRASH_INSERTION2(5042, tabptr.i == c_error_insert_table_id);
4803
regTcPtr->activeCreat = Fragrecord::AC_NORMAL;
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))
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);
4827
LQHKEY_error(signal, 1);
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
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
4842
* Normal processing :
4843
* - LQH passes ATTRINFO section to TUP attached to direct TUPKEYREQ
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
4852
* Interpreted Update / Delete processing
4853
* - LQH passes ATTRINFO section to TUP attached to direct TUPKEYREQ
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
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)
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);
4878
attrInfoToPropagate &&
4879
(! tupCanChangePropagatedAttrInfo);
4882
regTcPtr->m_flags|= TcConnectionrec::OP_SAVEATTRINFO;
4884
/* Handle any AttrInfo we received with the LQHKEYREQ */
4885
if (regTcPtr->currReclenAi != 0)
4890
/* Long LQHKEYREQ */
4893
regTcPtr->currTupAiLen= saveAttrInfo ?
4894
regTcPtr->totReclenAi :
4899
/* Short LQHKEYREQ */
4902
/* Lets put the AttrInfo into a segmented section */
4903
bool ok= appendToSection(regTcPtr->attrInfoIVal,
4904
lqhKeyReq->variableData + nextPos,
4909
terrorCode= ZGET_DATAREC_ERROR;
4910
abortErrorLab(signal);
4915
regTcPtr->currTupAiLen= TreclenAiLqhkey;
4919
/* If we've received all KeyInfo, proceed with processing,
4920
* otherwise wait for discrete KeyInfo signals
4922
if (regTcPtr->primKeyLen == keyLenWithLQHReq) {
4923
endgettupkeyLab(signal);
4927
ndbassert(!isLongReq);
4928
/* Wait for remaining KeyInfo */
4929
regTcPtr->save1 = keyLenWithLQHReq;
4930
regTcPtr->transactionState = TcConnectionrec::WAIT_TUPKEYINFO;
4934
}//Dblqh::execLQHKEYREQ()
4940
* Invoked when all KeyInfo and/or all AttrInfo has been
4943
void Dblqh::endgettupkeyLab(Signal* signal)
4945
TcConnectionrec * const regTcPtr = tcConnectptr.p;
4946
if (regTcPtr->totReclenAi == regTcPtr->currReclenAi) {
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;
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. */
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. */
4970
/* THE FIRST STEP IN PROCESSING THE MESSAGE IS TO CONTACT DBACC. */
4971
/*------------------------------------------------------------------------*/
4972
switch (fragptr.p->fragStatus) {
4973
case Fragrecord::FSACTIVE:
4974
case Fragrecord::CRASH_RECOVERING:
4975
case Fragrecord::ACTIVE_CREATION:
4976
prepareContinueAfterBlockedLab(signal);
4979
case Fragrecord::BLOCKED:
4981
linkFragQueue(signal);
4982
regTcPtr->transactionState = TcConnectionrec::STOPPED;
4985
case Fragrecord::FREE:
4987
case Fragrecord::DEFINED:
4989
case Fragrecord::REMOVING:
4996
}//Dblqh::endgettupkeyLab()
4998
void Dblqh::prepareContinueAfterBlockedLab(Signal* signal)
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)
5017
handleUserUnlockRequest(signal);
5021
if (regTcPtr->indTakeOver == ZTRUE) {
5023
ttcScanOp = KeyInfo20::getScanOp(regTcPtr->tcScanInfo);
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);
5035
if (scanptr.i == RNIL) {
5037
takeOverErrorLab(signal);
5040
Uint32 accOpPtr= get_acc_ptr_from_scan_record(scanptr.p,
5043
if (accOpPtr == RNIL) {
5045
takeOverErrorLab(signal);
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,
5053
if (signal->theData[0] == (UintR)-1) {
5054
execACC_TO_REF(signal);
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. */
5066
/* BEFORE SENDING THE MESSAGE THE REQUEST INFORMATION IS SET */
5068
/* ----------------------------------------------------------------- */
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;
5083
TRACENR(" tab: " << regTcPtr->tableref
5084
<< " frag: " << regTcPtr->fragmentid
5085
<< " activeCreat: " << (Uint32)activeCreat);
5086
if (LqhKeyReq::getNrCopyFlag(regTcPtr->reqinfo))
5088
if (LqhKeyReq::getRowidFlag(regTcPtr->reqinfo))
5089
TRACENR(" rowid: " << regTcPtr->m_row_id);
5090
TRACENR(" key: " << getKeyInfoWordOrZero(regTcPtr, 0));
5093
if (likely(activeCreat == Fragrecord::AC_NORMAL))
5097
ndbassert(!LqhKeyReq::getNrCopyFlag(regTcPtr->reqinfo));
5098
exec_acckeyreq(signal, tcConnectptr);
5100
else if (activeCreat == Fragrecord::AC_NR_COPY)
5102
regTcPtr->totSendlenAi = regTcPtr->totReclenAi;
5103
handle_nr_copy(signal, tcConnectptr);
5107
ndbassert(activeCreat == Fragrecord::AC_IGNORED);
5109
TRACENR(" IGNORING (activeCreat == 2)" << endl);
5111
signal->theData[0] = tc_ptr_i;
5112
regTcPtr->transactionState = TcConnectionrec::WAIT_ACC_ABORT;
5114
signal->theData[0] = regTcPtr->tupConnectrec;
5115
EXECUTE_DIRECT(DBTUP, GSN_TUP_ABORTREQ, signal, 1);
5118
regTcPtr->totSendlenAi = regTcPtr->totReclenAi;
5119
packLqhkeyreqLab(signal);
5124
Dblqh::exec_acckeyreq(Signal* signal, TcConnectionrecPtr regTcPtr)
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);
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;
5149
sig0 = regTcPtr.p->transid[1];
5150
signal->theData[6] = sig0;
5152
/* Copy KeyInfo to end of ACCKEYREQ signal, starting at offset 7 */
5153
sendKeyinfoAcc(signal, 7);
5155
TRACE_OP(regTcPtr.p, "ACC");
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);
5163
} else if (signal->theData[0] == RNIL) {
5166
ndbrequire(signal->theData[0] == (UintR)-1);
5167
signal->theData[0] = regTcPtr.i;
5168
execACCKEYREF(signal);
5171
}//Dblqh::prepareContinueAfterBlockedLab()
5174
Dblqh::handle_nr_copy(Signal* signal, Ptr<TcConnectionrec> regTcPtr)
5177
Uint32 fragPtr = fragptr.p->tupFragptr;
5178
Uint32 op = regTcPtr.p->operation;
5180
const bool copy = LqhKeyReq::getNrCopyFlag(regTcPtr.p->reqinfo);
5182
if (!LqhKeyReq::getRowidFlag(regTcPtr.p->reqinfo))
5185
* Rowid not set, that mean that primary has finished copying...
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);
5196
regTcPtr.p->m_nr_delete.m_cnt = 1; // Wait for real op aswell
5197
Uint32* dst = signal->theData+24;
5199
const int len = c_tup->nr_read_pk(fragPtr, ®TcPtr.p->m_row_id, dst,
5201
const bool match = (len>0) ? compare_key(regTcPtr.p, dst, len) == 0 : false;
5204
TRACENR(" len: " << len << " match: " << match
5205
<< " uncommitted: " << uncommitted);
5209
ndbassert(LqhKeyReq::getGCIFlag(regTcPtr.p->reqinfo));
5216
ndbassert(op == ZINSERT);
5218
TRACENR(" Changing from INSERT to ZUPDATE" << endl);
5219
regTcPtr.p->operation = ZUPDATE;
5222
else if (len > 0 && op == ZDELETE)
5226
* Perform delete using rowid
5231
ndbassert(regTcPtr.p->primKeyLen == 0);
5233
TRACENR(" performing DELETE key: "
5236
nr_copy_delete_row(signal, regTcPtr, ®TcPtr.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)
5244
packLqhkeyreqLab(signal);
5247
else if (len == 0 && op == ZDELETE)
5254
TRACENR(" UPDATE_GCI" << endl);
5255
c_tup->nr_update_gci(fragPtr, ®TcPtr.p->m_row_id, regTcPtr.p->gci_hi);
5256
goto update_gci_ignore;
5260
* 1) Delete row at specified rowid (if len > 0)
5261
* 2) Delete specified row at different rowid (if exists)
5267
* 1) Delete row at specified rowid (if len > 0)
5270
nr_copy_delete_row(signal, regTcPtr, ®TcPtr.p->m_row_id, len);
5273
* 2) Delete specified row at different rowid (if exists)
5276
nr_copy_delete_row(signal, regTcPtr, 0, 0);
5278
TRACENR(" RUN INSERT" << endl);
5283
if (!match && op != ZINSERT)
5287
TRACENR(" IGNORE " << endl);
5293
if (op != ZDELETE && op != ZREFRESH)
5296
TRACENR(" Changing from INSERT/UPDATE to ZWRITE" << endl);
5297
regTcPtr.p->operation = ZWRITE;
5302
ndbassert(!match && op == ZINSERT);
5305
* 1) Delete row at specified rowid (if len > 0)
5306
* 2) Delete specified row at different rowid (if exists)
5312
* 1) Delete row at specified rowid (if len > 0)
5315
nr_copy_delete_row(signal, regTcPtr, ®TcPtr.p->m_row_id, len);
5319
* 2) Delete specified row at different rowid (if exists)
5322
nr_copy_delete_row(signal, regTcPtr, 0, 0);
5324
TRACENR(" RUN op: " << op << endl);
5330
exec_acckeyreq(signal, regTcPtr);
5335
ndbassert(!LqhKeyReq::getNrCopyFlag(regTcPtr.p->reqinfo));
5337
regTcPtr.p->activeCreat = Fragrecord::AC_IGNORED;
5338
signal->theData[0] = regTcPtr.p->tupConnectrec;
5339
EXECUTE_DIRECT(DBTUP, GSN_TUP_ABORTREQ, signal, 1);
5341
packLqhkeyreqLab(signal);
5345
* Compare received key data with the data supplied
5346
* returning 0 if they are the same, 1 otherwise
5349
Dblqh::compare_key(const TcConnectionrec* regTcPtr,
5350
const Uint32 * ptr, Uint32 len)
5352
if (regTcPtr->primKeyLen != len)
5355
ndbassert( regTcPtr->keyInfoIVal != RNIL );
5357
SectionReader keyInfoReader(regTcPtr->keyInfoIVal,
5358
getSectionSegmentPool());
5360
ndbassert(regTcPtr->primKeyLen == keyInfoReader.getSize());
5364
const Uint32* keyChunk= NULL;
5365
Uint32 chunkSize= 0;
5367
/* Get a ptr to a chunk of contiguous words to compare */
5368
bool ok= keyInfoReader.getWordsPtr(len, keyChunk, chunkSize);
5372
if ( memcmp(ptr, keyChunk, chunkSize << 2))
5383
Dblqh::nr_copy_delete_row(Signal* signal,
5384
Ptr<TcConnectionrec> regTcPtr,
5385
Local_key* rowid, Uint32 len)
5387
Ptr<Fragrecord> fragPtr = fragptr;
5390
Uint32 tableId = regTcPtr.p->tableref;
5391
Uint32 accPtr = regTcPtr.p->accConnectrec;
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];
5403
if (g_key_descriptor_pool.getPtr(tableId)->hasCharAttr)
5405
signal->theData[3] = calculateHash(tableId, signal->theData+24);
5409
signal->theData[3] = md5_hash((Uint64*)(signal->theData+24), len);
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;
5418
keylen = regTcPtr.p->primKeyLen;
5419
signal->theData[3] = regTcPtr.p->hashValue;
5420
signal->theData[4] = keylen;
5422
/* Copy KeyInfo inline into the ACCKEYREQ signal,
5423
* starting at word 7
5425
sendKeyinfoAcc(signal, 7);
5427
const Uint32 ref = refToMain(regTcPtr.p->tcAccBlockref);
5428
EXECUTE_DIRECT(ref, GSN_ACCKEYREQ, signal, 7 + keylen);
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
5435
if (retValue == (Uint32)-1)
5438
* Only delete by pk, may fail
5441
ndbrequire(rowid == 0);
5442
signal->theData[0] = accPtr;
5443
signal->theData[1] = 0;
5444
EXECUTE_DIRECT(ref, GSN_ACC_ABORTREQ, signal, 2);
5450
* We found row (and have it locked in ACC)
5452
ndbrequire(regTcPtr.p->m_dealloc == 0);
5453
Local_key save = regTcPtr.p->m_row_id;
5455
c_acc->execACCKEY_ORD(signal, accPtr);
5456
signal->theData[0] = accPtr;
5457
EXECUTE_DIRECT(ref, GSN_ACC_COMMITREQ, signal, 1);
5460
ndbrequire(regTcPtr.p->m_dealloc == 1);
5461
int ret = c_tup->nr_delete(signal, regTcPtr.i,
5462
fragPtr.p->tupFragptr, ®TcPtr.p->m_row_id,
5463
regTcPtr.p->gci_hi);
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;
5478
TRACENR("DELETED: " << regTcPtr.p->m_row_id << endl);
5480
regTcPtr.p->m_dealloc = 0;
5481
regTcPtr.p->m_row_id = save;
5483
tcConnectptr = regTcPtr;
5487
Dblqh::get_nr_op_info(Nr_op_info* op, Uint32 page_id)
5489
Ptr<TcConnectionrec> tcPtr;
5490
tcPtr.i = op->m_ptr_i;
5491
ptrCheckGuard(tcPtr, ctcConnectrecFileSize, tcConnectionrec);
5493
Ptr<Fragrecord> fragPtr;
5494
c_fragment_pool.getPtr(fragPtr, tcPtr.p->fragmentptr);
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;
5500
ndbrequire(tcPtr.p->activeCreat == Fragrecord::AC_NR_COPY);
5501
ndbrequire(tcPtr.p->m_nr_delete.m_cnt);
5504
if (page_id == RNIL)
5506
// get log buffer callback
5507
for (Uint32 i = 0; i<2; i++)
5509
if (tcPtr.p->m_nr_delete.m_page_id[i] != RNIL)
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];
5519
// get page callback
5520
for (Uint32 i = 0; i<2; i++)
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)
5527
op->m_disk_ref = key;
5528
tcPtr.p->m_nr_delete.m_page_id[i] = page_id;
5537
Dblqh::nr_delete_complete(Signal* signal, Nr_op_info* op)
5540
Ptr<TcConnectionrec> tcPtr;
5541
tcPtr.i = op->m_ptr_i;
5542
ptrCheckGuard(tcPtr, ctcConnectrecFileSize, tcConnectionrec);
5544
ndbrequire(tcPtr.p->activeCreat == Fragrecord::AC_NR_COPY);
5545
ndbrequire(tcPtr.p->m_nr_delete.m_cnt);
5547
tcPtr.p->m_nr_delete.m_cnt--;
5548
if (tcPtr.p->m_nr_delete.m_cnt == 0)
5551
tcConnectptr = tcPtr;
5552
c_fragment_pool.getPtr(fragptr, tcPtr.p->fragmentptr);
5554
if (tcPtr.p->abortState != TcConnectionrec::ABORT_IDLE)
5557
tcPtr.p->activeCreat = Fragrecord::AC_NORMAL;
5558
abortCommonLab(signal);
5560
else if (tcPtr.p->operation == ZDELETE &&
5561
LqhKeyReq::getNrCopyFlag(tcPtr.p->reqinfo))
5564
* This is run directly in handle_nr_copy
5567
packLqhkeyreqLab(signal);
5572
rwConcludedLab(signal);
5577
if (memcmp(&tcPtr.p->m_nr_delete.m_disk_ref[0],
5578
&op->m_disk_ref, sizeof(Local_key)) == 0)
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];
5588
Dblqh::readPrimaryKeys(Uint32 opPtrI, Uint32 * dst, bool xfrm)
5590
TcConnectionrecPtr regTcPtr;
5591
Uint64 Tmp[MAX_KEY_SIZE_IN_WORDS >> 1];
5594
regTcPtr.i = opPtrI;
5595
ptrCheckGuard(regTcPtr, ctcConnectrecFileSize, tcConnectionrec);
5597
Uint32 tableId = regTcPtr.p->tableref;
5598
Uint32 keyLen = regTcPtr.p->primKeyLen;
5599
Uint32 * tmp = xfrm ? (Uint32*)Tmp : dst;
5601
copy(tmp, regTcPtr.p->keyInfoIVal);
5606
Uint32 keyPartLen[MAX_ATTRIBUTES_IN_INDEX];
5607
return xfrm_key(tableId, (Uint32*)Tmp, dst, ~0, keyPartLen);
5614
* getKeyInfoWordOrZero
5615
* Get given word of KeyInfo, or zero if it's not available
5619
Dblqh::getKeyInfoWordOrZero(const TcConnectionrec* regTcPtr,
5622
if (regTcPtr->keyInfoIVal != RNIL)
5624
SectionReader keyInfoReader(regTcPtr->keyInfoIVal,
5625
g_sectionSegmentPool);
5627
if (keyInfoReader.getSize() > offset)
5630
keyInfoReader.step(offset);
5633
keyInfoReader.getWord(&word);
5640
void Dblqh::unlockError(Signal* signal, Uint32 error)
5643
abortErrorLab(signal);
5647
* handleUserUnlockRequest
5649
* This method handles an LQHKEYREQ unlock request from
5652
void Dblqh::handleUserUnlockRequest(Signal* signal)
5655
TcConnectionrec * const regTcPtr = tcConnectptr.p;
5656
Uint32 tcPtrI = tcConnectptr.i;
5658
/* Request to unlock (abort) an existing read operation
5660
* 1) Get user's LOCK_REF from KeyInfo
5662
* 2) Lookup TC_OP_REF in hash
5664
* 3) Check state of found op : TransId, state, type, lock
5666
* 4) Check op_id portion
5668
* 5) Abort locking op in ACC
5670
* 6) Clean up locking op in LQH
5672
* 7) Send LQHKEYCONF to TC for user unlock op
5674
* 8) Clean up user unlock op
5676
if (unlikely( regTcPtr->primKeyLen != LqhKeyReq::UnlockKeyLen ))
5679
unlockError(signal, 4109); /* Faulty primary key attribute length */
5683
SectionReader keyInfoReader(regTcPtr->keyInfoIVal,
5684
getSectionSegmentPool());
5686
ndbrequire( keyInfoReader.getSize() == regTcPtr->primKeyLen );
5688
/* Extract components of user lock reference */
5689
Uint32 tcOpRecIndex;
5691
ndbrequire( keyInfoReader.getWord( &tcOpRecIndex ) ); // Locking op TC index
5692
ndbrequire( keyInfoReader.getWord( &lqhOpIdWord ) ); // Part of Locking op LQH id
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.
5700
if (unlikely( findTransaction(regTcPtr->transid[0],
5701
regTcPtr->transid[1],
5706
unlockError(signal, ZBAD_OP_REF);
5710
TcConnectionrec * const regLockTcPtr = tcConnectptr.p;
5712
/* Validate that the bottom 32-bits of the operation id reference
5713
* we were given are in alignment
5715
Uint32 lockOpKeyReqId = (Uint32) regLockTcPtr->lqhKeyReqId;
5716
if (unlikely( lockOpKeyReqId != lqhOpIdWord ))
5719
unlockError(signal, ZBAD_OP_REF);
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
5732
( regLockTcPtr->transactionState == TcConnectionrec::PREPARED ) &&
5733
( regLockTcPtr->commitAckMarker == RNIL ) &&
5734
// No commit ack marker
5735
( regLockTcPtr->logWriteState ==
5736
TcConnectionrec::NOT_STARTED )); // No log written
5738
if (unlikely(! lockingOpValid))
5741
unlockError(signal, ZBAD_UNLOCK_STATE);
5745
/* Ok, now we're ready to start 'aborting' this operation, to get the
5746
* effect of unlocking it
5748
signal->theData[0] = regLockTcPtr->accConnectrec;
5749
signal->theData[1] = 0; // For Execute_Direct
5750
EXECUTE_DIRECT(refToMain(regLockTcPtr->tcAccBlockref),
5756
/* Would be nice to handle non-success case somehow */
5757
ndbrequire(signal->theData[1] == 0);
5759
/* Now we want to release LQH resources associated with the
5764
/* Now that the locking operation has been 'disappeared', we need to
5765
* send an LQHKEYCONF for the unlock operation and then 'disappear' it
5768
tcConnectptr.i = tcPtrI;
5769
ptrCheckGuard(tcConnectptr, ctcConnectrecFileSize, tcConnectionrec);
5771
ndbrequire( regTcPtr == tcConnectptr.p );
5773
/* Set readlenAi to the unlocked operation's TC operation ref */
5774
regTcPtr->readlenAi = tcOpRecIndex;
5776
/* Clear number of fired triggers */
5777
regTcPtr->noFiredTriggers = 0;
5779
/* Now send the LQHKEYCONF to TC */
5780
sendLqhkeyconfTc(signal, regTcPtr->tcBlockref);
5782
/* Finally, clean up the unlock operation itself */
5788
/* =*======================================================================= */
5789
/* ======= SEND KEYINFO TO ACC ======= */
5791
/* ========================================================================= */
5792
void Dblqh::sendKeyinfoAcc(Signal* signal, Uint32 Ti)
5794
/* Copy all KeyInfo into the signal at offset Ti */
5795
copy(&signal->theData[Ti],
5796
tcConnectptr.p->keyInfoIVal);
5797
}//Dblqh::sendKeyinfoAcc()
5799
void Dblqh::execLQH_ALLOCREQ(Signal* signal)
5801
TcConnectionrecPtr regTcPtr;
5802
FragrecordPtr regFragptr;
5805
regTcPtr.i = signal->theData[0];
5806
ptrCheckGuard(regTcPtr, ctcConnectrecFileSize, tcConnectionrec);
5808
regFragptr.i = regTcPtr.p->fragmentptr;
5809
c_fragment_pool.getPtr(regFragptr);
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()
5818
void Dblqh::execTUP_DEALLOCREQ(Signal* signal)
5820
TcConnectionrecPtr regTcPtr;
5823
regTcPtr.i = signal->theData[4];
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);
5834
if (signal->theData[5])
5839
tmp.m_page_no = signal->theData[2];
5840
tmp.m_page_idx = signal->theData[3];
5842
if (ERROR_INSERTED(5712))
5844
ndbout << "TUP_DEALLOC: " << tmp << endl;
5847
EXECUTE_DIRECT(DBTUP, GSN_TUP_DEALLOCREQ, signal, signal->getLength());
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];
5857
TRACE_OP(regTcPtr.p, "SET DEALLOC");
5859
ndbrequire(regTcPtr.p->m_dealloc == 0);
5860
regTcPtr.p->m_dealloc = 1;
5862
}//Dblqh::execTUP_ALLOCREQ()
5864
/* ************>> */
5866
/* ************>> */
5867
void Dblqh::execACCKEYCONF(Signal* signal)
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];
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);
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
5891
* ----------------------------------------------------------------------- */
5892
if (regTcPtr->operation == ZWRITE)
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))
5901
regTcPtr->operation = op;
5906
warningEvent("Convering %d to ZUPDATE", op);
5907
op = regTcPtr->operation = ZUPDATE;
5909
if (regTcPtr->seqNoReplica == 0)
5912
requestInfo &= ~(RI_OPERATION_MASK << RI_OPERATION_SHIFT);
5913
LqhKeyReq::setOperation(requestInfo, op);
5914
regTcPtr->reqinfo = requestInfo;
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
5925
* ----------------------------------------------------------------------- */
5926
FragrecordPtr regFragptr;
5927
regFragptr.i = regTcPtr->fragmentptr;
5928
c_fragment_pool.getPtr(regFragptr);
5930
if(!regTcPtr->m_disk_table)
5931
acckeyconf_tupkeyreq(signal, regTcPtr, regFragptr.p,
5932
localKey1, localKey2, RNIL);
5934
acckeyconf_load_diskpage(signal, tcConnectptr, regFragptr.p,
5935
localKey1, localKey2);
5939
Dblqh::acckeyconf_tupkeyreq(Signal* signal, TcConnectionrec* regTcPtr,
5940
Fragrecord* regFragptrP,
5941
Uint32 lkey1, Uint32 lkey2,
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
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);
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;
5973
Uint32 sig0, sig1, sig2, sig3;
5974
sig0 = regTcPtr->tupConnectrec;
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;
5982
sig0 = regTcPtr->totReclenAi;
5983
sig1 = regTcPtr->applOprec;
5984
sig2 = regTcPtr->applRef;
5986
tupKeyReq->attrBufLen = sig0;
5987
tupKeyReq->opRef = sig1;
5988
tupKeyReq->applRef = sig2;
5990
sig0 = regTcPtr->storedProcId;
5991
sig1 = regTcPtr->transid[0];
5992
sig2 = regTcPtr->transid[1];
5993
sig3 = regFragptrP->tupFragptr;
5994
Uint32 tup = refToMain(regTcPtr->tcTupBlockref);
5996
tupKeyReq->storedProcedure = sig0;
5997
tupKeyReq->transId1 = sig1;
5998
tupKeyReq->transId2 = sig2;
5999
tupKeyReq->fragPtr = sig3;
6001
sig0 = regTcPtr->m_row_id.m_page_no;
6002
sig1 = regTcPtr->m_row_id.m_page_idx;
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;
6010
tupKeyReq->m_row_id_page_no = sig0;
6011
tupKeyReq->m_row_id_page_idx = sig1;
6013
TRACE_OP(regTcPtr, "TUPKEYREQ");
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;
6019
tupKeyReq->attrInfoIVal= RNIL;
6020
tupKeyReq->deferred_constraints =
6021
(flags & TcConnectionrec::OP_DEFERRED_CONSTRAINTS) != 0;
6023
/* Pass AttrInfo section if available in the TupKeyReq signal
6024
* We are still responsible for releasing it, TUP is just
6027
if (tupKeyReq->attrBufLen > 0)
6029
ndbassert( regTcPtr->attrInfoIVal != RNIL );
6030
tupKeyReq->attrInfoIVal= regTcPtr->attrInfoIVal;
6033
EXECUTE_DIRECT(tup, GSN_TUPKEYREQ, signal, TupKeyReq::SignalLength);
6034
}//Dblqh::execACCKEYCONF()
6037
Dblqh::acckeyconf_load_diskpage(Signal* signal, TcConnectionrecPtr regTcPtr,
6038
Fragrecord* regFragptrP,
6039
Uint32 lkey1, Uint32 lkey2)
6042
if((res= c_tup->load_diskpage(signal,
6043
regTcPtr.p->tupConnectrec,
6044
regFragptrP->tupFragptr,
6046
regTcPtr.p->operation)) > 0)
6048
acckeyconf_tupkeyreq(signal, regTcPtr.p, regFragptrP, lkey1, lkey2, res);
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;
6058
regTcPtr.p->transactionState = TcConnectionrec::WAIT_TUP;
6059
TupKeyRef * ref = (TupKeyRef *)signal->getDataPtr();
6060
ref->userRef= regTcPtr.i;
6062
execTUPKEYREF(signal);
6067
Dblqh::acckeyconf_load_diskpage_callback(Signal* signal,
6068
Uint32 callbackData,
6072
tcConnectptr.i = callbackData;
6073
ptrCheckGuard(tcConnectptr, ctcConnectrecFileSize, tcConnectionrec);
6074
TcConnectionrec * const regTcPtr = tcConnectptr.p;
6076
TcConnectionrec::TransactionState state = regTcPtr->transactionState;
6077
if (likely(disk_page > 0 && state == TcConnectionrec::WAIT_TUP))
6079
FragrecordPtr fragPtr;
6080
c_fragment_pool.getPtr(fragPtr, regTcPtr->fragmentptr);
6082
acckeyconf_tupkeyreq(signal, regTcPtr, fragPtr.p,
6083
regTcPtr->m_row_id.m_page_no,
6084
regTcPtr->m_row_id.m_page_idx,
6087
else if (state != TcConnectionrec::WAIT_TUP)
6089
ndbrequire(state == TcConnectionrec::WAIT_TUP_TO_ABORT);
6090
abortCommonLab(signal);
6095
regTcPtr->transactionState = TcConnectionrec::WAIT_TUP;
6096
TupKeyRef * ref = (TupKeyRef *)signal->getDataPtr();
6097
ref->userRef= callbackData;
6098
ref->errorCode= disk_page;
6099
execTUPKEYREF(signal);
6103
/* --------------------------------------------------------------------------
6104
* ------- ENTER TUP... -------
6105
* ENTER TUPKEYCONF WITH
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
6113
* TAKE CARE OF RESPONSES FROM TUPLE MANAGER.
6114
* -------------------------------------------------------------------------- */
6115
void Dblqh::tupkeyConfLab(Signal* signal)
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;
6124
TRACE_OP(regTcPtr, "TUPKEYCONF");
6126
Uint32 accOp = regTcPtr->accConnectrec;
6127
c_acc->execACCKEY_ORD(signal, accOp);
6133
/* SET BIT 15 IN REQINFO */
6134
LqhKeyReq::setApplicationAddressFlag(regTcPtr->reqinfo, 1);
6135
regTcPtr->readlenAi = readLen;
6138
if (regTcPtr->operation == ZREAD &&
6139
(regTcPtr->opSimple || regTcPtr->dirtyOp))
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
6150
* --------------------------------------------------------------------- */
6151
commitContinueAfterBlockedLab(signal);
6155
regTcPtr->totSendlenAi = writeLen;
6156
/* We will propagate / log writeLen words
6157
* Check that that is how many we have available to
6160
ndbrequire(regTcPtr->totSendlenAi == regTcPtr->currTupAiLen);
6162
if (unlikely(activeCreat == Fragrecord::AC_NR_COPY))
6165
ndbrequire(regTcPtr->m_nr_delete.m_cnt);
6166
regTcPtr->m_nr_delete.m_cnt--;
6167
if (regTcPtr->m_nr_delete.m_cnt)
6171
* Let operation wait for pending NR operations
6172
* even for before writing log...(as it's simpler)
6177
* Only disk table can have pending ops...
6179
TablerecPtr tablePtr;
6180
tablePtr.i = regTcPtr->tableref;
6181
ptrCheckGuard(tablePtr, ctabrecFileSize, tablerec);
6182
ndbrequire(tablePtr.p->m_disk_table);
6189
rwConcludedLab(signal);
6191
}//Dblqh::tupkeyConfLab()
6193
/* --------------------------------------------------------------------------
6194
* THE CODE IS FOUND IN THE SIGNAL RECEPTION PART OF LQH
6195
* -------------------------------------------------------------------------- */
6196
void Dblqh::rwConcludedLab(Signal* signal)
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) {
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);
6213
FragrecordPtr regFragptr = fragptr;
6214
if (regFragptr.p->logFlag == Fragrecord::STATE_FALSE){
6215
if (regTcPtr->dirtyOp == ZTRUE) {
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);
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);
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);
6246
}//Dblqh::rwConcludedLab()
6248
void Dblqh::rwConcludedAiLab(Signal* signal)
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
6259
* ------------------------------------------------------------------------ */
6260
if (regTcPtr->operation == ZREAD) {
6261
if (regTcPtr->opSimple == 1) {
6263
/* --------------------------------------------------------------------
6264
* THE OPERATION IS A SIMPLE READ. WE WILL IMMEDIATELY COMMIT THE
6266
* -------------------------------------------------------------------- */
6267
localCommitLab(signal);
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);
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
* ----------------------------------------------------------------- */
6289
/* ----------------------------------------------------------------
6290
* IT MUST BE ACTIVE CREATION OF A FRAGMENT.
6291
* ---------------------------------------------------------------- */
6292
localCommitLab(signal);
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
* ------------------------------------------------------------------ */
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);
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);
6321
}//Dblqh::rwConcludedAiLab()
6323
/* ##########################################################################
6324
* ####### LOG MODULE #######
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)
6334
UintR tcurrentFilepage;
6335
TcConnectionrecPtr tmpTcConnectptr;
6337
const bool out_of_log_buffer = cnoOfLogPages < ZMIN_LOG_PAGES_OPERATION;
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);
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))
6357
if (abort_on_redo_problems)
6359
logLqhkeyreqLab_problems(signal);
6368
if (regLogPartPtr->logPartState == LogPartRecord::IDLE)
6372
else if (regLogPartPtr->logPartState == LogPartRecord::ACTIVE)
6376
linkWaitLog(signal, logPartPtr, logPartPtr.p->m_log_prepare_queue);
6377
regTcPtr->transactionState = TcConnectionrec::LOG_QUEUED;
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 */
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) {
6413
regLogPartPtr->firstLogTcrec = tcIndex;
6415
ptrCheckGuard(tmpTcConnectptr, ctcConnectrecFileSize, tcConnectionrec);
6416
tmpTcConnectptr.p->nextLogTcrec = tcIndex;
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
/* -------------------------------------------------- */
6436
/* -------------------------------------------------- */
6437
/* WRITE THE ATTRIBUTE INFO OF THIS OPERATION. */
6438
/* -------------------------------------------------- */
6439
writeAttrinfoLab(signal);
6441
/* -------------------------------------------------- */
6442
/* RESET THE STATE OF THE LOG PART. IF ANY */
6443
/* OPERATIONS HAVE QUEUED THEN START THE FIRST */
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) {
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);
6465
if (regTcPtr->dirtyOp != ZTRUE) {
6466
packLqhkeyreqLab(signal);
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);
6480
}//Dblqh::logLqhkeyreqLab()
6483
Dblqh::logLqhkeyreqLab_problems(Signal * signal)
6486
LogPartRecord * const regLogPartPtr = logPartPtr.p;
6487
Uint32 problems = regLogPartPtr->m_log_problems;
6489
if (cnoOfLogPages < ZMIN_LOG_PAGES_OPERATION)
6492
terrorCode = ZTEMPORARY_REDO_LOG_FAILURE;
6494
else if ((problems & LogPartRecord::P_TAIL_PROBLEM) != 0)
6497
terrorCode = ZTAIL_PROBLEM_IN_LOG_ERROR;
6499
else if ((problems & LogPartRecord::P_REDO_IO_PROBLEM) != 0)
6502
terrorCode = ZREDO_IO_PROBLEM;
6504
else if ((problems & LogPartRecord::P_FILE_CHANGE_PROBLEM) != 0)
6507
terrorCode = ZFILE_CHANGE_PROBLEM_IN_LOG_ERROR;
6509
abortErrorLab(signal);
6513
Dblqh::update_log_problem(Signal* signal, Ptr<LogPartRecord> partPtr,
6514
Uint32 problem, bool value)
6516
Uint32 problems = partPtr.p->m_log_problems;
6523
if ((problems & problem) == 0)
6526
problems |= problem;
6535
if ((problems & problem) != 0)
6538
problems &= ~(Uint32)problem;
6540
if (partPtr.p->LogLqhKeyReqSent == ZFALSE &&
6541
(!partPtr.p->m_log_prepare_queue.isEmpty() ||
6542
!partPtr.p->m_log_complete_queue.isEmpty()))
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);
6553
partPtr.p->m_log_problems = problems;
6556
/* ------------------------------------------------------------------------- */
6557
/* ------- SEND LQHKEYREQ */
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)
6565
TcConnectionrec * const regTcPtr = tcConnectptr.p;
6566
if (regTcPtr->nextReplica == ZNIL) {
6567
/* ------------------------------------------------------------------------- */
6568
/* ------- SEND LQHKEYCONF ------- */
6570
/* ------------------------------------------------------------------------- */
6571
sendLqhkeyconfTc(signal, regTcPtr->tcBlockref);
6572
if (! (regTcPtr->dirtyOp ||
6573
(regTcPtr->operation == ZREAD && regTcPtr->opSimple)))
6576
regTcPtr->transactionState = TcConnectionrec::PREPARED;
6577
releaseOprec(signal);
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. */
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. */
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 */
6600
/*************************************************************>*/
6605
/* ------------------------------------------------------------------------- */
6606
/* ------- SEND LQHKEYREQ ------- */
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];
6622
UintR sig0, sig1, sig2, sig3, sig4, sig5, sig6;
6623
Treqinfo = preComputedRequestInfoMask & regTcPtr->reqinfo;
6625
Uint32 nextNodeId = regTcPtr->nextReplica;
6626
Uint32 nextVersion = getNodeInfo(nextNodeId).m_version;
6628
/* Send long LqhKeyReq to next replica if it can support it */
6629
bool sendLongReq= ! ((nextVersion < NDBD_LONG_LQHKEYREQ) ||
6630
ERROR_INSERTED(5051));
6632
UintR TAiLen = sendLongReq ?
6634
MIN(regTcPtr->totSendlenAi, LqhKeyReq::MaxAttrInfo);
6636
/* Long LQHKeyReq uses section size for key length */
6637
Uint32 lqhKeyLen= sendLongReq?
6639
regTcPtr->primKeyLen;
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);
6648
if (unlikely(nextVersion < NDBD_ROWID_VERSION))
6650
LqhKeyReq::setLockType(Treqinfo, regTcPtr->lockType);
6654
regTcPtr->m_use_rowid |=
6655
fragptr.p->m_copy_started_state == Fragrecord::AC_NR_COPY;
6656
LqhKeyReq::setRowidFlag(Treqinfo, regTcPtr->m_use_rowid);
6659
if (LqhKeyReq::getRowidFlag(Treqinfo))
6661
//ndbassert(LqhKeyReq::getOperation(Treqinfo) == ZINSERT);
6665
if (fragptr.p->m_copy_started_state != Fragrecord::AC_IGNORED)
6667
ndbassert(LqhKeyReq::getOperation(Treqinfo) != ZINSERT ||
6668
get_node_status(nextNodeId) != ZNODE_UP);
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);
6678
/* Long LQHKeyReq uses section size for AttrInfo length */
6679
UintR TotReclenAi = sendLongReq ?
6681
regTcPtr->totSendlenAi;
6683
LqhKeyReq::setReorgFlag(TotReclenAi, regTcPtr->m_reorg);
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 */
6691
/* ------------------------------------------------------------------------- */
6692
sig0 = tcConnectptr.i;
6693
sig1 = regTcPtr->savePointId;
6694
sig2 = regTcPtr->hashValue;
6695
sig4 = regTcPtr->tcBlockref;
6697
lqhKeyReq->clientConnectPtr = sig0;
6698
lqhKeyReq->attrLen = TotReclenAi;
6699
lqhKeyReq->savePointId = sig1;
6700
lqhKeyReq->hashValue = sig2;
6701
lqhKeyReq->requestInfo = Treqinfo;
6702
lqhKeyReq->tcBlockref = sig4;
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);
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;
6722
nextPos += TsameLqhAndClient;
6724
if ((regTcPtr->lastReplicaNo - regTcPtr->nextSeqNoReplica) > 1) {
6725
sig0 = (UintR)regTcPtr->nodeAfterNext[1] +
6726
(UintR)(regTcPtr->nodeAfterNext[2] << 16);
6727
lqhKeyReq->variableData[nextPos] = sig0;
6730
sig0 = regTcPtr->readlenAi;
6731
lqhKeyReq->variableData[nextPos] = sig0;
6732
nextPos += TreadLenAiInd;
6736
/* Short LQHKEYREQ to older LQH
6737
* First few words of KeyInfo go into LQHKEYREQ
6738
* Sometimes have no Keyinfo
6740
if (regTcPtr->primKeyLen != 0)
6742
SegmentedSectionPtr keyInfoSection;
6744
ndbassert(regTcPtr->keyInfoIVal != RNIL);
6746
getSection(keyInfoSection, regTcPtr->keyInfoIVal);
6747
SectionReader keyInfoReader(keyInfoSection, g_sectionSegmentPool);
6749
UintR keyLenInLqhKeyReq= MIN(LqhKeyReq::MaxKeyInfo,
6750
regTcPtr->primKeyLen);
6752
keyInfoReader.getWords(&lqhKeyReq->variableData[nextPos],
6755
nextPos+= keyLenInLqhKeyReq;
6759
sig0 = regTcPtr->gci_hi;
6760
Local_key tmp = regTcPtr->m_row_id;
6762
lqhKeyReq->variableData[nextPos + 0] = tmp.m_page_no;
6763
lqhKeyReq->variableData[nextPos + 1] = tmp.m_page_idx;
6764
nextPos += 2*LqhKeyReq::getRowidFlag(Treqinfo);
6766
lqhKeyReq->variableData[nextPos + 0] = sig0;
6767
nextPos += LqhKeyReq::getGCIFlag(Treqinfo);
6769
// pass full instance key for remote to map to real instance
6770
BlockReference lqhRef = numberToRef(DBLQH,
6771
fragptr.p->lqhInstanceKey,
6772
regTcPtr->nextReplica);
6774
if (likely(sendLongReq))
6776
/* Long LQHKEYREQ, attach KeyInfo and AttrInfo
6777
* sections to signal
6779
SectionHandle handle(this);
6782
if (regTcPtr->primKeyLen > 0)
6784
SegmentedSectionPtr keyInfoSection;
6786
ndbassert(regTcPtr->keyInfoIVal != RNIL);
6787
getSection(keyInfoSection, regTcPtr->keyInfoIVal);
6789
handle.m_ptr[ LqhKeyReq::KeyInfoSectionNum ]= keyInfoSection;
6792
if (regTcPtr->totSendlenAi > 0)
6794
SegmentedSectionPtr attrInfoSection;
6796
ndbassert(regTcPtr->attrInfoIVal != RNIL);
6797
getSection(attrInfoSection, regTcPtr->attrInfoIVal);
6799
handle.m_ptr[ LqhKeyReq::AttrInfoSectionNum ]= attrInfoSection;
6804
/* No AttrInfo to be sent on. This can occur for delete
6805
* or with an interpreted update when no actual update
6807
* In this case, we free any attrInfo section now.
6809
if (regTcPtr->attrInfoIVal != RNIL)
6811
ndbassert(!( regTcPtr->m_flags &
6812
TcConnectionrec::OP_SAVEATTRINFO));
6813
releaseSection(regTcPtr->attrInfoIVal);
6814
regTcPtr->attrInfoIVal= RNIL;
6820
/* Zero-length primary key, better not have any
6823
ndbrequire(regTcPtr->totSendlenAi == 0);
6824
ndbassert(regTcPtr->keyInfoIVal == RNIL);
6825
ndbassert(regTcPtr->attrInfoIVal == RNIL);
6828
sendSignal(lqhRef, GSN_LQHKEYREQ, signal,
6829
LqhKeyReq::FixedSignalLength + nextPos,
6833
/* Long sections were freed as part of sendSignal */
6834
ndbassert( handle.m_cnt == 0);
6835
regTcPtr->keyInfoIVal= RNIL;
6836
regTcPtr->attrInfoIVal= RNIL;
6840
/* Short LQHKEYREQ to older LQH
6841
* First few words of ATTRINFO go into LQHKEYREQ
6846
if (likely(nextPos + TAiLen + LqhKeyReq::FixedSignalLength <= 25))
6849
SegmentedSectionPtr attrInfoSection;
6851
ndbassert(regTcPtr->attrInfoIVal != RNIL);
6853
getSection(attrInfoSection, regTcPtr->attrInfoIVal);
6854
SectionReader attrInfoReader(attrInfoSection, getSectionSegmentPool());
6856
attrInfoReader.getWords(&lqhKeyReq->variableData[nextPos],
6863
/* Not enough space in LQHKEYREQ, we'll send everything in
6864
* separate ATTRINFO signals
6866
Treqinfo &= ~(Uint32)(RI_AI_IN_THIS_MASK << RI_AI_IN_THIS_SHIFT);
6867
lqhKeyReq->requestInfo = Treqinfo;
6872
sendSignal(lqhRef, GSN_LQHKEYREQ, signal,
6873
nextPos + LqhKeyReq::FixedSignalLength, JBB);
6875
/* Send extra KeyInfo signals if necessary... */
6876
if (regTcPtr->primKeyLen > LqhKeyReq::MaxKeyInfo) {
6881
/* Send extra AttrInfo signals if necessary... */
6882
Uint32 remainingAiLen= regTcPtr->totSendlenAi - TAiLen;
6884
if (remainingAiLen != 0)
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;
6893
SectionReader attrInfoReader(regTcPtr->attrInfoIVal,
6894
g_sectionSegmentPool);
6896
ndbassert(attrInfoReader.getSize() == regTcPtr->totSendlenAi);
6898
/* Step over words already sent in LQHKEYREQ above */
6899
attrInfoReader.step(TAiLen);
6901
while (remainingAiLen != 0)
6903
Uint32 dataInSignal= MIN(AttrInfo::DataLength, remainingAiLen);
6904
attrInfoReader.getWords(&signal->theData[3],
6906
remainingAiLen-= dataInSignal;
6907
sendSignal(lqhRef, GSN_ATTRINFO, signal,
6908
AttrInfo::HeaderLength + dataInSignal, JBB);
6913
/* LQHKEYREQ sent */
6915
regTcPtr->transactionState = TcConnectionrec::PREPARED;
6916
if (regTcPtr->dirtyOp == ZTRUE) {
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. */
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. */
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 */
6937
/*************************************************************>*/
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()
6950
/* ========================================================================= */
6951
/* ==== CHECK IF THE LOG RECORD FITS INTO THE CURRENT MBYTE, ======= */
6952
/* OTHERWISE SWITCH TO NEXT MBYTE. */
6954
/* ========================================================================= */
6955
void Dblqh::checkNewMbyte(Signal* signal)
6958
UintR ttotalLogSize;
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 */
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;
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;
6992
ndbrequire(tcnmTmp >= ttotalLogSize);
6993
logFilePtr.p->remainingWordsInMbyte = tcnmTmp - ttotalLogSize;
6994
}//Dblqh::checkNewMbyte()
6996
/* --------------------------------------------------------------------------
6997
* ------- WRITE OPERATION HEADER TO LOG -------
6999
* SUBROUTINE SHORT NAME: WLH
7000
* ------------------------------------------------------------------------- */
7001
void Dblqh::writeLogHeader(Signal* signal)
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;
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;
7019
dataPtr[5] = keyLen;
7020
dataPtr[6] = rowid.m_page_no;
7021
dataPtr[7] = rowid.m_page_idx;
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);
7032
}//Dblqh::writeLogHeader()
7034
/* --------------------------------------------------------------------------
7035
* ------- WRITE TUPLE KEY TO LOG -------
7037
* SUBROUTINE SHORT NAME: WK
7038
* ------------------------------------------------------------------------- */
7039
void Dblqh::writeKey(Signal* signal)
7041
TcConnectionrec * const regTcPtr = tcConnectptr.p;
7043
SectionReader keyInfoReader(regTcPtr->keyInfoIVal,
7044
g_sectionSegmentPool);
7045
const Uint32* srcPtr;
7047
Uint32 wordsWritten= 0;
7049
/* Write contiguous chunks of words from the KeyInfo
7050
* section to the log
7052
while (keyInfoReader.getWordsPtr(srcPtr,
7055
writeLogWords(signal, srcPtr, length);
7056
wordsWritten+= length;
7059
ndbassert( wordsWritten == regTcPtr->primKeyLen );
7060
}//Dblqh::writeKey()
7062
/* --------------------------------------------------------------------------
7063
* ------- WRITE ATTRINFO TO LOG -------
7065
* SUBROUTINE SHORT NAME: WA
7066
* ------------------------------------------------------------------------- */
7067
void Dblqh::writeAttrinfoLab(Signal* signal)
7069
TcConnectionrec * const regTcPtr = tcConnectptr.p;
7070
Uint32 totLen = regTcPtr->currTupAiLen;
7075
ndbassert( regTcPtr->attrInfoIVal != RNIL );
7076
SectionReader attrInfoReader(regTcPtr->attrInfoIVal,
7077
g_sectionSegmentPool);
7078
const Uint32* srcPtr;
7080
Uint32 wordsWritten= 0;
7082
/* Write contiguous chunks of words from the
7083
* AttrInfo section to the log
7085
while (attrInfoReader.getWordsPtr(srcPtr,
7088
writeLogWords(signal, srcPtr, length);
7089
wordsWritten+= length;
7092
ndbassert( wordsWritten == totLen );
7093
}//Dblqh::writeAttrinfoLab()
7095
/* ------------------------------------------------------------------------- */
7096
/* ------- SEND TUPLE KEY IN KEYINFO SIGNAL(S) ------- */
7098
/* SUBROUTINE SHORT NAME: STU */
7099
/* ------------------------------------------------------------------------- */
7100
void Dblqh::sendTupkey(Signal* signal)
7102
BlockReference lqhRef = 0;
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);
7113
signal->theData[0] = tcConnectptr.p->tcOprec;
7114
signal->theData[1] = tcConnectptr.p->transid[0];
7115
signal->theData[2] = tcConnectptr.p->transid[1];
7117
Uint32 remainingLen= tcConnectptr.p->primKeyLen -
7118
LqhKeyReq::MaxKeyInfo;
7120
SectionReader keyInfoReader(tcConnectptr.p->keyInfoIVal,
7121
g_sectionSegmentPool);
7123
ndbassert(keyInfoReader.getSize() > LqhKeyReq::MaxKeyInfo);
7125
/* Step over the words already sent in LQHKEYREQ */
7126
keyInfoReader.step(LqhKeyReq::MaxKeyInfo);
7128
while (remainingLen != 0)
7130
Uint32 dataInSignal= MIN(KeyInfo::DataLength, remainingLen);
7131
keyInfoReader.getWords(&signal->theData[3],
7133
remainingLen-= dataInSignal;
7134
sendSignal(lqhRef, GSN_KEYINFO, signal,
7135
KeyInfo::HeaderLength + dataInSignal, JBB);
7137
}//Dblqh::sendTupkey()
7139
void Dblqh::cleanUp(Signal* signal)
7141
releaseOprec(signal);
7142
deleteTransidHash(signal);
7143
releaseTcrec(signal, tcConnectptr);
7146
/* --------------------------------------------------------------------------
7147
* ---- RELEASE ALL RECORDS CONNECTED TO THE OPERATION RECORD AND THE ----
7148
* OPERATION RECORD ITSELF
7149
* ------------------------------------------------------------------------- */
7150
void Dblqh::releaseOprec(Signal* signal)
7152
TcConnectionrec * const regTcPtr = tcConnectptr.p;
7154
/* Release long sections if present */
7155
releaseSection(regTcPtr->keyInfoIVal);
7156
regTcPtr->keyInfoIVal = RNIL;
7157
releaseSection(regTcPtr->attrInfoIVal);
7158
regTcPtr->attrInfoIVal = RNIL;
7160
if (regTcPtr->m_dealloc)
7163
regTcPtr->m_dealloc = 0;
7166
TRACENR("DELETED: " << regTcPtr->m_row_id << endl);
7168
TRACE_OP(regTcPtr, "DO DEALLOC");
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);
7177
}//Dblqh::releaseOprec()
7179
/* ------------------------------------------------------------------------- */
7180
/* ------ DELETE TRANSACTION ID FROM HASH TABLE ------- */
7182
/* ------------------------------------------------------------------------- */
7183
void Dblqh::deleteTransidHash(Signal* signal)
7185
TcConnectionrec * const regTcPtr = tcConnectptr.p;
7186
TcConnectionrecPtr prevHashptr;
7187
TcConnectionrecPtr nextHashptr;
7189
prevHashptr.i = regTcPtr->prevHashRec;
7190
nextHashptr.i = regTcPtr->nextHashRec;
7191
if (prevHashptr.i != RNIL) {
7193
ptrCheckGuard(prevHashptr, ctcConnectrecFileSize, tcConnectionrec);
7194
prevHashptr.p->nextHashRec = nextHashptr.i;
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;
7204
if (nextHashptr.i != RNIL) {
7206
ptrCheckGuard(nextHashptr, ctcConnectrecFileSize, tcConnectionrec);
7207
nextHashptr.p->prevHashRec = prevHashptr.i;
7210
regTcPtr->prevHashRec = regTcPtr->nextHashRec = RNIL;
7211
}//Dblqh::deleteTransidHash()
7213
/* -------------------------------------------------------------------------
7214
* ------- RELEASE OPERATION FROM ACTIVE LIST ON FRAGMENT -------
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)
7228
ndbout << "W: Received COMMIT in wrong state in Dblqh" << endl;
7234
ndbout << "W: Received COMMIT with wrong transid in Dblqh" << endl;
7240
ndbout << "W: Received COMPLETE in wrong state in Dblqh" << endl;
7246
ndbout << "W: Received COMPLETE with wrong transid in Dblqh" << endl;
7252
ndbout << "W: Received COMMITREQ in wrong state in Dblqh" << endl;
7258
ndbout << "W: Received COMMITREQ with wrong transid in Dblqh" << endl;
7264
ndbout << "W: Received COMPLETEREQ in wrong state in Dblqh" << endl;
7270
ndbout << "W: Received COMPLETEREQ with wrong transid in Dblqh" << endl;
7276
ndbout << "W: Received ABORT with non-existing transid in Dblqh" << endl;
7282
ndbout << "W: Received ABORTREQ with non-existing transid in Dblqh" << endl;
7288
ndbout << "W: Received ABORTREQ in wrong state in Dblqh" << endl;
7294
ndbout << "W: Received COMMIT when tc-rec released in Dblqh" << endl;
7300
ndbout << "W: Received COMPLETE when tc-rec released in Dblqh" << endl;
7306
ndbout << "W: Received LQHKEYREF when tc-rec released in Dblqh" << endl;
7312
ndbout << "W: Received LQHKEYREF with wrong transid in Dblqh" << endl;
7318
ndbout << "W: Received LQHKEYREF when already aborting in Dblqh" << endl;
7323
ndbrequire(cstartPhase == ZNIL);
7325
ndbout << "W: Received LQHKEYREF in wrong state in Dblqh" << endl;
7333
}//Dblqh::warningReport()
7335
void Dblqh::errorReport(Signal* signal, int place)
7354
systemErrorLab(signal, __LINE__);
7356
}//Dblqh::errorReport()
7359
Dblqh::execFIRE_TRIG_REQ(Signal* signal)
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();
7369
if (ERROR_INSERTED_CLEAR(5064))
7371
// throw away...should cause timeout in TC
7375
CRASH_INSERTION(5072);
7378
if (findTransaction(transid1, transid2, tcOprec, 0) == ZOK &&
7379
!ERROR_INSERTED_CLEAR(5065) &&
7380
!ERROR_INSERTED(5070) &&
7381
!ERROR_INSERTED(5071))
7383
TcConnectionrec * const regTcPtr = tcConnectptr.p;
7385
if (unlikely(regTcPtr->transactionState != TcConnectionrec::PREPARED ||
7386
ERROR_INSERTED_CLEAR(5067)))
7388
err = FireTrigRef::FTR_IncorrectState;
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);
7404
err = signal->theData[0];
7405
Uint32 cnt = signal->theData[1];
7407
if (ERROR_INSERTED_CLEAR(5066))
7412
if (ERROR_INSERTED_CLEAR(5068))
7414
if (ERROR_INSERTED_CLEAR(5069))
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);
7433
err = FireTrigRef::FTR_UnknownOperation;
7437
if (ERROR_INSERTED_CLEAR(5070))
7440
if (ERROR_INSERTED_CLEAR(5071))
7443
FireTrigRef * ref = CAST_PTR(FireTrigRef, signal->getDataPtrSend());
7444
ref->tcOpRec = tcOprec;
7445
ref->transId[0] = transid1;
7446
ref->transId[1] = transid2;
7448
sendSignal(senderRef, GSN_FIRE_TRIG_REF,
7449
signal, FireTrigRef::SignalLength, JBB);
7455
Dblqh::sendFireTrigConfTc(Signal* signal,
7456
BlockReference atcBlockref,
7459
if (refToInstance(atcBlockref) != 0)
7462
memcpy(signal->theData, Tdata, 4 * FireTrigConf::SignalLength);
7463
sendSignal(atcBlockref, GSN_FIRE_TRIG_CONF,
7464
signal, FireTrigConf::SignalLength, JBB);
7468
HostRecordPtr Thostptr;
7469
Uint32 len = FireTrigConf::SignalLength;
7471
Thostptr.i = refToNode(atcBlockref);
7472
ptrCheckGuard(Thostptr, chostFileSize, hostRecord);
7474
if (Thostptr.p->noOfPackedWordsTc > (25 - len))
7477
sendPackedSignalTc(signal, Thostptr.p);
7482
updatePackedList(signal, Thostptr.p, Thostptr.i);
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);
7495
Dblqh::check_fire_trig_pass(Uint32 opId, Uint32 pass)
7498
* Check that trigger only fires once per pass
7501
TcConnectionrecPtr regTcPtr;
7503
ptrCheckGuard(regTcPtr, ctcConnectrecFileSize, tcConnectionrec);
7504
if (regTcPtr.p->m_fire_trig_pass <= pass)
7506
regTcPtr.p->m_fire_trig_pass = pass + 1;
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)
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];
7529
if (tcIndex >= ttcConnectrecFileSize) {
7530
errorReport(signal, 0);
7533
if (ERROR_INSERTED(5011)) {
7534
CLEAR_ERROR_INSERT_VALUE;
7535
sendSignalWithDelay(cownref, GSN_COMMIT, signal, 2000,signal->getLength());
7538
if (ERROR_INSERTED(5012)) {
7539
SET_ERROR_INSERT_VALUE(5017);
7540
sendSignalWithDelay(cownref, GSN_COMMIT, signal, 2000,signal->getLength());
7543
if (ERROR_INSERTED(5062) &&
7544
((refToMain(signal->getSendersBlockRef()) == DBTC) ||
7545
signal->getSendersBlockRef() == reference()))
7547
Uint32 save = signal->getSendersBlockRef();
7548
ndbout_c("Delaying execCOMMIT");
7549
sendSignalWithDelay(cownref, GSN_COMMIT, signal, 2000, signal->getLength());
7551
if (refToMain(save) == DBTC)
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);
7561
tcConnectptr.i = tcIndex;
7562
ptrAss(tcConnectptr, regTcConnectionrec);
7563
if ((tcConnectptr.p->transid[0] == transid1) &&
7564
(tcConnectptr.p->transid[1] == transid2)) {
7566
TcConnectionrec * const regTcPtr = tcConnectptr.p;
7567
TRACE_OP(regTcPtr, "COMMIT");
7569
CRASH_INSERTION(5048);
7570
if (ERROR_INSERTED(5049))
7572
SET_ERROR_INSERT_VALUE(5048);
7575
commitReqLab(signal, gci_hi, gci_lo);
7578
warningReport(signal, 1);
7580
}//Dblqh::execCOMMIT()
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
7587
* ************************************************************************>> */
7588
void Dblqh::execCOMMITREQ(Signal* signal)
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];
7599
if (unlikely(signal->getLength() < 8))
7603
ndbassert(!ndb_check_micro_gcp(getNodeInfo(refToNode(signal->getSendersBlockRef())).m_version));
7606
if (ERROR_INSERTED(5004)) {
7607
systemErrorLab(signal, __LINE__);
7609
if (ERROR_INSERTED(5017)) {
7610
CLEAR_ERROR_INSERT_VALUE;
7611
sendSignalWithDelay(cownref, GSN_COMMITREQ, signal, 2000,
7612
signal->getLength());
7615
if (findTransaction(transid1,
7617
tcOprec, 0) != ZOK) {
7618
warningReport(signal, 5);
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:
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);
7636
case TcConnectionrec::COMMITTED:
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);
7652
case TcConnectionrec::COMMIT_STOPPED:
7653
case TcConnectionrec::WAIT_TUP_COMMIT:
7655
regTcPtr->reqBlockref = reqBlockref;
7656
regTcPtr->reqRef = reqPtr;
7657
regTcPtr->abortState = TcConnectionrec::REQ_FROM_TC;
7662
warningReport(signal, 4);
7667
}//Dblqh::execCOMMITREQ()
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)
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];
7682
if (tcIndex >= ttcConnectrecFileSize) {
7683
errorReport(signal, 1);
7686
CRASH_INSERTION(5042);
7688
if (ERROR_INSERTED(5013)) {
7689
CLEAR_ERROR_INSERT_VALUE;
7690
sendSignalWithDelay(cownref, GSN_COMPLETE, signal, 2000, 3);
7693
if (ERROR_INSERTED(5014)) {
7694
SET_ERROR_INSERT_VALUE(5018);
7695
sendSignalWithDelay(cownref, GSN_COMPLETE, signal, 2000, 3);
7698
if (ERROR_INSERTED(5063) &&
7699
((refToMain(signal->getSendersBlockRef()) == DBTC) ||
7700
signal->getSendersBlockRef() == reference()))
7702
Uint32 save = signal->getSendersBlockRef();
7703
ndbout_c("Delaying execCOMPLETE");
7704
sendSignalWithDelay(cownref, GSN_COMPLETE,signal, 2000,signal->getLength());
7706
if (refToMain(save) == DBTC)
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);
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)) {
7722
TcConnectionrec * const regTcPtr = tcConnectptr.p;
7723
TRACE_OP(regTcPtr, "COMPLETE");
7725
if (tcConnectptr.p->seqNoReplica != 0 &&
7726
tcConnectptr.p->activeCreat == Fragrecord::AC_NORMAL) {
7728
localCommitLab(signal);
7731
else if (tcConnectptr.p->seqNoReplica == 0)
7734
completeTransLastLab(signal);
7740
completeTransNotLastLab(signal);
7744
if (tcConnectptr.p->transactionState != TcConnectionrec::COMMITTED) {
7745
warningReport(signal, 2);
7747
warningReport(signal, 3);
7749
}//Dblqh::execCOMPLETE()
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)
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__);
7766
if (ERROR_INSERTED(5018)) {
7767
CLEAR_ERROR_INSERT_VALUE;
7768
sendSignalWithDelay(cownref, GSN_COMPLETEREQ, signal, 2000, 6);
7771
if (findTransaction(transid1,
7773
tcOprec, 0) != ZOK) {
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);
7788
TcConnectionrec * const regTcPtr = tcConnectptr.p;
7789
switch (regTcPtr->transactionState) {
7790
case TcConnectionrec::COMMITTED:
7792
regTcPtr->reqBlockref = reqBlockref;
7793
regTcPtr->reqRef = reqPtr;
7794
regTcPtr->abortState = TcConnectionrec::REQ_FROM_TC;
7797
/*---------------------------------------------------------*/
7798
/* THE NORMAL CASE. */
7799
/*---------------------------------------------------------*/
7800
case TcConnectionrec::COMMIT_STOPPED:
7801
case TcConnectionrec::WAIT_TUP_COMMIT:
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 */
7808
/*---------------------------------------------------------*/
7809
regTcPtr->reqBlockref = reqBlockref;
7810
regTcPtr->reqRef = reqPtr;
7811
regTcPtr->abortState = TcConnectionrec::REQ_FROM_TC;
7816
warningReport(signal, 6);
7820
if (regTcPtr->seqNoReplica != 0 &&
7821
regTcPtr->activeCreat != Fragrecord::AC_NR_COPY) {
7823
localCommitLab(signal);
7825
else if (regTcPtr->seqNoReplica == 0)
7828
completeTransLastLab(signal);
7833
completeTransNotLastLab(signal);
7835
}//Dblqh::execCOMPLETEREQ()
7840
void Dblqh::execLQHKEYCONF(Signal* signal)
7842
LqhKeyConf * const lqhKeyConf = (LqhKeyConf *)signal->getDataPtr();
7843
Uint32 tcIndex = lqhKeyConf->opPtr;
7844
Uint32 ttcConnectrecFileSize = ctcConnectrecFileSize;
7845
TcConnectionrec *regTcConnectionrec = tcConnectionrec;
7847
if (tcIndex >= ttcConnectrecFileSize) {
7848
errorReport(signal, 2);
7851
tcConnectptr.i = tcIndex;
7852
ptrAss(tcConnectptr, regTcConnectionrec);
7853
switch (tcConnectptr.p->connectState) {
7854
case TcConnectionrec::LOG_CONNECTED:
7856
completedLab(signal);
7859
case TcConnectionrec::COPY_CONNECTED:
7861
copyCompletedLab(signal);
7865
jamLine(tcConnectptr.p->connectState);
7870
}//Dblqh::execLQHKEYCONF()
7872
/* ------------------------------------------------------------------------- */
7873
/* ------- COMMIT PHASE ------- */
7875
/* ------------------------------------------------------------------------- */
7876
void Dblqh::commitReqLab(Signal* signal, Uint32 gci_hi, Uint32 gci_lo)
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) {
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);
7894
if (regTcPtr->transactionState == TcConnectionrec::LOG_COMMIT_QUEUED) {
7898
ndbrequire(regTcPtr->transactionState == TcConnectionrec::LOG_COMMIT_WRITTEN);
7899
tcConnectptr = saveTcPtr;
7900
} else if (logWriteState == TcConnectionrec::NOT_STARTED) {
7902
} else if (logWriteState == TcConnectionrec::NOT_WRITTEN) {
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;
7913
ndbrequire(logWriteState == TcConnectionrec::NOT_WRITTEN_WAIT);
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);
7923
} else if (transState == TcConnectionrec::LOG_COMMIT_QUEUED_WAIT_SIGNAL) {
7925
regTcPtr->transactionState = TcConnectionrec::LOG_COMMIT_QUEUED;
7927
} else if (transState == TcConnectionrec::LOG_COMMIT_WRITTEN_WAIT_SIGNAL) {
7930
warningReport(signal, 0);
7933
if (regTcPtr->seqNoReplica == 0 ||
7934
regTcPtr->activeCreat == Fragrecord::AC_NR_COPY) {
7936
localCommitLab(signal);
7939
commitReplyLab(signal);
7941
}//Dblqh::commitReqLab()
7943
void Dblqh::execLQH_WRITELOG_REQ(Signal* signal)
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) {
7958
/* ------------------------------------------------------------------------- */
7959
/* KEEP TRACK OF NEWEST GLOBAL CHECKPOINT THAT LQH HAS HEARD OF. */
7960
/* ------------------------------------------------------------------------- */
7961
cnewestGci = gci_hi;
7963
if (logWriteState == TcConnectionrec::WRITTEN) {
7964
/*---------------------------------------------------------------------------*/
7965
/* I NEED TO INSERT A COMMIT LOG RECORD SINCE WE ARE WRITING LOG IN THIS */
7967
/*---------------------------------------------------------------------------*/
7969
LogPartRecordPtr regLogPartPtr;
7970
Uint32 noOfLogPages = cnoOfLogPages;
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))
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) {
7990
regTcPtr->transactionState = TcConnectionrec::LOG_COMMIT_QUEUED_WAIT_SIGNAL;
7993
ndbrequire(transState == TcConnectionrec::PREPARED_RECEIVED_COMMIT);
7994
regTcPtr->transactionState = TcConnectionrec::LOG_COMMIT_QUEUED;
7998
writeCommitLog(signal, regLogPartPtr);
7999
if (transState == TcConnectionrec::PREPARED) {
8001
regTcPtr->transactionState = TcConnectionrec::LOG_COMMIT_WRITTEN_WAIT_SIGNAL;
8004
ndbrequire(transState == TcConnectionrec::PREPARED_RECEIVED_COMMIT);
8005
regTcPtr->transactionState = TcConnectionrec::LOG_COMMIT_WRITTEN;
8008
}//Dblqh::execLQH_WRITELOG_REQ()
8010
void Dblqh::localCommitLab(Signal* signal)
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;
8018
case Fragrecord::FSACTIVE:
8019
case Fragrecord::CRASH_RECOVERING:
8020
case Fragrecord::ACTIVE_CREATION:
8022
commitContinueAfterBlockedLab(signal);
8025
case Fragrecord::BLOCKED:
8027
linkFragQueue(signal);
8028
tcConnectptr.p->transactionState = TcConnectionrec::COMMIT_STOPPED;
8030
case Fragrecord::FREE:
8032
case Fragrecord::DEFINED:
8034
case Fragrecord::REMOVING:
8040
}//Dblqh::localCommitLab()
8042
void Dblqh::commitContinueAfterBlockedLab(Signal* signal)
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);
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);
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);
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;
8092
TRACENR(" tab: " << regTcPtr.p->tableref
8093
<< " frag: " << regTcPtr.p->fragmentid
8094
<< " activeCreat: " << (Uint32)regTcPtr.p->activeCreat);
8095
if (LqhKeyReq::getNrCopyFlag(regTcPtr.p->reqinfo))
8097
if (LqhKeyReq::getRowidFlag(regTcPtr.p->reqinfo))
8098
TRACENR(" rowid: " << regTcPtr.p->m_row_id);
8099
TRACENR(" key: " << getKeyInfoWordOrZero(regTcPtr.p, 0));
8101
if (signal->theData[0] != 0)
8102
TRACENR(" TIMESLICE");
8106
if(signal->theData[0] != 0)
8108
regTcPtr.p->transactionState = TcConnectionrec::WAIT_TUP_COMMIT;
8109
return; // TUP_COMMIT was timesliced
8112
TRACE_OP(regTcPtr.p, "ACC_COMMITREQ");
8114
Uint32 acc = refToMain(regTcPtr.p->tcAccBlockref);
8115
signal->theData[0] = regTcPtr.p->accConnectrec;
8116
EXECUTE_DIRECT(acc, GSN_ACC_COMMITREQ, signal, 1);
8120
TRACE_OP(regTcPtr.p, "ACC_COMMITREQ");
8122
Uint32 acc = refToMain(regTcPtr.p->tcAccBlockref);
8123
signal->theData[0] = regTcPtr.p->accConnectrec;
8124
EXECUTE_DIRECT(acc, GSN_ACC_COMMITREQ, signal, 1);
8127
if (dirtyOp && normalProtocol == 0)
8131
* The dirtyRead does not send anything but TRANSID_AI from LDM
8133
fragptr = regFragptr;
8134
tcConnectptr = regTcPtr;
8140
* The simpleRead will send a LQHKEYCONF
8141
* but have already released the locks
8145
fragptr = regFragptr;
8146
tcConnectptr = regTcPtr;
8147
packLqhkeyreqLab(signal);
8153
fragptr = regFragptr;
8154
tcConnectptr = regTcPtr;
8155
tupcommit_conf(signal, regTcPtr.p, regFragptr.p);
8159
Dblqh::tupcommit_conf_callback(Signal* signal, Uint32 tcPtrI)
8163
tcConnectptr.i = tcPtrI;
8164
ptrCheckGuard(tcConnectptr, ctcConnectrecFileSize, tcConnectionrec);
8165
TcConnectionrec * tcPtr = tcConnectptr.p;
8167
ndbrequire(tcPtr->transactionState == TcConnectionrec::WAIT_TUP_COMMIT);
8169
FragrecordPtr regFragptr;
8170
regFragptr.i = tcPtr->fragmentptr;
8171
c_fragment_pool.getPtr(regFragptr);
8172
fragptr = regFragptr;
8174
TRACE_OP(tcPtr, "ACC_COMMITREQ");
8176
Uint32 acc = refToMain(tcPtr->tcAccBlockref);
8177
signal->theData[0] = tcPtr->accConnectrec;
8178
EXECUTE_DIRECT(acc, GSN_ACC_COMMITREQ, signal, 1);
8181
tcConnectptr.i = tcPtrI;
8182
tcConnectptr.p = tcPtr;
8183
tupcommit_conf(signal, tcPtr, regFragptr.p);
8187
Dblqh::tupcommit_conf(Signal* signal,
8188
TcConnectionrec * tcPtrP,
8189
Fragrecord * regFragptr)
8191
Uint32 dirtyOp = tcPtrP->dirtyOp;
8192
Uint32 seqNoReplica = tcPtrP->seqNoReplica;
8193
Uint32 activeCreat = tcPtrP->activeCreat;
8194
if (tcPtrP->gci_hi > regFragptr->newestGci) {
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;
8202
if (dirtyOp != ZTRUE)
8204
if (seqNoReplica == 0 || activeCreat == Fragrecord::AC_NR_COPY)
8207
commitReplyLab(signal);
8210
if (seqNoReplica == 0)
8213
completeTransLastLab(signal);
8218
completeTransNotLastLab(signal);
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)
8230
if (activeCreat == Fragrecord::AC_NR_COPY)
8233
ndbrequire(LqhKeyReq::getNrCopyFlag(tcPtrP->reqinfo));
8234
ndbrequire(tcPtrP->m_nr_delete.m_cnt == 0);
8236
packLqhkeyreqLab(signal);
8240
ndbrequire(tcPtrP->abortState != TcConnectionrec::NEW_FROM_TC);
8242
sendLqhTransconf(signal, LqhTransConf::Committed);
8246
}//Dblqh::commitContinueAfterBlockedLab()
8248
void Dblqh::commitReplyLab(Signal* signal)
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) {
8260
sendCommittedTc(signal, clientBlockref);
8264
sendCommitLqh(signal, clientBlockref);
8267
} else if (regTcPtr->abortState == TcConnectionrec::REQ_FROM_TC) {
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);
8275
ndbrequire(regTcPtr->abortState == TcConnectionrec::NEW_FROM_TC);
8278
}//Dblqh::commitReplyLab()
8280
/* ------------------------------------------------------------------------- */
8281
/* ------- COMPLETE PHASE ------- */
8283
/* ------------------------------------------------------------------------- */
8284
void Dblqh::completeTransNotLastLab(Signal* signal)
8286
TcConnectionrec * const regTcPtr = tcConnectptr.p;
8287
if (regTcPtr->abortState == TcConnectionrec::ABORT_IDLE) {
8288
Uint32 clientBlockref = regTcPtr->clientBlockref;
8290
sendCompleteLqh(signal, clientBlockref);
8295
completeUnusualLab(signal);
8298
}//Dblqh::completeTransNotLastLab()
8300
void Dblqh::completeTransLastLab(Signal* signal)
8302
TcConnectionrec * const regTcPtr = tcConnectptr.p;
8303
if (regTcPtr->abortState == TcConnectionrec::ABORT_IDLE) {
8304
Uint32 clientBlockref = regTcPtr->clientBlockref;
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);
8315
completeUnusualLab(signal);
8318
}//Dblqh::completeTransLastLab()
8320
void Dblqh::completeUnusualLab(Signal* signal)
8322
TcConnectionrec * const regTcPtr = tcConnectptr.p;
8323
if (regTcPtr->abortState == TcConnectionrec::ABORT_FROM_TC) {
8325
sendAborted(signal);
8326
} else if (regTcPtr->abortState == TcConnectionrec::NEW_FROM_TC) {
8329
ndbrequire(regTcPtr->abortState == TcConnectionrec::REQ_FROM_TC);
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);
8340
}//Dblqh::completeUnusualLab()
8342
/* ========================================================================= */
8343
/* ======= RELEASE TC CONNECT RECORD ======= */
8345
/* RELEASE A TC CONNECT RECORD TO THE FREELIST. */
8346
/* ========================================================================= */
8347
void Dblqh::releaseTcrec(Signal* signal, TcConnectionrecPtr locTcConnectptr)
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;
8356
ndbassert(locTcConnectptr.p->tcScanRec == RNIL);
8359
tabPtr.i = locTcConnectptr.p->tableref;
8360
if(tabPtr.i == RNIL)
8363
ptrCheckGuard(tabPtr, ctabrecFileSize, tablerec);
8368
if (op == ZREAD || op == ZUNLOCK)
8370
ndbrequire(tabPtr.p->usageCountR > 0);
8371
tabPtr.p->usageCountR--;
8375
ndbrequire(tabPtr.p->usageCountW > 0);
8376
tabPtr.p->usageCountW--;
8378
}//Dblqh::releaseTcrec()
8380
void Dblqh::releaseTcrecLog(Signal* signal, TcConnectionrecPtr locTcConnectptr)
8383
locTcConnectptr.p->tcTimer = 0;
8384
locTcConnectptr.p->transactionState = TcConnectionrec::TC_NOT_CONNECTED;
8385
locTcConnectptr.p->nextTcConnectrec = cfirstfreeTcConrec;
8386
cfirstfreeTcConrec = locTcConnectptr.i;
8389
tabPtr.i = locTcConnectptr.p->tableref;
8390
if(tabPtr.i == RNIL)
8393
}//Dblqh::releaseTcrecLog()
8395
/* ------------------------------------------------------------------------- */
8396
/* ------- ABORT PHASE ------- */
8398
/*THIS PART IS USED AT ERRORS THAT CAUSE ABORT OF TRANSACTION. */
8399
/* ------------------------------------------------------------------------- */
8401
Dblqh::remove_commit_marker(TcConnectionrec * const regTcPtr)
8403
Ptr<CommitAckMarker> tmp;
8404
Uint32 commitAckMarker = regTcPtr->commitAckMarker;
8405
regTcPtr->commitAckMarker = RNIL;
8406
if (commitAckMarker == RNIL)
8409
m_commitAckMarkerHash.getPtr(tmp, commitAckMarker);
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);
8415
ndbrequire(tmp.p->reference_count > 0);
8416
tmp.p->reference_count--;
8417
if (tmp.p->reference_count == 0)
8420
m_commitAckMarkerHash.release(tmp);
8424
/* ***************************************************>> */
8425
/* ABORT: Abort transaction in connection. Sender TC. */
8426
/* This is the normal protocol (See COMMIT) */
8427
/* ***************************************************>> */
8428
void Dblqh::execABORT(Signal* signal)
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);
8441
if (findTransaction(transid1,
8443
tcOprec, 0) != ZOK) {
8446
if(ERROR_INSERTED(5039) &&
8447
refToNode(signal->getSendersBlockRef()) != getOwnNodeId()){
8449
SET_ERROR_INSERT_VALUE(5040);
8453
if(ERROR_INSERTED(5040) &&
8454
refToNode(signal->getSendersBlockRef()) != getOwnNodeId()){
8456
SET_ERROR_INSERT_VALUE(5003);
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);
8474
TcConnectionrec * const regTcPtr = tcConnectptr.p;
8475
if (ERROR_INSERTED(5100))
8477
SET_ERROR_INSERT_VALUE(5101);
8480
CRASH_INSERTION2(5101, regTcPtr->nextReplica != ZNIL);
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);
8503
regTcPtr->abortState = TcConnectionrec::ABORT_FROM_TC;
8505
remove_commit_marker(regTcPtr);
8506
TRACE_OP(regTcPtr, "ABORT");
8508
abortStateHandlerLab(signal);
8511
}//Dblqh::execABORT()
8513
/* ************************************************************************>>
8514
* ABORTREQ: Same as ABORT but used in case one node isn't working ok.
8516
* ************************************************************************>> */
8517
void Dblqh::execABORTREQ(Signal* signal)
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__);
8528
if (ERROR_INSERTED(5016)) {
8529
CLEAR_ERROR_INSERT_VALUE;
8530
sendSignalWithDelay(cownref, GSN_ABORTREQ, signal, 2000, 6);
8533
if (findTransaction(transid1,
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);
8544
TcConnectionrec * const regTcPtr = tcConnectptr.p;
8545
if (regTcPtr->transactionState != TcConnectionrec::PREPARED) {
8546
warningReport(signal, 10);
8549
regTcPtr->reqBlockref = reqBlockref;
8550
regTcPtr->reqRef = reqPtr;
8551
regTcPtr->abortState = TcConnectionrec::REQ_FROM_TC;
8553
abortCommonLab(signal);
8555
}//Dblqh::execABORTREQ()
8557
/* ************>> */
8559
/* ************>> */
8560
void Dblqh::execACC_TO_REF(Signal* signal)
8563
terrorCode = signal->theData[1];
8564
abortErrorLab(signal);
8566
}//Dblqh::execACC_TO_REF()
8571
void Dblqh::execACCKEYREF(Signal* signal)
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:
8582
case TcConnectionrec::WAIT_ACC_ABORT:
8583
case TcConnectionrec::ABORT_STOPPED:
8584
case TcConnectionrec::ABORT_QUEUED:
8586
/* ------------------------------------------------------------------------- */
8587
/*IGNORE SINCE ABORT OF THIS OPERATION IS ONGOING ALREADY. */
8588
/* ------------------------------------------------------------------------- */
8595
const Uint32 errCode = terrorCode;
8596
tcPtr->errorCode = errCode;
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;
8611
TRACENR(" tab: " << tcPtr->tableref
8612
<< " frag: " << tcPtr->fragmentid
8613
<< " activeCreat: " << (Uint32)tcPtr->activeCreat);
8614
if (LqhKeyReq::getNrCopyFlag(tcPtr->reqinfo))
8616
if (LqhKeyReq::getRowidFlag(tcPtr->reqinfo))
8617
TRACENR(" rowid: " << tcPtr->m_row_id);
8618
TRACENR(" key: " << getKeyInfoWordOrZero(tcPtr, 0));
8623
ndbrequire(tcPtr->activeCreat == Fragrecord::AC_NORMAL);
8624
ndbrequire(!LqhKeyReq::getNrCopyFlag(tcPtr->reqinfo));
8627
* Not only primary replica can get ZTUPLE_ALREADY_EXIST || ZNO_TUPLE_FOUND
8629
* 1) op1 - primary insert ok
8630
* 2) op1 - backup insert fail (log full or what ever)
8631
* 3) op1 - delete ok @ primary
8632
* 4) op1 - delete fail @ backup
8634
* -> ZNO_TUPLE_FOUND is possible
8636
* 1) op1 primary delete ok
8637
* 2) op1 backup delete fail (log full or what ever)
8638
* 3) op2 insert ok @ primary
8639
* 4) op2 insert fail @ backup
8641
* -> ZTUPLE_ALREADY_EXIST
8643
tcPtr->abortState = TcConnectionrec::ABORT_FROM_LQH;
8644
abortCommonLab(signal);
8646
}//Dblqh::execACCKEYREF()
8648
void Dblqh::localAbortStateHandlerLab(Signal* signal)
8650
TcConnectionrec * const regTcPtr = tcConnectptr.p;
8651
if (regTcPtr->abortState != TcConnectionrec::ABORT_IDLE) {
8655
regTcPtr->abortState = TcConnectionrec::ABORT_FROM_LQH;
8656
regTcPtr->errorCode = terrorCode;
8657
abortStateHandlerLab(signal);
8659
}//Dblqh::localAbortStateHandlerLab()
8661
void Dblqh::abortStateHandlerLab(Signal* signal)
8663
TcConnectionrec * const regTcPtr = tcConnectptr.p;
8664
switch (regTcPtr->transactionState) {
8665
case TcConnectionrec::PREPARED:
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) {
8675
sendLqhTransconf(signal, LqhTransConf::Prepared);
8679
case TcConnectionrec::LOG_COMMIT_WRITTEN_WAIT_SIGNAL:
8680
case TcConnectionrec::LOG_COMMIT_QUEUED_WAIT_SIGNAL:
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);
8690
case TcConnectionrec::WAIT_TUPKEYINFO:
8691
case TcConnectionrec::WAIT_ATTR:
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
/* ------------------------------------------------------------------------- */
8699
case TcConnectionrec::WAIT_TUP:
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;
8708
case TcConnectionrec::WAIT_ACC:
8710
abortContinueAfterBlockedLab(signal);
8713
case TcConnectionrec::LOG_QUEUED:
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
/* ------------------------------------------------------------------------- */
8723
case TcConnectionrec::STOPPED:
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
8731
releaseWaitQueue(signal);
8732
continueAfterLogAbortWriteLab(signal);
8735
case TcConnectionrec::WAIT_AI_AFTER_ABORT:
8737
/* ------------------------------------------------------------------------- */
8738
/* ABORT OF ACC AND TUP ALREADY COMPLETED. THIS STATE IS ONLY USED WHEN */
8739
/* CREATING A NEW FRAGMENT. */
8740
/* ------------------------------------------------------------------------- */
8741
continueAbortLab(signal);
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:
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 */
8754
/* ------------------------------------------------------------------------- */
8757
case TcConnectionrec::WAIT_TUP_COMMIT:
8758
case TcConnectionrec::COMMIT_STOPPED:
8759
case TcConnectionrec::LOG_COMMIT_QUEUED:
8760
case TcConnectionrec::COMMIT_QUEUED:
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) {
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
/* ------------------------------------------------------------------------- */
8774
if (regTcPtr->opSimple) {
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
/* ------------------------------------------------------------------------- */
8783
ndbrequire(regTcPtr->abortState == TcConnectionrec::NEW_FROM_TC);
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);
8792
case TcConnectionrec::COMMITTED:
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);
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
/* ------------------------------------------------------------------------- */
8810
abortCommonLab(signal);
8812
}//Dblqh::abortStateHandlerLab()
8814
void Dblqh::abortErrorLab(Signal* signal)
8816
ptrCheckGuard(tcConnectptr, ctcConnectrecFileSize, tcConnectionrec);
8817
TcConnectionrec * const regTcPtr = tcConnectptr.p;
8818
if (regTcPtr->abortState == TcConnectionrec::ABORT_IDLE) {
8820
regTcPtr->abortState = TcConnectionrec::ABORT_FROM_LQH;
8821
regTcPtr->errorCode = terrorCode;
8823
abortCommonLab(signal);
8825
}//Dblqh::abortErrorLab()
8827
void Dblqh::abortCommonLab(Signal* signal)
8829
TcConnectionrec * const regTcPtr = tcConnectptr.p;
8830
const Uint32 activeCreat = regTcPtr->activeCreat;
8832
remove_commit_marker(regTcPtr);
8834
if (unlikely(activeCreat == Fragrecord::AC_NR_COPY))
8837
if (regTcPtr->m_nr_delete.m_cnt)
8841
* Let operation wait for pending NR operations
8846
* Only disk table can have pending ops...
8848
TablerecPtr tablePtr;
8849
tablePtr.i = regTcPtr->tableref;
8850
ptrCheckGuard(tablePtr, ctabrecFileSize, tablerec);
8851
ndbrequire(tablePtr.p->m_disk_table);
8857
fragptr.i = regTcPtr->fragmentptr;
8858
if (fragptr.i != RNIL) {
8860
c_fragment_pool.getPtr(fragptr);
8861
switch (fragptr.p->fragStatus) {
8862
case Fragrecord::FSACTIVE:
8863
case Fragrecord::CRASH_RECOVERING:
8864
case Fragrecord::ACTIVE_CREATION:
8866
abortContinueAfterBlockedLab(signal);
8869
case Fragrecord::BLOCKED:
8871
linkFragQueue(signal);
8872
regTcPtr->transactionState = TcConnectionrec::ABORT_STOPPED;
8875
case Fragrecord::FREE:
8877
case Fragrecord::DEFINED:
8879
case Fragrecord::REMOVING:
8887
continueAbortLab(signal);
8889
}//Dblqh::abortCommonLab()
8891
void Dblqh::abortContinueAfterBlockedLab(Signal* signal)
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;
8905
TRACE_OP(regTcPtr, "ACC ABORT");
8906
Uint32 canBlock = 2; // 2, block if needed
8907
switch(regTcPtr->transactionState){
8908
case TcConnectionrec::WAIT_TUP:
8911
* This is when getting from execTUPKEYREF
8912
* in which case we *do* have ACC lock
8913
* and should not (need to) block
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);
8926
if (signal->theData[1] == RNIL)
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
8935
* --------------------------------------------------------------------- */
8939
execACC_ABORTCONF(signal);
8941
}//Dblqh::abortContinueAfterBlockedLab()
8943
/* ******************>> */
8944
/* ACC_ABORTCONF > */
8945
/* ******************>> */
8946
void Dblqh::execACC_ABORTCONF(Signal* signal)
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);
8954
TRACE_OP(regTcPtr, "ACC_ABORTCONF");
8955
signal->theData[0] = regTcPtr->tupConnectrec;
8956
EXECUTE_DIRECT(DBTUP, GSN_TUP_ABORTREQ, signal, 1);
8959
continueAbortLab(signal);
8961
}//Dblqh::execACC_ABORTCONF()
8963
void Dblqh::continueAbortLab(Signal* signal)
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) {
8976
/* ----------------------------------------------------------------------
8977
* I NEED TO INSERT A ABORT LOG RECORD SINCE WE ARE WRITING LOG IN THIS
8979
* ---------------------------------------------------------------------- */
8980
initLogPointers(signal);
8981
if (cnoOfLogPages == 0 ||
8982
!logPartPtr.p->m_log_complete_queue.isEmpty())
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;
8995
writeAbortLog(signal);
8996
removeLogTcrec(signal);
8997
} else if (regTcPtr->logWriteState == TcConnectionrec::NOT_STARTED) {
8999
} else if (regTcPtr->logWriteState == TcConnectionrec::NOT_WRITTEN) {
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;
9010
ndbrequire(regTcPtr->logWriteState == TcConnectionrec::NOT_WRITTEN_WAIT);
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);
9021
continueAfterLogAbortWriteLab(signal);
9023
}//Dblqh::continueAbortLab()
9025
void Dblqh::continueAfterLogAbortWriteLab(Signal* signal)
9027
TcConnectionrec * const regTcPtr = tcConnectptr.p;
9029
remove_commit_marker(regTcPtr);
9031
if (regTcPtr->operation == ZREAD && regTcPtr->dirtyOp &&
9032
!LqhKeyReq::getNormalProtocolFlag(regTcPtr->reqinfo))
9035
TcKeyRef * const tcKeyRef = (TcKeyRef *) signal->getDataPtrSend();
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);
9045
if (regTcPtr->abortState == TcConnectionrec::ABORT_FROM_LQH) {
9046
LqhKeyRef * const lqhKeyRef = (LqhKeyRef *)signal->getDataPtrSend();
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) {
9058
sendAborted(signal);
9059
} else if (regTcPtr->abortState == TcConnectionrec::NEW_FROM_TC) {
9061
sendLqhTransconf(signal, LqhTransConf::Aborted);
9063
ndbrequire(regTcPtr->abortState == TcConnectionrec::REQ_FROM_TC);
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,
9074
}//Dblqh::continueAfterLogAbortWriteLab()
9077
Dblqh::sendTCKEYREF(Signal* signal, Uint32 ref, Uint32 routeRef, Uint32 cnt)
9079
const Uint32 nodeId = refToNode(ref);
9080
const bool connectedToNode = getNodeInfo(nodeId).m_connected;
9082
if (likely(connectedToNode))
9085
sendSignal(ref, GSN_TCKEYREF, signal, TcKeyRef::SignalLength, JBB);
9090
getNodeInfo(refToNode(routeRef)).m_version >= MAKE_VERSION(5,1,14))
9093
memmove(signal->theData+25, signal->theData, 4*TcKeyRef::SignalLength);
9094
RouteOrd* ord = (RouteOrd*)signal->getDataPtrSend();
9096
ord->srcRef = reference();
9097
ord->gsn = GSN_TCKEYREF;
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,
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);
9118
/* ##########################################################################
9119
* ####### MODULE TO HANDLE TC FAILURE #######
9121
* ########################################################################## */
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)
9130
UintR TfoundNodes = 0;
9132
UintR Tdata[MAX_NDB_NODES];
9135
NodeFailRep * const nodeFail = (NodeFailRep *)&signal->theData[0];
9137
TnoOfNodes = nodeFail->noOfNodes;
9139
for (i = 1; i < MAX_NDB_NODES; i++) {
9141
if(NdbNodeBitmask::get(nodeFail->theNodes, i)){
9149
c_master_node_id = nodeFail->masterNodeId;
9153
ptrAss(lcpPtr, lcpRecord);
9155
ndbrequire(index == TnoOfNodes);
9156
ndbrequire(cnoOfNodes - 1 < MAX_NDB_NODES);
9157
for (i = 0; i < TnoOfNodes; i++) {
9158
const Uint32 nodeId = Tdata[i];
9161
HostRecordPtr Thostptr;
9162
Thostptr.i = nodeId;
9163
ptrCheckGuard(Thostptr, chostFileSize, hostRecord);
9164
Thostptr.p->nodestatus = ZNODE_DOWN;
9167
lcpPtr.p->m_EMPTY_LCP_REQ.clear(nodeId);
9169
for (Uint32 j = 0; j < cnoOfNodes; j++) {
9171
if (cnodeData[j] == nodeId){
9173
cnodeStatus[j] = ZNODE_DOWN;
9179
/* Perform block-level ndbd failure handling */
9180
Callback cb = { safe_cast(&Dblqh::ndbdFailBlockCleanupCallback),
9182
simBlockNodeFailure(signal, Tdata[i], cb);
9184
ndbrequire(TnoOfNodes == TfoundNodes);
9185
}//Dblqh::execNODE_FAILREP()
9189
Dblqh::ndbdFailBlockCleanupCallback(Signal* signal,
9190
Uint32 failedNodeId,
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);
9204
/* ************************************************************************>>
9205
* LQH_TRANSREQ: Report status of all transactions where TC was coordinated
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)
9218
if (!checkNodeFailSequence(signal))
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)) {
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;
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);
9256
}//Dblqh::execLQH_TRANSREQ()
9258
void Dblqh::lqhTransNextLab(Signal* signal)
9264
if (tcNodeFailptr.p->tcFailStatus == TcNodeFailRecord::TC_STATE_BREAK) {
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;
9276
tstart = tcNodeFailptr.p->tcRecNow;
9277
tend = tstart + 200;
9279
for (tcConnectptr.i = tstart; tcConnectptr.i <= guard0; tcConnectptr.i++) {
9281
if (tcConnectptr.i >= ctcConnectrecFileSize) {
9284
* Finished with scanning operation record
9289
if (ERROR_INSERTED(5061))
9291
CLEAR_ERROR_INSERT_VALUE;
9292
for (Uint32 i = 0; i < cnoOfNodes; i++)
9294
Uint32 node = cnodeData[i];
9295
if (node != getOwnNodeId() && cnodeStatus[i] == ZNODE_UP)
9297
ndbout_c("clearing ERROR_INSERT in LQH:%u", node);
9298
signal->theData[0] = 0;
9299
sendSignal(numberToRef(DBLQH, node), GSN_NDB_TAMPER,
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);
9312
if (ERROR_INSERTED(5050))
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);
9322
signal->theData[0] = 9999;
9323
sendSignal(numberToRef(CMVMI, c_master_node_id),
9324
GSN_NDB_TAMPER, signal, 1, JBB);
9328
scanMarkers(signal, tcNodeFailptr.i, 0, RNIL);
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 ) {
9338
jam(); /* Skip over */
9342
if (tcConnectptr.p->opSimple == ZTRUE) {
9344
break; /* Skip over */
9349
tcConnectptr.p->tcNodeFailrec = tcNodeFailptr.i;
9350
tcConnectptr.p->abortState = TcConnectionrec::NEW_FROM_TC;
9351
abortStateHandlerLab(signal);
9356
scanptr.i = tcConnectptr.p->tcScanRec;
9357
c_scanRecordPool.getPtr(scanptr);
9358
switch(scanptr.p->scanType){
9359
case ScanRecord::COPY:
9362
if (scanptr.p->scanNodeId == tcNodeFailptr.p->oldNodeId) {
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);
9376
case ScanRecord::SCAN:
9379
if (refToNode(tcConnectptr.p->tcBlockref) ==
9380
tcNodeFailptr.p->oldNodeId) {
9382
tcConnectptr.p->tcNodeFailrec = tcNodeFailptr.i;
9383
tcConnectptr.p->abortState = TcConnectionrec::NEW_FROM_TC;
9384
closeScanRequestLab(signal);
9390
ndbout_c("scanptr.p->scanType: %u", scanptr.p->scanType);
9391
ndbout_c("tcConnectptr.p->transactionState: %u",
9392
tcConnectptr.p->transactionState);
9399
#if defined VM_TRACE || defined ERROR_INSERT
9401
ndbrequire(tcConnectptr.p->tcScanRec == RNIL);
9407
#if defined VM_TRACE || defined ERROR_INSERT
9409
ndbrequire(tcConnectptr.p->tcScanRec == RNIL);
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);
9418
}//Dblqh::lqhTransNextLab()
9421
Dblqh::scanMarkers(Signal* signal,
9428
TcNodeFailRecordPtr tcNodeFailPtr;
9429
tcNodeFailPtr.i = tcNodeFail;
9430
ptrCheckGuard(tcNodeFailPtr, ctcNodeFailrecFileSize, tcNodeFailRecord);
9431
const Uint32 crashedTcNodeId = tcNodeFailPtr.p->oldNodeId;
9433
if (tcNodeFailPtr.p->tcFailStatus == TcNodeFailRecord::TC_STATE_BREAK)
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);
9447
CommitAckMarkerIterator iter;
9449
m_commitAckMarkerHash.next(startBucket, iter);
9453
iter.bucket = startBucket;
9454
m_commitAckMarkerHash.getPtr(iter.curr);
9455
m_commitAckMarkerHash.next(iter);
9458
const Uint32 RT_BREAK = 256;
9459
for(i = 0; i<RT_BREAK || iter.bucket == startBucket; i++){
9462
if(iter.curr.i == RNIL){
9464
* Done with iteration
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,
9477
if(iter.curr.p->tcNodeId == crashedTcNodeId){
9481
* Found marker belonging to crashed node
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,
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);
9502
m_commitAckMarkerHash.next(iter);
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);
9512
/* #########################################################################
9513
* ####### SCAN MODULE #######
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)
9527
AccScanConf * const accScanConf = (AccScanConf *)&signal->theData[0];
9529
scanptr.i = accScanConf->scanPtr;
9530
c_scanRecordPool.getPtr(scanptr);
9531
if (scanptr.p->scanState == ScanRecord::WAIT_ACC_SCAN) {
9532
accScanConfScanLab(signal);
9534
ndbrequire(scanptr.p->scanState == ScanRecord::WAIT_ACC_COPY);
9535
accScanConfCopyLab(signal);
9537
}//Dblqh::execACC_SCANCONF()
9539
/* ************>> */
9541
/* ************>> */
9542
void Dblqh::execACC_SCANREF(Signal* signal)
9545
ndbrequire(refToMain(signal->getSendersBlockRef()) == DBTUX);
9546
const AccScanRef refCopy = *(const AccScanRef*)signal->getDataPtr();
9547
const AccScanRef* ref = &refCopy;
9548
ndbrequire(ref->errorCode != 0);
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;
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.
9561
if (scanptr.p->scanStoredProcId != RNIL) {
9563
scanptr.p->scanCompletedStatus = ZTRUE;
9564
accScanCloseConfLab(signal);
9567
tupScanCloseConfLab(signal);
9568
}//Dblqh::execACC_SCANREF()
9570
/* ***************>> */
9571
/* NEXT_SCANCONF > */
9572
/* ***************>> */
9573
void Dblqh::execNEXT_SCANCONF(Signal* signal)
9575
NextScanConf * const nextScanConf = (NextScanConf *)&signal->theData[0];
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];
9583
if (signal->getLength() > 2 && nextScanConf->accOperationPtr != RNIL)
9585
Ptr<TcConnectionrec> regTcPtr;
9586
regTcPtr.i = scanptr.p->scanTcrec;
9587
ptrCheckGuard(regTcPtr, ctcConnectrecFileSize, tcConnectionrec);
9588
ndbassert(regTcPtr.p->fragmentid == nextScanConf->fragId);
9592
fragptr.i = scanptr.p->fragPtrI;
9593
c_fragment_pool.getPtr(fragptr);
9594
switch (scanptr.p->scanState) {
9595
case ScanRecord::WAIT_CLOSE_SCAN:
9597
accScanCloseConfLab(signal);
9599
case ScanRecord::WAIT_CLOSE_COPY:
9601
accCopyCloseConfLab(signal);
9603
case ScanRecord::WAIT_NEXT_SCAN:
9605
nextScanConfScanLab(signal);
9607
case ScanRecord::WAIT_NEXT_SCAN_COPY:
9609
nextScanConfCopyLab(signal);
9611
case ScanRecord::WAIT_RELEASE_LOCK:
9613
ndbrequire(signal->length() == 1);
9614
scanLockReleasedLab(signal);
9617
ndbout_c("%d", scanptr.p->scanState);
9620
}//Dblqh::execNEXT_SCANCONF()
9622
/* ***************> */
9623
/* NEXT_SCANREF > */
9624
/* ***************> */
9625
void Dblqh::execNEXT_SCANREF(Signal* signal)
9628
ndbrequire(refToMain(signal->getSendersBlockRef()) == DBTUX);
9629
const NextScanRef refCopy = *(const NextScanRef*)signal->getDataPtr();
9630
const NextScanRef* ref = &refCopy;
9631
ndbrequire(ref->errorCode != 0);
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;
9640
* MRR scan may have other ranges left. But the scan has already
9641
* failed. Terminate the scan now.
9643
scanptr.p->scanCompletedStatus = ZTRUE;
9644
accScanCloseConfLab(signal);
9645
}//Dblqh::execNEXT_SCANREF()
9647
/* ******************> */
9648
/* STORED_PROCCONF > */
9649
/* ******************> */
9650
void Dblqh::execSTORED_PROCCONF(Signal* signal)
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:
9661
scanptr.p->scanStoredProcId = storedProcId;
9662
storedProcConfScanLab(signal);
9664
case ScanRecord::WAIT_DELETE_STORED_PROC_ID_SCAN:
9666
tupScanCloseConfLab(signal);
9668
case ScanRecord::WAIT_STORED_PROC_COPY:
9670
scanptr.p->scanStoredProcId = storedProcId;
9671
storedProcConfCopyLab(signal);
9673
case ScanRecord::WAIT_DELETE_STORED_PROC_ID_COPY:
9675
tupCopyCloseConfLab(signal);
9680
}//Dblqh::execSTORED_PROCCONF()
9682
/* ****************** */
9683
/* STORED_PROCREF > */
9684
/* ****************** */
9685
void Dblqh::execSTORED_PROCREF(Signal* signal)
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:
9696
scanptr.p->scanCompletedStatus = ZTRUE;
9697
scanptr.p->scanStoredProcId = signal->theData[2];
9698
tcConnectptr.p->errorCode = errorCode;
9699
closeScanLab(signal);
9704
}//Dblqh::execSTORED_PROCREF()
9706
/* --------------------------------------------------------------------------
9707
* ENTER SCAN_NEXTREQ
9708
* --------------------------------------------------------------------------
9710
* TRANSACTION_STATE = SCAN_STATE
9711
* SCAN_STATE = WAIT_SCAN_NEXTREQ
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)
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();
9730
if (findTransaction(transid1, transid2, senderData, hashHi) != ZOK){
9733
" Received SCAN_NEXTREQ in LQH with close flag when closed");
9734
ndbrequire(nextReq->requestInfo == ScanFragNextReq::ZCLOSE);
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);
9743
if (ERROR_INSERTED(5023)){
9744
// Drop signal if sender is same node
9745
if (refToNode(signal->senderBlockRef()) == cownNodeid) {
9746
CLEAR_ERROR_INSERT_VALUE;
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;
9757
if (ERROR_INSERTED(5025))
9760
* This does not work as signal->getSendersBlockRef() is used
9761
* as "hashHi"...not having a real data-word for this is not optimal
9762
* but it will work...summary: disable this ERROR_INSERT
9764
CLEAR_ERROR_INSERT_VALUE;
9767
if (ERROR_INSERTED(5030)){
9768
ndbout << "ERROR 5030" << endl;
9769
CLEAR_ERROR_INSERT_VALUE;
9774
if(ERROR_INSERTED(5036)){
9779
if (ScanFragNextReq::getCorrFactorFlag(nextReq->requestInfo))
9782
Uint32 corrFactorLo = nextReq->variableData[pos++];
9783
tcConnectptr.p->m_corrFactorLo &= 0xFFFF0000;
9784
tcConnectptr.p->m_corrFactorLo |= corrFactorLo;
9787
scanptr.i = tcConnectptr.p->tcScanRec;
9788
ndbrequire(scanptr.i != RNIL);
9789
c_scanRecordPool.getPtr(scanptr);
9790
scanptr.p->scanTcWaiting = cLqhTimeOutCount;
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
9797
* ------------------------------------------------------------------ */
9798
if (nextReq->requestInfo == ScanFragNextReq::ZCLOSE)
9801
if(ERROR_INSERTED(5034)){
9802
CLEAR_ERROR_INSERT_VALUE;
9804
if(ERROR_INSERTED(5036)){
9805
CLEAR_ERROR_INSERT_VALUE;
9808
closeScanRequestLab(signal);
9812
fragptr.i = tcConnectptr.p->fragmentptr;
9813
c_fragment_pool.getPtr(fragptr);
9816
* Change parameters while running
9817
* (is currently not supported)
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;
9823
if (max_rows > scanptr.p->m_max_batch_size_rows)
9829
if (!seize_acc_ptr_list(scanptr.p,
9830
scanptr.p->m_max_batch_size_rows, max_rows))
9833
tcConnectptr.p->errorCode = ScanFragRef::ZTOO_MANY_ACTIVE_SCAN_ERROR;
9834
closeScanRequestLab(signal);
9837
cbookedAccOps += (max_rows - scanptr.p->m_max_batch_size_rows);
9838
scanptr.p->m_max_batch_size_rows = max_rows;
9840
else if (unlikely(max_rows < scanptr.p->m_max_batch_size_rows))
9843
cbookedAccOps -= (scanptr.p->m_max_batch_size_rows - max_rows);
9844
scanptr.p->m_max_batch_size_rows = max_rows;
9847
/* --------------------------------------------------------------------
9848
* If scanLockHold = TRUE we need to unlock previous round of
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)) {
9858
scanptr.p->scanReleaseCounter = 1;
9859
scanReleaseLocksLab(signal);
9863
/* -----------------------------------------------------------------------
9864
* We end up here when scanLockHold = FALSE or no rows was locked from
9866
* Simply continue scanning.
9867
* ----------------------------------------------------------------------- */
9868
continueScanNextReqLab(signal);
9869
}//Dblqh::execSCAN_NEXTREQ()
9871
void Dblqh::continueScanNextReqLab(Signal* signal)
9873
if (scanptr.p->scanCompletedStatus == ZTRUE) {
9875
closeScanLab(signal);
9879
if(scanptr.p->m_last_row){
9881
scanptr.p->scanCompletedStatus = ZTRUE;
9882
scanptr.p->scanState = ScanRecord::WAIT_SCAN_NEXTREQ;
9883
sendScanFragConf(signal, ZFALSE);
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()
9894
/* -------------------------------------------------------------------------
9895
* WE NEED TO RELEASE LOCKS BEFORE CONTINUING
9896
* ------------------------------------------------------------------------- */
9897
void Dblqh::scanReleaseLocksLab(Signal* signal)
9899
switch (fragptr.p->fragStatus) {
9900
case Fragrecord::FSACTIVE:
9903
case Fragrecord::BLOCKED:
9905
linkFragQueue(signal);
9906
tcConnectptr.p->transactionState = TcConnectionrec::SCAN_RELEASE_STOPPED;
9909
case Fragrecord::FREE:
9911
case Fragrecord::ACTIVE_CREATION:
9913
case Fragrecord::CRASH_RECOVERING:
9915
case Fragrecord::DEFINED:
9917
case Fragrecord::REMOVING:
9922
continueScanReleaseAfterBlockedLab(signal);
9923
}//Dblqh::scanReleaseLocksLab()
9925
void Dblqh::continueScanReleaseAfterBlockedLab(Signal* signal)
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;
9932
get_acc_ptr_from_scan_record(scanptr.p,
9933
scanptr.p->scanReleaseCounter -1,
9935
signal->theData[2] = NextScanReq::ZSCAN_COMMIT;
9936
sendSignal(scanptr.p->scanBlockref, GSN_NEXT_SCANREQ, signal, 3, JBB);
9937
}//Dblqh::continueScanReleaseAfterBlockedLab()
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
* -------------------------------------------------------------------------
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
9952
* ------------------------------------------------------------------------- */
9953
void Dblqh::closeScanRequestLab(Signal* signal)
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:
9962
tupScanCloseConfLab(signal);
9964
case ScanRecord::WAIT_NEXT_SCAN:
9966
/* -------------------------------------------------------------------
9967
* SET COMPLETION STATUS AND WAIT FOR OPPORTUNITY TO STOP THE SCAN.
9968
* ------------------------------------------------------------------- */
9969
scanptr.p->scanCompletedStatus = ZTRUE;
9971
case ScanRecord::WAIT_ACC_SCAN:
9972
case ScanRecord::WAIT_STORED_PROC_SCAN:
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;
9980
case ScanRecord::WAIT_CLOSE_SCAN:
9982
scanptr.p->scanCompletedStatus = ZTRUE;
9983
case ScanRecord::WAIT_DELETE_STORED_PROC_ID_SCAN:
9987
/* -------------------------------------------------------------------
9988
* CLOSE IS ALREADY ONGOING. WE NEED NOT DO ANYTHING.
9989
* ------------------------------------------------------------------- */
9990
case ScanRecord::WAIT_RELEASE_LOCK:
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;
9998
case ScanRecord::WAIT_SCAN_NEXTREQ:
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;
10006
fragptr.i = tcConnectptr.p->fragmentptr;
10007
c_fragment_pool.getPtr(fragptr);
10009
if (scanptr.p->scanLockHold == ZTRUE) {
10010
if (scanptr.p->m_curr_batch_size_rows > 0) {
10012
scanptr.p->scanReleaseCounter = 1;
10013
scanReleaseLocksLab(signal);
10017
closeScanLab(signal);
10023
case TcConnectionrec::WAIT_SCAN_AI:
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);
10032
case TcConnectionrec::SCAN_TUPKEY:
10033
case TcConnectionrec::SCAN_FIRST_STOPPED:
10034
case TcConnectionrec::SCAN_CHECK_STOPPED:
10035
case TcConnectionrec::SCAN_STOPPED:
10037
/* ---------------------------------------------------------------------
10038
* SET COMPLETION STATUS AND WAIT FOR OPPORTUNITY TO STOP THE SCAN.
10039
* --------------------------------------------------------------------- */
10040
scanptr.p->scanCompletedStatus = ZTRUE;
10042
case TcConnectionrec::SCAN_RELEASE_STOPPED:
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;
10050
case TcConnectionrec::SCAN_CLOSE_STOPPED:
10052
/* ---------------------------------------------------------------------
10053
* CLOSE IS ALREADY ONGOING. WE NEED NOT DO ANYTHING.
10054
* --------------------------------------------------------------------- */
10060
}//Dblqh::closeScanRequestLab()
10062
/* -------------------------------------------------------------------------
10063
* ENTER NEXT_SCANCONF
10064
* -------------------------------------------------------------------------
10065
* PRECONDITION: SCAN_STATE = WAIT_RELEASE_LOCK
10066
* ------------------------------------------------------------------------- */
10067
void Dblqh::scanLockReleasedLab(Signal* signal)
10069
tcConnectptr.i = scanptr.p->scanTcrec;
10070
ptrCheckGuard(tcConnectptr, ctcConnectrecFileSize, tcConnectionrec);
10072
check_send_scan_hb_rep(signal, scanptr.p, tcConnectptr.p);
10074
if (scanptr.p->scanReleaseCounter == scanptr.p->m_curr_batch_size_rows) {
10075
if ((scanptr.p->scanErrorCounter > 0) ||
10076
(scanptr.p->scanCompletedStatus == ZTRUE)) {
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) {
10083
closeScanLab(signal);
10085
} else if (scanptr.p->check_scan_batch_completed() &&
10086
scanptr.p->scanLockHold != ZTRUE) {
10088
scanptr.p->scanState = ScanRecord::WAIT_SCAN_NEXTREQ;
10089
sendScanFragConf(signal, ZFALSE);
10093
* We came here after releasing locks after
10094
* receiving SCAN_NEXTREQ from TC. We only come here
10095
* when scanHoldLock == ZTRUE
10097
scanptr.p->m_curr_batch_size_rows = 0;
10098
scanptr.p->m_curr_batch_size_bytes = 0;
10099
continueScanNextReqLab(signal);
10101
} else if (scanptr.p->scanReleaseCounter < scanptr.p->m_curr_batch_size_rows) {
10103
scanptr.p->scanReleaseCounter++;
10104
scanReleaseLocksLab(signal);
10106
else if (scanptr.p->scanCompletedStatus != ZTRUE)
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
10115
scanptr.p->scanState = ScanRecord::WAIT_SCAN_NEXTREQ;
10116
sendScanFragConf(signal, ZFALSE);
10121
closeScanLab(signal);
10123
}//Dblqh::scanLockReleasedLab()
10126
Dblqh::seize_acc_ptr_list(ScanRecord* scanP,
10127
Uint32 curr_batch_size,
10128
Uint32 new_batch_size)
10130
/* 1 maps to 0 segments
10131
* >1 maps to enough segments to store
10133
Uint32 segments= (new_batch_size + (SectionSegment::DataLength -2 )) /
10134
SectionSegment::DataLength;
10136
if (segments <= scanP->scan_acc_segments)
10138
// No need to allocate more segments.
10142
if (new_batch_size > 1)
10144
for (Uint32 i = 1 + scanP->scan_acc_segments; i <= segments; i++)
10146
Uint32 seg= seizeSegment();
10147
if (unlikely(seg == RNIL))
10150
/* Cleanup any allocated segments and return */
10151
scanP->scan_acc_segments= (i-1);
10152
release_acc_ptr_list(scanP);
10155
scanP->scan_acc_op_ptr[i]= seg;
10158
scanP->scan_acc_segments= segments;
10163
Dblqh::release_acc_ptr_list(ScanRecord* scanP)
10165
Uint32 i, segments;
10166
segments= scanP->scan_acc_segments;
10168
for (i= 1; i <= segments; i++) {
10169
releaseSection(scanP->scan_acc_op_ptr[i]);
10171
scanP->scan_acc_segments= 0;
10172
scanP->scan_acc_index = 0;
10176
Dblqh::seizeSegment()
10181
/* Rather grungy way to grab a segment */
10182
if (!appendToSection(iVal, &junk, 1))
10189
Dblqh::init_acc_ptr_list(ScanRecord* scanP)
10191
scanP->scan_acc_index = 0;
10195
Dblqh::get_acc_ptr_from_scan_record(ScanRecord* scanP,
10200
if (!((index < MAX_PARALLEL_OP_PER_SCAN) &&
10201
index < scanP->scan_acc_index)) {
10202
ndbrequire(crash_flag);
10205
i_get_acc_ptr(scanP, acc_ptr, index);
10210
Dblqh::set_acc_ptr_in_scan_record(ScanRecord* scanP,
10211
Uint32 index, Uint32 acc)
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);
10221
/* -------------------------------------------------------------------------
10222
* SCAN_FRAGREQ: Request to start scanning the specified fragment of a table.
10223
* ------------------------------------------------------------------------- */
10224
void Dblqh::execSCAN_FRAGREQ(Signal* signal)
10228
/* Reassemble if the request was fragmented */
10229
if (!assembleFragments(signal)){
10234
ScanFragReq * const scanFragReq = (ScanFragReq *)&signal->theData[0];
10236
const Uint32 transid1 = scanFragReq->transId1;
10237
const Uint32 transid2 = scanFragReq->transId2;
10238
Uint32 errorCode= 0;
10241
TcConnectionrecPtr nextHashptr;
10242
Uint32 senderHi = signal->getSendersBlockRef();
10244
const Uint32 reqinfo = scanFragReq->requestInfo;
10246
/* Short SCANFRAGREQ has no sections, Long SCANFRAGREQ has 1 or 2
10247
* Section 0 : Mandatory ATTRINFO section
10248
* Section 1 : Optional KEYINFO section
10250
const Uint32 numSections= signal->getNoOfSections();
10251
bool isLongReq= ( numSections != 0 );
10253
SectionHandle handle(this, signal);
10255
SegmentedSectionPtr attrInfoPtr, keyInfoPtr;
10259
if (likely(isLongReq))
10261
/* Long request, get Attr + Key len from section sizes */
10262
handle.getSection(attrInfoPtr, ScanFragReq::AttrInfoSectionNum);
10263
aiLen= attrInfoPtr.sz;
10265
if (numSections == 2)
10267
handle.getSection(keyInfoPtr, ScanFragReq::KeyInfoSectionNum);
10268
keyLen= keyInfoPtr.sz;
10273
/* Short request, get Attr + Key len from signal */
10274
aiLen= ScanFragReq::getAttrLen(reqinfo);
10275
keyLen= (scanFragReq->fragmentNoKeyLen >> 16);
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);
10285
ptrCheckGuard(tabptr, ctabrecFileSize, tablerec);
10286
if (tabptr.p->tableStatus != Tablerec::TABLE_DEFINED &&
10287
tabptr.p->tableStatus != Tablerec::TABLE_READ_ONLY)
10289
senderData = scanFragReq->senderData;
10290
goto error_handler_early_1;
10293
if (cfirstfreeTcConrec != RNIL && !ERROR_INSERTED_CLEAR(5055)) {
10295
tcConnectptr.p->clientConnectrec = scanFragReq->senderData;
10296
tcConnectptr.p->clientBlockref = signal->senderBlockRef();
10297
tcConnectptr.p->savePointId = scanFragReq->savePointId;
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;
10308
* A write always has to get keyinfo
10310
ndbrequire(scanLockMode == 0 || keyinfo);
10312
ndbrequire(max_rows > 0 && max_rows <= MAX_PARALLEL_OP_PER_SCAN);
10313
if (!getFragmentrec(signal, fragId)) {
10315
goto error_handler;
10318
// Verify scan type vs table type (both sides are boolean)
10319
if (rangeScan != DictTabInfo::isOrderedIndex(fragptr.p->tableType)) {
10321
goto error_handler;
10324
// XXX adjust cmaxAccOps for range scans and remove this comment
10325
if ((cbookedAccOps + max_rows) > cmaxAccOps) {
10327
errorCode = ScanFragRef::ZSCAN_BOOK_ACC_OP_ERROR;
10328
goto error_handler;
10331
if (ScanFragReq::getLcpScanFlag(reqinfo))
10334
ndbrequire(m_reserved_scans.first(scanptr));
10335
m_reserved_scans.remove(scanptr);
10337
else if (!c_scanRecordPool.seize(scanptr))
10340
errorCode = ScanFragRef::ZNO_FREE_SCANREC_ERROR;
10341
goto error_handler;
10344
initScanTc(scanFragReq,
10350
tcConnectptr.p->save1 = 0;
10351
tcConnectptr.p->primKeyLen = keyLen;
10352
tcConnectptr.p->applRef = scanFragReq->resultRef;
10353
if (likely(isLongReq))
10355
tcConnectptr.p->attrInfoIVal= attrInfoPtr.i;
10357
tcConnectptr.p->keyInfoIVal= keyInfoPtr.i;
10358
/* Scan state machine is now responsible for freeing
10359
* these sections, usually via releaseOprec()
10364
if (ScanFragReq::getCorrFactorFlag(reqinfo))
10367
* Correlattion factor for SPJ
10369
tcConnectptr.p->m_corrFactorLo = scanFragReq->variableData[0];
10370
tcConnectptr.p->m_corrFactorHi = scanFragReq->variableData[1];
10373
errorCode = initScanrec(scanFragReq, aiLen);
10374
if (errorCode != ZOK) {
10376
goto error_handler2;
10378
cbookedAccOps += max_rows;
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) {
10387
/* ---------------------------------------------------------------------
10388
* ENSURE THAT THE NEXT RECORD HAS SET PREVIOUS TO OUR RECORD
10390
* --------------------------------------------------------------------- */
10391
ptrCheckGuard(nextHashptr, ctcConnectrecFileSize, tcConnectionrec);
10392
nextHashptr.p->prevHashRec = tcConnectptr.i;
10394
if ((! isLongReq ) &&
10395
( scanptr.p->scanAiLength > 0 )) {
10397
tcConnectptr.p->transactionState = TcConnectionrec::WAIT_SCAN_AI;
10400
continueAfterReceivingAllAiLab(signal);
10404
// no scan number allocated
10405
if (scanptr.p->m_reserved == 0)
10408
c_scanRecordPool.release(scanptr);
10413
m_reserved_scans.add(scanptr);
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);
10430
error_handler_early_1:
10431
errorCode = get_table_state_error(tabptr);
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()
10444
void Dblqh::continueAfterReceivingAllAiLab(Signal* signal)
10446
tcConnectptr.p->transactionState = TcConnectionrec::SCAN_STATE_USED;
10448
if(scanptr.p->scanState == ScanRecord::IN_QUEUE){
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);
10465
if (refToMain(tcConnectptr.p->clientBlockref) == BACKUP)
10467
if (scanptr.p->lcpScan)
10469
AccScanReq::setNoDiskScanFlag(req->requestInfo, 1);
10470
AccScanReq::setLcpScanFlag(req->requestInfo, 1);
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);
10482
#if BUG_27776_FIXED
10483
AccScanReq::setNoDiskScanFlag(req->requestInfo,
10484
!tcConnectptr.p->m_disk_table);
10486
AccScanReq::setNoDiskScanFlag(req->requestInfo, 1);
10488
AccScanReq::setLcpScanFlag(req->requestInfo, 0);
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()
10498
void Dblqh::scanAttrinfoLab(Signal* signal, Uint32* dataPtr, Uint32 length)
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) {
10507
ndbrequire(tcConnectptr.p->currTupAiLen == scanptr.p->scanAiLength);
10508
continueAfterReceivingAllAiLab(signal);
10512
abort_scan(signal, scanptr.i, ZGET_ATTRINBUF_ERROR);
10515
void Dblqh::abort_scan(Signal* signal, Uint32 scan_ptr_i, Uint32 errcode){
10517
scanptr.i = scan_ptr_i;
10518
c_scanRecordPool.getPtr(scanptr);
10520
tcConnectptr.p->errorCode = errcode;
10521
tupScanCloseConfLab(signal);
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
/*---------------------------------------------------------------------*/
10531
Dblqh::check_send_scan_hb_rep(Signal* signal,
10532
ScanRecord* scanPtrP,
10533
TcConnectionrec* tcPtrP)
10535
switch(scanPtrP->scanType){
10536
case ScanRecord::SCAN:
10538
case ScanRecord::COPY:
10541
case ScanRecord::ST_IDLE:
10545
case ScanRecord::ST_IDLE:
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;
10556
now >= ((10 * last + limit) / 10) || now < last; // wrap
10562
scanPtrP->scanTcWaiting = Uint32(now);
10563
if (tcPtrP->tcTimer != 0)
10565
tcPtrP->tcTimer = Uint32(now);
10569
save[0] = signal->theData[0];
10570
save[1] = signal->theData[1];
10571
save[2] = signal->theData[2];
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);
10579
signal->theData[0] = save[0];
10580
signal->theData[1] = save[1];
10581
signal->theData[2] = save[2];
10585
void Dblqh::accScanConfScanLab(Signal* signal)
10587
AccScanConf * const accScanConf = (AccScanConf *)&signal->theData[0];
10588
tcConnectptr.i = scanptr.p->scanTcrec;
10589
ptrCheckGuard(tcConnectptr, ctcConnectrecFileSize, tcConnectionrec);
10591
/* -----------------------------------------------------------------------
10592
* PRECONDITION: SCAN_STATE = WAIT_ACC_SCAN
10593
* ----------------------------------------------------------------------- */
10594
if (accScanConf->flag == AccScanConf::ZEMPTY_FRAGMENT) {
10596
/* ---------------------------------------------------------------------
10597
* THE FRAGMENT WAS EMPTY.
10598
* REPORT SUCCESSFUL COPYING.
10599
* --------------------------------------------------------------------- */
10601
* MRR scan + delete can hit this when the fragment was not
10602
* initially empty, but has become empty after previous range.
10604
if (scanptr.p->scanStoredProcId != RNIL) {
10606
scanptr.p->scanCompletedStatus = ZTRUE;
10607
accScanCloseConfLab(signal);
10610
tupScanCloseConfLab(signal);
10614
check_send_scan_hb_rep(signal, scanptr.p, tcConnectptr.p);
10616
scanptr.p->scanAccPtr = accScanConf->accPtr;
10617
if (scanptr.p->rangeScan) {
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);
10628
if (req->errorCode != 0) {
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.
10635
tcConnectptr.p->errorCode = req->errorCode;
10639
scanptr.p->scanState = ScanRecord::WAIT_STORED_PROC_SCAN;
10640
if(scanptr.p->scanStoredProcId == RNIL)
10643
/* Send AttrInfo to TUP to store as 'stored procedure'
10644
* and get storedProcId back for future reference
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;
10653
/* Pass ATTRINFO as long section, we don't need
10656
SectionHandle handle(this);
10657
handle.m_ptr[0].i= tcConnectptr.p->attrInfoIVal;
10659
tcConnectptr.p->attrInfoIVal= RNIL;
10660
getSections(handle.m_cnt, handle.m_ptr);
10662
sendSignal(tcConnectptr.p->tcTupBlockref,
10663
GSN_STORED_PROCREQ, signal, 6, JBB,
10668
/* TUP already has the Stored procedure, continue */
10670
storedProcConfScanLab(signal);
10672
}//Dblqh::accScanConfScanLab()
10675
Dblqh::copyNextRange(Uint32 * dst, TcConnectionrec* tcPtrP)
10678
* Copy the bound info for the next range from the KeyInfo
10680
* There may be zero or more bounds
10681
* A SectionReader is used to read bound information, its
10682
* position is saved between calls
10683
* This method also extracts range numbers from the
10686
Uint32 totalLen = tcPtrP->primKeyLen;
10690
ndbassert( tcPtrP->keyInfoIVal != RNIL );
10691
SectionReader keyInfoReader(tcPtrP->keyInfoIVal,
10692
g_sectionSegmentPool);
10694
if (tcPtrP->m_flags & TcConnectionrec::OP_SCANKEYINFOPOSSAVED)
10696
/* Second or higher range in an MRR scan
10697
* Restore SectionReader to the last position it was in
10699
bool ok= keyInfoReader.setPos(tcPtrP->scanKeyInfoPos);
10703
/* Get first word of next range and extract range
10704
* length, number from it.
10705
* For non MRR, these will be zero.
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
10716
/* Write range info to dst */
10717
*(dst++)= firstWord;
10718
bool ok= keyInfoReader.getWords(dst, rangeLen - 1);
10722
tcPtrP->primKeyLen-= rangeLen;
10724
if (rangeLen == totalLen)
10726
/* All range information has been copied, free the section */
10727
releaseSection(tcPtrP->keyInfoIVal);
10728
tcPtrP->keyInfoIVal= RNIL;
10732
/* Save position of SectionReader for next range (if any) */
10733
tcPtrP->scanKeyInfoPos= keyInfoReader.getPos();
10734
tcPtrP->m_flags|= TcConnectionrec::OP_SCANKEYINFOPOSSAVED;
10743
/* -------------------------------------------------------------------------
10744
* ENTER STORED_PROCCONF WITH
10747
* -------------------------------------------------------------------------
10748
* PRECONDITION: SCAN_STATE = WAIT_STORED_PROC_SCAN
10749
* ------------------------------------------------------------------------- */
10750
void Dblqh::storedProcConfScanLab(Signal* signal)
10752
fragptr.i = tcConnectptr.p->fragmentptr;
10753
c_fragment_pool.getPtr(fragptr);
10754
if (scanptr.p->scanCompletedStatus == ZTRUE) {
10756
// STOP THE SCAN PROCESS IF THIS HAS BEEN REQUESTED.
10757
closeScanLab(signal);
10760
switch (fragptr.p->fragStatus) {
10761
case Fragrecord::FSACTIVE:
10764
case Fragrecord::BLOCKED:
10766
linkFragQueue(signal);
10767
tcConnectptr.p->transactionState = TcConnectionrec::SCAN_FIRST_STOPPED;
10770
case Fragrecord::FREE:
10772
case Fragrecord::ACTIVE_CREATION:
10774
case Fragrecord::CRASH_RECOVERING:
10776
case Fragrecord::DEFINED:
10778
case Fragrecord::REMOVING:
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
10788
continueFirstScanAfterBlockedLab(signal);
10789
}//Dblqh::storedProcConfScanLab()
10791
void Dblqh::continueFirstScanAfterBlockedLab(Signal* signal)
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);
10801
}//Dblqh::continueFirstScanAfterBlockedLab()
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)
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;
10816
c_fragment_pool.getPtr(fragptr);
10817
if (signal->theData[1] == ZTRUE) {
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;
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;
10831
}//Dblqh::execCHECK_LCP_STOP()
10833
void Dblqh::checkLcpStopBlockedLab(Signal* signal)
10835
switch (fragptr.p->fragStatus) {
10836
case Fragrecord::FSACTIVE:
10838
continueAfterCheckLcpStopBlocked(signal);
10840
case Fragrecord::BLOCKED:
10842
linkFragQueue(signal);
10843
tcConnectptr.p->transactionState = TcConnectionrec::SCAN_CHECK_STOPPED;
10846
case Fragrecord::FREE:
10848
case Fragrecord::ACTIVE_CREATION:
10850
case Fragrecord::CRASH_RECOVERING:
10852
case Fragrecord::DEFINED:
10854
case Fragrecord::REMOVING:
10859
}//Dblqh::checkLcpStopBlockedLab()
10861
void Dblqh::continueAfterCheckLcpStopBlocked(Signal* signal)
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,
10869
}//Dblqh::continueAfterCheckLcpStopBlocked()
10871
/* -------------------------------------------------------------------------
10872
* ENTER NEXT_SCANCONF
10873
* -------------------------------------------------------------------------
10874
* PRECONDITION: SCAN_STATE = WAIT_NEXT_SCAN
10875
* ------------------------------------------------------------------------- */
10876
void Dblqh::nextScanConfScanLab(Signal* signal)
10878
NextScanConf * const nextScanConf = (NextScanConf *)&signal->theData[0];
10879
tcConnectptr.i = scanptr.p->scanTcrec;
10880
ptrCheckGuard(tcConnectptr, ctcConnectrecFileSize, tcConnectionrec);
10882
if (nextScanConf->fragId == RNIL) {
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)
10897
closeScanLab(signal);
10901
if (scanptr.p->scanCompletedStatus == ZTRUE) {
10902
if ((scanptr.p->scanLockHold == ZTRUE) &&
10903
(scanptr.p->m_curr_batch_size_rows > 0)) {
10905
scanptr.p->scanReleaseCounter = 1;
10906
scanReleaseLocksLab(signal);
10910
closeScanLab(signal);
10914
if (scanptr.p->m_curr_batch_size_rows > 0) {
10917
if((tcConnectptr.p->primKeyLen) == 0)
10918
scanptr.p->scanCompletedStatus = ZTRUE;
10920
scanptr.p->scanState = ScanRecord::WAIT_SCAN_NEXTREQ;
10921
sendScanFragConf(signal, ZFALSE);
10924
closeScanLab(signal);
10928
// If accOperationPtr == RNIL no record was returned by ACC
10929
Uint32 accOpPtr = nextScanConf->accOperationPtr;
10930
if (accOpPtr == RNIL)
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)) {
10940
scanptr.p->scanReleaseCounter = 1;
10941
scanReleaseLocksLab(signal);
10945
closeScanLab(signal);
10949
if (scanptr.p->m_curr_batch_size_rows > 0) {
10951
scanptr.p->scanState = ScanRecord::WAIT_SCAN_NEXTREQ;
10952
sendScanFragConf(signal, ZFALSE);
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);
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,
10970
nextScanConfLoopLab(signal);
10971
}//Dblqh::nextScanConfScanLab()
10973
void Dblqh::nextScanConfLoopLab(Signal* signal)
10975
/* ----------------------------------------------------------------------
10976
* STOP THE SCAN PROCESS IF THIS HAS BEEN REQUESTED.
10977
* ---------------------------------------------------------------------- */
10978
if (scanptr.p->scanCompletedStatus == ZTRUE) {
10980
if ((scanptr.p->scanLockHold == ZTRUE) &&
10981
(scanptr.p->m_curr_batch_size_rows > 0)) {
10983
scanptr.p->scanReleaseCounter = 1;
10984
scanReleaseLocksLab(signal);
10987
closeScanLab(signal);
10991
Fragrecord* fragPtrP= fragptr.p;
10992
if (scanptr.p->rangeScan) {
10994
// for ordered index use primary table
10995
fragPtrP= c_fragment_pool.getPtr(fragPtrP->tableFragptr);
10998
tcConnectptr.p->transactionState = TcConnectionrec::SCAN_TUPKEY;
10999
if(tcConnectptr.p->m_disk_table)
11001
next_scanconf_load_diskpage(signal, scanptr, tcConnectptr,fragPtrP);
11005
next_scanconf_tupkeyreq(signal, scanptr, tcConnectptr.p, fragPtrP, RNIL);
11010
Dblqh::next_scanconf_load_diskpage(Signal* signal,
11011
ScanRecordPtr scanPtr,
11012
Ptr<TcConnectionrec> regTcPtr,
11013
Fragrecord* fragPtrP)
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,
11026
next_scanconf_tupkeyreq(signal, scanptr, regTcPtr.p, fragPtrP, res);
11028
else if(unlikely(res != 0))
11031
TupKeyRef * ref = (TupKeyRef *)signal->getDataPtr();
11032
ref->userRef= regTcPtr.i;
11033
ref->errorCode= ~0;
11034
execTUPKEYREF(signal);
11039
Dblqh::next_scanconf_load_diskpage_callback(Signal* signal,
11040
Uint32 callbackData,
11045
Ptr<TcConnectionrec> regTcPtr;
11046
regTcPtr.i= callbackData;
11047
ptrCheckGuard(regTcPtr, ctcConnectrecFileSize, tcConnectionrec);
11049
ScanRecordPtr scanPtr;
11050
c_scanRecordPool.getPtr(scanPtr, regTcPtr.p->tcScanRec);
11054
FragrecordPtr fragPtr;
11055
c_fragment_pool.getPtr(fragPtr, regTcPtr.p->fragmentptr);
11057
if (scanPtr.p->rangeScan) {
11059
// for ordered index use primary table
11060
fragPtr.p = c_fragment_pool.getPtr(fragPtr.p->tableFragptr);
11063
next_scanconf_tupkeyreq(signal, scanPtr, regTcPtr.p, fragPtr.p, disk_page);
11067
TupKeyRef * ref = (TupKeyRef *)signal->getDataPtr();
11068
ref->userRef= callbackData;
11069
ref->errorCode= disk_page;
11070
execTUPKEYREF(signal);
11075
Dblqh::next_scanconf_tupkeyreq(Signal* signal,
11076
Ptr<ScanRecord> scanPtr,
11077
TcConnectionrec * regTcPtr,
11078
Fragrecord* fragPtrP,
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);
11087
TupKeyReq * const tupKeyReq = (TupKeyReq *)signal->getDataPtrSend();
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);
11112
/* -------------------------------------------------------------------------
11113
* STORE KEYINFO IN A LONG SECTION PRIOR TO SENDING
11114
* -------------------------------------------------------------------------
11115
* PRECONDITION: SCAN_STATE = WAIT_SCAN_KEYINFO
11116
* ------------------------------------------------------------------------- */
11118
Dblqh::keyinfoLab(const Uint32 * src, Uint32 len)
11120
ndbassert( tcConnectptr.p->keyInfoIVal == RNIL );
11121
ndbassert( len > 0 );
11123
if (ERROR_INSERTED(5052) || ERROR_INSERTED_CLEAR(5060))
11126
return(appendToSection(tcConnectptr.p->keyInfoIVal,
11129
}//Dblqh::keyinfoLab()
11132
Dblqh::readPrimaryKeys(ScanRecord *scanP, TcConnectionrec *tcConP, Uint32 *dst)
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;
11139
if(scanP->rangeScan)
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;
11149
int ret = c_tup->accReadPk(tableId, fragId, fragPageId, pageIndex, dst, false);
11152
ndbout_c("readPrimaryKeys(table: %d fragment: %d [ %d %d ] -> %d",
11153
tableId, fragId, fragPageId, pageIndex, ret);
11154
ndbassert(ret > 0);
11159
/* -------------------------------------------------------------------------
11161
* -------------------------------------------------------------------------
11162
* PRECONDITION: TRANSACTION_STATE = SCAN_TUPKEY
11163
* ------------------------------------------------------------------------- */
11164
void Dblqh::scanTupkeyConfLab(Signal* signal)
11166
const TupKeyConf * conf = (TupKeyConf *)signal->getDataPtr();
11167
UintR tdata4 = conf->readLength;
11168
UintR tdata5 = conf->lastRow;
11170
tcConnectptr.p->transactionState = TcConnectionrec::SCAN_STATE_USED;
11171
scanptr.i = tcConnectptr.p->tcScanRec;
11172
c_scanRecordPool.getPtr(scanptr);
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)
11178
c_acc->execACCKEY_ORD(signal, accOpPtr);
11183
ndbassert(refToBlock(scanptr.p->scanBlockref) != DBACC);
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)
11193
scanptr.p->scanReleaseCounter = 1;
11194
scanReleaseLocksLab(signal);
11198
closeScanLab(signal);
11201
if (scanptr.p->scanKeyinfoFlag) {
11203
// Inform API about keyinfo len aswell
11204
tdata4 += sendKeyinfo20(signal, scanptr.p, tcConnectptr.p);
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) {
11213
scanptr.p->scanState = ScanRecord::WAIT_SCAN_NEXTREQ;
11214
sendScanFragConf(signal, ZFALSE);
11218
scanptr.p->scanReleaseCounter = rows + 1;
11219
scanReleaseLocksLab(signal);
11223
if (scanptr.p->scanLockHold == ZTRUE) {
11225
scanptr.p->scanFlag = NextScanReq::ZSCAN_NEXT;
11228
scanptr.p->scanFlag = NextScanReq::ZSCAN_NEXT_COMMIT;
11231
scanNextLoopLab(signal);
11232
}//Dblqh::scanTupkeyConfLab()
11234
void Dblqh::scanNextLoopLab(Signal* signal)
11236
switch (fragptr.p->fragStatus) {
11237
case Fragrecord::FSACTIVE:
11240
case Fragrecord::BLOCKED:
11242
linkFragQueue(signal);
11243
tcConnectptr.p->transactionState = TcConnectionrec::SCAN_STOPPED;
11246
case Fragrecord::FREE:
11248
case Fragrecord::ACTIVE_CREATION:
11250
case Fragrecord::CRASH_RECOVERING:
11252
case Fragrecord::DEFINED:
11254
case Fragrecord::REMOVING:
11259
continueScanAfterBlockedLab(signal);
11260
}//Dblqh::scanNextLoopLab()
11262
void Dblqh::continueScanAfterBlockedLab(Signal* signal)
11264
scanptr.i = tcConnectptr.p->tcScanRec;
11265
c_scanRecordPool.getPtr(scanptr);
11267
if (scanptr.p->scanFlag == NextScanReq::ZSCAN_NEXT_ABORT) {
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,
11273
scanptr.p->scan_acc_index--;
11274
} else if (scanptr.p->scanFlag == NextScanReq::ZSCAN_NEXT_COMMIT) {
11276
accOpPtr= get_acc_ptr_from_scan_record(scanptr.p,
11277
scanptr.p->m_curr_batch_size_rows-1,
11281
accOpPtr = RNIL; // The value is not used in ACC
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()
11290
/* -------------------------------------------------------------------------
11291
* ENTER TUPKEYREF WITH
11294
* -------------------------------------------------------------------------
11295
* PRECONDITION: TRANSACTION_STATE = SCAN_TUPKEY
11296
* ------------------------------------------------------------------------- */
11297
void Dblqh::scanTupkeyRefLab(Signal* signal)
11299
tcConnectptr.p->transactionState = TcConnectionrec::SCAN_STATE_USED;
11300
scanptr.i = tcConnectptr.p->tcScanRec;
11301
c_scanRecordPool.getPtr(scanptr);
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)
11307
c_acc->execACCKEY_ORD(signal, accOpPtr);
11311
ndbassert(refToBlock(scanptr.p->scanBlockref) != DBACC);
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)
11321
scanptr.p->scanReleaseCounter = 1;
11322
scanReleaseLocksLab(signal);
11326
closeScanLab(signal);
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;
11335
if (scanptr.p->scanLockHold == ZTRUE) {
11337
scanptr.p->scanReleaseCounter = 1;
11340
scanptr.p->m_curr_batch_size_rows = rows + 1;
11341
scanptr.p->scanReleaseCounter = rows + 1;
11343
/* --------------------------------------------------------------------
11344
* WE NEED TO RELEASE ALL LOCKS CURRENTLY
11345
* HELD BY THIS SCAN.
11346
* -------------------------------------------------------------------- */
11347
scanReleaseLocksLab(signal);
11350
Uint32 time_passed= tcConnectptr.p->tcTimer - cLqhTimeOutCount;
11353
if (time_passed > 1)
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);
11367
scanptr.p->scanFlag = NextScanReq::ZSCAN_NEXT_ABORT;
11368
scanNextLoopLab(signal);
11369
}//Dblqh::scanTupkeyRefLab()
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)
11377
fragptr.i = tcConnectptr.p->fragmentptr;
11378
c_fragment_pool.getPtr(fragptr);
11379
switch (fragptr.p->fragStatus) {
11380
case Fragrecord::FSACTIVE:
11383
case Fragrecord::BLOCKED:
11385
linkFragQueue(signal);
11386
tcConnectptr.p->transactionState = TcConnectionrec::SCAN_CLOSE_STOPPED;
11389
case Fragrecord::FREE:
11391
case Fragrecord::ACTIVE_CREATION:
11393
case Fragrecord::CRASH_RECOVERING:
11395
case Fragrecord::DEFINED:
11397
case Fragrecord::REMOVING:
11402
continueCloseScanAfterBlockedLab(signal);
11403
}//Dblqh::closeScanLab()
11405
void Dblqh::continueCloseScanAfterBlockedLab(Signal* signal)
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()
11417
/* -------------------------------------------------------------------------
11418
* ENTER NEXT_SCANCONF
11419
* -------------------------------------------------------------------------
11420
* PRECONDITION: SCAN_STATE = WAIT_CLOSE_SCAN
11421
* ------------------------------------------------------------------------- */
11422
void Dblqh::accScanCloseConfLab(Signal* signal)
11424
tcConnectptr.i = scanptr.p->scanTcrec;
11425
ptrCheckGuard(tcConnectptr, ctcConnectrecFileSize, tcConnectionrec);
11427
/* Do we have another range to scan? */
11428
if((tcConnectptr.p->primKeyLen > 0) &&
11429
(scanptr.p->scanCompletedStatus != ZTRUE))
11432
/* Start next range scan...*/
11433
continueAfterReceivingAllAiLab(signal);
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()
11448
/* -------------------------------------------------------------------------
11449
* ENTER STORED_PROCCONF WITH
11450
* -------------------------------------------------------------------------
11451
* PRECONDITION: SCAN_STATE = WAIT_DELETE_STORED_PROC_ID_SCAN
11452
* ------------------------------------------------------------------------- */
11453
void Dblqh::tupScanCloseConfLab(Signal* signal)
11455
fragptr.i = tcConnectptr.p->fragmentptr;
11456
c_fragment_pool.getPtr(fragptr);
11457
if (tcConnectptr.p->abortState == TcConnectionrec::NEW_FROM_TC) {
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) {
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);
11476
sendScanFragConf(signal, ZSCAN_FRAG_CLOSED);
11478
finishScanrec(signal);
11479
releaseScanrec(signal);
11480
tcConnectptr.p->tcScanRec = RNIL;
11481
deleteTransidHash(signal);
11482
releaseOprec(signal);
11483
releaseTcrec(signal, tcConnectptr);
11484
}//Dblqh::tupScanCloseConfLab()
11486
/* =========================================================================
11487
* ======= INITIATE SCAN RECORD =======
11489
* SUBROUTINE SHORT NAME = ISC
11490
* ========================================================================= */
11491
Uint32 Dblqh::initScanrec(const ScanFragReq* scanFragReq,
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);
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;
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;
11522
scanptr.p->scanBlockref = tcConnectptr.p->tcAccBlockref;
11523
else if (! tupScan)
11524
scanptr.p->scanBlockref = tcConnectptr.p->tcTuxBlockref;
11526
scanptr.p->scanBlockref = tcConnectptr.p->tcTupBlockref;
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)){
11547
return ScanFragRef::ZWRONG_BATCH_SIZE;
11550
if (ERROR_INSERTED(5057))
11552
CLEAR_ERROR_INSERT_VALUE;
11553
return ScanFragRef::ZTOO_MANY_ACTIVE_SCAN_ERROR;
11556
scanptr.p->scan_acc_segments = 0;
11557
if (!seize_acc_ptr_list(scanptr.p, 0, max_rows)){
11559
return ScanFragRef::ZTOO_MANY_ACTIVE_SCAN_ERROR;
11561
init_acc_ptr_list(scanptr.p);
11564
* Used for scan take over
11566
FragrecordPtr tFragPtr;
11567
tFragPtr.i = fragptr.p->tableFragptr;
11568
c_fragment_pool.getPtr(tFragPtr);
11569
scanptr.p->fragPtrI = fragptr.p->tableFragptr;
11572
* !idx uses 1 - (MAX_PARALLEL_SCANS_PER_FRAG - 1) = 1-11
11573
* idx uses from MAX_PARALLEL_SCANS_PER_FRAG - MAX = 12-42)
11577
* ACC only supports 12 parallel scans per fragment (hard limit)
11578
* TUP/TUX does not have any such limit...but when scanning with keyinfo
11579
* (for take-over) no more than 255 such scans can be active
11580
* at a fragment (dur to 8 bit number in scan-keyinfo protocol)
11582
* TODO: Make TUP/TUX limits depend on scanKeyinfoFlag (possibly with
11583
* other config limit too)
11586
Uint32 start, stop;
11587
Uint32 max_parallel_scans_per_frag = c_max_parallel_scans_per_frag;
11591
stop = MAX_PARALLEL_SCANS_PER_FRAG - 1;
11593
else if (rangeScan)
11595
start = MAX_PARALLEL_SCANS_PER_FRAG;
11596
stop = start + max_parallel_scans_per_frag - 1;
11600
ndbassert(tupScan);
11601
start = MAX_PARALLEL_SCANS_PER_FRAG + max_parallel_scans_per_frag;
11602
stop = start + max_parallel_scans_per_frag - 1;
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);
11608
if(free == Fragrecord::ScanNumberMask::NotFound || free >= stop){
11613
return ScanFragRef::ZTOO_MANY_ACTIVE_SCAN_ERROR;
11619
scanptr.p->scanState = ScanRecord::IN_QUEUE;
11620
LocalDLFifoList<ScanRecord> queue(c_scanRecordPool,
11622
fragptr.p->m_queuedScans :
11623
fragptr.p->m_queuedTupScans);
11624
queue.add(scanptr);
11628
scanptr.p->scanNumber = free;
11629
tFragPtr.p->m_scanNumberMask.clear(free);// Update mask
11631
LocalDLList<ScanRecord> active(c_scanRecordPool, fragptr.p->m_activeScans);
11632
active.add(scanptr);
11633
if(scanptr.p->scanKeyinfoFlag){
11635
#if defined VM_TRACE || defined ERROR_INSERT
11637
ndbrequire(!c_scanTakeOverHash.find(tmp, * scanptr.p));
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);
11645
c_scanTakeOverHash.add(scanptr);
11650
/* =========================================================================
11651
* ======= INITIATE TC RECORD AT SCAN =======
11653
* SUBROUTINE SHORT NAME = IST
11654
* ========================================================================= */
11655
void Dblqh::initScanTc(const ScanFragReq* req,
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;
11695
tabptr.p->usageCountR++;
11696
}//Dblqh::initScanTc()
11698
/* =========================================================================
11699
* ======= FINISH SCAN RECORD =======
11701
* REMOVE SCAN RECORD FROM PER FRAGMENT LIST.
11702
* ========================================================================= */
11703
void Dblqh::finishScanrec(Signal* signal)
11705
release_acc_ptr_list(scanptr.p);
11707
Uint32 tupScan = scanptr.p->tupScan;
11708
LocalDLFifoList<ScanRecord> queue(c_scanRecordPool,
11710
fragptr.p->m_queuedScans :
11711
fragptr.p->m_queuedTupScans);
11713
if (scanptr.p->scanState == ScanRecord::IN_QUEUE)
11716
if (scanptr.p->m_reserved == 0)
11719
queue.release(scanptr);
11724
queue.remove(scanptr);
11725
m_reserved_scans.add(scanptr);
11731
if(scanptr.p->scanKeyinfoFlag){
11734
#ifdef TRACE_SCAN_TAKEOVER
11735
ndbout_c("removing (%d %d)", scanptr.p->scanNumber, scanptr.p->fragPtrI);
11737
c_scanTakeOverHash.remove(tmp, * scanptr.p);
11738
ndbrequire(tmp.p == scanptr.p);
11741
LocalDLList<ScanRecord> scans(c_scanRecordPool, fragptr.p->m_activeScans);
11742
if (scanptr.p->m_reserved == 0)
11745
scans.release(scanptr);
11750
scans.remove(scanptr);
11751
m_reserved_scans.add(scanptr);
11754
FragrecordPtr tFragPtr;
11755
tFragPtr.i = scanptr.p->fragPtrI;
11756
c_fragment_pool.getPtr(tFragPtr);
11758
const Uint32 scanNumber = scanptr.p->scanNumber;
11759
ndbrequire(!tFragPtr.p->m_scanNumberMask.get(scanNumber));
11760
ScanRecordPtr restart;
11763
* Start on of queued scans
11765
if(scanNumber == NR_ScanNo || !queue.first(restart)){
11767
tFragPtr.p->m_scanNumberMask.set(scanNumber);
11771
if(ERROR_INSERTED(5034)){
11773
tFragPtr.p->m_scanNumberMask.set(scanNumber);
11777
ndbrequire(restart.p->scanState == ScanRecord::IN_QUEUE);
11779
ScanRecordPtr tmpScan = scanptr;
11780
TcConnectionrecPtr tmpTc = tcConnectptr;
11782
tcConnectptr.i = restart.p->scanTcrec;
11783
ptrCheckGuard(tcConnectptr, ctcConnectrecFileSize, tcConnectionrec);
11784
restart.p->scanNumber = scanNumber;
11786
queue.remove(restart);
11787
scans.add(restart);
11788
if(restart.p->scanKeyinfoFlag){
11790
#if defined VM_TRACE || defined ERROR_INSERT
11792
ndbrequire(!c_scanTakeOverHash.find(tmp, * restart.p));
11794
c_scanTakeOverHash.add(restart);
11795
#ifdef TRACE_SCAN_TAKEOVER
11796
ndbout_c("adding-r (%d %d)", restart.p->scanNumber, restart.p->fragPtrI);
11801
* This state is a bit weird, but that what set in initScanRec
11803
restart.p->scanState = ScanRecord::SCAN_FREE;
11804
if(tcConnectptr.p->transactionState == TcConnectionrec::SCAN_STATE_USED)
11807
continueAfterReceivingAllAiLab(signal);
11811
ndbrequire(tcConnectptr.p->transactionState == TcConnectionrec::WAIT_SCAN_AI);
11815
tcConnectptr = tmpTc;
11816
}//Dblqh::finishScanrec()
11818
/* =========================================================================
11819
* ======= RELEASE SCAN RECORD =======
11821
* RELEASE A SCAN RECORD TO THE FREELIST.
11822
* ========================================================================= */
11823
void Dblqh::releaseScanrec(Signal* signal)
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()
11831
/* ------------------------------------------------------------------------
11832
* ------- SEND KEYINFO20 TO API -------
11834
* ------------------------------------------------------------------------ */
11835
Uint32 Dblqh::sendKeyinfo20(Signal* signal,
11836
ScanRecord * scanP,
11837
TcConnectionrec * tcConP)
11839
ndbrequire(scanP->m_curr_batch_size_rows < MAX_PARALLEL_OP_PER_SCAN);
11840
KeyInfo20 * keyInfo = (KeyInfo20 *)&signal->theData[0];
11843
* Note that this code requires signal->theData to be big enough for
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;
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));
11855
const bool longable = true; // TODO is_api && !old_dest;
11857
Uint32 * dst = keyInfo->keyData;
11858
dst += nodeId == getOwnNodeId() ? 0 : KeyInfo20::DataLength;
11862
* currently only SUMA receives KEYINFO20 inside kernel..
11863
* and it's not really interested in the actual keyinfo,
11864
* only the scanInfo_Node...so send only that and avoid
11865
* messing with if's below...
11868
if (refToMain(ref) == SUMA && nodeId == getOwnNodeId())
11874
keyLen = readPrimaryKeys(scanP, tcConP, dst);
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];
11885
Uint32 * src = signal->theData+25;
11886
if(connectedToNode)
11890
if (isNdbMtLqh() && instance() != refToInstance(ref))
11893
nodeId = 0; // prevent execute direct
11895
if (nodeId == getOwnNodeId())
11897
EXECUTE_DIRECT(refToBlock(ref), GSN_KEYINFO20, signal,
11898
KeyInfo20::HeaderLength + keyLen);
11904
if(keyLen <= KeyInfo20::DataLength || !longable) {
11905
while(keyLen > KeyInfo20::DataLength){
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;
11913
MEMCOPY_NO_WORDS(keyInfo->keyData, src, keyLen);
11914
sendSignal(ref, GSN_KEYINFO20, signal,
11915
KeyInfo20::HeaderLength+keyLen, JBB);
11919
LinearSectionPtr ptr[3];
11921
ptr[0].sz = keyLen;
11922
sendSignal(ref, GSN_KEYINFO20, signal, KeyInfo20::HeaderLength,
11929
* If this node does not have a direct connection
11930
* to the receiving node we want to send the signals
11931
* routed via the node that controls this read
11933
Uint32 routeBlockref = tcConP->clientBlockref;
11935
if(keyLen < KeyInfo20::DataLength || !longable){
11938
while (keyLen > (KeyInfo20::DataLength - 1)) {
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;
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);
11954
keyInfo->keyData[0] = ref;
11955
LinearSectionPtr ptr[3];
11957
ptr[0].sz = keyLen;
11958
sendSignal(routeBlockref, GSN_KEYINFO20_R, signal,
11959
KeyInfo20::HeaderLength+1, JBB, ptr, 1);
11963
/* ------------------------------------------------------------------------
11964
* ------- SEND SCAN_FRAGCONF TO TC THAT CONTROLS THE SCAN -------
11966
* ------------------------------------------------------------------------ */
11967
void Dblqh::sendScanFragConf(Signal* signal, Uint32 scanCompleted)
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;
11973
if(ERROR_INSERTED(5037)){
11974
CLEAR_ERROR_INSERT_VALUE;
11977
ScanFragConf * conf = (ScanFragConf*)&signal->theData[0];
11979
NodeId tc_node_id= refToNode(tcConnectptr.p->clientBlockref);
11981
Uint32 trans_id1= tcConnectptr.p->transid[0];
11982
Uint32 trans_id2= tcConnectptr.p->transid[1];
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);
11993
if(!scanptr.p->scanLockHold)
11996
scanptr.p->m_curr_batch_size_rows = 0;
11997
scanptr.p->m_curr_batch_size_bytes= 0;
11999
}//Dblqh::sendScanFragConf()
12001
/* ######################################################################### */
12002
/* ####### NODE RECOVERY MODULE ####### */
12004
/* ######################################################################### */
12005
/*---------------------------------------------------------------------------*/
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
/*---------------------------------------------------------------------------*/
12012
Dblqh::calculateHash(Uint32 tableId, const Uint32* src)
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,
12019
ndbrequire(keyLen);
12021
return md5_hash(Tmp, keyLen);
12022
}//Dblqh::calculateHash()
12025
* PREPARE COPY FRAG REQ
12028
Dblqh::execPREPARE_COPY_FRAG_REQ(Signal* signal)
12031
PrepareCopyFragReq req = *(PrepareCopyFragReq*)signal->getDataPtr();
12033
CRASH_INSERTION(5045);
12035
tabptr.i = req.tableId;
12036
ptrCheckGuard(tabptr, ctabrecFileSize, tablerec);
12038
Uint32 max_page = RNIL;
12040
if (getOwnNodeId() != req.startingNodeId)
12044
* This is currently dead code...
12045
* but is provided so we can impl. a better scan+delete on
12046
* starting node wo/ having to change running node
12048
ndbrequire(getOwnNodeId() == req.copyNodeId);
12049
c_tup->get_frag_info(req.tableId, req.fragId, &max_page);
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);
12065
if (! DictTabInfo::isOrderedIndex(tabptr.p->tableType))
12068
ndbrequire(getFragmentrec(signal, req.fragId));
12073
if (cstartType == NodeState::ST_SYSTEM_RESTART)
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);
12086
fragptr.p->m_copy_started_state = Fragrecord::AC_IGNORED;
12087
fragptr.p->fragStatus = Fragrecord::ACTIVE_CREATION;
12088
fragptr.p->logFlag = Fragrecord::STATE_FALSE;
12090
c_tup->get_frag_info(req.tableId, req.fragId, &max_page);
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);
12105
/* *************************************** */
12106
/* COPY_FRAGREQ: Start copying a fragment */
12107
/* *************************************** */
12108
void Dblqh::execCOPY_FRAGREQ(Signal* signal)
12111
const CopyFragReq * const copyFragReq = (CopyFragReq *)&signal->theData[0];
12112
tabptr.i = copyFragReq->tableId;
12113
ptrCheckGuard(tabptr, ctabrecFileSize, tablerec);
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;
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));
12127
Uint32 checkversion = NDB_VERSION >= MAKE_VERSION(5,1,0) ?
12128
NDBD_UPDATE_FRAG_DIST_KEY_51 : NDBD_UPDATE_FRAG_DIST_KEY_50;
12130
Uint32 nodeCount = copyFragReq->nodeCount;
12131
NdbNodeBitmask nodemask;
12132
if (getNodeInfo(refToNode(userRef)).m_version >= checkversion)
12134
ndbrequire(nodeCount <= MAX_REPLICAS);
12135
for (i = 0; i<nodeCount; i++)
12136
nodemask.set(copyFragReq->nodeList[i]);
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)
12147
if (signal->getLength() < CopyFragReq::SignalLength + nodeCount)
12150
requestInfo = CopyFragReq::CFR_TRANSACTIONAL;
12153
if (requestInfo == CopyFragReq::CFR_NON_TRANSACTIONAL)
12159
fragptr.p->fragDistributionKey = copyFragReq->distributionKey;
12161
Uint32 key = fragptr.p->fragDistributionKey;
12163
if (DictTabInfo::isOrderedIndex(tabptr.p->tableType)) {
12166
* Ordered index doesn't need to be copied
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);
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);
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;
12195
tcConnectptr.p->clientBlockref = userRef;
12198
* Remove implicit cast/usage of CopyFragReq
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;
12222
(DBLQH << 20) + (cownNodeid << 8),
12224
copyFragReq->nodeId,
12226
cactiveCopy[cnoActiveCopy] = fragptr.i;
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;
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;
12245
if (requestInfo == CopyFragReq::CFR_TRANSACTIONAL)
12249
* An node-recovery scan, is shared lock
12250
* and may not perform disk-scan (as it then can miss uncomitted inserts)
12252
AccScanReq::setLockMode(req->requestInfo, 0);
12253
AccScanReq::setReadCommittedFlag(req->requestInfo, 0);
12254
AccScanReq::setNRScanFlag(req->requestInfo, 1);
12255
AccScanReq::setNoDiskScanFlag(req->requestInfo, 1);
12261
* The non-transaction scan is really only a "normal" tup scan
12262
* committed read, and don't disable disk-scan
12264
AccScanReq::setLockMode(req->requestInfo, 0);
12265
AccScanReq::setReadCommittedFlag(req->requestInfo, 1);
12266
scanptr.p->readCommitted = 1;
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);
12276
if (! nodemask.isclear())
12278
ndbrequire(nodemask.get(getOwnNodeId()));
12279
ndbrequire(nodemask.get(nodeId)); // cpy dest
12280
nodemask.clear(getOwnNodeId());
12281
nodemask.clear(nodeId);
12283
UpdateFragDistKeyOrd*
12284
ord = (UpdateFragDistKeyOrd*)signal->getDataPtrSend();
12285
ord->tableId = tabptr.i;
12286
ord->fragId = fragId;
12287
ord->fragDistributionKey = key;
12289
while ((i = nodemask.find(i+1)) != NdbNodeBitmask::NotFound)
12291
if (getNodeInfo(i).m_version >= checkversion)
12292
sendSignal(calcInstanceBlockRef(number(), i),
12293
GSN_UPDATE_FRAG_DIST_KEY_ORD,
12294
signal, UpdateFragDistKeyOrd::SignalLength, JBB);
12298
}//Dblqh::execCOPY_FRAGREQ()
12301
Dblqh::execUPDATE_FRAG_DIST_KEY_ORD(Signal * signal)
12304
UpdateFragDistKeyOrd* ord =(UpdateFragDistKeyOrd*)signal->getDataPtr();
12306
tabptr.i = ord->tableId;
12307
ptrCheckGuard(tabptr, ctabrecFileSize, tablerec);
12308
ndbrequire(getFragmentrec(signal, ord->fragId));
12309
fragptr.p->fragDistributionKey = ord->fragDistributionKey;
12312
void Dblqh::accScanConfCopyLab(Signal* signal)
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) {
12322
/*---------------------------------------------------------------------------*/
12323
/* THE FRAGMENT WAS EMPTY. */
12324
/* REPORT SUCCESSFUL COPYING. */
12325
/*---------------------------------------------------------------------------*/
12326
tupCopyCloseConfLab(signal);
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);
12339
}//Dblqh::accScanConfCopyLab()
12341
/*---------------------------------------------------------------------------*/
12342
/* ENTER STORED_PROCCONF WITH */
12343
/* TC_CONNECTPTR, */
12344
/* TSTORED_PROC_ID */
12345
/*---------------------------------------------------------------------------*/
12346
void Dblqh::storedProcConfCopyLab(Signal* signal)
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) {
12355
/*---------------------------------------------------------------------------*/
12356
/* THE COPY PROCESS HAVE BEEN COMPLETED, MOST LIKELY DUE TO A NODE FAILURE.*/
12357
/*---------------------------------------------------------------------------*/
12358
closeCopyLab(signal);
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:
12368
case Fragrecord::BLOCKED:
12370
linkFragQueue(signal);
12371
tcConnectptr.p->transactionState = TcConnectionrec::COPY_FIRST_STOPPED;
12374
case Fragrecord::FREE:
12376
case Fragrecord::ACTIVE_CREATION:
12378
case Fragrecord::CRASH_RECOVERING:
12380
case Fragrecord::DEFINED:
12382
case Fragrecord::REMOVING:
12386
systemErrorLab(signal, __LINE__);
12390
continueFirstCopyAfterBlockedLab(signal);
12392
}//Dblqh::storedProcConfCopyLab()
12394
void Dblqh::continueFirstCopyAfterBlockedLab(Signal* signal)
12397
* Start sending ROWID for all operations from now on
12399
fragptr.p->m_copy_started_state = Fragrecord::AC_NR_COPY;
12400
if (ERROR_INSERTED(5714))
12402
ndbout_c("Starting copy of tab: %u frag: %u",
12403
fragptr.p->tabRef, fragptr.p->fragId);
12406
scanptr.i = tcConnectptr.p->tcScanRec;
12407
c_scanRecordPool.getPtr(scanptr);
12409
if (false && fragptr.p->tabRef > 4)
12411
ndbout_c("STOPPING COPY X = [ %d %d %d %d ]",
12412
refToBlock(scanptr.p->scanBlockref),
12413
scanptr.p->scanAccPtr, RNIL, NextScanReq::ZSCAN_NEXT);
12416
* RESTART: > DUMP 7020 332 X
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);
12426
}//Dblqh::continueFirstCopyAfterBlockedLab()
12428
/*---------------------------------------------------------------------------*/
12429
/* ENTER NEXT_SCANCONF WITH */
12440
/*---------------------------------------------------------------------------*/
12441
/* PRECONDITION: SCAN_STATE = WAIT_NEXT_SCAN_COPY */
12442
/*---------------------------------------------------------------------------*/
12443
void Dblqh::nextScanConfCopyLab(Signal* signal)
12445
NextScanConf * const nextScanConf = (NextScanConf *)&signal->theData[0];
12446
tcConnectptr.i = scanptr.p->scanTcrec;
12447
ptrCheckGuard(tcConnectptr, ctcConnectrecFileSize, tcConnectionrec);
12448
if (nextScanConf->fragId == RNIL) {
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);
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))
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);
12475
TcConnectionrec * tcConP = tcConnectptr.p;
12477
tcConP->m_use_rowid = true;
12478
tcConP->m_row_id = scanptr.p->m_row_id;
12480
scanptr.p->m_curr_batch_size_rows++;
12482
if (signal->getLength() == NextScanConf::SignalLengthNoKeyInfo)
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;
12491
tcConP->primKeyLen = 0;
12492
tcConP->totSendlenAi = 0;
12493
tcConP->connectState = TcConnectionrec::COPY_CONNECTED;
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
12504
/*---------------------------------------------------------------------------*/
12505
UintR TnoOfWords = 8;
12506
TnoOfWords = TnoOfWords + MAGIC_CONSTANT;
12507
TnoOfWords = TnoOfWords + (TnoOfWords >> 2);
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.
12519
* However efficient this method is rather unsafe in such way that
12520
* it overwrites the transid1 original data.
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);
12535
// If accOperationPtr == RNIL no record was returned by ACC
12536
if (nextScanConf->accOperationPtr == RNIL) {
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);
12544
initCopyTc(signal, ZINSERT);
12545
set_acc_ptr_in_scan_record(scanptr.p, 0, nextScanConf->accOperationPtr);
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)
12552
next_scanconf_load_diskpage(signal, scanptr, tcConnectptr,fragPtrP);
12556
next_scanconf_tupkeyreq(signal, scanptr, tcConP, fragPtrP, RNIL);
12559
}//Dblqh::nextScanConfCopyLab()
12562
/*---------------------------------------------------------------------------*/
12563
/* USED IN COPYING OPERATION TO RECEIVE ATTRINFO FROM TUP. */
12564
/*---------------------------------------------------------------------------*/
12565
/* ************>> */
12567
/* ************>> */
12568
void Dblqh::execTRANSID_AI(Signal* signal)
12571
/* TransID_AI received from local TUP, data is linear inline in
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,
12582
if (unlikely(! ok))
12585
tcConnectptr.p->errorCode = ZGET_ATTRINBUF_ERROR;
12587
}//Dblqh::execTRANSID_AI()
12589
/*--------------------------------------------------------------------------*/
12590
/* ENTER TUPKEYCONF WITH */
12591
/* TC_CONNECTPTR, */
12596
/*--------------------------------------------------------------------------*/
12597
/* PRECONDITION: TRANSACTION_STATE = COPY_TUPKEY */
12598
/*--------------------------------------------------------------------------*/
12599
void Dblqh::copyTupkeyRefLab(Signal* signal)
12601
//const TupKeyRef * tupKeyRef = (TupKeyRef *)signal->getDataPtr();
12603
scanptr.i = tcConnectptr.p->tcScanRec;
12604
c_scanRecordPool.getPtr(scanptr);
12605
ScanRecord* scanP = scanptr.p;
12607
if (scanP->readCommitted == 0)
12610
ndbrequire(false); // Should not be possibe...we read with lock
12616
* Any readCommitted scan, can get 626 if it finds a candidate record
12617
* that is not visible to the scan (i.e uncommitted inserts)
12618
* if scanning with locks (shared/exclusive) this is not visible
12619
* to LQH as lock is taken earlier
12621
ndbrequire(terrorCode == 626);
12624
ndbrequire(scanptr.p->scanState == ScanRecord::WAIT_TUPKEY_COPY);
12625
if (tcConnectptr.p->errorCode != 0)
12628
closeCopyLab(signal);
12632
if (scanptr.p->scanCompletedStatus == ZTRUE)
12635
closeCopyLab(signal);
12639
ndbrequire(tcConnectptr.p->copyCountWords < cmaxWordsAtNodeRec);
12640
scanptr.p->scanState = ScanRecord::WAIT_LQHKEY_COPY;
12641
nextRecordCopy(signal);
12644
void Dblqh::copyTupkeyConfLab(Signal* signal)
12646
const TupKeyConf * const tupKeyConf = (TupKeyConf *)signal->getDataPtr();
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;
12654
if (scanP->readCommitted == 0)
12657
Uint32 accOpPtr= get_acc_ptr_from_scan_record(scanP, 0, false);
12658
ndbassert(accOpPtr != (Uint32)-1);
12659
c_acc->execACCKEY_ORD(signal, accOpPtr);
12662
if (tcConnectptr.p->errorCode != 0) {
12664
closeCopyLab(signal);
12667
if (scanptr.p->scanCompletedStatus == ZTRUE) {
12669
/*---------------------------------------------------------------------------*/
12670
/* THE COPY PROCESS HAVE BEEN CLOSED. MOST LIKELY A NODE FAILURE. */
12671
/*---------------------------------------------------------------------------*/
12672
closeCopyLab(signal);
12675
TcConnectionrec * tcConP = tcConnectptr.p;
12676
tcConnectptr.p->totSendlenAi = readLength;
12677
tcConnectptr.p->connectState = TcConnectionrec::COPY_CONNECTED;
12679
/* Read primary keys from TUP into signal buffer space
12680
* (used to get here via scan keyinfo)
12682
Uint32* tmp = signal->getDataPtrSend()+24;
12683
Uint32 len= tcConnectptr.p->primKeyLen = readPrimaryKeys(scanP, tcConP, tmp);
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)
12690
tcConnectptr.p->hashValue = calculateHash(tableId, tmp);
12694
tcConnectptr.p->hashValue = md5_hash((Uint64*)tmp, len);
12697
// Copy keyinfo into long section for LQHKEYREQ below
12698
if (unlikely(!keyinfoLab(tmp, len)))
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
12704
scanptr.p->scanErrorCounter++;
12705
tcConP->errorCode= ZGET_DATAREC_ERROR;
12706
scanptr.p->scanCompletedStatus= ZTRUE;
12708
closeCopyLab(signal);
12712
LqhKeyReq::setKeyLen(tcConP->reqinfo, len);
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
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);
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.
12739
* However efficient this method is rather unsafe in such way that
12740
* it overwrites the transid1 original data.
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);
12753
}//Dblqh::copyTupkeyConfLab()
12755
/*---------------------------------------------------------------------------*/
12756
/* ENTER LQHKEYCONF */
12757
/*---------------------------------------------------------------------------*/
12758
/* PRECONDITION: CONNECT_STATE = COPY_CONNECTED */
12759
/*---------------------------------------------------------------------------*/
12760
void Dblqh::copyCompletedLab(Signal* signal)
12762
const LqhKeyConf * const lqhKeyConf = (LqhKeyConf *)signal->getDataPtr();
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) {
12771
/*---------------------------------------------------------------------------*/
12772
// Copy to complete, we will not start any new copying.
12773
/*---------------------------------------------------------------------------*/
12774
closeCopyLab(signal);
12777
if (tcConnectptr.p->copyCountWords < cmaxWordsAtNodeRec) {
12779
nextRecordCopy(signal);
12783
tcConnectptr.p->copyCountWords -= lqhKeyConf->transId1; // Data overload, see note!
12784
ndbrequire(tcConnectptr.p->copyCountWords <= cmaxWordsAtNodeRec);
12785
if (tcConnectptr.p->copyCountWords > 0) {
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) {
12797
closeCopyLab(signal);
12801
if (scanptr.p->scanState == ScanRecord::WAIT_LQHKEY_COPY &&
12802
scanptr.p->scanErrorCounter)
12805
closeCopyLab(signal);
12809
if (scanptr.p->scanState == ScanRecord::WAIT_LQHKEY_COPY) {
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__);
12819
}//Dblqh::copyCompletedLab()
12821
void Dblqh::nextRecordCopy(Signal* signal)
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) {
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
12833
/*---------------------------------------------------------------------------*/
12834
systemErrorLab(signal, __LINE__);
12837
scanptr.p->scanState = ScanRecord::WAIT_NEXT_SCAN_COPY;
12838
switch (fragptr.p->fragStatus) {
12839
case Fragrecord::FSACTIVE:
12842
case Fragrecord::BLOCKED:
12844
linkFragQueue(signal);
12845
tcConnectptr.p->transactionState = TcConnectionrec::COPY_STOPPED;
12848
case Fragrecord::FREE:
12850
case Fragrecord::ACTIVE_CREATION:
12852
case Fragrecord::CRASH_RECOVERING:
12854
case Fragrecord::DEFINED:
12856
case Fragrecord::REMOVING:
12860
systemErrorLab(signal, __LINE__);
12864
continueCopyAfterBlockedLab(signal);
12866
}//Dblqh::nextRecordCopy()
12868
void Dblqh::continueCopyAfterBlockedLab(Signal* signal)
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)
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);
12884
* No need to commit (unlock)
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);
12892
}//Dblqh::continueCopyAfterBlockedLab()
12894
void Dblqh::copyLqhKeyRefLab(Signal* signal)
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;
12903
LqhKeyConf* conf = (LqhKeyConf*)signal->getDataPtrSend();
12904
conf->transId1 = copyWords;
12905
conf->transId2 = tcConnectptr.p->transid[1];
12906
copyCompletedLab(signal);
12907
}//Dblqh::copyLqhKeyRefLab()
12909
void Dblqh::closeCopyLab(Signal* signal)
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
12916
/*---------------------------------------------------------------------------*/
12917
scanptr.p->scanState = ScanRecord::WAIT_LQHKEY_COPY;
12921
tcConnectptr.p->transid[0] = 0;
12922
tcConnectptr.p->transid[1] = 0;
12923
fragptr.i = tcConnectptr.p->fragmentptr;
12924
c_fragment_pool.getPtr(fragptr);
12927
* Stop sending ROWID for all operations from now on
12929
fragptr.p->m_copy_started_state = Fragrecord::AC_NORMAL;
12930
if (ERROR_INSERTED(5714))
12932
ndbout_c("Copy of tab: %u frag: %u complete",
12933
fragptr.p->tabRef, fragptr.p->fragId);
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:
12943
case Fragrecord::BLOCKED:
12945
linkFragQueue(signal);
12946
tcConnectptr.p->transactionState = TcConnectionrec::COPY_CLOSE_STOPPED;
12949
case Fragrecord::FREE:
12951
case Fragrecord::ACTIVE_CREATION:
12953
case Fragrecord::CRASH_RECOVERING:
12955
case Fragrecord::DEFINED:
12957
case Fragrecord::REMOVING:
12961
systemErrorLab(signal, __LINE__);
12965
continueCloseCopyAfterBlockedLab(signal);
12967
}//Dblqh::closeCopyLab()
12969
void Dblqh::continueCloseCopyAfterBlockedLab(Signal* signal)
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);
12978
}//Dblqh::continueCloseCopyAfterBlockedLab()
12980
/*---------------------------------------------------------------------------*/
12981
/* ENTER NEXT_SCANCONF WITH */
12992
/*---------------------------------------------------------------------------*/
12993
/* PRECONDITION: SCAN_STATE = WAIT_CLOSE_COPY */
12994
/*---------------------------------------------------------------------------*/
12995
void Dblqh::accCopyCloseConfLab(Signal* signal)
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);
13008
}//Dblqh::accCopyCloseConfLab()
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)
13019
fragptr.i = tcConnectptr.p->fragmentptr;
13020
c_fragment_pool.getPtr(fragptr);
13021
fragptr.p->copyFragState = ZIDLE;
13023
if (tcConnectptr.p->abortState == TcConnectionrec::NEW_FROM_TC) {
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);
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);
13042
if (scanptr.p->scanErrorCounter > 0) {
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);
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);
13067
releaseActiveCopy(signal);
13068
tcConnectptr.p->tcScanRec = RNIL;
13069
finishScanrec(signal);
13070
releaseOprec(signal);
13071
releaseTcrec(signal, tcConnectptr);
13072
releaseScanrec(signal);
13073
}//Dblqh::tupCopyCloseConfLab()
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)
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:
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;
13095
case ScanRecord::WAIT_ACC_COPY:
13096
case ScanRecord::WAIT_STORED_PROC_COPY:
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;
13104
case ScanRecord::WAIT_CLOSE_COPY:
13105
case ScanRecord::WAIT_DELETE_STORED_PROC_ID_COPY:
13107
/*---------------------------------------------------------------------------*/
13108
/* CLOSE IS ALREADY ONGOING. WE NEED NOT DO ANYTHING. */
13109
/*---------------------------------------------------------------------------*/
13111
case ScanRecord::WAIT_LQHKEY_COPY:
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);
13126
}//Dblqh::closeCopyRequestLab()
13128
/* ****************************************************** */
13129
/* COPY_ACTIVEREQ: Change state of a fragment to ACTIVE. */
13130
/* ****************************************************** */
13131
void Dblqh::execCOPY_ACTIVEREQ(Signal* signal)
13133
CRASH_INSERTION(5026);
13135
const CopyActiveReq * const req = (CopyActiveReq *)&signal->theData[0];
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))
13149
ndbrequire(getFragmentrec(signal, fragId));
13151
fragptr.p->fragStatus = Fragrecord::FSACTIVE;
13152
fragptr.p->fragDistributionKey = req->distributionKey;
13155
TRACENR("tab: " << tabptr.i
13156
<< " frag: " << fragId
13158
<< " flags: " << hex << flags << endl);
13160
ndbrequire(cnoActiveCopy < 3);
13161
cactiveCopy[cnoActiveCopy] = fragptr.i;
13163
fragptr.p->masterBlockref = masterRef;
13164
fragptr.p->masterPtr = masterPtr;
13166
if ((flags & CopyActiveReq::CAR_NO_LOGGING) == 0)
13169
if (fragptr.p->lcpFlag == Fragrecord::LCP_STATE_TRUE)
13172
fragptr.p->logFlag = Fragrecord::STATE_TRUE;
13176
if (flags & CopyActiveReq::CAR_NO_WAIT)
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;
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 */
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);
13199
}//Dblqh::execCOPY_ACTIVEREQ()
13201
void Dblqh::scanTcConnectLab(Signal* signal, Uint32 tstartTcConnect, Uint32 fragId)
13203
Uint32 tendTcConnect;
13205
ndbrequire(getFragmentrec(signal, fragId));
13206
if ((tstartTcConnect + 200) >= ctcConnectrecFileSize) {
13208
tendTcConnect = ctcConnectrecFileSize - 1;
13211
tendTcConnect = tstartTcConnect + 200;
13213
for (tcConnectptr.i = tstartTcConnect;
13214
tcConnectptr.i <= tendTcConnect;
13215
tcConnectptr.i++) {
13217
ptrCheckGuard(tcConnectptr, ctcConnectrecFileSize, tcConnectionrec);
13218
if (tcConnectptr.p->transactionState != TcConnectionrec::IDLE) {
13219
switch (tcConnectptr.p->logWriteState) {
13220
case TcConnectionrec::NOT_WRITTEN:
13222
if (fragptr.i == tcConnectptr.p->fragmentptr) {
13224
fragptr.p->activeTcCounter = fragptr.p->activeTcCounter + 1;
13225
tcConnectptr.p->logWriteState = TcConnectionrec::NOT_WRITTEN_WAIT;
13235
if (tendTcConnect < (ctcConnectrecFileSize - 1)) {
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);
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) {
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);
13262
}//Dblqh::scanTcConnectLab()
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)
13275
Uint32* dataPtr = &signal->theData[2];
13276
BlockReference tmasterBlockref = signal->theData[0];
13277
Uint32 tnoCopy = 0;
13280
arrGuard(tnoCopy, 4);
13281
fragptr.i = cactiveCopy[tnoCopy];
13282
if (fragptr.i == RNIL) {
13286
c_fragment_pool.getPtr(fragptr);
13287
if (fragptr.p->copyFragState != ZIDLE) {
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) {
13296
dataPtr[3 + (tnoCopy << 2)] = ZCOPY_CLOSING;
13299
dataPtr[3 + (tnoCopy << 2)] = ZCOPY_ONGOING;
13301
dataPtr[2 + (tnoCopy << 2)] = scanptr.p->scanSchemaVersion;
13302
scanptr.p->scanApiBlockref = tmasterBlockref;
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;
13312
dataPtr[tnoCopy << 2] = fragptr.p->tabRef;
13313
dataPtr[1 + (tnoCopy << 2)] = fragptr.p->fragId;
13315
} while (tnoCopy < cnoActiveCopy);
13316
signal->theData[0] = cownNodeid;
13317
signal->theData[1] = tnoCopy;
13318
sendSignal(tmasterBlockref, GSN_COPY_STATECONF, signal, 18, JBB);
13321
}//Dblqh::execCOPY_STATEREQ()
13323
/* ========================================================================= */
13324
/* ======= INITIATE TC RECORD AT COPY FRAGMENT ======= */
13326
/* SUBROUTINE SHORT NAME = ICT */
13327
/* ========================================================================= */
13328
void Dblqh::initCopyTc(Signal* signal, Operation_t op)
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()
13359
/* ------------------------------------------------------------------------- */
13360
/* ------- SEND COPY_ACTIVECONF TO MASTER DIH ------- */
13362
/* ------------------------------------------------------------------------- */
13363
void Dblqh::sendCopyActiveConf(Signal* signal, Uint32 tableId)
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()
13376
/* ##########################################################################
13377
* ####### LOCAL CHECKPOINT MODULE #######
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)
13388
CRASH_INSERTION(5008);
13389
EmptyLcpReq * const emptyLcpOrd = (EmptyLcpReq*)&signal->theData[0];
13391
ndbrequire(!isNdbMtLqh()); // Handled by DblqhProxy
13394
ptrAss(lcpPtr, lcpRecord);
13396
Uint32 nodeId = refToNode(emptyLcpOrd->senderRef);
13398
lcpPtr.p->m_EMPTY_LCP_REQ.set(nodeId);
13399
lcpPtr.p->reportEmpty = true;
13401
if (lcpPtr.p->lcpState == LcpRecord::LCP_IDLE){
13404
switch(clcpCompletedState){
13407
sendEMPTY_LCP_CONF(signal, true);
13411
sendEMPTY_LCP_CONF(signal, false);
13413
case LCP_CLOSE_STARTED:
13415
case ACC_LCP_CLOSE_COMPLETED:
13417
case TUP_LCP_CLOSE_COMPLETED:
13427
}//Dblqh::execEMPTY_LCPREQ()
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);
13440
SignalHeader header;
13441
Uint32 theData[25];
13443
Vector<Sig> m_signals;
13445
template class Vector<TraceLCP::Sig>;
13450
Dblqh::force_lcp(Signal* signal)
13452
if (cLqhTimeOutCount == c_last_force_lcp_time)
13458
c_last_force_lcp_time = cLqhTimeOutCount;
13459
signal->theData[0] = 7099;
13460
sendSignal(DBDIH_REF, GSN_DUMP_STATE_ORD, signal, 1, JBB);
13463
void Dblqh::execLCP_FRAG_ORD(Signal* signal)
13466
CRASH_INSERTION(5010);
13468
LcpFragOrd lcpFragOrdCopy = * (LcpFragOrd *)&signal->theData[0];
13469
LcpFragOrd * lcpFragOrd = &lcpFragOrdCopy;
13471
Uint32 lcpId = lcpFragOrd->lcpId;
13474
ptrAss(lcpPtr, lcpRecord);
13476
lcpPtr.p->lastFragmentFlag = lcpFragOrd->lastFragmentFlag;
13477
if (lcpFragOrd->lastFragmentFlag)
13480
CRASH_INSERTION(5054);
13481
if (lcpPtr.p->lcpState == LcpRecord::LCP_IDLE) {
13483
/* ----------------------------------------------------------
13484
* NOW THE COMPLETE LOCAL CHECKPOINT ROUND IS COMPLETED.
13485
* -------------------------------------------------------- */
13486
if (cnoOfFragsCheckpointed > 0) {
13488
completeLcpRoundLab(signal, lcpId);
13491
clcpCompletedState = LCP_IDLE;
13492
sendLCP_COMPLETE_REP(signal, lcpId);
13497
tabptr.i = lcpFragOrd->tableId;
13498
ptrCheckGuard(tabptr, ctabrecFileSize, tablerec);
13501
ptrAss(lcpPtr, lcpRecord);
13502
ndbrequire(!lcpPtr.p->lcpQueued);
13504
if (c_lcpId < lcpFragOrd->lcpId)
13508
lcpPtr.p->firstFragmentFlag= true;
13510
#ifdef ERROR_INSERT
13511
if (check_ndb_versions())
13514
* Only (so-far) in error insert
13515
* check that keepGci (tail of REDO) is smaller than of head of REDO
13518
if (! ((cnewestCompletedGci >= lcpFragOrd->keepGci) &&
13519
(cnewestGci >= lcpFragOrd->keepGci)))
13521
ndbout_c("lcpFragOrd->keepGci: %u cnewestCompletedGci: %u cnewestGci: %u",
13522
lcpFragOrd->keepGci, cnewestCompletedGci, cnewestGci);
13524
ndbrequire(cnewestCompletedGci >= lcpFragOrd->keepGci);
13525
ndbrequire(cnewestGci >= lcpFragOrd->keepGci);
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;
13536
if (! (tabptr.p->tableStatus == Tablerec::TABLE_DEFINED || tabptr.p->tableStatus == Tablerec::TABLE_READ_ONLY))
13539
LcpRecord::FragOrd fragOrd;
13540
fragOrd.fragPtrI = RNIL;
13541
fragOrd.lcpFragOrd = * lcpFragOrd;
13544
tmp.maxGciInLcp = cnewestGci;
13545
tmp.maxGciCompletedInLcp = cnewestCompletedGci;
13546
sendLCP_FRAG_REP(signal, fragOrd, &tmp);
13550
cnoOfFragsCheckpointed++;
13551
ndbrequire(getFragmentrec(signal, lcpFragOrd->fragmentId));
13553
if (lcpPtr.p->lcpState != LcpRecord::LCP_IDLE)
13555
ndbrequire(lcpPtr.p->lcpQueued == false);
13556
lcpPtr.p->lcpQueued = true;
13557
lcpPtr.p->queuedFragment.fragPtrI = fragptr.i;
13558
lcpPtr.p->queuedFragment.lcpFragOrd = * lcpFragOrd;
13562
lcpPtr.p->currentFragment.fragPtrI = fragptr.i;
13563
lcpPtr.p->currentFragment.lcpFragOrd = * lcpFragOrd;
13565
sendLCP_FRAGIDREQ(signal);
13566
}//Dblqh::execLCP_FRAGORD()
13568
void Dblqh::execLCP_PREPARE_REF(Signal* signal)
13572
LcpPrepareRef* ref= (LcpPrepareRef*)signal->getDataPtr();
13574
lcpPtr.i = ref->senderData;
13575
ptrCheckGuard(lcpPtr, clcpFileSize, lcpRecord);
13576
ndbrequire(lcpPtr.p->lcpState == LcpRecord::LCP_WAIT_FRAGID);
13578
fragptr.i = lcpPtr.p->currentFragment.fragPtrI;
13579
c_fragment_pool.getPtr(fragptr);
13581
ndbrequire(ref->tableId == fragptr.p->tabRef);
13582
ndbrequire(ref->fragmentId == fragptr.p->fragId);
13584
tabptr.i = ref->tableId;
13585
ptrCheckGuard(tabptr, ctabrecFileSize, tablerec);
13587
ndbrequire(lcpPtr.p->m_outstanding);
13588
lcpPtr.p->m_outstanding--;
13591
* Only BACKUP is allowed to ref LCP_PREPARE
13593
ndbrequire(refToMain(signal->getSendersBlockRef()) == BACKUP);
13594
lcpPtr.p->m_error = ref->errorCode;
13596
if (lcpPtr.p->m_outstanding == 0)
13600
if(lcpPtr.p->firstFragmentFlag)
13603
LcpFragOrd *ord= (LcpFragOrd*)signal->getDataPtrSend();
13604
lcpPtr.p->firstFragmentFlag= false;
13609
*ord = lcpPtr.p->currentFragment.lcpFragOrd;
13610
EXECUTE_DIRECT(PGMAN, GSN_LCP_FRAG_ORD, signal, signal->length());
13614
* First fragment mean that last LCP is complete :-)
13617
*ord = lcpPtr.p->currentFragment.lcpFragOrd;
13618
EXECUTE_DIRECT(TSMAN, GSN_LCP_FRAG_ORD,
13619
signal, signal->length(), 0);
13625
* Handle by LqhProxy
13630
lcpPtr.p->lcpState = LcpRecord::LCP_COMPLETED;
13631
contChkpNextFragLab(signal);
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)
13644
LcpPrepareConf* conf= (LcpPrepareConf*)signal->getDataPtr();
13646
lcpPtr.i = conf->senderData;
13647
ptrCheckGuard(lcpPtr, clcpFileSize, lcpRecord);
13648
ndbrequire(lcpPtr.p->lcpState == LcpRecord::LCP_WAIT_FRAGID);
13650
fragptr.i = lcpPtr.p->currentFragment.fragPtrI;
13651
c_fragment_pool.getPtr(fragptr);
13653
// wl4391_todo obsolete
13654
if (refToBlock(signal->getSendersBlockRef()) != PGMAN)
13656
ndbrequire(conf->tableId == fragptr.p->tabRef);
13657
ndbrequire(conf->fragmentId == fragptr.p->fragId);
13660
ndbrequire(lcpPtr.p->m_outstanding);
13661
lcpPtr.p->m_outstanding--;
13662
if (lcpPtr.p->m_outstanding == 0)
13666
if(lcpPtr.p->firstFragmentFlag)
13669
LcpFragOrd *ord= (LcpFragOrd*)signal->getDataPtrSend();
13670
lcpPtr.p->firstFragmentFlag= false;
13672
// proxy is used in MT LQH to handle also the extra pgman worker
13676
*ord = lcpPtr.p->currentFragment.lcpFragOrd;
13677
EXECUTE_DIRECT(PGMAN, GSN_LCP_FRAG_ORD, signal, signal->length());
13681
* First fragment mean that last LCP is complete :-)
13684
*ord = lcpPtr.p->currentFragment.lcpFragOrd;
13685
EXECUTE_DIRECT(TSMAN, GSN_LCP_FRAG_ORD,
13686
signal, signal->length(), 0);
13697
if (lcpPtr.p->m_error)
13701
lcpPtr.p->lcpState = LcpRecord::LCP_COMPLETED;
13702
contChkpNextFragLab(signal);
13706
lcpPtr.p->lcpState = LcpRecord::LCP_WAIT_HOLDOPS;
13707
lcpPtr.p->lcpState = LcpRecord::LCP_START_CHKP;
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;
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);
13724
*ord = lcpPtr.p->currentFragment.lcpFragOrd;
13725
EXECUTE_DIRECT(DBTUP, GSN_LCP_FRAG_ORD, signal, signal->length());
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;
13736
#ifdef NDB_DEBUG_FULL
13737
if(ERROR_INSERTED(5904))
13739
g_trace_lcp.sendSignal(BACKUP_REF, GSN_BACKUP_FRAGMENT_REQ, signal,
13740
BackupFragmentReq::SignalLength, JBB);
13745
if (ERROR_INSERTED(5044) &&
13746
(fragptr.p->tabRef == c_error_insert_table_id) &&
13747
fragptr.p->fragId) // Not first frag
13750
* Force CRASH_INSERTION in 10s
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);
13756
else if (ERROR_INSERTED(5053))
13758
BlockReference backupRef = calcInstanceBlockRef(BACKUP);
13759
sendSignalWithDelay(backupRef, GSN_BACKUP_FRAGMENT_REQ, signal,
13760
150, BackupFragmentReq::SignalLength);
13764
BlockReference backupRef = calcInstanceBlockRef(BACKUP);
13765
sendSignal(backupRef, GSN_BACKUP_FRAGMENT_REQ, signal,
13766
BackupFragmentReq::SignalLength, JBB);
13772
void Dblqh::execBACKUP_FRAGMENT_REF(Signal* signal)
13774
BackupFragmentRef *ref= (BackupFragmentRef*)signal->getDataPtr();
13776
BaseString::snprintf(buf,sizeof(buf),
13777
"Unable to store fragment during LCP. NDBFS Error: %u",
13780
progError(__LINE__,
13781
(ref->errorCode & FsRef::FS_ERR_BIT)?
13782
NDBD_EXIT_AFS_UNKNOWN
13787
void Dblqh::execBACKUP_FRAGMENT_CONF(Signal* signal)
13790
//BackupFragmentConf* conf= (BackupFragmentConf*)signal->getDataPtr();
13793
ptrCheckGuard(lcpPtr, clcpFileSize, lcpRecord);
13794
ndbrequire(lcpPtr.p->lcpState == LcpRecord::LCP_START_CHKP);
13795
lcpPtr.p->lcpState = LcpRecord::LCP_COMPLETED;
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);
13808
* Update maxGciInLcp after scan has been performed
13810
#if defined VM_TRACE || defined ERROR_INSERT
13811
if (fragptr.p->newestGci != fragptr.p->maxGciInLcp)
13813
ndbout_c("tab: %u frag: %u increasing maxGciInLcp from %u to %u",
13816
fragptr.p->maxGciInLcp, fragptr.p->newestGci);
13820
fragptr.p->maxGciInLcp = fragptr.p->newestGci;
13822
contChkpNextFragLab(signal);
13824
}//Dblqh::lcpCompletedLab()
13827
Dblqh::sendLCP_FRAG_REP(Signal * signal,
13828
const LcpRecord::FragOrd & fragOrd,
13829
const Fragrecord * fragPtrP) const
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;
13841
Uint32 ref = DBDIH_REF;
13847
lcpReport->nodeId = LcpFragRep::BROADCAST_REQ;
13848
sendSignal(ref, GSN_LCP_FRAG_REP, signal,
13849
LcpFragRep::SignalLength, JBB);
13852
void Dblqh::contChkpNextFragLab(Signal* signal)
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) {
13862
* LCP of fragment complete
13863
* but restarting of operations isn't
13865
lcpPtr.p->lcpState = LcpRecord::LCP_BLOCKED_COMP;
13870
* Send rep when fragment is done + unblocked
13872
sendLCP_FRAG_REP(signal, lcpPtr.p->currentFragment,
13873
c_fragment_pool.getPtr(lcpPtr.p->currentFragment.fragPtrI));
13875
/* ------------------------------------------------------------------------
13876
* WE ALSO RELEASE THE LOCAL LCP RECORDS.
13877
* ----------------------------------------------------------------------- */
13878
if (lcpPtr.p->lcpQueued) {
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;
13886
/* ----------------------------------------------------------------------
13887
* START THE QUEUED LOCAL CHECKPOINT.
13888
* --------------------------------------------------------------------- */
13889
sendLCP_FRAGIDREQ(signal);
13893
lcpPtr.p->lcpState = LcpRecord::LCP_IDLE;
13894
if (lcpPtr.p->lastFragmentFlag){
13896
/* ----------------------------------------------------------------------
13897
* NOW THE COMPLETE LOCAL CHECKPOINT ROUND IS COMPLETED.
13898
* --------------------------------------------------------------------- */
13899
completeLcpRoundLab(signal, lcpPtr.p->currentFragment.lcpFragOrd.lcpId);
13903
if (lcpPtr.p->reportEmpty) {
13905
sendEMPTY_LCP_CONF(signal, false);
13908
}//Dblqh::contChkpNextFragLab()
13910
void Dblqh::sendLCP_FRAGIDREQ(Signal* signal)
13912
TablerecPtr tabPtr;
13913
tabPtr.i = lcpPtr.p->currentFragment.lcpFragOrd.tableId;
13914
ptrAss(tabPtr, tablerec);
13916
if(tabPtr.p->tableStatus != Tablerec::TABLE_DEFINED)
13920
* Fake that the fragment is done
13922
contChkpNextFragLab(signal);
13926
lcpPtr.p->m_error = 0;
13927
lcpPtr.p->m_outstanding = 1;
13929
ndbrequire(tabPtr.p->tableStatus == Tablerec::TABLE_DEFINED ||
13930
tabPtr.p->tableStatus == Tablerec::TABLE_READ_ONLY);
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);
13946
}//Dblqh::sendLCP_FRAGIDREQ()
13948
void Dblqh::sendEMPTY_LCP_CONF(Signal* signal, bool idle)
13950
EmptyLcpRep * sig = (EmptyLcpRep*)signal->getDataPtrSend();
13951
EmptyLcpConf * rep = (EmptyLcpConf*)sig->conf;
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();
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;
13970
rep->fragmentId = ~0;
13972
rep->lcpId = c_lcpId;
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);
13979
lcpPtr.p->reportEmpty = false;
13980
lcpPtr.p->m_EMPTY_LCP_REQ.clear();
13981
}//Dblqh::sendEMPTY_LCPCONF()
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)
13989
clcpCompletedState = LCP_CLOSE_STARTED;
13992
ptrAss(lcpPtr, lcpRecord);
13993
lcpPtr.p->m_outstanding = 0;
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;
14001
BlockReference backupRef = calcInstanceBlockRef(BACKUP);
14003
lcpPtr.p->m_outstanding++;
14004
sendSignal(backupRef, GSN_END_LCP_REQ, signal,
14005
EndLcpReq::SignalLength, JBB);
14010
lcpPtr.p->m_outstanding++;
14011
sendSignal(PGMAN_REF, GSN_END_LCP_REQ, signal,
14012
EndLcpReq::SignalLength, JBB);
14014
lcpPtr.p->m_outstanding++;
14015
sendSignal(LGMAN_REF, GSN_END_LCP_REQ, signal,
14016
EndLcpReq::SignalLength, JBB);
14018
EXECUTE_DIRECT(TSMAN, GSN_END_LCP_REQ,
14019
signal, EndLcpReq::SignalLength, 0);
14024
* This is all handled by LqhProxy
14028
}//Dblqh::completeLcpRoundLab()
14030
void Dblqh::execEND_LCPCONF(Signal* signal)
14034
ptrAss(lcpPtr, lcpRecord);
14036
ndbrequire(clcpCompletedState == LCP_CLOSE_STARTED);
14037
ndbrequire(lcpPtr.p->m_outstanding);
14039
lcpPtr.p->m_outstanding--;
14040
if(lcpPtr.p->m_outstanding == 0)
14043
clcpCompletedState = LCP_IDLE;
14044
sendLCP_COMPLETE_REP(signal, lcpPtr.p->currentFragment.lcpFragOrd.lcpId);
14046
CRASH_INSERTION(5056);
14048
}//Dblqh::execEND_LCPCONF()
14050
void Dblqh::sendLCP_COMPLETE_REP(Signal* signal, Uint32 lcpId)
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
* ----------------------------------------------------------------------- */
14058
ptrAss(lcpPtr, lcpRecord);
14059
lcpPtr.p->lastFragmentFlag = false;
14060
lcpPtr.p->firstFragmentFlag = false;
14062
LcpCompleteRep* rep = (LcpCompleteRep*)signal->getDataPtrSend();
14063
rep->nodeId = getOwnNodeId();
14064
rep->lcpId = lcpId;
14065
rep->blockNo = DBLQH;
14067
Uint32 ref = DBDIH_REF;
14073
rep->nodeId = LcpFragRep::BROADCAST_REQ;
14075
sendSignal(ref, GSN_LCP_COMPLETE_REP, signal,
14076
LcpCompleteRep::SignalLength, JBB);
14078
if(lcpPtr.p->reportEmpty){
14080
sendEMPTY_LCP_CONF(signal, true);
14083
if (cstartRecReq < SRR_FIRST_LCP_DONE)
14086
ndbrequire(cstartRecReq == SRR_REDO_COMPLETE);
14087
cstartRecReq = SRR_FIRST_LCP_DONE;
14091
}//Dblqh::sendCOMP_LCP_ROUND()
14095
Dblqh::execLCP_COMPLETE_REP(Signal* signal)
14098
* This is sent when last LCP is restorable
14100
LcpCompleteRep * rep = (LcpCompleteRep*)signal->getDataPtr();
14101
Uint32 keepGci = rep->keepGci;
14102
setLogTail(signal, keepGci);
14106
/* ------------------------------------------------------------------------- */
14107
/* ------- SEND ACC_LCPREQ AND TUP_LCPREQ ------- */
14109
/* INPUT: LCP_PTR LOCAL CHECKPOINT RECORD */
14110
/* FRAGPTR FRAGMENT RECORD */
14111
/* SUBROUTINE SHORT NAME = STL */
14112
/* ------------------------------------------------------------------------- */
14113
void Dblqh::sendStartLcp(Signal* signal)
14115
}//Dblqh::sendStartLcp()
14117
/* ------------------------------------------------------------------------- */
14118
/* ------- SET THE LOG TAIL IN THE LOG FILES ------- */
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
/* ------------------------------------------------------------------------- */
14130
void Dblqh::setLogTail(Signal* signal, Uint32 keepGci)
14132
LogPartRecordPtr sltLogPartPtr;
14133
LogFileRecordPtr sltLogFilePtr;
14135
UintR tsltStartMbyte;
14139
for (sltLogPartPtr.i = 0; sltLogPartPtr.i < clogPartFileSize; sltLogPartPtr.i++) {
14141
bool TchangeMB = false;
14143
ptrAss(sltLogPartPtr, logPartRecord);
14144
findLogfile(signal, sltLogPartPtr.p->logTailFileNo,
14145
sltLogPartPtr, &sltLogFilePtr);
14147
tsltMbyte = sltLogPartPtr.p->logTailMbyte;
14148
tsltStartMbyte = tsltMbyte;
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) {
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
/* ------------------------------------------------------------------------- */
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
/* ------------------------------------------------------------------------- */
14174
for (tsltIndex = tsltStartMbyte;
14175
tsltIndex <= clogFileSize - 1;
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) {
14185
tsltMbyte = tsltIndex - 1;
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);
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) {
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;
14215
sltLogFilePtr.i = sltLogFilePtr.p->nextLogFile;
14216
ptrCheckGuard(sltLogFilePtr, clogFileFileSize, logFileRecord);
14217
if (sltLogFilePtr.i == sltLogPartPtr.p->currentLogfile) {
14221
tsltStartMbyte = 0;
14226
UintR ToldTailFileNo = sltLogPartPtr.p->logTailFileNo;
14227
UintR ToldTailMByte = sltLogPartPtr.p->logTailMbyte;
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;
14243
ndbout_c("part: %u setLogTail(gci: %u): file: %u mb: %u",
14244
sltLogPartPtr.p->logPartNo,
14246
sltLogPartPtr.p->logTailFileNo,
14247
sltLogPartPtr.p->logTailMbyte);
14250
bool tailmoved = !(ToldTailFileNo == sltLogPartPtr.p->logTailFileNo &&
14251
ToldTailMByte == sltLogPartPtr.p->logTailMbyte);
14253
LogFileRecordPtr tmpfile;
14254
tmpfile.i = sltLogPartPtr.p->currentLogfile;
14255
ptrCheckGuard(tmpfile, clogFileFileSize, logFileRecord);
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,
14263
if (mb <= c_free_mb_force_lcp_limit)
14271
if (tailmoved && mb > c_free_mb_tail_problem_limit)
14274
update_log_problem(signal, sltLogPartPtr,
14275
LogPartRecord::P_TAIL_PROBLEM, false);
14277
else if (!tailmoved && mb <= c_free_mb_force_lcp_limit)
14281
* Tail didn't move...and we forced a new LCP
14282
* This could be as currentMb, contains backreferences making it
14283
* Check if changing mb forward will help situation
14288
* 0 or 1 mb free, no point in trying to changeMbyte forward...
14298
* We already did move forward...
14303
TcConnectionrecPtr tmp;
14304
tmp.i = sltLogPartPtr.p->firstLogTcrec;
14308
ptrCheckGuard(tmp, ctcConnectrecFileSize, tcConnectionrec);
14309
Uint32 fileNo = tmp.p->logStartFileNo;
14310
Uint32 mbyte = tmp.p->logStartPageNo >> ZTWOLOG_NO_PAGES_IN_MBYTE;
14312
if (fileNo == sltLogPartPtr.p->logTailFileNo &&
14313
mbyte == sltLogPartPtr.p->logTailMbyte)
14317
* An uncommitted operation...still pending...
14318
* with back-reference to tail...not much to do
14319
* (theoretically we could rewrite log-entry here...
14320
* but this is for future)
14329
* Try forcing a changeMbyte
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...
14346
}//Dblqh::setLogTail()
14348
/* ######################################################################### */
14349
/* ####### GLOBAL CHECKPOINT MODULE ####### */
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
/* *************** */
14361
#if defined VM_TRACE || defined ERROR_INSERT
14362
static Uint32 m_gcp_monitor = 0;
14365
void Dblqh::execGCP_SAVEREQ(Signal* signal)
14368
const GCPSaveReq * const saveReq = (GCPSaveReq *)&signal->theData[0];
14370
CRASH_INSERTION(5000);
14372
if (ERROR_INSERTED(5007)){
14373
CLEAR_ERROR_INSERT_VALUE;
14374
sendSignalWithDelay(cownref, GSN_GCP_SAVEREQ, signal, 10000,
14379
if (unlikely(refToNode(signal->getSendersBlockRef()) != getOwnNodeId()))
14382
* This code is only run during upgrade from pre-micro-gcp version.
14384
* During startup, we make sure not to allow starting multi-threaded
14385
* NDBD while such an upgrade is taking place. So the EXECUTE_DIRECT()
14386
* below, which would be cross-thread in multi-threaded NDBD, is thus
14387
* safe since it never runs in the non-safe case.
14389
ndbassert(!isMultiThreaded());
14391
ndbassert(!ndb_check_micro_gcp
14392
(getNodeInfo(refToNode
14393
(signal->getSendersBlockRef())).m_version));
14394
EXECUTE_DIRECT(DBDIH, GSN_GCP_SAVEREQ, signal, signal->getLength());
14398
const Uint32 dihBlockRef = saveReq->dihBlockRef;
14399
const Uint32 dihPtr = saveReq->dihPtr;
14400
const Uint32 gci = saveReq->gci;
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);
14408
m_gcp_monitor = gci;
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);
14422
Uint32 saveNewestCompletedGci = cnewestCompletedGci;
14423
cnewestCompletedGci = gci;
14425
if (cstartRecReq < SRR_REDO_COMPLETE)
14428
* REDO running is not complete
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);
14440
ndbrequire(gci >= saveNewestCompletedGci);
14442
if (gci == saveNewestCompletedGci)
14444
/*---------------------------------------------------------------------------*/
14445
/* GLOBAL CHECKPOINT HAVE ALREADY BEEN HANDLED. REQUEST MUST HAVE BEEN SENT */
14446
/* FROM NEW MASTER DIH. */
14447
/*---------------------------------------------------------------------------*/
14448
if (ccurrentGcprec == RNIL) {
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);
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 */
14467
/*---------------------------------------------------------------------------*/
14468
gcpPtr.i = ccurrentGcprec;
14469
ptrCheckGuard(gcpPtr, cgcprecFileSize, gcpRecord);
14470
gcpPtr.p->gcpUserptr = dihPtr;
14471
gcpPtr.p->gcpBlockref = dihBlockRef;
14475
ndbrequire(ccurrentGcprec == RNIL);
14476
cnewestCompletedGci = gci;
14477
if (gci > cnewestGci) {
14482
if(cstartRecReq < SRR_FIRST_LCP_DONE)
14485
* First LCP has not been done
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);
14495
if (ERROR_INSERTED(5052))
14498
signal->theData[0] = 9999;
14499
sendSignalWithDelay(CMVMI_REF, GSN_NDB_TAMPER, signal, 300, 1);
14504
CRASH_INSERTION(5052);
14506
#ifdef GCP_TIMER_HACK
14507
NdbTick_getMicroTimer(&globalData.gcp_timer_save[0]);
14510
ccurrentGcprec = 0;
14511
gcpPtr.i = ccurrentGcprec;
14512
ptrCheckGuard(gcpPtr, cgcprecFileSize, gcpRecord);
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) {
14522
logPartPtr.p->waitWriteGciLog = LogPartRecord::WWGL_TRUE;
14524
if (logPartPtr.p->LogLqhKeyReqSent == ZFALSE)
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);
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);
14542
if (tlogActive == true) {
14546
initGcpRecLab(signal);
14547
startTimeSupervision(signal);
14549
}//Dblqh::execGCP_SAVEREQ()
14552
* This is needed for ndbmtd to serialize
14553
* SUB_GCP_COMPLETE_REP vs FIRE_TRIG_ORD
14556
Dblqh::execSUB_GCP_COMPLETE_REP(Signal* signal)
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);
14564
/* ------------------------------------------------------------------------- */
14565
/* START TIME SUPERVISION OF THE LOG PARTS. */
14566
/* ------------------------------------------------------------------------- */
14567
void Dblqh::startTimeSupervision(Signal* signal)
14569
for (logPartPtr.i = 0; logPartPtr.i < clogPartFileSize; logPartPtr.i++) {
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);
14582
}//Dblqh::startTimeSupervision()
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)
14591
/* ======================================================================== */
14592
/* ======= INITIATE GCP RECORD ======= */
14594
/* SUBROUTINE SHORT NAME = IGR */
14595
/* ======================================================================== */
14596
for (logPartPtr.i = 0; logPartPtr.i < clogPartFileSize; logPartPtr.i++) {
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) {
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 */
14622
/*--------------------------------------------------*/
14623
gcpPtr.p->gcpPageNo[logPartPtr.i] = logFilePtr.p->currentFilepage - 1;
14624
gcpPtr.p->gcpWordNo[logPartPtr.i] = ZPAGE_SIZE - 1;
14627
gcpPtr.p->gcpPageNo[logPartPtr.i] = logFilePtr.p->currentFilepage;
14628
gcpPtr.p->gcpWordNo[logPartPtr.i] =
14629
logPagePtr.p->logPageWord[ZCURR_PAGE_INDEX] - 1;
14632
// initialize un-used part
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;
14641
}//Dblqh::initGcpRecLab()
14643
/* ========================================================================= */
14644
/* ==== CHECK IF ANY GLOBAL CHECKPOINTS ARE COMPLETED AFTER A COMPLETED===== */
14647
/* SUBROUTINE SHORT NAME = CGC */
14648
/* return: true if gcp was completed */
14649
/* ========================================================================= */
14651
Dblqh::checkGcpCompleted(Signal* signal,
14652
Uint32 tcgcPageWritten,
14653
Uint32 tcgcWordWritten)
14658
gcpPtr.i = logPartPtr.p->gcprec;
14659
if (gcpPtr.i != RNIL)
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]) {
14674
/* ------------------------------------------------------------------------- */
14675
/* THIS LOG PART HAVE NOT YET WRITTEN THE GLOBAL CHECKPOINT TO DISK. */
14676
/* ------------------------------------------------------------------------- */
14679
if (tcgcPageWritten == gcpPtr.p->gcpPageNo[logPartPtr.i]) {
14680
if (tcgcWordWritten < gcpPtr.p->gcpWordNo[logPartPtr.i]) {
14682
/* ------------------------------------------------------------------------- */
14683
/* THIS LOG PART HAVE NOT YET WRITTEN THE GLOBAL CHECKPOINT TO DISK. */
14684
/* ------------------------------------------------------------------------- */
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;
14695
for (tcgcJ = 0; tcgcJ < clogPartFileSize; tcgcJ++)
14698
if (gcpPtr.p->gcpLogPartState[tcgcJ] != ZON_DISK) {
14700
/* ------------------------------------------------------------------------- */
14701
/*ALL LOG PARTS HAVE NOT SAVED THIS GLOBAL CHECKPOINT TO DISK YET. WAIT FOR */
14702
/*THEM TO COMPLETE. */
14703
/* ------------------------------------------------------------------------- */
14707
if (tcgcFlag == ZFALSE)
14712
if (tcgcFlag == ZTRUE)
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
/* ------------------------------------------------------------------------- */
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) {
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);
14734
ndbrequire((loopLogFilePtr.p->logFileStatus ==
14735
LogFileRecord::CLOSED) ||
14736
(loopLogFilePtr.p->logFileStatus ==
14737
LogFileRecord::CLOSING_WRITE_LOG) ||
14738
(loopLogFilePtr.p->logFileStatus ==
14739
LogFileRecord::OPENING_WRITE_LOG));
14740
signal->theData[0] = loopLogFilePtr.i;
14741
execFSSYNCCONF(signal);
14749
}//Dblqh::checkGcpCompleted()
14752
Dblqh::execFSSYNCCONF(Signal* signal)
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;
14768
ndbout_c("part: %u file: %u gci: %u SYNC CONF",
14769
localLogPartPtr.p->logPartNo,
14770
localLogFilePtr.p->fileNo,
14771
localGcpPtr.p->gcpId);
14773
for (Ti = 0; Ti < clogPartFileSize; Ti++) {
14775
if (localGcpPtr.p->gcpSyncReady[Ti] == ZFALSE) {
14781
#ifdef GCP_TIMER_HACK
14782
NdbTick_getMicroTimer(&globalData.gcp_timer_save[1]);
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()
14795
/* ######################################################################### */
14796
/* ####### FILE HANDLING MODULE ####### */
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. */
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)
14814
logFilePtr.i = signal->theData[0];
14815
ptrCheckGuard(logFilePtr, clogFileFileSize, logFileRecord);
14816
logFilePtr.p->fileRef = RNIL;
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);
14827
switch (logFilePtr.p->logFileStatus) {
14828
case LogFileRecord::CLOSE_SR_READ_INVALIDATE_PAGES:
14830
logFilePtr.p->logFileStatus = LogFileRecord::CLOSED;
14832
logPartPtr.i = logFilePtr.p->logPartRec;
14833
ptrCheckGuard(logPartPtr, clogPartFileSize, logPartRecord);
14835
readFileInInvalidate(signal, 2);
14838
case LogFileRecord::CLOSE_SR_READ_INVALIDATE_SEARCH_FILES:
14840
logFilePtr.p->logFileStatus = LogFileRecord::CLOSED;
14842
logPartPtr.i = logFilePtr.p->logPartRec;
14843
ptrCheckGuard(logPartPtr, clogPartFileSize, logPartRecord);
14845
readFileInInvalidate(signal, 4);
14847
case LogFileRecord::CLOSE_SR_READ_INVALIDATE_SEARCH_LAST_FILE:
14848
logFilePtr.p->logFileStatus = LogFileRecord::CLOSED;
14850
logPartPtr.i = logFilePtr.p->logPartRec;
14851
ptrCheckGuard(logPartPtr, clogPartFileSize, logPartRecord);
14853
readFileInInvalidate(signal, 7);
14855
case LogFileRecord::CLOSE_SR_WRITE_INVALIDATE_PAGES:
14857
logFilePtr.p->logFileStatus = LogFileRecord::CLOSED;
14859
logPartPtr.i = logFilePtr.p->logPartRec;
14860
ptrCheckGuard(logPartPtr, clogPartFileSize, logPartRecord);
14862
writeFileInInvalidate(signal, 1);
14864
case LogFileRecord::CLOSING_INIT:
14866
logFileInitDone++ ;
14867
closingInitLab(signal);
14869
case LogFileRecord::CLOSING_SR:
14871
closingSrLab(signal);
14873
case LogFileRecord::CLOSING_EXEC_SR:
14875
closeExecSrLab(signal);
14877
case LogFileRecord::CLOSING_EXEC_SR_COMPLETED:
14879
closeExecSrCompletedLab(signal);
14881
case LogFileRecord::CLOSING_WRITE_LOG:
14883
closeWriteLogLab(signal);
14885
case LogFileRecord::CLOSING_EXEC_LOG:
14887
closeExecLogLab(signal);
14889
#ifndef NO_REDO_OPEN_FILE_CACHE
14890
case LogFileRecord::CLOSING_EXEC_LOG_CACHED:
14892
logFilePtr.p->logFileStatus = LogFileRecord::CLOSED;
14893
release(signal, m_redo_open_file_cache);
14898
systemErrorLab(signal, __LINE__);
14901
}//Dblqh::execFSCLOSECONF()
14904
/* ************>> */
14906
/* ************>> */
14907
void Dblqh::execFSOPENCONF(Signal* signal)
14910
initFsopenconf(signal);
14911
switch (logFilePtr.p->logFileStatus) {
14912
case LogFileRecord::OPEN_SR_READ_INVALIDATE_PAGES:
14914
logFilePtr.p->logFileStatus = LogFileRecord::OPEN;
14915
readFileInInvalidate(signal, 0);
14917
case LogFileRecord::OPEN_SR_READ_INVALIDATE_SEARCH_FILES:
14919
logFilePtr.p->logFileStatus = LogFileRecord::OPEN;
14920
readFileInInvalidate(signal, 5);
14922
case LogFileRecord::OPEN_SR_WRITE_INVALIDATE_PAGES:
14924
logFilePtr.p->logFileStatus = LogFileRecord::OPEN;
14925
writeFileInInvalidate(signal, 0);
14927
case LogFileRecord::OPENING_INIT:
14929
logFilePtr.p->logFileStatus = LogFileRecord::OPEN;
14930
openFileInitLab(signal);
14932
case LogFileRecord::OPEN_SR_FRONTPAGE:
14934
logFilePtr.p->logFileStatus = LogFileRecord::OPEN;
14935
openSrFrontpageLab(signal);
14937
case LogFileRecord::OPEN_SR_LAST_FILE:
14939
logFilePtr.p->logFileStatus = LogFileRecord::OPEN;
14940
openSrLastFileLab(signal);
14942
case LogFileRecord::OPEN_SR_NEXT_FILE:
14944
logFilePtr.p->logFileStatus = LogFileRecord::OPEN;
14945
openSrNextFileLab(signal);
14947
case LogFileRecord::OPEN_EXEC_SR_START:
14949
logFilePtr.p->logFileStatus = LogFileRecord::OPEN;
14950
openExecSrStartLab(signal);
14952
case LogFileRecord::OPEN_EXEC_SR_NEW_MBYTE:
14954
logFilePtr.p->logFileStatus = LogFileRecord::OPEN;
14955
openExecSrNewMbyteLab(signal);
14957
case LogFileRecord::OPEN_SR_FOURTH_PHASE:
14959
logFilePtr.p->logFileStatus = LogFileRecord::OPEN;
14960
openSrFourthPhaseLab(signal);
14962
case LogFileRecord::OPEN_SR_FOURTH_NEXT:
14964
logFilePtr.p->logFileStatus = LogFileRecord::OPEN;
14965
openSrFourthNextLab(signal);
14967
case LogFileRecord::OPEN_SR_FOURTH_ZERO:
14969
logFilePtr.p->logFileStatus = LogFileRecord::OPEN;
14970
openSrFourthZeroLab(signal);
14972
case LogFileRecord::OPENING_WRITE_LOG:
14974
logFilePtr.p->logFileStatus = LogFileRecord::OPEN;
14976
case LogFileRecord::OPEN_EXEC_LOG:
14978
logFilePtr.p->logFileStatus = LogFileRecord::OPEN;
14979
#ifndef NO_REDO_OPEN_FILE_CACHE
14982
m_redo_open_file_cache.m_lru.addFirst(logFilePtr);
14985
case LogFileRecord::OPEN_EXEC_LOG_CACHED:
14988
openExecLogLab(signal);
14992
systemErrorLab(signal, __LINE__);
14995
}//Dblqh::execFSOPENCONF()
14998
Dblqh::execFSOPENREF(Signal* signal)
15001
FsRef* ref = (FsRef*)signal->getDataPtr();
15002
Uint32 err = ref->errorCode;
15003
if (err == FsRef::fsErrInvalidFileSize)
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,
15015
SimulatedBlock::execFSOPENREF(signal);
15018
/* ************>> */
15020
/* ************>> */
15021
void Dblqh::execFSREADCONF(Signal* signal)
15024
initFsrwconf(signal, false);
15026
switch (lfoPtr.p->lfoState) {
15027
case LogFileOperationRecord::READ_SR_LAST_MBYTE:
15029
releaseLfo(signal);
15030
readSrLastMbyteLab(signal);
15032
case LogFileOperationRecord::READ_SR_FRONTPAGE:
15034
releaseLfo(signal);
15035
readSrFrontpageLab(signal);
15037
case LogFileOperationRecord::READ_SR_LAST_FILE:
15039
releaseLfo(signal);
15040
readSrLastFileLab(signal);
15042
case LogFileOperationRecord::READ_SR_NEXT_FILE:
15044
releaseLfo(signal);
15045
readSrNextFileLab(signal);
15047
case LogFileOperationRecord::READ_EXEC_SR:
15049
readExecSrLab(signal);
15051
case LogFileOperationRecord::READ_EXEC_LOG:
15053
readExecLogLab(signal);
15055
case LogFileOperationRecord::READ_SR_INVALIDATE_PAGES:
15057
invalidateLogAfterLastGCI(signal);
15059
case LogFileOperationRecord::READ_SR_INVALIDATE_SEARCH_FILES:
15061
invalidateLogAfterLastGCI(signal);
15063
case LogFileOperationRecord::READ_SR_FOURTH_PHASE:
15065
releaseLfo(signal);
15066
readSrFourthPhaseLab(signal);
15068
case LogFileOperationRecord::READ_SR_FOURTH_ZERO:
15070
releaseLfo(signal);
15071
readSrFourthZeroLab(signal);
15075
systemErrorLab(signal, __LINE__);
15078
}//Dblqh::execFSREADCONF()
15080
/* ************>> */
15082
/* ************>> */
15083
void Dblqh::execFSREADREF(Signal* signal)
15086
lfoPtr.i = signal->theData[0];
15087
ptrCheckGuard(lfoPtr, clfoFileSize, logFileOperationRecord);
15088
switch (lfoPtr.p->lfoState) {
15089
case LogFileOperationRecord::READ_SR_LAST_MBYTE:
15092
case LogFileOperationRecord::READ_SR_FRONTPAGE:
15095
case LogFileOperationRecord::READ_SR_LAST_FILE:
15098
case LogFileOperationRecord::READ_SR_NEXT_FILE:
15101
case LogFileOperationRecord::READ_EXEC_SR:
15104
case LogFileOperationRecord::READ_EXEC_LOG:
15107
case LogFileOperationRecord::READ_SR_FOURTH_PHASE:
15110
case LogFileOperationRecord::READ_SR_FOURTH_ZERO:
15113
case LogFileOperationRecord::READ_SR_INVALIDATE_PAGES:
15122
sprintf(msg, "File system read failed during LogFileOperationRecord state %d", (Uint32)lfoPtr.p->lfoState);
15123
fsRefError(signal,__LINE__,msg);
15125
}//Dblqh::execFSREADREF()
15127
/* *************** */
15128
/* FSWRITECONF > */
15129
/* *************** */
15130
void Dblqh::execFSWRITECONF(Signal* signal)
15133
initFsrwconf(signal, true);
15134
switch (lfoPtr.p->lfoState) {
15135
case LogFileOperationRecord::WRITE_SR_INVALIDATE_PAGES:
15137
invalidateLogAfterLastGCI(signal);
15138
CRASH_INSERTION(5047);
15140
case LogFileOperationRecord::WRITE_PAGE_ZERO:
15142
writePageZeroLab(signal, __LINE__);
15143
releaseLfo(signal);
15145
case LogFileOperationRecord::LAST_WRITE_IN_FILE:
15147
lastWriteInFileLab(signal);
15149
case LogFileOperationRecord::INIT_WRITE_AT_END:
15151
initWriteEndLab(signal);
15153
case LogFileOperationRecord::INIT_FIRST_PAGE:
15155
logMBytesInitDone++;
15156
initFirstPageLab(signal);
15158
case LogFileOperationRecord::WRITE_GCI_ZERO:
15160
writeGciZeroLab(signal);
15162
case LogFileOperationRecord::WRITE_DIRTY:
15164
writeDirtyLab(signal);
15166
case LogFileOperationRecord::WRITE_INIT_MBYTE:
15168
logMBytesInitDone++;
15169
writeInitMbyteLab(signal);
15171
case LogFileOperationRecord::ACTIVE_WRITE_LOG:
15173
writeLogfileLab(signal);
15175
case LogFileOperationRecord::FIRST_PAGE_WRITE_IN_LOGFILE:
15177
firstPageWriteLab(signal);
15179
case LogFileOperationRecord::WRITE_SR_INVALIDATE_PAGES_UPDATE_PAGE0:
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);
15189
systemErrorLab(signal, __LINE__);
15192
}//Dblqh::execFSWRITECONF()
15194
/* ************>> */
15196
/* ************>> */
15197
void Dblqh::execFSWRITEREF(Signal* signal)
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:
15207
case LogFileOperationRecord::LAST_WRITE_IN_FILE:
15210
case LogFileOperationRecord::INIT_WRITE_AT_END:
15213
case LogFileOperationRecord::INIT_FIRST_PAGE:
15216
case LogFileOperationRecord::WRITE_GCI_ZERO:
15219
case LogFileOperationRecord::WRITE_DIRTY:
15222
case LogFileOperationRecord::WRITE_INIT_MBYTE:
15225
case LogFileOperationRecord::ACTIVE_WRITE_LOG:
15228
case LogFileOperationRecord::FIRST_PAGE_WRITE_IN_LOGFILE:
15231
case LogFileOperationRecord::WRITE_SR_INVALIDATE_PAGES:
15233
systemErrorLab(signal, __LINE__);
15240
sprintf(msg, "File system write failed during LogFileOperationRecord state %d", (Uint32)lfoPtr.p->lfoState);
15241
fsRefError(signal,__LINE__,msg);
15243
}//Dblqh::execFSWRITEREF()
15246
/* ========================================================================= */
15247
/* ======= INITIATE WHEN RECEIVING FSOPENCONF ======= */
15249
/* ========================================================================= */
15250
void Dblqh::initFsopenconf(Signal* signal)
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()
15261
/* ========================================================================= */
15262
/* ======= INITIATE WHEN RECEIVING FSREADCONF AND FSWRITECONF ======= */
15264
/* ========================================================================= */
15265
void Dblqh::initFsrwconf(Signal* signal, bool write)
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);
15280
ndbassert(totPages > 0);
15284
Uint32 bytesWritten = totPages * 32768;
15285
logPartPtr.p->m_io_tracker.complete_io(bytesWritten);
15290
logP.p->logPageWord[ZPOS_IN_WRITING]= 0;
15291
logP.p->logPageWord[ZPOS_IN_FREE_LIST]= 0;
15292
if (noPages == totPages)
15295
logP.i= logP.p->logPageWord[ZNEXT_PAGE];
15297
logP.i= lfoPtr.p->logPageArray[noPages];
15298
ptrCheckGuard(logP, clogPageFileSize, logPageRecord);
15302
}//Dblqh::initFsrwconf()
15304
/* ######################################################################### */
15305
/* NORMAL OPERATION MODULE */
15306
/* THIS MODULE IS A SUB-MODULE OF THE FILE SYSTEM HANDLING. */
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)
15317
LogPageRecordPtr origLogPagePtr;
15318
Uint32 wordWritten;
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) {
15329
if (true) // less merge conflicts
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) {
15344
/*---------------------------------------------------------------------------*/
15345
/* THIS IS THE LAST PAGE IN THIS MBYTE. WRITE NEXT LOG AND SWITCH TO NEXT */
15347
/*---------------------------------------------------------------------------*/
15348
changeMbyte(signal);
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],
15361
ndbrequire(wordWritten < ZPAGE_SIZE);
15362
if (logFilePtr.p->noLogpagesInBuffer > 0) {
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;
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
/*---------------------------------------------------------------------------*/
15383
releaseLogpage(signal);
15386
writeSinglePage(signal, logFilePtr.p->currentFilepage,
15387
wordWritten, __LINE__);
15388
lfoPtr.p->lfoState = LogFileOperationRecord::ACTIVE_WRITE_LOG;
15395
logPartPtr.p->logTimer++;
15397
}//Dblqh::timeSup()
15399
void Dblqh::writeLogfileLab(Signal* signal)
15401
/*---------------------------------------------------------------------------*/
15402
/* CHECK IF ANY GLOBAL CHECKPOINTS ARE COMPLETED DUE TO THIS COMPLETED DISK */
15404
/*---------------------------------------------------------------------------*/
15405
switch (logFilePtr.p->fileChangeState) {
15406
case LogFileRecord::NOT_ONGOING:
15408
checkGcpCompleted(signal,
15409
((lfoPtr.p->lfoPageNo + lfoPtr.p->noPagesRw) - 1),
15410
lfoPtr.p->lfoWordWritten);
15413
case LogFileRecord::BOTH_WRITES_ONGOING:
15415
ndbout_c("not crashing!!");
15418
case LogFileRecord::WRITE_PAGE_ZERO_ONGOING:
15419
case LogFileRecord::LAST_WRITE_ONGOING:
15421
logFilePtr.p->lastPageWritten = (lfoPtr.p->lfoPageNo + lfoPtr.p->noPagesRw) - 1;
15422
logFilePtr.p->lastWordWritten = lfoPtr.p->lfoWordWritten;
15426
systemErrorLab(signal, __LINE__);
15430
releaseLfoPages(signal);
15431
releaseLfo(signal);
15433
}//Dblqh::writeLogfileLab()
15435
void Dblqh::closeWriteLogLab(Signal* signal)
15437
logFilePtr.p->logFileStatus = LogFileRecord::CLOSED;
15439
}//Dblqh::closeWriteLogLab()
15441
/* ######################################################################### */
15442
/* FILE CHANGE MODULE */
15443
/* THIS MODULE IS A SUB-MODULE OF THE FILE SYSTEM HANDLING. */
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 */
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*/
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)
15467
releaseLfo(signal);
15468
/*---------------------------------------------------------------------------*/
15469
/* RELEASE PAGE ZERO IF THE FILE IS NOT FILE 0. */
15470
/*---------------------------------------------------------------------------*/
15471
Uint32 fileNo = logFilePtr.p->fileNo;
15474
releaseLogpage(signal);
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) {
15485
/*---------------------------------------------------------------------------*/
15486
/* THE LAST WRITE WAS STILL ONGOING. */
15487
/*---------------------------------------------------------------------------*/
15488
logFilePtr.p->fileChangeState = LogFileRecord::LAST_WRITE_ONGOING;
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;
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__);
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 */
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;
15527
}//Dblqh::firstPageWriteLab()
15529
void Dblqh::lastWriteInFileLab(Signal* signal)
15531
LogFileRecordPtr locLogFilePtr;
15532
/*---------------------------------------------------------------------------*/
15533
/* CHECK IF ANY GLOBAL CHECKPOINTS ARE COMPLETED DUE TO THIS COMPLETED DISK */
15535
/*---------------------------------------------------------------------------*/
15536
checkGcpCompleted(signal,
15537
((lfoPtr.p->lfoPageNo + lfoPtr.p->noPagesRw) - 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) {
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 */
15554
/*---------------------------------------------------------------------------*/
15555
/* WE WILL CLOSE THE FILE. */
15556
/*---------------------------------------------------------------------------*/
15557
logFilePtr.p->logFileStatus = LogFileRecord::CLOSING_WRITE_LOG;
15558
closeFile(signal, logFilePtr, __LINE__);
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) {
15575
/*---------------------------------------------------------------------------*/
15576
/* THE FIRST WRITE WAS STILL ONGOING. */
15577
/*---------------------------------------------------------------------------*/
15578
logFilePtr.p->fileChangeState = LogFileRecord::FIRST_WRITE_ONGOING;
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;
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__);
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 */
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;
15617
}//Dblqh::lastWriteInFileLab()
15619
void Dblqh::writePageZeroLab(Signal* signal, Uint32 from)
15621
if ((logPartPtr.p->m_log_problems & LogPartRecord::P_FILE_CHANGE_PROBLEM)!= 0)
15624
update_log_problem(signal, logPartPtr,
15625
LogPartRecord::P_FILE_CHANGE_PROBLEM,
15626
/* clear */ false);
15629
logFilePtr.p->fileChangeState = LogFileRecord::NOT_ONGOING;
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);
15641
gcpPtr.i = ccurrentGcprec;
15642
ptrCheckGuard(gcpPtr, cgcprecFileSize, gcpRecord);
15644
infoEvent("KESO completing GCP %u in writePageZeroLab from %u",
15645
gcpPtr.p->gcpId, from);
15648
}//Dblqh::writePageZeroLab()
15650
/* ######################################################################### */
15651
/* INITIAL START MODULE */
15652
/* THIS MODULE IS A SUB-MODULE OF THE FILE SYSTEM HANDLING. */
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)
15660
logFilePtr.p->logFileStatus = LogFileRecord::OPEN_INIT;
15661
seizeLogpage(signal);
15662
if (m_use_om_init == 0)
15665
initLogpage(signal);
15666
writeSinglePage(signal, (clogFileSize * ZPAGES_IN_MBYTE) - 1,
15667
ZPAGE_SIZE - 1, __LINE__, false);
15668
lfoPtr.p->lfoState = LogFileOperationRecord::INIT_WRITE_AT_END;
15674
initWriteEndLab(signal);
15677
}//Dblqh::openFileInitLab()
15679
void Dblqh::initWriteEndLab(Signal* signal)
15681
releaseLfo(signal);
15682
initLogpage(signal);
15683
if (logFilePtr.p->fileNo == 0) {
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;
15695
/*---------------------------------------------------------------------------*/
15696
/* REUSE CODE FOR INITIALISATION OF FIRST PAGE IN ALL LOG FILES. */
15697
/*---------------------------------------------------------------------------*/
15698
writeFileHeaderOpen(signal, ZINIT);
15700
}//Dblqh::initWriteEndLab()
15702
void Dblqh::initFirstPageLab(Signal* signal)
15704
releaseLfo(signal);
15705
if (logFilePtr.p->fileNo == 0) {
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;
15719
logFilePtr.p->currentMbyte = 1;
15720
writeInitMbyte(signal);
15722
}//Dblqh::initFirstPageLab()
15724
void Dblqh::writeGciZeroLab(Signal* signal)
15726
releaseLfo(signal);
15727
logFilePtr.p->currentMbyte = 1;
15728
writeInitMbyte(signal);
15730
}//Dblqh::writeGciZeroLab()
15732
void Dblqh::writeInitMbyteLab(Signal* signal)
15734
releaseLfo(signal);
15735
logFilePtr.p->currentMbyte = logFilePtr.p->currentMbyte + 1;
15736
if (logFilePtr.p->currentMbyte == clogFileSize) {
15738
releaseLogpage(signal);
15739
logFilePtr.p->logFileStatus = LogFileRecord::CLOSING_INIT;
15740
closeFile(signal, logFilePtr, __LINE__);
15743
writeInitMbyte(signal);
15745
}//Dblqh::writeInitMbyteLab()
15747
void Dblqh::closingInitLab(Signal* signal)
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) {
15754
checkInitCompletedLab(signal);
15758
logFilePtr.i = logFilePtr.p->nextLogFile;
15759
ptrCheckGuard(logFilePtr, clogFileFileSize, logFileRecord);
15760
openLogfileInit(signal);
15763
}//Dblqh::closingInitLab()
15765
void Dblqh::checkInitCompletedLab(Signal* signal)
15767
logPartPtr.p->logPartState = LogPartRecord::SR_FIRST_PHASE_COMPLETED;
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;
15775
if (m_use_om_init && ++logPartPtr.i != clogPartFileSize)
15778
ptrAss(logPartPtr, logPartRecord);
15779
logFilePtr.i = logPartPtr.p->firstLogfile;
15780
ptrCheckGuard(logFilePtr, clogFileFileSize, logFileRecord);
15781
openLogfileInit(signal);
15785
for (logPartPtr.i = 0; logPartPtr.i < clogPartFileSize; logPartPtr.i++)
15788
ptrAss(logPartPtr, logPartRecord);
15789
if (logPartPtr.p->logPartState != LogPartRecord::SR_FIRST_PHASE_COMPLETED)
15792
/*---------------------------------------------------------------------------*/
15793
/* THIS PART HAS STILL NOT COMPLETED. WAIT FOR THIS TO OCCUR. */
15794
/*---------------------------------------------------------------------------*/
15800
enable_global_variables();
15802
logfileInitCompleteReport(signal);
15803
sendNdbSttorryLab(signal);
15806
/* ========================================================================= */
15807
/* ======= INITIATE LOG FILE OPERATION RECORD WHEN ALLOCATED ======= */
15809
/* ========================================================================= */
15810
void Dblqh::initLfo(Signal* signal)
15812
lfoPtr.p->firstLfoPage = RNIL;
15813
lfoPtr.p->lfoState = LogFileOperationRecord::IDLE;
15814
lfoPtr.p->logFileRec = logFilePtr.i;
15815
lfoPtr.p->noPagesRw = 0;
15816
lfoPtr.p->lfoPageNo = ZNIL;
15817
}//Dblqh::initLfo()
15819
/* ========================================================================= */
15820
/* ======= INITIATE LOG FILE WHEN ALLOCATED ======= */
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)
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;
15861
}//Dblqh::initLogfile()
15863
/* ========================================================================= */
15864
/* ======= INITIATE LOG PAGE WHEN ALLOCATED ======= */
15866
/* ========================================================================= */
15867
void Dblqh::initLogpage(Signal* signal)
15869
TcConnectionrecPtr ilpTcConnectptr;
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) {
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);
15887
logPagePtr.p->logPageWord[ZLAST_LOG_PREP_REF] =
15888
(logFilePtr.p->fileNo << 16) +
15889
(logFilePtr.p->currentFilepage >> ZTWOLOG_NO_PAGES_IN_MBYTE);
15891
}//Dblqh::initLogpage()
15893
/* ------------------------------------------------------------------------- */
15894
/* ------- OPEN LOG FILE FOR READ AND WRITE ------- */
15896
/* SUBROUTINE SHORT NAME = OFR */
15897
/* ------------------------------------------------------------------------- */
15898
void Dblqh::openFileRw(Signal* signal,
15899
LogFileRecordPtr olfLogFilePtr,
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;
15911
signal->theData[6] |= FsOpenReq::OM_DIRECT;
15913
signal->theData[6] |= FsOpenReq::OM_WRITE_BUFFER;
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()
15923
/* ------------------------------------------------------------------------- */
15924
/* ------- OPEN LOG FILE DURING INITIAL START ------- */
15926
/* SUBROUTINE SHORT NAME = OLI */
15927
/* ------------------------------------------------------------------------- */
15928
void Dblqh::openLogfileInit(Signal* signal)
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;
15940
signal->theData[6] |= FsOpenReq::OM_DIRECT;
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;
15949
signal->theData[6] |= FsOpenReq::OM_INIT;
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()
15957
Dblqh::execFSWRITEREQ(Signal* signal)
15960
* This is currently run in other thread -> no jam
15961
* and no global variables
15963
Ptr<GlobalPage> page_ptr;
15964
FsReadWriteReq* req= (FsReadWriteReq*)signal->getDataPtr();
15965
m_shared_page_pool.getPtr(page_ptr, req->data.pageData[0]);
15967
LogFileRecordPtr currLogFilePtr;
15968
currLogFilePtr.i = req->userPointer;
15969
ptrCheckGuard(currLogFilePtr, clogFileFileSize, logFileRecord);
15971
LogPartRecordPtr currLogPartPtr;
15972
currLogPartPtr.i = currLogFilePtr.p->logPartRec;
15973
ptrCheckGuard(currLogPartPtr, clogPartFileSize, logPartRecord);
15975
Uint32 page_no = req->varIndex;
15976
LogPageRecordPtr currLogPagePtr;
15977
currLogPagePtr.p = (LogPageRecord*)page_ptr.p;
15979
bzero(page_ptr.p, sizeof(LogPageRecord));
15982
// keep writing these afterwards
15984
else if (((page_no % ZPAGES_IN_MBYTE) == 0) ||
15985
(page_no == ((clogFileSize * ZPAGES_IN_MBYTE) - 1)))
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);
15999
currLogPagePtr.p->logPageWord[ZNEXT_PAGE] = RNIL;
16000
currLogPagePtr.p->logPageWord[ZPOS_CHECKSUM] =
16001
calcPageCheckSum(currLogPagePtr);
16005
currLogPagePtr.p->logPageWord[ZNEXT_PAGE] = RNIL;
16006
currLogPagePtr.p->logPageWord[ZPOS_CHECKSUM] =
16007
calcPageCheckSum(currLogPagePtr);
16011
/* OPEN FOR READ/WRITE, DO CREATE AND DO TRUNCATE FILE */
16012
/* ------------------------------------------------------------------------- */
16013
/* ------- OPEN NEXT LOG FILE ------- */
16015
/* SUBROUTINE SHORT NAME = ONL */
16016
/* ------------------------------------------------------------------------- */
16017
void Dblqh::openNextLogfile(Signal* signal)
16019
LogFileRecordPtr onlLogFilePtr;
16021
if (logPartPtr.p->noLogFiles > 2) {
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);
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;
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);
16052
}//Dblqh::openNextLogfile()
16054
/* OPEN FOR READ/WRITE, DON'T CREATE AND DON'T TRUNCATE FILE */
16055
/* ------------------------------------------------------------------------- */
16056
/* ------- RELEASE LFO RECORD ------- */
16058
/* ------------------------------------------------------------------------- */
16059
void Dblqh::releaseLfo(Signal* signal)
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;
16071
lfoPtr.p->nextLfo = cfirstfreeLfo;
16072
lfoPtr.p->lfoTimer = 0;
16073
cfirstfreeLfo = lfoPtr.i;
16074
lfoPtr.p->lfoState = LogFileOperationRecord::IDLE;
16075
}//Dblqh::releaseLfo()
16077
/* ------------------------------------------------------------------------- */
16078
/* ------- RELEASE ALL LOG PAGES CONNECTED TO A LFO RECORD ------- */
16080
/* SUBROUTINE SHORT NAME = RLP */
16081
/* ------------------------------------------------------------------------- */
16082
void Dblqh::releaseLfoPages(Signal* signal)
16084
logPagePtr.i = lfoPtr.p->firstLfoPage;
16085
while (logPagePtr.i != RNIL)
16087
ptrCheckGuard(logPagePtr, clogPageFileSize, logPageRecord);
16088
Uint32 tmp = logPagePtr.p->logPageWord[ZNEXT_PAGE];
16089
releaseLogpage(signal);
16090
logPagePtr.i = tmp;
16092
lfoPtr.p->firstLfoPage = RNIL;
16093
}//Dblqh::releaseLfoPages()
16095
/* ------------------------------------------------------------------------- */
16096
/* ------- RELEASE LOG PAGE ------- */
16098
/* ------------------------------------------------------------------------- */
16099
void Dblqh::releaseLogpage(Signal* signal)
16102
// Check that log page isn't already in free list
16103
ndbrequire(logPagePtr.p->logPageWord[ZPOS_IN_FREE_LIST] == 0);
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()
16113
/* ------------------------------------------------------------------------- */
16114
/* ------- SEIZE LFO RECORD ------- */
16116
/* ------------------------------------------------------------------------- */
16117
void Dblqh::seizeLfo(Signal* signal)
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()
16126
/* ------------------------------------------------------------------------- */
16127
/* ------- SEIZE LOG FILE RECORD ------- */
16129
/* ------------------------------------------------------------------------- */
16130
void Dblqh::seizeLogfile(Signal* signal)
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()
16141
/* ------------------------------------------------------------------------- */
16142
/* ------- SEIZE LOG PAGE RECORD ------- */
16144
/* ------------------------------------------------------------------------- */
16145
void Dblqh::seizeLogpage(Signal* signal)
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];
16155
bzero(logPagePtr.p, sizeof(LogPageRecord));
16157
logPagePtr.p->logPageWord[ZNEXT_PAGE] = RNIL;
16158
logPagePtr.p->logPageWord[ZPOS_IN_FREE_LIST] = 0;
16159
}//Dblqh::seizeLogpage()
16161
/* ------------------------------------------------------------------------- */
16162
/* ------- WRITE FILE DESCRIPTOR INFORMATION ------- */
16164
/* SUBROUTINE SHORT NAME: WFD */
16165
// Pointer handling:
16168
/* ------------------------------------------------------------------------- */
16169
void Dblqh::writeFileDescriptor(Signal* signal)
16171
TcConnectionrecPtr wfdTcConnectptr;
16175
/* -------------------------------------------------- */
16176
/* START BY WRITING TO LOG FILE RECORD */
16177
/* -------------------------------------------------- */
16178
arrGuard(logFilePtr.p->currentMbyte, clogFileSize);
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,
16188
logFilePtr.p->currentMbyte);
16189
if (logPartPtr.p->firstLogTcrec == RNIL)
16191
ndbout_c("file: %u mb: %u (RNIL)",
16192
logFilePtr.p->fileNo,
16193
logFilePtr.p->currentMbyte);
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);
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) {
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;
16217
logFilePtr.p->logLastPrepRef[logFilePtr.p->currentMbyte] =
16218
(logFilePtr.p->fileNo << 16) + logFilePtr.p->currentMbyte;
16220
}//Dblqh::writeFileDescriptor()
16222
/* ------------------------------------------------------------------------- */
16223
/* ------- WRITE THE HEADER PAGE OF A NEW FILE ------- */
16225
/* SUBROUTINE SHORT NAME: WMO */
16226
/* ------------------------------------------------------------------------- */
16227
void Dblqh::writeFileHeaderOpen(Signal* signal, Uint32 wmoType)
16229
UintR twmoNoLogDescriptors;
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) {
16239
twmoNoLogDescriptors = cmaxLogFilesInPageZero;
16242
twmoNoLogDescriptors = logPartPtr.p->noLogFiles;
16244
logPagePtr.p->logPageWord[ZPAGE_HEADER_SIZE + ZPOS_NO_FD] =
16245
twmoNoLogDescriptors;
16248
Uint32 pos = ZPAGE_HEADER_SIZE + ZFD_HEADER_SIZE;
16249
LogFileRecordPtr filePtr = logFilePtr;
16250
for (Uint32 fd = 0; fd < twmoNoLogDescriptors; fd++)
16253
ptrCheckGuard(filePtr, clogFileFileSize, logFileRecord);
16254
for (Uint32 mb = 0; mb < clogFileSize; mb ++)
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];
16267
filePtr.i = filePtr.p->prevLogFile;
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;
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) {
16282
writeSinglePage(signal, 0, ZPAGE_SIZE - 1, __LINE__, false);
16283
lfoPtr.p->lfoState = LogFileOperationRecord::INIT_FIRST_PAGE;
16286
writeSinglePage(signal, 0, ZPAGE_SIZE - 1, __LINE__, true);
16287
lfoPtr.p->lfoState = LogFileOperationRecord::FIRST_PAGE_WRITE_IN_LOGFILE;
16289
logFilePtr.p->filePosition = 1;
16290
if (wmoType == ZNORMAL) {
16292
/* -------------------------------------------------- */
16293
/* ALLOCATE A NEW PAGE SINCE THE CURRENT IS */
16295
/* -------------------------------------------------- */
16296
seizeLogpage(signal);
16297
initLogpage(signal);
16298
logFilePtr.p->currentLogpage = logPagePtr.i;
16299
logFilePtr.p->currentFilepage = logFilePtr.p->currentFilepage + 1;
16301
}//Dblqh::writeFileHeaderOpen()
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 ------- */
16310
/* SUBROUTINE SHORT NAME: WIM */
16311
/* ------------------------------------------------------------------------- */
16312
void Dblqh::writeInitMbyte(Signal* signal)
16314
if (m_use_om_init == 0)
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);
16327
logFilePtr.p->currentMbyte = clogFileSize - 1;
16328
writeInitMbyteLab(signal);
16330
}//Dblqh::writeInitMbyte()
16332
/* ------------------------------------------------------------------------- */
16333
/* ------- WRITE A SINGLE PAGE INTO A FILE ------- */
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,
16344
lfoPtr.p->firstLfoPage = logPagePtr.i;
16345
logPagePtr.p->logPageWord[ZNEXT_PAGE] = RNIL;
16347
writeDbgInfoPageHeader(logPagePtr, place, pageNo, wordWritten);
16348
// Calculate checksum for page
16349
logPagePtr.p->logPageWord[ZPOS_CHECKSUM] = calcPageCheckSum(logPagePtr);
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);
16369
ndbrequire(logFilePtr.p->fileRef != RNIL);
16371
logPartPtr.p->m_io_tracker.send_io(32768);
16375
ndbout_c("writeSingle 1 page at part: %u file: %u page: %u (mb: %u)",
16376
logPartPtr.p->logPartNo,
16377
logFilePtr.p->fileNo,
16379
pageNo >> ZTWOLOG_NO_PAGES_IN_MBYTE);
16381
}//Dblqh::writeSinglePage()
16383
/* ##########################################################################
16384
* SYSTEM RESTART PHASE ONE MODULE
16385
* THIS MODULE IS A SUB-MODULE OF THE FILE SYSTEM HANDLING.
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
16397
* -------------------------------------------------------------------------- */
16398
void Dblqh::openSrFrontpageLab(Signal* signal)
16400
readSinglePage(signal, 0);
16401
lfoPtr.p->lfoState = LogFileOperationRecord::READ_SR_FRONTPAGE;
16403
}//Dblqh::openSrFrontpageLab()
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)
16413
Uint32 fileNo = logPagePtr.p->logPageWord[ZPAGE_HEADER_SIZE + ZPOS_FILE_NO];
16416
/* ----------------------------------------------------------------------
16417
* FILE 0 WAS ALSO LAST FILE SO WE DO NOT NEED TO READ IT AGAIN.
16418
* ---------------------------------------------------------------------- */
16419
readSrLastFileLab(signal);
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);
16434
}//Dblqh::readSrFrontpageLab()
16436
void Dblqh::openSrLastFileLab(Signal* signal)
16438
readSinglePage(signal, 0);
16439
lfoPtr.p->lfoState = LogFileOperationRecord::READ_SR_LAST_FILE;
16441
}//Dblqh::openSrLastFileLab()
16443
void Dblqh::readSrLastFileLab(Signal* signal)
16445
logPartPtr.p->logLap = logPagePtr.p->logPageWord[ZPOS_LOG_LAP];
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);
16454
if (logPartPtr.p->noLogFiles > cmaxLogFilesInPageZero) {
16456
initGciInLogFileRec(signal, cmaxLogFilesInPageZero);
16459
initGciInLogFileRec(signal, logPartPtr.p->noLogFiles);
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;
16471
}//Dblqh::readSrLastFileLab()
16473
void Dblqh::readSrLastMbyteLab(Signal* signal)
16475
if (logPartPtr.p->lastMbyte == ZNIL)
16477
if (logPagePtr.p->logPageWord[ZPOS_LOG_LAP] < logPartPtr.p->logLap) {
16479
logPartPtr.p->lastMbyte = logFilePtr.p->currentMbyte - 1;
16482
ndbout_c("readSrLastMbyteLab part: %u file: %u lastMbyte: %u",
16483
logPartPtr.p->logPartNo,
16484
logFilePtr.p->fileNo,
16485
logPartPtr.p->lastMbyte);
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)) {
16499
logFilePtr.p->currentMbyte++;
16500
readSinglePage(signal, ZPAGES_IN_MBYTE * logFilePtr.p->currentMbyte);
16501
lfoPtr.p->lfoState = LogFileOperationRecord::READ_SR_LAST_MBYTE;
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) {
16511
logPartPtr.p->lastMbyte = clogFileSize - 1;
16514
logFilePtr.p->logFileStatus = LogFileRecord::CLOSING_SR;
16515
closeFile(signal, logFilePtr, __LINE__);
16516
if (logPartPtr.p->noLogFiles > cmaxLogFilesInPageZero) {
16518
if (logFilePtr.p->fileNo >= cmaxLogFilesInPageZero) {
16520
fileNo = logFilePtr.p->fileNo - cmaxLogFilesInPageZero;
16524
(logPartPtr.p->noLogFiles + logFilePtr.p->fileNo) -
16525
cmaxLogFilesInPageZero;
16529
/* --------------------------------------------------------------------
16530
* AVOID USING FILE 0 AGAIN SINCE THAT IS PROBABLY CLOSING AT THE
16532
* -------------------------------------------------------------------- */
16534
logPartPtr.p->srRemainingFiles =
16535
logPartPtr.p->noLogFiles - (cmaxLogFilesInPageZero - 1);
16538
logPartPtr.p->srRemainingFiles =
16539
logPartPtr.p->noLogFiles - cmaxLogFilesInPageZero;
16541
LogFileRecordPtr locLogFilePtr;
16542
findLogfile(signal, fileNo, logPartPtr, &locLogFilePtr);
16543
locLogFilePtr.p->logFileStatus = LogFileRecord::OPEN_SR_NEXT_FILE;
16544
openFileRw(signal, locLogFilePtr);
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
* ------------------------------------------------------------------------ */
16553
}//Dblqh::readSrLastMbyteLab()
16555
void Dblqh::openSrNextFileLab(Signal* signal)
16557
readSinglePage(signal, 0);
16558
lfoPtr.p->lfoState = LogFileOperationRecord::READ_SR_NEXT_FILE;
16560
}//Dblqh::openSrNextFileLab()
16562
void Dblqh::readSrNextFileLab(Signal* signal)
16564
if (logPartPtr.p->srRemainingFiles > cmaxLogFilesInPageZero) {
16566
initGciInLogFileRec(signal, cmaxLogFilesInPageZero);
16569
initGciInLogFileRec(signal, logPartPtr.p->srRemainingFiles);
16571
releaseLogpage(signal);
16572
logFilePtr.p->logFileStatus = LogFileRecord::CLOSING_SR;
16573
closeFile(signal, logFilePtr, __LINE__);
16574
if (logPartPtr.p->srRemainingFiles > cmaxLogFilesInPageZero) {
16576
if (logFilePtr.p->fileNo >= cmaxLogFilesInPageZero) {
16578
fileNo = logFilePtr.p->fileNo - cmaxLogFilesInPageZero;
16582
(logPartPtr.p->noLogFiles + logFilePtr.p->fileNo) -
16583
cmaxLogFilesInPageZero;
16587
/* --------------------------------------------------------------------
16588
* AVOID USING FILE 0 AGAIN SINCE THAT IS PROBABLY CLOSING AT THE MOMENT.
16589
* -------------------------------------------------------------------- */
16591
logPartPtr.p->srRemainingFiles =
16592
logPartPtr.p->srRemainingFiles - (cmaxLogFilesInPageZero - 1);
16595
logPartPtr.p->srRemainingFiles =
16596
logPartPtr.p->srRemainingFiles - cmaxLogFilesInPageZero;
16598
LogFileRecordPtr locLogFilePtr;
16599
findLogfile(signal, fileNo, logPartPtr, &locLogFilePtr);
16600
locLogFilePtr.p->logFileStatus = LogFileRecord::OPEN_SR_NEXT_FILE;
16601
openFileRw(signal, locLogFilePtr);
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
* ------------------------------------------------------------------------ */
16609
}//Dblqh::readSrNextFileLab()
16611
void Dblqh::closingSrLab(Signal* signal)
16613
logFilePtr.p->logFileStatus = LogFileRecord::CLOSED;
16614
logPartPtr.i = logFilePtr.p->logPartRec;
16615
ptrCheckGuard(logPartPtr, clogPartFileSize, logPartRecord);
16616
logFilePtr.i = logPartPtr.p->firstLogfile;
16619
ptrCheckGuard(logFilePtr, clogFileFileSize, logFileRecord);
16620
if (logFilePtr.p->logFileStatus != LogFileRecord::CLOSED) {
16622
/* --------------------------------------------------------------------
16623
* EXIT AND WAIT FOR REMAINING LOG FILES TO COMPLETE THEIR WORK.
16624
* -------------------------------------------------------------------- */
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
* ------------------------------------------------------------------------ */
16634
logPartPtr.p->logPartState = LogPartRecord::SR_FIRST_PHASE_COMPLETED;
16635
for (logPartPtr.i = 0; logPartPtr.i < clogPartFileSize; logPartPtr.i++) {
16637
ptrAss(logPartPtr, logPartRecord);
16638
if (logPartPtr.p->logPartState != LogPartRecord::SR_FIRST_PHASE_COMPLETED) {
16640
/* --------------------------------------------------------------------
16641
* EXIT AND WAIT FOR THE REST OF THE LOG PARTS TO COMPLETE.
16642
* -------------------------------------------------------------------- */
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);
16653
}//Dblqh::closingSrLab()
16655
/* ##########################################################################
16656
* ####### SYSTEM RESTART PHASE TWO MODULE #######
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
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)
16673
const StartFragReq * const startFragReq = (StartFragReq *)&signal->theData[0];
16676
tabptr.i = startFragReq->tableId;
16677
Uint32 fragId = startFragReq->fragId;
16679
ptrCheckGuard(tabptr, ctabrecFileSize, tablerec);
16680
if (!getFragmentrec(signal, fragId)) {
16681
startFragRefLab(signal);
16684
tabptr.p->tableStatus = Tablerec::TABLE_DEFINED;
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)
16693
requestInfo = StartFragReq::SFR_RESTORE_LCP;
16696
bool doprint = false;
16697
#ifdef ERROR_INSERT
16699
* Always printSTART_FRAG_REQ (for debugging) if ERROR_INSERT is set
16703
if (doprint || noOfLogNodes > 1)
16705
printSTART_FRAG_REQ(stdout, signal->getDataPtr(), signal->getLength(),
16709
ndbrequire(noOfLogNodes <= MAX_LOG_EXEC);
16710
fragptr.p->fragStatus = Fragrecord::CRASH_RECOVERING;
16711
fragptr.p->srBlockref = startFragReq->userRef;
16712
fragptr.p->srUserptr = startFragReq->userPtr;
16713
fragptr.p->srChkpnr = lcpNo;
16714
if (lcpNo == (MAX_LCP_STORED - 1)) {
16716
fragptr.p->lcpId[lcpNo] = lcpId;
16717
} else if (lcpNo < (MAX_LCP_STORED - 1)) {
16719
fragptr.p->lcpId[lcpNo] = lcpId;
16721
ndbrequire(lcpNo == ZNIL);
16724
fragptr.p->srNoLognodes = noOfLogNodes;
16725
fragptr.p->logFlag = Fragrecord::STATE_FALSE;
16726
fragptr.p->srStatus = Fragrecord::SS_IDLE;
16728
if (requestInfo == StartFragReq::SFR_COPY_FRAG)
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));
16734
// Magic no, meaning to COPY_FRAGREQ instead of read from disk
16735
fragptr.p->srChkpnr = Z8NIL;
16738
if (noOfLogNodes > 0)
16741
for (Uint32 i = 0; i < noOfLogNodes; i++) {
16743
fragptr.p->srStartGci[i] = startFragReq->startGci[i];
16744
fragptr.p->srLastGci[i] = startFragReq->lastGci[i];
16745
fragptr.p->srLqhLognode[i] = startFragReq->lqhLogNode[i];
16747
fragptr.p->newestGci = startFragReq->lastGci[noOfLogNodes - 1];
16753
* This is a really weird piece of code
16754
* it's probably incorrect, but seems to mask problems...
16756
if (cnewestGci > fragptr.p->newestGci)
16759
fragptr.p->newestGci = cnewestGci;
16763
if (requestInfo == StartFragReq::SFR_COPY_FRAG)
16767
else if (lcpNo == ZNIL)
16771
* THERE WAS NO LOCAL CHECKPOINT AVAILABLE FOR THIS FRAGMENT. WE DO
16772
* NOT NEED TO READ IN THE LOCAL FRAGMENT.
16775
* Or this is not "first" fragment in table
16776
* RESTORE_LCP_REQ will currently restore all fragments
16778
c_lcp_complete_fragments.add(fragptr);
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);
16791
c_tup->disk_restart_lcp_id(tabptr.i, fragId, lcpId);
16794
if (ERROR_INSERTED(5055))
16796
ndbrequire(c_lcpId == 0 || lcpId == 0 || c_lcpId == lcpId);
16800
* Keep track of minimal lcp-id
16802
c_lcpId = (c_lcpId == 0 ? lcpId : c_lcpId);
16803
c_lcpId = (c_lcpId < lcpId ? c_lcpId : lcpId);
16806
c_lcp_waiting_fragments.add(fragptr);
16807
if(c_lcp_restoring_fragments.isEmpty())
16808
send_restore_lcp(signal);
16809
}//Dblqh::execSTART_FRAGREQ()
16812
Dblqh::send_restore_lcp(Signal * signal)
16814
c_lcp_waiting_fragments.first(fragptr);
16815
c_lcp_waiting_fragments.remove(fragptr);
16816
c_lcp_restoring_fragments.add(fragptr);
16818
if (fragptr.p->srChkpnr != Z8NIL)
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);
16836
tabptr.i = fragptr.p->tabRef;
16837
ptrCheckGuard(tabptr, ctabrecFileSize, tablerec);
16839
fragptr.p->fragStatus = Fragrecord::ACTIVE_CREATION;
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]);
16855
sendSignal(ref, GSN_COPY_FRAGREQ, signal,
16856
CopyFragReq::SignalLength, JBB);
16861
Dblqh::execCOPY_FRAGREF(Signal* signal)
16865
const CopyFragRef * ref = CAST_CONSTPTR(CopyFragRef, signal->getDataPtr());
16866
Uint32 errorCode = ref->errorCode;
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);
16878
Dblqh::execCOPY_FRAGCONF(Signal* signal)
16882
const CopyFragConf* conf = CAST_CONSTPTR(CopyFragConf,
16883
signal->getDataPtr());
16884
c_fragment_pool.getPtr(fragptr, conf->senderData);
16885
fragptr.p->fragStatus = Fragrecord::CRASH_RECOVERING;
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);
16901
RestoreLcpConf* conf= (RestoreLcpConf*)signal->getDataPtr();
16902
conf->senderData = fragptr.i;
16903
execRESTORE_LCP_CONF(signal);
16907
void Dblqh::startFragRefLab(Signal* signal)
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);
16917
}//Dblqh::startFragRefLab()
16919
void Dblqh::execRESTORE_LCP_REF(Signal* signal)
16926
void Dblqh::execRESTORE_LCP_CONF(Signal* signal)
16929
RestoreLcpConf* conf= (RestoreLcpConf*)signal->getDataPtr();
16930
fragptr.i = conf->senderData;
16931
c_fragment_pool.getPtr(fragptr);
16933
c_lcp_restoring_fragments.remove(fragptr);
16934
c_lcp_complete_fragments.add(fragptr);
16937
* Disable expand check in ACC
16938
* before running REDO
16940
tabptr.i = fragptr.p->tabRef;
16941
ptrCheckGuard(tabptr, ctabrecFileSize, tablerec);
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);
16948
if (!c_lcp_waiting_fragments.isEmpty())
16950
send_restore_lcp(signal);
16954
if (c_lcp_restoring_fragments.isEmpty() &&
16955
cstartRecReq == SRR_START_REC_REQ_ARRIVED)
16958
/* ----------------------------------------------------------------
16959
* WE HAVE ALSO RECEIVED AN INDICATION THAT NO MORE FRAGMENTS
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;
16969
ptrAss(lcpPtr, lcpRecord);
16970
lcpPtr.p->m_outstanding = 1;
16972
if (cstartType == NodeState::ST_INITIAL_NODE_RESTART)
16976
* Skip lgman undo...
16978
signal->theData[0] = LGMAN_REF;
16979
sendSignal(reference(), GSN_START_RECCONF, signal, 1, JBB);
16986
signal->theData[0] = c_lcpId;
16987
sendSignal(LGMAN_REF, GSN_START_RECREQ, signal, 1, JBB);
16992
signal->theData[0] = c_lcpId;
16993
signal->theData[1] = LGMAN;
16994
sendSignal(DBLQH_REF, GSN_START_RECREQ, signal, 2, JBB);
17000
/* ***************> */
17001
/* START_RECREQ > */
17002
/* ***************> */
17003
void Dblqh::execSTART_RECREQ(Signal* signal)
17005
CRASH_INSERTION(5027);
17008
StartRecReq * const req = (StartRecReq*)&signal->theData[0];
17009
cmasterDihBlockref = req->senderRef;
17011
crestartOldestGci = req->keepGci;
17012
crestartNewestGci = req->lastCompletedGci;
17013
cnewestGci = req->newestGci;
17014
cstartRecReqData = req->senderData;
17016
if (check_ndb_versions())
17018
ndbrequire(crestartOldestGci <= crestartNewestGci);
17021
ndbrequire(req->receivingNodeId == cownNodeid);
17023
cnewestCompletedGci = cnewestGci;
17024
cstartRecReq = SRR_START_REC_REQ_ARRIVED; // StartRecReq has arrived
17026
if (signal->getLength() == StartRecReq::SignalLength)
17029
NdbNodeBitmask tmp;
17030
tmp.assign(NdbNodeBitmask::Size, req->sr_nodes);
17031
if (!tmp.equal(m_sr_nodes))
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));
17039
m_sr_nodes.assign(NdbNodeBitmask::Size, req->sr_nodes);
17044
cstartRecReqData = RNIL;
17047
for (logPartPtr.i = 0; logPartPtr.i < clogPartFileSize; logPartPtr.i++) {
17048
ptrAss(logPartPtr, logPartRecord);
17049
logPartPtr.p->logPartNewestCompletedGCI = cnewestCompletedGci;
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
*------------------------------------------------------------------------ */
17059
if (c_lcp_restoring_fragments.isEmpty())
17062
csrExecUndoLogState = EULS_STARTED;
17065
ptrAss(lcpPtr, lcpRecord);
17066
lcpPtr.p->m_outstanding = 1;
17068
if (cstartType == NodeState::ST_INITIAL_NODE_RESTART)
17072
* Skip lgman undo...
17074
signal->theData[0] = LGMAN_REF;
17075
sendSignal(reference(), GSN_START_RECCONF, signal, 1, JBB);
17082
signal->theData[0] = c_lcpId;
17083
sendSignal(LGMAN_REF, GSN_START_RECREQ, signal, 1, JBB);
17088
signal->theData[0] = c_lcpId;
17089
signal->theData[1] = LGMAN;
17090
sendSignal(DBLQH_REF, GSN_START_RECREQ, signal, 2, JBB);
17093
}//Dblqh::execSTART_RECREQ()
17095
/* ***************>> */
17096
/* START_RECCONF > */
17097
/* ***************>> */
17098
void Dblqh::execSTART_RECCONF(Signal* signal)
17102
ptrAss(lcpPtr, lcpRecord);
17103
ndbrequire(csrExecUndoLogState == EULS_STARTED);
17104
ndbrequire(lcpPtr.p->m_outstanding);
17106
Uint32 sender= signal->theData[0];
17108
if (ERROR_INSERTED(5055))
17110
CLEAR_ERROR_INSERT_VALUE;
17113
lcpPtr.p->m_outstanding--;
17114
if(lcpPtr.p->m_outstanding)
17120
switch(refToBlock(sender)){
17126
lcpPtr.p->m_outstanding++;
17130
signal->theData[0] = c_lcpId;
17131
sendSignal(TSMAN_REF, GSN_START_RECREQ, signal, 1, JBB);
17136
signal->theData[0] = c_lcpId;
17137
signal->theData[1] = TSMAN;
17138
sendSignal(DBLQH_REF, GSN_START_RECREQ, signal, 2, JBB);
17147
csrExecUndoLogState = EULS_COMPLETED;
17149
if(cstartType == NodeState::ST_INITIAL_NODE_RESTART)
17152
cstartRecReq = SRR_REDO_COMPLETE; // REDO complete
17154
rebuildOrderedIndexes(signal, 0);
17158
startExecSr(signal);
17161
/* ***************> */
17162
/* START_RECREF > */
17163
/* ***************> */
17164
void Dblqh::execSTART_RECREF(Signal* signal)
17168
}//Dblqh::execSTART_RECREF()
17171
Dblqh::rebuildOrderedIndexes(Signal* signal, Uint32 tableId)
17178
infoEvent("LQH: Starting to rebuild ordered indexes");
17181
if (tableId >= ctabrecFileSize)
17185
for (logPartPtr.i = 0; logPartPtr.i < clogPartFileSize; logPartPtr.i++)
17188
ptrCheckGuard(logPartPtr, clogPartFileSize, logPartRecord);
17189
LogFileRecordPtr logFile;
17190
logFile.i = logPartPtr.p->currentLogfile;
17191
ptrCheckGuard(logFile, clogFileFileSize, logFileRecord);
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)
17200
update_log_problem(signal, logPartPtr,
17201
LogPartRecord::P_TAIL_PROBLEM, true);
17208
* There should be no disk-ops in flight here...check it
17210
signal->theData[0] = 12003;
17211
sendSignal(LGMAN_REF, GSN_DUMP_STATE_ORD, signal, 1, JBB);
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);
17220
infoEvent("LQH: Rebuild ordered indexes complete");
17224
tabptr.i = tableId;
17225
ptrCheckGuard(tabptr, ctabrecFileSize, tablerec);
17226
if (! (DictTabInfo::isOrderedIndex(tabptr.p->tableType) &&
17227
tabptr.p->tableStatus == Tablerec::TABLE_DEFINED))
17230
signal->theData[0] = ZREBUILD_ORDERED_INDEXES;
17231
signal->theData[1] = tableId + 1;
17232
sendSignal(reference(), GSN_CONTINUEB, signal, 2, JBB);
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);
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
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);
17257
Dblqh::execBUILD_INDX_IMPL_REF(Signal * signal)
17260
ndbrequire(false); // TODO error message
17264
Dblqh::execBUILD_INDX_IMPL_CONF(Signal* signal)
17267
BuildIndxImplConf * conf = (BuildIndxImplConf*)signal->getDataPtr();
17268
Uint32 tableId = conf->senderData;
17269
rebuildOrderedIndexes(signal, tableId + 1);
17270
infoEvent("LQH: index %u rebuild done", tableId);
17273
/* ***************>> */
17274
/* START_EXEC_SR > */
17275
/* ***************>> */
17276
void Dblqh::execSTART_EXEC_SR(Signal* signal)
17279
fragptr.i = signal->theData[0];
17280
Uint32 next = RNIL;
17282
if (fragptr.i == RNIL)
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;
17297
NodeReceiverGroup rg(DBLQH, m_sr_nodes);
17298
sendSignal(rg, GSN_EXEC_SRREQ, signal, 1, JBB);
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);
17310
c_lcp_complete_fragments.getPtr(fragptr);
17311
next = fragptr.p->nextList;
17313
if (fragptr.p->srNoLognodes > csrPhasesCompleted)
17316
cnoOutstandingExecFragReq++;
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;
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;
17342
// send via local proxy
17343
sendSignal(DBLQH_REF, GSN_EXEC_FRAGREQ, signal,
17344
ExecFragReq::SignalLength, JBB);
17346
else if (ndb_route_exec_frag(getNodeInfo(refToNode(ref)).m_version))
17349
// send via remote proxy
17350
sendSignal(numberToRef(DBLQH, refToNode(ref)), GSN_EXEC_FRAGREQ, signal,
17351
ExecFragReq::SignalLength, JBB);
17357
sendSignal(ref, GSN_EXEC_FRAGREQ, signal,
17358
ExecFragReq::SignalLength, JBB);
17361
signal->theData[0] = next;
17362
sendSignal(cownref, GSN_START_EXEC_SR, signal, 1, JBB);
17365
}//Dblqh::execSTART_EXEC_SR()
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)
17376
ExecFragReq * const execFragReq = (ExecFragReq *)&signal->theData[0];
17378
tabptr.i = execFragReq->tableId;
17379
Uint32 fragId = execFragReq->fragId;
17380
ptrCheckGuard(tabptr, ctabrecFileSize, tablerec);
17381
ndbrequire(getFragmentrec(signal, fragId));
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++;
17392
}//Dblqh::execEXEC_FRAGREQ()
17394
void Dblqh::sendExecFragRefLab(Signal* signal)
17396
ExecFragReq * const execFragReq = (ExecFragReq *)&signal->theData[0];
17397
BlockReference retRef = execFragReq->userRef;
17398
Uint32 retPtr = execFragReq->userPtr;
17400
signal->theData[0] = retPtr;
17401
signal->theData[1] = terrorCode;
17402
sendSignal(retRef, GSN_EXEC_FRAGREF, signal, 2, JBB);
17404
}//Dblqh::sendExecFragRefLab()
17406
/* ***************>> */
17407
/* EXEC_FRAGCONF > */
17408
/* ***************>> */
17409
void Dblqh::execEXEC_FRAGCONF(Signal* signal)
17412
fragptr.i = signal->theData[0];
17413
c_fragment_pool.getPtr(fragptr);
17414
fragptr.p->srStatus = Fragrecord::SS_COMPLETED;
17416
ndbrequire(cnoOutstandingExecFragReq);
17417
cnoOutstandingExecFragReq--;
17418
if (fragptr.p->srNoLognodes == csrPhasesCompleted + 1)
17422
fragptr.p->logFlag = Fragrecord::STATE_TRUE;
17423
fragptr.p->fragStatus = Fragrecord::FSACTIVE;
17425
signal->theData[0] = fragptr.p->srUserptr;
17426
signal->theData[1] = cownNodeid;
17427
sendSignal(fragptr.p->srBlockref, GSN_START_FRAGCONF, signal, 2, JBB);
17431
}//Dblqh::execEXEC_FRAGCONF()
17433
/* ***************> */
17434
/* EXEC_FRAGREF > */
17435
/* ***************> */
17436
void Dblqh::execEXEC_FRAGREF(Signal* signal)
17439
terrorCode = signal->theData[1];
17440
systemErrorLab(signal, __LINE__);
17442
}//Dblqh::execEXEC_FRAGREF()
17444
/* *************** */
17445
/* EXEC_SRCONF > */
17446
/* *************** */
17447
void Dblqh::execEXEC_SRCONF(Signal* signal)
17450
Uint32 nodeId = signal->theData[0];
17451
arrGuard(nodeId, MAX_NDB_NODES);
17452
m_sr_exec_sr_conf.set(nodeId);
17454
if (!m_sr_nodes.equal(m_sr_exec_sr_conf))
17457
/* ------------------------------------------------------------------
17458
* ALL NODES HAVE NOT REPORTED COMPLETION OF EXECUTING FRAGMENT
17460
* ----------------------------------------------------------------- */
17464
if (cnoOutstandingExecFragReq != 0)
17467
* This should now have been fixed!
17468
* but could occur during upgrade
17469
* old: wl4391_todo workaround until timing fixed
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());
17480
/* ------------------------------------------------------------------------
17481
* CLEAR NODE SYSTEM RESTART EXECUTION STATE TO PREPARE FOR NEXT PHASE OF
17483
* ----------------------------------------------------------------------- */
17484
m_sr_exec_sr_conf.clear();
17485
cnoFragmentsExecSr = 0;
17487
/* ------------------------------------------------------------------------
17488
* NOW CHECK IF ALL FRAGMENTS IN THIS PHASE HAVE COMPLETED. IF SO START THE
17490
* ----------------------------------------------------------------------- */
17491
ndbrequire(cnoOutstandingExecFragReq == 0);
17493
execSrCompletedLab(signal);
17495
}//Dblqh::execEXEC_SRCONF()
17497
void Dblqh::execSrCompletedLab(Signal* signal)
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) {
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
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++) {
17520
ptrAss(logPartPtr, logPartRecord);
17521
logPartPtr.p->logPartState = LogPartRecord::SR_FOURTH_PHASE_STARTED;
17522
logPartPtr.p->logLastGci = crestartNewestGci;
17523
logPartPtr.p->logStartGci = crestartOldestGci;
17524
logPartPtr.p->logExecState = LogPartRecord::LES_SEARCH_STOP;
17525
if (logPartPtr.p->headFileNo == ZNIL) {
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__);
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);
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);
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);
17563
}//Dblqh::execSrCompletedLab()
17565
/* ************>> */
17567
/* ************>> */
17568
void Dblqh::execEXEC_SRREQ(Signal* signal)
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))
17580
/* ------------------------------------------------------------------------
17581
* CLEAR NODE SYSTEM RESTART STATE TO PREPARE FOR NEXT PHASE OF LOG
17583
* ----------------------------------------------------------------------- */
17584
m_sr_exec_sr_req.clear();
17586
if (csrPhasesCompleted != 0) {
17587
/* ----------------------------------------------------------------------
17588
* THE FIRST PHASE MUST ALWAYS EXECUTE THE LOG.
17589
* --------------------------------------------------------------------- */
17590
if (cnoFragmentsExecSr == 0) {
17592
/* --------------------------------------------------------------------
17593
* THERE WERE NO FRAGMENTS THAT NEEDED TO EXECUTE THE LOG IN THIS PHASE.
17594
* ------------------------------------------------------------------- */
17595
srPhase3Comp(signal);
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.
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);
17610
}//Dblqh::execEXEC_SRREQ()
17612
/* ######################################################################### */
17613
/* SYSTEM RESTART PHASE THREE MODULE */
17614
/* THIS MODULE IS A SUB-MODULE OF THE FILE SYSTEM HANDLING. */
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. */
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 */
17627
/*---------------------------------------------------------------------------*/
17628
void Dblqh::srPhase3Start(Signal* signal)
17630
UintR tsrPhaseStarted;
17634
tsrPhaseStarted = signal->theData[1];
17635
if (csrPhaseStarted == ZSR_NO_PHASE_STARTED) {
17637
csrPhaseStarted = tsrPhaseStarted;
17640
ndbrequire(csrPhaseStarted != tsrPhaseStarted);
17641
ndbrequire(csrPhaseStarted != ZSR_BOTH_PHASES_STARTED);
17643
csrPhaseStarted = ZSR_BOTH_PHASES_STARTED;
17644
for (logPartPtr.i = 0; logPartPtr.i < clogPartFileSize; logPartPtr.i++) {
17646
ptrAss(logPartPtr, logPartRecord);
17647
logPartPtr.p->logPartState = LogPartRecord::SR_THIRD_PHASE_STARTED;
17648
logPartPtr.p->logStartGci = (UintR)-1;
17649
if (csrPhasesCompleted == 0) {
17651
/* --------------------------------------------------------------------
17652
* THE FIRST PHASE WE MUST ENSURE THAT IT REACHES THE END OF THE LOG.
17653
* ------------------------------------------------------------------- */
17654
logPartPtr.p->logLastGci = crestartNewestGci;
17657
logPartPtr.p->logLastGci = 2;
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);
17667
}//Dblqh::srPhase3Start()
17669
/* --------------------------------------------------------------------------
17670
* WE NOW WE NEED TO FIND THE LIMITS WITHIN WHICH TO EXECUTE
17672
* ------------------------------------------------------------------------- */
17673
void Dblqh::srGciLimits(Signal* signal)
17676
fragptr.i = signal->theData[0];
17677
Uint32 loopCount = 0;
17679
ptrAss(logPartPtr, logPartRecord);
17680
while (fragptr.i != RNIL){
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++) {
17686
if (fragptr.p->execSrStartGci[i] < logPartPtr.p->logStartGci) {
17688
logPartPtr.p->logStartGci = fragptr.p->execSrStartGci[i];
17690
if (fragptr.p->execSrLastGci[i] > logPartPtr.p->logLastGci) {
17692
logPartPtr.p->logLastGci = fragptr.p->execSrLastGci[i];
17697
if (loopCount > 20) {
17699
signal->theData[0] = ZSR_GCI_LIMITS;
17700
signal->theData[1] = fragptr.p->nextList;
17701
sendSignal(cownref, GSN_CONTINUEB, signal, 2, JBB);
17705
fragptr.i = fragptr.p->nextList;
17709
if (logPartPtr.p->logStartGci == (UintR)-1) {
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;
17719
for(Uint32 i = 1; i < clogPartFileSize; i++)
17721
LogPartRecordPtr tmp;
17723
ptrAss(tmp, logPartRecord);
17724
tmp.p->logStartGci = logPartPtr.p->logStartGci;
17725
tmp.p->logLastGci = logPartPtr.p->logLastGci;
17728
for (logPartPtr.i = 0; logPartPtr.i < clogPartFileSize; logPartPtr.i++) {
17730
ptrAss(logPartPtr, logPartRecord);
17731
logPartPtr.p->logExecState = LogPartRecord::LES_SEARCH_STOP;
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);
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);
17747
}//Dblqh::srGciLimits()
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)
17756
Uint32 tlastPrepRef;
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
17769
* ----------------------------------------------------------------------- */
17771
ndbrequire(tmbyte < clogFileSize);
17772
if (logPartPtr.p->logExecState == LogPartRecord::LES_SEARCH_STOP)
17774
if (logFilePtr.p->logMaxGciCompleted[tmbyte] <= logPartPtr.p->logLastGci)
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
17782
* ------------------------------------------------------------------ */
17783
logPartPtr.p->stopLogfile = logFilePtr.i;
17784
logPartPtr.p->stopMbyte = tmbyte;
17785
logPartPtr.p->logExecState = LogPartRecord::LES_SEARCH_START;
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,
17792
logFilePtr.p->logMaxGciCompleted[tmbyte],
17793
logPartPtr.p->logLastGci);
17796
else if (DEBUG_REDO)
17798
ndbout_c("SEARCH STOP SKIP part: %u file: %u mb: %u "
17799
"logMaxGciCompleted: %u > %u",
17800
logPartPtr.p->logPartNo,
17801
logFilePtr.p->fileNo,
17803
logFilePtr.p->logMaxGciCompleted[tmbyte],
17804
logPartPtr.p->logLastGci);
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)
17816
if (logFilePtr.p->logMaxGciStarted[tmbyte] < logPartPtr.p->logStartGci)
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
* ------------------------------------------------------------------ */
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,
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);
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;
17844
else if (DEBUG_REDO)
17846
ndbout_c("SEARCH START SKIP part: %u file: %u mb: %u "
17847
"logMaxGciCompleted: %u >= %u",
17848
logPartPtr.p->logPartNo,
17849
logFilePtr.p->fileNo,
17851
logFilePtr.p->logMaxGciStarted[tmbyte],
17852
logPartPtr.p->logStartGci);
17855
if (logPartPtr.p->logExecState != LogPartRecord::LES_EXEC_LOG) {
17858
tmbyte = clogFileSize - 1;
17859
logFilePtr.i = logFilePtr.p->prevLogFile;
17860
ptrCheckGuard(logFilePtr, clogFileFileSize, logFileRecord);
17865
if (logPartPtr.p->lastLogfile == logFilePtr.i) {
17866
ndbrequire(logPartPtr.p->lastMbyte != tmbyte);
17868
if (loopCount > 20) {
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);
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,
17896
logPartPtr.p->stopMbyte);
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) {
17908
logFilePtr.i = logPartPtr.p->startLogfile;
17909
ptrCheckGuard(logFilePtr, clogFileFileSize, logFileRecord);
17910
logFilePtr.p->logFileStatus = LogFileRecord::OPEN_EXEC_SR_START;
17911
openFileRw(signal, logFilePtr);
17912
send_runredo_event(signal, logPartPtr.p, logPartPtr.p->logStartGci);
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);
17936
}//Dblqh::srLogLimits()
17938
void Dblqh::openExecSrStartLab(Signal* signal)
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
* ------------------------------------------------------------------------ */
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);
17956
}//Dblqh::openExecSrStartLab()
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.
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)
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) {
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 *
17990
logPartPtr.p->prevFilepage = logFilePtr.p->currentFilepage;
17991
logFilePtr.p->currentLogpage = lfoPtr.p->firstLfoPage;
17992
logPartPtr.p->prevLogpage = logFilePtr.p->currentLogpage;
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) {
18003
signal->theData[0] = ZEXEC_SR;
18004
signal->theData[1] = logPartPtr.i;
18005
sendSignal(cownref, GSN_CONTINUEB, signal, 2, JBB);
18009
}//Dblqh::readExecSrLab()
18011
void Dblqh::openExecSrNewMbyteLab(Signal* signal)
18013
readExecSrNewMbyte(signal);
18015
}//Dblqh::openExecSrNewMbyteLab()
18017
void Dblqh::closeExecSrLab(Signal* signal)
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);
18028
}//Dblqh::closeExecSrLab()
18030
void Dblqh::writeDirtyLab(Signal* signal)
18032
releaseLfo(signal);
18033
signal->theData[0] = logPartPtr.i;
18036
}//Dblqh::writeDirtyLab()
18038
/* --------------------------------------------------------------------------
18039
* EXECUTE A LOG RECORD WITHIN THE CURRENT MBYTE.
18040
* ------------------------------------------------------------------------- */
18041
void Dblqh::execSr(Signal* signal)
18043
LogFileRecordPtr nextLogFilePtr;
18044
LogPageRecordPtr tmpLogPagePtr;
18047
const char * crash_msg = 0;
18050
logPartPtr.i = signal->theData[0];
18051
ptrCheckGuard(logPartPtr, clogPartFileSize, logPartRecord);
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) {
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:
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__);
18073
case LogPartRecord::LES_EXEC_LOG:
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) {
18081
writeDirty(signal, __LINE__);
18090
if (logFilePtr.p->currentLogpage != logPartPtr.p->prevLogpage) {
18092
logPartPtr.p->prevLogpage = logPagePtr.p->logPageWord[ZNEXT_PAGE];
18093
logPartPtr.p->prevFilepage++;
18096
switch (logPartPtr.p->logExecState) {
18097
case LogPartRecord::LES_EXEC_LOG_COMPLETED:
18099
releaseMmPages(signal);
18100
logFilePtr.p->logFileStatus = LogFileRecord::CLOSING_EXEC_SR_COMPLETED;
18101
closeFile(signal, logFilePtr, __LINE__);
18104
case LogPartRecord::LES_EXEC_LOG_NEW_MBYTE:
18106
logFilePtr.p->currentMbyte++;
18107
readExecSrNewMbyte(signal);
18110
case LogPartRecord::LES_EXEC_LOG_NEW_FILE:
18112
nextLogFilePtr.i = logFilePtr.p->nextLogFile;
18113
logPartPtr.p->currentLogfile = nextLogFilePtr.i;
18114
ptrCheckGuard(nextLogFilePtr, clogFileFileSize, logFileRecord);
18115
nextLogFilePtr.p->currentMbyte = 0;
18116
logFilePtr.p->logFileStatus = LogFileRecord::CLOSING_EXEC_SR;
18117
closeFile(signal, logFilePtr, __LINE__);
18120
case LogPartRecord::LES_EXEC_LOG:
18126
systemErrorLab(signal, __LINE__);
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) {
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;
18152
logWord = readLogword(signal);
18154
/* ========================================================================= */
18155
/* ========================================================================= */
18156
case ZPREP_OP_TYPE:
18158
logWord = readLogword(signal);
18159
stepAhead(signal, logWord - 2);
18162
/* ========================================================================= */
18163
/* ========================================================================= */
18164
case ZINVALID_COMMIT_TYPE:
18166
stepAhead(signal, ZCOMMIT_LOG_SIZE - 1);
18168
/* ========================================================================= */
18169
/* ========================================================================= */
18172
CommitLogRecord commitLogRecord;
18174
tcConnectptr.i = logPartPtr.p->logTcConrec;
18175
ptrCheckGuard(tcConnectptr, ctcConnectrecFileSize, tcConnectionrec);
18176
readCommitLog(signal, &commitLogRecord);
18177
if (tcConnectptr.p->gci_hi > crestartNewestGci) {
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;
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 */
18196
/*---------------------------------------------------------------------------*/
18197
logPartPtr.p->execSrExecuteIndex = 0;
18198
Uint32 result = checkIfExecLog(signal);
18199
if (result == ZOK) {
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) {
18212
logPagePtr.p->logPageWord[ZCURR_PAGE_INDEX] = commitLogRecord.startPageIndex;
18213
logPartPtr.p->execSrLogPage = logPagePtr.i;
18214
execLogRecord(signal);
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) {
18223
#ifndef NO_REDO_PAGE_CACHE
18225
logPartPtr.p->execSrStopPageNo - logPartPtr.p->execSrStartPageNo;
18226
evict(m_redo_page_cache, cnt);
18228
readExecLog(signal);
18229
lfoPtr.p->lfoState = LogFileOperationRecord::READ_EXEC_LOG;
18233
/*---------------------------------------------------------------------------*/
18234
/* THE FILE IS CURRENTLY NOT OPEN. WE MUST OPEN IT BEFORE WE CAN READ FROM */
18236
/*---------------------------------------------------------------------------*/
18237
#ifndef NO_REDO_OPEN_FILE_CACHE
18238
openFileRw_cache(signal, logFilePtr);
18240
logFilePtr.p->logFileStatus = LogFileRecord::OPEN_EXEC_LOG;
18241
openFileRw(signal, logFilePtr);
18249
/* ========================================================================= */
18250
/* ========================================================================= */
18253
stepAhead(signal, ZABORT_LOG_SIZE - 1);
18255
/* ========================================================================= */
18256
/* ========================================================================= */
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*/
18266
/*---------------------------------------------------------------------------*/
18267
if (unlikely(logPagePtr.p->logPageWord[ZCURR_PAGE_INDEX] !=
18268
(ZPAGE_HEADER_SIZE + ZPOS_NO_FD)))
18271
logWord = logPagePtr.p->logPageWord[ZCURR_PAGE_INDEX];
18272
crash_msg = "ZFD_TYPE at incorrect position!";
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);
18283
/* ========================================================================= */
18284
/* ========================================================================= */
18285
case ZNEXT_LOG_RECORD_TYPE:
18287
stepAhead(signal, ZPAGE_SIZE - logPagePtr.p->logPageWord[ZCURR_PAGE_INDEX]);
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) {
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
/*---------------------------------------------------------------------------*/
18312
logWord = ZNEXT_MBYTE_TYPE;
18313
crash_msg = "end of log wo/ having found last GCI";
18317
/*---------------------------------------------------------------------------*/
18318
/* START EXECUTION OF A NEW MBYTE IN THE LOG. */
18319
/*---------------------------------------------------------------------------*/
18320
if (logFilePtr.p->currentMbyte < (clogFileSize - 1)) {
18322
logPartPtr.p->logExecState = LogPartRecord::LES_EXEC_LOG_NEW_MBYTE;
18324
ndbrequire(logFilePtr.p->currentMbyte == (clogFileSize - 1));
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;
18332
/* ========================================================================= */
18333
/* ========================================================================= */
18334
case ZCOMPLETED_GCI_TYPE:
18336
logWord = readLogword(signal);
18339
ndbout_c("found gci: %u part: %u file: %u page: %u (mb: %u)",
18341
logPartPtr.p->logPartNo,
18342
logFilePtr.p->fileNo,
18343
logFilePtr.p->currentFilepage,
18344
logFilePtr.p->currentFilepage >> ZTWOLOG_NO_PAGES_IN_MBYTE);
18346
if (logWord == logPartPtr.p->logLastGci)
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 */
18353
/*---------------------------------------------------------------------------*/
18354
if (csrPhasesCompleted == 0) {
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];
18366
ndbout_c("execSr part: %u logLap: %u",
18367
logPartPtr.p->logPartNo, logPartPtr.p->logLap);
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);
18381
/* ========================================================================= */
18382
/* ========================================================================= */
18383
/*---------------------------------------------------------------------------*/
18384
/* SEND A SIGNAL TO THE SIGNAL LOG AND THEN CRASH THE SYSTEM. */
18385
/*---------------------------------------------------------------------------*/
18387
crash_msg = "Invalid logword";
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
/*---------------------------------------------------------------------------*/
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;
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);
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);
18434
progError(__LINE__, NDBD_EXIT_SR_REDOLOG, buf);
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)
18444
2.5 TEMPORARY VARIABLES
18445
-----------------------
18448
//logPagePtr.i = signal->theData[0];
18449
//tdebug = logPagePtr.p->logPageWord[0];
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]);
18459
progError(__LINE__, NDBD_EXIT_SR_REDOLOG, buf);
18462
}//Dblqh::execDEBUG_SIG()
18464
/*---------------------------------------------------------------------------*/
18465
/*---------------------------------------------------------------------------*/
18466
void Dblqh::closeExecLogLab(Signal* signal)
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);
18473
}//Dblqh::closeExecLogLab()
18475
void Dblqh::openExecLogLab(Signal* signal)
18477
#ifndef NO_REDO_PAGE_CACHE
18479
logPartPtr.p->execSrStopPageNo - logPartPtr.p->execSrStartPageNo;
18482
Uint32 MAX_EXTRA_READ = 9; // can be max 9 due to FSREADREQ formatting
18483
while (cnt < maxextraread && (logPartPtr.p->execSrStopPageNo % 32) != 31)
18487
logPartPtr.p->execSrStopPageNo++;
18491
evict(m_redo_page_cache, cnt);
18494
readExecLog(signal);
18495
lfoPtr.p->lfoState = LogFileOperationRecord::READ_EXEC_LOG;
18497
}//Dblqh::openExecLogLab()
18499
void Dblqh::readExecLogLab(Signal* signal)
18501
buildLinkedLogPageList(signal);
18502
#ifndef NO_REDO_PAGE_CACHE
18503
addCachePages(m_redo_page_cache,
18504
logPartPtr.p->logPartNo,
18505
logPartPtr.p->execSrStartPageNo,
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);
18515
}//Dblqh::readExecLogLab()
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)
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;
18531
// Read a log record and prepare it for execution
18532
readLogHeader(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);
18544
}//Dblqh::execLogRecord()
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
//----------------------------------------------------------------------------
18553
Dblqh::nextLogFilePtr(Uint32 logFilePtrI)
18555
LogFileRecordPtr tmp;
18556
tmp.i = logFilePtrI;
18557
ptrCheckGuard(tmp, clogFileFileSize, logFileRecord);
18558
return tmp.p->nextLogFile;
18562
Dblqh::invalidateLogAfterLastGCI(Signal* signal)
18565
if (logPartPtr.p->logExecState != LogPartRecord::LES_EXEC_LOG_INVALIDATE) {
18567
systemError(signal, __LINE__);
18570
if (logFilePtr.p->fileNo != logPartPtr.p->invalidateFileNo) {
18572
systemError(signal, __LINE__);
18575
switch (lfoPtr.p->lfoState) {
18576
case LogFileOperationRecord::READ_SR_INVALIDATE_SEARCH_FILES:
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);
18587
// This page must be invalidated.
18588
// We search next file
18589
readFileInInvalidate(signal, 3);
18596
* This file doest not need to be invalidated...move to previous
18597
* file and search forward linear
18599
readFileInInvalidate(signal, 6);
18604
case LogFileOperationRecord::READ_SR_INVALIDATE_PAGES:
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
18611
if (logPagePtr.p->logPageWord[ZPOS_LOG_LAP] == logPartPtr.p->logLap)
18614
// This page must be invalidated.
18615
// We search for end
18617
releaseLfo(signal);
18618
releaseLogpage(signal);
18619
readFileInInvalidate(signal, 1);
18624
* We found the "last" page to invalidate...
18625
* Invalidate backwards until head...
18629
case LogFileOperationRecord::WRITE_SR_INVALIDATE_PAGES:
18632
releaseLfo(signal);
18633
releaseLogpage(signal);
18635
// Step backwards...
18636
logPartPtr.p->invalidatePageNo--;
18638
if (logPartPtr.p->invalidatePageNo == 0)
18642
if (logFilePtr.p->fileNo == 0)
18646
* We're wrapping in the log...
18649
logPartPtr.p->logLap--;
18650
ndbrequire(logPartPtr.p->logLap); // Should always be > 0
18653
ndbout_c("invalidateLogAfterLastGCI part: %u wrap from file 0 -> logLap: %u",
18654
logPartPtr.p->logPartNo, logPartPtr.p->logLap);
18658
if (invalidateCloseFile(signal, logPartPtr, logFilePtr,
18659
LogFileRecord::CLOSE_SR_WRITE_INVALIDATE_PAGES))
18664
writeFileInInvalidate(signal, 1); // step prev
18667
writeFileInInvalidate(signal, 0);
18670
jamLine(lfoPtr.p->lfoState);
18676
Dblqh::writeFileInInvalidate(Signal* signal, int stepPrev)
18679
* Move to prev file
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;
18690
if (logPartPtr.p->invalidateFileNo == logPartPtr.p->headFileNo &&
18691
logPartPtr.p->invalidatePageNo == logPartPtr.p->headPageNo)
18697
logFilePtr.i = logPartPtr.p->currentLogfile;
18698
ptrCheckGuard(logFilePtr, clogFileFileSize, logFileRecord);
18700
logFilePtr.i = logFilePtr.p->nextLogFile;
18701
ptrCheckGuard(logFilePtr, clogFileFileSize, logFileRecord);
18703
exitFromInvalidate(signal);
18707
if (stepPrev == 1 && logFilePtr.p->logFileStatus != LogFileRecord::OPEN)
18712
ndbout_c("invalidate part: %u open for write %u",
18713
logPartPtr.p->logPartNo, logFilePtr.p->fileNo);
18715
logFilePtr.p->logFileStatus =LogFileRecord::OPEN_SR_WRITE_INVALIDATE_PAGES;
18716
openFileRw(signal, logFilePtr);
18720
seizeLogpage(signal);
18723
* Make page really empty
18725
bzero(logPagePtr.p, sizeof(LogPageRecord));
18726
writeSinglePage(signal, logPartPtr.p->invalidatePageNo,
18727
ZPAGE_SIZE - 1, __LINE__);
18729
lfoPtr.p->lfoState = LogFileOperationRecord::WRITE_SR_INVALIDATE_PAGES;
18731
}//Dblqh::invalidateLogAfterLastGCI
18734
Dblqh::invalidateCloseFile(Signal* signal,
18735
Ptr<LogPartRecord> partPtr,
18736
Ptr<LogFileRecord> filePtr,
18737
LogFileRecord::LogFileStatus status)
18740
if (filePtr.p->fileNo != 0 &&
18741
filePtr.i != partPtr.p->currentLogfile &&
18742
filePtr.i != nextLogFilePtr(logPartPtr.p->currentLogfile))
18747
ndbout_c("invalidate part: %u close %u(%u) state: %u (%u)",
18748
logPartPtr.p->logPartNo,
18749
logFilePtr.p->fileNo,
18752
logPartPtr.p->currentLogfile);
18754
filePtr.p->logFileStatus = status;
18755
closeFile(signal, filePtr, __LINE__);
18761
void Dblqh::readFileInInvalidate(Signal* signal, int stepNext)
18767
ndbout_c("readFileInInvalidate part: %u file: %u stepNext: %u",
18768
logPartPtr.p->logPartNo, logFilePtr.p->fileNo, stepNext);
18774
// Contact NDBFS. Real time break.
18775
readSinglePage(signal, logPartPtr.p->invalidatePageNo);
18776
lfoPtr.p->lfoState = LogFileOperationRecord::READ_SR_INVALIDATE_PAGES;
18783
logPartPtr.p->invalidatePageNo++;
18784
if (logPartPtr.p->invalidatePageNo == (clogFileSize * ZPAGES_IN_MBYTE))
18786
if (invalidateCloseFile(signal, logPartPtr, logFilePtr,
18787
LogFileRecord::CLOSE_SR_READ_INVALIDATE_PAGES))
18795
stepNext = 2; // After close
18801
// Contact NDBFS. Real time break.
18802
readSinglePage(signal, logPartPtr.p->invalidatePageNo);
18803
lfoPtr.p->lfoState = LogFileOperationRecord::READ_SR_INVALIDATE_PAGES;
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;
18818
if (logFilePtr.p->fileNo == 0)
18821
* We're wrapping in the log...
18824
logPartPtr.p->logLap++;
18827
ndbout_c("readFileInInvalidate part: %u step: %u wrap to file 0 -> logLap: %u",
18828
logPartPtr.p->logPartNo, stepNext, logPartPtr.p->logLap);
18833
if (logFilePtr.p->logFileStatus != LogFileRecord::OPEN)
18838
ndbout_c("invalidate part: %u step: %u open for read %u",
18839
logPartPtr.p->logPartNo, stepNext, logFilePtr.p->fileNo);
18841
logFilePtr.p->logFileStatus =LogFileRecord::OPEN_SR_READ_INVALIDATE_PAGES;
18842
openFileRw(signal, logFilePtr);
18846
// Contact NDBFS. Real time break.
18847
readSinglePage(signal, logPartPtr.p->invalidatePageNo);
18848
lfoPtr.p->lfoState = LogFileOperationRecord::READ_SR_INVALIDATE_PAGES;
18855
if (invalidateCloseFile
18856
(signal, logPartPtr, logFilePtr,
18857
LogFileRecord::CLOSE_SR_READ_INVALIDATE_SEARCH_FILES))
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;
18874
if (logFilePtr.p->fileNo == 0)
18877
* We're wrapping in the log...
18880
logPartPtr.p->logLap++;
18883
ndbout_c("readFileInInvalidate part: %u step: %u wrap to file 0 -> logLap: %u",
18884
logPartPtr.p->logPartNo, stepNext, logPartPtr.p->logLap);
18888
if (logFilePtr.p->logFileStatus != LogFileRecord::OPEN)
18893
ndbout_c("invalidate part: %u step: %u open for read %u",
18894
logPartPtr.p->logPartNo, stepNext, logFilePtr.p->fileNo);
18896
logFilePtr.p->logFileStatus =
18897
LogFileRecord::OPEN_SR_READ_INVALIDATE_SEARCH_FILES;
18898
openFileRw(signal, logFilePtr);
18907
// Contact NDBFS. Real time break.
18908
readSinglePage(signal, logPartPtr.p->invalidatePageNo);
18909
lfoPtr.p->lfoState =
18910
LogFileOperationRecord::READ_SR_INVALIDATE_SEARCH_FILES;
18917
if (invalidateCloseFile
18918
(signal, logPartPtr, logFilePtr,
18919
LogFileRecord::CLOSE_SR_READ_INVALIDATE_SEARCH_LAST_FILE))
18931
if (logFilePtr.p->fileNo == 0)
18935
* We're wrapping in the log...
18938
logPartPtr.p->logLap--;
18939
ndbrequire(logPartPtr.p->logLap); // Should always be > 0
18942
ndbout_c("invalidateLogAfterLastGCI part: %u step: %u wrap from file 0 -> logLap: %u",
18943
logPartPtr.p->logPartNo, stepNext, logPartPtr.p->logLap);
18947
logFilePtr.i = logFilePtr.p->prevLogFile;
18948
ptrCheckGuard(logFilePtr, clogFileFileSize, logFileRecord);
18950
logPartPtr.p->invalidateFileNo = logFilePtr.p->fileNo;
18951
// Page 0 is used for file descriptors.
18952
logPartPtr.p->invalidatePageNo = 1;
18954
if (logPartPtr.p->invalidateFileNo == logPartPtr.p->headFileNo)
18957
logPartPtr.p->invalidatePageNo = logPartPtr.p->headPageNo;
18959
if (! ((cstartType == NodeState::ST_INITIAL_START) ||
18960
(cstartType == NodeState::ST_INITIAL_NODE_RESTART)))
18963
if (logFilePtr.i == logPartPtr.p->lastLogfile)
18966
Uint32 lastMbytePageNo =
18967
logPartPtr.p->lastMbyte << ZTWOLOG_NO_PAGES_IN_MBYTE;
18968
if (logPartPtr.p->invalidatePageNo < lastMbytePageNo)
18973
ndbout_c("readFileInInvalidate part: %u step: %u moving invalidatePageNo from %u to %u (lastMbyte)",
18974
logPartPtr.p->logPartNo, stepNext,
18975
logPartPtr.p->invalidatePageNo,
18978
logPartPtr.p->invalidatePageNo = lastMbytePageNo;
18982
readFileInInvalidate(signal, 1);
18991
void Dblqh::exitFromInvalidate(Signal* signal)
18998
printf("exitFromInvalidate part: %u head file: %u page: %u open: ",
18999
logPartPtr.p->logPartNo,
19000
logPartPtr.p->headFileNo,
19001
logPartPtr.p->headPageNo);
19003
LogFileRecordPtr tmp;
19004
tmp.i = logPartPtr.p->currentLogfile;
19008
ptrCheckGuard(tmp, clogFileFileSize, logFileRecord);
19009
if (tmp.p->logFileStatus != LogFileRecord::LFS_IDLE &&
19010
tmp.p->logFileStatus != LogFileRecord::CLOSED)
19013
printf("%u ", tmp.p->fileNo);
19015
tmp.i = tmp.p->nextLogFile;
19016
} while (tmp.i != logPartPtr.p->currentLogfile && tmp.i != RNIL);
19019
tmp.i = logPartPtr.p->currentLogfile;
19020
ptrCheckGuard(tmp, clogFileFileSize, logFileRecord);
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,
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__);
19041
lfoPtr.p->logFileRec = logFilePtr.i;
19042
lfoPtr.p->lfoState = LogFileOperationRecord::WRITE_SR_INVALIDATE_PAGES_UPDATE_PAGE0;
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)
19052
Uint32 result = returnExecLog(signal);
19053
/*---------------------------------------------------------------------------*/
19054
/* ENTER COMPLETED WITH */
19055
/* LQH_CONNECTPTR */
19056
/*---------------------------------------------------------------------------*/
19057
if (result == ZOK) {
19059
execLogRecord(signal);
19061
} else if (result == ZNOT_OK) {
19063
signal->theData[0] = ZEXEC_SR;
19064
signal->theData[1] = logPartPtr.i;
19065
sendSignal(cownref, GSN_CONTINUEB, signal, 2, JBB);
19070
/*---------------------------------------------------------------------------*/
19071
/* WE HAVE TO WAIT FOR CLOSING OF THE EXECUTED LOG FILE BEFORE PROCEEDING IN */
19073
/*---------------------------------------------------------------------------*/
19075
}//Dblqh::completedLab()
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)
19083
Uint32 result = returnExecLog(signal);
19084
switch (tcConnectptr.p->operation) {
19088
if (unlikely(terrorCode != ZNO_TUPLE_FOUND))
19093
if (unlikely(terrorCode != ZTUPLE_ALREADY_EXIST && terrorCode != 899))
19101
if (result == ZOK) {
19103
execLogRecord(signal);
19105
} else if (result == ZNOT_OK) {
19107
signal->theData[0] = ZEXEC_SR;
19108
signal->theData[1] = logPartPtr.i;
19109
sendSignal(cownref, GSN_CONTINUEB, signal, 2, JBB);
19114
/* ------------------------------------------------------------------------
19115
* WE HAVE TO WAIT FOR CLOSING OF THE EXECUTED LOG FILE BEFORE
19116
* PROCEEDING IN RARE CASES.
19117
* ----------------------------------------------------------------------- */
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,
19130
progError(__LINE__, NDBD_EXIT_SYSTEM_ERROR,
19132
}//Dblqh::logLqhkeyrefLab()
19134
void Dblqh::closeExecSrCompletedLab(Signal* signal)
19136
logFilePtr.p->logFileStatus = LogFileRecord::CLOSED;
19137
signal->theData[0] = logFilePtr.p->logPartRec;
19138
execLogComp(signal);
19140
}//Dblqh::closeExecSrCompletedLab()
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)
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++) {
19160
ptrAss(logPartPtr, logPartRecord);
19161
if (logPartPtr.p->logPartState != LogPartRecord::SR_THIRD_PHASE_COMPLETED) {
19162
if (logPartPtr.p->logPartState != LogPartRecord::SR_THIRD_PHASE_STARTED) {
19164
systemErrorLab(signal, __LINE__);
19168
/* ------------------------------------------------------------------
19169
* THIS LOG PART WAS NOT COMPLETED YET. EXIT AND WAIT FOR IT
19171
* ----------------------------------------------------------------- */
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
* ----------------------------------------------------------------------- */
19182
#ifndef NO_REDO_PAGE_CACHE
19183
release(m_redo_page_cache);
19186
#ifndef NO_REDO_OPEN_FILE_CACHE
19187
release(signal, m_redo_open_file_cache);
19189
execLogComp_extra_files_closed(signal);
19194
Dblqh::execLogComp_extra_files_closed(Signal * signal)
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);
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)
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) {
19217
ndbrequire(fragptr.p->execSrNoReplicas - 1 < MAX_REPLICAS);
19218
for (Uint32 i = 0; i < fragptr.p->execSrNoReplicas; i++) {
19220
Uint32 ref = fragptr.p->execSrBlockref[i];
19221
signal->theData[0] = fragptr.p->execSrUserptr[i];
19226
// send via own proxy
19227
signal->theData[1] = ref;
19228
sendSignal(DBLQH_REF, GSN_EXEC_FRAGCONF, signal, 2, JBB);
19230
else if (refToInstance(ref) != 0 &&
19231
ndb_route_exec_frag(getNodeInfo(refToNode(ref)).m_version))
19234
// send via remote proxy
19235
signal->theData[1] = ref;
19236
sendSignal(numberToRef(refToMain(ref), refToNode(ref)),
19237
GSN_EXEC_FRAGCONF, signal, 2, JBB);
19243
sendSignal(ref, GSN_EXEC_FRAGCONF, signal, 1, JBB);
19246
fragptr.p->execSrNoReplicas = 0;
19249
if (loopCount > 20) {
19251
signal->theData[0] = ZSEND_EXEC_CONF;
19252
signal->theData[1] = next;
19253
sendSignal(cownref, GSN_CONTINUEB, signal, 2, JBB);
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()
19267
/* --------------------------------------------------------------------------
19268
* PHASE 3 HAS NOW COMPLETED. INFORM ALL OTHER NODES OF THIS EVENT.
19269
* ------------------------------------------------------------------------- */
19270
void Dblqh::srPhase3Comp(Signal* signal)
19274
signal->theData[0] = cownNodeid;
19278
NodeReceiverGroup rg(DBLQH, m_sr_nodes);
19279
sendSignal(rg, GSN_EXEC_SRCONF, signal, 1, JBB);
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);
19289
}//Dblqh::srPhase3Comp()
19291
/* ##########################################################################
19292
* SYSTEM RESTART PHASE FOUR MODULE
19293
* THIS MODULE IS A SUB-MODULE OF THE FILE SYSTEM HANDLING.
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
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
19303
* THIS PART IS ACTUALLY EXECUTED FOR ALL RESTART TYPES.
19304
* ######################################################################### */
19305
void Dblqh::initFourth(Signal* signal)
19307
LogFileRecordPtr locLogFilePtr;
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;
19319
logPartPtr.p->logPartState = LogPartRecord::SR_FOURTH_PHASE_STARTED;
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);
19327
}//Dblqh::initFourth()
19329
void Dblqh::openSrFourthPhaseLab(Signal* signal)
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;
19338
}//Dblqh::openSrFourthPhaseLab()
19340
void Dblqh::readSrFourthPhaseLab(Signal* signal)
19344
logPagePtr.p->logPageWord[ZPOS_LOG_LAP] = 1;
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)
19369
* If "keepGci" is bigger than latest-completed-gci
19370
* move cnewest/cnewestCompletedGci forward
19372
ndbout_c("readSrFourthPhaseLab: gci %u => %u",
19373
gci, crestartOldestGci);
19374
gci = crestartOldestGci;
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;
19388
initLogpage(signal);
19389
logPagePtr.p->logPageWord[ZCURR_PAGE_INDEX] = logPartPtr.p->headPageIndex;
19390
logFilePtr.p->remainingWordsInMbyte =
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;
19402
locLogFilePtr.i = logFilePtr.p->nextLogFile;
19403
ptrCheckGuard(locLogFilePtr, clogFileFileSize, logFileRecord);
19404
locLogFilePtr.p->logFileStatus = LogFileRecord::OPEN_SR_FOURTH_NEXT;
19405
openFileRw(signal, locLogFilePtr);
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);
19417
}//Dblqh::readSrFourthPhaseLab()
19419
void Dblqh::openSrFourthNextLab(Signal* signal)
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) {
19428
openSrFourthZeroSkipInitLab(signal);
19432
logFilePtr.p->logFileStatus = LogFileRecord::OPEN_SR_FOURTH_ZERO;
19433
openFileRw(signal, logFilePtr);
19436
}//Dblqh::openSrFourthNextLab()
19438
void Dblqh::openSrFourthZeroLab(Signal* signal)
19440
openSrFourthZeroSkipInitLab(signal);
19442
}//Dblqh::openSrFourthZeroLab()
19444
void Dblqh::openSrFourthZeroSkipInitLab(Signal* signal)
19446
if (logFilePtr.i == logPartPtr.p->currentLogfile) {
19447
if (logFilePtr.p->currentFilepage == 0) {
19449
/* -------------------------------------------------------------------
19450
* THE HEADER PAGE IN THE LOG IS PAGE ZERO IN FILE ZERO.
19451
* THIS SHOULD NEVER OCCUR.
19452
* ------------------------------------------------------------------- */
19453
systemErrorLab(signal, __LINE__);
19457
readSinglePage(signal, 0);
19458
lfoPtr.p->lfoState = LogFileOperationRecord::READ_SR_FOURTH_ZERO;
19460
}//Dblqh::openSrFourthZeroSkipInitLab()
19462
void Dblqh::readSrFourthZeroLab(Signal* signal)
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
// --------------------------------------------------------------------
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;
19480
readFileInInvalidate(signal, 3);
19482
}//Dblqh::readSrFourthZeroLab()
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)
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++) {
19496
ptrAss(logPartPtr, logPartRecord);
19497
if (logPartPtr.p->logPartState != LogPartRecord::SR_FOURTH_PHASE_COMPLETED) {
19498
if (logPartPtr.p->logPartState != LogPartRecord::SR_FOURTH_PHASE_STARTED) {
19500
systemErrorLab(signal, __LINE__);
19504
/* ------------------------------------------------------------------
19505
* THIS LOG PART WAS NOT COMPLETED YET.
19506
* EXIT AND WAIT FOR IT TO COMPLETE
19507
* ----------------------------------------------------------------- */
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;
19524
if ((cstartType == NodeState::ST_INITIAL_START) ||
19525
(cstartType == NodeState::ST_INITIAL_NODE_RESTART)) {
19528
ndbrequire(cinitialStartOngoing == ZTRUE);
19529
cinitialStartOngoing = ZFALSE;
19530
cstartRecReq = SRR_REDO_COMPLETE;
19531
checkStartCompletedLab(signal);
19533
} else if ((cstartType == NodeState::ST_NODE_RESTART) ||
19534
(cstartType == NodeState::ST_SYSTEM_RESTART)) {
19537
if(cstartType == NodeState::ST_SYSTEM_RESTART)
19540
if (c_lcp_complete_fragments.first(fragptr))
19543
signal->theData[0] = ZENABLE_EXPAND_CHECK;
19544
signal->theData[1] = fragptr.i;
19545
sendSignal(reference(), GSN_CONTINUEB, signal, 2, JBB);
19550
cstartRecReq = SRR_REDO_COMPLETE; // REDO complete
19552
rebuildOrderedIndexes(signal, 0);
19558
}//Dblqh::srFourthComp()
19560
/* ######################################################################### */
19561
/* ####### ERROR MODULE ####### */
19563
/* ######################################################################### */
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
/*---------------------------------------------------------------------------*/
19584
void Dblqh::systemErrorLab(Signal* signal, int line)
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()
19594
/* ------- ERROR SITUATIONS ------- */
19596
void Dblqh::aiStateErrorCheckLab(Signal* signal, Uint32* dataPtr, Uint32 length)
19598
ndbrequire(tcConnectptr.p->abortState != TcConnectionrec::ABORT_IDLE);
19599
if (tcConnectptr.p->transactionState != TcConnectionrec::IDLE) {
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 */
19606
/*************************************************************************>*/
19607
if (tcConnectptr.p->activeCreat == Fragrecord::AC_IGNORED) {
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 */
19620
/*************************************************************************>*/
19621
if (saveAttrInfoInSection(dataPtr, length) == ZOK) {
19623
if (tcConnectptr.p->transactionState ==
19624
TcConnectionrec::WAIT_AI_AFTER_ABORT) {
19625
if (tcConnectptr.p->currTupAiLen == tcConnectptr.p->totReclenAi) {
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);
19639
ndbrequire(tcConnectptr.p->currTupAiLen < tcConnectptr.p->totReclenAi);
19641
return; /* STILL WAITING FOR MORE ATTRIBUTE INFO */
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) {
19656
/*************************************************************************>*/
19657
/* ABORT IS ALREADY COMPLETED. WE NEED TO RESTART IT FROM WHERE IT */
19658
/* WAS INTERRUPTED. */
19659
/*************************************************************************>*/
19660
continueAbortLab(signal);
19665
/*************************************************************************>*/
19666
// Abort is ongoing. It will complete since we set the activeCreat = ZFALSE
19667
/*************************************************************************>*/
19672
/*************************************************************************>*/
19673
/* TRANSACTION HAVE BEEN ABORTED. THUS IGNORE ALL SIGNALS BELONGING TO IT. */
19674
/*************************************************************************>*/
19676
}//Dblqh::aiStateErrorCheckLab()
19678
void Dblqh::takeOverErrorLab(Signal* signal)
19680
terrorCode = ZTAKE_OVER_ERROR;
19681
abortErrorLab(signal);
19683
}//Dblqh::takeOverErrorLab()
19685
/* ##########################################################################
19687
* ######################################################################### */
19689
void Dblqh::execTESTSIG(Signal* signal)
19692
Uint32 userpointer = signal->theData[0];
19693
BlockReference userblockref = signal->theData[1];
19694
Uint32 testcase = signal->theData[2];
19696
signal->theData[0] = userpointer;
19697
signal->theData[1] = cownref;
19698
signal->theData[2] = testcase;
19699
sendSignal(userblockref, GSN_TESTSIG, signal, 25, JBB);
19701
}//Dblqh::execTESTSIG()
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)
19713
Uint32* dataPtr = &signal->theData[0];
19715
BlockReference userblockref = signal->theData[0];
19717
for (Uint32 i = 0; i < 7; i++)
19719
addfragptr.i = cfirstfreeAddfragrec;
19720
while (addfragptr.i != RNIL) {
19721
ptrCheckGuard(addfragptr, caddfragrecFileSize, addFragRecord);
19722
addfragptr.i = addfragptr.p->nextAddfragrec;
19731
tabptr.i < ctabrecFileSize;
19733
ptrAss(tabptr, tablerec);
19734
if (tabptr.p->tableStatus == Tablerec::NOT_DEFINED) {
19739
tcConnectptr.i = cfirstfreeTcConrec;
19740
while (tcConnectptr.i != RNIL) {
19741
ptrCheckGuard(tcConnectptr, ctcConnectrecFileSize, tcConnectionrec);
19742
tcConnectptr.i = tcConnectptr.p->nextTcConnectrec;
19745
sendSignal(userblockref, GSN_MEMCHECKCONF, signal, 10, JBB);
19747
}//Dblqh::execMEMCHECKREQ()
19751
/* ************************************************************************* */
19752
/* ************************* STATEMENT BLOCKS ****************************** */
19753
/* ************************************************************************* */
19754
/* ========================================================================= */
19755
/* ====== BUILD LINKED LIST OF LOG PAGES AFTER RECEIVING FSREADCONF ======= */
19757
/* ========================================================================= */
19758
void Dblqh::buildLinkedLogPageList(Signal* signal)
19760
LogPageRecordPtr bllLogPagePtr;
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++) {
19767
/* ----------------------------------------------------------------------
19768
* BUILD LINKED LIST BUT ALSO ENSURE THAT PAGE IS NOT SEEN AS DIRTY
19770
* --------------------------------------------------------------------- */
19771
bllLogPagePtr.i = lfoPtr.p->logPageArray[tbllIndex];
19772
ptrCheckGuard(bllLogPagePtr, clogPageFileSize, logPageRecord);
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.");
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;
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()
19795
/* =========================================================================
19796
* ======= CHANGE TO NEXT MBYTE IN LOG =======
19798
* ========================================================================= */
19799
void Dblqh::changeMbyte(Signal* signal)
19801
writeNextLog(signal);
19802
writeFileDescriptor(signal);
19803
}//Dblqh::changeMbyte()
19805
/* ========================================================================= */
19806
/* ====== CHECK IF THIS COMMIT LOG RECORD IS TO BE EXECUTED ======= */
19808
/* SUBROUTINE SHORT NAME = CEL */
19809
/* ========================================================================= */
19810
Uint32 Dblqh::checkIfExecLog(Signal* signal)
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;
19823
if (tcConnectptr.p->gci_hi >= fragptr.p->execSrStartGci[i]) {
19824
if (tcConnectptr.p->gci_hi <= fragptr.p->execSrLastGci[i]) {
19826
logPartPtr.p->execSrExecuteIndex = i;
19835
}//Dblqh::checkIfExecLog()
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. */
19842
/* ========================================================================= */
19843
void Dblqh::checkReadExecSr(Signal* signal)
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) {
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) <
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;
19867
}//Dblqh::checkReadExecSr()
19869
/* ========================================================================= */
19870
/* ==== CHECK IF START OF NEW FRAGMENT IS COMPLETED AND WE CAN ======= */
19871
/* ==== GET THE START GCI ======= */
19873
/* SUBROUTINE SHORT NAME = CTC */
19874
/* ========================================================================= */
19875
void Dblqh::checkScanTcCompleted(Signal* signal)
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) {
19883
fragptr.p->startGci = cnewestGci + 1;
19884
tabptr.i = tcConnectptr.p->tableref;
19885
ptrCheckGuard(tabptr, ctabrecFileSize, tablerec);
19886
sendCopyActiveConf(signal, tcConnectptr.p->tableref);
19888
}//Dblqh::checkScanTcCompleted()
19890
/* ------------------------------------------------------------------------- */
19891
/* ------ CLOSE A FILE DURING EXECUTION OF FRAGMENT LOG ------- */
19893
/* ------------------------------------------------------------------------- */
19894
void Dblqh::closeFile(Signal* signal,
19895
LogFileRecordPtr clfLogFilePtr, Uint32 line)
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()
19906
/* ---------------------------------------------------------------- */
19907
/* ---------------- A LOG PAGE HAVE BEEN COMPLETED ---------------- */
19909
/* SUBROUTINE SHORT NAME = CLP */
19915
/* ---------------------------------------------------------------- */
19916
void Dblqh::completedLogPage(Signal* signal, Uint32 clpType, Uint32 place)
19918
LogPageRecordPtr clpLogPagePtr;
19919
LogPageRecordPtr wlpLogPagePtr;
19923
if (logFilePtr.p->firstFilledPage == RNIL) {
19925
logFilePtr.p->firstFilledPage = logPagePtr.i;
19928
clpLogPagePtr.i = logFilePtr.p->lastFilledPage;
19929
ptrCheckGuard(clpLogPagePtr, clogPageFileSize, logPageRecord);
19930
clpLogPagePtr.p->logPageWord[ZNEXT_PAGE] = logPagePtr.i;
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) {
19943
twlpType = clpType;
19944
/* ------------------------------------------------------------------------- */
19945
/* ------ WRITE A SET OF LOG PAGES TO DISK ------- */
19947
/* SUBROUTINE SHORT NAME: WLP */
19948
/* ------------------------------------------------------------------------- */
19951
Uint32* dataPtr = &signal->theData[6];
19953
wlpLogPagePtr.i = logFilePtr.p->firstFilledPage;
19955
dataPtr[twlpNoPages] = wlpLogPagePtr.i;
19957
ptrCheckGuard(wlpLogPagePtr, clogPageFileSize, logPageRecord);
19959
writeDbgInfoPageHeader(wlpLogPagePtr, place,
19960
logFilePtr.p->filePosition + twlpNoPages - 1,
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) {
19978
signal->theData[3] = ZLIST_OF_MEM_PAGES_SYNCH;
19981
signal->theData[3] = ZLIST_OF_MEM_PAGES;
19983
signal->theData[4] = ZVAR_NO_LOG_PAGE_WORD;
19984
signal->theData[5] = twlpNoPages;
19985
sendSignal(NDBFS_REF, GSN_FSWRITEREQ, signal, 15, JBA);
19987
ndbrequire(logFilePtr.p->fileRef != RNIL);
19989
logPartPtr.p->m_io_tracker.send_io(32768*twlpNoPages);
19993
ndbout_c("writing %d pages at part: %u file: %u page: %u (mb: %u)",
19995
logPartPtr.p->logPartNo,
19996
logFilePtr.p->fileNo,
19997
logFilePtr.p->filePosition,
19998
logFilePtr.p->filePosition >> ZTWOLOG_NO_PAGES_IN_MBYTE);
20001
if (twlpType == ZNORMAL) {
20003
lfoPtr.p->lfoState = LogFileOperationRecord::ACTIVE_WRITE_LOG;
20004
} else if (twlpType == ZLAST_WRITE_IN_FILE) {
20006
lfoPtr.p->lfoState = LogFileOperationRecord::LAST_WRITE_IN_FILE;
20008
ndbrequire(twlpType == ZENFORCE_WRITE);
20010
lfoPtr.p->lfoState = LogFileOperationRecord::ACTIVE_WRITE_LOG;
20012
/* ----------------------------------------------------------------------- */
20013
/* ------ MOVE PAGES FROM LOG FILE TO LFO RECORD ------- */
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;
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()
20031
/* ---------------------------------------------------------------- */
20032
/* ---------------- DELETE FRAGMENT RECORD ------------------------ */
20034
/* SUBROUTINE SHORT NAME = DFR */
20035
/* ---------------------------------------------------------------- */
20036
void Dblqh::deleteFragrec(Uint32 fragId)
20038
Uint32 indexFound= RNIL;
20040
for (Uint32 i = 0; i < MAX_FRAG_PER_NODE; i++) {
20042
if (tabptr.p->fragid[i] == fragId) {
20043
fragptr.i = tabptr.p->fragrec[i];
20048
if (fragptr.i != RNIL) {
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);
20056
}//Dblqh::deleteFragrec()
20058
/* ------------------------------------------------------------------------- */
20059
/* ------- FIND LOG FILE RECORD GIVEN FILE NUMBER ------- */
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,
20068
LogPartRecordPtr flfLogPartPtr,
20069
LogFileRecordPtr* parLogFilePtr)
20071
LogFileRecordPtr locLogFilePtr;
20072
locLogFilePtr.i = flfLogPartPtr.p->firstLogfile;
20073
Uint32 loopCount = 0;
20075
ptrCheckGuard(locLogFilePtr, clogFileFileSize, logFileRecord);
20076
if (locLogFilePtr.p->fileNo == fileNo) {
20078
ndbrequire(loopCount == fileNo);
20079
parLogFilePtr->i = locLogFilePtr.i;
20080
parLogFilePtr->p = locLogFilePtr.p;
20083
locLogFilePtr.i = locLogFilePtr.p->nextLogFile;
20085
if (loopCount >= flfLogPartPtr.p->noLogFiles &&
20086
getNodeState().startLevel != NodeState::SL_STARTED)
20090
ndbrequire(loopCount < flfLogPartPtr.p->noLogFiles);
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,
20101
}//Dblqh::findLogfile()
20103
/* ------------------------------------------------------------------------- */
20104
/* ------ FIND PAGE REFERENCE IN MEMORY BUFFER AT LOG EXECUTION ------- */
20106
/* ------------------------------------------------------------------------- */
20107
void Dblqh::findPageRef(Signal* signal, CommitLogRecord* commitLogRecord)
20111
logPagePtr.i = RNIL;
20112
if (ERROR_INSERTED(5020)) {
20113
// Force system to read page from disk
20116
pageRefPtr.i = logPartPtr.p->lastPageRef;
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)) {
20123
tfprIndex = commitLogRecord->startPageNo - pageRefPtr.p->prPageNo;
20124
logPagePtr.i = pageRefPtr.p->pageRef[tfprIndex];
20125
ptrCheckGuard(logPagePtr, clogPageFileSize, logPageRecord);
20130
pageRefPtr.i = pageRefPtr.p->prPrev;
20131
} while (pageRefPtr.i != RNIL);
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;
20139
Ptr<RedoCacheLogPageRecord> pagePtr;
20140
if (cache.m_hash.find(pagePtr, key))
20143
if (cache.m_lru.hasPrev(pagePtr))
20146
cache.m_lru.remove(pagePtr);
20147
cache.m_lru.addFirst(pagePtr);
20149
logPagePtr.i = pagePtr.i;
20150
ptrCheckGuard(logPagePtr, clogPageFileSize, logPageRecord);
20152
Ptr<LogPageRecord> loopPtr = logPagePtr;
20153
Uint32 extra = commitLogRecord->stopPageNo - commitLogRecord->startPageNo;
20154
for (Uint32 i = 0; i<extra; i++)
20157
Uint32 prevPtrI = loopPtr.i;
20158
loopPtr.i = loopPtr.p->logPageWord[ZNEXT_PAGE];
20159
if (loopPtr.i == RNIL)
20163
* next page is not linked
20164
* check if it's added as a "single" page
20166
key.m_page_no = commitLogRecord->startPageNo + i + 1;
20167
if (cache.m_hash.find(pagePtr, key))
20171
* Yes it is...link them
20173
Ptr<LogPageRecord> tmp;
20175
tmp.p = reinterpret_cast<LogPageRecord*>(pagePtr.p);
20176
tmp.p->logPageWord[ZPREV_PAGE] = prevPtrI;
20177
loopPtr.p->logPageWord[ZNEXT_PAGE] = tmp.i;
20183
logPagePtr.i = RNIL;
20184
cache.m_multi_miss++;
20186
ndbout_c("Found part: %u file: %u page: %u but not next page(%u) %u",
20188
commitLogRecord->fileNo,
20189
commitLogRecord->startPageNo,
20191
commitLogRecord->startPageNo + i + 1);
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))
20202
cache.m_lru.remove(pagePtr);
20203
cache.m_lru.addFirst(pagePtr);
20210
cache.m_multi_page++;
20214
}//Dblqh::findPageRef()
20216
/* ------------------------------------------------------------------------- */
20217
/* ------ GET FIRST OPERATION QUEUED FOR LOGGING ------- */
20219
/* SUBROUTINE SHORT NAME = GFL */
20220
/* ------------------------------------------------------------------------- */
20222
Dblqh::getFirstInLogQueue(Signal* signal,
20223
Ptr<TcConnectionrec> & dst)
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;
20235
queue = &logPartPtr.p->m_log_prepare_queue;
20236
tmp.i = queue->firstElement;
20238
ptrCheckGuard(tmp, ctcConnectrecFileSize, tcConnectionrec);
20239
queue->firstElement = tmp.p->nextTcLogQueue;
20240
if (queue->firstElement == RNIL) {
20242
queue->lastElement = RNIL;
20245
}//Dblqh::getFirstInLogQueue()
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)
20255
for (Uint32 i = 0; i < MAX_FRAG_PER_NODE; i++) {
20257
if (tabptr.p->fragid[i] == fragId) {
20258
fragptr.i = tabptr.p->fragrec[i];
20259
c_fragment_pool.getPtr(fragptr);
20264
}//Dblqh::getFragmentrec()
20266
/* ========================================================================= */
20267
/* ====== INITIATE FRAGMENT RECORD ======= */
20269
/* ========================================================================= */
20270
void Dblqh::initialiseAddfragrec(Signal* signal)
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;
20278
addfragptr.i = caddfragrecFileSize - 1;
20279
ptrAss(addfragptr, addFragRecord);
20280
addfragptr.p->nextAddfragrec = RNIL;
20281
cfirstfreeAddfragrec = 0;
20284
cfirstfreeAddfragrec = RNIL;
20286
}//Dblqh::initialiseAddfragrec()
20288
/* ========================================================================= */
20289
/* ====== INITIATE FRAGMENT RECORD ======= */
20291
/* ========================================================================= */
20292
void Dblqh::initialiseFragrec(Signal* signal)
20295
SLList<Fragrecord> tmp(c_fragment_pool);
20296
while(tmp.seize(fragptr))
20298
refresh_watch_dog();
20299
new (fragptr.p) Fragrecord();
20300
fragptr.p->fragStatus = Fragrecord::FREE;
20301
fragptr.p->execSrStatus = Fragrecord::IDLE;
20302
fragptr.p->srStatus = Fragrecord::SS_IDLE;
20305
}//Dblqh::initialiseFragrec()
20307
/* ========================================================================= */
20308
/* ====== INITIATE FRAGMENT RECORD ======= */
20310
/* ========================================================================= */
20311
void Dblqh::initialiseGcprec(Signal* signal)
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;
20324
}//Dblqh::initialiseGcprec()
20326
/* ========================================================================= */
20327
/* ====== INITIATE LCP RECORD ======= */
20329
/* ========================================================================= */
20330
void Dblqh::initialiseLcpRec(Signal* signal)
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;
20342
}//Dblqh::initialiseLcpRec()
20344
/* ========================================================================= */
20345
/* ====== INITIATE LOG FILE OPERATION RECORD ======= */
20347
/* ========================================================================= */
20348
void Dblqh::initialiseLfo(Signal* signal)
20350
if (clfoFileSize != 0) {
20351
for (lfoPtr.i = 0; lfoPtr.i < clfoFileSize; lfoPtr.i++) {
20352
ptrAss(lfoPtr, logFileOperationRecord);
20353
lfoPtr.p->lfoState = LogFileOperationRecord::IDLE;
20354
lfoPtr.p->lfoTimer = 0;
20355
lfoPtr.p->nextLfo = lfoPtr.i + 1;
20357
lfoPtr.i = clfoFileSize - 1;
20358
ptrAss(lfoPtr, logFileOperationRecord);
20359
lfoPtr.p->nextLfo = RNIL;
20363
cfirstfreeLfo = RNIL;
20365
}//Dblqh::initialiseLfo()
20367
/* ========================================================================= */
20368
/* ====== INITIATE LOG FILE RECORD ======= */
20370
/* ========================================================================= */
20371
void Dblqh::initialiseLogFile(Signal* signal)
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;
20379
logFilePtr.p->logLastPrepRef = new Uint32[clogFileSize];
20380
logFilePtr.p->logMaxGciCompleted = new Uint32[clogFileSize];
20381
logFilePtr.p->logMaxGciStarted = new Uint32[clogFileSize];
20383
if (logFilePtr.p->logLastPrepRef == 0 ||
20384
logFilePtr.p->logMaxGciCompleted == 0 ||
20385
logFilePtr.p->logMaxGciStarted == 0)
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);
20395
logFilePtr.i = clogFileFileSize - 1;
20396
ptrAss(logFilePtr, logFileRecord);
20397
logFilePtr.p->nextLogFile = RNIL;
20398
cfirstfreeLogFile = 0;
20401
cfirstfreeLogFile = RNIL;
20403
}//Dblqh::initialiseLogFile()
20405
/* ========================================================================= */
20406
/* ====== INITIATE LOG PAGES ======= */
20408
/* ========================================================================= */
20409
void Dblqh::initialiseLogPage(Signal* signal)
20412
* Moved into initRecords()
20414
}//Dblqh::initialiseLogPage()
20416
/* =========================================================================
20417
* ====== INITIATE LOG PART RECORD =======
20419
* ========================================================================= */
20420
void Dblqh::initialiseLogPart(Signal* signal)
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;
20429
}//Dblqh::initialiseLogPart()
20431
void Dblqh::initialisePageRef(Signal* signal)
20433
if (cpageRefFileSize != 0) {
20434
for (pageRefPtr.i = 0;
20435
pageRefPtr.i < cpageRefFileSize;
20437
ptrAss(pageRefPtr, pageRefRecord);
20438
pageRefPtr.p->prNext = pageRefPtr.i + 1;
20440
pageRefPtr.i = cpageRefFileSize - 1;
20441
ptrAss(pageRefPtr, pageRefRecord);
20442
pageRefPtr.p->prNext = RNIL;
20443
cfirstfreePageRef = 0;
20446
cfirstfreePageRef = RNIL;
20448
}//Dblqh::initialisePageRef()
20450
/* ==========================================================================
20451
* ======= INITIATE RECORDS =======
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)
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;
20469
ccurrentGcprec = RNIL;
20470
caddNodeState = ZFALSE;
20471
cstartRecReq = SRR_INITIAL; // Initial
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;
20484
cnoOfFragsCheckpointed = 0;
20488
initialiseAddfragrec(signal);
20500
initialiseFragrec(signal);
20504
initialiseGcprec(signal);
20505
initialiseLcpRec(signal);
20509
initialiseLogPage(signal);
20513
initialiseLfo(signal);
20517
initialiseLogFile(signal);
20518
initialiseLogPart(signal);
20522
initialisePageRef(signal);
20526
initialiseScanrec(signal);
20530
initialiseTabrec(signal);
20534
initialiseTcNodeFailRec(signal);
20535
initialiseTcrec(signal);
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);
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);
20558
}//Dblqh::initialiseRecordsLab()
20560
/* ==========================================================================
20561
* ======= INITIATE TC CONNECTION RECORD =======
20563
* ========================================================================= */
20564
void Dblqh::initialiseScanrec(Signal* signal)
20566
ndbrequire(cscanrecFileSize > 1);
20567
DLList<ScanRecord> tmp(c_scanRecordPool);
20568
while (tmp.seize(scanptr)){
20569
//new (scanptr.p) ScanRecord();
20570
refresh_watch_dog();
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;
20583
* just seize records from pool and put into
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;
20591
}//Dblqh::initialiseScanrec()
20593
/* ==========================================================================
20594
* ======= INITIATE TABLE RECORD =======
20596
* ========================================================================= */
20597
void Dblqh::initialiseTabrec(Signal* signal)
20599
if (ctabrecFileSize != 0) {
20600
for (tabptr.i = 0; tabptr.i < ctabrecFileSize; tabptr.i++) {
20601
refresh_watch_dog();
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;
20612
}//Dblqh::initialiseTabrec()
20614
/* ==========================================================================
20615
* ======= INITIATE TC CONNECTION RECORD =======
20617
* ========================================================================= */
20618
void Dblqh::initialiseTcrec(Signal* signal)
20620
if (ctcConnectrecFileSize != 0) {
20621
for (tcConnectptr.i = 0;
20622
tcConnectptr.i < ctcConnectrecFileSize;
20623
tcConnectptr.i++) {
20624
refresh_watch_dog();
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;
20635
tcConnectptr.i = ctcConnectrecFileSize - 1;
20636
ptrAss(tcConnectptr, tcConnectionrec);
20637
tcConnectptr.p->nextTcConnectrec = RNIL;
20638
cfirstfreeTcConrec = 0;
20641
cfirstfreeTcConrec = RNIL;
20643
}//Dblqh::initialiseTcrec()
20645
/* ==========================================================================
20646
* ======= INITIATE TC CONNECTION RECORD =======
20648
* ========================================================================= */
20649
void Dblqh::initialiseTcNodeFailRec(Signal* signal)
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;
20659
}//Dblqh::initialiseTcNodeFailRec()
20661
/* ==========================================================================
20662
* ======= INITIATE FRAGMENT RECORD =======
20664
* SUBROUTINE SHORT NAME = IF
20665
* ========================================================================= */
20666
void Dblqh::initFragrec(Signal* signal,
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;
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()
20700
/* ==========================================================================
20701
* ======= INITIATE FRAGMENT RECORD FOR SYSTEM RESTART =======
20703
* SUBROUTINE SHORT NAME = IFS
20704
* ========================================================================= */
20706
/* ==========================================================================
20707
* ======= INITIATE INFORMATION ABOUT GLOBAL CHECKPOINTS =======
20708
* IN LOG FILE RECORDS
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)
20718
LogFileRecordPtr filePtr = logFilePtr;
20719
Uint32 pos = ZPAGE_HEADER_SIZE + ZFD_HEADER_SIZE;
20720
for (Uint32 fd = 0; fd < noFdDescriptors; fd++)
20723
for (Uint32 mb = 0; mb < clogFileSize; mb++)
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];
20736
if (fd + 1 < noFdDescriptors)
20739
filePtr.i = filePtr.p->prevLogFile;
20740
ptrCheckGuard(filePtr, clogFileFileSize, logFileRecord);
20743
}//Dblqh::initGciInLogFileRec()
20745
/* ==========================================================================
20746
* ======= INITIATE LCP RECORD WHEN USED FOR SYSTEM RESTART =======
20748
* SUBROUTINE SHORT NAME = ILS
20749
* ========================================================================= */
20750
void Dblqh::initLcpSr(Signal* signal,
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()
20766
/* ==========================================================================
20767
* ======= INITIATE LOG PART =======
20769
* ========================================================================= */
20770
void Dblqh::initLogpart(Signal* signal)
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;
20780
logPartPtr.p->logPartState = LogPartRecord::SR_FIRST_PHASE;
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()
20799
/* ==========================================================================
20800
* ======= INITIATE LOG POINTERS =======
20802
* ========================================================================= */
20803
void Dblqh::initLogPointers(Signal* signal)
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()
20813
/* ------------------------------------------------------------------------- */
20814
/* ------- INIT REQUEST INFO BEFORE EXECUTING A LOG RECORD ------- */
20816
/* ------------------------------------------------------------------------- */
20817
void Dblqh::initReqinfoExecSr(Signal* signal)
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()
20864
/* --------------------------------------------------------------------------
20865
* ------- INSERT FRAGMENT -------
20867
* ------------------------------------------------------------------------- */
20868
bool Dblqh::insertFragrec(Signal* signal, Uint32 fragId)
20871
if(c_fragment_pool.seize(fragptr) == false)
20873
terrorCode = ZNO_FREE_FRAGMENTREC;
20876
for (Uint32 i = 0; i < MAX_FRAG_PER_NODE; i++) {
20878
if (tabptr.p->fragid[i] == ZNIL) {
20880
tabptr.p->fragid[i] = fragId;
20881
tabptr.p->fragrec[i] = fragptr.i;
20885
c_fragment_pool.release(fragptr);
20886
terrorCode = ZTOO_MANY_FRAGMENTS;
20888
}//Dblqh::insertFragrec()
20890
/* --------------------------------------------------------------------------
20891
* ------- LINK OPERATION IN ACTIVE LIST ON FRAGMENT -------
20893
* SUBROUTINE SHORT NAME: LFQ
20897
* ------------------------------------------------------------------------- */
20898
void Dblqh::linkFragQueue(Signal* signal)
20900
TcConnectionrecPtr lfqTcConnectptr;
20901
TcConnectionrec * const regTcPtr = tcConnectptr.p;
20902
Fragrecord * const regFragPtr = fragptr.p;
20903
Uint32 tcIndex = tcConnectptr.i;
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) {
20913
ptrCheckGuard(lfqTcConnectptr, ctcConnectrecFileSize, tcConnectionrec);
20914
lfqTcConnectptr.p->nextTc = tcIndex;
20916
regFragPtr->firstWaitQueue = tcIndex;
20919
}//Dblqh::linkFragQueue()
20921
/* -------------------------------------------------------------------------
20922
* ------- LINK OPERATION INTO WAITING FOR LOGGING -------
20924
* SUBROUTINE SHORT NAME = LWL
20928
* ------------------------------------------------------------------------- */
20930
Dblqh::linkWaitLog(Signal* signal,
20931
LogPartRecordPtr regLogPartPtr,
20932
LogPartRecord::OperationQueue & queue)
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) {
20942
queue.firstElement = tcConnectptr.i;
20945
ptrCheckGuard(lwlTcConnectptr, ctcConnectrecFileSize, tcConnectionrec);
20946
lwlTcConnectptr.p->nextTcLogQueue = tcConnectptr.i;
20948
queue.lastElement = tcConnectptr.i;
20949
tcConnectptr.p->nextTcLogQueue = RNIL;
20950
regLogPartPtr.p->logPartState = LogPartRecord::ACTIVE;
20951
if (regLogPartPtr.p->LogLqhKeyReqSent == ZFALSE)
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);
20959
}//Dblqh::linkWaitLog()
20961
/* --------------------------------------------------------------------------
20962
* ------- START THE NEXT OPERATION ON THIS LOG PART IF ANY -------
20963
* ------- OPERATIONS ARE QUEUED. -------
20965
* SUBROUTINE SHORT NAME = LNS
20969
* ------------------------------------------------------------------------- */
20970
void Dblqh::logNextStart(Signal* signal)
20972
LogPartRecordPtr lnsLogPartPtr;
20973
UintR tlnsStillWaiting;
20974
LogPartRecord * const regLogPartPtr = logPartPtr.p;
20976
if (regLogPartPtr->m_log_prepare_queue.isEmpty() &&
20977
regLogPartPtr->m_log_complete_queue.isEmpty() &&
20978
(regLogPartPtr->waitWriteGciLog != LogPartRecord::WWGL_TRUE))
20980
// --------------------------------------------------------------------------
20981
// Optimised route for the common case
20982
// --------------------------------------------------------------------------
20986
if (!regLogPartPtr->m_log_prepare_queue.isEmpty() ||
20987
!regLogPartPtr->m_log_complete_queue.isEmpty())
20990
regLogPartPtr->logPartState = LogPartRecord::ACTIVE;
20991
if (regLogPartPtr->LogLqhKeyReqSent == ZFALSE)
20994
regLogPartPtr->LogLqhKeyReqSent = ZTRUE;
20995
signal->theData[0] = ZLOG_LQHKEYREQ;
20996
signal->theData[1] = logPartPtr.i;
20997
sendSignal(cownref, GSN_CONTINUEB, signal, 2, JBB);
21001
if (regLogPartPtr->waitWriteGciLog != LogPartRecord::WWGL_TRUE)
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++) {
21020
ptrAss(lnsLogPartPtr, logPartRecord);
21021
if (lnsLogPartPtr.p->waitWriteGciLog == LogPartRecord::WWGL_TRUE) {
21023
tlnsStillWaiting = ZTRUE;
21026
if (tlnsStillWaiting == ZFALSE) {
21028
signal->theData[0] = ZINIT_GCP_REC;
21029
sendSignal(cownref, GSN_CONTINUEB, signal, 1, JBB);
21032
}//Dblqh::logNextStart()
21034
/* --------------------------------------------------------------------------
21035
* ------- MOVE PAGES FROM LFO RECORD TO PAGE REFERENCE RECORD -------
21036
* WILL ALWAYS MOVE 8 PAGES TO A PAGE REFERENCE RECORD.
21038
* SUBROUTINE SHORT NAME = MPR
21039
* ------------------------------------------------------------------------- */
21040
void Dblqh::moveToPageRef(Signal* signal)
21042
LogPageRecordPtr mprLogPagePtr;
21043
PageRefRecordPtr mprPageRefPtr;
21046
/* --------------------------------------------------------------------------
21047
* ------- INSERT PAGE REFERENCE RECORD -------
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;
21055
if ((logPartPtr.p->mmBufferSize + 8) >= ZMAX_MM_BUFFER_SIZE) {
21057
pageRefPtr.i = logPartPtr.p->firstPageRef;
21058
ptrCheckGuard(pageRefPtr, cpageRefFileSize, pageRefRecord);
21059
releasePrPages(signal);
21060
removePageRef(signal);
21063
logPartPtr.p->mmBufferSize = logPartPtr.p->mmBufferSize + 8;
21065
seizePageRef(signal);
21066
if (logPartPtr.p->firstPageRef == RNIL) {
21068
logPartPtr.p->firstPageRef = pageRefPtr.i;
21071
iprPageRefPtr.i = logPartPtr.p->lastPageRef;
21072
ptrCheckGuard(iprPageRefPtr, cpageRefFileSize, pageRefRecord);
21073
iprPageRefPtr.p->prNext = pageRefPtr.i;
21075
pageRefPtr.p->prPrev = logPartPtr.p->lastPageRef;
21076
logPartPtr.p->lastPageRef = pageRefPtr.i;
21078
pageRefPtr.p->prFileNo = logFilePtr.p->fileNo;
21079
pageRefPtr.p->prPageNo = lfoPtr.p->lfoPageNo;
21081
mprLogPagePtr.i = lfoPtr.p->firstLfoPage;
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) {
21092
mprPageRefPtr.i = pageRefPtr.p->prPrev;
21093
if (mprPageRefPtr.i != RNIL) {
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];
21100
}//Dblqh::moveToPageRef()
21102
/* ------------------------------------------------------------------------- */
21103
/* ------- READ THE ATTRINFO FROM THE LOG ------- */
21105
/* SUBROUTINE SHORT NAME = RA */
21106
/* ------------------------------------------------------------------------- */
21107
void Dblqh::readAttrinfo(Signal* signal)
21109
Uint32 remainingLen = tcConnectptr.p->totSendlenAi;
21110
tcConnectptr.p->reclenAiLqhkey = 0;
21111
if (remainingLen == 0) {
21116
readLogData(signal, remainingLen, tcConnectptr.p->attrInfoIVal);
21117
}//Dblqh::readAttrinfo()
21119
/* ------------------------------------------------------------------------- */
21120
/* ------- READ COMMIT LOG ------- */
21122
/* SUBROUTINE SHORT NAME = RCL */
21123
/* ------------------------------------------------------------------------- */
21124
void Dblqh::readCommitLog(Signal* signal, CommitLogRecord* commitLogRecord)
21126
Uint32 trclPageIndex = logPagePtr.p->logPageWord[ZCURR_PAGE_INDEX];
21127
if ((trclPageIndex + (ZCOMMIT_LOG_SIZE - 1)) < ZPAGE_SIZE) {
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;
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;
21152
tcConnectptr.p->transid[0] = logPartPtr.i + 65536;
21153
tcConnectptr.p->transid[1] = (DBLQH << 20) + (cownNodeid << 8);
21154
}//Dblqh::readCommitLog()
21156
/* ------------------------------------------------------------------------- */
21157
/* ------- READ LOG PAGES FROM DISK IN ORDER TO EXECUTE A LOG ------- */
21158
/* RECORD WHICH WAS NOT FOUND IN MAIN MEMORY. */
21160
/* SUBROUTINE SHORT NAME = REL */
21161
/* ------------------------------------------------------------------------- */
21162
void Dblqh::readExecLog(Signal* 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--) {
21175
seizeLogpage(signal);
21176
arrGuard(trelI, 16);
21177
lfoPtr.p->logPageArray[trelI] = logPagePtr.i;
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);
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);
21211
}//Dblqh::readExecLog()
21213
/* ------------------------------------------------------------------------- */
21214
/* ------- READ 64 KBYTES WHEN EXECUTING THE FRAGMENT LOG ------- */
21216
/* SUBROUTINE SHORT NAME = RES */
21217
/* ------------------------------------------------------------------------- */
21218
void Dblqh::readExecSrNewMbyte(Signal* signal)
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()
21229
/* ------------------------------------------------------------------------- */
21230
/* ------- READ 64 KBYTES WHEN EXECUTING THE FRAGMENT LOG ------- */
21232
/* SUBROUTINE SHORT NAME = RES */
21233
/* ------------------------------------------------------------------------- */
21234
void Dblqh::readExecSr(Signal* signal)
21239
tresPageid = logFilePtr.p->filePosition;
21242
for (tresIndex = 7; (UintR)~tresIndex; tresIndex--) {
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;
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);
21276
ndbout_c("readExecSr %u page at part: %u file: %u page: %u (mb: %u)",
21278
logPartPtr.p->logPartNo,
21279
logFilePtr.p->fileNo,
21281
tresPageid >> ZTWOLOG_NO_PAGES_IN_MBYTE);
21283
}//Dblqh::readExecSr()
21285
/* ------------------------------------------------------------------------- */
21286
/* ------------ READ THE PRIMARY KEY FROM THE LOG ---------------- */
21288
/* SUBROUTINE SHORT NAME = RK */
21289
/* --------------------------------------------------------------------------*/
21290
void Dblqh::readKey(Signal* signal)
21292
Uint32 remainingLen = tcConnectptr.p->primKeyLen;
21293
ndbrequire(remainingLen != 0);
21295
readLogData(signal, remainingLen, tcConnectptr.p->keyInfoIVal);
21296
}//Dblqh::readKey()
21298
/* ------------------------------------------------------------------------- */
21299
/* ------------ READ A NUMBER OF WORDS FROM LOG INTO CDATA ---------------- */
21301
/* SUBROUTINE SHORT NAME = RLD */
21302
/* --------------------------------------------------------------------------*/
21303
void Dblqh::readLogData(Signal* signal, Uint32 noOfWords, Uint32& sectionIVal)
21305
Uint32 logPos = logPagePtr.p->logPageWord[ZCURR_PAGE_INDEX];
21306
if ((logPos + noOfWords) >= ZPAGE_SIZE) {
21307
for (Uint32 i = 0; i < noOfWords; i++)
21309
/* Todo : Consider reading > 1 word at a time */
21310
Uint32 word= readLogwordExec(signal);
21311
bool ok= appendToSection(sectionIVal,
21318
bool ok= appendToSection(sectionIVal,
21319
&logPagePtr.p->logPageWord[logPos],
21322
logPagePtr.p->logPageWord[ZCURR_PAGE_INDEX] = logPos + noOfWords;
21324
}//Dblqh::readLogData()
21326
/* ------------------------------------------------------------------------- */
21327
/* ------------ READ THE LOG HEADER OF A PREPARE LOG HEADER ---------------- */
21329
/* SUBROUTINE SHORT NAME = RLH */
21330
/* --------------------------------------------------------------------------*/
21331
void Dblqh::readLogHeader(Signal* signal)
21333
Uint32 logPos = logPagePtr.p->logPageWord[ZCURR_PAGE_INDEX];
21334
if ((logPos + ZLOG_HEAD_SIZE) < ZPAGE_SIZE) {
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;
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);
21355
tcConnectptr.p->m_use_rowid = (tcConnectptr.p->operation == ZINSERT);
21356
}//Dblqh::readLogHeader()
21358
/* ------------------------------------------------------------------------- */
21359
/* ------- READ A WORD FROM THE LOG ------- */
21361
/* OUTPUT: TLOG_WORD */
21362
/* SUBROUTINE SHORT NAME = RLW */
21363
/* ------------------------------------------------------------------------- */
21364
Uint32 Dblqh::readLogword(Signal* signal)
21366
Uint32 logPos = logPagePtr.p->logPageWord[ZCURR_PAGE_INDEX];
21367
ndbrequire(logPos < ZPAGE_SIZE);
21368
Uint32 logWord = logPagePtr.p->logPageWord[logPos];
21370
logPagePtr.p->logPageWord[ZCURR_PAGE_INDEX] = logPos;
21371
if (logPos >= ZPAGE_SIZE) {
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++;
21382
}//Dblqh::readLogword()
21384
/* ------------------------------------------------------------------------- */
21385
/* ------- READ A WORD FROM THE LOG WHEN EXECUTING A LOG RECORD ------- */
21387
/* OUTPUT: TLOG_WORD */
21388
/* SUBROUTINE SHORT NAME = RWE */
21389
/* ------------------------------------------------------------------------- */
21390
Uint32 Dblqh::readLogwordExec(Signal* signal)
21392
Uint32 logPos = logPagePtr.p->logPageWord[ZCURR_PAGE_INDEX];
21393
ndbrequire(logPos < ZPAGE_SIZE);
21394
Uint32 logWord = logPagePtr.p->logPageWord[logPos];
21396
logPagePtr.p->logPageWord[ZCURR_PAGE_INDEX] = logPos;
21397
if (logPos >= ZPAGE_SIZE) {
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;
21404
// Reading word at the last pos in the last page
21405
// Don't step forward to next page!
21407
logPagePtr.p->logPageWord[ZCURR_PAGE_INDEX]++;
21411
}//Dblqh::readLogwordExec()
21413
/* ------------------------------------------------------------------------- */
21414
/* ------- READ A SINGLE PAGE FROM THE LOG ------- */
21416
/* INPUT: TRSP_PAGE_NO */
21417
/* SUBROUTINE SHORT NAME = RSP */
21418
/* ------------------------------------------------------------------------- */
21419
void Dblqh::readSinglePage(Signal* signal, Uint32 pageNo)
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);
21439
ndbout_c("readSinglePage 1 page at part: %u file: %u page: %u (mb: %u)",
21440
logPartPtr.p->logPartNo,
21441
logFilePtr.p->fileNo,
21443
pageNo >> ZTWOLOG_NO_PAGES_IN_MBYTE);
21445
}//Dblqh::readSinglePage()
21447
/* --------------------------------------------------------------------------
21448
* ------- REMOVE COPY FRAGMENT FROM ACTIVE COPY LIST -------
21450
* ------------------------------------------------------------------------- */
21451
void Dblqh::releaseActiveCopy(Signal* signal)
21453
/* MUST BE 8 BIT */
21458
for (tracIndex = 0; tracIndex < 4; tracIndex++) {
21459
if (tracFlag == ZFALSE) {
21461
if (cactiveCopy[tracIndex] == fragptr.i) {
21466
if (tracIndex < 3) {
21468
cactiveCopy[tracIndex - 1] = cactiveCopy[tracIndex];
21471
cactiveCopy[3] = RNIL;
21475
ndbrequire(tracFlag == ZTRUE);
21477
}//Dblqh::releaseActiveCopy()
21480
/* --------------------------------------------------------------------------
21481
* ------- RELEASE ADD FRAGMENT RECORD -------
21483
* ------------------------------------------------------------------------- */
21484
void Dblqh::releaseAddfragrec(Signal* signal)
21486
addfragptr.p->addfragStatus = AddFragRecord::FREE;
21487
addfragptr.p->nextAddfragrec = cfirstfreeAddfragrec;
21488
cfirstfreeAddfragrec = addfragptr.i;
21489
}//Dblqh::releaseAddfragrec()
21491
/* --------------------------------------------------------------------------
21492
* ------- RELEASE A PAGE REFERENCE RECORD. -------
21494
* ------------------------------------------------------------------------- */
21495
void Dblqh::releasePageRef(Signal* signal)
21497
pageRefPtr.p->prNext = cfirstfreePageRef;
21498
cfirstfreePageRef = pageRefPtr.i;
21499
}//Dblqh::releasePageRef()
21501
/* --------------------------------------------------------------------------
21502
* --- RELEASE ALL PAGES IN THE MM BUFFER AFTER EXECUTING THE LOG ON IT. ----
21504
* ------------------------------------------------------------------------- */
21505
void Dblqh::releaseMmPages(Signal* signal)
21509
pageRefPtr.i = logPartPtr.p->firstPageRef;
21510
if (pageRefPtr.i != RNIL) {
21512
ptrCheckGuard(pageRefPtr, cpageRefFileSize, pageRefRecord);
21513
releasePrPages(signal);
21514
removePageRef(signal);
21517
}//Dblqh::releaseMmPages()
21519
/* --------------------------------------------------------------------------
21520
* ------- RELEASE A SET OF PAGES AFTER EXECUTING THE LOG ON IT. -------
21522
* ------------------------------------------------------------------------- */
21523
void Dblqh::releasePrPages(Signal* signal)
21527
for (trppIndex = 0; trppIndex <= 7; trppIndex++) {
21529
logPagePtr.i = pageRefPtr.p->pageRef[trppIndex];
21530
ptrCheckGuard(logPagePtr, clogPageFileSize, logPageRecord);
21531
releaseLogpage(signal);
21533
}//Dblqh::releasePrPages()
21535
/* --------------------------------------------------------------------------
21536
* ------- RELEASE OPERATION FROM WAIT QUEUE LIST ON FRAGMENT -------
21538
* SUBROUTINE SHORT NAME : RWA
21539
* ------------------------------------------------------------------------- */
21540
void Dblqh::releaseWaitQueue(Signal* signal)
21542
TcConnectionrecPtr rwaTcNextConnectptr;
21543
TcConnectionrecPtr rwaTcPrevConnectptr;
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) {
21551
systemError(signal, __LINE__);
21553
tcConnectptr.p->listState = TcConnectionrec::NOT_IN_LIST;
21554
if (rwaTcNextConnectptr.i != RNIL) {
21556
ptrCheckGuard(rwaTcNextConnectptr, ctcConnectrecFileSize, tcConnectionrec);
21557
rwaTcNextConnectptr.p->prevTc = rwaTcPrevConnectptr.i;
21560
fragptr.p->lastWaitQueue = rwaTcPrevConnectptr.i;
21562
if (rwaTcPrevConnectptr.i != RNIL) {
21564
ptrCheckGuard(rwaTcPrevConnectptr, ctcConnectrecFileSize, tcConnectionrec);
21565
rwaTcPrevConnectptr.p->nextTc = rwaTcNextConnectptr.i;
21568
fragptr.p->firstWaitQueue = rwaTcNextConnectptr.i;
21570
}//Dblqh::releaseWaitQueue()
21572
/* --------------------------------------------------------------------------
21573
* ------- REMOVE OPERATION RECORD FROM LIST ON LOG PART OF NOT -------
21574
* COMPLETED OPERATIONS IN THE LOG.
21576
* SUBROUTINE SHORT NAME = RLO
21577
* ------------------------------------------------------------------------- */
21578
void Dblqh::removeLogTcrec(Signal* signal)
21580
TcConnectionrecPtr rloTcNextConnectptr;
21581
TcConnectionrecPtr rloTcPrevConnectptr;
21582
rloTcPrevConnectptr.i = tcConnectptr.p->prevLogTcrec;
21583
rloTcNextConnectptr.i = tcConnectptr.p->nextLogTcrec;
21584
if (rloTcNextConnectptr.i != RNIL) {
21586
ptrCheckGuard(rloTcNextConnectptr, ctcConnectrecFileSize, tcConnectionrec);
21587
rloTcNextConnectptr.p->prevLogTcrec = rloTcPrevConnectptr.i;
21590
logPartPtr.p->lastLogTcrec = rloTcPrevConnectptr.i;
21592
if (rloTcPrevConnectptr.i != RNIL) {
21594
ptrCheckGuard(rloTcPrevConnectptr, ctcConnectrecFileSize, tcConnectionrec);
21595
rloTcPrevConnectptr.p->nextLogTcrec = rloTcNextConnectptr.i;
21598
logPartPtr.p->firstLogTcrec = rloTcNextConnectptr.i;
21600
}//Dblqh::removeLogTcrec()
21602
/* --------------------------------------------------------------------------
21603
* ------- REMOVE PAGE REFERENCE RECORD FROM LIST IN THIS LOG PART -------
21605
* SUBROUTINE SHORT NAME = RPR
21606
* ------------------------------------------------------------------------- */
21607
void Dblqh::removePageRef(Signal* signal)
21609
PageRefRecordPtr rprPageRefPtr;
21611
pageRefPtr.i = logPartPtr.p->firstPageRef;
21612
if (pageRefPtr.i != RNIL) {
21614
ptrCheckGuard(pageRefPtr, cpageRefFileSize, pageRefRecord);
21615
if (pageRefPtr.p->prNext == RNIL) {
21617
logPartPtr.p->lastPageRef = RNIL;
21618
logPartPtr.p->firstPageRef = RNIL;
21621
logPartPtr.p->firstPageRef = pageRefPtr.p->prNext;
21622
rprPageRefPtr.i = pageRefPtr.p->prNext;
21623
ptrCheckGuard(rprPageRefPtr, cpageRefFileSize, pageRefRecord);
21624
rprPageRefPtr.p->prPrev = RNIL;
21626
releasePageRef(signal);
21628
}//Dblqh::removePageRef()
21630
/* ------------------------------------------------------------------------- */
21631
/* ------- RETURN FROM EXECUTION OF LOG ------- */
21633
/* ------------------------------------------------------------------------- */
21634
Uint32 Dblqh::returnExecLog(Signal* signal)
21636
tcConnectptr.p->connectState = TcConnectionrec::CONNECTED;
21637
initLogPointers(signal);
21638
logPartPtr.p->execSrExecuteIndex++;
21639
Uint32 result = checkIfExecLog(signal);
21640
if (result == ZOK) {
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;
21651
/* ------------------------------------------------------------------------- */
21652
/* NO MORE EXECUTION OF THIS LOG RECORD. */
21653
/* ------------------------------------------------------------------------- */
21654
if (logPartPtr.p->logExecState ==
21655
LogPartRecord::LES_EXEC_LOGREC_FROM_FILE) {
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) {
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__);
21673
clfLogFilePtr.p->logFileStatus = LogFileRecord::CLOSING_EXEC_LOG;
21674
closeFile(signal, clfLogFilePtr, __LINE__);
21676
result = ZCLOSE_FILE;
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;
21687
}//Dblqh::returnExecLog()
21689
/* --------------------------------------------------------------------------
21690
* ------- SEIZE ADD FRAGMENT RECORD ------
21692
* ------------------------------------------------------------------------- */
21693
void Dblqh::seizeAddfragrec(Signal* signal)
21695
addfragptr.i = cfirstfreeAddfragrec;
21696
ptrCheckGuard(addfragptr, caddfragrecFileSize, addFragRecord);
21697
cfirstfreeAddfragrec = addfragptr.p->nextAddfragrec;
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()
21715
/* --------------------------------------------------------------------------
21716
* ------- SEIZE FRAGMENT RECORD -------
21718
* ------------------------------------------------------------------------- */
21719
/* ------------------------------------------------------------------------- */
21720
/* ------- SEIZE A PAGE REFERENCE RECORD. ------- */
21722
/* ------------------------------------------------------------------------- */
21723
void Dblqh::seizePageRef(Signal* signal)
21725
pageRefPtr.i = cfirstfreePageRef;
21726
ptrCheckGuard(pageRefPtr, cpageRefFileSize, pageRefRecord);
21727
cfirstfreePageRef = pageRefPtr.p->prNext;
21728
pageRefPtr.p->prNext = RNIL;
21729
}//Dblqh::seizePageRef()
21731
/* --------------------------------------------------------------------------
21732
* ------- SEND ABORTED -------
21734
* ------------------------------------------------------------------------- */
21735
void Dblqh::sendAborted(Signal* signal)
21738
if (tcConnectptr.p->nextReplica == ZNIL) {
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);
21750
}//Dblqh::sendAborted()
21752
/* --------------------------------------------------------------------------
21753
* ------- SEND LQH_TRANSCONF -------
21755
* ------------------------------------------------------------------------- */
21756
void Dblqh::sendLqhTransconf(Signal* signal, LqhTransConf::OperationStatus stat)
21758
tcNodeFailptr.i = tcConnectptr.p->tcNodeFailrec;
21759
ptrCheckGuard(tcNodeFailptr, ctcNodeFailrecFileSize, tcNodeFailRecord);
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);
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);
21796
ndbout_c("sending LQH_TRANSCONF %u transid: H'%.8x, H'%.8x op: %u state: %u(%u) marker: %u",
21798
tcConnectptr.p->transid[0],
21799
tcConnectptr.p->transid[1],
21800
tcConnectptr.p->operation,
21801
tcConnectptr.p->transactionState,
21803
tcConnectptr.p->commitAckMarker);
21805
}//Dblqh::sendLqhTransconf()
21807
/* --------------------------------------------------------------------------
21808
* ------- START ANOTHER PHASE OF LOG EXECUTION -------
21809
* RESET THE VARIABLES NEEDED BY THIS PROCESS AND SEND THE START SIGNAL
21811
* ------------------------------------------------------------------------- */
21812
void Dblqh::startExecSr(Signal* signal)
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()
21819
/* Ā¤Ā¤Ā¤Ā¤Ā¤Ā¤Ā¤Ā¤Ā¤Ā¤Ā¤Ā¤Ā¤Ā¤Ā¤Ā¤Ā¤Ā¤Ā¤Ā¤Ā¤Ā¤Ā¤Ā¤Ā¤Ā¤Ā¤Ā¤Ā¤Ā¤Ā¤Ā¤Ā¤Ā¤Ā¤Ā¤Ā¤Ā¤Ā¤Ā¤Ā¤Ā¤Ā¤Ā¤Ā¤Ā¤Ā¤Ā¤Ā¤Ā¤Ā¤Ā¤Ā¤Ā¤Ā¤Ā¤Ā¤Ā¤Ā¤Ā¤Ā¤Ā¤Ā¤Ā¤Ā¤Ā¤Ā¤Ā¤Ā¤Ā¤Ā¤Ā¤Ā¤Ā¤
21820
* Ā¤Ā¤Ā¤Ā¤Ā¤Ā¤Ā¤ LOG MODULE Ā¤Ā¤Ā¤Ā¤Ā¤Ā¤Ā¤
21821
* Ā¤Ā¤Ā¤Ā¤Ā¤Ā¤Ā¤Ā¤Ā¤Ā¤Ā¤Ā¤Ā¤Ā¤Ā¤Ā¤Ā¤Ā¤Ā¤Ā¤Ā¤Ā¤Ā¤Ā¤Ā¤Ā¤Ā¤Ā¤Ā¤Ā¤Ā¤Ā¤Ā¤Ā¤Ā¤Ā¤Ā¤Ā¤Ā¤Ā¤Ā¤Ā¤Ā¤Ā¤Ā¤Ā¤Ā¤Ā¤Ā¤Ā¤Ā¤Ā¤Ā¤Ā¤Ā¤Ā¤Ā¤Ā¤Ā¤Ā¤Ā¤Ā¤Ā¤Ā¤Ā¤Ā¤Ā¤Ā¤Ā¤Ā¤Ā¤Ā¤Ā¤ */
21822
/* --------------------------------------------------------------------------
21823
* ------- STEP FORWARD IN FRAGMENT LOG DURING LOG EXECUTION -------
21825
* ------------------------------------------------------------------------- */
21826
void Dblqh::stepAhead(Signal* signal, Uint32 stepAheadWords)
21830
tsaPos = logPagePtr.p->logPageWord[ZCURR_PAGE_INDEX];
21831
while ((stepAheadWords + tsaPos) >= ZPAGE_SIZE) {
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;
21845
logPagePtr.p->logPageWord[ZCURR_PAGE_INDEX] = stepAheadWords + tsaPos;
21846
}//Dblqh::stepAhead()
21848
/* --------------------------------------------------------------------------
21849
* ------- WRITE A ABORT LOG RECORD -------
21851
* SUBROUTINE SHORT NAME: WAL
21852
* ------------------------------------------------------------------------- */
21853
void Dblqh::writeAbortLog(Signal* signal)
21855
if ((ZABORT_LOG_SIZE + ZNEXT_LOG_SIZE) >
21856
logFilePtr.p->remainingWordsInMbyte) {
21858
changeMbyte(signal);
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()
21867
/* --------------------------------------------------------------------------
21868
* ------- WRITE A COMMIT LOG RECORD -------
21870
* SUBROUTINE SHORT NAME: WCL
21871
* ------------------------------------------------------------------------- */
21872
void Dblqh::writeCommitLog(Signal* signal, LogPartRecordPtr regLogPartPtr)
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) {
21887
changeMbyte(signal);
21888
twclTmp = logFilePtr.p->remainingWordsInMbyte;
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;
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);
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;
21925
TcConnectionrecPtr rloTcNextConnectptr;
21926
TcConnectionrecPtr rloTcPrevConnectptr;
21927
rloTcPrevConnectptr.i = regTcPtr->prevLogTcrec;
21928
rloTcNextConnectptr.i = regTcPtr->nextLogTcrec;
21929
if (rloTcNextConnectptr.i != RNIL) {
21931
ptrCheckGuard(rloTcNextConnectptr, ctcConnectrecFileSize, tcConnectionrec);
21932
rloTcNextConnectptr.p->prevLogTcrec = rloTcPrevConnectptr.i;
21934
regLogPartPtr.p->lastLogTcrec = rloTcPrevConnectptr.i;
21936
if (rloTcPrevConnectptr.i != RNIL) {
21938
ptrCheckGuard(rloTcPrevConnectptr, ctcConnectrecFileSize, tcConnectionrec);
21939
rloTcPrevConnectptr.p->nextLogTcrec = rloTcNextConnectptr.i;
21941
regLogPartPtr.p->firstLogTcrec = rloTcNextConnectptr.i;
21943
}//Dblqh::writeCommitLog()
21945
/* --------------------------------------------------------------------------
21946
* ------- WRITE A COMPLETED GCI LOG RECORD -------
21948
* SUBROUTINE SHORT NAME: WCG
21952
* ------------------------------------------------------------------------- */
21953
void Dblqh::writeCompletedGciLog(Signal* signal)
21955
if ((ZCOMPLETED_GCI_LOG_SIZE + ZNEXT_LOG_SIZE) >
21956
logFilePtr.p->remainingWordsInMbyte) {
21958
changeMbyte(signal);
21961
if (ERROR_INSERTED(5051) && (logFilePtr.p->currentFilepage > 0) &&
21962
(logFilePtr.p->currentFilepage % 32) == 0)
21964
SET_ERROR_INSERT_VALUE(5000);
21967
logFilePtr.p->remainingWordsInMbyte =
21968
logFilePtr.p->remainingWordsInMbyte - ZCOMPLETED_GCI_LOG_SIZE;
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);
21980
writeLogWord(signal, ZCOMPLETED_GCI_TYPE);
21981
writeLogWord(signal, cnewestCompletedGci);
21982
logPartPtr.p->logPartNewestCompletedGCI = cnewestCompletedGci;
21983
}//Dblqh::writeCompletedGciLog()
21985
/* --------------------------------------------------------------------------
21986
* ------- WRITE A DIRTY PAGE DURING LOG EXECUTION -------
21988
* SUBROUTINE SHORT NAME: WD
21989
* ------------------------------------------------------------------------- */
21990
void Dblqh::writeDirty(Signal* signal, Uint32 place)
21992
logPagePtr.p->logPageWord[ZPOS_DIRTY] = ZNOT_DIRTY;
21994
ndbassert(logPartPtr.p->prevFilepage ==
21995
logPagePtr.p->logPageWord[ZPOS_PAGE_NO]);
21996
writeDbgInfoPageHeader(logPagePtr, place, logPartPtr.p->prevFilepage,
21998
// Calculate checksum for page
21999
logPagePtr.p->logPageWord[ZPOS_CHECKSUM] = calcPageCheckSum(logPagePtr);
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);
22017
ndbrequire(logFilePtr.p->fileRef != RNIL);
22019
logPartPtr.p->m_io_tracker.send_io(32768);
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);
22029
}//Dblqh::writeDirty()
22031
/* --------------------------------------------------------------------------
22032
* ------- WRITE A WORD INTO THE LOG, CHECK FOR NEW PAGE -------
22034
* SUBROUTINE SHORT NAME: WLW
22035
* ------------------------------------------------------------------------- */
22036
void Dblqh::writeLogWord(Signal* signal, Uint32 data)
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) {
22044
completedLogPage(signal, ZNORMAL, __LINE__);
22045
seizeLogpage(signal);
22046
initLogpage(signal);
22047
logFilePtr.p->currentLogpage = logPagePtr.i;
22048
logFilePtr.p->currentFilepage++;
22050
}//Dblqh::writeLogWord()
22052
/* --------------------------------------------------------------------------
22053
* ------- WRITE MULTIPLE WORDS INTO THE LOG, CHECK FOR NEW PAGES -------
22055
* ------------------------------------------------------------------------- */
22057
void Dblqh::writeLogWords(Signal* signal, const Uint32* data, Uint32 len)
22059
Uint32 logPos = logPagePtr.p->logPageWord[ZCURR_PAGE_INDEX];
22060
ndbrequire(logPos < ZPAGE_SIZE);
22061
Uint32 wordsThisPage= ZPAGE_SIZE - logPos;
22063
while (len >= wordsThisPage)
22065
/* Fill rest of the log page */
22066
MEMCOPY_NO_WORDS(&logPagePtr.p->logPageWord[logPos],
22069
logPagePtr.p->logPageWord[ZCURR_PAGE_INDEX] = ZPAGE_SIZE;
22070
data+= wordsThisPage;
22071
len-= wordsThisPage;
22073
/* Mark page completed and get a new one */
22075
completedLogPage(signal, ZNORMAL, __LINE__);
22076
seizeLogpage(signal);
22077
initLogpage(signal);
22078
logFilePtr.p->currentLogpage = logPagePtr.i;
22079
logFilePtr.p->currentFilepage++;
22081
logPos = logPagePtr.p->logPageWord[ZCURR_PAGE_INDEX];
22082
ndbrequire(logPos < ZPAGE_SIZE);
22083
wordsThisPage= ZPAGE_SIZE - logPos;
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],
22094
logPagePtr.p->logPageWord[ZCURR_PAGE_INDEX] = logPos + len;
22097
ndbassert( logPagePtr.p->logPageWord[ZCURR_PAGE_INDEX] < ZPAGE_SIZE );
22100
/* --------------------------------------------------------------------------
22101
* ------- WRITE A NEXT LOG RECORD AND CHANGE TO NEXT MBYTE -------
22103
* SUBROUTINE SHORT NAME: WNL
22105
// logFilePtr(Redefines)
22106
// logPagePtr (Redefines)
22108
* ------------------------------------------------------------------------- */
22109
void Dblqh::writeNextLog(Signal* signal)
22111
LogFileRecordPtr wnlNextLogFilePtr;
22112
UintR twnlNextFileNo;
22113
UintR twnlNewMbyte;
22114
UintR twnlRemWords;
22115
UintR twnlNextMbyte;
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]] =
22133
if (logFilePtr.p->currentMbyte == (clogFileSize - 1)) {
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) {
22153
/* -------------------------------------------------- */
22154
/* WE HAVE FINALISED A LOG LAP, START FROM LOG */
22156
/* -------------------------------------------------- */
22157
logPartPtr.p->logLap++;
22159
logPartPtr.p->currentLogfile = wnlNextLogFilePtr.i;
22160
logFilePtr.i = wnlNextLogFilePtr.i;
22161
logFilePtr.p = wnlNextLogFilePtr.p;
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;
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) {
22188
logFilePtr.p->lastPageWritten = 0;
22189
if (logFilePtr.p->fileNo == 0) {
22191
releaseLogpage(signal);
22192
logPagePtr.i = logFilePtr.p->logPageZero;
22193
ptrCheckGuard(logPagePtr, clogPageFileSize, logPageRecord);
22196
initLogpage(signal);
22197
logFilePtr.p->currentLogpage = logPagePtr.i;
22198
if (logFilePtr.p->currentMbyte == 0) {
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;
22209
if (logFilePtr.p->fileNo == logPartPtr.p->logTailFileNo)
22211
if (logFilePtr.p->currentMbyte == logPartPtr.p->logTailMbyte)
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
/* -------------------------------------------------- */
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);
22232
signal->theData[0] = 2398;
22233
execDUMP_STATE_ORD(signal);
22234
progError(__LINE__, NDBD_EXIT_NO_MORE_REDOLOG, buf);
22235
systemError(signal, __LINE__);
22238
if (logFilePtr.p->currentMbyte == (clogFileSize - 1)) {
22241
if (logFilePtr.p->fileChangeState != LogFileRecord::NOT_ONGOING)
22244
update_log_problem(signal, logPartPtr,
22245
LogPartRecord::P_FILE_CHANGE_PROBLEM,
22248
twnlNextFileNo = wnlNextLogFilePtr.p->fileNo;
22251
twnlNextMbyte = logFilePtr.p->currentMbyte + 1;
22252
twnlNextFileNo = logFilePtr.p->fileNo;
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)
22264
if (free_mb <= c_free_mb_tail_problem_limit)
22267
update_log_problem(signal, logPartPtr, LogPartRecord::P_TAIL_PROBLEM, true);
22270
if (ERROR_INSERTED(5058) &&
22271
(twnlNextMbyte + 3 >= clogFileSize) &&
22272
logFilePtr.p->fileNo != 0 &&
22273
logFilePtr.p->nextLogFile != logPartPtr.p->firstLogfile)
22276
srand((int)time(0));
22277
Uint32 wait = 3 + (rand() % 5);
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;
22286
if (ERROR_INSERTED(5059) &&
22287
twnlNextMbyte == 4 &&
22288
logFilePtr.p->fileNo != 0)
22290
signal->theData[0] = 9999;
22291
sendSignal(CMVMI_REF, GSN_NDB_TAMPER, signal, 1, JBA);
22294
}//Dblqh::writeNextLog()
22297
Dblqh::validate_filter(Signal* signal)
22299
Uint32 * start = signal->theData + 1;
22300
Uint32 * end = signal->theData + signal->getLength();
22303
infoEvent("No filter specified, not listing...");
22304
if (!ERROR_INSERTED(4002))
22314
case 1: // API Node
22322
infoEvent("Invalid filter op: 0x%x pos: %ld",
22324
(long int)(start - (signal->theData + 1)));
22331
infoEvent("Invalid filter, unexpected end");
22339
Dblqh::match_and_print(Signal* signal, Ptr<TcConnectionrec> tcRec)
22341
Uint32 len = signal->getLength();
22342
Uint32* start = signal->theData + 3;
22343
Uint32* end = signal->theData + len;
22344
while (start < end)
22348
if (tcRec.p->tableref != * (start + 1))
22353
if (refToNode(tcRec.p->applRef) != * (start + 1))
22358
if (tcRec.p->transid[0] != * (start + 1) ||
22359
tcRec.p->transid[1] != * (start + 2))
22364
if (refToNode(tcRec.p->tcBlockref) != * (start + 1))
22383
Uint32 *temp = signal->theData + 25;
22384
memcpy(temp, signal->theData, 4 * len);
22387
const char* op = "<Unknown>";
22388
if (tcRec.p->tcScanRec != RNIL)
22391
sp.i = tcRec.p->tcScanRec;
22392
c_scanRecordPool.getPtr(sp);
22394
if (sp.p->scanLockMode)
22396
else if(sp.p->scanLockHold)
22401
switch(sp.p->scanState){
22402
case ScanRecord::WAIT_NEXT_SCAN:
22403
BaseString::snprintf(state, sizeof(state), "WaitNextScan");
22405
case ScanRecord::IN_QUEUE:
22406
BaseString::snprintf(state, sizeof(state), "InQueue");
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);
22427
switch(tcRec.p->operation){
22429
if (tcRec.p->lockType)
22431
else if(!tcRec.p->dirtyOp)
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;
22443
switch(tcRec.p->transactionState){
22444
case TcConnectionrec::IDLE:
22445
case TcConnectionrec::WAIT_ACC:
22446
BaseString::snprintf(state, sizeof(state), "In lock queue");
22448
case TcConnectionrec::WAIT_TUPKEYINFO:
22449
case TcConnectionrec::WAIT_ATTR:
22450
BaseString::snprintf(state, sizeof(state), "WaitData");
22452
case TcConnectionrec::WAIT_TUP:
22453
BaseString::snprintf(state, sizeof(state), "Running");
22455
case TcConnectionrec::WAIT_TUP_COMMIT:
22456
BaseString::snprintf(state, sizeof(state), "Committing");
22458
case TcConnectionrec::PREPARED:
22459
BaseString::snprintf(state, sizeof(state), "Prepared");
22461
case TcConnectionrec::COMMITTED:
22462
BaseString::snprintf(state, sizeof(state), "Committed");
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);
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",
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],
22511
if (!ERROR_INSERTED(4002))
22512
infoEvent("%s", buf);
22514
ndbout_c("%s", buf);
22516
memcpy(signal->theData, temp, 4*len);
22521
Dblqh::execDUMP_STATE_ORD(Signal* signal)
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());
22531
if(dumpState->args[0] == DumpStateOrd::CommitAckMarkersDump){
22532
infoEvent("LQH: m_commitAckMarkerPool: %d free size: %d",
22533
m_commitAckMarkerPool.getNoOfFree(),
22534
m_commitAckMarkerPool.getSize());
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",
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);
22551
// Dump info about number of log pages
22552
if(dumpState->args[0] == DumpStateOrd::LqhDumpNoLogPages){
22553
infoEvent("LQH: Log pages : %d Free: %d",
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;
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);
22569
for (Uint32 j = 0; j<MAX_FRAG_PER_NODE; j++)
22571
FragrecordPtr fragPtr;
22572
if ((fragPtr.i = tabPtr.p->fragrec[j]) != RNIL)
22574
c_fragment_pool.getPtr(fragPtr);
22575
infoEvent(" frag: %d distKey: %u",
22576
tabPtr.p->fragid[j],
22577
fragPtr.p->fragDistributionKey);
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",
22591
else if (signal->length() == 2)
22592
recordNo = dumpState->args[1];
22596
dumpState->args[0] = DumpStateOrd::LqhDumpOneScanRec;
22597
dumpState->args[1] = recordNo;
22598
execDUMP_STATE_ORD(signal);
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);
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",
22614
else if (signal->length() == 2)
22615
recordNo = dumpState->args[1];
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);
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);
22636
if(dumpState->args[0] == DumpStateOrd::LqhDumpOneScanRec){
22637
Uint32 recordNo = RNIL;
22638
if (signal->length() == 2)
22639
recordNo = dumpState->args[1];
22643
if (recordNo >= cscanrecFileSize)
22648
c_scanRecordPool.getPtr(sp);
22649
infoEvent("Dblqh::ScanRecord[%d]: state=%d, type=%d, "
22650
"complStatus=%d, scanNodeId=%d",
22654
sp.p->scanCompletedStatus,
22656
infoEvent(" apiBref=0x%x, scanAccPtr=%d",
22657
sp.p->scanApiBlockref,
22659
infoEvent(" copyptr=%d, ailen=%d, complOps=%d, concurrOps=%d",
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,
22670
sp.p->scanLockHold,
22671
sp.p->scanLockMode,
22673
infoEvent(" relCount=%d, TCwait=%d, TCRec=%d, KIflag=%d",
22674
sp.p->scanReleaseCounter,
22675
sp.p->scanTcWaiting,
22677
sp.p->scanKeyinfoFlag);
22680
if(dumpState->args[0] == DumpStateOrd::LqhDumpLcpState){
22682
infoEvent("== LQH LCP STATE ==");
22683
infoEvent(" clcpCompletedState=%d, c_lcpId=%d, cnoOfFragsCheckpointed=%d",
22684
clcpCompletedState,
22686
cnoOfFragsCheckpointed);
22688
LcpRecordPtr TlcpPtr;
22689
// Print information about the current local checkpoint
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));
22707
if (dumpState->args[0] == DumpStateOrd::LQHLogFileInitStatus){
22708
reportStatus(signal);
22712
#ifdef ERROR_INSERT
22713
#ifdef NDB_DEBUG_FULL
22714
if(dumpState->args[0] == DumpStateOrd::LCPContinue){
22715
switch(cerrorInsert){
22717
CLEAR_ERROR_INSERT_VALUE;
22718
g_trace_lcp.restore(*globalData.getBlock(BACKUP), signal);
22727
if(arg == 2304 || arg == 2305)
22731
void * logPartPtr = 0;
22733
GcpRecordPtr gcp; gcp.i = RNIL;
22734
for(i = 0; i < clogPartFileSize; i++)
22736
Ptr<LogPartRecord> lp;
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",
22743
lp.p->logPartState,
22744
lp.p->waitWriteGciLog,
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,
22752
lp.p->m_log_problems);
22754
if(gcp.i == RNIL && lp.p->gcprec != RNIL)
22755
gcp.i = lp.p->gcprec;
22757
LogFileRecordPtr logFilePtr;
22758
Uint32 first= logFilePtr.i= lp.p->firstLogfile;
22761
ptrCheckGuard(logFilePtr, clogFileFileSize, logFileRecord);
22762
ndbout_c(" file %d(%d) FileChangeState: %d logFileStatus: %d currentMbyte: %d currentFilepage %d",
22763
logFilePtr.p->fileNo,
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);
22775
ptrCheckGuard(gcp, cgcprecFileSize, gcpRecord);
22776
for(i = 0; i<4; i++)
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]);
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");
22797
if (dumpState->args[0] == DumpStateOrd::LqhErrorInsert5042 && (signal->getLength() >= 2))
22799
c_error_insert_table_id = dumpState->args[1];
22800
if (signal->getLength() == 2)
22802
SET_ERROR_INSERT_VALUE(5042);
22806
SET_ERROR_INSERT_VALUE(dumpState->args[2]);
22810
TcConnectionrec *regTcConnectionrec = tcConnectionrec;
22811
Uint32 ttcConnectrecFileSize = ctcConnectrecFileSize;
22814
for(Uint32 i = 0; i<1024; i++)
22816
TcConnectionrecPtr tcRec;
22817
tcRec.i = ctransidHash[i];
22818
while(tcRec.i != RNIL)
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;
22830
if(arg == 2307 || arg == 2308)
22832
TcConnectionrecPtr tcRec;
22833
tcRec.i = signal->theData[1];
22834
ptrCheckGuard(tcRec, ttcConnectrecFileSize, regTcConnectionrec);
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
22841
ndbout << " replicaType = " << tcRec.p->replicaType
22842
<< " reclenAiLqhkey = " << tcRec.p->reclenAiLqhkey
22843
<< " opExec = " << tcRec.p->opExec
22845
ndbout << " opSimple = " << tcRec.p->opSimple
22846
<< " nextSeqNoReplica = " << tcRec.p->nextSeqNoReplica
22847
<< " lockType = " << tcRec.p->lockType
22849
ndbout << " lastReplicaNo = " << tcRec.p->lastReplicaNo
22850
<< " indTakeOver = " << tcRec.p->indTakeOver
22851
<< " dirtyOp = " << tcRec.p->dirtyOp
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)
22859
ndbout << " nextReplica = " << tcRec.p->nextReplica
22860
<< " tcBlockref = " << hex << tcRec.p->tcBlockref
22861
<< " reqBlockref = " << hex << tcRec.p->reqBlockref
22862
<< " primKeyLen = " << tcRec.p->primKeyLen
22864
ndbout << " logStopPageNo = " << tcRec.p->logStopPageNo
22865
<< " logStartPageNo = " << tcRec.p->logStartPageNo
22866
<< " logStartPageIndex = " << tcRec.p->logStartPageIndex
22868
ndbout << " errorCode = " << tcRec.p->errorCode
22869
<< " clientBlockref = " << hex << tcRec.p->clientBlockref
22870
<< " applRef = " << hex << tcRec.p->applRef
22871
<< " totSendlenAi = " << tcRec.p->totSendlenAi
22873
ndbout << " totReclenAi = " << tcRec.p->totReclenAi
22874
<< " tcScanRec = " << tcRec.p->tcScanRec
22875
<< " tcScanInfo = " << tcRec.p->tcScanInfo
22876
<< " tcOprec = " << hex << tcRec.p->tcOprec
22878
ndbout << " tableref = " << tcRec.p->tableref
22879
<< " simpleTcConnect = " << tcRec.p->simpleTcConnect
22880
<< " storedProcId = " << tcRec.p->storedProcId
22881
<< " schemaVersion = " << tcRec.p->schemaVersion
22883
ndbout << " reqinfo = " << tcRec.p->reqinfo
22884
<< " reqRef = " << tcRec.p->reqRef
22885
<< " readlenAi = " << tcRec.p->readlenAi
22886
<< " prevTc = " << tcRec.p->prevTc
22888
ndbout << " prevLogTcrec = " << tcRec.p->prevLogTcrec
22889
<< " prevHashRec = " << tcRec.p->prevHashRec
22890
<< " nodeAfterNext0 = " << tcRec.p->nodeAfterNext[0]
22891
<< " nodeAfterNext1 = " << tcRec.p->nodeAfterNext[1]
22893
ndbout << " nextTcConnectrec = " << tcRec.p->nextTcConnectrec
22894
<< " nextTc = " << tcRec.p->nextTc
22895
<< " nextTcLogQueue = " << tcRec.p->nextTcLogQueue
22896
<< " nextLogTcrec = " << tcRec.p->nextLogTcrec
22898
ndbout << " nextHashRec = " << tcRec.p->nextHashRec
22899
<< " logWriteState = " << tcRec.p->logWriteState
22900
<< " logStartFileNo = " << tcRec.p->logStartFileNo
22901
<< " listState = " << tcRec.p->listState
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
22908
ndbout << " hashValue = " << tcRec.p->hashValue
22909
<< " currTupAiLen = " << tcRec.p->currTupAiLen
22910
<< " currReclenAi = " << tcRec.p->currReclenAi
22912
ndbout << " tcTimer = " << tcRec.p->tcTimer
22913
<< " clientConnectrec = " << tcRec.p->clientConnectrec
22914
<< " applOprec = " << hex << tcRec.p->applOprec
22915
<< " abortState = " << tcRec.p->abortState
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)
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
22926
switch (tcRec.p->transactionState) {
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
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
22944
ndbout << " scanSchemaVersion="<<TscanPtr.p->scanSchemaVersion
22945
<< " scanStoredProcId="<<TscanPtr.p->scanStoredProcId
22946
<< " scanTcrec="<<TscanPtr.p->scanTcrec
22948
ndbout << " scanType="<<TscanPtr.p->scanType
22949
<< " scanApiBlockref="<<TscanPtr.p->scanApiBlockref
22950
<< " scanNodeId="<<TscanPtr.p->scanNodeId
22951
<< " scanCompletedStatus="<<TscanPtr.p->scanCompletedStatus
22953
ndbout << " scanFlag="<<TscanPtr.p->scanFlag
22954
<< " scanLockHold="<<TscanPtr.p->scanLockHold
22955
<< " scanLockMode="<<TscanPtr.p->scanLockMode
22956
<< " scanNumber="<<TscanPtr.p->scanNumber
22958
ndbout << " scanReleaseCounter="<<TscanPtr.p->scanReleaseCounter
22959
<< " scanTcWaiting="<<TscanPtr.p->scanTcWaiting
22960
<< " scanKeyinfoFlag="<<TscanPtr.p->scanKeyinfoFlag
22963
ndbout << "No connected scan record found" << endl;
22969
ndbrequire(arg != 2308);
22972
#ifdef NDBD_TRACENR
22973
if (arg == 5712 || arg == 5713)
22977
traceopout = &ndbout;
22979
else if (arg == 5713)
22981
traceopout = tracenrout;
22983
SET_ERROR_INSERT_VALUE(arg);
22990
Uint32 len = signal->getLength() - 1;
22994
infoEvent("Too long filter");
22997
if (validate_filter(signal))
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);
23006
infoEvent("Starting dump of operations");
23014
Uint32 bucket = signal->theData[1];
23015
Uint32 record = signal->theData[2];
23016
Uint32 len = signal->getLength();
23017
TcConnectionrecPtr tcRec;
23018
if (record != RNIL)
23022
* Check that record is still in use...
23025
ptrCheckGuard(tcRec, ttcConnectrecFileSize, regTcConnectionrec);
23027
Uint32 hashIndex = (tcRec.p->transid[0] ^ tcRec.p->tcOprec) & 1023;
23028
if (hashIndex != bucket)
23036
if (tcRec.p->nextHashRec == RNIL &&
23037
tcRec.p->prevHashRec == RNIL &&
23038
ctransidHash[hashIndex] != record)
23045
if (record == RNIL)
23048
signal->theData[2] = RNIL;
23049
sendSignal(reference(), GSN_DUMP_STATE_ORD, signal,
23050
signal->getLength(), JBB);
23054
else if ((record = ctransidHash[bucket]) == RNIL)
23061
signal->theData[1] = bucket;
23062
signal->theData[2] = RNIL;
23063
sendSignal(reference(), GSN_DUMP_STATE_ORD, signal,
23064
signal->getLength(), JBB);
23069
infoEvent("End of operation dump");
23070
if (ERROR_INSERTED(4002))
23082
ptrCheckGuard(tcRec, ttcConnectrecFileSize, regTcConnectionrec);
23085
for (Uint32 i = 0; i<32; i++)
23088
bool print = match_and_print(signal, tcRec);
23090
tcRec.i = tcRec.p->nextHashRec;
23091
if (tcRec.i == RNIL || print)
23097
ptrCheckGuard(tcRec, ttcConnectrecFileSize, regTcConnectionrec);
23100
if (tcRec.i == RNIL)
23107
signal->theData[1] = bucket;
23108
signal->theData[2] = RNIL;
23109
sendSignal(reference(), GSN_DUMP_STATE_ORD, signal, len, JBB);
23114
infoEvent("End of operation dump");
23115
if (ERROR_INSERTED(4002))
23126
signal->theData[2] = tcRec.i;
23127
sendSignalWithDelay(reference(), GSN_DUMP_STATE_ORD, signal, 200, len);
23132
if (arg == 2352 && signal->getLength() == 2)
23135
Uint32 opNo = signal->theData[1];
23136
TcConnectionrecPtr tcRec;
23137
if (opNo < ttcConnectrecFileSize)
23141
ptrCheckGuard(tcRec, ttcConnectrecFileSize, regTcConnectionrec);
23144
if (tcRec.p->keyInfoIVal != RNIL)
23147
SectionReader keyInfoReader(tcRec.p->keyInfoIVal,
23148
g_sectionSegmentPool);
23151
while (keyInfoReader.getWord(&keyWord))
23152
key.appfmt("0x%x ", keyWord);
23156
BaseString::snprintf(buf, sizeof(buf),
23157
"OP[%u]: transid: 0x%x 0x%x key: %s",
23159
tcRec.p->transid[0], tcRec.p->transid[1], key.c_str());
23160
infoEvent("%s", buf);
23164
if (arg == DumpStateOrd::SchemaResourceSnapshot)
23166
RSS_AP_SNAPSHOT_SAVE(c_fragment_pool);
23170
if (arg == DumpStateOrd::SchemaResourceCheckLeak)
23172
RSS_AP_SNAPSHOT_CHECK(c_fragment_pool);
23179
for (Uint32 i = 0; i<1024; i++)
23181
if (ctransidHash[i] != RNIL)
23189
bool markers = m_commitAckMarkerPool.getNoOfFree() !=
23190
m_commitAckMarkerPool.getSize();
23191
if (unlikely(ops || markers))
23196
ndbout_c("LQH: m_commitAckMarkerPool: %d free size: %d",
23197
m_commitAckMarkerPool.getNoOfFree(),
23198
m_commitAckMarkerPool.getSize());
23200
CommitAckMarkerIterator iter;
23201
for(m_commitAckMarkerHash.first(iter); iter.curr.i != RNIL;
23202
m_commitAckMarkerHash.next(iter))
23204
ndbout_c("CommitAckMarker: i = %d (H'%.8x, H'%.8x)"
23205
" ApiRef: 0x%x apiOprec: 0x%x TcNodeId: %d ref_count: %u",
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);
23215
SET_ERROR_INSERT_VALUE(4002);
23216
signal->theData[0] = 2350;
23217
EXECUTE_DIRECT(DBLQH, GSN_DUMP_STATE_ORD, signal, 1);
23225
if (cstartRecReq < SRR_REDO_COMPLETE)
23231
for(Uint32 i = 0; i<4; i++)
23234
ptrCheckGuard(logPartPtr, clogPartFileSize, logPartRecord);
23235
LogFileRecordPtr logFile;
23236
logFile.i = logPartPtr.p->currentLogfile;
23237
ptrCheckGuard(logFile, clogFileFileSize, logFileRecord);
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);
23262
if (cstartRecReq < SRR_REDO_COMPLETE)
23268
for(Uint32 i = 0; i<clogPartFileSize; i++)
23271
ptrCheckGuard(logPartPtr, clogPartFileSize, logPartRecord);
23272
LogFileRecordPtr logFile;
23273
logFile.i = logPartPtr.p->currentLogfile;
23274
ptrCheckGuard(logFile, clogFileFileSize, logFileRecord);
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,
23289
}//Dblqh::execDUMP_STATE_ORD()
23292
void Dblqh::execDBINFO_SCANREQ(Signal *signal)
23294
DbinfoScanReq req= *(DbinfoScanReq*)signal->theData;
23295
const Ndbinfo::ScanCursor* cursor =
23296
CAST_CONSTPTR(Ndbinfo::ScanCursor, DbinfoScan::getCursorPtr(&req));
23297
Ndbinfo::Ratelimit rl;
23301
switch(req.tableId){
23302
case Ndbinfo::LOGSPACES_TABLEID:
23304
Uint32 logpart = cursor->data[0];
23305
while(logpart < clogPartFileSize)
23309
logPartPtr.i = logpart;
23310
ptrCheckGuard(logPartPtr, clogPartFileSize, logPartRecord);
23312
LogFileRecordPtr logFile;
23313
logFile.i = logPartPtr.p->currentLogfile;
23314
ptrCheckGuard(logFile, clogFileFileSize, logFileRecord);
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
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
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);
23334
if (rl.need_break(req))
23337
ndbinfo_send_scan_break(signal, req, rl, logpart);
23344
case Ndbinfo::LOGBUFFERS_TABLEID:
23346
const size_t entry_size = sizeof(LogPageRecord);
23347
const Uint64 free = cnoOfLogPages;
23348
const Uint64 total = clogPageCount;
23349
const Uint64 high = 0; // TODO
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
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);
23365
case Ndbinfo::COUNTERS_TABLEID:
23367
Ndbinfo::counter_entry counters[] = {
23368
{ Ndbinfo::OPERATIONS_COUNTER, c_Counters.operations }
23370
const size_t num_counters = sizeof(counters) / sizeof(counters[0]);
23372
Uint32 i = cursor->data[0];
23373
BlockNumber bn = blockToMain(number());
23374
while(i < num_counters)
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);
23383
row.write_uint64(counters[i].val);
23384
ndbinfo_send_row(signal, req, row, rl);
23386
if (rl.need_break(req))
23389
ndbinfo_send_scan_break(signal, req, rl, i);
23400
ndbinfo_send_scan_conf(signal, req, rl);
23404
/* **************************************************************** */
23405
/* ---------------------------------------------------------------- */
23406
/* ---------------------- TRIGGER HANDLING ------------------------ */
23407
/* ---------------------------------------------------------------- */
23409
/* All trigger signals from TRIX are forwarded top TUP */
23410
/* ---------------------------------------------------------------- */
23411
/* **************************************************************** */
23415
Dblqh::execCREATE_TRIG_IMPL_REQ(Signal* signal)
23419
if (!assembleFragments(signal))
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);
23434
Dblqh::execCREATE_TRIG_IMPL_CONF(Signal* signal)
23438
BlockReference dictRef = !isNdbMtLqh() ? DBDICT_REF : DBLQH_REF;
23439
sendSignal(dictRef, GSN_CREATE_TRIG_IMPL_CONF, signal,
23440
CreateTrigImplConf::SignalLength, JBB);
23444
Dblqh::execCREATE_TRIG_IMPL_REF(Signal* signal)
23448
BlockReference dictRef = !isNdbMtLqh() ? DBDICT_REF : DBLQH_REF;
23449
sendSignal(dictRef, GSN_CREATE_TRIG_IMPL_REF, signal,
23450
CreateTrigImplRef::SignalLength, JBB);
23454
Dblqh::execDROP_TRIG_IMPL_REQ(Signal* signal)
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);
23466
Dblqh::execDROP_TRIG_IMPL_CONF(Signal* signal)
23470
BlockReference dictRef = !isNdbMtLqh() ? DBDICT_REF : DBLQH_REF;
23471
sendSignal(dictRef, GSN_DROP_TRIG_IMPL_CONF, signal,
23472
DropTrigImplConf::SignalLength, JBB);
23476
Dblqh::execDROP_TRIG_IMPL_REF(Signal* signal)
23480
BlockReference dictRef = !isNdbMtLqh() ? DBDICT_REF : DBLQH_REF;
23481
sendSignal(dictRef, GSN_DROP_TRIG_IMPL_REF, signal,
23482
DropTrigImplRef::SignalLength, JBB);
23485
Uint32 Dblqh::calcPageCheckSum(LogPageRecordPtr logP){
23486
Uint32 checkSum = 37;
23488
for (Uint32 i = (ZPOS_CHECKSUM+1); i<ZPAGE_SIZE; i++)
23489
checkSum = logP.p->logPageWord[i] ^ checkSum;
23494
#ifdef NDB_DEBUG_FULL
23495
#ifdef ERROR_INSERT
23497
TraceLCP::sendSignal(Uint32 ref, Uint32 gsn, Signal* signal,
23498
Uint32 len, Uint32 prio)
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);
23512
TraceLCP::save(Signal* signal){
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);
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,
23532
sig->header.theLength,
23535
case Sig::Sig_save:
23536
lqh.executeFunction(sig->header.theVerId_signalNumber, sig);
23545
void Dblqh::writeDbgInfoPageHeader(LogPageRecordPtr logP, Uint32 place,
23546
Uint32 pageNo, Uint32 wordWritten)
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;
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);
23564
void Dblqh::checkReportStatus(Signal* signal){
23565
if (m_startup_report_frequency == 0)
23568
NDB_TICKS current_time = NdbTick_CurrentMillisecond();
23569
if (current_time > m_next_report_time)
23571
reportStatus(signal);
23572
m_next_report_time = current_time +
23573
((NDB_TICKS)m_startup_report_frequency) * ((NDB_TICKS)1000);
23577
void Dblqh::reportStatus(Signal* signal){
23578
const int signal_length = 6;
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;
23590
sendSignal(CMVMI_REF, GSN_EVENT_REP, signal, signal_length, JBB);
23593
void Dblqh::logfileInitCompleteReport(Signal* signal){
23594
const int signal_length = 6;
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);
23605
#ifdef NDBD_TRACENR
23607
Dblqh::TRACE_OP_DUMP(const Dblqh::TcConnectionrec* regTcPtr, const char * pos)
23610
<< "[ " << hex << regTcPtr->transid[0]
23611
<< " " << hex << regTcPtr->transid[1] << " ] " << dec
23613
<< " " << (Operation_t)regTcPtr->operation
23614
<< " " << regTcPtr->tableref
23615
<< "(" << regTcPtr->fragmentid << ")"
23616
<< "(" << (regTcPtr->seqNoReplica == 0 ? "P" : "B") << ")" ;
23619
(* traceopout) << "key=[" << hex;
23620
if (regTcPtr->keyInfoIVal != RNIL)
23622
SectionReader keyInfoReader(regTcPtr->keyInfoIVal,
23623
g_sectionSegmentPool);
23626
while (keyInfoReader.getWord(&keyWord))
23627
(* traceopout) << hex << keyWord << " ";
23629
(* traceopout) << "] ";
23632
if (regTcPtr->m_use_rowid)
23633
(* traceopout) << " " << regTcPtr->m_row_id;
23634
(* traceopout) << endl;
23639
Dblqh::get_node_status(Uint32 nodeId) const
23641
HostRecordPtr Thostptr;
23642
Thostptr.i = nodeId;
23643
ptrCheckGuard(Thostptr, chostFileSize, hostRecord);
23644
return Thostptr.p->nodestatus;
23647
#ifndef NO_REDO_PAGE_CACHE
23649
* Don't cache pages if less then 64 pages are free
23651
#define MIN_REDO_PAGES_FREE 64
23654
Dblqh::do_evict(RedoPageCache& cache, Ptr<RedoCacheLogPageRecord> pagePtr)
23656
LogPageRecordPtr save = logPagePtr;
23657
cache.m_lru.remove(pagePtr);
23658
cache.m_hash.remove(pagePtr);
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,
23666
logPagePtr.i = pagePtr.i;
23667
ptrCheckGuard(logPagePtr, clogPageFileSize, logPageRecord);
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)
23676
* Remove ZNEXT pointer from prevPagePtr
23677
* so we don't try to "serve" multi-page request
23678
* if next-page has been evicted
23680
ptrCheckGuard(prevPagePtr, clogPageFileSize, logPageRecord);
23681
ndbrequire(prevPagePtr.p->logPageWord[ZNEXT_PAGE] == logPagePtr.i);
23682
prevPagePtr.p->logPageWord[ZNEXT_PAGE] = RNIL;
23685
if (nextPagePtr.i != RNIL)
23689
* Remove ZPREV pointer from nextPagePtr
23690
* so don't try to do above if prev has been evicted
23692
ptrCheckGuard(nextPagePtr, clogPageFileSize, logPageRecord);
23693
ndbrequire(nextPagePtr.p->logPageWord[ZPREV_PAGE] == logPagePtr.i);
23694
nextPagePtr.p->logPageWord[ZPREV_PAGE] = RNIL;
23702
Dblqh::evict(RedoPageCache& cache, Uint32 cnt)
23704
while (cnoOfLogPages < (cnt + MIN_REDO_PAGES_FREE) && !cache.m_lru.isEmpty())
23707
Ptr<RedoCacheLogPageRecord> pagePtr;
23708
cache.m_lru.last(pagePtr);
23709
do_evict(cache, pagePtr);
23714
Dblqh::addCachePages(RedoPageCache& cache,
23716
Uint32 startPageNo,
23717
LogFileOperationRecord* lfoPtrP)
23719
Uint32 cnt = lfoPtrP->noPagesRw;
23720
Ptr<LogFileRecord> filePtr;
23721
filePtr.i = lfoPtrP->logFileRec;
23722
ptrCheckGuard(filePtr, clogFileFileSize, logFileRecord);
23726
if (cnoOfLogPages < cnt + MIN_REDO_PAGES_FREE)
23729
* Don't cache if low on redo-buffer
23734
for (Uint32 i = 0; i<cnt ; i++)
23736
Ptr<RedoCacheLogPageRecord> pagePtr;
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;
23743
bool found = false;
23745
RedoCacheLogPageRecord key;
23746
key.m_part_no = partNo;
23747
key.m_page_no = startPageNo + i;
23748
key.m_file_no = filePtr.p->fileNo;
23749
Ptr<RedoCacheLogPageRecord> tmp;
23750
if (cache.m_hash.find(tmp, key))
23754
do_evict(cache, tmp);
23758
cache.m_hash.add(pagePtr);
23759
cache.m_lru.addFirst(pagePtr);
23761
ndbout_c("adding(%u) part: %u file: %u page: %u cnoOfLogPages: %u cnt: %u",
23763
pagePtr.p->m_part_no,
23764
pagePtr.p->m_file_no,
23765
pagePtr.p->m_page_no,
23771
* Make sure pages are not released when prepare-record is executed
23772
* @see releaseLfoPages
23774
lfoPtrP->firstLfoPage = RNIL;
23778
Dblqh::release(RedoPageCache& cache)
23780
while (!cache.m_lru.isEmpty())
23783
Ptr<RedoCacheLogPageRecord> pagePtr;
23784
cache.m_lru.last(pagePtr);
23785
cache.m_lru.remove(pagePtr);
23787
logPagePtr.i = pagePtr.i;
23788
ptrCheckGuard(logPagePtr, clogPageFileSize, logPageRecord);
23791
cache.m_hash.removeAll();
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);
23798
cache.m_multi_page = 0;
23799
cache.m_multi_miss = 0;
23803
#ifndef NO_REDO_OPEN_FILE_CACHE
23805
#define MAX_CACHED_OPEN_FILES 4
23808
Dblqh::openFileRw_cache(Signal* signal,
23809
LogFileRecordPtr filePtr)
23813
LogFileRecord::LogFileStatus state = filePtr.p->logFileStatus;
23814
if (state != LogFileRecord::CLOSED)
23818
m_redo_open_file_cache.m_hits++;
23820
if (m_redo_open_file_cache.m_lru.hasPrev(filePtr))
23823
m_redo_open_file_cache.m_lru.remove(filePtr);
23824
m_redo_open_file_cache.m_lru.addFirst(filePtr);
23827
filePtr.p->logFileStatus = LogFileRecord::OPEN_EXEC_LOG_CACHED;
23829
signal->theData[0] = filePtr.i;
23830
signal->theData[1] = filePtr.p->fileRef;
23831
sendSignal(reference(), GSN_FSOPENCONF, signal, 2, JBB);
23835
filePtr.p->logFileStatus = LogFileRecord::OPEN_EXEC_LOG;
23836
openFileRw(signal, filePtr, false);
23840
Dblqh::closeFile_cache(Signal* signal,
23841
LogFileRecordPtr filePtr,
23846
filePtr.p->logFileStatus = LogFileRecord::CLOSING_EXEC_LOG_CACHED;
23847
if (m_redo_open_file_cache.m_lru.count() >= MAX_CACHED_OPEN_FILES)
23850
Ptr<LogFileRecord> evictPtr;
23851
Uint32 logPartRec = filePtr.p->logPartRec;
23853
* Only evict file with same log-part, other redo-execution will continue
23854
* for the log-part once file is closed
23856
* Note: 1) loop is guaranteed to terminate as filePtr must be in list
23857
* 2) loop is ok as MAX_CACHED_OPEN_FILES is "small"
23858
* (if it was big, the m_lru should be split per log-part)
23860
m_redo_open_file_cache.m_lru.last(evictPtr);
23861
while (evictPtr.p->logPartRec != logPartRec)
23864
ndbrequire(m_redo_open_file_cache.m_lru.prev(evictPtr));
23866
m_redo_open_file_cache.m_lru.remove(evictPtr);
23867
evictPtr.p->logFileStatus = LogFileRecord::CLOSING_EXEC_LOG;
23868
closeFile(signal, evictPtr, line);
23873
signal->theData[0] = ZEXEC_SR;
23874
signal->theData[1] = filePtr.p->logPartRec;
23875
sendSignal(cownref, GSN_CONTINUEB, signal, 2, JBB);
23880
Dblqh::release(Signal* signal, RedoOpenFileCache & cache)
23882
Ptr<LogFileRecord> closePtr;
23884
while (m_redo_open_file_cache.m_lru.first(closePtr))
23887
m_redo_open_file_cache.m_lru.remove(closePtr);
23888
if (closePtr.p->logFileStatus == LogFileRecord::CLOSING_EXEC_LOG_CACHED)
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);
23903
ndbout_c("Found file with state: %u",
23904
closePtr.p->logFileStatus);
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);
23919
Dblqh::check_ndb_versions() const
23921
Uint32 version = getNodeInfo(getOwnNodeId()).m_version;
23922
for (Uint32 i = 0; i < cnoOfNodes; i++)
23924
Uint32 node = cnodeData[i];
23925
if (cnodeStatus[i] == ZNODE_UP)
23927
if(getNodeInfo(node).m_version != version)
23937
Dblqh::suspendFile(Signal* signal, Uint32 filePtrI, Uint32 millis)
23939
Ptr<LogFileRecord> tmp;
23941
ptrCheckGuard(tmp, clogFileFileSize, logFileRecord);
23942
suspendFile(signal, tmp, millis);
23946
Dblqh::suspendFile(Signal* signal, Ptr<LogFileRecord> logFilePtr, Uint32 millis)
23948
SaveSignal<FsSuspendOrd::SignalLength> tmp(signal);
23949
signal->theData[0] = logFilePtr.p->fileRef;
23950
signal->theData[1] = millis;
23951
sendSignal(NDBFS_REF, GSN_FSSUSPENDORD, signal, 2, JBA);
23955
Dblqh::send_runredo_event(Signal* signal, LogPartRecord * lp, Uint32 gci)
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;
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;
23971
filePtr.i = lp->currentLogfile;
23972
ptrCheckGuard(filePtr, clogFileFileSize, logFileRecord);
23973
signal->theData[8] = filePtr.p->fileNo;
23974
signal->theData[9] = filePtr.p->currentMbyte;
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);
23984
Dblqh::IOTracker::init(Uint32 partNo)
23986
bzero(this, sizeof(* this));
23987
m_log_part_no = partNo;
23991
Dblqh::IOTracker::tick(Uint32 now, Uint32 maxlag, Uint32 maxlag_cnt)
23993
Uint32 t = m_current_time;
23995
if ((t / SAMPLE_TIME) == (now / SAMPLE_TIME))
23998
m_current_time = now;
23999
if (m_sample_completed_bytes >= m_sample_sent_bytes)
24002
* If we completed all io we sent during current sample...
24003
* we can't have any problem...and
24004
* we can't measure io throughput, so don't add measurement
24007
m_sample_sent_bytes = 0;
24008
m_sample_completed_bytes = 0;
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;
24017
m_curr_written_bytes += m_sample_completed_bytes;
24018
m_curr_elapsed_millis += elapsed;
24020
Uint32 bps = (1000 * m_sample_completed_bytes) / elapsed;
24021
Uint32 lag = bps ? m_sum_outstanding_bytes / bps : 30;
24022
if (false && lag >= 30)
24024
g_eventLogger->info("part: %u tick(%u) m_sample_completed_bytes: %u m_sample_sent_bytes: %u elapsed: %u kbps: %u lag: %u",
24026
now, m_sample_completed_bytes, m_sample_sent_bytes,
24027
elapsed, bps/1000, lag);
24030
m_sample_sent_bytes -= m_sample_completed_bytes;
24031
m_sample_completed_bytes = 0;
24035
Uint32 save_lag_cnt = m_lag_cnt;
24036
if ((now / SLIDING_WINDOW_LEN) != (t / SLIDING_WINDOW_LEN))
24038
Uint32 lag = m_curr_written_bytes ?
24039
((Uint64(m_sum_outstanding_bytes) / 1000) * Uint64(m_curr_elapsed_millis)) / m_curr_written_bytes:
24045
* We did have lag last second...
24046
* increase m_lag_cnt and check if it has reached maxlag_cnt
24048
Uint32 tmp = m_lag_cnt;
24049
m_lag_cnt += (lag / maxlag);
24050
if (tmp < maxlag_cnt && m_lag_cnt >= maxlag_cnt)
24052
retVal = -1; // start aborting transaction
24058
* We did not have lag...reset m_lag_cnt
24060
if (m_lag_cnt >= maxlag_cnt)
24062
// stop aborting transcation
24069
if (m_lag_cnt == 0 && lag == 0)
24072
else if (lag > 0 && m_lag_cnt == 0)
24074
g_eventLogger->info("part: %u : time to complete: %u",
24075
m_log_part_no, lag);
24077
else if (m_lag_cnt < maxlag_cnt && m_lag_cnt == save_lag_cnt)
24079
g_eventLogger->info("part: %u : time to complete: %u lag_cnt: %u => %u => retVal: %d",
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);
24095
* And finally rotate sliding window
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;
24110
Dblqh::IOTracker::send_io(Uint32 bytes)
24112
m_sum_outstanding_bytes += bytes;
24113
m_sample_sent_bytes += bytes;
24117
Dblqh::IOTracker::complete_io(Uint32 bytes)
24119
assert(m_sum_outstanding_bytes >= bytes);
24121
m_sum_outstanding_bytes -= bytes;
24122
m_sample_completed_bytes += bytes;