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

« back to all changes in this revision

Viewing changes to storage/ndb/test/src/UtilTransactions.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 "UtilTransactions.hpp"
 
17
#include <NdbSleep.h>
 
18
#include <NdbScanFilter.hpp>
 
19
 
 
20
#define VERBOSE 0
 
21
 
 
22
UtilTransactions::UtilTransactions(const NdbDictionary::Table& _tab,
 
23
                                   const NdbDictionary::Index* _idx):
 
24
  tab(_tab), idx(_idx), pTrans(0)
 
25
{
 
26
  m_defaultClearMethod = 3;
 
27
}
 
28
 
 
29
UtilTransactions::UtilTransactions(Ndb* ndb, 
 
30
                                   const char * name,
 
31
                                   const char * index) :
 
32
  tab(* ndb->getDictionary()->getTable(name)),
 
33
  idx(index ? ndb->getDictionary()->getIndex(index, name) : 0),
 
34
  pTrans(0)
 
35
{
 
36
  m_defaultClearMethod = 3;
 
37
}
 
38
 
 
39
#define RESTART_SCAN 99
 
40
 
 
41
#define RETURN_FAIL(err) return (err.code != 0 ? err.code : NDBT_FAILED) 
 
42
 
 
43
int 
 
44
UtilTransactions::clearTable(Ndb* pNdb, 
 
45
                             NdbScanOperation::ScanFlag flags,
 
46
                             int records,
 
47
                             int parallelism){
 
48
  // Scan all records exclusive and delete 
 
49
  // them one by one
 
50
  int                  retryAttempt = 0;
 
51
  const int            retryMax = 10;
 
52
  int deletedRows = 0;
 
53
  int check;
 
54
  NdbScanOperation *pOp;
 
55
  NdbError err;
 
56
 
 
57
  int par = parallelism;
 
58
  while (true){
 
59
  restart:
 
60
    if (retryAttempt++ >= retryMax){
 
61
      g_info << "ERROR: has retried this operation " << retryAttempt 
 
62
             << " times, failing!" << endl;
 
63
      return NDBT_FAILED;
 
64
    }
 
65
    
 
66
    pTrans = pNdb->startTransaction();
 
67
    if (pTrans == NULL) {
 
68
      err = pNdb->getNdbError();
 
69
      if (err.status == NdbError::TemporaryError){
 
70
        ERR(err);
 
71
        NdbSleep_MilliSleep(50);
 
72
        continue;
 
73
      }
 
74
      goto failed;
 
75
    }
 
76
 
 
77
    pOp = getScanOperation(pTrans);
 
78
    if (pOp == NULL) {
 
79
      err = pTrans->getNdbError();
 
80
      if(err.status == NdbError::TemporaryError){
 
81
        ERR(err);
 
82
        closeTransaction(pNdb);
 
83
        NdbSleep_MilliSleep(50);
 
84
        par = 1;
 
85
        goto restart;
 
86
      }
 
87
      goto failed;
 
88
    }
 
89
    
 
90
    if( pOp->readTuples(NdbOperation::LM_Exclusive, flags, par) ) {
 
91
      err = pTrans->getNdbError();
 
92
      goto failed;
 
93
    }
 
94
    
 
95
    if(pTrans->execute(NoCommit, AbortOnError) != 0){
 
96
      err = pTrans->getNdbError();    
 
97
      if(err.status == NdbError::TemporaryError){
 
98
        ERR(err);
 
99
        closeTransaction(pNdb);
 
100
        NdbSleep_MilliSleep(50);
 
101
        continue;
 
102
      }
 
103
      goto failed;
 
104
    }
 
105
    
 
106
    while((check = pOp->nextResult(true)) == 0){
 
107
      do {
 
108
        if (pOp->deleteCurrentTuple() != 0){
 
109
          goto failed;
 
110
        }
 
111
        deletedRows++;
 
112
      } while((check = pOp->nextResult(false)) == 0);
 
113
      
 
114
      if(check != -1){
 
115
        check = pTrans->execute(Commit, AbortOnError);   
 
116
        pTrans->restart();
 
117
      }
 
118
      
 
119
      err = pTrans->getNdbError();    
 
120
      if(check == -1){
 
121
        if(err.status == NdbError::TemporaryError){
 
122
          ERR(err);
 
123
          closeTransaction(pNdb);
 
124
          NdbSleep_MilliSleep(50);
 
125
          par = 1;
 
126
          goto restart;
 
127
        }
 
128
        goto failed;
 
129
      }
 
130
    }
 
131
    if(check == -1){
 
132
      err = pTrans->getNdbError();    
 
133
      if(err.status == NdbError::TemporaryError){
 
134
        ERR(err);
 
135
        closeTransaction(pNdb);
 
136
        NdbSleep_MilliSleep(50);
 
137
        par = 1;
 
138
        goto restart;
 
139
      }
 
140
      goto failed;
 
141
    }
 
142
    closeTransaction(pNdb);
 
143
    return NDBT_OK;
 
144
  }
 
145
  return NDBT_FAILED;
 
146
  
 
147
 failed:
 
148
  if(pTrans != 0) closeTransaction(pNdb);
 
149
  ERR(err);
 
150
  return (err.code != 0 ? err.code : NDBT_FAILED);
 
151
}
 
152
 
 
153
int 
 
154
UtilTransactions::clearTable(Ndb* pNdb, 
 
155
                             int records,
 
156
                             int parallelism){
 
157
 
 
158
  return clearTable(pNdb, (NdbScanOperation::ScanFlag)0,
 
159
                    records, parallelism);
 
160
}
 
161
 
 
162
 
 
163
int 
 
164
UtilTransactions::clearTable1(Ndb* pNdb, 
 
165
                             int records,
 
166
                             int parallelism)
 
167
{
 
168
  return clearTable(pNdb, (NdbScanOperation::ScanFlag)0,
 
169
                    records, 1);
 
170
}
 
171
 
 
172
int 
 
173
UtilTransactions::clearTable2(Ndb* pNdb, 
 
174
                              int records,
 
175
                              int parallelism)
 
176
{
 
177
  return clearTable(pNdb, (NdbScanOperation::ScanFlag)0,
 
178
                    records, parallelism);
 
179
}
 
180
 
 
181
int 
 
182
UtilTransactions::clearTable3(Ndb* pNdb, 
 
183
                              int records,
 
184
                              int parallelism)
 
185
{
 
186
  return clearTable(pNdb, (NdbScanOperation::ScanFlag)0,
 
187
                    records, parallelism);
 
188
}
 
189
 
 
190
int 
 
191
UtilTransactions::copyTableData(Ndb* pNdb,
 
192
                            const char* destName){
 
193
  // Scan all records and copy 
 
194
  // them to destName table
 
195
  int                  retryAttempt = 0;
 
196
  const int            retryMax = 10;
 
197
  int insertedRows = 0;
 
198
  int parallelism = 240;
 
199
  int check;
 
200
  NdbScanOperation              *pOp;
 
201
  NDBT_ResultRow       row(tab);
 
202
  
 
203
  while (true){
 
204
    
 
205
    if (retryAttempt >= retryMax){
 
206
      g_info << "ERROR: has retried this operation " << retryAttempt 
 
207
             << " times, failing!" << endl;
 
208
      return NDBT_FAILED;
 
209
    }
 
210
 
 
211
 
 
212
    pTrans = pNdb->startTransaction();
 
213
    if (pTrans == NULL) {
 
214
      const NdbError err = pNdb->getNdbError();
 
215
 
 
216
      if (err.status == NdbError::TemporaryError){
 
217
        ERR(err);
 
218
        NdbSleep_MilliSleep(50);
 
219
        retryAttempt++;
 
220
        continue;
 
221
      }
 
222
      ERR(err);
 
223
      return NDBT_FAILED;
 
224
    }
 
225
 
 
226
    pOp = pTrans->getNdbScanOperation(tab.getName());   
 
227
    if (pOp == NULL) {
 
228
      ERR(pTrans->getNdbError());
 
229
      closeTransaction(pNdb);
 
230
      return NDBT_FAILED;
 
231
    }
 
232
 
 
233
    if( pOp->readTuples(NdbScanOperation::LM_Read, parallelism) ) {
 
234
      ERR(pTrans->getNdbError());
 
235
      closeTransaction(pNdb);
 
236
      return NDBT_FAILED;
 
237
    }
 
238
 
 
239
    check = pOp->interpret_exit_ok();
 
240
    if( check == -1 ) {
 
241
      ERR(pTrans->getNdbError());
 
242
      closeTransaction(pNdb);
 
243
      return NDBT_FAILED;
 
244
    }  
 
245
 
 
246
    // Read all attributes
 
247
    for (int a = 0; a < tab.getNoOfColumns(); a++){
 
248
      if ((row.attributeStore(a) =  
 
249
           pOp->getValue(tab.getColumn(a)->getName())) == 0) {
 
250
        ERR(pTrans->getNdbError());
 
251
        closeTransaction(pNdb);
 
252
        return NDBT_FAILED;
 
253
      }
 
254
    }
 
255
    
 
256
    check = pTrans->execute(NoCommit, AbortOnError);
 
257
    if( check == -1 ) {
 
258
      ERR(pTrans->getNdbError());
 
259
      closeTransaction(pNdb);
 
260
      return NDBT_FAILED;
 
261
    }
 
262
  
 
263
    int eof;
 
264
    while((eof = pOp->nextResult(true)) == 0){
 
265
      do {
 
266
        insertedRows++;
 
267
        if (addRowToInsert(pNdb, pTrans, row, destName) != 0){
 
268
          closeTransaction(pNdb);
 
269
          return NDBT_FAILED;
 
270
        }
 
271
      } while((eof = pOp->nextResult(false)) == 0);
 
272
      
 
273
      check = pTrans->execute(Commit, AbortOnError);   
 
274
      pTrans->restart();
 
275
      if( check == -1 ) {
 
276
        const NdbError err = pTrans->getNdbError();    
 
277
        ERR(err);
 
278
        closeTransaction(pNdb);
 
279
        return NDBT_FAILED;
 
280
      }
 
281
    }  
 
282
    if (eof == -1) {
 
283
      const NdbError err = pTrans->getNdbError();
 
284
      
 
285
      if (err.status == NdbError::TemporaryError){
 
286
        ERR(err);
 
287
        closeTransaction(pNdb);
 
288
        NdbSleep_MilliSleep(50);
 
289
        // If error = 488 there should be no limit on number of retry attempts
 
290
        if (err.code != 488) 
 
291
          retryAttempt++;
 
292
        continue;
 
293
      }
 
294
      ERR(err);
 
295
      closeTransaction(pNdb);
 
296
      return NDBT_FAILED;
 
297
    }
 
298
    
 
299
    closeTransaction(pNdb);
 
300
    
 
301
    g_info << insertedRows << " rows copied" << endl;
 
302
    
 
303
    return NDBT_OK;
 
304
  }
 
305
  return NDBT_FAILED;
 
306
}
 
307
 
 
308
int 
 
309
UtilTransactions::addRowToInsert(Ndb* pNdb,
 
310
                                 NdbConnection* pInsTrans,
 
311
                                 NDBT_ResultRow & row,
 
312
                                 const char *insertTabName){
 
313
 
 
314
  int check;
 
315
  NdbOperation* pInsOp;
 
316
 
 
317
  pInsOp = pInsTrans->getNdbOperation(insertTabName);   
 
318
  if (pInsOp == NULL) {
 
319
    ERR(pInsTrans->getNdbError());
 
320
    return NDBT_FAILED;
 
321
  }
 
322
  
 
323
  check = pInsOp->insertTuple();
 
324
  if( check == -1 ) {
 
325
    ERR(pInsTrans->getNdbError());
 
326
    return NDBT_FAILED;
 
327
  }
 
328
 
 
329
  // Set all attributes
 
330
  for (int a = 0; a < tab.getNoOfColumns(); a++){
 
331
    NdbRecAttr* r =  row.attributeStore(a);
 
332
    int  sz = r->get_size_in_bytes();
 
333
    if (pInsOp->setValue(tab.getColumn(a)->getName(),
 
334
                         r->aRef(),
 
335
                         sz) != 0) {
 
336
      ERR(pInsTrans->getNdbError());
 
337
      return NDBT_FAILED;
 
338
    }
 
339
  }
 
340
  
 
341
  return NDBT_OK;
 
342
}
 
343
 
 
344
 
 
345
int 
 
346
UtilTransactions::scanReadRecords(Ndb* pNdb,
 
347
                                  int parallelism,
 
348
                                  NdbOperation::LockMode lm,
 
349
                                  int records,
 
350
                                  int noAttribs,
 
351
                                  int *attrib_list,
 
352
                                  ReadCallBackFn* fn){
 
353
  
 
354
  int                  retryAttempt = 0;
 
355
  const int            retryMax = 100;
 
356
  int                  check;
 
357
  NdbScanOperation             *pOp;
 
358
  NDBT_ResultRow       row(tab);
 
359
 
 
360
  while (true){
 
361
 
 
362
    if (retryAttempt >= retryMax){
 
363
      g_info << "ERROR: has retried this operation " << retryAttempt 
 
364
             << " times, failing!" << endl;
 
365
      return NDBT_FAILED;
 
366
    }
 
367
 
 
368
    pTrans = pNdb->startTransaction();
 
369
    if (pTrans == NULL) {
 
370
      const NdbError err = pNdb->getNdbError();
 
371
 
 
372
      if (err.status == NdbError::TemporaryError){
 
373
        ERR(err);
 
374
        NdbSleep_MilliSleep(50);
 
375
        retryAttempt++;
 
376
        continue;
 
377
      }
 
378
      ERR(err);
 
379
      return NDBT_FAILED;
 
380
    }
 
381
 
 
382
    pOp = getScanOperation(pTrans);
 
383
    if (pOp == NULL) {
 
384
      const NdbError err = pNdb->getNdbError();
 
385
      closeTransaction(pNdb);
 
386
 
 
387
      if (err.status == NdbError::TemporaryError){
 
388
        ERR(err);
 
389
        NdbSleep_MilliSleep(50);
 
390
        retryAttempt++;
 
391
        continue;
 
392
      }
 
393
      ERR(err);
 
394
      return NDBT_FAILED;
 
395
    }
 
396
 
 
397
    if( pOp->readTuples(lm, 0, parallelism) ) {
 
398
      ERR(pTrans->getNdbError());
 
399
      closeTransaction(pNdb);
 
400
      return NDBT_FAILED;
 
401
    }
 
402
 
 
403
    check = pOp->interpret_exit_ok();
 
404
    if( check == -1 ) {
 
405
      ERR(pTrans->getNdbError());
 
406
      closeTransaction(pNdb);
 
407
      return NDBT_FAILED;
 
408
    }
 
409
    
 
410
    // Call getValue for all the attributes supplied in attrib_list
 
411
    // ************************************************
 
412
    for (int a = 0; a < noAttribs; a++){
 
413
      if (attrib_list[a] < tab.getNoOfColumns()){ 
 
414
        g_info << "getValue(" << attrib_list[a] << ")" << endl;
 
415
        if ((row.attributeStore(attrib_list[a]) =  
 
416
             pOp->getValue(tab.getColumn(attrib_list[a])->getName())) == 0) {
 
417
          ERR(pTrans->getNdbError());
 
418
          closeTransaction(pNdb);
 
419
          return NDBT_FAILED;
 
420
        }
 
421
      }
 
422
    }
 
423
    // *************************************************
 
424
    
 
425
    check = pTrans->execute(NoCommit, AbortOnError);
 
426
    if( check == -1 ) {
 
427
      const NdbError err = pTrans->getNdbError();
 
428
 
 
429
      if (err.status == NdbError::TemporaryError){
 
430
        ERR(err);
 
431
        closeTransaction(pNdb);
 
432
        NdbSleep_MilliSleep(50);
 
433
        retryAttempt++;
 
434
        continue;
 
435
      }
 
436
      ERR(err);
 
437
      closeTransaction(pNdb);
 
438
      return NDBT_FAILED;
 
439
    }
 
440
    
 
441
    int eof;
 
442
    int rows = 0;
 
443
    
 
444
    
 
445
    while((eof = pOp->nextResult()) == 0){
 
446
      rows++;
 
447
      
 
448
      // Call callback for each record returned
 
449
      if(fn != NULL)
 
450
        fn(&row);
 
451
    }
 
452
    if (eof == -1) {
 
453
      const NdbError err = pTrans->getNdbError();
 
454
      
 
455
      if (err.status == NdbError::TemporaryError){
 
456
        ERR(err);
 
457
        closeTransaction(pNdb);
 
458
        NdbSleep_MilliSleep(50);
 
459
        retryAttempt++;
 
460
        continue;
 
461
      }
 
462
      ERR(err);
 
463
      closeTransaction(pNdb);
 
464
      return NDBT_FAILED;
 
465
    }
 
466
    
 
467
    closeTransaction(pNdb);
 
468
    g_info << rows << " rows have been read" << endl;
 
469
    if (records != 0 && rows != records){
 
470
      g_info << "Check expected number of records failed" << endl 
 
471
             << "  expected=" << records <<", " << endl
 
472
             << "  read=" << rows << endl;
 
473
      return NDBT_FAILED;
 
474
    }
 
475
    
 
476
    return NDBT_OK;
 
477
  }
 
478
  return NDBT_FAILED;
 
479
}
 
480
 
 
481
int 
 
482
UtilTransactions::selectCount(Ndb* pNdb, 
 
483
                              int parallelism,
 
484
                              int* count_rows,
 
485
                              NdbOperation::LockMode lm,
 
486
                              NdbConnection* pTrans){
 
487
  
 
488
  int                  retryAttempt = 0;
 
489
  const int            retryMax = 100;
 
490
  int                  check;
 
491
  NdbScanOperation     *pOp;
 
492
 
 
493
  if(!pTrans)
 
494
    pTrans = pNdb->startTransaction();
 
495
    
 
496
  while (true){
 
497
 
 
498
    if (retryAttempt >= retryMax){
 
499
      g_info << "ERROR: has retried this operation " << retryAttempt 
 
500
             << " times, failing!" << endl;
 
501
      return NDBT_FAILED;
 
502
    }
 
503
    pOp = getScanOperation(pTrans);
 
504
    if (pOp == NULL) {
 
505
      ERR(pTrans->getNdbError());
 
506
      closeTransaction(pNdb);
 
507
      return NDBT_FAILED;
 
508
    }
 
509
 
 
510
    if( pOp->readTuples(lm) ) {
 
511
      ERR(pTrans->getNdbError());
 
512
      closeTransaction(pNdb);
 
513
      return NDBT_FAILED;
 
514
    }
 
515
 
 
516
    if(0){
 
517
      NdbScanFilter sf(pOp);
 
518
      sf.begin(NdbScanFilter::OR);
 
519
      sf.eq(2, (Uint32)30);
 
520
      sf.end();
 
521
    } else {
 
522
      check = pOp->interpret_exit_ok();
 
523
      if( check == -1 ) {
 
524
        ERR(pTrans->getNdbError());
 
525
        closeTransaction(pNdb);
 
526
        return NDBT_FAILED;
 
527
      }
 
528
    }
 
529
    
 
530
    
 
531
    check = pTrans->execute(NoCommit, AbortOnError);
 
532
    if( check == -1 ) {
 
533
      ERR(pTrans->getNdbError());
 
534
      closeTransaction(pNdb);
 
535
      return NDBT_FAILED;
 
536
    }
 
537
 
 
538
    int eof;
 
539
    int rows = 0;
 
540
    
 
541
 
 
542
    while((eof = pOp->nextResult()) == 0){
 
543
      rows++;
 
544
    }
 
545
    if (eof == -1) {
 
546
      const NdbError err = pTrans->getNdbError();
 
547
      
 
548
      if (err.status == NdbError::TemporaryError){
 
549
        closeTransaction(pNdb);
 
550
        NdbSleep_MilliSleep(50);
 
551
        retryAttempt++;
 
552
        continue;
 
553
      }
 
554
      ERR(err);
 
555
      closeTransaction(pNdb);
 
556
      return NDBT_FAILED;
 
557
    }
 
558
    
 
559
    closeTransaction(pNdb);
 
560
    
 
561
    if (count_rows != NULL){
 
562
      *count_rows = rows;
 
563
    }
 
564
    
 
565
    return NDBT_OK;
 
566
  }
 
567
  return NDBT_FAILED;
 
568
}
 
569
  
 
570
int 
 
571
UtilTransactions::verifyIndex(Ndb* pNdb,
 
572
                              const char* indexName,
 
573
                              int parallelism,
 
574
                              bool transactional){
 
575
  
 
576
 
 
577
  const NdbDictionary::Index* pIndex
 
578
    = pNdb->getDictionary()->getIndex(indexName, tab.getName());
 
579
  if (pIndex == 0){
 
580
    ndbout << " Index " << indexName << " does not exist!" << endl;
 
581
    return NDBT_FAILED;
 
582
  }
 
583
  
 
584
  switch (pIndex->getType()){
 
585
  case NdbDictionary::Index::UniqueHashIndex:
 
586
    return verifyUniqueIndex(pNdb, pIndex, parallelism, transactional);
 
587
  case NdbDictionary::Index::OrderedIndex:
 
588
    return verifyOrderedIndex(pNdb, pIndex, parallelism, transactional);
 
589
    break;
 
590
  default:
 
591
    ndbout << "Unknown index type" << endl;
 
592
    break;
 
593
  }
 
594
  
 
595
  return NDBT_FAILED;
 
596
}
 
597
 
 
598
int 
 
599
UtilTransactions::verifyUniqueIndex(Ndb* pNdb,
 
600
                                    const NdbDictionary::Index * pIndex,
 
601
                                    int parallelism,
 
602
                                    bool transactional){
 
603
  
 
604
  /**
 
605
   * Scan all rows in TABLE and for each found row make one read in
 
606
   * TABLE and one using INDEX_TABLE. Then compare the two returned 
 
607
   * rows. They should be equal!
 
608
   *
 
609
   */
 
610
 
 
611
  if (scanAndCompareUniqueIndex(pNdb, 
 
612
                                pIndex,
 
613
                                parallelism,
 
614
                                transactional) != NDBT_OK){
 
615
    return NDBT_FAILED;
 
616
  }
 
617
 
 
618
 
 
619
  return NDBT_OK;
 
620
  
 
621
}
 
622
 
 
623
 
 
624
int 
 
625
UtilTransactions::scanAndCompareUniqueIndex(Ndb* pNdb,
 
626
                                            const NdbDictionary::Index* pIndex,
 
627
                                            int parallelism,
 
628
                                            bool transactional){
 
629
  
 
630
  int                  retryAttempt = 0;
 
631
  const int            retryMax = 100;
 
632
  int                  check;
 
633
  NdbScanOperation       *pOp;
 
634
  NDBT_ResultRow       row(tab);
 
635
 
 
636
  parallelism = 1;
 
637
 
 
638
  while (true){
 
639
restart:
 
640
    if (retryAttempt >= retryMax){
 
641
      g_info << "ERROR: has retried this operation " << retryAttempt 
 
642
             << " times, failing!" << endl;
 
643
      return NDBT_FAILED;
 
644
    }
 
645
 
 
646
    pTrans = pNdb->startTransaction();
 
647
    if (pTrans == NULL) {
 
648
      const NdbError err = pNdb->getNdbError();
 
649
 
 
650
      if (err.status == NdbError::TemporaryError){
 
651
        ERR(err);
 
652
        NdbSleep_MilliSleep(50);
 
653
        retryAttempt++;
 
654
        continue;
 
655
      }
 
656
      ERR(err);
 
657
      return NDBT_FAILED;
 
658
    }
 
659
 
 
660
    pOp = pTrans->getNdbScanOperation(tab.getName());   
 
661
    if (pOp == NULL) {
 
662
      const NdbError err = pNdb->getNdbError();
 
663
      closeTransaction(pNdb);
 
664
      ERR(err);
 
665
      
 
666
      if (err.status == NdbError::TemporaryError){
 
667
        NdbSleep_MilliSleep(50);
 
668
        retryAttempt++;
 
669
        continue;
 
670
      }
 
671
      return NDBT_FAILED;
 
672
    }
 
673
 
 
674
    int rs;
 
675
    if(transactional){
 
676
      rs = pOp->readTuples(NdbScanOperation::LM_Read, 0, parallelism);
 
677
    } else {
 
678
      rs = pOp->readTuples(NdbScanOperation::LM_CommittedRead, 0, parallelism);
 
679
    }
 
680
    
 
681
    if( rs != 0 ) {
 
682
      ERR(pTrans->getNdbError());
 
683
      closeTransaction(pNdb);
 
684
      return NDBT_FAILED;
 
685
    }
 
686
 
 
687
    check = pOp->interpret_exit_ok();
 
688
    if( check == -1 ) {
 
689
      ERR(pTrans->getNdbError());
 
690
      closeTransaction(pNdb);
 
691
      return NDBT_FAILED;
 
692
    }
 
693
 
 
694
    // Read all attributes
 
695
    for (int a = 0; a < tab.getNoOfColumns(); a++){
 
696
      if ((row.attributeStore(a) =  
 
697
           pOp->getValue(tab.getColumn(a)->getName())) == 0) {
 
698
        ERR(pTrans->getNdbError());
 
699
        closeTransaction(pNdb);
 
700
        return NDBT_FAILED;
 
701
      }
 
702
    }
 
703
 
 
704
    check = pTrans->execute(NoCommit, AbortOnError);
 
705
    if( check == -1 ) {
 
706
      const NdbError err = pTrans->getNdbError();
 
707
      
 
708
      if (err.status == NdbError::TemporaryError){
 
709
        ERR(err);
 
710
        closeTransaction(pNdb);
 
711
        NdbSleep_MilliSleep(50);
 
712
        retryAttempt++;
 
713
        continue;
 
714
      }
 
715
      ERR(err);
 
716
      closeTransaction(pNdb);
 
717
      return NDBT_FAILED;
 
718
    }
 
719
    
 
720
    int eof;
 
721
    int rows = 0;
 
722
    
 
723
    
 
724
    while((eof = pOp->nextResult()) == 0){
 
725
      rows++;
 
726
      
 
727
      // ndbout << row.c_str().c_str() << endl;
 
728
      
 
729
      if (readRowFromTableAndIndex(pNdb,
 
730
                                   pTrans,
 
731
                                   pIndex,
 
732
                                   row) != NDBT_OK){    
 
733
        
 
734
        while((eof= pOp->nextResult(false)) == 0);
 
735
        if(eof == 2)
 
736
          eof = pOp->nextResult(true); // this should give -1
 
737
        if(eof == -1)
 
738
        {
 
739
          const NdbError err = pTrans->getNdbError();
 
740
          
 
741
          if (err.status == NdbError::TemporaryError){
 
742
            ERR(err);
 
743
            closeTransaction(pNdb);
 
744
            NdbSleep_MilliSleep(50);
 
745
            retryAttempt++;
 
746
            goto restart;
 
747
          }
 
748
        }
 
749
        closeTransaction(pNdb);
 
750
        return NDBT_FAILED;
 
751
      }
 
752
    }
 
753
    if (eof == -1) {
 
754
      const NdbError err = pTrans->getNdbError();
 
755
      
 
756
      if (err.status == NdbError::TemporaryError){
 
757
        ERR(err);
 
758
        closeTransaction(pNdb);
 
759
        NdbSleep_MilliSleep(50);
 
760
        retryAttempt++;
 
761
        continue;
 
762
      }
 
763
      ERR(err);
 
764
      closeTransaction(pNdb);
 
765
      return NDBT_FAILED;
 
766
    }
 
767
    
 
768
    closeTransaction(pNdb);
 
769
    
 
770
    return NDBT_OK;
 
771
  }
 
772
  return NDBT_FAILED;
 
773
}
 
774
int 
 
775
UtilTransactions::readRowFromTableAndIndex(Ndb* pNdb,
 
776
                                           NdbConnection* scanTrans,
 
777
                                           const NdbDictionary::Index* pIndex,
 
778
                                           NDBT_ResultRow& row ){
 
779
 
 
780
 
 
781
  NdbDictionary::Index::Type indexType= pIndex->getType();
 
782
  int                  retryAttempt = 0;
 
783
  const int            retryMax = 100;
 
784
  int                  check, a;
 
785
  NdbConnection        *pTrans1=NULL;
 
786
  NdbOperation         *pOp;
 
787
 
 
788
  int return_code= NDBT_FAILED;
 
789
 
 
790
  // Allocate place to store the result
 
791
  NDBT_ResultRow       tabRow(tab);
 
792
  NDBT_ResultRow       indexRow(tab);
 
793
  const char * indexName = pIndex->getName();
 
794
 
 
795
  while (true){
 
796
    if(retryAttempt)
 
797
      ndbout_c("retryAttempt %d", retryAttempt);
 
798
    if (retryAttempt >= retryMax){
 
799
      g_info << "ERROR: has retried this operation " << retryAttempt 
 
800
             << " times, failing!" << endl;
 
801
        goto close_all;
 
802
    }
 
803
 
 
804
    pTrans1 = pNdb->hupp(scanTrans); //startTransaction();
 
805
    if (pTrans1 == NULL) {
 
806
      const NdbError err = pNdb->getNdbError();
 
807
      
 
808
      if (err.status == NdbError::TemporaryError){
 
809
        ERR(err);
 
810
        NdbSleep_MilliSleep(50);
 
811
        retryAttempt++;
 
812
        continue;
 
813
      }
 
814
 
 
815
      if(err.code == 0){
 
816
        return_code = NDBT_OK;
 
817
        goto close_all;
 
818
      }
 
819
      ERR(err);
 
820
      goto close_all;
 
821
    }
 
822
 
 
823
    /**
 
824
     * Read the record from TABLE
 
825
     */
 
826
    pOp = pTrans1->getNdbOperation(tab.getName());      
 
827
    if (pOp == NULL) {
 
828
      ERR(pTrans1->getNdbError());
 
829
      goto close_all;
 
830
    }
 
831
    
 
832
    check = pOp->readTuple();
 
833
    if( check == -1 ) {
 
834
      ERR(pTrans1->getNdbError());
 
835
      goto close_all;
 
836
    }
 
837
    
 
838
    // Define primary keys
 
839
#if VERBOSE
 
840
    printf("PK: ");
 
841
#endif
 
842
    for(a = 0; a<tab.getNoOfColumns(); a++){
 
843
      const NdbDictionary::Column* attr = tab.getColumn(a);
 
844
      if (attr->getPrimaryKey() == true){
 
845
        if (pOp->equal(attr->getName(), row.attributeStore(a)->aRef()) != 0){
 
846
          ERR(pTrans1->getNdbError());
 
847
          goto close_all;
 
848
        }
 
849
#if VERBOSE
 
850
        printf("%s = %d: ", attr->getName(), row.attributeStore(a)->aRef());
 
851
#endif
 
852
      }
 
853
    }
 
854
#if VERBOSE
 
855
    printf("\n");
 
856
#endif
 
857
    // Read all attributes
 
858
#if VERBOSE
 
859
    printf("Reading %u attributes: ", tab.getNoOfColumns());
 
860
#endif
 
861
    for(a = 0; a<tab.getNoOfColumns(); a++){
 
862
      if((tabRow.attributeStore(a) = 
 
863
          pOp->getValue(tab.getColumn(a)->getName())) == 0) {
 
864
        ERR(pTrans1->getNdbError());
 
865
        goto close_all;
 
866
      }
 
867
#if VERBOSE
 
868
      printf("%s ", tab.getColumn(a)->getName());
 
869
#endif
 
870
    }
 
871
#if VERBOSE
 
872
    printf("\n");
 
873
#endif
 
874
 
 
875
    /**
 
876
     * Read the record from INDEX_TABLE
 
877
     */    
 
878
    NdbIndexOperation* pIndexOp= NULL;
 
879
    NdbIndexScanOperation *pScanOp= NULL;
 
880
    NdbOperation *pIOp= 0;
 
881
 
 
882
    bool null_found= false;
 
883
    for(a = 0; a<(int)pIndex->getNoOfColumns(); a++){
 
884
      const NdbDictionary::Column *  col = pIndex->getColumn(a);
 
885
      
 
886
      if (row.attributeStore(col->getName())->isNULL())
 
887
      {
 
888
        null_found= true;
 
889
        break;
 
890
      }
 
891
    }
 
892
    
 
893
    const char * tabName= tab.getName();
 
894
    if(!null_found)
 
895
    {
 
896
      if (indexType == NdbDictionary::Index::UniqueHashIndex) {
 
897
        pIOp= pIndexOp= pTrans1->getNdbIndexOperation(indexName, tabName);
 
898
      } else {
 
899
        pIOp= pScanOp= pTrans1->getNdbIndexScanOperation(indexName, tabName);
 
900
      }
 
901
      
 
902
      if (pIOp == NULL) {
 
903
        ERR(pTrans1->getNdbError());
 
904
        goto close_all;
 
905
      }
 
906
    
 
907
      {
 
908
        bool not_ok;
 
909
        if (pIndexOp) {
 
910
          not_ok = pIndexOp->readTuple() == -1;
 
911
        } else {
 
912
          not_ok = pScanOp->readTuples();
 
913
        }
 
914
        
 
915
        if( not_ok ) {
 
916
          ERR(pTrans1->getNdbError());
 
917
          goto close_all;
 
918
        }
 
919
      }
 
920
    
 
921
    // Define primary keys for index
 
922
#if VERBOSE
 
923
      printf("SI: ");
 
924
#endif
 
925
      for(a = 0; a<(int)pIndex->getNoOfColumns(); a++){
 
926
        const NdbDictionary::Column *  col = pIndex->getColumn(a);
 
927
        
 
928
        int r;
 
929
        if ( !row.attributeStore(col->getName())->isNULL() ) {
 
930
          if(pIOp->equal(col->getName(), 
 
931
                         row.attributeStore(col->getName())->aRef()) != 0){
 
932
            ERR(pTrans1->getNdbError());
 
933
            goto close_all;
 
934
          }
 
935
        }
 
936
#if VERBOSE
 
937
        printf("%s = %d: ", col->getName(), row.attributeStore(a)->aRef());
 
938
#endif
 
939
      }
 
940
#if VERBOSE
 
941
      printf("\n");
 
942
#endif
 
943
      
 
944
      // Read all attributes
 
945
#if VERBOSE
 
946
      printf("Reading %u attributes: ", tab.getNoOfColumns());
 
947
#endif
 
948
      for(a = 0; a<tab.getNoOfColumns(); a++){
 
949
        void* pCheck;
 
950
        
 
951
        pCheck= indexRow.attributeStore(a)= 
 
952
          pIOp->getValue(tab.getColumn(a)->getName());
 
953
        
 
954
        if(pCheck == NULL) {
 
955
          ERR(pTrans1->getNdbError());
 
956
          goto close_all;
 
957
        }
 
958
#if VERBOSE
 
959
        printf("%s ", tab.getColumn(a)->getName());
 
960
#endif
 
961
      }
 
962
    }
 
963
#if VERBOSE
 
964
    printf("\n");
 
965
#endif
 
966
    scanTrans->refresh();
 
967
    check = pTrans1->execute(Commit, AbortOnError);
 
968
    if( check == -1 ) {
 
969
      const NdbError err = pTrans1->getNdbError();
 
970
      
 
971
      if (err.status == NdbError::TemporaryError){
 
972
        ERR(err);
 
973
        pNdb->closeTransaction(pTrans1);
 
974
        NdbSleep_MilliSleep(50);
 
975
        retryAttempt++;
 
976
        continue;
 
977
      }
 
978
      ndbout << "Error when comparing records - normal op" << endl;
 
979
      ERR(err);
 
980
      ndbout << "row: " << row.c_str().c_str() << endl;
 
981
      goto close_all;
 
982
    } 
 
983
    
 
984
    /** 
 
985
     * Compare the two rows
 
986
     */ 
 
987
    if(!null_found){
 
988
      if (pScanOp) {
 
989
        if (pScanOp->nextResult() != 0){
 
990
          const NdbError err = pTrans1->getNdbError();
 
991
          ERR(err);
 
992
          ndbout << "Error when comparing records - index op next_result missing" << endl;
 
993
          ndbout << "row: " << row.c_str().c_str() << endl;
 
994
          goto close_all;
 
995
        }
 
996
      }
 
997
      if (!(tabRow.c_str() == indexRow.c_str())){
 
998
        ndbout << "Error when comapring records" << endl;
 
999
        ndbout << " tabRow: \n" << tabRow.c_str().c_str() << endl;
 
1000
        ndbout << " indexRow: \n" << indexRow.c_str().c_str() << endl;
 
1001
        goto close_all;
 
1002
      }
 
1003
      if (pScanOp) {
 
1004
        if (pScanOp->nextResult() == 0){
 
1005
          ndbout << "Error when comparing records - index op next_result to many" << endl;
 
1006
          ndbout << "row: " << row.c_str().c_str() << endl;
 
1007
          goto close_all;
 
1008
        }
 
1009
      }
 
1010
    }
 
1011
    return_code= NDBT_OK;
 
1012
    goto close_all;
 
1013
  }
 
1014
  
 
1015
close_all:
 
1016
  if (pTrans1)
 
1017
    pNdb->closeTransaction(pTrans1);
 
1018
  
 
1019
  return return_code;
 
1020
}
 
1021
 
 
1022
int 
 
1023
UtilTransactions::verifyOrderedIndex(Ndb* pNdb,
 
1024
                                     const NdbDictionary::Index* pIndex,
 
1025
                                     int parallelism,
 
1026
                                     bool transactional){
 
1027
  
 
1028
  int                  retryAttempt = 0;
 
1029
  const int            retryMax = 100;
 
1030
  int                  check;
 
1031
  NdbScanOperation     *pOp;
 
1032
  NdbIndexScanOperation * iop = 0;
 
1033
 
 
1034
  NDBT_ResultRow       scanRow(tab);
 
1035
  NDBT_ResultRow       pkRow(tab);
 
1036
  NDBT_ResultRow       indexRow(tab);
 
1037
  const char * indexName = pIndex->getName();
 
1038
 
 
1039
  int res;
 
1040
  parallelism = 1;
 
1041
  
 
1042
  while (true){
 
1043
 
 
1044
    if (retryAttempt >= retryMax){
 
1045
      g_info << "ERROR: has retried this operation " << retryAttempt 
 
1046
             << " times, failing!" << endl;
 
1047
      return NDBT_FAILED;
 
1048
    }
 
1049
 
 
1050
    pTrans = pNdb->startTransaction();
 
1051
    if (pTrans == NULL) {
 
1052
      const NdbError err = pNdb->getNdbError();
 
1053
 
 
1054
      if (err.status == NdbError::TemporaryError){
 
1055
        ERR(err);
 
1056
        NdbSleep_MilliSleep(50);
 
1057
        retryAttempt++;
 
1058
        continue;
 
1059
      }
 
1060
      ERR(err);
 
1061
      return NDBT_FAILED;
 
1062
    }
 
1063
 
 
1064
    pOp = pTrans->getNdbScanOperation(tab.getName());   
 
1065
    if (pOp == NULL) {
 
1066
      ERR(pTrans->getNdbError());
 
1067
      closeTransaction(pNdb);
 
1068
      return NDBT_FAILED;
 
1069
    }
 
1070
 
 
1071
    if( pOp->readTuples(NdbScanOperation::LM_Read, 0, parallelism) ) {
 
1072
      ERR(pTrans->getNdbError());
 
1073
      closeTransaction(pNdb);
 
1074
      return NDBT_FAILED;
 
1075
    }
 
1076
 
 
1077
    check = pOp->interpret_exit_ok();
 
1078
    if( check == -1 ) {
 
1079
      ERR(pTrans->getNdbError());
 
1080
      closeTransaction(pNdb);
 
1081
      return NDBT_FAILED;
 
1082
    }
 
1083
 
 
1084
    if(get_values(pOp, scanRow))
 
1085
    {
 
1086
      abort();
 
1087
    }
 
1088
 
 
1089
    check = pTrans->execute(NoCommit, AbortOnError);
 
1090
    if( check == -1 ) {
 
1091
      const NdbError err = pTrans->getNdbError();
 
1092
      
 
1093
      if (err.status == NdbError::TemporaryError){
 
1094
        ERR(err);
 
1095
        closeTransaction(pNdb);
 
1096
        NdbSleep_MilliSleep(50);
 
1097
        retryAttempt++;
 
1098
        continue;
 
1099
      }
 
1100
      ERR(err);
 
1101
      closeTransaction(pNdb);
 
1102
      return NDBT_FAILED;
 
1103
    }
 
1104
        
 
1105
    int eof;
 
1106
    int rows = 0;
 
1107
    while(check == 0 && (eof = pOp->nextResult()) == 0){
 
1108
      rows++;
 
1109
 
 
1110
      bool null_found= false;
 
1111
      for(int a = 0; a<(int)pIndex->getNoOfColumns(); a++){
 
1112
        const NdbDictionary::Column *  col = pIndex->getColumn(a);
 
1113
        if (scanRow.attributeStore(col->getName())->isNULL())
 
1114
        {
 
1115
          null_found= true;
 
1116
          break;
 
1117
        }
 
1118
      }
 
1119
      
 
1120
      // Do pk lookup
 
1121
      NdbOperation * pk = pTrans->getNdbOperation(tab.getName());
 
1122
      if(!pk || pk->readTuple())
 
1123
        goto error;
 
1124
      if(equal(&tab, pk, scanRow) || get_values(pk, pkRow))
 
1125
        goto error;
 
1126
 
 
1127
      if(!null_found)
 
1128
      {
 
1129
        if(!iop && (iop= pTrans->getNdbIndexScanOperation(indexName, 
 
1130
                                                          tab.getName())))
 
1131
        {
 
1132
          if(iop->readTuples(NdbScanOperation::LM_CommittedRead, 
 
1133
                             parallelism))
 
1134
            goto error;
 
1135
          iop->interpret_exit_ok();
 
1136
          if(get_values(iop, indexRow))
 
1137
            goto error;
 
1138
        }
 
1139
        else if(!iop || iop->reset_bounds())
 
1140
        {
 
1141
          goto error;
 
1142
        }
 
1143
        
 
1144
        if(equal(pIndex, iop, scanRow))
 
1145
          goto error;
 
1146
      }     
 
1147
 
 
1148
      check = pTrans->execute(NoCommit, AbortOnError);
 
1149
      if(check)
 
1150
        goto error;
 
1151
 
 
1152
      if(scanRow.c_str() != pkRow.c_str()){
 
1153
        g_err << "Error when comapring records" << endl;
 
1154
        g_err << " scanRow: \n" << scanRow.c_str().c_str() << endl;
 
1155
        g_err << " pkRow: \n" << pkRow.c_str().c_str() << endl;
 
1156
        closeTransaction(pNdb);
 
1157
        return NDBT_FAILED;
 
1158
      }
 
1159
 
 
1160
      if(!null_found)
 
1161
      {
 
1162
        
 
1163
        if((res= iop->nextResult()) != 0){
 
1164
          g_err << "Failed to find row using index: " << res << endl;
 
1165
          ERR(pTrans->getNdbError());
 
1166
          closeTransaction(pNdb);
 
1167
          return NDBT_FAILED;
 
1168
        }
 
1169
        
 
1170
        if(scanRow.c_str() != indexRow.c_str()){
 
1171
          g_err << "Error when comapring records" << endl;
 
1172
          g_err << " scanRow: \n" << scanRow.c_str().c_str() << endl;
 
1173
          g_err << " indexRow: \n" << indexRow.c_str().c_str() << endl;
 
1174
          closeTransaction(pNdb);
 
1175
          return NDBT_FAILED;
 
1176
        }
 
1177
        
 
1178
        if(iop->nextResult() == 0){
 
1179
          g_err << "Found extra row!!" << endl;
 
1180
          g_err << " indexRow: \n" << indexRow.c_str().c_str() << endl;
 
1181
          closeTransaction(pNdb);
 
1182
          return NDBT_FAILED;
 
1183
        }
 
1184
      }
 
1185
    }
 
1186
    
 
1187
    if (eof == -1 || check == -1) {
 
1188
  error:
 
1189
      const NdbError err = pTrans->getNdbError();
 
1190
      
 
1191
      if (err.status == NdbError::TemporaryError){
 
1192
        ERR(err);
 
1193
        iop = 0;
 
1194
        closeTransaction(pNdb);
 
1195
        NdbSleep_MilliSleep(50);
 
1196
        retryAttempt++;
 
1197
        rows--;
 
1198
        continue;
 
1199
      }
 
1200
      ERR(err);
 
1201
      closeTransaction(pNdb);
 
1202
      return NDBT_FAILED;
 
1203
    }
 
1204
      
 
1205
    closeTransaction(pNdb);
 
1206
    
 
1207
    return NDBT_OK;
 
1208
  }
 
1209
  return NDBT_FAILED;
 
1210
}
 
1211
 
 
1212
int
 
1213
UtilTransactions::get_values(NdbOperation* op, NDBT_ResultRow& dst)
 
1214
{
 
1215
  for (int a = 0; a < tab.getNoOfColumns(); a++){
 
1216
    NdbRecAttr*& ref= dst.attributeStore(a);
 
1217
    if ((ref= op->getValue(a)) == 0)
 
1218
    {
 
1219
      return NDBT_FAILED;
 
1220
    }
 
1221
  }
 
1222
  return 0;
 
1223
}
 
1224
 
 
1225
int
 
1226
UtilTransactions::equal(const NdbDictionary::Index* pIndex, 
 
1227
                        NdbOperation* op, const NDBT_ResultRow& src)
 
1228
{
 
1229
  for(Uint32 a = 0; a<pIndex->getNoOfColumns(); a++){
 
1230
    const NdbDictionary::Column *  col = pIndex->getColumn(a);
 
1231
    if(op->equal(col->getName(), 
 
1232
                 src.attributeStore(col->getName())->aRef()) != 0){
 
1233
      return NDBT_FAILED;
 
1234
    }
 
1235
  }
 
1236
  return 0;
 
1237
}
 
1238
 
 
1239
int
 
1240
UtilTransactions::equal(const NdbDictionary::Table* pTable, 
 
1241
                        NdbOperation* op, const NDBT_ResultRow& src)
 
1242
{
 
1243
  for(Uint32 a = 0; a<tab.getNoOfColumns(); a++){
 
1244
    const NdbDictionary::Column* attr = tab.getColumn(a);
 
1245
    if (attr->getPrimaryKey() == true){
 
1246
      if (op->equal(attr->getName(), src.attributeStore(a)->aRef()) != 0){
 
1247
        return NDBT_FAILED;
 
1248
      }
 
1249
    }
 
1250
  }
 
1251
  return 0;
 
1252
}
 
1253
 
 
1254
NdbScanOperation*
 
1255
UtilTransactions::getScanOperation(NdbConnection* pTrans)
 
1256
{
 
1257
  return (NdbScanOperation*)
 
1258
    getOperation(pTrans, NdbOperation::OpenScanRequest);
 
1259
}
 
1260
 
 
1261
NdbOperation*
 
1262
UtilTransactions::getOperation(NdbConnection* pTrans,
 
1263
                               NdbOperation::OperationType type)
 
1264
{
 
1265
  switch(type){
 
1266
  case NdbOperation::ReadRequest:
 
1267
  case NdbOperation::ReadExclusive:
 
1268
    if(idx)
 
1269
    {
 
1270
      switch(idx->getType()){
 
1271
      case NdbDictionary::Index::UniqueHashIndex:
 
1272
        return pTrans->getNdbIndexOperation(idx->getName(), tab.getName());
 
1273
      case NdbDictionary::Index::OrderedIndex:
 
1274
        return pTrans->getNdbIndexScanOperation(idx->getName(), tab.getName());
 
1275
      }
 
1276
    }
 
1277
  case NdbOperation::InsertRequest:
 
1278
  case NdbOperation::WriteRequest:
 
1279
    return pTrans->getNdbOperation(tab.getName());
 
1280
  case NdbOperation::UpdateRequest:
 
1281
  case NdbOperation::DeleteRequest:
 
1282
    if(idx)
 
1283
    {
 
1284
      switch(idx->getType()){
 
1285
      case NdbDictionary::Index::UniqueHashIndex:
 
1286
        return pTrans->getNdbIndexOperation(idx->getName(), tab.getName());
 
1287
      }
 
1288
    }
 
1289
    return pTrans->getNdbOperation(tab.getName());
 
1290
  case NdbOperation::OpenScanRequest:
 
1291
    if(idx)
 
1292
    {
 
1293
      switch(idx->getType()){
 
1294
      case NdbDictionary::Index::OrderedIndex:
 
1295
        return pTrans->getNdbIndexScanOperation(idx->getName(), tab.getName());
 
1296
      }
 
1297
    }
 
1298
    return pTrans->getNdbScanOperation(tab.getName());
 
1299
  case NdbOperation::OpenRangeScanRequest:
 
1300
    if(idx)
 
1301
    {
 
1302
      switch(idx->getType()){
 
1303
      case NdbDictionary::Index::OrderedIndex:
 
1304
        return pTrans->getNdbIndexScanOperation(idx->getName(), tab.getName());
 
1305
      }
 
1306
    }
 
1307
    return 0;
 
1308
  }
 
1309
}
 
1310
 
 
1311
#include <HugoOperations.hpp>
 
1312
 
 
1313
int
 
1314
UtilTransactions::closeTransaction(Ndb* pNdb)
 
1315
{
 
1316
  if (pTrans != NULL){
 
1317
    pNdb->closeTransaction(pTrans);
 
1318
    pTrans = NULL;
 
1319
  }
 
1320
  return 0;
 
1321
}
 
1322
 
 
1323
int 
 
1324
UtilTransactions::compare(Ndb* pNdb, const char* tab_name2, int flags){
 
1325
 
 
1326
 
 
1327
  NdbError err;
 
1328
  int return_code= 0, row_count= 0;
 
1329
  int retryAttempt = 0, retryMax = 10;
 
1330
 
 
1331
  HugoCalculator calc(tab);
 
1332
  NDBT_ResultRow row(tab);
 
1333
  const NdbDictionary::Table* tmp= pNdb->getDictionary()->getTable(tab_name2);
 
1334
  if(tmp == 0)
 
1335
  {
 
1336
    g_err << "Unable to lookup table: " << tab_name2
 
1337
          << endl << pNdb->getDictionary()->getNdbError() << endl;
 
1338
    return -1;
 
1339
  }
 
1340
  const NdbDictionary::Table& tab2= *tmp;
 
1341
 
 
1342
  HugoOperations cmp(tab2);
 
1343
  UtilTransactions count(tab2);
 
1344
 
 
1345
  while (true){
 
1346
loop:    
 
1347
    if (retryAttempt++ >= retryMax){
 
1348
      g_err << "ERROR: compare has retried this operation " << retryAttempt 
 
1349
             << " times, failing!" << endl;
 
1350
      return -1;
 
1351
    }
 
1352
 
 
1353
    NdbScanOperation *pOp= 0;
 
1354
    pTrans = pNdb->startTransaction();
 
1355
    if (pTrans == NULL) {
 
1356
      err = pNdb->getNdbError();
 
1357
      goto error;
 
1358
    }
 
1359
 
 
1360
    pOp= pTrans->getNdbScanOperation(tab.getName());    
 
1361
    if (pOp == NULL) {
 
1362
      ERR(err= pTrans->getNdbError());
 
1363
      goto error;
 
1364
    }
 
1365
 
 
1366
    if( pOp->readTuples(NdbScanOperation::LM_Read) ) {
 
1367
      ERR(err= pTrans->getNdbError());
 
1368
      goto error;
 
1369
    }
 
1370
 
 
1371
    if( pOp->interpret_exit_ok() == -1 ) {
 
1372
      ERR(err= pTrans->getNdbError());
 
1373
      goto error;
 
1374
    }  
 
1375
 
 
1376
    // Read all attributes
 
1377
    {
 
1378
      for (int a = 0; a < tab.getNoOfColumns(); a++){
 
1379
        if ((row.attributeStore(a) = 
 
1380
             pOp->getValue(tab.getColumn(a)->getName())) == 0) {
 
1381
          ERR(err= pTrans->getNdbError());
 
1382
          goto error;
 
1383
        }
 
1384
      }
 
1385
    }
 
1386
    
 
1387
    if( pTrans->execute(NoCommit, AbortOnError) == -1 ) {
 
1388
      ERR(err= pTrans->getNdbError());
 
1389
      goto error;
 
1390
    }
 
1391
  
 
1392
    row_count= 0;
 
1393
    {
 
1394
      int eof;
 
1395
      while((eof = pOp->nextResult(true)) == 0)
 
1396
      {
 
1397
        do {
 
1398
          row_count++;
 
1399
          if(cmp.startTransaction(pNdb) != NDBT_OK)
 
1400
          {
 
1401
            ERR(err= pNdb->getNdbError());
 
1402
            goto error;
 
1403
          }
 
1404
          int rowNo= calc.getIdValue(&row);
 
1405
          if(cmp.pkReadRecord(pNdb, rowNo, 1) != NDBT_OK)
 
1406
          {
 
1407
            ERR(err= cmp.getTransaction()->getNdbError());
 
1408
            goto error;
 
1409
          }
 
1410
          if(cmp.execute_Commit(pNdb) != NDBT_OK ||
 
1411
             cmp.getTransaction()->getNdbError().code)
 
1412
          {
 
1413
            ERR(err= cmp.getTransaction()->getNdbError());
 
1414
            goto error;
 
1415
          }
 
1416
          if(row != cmp.get_row(0))
 
1417
          {
 
1418
            g_err << "COMPARE FAILED" << endl;
 
1419
            g_err << row << endl;
 
1420
            g_err << cmp.get_row(0) << endl;
 
1421
            return_code++;
 
1422
          }
 
1423
          retryAttempt= 0;
 
1424
          cmp.closeTransaction(pNdb);
 
1425
        } while((eof = pOp->nextResult(false)) == 0);
 
1426
      }
 
1427
      if (eof == -1) 
 
1428
      {
 
1429
        err = pTrans->getNdbError();
 
1430
        goto error;
 
1431
      }
 
1432
    }
 
1433
    
 
1434
    closeTransaction(pNdb);
 
1435
    
 
1436
    g_info << row_count << " rows compared" << endl;
 
1437
    {
 
1438
      int row_count2;
 
1439
      if(count.selectCount(pNdb, 0, &row_count2) != NDBT_OK)
 
1440
      {
 
1441
        g_err << "Failed to count rows in tab_name2" << endl;
 
1442
        return -1;
 
1443
      }
 
1444
      
 
1445
      g_info << row_count2 << " rows in tab_name2 - failed " << return_code
 
1446
             << endl;
 
1447
      return (row_count == row_count2 ? return_code : 1);
 
1448
    }
 
1449
error:
 
1450
    if(err.status == NdbError::TemporaryError)
 
1451
    {
 
1452
      g_err << err << endl;
 
1453
      NdbSleep_MilliSleep(50);
 
1454
      closeTransaction(pNdb);
 
1455
      if(cmp.getTransaction())
 
1456
        cmp.closeTransaction(pNdb);
 
1457
      
 
1458
      goto loop;
 
1459
    }
 
1460
    g_err << "ERROR" << endl;
 
1461
    g_err << err << endl;
 
1462
    
 
1463
    break;
 
1464
  }
 
1465
 
 
1466
close:
 
1467
  closeTransaction(pNdb);
 
1468
  
 
1469
  return return_code;
 
1470
}
 
1471