mirror of
https://github.com/MariaDB/server.git
synced 2025-08-07 00:04:31 +03:00
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
This commit is contained in:
@@ -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)
|
|||||||
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)
|
|||||||
}
|
}
|
||||||
#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:
|
|||||||
*/
|
*/
|
||||||
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 @@
|
|||||||
|
|
||||||
#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){
|
|||||||
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){
|
|||||||
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",
|
|||||||
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
|
|||||||
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
|
||||||
|
Reference in New Issue
Block a user