1
/* Copyright (C) 2003 MySQL AB
3
This program is free software; you can redistribute it and/or modify
4
it under the terms of the GNU General Public License as published by
5
the Free Software Foundation; version 2 of the License.
7
This program is distributed in the hope that it will be useful,
8
but WITHOUT ANY WARRANTY; without even the implied warranty of
9
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10
GNU General Public License for more details.
12
You should have received a copy of the GNU General Public License
13
along with this program; if not, write to the Free Software
14
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
17
#include <NDBT_Test.hpp>
18
#include <HugoTransactions.hpp>
19
#include <UtilTransactions.hpp>
21
#include <NdbConfig.hpp>
22
#include <signaldata/DumpStateOrd.hpp>
24
#define TIMEOUT (Uint32)3000
25
Uint32 g_org_timeout = 3000;
26
Uint32 g_org_deadlock = 3000;
29
setTransactionTimeout(NDBT_Context* ctx, NDBT_Step* step){
30
NdbRestarter restarter;
31
int timeout = ctx->getProperty("TransactionInactiveTimeout",TIMEOUT);
33
NdbConfig conf(GETNDB(step)->getNodeId()+1);
34
unsigned int nodeId = conf.getMasterNodeId();
35
if (!conf.getProperty(nodeId,
37
CFG_DB_TRANSACTION_INACTIVE_TIMEOUT,
42
int val[] = { DumpStateOrd::TcSetApplTransactionTimeout, timeout };
43
if(restarter.dumpStateAllNodes(val, 2) != 0){
51
resetTransactionTimeout(NDBT_Context* ctx, NDBT_Step* step){
52
NdbRestarter restarter;
54
int val[] = { DumpStateOrd::TcSetApplTransactionTimeout, g_org_timeout };
55
if(restarter.dumpStateAllNodes(val, 2) != 0){
63
setDeadlockTimeout(NDBT_Context* ctx, NDBT_Step* step){
64
NdbRestarter restarter;
65
int timeout = ctx->getProperty("TransactionDeadlockTimeout", TIMEOUT);
67
NdbConfig conf(GETNDB(step)->getNodeId()+1);
68
unsigned int nodeId = conf.getMasterNodeId();
69
if (!conf.getProperty(nodeId,
71
CFG_DB_TRANSACTION_DEADLOCK_TIMEOUT,
75
g_err << "Setting timeout: " << timeout << endl;
76
int val[] = { DumpStateOrd::TcSetTransactionTimeout, timeout };
77
if(restarter.dumpStateAllNodes(val, 2) != 0){
85
getDeadlockTimeout(NDBT_Context* ctx, NDBT_Step* step){
86
NdbRestarter restarter;
89
NdbConfig conf(GETNDB(step)->getNodeId()+1);
90
unsigned int nodeId = conf.getMasterNodeId();
91
if (!conf.getProperty(nodeId,
93
CFG_DB_TRANSACTION_DEADLOCK_TIMEOUT,
99
ctx->setProperty("TransactionDeadlockTimeout", 4*val);
105
resetDeadlockTimeout(NDBT_Context* ctx, NDBT_Step* step){
106
NdbRestarter restarter;
108
int val[] = { DumpStateOrd::TcSetTransactionTimeout, g_org_deadlock };
109
if(restarter.dumpStateAllNodes(val, 2) != 0){
117
int runLoadTable(NDBT_Context* ctx, NDBT_Step* step){
119
int records = ctx->getNumRecords();
120
HugoTransactions hugoTrans(*ctx->getTab());
121
if (hugoTrans.loadTable(GETNDB(step), records) != 0){
127
int runClearTable(NDBT_Context* ctx, NDBT_Step* step){
128
int records = ctx->getNumRecords();
130
UtilTransactions utilTrans(*ctx->getTab());
131
if (utilTrans.clearTable2(GETNDB(step), records) != 0){
138
#define CHECK(b) if (!(b)) { \
139
ndbout << "ERR: "<< step->getName() \
140
<< " failed on line " << __LINE__ << endl; \
141
result = NDBT_FAILED; \
144
int runTimeoutTrans2(NDBT_Context* ctx, NDBT_Step* step){
145
int result = NDBT_OK;
146
int loops = ctx->getNumLoops();
147
int stepNo = step->getStepNo();
148
int mul1 = ctx->getProperty("Op1", (Uint32)0);
149
int mul2 = ctx->getProperty("Op2", (Uint32)0);
150
int records = ctx->getNumRecords();
152
int timeout = ctx->getProperty("TransactionInactiveTimeout",TIMEOUT);
154
int minSleep = (int)(timeout * 1.5);
155
int maxSleep = timeout * 2;
157
HugoOperations hugoOps(*ctx->getTab());
158
Ndb* pNdb = GETNDB(step);
160
for (int l = 0; l<loops && !ctx->isTestStopped() && result == NDBT_OK; l++){
162
int op1 = 0 + (l + stepNo) * mul1;
163
int op2 = 0 + (l + stepNo) * mul2;
168
ndbout << stepNo << ": TransactionInactiveTimeout="<< timeout
169
<< ", minSleep="<<minSleep
170
<< ", maxSleep="<<maxSleep
172
<< ", op2=" << op2 << endl;;
175
// Commit transaction
176
CHECK(hugoOps.startTransaction(pNdb) == 0);
182
if(hugoOps.pkReadRecord(pNdb, stepNo) != 0){
183
g_err << stepNo << ": Fail" << __LINE__ << endl;
184
result = NDBT_FAILED; break;
188
if(hugoOps.pkUpdateRecord(pNdb, stepNo) != 0){
189
g_err << stepNo << ": Fail" << __LINE__ << endl;
190
result = NDBT_FAILED; break;
194
if(hugoOps.pkDeleteRecord(pNdb, stepNo) != 0){
195
g_err << stepNo << ": Fail" << __LINE__ << endl;
196
result = NDBT_FAILED; break;
200
if(hugoOps.pkInsertRecord(pNdb, stepNo+records+l) != 0){
201
g_err << stepNo << ": Fail" << __LINE__ << endl;
202
result = NDBT_FAILED; break;
207
if(result != NDBT_OK)
210
int res = hugoOps.execute_NoCommit(pNdb);
212
g_err << stepNo << ": Fail" << __LINE__ << endl;
213
result = NDBT_FAILED; break;
216
int sleep = minSleep + myRandom48(maxSleep-minSleep);
217
ndbout << stepNo << ": Sleeping for "<< sleep << " milliseconds" << endl;
218
NdbSleep_MilliSleep(sleep);
224
if(hugoOps.pkReadRecord(pNdb, stepNo) != 0){
225
g_err << stepNo << ": Fail" << __LINE__ << endl;
226
result = NDBT_FAILED; break;
230
if(hugoOps.pkUpdateRecord(pNdb, stepNo) != 0){
231
g_err << stepNo << ": Fail" << __LINE__ << endl;
232
result = NDBT_FAILED; break;
236
if(hugoOps.pkDeleteRecord(pNdb, stepNo) != 0){
237
g_err << stepNo << ": Fail" << __LINE__ << endl;
238
result = NDBT_FAILED; break;
242
if(hugoOps.pkInsertRecord(pNdb, stepNo+2*records+l) != 0){
243
g_err << stepNo << ": Fail" << __LINE__ << endl;
244
result = NDBT_FAILED; break;
249
// Expect that transaction has timed-out
250
res = hugoOps.execute_Commit(pNdb);
251
if(op1 != 0 && res != 266){
252
g_err << stepNo << ": Fail: " << res << "!= 237, op1="
253
<< op1 << ", op2=" << op2 << endl;
254
result = NDBT_FAILED; break;
259
hugoOps.closeTransaction(pNdb);
265
int runDontTimeoutTrans(NDBT_Context* ctx, NDBT_Step* step){
266
int result = NDBT_OK;
267
int loops = ctx->getNumLoops();
268
int stepNo = step->getStepNo();
270
int timeout = ctx->getProperty("TransactionInactiveTimeout",TIMEOUT);
272
int maxSleep = (int)(timeout * 0.5);
273
ndbout << "TransactionInactiveTimeout="<< timeout
274
<< ", maxSleep="<<maxSleep<<endl;
277
HugoOperations hugoOps(*ctx->getTab());
278
Ndb* pNdb = GETNDB(step);
280
for (int l = 0; l < loops && result == NDBT_OK; l++){
283
// Commit transaction
284
CHECK(hugoOps.startTransaction(pNdb) == 0);
285
CHECK(hugoOps.pkReadRecord(pNdb, stepNo) == 0);
286
CHECK(hugoOps.execute_NoCommit(pNdb) == 0);
288
int sleep = myRandom48(maxSleep);
289
ndbout << "Sleeping for " << sleep << " milliseconds" << endl;
290
NdbSleep_MilliSleep(sleep);
292
// Expect that transaction has NOT timed-out
293
CHECK(hugoOps.execute_Commit(pNdb) == 0);
297
hugoOps.closeTransaction(pNdb);
303
int runDeadlockTimeoutTrans(NDBT_Context* ctx, NDBT_Step* step){
304
int result = NDBT_OK;
305
int loops = ctx->getNumLoops();
306
int stepNo = step->getStepNo();
308
Uint32 deadlock_timeout;
309
NdbConfig conf(GETNDB(step)->getNodeId()+1);
310
unsigned int nodeId = conf.getMasterNodeId();
311
if (!conf.getProperty(nodeId,
313
CFG_DB_TRANSACTION_DEADLOCK_TIMEOUT,
319
int do_sleep = (int)(deadlock_timeout * 0.5);
322
HugoOperations hugoOps(*ctx->getTab());
323
Ndb* pNdb = GETNDB(step);
325
for (int l = 0; l < loops && result == NDBT_OK; l++){
328
// Commit transaction
329
CHECK(hugoOps.startTransaction(pNdb) == 0);
330
CHECK(hugoOps.pkReadRecord(pNdb, stepNo) == 0);
331
CHECK(hugoOps.execute_NoCommit(pNdb) == 0);
333
int sleep = deadlock_timeout * 1.5 + myRandom48(do_sleep);
334
ndbout << "Sleeping for " << sleep << " milliseconds" << endl;
335
NdbSleep_MilliSleep(sleep);
337
// Expect that transaction has NOT timed-out
338
CHECK(hugoOps.execute_Commit(pNdb) == 0);
342
hugoOps.closeTransaction(pNdb);
348
int runBuddyTransNoTimeout(NDBT_Context* ctx, NDBT_Step* step){
349
int result = NDBT_OK;
350
int loops = ctx->getNumLoops();
351
int records = ctx->getNumRecords();
352
int stepNo = step->getStepNo();
353
int maxSleep = (int)(TIMEOUT * 0.3);
354
ndbout << "TransactionInactiveTimeout="<< TIMEOUT
355
<< ", maxSleep="<<maxSleep<<endl;
357
HugoOperations hugoOps(*ctx->getTab());
358
Ndb* pNdb = GETNDB(step);
360
for (int l = 1; l < loops && result == NDBT_OK; l++){
363
// Start an insert trans
364
CHECK(hugoOps.startTransaction(pNdb) == 0);
365
int recordNo = records + (stepNo*loops) + l;
366
CHECK(hugoOps.pkInsertRecord(pNdb, recordNo) == 0);
367
CHECK(hugoOps.execute_NoCommit(pNdb) == 0);
369
for (int i = 0; i < 3; i++){
370
// Perform buddy scan reads
371
CHECK((hugoOps.scanReadRecords(pNdb)) == 0);
372
CHECK(hugoOps.execute_NoCommit(pNdb) == 0);
374
int sleep = myRandom48(maxSleep);
375
ndbout << "Sleeping for " << sleep << " milliseconds" << endl;
376
NdbSleep_MilliSleep(sleep);
379
// Expect that transaction has NOT timed-out
380
CHECK(hugoOps.execute_Commit(pNdb) == 0);
384
hugoOps.closeTransaction(pNdb);
390
int runBuddyTransTimeout(NDBT_Context* ctx, NDBT_Step* step){
391
int result = NDBT_OK;
392
int loops = ctx->getNumLoops();
393
int records = ctx->getNumRecords();
394
int stepNo = step->getStepNo();
395
ndbout << "TransactionInactiveTimeout="<< TIMEOUT <<endl;
397
HugoOperations hugoOps(*ctx->getTab());
398
Ndb* pNdb = GETNDB(step);
400
for (int l = 1; l < loops && result == NDBT_OK; l++){
402
NdbTransaction* pTrans = 0;
404
pTrans = pNdb->startTransaction();
405
NdbScanOperation* pOp = pTrans->getNdbScanOperation(ctx->getTab());
406
CHECK(pOp->readTuples(NdbOperation::LM_Read, 0, 0, 1) == 0);
407
CHECK(pTrans->execute(NoCommit) == 0);
409
int sleep = 2 * TIMEOUT;
410
ndbout << "Sleeping for " << sleep << " milliseconds" << endl;
411
NdbSleep_MilliSleep(sleep);
414
while((res = pOp->nextResult()) == 0);
415
ndbout_c("res: %d", res);
430
runError4012(NDBT_Context* ctx, NDBT_Step* step){
431
int result = NDBT_OK;
432
int loops = ctx->getNumLoops();
433
int stepNo = step->getStepNo();
435
int timeout = ctx->getProperty("TransactionDeadlockTimeout", TIMEOUT);
437
HugoOperations hugoOps(*ctx->getTab());
438
Ndb* pNdb = GETNDB(step);
441
// Commit transaction
442
CHECK(hugoOps.startTransaction(pNdb) == 0);
443
CHECK(hugoOps.pkUpdateRecord(pNdb, 0) == 0);
444
int ret = hugoOps.execute_NoCommit(pNdb);
448
ndbout << "Sleeping for " << sleep << " milliseconds" << endl;
449
NdbSleep_MilliSleep(sleep);
451
// Expect that transaction has NOT timed-out
452
CHECK(hugoOps.execute_Commit(pNdb) == 0);
460
hugoOps.closeTransaction(pNdb);
466
NDBT_TESTSUITE(testTimeout);
467
TESTCASE("DontTimeoutTransaction",
468
"Test that the transaction does not timeout "\
469
"if we sleep during the transaction. Use a sleep "\
470
"value which is smaller than TransactionInactiveTimeout"){
471
INITIALIZER(runLoadTable);
472
INITIALIZER(setTransactionTimeout);
473
STEPS(runDontTimeoutTrans, 1);
474
FINALIZER(resetTransactionTimeout);
475
FINALIZER(runClearTable);
478
"Setting TransactionInactiveTimeout to 0(zero) "\
479
"should result in infinite timeout, and not as "\
480
"was the bug, a timeout that is equal to the deadlock timeout"){
481
TC_PROPERTY("TransactionInactiveTimeout",(Uint32)0);
482
INITIALIZER(runLoadTable);
483
INITIALIZER(setTransactionTimeout);
484
STEPS(runDeadlockTimeoutTrans, 1);
485
FINALIZER(resetTransactionTimeout);
486
FINALIZER(runClearTable);
488
TESTCASE("DontTimeoutTransaction5",
489
"Test that the transaction does not timeout "\
490
"if we sleep during the transaction. Use a sleep "\
491
"value which is smaller than TransactionInactiveTimeout" \
492
"Five simultaneous threads"){
493
INITIALIZER(runLoadTable);
494
INITIALIZER(setTransactionTimeout);
495
STEPS(runDontTimeoutTrans, 5);
496
FINALIZER(resetTransactionTimeout);
497
FINALIZER(runClearTable);
499
TESTCASE("TimeoutRandTransaction",
500
"Test that the transaction does timeout "\
501
"if we sleep during the transaction. Use a sleep "\
502
"value which is larger than TransactionInactiveTimeout"){
503
INITIALIZER(runLoadTable);
504
INITIALIZER(setTransactionTimeout);
505
TC_PROPERTY("Op1", 7);
506
TC_PROPERTY("Op2", 11);
507
STEPS(runTimeoutTrans2, 5);
508
FINALIZER(resetTransactionTimeout);
509
FINALIZER(runClearTable);
511
TESTCASE("BuddyTransNoTimeout",
512
"Start a transaction and perform an insert with NoCommit. " \
513
"Start a buddy transaction wich performs long running scans " \
515
"The total sleep time is longer than TransactionInactiveTimeout" \
516
"Commit the first transaction, it should not have timed out."){
517
INITIALIZER(runLoadTable);
518
INITIALIZER(setTransactionTimeout);
519
STEPS(runBuddyTransNoTimeout, 1);
520
FINALIZER(resetTransactionTimeout);
521
FINALIZER(runClearTable);
523
TESTCASE("BuddyTransNoTimeout5",
524
"Start a transaction and perform an insert with NoCommit. " \
525
"Start a buddy transaction wich performs long running scans " \
527
"The total sleep time is longer than TransactionInactiveTimeout" \
528
"Commit the first transaction, it should not have timed out." \
529
"Five simultaneous threads"){
530
INITIALIZER(runLoadTable);
531
INITIALIZER(setTransactionTimeout);
532
STEPS(runBuddyTransNoTimeout, 5);
533
FINALIZER(resetTransactionTimeout);
534
FINALIZER(runClearTable);
536
TESTCASE("BuddyTransTimeout1",
537
"Start a scan and check that it gets aborted"){
538
INITIALIZER(runLoadTable);
539
INITIALIZER(setTransactionTimeout);
540
STEPS(runBuddyTransTimeout, 1);
541
FINALIZER(resetTransactionTimeout);
542
FINALIZER(runClearTable);
545
TESTCASE("Error4012", ""){
546
TC_PROPERTY("TransactionDeadlockTimeout", 120000);
547
INITIALIZER(runLoadTable);
548
INITIALIZER(getDeadlockTimeout);
549
INITIALIZER(setDeadlockTimeout);
550
STEPS(runError4012, 2);
551
FINALIZER(runClearTable);
554
NDBT_TESTSUITE_END(testTimeout);
556
int main(int argc, const char** argv){
558
myRandom48Init(NdbTick_CurrentMillisecond());
559
return testTimeout.execute(argc, argv);