From 51a093f18762d299899c7c9e5cb0a2a639631720 Mon Sep 17 00:00:00 2001 From: unknown Date: Mon, 20 Mar 2006 14:49:46 +0100 Subject: [PATCH] ndb - bug#18352 Use variable waitfor_response_timeout (depending on TransactionDeadLockTimeout) When getting 4012, set NeedAbort and ReleaseOnClose ndb/src/ndbapi/NdbConnection.cpp: Use variable for WAITFOR_RESPONSE_TIMEOUT ndb/src/ndbapi/Ndbif.cpp: Use variable timeout for waitfor, when receiving 4012, set NeedAbort and ReleaseOnClose ndb/src/ndbapi/TransporterFacade.cpp: Init wait_for_response_timoue as max TRANSACTION_DEADLOCK_TIMEOUT ndb/src/ndbapi/TransporterFacade.hpp: Init wait_for_response_timoue as max TRANSACTION_DEADLOCK_TIMEOUT ndb/test/ndbapi/testTimeout.cpp: Add testcase for 4012 ndb/test/run-test/daily-basic-tests.txt: Add testcase for 4012 --- ndb/src/ndbapi/NdbConnection.cpp | 4 +- ndb/src/ndbapi/Ndbif.cpp | 12 +-- ndb/src/ndbapi/TransporterFacade.cpp | 14 ++++ ndb/src/ndbapi/TransporterFacade.hpp | 1 + ndb/test/ndbapi/testTimeout.cpp | 101 ++++++++++++++++++++++++ ndb/test/run-test/daily-basic-tests.txt | 4 + 6 files changed, 129 insertions(+), 7 deletions(-) diff --git a/ndb/src/ndbapi/NdbConnection.cpp b/ndb/src/ndbapi/NdbConnection.cpp index c9e26f8ccaf..9cd7d6ed42e 100644 --- a/ndb/src/ndbapi/NdbConnection.cpp +++ b/ndb/src/ndbapi/NdbConnection.cpp @@ -450,12 +450,12 @@ NdbConnection::executeNoBlobs(ExecType aTypeOfExec, //------------------------------------------------------------------------ Ndb* tNdb = theNdb; + Uint32 timeout = TransporterFacade::instance()->m_waitfor_timeout; m_waitForReply = false; executeAsynchPrepare(aTypeOfExec, NULL, NULL, abortOption); if (m_waitForReply){ while (1) { - int noOfComp = tNdb->sendPollNdb((3 * WAITFOR_RESPONSE_TIMEOUT), - 1, forceSend); + int noOfComp = tNdb->sendPollNdb(3 * timeout, 1, forceSend); if (noOfComp == 0) { /** * This timeout situation can occur if NDB crashes. diff --git a/ndb/src/ndbapi/Ndbif.cpp b/ndb/src/ndbapi/Ndbif.cpp index 3ebba7e1c4a..d753117aa9a 100644 --- a/ndb/src/ndbapi/Ndbif.cpp +++ b/ndb/src/ndbapi/Ndbif.cpp @@ -954,23 +954,25 @@ Ndb::pollCompleted(NdbConnection** aCopyArray) void Ndb::check_send_timeout() { + Uint32 timeout = TransporterFacade::instance()->m_waitfor_timeout; NDB_TICKS current_time = NdbTick_CurrentMillisecond(); if (current_time - the_last_check_time > 1000) { the_last_check_time = current_time; Uint32 no_of_sent = theNoOfSentTransactions; for (Uint32 i = 0; i < no_of_sent; i++) { NdbConnection* a_con = theSentTransactionsArray[i]; - if ((current_time - a_con->theStartTransTime) > - WAITFOR_RESPONSE_TIMEOUT) { + if ((current_time - a_con->theStartTransTime) > timeout) + { #ifdef VM_TRACE a_con->printState(); Uint32 t1 = a_con->theTransactionId; Uint32 t2 = a_con->theTransactionId >> 32; - ndbout_c("[%.8x %.8x]", t1, t2); - abort(); + ndbout_c("4012 [%.8x %.8x]", t1, t2); + //abort(); #endif + a_con->theReleaseOnClose = true; a_con->setOperationErrorCodeAbort(4012); - a_con->theCommitStatus = NdbConnection::Aborted; + a_con->theCommitStatus = NdbConnection::NeedAbort; a_con->theCompletionStatus = NdbConnection::CompletedFailure; a_con->handleExecuteCompletion(); remove_sent_list(i); diff --git a/ndb/src/ndbapi/TransporterFacade.cpp b/ndb/src/ndbapi/TransporterFacade.cpp index b6fb2d6cded..5e9147304eb 100644 --- a/ndb/src/ndbapi/TransporterFacade.cpp +++ b/ndb/src/ndbapi/TransporterFacade.cpp @@ -567,6 +567,20 @@ TransporterFacade::init(Uint32 nodeId, const ndb_mgm_configuration* props) } #endif + Uint32 timeout = 120000; + iter.first(); + for (iter.first(); iter.valid(); iter.next()) + { + Uint32 tmp1 = 0, tmp2 = 0; + iter.get(CFG_DB_TRANSACTION_CHECK_INTERVAL, &tmp1); + iter.get(CFG_DB_TRANSACTION_DEADLOCK_TIMEOUT, &tmp2); + tmp1 += tmp2; + if (tmp1 > timeout) + timeout = tmp1; + } + m_waitfor_timeout = timeout; + ndbout_c("Using waitfor: %d", timeout); + if (!theTransporterRegistry->start_service(m_socket_server)){ ndbout_c("Unable to start theTransporterRegistry->start_service"); DBUG_RETURN(false); diff --git a/ndb/src/ndbapi/TransporterFacade.hpp b/ndb/src/ndbapi/TransporterFacade.hpp index 99edea846c1..1e7377a3b4d 100644 --- a/ndb/src/ndbapi/TransporterFacade.hpp +++ b/ndb/src/ndbapi/TransporterFacade.hpp @@ -172,6 +172,7 @@ private: */ public: STATIC_CONST( MAX_NO_THREADS = 4711 ); + Uint32 m_waitfor_timeout; // in milli seconds... private: struct ThreadData { diff --git a/ndb/test/ndbapi/testTimeout.cpp b/ndb/test/ndbapi/testTimeout.cpp index 71c11b25859..25392698642 100644 --- a/ndb/test/ndbapi/testTimeout.cpp +++ b/ndb/test/ndbapi/testTimeout.cpp @@ -24,6 +24,7 @@ #define TIMEOUT (Uint32)3000 Uint32 g_org_timeout = 3000; +Uint32 g_org_deadlock = 3000; int setTransactionTimeout(NDBT_Context* ctx, NDBT_Step* step){ @@ -59,6 +60,60 @@ resetTransactionTimeout(NDBT_Context* ctx, NDBT_Step* step){ return NDBT_OK; } +int +setDeadlockTimeout(NDBT_Context* ctx, NDBT_Step* step){ + NdbRestarter restarter; + int timeout = ctx->getProperty("TransactionDeadlockTimeout", TIMEOUT); + + NdbConfig conf(GETNDB(step)->getNodeId()+1); + unsigned int nodeId = conf.getMasterNodeId(); + if (!conf.getProperty(nodeId, + NODE_TYPE_DB, + CFG_DB_TRANSACTION_DEADLOCK_TIMEOUT, + &g_org_deadlock)) + return NDBT_FAILED; + + g_err << "Setting timeout: " << timeout << endl; + int val[] = { DumpStateOrd::TcSetTransactionTimeout, timeout }; + if(restarter.dumpStateAllNodes(val, 2) != 0){ + return NDBT_FAILED; + } + + return NDBT_OK; +} + +int +getDeadlockTimeout(NDBT_Context* ctx, NDBT_Step* step){ + NdbRestarter restarter; + + Uint32 val = 0; + NdbConfig conf(GETNDB(step)->getNodeId()+1); + unsigned int nodeId = conf.getMasterNodeId(); + if (!conf.getProperty(nodeId, + NODE_TYPE_DB, + CFG_DB_TRANSACTION_DEADLOCK_TIMEOUT, + &val)) + return NDBT_FAILED; + + if (val < 120000) + val = 120000; + ctx->setProperty("TransactionDeadlockTimeout", 4*val); + + return NDBT_OK; +} + +int +resetDeadlockTimeout(NDBT_Context* ctx, NDBT_Step* step){ + NdbRestarter restarter; + + int val[] = { DumpStateOrd::TcSetTransactionTimeout, g_org_deadlock }; + if(restarter.dumpStateAllNodes(val, 2) != 0){ + return NDBT_FAILED; + } + + return NDBT_OK; +} + int runLoadTable(NDBT_Context* ctx, NDBT_Step* step){ @@ -374,6 +429,43 @@ int runBuddyTransNoTimeout(NDBT_Context* ctx, NDBT_Step* step){ return result; } +int +runError4012(NDBT_Context* ctx, NDBT_Step* step){ + int result = NDBT_OK; + int loops = ctx->getNumLoops(); + int stepNo = step->getStepNo(); + + int timeout = ctx->getProperty("TransactionDeadlockTimeout", TIMEOUT); + + HugoOperations hugoOps(*ctx->getTab()); + Ndb* pNdb = GETNDB(step); + + do{ + // Commit transaction + CHECK(hugoOps.startTransaction(pNdb) == 0); + CHECK(hugoOps.pkUpdateRecord(pNdb, 0) == 0); + int ret = hugoOps.execute_NoCommit(pNdb); + if (ret == 0) + { + int sleep = timeout; + ndbout << "Sleeping for " << sleep << " milliseconds" << endl; + NdbSleep_MilliSleep(sleep); + + // Expect that transaction has NOT timed-out + CHECK(hugoOps.execute_Commit(pNdb) == 0); + } + else + { + CHECK(ret == 4012); + } + } while(false); + + hugoOps.closeTransaction(pNdb); + + return result; +} + + NDBT_TESTSUITE(testTimeout); TESTCASE("DontTimeoutTransaction", "Test that the transaction does not timeout "\ @@ -465,6 +557,15 @@ TESTCASE("BuddyTransNoTimeout5", FINALIZER(resetTransactionTimeout); FINALIZER(runClearTable); } +TESTCASE("Error4012", ""){ + TC_PROPERTY("TransactionDeadlockTimeout", 120000); + INITIALIZER(runLoadTable); + INITIALIZER(getDeadlockTimeout); + INITIALIZER(setDeadlockTimeout); + STEPS(runError4012, 2); + FINALIZER(runClearTable); +} + NDBT_TESTSUITE_END(testTimeout); int main(int argc, const char** argv){ diff --git a/ndb/test/run-test/daily-basic-tests.txt b/ndb/test/run-test/daily-basic-tests.txt index 169daae6d7f..70518f7881d 100644 --- a/ndb/test/run-test/daily-basic-tests.txt +++ b/ndb/test/run-test/daily-basic-tests.txt @@ -236,6 +236,10 @@ max-time: 500 cmd: testTimeout args: -n TimeoutRandTransaction T1 +max-time: 600 +cmd: testTimeout +args: -n Error4012 T1 + # SCAN TESTS # max-time: 500