List:Commits« Previous MessageNext Message »
From:magnus.blaudd Date:June 22 2011 8:28am
Subject:bzr commit into mysql-5.5-cluster branch (magnus.blaudd:3366)
View as plain text  
#At file:///data0/magnus/mysql/5.5-cluster/ based on revid:magnus.blaudd@stripped

 3366 magnus.blaudd@stripped	2011-06-22 [merge]
      Merge 7.1 -> 5.5-cluster

    added:
      mysql-test/suite/ndb/r/ndb_select_count.result
      mysql-test/suite/ndb/t/ndb_select_count.test
    modified:
      sql/ha_ndbcluster.cc
      storage/ndb/include/mgmapi/mgmapi.h
      storage/ndb/src/kernel/blocks/qmgr/QmgrMain.cpp
      storage/ndb/src/mgmapi/mgmapi.cpp
      storage/ndb/src/mgmsrv/MgmtSrvr.cpp
      storage/ndb/src/mgmsrv/MgmtSrvr.hpp
      storage/ndb/src/ndbapi/ClusterMgr.cpp
      storage/ndb/src/ndbapi/NdbQueryBuilder.hpp
      storage/ndb/src/ndbapi/NdbQueryOperation.cpp
      storage/ndb/src/ndbapi/NdbQueryOperation.hpp
      storage/ndb/src/ndbapi/NdbQueryOperationImpl.hpp
      storage/ndb/test/ndbapi/testMgmd.cpp
=== added file 'mysql-test/suite/ndb/r/ndb_select_count.result'
--- a/mysql-test/suite/ndb/r/ndb_select_count.result	1970-01-01 00:00:00 +0000
+++ b/mysql-test/suite/ndb/r/ndb_select_count.result	2011-06-20 12:34:27 +0000
@@ -0,0 +1,19 @@
+create table t1(
+k int not null auto_increment primary key,
+i int,
+j int
+) engine=ndbcluster;
+insert into t1(i,j) values (1,1),(2,2),(3,3),(4,4),(5,5),(6,6),(7,7);
+select count(*) from t1;
+count(*)
+7
+begin;
+delete from t1 where k = 10000;
+select count(*) from t1;
+count(*)
+7
+commit;
+select count(*) from t1;
+count(*)
+7
+drop table t1;

=== added file 'mysql-test/suite/ndb/t/ndb_select_count.test'
--- a/mysql-test/suite/ndb/t/ndb_select_count.test	1970-01-01 00:00:00 +0000
+++ b/mysql-test/suite/ndb/t/ndb_select_count.test	2011-06-20 12:34:27 +0000
@@ -0,0 +1,18 @@
+-- source include/have_ndb.inc
+
+create table t1(
+  k int not null auto_increment primary key,
+  i int,
+  j int
+) engine=ndbcluster;
+
+insert into t1(i,j) values (1,1),(2,2),(3,3),(4,4),(5,5),(6,6),(7,7);
+
+select count(*) from t1;
+begin;
+delete from t1 where k = 10000; # none existant, rbwr
+select count(*) from t1;
+commit;
+select count(*) from t1;
+
+drop table t1;

=== modified file 'sql/ha_ndbcluster.cc'
--- a/sql/ha_ndbcluster.cc	2011-06-22 08:20:35 +0000
+++ b/sql/ha_ndbcluster.cc	2011-06-22 08:27:29 +0000
@@ -5034,6 +5034,7 @@ int ha_ndbcluster::end_bulk_delete()
 
   assert(m_rows_deleted >= ignore_count);
   m_rows_deleted-= ignore_count;
+  no_uncommitted_rows_update(ignore_count);
   DBUG_RETURN(0);
 }
 
@@ -5226,6 +5227,7 @@ int ha_ndbcluster::ndb_delete_row(const 
   {
     assert(m_rows_deleted >= ignore_count);
     m_rows_deleted-= ignore_count;
+    no_uncommitted_rows_update(ignore_count);
   }
   DBUG_RETURN(0);
 }

=== modified file 'storage/ndb/include/mgmapi/mgmapi.h'
--- a/storage/ndb/include/mgmapi/mgmapi.h	2011-02-01 23:27:25 +0000
+++ b/storage/ndb/include/mgmapi/mgmapi.h	2011-06-21 13:10:37 +0000
@@ -206,11 +206,13 @@ extern "C" {
     NDB_MGM_NODE_STATUS_SINGLEUSER    = 7,
     /** Resume mode*/
     NDB_MGM_NODE_STATUS_RESUME        = 8,
+    /** Node is connected */
+    NDB_MGM_NODE_STATUS_CONNECTED     = 9,
 #ifndef DOXYGEN_SHOULD_SKIP_INTERNAL
     /** Min valid value*/
     NDB_MGM_NODE_STATUS_MIN           = 0,
     /** Max valid value*/
-    NDB_MGM_NODE_STATUS_MAX           = 8
+    NDB_MGM_NODE_STATUS_MAX           = 9
 #endif
   };
 

=== modified file 'storage/ndb/src/kernel/blocks/qmgr/QmgrMain.cpp'
--- a/storage/ndb/src/kernel/blocks/qmgr/QmgrMain.cpp	2011-06-13 06:14:32 +0000
+++ b/storage/ndb/src/kernel/blocks/qmgr/QmgrMain.cpp	2011-06-21 13:10:37 +0000
@@ -3728,6 +3728,7 @@ Qmgr::execAPI_VERSION_REQ(Signal * signa
   else
   {
     conf->version =  0;
+    conf->mysql_version =  0;
     conf->inet_addr= 0;
   }
   conf->nodeId = nodeId;

=== modified file 'storage/ndb/src/mgmapi/mgmapi.cpp'
--- a/storage/ndb/src/mgmapi/mgmapi.cpp	2011-04-04 13:32:06 +0000
+++ b/storage/ndb/src/mgmapi/mgmapi.cpp	2011-06-22 08:27:29 +0000
@@ -934,7 +934,10 @@ static struct ndb_mgm_status_atoi status
   { "STARTED", NDB_MGM_NODE_STATUS_STARTED },
   { "SHUTTING_DOWN", NDB_MGM_NODE_STATUS_SHUTTING_DOWN },
   { "RESTARTING", NDB_MGM_NODE_STATUS_RESTARTING },
-  { "SINGLE USER MODE", NDB_MGM_NODE_STATUS_SINGLEUSER }
+  { "SINGLE USER MODE", NDB_MGM_NODE_STATUS_SINGLEUSER },
+  { "SINGLE USER MODE", NDB_MGM_NODE_STATUS_SINGLEUSER },
+  { "RESUME", NDB_MGM_NODE_STATUS_RESUME },
+  { "CONNECTED", NDB_MGM_NODE_STATUS_CONNECTED }
 };
 
 const int no_of_status_values = (sizeof(status_values) / 

=== modified file 'storage/ndb/src/mgmsrv/MgmtSrvr.cpp'
--- a/storage/ndb/src/mgmsrv/MgmtSrvr.cpp	2011-06-01 07:51:41 +0000
+++ b/storage/ndb/src/mgmsrv/MgmtSrvr.cpp	2011-06-21 13:50:33 +0000
@@ -835,59 +835,34 @@ MgmtSrvr::start(int nodeId)
  * Version handling
  *****************************************************************************/
 
-int 
-MgmtSrvr::versionNode(int nodeId, Uint32 &version, Uint32& mysql_version,
-		      const char **address)
-{
-  version= 0;
-  mysql_version = 0;
-  if (getOwnNodeId() == nodeId)
-  {
-    /**
-     * If we're inquiring about our own node id,
-     * We know what version we are (version implies connected for mgm)
-     * but would like to find out from elsewhere what address they're using
-     * to connect to us. This means that secondary mgm servers
-     * can list ip addresses for mgm servers.
-     *
-     * If we don't get an address (i.e. no db nodes),
-     * we get the address from the configuration.
-     */
-    sendVersionReq(nodeId, version, mysql_version, address);
-    version= NDB_VERSION;
-    mysql_version = NDB_MYSQL_VERSION_D;
-    if(!*address)
-    {
-      Guard g(m_local_config_mutex);
-      ConfigIter iter(m_local_config, CFG_SECTION_NODE);
-      unsigned tmp= 0;
-      for(iter.first();iter.valid();iter.next())
-      {
-	if(iter.get(CFG_NODE_ID, &tmp)) require(false);
-	if((unsigned)nodeId!=tmp)
-	  continue;
-	if(iter.get(CFG_NODE_HOST, address)) require(false);
-	break;
-      }
-    }
+void
+MgmtSrvr::status_api(int nodeId,
+                     ndb_mgm_node_status& node_status,
+                     Uint32& version, Uint32& mysql_version,
+                     const char **address)
+{
+  assert(getNodeType(nodeId) == NDB_MGM_NODE_TYPE_API);
+  assert(version == 0 && mysql_version == 0);
+
+  if (sendVersionReq(nodeId, version, mysql_version, address) != 0)
+  {
+    // Couldn't get version from any NDB node.
+    assert(version == 0);
+    node_status = NDB_MGM_NODE_STATUS_UNKNOWN;
+    return;
   }
-  else if (getNodeType(nodeId) == NDB_MGM_NODE_TYPE_NDB)
+
+  if (version)
   {
-    trp_node node = getNodeInfo(nodeId);
-    if(node.is_connected())
-    {
-      version= node.m_info.m_version;
-      mysql_version = node.m_info.m_mysql_version;
-    }
-    *address= get_connect_address(nodeId);
+    assert(mysql_version);
+    node_status = NDB_MGM_NODE_STATUS_CONNECTED;
   }
-  else if (getNodeType(nodeId) == NDB_MGM_NODE_TYPE_API ||
-	   getNodeType(nodeId) == NDB_MGM_NODE_TYPE_MGM)
+  else
   {
-    return sendVersionReq(nodeId, version, mysql_version, address);
+    assert(mysql_version == 0);
+    node_status = NDB_MGM_NODE_STATUS_NO_CONTACT;
   }
-
-  return 0;
+  return;
 }
 
 
@@ -1898,6 +1873,75 @@ MgmtSrvr::updateStatus()
   theFacade->ext_forceHB();
 }
 
+
+void
+MgmtSrvr::status_mgmd(NodeId node_id,
+                      ndb_mgm_node_status& node_status,
+                      Uint32& version, Uint32& mysql_version,
+                      const char **address)
+{
+  assert(getNodeType(node_id) == NDB_MGM_NODE_TYPE_MGM);
+
+  if (node_id == getOwnNodeId())
+  {
+    /*
+      Special case to get version of own node
+      - version and mysql_version is hardcoded
+      - address should be the address seen from ndbd(if it's connected)
+        else use HostName from config
+    */
+    Uint32 tmp_version = 0, tmp_mysql_version = 0;
+    sendVersionReq(node_id, tmp_version, tmp_mysql_version, address);
+    // Check that the version returned is equal to compiled in version
+    assert(tmp_version == 0 ||
+           (tmp_version == NDB_VERSION &&
+            tmp_mysql_version == NDB_MYSQL_VERSION_D));
+
+    version = NDB_VERSION;
+    mysql_version = NDB_MYSQL_VERSION_D;
+    if(!*address)
+    {
+      // No address returned from ndbd -> get HostName from config
+      Guard g(m_local_config_mutex);
+      ConfigIter iter(m_local_config, CFG_SECTION_NODE);
+      require(iter.find(CFG_NODE_ID, node_id) == 0);
+      require(iter.get(CFG_NODE_HOST, address) == 0);
+
+      /*
+        Try to convert HostName to numerical ip address
+        (to get same output as if ndbd had replied)
+      */
+      struct in_addr addr;
+      if (Ndb_getInAddr(&addr, *address) == 0)
+        *address = inet_ntoa(addr);
+    }
+
+    node_status = NDB_MGM_NODE_STATUS_CONNECTED;
+    return;
+  }
+
+  /*
+    MGM nodes are connected directly to all other MGM
+    node(s), return status as seen by ClusterMgr
+  */
+  const trp_node node = getNodeInfo(node_id);
+  if(node.is_connected())
+  {
+    version = node.m_info.m_version;
+    mysql_version = node.m_info.m_mysql_version;
+    node_status = NDB_MGM_NODE_STATUS_CONNECTED;
+    *address= get_connect_address(node_id);
+  }
+  else
+  {
+    version = 0;
+    mysql_version = 0;
+    node_status = NDB_MGM_NODE_STATUS_NO_CONTACT;
+  }
+
+  return;
+}
+
 int 
 MgmtSrvr::status(int nodeId, 
                  ndb_mgm_node_status * _status, 
@@ -1910,24 +1954,38 @@ MgmtSrvr::status(int nodeId, 
 		 Uint32 * connectCount,
 		 const char **address)
 {
-  if (getNodeType(nodeId) == NDB_MGM_NODE_TYPE_API ||
-      getNodeType(nodeId) == NDB_MGM_NODE_TYPE_MGM) {
-    versionNode(nodeId, *version, *mysql_version, address);
-  } else {
-    *address= get_connect_address(nodeId);
+  switch(getNodeType(nodeId)){
+  case NDB_MGM_NODE_TYPE_API:
+    status_api(nodeId, *_status, *version, *mysql_version, address);
+    return 0;
+    break;
+
+  case NDB_MGM_NODE_TYPE_MGM:
+    status_mgmd(nodeId, *_status, *version, *mysql_version, address);
+    return 0;
+    break;
+
+  case NDB_MGM_NODE_TYPE_NDB:
+    break;
+
+  default:
+    abort();
+    break;
   }
 
   const trp_node node = getNodeInfo(nodeId);
+  assert(getNodeType(nodeId) == NDB_MGM_NODE_TYPE_NDB &&
+         node.m_info.getType() == NodeInfo::DB);
 
   if(!node.is_connected()){
     * _status = NDB_MGM_NODE_STATUS_NO_CONTACT;
     return 0;
   }
-  
-  if (getNodeType(nodeId) == NDB_MGM_NODE_TYPE_NDB) {
-    * version = node.m_info.m_version;
-    * mysql_version = node.m_info.m_mysql_version;
-  }
+
+  * version = node.m_info.m_version;
+  * mysql_version = node.m_info.m_mysql_version;
+
+  *address= get_connect_address(nodeId);
 
   * dynamic = node.m_state.dynamicId;
   * nodegroup = node.m_state.nodeGroup;
@@ -2792,9 +2850,10 @@ MgmtSrvr::getNodeType(NodeId nodeId) con
 
 const char *MgmtSrvr::get_connect_address(Uint32 node_id)
 {
-  if (m_connect_address[node_id].s_addr == 0 &&
-      theFacade &&
-      getNodeType(node_id) == NDB_MGM_NODE_TYPE_NDB) 
+  if (theFacade &&
+      m_connect_address[node_id].s_addr == 0 &&
+      (getNodeType(node_id) == NDB_MGM_NODE_TYPE_MGM ||
+       getNodeType(node_id) == NDB_MGM_NODE_TYPE_NDB))
   {
     const trp_node &node= getNodeInfo(node_id);
     if (node.is_connected())

=== modified file 'storage/ndb/src/mgmsrv/MgmtSrvr.hpp'
--- a/storage/ndb/src/mgmsrv/MgmtSrvr.hpp	2011-06-01 07:40:49 +0000
+++ b/storage/ndb/src/mgmsrv/MgmtSrvr.hpp	2011-06-21 13:10:37 +0000
@@ -364,8 +364,14 @@ public:
 private:
   int guess_master_node(SignalSender&);
 
-  int versionNode(int nodeId, Uint32 &version,
-                  Uint32 &mysql_version, const char **address);
+  void status_api(int nodeId,
+                  ndb_mgm_node_status& node_status,
+                  Uint32& version, Uint32& mysql_version,
+                  const char **address);
+  void status_mgmd(NodeId node_id,
+                   ndb_mgm_node_status& node_status,
+                   Uint32& version, Uint32& mysql_version,
+                   const char **address);
 
   int sendVersionReq(int processId, Uint32 &version,
                      Uint32& mysql_version, const char **address);

=== modified file 'storage/ndb/src/ndbapi/ClusterMgr.cpp'
--- a/storage/ndb/src/ndbapi/ClusterMgr.cpp	2011-02-03 14:45:49 +0000
+++ b/storage/ndb/src/ndbapi/ClusterMgr.cpp	2011-06-21 13:50:33 +0000
@@ -651,6 +651,9 @@ ClusterMgr::execAPI_REGREQ(const Uint32 
 
   if(node.m_info.m_version != apiRegReq->version){
     node.m_info.m_version = apiRegReq->version;
+    node.m_info.m_mysql_version = apiRegReq->mysql_version;
+    if (node.m_info.m_version < NDBD_SPLIT_VERSION)
+      node.m_info.m_mysql_version = 0;
 
     if (getMajor(node.m_info.m_version) < getMajor(NDB_VERSION) ||
 	getMinor(node.m_info.m_version) < getMinor(NDB_VERSION)) {

=== modified file 'storage/ndb/src/ndbapi/NdbQueryBuilder.hpp'
--- a/storage/ndb/src/ndbapi/NdbQueryBuilder.hpp	2011-06-16 09:32:43 +0000
+++ b/storage/ndb/src/ndbapi/NdbQueryBuilder.hpp	2011-06-20 13:25:48 +0000
@@ -479,13 +479,8 @@ private:
  * times. It is valid until it is explicitely released().
  *
  * The NdbQueryDef *must* be keept alive until the last thread
- * which executing a query based on this NdbQueryDef has completed execution 
- * *and* result handling. Used from multiple threads this implies either:
- *
- *  - Keep the NdbQueryDef until all threads terminates.
- *  - Implement reference counting on the NdbQueryDef.
- *  - Use the supplied copy constructor to give each thread its own copy
- *    of the NdbQueryDef.
+ * which executing a query based on this NdbQueryDef has called
+ * NdbQuery::close().
  *
  * A NdbQueryDef is scheduled for execution by appending it to an open 
  * transaction - optionally together with a set of parameters specifying 

=== modified file 'storage/ndb/src/ndbapi/NdbQueryOperation.cpp'
--- a/storage/ndb/src/ndbapi/NdbQueryOperation.cpp	2011-06-16 09:32:43 +0000
+++ b/storage/ndb/src/ndbapi/NdbQueryOperation.cpp	2011-06-20 13:25:48 +0000
@@ -1389,7 +1389,7 @@ NdbQueryImpl::NdbQueryImpl(NdbTransactio
   m_state(Initial),
   m_tcState(Inactive),
   m_next(NULL),
-  m_queryDef(queryDef),
+  m_queryDef(&queryDef),
   m_error(),
   m_transaction(trans),
   m_scanTransaction(NULL),
@@ -1452,9 +1452,13 @@ NdbQueryImpl::NdbQueryImpl(NdbTransactio
 
 NdbQueryImpl::~NdbQueryImpl()
 {
- 
-  // Do this to check that m_queryDef still exists.
-  assert(getNoOfOperations() == m_queryDef.getNoOfOperations());
+  /** BEWARE:
+   *  Don't refer NdbQueryDef or NdbQueryOperationDefs after 
+   *  NdbQuery::close() as at this stage the appliaction is 
+   *  allowed to destruct the Def's.
+   */
+  assert(m_state==Closed);
+  assert(m_rootFrags==NULL);
 
   // NOTE: m_operations[] was allocated as a single memory chunk with
   // placement new construction of each operation.
@@ -1465,8 +1469,6 @@ NdbQueryImpl::~NdbQueryImpl()
     }
     m_operations = NULL;
   }
-  delete[] m_rootFrags;
-  m_rootFrags = NULL;
   m_state = Destructed;
 }
 
@@ -1478,6 +1480,9 @@ NdbQueryImpl::postFetchRelease()
     { m_operations[i].postFetchRelease();
     }
   }
+  delete[] m_rootFrags;
+  m_rootFrags = NULL;
+
   m_rowBufferAlloc.reset();
   m_tupleSetAlloc.reset();
   m_resultStreamAlloc.reset();
@@ -1957,7 +1962,7 @@ NdbQueryImpl::awaitMoreResults(bool forc
   assert(m_applFrags.getCurrent() == NULL);
 
   /* Check if there are any more completed fragments available.*/
-  if (m_queryDef.isScanQuery())
+  if (getQueryDef().isScanQuery())
   {
     assert (m_scanTransaction);
     assert (m_state==Executing);
@@ -2052,7 +2057,7 @@ NdbQueryImpl::awaitMoreResults(bool forc
     assert(m_pendingFrags == 0);
     assert(m_finalBatchFrags == getRootFragCount());
     return FetchResult_noMoreData;
-  } // if(m_queryDef.isScanQuery())
+  } // if(getQueryDef().isScanQuery())
 
 } //NdbQueryImpl::awaitMoreResults
 
@@ -2131,32 +2136,41 @@ NdbQueryImpl::close(bool forceSend)
   int res = 0;
 
   assert (m_state >= Initial && m_state < Destructed);
-  Ndb* const ndb = m_transaction.getNdb();
-
-  if (m_tcState != Inactive)
+  if (m_state != Closed)
   {
-    /* We have started a scan, but we have not yet received the last batch
-     * for all root fragments. We must therefore close the scan to release 
-     * the scan context at TC.*/
-    res = closeTcCursor(forceSend);
-  }
+    if (m_tcState != Inactive)
+    {
+      /* We have started a scan, but we have not yet received the last batch
+       * for all root fragments. We must therefore close the scan to release 
+       * the scan context at TC.*/
+      res = closeTcCursor(forceSend);
+    }
 
-  // Throw any pending results
-  m_fullFrags.clear();
-  m_applFrags.clear();
+    // Throw any pending results
+    m_fullFrags.clear();
+    m_applFrags.clear();
 
-  if (m_scanTransaction != NULL)
-  {
-    assert (m_state != Closed);
-    assert (m_scanTransaction->m_scanningQuery == this);
-    m_scanTransaction->m_scanningQuery = NULL;
-    ndb->closeTransaction(m_scanTransaction);
-    ndb->theRemainingStartTransactions--;  // Compensate; m_scanTransaction was not a real Txn
-    m_scanTransaction = NULL;
+    Ndb* const ndb = m_transaction.getNdb();
+    if (m_scanTransaction != NULL)
+    {
+      assert (m_state != Closed);
+      assert (m_scanTransaction->m_scanningQuery == this);
+      m_scanTransaction->m_scanningQuery = NULL;
+      ndb->closeTransaction(m_scanTransaction);
+      ndb->theRemainingStartTransactions--;  // Compensate; m_scanTransaction was not a real Txn
+      m_scanTransaction = NULL;
+    }
+
+    postFetchRelease();
+    m_state = Closed;  // Even if it was previously 'Failed' it is closed now!
   }
 
-  postFetchRelease();
-  m_state = Closed;  // Even if it was previously 'Failed' it is closed now!
+  /** BEWARE:
+   *  Don't refer NdbQueryDef or its NdbQueryOperationDefs after ::close()
+   *  as the application is allowed to destruct the Def's after this point.
+   */
+  m_queryDef= NULL;
+
   return res;
 } //NdbQueryImpl::close
 
@@ -2819,7 +2833,7 @@ NdbQueryImpl::sendFetchMore(NdbRootFragm
 {
   assert(getRoot().m_resultStreams!=NULL);
   assert(!emptyFrag.finalBatchReceived());
-  assert(m_queryDef.isScanQuery());
+  assert(getQueryDef().isScanQuery());
 
   const Uint32 fragNo = emptyFrag.getFragNo();
   emptyFrag.reset();
@@ -2892,7 +2906,7 @@ NdbQueryImpl::sendFetchMore(NdbRootFragm
 int
 NdbQueryImpl::closeTcCursor(bool forceSend)
 {
-  assert (m_queryDef.isScanQuery());
+  assert (getQueryDef().isScanQuery());
 
   NdbImpl* const ndb = m_transaction.getNdb()->theImpl;
   const Uint32 timeout  = ndb->get_waitfor_timeout();

=== modified file 'storage/ndb/src/ndbapi/NdbQueryOperation.hpp'
--- a/storage/ndb/src/ndbapi/NdbQueryOperation.hpp	2011-04-06 14:16:13 +0000
+++ b/storage/ndb/src/ndbapi/NdbQueryOperation.hpp	2011-06-20 13:25:48 +0000
@@ -180,7 +180,15 @@ public:
   NdbTransaction* getNdbTransaction() const;
 
   /**
-   * Close query
+   * Close query.
+   *
+   * Will release most of the internally allocated objects owned 
+   * by this NdbQuery and detach itself from the NdbQueryDef
+   * used to instantiate it.
+   *
+   * The application may destruct the NdbQueryDef after 
+   * ::close() has been called on *all* NdbQuery objects
+   * instantiated from it.
    */
   void close(bool forceSend = false);
 

=== modified file 'storage/ndb/src/ndbapi/NdbQueryOperationImpl.hpp'
--- a/storage/ndb/src/ndbapi/NdbQueryOperationImpl.hpp	2011-04-06 14:16:13 +0000
+++ b/storage/ndb/src/ndbapi/NdbQueryOperationImpl.hpp	2011-06-20 13:25:48 +0000
@@ -142,7 +142,8 @@ public:
   /** Close query: 
    *  - Release datanode resources,
    *  - Discard pending result sets,
-   *  - optionaly dealloc NdbQuery structures
+   *  - Delete internal buffer and structures for receiving results.
+   *  - Disconnect with NdbQueryDef - it might now be destructed .
    */
   int close(bool forceSend);
 
@@ -191,7 +192,10 @@ public:
 
   /** Get the (transaction independent) definition of this query. */
   const NdbQueryDefImpl& getQueryDef() const
-  { return m_queryDef; }
+  {
+    assert(m_queryDef);
+    return *m_queryDef;
+  }
 
   /** Process TCKEYCONF message. Return true if query is complete. */
   bool execTCKEYCONF();
@@ -213,7 +217,7 @@ public:
    */
   void setStartIndicator()
   { 
-    assert(!m_queryDef.isScanQuery());
+    assert(!getQueryDef().isScanQuery());
     m_startIndicator = true; 
   }
 
@@ -224,7 +228,7 @@ public:
    */
   void setCommitIndicator()
   {  
-    assert(!m_queryDef.isScanQuery());
+    assert(!getQueryDef().isScanQuery());
     m_commitIndicator = true; 
   }
 
@@ -415,7 +419,7 @@ private:
   /** Next query in same transaction.*/
   NdbQueryImpl* m_next;
   /** Definition of this query.*/
-  const NdbQueryDefImpl& m_queryDef;
+  const NdbQueryDefImpl* m_queryDef;
 
   /** Possible error status of this query.*/
   NdbError m_error;

=== modified file 'storage/ndb/test/ndbapi/testMgmd.cpp'
--- a/storage/ndb/test/ndbapi/testMgmd.cpp	2011-02-03 14:45:49 +0000
+++ b/storage/ndb/test/ndbapi/testMgmd.cpp	2011-06-21 13:50:33 +0000
@@ -934,6 +934,171 @@ runBug56844(NDBT_Context* ctx, NDBT_Step
   return NDBT_OK;
 }
 
+static bool
+get_status(const char* connectstring,
+           Properties& status)
+{
+  NdbMgmd ndbmgmd;
+  if (!ndbmgmd.connect(connectstring))
+    return false;
+
+  Properties args;
+  if (!ndbmgmd.call("get status", args,
+                    "node status", status, NULL, true))
+  {
+    g_err << "fetch_mgmd_status: mgmd.call failed" << endl;
+    return false;
+  }
+  return true;
+}
+
+static bool
+value_equal(Properties& status,
+            int nodeid, const char* name,
+            const char* expected_value)
+{
+  const char* value;
+  BaseString key;
+  key.assfmt("node.%d.%s", nodeid, name);
+  if (!status.get(key.c_str(), &value))
+  {
+    g_err << "value_equal: no value found for '" << name
+          << "." << nodeid << "'" << endl;
+    return false;
+  }
+
+  if (strcmp(value, expected_value))
+  {
+    g_err << "value_equal: found unexpected value: '" << value
+          << "', expected: '" << expected_value << "'" <<endl;
+    return false;
+  }
+  g_info << "'" << value << "'=='" << expected_value << "'" << endl;
+  return true;
+}
+
+#include <ndb_version.h>
+
+int runTestBug12352191(NDBT_Context* ctx, NDBT_Step* step)
+{
+  BaseString version;
+  version.assfmt("%u", NDB_VERSION_D);
+  BaseString mysql_version;
+  mysql_version.assfmt("%u", NDB_MYSQL_VERSION_D);
+  BaseString address("127.0.0.1");
+
+  NDBT_Workingdir wd("test_mgmd"); // temporary working directory
+
+  g_err << "** Create config.ini" << endl;
+  Properties config = ConfigFactory::create(2);
+  CHECK(ConfigFactory::write_config_ini(config,
+                                        path(wd.path(),
+                                             "config.ini",
+                                             NULL).c_str()));
+
+  MgmdProcessList mgmds;
+  const int nodeid1 = 1;
+  Mgmd* mgmd1 = new Mgmd(nodeid1);
+  mgmds.push_back(mgmd1);
+
+  const int nodeid2 = 2;
+  Mgmd* mgmd2 = new Mgmd(nodeid2);
+  mgmds.push_back(mgmd2);
+
+  // Start first mgmd
+  CHECK(mgmd1->start_from_config_ini(wd.path()));
+  CHECK(mgmd1->connect(config));
+
+  Properties status1;
+  CHECK(get_status(mgmd1->connectstring(config).c_str(), status1));
+  //status1.print();
+  // Check status for own mgm node, always CONNECTED
+  CHECK(value_equal(status1, nodeid1, "type", "MGM"));
+  CHECK(value_equal(status1, nodeid1, "status", "CONNECTED"));
+  CHECK(value_equal(status1, nodeid1, "version", version.c_str()));
+  CHECK(value_equal(status1, nodeid1, "mysql_version", mysql_version.c_str()));
+  CHECK(value_equal(status1, nodeid1, "address", address.c_str()));
+  CHECK(value_equal(status1, nodeid1, "startphase", "0"));
+  CHECK(value_equal(status1, nodeid1, "dynamic_id", "0"));
+  CHECK(value_equal(status1, nodeid1, "node_group", "0"));
+  CHECK(value_equal(status1, nodeid1, "connect_count", "0"));
+
+  // Check status for other mgm node
+  // not started yet -> NO_CONTACT, no address, no versions
+  CHECK(value_equal(status1, nodeid2, "type", "MGM"));
+  CHECK(value_equal(status1, nodeid2, "status", "NO_CONTACT"));
+  CHECK(value_equal(status1, nodeid2, "version", "0"));
+  CHECK(value_equal(status1, nodeid2, "mysql_version", "0"));
+  CHECK(value_equal(status1, nodeid2, "address", ""));
+  CHECK(value_equal(status1, nodeid2, "startphase", "0"));
+  CHECK(value_equal(status1, nodeid2, "dynamic_id", "0"));
+  CHECK(value_equal(status1, nodeid2, "node_group", "0"));
+  CHECK(value_equal(status1, nodeid2, "connect_count", "0"));
+
+  // Start second mgmd
+  CHECK(mgmd2->start_from_config_ini(wd.path()));
+  CHECK(mgmd2->connect(config));
+
+  // wait for confirmed config
+  for (unsigned i = 0; i < mgmds.size(); i++)
+    CHECK(mgmds[i]->wait_confirmed_config());
+
+  Properties status2;
+  CHECK(get_status(mgmd2->connectstring(config).c_str(), status2));
+  //status2.print();
+  // Check status for own mgm node, always CONNECTED
+  CHECK(value_equal(status2, nodeid2, "type", "MGM"));
+  CHECK(value_equal(status2, nodeid2, "status", "CONNECTED"));
+  CHECK(value_equal(status2, nodeid2, "version", version.c_str()));
+  CHECK(value_equal(status2, nodeid2, "mysql_version", mysql_version.c_str()));
+  CHECK(value_equal(status2, nodeid2, "address", address.c_str()));
+  CHECK(value_equal(status2, nodeid2, "startphase", "0"));
+  CHECK(value_equal(status2, nodeid2, "dynamic_id", "0"));
+  CHECK(value_equal(status2, nodeid2, "node_group", "0"));
+  CHECK(value_equal(status2, nodeid2, "connect_count", "0"));
+
+  // Check status for other mgm node
+  // both started now -> CONNECTED, address and versions filled in
+  CHECK(value_equal(status2, nodeid1, "type", "MGM"));
+  CHECK(value_equal(status2, nodeid1, "status", "CONNECTED"));
+  CHECK(value_equal(status2, nodeid1, "version", version.c_str()));
+  CHECK(value_equal(status2, nodeid1, "mysql_version", mysql_version.c_str()));
+  CHECK(value_equal(status2, nodeid1, "address", address.c_str()));
+  CHECK(value_equal(status2, nodeid1, "startphase", "0"));
+  CHECK(value_equal(status2, nodeid1, "dynamic_id", "0"));
+  CHECK(value_equal(status2, nodeid1, "node_group", "0"));
+  CHECK(value_equal(status2, nodeid1, "connect_count", "0"));
+
+  Properties status3;
+  CHECK(get_status(mgmd1->connectstring(config).c_str(), status3));
+  //status3.print();
+  // Check status for own mgm node, always CONNECTED
+  CHECK(value_equal(status3, nodeid1, "type", "MGM"));
+  CHECK(value_equal(status3, nodeid1, "status", "CONNECTED"));
+  CHECK(value_equal(status3, nodeid1, "version", version.c_str()));
+  CHECK(value_equal(status3, nodeid1, "mysql_version", mysql_version.c_str()));
+  CHECK(value_equal(status3, nodeid1, "address", address.c_str()));
+  CHECK(value_equal(status3, nodeid1, "startphase", "0"));
+  CHECK(value_equal(status3, nodeid1, "dynamic_id", "0"));
+  CHECK(value_equal(status3, nodeid1, "node_group", "0"));
+  CHECK(value_equal(status3, nodeid1, "connect_count", "0"));
+
+  // Check status for other mgm node
+  // both started now -> CONNECTED, address and versions filled in
+  CHECK(value_equal(status3, nodeid2, "type", "MGM"));
+  CHECK(value_equal(status3, nodeid2, "status", "CONNECTED"));
+  CHECK(value_equal(status3, nodeid2, "version", version.c_str()));
+  CHECK(value_equal(status3, nodeid2, "mysql_version", mysql_version.c_str()));
+  CHECK(value_equal(status3, nodeid2, "address", address.c_str()));
+  CHECK(value_equal(status3, nodeid2, "startphase", "0"));
+  CHECK(value_equal(status3, nodeid2, "dynamic_id", "0"));
+  CHECK(value_equal(status3, nodeid2, "node_group", "0"));
+  CHECK(value_equal(status3, nodeid2, "connect_count", "0"));
+
+  return NDBT_OK;
+
+}
+
 NDBT_TESTSUITE(testMgmd);
 DRIVER(DummyDriver); /* turn off use of NdbApi */
 
@@ -981,6 +1146,11 @@ TESTCASE("Bug56844",
 {
   INITIALIZER(runBug56844);
 }
+TESTCASE("Bug12352191",
+         "Test mgmd status for other mgmd")
+{
+  INITIALIZER(runTestBug12352191);
+}
 
 NDBT_TESTSUITE_END(testMgmd);
 

No bundle (reason: revision is a merge (you can force generation of a bundle with env var BZR_FORCE_BUNDLE=1)).
Thread
bzr commit into mysql-5.5-cluster branch (magnus.blaudd:3366) magnus.blaudd22 Jun