~ubuntu-branches/ubuntu/precise/mysql-5.1/precise

« back to all changes in this revision

Viewing changes to storage/ndb/test/ndbapi/testOperations.cpp

  • Committer: Bazaar Package Importer
  • Author(s): Norbert Tretkowski
  • Date: 2010-03-17 14:56:02 UTC
  • Revision ID: james.westby@ubuntu.com-20100317145602-x7e30l1b2sb5s6w6
Tags: upstream-5.1.45
ImportĀ upstreamĀ versionĀ 5.1.45

Show diffs side-by-side

added added

removed removed

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