List:Commits« Previous MessageNext Message »
From:Magnus Svensson Date:November 19 2008 2:47pm
Subject:bzr commit into mysql-5.1 branch (msvensson:3114)
View as plain text  
#At file:///home/msvensson/mysql/6.4/

 3114 Magnus Svensson	2008-11-19 [merge]
      Merge
added:
  storage/ndb/test/include/SocketInputStream2.hpp
  storage/ndb/test/src/SocketInputStream2.cpp
modified:
  storage/ndb/src/common/mgmcommon/ConfigRetriever.cpp
  storage/ndb/src/mgmapi/mgmapi.cpp
  storage/ndb/src/mgmapi/mgmapi_internal.h
  storage/ndb/src/mgmsrv/MgmtSrvr.cpp
  storage/ndb/src/mgmsrv/MgmtSrvr.hpp
  storage/ndb/src/mgmsrv/Services.cpp
  storage/ndb/src/mgmsrv/main.cpp
  storage/ndb/test/include/NdbMgmd.hpp
  storage/ndb/test/ndbapi/Makefile.am
  storage/ndb/test/ndbapi/testMgm.cpp
  storage/ndb/test/src/Makefile.am

=== modified file 'storage/ndb/src/common/mgmcommon/ConfigRetriever.cpp'
--- a/storage/ndb/src/common/mgmcommon/ConfigRetriever.cpp	2008-10-24 10:06:10 +0000
+++ b/storage/ndb/src/common/mgmcommon/ConfigRetriever.cpp	2008-11-19 08:53:00 +0000
@@ -275,8 +275,10 @@ ConfigRetriever::verifyConfig(const stru
   if (hostname && hostname[0] != 0 &&
       !SocketServer::tryBind(0,hostname)) {
     BaseString::snprintf(buf, 255,
-                         "Config hostname: %s don't match a local "
-                         "interface, tried to bind, error: %d '%s'",
+                         "The hostname this node should have according "
+                         "to the configuration does not match a local "
+                         "interface. Attempt to bind '%s' "
+                         "failed with error: %d '%s'",
                          hostname, errno, strerror(errno));
     setError(CR_ERROR, buf);
     return false;

=== modified file 'storage/ndb/src/mgmapi/mgmapi.cpp'
--- a/storage/ndb/src/mgmapi/mgmapi.cpp	2008-11-19 10:34:01 +0000
+++ b/storage/ndb/src/mgmapi/mgmapi.cpp	2008-11-19 14:47:19 +0000
@@ -3342,4 +3342,9 @@ int ndb_mgm_ndbinfo_getrow(NdbMgmHandle 
   return 0;
 }
 
+NDB_SOCKET_TYPE _ndb_mgm_get_socket(NdbMgmHandle h)
+{
+  return h->socket;
+}
+
 template class Vector<const ParserRow<ParserDummy>*>;

=== modified file 'storage/ndb/src/mgmapi/mgmapi_internal.h'
--- a/storage/ndb/src/mgmapi/mgmapi_internal.h	2008-09-12 09:09:01 +0000
+++ b/storage/ndb/src/mgmapi/mgmapi_internal.h	2008-11-19 13:42:48 +0000
@@ -80,6 +80,8 @@ extern "C" {
                                 struct ndb_mgm_configuration* config);
 
 
+  NDB_SOCKET_TYPE _ndb_mgm_get_socket(NdbMgmHandle handle);
+
 #ifdef __cplusplus
 }
 #endif

=== modified file 'storage/ndb/src/mgmsrv/MgmtSrvr.cpp'
--- a/storage/ndb/src/mgmsrv/MgmtSrvr.cpp	2008-11-13 13:36:29 +0000
+++ b/storage/ndb/src/mgmsrv/MgmtSrvr.cpp	2008-11-19 14:47:19 +0000
@@ -421,7 +421,6 @@ MgmtSrvr::init()
   BaseString error_string;
   if (!alloc_node_id(&nodeId, NDB_MGM_NODE_TYPE_MGM,
                      0, /* client_addr */
-                     0, /* client_addr_len */
                      error_code, error_string,
                      0 /* log_event */ ))
   {
@@ -2741,7 +2740,6 @@ bool
 MgmtSrvr::alloc_node_id(NodeId * nodeId,
 			enum ndb_mgm_node_type type,
 			struct sockaddr *client_addr, 
-			SOCKET_SIZE_TYPE *client_addr_len,
 			int &error_code, BaseString &error_string,
                         int log_event)
 {
@@ -2757,6 +2755,7 @@ MgmtSrvr::alloc_node_id(NodeId * nodeId,
     }
     DBUG_RETURN(true);
   }
+
   Guard g(m_node_id_mutex);
   int no_mgm= 0;
   NodeBitmask connected_nodes(m_reserved_nodes);
@@ -2775,91 +2774,98 @@ MgmtSrvr::alloc_node_id(NodeId * nodeId,
   int r_config_addr= -1;
   unsigned type_c= 0;
 
-  NdbMutex_Lock(m_local_config_mutex);
-  ConfigIter iter(m_local_config, CFG_SECTION_NODE);
-  for(iter.first(); iter.valid(); iter.next()) {
-    unsigned tmp= 0;
-    if(iter.get(CFG_NODE_ID, &tmp)) require(false);
-    if (*nodeId && *nodeId != tmp)
-      continue;
-    found_matching_id= true;
-    if(iter.get(CFG_TYPE_OF_SECTION, &type_c)) require(false);
-    if(type_c != (unsigned)type)
-      continue;
-    found_matching_type= true;
-    if (connected_nodes.get(tmp))
-      continue;
-    found_free_node= true;
-    if(iter.get(CFG_NODE_HOST, &config_hostname)) require(false);
-    if (config_hostname && config_hostname[0] == 0)
-      config_hostname= 0;
-    else if (client_addr) {
-      // check hostname compatability
-      const void *tmp_in= &(((sockaddr_in*)client_addr)->sin_addr);
-      if((r_config_addr= Ndb_getInAddr(&config_addr, config_hostname)) != 0
-	 || memcmp(&config_addr, tmp_in, sizeof(config_addr)) != 0) {
-	struct in_addr tmp_addr;
-	if(Ndb_getInAddr(&tmp_addr, "localhost") != 0
-	   || memcmp(&tmp_addr, tmp_in, sizeof(config_addr)) != 0) {
-	  // not localhost
-#if 0
-	  ndbout << "MgmtSrvr::getFreeNodeId compare failed for \""
-		 << config_hostname
-		 << "\" id=" << tmp << endl;
-#endif
-	  continue;
-	}
-	// connecting through localhost
-	// check if config_hostname is local
-	if (!SocketServer::tryBind(0,config_hostname)) {
-	  continue;
-	}
+  {
+    Guard guard_config(m_local_config_mutex);
+    ConfigIter iter(m_local_config, CFG_SECTION_NODE);
+    for(iter.first(); iter.valid(); iter.next())
+    {
+      unsigned curr_nodeid = 0;
+      require(!iter.get(CFG_NODE_ID, &curr_nodeid));
+      if (*nodeId && *nodeId != curr_nodeid)
+        continue;
+      found_matching_id = true;
+
+      require(!iter.get(CFG_TYPE_OF_SECTION, &type_c));
+      if(type_c != (unsigned)type)
+        continue;
+      found_matching_type = true;
+
+      if (connected_nodes.get(curr_nodeid))
+        continue;
+      found_free_node = true;
+
+      require(!iter.get(CFG_NODE_HOST, &config_hostname));
+      if (config_hostname && config_hostname[0] == 0)
+        config_hostname = 0;
+      else if (client_addr)
+      {
+        // check hostname compatibility
+        const void *tmp_in = &(((sockaddr_in*)client_addr)->sin_addr);
+        if((r_config_addr= Ndb_getInAddr(&config_addr, config_hostname)) != 0 ||
+           memcmp(&config_addr, tmp_in, sizeof(config_addr)) != 0)
+        {
+          struct in_addr tmp_addr;
+          if(Ndb_getInAddr(&tmp_addr, "localhost") != 0 ||
+             memcmp(&tmp_addr, tmp_in, sizeof(config_addr)) != 0)
+          {
+            // not localhost
+            continue;
+          }
+
+          // connecting through localhost
+          // check if config_hostname is local
+          if (!SocketServer::tryBind(0,config_hostname))
+            continue;
+        }
       }
-    } else { // client_addr == 0
-      if (!SocketServer::tryBind(0,config_hostname)) {
-	continue;
+      else
+      {
+        // client_addr == 0
+        if (!SocketServer::tryBind(0,config_hostname))
+          continue;
       }
+
+      if (*nodeId != 0 ||
+          type != NDB_MGM_NODE_TYPE_MGM ||
+          no_mgm == 1)  // any match is ok
+      {
+        if (config_hostname == 0 &&
+            *nodeId == 0 &&
+            type != NDB_MGM_NODE_TYPE_MGM)
+        {
+          if (!id_found) // only set if not set earlier
+            id_found = curr_nodeid;
+          continue; /* continue looking for a nodeid with specified hostname */
+        }
+        assert(id_found == 0);
+        id_found = curr_nodeid;
+        break;
+      }
+
+      if (id_found) // mgmt server may only have one match
+      {
+        error_string.appfmt("Ambiguous node id's %d and %d. "
+                            "Suggest specifying node id in connectstring, "
+                            "or specifying unique host names in config file.",
+                            id_found, curr_nodeid);
+        error_code = NDB_MGM_ALLOCID_CONFIG_MISMATCH;
+        DBUG_RETURN(false);
+      }
+
+      if (config_hostname == 0)
+      {
+        error_string.appfmt("Ambiguity for node id %d. "
+                            "Suggest specifying node id in connectstring, "
+                            "or specifying unique host names in config file, "
+                            "or specifying just one mgmt server in "
+                            "config file.",
+                            curr_nodeid);
+        error_code = NDB_MGM_ALLOCID_CONFIG_MISMATCH;
+        DBUG_RETURN(false);
+      }
+      id_found = curr_nodeid; // mgmt server matched, check for more matches
     }
-    if (*nodeId != 0 ||
-	type != NDB_MGM_NODE_TYPE_MGM ||
-	no_mgm == 1) { // any match is ok
-
-      if (config_hostname == 0 &&
-	  *nodeId == 0 &&
-	  type != NDB_MGM_NODE_TYPE_MGM)
-      {
-	if (!id_found) // only set if not set earlier
-	  id_found= tmp;
-	continue; /* continue looking for a nodeid with specified
-		   * hostname
-		   */
-      }
-      assert(id_found == 0);
-      id_found= tmp;
-      break;
-    }
-    if (id_found) { // mgmt server may only have one match
-      error_string.appfmt("Ambiguous node id's %d and %d.\n"
-			  "Suggest specifying node id in connectstring,\n"
-			  "or specifying unique host names in config file.",
-			  id_found, tmp);
-      NdbMutex_Unlock(m_local_config_mutex);
-      error_code = NDB_MGM_ALLOCID_CONFIG_MISMATCH;
-      DBUG_RETURN(false);
-    }
-    if (config_hostname == 0) {
-      error_string.appfmt("Ambiguity for node id %d.\n"
-			  "Suggest specifying node id in connectstring,\n"
-			  "or specifying unique host names in config file,\n"
-			  "or specifying just one mgmt server in config file.",
-			  tmp);
-      NdbMutex_Unlock(m_local_config_mutex);
-      error_code = NDB_MGM_ALLOCID_CONFIG_MISMATCH;
-      DBUG_RETURN(false);
-    }
-    id_found= tmp; // mgmt server matched, check for more matches
   }
-  NdbMutex_Unlock(m_local_config_mutex);
 
   if (id_found && client_addr != 0)
   {

=== modified file 'storage/ndb/src/mgmsrv/MgmtSrvr.hpp'
--- a/storage/ndb/src/mgmsrv/MgmtSrvr.hpp	2008-11-12 08:17:14 +0000
+++ b/storage/ndb/src/mgmsrv/MgmtSrvr.hpp	2008-11-19 09:09:11 +0000
@@ -93,7 +93,6 @@ public:
     NodeBitmask m_reserved_nodes;
     NDB_TICKS m_alloc_timeout;
   };
-  NdbMutex *m_node_id_mutex;
 
   /**
    * Enable/disable eventlog log levels/severities.
@@ -358,7 +357,6 @@ public:
   bool getNextNodeId(NodeId * _nodeId, enum ndb_mgm_node_type type) const ;
   bool alloc_node_id(NodeId * _nodeId, enum ndb_mgm_node_type type,
 		     struct sockaddr *client_addr,
-                     SOCKET_SIZE_TYPE *client_addr_len,
 		     int &error_code, BaseString &error_string,
                      int log_event = 1);
 
@@ -480,6 +478,8 @@ private:
   NdbMutex* m_local_config_mutex;
   const Config* m_local_config;
 
+  NdbMutex *m_node_id_mutex;
+
   BlockReference _ownReference;
 
   class ConfigManager* m_config_manager;

=== modified file 'storage/ndb/src/mgmsrv/Services.cpp'
--- a/storage/ndb/src/mgmsrv/Services.cpp	2008-11-07 11:00:38 +0000
+++ b/storage/ndb/src/mgmsrv/Services.cpp	2008-11-17 09:22:20 +0000
@@ -556,7 +556,7 @@ MgmApiSession::get_nodeid(Parser_t::Cont
     NDB_TICKS tick= 0;
     /* only report error on second attempt as not to clog the cluster log */
     while (!m_mgmsrv.alloc_node_id(&tmp, (enum ndb_mgm_node_type)nodetype, 
-                                   (struct sockaddr*)&addr, &addrlen,
+                                   (struct sockaddr*)&addr,
                                    error_code, error_string,
                                    tick == 0 ? 0 : log_event))
     {

=== modified file 'storage/ndb/src/mgmsrv/main.cpp'
--- a/storage/ndb/src/mgmsrv/main.cpp	2008-11-13 08:00:21 +0000
+++ b/storage/ndb/src/mgmsrv/main.cpp	2008-11-13 12:10:52 +0000
@@ -136,12 +136,16 @@ static void usage()
   ndb_usage(short_usage_sub, load_default_groups, my_long_options);
 }
 
+static char **defaults_argv;
 
 static void
 mgmd_exit(int result)
 {
   g_eventLogger->close();
 
+  /* Free memory allocated by 'load_defaults' */
+  free_defaults(defaults_argv);
+
   ndb_end(opt_ndb_endinfo ? MY_CHECK_ERROR | MY_GIVE_INFO : 0);
 
   exit(result);
@@ -157,6 +161,7 @@ int main(int argc, char** argv)
   ndb_opt_set_usage_funcs(NULL, short_usage_sub, usage);
 
   load_defaults("my",load_default_groups,&argc,&argv);
+  defaults_argv= argv; /* Must be freed by 'free_defaults' */
 
   int ho_error;
 #ifndef DBUG_OFF

=== modified file 'storage/ndb/test/include/NdbMgmd.hpp'
--- a/storage/ndb/test/include/NdbMgmd.hpp	2008-11-05 08:03:07 +0000
+++ b/storage/ndb/test/include/NdbMgmd.hpp	2008-11-19 13:42:48 +0000
@@ -16,18 +16,28 @@
 #ifndef NDB_MGMD_HPP
 #define NDB_MGMD_HPP
 
+#include <mgmapi.h>
+#include <mgmapi_internal.h>
+
 #include <BaseString.hpp>
+#include <Properties.hpp>
 
-#include <mgmapi.h>
-#include <mgmapi_debug.h>
+#include <OutputStream.hpp>
+#include <SocketInputStream2.hpp>
+
+#include "../../src/mgmsrv/Config.hpp"
 
 class NdbMgmd {
   BaseString m_connect_str;
   NdbMgmHandle m_handle;
-
-  void error(const char* msg)
+  void error(const char* msg, ...) ATTRIBUTE_FORMAT(printf, 2, 3)
   {
-    ndbout_c("NdbMgmd:%s", msg);
+    va_list args;
+    printf("NdbMgmd::");
+    va_start(args, msg);
+    vprintf(msg, args);
+    va_end(args);
+    printf("\n");
 
     if (m_handle){
       ndbout_c(" error: %d, line: %d, desc: %s",
@@ -78,6 +88,160 @@ public:
     return true;
   }
 
+  bool is_connected(void) {
+    if (!m_handle){
+      error("is_connected: no handle");
+      return false;
+    }
+    if (!ndb_mgm_is_connected(m_handle)){
+      error("is_connected: not connected");
+      return false;
+    }
+    return true;
+  }
+
+  bool call(const char* cmd, const Properties& args,
+            const char* cmd_reply, Properties& reply){
+
+    if (!is_connected()){
+      error("call: not connected");
+      return false;
+    }
+
+    SocketOutputStream out(_ndb_mgm_get_socket(m_handle));
+
+    if (out.println(cmd)){
+      error("call: println failed at line %d", __LINE__);
+      return false;
+    }
+
+    Properties::Iterator iter(&args);
+    const char *name;
+    while((name = iter.next()) != NULL) {
+      PropertiesType t;
+      Uint32 val_i;
+      Uint64 val_64;
+      BaseString val_s;
+
+      args.getTypeOf(name, &t);
+      switch(t) {
+      case PropertiesType_Uint32:
+	args.get(name, &val_i);
+	if (out.println("%s: %d", name, val_i)){
+          error("call: println failed at line %d", __LINE__);
+          return false;
+        }
+	break;
+      case PropertiesType_Uint64:
+	args.get(name, &val_64);
+	if (out.println("%s: %Ld", name, val_64)){
+          error("call: println failed at line %d", __LINE__);
+          return false;
+        }
+	break;
+      case PropertiesType_char:
+	args.get(name, val_s);
+	if (out.println("%s: %s", name, val_s.c_str())){
+          error("call: println failed at line %d", __LINE__);
+          return false;
+        }
+	break;
+      default:
+      case PropertiesType_Properties:
+	/* Illegal */
+        abort();
+	break;
+      }
+    }
+    if (out.print("\n")){
+      error("call: print('\n') failed at line %d", __LINE__);
+      return false;
+    }
+
+
+    // Read the reply
+    BaseString buf;
+    SocketInputStream2 in(_ndb_mgm_get_socket(m_handle));
+    if (!in.gets(buf)){
+      error("call: could not read reply command");
+      return false;
+    }
+
+    // 1. Check correct reply header
+    if (buf != cmd_reply){
+      error("call: unexpected reply command, expected: '%s', got '%s'",
+            cmd_reply, buf.c_str());
+      return false;
+    }
+
+    // 2. Read colon separated name value pairs until empty line
+    while(in.gets(buf)){
+
+      // empty line -> end of reply
+      if (buf == "")
+        return true;
+
+      // Split the name value pair on first ':'
+      Vector<BaseString> name_value_pair;
+      if (buf.split(name_value_pair, ":", 2) != 2){
+        error("call: illegal name value pair '%s' received", buf.c_str());
+        return false;
+      }
+
+      reply.put(name_value_pair[0].trim(" ").c_str(),
+                name_value_pair[1].trim(" ").c_str());
+    }
+
+    error("call: should never come here");
+    abort();
+    return false;
+  }
+
+
+  bool get_config(Config& config){
+
+    if (!is_connected()){
+      error("get_config: not connected");
+      return false;
+    }
+
+    struct ndb_mgm_configuration* conf =
+      ndb_mgm_get_configuration(m_handle,0);
+    if (!conf) {
+      error("get_config: ndb_mgm_get_configuration failed");
+      return false;
+    }
+
+    config.m_configValues= conf;
+    return true;
+  }
+
+  bool end_session(void){
+    if (!is_connected()){
+      error("end_session: not connected");
+      return false;
+    }
+
+    if (ndb_mgm_end_session(m_handle) != 0){
+      error("end_session: ndb_mgm_end_session failed");
+      return false;
+    }
+    return true;
+  }
+
+  // Pretty printer for 'ndb_mgm_node_type'
+  class NodeType {
+    BaseString m_str;
+  public:
+    NodeType(Uint32 node_type) {
+      const char* str= NULL;
+      const char* alias=
+        ndb_mgm_get_node_type_alias_string((ndb_mgm_node_type)node_type, &str);
+      m_str.assfmt("%s(%s)", alias, str);
+    }
+
+    const char* c_str() { return m_str.c_str(); }
+  };
 };
 
 #endif

=== added file 'storage/ndb/test/include/SocketInputStream2.hpp'
--- a/storage/ndb/test/include/SocketInputStream2.hpp	1970-01-01 00:00:00 +0000
+++ b/storage/ndb/test/include/SocketInputStream2.hpp	2008-11-19 13:42:48 +0000
@@ -0,0 +1,55 @@
+/* Copyright (C) 2008 Sun Microsystems Inc.
+
+   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., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA */
+
+#ifndef SOCKETINPUTSTREAM2_HPP
+#define SOCKETINPUTSTREAM2_HPP
+
+#include <NdbTCP.h>
+#include <BaseString.hpp>
+#include <UtilBuffer.hpp>
+
+class SocketInputStream2 {
+  NDB_SOCKET_TYPE m_socket;
+  unsigned m_read_timeout;
+  UtilBuffer m_buffer;
+  size_t m_buffer_read_pos;
+
+  bool has_data_to_read();
+  ssize_t read_socket(char* buf, size_t len);
+  bool get_buffered_line(BaseString& str);
+  bool add_buffer(char* buf, ssize_t len);
+
+public:
+  SocketInputStream2(NDB_SOCKET_TYPE socket,
+                     unsigned read_timeout = 60) :
+    m_socket(socket),
+    m_read_timeout(read_timeout),
+    m_buffer_read_pos(0)
+    {};
+
+  /*
+    Read a line from socket into the string "str" until
+    either terminating newline, EOF or read timeout encountered.
+
+    Returns:
+     true - a line ended with newline was read from socket
+     false - EOF or read timeout occured
+
+  */
+  bool gets(BaseString& str);
+
+};
+
+#endif

=== modified file 'storage/ndb/test/ndbapi/Makefile.am'
--- a/storage/ndb/test/ndbapi/Makefile.am	2008-11-19 10:34:01 +0000
+++ b/storage/ndb/test/ndbapi/Makefile.am	2008-11-19 14:47:19 +0000
@@ -90,7 +90,10 @@ testDataBuffers_SOURCES = testDataBuffer
 testDict_SOURCES = testDict.cpp
 testIndex_SOURCES = testIndex.cpp
 testLimits_SOURCES = testLimits.cpp
-testMgm_SOURCES = testMgm.cpp
+testMgm_SOURCES = testMgm.cpp \
+	$(top_srcdir)/storage/ndb/src/mgmsrv/Config.cpp \
+	$(top_srcdir)/storage/ndb/src/mgmsrv/ConfigInfo.cpp \
+	$(top_srcdir)/storage/ndb/src/mgmsrv/InitConfigFileParser.cpp
 testMgm_CXXFLAGS = -I$(top_srcdir)/storage/ndb/src/mgmapi
 testSingleUserMode_SOURCES = testSingleUserMode.cpp
 testNdbApi_SOURCES = testNdbApi.cpp

=== modified file 'storage/ndb/test/ndbapi/testMgm.cpp'
--- a/storage/ndb/test/ndbapi/testMgm.cpp	2008-11-06 16:28:49 +0000
+++ b/storage/ndb/test/ndbapi/testMgm.cpp	2008-11-19 13:42:48 +0000
@@ -675,6 +675,17 @@ int runSetConfig(NDBT_Context* ctx, NDBT
 }
 
 
+int runSetConfigUntilStopped(NDBT_Context* ctx, NDBT_Step* step)
+{
+  int result= NDBT_OK;
+  while(!ctx->isTestStopped() &&
+        (result= runSetConfig(ctx, step)) == NDBT_OK)
+    ;
+  ctx->stopTest();
+  return result;
+}
+
+
 int runGetConfig(NDBT_Context* ctx, NDBT_Step* step)
 {
   NdbMgmd mgmd;
@@ -695,11 +706,20 @@ int runGetConfig(NDBT_Context* ctx, NDBT
 }
 
 
-int getMgmLogInfo(NdbMgmHandle h, off_t *current_size, off_t *max_size)
+int runGetConfigUntilStopped(NDBT_Context* ctx, NDBT_Step* step)
 {
-  NdbMgmd mgmd;
+  int result= NDBT_OK;
+  while(!ctx->isTestStopped() &&
+        (result= runGetConfig(ctx, step)) == NDBT_OK)
+    ;
+  ctx->stopTest();
+  return result;
+}
 
-  const char *mgm= mgmd.getConnectString();
+
+
+int getMgmLogInfo(NdbMgmHandle h, off_t *current_size, off_t *max_size)
+{
   int r, ncol;
   char rowbuf[1024];
   char **cols;
@@ -749,8 +769,8 @@ int getMgmLogInfo(NdbMgmHandle h, off_t 
 
   }
 
-  ndbout_c("CURRENT SIZE = %llu",*current_size);
-  ndbout_c("MAX SIZE = %llu",*max_size);
+  ndbout_c("CURRENT SIZE = %lu",*current_size);
+  ndbout_c("MAX SIZE = %lu",*max_size);
 
   free(cols);
 
@@ -762,7 +782,6 @@ int runTestMgmLogRotation(NDBT_Context* 
   NdbMgmd mgmd;
   const char *mgm= mgmd.getConnectString();
   int result= NDBT_FAILED;
-  const char *logdest= NULL;
   int mgmid= 0;
   off_t current_size= 0, max_size= 0;
   int i,j;
@@ -848,8 +867,6 @@ done:
 
 int runTestStatus(NDBT_Context* ctx, NDBT_Step* step)
 {
-  NdbMgmHandle h;
-
   ndb_mgm_node_type types[2] = {
     NDB_MGM_NODE_TYPE_NDB,
     NDB_MGM_NODE_TYPE_UNKNOWN
@@ -857,35 +874,16 @@ int runTestStatus(NDBT_Context* ctx, NDB
 
   NdbMgmd mgmd;
   struct ndb_mgm_cluster_state *state;
-  const char *connectstring= mgmd.getConnectString();
   int iterations = ctx->getNumLoops();
   int delay = 2;
 
-  h= ndb_mgm_create_handle();
-  if ( h == 0)
-  {
-    ndbout_c("Unable to create handle");
-    return NDBT_FAILED;
-  }
-  if (ndb_mgm_set_connectstring(h, connectstring) == -1)
-  {
-    ndbout_c("Unable to set connectstring");
-    ndb_mgm_destroy_handle(&h);
-    return NDBT_FAILED;
-  }
-  if (ndb_mgm_connect(h,0,0,0))
-  {
-    ndbout_c("connect failed, %d: %s",
-             ndb_mgm_get_latest_error(h),
-             ndb_mgm_get_latest_error_msg(h));
-    ndb_mgm_destroy_handle(&h);
+  if (!mgmd.connect())
     return NDBT_FAILED;
-  }
 
   int result= NDBT_OK;
   while (iterations-- != 0 && result == NDBT_OK)
   {
-    state = ndb_mgm_get_status(h);
+    state = ndb_mgm_get_status(mgmd.handle());
     if(state == NULL) {
       ndbout_c("Could not get status!");
       result= NDBT_FAILED;
@@ -893,7 +891,7 @@ int runTestStatus(NDBT_Context* ctx, NDB
     }
     free(state);
 
-    state = ndb_mgm_get_status2(h, types);
+    state = ndb_mgm_get_status2(mgmd.handle(), types);
     if(state == NULL){
       ndbout_c("Could not get status2!");
       result= NDBT_FAILED;
@@ -901,23 +899,364 @@ int runTestStatus(NDBT_Context* ctx, NDB
     }
     free(state);
 
-    state = ndb_mgm_get_status2(h, 0);
+    state = ndb_mgm_get_status2(mgmd.handle(), 0);
     if(state == NULL){
       ndbout_c("Could not get status2 second time!");
       result= NDBT_FAILED;
       continue;
     }
     free(state);
+  }
+  return result;
+}
+
+
+int runTestStatusUntilStopped(NDBT_Context* ctx, NDBT_Step* step)
+{
+  int result= NDBT_OK;
+  while(!ctx->isTestStopped() &&
+        (result= runTestStatus(ctx, step)) == NDBT_OK)
+    ;
+  ctx->stopTest();
+  return result;
+}
+
+
+static bool
+get_nodeid(NdbMgmd& mgmd,
+           const Properties& args,
+           Properties& reply)
+{
+  // Fill in default values of other args
+  Properties call_args(args);
+  if (!call_args.contains("version"))
+    call_args.put("version", 1);
+  if (!call_args.contains("nodetype"))
+    call_args.put("nodetype", 1);
+  if (!call_args.contains("nodeid"))
+    call_args.put("nodeid", 1);
+  if (!call_args.contains("user"))
+    call_args.put("user", "mysqld");
+  if (!call_args.contains("password"))
+    call_args.put("password", "mysqld");
+  if (!call_args.contains("public key"))
+  call_args.put("public key", "a public key");
+  if (!call_args.contains("name"))
+    call_args.put("name", "testMgm");
+  if (!call_args.contains("log_event"))
+    call_args.put("log_event", 1);
+  if (!call_args.contains("timeout"))
+    call_args.put("timeout", 100);
+
+  if (!call_args.contains("endian"))
+  {
+    union { long l; char c[sizeof(long)]; } endian_check;
+    endian_check.l = 1;
+    call_args.put("endian", (endian_check.c[sizeof(long)-1])?"big":"little");
+  }
+
+  if (!mgmd.call("get nodeid", call_args,
+                 "get nodeid reply", reply))
+  {
+    g_err << "get_nodeid: mgmd.call failed" << endl;
+    return false;
+  }
+
+  // reply.print();
+  return true;
+}
+
+
+static const char*
+get_result(const Properties& reply)
+{
+  const char* result;
+  if (!reply.get("result", &result)){
+    ndbout_c("result: no 'result' found in reply");
+    return NULL;
+  }
+  return result;
+}
+
+
+static bool result_contains(const Properties& reply,
+                            const char* expected_result)
+{
+  BaseString result(get_result(reply));
+  if (strstr(result.c_str(), expected_result) == NULL){
+    ndbout_c("result_contains: result string '%s' "
+             "didn't contain expected result '%s'",
+             result.c_str(), expected_result);
+    return false;
+  }
+  g_info << " result: " << result << endl;
+  return true;
+}
+
+
+static bool ok(const Properties& reply)
+{
+  BaseString result(get_result(reply));
+  if (result == "Ok")
+    return true;
+  return false;
+}
+
+
+static bool get_nodeid_result_contains(NdbMgmd& mgmd,
+                                       const Properties& args,
+                                       const char* expected_result)
+{
+  Properties reply;
+  if (!get_nodeid(mgmd, args, reply))
+    return false;
+  return result_contains(reply, expected_result);
+}
+
+
+
+static bool
+check_get_nodeid_invalid_endian1(NdbMgmd& mgmd)
+{
+  union { long l; char c[sizeof(long)]; } endian_check;
+  endian_check.l = 1;
+  Properties args;
+  /* Set endian to opposite value */
+  args.put("endian", (endian_check.c[sizeof(long)-1])?"little":"big");
+  return get_nodeid_result_contains(mgmd, args,
+                                    "Node does not have the same endian");
+}
+
+
+static bool
+check_get_nodeid_invalid_endian2(NdbMgmd& mgmd)
+{
+  Properties args;
+  /* Set endian to weird value */
+  args.put("endian", "hepp");
+  return get_nodeid_result_contains(mgmd, args,
+                                    "Node does not have the same endian");
+}
+
+
+static bool
+check_get_nodeid_invalid_nodetype1(NdbMgmd& mgmd)
+{
+  Properties args;
+  args.put("nodetype", 37);
+  return get_nodeid_result_contains(mgmd, args,
+                                    "unknown nodetype 37");
+}
+
+
+static bool
+check_get_nodeid_invalid_nodeid(NdbMgmd& mgmd)
+{
+  for (int nodeId = MAX_NODES; nodeId < MAX_NODES+2; nodeId++){
+    g_info << "Testing invalid node " << nodeId << endl;;
+
+    Properties args;
+    args.put("nodeid", nodeId);
+    BaseString expected;
+    expected.assfmt("No node defined with id=%d", nodeId);
+    if (!get_nodeid_result_contains(mgmd, args, expected.c_str()))
+      return false;
+  }
+  return true;
+}
+
+
+static bool
+check_get_nodeid_dynamic_nodeid(NdbMgmd& mgmd)
+{
+  bool result = true;
+  Uint32 nodeId= 0; // Get dynamic node id
+  for (int nodeType = NDB_MGM_NODE_TYPE_MIN;
+       nodeType < NDB_MGM_NODE_TYPE_MAX; nodeType++){
+    while(true)
+    {
+      g_info << "Testing dynamic nodeid " << nodeId
+             << ", nodeType: " << nodeType << endl;
+
+      Properties args;
+      args.put("nodeid", nodeId);
+      args.put("nodetype", nodeType);
+      Properties reply;
+      if (!get_nodeid(mgmd, args, reply))
+        return false;
+
+      /*
+        Continue to get dynamic id's until
+        an error "there is no more nodeid" occur
+      */
+      if (!ok(reply)){
+        BaseString expected;
+        expected.assfmt("No free node id found for %s",
+                        NdbMgmd::NodeType(nodeType).c_str());
+        if (!result_contains(reply, expected.c_str()))
+          result= false; // Got wrong error message
+        break;
+      }
+    }
+  }
+  return result;
+}
+
+
+static bool
+check_get_nodeid_nonode(NdbMgmd& mgmd)
+{
+  // Find a node that does not exist
+  Config conf;
+  if (!mgmd.get_config(conf))
+    return false;
+
+  Uint32 nodeId = 0;
+  for(Uint32 i= 1; i < MAX_NODES; i++){
+    ConfigIter iter(&conf, CFG_SECTION_NODE);
+    if (iter.find(CFG_NODE_ID, i) != 0){
+      nodeId = i;
+      break;
+    }
+  }
+  if (nodeId == 0)
+    return true; // All nodes probably defined
+
+  g_info << "Testing nonexisting node " << nodeId << endl;;
+
+  Properties args;
+  args.put("nodeid", nodeId);
+  BaseString expected;
+  expected.assfmt("No node defined with id=%d", nodeId);
+  return get_nodeid_result_contains(mgmd, args, expected.c_str());
+}
+
+
+static bool
+check_get_nodeid_nodeid1(NdbMgmd& mgmd)
+{
+
+  // Find a node that does exist
+  Config conf;
+  if (!mgmd.get_config(conf))
+    return false;
+
+  Uint32 nodeId = 0;
+  Uint32 nodeType = NDB_MGM_NODE_TYPE_UNKNOWN;
+  for(Uint32 i= 1; i < MAX_NODES; i++){
+    ConfigIter iter(&conf, CFG_SECTION_NODE);
+    if (iter.find(CFG_NODE_ID, i) == 0){
+      nodeId = i;
+      iter.get(CFG_TYPE_OF_SECTION, &nodeType);
+      break;
+    }
+  }
+  assert(nodeId);
+  assert(nodeType != (Uint32)NDB_MGM_NODE_TYPE_UNKNOWN);
+
+  Properties args, reply;
+  args.put("nodeid",nodeId);
+  args.put("nodetype",nodeType);
+  if (!get_nodeid(mgmd, args, reply))
+  {
+    g_err << "check_get_nodeid_nodeid1: failed for "
+          << "nodeid: " << nodeId << ", nodetype: " << nodeType << endl;
+    return false;
+  }
+  reply.print();
+  return ok(reply);
+}
+
+
+static bool
+check_get_nodeid_wrong_nodetype(NdbMgmd& mgmd)
+{
+  // Find a node that does exist
+  Config conf;
+  if (!mgmd.get_config(conf))
+    return false;
+
+  Uint32 nodeId = 0;
+  Uint32 nodeType = NDB_MGM_NODE_TYPE_UNKNOWN;
+  for(Uint32 i= 1; i < MAX_NODES; i++){
+    ConfigIter iter(&conf, CFG_SECTION_NODE);
+    if (iter.find(CFG_NODE_ID, i) == 0){
+      nodeId = i;
+      iter.get(CFG_TYPE_OF_SECTION, &nodeType);
+      break;
+    }
+  }
+  assert(nodeId && nodeType != (Uint32)NDB_MGM_NODE_TYPE_UNKNOWN);
+
+  nodeType = (nodeType + 1) / NDB_MGM_NODE_TYPE_MAX;
+  assert(nodeType > NDB_MGM_NODE_TYPE_MIN && nodeType < NDB_MGM_NODE_TYPE_MAX);
 
-    NdbSleep_MilliSleep(delay);
+  Properties args, reply;
+  args.put("nodeid",nodeId);
+  args.put("nodeid",nodeType);
+  if (!get_nodeid(mgmd, args, reply))
+  {
+    g_err << "check_get_nodeid_nodeid1: failed for "
+          << "nodeid: " << nodeId << ", nodetype: " << nodeType << endl;
+    return false;
   }
-  // No disconnect, destroy should take care of that
-  // ndb_mgm_disconnect(h);
-  ndb_mgm_destroy_handle(&h);
+  BaseString expected;
+  expected.assfmt("Id %d configured as", nodeId);
+  return result_contains(reply, expected.c_str());
+}
+
+
+
+int runTestGetNodeId(NDBT_Context* ctx, NDBT_Step* step)
+{
+  NdbMgmd mgmd;
+
+  if (!mgmd.connect())
+    return NDBT_FAILED;
+
+  int result= NDBT_FAILED;
+  if (
+      check_get_nodeid_invalid_endian1(mgmd) &&
+      check_get_nodeid_invalid_endian2(mgmd) &&
+      check_get_nodeid_invalid_nodetype1(mgmd) &&
+//      check_get_nodeid_invalid_nodeid(mgmd) &&
+      check_get_nodeid_dynamic_nodeid(mgmd) &&
+      check_get_nodeid_nonode(mgmd) &&
+//      check_get_nodeid_nodeid1(mgmd) &&
+      check_get_nodeid_wrong_nodetype(mgmd) &&
+      true)
+    result= NDBT_OK;
+
+  if (!mgmd.end_session())
+    result= NDBT_FAILED;
+
+  return result;
+}
+
+
+int runTestGetNodeIdUntilStopped(NDBT_Context* ctx, NDBT_Step* step)
+{
+  int result= NDBT_OK;
+  while(!ctx->isTestStopped() &&
+        (result= runTestGetNodeId(ctx, step)) == NDBT_OK)
+    ;
+  ctx->stopTest();
   return result;
 }
 
 
+int runSleepAndStop(NDBT_Context* ctx, NDBT_Step* step)
+{
+  int counter= 10*ctx->getNumLoops();
+
+  while(!ctx->isTestStopped() && counter--)
+    NdbSleep_SecSleep(1);;
+  ctx->stopTest();
+  return NDBT_OK;
+}
+
+
+
 NDBT_TESTSUITE(testMgm);
 DRIVER(DummyDriver); /* turn off use of NdbApi */
 TESTCASE("ApiSessionFailure",
@@ -963,11 +1302,13 @@ TESTCASE("SetConfig",
 TESTCASE("GetConfig", "Run ndb_mgm_get_configuration in parallel"){
   STEPS(runGetConfig, 100);
 }
+#if 0
 TESTCASE("MgmLogRotation",
 	 "Test log rotation"){
   INITIALIZER(runTestMgmLogRotation);
 
 }
+#endif
 TESTCASE("TestStatus",
 	 "Test status and status2"){
   INITIALIZER(runTestStatus);
@@ -978,6 +1319,19 @@ TESTCASE("TestStatus200",
   STEPS(runTestStatus, 200);
 
 }
+TESTCASE("TestGetNodeId",
+	 "Test 'get nodeid'"){
+  INITIALIZER(runTestGetNodeId);
+
+}
+TESTCASE("Stress",
+	 "Run everything while changing config"){
+  STEP(runTestGetNodeIdUntilStopped);
+  STEP(runSetConfigUntilStopped);
+  STEPS(runGetConfigUntilStopped, 10);
+  STEPS(runTestStatusUntilStopped, 10);
+  STEP(runSleepAndStop);
+}
 NDBT_TESTSUITE_END(testMgm);
 
 int main(int argc, const char** argv){

=== modified file 'storage/ndb/test/src/Makefile.am'
--- a/storage/ndb/test/src/Makefile.am	2008-08-26 14:20:06 +0000
+++ b/storage/ndb/test/src/Makefile.am	2008-11-19 13:42:48 +0000
@@ -26,7 +26,8 @@ libNDBT_a_SOURCES = \
 	NdbRestarter.cpp NdbRestarts.cpp NDBT_Output.cpp \
 	NdbBackup.cpp  NdbConfig.cpp NDBT_Table.cpp \
 	NdbSchemaCon.cpp NdbSchemaOp.cpp getarg.c AtrtClient.cpp \
-	CpcClient.cpp NdbMixRestarter.cpp NDBT_Thread.cpp DbUtil.cpp
+	CpcClient.cpp NdbMixRestarter.cpp NDBT_Thread.cpp DbUtil.cpp \
+	SocketInputStream2.cpp
 
 INCLUDES_LOC = -I$(top_srcdir)/storage/ndb/src/common/mgmcommon -I$(top_srcdir)/storage/ndb/include/mgmcommon -I$(top_srcdir)/storage/ndb/include/kernel -I$(top_srcdir)/storage/ndb/src/mgmapi -I$(top_srcdir)/include
 

=== added file 'storage/ndb/test/src/SocketInputStream2.cpp'
--- a/storage/ndb/test/src/SocketInputStream2.cpp	1970-01-01 00:00:00 +0000
+++ b/storage/ndb/test/src/SocketInputStream2.cpp	2008-11-19 13:42:48 +0000
@@ -0,0 +1,120 @@
+/* Copyright (C) 2008 Sun Microsystems Inc.
+
+   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., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA */
+
+#include <SocketInputStream2.hpp>
+
+#include <NdbOut.hpp>
+
+bool
+SocketInputStream2::gets(BaseString& str)
+{
+  if (get_buffered_line(str))
+    return true;
+
+  char buf[16];
+  do {
+    ssize_t read_res = read_socket(buf, sizeof(buf));
+    if (read_res == -1)
+      return false;
+
+    if (!add_buffer(buf, read_res))
+      return false;
+
+    if (get_buffered_line(str))
+      return true;
+
+  } while(true);
+
+  abort(); // Should never come here
+  return false;
+};
+
+
+bool
+SocketInputStream2::has_data_to_read()
+{
+  fd_set readset;
+  FD_ZERO(&readset);
+  my_FD_SET(m_socket, &readset);
+
+  struct timeval timeout;
+  timeout.tv_sec  = m_read_timeout;
+  timeout.tv_usec = 0;
+
+  const int res = select(my_socket_nfds(m_socket, 0) + 1,
+                         &readset, 0, 0, &timeout);
+
+  if (res == 1)
+    return true; // Yes, there was data
+
+  if (res == 0)
+    return false; // Timeout occured
+
+  assert(res == -1);
+  return false;
+}
+
+
+ssize_t
+SocketInputStream2::read_socket(char* buf, size_t len)
+{
+  if (!has_data_to_read())
+    return -1;
+
+  size_t read_res = my_recv(m_socket, buf, len, 0);
+  if (read_res == 0)
+    return -1; // Has data to read but only EOF received
+
+  return read_res;
+}
+
+
+bool
+SocketInputStream2::get_buffered_line(BaseString& str)
+{
+  char *start, *ptr;
+  char *end = (char*)m_buffer.get_data() + m_buffer.length();
+  start = ptr =(char*)m_buffer.get_data() + m_buffer_read_pos;
+
+  while(ptr && ptr < end && *ptr)
+  {
+    if (*ptr == '\n')
+    {
+      size_t len = ptr-start;
+      /* Found end of line, return this part of the buffer */
+      str.assign(start, len);
+
+      /*
+         Set new read position in buffer, increase with
+         one to step past '\n'
+      */
+      m_buffer_read_pos += (len + 1);
+
+      return true;
+    }
+    ptr++;
+  }
+  return false;
+}
+
+
+bool
+SocketInputStream2::add_buffer(char* buf, ssize_t len)
+{
+  // ndbout_c("add_buffer: '%.*s'", len, buf);
+  if (m_buffer.append(buf, len) != 0)
+    return false;
+  return true;
+}

Thread
bzr commit into mysql-5.1 branch (msvensson:3114) Magnus Svensson19 Nov