MySQL 5.6.14 Source Code Document
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
testOperations.cpp
1 /*
2  Copyright (C) 2003-2007 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 
26  const char * name;
27  bool preCond; // start transaction | insert | commit
28 
29  // start transaction
30  const char * op1;
31  const int res1;
32  const int val1;
33 
34  // no commit
35 
36  const char * op2;
37  const int res2;
38  const int val2;
39  // Commit
40 
41  // start transaction
42  // op3 = READ
43  const int res3;
44  const int val3;
45  // commit transaction
46 };
47 
48 OperationTestCase matrix[] = {
49  { "ReadRead", true, "READ", 0, 0, "READ", 0, 0, 0, 0 },
50  { "ReadReadEx", true, "READ", 0, 0, "READ-EX", 0, 0, 0, 0 },
51  { "ReadSimpleRead", true, "READ", 0, 0, "S-READ", 0, 0, 0, 0 },
52  { "ReadDirtyRead", true, "READ", 0, 0, "D-READ", 0, 0, 0, 0 },
53  { "ReadInsert", true, "READ", 0, 0, "INSERT", 630, 1, 0, 0 },
54  { "ReadUpdate", true, "READ", 0, 0, "UPDATE", 0, 1, 0, 1 },
55  { "ReadDelete", true, "READ", 0, 0, "DELETE", 0, 0, 626, 0 },
56 
57  { "FReadRead", false, "READ", 626, 0, "READ", 626, 0, 626, 0 },
58  { "FReadReadEx", false, "READ", 626, 0, "READ-EX", 626, 0, 626, 0 },
59  { "FReadSimpleRead", false, "READ", 626, 0, "S-READ", 626, 0, 626, 0 },
60  { "FReadDirtyRead", false, "READ", 626, 0, "D-READ", 626, 0, 626, 0 },
61  { "FReadInsert", false, "READ", 626, 0, "INSERT", 0, 1, 0, 1 },
62  { "FReadUpdate", false, "READ", 626, 0, "UPDATE", 626, 0, 626, 0 },
63  { "FReadDelete", false, "READ", 626, 0, "DELETE", 626, 0, 626, 0 },
64 
65  { "FSimpleReadRead", false, "S-READ", 626, 0, "READ", 626, 0, 626, 0 },
66  { "FSimpleReadReadEx",
67  false, "S-READ", 626, 0, "READ-EX", 626, 0, 626, 0 },
68  { "FSimpleReadSimpleRead",
69  false, "S-READ", 626, 0, "S-READ", 626, 0, 626, 0 },
70  { "FSimpleReadDirtyRead",
71  false, "S-READ", 626, 0, "D-READ", 626, 0, 626, 0 },
72  { "FSimpleReadInsert",
73  false, "S-READ", 626, 0, "INSERT", 0, 1, 0, 1 },
74  { "FSimpleReadUpdate",
75  false, "S-READ", 626, 0, "UPDATE", 626, 0, 626, 0 },
76  { "FSimpleReadDelete",
77  false, "S-READ", 626, 0, "DELETE", 626, 0, 626, 0 },
78 
79  { "ReadExRead", true, "READ-EX", 0, 0, "READ", 0, 0, 0, 0 },
80  { "ReadExReadEx", true, "READ-EX", 0, 0, "READ-EX", 0, 0, 0, 0 },
81  { "ReadExSimpleRead", true, "READ-EX", 0, 0, "S-READ", 0, 0, 0, 0 },
82  { "ReadExDirtyRead", true, "READ-EX", 0, 0, "D-READ", 0, 0, 0, 0 },
83  { "ReadExInsert", true, "READ-EX", 0, 0, "INSERT", 630, 1, 0, 0 },
84  { "ReadExUpdate", true, "READ-EX", 0, 0, "UPDATE", 0, 1, 0, 1 },
85  { "ReadExDelete", true, "READ-EX", 0, 0, "DELETE", 0, 0, 626, 0 },
86 
87  { "InsertRead", false, "INSERT", 0, 0, "READ", 0, 0, 0, 0 },
88  { "InsertReadEx", false, "INSERT", 0, 0, "READ-EX", 0, 0, 0, 0 },
89  { "InsertSimpleRead",false, "INSERT", 0, 0, "S-READ", 0, 0, 0, 0 },
90  { "InsertDirtyRead", false, "INSERT", 0, 0, "D-READ", 0, 0, 0, 0 },
91  { "InsertInsert", false, "INSERT", 0, 0, "INSERT", 630, 0, 626, 0 },
92  { "InsertUpdate", false, "INSERT", 0, 0, "UPDATE", 0, 1, 0, 1 },
93  { "InsertDelete", false, "INSERT", 0, 0, "DELETE", 0, 0, 626, 0 },
94 
95  { "UpdateRead", true, "UPDATE", 0, 1, "READ", 0, 1, 0, 1 },
96  { "UpdateReadEx", true, "UPDATE", 0, 1, "READ-EX", 0, 1, 0, 1 },
97  { "UpdateSimpleRead", true, "UPDATE", 0, 1, "S-READ", 0, 1, 0, 1 },
98  { "UpdateDirtyRead", true, "UPDATE", 0, 1, "D-READ", 0, 1, 0, 1 },
99  { "UpdateInsert", true, "UPDATE", 0, 1, "INSERT", 630, 0, 0, 0 },
100  { "UpdateUpdate", true, "UPDATE", 0, 1, "UPDATE", 0, 2, 0, 2 },
101  { "UpdateDelete", true, "UPDATE", 0, 1, "DELETE", 0, 0, 626, 0 },
102 
103  { "DeleteRead", true, "DELETE", 0, 0, "READ", 626, 0, 0, 0 },
104  { "DeleteReadEx", true, "DELETE", 0, 0, "READ-EX", 626, 0, 0, 0 },
105  { "DeleteSimpleRead", true, "DELETE", 0, 0, "S-READ", 626, 0, 0, 0 },
106  { "DeleteDirtyRead", true, "DELETE", 0, 0, "D-READ", 626, 0, 626, 0 },
107  { "DeleteInsert", true, "DELETE", 0, 0, "INSERT", 0, 1, 0, 1 },
108  { "DeleteUpdate", true, "DELETE", 0, 0, "UPDATE", 626, 1, 0, 0 },
109  { "DeleteDelete", true, "DELETE", 0, 0, "DELETE", 626, 0, 0, 0 }
110 };
111 
112 #define CHECK(b) if (!(b)) { \
113  g_err << "ERR: "<< step->getName() \
114  << " failed on line " << __LINE__ << endl; \
115  result = NDBT_FAILED; \
116  break; }
117 
118 #define C3(b) if (!(b)) { \
119  g_err << "ERR: failed on line " << __LINE__ << endl; \
120  return NDBT_FAILED; }
121 
122 int
123 runOp(HugoOperations & hugoOps,
124  Ndb * pNdb,
125  const char * op,
126  int value){
127 
128 #define C2(x, y) { int r = (x); int s = (y); if(r != s) {\
129  g_err << "ERR: failed on line " << __LINE__ << ": " \
130  << r << " != " << s << endl; \
131  return NDBT_FAILED; }}
132 
133  if(strcmp(op, "READ") == 0){
134  C2(hugoOps.pkReadRecord(pNdb, 1, 1, NdbOperation::LM_Read), 0);
135  } else if(strcmp(op, "READ-EX") == 0){
136  C2(hugoOps.pkReadRecord(pNdb, 1, 1, NdbOperation::LM_Exclusive), 0);
137  } else if(strcmp(op, "S-READ") == 0){
138  C2(hugoOps.pkReadRecord(pNdb, 1, 1, NdbOperation::LM_SimpleRead), 0);
139  } else if(strcmp(op, "D-READ") == 0){
140  C2(hugoOps.pkReadRecord(pNdb, 1, 1, NdbOperation::LM_CommittedRead), 0);
141  } else if(strcmp(op, "INSERT") == 0){
142  C2(hugoOps.pkInsertRecord(pNdb, 1, 1, value), 0);
143  } else if(strcmp(op, "UPDATE") == 0){
144  C2(hugoOps.pkUpdateRecord(pNdb, 1, 1, value), 0);
145  } else if(strcmp(op, "DELETE") == 0){
146  C2(hugoOps.pkDeleteRecord(pNdb, 1, 1), 0);
147  } else {
148  g_err << __FILE__ << " - " << __LINE__
149  << ": Unknown operation" << op << endl;
150  return NDBT_FAILED;
151  }
152 
153  return NDBT_OK;
154 }
155 
156 int
157 checkVal(HugoOperations & hugoOps,
158  const char * op,
159  int value,
160  int result){
161  if(result != 0)
162  return NDBT_OK;
163 
164  if(strcmp(op, "READ") == 0){
165  } else if(strcmp(op, "READ-EX") == 0){
166  } else if(strcmp(op, "S-READ") == 0){
167  } else if(strcmp(op, "D-READ") == 0){
168  } else {
169  return NDBT_OK;
170  }
171 
172  return hugoOps.verifyUpdatesValue(value);
173 }
174 
175 int
176 runTwoOperations(NDBT_Context* ctx, NDBT_Step* step){
177  int result = NDBT_OK;
178  HugoOperations hugoOps(*ctx->getTab());
179  Ndb* pNdb = GETNDB(step);
180 
181  const char * op1 = ctx->getProperty("op1", "NONE");
182  const int val1 = ctx->getProperty("val1", ~0);
183  const int res1 = ctx->getProperty("res1", ~0);
184  const char * op2 = ctx->getProperty("op2", "NONE");
185  const int res2 = ctx->getProperty("res2", ~0);
186  const int val2 = ctx->getProperty("val2", ~0);
187 
188  const int res3 = ctx->getProperty("res3", ~0);
189  const int val3 = ctx->getProperty("val3", ~0);
190 
191  do {
192  // Insert, read
193  CHECK(hugoOps.startTransaction(pNdb) == 0);
194  CHECK(runOp(hugoOps, pNdb, op1, val1) == 0);
195  AbortOption oa = (res1 == 0) ? AbortOnError : AO_IgnoreError;
196  CHECK(hugoOps.execute_NoCommit(pNdb, oa) == res1);
197  CHECK(checkVal(hugoOps, op1, val1, res1) == 0);
198 
199  ndbout_c("-- running op 2");
200 
201  CHECK(runOp(hugoOps, pNdb, op2, val2) == 0);
202  CHECK(hugoOps.execute_Commit(pNdb) == res2);
203  CHECK(checkVal(hugoOps, op2, val2, res2) == 0);
204 
205  } while(false);
206  hugoOps.closeTransaction(pNdb);
207 
208  if(result != NDBT_OK)
209  return result;
210 
211  do {
212  CHECK(hugoOps.startTransaction(pNdb) == 0);
213  CHECK(runOp(hugoOps, pNdb, "READ", 0) == 0);
214  CHECK(hugoOps.execute_Commit(pNdb) == res3);
215  CHECK(checkVal(hugoOps, "READ", val3, res3) == 0);
216  } while(false);
217  hugoOps.closeTransaction(pNdb);
218 
219  return result;
220 }
221 
222 int
223 runInsertRecord(NDBT_Context* ctx, NDBT_Step* step){
224  int result = NDBT_OK;
225  HugoOperations hugoOps(*ctx->getTab());
226  Ndb* pNdb = GETNDB(step);
227 
228  do{
229  // Insert, insert
230  CHECK(hugoOps.startTransaction(pNdb) == 0);
231  CHECK(hugoOps.pkInsertRecord(pNdb, 1) == 0);
232  CHECK(hugoOps.execute_Commit(pNdb) == 0);
233 
234  } while(false);
235 
236  hugoOps.closeTransaction(pNdb);
237 
238  return result;
239 }
240 
241 int
242 runClearTable(NDBT_Context* ctx, NDBT_Step* step){
243  int records = ctx->getNumRecords();
244 
245  UtilTransactions utilTrans(*ctx->getTab());
246  if (utilTrans.clearTable2(GETNDB(step), records, 240) != 0){
247  return NDBT_FAILED;
248  }
249 
250  NdbRestarter r;
251  int lcp = 7099;
252  r.dumpStateAllNodes(&lcp, 1);
253 
254  return NDBT_OK;
255 }
256 
257 enum OPS { o_DONE= 0, o_INS= 1, o_UPD= 2, o_DEL= 3 };
258 typedef Vector<OPS> Sequence;
259 
260 static
261 bool
262 valid(const Sequence& s)
263 {
264  if(s.size() == 0)
265  return false;
266 
267  for(size_t i = 1; i<s.size(); i++)
268  {
269  switch(s[i]){
270  case o_INS:
271  if(s[i-1] != o_DEL)
272  return false;
273  break;
274  case o_UPD:
275  case o_DEL:
276  if(s[i-1] == o_DEL)
277  return false;
278  break;
279  case o_DONE:
280  return true;
281  }
282  }
283  return true;
284 }
285 
286 #if 0
287 static
288 NdbOut& operator<<(NdbOut& out, const Sequence& s)
289 {
290  out << "[ ";
291  for(size_t i = 0; i<s.size(); i++)
292  {
293  switch(s[i]){
294  case o_INS:
295  out << "INS ";
296  break;
297  case o_DEL:
298  out << "DEL ";
299  break;
300  case o_UPD:
301  out << "UPD ";
302  break;
303  case o_DONE:
304  abort();
305  }
306  }
307  out << "]";
308  return out;
309 }
310 #endif
311 
312 static
313 void
314 generate(Sequence& out, int no)
315 {
316  while(no & 3)
317  {
318  out.push_back((OPS)(no & 3));
319  no >>= 2;
320  }
321 }
322 
323 static
324 void
325 generate(Vector<int>& out, size_t len)
326 {
327  int max= 1;
328  while(len)
329  {
330  max <<= 2;
331  len--;
332  }
333 
334  len= 1;
335  for(int i = 0; i<max; i++)
336  {
337  Sequence tmp;
338  generate(tmp, i);
339 
340  if(tmp.size() >= len && valid(tmp))
341  {
342  out.push_back(i);
343  len= tmp.size();
344  }
345  else
346  {
347  //ndbout << "DISCARD: " << tmp << endl;
348  }
349  }
350 }
351 
352 static const Uint32 DUMMY = 0;
353 static const Uint32 ROW = 1;
354 
355 int
356 verify_other(NDBT_Context* ctx,
357  Ndb* pNdb, int seq, OPS latest, bool initial_row, bool commit)
358 {
359  Uint32 no_wait = NdbOperation::LM_CommittedRead*
360  ctx->getProperty("NoWait", (Uint32)1);
361 
362  for(size_t j = no_wait; j<3; j++)
363  {
364  HugoOperations other(*ctx->getTab());
365  C3(other.startTransaction(pNdb) == 0);
366  C3(other.pkReadRecord(pNdb, ROW, 1, (NdbOperation::LockMode)j) == 0);
367  int tmp= other.execute_Commit(pNdb);
368  if(seq == 0){
370  {
371  C3(initial_row? tmp==0 && other.verifyUpdatesValue(0) == 0 : tmp==626);
372  }
373  else
374  {
375  C3(tmp == 266);
376  }
377  }
378  else if(commit)
379  {
380  switch(latest){
381  case o_INS:
382  case o_UPD:
383  C3(tmp == 0 && other.verifyUpdatesValue(seq) == 0);
384  break;
385  case o_DEL:
386  C3(tmp == 626);
387  break;
388  case o_DONE:
389  abort();
390  }
391  }
392  else
393  {
394  // rollback
395  C3(initial_row? tmp==0 && other.verifyUpdatesValue(0) == 0 : tmp==626);
396  }
397  }
398 
399  return NDBT_OK;
400 }
401 
402 int
403 verify_savepoint(NDBT_Context* ctx,
404  Ndb* pNdb, int seq, OPS latest,
405  Uint64 transactionId)
406 {
407  bool initial_row= (seq == 0) && latest == o_INS;
408 
409  for(size_t j = 0; j<3; j++)
410  {
412 
413  HugoOperations same(*ctx->getTab());
414  C3(same.startTransaction(pNdb) == 0);
415  same.setTransactionId(transactionId); // Cheat
416 
420  for(size_t l = 1; l<=(size_t)seq; l++)
421  {
422  C3(same.pkReadRecord(pNdb, DUMMY, 1, lm) == 0); // Read dummy row
423  C3(same.execute_NoCommit(pNdb) == 0);
424  g_info << "savepoint: " << l << endl;
425  }
426 
427  g_info << "op(" << seq << "): "
428  << " lock mode " << lm << endl;
429 
430  C3(same.pkReadRecord(pNdb, ROW, 1, lm) == 0); // Read real row
431  int tmp= same.execute_Commit(pNdb);
432  if(seq == 0)
433  {
434  if(initial_row)
435  {
436  C3(tmp == 0 && same.verifyUpdatesValue(0) == 0);
437  } else
438  {
439  C3(tmp == 626);
440  }
441  }
442  else
443  {
444  switch(latest){
445  case o_INS:
446  case o_UPD:
447  C3(tmp == 0 && same.verifyUpdatesValue(seq) == 0);
448  break;
449  case o_DEL:
450  C3(tmp == 626);
451  break;
452  case o_DONE:
453  abort();
454  }
455  }
456  }
457  return NDBT_OK;
458 }
459 
460 int
461 runOperations(NDBT_Context* ctx, NDBT_Step* step)
462 {
463  Ndb* pNdb = GETNDB(step);
464 
465  Uint32 seqNo = ctx->getProperty("Sequence", (Uint32)0);
466  Uint32 commit= ctx->getProperty("Commit", (Uint32)1);
467 
468  if(seqNo == 0)
469  {
470  return NDBT_FAILED;
471  }
472 
473  Sequence seq;
474  generate(seq, seqNo);
475 
476  {
477  // Dummy row
478  HugoOperations hugoOps(*ctx->getTab());
479  C3(hugoOps.startTransaction(pNdb) == 0);
480  C3(hugoOps.pkInsertRecord(pNdb, DUMMY, 1, 0) == 0);
481  C3(hugoOps.execute_Commit(pNdb) == 0);
482  }
483 
484  const bool initial_row= (seq[0] != o_INS);
485  if(initial_row)
486  {
487  HugoOperations hugoOps(*ctx->getTab());
488  C3(hugoOps.startTransaction(pNdb) == 0);
489  C3(hugoOps.pkInsertRecord(pNdb, ROW, 1, 0) == 0);
490  C3(hugoOps.execute_Commit(pNdb) == 0);
491  }
492 
493  HugoOperations trans1(*ctx->getTab());
494  C3(trans1.startTransaction(pNdb) == 0);
495  for(size_t i = 0; i<seq.size(); i++)
496  {
500  switch(seq[i]){
501  case o_INS:
502  C3(trans1.pkInsertRecord(pNdb, ROW, 1, i+1) == 0);
503  break;
504  case o_UPD:
505  C3(trans1.pkUpdateRecord(pNdb, ROW, 1, i+1) == 0);
506  break;
507  case o_DEL:
508  C3(trans1.pkDeleteRecord(pNdb, ROW, 1) == 0);
509  break;
510  case o_DONE:
511  abort();
512  }
513  C3(trans1.execute_NoCommit(pNdb) == 0);
514 
518  if(verify_other(ctx, pNdb, 0, seq[0], initial_row, commit) != NDBT_OK)
519  return NDBT_FAILED;
520 
524  Uint64 transactionId= trans1.getTransaction()->getTransactionId();
525 
526  for(size_t k=0; k<=i+1; k++)
527  {
528  if(verify_savepoint(ctx, pNdb, k,
529  k>0 ? seq[k-1] : initial_row ? o_INS : o_DONE,
530  transactionId) != NDBT_OK)
531  return NDBT_FAILED;
532  }
533  }
534 
535  if(commit)
536  {
537  C3(trans1.execute_Commit(pNdb) == 0);
538  }
539  else
540  {
541  C3(trans1.execute_Rollback(pNdb) == 0);
542  }
543 
544  if(verify_other(ctx, pNdb, seq.size(), seq.back(),
545  initial_row, commit) != NDBT_OK)
546  return NDBT_FAILED;
547 
548  return NDBT_OK;
549 }
550 
551 int
552 runLockUpgrade1(NDBT_Context* ctx, NDBT_Step* step){
553  // Verify that data in index match
554  // table data
555  Ndb* pNdb = GETNDB(step);
556  HugoOperations hugoOps(*ctx->getTab());
557  HugoTransactions hugoTrans(*ctx->getTab());
558 
559  if(hugoTrans.loadTable(pNdb, 1) != 0){
560  g_err << "Load table failed" << endl;
561  return NDBT_FAILED;
562  }
563 
564  int result= NDBT_OK;
565  do
566  {
567  CHECK(hugoOps.startTransaction(pNdb) == 0);
568  if(ctx->getProperty("LOCK_UPGRADE", 1) == 1)
569  {
570  CHECK(hugoOps.pkReadRecord(pNdb, 0, 1, NdbOperation::LM_Read) == 0);
571  CHECK(hugoOps.execute_NoCommit(pNdb) == 0);
572 
573  ctx->setProperty("READ_DONE", 1);
574  ctx->broadcast();
575  ndbout_c("wait 2");
576  ctx->getPropertyWait("READ_DONE", 2);
577  ndbout_c("wait 2 - done");
578  }
579  else
580  {
581  ctx->setProperty("READ_DONE", 1);
582  ctx->broadcast();
583  ctx->getPropertyWait("READ_DONE", 2);
584  ndbout_c("wait 2 - done");
585  CHECK(hugoOps.pkReadRecord(pNdb, 0, 1, NdbOperation::LM_Read) == 0);
586  CHECK(hugoOps.execute_NoCommit(pNdb) == 0);
587  }
588  if(ctx->getProperty("LU_OP", o_INS) == o_INS)
589  {
590  CHECK(hugoOps.pkDeleteRecord(pNdb, 0, 1) == 0);
591  CHECK(hugoOps.pkInsertRecord(pNdb, 0, 1, 2) == 0);
592  }
593  else if(ctx->getProperty("LU_OP", o_UPD) == o_UPD)
594  {
595  CHECK(hugoOps.pkUpdateRecord(pNdb, 0, 1, 2) == 0);
596  }
597  else
598  {
599  CHECK(hugoOps.pkDeleteRecord(pNdb, 0, 1) == 0);
600  }
601  ctx->setProperty("READ_DONE", 3);
602  ctx->broadcast();
603  ndbout_c("before update");
604  ndbout_c("wait update");
605  CHECK(hugoOps.execute_Commit(pNdb) == 0);
606  CHECK(hugoOps.closeTransaction(pNdb) == 0);
607 
608  CHECK(hugoOps.startTransaction(pNdb) == 0);
609  CHECK(hugoOps.pkReadRecord(pNdb, 0, 1) == 0);
610  int res= hugoOps.execute_Commit(pNdb);
611  if(ctx->getProperty("LU_OP", o_INS) == o_INS)
612  {
613  CHECK(res == 0);
614  CHECK(hugoOps.verifyUpdatesValue(2) == 0);
615  }
616  else if(ctx->getProperty("LU_OP", o_UPD) == o_UPD)
617  {
618  CHECK(res == 0);
619  CHECK(hugoOps.verifyUpdatesValue(2) == 0);
620  }
621  else
622  {
623  CHECK(res == 626);
624  }
625 
626  } while(0);
627 
628  return result;
629 }
630 
631 int
632 runLockUpgrade2(NDBT_Context* ctx, NDBT_Step* step){
633  // Verify that data in index match
634  // table data
635  Ndb* pNdb = GETNDB(step);
636  HugoOperations hugoOps(*ctx->getTab());
637  HugoTransactions hugoTrans(*ctx->getTab());
638 
639 
640  int result= NDBT_OK;
641  do
642  {
643  CHECK(hugoOps.startTransaction(pNdb) == 0);
644  ndbout_c("wait 1");
645  ctx->getPropertyWait("READ_DONE", 1);
646  ndbout_c("wait 1 - done");
647  CHECK(hugoOps.pkReadRecord(pNdb, 0, 1, NdbOperation::LM_Read) == 0);
648  CHECK(hugoOps.execute_NoCommit(pNdb) == 0);
649  ctx->setProperty("READ_DONE", 2);
650  ctx->broadcast();
651  ndbout_c("wait 3");
652  ctx->getPropertyWait("READ_DONE", 3);
653  ndbout_c("wait 3 - done");
654 
655  NdbSleep_MilliSleep(200);
656  if(ctx->getProperty("LU_COMMIT", (Uint32)0) == 0)
657  {
658  CHECK(hugoOps.execute_Commit(pNdb) == 0);
659  }
660  else
661  {
662  CHECK(hugoOps.execute_Rollback(pNdb) == 0);
663  }
664  } while(0);
665 
666  return result;
667 }
668 
669 int
670 main(int argc, const char** argv){
671  ndb_init();
672 
673  Vector<int> tmp;
674  generate(tmp, 5);
675 
676  NDBT_TestSuite ts("testOperations");
677 
678  ts.setTemporaryTables(true);
679 
680  for(Uint32 i = 0; i < 12; i++)
681  {
682  if(false && (i == 6 || i == 8 || i == 10))
683  continue;
684 
685  BaseString name("bug_9749");
686  name.appfmt("_%d", i);
687  NDBT_TestCaseImpl1 *pt = new NDBT_TestCaseImpl1(&ts,
688  name.c_str(), "");
689 
690  pt->setProperty("LOCK_UPGRADE", 1 + (i & 1));
691  pt->setProperty("LU_OP", 1 + ((i >> 1) % 3));
692  pt->setProperty("LU_COMMIT", i / 6);
693 
694  pt->addInitializer(new NDBT_Initializer(pt,
695  "runClearTable",
696  runClearTable));
697 
698  pt->addStep(new NDBT_ParallelStep(pt,
699  "thread1",
700  runLockUpgrade1));
701 
702 
703  pt->addStep(new NDBT_ParallelStep(pt,
704  "thread2",
705  runLockUpgrade2));
706 
707  pt->addFinalizer(new NDBT_Finalizer(pt,
708  "runClearTable",
709  runClearTable));
710  ts.addTest(pt);
711  }
712 
713  for(size_t i = 0; i<tmp.size(); i++)
714  {
716  Sequence s;
717  generate(s, tmp[i]);
718  for(size_t j = 0; j<s.size(); j++){
719  switch(s[j]){
720  case o_INS:
721  name.append("_INS");
722  break;
723  case o_DEL:
724  name.append("_DEL");
725  break;
726  case o_UPD:
727  name.append("_UPD");
728  break;
729  case o_DONE:
730  abort();
731  }
732  }
733 
734  BaseString n1;
735  n1.append(name);
736  n1.append("_COMMIT");
737 
738  NDBT_TestCaseImpl1 *pt = new NDBT_TestCaseImpl1(&ts,
739  n1.c_str()+1, "");
740 
741  pt->setProperty("Sequence", tmp[i]);
742  pt->addInitializer(new NDBT_Initializer(pt,
743  "runClearTable",
744  runClearTable));
745 
746  pt->addStep(new NDBT_ParallelStep(pt,
747  "run",
748  runOperations));
749 
750  pt->addFinalizer(new NDBT_Finalizer(pt,
751  "runClearTable",
752  runClearTable));
753 
754  ts.addTest(pt);
755 
756  name.append("_ABORT");
757  pt = new NDBT_TestCaseImpl1(&ts, name.c_str()+1, "");
758  pt->setProperty("Sequence", tmp[i]);
759  pt->setProperty("Commit", (Uint32)0);
760  pt->addInitializer(new NDBT_Initializer(pt,
761  "runClearTable",
762  runClearTable));
763 
764  pt->addStep(new NDBT_ParallelStep(pt,
765  "run",
766  runOperations));
767 
768  pt->addFinalizer(new NDBT_Finalizer(pt,
769  "runClearTable",
770  runClearTable));
771 
772  ts.addTest(pt);
773  }
774 
775  for(Uint32 i = 0; i<sizeof(matrix)/sizeof(matrix[0]); i++){
776  NDBT_TestCaseImpl1 *pt = new NDBT_TestCaseImpl1(&ts, matrix[i].name, "");
777 
778  pt->addInitializer(new NDBT_Initializer(pt,
779  "runClearTable",
780  runClearTable));
781 
782  if(matrix[i].preCond){
783  pt->addInitializer(new NDBT_Initializer(pt,
784  "runInsertRecord",
785  runInsertRecord));
786  }
787 
788  pt->setProperty("op1", matrix[i].op1);
789  pt->setProperty("res1", matrix[i].res1);
790  pt->setProperty("val1", matrix[i].val1);
791 
792  pt->setProperty("op2", matrix[i].op2);
793  pt->setProperty("res2", matrix[i].res2);
794  pt->setProperty("val2", matrix[i].val2);
795 
796  pt->setProperty("res3", matrix[i].res3);
797  pt->setProperty("val3", matrix[i].val3);
798 
799  pt->addStep(new NDBT_ParallelStep(pt,
800  matrix[i].name,
801  runTwoOperations));
802  pt->addFinalizer(new NDBT_Finalizer(pt,
803  "runClearTable",
804  runClearTable));
805 
806  ts.addTest(pt);
807  }
808 
809  return ts.execute(argc, argv);
810 }
811 
812 template class Vector<OPS>;
813 template class Vector<Sequence>;