diff --git a/extra/yassl/src/handshake.cpp b/extra/yassl/src/handshake.cpp index 12b62f26e14..66ec64f4af8 100644 --- a/extra/yassl/src/handshake.cpp +++ b/extra/yassl/src/handshake.cpp @@ -880,7 +880,7 @@ int sendData(SSL& ssl, const void* buffer, int sz) ssl.SetError(no_error); ssl.verfiyHandShakeComplete(); - if (ssl.GetError()) return 0; + if (ssl.GetError()) return -1; int sent = 0; for (;;) { @@ -891,7 +891,7 @@ int sendData(SSL& ssl, const void* buffer, int sz) buildMessage(ssl, out, data); ssl.Send(out.get_buffer(), out.get_size()); - if (ssl.GetError()) return 0; + if (ssl.GetError()) return -1; sent += len; if (sent == sz) break; } @@ -918,14 +918,14 @@ int receiveData(SSL& ssl, Data& data) ssl.SetError(no_error); ssl.verfiyHandShakeComplete(); - if (ssl.GetError()) return 0; + if (ssl.GetError()) return -1; if (!ssl.bufferedData()) processReply(ssl); ssl.fillData(data); ssl.useLog().ShowData(data.get_length()); - if (ssl.GetError()) return 0; + if (ssl.GetError()) return -1; if (data.get_length() == 0 && ssl.getSocket().WouldBlock()) { ssl.SetError(YasslError(SSL_ERROR_WANT_READ)); diff --git a/extra/yassl/src/socket_wrapper.cpp b/extra/yassl/src/socket_wrapper.cpp index 803f4b01249..06b403c999d 100644 --- a/extra/yassl/src/socket_wrapper.cpp +++ b/extra/yassl/src/socket_wrapper.cpp @@ -113,13 +113,22 @@ uint Socket::get_ready() const uint Socket::send(const byte* buf, unsigned int sz, int flags) const { + const byte* pos = buf; + const byte* end = pos + sz; + assert(socket_ != INVALID_SOCKET); - int sent = ::send(socket_, reinterpret_cast(buf), sz, flags); + + while (pos != end) { + int sent = ::send(socket_, reinterpret_cast(pos), + static_cast(end - pos), flags); if (sent == -1) return 0; - return sent; + pos += sent; + } + + return sz; } diff --git a/mysql-test/r/ndb_condition_pushdown.result b/mysql-test/r/ndb_condition_pushdown.result index 140324a21d8..2fc1e8f3127 100644 --- a/mysql-test/r/ndb_condition_pushdown.result +++ b/mysql-test/r/ndb_condition_pushdown.result @@ -1842,5 +1842,29 @@ a b select * from t1 where b like 'abc' or b like 'abc'; a b 3 abc +drop table t1; +create table t1 ( fname varchar(255), lname varchar(255) ) +engine=ndbcluster; +insert into t1 values ("Young","Foo"); +set engine_condition_pushdown = 0; +SELECT fname, lname FROM t1 WHERE (fname like 'Y%') or (lname like 'F%'); +fname lname +Young Foo +set engine_condition_pushdown = 1; +SELECT fname, lname FROM t1 WHERE (fname like 'Y%') or (lname like 'F%'); +fname lname +Young Foo +insert into t1 values ("aaa", "aaa"); +insert into t1 values ("bbb", "bbb"); +insert into t1 values ("ccc", "ccc"); +insert into t1 values ("ddd", "ddd"); +set engine_condition_pushdown = 0; +SELECT fname, lname FROM t1 WHERE (fname like 'Y%') or (lname like 'F%'); +fname lname +Young Foo +set engine_condition_pushdown = 1; +SELECT fname, lname FROM t1 WHERE (fname like 'Y%') or (lname like 'F%'); +fname lname +Young Foo set engine_condition_pushdown = @old_ecpd; DROP TABLE t1,t2,t3,t4,t5; diff --git a/mysql-test/r/type_newdecimal.result b/mysql-test/r/type_newdecimal.result index 702b589c911..b15683a0882 100644 --- a/mysql-test/r/type_newdecimal.result +++ b/mysql-test/r/type_newdecimal.result @@ -1397,3 +1397,14 @@ c1 9999999999999999999999999999999999999999999999999999999999999999 9999999999999999999999999999999999999999999999999999999999999999 drop table t1; +create table t1 (i int, j int); +insert into t1 values (1,1), (1,2), (2,3), (2,4); +select i, count(distinct j) from t1 group by i; +i count(distinct j) +1 2 +2 2 +select i+0.0 as i2, count(distinct j) from t1 group by i2; +i2 count(distinct j) +1.0 2 +2.0 2 +drop table t1; diff --git a/mysql-test/r/view_grant.result b/mysql-test/r/view_grant.result index db82016f398..ad6028b8a8c 100644 --- a/mysql-test/r/view_grant.result +++ b/mysql-test/r/view_grant.result @@ -620,3 +620,32 @@ ERROR HY000: There is no 'no-such-user'@'localhost' registered DROP VIEW v; DROP TABLE t1; USE test; +CREATE USER mysqltest_db1@localhost identified by 'PWD'; +GRANT ALL ON mysqltest_db1.* TO mysqltest_db1@localhost WITH GRANT OPTION; +CREATE SCHEMA mysqltest_db1 ; +USE mysqltest_db1 ; +CREATE TABLE t1 (f1 INTEGER); +CREATE VIEW view1 AS +SELECT * FROM t1; +SHOW CREATE VIEW view1; +View Create View +view1 CREATE ALGORITHM=UNDEFINED DEFINER=`mysqltest_db1`@`localhost` SQL SECURITY DEFINER VIEW `view1` AS select `t1`.`f1` AS `f1` from `t1` +CREATE VIEW view2 AS +SELECT * FROM view1; +# Here comes a suspicious warning +SHOW CREATE VIEW view2; +View Create View +view2 CREATE ALGORITHM=UNDEFINED DEFINER=`mysqltest_db1`@`localhost` SQL SECURITY DEFINER VIEW `view2` AS select `view1`.`f1` AS `f1` from `view1` +# But the view view2 is usable +SELECT * FROM view2; +f1 +CREATE VIEW view3 AS +SELECT * FROM view2; +SELECT * from view3; +f1 +DROP VIEW mysqltest_db1.view3; +DROP VIEW mysqltest_db1.view2; +DROP VIEW mysqltest_db1.view1; +DROP TABLE mysqltest_db1.t1; +DROP SCHEMA mysqltest_db1; +DROP USER mysqltest_db1@localhost; diff --git a/mysql-test/t/ndb_condition_pushdown.test b/mysql-test/t/ndb_condition_pushdown.test index 3b53f7b3431..9795c831161 100644 --- a/mysql-test/t/ndb_condition_pushdown.test +++ b/mysql-test/t/ndb_condition_pushdown.test @@ -1686,5 +1686,27 @@ select * from t1 where b like 'ab' or b like 'ab'; select * from t1 where b like 'abc'; select * from t1 where b like 'abc' or b like 'abc'; +# bug#20406 (maybe same as bug#17421 -1, not seen on 32-bit x86) +drop table t1; +create table t1 ( fname varchar(255), lname varchar(255) ) +engine=ndbcluster; +insert into t1 values ("Young","Foo"); + +set engine_condition_pushdown = 0; +SELECT fname, lname FROM t1 WHERE (fname like 'Y%') or (lname like 'F%'); +set engine_condition_pushdown = 1; +SELECT fname, lname FROM t1 WHERE (fname like 'Y%') or (lname like 'F%'); + +# make sure optimizer does not do some crazy shortcut +insert into t1 values ("aaa", "aaa"); +insert into t1 values ("bbb", "bbb"); +insert into t1 values ("ccc", "ccc"); +insert into t1 values ("ddd", "ddd"); + +set engine_condition_pushdown = 0; +SELECT fname, lname FROM t1 WHERE (fname like 'Y%') or (lname like 'F%'); +set engine_condition_pushdown = 1; +SELECT fname, lname FROM t1 WHERE (fname like 'Y%') or (lname like 'F%'); + set engine_condition_pushdown = @old_ecpd; DROP TABLE t1,t2,t3,t4,t5; diff --git a/mysql-test/t/type_newdecimal.test b/mysql-test/t/type_newdecimal.test index 74782a5bddb..35aff8b3c5a 100644 --- a/mysql-test/t/type_newdecimal.test +++ b/mysql-test/t/type_newdecimal.test @@ -1095,3 +1095,12 @@ insert into t1 values( insert into t1 values(1e100); select * from t1; drop table t1; + +# +# Bug#19667 group by a decimal expression yields wrong result +# +create table t1 (i int, j int); +insert into t1 values (1,1), (1,2), (2,3), (2,4); +select i, count(distinct j) from t1 group by i; +select i+0.0 as i2, count(distinct j) from t1 group by i2; +drop table t1; diff --git a/mysql-test/t/view_grant.test b/mysql-test/t/view_grant.test index aa420689149..2a1977702c2 100644 --- a/mysql-test/t/view_grant.test +++ b/mysql-test/t/view_grant.test @@ -813,3 +813,42 @@ SELECT * FROM v; DROP VIEW v; DROP TABLE t1; USE test; + +# +# Bug#20363: Create view on just created view is now denied +# +eval CREATE USER mysqltest_db1@localhost identified by 'PWD'; +eval GRANT ALL ON mysqltest_db1.* TO mysqltest_db1@localhost WITH GRANT OPTION; + +# The session with the non root user is needed. +--replace_result $MASTER_MYPORT MYSQL_PORT $MASTER_MYSOCK MYSQL_SOCK +connect (session1,localhost,mysqltest_db1,PWD,test); + +CREATE SCHEMA mysqltest_db1 ; +USE mysqltest_db1 ; + +CREATE TABLE t1 (f1 INTEGER); + +CREATE VIEW view1 AS +SELECT * FROM t1; +SHOW CREATE VIEW view1; + +CREATE VIEW view2 AS +SELECT * FROM view1; +--echo # Here comes a suspicious warning +SHOW CREATE VIEW view2; +--echo # But the view view2 is usable +SELECT * FROM view2; + +CREATE VIEW view3 AS +SELECT * FROM view2; + +SELECT * from view3; + +connection default; +DROP VIEW mysqltest_db1.view3; +DROP VIEW mysqltest_db1.view2; +DROP VIEW mysqltest_db1.view1; +DROP TABLE mysqltest_db1.t1; +DROP SCHEMA mysqltest_db1; +DROP USER mysqltest_db1@localhost; diff --git a/mysql-test/valgrind.supp b/mysql-test/valgrind.supp index 9061a71364d..dc0f6bf1977 100644 --- a/mysql-test/valgrind.supp +++ b/mysql-test/valgrind.supp @@ -408,6 +408,19 @@ } # +# BUG#19940: NDB sends uninitialized parts of field buffers across the wire. +# This is "works as designed"; the uninitialized part is not used at the +# other end (but Valgrind cannot see this). +# +{ + bug19940 + Memcheck:Param + socketcall.sendto(msg) + fun:send + fun:_ZN15TCP_Transporter6doSendEv + fun:_ZN19TransporterRegistry11performSendEv + fun:_ZN19TransporterRegistry14forceSendCheckEi +} # Warning when printing stack trace (to suppress some not needed warnings) # diff --git a/sql/item_buff.cc b/sql/item_buff.cc index 9db2f465080..1661f04a4ae 100644 --- a/sql/item_buff.cc +++ b/sql/item_buff.cc @@ -132,7 +132,7 @@ bool Cached_item_decimal::cmp() { my_decimal tmp; my_decimal *ptmp= item->val_decimal(&tmp); - if (null_value != item->null_value || my_decimal_cmp(&value, ptmp) == 0) + if (null_value != item->null_value || my_decimal_cmp(&value, ptmp)) { null_value= item->null_value; my_decimal2decimal(ptmp, &value); diff --git a/sql/sql_parse.cc b/sql/sql_parse.cc index 14847a9906d..00aacd7b67b 100644 --- a/sql/sql_parse.cc +++ b/sql/sql_parse.cc @@ -5201,7 +5201,14 @@ bool check_one_table_access(THD *thd, ulong privilege, TABLE_LIST *all_tables) if (all_tables->security_ctx) thd->security_ctx= all_tables->security_ctx; - if (check_access(thd, privilege, all_tables->db, + const char *db_name; + if ((all_tables->view || all_tables->field_translation) && + !all_tables->schema_table) + db_name= all_tables->view_db.str; + else + db_name= all_tables->db; + + if (check_access(thd, privilege, db_name, &all_tables->grant.privilege, 0, 0, test(all_tables->schema_table))) goto deny; diff --git a/sql/sql_table.cc b/sql/sql_table.cc index d379af3b3eb..bf0535567b4 100644 --- a/sql/sql_table.cc +++ b/sql/sql_table.cc @@ -5009,6 +5009,7 @@ bool mysql_alter_table(THD *thd,char *new_db, char *new_name, old_db_type= table->s->db_type; if (!create_info->db_type) { +#ifdef WITH_PARTITION_STORAGE_ENGINE if (table->part_info && create_info->used_fields & HA_CREATE_USED_ENGINE) { @@ -5022,6 +5023,7 @@ bool mysql_alter_table(THD *thd,char *new_db, char *new_name, create_info->db_type= table->part_info->default_engine_type; } else +#endif create_info->db_type= old_db_type; } diff --git a/storage/ndb/include/mgmapi/mgmapi.h b/storage/ndb/include/mgmapi/mgmapi.h index 5a0ffcfe2c6..0785a5dba99 100644 --- a/storage/ndb/include/mgmapi/mgmapi.h +++ b/storage/ndb/include/mgmapi/mgmapi.h @@ -699,6 +699,28 @@ extern "C" { int ndb_mgm_stop2(NdbMgmHandle handle, int no_of_nodes, const int * node_list, int abort); + /** + * Stops cluster nodes + * + * @param handle Management handle. + * @param no_of_nodes Number of database nodes to stop
+ * -1: All database and management nodes
+ * 0: All database nodes in cluster
+ * n: Stop the n node(s) specified in + * the array node_list + * @param node_list List of node IDs of database nodes to be stopped + * @param abort Don't perform graceful stop, + * but rather stop immediately + * @param disconnect Returns true if you need to disconnect to apply + * the stop command (e.g. stopping the mgm server + * that handle is connected to) + * + * @return Number of nodes stopped (-1 on error). + */ + int ndb_mgm_stop3(NdbMgmHandle handle, int no_of_nodes, + const int * node_list, int abort, int *disconnect); + + /** * Restart database nodes * @@ -738,6 +760,31 @@ extern "C" { const int * node_list, int initial, int nostart, int abort); + /** + * Restart nodes + * + * @param handle Management handle. + * @param no_of_nodes Number of database nodes to be restarted:
+ * 0: Restart all database nodes in the cluster
+ * n: Restart the n node(s) specified in the + * array node_list + * @param node_list List of node IDs of database nodes to be restarted + * @param initial Remove filesystem from restarting node(s) + * @param nostart Don't actually start node(s) but leave them + * waiting for start command + * @param abort Don't perform graceful restart, + * but rather restart immediately + * @param disconnect Returns true if mgmapi client must disconnect from + * server to apply the requested operation. (e.g. + * restart the management server) + * + * + * @return Number of nodes stopped (-1 on error). + */ + int ndb_mgm_restart3(NdbMgmHandle handle, int no_of_nodes, + const int * node_list, int initial, + int nostart, int abort, int *disconnect); + /** * Start database nodes * @@ -1018,6 +1065,16 @@ extern "C" { */ Uint32 ndb_mgm_get_mgmd_nodeid(NdbMgmHandle handle); + /** + * Get the version of the mgm server we're talking to. + * Designed to allow switching of protocol depending on version + * so that new clients can speak to old servers in a compat mode + */ + int ndb_mgm_get_version(NdbMgmHandle handle, + int *major, int *minor, int* build, + int len, char* str); + + /** * Config iterator */ diff --git a/storage/ndb/src/mgmapi/mgmapi.cpp b/storage/ndb/src/mgmapi/mgmapi.cpp index 6dfb48667aa..f184f089f2d 100644 --- a/storage/ndb/src/mgmapi/mgmapi.cpp +++ b/storage/ndb/src/mgmapi/mgmapi.cpp @@ -27,6 +27,7 @@ #include #include "mgmapi_configuration.hpp" #include +#include #include #include @@ -103,6 +104,9 @@ struct ndb_mgm_handle { #endif FILE *errstream; char *m_name; + int mgmd_version_major; + int mgmd_version_minor; + int mgmd_version_build; }; #define SET_ERROR(h, e, s) setError(h, e, __LINE__, s) @@ -174,6 +178,10 @@ ndb_mgm_create_handle() h->logfile = 0; #endif + h->mgmd_version_major= -1; + h->mgmd_version_minor= -1; + h->mgmd_version_build= -1; + DBUG_PRINT("info", ("handle=0x%x", (UintPtr)h)); DBUG_RETURN(h); } @@ -367,8 +375,9 @@ ndb_mgm_call(NdbMgmHandle handle, const ParserRow *command_reply, * Print some info about why the parser returns NULL */ fprintf(handle->errstream, - "Error in mgm protocol parser. cmd: >%s< status: %d curr: %d\n", - cmd, (Uint32)ctx.m_status, ctx.m_currentToken); + "Error in mgm protocol parser. cmd: >%s< status: %d curr: %s\n", + cmd, (Uint32)ctx.m_status, + (ctx.m_currentToken)?ctx.m_currentToken:"NULL"); DBUG_PRINT("info",("ctx.status: %d, ctx.m_currentToken: %s", ctx.m_status, ctx.m_currentToken)); } @@ -684,7 +693,11 @@ ndb_mgm_get_status(NdbMgmHandle handle) out.println(""); char buf[1024]; - in.gets(buf, sizeof(buf)); + if(!in.gets(buf, sizeof(buf))) + { + SET_ERROR(handle, NDB_MGM_ILLEGAL_SERVER_REPLY, "Probably disconnected"); + return NULL; + } if(buf[strlen(buf)-1] == '\n') buf[strlen(buf)-1] = '\0'; @@ -693,7 +706,11 @@ ndb_mgm_get_status(NdbMgmHandle handle) return NULL; } - in.gets(buf, sizeof(buf)); + if(!in.gets(buf, sizeof(buf))) + { + SET_ERROR(handle, NDB_MGM_ILLEGAL_SERVER_REPLY, "Probably disconnected"); + return NULL; + } if(buf[strlen(buf)-1] == '\n') buf[strlen(buf)-1] = '\0'; @@ -716,6 +733,13 @@ ndb_mgm_get_status(NdbMgmHandle handle) malloc(sizeof(ndb_mgm_cluster_state)+ noOfNodes*(sizeof(ndb_mgm_node_state)+sizeof("000.000.000.000#"))); + if(!state) + { + SET_ERROR(handle, NDB_MGM_OUT_OF_MEMORY, + "Allocating ndb_mgm_cluster_state"); + return NULL; + } + state->no_of_nodes= noOfNodes; ndb_mgm_node_state * ptr = &state->node_states[0]; int nodeId = 0; @@ -725,7 +749,13 @@ ndb_mgm_get_status(NdbMgmHandle handle) } i = -1; ptr--; for(; i stop_reply[] = { + int disconnect; + return ndb_mgm_stop3(handle, no_of_nodes, node_list, abort, &disconnect); +} + + +extern "C" +int +ndb_mgm_stop3(NdbMgmHandle handle, int no_of_nodes, const int * node_list, + int abort, int *disconnect) +{ + SET_ERROR(handle, NDB_MGM_NO_ERROR, "Executing: ndb_mgm_stop3"); + const ParserRow stop_reply_v1[] = { MGM_CMD("stop reply", NULL, ""), MGM_ARG("stopped", Int, Optional, "No of stopped nodes"), MGM_ARG("result", String, Mandatory, "Error message"), MGM_END() }; + const ParserRow stop_reply_v2[] = { + MGM_CMD("stop reply", NULL, ""), + MGM_ARG("stopped", Int, Optional, "No of stopped nodes"), + MGM_ARG("result", String, Mandatory, "Error message"), + MGM_ARG("disconnect", Int, Mandatory, "Need to disconnect"), + MGM_END() + }; + CHECK_HANDLE(handle, -1); CHECK_CONNECTED(handle, -1); - if(no_of_nodes < 0){ + if(handle->mgmd_version_build==-1) + { + char verstr[50]; + if(!ndb_mgm_get_version(handle, + &(handle->mgmd_version_major), + &(handle->mgmd_version_minor), + &(handle->mgmd_version_build), + sizeof(verstr), + verstr)) + { + return -1; + } + } + int use_v2= ((handle->mgmd_version_major==5) + && ( + (handle->mgmd_version_minor==0 && handle->mgmd_version_build>=21) + ||(handle->mgmd_version_minor==1 && handle->mgmd_version_build>=12) + ||(handle->mgmd_version_minor>1) + ) + ) + || (handle->mgmd_version_major>5); + + if(no_of_nodes < -1){ SET_ERROR(handle, NDB_MGM_ILLEGAL_NUMBER_OF_NODES, "Negative number of nodes requested to stop"); return -1; } Uint32 stoppedNoOfNodes = 0; - if(no_of_nodes == 0){ + if(no_of_nodes <= 0){ /** - * All database nodes should be stopped + * All nodes should be stopped (all or just db) */ Properties args; args.put("abort", abort); + if(use_v2) + args.put("stop", (no_of_nodes==-1)?"mgm,db":"db"); const Properties *reply; - reply = ndb_mgm_call(handle, stop_reply, "stop all", &args); + if(use_v2) + 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); if(!reply->get("stopped", &stoppedNoOfNodes)){ @@ -874,6 +948,10 @@ ndb_mgm_stop2(NdbMgmHandle handle, int no_of_nodes, const int * node_list, delete reply; return -1; } + if(use_v2) + reply->get("disconnect", (Uint32*)disconnect); + else + *disconnect= 0; BaseString result; reply->get("result", result); if(strcmp(result.c_str(), "Ok") != 0) { @@ -899,7 +977,11 @@ ndb_mgm_stop2(NdbMgmHandle handle, int no_of_nodes, const int * node_list, args.put("abort", abort); const Properties *reply; - reply = ndb_mgm_call(handle, stop_reply, "stop", &args); + if(use_v2) + reply = ndb_mgm_call(handle, stop_reply_v2, "stop v2", &args); + else + reply = ndb_mgm_call(handle, stop_reply_v1, "stop", &args); + CHECK_REPLY(reply, stoppedNoOfNodes); if(!reply->get("stopped", &stoppedNoOfNodes)){ SET_ERROR(handle, NDB_MGM_STOP_FAILED, @@ -907,6 +989,10 @@ ndb_mgm_stop2(NdbMgmHandle handle, int no_of_nodes, const int * node_list, delete reply; return -1; } + if(use_v2) + reply->get("disconnect", (Uint32*)disconnect); + else + *disconnect= 0; BaseString result; reply->get("result", result); if(strcmp(result.c_str(), "Ok") != 0) { @@ -918,22 +1004,71 @@ ndb_mgm_stop2(NdbMgmHandle handle, int no_of_nodes, const int * node_list, return stoppedNoOfNodes; } +extern "C" +int +ndb_mgm_restart(NdbMgmHandle handle, int no_of_nodes, const int *node_list) +{ + SET_ERROR(handle, NDB_MGM_NO_ERROR, "Executing: ndb_mgm_restart"); + return ndb_mgm_restart2(handle, no_of_nodes, node_list, 0, 0, 0); +} + extern "C" int ndb_mgm_restart2(NdbMgmHandle handle, int no_of_nodes, const int * node_list, int initial, int nostart, int abort) { - SET_ERROR(handle, NDB_MGM_NO_ERROR, "Executing: ndb_mgm_restart2"); + int disconnect; + + return ndb_mgm_restart3(handle, no_of_nodes, node_list, initial, nostart, + abort, &disconnect); +} + +extern "C" +int +ndb_mgm_restart3(NdbMgmHandle handle, int no_of_nodes, const int * node_list, + int initial, int nostart, int abort, int *disconnect) +{ + SET_ERROR(handle, NDB_MGM_NO_ERROR, "Executing: ndb_mgm_restart3"); Uint32 restarted = 0; - const ParserRow restart_reply[] = { + const ParserRow restart_reply_v1[] = { MGM_CMD("restart reply", NULL, ""), MGM_ARG("result", String, Mandatory, "Error message"), MGM_ARG("restarted", Int, Optional, "No of restarted nodes"), MGM_END() }; + const ParserRow restart_reply_v2[] = { + MGM_CMD("restart reply", NULL, ""), + MGM_ARG("result", String, Mandatory, "Error message"), + MGM_ARG("restarted", Int, Optional, "No of restarted nodes"), + MGM_ARG("disconnect", Int, Optional, "Disconnect to apply"), + MGM_END() + }; + CHECK_HANDLE(handle, -1); CHECK_CONNECTED(handle, -1); - + + if(handle->mgmd_version_build==-1) + { + char verstr[50]; + if(!ndb_mgm_get_version(handle, + &(handle->mgmd_version_major), + &(handle->mgmd_version_minor), + &(handle->mgmd_version_build), + sizeof(verstr), + verstr)) + { + return -1; + } + } + int use_v2= ((handle->mgmd_version_major==5) + && ( + (handle->mgmd_version_minor==0 && handle->mgmd_version_build>=21) + ||(handle->mgmd_version_minor==1 && handle->mgmd_version_build>=12) + ||(handle->mgmd_version_minor>1) + ) + ) + || (handle->mgmd_version_major>5); + if(no_of_nodes < 0){ SET_ERROR(handle, NDB_MGM_RESTART_FAILED, "Restart requested of negative number of nodes"); @@ -948,7 +1083,7 @@ ndb_mgm_restart2(NdbMgmHandle handle, int no_of_nodes, const int * node_list, const Properties *reply; const int timeout = handle->read_timeout; handle->read_timeout= 5*60*1000; // 5 minutes - reply = ndb_mgm_call(handle, restart_reply, "restart all", &args); + reply = ndb_mgm_call(handle, restart_reply_v1, "restart all", &args); handle->read_timeout= timeout; CHECK_REPLY(reply, -1); @@ -984,7 +1119,10 @@ ndb_mgm_restart2(NdbMgmHandle handle, int no_of_nodes, const int * node_list, const Properties *reply; const int timeout = handle->read_timeout; handle->read_timeout= 5*60*1000; // 5 minutes - reply = ndb_mgm_call(handle, restart_reply, "restart node", &args); + if(use_v2) + reply = ndb_mgm_call(handle, restart_reply_v2, "restart node v2", &args); + else + reply = ndb_mgm_call(handle, restart_reply_v1, "restart node", &args); handle->read_timeout= timeout; if(reply != NULL) { BaseString result; @@ -995,20 +1133,16 @@ ndb_mgm_restart2(NdbMgmHandle handle, int no_of_nodes, const int * node_list, return -1; } reply->get("restarted", &restarted); + if(use_v2) + reply->get("disconnect", (Uint32*)disconnect); + else + *disconnect= 0; delete reply; } return restarted; } -extern "C" -int -ndb_mgm_restart(NdbMgmHandle handle, int no_of_nodes, const int *node_list) -{ - SET_ERROR(handle, NDB_MGM_NO_ERROR, "Executing: ndb_mgm_restart"); - return ndb_mgm_restart2(handle, no_of_nodes, node_list, 0, 0, 0); -} - static const char *clusterlog_severity_names[]= { "enabled", "debug", "info", "warning", "error", "critical", "alert" }; @@ -2340,4 +2474,56 @@ int ndb_mgm_end_session(NdbMgmHandle handle) DBUG_RETURN(0); } +extern "C" +int ndb_mgm_get_version(NdbMgmHandle handle, + int *major, int *minor, int *build, int len, char* str) +{ + DBUG_ENTER("ndb_mgm_get_version"); + CHECK_HANDLE(handle, 0); + CHECK_CONNECTED(handle, 0); + + Properties args; + + const ParserRow reply[]= { + MGM_CMD("version", NULL, ""), + MGM_ARG("id", Int, Mandatory, "ID"), + MGM_ARG("major", Int, Mandatory, "Major"), + MGM_ARG("minor", Int, Mandatory, "Minor"), + MGM_ARG("string", String, Mandatory, "String"), + MGM_END() + }; + + const Properties *prop; + prop = ndb_mgm_call(handle, reply, "get version", &args); + CHECK_REPLY(prop, 0); + + Uint32 id; + if(!prop->get("id",&id)){ + fprintf(handle->errstream, "Unable to get value\n"); + return 0; + } + *build= getBuild(id); + + if(!prop->get("major",(Uint32*)major)){ + fprintf(handle->errstream, "Unable to get value\n"); + return 0; + } + + if(!prop->get("minor",(Uint32*)minor)){ + fprintf(handle->errstream, "Unable to get value\n"); + return 0; + } + + BaseString result; + if(!prop->get("string", result)){ + fprintf(handle->errstream, "Unable to get value\n"); + return 0; + } + + strncpy(str, result.c_str(), len); + + delete prop; + DBUG_RETURN(1); +} + template class Vector*>; diff --git a/storage/ndb/src/mgmclient/CommandInterpreter.cpp b/storage/ndb/src/mgmclient/CommandInterpreter.cpp index ccd05abaaa1..c31efebbf1e 100644 --- a/storage/ndb/src/mgmclient/CommandInterpreter.cpp +++ b/storage/ndb/src/mgmclient/CommandInterpreter.cpp @@ -155,6 +155,7 @@ private: NdbMgmHandle m_mgmsrv; NdbMgmHandle m_mgmsrv2; + const char *m_constr; bool m_connected; int m_verbose; int try_reconnect; @@ -335,22 +336,7 @@ convert(const char* s, int& val) { CommandInterpreter::CommandInterpreter(const char *_host,int verbose) : m_verbose(verbose) { - m_mgmsrv = ndb_mgm_create_handle(); - if(m_mgmsrv == NULL) { - ndbout_c("Cannot create handle to management server."); - exit(-1); - } - m_mgmsrv2 = ndb_mgm_create_handle(); - if(m_mgmsrv2 == NULL) { - ndbout_c("Cannot create 2:nd handle to management server."); - exit(-1); - } - if (ndb_mgm_set_connectstring(m_mgmsrv, _host)) - { - printError(); - exit(-1); - } - + m_constr= _host; m_connected= false; m_event_thread= 0; try_reconnect = 0; @@ -362,8 +348,6 @@ CommandInterpreter::CommandInterpreter(const char *_host,int verbose) CommandInterpreter::~CommandInterpreter() { disconnect(); - ndb_mgm_destroy_handle(&m_mgmsrv); - ndb_mgm_destroy_handle(&m_mgmsrv2); } static bool @@ -385,15 +369,14 @@ emptyString(const char* s) void CommandInterpreter::printError() { - if (ndb_mgm_check_connection(m_mgmsrv)) - { - m_connected= false; - disconnect(); - } ndbout_c("* %5d: %s", ndb_mgm_get_latest_error(m_mgmsrv), ndb_mgm_get_latest_error_msg(m_mgmsrv)); ndbout_c("* %s", ndb_mgm_get_latest_error_desc(m_mgmsrv)); + if (ndb_mgm_check_connection(m_mgmsrv)) + { + disconnect(); + } } //***************************************************************************** @@ -437,78 +420,97 @@ event_thread_run(void* m) } bool -CommandInterpreter::connect() +CommandInterpreter::connect() { DBUG_ENTER("CommandInterpreter::connect"); - if(!m_connected) + + if(m_connected) + DBUG_RETURN(m_connected); + + m_mgmsrv = ndb_mgm_create_handle(); + if(m_mgmsrv == NULL) { + ndbout_c("Cannot create handle to management server."); + exit(-1); + } + m_mgmsrv2 = ndb_mgm_create_handle(); + if(m_mgmsrv2 == NULL) { + ndbout_c("Cannot create 2:nd handle to management server."); + exit(-1); + } + + if (ndb_mgm_set_connectstring(m_mgmsrv, m_constr)) { - if(!ndb_mgm_connect(m_mgmsrv, try_reconnect-1, 5, 1)) + printError(); + exit(-1); + } + + if(ndb_mgm_connect(m_mgmsrv, try_reconnect-1, 5, 1)) + DBUG_RETURN(m_connected); // couldn't connect, always false + + const char *host= ndb_mgm_get_connected_host(m_mgmsrv); + unsigned port= ndb_mgm_get_connected_port(m_mgmsrv); + BaseString constr; + constr.assfmt("%s:%d",host,port); + if(!ndb_mgm_set_connectstring(m_mgmsrv2, constr.c_str()) && + !ndb_mgm_connect(m_mgmsrv2, try_reconnect-1, 5, 1)) + { + DBUG_PRINT("info",("2:ndb connected to Management Server ok at: %s:%d", + host, port)); + assert(m_event_thread == 0); + assert(do_event_thread == 0); + do_event_thread= 0; + m_event_thread = NdbThread_Create(event_thread_run, + (void**)&m_mgmsrv2, + 32768, + "CommandInterpreted_event_thread", + NDB_THREAD_PRIO_LOW); + if (m_event_thread != 0) { - const char *host= ndb_mgm_get_connected_host(m_mgmsrv); - unsigned port= ndb_mgm_get_connected_port(m_mgmsrv); - BaseString constr; - constr.assfmt("%s:%d",host,port); - if(!ndb_mgm_set_connectstring(m_mgmsrv2, constr.c_str()) && - !ndb_mgm_connect(m_mgmsrv2, try_reconnect-1, 5, 1)) + DBUG_PRINT("info",("Thread created ok, waiting for started...")); + int iter= 1000; // try for 30 seconds + while(do_event_thread == 0 && + iter-- > 0) + NdbSleep_MilliSleep(30); + } + if (m_event_thread == 0 || + do_event_thread == 0 || + do_event_thread == -1) + { + DBUG_PRINT("info",("Warning, event thread startup failed, " + "degraded printouts as result, errno=%d", + errno)); + printf("Warning, event thread startup failed, " + "degraded printouts as result, errno=%d\n", errno); + do_event_thread= 0; + if (m_event_thread) { - DBUG_PRINT("info",("2:ndb connected to Management Server ok at: %s:%d", - host, port)); - assert(m_event_thread == 0); - assert(do_event_thread == 0); - do_event_thread= 0; - m_event_thread = NdbThread_Create(event_thread_run, - (void**)&m_mgmsrv2, - 32768, - "CommandInterpreted_event_thread", - NDB_THREAD_PRIO_LOW); - if (m_event_thread != 0) - { - DBUG_PRINT("info",("Thread created ok, waiting for started...")); - int iter= 1000; // try for 30 seconds - while(do_event_thread == 0 && - iter-- > 0) - NdbSleep_MilliSleep(30); - } - if (m_event_thread == 0 || - do_event_thread == 0 || - do_event_thread == -1) - { - DBUG_PRINT("info",("Warning, event thread startup failed, " - "degraded printouts as result, errno=%d", - errno)); - printf("Warning, event thread startup failed, " - "degraded printouts as result, errno=%d\n", errno); - do_event_thread= 0; - if (m_event_thread) - { - void *res; - NdbThread_WaitFor(m_event_thread, &res); - NdbThread_Destroy(&m_event_thread); - } - ndb_mgm_disconnect(m_mgmsrv2); - } - } - else - { - DBUG_PRINT("warning", - ("Could not do 2:nd connect to mgmtserver for event listening")); - DBUG_PRINT("info", ("code: %d, msg: %s", - ndb_mgm_get_latest_error(m_mgmsrv2), - ndb_mgm_get_latest_error_msg(m_mgmsrv2))); - printf("Warning, event connect failed, degraded printouts as result\n"); - printf("code: %d, msg: %s\n", - ndb_mgm_get_latest_error(m_mgmsrv2), - ndb_mgm_get_latest_error_msg(m_mgmsrv2)); - } - m_connected= true; - DBUG_PRINT("info",("Connected to Management Server at: %s:%d", host, port)); - if (m_verbose) - { - printf("Connected to Management Server at: %s:%d\n", - host, port); + void *res; + NdbThread_WaitFor(m_event_thread, &res); + NdbThread_Destroy(&m_event_thread); } + ndb_mgm_disconnect(m_mgmsrv2); } } + else + { + DBUG_PRINT("warning", + ("Could not do 2:nd connect to mgmtserver for event listening")); + DBUG_PRINT("info", ("code: %d, msg: %s", + ndb_mgm_get_latest_error(m_mgmsrv2), + ndb_mgm_get_latest_error_msg(m_mgmsrv2))); + printf("Warning, event connect failed, degraded printouts as result\n"); + printf("code: %d, msg: %s\n", + ndb_mgm_get_latest_error(m_mgmsrv2), + ndb_mgm_get_latest_error_msg(m_mgmsrv2)); + } + m_connected= true; + DBUG_PRINT("info",("Connected to Management Server at: %s:%d", host, port)); + if (m_verbose) + { + printf("Connected to Management Server at: %s:%d\n", + host, port); + } + DBUG_RETURN(m_connected); } @@ -516,20 +518,18 @@ bool CommandInterpreter::disconnect() { DBUG_ENTER("CommandInterpreter::disconnect"); + if (m_event_thread) { void *res; do_event_thread= 0; NdbThread_WaitFor(m_event_thread, &res); NdbThread_Destroy(&m_event_thread); m_event_thread= 0; - ndb_mgm_disconnect(m_mgmsrv2); + ndb_mgm_destroy_handle(&m_mgmsrv2); } if (m_connected) { - if (ndb_mgm_disconnect(m_mgmsrv) == -1) { - ndbout_c("Could not disconnect from management server"); - printError(); - } + ndb_mgm_destroy_handle(&m_mgmsrv); m_connected= false; } DBUG_RETURN(true); @@ -985,7 +985,8 @@ CommandInterpreter::executeShutdown(char* parameters) NdbAutoPtr ap1((char*)state); int result = 0; - result = ndb_mgm_stop(m_mgmsrv, 0, 0); + int need_disconnect; + result = ndb_mgm_stop3(m_mgmsrv, -1, 0, 0, &need_disconnect); if (result < 0) { ndbout << "Shutdown of NDB Cluster node(s) failed." << endl; printError(); @@ -994,28 +995,11 @@ CommandInterpreter::executeShutdown(char* parameters) ndbout << result << " NDB Cluster node(s) have shutdown." << endl; - int mgm_id= 0; - mgm_id= ndb_mgm_get_mgmd_nodeid(m_mgmsrv); - if (mgm_id == 0) - { - ndbout << "Unable to locate management server, " - << "shutdown manually with STOP" + if(need_disconnect) { + ndbout << "Disconnecting to allow management server to shutdown." << endl; - return 1; + disconnect(); } - - result = ndb_mgm_stop(m_mgmsrv, 1, &mgm_id); - if (result <= 0) { - ndbout << "Shutdown of NDB Cluster management server failed." << endl; - printError(); - if (result == 0) - return 1; - return result; - } - - m_connected= false; - disconnect(); - ndbout << "NDB Cluster management server shutdown." << endl; return 0; } @@ -1237,12 +1221,7 @@ CommandInterpreter::executeConnect(char* parameters) { disconnect(); if (!emptyString(parameters)) { - if (ndb_mgm_set_connectstring(m_mgmsrv, - BaseString(parameters).trim().c_str())) - { - printError(); - return; - } + m_constr= BaseString(parameters).trim().c_str(); } connect(); } @@ -1407,6 +1386,7 @@ CommandInterpreter::executeStop(Vector &command_list, unsigned command_pos, int *node_ids, int no_of_nodes) { + int need_disconnect; int abort= 0; for (; command_pos < command_list.size(); command_pos++) { @@ -1421,7 +1401,8 @@ CommandInterpreter::executeStop(Vector &command_list, return; } - int result= ndb_mgm_stop2(m_mgmsrv, no_of_nodes, node_ids, abort); + int result= ndb_mgm_stop3(m_mgmsrv, no_of_nodes, node_ids, abort, + &need_disconnect); if (result < 0) { ndbout_c("Shutdown failed."); @@ -1435,10 +1416,17 @@ CommandInterpreter::executeStop(Vector &command_list, { ndbout << "Node"; for (int i= 0; i < no_of_nodes; i++) - ndbout << " " << node_ids[i]; + ndbout << " " << node_ids[i]; ndbout_c(" has shutdown."); } } + + if(need_disconnect) + { + ndbout << "Disconnecting to allow Management Server to shutdown" << endl; + disconnect(); + } + } void @@ -1529,6 +1517,7 @@ CommandInterpreter::executeRestart(Vector &command_list, int nostart= 0; int initialstart= 0; int abort= 0; + int need_disconnect= 0; for (; command_pos < command_list.size(); command_pos++) { @@ -1553,9 +1542,9 @@ CommandInterpreter::executeRestart(Vector &command_list, return; } - result= ndb_mgm_restart2(m_mgmsrv, no_of_nodes, node_ids, - initialstart, nostart, abort); - + result= ndb_mgm_restart3(m_mgmsrv, no_of_nodes, node_ids, + initialstart, nostart, abort, &need_disconnect); + if (result <= 0) { ndbout_c("Restart failed."); printError(); @@ -1571,6 +1560,8 @@ CommandInterpreter::executeRestart(Vector &command_list, ndbout << " " << node_ids[i]; ndbout_c(" is being restarted"); } + if(need_disconnect) + disconnect(); } } diff --git a/storage/ndb/src/mgmsrv/MgmtSrvr.cpp b/storage/ndb/src/mgmsrv/MgmtSrvr.cpp index 3e92a892ddc..511536d2fdd 100644 --- a/storage/ndb/src/mgmsrv/MgmtSrvr.cpp +++ b/storage/ndb/src/mgmsrv/MgmtSrvr.cpp @@ -60,9 +60,6 @@ #include -extern bool g_StopServer; -extern bool g_RestartServer; - //#define MGM_SRV_DEBUG #ifdef MGM_SRV_DEBUG #define DEBUG(x) do ndbout << x << endl; while(0) @@ -937,6 +934,13 @@ int MgmtSrvr::sendStopMgmd(NodeId nodeId, * client connection to that mgmd and stop it that way. * This allows us to stop mgm servers when there isn't any real * distributed communication up. + * + * node_ids.size()==0 means to stop all DB nodes. + * MGM nodes will *NOT* be stopped. + * + * If we work out we should be stopping or restarting ourselves, + * we return <0 in stopSelf for restart, >0 for stop + * and 0 for do nothing. */ int MgmtSrvr::sendSTOP_REQ(const Vector &node_ids, @@ -946,7 +950,8 @@ int MgmtSrvr::sendSTOP_REQ(const Vector &node_ids, bool stop, bool restart, bool nostart, - bool initialStart) + bool initialStart, + int* stopSelf) { int error = 0; DBUG_ENTER("MgmtSrvr::sendSTOP_REQ"); @@ -995,12 +1000,13 @@ int MgmtSrvr::sendSTOP_REQ(const Vector &node_ids, NodeId nodeId= 0; int use_master_node= 0; int do_send= 0; - int do_stop_self= 0; + *stopSelf= 0; NdbNodeBitmask nodes_to_stop; { for (unsigned i= 0; i < node_ids.size(); i++) { nodeId= node_ids[i]; + ndbout << "asked to stop " << nodeId << endl; if (getNodeType(nodeId) != NDB_MGM_NODE_TYPE_MGM) nodes_to_stop.set(nodeId); else if (nodeId != getOwnNodeId()) @@ -1011,7 +1017,11 @@ int MgmtSrvr::sendSTOP_REQ(const Vector &node_ids, stoppedNodes.set(nodeId); } else - do_stop_self= 1;; + { + ndbout << "which is me" << endl; + *stopSelf= (restart)? -1 : 1; + stoppedNodes.set(nodeId); + } } } int no_of_nodes_to_stop= nodes_to_stop.count(); @@ -1044,14 +1054,6 @@ int MgmtSrvr::sendSTOP_REQ(const Vector &node_ids, nodes.set(nodeId); } } - nodeId= 0; - while(getNextNodeId(&nodeId, NDB_MGM_NODE_TYPE_MGM)) - { - if(nodeId==getOwnNodeId()) - continue; - if(sendStopMgmd(nodeId, abort, stop, restart, nostart, initialStart)==0) - stoppedNodes.set(nodeId); - } } // now wait for the replies @@ -1143,11 +1145,9 @@ int MgmtSrvr::sendSTOP_REQ(const Vector &node_ids, DBUG_RETURN(SEND_OR_RECEIVE_FAILED); } } - if (!error && do_stop_self) + if (error && *stopSelf) { - if (restart) - g_RestartServer= true; - g_StopServer= true; + *stopSelf= 0; } DBUG_RETURN(error); } @@ -1157,7 +1157,7 @@ int MgmtSrvr::sendSTOP_REQ(const Vector &node_ids, */ int MgmtSrvr::stopNodes(const Vector &node_ids, - int *stopCount, bool abort) + int *stopCount, bool abort, int* stopSelf) { if (!abort) { @@ -1179,20 +1179,46 @@ int MgmtSrvr::stopNodes(const Vector &node_ids, false, false, false, - false); + false, + stopSelf); if (stopCount) *stopCount= nodes.count(); return ret; } +int MgmtSrvr::shutdownMGM(int *stopCount, bool abort, int *stopSelf) +{ + NodeId nodeId = 0; + int error; + + while(getNextNodeId(&nodeId, NDB_MGM_NODE_TYPE_MGM)) + { + if(nodeId==getOwnNodeId()) + continue; + error= sendStopMgmd(nodeId, abort, true, false, + false, false); + if (error == 0) + *stopCount++; + } + + *stopSelf= 1; + *stopCount++; + + return 0; +} + /* - * Perform system shutdown + * Perform DB nodes shutdown. + * MGM servers are left in their current state */ -int MgmtSrvr::stop(int * stopCount, bool abort) +int MgmtSrvr::shutdownDB(int * stopCount, bool abort) { NodeBitmask nodes; Vector node_ids; + + int tmp; + int ret = sendSTOP_REQ(node_ids, nodes, 0, @@ -1200,7 +1226,8 @@ int MgmtSrvr::stop(int * stopCount, bool abort) true, false, false, - false); + false, + &tmp); if (stopCount) *stopCount = nodes.count(); return ret; @@ -1225,6 +1252,7 @@ int MgmtSrvr::enterSingleUser(int * stopCount, Uint32 singleUserNodeId) } NodeBitmask nodes; Vector node_ids; + int stopSelf; int ret = sendSTOP_REQ(node_ids, nodes, singleUserNodeId, @@ -1232,7 +1260,8 @@ int MgmtSrvr::enterSingleUser(int * stopCount, Uint32 singleUserNodeId) false, false, false, - false); + false, + &stopSelf); if (stopCount) *stopCount = nodes.count(); return ret; @@ -1244,7 +1273,8 @@ int MgmtSrvr::enterSingleUser(int * stopCount, Uint32 singleUserNodeId) int MgmtSrvr::restartNodes(const Vector &node_ids, int * stopCount, bool nostart, - bool initialStart, bool abort) + bool initialStart, bool abort, + int *stopSelf) { NodeBitmask nodes; int ret= sendSTOP_REQ(node_ids, @@ -1254,7 +1284,8 @@ int MgmtSrvr::restartNodes(const Vector &node_ids, false, true, true, - initialStart); + initialStart, + stopSelf); if (ret) return ret; @@ -1297,14 +1328,16 @@ int MgmtSrvr::restartNodes(const Vector &node_ids, } /* - * Perform system restart + * Perform restart of all DB nodes */ -int MgmtSrvr::restart(bool nostart, bool initialStart, - bool abort, int * stopCount ) +int MgmtSrvr::restartDB(bool nostart, bool initialStart, + bool abort, int * stopCount) { NodeBitmask nodes; Vector node_ids; + int tmp; + int ret = sendSTOP_REQ(node_ids, nodes, 0, @@ -1312,7 +1345,8 @@ int MgmtSrvr::restart(bool nostart, bool initialStart, true, true, true, - initialStart); + initialStart, + &tmp); if (ret) return ret; diff --git a/storage/ndb/src/mgmsrv/MgmtSrvr.hpp b/storage/ndb/src/mgmsrv/MgmtSrvr.hpp index 80eef3b1af2..a00ba2cda12 100644 --- a/storage/ndb/src/mgmsrv/MgmtSrvr.hpp +++ b/storage/ndb/src/mgmsrv/MgmtSrvr.hpp @@ -255,12 +255,15 @@ public: * @param processId: Id of the DB process to stop * @return 0 if succeeded, otherwise: as stated above, plus: */ - int stopNodes(const Vector &node_ids, int *stopCount, bool abort); + int stopNodes(const Vector &node_ids, int *stopCount, bool abort, + int *stopSelf); + + int shutdownMGM(int *stopCount, bool abort, int *stopSelf); /** - * Stop the system + * shutdown the DB nodes */ - int stop(int * cnt = 0, bool abort = false); + int shutdownDB(int * cnt = 0, bool abort = false); /** * print version info about a node @@ -294,14 +297,14 @@ public: */ int restartNodes(const Vector &node_ids, int *stopCount, bool nostart, - bool initialStart, bool abort); + bool initialStart, bool abort, int *stopSelf); /** - * Restart the system + * Restart all DB nodes */ - int restart(bool nostart, bool initialStart, - bool abort = false, - int * stopCount = 0); + int restartDB(bool nostart, bool initialStart, + bool abort = false, + int * stopCount = 0); struct BackupEvent { enum Event { @@ -500,7 +503,8 @@ private: bool stop, bool restart, bool nostart, - bool initialStart); + bool initialStart, + int *stopSelf); /** * Check if it is possible to send a signal to a (DB) process diff --git a/storage/ndb/src/mgmsrv/Services.cpp b/storage/ndb/src/mgmsrv/Services.cpp index beec5a819b7..cc7892f8b36 100644 --- a/storage/ndb/src/mgmsrv/Services.cpp +++ b/storage/ndb/src/mgmsrv/Services.cpp @@ -35,6 +35,7 @@ #include extern bool g_StopServer; +extern bool g_RestartServer; extern EventLogger g_eventLogger; static const unsigned int MAX_READ_TIMEOUT = 1000 ; @@ -144,7 +145,13 @@ ParserRow commands[] = { MGM_CMD("get info clusterlog", &MgmApiSession::getInfoClusterLog, ""), - MGM_CMD("restart node", &MgmApiSession::restart, ""), + MGM_CMD("restart node", &MgmApiSession::restart_v1, ""), + MGM_ARG("node", String, Mandatory, "Nodes to restart"), + MGM_ARG("initialstart", Int, Optional, "Initial start"), + MGM_ARG("nostart", Int, Optional, "No start"), + MGM_ARG("abort", Int, Optional, "Abort"), + + MGM_CMD("restart node v2", &MgmApiSession::restart_v2, ""), MGM_ARG("node", String, Mandatory, "Nodes to restart"), MGM_ARG("initialstart", Int, Optional, "Initial start"), MGM_ARG("nostart", Int, Optional, "No start"), @@ -185,13 +192,18 @@ ParserRow commands[] = { MGM_CMD("abort backup", &MgmApiSession::abortBackup, ""), MGM_ARG("id", Int, Mandatory, "Backup id"), - MGM_CMD("stop", &MgmApiSession::stop, ""), + MGM_CMD("stop", &MgmApiSession::stop_v1, ""), + MGM_ARG("node", String, Mandatory, "Node"), + MGM_ARG("abort", Int, Mandatory, "Node"), + + MGM_CMD("stop v2", &MgmApiSession::stop_v2, ""), MGM_ARG("node", String, Mandatory, "Node"), MGM_ARG("abort", Int, Mandatory, "Node"), MGM_CMD("stop all", &MgmApiSession::stopAll, ""), MGM_ARG("abort", Int, Mandatory, "Node"), - + MGM_ARG("stop", String, Optional, "MGM/DB or both"), + MGM_CMD("enter single user", &MgmApiSession::enterSingleUser, ""), MGM_ARG("nodeId", Int, Mandatory, "Node"), @@ -276,6 +288,7 @@ MgmApiSession::MgmApiSession(class MgmtSrvr & mgm, NDB_SOCKET_TYPE sock) m_output = new SocketOutputStream(sock); m_parser = new Parser_t(commands, *m_input, true, true, true); m_allocated_resources= new MgmtSrvr::Allocated_resources(m_mgmsrv); + m_stopSelf= 0; DBUG_VOID_RETURN; } @@ -295,6 +308,10 @@ MgmApiSession::~MgmApiSession() NDB_CLOSE_SOCKET(m_socket); m_socket= NDB_INVALID_SOCKET; } + if(m_stopSelf < 0) + g_RestartServer= true; + if(m_stopSelf) + g_StopServer= true; DBUG_VOID_RETURN; } @@ -875,8 +892,19 @@ MgmApiSession::stopSignalLog(Parser::Context &, } void -MgmApiSession::restart(Parser::Context &, +MgmApiSession::restart_v1(Parser::Context &, Properties const &args) { + restart(args,1); +} + +void +MgmApiSession::restart_v2(Parser::Context &, + Properties const &args) { + restart(args,2); +} + +void +MgmApiSession::restart(Properties const &args, int version) { Uint32 nostart = 0, initialstart = 0, @@ -901,7 +929,8 @@ MgmApiSession::restart(Parser::Context &, &restarted, nostart != 0, initialstart != 0, - abort != 0); + abort != 0, + &m_stopSelf); m_output->println("restart reply"); if(result != 0){ @@ -909,6 +938,8 @@ MgmApiSession::restart(Parser::Context &, } else m_output->println("result: Ok"); m_output->println("restarted: %d", restarted); + if(version>1) + m_output->println("disconnect: %d", (m_stopSelf)?1:0); m_output->println(""); } @@ -925,7 +956,7 @@ MgmApiSession::restartAll(Parser::Context &, args.get("nostart", &nostart); int count = 0; - int result = m_mgmsrv.restart(nostart, initialstart, abort, &count); + int result = m_mgmsrv.restartDB(nostart, initialstart, abort, &count); m_output->println("restart reply"); if(result != 0) @@ -1018,8 +1049,19 @@ MgmApiSession::getInfoClusterLog(Parser::Context &, } void -MgmApiSession::stop(Parser::Context &, - Properties const &args) { +MgmApiSession::stop_v1(Parser::Context &, + Properties const &args) { + stop(args,1); +} + +void +MgmApiSession::stop_v2(Parser::Context &, + Properties const &args) { + stop(args,2); +} + +void +MgmApiSession::stop(Properties const &args, int version) { Uint32 abort; char *nodes_str; Vector nodes; @@ -1044,7 +1086,7 @@ MgmApiSession::stop(Parser::Context &, int stopped= 0; int result= 0; if (nodes.size()) - result= m_mgmsrv.stopNodes(nodes, &stopped, abort != 0); + result= m_mgmsrv.stopNodes(nodes, &stopped, abort != 0, &m_stopSelf); m_output->println("stop reply"); if(result != 0) @@ -1052,25 +1094,41 @@ MgmApiSession::stop(Parser::Context &, else m_output->println("result: Ok"); m_output->println("stopped: %d", stopped); + if(version>1) + m_output->println("disconnect: %d", (m_stopSelf)?1:0); m_output->println(""); } - void MgmApiSession::stopAll(Parser::Context &, - Properties const &args) { - int stopped = 0; + Properties const &args) { + int stopped[2] = {0,0}; Uint32 abort; args.get("abort", &abort); - int result = m_mgmsrv.stop(&stopped, abort != 0); + BaseString stop; + const char* tostop= "db"; + int ver=1; + if (args.get("stop", stop)) + { + tostop= stop.c_str(); + ver= 2; + } + + int result= 0; + if(strstr(tostop,"db")) + result= m_mgmsrv.shutdownDB(&stopped[0], abort != 0); + if(!result && strstr(tostop,"mgm")) + result= m_mgmsrv.shutdownMGM(&stopped[1], abort!=0, &m_stopSelf); m_output->println("stop reply"); if(result != 0) m_output->println("result: %s", get_error_text(result)); else m_output->println("result: Ok"); - m_output->println("stopped: %d", stopped); + m_output->println("stopped: %d", stopped[0]+stopped[1]); + if(ver >1) + m_output->println("disconnect: %d", (m_stopSelf)?1:0); m_output->println(""); } diff --git a/storage/ndb/src/mgmsrv/Services.hpp b/storage/ndb/src/mgmsrv/Services.hpp index abe0233cb33..d0a61b3f91d 100644 --- a/storage/ndb/src/mgmsrv/Services.hpp +++ b/storage/ndb/src/mgmsrv/Services.hpp @@ -41,6 +41,7 @@ private: Parser_t *m_parser; MgmtSrvr::Allocated_resources *m_allocated_resources; char m_err_str[1024]; + int m_stopSelf; // -1 is restart, 0 do nothing, 1 stop void getConfig_common(Parser_t::Context &ctx, const class Properties &args, @@ -62,7 +63,9 @@ public: void getVersion(Parser_t::Context &ctx, const class Properties &args); void getStatus(Parser_t::Context &ctx, const class Properties &args); void getInfoClusterLog(Parser_t::Context &ctx, const class Properties &args); - void restart(Parser_t::Context &ctx, const class Properties &args); + void restart(const class Properties &args, int version); + void restart_v1(Parser_t::Context &ctx, const class Properties &args); + void restart_v2(Parser_t::Context &ctx, const class Properties &args); void restartAll(Parser_t::Context &ctx, const class Properties &args); void insertError(Parser_t::Context &ctx, const class Properties &args); void setTrace(Parser_t::Context &ctx, const class Properties &args); @@ -74,7 +77,9 @@ public: void abortBackup(Parser_t::Context &ctx, const class Properties &args); void enterSingleUser(Parser_t::Context &ctx, const class Properties &args); void exitSingleUser(Parser_t::Context &ctx, const class Properties &args); - void stop(Parser_t::Context &ctx, const class Properties &args); + void stop_v1(Parser_t::Context &ctx, const class Properties &args); + void stop_v2(Parser_t::Context &ctx, const class Properties &args); + void stop(const class Properties &args, int version); void stopAll(Parser_t::Context &ctx, const class Properties &args); void start(Parser_t::Context &ctx, const class Properties &args); void startAll(Parser_t::Context &ctx, const class Properties &args); diff --git a/win/build-vs71.bat b/win/build-vs71.bat index 46f3bc32f6e..959067695c5 100644 --- a/win/build-vs71.bat +++ b/win/build-vs71.bat @@ -1,6 +1,6 @@ @echo off -del cmakecache.txt +if exist cmakecache.txt del cmakecache.txt copy win\vs71cache.txt cmakecache.txt cmake -G "Visual Studio 7 .NET 2003" copy cmakecache.txt win\vs71cache.txt diff --git a/win/build-vs8.bat b/win/build-vs8.bat index 349c3e78628..d9c06241a9b 100644 --- a/win/build-vs8.bat +++ b/win/build-vs8.bat @@ -1,6 +1,6 @@ @echo off -del cmakecache.txt +if exist cmakecache.txt del cmakecache.txt copy win\vs8cache.txt cmakecache.txt cmake -G "Visual Studio 8 2005" copy cmakecache.txt win\vs8cache.txt