List:Commits« Previous MessageNext Message »
From:jonas Date:February 3 2008 9:30am
Subject:bk commit into 5.1 tree (jonas:1.2862)
View as plain text  
Below is the list of changes that have just been committed into a local
5.1 repository of jonas.  When jonas does a push these changes
will be propagated to the main repository and, within 24 hours after the
push, to the public repository.
For information on how to access the public repository
see http://dev.mysql.com/doc/mysql/en/installing-source-tree.html

ChangeSet@stripped, 2008-02-03 10:30:10+01:00, jonas@stripped +9 -0
  bug34216 - commit to autotest

  storage/ndb/src/kernel/blocks/ERROR_codes.txt@stripped, 2008-02-03 10:30:08+01:00, jonas@stripped +7 -1
    new error codes

  storage/ndb/src/kernel/blocks/dblqh/DblqhMain.cpp@stripped, 2008-02-03 10:30:08+01:00, jonas@stripped +6 -0
    new error codes

  storage/ndb/src/kernel/blocks/dbtc/DbtcMain.cpp@stripped, 2008-02-03 10:30:08+01:00, jonas@stripped +4 -1
    new error code

  storage/ndb/src/kernel/blocks/dbtup/Dbtup.hpp@stripped, 2008-02-03 10:30:08+01:00, jonas@stripped +1 -1
    bug34216 - commit to autotest

  storage/ndb/src/kernel/blocks/dbtup/DbtupAbort.cpp@stripped, 2008-02-03 10:30:08+01:00, jonas@stripped +35 -0
    bug34216 - commit to autotest

  storage/ndb/src/kernel/blocks/dbtup/DbtupCommit.cpp@stripped, 2008-02-03 10:30:08+01:00, jonas@stripped +94 -117
    bug34216 - commit to autotest

  storage/ndb/src/kernel/blocks/dbtup/DbtupExecQuery.cpp@stripped, 2008-02-03 10:30:08+01:00, jonas@stripped +1 -1
    bug34216 - commit to autotest

  storage/ndb/test/ndbapi/testNodeRestart.cpp@stripped, 2008-02-03 10:30:08+01:00, jonas@stripped +253 -9
    bug34216 - commit to autotest

  storage/ndb/test/run-test/daily-basic-tests.txt@stripped, 2008-02-03 10:30:08+01:00, jonas@stripped +8 -0
    bug34216 - commit to autotest

diff -Nrup a/storage/ndb/src/kernel/blocks/ERROR_codes.txt b/storage/ndb/src/kernel/blocks/ERROR_codes.txt
--- a/storage/ndb/src/kernel/blocks/ERROR_codes.txt	2008-01-24 12:30:23 +01:00
+++ b/storage/ndb/src/kernel/blocks/ERROR_codes.txt	2008-02-03 10:30:08 +01:00
@@ -3,7 +3,7 @@ Next NDBCNTR 1002
 Next NDBFS 2000
 Next DBACC 3002
 Next DBTUP 4029
-Next DBLQH 5048
+Next DBLQH 5050
 Next DBDICT 6008
 Next DBDIH 7202
 Next DBTC 8057
@@ -255,6 +255,10 @@ Delay execution of ABORTREQ signal 2 sec
 
 5047: ZTRANSPORTER_OVERLOADED_ERROR in execLQHKEYREQ
 
+5048: Crash in execCOMMIT
+5049: SET_ERROR_INSERT_VALUE(5048)
+
+
 ERROR CODES FOR TESTING TIME-OUT HANDLING IN DBTC
 -------------------------------------------------
 8040:
@@ -340,6 +344,8 @@ ABORT OF TCKEYREQ
 
 8055 : Crash in sendApiCommit, disconnect API, and set 8056
 8056 : return directly in API_FAILREQ
+
+8057 : Send only 1 COMMIT per timeslice
 
 8052 : Simulate failure of TransactionBufferMemory allocation for OI lookup
 
diff -Nrup a/storage/ndb/src/kernel/blocks/dblqh/DblqhMain.cpp b/storage/ndb/src/kernel/blocks/dblqh/DblqhMain.cpp
--- a/storage/ndb/src/kernel/blocks/dblqh/DblqhMain.cpp	2008-01-08 15:20:34 +01:00
+++ b/storage/ndb/src/kernel/blocks/dblqh/DblqhMain.cpp	2008-02-03 10:30:08 +01:00
@@ -6045,6 +6045,12 @@ void Dblqh::execCOMMIT(Signal* signal) 
     TcConnectionrec * const regTcPtr = tcConnectptr.p;
     TRACE_OP(regTcPtr, "COMMIT");
     
+    CRASH_INSERTION(5048);
+    if (ERROR_INSERTED(5049))
+    {
+      SET_ERROR_INSERT_VALUE(5048);
+    }
+
     commitReqLab(signal, gci_hi, gci_lo);
     return;
   }//if
diff -Nrup a/storage/ndb/src/kernel/blocks/dbtc/DbtcMain.cpp b/storage/ndb/src/kernel/blocks/dbtc/DbtcMain.cpp
--- a/storage/ndb/src/kernel/blocks/dbtc/DbtcMain.cpp	2008-01-23 10:41:04 +01:00
+++ b/storage/ndb/src/kernel/blocks/dbtc/DbtcMain.cpp	2008-02-03 10:30:08 +01:00
@@ -4525,7 +4525,7 @@ void Dbtc::commit020Lab(Signal* signal) 
 
     if (localTcConnectptr.i != RNIL) {
       Tcount = Tcount + 1;
-      if (Tcount < 16) {
+      if (Tcount < 16 && !ERROR_INSERTED(8057)) {
         ptrCheckGuard(localTcConnectptr,
                       TtcConnectFilesize, localTcConnectRecord);
         jam();
@@ -4544,6 +4544,9 @@ void Dbtc::commit020Lab(Signal* signal) 
       }//if
     } else {
       jam();
+      if (ERROR_INSERTED(8057))
+        CLEAR_ERROR_INSERT_VALUE;
+
       regApiPtr->apiConnectstate = CS_COMMIT_SENT;
       return;
     }//if
diff -Nrup a/storage/ndb/src/kernel/blocks/dbtup/Dbtup.hpp b/storage/ndb/src/kernel/blocks/dbtup/Dbtup.hpp
--- a/storage/ndb/src/kernel/blocks/dbtup/Dbtup.hpp	2008-02-01 07:30:18 +01:00
+++ b/storage/ndb/src/kernel/blocks/dbtup/Dbtup.hpp	2008-02-03 10:30:08 +01:00
@@ -3167,7 +3167,7 @@ private:
   void verify_page_lists(Disk_alloc_info&) {}
 #endif
   
-  void fix_commit_order(OperationrecPtr);
+  void findFirstOp(OperationrecPtr&);
   void commit_operation(Signal*, Uint32, Tuple_header*, PagePtr,
 			Operationrec*, Fragrecord*, Tablerec*);
   
diff -Nrup a/storage/ndb/src/kernel/blocks/dbtup/DbtupAbort.cpp b/storage/ndb/src/kernel/blocks/dbtup/DbtupAbort.cpp
--- a/storage/ndb/src/kernel/blocks/dbtup/DbtupAbort.cpp	2007-08-30 13:22:09 +02:00
+++ b/storage/ndb/src/kernel/blocks/dbtup/DbtupAbort.cpp	2008-02-03 10:30:08 +01:00
@@ -410,3 +410,38 @@ void Dbtup::send_TUPKEYREF(Signal* signa
              TupKeyRef::SignalLength, JBB);
 }
 
+void Dbtup::removeActiveOpList(Operationrec*  const regOperPtr,
+                               Tuple_header *tuple_ptr)
+{
+  OperationrecPtr raoOperPtr;
+
+  /**
+   * Release copy tuple
+   */
+  if(!regOperPtr->m_copy_tuple_location.isNull())
+  {
+    jam();
+    c_undo_buffer.free_copy_tuple(&regOperPtr->m_copy_tuple_location);
+  }
+
+  if (regOperPtr->op_struct.in_active_list) {
+    regOperPtr->op_struct.in_active_list= false;
+    if (regOperPtr->nextActiveOp != RNIL) {
+      jam();
+      raoOperPtr.i= regOperPtr->nextActiveOp;
+      c_operation_pool.getPtr(raoOperPtr);
+      raoOperPtr.p->prevActiveOp= regOperPtr->prevActiveOp;
+    } else {
+      jam();
+      tuple_ptr->m_operation_ptr_i = regOperPtr->prevActiveOp;
+    }
+    if (regOperPtr->prevActiveOp != RNIL) {
+      jam();
+      raoOperPtr.i= regOperPtr->prevActiveOp;
+      c_operation_pool.getPtr(raoOperPtr);
+      raoOperPtr.p->nextActiveOp= regOperPtr->nextActiveOp;
+    }
+    regOperPtr->prevActiveOp= RNIL;
+    regOperPtr->nextActiveOp= RNIL;
+  }
+}
diff -Nrup a/storage/ndb/src/kernel/blocks/dbtup/DbtupCommit.cpp b/storage/ndb/src/kernel/blocks/dbtup/DbtupCommit.cpp
--- a/storage/ndb/src/kernel/blocks/dbtup/DbtupCommit.cpp	2008-01-24 15:57:08 +01:00
+++ b/storage/ndb/src/kernel/blocks/dbtup/DbtupCommit.cpp	2008-02-03 10:30:08 +01:00
@@ -100,42 +100,6 @@ void Dbtup::execTUP_WRITELOG_REQ(Signal*
   } while (true);
 }
 
-void Dbtup::removeActiveOpList(Operationrec*  const regOperPtr,
-                               Tuple_header *tuple_ptr)
-{
-  OperationrecPtr raoOperPtr;
-
-  /**
-   * Release copy tuple
-   */
-  if(!regOperPtr->m_copy_tuple_location.isNull())
-  {
-    jam();
-    c_undo_buffer.free_copy_tuple(&regOperPtr->m_copy_tuple_location);
-  }  
-
-  if (regOperPtr->op_struct.in_active_list) {
-    regOperPtr->op_struct.in_active_list= false;
-    if (regOperPtr->nextActiveOp != RNIL) {
-      jam();
-      raoOperPtr.i= regOperPtr->nextActiveOp;
-      c_operation_pool.getPtr(raoOperPtr);
-      raoOperPtr.p->prevActiveOp= regOperPtr->prevActiveOp;
-    } else {
-      jam();
-      tuple_ptr->m_operation_ptr_i = regOperPtr->prevActiveOp;
-    }
-    if (regOperPtr->prevActiveOp != RNIL) {
-      jam();
-      raoOperPtr.i= regOperPtr->prevActiveOp;
-      c_operation_pool.getPtr(raoOperPtr);
-      raoOperPtr.p->nextActiveOp= regOperPtr->nextActiveOp;
-    }
-    regOperPtr->prevActiveOp= RNIL;
-    regOperPtr->nextActiveOp= RNIL;
-  }
-}
-
 /* ---------------------------------------------------------------- */
 /* INITIALIZATION OF ONE CONNECTION RECORD TO PREPARE FOR NEXT OP.  */
 /* ---------------------------------------------------------------- */
@@ -148,6 +112,7 @@ void Dbtup::initOpConnection(Operationre
   regOperPtr->op_struct.m_disk_preallocated= 0;
   regOperPtr->op_struct.m_load_diskpage_on_commit= 0;
   regOperPtr->op_struct.m_wait_log_buffer= 0;
+  regOperPtr->op_struct.in_active_list = false;
   regOperPtr->m_undo_buffer_space= 0;
 }
 
@@ -483,38 +448,17 @@ Dbtup::disk_page_log_buffer_callback(Sig
 }
 
 void
-Dbtup::fix_commit_order(OperationrecPtr opPtr)
+Dbtup::findFirstOp(OperationrecPtr & firstPtr)
 {
   jam();
-  ndbassert(!opPtr.p->is_first_operation());
-  OperationrecPtr firstPtr = opPtr;
+  printf("Detect out-of-order commit(%u) -> ", firstPtr.i);
+  ndbassert(!firstPtr.p->is_first_operation());
   while(firstPtr.p->prevActiveOp != RNIL)
   {
     firstPtr.i = firstPtr.p->prevActiveOp;
     c_operation_pool.getPtr(firstPtr);    
   }
-
-  ndbout_c("fix_commit_order (swapping %d and %d)",
-	   opPtr.i, firstPtr.i);
-  
-  /**
-   * Swap data between first and curr
-   */
-  Uint32 prev= opPtr.p->prevActiveOp;
-  Uint32 next= opPtr.p->nextActiveOp;
-  Uint32 seco= firstPtr.p->nextActiveOp;
-
-  Operationrec tmp = *opPtr.p;
-  * opPtr.p = * firstPtr.p;
-  * firstPtr.p = tmp;
-
-  c_operation_pool.getPtr(seco)->prevActiveOp = opPtr.i;
-  c_operation_pool.getPtr(prev)->nextActiveOp = firstPtr.i;
-  if(next != RNIL)
-  {
-    jam();
-    c_operation_pool.getPtr(next)->prevActiveOp = firstPtr.i;
-  }
+  ndbout_c("%u", firstPtr.i);
 }
 
 /* ----------------------------------------------------------------- */
@@ -527,22 +471,18 @@ void Dbtup::execTUP_COMMITREQ(Signal* si
   TablerecPtr regTabPtr;
   KeyReqStruct req_struct;
   TransState trans_state;
-  Uint32 no_of_fragrec, no_of_tablerec, hash_value;
+  Uint32 no_of_fragrec, no_of_tablerec;
 
   TupCommitReq * const tupCommitReq= (TupCommitReq *)signal->getDataPtr();
 
   regOperPtr.i= tupCommitReq->opPtr;
+  Uint32 hash_value= tupCommitReq->hashValue;
+  Uint32 gci_hi = tupCommitReq->gci_hi;
+  Uint32 gci_lo = tupCommitReq->gci_lo;
+
   jamEntry();
 
   c_operation_pool.getPtr(regOperPtr);
-  if(!regOperPtr.p->is_first_operation())
-  {
-    /**
-     * Out of order commit   XXX check effect on triggers
-     */
-    fix_commit_order(regOperPtr);
-  }
-  ndbassert(regOperPtr.p->is_first_operation());
   
   regFragPtr.i= regOperPtr.p->fragmentPtr;
   trans_state= get_trans_state(regOperPtr.p);
@@ -554,9 +494,6 @@ void Dbtup::execTUP_COMMITREQ(Signal* si
 
   no_of_tablerec= cnoOfTablerec;
   regTabPtr.i= regFragPtr.p->fragTableId;
-  hash_value= tupCommitReq->hashValue;
-  Uint32 gci_hi = tupCommitReq->gci_hi;
-  Uint32 gci_lo = tupCommitReq->gci_lo;
 
   req_struct.signal= signal;
   req_struct.hash_value= hash_value;
@@ -567,8 +504,10 @@ void Dbtup::execTUP_COMMITREQ(Signal* si
 #ifdef VM_TRACE
   if (tupCommitReq->diskpage == RNIL)
   {
-    m_pgman.m_ptr.setNull();
-    req_struct.m_disk_page_ptr.setNull();
+    m_pgman.m_ptr.i = RNIL;
+    m_pgman.m_ptr.p = 0;
+    req_struct.m_disk_page_ptr.i = RNIL;
+    req_struct.m_disk_page_ptr.p = 0;
   }
 #endif
   
@@ -577,14 +516,56 @@ void Dbtup::execTUP_COMMITREQ(Signal* si
   PagePtr page;
   Tuple_header* tuple_ptr= (Tuple_header*)
     get_ptr(&page, &regOperPtr.p->m_tuple_location, regTabPtr.p);
+
+  /**
+   * NOTE: This has to be run before potential time-slice when
+   *       waiting for disk, as otherwise the "other-ops" in a multi-op
+   *       commit might run while we're waiting for disk
+   *
+   */
+  if (!regTabPtr.p->tuxCustomTriggers.isEmpty())
+  {
+    if(get_tuple_state(regOperPtr.p) == TUPLE_PREPARED)
+    {
+      jam();
+
+      OperationrecPtr loopPtr = regOperPtr;
+      if (unlikely(!regOperPtr.p->is_first_operation()))
+      {
+        findFirstOp(loopPtr);
+      }
+
+      /**
+       * Execute all tux triggers at first commit
+       *   since previous tuple is otherwise removed...
+       */
+      jam();
+      goto first;
+      while(loopPtr.i != RNIL)
+      {
+	c_operation_pool.getPtr(loopPtr);
+    first:
+	executeTuxCommitTriggers(signal,
+				 loopPtr.p,
+				 regFragPtr.p,
+				 regTabPtr.p);
+	set_tuple_state(loopPtr.p, TUPLE_TO_BE_COMMITTED);
+	loopPtr.i = loopPtr.p->nextActiveOp;
+      }
+    }
+  }
   
   bool get_page = false;
   if(regOperPtr.p->op_struct.m_load_diskpage_on_commit)
   {
     jam();
     Page_cache_client::Request req;
-    ndbassert(regOperPtr.p->is_first_operation() && 
-	      regOperPtr.p->is_last_operation());
+
+    /**
+     * Only last op on tuple needs "real" commit,
+     *   hence only this one should habe m_load_diskpage_on_commit
+     */
+    ndbassert(tuple_ptr->m_operation_ptr_i == regOperPtr.i);
 
     /**
      * Check for page
@@ -669,8 +650,11 @@ void Dbtup::execTUP_COMMITREQ(Signal* si
   if(regOperPtr.p->op_struct.m_wait_log_buffer)
   {
     jam();
-    ndbassert(regOperPtr.p->is_first_operation() && 
-	      regOperPtr.p->is_last_operation());
+    /**
+     * Only last op on tuple needs "real" commit,
+     *   hence only this one should have m_wait_log_buffer
+     */
+    ndbassert(tuple_ptr->m_operation_ptr_i == regOperPtr.i);
     
     Callback cb;
     cb.m_callbackData= regOperPtr.i;
@@ -694,42 +678,24 @@ void Dbtup::execTUP_COMMITREQ(Signal* si
     }
   }
   
-  if(!tuple_ptr)
-  {
-    jam();
-    tuple_ptr = (Tuple_header*)
-      get_ptr(&page, &regOperPtr.p->m_tuple_location,regTabPtr.p);
-  }
+  assert(tuple_ptr);
 skip_disk:
   req_struct.m_tuple_ptr = tuple_ptr;
   
-  if(get_tuple_state(regOperPtr.p) == TUPLE_PREPARED)
-  {
-    jam();
-    /**
-     * Execute all tux triggers at first commit
-     *   since previous tuple is otherwise removed...
-     *   btw...is this a "good" solution??
-     *   
-     *   why can't we instead remove "own version" (when approriate ofcourse)
-     */
-    if (!regTabPtr.p->tuxCustomTriggers.isEmpty()) {
-      jam();
-      OperationrecPtr loopPtr= regOperPtr;
-      while(loopPtr.i != RNIL)
-      {
-	c_operation_pool.getPtr(loopPtr);
-	executeTuxCommitTriggers(signal,
-				 loopPtr.p,
-				 regFragPtr.p,
-				 regTabPtr.p);
-	set_tuple_state(loopPtr.p, TUPLE_TO_BE_COMMITTED);
-	loopPtr.i = loopPtr.p->nextActiveOp;
-      }
-    }
-  }
-  
-  if(regOperPtr.p->is_last_operation())
+  Uint32 nextOp = regOperPtr.p->nextActiveOp;
+  Uint32 prevOp = regOperPtr.p->prevActiveOp;
+
+  /**
+   * The trigger code (which is shared between detached/imediate)
+   *   check op-list to check were to read before values from
+   *   detached triggers should always read from *pre* op
+   *   i.e not intermediate update
+   *
+   * Setting the op-list has this effect
+   */
+  regOperPtr.p->nextActiveOp = RNIL;
+  regOperPtr.p->prevActiveOp = RNIL;
+  if(tuple_ptr->m_operation_ptr_i == regOperPtr.i)
   {
     jam();
     /**
@@ -737,30 +703,41 @@ skip_disk:
      */
     Uint32 disk = regOperPtr.p->m_commit_disk_callback_page;
     set_change_mask_info(&req_struct, regOperPtr.p);
+
     checkDetachedTriggers(&req_struct, regOperPtr.p, regTabPtr.p, 
                           disk != RNIL);
     
+    tuple_ptr->m_operation_ptr_i = RNIL;
     if(regOperPtr.p->op_struct.op_type != ZDELETE)
     {
       jam();
       commit_operation(signal, gci_hi, tuple_ptr, page,
 		       regOperPtr.p, regFragPtr.p, regTabPtr.p); 
-      removeActiveOpList(regOperPtr.p, tuple_ptr);
     }
     else
     {
       jam();
-      removeActiveOpList(regOperPtr.p, tuple_ptr);
       if (get_page)
 	ndbassert(tuple_ptr->m_header_bits & Tuple_header::DISK_PART);
       dealloc_tuple(signal, gci_hi, page.p, tuple_ptr,
 		    regOperPtr.p, regFragPtr.p, regTabPtr.p); 
     }
-  } 
-  else
+  }
+
+  if (nextOp != RNIL)
+  {
+    c_operation_pool.getPtr(nextOp)->prevActiveOp = prevOp;
+  }
+
+  if (prevOp != RNIL)
+  {
+    c_operation_pool.getPtr(prevOp)->nextActiveOp = nextOp;
+  }
+
+  if(!regOperPtr.p->m_copy_tuple_location.isNull())
   {
     jam();
-    removeActiveOpList(regOperPtr.p, tuple_ptr);   
+    c_undo_buffer.free_copy_tuple(&regOperPtr.p->m_copy_tuple_location);
   }
   
   initOpConnection(regOperPtr.p);
diff -Nrup a/storage/ndb/src/kernel/blocks/dbtup/DbtupExecQuery.cpp b/storage/ndb/src/kernel/blocks/dbtup/DbtupExecQuery.cpp
--- a/storage/ndb/src/kernel/blocks/dbtup/DbtupExecQuery.cpp	2008-02-01 07:30:18 +01:00
+++ b/storage/ndb/src/kernel/blocks/dbtup/DbtupExecQuery.cpp	2008-02-03 10:30:08 +01:00
@@ -254,7 +254,7 @@ Dbtup::calculateChecksum(Tuple_header* t
   // includes tupVersion
   //printf("%p - ", tuple_ptr);
   
-  for (i= 0; i < rec_size-2; i++) {
+  for (i= 0; i < rec_size-Tuple_header::HeaderSize; i++) {
     checksum ^= tuple_header[i];
     //printf("%.8x ", tuple_header[i]);
   }
diff -Nrup a/storage/ndb/test/ndbapi/testNodeRestart.cpp b/storage/ndb/test/ndbapi/testNodeRestart.cpp
--- a/storage/ndb/test/ndbapi/testNodeRestart.cpp	2007-12-18 14:24:36 +01:00
+++ b/storage/ndb/test/ndbapi/testNodeRestart.cpp	2008-02-03 10:30:08 +01:00
@@ -23,6 +23,7 @@
 #include <signaldata/DumpStateOrd.hpp>
 #include <Bitmask.hpp>
 #include <RefConvert.hpp>
+#include <NdbEnv.h>
 
 int runLoadTable(NDBT_Context* ctx, NDBT_Step* step){
 
@@ -121,15 +122,57 @@ int runPkReadUntilStopped(NDBT_Context* 
 int runPkUpdateUntilStopped(NDBT_Context* ctx, NDBT_Step* step){
   int result = NDBT_OK;
   int records = ctx->getNumRecords();
+  int multiop = ctx->getProperty("MULTI_OP", 1);
+  Ndb* pNdb = GETNDB(step);
   int i = 0;
-  HugoTransactions hugoTrans(*ctx->getTab());
-  while (ctx->isTestStopped() == false) {
+
+  HugoOperations hugoOps(*ctx->getTab());
+  while (ctx->isTestStopped() == false)
+  {
     g_info << i << ": ";
-    int rows = (rand()%records)+1;
-    int batch = (rand()%rows)+1;
-    if (hugoTrans.pkUpdateRecords(GETNDB(step), rows, batch) != 0){
-      return NDBT_FAILED;
+    int batch = (rand()%records)+1;
+    int row = rand() % records;
+
+    if (batch > 25)
+      batch = 25;
+
+    if(row + batch > records)
+      batch = records - row;
+
+    if(hugoOps.startTransaction(pNdb) != 0)
+      goto err;
+
+    if(hugoOps.pkUpdateRecord(pNdb, row, batch, rand()) != 0)
+      goto err;
+
+    for (int j = 1; j<multiop; j++)
+    {
+      if(hugoOps.execute_NoCommit(pNdb) != 0)
+	goto err;
+
+      if(hugoOps.pkUpdateRecord(pNdb, row, batch, rand()) != 0)
+        goto err;
     }
+
+    if(hugoOps.execute_Commit(pNdb) != 0)
+      goto err;
+
+    hugoOps.closeTransaction(pNdb);
+
+    continue;
+
+err:
+    NdbConnection* pCon = hugoOps.getTransaction();
+    if(pCon == 0)
+      continue;
+    NdbError error = pCon->getNdbError();
+    hugoOps.closeTransaction(pNdb);
+    if (error.status == NdbError::TemporaryError){
+      NdbSleep_MilliSleep(50);
+      continue;
+    }
+    return NDBT_FAILED;
+
     i++;
   }
   return result;
@@ -258,7 +301,7 @@ int runRestarter(NDBT_Context* ctx, NDBT
     return NDBT_OK;
   }
 
-  if(restarter.waitClusterStarted(60) != 0){
+  if(restarter.waitClusterStarted() != 0){
     g_err << "Cluster failed to start" << endl;
     return NDBT_FAILED;
   }
@@ -269,13 +312,27 @@ int runRestarter(NDBT_Context* ctx, NDBT
     int id = lastId % restarter.getNumDbNodes();
     int nodeId = restarter.getDbNodeId(id);
     ndbout << "Restart node " << nodeId << endl; 
-    if(restarter.restartOneDbNode(nodeId, false, false, true) != 0){
+    if(restarter.restartOneDbNode(nodeId, false, true, true) != 0){
       g_err << "Failed to restartNextDbNode" << endl;
       result = NDBT_FAILED;
       break;
     }    
 
-    if(restarter.waitClusterStarted(60) != 0){
+    if (restarter.waitNodesNoStart(&nodeId, 1))
+    {
+      g_err << "Failed to waitNodesNoStart" << endl;
+      result = NDBT_FAILED;
+      break;
+    }
+
+    if (restarter.startNodes(&nodeId, 1))
+    {
+      g_err << "Failed to start node" << endl;
+      result = NDBT_FAILED;
+      break;
+    }
+
+    if(restarter.waitClusterStarted() != 0){
       g_err << "Cluster failed to start" << endl;
       result = NDBT_FAILED;
       break;
@@ -2268,6 +2325,178 @@ runBug32922(NDBT_Context* ctx, NDBT_Step
   return NDBT_OK;
 }
 
+int
+runNFMultiOp_commit(NDBT_Context* ctx, NDBT_Step* step)
+{
+  int result = NDBT_OK;
+  int loops = ctx->getNumLoops();
+  NdbRestarter restarter;
+  int i = 0;
+  int lastId = 0;
+  HugoOperations hugoOps(*ctx->getTab());
+  int records = ctx->getNumRecords();
+  Ndb* pNdb = GETNDB(step);
+
+  if (restarter.getNumDbNodes() < 2)
+  {
+    ctx->stopTest();
+    return NDBT_OK;
+  }
+
+  if(restarter.waitClusterStarted() != 0){
+    g_err << "Cluster failed to start" << endl;
+    return NDBT_FAILED;
+  }
+
+  char buf[100];
+  const char * off = NdbEnv_GetEnv("NDB_ERR_OFFSET", buf, sizeof(buf));
+  int offset = off ? atoi(off) : 0;
+
+  while(i<loops && result != NDBT_FAILED && !ctx->isTestStopped())
+  {
+    int id = lastId % restarter.getNumDbNodes();
+    int nodeId = restarter.getDbNodeId(id);
+    int err = 5048 + ((i+offset) % 2);
+
+    int val2[] = { DumpStateOrd::CmvmiSetRestartOnErrorInsert, 1 };
+
+    if(hugoOps.startTransaction(pNdb) != 0)
+      goto err;
+
+    nodeId = hugoOps.getTransaction()->getConnectedNodeId();
+    ndbout << "Restart node " << nodeId << " " << err <<endl;
+
+    if (restarter.dumpStateOneNode(nodeId, val2, 2))
+      return NDBT_FAILED;
+
+    if(restarter.insertErrorInNode(nodeId, err) != 0){
+      g_err << "Failed to restartNextDbNode" << endl;
+      result = NDBT_FAILED;
+      break;
+    }
+
+    if (restarter.insertErrorInNode(nodeId, 8057) != 0)
+    {
+      g_err << "Failed to insert error 8057" << endl;
+      result = NDBT_FAILED;
+      break;
+    }
+
+    int rows = 1;
+    int batch = 1;
+    int row = (records - rows) ? rand() % (records - rows) : 0;
+
+    if(hugoOps.pkUpdateRecord(pNdb, row, batch, rand()) != 0)
+      goto err;
+
+    for (int l = 1; l<5; l++)
+    {
+      if (hugoOps.execute_NoCommit(pNdb) != 0)
+        goto err;
+
+      if(hugoOps.pkUpdateRecord(pNdb, row, batch, rand()) != 0)
+        goto err;
+    }
+
+    hugoOps.execute_Commit(pNdb);
+    hugoOps.closeTransaction(pNdb);
+
+    if (restarter.waitNodesNoStart(&nodeId, 1))
+    {
+      g_err << "Failed to waitNodesNoStart" << endl;
+      result = NDBT_FAILED;
+      break;
+    }
+
+    if (restarter.startNodes(&nodeId, 1))
+    {
+      g_err << "Failed to startNodes" << endl;
+      result = NDBT_FAILED;
+      break;
+    }
+
+    if(restarter.waitClusterStarted() != 0){
+      g_err << "Cluster failed to start" << endl;
+      result = NDBT_FAILED;
+      break;
+    }
+
+    lastId++;
+    i++;
+  }
+
+  ctx->stopTest();
+
+  return result;
+err:
+  return NDBT_FAILED;
+}
+
+
+int
+runNF_commit(NDBT_Context* ctx, NDBT_Step* step)
+{
+  int result = NDBT_OK;
+  int loops = ctx->getNumLoops();
+  NdbRestarter restarter;
+  if (restarter.getNumDbNodes() < 2)
+  {
+    ctx->stopTest();
+    return NDBT_OK;
+  }
+
+  if(restarter.waitClusterStarted() != 0){
+    g_err << "Cluster failed to start" << endl;
+    return NDBT_FAILED;
+  }
+
+  int i = 0;
+  while(i<loops && result != NDBT_FAILED && !ctx->isTestStopped())
+  {
+    int nodeId = restarter.getDbNodeId(rand() % restarter.getNumDbNodes());
+    int err = 5048;
+
+    ndbout << "Restart node " << nodeId << " " << err <<endl;
+
+    int val2[] = { DumpStateOrd::CmvmiSetRestartOnErrorInsert, 1 };
+    if (restarter.dumpStateOneNode(nodeId, val2, 2))
+      return NDBT_FAILED;
+
+    if(restarter.insertErrorInNode(nodeId, err) != 0){
+      g_err << "Failed to restartNextDbNode" << endl;
+      result = NDBT_FAILED;
+      break;
+    }
+
+    if (restarter.waitNodesNoStart(&nodeId, 1))
+    {
+      g_err << "Failed to waitNodesNoStart" << endl;
+      result = NDBT_FAILED;
+      break;
+    }
+
+    if (restarter.startNodes(&nodeId, 1))
+    {
+      g_err << "Failed to startNodes" << endl;
+      result = NDBT_FAILED;
+      break;
+    }
+
+    if(restarter.waitClusterStarted() != 0){
+      g_err << "Cluster failed to start" << endl;
+      result = NDBT_FAILED;
+      break;
+    }
+
+    i++;
+  }
+
+  ctx->stopTest();
+
+  return result;
+}
+
+
 NDBT_TESTSUITE(testNodeRestart);
 TESTCASE("NoLoad", 
 	 "Test that one node at a time can be stopped and then restarted "\
@@ -2675,6 +2904,21 @@ TESTCASE("pnr_lcp", "Parallel node resta
 }
 TESTCASE("Bug32922", ""){
   INITIALIZER(runBug32922);
+}
+TESTCASE("multiop", ""){
+  INITIALIZER(runCheckAllNodesStarted);
+  INITIALIZER(runLoadTable);
+  STEP(runNFMultiOp_commit);
+  FINALIZER(runClearTable);
+}
+TESTCASE("mixedmultiop", ""){
+  TC_PROPERTY("MULTI_OP", 5);
+  INITIALIZER(runCheckAllNodesStarted);
+  INITIALIZER(runLoadTable);
+  STEP(runNF_commit);
+  STEP(runPkUpdateUntilStopped);
+  STEP(runPkUpdateUntilStopped);
+  FINALIZER(runClearTable);
 }
 NDBT_TESTSUITE_END(testNodeRestart);
 
diff -Nrup a/storage/ndb/test/run-test/daily-basic-tests.txt b/storage/ndb/test/run-test/daily-basic-tests.txt
--- a/storage/ndb/test/run-test/daily-basic-tests.txt	2008-02-01 07:30:18 +01:00
+++ b/storage/ndb/test/run-test/daily-basic-tests.txt	2008-02-03 10:30:08 +01:00
@@ -1106,3 +1106,11 @@ max-time: 300
 cmd: test_event
 args: -n Bug33793 T1
 
+max-time: 3600
+cmd: testNodeRestart
+args: --nologging -n multiop T1 I2 I3 D2
+
+max-time: 3600
+cmd: testNodeRestart
+args: -n mixedmultiop -l 10 T1 I2 I3 D2
+
Thread
bk commit into 5.1 tree (jonas:1.2862)jonas3 Feb
  • Re: bk commit into 5.1 tree (jonas:1.2862)Kristian Nielsen4 Feb
    • Re: bk commit into 5.1 tree (jonas:1.2862)Jonas Oreland6 Feb