List:Commits« Previous MessageNext Message »
From:Pekka Nousiainen Date:December 21 2009 3:36pm
Subject:bzr commit into mysql-5.1-telco-6.2 branch (pekka:3067) Bug#34348
View as plain text  
#At file:///export/space/pekka/ndb/version/my51-bug34348/ based on revid:jonas@stripped

 3067 Pekka Nousiainen	2009-12-21
      bug#34348 01_acc.diff
      In ACC, hash expand fails if fragment top level directory is full (256).
      Instead of crash, set a flag on fragment and return error on any insert.
      The flag is cleared when a hash shrink takes place.

    modified:
      storage/ndb/src/kernel/blocks/ERROR_codes.txt
      storage/ndb/src/kernel/blocks/dbacc/Dbacc.hpp
      storage/ndb/src/kernel/blocks/dbacc/DbaccMain.cpp
      storage/ndb/src/ndbapi/ndberror.c
      storage/ndb/test/include/HugoOperations.hpp
      storage/ndb/test/ndbapi/testBasic.cpp
      storage/ndb/test/src/HugoOperations.cpp
=== modified file 'storage/ndb/src/kernel/blocks/ERROR_codes.txt'
--- a/storage/ndb/src/kernel/blocks/ERROR_codes.txt	2009-10-26 20:02:17 +0000
+++ b/storage/ndb/src/kernel/blocks/ERROR_codes.txt	2009-12-21 15:35:52 +0000
@@ -601,3 +601,9 @@ LGMAN:
 TSMAN:
 -----
 16000: Fail to create data file
+
+ACC bug#34348
+-------------
+3002: limit frags to 2 directory pages (instead of 256)
+      print (if VM_TRACE) LH variables at expand and shrink
+      apply before mass data load, reset with error insert 0

=== modified file 'storage/ndb/src/kernel/blocks/dbacc/Dbacc.hpp'
--- a/storage/ndb/src/kernel/blocks/dbacc/Dbacc.hpp	2009-05-26 18:53:34 +0000
+++ b/storage/ndb/src/kernel/blocks/dbacc/Dbacc.hpp	2009-12-21 15:35:52 +0000
@@ -1,3 +1,4 @@
+/** **/
 /*
    Copyright (C) 2003 MySQL AB
     All rights reserved. Use is subject to license terms.
@@ -180,6 +181,7 @@ ndbout << "Ptr: " << ptr.p->word32 << " 
 #define ZWRITE_ERROR 630
 #define ZTO_OP_STATE_ERROR 631
 #define ZTOO_EARLY_ACCESS_ERROR 632
+#define ZDIR_RANGE_FULL_ERROR 633 // on fragment
 #endif
 
 class ElementHeader {
@@ -472,6 +474,11 @@ struct Fragmentrec {
 // flag to avoid accessing table record if no char attributes
 //-----------------------------------------------------------------------------
   Uint8 hasCharAttr;
+
+//-----------------------------------------------------------------------------
+// flag to mark that execEXPANDCHECK2 has failed due to DirRange full
+//-----------------------------------------------------------------------------
+  Uint8 dirRangeFull;
 };
 
   typedef Ptr<Fragmentrec> FragmentrecPtr;
@@ -849,6 +856,12 @@ private:
   void initData();
   void initRecords();
 
+#ifdef VM_TRACE
+  void debug_lh_vars(const char* where);
+#else
+  void debug_lh_vars(const char* where) {}
+#endif
+
   // Variables
 /* --------------------------------------------------------------------------------- */
 /* DIRECTORY RANGE                                                                   */

=== modified file 'storage/ndb/src/kernel/blocks/dbacc/DbaccMain.cpp'
--- a/storage/ndb/src/kernel/blocks/dbacc/DbaccMain.cpp	2009-09-22 13:04:32 +0000
+++ b/storage/ndb/src/kernel/blocks/dbacc/DbaccMain.cpp	2009-12-21 15:35:52 +0000
@@ -1553,6 +1553,12 @@ void Dbacc::insertExistElemLab(Signal* s
 /* --------------------------------------------------------------------------------- */
 void Dbacc::insertelementLab(Signal* signal) 
 {
+  if (unlikely(fragrecptr.p->dirRangeFull))
+  {
+    jam();
+    acckeyref1Lab(signal, ZDIR_RANGE_FULL_ERROR);
+    return;
+  }
   if (fragrecptr.p->firstOverflowRec == RNIL) {
     jam();
     allocOverflowPage(signal);
@@ -5218,6 +5224,12 @@ void Dbacc::execEXPANDCHECK2(Signal* sig
     /*       THE SLACK HAS IMPROVED AND IS NOW ACCEPTABLE AND WE    */
     /*       CAN FORGET ABOUT THE EXPAND PROCESS.                   */
     /*--------------------------------------------------------------*/
+    if (ERROR_INSERTED(3002))
+      debug_lh_vars("SLK");
+    if (fragrecptr.p->dirRangeFull == ZTRUE) {
+      jam();
+      fragrecptr.p->dirRangeFull = ZFALSE;
+    }
     return;
   }//if
   if (fragrecptr.p->firstOverflowRec == RNIL) {
@@ -5265,7 +5277,20 @@ void Dbacc::execEXPANDCHECK2(Signal* sig
   ptrNull(newDirptr);
   texpDirRangeIndex = texpDirInd >> 8;
   ptrCheckGuard(expDirRangePtr, cdirrangesize, dirRange);
-  arrGuard(texpDirRangeIndex, 256);
+  Uint32 max_dir_range_size = 256;
+  if (ERROR_INSERTED(3002)) {
+      debug_lh_vars("EXP");
+      max_dir_range_size = 2;
+  }
+  if (texpDirRangeIndex >= max_dir_range_size) {
+    jam();
+    ndbrequire(texpDirRangeIndex == max_dir_range_size);
+    if (fragrecptr.p->dirRangeFull == ZFALSE) {
+      jam();
+      fragrecptr.p->dirRangeFull = ZTRUE;
+    }
+    return;
+  }
   expDirptr.i = expDirRangePtr.p->dirArray[texpDirRangeIndex];
   if (expDirptr.i == RNIL) {
     jam();
@@ -5802,6 +5827,13 @@ void Dbacc::execSHRINKCHECK2(Signal* sig
     jam();
     fragrecptr.p->p--;
   }//if
+  
+  if (ERROR_INSERTED(3002))
+    debug_lh_vars("SHR");
+  if (fragrecptr.p->dirRangeFull == ZTRUE) {
+    jam();
+    fragrecptr.p->dirRangeFull = ZFALSE;
+  }
 
   /*--------------------------------------------------------------------------*/
   /*       WE START BY FINDING THE NECESSARY INFORMATION OF THE BUCKET TO BE  */
@@ -6192,6 +6224,7 @@ void Dbacc::initFragGeneral(FragmentrecP
 
   regFragPtr.p->activeDataPage = 0;
   regFragPtr.p->hasCharAttr = ZFALSE;
+  regFragPtr.p->dirRangeFull = ZFALSE;
   regFragPtr.p->nextAllocPage = 0;
   regFragPtr.p->fragState = FREEFRAG;
 }//Dbacc::initFragGeneral()
@@ -8502,3 +8535,25 @@ Dbacc::execREAD_PSEUDO_REQ(Signal* signa
   //  signal->theData[0] = src[0];
   //  signal->theData[1] = src[1];
 }
+
+#ifdef VM_TRACE
+void
+Dbacc::debug_lh_vars(const char* where)
+{
+  Uint32 b = fragrecptr.p->maxp + fragrecptr.p->p;
+  Uint32 di = b >> fragrecptr.p->k;
+  Uint32 ri = di >> 8;
+  ndbout
+    << "DBACC: " << where << ":"
+    << " frag:" << fragrecptr.p->myTableId
+    << "/" << fragrecptr.p->myfid
+    << " slack:" << (Int32)fragrecptr.p->slack
+    << "/" << fragrecptr.p->slackCheck
+    << " maxp:" << fragrecptr.p->maxp
+    << " p:" << fragrecptr.p->p
+    << " di:" << di
+    << " ri:" << ri
+    << " full:" << fragrecptr.p->dirRangeFull
+    << "\n";
+}
+#endif

=== modified file 'storage/ndb/src/ndbapi/ndberror.c'
--- a/storage/ndb/src/ndbapi/ndberror.c	2009-10-01 22:18:31 +0000
+++ b/storage/ndb/src/ndbapi/ndberror.c	2009-12-21 15:35:52 +0000
@@ -202,6 +202,7 @@ ErrorBundle ErrorCodes[] = {
   { 623,  HA_ERR_RECORD_FILE_FULL, IS, "623" },
   { 624,  HA_ERR_RECORD_FILE_FULL, IS, "624" },
   { 625,  HA_ERR_INDEX_FILE_FULL, IS, "Out of memory in Ndb Kernel, hash index part (increase IndexMemory)" },
+  { 633,  HA_ERR_INDEX_FILE_FULL, IS, "Table fragment hash index has reached maximum possible size" },
   { 640,  DMEC, IS, "Too many hash indexes (should not happen)" },
   { 826,  HA_ERR_RECORD_FILE_FULL, IS, "Too many tables and attributes (increase MaxNoOfAttributes or MaxNoOfTables)" },
   { 827,  HA_ERR_RECORD_FILE_FULL, IS, "Out of memory in Ndb Kernel, table data (increase DataMemory)" },

=== modified file 'storage/ndb/test/include/HugoOperations.hpp'
--- a/storage/ndb/test/include/HugoOperations.hpp	2009-05-26 18:53:34 +0000
+++ b/storage/ndb/test/include/HugoOperations.hpp	2009-12-21 15:35:52 +0000
@@ -124,6 +124,9 @@ public:  
   
   int wait_async(Ndb*, int timeout = -1);
 
+  const NdbError& getNdbError() const;
+  void setQuiet() { m_quiet = true; }
+
 protected:
   void allocRows(int rows);
   void deallocRows();
@@ -142,6 +145,10 @@ protected:
   int m_async_return;
   friend void HugoOperations_async_callback(int, NdbTransaction*, void*);
   void callback(int res, NdbTransaction*);
+
+  void setNdbError(const NdbError& error);
+  NdbError m_error;
+  bool m_quiet;
 };
 
 #endif

=== modified file 'storage/ndb/test/ndbapi/testBasic.cpp'
--- a/storage/ndb/test/ndbapi/testBasic.cpp	2009-10-20 12:44:56 +0000
+++ b/storage/ndb/test/ndbapi/testBasic.cpp	2009-12-21 15:35:52 +0000
@@ -21,6 +21,8 @@
 #include <HugoTransactions.hpp>
 #include <UtilTransactions.hpp>
 #include <NdbRestarter.hpp>
+#include <Bitmask.hpp>
+#include <random.h>
 
 #define GETNDB(ps) ((NDBT_NdbApiStep*)ps)->getNdb()
 
@@ -1658,6 +1660,234 @@ runDDInsertFailUpdateBatch(NDBT_Context*
   return result;
 }
 
+// Bug34348
+
+#define chk1(b) \
+  if (!(b)) { g_err << "ERR: " << step->getName() << " failed on line " << __LINE__ << endl; result = NDBT_FAILED; continue; }
+#define chk2(b, e) \
+  if (!(b)) { g_err << "ERR: " << step->getName() << " failed on line " << __LINE__ << ": " << e << endl; result = NDBT_FAILED; continue; }
+
+const char* tabname_bug34348 = "TBug34348";
+
+int
+runBug34348insert(NDBT_Context* ctx, NDBT_Step* step,
+                  HugoOperations& ops, int i, bool* rangeFull)
+{
+  const int rangeFullError = 633;
+  Ndb* pNdb = GETNDB(step);
+  int result = NDBT_OK;
+  while (result == NDBT_OK)
+  {
+    int code = 0;
+    chk2(ops.startTransaction(pNdb) == 0, ops.getNdbError());
+    chk2(ops.pkInsertRecord(pNdb, i, 1) == 0, ops.getNdbError());
+    chk2(ops.execute_Commit(pNdb) == 0 || (code = ops.getNdbError().code) == rangeFullError, ops.getNdbError());
+    ops.closeTransaction(pNdb);
+    *rangeFull = (code == rangeFullError);
+    break;
+  }
+  return result;
+}
+
+int
+runBug34348delete(NDBT_Context* ctx, NDBT_Step* step,
+                  HugoOperations& ops, int i)
+{
+  Ndb* pNdb = GETNDB(step);
+  int result = NDBT_OK;
+  while (result == NDBT_OK)
+  {
+    chk2(ops.startTransaction(pNdb) == 0, ops.getNdbError());
+    chk2(ops.pkDeleteRecord(pNdb, i, 1) == 0, ops.getNdbError());
+    chk2(ops.execute_Commit(pNdb) == 0, ops.getNdbError());
+    ops.closeTransaction(pNdb);
+    break;
+  }
+  return result;
+}
+
+int
+runBug34348(NDBT_Context* ctx, NDBT_Step* step)
+{
+  myRandom48Init(NdbTick_CurrentMillisecond());
+  Ndb* pNdb = GETNDB(step);
+  NdbDictionary::Dictionary* pDict = pNdb->getDictionary();
+  NdbRestarter restarter;
+  int result = NDBT_OK;
+  const int loops = ctx->getNumLoops();
+  const int errInsDBACC = 3002;
+  const int errInsCLEAR = 0;
+  Uint32* rowmask = 0;
+
+  while (result == NDBT_OK)
+  {
+    chk1(restarter.insertErrorInAllNodes(errInsDBACC) == 0);
+    ndbout << "error insert " << errInsDBACC << " done" << endl;
+
+    const NdbDictionary::Table* pTab = 0;
+    while (result == NDBT_OK)
+    {
+      (void)pDict->dropTable(tabname_bug34348);
+      NdbDictionary::Table tab(tabname_bug34348);
+      {
+        NdbDictionary::Column col("a");
+        col.setType(NdbDictionary::Column::Unsigned);
+        col.setPrimaryKey(true);
+        tab.addColumn(col);
+      }
+      {
+        NdbDictionary::Column col("b");
+        col.setType(NdbDictionary::Column::Unsigned);
+        col.setNullable(false);
+        tab.addColumn(col);
+      }
+      chk2(pDict->createTable(tab) == 0, pDict->getNdbError());
+      chk2((pTab = pDict->getTable(tabname_bug34348)) != 0, pDict->getNdbError());
+      break;
+    }
+
+    HugoOperations ops(*pTab);
+    ops.setQuiet();
+
+    int rowmaxprev = 0;
+    int loop = 0;
+    while (result == NDBT_OK && loop < loops)
+    {
+      ndbout << "loop:" << loop << endl;
+      int rowcnt = 0;
+
+      // fill up
+      while (result == NDBT_OK)
+      {
+        bool rangeFull;
+        chk1(runBug34348insert(ctx, step, ops, rowcnt, &rangeFull) == NDBT_OK);
+        if (rangeFull)
+        {
+          // 360449 (1 fragment)
+          ndbout << "dir range full at " << rowcnt << endl;
+          break;
+        }
+        rowcnt++;
+      }
+      chk1(result == NDBT_OK);
+      const int rowmax = rowcnt;
+
+      if (loop == 0)
+        rowmaxprev = rowmax;
+      else
+        chk2(rowmaxprev == rowmax, "rowmaxprev:" << rowmaxprev << " rowmax:" << rowmax);
+
+      const int sz = (rowmax + 31) / 32;
+      delete [] rowmask;
+      rowmask = new Uint32 [sz];
+      BitmaskImpl::clear(sz, rowmask);
+      {
+        int i;
+        for (i = 0; i < rowmax; i++)
+          BitmaskImpl::set(sz, rowmask, i);
+      }
+
+      // random delete until insert succeeds
+      while (result == NDBT_OK)
+      {
+        int i = myRandom48(rowmax);
+        if (!BitmaskImpl::get(sz, rowmask, i))
+          continue;
+        chk1(runBug34348delete(ctx, step, ops, i) == NDBT_OK);
+        BitmaskImpl::clear(sz, rowmask, i);
+        rowcnt--;
+        bool rangeFull;
+        chk1(runBug34348insert(ctx, step, ops, rowmax, &rangeFull) == NDBT_OK);
+        if (!rangeFull)
+        {
+          chk1(runBug34348delete(ctx, step, ops, rowmax) == NDBT_OK);
+          // 344063 (1 fragment)
+          ndbout << "dir range released at " << rowcnt << endl;
+          break;
+        }
+      }
+      chk1(result == NDBT_OK);
+      assert(BitmaskImpl::count(sz, rowmask)== rowcnt);
+
+      // delete about 1/2 remaining
+      while (result == NDBT_OK)
+      {
+        int i;
+        for (i = 0; result == NDBT_OK && i < rowmax; i++)
+        {
+          if (!BitmaskImpl::get(sz, rowmask, i))
+            continue;
+          if (myRandom48(100) < 50)
+            continue;
+          chk1(runBug34348delete(ctx, step, ops, i) == NDBT_OK);
+          BitmaskImpl::clear(sz, rowmask, i);
+          rowcnt--;
+        }
+        ndbout << "deleted down to " << rowcnt << endl;
+        break;
+      }
+      chk1(result == NDBT_OK);
+      assert(BitmaskImpl::count(sz, rowmask)== rowcnt);
+
+      // insert until full again
+      while (result == NDBT_OK)
+      {
+        int i;
+        for (i = 0; result == NDBT_OK && i < rowmax; i++)
+        {
+          if (BitmaskImpl::get(sz, rowmask, i))
+            continue;
+          bool rangeFull;
+          chk1(runBug34348insert(ctx, step, ops, i, &rangeFull) == NDBT_OK);
+          // assume all can be inserted back
+          chk2(!rangeFull, "dir range full too early at " << rowcnt);
+          BitmaskImpl::set(sz, rowmask, i);
+          rowcnt++;
+        }
+        chk1(result == NDBT_OK);
+        ndbout << "inserted all back to " << rowcnt << endl;
+        break;
+      }
+      chk1(result == NDBT_OK);
+      assert(BitmaskImpl::count(sz, rowmask)== rowcnt);
+
+      // delete all
+      while (result == NDBT_OK)
+      {
+        int i;
+        for (i = 0; result == NDBT_OK && i < rowmax; i++)
+        {
+          if (!BitmaskImpl::get(sz, rowmask, i))
+            continue;
+          chk1(runBug34348delete(ctx, step, ops, i) == NDBT_OK);
+          BitmaskImpl::clear(sz, rowmask, i);
+          rowcnt--;
+        }
+        ndbout << "deleted all" << endl;
+        break;
+      }
+      chk1(result == NDBT_OK);
+      assert(BitmaskImpl::count(sz, rowmask)== rowcnt);
+      assert(rowcnt == 0);
+
+      loop++;
+    }
+
+    chk2(pDict->dropTable(tabname_bug34348) == 0, pDict->getNdbError());
+
+    chk1(restarter.insertErrorInAllNodes(errInsCLEAR) == 0);
+    ndbout << "error insert clear done" << endl;
+    break;
+  }
+
+  if (result != NDBT_OK && restarter.insertErrorInAllNodes(errInsCLEAR) != 0)
+    g_err << "error insert clear failed" << endl;
+
+  delete [] rowmask;
+  rowmask = 0;
+  return result;
+}
+
 template class Vector<NdbRecAttr*>;
 
 NDBT_TESTSUITE(testBasic);
@@ -1959,6 +2189,12 @@ TESTCASE("DDInsertFailUpdateBatch",
          "Verify DD insert failure effect on other ops in batch on same PK"){
   STEP(runDDInsertFailUpdateBatch);
 }
+
+TESTCASE("Bug34348",
+         "Test fragment directory range full in ACC.\n"
+         "NOTE: If interrupted, must clear error insert 3002 manually"){
+  STEP(runBug34348);
+}
 NDBT_TESTSUITE_END(testBasic);
 
 #if 0

=== modified file 'storage/ndb/test/src/HugoOperations.cpp'
--- a/storage/ndb/test/src/HugoOperations.cpp	2009-05-26 18:53:34 +0000
+++ b/storage/ndb/test/src/HugoOperations.cpp	2009-12-21 15:35:52 +0000
@@ -18,6 +18,13 @@
 
 #include <HugoOperations.hpp>
 
+#undef ERR
+#define ERR(error) \
+{ \
+  const NdbError &_error= (error); \
+  if (!m_quiet) ERR_OUT(g_err, _error); \
+}
+
 int HugoOperations::startTransaction(Ndb* pNdb,
                                      const NdbDictionary::Table *table,
                                      const char  *keyData, Uint32 keyLen){
@@ -30,6 +37,7 @@ int HugoOperations::startTransaction(Ndb
   if (pTrans == NULL) {
     const NdbError err = pNdb->getNdbError();
     ERR(err);
+    setNdbError(err);
     return NDBT_FAILED;
   }
   return NDBT_OK;
@@ -90,6 +98,7 @@ int HugoOperations::pkReadRecord(Ndb* pN
     }
     if (pOp == NULL) {
       ERR(pTrans->getNdbError());
+      setNdbError(pTrans->getNdbError());
       return NDBT_FAILED;
     }
     
@@ -119,6 +128,7 @@ rand_lock_mode:
     
     if( check == -1 ) {
       ERR(pTrans->getNdbError());
+      setNdbError(pTrans->getNdbError());
       return NDBT_FAILED;
     }
     
@@ -141,6 +151,7 @@ rand_lock_mode:
 	if((rows[r]->attributeStore(a) = 
 	    pOp->getValue(tab.getColumn(a)->getName())) == 0) {
 	  ERR(pTrans->getNdbError());
+          setNdbError(pTrans->getNdbError());
 	  return NDBT_FAILED;
 	}
       } 
@@ -174,6 +185,7 @@ int HugoOperations::pkReadRandRecord(Ndb
     }
     if (pOp == NULL) {
       ERR(pTrans->getNdbError());
+      setNdbError(pTrans->getNdbError());
       return NDBT_FAILED;
     }
     
@@ -203,6 +215,7 @@ rand_lock_mode:
     
     if( check == -1 ) {
       ERR(pTrans->getNdbError());
+      setNdbError(pTrans->getNdbError());
       return NDBT_FAILED;
     }
     
@@ -220,6 +233,7 @@ rand_lock_mode:
 	if((rows[r]->attributeStore(a) = 
 	    pOp->getValue(tab.getColumn(a)->getName())) == 0) {
 	  ERR(pTrans->getNdbError());
+          setNdbError(pTrans->getNdbError());
 	  return NDBT_FAILED;
 	}
       } 
@@ -242,12 +256,14 @@ int HugoOperations::pkUpdateRecord(Ndb* 
     NdbOperation* pOp = getOperation(pTrans, NdbOperation::UpdateRequest);
     if (pOp == NULL) {
       ERR(pTrans->getNdbError());
+      setNdbError(pTrans->getNdbError());
       return NDBT_FAILED;
     }
     
     check = pOp->updateTuple();
     if( check == -1 ) {
       ERR(pTrans->getNdbError());
+      setNdbError(pTrans->getNdbError());
       return NDBT_FAILED;
     }
     
@@ -271,6 +287,7 @@ HugoOperations::setValues(NdbOperation* 
     if (tab.getColumn(a)->getPrimaryKey() == false){
       if(setValueForAttr(pOp, a, rowId, updateId ) != 0){ 
 	ERR(pTrans->getNdbError());
+        setNdbError(pTrans->getNdbError());
 	return NDBT_FAILED;
       }
     }
@@ -289,17 +306,20 @@ int HugoOperations::pkInsertRecord(Ndb* 
     NdbOperation* pOp = getOperation(pTrans, NdbOperation::InsertRequest);
     if (pOp == NULL) {
       ERR(pTrans->getNdbError());
+      setNdbError(pTrans->getNdbError());
       return NDBT_FAILED;
     }
     
     check = pOp->insertTuple();
     if( check == -1 ) {
       ERR(pTrans->getNdbError());
+      setNdbError(pTrans->getNdbError());
       return NDBT_FAILED;
     }
     
     if(setValues(pOp, r+recordNo, updatesValue) != NDBT_OK)
     {
+      m_error.code = pTrans->getNdbError().code;
       return NDBT_FAILED;
     }
   }
@@ -316,12 +336,14 @@ int HugoOperations::pkWriteRecord(Ndb* p
     NdbOperation* pOp = pTrans->getNdbOperation(tab.getName());	
     if (pOp == NULL) {
       ERR(pTrans->getNdbError());
+      setNdbError(pTrans->getNdbError());
       return NDBT_FAILED;
     }
     
     check = pOp->writeTuple();
     if( check == -1 ) {
       ERR(pTrans->getNdbError());
+      setNdbError(pTrans->getNdbError());
       return NDBT_FAILED;
     }
     
@@ -334,6 +356,7 @@ int HugoOperations::pkWriteRecord(Ndb* p
       if (tab.getColumn(a)->getPrimaryKey() == false){
 	if(setValueForAttr(pOp, a, recordNo+r, updatesValue ) != 0){ 
 	  ERR(pTrans->getNdbError());
+          setNdbError(pTrans->getNdbError());
 	  return NDBT_FAILED;
 	}
       }
@@ -351,12 +374,14 @@ int HugoOperations::pkWritePartialRecord
     NdbOperation* pOp = pTrans->getNdbOperation(tab.getName());	
     if (pOp == NULL) {
       ERR(pTrans->getNdbError());
+      setNdbError(pTrans->getNdbError());
       return NDBT_FAILED;
     }
     
     check = pOp->writeTuple();
     if( check == -1 ) {
       ERR(pTrans->getNdbError());
+      setNdbError(pTrans->getNdbError());
       return NDBT_FAILED;
     }
     
@@ -376,12 +401,14 @@ int HugoOperations::pkDeleteRecord(Ndb* 
     NdbOperation* pOp = getOperation(pTrans, NdbOperation::DeleteRequest);
     if (pOp == NULL) {
       ERR(pTrans->getNdbError());
+      setNdbError(pTrans->getNdbError());
       return NDBT_FAILED;
     }
     
     check = pOp->deleteTuple();
     if( check == -1 ) {
       ERR(pTrans->getNdbError());
+      setNdbError(pTrans->getNdbError());
       return NDBT_FAILED;
     }
     
@@ -401,10 +428,12 @@ int HugoOperations::execute_Commit(Ndb* 
   const NdbError err = pTrans->getNdbError();
   if( check == -1 || err.code) {
     ERR(err);
+    setNdbError(err);
     NdbOperation* pOp = pTrans->getNdbErrorOperation();
     if (pOp != NULL){
       const NdbError err2 = pOp->getNdbError();
       ERR(err2);
+      setNdbError(err2);
     }
     if (err.code == 0)
       return NDBT_FAILED;
@@ -423,6 +452,7 @@ int HugoOperations::execute_Commit(Ndb* 
     case -1:
       const NdbError err = pTrans->getNdbError();
       ERR(err);
+      setNdbError(err);
       return (err.code > 0 ? err.code : NDBT_FAILED);
     }
 
@@ -450,12 +480,16 @@ int HugoOperations::execute_NoCommit(Ndb
   const NdbError err = pTrans->getNdbError();
   if( check == -1 || err.code) {
     ERR(err);
+    setNdbError(err);
     const NdbOperation* pOp = pTrans->getNdbErrorOperation();
     while (pOp != NULL)
     {
       const NdbError err2 = pOp->getNdbError();
       if (err2.code)
+      {
 	ERR(err2);
+        setNdbError(err2);
+      }
       pOp = pTrans->getNextCompletedOperation(pOp);
     }
     if (err.code == 0)
@@ -475,6 +509,7 @@ int HugoOperations::execute_NoCommit(Ndb
     case -1:
       const NdbError err = pTrans->getNdbError();
       ERR(err);
+      setNdbError(err);
       return (err.code > 0 ? err.code : NDBT_FAILED);
     }
 
@@ -500,6 +535,7 @@ int HugoOperations::execute_Rollback(Ndb
   if( check == -1 ) {
     const NdbError err = pTrans->getNdbError();
     ERR(err);
+    setNdbError(err);
     return NDBT_FAILED;
   }
   return NDBT_OK;
@@ -576,7 +612,8 @@ HugoOperations::wait_async(Ndb* pNdb, in
 HugoOperations::HugoOperations(const NdbDictionary::Table& _tab,
 			       const NdbDictionary::Index* idx):
   UtilTransactions(_tab, idx),
-  calc(_tab)
+  calc(_tab),
+  m_quiet(false)
 {
 }
 
@@ -599,6 +636,7 @@ HugoOperations::equalForRow(NdbOperation
       if(equalForAttr(pOp, a, row) != 0)
       {
         ERR(pOp->getNdbError());
+        setNdbError(pOp->getNdbError());
         return NDBT_FAILED;
       }
     }
@@ -750,6 +788,7 @@ int HugoOperations::indexReadRecords(Ndb
     NdbOperation* pOp = pTrans->getNdbIndexOperation(idxName, tab.getName());
     if (pOp == NULL) {
       ERR(pTrans->getNdbError());
+      setNdbError(pTrans->getNdbError());
       return NDBT_FAILED;
     }
     
@@ -759,6 +798,7 @@ int HugoOperations::indexReadRecords(Ndb
       check = pOp->readTuple();
     if( check == -1 ) {
       ERR(pTrans->getNdbError());
+      setNdbError(pTrans->getNdbError());
       return NDBT_FAILED;
     }
     
@@ -771,6 +811,7 @@ int HugoOperations::indexReadRecords(Ndb
       if((rows[r]->attributeStore(a) = 
 	  pOp->getValue(tab.getColumn(a)->getName())) == 0) {
 	ERR(pTrans->getNdbError());
+        setNdbError(pTrans->getNdbError());
 	return NDBT_FAILED;
       }
     } 
@@ -791,12 +832,14 @@ HugoOperations::indexUpdateRecord(Ndb*,
     NdbOperation* pOp = pTrans->getNdbIndexOperation(idxName, tab.getName());
     if (pOp == NULL) {
       ERR(pTrans->getNdbError());
+      setNdbError(pTrans->getNdbError());
       return NDBT_FAILED;
     }
     
     check = pOp->updateTuple();
     if( check == -1 ) {
       ERR(pTrans->getNdbError());
+      setNdbError(pTrans->getNdbError());
       return NDBT_FAILED;
     }
     
@@ -809,6 +852,7 @@ HugoOperations::indexUpdateRecord(Ndb*,
       if (tab.getColumn(a)->getPrimaryKey() == false){
 	if(setValueForAttr(pOp, a, recordNo+r, updatesValue ) != 0){ 
 	  ERR(pTrans->getNdbError());
+          setNdbError(pTrans->getNdbError());
 	  return NDBT_FAILED;
 	}
       }
@@ -835,6 +879,7 @@ HugoOperations::scanReadRecords(Ndb* pNd
     if((rows[0]->attributeStore(a) = 
 	pOp->getValue(tab.getColumn(a)->getName())) == 0) {
       ERR(pTrans->getNdbError());
+      setNdbError(pTrans->getNdbError());
       return NDBT_FAILED;
     }
   } 
@@ -845,4 +890,26 @@ HugoOperations::scanReadRecords(Ndb* pNd
   return 0;
 }
 
+static void
+update(const NdbError & _err)
+{
+  NdbError & error = (NdbError &) _err;
+  ndberror_struct ndberror = (ndberror_struct)error;
+  ndberror_update(&ndberror);
+  error = NdbError(ndberror);
+}
+
+const NdbError &
+HugoOperations::getNdbError() const
+{
+  update(m_error);
+  return m_error;
+}
+
+void
+HugoOperations::setNdbError(const NdbError& error)
+{
+  m_error.code = error.code ? error.code : 1;
+}
+
 template class Vector<HugoOperations::RsPair>;


Attachment: [text/bzr-bundle] bzr/pekka@mysql.com-20091221153552-ya2lb1i32eys44an.bundle
Thread
bzr commit into mysql-5.1-telco-6.2 branch (pekka:3067) Bug#34348Pekka Nousiainen21 Dec