mirror of
https://github.com/MariaDB/server.git
synced 2026-05-08 08:04:29 +02:00
Make operation list on fragment fifo so that uncommitted operations
are undo-logged in correct order
Add bunch of testcases to autotest
ndb/src/kernel/blocks/dbtup/Dbtup.hpp:
Send fragrecord ptr to initOpConnection so that is does not
have to look it up every time (if needed)
Make operation list on fragment fifo so that uncommitted operations
are undo-logged in correct order
ndb/src/kernel/blocks/dbtup/DbtupAbort.cpp:
Send fragptr to initOpConnection
ndb/src/kernel/blocks/dbtup/DbtupCommit.cpp:
dllist -> dlfifolist
ndb/src/kernel/blocks/dbtup/DbtupExecQuery.cpp:
dllist -> dlfifolist
ndb/src/kernel/blocks/dbtup/DbtupGen.cpp:
Make operation list on fragment fifo so that uncommitted operations
are undo-logged in correct order
ndb/src/kernel/blocks/ndbcntr/NdbcntrMain.cpp:
Fix uninitialized variable c_start.m_startTime
which made startPartial and startPartitioned fail
ndb/test/ndbapi/testSystemRestart.cpp:
Added testSystemRestart -n SR9 which
demonstrates that two prepared operation on same
records _used to_ be undo-logged in wrong order makeing
system restart fail
ndb/test/run-test/daily-devel-tests.txt:
Add
* testSystemRestart -n SR6
Restart while some nodes have fs and other not
* testSystemRestart -n SR7
Restart in partition win
* testSystemRestart -n SR8
Restart in partition win, others starting during restart
* testSystemRestart -n SR9
Multiple ops on same record prepared before
This commit is contained in:
parent
300346fad3
commit
b61bfd8c97
8 changed files with 103 additions and 30 deletions
|
|
@ -515,6 +515,7 @@ struct Fragrecord {
|
|||
Uint32 emptyPrimPage;
|
||||
|
||||
Uint32 firstusedOprec;
|
||||
Uint32 lastusedOprec;
|
||||
|
||||
Uint32 thFreeFirst;
|
||||
Uint32 thFreeCopyFirst;
|
||||
|
|
@ -1653,7 +1654,7 @@ private:
|
|||
|
||||
//------------------------------------------------------------------
|
||||
//------------------------------------------------------------------
|
||||
void initOpConnection(Operationrec* const regOperPtr);
|
||||
void initOpConnection(Operationrec* regOperPtr, Fragrecord*);
|
||||
|
||||
//------------------------------------------------------------------
|
||||
//------------------------------------------------------------------
|
||||
|
|
|
|||
|
|
@ -77,7 +77,7 @@ void Dbtup::execTUP_ABORTREQ(Signal* signal)
|
|||
if (regOperPtr.p->optype == ZREAD) {
|
||||
ljam();
|
||||
freeAllAttrBuffers(regOperPtr.p);
|
||||
initOpConnection(regOperPtr.p);
|
||||
initOpConnection(regOperPtr.p, 0);
|
||||
return;
|
||||
}//if
|
||||
|
||||
|
|
@ -134,7 +134,7 @@ void Dbtup::execTUP_ABORTREQ(Signal* signal)
|
|||
ndbrequire(regOperPtr.p->tupleState == ALREADY_ABORTED);
|
||||
commitUpdate(signal, regOperPtr.p, regFragPtr.p, regTabPtr.p);
|
||||
}//if
|
||||
initOpConnection(regOperPtr.p);
|
||||
initOpConnection(regOperPtr.p, regFragPtr.p);
|
||||
}//execTUP_ABORTREQ()
|
||||
|
||||
void Dbtup::setTupleStateOnPreviousOps(Uint32 prevOpIndex)
|
||||
|
|
@ -459,7 +459,7 @@ void Dbtup::tupkeyErrorLab(Signal* signal)
|
|||
freeAllAttrBuffers(regOperPtr);
|
||||
abortUpdate(signal, regOperPtr, fragptr.p, tabptr.p);
|
||||
removeActiveOpList(regOperPtr);
|
||||
initOpConnection(regOperPtr);
|
||||
initOpConnection(regOperPtr, fragptr.p);
|
||||
regOperPtr->transstate = IDLE;
|
||||
regOperPtr->tupleState = NO_OTHER_OP;
|
||||
TupKeyRef * const tupKeyRef = (TupKeyRef *)signal->getDataPtrSend();
|
||||
|
|
|
|||
|
|
@ -224,7 +224,8 @@ void Dbtup::removeActiveOpList(Operationrec* const regOperPtr)
|
|||
/* ---------------------------------------------------------------- */
|
||||
/* INITIALIZATION OF ONE CONNECTION RECORD TO PREPARE FOR NEXT OP. */
|
||||
/* ---------------------------------------------------------------- */
|
||||
void Dbtup::initOpConnection(Operationrec* const regOperPtr)
|
||||
void Dbtup::initOpConnection(Operationrec* regOperPtr,
|
||||
Fragrecord * fragPtrP)
|
||||
{
|
||||
Uint32 RinFragList = regOperPtr->inFragList;
|
||||
regOperPtr->transstate = IDLE;
|
||||
|
|
@ -244,22 +245,18 @@ void Dbtup::initOpConnection(Operationrec* const regOperPtr)
|
|||
regOperPtr->inFragList = ZFALSE;
|
||||
if (tropPrevLinkPtr.i == RNIL) {
|
||||
ljam();
|
||||
FragrecordPtr regFragPtr;
|
||||
regFragPtr.i = regOperPtr->fragmentPtr;
|
||||
ptrCheckGuard(regFragPtr, cnoOfFragrec, fragrecord);
|
||||
regFragPtr.p->firstusedOprec = tropNextLinkPtr.i;
|
||||
fragPtrP->firstusedOprec = tropNextLinkPtr.i;
|
||||
} else {
|
||||
ljam();
|
||||
ptrCheckGuard(tropPrevLinkPtr, cnoOfOprec, operationrec);
|
||||
tropPrevLinkPtr.p->nextOprecInList = tropNextLinkPtr.i;
|
||||
}//if
|
||||
if (tropNextLinkPtr.i == RNIL) {
|
||||
;
|
||||
fragPtrP->lastusedOprec = tropPrevLinkPtr.i;
|
||||
} else {
|
||||
ljam();
|
||||
ptrCheckGuard(tropNextLinkPtr, cnoOfOprec, operationrec);
|
||||
tropNextLinkPtr.p->prevOprecInList = tropPrevLinkPtr.i;
|
||||
}//if
|
||||
}
|
||||
regOperPtr->prevOprecInList = RNIL;
|
||||
regOperPtr->nextOprecInList = RNIL;
|
||||
}//if
|
||||
|
|
@ -336,7 +333,7 @@ void Dbtup::execTUP_COMMITREQ(Signal* signal)
|
|||
commitUpdate(signal, regOperPtr.p, regFragPtr.p, regTabPtr.p);
|
||||
removeActiveOpList(regOperPtr.p);
|
||||
}//if
|
||||
initOpConnection(regOperPtr.p);
|
||||
initOpConnection(regOperPtr.p, regFragPtr.p);
|
||||
}//execTUP_COMMITREQ()
|
||||
|
||||
void
|
||||
|
|
|
|||
|
|
@ -319,24 +319,20 @@ void Dbtup::linkOpIntoFragList(OperationrecPtr regOperPtr,
|
|||
Fragrecord* const regFragPtr)
|
||||
{
|
||||
OperationrecPtr sopTmpOperPtr;
|
||||
/* ----------------------------------------------------------------- */
|
||||
/* LINK THE OPERATION INTO A DOUBLY LINKED LIST ON THE FRAGMENT*/
|
||||
/* PUT IT FIRST IN THIS LIST SINCE IT DOESN'T MATTER WHERE IT */
|
||||
/* IS PUT. */
|
||||
/* ----------------------------------------------------------------- */
|
||||
Uint32 tail = regFragPtr->lastusedOprec;
|
||||
ndbrequire(regOperPtr.p->inFragList == ZFALSE);
|
||||
regOperPtr.p->inFragList = ZTRUE;
|
||||
regOperPtr.p->prevOprecInList = RNIL;
|
||||
sopTmpOperPtr.i = regFragPtr->firstusedOprec;
|
||||
regFragPtr->firstusedOprec = regOperPtr.i;
|
||||
regOperPtr.p->nextOprecInList = sopTmpOperPtr.i;
|
||||
if (sopTmpOperPtr.i == RNIL) {
|
||||
return;
|
||||
regOperPtr.p->prevOprecInList = tail;
|
||||
regOperPtr.p->nextOprecInList = RNIL;
|
||||
sopTmpOperPtr.i = tail;
|
||||
if (tail == RNIL) {
|
||||
regFragPtr->firstusedOprec = regOperPtr.i;
|
||||
} else {
|
||||
jam();
|
||||
ptrCheckGuard(sopTmpOperPtr, cnoOfOprec, operationrec);
|
||||
sopTmpOperPtr.p->prevOprecInList = regOperPtr.i;
|
||||
sopTmpOperPtr.p->nextOprecInList = regOperPtr.i;
|
||||
}//if
|
||||
regFragPtr->lastusedOprec = regOperPtr.i;
|
||||
}//Dbtup::linkOpIntoFragList()
|
||||
|
||||
/*
|
||||
|
|
|
|||
|
|
@ -963,6 +963,7 @@ void Dbtup::initializeFragrecord()
|
|||
regFragPtr.p->nextfreefrag = regFragPtr.i + 1;
|
||||
regFragPtr.p->checkpointVersion = RNIL;
|
||||
regFragPtr.p->firstusedOprec = RNIL;
|
||||
regFragPtr.p->lastusedOprec = RNIL;
|
||||
regFragPtr.p->fragStatus = IDLE;
|
||||
}//for
|
||||
regFragPtr.i = cnoOfFragrec - 1;
|
||||
|
|
@ -1164,7 +1165,7 @@ void Dbtup::execTUPSEIZEREQ(Signal* signal)
|
|||
return;
|
||||
}//if
|
||||
regOperPtr.p->optype = ZREAD;
|
||||
initOpConnection(regOperPtr.p);
|
||||
initOpConnection(regOperPtr.p, 0);
|
||||
regOperPtr.p->userpointer = userPtr;
|
||||
regOperPtr.p->userblockref = userRef;
|
||||
signal->theData[0] = regOperPtr.p->userpointer;
|
||||
|
|
|
|||
|
|
@ -103,7 +103,7 @@ void Ndbcntr::execCONTINUEB(Signal* signal)
|
|||
}
|
||||
|
||||
Uint64 now = NdbTick_CurrentMillisecond();
|
||||
if(c_start.m_startFailureTimeout > now){
|
||||
if(now > c_start.m_startFailureTimeout){
|
||||
ndbrequire(false);
|
||||
}
|
||||
|
||||
|
|
@ -446,13 +446,17 @@ void Ndbcntr::execREAD_NODESCONF(Signal* signal)
|
|||
ndb_mgm_get_int_parameter(p, CFG_DB_START_PARTITION_TIMEOUT, &to_2);
|
||||
ndb_mgm_get_int_parameter(p, CFG_DB_START_FAILURE_TIMEOUT, &to_3);
|
||||
|
||||
c_start.m_startTime = NdbTick_CurrentMillisecond();
|
||||
c_start.m_startPartialTimeout = setTimeout(c_start.m_startTime, to_1);
|
||||
c_start.m_startPartitionedTimeout = setTimeout(c_start.m_startTime, to_2);
|
||||
c_start.m_startFailureTimeout = setTimeout(c_start.m_startTime, to_3);
|
||||
|
||||
|
||||
UpgradeStartup::sendCmAppChg(* this, signal, 0); // ADD
|
||||
|
||||
sendCntrStartReq(signal);
|
||||
|
||||
signal->theData[0] = ZSTARTUP;
|
||||
sendSignalWithDelay(reference(), GSN_CONTINUEB, signal, 1000, 1);
|
||||
|
||||
return;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -872,7 +872,7 @@ int runSystemRestart7(NDBT_Context* ctx, NDBT_Step* step){
|
|||
|
||||
const Uint32 nodeCount = restarter.getNumDbNodes();
|
||||
if(nodeCount < 2){
|
||||
g_info << "SR8 - Needs atleast 2 nodes to test" << endl;
|
||||
g_info << "SR7 - Needs atleast 2 nodes to test" << endl;
|
||||
return NDBT_OK;
|
||||
}
|
||||
|
||||
|
|
@ -1001,7 +1001,52 @@ int runSystemRestart8(NDBT_Context* ctx, NDBT_Step* step){
|
|||
i++;
|
||||
}
|
||||
|
||||
g_info << "runSystemRestart7 finished" << endl;
|
||||
g_info << "runSystemRestart8 finished" << endl;
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
int runSystemRestart9(NDBT_Context* ctx, NDBT_Step* step){
|
||||
Ndb* pNdb = GETNDB(step);
|
||||
int result = NDBT_OK;
|
||||
int timeout = 300;
|
||||
Uint32 loops = ctx->getNumLoops();
|
||||
int records = ctx->getNumRecords();
|
||||
NdbRestarter restarter;
|
||||
Uint32 i = 1;
|
||||
|
||||
Uint32 currentRestartNodeIndex = 1;
|
||||
UtilTransactions utilTrans(*ctx->getTab());
|
||||
HugoTransactions hugoTrans(*ctx->getTab());
|
||||
|
||||
int args[] = { DumpStateOrd::DihMaxTimeBetweenLCP };
|
||||
int dump[] = { DumpStateOrd::DihStartLcpImmediately };
|
||||
|
||||
do {
|
||||
CHECK(restarter.dumpStateAllNodes(args, 1) == 0);
|
||||
|
||||
HugoOperations ops(* ctx->getTab());
|
||||
CHECK(ops.startTransaction(pNdb) == 0);
|
||||
for(i = 0; i<10; i++){
|
||||
CHECK(ops.pkInsertRecord(pNdb, i, 1, 1) == 0);
|
||||
CHECK(ops.execute_NoCommit(pNdb) == 0);
|
||||
}
|
||||
for(i = 0; i<10; i++){
|
||||
CHECK(ops.pkUpdateRecord(pNdb, i, 1) == 0);
|
||||
CHECK(ops.execute_NoCommit(pNdb) == 0);
|
||||
}
|
||||
NdbSleep_SecSleep(10);
|
||||
CHECK(restarter.dumpStateAllNodes(dump, 1) == 0);
|
||||
NdbSleep_SecSleep(10);
|
||||
CHECK(ops.execute_Commit(pNdb) == 0);
|
||||
|
||||
CHECK(restarter.restartAll() == 0);
|
||||
CHECK(restarter.waitClusterStarted(timeout) == 0);
|
||||
CHECK(pNdb->waitUntilReady(timeout) == 0);
|
||||
ops.closeTransaction(pNdb);
|
||||
} while(0);
|
||||
|
||||
g_info << "runSystemRestart9 finished" << endl;
|
||||
|
||||
return result;
|
||||
}
|
||||
|
|
@ -1176,6 +1221,19 @@ TESTCASE("SR8",
|
|||
STEP(runSystemRestart8);
|
||||
FINALIZER(runClearTable);
|
||||
}
|
||||
TESTCASE("SR9",
|
||||
"Perform partition win system restart with other nodes delayed\n"
|
||||
"* 1. Start transaction\n"
|
||||
"* 2. insert (1,1)\n"
|
||||
"* 3. update (1,2)\n"
|
||||
"* 4. start lcp\n"
|
||||
"* 5. commit\n"
|
||||
"* 6. restart\n"){
|
||||
INITIALIZER(runWaitStarted);
|
||||
INITIALIZER(runClearTable);
|
||||
STEP(runSystemRestart9);
|
||||
FINALIZER(runClearTable);
|
||||
}
|
||||
NDBT_TESTSUITE_END(testSystemRestart);
|
||||
|
||||
int main(int argc, const char** argv){
|
||||
|
|
|
|||
|
|
@ -190,3 +190,19 @@ max-time: 2500
|
|||
cmd: test_event
|
||||
args: -n BasicEventOperation T1 T6
|
||||
|
||||
#
|
||||
max-time: 1500
|
||||
cmd: testSystemRestart
|
||||
args: -n SR6 -l 1 T1
|
||||
|
||||
max-time: 1500
|
||||
cmd: testSystemRestart
|
||||
args: -n SR7 -l 1 T1
|
||||
|
||||
max-time: 1500
|
||||
cmd: testSystemRestart
|
||||
args: -n S8 -l 1 T1
|
||||
|
||||
max-time: 1500
|
||||
cmd: testSystemRestart
|
||||
args: -n S9 -l 1 T1
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue