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