/* Copyright (c) 2003, 2015, Oracle and/or its affiliates. All rights reserved. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; version 2 of the License. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #include #include #include "NdbMgmd.hpp" #include #include #include "../../src/mgmapi/mgmapi_internal.h" #include #include #include #include /* Tests that only need the mgmd(s) started Start ndb_mgmd and set NDB_CONNECTSTRING pointing to that/those ndb_mgmd(s), then run testMgm */ int runTestApiSession(NDBT_Context* ctx, NDBT_Step* step) { NdbMgmd mgmd; Uint64 session_id= 0; NdbMgmHandle h; h= ndb_mgm_create_handle(); ndb_mgm_set_connectstring(h, mgmd.getConnectString()); ndb_mgm_connect(h,0,0,0); #ifdef NDB_WIN SOCKET s = ndb_mgm_get_fd(h); #else int s= ndb_mgm_get_fd(h); #endif session_id= ndb_mgm_get_session_id(h); ndbout << "MGM Session id: " << session_id << endl; send(s,"get",3,0); ndb_mgm_disconnect(h); ndb_mgm_destroy_handle(&h); struct NdbMgmSession sess; int slen= sizeof(struct NdbMgmSession); h= ndb_mgm_create_handle(); ndb_mgm_set_connectstring(h, mgmd.getConnectString()); ndb_mgm_connect(h,0,0,0); NdbSleep_SecSleep(1); if(ndb_mgm_get_session(h,session_id,&sess,&slen)) { ndbout << "Failed, session still exists" << endl; ndb_mgm_disconnect(h); ndb_mgm_destroy_handle(&h); return NDBT_FAILED; } else { ndbout << "SUCCESS: session is gone" << endl; ndb_mgm_disconnect(h); ndb_mgm_destroy_handle(&h); return NDBT_OK; } } int runTestApiConnectTimeout(NDBT_Context* ctx, NDBT_Step* step) { NdbMgmd mgmd; g_info << "Check connect works with timeout 3000" << endl; if (!mgmd.set_timeout(3000)) return NDBT_FAILED; if (!mgmd.connect(0, 0, 0)) { g_err << "Connect failed with timeout 3000" << endl; return NDBT_FAILED; } if (!mgmd.disconnect()) return NDBT_FAILED; g_info << "Check connect to illegal host will timeout after 3000" << endl; if (!mgmd.set_timeout(3000)) return NDBT_FAILED; mgmd.setConnectString("1.1.1.1"); const Uint64 tstart= NdbTick_CurrentMillisecond(); if (mgmd.connect(0, 0, 0)) { g_err << "Connect to illegal host suceeded" << endl; return NDBT_FAILED; } const Uint64 msecs= NdbTick_CurrentMillisecond() - tstart; ndbout << "Took about " << msecs <<" milliseconds"< 6000) { g_err << "The connect to illegal host timedout after much longer " << "time than was expected, expected <= 6000, got " << msecs << endl; return NDBT_FAILED; } return NDBT_OK; } int runTestApiTimeoutBasic(NDBT_Context* ctx, NDBT_Step* step) { NdbMgmd mgmd; int result= NDBT_FAILED; int cc= 0; int mgmd_nodeid= 0; ndb_mgm_reply reply; NdbMgmHandle h; h= ndb_mgm_create_handle(); ndb_mgm_set_connectstring(h, mgmd.getConnectString()); ndbout << "TEST timout check_connection" << endl; int errs[] = { 1, 2, 3, -1}; for(int error_ins_no=0; errs[error_ins_no]!=-1; error_ins_no++) { int error_ins= errs[error_ins_no]; ndbout << "trying error " << error_ins << endl; ndb_mgm_connect(h,0,0,0); if(ndb_mgm_check_connection(h) < 0) { result= NDBT_FAILED; goto done; } mgmd_nodeid= ndb_mgm_get_mgmd_nodeid(h); if(mgmd_nodeid==0) { ndbout << "Failed to get mgmd node id to insert error" << endl; result= NDBT_FAILED; goto done; } reply.return_code= 0; if(ndb_mgm_insert_error(h, mgmd_nodeid, error_ins, &reply)< 0) { ndbout << "failed to insert error " << endl; result= NDBT_FAILED; goto done; } ndb_mgm_set_timeout(h,2500); cc= ndb_mgm_check_connection(h); if(cc < 0) result= NDBT_OK; else result= NDBT_FAILED; if(ndb_mgm_is_connected(h)) { ndbout << "FAILED: still connected" << endl; result= NDBT_FAILED; } } ndbout << "TEST get_mgmd_nodeid" << endl; ndb_mgm_connect(h,0,0,0); if(ndb_mgm_insert_error(h, mgmd_nodeid, 0, &reply)< 0) { ndbout << "failed to remove inserted error " << endl; result= NDBT_FAILED; goto done; } cc= ndb_mgm_get_mgmd_nodeid(h); ndbout << "got node id: " << cc << endl; if(cc==0) { ndbout << "FAILED: didn't get node id" << endl; result= NDBT_FAILED; } else result= NDBT_OK; ndbout << "TEST end_session" << endl; ndb_mgm_connect(h,0,0,0); if(ndb_mgm_insert_error(h, mgmd_nodeid, 4, &reply)< 0) { ndbout << "FAILED: insert error 1" << endl; result= NDBT_FAILED; goto done; } cc= ndb_mgm_end_session(h); if(cc==0) { ndbout << "FAILED: success in calling end_session" << endl; result= NDBT_FAILED; } else if(ndb_mgm_get_latest_error(h)!=ETIMEDOUT) { ndbout << "FAILED: Incorrect error code (" << ndb_mgm_get_latest_error(h) << " != expected " << ETIMEDOUT << ") desc: " << ndb_mgm_get_latest_error_desc(h) << " line: " << ndb_mgm_get_latest_error_line(h) << " msg: " << ndb_mgm_get_latest_error_msg(h) << endl; result= NDBT_FAILED; } else result= NDBT_OK; if(ndb_mgm_is_connected(h)) { ndbout << "FAILED: is still connected after error" << endl; result= NDBT_FAILED; } done: ndb_mgm_disconnect(h); ndb_mgm_destroy_handle(&h); return result; } int runTestApiGetStatusTimeout(NDBT_Context* ctx, NDBT_Step* step) { NdbMgmd mgmd; int result= NDBT_OK; int mgmd_nodeid= 0; NdbMgmHandle h; h= ndb_mgm_create_handle(); ndb_mgm_set_connectstring(h, mgmd.getConnectString()); int errs[] = { 0, 5, 6, 7, 8, 9, -1 }; for(int error_ins_no=0; errs[error_ins_no]!=-1; error_ins_no++) { int error_ins= errs[error_ins_no]; ndb_mgm_connect(h,0,0,0); if(ndb_mgm_check_connection(h) < 0) { result= NDBT_FAILED; goto done; } mgmd_nodeid= ndb_mgm_get_mgmd_nodeid(h); if(mgmd_nodeid==0) { ndbout << "Failed to get mgmd node id to insert error" << endl; result= NDBT_FAILED; goto done; } ndb_mgm_reply reply; reply.return_code= 0; if(ndb_mgm_insert_error(h, mgmd_nodeid, error_ins, &reply)< 0) { ndbout << "failed to insert error " << error_ins << endl; result= NDBT_FAILED; } ndbout << "trying error: " << error_ins << endl; ndb_mgm_set_timeout(h,2500); struct ndb_mgm_cluster_state *cl= ndb_mgm_get_status(h); if(cl!=NULL) free(cl); /* * For whatever strange reason, * get_status is okay with not having the last enter there. * instead of "fixing" the api, let's have a special case * so we don't break any behaviour */ if(error_ins!=0 && error_ins!=9 && cl!=NULL) { ndbout << "FAILED: got a ndb_mgm_cluster_state back" << endl; result= NDBT_FAILED; } if(error_ins!=0 && error_ins!=9 && ndb_mgm_is_connected(h)) { ndbout << "FAILED: is still connected after error" << endl; result= NDBT_FAILED; } if(error_ins!=0 && error_ins!=9 && ndb_mgm_get_latest_error(h)!=ETIMEDOUT) { ndbout << "FAILED: Incorrect error code (" << ndb_mgm_get_latest_error(h) << " != expected " << ETIMEDOUT << ") desc: " << ndb_mgm_get_latest_error_desc(h) << " line: " << ndb_mgm_get_latest_error_line(h) << " msg: " << ndb_mgm_get_latest_error_msg(h) << endl; result= NDBT_FAILED; } } done: ndb_mgm_disconnect(h); ndb_mgm_destroy_handle(&h); return result; } int runTestMgmApiGetConfigTimeout(NDBT_Context* ctx, NDBT_Step* step) { NdbMgmd mgmd; int result= NDBT_OK; int mgmd_nodeid= 0; NdbMgmHandle h; h= ndb_mgm_create_handle(); ndb_mgm_set_connectstring(h, mgmd.getConnectString()); int errs[] = { 0, 1, 2, 3, -1 }; for(int error_ins_no=0; errs[error_ins_no]!=-1; error_ins_no++) { int error_ins= errs[error_ins_no]; ndb_mgm_connect(h,0,0,0); if(ndb_mgm_check_connection(h) < 0) { result= NDBT_FAILED; goto done; } mgmd_nodeid= ndb_mgm_get_mgmd_nodeid(h); if(mgmd_nodeid==0) { ndbout << "Failed to get mgmd node id to insert error" << endl; result= NDBT_FAILED; goto done; } ndb_mgm_reply reply; reply.return_code= 0; if(ndb_mgm_insert_error(h, mgmd_nodeid, error_ins, &reply)< 0) { ndbout << "failed to insert error " << error_ins << endl; result= NDBT_FAILED; } ndbout << "trying error: " << error_ins << endl; ndb_mgm_set_timeout(h,2500); struct ndb_mgm_configuration *c= ndb_mgm_get_configuration(h,0); if(c!=NULL) free(c); if(error_ins!=0 && c!=NULL) { ndbout << "FAILED: got a ndb_mgm_configuration back" << endl; result= NDBT_FAILED; } if(error_ins!=0 && ndb_mgm_is_connected(h)) { ndbout << "FAILED: is still connected after error" << endl; result= NDBT_FAILED; } if(error_ins!=0 && ndb_mgm_get_latest_error(h)!=ETIMEDOUT) { ndbout << "FAILED: Incorrect error code (" << ndb_mgm_get_latest_error(h) << " != expected " << ETIMEDOUT << ") desc: " << ndb_mgm_get_latest_error_desc(h) << " line: " << ndb_mgm_get_latest_error_line(h) << " msg: " << ndb_mgm_get_latest_error_msg(h) << endl; result= NDBT_FAILED; } } done: ndb_mgm_disconnect(h); ndb_mgm_destroy_handle(&h); return result; } int runTestMgmApiEventTimeout(NDBT_Context* ctx, NDBT_Step* step) { NdbMgmd mgmd; int result= NDBT_OK; int mgmd_nodeid= 0; NdbMgmHandle h; h= ndb_mgm_create_handle(); ndb_mgm_set_connectstring(h, mgmd.getConnectString()); int errs[] = { 10000, 0, -1 }; for(int error_ins_no=0; errs[error_ins_no]!=-1; error_ins_no++) { int error_ins= errs[error_ins_no]; ndb_mgm_connect(h,0,0,0); if(ndb_mgm_check_connection(h) < 0) { result= NDBT_FAILED; goto done; } mgmd_nodeid= ndb_mgm_get_mgmd_nodeid(h); if(mgmd_nodeid==0) { ndbout << "Failed to get mgmd node id to insert error" << endl; result= NDBT_FAILED; goto done; } ndb_mgm_reply reply; reply.return_code= 0; if(ndb_mgm_insert_error(h, mgmd_nodeid, error_ins, &reply)< 0) { ndbout << "failed to insert error " << error_ins << endl; result= NDBT_FAILED; } ndbout << "trying error: " << error_ins << endl; ndb_mgm_set_timeout(h,2500); int filter[] = { 15, NDB_MGM_EVENT_CATEGORY_BACKUP, 1, NDB_MGM_EVENT_CATEGORY_STARTUP, 0 }; NDB_SOCKET_TYPE my_fd; #ifdef NDB_WIN SOCKET fd= ndb_mgm_listen_event(h, filter); my_fd.s= fd; #else int fd= ndb_mgm_listen_event(h, filter); my_fd.fd= fd; #endif if(!my_socket_valid(my_fd)) { ndbout << "FAILED: could not listen to event" << endl; result= NDBT_FAILED; } union { Uint32 theData[25]; EventReport repData; }; EventReport *fake_event = &repData; fake_event->setEventType(NDB_LE_NDBStopForced); fake_event->setNodeId(42); theData[2]= 0; theData[3]= 0; theData[4]= 0; theData[5]= 0; ndb_mgm_report_event(h, theData, 6); char *tmp= 0; char buf[512]; SocketInputStream in(my_fd,2000); for(int i=0; i<20; i++) { if((tmp = in.gets(buf, sizeof(buf)))) { // const char ping_token[]=""; // if(memcmp(ping_token,tmp,sizeof(ping_token)-1)) if(tmp && strlen(tmp)) ndbout << tmp; } else { if(in.timedout()) { ndbout << "TIMED OUT READING EVENT at iteration " << i << endl; break; } } } /* * events go through a *DIFFERENT* socket than the NdbMgmHandle * so we should still be connected (and be able to check_connection) * */ if(ndb_mgm_check_connection(h) && !ndb_mgm_is_connected(h)) { ndbout << "FAILED: is still connected after error" << endl; result= NDBT_FAILED; } ndb_mgm_disconnect(h); } done: ndb_mgm_disconnect(h); ndb_mgm_destroy_handle(&h); return result; } int runTestMgmApiStructEventTimeout(NDBT_Context* ctx, NDBT_Step* step) { NdbMgmd mgmd; int result= NDBT_OK; int mgmd_nodeid= 0; NdbMgmHandle h; h= ndb_mgm_create_handle(); ndb_mgm_set_connectstring(h, mgmd.getConnectString()); int errs[] = { 10000, 0, -1 }; for(int error_ins_no=0; errs[error_ins_no]!=-1; error_ins_no++) { int error_ins= errs[error_ins_no]; ndb_mgm_connect(h,0,0,0); if(ndb_mgm_check_connection(h) < 0) { result= NDBT_FAILED; goto done; } mgmd_nodeid= ndb_mgm_get_mgmd_nodeid(h); if(mgmd_nodeid==0) { ndbout << "Failed to get mgmd node id to insert error" << endl; result= NDBT_FAILED; goto done; } ndb_mgm_reply reply; reply.return_code= 0; if(ndb_mgm_insert_error(h, mgmd_nodeid, error_ins, &reply)< 0) { ndbout << "failed to insert error " << error_ins << endl; result= NDBT_FAILED; } ndbout << "trying error: " << error_ins << endl; ndb_mgm_set_timeout(h,2500); int filter[] = { 15, NDB_MGM_EVENT_CATEGORY_BACKUP, 1, NDB_MGM_EVENT_CATEGORY_STARTUP, 0 }; NdbLogEventHandle le_handle= ndb_mgm_create_logevent_handle(h, filter); struct ndb_logevent le; for(int i=0; i<20; i++) { if(error_ins==0 || (error_ins!=0 && i<5)) { union { Uint32 theData[25]; EventReport repData; }; EventReport *fake_event = &repData; fake_event->setEventType(NDB_LE_NDBStopForced); fake_event->setNodeId(42); theData[2]= 0; theData[3]= 0; theData[4]= 0; theData[5]= 0; ndb_mgm_report_event(h, theData, 6); } int r= ndb_logevent_get_next(le_handle, &le, 2500); if(r>0) { ndbout << "Receieved event" << endl; } else if(r<0) { ndbout << "ERROR" << endl; } else // no event { ndbout << "TIMED OUT READING EVENT at iteration " << i << endl; if(error_ins==0) result= NDBT_FAILED; else result= NDBT_OK; break; } } /* * events go through a *DIFFERENT* socket than the NdbMgmHandle * so we should still be connected (and be able to check_connection) * */ if(ndb_mgm_check_connection(h) && !ndb_mgm_is_connected(h)) { ndbout << "FAILED: is still connected after error" << endl; result= NDBT_FAILED; } ndb_mgm_disconnect(h); } done: ndb_mgm_disconnect(h); ndb_mgm_destroy_handle(&h); return result; } int runSetConfig(NDBT_Context* ctx, NDBT_Step* step) { NdbMgmd mgmd; if (!mgmd.connect()) return NDBT_FAILED; int loops= ctx->getNumLoops(); for (int l= 0; l < loops; l++){ g_info << l << ": "; struct ndb_mgm_configuration* conf= ndb_mgm_get_configuration(mgmd.handle(), 0); if (!conf) { g_err << "ndb_mgm_get_configuration failed, error: " << ndb_mgm_get_latest_error_msg(mgmd.handle()) << endl; return NDBT_FAILED; } int r= ndb_mgm_set_configuration(mgmd.handle(), conf); free(conf); if (r != 0) { g_err << "ndb_mgm_set_configuration failed, error: " << ndb_mgm_get_latest_error_msg(mgmd.handle()) << endl; return NDBT_FAILED; } } return NDBT_OK; } int runSetConfigUntilStopped(NDBT_Context* ctx, NDBT_Step* step) { int result= NDBT_OK; while(!ctx->isTestStopped() && (result= runSetConfig(ctx, step)) == NDBT_OK) ; return result; } int runGetConfig(NDBT_Context* ctx, NDBT_Step* step) { NdbMgmd mgmd; if (!mgmd.connect()) return NDBT_FAILED; int loops= ctx->getNumLoops(); for (int l= 0; l < loops; l++){ g_info << l << ": "; struct ndb_mgm_configuration* conf= ndb_mgm_get_configuration(mgmd.handle(), 0); if (!conf) return NDBT_FAILED; free(conf); } return NDBT_OK; } int runGetConfigUntilStopped(NDBT_Context* ctx, NDBT_Step* step) { int result= NDBT_OK; while(!ctx->isTestStopped() && (result= runGetConfig(ctx, step)) == NDBT_OK) ; return result; } // Find a random node of a given type. static bool get_nodeid_of_type(NdbMgmd& mgmd, ndb_mgm_node_type type, int *nodeId) { ndb_mgm_node_type node_types[2] = { type, NDB_MGM_NODE_TYPE_UNKNOWN }; ndb_mgm_cluster_state *cs = ndb_mgm_get_status2(mgmd.handle(), node_types); if (cs == NULL) { g_err << "ndb_mgm_get_status2 failed, error: " << ndb_mgm_get_latest_error(mgmd.handle()) << " " << ndb_mgm_get_latest_error_msg(mgmd.handle()) << endl; return false; } int noOfNodes = cs->no_of_nodes; int randomnode = myRandom48(noOfNodes); ndb_mgm_node_state *ns = cs->node_states + randomnode; require((Uint32)ns->node_type == (Uint32)type); require(ns->node_id != 0); *nodeId = ns->node_id; g_info << "Got node id " << *nodeId << " of type " << type << endl; free(cs); return true; } // Ensure getting config from an illegal node fails. // Return true in that case. static bool get_config_from_illegal_node(NdbMgmd& mgmd, int nodeId) { struct ndb_mgm_configuration* conf= ndb_mgm_get_configuration_from_node(mgmd.handle(), nodeId); // Get conf from an illegal node should fail. if (ndb_mgm_get_latest_error(mgmd.handle()) != NDB_MGM_GET_CONFIG_FAILED) { g_err << "ndb_mgm_get_configuration from illegal node " << nodeId << " not failed, error: " << ndb_mgm_get_latest_error(mgmd.handle()) << " " << ndb_mgm_get_latest_error_msg(mgmd.handle()) << endl; return false; } if (conf) { // Should not get a conf from an illegal node. g_err << "ndb_mgm_get_configuration from illegal node: " << nodeId << ", error: " << ndb_mgm_get_latest_error(mgmd.handle()) << " " << ndb_mgm_get_latest_error_msg(mgmd.handle()) << endl; free(conf); return false; } return true; } // Check get_config from a non-existing node fails. static bool check_get_config_illegal_node(NdbMgmd& mgmd) { // Find a node that does not exist Config conf; if (!mgmd.get_config(conf)) return false; int 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 return get_config_from_illegal_node(mgmd, nodeId); } // Check get_config from a non-NDB/MGM node type fails static bool check_get_config_wrong_type(NdbMgmd& mgmd) { int myChoice = myRandom48(2); ndb_mgm_node_type randomAllowedType = (myChoice) ? NDB_MGM_NODE_TYPE_API : NDB_MGM_NODE_TYPE_MGM; int nodeId = 0; if (get_nodeid_of_type(mgmd, randomAllowedType, &nodeId)) { return get_config_from_illegal_node(mgmd, nodeId); } // No API/MGM nodes found. return true; } /* Find management node or a random data node, and get config from it. * Also ensure failure when getting config from * an illegal node (a non-NDB/MGM type, nodeid not defined, * or nodeid > MAX_NODES). */ int runGetConfigFromNode(NDBT_Context* ctx, NDBT_Step* step) { NdbMgmd mgmd; if (!mgmd.connect()) return NDBT_FAILED; if (!check_get_config_wrong_type(mgmd) || !check_get_config_illegal_node(mgmd) || !get_config_from_illegal_node(mgmd, MAX_NODES + 2)) { return NDBT_FAILED; } int loops= ctx->getNumLoops(); for (int l= 0; l < loops; l++) { /* Get config from a node of type: * NDB_MGM_NODE_TYPE_NDB */ int nodeId = 0; if (get_nodeid_of_type(mgmd, NDB_MGM_NODE_TYPE_NDB, &nodeId)) { struct ndb_mgm_configuration* conf = ndb_mgm_get_configuration_from_node(mgmd.handle(), nodeId); if (!conf) { g_err << "ndb_mgm_get_configuration_from_node " << nodeId << " failed, error: " << ndb_mgm_get_latest_error(mgmd.handle()) << " " << ndb_mgm_get_latest_error_msg(mgmd.handle()) << endl; return NDBT_FAILED; } free(conf); } else { // ignore } } return NDBT_OK; } int runGetConfigFromNodeUntilStopped(NDBT_Context* ctx, NDBT_Step* step) { int result= NDBT_OK; while(!ctx->isTestStopped() && (result= runGetConfigFromNode(ctx, step)) == NDBT_OK) ; return result; } int runTestStatus(NDBT_Context* ctx, NDBT_Step* step) { ndb_mgm_node_type types[2] = { NDB_MGM_NODE_TYPE_NDB, NDB_MGM_NODE_TYPE_UNKNOWN }; NdbMgmd mgmd; struct ndb_mgm_cluster_state *state; int iterations = ctx->getNumLoops(); if (!mgmd.connect()) return NDBT_FAILED; int result= NDBT_OK; while (iterations-- != 0 && result == NDBT_OK) { state = ndb_mgm_get_status(mgmd.handle()); if(state == NULL) { ndbout_c("Could not get status!"); result= NDBT_FAILED; continue; } free(state); state = ndb_mgm_get_status2(mgmd.handle(), types); if(state == NULL){ ndbout_c("Could not get status2!"); result= NDBT_FAILED; continue; } free(state); 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) ; 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 failed(const Properties& reply) { BaseString result(get_result(reply)); if (result == "Failed") return true; return false; } static const char* get_message(const Properties& reply) { const char* message; if (!reply.get("message", &message)){ ndbout_c("message: no 'message' found in reply"); return NULL; } return message; } static bool message_contains(const Properties& reply, const char* expected_message) { BaseString message(get_message(reply)); if (strstr(message.c_str(), expected_message) == NULL){ ndbout_c("message_contains: message string '%s' " "didn't contain expected message '%s'", message.c_str(), expected_message); return false; } g_info << " message: " << message << endl; return true; } 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("illegal nodeid %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 expected1; expected1.assfmt("No free node id found for %s", NdbMgmd::NodeType(nodeType).c_str()); BaseString expected2; expected2.assfmt("Connection done from wrong host"); if (!(result_contains(reply, expected1.c_str()) || result_contains(reply, expected2.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()); } #if 0 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; } } require(nodeId); require(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); } #endif 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; } } require(nodeId); require(nodeType != (Uint32)NDB_MGM_NODE_TYPE_UNKNOWN); nodeType = (nodeType + 1) / NDB_MGM_NODE_TYPE_MAX; require((int)nodeType >= (int)NDB_MGM_NODE_TYPE_MIN && (int)nodeType <= (int)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) ; return result; } int runSleepAndStop(NDBT_Context* ctx, NDBT_Step* step) { int counter= 3*ctx->getNumLoops(); while(!ctx->isTestStopped() && counter--) NdbSleep_SecSleep(1);; ctx->stopTest(); return NDBT_OK; } static bool check_connection(NdbMgmd& mgmd) { Properties args, reply; mgmd.verbose(false); // Verbose off bool result= mgmd.call("check connection", args, "check connection reply", reply); mgmd.verbose(); // Verbose on return result; } static bool check_transporter_connect(NdbMgmd& mgmd, const char * hello) { SocketOutputStream out(mgmd.socket()); // Call 'transporter connect' if (out.println("transporter connect\n")) { g_err << "Send failed" << endl; return false; } // Send the 'hello' g_info << "Client hello: '" << hello << "'" << endl; if (out.println("%s", hello)) { g_err << "Send hello '" << hello << "' failed" << endl; return false; } // Should not be possible to read a reply now, socket // should have been closed if (check_connection(mgmd)){ g_err << "not disconnected" << endl; return false; } // disconnect and connect again if (!mgmd.disconnect()) return false; if (!mgmd.connect()) return false; return true; } int runTestTransporterConnect(NDBT_Context* ctx, NDBT_Step* step) { NdbMgmd mgmd; if (!mgmd.connect()) return NDBT_FAILED; int result = NDBT_FAILED; if ( // Junk hello strings check_transporter_connect(mgmd, "hello") && check_transporter_connect(mgmd, "hello again") && // "Blow" the buffer check_transporter_connect(mgmd, "string_longer_than_buf_1234567890") && // Out of range nodeid check_transporter_connect(mgmd, "-1") && check_transporter_connect(mgmd, "-2 2") && check_transporter_connect(mgmd, "10000") && check_transporter_connect(mgmd, "99999 8") && // Valid nodeid, invalid transporter type // Valid nodeid and transporter type, state != CONNECTING // ^These are only possible to test by finding an existing // NDB node that are not started and use its setting(s) true) result = NDBT_OK; return result; } static bool show_config(NdbMgmd& mgmd, const Properties& args, Properties& reply) { if (!mgmd.call("show config", args, "show config reply", reply, NULL, false)) { g_err << "show_config: mgmd.call failed" << endl; return false; } // reply.print(); return true; } int runCheckConfig(NDBT_Context* ctx, NDBT_Step* step) { NdbMgmd mgmd; // Connect to any mgmd and get the config if (!mgmd.connect()) return NDBT_FAILED; Properties args1; Properties config1; if (!show_config(mgmd, args1, config1)) return NDBT_FAILED; // Get the binary config Config conf; if (!mgmd.get_config(conf)) return NDBT_FAILED; // Extract list of connectstrings to each mgmd BaseString connectstring; conf.getConnectString(connectstring, ";"); Vector mgmds; connectstring.split(mgmds, ";"); // Connect to each mgmd and check // they all have the same config for (unsigned i = 0; i < mgmds.size(); i++) { NdbMgmd mgmd2; g_info << "Connecting to " << mgmds[i].c_str() << endl; if (!mgmd2.connect(mgmds[i].c_str())) return NDBT_FAILED; Properties args2; Properties config2; if (!show_config(mgmd, args2, config2)) return NDBT_FAILED; // Compare config1 and config2 line by line Uint32 line = 1; const char* value1; const char* value2; while (true) { if (config1.get("line", line, &value1)) { // config1 had line, so should config2 if (config2.get("line", line, &value2)) { // both configs had line, check they are equal if (strcmp(value1, value2) != 0) { g_err << "the value on line " << line << "didn't match!" << endl; g_err << "config1, value: " << value1 << endl; g_err << "config2, value: " << value2 << endl; return NDBT_FAILED; } // g_info << line << ": " << value1 << " = " << value2 << endl; } else { g_err << "config2 didn't have line " << line << "!" << endl; return NDBT_FAILED; } } else { // Make sure config2 does not have this line either and end loop if (config2.get("line", line, &value2)) { g_err << "config2 had line " << line << " not in config1!" << endl; return NDBT_FAILED; } // End of loop g_info << "There was " << line << " lines in config" << endl; break; } line++; } if (line == 0) { g_err << "FAIL: config should have lines!" << endl; return NDBT_FAILED; } // Compare the binary config Config conf2; if (!mgmd.get_config(conf2)) return NDBT_FAILED; if (!conf.equal(&conf2)) { g_err << "The binary config was different! host: " << mgmds[i] << endl; return NDBT_FAILED; } } return NDBT_OK; } static bool reload_config(NdbMgmd& mgmd, const Properties& args, Properties& reply) { if (!mgmd.call("reload config", args, "reload config reply", reply)) { g_err << "reload config: mgmd.call failed" << endl; return false; } //reply.print(); return true; } static bool reload_config_result_contains(NdbMgmd& mgmd, const Properties& args, const char* expected_result) { Properties reply; if (!reload_config(mgmd, args, reply)) return false; return result_contains(reply, expected_result); } static bool check_reload_config_both_config_and_mycnf(NdbMgmd& mgmd) { Properties args; // Send reload command with both config_filename and mycnf set args.put("config_filename", "some filename"); args.put("mycnf", 1); return reload_config_result_contains(mgmd, args, "ERROR: Both mycnf and config_filename"); } static bool show_variables(NdbMgmd& mgmd, Properties& reply) { if (!mgmd.call("show variables", "", "show variables reply", reply)) { g_err << "show_variables: mgmd.call failed" << endl; return false; } return true; } static bool check_reload_config_invalid_config_filename(NdbMgmd& mgmd, bool mycnf) { BaseString expected("Could not load configuration from 'nonexisting_file"); if (mycnf) { // Differing error message if started from my.cnf expected.assign("Can't switch to use config.ini 'nonexisting_file' " "when node was started from my.cnf"); } Properties args; // Send reload command with an invalid config_filename args.put("config_filename", "nonexisting_file"); return reload_config_result_contains(mgmd, args, expected.c_str()); } int runTestReloadConfig(NDBT_Context* ctx, NDBT_Step* step) { NdbMgmd mgmd; if (!mgmd.connect()) return NDBT_FAILED; Properties variables; if (!show_variables(mgmd, variables)) return NDBT_FAILED; variables.print(); const char* mycnf_str; if (!variables.get("mycnf", &mycnf_str)) abort(); bool uses_mycnf = (strcmp(mycnf_str, "yes") == 0); int result= NDBT_FAILED; if ( check_reload_config_both_config_and_mycnf(mgmd) && check_reload_config_invalid_config_filename(mgmd, uses_mycnf) && true) result= NDBT_OK; if (!mgmd.end_session()) result= NDBT_FAILED; return result; } static bool set_config(NdbMgmd& mgmd, const Properties& args, BaseString encoded_config, Properties& reply) { // Fill in default values of other args Properties call_args(args); if (!call_args.contains("Content-Type")) call_args.put("Content-Type", "ndbconfig/octet-stream"); if (!call_args.contains("Content-Transfer-Encoding")) call_args.put("Content-Transfer-Encoding", "base64"); if (!call_args.contains("Content-Length")) call_args.put("Content-Length", encoded_config.length() ? encoded_config.length() - 1 : 1); if (!mgmd.call("set config", call_args, "set config reply", reply, encoded_config.c_str())) { g_err << "set config: mgmd.call failed" << endl; return false; } //reply.print(); return true; } static bool set_config_result_contains(NdbMgmd& mgmd, const Properties& args, const BaseString& encoded_config, const char* expected_result) { Properties reply; if (!set_config(mgmd, args, encoded_config, reply)) return false; return result_contains(reply, expected_result); } static bool set_config_result_contains(NdbMgmd& mgmd, const Config& conf, const char* expected_result) { Properties reply; Properties args; BaseString encoded_config; if (!conf.pack64(encoded_config)) return false; if (!set_config(mgmd, args, encoded_config, reply)) return false; return result_contains(reply, expected_result); } static bool check_set_config_invalid_content_type(NdbMgmd& mgmd) { Properties args; args.put("Content-Type", "illegal type"); return set_config_result_contains(mgmd, args, BaseString(""), "Unhandled content type 'illegal type'"); } static bool check_set_config_invalid_content_encoding(NdbMgmd& mgmd) { Properties args; args.put("Content-Transfer-Encoding", "illegal encoding"); return set_config_result_contains(mgmd, args, BaseString(""), "Unhandled content encoding " "'illegal encoding'"); } static bool check_set_config_too_large_content_length(NdbMgmd& mgmd) { Properties args; args.put("Content-Length", 1024*1024 + 1); return set_config_result_contains(mgmd, args, BaseString(""), "Illegal config length size 1048577"); } static bool check_set_config_too_small_content_length(NdbMgmd& mgmd) { Properties args; args.put("Content-Length", (Uint32)0); return set_config_result_contains(mgmd, args, BaseString(""), "Illegal config length size 0"); } static bool check_set_config_wrong_config_length(NdbMgmd& mgmd) { // Get the binary config Config conf; if (!mgmd.get_config(conf)) return false; BaseString encoded_config; if (!conf.pack64(encoded_config)) return false; Properties args; args.put("Content-Length", encoded_config.length() - 20); bool res = set_config_result_contains(mgmd, args, encoded_config, "Failed to unpack config"); if (res){ /* There are now additional 20 bytes of junk that has been sent to mgmd, reconnect to get rid of it */ if (!mgmd.disconnect()) return false; if (!mgmd.connect()) return false; } return res; } static bool check_set_config_any_node(NDBT_Context* ctx, NDBT_Step* step, NdbMgmd& mgmd) { // Get the binary config Config conf; if (!mgmd.get_config(conf)) return false; // Extract list of connectstrings to each mgmd BaseString connectstring; conf.getConnectString(connectstring, ";"); Vector mgmds; connectstring.split(mgmds, ";"); // Connect to each mgmd and check // they all have the same config for (unsigned i = 0; i < mgmds.size(); i++) { NdbMgmd mgmd2; g_info << "Connecting to " << mgmds[i].c_str() << endl; if (!mgmd2.connect(mgmds[i].c_str())) return false; // Get the binary config Config conf2; if (!mgmd2.get_config(conf2)) return false; // Set the modified config if (!mgmd2.set_config(conf2)) return false; // Check that all mgmds now have the new config if (runCheckConfig(ctx, step) != NDBT_OK) return false; } return true; } static bool check_set_config_fail_wrong_generation(NdbMgmd& mgmd) { // Get the binary config Config conf; if (!mgmd.get_config(conf)) return false; // Change generation if (!conf.setGeneration(conf.getGeneration() + 10)) return false; // Set the modified config return set_config_result_contains(mgmd, conf, "Invalid generation in"); } static bool check_set_config_fail_wrong_name(NdbMgmd& mgmd) { // Get the binary config Config conf; if (!mgmd.get_config(conf)) return false; // Change name if (!conf.setName("NEWNAME")) return false; // Set the modified config return set_config_result_contains(mgmd, conf, "Invalid configuration name"); } static bool check_set_config_fail_wrong_primary(NdbMgmd& mgmd) { // Get the binary config Config conf; if (!mgmd.get_config(conf)) return false; // Change primary and thus make this configuration invalid if (!conf.setPrimaryMgmNode(conf.getPrimaryMgmNode()+10)) return false; // Set the modified config return set_config_result_contains(mgmd, conf, "Not primary mgm node"); } int runTestSetConfig(NDBT_Context* ctx, NDBT_Step* step) { NdbMgmd mgmd; if (!mgmd.connect()) return NDBT_FAILED; int result= NDBT_FAILED; if ( check_set_config_invalid_content_type(mgmd) && check_set_config_invalid_content_encoding(mgmd) && check_set_config_too_large_content_length(mgmd) && check_set_config_too_small_content_length(mgmd) && check_set_config_wrong_config_length(mgmd) && check_set_config_any_node(ctx, step, mgmd) && check_set_config_fail_wrong_generation(mgmd) && check_set_config_fail_wrong_name(mgmd) && check_set_config_fail_wrong_primary(mgmd) && true) result= NDBT_OK; if (!mgmd.end_session()) result= NDBT_FAILED; return result; } int runTestSetConfigParallel(NDBT_Context* ctx, NDBT_Step* step) { NdbMgmd mgmd; if (!mgmd.connect()) return NDBT_FAILED; int result = NDBT_OK; int loops = ctx->getNumLoops(); int sucessful = 0; int invalid_generation = 0, config_change_ongoing = 0; /* continue looping until "loops" number of successful changes have been made from this thread */ while (sucessful < loops && !ctx->isTestStopped() && result == NDBT_OK) { // Get the binary config Config conf; if (!mgmd.get_config(conf)) return NDBT_FAILED; /* Set the config and check for valid errors */ mgmd.verbose(false); if (mgmd.set_config(conf)) { /* Config change suceeded */ sucessful++; } else { /* Config change failed */ if (mgmd.last_error() != NDB_MGM_CONFIG_CHANGE_FAILED) { g_err << "Config change failed with unexpected error: " << mgmd.last_error() << endl; result = NDBT_FAILED; continue; } BaseString error(mgmd.last_error_message()); if (error == "Invalid generation in configuration") invalid_generation++; else if (error == "Config change ongoing") config_change_ongoing++; else { g_err << "Config change failed with unexpected error: '" << error << "'" << endl; result = NDBT_FAILED; } } } ndbout << "Thread " << step->getStepNo() << ", sucess: " << sucessful << ", ongoing: " << config_change_ongoing << ", invalid_generation: " << invalid_generation << endl; return result; } int runTestSetConfigParallelUntilStopped(NDBT_Context* ctx, NDBT_Step* step) { int result= NDBT_OK; while(!ctx->isTestStopped() && (result= runTestSetConfigParallel(ctx, step)) == NDBT_OK) ; return result; } static bool get_connection_parameter(NdbMgmd& mgmd, const Properties& args, Properties& reply) { // Fill in default values of other args Properties call_args(args); if (!call_args.contains("node1")) call_args.put("node1", 1); if (!call_args.contains("node2")) call_args.put("node2", 1); if (!call_args.contains("param")) call_args.put("param", CFG_CONNECTION_SERVER_PORT); if (!mgmd.call("get connection parameter", call_args, "get connection parameter reply", reply)) { g_err << "get_connection_parameter: mgmd.call failed" << endl; return false; } return true; } static bool set_connection_parameter(NdbMgmd& mgmd, const Properties& args, Properties& reply) { // Fill in default values of other args Properties call_args(args); if (!call_args.contains("node1")) call_args.put("node1", 1); if (!call_args.contains("node2")) call_args.put("node2", 1); if (!call_args.contains("param")) call_args.put("param", CFG_CONNECTION_SERVER_PORT); if (!call_args.contains("value")) call_args.put("value", 37); if (!mgmd.call("set connection parameter", call_args, "set connection parameter reply", reply)) { g_err << "set_connection_parameter: mgmd.call failed" << endl; return false; } return true; } static bool check_connection_parameter_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("node1", nodeId); args.put("node2", nodeId); Properties get_result; if (!get_connection_parameter(mgmd, args, get_result)) return false; if (!result_contains(get_result, "Unable to find connection between nodes")) return false; Properties set_result; if (!set_connection_parameter(mgmd, args, set_result)) return false; if (!failed(set_result)) return false; if (!message_contains(set_result, "Unable to find connection between nodes")) return false; } return true; } static bool check_connection_parameter(NdbMgmd& mgmd) { // Find a NDB node with dynamic port Config conf; if (!mgmd.get_config(conf)) return false; Uint32 nodeId1 = 0; for(Uint32 i= 1; i < MAX_NODES; i++){ Uint32 nodeType; ConfigIter iter(&conf, CFG_SECTION_NODE); if (iter.find(CFG_NODE_ID, i) == 0 && iter.get(CFG_TYPE_OF_SECTION, &nodeType) == 0 && nodeType == NDB_MGM_NODE_TYPE_NDB){ nodeId1 = i; break; } } NodeId otherNodeId = 0; BaseString original_value; // Get current value of first connection between mgmd and other node for (int nodeId = 1; nodeId < MAX_NODES; nodeId++){ g_info << "Checking if connection between " << nodeId1 << " and " << nodeId << " exists" << endl; Properties args; args.put("node1", nodeId1); args.put("node2", nodeId); Properties result; if (!get_connection_parameter(mgmd, args, result)) return false; if (!ok(result)) continue; result.print(); // Get the nodeid otherNodeId = nodeId; // Get original value if (!result.get("value", original_value)) { g_err << "Failed to get original value" << endl; return false; } break; // Done with the loop } if (otherNodeId == 0) { g_err << "Could not find a suitable connection for test" << endl; return false; } Properties get_args; get_args.put("node1", nodeId1); get_args.put("node2", otherNodeId); { g_info << "Set new value(37 by default)" << endl; Properties set_args(get_args); Properties set_result; if (!set_connection_parameter(mgmd, set_args, set_result)) return false; if (!ok(set_result)) return false; } { g_info << "Check new value" << endl; Properties get_result; if (!get_connection_parameter(mgmd, get_args, get_result)) return false; if (!ok(get_result)) return false; BaseString new_value; if (!get_result.get("value", new_value)) { g_err << "Failed to get new value" << endl; return false; } g_info << "new_value: " << new_value << endl; if (new_value != "37") { g_err << "New value was not correct, expected 37, got " << new_value << endl; return false; } } { g_info << "Restore old value" << endl; Properties set_args(get_args); if (!set_args.put("value", original_value.c_str())) { g_err << "Failed to put original_value" << endl; return false; } Properties set_result; if (!set_connection_parameter(mgmd, set_args, set_result)) return false; if (!ok(set_result)) return false; } { g_info << "Check restored value" << endl; Properties get_result; if (!get_connection_parameter(mgmd, get_args, get_result)) return false; if (!ok(get_result)) return false; BaseString restored_value; if (!get_result.get("value", restored_value)) { g_err << "Failed to get restored value" << endl; return false; } if (restored_value != original_value) { g_err << "Restored value was not correct, expected " << original_value << ", got " << restored_value << endl; return false; } g_info << "restored_value: " << restored_value << endl; } return true; } int runTestConnectionParameter(NDBT_Context* ctx, NDBT_Step* step) { NdbMgmd mgmd; if (!mgmd.connect()) return NDBT_FAILED; int result= NDBT_FAILED; if ( check_connection_parameter(mgmd) && check_connection_parameter_invalid_nodeid(mgmd) && true) result= NDBT_OK; if (!mgmd.end_session()) result= NDBT_FAILED; return result; } int runTestConnectionParameterUntilStopped(NDBT_Context* ctx, NDBT_Step* step) { int result= NDBT_OK; while(!ctx->isTestStopped() && (result= runTestConnectionParameter(ctx, step)) == NDBT_OK) ; return result; } static bool set_ports(NdbMgmd& mgmd, const Properties& args, const char* bulk_arg, Properties& reply) { if (!mgmd.call("set ports", args, "set ports reply", reply, bulk_arg)) { g_err << "set_ports: mgmd.call failed" << endl; return false; } return true; } static bool check_set_ports_invalid_nodeid(NdbMgmd& mgmd) { for (int nodeId = MAX_NODES; nodeId < MAX_NODES+2; nodeId++) { g_err << "Testing invalid node " << nodeId << endl; Properties args; args.put("node", nodeId); args.put("num_ports", 2); Properties set_result; if (!set_ports(mgmd, args, "", set_result)) return false; if (ok(set_result)) return false; if (!result_contains(set_result, "Illegal value for argument node")) return false; } return true; } static bool check_set_ports_invalid_num_ports(NdbMgmd& mgmd) { g_err << "Testing invalid number of ports "<< endl; Properties args; args.put("node", 1); args.put("num_ports", MAX_NODES + 37); Properties set_result; if (!set_ports(mgmd, args, "", set_result)) return false; if (ok(set_result)) return false; if (!result_contains(set_result, "Illegal value for argument num_ports")) return false; return true; } static bool check_set_ports_invalid_mismatch_num_port_1(NdbMgmd& mgmd) { g_err << "Testing invalid num port 1"<< endl; Properties args; args.put("node", 1); args.put("num_ports", 1); // Intend to send 1 ^ but passes two below Properties set_result; if (!set_ports(mgmd, args, "1=-37\n2=-38\n", set_result)) return false; if (ok(set_result)) return false; set_result.print(); if (!result_contains(set_result, "expected empty line")) return false; return true; } static bool check_set_ports_invalid_mismatch_num_port_2(NdbMgmd& mgmd) { g_err << "Testing invalid num port 2"<< endl; Properties args; args.put("node", 1); args.put("num_ports", 2); // Intend to send 2 ^ but pass only one line below Properties set_result; if (!set_ports(mgmd, args, "1=-37\n", set_result)) return false; if (ok(set_result)) return false; set_result.print(); if (!result_contains(set_result, "expected name=value pair")) return false; return true; } static bool check_set_ports_invalid_port_list(NdbMgmd& mgmd) { g_err << "Testing invalid port list"<< endl; Properties args; args.put("node", 1); // No connection from 1 -> 1 exist args.put("num_ports", 1); Properties set_result; if (!set_ports(mgmd, args, "1=-37\n", set_result)) return false; set_result.print(); if (ok(set_result)) return false; if (!result_contains(set_result, "Unable to find connection between nodes 1 -> 1")) return false; return true; } static bool check_mgmapi_err(NdbMgmd& mgmd, int return_code, int expected_error, const char* expected_message) { if (return_code != -1) { ndbout_c("check_mgmapi_error: unexpected return code: %d", return_code); return false; } if (mgmd.last_error() != expected_error) { ndbout_c("check_mgmapi_error: unexpected error code: %d " "expected %d", mgmd.last_error(), expected_error); return false; } if (strstr(mgmd.last_error_message(), expected_message) == NULL) { ndbout_c("check_mgmapi_error: last_error_message '%s' " "didn't contain expected message '%s'", mgmd.last_error_message(), expected_message); return false; } return true; } static bool check_set_ports_mgmapi(NdbMgmd& mgmd) { g_err << "Testing mgmapi"<< endl; int ret; int nodeid = 1; unsigned num_ports = 1; ndb_mgm_dynamic_port ports[MAX_NODES * 10]; compile_time_assert(MAX_NODES < NDB_ARRAY_SIZE(ports)); ports[0].nodeid = 1; ports[0].port = -1; { ndbout_c("No handle"); NdbMgmd no_handle; ret = ndb_mgm_set_dynamic_ports(no_handle.handle(), nodeid, ports, num_ports); if (ret != -1) return false; } { ndbout_c("Not connected"); NdbMgmd no_con; no_con.verbose(false); if (no_con.connect("no_such_host:12345", 0, 1)) { // Connect should not suceed! return false; } ret = ndb_mgm_set_dynamic_ports(no_con.handle(), nodeid, ports, num_ports); if (!check_mgmapi_err(no_con, ret, NDB_MGM_SERVER_NOT_CONNECTED, "")) return false; } ndbout_c("Invalid number of ports"); num_ports = 0; // << ret = ndb_mgm_set_dynamic_ports(mgmd.handle(), nodeid, ports, num_ports); if (!check_mgmapi_err(mgmd, ret, NDB_MGM_USAGE_ERROR, "Illegal number of dynamic ports")) return false; ndbout_c("Invalid nodeid"); nodeid = 0; // << num_ports = 1; ret = ndb_mgm_set_dynamic_ports(mgmd.handle(), nodeid, ports, num_ports); if (!check_mgmapi_err(mgmd, ret, NDB_MGM_USAGE_ERROR, "Illegal value for argument node: 0")) return false; ndbout_c("Invalid port in list"); nodeid = 1; ports[0].nodeid = 1; ports[0].port = 1; // << ret = ndb_mgm_set_dynamic_ports(mgmd.handle(), nodeid, ports, num_ports); if (!check_mgmapi_err(mgmd, ret, NDB_MGM_USAGE_ERROR, "Illegal port specfied in ports array")) return false; ndbout_c("Invalid nodeid in list"); nodeid = 1; ports[0].nodeid = 0; // << ports[0].port = -11; ret = ndb_mgm_set_dynamic_ports(mgmd.handle(), nodeid, ports, num_ports); if (!check_mgmapi_err(mgmd, ret, NDB_MGM_USAGE_ERROR, "Illegal nodeid specfied in ports array")) return false; ndbout_c("Max number of ports exceeded"); nodeid = 1; num_ports = MAX_NODES; // << for (unsigned i = 0; i < num_ports; i++) { ports[i].nodeid = i+1; ports[i].port = -37; } ret = ndb_mgm_set_dynamic_ports(mgmd.handle(), nodeid, ports, num_ports); if (!check_mgmapi_err(mgmd, ret, NDB_MGM_USAGE_ERROR, "Illegal value for argument num_ports")) return false; ndbout_c("Many many ports"); nodeid = 1; num_ports = NDB_ARRAY_SIZE(ports); // << for (unsigned i = 0; i < num_ports; i++) { ports[i].nodeid = i+1; ports[i].port = -37; } ret = ndb_mgm_set_dynamic_ports(mgmd.handle(), nodeid, ports, num_ports); if (!check_mgmapi_err(mgmd, ret, NDB_MGM_USAGE_ERROR, "Illegal value for argument num_ports")) return false; return true; } // Return name value pair of nodeid/ports which can be sent // verbatim back to ndb_mgmd static bool get_all_ports(NdbMgmd& mgmd, Uint32 nodeId1, BaseString& values) { for (int nodeId = 1; nodeId < MAX_NODES; nodeId++) { Properties args; args.put("node1", nodeId1); args.put("node2", nodeId); Properties result; if (!get_connection_parameter(mgmd, args, result)) return false; if (!ok(result)) continue; // Get value BaseString value; if (!result.get("value", value)) { g_err << "Failed to get value" << endl; return false; } values.appfmt("%d=%s\n", nodeId, value.c_str()); } return true; } static bool check_set_ports(NdbMgmd& mgmd) { // Find a NDB node with dynamic port Config conf; if (!mgmd.get_config(conf)) return false; Uint32 nodeId1 = 0; for(Uint32 i= 1; i < MAX_NODES; i++){ Uint32 nodeType; ConfigIter iter(&conf, CFG_SECTION_NODE); if (iter.find(CFG_NODE_ID, i) == 0 && iter.get(CFG_TYPE_OF_SECTION, &nodeType) == 0 && nodeType == NDB_MGM_NODE_TYPE_NDB){ nodeId1 = i; break; } } g_err << "Using NDB node with id: " << nodeId1 << endl; g_err << "Get original values of dynamic ports" << endl; BaseString original_values; if (!get_all_ports(mgmd, nodeId1, original_values)) { g_err << "Failed to get all original values" << endl; return false; } ndbout_c("original values: %s", original_values.c_str()); g_err << "Set new values for all dynamic ports" << endl; BaseString new_values; { Vector port_pairs; original_values.split(port_pairs, "\n"); // Remove last empty line require(port_pairs[port_pairs.size()-1] == ""); port_pairs.erase(port_pairs.size()-1); // Generate new portnumbers for (unsigned i = 0; i < port_pairs.size(); i++) { int nodeid, port; if (sscanf(port_pairs[i].c_str(), "%d=%d", &nodeid, &port) != 2) { g_err << "Failed to parse port_pairs[" << i << "]: '" << port_pairs[i] << "'" << endl; return false; } const int new_port = -(int)(i + 37); new_values.appfmt("%d=%d\n", nodeid, new_port); } Properties args; args.put("node", nodeId1); args.put("num_ports", port_pairs.size()); Properties set_result; if (!set_ports(mgmd, args, new_values.c_str(), set_result)) return false; if (!ok(set_result)) { g_err << "Unexpected result received from set_ports" << endl; set_result.print(); return false; } } g_err << "Compare new values of dynamic ports" << endl; { BaseString current_values; if (!get_all_ports(mgmd, nodeId1, current_values)) { g_err << "Failed to get all current values" << endl; return false; } ndbout_c("current values: %s", current_values.c_str()); if (current_values != new_values) { g_err << "Set values was not correct, expected " << new_values << ", got " << current_values << endl; return false; } } g_err << "Restore old values" << endl; { Vector port_pairs; original_values.split(port_pairs, "\n"); // Remove last empty line require(port_pairs[port_pairs.size()-1] == ""); port_pairs.erase(port_pairs.size()-1); Properties args; args.put("node", nodeId1); args.put("num_ports", port_pairs.size()); Properties set_result; if (!set_ports(mgmd, args, original_values.c_str(), set_result)) return false; if (!ok(set_result)) { g_err << "Unexpected result received from set_ports" << endl; set_result.print(); return false; } } g_err << "Check restored values" << endl; { BaseString current_values; if (!get_all_ports(mgmd, nodeId1, current_values)) { g_err << "Failed to get all current values" << endl; return false; } ndbout_c("current values: %s", current_values.c_str()); if (current_values != original_values) { g_err << "Restored values was not correct, expected " << original_values << ", got " << current_values << endl; return false; } } return true; } int runTestSetPorts(NDBT_Context* ctx, NDBT_Step* step) { NdbMgmd mgmd; if (!mgmd.connect()) return NDBT_FAILED; int result= NDBT_FAILED; if ( check_set_ports(mgmd) && check_set_ports_invalid_nodeid(mgmd) && check_set_ports_invalid_num_ports(mgmd) && check_set_ports_invalid_mismatch_num_port_1(mgmd) && check_set_ports_invalid_mismatch_num_port_2(mgmd) && check_set_ports_invalid_port_list(mgmd) && check_set_ports_mgmapi(mgmd) && true) result= NDBT_OK; if (!mgmd.end_session()) result= NDBT_FAILED; return result; } #ifdef NOT_YET static bool check_restart_connected(NdbMgmd& mgmd) { if (!mgmd.restart()) return false; return true; } int runTestRestartMgmd(NDBT_Context* ctx, NDBT_Step* step) { NdbMgmd mgmd; if (!mgmd.connect()) return NDBT_FAILED; int result= NDBT_FAILED; if ( check_restart_connected(mgmd) && true) result= NDBT_OK; if (!mgmd.end_session()) result= NDBT_FAILED; return result; } #endif static bool set_logfilter(NdbMgmd& mgmd, enum ndb_mgm_event_severity severity, int enable) { struct ndb_mgm_reply reply; if (ndb_mgm_set_clusterlog_severity_filter(mgmd.handle(), severity, enable, &reply ) == -1) { g_err << "set_logfilter: ndb_mgm_set_clusterlog_severity_filter failed" << endl; return false; } return true; } static bool get_logfilter(NdbMgmd& mgmd, enum ndb_mgm_event_severity severity, unsigned int* value) { struct ndb_mgm_severity severity_struct; severity_struct.category = severity; if (ndb_mgm_get_clusterlog_severity_filter(mgmd.handle(), &severity_struct, 1) != 1) { g_err << "get_logfilter: ndb_mgm_get_clusterlog_severity_filter failed" << endl; return false; } require(value); *value = severity_struct.value; return true; } int runTestSetLogFilter(NDBT_Context* ctx, NDBT_Step* step) { NdbMgmd mgmd; if (!mgmd.connect()) return NDBT_FAILED; for (int i = 0; i < (int)NDB_MGM_EVENT_SEVERITY_ALL; i++) { g_info << "severity: " << i << endl; ndb_mgm_event_severity severity = (ndb_mgm_event_severity)i; // Get initial value of level unsigned int initial_value; if (!get_logfilter(mgmd, severity, &initial_value)) return NDBT_FAILED; // Turn level off if (!set_logfilter(mgmd, severity, 0)) return NDBT_FAILED; // Check it's off unsigned int curr_value; if (!get_logfilter(mgmd, severity, &curr_value)) return NDBT_FAILED; if (curr_value != 0) { g_err << "Failed to turn off severity: " << severity << endl; return NDBT_FAILED; } // Turn level on if (!set_logfilter(mgmd, severity, 1)) return NDBT_FAILED; // Check it's on if (!get_logfilter(mgmd, severity, &curr_value)) return NDBT_FAILED; if (curr_value == 0) { g_err << "Filed to turn on severity: " << severity << endl; return NDBT_FAILED; } // Toggle, ie. turn off if (!set_logfilter(mgmd, severity, -1)) return NDBT_FAILED; // Check it's off if (!get_logfilter(mgmd, severity, &curr_value)) return NDBT_FAILED; if (curr_value != 0) { g_err << "Failed to toggle severity : " << severity << endl; return NDBT_FAILED; } // Set back initial value if (!set_logfilter(mgmd, severity, initial_value)) return NDBT_FAILED; } return NDBT_OK; } int runTestBug40922(NDBT_Context* ctx, NDBT_Step* step) { NdbMgmd mgmd; if (!mgmd.connect()) return NDBT_FAILED; int filter[] = { 15, NDB_MGM_EVENT_CATEGORY_BACKUP, 1, NDB_MGM_EVENT_CATEGORY_STARTUP, 0 }; NdbLogEventHandle le_handle = ndb_mgm_create_logevent_handle(mgmd.handle(), filter); if (!le_handle) return NDBT_FAILED; g_info << "Calling ndb_log_event_get_next" << endl; struct ndb_logevent le_event; int r = ndb_logevent_get_next(le_handle, &le_event, 2000); g_info << "ndb_log_event_get_next returned " << r << endl; int result = NDBT_FAILED; if (r == 0) { // Got timeout g_info << "ndb_logevent_get_next returned timeout" << endl; result = NDBT_OK; } else { if(r>0) g_err << "ERROR: Receieved unexpected event: " << le_event.type << endl; if(r<0) g_err << "ERROR: ndb_logevent_get_next returned error: " << r << endl; } ndb_mgm_destroy_logevent_handle(&le_handle); return result; } int runTestBug45497(NDBT_Context* ctx, NDBT_Step* step) { int result = NDBT_OK; int loops = ctx->getNumLoops(); Vector mgmds; while(true) { NdbMgmd* mgmd = new NdbMgmd(); // Set quite short timeout if (!mgmd->set_timeout(1000)) { result = NDBT_FAILED; break; } if (mgmd->connect()) { mgmds.push_back(mgmd); g_info << "connections: " << mgmds.size() << endl; continue; } g_err << "Failed to make another connection, connections: " << mgmds.size() << endl; // Disconnect some connections int to_disconnect = 10; while(mgmds.size() && to_disconnect--) { g_info << "disconnnect, connections: " << mgmds.size() << endl; NdbMgmd* mgmd = mgmds[0]; mgmds.erase(0); delete mgmd; } if (loops-- == 0) break; } while(mgmds.size()) { NdbMgmd* mgmd = mgmds[0]; mgmds.erase(0); delete mgmd; } return result; } bool isCategoryValid(struct ndb_logevent* le) { switch (le->category) { case NDB_MGM_EVENT_CATEGORY_BACKUP: case NDB_MGM_EVENT_CATEGORY_STARTUP: case NDB_MGM_EVENT_CATEGORY_NODE_RESTART: case NDB_MGM_EVENT_CATEGORY_CONNECTION: case NDB_MGM_EVENT_CATEGORY_STATISTIC: case NDB_MGM_EVENT_CATEGORY_CHECKPOINT: return true; default: return false; } } int runTestBug16723708(NDBT_Context* ctx, NDBT_Step* step) { NdbMgmd mgmd; int loops = ctx->getNumLoops(); int result = NDBT_FAILED; if (!mgmd.connect()) return NDBT_FAILED; int filter[] = { 15, NDB_MGM_EVENT_CATEGORY_BACKUP, 15, NDB_MGM_EVENT_CATEGORY_STARTUP, 15, NDB_MGM_EVENT_CATEGORY_NODE_RESTART, 15, NDB_MGM_EVENT_CATEGORY_CONNECTION, 15, NDB_MGM_EVENT_CATEGORY_STATISTIC, 15, NDB_MGM_EVENT_CATEGORY_CHECKPOINT, 0 }; NdbLogEventHandle le_handle = ndb_mgm_create_logevent_handle(mgmd.handle(), filter); if (!le_handle) return NDBT_FAILED; NdbLogEventHandle le_handle2 = ndb_mgm_create_logevent_handle(mgmd.handle(), filter); if (!le_handle2) return NDBT_FAILED; for(int l=0; l0) { g_info << "next() ndb_logevent type : " << le_event.type << " category : " << le_event.category << " " << ndb_mgm_get_event_category_string(le_event.category) << endl; if (isCategoryValid(&le_event)) { g_err << "ERROR: ndb_logevent_get_next() returned valid category! " << le_event.category << endl; result = NDBT_FAILED; } } else { g_err << "ERROR: ndb_logevent_get_next returned error: " << r << endl; } if(r2>0) { g_info << "next2() ndb_logevent type : " << le_event2.type << " category : " << le_event2.category << " " << ndb_mgm_get_event_category_string(le_event2.category) << endl; if (!isCategoryValid(&le_event2)) { g_err << "ERROR: ndb_logevent_get_next2() returned invalid category! " << le_event2.category << endl; result = NDBT_FAILED; } } else { g_err << "ERROR: ndb_logevent_get_next2 returned error: " << r << endl; result = NDBT_FAILED; } } if(result == NDBT_FAILED) break; } ndb_mgm_destroy_logevent_handle(&le_handle2); ndb_mgm_destroy_logevent_handle(&le_handle); return result; } static int runTestGetVersion(NDBT_Context* ctx, NDBT_Step* step) { NdbMgmd mgmd; if (!mgmd.connect()) return NDBT_FAILED; char verStr[64]; int major, minor, build; if (ndb_mgm_get_version(mgmd.handle(), &major, &minor, &build, sizeof(verStr), verStr) != 1) { g_err << "ndb_mgm_get_version failed," << "error: " << ndb_mgm_get_latest_error_msg(mgmd.handle()) << "desc: " << ndb_mgm_get_latest_error_desc(mgmd.handle()) << endl; return NDBT_FAILED; } g_info << "Using major: " << major << " minor: " << minor << " build: " << build << " string: " << verStr << endl; int l = 0; int loops = ctx->getNumLoops(); while(l < loops) { char verStr2[64]; int major2, minor2, build2; if (ndb_mgm_get_version(mgmd.handle(), &major2, &minor2, &build2, sizeof(verStr2), verStr2) != 1) { g_err << "ndb_mgm_get_version failed," << "error: " << ndb_mgm_get_latest_error_msg(mgmd.handle()) << "desc: " << ndb_mgm_get_latest_error_desc(mgmd.handle()) << endl; return NDBT_FAILED; } if (major != major2) { g_err << "Got different major: " << major2 << " excpected: " << major << endl; return NDBT_FAILED; } if (minor != minor2) { g_err << "Got different minor: " << minor2 << " excpected: " << minor << endl; return NDBT_FAILED; } if (build != build2) { g_err << "Got different build: " << build2 << " excpected: " << build << endl; return NDBT_FAILED; } if (strcmp(verStr, verStr2) != 0) { g_err << "Got different verStr: " << verStr2 << " excpected: " << verStr << endl; return NDBT_FAILED; } l++; } return NDBT_OK; } static int runTestGetVersionUntilStopped(NDBT_Context* ctx, NDBT_Step* step) { int result= NDBT_OK; while(!ctx->isTestStopped() && (result= runTestGetVersion(ctx, step)) == NDBT_OK) ; return result; } int runTestDumpEvents(NDBT_Context* ctx, NDBT_Step* step) { NdbMgmd mgmd; if (!mgmd.connect()) return NDBT_FAILED; // Test with unsupported logevent_type { const Ndb_logevent_type unsupported = NDB_LE_NDBStopForced; g_info << "ndb_mgm_dump_events(" << unsupported << ")" << endl; const struct ndb_mgm_events* events = ndb_mgm_dump_events(mgmd.handle(), unsupported, 0, 0); if (events != NULL) { g_err << "ndb_mgm_dump_events returned events " << "for unsupported Ndb_logevent_type" << endl; return NDBT_FAILED; } if (ndb_mgm_get_latest_error(mgmd.handle()) != NDB_MGM_USAGE_ERROR || strcmp("ndb_logevent_type 59 not supported", ndb_mgm_get_latest_error_desc(mgmd.handle()))) { g_err << "Unexpected error for unsupported logevent type, " << ndb_mgm_get_latest_error(mgmd.handle()) << ", desc: " << ndb_mgm_get_latest_error_desc(mgmd.handle()) << endl; return NDBT_FAILED; } } // Test with nodes >= MAX_NDB_NODES for (int i = MAX_NDB_NODES; i < MAX_NDB_NODES + 3; i++) { g_info << "ndb_mgm_dump_events(NDB_LE_MemoryUsage, 1, " << i << ")" << endl; const struct ndb_mgm_events* events = ndb_mgm_dump_events(mgmd.handle(), NDB_LE_MemoryUsage, 1, &i); if (events != NULL) { g_err << "ndb_mgm_dump_events returned events " << "for too large nodeid" << endl; return NDBT_FAILED; } int invalid_nodeid; if (ndb_mgm_get_latest_error(mgmd.handle()) != NDB_MGM_USAGE_ERROR || sscanf(ndb_mgm_get_latest_error_desc(mgmd.handle()), "invalid nodes: '%d'", &invalid_nodeid) != 1 || invalid_nodeid != i) { g_err << "Unexpected error for too large nodeid, " << ndb_mgm_get_latest_error(mgmd.handle()) << ", desc: " << ndb_mgm_get_latest_error_desc(mgmd.handle()) << endl; return NDBT_FAILED; } } int l = 0; int loops = ctx->getNumLoops(); while (lno_of_events < 0) { g_err << "ndb_mgm_dump_events returned a negative number of events: " << events->no_of_events << endl; free(events); return NDBT_FAILED; } g_info << "Got " << events->no_of_events << " events" << endl; free(events); } l++; } return NDBT_OK; } int runTestStatusAfterStop(NDBT_Context* ctx, NDBT_Step* step) { NdbMgmd mgmd; if (!mgmd.connect()) return NDBT_FAILED; ndb_mgm_node_type node_types[2] = { NDB_MGM_NODE_TYPE_NDB, NDB_MGM_NODE_TYPE_UNKNOWN }; // Test: get status, stop node, get status again printf("Getting status\n"); ndb_mgm_cluster_state *cs = ndb_mgm_get_status2(mgmd.handle(), node_types); if (cs == NULL) { printf("%s (%d)\n", ndb_mgm_get_latest_error_msg(mgmd.handle()), ndb_mgm_get_latest_error(mgmd.handle())); return NDBT_FAILED; } int nodeId = 0; for(int i=0; i < cs->no_of_nodes; i++ ) { ndb_mgm_node_state *ns = cs->node_states + i; printf("Node ID: %d status:%d\n", ns->node_id, ns->node_status); if (nodeId == 0 && ns->node_type == NDB_MGM_NODE_TYPE_NDB) nodeId = ns->node_id; } free(cs); cs = NULL; printf("Stopping data node\n"); // We only stop 1 data node, in this case NodeId=2 int nodes[1] = { nodeId }; int stopped = ndb_mgm_restart2(mgmd.handle(), NDB_ARRAY_SIZE(nodes), nodes, 0, 0, 1); if (stopped < 0) { printf("ndb_mgm_stop failed, '%s' (%d)\n", ndb_mgm_get_latest_error_msg(mgmd.handle()), ndb_mgm_get_latest_error(mgmd.handle())); return NDBT_FAILED; } printf("Stopped %d data node(s)\n", stopped); printf("Getting status\n"); cs = ndb_mgm_get_status2(mgmd.handle(), node_types); if (cs == NULL) { printf("%s (%d)\n", ndb_mgm_get_latest_error_msg(mgmd.handle()), ndb_mgm_get_latest_error(mgmd.handle())); return NDBT_FAILED; } for(int i=0; i < cs->no_of_nodes; i++ ) { ndb_mgm_node_state *ns = cs->node_states + i; printf("Node ID: %d status:%d\n", ns->node_id, ns->node_status); } free(cs); NdbRestarter res; res.startAll(); res.waitClusterStarted(); return NDBT_OK; } int sort_ng(const void * _e0, const void * _e1) { const struct ndb_mgm_node_state * e0 = (const struct ndb_mgm_node_state*)_e0; const struct ndb_mgm_node_state * e1 = (const struct ndb_mgm_node_state*)_e1; if (e0->node_group != e1->node_group) return e0->node_group - e1->node_group; return e0->node_id - e1->node_id; } int runBug12928429(NDBT_Context* ctx, NDBT_Step* step) { NdbMgmd mgmd; if (!mgmd.connect()) { return NDBT_FAILED; } ndb_mgm_node_type node_types[2] = { NDB_MGM_NODE_TYPE_NDB, NDB_MGM_NODE_TYPE_UNKNOWN }; ndb_mgm_cluster_state * cs = ndb_mgm_get_status2(mgmd.handle(), node_types); if (cs == NULL) { printf("%s (%d)\n", ndb_mgm_get_latest_error_msg(mgmd.handle()), ndb_mgm_get_latest_error(mgmd.handle())); return NDBT_FAILED; } /** * sort according to node-group */ qsort(cs->node_states, cs->no_of_nodes, sizeof(cs->node_states[0]), sort_ng); int ng = cs->node_states[0].node_group; int replicas = 1; for (int i = 1; i < cs->no_of_nodes; i++) { if (cs->node_states[i].node_status != NDB_MGM_NODE_STATUS_STARTED) { ndbout_c("node %u is not started!!!", cs->node_states[i].node_id); free(cs); return NDBT_OK; } if (cs->node_states[i].node_group == ng) { replicas++; } else { break; } } if (replicas == 1) { free(cs); return NDBT_OK; } int nodes[MAX_NODES]; int cnt = 0; for (int i = 0; i < cs->no_of_nodes; i += replicas) { printf("%u ", cs->node_states[i].node_id); nodes[cnt++] = cs->node_states[i].node_id; } printf("\n"); int initial = 0; int nostart = 1; int abort = 0; int force = 1; int disconnnect = 0; /** * restart half of the node...should be only restart half of the nodes */ int res = ndb_mgm_restart4(mgmd.handle(), cnt, nodes, initial, nostart, abort, force, &disconnnect); if (res == -1) { ndbout_c("%u res: %u ndb_mgm_get_latest_error: %u line: %u msg: %s", __LINE__, res, ndb_mgm_get_latest_error(mgmd.handle()), ndb_mgm_get_latest_error_line(mgmd.handle()), ndb_mgm_get_latest_error_msg(mgmd.handle())); return NDBT_FAILED; } { ndb_mgm_cluster_state * cs2 = ndb_mgm_get_status2(mgmd.handle(),node_types); if (cs2 == NULL) { printf("%s (%d)\n", ndb_mgm_get_latest_error_msg(mgmd.handle()), ndb_mgm_get_latest_error(mgmd.handle())); return NDBT_FAILED; } for (int i = 0; i < cs2->no_of_nodes; i++) { int node_id = cs2->node_states[i].node_id; int expect = NDB_MGM_NODE_STATUS_STARTED; for (int c = 0; c < cnt; c++) { if (node_id == nodes[c]) { expect = NDB_MGM_NODE_STATUS_NOT_STARTED; break; } } if (cs2->node_states[i].node_status != expect) { ndbout_c("%u node %u expect: %u found: %u", __LINE__, cs2->node_states[i].node_id, expect, cs2->node_states[i].node_status); return NDBT_FAILED; } } free(cs2); } NdbRestarter restarter; restarter.startAll(); restarter.waitClusterStarted(); /** * restart half of the node...and all nodes in one node group * should restart cluster */ cnt = 0; for (int i = 0; i < replicas; i++) { printf("%u ", cs->node_states[i].node_id); nodes[cnt++] = cs->node_states[i].node_id; } for (int i = replicas; i < cs->no_of_nodes; i += replicas) { printf("%u ", cs->node_states[i].node_id); nodes[cnt++] = cs->node_states[i].node_id; } printf("\n"); res = ndb_mgm_restart4(mgmd.handle(), cnt, nodes, initial, nostart, abort, force, &disconnnect); if (res == -1) { ndbout_c("%u res: %u ndb_mgm_get_latest_error: %u line: %u msg: %s", __LINE__, res, ndb_mgm_get_latest_error(mgmd.handle()), ndb_mgm_get_latest_error_line(mgmd.handle()), ndb_mgm_get_latest_error_msg(mgmd.handle())); return NDBT_FAILED; } { ndb_mgm_cluster_state * cs2 = ndb_mgm_get_status2(mgmd.handle(),node_types); if (cs2 == NULL) { printf("%s (%d)\n", ndb_mgm_get_latest_error_msg(mgmd.handle()), ndb_mgm_get_latest_error(mgmd.handle())); return NDBT_FAILED; } for (int i = 0; i < cs2->no_of_nodes; i++) { int expect = NDB_MGM_NODE_STATUS_NOT_STARTED; if (cs2->node_states[i].node_status != expect) { ndbout_c("%u node %u expect: %u found: %u", __LINE__, cs2->node_states[i].node_id, expect, cs2->node_states[i].node_status); return NDBT_FAILED; } } free(cs2); } restarter.startAll(); restarter.waitClusterStarted(); free(cs); return NDBT_OK; } int runTestNdbApiConfig(NDBT_Context* ctx, NDBT_Step* step) { NdbMgmd mgmd; if (!mgmd.connect()) return NDBT_FAILED; struct test_parameter { Uint32 key; Uint32 NdbApiConfig::*ptr; Uint32 values[2]; } parameters[] = { { CFG_MAX_SCAN_BATCH_SIZE, &NdbApiConfig::m_scan_batch_size, { 10, 1000 } }, { CFG_BATCH_BYTE_SIZE, &NdbApiConfig::m_batch_byte_size, { 10, 1000 } }, { CFG_BATCH_SIZE, &NdbApiConfig::m_batch_size, { 10, 1000 } }, // Skip test of m_waitfor_timeout since it is not configurable in API-section { CFG_DEFAULT_OPERATION_REDO_PROBLEM_ACTION, &NdbApiConfig::m_default_queue_option, { OPERATION_REDO_PROBLEM_ACTION_ABORT, OPERATION_REDO_PROBLEM_ACTION_QUEUE } }, { CFG_DEFAULT_HASHMAP_SIZE, &NdbApiConfig::m_default_hashmap_size, { 240, 3840 } }, }; // Catch if new members are added to NdbApiConfig, // if so add tests and adjust expected size NDB_STATIC_ASSERT(sizeof(NdbApiConfig) == 6 * sizeof(Uint32)); Config savedconf; if (!mgmd.get_config(savedconf)) return NDBT_FAILED; for (size_t i = 0; i < NDB_ARRAY_SIZE(parameters[0].values) ; i ++) { /** * Setup configuration */ // Get the binary config Config conf; if (!mgmd.get_config(conf)) return NDBT_FAILED; ConfigValues::Iterator iter(conf.m_configValues->m_config); for (Uint32 nodeid = 1; nodeid < MAX_NODES; nodeid ++) { Uint32 type; if (!iter.openSection(CFG_SECTION_NODE, nodeid)) continue; if (iter.get(CFG_TYPE_OF_SECTION, &type) && type == NDB_MGM_NODE_TYPE_API) { for (size_t param = 0; param < NDB_ARRAY_SIZE(parameters) ; param ++) { iter.set(parameters[param].key, parameters[param].values[i]); } } iter.closeSection(); } // Set the modified config if (!mgmd.set_config(conf)) return NDBT_FAILED; /** * Connect api */ Ndb_cluster_connection con(mgmd.getConnectString()); const int retries = 12; const int retry_delay = 5; const int verbose = 1; if (con.connect(retries, retry_delay, verbose) != 0) { g_err << "Ndb_cluster_connection.connect failed" << endl; return NDBT_FAILED; } /** * Check api configuration */ NDBT_Context conctx(con); int failures = 0; for (size_t param = 0; param < NDB_ARRAY_SIZE(parameters) ; param ++) { Uint32 expected = parameters[param].values[i]; Uint32 got = conctx.getConfig().*parameters[param].ptr; if (got != expected) { int j; for(j = 0; j < ConfigInfo::m_NoOfParams ; j ++) { if (ConfigInfo::m_ParamInfo[j]._paramId == parameters[param].key) break; } g_err << "Parameter "; if (j < ConfigInfo::m_NoOfParams) g_err << ConfigInfo::m_ParamInfo[j]._fname << " (" << parameters[param].key << ")"; else g_err << "Unknown (" << parameters[param].key << ")"; g_err << ": Expected " << expected << " got " << got << endl; failures++; } if (failures > 0) return NDBT_FAILED; } } // Restore conf after upgrading config generation Config conf; if (!mgmd.get_config(conf)) return NDBT_FAILED; savedconf.setGeneration(conf.getGeneration()); if (!mgmd.set_config(savedconf)) { g_err << "Failed to restore config." << endl; return NDBT_FAILED; } return NDBT_OK; } static int runTestCreateLogEvent(NDBT_Context* ctx, NDBT_Step* step) { NdbMgmd mgmd; int loops = ctx->getNumLoops(); if (!mgmd.connect()) return NDBT_FAILED; int filter[] = { 15, NDB_MGM_EVENT_CATEGORY_BACKUP, 0 }; for(int l=0; l;