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

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