Commit b3d8ec93 authored by unknown's avatar unknown

BUG#4230 - fixed


ndb/src/kernel/blocks/dbtc/DbtcMain.cpp:
  BUG#4230
  Solution: always reply when exeute bit is set
ndb/test/ndbapi/testTimeout.cpp:
  test for BUG#4230
parent 8358e07a
...@@ -1686,6 +1686,20 @@ Dbtc::TCKEY_abort(Signal* signal, int place) ...@@ -1686,6 +1686,20 @@ Dbtc::TCKEY_abort(Signal* signal, int place)
return; return;
} }
case 59:{
jam();
const TcKeyReq * const tcKeyReq = (TcKeyReq *)&signal->theData[0];
const Uint32 t1 = tcKeyReq->transId1;
const Uint32 t2 = tcKeyReq->transId2;
signal->theData[0] = apiConnectptr.p->ndbapiConnect;
signal->theData[1] = t1;
signal->theData[2] = t2;
signal->theData[3] = ZABORTINPROGRESS;
sendSignal(apiConnectptr.p->ndbapiBlockref,
GSN_TCROLLBACKREP, signal, 4, JBB);
return;
}
default: default:
jam(); jam();
systemErrorLab(signal); systemErrorLab(signal);
...@@ -2363,6 +2377,8 @@ void Dbtc::execTCKEYREQ(Signal* signal) ...@@ -2363,6 +2377,8 @@ void Dbtc::execTCKEYREQ(Signal* signal)
apiConnectptr.p = regApiPtr; apiConnectptr.p = regApiPtr;
Uint32 TstartFlag = tcKeyReq->getStartFlag(Treqinfo); Uint32 TstartFlag = tcKeyReq->getStartFlag(Treqinfo);
Uint32 TexecFlag = TcKeyReq::getExecuteFlag(Treqinfo);
bool isIndexOp = regApiPtr->isIndexOp; bool isIndexOp = regApiPtr->isIndexOp;
bool isIndexOpReturn = regApiPtr->indexOpReturn; bool isIndexOpReturn = regApiPtr->indexOpReturn;
regApiPtr->isIndexOp = false; // Reset marker regApiPtr->isIndexOp = false; // Reset marker
...@@ -2416,6 +2432,9 @@ void Dbtc::execTCKEYREQ(Signal* signal) ...@@ -2416,6 +2432,9 @@ void Dbtc::execTCKEYREQ(Signal* signal)
//-------------------------------------------------------------------- //--------------------------------------------------------------------
jam(); jam();
initApiConnectRec(signal, regApiPtr); initApiConnectRec(signal, regApiPtr);
} else if(TexecFlag) {
TCKEY_abort(signal, 59);
return;
} else { } else {
//-------------------------------------------------------------------- //--------------------------------------------------------------------
// The current transaction was aborted successfully. // The current transaction was aborted successfully.
...@@ -2423,7 +2442,7 @@ void Dbtc::execTCKEYREQ(Signal* signal) ...@@ -2423,7 +2442,7 @@ void Dbtc::execTCKEYREQ(Signal* signal)
// with a start indicator. We will ignore this signal. // with a start indicator. We will ignore this signal.
//-------------------------------------------------------------------- //--------------------------------------------------------------------
jam(); jam();
// DEBUG("Drop TCKEYREQ - apiConnectState=CS_ABORTING, ==AS_IDLE"); DEBUG("Drop TCKEYREQ - apiConnectState=CS_ABORTING, ==AS_IDLE");
return; return;
}//if }//if
} else { } else {
...@@ -2438,11 +2457,14 @@ void Dbtc::execTCKEYREQ(Signal* signal) ...@@ -2438,11 +2457,14 @@ void Dbtc::execTCKEYREQ(Signal* signal)
//-------------------------------------------------------------------- //--------------------------------------------------------------------
TCKEY_abort(signal, 2); TCKEY_abort(signal, 2);
return; return;
}//if } else if(TexecFlag) {
TCKEY_abort(signal, 59);
return;
}
//---------------------------------------------------------------------- //----------------------------------------------------------------------
// Ignore signals without start indicator set when aborting transaction. // Ignore signals without start indicator set when aborting transaction.
//---------------------------------------------------------------------- //----------------------------------------------------------------------
// DEBUG("Drop TCKEYREQ - apiConnectState=CS_ABORTING, !=AS_IDLE"); DEBUG("Drop TCKEYREQ - apiConnectState=CS_ABORTING, !=AS_IDLE");
return; return;
}//if }//if
break; break;
...@@ -2532,7 +2554,7 @@ void Dbtc::execTCKEYREQ(Signal* signal) ...@@ -2532,7 +2554,7 @@ void Dbtc::execTCKEYREQ(Signal* signal)
regTcPtr->triggeringOperation = TsenderData; regTcPtr->triggeringOperation = TsenderData;
} }
if (TcKeyReq::getExecuteFlag(Treqinfo)){ if (TexecFlag){
Uint32 currSPId = regApiPtr->currSavePointId; Uint32 currSPId = regApiPtr->currSavePointId;
regApiPtr->currSavePointId = ++currSPId; regApiPtr->currSavePointId = ++currSPId;
} }
...@@ -2553,7 +2575,7 @@ void Dbtc::execTCKEYREQ(Signal* signal) ...@@ -2553,7 +2575,7 @@ void Dbtc::execTCKEYREQ(Signal* signal)
Uint8 TDistrGroupFlag = tcKeyReq->getDistributionGroupFlag(Treqinfo); Uint8 TDistrGroupFlag = tcKeyReq->getDistributionGroupFlag(Treqinfo);
Uint8 TDistrGroupTypeFlag = tcKeyReq->getDistributionGroupTypeFlag(Treqinfo); Uint8 TDistrGroupTypeFlag = tcKeyReq->getDistributionGroupTypeFlag(Treqinfo);
Uint8 TDistrKeyFlag = tcKeyReq->getDistributionKeyFlag(Treqinfo); Uint8 TDistrKeyFlag = tcKeyReq->getDistributionKeyFlag(Treqinfo);
Uint8 TexecuteFlag = tcKeyReq->getExecuteFlag(Treqinfo); Uint8 TexecuteFlag = TexecFlag;
//RONM_TEST Disable simple reads temporarily //RONM_TEST Disable simple reads temporarily
regCachePtr->opSimple = 0; regCachePtr->opSimple = 0;
......
...@@ -95,6 +95,131 @@ int runTimeoutTrans(NDBT_Context* ctx, NDBT_Step* step){ ...@@ -95,6 +95,131 @@ int runTimeoutTrans(NDBT_Context* ctx, NDBT_Step* step){
return result; return result;
} }
int runTimeoutTrans2(NDBT_Context* ctx, NDBT_Step* step){
int result = NDBT_OK;
int loops = ctx->getNumLoops();
NdbConfig conf(GETNDB(step)->getNodeId()+1);
unsigned int nodeId = conf.getMasterNodeId();
int stepNo = step->getStepNo();
int mul1 = ctx->getProperty("Op1", (Uint32)0);
int mul2 = ctx->getProperty("Op2", (Uint32)0);
int records = ctx->getNumRecords();
Uint32 timeoutVal;
if (!conf.getProperty(nodeId,
NODE_TYPE_DB,
CFG_DB_TRANSACTION_INACTIVE_TIMEOUT,
&timeoutVal)){
return NDBT_FAILED;
}
int minSleep = (int)(timeoutVal * 1.5);
int maxSleep = timeoutVal * 2;
HugoOperations hugoOps(*ctx->getTab());
Ndb* pNdb = GETNDB(step);
for (int l = 0; l < loops && !ctx->isTestStopped(); l++){
int op1 = 0 + (l + stepNo) * mul1;
int op2 = 0 + (l + stepNo) * mul2;
op1 = (op1 % 5);
op2 = (op2 % 5);
ndbout << stepNo << ": TransactionInactiveTimeout="<<timeoutVal
<< ", minSleep="<<minSleep
<< ", maxSleep="<<maxSleep
<< ", op1=" << op1
<< ", op2=" << op2 << endl;;
do{
// Commit transaction
CHECK(hugoOps.startTransaction(pNdb) == 0);
switch(op1){
case 0:
break;
case 1:
if(hugoOps.pkReadRecord(pNdb, stepNo, true) != 0){
g_err << stepNo << ": Fail" << __LINE__ << endl;
return NDBT_FAILED;
}
break;
case 2:
if(hugoOps.pkUpdateRecord(pNdb, stepNo, true) != 0){
g_err << stepNo << ": Fail" << __LINE__ << endl;
return NDBT_FAILED;
}
break;
case 3:
if(hugoOps.pkDeleteRecord(pNdb, stepNo, true) != 0){
g_err << stepNo << ": Fail" << __LINE__ << endl;
return NDBT_FAILED;
}
break;
case 4:
if(hugoOps.pkInsertRecord(pNdb, stepNo+records+l, true) != 0){
g_err << stepNo << ": Fail" << __LINE__ << endl;
return NDBT_FAILED;
}
break;
}
int res = hugoOps.execute_NoCommit(pNdb);
if(res != 0){
g_err << stepNo << ": Fail" << __LINE__ << endl;
return NDBT_FAILED;
}
int sleep = minSleep + myRandom48(maxSleep-minSleep);
ndbout << stepNo << ": Sleeping for "<< sleep << " milliseconds" << endl;
NdbSleep_MilliSleep(sleep);
switch(op2){
case 0:
break;
case 1:
if(hugoOps.pkReadRecord(pNdb, stepNo, true) != 0){
g_err << stepNo << ": Fail" << __LINE__ << endl;
return NDBT_FAILED;
}
break;
case 2:
if(hugoOps.pkUpdateRecord(pNdb, stepNo, true) != 0){
g_err << stepNo << ": Fail" << __LINE__ << endl;
return NDBT_FAILED;
}
break;
case 3:
if(hugoOps.pkDeleteRecord(pNdb, stepNo, true) != 0){
g_err << stepNo << ": Fail" << __LINE__ << endl;
return NDBT_FAILED;
}
break;
case 4:
if(hugoOps.pkInsertRecord(pNdb, stepNo+2*records+l, true) != 0){
g_err << stepNo << ": Fail" << __LINE__ << endl;
return NDBT_FAILED;
}
break;
}
// Expect that transaction has timed-out
res = hugoOps.execute_Commit(pNdb);
if(op1 != 0 && res != 237){
g_err << stepNo << ": Fail: " << res << "!= 237, op1="
<< op1 << ", op2=" << op2 << endl;
return NDBT_FAILED;
}
} while(false);
hugoOps.closeTransaction(pNdb);
}
return result;
}
int runDontTimeoutTrans(NDBT_Context* ctx, NDBT_Step* step){ int runDontTimeoutTrans(NDBT_Context* ctx, NDBT_Step* step){
int result = NDBT_OK; int result = NDBT_OK;
int loops = ctx->getNumLoops(); int loops = ctx->getNumLoops();
...@@ -231,6 +356,16 @@ TESTCASE("TimeoutTransaction5", ...@@ -231,6 +356,16 @@ TESTCASE("TimeoutTransaction5",
STEPS(runTimeoutTrans, 5); STEPS(runTimeoutTrans, 5);
FINALIZER(runClearTable); FINALIZER(runClearTable);
} }
TESTCASE("TimeoutRandTransaction",
"Test that the transaction does timeout "\
"if we sleep during the transaction. Use a sleep "\
"value which is larger than TransactionInactiveTimeout"){
INITIALIZER(runLoadTable);
TC_PROPERTY("Op1", 7);
TC_PROPERTY("Op2", 11);
STEPS(runTimeoutTrans2, 5);
FINALIZER(runClearTable);
}
TESTCASE("BuddyTransNoTimeout", TESTCASE("BuddyTransNoTimeout",
"Start a transaction and perform an insert with NoCommit. " \ "Start a transaction and perform an insert with NoCommit. " \
"Start a buddy transaction wich performs long running scans " \ "Start a buddy transaction wich performs long running scans " \
......
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