List:Commits« Previous MessageNext Message »
From:jonas oreland Date:April 17 2011 6:26pm
Subject:bzr push into mysql-5.1-telco-7.0-spj-scan-vs-scan branch (jonas:3478 to
3479)
View as plain text  
 3479 jonas oreland	2011-04-17 [merge]
      ndb - merge 70 to 70-spj

    added:
      storage/ndb/include/kernel/signaldata/DihRestart.hpp
    modified:
      mysql-test/suite/funcs_1/r/ndb_storedproc_06.result
      mysql-test/suite/ndb/my.cnf
      mysql-test/suite/ndb_binlog/my.cnf
      mysql-test/suite/ndb_binlog/t/ndb_binlog_variants.cnf
      mysql-test/suite/ndb_team/my.cnf
      mysql-test/suite/rpl_ndb/my.cnf
      mysql-test/suite/rpl_ndb/r/rpl_ndb_relayrotate.result
      mysql-test/suite/rpl_ndb/t/rpl_ndb_relayrotate-slave.opt
      mysql-test/suite/rpl_ndb/t/rpl_ndb_relayrotate.test
      storage/ndb/include/kernel/ndb_limits.h
      storage/ndb/include/mgmapi/mgmapi_config_parameters.h
      storage/ndb/include/ndbapi/Ndb.hpp
      storage/ndb/src/common/debugger/EventLogger.cpp
      storage/ndb/src/kernel/blocks/cmvmi/Cmvmi.cpp
      storage/ndb/src/kernel/blocks/dbdih/Dbdih.hpp
      storage/ndb/src/kernel/blocks/dbdih/DbdihMain.cpp
      storage/ndb/src/kernel/blocks/dbtup/DbtupRoutines.cpp
      storage/ndb/src/kernel/blocks/ndbcntr/NdbcntrMain.cpp
      storage/ndb/src/kernel/blocks/qmgr/Qmgr.hpp
      storage/ndb/src/kernel/blocks/qmgr/QmgrMain.cpp
      storage/ndb/src/kernel/vm/Configuration.cpp
      storage/ndb/src/kernel/vm/Configuration.hpp
      storage/ndb/src/kernel/vm/NdbinfoTables.cpp
      storage/ndb/src/mgmsrv/ConfigInfo.cpp
      storage/ndb/src/mgmsrv/MgmtSrvr.cpp
      storage/ndb/src/mgmsrv/MgmtSrvr.hpp
      storage/ndb/src/ndbapi/Ndb.cpp
      storage/ndb/src/ndbapi/NdbImpl.hpp
      storage/ndb/src/ndbapi/Ndbinit.cpp
      storage/ndb/src/ndbapi/ndb_cluster_connection.cpp
      storage/ndb/test/include/NDBT_Tables.hpp
      storage/ndb/test/ndbapi/testIndex.cpp
      storage/ndb/test/run-test/daily-basic-tests.txt
      storage/ndb/test/src/NDBT_Tables.cpp
      storage/ndb/tools/ndbinfo_sql.cpp
 3478 Ole John Aske	2011-04-14
      Minor refactoring to fix that both 'NdbImpl* const ndb' and 'NdbImpl* const impl' 
      was declared - Both referring the same NdbImpl object.

    modified:
      storage/ndb/src/ndbapi/NdbQueryOperation.cpp
=== modified file 'mysql-test/suite/funcs_1/r/ndb_storedproc_06.result'
--- a/mysql-test/suite/funcs_1/r/ndb_storedproc_06.result	2010-03-22 10:32:17 +0000
+++ b/mysql-test/suite/funcs_1/r/ndb_storedproc_06.result	2011-04-15 08:12:18 +0000
@@ -128,8 +128,6 @@ root@localhost	db_storedproc_1
 drop user 'user_1'@'localhost';
 DROP PROCEDURE sp3;
 DROP FUNCTION fn1;
-Warnings:
-Warning	1403	There is no such grant defined for user 'user_1' on host 'localhost' on routine 'fn1'
 
 Testcase 3.1.6.4:
 -----------------

=== modified file 'mysql-test/suite/ndb/my.cnf'
--- a/mysql-test/suite/ndb/my.cnf	2011-01-06 21:19:05 +0000
+++ b/mysql-test/suite/ndb/my.cnf	2011-04-17 18:25:41 +0000
@@ -39,7 +39,7 @@ NodeId=255
 # Make all mysqlds use cluster
 ndbcluster
 ndb-wait-connected=20
-ndb-wait-setup=60
+ndb-wait-setup=120
 ndb-cluster-connection-pool=3
 ndb-extra-logging=99
 ndb-join-pushdown=1

=== modified file 'mysql-test/suite/ndb_binlog/my.cnf'
--- a/mysql-test/suite/ndb_binlog/my.cnf	2009-10-23 14:31:33 +0000
+++ b/mysql-test/suite/ndb_binlog/my.cnf	2011-04-15 09:31:03 +0000
@@ -12,7 +12,7 @@ ndbapi=,,,,,,,,,,,
 # Make all mysqlds use cluster
 ndbcluster
 ndb-wait-connected=20
-ndb-wait-setup=60
+ndb-wait-setup=120
 ndb-cluster-connection-pool=3
 ndb-extra-logging=99
 

=== modified file 'mysql-test/suite/ndb_binlog/t/ndb_binlog_variants.cnf'
--- a/mysql-test/suite/ndb_binlog/t/ndb_binlog_variants.cnf	2009-10-23 14:02:54 +0000
+++ b/mysql-test/suite/ndb_binlog/t/ndb_binlog_variants.cnf	2011-04-15 09:31:03 +0000
@@ -15,7 +15,7 @@ ndbapi=,,,,,,,,,,,
 # Make all mysqlds use cluster
 ndbcluster
 ndb-wait-connected=20
-ndb-wait-setup=60
+ndb-wait-setup=120
 ndb-cluster-connection-pool=1
 binlog-format=row
 

=== modified file 'mysql-test/suite/ndb_team/my.cnf'
--- a/mysql-test/suite/ndb_team/my.cnf	2009-10-23 14:31:33 +0000
+++ b/mysql-test/suite/ndb_team/my.cnf	2011-04-15 09:31:03 +0000
@@ -19,7 +19,7 @@ ndbapi=,,,,
 # Make all mysqlds use cluster
 ndbcluster
 ndb-wait-connected=20
-ndb-wait-setup=60
+ndb-wait-setup=120
 ndb-cluster-connection-pool=3
 loose-slave-allow-batching
 loose-ndb-log-orig

=== modified file 'mysql-test/suite/rpl_ndb/my.cnf'
--- a/mysql-test/suite/rpl_ndb/my.cnf	2010-10-12 11:54:35 +0000
+++ b/mysql-test/suite/rpl_ndb/my.cnf	2011-04-15 12:21:13 +0000
@@ -1,6 +1,9 @@
 !include include/default_mysqld.cnf
 !include include/default_ndbd.cnf
 
+[cluster_config]
+TimeBetweenEpochsTimeout = 30000
+
 [cluster_config.1]
 NoOfReplicas=                  2
 ndbd=,
@@ -19,7 +22,7 @@ ndbapi=,,,,
 # Make all mysqlds use cluster
 ndbcluster
 ndb-wait-connected=20
-ndb-wait-setup=60
+ndb-wait-setup=120
 ndb-cluster-connection-pool=3
 slave-allow-batching
 ndb-log-orig

=== modified file 'mysql-test/suite/rpl_ndb/r/rpl_ndb_relayrotate.result'
--- a/mysql-test/suite/rpl_ndb/r/rpl_ndb_relayrotate.result	2007-06-27 12:28:02 +0000
+++ b/mysql-test/suite/rpl_ndb/r/rpl_ndb_relayrotate.result	2011-04-15 12:45:47 +0000
@@ -1,9 +1,5 @@
-stop slave;
-drop table if exists t1,t2,t3,t4,t5,t6,t7,t8,t9;
-reset master;
-reset slave;
-drop table if exists t1,t2,t3,t4,t5,t6,t7,t8,t9;
-start slave;
+include/master-slave.inc
+[connection master]
 stop slave;
 create table t1 (a int) engine=NDB;
 reset slave;
@@ -14,3 +10,4 @@ select max(a) from t1;
 max(a)
 8000
 drop table t1;
+include/rpl_end.inc

=== modified file 'mysql-test/suite/rpl_ndb/t/rpl_ndb_relayrotate-slave.opt'
--- a/mysql-test/suite/rpl_ndb/t/rpl_ndb_relayrotate-slave.opt	2007-06-27 12:28:02 +0000
+++ b/mysql-test/suite/rpl_ndb/t/rpl_ndb_relayrotate-slave.opt	2011-04-15 12:45:47 +0000
@@ -1,3 +1,3 @@
--O max_relay_log_size=16384
+--max_relay_log_size=16384
 --loose-innodb
 --log-warnings

=== modified file 'mysql-test/suite/rpl_ndb/t/rpl_ndb_relayrotate.test'
--- a/mysql-test/suite/rpl_ndb/t/rpl_ndb_relayrotate.test	2011-04-08 11:06:53 +0000
+++ b/mysql-test/suite/rpl_ndb/t/rpl_ndb_relayrotate.test	2011-04-15 12:45:47 +0000
@@ -3,7 +3,6 @@
 # to reuse test code between engine runs                   #
 ############################################################
 -- source include/have_ndb.inc
--- source include/have_ndb_extra.inc
 -- source suite/rpl_ndb/ndb_master-slave.inc
 let $engine_type=NDB;
 -- source extra/rpl_tests/rpl_relayrotate.test

=== modified file 'storage/ndb/include/kernel/ndb_limits.h'
--- a/storage/ndb/include/kernel/ndb_limits.h	2011-04-12 08:57:18 +0000
+++ b/storage/ndb/include/kernel/ndb_limits.h	2011-04-17 18:25:41 +0000
@@ -82,7 +82,7 @@
  * When sending a SUB_TABLE_DATA from SUMA to API
  *
  */
-#define MAX_SUMA_MESSAGE_IN_WORDS 8000
+#define MAX_SUMA_MESSAGE_IN_WORDS 8028
 
 /**
  * When sending a SUB_TABLE_DATA

=== added file 'storage/ndb/include/kernel/signaldata/DihRestart.hpp'
--- a/storage/ndb/include/kernel/signaldata/DihRestart.hpp	1970-01-01 00:00:00 +0000
+++ b/storage/ndb/include/kernel/signaldata/DihRestart.hpp	2011-04-15 13:52:53 +0000
@@ -0,0 +1,51 @@
+/*
+   Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved.
+
+   This program is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; version 2 of the License.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program; if not, write to the Free Software
+   Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301  USA
+*/
+
+#ifndef DIH_RESTART_HPP
+#define DIH_RESTART_HPP
+
+#include "SignalData.hpp"
+
+struct DihRestartReq
+{
+  STATIC_CONST( SignalLength = 1 );
+  Uint32 senderRef;
+
+  /**
+   * Qmgr checks if it can continue...using EXECUTE_DIRECT
+   *   and fields below, setting senderRef == 0
+   */
+  STATIC_CONST( CheckLength = 1 + NdbNodeBitmask::Size + MAX_NDB_NODES);
+  Uint32 nodemask[NdbNodeBitmask::Size];
+  Uint32 node_gcis[MAX_NDB_NODES];
+};
+
+struct DihRestartRef
+{
+  STATIC_CONST( SignalLength = NdbNodeBitmask::Size );
+  Uint32 no_nodegroup_mask[NdbNodeBitmask::Size];
+};
+
+struct DihRestartConf
+{
+  STATIC_CONST( SignalLength = 2 + NdbNodeBitmask::Size );
+  Uint32 unused;
+  Uint32 latest_gci;
+  Uint32 no_nodegroup_mask[NdbNodeBitmask::Size];
+};
+
+#endif

=== modified file 'storage/ndb/include/mgmapi/mgmapi_config_parameters.h'
--- a/storage/ndb/include/mgmapi/mgmapi_config_parameters.h	2011-04-09 15:48:21 +0000
+++ b/storage/ndb/include/mgmapi/mgmapi_config_parameters.h	2011-04-15 13:52:53 +0000
@@ -184,6 +184,8 @@
 
 #define CFG_DB_CONNECT_CHECK_DELAY    618
 
+#define CFG_DB_START_NO_NODEGROUP_TIMEOUT 619
+
 #define CFG_NODE_ARBIT_RANK           200
 #define CFG_NODE_ARBIT_DELAY          201
 #define CFG_RESERVED_SEND_BUFFER_MEMORY 202

=== modified file 'storage/ndb/include/ndbapi/Ndb.hpp'
--- a/storage/ndb/include/ndbapi/Ndb.hpp	2011-02-09 14:59:39 +0000
+++ b/storage/ndb/include/ndbapi/Ndb.hpp	2011-04-17 18:25:41 +0000
@@ -1757,6 +1757,10 @@ public:
   /* Get minimum known DB node version */
   Uint32 getMinDbNodeVersion() const;
 
+  /* Get/Set per-Ndb custom data pointer */
+  void setCustomData(void*);
+  void* getCustomData() const;
+  
   /* Some client behaviour counters to assist
    * optimisation
    */

=== modified file 'storage/ndb/src/common/debugger/EventLogger.cpp'
--- a/storage/ndb/src/common/debugger/EventLogger.cpp	2011-04-09 15:48:21 +0000
+++ b/storage/ndb/src/common/debugger/EventLogger.cpp	2011-04-15 13:52:53 +0000
@@ -964,7 +964,13 @@ void getTextStartReport(QQQQ) {
     bstr0 = BaseString::getPrettyText(sz, theData + 4 + (0 * sz)), 
     bstr1 = BaseString::getPrettyText(sz, theData + 4 + (1 * sz)), 
     bstr2 = BaseString::getPrettyText(sz, theData + 4 + (2 * sz)), 
-    bstr3 = BaseString::getPrettyText(sz, theData + 4 + (3 * sz));
+    bstr3 = BaseString::getPrettyText(sz, theData + 4 + (3 * sz)),
+    bstr4 = BaseString::getPrettyText(sz, theData + 4 + (4 * sz));
+
+  if (len < 4 + 5 * sz)
+  {
+    bstr4.assign("<unknown>");
+  }
 
   switch(theData[1]){
   case 1: // Wait initial
@@ -1002,6 +1008,24 @@ void getTextStartReport(QQQQ) {
        "nodes [ all: %s connected: %s missing: %s no-wait: %s ]",
        time, bstr0.c_str(), bstr1.c_str(), bstr3.c_str(), bstr2.c_str());
     break;
+  case 6:
+    BaseString::snprintf
+      (m_text, m_text_len,
+       "Initial start, waiting %u for %s to connect, "
+       "nodes [ all: %s connected: %s missing: %s no-wait: %s no-nodegroup: %s ]",
+       time, bstr4.c_str(),
+       bstr0.c_str(), bstr1.c_str(), bstr3.c_str(), bstr2.c_str(),
+       bstr4.c_str());
+    break;
+  case 7: // Wait no-nodes/partial timeout
+    BaseString::snprintf
+      (m_text, m_text_len,
+       "Waiting %u sec for nodes %s to connect, "
+       "nodes [ all: %s connected: %s no-wait: %s no-nodegroup: %s ]",
+       time, bstr3.c_str(), bstr0.c_str(), bstr1.c_str(), bstr2.c_str(),
+       bstr4.c_str());
+    break;
+
   case 0x8000: // Do initial
     BaseString::snprintf
       (m_text, m_text_len,

=== modified file 'storage/ndb/src/kernel/blocks/cmvmi/Cmvmi.cpp'
--- a/storage/ndb/src/kernel/blocks/cmvmi/Cmvmi.cpp	2011-04-10 17:32:41 +0000
+++ b/storage/ndb/src/kernel/blocks/cmvmi/Cmvmi.cpp	2011-04-17 18:25:41 +0000
@@ -2108,7 +2108,8 @@ void Cmvmi::execDBINFO_SCANREQ(Signal *s
     const NodeState& nodeState = getNodeState();
     const Uint32 start_level = nodeState.startLevel;
     const NDB_TICKS uptime = (NdbTick_CurrentMillisecond()/1000) - m_start_time;
-
+    Uint32 generation = m_ctx.m_config.get_config_generation(); 
+ 
     Ndbinfo::Row row(signal, req);
     row.write_uint32(getOwnNodeId()); // Node id
 
@@ -2116,6 +2117,7 @@ void Cmvmi::execDBINFO_SCANREQ(Signal *s
     row.write_uint32(start_level);
     row.write_uint32(start_level == NodeState::SL_STARTING ?
                      nodeState.starting.startPhase : 0);
+    row.write_uint32(generation);
     ndbinfo_send_row(signal, req, row, rl);
     break;
   }

=== modified file 'storage/ndb/src/kernel/blocks/dbdih/Dbdih.hpp'
--- a/storage/ndb/src/kernel/blocks/dbdih/Dbdih.hpp	2011-02-15 11:41:27 +0000
+++ b/storage/ndb/src/kernel/blocks/dbdih/Dbdih.hpp	2011-04-15 13:52:53 +0000
@@ -951,6 +951,7 @@ private:
   void replication(Uint32 noOfReplicas,
                    NodeGroupRecordPtr NGPtr,
                    FragmentstorePtr regFragptr);
+  void sendDihRestartRef(Signal*);
   void selectMasterCandidateAndSend(Signal *);
   void setLcpActiveStatusEnd(Signal*);
   void setLcpActiveStatusStart(Signal *);

=== modified file 'storage/ndb/src/kernel/blocks/dbdih/DbdihMain.cpp'
--- a/storage/ndb/src/kernel/blocks/dbdih/DbdihMain.cpp	2011-02-24 07:39:24 +0000
+++ b/storage/ndb/src/kernel/blocks/dbdih/DbdihMain.cpp	2011-04-17 18:25:41 +0000
@@ -79,6 +79,7 @@
 #include <signaldata/DropNodegroupImpl.hpp>
 #include <signaldata/DihGetTabInfo.hpp>
 #include <SectionReader.hpp>
+#include <signaldata/DihRestart.hpp>
 
 #include <EventLogger.hpp>
 extern EventLogger * g_eventLogger;
@@ -1455,15 +1456,18 @@ void Dbdih::execTAB_COMMITREQ(Signal* si
   3.2.1.1    LOADING   O W N   B L O C K  R E F E R E N C E (ABSOLUTE PHASE 1)
   *****************************************************************************
   */
-void Dbdih::execDIH_RESTARTREQ(Signal* signal) 
+void Dbdih::execDIH_RESTARTREQ(Signal* signal)
 {
   jamEntry();
-  if (signal->theData[0])
+  const DihRestartReq* req = CAST_CONSTPTR(DihRestartReq,
+                                           signal->getDataPtr());
+  if (req->senderRef != 0)
   {
     jam();
-    cntrlblockref = signal->theData[0];
-    if(m_ctx.m_config.getInitialStart()){
-      sendSignal(cntrlblockref, GSN_DIH_RESTARTREF, signal, 1, JBB);
+    cntrlblockref = req->senderRef;
+    if(m_ctx.m_config.getInitialStart())
+    {
+      sendDihRestartRef(signal);
     } else {
       readGciFileLab(signal);
     }
@@ -1476,8 +1480,8 @@ void Dbdih::execDIH_RESTARTREQ(Signal* s
      */
     Uint32 i;
     NdbNodeBitmask mask;
-    mask.assign(NdbNodeBitmask::Size, signal->theData + 1);
-    Uint32 *node_gcis = signal->theData+1+NdbNodeBitmask::Size;
+    mask.assign(NdbNodeBitmask::Size, req->nodemask);
+    const Uint32 *node_gcis = req->node_gcis;
     Uint32 node_group_gcis[MAX_NDB_NODES+1];
     bzero(node_group_gcis, sizeof(node_group_gcis));
     for (i = 0; i<MAX_NDB_NODES; i++)
@@ -4696,24 +4700,65 @@ void Dbdih::closingGcpLab(Signal* signal
     return;
   } else {
     jam();
-    sendSignal(cntrlblockref, GSN_DIH_RESTARTREF, signal, 1, JBB);
+    sendDihRestartRef(signal);
     return;
   }//if
 }//Dbdih::closingGcpLab()
 
+void
+Dbdih::sendDihRestartRef(Signal* signal)
+{
+  jam();
+
+  /**
+   * We couldn't read P0.Sysfile...
+   *   so compute no_nodegroup_mask from configuration
+   */
+  NdbNodeBitmask no_nodegroup_mask;
+
+  ndb_mgm_configuration_iterator * iter =
+    m_ctx.m_config.getClusterConfigIterator();
+  for(ndb_mgm_first(iter); ndb_mgm_valid(iter); ndb_mgm_next(iter))
+  {
+    jam();
+    Uint32 nodeId;
+    Uint32 nodeType;
+
+    ndbrequire(!ndb_mgm_get_int_parameter(iter,CFG_NODE_ID, &nodeId));
+    ndbrequire(!ndb_mgm_get_int_parameter(iter,CFG_TYPE_OF_SECTION,
+                                          &nodeType));
+
+    if (nodeType == NodeInfo::DB)
+    {
+      jam();
+      Uint32 ng;
+      if (ndb_mgm_get_int_parameter(iter, CFG_DB_NODEGROUP, &ng) == 0)
+      {
+        jam();
+        if (ng == NDB_NO_NODEGROUP)
+        {
+          no_nodegroup_mask.set(nodeId);
+        }
+      }
+    }
+  }
+  DihRestartRef * ref = CAST_PTR(DihRestartRef, signal->getDataPtrSend());
+  no_nodegroup_mask.copyto(NdbNodeBitmask::Size, ref->no_nodegroup_mask);
+  sendSignal(cntrlblockref, GSN_DIH_RESTARTREF, signal,
+             DihRestartRef::SignalLength, JBB);
+}
+
 /* ------------------------------------------------------------------------- */
 /*       SELECT THE MASTER CANDIDATE TO BE USED IN SYSTEM RESTARTS.          */
 /* ------------------------------------------------------------------------- */
 void Dbdih::selectMasterCandidateAndSend(Signal* signal)
 {
   setNodeGroups();
-  signal->theData[0] = getOwnNodeId();
-  signal->theData[1] = SYSFILE->lastCompletedGCI[getOwnNodeId()];
-  sendSignal(cntrlblockref, GSN_DIH_RESTARTCONF, signal, 2, JBB);
-  
+
   NodeRecordPtr nodePtr;
   Uint32 node_groups[MAX_NDB_NODES];
   memset(node_groups, 0, sizeof(node_groups));
+  NdbNodeBitmask no_nodegroup_mask;
   for (nodePtr.i = 1; nodePtr.i < MAX_NDB_NODES; nodePtr.i++) {
     jam();
     if (Sysfile::getNodeStatus(nodePtr.i, SYSFILE->nodeStatus) == Sysfile::NS_NotDefined)
@@ -4722,12 +4767,24 @@ void Dbdih::selectMasterCandidateAndSend
       continue;
     }
     const Uint32 ng = Sysfile::getNodeGroup(nodePtr.i, SYSFILE->nodeGroups);
-    if(ng != NO_NODE_GROUP_ID){
+    if(ng != NO_NODE_GROUP_ID)
+    {
       ndbrequire(ng < MAX_NDB_NODES);
       node_groups[ng]++;
     }
+    else
+    {
+      no_nodegroup_mask.set(nodePtr.i);
+    }
   }
-  
+
+  DihRestartConf * conf = CAST_PTR(DihRestartConf, signal->getDataPtrSend());
+  conf->unused = getOwnNodeId();
+  conf->latest_gci = SYSFILE->lastCompletedGCI[getOwnNodeId()];
+  no_nodegroup_mask.copyto(NdbNodeBitmask::Size, conf->no_nodegroup_mask);
+  sendSignal(cntrlblockref, GSN_DIH_RESTARTCONF, signal,
+             DihRestartConf::SignalLength, JBB);
+
   for (nodePtr.i = 0; nodePtr.i < MAX_NDB_NODES; nodePtr.i++) {
     jam();
     Uint32 count = node_groups[nodePtr.i];
@@ -4767,7 +4824,7 @@ void Dbdih::openingGcpErrorLab(Signal* s
     /*   CANNOT CONTINUE THE RESTART IN THIS CASE. TELL NDBCNTR OF OUR       */
     /*   FAILURE.                                                            */
     /*---------------------------------------------------------------------- */
-    sendSignal(cntrlblockref, GSN_DIH_RESTARTREF, signal, 1, JBB);
+    sendDihRestartRef(signal);
     return;
   }//if
 }//Dbdih::openingGcpErrorLab()
@@ -4799,7 +4856,7 @@ void Dbdih::closingGcpCrashLab(Signal* s
   /*     WE DISCOVERED A FAILURE WITH THE SECOND FILE AS WELL. THIS IS A     */
   /*     SERIOUS PROBLEM. REPORT FAILURE TO NDBCNTR.                         */
   /* ----------------------------------------------------------------------- */
-  sendSignal(cntrlblockref, GSN_DIH_RESTARTREF, signal, 1, JBB);
+  sendDihRestartRef(signal);
 }//Dbdih::closingGcpCrashLab()
 
 /*****************************************************************************/

=== modified file 'storage/ndb/src/kernel/blocks/dbtup/DbtupRoutines.cpp'
--- a/storage/ndb/src/kernel/blocks/dbtup/DbtupRoutines.cpp	2011-03-29 19:12:09 +0000
+++ b/storage/ndb/src/kernel/blocks/dbtup/DbtupRoutines.cpp	2011-04-17 18:25:41 +0000
@@ -3291,7 +3291,6 @@ Dbtup::read_lcp(const Uint32* inBuf, Uin
   dst[0] = req_struct->frag_page_id;
   dst[1] = req_struct->operPtrP->m_tuple_location.m_page_idx;
   ndbassert(req_struct->m_tuple_ptr->m_data != 0);
-  ndbassert(fixsz < 8192);
   memcpy(dst+2, req_struct->m_tuple_ptr->m_data, fixsz);
 
   if (varstart)

=== modified file 'storage/ndb/src/kernel/blocks/ndbcntr/NdbcntrMain.cpp'
--- a/storage/ndb/src/kernel/blocks/ndbcntr/NdbcntrMain.cpp	2011-02-24 07:39:24 +0000
+++ b/storage/ndb/src/kernel/blocks/ndbcntr/NdbcntrMain.cpp	2011-04-17 18:25:41 +0000
@@ -50,6 +50,7 @@
 #include <AttributeHeader.hpp>
 #include <Configuration.hpp>
 #include <DebuggerNames.hpp>
+#include <signaldata/DihRestart.hpp>
 
 #include <NdbOut.hpp>
 #include <NdbTick.h>
@@ -659,9 +660,11 @@ void Ndbcntr::startPhase2Lab(Signal* sig
 {
   c_start.m_lastGci = 0;
   c_start.m_lastGciNodeId = getOwnNodeId();
-  
-  signal->theData[0] = reference();
-  sendSignal(DBDIH_REF, GSN_DIH_RESTARTREQ, signal, 1, JBB);
+
+  DihRestartReq * req = CAST_PTR(DihRestartReq, signal->getDataPtrSend());
+  req->senderRef = reference();
+  sendSignal(DBDIH_REF, GSN_DIH_RESTARTREQ, signal,
+             DihRestartReq::SignalLength, JBB);
   return;
 }//Ndbcntr::startPhase2Lab()
 
@@ -671,8 +674,10 @@ void Ndbcntr::startPhase2Lab(Signal* sig
 void Ndbcntr::execDIH_RESTARTCONF(Signal* signal) 
 {
   jamEntry();
-  //cmasterDihId = signal->theData[0];
-  c_start.m_lastGci = signal->theData[1];
+
+  const DihRestartConf * conf = CAST_CONSTPTR(DihRestartConf,
+                                              signal->getDataPtrSend());
+  c_start.m_lastGci = conf->latest_gci;
   ctypeOfStart = NodeState::ST_SYSTEM_RESTART;
   cdihStartType = ctypeOfStart;
   ph2ALab(signal);

=== modified file 'storage/ndb/src/kernel/blocks/qmgr/Qmgr.hpp'
--- a/storage/ndb/src/kernel/blocks/qmgr/Qmgr.hpp	2011-04-10 17:32:41 +0000
+++ b/storage/ndb/src/kernel/blocks/qmgr/Qmgr.hpp	2011-04-17 18:25:41 +0000
@@ -127,6 +127,7 @@ public:
     NdbNodeBitmask m_skip_nodes;
     NdbNodeBitmask m_starting_nodes;
     NdbNodeBitmask m_starting_nodes_w_log;
+    NdbNodeBitmask m_no_nodegroup_nodes;
 
     Uint16 m_president_candidate;
     Uint32 m_president_candidate_gci;
@@ -508,6 +509,7 @@ private:
   Uint32 c_restartPartialTimeout;
   Uint32 c_restartPartionedTimeout;
   Uint32 c_restartFailureTimeout;
+  Uint32 c_restartNoNodegroupTimeout;
   Uint64 c_start_election_time;
 
   Uint16 creadyDistCom;

=== modified file 'storage/ndb/src/kernel/blocks/qmgr/QmgrMain.cpp'
--- a/storage/ndb/src/kernel/blocks/qmgr/QmgrMain.cpp	2011-04-10 17:32:41 +0000
+++ b/storage/ndb/src/kernel/blocks/qmgr/QmgrMain.cpp	2011-04-17 18:25:41 +0000
@@ -39,7 +39,7 @@
 #include <signaldata/EnableCom.hpp>
 #include <signaldata/RouteOrd.hpp>
 #include <signaldata/NodePing.hpp>
-
+#include <signaldata/DihRestart.hpp>
 #include <ndb_version.h>
 
 //#define DEBUG_QMGR_START
@@ -386,14 +386,15 @@ void Qmgr::startphase1(Signal* signal) 
 {
   jamEntry();
 
-  
   NodeRecPtr nodePtr;
   nodePtr.i = getOwnNodeId();
   ptrAss(nodePtr, nodeRec);
   nodePtr.p->phase = ZSTARTING;
-  
-  signal->theData[0] = reference();
-  sendSignal(DBDIH_REF, GSN_DIH_RESTARTREQ, signal, 1, JBB);
+
+  DihRestartReq * req = CAST_PTR(DihRestartReq, signal->getDataPtrSend());
+  req->senderRef = reference();
+  sendSignal(DBDIH_REF, GSN_DIH_RESTARTREQ, signal,
+             DihRestartReq::SignalLength, JBB);
   return;
 }
 
@@ -402,7 +403,11 @@ Qmgr::execDIH_RESTARTREF(Signal*signal)
 {
   jamEntry();
 
+  const DihRestartRef * ref = CAST_CONSTPTR(DihRestartRef,
+                                            signal->getDataPtr());
   c_start.m_latest_gci = 0;
+  c_start.m_no_nodegroup_nodes.assign(NdbNodeBitmask::Size,
+                                      ref->no_nodegroup_mask);
   execCM_INFOCONF(signal);
 }
 
@@ -410,8 +415,13 @@ void
 Qmgr::execDIH_RESTARTCONF(Signal*signal)
 {
   jamEntry();
-  
-  c_start.m_latest_gci = signal->theData[1];
+
+  const DihRestartConf * conf = CAST_CONSTPTR(DihRestartConf,
+                                              signal->getDataPtr());
+
+  c_start.m_latest_gci = conf->latest_gci;
+  c_start.m_no_nodegroup_nodes.assign(NdbNodeBitmask::Size,
+                                      conf->no_nodegroup_mask);
   execCM_INFOCONF(signal);
 }
 
@@ -1446,6 +1456,12 @@ Qmgr::check_startup(Signal* signal)
   Uint64 now = NdbTick_CurrentMillisecond();
   Uint64 partial_timeout = c_start_election_time + c_restartPartialTimeout;
   Uint64 partitioned_timeout = partial_timeout + c_restartPartionedTimeout;
+  Uint64 no_nodegroup_timeout = c_start_election_time +
+    c_restartNoNodegroupTimeout;
+
+  const bool no_nodegroup_active =
+    (c_restartNoNodegroupTimeout != ~Uint32(0)) &&
+    (! c_start.m_no_nodegroup_nodes.isclear());
 
   /**
    * First see if we should wait more...
@@ -1465,25 +1481,60 @@ Qmgr::check_startup(Signal* signal)
   if ((c_start.m_latest_gci == 0) || 
       (c_start.m_start_type == (1 << NodeState::ST_INITIAL_START)))
   {
-    if (!tmp.equal(c_definedNodes))
+    if (tmp.equal(c_definedNodes))
     {
       jam();
-      signal->theData[1] = 1;
-      signal->theData[2] = ~0;
-      report_mask.assign(wait);
-      retVal = 0;
+      signal->theData[1] = 0x8000;
+      report_mask.assign(c_definedNodes);
+      report_mask.bitANDC(c_start.m_starting_nodes);
+      retVal = 1;
       goto start_report;
     }
+    else if (no_nodegroup_active)
+    {
+      if (now < no_nodegroup_timeout)
+      {
+        signal->theData[1] = 6;
+        signal->theData[2] = Uint32((no_nodegroup_timeout - now + 500) / 1000);
+        report_mask.assign(wait);
+        retVal = 0;
+        goto start_report;
+      }
+      tmp.bitOR(c_start.m_no_nodegroup_nodes);
+      if (tmp.equal(c_definedNodes))
+      {
+        signal->theData[1] = 0x8000;
+        report_mask.assign(c_definedNodes);
+        report_mask.bitANDC(c_start.m_starting_nodes);
+        retVal = 1;
+        goto start_report;
+      }
+      else
+      {
+        jam();
+        signal->theData[1] = 1;
+        signal->theData[2] = ~0;
+        report_mask.assign(wait);
+        retVal = 0;
+        goto start_report;
+      }
+    }
     else
     {
       jam();
-      signal->theData[1] = 0x8000;
-      report_mask.assign(c_definedNodes);
-      report_mask.bitANDC(c_start.m_starting_nodes);
-      retVal = 1;
+      signal->theData[1] = 1;
+      signal->theData[2] = ~0;
+      report_mask.assign(wait);
+      retVal = 0;
       goto start_report;
     }
   }
+
+  if (now >= no_nodegroup_timeout)
+  {
+    tmp.bitOR(c_start.m_no_nodegroup_nodes);
+  }
+
   {
     const bool all = c_start.m_starting_nodes.equal(c_definedNodes);
     CheckNodeGroups* sd = (CheckNodeGroups*)&signal->theData[0];
@@ -1559,10 +1610,22 @@ Qmgr::check_startup(Signal* signal)
     if (now < partial_timeout)
     {
       jam();
+
       signal->theData[1] = c_restartPartialTimeout == (Uint32) ~0 ? 2 : 3;
       signal->theData[2] = Uint32((partial_timeout - now + 500) / 1000);
       report_mask.assign(wait);
       retVal = 0;
+
+      if (no_nodegroup_active && now < no_nodegroup_timeout)
+      {
+        signal->theData[1] = 7;
+        signal->theData[2] = Uint32((no_nodegroup_timeout - now + 500) / 1000);
+      }
+      else if (no_nodegroup_active && now >= no_nodegroup_timeout)
+      {
+        report_mask.bitANDC(c_start.m_no_nodegroup_nodes);
+      }
+
       goto start_report;
     }
   
@@ -1595,14 +1658,14 @@ check_log:
   {
     Uint32 save[4+4*NdbNodeBitmask::Size];
     memcpy(save, signal->theData, sizeof(save));
-    
-    signal->theData[0] = 0;
-    c_start.m_starting_nodes.copyto(NdbNodeBitmask::Size, signal->theData+1);
-    memcpy(signal->theData+1+NdbNodeBitmask::Size, c_start.m_node_gci,
-	   4*MAX_NDB_NODES);
-    EXECUTE_DIRECT(DBDIH, GSN_DIH_RESTARTREQ, signal, 
-		   1+NdbNodeBitmask::Size+MAX_NDB_NODES);
-    
+
+    DihRestartReq * req = CAST_PTR(DihRestartReq, signal->getDataPtrSend());
+    req->senderRef = 0;
+    c_start.m_starting_nodes.copyto(NdbNodeBitmask::Size, req->nodemask);
+    memcpy(req->node_gcis, c_start.m_node_gci, 4*MAX_NDB_NODES);
+    EXECUTE_DIRECT(DBDIH, GSN_DIH_RESTARTREQ, signal,
+		   DihRestartReq::CheckLength);
+
     incompleteng = signal->theData[0];
     memcpy(signal->theData, save, sizeof(save));
 
@@ -1650,8 +1713,9 @@ start_report:
     c_start.m_starting_nodes.copyto(sz, ptr); ptr += sz;
     c_start.m_skip_nodes.copyto(sz, ptr); ptr += sz;
     report_mask.copyto(sz, ptr); ptr+= sz;
-    sendSignal(CMVMI_REF, GSN_EVENT_REP, signal, 
-	       4+4*NdbNodeBitmask::Size, JBB);
+    c_start.m_no_nodegroup_nodes.copyto(sz, ptr); ptr += sz;
+    sendSignal(CMVMI_REF, GSN_EVENT_REP, signal,
+	       4+5*NdbNodeBitmask::Size, JBB);
   }
   return retVal;
   
@@ -2434,6 +2498,7 @@ void Qmgr::initData(Signal* signal) 
   c_restartPartialTimeout = 30000;
   c_restartPartionedTimeout = 60000;
   c_restartFailureTimeout = ~0;
+  c_restartNoNodegroupTimeout = 15000;
   ndb_mgm_get_int_parameter(p, CFG_DB_HEARTBEAT_INTERVAL, &hbDBDB);
   ndb_mgm_get_int_parameter(p, CFG_DB_ARBIT_TIMEOUT, &arbitTimeout);
   ndb_mgm_get_int_parameter(p, CFG_DB_ARBIT_METHOD, &arbitMethod);
@@ -2441,26 +2506,33 @@ void Qmgr::initData(Signal* signal) 
 			    &c_restartPartialTimeout);
   ndb_mgm_get_int_parameter(p, CFG_DB_START_PARTITION_TIMEOUT,
 			    &c_restartPartionedTimeout);
+  ndb_mgm_get_int_parameter(p, CFG_DB_START_NO_NODEGROUP_TIMEOUT,
+			    &c_restartNoNodegroupTimeout);
   ndb_mgm_get_int_parameter(p, CFG_DB_START_FAILURE_TIMEOUT,
 			    &c_restartFailureTimeout);
   ndb_mgm_get_int_parameter(p, CFG_DB_CONNECT_CHECK_DELAY,
                             &ccInterval);
- 
+
   if(c_restartPartialTimeout == 0)
   {
     c_restartPartialTimeout = ~0;
   }
-  
+
   if (c_restartPartionedTimeout ==0)
   {
     c_restartPartionedTimeout = ~0;
   }
-  
+
   if (c_restartFailureTimeout == 0)
   {
     c_restartFailureTimeout = ~0;
   }
 
+  if (c_restartNoNodegroupTimeout == 0)
+  {
+    c_restartNoNodegroupTimeout = ~0;
+  }
+
   setHbDelay(hbDBDB);
   setCCDelay(ccInterval);
   setArbitTimeout(arbitTimeout);

=== modified file 'storage/ndb/src/kernel/vm/Configuration.cpp'
--- a/storage/ndb/src/kernel/vm/Configuration.cpp	2011-03-29 12:32:02 +0000
+++ b/storage/ndb/src/kernel/vm/Configuration.cpp	2011-04-12 11:59:36 +0000
@@ -545,6 +545,16 @@ Configuration::getClusterConfigIterator(
   return m_clusterConfigIter;
 }
 
+Uint32 
+Configuration::get_config_generation() const {
+  Uint32 generation = ~0;
+  ndb_mgm_configuration_iterator sys_iter(*m_clusterConfig,
+                                          CFG_SECTION_SYSTEM);
+  sys_iter.get(CFG_SYS_CONFIG_GENERATION, &generation);
+  return generation;
+}
+ 
+
 void
 Configuration::calcSizeAlt(ConfigValues * ownConfig){
   const char * msg = "Invalid configuration fetched";

=== modified file 'storage/ndb/src/kernel/vm/Configuration.hpp'
--- a/storage/ndb/src/kernel/vm/Configuration.hpp	2011-02-01 23:27:25 +0000
+++ b/storage/ndb/src/kernel/vm/Configuration.hpp	2011-04-12 11:59:36 +0000
@@ -124,6 +124,7 @@ public:
   ndb_mgm_configuration_iterator * getClusterConfigIterator() const;
 
   ndb_mgm_configuration* getClusterConfig() const { return m_clusterConfig; }
+  Uint32 get_config_generation() const; 
 
 private:
   friend class Cmvmi;

=== modified file 'storage/ndb/src/kernel/vm/NdbinfoTables.cpp'
--- a/storage/ndb/src/kernel/vm/NdbinfoTables.cpp	2011-02-02 00:40:07 +0000
+++ b/storage/ndb/src/kernel/vm/NdbinfoTables.cpp	2011-04-12 11:59:36 +0000
@@ -141,14 +141,15 @@ DECLARE_NDBINFO_TABLE(COUNTERS,5) =
   }
 };
 
-DECLARE_NDBINFO_TABLE(NODES,4) =
-{ { "nodes", 4, 0, "node status" },
+DECLARE_NDBINFO_TABLE(NODES,5) =
+{ { "nodes", 5, 0, "node status" },
   {
     {"node_id",            Ndbinfo::Number, ""},
 
     {"uptime",             Ndbinfo::Number64, "time in seconds that node has been running"},
     {"status",             Ndbinfo::Number, "starting/started/stopped etc."},
-    {"start_phase",        Ndbinfo::Number, "start phase if node is starting"}
+    {"start_phase",        Ndbinfo::Number, "start phase if node is starting"},
+    {"config_generation",  Ndbinfo::Number, "configuration generation number"}
   }
 };
 

=== modified file 'storage/ndb/src/mgmsrv/ConfigInfo.cpp'
--- a/storage/ndb/src/mgmsrv/ConfigInfo.cpp	2011-04-09 15:48:21 +0000
+++ b/storage/ndb/src/mgmsrv/ConfigInfo.cpp	2011-04-15 13:52:53 +0000
@@ -977,7 +977,19 @@ const ConfigInfo::ParamInfo ConfigInfo::
     "0",
     "0",
     STR_VALUE(MAX_INT_RNIL) },
-  
+
+  {
+    CFG_DB_START_NO_NODEGROUP_TIMEOUT,
+    "StartNoNodegroupTimeout",
+    DB_TOKEN,
+    "Time to wait for nodes wo/ nodegroup before trying to start (0=forever)",
+    ConfigInfo::CI_USED,
+    0,
+    ConfigInfo::CI_INT,
+    "15000",
+    "0",
+    STR_VALUE(MAX_INT_RNIL) },
+
   {
     CFG_DB_HEARTBEAT_INTERVAL,
     "HeartbeatIntervalDbDb",

=== modified file 'storage/ndb/src/mgmsrv/MgmtSrvr.cpp'
--- a/storage/ndb/src/mgmsrv/MgmtSrvr.cpp	2011-02-03 14:20:36 +0000
+++ b/storage/ndb/src/mgmsrv/MgmtSrvr.cpp	2011-04-15 08:09:04 +0000
@@ -1050,6 +1050,187 @@ int MgmtSrvr::sendStopMgmd(NodeId nodeId
   return 0;
 }
 
+/**
+ * send STOP_REQ to all DB-nodes
+ *   and wait for them to stop or refuse
+ *
+ */
+int
+MgmtSrvr::sendall_STOP_REQ(NodeBitmask &stoppedNodes,
+                           bool abort,
+                           bool stop,
+                           bool restart,
+                           bool nostart,
+                           bool initialStart)
+{
+  int error = 0;
+  DBUG_ENTER("MgmtSrvr::sendall_STOP_REQ");
+  DBUG_PRINT("enter", ("abort: %d  stop: %d  restart: %d  "
+                       "nostart: %d  initialStart: %d",
+                       abort, stop, restart, nostart, initialStart));
+
+  stoppedNodes.clear();
+
+  SignalSender ss(theFacade);
+  ss.lock(); // lock will be released on exit
+
+  SimpleSignal ssig;
+  StopReq* const stopReq = CAST_PTR(StopReq, ssig.getDataPtrSend());
+  ssig.set(ss, TestOrd::TraceAPI, NDBCNTR, GSN_STOP_REQ, StopReq::SignalLength);
+
+  stopReq->requestInfo = 0;
+  stopReq->apiTimeout = 5000;
+  stopReq->transactionTimeout = 1000;
+  stopReq->readOperationTimeout = 1000;
+  stopReq->operationTimeout = 1000;
+  stopReq->senderData = 12;
+  stopReq->senderRef = ss.getOwnRef();
+  stopReq->singleuser = 0;
+  StopReq::setSystemStop(stopReq->requestInfo, stop);
+  StopReq::setPerformRestart(stopReq->requestInfo, restart);
+  StopReq::setStopAbort(stopReq->requestInfo, abort);
+  StopReq::setNoStart(stopReq->requestInfo, nostart);
+  StopReq::setInitialStart(stopReq->requestInfo, initialStart);
+
+  // send the signals
+  int failed = 0;
+  NodeBitmask nodes;
+  {
+    NodeId nodeId = 0;
+    while(getNextNodeId(&nodeId, NDB_MGM_NODE_TYPE_NDB))
+    {
+      if (okToSendTo(nodeId, true) == 0)
+      {
+	SendStatus result = ss.sendSignal(nodeId, &ssig);
+	if (result == SEND_OK)
+	  nodes.set(nodeId);
+        else
+          failed++;
+      }
+      else
+      {
+        failed++;
+      }
+    }
+  }
+
+  if (nodes.isclear() && failed > 0)
+  {
+    DBUG_RETURN(SEND_OR_RECEIVE_FAILED);
+  }
+
+  // now wait for the replies
+  while (!nodes.isclear())
+  {
+    SimpleSignal *signal = ss.waitFor();
+    int gsn = signal->readSignalNumber();
+    switch (gsn) {
+    case GSN_STOP_REF:
+    {
+      const StopRef * const ref = CAST_CONSTPTR(StopRef, signal->getDataPtr());
+      const NodeId nodeId = refToNode(signal->header.theSendersBlockRef);
+#ifdef VM_TRACE
+      ndbout_c("Node %d refused stop", nodeId);
+#endif
+      assert(nodes.get(nodeId));
+      nodes.clear(nodeId);
+      error = translateStopRef(ref->errorCode);
+      break;
+    }
+    case GSN_STOP_CONF:
+    {
+      const NodeId nodeId = refToNode(signal->header.theSendersBlockRef);
+      assert(nodes.get(nodeId));
+      nodes.clear(nodeId);
+      break;
+    }
+    case GSN_NF_COMPLETEREP:
+    {
+      const NFCompleteRep * rep = CAST_CONSTPTR(NFCompleteRep,
+                                                signal->getDataPtr());
+      nodes.clear(rep->failedNodeId); // clear the failed node
+      stoppedNodes.set(rep->failedNodeId);
+      break;
+    }
+    case GSN_NODE_FAILREP:
+    {
+      const NodeFailRep * rep = CAST_CONSTPTR(NodeFailRep,
+                                              signal->getDataPtr());
+      NodeBitmask mask;
+      mask.assign(NdbNodeBitmask::Size, rep->theNodes);
+      nodes.bitANDC(mask);
+      stoppedNodes.bitOR(mask);
+      break;
+    }
+    case GSN_API_REGCONF:
+    case GSN_TAKE_OVERTCCONF:
+    case GSN_CONNECT_REP:
+      continue;
+    default:
+      report_unknown_signal(signal);
+      DBUG_RETURN(SEND_OR_RECEIVE_FAILED);
+    }
+  }
+
+  DBUG_RETURN(error);
+}
+
+int
+MgmtSrvr::guess_master_node(SignalSender& ss)
+{
+  /**
+   * First check if m_master_node is started
+   */
+  NodeId guess = m_master_node;
+  if (guess != 0)
+  {
+    trp_node node = ss.getNodeInfo(guess);
+    if (node.m_state.startLevel == NodeState::SL_STARTED)
+      return guess;
+  }
+
+  /**
+   * Check for any started node
+   */
+  guess = 0;
+  while(getNextNodeId(&guess, NDB_MGM_NODE_TYPE_NDB))
+  {
+    trp_node node = ss.getNodeInfo(guess);
+    if (node.m_state.startLevel == NodeState::SL_STARTED)
+    {
+      return guess;
+    }
+  }
+
+  /**
+   * Check any confirmed node
+   */
+  guess = 0;
+  while(getNextNodeId(&guess, NDB_MGM_NODE_TYPE_NDB))
+  {
+    trp_node node = ss.getNodeInfo(guess);
+    if (node.is_confirmed())
+    {
+      return guess;
+    }
+  }
+
+  /**
+   * Check any connected node
+   */
+  guess = 0;
+  while(getNextNodeId(&guess, NDB_MGM_NODE_TYPE_NDB))
+  {
+    trp_node node = ss.getNodeInfo(guess);
+    if (node.is_connected())
+    {
+      return guess;
+    }
+  }
+
+  return 0; // give up
+}
+
 /*
  * Common method for handeling all STOP_REQ signalling that
  * is used by Stopping, Restarting and Single user commands
@@ -1068,8 +1249,7 @@ int MgmtSrvr::sendStopMgmd(NodeId nodeId
  */
 
 int MgmtSrvr::sendSTOP_REQ(const Vector<NodeId> &node_ids,
-			   NdbNodeBitmask &stoppedNodes,
-			   Uint32 singleUserNodeId,
+			   NodeBitmask &stoppedNodes,
 			   bool abort,
 			   bool stop,
 			   bool restart,
@@ -1079,30 +1259,69 @@ int MgmtSrvr::sendSTOP_REQ(const Vector<
 {
   int error = 0;
   DBUG_ENTER("MgmtSrvr::sendSTOP_REQ");
-  DBUG_PRINT("enter", ("no of nodes: %d  singleUseNodeId: %d  "
+  DBUG_PRINT("enter", ("no of nodes: %d "
                        "abort: %d  stop: %d  restart: %d  "
                        "nostart: %d  initialStart: %d",
-                       node_ids.size(), singleUserNodeId,
+                       node_ids.size(),
                        abort, stop, restart, nostart, initialStart));
 
   stoppedNodes.clear();
+  *stopSelf= 0;
+
+  NodeBitmask ndb_nodes_to_stop;
+  NodeBitmask mgm_nodes_to_stop;
 
   SignalSender ss(theFacade);
   ss.lock(); // lock will be released on exit
 
+  /**
+   * First verify arguments
+   */
+  for (unsigned i = 0; i < node_ids.size(); i++)
+  {
+    switch(getNodeType(node_ids[i])){
+    case NDB_MGM_NODE_TYPE_MGM:
+      mgm_nodes_to_stop.set(node_ids[i]);
+      break;
+    case NDB_MGM_NODE_TYPE_NDB:
+      ndb_nodes_to_stop.set(node_ids[i]);
+      break;
+    default:
+      DBUG_RETURN(WRONG_PROCESS_TYPE);
+    }
+  }
+
+  /**
+   * Process ndb_mgmd
+   */
+  for (Uint32 i = mgm_nodes_to_stop.find(0);
+       i != mgm_nodes_to_stop.NotFound;
+       i = mgm_nodes_to_stop.find(i + 1))
+  {
+    if (i != getOwnNodeId())
+    {
+      error= sendStopMgmd(i, abort, stop, restart,
+                          nostart, initialStart);
+      if (error == 0)
+      {
+        stoppedNodes.set(i);
+      }
+    }
+    else
+    {
+      g_eventLogger->info("Stopping this node");
+      * stopSelf = (restart)? -1 : 1;
+      stoppedNodes.set(i);
+    }
+  }
+
+  /**
+   * Process ndbd
+   */
   SimpleSignal ssig;
   StopReq* const stopReq = CAST_PTR(StopReq, ssig.getDataPtrSend());
   ssig.set(ss, TestOrd::TraceAPI, NDBCNTR, GSN_STOP_REQ, StopReq::SignalLength);
 
-  NdbNodeBitmask notstarted;
-  for (Uint32 i = 0; i<node_ids.size(); i++)
-  {
-    Uint32 nodeId = node_ids[i];
-    trp_node node = ss.getNodeInfo(nodeId);
-    if (node.m_state.startLevel != NodeState::SL_STARTED)
-      notstarted.set(nodeId);
-  }
-  
   stopReq->requestInfo = 0;
   stopReq->apiTimeout = 5000;
   stopReq->transactionTimeout = 1000;
@@ -1110,134 +1329,75 @@ int MgmtSrvr::sendSTOP_REQ(const Vector<
   stopReq->operationTimeout = 1000;
   stopReq->senderData = 12;
   stopReq->senderRef = ss.getOwnRef();
-  if (singleUserNodeId)
-  {
-    stopReq->singleuser = 1;
-    stopReq->singleUserApi = singleUserNodeId;
-    StopReq::setSystemStop(stopReq->requestInfo, false);
-    StopReq::setPerformRestart(stopReq->requestInfo, false);
-    StopReq::setStopAbort(stopReq->requestInfo, false);
+  stopReq->singleuser = 0;
+  StopReq::setSystemStop(stopReq->requestInfo, stop);
+  StopReq::setPerformRestart(stopReq->requestInfo, restart);
+  StopReq::setStopAbort(stopReq->requestInfo, abort);
+  StopReq::setNoStart(stopReq->requestInfo, nostart);
+  StopReq::setInitialStart(stopReq->requestInfo, initialStart);
+
+  int use_master_node = 0;
+  int do_send = 0;
+  if (ndb_nodes_to_stop.count() > 1)
+  {
+    do_send = 1;
+    use_master_node = 1;
+    ndb_nodes_to_stop.copyto(NdbNodeBitmask::Size, stopReq->nodes);
+    StopReq::setStopNodes(stopReq->requestInfo, 1);
   }
   else
   {
-    stopReq->singleuser = 0;
-    StopReq::setSystemStop(stopReq->requestInfo, stop);
-    StopReq::setPerformRestart(stopReq->requestInfo, restart);
-    StopReq::setStopAbort(stopReq->requestInfo, abort);
-    StopReq::setNoStart(stopReq->requestInfo, nostart);
-    StopReq::setInitialStart(stopReq->requestInfo, initialStart);
-  }
-
-  // send the signals
-  NdbNodeBitmask nodes;
-  NodeId nodeId= 0;
-  int use_master_node= 0;
-  int do_send= 0;
-  *stopSelf= 0;
-  NdbNodeBitmask nodes_to_stop;
-  {
-    for (unsigned i= 0; i < node_ids.size(); i++)
-    {
-      nodeId= node_ids[i];
-      g_eventLogger->info("Going to stop node %d", nodeId);
-
-      if ((getNodeType(nodeId) != NDB_MGM_NODE_TYPE_MGM)
-          &&(getNodeType(nodeId) != NDB_MGM_NODE_TYPE_NDB))
-        DBUG_RETURN(WRONG_PROCESS_TYPE);
-
-      if (getNodeType(nodeId) != NDB_MGM_NODE_TYPE_MGM)
-        nodes_to_stop.set(nodeId);
-      else if (nodeId != getOwnNodeId())
-      {
-        error= sendStopMgmd(nodeId, abort, stop, restart,
-                            nostart, initialStart);
-        if (error == 0)
-          stoppedNodes.set(nodeId);
-      }
-      else
-      {
-        g_eventLogger->info("Stopping this node");
-        *stopSelf= (restart)? -1 : 1;
-        stoppedNodes.set(nodeId);
-      }
-    }
-  }
-  int no_of_nodes_to_stop= nodes_to_stop.count();
-  if (node_ids.size())
-  {
-    if (no_of_nodes_to_stop)
+    Uint32 nodeId = ndb_nodes_to_stop.find(0);
+    if (okToSendTo(nodeId, true) == 0)
     {
-      do_send= 1;
-      if (no_of_nodes_to_stop == 1)
-      {
-        nodeId= nodes_to_stop.find(0);
-      }
-      else // multi node stop, send to master
+      SendStatus result = ss.sendSignal(nodeId, &ssig);
+      if (result != SEND_OK)
       {
-        use_master_node= 1;
-        nodes_to_stop.copyto(NdbNodeBitmask::Size, stopReq->nodes);
-        StopReq::setStopNodes(stopReq->requestInfo, 1);
+        DBUG_RETURN(SEND_OR_RECEIVE_FAILED);
       }
     }
-  }
-  else
-  {
-    nodeId= 0;
-    while(getNextNodeId(&nodeId, NDB_MGM_NODE_TYPE_NDB))
+    else
     {
-      if(okToSendTo(nodeId, true) == 0)
-      {
-	SendStatus result = ss.sendSignal(nodeId, &ssig);
-	if (result == SEND_OK)
-	  nodes.set(nodeId);
-      }
+      DBUG_RETURN(SEND_OR_RECEIVE_FAILED);
     }
   }
 
+
   // now wait for the replies
-  while (!nodes.isclear() || do_send)
+  Uint32 sendNodeId = ndb_nodes_to_stop.find(0);
+  while (!stoppedNodes.contains(ndb_nodes_to_stop))
   {
     if (do_send)
     {
-      int r;
-      assert(nodes.count() == 0);
-      if (use_master_node)
-        nodeId= m_master_node;
-      if ((r= okToSendTo(nodeId, true)) != 0)
-      {
-        bool next;
-        if (!use_master_node)
-          DBUG_RETURN(r);
-        m_master_node= nodeId= 0;
-        while((next= getNextNodeId(&nodeId, NDB_MGM_NODE_TYPE_NDB)) == true &&
-              (r= okToSendTo(nodeId, true)) != 0);
-        if (!next)
-          DBUG_RETURN(NO_CONTACT_WITH_DB_NODES);
+      assert(use_master_node);
+      sendNodeId = guess_master_node(ss);
+      if (okToSendTo(sendNodeId, true) != 0)
+      {
+        DBUG_RETURN(SEND_OR_RECEIVE_FAILED);
       }
-      if (ss.sendSignal(nodeId, &ssig) != SEND_OK)
+
+      if (ss.sendSignal(sendNodeId, &ssig) != SEND_OK)
+      {
         DBUG_RETURN(SEND_OR_RECEIVE_FAILED);
-      nodes.set(nodeId);
-      do_send= 0;
+      }
+      do_send = 0;
     }
+
     SimpleSignal *signal = ss.waitFor();
     int gsn = signal->readSignalNumber();
     switch (gsn) {
     case GSN_STOP_REF:{
       const StopRef * const ref = CAST_CONSTPTR(StopRef, signal->getDataPtr());
       const NodeId nodeId = refToNode(signal->header.theSendersBlockRef);
-#ifdef VM_TRACE
-      ndbout_c("Node %d refused stop", nodeId);
-#endif
-      assert(nodes.get(nodeId));
-      nodes.clear(nodeId);
+      assert(nodeId == sendNodeId);
       if (ref->errorCode == StopRef::MultiNodeShutdownNotMaster)
       {
         assert(use_master_node);
         m_master_node= ref->masterNodeId;
-        do_send= 1;
+        do_send = 1;
         continue;
       }
-      error = translateStopRef(ref->errorCode);
+      DBUG_RETURN(translateStopRef(ref->errorCode));
       break;
     }
     case GSN_STOP_CONF:{
@@ -1245,43 +1405,22 @@ int MgmtSrvr::sendSTOP_REQ(const Vector<
       const StopConf * const ref = CAST_CONSTPTR(StopConf, signal->getDataPtr());
 #endif
       const NodeId nodeId = refToNode(signal->header.theSendersBlockRef);
-#ifdef VM_TRACE
-      ndbout_c("Node %d single user mode", nodeId);
-#endif
-      assert(nodes.get(nodeId));
-      if (singleUserNodeId != 0)
-      {
-        stoppedNodes.set(nodeId);
-      }
-      else
-      {
-        assert(no_of_nodes_to_stop > 1);
-        stoppedNodes.bitOR(nodes_to_stop);
-      }
-      nodes.clear(nodeId);
+      assert(nodeId == sendNodeId);
+      stoppedNodes.bitOR(ndb_nodes_to_stop);
       break;
     }
     case GSN_NF_COMPLETEREP:{
       const NFCompleteRep * const rep =
 	CAST_CONSTPTR(NFCompleteRep, signal->getDataPtr());
-#ifdef VM_TRACE
-      ndbout_c("sendSTOP_REQ Node %d fail completed", rep->failedNodeId);
-#endif
-      nodes.clear(rep->failedNodeId); // clear the failed node
-      if (singleUserNodeId == 0)
-        stoppedNodes.set(rep->failedNodeId);
+      stoppedNodes.set(rep->failedNodeId);
       break;
     }
     case GSN_NODE_FAILREP:{
       const NodeFailRep * const rep =
 	CAST_CONSTPTR(NodeFailRep, signal->getDataPtr());
-      NdbNodeBitmask mask;
+      NodeBitmask mask;
       mask.assign(NdbNodeBitmask::Size, rep->theNodes);
-      mask.bitANDC(notstarted);
-      nodes.bitANDC(mask);
-      
-      if (singleUserNodeId == 0)
-	stoppedNodes.bitOR(mask);
+      stoppedNodes.bitOR(mask);
       break;
     }
     case GSN_API_REGCONF:
@@ -1290,9 +1429,6 @@ int MgmtSrvr::sendSTOP_REQ(const Vector<
       continue;
     default:
       report_unknown_signal(signal);
-#ifdef VM_TRACE
-      ndbout_c("Unknown signal %d", gsn);
-#endif
       DBUG_RETURN(SEND_OR_RECEIVE_FAILED);
     }
   }
@@ -1319,16 +1455,20 @@ int MgmtSrvr::stopNodes(const Vector<Nod
     return OPERATION_NOT_ALLOWED_START_STOP;
   }
 
-  NdbNodeBitmask nodes;
-  int ret= sendSTOP_REQ(node_ids,
-                        nodes,
-                        0,
-                        abort,
-                        false,
-                        false,
-                        false,
-                        false,
-                        stopSelf);
+  NodeBitmask nodes;
+  int ret = 0;
+  if (node_ids.size() > 0)
+  {
+    ret = sendSTOP_REQ(node_ids, nodes,
+                       abort, false, false, false, false,
+                       stopSelf);
+  }
+  else
+  {
+    ret = sendall_STOP_REQ(nodes,
+                           abort, false, false, false, false);
+  }
+
   if (stopCount)
     *stopCount= nodes.count();
   return ret;
@@ -1362,20 +1502,15 @@ int MgmtSrvr::shutdownMGM(int *stopCount
 
 int MgmtSrvr::shutdownDB(int * stopCount, bool abort)
 {
-  NdbNodeBitmask nodes;
-  Vector<NodeId> node_ids;
+  NodeBitmask nodes;
 
-  int tmp;
+  int ret = sendall_STOP_REQ(nodes,
+                             abort,
+                             true,
+                             false,
+                             false,
+                             false);
 
-  int ret = sendSTOP_REQ(node_ids,
-			 nodes,
-			 0,
-			 abort,
-			 true,
-			 false,
-			 false,
-			 false,
-                         &tmp);
   if (stopCount)
     *stopCount = nodes.count();
   return ret;
@@ -1385,25 +1520,120 @@ int MgmtSrvr::shutdownDB(int * stopCount
  * Enter single user mode on all live nodes
  */
 
-int MgmtSrvr::enterSingleUser(int * stopCount, Uint32 singleUserNodeId)
+int MgmtSrvr::enterSingleUser(int * stopCount, Uint32 apiNodeId)
 {
-  if (getNodeType(singleUserNodeId) != NDB_MGM_NODE_TYPE_API)
+  if (getNodeType(apiNodeId) != NDB_MGM_NODE_TYPE_API)
     return NODE_NOT_API_NODE;
-  NdbNodeBitmask nodes;
-  Vector<NodeId> node_ids;
-  int stopSelf;
-  int ret = sendSTOP_REQ(node_ids,
-			 nodes,
-			 singleUserNodeId,
-			 false,
-			 false,
-			 false,
-			 false,
-			 false,
-                         &stopSelf);
+
+  // Init
   if (stopCount)
-    *stopCount = nodes.count();
-  return ret;
+  {
+    * stopCount = 0;
+  }
+
+  SignalSender ss(theFacade);
+  ss.lock(); // lock will be released on exit
+
+  SimpleSignal ssig;
+  StopReq* const stopReq = CAST_PTR(StopReq, ssig.getDataPtrSend());
+  ssig.set(ss, TestOrd::TraceAPI, NDBCNTR, GSN_STOP_REQ, StopReq::SignalLength);
+
+  stopReq->requestInfo = 0;
+  stopReq->apiTimeout = 5000;
+  stopReq->transactionTimeout = 1000;
+  stopReq->readOperationTimeout = 1000;
+  stopReq->operationTimeout = 1000;
+  stopReq->senderData = 12;
+  stopReq->senderRef = ss.getOwnRef();
+  stopReq->singleuser = 1;
+  stopReq->singleUserApi = apiNodeId;
+  StopReq::setSystemStop(stopReq->requestInfo, false);
+  StopReq::setPerformRestart(stopReq->requestInfo, false);
+  StopReq::setStopAbort(stopReq->requestInfo, false);
+
+  NodeBitmask nodes;
+  {
+    NodeId nodeId = 0;
+    Uint32 failed = 0;
+    while (getNextNodeId(&nodeId, NDB_MGM_NODE_TYPE_NDB))
+    {
+      if (okToSendTo(nodeId, true) == 0)
+      {
+	SendStatus result = ss.sendSignal(nodeId, &ssig);
+	if (result == SEND_OK)
+	  nodes.set(nodeId);
+        else
+          failed++;
+      }
+      else
+      {
+        failed++;
+      }
+    }
+    if (nodes.isclear())
+    {
+      if (failed)
+      {
+        return SEND_OR_RECEIVE_FAILED;
+      }
+      return NO_CONTACT_WITH_DB_NODES;
+    }
+  }
+
+  int error = 0;
+  int ok = 0;
+  while (!nodes.isclear())
+  {
+    SimpleSignal *signal = ss.waitFor();
+    int gsn = signal->readSignalNumber();
+    switch (gsn) {
+    case GSN_STOP_REF:
+    {
+      const StopRef * const ref = CAST_CONSTPTR(StopRef, signal->getDataPtr());
+      nodes.clear(refToNode(signal->header.theSendersBlockRef));
+      error = translateStopRef(ref->errorCode);
+      break;
+    }
+    case GSN_STOP_CONF:
+    {
+      ok++;
+      nodes.clear(refToNode(signal->header.theSendersBlockRef));
+      break;
+    }
+    case GSN_NF_COMPLETEREP:
+    {
+      const NFCompleteRep * rep = CAST_CONSTPTR(NFCompleteRep,
+                                                signal->getDataPtr());
+      nodes.clear(rep->failedNodeId);
+      break;
+    }
+
+    case GSN_NODE_FAILREP:
+    {
+      const NodeFailRep * rep = CAST_CONSTPTR(NodeFailRep,
+                                              signal->getDataPtr());
+      NodeBitmask mask;
+      mask.assign(NdbNodeBitmask::Size, rep->theNodes);
+      nodes.bitANDC(mask);
+      break;
+    }
+    case GSN_API_REGCONF:
+    case GSN_TAKE_OVERTCCONF:
+    case GSN_CONNECT_REP:
+      continue;
+
+    default:
+      report_unknown_signal(signal);
+      return SEND_OR_RECEIVE_FAILED;
+    }
+  }
+
+  if (stopCount)
+  {
+    * stopCount = ok;
+  }
+
+  return error;
 }
 
 /*
@@ -1476,16 +1706,19 @@ int MgmtSrvr::restartNodes(const Vector<
     return OPERATION_NOT_ALLOWED_START_STOP;
   }
 
-  NdbNodeBitmask nodes;
-  int ret= sendSTOP_REQ(node_ids,
-                        nodes,
-                        0,
-                        abort,
-                        false,
-                        true,
-                        true,
-                        initialStart,
-                        stopSelf);
+  NodeBitmask nodes;
+  int ret = 0;
+  if (node_ids.size() > 0)
+  {
+    ret = sendSTOP_REQ(node_ids, nodes,
+                       abort, false, true, true, initialStart,
+                       stopSelf);
+  }
+  else
+  {
+    ret = sendall_STOP_REQ(nodes,
+                           abort, false, true, true, initialStart);
+  }
 
   if (ret)
     return ret;
@@ -1550,19 +1783,14 @@ int MgmtSrvr::restartNodes(const Vector<
 int MgmtSrvr::restartDB(bool nostart, bool initialStart,
                         bool abort, int * stopCount)
 {
-  NdbNodeBitmask nodes;
-  Vector<NodeId> node_ids;
-  int tmp;
+  NodeBitmask nodes;
 
-  int ret = sendSTOP_REQ(node_ids,
-			 nodes,
-			 0,
-			 abort,
-			 true,
-			 true,
-			 true,
-			 initialStart,
-                         &tmp);
+  int ret = sendall_STOP_REQ(nodes,
+                             abort,
+                             true,
+                             true,
+                             true,
+                             initialStart);
 
   if (ret)
     return ret;

=== modified file 'storage/ndb/src/mgmsrv/MgmtSrvr.hpp'
--- a/storage/ndb/src/mgmsrv/MgmtSrvr.hpp	2011-02-01 23:27:25 +0000
+++ b/storage/ndb/src/mgmsrv/MgmtSrvr.hpp	2011-04-15 08:09:04 +0000
@@ -362,6 +362,7 @@ public:
                      Uint32 transId, Uint32 transKey, Uint32 flags);
 
 private:
+  int guess_master_node(SignalSender&);
 
   int versionNode(int nodeId, Uint32 &version,
                   Uint32 &mysql_version, const char **address);
@@ -376,9 +377,15 @@ private:
                    bool nostart,
                    bool initialStart);
 
+  int sendall_STOP_REQ(NodeBitmask &stoppedNodes,
+                       bool abort,
+                       bool stop,
+                       bool restart,
+                       bool nostart,
+                       bool initialStart);
+
   int sendSTOP_REQ(const Vector<NodeId> &node_ids,
-		   NdbNodeBitmask &stoppedNodes,
-		   Uint32 singleUserNodeId,
+		   NodeBitmask &stoppedNodes,
 		   bool abort,
 		   bool stop,
 		   bool restart,

=== modified file 'storage/ndb/src/ndbapi/Ndb.cpp'
--- a/storage/ndb/src/ndbapi/Ndb.cpp	2011-02-10 07:55:45 +0000
+++ b/storage/ndb/src/ndbapi/Ndb.cpp	2011-04-13 19:33:59 +0000
@@ -2194,6 +2194,17 @@ Ndb::getNdbErrorDetail(const NdbError& e
   DBUG_RETURN(NULL);
 }
 
+void
+Ndb::setCustomData(void* _customDataPtr)
+{
+  theImpl->customDataPtr = _customDataPtr;
+}
+
+void*
+Ndb::getCustomData() const
+{
+  return theImpl->customDataPtr;
+}
 
 Uint32
 Ndb::getMinDbNodeVersion() const

=== modified file 'storage/ndb/src/ndbapi/NdbImpl.hpp'
--- a/storage/ndb/src/ndbapi/NdbImpl.hpp	2011-04-10 17:32:41 +0000
+++ b/storage/ndb/src/ndbapi/NdbImpl.hpp	2011-04-17 18:25:41 +0000
@@ -124,6 +124,8 @@ public:
   }
 
   BaseString m_systemPrefix; // Buffer for preformatted for <sys>/<def>/
+  
+  void* customDataPtr;
 
   Uint64 clientStats[ Ndb::NumClientStatistics ];
   

=== modified file 'storage/ndb/src/ndbapi/Ndbinit.cpp'
--- a/storage/ndb/src/ndbapi/Ndbinit.cpp	2011-02-04 17:52:38 +0000
+++ b/storage/ndb/src/ndbapi/Ndbinit.cpp	2011-04-15 06:29:59 +0000
@@ -128,6 +128,19 @@ Ndb::~Ndb()
   if (m_sys_tab_0)
     getDictionary()->removeTableGlobal(*m_sys_tab_0, 0);
 
+  if (theImpl->m_ev_op != 0)
+  {
+    g_eventLogger->warning("Deleting Ndb-object with NdbEventOperation still"
+                           " active");
+    printf("this: %p NdbEventOperation(s): ", this);
+    for (NdbEventOperationImpl *op= theImpl->m_ev_op; op; op=op->m_next)
+    {
+      printf("%p ", op);
+    }
+    printf("\n");
+    fflush(stdout);
+  }
+
   assert(theImpl->m_ev_op == 0); // user should return NdbEventOperation's
   for (NdbEventOperationImpl *op= theImpl->m_ev_op; op; op=op->m_next)
   {
@@ -192,7 +205,8 @@ NdbImpl::NdbImpl(Ndb_cluster_connection 
 		      1024,1024),
     theNoOfDBnodes(0),
     theWaiter(this),
-    m_ev_op(0)
+    m_ev_op(0),
+    customDataPtr(0)
 {
   int i;
   for (i = 0; i < MAX_NDB_NODES; i++) {

=== modified file 'storage/ndb/src/ndbapi/ndb_cluster_connection.cpp'
--- a/storage/ndb/src/ndbapi/ndb_cluster_connection.cpp	2011-02-04 17:52:38 +0000
+++ b/storage/ndb/src/ndbapi/ndb_cluster_connection.cpp	2011-04-15 06:29:59 +0000
@@ -427,6 +427,22 @@ Ndb_cluster_connection_impl(const char *
 Ndb_cluster_connection_impl::~Ndb_cluster_connection_impl()
 {
   DBUG_ENTER("~Ndb_cluster_connection");
+
+  if (m_first_ndb_object != 0)
+  {
+    g_eventLogger->warning("Deleting Ndb_cluster_connection with Ndb-object"
+                           " not deleted");
+    Ndb * p = m_first_ndb_object;
+    printf("this: %p Ndb-object(s): ", (Ndb_cluster_connection*)this);
+    while (p)
+    {
+      printf("%p ", p);
+      p = p->theImpl->m_next_ndb_object;
+    }
+    printf("\n");
+    fflush(stdout);
+  }
+
   if (m_transporter_facade != 0)
   {
     m_transporter_facade->stop_instance();

=== modified file 'storage/ndb/test/include/NDBT_Tables.hpp'
--- a/storage/ndb/test/include/NDBT_Tables.hpp	2011-02-02 00:40:07 +0000
+++ b/storage/ndb/test/include/NDBT_Tables.hpp	2011-04-13 08:51:04 +0000
@@ -46,11 +46,17 @@ public:
   STATIC_CONST(MinKeyMaxVarTypeAttrBytes= MinKeyMaxAttrBytes - 2);
 
   STATIC_CONST(UniqueIndexOverheadBytes= 4); // For FragId
-  STATIC_CONST(MaxKeyMaxVarTypeAttrBytesIndex = 
-               MaxKeyMaxVarTypeAttrBytes - UniqueIndexOverheadBytes);
 
-  /* Hugo requires 2 unsigned int columns somewhere in the table */
-  STATIC_CONST(HugoOverheadBytes= 2 * 4); 
+  // Note that since we'll put an unique index on this...it can't be bigger
+  // than MaxKeyBytes
+  STATIC_CONST(MaxKeyMaxVarTypeAttrBytesIndex =
+               ((MaxKeyMaxVarTypeAttrBytes <= MaxKeyBytes) ?
+                MaxKeyMaxVarTypeAttrBytes : MaxKeyBytes) - UniqueIndexOverheadBytes);
+
+  /* Hugo requires 2 unsigned int columns somewhere in the table
+   * and these also counts towards #attributes relation
+   */
+  STATIC_CONST(HugoOverheadBytes= 2 * (4 + 4));
 
   static int createTable(Ndb* pNdb, const char* _name, bool _temp = false, 
 			 bool existsOK = false, NDBT_CreateTableHook = 0,

=== modified file 'storage/ndb/test/ndbapi/testIndex.cpp'
--- a/storage/ndb/test/ndbapi/testIndex.cpp	2011-04-07 07:22:49 +0000
+++ b/storage/ndb/test/ndbapi/testIndex.cpp	2011-04-14 16:29:07 +0000
@@ -2782,6 +2782,67 @@ runBug12315582(NDBT_Context* ctx, NDBT_S
   return NDBT_OK;
 }
 
+int
+runBug60851(NDBT_Context* ctx, NDBT_Step* step)
+{
+  const NdbDictionary::Table * pTab = ctx->getTab();
+  Ndb* pNdb = GETNDB(step);
+  NdbDictionary::Dictionary * dict = pNdb->getDictionary();
+
+  const NdbDictionary::Index* pIdx= dict->getIndex(pkIdxName, pTab->getName());
+  CHK_RET_FAILED(pIdx != 0);
+
+  const NdbRecord * pRowRecord = pTab->getDefaultRecord();
+  CHK_RET_FAILED(pRowRecord != 0);
+  const NdbRecord * pIdxRecord = pIdx->getDefaultRecord();
+  CHK_RET_FAILED(pIdxRecord != 0);
+
+  const Uint32 len = NdbDictionary::getRecordRowLength(pRowRecord);
+  Uint8 * pRow = new Uint8[len];
+
+  NdbTransaction* pTrans = pNdb->startTransaction();
+  CHK_RET_FAILED(pTrans != 0);
+
+  const NdbOperation * pOp[3] = { 0, 0, 0};
+  for (Uint32 i = 0; i<3; i++)
+  {
+    NdbInterpretedCode code;
+    if (i == 1)
+      code.interpret_exit_nok();
+    else
+      code.interpret_exit_ok();
+
+    code.finalise();
+
+    bzero(pRow, len);
+    HugoCalculator calc(* pTab);
+    calc.equalForRow(pRow, pRowRecord, i);
+
+    NdbOperation::OperationOptions opts;
+    bzero(&opts, sizeof(opts));
+    opts.optionsPresent = NdbOperation::OperationOptions::OO_INTERPRETED;
+    opts.interpretedCode = &code;
+
+    pOp[i] = pTrans->deleteTuple(pIdxRecord, (char*)pRow,
+                                 pRowRecord, (char*)pRow,
+                                 0,
+                                 &opts,
+                                 sizeof(opts));
+    CHK_RET_FAILED(pOp[i]);
+  }
+
+  int res = pTrans->execute(Commit, AO_IgnoreError);
+
+  CHK_RET_FAILED(res == 0);
+  CHK_RET_FAILED(pOp[0]->getNdbError().code == 0);
+  CHK_RET_FAILED(pOp[1]->getNdbError().code != 0);
+  CHK_RET_FAILED(pOp[2]->getNdbError().code == 0);
+
+  delete [] pRow;
+
+  return NDBT_OK;
+}
+
 NDBT_TESTSUITE(testIndex);
 TESTCASE("CreateAll", 
 	 "Test that we can create all various indexes on each table\n"
@@ -3196,6 +3257,15 @@ TESTCASE("Bug12315582", "")
   INITIALIZER(runBug12315582);
   FINALIZER(createPkIndex_Drop);
 }
+TESTCASE("Bug60851", "")
+{
+  TC_PROPERTY("LoggedIndexes", Uint32(0));
+  TC_PROPERTY("OrderedIndex", Uint32(0));
+  INITIALIZER(createPkIndex);
+  INITIALIZER(runLoadTable);
+  INITIALIZER(runBug60851);
+  FINALIZER(createPkIndex_Drop);
+}
 NDBT_TESTSUITE_END(testIndex);
 
 int main(int argc, const char** argv){

=== modified file 'storage/ndb/test/run-test/daily-basic-tests.txt'
--- a/storage/ndb/test/run-test/daily-basic-tests.txt	2011-04-10 17:32:41 +0000
+++ b/storage/ndb/test/run-test/daily-basic-tests.txt	2011-04-17 18:25:41 +0000
@@ -1671,6 +1671,10 @@ max-time: 300
 cmd: testIndex
 args: -n Bug12315582 T1
 
+max-time: 300
+cmd: testIndex
+args: -n Bug60851 T1
+
 max-time: 500
 cmd: testNodeRestart
 args: -n ForceStopAndRestart T1

=== modified file 'storage/ndb/test/src/NDBT_Tables.cpp'
--- a/storage/ndb/test/src/NDBT_Tables.cpp	2011-02-02 00:40:07 +0000
+++ b/storage/ndb/test/src/NDBT_Tables.cpp	2011-04-13 08:51:04 +0000
@@ -918,14 +918,14 @@ NDBT_Table* createMaxKeyMaxColsHugoTabDe
 
     /* Last attr uses remaining attr space */
     BaseString::snprintf(namebuff, buffsize, "A%d", attrNum);
+    Uint32 sz32 = NDB_MAX_TUPLE_SIZE_IN_WORDS;
+    sz32 -= NDB_MAX_KEYSIZE_IN_WORDS;
+    sz32 -= NDB_MAX_ATTRIBUTES_IN_INDEX;
+    sz32 -= 2 * NDB_MAX_ATTRIBUTES_IN_TABLE;
     attrs[attrNum]= new NDBT_Attribute(namebuff,
-                                       NdbDictionary::Column::Char,
-                                       (NDB_MAX_TUPLE_SIZE_IN_WORDS -
-                                        NDB_MAX_KEYSIZE_IN_WORDS -
-                                        ((NDB_MAX_ATTRIBUTES_IN_TABLE -
-                                          NDB_MAX_ATTRIBUTES_IN_INDEX) - 1)) * 4,
+                                       NdbDictionary::Column::Char, 4 * sz32,
                                        false);
-    
+
     WIDE_MAXKEYMAXCOLS_HUGO= new NDBT_Table(name, NDB_MAX_ATTRIBUTES_IN_TABLE,
                                             attrs);
 

=== modified file 'storage/ndb/tools/ndbinfo_sql.cpp'
--- a/storage/ndb/tools/ndbinfo_sql.cpp	2011-04-10 17:32:41 +0000
+++ b/storage/ndb/tools/ndbinfo_sql.cpp	2011-04-17 18:25:41 +0000
@@ -153,7 +153,8 @@ struct view {
     "  WHEN 8 THEN \"STOPPING_4\""
     "  ELSE \"<unknown>\" "
     " END AS status, "
-    "start_phase "
+    "start_phase, "
+    "config_generation "
     "FROM <NDBINFO_DB>.<TABLE_PREFIX>nodes"
    },
   { "memoryusage",

No bundle (reason: useless for push emails).
Thread
bzr push into mysql-5.1-telco-7.0-spj-scan-vs-scan branch (jonas:3478 to3479) jonas oreland17 Apr