List:Commits« Previous MessageNext Message »
From:tomas Date:November 2 2007 4:23pm
Subject:bk commit into 5.1 tree (tomas:1.2700)
View as plain text  
Below is the list of changes that have just been committed into a local
5.1 repository of tomas. When tomas 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, 2007-11-02 17:23:17+01:00, tomas@stripped +15 -0
  WL#3686 - kernel part
  - commit ack marker

  mysql-test/suite/ndb/r/ndb_bulk_delete.result@stripped, 2007-11-02 17:23:12+01:00, tomas@stripped +3 -3
    WL#3686 - kernel part
    - commit ack marker

  mysql-test/suite/ndb/r/ndb_update_no_read.result@stripped, 2007-11-02 17:23:12+01:00, tomas@stripped +9 -9
    WL#3686 - kernel part
    - commit ack marker

  mysql-test/suite/ndb/t/ndb_bulk_delete.test@stripped, 2007-11-02 17:23:12+01:00, tomas@stripped +2 -2
    WL#3686 - kernel part
    - commit ack marker

  mysql-test/suite/ndb/t/ndb_update_no_read.test@stripped, 2007-11-02 17:23:12+01:00, tomas@stripped +6 -6
    WL#3686 - kernel part
    - commit ack marker

  sql/ha_ndbcluster.cc@stripped, 2007-11-02 17:23:12+01:00, tomas@stripped +0 -3
    WL#3686 - kernel part
    - commit ack marker

  storage/ndb/include/kernel/signaldata/DiGetNodes.hpp@stripped, 2007-11-02 17:23:12+01:00, tomas@stripped +1 -1
    WL#3686 - kernel part
    - commit ack marker

  storage/ndb/src/kernel/blocks/ERROR_codes.txt@stripped, 2007-11-02 17:23:12+01:00, tomas@stripped +3 -1
    WL#3686 - kernel part
    - commit ack marker

  storage/ndb/src/kernel/blocks/dbdih/DbdihMain.cpp@stripped, 2007-11-02 17:23:12+01:00, tomas@stripped +2 -1
    WL#3686 - kernel part
    - commit ack marker

  storage/ndb/src/kernel/blocks/dblqh/Dblqh.hpp@stripped, 2007-11-02 17:23:13+01:00, tomas@stripped +3 -1
    WL#3686 - kernel part
    - commit ack marker

  storage/ndb/src/kernel/blocks/dblqh/DblqhMain.cpp@stripped, 2007-11-02 17:23:13+01:00, tomas@stripped +60 -52
    WL#3686 - kernel part
    - commit ack marker

  storage/ndb/src/kernel/blocks/dbtc/Dbtc.hpp@stripped, 2007-11-02 17:23:13+01:00, tomas@stripped +27 -22
    WL#3686 - kernel part
    - commit ack marker

  storage/ndb/src/kernel/blocks/dbtc/DbtcInit.cpp@stripped, 2007-11-02 17:23:13+01:00, tomas@stripped +2 -2
    WL#3686 - kernel part
    - commit ack marker

  storage/ndb/src/kernel/blocks/dbtc/DbtcMain.cpp@stripped, 2007-11-02 17:23:13+01:00, tomas@stripped +121 -115
    WL#3686 - kernel part
    - commit ack marker

  storage/ndb/test/ndbapi/testBasic.cpp@stripped, 2007-11-02 17:23:13+01:00, tomas@stripped +1 -1
    WL#3686 - kernel part
    - commit ack marker

  storage/ndb/test/ndbapi/testNodeRestart.cpp@stripped, 2007-11-02 17:23:13+01:00, tomas@stripped +205 -0
    WL#3686 - kernel part
    - commit ack marker

diff -Nrup a/mysql-test/suite/ndb/r/ndb_bulk_delete.result b/mysql-test/suite/ndb/r/ndb_bulk_delete.result
--- a/mysql-test/suite/ndb/r/ndb_bulk_delete.result	2007-11-01 08:05:42 +01:00
+++ b/mysql-test/suite/ndb/r/ndb_bulk_delete.result	2007-11-02 17:23:12 +01:00
@@ -11,13 +11,13 @@ insert into t1 select a+64 from t1;
 insert into t1 select a+128 from t1;
 
 # test: simple delete of multiple pk's
-# expected result 3 roundtrips
+# expected result 2 roundtrips
 # 1 - info call
-# 1 - read the rows
+# 0 - read the rows (with read before delete, this is 1)
 # 0 - delete the rows (without bulk update this is 5 + 1 for execute no commit)
 # 1 - delete the row + commit the transaction
 
 delete from t1 where a in (1,7, 90, 100, 130);
 @ndb_execute_count:=VARIABLE_VALUE-@ndb_init_execute_count
-3
+2
 drop table t1;
diff -Nrup a/mysql-test/suite/ndb/r/ndb_update_no_read.result b/mysql-test/suite/ndb/r/ndb_update_no_read.result
--- a/mysql-test/suite/ndb/r/ndb_update_no_read.result	2007-11-01 10:27:00 +01:00
+++ b/mysql-test/suite/ndb/r/ndb_update_no_read.result	2007-11-02 17:23:12 +01:00
@@ -24,16 +24,16 @@ a	b	c
 1	20	111
 affected rows: 1
 
-# expected result 3 roundtrips
+# expected result 2 roundtrips
 # 1 - info call
-# 1 - read the row
+# 0 - read the rows (1 with read before)
 # 0 - delete the row (deferred to commit)
 # 1 - delete + commit the transaction
 
 delete from t1 where a = 1;
 affected rows: 1
 @ndb_execute_count:=VARIABLE_VALUE-@ndb_init_execute_count
-3
+2
 affected rows: 1
 select * from t1 where a = 1 order by a;
 a	b	c
@@ -55,16 +55,16 @@ select * from t1 where b = 2 order by a;
 a	b	c
 affected rows: 0
 
-# expected result 3 roundtrips
+# expected result 2 roundtrips
 # 1 - info call
-# 1 - read the row
+# 0 - read the rows (1 with read before)
 # 0 - delete the row (deferred to commit)
 # 1 - delete and commit the transaction
 
 delete from t1 where b = 19;
 affected rows: 1
 @ndb_execute_count:=VARIABLE_VALUE-@ndb_init_execute_count
-3
+2
 affected rows: 1
 select * from t1 where b = 19 order by a;
 a	b	c
@@ -219,16 +219,16 @@ a	b	c
 12	19	11
 affected rows: 1
 
-# expected result 3 roundtrips
+# expected result 2 roundtrips
 # 1 - info call
-# 1 - read the rows
+# 0 - read the rows (1 with read before)
 # 0 - delete the rows (no row found)
 # 1 - commit the transaction
 
 delete from t1 where b = 6 and c = 12;
 affected rows: 0
 @ndb_execute_count:=VARIABLE_VALUE-@ndb_init_execute_count
-3
+2
 affected rows: 1
 select * from t1 where b = 6 order by a;
 a	b	c
diff -Nrup a/mysql-test/suite/ndb/t/ndb_bulk_delete.test b/mysql-test/suite/ndb/t/ndb_bulk_delete.test
--- a/mysql-test/suite/ndb/t/ndb_bulk_delete.test	2007-11-01 08:05:42 +01:00
+++ b/mysql-test/suite/ndb/t/ndb_bulk_delete.test	2007-11-02 17:23:12 +01:00
@@ -22,9 +22,9 @@ insert into t1 select a+128 from t1;
 
 --echo
 --echo # test: simple delete of multiple pk's
---echo # expected result 3 roundtrips
+--echo # expected result 2 roundtrips
 --echo # 1 - info call
---echo # 1 - read the rows
+--echo # 0 - read the rows (with read before delete, this is 1)
 --echo # 0 - delete the rows (without bulk update this is 5 + 1 for execute no commit)
 --echo # 1 - delete the row + commit the transaction
 --echo
diff -Nrup a/mysql-test/suite/ndb/t/ndb_update_no_read.test b/mysql-test/suite/ndb/t/ndb_update_no_read.test
--- a/mysql-test/suite/ndb/t/ndb_update_no_read.test	2007-11-01 10:27:00 +01:00
+++ b/mysql-test/suite/ndb/t/ndb_update_no_read.test	2007-11-02 17:23:12 +01:00
@@ -39,9 +39,9 @@ update t1 set c = 111, b = 20 where a = 
 select * from t1 where a = 1 order by a;
 
 --echo
---echo # expected result 3 roundtrips
+--echo # expected result 2 roundtrips
 --echo # 1 - info call
---echo # 1 - read the row
+--echo # 0 - read the rows (1 with read before)
 --echo # 0 - delete the row (deferred to commit)
 --echo # 1 - delete + commit the transaction
 --echo
@@ -65,9 +65,9 @@ update t1 set c = 12, b = 19 where b = 2
 select * from t1 where b = 2 order by a;
 
 --echo
---echo # expected result 3 roundtrips
+--echo # expected result 2 roundtrips
 --echo # 1 - info call
---echo # 1 - read the row
+--echo # 0 - read the rows (1 with read before)
 --echo # 0 - delete the row (deferred to commit)
 --echo # 1 - delete and commit the transaction
 --echo
@@ -178,9 +178,9 @@ update t1 set c = 12, b = 29 where a = 5
 select * from t1 where b = 19 order by a;
 
 --echo
---echo # expected result 3 roundtrips
+--echo # expected result 2 roundtrips
 --echo # 1 - info call
---echo # 1 - read the rows
+--echo # 0 - read the rows (1 with read before)
 --echo # 0 - delete the rows (no row found)
 --echo # 1 - commit the transaction
 --echo
diff -Nrup a/sql/ha_ndbcluster.cc b/sql/ha_ndbcluster.cc
--- a/sql/ha_ndbcluster.cc	2007-11-01 15:11:25 +01:00
+++ b/sql/ha_ndbcluster.cc	2007-11-02 17:23:12 +01:00
@@ -5322,9 +5322,6 @@ bool ha_ndbcluster::read_before_write_re
       }
     }
   }
-  /* disable read_before_write_removal until commit ack marker patch is in */
-  DBUG_RETURN(FALSE);
-
   DBUG_PRINT("info", ("read_before_write_removal_possible TRUE"));
   m_read_before_write_removal_possible= TRUE;
   DBUG_RETURN(TRUE);
diff -Nrup a/storage/ndb/include/kernel/signaldata/DiGetNodes.hpp b/storage/ndb/include/kernel/signaldata/DiGetNodes.hpp
--- a/storage/ndb/include/kernel/signaldata/DiGetNodes.hpp	2006-12-23 20:20:04 +01:00
+++ b/storage/ndb/include/kernel/signaldata/DiGetNodes.hpp	2007-11-02 17:23:12 +01:00
@@ -54,8 +54,8 @@ class DiGetNodesReq {
 public:
   STATIC_CONST( SignalLength = 3 );
 private:
-  Uint32 notUsed;
   Uint32 tableId;
   Uint32 hashValue;
+  Uint32 distr_key_indicator;
 };
 #endif
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	2007-10-23 15:58:26 +02:00
+++ b/storage/ndb/src/kernel/blocks/ERROR_codes.txt	2007-11-02 17:23:12 +01:00
@@ -6,7 +6,7 @@ Next DBTUP 4029
 Next DBLQH 5048
 Next DBDICT 6008
 Next DBDIH 7193
-Next DBTC 8054
+Next DBTC 8055
 Next CMVMI 9000
 Next BACKUP 10038
 Next DBUTIL 11002
@@ -271,6 +271,8 @@ Delay execution of ABORTCONF signal 2 se
 8050: Send ZABORT_TIMEOUT_BREAK delayed
 
 8053: Crash in timeOutFoundLab, state CS_WAIT_COMMIT_CONF
+
+8054: Throw away TC_KEYCONF to api and die 5 seconds later.  To test commit ack markers
 
 ERROR CODES FOR TESTING TIME-OUT HANDLING IN DBTC
 -------------------------------------------------
diff -Nrup a/storage/ndb/src/kernel/blocks/dbdih/DbdihMain.cpp b/storage/ndb/src/kernel/blocks/dbdih/DbdihMain.cpp
--- a/storage/ndb/src/kernel/blocks/dbdih/DbdihMain.cpp	2007-10-23 11:38:17 +02:00
+++ b/storage/ndb/src/kernel/blocks/dbdih/DbdihMain.cpp	2007-11-02 17:23:12 +01:00
@@ -7673,7 +7673,7 @@ void Dbdih::execDIGETNODESREQ(Signal* si
     jam();
     ndbassert(tabPtr.p->method == TabRecord::USER_DEFINED);
     fragId= hashValue;
-    if (fragId >= tabPtr.p->totalfragments)
+    if (fragId >= tabPtr.p->totalfragments || !req->distr_key_indicator)
     {
       jam();
       conf->zero= 1; //Indicate error;
@@ -7693,6 +7693,7 @@ void Dbdih::execDIGETNODESREQ(Signal* si
 Uint32 Dbdih::extractNodeInfo(const Fragmentstore * fragPtr, Uint32 nodes[]) 
 {
   Uint32 nodeCount = 0;
+  nodes[0] = nodes[1] = nodes[2] = nodes[3] = 0;
   for (Uint32 i = 0; i < fragPtr->fragReplicas; i++) {
     jam();
     NodeRecordPtr nodePtr;
diff -Nrup a/storage/ndb/src/kernel/blocks/dblqh/Dblqh.hpp b/storage/ndb/src/kernel/blocks/dblqh/Dblqh.hpp
--- a/storage/ndb/src/kernel/blocks/dblqh/Dblqh.hpp	2007-10-23 11:29:26 +02:00
+++ b/storage/ndb/src/kernel/blocks/dblqh/Dblqh.hpp	2007-11-02 17:23:13 +01:00
@@ -2540,7 +2540,8 @@ private:
   void sendAddAttrReq(Signal* signal);
   void checkDropTab(Signal*);
   Uint32 checkDropTabState(Tablerec::TableStatus, Uint32) const;
-  
+
+  void remove_commit_marker(TcConnectionrec * const regTcPtr);
   // Initialisation
   void initData();
   void initRecords();
@@ -2919,6 +2920,7 @@ public:
     Uint32 tcNodeId;  
     union { Uint32 nextPool; Uint32 nextHash; };
     Uint32 prevHash;
+    Uint32 reference_count;
 
     inline bool equal(const CommitAckMarker & p) const {
       return ((p.transid1 == transid1) && (p.transid2 == transid2));
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	2007-10-23 15:58:26 +02:00
+++ b/storage/ndb/src/kernel/blocks/dblqh/DblqhMain.cpp	2007-11-02 17:23:13 +01:00
@@ -3528,30 +3528,44 @@ void Dblqh::execLQHKEYREQ(Signal* signal
   regTcPtr->applOprec = sig4;
 
   regTcPtr->commitAckMarker = RNIL;
-  if(LqhKeyReq::getMarkerFlag(Treqinfo)){
-    jam();
-    
+  if (LqhKeyReq::getMarkerFlag(Treqinfo))
+  {
+    struct CommitAckMarker check;
     CommitAckMarkerPtr markerPtr;
-    m_commitAckMarkerHash.seize(markerPtr);
-    if(markerPtr.i == RNIL){
-      noFreeRecordLab(signal, lqhKeyReq, ZNO_FREE_MARKER_RECORDS_ERROR);
-      return;
+    jam();
+    check.transid1 = regTcPtr->transid[0];
+    check.transid2 = regTcPtr->transid[1];
+
+    if (m_commitAckMarkerHash.find(markerPtr, check))
+    {
+      /*
+        A commit ack marker was already placed here for this transaction.
+        We increase the reference count to ensure we don't remove the
+        commit ack marker prematurely.
+      */
+      markerPtr.p->reference_count++;
+    }
+    else
+    {
+      m_commitAckMarkerHash.seize(markerPtr);
+      if (markerPtr.i == RNIL)
+      {
+        noFreeRecordLab(signal, lqhKeyReq, ZNO_FREE_MARKER_RECORDS_ERROR);
+        return;
+      }
+      markerPtr.p->transid1 = sig1;
+      markerPtr.p->transid2 = sig2;
+      markerPtr.p->apiRef   = sig3;
+      markerPtr.p->apiOprec = sig4;
+      const NodeId tcNodeId  = refToNode(sig5);
+      markerPtr.p->tcNodeId = tcNodeId;
+      markerPtr.p->reference_count = 1;
+      m_commitAckMarkerHash.add(markerPtr);
     }
-    markerPtr.p->transid1 = sig1;
-    markerPtr.p->transid2 = sig2;
-    markerPtr.p->apiRef   = sig3;
-    markerPtr.p->apiOprec = sig4;
-    const NodeId tcNodeId  = refToNode(sig5);
-    markerPtr.p->tcNodeId = tcNodeId;
     
-    CommitAckMarkerPtr tmp;
-#if defined VM_TRACE || defined ERROR_INSERT
 #ifdef MARKER_TRACE
     ndbout_c("Add marker[%.8x %.8x]", markerPtr.p->transid1, markerPtr.p->transid2);
 #endif
-    ndbrequire(!m_commitAckMarkerHash.find(tmp, * markerPtr.p));
-#endif
-    m_commitAckMarkerHash.add(markerPtr);
     regTcPtr->commitAckMarker = markerPtr.i;
   } 
   
@@ -6826,6 +6840,28 @@ void Dblqh::releaseTcrecLog(Signal* sign
 /*                                                                           */
 /*THIS PART IS USED AT ERRORS THAT CAUSE ABORT OF TRANSACTION.               */
 /* ------------------------------------------------------------------------- */
+void
+Dblqh::remove_commit_marker(TcConnectionrec * const regTcPtr)
+{
+  CommitAckMarker *tmp;
+  Uint32 commitAckMarker = regTcPtr->commitAckMarker;
+  regTcPtr->commitAckMarker = RNIL;
+  if (commitAckMarker == RNIL)
+    return;
+  jam();
+  tmp = m_commitAckMarkerHash.getPtr(commitAckMarker);
+#ifdef MARKER_TRACE
+  ndbout_c("Ab2 marker[%.8x %.8x]", tmp->transid1, tmp->transid2);
+#endif
+  ndbrequire(tmp->reference_count > 0);
+  tmp->reference_count--;
+  if (tmp->reference_count == 0)
+  {
+    jam();
+    m_commitAckMarkerHash.release(commitAckMarker);
+  }
+}
+
 /* ***************************************************>> */
 /*  ABORT: Abort transaction in connection. Sender TC.   */
 /*  This is the normal protocol (See COMMIT)             */
@@ -6902,21 +6938,7 @@ void Dblqh::execABORT(Signal* signal) 
   }//if
   regTcPtr->abortState = TcConnectionrec::ABORT_FROM_TC;
 
-  const Uint32 commitAckMarker = regTcPtr->commitAckMarker;
-  if(commitAckMarker != RNIL)
-  {
-    jam();
-#ifdef MARKER_TRACE
-    {
-      CommitAckMarkerPtr tmp;
-      m_commitAckMarkerHash.getPtr(tmp, commitAckMarker);
-      ndbout_c("Ab2 marker[%.8x %.8x]", tmp.p->transid1, tmp.p->transid2);
-    }
-#endif
-    m_commitAckMarkerHash.release(commitAckMarker);
-    regTcPtr->commitAckMarker = RNIL;
-  }
-
+  remove_commit_marker(regTcPtr);
   TRACE_OP(regTcPtr, "ABORT");
 
   abortStateHandlerLab(signal);
@@ -7248,24 +7270,9 @@ void Dblqh::abortErrorLab(Signal* signal
 void Dblqh::abortCommonLab(Signal* signal) 
 {
   TcConnectionrec * const regTcPtr = tcConnectptr.p;
-  const Uint32 commitAckMarker = regTcPtr->commitAckMarker;
   const Uint32 activeCreat = regTcPtr->activeCreat;
-  if (commitAckMarker != RNIL)
-  {
-    /**
-     * There is no NR ongoing and we have a marker
-     */
-    jam();
-#ifdef MARKER_TRACE
-    {
-      CommitAckMarkerPtr tmp;
-      m_commitAckMarkerHash.getPtr(tmp, commitAckMarker);
-      ndbout_c("Abo marker[%.8x %.8x]", tmp.p->transid1, tmp.p->transid2);
-    }
-#endif
-    m_commitAckMarkerHash.release(commitAckMarker);
-    regTcPtr->commitAckMarker = RNIL;
-  }
+
+  remove_commit_marker(regTcPtr);
 
   if (unlikely(activeCreat == Fragrecord::AC_NR_COPY))
   {
@@ -19189,13 +19196,14 @@ Dblqh::execDUMP_STATE_ORD(Signal* signal
     for(m_commitAckMarkerHash.first(iter); iter.curr.i != RNIL;
 	m_commitAckMarkerHash.next(iter)){
       infoEvent("CommitAckMarker: i = %d (0x%x, 0x%x)"
-		" ApiRef: 0x%x apiOprec: 0x%x TcNodeId: %d",
+		" ApiRef: 0x%x apiOprec: 0x%x TcNodeId: %d, ref_count: %d",
 		iter.curr.i,
 		iter.curr.p->transid1,
 		iter.curr.p->transid2,
 		iter.curr.p->apiRef,
 		iter.curr.p->apiOprec,
-		iter.curr.p->tcNodeId);
+		iter.curr.p->tcNodeId,
+                iter.curr.p->reference_count);
     }
   }
 
diff -Nrup a/storage/ndb/src/kernel/blocks/dbtc/Dbtc.hpp b/storage/ndb/src/kernel/blocks/dbtc/Dbtc.hpp
--- a/storage/ndb/src/kernel/blocks/dbtc/Dbtc.hpp	2007-10-15 10:05:55 +02:00
+++ b/storage/ndb/src/kernel/blocks/dbtc/Dbtc.hpp	2007-11-02 17:23:13 +01:00
@@ -636,7 +636,6 @@ public:
     ConnectionState apiConnectstate;
     UintR transid[2];
     UintR firstTcConnect;
-    NdbNodeBitmask m_transaction_nodes; 
     
     //---------------------------------------------------
     // Second 16 byte cache line. Hot variables.
@@ -672,26 +671,43 @@ public:
     //---------------------------------------------------
     UintR lastTcConnect;
     UintR lqhkeyreqrec;
-    AbortState abortState;
     Uint32 buddyPtr;
+    union {
+      UintR apiScanRec;
+      UintR commitAckMarker;
+    };
+
+    Uint32 no_commit_ack_markers;
+    ReturnSignal returnsignal;
+    AbortState abortState;
+
+    Uint8 indexOpReturn;
+    Uint8 triggerPending; // Used to mark waiting for a CONTINUEB
+
     Uint8 m_exec_flag;
-    Uint8 unused2;
+    Uint8 isIndexOp;      // Used to mark on-going TcKeyReq as indx table access
+
     Uint8 takeOverRec;
     Uint8 currentReplicaNo;
+    Uint8 m_commit_ack_marker_received;
+
+    Uint8 tckeyrec; // Changed from R
+
+    Uint8 tcindxrec;
+    Uint8 apiFailState; // Changed R
+    Uint8 timeOutCounter;
+    Uint8 singleUserMode;
     
+    Uint16 returncode;
+    Uint16 takeOverInd;
     //---------------------------------------------------
     // Error Handling variables. If cache line 32 bytes
     // ensures that cache line is still only read in
     // early phases.
     //---------------------------------------------------
-    union {
-      UintR apiScanRec;
-      UintR commitAckMarker;
-    };
     UintR currentTcConnect;
     BlockReference tcBlockref;
-    Uint16 returncode;
-    Uint16 takeOverInd;
+    UintR failureNr;
     
     //---------------------------------------------------
     // Second 64 byte cache line. Third 16 byte cache line
@@ -706,15 +722,8 @@ public:
     // timeOutCounter is used waiting for ABORTCONF, COMMITCONF
     // and COMPLETECONF
     //---------------------------------------------------
-    UintR failureNr;
-    Uint8 tcindxrec;
-    Uint8 singleUserMode;
-    ReturnSignal returnsignal;
-    Uint8 timeOutCounter;
-    
     UintR tcSendArray[6];
+    NdbNodeBitmask m_transaction_nodes; 
     
     // Trigger data
     
@@ -723,12 +732,9 @@ public:
      */  
     DLFifoList<TcFiredTriggerData> theFiredTriggers;
     
-    bool triggerPending; // Used to mark waiting for a CONTINUEB
     
     // Index data
     
-    Uint8 isIndexOp;      // Used to mark on-going TcKeyReq as indx table access
-    bool indexOpReturn;
     UintR noIndexOp;     // No outstanding index ops
 
     // Index op return context
@@ -1825,8 +1831,7 @@ public:
     Uint32 prevHash;
     Uint32 apiConnectPtr;
     Uint16 apiNodeId;
-    Uint16 noOfLqhs;
-    Uint16 lqhNodeId[MAX_REPLICAS];
+    NdbNodeBitmask m_commit_ack_marker_nodes; 
 
     inline bool equal(const CommitAckMarker & p) const {
       return ((p.transid1 == transid1) && (p.transid2 == transid2));
diff -Nrup a/storage/ndb/src/kernel/blocks/dbtc/DbtcInit.cpp b/storage/ndb/src/kernel/blocks/dbtc/DbtcInit.cpp
--- a/storage/ndb/src/kernel/blocks/dbtc/DbtcInit.cpp	2007-02-14 18:24:37 +01:00
+++ b/storage/ndb/src/kernel/blocks/dbtc/DbtcInit.cpp	2007-11-02 17:23:13 +01:00
@@ -113,8 +113,8 @@ void Dbtc::initRecords() 
 						  sizeof(TcConnectRecord),
 						  ctcConnectFilesize);
   
-  m_commitAckMarkerPool.setSize(capiConnectFilesize);
-  m_commitAckMarkerHash.setSize(512);
+  m_commitAckMarkerPool.setSize(2 * capiConnectFilesize);
+  m_commitAckMarkerHash.setSize(1024);
 
   hostRecord = (HostRecord*)allocRecord("HostRecord",
 					sizeof(HostRecord),
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	2007-10-15 11:30:56 +02:00
+++ b/storage/ndb/src/kernel/blocks/dbtc/DbtcMain.cpp	2007-11-02 17:23:13 +01:00
@@ -22,6 +22,7 @@
 #include <my_sys.h>
 #include <ndb_rand.h>
 
+#include <signaldata/DiGetNodes.hpp>
 #include <signaldata/EventReport.hpp>
 #include <signaldata/TcKeyReq.hpp>
 #include <signaldata/TcKeyConf.hpp>
@@ -2411,6 +2412,8 @@ void Dbtc::initApiConnectRec(Signal* sig
   regApiPtr->lqhkeyreqrec = 0;
   regApiPtr->tckeyrec = 0;
   regApiPtr->tcindxrec = 0;
+  regApiPtr->m_commit_ack_marker_received = 0;
+  regApiPtr->no_commit_ack_markers = 0;
   regApiPtr->failureNr = TfailureNr;
   regApiPtr->transid[0] = Ttransid0;
   regApiPtr->transid[1] = Ttransid1;
@@ -2865,29 +2868,41 @@ void Dbtc::execTCKEYREQ(Signal* signal) 
     Uint32 TreadCount = c_counters.creadCount;
     jam();
     c_counters.creadCount = TreadCount + 1;
-  } else {
-    if(regApiPtr->commitAckMarker == RNIL){
-      jam();
-      CommitAckMarkerPtr tmp;
-      if(!m_commitAckMarkerHash.seize(tmp)){
-        TCKEY_abort(signal, 56);
-        return;
-      } else {
-        regTcPtr->commitAckMarker = tmp.i;
-        regApiPtr->commitAckMarker = tmp.i;
-        tmp.p->transid1      = tcKeyReq->transId1;
-        tmp.p->transid2      = tcKeyReq->transId2;
-        tmp.p->apiNodeId     = refToNode(regApiPtr->ndbapiBlockref);
-        tmp.p->apiConnectPtr = TapiIndex;
-        tmp.p->noOfLqhs      = 0;
+  }
+  else
+  {
+    if (!regApiPtr->m_commit_ack_marker_received)
+    {
+      if(regApiPtr->commitAckMarker != RNIL)
+        regTcPtr->commitAckMarker = regApiPtr->commitAckMarker;
+      else
+      {
+        jam();
+        CommitAckMarkerPtr tmp;
+        if (!m_commitAckMarkerHash.seize(tmp))
+        {
+          TCKEY_abort(signal, 56);
+          return;
+        }
+        else
+        {
+          regTcPtr->commitAckMarker = tmp.i;
+          regApiPtr->commitAckMarker = tmp.i;
+          tmp.p->transid1      = tcKeyReq->transId1;
+          tmp.p->transid2      = tcKeyReq->transId2;
+          tmp.p->apiNodeId     = refToNode(regApiPtr->ndbapiBlockref);
+          tmp.p->apiConnectPtr = TapiIndex;
+          tmp.p->m_commit_ack_marker_nodes.clear();
 #if defined VM_TRACE || defined ERROR_INSERT
-	{
-	  CommitAckMarkerPtr check;
-	  ndbrequire(!m_commitAckMarkerHash.find(check, *tmp.p));
-	}
+	  {
+	    CommitAckMarkerPtr check;
+	    ndbrequire(!m_commitAckMarkerHash.find(check, *tmp.p));
+          }
 #endif
-        m_commitAckMarkerHash.add(tmp);
+          m_commitAckMarkerHash.add(tmp);
+        }
       }
+      regApiPtr->no_commit_ack_markers++;
     }
     
     UintR TwriteCount = c_counters.cwriteCount;
@@ -2993,12 +3008,6 @@ void Dbtc::tckeyreq050Lab(Signal* signal
 
   hash(signal); /* NOW IT IS TIME TO CALCULATE THE HASH VALUE*/
   
-  if (unlikely(terrorCode))
-  {
-    releaseAtErrorLab(signal);
-    return;
-  }
-
   CacheRecord * const regCachePtr = cachePtr.p;
   TcConnectRecord * const regTcPtr = tcConnectptr.p;
   ApiConnectRecord * const regApiPtr = apiConnectptr.p;
@@ -3006,7 +3015,6 @@ void Dbtc::tckeyreq050Lab(Signal* signal
   UintR TtcTimer = ctcTimer;
   UintR ThashValue = thashValue;
   UintR TdistrHashValue = tdistrHashValue;
-  UintR TdihConnectptr = regTcPtr->dihConnectptr;
   UintR Ttableref = regCachePtr->tableref;
   
   TableRecordPtr localTabptr;
@@ -3024,13 +3032,10 @@ void Dbtc::tckeyreq050Lab(Signal* signal
   setApiConTimer(apiConnectptr.i, TtcTimer, __LINE__);
   regCachePtr->hashValue = ThashValue;
 
-  signal->theData[0] = TdihConnectptr;
-  signal->theData[1] = Ttableref;
-  signal->theData[2] = TdistrHashValue;
-  signal->theData[3] = 0;
-  signal->theData[4] = 0;
-  signal->theData[5] = 0;
-  signal->theData[6] = 0;
+  DiGetNodesReq * const req = (DiGetNodesReq *)&signal->theData[0];
+  req->tableId = Ttableref;
+  req->hashValue = TdistrHashValue;
+  req->distr_key_indicator = regCachePtr->distributionKeyIndicator;
 
   /*-------------------------------------------------------------*/
   /* FOR EFFICIENCY REASONS WE AVOID THE SIGNAL SENDING HERE AND */
@@ -3040,7 +3045,8 @@ void Dbtc::tckeyreq050Lab(Signal* signal
   /* TO DIH IN TRAFFIC IT SHOULD BE OK (3% OF THE EXECUTION TIME */
   /* IS SPENT IN DIH AND EVEN LESS IN REPLICATED NDB.            */
   /*-------------------------------------------------------------*/
-  EXECUTE_DIRECT(DBDIH, GSN_DIGETNODESREQ, signal, 3);
+  EXECUTE_DIRECT(DBDIH, GSN_DIGETNODESREQ, signal,
+                 DiGetNodesReq::SignalLength);
   UintR TerrorIndicator = signal->theData[0];
   jamEntry();
   if (TerrorIndicator != 0) {
@@ -3060,12 +3066,13 @@ void Dbtc::tckeyreq050Lab(Signal* signal
   /* DIGETNODESCONF >*/
   /* ***************>*/
 
-  UintR Tdata1 = signal->theData[1];
-  UintR Tdata2 = signal->theData[2];
-  UintR Tdata3 = signal->theData[3];
-  UintR Tdata4 = signal->theData[4];
-  UintR Tdata5 = signal->theData[5];
-  UintR Tdata6 = signal->theData[6];
+  const DiGetNodesConf * const conf = (DiGetNodesConf *)&signal->theData[0];
+  UintR Tdata1 = conf->fragId;
+  UintR Tdata2 = conf->reqinfo;
+  UintR Tdata3 = conf->nodes[0];
+  UintR Tdata4 = conf->nodes[1];
+  UintR Tdata5 = conf->nodes[2];
+  UintR Tdata6 = conf->nodes[3];
 
   regCachePtr->fragmentid = Tdata1;
   tnodeinfo = Tdata2;
@@ -3282,22 +3289,7 @@ void Dbtc::sendlqhkeyreq(Signal* signal,
    * Bit 28 == 0 since readLenAi can only be set after reading in LQH.
    * ----------------------------------------------------------------------- */
   //LqhKeyReq::setAPIVersion(Tdata10, regCachePtr->apiVersionNo);
-  Uint32 commitAckMarker = regTcPtr->commitAckMarker;
-  const Uint32 noOfLqhs = regTcPtr->noOfNodes;
-  if(commitAckMarker != RNIL){
-    jam();
-    LqhKeyReq::setMarkerFlag(Tdata10, 1);
-
-    CommitAckMarker * tmp = m_commitAckMarkerHash.getPtr(commitAckMarker);
-    
-    /**
-     * Populate LQH array
-     */
-    tmp->noOfLqhs = noOfLqhs;
-    for(Uint32 i = 0; i<noOfLqhs; i++){
-      tmp->lqhNodeId[i] = regTcPtr->tcNodedata[i];
-    }
-  }
+  LqhKeyReq::setMarkerFlag(Tdata10, regTcPtr->commitAckMarker != RNIL ? 1 : 0);
   
   /* ************************************************************> */
   /* NO READ LENGTH SENT FROM TC. SEQUENTIAL NUMBER IS 1 AND IT    */
@@ -3786,8 +3778,21 @@ void Dbtc::execLQHKEYCONF(Signal* signal
     return;
   }//if
 
+  Uint32 commitAckMarker = regTcPtr->commitAckMarker;
   setApiConTimer(apiConnectptr.i, TtcTimer, __LINE__);
 
+  if (commitAckMarker != RNIL)
+  {
+    const Uint32 noOfLqhs = regTcPtr->noOfNodes;
+    CommitAckMarker * tmp = m_commitAckMarkerHash.getPtr(commitAckMarker);
+    jam();
+    regApiPtr.p->m_commit_ack_marker_received = TRUE;
+    /**
+     * Populate LQH array
+     */
+    for(Uint32 i = 0; i < noOfLqhs; i++)
+      tmp->m_commit_ack_marker_nodes.set(regTcPtr->tcNodedata[i]);
+  }
   if (regTcPtr->isIndexOp) {
     jam();
     // This was an internal TCKEYREQ
@@ -4703,8 +4708,16 @@ void Dbtc::sendApiCommit(Signal* signal)
 {
   ApiConnectRecord * const regApiPtr = apiConnectptr.p;
 
-  if (regApiPtr->returnsignal == RS_TCKEYCONF) {
-    sendtckeyconf(signal, 1);
+  if (regApiPtr->returnsignal == RS_TCKEYCONF)
+  {
+    if (ERROR_INSERTED(8054))
+    {
+      CLEAR_ERROR_INSERT_VALUE;
+      signal->theData[0] = 9999;
+      sendSignalWithDelay(CMVMI_REF, GSN_NDB_TAMPER, signal, 5000, 1);
+    }
+    else
+      sendtckeyconf(signal, 1);
   } else if (regApiPtr->returnsignal == RS_TC_COMMITCONF) {
     jam();
     TcCommitConf * const commitConf = (TcCommitConf *)&signal->theData[0];
@@ -4923,16 +4936,17 @@ Dbtc::execTC_COMMIT_ACK(Signal* signal){
 }
 
 void
-Dbtc::sendRemoveMarkers(Signal* signal, const CommitAckMarker * marker){
+Dbtc::sendRemoveMarkers(Signal* signal, const CommitAckMarker * marker)
+{
   jam();
-  const Uint32 noOfLqhs = marker->noOfLqhs;
   const Uint32 transId1 = marker->transid1;
   const Uint32 transId2 = marker->transid2;
   
-  for(Uint32 i = 0; i<noOfLqhs; i++){
+  for(Uint32 node_id = 1; node_id < MAX_NDB_NODES; node_id++)
+  {
     jam();
-    const NodeId nodeId = marker->lqhNodeId[i];
-    sendRemoveMarker(signal, nodeId, transId1, transId2);
+    if (marker->m_commit_ack_marker_nodes.get(node_id))
+      sendRemoveMarker(signal, node_id, transId1, transId2);
   }
 }
 
@@ -5234,7 +5248,6 @@ void Dbtc::execLQHKEYREF(Signal* signal)
 	}
       }
       
-      Uint32 marker = regTcPtr->commitAckMarker;
       markOperationAborted(regApiPtr, regTcPtr);
       
       if(regApiPtr->apiConnectstate == CS_ABORTING){
@@ -5254,16 +5267,6 @@ void Dbtc::execLQHKEYREF(Signal* signal)
 	return;
       }//if
 
-      if (marker != RNIL){
-	/**
-	 * This was an insert/update/delete/write which failed
-	 *   that contained the marker
-	 * Currently unsupported to place new marker
-	 */
-	TCKEY_abort(signal, 49);
-	return;
-      }
-      
       /* *************** */
       /*    TCKEYREF   < */
       /* *************** */
@@ -5326,13 +5329,18 @@ void Dbtc::clearCommitAckMarker(ApiConne
   const Uint32 commitAckMarker = regTcPtr->commitAckMarker;
   if (regApiPtr->commitAckMarker == RNIL)
     ndbassert(commitAckMarker == RNIL);
-  if (commitAckMarker != RNIL)
-    ndbassert(regApiPtr->commitAckMarker != RNIL);
   if(commitAckMarker != RNIL){
     jam();
-    m_commitAckMarkerHash.release(commitAckMarker);
+    ndbassert(regApiPtr->commitAckMarker != RNIL);
+    ndbrequire(regApiPtr->no_commit_ack_markers > 0);
+    regApiPtr->no_commit_ack_markers--;
     regTcPtr->commitAckMarker = RNIL;
-    regApiPtr->commitAckMarker = RNIL;
+    if (regApiPtr->no_commit_ack_markers == 0)
+    {
+      regApiPtr->commitAckMarker = RNIL;
+      regApiPtr->m_commit_ack_marker_received = FALSE;
+      m_commitAckMarkerHash.release(commitAckMarker);
+    }
   }
 }
 
@@ -7939,12 +7947,7 @@ void Dbtc::toAbortHandlingLab(Signal* si
 	  const Uint32 marker = apiConnectptr.p->commitAckMarker;
           if(marker != RNIL){
 	    jam();
-
-            CommitAckMarkerPtr tmp;
-            tmp.i = marker;
-            tmp.p = m_commitAckMarkerHash.getPtr(tmp.i);
-            
-            m_commitAckMarkerHash.release(tmp);
+            m_commitAckMarkerHash.release(marker);
             apiConnectptr.p->commitAckMarker = RNIL;
           }
           
@@ -8400,8 +8403,7 @@ void Dbtc::initApiConnectFail(Signal* si
     tmp.p->transid1      = ttransid1;
     tmp.p->transid2      = ttransid2;
     tmp.p->apiNodeId     = refToNode(tapplRef);
-    tmp.p->noOfLqhs      = 1;
-    tmp.p->lqhNodeId[0]  = tnodeid;
+    tmp.p->m_commit_ack_marker_nodes.set(tnodeid);
     tmp.p->apiConnectPtr = apiConnectptr.i;
 
 #if defined VM_TRACE || defined ERROR_INSERT
@@ -8549,13 +8551,14 @@ void Dbtc::setupFailData(Signal* signal)
 /*----------------------------------------------------------*/
 void Dbtc::updateApiStateFail(Signal* signal) 
 {
-  if(LqhTransConf::getMarkerFlag(treqinfo)){
-    jam();
+  if(LqhTransConf::getMarkerFlag(treqinfo))
+  {
+    CommitAckMarkerPtr tmp;
     const Uint32 marker = apiConnectptr.p->commitAckMarker;
-    if(marker == RNIL){
+    if (marker == RNIL)
+    {
       jam();
 
-      CommitAckMarkerPtr tmp;
       m_commitAckMarkerHash.seize(tmp);
       ndbrequire(tmp.i != RNIL);
       
@@ -8563,8 +8566,6 @@ void Dbtc::updateApiStateFail(Signal* si
       tmp.p->transid1      = ttransid1;
       tmp.p->transid2      = ttransid2;
       tmp.p->apiNodeId     = refToNode(tapplRef);
-      tmp.p->noOfLqhs      = 1;
-      tmp.p->lqhNodeId[0]  = tnodeid;
       tmp.p->apiConnectPtr = apiConnectptr.i;
 #if defined VM_TRACE || defined ERROR_INSERT
       {
@@ -8575,16 +8576,10 @@ void Dbtc::updateApiStateFail(Signal* si
       m_commitAckMarkerHash.add(tmp);
     } else {
       jam();
-      
-      CommitAckMarkerPtr tmp;
       tmp.i = marker;
       tmp.p = m_commitAckMarkerHash.getPtr(marker);
-
-      const Uint32 noOfLqhs = tmp.p->noOfLqhs;
-      ndbrequire(noOfLqhs < MAX_REPLICAS);
-      tmp.p->lqhNodeId[noOfLqhs] = tnodeid;
-      tmp.p->noOfLqhs = (noOfLqhs + 1);
     }
+    tmp.p->m_commit_ack_marker_nodes.set(tnodeid);
   }
 
   switch (ttransStatus) {
@@ -9244,10 +9239,13 @@ void Dbtc::diFcountReqLab(Signal* signal
   }
   else 
   {
-    signal->theData[0] = tcConnectptr.p->dihConnectptr;
-    signal->theData[1] = tabPtr.i;
-    signal->theData[2] = cachePtr.p->distributionKey;
-    EXECUTE_DIRECT(DBDIH, GSN_DIGETNODESREQ, signal, 3);
+    DiGetNodesReq * const req = (DiGetNodesReq *)&signal->theData[0];
+    const DiGetNodesConf * const get_conf = (DiGetNodesConf *)&signal->theData[0];
+    req->tableId = tabPtr.i;
+    req->hashValue = cachePtr.p->distributionKey;
+    req->distr_key_indicator = TRUE;
+    EXECUTE_DIRECT(DBDIH, GSN_DIGETNODESREQ, signal,
+                   DiGetNodesReq::SignalLength);
     UintR TerrorIndicator = signal->theData[0];
     jamEntry();
     if (TerrorIndicator != 0) {
@@ -9258,8 +9256,7 @@ void Dbtc::diFcountReqLab(Signal* signal
       return;
     }
     
-    UintR Tdata1 = signal->theData[1];
-    scanptr.p->scanNextFragId = Tdata1;
+    scanptr.p->scanNextFragId = get_conf->fragId;
     DihFragCountConf * const conf = (DihFragCountConf*)signal->getDataPtr();
     conf->m_connectionData = tcConnectptr.i;
     conf->m_fragmentCount = 1; // Frag count
@@ -10977,32 +10974,34 @@ Dbtc::execDUMP_STATE_ORD(Signal* signal)
   jamEntry();
   DumpStateOrd * const dumpState = (DumpStateOrd *)&signal->theData[0];
   Uint32 arg = signal->theData[0];
-  if(signal->theData[0] == DumpStateOrd::CommitAckMarkersSize){
+  if (signal->theData[0] == DumpStateOrd::CommitAckMarkersSize)
+  {
     infoEvent("TC: m_commitAckMarkerPool: %d free size: %d",
               m_commitAckMarkerPool.getNoOfFree(),
               m_commitAckMarkerPool.getSize());
+    return;
   }
-  if(signal->theData[0] == DumpStateOrd::CommitAckMarkersDump){
+  if (signal->theData[0] == DumpStateOrd::CommitAckMarkersDump)
+  {
     infoEvent("TC: m_commitAckMarkerPool: %d free size: %d",
               m_commitAckMarkerPool.getNoOfFree(),
               m_commitAckMarkerPool.getSize());
-    
     CommitAckMarkerIterator iter;
     for(m_commitAckMarkerHash.first(iter); iter.curr.i != RNIL;
         m_commitAckMarkerHash.next(iter)){
       infoEvent("CommitAckMarker: i = %d (0x%x, 0x%x)"
-                " Api: %d Lghs(%d): %d %d %d %d bucket = %d",
+                " Api: %d %x %x %x %x bucket = %d",
                 iter.curr.i,
                 iter.curr.p->transid1,
                 iter.curr.p->transid2,
                 iter.curr.p->apiNodeId,
-                iter.curr.p->noOfLqhs,
-                iter.curr.p->lqhNodeId[0],
-                iter.curr.p->lqhNodeId[1],
-                iter.curr.p->lqhNodeId[2],
-                iter.curr.p->lqhNodeId[3],
+                iter.curr.p->m_commit_ack_marker_nodes.getWord(0),
+                iter.curr.p->m_commit_ack_marker_nodes.getWord(1),
+                iter.curr.p->m_commit_ack_marker_nodes.getWord(2),
+                iter.curr.p->m_commit_ack_marker_nodes.getWord(3),
                 iter.bucket);
     }
+    return;
   }
   // Dump all ScanFragRecs
   if (dumpState->args[0] == DumpStateOrd::TcDumpAllScanFragRec){
@@ -11374,6 +11373,13 @@ Dbtc::execDUMP_STATE_ORD(Signal* signal)
     }
     return;
   }
+#ifdef ERROR_INSERT
+  if (arg == 2552)
+  {
+    ndbrequire(m_commitAckMarkerPool.getNoOfFree() == m_commitAckMarkerPool.getSize());
+    return;
+  }
+#endif
 }//Dbtc::execDUMP_STATE_ORD()
 
 bool
diff -Nrup a/storage/ndb/test/ndbapi/testBasic.cpp b/storage/ndb/test/ndbapi/testBasic.cpp
--- a/storage/ndb/test/ndbapi/testBasic.cpp	2007-10-15 10:05:57 +02:00
+++ b/storage/ndb/test/ndbapi/testBasic.cpp	2007-11-02 17:23:13 +01:00
@@ -532,7 +532,7 @@ int runCommit_CommitAsMuchAsPossible630(
 
     CHECK(hugoOps.startTransaction(pNdb) == 0);
     CHECK(hugoOps.pkReadRecord(pNdb, 2) == 0);
-    CHECK(hugoOps.execute_Commit(pNdb) == 0);
+    CHECK(hugoOps.execute_Commit(pNdb) == 626);
   } while(false);
 
   hugoOps.closeTransaction(pNdb);
diff -Nrup a/storage/ndb/test/ndbapi/testNodeRestart.cpp b/storage/ndb/test/ndbapi/testNodeRestart.cpp
--- a/storage/ndb/test/ndbapi/testNodeRestart.cpp	2007-10-15 15:05:24 +02:00
+++ b/storage/ndb/test/ndbapi/testNodeRestart.cpp	2007-11-02 17:23:13 +01:00
@@ -1921,6 +1921,207 @@ runBug31525(NDBT_Context* ctx, NDBT_Step
   return NDBT_OK;
 }
 
+int 
+runCommitAck(NDBT_Context* ctx, NDBT_Step* step)
+{
+  int loops = ctx->getNumLoops();
+  int records = ctx->getNumRecords();
+  NdbRestarter restarter;
+  Ndb* pNdb = GETNDB(step);
+
+  if (records < 2)
+    return NDBT_OK;
+  if (restarter.getNumDbNodes() < 2)
+    return NDBT_OK;
+
+  int trans_type= -1;
+  NdbConnection *pCon;
+  int node;
+  while (loops--)
+  {
+    trans_type++;
+    if (trans_type > 2)
+      trans_type= 0;
+    HugoTransactions hugoTrans(*ctx->getTab());
+    switch (trans_type) {
+    case 0:
+      /*
+        - load records less 1
+      */
+      g_info << "case 0\n";
+      if (hugoTrans.loadTable(GETNDB(step), records - 1))
+      {
+        return NDBT_FAILED;
+      }
+      break;
+    case 1:
+      /*
+        - load 1 record
+      */
+      g_info << "case 1\n";
+      if (hugoTrans.loadTable(GETNDB(step), 1))
+      {
+        return NDBT_FAILED;
+      }
+      break;
+    case 2:
+      /*
+        - load 1 record in the end
+      */
+      g_info << "case 2\n";
+      {
+        HugoOperations hugoOps(*ctx->getTab());
+        if (hugoOps.startTransaction(pNdb))
+          abort();
+        if (hugoOps.pkInsertRecord(pNdb, records-1))
+          abort();
+        if (hugoOps.execute_Commit(pNdb))
+          abort();
+        if (hugoOps.closeTransaction(pNdb))
+          abort();
+      }
+      break;
+    default:
+      abort();
+    }
+
+    /* run transaction that should be tested */
+    HugoOperations hugoOps(*ctx->getTab());
+    if (hugoOps.startTransaction(pNdb))
+      return NDBT_FAILED;
+    pCon= hugoOps.getTransaction();
+    node= pCon->getConnectedNodeId();
+    switch (trans_type) {
+    case 0:
+    case 1:
+      /*
+        insert records with ignore error
+        - insert rows, some exist already
+      */
+      for (int i= 0; i < records; i++)
+      {
+        if (hugoOps.pkInsertRecord(pNdb, i))
+          goto err;
+      }
+      break;
+    case 2:
+      /*
+        insert records with ignore error
+        - insert rows, some exist already
+      */
+      for (int i= 0; i < records; i++)
+      {
+        if (hugoOps.pkInsertRecord(pNdb, i))
+          goto err;
+      }
+      break;
+    default:
+      abort();
+    }
+
+    /*
+      insert error in ndb kernel (TC) that throws away acknowledge of commit
+      and then die 5 seconds later
+    */
+    {
+      if (restarter.insertErrorInNode(node, 8054))
+        goto err;
+    }
+    {
+      int val2[] = { DumpStateOrd::CmvmiSetRestartOnErrorInsert, 1 };
+      if (restarter.dumpStateOneNode(node, val2, 2))
+        goto err;
+    }
+
+    /* execute transaction and verify return code */
+    g_info << "  execute... hangs for 5 seconds\n";
+    {
+      const NdbOperation *first= pCon->getFirstDefinedOperation();
+      int check= pCon->execute(Commit, AO_IgnoreError);
+      const NdbError err = pCon->getNdbError();
+
+      while (first)
+      {
+        const NdbError &err= first->getNdbError();
+        g_info << "         error " << err.code << endl;
+        first= pCon->getNextCompletedOperation(first);
+      }
+
+      int expected_commit_res[3]= { 630, 630, 630 };
+      if (check == -1 ||
+          err.code != expected_commit_res[trans_type])
+      {
+        g_err << "check == " << check << endl;
+        g_err << "got error: "
+              << err.code
+              << " expected: "
+              << expected_commit_res[trans_type]
+              << endl;
+        goto err;
+      }
+    }
+
+    g_info << "  wait node nostart\n";
+    if (restarter.waitNodesNoStart(&node, 1))
+    {
+      g_err << "  wait node nostart failed\n";
+      goto err;
+    }
+
+    /* close transaction */
+    if (hugoOps.closeTransaction(pNdb))
+      return NDBT_FAILED;
+
+    /* commit ack marker pools should be empty */
+    g_info << "  dump pool status\n";
+    {
+      int dump[255];
+      dump[0] = 2552;
+      if (restarter.dumpStateAllNodes(dump, 1))
+        return NDBT_FAILED;
+    }
+
+    /* wait for cluster to come up again */
+    g_info << "  wait cluster started\n";
+    if (restarter.startNodes(&node, 1) ||
+        restarter.waitNodesStarted(&node, 1))
+    {
+      g_err << "Cluster failed to start\n";
+      return NDBT_FAILED;
+    }
+
+    /* verify data */
+    g_info << "  verifying\n";
+    switch (trans_type) {
+    case 0:
+    case 1:
+    case 2:
+      /*
+        insert records with ignore error
+        - should have all records
+      */
+      if (hugoTrans.scanReadRecords(GETNDB(step), records, 0, 64) != 0){
+        return NDBT_FAILED;
+      }
+      break;
+    default:
+      abort();
+    }
+
+    /* cleanup for next round in loop */
+    g_info << "  cleaning\n";
+    if (hugoTrans.clearTable(GETNDB(step), records))
+    {
+      return NDBT_FAILED;
+    }
+    continue;
+err:
+    hugoOps.closeTransaction(pNdb);
+    return NDBT_FAILED;
+  }
+  return NDBT_OK;
+}
+
 NDBT_TESTSUITE(testNodeRestart);
 TESTCASE("NoLoad", 
 	 "Test that one node at a time can be stopped and then restarted "\
@@ -2294,6 +2495,10 @@ TESTCASE("GCP", ""){
   INITIALIZER(runLoadTable);
   STEP(runGCP);
   STEP(runScanUpdateUntilStopped);
+  FINALIZER(runClearTable);
+}
+TESTCASE("CommitAck", ""){
+  INITIALIZER(runCommitAck);
   FINALIZER(runClearTable);
 }
 NDBT_TESTSUITE_END(testNodeRestart);
Thread
bk commit into 5.1 tree (tomas:1.2700)tomas2 Nov