00001 /* Copyright (C) 2003 MySQL AB 00002 00003 This program is free software; you can redistribute it and/or modify 00004 it under the terms of the GNU General Public License as published by 00005 the Free Software Foundation; either version 2 of the License, or 00006 (at your option) any later version. 00007 00008 This program is distributed in the hope that it will be useful, 00009 but WITHOUT ANY WARRANTY; without even the implied warranty of 00010 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00011 GNU General Public License for more details. 00012 00013 You should have received a copy of the GNU General Public License 00014 along with this program; if not, write to the Free Software 00015 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ 00016 00017 #include <ndb_global.h> 00018 #include <my_sys.h> 00019 00020 #include <LocalConfig.hpp> 00021 #include <NdbAutoPtr.hpp> 00022 00023 #include <NdbSleep.h> 00024 #include <NdbTCP.h> 00025 #include <mgmapi.h> 00026 #include <mgmapi_internal.h> 00027 #include <mgmapi_debug.h> 00028 #include "mgmapi_configuration.hpp" 00029 #include <socket_io.h> 00030 #include <version.h> 00031 00032 #include <NdbOut.hpp> 00033 #include <SocketServer.hpp> 00034 #include <SocketClient.hpp> 00035 #include <Parser.hpp> 00036 #include <OutputStream.hpp> 00037 #include <InputStream.hpp> 00038 00039 #include <base64.h> 00040 00041 #define MGM_CMD(name, fun, desc) \ 00042 { name, \ 00043 0, \ 00044 ParserRow<ParserDummy>::Cmd, \ 00045 ParserRow<ParserDummy>::String, \ 00046 ParserRow<ParserDummy>::Optional, \ 00047 ParserRow<ParserDummy>::IgnoreMinMax, \ 00048 0, 0, \ 00049 fun, \ 00050 desc, 0 } 00051 00052 #define MGM_ARG(name, type, opt, desc) \ 00053 { name, \ 00054 0, \ 00055 ParserRow<ParserDummy>::Arg, \ 00056 ParserRow<ParserDummy>::type, \ 00057 ParserRow<ParserDummy>::opt, \ 00058 ParserRow<ParserDummy>::IgnoreMinMax, \ 00059 0, 0, \ 00060 0, \ 00061 desc, 0 } 00062 00063 #define MGM_END() \ 00064 { 0, \ 00065 0, \ 00066 ParserRow<ParserDummy>::Arg, \ 00067 ParserRow<ParserDummy>::Int, \ 00068 ParserRow<ParserDummy>::Optional, \ 00069 ParserRow<ParserDummy>::IgnoreMinMax, \ 00070 0, 0, \ 00071 0, \ 00072 0, 0 } 00073 00074 class ParserDummy : private SocketServer::Session 00075 { 00076 public: 00077 ParserDummy(NDB_SOCKET_TYPE sock); 00078 }; 00079 00080 ParserDummy::ParserDummy(NDB_SOCKET_TYPE sock) : SocketServer::Session(sock) 00081 { 00082 } 00083 00084 typedef Parser<ParserDummy> Parser_t; 00085 00086 #define NDB_MGM_MAX_ERR_DESC_SIZE 256 00087 00088 struct ndb_mgm_handle { 00089 int cfg_i; 00090 00091 int connected; 00092 int last_error; 00093 int last_error_line; 00094 char last_error_desc[NDB_MGM_MAX_ERR_DESC_SIZE]; 00095 int read_timeout; 00096 int write_timeout; 00097 00098 NDB_SOCKET_TYPE socket; 00099 00100 LocalConfig cfg; 00101 00102 #ifdef MGMAPI_LOG 00103 FILE* logfile; 00104 #endif 00105 FILE *errstream; 00106 char *m_name; 00107 int mgmd_version_major; 00108 int mgmd_version_minor; 00109 int mgmd_version_build; 00110 }; 00111 00112 #define SET_ERROR(h, e, s) setError(h, e, __LINE__, s) 00113 00114 static 00115 void 00116 setError(NdbMgmHandle h, int error, int error_line, const char * msg, ...){ 00117 00118 h->last_error = error; \ 00119 h->last_error_line = error_line; 00120 00121 va_list ap; 00122 va_start(ap, msg); 00123 BaseString::vsnprintf(h->last_error_desc, sizeof(h->last_error_desc), msg, ap); 00124 va_end(ap); 00125 } 00126 00127 #define CHECK_HANDLE(handle, ret) \ 00128 if(handle == 0) { \ 00129 SET_ERROR(handle, NDB_MGM_ILLEGAL_SERVER_HANDLE, ""); \ 00130 return ret; \ 00131 } 00132 00133 #define CHECK_CONNECTED(handle, ret) \ 00134 if (handle->connected != 1) { \ 00135 SET_ERROR(handle, NDB_MGM_SERVER_NOT_CONNECTED , ""); \ 00136 return ret; \ 00137 } 00138 00139 #define CHECK_REPLY(reply, ret) \ 00140 if(reply == NULL) { \ 00141 SET_ERROR(handle, NDB_MGM_ILLEGAL_SERVER_REPLY, ""); \ 00142 return ret; \ 00143 } 00144 00145 #define DBUG_CHECK_REPLY(reply, ret) \ 00146 if (reply == NULL) { \ 00147 SET_ERROR(handle, NDB_MGM_ILLEGAL_SERVER_REPLY, ""); \ 00148 DBUG_RETURN(ret); \ 00149 } 00150 00151 /***************************************************************************** 00152 * Handles 00153 *****************************************************************************/ 00154 00155 extern "C" 00156 NdbMgmHandle 00157 ndb_mgm_create_handle() 00158 { 00159 DBUG_ENTER("ndb_mgm_create_handle"); 00160 NdbMgmHandle h = 00161 (NdbMgmHandle)my_malloc(sizeof(ndb_mgm_handle),MYF(MY_WME)); 00162 h->connected = 0; 00163 h->last_error = 0; 00164 h->last_error_line = 0; 00165 h->socket = NDB_INVALID_SOCKET; 00166 h->read_timeout = 50000; 00167 h->write_timeout = 100; 00168 h->cfg_i = -1; 00169 h->errstream = stdout; 00170 h->m_name = 0; 00171 00172 strncpy(h->last_error_desc, "No error", NDB_MGM_MAX_ERR_DESC_SIZE); 00173 00174 new (&(h->cfg)) LocalConfig; 00175 h->cfg.init(0, 0); 00176 00177 #ifdef MGMAPI_LOG 00178 h->logfile = 0; 00179 #endif 00180 00181 h->mgmd_version_major= -1; 00182 h->mgmd_version_minor= -1; 00183 h->mgmd_version_build= -1; 00184 00185 DBUG_PRINT("info", ("handle=0x%x", (UintPtr)h)); 00186 DBUG_RETURN(h); 00187 } 00188 00189 extern "C" 00190 void 00191 ndb_mgm_set_name(NdbMgmHandle handle, const char *name) 00192 { 00193 my_free(handle->m_name, MYF(MY_ALLOW_ZERO_PTR)); 00194 handle->m_name= my_strdup(name, MYF(MY_WME)); 00195 } 00196 00197 extern "C" 00198 int 00199 ndb_mgm_set_connectstring(NdbMgmHandle handle, const char * mgmsrv) 00200 { 00201 DBUG_ENTER("ndb_mgm_set_connectstring"); 00202 DBUG_PRINT("info", ("handle=0x%x", (UintPtr)handle)); 00203 handle->cfg.~LocalConfig(); 00204 new (&(handle->cfg)) LocalConfig; 00205 if (!handle->cfg.init(mgmsrv, 0) || 00206 handle->cfg.ids.size() == 0) 00207 { 00208 handle->cfg.~LocalConfig(); 00209 new (&(handle->cfg)) LocalConfig; 00210 handle->cfg.init(0, 0); /* reset the LocalConfig */ 00211 SET_ERROR(handle, NDB_MGM_ILLEGAL_CONNECT_STRING, mgmsrv ? mgmsrv : ""); 00212 DBUG_RETURN(-1); 00213 } 00214 handle->cfg_i= -1; 00215 DBUG_RETURN(0); 00216 } 00217 00221 extern "C" 00222 void 00223 ndb_mgm_destroy_handle(NdbMgmHandle * handle) 00224 { 00225 DBUG_ENTER("ndb_mgm_destroy_handle"); 00226 if(!handle) 00227 DBUG_VOID_RETURN; 00228 DBUG_PRINT("info", ("handle=0x%x", (UintPtr)(* handle))); 00233 if((* handle)->connected){ 00234 ndb_mgm_disconnect(* handle); 00235 } 00236 #ifdef MGMAPI_LOG 00237 if ((* handle)->logfile != 0){ 00238 fclose((* handle)->logfile); 00239 (* handle)->logfile = 0; 00240 } 00241 #endif 00242 (*handle)->cfg.~LocalConfig(); 00243 my_free((*handle)->m_name, MYF(MY_ALLOW_ZERO_PTR)); 00244 my_free((char*)* handle,MYF(MY_ALLOW_ZERO_PTR)); 00245 * handle = 0; 00246 DBUG_VOID_RETURN; 00247 } 00248 00249 extern "C" 00250 void 00251 ndb_mgm_set_error_stream(NdbMgmHandle handle, FILE * file) 00252 { 00253 handle->errstream = file; 00254 } 00255 00256 /***************************************************************************** 00257 * Error handling 00258 *****************************************************************************/ 00259 00263 extern "C" 00264 int 00265 ndb_mgm_get_latest_error(const NdbMgmHandle h) 00266 { 00267 return h->last_error; 00268 } 00269 00270 extern "C" 00271 const char * 00272 ndb_mgm_get_latest_error_desc(const NdbMgmHandle h){ 00273 return h->last_error_desc; 00274 } 00275 00276 extern "C" 00277 int 00278 ndb_mgm_get_latest_error_line(const NdbMgmHandle h) 00279 { 00280 return h->last_error_line; 00281 } 00282 00283 extern "C" 00284 const char * 00285 ndb_mgm_get_latest_error_msg(const NdbMgmHandle h) 00286 { 00287 for (int i=0; i<ndb_mgm_noOfErrorMsgs; i++) { 00288 if (ndb_mgm_error_msgs[i].code == h->last_error) 00289 return ndb_mgm_error_msgs[i].msg; 00290 } 00291 00292 return "Error"; // Unknown Error message 00293 } 00294 00295 /* 00296 * Call an operation, and return the reply 00297 */ 00298 static const Properties * 00299 ndb_mgm_call(NdbMgmHandle handle, const ParserRow<ParserDummy> *command_reply, 00300 const char *cmd, const Properties *cmd_args) 00301 { 00302 DBUG_ENTER("ndb_mgm_call"); 00303 DBUG_PRINT("enter",("handle->socket: %d, cmd: %s", 00304 handle->socket, cmd)); 00305 SocketOutputStream out(handle->socket); 00306 SocketInputStream in(handle->socket, handle->read_timeout); 00307 00308 out.println(cmd); 00309 #ifdef MGMAPI_LOG 00310 00313 FileOutputStream f(handle->logfile); 00314 f.println("OUT: %s", cmd); 00315 #endif 00316 00317 if(cmd_args != NULL) { 00318 Properties::Iterator iter(cmd_args); 00319 const char *name; 00320 while((name = iter.next()) != NULL) { 00321 PropertiesType t; 00322 Uint32 val_i; 00323 Uint64 val_64; 00324 BaseString val_s; 00325 00326 cmd_args->getTypeOf(name, &t); 00327 switch(t) { 00328 case PropertiesType_Uint32: 00329 cmd_args->get(name, &val_i); 00330 out.println("%s: %d", name, val_i); 00331 break; 00332 case PropertiesType_Uint64: 00333 cmd_args->get(name, &val_64); 00334 out.println("%s: %Ld", name, val_64); 00335 break; 00336 case PropertiesType_char: 00337 cmd_args->get(name, val_s); 00338 out.println("%s: %s", name, val_s.c_str()); 00339 break; 00340 case PropertiesType_Properties: 00341 DBUG_PRINT("info",("Ignoring PropertiesType_Properties.")); 00342 /* Ignore */ 00343 break; 00344 default: 00345 DBUG_PRINT("info",("Ignoring PropertiesType: %d.",t)); 00346 } 00347 } 00348 #ifdef MGMAPI_LOG 00349 00352 cmd_args->print(handle->logfile, "OUT: "); 00353 #endif 00354 } 00355 out.println(""); 00356 00357 Parser_t::Context ctx; 00358 ParserDummy session(handle->socket); 00359 Parser_t parser(command_reply, in, true, true, true); 00360 00361 const Properties* p = parser.parse(ctx, session); 00362 if (p == NULL){ 00363 if(!ndb_mgm_is_connected(handle)) { 00364 DBUG_RETURN(NULL); 00365 } 00366 else 00367 { 00368 if(ctx.m_status==Parser_t::Eof 00369 || ctx.m_status==Parser_t::NoLine) 00370 { 00371 ndb_mgm_disconnect(handle); 00372 DBUG_RETURN(NULL); 00373 } 00377 fprintf(handle->errstream, 00378 "Error in mgm protocol parser. cmd: >%s< status: %d curr: %s\n", 00379 cmd, (Uint32)ctx.m_status, 00380 (ctx.m_currentToken)?ctx.m_currentToken:"NULL"); 00381 DBUG_PRINT("info",("ctx.status: %d, ctx.m_currentToken: %s", 00382 ctx.m_status, ctx.m_currentToken)); 00383 } 00384 } 00385 #ifdef MGMAPI_LOG 00386 else { 00390 p->print(handle->logfile, "IN: "); 00391 } 00392 #endif 00393 DBUG_RETURN(p); 00394 } 00395 00399 extern "C" 00400 int ndb_mgm_is_connected(NdbMgmHandle handle) 00401 { 00402 if(!handle) 00403 return 0; 00404 00405 if(handle->connected) 00406 { 00407 if(Ndb_check_socket_hup(handle->socket)) 00408 { 00409 handle->connected= 0; 00410 NDB_CLOSE_SOCKET(handle->socket); 00411 } 00412 } 00413 return handle->connected; 00414 } 00415 00419 extern "C" 00420 int 00421 ndb_mgm_connect(NdbMgmHandle handle, int no_retries, 00422 int retry_delay_in_seconds, int verbose) 00423 { 00424 SET_ERROR(handle, NDB_MGM_NO_ERROR, "Executing: ndb_mgm_connect"); 00425 CHECK_HANDLE(handle, -1); 00426 00427 DBUG_ENTER("ndb_mgm_connect"); 00428 #ifdef MGMAPI_LOG 00429 00432 char logname[64]; 00433 BaseString::snprintf(logname, 64, "mgmapi.log"); 00434 handle->logfile = fopen(logname, "w"); 00435 #endif 00436 00440 LocalConfig &cfg= handle->cfg; 00441 NDB_SOCKET_TYPE sockfd= NDB_INVALID_SOCKET; 00442 Uint32 i; 00443 while (sockfd == NDB_INVALID_SOCKET) 00444 { 00445 // do all the mgmt servers 00446 for (i = 0; i < cfg.ids.size(); i++) 00447 { 00448 if (cfg.ids[i].type != MgmId_TCP) 00449 continue; 00450 SocketClient s(cfg.ids[i].name.c_str(), cfg.ids[i].port); 00451 sockfd = s.connect(); 00452 if (sockfd != NDB_INVALID_SOCKET) 00453 break; 00454 } 00455 if (sockfd != NDB_INVALID_SOCKET) 00456 break; 00457 #ifndef DBUG_OFF 00458 { 00459 char buf[1024]; 00460 DBUG_PRINT("info",("Unable to connect with connect string: %s", 00461 cfg.makeConnectString(buf,sizeof(buf)))); 00462 } 00463 #endif 00464 if (verbose > 0) { 00465 char buf[1024]; 00466 fprintf(handle->errstream, "Unable to connect with connect string: %s\n", 00467 cfg.makeConnectString(buf,sizeof(buf))); 00468 verbose= -1; 00469 } 00470 if (no_retries == 0) { 00471 char buf[1024]; 00472 setError(handle, NDB_MGM_COULD_NOT_CONNECT_TO_SOCKET, __LINE__, 00473 "Unable to connect with connect string: %s", 00474 cfg.makeConnectString(buf,sizeof(buf))); 00475 if (verbose == -2) 00476 fprintf(handle->errstream, ", failed.\n"); 00477 DBUG_RETURN(-1); 00478 } 00479 if (verbose == -1) { 00480 fprintf(handle->errstream, "Retrying every %d seconds", 00481 retry_delay_in_seconds); 00482 if (no_retries > 0) 00483 fprintf(handle->errstream, ". Attempts left:"); 00484 else 00485 fprintf(handle->errstream, ", until connected."); 00486 fflush(handle->errstream); 00487 verbose= -2; 00488 } 00489 if (no_retries > 0) { 00490 if (verbose == -2) { 00491 fprintf(handle->errstream, " %d", no_retries); 00492 fflush(handle->errstream); 00493 } 00494 no_retries--; 00495 } 00496 NdbSleep_SecSleep(retry_delay_in_seconds); 00497 } 00498 if (verbose == -2) 00499 { 00500 fprintf(handle->errstream, "\n"); 00501 fflush(handle->errstream); 00502 } 00503 handle->cfg_i = i; 00504 00505 handle->socket = sockfd; 00506 handle->connected = 1; 00507 00508 DBUG_RETURN(0); 00509 } 00510 00514 extern "C" 00515 int 00516 ndb_mgm_disconnect(NdbMgmHandle handle) 00517 { 00518 SET_ERROR(handle, NDB_MGM_NO_ERROR, "Executing: ndb_mgm_disconnect"); 00519 CHECK_HANDLE(handle, -1); 00520 CHECK_CONNECTED(handle, -1); 00521 00522 NDB_CLOSE_SOCKET(handle->socket); 00523 handle->socket = NDB_INVALID_SOCKET; 00524 handle->connected = 0; 00525 00526 return 0; 00527 } 00528 00529 struct ndb_mgm_type_atoi 00530 { 00531 const char * str; 00532 const char * alias; 00533 enum ndb_mgm_node_type value; 00534 }; 00535 00536 static struct ndb_mgm_type_atoi type_values[] = 00537 { 00538 { "NDB", "ndbd", NDB_MGM_NODE_TYPE_NDB}, 00539 { "API", "mysqld", NDB_MGM_NODE_TYPE_API }, 00540 { "MGM", "ndb_mgmd", NDB_MGM_NODE_TYPE_MGM } 00541 }; 00542 00543 const int no_of_type_values = (sizeof(type_values) / 00544 sizeof(ndb_mgm_type_atoi)); 00545 00546 extern "C" 00547 ndb_mgm_node_type 00548 ndb_mgm_match_node_type(const char * type) 00549 { 00550 if(type == 0) 00551 return NDB_MGM_NODE_TYPE_UNKNOWN; 00552 00553 for(int i = 0; i<no_of_type_values; i++) 00554 if(strcmp(type, type_values[i].str) == 0) 00555 return type_values[i].value; 00556 else if(strcmp(type, type_values[i].alias) == 0) 00557 return type_values[i].value; 00558 00559 return NDB_MGM_NODE_TYPE_UNKNOWN; 00560 } 00561 00562 extern "C" 00563 const char * 00564 ndb_mgm_get_node_type_string(enum ndb_mgm_node_type type) 00565 { 00566 for(int i = 0; i<no_of_type_values; i++) 00567 if(type_values[i].value == type) 00568 return type_values[i].str; 00569 return 0; 00570 } 00571 00572 extern "C" 00573 const char * 00574 ndb_mgm_get_node_type_alias_string(enum ndb_mgm_node_type type, const char** str) 00575 { 00576 for(int i = 0; i<no_of_type_values; i++) 00577 if(type_values[i].value == type) 00578 { 00579 if (str) 00580 *str= type_values[i].str; 00581 return type_values[i].alias; 00582 } 00583 return 0; 00584 } 00585 00586 struct ndb_mgm_status_atoi { 00587 const char * str; 00588 enum ndb_mgm_node_status value; 00589 }; 00590 00591 static struct ndb_mgm_status_atoi status_values[] = 00592 { 00593 { "UNKNOWN", NDB_MGM_NODE_STATUS_UNKNOWN }, 00594 { "NO_CONTACT", NDB_MGM_NODE_STATUS_NO_CONTACT }, 00595 { "NOT_STARTED", NDB_MGM_NODE_STATUS_NOT_STARTED }, 00596 { "STARTING", NDB_MGM_NODE_STATUS_STARTING }, 00597 { "STARTED", NDB_MGM_NODE_STATUS_STARTED }, 00598 { "SHUTTING_DOWN", NDB_MGM_NODE_STATUS_SHUTTING_DOWN }, 00599 { "RESTARTING", NDB_MGM_NODE_STATUS_RESTARTING }, 00600 { "SINGLE USER MODE", NDB_MGM_NODE_STATUS_SINGLEUSER } 00601 }; 00602 00603 const int no_of_status_values = (sizeof(status_values) / 00604 sizeof(ndb_mgm_status_atoi)); 00605 00606 extern "C" 00607 ndb_mgm_node_status 00608 ndb_mgm_match_node_status(const char * status) 00609 { 00610 if(status == 0) 00611 return NDB_MGM_NODE_STATUS_UNKNOWN; 00612 00613 for(int i = 0; i<no_of_status_values; i++) 00614 if(strcmp(status, status_values[i].str) == 0) 00615 return status_values[i].value; 00616 00617 return NDB_MGM_NODE_STATUS_UNKNOWN; 00618 } 00619 00620 extern "C" 00621 const char * 00622 ndb_mgm_get_node_status_string(enum ndb_mgm_node_status status) 00623 { 00624 int i; 00625 for(i = 0; i<no_of_status_values; i++) 00626 if(status_values[i].value == status) 00627 return status_values[i].str; 00628 00629 for(i = 0; i<no_of_status_values; i++) 00630 if(status_values[i].value == NDB_MGM_NODE_STATUS_UNKNOWN) 00631 return status_values[i].str; 00632 00633 return 0; 00634 } 00635 00636 static int 00637 status_ackumulate(struct ndb_mgm_node_state * state, 00638 const char * field, 00639 const char * value) 00640 { 00641 if(strcmp("type", field) == 0){ 00642 state->node_type = ndb_mgm_match_node_type(value); 00643 } else if(strcmp("status", field) == 0){ 00644 state->node_status = ndb_mgm_match_node_status(value); 00645 } else if(strcmp("startphase", field) == 0){ 00646 state->start_phase = atoi(value); 00647 } else if(strcmp("dynamic_id", field) == 0){ 00648 state->dynamic_id = atoi(value); 00649 } else if(strcmp("node_group", field) == 0){ 00650 state->node_group = atoi(value); 00651 } else if(strcmp("version", field) == 0){ 00652 state->version = atoi(value); 00653 } else if(strcmp("connect_count", field) == 0){ 00654 state->connect_count = atoi(value); 00655 } else if(strcmp("address", field) == 0){ 00656 strncpy(state->connect_address, value, sizeof(state->connect_address)); 00657 state->connect_address[sizeof(state->connect_address)-1]= 0; 00658 } else { 00659 ndbout_c("Unknown field: %s", field); 00660 } 00661 return 0; 00662 } 00663 00668 static int 00669 cmp_state(const void *_a, const void *_b) 00670 { 00671 struct ndb_mgm_node_state *a, *b; 00672 00673 a = (struct ndb_mgm_node_state *)_a; 00674 b = (struct ndb_mgm_node_state *)_b; 00675 00676 if (a->node_id > b->node_id) 00677 return 1; 00678 return -1; 00679 } 00680 00681 extern "C" 00682 struct ndb_mgm_cluster_state * 00683 ndb_mgm_get_status(NdbMgmHandle handle) 00684 { 00685 SET_ERROR(handle, NDB_MGM_NO_ERROR, "Executing: ndb_mgm_get_status"); 00686 CHECK_HANDLE(handle, NULL); 00687 CHECK_CONNECTED(handle, NULL); 00688 00689 SocketOutputStream out(handle->socket); 00690 SocketInputStream in(handle->socket, handle->read_timeout); 00691 00692 out.println("get status"); 00693 out.println(""); 00694 00695 char buf[1024]; 00696 if(!in.gets(buf, sizeof(buf))) 00697 { 00698 SET_ERROR(handle, NDB_MGM_ILLEGAL_SERVER_REPLY, "Probably disconnected"); 00699 return NULL; 00700 } 00701 if(buf[strlen(buf)-1] == '\n') 00702 buf[strlen(buf)-1] = '\0'; 00703 00704 if(strcmp("node status", buf) != 0) { 00705 SET_ERROR(handle, NDB_MGM_ILLEGAL_NODE_STATUS, buf); 00706 return NULL; 00707 } 00708 00709 if(!in.gets(buf, sizeof(buf))) 00710 { 00711 SET_ERROR(handle, NDB_MGM_ILLEGAL_SERVER_REPLY, "Probably disconnected"); 00712 return NULL; 00713 } 00714 if(buf[strlen(buf)-1] == '\n') 00715 buf[strlen(buf)-1] = '\0'; 00716 00717 BaseString tmp(buf); 00718 Vector<BaseString> split; 00719 tmp.split(split, ":"); 00720 if(split.size() != 2){ 00721 SET_ERROR(handle, NDB_MGM_ILLEGAL_NODE_STATUS, buf); 00722 return NULL; 00723 } 00724 00725 if(!(split[0].trim() == "nodes")){ 00726 SET_ERROR(handle, NDB_MGM_ILLEGAL_NODE_STATUS, buf); 00727 return NULL; 00728 } 00729 00730 const int noOfNodes = atoi(split[1].c_str()); 00731 00732 ndb_mgm_cluster_state *state = (ndb_mgm_cluster_state*) 00733 malloc(sizeof(ndb_mgm_cluster_state)+ 00734 noOfNodes*(sizeof(ndb_mgm_node_state)+sizeof("000.000.000.000#"))); 00735 00736 if(!state) 00737 { 00738 SET_ERROR(handle, NDB_MGM_OUT_OF_MEMORY, 00739 "Allocating ndb_mgm_cluster_state"); 00740 return NULL; 00741 } 00742 00743 state->no_of_nodes= noOfNodes; 00744 ndb_mgm_node_state * ptr = &state->node_states[0]; 00745 int nodeId = 0; 00746 int i; 00747 for (i= 0; i < noOfNodes; i++) { 00748 state->node_states[i].connect_address[0]= 0; 00749 } 00750 i = -1; ptr--; 00751 for(; i<noOfNodes; ){ 00752 if(!in.gets(buf, sizeof(buf))) 00753 { 00754 free(state); 00755 SET_ERROR(handle, NDB_MGM_ILLEGAL_SERVER_REPLY, 00756 "Probably disconnected"); 00757 return NULL; 00758 } 00759 tmp.assign(buf); 00760 00761 if(tmp.trim() == ""){ 00762 break; 00763 } 00764 00765 Vector<BaseString> split; 00766 tmp.split(split, ":.", 4); 00767 if(split.size() != 4) 00768 break; 00769 00770 const int id = atoi(split[1].c_str()); 00771 if(id != nodeId){ 00772 ptr++; 00773 i++; 00774 nodeId = id; 00775 ptr->node_id = id; 00776 } 00777 00778 split[3].trim(" \t\n"); 00779 00780 if(status_ackumulate(ptr,split[2].c_str(), split[3].c_str()) != 0) { 00781 break; 00782 } 00783 } 00784 00785 if(i+1 != noOfNodes){ 00786 free(state); 00787 SET_ERROR(handle, NDB_MGM_ILLEGAL_NODE_STATUS, "Node count mismatch"); 00788 return NULL; 00789 } 00790 00791 qsort(state->node_states, state->no_of_nodes, sizeof(state->node_states[0]), 00792 cmp_state); 00793 return state; 00794 } 00795 00796 extern "C" 00797 int 00798 ndb_mgm_enter_single_user(NdbMgmHandle handle, 00799 unsigned int nodeId, 00800 struct ndb_mgm_reply* /*reply*/) 00801 { 00802 SET_ERROR(handle, NDB_MGM_NO_ERROR, "Executing: ndb_mgm_enter_single_user"); 00803 const ParserRow<ParserDummy> enter_single_reply[] = { 00804 MGM_CMD("enter single user reply", NULL, ""), 00805 MGM_ARG("result", String, Mandatory, "Error message"), 00806 MGM_END() 00807 }; 00808 CHECK_HANDLE(handle, -1); 00809 CHECK_CONNECTED(handle, -1); 00810 00811 Properties args; 00812 args.put("nodeId", nodeId); 00813 const Properties *reply; 00814 reply = ndb_mgm_call(handle, enter_single_reply, "enter single user", &args); 00815 CHECK_REPLY(reply, -1); 00816 00817 BaseString result; 00818 reply->get("result", result); 00819 if(strcmp(result.c_str(), "Ok") != 0) { 00820 SET_ERROR(handle, NDB_MGM_COULD_NOT_ENTER_SINGLE_USER_MODE, 00821 result.c_str()); 00822 delete reply; 00823 return -1; 00824 } 00825 00826 delete reply; 00827 return 0; 00828 } 00829 00830 00831 extern "C" 00832 int 00833 ndb_mgm_exit_single_user(NdbMgmHandle handle, struct ndb_mgm_reply* /*reply*/) 00834 { 00835 SET_ERROR(handle, NDB_MGM_NO_ERROR, "Executing: ndb_mgm_exit_single_user"); 00836 const ParserRow<ParserDummy> exit_single_reply[] = { 00837 MGM_CMD("exit single user reply", NULL, ""), 00838 MGM_ARG("result", String, Mandatory, "Error message"), 00839 MGM_END() 00840 }; 00841 CHECK_HANDLE(handle, -1); 00842 CHECK_CONNECTED(handle, -1); 00843 00844 const Properties *reply; 00845 reply = ndb_mgm_call(handle, exit_single_reply, "exit single user", 0); 00846 CHECK_REPLY(reply, -1); 00847 00848 const char * buf; 00849 reply->get("result", &buf); 00850 if(strcmp(buf,"Ok")!=0) { 00851 SET_ERROR(handle, NDB_MGM_COULD_NOT_EXIT_SINGLE_USER_MODE, buf); 00852 delete reply; 00853 return -1; 00854 } 00855 00856 delete reply; 00857 return 0; 00858 } 00859 00860 extern "C" 00861 int 00862 ndb_mgm_stop(NdbMgmHandle handle, int no_of_nodes, const int * node_list) 00863 { 00864 SET_ERROR(handle, NDB_MGM_NO_ERROR, "Executing: ndb_mgm_stop"); 00865 return ndb_mgm_stop2(handle, no_of_nodes, node_list, 0); 00866 } 00867 00868 extern "C" 00869 int 00870 ndb_mgm_stop2(NdbMgmHandle handle, int no_of_nodes, const int * node_list, 00871 int abort) 00872 { 00873 int disconnect; 00874 return ndb_mgm_stop3(handle, no_of_nodes, node_list, abort, &disconnect); 00875 } 00876 00877 00878 extern "C" 00879 int 00880 ndb_mgm_stop3(NdbMgmHandle handle, int no_of_nodes, const int * node_list, 00881 int abort, int *disconnect) 00882 { 00883 SET_ERROR(handle, NDB_MGM_NO_ERROR, "Executing: ndb_mgm_stop3"); 00884 const ParserRow<ParserDummy> stop_reply_v1[] = { 00885 MGM_CMD("stop reply", NULL, ""), 00886 MGM_ARG("stopped", Int, Optional, "No of stopped nodes"), 00887 MGM_ARG("result", String, Mandatory, "Error message"), 00888 MGM_END() 00889 }; 00890 const ParserRow<ParserDummy> stop_reply_v2[] = { 00891 MGM_CMD("stop reply", NULL, ""), 00892 MGM_ARG("stopped", Int, Optional, "No of stopped nodes"), 00893 MGM_ARG("result", String, Mandatory, "Error message"), 00894 MGM_ARG("disconnect", Int, Mandatory, "Need to disconnect"), 00895 MGM_END() 00896 }; 00897 00898 CHECK_HANDLE(handle, -1); 00899 CHECK_CONNECTED(handle, -1); 00900 00901 if(handle->mgmd_version_build==-1) 00902 { 00903 char verstr[50]; 00904 if(!ndb_mgm_get_version(handle, 00905 &(handle->mgmd_version_major), 00906 &(handle->mgmd_version_minor), 00907 &(handle->mgmd_version_build), 00908 sizeof(verstr), 00909 verstr)) 00910 { 00911 return -1; 00912 } 00913 } 00914 int use_v2= ((handle->mgmd_version_major==5) 00915 && ( 00916 (handle->mgmd_version_minor==0 && handle->mgmd_version_build>=21) 00917 ||(handle->mgmd_version_minor==1 && handle->mgmd_version_build>=12) 00918 ||(handle->mgmd_version_minor>1) 00919 ) 00920 ) 00921 || (handle->mgmd_version_major>5); 00922 00923 if(no_of_nodes < -1){ 00924 SET_ERROR(handle, NDB_MGM_ILLEGAL_NUMBER_OF_NODES, 00925 "Negative number of nodes requested to stop"); 00926 return -1; 00927 } 00928 00929 Uint32 stoppedNoOfNodes = 0; 00930 if(no_of_nodes <= 0){ 00934 Properties args; 00935 args.put("abort", abort); 00936 if(use_v2) 00937 args.put("stop", (no_of_nodes==-1)?"mgm,db":"db"); 00938 const Properties *reply; 00939 if(use_v2) 00940 reply = ndb_mgm_call(handle, stop_reply_v2, "stop all", &args); 00941 else 00942 reply = ndb_mgm_call(handle, stop_reply_v1, "stop all", &args); 00943 CHECK_REPLY(reply, -1); 00944 00945 if(!reply->get("stopped", &stoppedNoOfNodes)){ 00946 SET_ERROR(handle, NDB_MGM_STOP_FAILED, 00947 "Could not get number of stopped nodes from mgm server"); 00948 delete reply; 00949 return -1; 00950 } 00951 if(use_v2) 00952 reply->get("disconnect", (Uint32*)disconnect); 00953 else 00954 *disconnect= 0; 00955 BaseString result; 00956 reply->get("result", result); 00957 if(strcmp(result.c_str(), "Ok") != 0) { 00958 SET_ERROR(handle, NDB_MGM_STOP_FAILED, result.c_str()); 00959 delete reply; 00960 return -1; 00961 } 00962 delete reply; 00963 return stoppedNoOfNodes; 00964 } 00965 00969 Properties args; 00970 00971 BaseString node_list_str; 00972 node_list_str.assfmt("%d", node_list[0]); 00973 for(int node = 1; node < no_of_nodes; node++) 00974 node_list_str.appfmt(" %d", node_list[node]); 00975 00976 args.put("node", node_list_str.c_str()); 00977 args.put("abort", abort); 00978 00979 const Properties *reply; 00980 if(use_v2) 00981 reply = ndb_mgm_call(handle, stop_reply_v2, "stop v2", &args); 00982 else 00983 reply = ndb_mgm_call(handle, stop_reply_v1, "stop", &args); 00984 00985 CHECK_REPLY(reply, stoppedNoOfNodes); 00986 if(!reply->get("stopped", &stoppedNoOfNodes)){ 00987 SET_ERROR(handle, NDB_MGM_STOP_FAILED, 00988 "Could not get number of stopped nodes from mgm server"); 00989 delete reply; 00990 return -1; 00991 } 00992 if(use_v2) 00993 reply->get("disconnect", (Uint32*)disconnect); 00994 else 00995 *disconnect= 0; 00996 BaseString result; 00997 reply->get("result", result); 00998 if(strcmp(result.c_str(), "Ok") != 0) { 00999 SET_ERROR(handle, NDB_MGM_STOP_FAILED, result.c_str()); 01000 delete reply; 01001 return -1; 01002 } 01003 delete reply; 01004 return stoppedNoOfNodes; 01005 } 01006 01007 extern "C" 01008 int 01009 ndb_mgm_restart(NdbMgmHandle handle, int no_of_nodes, const int *node_list) 01010 { 01011 SET_ERROR(handle, NDB_MGM_NO_ERROR, "Executing: ndb_mgm_restart"); 01012 return ndb_mgm_restart2(handle, no_of_nodes, node_list, 0, 0, 0); 01013 } 01014 01015 extern "C" 01016 int 01017 ndb_mgm_restart2(NdbMgmHandle handle, int no_of_nodes, const int * node_list, 01018 int initial, int nostart, int abort) 01019 { 01020 int disconnect; 01021 01022 return ndb_mgm_restart3(handle, no_of_nodes, node_list, initial, nostart, 01023 abort, &disconnect); 01024 } 01025 01026 extern "C" 01027 int 01028 ndb_mgm_restart3(NdbMgmHandle handle, int no_of_nodes, const int * node_list, 01029 int initial, int nostart, int abort, int *disconnect) 01030 { 01031 SET_ERROR(handle, NDB_MGM_NO_ERROR, "Executing: ndb_mgm_restart3"); 01032 Uint32 restarted = 0; 01033 const ParserRow<ParserDummy> restart_reply_v1[] = { 01034 MGM_CMD("restart reply", NULL, ""), 01035 MGM_ARG("result", String, Mandatory, "Error message"), 01036 MGM_ARG("restarted", Int, Optional, "No of restarted nodes"), 01037 MGM_END() 01038 }; 01039 const ParserRow<ParserDummy> restart_reply_v2[] = { 01040 MGM_CMD("restart reply", NULL, ""), 01041 MGM_ARG("result", String, Mandatory, "Error message"), 01042 MGM_ARG("restarted", Int, Optional, "No of restarted nodes"), 01043 MGM_ARG("disconnect", Int, Optional, "Disconnect to apply"), 01044 MGM_END() 01045 }; 01046 01047 CHECK_HANDLE(handle, -1); 01048 CHECK_CONNECTED(handle, -1); 01049 01050 if(handle->mgmd_version_build==-1) 01051 { 01052 char verstr[50]; 01053 if(!ndb_mgm_get_version(handle, 01054 &(handle->mgmd_version_major), 01055 &(handle->mgmd_version_minor), 01056 &(handle->mgmd_version_build), 01057 sizeof(verstr), 01058 verstr)) 01059 { 01060 return -1; 01061 } 01062 } 01063 int use_v2= ((handle->mgmd_version_major==5) 01064 && ( 01065 (handle->mgmd_version_minor==0 && handle->mgmd_version_build>=21) 01066 ||(handle->mgmd_version_minor==1 && handle->mgmd_version_build>=12) 01067 ||(handle->mgmd_version_minor>1) 01068 ) 01069 ) 01070 || (handle->mgmd_version_major>5); 01071 01072 if(no_of_nodes < 0){ 01073 SET_ERROR(handle, NDB_MGM_RESTART_FAILED, 01074 "Restart requested of negative number of nodes"); 01075 return -1; 01076 } 01077 01078 if(no_of_nodes == 0) { 01079 Properties args; 01080 args.put("abort", abort); 01081 args.put("initialstart", initial); 01082 args.put("nostart", nostart); 01083 const Properties *reply; 01084 const int timeout = handle->read_timeout; 01085 handle->read_timeout= 5*60*1000; // 5 minutes 01086 reply = ndb_mgm_call(handle, restart_reply_v1, "restart all", &args); 01087 handle->read_timeout= timeout; 01088 CHECK_REPLY(reply, -1); 01089 01090 BaseString result; 01091 reply->get("result", result); 01092 if(strcmp(result.c_str(), "Ok") != 0) { 01093 SET_ERROR(handle, NDB_MGM_RESTART_FAILED, result.c_str()); 01094 delete reply; 01095 return -1; 01096 } 01097 if(!reply->get("restarted", &restarted)){ 01098 SET_ERROR(handle, NDB_MGM_RESTART_FAILED, 01099 "Could not get restarted number of nodes from mgm server"); 01100 delete reply; 01101 return -1; 01102 } 01103 delete reply; 01104 return restarted; 01105 } 01106 01107 BaseString node_list_str; 01108 node_list_str.assfmt("%d", node_list[0]); 01109 for(int node = 1; node < no_of_nodes; node++) 01110 node_list_str.appfmt(" %d", node_list[node]); 01111 01112 Properties args; 01113 01114 args.put("node", node_list_str.c_str()); 01115 args.put("abort", abort); 01116 args.put("initialstart", initial); 01117 args.put("nostart", nostart); 01118 01119 const Properties *reply; 01120 const int timeout = handle->read_timeout; 01121 handle->read_timeout= 5*60*1000; // 5 minutes 01122 if(use_v2) 01123 reply = ndb_mgm_call(handle, restart_reply_v2, "restart node v2", &args); 01124 else 01125 reply = ndb_mgm_call(handle, restart_reply_v1, "restart node", &args); 01126 handle->read_timeout= timeout; 01127 if(reply != NULL) { 01128 BaseString result; 01129 reply->get("result", result); 01130 if(strcmp(result.c_str(), "Ok") != 0) { 01131 SET_ERROR(handle, NDB_MGM_RESTART_FAILED, result.c_str()); 01132 delete reply; 01133 return -1; 01134 } 01135 reply->get("restarted", &restarted); 01136 if(use_v2) 01137 reply->get("disconnect", (Uint32*)disconnect); 01138 else 01139 *disconnect= 0; 01140 delete reply; 01141 } 01142 01143 return restarted; 01144 } 01145 01146 static const char *clusterlog_severity_names[]= 01147 { "enabled", "debug", "info", "warning", "error", "critical", "alert" }; 01148 01149 struct ndb_mgm_event_severities 01150 { 01151 const char* name; 01152 enum ndb_mgm_event_severity severity; 01153 } clusterlog_severities[] = { 01154 { clusterlog_severity_names[0], NDB_MGM_EVENT_SEVERITY_ON }, 01155 { clusterlog_severity_names[1], NDB_MGM_EVENT_SEVERITY_DEBUG }, 01156 { clusterlog_severity_names[2], NDB_MGM_EVENT_SEVERITY_INFO }, 01157 { clusterlog_severity_names[3], NDB_MGM_EVENT_SEVERITY_WARNING }, 01158 { clusterlog_severity_names[4], NDB_MGM_EVENT_SEVERITY_ERROR }, 01159 { clusterlog_severity_names[5], NDB_MGM_EVENT_SEVERITY_CRITICAL }, 01160 { clusterlog_severity_names[6], NDB_MGM_EVENT_SEVERITY_ALERT }, 01161 { "all", NDB_MGM_EVENT_SEVERITY_ALL }, 01162 { 0, NDB_MGM_ILLEGAL_EVENT_SEVERITY }, 01163 }; 01164 01165 extern "C" 01166 ndb_mgm_event_severity 01167 ndb_mgm_match_event_severity(const char * name) 01168 { 01169 if(name == 0) 01170 return NDB_MGM_ILLEGAL_EVENT_SEVERITY; 01171 01172 for(int i = 0; clusterlog_severities[i].name !=0 ; i++) 01173 if(strcasecmp(name, clusterlog_severities[i].name) == 0) 01174 return clusterlog_severities[i].severity; 01175 01176 return NDB_MGM_ILLEGAL_EVENT_SEVERITY; 01177 } 01178 01179 extern "C" 01180 const char * 01181 ndb_mgm_get_event_severity_string(enum ndb_mgm_event_severity severity) 01182 { 01183 int i= (int)severity; 01184 if (i >= 0 && i < (int)NDB_MGM_EVENT_SEVERITY_ALL) 01185 return clusterlog_severity_names[i]; 01186 for(i = (int)NDB_MGM_EVENT_SEVERITY_ALL; clusterlog_severities[i].name != 0; i++) 01187 if(clusterlog_severities[i].severity == severity) 01188 return clusterlog_severities[i].name; 01189 return 0; 01190 } 01191 01192 extern "C" 01193 const unsigned int * 01194 ndb_mgm_get_clusterlog_severity_filter(NdbMgmHandle handle) 01195 { 01196 SET_ERROR(handle, NDB_MGM_NO_ERROR, "Executing: ndb_mgm_get_clusterlog_severity_filter"); 01197 static unsigned int enabled[(int)NDB_MGM_EVENT_SEVERITY_ALL]= 01198 {0,0,0,0,0,0,0}; 01199 const ParserRow<ParserDummy> getinfo_reply[] = { 01200 MGM_CMD("clusterlog", NULL, ""), 01201 MGM_ARG(clusterlog_severity_names[0], Int, Mandatory, ""), 01202 MGM_ARG(clusterlog_severity_names[1], Int, Mandatory, ""), 01203 MGM_ARG(clusterlog_severity_names[2], Int, Mandatory, ""), 01204 MGM_ARG(clusterlog_severity_names[3], Int, Mandatory, ""), 01205 MGM_ARG(clusterlog_severity_names[4], Int, Mandatory, ""), 01206 MGM_ARG(clusterlog_severity_names[5], Int, Mandatory, ""), 01207 MGM_ARG(clusterlog_severity_names[6], Int, Mandatory, ""), 01208 }; 01209 CHECK_HANDLE(handle, NULL); 01210 CHECK_CONNECTED(handle, NULL); 01211 01212 Properties args; 01213 const Properties *reply; 01214 reply = ndb_mgm_call(handle, getinfo_reply, "get info clusterlog", &args); 01215 CHECK_REPLY(reply, NULL); 01216 01217 for(int i=0; i < (int)NDB_MGM_EVENT_SEVERITY_ALL; i++) { 01218 reply->get(clusterlog_severity_names[i], &enabled[i]); 01219 } 01220 return enabled; 01221 } 01222 01223 extern "C" 01224 int 01225 ndb_mgm_set_clusterlog_severity_filter(NdbMgmHandle handle, 01226 enum ndb_mgm_event_severity severity, 01227 int enable, 01228 struct ndb_mgm_reply* /*reply*/) 01229 { 01230 SET_ERROR(handle, NDB_MGM_NO_ERROR, 01231 "Executing: ndb_mgm_set_clusterlog_severity_filter"); 01232 const ParserRow<ParserDummy> filter_reply[] = { 01233 MGM_CMD("set logfilter reply", NULL, ""), 01234 MGM_ARG("result", String, Mandatory, "Error message"), 01235 MGM_END() 01236 }; 01237 int retval = -1; 01238 CHECK_HANDLE(handle, -1); 01239 CHECK_CONNECTED(handle, -1); 01240 01241 Properties args; 01242 args.put("level", severity); 01243 args.put("enable", enable); 01244 01245 const Properties *reply; 01246 reply = ndb_mgm_call(handle, filter_reply, "set logfilter", &args); 01247 CHECK_REPLY(reply, retval); 01248 01249 BaseString result; 01250 reply->get("result", result); 01251 01252 if (strcmp(result.c_str(), "1") == 0) 01253 retval = 1; 01254 else if (strcmp(result.c_str(), "0") == 0) 01255 retval = 0; 01256 else 01257 { 01258 SET_ERROR(handle, EINVAL, result.c_str()); 01259 } 01260 delete reply; 01261 return retval; 01262 } 01263 01264 struct ndb_mgm_event_categories 01265 { 01266 const char* name; 01267 enum ndb_mgm_event_category category; 01268 } categories[] = { 01269 { "STARTUP", NDB_MGM_EVENT_CATEGORY_STARTUP }, 01270 { "SHUTDOWN", NDB_MGM_EVENT_CATEGORY_SHUTDOWN }, 01271 { "STATISTICS", NDB_MGM_EVENT_CATEGORY_STATISTIC }, 01272 { "NODERESTART", NDB_MGM_EVENT_CATEGORY_NODE_RESTART }, 01273 { "CONNECTION", NDB_MGM_EVENT_CATEGORY_CONNECTION }, 01274 { "CHECKPOINT", NDB_MGM_EVENT_CATEGORY_CHECKPOINT }, 01275 { "DEBUG", NDB_MGM_EVENT_CATEGORY_DEBUG }, 01276 { "INFO", NDB_MGM_EVENT_CATEGORY_INFO }, 01277 { "ERROR", NDB_MGM_EVENT_CATEGORY_ERROR }, 01278 { "BACKUP", NDB_MGM_EVENT_CATEGORY_BACKUP }, 01279 { "CONGESTION", NDB_MGM_EVENT_CATEGORY_CONGESTION }, 01280 { 0, NDB_MGM_ILLEGAL_EVENT_CATEGORY } 01281 }; 01282 01283 extern "C" 01284 ndb_mgm_event_category 01285 ndb_mgm_match_event_category(const char * status) 01286 { 01287 if(status == 0) 01288 return NDB_MGM_ILLEGAL_EVENT_CATEGORY; 01289 01290 for(int i = 0; categories[i].name !=0 ; i++) 01291 if(strcmp(status, categories[i].name) == 0) 01292 return categories[i].category; 01293 01294 return NDB_MGM_ILLEGAL_EVENT_CATEGORY; 01295 } 01296 01297 extern "C" 01298 const char * 01299 ndb_mgm_get_event_category_string(enum ndb_mgm_event_category status) 01300 { 01301 int i; 01302 for(i = 0; categories[i].name != 0; i++) 01303 if(categories[i].category == status) 01304 return categories[i].name; 01305 01306 return 0; 01307 } 01308 01309 extern "C" 01310 int 01311 ndb_mgm_set_clusterlog_loglevel(NdbMgmHandle handle, int nodeId, 01312 enum ndb_mgm_event_category cat, 01313 int level, 01314 struct ndb_mgm_reply* /*reply*/) 01315 { 01316 SET_ERROR(handle, NDB_MGM_NO_ERROR, 01317 "Executing: ndb_mgm_set_clusterlog_loglevel"); 01318 const ParserRow<ParserDummy> clusterlog_reply[] = { 01319 MGM_CMD("set cluster loglevel reply", NULL, ""), 01320 MGM_ARG("result", String, Mandatory, "Error message"), 01321 MGM_END() 01322 }; 01323 CHECK_HANDLE(handle, -1); 01324 CHECK_CONNECTED(handle, -1); 01325 01326 Properties args; 01327 args.put("node", nodeId); 01328 args.put("category", cat); 01329 args.put("level", level); 01330 01331 const Properties *reply; 01332 reply = ndb_mgm_call(handle, clusterlog_reply, 01333 "set cluster loglevel", &args); 01334 CHECK_REPLY(reply, -1); 01335 01336 DBUG_ENTER("ndb_mgm_set_clusterlog_loglevel"); 01337 DBUG_PRINT("enter",("node=%d, category=%d, level=%d", nodeId, cat, level)); 01338 01339 BaseString result; 01340 reply->get("result", result); 01341 if(strcmp(result.c_str(), "Ok") != 0) { 01342 SET_ERROR(handle, EINVAL, result.c_str()); 01343 delete reply; 01344 DBUG_RETURN(-1); 01345 } 01346 delete reply; 01347 DBUG_RETURN(0); 01348 } 01349 01350 extern "C" 01351 int 01352 ndb_mgm_set_loglevel_node(NdbMgmHandle handle, int nodeId, 01353 enum ndb_mgm_event_category category, 01354 int level, 01355 struct ndb_mgm_reply* /*reply*/) 01356 { 01357 SET_ERROR(handle, NDB_MGM_NO_ERROR, "Executing: ndb_mgm_set_loglevel_node"); 01358 const ParserRow<ParserDummy> loglevel_reply[] = { 01359 MGM_CMD("set loglevel reply", NULL, ""), 01360 MGM_ARG("result", String, Mandatory, "Error message"), 01361 MGM_END() 01362 }; 01363 CHECK_HANDLE(handle, -1); 01364 CHECK_CONNECTED(handle, -1); 01365 01366 Properties args; 01367 args.put("node", nodeId); 01368 args.put("category", category); 01369 args.put("level", level); 01370 const Properties *reply; 01371 reply = ndb_mgm_call(handle, loglevel_reply, "set loglevel", &args); 01372 CHECK_REPLY(reply, -1); 01373 01374 BaseString result; 01375 reply->get("result", result); 01376 if(strcmp(result.c_str(), "Ok") != 0) { 01377 SET_ERROR(handle, EINVAL, result.c_str()); 01378 delete reply; 01379 return -1; 01380 } 01381 01382 delete reply; 01383 return 0; 01384 } 01385 01386 int 01387 ndb_mgm_listen_event_internal(NdbMgmHandle handle, const int filter[], 01388 int parsable) 01389 { 01390 SET_ERROR(handle, NDB_MGM_NO_ERROR, "Executing: ndb_mgm_listen_event"); 01391 const ParserRow<ParserDummy> stat_reply[] = { 01392 MGM_CMD("listen event", NULL, ""), 01393 MGM_ARG("result", Int, Mandatory, "Error message"), 01394 MGM_ARG("msg", String, Optional, "Error message"), 01395 MGM_END() 01396 }; 01397 CHECK_HANDLE(handle, -1); 01398 01399 const char *hostname= ndb_mgm_get_connected_host(handle); 01400 int port= ndb_mgm_get_connected_port(handle); 01401 SocketClient s(hostname, port); 01402 const NDB_SOCKET_TYPE sockfd = s.connect(); 01403 if (sockfd == NDB_INVALID_SOCKET) { 01404 setError(handle, NDB_MGM_COULD_NOT_CONNECT_TO_SOCKET, __LINE__, 01405 "Unable to connect to"); 01406 return -1; 01407 } 01408 01409 Properties args; 01410 01411 if (parsable) 01412 args.put("parsable", parsable); 01413 { 01414 BaseString tmp; 01415 for(int i = 0; filter[i] != 0; i += 2){ 01416 tmp.appfmt("%d=%d ", filter[i+1], filter[i]); 01417 } 01418 args.put("filter", tmp.c_str()); 01419 } 01420 01421 int tmp = handle->socket; 01422 handle->socket = sockfd; 01423 01424 const Properties *reply; 01425 reply = ndb_mgm_call(handle, stat_reply, "listen event", &args); 01426 01427 handle->socket = tmp; 01428 01429 if(reply == NULL) { 01430 close(sockfd); 01431 CHECK_REPLY(reply, -1); 01432 } 01433 return sockfd; 01434 } 01435 01436 extern "C" 01437 int 01438 ndb_mgm_listen_event(NdbMgmHandle handle, const int filter[]) 01439 { 01440 return ndb_mgm_listen_event_internal(handle,filter,0); 01441 } 01442 01443 extern "C" 01444 int 01445 ndb_mgm_dump_state(NdbMgmHandle handle, int nodeId, int* _args, 01446 int _num_args, struct ndb_mgm_reply* /* reply */) 01447 { 01448 SET_ERROR(handle, NDB_MGM_NO_ERROR, "Executing: ndb_mgm_dump_state"); 01449 const ParserRow<ParserDummy> dump_state_reply[] = { 01450 MGM_CMD("dump state reply", NULL, ""), 01451 MGM_ARG("result", String, Mandatory, "Error message"), 01452 MGM_END() 01453 }; 01454 CHECK_HANDLE(handle, -1); 01455 CHECK_CONNECTED(handle, -1); 01456 01457 char buf[256]; 01458 buf[0] = 0; 01459 for (int i = 0; i < _num_args; i++){ 01460 unsigned n = strlen(buf); 01461 if (n + 20 > sizeof(buf)) { 01462 SET_ERROR(handle, NDB_MGM_USAGE_ERROR, "arguments too long"); 01463 return -1; 01464 } 01465 sprintf(buf + n, "%s%d", i ? " " : "", _args[i]); 01466 } 01467 01468 Properties args; 01469 args.put("node", nodeId); 01470 args.put("args", buf); 01471 01472 const Properties *prop; 01473 prop = ndb_mgm_call(handle, dump_state_reply, "dump state", &args); 01474 CHECK_REPLY(prop, -1); 01475 01476 BaseString result; 01477 prop->get("result", result); 01478 if(strcmp(result.c_str(), "Ok") != 0) { 01479 SET_ERROR(handle, EINVAL, result.c_str()); 01480 delete prop; 01481 return -1; 01482 } 01483 01484 delete prop; 01485 return 0; 01486 } 01487 01488 extern "C" 01489 int 01490 ndb_mgm_start_signallog(NdbMgmHandle handle, int nodeId, 01491 struct ndb_mgm_reply* reply) 01492 { 01493 SET_ERROR(handle, NDB_MGM_NO_ERROR, "Executing: ndb_mgm_start_signallog"); 01494 const ParserRow<ParserDummy> start_signallog_reply[] = { 01495 MGM_CMD("start signallog reply", NULL, ""), 01496 MGM_ARG("result", String, Mandatory, "Error message"), 01497 MGM_END() 01498 }; 01499 int retval = -1; 01500 CHECK_HANDLE(handle, -1); 01501 CHECK_CONNECTED(handle, -1); 01502 01503 Properties args; 01504 args.put("node", nodeId); 01505 01506 const Properties *prop; 01507 prop = ndb_mgm_call(handle, 01508 start_signallog_reply, 01509 "start signallog", 01510 &args); 01511 01512 if(prop != NULL) { 01513 BaseString result; 01514 prop->get("result", result); 01515 if(strcmp(result.c_str(), "Ok") == 0) { 01516 retval = 0; 01517 } else { 01518 SET_ERROR(handle, EINVAL, result.c_str()); 01519 retval = -1; 01520 } 01521 delete prop; 01522 } 01523 01524 return retval; 01525 } 01526 01527 extern "C" 01528 int 01529 ndb_mgm_stop_signallog(NdbMgmHandle handle, int nodeId, 01530 struct ndb_mgm_reply* reply) 01531 { 01532 SET_ERROR(handle, NDB_MGM_NO_ERROR, "Executing: ndb_mgm_stop_signallog"); 01533 const ParserRow<ParserDummy> stop_signallog_reply[] = { 01534 MGM_CMD("stop signallog reply", NULL, ""), 01535 MGM_ARG("result", String, Mandatory, "Error message"), 01536 MGM_END() 01537 }; 01538 int retval = -1; 01539 CHECK_HANDLE(handle, -1); 01540 CHECK_CONNECTED(handle, -1); 01541 01542 Properties args; 01543 args.put("node", nodeId); 01544 01545 const Properties *prop; 01546 prop = ndb_mgm_call(handle, stop_signallog_reply, "stop signallog", &args); 01547 01548 if(prop != NULL) { 01549 BaseString result; 01550 prop->get("result", result); 01551 if(strcmp(result.c_str(), "Ok") == 0) { 01552 retval = 0; 01553 } else { 01554 SET_ERROR(handle, EINVAL, result.c_str()); 01555 retval = -1; 01556 } 01557 delete prop; 01558 } 01559 01560 return retval; 01561 } 01562 01563 struct ndb_mgm_signal_log_modes 01564 { 01565 const char* name; 01566 enum ndb_mgm_signal_log_mode mode; 01567 }; 01568 01569 extern "C" 01570 int 01571 ndb_mgm_log_signals(NdbMgmHandle handle, int nodeId, 01572 enum ndb_mgm_signal_log_mode mode, 01573 const char* blockNames, 01574 struct ndb_mgm_reply* reply) 01575 { 01576 SET_ERROR(handle, NDB_MGM_NO_ERROR, "Executing: ndb_mgm_log_signals"); 01577 const ParserRow<ParserDummy> stop_signallog_reply[] = { 01578 MGM_CMD("log signals reply", NULL, ""), 01579 MGM_ARG("result", String, Mandatory, "Error message"), 01580 MGM_END() 01581 }; 01582 int retval = -1; 01583 CHECK_HANDLE(handle, -1); 01584 CHECK_CONNECTED(handle, -1); 01585 01586 Properties args; 01587 args.put("node", nodeId); 01588 args.put("blocks", blockNames); 01589 01590 switch(mode) { 01591 case NDB_MGM_SIGNAL_LOG_MODE_IN: 01592 args.put("in", (Uint32)1); 01593 args.put("out", (Uint32)0); 01594 break; 01595 case NDB_MGM_SIGNAL_LOG_MODE_OUT: 01596 args.put("in", (Uint32)0); 01597 args.put("out", (Uint32)1); 01598 break; 01599 case NDB_MGM_SIGNAL_LOG_MODE_INOUT: 01600 args.put("in", (Uint32)1); 01601 args.put("out", (Uint32)1); 01602 break; 01603 case NDB_MGM_SIGNAL_LOG_MODE_OFF: 01604 args.put("in", (Uint32)0); 01605 args.put("out", (Uint32)0); 01606 break; 01607 } 01608 01609 const Properties *prop; 01610 prop = ndb_mgm_call(handle, stop_signallog_reply, "log signals", &args); 01611 01612 if(prop != NULL) { 01613 BaseString result; 01614 prop->get("result", result); 01615 if(strcmp(result.c_str(), "Ok") == 0) { 01616 retval = 0; 01617 } else { 01618 SET_ERROR(handle, EINVAL, result.c_str()); 01619 retval = -1; 01620 } 01621 delete prop; 01622 } 01623 01624 return retval; 01625 } 01626 01627 extern "C" 01628 int 01629 ndb_mgm_set_trace(NdbMgmHandle handle, int nodeId, int traceNumber, 01630 struct ndb_mgm_reply* reply) 01631 { 01632 SET_ERROR(handle, NDB_MGM_NO_ERROR, "Executing: ndb_mgm_set_trace"); 01633 const ParserRow<ParserDummy> set_trace_reply[] = { 01634 MGM_CMD("set trace reply", NULL, ""), 01635 MGM_ARG("result", String, Mandatory, "Error message"), 01636 MGM_END() 01637 }; 01638 int retval = -1; 01639 CHECK_HANDLE(handle, -1); 01640 CHECK_CONNECTED(handle, -1); 01641 01642 Properties args; 01643 args.put("node", nodeId); 01644 args.put("trace", traceNumber); 01645 01646 const Properties *prop; 01647 prop = ndb_mgm_call(handle, set_trace_reply, "set trace", &args); 01648 01649 if(prop != NULL) { 01650 BaseString result; 01651 prop->get("result", result); 01652 if(strcmp(result.c_str(), "Ok") == 0) { 01653 retval = 0; 01654 } else { 01655 SET_ERROR(handle, EINVAL, result.c_str()); 01656 retval = -1; 01657 } 01658 delete prop; 01659 } 01660 01661 return retval; 01662 } 01663 01664 extern "C" 01665 int 01666 ndb_mgm_insert_error(NdbMgmHandle handle, int nodeId, int errorCode, 01667 struct ndb_mgm_reply* reply) 01668 { 01669 SET_ERROR(handle, NDB_MGM_NO_ERROR, "Executing: ndb_mgm_insert_error"); 01670 const ParserRow<ParserDummy> insert_error_reply[] = { 01671 MGM_CMD("insert error reply", NULL, ""), 01672 MGM_ARG("result", String, Mandatory, "Error message"), 01673 MGM_END() 01674 }; 01675 int retval = -1; 01676 CHECK_HANDLE(handle, -1); 01677 CHECK_CONNECTED(handle, -1); 01678 01679 Properties args; 01680 args.put("node", nodeId); 01681 args.put("error", errorCode); 01682 01683 const Properties *prop; 01684 prop = ndb_mgm_call(handle, insert_error_reply, "insert error", &args); 01685 01686 if(prop != NULL) { 01687 BaseString result; 01688 prop->get("result", result); 01689 if(strcmp(result.c_str(), "Ok") == 0) { 01690 retval = 0; 01691 } else { 01692 SET_ERROR(handle, EINVAL, result.c_str()); 01693 retval = -1; 01694 } 01695 delete prop; 01696 } 01697 01698 return retval; 01699 } 01700 01701 extern "C" 01702 int 01703 ndb_mgm_start(NdbMgmHandle handle, int no_of_nodes, const int * node_list) 01704 { 01705 SET_ERROR(handle, NDB_MGM_NO_ERROR, "Executing: ndb_mgm_start"); 01706 const ParserRow<ParserDummy> start_reply[] = { 01707 MGM_CMD("start reply", NULL, ""), 01708 MGM_ARG("started", Int, Optional, "No of started nodes"), 01709 MGM_ARG("result", String, Mandatory, "Error message"), 01710 MGM_END() 01711 }; 01712 int started = 0; 01713 CHECK_HANDLE(handle, -1); 01714 CHECK_CONNECTED(handle, -1); 01715 01716 if(no_of_nodes < 0){ 01717 SET_ERROR(handle, EINVAL, ""); 01718 return -1; 01719 } 01720 01721 if(no_of_nodes == 0){ 01722 Properties args; 01723 const Properties *reply; 01724 reply = ndb_mgm_call(handle, start_reply, "start all", &args); 01725 CHECK_REPLY(reply, -1); 01726 01727 Uint32 count = 0; 01728 if(!reply->get("started", &count)){ 01729 delete reply; 01730 return -1; 01731 } 01732 delete reply; 01733 return count; 01734 } 01735 01736 for(int node = 0; node < no_of_nodes; node++) { 01737 Properties args; 01738 args.put("node", node_list[node]); 01739 01740 const Properties *reply; 01741 reply = ndb_mgm_call(handle, start_reply, "start", &args); 01742 01743 if(reply != NULL) { 01744 BaseString result; 01745 reply->get("result", result); 01746 if(strcmp(result.c_str(), "Ok") == 0) { 01747 started++; 01748 } else { 01749 SET_ERROR(handle, EINVAL, result.c_str()); 01750 delete reply; 01751 return -1; 01752 } 01753 } 01754 delete reply; 01755 } 01756 01757 return started; 01758 } 01759 01760 /***************************************************************************** 01761 * Backup 01762 *****************************************************************************/ 01763 extern "C" 01764 int 01765 ndb_mgm_start_backup(NdbMgmHandle handle, int wait_completed, 01766 unsigned int* _backup_id, 01767 struct ndb_mgm_reply* /*reply*/) 01768 { 01769 SET_ERROR(handle, NDB_MGM_NO_ERROR, "Executing: ndb_mgm_start_backup"); 01770 const ParserRow<ParserDummy> start_backup_reply[] = { 01771 MGM_CMD("start backup reply", NULL, ""), 01772 MGM_ARG("result", String, Mandatory, "Error message"), 01773 MGM_ARG("id", Int, Optional, "Id of the started backup"), 01774 MGM_END() 01775 }; 01776 CHECK_HANDLE(handle, -1); 01777 CHECK_CONNECTED(handle, -1); 01778 01779 Properties args; 01780 args.put("completed", wait_completed); 01781 const Properties *reply; 01782 { // start backup can take some time, set timeout high 01783 Uint64 old_timeout= handle->read_timeout; 01784 if (wait_completed == 2) 01785 handle->read_timeout= 48*60*60*1000; // 48 hours 01786 else if (wait_completed == 1) 01787 handle->read_timeout= 10*60*1000; // 10 minutes 01788 reply = ndb_mgm_call(handle, start_backup_reply, "start backup", &args); 01789 handle->read_timeout= old_timeout; 01790 } 01791 CHECK_REPLY(reply, -1); 01792 01793 BaseString result; 01794 reply->get("result", result); 01795 reply->get("id", _backup_id); 01796 if(strcmp(result.c_str(), "Ok") != 0) { 01797 SET_ERROR(handle, NDB_MGM_COULD_NOT_START_BACKUP, result.c_str()); 01798 delete reply; 01799 return -1; 01800 } 01801 01802 delete reply; 01803 return 0; 01804 } 01805 01806 extern "C" 01807 int 01808 ndb_mgm_abort_backup(NdbMgmHandle handle, unsigned int backupId, 01809 struct ndb_mgm_reply* /*reply*/) 01810 { 01811 SET_ERROR(handle, NDB_MGM_NO_ERROR, "Executing: ndb_mgm_abort_backup"); 01812 const ParserRow<ParserDummy> stop_backup_reply[] = { 01813 MGM_CMD("abort backup reply", NULL, ""), 01814 MGM_ARG("result", String, Mandatory, "Error message"), 01815 MGM_END() 01816 }; 01817 CHECK_HANDLE(handle, -1); 01818 CHECK_CONNECTED(handle, -1); 01819 01820 Properties args; 01821 args.put("id", backupId); 01822 01823 const Properties *prop; 01824 prop = ndb_mgm_call(handle, stop_backup_reply, "abort backup", &args); 01825 CHECK_REPLY(prop, -1); 01826 01827 const char * buf; 01828 prop->get("result", &buf); 01829 if(strcmp(buf,"Ok")!=0) { 01830 SET_ERROR(handle, NDB_MGM_COULD_NOT_ABORT_BACKUP, buf); 01831 delete prop; 01832 return -1; 01833 } 01834 01835 delete prop; 01836 return 0; 01837 } 01838 01839 extern "C" 01840 struct ndb_mgm_configuration * 01841 ndb_mgm_get_configuration(NdbMgmHandle handle, unsigned int version) { 01842 01843 CHECK_HANDLE(handle, 0); 01844 CHECK_CONNECTED(handle, 0); 01845 01846 Properties args; 01847 args.put("version", version); 01848 01849 const ParserRow<ParserDummy> reply[] = { 01850 MGM_CMD("get config reply", NULL, ""), 01851 MGM_ARG("result", String, Mandatory, "Error message"), 01852 MGM_ARG("Content-Length", Int, Optional, "Content length in bytes"), 01853 MGM_ARG("Content-Type", String, Optional, "Type (octet-stream)"), 01854 MGM_ARG("Content-Transfer-Encoding", String, Optional, "Encoding(base64)"), 01855 MGM_END() 01856 }; 01857 01858 const Properties *prop; 01859 prop = ndb_mgm_call(handle, reply, "get config", &args); 01860 CHECK_REPLY(prop, 0); 01861 01862 do { 01863 const char * buf; 01864 if(!prop->get("result", &buf) || strcmp(buf, "Ok") != 0){ 01865 fprintf(handle->errstream, "ERROR Message: %s\n\n", buf); 01866 break; 01867 } 01868 01869 buf = "<Unspecified>"; 01870 if(!prop->get("Content-Type", &buf) || 01871 strcmp(buf, "ndbconfig/octet-stream") != 0){ 01872 fprintf(handle->errstream, "Unhandled response type: %s\n", buf); 01873 break; 01874 } 01875 01876 buf = "<Unspecified>"; 01877 if(!prop->get("Content-Transfer-Encoding", &buf) 01878 || strcmp(buf, "base64") != 0){ 01879 fprintf(handle->errstream, "Unhandled encoding: %s\n", buf); 01880 break; 01881 } 01882 01883 buf = "<Content-Length Unspecified>"; 01884 Uint32 len = 0; 01885 if(!prop->get("Content-Length", &len)){ 01886 fprintf(handle->errstream, "Invalid response: %s\n\n", buf); 01887 break; 01888 } 01889 01890 len += 1; // Trailing \n 01891 01892 char* buf64 = new char[len]; 01893 int read = 0; 01894 size_t start = 0; 01895 do { 01896 if((read = read_socket(handle->socket, handle->read_timeout, 01897 &buf64[start], len-start)) == -1){ 01898 delete[] buf64; 01899 buf64 = 0; 01900 break; 01901 } 01902 start += read; 01903 } while(start < len); 01904 if(buf64 == 0) 01905 break; 01906 01907 void *tmp_data = malloc(base64_needed_decoded_length((size_t) (len - 1))); 01908 const int res = base64_decode(buf64, len-1, tmp_data); 01909 delete[] buf64; 01910 UtilBuffer tmp; 01911 tmp.append((void *) tmp_data, res); 01912 free(tmp_data); 01913 if (res < 0) 01914 { 01915 fprintf(handle->errstream, "Failed to decode buffer\n"); 01916 break; 01917 } 01918 01919 ConfigValuesFactory cvf; 01920 const int res2 = cvf.unpack(tmp); 01921 if(!res2){ 01922 fprintf(handle->errstream, "Failed to unpack buffer\n"); 01923 break; 01924 } 01925 01926 delete prop; 01927 return (ndb_mgm_configuration*)cvf.getConfigValues(); 01928 } while(0); 01929 01930 delete prop; 01931 return 0; 01932 } 01933 01934 extern "C" 01935 void 01936 ndb_mgm_destroy_configuration(struct ndb_mgm_configuration *cfg) 01937 { 01938 if (cfg) { 01939 ((ConfigValues *)cfg)->~ConfigValues(); 01940 free((void *)cfg); 01941 } 01942 } 01943 01944 extern "C" 01945 int 01946 ndb_mgm_set_configuration_nodeid(NdbMgmHandle handle, int nodeid) 01947 { 01948 CHECK_HANDLE(handle, -1); 01949 handle->cfg._ownNodeId= nodeid; 01950 return 0; 01951 } 01952 01953 extern "C" 01954 int 01955 ndb_mgm_get_configuration_nodeid(NdbMgmHandle handle) 01956 { 01957 CHECK_HANDLE(handle, 0); 01958 return handle->cfg._ownNodeId; 01959 } 01960 01961 extern "C" 01962 int ndb_mgm_get_connected_port(NdbMgmHandle handle) 01963 { 01964 if (handle->cfg_i >= 0) 01965 return handle->cfg.ids[handle->cfg_i].port; 01966 else 01967 return 0; 01968 } 01969 01970 extern "C" 01971 const char *ndb_mgm_get_connected_host(NdbMgmHandle handle) 01972 { 01973 if (handle->cfg_i >= 0) 01974 return handle->cfg.ids[handle->cfg_i].name.c_str(); 01975 else 01976 return 0; 01977 } 01978 01979 extern "C" 01980 const char *ndb_mgm_get_connectstring(NdbMgmHandle handle, char *buf, int buf_sz) 01981 { 01982 return handle->cfg.makeConnectString(buf,buf_sz); 01983 } 01984 01985 extern "C" 01986 int 01987 ndb_mgm_alloc_nodeid(NdbMgmHandle handle, unsigned int version, int nodetype, 01988 int log_event) 01989 { 01990 CHECK_HANDLE(handle, 0); 01991 CHECK_CONNECTED(handle, 0); 01992 union { long l; char c[sizeof(long)]; } endian_check; 01993 01994 endian_check.l = 1; 01995 01996 int nodeid= handle->cfg._ownNodeId; 01997 01998 Properties args; 01999 args.put("version", version); 02000 args.put("nodetype", nodetype); 02001 args.put("nodeid", nodeid); 02002 args.put("user", "mysqld"); 02003 args.put("password", "mysqld"); 02004 args.put("public key", "a public key"); 02005 args.put("endian", (endian_check.c[sizeof(long)-1])?"big":"little"); 02006 if (handle->m_name) 02007 args.put("name", handle->m_name); 02008 args.put("log_event", log_event); 02009 02010 const ParserRow<ParserDummy> reply[]= { 02011 MGM_CMD("get nodeid reply", NULL, ""), 02012 MGM_ARG("error_code", Int, Optional, "Error code"), 02013 MGM_ARG("nodeid", Int, Optional, "Error message"), 02014 MGM_ARG("result", String, Mandatory, "Error message"), 02015 MGM_END() 02016 }; 02017 02018 const Properties *prop; 02019 prop= ndb_mgm_call(handle, reply, "get nodeid", &args); 02020 CHECK_REPLY(prop, -1); 02021 02022 nodeid= -1; 02023 do { 02024 const char * buf; 02025 if (!prop->get("result", &buf) || strcmp(buf, "Ok") != 0) 02026 { 02027 const char *hostname= ndb_mgm_get_connected_host(handle); 02028 unsigned port= ndb_mgm_get_connected_port(handle); 02029 BaseString err; 02030 Uint32 error_code= NDB_MGM_ALLOCID_ERROR; 02031 err.assfmt("Could not alloc node id at %s port %d: %s", 02032 hostname, port, buf); 02033 prop->get("error_code", &error_code); 02034 setError(handle, error_code, __LINE__, err.c_str()); 02035 break; 02036 } 02037 Uint32 _nodeid; 02038 if(!prop->get("nodeid", &_nodeid) != 0){ 02039 fprintf(handle->errstream, "ERROR Message: <nodeid Unspecified>\n"); 02040 break; 02041 } 02042 nodeid= _nodeid; 02043 }while(0); 02044 02045 delete prop; 02046 return nodeid; 02047 } 02048 02049 /***************************************************************************** 02050 * Global Replication 02051 ******************************************************************************/ 02052 extern "C" 02053 int 02054 ndb_mgm_rep_command(NdbMgmHandle handle, unsigned int request, 02055 unsigned int* replication_id, 02056 struct ndb_mgm_reply* /*reply*/) 02057 { 02058 SET_ERROR(handle, NDB_MGM_NO_ERROR, "Executing: ndb_mgm_rep_command"); 02059 const ParserRow<ParserDummy> replication_reply[] = { 02060 MGM_CMD("global replication reply", NULL, ""), 02061 MGM_ARG("result", String, Mandatory, "Error message"), 02062 MGM_ARG("id", Int, Optional, "Id of global replication"), 02063 MGM_END() 02064 }; 02065 CHECK_HANDLE(handle, -1); 02066 CHECK_CONNECTED(handle, -1); 02067 02068 Properties args; 02069 args.put("request", request); 02070 const Properties *reply; 02071 reply = ndb_mgm_call(handle, replication_reply, "rep", &args); 02072 CHECK_REPLY(reply, -1); 02073 02074 const char * result; 02075 reply->get("result", &result); 02076 reply->get("id", replication_id); 02077 if(strcmp(result,"Ok")!=0) { 02078 delete reply; 02079 return -1; 02080 } 02081 02082 delete reply; 02083 return 0; 02084 } 02085 02086 extern "C" 02087 int 02088 ndb_mgm_set_int_parameter(NdbMgmHandle handle, 02089 int node, 02090 int param, 02091 unsigned value, 02092 struct ndb_mgm_reply*){ 02093 CHECK_HANDLE(handle, 0); 02094 CHECK_CONNECTED(handle, 0); 02095 02096 Properties args; 02097 args.put("node", node); 02098 args.put("param", param); 02099 args.put("value", value); 02100 02101 const ParserRow<ParserDummy> reply[]= { 02102 MGM_CMD("set parameter reply", NULL, ""), 02103 MGM_ARG("result", String, Mandatory, "Error message"), 02104 MGM_END() 02105 }; 02106 02107 const Properties *prop; 02108 prop= ndb_mgm_call(handle, reply, "set parameter", &args); 02109 CHECK_REPLY(prop, -1); 02110 02111 int res= -1; 02112 do { 02113 const char * buf; 02114 if(!prop->get("result", &buf) || strcmp(buf, "Ok") != 0){ 02115 fprintf(handle->errstream, "ERROR Message: %s\n", buf); 02116 break; 02117 } 02118 res= 0; 02119 } while(0); 02120 02121 delete prop; 02122 return res; 02123 } 02124 02125 extern "C" 02126 int 02127 ndb_mgm_set_int64_parameter(NdbMgmHandle handle, 02128 int node, 02129 int param, 02130 unsigned long long value, 02131 struct ndb_mgm_reply*){ 02132 CHECK_HANDLE(handle, 0); 02133 CHECK_CONNECTED(handle, 0); 02134 02135 Properties args; 02136 args.put("node", node); 02137 args.put("param", param); 02138 args.put("value", value); 02139 02140 const ParserRow<ParserDummy> reply[]= { 02141 MGM_CMD("set parameter reply", NULL, ""), 02142 MGM_ARG("result", String, Mandatory, "Error message"), 02143 MGM_END() 02144 }; 02145 02146 const Properties *prop; 02147 prop= ndb_mgm_call(handle, reply, "set parameter", &args); 02148 02149 if(prop == NULL) { 02150 SET_ERROR(handle, EIO, "Unable set parameter"); 02151 return -1; 02152 } 02153 02154 int res= -1; 02155 do { 02156 const char * buf; 02157 if(!prop->get("result", &buf) || strcmp(buf, "Ok") != 0){ 02158 fprintf(handle->errstream, "ERROR Message: %s\n", buf); 02159 break; 02160 } 02161 res= 0; 02162 } while(0); 02163 02164 delete prop; 02165 return res; 02166 } 02167 02168 extern "C" 02169 int 02170 ndb_mgm_set_string_parameter(NdbMgmHandle handle, 02171 int node, 02172 int param, 02173 const char * value, 02174 struct ndb_mgm_reply*){ 02175 CHECK_HANDLE(handle, 0); 02176 CHECK_CONNECTED(handle, 0); 02177 02178 Properties args; 02179 args.put("node", node); 02180 args.put("parameter", param); 02181 args.put("value", value); 02182 02183 const ParserRow<ParserDummy> reply[]= { 02184 MGM_CMD("set parameter reply", NULL, ""), 02185 MGM_ARG("result", String, Mandatory, "Error message"), 02186 MGM_END() 02187 }; 02188 02189 const Properties *prop; 02190 prop= ndb_mgm_call(handle, reply, "set parameter", &args); 02191 02192 if(prop == NULL) { 02193 SET_ERROR(handle, EIO, "Unable set parameter"); 02194 return -1; 02195 } 02196 02197 int res= -1; 02198 do { 02199 const char * buf; 02200 if(!prop->get("result", &buf) || strcmp(buf, "Ok") != 0){ 02201 fprintf(handle->errstream, "ERROR Message: %s\n", buf); 02202 break; 02203 } 02204 res= 0; 02205 } while(0); 02206 02207 delete prop; 02208 return res; 02209 } 02210 02211 extern "C" 02212 int 02213 ndb_mgm_purge_stale_sessions(NdbMgmHandle handle, char **purged){ 02214 CHECK_HANDLE(handle, 0); 02215 CHECK_CONNECTED(handle, 0); 02216 02217 Properties args; 02218 02219 const ParserRow<ParserDummy> reply[]= { 02220 MGM_CMD("purge stale sessions reply", NULL, ""), 02221 MGM_ARG("purged", String, Optional, ""), 02222 MGM_ARG("result", String, Mandatory, "Error message"), 02223 MGM_END() 02224 }; 02225 02226 const Properties *prop; 02227 prop= ndb_mgm_call(handle, reply, "purge stale sessions", &args); 02228 02229 if(prop == NULL) { 02230 SET_ERROR(handle, EIO, "Unable to purge stale sessions"); 02231 return -1; 02232 } 02233 02234 int res= -1; 02235 do { 02236 const char * buf; 02237 if(!prop->get("result", &buf) || strcmp(buf, "Ok") != 0){ 02238 fprintf(handle->errstream, "ERROR Message: %s\n", buf); 02239 break; 02240 } 02241 if (purged) { 02242 if (prop->get("purged", &buf)) 02243 *purged= strdup(buf); 02244 else 02245 *purged= 0; 02246 } 02247 res= 0; 02248 } while(0); 02249 delete prop; 02250 return res; 02251 } 02252 02253 extern "C" 02254 int 02255 ndb_mgm_check_connection(NdbMgmHandle handle){ 02256 CHECK_HANDLE(handle, 0); 02257 CHECK_CONNECTED(handle, 0); 02258 SocketOutputStream out(handle->socket); 02259 SocketInputStream in(handle->socket, handle->read_timeout); 02260 char buf[32]; 02261 02262 if (out.println("check connection")) 02263 goto ndb_mgm_check_connection_error; 02264 02265 if (out.println("")) 02266 goto ndb_mgm_check_connection_error; 02267 02268 in.gets(buf, sizeof(buf)); 02269 if(strcmp("check connection reply\n", buf)) 02270 goto ndb_mgm_check_connection_error; 02271 02272 in.gets(buf, sizeof(buf)); 02273 if(strcmp("result: Ok\n", buf)) 02274 goto ndb_mgm_check_connection_error; 02275 02276 in.gets(buf, sizeof(buf)); 02277 if(strcmp("\n", buf)) 02278 goto ndb_mgm_check_connection_error; 02279 02280 return 0; 02281 02282 ndb_mgm_check_connection_error: 02283 ndb_mgm_disconnect(handle); 02284 return -1; 02285 } 02286 02287 extern "C" 02288 int 02289 ndb_mgm_set_connection_int_parameter(NdbMgmHandle handle, 02290 int node1, 02291 int node2, 02292 int param, 02293 int value, 02294 struct ndb_mgm_reply* mgmreply){ 02295 CHECK_HANDLE(handle, 0); 02296 CHECK_CONNECTED(handle, 0); 02297 DBUG_ENTER("ndb_mgm_set_connection_int_parameter"); 02298 02299 Properties args; 02300 args.put("node1", node1); 02301 args.put("node2", node2); 02302 args.put("param", param); 02303 args.put("value", (Uint32)value); 02304 02305 const ParserRow<ParserDummy> reply[]= { 02306 MGM_CMD("set connection parameter reply", NULL, ""), 02307 MGM_ARG("message", String, Mandatory, "Error Message"), 02308 MGM_ARG("result", String, Mandatory, "Status Result"), 02309 MGM_END() 02310 }; 02311 02312 const Properties *prop; 02313 prop= ndb_mgm_call(handle, reply, "set connection parameter", &args); 02314 DBUG_CHECK_REPLY(prop, -1); 02315 02316 int res= -1; 02317 do { 02318 const char * buf; 02319 if(!prop->get("result", &buf) || strcmp(buf, "Ok") != 0){ 02320 fprintf(handle->errstream, "ERROR Message: %s\n", buf); 02321 break; 02322 } 02323 res= 0; 02324 } while(0); 02325 02326 delete prop; 02327 DBUG_RETURN(res); 02328 } 02329 02330 extern "C" 02331 int 02332 ndb_mgm_get_connection_int_parameter(NdbMgmHandle handle, 02333 int node1, 02334 int node2, 02335 int param, 02336 int *value, 02337 struct ndb_mgm_reply* mgmreply){ 02338 CHECK_HANDLE(handle, -1); 02339 CHECK_CONNECTED(handle, -2); 02340 DBUG_ENTER("ndb_mgm_get_connection_int_parameter"); 02341 02342 Properties args; 02343 args.put("node1", node1); 02344 args.put("node2", node2); 02345 args.put("param", param); 02346 02347 const ParserRow<ParserDummy> reply[]= { 02348 MGM_CMD("get connection parameter reply", NULL, ""), 02349 MGM_ARG("value", Int, Mandatory, "Current Value"), 02350 MGM_ARG("result", String, Mandatory, "Result"), 02351 MGM_END() 02352 }; 02353 02354 const Properties *prop; 02355 prop = ndb_mgm_call(handle, reply, "get connection parameter", &args); 02356 DBUG_CHECK_REPLY(prop, -3); 02357 02358 int res= -1; 02359 do { 02360 const char * buf; 02361 if(!prop->get("result", &buf) || strcmp(buf, "Ok") != 0){ 02362 fprintf(handle->errstream, "ERROR Message: %s\n", buf); 02363 break; 02364 } 02365 res= 0; 02366 } while(0); 02367 02368 if(!prop->get("value",(Uint32*)value)){ 02369 fprintf(handle->errstream, "Unable to get value\n"); 02370 res = -4; 02371 } 02372 02373 delete prop; 02374 DBUG_RETURN(res); 02375 } 02376 02377 extern "C" 02378 NDB_SOCKET_TYPE 02379 ndb_mgm_convert_to_transporter(NdbMgmHandle *handle) 02380 { 02381 NDB_SOCKET_TYPE s; 02382 02383 CHECK_HANDLE((*handle), NDB_INVALID_SOCKET); 02384 CHECK_CONNECTED((*handle), NDB_INVALID_SOCKET); 02385 02386 (*handle)->connected= 0; // we pretend we're disconnected 02387 s= (*handle)->socket; 02388 02389 SocketOutputStream s_output(s); 02390 s_output.println("transporter connect"); 02391 s_output.println(""); 02392 02393 ndb_mgm_destroy_handle(handle); // set connected=0, so won't disconnect 02394 02395 return s; 02396 } 02397 02398 extern "C" 02399 Uint32 02400 ndb_mgm_get_mgmd_nodeid(NdbMgmHandle handle) 02401 { 02402 Uint32 nodeid=0; 02403 02404 CHECK_HANDLE(handle, 0); 02405 CHECK_CONNECTED(handle, 0); 02406 DBUG_ENTER("ndb_mgm_get_mgmd_nodeid"); 02407 02408 Properties args; 02409 02410 const ParserRow<ParserDummy> reply[]= { 02411 MGM_CMD("get mgmd nodeid reply", NULL, ""), 02412 MGM_ARG("nodeid", Int, Mandatory, "Node ID"), 02413 MGM_END() 02414 }; 02415 02416 const Properties *prop; 02417 prop = ndb_mgm_call(handle, reply, "get mgmd nodeid", &args); 02418 DBUG_CHECK_REPLY(prop, 0); 02419 02420 if(!prop->get("nodeid",&nodeid)){ 02421 fprintf(handle->errstream, "Unable to get value\n"); 02422 return 0; 02423 } 02424 02425 delete prop; 02426 DBUG_RETURN(nodeid); 02427 } 02428 02429 extern "C" 02430 int ndb_mgm_report_event(NdbMgmHandle handle, Uint32 *data, Uint32 length) 02431 { 02432 CHECK_HANDLE(handle, 0); 02433 CHECK_CONNECTED(handle, 0); 02434 DBUG_ENTER("ndb_mgm_report_event"); 02435 02436 Properties args; 02437 args.put("length", length); 02438 BaseString data_string; 02439 02440 for (int i = 0; i < length; i++) 02441 data_string.appfmt(" %u", data[i]); 02442 02443 args.put("data", data_string.c_str()); 02444 02445 const ParserRow<ParserDummy> reply[]= { 02446 MGM_CMD("report event reply", NULL, ""), 02447 MGM_ARG("result", String, Mandatory, "Result"), 02448 MGM_END() 02449 }; 02450 02451 const Properties *prop; 02452 prop = ndb_mgm_call(handle, reply, "report event", &args); 02453 DBUG_CHECK_REPLY(prop, -1); 02454 02455 DBUG_RETURN(0); 02456 } 02457 02458 extern "C" 02459 int ndb_mgm_end_session(NdbMgmHandle handle) 02460 { 02461 CHECK_HANDLE(handle, 0); 02462 CHECK_CONNECTED(handle, 0); 02463 DBUG_ENTER("ndb_mgm_end_session"); 02464 02465 SocketOutputStream s_output(handle->socket); 02466 s_output.println("end session"); 02467 s_output.println(""); 02468 02469 SocketInputStream in(handle->socket, handle->read_timeout); 02470 char buf[32]; 02471 02472 in.gets(buf, sizeof(buf)); 02473 02474 DBUG_RETURN(0); 02475 } 02476 02477 extern "C" 02478 int ndb_mgm_get_version(NdbMgmHandle handle, 02479 int *major, int *minor, int *build, int len, char* str) 02480 { 02481 DBUG_ENTER("ndb_mgm_get_version"); 02482 CHECK_HANDLE(handle, 0); 02483 CHECK_CONNECTED(handle, 0); 02484 02485 Properties args; 02486 02487 const ParserRow<ParserDummy> reply[]= { 02488 MGM_CMD("version", NULL, ""), 02489 MGM_ARG("id", Int, Mandatory, "ID"), 02490 MGM_ARG("major", Int, Mandatory, "Major"), 02491 MGM_ARG("minor", Int, Mandatory, "Minor"), 02492 MGM_ARG("string", String, Mandatory, "String"), 02493 MGM_END() 02494 }; 02495 02496 const Properties *prop; 02497 prop = ndb_mgm_call(handle, reply, "get version", &args); 02498 CHECK_REPLY(prop, 0); 02499 02500 Uint32 id; 02501 if(!prop->get("id",&id)){ 02502 fprintf(handle->errstream, "Unable to get value\n"); 02503 return 0; 02504 } 02505 *build= getBuild(id); 02506 02507 if(!prop->get("major",(Uint32*)major)){ 02508 fprintf(handle->errstream, "Unable to get value\n"); 02509 return 0; 02510 } 02511 02512 if(!prop->get("minor",(Uint32*)minor)){ 02513 fprintf(handle->errstream, "Unable to get value\n"); 02514 return 0; 02515 } 02516 02517 BaseString result; 02518 if(!prop->get("string", result)){ 02519 fprintf(handle->errstream, "Unable to get value\n"); 02520 return 0; 02521 } 02522 02523 strncpy(str, result.c_str(), len); 02524 02525 delete prop; 02526 DBUG_RETURN(1); 02527 } 02528 02529 template class Vector<const ParserRow<ParserDummy>*>;
1.4.7

