List:Commits« Previous MessageNext Message »
From:jonas Date:August 24 2007 2:17pm
Subject:bk commit into 5.1 tree (jonas:1.2612)
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, 2007-08-24 16:17:41+02:00, jonas@stripped +29 -0
  micro GCP - commit to test

  storage/ndb/include/kernel/signaldata/FireTrigOrd.hpp@stripped, 2007-08-24 16:17:30+02:00, jonas@stripped +6 -4
    micro GCP - commit to test

  storage/ndb/include/kernel/signaldata/GCP.hpp@stripped, 2007-08-24 16:17:30+02:00, jonas@stripped +18 -12
    micro GCP - commit to test

  storage/ndb/include/kernel/signaldata/MasterGCP.hpp@stripped, 2007-08-24 16:17:30+02:00, jonas@stripped +51 -4
    micro GCP - commit to test

  storage/ndb/include/kernel/signaldata/SumaImpl.hpp@stripped, 2007-08-24 16:17:30+02:00, jonas@stripped +10 -5
    micro GCP - commit to test

  storage/ndb/include/kernel/signaldata/TupCommit.hpp@stripped, 2007-08-24 16:17:30+02:00, jonas@stripped +3 -2
    micro GCP - commit to test

  storage/ndb/src/common/debugger/signaldata/SumaImpl.cpp@stripped, 2007-08-24 16:17:30+02:00, jonas@stripped +3 -2
    micro GCP - commit to test

  storage/ndb/src/kernel/blocks/ERROR_codes.txt@stripped, 2007-08-24 16:17:30+02:00, jonas@stripped +16 -1
    micro GCP - commit to test

  storage/ndb/src/kernel/blocks/dbdih/Dbdih.hpp@stripped, 2007-08-24 16:17:30+02:00, jonas@stripped +89 -53
    micro GCP - commit to test

  storage/ndb/src/kernel/blocks/dbdih/DbdihInit.cpp@stripped, 2007-08-24 16:17:31+02:00, jonas@stripped +3 -1
    micro GCP - commit to test

  storage/ndb/src/kernel/blocks/dbdih/DbdihMain.cpp@stripped, 2007-08-24 16:17:31+02:00, jonas@stripped +956 -501
    micro GCP - commit to test

  storage/ndb/src/kernel/blocks/dblqh/Dblqh.hpp@stripped, 2007-08-24 16:17:31+02:00, jonas@stripped +10 -7
    micro GCP - commit to test

  storage/ndb/src/kernel/blocks/dblqh/DblqhMain.cpp@stripped, 2007-08-24 16:17:31+02:00, jonas@stripped +62 -44
    micro GCP - commit to test

  storage/ndb/src/kernel/blocks/dbtc/Dbtc.hpp@stripped, 2007-08-24 16:17:31+02:00, jonas@stripped +8 -8
    micro GCP - commit to test

  storage/ndb/src/kernel/blocks/dbtc/DbtcMain.cpp@stripped, 2007-08-24 16:17:31+02:00, jonas@stripped +27 -19
    micro GCP - commit to test

  storage/ndb/src/kernel/blocks/dbtup/Dbtup.hpp@stripped, 2007-08-24 16:17:31+02:00, jonas@stripped +2 -1
    micro GCP - commit to test

  storage/ndb/src/kernel/blocks/dbtup/DbtupCommit.cpp@stripped, 2007-08-24 16:17:31+02:00, jonas@stripped +22 -16
    micro GCP - commit to test

  storage/ndb/src/kernel/blocks/dbtup/DbtupExecQuery.cpp@stripped, 2007-08-24 16:17:31+02:00, jonas@stripped +2 -2
    micro GCP - commit to test

  storage/ndb/src/kernel/blocks/dbtup/DbtupTrigger.cpp@stripped, 2007-08-24 16:17:31+02:00, jonas@stripped +3 -2
    micro GCP - commit to test

  storage/ndb/src/kernel/blocks/suma/Suma.cpp@stripped, 2007-08-24 16:17:32+02:00, jonas@stripped +120 -57
    micro GCP - commit to test

  storage/ndb/src/kernel/blocks/suma/Suma.hpp@stripped, 2007-08-24 16:17:32+02:00, jonas@stripped +26 -18
    micro GCP - commit to test

  storage/ndb/src/kernel/blocks/suma/SumaInit.cpp@stripped, 2007-08-24 16:17:32+02:00, jonas@stripped +4 -0
    micro GCP - commit to test

  storage/ndb/src/ndbapi/NdbEventOperationImpl.cpp@stripped, 2007-08-24 16:17:32+02:00, jonas@stripped +328 -171
    micro GCP - commit to test

  storage/ndb/src/ndbapi/NdbEventOperationImpl.hpp@stripped, 2007-08-24 16:17:32+02:00, jonas@stripped +24 -2
    micro GCP - commit to test

  storage/ndb/src/ndbapi/Ndbif.cpp@stripped, 2007-08-24 16:17:32+02:00, jonas@stripped +2 -2
    micro GCP - commit to test

  storage/ndb/test/include/NdbRestarter.hpp@stripped, 2007-08-24 16:17:32+02:00, jonas@stripped +9 -0
    micro GCP - commit to test

  storage/ndb/test/ndbapi/testNodeRestart.cpp@stripped, 2007-08-24 16:17:32+02:00, jonas@stripped +92 -0
    micro GCP - commit to test

  storage/ndb/test/run-test/daily-basic-tests.txt@stripped, 2007-08-24 16:17:32+02:00, jonas@stripped +3 -0
    micro GCP - commit to test

  storage/ndb/test/src/NdbRestarter.cpp@stripped, 2007-08-24 16:17:32+02:00, jonas@stripped +16 -0
    micro GCP - commit to test

  storage/ndb/test/tools/listen.cpp@stripped, 2007-08-24 16:17:32+02:00, jonas@stripped +2 -1
    micro GCP - commit to test

# This is a BitKeeper patch.  What follows are the unified diffs for the
# set of deltas contained in the patch.  The rest of the patch, the part
# that BitKeeper cares about, is below these diffs.
# User:	jonas
# Host:	perch.ndb.mysql.com
# Root:	/home/jonas/src/telco-6.2-micro-commit

--- 1.120/storage/ndb/test/run-test/daily-basic-tests.txt	2007-08-24 16:17:56 +02:00
+++ 1.121/storage/ndb/test/run-test/daily-basic-tests.txt	2007-08-24 16:17:56 +02:00
@@ -954,3 +954,6 @@
 cmd: testMgm
 args: -n ApiMgmStructEventTimeout T1
 
+max-time: 1000
+cmd_ testNodeRestart
+args: -n GCP T1

--- 1.5/storage/ndb/include/kernel/signaldata/FireTrigOrd.hpp	2007-08-24 16:17:56 +02:00
+++ 1.6/storage/ndb/include/kernel/signaldata/FireTrigOrd.hpp	2007-08-24 16:17:56 +02:00
@@ -44,6 +44,7 @@
   friend class Dbtc;
   friend class Backup;
   friend class SumaParticipant;
+  friend class Suma;
   
   /**
    * For printing
@@ -53,7 +54,7 @@
 public:
   STATIC_CONST( SignalLength = 8 );
   STATIC_CONST( SignalWithGCILength = 9 );
-  STATIC_CONST( SignalLengthSuma = 11 );
+  STATIC_CONST( SignalLengthSuma = 12 );
 
 private:
   Uint32 m_connectionPtr;
@@ -64,9 +65,10 @@
   Uint32 m_noBeforeValueWords;
   Uint32 m_noAfterValueWords;
   Uint32 fragId;
-  Uint32 m_gci;
+  Uint32 m_gci_hi;
   Uint32 m_hashValue;
   Uint32 m_any_value;
+  Uint32 m_gci_lo;
   // Public methods
 public:
   Uint32 getConnectionPtr() const;
@@ -178,13 +180,13 @@
 inline
 Uint32 FireTrigOrd::getGCI() const
 {
-  return m_gci;
+  return m_gci_hi;
 }
 
 inline
 void FireTrigOrd::setGCI(Uint32 aGCI)
 {
-  m_gci = aGCI;
+  m_gci_hi = aGCI;
 }
 
 inline

--- 1.5/storage/ndb/include/kernel/signaldata/GCP.hpp	2007-08-24 16:17:56 +02:00
+++ 1.6/storage/ndb/include/kernel/signaldata/GCP.hpp	2007-08-24 16:17:56 +02:00
@@ -20,50 +20,56 @@
 
 struct GCPPrepare // Distr. DIH-DIH
 {
-  STATIC_CONST( SignalLength = 2 );
+  STATIC_CONST( SignalLength = 3 );
 
   Uint32 nodeId;
-  Uint32 gci;
+  Uint32 gci_hi;
+  Uint32 gci_lo;
 };
 
 struct GCPPrepareConf // Distr. DIH-DIH
 {
-  STATIC_CONST( SignalLength = 2 );
+  STATIC_CONST( SignalLength = 3 );
 
   Uint32 nodeId;
-  Uint32 gci;
+  Uint32 gci_hi;
+  Uint32 gci_lo;
 };
 
 struct GCPCommit // Distr. DIH-DIH
 {
-  STATIC_CONST( SignalLength = 2 );
+  STATIC_CONST( SignalLength = 3 );
 
   Uint32 nodeId;
-  Uint32 gci;
+  Uint32 gci_hi;
+  Uint32 gci_lo;
 };
 
 struct GCPNoMoreTrans // Local DIH/TC
 {
-  STATIC_CONST( SignalLength = 2 );
+  STATIC_CONST( SignalLength = 3 );
   Uint32 senderData;
-  Uint32 gci;
+  Uint32 gci_hi;
+  Uint32 gci_lo;
 };
 
 struct GCPTCFinished // Local TC-DIH
 {
-  STATIC_CONST( SignalLength = 2 );
+  STATIC_CONST( SignalLength = 3 );
 
   Uint32 senderData;
-  Uint32 gci;
+  Uint32 gci_hi;
+  Uint32 gci_lo;
 };
 
 struct GCPNodeFinished // Distr. DIH-DIH
 {
-  STATIC_CONST( SignalLength = 3 );
+  STATIC_CONST( SignalLength = 4 );
 
   Uint32 nodeId;
-  Uint32 gci;
+  Uint32 gci_hi;
   Uint32 failno;
+  Uint32 gci_lo;
 };
 
 /**

--- 1.3/storage/ndb/include/kernel/signaldata/MasterGCP.hpp	2007-08-24 16:17:56 +02:00
+++ 1.4/storage/ndb/include/kernel/signaldata/MasterGCP.hpp	2007-08-24 16:17:56 +02:00
@@ -28,14 +28,57 @@
   friend class Dbdih;
     
 public:
-  STATIC_CONST( SignalLength = 8 + NdbNodeBitmask::Size );
+  STATIC_CONST( SignalLength = 10 + NdbNodeBitmask::Size );
 
   enum State {
     GCP_READY            = 0,
+    /**
+     * GCP_PREPARE recevied (and replied)
+     */
     GCP_PREPARE_RECEIVED = 1,
-    GCP_COMMIT_RECEIVED  = 2,
-    GCP_TC_FINISHED      = 3
+
+    /**
+     * GCP_COMMIT received (not replied)
+     */
+    GCP_COMMIT_RECEIVED  = 2, // GCP_COMMIT received (and is running)
+
+    /**
+     * Replied GCP_NODEFINISH
+     *   (i.e GCP_COMMIT finished)
+     */
+    GCP_COMMITTED = 3
+  };
+
+  enum SaveState {
+    GCP_SAVE_IDLE     = 0,
+    /**
+     * GCP_SAVE_REQ received (running in LQH)
+     */
+    GCP_SAVE_REQ      = 1,
+
+    /**
+     * GCP_SAVE_CONF (or REF)
+     */
+    GCP_SAVE_CONF     = 2,
+
+    /**
+     * COPY_GCI_REQ (GCP) has been received and is running
+     */
+    GCP_SAVE_COPY_GCI = 3
+  };
+
+  struct Upgrade {
+    /**
+     * States uses before micro GCP
+     */
+    enum State {
+      GCP_READY            = 0,
+      GCP_PREPARE_RECEIVED = 1,
+      GCP_COMMIT_RECEIVED  = 2,
+      GCP_TC_FINISHED      = 3
+    };
   };
+
 private:  
   /**
    * Data replied
@@ -43,12 +86,16 @@
   Uint32 gcpState;
   Uint32 senderNodeId;
   Uint32 failedNodeId;
-  Uint32 newGCP;
+  Uint32 newGCP_hi;
   Uint32 latestLCP;
   Uint32 oldestRestorableGCI;
   Uint32 keepGCI;
   Uint32 lcpActive[NdbNodeBitmask::Size];
+  Uint32 newGCP_lo;
+  Uint32 saveState;
+  Uint32 saveGCI;
 };
+
 /**
  * 
  */

--- 1.13/storage/ndb/include/kernel/signaldata/SumaImpl.hpp	2007-08-24 16:17:56 +02:00
+++ 1.14/storage/ndb/include/kernel/signaldata/SumaImpl.hpp	2007-08-24 16:17:56 +02:00
@@ -287,7 +287,7 @@
   friend struct Grep;
   
   friend bool printSUB_TABLE_DATA(FILE *, const Uint32 *, Uint32, Uint16);
-  STATIC_CONST( SignalLength = 7 );
+  STATIC_CONST( SignalLength = 8 );
   SECTION( DICT_TAB_INFO = 0 );
   SECTION( ATTR_INFO = 0 );
   SECTION( AFTER_VALUES = 1 );
@@ -300,7 +300,7 @@
   };
   
   Uint32 senderData;
-  Uint32 gci;
+  Uint32 gci_hi;
   Uint32 tableId;
   Uint32 requestInfo;
   Uint32 logType;
@@ -309,6 +309,7 @@
     Uint32 anyValue;
   };
   Uint32 totalLen;
+  Uint32 gci_lo;
 
   static void setOperation(Uint32& ri, Uint32 val) { 
     ri = (ri & 0xFFFFFF00) | val;
@@ -389,11 +390,15 @@
   friend struct Trix;
   
   friend bool printSUB_GCP_COMPLETE_REP(FILE *, const Uint32 *, Uint32, Uint16);
-  STATIC_CONST( SignalLength = 3 );
-  
-  Uint32 gci;
+  STATIC_CONST( SignalLength = 5 );
+  STATIC_CONST( ON_DISK = 1 );
+  STATIC_CONST( IN_MEMORY = 2 );
+
+  Uint32 gci_hi;
   Uint32 senderRef;
   Uint32 gcp_complete_rep_count;
+  Uint32 gci_lo;
+  Uint32 flags;
 };
 
 struct SubGcpCompleteAck {

--- 1.4/storage/ndb/include/kernel/signaldata/TupCommit.hpp	2007-08-24 16:17:56 +02:00
+++ 1.5/storage/ndb/include/kernel/signaldata/TupCommit.hpp	2007-08-24 16:17:56 +02:00
@@ -35,7 +35,7 @@
   friend bool printTUPCOMMITREQ(FILE * output, const Uint32 * theData, Uint32 len, Uint16 receiverBlockNo);
 
 public:
-  STATIC_CONST( SignalLength = 4 );
+  STATIC_CONST( SignalLength = 5 );
 
 private:
 
@@ -43,9 +43,10 @@
    * DATA VARIABLES
    */
   Uint32 opPtr;
-  Uint32 gci;
+  Uint32 gci_hi;
   Uint32 hashValue;
   Uint32 diskpage;
+  Uint32 gci_lo;
 };
 
 #endif

--- 1.7/storage/ndb/src/common/debugger/signaldata/SumaImpl.cpp	2007-08-24 16:17:56 +02:00
+++ 1.8/storage/ndb/src/common/debugger/signaldata/SumaImpl.cpp	2007-08-24 16:17:56 +02:00
@@ -173,7 +173,8 @@
 		    Uint32 len, Uint16 receiverBlockNo) {
   const SubTableData * const sig = (SubTableData *)theData;
   fprintf(output, " senderData: %x\n", sig->senderData);
-  fprintf(output, " gci: %x\n", sig->gci);
+  fprintf(output, " gci_hi: %x\n", sig->gci_hi);
+  fprintf(output, " gci_lo: %x\n", sig->gci_lo);
   fprintf(output, " tableId: %x\n", sig->tableId);
   fprintf(output, " operation: %x\n", 
 	  SubTableData::getOperation(sig->requestInfo));
@@ -211,7 +212,7 @@
 printSUB_GCP_COMPLETE_REP(FILE * output, const Uint32 * theData, 
 			  Uint32 len, Uint16 receiverBlockNo) {
   const SubGcpCompleteRep * const sig = (SubGcpCompleteRep *)theData;
-  fprintf(output, " gci: %x\n", sig->gci);
+  fprintf(output, " gci_hi: %x gci_lo: %x\n", sig->gci_hi, sig->gci_lo);
   return false;
 }
 

--- 1.49/storage/ndb/src/kernel/blocks/ERROR_codes.txt	2007-08-24 16:17:56 +02:00
+++ 1.50/storage/ndb/src/kernel/blocks/ERROR_codes.txt	2007-08-24 16:17:56 +02:00
@@ -5,7 +5,7 @@
 Next DBTUP 4029
 Next DBLQH 5048
 Next DBDICT 6008
-Next DBDIH 7186
+Next DBDIH 7190
 Next DBTC 8040
 Next CMVMI 9000
 Next BACKUP 10038
@@ -47,6 +47,21 @@
 7004:
 Insert system error in master after completing global checkpoint with
 all nodes in the cluster.
+
+7186:
+Master: Dont send GCP_PREPARE to all node(s)...and die after 1s
+
+7187:
+Master: Dont send GCP_COMMIT to all node(s)...and die after 1s
+
+7188:
+Master: Dont send GCP_SAVE_REQ to all node(s)...and die after 1s
+
+7189:
+Master: Dont send COPY_GCIREQ (GCP) to all node(s)...and die after 1s
+
+7190:
+Master Dont send SUB_GCP_COMPLETE_REP to all node(s) and dies after 1s
 
 7005:
 Insert system error in GCP participant when receiving GCP_PREPARE.

--- 1.43/storage/ndb/src/kernel/blocks/dbdih/Dbdih.hpp	2007-08-24 16:17:56 +02:00
+++ 1.44/storage/ndb/src/kernel/blocks/dbdih/Dbdih.hpp	2007-08-24 16:17:56 +02:00
@@ -102,6 +102,9 @@
 #endif
 
 class Dbdih: public SimulatedBlock {
+#ifdef ERROR_INSERT
+  typedef void (Dbdih::* SendFunction)(Signal*, Uint32);
+#endif
 public:
 
   // Records
@@ -113,7 +116,7 @@
    *  IT IS LINKED INTO A QUEUE IN CASE THE GLOBAL CHECKPOINT IS CURRENTLY 
    * ONGOING */
   struct ApiConnectRecord {
-    Uint32 apiGci;
+    Uint64 apiGci;
     Uint32 nextApi;
   };
   typedef Ptr<ApiConnectRecord> ApiConnectRecordPtr;
@@ -278,18 +281,6 @@
       Uint32 replicaPtr;
     };
     
-    enum GcpState {
-      READY = 0,
-      PREPARE_SENT = 1,
-      PREPARE_RECEIVED = 2,
-      COMMIT_SENT = 3,
-      NODE_FINISHED = 4,
-      SAVE_REQ_SENT = 5,
-      SAVE_RECEIVED = 6,
-      COPY_GCI_SENT = 7
-    };
-
-    GcpState gcpstate;
     Sysfile::ActiveStatus activeStatus;
     
     NodeStatus nodeStatus;
@@ -622,11 +613,13 @@
   void execCREATE_FRAGREQ(Signal *);
   void execCREATE_FRAGCONF(Signal *);
   void execDIVERIFYREQ(Signal *);
+  void execGCP_SAVEREQ(Signal *);
   void execGCP_SAVECONF(Signal *);
   void execGCP_PREPARECONF(Signal *);
   void execGCP_PREPARE(Signal *);
   void execGCP_NODEFINISH(Signal *);
   void execGCP_COMMIT(Signal *);
+  void execSUB_GCP_COMPLETE_REP(Signal *);
   void execDIHNDBTAMPER(Signal *);
   void execCONTINUEB(Signal *);
   void execCOPY_GCIREQ(Signal *);
@@ -853,7 +846,7 @@
   void initRestorableGciFiles();
   void makeNodeGroups(Uint32 nodeArray[]);
   void makePrnList(class ReadNodesConf * readNodes, Uint32 nodeArray[]);
-  void nodeResetStart();
+  void nodeResetStart(Signal* signal);
   void releaseTabPages(Uint32 tableId);
   void replication(Uint32 noOfReplicas,
                    NodeGroupRecordPtr NGPtr,
@@ -975,7 +968,7 @@
   void startNextChkpt(Signal *);
   void failedNodeLcpHandling(Signal*, NodeRecordPtr failedNodePtr);
   void failedNodeSynchHandling(Signal *, NodeRecordPtr failedNodePtr);
-  void checkCopyTab(NodeRecordPtr failedNodePtr);
+  void checkCopyTab(Signal*, NodeRecordPtr failedNodePtr);
 
   void initCommonData();
   void initialiseRecordsLab(Signal *, Uint32 stepNo, Uint32, Uint32);
@@ -1208,36 +1201,82 @@
   /*       ON DISK.                                                         */
   /*------------------------------------------------------------------------*/
   Uint32 crestartInfoFile[2];
-  /*------------------------------------------------------------------------*/
-  /*       THIS VARIABLE KEEPS TRACK OF THE STATUS OF A GLOBAL CHECKPOINT   */
-  /*       PARTICIPANT. THIS IS NEEDED TO HANDLE A NODE FAILURE. WHEN A NODE*/
-  /*       FAILURE OCCURS IT IS EASY THAT THE PROTOCOL STOPS IF NO ACTION IS*/
-  /*       TAKEN TO PREVENT THIS. THIS VARIABLE ENSURES SUCH ACTION CAN BE  */
-  /*       TAKEN.                                                           */
-  /*------------------------------------------------------------------------*/
-  enum GcpParticipantState {
-    GCP_PARTICIPANT_READY = 0,
-    GCP_PARTICIPANT_PREPARE_RECEIVED = 1,
-    GCP_PARTICIPANT_COMMIT_RECEIVED = 2,
-    GCP_PARTICIPANT_TC_FINISHED = 3,
-    GCP_PARTICIPANT_COPY_GCI_RECEIVED = 4
-  };
-  GcpParticipantState cgcpParticipantState;
-  /*------------------------------------------------------------------------*/
-  /*       THESE VARIABLES ARE USED TO CONTROL THAT GCP PROCESSING DO NOT   */
-  /*STOP FOR SOME REASON.                                                   */
-  /*------------------------------------------------------------------------*/
-  enum GcpStatus {
-    GCP_READY = 0,
-    GCP_PREPARE_SENT = 1,
-    GCP_COMMIT_SENT = 2,
-    GCP_NODE_FINISHED = 3,
-    GCP_SAVE_LQH_FINISHED = 4
-  };
-  GcpStatus cgcpStatus;
+
+  /**
+   * GCP Monitor
+   */
+#if 0
   Uint32 cgcpStartCounter; 
   Uint32 coldGcpStatus;
   Uint32 coldGcpId;
+  Uint32 cgcpSameCounter;
+#endif
+
+  bool cstartGcpNow;
+  bool cgckptflag;    /* A FLAG WHICH IS SET WHILE A NEW GLOBAL CHECK
+                           POINT IS BEING CREATED. NO VERIFICATION IS ALLOWED
+                           IF THE FLAG IS SET*/
+  Uint32 cgcpOrderBlocked;
+
+  /**
+   * This structure describes
+   *   the GCP Save protocol
+   */
+  struct GcpSave
+  {
+    bool m_master_take_over;
+    Uint32 m_time_between_gcp;   /* Delay between global checkpoints */
+    Uint32 m_gci;
+    Uint32 m_master_ref;
+    Uint64 m_start_time;
+    enum State {
+      GCP_SAVE_IDLE     = 0, // Idle
+      GCP_SAVE_REQ      = 1, // REQ received
+      GCP_SAVE_CONF     = 3, // REF/CONF sent
+      GCP_SAVE_COPY_GCI = 4
+    } m_state, m_master_state;
+  } m_gcp_save;
+
+  /**
+   * This structure describes the MicroGCP protocol
+   */
+  struct MicroGcp
+  {
+    bool m_enabled;
+    bool m_master_take_over;
+    Uint32 m_time_between_gcp;
+    Uint32 m_master_ref;
+    Uint64 m_old_gci;
+    Uint64 m_current_gci; // Currently active
+    Uint64 m_new_gci;     // Currently being prepared...
+    Uint64 m_next_gci;    // Next to prepare
+    Uint64 m_start_time;
+    enum State {
+      M_GCP_IDLE      = 0,
+      M_GCP_PREPARE   = 1,
+      M_GCP_COMMIT    = 2,
+      M_GCP_COMMITTED = 3,
+      M_GCP_SAVE      = 4 /** Only used when running with old node(s) */
+    } m_state, m_master_state;
+  } m_micro_gcp;
+
+  struct GcpMonitor
+  {
+    struct
+    {
+      Uint32 m_gci;
+      GcpSave::State m_state;
+      Uint32 m_counter;
+    } m_old_gcp_save;
+
+    struct
+    {
+      Uint64 m_gci;
+      MicroGcp::State m_state;
+      Uint32 m_counter;
+    } m_old_micro_gcp;
+  } m_gcp_monitor;
+
   /*------------------------------------------------------------------------*/
   /*       THIS VARIABLE KEEPS TRACK OF THE STATE OF THIS NODE AS MASTER.   */
   /*------------------------------------------------------------------------*/
@@ -1363,32 +1402,24 @@
   /*       WHEN NO TABLES ARE ACTIVATED.                                    */
   /*------------------------------------------------------------------------*/
   Uint32 cnoOfActiveTables;
-  Uint32 cgcpDelay;                       /* Delay between global checkpoints */
 
   BlockReference cdictblockref;          /* DICTIONARY BLOCK REFERENCE */
   Uint32 cfailurenr;              /* EVERY TIME WHEN A NODE FAILURE IS REPORTED
                                     THIS NUMBER IS INCREMENTED. AT THE START OF
                                     THE SYSTEM THIS NUMBER MUST BE INITIATED TO
                                     ZERO */
-  bool cgckptflag;    /* A FLAG WHICH IS SET WHILE A NEW GLOBAL CHECK
-                           POINT IS BEING CREATED. NO VERIFICATION IS ALLOWED 
-                           IF THE FLAG IS SET*/
-  Uint32 cgcpOrderBlocked;
+
   BlockReference clocallqhblockref;
   BlockReference clocaltcblockref;
   BlockReference cmasterdihref;
   Uint16 cownNodeId;
-  Uint32 cnewgcp;
   BlockReference cndbStartReqBlockref;
   BlockReference cntrlblockref;
-  Uint32 cgcpSameCounter;
-  Uint32 coldgcp;
   Uint32 con_lineNodes;
   Uint32 creceivedfrag;
   Uint32 cremainingfrags;
   Uint32 cstarttype;
   Uint32 csystemnodes;
-  Uint32 currentgcp;
   Uint32 c_newest_restorable_gci;
   Uint32 c_set_initial_start_flag;
 
@@ -1465,8 +1496,6 @@
   
   bool cwaitLcpSr;
   Uint32 cnoOfNodeGroups;
-  bool cstartGcpNow;
-
   Uint32 crestartGci;      /* VALUE OF GCI WHEN SYSTEM RESTARTED OR STARTED */
   Uint32 cminHotSpareNodes;
   
@@ -1656,6 +1685,13 @@
   void recvDictLockConf_nodeRestart(Signal* signal, Uint32 data, Uint32 ret);
 
   Uint32 c_error_7181_ref;
+
+#ifdef ERROR_INSERT
+  void sendToRandomNodes(const char*, Signal*, SignalCounter*,
+                         SendFunction,
+                         Uint32 block = 0, Uint32 gsn = 0, Uint32 len = 0,
+                         JobBufferLevel = JBB);
+#endif
 };
 
 #if (DIH_CDATA_SIZE < _SYSFILE_SIZE32)

--- 1.24/storage/ndb/src/kernel/blocks/dbdih/DbdihInit.cpp	2007-08-24 16:17:56 +02:00
+++ 1.25/storage/ndb/src/kernel/blocks/dbdih/DbdihInit.cpp	2007-08-24 16:17:56 +02:00
@@ -151,11 +151,14 @@
   addRecSignal(GSN_CREATE_FRAGREQ, &Dbdih::execCREATE_FRAGREQ);
   addRecSignal(GSN_CREATE_FRAGCONF, &Dbdih::execCREATE_FRAGCONF);
   addRecSignal(GSN_DIVERIFYREQ, &Dbdih::execDIVERIFYREQ);
+  addRecSignal(GSN_GCP_SAVEREQ, &Dbdih::execGCP_SAVEREQ);
+  addRecSignal(GSN_GCP_SAVEREF, &Dbdih::execGCP_SAVEREF);
   addRecSignal(GSN_GCP_SAVECONF, &Dbdih::execGCP_SAVECONF);
   addRecSignal(GSN_GCP_PREPARECONF, &Dbdih::execGCP_PREPARECONF);
   addRecSignal(GSN_GCP_PREPARE, &Dbdih::execGCP_PREPARE);
   addRecSignal(GSN_GCP_NODEFINISH, &Dbdih::execGCP_NODEFINISH);
   addRecSignal(GSN_GCP_COMMIT, &Dbdih::execGCP_COMMIT);
+  addRecSignal(GSN_SUB_GCP_COMPLETE_REP, &Dbdih::execSUB_GCP_COMPLETE_REP);
   addRecSignal(GSN_DIHNDBTAMPER, &Dbdih::execDIHNDBTAMPER);
   addRecSignal(GSN_CONTINUEB, &Dbdih::execCONTINUEB);
   addRecSignal(GSN_COPY_GCIREQ, &Dbdih::execCOPY_GCIREQ);
@@ -184,7 +187,6 @@
   addRecSignal(GSN_STTOR, &Dbdih::execSTTOR);
   addRecSignal(GSN_DI_FCOUNTREQ, &Dbdih::execDI_FCOUNTREQ);
   addRecSignal(GSN_DIGETPRIMREQ, &Dbdih::execDIGETPRIMREQ);
-  addRecSignal(GSN_GCP_SAVEREF, &Dbdih::execGCP_SAVEREF);
   addRecSignal(GSN_GCP_TCFINISHED, &Dbdih::execGCP_TCFINISHED);
   addRecSignal(GSN_READ_NODESCONF, &Dbdih::execREAD_NODESCONF);
   addRecSignal(GSN_NDB_STTOR, &Dbdih::execNDB_STTOR);

--- 1.137/storage/ndb/src/kernel/blocks/dbdih/DbdihMain.cpp	2007-08-24 16:17:56 +02:00
+++ 1.138/storage/ndb/src/kernel/blocks/dbdih/DbdihMain.cpp	2007-08-24 16:17:57 +02:00
@@ -187,7 +187,8 @@
   BlockReference ref = calcDihBlockRef(nodeId);
   GCPCommit *req = (GCPCommit*)signal->getDataPtrSend();
   req->nodeId = cownNodeId;
-  req->gci = cnewgcp;
+  req->gci_hi = Uint32(m_micro_gcp.m_new_gci >> 32);
+  req->gci_lo = Uint32(m_micro_gcp.m_new_gci);
   sendSignal(ref, GSN_GCP_COMMIT, signal, GCPCommit::SignalLength, JBA);
 }//Dbdih::sendGCP_COMMIT()
 
@@ -196,17 +197,18 @@
   BlockReference ref = calcDihBlockRef(nodeId);
   GCPPrepare *req = (GCPPrepare*)signal->getDataPtrSend();
   req->nodeId = cownNodeId;
-  req->gci = cnewgcp;
+  req->gci_hi = Uint32(m_micro_gcp.m_new_gci >> 32);
+  req->gci_lo = Uint32(m_micro_gcp.m_new_gci);
   sendSignal(ref, GSN_GCP_PREPARE, signal, GCPPrepare::SignalLength, JBA);
 }//Dbdih::sendGCP_PREPARE()
 
 void Dbdih::sendGCP_SAVEREQ(Signal* signal, Uint32 nodeId)
 {
   GCPSaveReq * const saveReq = (GCPSaveReq*)&signal->theData[0];
-  BlockReference ref = calcLqhBlockRef(nodeId);
+  BlockReference ref = calcDihBlockRef(nodeId);
   saveReq->dihBlockRef = reference();
   saveReq->dihPtr = nodeId;
-  saveReq->gci = coldgcp;
+  saveReq->gci = m_gcp_save.m_gci;
   sendSignal(ref, GSN_GCP_SAVEREQ, signal, GCPSaveReq::SignalLength, JBB);
 }//Dbdih::sendGCP_SAVEREQ()
 
@@ -217,8 +219,9 @@
   signal->theData[1] = c_nodeStartMaster.startNode;
   signal->theData[2] = c_nodeStartMaster.failNr;
   signal->theData[3] = 0;
-  signal->theData[4] = currentgcp;  
-  sendSignal(nodeDihRef, GSN_INCL_NODEREQ, signal, 5, JBA);
+  signal->theData[4] = m_micro_gcp.m_current_gci >> 32;
+  signal->theData[5] = m_micro_gcp.m_current_gci & 0xFFFFFFFF;
+  sendSignal(nodeDihRef, GSN_INCL_NODEREQ, signal, 6, JBA);
 }//Dbdih::sendINCL_NODEREQ()
 
 void Dbdih::sendMASTER_GCPREQ(Signal* signal, Uint32 nodeId)
@@ -477,6 +480,16 @@
     jam();
     CopyGCIReq::CopyReason reason = (CopyGCIReq::CopyReason)signal->theData[1];
     ndbrequire(c_copyGCIMaster.m_copyReason == reason);
+
+    if (reason == CopyGCIReq::GLOBAL_CHECKPOINT && ERROR_INSERTED(7189))
+    {
+      sendToRandomNodes("COPY_GCI", signal, &c_COPY_GCIREQ_Counter,
+                        &Dbdih::sendCOPY_GCIREQ);
+      signal->theData[0] = 9999;
+      sendSignalWithDelay(CMVMI_REF, GSN_NDB_TAMPER, signal, 1000, 1);
+      return;
+    }
+
     sendLoopMacro(COPY_GCIREQ, sendCOPY_GCIREQ);
     return;
   }
@@ -634,7 +647,9 @@
   const Uint32 tstart = copyGCI->startWord;
   
   ndbrequire(cmasterdihref == signal->senderBlockRef()) ;
-  ndbrequire(c_copyGCISlave.m_copyReason  == CopyGCIReq::IDLE);
+  ndbrequire((reason == CopyGCIReq::GLOBAL_CHECKPOINT &&
+              c_copyGCISlave.m_copyReason == CopyGCIReq::GLOBAL_CHECKPOINT) ||
+             c_copyGCISlave.m_copyReason == CopyGCIReq::IDLE);
   ndbrequire(c_copyGCISlave.m_expectedNextWord == tstart);
   ndbrequire(reason != CopyGCIReq::IDLE);
   bool isdone = (tstart + CopyGCIReq::DATA_SIZE) >= Sysfile::SYSFILE_SIZE32;
@@ -717,12 +732,14 @@
   case CopyGCIReq::RESTART: {
     ok = true;
     jam();
-    coldgcp = SYSFILE->newestRestorableGCI;
-    crestartGci = SYSFILE->newestRestorableGCI;
-    c_newest_restorable_gci = SYSFILE->newestRestorableGCI;
+    Uint32 newest = SYSFILE->newestRestorableGCI;
+    m_micro_gcp.m_old_gci = Uint64(newest) << 32;
+    crestartGci = newest;
+    c_newest_restorable_gci = newest;
     Sysfile::setRestartOngoing(SYSFILE->systemRestartBits);
-    currentgcp = coldgcp + 1;
-    cnewgcp = coldgcp + 1;
+    m_micro_gcp.m_current_gci = Uint64(newest + 1) << 32;
+    m_micro_gcp.m_new_gci = Uint64(newest + 1) << 32;
+    m_micro_gcp.m_next_gci = (Uint64(newest + 1) << 32) + 1;
     setNodeInfo(signal);
     if ((Sysfile::getLCPOngoing(SYSFILE->systemRestartBits))) {
       jam();
@@ -737,7 +754,35 @@
   case CopyGCIReq::GLOBAL_CHECKPOINT: {
     ok = true;
     jam();
-    cgcpParticipantState = GCP_PARTICIPANT_COPY_GCI_RECEIVED;
+
+    if (m_gcp_save.m_state == GcpSave::GCP_SAVE_COPY_GCI)
+    {
+      jam();
+      /**
+       * This must be master take over...and it already running...
+       */
+      ndbrequire(m_gcp_save.m_master_ref != c_copyGCISlave.m_senderRef);
+      m_gcp_save.m_master_ref = c_copyGCISlave.m_senderRef;
+      return;
+    }
+
+    if (m_gcp_save.m_state == GcpSave::GCP_SAVE_IDLE)
+    {
+      jam();
+      /**
+       * This must be master take over...and it already complete...
+       */
+      ndbrequire(m_gcp_save.m_master_ref != c_copyGCISlave.m_senderRef);
+      m_gcp_save.m_master_ref = c_copyGCISlave.m_senderRef;
+      c_copyGCISlave.m_copyReason = CopyGCIReq::IDLE;
+      signal->theData[0] = c_copyGCISlave.m_senderData;
+      sendSignal(m_gcp_save.m_master_ref, GSN_COPY_GCICONF, signal, 1, JBB);
+      return;
+    }
+
+    ndbrequire(m_gcp_save.m_state == GcpSave::GCP_SAVE_CONF);
+    m_gcp_save.m_state = GcpSave::GCP_SAVE_COPY_GCI;
+    m_gcp_save.m_master_ref = c_copyGCISlave.m_senderRef;
     c_newest_restorable_gci = SYSFILE->newestRestorableGCI;
     setNodeInfo(signal);
     break;
@@ -2004,7 +2049,7 @@
     ref->errorCode = c_nodeStartMaster.startInfoErrorCode;
     sendSignal(calcDihBlockRef(c_nodeStartMaster.startNode), 
 	       GSN_START_PERMREF, signal, StartPermRef::SignalLength, JBB);
-    nodeResetStart();
+    nodeResetStart(signal);
   }//if
 }//Dbdih::startInfoReply()
 
@@ -2056,6 +2101,12 @@
 
 void Dbdih::nodeDictStartConfLab(Signal* signal) 
 {
+  /*-----------------------------------------------------------------*/
+  // Report that node restart has completed copy of dictionary.
+  /*-----------------------------------------------------------------*/
+  signal->theData[0] = NDB_LE_NR_CopyDict;
+  sendSignal(CMVMI_REF, GSN_EVENT_REP, signal, 1, JBB);
+
   /*-------------------------------------------------------------------------*/
   // NOW WE HAVE COPIED BOTH DIH AND DICT INFORMATION. WE ARE NOW READY TO
   // INTEGRATE THE NODE INTO THE LCP AND GCP PROTOCOLS AND TO ALLOW UPDATES OF
@@ -2063,28 +2114,15 @@
   /*-------------------------------------------------------------------------*/
   c_nodeStartMaster.wait = ZFALSE;
   c_nodeStartMaster.blockGcp = true;
-  if (cgcpStatus != GCP_READY) {
-    /*-----------------------------------------------------------------------*/
-    // The global checkpoint is executing. Wait until it is completed before we
-    // continue processing the node recovery.
-    /*-----------------------------------------------------------------------*/
-    jam();
-    return;
-  }//if
-  gcpBlockedLab(signal);
 
-  /*-----------------------------------------------------------------*/
-  // Report that node restart has completed copy of dictionary.
-  /*-----------------------------------------------------------------*/
-  signal->theData[0] = NDB_LE_NR_CopyDict;
-  sendSignal(CMVMI_REF, GSN_EVENT_REP, signal, 1, JBB);
+  return;
 }//Dbdih::nodeDictStartConfLab()
 
 void Dbdih::dihCopyCompletedLab(Signal* signal)
 {
   BlockReference ref = calcDictBlockRef(c_nodeStartMaster.startNode);
   DictStartReq * req = (DictStartReq*)&signal->theData[0];
-  req->restartGci = cnewgcp;
+  req->restartGci = m_micro_gcp.m_new_gci >> 32;
   req->senderRef = reference();
   sendSignal(ref, GSN_DICTSTARTREQ,
              signal, DictStartReq::SignalLength, JBB);
@@ -2094,12 +2132,6 @@
 
 void Dbdih::gcpBlockedLab(Signal* signal)
 {
-  /*-----------------------------------------------------------------*/
-  // Report that node restart has completed copy of distribution info.
-  /*-----------------------------------------------------------------*/
-  signal->theData[0] = NDB_LE_NR_CopyDistr;
-  sendSignal(CMVMI_REF, GSN_EVENT_REP, signal, 1, JBB);
-
   /**
    * The node DIH will be part of LCP
    */
@@ -2196,6 +2228,12 @@
   c_nodeStartMaster.wait = 11;
   c_nodeStartMaster.blockGcp = false;
 
+  /**
+   * Restart GCP
+   */
+  signal->theData[0] = DihContinueB::ZSTART_GCP;
+  sendSignal(reference(), GSN_CONTINUEB, signal, 1, JBB);
+
   signal->theData[0] = reference();
   sendSignal(reference(), GSN_UNBLO_DICTCONF, signal, 1, JBB);
 }//Dbdih::execINCL_NODECONF()
@@ -2335,10 +2373,12 @@
   }
   
   Uint32 tnodeStartFailNr = signal->theData[2];
-  currentgcp = signal->theData[4];
+  Uint32 gci_hi = signal->theData[4];
+  Uint32 gci_lo = signal->theData[5];
+  Uint64 gci = gci_lo | (Uint64(gci_hi) << 32);
   CRASH_INSERTION(7127);
-  cnewgcp = currentgcp;
-  coldgcp = currentgcp -  1;
+  m_micro_gcp.m_current_gci = gci;
+  m_micro_gcp.m_old_gci = gci - 1;
   if (!isMaster()) {
     jam();
     /*-----------------------------------------------------------------------*/
@@ -2408,7 +2448,7 @@
   /*-------------------------------------------------------------------------*/
   signal->theData[0] = reference();
   signal->theData[1] = nodeId;
-  signal->theData[2] = currentgcp;
+  signal->theData[2] = m_micro_gcp.m_current_gci >> 32;
   sendSignal(clocallqhblockref, GSN_INCL_NODEREQ, signal, 3, JBB);
 }//Dbdih::execINCL_NODEREQ()
 
@@ -2597,7 +2637,7 @@
     ndbrequire(false);
     break;
   }//switch
-  nodeResetStart();
+  nodeResetStart(signal);
 }//Dbdih::nodeRestartTakeOver()
 
 /*************************************************************************/
@@ -4302,7 +4342,7 @@
     sysErr->data1= 0;
     sysErr->data2= __LINE__;
     sendSignal(cntrRef, GSN_SYSTEM_ERROR, signal,  SystemError::SignalLength, JBA);
-    nodeResetStart();  
+    nodeResetStart(signal);
   }//if
 #endif
 
@@ -4327,7 +4367,7 @@
       /*-------------------------------------------------------*/
       // Functions that need to be called only for master nodes.
       /*-------------------------------------------------------*/
-      checkCopyTab(failedNodePtr);
+      checkCopyTab(signal, failedNodePtr);
       checkStopPermMaster(signal, failedNodePtr);
       checkWaitGCPMaster(signal, failedNodes[i]);
       checkTakeOverInMasterAllNodeFailure(signal, failedNodePtr);
@@ -4387,7 +4427,7 @@
   }//if
 }//Dbdih::execNODE_FAILREP()
 
-void Dbdih::checkCopyTab(NodeRecordPtr failedNodePtr)
+void Dbdih::checkCopyTab(Signal* signal, NodeRecordPtr failedNodePtr)
 {
   jam();
 
@@ -4417,7 +4457,7 @@
     ndbrequire(false);
   }
   
-  nodeResetStart();  
+  nodeResetStart(signal);
 }//Dbdih::checkCopyTab()
 
 void Dbdih::checkStopMe(Signal* signal, NodeRecordPtr failedNodePtr)
@@ -4978,7 +5018,8 @@
     jam();
     GCPPrepareConf* conf = (GCPPrepareConf*)signal->getDataPtrSend();
     conf->nodeId = failedNodeId;
-    conf->gci = cnewgcp;
+    conf->gci_hi = Uint32(m_micro_gcp.m_new_gci >> 32);
+    conf->gci_lo = Uint32(m_micro_gcp.m_new_gci);
     sendSignal(reference(), GSN_GCP_PREPARECONF, signal, 
                GCPPrepareConf::SignalLength, JBB);
   }//if
@@ -4987,7 +5028,8 @@
     jam();
     GCPNodeFinished* conf = (GCPNodeFinished*)signal->getDataPtrSend();
     conf->nodeId = failedNodeId;
-    conf->gci = coldgcp;
+    conf->gci_hi = Uint32(m_micro_gcp.m_old_gci >> 32);
+    conf->gci_lo = Uint32(m_micro_gcp.m_old_gci);
     conf->failno = cfailurenr;
     sendSignal(reference(), GSN_GCP_NODEFINISH, signal, 
                GCPNodeFinished::SignalLength, JBB);
@@ -4998,7 +5040,7 @@
     GCPSaveRef * const saveRef = (GCPSaveRef*)&signal->theData[0];
     saveRef->dihPtr = failedNodeId;
     saveRef->nodeId = failedNodeId;
-    saveRef->gci    = coldgcp;
+    saveRef->gci    = m_gcp_save.m_gci;
     saveRef->errorCode = GCPSaveRef::FakedSignalDueToNodeFailure;
     sendSignal(reference(), GSN_GCP_SAVEREF, signal, 
 	       GCPSaveRef::SignalLength, JBB);
@@ -5086,7 +5128,7 @@
   req->failedNodeId = oldMasterId;
   sendLoopMacro(MASTER_GCPREQ, sendMASTER_GCPREQ);
   cgcpMasterTakeOverState = GMTOS_INITIAL;
-  
+
   signal->theData[0] = NDB_LE_GCP_TakeoverStarted;
   sendSignal(CMVMI_REF, GSN_EVENT_REP, signal, 1, JBB);
 
@@ -5180,22 +5222,7 @@
   jamEntry();
   const BlockReference newMasterBlockref = masterGCPReq->masterRef;
   const Uint32 failedNodeId = masterGCPReq->failedNodeId;
-  if (c_copyGCISlave.m_copyReason != CopyGCIReq::IDLE) {
-    jam();
-    /*--------------------------------------------------*/
-    /*       WE ARE CURRENTLY WRITING THE RESTART INFO  */
-    /*       IN THIS NODE. SINCE ONLY ONE PROCESS IS    */
-    /*       ALLOWED TO DO THIS AT A TIME WE MUST ENSURE*/
-    /*       THAT THIS IS NOT ONGOING WHEN THE NEW      */
-    /*       MASTER TAKES OVER CONTROL. IF NOT ALL NODES*/
-    /*       RECEIVE THE SAME RESTART INFO DUE TO THE   */
-    /*       FAILURE OF THE MASTER IT IS TAKEN CARE OF  */
-    /*       BY THE NEW MASTER.                         */
-    /*--------------------------------------------------*/
-    sendSignalWithDelay(reference(), GSN_MASTER_GCPREQ,
-                        signal, 10, MasterGCPReq::SignalLength);
-    return;
-  }//if
+
   failedNodePtr.i = failedNodeId;
   ptrCheckGuard(failedNodePtr, MAX_NDB_NODES, nodeRecord);
   if (failedNodePtr.p->nodeStatus == NodeRecord::ALIVE) {
@@ -5219,74 +5246,70 @@
     ndbout_c("execGCP_TCFINISHED in MASTER_GCPREQ");
     CLEAR_ERROR_INSERT_VALUE;
     signal->theData[0] = c_error_7181_ref;
-    signal->theData[1] = coldgcp;
+    signal->theData[1] = m_micro_gcp.m_old_gci >> 32;
+    signal->theData[2] = m_micro_gcp.m_old_gci & 0xFFFFFFFF;
     execGCP_TCFINISHED(signal);
   }
-  
+
   MasterGCPConf::State gcpState;
-  switch (cgcpParticipantState) {
-  case GCP_PARTICIPANT_READY:
+  switch(m_micro_gcp.m_state){
+  case MicroGcp::M_GCP_IDLE:
     jam();
-    /*--------------------------------------------------*/
-    /*       THE GLOBAL CHECKPOINT IS NOT ACTIVE SINCE  */
-    /*       THE PREVIOUS GLOBAL CHECKPOINT IS COMPLETED*/
-    /*       AND THE NEW HAVE NOT STARTED YET.          */
-    /*--------------------------------------------------*/
     gcpState = MasterGCPConf::GCP_READY;
     break;
-  case GCP_PARTICIPANT_PREPARE_RECEIVED:
+  case MicroGcp::M_GCP_PREPARE:
     jam();
-    /*--------------------------------------------------*/
-    /*       GCP_PREPARE HAVE BEEN RECEIVED AND RESPONSE*/
-    /*       HAVE BEEN SENT.                            */
-    /*--------------------------------------------------*/
     gcpState = MasterGCPConf::GCP_PREPARE_RECEIVED;
     break;
-  case GCP_PARTICIPANT_COMMIT_RECEIVED:
+  case MicroGcp::M_GCP_COMMIT:
     jam();
-    /*------------------------------------------------*/
-    /*       GCP_COMMIT HAVE BEEN RECEIVED BUT NOT YET*/
-    /*       GCP_TCFINISHED FROM LOCAL TC.            */
-    /*------------------------------------------------*/
     gcpState = MasterGCPConf::GCP_COMMIT_RECEIVED;
     break;
-  case GCP_PARTICIPANT_TC_FINISHED:
+  case MicroGcp::M_GCP_COMMITTED:
     jam();
-    /*------------------------------------------------*/
-    /*       GCP_COMMIT HAS BEEN RECEIVED AND ALSO    */
-    /*       GCP_TCFINISHED HAVE BEEN RECEIVED.       */
-    /*------------------------------------------------*/
-    gcpState = MasterGCPConf::GCP_TC_FINISHED;
+    gcpState = MasterGCPConf::GCP_COMMITTED;
     break;
-  case GCP_PARTICIPANT_COPY_GCI_RECEIVED:
-    /*--------------------------------------------------*/
-    /*       COPY RESTART INFORMATION HAS BEEN RECEIVED */
-    /*       BUT NOT YET COMPLETED.                     */
-    /*--------------------------------------------------*/
+  case MicroGcp::M_GCP_SAVE:
+    /**
+     * Only when running old protocol, only at master...
+     */
+    jam();
     ndbrequire(false);
-    gcpState= MasterGCPConf::GCP_READY; // remove warning
+  };
+
+  MasterGCPConf::SaveState saveState;
+  switch(m_gcp_save.m_state){
+  case GcpSave::GCP_SAVE_IDLE:
+    jam();
+    saveState = MasterGCPConf::GCP_SAVE_IDLE;
     break;
-  default:
-    /*------------------------------------------------*/
-    /*                                                */
-    /*       THIS SHOULD NOT OCCUR SINCE THE ABOVE    */
-    /*       STATES ARE THE ONLY POSSIBLE STATES AT A */
-    /*       NODE WHICH WAS NOT A MASTER NODE.        */
-    /*------------------------------------------------*/
-    ndbrequire(false);
-    gcpState= MasterGCPConf::GCP_READY; // remove warning
+  case GcpSave::GCP_SAVE_REQ:
+    jam();
+    saveState = MasterGCPConf::GCP_SAVE_REQ;
     break;
-  }//switch
+  case GcpSave::GCP_SAVE_CONF:
+    jam();
+    saveState = MasterGCPConf::GCP_SAVE_CONF;
+    break;
+  case GcpSave::GCP_SAVE_COPY_GCI:
+    saveState = MasterGCPConf::GCP_SAVE_COPY_GCI;
+    break;
+  }
+
   MasterGCPConf * const masterGCPConf = (MasterGCPConf *)&signal->theData[0];  
   masterGCPConf->gcpState  = gcpState;
   masterGCPConf->senderNodeId = cownNodeId;
   masterGCPConf->failedNodeId = failedNodeId;
-  masterGCPConf->newGCP = cnewgcp;
+  masterGCPConf->newGCP_hi = m_micro_gcp.m_new_gci >> 32;
   masterGCPConf->latestLCP = SYSFILE->latestLCP_ID;
   masterGCPConf->oldestRestorableGCI = SYSFILE->oldestRestorableGCI;
   masterGCPConf->keepGCI = SYSFILE->keepGCI;  
+  masterGCPConf->newGCP_lo = Uint32(m_micro_gcp.m_new_gci);
+  masterGCPConf->saveState = saveState;
+  masterGCPConf->saveGCI = m_gcp_save.m_gci;
   for(Uint32 i = 0; i < NdbNodeBitmask::Size; i++)
     masterGCPConf->lcpActive[i] = SYSFILE->lcpActive[i];
+
   sendSignal(newMasterBlockref, GSN_MASTER_GCPCONF, signal, 
              MasterGCPConf::SignalLength, JBB);
 
@@ -5295,9 +5318,12 @@
     ndbout_c("execGCP_TCFINISHED in MASTER_GCPREQ");
     CLEAR_ERROR_INSERT_VALUE;
     signal->theData[0] = c_error_7181_ref;
-    signal->theData[1] = coldgcp;
+    signal->theData[1] = m_micro_gcp.m_old_gci >> 32;
+    signal->theData[2] = m_micro_gcp.m_old_gci & 0xFFFFFFFF;
     execGCP_TCFINISHED(signal);
   }
+
+  c_copyGCISlave.m_copyReason = CopyGCIReq::IDLE;
 }//Dbdih::execMASTER_GCPREQ()
 
 void Dbdih::execMASTER_GCPCONF(Signal* signal) 
@@ -5309,11 +5335,17 @@
   ptrCheckGuard(senderNodePtr, MAX_NDB_NODES, nodeRecord);
   
   MasterGCPConf::State gcpState = (MasterGCPConf::State)masterGCPConf->gcpState;
+  MasterGCPConf::SaveState saveState =
+    (MasterGCPConf::SaveState)masterGCPConf->saveState;
   const Uint32 failedNodeId = masterGCPConf->failedNodeId;
-  const Uint32 newGcp = masterGCPConf->newGCP;
+  const Uint32 newGcp_hi = masterGCPConf->newGCP_hi;
+  const Uint32 newGcp_lo = masterGCPConf->newGCP_lo;
+  Uint64 newGCI = newGcp_lo | (Uint64(newGcp_hi) << 32);
   const Uint32 latestLcpId = masterGCPConf->latestLCP;
   const Uint32 oldestRestorableGci = masterGCPConf->oldestRestorableGCI;
   const Uint32 oldestKeepGci = masterGCPConf->keepGCI;
+  const Uint32 saveGCI = masterGCPConf->saveGCI;
+
   if (latestLcpId > SYSFILE->latestLCP_ID) {
     jam();
 #if 0
@@ -5326,184 +5358,105 @@
     for(Uint32 i = 0; i < NdbNodeBitmask::Size; i++)
       SYSFILE->lcpActive[i] = masterGCPConf->lcpActive[i];
   }//if
+
+  bool ok = false;
   switch (gcpState) {
   case MasterGCPConf::GCP_READY:
     jam();
-    senderNodePtr.p->gcpstate = NodeRecord::READY;
+    ok = true;
+    // Either not started or complete...
     break;
   case MasterGCPConf::GCP_PREPARE_RECEIVED:
     jam();
-    senderNodePtr.p->gcpstate = NodeRecord::PREPARE_RECEIVED;
-    cnewgcp = newGcp;
+    ok = true;
+    if (m_micro_gcp.m_master_state == MicroGcp::M_GCP_IDLE)
+    {
+      jam();
+      m_micro_gcp.m_master_state = MicroGcp::M_GCP_PREPARE;
+      m_micro_gcp.m_new_gci = newGCI;
+    }
+    else
+    {
+      jam();
+      ndbrequire(m_micro_gcp.m_new_gci == newGCI);
+    }
     break;
   case MasterGCPConf::GCP_COMMIT_RECEIVED:
     jam();
-    senderNodePtr.p->gcpstate = NodeRecord::COMMIT_SENT;
-    break;
-  case MasterGCPConf::GCP_TC_FINISHED:
+  case MasterGCPConf::GCP_COMMITTED:
     jam();
-    senderNodePtr.p->gcpstate = NodeRecord::NODE_FINISHED;
+    ok = true;
+    ndbrequire(m_micro_gcp.m_new_gci == newGCI);
+    m_micro_gcp.m_master_state = MicroGcp::M_GCP_COMMIT;
     break;
+#ifndef VM_TRACE
   default:
+    jamLine(gcpState);
     ndbrequire(false);
+#endif
+  }
+  ndbassert(ok); // Unhandled case...
+
+  ok = false;
+  switch(saveState){
+  case MasterGCPConf::GCP_SAVE_IDLE:
+    jam();
+    ok = true;
     break;
-  }//switch
-  switch (cgcpMasterTakeOverState) {
-  case GMTOS_INITIAL:
-    switch (gcpState) {
-    case MasterGCPConf::GCP_READY:
-      jam();
-      cgcpMasterTakeOverState = ALL_READY;
-      break;
-    case MasterGCPConf::GCP_PREPARE_RECEIVED:
-      jam();
-      cgcpMasterTakeOverState = ALL_PREPARED;
-      break;
-    case MasterGCPConf::GCP_COMMIT_RECEIVED:
-      jam();
-      cgcpMasterTakeOverState = COMMIT_STARTED_NOT_COMPLETED;
-      break;
-    case MasterGCPConf::GCP_TC_FINISHED:
-      jam();
-      cgcpMasterTakeOverState = COMMIT_COMPLETED;
-      break;
-    default:
-      ndbrequire(false);
-      break;
-    }//switch
-    break;
-  case ALL_READY:
-    switch (gcpState) {
-    case MasterGCPConf::GCP_READY:
-      jam();
-      /*empty*/;
-      break;
-    case MasterGCPConf::GCP_PREPARE_RECEIVED:
-      jam();
-      cgcpMasterTakeOverState = PREPARE_STARTED_NOT_COMMITTED;
-      break;
-    case MasterGCPConf::GCP_COMMIT_RECEIVED:
-      ndbrequire(false);
-      break;
-    case MasterGCPConf::GCP_TC_FINISHED:
-      jam();
-      cgcpMasterTakeOverState = SAVE_STARTED_NOT_COMPLETED;
-      break;
-    default:
-      ndbrequire(false);
-      break;
-    }//switch
-    break;
-  case PREPARE_STARTED_NOT_COMMITTED:
-    switch (gcpState) {
-    case MasterGCPConf::GCP_READY:
-      jam();
-      break;
-    case MasterGCPConf::GCP_PREPARE_RECEIVED:
-      jam();
-      break;
-    case MasterGCPConf::GCP_COMMIT_RECEIVED:
-      ndbrequire(false);
-      break;
-    case MasterGCPConf::GCP_TC_FINISHED:
-      ndbrequire(false);
-      break;
-    default:
-      ndbrequire(false);
-      break;
-    }//switch
-    break;
-  case ALL_PREPARED:
-    switch (gcpState) {
-    case MasterGCPConf::GCP_READY:
-      jam();
-      cgcpMasterTakeOverState = PREPARE_STARTED_NOT_COMMITTED;
-      break;
-    case MasterGCPConf::GCP_PREPARE_RECEIVED:
-      jam();
-      break;
-    case MasterGCPConf::GCP_COMMIT_RECEIVED:
-      jam();
-      cgcpMasterTakeOverState = COMMIT_STARTED_NOT_COMPLETED;
-      break;
-    case MasterGCPConf::GCP_TC_FINISHED:
-      jam();
-      cgcpMasterTakeOverState = COMMIT_STARTED_NOT_COMPLETED;
-      break;
-    default:
-      ndbrequire(false);
-      break;
-    }//switch
-    break;
-  case COMMIT_STARTED_NOT_COMPLETED:
-    switch (gcpState) {
-    case MasterGCPConf::GCP_READY:
-      ndbrequire(false);
-      break;
-    case MasterGCPConf::GCP_PREPARE_RECEIVED:
-      jam();
-      break;
-    case MasterGCPConf::GCP_COMMIT_RECEIVED:
-      jam();
-      break;
-    case MasterGCPConf::GCP_TC_FINISHED:
-      jam();
-      break;
-    default:
-      ndbrequire(false);
-      break;
-    }//switch
+  case MasterGCPConf::GCP_SAVE_REQ:
+    jam();
+    ok = true;
+    if (m_gcp_save.m_master_state == GcpSave::GCP_SAVE_IDLE)
+    {
+      m_gcp_save.m_gci = saveGCI;
+      m_gcp_save.m_master_state = GcpSave::GCP_SAVE_REQ;
+    }
+    else
+    {
+      ndbrequire(m_gcp_save.m_gci == saveGCI);
+    }
     break;
-  case COMMIT_COMPLETED:
-    switch (gcpState) {
-    case MasterGCPConf::GCP_READY:
-      cgcpMasterTakeOverState = SAVE_STARTED_NOT_COMPLETED;
-      break;
-    case MasterGCPConf::GCP_PREPARE_RECEIVED:
-      jam();
-      cgcpMasterTakeOverState = COMMIT_STARTED_NOT_COMPLETED;
-      break;
-    case MasterGCPConf::GCP_COMMIT_RECEIVED:
-      jam();
-      cgcpMasterTakeOverState = COMMIT_STARTED_NOT_COMPLETED;
-      break;
-    case MasterGCPConf::GCP_TC_FINISHED:
-      jam();
-      break;
-    default:
-      ndbrequire(false);
-      break;
-    }//switch
+  case MasterGCPConf::GCP_SAVE_CONF:
+    jam();
+    ok = true;
+    if (m_gcp_save.m_master_state == GcpSave::GCP_SAVE_IDLE)
+    {
+      m_gcp_save.m_gci = saveGCI;
+      m_gcp_save.m_master_state = GcpSave::GCP_SAVE_CONF;
+    }
+    else if (m_gcp_save.m_master_state == GcpSave::GCP_SAVE_REQ)
+    {
+      ndbrequire(m_gcp_save.m_gci = saveGCI);
+    }
+    else if (m_gcp_save.m_master_state == GcpSave::GCP_SAVE_COPY_GCI)
+    {
+      ndbrequire(m_gcp_save.m_gci = saveGCI);
+    }
     break;
-  case SAVE_STARTED_NOT_COMPLETED:
-    switch (gcpState) {
-    case MasterGCPConf::GCP_READY:
-      jam();
-      break;
-    case MasterGCPConf::GCP_PREPARE_RECEIVED:
-      ndbrequire(false);
-      break;
-    case MasterGCPConf::GCP_COMMIT_RECEIVED:
-      ndbrequire(false);
-      break;
-    case MasterGCPConf::GCP_TC_FINISHED:
-      jam();
-      break;
-    default:
-      ndbrequire(false);
-      break;
-    }//switch
+  case MasterGCPConf::GCP_SAVE_COPY_GCI:
+    jam();
+    ok= true;
+    if (m_gcp_save.m_master_state == GcpSave::GCP_SAVE_IDLE)
+    {
+      m_gcp_save.m_gci = saveGCI;
+    }
+    m_gcp_save.m_master_state = GcpSave::GCP_SAVE_COPY_GCI;
     break;
+#ifndef VM_TRACE
   default:
+    jamLine(saveState);
     ndbrequire(false);
-    break;
-  }//switch
+#endif
+  }
+  ndbassert(ok); // Unhandled case
+
   receiveLoopMacro(MASTER_GCPREQ, senderNodePtr.i);
   /*-------------------------------------------------------------------------*/
   // We have now received all responses and are ready to take over the GCP
   // protocol as master.
   /*-------------------------------------------------------------------------*/
   MASTER_GCPhandling(signal, failedNodeId);
+
   return;
 }//Dbdih::execMASTER_GCPCONF()
 
@@ -5521,105 +5474,96 @@
 
 void Dbdih::MASTER_GCPhandling(Signal* signal, Uint32 failedNodeId) 
 {
-  NodeRecordPtr failedNodePtr;
   cmasterState = MASTER_ACTIVE;
-  /*----------------------------------------------------------*/
-  /*       REMOVE ALL ACTIVE STATUS ON ALREADY FAILED NODES   */
-  /*       THIS IS PERFORMED HERE SINCE WE GET THE LCP ACTIVE */
-  /*       STATUS AS PART OF THE COPY RESTART INFO AND THIS IS*/
-  /*       HANDLED BY THE MASTER GCP TAKE OVER PROTOCOL.      */
-  /*----------------------------------------------------------*/
-  
-  failedNodePtr.i = failedNodeId;
-  ptrCheckGuard(failedNodePtr, MAX_NDB_NODES, nodeRecord);
-  switch (cgcpMasterTakeOverState) {
-  case ALL_READY:
+  m_micro_gcp.m_start_time = 0;
+  m_gcp_save.m_start_time = 0;
+  m_micro_gcp.m_next_gci = m_micro_gcp.m_new_gci + 1;
+
+  bool ok = false;
+  switch(m_micro_gcp.m_master_state){
+  case MicroGcp::M_GCP_IDLE:
     jam();
-    startGcp(signal);
+    ok = true;
+    signal->theData[0] = DihContinueB::ZSTART_GCP;
+    sendSignal(reference(), GSN_CONTINUEB, signal, 1, JBB);
     break;
-  case PREPARE_STARTED_NOT_COMMITTED:
-    {
-      NodeRecordPtr nodePtr;
-      jam();
-      c_GCP_PREPARE_Counter.clearWaitingFor();
-      nodePtr.i = cfirstAliveNode;
-      do {
-	jam();
-	ptrCheckGuard(nodePtr, MAX_NDB_NODES, nodeRecord);
-	if (nodePtr.p->gcpstate == NodeRecord::READY) {
-	  jam();
-	  c_GCP_PREPARE_Counter.setWaitingFor(nodePtr.i);
-	  sendGCP_PREPARE(signal, nodePtr.i);
-	}//if
-	nodePtr.i = nodePtr.p->nextNode;
-      } while(nodePtr.i != RNIL);
-      if (c_GCP_PREPARE_Counter.done()) {
-	jam();
-	gcpcommitreqLab(signal);
-      }//if
-      break;
-    }
-  case ALL_PREPARED:
+  case MicroGcp::M_GCP_PREPARE:
+  {
     jam();
-    gcpcommitreqLab(signal);
+    ok = true;
+
+    /**
+     * Restart GCP_PREPARE
+     */
+    sendLoopMacro(GCP_PREPARE, sendGCP_PREPARE);
     break;
-  case COMMIT_STARTED_NOT_COMPLETED:
-    {
-      NodeRecordPtr nodePtr;
-      jam();
-      c_GCP_COMMIT_Counter.clearWaitingFor();
-      nodePtr.i = cfirstAliveNode;
-      do {
-	jam();
-	ptrCheckGuard(nodePtr, MAX_NDB_NODES, nodeRecord);
-	if (nodePtr.p->gcpstate == NodeRecord::PREPARE_RECEIVED) {
-	  jam();
-	  sendGCP_COMMIT(signal, nodePtr.i);
-	  c_GCP_COMMIT_Counter.setWaitingFor(nodePtr.i);
-	} else {
-	  ndbrequire((nodePtr.p->gcpstate == NodeRecord::NODE_FINISHED) ||
-		     (nodePtr.p->gcpstate == NodeRecord::COMMIT_SENT));
-	}//if
-	nodePtr.i = nodePtr.p->nextNode;
-      } while(nodePtr.i != RNIL);
-      if (c_GCP_COMMIT_Counter.done()){
-	jam();
-	gcpsavereqLab(signal);
-      }//if
-      break;
-    }
-  case COMMIT_COMPLETED:
+  }
+  case MicroGcp::M_GCP_COMMIT:
+  {
     jam();
-    gcpsavereqLab(signal);
+    ok = true;
+
+    /**
+     * Restart GCP_COMMIT
+     */
+    sendLoopMacro(GCP_COMMIT, sendGCP_COMMIT);
     break;
-  case SAVE_STARTED_NOT_COMPLETED:
-    {
-      NodeRecordPtr nodePtr;
-      jam();
-      SYSFILE->newestRestorableGCI = coldgcp;
-      nodePtr.i = cfirstAliveNode;
-      do {
-	jam();
-	ptrCheckGuard(nodePtr, MAX_NDB_NODES, nodeRecord);
-	SYSFILE->lastCompletedGCI[nodePtr.i] = coldgcp;
-	nodePtr.i = nodePtr.p->nextNode;
-      } while (nodePtr.i != RNIL);
-      /**-------------------------------------------------------------------
-       * THE FAILED NODE DID ALSO PARTICIPATE IN THIS GLOBAL CHECKPOINT 
-       * WHICH IS RECORDED.
-       *-------------------------------------------------------------------*/
-      SYSFILE->lastCompletedGCI[failedNodeId] = coldgcp;
-      copyGciLab(signal, CopyGCIReq::GLOBAL_CHECKPOINT);
-      break;
-    }
+  }
+  case MicroGcp::M_GCP_SAVE:
+    jam();
+  case MicroGcp::M_GCP_COMMITTED:
+    jam();
+    ndbrequire(false);
+#ifndef VM_TRACE
   default:
+    jamLine(m_micro_gcp.m_master_state);
     ndbrequire(false);
+#endif
+  }
+  ndbassert(ok);
+
+  ok = false;
+  switch(m_gcp_save.m_master_state){
+  case GcpSave::GCP_SAVE_IDLE:
+    jam();
+    ok = true;
     break;
-  }//switch
+  case GcpSave::GCP_SAVE_REQ:
+  {
+    jam();
+    ok = true;
+
+    /**
+     * Restart GCP_SAVE_REQ
+     */
+    sendLoopMacro(GCP_SAVEREQ, sendGCP_SAVEREQ);
+    break;
+  }
+  case GcpSave::GCP_SAVE_CONF:
+    jam();
+  case GcpSave::GCP_SAVE_COPY_GCI:
+    jam();
+    ok = true;
+    copyGciLab(signal, CopyGCIReq::GLOBAL_CHECKPOINT);
+    m_gcp_save.m_master_state = GcpSave::GCP_SAVE_COPY_GCI;
+    break;
+#ifndef VM_TRACE
+  default:
+    jamLine(m_gcp_save.m_master_state);
+    ndbrequire(false);
+#endif
+  }
+  ndbrequire(ok);
 
   signal->theData[0] = NDB_LE_GCP_TakeoverCompleted;
+  signal->theData[1] = m_micro_gcp.m_master_state;
+  signal->theData[2] = m_gcp_save.m_master_state;
   sendSignal(CMVMI_REF, GSN_EVENT_REP, signal, 1, JBB);
 
+  infoEvent("kk: %u %u",
+            m_micro_gcp.m_master_state,
+            m_gcp_save.m_master_state);
+
   /*--------------------------------------------------*/
   /*       WE SEPARATE HANDLING OF GLOBAL CHECKPOINTS */
   /*       AND LOCAL CHECKPOINTS HERE. LCP'S HAVE TO  */
@@ -7756,8 +7700,9 @@
     // theData[0] already contains the correct information so 
     // we need not touch it.
     /*-----------------------------------------------------------------------*/
-    signal->theData[1] = currentgcp;
-    signal->theData[2] = 0;
+    signal->theData[1] = m_micro_gcp.m_current_gci >> 32;
+    signal->theData[2] = m_micro_gcp.m_current_gci & 0xFFFFFFFF;
+    signal->theData[3] = 0;
     return;
   }//if
   /*-------------------------------------------------------------------------*/
@@ -7771,7 +7716,7 @@
   localApiConnectptr.i = signal->theData[0];
   tmpApiConnectptr.i = clastVerifyQueue;
   ptrCheckGuard(localApiConnectptr, capiConnectFileSize, apiConnectRecord);
-  localApiConnectptr.p->apiGci = cnewgcp;
+  localApiConnectptr.p->apiGci = m_micro_gcp.m_new_gci;
   localApiConnectptr.p->nextApi = RNIL;
   clastVerifyQueue = localApiConnectptr.i;
   if (tmpApiConnectptr.i == RNIL) {
@@ -7783,7 +7728,7 @@
     tmpApiConnectptr.p->nextApi = localApiConnectptr.i;
   }//if
   emptyverificbuffer(signal, false);
-  signal->theData[2] = 1; // Indicate no immediate return
+  signal->theData[3] = 1; // Indicate no immediate return
   return;
 }//Dbdih::execDIVERIFYREQ()
 
@@ -7912,7 +7857,7 @@
 void Dbdih::checkGcpStopLab(Signal* signal) 
 {
   Uint32 tgcpStatus;
-
+#if 0
   tgcpStatus = cgcpStatus;
   if (tgcpStatus == coldGcpStatus) {
     jam();
@@ -7966,13 +7911,24 @@
   sendSignalWithDelay(reference(), GSN_CONTINUEB, signal, 100, 6);
   coldGcpStatus = cgcpStatus;
   coldGcpId = cnewgcp;
+#endif
   return;
 }//Dbdih::checkGcpStopLab()
 
 void Dbdih::startGcpLab(Signal* signal, Uint32 aWaitTime) 
 {
+  if (c_nodeStartMaster.blockGcp == true)
+  {
+    jam();
+    /* ------------------------------------------------------------------ */
+    /*  A NEW NODE WANTS IN AND WE MUST ALLOW IT TO COME IN NOW SINCE THE */
+    /*       GCP IS COMPLETED.                                            */
+    /* ------------------------------------------------------------------ */
+    gcpBlockedLab(signal);
+    return;
+  }//if
+
   if ((cgcpOrderBlocked == 1) ||
-      (c_nodeStartMaster.blockGcp == true) ||
       (cfirstVerifyQueue != RNIL)) {
     /*************************************************************************/
     // 1: Global Checkpoint has been stopped by management command
@@ -7981,51 +7937,73 @@
     // All this means that global checkpoint cannot start now.
     /*************************************************************************/
     jam();
-    cgcpStartCounter++;
     signal->theData[0] = DihContinueB::ZSTART_GCP;
-    signal->theData[1] = aWaitTime > 100 ? (aWaitTime - 100) : 0;
-    sendSignalWithDelay(reference(), GSN_CONTINUEB, signal, 100, 2);
+    sendSignalWithDelay(reference(), GSN_CONTINUEB, signal, 10, 1);
     return;
   }//if
-  if (cstartGcpNow == false && aWaitTime > 100){
-    /*************************************************************************/
-    // We still have more than 100 milliseconds before we start the next and 
-    // nobody has ordered immediate start of a global checkpoint.
-    // During initial start we will use continuos global checkpoints to 
-    // speed it up since we need to complete a global checkpoint after 
-    // inserting a lot of records.
-    /*************************************************************************/
+
+  Uint64 now = NdbTick_CurrentMillisecond();
+  if (cstartGcpNow == false)
+  {
     jam();
-    cgcpStartCounter++;
-    signal->theData[0] = DihContinueB::ZSTART_GCP;
-    signal->theData[1] = (aWaitTime - 100);
-    sendSignalWithDelay(reference(), GSN_CONTINUEB, signal, 100, 2);
-    return;
+    Uint32 delay = m_micro_gcp.m_time_between_gcp;
+    if (delay == 0)
+    {
+      jam(); // I.e not configured
+      delay = m_gcp_save.m_time_between_gcp;
+    }
+
+    if (m_micro_gcp.m_start_time + delay > now)
+    {
+      jam();
+      signal->theData[0] = DihContinueB::ZSTART_GCP;
+      sendSignalWithDelay(reference(), GSN_CONTINUEB, signal, 10, 1);
+      return;
+    }
   }//if
-  cgcpStartCounter = 0;
   cstartGcpNow = false;
+  m_micro_gcp.m_start_time = now;
+
+  m_micro_gcp.m_new_gci = m_micro_gcp.m_next_gci;
+  m_micro_gcp.m_next_gci++;
+
+  /**
+   * Check that there has not been more than 2^32 micro GCP wo/ any save
+   */
+  ndbrequire((m_micro_gcp.m_new_gci & 0xFFFFFFFF) != 0xFFFFFFFF);
+
   /***************************************************************************/
   // Report the event that a global checkpoint has started.
   /***************************************************************************/
   signal->theData[0] = NDB_LE_GlobalCheckpointStarted; //Event type
-  signal->theData[1] = cnewgcp;
-  sendSignal(CMVMI_REF, GSN_EVENT_REP, signal, 2, JBB);
-
-  NdbTick_getMicroTimer(&gcp_timer_start);
+  signal->theData[1] = m_micro_gcp.m_new_gci >> 32;
+  signal->theData[2] = m_micro_gcp.m_new_gci & 0xFFFFFFFF;
+  sendSignal(CMVMI_REF, GSN_EVENT_REP, signal, 3, JBB);
 
   CRASH_INSERTION(7000);
-  cnewgcp++;
+  m_micro_gcp.m_master_state = MicroGcp::M_GCP_PREPARE;
   signal->setTrace(TestOrd::TraceGlobalCheckpoint);
+
+  if (ERROR_INSERTED(7186))
+  {
+    sendToRandomNodes("GCP_PREPARE",
+                      signal, &c_GCP_PREPARE_Counter, &Dbdih::sendGCP_PREPARE);
+    signal->theData[0] = 9999;
+    sendSignalWithDelay(CMVMI_REF, GSN_NDB_TAMPER, signal, 1000, 1);
+    return;
+  }
+
   sendLoopMacro(GCP_PREPARE, sendGCP_PREPARE);
-  cgcpStatus = GCP_PREPARE_SENT;
 }//Dbdih::startGcpLab()
 
-void Dbdih::execGCP_PREPARECONF(Signal* signal) 
+void Dbdih::execGCP_PREPARECONF(Signal* signal)
 {
   jamEntry();
   Uint32 senderNodeId = signal->theData[0];
-  Uint32 gci = signal->theData[1];
-  ndbrequire(gci == cnewgcp);
+  Uint32 gci_hi = signal->theData[1];
+  Uint32 gci_lo = signal->theData[2];
+  Uint64 gci = gci_lo | (Uint64(gci_hi) << 32);
+  ndbrequire(gci == m_micro_gcp.m_new_gci);
   receiveLoopMacro(GCP_PREPARE, senderNodeId);
   //-------------------------------------------------------------
   // We have now received all replies. We are ready to continue
@@ -8034,20 +8012,43 @@
   gcpcommitreqLab(signal);
 }//Dbdih::execGCP_PREPARECONF()
 
-void Dbdih::gcpcommitreqLab(Signal* signal) 
+void Dbdih::gcpcommitreqLab(Signal* signal)
 {
   CRASH_INSERTION(7001);
+
+  m_micro_gcp.m_master_state = MicroGcp::M_GCP_COMMIT;
+
+  if (ERROR_INSERTED(7187))
+  {
+    sendToRandomNodes("GCP_COMMIT",
+                      signal, &c_GCP_COMMIT_Counter, &Dbdih::sendGCP_COMMIT);
+    signal->theData[0] = 9999;
+    sendSignalWithDelay(CMVMI_REF, GSN_NDB_TAMPER, signal, 1000, 1);
+    return;
+  }
+
   sendLoopMacro(GCP_COMMIT, sendGCP_COMMIT);
-  cgcpStatus = GCP_COMMIT_SENT;
   return;
 }//Dbdih::gcpcommitreqLab()
 
-void Dbdih::execGCP_NODEFINISH(Signal* signal) 
+void Dbdih::execGCP_NODEFINISH(Signal* signal)
 {
   jamEntry();
   const Uint32 senderNodeId = signal->theData[0];
-  const Uint32 gci = signal->theData[1];
+  const Uint32 gci_hi = signal->theData[1];
   const Uint32 failureNr = signal->theData[2];
+  const Uint32 gci_lo = signal->theData[3];
+  const Uint64 gci = gci_lo | (Uint64(gci_hi) << 32);
+
+#if 0
+  /**
+   * This section is #if 0
+   *   as I changed GCP_NODEFINISH to only be sent in return to
+   *   node sending GCP_COMMIT
+   *
+   * So...this can never arraive at "new master"
+   */
+
   if (!isMaster()) {
     jam();
     ndbrequire(failureNr > cfailurenr);
@@ -8062,35 +8063,189 @@
     jam();
     //-------------------------------------------------------------
     // We are currently taking over as master. Ignore
-    // signal in this case since we will discover it in reception of 
+    // signal in this case since we will discover it in reception of
     // MASTER_GCPCONF.
     //-------------------------------------------------------------
     return;
   } else {
     ndbrequire(cmasterState == MASTER_ACTIVE);
   }//if
-  ndbrequire(gci == coldgcp);
+#endif
+
+  ndbrequire(m_micro_gcp.m_master_state == MicroGcp::M_GCP_COMMIT);
   receiveLoopMacro(GCP_COMMIT, senderNodeId);
+
+  if (m_micro_gcp.m_enabled)
+  {
+    jam();
+
+    SubGcpCompleteRep * const rep = (SubGcpCompleteRep*)signal->getDataPtr();
+    rep->senderRef = reference();
+#if 1
+    rep->gci_hi = m_micro_gcp.m_old_gci >> 32;
+    rep->gci_lo = m_micro_gcp.m_old_gci & 0xFFFFFFFF;
+    rep->flags = SubGcpCompleteRep::IN_MEMORY;
+#else
+    rep->gci = m_micro_gcp.m_old_gci >> 32;
+#endif
+
+    if (ERROR_INSERTED(7190))
+    {
+      sendToRandomNodes("GCP_COMPLETE_REP", signal, 0, 0,
+                        DBDIH,
+                        GSN_SUB_GCP_COMPLETE_REP,
+                        SubGcpCompleteRep::SignalLength,
+                        JBA);
+      signal->theData[0] = 9999;
+      sendSignalWithDelay(CMVMI_REF, GSN_NDB_TAMPER, signal, 1000, 1);
+    }
+    else
+    {
+      NodeRecordPtr specNodePtr;
+      specNodePtr.i = cfirstAliveNode;
+      do {
+        jam();
+        ptrCheckGuard(specNodePtr, MAX_NDB_NODES, nodeRecord);
+        sendSignal(calcDihBlockRef(specNodePtr.i), GSN_SUB_GCP_COMPLETE_REP,
+                   signal, SubGcpCompleteRep::SignalLength, JBA);
+        specNodePtr.i = specNodePtr.p->nextNode;
+      } while (specNodePtr.i != RNIL);
+    }
+  }
+
   //-------------------------------------------------------------
   // We have now received all replies. We are ready to continue
   // with saving the global checkpoint to disk.
   //-------------------------------------------------------------
   CRASH_INSERTION(7002);
-  gcpsavereqLab(signal);
+
+  /**
+   * New protocol
+   */
+  Uint64 now;
+  if (m_micro_gcp.m_enabled)
+  {
+    jam();
+
+    m_micro_gcp.m_master_state = MicroGcp::M_GCP_IDLE;
+    if (!ERROR_INSERTED(7190))
+    {
+      signal->theData[0] = DihContinueB::ZSTART_GCP;
+      sendSignalWithDelay(reference(), GSN_CONTINUEB, signal, 10, 1);
+    }
+
+    if (m_gcp_save.m_master_state != GcpSave::GCP_SAVE_IDLE)
+    {
+      jam();
+      return;
+    }
+
+    now = NdbTick_CurrentMillisecond();
+    if (m_gcp_save.m_start_time + m_gcp_save.m_time_between_gcp > now)
+    {
+      jam();
+      return;
+    }
+  }
+  else
+  {
+    jam();
+    m_micro_gcp.m_master_state = MicroGcp::M_GCP_SAVE;
+  }
+
+  /**
+   * Start a save
+   */
+  m_gcp_save.m_master_state = GcpSave::GCP_SAVE_REQ;
+  m_gcp_save.m_gci = m_micro_gcp.m_old_gci >> 32;
+  m_gcp_save.m_start_time = now;
+
+  if (ERROR_INSERTED(7188))
+  {
+    sendToRandomNodes("GCP_SAVE",
+                      signal, &c_GCP_SAVEREQ_Counter, &Dbdih::sendGCP_SAVEREQ);
+    signal->theData[0] = 9999;
+    sendSignalWithDelay(CMVMI_REF, GSN_NDB_TAMPER, signal, 1000, 1);
+    return;
+  }
+
+  sendLoopMacro(GCP_SAVEREQ, sendGCP_SAVEREQ);
   return;
 }//Dbdih::execGCP_NODEFINISH()
 
-void Dbdih::gcpsavereqLab(Signal* signal) 
+
+void Dbdih::gcpsavereqLab(Signal*)
 {
-  sendLoopMacro(GCP_SAVEREQ, sendGCP_SAVEREQ);
-  cgcpStatus = GCP_NODE_FINISHED;
-}//Dbdih::gcpsavereqLab()
+  ndbrequire(false);
+}
+
+void
+Dbdih::execGCP_SAVEREQ(Signal* signal)
+{
+  jamEntry();
+  GCPSaveReq * req = (GCPSaveReq*)&signal->theData[0];
+
+  if (m_gcp_save.m_state == GcpSave::GCP_SAVE_REQ)
+  {
+    jam();
+    /**
+     * This is master take over...
+     * and SAVE_REQ is already running
+     */
+    ndbrequire(m_gcp_save.m_master_ref != req->dihBlockRef);
+    ndbrequire(m_gcp_save.m_gci == req->gci);
+    m_gcp_save.m_master_ref = req->dihBlockRef;
+    return;
+  }
+
+  if (m_gcp_save.m_state == GcpSave::GCP_SAVE_CONF)
+  {
+    jam();
+    /**
+     * This is master take over...
+     * and SAVE_REQ is complete...
+     */
+    ndbrequire(m_gcp_save.m_master_ref != req->dihBlockRef);
+    ndbrequire(m_gcp_save.m_gci == req->gci);
+    m_gcp_save.m_master_ref = req->dihBlockRef;
+
+    GCPSaveReq save = (* req);
+    GCPSaveConf * conf = (GCPSaveConf*)signal->getDataPtrSend();
+    conf->dihPtr = save.dihPtr;
+    conf->nodeId = getOwnNodeId();
+    conf->gci    = save.gci;
+    sendSignal(m_gcp_save.m_master_ref, GSN_GCP_SAVECONF, signal,
+               GCPSaveConf::SignalLength, JBA);
+    return;
+  }
+
+  ndbrequire(m_gcp_save.m_state == GcpSave::GCP_SAVE_IDLE);
+  m_gcp_save.m_state = GcpSave::GCP_SAVE_REQ;
+  m_gcp_save.m_master_ref = req->dihBlockRef;
+  m_gcp_save.m_gci = req->gci;
+
+  req->dihBlockRef = reference();
+  sendSignal(DBLQH_REF, GSN_GCP_SAVEREQ, signal, signal->getLength(), JBA);
+}
 
 void Dbdih::execGCP_SAVECONF(Signal* signal) 
 {
   jamEntry();  
-  const GCPSaveConf * const saveConf = (GCPSaveConf*)&signal->theData[0];
-  ndbrequire(saveConf->gci == coldgcp);
+  GCPSaveConf * saveConf = (GCPSaveConf*)&signal->theData[0];
+
+  if (refToBlock(signal->getSendersBlockRef()) == DBLQH)
+  {
+    jam();
+
+    ndbrequire(m_gcp_save.m_state == GcpSave::GCP_SAVE_REQ);
+    m_gcp_save.m_state = GcpSave::GCP_SAVE_CONF;
+
+    sendSignal(m_gcp_save.m_master_ref,
+               GSN_GCP_SAVECONF, signal, signal->getLength(), JBA);
+    return;
+  }
+
+  ndbrequire(saveConf->gci == m_gcp_save.m_gci);
   ndbrequire(saveConf->nodeId == saveConf->dihPtr);
   SYSFILE->lastCompletedGCI[saveConf->nodeId] = saveConf->gci;  
   GCP_SAVEhandling(signal, saveConf->nodeId);
@@ -8099,9 +8254,23 @@
 void Dbdih::execGCP_SAVEREF(Signal* signal) 
 {
   jamEntry();
-  const GCPSaveRef * const saveRef = (GCPSaveRef*)&signal->theData[0];
-  ndbrequire(saveRef->gci == coldgcp);
+  GCPSaveRef * const saveRef = (GCPSaveRef*)&signal->theData[0];
+
+  if (refToBlock(signal->getSendersBlockRef()) == DBLQH)
+  {
+    jam();
+
+    ndbrequire(m_gcp_save.m_state == GcpSave::GCP_SAVE_REQ);
+    m_gcp_save.m_state = GcpSave::GCP_SAVE_CONF;
+
+    sendSignal(m_gcp_save.m_master_ref,
+               GSN_GCP_SAVEREF, signal, signal->getLength(), JBA);
+    return;
+  }
+
+  ndbrequire(saveRef->gci == m_gcp_save.m_gci);
   ndbrequire(saveRef->nodeId == saveRef->dihPtr);
+
   /**
    * Only allow reason not to save
    */
@@ -8113,11 +8282,12 @@
 
 void Dbdih::GCP_SAVEhandling(Signal* signal, Uint32 nodeId) 
 {
+  ndbrequire(m_gcp_save.m_master_state == GcpSave::GCP_SAVE_REQ);
   receiveLoopMacro(GCP_SAVEREQ, nodeId);
   /*-------------------------------------------------------------------------*/
   // All nodes have replied. We are ready to update the system file.
   /*-------------------------------------------------------------------------*/
-  cgcpStatus = GCP_SAVE_LQH_FINISHED;  
+
   CRASH_INSERTION(7003);
   checkToCopy();
   /**------------------------------------------------------------------------
@@ -8127,7 +8297,7 @@
    * SET BACK THE RESTART GCI IF WE ENCOUNTER MORE THAN ONE UNSUCCESSFUL 
    * RESTART.
    *------------------------------------------------------------------------*/
-  SYSFILE->newestRestorableGCI = coldgcp;
+  SYSFILE->newestRestorableGCI = m_gcp_save.m_gci;
   if(Sysfile::getInitialStartOngoing(SYSFILE->systemRestartBits) &&
      getNodeState().startLevel == NodeState::SL_STARTED){
     jam();
@@ -8137,6 +8307,9 @@
     Sysfile::clearInitialStartOngoing(SYSFILE->systemRestartBits);
   }
   copyGciLab(signal, CopyGCIReq::GLOBAL_CHECKPOINT);
+
+  m_gcp_save.m_master_state = GcpSave::GCP_SAVE_COPY_GCI;
+
 }//Dbdih::GCP_SAVEhandling()
 
 /*
@@ -8158,17 +8331,51 @@
   }
   
   GCPPrepare* req = (GCPPrepare*)signal->getDataPtr();
+  GCPPrepareConf * conf = (GCPPrepareConf*)signal->getDataPtrSend();
   Uint32 masterNodeId = req->nodeId;
-  Uint32 gci = req->gci;
+  Uint32 gci_hi = req->gci_hi;
+  Uint32 gci_lo = req->gci_lo;
+  Uint64 gci = gci_lo | (Uint64(gci_hi) << 32);
   BlockReference retRef = calcDihBlockRef(masterNodeId);
-                                                 
-  ndbrequire (cmasterdihref == retRef);
-  ndbrequire (cgcpParticipantState == GCP_PARTICIPANT_READY);
-  ndbrequire (gci == (currentgcp + 1));
+
+  if (isMaster())
+  {
+    ndbrequire(m_micro_gcp.m_master_state == MicroGcp::M_GCP_PREPARE);
+  }
+
+  if (m_micro_gcp.m_state == MicroGcp::M_GCP_PREPARE)
+  {
+    jam();
+    /**
+     * This must be master take over
+     *   Prepare is already complete
+     */
+    ndbrequire(m_micro_gcp.m_master_ref != retRef);
+    ndbrequire(m_micro_gcp.m_new_gci == gci);
+    m_micro_gcp.m_master_ref = retRef;
+
+    goto reply;
+  }
+
+  ndbrequire(m_micro_gcp.m_state == MicroGcp::M_GCP_IDLE);
   
+  if (m_micro_gcp.m_current_gci == gci)
+  {
+    jam();
+    /**
+     * This GCP has already been prepared...
+     *   Must be master takeover
+     */
+    infoEvent("keso");
+    ndbrequire(m_micro_gcp.m_master_ref != retRef);
+    // Note...done set master_ref...and this will also be GCP_COMMIT:ed
+    goto reply;
+  }
+
   cgckptflag = true;
-  cgcpParticipantState = GCP_PARTICIPANT_PREPARE_RECEIVED;
-  cnewgcp = gci;
+  m_micro_gcp.m_state = MicroGcp::M_GCP_PREPARE;
+  m_micro_gcp.m_new_gci = gci;
+  m_micro_gcp.m_master_ref = retRef;
 
   if (ERROR_INSERTED(7031))
   {
@@ -8177,36 +8384,84 @@
     sendSignalWithDelay(CMVMI_REF, GSN_NDB_TAMPER, signal, 3000, 1);
     return;
   }
-  
-  GCPPrepareConf* conf = (GCPPrepareConf*)signal->getDataPtrSend();
+#ifdef GCP_TIMER_HACK
+  NdbTick_getMicroTimer(&globalData.gcp_timer_commit[0]);
+#endif
+
+reply:
   conf->nodeId = cownNodeId;
-  conf->gci = gci;  
+  conf->gci_hi = gci_hi;
+  conf->gci_lo = gci_lo;
   sendSignal(retRef, GSN_GCP_PREPARECONF, signal, 
              GCPPrepareConf::SignalLength, JBA);
   return;
-}//Dbdih::execGCP_PREPARE()
+}
 
 void Dbdih::execGCP_COMMIT(Signal* signal) 
 {
   jamEntry();
   CRASH_INSERTION(7006);
+
   GCPCommit * req = (GCPCommit*)signal->getDataPtr();
   Uint32 masterNodeId = req->nodeId;
-  Uint32 gci = req->gci;
+  Uint32 gci_hi = req->gci_hi;
+  Uint32 gci_lo = req->gci_lo;
+  Uint64 gci = gci_lo | (Uint64(gci_hi) << 32);
 
-  ndbrequire(gci == (currentgcp + 1));
+  Uint32 masterRef = calcDihBlockRef(masterNodeId);
   ndbrequire(masterNodeId = cmasterNodeId);
-  ndbrequire(cgcpParticipantState == GCP_PARTICIPANT_PREPARE_RECEIVED);
+  if (isMaster())
+  {
+    ndbrequire(m_micro_gcp.m_master_state == MicroGcp::M_GCP_COMMIT);
+  }
+
+  if (m_micro_gcp.m_state == MicroGcp::M_GCP_COMMIT)
+  {
+    jam();
+    /**
+     * This must be master take over
+     *   Commit is already ongoing...
+     */
+    ndbrequire(m_micro_gcp.m_master_ref != masterRef);
+    ndbrequire(m_micro_gcp.m_current_gci == gci);
+    m_micro_gcp.m_master_ref = masterRef;
+    return;
+  }
+
+  if (m_micro_gcp.m_state == MicroGcp::M_GCP_COMMITTED ||
+      m_micro_gcp.m_state == MicroGcp::M_GCP_IDLE)
+  {
+    jam();
+    /**
+     * This must be master take over
+     *   Commit has already completed
+     */
+    ndbrequire(m_micro_gcp.m_master_ref != masterRef);
+    ndbrequire(m_micro_gcp.m_current_gci == gci);
+
+    GCPNodeFinished* conf = (GCPNodeFinished*)signal->getDataPtrSend();
+    conf->nodeId = cownNodeId;
+    conf->gci_hi = m_micro_gcp.m_old_gci >> 32;
+    conf->failno = cfailurenr;
+    conf->gci_lo = m_micro_gcp.m_old_gci & 0xFFFFFFFF;
+    sendSignal(masterRef, GSN_GCP_NODEFINISH, signal,
+               GCPNodeFinished::SignalLength, JBB);
+    return;
+  }
+
+  ndbrequire(m_micro_gcp.m_state == MicroGcp::M_GCP_PREPARE);
+  m_micro_gcp.m_state = MicroGcp::M_GCP_COMMIT;
+  m_micro_gcp.m_master_ref = calcDihBlockRef(masterNodeId);
   
-  coldgcp = currentgcp;
-  currentgcp = cnewgcp;  
+  m_micro_gcp.m_old_gci = m_micro_gcp.m_current_gci;
+  m_micro_gcp.m_current_gci = gci;
   cgckptflag = false;
   emptyverificbuffer(signal, true);
-  cgcpParticipantState = GCP_PARTICIPANT_COMMIT_RECEIVED;
 
   GCPNoMoreTrans* req2 = (GCPNoMoreTrans*)signal->getDataPtrSend();
   req2->senderData = calcDihBlockRef(masterNodeId);
-  req2->gci = coldgcp;
+  req2->gci_hi = m_micro_gcp.m_old_gci >> 32;
+  req2->gci_lo = m_micro_gcp.m_old_gci & 0xFFFFFFFF;
   sendSignal(clocaltcblockref, GSN_GCP_NOMORETRANS, signal, 
              GCPNoMoreTrans::SignalLength, JBB);
   return;
@@ -8216,10 +8471,12 @@
 {
   jamEntry();
   CRASH_INSERTION(7007);
-  GCPTCFinished* req = (GCPTCFinished*)signal->getDataPtr();
-  Uint32 retRef = req->senderData;
-  Uint32 gci = req->gci;
-  ndbrequire(gci == coldgcp);
+  GCPTCFinished* conf = (GCPTCFinished*)signal->getDataPtr();
+  Uint32 retRef = conf->senderData;
+  Uint32 gci_hi = conf->gci_hi;
+  Uint32 gci_lo = conf->gci_lo;
+  Uint64 gci = gci_lo | (Uint64(gci_hi) << 32);
+  ndbrequire(gci == m_micro_gcp.m_old_gci);
 
   if (ERROR_INSERTED(7181) || ERROR_INSERTED(7182))
   {
@@ -8231,16 +8488,52 @@
     return;
   }
 
-  cgcpParticipantState = GCP_PARTICIPANT_TC_FINISHED;
+#ifdef GCP_TIMER_HACK
+  NdbTick_getMicroTimer(&globalData.gcp_timer_commit[1]);
+#endif
 
-  GCPNodeFinished* conf = (GCPNodeFinished*)signal->getDataPtrSend();
-  conf->nodeId = cownNodeId;
-  conf->gci = coldgcp;
-  conf->failno = cfailurenr;
+  ndbrequire(m_micro_gcp.m_state == MicroGcp::M_GCP_COMMIT);
+  m_micro_gcp.m_state = MicroGcp::M_GCP_COMMITTED;
+  retRef = m_micro_gcp.m_master_ref;
+
+  GCPNodeFinished* conf2 = (GCPNodeFinished*)signal->getDataPtrSend();
+  conf2->nodeId = cownNodeId;
+  conf2->gci_hi = m_micro_gcp.m_old_gci >> 32;
+  conf2->failno = cfailurenr;
+  conf2->gci_lo = m_micro_gcp.m_old_gci & 0xFFFFFFFF;
   sendSignal(retRef, GSN_GCP_NODEFINISH, signal, 
              GCPNodeFinished::SignalLength, JBB);
 }//Dbdih::execGCP_TCFINISHED()
 
+void
+Dbdih::execSUB_GCP_COMPLETE_REP(Signal* signal)
+{
+  jamEntry();
+
+  SubGcpCompleteRep* rep = (SubGcpCompleteRep*)signal->getDataPtr();
+  if (isMaster())
+  {
+    ndbrequire(m_micro_gcp.m_master_state == MicroGcp::M_GCP_IDLE);
+  }
+
+  Uint32 masterRef = rep->senderRef;
+  if (m_micro_gcp.m_state == MicroGcp::M_GCP_IDLE)
+  {
+    jam();
+    /**
+     * This must be master take over
+     *   signal has already arrived
+     */
+    ndbrequire(m_micro_gcp.m_master_ref != masterRef);
+    m_micro_gcp.m_master_ref = masterRef;
+    return;
+  }
+
+  ndbrequire(m_micro_gcp.m_state == MicroGcp::M_GCP_COMMITTED);
+  m_micro_gcp.m_state = MicroGcp::M_GCP_IDLE;
+  EXECUTE_DIRECT(SUMA, GSN_SUB_GCP_COMPLETE_REP, signal, signal->length());
+}
+
 /*****************************************************************************/
 //******     RECEIVING   TAMPER   REQUEST   FROM    NDBAPI             ******
 /*****************************************************************************/
@@ -8482,6 +8775,16 @@
     return;
   }
   c_copyGCIMaster.m_copyReason = reason;
+
+  if (reason == CopyGCIReq::GLOBAL_CHECKPOINT && ERROR_INSERTED(7189))
+  {
+    sendToRandomNodes("COPY_GCI",
+                      signal, &c_COPY_GCIREQ_Counter, &Dbdih::sendCOPY_GCIREQ);
+    signal->theData[0] = 9999;
+    sendSignalWithDelay(CMVMI_REF, GSN_NDB_TAMPER, signal, 1000, 1);
+    return;
+  }
+
   sendLoopMacro(COPY_GCIREQ, sendCOPY_GCIREQ);
 
 }//Dbdih::copyGciLab()
@@ -8530,7 +8833,7 @@
     /************************************************************************/
     signal->setTrace(0);
     signal->theData[0] = NDB_LE_GlobalCheckpointCompleted; //Event type
-    signal->theData[1] = coldgcp;
+    signal->theData[1] = m_gcp_save.m_gci;
     sendSignal(CMVMI_REF, GSN_EVENT_REP, signal, 2, JBB);    
 
     {
@@ -8539,28 +8842,35 @@
       NDB_TICKS ticks = NdbTick_getMicrosPassed(gcp_timer_start, stop);
       Uint32 ms = ticks / 1000;
       // random formula to report excessive duration
-      bool report = ms > 3000 * (1 + cgcpDelay / 1000);
+      bool report = ms > 3000 * (1 + m_gcp_save.m_time_between_gcp / 1000);
       if (report)
         infoEvent("GCP %u duration %u ms (config %u ms)",
-                  coldgcp, ms, cgcpDelay);
+                  m_gcp_save.m_gci, ms, m_gcp_save.m_time_between_gcp);
     }
 
-    c_newest_restorable_gci = coldgcp;
+    c_newest_restorable_gci = m_gcp_save.m_gci;
+
+    Uint64 next = m_micro_gcp.m_next_gci;
+    ndbout_c("execCOPY_GCICONF: %u micros: %d",
+             m_gcp_save.m_gci, next & 0xFFFFFFFF);
+    ndbassert(next & 0xFFFFFFFF);
+    next &= ~Uint64(0xFFFFFFFF);
+    next += Uint64(1) << 32;
+    m_micro_gcp.m_next_gci = next;
+
+    if (m_micro_gcp.m_state == MicroGcp::M_GCP_SAVE)
+    {
+      jam();
+      /**
+       * Running old protocol
+       */
+      signal->theData[0] = DihContinueB::ZSTART_GCP;
+      sendSignal(reference(), GSN_CONTINUEB, signal, 1, JBB);
+    }
+    m_gcp_save.m_master_state = GcpSave::GCP_SAVE_IDLE;
 
     CRASH_INSERTION(7004);
     emptyWaitGCPMasterQueue(signal);    
-    cgcpStatus = GCP_READY;
-    signal->theData[0] = DihContinueB::ZSTART_GCP;
-    signal->theData[1] = cgcpDelay;
-    sendSignalWithDelay(reference(), GSN_CONTINUEB, signal, 100, 2);
-    if (c_nodeStartMaster.blockGcp == true) {
-      jam();
-      /* ------------------------------------------------------------------ */
-      /*  A NEW NODE WANTS IN AND WE MUST ALLOW IT TO COME IN NOW SINCE THE */
-      /*       GCP IS COMPLETED.                                            */
-      /* ------------------------------------------------------------------ */
-      gcpBlockedLab(signal);
-    }//if
     break;
   case CopyGCIReq::INITIAL_START_COMPLETED:
     ok = true;
@@ -8662,12 +8972,23 @@
   
   if (reason == CopyGCIReq::GLOBAL_CHECKPOINT) {
     jam();
-    cgcpParticipantState = GCP_PARTICIPANT_READY;
+    m_gcp_save.m_state = GcpSave::GCP_SAVE_IDLE;
     
     SubGcpCompleteRep * const rep = (SubGcpCompleteRep*)signal->getDataPtr();
-    rep->gci = coldgcp;
-    sendSignal(SUMA_REF, GSN_SUB_GCP_COMPLETE_REP, signal, 
-	       SubGcpCompleteRep::SignalLength, JBB);
+#if 1
+    rep->gci_hi = SYSFILE->newestRestorableGCI;
+    rep->gci_lo = 0;
+    rep->flags = SubGcpCompleteRep::ON_DISK;
+#else
+    rep->gci = SYSFILE->newestRestorableGCI;
+#endif
+
+    if (m_micro_gcp.m_enabled == false)
+    {
+      jam();
+      sendSignal(SUMA_REF, GSN_SUB_GCP_COMPLETE_REP, signal,
+                 SubGcpCompleteRep::SignalLength, JBB);
+    }
 
     EXECUTE_DIRECT(LGMAN, GSN_SUB_GCP_COMPLETE_REP, signal, 
 		   SubGcpCompleteRep::SignalLength);
@@ -8677,14 +8998,20 @@
   jam();
   c_copyGCISlave.m_copyReason = CopyGCIReq::IDLE;
   
-  if(c_copyGCISlave.m_senderRef == cmasterdihref){
+  if (reason == CopyGCIReq::GLOBAL_CHECKPOINT)
+  {
+    jam();
+    signal->theData[0] = c_copyGCISlave.m_senderData;
+    sendSignal(m_gcp_save.m_master_ref, GSN_COPY_GCICONF, signal, 1, JBB);
+  }
+  else if (c_copyGCISlave.m_senderRef == cmasterdihref)
+  {
     jam();
     /**
      * Only if same master
      */
     signal->theData[0] = c_copyGCISlave.m_senderData;
     sendSignal(c_copyGCISlave.m_senderRef, GSN_COPY_GCICONF, signal, 1, JBB);
-
   }
   return;
 }//Dbdih::writingCopyGciLab()
@@ -10143,13 +10470,14 @@
   // one global checkpoints between each local checkpoint that we start up.
   /* ----------------------------------------------------------------------- */
   c_lcpState.ctimer = 0;
-  c_lcpState.keepGci = coldgcp;
+  c_lcpState.keepGci = m_micro_gcp.m_old_gci >> 32;
+  c_lcpState.oldestRestorableGci = SYSFILE->oldestRestorableGCI;
+
   /* ----------------------------------------------------------------------- */
   /*       UPDATE THE NEW LATEST LOCAL CHECKPOINT ID.                        */
   /* ----------------------------------------------------------------------- */
   cnoOfActiveTables = 0;
   c_lcpState.setLcpStatus(LCP_CALCULATE_KEEP_GCI, __LINE__);
-  c_lcpState.oldestRestorableGci = SYSFILE->oldestRestorableGCI;
   ndbrequire(((int)c_lcpState.oldestRestorableGci) > 0);
 
   if (ERROR_INSERTED(7011)) {
@@ -10158,6 +10486,7 @@
     sendSignal(CMVMI_REF, GSN_EVENT_REP, signal, 2, JBB);
     return;
   }//if
+
   signal->theData[0] = DihContinueB::ZCALCULATE_KEEP_GCI;
   signal->theData[1] = 0;  /* TABLE ID = 0          */
   signal->theData[2] = 0;  /* FRAGMENT ID = 0       */
@@ -11327,6 +11656,7 @@
   if (local)
     goto dolocal;
 
+#if 0
   switch(cgcpStatus){
   case GCP_PREPARE_SENT:
   {
@@ -11437,6 +11767,7 @@
   }
   case GCP_READY: (void)1;
   }
+#endif
 
 dolocal:  
   ndbout_c("m_copyReason: %d m_waiting: %d",
@@ -11512,7 +11843,7 @@
         SystemError * const sysErr = (SystemError*)&signal->theData[0];
         sysErr->errorCode = SystemError::GCPStopDetected;
         sysErr->errorRef = reference();
-        sysErr->data1 = cgcpStatus;
+        sysErr->data1 = 0; // XXX JONAS cgcpStatus;
         sysErr->data2 = cgcpOrderBlocked;
         sendSignal(ref, GSN_SYSTEM_ERROR, signal, 
                    SystemError::SignalLength, JBA);
@@ -11525,7 +11856,7 @@
     SystemError * const sysErr = (SystemError*)&signal->theData[0];
     sysErr->errorCode = SystemError::GCPStopDetected;
     sysErr->errorRef = reference();
-    sysErr->data1 = cgcpStatus;
+    sysErr->data1 = 0; // XXX JONAS cgcpStatus;
     sysErr->data2 = cgcpOrderBlocked;
     EXECUTE_DIRECT(NDBCNTR, GSN_SYSTEM_ERROR, 
                    signal, SystemError::SignalLength);
@@ -11573,13 +11904,12 @@
     newReplicaPtr.p->lcpStatus[i] = ZINVALID;
   }//for
   newReplicaPtr.p->noCrashedReplicas = 0;
-  newReplicaPtr.p->initialGci = currentgcp;
+  newReplicaPtr.p->initialGci = m_micro_gcp.m_current_gci >> 32;
   for (i = 0; i < 8; i++) {
     newReplicaPtr.p->replicaLastGci[i] = (Uint32)-1;
     newReplicaPtr.p->createGci[i] = 0;
   }//for
-  newReplicaPtr.p->createGci[0] = currentgcp;
-  ndbrequire(currentgcp != 0xF1F1F1F1);
+  newReplicaPtr.p->createGci[0] = m_micro_gcp.m_current_gci >> 32;
   newReplicaPtr.p->nextLcp = 0;
   newReplicaPtr.p->procNode = nodeId;
   newReplicaPtr.p->lcpOngoingFlag = false;
@@ -11784,7 +12114,7 @@
     cverifyQueueCounter--;
     localApiConnectptr.i = cfirstVerifyQueue;
     ptrCheckGuard(localApiConnectptr, capiConnectFileSize, apiConnectRecord);
-    ndbrequire(localApiConnectptr.p->apiGci <= currentgcp);
+    ndbrequire(localApiConnectptr.p->apiGci <= m_micro_gcp.m_current_gci);
     cfirstVerifyQueue = localApiConnectptr.p->nextApi;
     if (cfirstVerifyQueue == RNIL) {
       jam();
@@ -11792,8 +12122,10 @@
       clastVerifyQueue = RNIL;
     }//if
     signal->theData[0] = localApiConnectptr.i;
-    signal->theData[1] = currentgcp;
-    sendSignal(clocaltcblockref, GSN_DIVERIFYCONF, signal, 2, JBB);
+    signal->theData[1] = m_micro_gcp.m_current_gci >> 32;
+    signal->theData[2] = m_micro_gcp.m_current_gci & 0xFFFFFFFF;
+    signal->theData[3] = 0;
+    sendSignal(clocaltcblockref, GSN_DIVERIFYCONF, signal, 4, JBB);
     if (aContinueB == true) {
       jam();
       //-----------------------------------------------------------------------
@@ -12047,6 +12379,8 @@
 	 * VALID LOCAL CHECKPOINT AS THE MINIMUM GCI RECOVERABLE.
 	 *-----------------------------------------------------------------*/
         keepGci = fmgReplicaPtr.p->createGci[0];
+        // XXX Jonas
+        //oldestRestorableGci = fmgReplicaPtr.p->createGci[0];
       }//if
     }//if
     lcpNo = prevLcpNo(lcpNo);
@@ -12139,13 +12473,8 @@
   cfirstDeadNode = RNIL;
   cfirstVerifyQueue = RNIL;
   cgckptflag = false;
-  cgcpDelay = 0;
   cgcpMasterTakeOverState = GMTOS_IDLE; 
   cgcpOrderBlocked = 0;
-  cgcpParticipantState = GCP_PARTICIPANT_READY;
-  cgcpSameCounter = 0;
-  cgcpStartCounter = 0;
-  cgcpStatus = GCP_READY;
 
   clastVerifyQueue = RNIL;
   c_lcpMasterTakeOverState.set(LMTOS_IDLE, __LINE__);
@@ -12168,15 +12497,17 @@
   cmasterNodeId = 0;
   cmasterState = MASTER_IDLE;
   cmasterTakeOverNode = 0;
-  cnewgcp = 0;
   cnoHotSpare = 0;
   cnoOfActiveTables = 0;
   cnoOfNodeGroups = 0;
   c_nextNodeGroup = 0;
   cnoReplicas = 0;
+#if 0
   coldgcp = 0;
   coldGcpId = 0;
   coldGcpStatus = cgcpStatus;
+  cgcpSameCounter = 0;
+#endif
   con_lineNodes = 0;
   creceivedfrag = 0;
   crestartGci = 0;
@@ -12188,13 +12519,13 @@
   cstarttype = (Uint32)-1;
   csystemnodes = 0;
   c_updateToLock = RNIL;
-  currentgcp = 0;
   c_newest_restorable_gci = 0;
   cverifyQueueCounter = 0;
   cwaitLcpSr = false;
   c_nextLogPart = 0;
+  c_nodeStartMaster.blockGcp = false;
 
-  nodeResetStart();
+  nodeResetStart(0);
   c_nodeStartMaster.wait = ZFALSE;
 
   memset(&sysfileData[0], 0, sizeof(sysfileData));
@@ -12219,9 +12550,35 @@
 	      "Only up to four replicas are supported. Check NoOfReplicas.");
   }
 
-  cgcpDelay = 2000;
-  ndb_mgm_get_int_parameter(p, CFG_DB_GCP_INTERVAL, &cgcpDelay);
-  cgcpDelay =  cgcpDelay > 60000 ? 60000 : (cgcpDelay < 10 ? 10 : cgcpDelay);
+  bzero(&m_gcp_save, sizeof(m_gcp_save));
+  bzero(&m_micro_gcp, sizeof(m_micro_gcp));
+  {
+    Uint32 tmp = 2000;
+    //ndb_mgm_get_int_parameter(p, CFG_DB_GCP_INTERVAL, &tmp);
+    tmp = tmp > 60000 ? 60000 : (tmp < 10 ? 10 : tmp);
+    m_gcp_save.m_time_between_gcp = tmp;
+
+    tmp = 20;
+    //ndb_mgm_get_int_parameter(p, CFG_DB_MICRO_GCP_INTERVAL, &tmp);
+    if (tmp)
+    {
+      /**
+       * A value is set for micro gcp...run new protocol when applicable
+       */
+      if (tmp > m_gcp_save.m_time_between_gcp)
+        tmp = m_gcp_save.m_time_between_gcp;
+      if (tmp < 10)
+        tmp = 10;
+      m_micro_gcp.m_time_between_gcp = tmp;
+      m_micro_gcp.m_enabled = true;
+
+      if (m_micro_gcp.m_enabled == false)
+      {
+        jam();
+        m_micro_gcp.m_time_between_gcp = m_gcp_save.m_time_between_gcp;
+      }
+    }
+  }
 }//Dbdih::initCommonData()
 
 void Dbdih::initFragstore(FragmentstorePtr fragPtr) 
@@ -12262,9 +12619,11 @@
     /* FIRST GCP = 1 ALREADY SET BY LQH */
     nodePtr.i = nodePtr.p->nextNode;
   } while (nodePtr.i != RNIL);
-  coldgcp = 1;
-  currentgcp = 2;
-  cnewgcp = 2;
+
+  m_micro_gcp.m_old_gci = Uint64(1) << 32;
+  m_micro_gcp.m_current_gci = Uint64(2) << 32;
+  m_micro_gcp.m_new_gci = Uint64(2) << 32;
+  m_micro_gcp.m_next_gci = m_micro_gcp.m_new_gci + 1;
   crestartGci = 1;
   c_newest_restorable_gci = 1;
 
@@ -12934,15 +13293,26 @@
 /*       SET OF VARIABLES CONTROLLING THE START AND INDICATING ONGOING   */
 /*       START OF A NEW NODE.                                            */
 /*************************************************************************/
-void Dbdih::nodeResetStart()
+void Dbdih::nodeResetStart(Signal *signal)
 {
   jam();
+  bool startGCP = c_nodeStartMaster.blockGcp;
+
   c_nodeStartMaster.startNode = RNIL;
   c_nodeStartMaster.failNr = cfailurenr;
   c_nodeStartMaster.activeState = false;
   c_nodeStartMaster.blockGcp = false;
   c_nodeStartMaster.blockLcp = false;
   c_nodeStartMaster.m_outstandingGsn = 0;
+
+  if (startGCP)
+  {
+    jam();
+    ndbrequire(isMaster());
+    ndbrequire(m_micro_gcp.m_master_state == MicroGcp::M_GCP_IDLE);
+    signal->theData[0] = DihContinueB::ZSTART_GCP;
+    sendSignal(reference(), GSN_CONTINUEB, signal, 1, JBB);
+  }
 }//Dbdih::nodeResetStart()
 
 void Dbdih::openFileRw(Signal* signal, FileRecordPtr filePtr) 
@@ -14087,13 +14457,14 @@
 /*************************************************************************/
 void Dbdih::startGcp(Signal* signal) 
 {
-  cgcpStatus = GCP_READY;
+#if 0
   coldGcpStatus = cgcpStatus;
   coldGcpId = cnewgcp;
   cgcpSameCounter = 0;
+#endif
+
   signal->theData[0] = DihContinueB::ZSTART_GCP;
-  signal->theData[1] = 0;
-  sendSignal(reference(), GSN_CONTINUEB, signal, 2, JBB);
+  sendSignal(reference(), GSN_CONTINUEB, signal, 1, JBB);
   signal->theData[0] = DihContinueB::ZCHECK_GCP_STOP;
   sendSignalWithDelay(reference(), GSN_CONTINUEB, signal, 100, 1);
 }//Dbdih::startGcp()
@@ -14230,12 +14601,12 @@
   if (arg == DumpStateOrd::DihDumpNodeRestartInfo) {
     infoEvent("c_nodeStartMaster.blockLcp = %d, c_nodeStartMaster.blockGcp = %d, c_nodeStartMaster.wait = %d",
 	      c_nodeStartMaster.blockLcp, c_nodeStartMaster.blockGcp, c_nodeStartMaster.wait);
-    infoEvent("cstartGcpNow = %d, cgcpStatus = %d",
-              cstartGcpNow, cgcpStatus);
+    infoEvent("cstartGcpNow = %d",
+              cstartGcpNow);
     infoEvent("cfirstVerifyQueue = %d, cverifyQueueCounter = %d",
               cfirstVerifyQueue, cverifyQueueCounter);
-    infoEvent("cgcpOrderBlocked = %d, cgcpStartCounter = %d",
-              cgcpOrderBlocked, cgcpStartCounter);
+    infoEvent("cgcpOrderBlocked = %d",
+              cgcpOrderBlocked);
   }//if  
   if (arg == DumpStateOrd::DihDumpNodeStatusInfo) {
     NodeRecordPtr localNodePtr;
@@ -14278,10 +14649,13 @@
   }
   
   if (signal->theData[0] == 7000) {
-    infoEvent("ctimer = %d, cgcpParticipantState = %d, cgcpStatus = %d",
-              c_lcpState.ctimer, cgcpParticipantState, cgcpStatus);
-    infoEvent("coldGcpStatus = %d, coldGcpId = %d, cmasterState = %d",
-              coldGcpStatus, coldGcpId, cmasterState);
+    infoEvent("ctimer = %d",
+              c_lcpState.ctimer);
+    infoEvent("cmasterState = %d", cmasterState);
+#if 0
+    infoEvent("coldGcpStatus = %d, coldGcpId = %d cgcpSameCounter = %d",
+              coldGcpStatus, coldGcpId, cgcpSameCounter);
+#endif
     infoEvent("cmasterTakeOverNode = %d, ctcCounter = %d",
               cmasterTakeOverNode, c_lcpState.ctcCounter);
   }//if  
@@ -14291,12 +14665,12 @@
     infoEvent("c_lcpState.lcpStatus = %d, clcpStopGcp = %d",
               c_lcpState.lcpStatus, 
 	      c_lcpState.lcpStopGcp);
-    infoEvent("cgcpStartCounter = %d, cimmediateLcpStart = %d",
-              cgcpStartCounter, c_lcpState.immediateLcpStart);
+    infoEvent("cimmediateLcpStart = %d",
+              c_lcpState.immediateLcpStart);
   }//if  
   if (signal->theData[0] == 7002) {
-    infoEvent("cnoOfActiveTables = %d, cgcpDelay = %d",
-              cnoOfActiveTables, cgcpDelay);
+    infoEvent("cnoOfActiveTables = %d",
+              cnoOfActiveTables);
     infoEvent("cdictblockref = %d, cfailurenr = %d",
               cdictblockref, cfailurenr);
     infoEvent("con_lineNodes = %d, reference() = %d, creceivedfrag = %d",
@@ -14307,16 +14681,14 @@
               cfirstAliveNode, cgckptflag);
     infoEvent("clocallqhblockref = %d, clocaltcblockref = %d, cgcpOrderBlocked = %d",
               clocallqhblockref, clocaltcblockref, cgcpOrderBlocked);
-    infoEvent("cstarttype = %d, csystemnodes = %d, currentgcp = %d",
-              cstarttype, csystemnodes, currentgcp);
+    infoEvent("cstarttype = %d, csystemnodes = %d",
+              cstarttype, csystemnodes);
   }//if  
   if (signal->theData[0] == 7004) {
-    infoEvent("cmasterdihref = %d, cownNodeId = %d, cnewgcp = %d",
-              cmasterdihref, cownNodeId, cnewgcp);
+    infoEvent("cmasterdihref = %d, cownNodeId = %d",
+              cmasterdihref, cownNodeId);
     infoEvent("cndbStartReqBlockref = %d, cremainingfrags = %d",
               cndbStartReqBlockref, cremainingfrags);
-    infoEvent("cntrlblockref = %d, cgcpSameCounter = %d, coldgcp = %d",
-              cntrlblockref, cgcpSameCounter, coldgcp);
   }//if  
   if (signal->theData[0] == 7005) {
     infoEvent("crestartGci = %d",
@@ -14565,18 +14937,20 @@
 
   if (arg == DumpStateOrd::DihSetTimeBetweenGcp)
   {
+    Uint32 tmp = 0;
     if (signal->getLength() == 1)
     {
       const ndb_mgm_configuration_iterator * p = 
 	m_ctx.m_config.getOwnConfigIterator();
       ndbrequire(p != 0);
-      ndb_mgm_get_int_parameter(p, CFG_DB_GCP_INTERVAL, &cgcpDelay);
+      ndb_mgm_get_int_parameter(p, CFG_DB_GCP_INTERVAL, &tmp);
     }
     else
     {
-      cgcpDelay = signal->theData[1];
+      tmp = signal->theData[1];
     }
-    g_eventLogger.info("Setting time between gcp : %d", cgcpDelay);
+    m_gcp_save.m_time_between_gcp = tmp;
+    g_eventLogger.info("Setting time between gcp : %d", tmp);
   }
 
   if (arg == 7021 && signal->getLength() == 2)
@@ -15334,7 +15708,7 @@
   if(requestType == WaitGCPReq::CurrentGCI) {
     jam();
     conf->senderData = senderData;
-    conf->gcp = cnewgcp;
+    conf->gcp = m_micro_gcp.m_current_gci >> 32;
     conf->blockStatus = cgcpOrderBlocked;
     sendSignal(senderRef, GSN_WAIT_GCP_CONF, signal, 
 	       WaitGCPConf::SignalLength, JBB);
@@ -15345,7 +15719,7 @@
   {
     jam();
     conf->senderData = senderData;
-    conf->gcp = cnewgcp;
+    conf->gcp = m_micro_gcp.m_current_gci >> 32;
     conf->blockStatus = cgcpOrderBlocked;
     sendSignal(senderRef, GSN_WAIT_GCP_CONF, signal, 
 	       WaitGCPConf::SignalLength, JBB);
@@ -15357,7 +15731,7 @@
   {
     jam();
     conf->senderData = senderData;
-    conf->gcp = cnewgcp;
+    conf->gcp = m_micro_gcp.m_current_gci >> 32;
     conf->blockStatus = cgcpOrderBlocked;
     sendSignal(senderRef, GSN_WAIT_GCP_CONF, signal, 
 	       WaitGCPConf::SignalLength, JBB);
@@ -15372,10 +15746,10 @@
     jam();
 
     if((requestType == WaitGCPReq::CompleteIfRunning) &&
-       (cgcpStatus == GCP_READY)) {
+       (m_gcp_save.m_master_state == GcpSave::GCP_SAVE_IDLE)) {
       jam();
       conf->senderData = senderData;
-      conf->gcp = coldgcp;
+      conf->gcp = m_micro_gcp.m_old_gci >> 32;
       conf->blockStatus = cgcpOrderBlocked;
       sendSignal(senderRef, GSN_WAIT_GCP_CONF, signal, 
 		 WaitGCPConf::SignalLength, JBB);
@@ -15395,7 +15769,7 @@
     ptr.p->clientData = senderData;
     
     if((requestType == WaitGCPReq::CompleteForceStart) && 
-       (cgcpStatus == GCP_READY)) {
+       (m_gcp_save.m_master_state == GcpSave::GCP_SAVE_IDLE)) {
       jam();
       cstartGcpNow = true;
     }//if
@@ -15519,7 +15893,7 @@
 {
   jam();
   WaitGCPConf* const conf = (WaitGCPConf*)&signal->theData[0];
-  conf->gcp = coldgcp;
+  conf->gcp = m_micro_gcp.m_old_gci >> 32;
   
   WaitGCPMasterPtr ptr;
   c_waitGCPMasterList.first(ptr);  
@@ -15631,7 +16005,6 @@
 
 Dbdih::NodeRecord::NodeRecord(){
   m_nodefailSteps.clear();
-  gcpstate = NodeRecord::READY;
 
   activeStatus = Sysfile::NS_NotDefined;
   recNODE_FAILREP = ZFALSE;
@@ -15769,3 +16142,85 @@
   sendSignal(dictMasterRef, GSN_DICT_UNLOCK_ORD, signal,
       DictUnlockOrd::SignalLength, JBB);
 }
+
+#ifdef ERROR_INSERT
+void
+Dbdih::sendToRandomNodes(const char * msg,
+                         Signal* signal,
+                         SignalCounter* counter,
+                         SendFunction fun,
+                         Uint32 block,
+                         Uint32 gsn,
+                         Uint32 len,
+                         JobBufferLevel level)
+{
+
+  if (counter)
+    counter->clearWaitingFor();
+
+  Vector<Uint32> nodes;
+  NodeRecordPtr nodePtr;
+  nodePtr.i = cfirstAliveNode;
+  do {
+    jam();
+    ptrCheckGuard(nodePtr, MAX_NDB_NODES, nodeRecord);
+    if (nodePtr.i != getOwnNodeId())
+    {
+      nodes.push_back(nodePtr.i);
+    }
+    nodePtr.i = nodePtr.p->nextNode;
+  } while (nodePtr.i != RNIL);
+
+
+  NdbNodeBitmask masked;
+  Uint32 cnt = nodes.size();
+  if (cnt <= 1)
+  {
+    goto do_send;
+  }
+
+  Uint32 remove = (rand() % cnt);
+  if (remove == 0)
+    remove = 1;
+
+  for (Uint32 i = 0; i<remove; i++)
+  {
+    Uint32 i = rand() % nodes.size();
+    masked.set(nodes[i]);
+    nodes.erase(i);
+  }
+
+do_send:
+  char bufpos = 0;
+  char buf[256];
+
+  nodePtr.i = cfirstAliveNode;
+  do {
+    jam();
+    ptrCheckGuard(nodePtr, MAX_NDB_NODES, nodeRecord);
+    if (counter)
+      counter->setWaitingFor(nodePtr.i);
+    if (!masked.get(nodePtr.i))
+    {
+      if (fun)
+      {
+        (this->*fun)(signal, nodePtr.i);
+      }
+      else
+      {
+        Uint32 ref = numberToRef(block, nodePtr.i);
+        sendSignal(ref, gsn, signal, len, level);
+      }
+      BaseString::snprintf(buf+bufpos, sizeof(buf)-bufpos, "%u ", nodePtr.i);
+    }
+    else
+    {
+      BaseString::snprintf(buf+bufpos, sizeof(buf)-bufpos, "[%u] ", nodePtr.i);
+    }
+    bufpos = strlen(buf);
+    nodePtr.i = nodePtr.p->nextNode;
+  } while (nodePtr.i != RNIL);
+  infoEvent("%s %s", msg, buf);
+}
+
+#endif

--- 1.80/storage/ndb/src/kernel/blocks/dblqh/Dblqh.hpp	2007-08-24 16:17:57 +02:00
+++ 1.81/storage/ndb/src/kernel/blocks/dblqh/Dblqh.hpp	2007-08-24 16:17:57 +02:00
@@ -1955,7 +1955,8 @@
     UintR firstTupkeybuf;
     UintR fragmentid;
     UintR fragmentptr;
-    UintR gci;
+    UintR gci_hi;
+    UintR gci_lo;
     UintR hashValue;
     UintR lastTupkeybuf;
     UintR lastAttrinbuf;
@@ -2467,7 +2468,7 @@
   void closeScanLab(Signal* signal);
   void nextScanConfLoopLab(Signal* signal);
   void scanNextLoopLab(Signal* signal);
-  void commitReqLab(Signal* signal, Uint32 gci);
+  void commitReqLab(Signal* signal, Uint32 gci_hi, Uint32 gci_lo);
   void completeTransLastLab(Signal* signal);
   void tupScanCloseConfLab(Signal* signal);
   void tupCopyCloseConfLab(Signal* signal);
@@ -2590,7 +2591,8 @@
   {
     Uint32 m_ptr_i;
     Uint32 m_tup_frag_ptr_i;
-    Uint32 m_gci;
+    Uint32 m_gci_hi;
+    Uint32 m_gci_lo;
     Uint32 m_page_id;
     Local_key m_disk_ref;
   };
@@ -2902,7 +2904,7 @@
   
 public:
   bool is_same_trans(Uint32 opId, Uint32 trid1, Uint32 trid2);
-  void get_op_info(Uint32 opId, Uint32 *hash, Uint32* gci);
+  void get_op_info(Uint32 opId, Uint32 *hash, Uint32* gci_hi, Uint32* gci_lo);
   void accminupdate(Signal*, Uint32 opPtrI, const Local_key*);
 
   /**
@@ -3001,13 +3003,14 @@
 
 inline
 void
-Dblqh::get_op_info(Uint32 opId, Uint32 *hash, Uint32* gci)
+Dblqh::get_op_info(Uint32 opId, Uint32 *hash, Uint32* gci_hi, Uint32* gci_lo)
 {
   TcConnectionrecPtr regTcPtr;  
   regTcPtr.i= opId;
   ptrCheckGuard(regTcPtr, ctcConnectrecFileSize, tcConnectionrec);
-  *hash= regTcPtr.p->hashValue;
-  *gci= regTcPtr.p->gci;
+  *hash = regTcPtr.p->hashValue;
+  *gci_hi = regTcPtr.p->gci_hi;
+  *gci_lo = regTcPtr.p->gci_lo;
 }
 
 #include "../dbacc/Dbacc.hpp"

--- 1.186/storage/ndb/src/kernel/blocks/dblqh/DblqhMain.cpp	2007-08-24 16:17:57 +02:00
+++ 1.187/storage/ndb/src/kernel/blocks/dblqh/DblqhMain.cpp	2007-08-24 16:17:57 +02:00
@@ -2475,13 +2475,15 @@
       sig1 = TpackedData[Tstep + 1];
       sig2 = TpackedData[Tstep + 2];
       sig3 = TpackedData[Tstep + 3];
+      sig4 = TpackedData[Tstep + 4];
       signal->theData[0] = sig0;
       signal->theData[1] = sig1;
       signal->theData[2] = sig2;
       signal->theData[3] = sig3;
-      signal->header.theLength = 4;
+      signal->theData[4] = sig4;
+      signal->header.theLength = 5;
       execCOMMIT(signal);
-      Tstep += 4;
+      Tstep += 5;
       break;
     case ZCOMPLETE:
       jam();
@@ -2809,7 +2811,7 @@
   HostRecordPtr Thostptr;
   Thostptr.i = refToNode(alqhBlockref);
   ptrCheckGuard(Thostptr, chostFileSize, hostRecord);
-  if (Thostptr.p->noOfPackedWordsLqh > 21) {
+  if (Thostptr.p->noOfPackedWordsLqh > 25 - 5) {
     jam();
     sendPackedSignalLqh(signal, Thostptr.p);
   } else {
@@ -2818,14 +2820,16 @@
   }//if
   Uint32 pos = Thostptr.p->noOfPackedWordsLqh;
   Uint32 ptrAndType = tcConnectptr.p->clientConnectrec | (ZCOMMIT << 28);
-  Uint32 gci = tcConnectptr.p->gci;
+  Uint32 gci_hi = tcConnectptr.p->gci_hi;
+  Uint32 gci_lo = tcConnectptr.p->gci_lo;
   Uint32 transid1 = tcConnectptr.p->transid[0];
   Uint32 transid2 = tcConnectptr.p->transid[1];
   Thostptr.p->packedWordsLqh[pos] = ptrAndType;
-  Thostptr.p->packedWordsLqh[pos + 1] = gci;
+  Thostptr.p->packedWordsLqh[pos + 1] = gci_hi;
   Thostptr.p->packedWordsLqh[pos + 2] = transid1;
   Thostptr.p->packedWordsLqh[pos + 3] = transid2;
-  Thostptr.p->noOfPackedWordsLqh = pos + 4;
+  Thostptr.p->packedWordsLqh[pos + 4] = gci_lo;
+  Thostptr.p->noOfPackedWordsLqh = pos + 5;
 }//Dblqh::sendCommitLqh()
 
 void Dblqh::sendCompleteLqh(Signal* signal, BlockReference alqhBlockref)
@@ -3343,7 +3347,8 @@
   locTcConnectptr.p->tcTimer = cLqhTimeOutCount;
   locTcConnectptr.p->tableref = RNIL;
   locTcConnectptr.p->savePointId = 0;
-  locTcConnectptr.p->gci = 0;
+  locTcConnectptr.p->gci_hi = 0;
+  locTcConnectptr.p->gci_lo = 0;
   cfirstfreeTcConrec = nextTc;
   tcConnectptr = locTcConnectptr;
   locTcConnectptr.p->connectState = TcConnectionrec::CONNECTED;
@@ -3620,7 +3625,8 @@
 
   sig2 = lqhKeyReq->variableData[nextPos + 0];
   sig3 = cnewestGci;
-  regTcPtr->gci = LqhKeyReq::getGCIFlag(Treqinfo) ? sig2 : sig3;
+  regTcPtr->gci_hi = LqhKeyReq::getGCIFlag(Treqinfo) ? sig2 : sig3;
+  regTcPtr->gci_lo = 0;
   nextPos += LqhKeyReq::getGCIFlag(Treqinfo);
   
   if (LqhKeyReq::getRowidFlag(Treqinfo))
@@ -4128,7 +4134,7 @@
       jam();
       if (TRACENR_FLAG)
 	TRACENR(" UPDATE_GCI" << endl); 
-      c_tup->nr_update_gci(fragPtr, &regTcPtr.p->m_row_id, regTcPtr.p->gci);
+      c_tup->nr_update_gci(fragPtr, &regTcPtr.p->m_row_id, regTcPtr.p->gci_hi);
       goto update_gci_ignore;
     }
     
@@ -4332,7 +4338,7 @@
   ndbrequire(regTcPtr.p->m_dealloc == 1);  
   int ret = c_tup->nr_delete(signal, regTcPtr.i, 
 			     fragPtr.p->tupFragptr, &regTcPtr.p->m_row_id, 
-			     regTcPtr.p->gci);
+			     regTcPtr.p->gci_hi);
   jamEntry();
   
   if (ret)
@@ -4365,7 +4371,8 @@
   Ptr<Fragrecord> fragPtr;
   c_fragment_pool.getPtr(fragPtr, tcPtr.p->fragmentptr);  
 
-  op->m_gci = tcPtr.p->gci;
+  op->m_gci_hi = tcPtr.p->gci_hi;
+  op->m_gci_lo = tcPtr.p->gci_lo;
   op->m_tup_frag_ptr_i = fragPtr.p->tupFragptr;
 
   ndbrequire(tcPtr.p->activeCreat == Fragrecord::AC_NR_COPY);
@@ -5372,7 +5379,7 @@
     nextPos += 4;
   }//if
 
-  sig0 = regTcPtr->gci;
+  sig0 = regTcPtr->gci_hi;
   Local_key tmp = regTcPtr->m_row_id;
   
   lqhKeyReq->variableData[nextPos + 0] = tmp.m_page_no;
@@ -5969,9 +5976,10 @@
   TcConnectionrec *regTcConnectionrec = tcConnectionrec;
   Uint32 ttcConnectrecFileSize = ctcConnectrecFileSize;
   Uint32 tcIndex = signal->theData[0];
-  Uint32 gci = signal->theData[1];
+  Uint32 gci_hi = signal->theData[1];
   Uint32 transid1 = signal->theData[2];
   Uint32 transid2 = signal->theData[3];
+  Uint32 gci_lo = signal->theData[4];
   jamEntry();
   if (tcIndex >= ttcConnectrecFileSize) {
     errorReport(signal, 0);
@@ -5979,12 +5987,12 @@
   }//if
   if (ERROR_INSERTED(5011)) {
     CLEAR_ERROR_INSERT_VALUE;
-    sendSignalWithDelay(cownref, GSN_COMMIT, signal, 2000, 4);
+    sendSignalWithDelay(cownref, GSN_COMMIT, signal, 2000,signal->getLength());
     return;
   }//if
   if (ERROR_INSERTED(5012)) {
     SET_ERROR_INSERT_VALUE(5017);
-    sendSignalWithDelay(cownref, GSN_COMMIT, signal, 2000, 4);
+    sendSignalWithDelay(cownref, GSN_COMMIT, signal, 2000,signal->getLength());
     return;
   }//if
   tcConnectptr.i = tcIndex;
@@ -5995,7 +6003,7 @@
     TcConnectionrec * const regTcPtr = tcConnectptr.p;
     TRACE_OP(regTcPtr, "COMMIT");
     
-    commitReqLab(signal, gci);
+    commitReqLab(signal, gci_hi, gci_lo);
     return;
   }//if
   warningReport(signal, 1);
@@ -6013,16 +6021,18 @@
   jamEntry();
   Uint32 reqPtr = signal->theData[0];
   BlockReference reqBlockref = signal->theData[1];
-  Uint32 gci = signal->theData[2];
+  Uint32 gci_hi = signal->theData[2];
   Uint32 transid1 = signal->theData[3];
   Uint32 transid2 = signal->theData[4];
   Uint32 tcOprec = signal->theData[6];
+  Uint32 gci_lo = signal->theData[7];
   if (ERROR_INSERTED(5004)) {
     systemErrorLab(signal, __LINE__);
   }
   if (ERROR_INSERTED(5017)) {
     CLEAR_ERROR_INSERT_VALUE;
-    sendSignalWithDelay(cownref, GSN_COMMITREQ, signal, 2000, 7);
+    sendSignalWithDelay(cownref, GSN_COMMITREQ, signal, 2000,
+                        signal->getLength());
     return;
   }//if
   if (findTransaction(transid1,
@@ -6043,7 +6053,7 @@
     regTcPtr->reqBlockref = reqBlockref;
     regTcPtr->reqRef = reqPtr;
     regTcPtr->abortState = TcConnectionrec::REQ_FROM_TC;
-    commitReqLab(signal, gci);
+    commitReqLab(signal, gci_hi, gci_lo);
     return;
     break;
   case TcConnectionrec::COMMITTED:
@@ -6269,12 +6279,13 @@
 /* -------                       COMMIT PHASE                        ------- */
 /*                                                                           */
 /* ------------------------------------------------------------------------- */
-void Dblqh::commitReqLab(Signal* signal, Uint32 gci) 
+void Dblqh::commitReqLab(Signal* signal, Uint32 gci_hi, Uint32 gci_lo)
 {
   TcConnectionrec * const regTcPtr = tcConnectptr.p;
   TcConnectionrec::LogWriteState logWriteState = regTcPtr->logWriteState;
   TcConnectionrec::TransactionState transState = regTcPtr->transactionState;
-  regTcPtr->gci = gci; 
+  regTcPtr->gci_hi = gci_hi;
+  regTcPtr->gci_lo = gci_lo;
   if (transState == TcConnectionrec::PREPARED) {
     if (logWriteState == TcConnectionrec::WRITTEN) {
       jam();
@@ -6282,8 +6293,9 @@
       TcConnectionrecPtr saveTcPtr = tcConnectptr;
       Uint32 blockNo = refToBlock(regTcPtr->tcTupBlockref);
       signal->theData[0] = regTcPtr->tupConnectrec;
-      signal->theData[1] = gci;
-      EXECUTE_DIRECT(blockNo, GSN_TUP_WRITELOG_REQ, signal, 2);
+      signal->theData[1] = gci_hi;
+      signal->theData[2] = gci_lo;
+      EXECUTE_DIRECT(blockNo, GSN_TUP_WRITELOG_REQ, signal, 3);
       jamEntry();
       if (regTcPtr->transactionState == TcConnectionrec::LOG_COMMIT_QUEUED) {
         jam();
@@ -6340,17 +6352,19 @@
   tcConnectptr.i = signal->theData[0];
   ptrCheckGuard(tcConnectptr, ctcConnectrecFileSize, tcConnectionrec);
   TcConnectionrec * const regTcPtr = tcConnectptr.p;
-  Uint32 gci = signal->theData[1];
+  Uint32 gci_hi = signal->theData[1];
+  Uint32 gci_lo = signal->theData[2];
   Uint32 newestGci = cnewestGci;
   TcConnectionrec::LogWriteState logWriteState = regTcPtr->logWriteState;
   TcConnectionrec::TransactionState transState = regTcPtr->transactionState;
-  regTcPtr->gci = gci;
-  if (gci > newestGci) {
+  regTcPtr->gci_hi = gci_hi;
+  regTcPtr->gci_lo = gci_lo;
+  if (gci_hi > newestGci) {
     jam();
 /* ------------------------------------------------------------------------- */
 /*       KEEP TRACK OF NEWEST GLOBAL CHECKPOINT THAT LQH HAS HEARD OF.       */
 /* ------------------------------------------------------------------------- */
-    cnewestGci = gci;
+    cnewestGci = gci_hi;
   }//if
   if (logWriteState == TcConnectionrec::WRITTEN) {
 /*---------------------------------------------------------------------------*/
@@ -6461,9 +6475,10 @@
       Uint32 tup = refToBlock(regTcPtr.p->tcTupBlockref);
       jam();
       tupCommitReq->opPtr = sig0;
-      tupCommitReq->gci = regTcPtr.p->gci;
+      tupCommitReq->gci_hi = regTcPtr.p->gci_hi;
       tupCommitReq->hashValue = regTcPtr.p->hashValue;
       tupCommitReq->diskpage = RNIL;
+      tupCommitReq->gci_lo = regTcPtr.p->gci_lo;
       EXECUTE_DIRECT(tup, GSN_TUP_COMMITREQ, signal, 
 		     TupCommitReq::SignalLength);
 
@@ -6568,13 +6583,13 @@
   Uint32 dirtyOp = tcPtrP->dirtyOp;
   Uint32 seqNoReplica = tcPtrP->seqNoReplica;
   Uint32 activeCreat = tcPtrP->activeCreat;
-  if (tcPtrP->gci > regFragptr->newestGci) {
+  if (tcPtrP->gci_hi > regFragptr->newestGci) {
     jam();
 /* ------------------------------------------------------------------------- */
 /*IT IS THE FIRST TIME THIS GLOBAL CHECKPOINT IS INVOLVED IN UPDATING THIS   */
 /*FRAGMENT. UPDATE THE VARIABLE THAT KEEPS TRACK OF NEWEST GCI IN FRAGMENT   */
 /* ------------------------------------------------------------------------- */
-    regFragptr->newestGci = tcPtrP->gci;
+    regFragptr->newestGci = tcPtrP->gci_hi;
   }//if
   if (dirtyOp != ZTRUE) 
   {
@@ -10499,8 +10514,9 @@
     ndbrequire(nextScanConf->accOperationPtr == RNIL);
     initCopyTc(signal, ZDELETE);
     set_acc_ptr_in_scan_record(scanptr.p, 0, RNIL);
-    tcConP->gci = nextScanConf->gci;
-    
+    tcConP->gci_hi = nextScanConf->gci;
+    tcConP->gci_lo = 0;
+
     tcConP->primKeyLen = 0;
     tcConP->totSendlenAi = 0;
     tcConP->connectState = TcConnectionrec::COPY_CONNECTED;
@@ -10650,7 +10666,8 @@
   Uint32* tmp = signal->getDataPtrSend()+24;
   Uint32 len= tcConnectptr.p->primKeyLen = readPrimaryKeys(scanP, tcConP, tmp);
   
-  tcConP->gci = tmp[len];
+  tcConP->gci_hi = tmp[len];
+  tcConP->gci_lo = 0;
   // Calculate hash (no need to linearies key)
   if (g_key_descriptor_pool.getPtr(tableId)->hasCharAttr)
   {
@@ -12113,9 +12130,7 @@
   jamEntry();
   const GCPSaveReq * const saveReq = (GCPSaveReq *)&signal->theData[0];
 
-  if (ERROR_INSERTED(5000)) {
-    systemErrorLab(signal, __LINE__);
-  }
+  CRASH_INSERTION(5000);
 
   if (ERROR_INSERTED(5007)){
     CLEAR_ERROR_INSERT_VALUE;
@@ -15274,7 +15289,7 @@
       tcConnectptr.i = logPartPtr.p->logTcConrec;
       ptrCheckGuard(tcConnectptr, ctcConnectrecFileSize, tcConnectionrec);
       readCommitLog(signal, &commitLogRecord);
-      if (tcConnectptr.p->gci > crestartNewestGci) {
+      if (tcConnectptr.p->gci_hi > crestartNewestGci) {
         jam();
 /*---------------------------------------------------------------------------*/
 /* THIS LOG RECORD MUST BE IGNORED. IT IS PART OF A GLOBAL CHECKPOINT WHICH  */
@@ -16549,8 +16564,8 @@
 	     i < fragptr.p->execSrNoReplicas; 
 	     i++) {
           jam();
-          if (tcConnectptr.p->gci >= fragptr.p->execSrStartGci[i]) {
-            if (tcConnectptr.p->gci <= fragptr.p->execSrLastGci[i]) {
+          if (tcConnectptr.p->gci_hi >= fragptr.p->execSrStartGci[i]) {
+            if (tcConnectptr.p->gci_hi <= fragptr.p->execSrLastGci[i]) {
               jam();
               logPartPtr.p->execSrExecuteIndex = i;
               return ZOK;
@@ -17816,7 +17831,8 @@
     commitLogRecord->startPageNo = logPagePtr.p->logPageWord[trclPageIndex + 4];
     commitLogRecord->startPageIndex = logPagePtr.p->logPageWord[trclPageIndex + 5];
     commitLogRecord->stopPageNo = logPagePtr.p->logPageWord[trclPageIndex + 6];
-    tcConnectptr.p->gci = logPagePtr.p->logPageWord[trclPageIndex + 7];
+    tcConnectptr.p->gci_hi = logPagePtr.p->logPageWord[trclPageIndex + 7];
+    tcConnectptr.p->gci_lo = 0;
     logPagePtr.p->logPageWord[ZCURR_PAGE_INDEX] = 
                             (trclPageIndex + ZCOMMIT_LOG_SIZE) - 1;
   } else {
@@ -17828,7 +17844,8 @@
     commitLogRecord->startPageNo = readLogword(signal);
     commitLogRecord->startPageIndex = readLogword(signal);
     commitLogRecord->stopPageNo = readLogword(signal);
-    tcConnectptr.p->gci = readLogword(signal);
+    tcConnectptr.p->gci_hi = readLogword(signal);
+    tcConnectptr.p->gci_lo = 0;
   }//if
   tcConnectptr.p->transid[0] = logPartPtr.i + 65536;  
   tcConnectptr.p->transid[1] = (DBLQH << 20) + (cownNodeid << 8);  
@@ -18433,7 +18450,7 @@
   lqhTransConf->transId2        = tcConnectptr.p->transid[1];
   lqhTransConf->oldTcOpRec      = tcConnectptr.p->tcOprec;
   lqhTransConf->requestInfo     = reqInfo;
-  lqhTransConf->gci             = tcConnectptr.p->gci;
+  lqhTransConf->gci             = tcConnectptr.p->gci_hi;
   lqhTransConf->nextNodeId1     = tcConnectptr.p->nextReplica;
   lqhTransConf->nextNodeId2     = tcConnectptr.p->nodeAfterNext[0];
   lqhTransConf->nextNodeId3     = tcConnectptr.p->nodeAfterNext[1];
@@ -18541,7 +18558,7 @@
   Uint32 startPageNo = regTcPtr->logStartPageNo;
   Uint32 pageIndex = regTcPtr->logStartPageIndex;
   Uint32 stopPageNo = regTcPtr->logStopPageNo;
-  Uint32 gci = regTcPtr->gci;
+  Uint32 gci = regTcPtr->gci_hi;
   logFilePtr.p->remainingWordsInMbyte = twclTmp - ZCOMMIT_LOG_SIZE;
 
   if ((twclLogPos + ZCOMMIT_LOG_SIZE) >= ZPAGE_SIZE) {
@@ -19422,7 +19439,8 @@
 	   << " lastTupkeybuf = " << tcRec.p->lastTupkeybuf
 	   << " hashValue = " << tcRec.p->hashValue
 	   << endl;
-    ndbout << " gci = " << tcRec.p->gci
+    ndbout << " gci_hi = " << tcRec.p->gci_hi
+           << " gci_lo = " << tcRec.p->gci_lo
 	   << " fragmentptr = " << tcRec.p->fragmentptr
 	   << " fragmentid = " << tcRec.p->fragmentid
 	   << " firstTupkeybuf = " << tcRec.p->firstTupkeybuf

--- 1.59/storage/ndb/src/kernel/blocks/dbtc/Dbtc.hpp	2007-08-24 16:17:57 +02:00
+++ 1.60/storage/ndb/src/kernel/blocks/dbtc/Dbtc.hpp	2007-08-24 16:17:57 +02:00
@@ -663,7 +663,7 @@
     UintR nextApiConnect;
     BlockReference ndbapiBlockref;
     UintR apiCopyRecord;
-    UintR globalcheckpointid;
+    Uint64 globalcheckpointid;
     
     //---------------------------------------------------
     // Second 64 byte cache line starts. First 16 byte
@@ -1248,13 +1248,13 @@
   /*       GCP RECORD ALIGNED TO BE 32 BYTES                                 */
   /*************************************************************************>*/
   struct GcpRecord {
+    Uint16 gcpUnused0;
+    Uint16 gcpNomoretransRec;
     UintR gcpUnused1[2];	/* p2c: Not used */
     UintR firstApiConnect;
     UintR lastApiConnect;
-    UintR gcpId;
     UintR nextGcp;
-    UintR gcpUnused2;	/* p2c: Not used */
-    Uint16 gcpNomoretransRec;
+    Uint64 gcpId;
   }; /* p2c: size = 32 bytes */
   
   typedef Ptr<GcpRecord> GcpRecordPtr;
@@ -1433,9 +1433,9 @@
   void close_scan_req_send_conf(Signal*, ScanRecordPtr);
   
   void checkGcp(Signal* signal);
-  void commitGciHandling(Signal* signal, UintR Tgci);
+  void commitGciHandling(Signal* signal, Uint64 Tgci);
   void copyApi(Signal* signal);
-  void DIVER_node_fail_handling(Signal* signal, UintR Tgci);
+  void DIVER_node_fail_handling(Signal* signal, Uint64 Tgci);
   void gcpTcfinished(Signal* signal);
   void handleGcp(Signal* signal);
   void hash(Signal* signal);
@@ -1680,7 +1680,7 @@
   UintR ctcTimer;
 
   ApiConnectRecordPtr tmpApiConnectptr;
-  UintR tcheckGcpId;
+  Uint64 tcheckGcpId;
 
   struct TransCounters {
     TransCounters() {}
@@ -1797,7 +1797,7 @@
   Uint8 tcurrentReplicaNo;
   Uint8 tpad1;
 
-  UintR tgci;
+  Uint64 tgci;
   UintR tapplRef;
   UintR tapplOprec;
 

--- 1.158/storage/ndb/src/kernel/blocks/dbtc/DbtcMain.cpp	2007-08-24 16:17:57 +02:00
+++ 1.159/storage/ndb/src/kernel/blocks/dbtc/DbtcMain.cpp	2007-08-24 16:17:57 +02:00
@@ -4001,7 +4001,7 @@
     TcKeyConf * const tcKeyConf = (TcKeyConf *)signal->getDataPtrSend();
     TcKeyConf::setNoOfOperations(confInfo, 1);
     tcKeyConf->apiConnectPtr = regApiPtr->indexOp;
-    tcKeyConf->gci = regApiPtr->globalcheckpointid;
+    tcKeyConf->gci = regApiPtr->globalcheckpointid >> 32; // XXX JONAS
     tcKeyConf->confInfo = confInfo;
     tcKeyConf->transId1 = regApiPtr->transid[0];
     tcKeyConf->transId2 = regApiPtr->transid[1];
@@ -4025,7 +4025,7 @@
     
     jam();
     tcKeyConf->apiConnectPtr = regApiPtr->ndbapiConnect;
-    tcKeyConf->gci = regApiPtr->globalcheckpointid;;
+    tcKeyConf->gci = regApiPtr->globalcheckpointid >> 32; // XXX JONAS
     tcKeyConf->confInfo = confInfo;
     tcKeyConf->transId1 = regApiPtr->transid[0];
     tcKeyConf->transId2 = regApiPtr->transid[1];
@@ -4050,7 +4050,7 @@
   // -------------------------------------------------------------------------
   UintR Tpack0 = (TblockNum << 16) + (TpacketLen - 4);
   UintR Tpack1 = regApiPtr->ndbapiConnect;
-  UintR Tpack2 = regApiPtr->globalcheckpointid;
+  UintR Tpack2 = regApiPtr->globalcheckpointid >> 32; // XXX JONAS
   UintR Tpack3 = confInfo;
   UintR Tpack4 = regApiPtr->transid[0];
   UintR Tpack5 = regApiPtr->transid[1];
@@ -4228,7 +4228,7 @@
      * COMMIT MESSAGE CAN BE SENT TO ALL INVOLVED PARTS.
      *-----------------------------------------------------------------------*/
     EXECUTE_DIRECT(DBDIH, GSN_DIVERIFYREQ, signal, 1);
-    if (signal->theData[2] == 0) {
+    if (signal->theData[3] == 0) {
       execDIVERIFYCONF(signal);
     }
     return;
@@ -4273,7 +4273,9 @@
 {
   UintR TapiConnectptrIndex = signal->theData[0];
   UintR TapiConnectFilesize = capiConnectFilesize;
-  UintR Tgci = signal->theData[1];
+  UintR Tgci_hi = signal->theData[1];
+  UintR Tgci_lo = signal->theData[2];
+  Uint64 Tgci = Tgci_lo | (Uint64(Tgci_hi) << 32);
   ApiConnectRecord *localApiConnectRecord = apiConnectRecord;
 
   jamEntry();
@@ -4334,7 +4336,7 @@
 /*                             COMMIT_GCI_HANDLING                          */
 /*       SET UP GLOBAL CHECKPOINT DATA STRUCTURE AT THE COMMIT POINT.       */
 /*--------------------------------------------------------------------------*/
-void Dbtc::commitGciHandling(Signal* signal, UintR Tgci) 
+void Dbtc::commitGciHandling(Signal* signal, Uint64 Tgci)
 {
   GcpRecordPtr localGcpPointer;
 
@@ -4412,7 +4414,7 @@
   GcpRecordPtr localGcpPointer;
 
   UintR Tfirstgcp = cfirstgcp;
-  UintR Tglobalcheckpointid = apiConnectptr.p->globalcheckpointid;
+  Uint64 Tglobalcheckpointid = apiConnectptr.p->globalcheckpointid;
   UintR TgcpFilesize = cgcpFilesize;
   GcpRecord *localGcpRecord = gcpRecord;
 
@@ -4498,7 +4500,7 @@
   ApiConnectRecord * const regApiPtr = apiConnectptr.p;
   Thostptr.i = regTcPtr->lastLqhNodeId;
   ptrCheckGuard(Thostptr, ThostFilesize, hostRecord);
-  if (Thostptr.p->noOfPackedWordsLqh > 21) {
+  if (Thostptr.p->noOfPackedWordsLqh > 25 - 5) {
     jam();
     sendPackedSignalLqh(signal, Thostptr.p);
   } else {
@@ -4508,19 +4510,21 @@
   UintR Tindex = Thostptr.p->noOfPackedWordsLqh;
   UintR* TDataPtr = &Thostptr.p->packedWordsLqh[Tindex];
   UintR Tdata1 = regTcPtr->lastLqhCon;
-  UintR Tdata2 = regApiPtr->globalcheckpointid;
+  UintR Tdata2 = regApiPtr->globalcheckpointid >> 32; // XXX Jonas
   UintR Tdata3 = regApiPtr->transid[0];
   UintR Tdata4 = regApiPtr->transid[1];
+  UintR Tdata5 = regApiPtr->globalcheckpointid & 0xFFFFFFFF;
 
   TDataPtr[0] = Tdata1 | (ZCOMMIT << 28);
   TDataPtr[1] = Tdata2;
   TDataPtr[2] = Tdata3;
   TDataPtr[3] = Tdata4;
-  Thostptr.p->noOfPackedWordsLqh = Tindex + 4;
+  TDataPtr[4] = Tdata5;
+  Thostptr.p->noOfPackedWordsLqh = Tindex + 5;
 }//Dbtc::sendCommitLqh()
 
 void
-Dbtc::DIVER_node_fail_handling(Signal* signal, UintR Tgci)
+Dbtc::DIVER_node_fail_handling(Signal* signal, Uint64 Tgci)
 {
   /*------------------------------------------------------------------------
    * AT LEAST ONE NODE HAS FAILED DURING THE TRANSACTION. WE NEED TO CHECK IF  
@@ -4665,7 +4669,7 @@
     }
     commitConf->transId1 = regApiPtr->transid[0];
     commitConf->transId2 = regApiPtr->transid[1];
-    commitConf->gci = regApiPtr->globalcheckpointid;
+    commitConf->gci = regApiPtr->globalcheckpointid >> 32; // XXX JONAS
 
     sendSignal(regApiPtr->ndbapiBlockref, GSN_TC_COMMITCONF, signal,
 	       TcCommitConf::SignalLength, JBB);
@@ -7008,7 +7012,9 @@
   jamEntry();
   GCPNoMoreTrans* req = (GCPNoMoreTrans*)signal->getDataPtr();
   c_gcp_ref = req->senderData;
-  tcheckGcpId = req->gci;
+  Uint32 gci_lo = req->gci_lo;
+  Uint32 gci_hi = req->gci_hi;
+  tcheckGcpId = gci_lo | (Uint64(gci_hi) << 32);
   if (cfirstgcp != RNIL) {
     jam();
                                       /* A GLOBAL CHECKPOINT IS GOING ON */
@@ -7343,7 +7349,7 @@
   ttransid2    = lqhTransConf->transId2;
   ttcOprec     = lqhTransConf->oldTcOpRec;
   treqinfo     = lqhTransConf->requestInfo;
-  tgci         = lqhTransConf->gci;
+  tgci         = Uint64(lqhTransConf->gci) << 32;
   cnodes[0]    = lqhTransConf->nextNodeId1;
   cnodes[1]    = lqhTransConf->nextNodeId2;
   cnodes[2]    = lqhTransConf->nextNodeId3;
@@ -7990,12 +7996,13 @@
           tcConnectptr.p->tcConnectstate = OS_WAIT_COMMIT_CONF;
           signal->theData[0] = tcConnectptr.i;
           signal->theData[1] = cownref;
-          signal->theData[2] = apiConnectptr.p->globalcheckpointid;
+          signal->theData[2] = apiConnectptr.p->globalcheckpointid >> 32; // XXX JON
           signal->theData[3] = apiConnectptr.p->transid[0];
           signal->theData[4] = apiConnectptr.p->transid[1];
           signal->theData[5] = apiConnectptr.p->tcBlockref;
           signal->theData[6] = tcConnectptr.p->tcOprec;
-          sendSignal(tblockref, GSN_COMMITREQ, signal, 7, JBB);
+          signal->theData[7] = apiConnectptr.p->globalcheckpointid& 0xFFFFFFFF;
+          sendSignal(tblockref, GSN_COMMITREQ, signal, 8, JBB);
           return;
         }//if
         break;
@@ -10161,7 +10168,8 @@
 {
   GCPTCFinished* conf = (GCPTCFinished*)signal->getDataPtrSend();
   conf->senderData = c_gcp_ref;
-  conf->gci = tcheckGcpId;
+  conf->gci_hi = Uint32(tcheckGcpId >> 32);
+  conf->gci_lo = Uint32(tcheckGcpId);
   sendSignal(cdihblockref, GSN_GCP_TCFINISHED, signal, 
              GCPTCFinished::SignalLength, JBB);
 }//Dbtc::gcpTcfinished()
@@ -11992,7 +12000,7 @@
     
     jam();
     tcIndxConf->apiConnectPtr = regApiPtr->ndbapiConnect;
-    tcIndxConf->gci = regApiPtr->globalcheckpointid;;
+    tcIndxConf->gci = regApiPtr->globalcheckpointid >> 32; // XXX JONAS
     tcIndxConf->confInfo = confInfo;
     tcIndxConf->transId1 = regApiPtr->transid[0];
     tcIndxConf->transId2 = regApiPtr->transid[1];
@@ -12017,7 +12025,7 @@
 // -------------------------------------------------------------------------
   UintR Tpack0 = (TblockNum << 16) + (TpacketLen - 4);
   UintR Tpack1 = regApiPtr->ndbapiConnect;
-  UintR Tpack2 = regApiPtr->globalcheckpointid;
+  UintR Tpack2 = regApiPtr->globalcheckpointid >> 32; // XXX JONAS
   UintR Tpack3 = confInfo;
   UintR Tpack4 = regApiPtr->transid[0];
   UintR Tpack5 = regApiPtr->transid[1];

--- 1.86/storage/ndb/src/kernel/blocks/dbtup/Dbtup.hpp	2007-08-24 16:17:57 +02:00
+++ 1.87/storage/ndb/src/kernel/blocks/dbtup/Dbtup.hpp	2007-08-24 16:17:57 +02:00
@@ -1563,7 +1563,8 @@
   Uint32 no_fired_triggers;
   Uint32 frag_page_id;
   Uint32 hash_value;
-  Uint32 gci;
+  Uint32 gci_hi;
+  Uint32 gci_lo;
   Uint32 log_size;
   Uint32 read_length;
   Uint32 attrinfo_len;

--- 1.37/storage/ndb/src/kernel/blocks/dbtup/DbtupCommit.cpp	2007-08-24 16:17:57 +02:00
+++ 1.38/storage/ndb/src/kernel/blocks/dbtup/DbtupCommit.cpp	2007-08-24 16:17:57 +02:00
@@ -74,7 +74,8 @@
   jamEntry();
   OperationrecPtr loopOpPtr;
   loopOpPtr.i= signal->theData[0];
-  Uint32 gci= signal->theData[1];
+  Uint32 gci_hi = signal->theData[1];
+  Uint32 gci_lo = signal->theData[2];
   c_operation_pool.getPtr(loopOpPtr);
   while (loopOpPtr.p->prevActiveOp != RNIL) {
     jam();
@@ -83,15 +84,16 @@
   }
   do {
     ndbrequire(get_trans_state(loopOpPtr.p) == TRANS_STARTED);
-    signal->theData[0]= loopOpPtr.p->userpointer;
-    signal->theData[1]= gci;
+    signal->theData[0] = loopOpPtr.p->userpointer;
+    signal->theData[1] = gci_hi;
+    signal->theData[2] = gci_lo;
     if (loopOpPtr.p->nextActiveOp == RNIL) {
       jam();
-      EXECUTE_DIRECT(DBLQH, GSN_LQH_WRITELOG_REQ, signal, 2);
+      EXECUTE_DIRECT(DBLQH, GSN_LQH_WRITELOG_REQ, signal, 3);
       return;
     }
     jam();
-    EXECUTE_DIRECT(DBLQH, GSN_LQH_WRITELOG_REQ, signal, 2);
+    EXECUTE_DIRECT(DBLQH, GSN_LQH_WRITELOG_REQ, signal, 3);
     jamEntry();
     loopOpPtr.i= loopOpPtr.p->nextActiveOp;
     c_operation_pool.getPtr(loopOpPtr);
@@ -370,19 +372,20 @@
 				 Uint32 opPtrI, Uint32 page_id)
 {
   Uint32 hash_value;
-  Uint32 gci;
+  Uint32 gci_hi, gci_lo;
   OperationrecPtr regOperPtr;
 
   jamEntry();
   
   c_operation_pool.getPtr(regOperPtr, opPtrI);
-  c_lqh->get_op_info(regOperPtr.p->userpointer, &hash_value, &gci);
+  c_lqh->get_op_info(regOperPtr.p->userpointer, &hash_value, &gci_hi, &gci_lo);
 
   TupCommitReq * const tupCommitReq= (TupCommitReq *)signal->getDataPtr();
   
   tupCommitReq->opPtr= opPtrI;
   tupCommitReq->hashValue= hash_value;
-  tupCommitReq->gci= gci;
+  tupCommitReq->gci_hi= gci_hi;
+  tupCommitReq->gci_hi= gci_lo;
   tupCommitReq->diskpage = page_id;
 
   regOperPtr.p->op_struct.m_load_diskpage_on_commit= 0;
@@ -407,20 +410,21 @@
 				     Uint32 unused)
 {
   Uint32 hash_value;
-  Uint32 gci;
+  Uint32 gci_hi, gci_lo;
   OperationrecPtr regOperPtr;
 
   jamEntry();
   
   c_operation_pool.getPtr(regOperPtr, opPtrI);
-  c_lqh->get_op_info(regOperPtr.p->userpointer, &hash_value, &gci);
+  c_lqh->get_op_info(regOperPtr.p->userpointer, &hash_value, &gci_hi, &gci_lo);
   Uint32 page= regOperPtr.p->m_commit_disk_callback_page;
 
   TupCommitReq * const tupCommitReq= (TupCommitReq *)signal->getDataPtr();
   
   tupCommitReq->opPtr= opPtrI;
   tupCommitReq->hashValue= hash_value;
-  tupCommitReq->gci= gci;
+  tupCommitReq->gci_hi= gci_hi;
+  tupCommitReq->gci_lo= gci_lo;
   tupCommitReq->diskpage = page;
 
   ndbassert(regOperPtr.p->op_struct.m_load_diskpage_on_commit == 0);
@@ -474,7 +478,7 @@
   TablerecPtr regTabPtr;
   KeyReqStruct req_struct;
   TransState trans_state;
-  Uint32 no_of_fragrec, no_of_tablerec, hash_value, gci;
+  Uint32 no_of_fragrec, no_of_tablerec, hash_value;
 
   TupCommitReq * const tupCommitReq= (TupCommitReq *)signal->getDataPtr();
 
@@ -502,11 +506,13 @@
   no_of_tablerec= cnoOfTablerec;
   regTabPtr.i= regFragPtr.p->fragTableId;
   hash_value= tupCommitReq->hashValue;
-  gci= tupCommitReq->gci;
+  Uint32 gci_hi = tupCommitReq->gci_hi;
+  Uint32 gci_lo = tupCommitReq->gci_lo;
 
   req_struct.signal= signal;
   req_struct.hash_value= hash_value;
-  req_struct.gci= gci;
+  req_struct.gci_hi = gci_hi;
+  req_struct.gci_lo = gci_lo;
   regOperPtr.p->m_commit_disk_callback_page = tupCommitReq->diskpage;
 
 #ifdef VM_TRACE
@@ -673,7 +679,7 @@
     if(regOperPtr.p->op_struct.op_type != ZDELETE)
     {
       jam();
-      commit_operation(signal, gci, tuple_ptr, page,
+      commit_operation(signal, gci_hi, tuple_ptr, page,
 		       regOperPtr.p, regFragPtr.p, regTabPtr.p); 
       removeActiveOpList(regOperPtr.p, tuple_ptr);
     }
@@ -683,7 +689,7 @@
       removeActiveOpList(regOperPtr.p, tuple_ptr);
       if (get_page)
 	ndbassert(tuple_ptr->m_header_bits & Tuple_header::DISK_PART);
-      dealloc_tuple(signal, gci, page.p, tuple_ptr, 
+      dealloc_tuple(signal, gci_hi, page.p, tuple_ptr,
 		    regOperPtr.p, regFragPtr.p, regTabPtr.p); 
     }
   } 

--- 1.88/storage/ndb/src/kernel/blocks/dbtup/DbtupExecQuery.cpp	2007-08-24 16:17:57 +02:00
+++ 1.89/storage/ndb/src/kernel/blocks/dbtup/DbtupExecQuery.cpp	2007-08-24 16:17:57 +02:00
@@ -3685,7 +3685,7 @@
     
   if (0) ndbout << "PAGE CALLBACK DISK DELETE: " << op.m_disk_ref << endl;
   disk_page_free(signal, tablePtr.p, fragPtr.p,
-		 &op.m_disk_ref, pagePtr, op.m_gci);
+		 &op.m_disk_ref, pagePtr, op.m_gci_hi);
   
   c_lqh->nr_delete_complete(signal, &op);
   return;
@@ -3718,7 +3718,7 @@
   if (0) ndbout << "LOGBUFFER CALLBACK DISK DELETE: " << op.m_disk_ref << endl;
   
   disk_page_free(signal, tablePtr.p, fragPtr.p,
-		 &op.m_disk_ref, pagePtr, op.m_gci);
+		 &op.m_disk_ref, pagePtr, op.m_gci_hi);
   
   c_lqh->nr_delete_complete(signal, &op);
 }

--- 1.32/storage/ndb/src/kernel/blocks/dbtup/DbtupTrigger.cpp	2007-08-24 16:17:57 +02:00
+++ 1.33/storage/ndb/src/kernel/blocks/dbtup/DbtupTrigger.cpp	2007-08-24 16:17:57 +02:00
@@ -1053,9 +1053,10 @@
     jam();
     // Since only backup uses subscription triggers we 
     // send to backup directly for now
-    fireTrigOrd->setGCI(req_struct->gci);
+    fireTrigOrd->setGCI(req_struct->gci_hi);
     fireTrigOrd->setHashValue(req_struct->hash_value);
     fireTrigOrd->m_any_value = regOperPtr->m_any_value;
+    fireTrigOrd->m_gci_lo = req_struct->gci_lo;
     EXECUTE_DIRECT(trigPtr->m_receiverBlock,
                    GSN_FIRE_TRIG_ORD,
                    signal,
@@ -1065,7 +1066,7 @@
     jam();
     // Since only backup uses subscription triggers we 
     // send to backup directly for now
-    fireTrigOrd->setGCI(req_struct->gci);
+    fireTrigOrd->setGCI(req_struct->gci_hi);
     EXECUTE_DIRECT(trigPtr->m_receiverBlock,
                    GSN_FIRE_TRIG_ORD,
                    signal,

--- 1.69/storage/ndb/src/kernel/blocks/suma/Suma.cpp	2007-08-24 16:17:57 +02:00
+++ 1.70/storage/ndb/src/kernel/blocks/suma/Suma.cpp	2007-08-24 16:17:57 +02:00
@@ -499,7 +499,7 @@
   c_startup.m_handover_nodes.assign(c_alive_nodes);
   c_startup.m_handover_nodes.bitAND(c_nodes_in_nodegroup_mask);
   c_startup.m_handover_nodes.clear(getOwnNodeId());
-  Uint32 gci= m_last_complete_gci + 3;
+  Uint32 gci= (m_last_complete_gci >> 32) + 3;
   
   SumaHandoverReq* req= (SumaHandoverReq*)signal->getDataPtrSend();
   char buf[255];
@@ -540,15 +540,28 @@
   Uint32 type= signal->theData[0];
   switch(type){
   case SumaContinueB::RELEASE_GCI:
-    release_gci(signal, signal->theData[1], signal->theData[2]);
+  {
+    Uint32 gci_hi = signal->theData[2];
+    Uint32 gci_lo = signal->theData[3];
+    Uint64 gci = gci_lo | (Uint64(gci_hi) << 32);
+    release_gci(signal, signal->theData[1], gci);
     return;
+  }
   case SumaContinueB::RESEND_BUCKET:
+  {
+    Uint32 min_gci_hi = signal->theData[2];
+    Uint32 min_gci_lo = signal->theData[5];
+    Uint32 last_gci_hi = signal->theData[4];
+    Uint32 last_gci_lo = signal->theData[6];
+    Uint64 min_gci = min_gci_lo | (Uint64(min_gci_hi) << 32);
+    Uint64 last_gci = last_gci_lo | (Uint64(last_gci_hi) << 32);
     resend_bucket(signal, 
 		  signal->theData[1], 
-		  signal->theData[2],
+		  min_gci,
 		  signal->theData[3],
-		  signal->theData[4]);
+		  last_gci);
     return;
+  }
   case SumaContinueB::OUT_OF_BUFFER_RELEASE:
     out_of_buffer_release(signal, signal->theData[1]);
     return;
@@ -603,7 +616,8 @@
   for(c_gcp_list.first(gcp); !gcp.isNull(); c_gcp_list.next(gcp))
   {
     jam();
-    ack->rep.gci = gcp.p->m_gci;
+    ack->rep.gci_hi = gcp.p->m_gci >> 32;
+    ack->rep.gci_lo = gcp.p->m_gci & 0xFFFFFFFF;
     if(gcp.p->m_subscribers.get(failedApiNode))
     {
       jam();
@@ -768,8 +782,6 @@
     }
   }
   
-  signal->theData[0] = SumaContinueB::RESEND_BUCKET;
-
   NdbNodeBitmask tmp;
   tmp.assign(c_alive_nodes);
   tmp.bitANDC(failed);
@@ -2382,7 +2394,7 @@
 void
 Suma::sendSubStartComplete(Signal* signal,
 			   SubscriberPtr subbPtr, 
-			   Uint32 firstGCI,
+			   Uint64 firstGCI,
 			   SubscriptionData::Part part)
 {
   jam();
@@ -2706,7 +2718,8 @@
   // let subscriber know that subscrber is stopped
   {
     SubTableData * data  = (SubTableData*)signal->getDataPtrSend();
-    data->gci            = m_last_complete_gci + 1; // XXX ???
+    data->gci_hi         = (m_last_complete_gci >> 32) + 1;
+    data->gci_lo         = 0;
     data->tableId        = 0;
     data->requestInfo    = 0;
     SubTableData::setOperation(data->requestInfo, 
@@ -2749,7 +2762,8 @@
   if (table_event == NdbDictionary::Event::_TE_SUBSCRIBE &&
       !c_startup.m_restart_server_node_id)
   {
-    data->gci            = m_last_complete_gci + 1;
+    data->gci_hi         = (m_last_complete_gci >> 32) + 1;
+    data->gci_lo         = 0;
     data->tableId        = subPtr.p->m_tableId;
     data->requestInfo    = 0;
     SubTableData::setOperation(data->requestInfo, 
@@ -2778,7 +2792,8 @@
   ndbout_c("reportAllSubscribers  subPtr.i: %d  subPtr.p->n_subscribers: %d",
            subPtr.i, subPtr.p->n_subscribers);
 //#endif
-  data->gci            = m_last_complete_gci + 1;
+  data->gci_hi         = (m_last_complete_gci >> 32) + 1;
+  data->gci_lo         = 0;
   data->tableId        = subPtr.p->m_tableId;
   data->requestInfo    = 0;
   SubTableData::setOperation(data->requestInfo, table_event);
@@ -3224,7 +3239,8 @@
   sdata->requestInfo = 0;
   SubTableData::setOperation(sdata->requestInfo, 
 			     NdbDictionary::Event::_TE_SCAN); // Scan
-  sdata->gci = 0; // Undefined
+  sdata->gci_hi = 0; // Undefined
+  sdata->gci_lo = 0;
 #if PRINT_ONLY
   ndbout_c("GSN_SUB_TABLE_DATA (scan) #attr: %d len: %d", attribs, sum);
 #else
@@ -3343,7 +3359,7 @@
 }
 
 bool
-Suma::check_switchover(Uint32 bucket, Uint32 gci)
+Suma::check_switchover(Uint32 bucket, Uint64 gci)
 {
   const Uint32 send_mask = (Bucket::BUCKET_STARTING | Bucket::BUCKET_TAKEOVER);
   bool send = c_buckets[bucket].m_state & send_mask;
@@ -3403,7 +3419,9 @@
   FireTrigOrd* const trg = (FireTrigOrd*)signal->getDataPtr();
   const Uint32 trigId    = trg->getTriggerId();
   const Uint32 hashValue = trg->getHashValue();
-  const Uint32 gci       = trg->getGCI();
+  const Uint32 gci_hi    = trg->getGCI();
+  const Uint32 gci_lo    = trg->m_gci_lo;
+  const Uint64 gci = gci_lo | (Uint64(gci_hi) << 32);
   const Uint32 event     = trg->getTriggerEvent();
   const Uint32 any_value = trg->getAnyValue();
   TablePtr tabPtr;
@@ -3441,7 +3459,8 @@
     ndbrequire((tabPtr.p = c_tablePool.getPtr(tabPtr.i)) != 0);
     
     SubTableData * data = (SubTableData*)signal->getDataPtrSend();//trg;
-    data->gci            = gci;
+    data->gci_hi         = gci_hi;
+    data->gci_lo         = gci_lo;
     data->tableId        = tableId;
     data->requestInfo    = 0;
     SubTableData::setOperation(data->requestInfo, event);
@@ -3489,7 +3508,28 @@
   ndbassert(signal->getNoOfSections() == 0);
 
   SubGcpCompleteRep * rep = (SubGcpCompleteRep*)signal->getDataPtrSend();
-  Uint32 gci = m_last_complete_gci = rep->gci;
+  Uint32 gci_hi = rep->gci_hi;
+  Uint32 gci_lo = rep->gci_lo;
+  Uint64 gci = gci_lo | (Uint64(gci_hi) << 32);
+  Uint32 flags = rep->flags;
+
+#ifdef VM_TRACE
+  if (m_gcp_monitor == 0)
+  {
+  }
+  else if (gci_hi == Uint32(m_gcp_monitor >> 32))
+  {
+    ndbrequire(gci_lo == Uint32(m_gcp_monitor) + 1);
+  }
+  else
+  {
+    ndbrequire(gci_hi == Uint32(m_gcp_monitor >> 32) + 1);
+    ndbrequire(gci_lo == 0);
+  }
+  m_gcp_monitor = gci;
+#endif
+
+  m_last_complete_gci = gci;
   m_max_seen_gci = (gci > m_max_seen_gci ? gci : m_max_seen_gci);
 
   /**
@@ -3529,7 +3569,9 @@
 	  Buffer_page* page= (Buffer_page*)
 	    m_tup->c_page_pool.getPtr(pos.m_page_id);
 	  ndbout_c("takeover %d", pos.m_page_id);
-	  page->m_max_gci = pos.m_max_gci;
+	  page->m_max_gci_hi = pos.m_max_gci >> 32;
+          page->m_max_gci_lo = pos.m_max_gci & 0xFFFFFFFF;
+          ndbassert(pos.m_max_gci);
 	  page->m_words_used = pos.m_page_pos;
 	  page->m_next_page = RNIL;
 	  memset(&bucket->m_buffer_head, 0, sizeof(bucket->m_buffer_head));
@@ -3568,14 +3610,16 @@
   if(ERROR_INSERTED(13010))
   {
     CLEAR_ERROR_INSERT_VALUE;
-    ndbout_c("Don't send GCP_COMPLETE_REP(%d)", gci);
+    ndbout_c("Don't send GCP_COMPLETE_REP(%llu)", gci);
     return;
   }
 
   /**
    * Signal to subscribers
    */
-  rep->gci = gci;
+  rep->gci_hi = gci_hi;
+  rep->gci_lo = gci_lo;
+  rep->flags = flags;
   rep->senderRef  = reference();
   rep->gcp_complete_rep_count = m_gcp_complete_rep_count;
   
@@ -3671,7 +3715,8 @@
   // dict coordinator sends info to API
   
   SubTableData * data = (SubTableData*)signal->getDataPtrSend();
-  data->gci            = m_last_complete_gci+1;
+  data->gci_hi         = (m_last_complete_gci >> 32) + 1;
+  data->gci_lo         = 0;
   data->tableId        = tableId;
   data->requestInfo    = 0;
   SubTableData::setOperation(data->requestInfo,NdbDictionary::Event::_TE_DROP);
@@ -3756,7 +3801,8 @@
   releaseSections(signal);
 
   SubTableData * data = (SubTableData*)signal->getDataPtrSend();
-  data->gci            = m_last_complete_gci+1;
+  data->gci_hi         = (m_last_complete_gci >> 32) + 1;
+  data->gci_lo         = 0;
   data->tableId        = tableId;
   data->requestInfo    = 0;
   SubTableData::setOperation(data->requestInfo, 
@@ -3805,7 +3851,9 @@
   ndbassert(signal->getNoOfSections() == 0);
 
   SubGcpCompleteAck * const ack = (SubGcpCompleteAck*)signal->getDataPtr();
-  Uint32 gci = ack->rep.gci;
+  Uint32 gci_hi = ack->rep.gci_hi;
+  Uint32 gci_lo = ack->rep.gci_lo;
+  Uint64 gci = gci_lo | (Uint64(gci_hi) << 32);
   Uint32 senderRef  = ack->rep.senderRef;
   m_max_seen_gci = (gci > m_max_seen_gci ? gci : m_max_seen_gci);
 
@@ -3847,7 +3895,7 @@
   
   if(gcp.isNull())
   {
-    ndbout_c("ACK wo/ gcp record (gci: %d)", gci);
+    ndbout_c("ACK wo/ gcp record (gci: %llu)", gci);
   }
   else
   {
@@ -4465,7 +4513,7 @@
 
   Uint32 gci = req->gci;
   Uint32 nodeId = req->nodeId;
-  Uint32 new_gci = m_last_complete_gci + MAX_CONCURRENT_GCP + 1;
+  Uint32 new_gci = (m_last_complete_gci >> 32) + MAX_CONCURRENT_GCP + 1;
   
   Uint32 start_gci = (gci > new_gci ? gci : new_gci);
   // mark all active buckets really belonging to restarting SUMA
@@ -4481,7 +4529,7 @@
 	tmp.set(i);
 	m_active_buckets.clear(i);
 	m_switchover_buckets.set(i);
-	c_buckets[i].m_switchover_gci = start_gci;
+	c_buckets[i].m_switchover_gci = Uint64(start_gci) << 32;
 	c_buckets[i].m_state |= Bucket::BUCKET_HANDOVER;
 	c_buckets[i].m_switchover_node = nodeId;
 	ndbout_c("prepare to handover bucket: %d", i);
@@ -4531,7 +4579,7 @@
     {
       ndbrequire(get_responsible_node(i) == getOwnNodeId());
       // We should run this bucket, but _nodeId_ is
-      c_buckets[i].m_switchover_gci = gci;
+      c_buckets[i].m_switchover_gci = Uint64(gci) << 32;
       c_buckets[i].m_state |= Bucket::BUCKET_STARTING;
     }
   }
@@ -4560,7 +4608,7 @@
 #endif
 
 Uint32*
-Suma::get_buffer_ptr(Signal* signal, Uint32 buck, Uint32 gci, Uint32 sz)
+Suma::get_buffer_ptr(Signal* signal, Uint32 buck, Uint64 gci, Uint32 sz)
 {
   sz += 1; // len
   Bucket* bucket= c_buckets+buck;
@@ -4579,7 +4627,7 @@
   
   pos.m_page_pos += sz;
   pos.m_last_gci = gci;
-  Uint32 max = pos.m_max_gci > gci ? pos.m_max_gci : gci;
+  Uint64 max = pos.m_max_gci > gci ? pos.m_max_gci : gci;
   
   if(likely(same_gci && pos.m_page_pos <= Buffer_page::DATA_WORDS))
   {
@@ -4588,14 +4636,15 @@
     * ptr++ = (0x8000 << 16) | sz; // Same gci
     return ptr;
   }
-  else if(pos.m_page_pos + 1 <= Buffer_page::DATA_WORDS)
+  else if(pos.m_page_pos + Buffer_page::GCI_SZ32 <= Buffer_page::DATA_WORDS)
   {
 loop:
     pos.m_max_gci = max;
-    pos.m_page_pos += 1;
+    pos.m_page_pos += Buffer_page::GCI_SZ32;
     bucket->m_buffer_head = pos;
-    * ptr++ = (sz + 1); 
-    * ptr++ = gci;
+    * ptr++ = (sz + Buffer_page::GCI_SZ32);
+    * ptr++ = gci >> 32;
+    * ptr++ = gci & 0xFFFFFFFF;
     return ptr;
   }
   else
@@ -4617,9 +4666,11 @@
 
     if(likely(pos.m_page_id != RNIL))
     {
-      page->m_max_gci = pos.m_max_gci;
+      page->m_max_gci_hi = pos.m_max_gci >> 32;
+      page->m_max_gci_lo = pos.m_max_gci & 0xFFFFFFFF;
       page->m_words_used = pos.m_page_pos - sz;
       page->m_next_page= next;
+      ndbassert(pos.m_max_gci);
     }
     else
     {
@@ -4758,18 +4809,18 @@
 }
 
 void
-Suma::release_gci(Signal* signal, Uint32 buck, Uint32 gci)
+Suma::release_gci(Signal* signal, Uint32 buck, Uint64 gci)
 {
   Bucket* bucket= c_buckets+buck;
   Uint32 tail= bucket->m_buffer_tail;
   Page_pos head= bucket->m_buffer_head;
-  Uint32 max_acked = bucket->m_max_acked_gci;
+  Uint64 max_acked = bucket->m_max_acked_gci;
 
   const Uint32 mask = Bucket::BUCKET_TAKEOVER | Bucket::BUCKET_RESEND;
   if(unlikely(bucket->m_state & mask))
   {
     jam();
-    ndbout_c("release_gci(%d, %d) -> node failure -> abort", buck, gci);
+    ndbout_c("release_gci(%d, %llu) -> node failure -> abort", buck, gci);
     return;
   }
   
@@ -4795,7 +4846,7 @@
   {
     jam();
     Buffer_page* page= (Buffer_page*)m_tup->c_page_pool.getPtr(tail);
-    Uint32 max_gci = page->m_max_gci;
+    Uint64 max_gci = page->m_max_gci_lo | (Uint64(page->m_max_gci_hi) << 32);
     Uint32 next_page = page->m_next_page;
 
     ndbassert(max_gci);
@@ -4808,8 +4859,9 @@
       bucket->m_buffer_tail = next_page;
       signal->theData[0] = SumaContinueB::RELEASE_GCI;
       signal->theData[1] = buck;
-      signal->theData[2] = gci;
-      sendSignal(SUMA_REF, GSN_CONTINUEB, signal, 3, JBB);
+      signal->theData[2] = gci >> 32;
+      signal->theData[3] = gci & 0xFFFFFFFF;
+      sendSignal(SUMA_REF, GSN_CONTINUEB, signal, 4, JBB);
       return;
     }
     else
@@ -4848,8 +4900,8 @@
     return;
   }
 
-  Uint32 min= bucket->m_max_acked_gci + 1;
-  Uint32 max = pos.m_max_gci;
+  Uint64 min= bucket->m_max_acked_gci + 1;
+  Uint64 max = pos.m_max_gci;
 
   ndbrequire(max <= m_max_seen_gci);
 
@@ -4870,25 +4922,28 @@
 
   m_switchover_buckets.set(buck);
   
+  signal->theData[0] = SumaContinueB::RESEND_BUCKET;
   signal->theData[1] = buck;
-  signal->theData[2] = min;
+  signal->theData[2] = min >> 32;
   signal->theData[3] = 0;
   signal->theData[4] = 0;
-  sendSignal(reference(), GSN_CONTINUEB, signal, 5, JBB);	
+  signal->theData[5] = min & 0xFFFFFFFF;
+  signal->theData[6] = 0;
+  sendSignal(reference(), GSN_CONTINUEB, signal, 7, JBB);
   
-  ndbout_c("min: %d - max: %d) page: %d", min, max, bucket->m_buffer_tail);
+  ndbout_c("min: %llu - max: %llu) page: %d", min, max, bucket->m_buffer_tail);
   ndbrequire(max >= min);
 }
 
 void
-Suma::resend_bucket(Signal* signal, Uint32 buck, Uint32 min_gci, 
-		    Uint32 pos, Uint32 last_gci)
+Suma::resend_bucket(Signal* signal, Uint32 buck, Uint64 min_gci,
+		    Uint32 pos, Uint64 last_gci)
 {
   Bucket* bucket= c_buckets+buck;
   Uint32 tail= bucket->m_buffer_tail;
 
   Buffer_page* page= (Buffer_page*)m_tup->c_page_pool.getPtr(tail);
-  Uint32 max_gci = page->m_max_gci;
+  Uint64 max_gci = page->m_max_gci_lo | (Uint64(page->m_max_gci_hi) << 32);
   Uint32 next_page = page->m_next_page;
   Uint32 *ptr = page->m_data + pos;
   Uint32 *end = page->m_data + page->m_words_used;
@@ -4912,7 +4967,7 @@
   {
     free_page(tail, page);
     tail = bucket->m_buffer_tail = next_page;
-    ndbout_c("pos==0 && min_gci(%d) > max_gci(%d) resend switching page to %d", min_gci, max_gci, tail);
+    ndbout_c("pos==0 && min_gci(%llu) > max_gci(%llu) resend switching page to %d", min_gci, max_gci, tail);
     goto next;
   }
   
@@ -4936,8 +4991,11 @@
 
     if(! (tmp & (0x8000 << 16)))
     {
-      sz--;
-      last_gci = * src ++;
+      ndbrequire(sz >= Buffer_page::GCI_SZ32);
+      sz -= Buffer_page::GCI_SZ32;
+      Uint32 last_gci_hi = * src++;
+      Uint32 last_gci_lo = * src++;
+      last_gci = last_gci_lo | (Uint64(last_gci_hi) << 32);
     }
     else
     {
@@ -4955,13 +5013,15 @@
     if(sz == 0)
     {
       SubGcpCompleteRep * rep = (SubGcpCompleteRep*)signal->getDataPtrSend();
-      rep->gci = last_gci;
+      rep->gci_hi = last_gci >> 32;
+      rep->gci_lo = last_gci & 0xFFFFFFFF;
+      rep->flags = 0;
       rep->senderRef  = reference();
       rep->gcp_complete_rep_count = 1;
   
       char buf[255];
       c_subscriber_nodes.getText(buf);
-      ndbout_c("resending GCI: %d rows: %d -> %s", last_gci, g_cnt, buf);
+      ndbout_c("resending GCI: %llu rows: %d -> %s", last_gci, g_cnt, buf);
       g_cnt = 0;
       
       NodeReceiverGroup rg(API_CLUSTERMGR, c_subscriber_nodes);
@@ -4997,7 +5057,8 @@
           table_version_major(schemaVersion))
       {
 	SubTableData * data = (SubTableData*)signal->getDataPtrSend();//trg;
-	data->gci            = last_gci;
+	data->gci_hi         = last_gci >> 32;
+	data->gci_lo         = last_gci & 0xFFFFFFFF;
 	data->tableId        = table;
 	data->requestInfo    = 0;
 	SubTableData::setOperation(data->requestInfo, event);
@@ -5051,13 +5112,15 @@
   
   signal->theData[0] = SumaContinueB::RESEND_BUCKET;
   signal->theData[1] = buck;
-  signal->theData[2] = min_gci;
+  signal->theData[2] = min_gci >> 32;
   signal->theData[3] = pos;
-  signal->theData[4] = last_gci;
+  signal->theData[4] = last_gci >> 32;
+  signal->theData[5] = min_gci & 0xFFFFFFFF;
+  signal->theData[6] = last_gci & 0xFFFFFFFF;
   if(!delay)
-    sendSignal(SUMA_REF, GSN_CONTINUEB, signal, 5, JBB);
+    sendSignal(SUMA_REF, GSN_CONTINUEB, signal, 7, JBB);
   else
-    sendSignalWithDelay(SUMA_REF, GSN_CONTINUEB, signal, 10, 5);   
+    sendSignalWithDelay(SUMA_REF, GSN_CONTINUEB, signal, 10, 7);
 }
 
 template void append(DataBuffer<11>&,SegmentedSectionPtr,SectionSegmentPool&);

--- 1.23/storage/ndb/src/kernel/blocks/suma/Suma.hpp	2007-08-24 16:17:57 +02:00
+++ 1.24/storage/ndb/src/kernel/blocks/suma/Suma.hpp	2007-08-24 16:17:57 +02:00
@@ -369,7 +369,7 @@
   void sendSubSyncRef(Signal* signal, Uint32 errorCode);  
   void sendSubRemoveRef(Signal* signal, const SubRemoveReq& ref,
 			Uint32 errorCode);
-  void sendSubStartComplete(Signal*, SubscriberPtr, Uint32, 
+  void sendSubStartComplete(Signal*, SubscriberPtr, Uint64 gci,
 			    SubscriptionData::Part);
   void sendSubStopComplete(Signal*, SubscriberPtr);
   void sendSubStopReq(Signal* signal, bool unlock= false);
@@ -529,15 +529,15 @@
 
   Uint32 get_responsible_node(Uint32 B) const;
   Uint32 get_responsible_node(Uint32 B, const NdbNodeBitmask& mask) const;
-  bool check_switchover(Uint32 bucket, Uint32 gci);
+  bool check_switchover(Uint32 bucket, Uint64 gci);
 
 public:  
   struct Page_pos
   {
     Uint32 m_page_id;
     Uint32 m_page_pos;  
-    Uint32 m_max_gci;   // max gci on page
-    Uint32 m_last_gci;  // last gci on page
+    Uint64 m_max_gci;   // max gci on page
+    Uint64 m_last_gci;  // last gci on page
   };
 private:
   
@@ -552,15 +552,17 @@
     Uint16 m_state;
     Uint16 m_switchover_node;
     Uint16 m_nodes[MAX_REPLICAS]; 
-    Uint32 m_switchover_gci;
-    Uint32 m_max_acked_gci;
     Uint32 m_buffer_tail;   // Page
+    Uint64 m_switchover_gci;
+    Uint64 m_max_acked_gci;
     Page_pos m_buffer_head;
   };
   
   struct Buffer_page 
   {
-    STATIC_CONST( DATA_WORDS = 8192 - 9);
+    STATIC_CONST( DATA_WORDS = 8192 - 10);
+    STATIC_CONST( GCI_SZ32 = 2 );
+
     Uint32 _tupdata1;
     Uint32 _tupdata2;
     Uint32 _tupdata3;
@@ -569,7 +571,8 @@
     Uint32 m_page_chunk_ptr_i;
     Uint32 m_next_page;      
     Uint32 m_words_used;     // 
-    Uint32 m_max_gci;        //
+    Uint32 m_max_gci_hi;     //
+    Uint32 m_max_gci_lo;     //
     Uint32 m_data[DATA_WORDS];
   };
   
@@ -584,26 +587,26 @@
   
   class Dbtup* m_tup;
   void init_buffers();
-  Uint32* get_buffer_ptr(Signal*, Uint32 buck, Uint32 gci, Uint32 sz);
+  Uint32* get_buffer_ptr(Signal*, Uint32 buck, Uint64 gci, Uint32 sz);
   Uint32 seize_page();
   void free_page(Uint32 page_id, Buffer_page* page);
   void out_of_buffer(Signal*);
   void out_of_buffer_release(Signal* signal, Uint32 buck);
 
   void start_resend(Signal*, Uint32 bucket);
-  void resend_bucket(Signal*, Uint32 bucket, Uint32 gci, 
-		     Uint32 page_pos, Uint32 last_gci);
-  void release_gci(Signal*, Uint32 bucket, Uint32 gci);
-
-  Uint32 m_max_seen_gci;      // FIRE_TRIG_ORD
-  Uint32 m_max_sent_gci;      // FIRE_TRIG_ORD -> send
-  Uint32 m_last_complete_gci; // SUB_GCP_COMPLETE_REP
-  Uint32 m_out_of_buffer_gci;
+  void resend_bucket(Signal*, Uint32 bucket, Uint64 gci,
+		     Uint32 page_pos, Uint64 last_gci);
+  void release_gci(Signal*, Uint32 bucket, Uint64 gci);
+
+  Uint64 m_max_seen_gci;      // FIRE_TRIG_ORD
+  Uint64 m_max_sent_gci;      // FIRE_TRIG_ORD -> send
+  Uint64 m_last_complete_gci; // SUB_GCP_COMPLETE_REP
+  Uint64 m_out_of_buffer_gci;
   Uint32 m_gcp_complete_rep_count;
 
   struct Gcp_record 
   {
-    Uint32 m_gci;
+    Uint64 m_gci;
     NodeBitmask m_subscribers;
     union {
       Uint32 nextPool;
@@ -628,6 +631,11 @@
 
   Uint32 m_first_free_page;
   ArrayPool<Page_chunk> c_page_chunk_pool;
+
+#ifdef VM_TRACE
+  Uint64 m_gcp_monitor;
+#endif
+
 };
 
 #endif

--- 1.17/storage/ndb/src/kernel/blocks/suma/SumaInit.cpp	2007-08-24 16:17:57 +02:00
+++ 1.18/storage/ndb/src/kernel/blocks/suma/SumaInit.cpp	2007-08-24 16:17:57 +02:00
@@ -123,6 +123,10 @@
 	       &Suma::execSUB_GCP_COMPLETE_REP);
 
   c_startup.m_restart_server_node_id = RNIL; // Server for my NR
+
+#ifdef VM_TRACE
+  m_gcp_monitor = 0;
+#endif
 }
 
 Suma::~Suma()

--- 1.96/storage/ndb/src/ndbapi/NdbEventOperationImpl.cpp	2007-08-24 16:17:57 +02:00
+++ 1.97/storage/ndb/src/ndbapi/NdbEventOperationImpl.cpp	2007-08-24 16:17:57 +02:00
@@ -54,7 +54,8 @@
 static void
 print_std(const SubTableData * sdata, LinearSectionPtr ptr[3])
 {
-  printf("addr=%p gci=%d op=%d\n", (void*)sdata, sdata->gci, 
+  printf("addr=%p gci{hi/lo}hi=%d/%d op=%d\n", (void*)sdata,
+         sdata->gci_hi, sdata->gci_lo,
 	 SubTableData::getOperation(sdata->requestInfo));
   for (int i = 0; i <= 2; i++) {
     printf("sec=%d addr=%p sz=%d\n", i, (void*)ptr[i].p, ptr[i].sz);
@@ -719,7 +720,9 @@
 Uint64
 NdbEventOperationImpl::getGCI()
 {
-  return m_data_item->sdata->gci;
+  Uint32 gci_hi = m_data_item->sdata->gci_hi;
+  Uint32 gci_lo = m_data_item->sdata->gci_lo;
+  return gci_lo | (Uint64(gci_hi) << 32);
 }
 
 Uint32
@@ -750,6 +753,7 @@
       abort();
     }
   }
+
   const Uint32 i = SubTableData::DICT_TAB_INFO;
   DBUG_PRINT("info", ("Accumulated %u bytes for fragment %u", 
                       4 * ptr[i].sz, m_fragmentId));
@@ -1023,6 +1027,8 @@
   m_system_nodes(ndb->theImpl->theNoOfDBnodes),
   m_ndb(ndb),
   m_latestGCI(0), m_latest_complete_GCI(0),
+  m_min_gci_index(0),
+  m_max_gci_index(0),
   m_total_alloc(0),
   m_free_thresh(10),
   m_min_free_thresh(10),
@@ -1116,7 +1122,10 @@
   bzero(&m_complete_data, sizeof(m_complete_data));
   m_latest_complete_GCI = m_latestGCI = 0;
   m_active_gci.clear();
-  m_active_gci.fill(2 * ACTIVE_GCI_DIRECTORY_SIZE - 1, g_empty_gci_container);
+  m_active_gci.fill(3, g_empty_gci_container);
+  m_min_gci_index = m_max_gci_index = 0;
+  Uint64 gci = 0;
+  m_known_gci.fill(15, gci);
 }
 
 int NdbEventBuffer::expand(unsigned sz)
@@ -1185,20 +1194,22 @@
 int
 NdbEventBuffer::flushIncompleteEvents(Uint64 gci)
 {
+#if 0
   /**
    *  Find min complete gci
    */
   // called by user thread, so we need to lock the data
   lock();
-  Uint32 i;
-  Uint32 sz= m_active_gci.size();
   Gci_container* array = (Gci_container*)m_active_gci.getBase();
-  for(i = 0; i < sz; i++)
+  Uint32 mask = m_active_gci.size() - 1;
+  Uint32 minpos = m_min_gci_index;
+  Uint32 maxpos = m_max_gci_index;
+
+  while (minpos != maxpos)
   {
-    Gci_container* tmp = array + i;
+    Gci_container* tmp = array + minpos;
     if (tmp->m_gci && tmp->m_gci < gci)
     {
-      // we have found an old not-completed gci, remove it
       ndbout_c("ndb: flushing incomplete epoch %lld (<%lld)", tmp->m_gci, gci);
       if(!tmp->m_data.is_empty())
       {
@@ -1207,11 +1218,18 @@
       tmp->~Gci_container();
       bzero(tmp, sizeof(Gci_container));
     }
+    minpos = (minpos + 1) & mask;
   }
+
+  m_min_gci_index = minpos;
+  m_min_knownGCI = (array + minpos)->m_gci;
+
 #ifdef VM_TRACE
   m_flush_gci = gci;
 #endif
+
   unlock();
+#endif
   return 0;
 }
 
@@ -1371,7 +1389,7 @@
 NdbOut&
 operator<<(NdbOut& out, const Gci_container& gci)
 {
-  out << "[ GCI: " << gci.m_gci
+  out << "[ GCI: " << (gci.m_gci >> 32) << "/" << (gci.m_gci & 0xFFFFFFFF)
       << "  state: " << hex << gci.m_state 
       << "  head: " << hex << gci.m_data.m_head
       << "  tail: " << hex << gci.m_data.m_tail
@@ -1395,88 +1413,204 @@
 #endif
 
 static
-Gci_container*
-find_bucket_chained(Vector<Gci_container_pod> * active, Uint64 gci
+void
+resize_known_gci()
+{
+  abort();
+}
+
 #ifdef VM_TRACE
-                    ,Uint64 flush_gci
-#endif
-                    )
+void
+NdbEventBuffer::verify_known_gci(bool allowempty)
 {
-  Uint32 pos = (gci & ACTIVE_GCI_MASK);
-  Gci_container *bucket= ((Gci_container*)active->getBase()) + pos;
+  Uint32 minpos = m_min_gci_index;
+  Uint32 maxpos = m_max_gci_index;
+  Uint32 mask = m_known_gci.size() - 1;
+
+  Uint32 line;
+#define MMASSERT(x) { if (!(x)) { line = __LINE__; goto fail; }}
+  if (m_min_gci_index == m_max_gci_index)
+  {
+    MMASSERT(allowempty);
+    for (Uint32 i = 0; i<m_active_gci.size(); i++)
+      MMASSERT(((Gci_container*)(m_active_gci.getBase()+i))->m_gci == 0);
+    return;
+  }
+
+  Uint64 last = m_known_gci[minpos];
+  MMASSERT(last > m_latestGCI);
+  MMASSERT(find_bucket(last) != 0);
+  MMASSERT(maxpos == m_max_gci_index);
 
-  if(gci > bucket->m_gci)
+  minpos = (minpos + 1) & mask;
+  while (minpos != maxpos)
   {
-    Gci_container* move;
-    Uint32 move_pos = pos + ACTIVE_GCI_DIRECTORY_SIZE;
-    do 
-    {
-      active->fill(move_pos, g_empty_gci_container);
-      // Needs to recomputed after fill
-      bucket = ((Gci_container*)active->getBase()) + pos; 
-      move = ((Gci_container*)active->getBase()) + move_pos;
-      if(move->m_gcp_complete_rep_count == 0)
-      {
-	memcpy(move, bucket, sizeof(Gci_container));
-	bzero(bucket, sizeof(Gci_container));
-	bucket->m_gci = gci;
-	bucket->m_gcp_complete_rep_count = ~(Uint32)0;
-#ifdef VM_TRACE
-        if (gci < flush_gci)
+    MMASSERT(m_known_gci[minpos] > last);
+    last = m_known_gci[minpos];
+    MMASSERT(find_bucket(last) != 0);
+    MMASSERT(maxpos == m_max_gci_index);
+    minpos = (minpos + 1) & mask;
+  }
+
+  Gci_container* bucktets = (Gci_container*)(m_active_gci.getBase());
+  for (Uint32 i = 0; i<m_active_gci.size(); i++)
+  {
+    if (bucktets[i].m_gci)
+    {
+      bool found = false;
+      for (Uint32 j = m_min_gci_index; j != m_max_gci_index;
+           j = (j + 1) & mask)
+      {
+        if (m_known_gci[j] == bucktets[i].m_gci)
         {
-          ndbout_c("received old gci %llu < flush gci %llu", gci, flush_gci);
-          assert(false);
+          found = true;
+          break;
         }
-#endif
-	return bucket;
       }
-      move_pos += ACTIVE_GCI_DIRECTORY_SIZE;
-    } while(true);
+      if (!found)
+        ndbout_c("%u/%u not found",
+                 Uint32(bucktets[i].m_gci >> 32),
+                 Uint32(bucktets[i].m_gci));
+      MMASSERT(found == true);
+    }
   }
-  else /** gci < bucket->m_gci */
+
+  return;
+fail:
+  ndbout_c("assertion at %d", line);
+  printf("known gci: ");
+  for (Uint32 i = m_min_gci_index; i != m_max_gci_index; i = (i + 1) & mask)
   {
-    Uint32 size = active->size() - ACTIVE_GCI_DIRECTORY_SIZE;
-    do 
+    printf("%u/%u ", Uint32(m_known_gci[i] >> 32), Uint32(m_known_gci[i]));
+  }
+
+  printf("\nContainers");
+  for (Uint32 i = 0; i<m_active_gci.size(); i++)
+    ndbout << m_active_gci[i] << endl;
+  abort();
+}
+#endif
+
+Gci_container*
+NdbEventBuffer::find_bucket_chained(Uint64 gci)
+{
+  if (0)
+    printf("find_bucket_chained(%u/%u) ", Uint32(gci >> 32), Uint32(gci));
+  if (unlikely(gci <= m_latestGCI))
+  {
+    /**
+     * an already complete GCI
+     */
+    if (0)
+      ndbout_c("already complete (%u/%u)",
+               Uint32(m_latestGCI >> 32),
+               Uint32(m_latestGCI));
+    return 0;
+  }
+
+  Uint32 pos = (gci & ACTIVE_GCI_MASK);
+  Uint32 size = m_active_gci.size();
+  Gci_container *buckets = (Gci_container*)(m_active_gci.getBase());
+  while (pos < size)
+  {
+    Uint64 cmp = (buckets + pos)->m_gci;
+    if (cmp == gci)
     {
-      pos += ACTIVE_GCI_DIRECTORY_SIZE;
-      bucket += ACTIVE_GCI_DIRECTORY_SIZE;
-      
-      if(bucket->m_gci == gci)
+      if (0)
+        ndbout_c("found pos: %u", pos);
+      return buckets + pos;
+    }
+
+    if (cmp == 0)
+    {
+      if (0)
+        ndbout_c("empty(%u) ", pos);
+      Uint32 search = pos + ACTIVE_GCI_DIRECTORY_SIZE;
+      while (search < size)
       {
-#ifdef VM_TRACE
-        if (gci < flush_gci)
+        if ((buckets + search)->m_gci == gci)
         {
-          ndbout_c("received old gci %llu < flush gci %llu", gci, flush_gci);
-          assert(false);
+          memcpy(buckets + pos, buckets + search, sizeof(Gci_container));
+          bzero(buckets + search, sizeof(Gci_container));
+          if (0)
+            printf("moved from %u to %u", search, pos);
+          if (search == size - 1)
+          {
+            m_active_gci.erase(search);
+            ndbout_c(" shrink");
+          }
+          else
+          {
+            if (0)
+              ndbout_c("");
+          }
+          return buckets + pos;
         }
-#endif
-	return bucket;
+        search += ACTIVE_GCI_DIRECTORY_SIZE;
       }
-      
-    } while(pos < size);
-    
-    return 0;
+      goto newbucket;
+    }
+    pos += ACTIVE_GCI_DIRECTORY_SIZE;
   }
-}
 
-inline
-Gci_container*
-find_bucket(Vector<Gci_container_pod> * active, Uint64 gci
+  /**
+   * This is a new bucket...likely close to start
+   */
+  ndbout_c("new (with expand) ");
+  m_active_gci.fill(pos, g_empty_gci_container);
+  buckets = (Gci_container*)(m_active_gci.getBase());
+newbucket:
+  Gci_container* bucket = buckets + pos;
+  bucket->m_gci = gci;
+  bucket->m_gcp_complete_rep_count = m_system_nodes;
+
+  Uint32 mask = m_known_gci.size() - 1;
+  Uint64 * array = m_known_gci.getBase();
+
+  Uint32 minpos = m_min_gci_index;
+  Uint32 maxpos = m_max_gci_index;
+  bool full = ((maxpos + 1) & mask) == minpos;
+  if (unlikely(full))
+  {
+    resize_known_gci();
+    minpos = m_min_gci_index;
+    maxpos = m_max_gci_index;
+  }
+
+  Uint32 maxindex = (maxpos - 1) & mask;
+  Uint32 newmaxpos = (maxpos + 1) & mask;
+  m_max_gci_index = newmaxpos;
+  if (likely(gci > array[maxindex]))
+  {
+    array[maxpos] = gci;
 #ifdef VM_TRACE
-            ,Uint64 flush_gci
+    verify_known_gci(false);
 #endif
-            )
-{
-  Uint32 pos = (gci & ACTIVE_GCI_MASK);
-  Gci_container *bucket= ((Gci_container*)active->getBase()) + pos;
-  if(likely(gci == bucket->m_gci))
     return bucket;
+  }
+
+  ndbout_c("insert");
+
+  for (pos = minpos; pos != maxpos; pos = (pos + 1) & mask)
+  {
+    if (array[pos] > gci)
+      break;
+  }
+
+  assert(pos != maxpos);
+  Uint64 oldgci;
+  do {
+    oldgci = array[pos];
+    array[pos] = gci;
+    gci = oldgci;
+    pos = (pos + 1) & mask;
+  } while (pos != maxpos);
+  array[pos] = gci;
 
-  return find_bucket_chained(active,gci
 #ifdef VM_TRACE
-                             , flush_gci
+  verify_known_gci(false);
 #endif
-                             );
+  return bucket;
 }
 
 static
@@ -1488,7 +1622,8 @@
   Uint32 old_cnt = bucket->m_gcp_complete_rep_count;
   
   ndbout_c("INVALID SUB_GCP_COMPLETE_REP");
-  ndbout_c("gci: %d", rep->gci);
+  ndbout_c("gci_hi: %u", rep->gci_hi);
+  ndbout_c("gci_lo: %u", rep->gci_lo);
   ndbout_c("sender: %x", rep->senderRef);
   ndbout_c("count: %d", rep->gcp_complete_rep_count);
   ndbout_c("bucket count: %u", old_cnt);
@@ -1497,6 +1632,39 @@
 }
 
 void
+NdbEventBuffer::complete_bucket(Gci_container* bucket)
+{
+  Uint64 gci = bucket->m_gci;
+  Gci_container* buckets = (Gci_container*)m_active_gci.getBase();
+
+  if (0)
+    ndbout_c("complete %u/%u pos: %u", (gci >> 32), Uint32(gci),
+             Uint32(bucket - buckets));
+
+  verify_known_gci(false);
+
+  /**
+   * Copy data
+   */
+  if(!bucket->m_data.is_empty())
+  {
+#ifdef VM_TRACE
+    assert(bucket->m_data.m_count);
+#endif
+    m_complete_data.m_data.append_list(&bucket->m_data, gci);
+  }
+
+  Uint32 minpos = m_min_gci_index;
+  Uint32 mask = m_known_gci.size() - 1;
+
+  bzero(bucket, sizeof(Gci_container));
+
+  m_min_gci_index = (minpos + 1) & mask;
+
+  verify_known_gci(true);
+}
+
+void
 NdbEventBuffer::execSUB_GCP_COMPLETE_REP(const SubGcpCompleteRep * const rep)
 {
   if (unlikely(m_active_op_count == 0))
@@ -1506,15 +1674,17 @@
   
   DBUG_ENTER_EVENT("NdbEventBuffer::execSUB_GCP_COMPLETE_REP");
 
-  const Uint64 gci= rep->gci;
+  Uint32 gci_hi = rep->gci_hi;
+  Uint32 gci_lo = rep->gci_lo;
+  const Uint64 gci= gci_lo | (Uint64(gci_hi) << 32);
   const Uint32 cnt= rep->gcp_complete_rep_count;
 
-  Gci_container *bucket = find_bucket(&m_active_gci, gci
-#ifdef VM_TRACE
-                                      , m_flush_gci
-#endif
-                                      );
-  Uint32 idx = bucket - (Gci_container*)m_active_gci.getBase();
+  Gci_container *bucket = find_bucket(gci);
+
+  if (0)
+    ndbout_c("execSUB_GCP_COMPLETE_REP(%u/%u) from %x",
+             (gci >> 32), Uint32(gci), rep->senderRef);
+
   if (unlikely(bucket == 0))
   {
     /**
@@ -1522,11 +1692,16 @@
      *   Possible in case of resend during NF handling
      */
 #ifdef VM_TRACE
-    ndbout << "bucket == 0, gci:" << gci
-	   << " complete: " << m_complete_data << endl;
+    Uint64 minGCI = m_known_gci[m_min_gci_index];
+    ndbout_c("bucket == 0, gci: %u/%u minGCI: %u/%u m_latestGCI: %u/%u",
+             Uint32(gci >> 32), Uint32(gci),
+             Uint32(minGCI >> 32), Uint32(minGCI),
+             Uint32(m_latestGCI >> 32), Uint32(m_latestGCI));
+    ndbout << " complete: " << m_complete_data << endl;
     for(Uint32 i = 0; i<m_active_gci.size(); i++)
     {
-      ndbout << i << " - " << m_active_gci[i] << endl;
+      if (((Gci_container*)(&m_active_gci[i]))->m_gci)
+        ndbout << i << " - " << m_active_gci[i] << endl;
     }
 #endif
     DBUG_VOID_RETURN_EVENT;
@@ -1547,31 +1722,12 @@
   
   if(old_cnt == cnt)
   {
-    if(likely(gci == m_latestGCI + 1 || m_latestGCI == 0))
+    Uint64 minGCI = m_known_gci[m_min_gci_index];
+    if(likely(minGCI == 0 || gci == minGCI))
     {
+      complete_bucket(bucket);
       m_latestGCI = m_complete_data.m_gci = gci; // before reportStatus
-      if(!bucket->m_data.is_empty())
-      {
-#ifdef VM_TRACE
-	assert(bucket->m_data.m_count);
-#endif
-	m_complete_data.m_data.append_list(&bucket->m_data, gci);
-      }
       reportStatus();
-      bzero(bucket, sizeof(Gci_container));
-      if (likely(idx < ACTIVE_GCI_DIRECTORY_SIZE))
-      {
-        /**
-         * Only "prepare" next GCI if we're in
-         *   the first 4 highest GCI's...else
-         *   this is somekind of "late" GCI...
-         *   which is only initialized to 0
-         *
-         *   This to make sure we dont get several buckets with same GCI
-         */
-        bucket->m_gci = gci + ACTIVE_GCI_DIRECTORY_SIZE;
-        bucket->m_gcp_complete_rep_count = m_system_nodes;
-      }
       
       if(unlikely(m_latest_complete_GCI > gci))
       {
@@ -1585,9 +1741,11 @@
     else
     {
       /** out of order something */
-      ndbout_c("out of order bucket: %d  gci: %ld  m_latestGCI: %ld", 
-	       (int) (bucket-(Gci_container*)m_active_gci.getBase()), 
-	       (long) gci, (long) m_latestGCI);
+      g_eventLogger.info("out of order bucket: %d gci: %u/%u minGCI: %u/%u m_latestGCI: %u/%u",
+                         (int)(bucket-(Gci_container*)m_active_gci.getBase()),
+                         Uint32(gci >> 32), Uint32(gci),
+                         Uint32(minGCI >> 32), Uint32(minGCI),
+                         Uint32(m_latestGCI >> 32), Uint32(m_latestGCI));
       bucket->m_state = Gci_container::GC_COMPLETE;
       bucket->m_gcp_complete_rep_count = 1; // Prevent from being reused
       m_latest_complete_GCI = gci;
@@ -1600,64 +1758,46 @@
 void
 NdbEventBuffer::complete_outof_order_gcis()
 {
-  Uint64 start_gci = m_latestGCI + 1;
-  Uint64 stop_gci = m_latest_complete_GCI;
-  
-  const Uint32 size = m_active_gci.size();
-  Gci_container* array= (Gci_container*)m_active_gci.getBase();
+  verify_known_gci(false);
   
-  ndbout_c("complete_outof_order_gcis");
-  for(Uint32 i = 0; i<size; i++)
-  {
-    ndbout << i << " - " << array[i] << endl;
-  }
-  
-  for(; start_gci <= stop_gci; start_gci++)
+  Uint64 * array = m_known_gci.getBase();
+  Uint32 mask = m_known_gci.size() - 1;
+  Uint32 minpos = m_min_gci_index;
+  Uint32 maxpos = m_max_gci_index;
+  Uint64 stop_gci = m_latest_complete_GCI;
+
+  Uint64 start_gci = array[minpos];
+  g_eventLogger.info("complete_outof_order_gcis from: %u/%u to: %u/%u",
+                     Uint32(start_gci >> 32), Uint32(start_gci),
+                     Uint32(stop_gci >> 32), Uint32(stop_gci));
+
+  assert(start_gci <= stop_gci);
+  do
   {
-    /**
-     * Find gci
-     */
-    Uint32 i;
-    Gci_container* bucket= 0;
-    for(i = 0; i<size; i++)
-    {
-      Gci_container* tmp = array + i;
-      if(tmp->m_gci == start_gci && tmp->m_state == Gci_container::GC_COMPLETE)
-      {
-	bucket= tmp;
-	break;
-      }
-    }
-    if(bucket == 0)
+    Uint64 start_gci = array[minpos];
+    Gci_container* bucket = find_bucket(start_gci);
+    assert(bucket);
+    assert(maxpos == m_max_gci_index);
+    if (bucket->m_state != Gci_container::GC_COMPLETE)
     {
-      break;
+      verify_known_gci(false);
+      return;
     }
 
-    printf("complete_outof_order_gcis - completing %lld", start_gci);
-    if(!bucket->m_data.is_empty())
-    {
 #ifdef VM_TRACE
-      assert(bucket->m_data.m_count);
-#endif
-      m_complete_data.m_data.append_list(&bucket->m_data, start_gci);
-#ifdef VM_TRACE
-      ndbout_c(" moved %ld rows -> %ld", (long) bucket->m_data.m_count,
-	       (long) m_complete_data.m_data.m_count);
+    ndbout_c("complete_outof_order_gcis - completing %u/%u rows: %lu",
+             Uint32(start_gci), Uint32(start_gci), bucket->m_data.m_count);
 #else
-      ndbout_c(" ");
+    ndbout_c("complete_outof_order_gcis - completing %u/%u",
+             Uint32(start_gci), Uint32(start_gci));
 #endif
-    }
-    bzero(bucket, sizeof(Gci_container));
-    if(i < ACTIVE_GCI_DIRECTORY_SIZE)
-    {
-      bucket->m_gci = start_gci + ACTIVE_GCI_DIRECTORY_SIZE;
-      bucket->m_gcp_complete_rep_count = m_system_nodes;
-    }
     
+    complete_bucket(bucket);
     m_latestGCI = m_complete_data.m_gci = start_gci;
-  }
-  
-  ndbout_c("complete_outof_order_gcis: m_latestGCI: %lld", m_latestGCI);
+
+    verify_known_gci(true);
+    minpos = (minpos + 1) & mask;
+  } while (start_gci != stop_gci);
 }
 
 void
@@ -1667,7 +1807,7 @@
                              Uint32 &oid_ref)
 {
   NdbEventOperationImpl *dropped_ev_op = m_dropped_ev_op;
-  DBUG_PRINT("info", ("gci: %u", data.gci));
+  DBUG_PRINT("info", ("gci{hi/lo}: %u/%u", data.gci_hi, data.gci_lo));
   do
   {
     do
@@ -1714,7 +1854,9 @@
   SubTableData::setReqNodeId(data.requestInfo, node_id);
   SubTableData::setNdbdNodeId(data.requestInfo, node_id);
   data.logType = SubTableData::LOG;
-  data.gci = m_latestGCI + 1;
+  data.gci_hi = m_latestGCI + (Uint64(1) << 32);
+  data.gci_lo = 0;
+
   /**
    * Insert this event for each operation
    */
@@ -1743,7 +1885,9 @@
   SubTableData::setReqNodeId(data.requestInfo, node_id);
   SubTableData::setNdbdNodeId(data.requestInfo, node_id);
   data.logType = SubTableData::LOG;
-  data.gci = m_latestGCI + 1;
+  data.gci_hi = m_latestGCI + (Uint64(1) << 32);
+  data.gci_lo = 0;
+
   /**
    * Insert this event for each operation
    */
@@ -1770,7 +1914,8 @@
   SubTableData::setOperation(data.requestInfo,
 			     NdbDictionary::Event::_TE_CLUSTER_FAILURE);
   data.logType = SubTableData::LOG;
-  data.gci = m_latestGCI + 1;
+  data.gci_hi = m_latestGCI + (Uint64(1) << 32);
+  data.gci_lo = 0;
   
 #ifdef VM_TRACE
   m_flush_gci = 0;
@@ -1787,7 +1932,9 @@
    */
   Uint32 i;
   Uint32 sz= m_active_gci.size();
-  Uint64 gci= data.gci;
+  Uint32 gci_hi = data.gci_hi;
+  Uint32 gci_lo = data.gci_lo;
+  Uint64 gci= gci_lo | (Uint64(gci_hi) << 32);
   Gci_container* bucket = 0;
   Gci_container* array = (Gci_container*)m_active_gci.getBase();
   for(i = 0; i < sz; i++)
@@ -1813,8 +1960,8 @@
       // something is wrong, assert in debug, but try so salvage
       // in release
       ndbout_c("out of order bucket detected at cluster disconnect, "
-               "data.gci: %u.  tmp->m_gci: %u",
-               (unsigned)data.gci, (unsigned)tmp->m_gci);
+               "data.gci{hi/lo}: %u/%u tmp->m_gci: %u",
+               (unsigned)data.gci_hi, data.gci_lo, (unsigned)tmp->m_gci);
       assert(false);
       if(!tmp->m_data.is_empty())
       {
@@ -1839,7 +1986,8 @@
    * And finally complete this GCI
    */
   SubGcpCompleteRep rep;
-  rep.gci= gci;
+  rep.gci_hi= gci >> 32;
+  rep.gci_lo= gci & 0xFFFFFFFF;
   rep.gcp_complete_rep_count= cnt;
   execSUB_GCP_COMPLETE_REP(&rep);
 
@@ -1860,7 +2008,9 @@
   DBUG_ENTER_EVENT("NdbEventBuffer::insertDataL");
   const Uint32 ri = sdata->requestInfo;
   const Uint32 operation = SubTableData::getOperation(ri);
-  Uint64 gci= sdata->gci;
+  Uint32 gci_hi = sdata->gci_hi;
+  Uint32 gci_lo = sdata->gci_lo;
+  Uint64 gci= gci_lo | (Uint64(gci_hi) << 32);
   const bool is_data_event = 
     operation < NdbDictionary::Event::_TE_FIRST_NON_DATA_EVENT;
 
@@ -1939,11 +2089,7 @@
   
   if ( likely((Uint32)op->mi_type & (1 << operation)))
   {
-    Gci_container* bucket= find_bucket(&m_active_gci, gci
-#ifdef VM_TRACE
-                                       , m_flush_gci
-#endif
-                                       );
+    Gci_container* bucket= find_bucket(gci);
     
     DBUG_PRINT_EVENT("info", ("data insertion in eventId %d", op->m_eventId));
     DBUG_PRINT_EVENT("info", ("gci=%d tab=%d op=%d node=%d",
@@ -2102,10 +2248,12 @@
       printf("no free data, m_latestGCI %lld\n",
              m_latestGCI);
       printf("m_free_data_count %d\n", m_free_data_count);
-      printf("m_available_data_count %d first gci %d last gci %d\n",
+      printf("m_available_data_count %d first gci{hi/lo} %u/%u last gci{hi/lo} %u/%u\n",
              m_available_data.m_count,
-             m_available_data.m_head ? m_available_data.m_head->sdata->gci : 0,
-             m_available_data.m_tail ? m_available_data.m_tail->sdata->gci : 0);
+             m_available_data.m_head?m_available_data.m_head->sdata->gci_hi:0,
+             m_available_data.m_head?m_available_data.m_head->sdata->gci_lo:0,
+             m_available_data.m_tail?m_available_data.m_tail->sdata->gci_hi:0,
+             m_available_data.m_tail?m_available_data.m_tail->sdata->gci_lo:0);
       printf("m_used_data_count %d\n", m_used_data.m_count);
 #endif
       DBUG_RETURN_EVENT(0); // TODO handle this, overrun, or, skip?
@@ -2869,7 +3017,11 @@
   if (apply_buf == 0)
     apply_buf= m_complete_data.m_data.m_head;
   if (apply_buf)
-    apply_gci= apply_buf->sdata->gci;
+  {
+    Uint32 gci_hi = apply_buf->sdata->gci_hi;
+    Uint32 gci_lo = apply_buf->sdata->gci_lo;
+    apply_gci= gci_lo | (Uint64(gci_hi) << 32);
+  }
   else
     apply_gci= latest_gci;
 
@@ -2920,6 +3072,7 @@
 void
 NdbEventBuffer::verify_size(const EventBufData* data, Uint32 count, Uint32 sz)
 {
+#if 0
   Uint32 tmp_count = 0;
   Uint32 tmp_sz = 0;
   while (data != 0) {
@@ -2931,11 +3084,14 @@
   }
   assert(tmp_count == count);
   assert(tmp_sz == sz);
+#endif
 }
 void
 NdbEventBuffer::verify_size(const EventBufData_list & list)
 {
+#if 0
   verify_size(list.m_head, list.m_count, list.m_sz);
+#endif
 }
 #endif
 
@@ -3061,5 +3217,6 @@
   DBUG_VOID_RETURN_EVENT;
 }
 
+template class Vector<Uint64>;
 template class Vector<Gci_container_pod>;
 template class Vector<NdbEventBuffer::EventBufData_chunk*>;

--- 1.38/storage/ndb/src/ndbapi/NdbEventOperationImpl.hpp	2007-08-24 16:17:57 +02:00
+++ 1.39/storage/ndb/src/ndbapi/NdbEventOperationImpl.hpp	2007-08-24 16:17:57 +02:00
@@ -323,8 +323,8 @@
     GC_COMPLETE = 0x1 // GCI is complete, but waiting for out of order
   };
   
-  Uint32 m_state;
-  Uint32 m_gcp_complete_rep_count; // Remaining SUB_GCP_COMPLETE_REP until done
+  Uint16 m_state;
+  Uint16 m_gcp_complete_rep_count; // Remaining SUB_GCP_COMPLETE_REP until done
   Uint64 m_gci;                    // GCI
   EventBufData_list m_data;
   EventBufData_hash m_data_hash;
@@ -488,7 +488,14 @@
   ~NdbEventBuffer();
 
   const Uint32 &m_system_nodes;
+
+  Uint16 m_min_gci_index;
+  Uint16 m_max_gci_index;
+  Vector<Uint64> m_known_gci;
   Vector<Gci_container_pod> m_active_gci;
+  STATIC_CONST( ACTIVE_GCI_DIRECTORY_SIZE = 4 );
+  STATIC_CONST( ACTIVE_GCI_MASK = ACTIVE_GCI_DIRECTORY_SIZE - 1 );
+
   NdbEventOperation *createEventOperation(const char* eventName,
 					  NdbError &);
   NdbEventOperationImpl *createEventOperationImpl(NdbEventImpl& evnt,
@@ -624,6 +631,21 @@
 
   Uint32 m_active_op_count;
   NdbMutex *m_add_drop_mutex;
+
+  inline Gci_container* find_bucket(Uint64 gci){
+    Uint32 pos = (gci & ACTIVE_GCI_MASK);
+    Gci_container *bucket= ((Gci_container*)(m_active_gci.getBase())) + pos;
+    if(likely(gci == bucket->m_gci))
+      return bucket;
+
+    return find_bucket_chained(gci);
+  }
+
+#ifdef VM_TRACE
+  void verify_known_gci(bool allowempty);
+#endif
+  Gci_container* find_bucket_chained(Uint64 gci);
+  void complete_bucket(Gci_container*);
 };
 
 inline

--- 1.52/storage/ndb/src/ndbapi/Ndbif.cpp	2007-08-24 16:17:57 +02:00
+++ 1.53/storage/ndb/src/ndbapi/Ndbif.cpp	2007-08-24 16:17:57 +02:00
@@ -758,9 +758,9 @@
       ptr[i].p = NULL;
       ptr[i].sz = 0;
     }
-    DBUG_PRINT("info",("oid=senderData: %d, gci: %d, operation: %d, "
+    DBUG_PRINT("info",("oid=senderData: %d, gci{hi/lo}: %d/%d, operation: %d, "
 		       "tableId: %d",
-		       sdata->senderData, sdata->gci, 
+		       sdata->senderData, sdata->gci_hi, sdata->gci_lo,
 		       SubTableData::getOperation(sdata->requestInfo),
 		       sdata->tableId));
 

--- 1.17/storage/ndb/test/include/NdbRestarter.hpp	2007-08-24 16:17:57 +02:00
+++ 1.18/storage/ndb/test/include/NdbRestarter.hpp	2007-08-24 16:17:57 +02:00
@@ -87,6 +87,15 @@
   int getRandomNotMasterNodeId(int randomNumber);
   
   NdbMgmHandle handle;  
+
+  enum NodeSelector
+  {
+    NS_RANDOM     = 0, // Any node
+    NS_MASTER     = 1, // Master node
+    NS_NON_MASTER = 2
+  };
+
+  int getNode(NodeSelector);
   
 protected:
 

--- 1.70/storage/ndb/test/ndbapi/testNodeRestart.cpp	2007-08-24 16:17:57 +02:00
+++ 1.71/storage/ndb/test/ndbapi/testNodeRestart.cpp	2007-08-24 16:17:57 +02:00
@@ -1762,6 +1762,92 @@
   return NDBT_OK;
 }
 
+static
+int
+f_master_failure [] = {
+  7000, 7001, 7002, 7003, 7004, 7186, 7187, 7188, 7189, 7190, 0
+};
+
+static
+int
+f_participant_failure [] = {
+  7005, 7006, 7007, 7008, 5000, 0
+};
+
+int
+runerrors(NdbRestarter& res, NdbRestarter::NodeSelector sel, const int* errors)
+{
+  for (Uint32 i = 0; errors[i]; i++)
+  {
+    int node = res.getNode(sel);
+
+    int val2[] = { DumpStateOrd::CmvmiSetRestartOnErrorInsert, 1 };
+    if (res.dumpStateOneNode(node, val2, 2))
+      return NDBT_FAILED;
+
+    ndbout << "node " << node << " err: " << errors[i]<< endl;
+    if (res.insertErrorInNode(node, errors[i]))
+      return NDBT_FAILED;
+
+    if (res.waitNodesNoStart(&node, 1) != 0)
+      return NDBT_FAILED;
+
+    res.startNodes(&node, 1);
+
+    if (res.waitClusterStarted() != 0)
+      return NDBT_FAILED;
+  }
+  return NDBT_OK;
+}
+
+int
+runGCP(NDBT_Context* ctx, NDBT_Step* step)
+{
+  int result = NDBT_OK;
+  NdbRestarter res;
+  int loops = ctx->getNumLoops();
+
+  if (res.getNumDbNodes() < 2)
+  {
+    return NDBT_OK;
+  }
+
+  if (res.getNumDbNodes() < 4)
+  {
+    /**
+     * 7186++ is only usable for 4 nodes and above
+     */
+    Uint32 i;
+    for (i = 0; f_master_failure[i] && f_master_failure[i] != 7186; i++);
+    f_master_failure[i] = 0;
+  }
+
+  while (loops >= 0 && !ctx->isTestStopped())
+  {
+    loops --;
+
+#if 0
+    if (runerrors(res, NdbRestarter::NS_NON_MASTER, f_participant_failure))
+    {
+      return NDBT_FAILED;
+    }
+
+    if (runerrors(res, NdbRestarter::NS_MASTER, f_participant_failure))
+    {
+      return NDBT_FAILED;
+    }
+#endif
+
+    if (runerrors(res, NdbRestarter::NS_MASTER, f_master_failure))
+    {
+      return NDBT_FAILED;
+    }
+  }
+  ctx->stopTest();
+
+  return NDBT_OK;
+}
+
 NDBT_TESTSUITE(testNodeRestart);
 TESTCASE("NoLoad", 
 	 "Test that one node at a time can be stopped and then restarted "\
@@ -2127,6 +2213,12 @@
 }
 TESTCASE("Bug29364", ""){
   INITIALIZER(runBug29364);
+}
+TESTCASE("GCP", ""){
+  INITIALIZER(runLoadTable);
+  STEP(runGCP);
+  STEP(runScanUpdateUntilStopped);
+  FINALIZER(runClearTable);
 }
 NDBT_TESTSUITE_END(testNodeRestart);
 

--- 1.21/storage/ndb/test/src/NdbRestarter.cpp	2007-08-24 16:17:57 +02:00
+++ 1.22/storage/ndb/test/src/NdbRestarter.cpp	2007-08-24 16:17:57 +02:00
@@ -747,4 +747,20 @@
   return m_config;
 }
 
+int
+NdbRestarter::getNode(NodeSelector type)
+{
+  switch(type){
+  case NS_RANDOM:
+    return getDbNodeId(rand() % getNumDbNodes());
+  case NS_MASTER:
+    return getMasterNodeId();
+  case NS_NON_MASTER:
+    return getRandomNotMasterNodeId(rand());
+  default:
+    abort();
+  }
+  return -1;
+}
+
 template class Vector<ndb_mgm_node_state>;

--- 1.8/storage/ndb/test/tools/listen.cpp	2007-08-24 16:17:57 +02:00
+++ 1.9/storage/ndb/test/tools/listen.cpp	2007-08-24 16:17:57 +02:00
@@ -353,7 +353,8 @@
       } while ((pOp= MyNdb.nextEvent()) && gci == pOp->getGCI());
       if (ndb2)
         do_commit(trans_arg);
-      ndbout_c("GCI: %lld events: %lld(I) %lld(U) %lld(D)", gci, cnt_i, cnt_u, cnt_d);
+      ndbout_c("GCI: %u/%u events: %lld(I) %lld(U) %lld(D)",
+               Uint32(gci >> 32), Uint32(gci), cnt_i, cnt_u, cnt_d);
     }
   }
 end:
Thread
bk commit into 5.1 tree (jonas:1.2612)jonas24 Aug