diff --git a/ndb/src/kernel/blocks/ERROR_codes.txt b/ndb/src/kernel/blocks/ERROR_codes.txt index 43532a973f94d2ce913a150c3bbba92b2a8759ca..70f11c33cd71d816cfe8ba9803823b4d0a5163e9 100644 --- a/ndb/src/kernel/blocks/ERROR_codes.txt +++ b/ndb/src/kernel/blocks/ERROR_codes.txt @@ -3,7 +3,7 @@ Next NDBCNTR 1000 Next NDBFS 2000 Next DBACC 3001 Next DBTUP 4007 -Next DBLQH 5040 +Next DBLQH 5042 Next DBDICT 6006 Next DBDIH 7174 Next DBTC 8035 @@ -193,6 +193,8 @@ Delay execution of ABORTREQ signal 2 seconds to generate time-out. 5038: Drop LQHKEYREQ + set 5039 5039: Drop ABORT + set 5003 +8048: Make TC not choose own node for simple/dirty read +5041: Crash is receiving simple read from other TC on different node ERROR CODES FOR TESTING TIME-OUT HANDLING IN DBTC ------------------------------------------------- diff --git a/ndb/src/kernel/blocks/dblqh/DblqhMain.cpp b/ndb/src/kernel/blocks/dblqh/DblqhMain.cpp index de4668a46dce0e9de67f7abccd22e07aa4f62004..5b003124fb115f312c13601104a6e0467fe55c0f 100644 --- a/ndb/src/kernel/blocks/dblqh/DblqhMain.cpp +++ b/ndb/src/kernel/blocks/dblqh/DblqhMain.cpp @@ -3305,6 +3305,9 @@ void Dblqh::execLQHKEYREQ(Signal* signal) UintR TreclenAiLqhkey = LqhKeyReq::getAIInLqhKeyReq(Treqinfo); regTcPtr->apiVersionNo = 0; + CRASH_INSERTION2(5041, regTcPtr->simpleRead && + refToNode(signal->senderBlockRef()) != cownNodeid); + regTcPtr->reclenAiLqhkey = TreclenAiLqhkey; regTcPtr->currReclenAi = TreclenAiLqhkey; UintR TitcKeyLen = LqhKeyReq::getKeyLen(Treqinfo); diff --git a/ndb/src/kernel/blocks/dbtc/DbtcMain.cpp b/ndb/src/kernel/blocks/dbtc/DbtcMain.cpp index 473f5cba9f5e151be4de47263999f4d3b2be5838..989d726dd688f0274af32902b1c3ebc5994ae161 100644 --- a/ndb/src/kernel/blocks/dbtc/DbtcMain.cpp +++ b/ndb/src/kernel/blocks/dbtc/DbtcMain.cpp @@ -2963,15 +2963,27 @@ void Dbtc::tckeyreq050Lab(Signal* signal) /*-------------------------------------------------------------*/ arrGuard(tnoOfBackup, 4); UintR Tindex; + UintR TownNode = cownNodeid; for (Tindex = 1; Tindex <= tnoOfBackup; Tindex++) { UintR Tnode = regTcPtr->tcNodedata[Tindex]; - UintR TownNode = cownNodeid; jam(); if (Tnode == TownNode) { jam(); regTcPtr->tcNodedata[0] = Tnode; }//if }//for + if(ERROR_INSERTED(8048)) + { + for (Tindex = 0; Tindex <= tnoOfBackup; Tindex++) + { + UintR Tnode = regTcPtr->tcNodedata[Tindex]; + jam(); + if (Tnode != TownNode) { + jam(); + regTcPtr->tcNodedata[0] = Tnode; + }//if + }//for + } }//if jam(); regTcPtr->lastReplicaNo = 0; diff --git a/ndb/test/include/NDBT_Test.hpp b/ndb/test/include/NDBT_Test.hpp index 6a968c491ae0e6837a827c7aff09588205be1f69..176cec3cd2736c1bdda4d37a5cd513afb9f3ae72 100644 --- a/ndb/test/include/NDBT_Test.hpp +++ b/ndb/test/include/NDBT_Test.hpp @@ -82,6 +82,12 @@ public: */ int getNoOfRunningSteps() const ; int getNoOfCompletedSteps() const ; + + /** + * Thread sync + */ + void sync_down(const char * key); + void sync_up_and_wait(const char * key, Uint32 count = 0); private: friend class NDBT_Step; friend class NDBT_TestSuite; diff --git a/ndb/test/ndbapi/testIndex.cpp b/ndb/test/ndbapi/testIndex.cpp index bef3b310c96cf2bf2eb614b959fdafcda79c43df..aca8514c931adf4c001f0af934a5b89c65c336af 100644 --- a/ndb/test/ndbapi/testIndex.cpp +++ b/ndb/test/ndbapi/testIndex.cpp @@ -380,27 +380,6 @@ runVerifyIndex(NDBT_Context* ctx, NDBT_Step* step){ return NDBT_OK; } -int -sync_down(NDBT_Context* ctx){ - Uint32 threads = ctx->getProperty("PauseThreads", (unsigned)0); - if(threads){ - ctx->decProperty("PauseThreads"); - } - return 0; -} - -int -sync_up_and_wait(NDBT_Context* ctx){ - Uint32 threads = ctx->getProperty("Threads", (unsigned)0); - ndbout_c("Setting PauseThreads to %d", threads); - ctx->setProperty("PauseThreads", threads); - ctx->getPropertyWait("PauseThreads", (unsigned)0); - if(threads){ - ndbout_c("wait completed"); - } - return 0; -} - int runTransactions1(NDBT_Context* ctx, NDBT_Step* step){ // Verify that data in index match @@ -416,7 +395,7 @@ runTransactions1(NDBT_Context* ctx, NDBT_Step* step){ return NDBT_FAILED; } - sync_down(ctx); + ctx->sync_down("PauseThreads"); if(ctx->isTestStopped()) break; @@ -425,7 +404,7 @@ runTransactions1(NDBT_Context* ctx, NDBT_Step* step){ return NDBT_FAILED; } - sync_down(ctx); + ctx->sync_down("PauseThreads"); } return NDBT_OK; } @@ -446,7 +425,7 @@ runTransactions2(NDBT_Context* ctx, NDBT_Step* step){ return NDBT_FAILED; } #endif - sync_down(ctx); + ctx->sync_down("PauseThreads"); if(ctx->isTestStopped()) break; #if 1 @@ -455,7 +434,7 @@ runTransactions2(NDBT_Context* ctx, NDBT_Step* step){ return NDBT_FAILED; } #endif - sync_down(ctx); + ctx->sync_down("PauseThreads"); } return NDBT_OK; } @@ -476,7 +455,7 @@ runTransactions3(NDBT_Context* ctx, NDBT_Step* step){ g_err << "Load table failed" << endl; return NDBT_FAILED; } - sync_down(ctx); + ctx->sync_down("PauseThreads"); if(ctx->isTestStopped()) break; @@ -485,7 +464,7 @@ runTransactions3(NDBT_Context* ctx, NDBT_Step* step){ return NDBT_FAILED; } - sync_down(ctx); + ctx->sync_down("PauseThreads"); if(ctx->isTestStopped()) break; @@ -494,7 +473,7 @@ runTransactions3(NDBT_Context* ctx, NDBT_Step* step){ return NDBT_FAILED; } - sync_down(ctx); + ctx->sync_down("PauseThreads"); if(ctx->isTestStopped()) break; @@ -503,7 +482,7 @@ runTransactions3(NDBT_Context* ctx, NDBT_Step* step){ return NDBT_FAILED; } - sync_down(ctx); + ctx->sync_down("PauseThreads"); if(ctx->isTestStopped()) break; @@ -512,7 +491,7 @@ runTransactions3(NDBT_Context* ctx, NDBT_Step* step){ return NDBT_FAILED; } - sync_down(ctx); + ctx->sync_down("PauseThreads"); if(ctx->isTestStopped()) break; @@ -521,14 +500,14 @@ runTransactions3(NDBT_Context* ctx, NDBT_Step* step){ return NDBT_FAILED; } - sync_down(ctx); + ctx->sync_down("PauseThreads"); if(ctx->isTestStopped()) break; int count = -1; if(utilTrans.selectCount(pNdb, 64, &count) != 0 || count != 0) return NDBT_FAILED; - sync_down(ctx); + ctx->sync_down("PauseThreads"); } return NDBT_OK; } @@ -540,6 +519,7 @@ int runRestarts(NDBT_Context* ctx, NDBT_Step* step){ NdbRestarts restarts; int i = 0; int timeout = 240; + int sync_threads = ctx->getProperty("Threads", (unsigned)0); while(i<loops && result != NDBT_FAILED && !ctx->isTestStopped()){ if(restarts.executeRestart("RestartRandomNodeAbort", timeout) != 0){ @@ -547,7 +527,7 @@ int runRestarts(NDBT_Context* ctx, NDBT_Step* step){ result = NDBT_FAILED; break; } - sync_up_and_wait(ctx); + ctx->sync_up_and_wait("PauseThreads", sync_threads); i++; } ctx->stopTest(); diff --git a/ndb/test/ndbapi/testNodeRestart.cpp b/ndb/test/ndbapi/testNodeRestart.cpp index 81193d671b6ea277a4de34ee0f8be5cf4ecbbaa2..0ba0d170984a5221996929a897a240ec1b374702 100644 --- a/ndb/test/ndbapi/testNodeRestart.cpp +++ b/ndb/test/ndbapi/testNodeRestart.cpp @@ -219,6 +219,7 @@ int runScanReadVerify(NDBT_Context* ctx, NDBT_Step* step){ int runRestarter(NDBT_Context* ctx, NDBT_Step* step){ int result = NDBT_OK; int loops = ctx->getNumLoops(); + int sync_threads = ctx->getProperty("SyncThreads", (unsigned)0); NdbRestarter restarter; int i = 0; int lastId = 0; @@ -235,7 +236,7 @@ int runRestarter(NDBT_Context* ctx, NDBT_Step* step){ loops *= restarter.getNumDbNodes(); while(i<loops && result != NDBT_FAILED && !ctx->isTestStopped()){ - + int id = lastId % restarter.getNumDbNodes(); int nodeId = restarter.getDbNodeId(id); ndbout << "Restart node " << nodeId << endl; @@ -251,7 +252,7 @@ int runRestarter(NDBT_Context* ctx, NDBT_Step* step){ break; } - NdbSleep_SecSleep(1); + ctx->sync_up_and_wait("PauseThreads", sync_threads); lastId++; i++; @@ -295,6 +296,32 @@ int runRestarts(NDBT_Context* ctx, NDBT_Step* step){ return result; } +int runDirtyRead(NDBT_Context* ctx, NDBT_Step* step){ + int result = NDBT_OK; + int loops = ctx->getNumLoops(); + NdbRestarter restarter; + HugoTransactions hugoTrans(*ctx->getTab()); + + int i = 0; + while(i<loops && result != NDBT_FAILED && !ctx->isTestStopped()){ + g_info << i << ": "; + + int id = i % restarter.getNumDbNodes(); + int nodeId = restarter.getDbNodeId(id); + ndbout << "Restart node " << nodeId << endl; + restarter.insertErrorInNode(nodeId, 5041); + restarter.insertErrorInAllNodes(8048); + + if (hugoTrans.pkReadRecords(GETNDB(step), 1, 1, + NdbOperation::LM_CommittedRead) != 0) + { + return NDBT_FAILED; + } + i++; + } + return result; +} + NDBT_TESTSUITE(testNodeRestart); TESTCASE("NoLoad", "Test that one node at a time can be stopped and then restarted "\ @@ -545,6 +572,12 @@ TESTCASE("StopOnError", FINALIZER(runScanReadVerify); FINALIZER(runClearTable); } +TESTCASE("CommittedRead", + "Test committed read"){ + INITIALIZER(runLoadTable); + STEP(runDirtyRead); + FINALIZER(runClearTable); +} NDBT_TESTSUITE_END(testNodeRestart); int main(int argc, const char** argv){ diff --git a/ndb/test/src/NDBT_Test.cpp b/ndb/test/src/NDBT_Test.cpp index 4ff94bcf29685df0fb797ca9ecb4d34304b89f2d..24446f089476a877b7a6fbaf83040a555968708c 100644 --- a/ndb/test/src/NDBT_Test.cpp +++ b/ndb/test/src/NDBT_Test.cpp @@ -1150,6 +1150,20 @@ void NDBT_Step::print(){ } +void +NDBT_Context::sync_down(const char * key){ + Uint32 threads = getProperty(key, (unsigned)0); + if(threads){ + decProperty(key); + } +} + +void +NDBT_Context::sync_up_and_wait(const char * key, Uint32 value){ + setProperty(key, value); + getPropertyWait(key, (unsigned)0); +} + template class Vector<NDBT_TestCase*>; template class Vector<NDBT_TestCaseResult*>; template class Vector<NDBT_Step*>;