UtilTransactions.cpp
上传用户:romrleung
上传日期:2022-05-23
资源大小:18897k
文件大小:35k
源码类别:

MySQL数据库

开发平台:

Visual C++

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