Commit 6b4d60e6 authored by joreland@mysql.com's avatar joreland@mysql.com

BUG#4230 - fixed

parent cd1a3dae
......@@ -1686,6 +1686,20 @@ Dbtc::TCKEY_abort(Signal* signal, int place)
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:
jam();
systemErrorLab(signal);
......@@ -2363,6 +2377,8 @@ void Dbtc::execTCKEYREQ(Signal* signal)
apiConnectptr.p = regApiPtr;
Uint32 TstartFlag = tcKeyReq->getStartFlag(Treqinfo);
Uint32 TexecFlag = TcKeyReq::getExecuteFlag(Treqinfo);
bool isIndexOp = regApiPtr->isIndexOp;
bool isIndexOpReturn = regApiPtr->indexOpReturn;
regApiPtr->isIndexOp = false; // Reset marker
......@@ -2416,14 +2432,17 @@ void Dbtc::execTCKEYREQ(Signal* signal)
//--------------------------------------------------------------------
jam();
initApiConnectRec(signal, regApiPtr);
} else {
} else if(TexecFlag) {
TCKEY_abort(signal, 59);
return;
} else {
//--------------------------------------------------------------------
// The current transaction was aborted successfully.
// We will not do anything before we receive an operation
// with a start indicator. We will ignore this signal.
//--------------------------------------------------------------------
jam();
// DEBUG("Drop TCKEYREQ - apiConnectState=CS_ABORTING, ==AS_IDLE");
jam();
DEBUG("Drop TCKEYREQ - apiConnectState=CS_ABORTING, ==AS_IDLE");
return;
}//if
} else {
......@@ -2438,11 +2457,14 @@ void Dbtc::execTCKEYREQ(Signal* signal)
//--------------------------------------------------------------------
TCKEY_abort(signal, 2);
return;
}//if
} else if(TexecFlag) {
TCKEY_abort(signal, 59);
return;
}
//----------------------------------------------------------------------
// 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;
}//if
break;
......@@ -2532,7 +2554,7 @@ void Dbtc::execTCKEYREQ(Signal* signal)
regTcPtr->triggeringOperation = TsenderData;
}
if (TcKeyReq::getExecuteFlag(Treqinfo)){
if (TexecFlag){
Uint32 currSPId = regApiPtr->currSavePointId;
regApiPtr->currSavePointId = ++currSPId;
}
......@@ -2553,7 +2575,7 @@ void Dbtc::execTCKEYREQ(Signal* signal)
Uint8 TDistrGroupFlag = tcKeyReq->getDistributionGroupFlag(Treqinfo);
Uint8 TDistrGroupTypeFlag = tcKeyReq->getDistributionGroupTypeFlag(Treqinfo);
Uint8 TDistrKeyFlag = tcKeyReq->getDistributionKeyFlag(Treqinfo);
Uint8 TexecuteFlag = tcKeyReq->getExecuteFlag(Treqinfo);
Uint8 TexecuteFlag = TexecFlag;
//RONM_TEST Disable simple reads temporarily
regCachePtr->opSimple = 0;
......
......@@ -95,6 +95,131 @@ int runTimeoutTrans(NDBT_Context* ctx, NDBT_Step* step){
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 result = NDBT_OK;
int loops = ctx->getNumLoops();
......@@ -231,6 +356,16 @@ TESTCASE("TimeoutTransaction5",
STEPS(runTimeoutTrans, 5);
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",
"Start a transaction and perform an insert with NoCommit. " \
"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