diff --git a/storage/ndb/src/common/util/InputStream.cpp b/storage/ndb/src/common/util/InputStream.cpp index 17703eb7e52d4e644e0313aab4596938026d3624..ee7f2d5c8b267b4999b4551067e2cab1206d17cd 100644 --- a/storage/ndb/src/common/util/InputStream.cpp +++ b/storage/ndb/src/common/util/InputStream.cpp @@ -59,6 +59,7 @@ SocketInputStream::gets(char * buf, int bufLen) { if(res == 0) { + m_timedout= true; buf[0]=0; return buf; } @@ -67,7 +68,6 @@ SocketInputStream::gets(char * buf, int bufLen) { if(res == -1) { - m_timedout= true; return 0; } diff --git a/storage/ndb/src/mgmapi/mgmapi.cpp b/storage/ndb/src/mgmapi/mgmapi.cpp index a0a6493f41da704a7637381b1375395a36f384f2..5671bf1561d2f0e38ead1391a4eb11fe49576b13 100644 --- a/storage/ndb/src/mgmapi/mgmapi.cpp +++ b/storage/ndb/src/mgmapi/mgmapi.cpp @@ -137,18 +137,41 @@ setError(NdbMgmHandle h, int error, int error_line, const char * msg, ...){ return ret; \ } -#define CHECK_REPLY(reply, ret) \ +#define CHECK_REPLY(handle, reply, ret) \ if(reply == NULL) { \ - SET_ERROR(handle, NDB_MGM_ILLEGAL_SERVER_REPLY, ""); \ + if(!handle->last_error) \ + SET_ERROR(handle, NDB_MGM_ILLEGAL_SERVER_REPLY, ""); \ return ret; \ } -#define DBUG_CHECK_REPLY(reply, ret) \ +#define DBUG_CHECK_REPLY(handle, reply, ret) \ if (reply == NULL) { \ - SET_ERROR(handle, NDB_MGM_ILLEGAL_SERVER_REPLY, ""); \ + if(!handle->last_error) \ + SET_ERROR(handle, NDB_MGM_ILLEGAL_SERVER_REPLY, ""); \ DBUG_RETURN(ret); \ } +#define CHECK_TIMEDOUT(in, out) \ + if(in.timedout() || out.timedout()) \ + SET_ERROR(handle, ETIMEDOUT, \ + "Time out talking to management server"); + +#define CHECK_TIMEDOUT_RET(h, in, out, ret) \ + if(in.timedout() || out.timedout()) { \ + SET_ERROR(handle, ETIMEDOUT, \ + "Time out talking to management server"); \ + ndb_mgm_disconnect_quiet(h); \ + return ret; \ + } + +#define DBUG_CHECK_TIMEDOUT_RET(h, in, out, ret) \ + if(in.timedout() || out.timedout()) { \ + SET_ERROR(handle, ETIMEDOUT, \ + "Time out talking to management server"); \ + ndb_mgm_disconnect_quiet(h); \ + DBUG_RETURN(ret); \ + } + /***************************************************************************** * Handles *****************************************************************************/ @@ -375,6 +398,8 @@ ndb_mgm_call(NdbMgmHandle handle, const ParserRow<ParserDummy> *command_reply, } out.println(""); + CHECK_TIMEDOUT_RET(handle, in, out, NULL); + Parser_t::Context ctx; ParserDummy session(handle->socket); Parser_t parser(command_reply, in, true, true, true); @@ -382,14 +407,17 @@ ndb_mgm_call(NdbMgmHandle handle, const ParserRow<ParserDummy> *command_reply, const Properties* p = parser.parse(ctx, session); if (p == NULL){ if(!ndb_mgm_is_connected(handle)) { + CHECK_TIMEDOUT_RET(handle, in, out, NULL); DBUG_RETURN(NULL); } else { + CHECK_TIMEDOUT_RET(handle, in, out, NULL); if(ctx.m_status==Parser_t::Eof || ctx.m_status==Parser_t::NoLine) { ndb_mgm_disconnect(handle); + CHECK_TIMEDOUT_RET(handle, in, out, NULL); DBUG_RETURN(NULL); } /** @@ -411,6 +439,10 @@ ndb_mgm_call(NdbMgmHandle handle, const ParserRow<ParserDummy> *command_reply, p->print(handle->logfile, "IN: "); } #endif + + if(p && (in.timedout() || out.timedout())) + delete p; + CHECK_TIMEDOUT_RET(handle, in, out, NULL); DBUG_RETURN(p); } @@ -603,6 +635,22 @@ ndb_mgm_get_fd(NdbMgmHandle handle) return handle->socket; } +/** + * Disconnect from mgm server without error checking + * Should be used internally only. + * e.g. on timeout, we leave NdbMgmHandle disconnected + */ +extern "C" +int +ndb_mgm_disconnect_quiet(NdbMgmHandle handle) +{ + NDB_CLOSE_SOCKET(handle->socket); + handle->socket = NDB_INVALID_SOCKET; + handle->connected = 0; + + return 0; +} + /** * Disconnect from a mgm server */ @@ -614,11 +662,7 @@ ndb_mgm_disconnect(NdbMgmHandle handle) CHECK_HANDLE(handle, -1); CHECK_CONNECTED(handle, -1); - NDB_CLOSE_SOCKET(handle->socket); - handle->socket = NDB_INVALID_SOCKET; - handle->connected = 0; - - return 0; + return ndb_mgm_disconnect_quiet(handle); } struct ndb_mgm_type_atoi @@ -787,18 +831,24 @@ ndb_mgm_get_status(NdbMgmHandle handle) out.println("get status"); out.println(""); + CHECK_TIMEDOUT_RET(handle, in, out, NULL); + char buf[1024]; if(!in.gets(buf, sizeof(buf))) { + CHECK_TIMEDOUT_RET(handle, in, out, NULL); SET_ERROR(handle, NDB_MGM_ILLEGAL_SERVER_REPLY, "Probably disconnected"); return NULL; } if(strcmp("node status\n", buf) != 0) { + CHECK_TIMEDOUT_RET(handle, in, out, NULL); + ndbout << in.timedout() << " " << out.timedout() << buf << endl; SET_ERROR(handle, NDB_MGM_ILLEGAL_NODE_STATUS, buf); return NULL; } if(!in.gets(buf, sizeof(buf))) { + CHECK_TIMEDOUT_RET(handle, in, out, NULL); SET_ERROR(handle, NDB_MGM_ILLEGAL_SERVER_REPLY, "Probably disconnected"); return NULL; } @@ -807,6 +857,7 @@ ndb_mgm_get_status(NdbMgmHandle handle) Vector<BaseString> split; tmp.split(split, ":"); if(split.size() != 2){ + CHECK_TIMEDOUT_RET(handle, in, out, NULL); SET_ERROR(handle, NDB_MGM_ILLEGAL_NODE_STATUS, buf); return NULL; } @@ -841,8 +892,12 @@ ndb_mgm_get_status(NdbMgmHandle handle) if(!in.gets(buf, sizeof(buf))) { free(state); - SET_ERROR(handle, NDB_MGM_ILLEGAL_SERVER_REPLY, - "Probably disconnected"); + if(in.timedout() || out.timedout()) + SET_ERROR(handle, ETIMEDOUT, + "Time out talking to management server"); + else + SET_ERROR(handle, NDB_MGM_ILLEGAL_SERVER_REPLY, + "Probably disconnected"); return NULL; } tmp.assign(buf); @@ -873,6 +928,7 @@ ndb_mgm_get_status(NdbMgmHandle handle) if(i+1 != noOfNodes){ free(state); + CHECK_TIMEDOUT_RET(handle, in, out, NULL); SET_ERROR(handle, NDB_MGM_ILLEGAL_NODE_STATUS, "Node count mismatch"); return NULL; } @@ -901,7 +957,7 @@ ndb_mgm_enter_single_user(NdbMgmHandle handle, args.put("nodeId", nodeId); const Properties *reply; reply = ndb_mgm_call(handle, enter_single_reply, "enter single user", &args); - CHECK_REPLY(reply, -1); + CHECK_REPLY(handle, reply, -1); BaseString result; reply->get("result", result); @@ -932,7 +988,7 @@ ndb_mgm_exit_single_user(NdbMgmHandle handle, struct ndb_mgm_reply* /*reply*/) const Properties *reply; reply = ndb_mgm_call(handle, exit_single_reply, "exit single user", 0); - CHECK_REPLY(reply, -1); + CHECK_REPLY(handle, reply, -1); const char * buf; reply->get("result", &buf); @@ -1029,7 +1085,7 @@ ndb_mgm_stop3(NdbMgmHandle handle, int no_of_nodes, const int * node_list, reply = ndb_mgm_call(handle, stop_reply_v2, "stop all", &args); else reply = ndb_mgm_call(handle, stop_reply_v1, "stop all", &args); - CHECK_REPLY(reply, -1); + CHECK_REPLY(handle, reply, -1); if(!reply->get("stopped", &stoppedNoOfNodes)){ SET_ERROR(handle, NDB_MGM_STOP_FAILED, @@ -1071,7 +1127,7 @@ ndb_mgm_stop3(NdbMgmHandle handle, int no_of_nodes, const int * node_list, else reply = ndb_mgm_call(handle, stop_reply_v1, "stop", &args); - CHECK_REPLY(reply, stoppedNoOfNodes); + CHECK_REPLY(handle, reply, stoppedNoOfNodes); if(!reply->get("stopped", &stoppedNoOfNodes)){ SET_ERROR(handle, NDB_MGM_STOP_FAILED, "Could not get number of stopped nodes from mgm server"); @@ -1174,7 +1230,7 @@ ndb_mgm_restart3(NdbMgmHandle handle, int no_of_nodes, const int * node_list, handle->read_timeout= 5*60*1000; // 5 minutes reply = ndb_mgm_call(handle, restart_reply_v1, "restart all", &args); handle->read_timeout= timeout; - CHECK_REPLY(reply, -1); + CHECK_REPLY(handle, reply, -1); BaseString result; reply->get("result", result); @@ -1301,7 +1357,7 @@ ndb_mgm_get_clusterlog_severity_filter(NdbMgmHandle handle, Properties args; const Properties *reply; reply = ndb_mgm_call(handle, getinfo_reply, "get info clusterlog", &args); - CHECK_REPLY(reply, -1); + CHECK_REPLY(handle, reply, -1); for(unsigned int i=0; i < severity_size; i++) { reply->get(clusterlog_severity_names[severity[i].category], &severity[i].value); @@ -1332,7 +1388,7 @@ ndb_mgm_get_clusterlog_severity_filter_old(NdbMgmHandle handle) Properties args; const Properties *reply; reply = ndb_mgm_call(handle, getinfo_reply, "get info clusterlog", &args); - CHECK_REPLY(reply, NULL); + CHECK_REPLY(handle, reply, NULL); for(int i=0; i < (int)NDB_MGM_EVENT_SEVERITY_ALL; i++) { reply->get(clusterlog_severity_names[i], &enabled[i]); @@ -1364,7 +1420,7 @@ ndb_mgm_set_clusterlog_severity_filter(NdbMgmHandle handle, const Properties *reply; reply = ndb_mgm_call(handle, filter_reply, "set logfilter", &args); - CHECK_REPLY(reply, retval); + CHECK_REPLY(handle, reply, retval); BaseString result; reply->get("result", result); @@ -1458,7 +1514,7 @@ ndb_mgm_get_clusterlog_loglevel(NdbMgmHandle handle, Properties args; const Properties *reply; reply = ndb_mgm_call(handle, getloglevel_reply, "get cluster loglevel", &args); - CHECK_REPLY(reply, -1); + CHECK_REPLY(handle, reply, -1); for(int i=0; i < loglevel_count; i++) { reply->get(clusterlog_names[loglevel[i].category], &loglevel[i].value); @@ -1494,7 +1550,7 @@ ndb_mgm_get_clusterlog_loglevel_old(NdbMgmHandle handle) Properties args; const Properties *reply; reply = ndb_mgm_call(handle, getloglevel_reply, "get cluster loglevel", &args); - CHECK_REPLY(reply, NULL); + CHECK_REPLY(handle, reply, NULL); for(int i=0; i < loglevel_count; i++) { reply->get(clusterlog_names[i], &loglevel[i]); @@ -1527,7 +1583,7 @@ ndb_mgm_set_clusterlog_loglevel(NdbMgmHandle handle, int nodeId, const Properties *reply; reply = ndb_mgm_call(handle, clusterlog_reply, "set cluster loglevel", &args); - CHECK_REPLY(reply, -1); + CHECK_REPLY(handle, reply, -1); DBUG_ENTER("ndb_mgm_set_clusterlog_loglevel"); DBUG_PRINT("enter",("node=%d, category=%d, level=%d", nodeId, cat, level)); @@ -1565,7 +1621,7 @@ ndb_mgm_set_loglevel_node(NdbMgmHandle handle, int nodeId, args.put("level", level); const Properties *reply; reply = ndb_mgm_call(handle, loglevel_reply, "set loglevel", &args); - CHECK_REPLY(reply, -1); + CHECK_REPLY(handle, reply, -1); BaseString result; reply->get("result", result); @@ -1624,7 +1680,7 @@ ndb_mgm_listen_event_internal(NdbMgmHandle handle, const int filter[], if(reply == NULL) { close(sockfd); - CHECK_REPLY(reply, -1); + CHECK_REPLY(handle, reply, -1); } delete reply; return sockfd; @@ -1668,7 +1724,7 @@ ndb_mgm_dump_state(NdbMgmHandle handle, int nodeId, const int * _args, const Properties *prop; prop = ndb_mgm_call(handle, dump_state_reply, "dump state", &args); - CHECK_REPLY(prop, -1); + CHECK_REPLY(handle, prop, -1); BaseString result; prop->get("result", result); @@ -1705,6 +1761,7 @@ ndb_mgm_start_signallog(NdbMgmHandle handle, int nodeId, start_signallog_reply, "start signallog", &args); + CHECK_REPLY(handle, prop, -1); if(prop != NULL) { BaseString result; @@ -1741,6 +1798,7 @@ ndb_mgm_stop_signallog(NdbMgmHandle handle, int nodeId, const Properties *prop; prop = ndb_mgm_call(handle, stop_signallog_reply, "stop signallog", &args); + CHECK_REPLY(handle, prop, -1); if(prop != NULL) { BaseString result; @@ -1805,6 +1863,7 @@ ndb_mgm_log_signals(NdbMgmHandle handle, int nodeId, const Properties *prop; prop = ndb_mgm_call(handle, stop_signallog_reply, "log signals", &args); + CHECK_REPLY(handle, prop, -1); if(prop != NULL) { BaseString result; @@ -1842,6 +1901,7 @@ ndb_mgm_set_trace(NdbMgmHandle handle, int nodeId, int traceNumber, const Properties *prop; prop = ndb_mgm_call(handle, set_trace_reply, "set trace", &args); + CHECK_REPLY(handle, prop, -1); if(prop != NULL) { BaseString result; @@ -1879,6 +1939,7 @@ ndb_mgm_insert_error(NdbMgmHandle handle, int nodeId, int errorCode, const Properties *prop; prop = ndb_mgm_call(handle, insert_error_reply, "insert error", &args); + CHECK_REPLY(handle, prop, -1); if(prop != NULL) { BaseString result; @@ -1919,7 +1980,7 @@ ndb_mgm_start(NdbMgmHandle handle, int no_of_nodes, const int * node_list) Properties args; const Properties *reply; reply = ndb_mgm_call(handle, start_reply, "start all", &args); - CHECK_REPLY(reply, -1); + CHECK_REPLY(handle, reply, -1); Uint32 count = 0; if(!reply->get("started", &count)){ @@ -1985,7 +2046,7 @@ ndb_mgm_start_backup(NdbMgmHandle handle, int wait_completed, reply = ndb_mgm_call(handle, start_backup_reply, "start backup", &args); handle->read_timeout= old_timeout; } - CHECK_REPLY(reply, -1); + CHECK_REPLY(handle, reply, -1); BaseString result; reply->get("result", result); @@ -2019,7 +2080,7 @@ ndb_mgm_abort_backup(NdbMgmHandle handle, unsigned int backupId, const Properties *prop; prop = ndb_mgm_call(handle, stop_backup_reply, "abort backup", &args); - CHECK_REPLY(prop, -1); + CHECK_REPLY(handle, prop, -1); const char * buf; prop->get("result", &buf); @@ -2036,7 +2097,7 @@ ndb_mgm_abort_backup(NdbMgmHandle handle, unsigned int backupId, extern "C" struct ndb_mgm_configuration * ndb_mgm_get_configuration(NdbMgmHandle handle, unsigned int version) { - + SET_ERROR(handle, NDB_MGM_NO_ERROR, "Executing: ndb_mgm_get_configuration"); CHECK_HANDLE(handle, 0); CHECK_CONNECTED(handle, 0); @@ -2054,7 +2115,7 @@ ndb_mgm_get_configuration(NdbMgmHandle handle, unsigned int version) { const Properties *prop; prop = ndb_mgm_call(handle, reply, "get config", &args); - CHECK_REPLY(prop, 0); + CHECK_REPLY(handle, prop, 0); do { const char * buf; @@ -2091,9 +2152,14 @@ ndb_mgm_get_configuration(NdbMgmHandle handle, unsigned int version) { size_t start = 0; do { if((read = read_socket(handle->socket, handle->read_timeout, - &buf64[start], len-start)) == -1){ - delete[] buf64; + &buf64[start], len-start)) < 1){ + delete[] buf64; buf64 = 0; + if(read==0) + SET_ERROR(handle, ETIMEDOUT, "Timeout reading packed config"); + else + SET_ERROR(handle, errno, "Error reading packed config"); + ndb_mgm_disconnect_quiet(handle); break; } start += read; @@ -2214,7 +2280,7 @@ ndb_mgm_alloc_nodeid(NdbMgmHandle handle, unsigned int version, int nodetype, const Properties *prop; prop= ndb_mgm_call(handle, reply, "get nodeid", &args); - CHECK_REPLY(prop, -1); + CHECK_REPLY(handle, prop, -1); nodeid= -1; do { @@ -2266,7 +2332,7 @@ ndb_mgm_set_int_parameter(NdbMgmHandle handle, const Properties *prop; prop= ndb_mgm_call(handle, reply, "set parameter", &args); - CHECK_REPLY(prop, -1); + CHECK_REPLY(handle, prop, -1); int res= -1; do { @@ -2305,7 +2371,8 @@ ndb_mgm_set_int64_parameter(NdbMgmHandle handle, const Properties *prop; prop= ndb_mgm_call(handle, reply, "set parameter", &args); - + CHECK_REPLY(handle, prop, 0); + if(prop == NULL) { SET_ERROR(handle, EIO, "Unable set parameter"); return -1; @@ -2348,6 +2415,7 @@ ndb_mgm_set_string_parameter(NdbMgmHandle handle, const Properties *prop; prop= ndb_mgm_call(handle, reply, "set parameter", &args); + CHECK_REPLY(handle, prop, 0); if(prop == NULL) { SET_ERROR(handle, EIO, "Unable set parameter"); @@ -2385,7 +2453,8 @@ ndb_mgm_purge_stale_sessions(NdbMgmHandle handle, char **purged){ const Properties *prop; prop= ndb_mgm_call(handle, reply, "purge stale sessions", &args); - + CHECK_REPLY(handle, prop, -1); + if(prop == NULL) { SET_ERROR(handle, EIO, "Unable to purge stale sessions"); return -1; @@ -2470,7 +2539,7 @@ ndb_mgm_set_connection_int_parameter(NdbMgmHandle handle, const Properties *prop; prop= ndb_mgm_call(handle, reply, "set connection parameter", &args); - DBUG_CHECK_REPLY(prop, -1); + DBUG_CHECK_REPLY(handle, prop, -1); int res= -1; do { @@ -2512,7 +2581,7 @@ ndb_mgm_get_connection_int_parameter(NdbMgmHandle handle, const Properties *prop; prop = ndb_mgm_call(handle, reply, "get connection parameter", &args); - DBUG_CHECK_REPLY(prop, -3); + DBUG_CHECK_REPLY(handle, prop, -3); int res= -1; do { @@ -2574,7 +2643,7 @@ ndb_mgm_get_mgmd_nodeid(NdbMgmHandle handle) const Properties *prop; prop = ndb_mgm_call(handle, reply, "get mgmd nodeid", &args); - DBUG_CHECK_REPLY(prop, 0); + DBUG_CHECK_REPLY(handle, prop, 0); if(!prop->get("nodeid",&nodeid)){ fprintf(handle->errstream, "Unable to get value\n"); @@ -2609,7 +2678,7 @@ int ndb_mgm_report_event(NdbMgmHandle handle, Uint32 *data, Uint32 length) const Properties *prop; prop = ndb_mgm_call(handle, reply, "report event", &args); - DBUG_CHECK_REPLY(prop, -1); + DBUG_CHECK_REPLY(handle, prop, -1); DBUG_RETURN(0); } @@ -2628,6 +2697,7 @@ int ndb_mgm_end_session(NdbMgmHandle handle) SocketInputStream in(handle->socket, handle->read_timeout); char buf[32]; in.gets(buf, sizeof(buf)); + CHECK_TIMEDOUT_RET(handle, in, s_output, -1); DBUG_RETURN(0); } @@ -2653,7 +2723,7 @@ int ndb_mgm_get_version(NdbMgmHandle handle, const Properties *prop; prop = ndb_mgm_call(handle, reply, "get version", &args); - CHECK_REPLY(prop, 0); + CHECK_REPLY(handle, prop, 0); Uint32 id; if(!prop->get("id",&id)){ @@ -2704,7 +2774,7 @@ ndb_mgm_get_session_id(NdbMgmHandle handle) const Properties *prop; prop = ndb_mgm_call(handle, reply, "get session id", &args); - CHECK_REPLY(prop, 0); + CHECK_REPLY(handle, prop, 0); if(!prop->get("id",&session_id)){ fprintf(handle->errstream, "Unable to get session id\n"); @@ -2741,7 +2811,7 @@ ndb_mgm_get_session(NdbMgmHandle handle, Uint64 id, const Properties *prop; prop = ndb_mgm_call(handle, reply, "get session", &args); - CHECK_REPLY(prop, 0); + CHECK_REPLY(handle, prop, 0); Uint64 r_id; int rlen= 0; diff --git a/storage/ndb/src/mgmapi/mgmapi_internal.h b/storage/ndb/src/mgmapi/mgmapi_internal.h index d30be221dcd98a73ad293b3d465934b91902d897..192bc57afd95eccfab981cc646dc8503d0a50777 100644 --- a/storage/ndb/src/mgmapi/mgmapi_internal.h +++ b/storage/ndb/src/mgmapi/mgmapi_internal.h @@ -68,6 +68,8 @@ extern "C" { */ NDB_SOCKET_TYPE ndb_mgm_convert_to_transporter(NdbMgmHandle *handle); + int ndb_mgm_disconnect_quiet(NdbMgmHandle handle); + #ifdef __cplusplus } #endif diff --git a/storage/ndb/src/mgmsrv/Services.cpp b/storage/ndb/src/mgmsrv/Services.cpp index 0bbdf4a9e51e51e90f1b71e9af322e12d9309955..17072c240aef7b8d33ae1a295cce370d0429db75 100644 --- a/storage/ndb/src/mgmsrv/Services.cpp +++ b/storage/ndb/src/mgmsrv/Services.cpp @@ -290,6 +290,8 @@ struct PurgeStruct #define ERROR_INSERTED(x) (g_errorInsert == x || m_errorInsert == x) +#define SLEEP_ERROR_INSERTED(x) if(ERROR_INSERTED(x)){NdbSleep_SecSleep(10);} + MgmApiSession::MgmApiSession(class MgmtSrvr & mgm, NDB_SOCKET_TYPE sock, Uint64 session_id) : SocketServer::Session(sock), m_mgmsrv(mgm) { @@ -599,13 +601,23 @@ MgmApiSession::getConfig(Parser_t::Context &, char *tmp_str = (char *) malloc(base64_needed_encoded_length(src.length())); (void) base64_encode(src.get_data(), src.length(), tmp_str); - + + SLEEP_ERROR_INSERTED(1); + m_output->println("get config reply"); m_output->println("result: Ok"); m_output->println("Content-Length: %d", strlen(tmp_str)); m_output->println("Content-Type: ndbconfig/octet-stream"); + SLEEP_ERROR_INSERTED(2); m_output->println("Content-Transfer-Encoding: base64"); m_output->println(""); + if(ERROR_INSERTED(3)) + { + int l= strlen(tmp_str); + tmp_str[l/2]='\0'; + m_output->println(tmp_str); + NdbSleep_SecSleep(10); + } m_output->println(tmp_str); free(tmp_str); @@ -748,6 +760,7 @@ MgmApiSession::endSession(Parser<MgmApiSession>::Context &, m_allocated_resources= new MgmtSrvr::Allocated_resources(m_mgmsrv); + SLEEP_ERROR_INSERTED(1); m_output->println("end session reply"); } @@ -998,12 +1011,16 @@ MgmApiSession::getStatus(Parser<MgmApiSession>::Context &, while(m_mgmsrv.getNextNodeId(&nodeId, NDB_MGM_NODE_TYPE_MGM)){ noOfNodes++; } - + SLEEP_ERROR_INSERTED(1); m_output->println("node status"); + SLEEP_ERROR_INSERTED(2); m_output->println("nodes: %d", noOfNodes); + SLEEP_ERROR_INSERTED(3); printNodeStatus(m_output, m_mgmsrv, NDB_MGM_NODE_TYPE_NDB); printNodeStatus(m_output, m_mgmsrv, NDB_MGM_NODE_TYPE_MGM); + SLEEP_ERROR_INSERTED(4); printNodeStatus(m_output, m_mgmsrv, NDB_MGM_NODE_TYPE_API); + SLEEP_ERROR_INSERTED(5); nodeId = 0; @@ -1118,8 +1135,10 @@ MgmApiSession::enterSingleUser(Parser<MgmApiSession>::Context &, Properties const &args) { int stopped = 0; Uint32 nodeId = 0; + int result= 0; args.get("nodeId", &nodeId); - int result = m_mgmsrv.enterSingleUser(&stopped, nodeId); + + result = m_mgmsrv.enterSingleUser(&stopped, nodeId); m_output->println("enter single user reply"); if(result != 0) { m_output->println("result: %s", get_error_text(result)); @@ -1616,12 +1635,11 @@ void MgmApiSession::check_connection(Parser_t::Context &ctx, const class Properties &args) { - if(ERROR_INSERTED(1)) - { - NdbSleep_SecSleep(10); - } + SLEEP_ERROR_INSERTED(1); m_output->println("check connection reply"); + SLEEP_ERROR_INSERTED(2); m_output->println("result: Ok"); + SLEEP_ERROR_INSERTED(3); m_output->println(""); } @@ -1642,10 +1660,7 @@ MgmApiSession::get_mgmd_nodeid(Parser_t::Context &ctx, { m_output->println("get mgmd nodeid reply"); m_output->println("nodeid:%u",m_mgmsrv.getOwnNodeId()); - if(ERROR_INSERTED(1)) - { - NdbSleep_SecSleep(10); - } + SLEEP_ERROR_INSERTED(1); m_output->println(""); } diff --git a/storage/ndb/test/ndbapi/testMgm.cpp b/storage/ndb/test/ndbapi/testMgm.cpp index 35ad6c73ec159144ef1fc99602b505d009e258ec..5f3147f1d91127a8548bb28e9eb49cf432f8f95d 100644 --- a/storage/ndb/test/ndbapi/testMgm.cpp +++ b/storage/ndb/test/ndbapi/testMgm.cpp @@ -22,6 +22,7 @@ #include <random.h> #include <mgmapi.h> #include <mgmapi_debug.h> +#include <InputStream.hpp> int runLoadTable(NDBT_Context* ctx, NDBT_Step* step){ @@ -191,6 +192,8 @@ int runTestApiSession(NDBT_Context* ctx, NDBT_Step* step) ndb_mgm_set_connectstring(h, mgm); 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; @@ -207,64 +210,278 @@ int runTestApiSession(NDBT_Context* ctx, NDBT_Step* step) } } -int runTestApiTimeout1(NDBT_Context* ctx, NDBT_Step* step) +int runTestApiTimeoutBasic(NDBT_Context* ctx, NDBT_Step* step) { char *mgm= ctx->getRemoteMgm(); 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, mgm); - ndb_mgm_connect(h,0,0,0); - if(ndb_mgm_check_connection(h) < 0) + ndbout << "TEST timout check_connection" << endl; + for(int error_ins=1; error_ins<=3; error_ins++) { - result= NDBT_FAILED; - goto done; + 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; + } } - ndb_mgm_reply reply; - reply.return_code= 0; + ndbout << "TEST get_mgmd_nodeid" << endl; + ndb_mgm_connect(h,0,0,0); - if(ndb_mgm_insert_error(h, 3, 1, &reply)< 0) + if(ndb_mgm_insert_error(h, mgmd_nodeid, 0, &reply)< 0) { - ndbout << "failed to insert error " << endl; + ndbout << "failed to remove inserted 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; - - ndbout << "test 2" << endl; - ndb_mgm_connect(h,0,0,0); - cc= ndb_mgm_get_mgmd_nodeid(h); + ndbout << "got node id: " << cc << endl; if(cc==0) - result= NDBT_OK; - else + { + 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, 3, 0, &reply)< 0) + if(ndb_mgm_insert_error(h, mgmd_nodeid, 1, &reply)< 0) { - ndbout << "failed to remove inserted error " << endl; + ndbout << "FAILED: insert error 1" << endl; result= NDBT_FAILED; goto done; } - cc= ndb_mgm_get_mgmd_nodeid(h); - ndbout << "got node id: " << cc << endl; + 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) +{ + char *mgm= ctx->getRemoteMgm(); + int result= NDBT_OK; + int cc= 0; + int mgmd_nodeid= 0; + + NdbMgmHandle h; + h= ndb_mgm_create_handle(); + ndb_mgm_set_connectstring(h, mgm); + + for(int error_ins=0; error_ins<=5; error_ins++) + { + 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!=5 && cl!=NULL) + { + ndbout << "FAILED: got a ndb_mgm_cluster_state back" << endl; + result= NDBT_FAILED; + } + + if(error_ins!=0 && error_ins!=5 && ndb_mgm_is_connected(h)) + { + ndbout << "FAILED: is still connected after error" << endl; + result= NDBT_FAILED; + } + + if(error_ins!=0 && error_ins!=5 && 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) +{ + char *mgm= ctx->getRemoteMgm(); + int result= NDBT_OK; + int mgmd_nodeid= 0; + + NdbMgmHandle h; + h= ndb_mgm_create_handle(); + ndb_mgm_set_connectstring(h, mgm); + + for(int error_ins=0; error_ins<=3; error_ins++) + { + 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); @@ -272,6 +489,103 @@ int runTestApiTimeout1(NDBT_Context* ctx, NDBT_Step* step) return result; } +int runTestMgmApiEventTimeout(NDBT_Context* ctx, NDBT_Step* step) +{ + char *mgm= ctx->getRemoteMgm(); + int result= NDBT_OK; + int mgmd_nodeid= 0; + + NdbMgmHandle h; + h= ndb_mgm_create_handle(); + ndb_mgm_set_connectstring(h, mgm); + + for(int error_ins=0; error_ins<=3; error_ins++) + { + 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 }; + int fd= ndb_mgm_listen_event(h, filter); + + if(fd==NDB_INVALID_SOCKET) + { + ndbout << "FAILED: could not listen to event" << endl; + result= NDBT_FAILED; + } + + char *tmp= 0; + char buf[512]; + SocketInputStream in(fd,20000); + do { + if((tmp = in.gets(buf, sizeof(buf)))) + { + const char ping_token[]="<PING>"; + if(memcmp(ping_token,tmp,sizeof(ping_token)-1)) + if(tmp && strlen(tmp)) + ndbout << tmp; + } + else + { + if(in.timedout()) + { + ndbout << "TIMED OUT READING EVENT" << endl; + break; + } + } + } while(true); + + 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; +} NDBT_TESTSUITE(testMgm); TESTCASE("SingleUserMode", @@ -284,9 +598,24 @@ TESTCASE("ApiSessionFailure", INITIALIZER(runTestApiSession); } -TESTCASE("ApiTimeout1", - "Test timeout for MGMAPI"){ - INITIALIZER(runTestApiTimeout1); +TESTCASE("ApiTimeoutBasic", + "Basic timeout tests for MGMAPI"){ + INITIALIZER(runTestApiTimeoutBasic); + +} +TESTCASE("ApiGetStatusTimeout", + "Test timeout for MGMAPI getStatus"){ + INITIALIZER(runTestApiGetStatusTimeout); + +} +TESTCASE("ApiGetConfigTimeout", + "Test timeouts for mgmapi get_configuration"){ + INITIALIZER(runTestMgmApiGetConfigTimeout); + +} +TESTCASE("ApiMgmEventTimeout", + "Test timeouts for mgmapi get_configuration"){ + INITIALIZER(runTestMgmApiEventTimeout); } NDBT_TESTSUITE_END(testMgm);