MySQL Lists are EOL. Please join:

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

 3091 Magnus Svensson	2008-11-19
      WL#4350
       - Extend test program for ndb_mgmd
added:
  storage/ndb/test/include/SocketInputStream2.hpp
  storage/ndb/test/src/SocketInputStream2.cpp
modified:
  storage/ndb/src/mgmapi/mgmapi.cpp
  storage/ndb/src/mgmapi/mgmapi_internal.h
  storage/ndb/test/include/NdbMgmd.hpp
  storage/ndb/test/ndbapi/Makefile.am
  storage/ndb/test/ndbapi/testMgm.cpp
  storage/ndb/test/src/Makefile.am

per-file messages:
  storage/ndb/src/mgmapi/mgmapi.cpp
    Add function '_ndb_mgm_get_socket' to mgmapi_internal
  storage/ndb/src/mgmapi/mgmapi_internal.h
    Add function '_ndb_mgm_get_socket' to mgmapi_internal
  storage/ndb/test/include/NdbMgmd.hpp
    Extend the NdbMgmd utility class with
     - 'call' - to call any "function" in ndb_mgmd without using mgmapi
     - 'get_config' - to fetch configuration from ndb_mgmd
     - 'end_session' - ndb_mgm_end_session wrapper
     - Pretty printer for "ndb_mgm_node_type"
  storage/ndb/test/include/SocketInputStream2.hpp
    Add utility class to read from socket
  storage/ndb/test/ndbapi/testMgm.cpp
    Add new test for "get nodeid", "get configuration" and "set configuration"
    Add stress test that runs all kind of things while changing config
  storage/ndb/test/src/Makefile.am
    Add SocketInputStream2 to be built
  storage/ndb/test/src/SocketInputStream2.cpp
    Add utility class to read from socket
=== modified file 'storage/ndb/src/mgmapi/mgmapi.cpp'
--- a/storage/ndb/src/mgmapi/mgmapi.cpp	2008-11-05 07:57:18 +0000
+++ b/storage/ndb/src/mgmapi/mgmapi.cpp	2008-11-19 13:42:48 +0000
@@ -3262,4 +3262,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/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-10-31 15:25:01 +0000
+++ b/storage/ndb/test/ndbapi/Makefile.am	2008-11-19 13:42:48 +0000
@@ -89,7 +89,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-17 09:36:02 +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,6 +706,18 @@ int runGetConfig(NDBT_Context* ctx, NDBT
 }
 
 
+int runGetConfigUntilStopped(NDBT_Context* ctx, NDBT_Step* step)
+{
+  int result= NDBT_OK;
+  while(!ctx->isTestStopped() &&
+        (result= runGetConfig(ctx, step)) == NDBT_OK)
+    ;
+  ctx->stopTest();
+  return result;
+}
+
+
+
 int getMgmLogInfo(NdbMgmHandle h, off_t *current_size, off_t *max_size)
 {
   int r, ncol;
@@ -883,13 +906,357 @@ int runTestStatus(NDBT_Context* ctx, NDB
       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;;
 
-    NdbSleep_MilliSleep(delay);
+    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);
+
+  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;
+  }
+  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",
@@ -952,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:3091) WL#4350Magnus Svensson19 Nov