List:Commits« Previous MessageNext Message »
From:Pekka Nousiainen Date:January 3 2011 3:09pm
Subject:bzr commit into mysql-5.1-telco-7.0 branch (pekka:4087)
View as plain text  
#At file:///export/space/pekka/ms/ms-bug58277-70/ based on revid:jonas@stripped

 4087 Pekka Nousiainen	2011-01-03 [merge]
      merge 6.3 to 7.0

    modified:
      storage/ndb/src/kernel/blocks/dblqh/DblqhMain.cpp
      storage/ndb/src/kernel/blocks/dbtup/Dbtup.hpp
      storage/ndb/src/kernel/blocks/dbtup/DbtupDebug.cpp
      storage/ndb/src/kernel/blocks/dbtup/DbtupGen.cpp
      storage/ndb/src/kernel/blocks/dbtup/DbtupStoredProcDef.cpp
      storage/ndb/src/kernel/vm/SimulatedBlock.hpp
      storage/ndb/src/ndbapi/NdbScanOperation.cpp
      storage/ndb/test/ndbapi/testDict.cpp
      storage/ndb/test/run-test/daily-basic-tests.txt
=== modified file 'storage/ndb/src/kernel/blocks/dblqh/DblqhMain.cpp'
--- a/storage/ndb/src/kernel/blocks/dblqh/DblqhMain.cpp	2010-12-21 12:06:15 +0000
+++ b/storage/ndb/src/kernel/blocks/dblqh/DblqhMain.cpp	2011-01-03 15:08:41 +0000
@@ -9280,12 +9280,18 @@ void Dblqh::execACC_SCANREF(Signal* sign
   ptrCheckGuard(tcConnectptr, ctcConnectrecFileSize, tcConnectionrec);
   tcConnectptr.p->errorCode = ref->errorCode;
 
-  AccScanConf* conf = (AccScanConf*)signal->getDataPtrSend();
-  conf->scanPtr = ref->scanPtr;
-  conf->accPtr = ref->accPtr;
-  conf->flag = AccScanConf::ZEMPTY_FRAGMENT;
-  sendSignal(reference(), GSN_ACC_SCANCONF,
-             signal, AccScanConf::SignalLength, JBB);
+  /*
+   * MRR scan can hit this between 2 DBTUX scans.  Previous range has
+   * terminated via last NEXT_SCANCONF, then index is set to Dropping,
+   * and then next range is started and returns ACC_SCANREF.
+   */
+  if (scanptr.p->scanStoredProcId != RNIL) {
+    jam();
+    scanptr.p->scanCompletedStatus = ZTRUE;
+    accScanCloseConfLab(signal);
+    return;
+  }
+  tupScanCloseConfLab(signal);
 }//Dblqh::execACC_SCANREF()
 
 /* ***************>> */
@@ -9366,13 +9372,12 @@ void Dblqh::execNEXT_SCANREF(Signal* sig
   ptrCheckGuard(tcConnectptr, ctcConnectrecFileSize, tcConnectionrec);
   tcConnectptr.p->errorCode = ref->errorCode;
 
-  NextScanConf* conf = (NextScanConf*)signal->getDataPtr();
-  conf->scanPtr = ref->scanPtr;
-  // usual weird flags to indicate scan end
-  conf->accOperationPtr = RNIL;
-  conf->fragId = RNIL;
-  sendSignal(reference(), GSN_NEXT_SCANCONF,
-             signal, 3, JBB);
+  /*
+   * MRR scan may have other ranges left.  But the scan has already
+   * failed.  Terminate the scan now.
+   */
+  scanptr.p->scanCompletedStatus = ZTRUE;
+  accScanCloseConfLab(signal);
 }//Dblqh::execNEXT_SCANREF()
 
 /* ******************> */
@@ -10292,6 +10297,16 @@ void Dblqh::accScanConfScanLab(Signal* s
      *       THE FRAGMENT WAS EMPTY.
      *       REPORT SUCCESSFUL COPYING.
      * --------------------------------------------------------------------- */
+    /*
+     * MRR scan + delete can hit this when the fragment was not
+     * initially empty, but has become empty after previous range.
+     */
+    if (scanptr.p->scanStoredProcId != RNIL) {
+      jam();
+      scanptr.p->scanCompletedStatus = ZTRUE;
+      accScanCloseConfLab(signal);
+      return;
+    }
     tupScanCloseConfLab(signal);
     return;
   }//if
@@ -10332,6 +10347,8 @@ void Dblqh::accScanConfScanLab(Signal* s
     signal->theData[1] = tcConnectptr.p->tableref;
     signal->theData[2] = scanptr.p->scanSchemaVersion;
     signal->theData[3] = ZSTORED_PROC_SCAN;
+// theData[4] is not used
+    signal->theData[5] = scanptr.p->scanApiBlockref;
     
     /* Pass ATTRINFO as long section, we don't need
      * it after this
@@ -10343,7 +10360,7 @@ void Dblqh::accScanConfScanLab(Signal* s
     getSections(handle.m_cnt, handle.m_ptr);
 
     sendSignal(tcConnectptr.p->tcTupBlockref,
-	       GSN_STORED_PROCREQ, signal, 4, JBB,
+	       GSN_STORED_PROCREQ, signal, 6, JBB,
                &handle);
   } 
   else 
@@ -11121,8 +11138,9 @@ void Dblqh::accScanCloseConfLab(Signal*
   signal->theData[2] = scanptr.p->scanSchemaVersion;
   signal->theData[3] = ZDELETE_STORED_PROC_ID;
   signal->theData[4] = scanptr.p->scanStoredProcId;
+  signal->theData[5] = scanptr.p->scanApiBlockref;
   sendSignal(tcConnectptr.p->tcTupBlockref,
-             GSN_STORED_PROCREQ, signal, 5, JBB);
+             GSN_STORED_PROCREQ, signal, 6, JBB);
 }//Dblqh::accScanCloseConfLab()
 
 /* -------------------------------------------------------------------------
@@ -11960,7 +11978,8 @@ void Dblqh::accScanConfCopyLab(Signal* s
   signal->theData[2] = scanptr.p->scanSchemaVersion;
   signal->theData[3] = ZSTORED_PROC_COPY;
 // theData[4] is not used in TUP with ZSTORED_PROC_COPY
-  sendSignal(scanptr.p->scanBlockref, GSN_STORED_PROCREQ, signal, 5, JBB);
+  signal->theData[5] = scanptr.p->scanApiBlockref;
+  sendSignal(scanptr.p->scanBlockref, GSN_STORED_PROCREQ, signal, 6, JBB);
   return;
 }//Dblqh::accScanConfCopyLab()
 
@@ -12569,7 +12588,8 @@ void Dblqh::accCopyCloseConfLab(Signal*
   signal->theData[2] = scanptr.p->scanSchemaVersion;
   signal->theData[3] = ZDELETE_STORED_PROC_ID;
   signal->theData[4] = scanptr.p->scanStoredProcId;
-  sendSignal(tcConnectptr.p->tcTupBlockref, GSN_STORED_PROCREQ, signal, 5, JBB);
+  signal->theData[5] = scanptr.p->scanApiBlockref;
+  sendSignal(tcConnectptr.p->tcTupBlockref, GSN_STORED_PROCREQ, signal, 6, JBB);
   return;
 }//Dblqh::accCopyCloseConfLab()
 

=== modified file 'storage/ndb/src/kernel/blocks/dbtup/Dbtup.hpp'
--- a/storage/ndb/src/kernel/blocks/dbtup/Dbtup.hpp	2010-12-08 11:34:29 +0000
+++ b/storage/ndb/src/kernel/blocks/dbtup/Dbtup.hpp	2011-01-03 15:08:41 +0000
@@ -1202,6 +1202,9 @@ ArrayPool<TupTriggerData> c_triggerPool;
 typedef Ptr<storedProc> StoredProcPtr;
 
 ArrayPool<storedProc> c_storedProcPool;
+RSS_AP_SNAPSHOT(c_storedProcPool);
+Uint32 c_storedProcCountNonAPI;
+void storedProcCountNonAPI(BlockReference apiBlockref, int add_del);
 
 /* **************************** TABLE_DESCRIPTOR RECORD ******************************** */
 /* THIS VARIABLE IS USED TO STORE TABLE DESCRIPTIONS. A TABLE DESCRIPTION IS STORED AS A */

=== modified file 'storage/ndb/src/kernel/blocks/dbtup/DbtupDebug.cpp'
--- a/storage/ndb/src/kernel/blocks/dbtup/DbtupDebug.cpp	2010-08-20 11:10:25 +0000
+++ b/storage/ndb/src/kernel/blocks/dbtup/DbtupDebug.cpp	2011-01-03 15:08:41 +0000
@@ -393,6 +393,8 @@ Dbtup::execDUMP_STATE_ORD(Signal* signal
     RSS_OP_SNAPSHOT_SAVE(cnoOfFreeFragoprec);
     RSS_OP_SNAPSHOT_SAVE(cnoOfFreeFragrec);
     RSS_OP_SNAPSHOT_SAVE(cnoOfFreeTabDescrRec);
+
+    RSS_AP_SNAPSHOT_SAVE2(c_storedProcPool, c_storedProcCountNonAPI);
     return;
   }
 
@@ -410,6 +412,8 @@ Dbtup::execDUMP_STATE_ORD(Signal* signal
     RSS_OP_SNAPSHOT_CHECK(cnoOfFreeFragoprec);
     RSS_OP_SNAPSHOT_CHECK(cnoOfFreeFragrec);
     RSS_OP_SNAPSHOT_CHECK(cnoOfFreeTabDescrRec);
+
+    RSS_AP_SNAPSHOT_CHECK2(c_storedProcPool, c_storedProcCountNonAPI);
     return;
   }
 }//Dbtup::execDUMP_STATE_ORD()

=== modified file 'storage/ndb/src/kernel/blocks/dbtup/DbtupGen.cpp'
--- a/storage/ndb/src/kernel/blocks/dbtup/DbtupGen.cpp	2010-09-07 06:44:00 +0000
+++ b/storage/ndb/src/kernel/blocks/dbtup/DbtupGen.cpp	2011-01-03 15:08:41 +0000
@@ -142,6 +142,7 @@ Dbtup::Dbtup(Block_context& ctx, Uint32
   RSS_OP_COUNTER_INIT(cnoOfFreeFragoprec);
   RSS_OP_COUNTER_INIT(cnoOfFreeFragrec);
   RSS_OP_COUNTER_INIT(cnoOfFreeTabDescrRec);
+  c_storedProcCountNonAPI = 0;
 
   {
     CallbackEntry& ce = m_callbackEntry[THE_NULL_CALLBACK];

=== modified file 'storage/ndb/src/kernel/blocks/dbtup/DbtupStoredProcDef.cpp'
--- a/storage/ndb/src/kernel/blocks/dbtup/DbtupStoredProcDef.cpp	2009-05-27 15:21:45 +0000
+++ b/storage/ndb/src/kernel/blocks/dbtup/DbtupStoredProcDef.cpp	2011-01-03 15:08:41 +0000
@@ -45,10 +45,19 @@ void Dbtup::execSTORED_PROCREQ(Signal* s
              ((trans_state == TRANS_ERROR_WAIT_STORED_PROCREQ) &&
              (requestInfo == ZSTORED_PROCEDURE_DELETE)));
   ndbrequire(regTabPtr.p->tableStatus == DEFINED);
+  /*
+   * Also store count of procs called from non-API scans.
+   * It can be done here since seize/release always succeeds.
+   * The count is only used under -DERROR_INSERT via DUMP.
+   */
+  BlockReference apiBlockref = signal->theData[5];
   switch (requestInfo) {
   case ZSCAN_PROCEDURE:
   {
     jam();
+#if defined VM_TRACE || defined ERROR_INSERT
+    storedProcCountNonAPI(apiBlockref, +1);
+#endif
     SectionHandle handle(this, signal);
     ndbrequire(handle.m_cnt == 1);
 
@@ -60,10 +69,16 @@ void Dbtup::execSTORED_PROCREQ(Signal* s
   }
   case ZCOPY_PROCEDURE:
     jam();
+#if defined VM_TRACE || defined ERROR_INSERT
+    storedProcCountNonAPI(apiBlockref, +1);
+#endif
     copyProcedure(signal, regTabPtr, regOperPtr.p);
     break;
   case ZSTORED_PROCEDURE_DELETE:
     jam();
+#if defined VM_TRACE || defined ERROR_INSERT
+    storedProcCountNonAPI(apiBlockref, -1);
+#endif
     deleteScanProcedure(signal, regOperPtr.p);
     break;
   default:
@@ -71,6 +86,26 @@ void Dbtup::execSTORED_PROCREQ(Signal* s
   }//switch
 }//Dbtup::execSTORED_PROCREQ()
 
+void Dbtup::storedProcCountNonAPI(BlockReference apiBlockref, int add_del)
+{
+  BlockNumber apiBlockno = refToBlock(apiBlockref);
+  if (apiBlockno < MIN_API_BLOCK_NO) {
+    ndbassert(blockToMain(apiBlockno) == BACKUP ||
+              blockToMain(apiBlockno) == SUMA ||
+              blockToMain(apiBlockno) == DBLQH);
+    if (add_del == +1) {
+      jam();
+      c_storedProcCountNonAPI++;
+    } else if (add_del == -1) {
+      jam();
+      ndbassert(c_storedProcCountNonAPI > 0);
+      c_storedProcCountNonAPI--;
+    } else {
+      ndbassert(false);
+    }
+  }
+}
+
 void Dbtup::deleteScanProcedure(Signal* signal,
                                 Operationrec* regOperPtr) 
 {

=== modified file 'storage/ndb/src/kernel/vm/SimulatedBlock.hpp'
--- a/storage/ndb/src/kernel/vm/SimulatedBlock.hpp	2010-11-10 08:40:08 +0000
+++ b/storage/ndb/src/kernel/vm/SimulatedBlock.hpp	2011-01-03 15:08:41 +0000
@@ -1315,6 +1315,8 @@ SectionHandle::~SectionHandle()
 #define RSS_AP_SNAPSHOT(x) Uint32 rss_##x
 #define RSS_AP_SNAPSHOT_SAVE(x) rss_##x = x.getNoOfFree()
 #define RSS_AP_SNAPSHOT_CHECK(x) ndbrequire(rss_##x == x.getNoOfFree())
+#define RSS_AP_SNAPSHOT_SAVE2(x,y) rss_##x = x.getNoOfFree()+(y)
+#define RSS_AP_SNAPSHOT_CHECK2(x,y) ndbrequire(rss_##x == x.getNoOfFree()+(y))
 
 #define RSS_OP_COUNTER(x) Uint32 x
 #define RSS_OP_COUNTER_INIT(x) x = 0
@@ -1330,6 +1332,8 @@ SectionHandle::~SectionHandle()
 #define RSS_AP_SNAPSHOT(x) struct rss_dummy0_##x { int dummy; }
 #define RSS_AP_SNAPSHOT_SAVE(x)
 #define RSS_AP_SNAPSHOT_CHECK(x)
+#define RSS_AP_SNAPSHOT_SAVE2(x,y)
+#define RSS_AP_SNAPSHOT_CHECK2(x,y)
 
 #define RSS_OP_COUNTER(x) struct rss_dummy1_##x { int dummy; }
 #define RSS_OP_COUNTER_INIT(x)

=== modified file 'storage/ndb/src/ndbapi/NdbScanOperation.cpp'
--- a/storage/ndb/src/ndbapi/NdbScanOperation.cpp	2010-12-11 05:20:28 +0000
+++ b/storage/ndb/src/ndbapi/NdbScanOperation.cpp	2011-01-03 15:08:41 +0000
@@ -3986,14 +3986,14 @@ NdbIndexScanOperation::end_of_bound(Uint
   {
     setErrorCodeAbort(4509);
     /* Non SF_MultiRange scan cannot have more than one bound */
-    return -1;
+    DBUG_RETURN(-1);
   }
 
   if (currentRangeOldApi == NULL)
   {
     setErrorCodeAbort(4259);
     /* Invalid set of range scan bounds */
-    return -1;
+    DBUG_RETURN(-1);
   }
 
   /* If it's an ordered scan and we're reading range numbers
@@ -4016,12 +4016,12 @@ NdbIndexScanOperation::end_of_bound(Uint
     {
       setErrorCodeAbort(4282);
       /* range_no not strictly increasing in ordered multi-range index scan */
-      return -1;
+      DBUG_RETURN(-1);
     }
   }
   
   if (buildIndexBoundOldApi(no) != 0)
-    return -1;
+    DBUG_RETURN(-1);
       
   DBUG_RETURN(0);
 }

=== modified file 'storage/ndb/test/ndbapi/testDict.cpp'
--- a/storage/ndb/test/ndbapi/testDict.cpp	2010-12-04 11:20:36 +0000
+++ b/storage/ndb/test/ndbapi/testDict.cpp	2011-01-03 15:08:41 +0000
@@ -7936,7 +7936,7 @@ runBug53944(NDBT_Context* ctx, NDBT_Step
   }
 }
 
-// Bug58277
+// Bug58277 + Bug57057
 
 #define CHK2(b, e) \
   if (!(b)) { \
@@ -7949,13 +7949,14 @@ runBug53944(NDBT_Context* ctx, NDBT_Step
 // allow list of expected error codes which do not cause NDBT_FAILED
 #define CHK3(b, e, x) \
   if (!(b)) { \
-    errcode = e.code; \
     int n = sizeof(x)/sizeof(x[0]); \
     int i; \
     for (i = 0; i < n; i++) { \
-      if (errcode == x[i]) { \
-        g_info << "OK: " << #b << " failed at line " << __LINE__ \
-              << ": " << e << endl; \
+      int s = (x[i] >= 0 ? +1 : -1); \
+      if (e.code == s * x[i]) { \
+        if (s == +1) \
+          g_info << "OK: " << #b << " failed at line " << __LINE__ \
+                << ": " << e << endl; \
         break; \
       } \
     } \
@@ -7970,78 +7971,194 @@ runBug53944(NDBT_Context* ctx, NDBT_Step
 const char* tabName_Bug58277 = "TBug58277";
 const char* indName_Bug58277 = "TBug58277X1";
 
-int
-runBug58277drop(NDBT_Context* ctx, NDBT_Step* step)
+static void
+sync_main_step(NDBT_Context* ctx, NDBT_Step* step, const char* state)
+{
+  // total sub-steps
+  Uint32 sub_steps = ctx->getProperty("SubSteps", (Uint32)0);
+  require(sub_steps != 0);
+  // count has been reset before
+  require(ctx->getProperty("SubCount", (Uint32)0) == 0);
+  // set the state
+  g_info << "step main: set " << state << endl;
+  require(ctx->getProperty(state, (Uint32)0) == 0);
+  ctx->setProperty(state, (Uint32)1);
+  // wait for sub-steps
+  ctx->getPropertyWait("SubCount", sub_steps);
+  if (ctx->isTestStopped())
+    return;
+  g_info << "step main: sub-steps got " << state << endl;
+  // reset count and state
+  ctx->setProperty("SubCount", (Uint32)0);
+  ctx->setProperty(state, (Uint32)0);
+}
+
+static void
+sync_sub_step(NDBT_Context* ctx, NDBT_Step* step, const char* state)
+{
+  // wait for main step to set state
+  g_info << "step " << step->getStepNo() << ": wait for " << state << endl;
+  ctx->getPropertyWait(state, (Uint32)1);
+  if (ctx->isTestStopped())
+    return;
+  // add to sub-step counter
+  ctx->incProperty("SubCount");
+  g_info << "step " << step->getStepNo() << ": got " << state << endl;
+  // continue to run until next sync
+}
+
+static int
+runBug58277createtable(NDBT_Context* ctx, NDBT_Step* step)
 {
   Ndb* pNdb = GETNDB(step);
   NdbDictionary::Dictionary* pDic = pNdb->getDictionary();
   int result = NDBT_OK;
+  const int rows = ctx->getNumRecords();
   const char* tabname = tabName_Bug58277;
-  const char* indname = indName_Bug58277;
-  int dropms = 0;
 
-  while (!ctx->isTestStopped())
+  do
   {
-    dropms = ctx->getProperty("DropMs", (Uint32)0);
-    if (dropms == 0)
+    CHK2(rows > 0, "cannot use --records=0"); // others require this
+    g_info << "create table " << tabname << endl;
+    NdbDictionary::Table tab(tabname);
+    const char* name[] = { "a", "b" };
+    for (int i = 0; i <= 1; i++)
     {
-      NdbSleep_MilliSleep(10);
-      continue;
+      NdbDictionary::Column c(name[i]);
+      c.setType(NdbDictionary::Column::Unsigned);
+      c.setPrimaryKey(i == 0);
+      c.setNullable(false);
+      tab.addColumn(c);
     }
-    NdbSleep_MilliSleep(dropms);
-    ctx->setProperty("DropMs", (Uint32)0);
+    if (rand() % 3 != 0)
+    {
+      g_info << "set FragAllLarge" << endl;
+      tab.setFragmentType(NdbDictionary::Object::FragAllLarge);
+    }
+    CHK2(pDic->createTable(tab) == 0, pDic->getNdbError());
+  }
+  while (0);
+  return result;
+}
 
-    g_info << "drop index " << indname << endl;
-    CHK2(pDic->dropIndex(indname, tabname) == 0, pDic->getNdbError());
-    g_info << "drop done" << endl;
+static int
+runBug58277loadtable(NDBT_Context* ctx, NDBT_Step* step)
+{
+  Ndb* pNdb = GETNDB(step);
+  NdbDictionary::Dictionary* pDic = pNdb->getDictionary();
+  int result = NDBT_OK;
+  const int rows = ctx->getNumRecords();
+  const char* tabname = tabName_Bug58277;
+
+  do
+  {
+    g_info << "load table" << endl;
+    const NdbDictionary::Table* pTab = 0;
+    CHK2((pTab = pDic->getTable(tabname)) != 0, pDic->getNdbError());
+
+    int cnt = 0;
+    for (int i = 0; i < rows; i++)
+    {
+      NdbTransaction* pTx = 0;
+      CHK2((pTx = pNdb->startTransaction()) != 0, pNdb->getNdbError());
+
+      NdbOperation* pOp = 0;
+      CHK2((pOp = pTx->getNdbOperation(pTab)) != 0, pTx->getNdbError());
+      CHK2(pOp->insertTuple() == 0, pOp->getNdbError());
+      Uint32 aVal = i;
+      Uint32 bVal = rand() % rows;
+      CHK2(pOp->equal("a", (char*)&aVal) == 0, pOp->getNdbError());
+      CHK2(pOp->setValue("b", bVal) == 0, pOp->getNdbError());
+
+      do
+      {
+        int x[] = {
+         -630
+        };
+        CHK3(pTx->execute(Commit) == 0, pTx->getNdbError(), x);
+        cnt++;
+      }
+      while (0);
+      CHK2(result == NDBT_OK, "load failed");
+      pNdb->closeTransaction(pTx);
+    }
+    CHK2(result == NDBT_OK, "load failed");
+    g_info << "load " << cnt << " rows" << endl;
   }
+  while (0);
+  return result;
+}
 
-  if (result != NDBT_OK)
+static int
+runBug58277createindex(NDBT_Context* ctx, NDBT_Step* step)
+{
+  Ndb* pNdb = GETNDB(step);
+  NdbDictionary::Dictionary* pDic = pNdb->getDictionary();
+  int result = NDBT_OK;
+  const char* tabname = tabName_Bug58277;
+  const char* indname = indName_Bug58277;
+
+  do
   {
-    g_info << "stop test at line " << __LINE__ << endl;
-    ctx->stopTest();
+    g_info << "create index " << indname << endl;
+    NdbDictionary::Index ind(indname);
+    ind.setTable(tabname);
+    ind.setType(NdbDictionary::Index::OrderedIndex);
+    ind.setLogging(false);
+    ind.addColumn("b");
+    CHK2(pDic->createIndex(ind) == 0, pDic->getNdbError());
+
+    const NdbDictionary::Index* pInd = 0;
+    CHK2((pInd = pDic->getIndex(indname, tabname)) != 0, pDic->getNdbError());
   }
+  while (0);
   return result;
 }
 
+// separate error handling test
 int
-runBug58277scan(NDBT_Context* ctx, NDBT_Step* step)
+runBug58277errtest(NDBT_Context* ctx, NDBT_Step* step)
 {
   Ndb* pNdb = GETNDB(step);
   NdbDictionary::Dictionary* pDic = pNdb->getDictionary();
+  const int loops = ctx->getNumLoops();
   int result = NDBT_OK;
   const int rows = ctx->getNumRecords();
+  NdbRestarter restarter;
   const char* tabname = tabName_Bug58277;
   const char* indname = indName_Bug58277;
-  int dropms = 0;
+  (void)pDic->dropTable(tabname);
 
-  while (!ctx->isTestStopped())
+  const int errloops = loops < 5 ? loops : 5;
+  int errloop = 0;
+  while (!ctx->isTestStopped() && errloop < errloops)
   {
-    CHK2(rows > 0, "cannot use -r 0");
-    dropms = ctx->getProperty("DropMs", (Uint32)0);
-    if (dropms == 0)
+    g_info << "===== errloop " << errloop << " =====" << endl;
+
+    if (errloop == 0)
     {
-      NdbSleep_MilliSleep(10);
-      continue;
+      CHK2(runBug58277createtable(ctx, step) == NDBT_OK, "create table failed");
+      CHK2(runBug58277loadtable(ctx, step) == NDBT_OK, "load table failed");
+      CHK2(runBug58277createindex(ctx, step) == NDBT_OK, "create index failed");
     }
-    g_info << "start scan loop" << endl;
-    int errcode = 0; // expected error
+    const NdbDictionary::Index* pInd = 0;
+    CHK2((pInd = pDic->getIndex(indname, tabname)) != 0, pDic->getNdbError());
 
-    while (!ctx->isTestStopped() && errcode == 0)
+    int errins[] = {
+      12008, 909,  // TuxNoFreeScanOp
+      12009, 4259  // InvalidBounds
+    };
+    for (int i = 0; i < sizeof(errins)/sizeof(errins[0]); i += 2)
     {
-      const NdbDictionary::Index* pInd = 0;
-      {
-        int x[] = {
-          4243  // Index not found
-        };
-        pDic->invalidateIndex(indname, tabname);
-        CHK3((pInd = pDic->getIndex(indname, tabname)) != 0, pDic->getNdbError(), x);
-      }
+      const int ei = errins[i + 0];
+      const int ec = errins[i + 1];
+      CHK2(restarter.insertErrorInAllNodes(ei) == 0, "value " << ei);
 
       NdbTransaction* pSTx = 0;
       CHK2((pSTx = pNdb->startTransaction()) != 0, pNdb->getNdbError());
       NdbIndexScanOperation* pSOp = 0;
       CHK2((pSOp = pSTx->getNdbIndexScanOperation(pInd)) != 0, pSTx->getNdbError());
+
       NdbOperation::LockMode lm = NdbOperation::LM_Exclusive;
       Uint32 flags = 0;
       CHK2(pSOp->readTuples(lm, flags) == 0, pSOp->getNdbError());
@@ -8049,72 +8166,249 @@ runBug58277scan(NDBT_Context* ctx, NDBT_
       Uint32 aVal = 0;
       CHK2(pSOp->getValue("a", (char*)&aVal) != 0, pSOp->getNdbError());
       CHK2(pSTx->execute(NoCommit) == 0, pSTx->getNdbError());
+      // before fixes 12009 failed to fail at once here
+      CHK2(pSOp->nextResult(true) == -1, "failed to fail on " << ei);
+      CHK2(pSOp->getNdbError().code == ec, "expect " << ec << " got " << pSOp->getNdbError());
+      pNdb->closeTransaction(pSTx);
+
+      g_info << "error " << ei << " " << ec << " ok" << endl;
+      CHK2(restarter.insertErrorInAllNodes(0) == 0, "value " << 0);
+    }
+    CHK2(result == NDBT_OK, "test error handling failed");
 
-      int cnt = 0;
-      while (!ctx->isTestStopped() && errcode == 0)
+    errloop++;
+    if (errloop == errloops)
+    {
+      CHK2(pDic->dropTable(tabname) == 0, pDic->getNdbError());
+      g_info << "table " << tabname << " dropped" << endl;
+    }
+  }
+  if (result != NDBT_OK)
+  {
+    g_info << "stop test at line " << __LINE__ << endl;
+    ctx->stopTest();
+  }
+  return result;
+}
+
+int
+runBug58277drop(NDBT_Context* ctx, NDBT_Step* step)
+{
+  Ndb* pNdb = GETNDB(step);
+  NdbDictionary::Dictionary* pDic = pNdb->getDictionary();
+  int result = NDBT_OK;
+  const char* tabname = tabName_Bug58277;
+  const char* indname = indName_Bug58277;
+  int dropms = 0;
+
+  while (!ctx->isTestStopped())
+  {
+    sync_sub_step(ctx, step, "Start");
+    if (ctx->isTestStopped())
+      break;
+    dropms = ctx->getProperty("DropMs", (Uint32)0);
+    NdbSleep_MilliSleep(dropms);
+
+    g_info << "drop index " << indname << endl;
+    CHK2(pDic->dropIndex(indname, tabname) == 0, pDic->getNdbError());
+    pDic->invalidateIndex(indname, tabname);
+    CHK2(pDic->getIndex(indname, tabname) == 0, "failed");
+    g_info << "drop index done" << endl;
+
+    sync_sub_step(ctx, step, "Stop");
+    if (ctx->isTestStopped())
+      break;
+  }
+  if (result != NDBT_OK)
+  {
+    g_info << "stop test at line " << __LINE__ << endl;
+    ctx->stopTest();
+  }
+  return result;
+}
+
+static int
+runBug58277scanop(NDBT_Context* ctx, NDBT_Step* step, int cnt[1+3])
+{
+  Ndb* pNdb = GETNDB(step);
+  NdbDictionary::Dictionary* pDic = pNdb->getDictionary();
+  int result = NDBT_OK;
+  const int rows = ctx->getNumRecords();
+  const char* tabname = tabName_Bug58277;
+  const char* indname = indName_Bug58277;
+  const int range_max = ctx->getProperty("RANGE_MAX", (Uint32)0);
+  require(range_max > 0);
+  const bool scan_delete = ctx->getProperty("SCAN_DELETE", (Uint32)0);
+
+  do
+  {
+    const NdbDictionary::Index* pInd = 0;
+    {
+      int x[] = {
+        4243  // Index not found
+      };
+      pDic->invalidateIndex(indname, tabname);
+      CHK3((pInd = pDic->getIndex(indname, tabname)) != 0, pDic->getNdbError(), x);
+    }
+
+    NdbTransaction* pSTx = 0;
+    CHK2((pSTx = pNdb->startTransaction()) != 0, pNdb->getNdbError());
+    NdbIndexScanOperation* pSOp = 0;
+    CHK2((pSOp = pSTx->getNdbIndexScanOperation(pInd)) != 0, pSTx->getNdbError());
+    NdbOperation::LockMode lm = NdbOperation::LM_Exclusive;
+    Uint32 flags = 0;
+    int range_cnt = rand() % range_max;
+    if (range_cnt > 1 || rand() % 5 == 0)
+      flags |= NdbIndexScanOperation::SF_MultiRange;
+    CHK2(pSOp->readTuples(lm, flags) == 0, pSOp->getNdbError());
+    g_info << "range cnt " << range_cnt << endl;
+    for (int i = 0; i < range_cnt; )
+    {
+      int tlo = -1;
+      int thi = -1;
+      if (rand() % 5 == 0)
       {
-        int ret;
-        {
-          int x[] = {
-            241,  // Invalid schema object version
-            274,  // Time-out in NDB, probably caused by deadlock
-            283,  // Table is being dropped
-            284,  // Table not defined in transaction coordinator
-            910,  // Index is being dropped
-            1226  // Table is being dropped
-          };
-          CHK3((ret = pSOp->nextResult(true)) != -1, pSOp->getNdbError(), x);
-        }
+        if (rand() % 5 != 0)
+          tlo = 0 + rand() % 2;
+        if (rand() % 5 != 0)
+          thi = 2 + rand() % 2;
+      }
+      else
+        tlo = 4;
+      // apparently no bounds is not allowed (see also bug#57396)
+      if (tlo == -1 && thi == -1)
+        continue;
+      Uint32 blo = 0;
+      Uint32 bhi = 0;
+      if (tlo != -1)
+      {
+        blo = rand() % rows;
+        CHK2(pSOp->setBound("b", tlo, &blo) == 0, pSOp->getNdbError());
+      }
+      if (thi != -1)
+      {
+        bhi = rand() % (rows + 1);
+        if (bhi < blo)
+          bhi = rand() % (rows + 1);
+        CHK2(pSOp->setBound("b", thi, &bhi) == 0, pSOp->getNdbError());
+      }
+      CHK2(pSOp->end_of_bound() == 0, pSOp->getNdbError());
+      i++;
+    }
+    CHK2(result == NDBT_OK, "set bound ranges failed");
 
-        CHK2(ret == 0 || ret == 1, "impossible ret " << ret);
-        if (ret == 1)
-          break;
+    Uint32 aVal = 0;
+    CHK2(pSOp->getValue("a", (char*)&aVal) != 0, pSOp->getNdbError());
+    CHK2(pSTx->execute(NoCommit) == 0, pSTx->getNdbError());
 
-        NdbTransaction* pTx = 0;
-        CHK2((pTx = pNdb->startTransaction()) != 0, pNdb->getNdbError());
-        int cntbatch = 0;
+    while (1)
+    {
+      int ret;
+      {
+        int x[] = {
+          241,  // Invalid schema object version
+          274,  // Time-out in NDB, probably caused by deadlock
+          283,  // Table is being dropped
+          284,  // Table not defined in transaction coordinator
+          910,  // Index is being dropped
+          1226  // Table is being dropped
+        };
+        CHK3((ret = pSOp->nextResult(true)) != -1, pSOp->getNdbError(), x);
+      }
+      require(ret == 0 || ret == 1);
+      if (ret == 1)
+        break;
 
-        while (!ctx->isTestStopped() && errcode == 0)
+      NdbTransaction* pTx = 0;
+      CHK2((pTx = pNdb->startTransaction()) != 0, pNdb->getNdbError());
+
+      while (1)
+      {
+        int type = 1 + rand() % 3;
+        if (type == 2) // insert->update
+          type = 1;
+        if (scan_delete)
+          type = 3;
+        do
         {
-          NdbOperation* pOp = 0;
-          CHK2((pOp = pSOp->updateCurrentTuple(pTx)) != 0, pSOp->getNdbError());
-          Uint32 bVal = (Uint32)(rand() % rows);
-          CHK2(pOp->setValue("b", bVal) == 0, pOp->getNdbError());
+          if (type == 1)
           {
-            int x[] = {
-              266,  // Time-out in NDB, probably caused by deadlock
-              499,  // Scan take over error
-              631   // 631
-            };
-            CHK3(pTx->execute(NoCommit) == 0, pTx->getNdbError(), x);
-            cntbatch++;
+            NdbOperation* pOp = 0;
+            CHK2((pOp = pSOp->updateCurrentTuple(pTx)) != 0, pSOp->getNdbError());
+            Uint32 bVal = (Uint32)(rand() % rows);
+            CHK2(pOp->setValue("b", bVal) == 0, pOp->getNdbError());
+            break;
           }
-
-          CHK2((ret = pSOp->nextResult(false)) != -1, pSOp->getNdbError());
-          CHK2(ret == 0 || ret == 2, "impossible ret " << ret);
-          if (ret == 2)
+          if (type == 3)
+          {
+            NdbOperation* pOp = 0;
+            CHK2(pSOp->deleteCurrentTuple(pTx) == 0, pSOp->getNdbError());
             break;
+          }
+          require(false);
         }
-        CHK2(result == NDBT_OK, "batch failed");
-        //g_info << "batch ops " << cntbatch << endl;
-        cnt += cntbatch;
+        while (0);
+        CHK2(result == NDBT_OK, "scan takeover error");
+        cnt[type]++;
         {
           int x[] = {
             266,  // Time-out in NDB, probably caused by deadlock
+            499,  // Scan take over error
+            631,  // 631
             4350  // Transaction already aborted
           };
-          CHK3(pTx->execute(Commit) == 0, pTx->getNdbError(), x);
+          CHK3(pTx->execute(NoCommit) == 0, pTx->getNdbError(), x);
         }
-        pNdb->closeTransaction(pTx);
+
+        CHK2((ret = pSOp->nextResult(false)) != -1, pSOp->getNdbError());
+        require(ret == 0 || ret == 2);
+        if (ret == 2)
+          break;
       }
+      CHK2(result == NDBT_OK, "batch failed");
 
-      CHK2(result == NDBT_OK, "scan failed");
-      pNdb->closeTransaction(pSTx);
-      g_info << "scan ops " << cnt << endl;
+      {
+        int x[] = {
+          266,  // Time-out in NDB, probably caused by deadlock
+          4350  // Transaction already aborted
+        };
+        CHK3(pTx->execute(Commit) == 0, pTx->getNdbError(), x);
+      }
+      pNdb->closeTransaction(pTx);
     }
-    CHK2(result == NDBT_OK, "scan loop failed");
+    CHK2(result == NDBT_OK, "batch failed");
+    pNdb->closeTransaction(pSTx);
   }
+  while (0);
+  return result;
+}
 
+int
+runBug58277scan(NDBT_Context* ctx, NDBT_Step* step)
+{
+  int result = NDBT_OK;
+
+  while (!ctx->isTestStopped())
+  {
+    sync_sub_step(ctx, step, "Start");
+    if (ctx->isTestStopped())
+      break;
+    g_info << "start scan loop" << endl;
+    while (!ctx->isTestStopped())
+    {
+      g_info << "start scan" << endl;
+      int cnt[1+3] = { 0, 0, 0, 0 };
+      CHK2(runBug58277scanop(ctx, step, cnt) == NDBT_OK, "scan failed");
+      g_info << "scan ops " << cnt[1] << "/-/" << cnt[3] << endl;
+
+      if (ctx->getProperty("Stop", (Uint32)0) == 1)
+      {
+        sync_sub_step(ctx, step, "Stop");
+        break;
+      }
+    }
+    CHK2(result == NDBT_OK, "scan loop failed");
+  }
   if (result != NDBT_OK)
   {
     g_info << "stop test at line " << __LINE__ << endl;
@@ -8123,108 +8417,135 @@ runBug58277scan(NDBT_Context* ctx, NDBT_
   return result;
 }
 
-int
-runBug58277pk(NDBT_Context* ctx, NDBT_Step* step)
+static int
+runBug58277pkop(NDBT_Context* ctx, NDBT_Step* step, int cnt[1+3])
 {
   Ndb* pNdb = GETNDB(step);
   NdbDictionary::Dictionary* pDic = pNdb->getDictionary();
   int result = NDBT_OK;
   const int rows = ctx->getNumRecords();
   const char* tabname = tabName_Bug58277;
-  int dropms = 0;
 
-  while (!ctx->isTestStopped())
+  do
   {
-    CHK2(rows > 0, "cannot use -r 0");
-    dropms = ctx->getProperty("DropMs", (Uint32)0);
-    if (dropms == 0)
-    {
-      NdbSleep_MilliSleep(10);
-      continue;
-    }
-    g_info << "start pk loop" << endl;
-    int errcode = 0; // expected error
+    const NdbDictionary::Table* pTab = 0;
+    CHK2((pTab = pDic->getTable(tabname)) != 0, pDic->getNdbError());
 
-    while (!ctx->isTestStopped() && errcode == 0)
-    {
-      const NdbDictionary::Table* pTab = 0;
-      CHK2((pTab = pDic->getTable(tabname)) != 0, pDic->getNdbError());
+    NdbTransaction* pTx = 0;
+    CHK2((pTx = pNdb->startTransaction()) != 0, pNdb->getNdbError());
+    NdbOperation* pOp = 0;
+    CHK2((pOp = pTx->getNdbOperation(pTab)) != 0, pTx->getNdbError());
+    int type = 1 + rand() % 3;
+    Uint32 aVal = rand() % rows;
+    Uint32 bVal = rand() % rows;
 
-      int cnt[1+3] = { 0, 0, 0, 0 };
-      while (!ctx->isTestStopped() && errcode == 0)
+    do
+    {
+      if (type == 1)
       {
-        NdbTransaction* pTx = 0;
-        CHK2((pTx = pNdb->startTransaction()) != 0, pNdb->getNdbError());
-        NdbOperation* pOp = 0;
-        CHK2((pOp = pTx->getNdbOperation(pTab)) != 0, pTx->getNdbError());
-        int type = 1 + rand() % 3;
-        Uint32 aVal = rand() % rows;
-        Uint32 bVal = rand() % rows;
+        CHK2(pOp->updateTuple() == 0, pOp->getNdbError());
+        CHK2(pOp->equal("a", (char*)&aVal) == 0, pOp->getNdbError());
+        CHK2(pOp->setValue("b", bVal) == 0, pOp->getNdbError());
+        int x[] = {
+          266,  // Time-out in NDB, probably caused by deadlock
+         -626   // Tuple did not exist
+        };
+        CHK3(pTx->execute(Commit) == 0, pTx->getNdbError(), x);
+        break;
+      }
+      if (type == 2)
+      {
+        CHK2(pOp->insertTuple() == 0, pOp->getNdbError());
+        CHK2(pOp->equal("a", (char*)&aVal) == 0, pOp->getNdbError());
+        CHK2(pOp->setValue("b", bVal) == 0, pOp->getNdbError());
+        int x[] = {
+          266,  // Time-out in NDB, probably caused by deadlock
+         -630   // Tuple already existed when attempting to insert
+        };
+        CHK3(pTx->execute(Commit) == 0, pTx->getNdbError(), x);
+        break;
+      }
+      if (type == 3)
+      {
+        CHK2(pOp->deleteTuple() == 0, pOp->getNdbError());
+        CHK2(pOp->equal("a", (char*)&aVal) == 0, pOp->getNdbError());
+        int x[] = {
+          266,  // Time-out in NDB, probably caused by deadlock
+         -626   // Tuple did not exist
+        };
+        CHK3(pTx->execute(Commit) == 0, pTx->getNdbError(), x);
+        break;
+      }
+      require(false);
+    }
+    while (0);
+    CHK2(result == NDBT_OK, "pk op failed");
 
-        while (1)
-        {
-          if (type == 1)
-          {
-            CHK2(pOp->updateTuple() == 0, pOp->getNdbError());
-            CHK2(pOp->equal("a", (char*)&aVal) == 0, pOp->getNdbError());
-            CHK2(pOp->setValue("b", bVal) == 0, pOp->getNdbError());
-            int x[] = {
-              266,  // Time-out in NDB, probably caused by deadlock
-              626   // Tuple did not exist
-            };
-            CHK3(pTx->execute(Commit) == 0, pTx->getNdbError(), x);
-          }
-          if (type == 2)
-          {
-            CHK2(pOp->insertTuple() == 0, pOp->getNdbError());
-            CHK2(pOp->equal("a", (char*)&aVal) == 0, pOp->getNdbError());
-            CHK2(pOp->setValue("b", bVal) == 0, pOp->getNdbError());
-            int x[] = {
-              266,  // Time-out in NDB, probably caused by deadlock
-              630   // Tuple already existed when attempting to insert
-            };
-            CHK3(pTx->execute(Commit) == 0, pTx->getNdbError(), x);
-          }
-          if (type == 3)
-          {
-            CHK2(pOp->deleteTuple() == 0, pOp->getNdbError());
-            CHK2(pOp->equal("a", (char*)&aVal) == 0, pOp->getNdbError());
-            int x[] = {
-              266,  // Time-out in NDB, probably caused by deadlock
-              626   // Tuple did not exist
-            };
-            CHK3(pTx->execute(Commit) == 0, pTx->getNdbError(), x);
-          }
-          break;
-        }
-        CHK2(result == NDBT_OK, "pk op failed");
+    pNdb->closeTransaction(pTx);
+    cnt[type]++;
+  }
+  while (0);
+  return result;
+}
 
-        if (errcode == 0)
-          cnt[type]++;
-        errcode = 0;  // ignore expected error
-        if (pTx != 0)
-          pNdb->closeTransaction(pTx);
+int
+runBug58277pk(NDBT_Context* ctx, NDBT_Step* step)
+{
+  int result = NDBT_OK;
 
-        int n = rows / 5;
-        if (n == 0 || rand() % n == 0)
-          break;
-      }
-      g_info << "pk ops " << cnt[1] << "/" << cnt[2] << "/" << cnt[3] << endl;
-      CHK2(result == NDBT_OK, "pk ops failed");
+  while (!ctx->isTestStopped())
+  {
+    sync_sub_step(ctx, step, "Start");
+    if (ctx->isTestStopped())
+      break;
+
+    g_info << "start pk loop" << endl;
+    int cnt[1+3] = { 0, 0, 0, 0 };
+    while (!ctx->isTestStopped())
+    {
+      CHK2(runBug58277pkop(ctx, step, cnt) == NDBT_OK, "pk op failed");
 
-      NdbSleep_MilliSleep(10);
-      dropms = ctx->getProperty("DropMs", (Uint32)0);
-      if (dropms == 0)
+      if (ctx->getProperty("Stop", (Uint32)0) == 1)
+      {
+        sync_sub_step(ctx, step, "Stop");
         break;
+      }
     }
     CHK2(result == NDBT_OK, "pk loop failed");
+    g_info << "pk ops " << cnt[1] << "/" << cnt[2] << "/" << cnt[3] << endl;
+  }
+  if (result != NDBT_OK)
+  {
+    g_info << "stop test at line " << __LINE__ << endl;
+    ctx->stopTest();
   }
+  return result;
+}
 
+int
+runBug58277rand(NDBT_Context* ctx, NDBT_Step* step)
+{
+  int result = NDBT_OK;
+  NdbRestarter restarter;
+
+  while (!ctx->isTestStopped())
+  {
+    int sleepms = rand() % 5000;
+    g_info << "rand sleep " << sleepms << " ms" << endl;
+    NdbSleep_MilliSleep(sleepms);
+    if (rand() % 5 == 0)
+    {
+      g_info << "rand force LCP" << endl;
+      int dump1[] = { DumpStateOrd::DihStartLcpImmediately };
+      CHK2(restarter.dumpStateAllNodes(dump1, 1) == 0, "failed");
+    }
+  }
   if (result != NDBT_OK)
   {
     g_info << "stop test at line " << __LINE__ << endl;
     ctx->stopTest();
   }
+  g_info << "rand exit" << endl;
   return result;
 }
 
@@ -8235,122 +8556,143 @@ runBug58277(NDBT_Context* ctx, NDBT_Step
   NdbDictionary::Dictionary* pDic = pNdb->getDictionary();
   const int loops = ctx->getNumLoops();
   int result = NDBT_OK;
-  const int rows = ctx->getNumRecords();
+  const bool rss_check = ctx->getProperty("RSS_CHECK", (Uint32)0);
   NdbRestarter restarter;
   const char* tabname = tabName_Bug58277;
   const char* indname = indName_Bug58277;
   (void)pDic->dropTable(tabname);
 
   int loop = 0;
-  int preloop = 0; // test some general stuff before bug itself
-  while (!ctx->isTestStopped() && loop < loops)
+  while (!ctx->isTestStopped())
   {
-    g_info << "loop " << loop << endl;
-    if (loop == 0)
-      g_info << "preloop " << preloop << endl;
+    g_info << "===== loop " << loop << " =====" << endl;
 
     if (loop == 0)
     {
-      const NdbDictionary::Table* pTab = 0;
-      if ((pTab = pDic->getTable(tabname)) == 0)
-      {
-        CHK2(pDic->getNdbError().code == 723, pDic->getNdbError());
-      }
-      else
-      {
-        g_info << "drop table " << tabname << endl;
-        CHK2(pDic->dropTable(tabname) == 0, pDic->getNdbError());
-      }
+      CHK2(runBug58277createtable(ctx, step) == NDBT_OK, "create table failed");
+      CHK2(runBug58277loadtable(ctx, step) == NDBT_OK, "load table failed");
+    }
 
-      g_info << "create table " << tabname << endl;
-      NdbDictionary::Table tab(tabname);
-      const char* name[] = { "a", "b" };
-      for (int i = 0; i <= 1; i++)
-      {
-        NdbDictionary::Column c(name[i]);
-        c.setType(NdbDictionary::Column::Unsigned);
-        c.setPrimaryKey(i == 0);
-        c.setNullable(false);
-        tab.addColumn(c);
-      }
-      if (rand() % 3 != 0)
-      {
-        g_info << "set FragAllLarge" << endl;
-        tab.setFragmentType(NdbDictionary::Object::FragAllLarge);
-      }
-      CHK2(pDic->createTable(tab) == 0, pDic->getNdbError());
-      CHK2((pTab = pDic->getTable(tabname)) != 0, pDic->getNdbError());
+    if (rss_check)
+    {
+      g_info << "save all resource usage" << endl;
+      int dump1[] = { DumpStateOrd::SchemaResourceSnapshot };
+      CHK2(restarter.dumpStateAllNodes(dump1, 1) == 0, "failed");
+    }
 
-      g_info << "insert records" << endl;
-      HugoTransactions trans(*pTab);
-      CHK2(trans.loadTable(pNdb, rows) == 0, trans.getNdbError());
+    CHK2(runBug58277createindex(ctx, step) == NDBT_OK, "create index failed");
+
+    int dropmin = 1000;
+    int dropmax = 9000;
+    int dropms = dropmin + rand() % (dropmax - dropmin + 1);
+    g_info << "drop in " << dropms << " ms" << endl;
+    ctx->setProperty("DropMs", dropms);
+
+    sync_main_step(ctx, step, "Start");
+    if (ctx->isTestStopped())
+      break;
+
+    // vary Stop time a bit in either direction
+    int stopvar = rand() % 100;
+    int stopsgn = (rand() % 2 == 0 ? +1 : -1);
+    int stopms = dropms + stopsgn * stopvar;
+    NdbSleep_MilliSleep(stopms);
+
+    sync_main_step(ctx, step, "Stop");
+    if (ctx->isTestStopped())
+      break;
+
+    // index must have been dropped
+    pDic->invalidateIndex(indname, tabname);
+    CHK2(pDic->getIndex(indname, tabname) == 0, "failed");
+
+    if (rss_check)
+    {
+      g_info << "check all resource usage" << endl;
+      int dump2[] = { DumpStateOrd::SchemaResourceCheckLeak };
+      CHK2(restarter.dumpStateAllNodes(dump2, 1) == 0, "failed");
+
+      g_info << "check cluster is up" << endl;
+      CHK2(restarter.waitClusterStarted() == 0, "failed");
     }
 
-    g_info << "create index " << indname << endl;
-    NdbDictionary::Index ind(indname);
-    ind.setTable(tabname);
-    ind.setType(NdbDictionary::Index::OrderedIndex);
-    ind.setLogging(false);
-    ind.addColumn("b");
-    CHK2(pDic->createIndex(ind) == 0, pDic->getNdbError());
+    if (++loop == loops)
+    {
+      CHK2(pDic->dropTable(tabname) == 0, pDic->getNdbError());
+      g_info << "table " << tabname << " dropped" << endl;
+      break;
+    }
+  }
 
-    const NdbDictionary::Index* pInd = 0;
-    CHK2((pInd = pDic->getIndex(indname, tabname)) != 0, pDic->getNdbError());
+  g_info << "stop test at line " << __LINE__ << endl;
+  ctx->stopTest();
+  return result;
+}
+
+int
+runBug57057(NDBT_Context* ctx, NDBT_Step* step)
+{
+  Ndb* pNdb = GETNDB(step);
+  NdbDictionary::Dictionary* pDic = pNdb->getDictionary();
+  const int loops = ctx->getNumLoops();
+  int result = NDBT_OK;
+  const bool rss_check = ctx->getProperty("RSS_CHECK", (Uint32)0);
+  NdbRestarter restarter;
+  const char* tabname = tabName_Bug58277;
+  const char* indname = indName_Bug58277;
+  (void)pDic->dropTable(tabname);
+
+  int loop = 0;
+  while (!ctx->isTestStopped())
+  {
+    g_info << "===== loop " << loop << " =====" << endl;
 
     if (loop == 0)
     {
-      g_info << "test error handling" << endl;
-      int errins[] = {
-        12008, 909,     // TuxNoFreeScanOp
-        12009, 4259,    // InvalidBounds
-        0, 0
-      };
+      CHK2(runBug58277createtable(ctx, step) == NDBT_OK, "create table failed");
+      CHK2(runBug58277createindex(ctx, step) == NDBT_OK, "create index failed");
+    }
 
-      int i = 0;
-      while (errins[i] != 0)
-      {
-        const int ei = errins[i++];
-        const int ec = errins[i++];
-        CHK2(restarter.insertErrorInAllNodes(ei) == 0, "value " << ei);
-
-        NdbTransaction* pSTx = 0;
-        CHK2((pSTx = pNdb->startTransaction()) != 0, pNdb->getNdbError());
-        NdbIndexScanOperation* pSOp = 0;
-        CHK2((pSOp = pSTx->getNdbIndexScanOperation(pInd)) != 0, pSTx->getNdbError());
-
-        NdbOperation::LockMode lm = NdbOperation::LM_Exclusive;
-        Uint32 flags = 0;
-        CHK2(pSOp->readTuples(lm, flags) == 0, pSOp->getNdbError());
-
-        Uint32 aVal = 0;
-        CHK2(pSOp->getValue("a", (char*)&aVal) != 0, pSOp->getNdbError());
-        CHK2(pSTx->execute(NoCommit) == 0, pSTx->getNdbError());
-        // before fixes 12009 failed to fail at once here
-        CHK2(pSOp->nextResult(true) == -1, "failed to fail on " << ei);
-        CHK2(pSOp->getNdbError().code == ec, "expect " << ec << " got " << pSOp->getNdbError());
-        pNdb->closeTransaction(pSTx);
+    CHK2(runBug58277loadtable(ctx, step) == NDBT_OK, "load table failed");
 
-        g_info << "error " << ei << " " << ec << " ok" << endl;
-        CHK2(restarter.insertErrorInAllNodes(0) == 0, "value " << 0);
-      }
-      CHK2(result == NDBT_OK, "test error handling failed");
+    if (rss_check)
+    {
+      g_info << "save all resource usage" << endl;
+      int dump1[] = { DumpStateOrd::SchemaResourceSnapshot };
+      CHK2(restarter.dumpStateAllNodes(dump1, 1) == 0, "failed");
     }
 
-    if (loop == 0 && preloop++ < 2)
-      continue;
-
     int dropmin = 1000;
-    int dropmax = 5000;
+    int dropmax = 2000;
     int dropms = dropmin + rand() % (dropmax - dropmin + 1);
-    g_info << "drop in " << dropms << " ms" << endl;
-    ctx->setProperty("DropMs", dropms);
-    NdbSleep_MilliSleep(dropms + 5000);
+    int stopms = dropms;
 
-    loop++;
-    if (loop == loops)
+    sync_main_step(ctx, step, "Start");
+    if (ctx->isTestStopped())
+      break;
+
+    g_info << "stop in " << stopms << " ms" << endl;
+    NdbSleep_MilliSleep(stopms);
+
+    sync_main_step(ctx, step, "Stop");
+    if (ctx->isTestStopped())
+      break;
+
+    if (rss_check)
+    {
+      g_info << "check all resource usage" << endl;
+      int dump2[] = { DumpStateOrd::SchemaResourceCheckLeak };
+      CHK2(restarter.dumpStateAllNodes(dump2, 1) == 0, "failed");
+
+      g_info << "check cluster is up" << endl;
+      CHK2(restarter.waitClusterStarted() == 0, "failed");
+    }
+
+    if (++loop == loops)
     {
-      g_info << "drop table " << tabname << endl;
       CHK2(pDic->dropTable(tabname) == 0, pDic->getNdbError());
+      g_info << "table " << tabname << " dropped" << endl;
+      break;
     }
   }
 
@@ -8622,7 +8964,12 @@ TESTCASE("Bug53944", "")
 TESTCASE("Bug58277",
          "Dropping busy ordered index can crash data node.\n"
          "Give any tablename as argument (T1)"){
+  TC_PROPERTY("RSS_CHECK", (Uint32)true);
+  TC_PROPERTY("RANGE_MAX", (Uint32)5);
+  INITIALIZER(runBug58277errtest);
   STEP(runBug58277);
+  // sub-steps 2-8 synced with main step
+  TC_PROPERTY("SubSteps", 7);
   STEP(runBug58277drop);
   /*
    * A single scan update can show the bug but this is not likely.
@@ -8634,6 +8981,18 @@ TESTCASE("Bug58277",
   STEP(runBug58277scan);
   STEP(runBug58277pk);
   STEP(runBug58277pk);
+  // kernel side scans (eg. LCP) for resource usage check
+  STEP(runBug58277rand);
+}
+TESTCASE("Bug57057",
+         "MRR + delete leaks stored procs (fixed under Bug58277).\n"
+         "Give any tablename as argument (T1)"){
+  TC_PROPERTY("RSS_CHECK", (Uint32)true);
+  TC_PROPERTY("RANGE_MAX", (Uint32)100);
+  TC_PROPERTY("SCAN_DELETE", (Uint32)1);
+  STEP(runBug57057);
+  TC_PROPERTY("SubSteps", 1);
+  STEP(runBug58277scan);
 }
 NDBT_TESTSUITE_END(testDict);
 

=== modified file 'storage/ndb/test/run-test/daily-basic-tests.txt'
--- a/storage/ndb/test/run-test/daily-basic-tests.txt	2010-12-13 13:20:16 +0000
+++ b/storage/ndb/test/run-test/daily-basic-tests.txt	2011-01-03 15:08:41 +0000
@@ -1629,3 +1629,7 @@ max-time: 300
 cmd: testDict
 args: -n Bug58277 T1
 
+max-time: 300
+cmd: testDict
+args: -n Bug57057 T1
+


Attachment: [text/bzr-bundle] bzr/pekka@mysql.com-20110103150841-7tgh4tfp10wsvz9k.bundle
Thread
bzr commit into mysql-5.1-telco-7.0 branch (pekka:4087) Pekka Nousiainen3 Jan