List:Commits« Previous MessageNext Message »
From:Jonas Oreland Date:November 2 2009 5:08pm
Subject:bzr commit into mysql-5.1-telco-6.3 branch (jonas:3150) Bug#48474
View as plain text  
#At file:///home/jonas/src/telco-6.3/ based on revid:jonas@stripped

 3150 Jonas Oreland	2009-11-02
      ndb - bug#48474 - don't start logging until all fragments has been copied

    modified:
      storage/ndb/include/kernel/signaldata/CopyActive.hpp
      storage/ndb/include/kernel/signaldata/DihContinueB.hpp
      storage/ndb/include/kernel/signaldata/TakeOver.hpp
      storage/ndb/include/ndb_version.h.in
      storage/ndb/src/kernel/blocks/dbdih/Dbdih.hpp
      storage/ndb/src/kernel/blocks/dbdih/DbdihMain.cpp
      storage/ndb/src/kernel/blocks/dblqh/DblqhMain.cpp
      storage/ndb/test/ndbapi/testNodeRestart.cpp
=== modified file 'storage/ndb/include/kernel/signaldata/CopyActive.hpp'
--- a/storage/ndb/include/kernel/signaldata/CopyActive.hpp	2009-05-26 18:53:34 +0000
+++ b/storage/ndb/include/kernel/signaldata/CopyActive.hpp	2009-11-02 17:08:02 +0000
@@ -32,7 +32,13 @@ class CopyActiveReq {
    */
   friend class Dblqh;
 public:
-  STATIC_CONST( SignalLength = 5 );
+  STATIC_CONST( SignalLength = 6 );
+
+  enum Flags
+  {
+    CAR_NO_WAIT = 0x1
+    ,CAR_NO_LOGGING = 0x2
+  };
 
 private:
   Uint32 userPtr;
@@ -40,6 +46,7 @@ private:
   Uint32 tableId;
   Uint32 fragId;
   Uint32 distributionKey;
+  Uint32 flags;
 };
 
 class CopyActiveConf {

=== modified file 'storage/ndb/include/kernel/signaldata/DihContinueB.hpp'
--- a/storage/ndb/include/kernel/signaldata/DihContinueB.hpp	2009-05-27 12:11:46 +0000
+++ b/storage/ndb/include/kernel/signaldata/DihContinueB.hpp	2009-11-02 17:08:02 +0000
@@ -72,6 +72,7 @@ private:
     ,ZCOPY_NODE_WAIT_CREATE_FRAG = 45
     ,ZLCP_TRY_LOCK = 46
     ,ZDELAY_RELEASE_FRAGMENT_INFO_MUTEX = 47
+    ,ZTO_START_LOGGING = 48
   };
 };
 

=== modified file 'storage/ndb/include/kernel/signaldata/TakeOver.hpp'
--- a/storage/ndb/include/kernel/signaldata/TakeOver.hpp	2009-05-27 12:11:46 +0000
+++ b/storage/ndb/include/kernel/signaldata/TakeOver.hpp	2009-11-02 17:08:02 +0000
@@ -133,7 +133,8 @@ struct CreateFragReq 
 
   enum ReplicaType {
     STORED = 7,
-    COMMIT_STORED = 9
+    COMMIT_STORED = 9,
+    START_LOGGING = 10
   };
 
   Uint32 senderData;

=== modified file 'storage/ndb/include/ndb_version.h.in'
--- a/storage/ndb/include/ndb_version.h.in	2009-05-27 12:11:46 +0000
+++ b/storage/ndb/include/ndb_version.h.in	2009-11-02 17:08:02 +0000
@@ -239,6 +239,9 @@ ndbd_LIST_TABLES_CONF_long_signal(Uint32
 #define NDBD_API_TAKE_OVERTCCONF_62 NDB_MAKE_VERSION(6,2,17)
 #define NDBD_API_TAKE_OVERTCCONF_63 NDB_MAKE_VERSION(6,3,19)
 
+#define NDBD_DELAYED_COPY_ACTIVEREQ_63 NDB_MAKE_VERSION(6,3,29)
+#define NDBD_DELAYED_COPY_ACTIVEREQ_70 NDB_MAKE_VERSION(7,0,10)
+
 static
 inline
 int
@@ -261,4 +264,26 @@ ndb_takeovertc(Uint32 x)
   }
 }
 
+static
+inline
+int
+ndb_delayed_copy_active_req(Uint32 x)
+{
+  if (x >= NDB_VERSION_D)
+    return 1;
+
+  {
+    const Uint32 major = (x >> 16) & 0xFF;
+
+    if (major >= 6)
+    {
+      return x >= NDBD_DELAYED_COPY_ACTIVEREQ_63;
+    }
+    else
+    {
+      return x >= NDBD_DELAYED_COPY_ACTIVEREQ_70;
+    }
+  }
+}
+
 #endif

=== modified file 'storage/ndb/src/kernel/blocks/dbdih/Dbdih.hpp'
--- a/storage/ndb/src/kernel/blocks/dbdih/Dbdih.hpp	2009-10-30 13:56:03 +0000
+++ b/storage/ndb/src/kernel/blocks/dbdih/Dbdih.hpp	2009-11-02 17:08:02 +0000
@@ -539,7 +539,10 @@ public:
       ,TO_CREATE_FRAG_COMMIT = 12  // Waiting for all (CREATE_FRAGREQ commit)
       ,TO_UPDATE_AFTER_COMMIT = 13 // Waiting for master (UPDATE_TOREQ)
 
-      ,TO_END_TO = 14               // Waiting for master (EBND_TOREQ)
+      ,TO_START_LOGGING = 14        // Enabling logging on all fragments
+      ,TO_SL_COPY_ACTIVE = 15       // Start logging: Copy active (local)
+      ,TO_SL_CREATE_FRAG = 16       // Start logging: Create Frag (dist)
+      ,TO_END_TO = 17               // Waiting for master (EBND_TOREQ)
     };
 
     /**
@@ -1186,7 +1189,8 @@ private:
   void nr_start_fragments(Signal*, TakeOverRecordPtr);
   void nr_start_fragment(Signal*, TakeOverRecordPtr, ReplicaRecordPtr);
   void nr_run_redo(Signal*, TakeOverRecordPtr);
-  
+  void nr_start_logging(Signal*, TakeOverRecordPtr);
+
   // Initialisation
   void initData();
   void initRecords();

=== modified file 'storage/ndb/src/kernel/blocks/dbdih/DbdihMain.cpp'
--- a/storage/ndb/src/kernel/blocks/dbdih/DbdihMain.cpp	2009-10-30 13:56:03 +0000
+++ b/storage/ndb/src/kernel/blocks/dbdih/DbdihMain.cpp	2009-11-02 17:08:02 +0000
@@ -649,6 +649,14 @@ void Dbdih::execCONTINUEB(Signal* signal
     mutex.unlock();
     return;
   }
+  case DihContinueB::ZTO_START_LOGGING:
+  {
+    jam();
+    TakeOverRecordPtr takeOverPtr;
+    c_takeOverPool.getPtr(takeOverPtr, signal->theData[1]);
+    nr_start_logging(signal, takeOverPtr);
+    return;
+  }
   
   }//switch
   
@@ -3249,7 +3257,7 @@ Dbdih::check_force_lcp(Ptr<TakeOverRecor
       }
     }
   }
-  add_lcp_counter(&c_lcpState.ctimer, (1 << c_lcpState.clcpDelay));  
+  add_lcp_counter(&c_lcpState.ctimer, (1 << 31));
 }
 
 void Dbdih::execEND_TOREQ(Signal* signal)
@@ -3329,7 +3337,8 @@ void Dbdih::execCREATE_FRAGREQ(Signal* s
   getFragstore(tabPtr.p, fragId, fragPtr);
   RETURN_IF_NODE_NOT_ALIVE(tdestNodeid);
   ReplicaRecordPtr frReplicaPtr;
-  findReplica(frReplicaPtr, fragPtr.p, tFailedNodeId, true);
+  findReplica(frReplicaPtr, fragPtr.p, tFailedNodeId,
+              replicaType == CreateFragReq::START_LOGGING ? false : true);
   if (frReplicaPtr.i == RNIL)
   {
     dump_replica_info(fragPtr.p);
@@ -3363,6 +3372,9 @@ void Dbdih::execCREATE_FRAGREQ(Signal* s
     linkStoredReplica(fragPtr, frReplicaPtr);
     updateNodeInfo(fragPtr);
     break;
+  case CreateFragReq::START_LOGGING:
+    jam();
+    break;
   default:
     ndbrequire(false);
     break;
@@ -3654,6 +3666,84 @@ Dbdih::nr_run_redo(Signal* signal, TakeO
 }
 
 void
+Dbdih::nr_start_logging(Signal* signal, TakeOverRecordPtr takeOverPtr)
+{
+  Uint32 loopCount = 0 ;
+  TabRecordPtr tabPtr;
+  while (loopCount++ < 100)
+  {
+    tabPtr.i = takeOverPtr.p->toCurrentTabref;
+    if (tabPtr.i >= ctabFileSize)
+    {
+      jam();
+      takeOverPtr.p->toSlaveStatus = TakeOverRecord::TO_END_TO;
+      EndToReq* req = (EndToReq*)signal->getDataPtrSend();
+      req->senderData = takeOverPtr.i;
+      req->senderRef = reference();
+      req->flags = takeOverPtr.p->m_flags;
+      sendSignal(cmasterdihref, GSN_END_TOREQ,
+                 signal, EndToReq::SignalLength, JBB);
+
+      return;
+    }
+    ptrAss(tabPtr, tabRecord);
+    if (tabPtr.p->tabStatus != TabRecord::TS_ACTIVE ||
+	tabPtr.p->tabStorage != TabRecord::ST_NORMAL)
+    {
+      jam();
+      takeOverPtr.p->toCurrentFragid = 0;
+      takeOverPtr.p->toCurrentTabref++;
+      continue;
+    }
+
+    Uint32 fragId = takeOverPtr.p->toCurrentFragid;
+    if (fragId >= tabPtr.p->totalfragments)
+    {
+      jam();
+      takeOverPtr.p->toCurrentFragid = 0;
+      takeOverPtr.p->toCurrentTabref++;
+      continue;
+    }
+
+    FragmentstorePtr fragPtr;
+    getFragstore(tabPtr.p, fragId, fragPtr);
+    ReplicaRecordPtr loopReplicaPtr;
+    loopReplicaPtr.i = fragPtr.p->storedReplicas;
+    while (loopReplicaPtr.i != RNIL)
+    {
+      ptrCheckGuard(loopReplicaPtr, creplicaFileSize, replicaRecord);
+      if (loopReplicaPtr.p->procNode == takeOverPtr.p->toStartingNode)
+      {
+        jam();
+        ndbrequire(loopReplicaPtr.p->procNode == getOwnNodeId());
+        takeOverPtr.p->toSlaveStatus = TakeOverRecord::TO_SL_COPY_ACTIVE;
+
+        CopyActiveReq * const req = (CopyActiveReq *)&signal->theData[0];
+        req->userPtr = takeOverPtr.i;
+        req->userRef = reference();
+        req->tableId = takeOverPtr.p->toCurrentTabref;
+        req->fragId = takeOverPtr.p->toCurrentFragid;
+        req->distributionKey = fragPtr.p->distributionKey;
+        req->flags = 0;
+        sendSignal(calcLqhBlockRef(loopReplicaPtr.p->procNode),
+                   GSN_COPY_ACTIVEREQ, signal,
+                   CopyActiveReq::SignalLength, JBB);
+        return;
+      }
+      else
+      {
+        jam();
+        loopReplicaPtr.i = loopReplicaPtr.p->nextReplica;
+      }
+    }
+    takeOverPtr.p->toCurrentFragid++;
+  }
+  signal->theData[0] = DihContinueB::ZTO_START_LOGGING;
+  signal->theData[1] = takeOverPtr.i;
+  sendSignal(reference(), GSN_CONTINUEB, signal, 2, JBB);
+}
+
+void
 Dbdih::sendStartTo(Signal* signal, TakeOverRecordPtr takeOverPtr)
 {
   takeOverPtr.p->toSlaveStatus = TakeOverRecord::TO_START_TO;
@@ -4045,6 +4135,15 @@ void Dbdih::execCREATE_FRAGCONF(Signal* 
     CRASH_INSERTION(7199);
     takeOverPtr.p->toSlaveStatus = TakeOverRecord::TO_UPDATE_AFTER_COMMIT;
     break;
+  case TakeOverRecord::TO_SL_CREATE_FRAG:
+    jam();
+    //CRASH_INSERTION(
+    takeOverPtr.p->toSlaveStatus = TakeOverRecord::TO_START_LOGGING;
+    takeOverPtr.p->toCurrentFragid++;
+    signal->theData[0] = DihContinueB::ZTO_START_LOGGING;
+    signal->theData[1] = takeOverPtr.i;
+    sendSignal(reference(), GSN_CONTINUEB, signal, 2, JBB);
+    return;
   default:
     jamLine(takeOverPtr.p->toSlaveStatus);
     ndbrequire(false);
@@ -4115,6 +4214,19 @@ void Dbdih::execCOPY_FRAGCONF(Signal* si
   req->tableId = takeOverPtr.p->toCurrentTabref;
   req->fragId = takeOverPtr.p->toCurrentFragid;
   req->distributionKey = fragPtr.p->distributionKey;
+  req->flags = 0;
+
+  Uint32 min_version = getNodeVersionInfo().m_type[NodeInfo::DB].m_min_version;
+  if (ndb_delayed_copy_active_req(min_version))
+  {
+    jam();
+    /**
+     * Bug48474 - Don't start logging an fragment
+     *            until all fragments has been copied
+     *            Else it's easy to run out of REDO
+     */
+    req->flags |= CopyActiveReq::CAR_NO_WAIT | CopyActiveReq::CAR_NO_LOGGING;
+  }
   
   sendSignal(lqhRef, GSN_COPY_ACTIVEREQ, signal,
              CopyActiveReq::SignalLength, JBB);
@@ -4144,12 +4256,24 @@ void Dbdih::execCOPY_ACTIVECONF(Signal* 
   ndbrequire(conf->tableId == takeOverPtr.p->toCurrentTabref);
   ndbrequire(conf->fragId == takeOverPtr.p->toCurrentFragid);
   ndbrequire(checkNodeAlive(conf->startingNodeId));
-  ndbrequire(takeOverPtr.p->toSlaveStatus == TakeOverRecord::TO_COPY_ACTIVE);
 
   takeOverPtr.p->startGci = conf->startGci;
-  takeOverPtr.p->toSlaveStatus = TakeOverRecord::TO_UPDATE_BEFORE_COMMIT;
 
-  sendUpdateTo(signal, takeOverPtr);
+  if (takeOverPtr.p->toSlaveStatus == TakeOverRecord::TO_COPY_ACTIVE)
+  {
+    jam();
+    ndbrequire(takeOverPtr.p->toSlaveStatus == TakeOverRecord::TO_COPY_ACTIVE);
+    takeOverPtr.p->toSlaveStatus = TakeOverRecord::TO_UPDATE_BEFORE_COMMIT;
+    sendUpdateTo(signal, takeOverPtr);
+  }
+  else
+  {
+    jam();
+    ndbrequire(takeOverPtr.p->toSlaveStatus==TakeOverRecord::TO_SL_COPY_ACTIVE);
+    takeOverPtr.p->toSlaveStatus = TakeOverRecord::TO_SL_CREATE_FRAG;
+    sendCreateFragReq(signal, takeOverPtr.p->startGci,
+                      CreateFragReq::START_LOGGING, takeOverPtr.i);
+  }
 }//Dbdih::execCOPY_ACTIVECONF()
 
 void Dbdih::toCopyCompletedLab(Signal * signal, TakeOverRecordPtr takeOverPtr)
@@ -4158,13 +4282,31 @@ void Dbdih::toCopyCompletedLab(Signal * 
   signal->theData[1] = takeOverPtr.p->toStartingNode;
   sendSignal(CMVMI_REF, GSN_EVENT_REP, signal, 2, JBB);
 
-  takeOverPtr.p->toSlaveStatus = TakeOverRecord::TO_END_TO;
-  EndToReq* req = (EndToReq*)signal->getDataPtrSend();
-  req->senderData = takeOverPtr.i;
-  req->senderRef = reference();
-  req->flags = takeOverPtr.p->m_flags;
-  sendSignal(cmasterdihref, GSN_END_TOREQ,
-             signal, EndToReq::SignalLength, JBB);
+  Uint32 min_version = getNodeVersionInfo().m_type[NodeInfo::DB].m_min_version;
+  if (ndb_delayed_copy_active_req(min_version))
+  {
+    jam();
+    takeOverPtr.p->toSlaveStatus = TakeOverRecord::TO_START_LOGGING;
+    takeOverPtr.p->toCurrentTabref = 0;
+    takeOverPtr.p->toCurrentFragid = 0;
+    takeOverPtr.p->toCurrentReplica = RNIL;
+    nr_start_logging(signal, takeOverPtr);
+    return;
+  }
+  else
+  {
+    jam();
+
+    takeOverPtr.p->toSlaveStatus = TakeOverRecord::TO_END_TO;
+
+    EndToReq* req = (EndToReq*)signal->getDataPtrSend();
+    req->senderData = takeOverPtr.i;
+    req->senderRef = reference();
+    req->flags = takeOverPtr.p->m_flags;
+    sendSignal(cmasterdihref, GSN_END_TOREQ,
+               signal, EndToReq::SignalLength, JBB);
+    return;
+  }
 }//Dbdih::toCopyCompletedLab()
 
 void
@@ -15554,7 +15696,7 @@ Dbdih::execDUMP_STATE_ORD(Signal* signal
     EXECUTE_DIRECT(DBTUP, GSN_DUMP_STATE_ORD, signal, 2);
     
     // Start immediate LCP
-    add_lcp_counter(&c_lcpState.ctimer, (1 << c_lcpState.clcpDelay));
+    add_lcp_counter(&c_lcpState.ctimer, (1 << 31));
     return;
   }
 
@@ -15603,7 +15745,7 @@ Dbdih::execDUMP_STATE_ORD(Signal* signal
   }
 
   if(arg == DumpStateOrd::DihStartLcpImmediately){
-    add_lcp_counter(&c_lcpState.ctimer, (1 << c_lcpState.clcpDelay));
+    add_lcp_counter(&c_lcpState.ctimer, (1 << 31));
     return;
   }
 

=== modified file 'storage/ndb/src/kernel/blocks/dblqh/DblqhMain.cpp'
--- a/storage/ndb/src/kernel/blocks/dblqh/DblqhMain.cpp	2009-10-30 13:56:03 +0000
+++ b/storage/ndb/src/kernel/blocks/dblqh/DblqhMain.cpp	2009-11-02 17:08:02 +0000
@@ -11417,42 +11417,51 @@ void Dblqh::execCOPY_ACTIVEREQ(Signal* s
   tabptr.i = req->tableId;
   ptrCheckGuard(tabptr, ctabrecFileSize, tablerec);
   Uint32 fragId = req->fragId;
+  Uint32 flags = req->flags;
+  if (unlikely(signal->getLength() < CopyActiveReq::SignalLength))
+  {
+    jam();
+    flags = 0;
+  }
+
   ndbrequire(getFragmentrec(signal, fragId));
 
+  fragptr.p->fragStatus = Fragrecord::FSACTIVE;
   fragptr.p->fragDistributionKey = req->distributionKey;
   
+  if (TRACENR_FLAG)
+    TRACENR("tab: " << tabptr.i
+	    << " frag: " << fragId
+	    << " COPY ACTIVE"
+            << " flags: " << hex << flags << endl);
+
   ndbrequire(cnoActiveCopy < 3);
   cactiveCopy[cnoActiveCopy] = fragptr.i;
   cnoActiveCopy++;
   fragptr.p->masterBlockref = masterRef;
   fragptr.p->masterPtr = masterPtr;
-  if (fragptr.p->fragStatus == Fragrecord::FSACTIVE) {
+
+  if ((flags & CopyActiveReq::CAR_NO_LOGGING) == 0)
+  {
     jam();
-/*------------------------------------------------------*/
-/*       PROCESS HAVE ALREADY BEEN STARTED BY PREVIOUS  */
-/*       MASTER. WE HAVE ALREADY SET THE PROPER MASTER  */
-/*       BLOCK REFERENCE.                               */
-/*------------------------------------------------------*/
-    if (fragptr.p->activeTcCounter == 0) {
+    if (fragptr.p->lcpFlag == Fragrecord::LCP_STATE_TRUE)
+    {
       jam();
-/*------------------------------------------------------*/
-/*       PROCESS WAS EVEN COMPLETED.                    */
-/*------------------------------------------------------*/
-      sendCopyActiveConf(signal, tabptr.i);
-    }//if
-    return;
-  }//if
-  
-  fragptr.p->fragStatus = Fragrecord::FSACTIVE;
-  if (TRACENR_FLAG)
-    TRACENR("tab: " << tabptr.i 
-	    << " frag: " << fragId 
-	    << " COPY ACTIVE" << endl);
+      fragptr.p->logFlag = Fragrecord::STATE_TRUE;
+    }
+  }
   
-  if (fragptr.p->lcpFlag == Fragrecord::LCP_STATE_TRUE) {
+  if (flags & CopyActiveReq::CAR_NO_WAIT)
+  {
     jam();
-    fragptr.p->logFlag = Fragrecord::STATE_TRUE;
-  }//if
+    ndbrequire(fragptr.p->activeTcCounter == 0);
+    Uint32 save = fragptr.p->startGci;
+    fragptr.p->startGci = 0;
+    sendCopyActiveConf(signal, tabptr.i);
+    fragptr.p->startGci = save;
+    return;
+  }
+
   fragptr.p->activeTcCounter = 1;
 /*------------------------------------------------------*/
 /*       SET IT TO ONE TO ENSURE THAT IT IS NOT POSSIBLE*/

=== modified file 'storage/ndb/test/ndbapi/testNodeRestart.cpp'
--- a/storage/ndb/test/ndbapi/testNodeRestart.cpp	2009-09-25 12:49:37 +0000
+++ b/storage/ndb/test/ndbapi/testNodeRestart.cpp	2009-11-02 17:08:02 +0000
@@ -3762,6 +3762,127 @@ runBug44952(NDBT_Context* ctx, NDBT_Step
   return NDBT_OK;
 }
 
+static BaseString tab_48474;
+
+int
+initBug48474(NDBT_Context* ctx, NDBT_Step* step)
+{
+  NdbDictionary::Table tab = * ctx->getTab();
+  NdbDictionary::Dictionary* pDict = GETNDB(step)->getDictionary();
+
+  const NdbDictionary::Table * pTab = pDict->getTable(tab.getName());
+  if (pTab == 0)
+    return NDBT_FAILED;
+
+  /**
+   * Create a table with tableid > ctx->getTab()
+   */
+  Uint32 cnt = 0;
+  Vector<BaseString> tables;
+  do
+  {
+    BaseString tmp;
+    tmp.assfmt("%s_%u", tab.getName(), cnt);
+    tab.setName(tmp.c_str());
+
+    pDict->dropTable(tab.getName());
+    if (pDict->createTable(tab) != 0)
+      return NDBT_FAILED;
+
+    const NdbDictionary::Table * pTab2 = pDict->getTable(tab.getName());
+    if (pTab2->getObjectId() < pTab->getObjectId())
+    {
+      tables.push_back(tmp);
+    }
+    else
+    {
+      tab_48474 = tmp;
+      HugoTransactions hugoTrans(* pTab2);
+      if (hugoTrans.loadTable(GETNDB(step), 1000) != 0)
+      {
+        return NDBT_FAILED;
+      }
+      break;
+    }
+    cnt++;
+  } while(true);
+
+  // Now delete the extra one...
+  for (Uint32 i = 0; i<tables.size(); i++)
+  {
+    pDict->dropTable(tables[i].c_str());
+  }
+
+  tables.clear();
+
+  return NDBT_OK;
+}
+
+int
+runBug48474(NDBT_Context* ctx, NDBT_Step* step)
+{
+  NdbRestarter res;
+  NdbDictionary::Dictionary* pDict = GETNDB(step)->getDictionary();
+  const NdbDictionary::Table * pTab = pDict->getTable(tab_48474.c_str());
+  Ndb* pNdb = GETNDB(step);
+  HugoOperations hugoOps(* pTab);
+
+  int nodeId = res.getNode(NdbRestarter::NS_RANDOM);
+  ndbout_c("restarting %d", nodeId);
+  res.restartOneDbNode(nodeId, false, true, true);
+  res.waitNodesNoStart(&nodeId, 1);
+
+  int minlcp[] = { 7017, 1 };
+  res.dumpStateAllNodes(minlcp, 1); // Set min time between LCP
+
+  ndbout_c("starting %d", nodeId);
+  res.startNodes(&nodeId, 1);
+
+  Uint32 minutes = 5;
+  ndbout_c("starting uncommitted transaction %u minutes", minutes);
+  for (Uint32 m = 0; m < minutes; m++)
+  {
+    if (hugoOps.startTransaction(pNdb) != 0)
+      return NDBT_FAILED;
+
+    if (hugoOps.pkUpdateRecord(pNdb, 0, 50, rand()) != 0)
+      return NDBT_FAILED;
+
+    if (hugoOps.execute_NoCommit(pNdb) != 0)
+      return NDBT_FAILED;
+
+
+    ndbout_c("sleeping 60s");
+    for (Uint32 i = 0; i<600 && !ctx->isTestStopped(); i++)
+    {
+      hugoOps.getTransaction()->refresh();
+      NdbSleep_MilliSleep(100);
+    }
+
+    if (hugoOps.execute_Commit(pNdb) != 0)
+      return NDBT_FAILED;
+
+    hugoOps.closeTransaction(pNdb);
+
+    if (ctx->isTestStopped())
+      break;
+  }
+
+
+  res.dumpStateAllNodes(minlcp, 2); // reset min time between LCP
+
+  ctx->stopTest();
+  return NDBT_OK;
+}
+
+int
+cleanupBug48474(NDBT_Context* ctx, NDBT_Step* step)
+{
+  NdbDictionary::Dictionary* pDict = GETNDB(step)->getDictionary();
+  pDict->dropTable(tab_48474.c_str());
+  return NDBT_OK;
+}
+
 NDBT_TESTSUITE(testNodeRestart);
 TESTCASE("NoLoad", 
 	 "Test that one node at a time can be stopped and then restarted "\
@@ -4259,6 +4380,14 @@ TESTCASE("Bug44952",
   FINALIZER(runScanReadVerify);
   FINALIZER(runClearTable);
 }
+TESTCASE("Bug48474", "")
+{
+  INITIALIZER(runLoadTable);
+  INITIALIZER(initBug48474);
+  STEP(runBug48474);
+  STEP(runScanUpdateUntilStopped);
+  FINALIZER(cleanupBug48474);
+}
 NDBT_TESTSUITE_END(testNodeRestart);
 
 int main(int argc, const char** argv){


Attachment: [text/bzr-bundle] bzr/jonas@mysql.com-20091102170802-dl2joq3y18z8wpzg.bundle
Thread
bzr commit into mysql-5.1-telco-6.3 branch (jonas:3150) Bug#48474Jonas Oreland2 Nov