MySQL 5.6.14 Source Code Document
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
testTimeout.cpp
1 /*
2  Copyright (c) 2003, 2010, Oracle and/or its affiliates. All rights reserved.
3 
4  This program is free software; you can redistribute it and/or modify
5  it under the terms of the GNU General Public License as published by
6  the Free Software Foundation; version 2 of the License.
7 
8  This program is distributed in the hope that it will be useful,
9  but WITHOUT ANY WARRANTY; without even the implied warranty of
10  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11  GNU General Public License for more details.
12 
13  You should have received a copy of the GNU General Public License
14  along with this program; if not, write to the Free Software
15  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
16 */
17 
18 #include <NDBT.hpp>
19 #include <NDBT_Test.hpp>
20 #include <HugoTransactions.hpp>
21 #include <UtilTransactions.hpp>
22 #include <random.h>
23 #include <NdbConfig.hpp>
24 #include <signaldata/DumpStateOrd.hpp>
25 
26 #define TIMEOUT (Uint32)3000
27 Uint32 g_org_timeout = 3000;
28 Uint32 g_org_deadlock = 3000;
29 
30 int
31 setTransactionTimeout(NDBT_Context* ctx, NDBT_Step* step){
32  NdbRestarter restarter;
33  int timeout = ctx->getProperty("TransactionInactiveTimeout",TIMEOUT);
34 
35  NdbConfig conf(GETNDB(step)->getNodeId()+1);
36  unsigned int nodeId = conf.getMasterNodeId();
37  if (!conf.getProperty(nodeId,
38  NODE_TYPE_DB,
39  CFG_DB_TRANSACTION_INACTIVE_TIMEOUT,
40  &g_org_timeout)){
41  return NDBT_FAILED;
42  }
43 
44  int val[] = { DumpStateOrd::TcSetApplTransactionTimeout, timeout };
45  if(restarter.dumpStateAllNodes(val, 2) != 0){
46  return NDBT_FAILED;
47  }
48 
49  return NDBT_OK;
50 }
51 
52 int
53 resetTransactionTimeout(NDBT_Context* ctx, NDBT_Step* step){
54  NdbRestarter restarter;
55 
56  int val[] = { DumpStateOrd::TcSetApplTransactionTimeout, g_org_timeout };
57  if(restarter.dumpStateAllNodes(val, 2) != 0){
58  return NDBT_FAILED;
59  }
60 
61  return NDBT_OK;
62 }
63 
64 int
65 setDeadlockTimeout(NDBT_Context* ctx, NDBT_Step* step){
66  NdbRestarter restarter;
67  int timeout = ctx->getProperty("TransactionDeadlockTimeout", TIMEOUT);
68 
69  NdbConfig conf(GETNDB(step)->getNodeId()+1);
70  unsigned int nodeId = conf.getMasterNodeId();
71  if (!conf.getProperty(nodeId,
72  NODE_TYPE_DB,
73  CFG_DB_TRANSACTION_DEADLOCK_TIMEOUT,
74  &g_org_deadlock))
75  return NDBT_FAILED;
76 
77  g_err << "Setting timeout: " << timeout << endl;
78  int val[] = { DumpStateOrd::TcSetTransactionTimeout, timeout };
79  if(restarter.dumpStateAllNodes(val, 2) != 0){
80  return NDBT_FAILED;
81  }
82 
83  return NDBT_OK;
84 }
85 
86 int
87 getDeadlockTimeout(NDBT_Context* ctx, NDBT_Step* step){
88  NdbRestarter restarter;
89 
90  Uint32 val = 0;
91  NdbConfig conf(GETNDB(step)->getNodeId()+1);
92  unsigned int nodeId = conf.getMasterNodeId();
93  if (!conf.getProperty(nodeId,
94  NODE_TYPE_DB,
95  CFG_DB_TRANSACTION_DEADLOCK_TIMEOUT,
96  &val))
97  return NDBT_FAILED;
98 
99  if (val < 120000)
100  val = 120000;
101  ctx->setProperty("TransactionDeadlockTimeout", 4*val);
102 
103  return NDBT_OK;
104 }
105 
106 int
107 resetDeadlockTimeout(NDBT_Context* ctx, NDBT_Step* step){
108  NdbRestarter restarter;
109 
110  int val[] = { DumpStateOrd::TcSetTransactionTimeout, g_org_deadlock };
111  if(restarter.dumpStateAllNodes(val, 2) != 0){
112  return NDBT_FAILED;
113  }
114 
115  return NDBT_OK;
116 }
117 
118 
119 int runLoadTable(NDBT_Context* ctx, NDBT_Step* step){
120 
121  int records = ctx->getNumRecords();
122  HugoTransactions hugoTrans(*ctx->getTab());
123  if (hugoTrans.loadTable(GETNDB(step), records) != 0){
124  return NDBT_FAILED;
125  }
126  return NDBT_OK;
127 }
128 
129 int runClearTable(NDBT_Context* ctx, NDBT_Step* step){
130  int records = ctx->getNumRecords();
131 
132  UtilTransactions utilTrans(*ctx->getTab());
133  if (utilTrans.clearTable2(GETNDB(step), records) != 0){
134  return NDBT_FAILED;
135  }
136  return NDBT_OK;
137 }
138 
139 
140 #define CHECK(b) if (!(b)) { \
141  ndbout << "ERR: "<< step->getName() \
142  << " failed on line " << __LINE__ << endl; \
143  result = NDBT_FAILED; \
144  break; }
145 
146 int runTimeoutTrans2(NDBT_Context* ctx, NDBT_Step* step){
147  int result = NDBT_OK;
148  int loops = ctx->getNumLoops();
149  int stepNo = step->getStepNo();
150  int mul1 = ctx->getProperty("Op1", (Uint32)0);
151  int mul2 = ctx->getProperty("Op2", (Uint32)0);
152  int records = ctx->getNumRecords();
153 
154  int timeout = ctx->getProperty("TransactionInactiveTimeout",TIMEOUT);
155 
156  int minSleep = (int)(timeout * 1.5);
157  int maxSleep = timeout * 2;
158 
159  HugoOperations hugoOps(*ctx->getTab());
160  Ndb* pNdb = GETNDB(step);
161 
162  for (int l = 0; l<loops && !ctx->isTestStopped() && result == NDBT_OK; l++){
163 
164  int op1 = 0 + (l + stepNo) * mul1;
165  int op2 = 0 + (l + stepNo) * mul2;
166 
167  op1 = (op1 % 5);
168  op2 = (op2 % 5);
169 
170  ndbout << stepNo << ": TransactionInactiveTimeout="<< timeout
171  << ", minSleep="<<minSleep
172  << ", maxSleep="<<maxSleep
173  << ", op1=" << op1
174  << ", op2=" << op2 << endl;;
175 
176  do{
177  // Commit transaction
178  CHECK(hugoOps.startTransaction(pNdb) == 0);
179 
180  switch(op1){
181  case 0:
182  break;
183  case 1:
184  if(hugoOps.pkReadRecord(pNdb, stepNo) != 0){
185  g_err << stepNo << ": Fail" << __LINE__ << endl;
186  result = NDBT_FAILED; break;
187  }
188  break;
189  case 2:
190  if(hugoOps.pkUpdateRecord(pNdb, stepNo) != 0){
191  g_err << stepNo << ": Fail" << __LINE__ << endl;
192  result = NDBT_FAILED; break;
193  }
194  break;
195  case 3:
196  if(hugoOps.pkDeleteRecord(pNdb, stepNo) != 0){
197  g_err << stepNo << ": Fail" << __LINE__ << endl;
198  result = NDBT_FAILED; break;
199  }
200  break;
201  case 4:
202  if(hugoOps.pkInsertRecord(pNdb, stepNo+records+l) != 0){
203  g_err << stepNo << ": Fail" << __LINE__ << endl;
204  result = NDBT_FAILED; break;
205  }
206  break;
207  }
208 
209  if(result != NDBT_OK)
210  break;
211 
212  int res = hugoOps.execute_NoCommit(pNdb);
213  if(res != 0){
214  g_err << stepNo << ": Fail" << __LINE__ << endl;
215  result = NDBT_FAILED; break;
216  }
217 
218  int sleep = minSleep + myRandom48(maxSleep-minSleep);
219  ndbout << stepNo << ": Sleeping for "<< sleep << " milliseconds" << endl;
220  NdbSleep_MilliSleep(sleep);
221 
222  switch(op2){
223  case 0:
224  break;
225  case 1:
226  if(hugoOps.pkReadRecord(pNdb, stepNo) != 0){
227  g_err << stepNo << ": Fail" << __LINE__ << endl;
228  result = NDBT_FAILED; break;
229  }
230  break;
231  case 2:
232  if(hugoOps.pkUpdateRecord(pNdb, stepNo) != 0){
233  g_err << stepNo << ": Fail" << __LINE__ << endl;
234  result = NDBT_FAILED; break;
235  }
236  break;
237  case 3:
238  if(hugoOps.pkDeleteRecord(pNdb, stepNo) != 0){
239  g_err << stepNo << ": Fail" << __LINE__ << endl;
240  result = NDBT_FAILED; break;
241  }
242  break;
243  case 4:
244  if(hugoOps.pkInsertRecord(pNdb, stepNo+2*records+l) != 0){
245  g_err << stepNo << ": Fail" << __LINE__ << endl;
246  result = NDBT_FAILED; break;
247  }
248  break;
249  }
250 
251  // Expect that transaction has timed-out
252  res = hugoOps.execute_Commit(pNdb);
253  if(op1 != 0 && res != 266){
254  g_err << stepNo << ": Fail: " << res << "!= 237, op1="
255  << op1 << ", op2=" << op2 << endl;
256  result = NDBT_FAILED; break;
257  }
258 
259  } while(false);
260 
261  hugoOps.closeTransaction(pNdb);
262  }
263 
264  return result;
265 }
266 
267 int runDontTimeoutTrans(NDBT_Context* ctx, NDBT_Step* step){
268  int result = NDBT_OK;
269  int loops = ctx->getNumLoops();
270  int stepNo = step->getStepNo();
271 
272  int timeout = ctx->getProperty("TransactionInactiveTimeout",TIMEOUT);
273 
274  int maxSleep = (int)(timeout * 0.5);
275  ndbout << "TransactionInactiveTimeout="<< timeout
276  << ", maxSleep="<<maxSleep<<endl;
277 
278 
279  HugoOperations hugoOps(*ctx->getTab());
280  Ndb* pNdb = GETNDB(step);
281 
282  for (int l = 0; l < loops && result == NDBT_OK; l++){
283 
284  do{
285  // Commit transaction
286  CHECK(hugoOps.startTransaction(pNdb) == 0);
287  CHECK(hugoOps.pkReadRecord(pNdb, stepNo) == 0);
288  CHECK(hugoOps.execute_NoCommit(pNdb) == 0);
289 
290  int sleep = myRandom48(maxSleep);
291  ndbout << "Sleeping for " << sleep << " milliseconds" << endl;
292  NdbSleep_MilliSleep(sleep);
293 
294  // Expect that transaction has NOT timed-out
295  CHECK(hugoOps.execute_Commit(pNdb) == 0);
296 
297  } while(false);
298 
299  hugoOps.closeTransaction(pNdb);
300  }
301 
302  return result;
303 }
304 
305 int runDeadlockTimeoutTrans(NDBT_Context* ctx, NDBT_Step* step){
306  int result = NDBT_OK;
307  int loops = ctx->getNumLoops();
308  int stepNo = step->getStepNo();
309 
310  Uint32 deadlock_timeout;
311  NdbConfig conf(GETNDB(step)->getNodeId()+1);
312  unsigned int nodeId = conf.getMasterNodeId();
313  if (!conf.getProperty(nodeId,
314  NODE_TYPE_DB,
315  CFG_DB_TRANSACTION_DEADLOCK_TIMEOUT,
316  &deadlock_timeout)){
317  return NDBT_FAILED;
318  }
319 
320 
321  int do_sleep = (int)(deadlock_timeout * 0.5);
322 
323 
324  HugoOperations hugoOps(*ctx->getTab());
325  Ndb* pNdb = GETNDB(step);
326 
327  for (int l = 0; l < loops && result == NDBT_OK; l++){
328 
329  do{
330  // Commit transaction
331  CHECK(hugoOps.startTransaction(pNdb) == 0);
332  CHECK(hugoOps.pkReadRecord(pNdb, stepNo) == 0);
333  CHECK(hugoOps.execute_NoCommit(pNdb) == 0);
334 
335  int sleep = int(deadlock_timeout * 1.5 + myRandom48(do_sleep));
336  ndbout << "Sleeping for " << sleep << " milliseconds" << endl;
337  NdbSleep_MilliSleep(sleep);
338 
339  // Expect that transaction has NOT timed-out
340  CHECK(hugoOps.execute_Commit(pNdb) == 0);
341 
342  } while(false);
343 
344  hugoOps.closeTransaction(pNdb);
345  }
346 
347  return result;
348 }
349 
350 int runBuddyTransNoTimeout(NDBT_Context* ctx, NDBT_Step* step){
351  int result = NDBT_OK;
352  int loops = ctx->getNumLoops();
353  int records = ctx->getNumRecords();
354  int stepNo = step->getStepNo();
355  int maxSleep = (int)(TIMEOUT * 0.3);
356  ndbout << "TransactionInactiveTimeout="<< TIMEOUT
357  << ", maxSleep="<<maxSleep<<endl;
358 
359  HugoOperations hugoOps(*ctx->getTab());
360  Ndb* pNdb = GETNDB(step);
361 
362  for (int l = 1; l < loops && result == NDBT_OK; l++){
363 
364  do{
365  // Start an insert trans
366  CHECK(hugoOps.startTransaction(pNdb) == 0);
367  int recordNo = records + (stepNo*loops) + l;
368  CHECK(hugoOps.pkInsertRecord(pNdb, recordNo) == 0);
369  CHECK(hugoOps.execute_NoCommit(pNdb) == 0);
370 
371  int remain = maxSleep;
372  for (int i = 0; i < 3; i++)
373  {
374  NdbTransaction* pTrans = hugoOps.getTransaction();
375 
376  // Perform buddy scan reads
377  NdbScanOperation* pOp = pTrans->getNdbScanOperation(ctx->getTab());
378  CHECK(pOp != 0);
379  CHECK(pOp->readTuples(NdbOperation::LM_Read, 0, 0, 1) == 0);
380  CHECK(pTrans->execute(NoCommit) == 0);
381  while(pOp->nextResult() == 0);
382 
383  int sleep = myRandom48(remain);
384  remain = remain - sleep + 1;
385  ndbout << "Sleeping for " << sleep << " milliseconds" << endl;
386  NdbSleep_MilliSleep(sleep);
387  }
388 
389  // Expect that transaction has NOT timed-out
390  CHECK(hugoOps.execute_Commit(pNdb) == 0);
391 
392  } while(false);
393 
394  hugoOps.closeTransaction(pNdb);
395  }
396 
397  return result;
398 }
399 
400 int runBuddyTransTimeout(NDBT_Context* ctx, NDBT_Step* step){
401  int result = NDBT_OK;
402  int loops = ctx->getNumLoops();
403  //int records = ctx->getNumRecords();
404  //int stepNo = step->getStepNo();
405  ndbout << "TransactionInactiveTimeout="<< TIMEOUT <<endl;
406 
407  HugoOperations hugoOps(*ctx->getTab());
408  Ndb* pNdb = GETNDB(step);
409 
410  for (int l = 1; l < loops && result == NDBT_OK; l++){
411 
412  NdbTransaction* pTrans = 0;
413  do{
414  pTrans = pNdb->startTransaction();
415  NdbScanOperation* pOp = pTrans->getNdbScanOperation(ctx->getTab());
416  CHECK(pOp->readTuples(NdbOperation::LM_Read, 0, 0, 1) == 0);
417  CHECK(pTrans->execute(NoCommit) == 0);
418 
419  int sleep = 2 * TIMEOUT;
420  ndbout << "Sleeping for " << sleep << " milliseconds" << endl;
421  NdbSleep_MilliSleep(sleep);
422 
423  int res = 0;
424  while((res = pOp->nextResult()) == 0);
425  ndbout_c("res: %d", res);
426  CHECK(res == -1);
427 
428  } while(false);
429 
430  if (pTrans)
431  {
432  pTrans->close();
433  }
434  }
435 
436  return result;
437 }
438 
439 int runScanRefreshNoTimeout(NDBT_Context* ctx, NDBT_Step* step){
440  int result = NDBT_OK;
441  int loops = ctx->getNumLoops();
442  int records = ctx->getNumRecords();
443  int stepNo = step->getStepNo();
444  int maxSleep = (int)(TIMEOUT * 0.3);
445  ndbout << "TransactionInactiveTimeout="<< TIMEOUT
446  << ", maxSleep="<<maxSleep<<endl;
447 
448  HugoOperations hugoOps(*ctx->getTab());
449  Ndb* pNdb = GETNDB(step);
450 
451  for (int l = 1; l < loops && result == NDBT_OK; l++){
452 
453  do{
454  // Start an insert trans
455  CHECK(hugoOps.startTransaction(pNdb) == 0);
456  int recordNo = records + (stepNo*loops) + l;
457  CHECK(hugoOps.pkInsertRecord(pNdb, recordNo) == 0);
458  CHECK(hugoOps.execute_NoCommit(pNdb) == 0);
459 
460  for (int i = 0; i < 3; i++)
461  {
462  NdbTransaction* pTrans = hugoOps.getTransaction();
463 
465  for (int j = 0; j <= i; j++)
466  {
467  // Perform buddy scan reads
468  NdbScanOperation* pOp = pTrans->getNdbScanOperation(ctx->getTab());
469  CHECK(pOp != 0);
470  CHECK(pOp->readTuples(NdbOperation::LM_Read, 0, 0, 1) == 0);
471  ops.push_back(pOp);
472  }
473  CHECK(pTrans->execute(NoCommit) == 0);
474 
475  for (unsigned i = 0; i<TIMEOUT; i += 1000)
476  {
477  pTrans->refresh();
478  NdbSleep_MilliSleep(1000);
479  }
480 
481  int res;
482  for (size_t j = 0; j < ops.size(); j++)
483  {
484  while((res = ops[j]->nextResult()) == 0);
485  CHECK(res != -1);
486  }
487  }
488 
489  // Expect that transaction has NOT timed-out
490  CHECK(hugoOps.execute_Commit(pNdb) == 0);
491 
492  } while(false);
493 
494  hugoOps.closeTransaction(pNdb);
495  }
496 
497  return result;
498 }
499 
500 int
501 runError4012(NDBT_Context* ctx, NDBT_Step* step){
502  int result = NDBT_OK;
503  //int loops = ctx->getNumLoops();
504  //int stepNo = step->getStepNo();
505 
506  int timeout = ctx->getProperty("TransactionDeadlockTimeout", TIMEOUT);
507 
508  HugoOperations hugoOps(*ctx->getTab());
509  Ndb* pNdb = GETNDB(step);
510 
511  do{
512  // Commit transaction
513  CHECK(hugoOps.startTransaction(pNdb) == 0);
514  CHECK(hugoOps.pkUpdateRecord(pNdb, 0) == 0);
515  int ret = hugoOps.execute_NoCommit(pNdb);
516  if (ret == 0)
517  {
518  int sleep = timeout;
519  ndbout << "Sleeping for " << sleep << " milliseconds" << endl;
520  NdbSleep_MilliSleep(sleep);
521 
522  // Expect that transaction has NOT timed-out
523  CHECK(hugoOps.execute_Commit(pNdb) == 0);
524  }
525  else
526  {
527  CHECK(ret == 4012);
528  }
529  } while(false);
530 
531  hugoOps.closeTransaction(pNdb);
532 
533  return result;
534 }
535 
536 
537 NDBT_TESTSUITE(testTimeout);
538 TESTCASE("DontTimeoutTransaction",
539  "Test that the transaction does not timeout "\
540  "if we sleep during the transaction. Use a sleep "\
541  "value which is smaller than TransactionInactiveTimeout"){
542  INITIALIZER(runLoadTable);
543  INITIALIZER(setTransactionTimeout);
544  STEPS(runDontTimeoutTrans, 1);
545  FINALIZER(resetTransactionTimeout);
546  FINALIZER(runClearTable);
547 }
548 TESTCASE("Bug11290",
549  "Setting TransactionInactiveTimeout to 0(zero) "\
550  "should result in infinite timeout, and not as "\
551  "was the bug, a timeout that is equal to the deadlock timeout"){
552  TC_PROPERTY("TransactionInactiveTimeout",(Uint32)0);
553  INITIALIZER(runLoadTable);
554  INITIALIZER(setTransactionTimeout);
555  STEPS(runDeadlockTimeoutTrans, 1);
556  FINALIZER(resetTransactionTimeout);
557  FINALIZER(runClearTable);
558 }
559 TESTCASE("DontTimeoutTransaction5",
560  "Test that the transaction does not timeout "\
561  "if we sleep during the transaction. Use a sleep "\
562  "value which is smaller than TransactionInactiveTimeout" \
563  "Five simultaneous threads"){
564  INITIALIZER(runLoadTable);
565  INITIALIZER(setTransactionTimeout);
566  STEPS(runDontTimeoutTrans, 5);
567  FINALIZER(resetTransactionTimeout);
568  FINALIZER(runClearTable);
569 }
570 TESTCASE("TimeoutRandTransaction",
571  "Test that the transaction does timeout "\
572  "if we sleep during the transaction. Use a sleep "\
573  "value which is larger than TransactionInactiveTimeout"){
574  INITIALIZER(runLoadTable);
575  INITIALIZER(setTransactionTimeout);
576  TC_PROPERTY("Op1", 7);
577  TC_PROPERTY("Op2", 11);
578  STEPS(runTimeoutTrans2, 5);
579  FINALIZER(resetTransactionTimeout);
580  FINALIZER(runClearTable);
581 }
582 TESTCASE("BuddyTransNoTimeout",
583  "Start a transaction and perform an insert with NoCommit. " \
584  "Start a buddy transaction wich performs long running scans " \
585  "and sleeps. " \
586  "The total sleep time is longer than TransactionInactiveTimeout" \
587  "Commit the first transaction, it should not have timed out."){
588  INITIALIZER(runLoadTable);
589  INITIALIZER(setTransactionTimeout);
590  STEPS(runBuddyTransNoTimeout, 1);
591  FINALIZER(resetTransactionTimeout);
592  FINALIZER(runClearTable);
593 }
594 TESTCASE("BuddyTransNoTimeout5",
595  "Start a transaction and perform an insert with NoCommit. " \
596  "Start a buddy transaction wich performs long running scans " \
597  "and sleeps. " \
598  "The total sleep time is longer than TransactionInactiveTimeout" \
599  "Commit the first transaction, it should not have timed out." \
600  "Five simultaneous threads"){
601  INITIALIZER(runLoadTable);
602  INITIALIZER(setTransactionTimeout);
603  STEPS(runBuddyTransNoTimeout, 5);
604  FINALIZER(resetTransactionTimeout);
605  FINALIZER(runClearTable);
606 }
607 TESTCASE("BuddyTransTimeout1",
608  "Start a scan and check that it gets aborted"){
609  INITIALIZER(runLoadTable);
610  INITIALIZER(setTransactionTimeout);
611  STEPS(runBuddyTransTimeout, 1);
612  FINALIZER(resetTransactionTimeout);
613  FINALIZER(runClearTable);
614 }
615 TESTCASE("ScanRefreshNoTimeout",
616  "")
617 {
618  INITIALIZER(runLoadTable);
619  INITIALIZER(setTransactionTimeout);
620  STEPS(runScanRefreshNoTimeout, 1);
621  FINALIZER(resetTransactionTimeout);
622  FINALIZER(runClearTable);
623 }
624 #if 0
625 TESTCASE("Error4012", ""){
626  TC_PROPERTY("TransactionDeadlockTimeout", 120000);
627  INITIALIZER(runLoadTable);
628  INITIALIZER(getDeadlockTimeout);
629  INITIALIZER(setDeadlockTimeout);
630  STEPS(runError4012, 2);
631  FINALIZER(runClearTable);
632 }
633 #endif
634 NDBT_TESTSUITE_END(testTimeout);
635 
636 int main(int argc, const char** argv){
637  ndb_init();
638  myRandom48Init((long)NdbTick_CurrentMillisecond());
639  NDBT_TESTSUITE_INSTANCE(testTimeout);
640  return testTimeout.execute(argc, argv);
641 }
642 
643 template class Vector<NdbScanOperation*>;