#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#4350 | Magnus Svensson | 19 Nov |