Commit 51a093f1 authored by unknown's avatar unknown
Browse files

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
parent 37230a2a
Loading
Loading
Loading
Loading
+2 −2
Original line number Diff line number Diff line
@@ -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.
+7 −5
Original line number Diff line number Diff line
@@ -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);
+14 −0
Original line number Diff line number Diff line
@@ -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);
+1 −0
Original line number Diff line number Diff line
@@ -172,6 +172,7 @@ private:
   */
public:
  STATIC_CONST( MAX_NO_THREADS = 4711 );
  Uint32 m_waitfor_timeout; // in milli seconds...
private:

  struct ThreadData {
+101 −0
Original line number Diff line number Diff line
@@ -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){
Loading