MySQL 5.6.14 Source Code Document
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
testTransactions.cpp
1 /*
2  Copyright (C) 2003-2006 MySQL AB, 2008, 2009 Sun Microsystems, Inc.
3  All rights reserved. Use is subject to license terms.
4 
5  This program is free software; you can redistribute it and/or modify
6  it under the terms of the GNU General Public License as published by
7  the Free Software Foundation; version 2 of the License.
8 
9  This program is distributed in the hope that it will be useful,
10  but WITHOUT ANY WARRANTY; without even the implied warranty of
11  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12  GNU General Public License for more details.
13 
14  You should have received a copy of the GNU General Public License
15  along with this program; if not, write to the Free Software
16  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
17 */
18 
19 #include <NDBT_Test.hpp>
20 #include <NDBT_ReturnCodes.h>
21 #include <HugoTransactions.hpp>
22 #include <UtilTransactions.hpp>
23 #include <NdbRestarter.hpp>
24 #include <signaldata/DumpStateOrd.hpp>
25 
26 struct OperationTestCase {
27  const char * name;
28  bool preCond; // start transaction | insert | commit
29 
30  // start transaction 1
31  const char * op1;
32  const int val1;
33 
34  // no commit
35 
36  // start transaction 2
37  const char * op2;
38  const int res2;
39  const int val2;
40  // no commit
41 
42  // commit transaction 1
43  // commit transaction 2
44 
45  // start transaction
46  // op3 = READ
47  const int res3;
48  const int val3;
49  // commit transaction
50 };
51 
52 #define X -1
53 
65 OperationTestCase matrix[] = {
66  { "ReadRead", true, "READ", 1, "READ", 0, 1, 0, 1 },
67  { "ReadReadEx", true, "READ", 1, "READ-EX", 266, X, 0, 1 },
68  { "ReadSimpleRead", true, "READ", 1, "S-READ", 0, 1, 0, 1 },
69  { "ReadDirtyRead", true, "READ", 1, "D-READ", 0, 1, 0, 1 },
70  { "ReadInsert", true, "READ", 1, "INSERT", 266, X, 0, 1 },
71  { "ReadUpdate", true, "READ", 1, "UPDATE", 266, X, 0, 1 },
72  { "ReadDelete", true, "READ", 1, "DELETE", 266, X, 0, 1 },
73  { "ReadScan", true, "READ", 1, "SCAN", 0, 1, 0, 1 },
74  { "ReadScanHl", true, "READ", 1, "SCAN-HL", 0, 1, 0, 1 },
75  { "ReadScanEx", true, "READ", 1, "SCAN-EX", 274, X, 0, 1 },
76 #if 0
77  { "ReadScanUp", true, "READ", 1, "SCAN-UP", 266, X, 0, 1 },
78  { "ReadScanDe", true, "READ", 1, "SCAN-DE", 266, X, 0, 1 },
79 #endif
80 
81  { "ScanRead", true, "SCAN", 1, "READ", 0, 1, 0, 1 },
82  { "ScanReadEx", true, "SCAN", 1, "READ-EX", 0, 1, 0, 1 },
83  { "ScanSimpleRead", true, "SCAN", 1, "S-READ", 0, 1, 0, 1 },
84  { "ScanDirtyRead", true, "SCAN", 1, "D-READ", 0, 1, 0, 1 },
85  { "ScanInsert", true, "SCAN", 1, "INSERT", 630, X, 0, 1 },
86  { "ScanUpdate", true, "SCAN", 1, "UPDATE", 0, 2, 0, 2 },
87  { "ScanDelete", true, "SCAN", 1, "DELETE", 0, X, 626, X },
88  { "ScanScan", true, "SCAN", 1, "SCAN", 0, 1, 0, 1 },
89  { "ScanScanHl", true, "SCAN", 1, "SCAN-HL", 0, 1, 0, 1 },
90  { "ScanScanEx", true, "SCAN", 1, "SCAN-EX", 0, 1, 0, 1 },
91 #if 0
92  { "ScanScanUp", true, "SCAN", 1, "SCAN-UP", 266, X, 0, 1 },
93  { "ScanScanDe", true, "SCAN", 1, "SCAN-DE", 266, X, 0, 1 },
94 #endif
95 
96  { "ScanHlRead", true, "SCAN-HL",1, "READ", 0, 1, 0, 1 },
97  { "ScanHlReadEx", true, "SCAN-HL",1, "READ-EX", 266, 1, 0, 1 },
98  { "ScanHlSimpleRead", true, "SCAN-HL",1, "S-READ", 0, 1, 0, 1 },
99  { "ScanHlDirtyRead", true, "SCAN-HL",1, "D-READ", 0, 1, 0, 1 },
100  { "ScanHlInsert", true, "SCAN-HL",1, "INSERT", 266, X, 0, 1 },
101  { "ScanHlUpdate", true, "SCAN-HL",1, "UPDATE", 266, 2, 0, 1 },
102  { "ScanHlDelete", true, "SCAN-HL",1, "DELETE", 266, X, 0, 1 },
103  { "ScanHlScan", true, "SCAN-HL",1, "SCAN", 0, 1, 0, 1 },
104  { "ScanHlScanHl", true, "SCAN-HL",1, "SCAN-HL", 0, 1, 0, 1 },
105  { "ScanHlScanEx", true, "SCAN-HL",1, "SCAN-EX", 274, X, 0, 1 },
106 #if 0
107  { "ScanHlScanUp", true, "SCAN-HL",1, "SCAN-UP", 266, X, 0, 1 },
108  { "ScanHlScanDe", true, "SCAN-HL",1, "SCAN-DE", 266, X, 0, 1 },
109 #endif
110 
111  { "ScanExRead", true, "SCAN-EX",1, "READ", 266, 1, 0, 1 },
112  { "ScanExReadEx", true, "SCAN-EX",1, "READ-EX", 266, 1, 0, 1 },
113 //XX1 { "ScanExSimpleRead", true, "SCAN-EX",1, "S-READ", 266, 1, 0, 1 },
114  { "ScanExDirtyRead", true, "SCAN-EX",1, "D-READ", 0, 1, 0, 1 },
115  { "ScanExInsert", true, "SCAN-EX",1, "INSERT", 266, X, 0, 1 },
116  { "ScanExUpdate", true, "SCAN-EX",1, "UPDATE", 266, 2, 0, 1 },
117  { "ScanExDelete", true, "SCAN-EX",1, "DELETE", 266, X, 0, 1 },
118  { "ScanExScan", true, "SCAN-EX",1, "SCAN", 0, 1, 0, 1 },
119  { "ScanExScanHl", true, "SCAN-EX",1, "SCAN-HL", 274, X, 0, 1 },
120  { "ScanExScanEx", true, "SCAN-EX",1, "SCAN-EX", 274, X, 0, 1 },
121 #if 0
122  { "ScanExScanUp", true, "SCAN-EX",1, "SCAN-UP", 266, X, 0, 1 },
123  { "ScanExScanDe", true, "SCAN-EX",1, "SCAN-DE", 266, X, 0, 1 },
124 #endif
125 
126  { "SimpleReadRead", true, "S-READ", 1, "READ", 0, 1, 0, 1 },
127  { "SimpleReadReadEx", true, "S-READ", 1, "READ-EX", 0, 1, 0, 1 }, // no lock held
128  { "SimpleReadSimpleRead",
129  true, "S-READ", 1, "S-READ", 0, 1, 0, 1 },
130  { "SimpleReadDirtyRead",
131  true, "S-READ", 1, "D-READ", 0, 1, 0, 1 },
132  { "SimpleReadInsert", true, "S-READ", 1, "INSERT", 630, X, 0, 1 }, // no lock held
133  { "SimpleReadUpdate", true, "S-READ", 1, "UPDATE", 0, 2, 0, 2 }, // no lock held
134  { "SimpleReadDelete", true, "S-READ", 1, "DELETE", 0, X, 626, X }, // no lock held
135  { "SimpleReadScan", true, "S-READ", 1, "SCAN", 0, 1, 0, 1 },
136  { "SimpleReadScanHl", true, "S-READ", 1, "SCAN-HL", 0, 1, 0, 1 },
137  { "SimpleReadScanEx", true, "S-READ", 1, "SCAN-EX", 0, 1, 0, 1 }, // no lock held
138 #if 0
139  { "SimpleReadScanUp", true, "S-READ", 1, "SCAN-UP", 0, 1, 0, 2 }, // no lock held
140  { "SimpleReadScanDe", true, "S-READ", 1, "SCAN-DE", 0, X, 626, X }, // no lock held
141 #endif
142 
143  { "ReadExRead", true, "READ-EX",1, "READ", 266, X, 0, 1 },
144  { "ReadExReadEx", true, "READ-EX",1, "READ-EX", 266, X, 0, 1 },
145 //XX1 { "ReadExSimpleRead", true, "READ-EX",1, "S-READ", 266, X, 0, 1 },
146  { "ReadExDirtyRead", true, "READ-EX",1, "D-READ", 0, 1, 0, 1 },
147  { "ReadExInsert", true, "READ-EX",1, "INSERT", 266, X, 0, 1 },
148  { "ReadExUpdate", true, "READ-EX",1, "UPDATE", 266, X, 0, 1 },
149  { "ReadExDelete", true, "READ-EX",1, "DELETE", 266, X, 0, 1 },
150  { "ReadExScan", true, "READ-EX",1, "SCAN", 0, 1, 0, 1 },
151  { "ReadExScanHl", true, "READ-EX",1, "SCAN-HL", 274, X, 0, 1 },
152  { "ReadExScanEx", true, "READ-EX",1, "SCAN-EX", 274, X, 0, 1 },
153 #if 0
154  { "ReadExScanUp", true, "READ-EX",1, "SCAN-UP", 266, X, 0, 1 },
155  { "ReadExScanDe", true, "READ-EX",1, "SCAN-DE", 266, X, 0, 1 },
156 #endif
157 
158  { "InsertRead", false, "INSERT", 1, "READ", 266, X, 0, 1 },
159  { "InsertReadEx", false, "INSERT", 1, "READ-EX", 266, X, 0, 1 },
160  { "InsertSimpleRead",false, "INSERT", 1, "S-READ", 266, X, 0, 1 },
161  { "InsertDirtyRead", false, "INSERT", 1, "D-READ", 626, X, 0, 1 },
162  { "InsertInsert", false, "INSERT", 1, "INSERT", 266, X, 0, 1 },
163  { "InsertUpdate", false, "INSERT", 1, "UPDATE", 266, X, 0, 1 },
164  { "InsertDelete", false, "INSERT", 1, "DELETE", 266, X, 0, 1 },
165  { "InsertScan", false, "INSERT", 1, "SCAN", 626, X, 0, 1 },
166  { "InsertScanHl", false, "INSERT", 1, "SCAN-HL", 274, X, 0, 1 },
167  { "InsertScanEx", false, "INSERT", 1, "SCAN-EX", 274, X, 0, 1 },
168 #if 0
169  { "InsertScanUp", false, "INSERT", 1, "SCAN-UP", 266, X, 0, 1 },
170  { "InsertScanDe", false, "INSERT", 1, "SCAN-DE", 266, X, 0, 1 },
171 #endif
172 
173  { "UpdateRead", true, "UPDATE", 2, "READ", 266, X, 0, 2 },
174  { "UpdateReadEx", true, "UPDATE", 2, "READ-EX", 266, X, 0, 2 },
175  { "UpdateSimpleRead", true, "UPDATE", 2, "S-READ", 266, X, 0, 2 },
176  { "UpdateDirtyRead", true, "UPDATE", 2, "D-READ", 0, 1, 0, 2 },
177  { "UpdateInsert", true, "UPDATE", 2, "INSERT", 266, X, 0, 2 },
178  { "UpdateUpdate", true, "UPDATE", 2, "UPDATE", 266, X, 0, 2 },
179  { "UpdateDelete", true, "UPDATE", 2, "DELETE", 266, X, 0, 2 },
180  { "UpdateScan", true, "UPDATE", 2, "SCAN", 0, 1, 0, 2 },
181  { "UpdateScanHl", true, "UPDATE", 2, "SCAN-HL", 274, X, 0, 2 },
182  { "UpdateScanEx", true, "UPDATE", 2, "SCAN-EX", 274, X, 0, 2 },
183 #if 0
184  { "UpdateScanUp", true, "UPDATE", 2, "SCAN-UP", 266, X, 0, 2 },
185  { "UpdateScanDe", true, "UPDATE", 2, "SCAN-DE", 266, X, 0, 2 },
186 #endif
187 
188  { "DeleteRead", true, "DELETE", X, "READ", 266, X, 626, X },
189  { "DeleteReadEx", true, "DELETE", X, "READ-EX", 266, X, 626, X },
190  { "DeleteSimpleRead", true, "DELETE", X, "S-READ", 266, X, 626, X },
191  { "DeleteDirtyRead", true, "DELETE", X, "D-READ", 0, 1, 626, X },
192  { "DeleteInsert", true, "DELETE", X, "INSERT", 266, X, 626, X },
193  { "DeleteUpdate", true, "DELETE", X, "UPDATE", 266, X, 626, X },
194  { "DeleteDelete", true, "DELETE", X, "DELETE", 266, X, 626, X },
195  { "DeleteScan", true, "DELETE", X, "SCAN", 0, 1, 626, X },
196  { "DeleteScanHl", true, "DELETE", X, "SCAN-HL", 274, X, 626, X },
197  { "DeleteScanEx", true, "DELETE", X, "SCAN-EX", 274, X, 626, X },
198 #if 0
199  { "DeleteScanUp", true, "DELETE", X, "SCAN-UP", 266, X, 626, X },
200  { "DeleteScanDe", true, "DELETE", X, "SCAN-DE", 266, X, 626, X }
201 #endif
202 
203 
204 
205 
206 };
207 
208 #define CHECK(a, b) { int x = a; int y = b; if (x != y) { \
209  g_err << "ERR: "<< step->getName() \
210  << " failed on line " << __LINE__ << endl << " " \
211  << x << " != " << y << endl;\
212  result = NDBT_FAILED; \
213  break; } }
214 
215 int
216 runOp(HugoOperations & hugoOps,
217  Ndb * pNdb,
218  const char * op,
219  int value){
220 
221 #define C2(x) if(!(x)) {\
222  g_err << "ERR: failed on line " << __LINE__ << endl; \
223  return NDBT_FAILED; }
224 
225  if(strcmp(op, "READ") == 0){
226  C2(hugoOps.pkReadRecord(pNdb, 1, 1, NdbOperation::LM_Read) == 0);
227  } else if(strcmp(op, "READ-EX") == 0){
228  C2(hugoOps.pkReadRecord(pNdb, 1, 1, NdbOperation::LM_Exclusive) == 0);
229  } else if(strcmp(op, "S-READ") == 0){
230  C2(hugoOps.pkReadRecord(pNdb, 1, 1, NdbOperation::LM_SimpleRead) == 0);
231  } else if(strcmp(op, "D-READ") == 0){
232  C2(hugoOps.pkReadRecord(pNdb, 1, 1, NdbOperation::LM_CommittedRead) == 0);
233  } else if(strcmp(op, "INSERT") == 0){
234  C2(hugoOps.pkInsertRecord(pNdb, 1, 1, value) == 0);
235  } else if(strcmp(op, "UPDATE") == 0){
236  C2(hugoOps.pkUpdateRecord(pNdb, 1, 1, value) == 0);
237  } else if(strcmp(op, "DELETE") == 0){
238  C2(hugoOps.pkDeleteRecord(pNdb, 1, 1) == 0);
239  } else if(strcmp(op, "SCAN") == 0){
240  C2(hugoOps.scanReadRecords(pNdb) == 0);
241  } else if(strcmp(op, "SCAN-HL") == 0){
242  C2(hugoOps.scanReadRecords(pNdb, NdbScanOperation::LM_Read)== 0);
243  } else if(strcmp(op, "SCAN-EX") == 0){
244  C2(hugoOps.scanReadRecords(pNdb, NdbScanOperation::LM_Exclusive)== 0);
245  } else {
246  g_err << __FILE__ << " - " << __LINE__
247  << ": Unknown operation" << op << endl;
248  return NDBT_FAILED;
249  }
250 
251  return NDBT_OK;
252 }
253 
254 int
255 checkVal(HugoOperations & hugoOps,
256  const char * op,
257  int value,
258  int result){
259 
260  if(result != 0)
261  return NDBT_OK;
262 
263  if(strcmp(op, "READ") == 0){
264  } else if(strcmp(op, "READ-EX") == 0){
265  } else if(strcmp(op, "S-READ") == 0){
266  } else if(strcmp(op, "D-READ") == 0){
267  } else if(strcmp(op, "SCAN") == 0){
268  } else if(strcmp(op, "SCAN-HL") == 0){
269  } else if(strcmp(op, "SCAN-EX") == 0){
270  } else {
271  return NDBT_OK;
272  }
273 
274  return hugoOps.verifyUpdatesValue(value);
275 }
276 
277 #define TIMEOUT 100
278 
279 int
280 setTransactionTimeout(NDBT_Context* ctx, NDBT_Step* step){
281  NdbRestarter restarter;
282 
283  int val[] =
284  { DumpStateOrd::TcSetTransactionTimeout, TIMEOUT };
285  if(restarter.dumpStateAllNodes(val, 2) != 0){
286  return NDBT_FAILED;
287  }
288 
289  return NDBT_OK;
290 }
291 
292 int
293 runTwoTrans1(NDBT_Context* ctx, NDBT_Step* step){
294  int result = NDBT_OK;
295  HugoOperations T1(*ctx->getTab());
296  Ndb* pNdb = GETNDB(step);
297 
298  const char * op1 = ctx->getProperty("op1", "NONE");
299  int val1 = ctx->getProperty("val1", ~0);
300 
301  do {
302  // Insert, read
303  CHECK(T1.startTransaction(pNdb), 0);
304  CHECK(runOp(T1, pNdb, op1, val1), 0);
305  CHECK(T1.execute_NoCommit(pNdb), 0);
306  CHECK(checkVal(T1, op1, val1, 0), 0);
307 
308  ctx->setProperty("T1-1-Complete", 1);
309  while(ctx->getProperty("T2-Complete", (Uint32)0) == 0){
310  T1.refresh();
311  NdbSleep_MilliSleep(10);
312  }
313 
314  CHECK(T1.execute_Commit(pNdb), 0);
315 
316  } while(false);
317  T1.closeTransaction(pNdb);
318 
319  if(result != NDBT_OK)
320  return result;
321 
322  const int res3 = ctx->getProperty("res3", ~0);
323  const int val3 = ctx->getProperty("val3", ~0);
324 
325  do {
326  CHECK(T1.startTransaction(pNdb), 0);
327  CHECK(runOp(T1, pNdb, "READ", 0), 0);
328  CHECK(T1.execute_Commit(pNdb), res3);
329  CHECK(checkVal(T1, "READ", val3, res3), 0);
330  } while(false);
331  T1.closeTransaction(pNdb);
332 
333  return result;
334 }
335 
336 int
337 runTwoTrans2(NDBT_Context* ctx, NDBT_Step* step){
338  int result = NDBT_OK;
339  HugoOperations T2(*ctx->getTab());
340  Ndb* pNdb = GETNDB(step);
341 
342  const char * op2 = ctx->getProperty("op2", "NONE");
343  const int res2 = ctx->getProperty("res2", ~0);
344  const int val2 = ctx->getProperty("val2", ~0);
345 
346  while(ctx->getProperty("T1-1-Complete", (Uint32)0) == 0 &&
347  !ctx->isTestStopped()){
348  NdbSleep_MilliSleep(100);
349  }
350 
351  if(!ctx->isTestStopped()){
352  do {
353  CHECK(T2.startTransaction(pNdb), 0);
354  CHECK(runOp(T2, pNdb, op2, val2), 0);
355  CHECK(T2.execute_NoCommit(pNdb), res2);
356  CHECK(checkVal(T2, op2, val2, res2), 0);
357  if(res2 == 0){
358  CHECK(T2.execute_Commit(pNdb), res2);
359  }
360  } while(false);
361  T2.closeTransaction(pNdb);
362  }
363 
364  ctx->setProperty("T2-Complete", 1);
365 
366  return result;
367 }
368 
369 int
370 runInsertRecord(NDBT_Context* ctx, NDBT_Step* step){
371  int result = NDBT_OK;
372  HugoOperations hugoOps(*ctx->getTab());
373  Ndb* pNdb = GETNDB(step);
374 
375  do{
376  // Insert, insert
377  CHECK(hugoOps.startTransaction(pNdb), 0);
378  CHECK(hugoOps.pkInsertRecord(pNdb, 1, 1, 1), 0);
379  CHECK(hugoOps.execute_Commit(pNdb), 0);
380  } while(false);
381 
382  hugoOps.closeTransaction(pNdb);
383 
384  return result;
385 }
386 
387 int
388 runClearTable(NDBT_Context* ctx, NDBT_Step* step){
389  int records = ctx->getNumRecords();
390 
391  UtilTransactions utilTrans(*ctx->getTab());
392  if (utilTrans.clearTable2(GETNDB(step), records, 240) != 0){
393  return NDBT_FAILED;
394  }
395 
396  NdbRestarter r;
397  int lcp = 7099;
398  r.dumpStateAllNodes(&lcp, 1);
399 
400  return NDBT_OK;
401 }
402 
403 int
404 main(int argc, const char** argv){
405  ndb_init();
406 
407  NDBT_TestSuite ts("testOperations");
408  ts.setTemporaryTables(true);
409 
410  for(Uint32 i = 0; i<sizeof(matrix)/sizeof(matrix[0]); i++){
411  NDBT_TestCaseImpl1 *pt = new NDBT_TestCaseImpl1(&ts, matrix[i].name, "");
412 
413  pt->addInitializer(new NDBT_Initializer(pt,
414  "runClearTable",
415  runClearTable));
416 
417  if(matrix[i].preCond){
418  pt->addInitializer(new NDBT_Initializer(pt,
419  "runInsertRecord",
420  runInsertRecord));
421  }
422 
423  pt->addInitializer(new NDBT_Initializer(pt,
424  "setTransactionTimeout",
425  setTransactionTimeout));
426 
427  pt->setProperty("op1", matrix[i].op1);
428  pt->setProperty("val1", matrix[i].val1);
429 
430  pt->setProperty("op2", matrix[i].op2);
431  pt->setProperty("res2", matrix[i].res2);
432  pt->setProperty("val2", matrix[i].val2);
433 
434  pt->setProperty("res3", matrix[i].res3);
435  pt->setProperty("val3", matrix[i].val3);
436 
437  pt->addStep(new NDBT_ParallelStep(pt,
438  matrix[i].name,
439  runTwoTrans1));
440  pt->addStep(new NDBT_ParallelStep(pt,
441  matrix[i].name,
442  runTwoTrans2));
443  pt->addFinalizer(new NDBT_Finalizer(pt,
444  "runClearTable",
445  runClearTable));
446 
447  ts.addTest(pt);
448  }
449 
450  return ts.execute(argc, argv);
451 }
452