ndb - bug#18352

  Use variable waitfor_response_timeout (depending on TransactionDeadLockTimeout)
  When getting 4012, set NeedAbort and ReleaseOnClose
parent dabd3e8f
...@@ -450,12 +450,12 @@ NdbConnection::executeNoBlobs(ExecType aTypeOfExec, ...@@ -450,12 +450,12 @@ NdbConnection::executeNoBlobs(ExecType aTypeOfExec,
//------------------------------------------------------------------------ //------------------------------------------------------------------------
Ndb* tNdb = theNdb; Ndb* tNdb = theNdb;
Uint32 timeout = TransporterFacade::instance()->m_waitfor_timeout;
m_waitForReply = false; m_waitForReply = false;
executeAsynchPrepare(aTypeOfExec, NULL, NULL, abortOption); executeAsynchPrepare(aTypeOfExec, NULL, NULL, abortOption);
if (m_waitForReply){ if (m_waitForReply){
while (1) { while (1) {
int noOfComp = tNdb->sendPollNdb((3 * WAITFOR_RESPONSE_TIMEOUT), int noOfComp = tNdb->sendPollNdb(3 * timeout, 1, forceSend);
1, forceSend);
if (noOfComp == 0) { if (noOfComp == 0) {
/** /**
* This timeout situation can occur if NDB crashes. * This timeout situation can occur if NDB crashes.
......
...@@ -954,23 +954,25 @@ Ndb::pollCompleted(NdbConnection** aCopyArray) ...@@ -954,23 +954,25 @@ Ndb::pollCompleted(NdbConnection** aCopyArray)
void void
Ndb::check_send_timeout() Ndb::check_send_timeout()
{ {
Uint32 timeout = TransporterFacade::instance()->m_waitfor_timeout;
NDB_TICKS current_time = NdbTick_CurrentMillisecond(); NDB_TICKS current_time = NdbTick_CurrentMillisecond();
if (current_time - the_last_check_time > 1000) { if (current_time - the_last_check_time > 1000) {
the_last_check_time = current_time; the_last_check_time = current_time;
Uint32 no_of_sent = theNoOfSentTransactions; Uint32 no_of_sent = theNoOfSentTransactions;
for (Uint32 i = 0; i < no_of_sent; i++) { for (Uint32 i = 0; i < no_of_sent; i++) {
NdbConnection* a_con = theSentTransactionsArray[i]; NdbConnection* a_con = theSentTransactionsArray[i];
if ((current_time - a_con->theStartTransTime) > if ((current_time - a_con->theStartTransTime) > timeout)
WAITFOR_RESPONSE_TIMEOUT) { {
#ifdef VM_TRACE #ifdef VM_TRACE
a_con->printState(); a_con->printState();
Uint32 t1 = a_con->theTransactionId; Uint32 t1 = a_con->theTransactionId;
Uint32 t2 = a_con->theTransactionId >> 32; Uint32 t2 = a_con->theTransactionId >> 32;
ndbout_c("[%.8x %.8x]", t1, t2); ndbout_c("4012 [%.8x %.8x]", t1, t2);
abort(); //abort();
#endif #endif
a_con->theReleaseOnClose = true;
a_con->setOperationErrorCodeAbort(4012); a_con->setOperationErrorCodeAbort(4012);
a_con->theCommitStatus = NdbConnection::Aborted; a_con->theCommitStatus = NdbConnection::NeedAbort;
a_con->theCompletionStatus = NdbConnection::CompletedFailure; a_con->theCompletionStatus = NdbConnection::CompletedFailure;
a_con->handleExecuteCompletion(); a_con->handleExecuteCompletion();
remove_sent_list(i); remove_sent_list(i);
......
...@@ -567,6 +567,20 @@ TransporterFacade::init(Uint32 nodeId, const ndb_mgm_configuration* props) ...@@ -567,6 +567,20 @@ TransporterFacade::init(Uint32 nodeId, const ndb_mgm_configuration* props)
} }
#endif #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)){ if (!theTransporterRegistry->start_service(m_socket_server)){
ndbout_c("Unable to start theTransporterRegistry->start_service"); ndbout_c("Unable to start theTransporterRegistry->start_service");
DBUG_RETURN(false); DBUG_RETURN(false);
......
...@@ -172,6 +172,7 @@ private: ...@@ -172,6 +172,7 @@ private:
*/ */
public: public:
STATIC_CONST( MAX_NO_THREADS = 4711 ); STATIC_CONST( MAX_NO_THREADS = 4711 );
Uint32 m_waitfor_timeout; // in milli seconds...
private: private:
struct ThreadData { struct ThreadData {
......
...@@ -24,6 +24,7 @@ ...@@ -24,6 +24,7 @@
#define TIMEOUT (Uint32)3000 #define TIMEOUT (Uint32)3000
Uint32 g_org_timeout = 3000; Uint32 g_org_timeout = 3000;
Uint32 g_org_deadlock = 3000;
int int
setTransactionTimeout(NDBT_Context* ctx, NDBT_Step* step){ setTransactionTimeout(NDBT_Context* ctx, NDBT_Step* step){
...@@ -59,6 +60,60 @@ resetTransactionTimeout(NDBT_Context* ctx, NDBT_Step* step){ ...@@ -59,6 +60,60 @@ resetTransactionTimeout(NDBT_Context* ctx, NDBT_Step* step){
return NDBT_OK; 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){ int runLoadTable(NDBT_Context* ctx, NDBT_Step* step){
...@@ -374,6 +429,43 @@ int runBuddyTransNoTimeout(NDBT_Context* ctx, NDBT_Step* step){ ...@@ -374,6 +429,43 @@ int runBuddyTransNoTimeout(NDBT_Context* ctx, NDBT_Step* step){
return result; 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); NDBT_TESTSUITE(testTimeout);
TESTCASE("DontTimeoutTransaction", TESTCASE("DontTimeoutTransaction",
"Test that the transaction does not timeout "\ "Test that the transaction does not timeout "\
...@@ -465,6 +557,15 @@ TESTCASE("BuddyTransNoTimeout5", ...@@ -465,6 +557,15 @@ TESTCASE("BuddyTransNoTimeout5",
FINALIZER(resetTransactionTimeout); FINALIZER(resetTransactionTimeout);
FINALIZER(runClearTable); FINALIZER(runClearTable);
} }
TESTCASE("Error4012", ""){
TC_PROPERTY("TransactionDeadlockTimeout", 120000);
INITIALIZER(runLoadTable);
INITIALIZER(getDeadlockTimeout);
INITIALIZER(setDeadlockTimeout);
STEPS(runError4012, 2);
FINALIZER(runClearTable);
}
NDBT_TESTSUITE_END(testTimeout); NDBT_TESTSUITE_END(testTimeout);
int main(int argc, const char** argv){ int main(int argc, const char** argv){
......
...@@ -236,6 +236,10 @@ max-time: 500 ...@@ -236,6 +236,10 @@ max-time: 500
cmd: testTimeout cmd: testTimeout
args: -n TimeoutRandTransaction T1 args: -n TimeoutRandTransaction T1
max-time: 600
cmd: testTimeout
args: -n Error4012 T1
# SCAN TESTS # SCAN TESTS
# #
max-time: 500 max-time: 500
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment