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 #include <Vector.hpp> 00020 #include <mgmapi.h> 00021 #include <util/BaseString.hpp> 00022 00023 class MgmtSrvr; 00024 00035 class CommandInterpreter { 00036 public: 00041 CommandInterpreter(const char *, int verbose); 00042 ~CommandInterpreter(); 00043 00051 int execute(const char *_line, int _try_reconnect=-1, int *error= 0); 00052 00053 private: 00054 void printError(); 00055 int execute_impl(const char *_line); 00056 00065 void analyseAfterFirstToken(int processId, char* allAfterFirstTokenCstr); 00066 00067 void executeCommand(Vector<BaseString> &command_list, 00068 unsigned command_pos, 00069 int *node_ids, int no_of_nodes); 00079 bool parseBlockSpecification(const char* allAfterLog, 00080 Vector<const char*>& blocks); 00081 00093 void executeHelp(char* parameters); 00094 void executeShow(char* parameters); 00095 void executeConnect(char* parameters); 00096 void executePurge(char* parameters); 00097 int executeShutdown(char* parameters); 00098 void executeRun(char* parameters); 00099 void executeInfo(char* parameters); 00100 void executeClusterLog(char* parameters); 00101 00102 public: 00103 void executeStop(int processId, const char* parameters, bool all); 00104 void executeStop(Vector<BaseString> &command_list, unsigned command_pos, 00105 int *node_ids, int no_of_nodes); 00106 void executeEnterSingleUser(char* parameters); 00107 void executeExitSingleUser(char* parameters); 00108 void executeStart(int processId, const char* parameters, bool all); 00109 void executeRestart(int processId, const char* parameters, bool all); 00110 void executeRestart(Vector<BaseString> &command_list, unsigned command_pos, 00111 int *node_ids, int no_of_nodes); 00112 void executeLogLevel(int processId, const char* parameters, bool all); 00113 void executeError(int processId, const char* parameters, bool all); 00114 void executeLog(int processId, const char* parameters, bool all); 00115 void executeLogIn(int processId, const char* parameters, bool all); 00116 void executeLogOut(int processId, const char* parameters, bool all); 00117 void executeLogOff(int processId, const char* parameters, bool all); 00118 void executeTestOn(int processId, const char* parameters, bool all); 00119 void executeTestOff(int processId, const char* parameters, bool all); 00120 void executeSet(int processId, const char* parameters, bool all); 00121 void executeGetStat(int processId, const char* parameters, bool all); 00122 void executeStatus(int processId, const char* parameters, bool all); 00123 void executeEventReporting(int processId, const char* parameters, bool all); 00124 void executeDumpState(int processId, const char* parameters, bool all); 00125 int executeStartBackup(char * parameters); 00126 void executeAbortBackup(char * parameters); 00127 00128 void executeRep(char* parameters); 00129 00130 void executeCpc(char * parameters); 00131 00132 public: 00133 bool connect(); 00134 bool disconnect(); 00135 00139 public: 00140 typedef void (CommandInterpreter::* ExecuteFunction)(int processId, 00141 const char * param, 00142 bool all); 00143 00144 struct CommandFunctionPair { 00145 const char * command; 00146 ExecuteFunction executeFunction; 00147 }; 00148 private: 00152 void executeForAll(const char * cmd, 00153 ExecuteFunction fun, 00154 const char * param); 00155 00156 NdbMgmHandle m_mgmsrv; 00157 NdbMgmHandle m_mgmsrv2; 00158 const char *m_constr; 00159 bool m_connected; 00160 int m_verbose; 00161 int try_reconnect; 00162 int m_error; 00163 struct NdbThread* m_event_thread; 00164 }; 00165 00166 00167 /* 00168 * Facade object for CommandInterpreter 00169 */ 00170 00171 #include "ndb_mgmclient.hpp" 00172 #include "ndb_mgmclient.h" 00173 00174 Ndb_mgmclient::Ndb_mgmclient(const char *host,int verbose) 00175 { 00176 m_cmd= new CommandInterpreter(host,verbose); 00177 } 00178 Ndb_mgmclient::~Ndb_mgmclient() 00179 { 00180 delete m_cmd; 00181 } 00182 int Ndb_mgmclient::execute(const char *_line, int _try_reconnect, int *error) 00183 { 00184 return m_cmd->execute(_line,_try_reconnect,error); 00185 } 00186 int 00187 Ndb_mgmclient::disconnect() 00188 { 00189 return m_cmd->disconnect(); 00190 } 00191 00192 extern "C" { 00193 Ndb_mgmclient_handle ndb_mgmclient_handle_create(const char *connect_string) 00194 { 00195 return (Ndb_mgmclient_handle) new Ndb_mgmclient(connect_string); 00196 } 00197 int ndb_mgmclient_execute(Ndb_mgmclient_handle h, int argc, char** argv) 00198 { 00199 return ((Ndb_mgmclient*)h)->execute(argc, argv, 1); 00200 } 00201 int ndb_mgmclient_handle_destroy(Ndb_mgmclient_handle h) 00202 { 00203 delete (Ndb_mgmclient*)h; 00204 return 0; 00205 } 00206 } 00207 /* 00208 * The CommandInterpreter 00209 */ 00210 00211 #include <mgmapi.h> 00212 #include <mgmapi_debug.h> 00213 #include <version.h> 00214 #include <NdbAutoPtr.hpp> 00215 #include <NdbOut.hpp> 00216 #include <NdbSleep.h> 00217 #include <NdbMem.h> 00218 #include <EventLogger.hpp> 00219 #include <signaldata/SetLogLevelOrd.hpp> 00220 #include "MgmtErrorReporter.hpp" 00221 #include <Parser.hpp> 00222 #include <SocketServer.hpp> 00223 #include <util/InputStream.hpp> 00224 #include <util/OutputStream.hpp> 00225 00226 int Ndb_mgmclient::execute(int argc, char** argv, int _try_reconnect, int *error) 00227 { 00228 if (argc <= 0) 00229 return 0; 00230 BaseString _line(argv[0]); 00231 for (int i= 1; i < argc; i++) 00232 { 00233 _line.appfmt(" %s", argv[i]); 00234 } 00235 return m_cmd->execute(_line.c_str(),_try_reconnect, error); 00236 } 00237 00238 /***************************************************************************** 00239 * HELP 00240 *****************************************************************************/ 00241 static const char* helpText = 00242 "---------------------------------------------------------------------------\n" 00243 " NDB Cluster -- Management Client -- Help\n" 00244 "---------------------------------------------------------------------------\n" 00245 "HELP Print help text\n" 00246 "HELP SHOW Help for SHOW command\n" 00247 #ifdef VM_TRACE // DEBUG ONLY 00248 "HELP DEBUG Help for debug compiled version\n" 00249 #endif 00250 "SHOW Print information about cluster\n" 00251 #if 0 00252 "SHOW CONFIG Print configuration\n" 00253 "SHOW PARAMETERS Print configuration parameters\n" 00254 #endif 00255 "START BACKUP [NOWAIT | WAIT STARTED | WAIT COMPLETED]\n" 00256 " Start backup (default WAIT COMPLETED)\n" 00257 "ABORT BACKUP <backup id> Abort backup\n" 00258 "SHUTDOWN Shutdown all processes in cluster\n" 00259 "CLUSTERLOG ON [<severity>] ... Enable Cluster logging\n" 00260 "CLUSTERLOG OFF [<severity>] ... Disable Cluster logging\n" 00261 "CLUSTERLOG TOGGLE [<severity>] ... Toggle severity filter on/off\n" 00262 "CLUSTERLOG INFO Print cluster log information\n" 00263 "<id> START Start DB node (started with -n)\n" 00264 "<id> RESTART [-n] [-i] Restart DB node\n" 00265 "<id> STOP Stop DB node\n" 00266 "ENTER SINGLE USER MODE <api-node> Enter single user mode\n" 00267 "EXIT SINGLE USER MODE Exit single user mode\n" 00268 "<id> STATUS Print status\n" 00269 "<id> CLUSTERLOG {<category>=<level>}+ Set log level for cluster log\n" 00270 "PURGE STALE SESSIONS Reset reserved nodeid's in the mgmt server\n" 00271 "CONNECT [<connectstring>] Connect to management server (reconnect if already connected)\n" 00272 "QUIT Quit management client\n" 00273 ; 00274 00275 static const char* helpTextShow = 00276 "---------------------------------------------------------------------------\n" 00277 " NDB Cluster -- Management Client -- Help for SHOW command\n" 00278 "---------------------------------------------------------------------------\n" 00279 "SHOW prints NDB Cluster information\n\n" 00280 "SHOW Print information about cluster\n" 00281 #if 0 00282 "SHOW CONFIG Print configuration (in initial config file format)\n" 00283 "SHOW PARAMETERS Print information about configuration parameters\n\n" 00284 #endif 00285 ; 00286 00287 #ifdef VM_TRACE // DEBUG ONLY 00288 static const char* helpTextDebug = 00289 "---------------------------------------------------------------------------\n" 00290 " NDB Cluster -- Management Client -- Help for Debugging (Internal use only)\n" 00291 "---------------------------------------------------------------------------\n" 00292 "SHOW PROPERTIES Print config properties object\n" 00293 "<id> LOGLEVEL {<category>=<level>}+ Set log level\n" 00294 #ifdef ERROR_INSERT 00295 "<id> ERROR <errorNo> Inject error into NDB node\n" 00296 #endif 00297 "<id> LOG [BLOCK = {ALL|<block>+}] Set logging on in & out signals\n" 00298 "<id> LOGIN [BLOCK = {ALL|<block>+}] Set logging on in signals\n" 00299 "<id> LOGOUT [BLOCK = {ALL|<block>+}] Set logging on out signals\n" 00300 "<id> LOGOFF [BLOCK = {ALL|<block>+}] Unset signal logging\n" 00301 "<id> TESTON Start signal logging\n" 00302 "<id> TESTOFF Stop signal logging\n" 00303 "<id> SET <configParamName> <value> Update configuration variable\n" 00304 "<id> DUMP <arg> Dump system state to cluster.log\n" 00305 "<id> GETSTAT Print statistics\n" 00306 "\n" 00307 "<id> = ALL | Any database node id\n" 00308 ; 00309 #endif 00310 00311 static bool 00312 convert(const char* s, int& val) { 00313 00314 if (s == NULL) 00315 return false; 00316 00317 if (strlen(s) == 0) 00318 return false; 00319 00320 errno = 0; 00321 char* p; 00322 long v = strtol(s, &p, 10); 00323 if (errno != 0) 00324 return false; 00325 00326 if (p != &s[strlen(s)]) 00327 return false; 00328 00329 val = v; 00330 return true; 00331 } 00332 00333 /* 00334 * Constructor 00335 */ 00336 CommandInterpreter::CommandInterpreter(const char *_host,int verbose) 00337 : m_verbose(verbose) 00338 { 00339 m_constr= _host; 00340 m_connected= false; 00341 m_event_thread= 0; 00342 try_reconnect = 0; 00343 } 00344 00345 /* 00346 * Destructor 00347 */ 00348 CommandInterpreter::~CommandInterpreter() 00349 { 00350 disconnect(); 00351 } 00352 00353 static bool 00354 emptyString(const char* s) 00355 { 00356 if (s == NULL) { 00357 return true; 00358 } 00359 00360 for (unsigned int i = 0; i < strlen(s); ++i) { 00361 if (! isspace(s[i])) { 00362 return false; 00363 } 00364 } 00365 00366 return true; 00367 } 00368 00369 void 00370 CommandInterpreter::printError() 00371 { 00372 ndbout_c("* %5d: %s", 00373 ndb_mgm_get_latest_error(m_mgmsrv), 00374 ndb_mgm_get_latest_error_msg(m_mgmsrv)); 00375 ndbout_c("* %s", ndb_mgm_get_latest_error_desc(m_mgmsrv)); 00376 if (ndb_mgm_check_connection(m_mgmsrv)) 00377 { 00378 disconnect(); 00379 } 00380 } 00381 00382 //***************************************************************************** 00383 //***************************************************************************** 00384 00385 static int do_event_thread; 00386 static void* 00387 event_thread_run(void* m) 00388 { 00389 DBUG_ENTER("event_thread_run"); 00390 00391 NdbMgmHandle handle= *(NdbMgmHandle*)m; 00392 00393 int filter[] = { 15, NDB_MGM_EVENT_CATEGORY_BACKUP, 00394 1, NDB_MGM_EVENT_CATEGORY_STARTUP, 00395 0 }; 00396 int fd = ndb_mgm_listen_event(handle, filter); 00397 if (fd != NDB_INVALID_SOCKET) 00398 { 00399 do_event_thread= 1; 00400 char *tmp= 0; 00401 char buf[1024]; 00402 SocketInputStream in(fd,10); 00403 do { 00404 if (tmp == 0) NdbSleep_MilliSleep(10); 00405 if((tmp = in.gets(buf, 1024))) 00406 { 00407 const char ping_token[]= "<PING>"; 00408 if (memcmp(ping_token,tmp,sizeof(ping_token)-1)) 00409 ndbout << tmp; 00410 } 00411 } while(do_event_thread); 00412 NDB_CLOSE_SOCKET(fd); 00413 } 00414 else 00415 { 00416 do_event_thread= -1; 00417 } 00418 00419 DBUG_RETURN(NULL); 00420 } 00421 00422 bool 00423 CommandInterpreter::connect() 00424 { 00425 DBUG_ENTER("CommandInterpreter::connect"); 00426 00427 if(m_connected) 00428 DBUG_RETURN(m_connected); 00429 00430 m_mgmsrv = ndb_mgm_create_handle(); 00431 if(m_mgmsrv == NULL) { 00432 ndbout_c("Cannot create handle to management server."); 00433 exit(-1); 00434 } 00435 m_mgmsrv2 = ndb_mgm_create_handle(); 00436 if(m_mgmsrv2 == NULL) { 00437 ndbout_c("Cannot create 2:nd handle to management server."); 00438 exit(-1); 00439 } 00440 00441 if (ndb_mgm_set_connectstring(m_mgmsrv, m_constr)) 00442 { 00443 printError(); 00444 exit(-1); 00445 } 00446 00447 if(ndb_mgm_connect(m_mgmsrv, try_reconnect-1, 5, 1)) 00448 DBUG_RETURN(m_connected); // couldn't connect, always false 00449 00450 const char *host= ndb_mgm_get_connected_host(m_mgmsrv); 00451 unsigned port= ndb_mgm_get_connected_port(m_mgmsrv); 00452 BaseString constr; 00453 constr.assfmt("%s:%d",host,port); 00454 if(!ndb_mgm_set_connectstring(m_mgmsrv2, constr.c_str()) && 00455 !ndb_mgm_connect(m_mgmsrv2, try_reconnect-1, 5, 1)) 00456 { 00457 DBUG_PRINT("info",("2:ndb connected to Management Server ok at: %s:%d", 00458 host, port)); 00459 assert(m_event_thread == 0); 00460 assert(do_event_thread == 0); 00461 do_event_thread= 0; 00462 m_event_thread = NdbThread_Create(event_thread_run, 00463 (void**)&m_mgmsrv2, 00464 32768, 00465 "CommandInterpreted_event_thread", 00466 NDB_THREAD_PRIO_LOW); 00467 if (m_event_thread != 0) 00468 { 00469 DBUG_PRINT("info",("Thread created ok, waiting for started...")); 00470 int iter= 1000; // try for 30 seconds 00471 while(do_event_thread == 0 && 00472 iter-- > 0) 00473 NdbSleep_MilliSleep(30); 00474 } 00475 if (m_event_thread == 0 || 00476 do_event_thread == 0 || 00477 do_event_thread == -1) 00478 { 00479 DBUG_PRINT("info",("Warning, event thread startup failed, " 00480 "degraded printouts as result, errno=%d", 00481 errno)); 00482 printf("Warning, event thread startup failed, " 00483 "degraded printouts as result, errno=%d\n", errno); 00484 do_event_thread= 0; 00485 if (m_event_thread) 00486 { 00487 void *res; 00488 NdbThread_WaitFor(m_event_thread, &res); 00489 NdbThread_Destroy(&m_event_thread); 00490 } 00491 ndb_mgm_disconnect(m_mgmsrv2); 00492 } 00493 } 00494 else 00495 { 00496 DBUG_PRINT("warning", 00497 ("Could not do 2:nd connect to mgmtserver for event listening")); 00498 DBUG_PRINT("info", ("code: %d, msg: %s", 00499 ndb_mgm_get_latest_error(m_mgmsrv2), 00500 ndb_mgm_get_latest_error_msg(m_mgmsrv2))); 00501 printf("Warning, event connect failed, degraded printouts as result\n"); 00502 printf("code: %d, msg: %s\n", 00503 ndb_mgm_get_latest_error(m_mgmsrv2), 00504 ndb_mgm_get_latest_error_msg(m_mgmsrv2)); 00505 } 00506 m_connected= true; 00507 DBUG_PRINT("info",("Connected to Management Server at: %s:%d", host, port)); 00508 if (m_verbose) 00509 { 00510 printf("Connected to Management Server at: %s:%d\n", 00511 host, port); 00512 } 00513 00514 DBUG_RETURN(m_connected); 00515 } 00516 00517 bool 00518 CommandInterpreter::disconnect() 00519 { 00520 DBUG_ENTER("CommandInterpreter::disconnect"); 00521 00522 if (m_event_thread) { 00523 void *res; 00524 do_event_thread= 0; 00525 NdbThread_WaitFor(m_event_thread, &res); 00526 NdbThread_Destroy(&m_event_thread); 00527 m_event_thread= 0; 00528 ndb_mgm_destroy_handle(&m_mgmsrv2); 00529 } 00530 if (m_connected) 00531 { 00532 ndb_mgm_destroy_handle(&m_mgmsrv); 00533 m_connected= false; 00534 } 00535 DBUG_RETURN(true); 00536 } 00537 00538 //***************************************************************************** 00539 //***************************************************************************** 00540 00541 int 00542 CommandInterpreter::execute(const char *_line, int _try_reconnect, 00543 int *error) 00544 { 00545 if (_try_reconnect >= 0) 00546 try_reconnect=_try_reconnect; 00547 int result= execute_impl(_line); 00548 if (error) 00549 *error= m_error; 00550 return result; 00551 } 00552 00553 static void 00554 invalid_command(const char *cmd) 00555 { 00556 ndbout << "Invalid command: " << cmd << endl; 00557 ndbout << "Type HELP for help." << endl << endl; 00558 } 00559 00560 int 00561 CommandInterpreter::execute_impl(const char *_line) 00562 { 00563 DBUG_ENTER("CommandInterpreter::execute_impl"); 00564 DBUG_PRINT("enter",("line=\"%s\"",_line)); 00565 m_error= 0; 00566 00567 char * line; 00568 if(_line == NULL) { 00569 DBUG_RETURN(false); 00570 } 00571 line = my_strdup(_line,MYF(MY_WME)); 00572 My_auto_ptr<char> ptr(line); 00573 00574 int do_continue; 00575 do { 00576 do_continue= 0; 00577 BaseString::trim(line," \t"); 00578 if (line[0] == 0 || 00579 line[0] == '#') 00580 { 00581 DBUG_RETURN(true); 00582 } 00583 // for mysql client compatability remove trailing ';' 00584 { 00585 unsigned last= strlen(line)-1; 00586 if (line[last] == ';') 00587 { 00588 line[last]= 0; 00589 do_continue= 1; 00590 } 00591 } 00592 } while (do_continue); 00593 // if there is anything in the line proceed 00594 Vector<BaseString> command_list; 00595 { 00596 BaseString tmp(line); 00597 tmp.split(command_list); 00598 for (unsigned i= 0; i < command_list.size();) 00599 command_list[i].c_str()[0] ? i++ : (command_list.erase(i),0); 00600 } 00601 char* firstToken = strtok(line, " "); 00602 char* allAfterFirstToken = strtok(NULL, ""); 00603 00604 if (strcasecmp(firstToken, "HELP") == 0 || 00605 strcasecmp(firstToken, "?") == 0) { 00606 executeHelp(allAfterFirstToken); 00607 DBUG_RETURN(true); 00608 } 00609 else if (strcasecmp(firstToken, "CONNECT") == 0) { 00610 executeConnect(allAfterFirstToken); 00611 DBUG_RETURN(true); 00612 } 00613 else if (strcasecmp(firstToken, "SLEEP") == 0) { 00614 if (allAfterFirstToken) 00615 sleep(atoi(allAfterFirstToken)); 00616 DBUG_RETURN(true); 00617 } 00618 else if((strcasecmp(firstToken, "QUIT") == 0 || 00619 strcasecmp(firstToken, "EXIT") == 0 || 00620 strcasecmp(firstToken, "BYE") == 0) && 00621 allAfterFirstToken == NULL){ 00622 DBUG_RETURN(false); 00623 } 00624 00625 if (!connect()) 00626 DBUG_RETURN(true); 00627 00628 if (strcasecmp(firstToken, "SHOW") == 0) { 00629 executeShow(allAfterFirstToken); 00630 DBUG_RETURN(true); 00631 } 00632 else if (strcasecmp(firstToken, "SHUTDOWN") == 0) { 00633 m_error= executeShutdown(allAfterFirstToken); 00634 DBUG_RETURN(true); 00635 } 00636 else if (strcasecmp(firstToken, "CLUSTERLOG") == 0){ 00637 executeClusterLog(allAfterFirstToken); 00638 DBUG_RETURN(true); 00639 } 00640 else if(strcasecmp(firstToken, "START") == 0 && 00641 allAfterFirstToken != NULL && 00642 strncasecmp(allAfterFirstToken, "BACKUP", sizeof("BACKUP") - 1) == 0){ 00643 m_error= executeStartBackup(allAfterFirstToken); 00644 DBUG_RETURN(true); 00645 } 00646 else if(strcasecmp(firstToken, "ABORT") == 0 && 00647 allAfterFirstToken != NULL && 00648 strncasecmp(allAfterFirstToken, "BACKUP", sizeof("BACKUP") - 1) == 0){ 00649 executeAbortBackup(allAfterFirstToken); 00650 DBUG_RETURN(true); 00651 } 00652 else if (strcasecmp(firstToken, "PURGE") == 0) { 00653 executePurge(allAfterFirstToken); 00654 DBUG_RETURN(true); 00655 } 00656 else if(strcasecmp(firstToken, "ENTER") == 0 && 00657 allAfterFirstToken != NULL && 00658 strncasecmp(allAfterFirstToken, "SINGLE USER MODE ", 00659 sizeof("SINGLE USER MODE") - 1) == 0){ 00660 executeEnterSingleUser(allAfterFirstToken); 00661 DBUG_RETURN(true); 00662 } 00663 else if(strcasecmp(firstToken, "EXIT") == 0 && 00664 allAfterFirstToken != NULL && 00665 strncasecmp(allAfterFirstToken, "SINGLE USER MODE ", 00666 sizeof("SINGLE USER MODE") - 1) == 0){ 00667 executeExitSingleUser(allAfterFirstToken); 00668 DBUG_RETURN(true); 00669 } 00670 else if (strcasecmp(firstToken, "ALL") == 0) { 00671 analyseAfterFirstToken(-1, allAfterFirstToken); 00672 } else { 00676 int node_ids[MAX_NODES]; 00677 unsigned pos; 00678 for (pos= 0; pos < command_list.size(); pos++) 00679 { 00680 int node_id; 00681 if (convert(command_list[pos].c_str(), node_id)) 00682 { 00683 if (node_id <= 0) { 00684 ndbout << "Invalid node ID: " << command_list[pos].c_str() 00685 << "." << endl; 00686 DBUG_RETURN(true); 00687 } 00688 node_ids[pos]= node_id; 00689 continue; 00690 } 00691 break; 00692 } 00693 int no_of_nodes= pos; 00694 if (no_of_nodes == 0) 00695 { 00696 /* No digit found */ 00697 invalid_command(_line); 00698 DBUG_RETURN(true); 00699 } 00700 if (pos == command_list.size()) 00701 { 00702 /* No command found */ 00703 invalid_command(_line); 00704 DBUG_RETURN(true); 00705 } 00706 if (no_of_nodes == 1) 00707 { 00708 analyseAfterFirstToken(node_ids[0], allAfterFirstToken); 00709 DBUG_RETURN(true); 00710 } 00711 executeCommand(command_list, pos, node_ids, no_of_nodes); 00712 DBUG_RETURN(true); 00713 } 00714 DBUG_RETURN(true); 00715 } 00716 00717 00721 static const CommandInterpreter::CommandFunctionPair commands[] = { 00722 { "START", &CommandInterpreter::executeStart } 00723 ,{ "RESTART", &CommandInterpreter::executeRestart } 00724 ,{ "STOP", &CommandInterpreter::executeStop } 00725 ,{ "STATUS", &CommandInterpreter::executeStatus } 00726 ,{ "LOGLEVEL", &CommandInterpreter::executeLogLevel } 00727 ,{ "CLUSTERLOG", &CommandInterpreter::executeEventReporting } 00728 #ifdef ERROR_INSERT 00729 ,{ "ERROR", &CommandInterpreter::executeError } 00730 #endif 00731 ,{ "LOG", &CommandInterpreter::executeLog } 00732 ,{ "LOGIN", &CommandInterpreter::executeLogIn } 00733 ,{ "LOGOUT", &CommandInterpreter::executeLogOut } 00734 ,{ "LOGOFF", &CommandInterpreter::executeLogOff } 00735 ,{ "TESTON", &CommandInterpreter::executeTestOn } 00736 ,{ "TESTOFF", &CommandInterpreter::executeTestOff } 00737 ,{ "SET", &CommandInterpreter::executeSet } 00738 ,{ "GETSTAT", &CommandInterpreter::executeGetStat } 00739 ,{ "DUMP", &CommandInterpreter::executeDumpState } 00740 }; 00741 00742 00743 //***************************************************************************** 00744 //***************************************************************************** 00745 void 00746 CommandInterpreter::analyseAfterFirstToken(int processId, 00747 char* allAfterFirstToken) { 00748 00749 if (emptyString(allAfterFirstToken)) { 00750 ndbout << "Expected a command after " 00751 << ((processId == -1) ? "ALL." : "node ID.") << endl; 00752 return; 00753 } 00754 00755 char* secondToken = strtok(allAfterFirstToken, " "); 00756 char* allAfterSecondToken = strtok(NULL, "\0"); 00757 00758 const int tmpSize = sizeof(commands)/sizeof(CommandFunctionPair); 00759 ExecuteFunction fun = 0; 00760 const char * command = 0; 00761 for(int i = 0; i<tmpSize; i++){ 00762 if(strcasecmp(secondToken, commands[i].command) == 0){ 00763 fun = commands[i].executeFunction; 00764 command = commands[i].command; 00765 break; 00766 } 00767 } 00768 00769 if(fun == 0){ 00770 invalid_command(secondToken); 00771 return; 00772 } 00773 00774 if(processId == -1){ 00775 executeForAll(command, fun, allAfterSecondToken); 00776 } else { 00777 (this->*fun)(processId, allAfterSecondToken, false); 00778 } 00779 ndbout << endl; 00780 } 00781 00782 void 00783 CommandInterpreter::executeCommand(Vector<BaseString> &command_list, 00784 unsigned command_pos, 00785 int *node_ids, int no_of_nodes) 00786 { 00787 const char *cmd= command_list[command_pos].c_str(); 00788 if (strcasecmp("STOP", cmd) == 0) 00789 { 00790 executeStop(command_list, command_pos+1, node_ids, no_of_nodes); 00791 return; 00792 } 00793 if (strcasecmp("RESTART", cmd) == 0) 00794 { 00795 executeRestart(command_list, command_pos+1, node_ids, no_of_nodes); 00796 return; 00797 } 00798 ndbout_c("Invalid command: '%s' after multi node id list. " 00799 "Expected STOP or RESTART.", cmd); 00800 return; 00801 } 00802 00813 static 00814 int 00815 get_next_nodeid(struct ndb_mgm_cluster_state *cl, 00816 int *node_id, 00817 enum ndb_mgm_node_type type) 00818 { 00819 int i; 00820 00821 if(cl == NULL) 00822 return 0; 00823 00824 i=0; 00825 while((i < cl->no_of_nodes)) { 00826 if((*node_id < cl->node_states[i].node_id) && 00827 (cl->node_states[i].node_type == type)) { 00828 00829 if(i >= cl->no_of_nodes) 00830 return 0; 00831 00832 *node_id = cl->node_states[i].node_id; 00833 return 1; 00834 } 00835 i++; 00836 } 00837 00838 return 0; 00839 } 00840 00841 void 00842 CommandInterpreter::executeForAll(const char * cmd, ExecuteFunction fun, 00843 const char * allAfterSecondToken) 00844 { 00845 int nodeId = 0; 00846 if(strcasecmp(cmd, "STOP") == 0) { 00847 ndbout_c("Executing STOP on all nodes."); 00848 (this->*fun)(nodeId, allAfterSecondToken, true); 00849 } else if(strcasecmp(cmd, "RESTART") == 0) { 00850 ndbout_c("Executing RESTART on all nodes."); 00851 ndbout_c("Starting shutdown. This may take a while. Please wait..."); 00852 (this->*fun)(nodeId, allAfterSecondToken, true); 00853 ndbout_c("Trying to start all nodes of system."); 00854 ndbout_c("Use ALL STATUS to see the system start-up phases."); 00855 } else { 00856 struct ndb_mgm_cluster_state *cl= ndb_mgm_get_status(m_mgmsrv); 00857 if(cl == 0){ 00858 ndbout_c("Unable get status from management server"); 00859 printError(); 00860 return; 00861 } 00862 NdbAutoPtr<char> ap1((char*)cl); 00863 while(get_next_nodeid(cl, &nodeId, NDB_MGM_NODE_TYPE_NDB)) 00864 (this->*fun)(nodeId, allAfterSecondToken, true); 00865 } 00866 } 00867 00868 //***************************************************************************** 00869 //***************************************************************************** 00870 bool 00871 CommandInterpreter::parseBlockSpecification(const char* allAfterLog, 00872 Vector<const char*>& blocks) 00873 { 00874 // Parse: [BLOCK = {ALL|<blockName>+}] 00875 00876 if (emptyString(allAfterLog)) { 00877 return true; 00878 } 00879 00880 // Copy allAfterLog since strtok will modify it 00881 char* newAllAfterLog = my_strdup(allAfterLog,MYF(MY_WME)); 00882 My_auto_ptr<char> ap1(newAllAfterLog); 00883 char* firstTokenAfterLog = strtok(newAllAfterLog, " "); 00884 for (unsigned int i = 0; i < strlen(firstTokenAfterLog); ++i) { 00885 firstTokenAfterLog[i] = toupper(firstTokenAfterLog[i]); 00886 } 00887 00888 if (strcasecmp(firstTokenAfterLog, "BLOCK") != 0) { 00889 ndbout << "Unexpected value: " << firstTokenAfterLog 00890 << ". Expected BLOCK." << endl; 00891 return false; 00892 } 00893 00894 char* allAfterFirstToken = strtok(NULL, "\0"); 00895 if (emptyString(allAfterFirstToken)) { 00896 ndbout << "Expected =." << endl; 00897 return false; 00898 } 00899 00900 char* secondTokenAfterLog = strtok(allAfterFirstToken, " "); 00901 if (strcasecmp(secondTokenAfterLog, "=") != 0) { 00902 ndbout << "Unexpected value: " << secondTokenAfterLog 00903 << ". Expected =." << endl; 00904 return false; 00905 } 00906 00907 char* blockName = strtok(NULL, " "); 00908 bool all = false; 00909 if (blockName != NULL && (strcasecmp(blockName, "ALL") == 0)) { 00910 all = true; 00911 } 00912 while (blockName != NULL) { 00913 blocks.push_back(strdup(blockName)); 00914 blockName = strtok(NULL, " "); 00915 } 00916 00917 if (blocks.size() == 0) { 00918 ndbout << "No block specified." << endl; 00919 return false; 00920 } 00921 if (blocks.size() > 1 && all) { 00922 // More than "ALL" specified 00923 ndbout << "Nothing expected after ALL." << endl; 00924 return false; 00925 } 00926 00927 return true; 00928 } 00929 00930 00931 00932 /***************************************************************************** 00933 * HELP 00934 *****************************************************************************/ 00935 void 00936 CommandInterpreter::executeHelp(char* parameters) 00937 { 00938 if (emptyString(parameters)) { 00939 ndbout << helpText; 00940 00941 ndbout << endl 00942 << "<severity> = " 00943 << "ALERT | CRITICAL | ERROR | WARNING | INFO | DEBUG" 00944 << endl; 00945 00946 ndbout << "<category> = "; 00947 for(int i = CFG_MIN_LOGLEVEL; i <= CFG_MAX_LOGLEVEL; i++){ 00948 const char *str= ndb_mgm_get_event_category_string((ndb_mgm_event_category)i); 00949 if (str) { 00950 if (i != CFG_MIN_LOGLEVEL) 00951 ndbout << " | "; 00952 ndbout << str; 00953 } 00954 } 00955 ndbout << endl; 00956 00957 ndbout << "<level> = " << "0 - 15" << endl; 00958 ndbout << "<id> = " << "ALL | Any database node id" << endl; 00959 ndbout << endl; 00960 } else if (strcasecmp(parameters, "SHOW") == 0) { 00961 ndbout << helpTextShow; 00962 #ifdef VM_TRACE // DEBUG ONLY 00963 } else if (strcasecmp(parameters, "DEBUG") == 0) { 00964 ndbout << helpTextDebug; 00965 #endif 00966 } else { 00967 invalid_command(parameters); 00968 } 00969 } 00970 00971 00972 /***************************************************************************** 00973 * SHUTDOWN 00974 *****************************************************************************/ 00975 00976 int 00977 CommandInterpreter::executeShutdown(char* parameters) 00978 { 00979 ndb_mgm_cluster_state *state = ndb_mgm_get_status(m_mgmsrv); 00980 if(state == NULL) { 00981 ndbout_c("Could not get status"); 00982 printError(); 00983 return 1; 00984 } 00985 NdbAutoPtr<char> ap1((char*)state); 00986 00987 int result = 0; 00988 int need_disconnect; 00989 result = ndb_mgm_stop3(m_mgmsrv, -1, 0, 0, &need_disconnect); 00990 if (result < 0) { 00991 ndbout << "Shutdown of NDB Cluster node(s) failed." << endl; 00992 printError(); 00993 return result; 00994 } 00995 00996 ndbout << result << " NDB Cluster node(s) have shutdown." << endl; 00997 00998 if(need_disconnect) { 00999 ndbout << "Disconnecting to allow management server to shutdown." 01000 << endl; 01001 disconnect(); 01002 } 01003 return 0; 01004 } 01005 01006 /***************************************************************************** 01007 * SHOW 01008 *****************************************************************************/ 01009 01010 01011 static 01012 const char *status_string(ndb_mgm_node_status status) 01013 { 01014 switch(status){ 01015 case NDB_MGM_NODE_STATUS_NO_CONTACT: 01016 return "not connected"; 01017 case NDB_MGM_NODE_STATUS_NOT_STARTED: 01018 return "not started"; 01019 case NDB_MGM_NODE_STATUS_STARTING: 01020 return "starting"; 01021 case NDB_MGM_NODE_STATUS_STARTED: 01022 return "started"; 01023 case NDB_MGM_NODE_STATUS_SHUTTING_DOWN: 01024 return "shutting down"; 01025 case NDB_MGM_NODE_STATUS_RESTARTING: 01026 return "restarting"; 01027 case NDB_MGM_NODE_STATUS_SINGLEUSER: 01028 return "single user mode"; 01029 default: 01030 return "unknown state"; 01031 } 01032 } 01033 01034 static void 01035 print_nodes(ndb_mgm_cluster_state *state, ndb_mgm_configuration_iterator *it, 01036 const char *proc_name, int no_proc, ndb_mgm_node_type type, 01037 int master_id) 01038 { 01039 int i; 01040 ndbout << "[" << proc_name 01041 << "(" << ndb_mgm_get_node_type_string(type) << ")]\t" 01042 << no_proc << " node(s)" << endl; 01043 for(i=0; i < state->no_of_nodes; i++) { 01044 struct ndb_mgm_node_state *node_state= &(state->node_states[i]); 01045 if(node_state->node_type == type) { 01046 int node_id= node_state->node_id; 01047 ndbout << "id=" << node_id; 01048 if(node_state->version != 0) { 01049 const char *hostname= node_state->connect_address; 01050 if (hostname == 0 01051 || strlen(hostname) == 0 01052 || strcasecmp(hostname,"0.0.0.0") == 0) 01053 ndbout << " "; 01054 else 01055 ndbout << "\t@" << hostname; 01056 ndbout << " (Version: " 01057 << getMajor(node_state->version) << "." 01058 << getMinor(node_state->version) << "." 01059 << getBuild(node_state->version); 01060 if (type == NDB_MGM_NODE_TYPE_NDB) { 01061 if (node_state->node_status != NDB_MGM_NODE_STATUS_STARTED) { 01062 ndbout << ", " << status_string(node_state->node_status); 01063 } 01064 if (node_state->node_group >= 0) { 01065 ndbout << ", Nodegroup: " << node_state->node_group; 01066 if (master_id && node_state->dynamic_id == master_id) 01067 ndbout << ", Master"; 01068 } 01069 } 01070 ndbout << ")" << endl; 01071 } else { 01072 ndb_mgm_first(it); 01073 if(ndb_mgm_find(it, CFG_NODE_ID, node_id) == 0){ 01074 const char *config_hostname= 0; 01075 ndb_mgm_get_string_parameter(it, CFG_NODE_HOST, &config_hostname); 01076 if (config_hostname == 0 || config_hostname[0] == 0) 01077 config_hostname= "any host"; 01078 ndbout_c(" (not connected, accepting connect from %s)", 01079 config_hostname); 01080 } 01081 else 01082 { 01083 ndbout_c("Unable to find node with id: %d", node_id); 01084 } 01085 } 01086 } 01087 } 01088 ndbout << endl; 01089 } 01090 01091 void 01092 CommandInterpreter::executePurge(char* parameters) 01093 { 01094 int command_ok= 0; 01095 do { 01096 if (emptyString(parameters)) 01097 break; 01098 char* firstToken = strtok(parameters, " "); 01099 char* nextToken = strtok(NULL, " \0"); 01100 if (strcasecmp(firstToken,"STALE") == 0 && 01101 nextToken && 01102 strcasecmp(nextToken, "SESSIONS") == 0) { 01103 command_ok= 1; 01104 break; 01105 } 01106 } while(0); 01107 01108 if (!command_ok) { 01109 ndbout_c("Unexpected command, expected: PURGE STALE SESSIONS"); 01110 return; 01111 } 01112 01113 int i; 01114 char *str; 01115 01116 if (ndb_mgm_purge_stale_sessions(m_mgmsrv, &str)) { 01117 ndbout_c("Command failed"); 01118 return; 01119 } 01120 if (str) { 01121 ndbout_c("Purged sessions with node id's: %s", str); 01122 free(str); 01123 } 01124 else 01125 { 01126 ndbout_c("No sessions purged"); 01127 } 01128 } 01129 01130 void 01131 CommandInterpreter::executeShow(char* parameters) 01132 { 01133 int i; 01134 if (emptyString(parameters)) { 01135 ndb_mgm_cluster_state *state = ndb_mgm_get_status(m_mgmsrv); 01136 if(state == NULL) { 01137 ndbout_c("Could not get status"); 01138 printError(); 01139 return; 01140 } 01141 NdbAutoPtr<char> ap1((char*)state); 01142 01143 ndb_mgm_configuration * conf = ndb_mgm_get_configuration(m_mgmsrv,0); 01144 if(conf == 0){ 01145 ndbout_c("Could not get configuration"); 01146 printError(); 01147 return; 01148 } 01149 01150 ndb_mgm_configuration_iterator * it; 01151 it = ndb_mgm_create_configuration_iterator((struct ndb_mgm_configuration *)conf, CFG_SECTION_NODE); 01152 01153 if(it == 0){ 01154 ndbout_c("Unable to create config iterator"); 01155 return; 01156 } 01157 NdbAutoPtr<ndb_mgm_configuration_iterator> ptr(it); 01158 01159 int 01160 master_id= 0, 01161 ndb_nodes= 0, 01162 api_nodes= 0, 01163 mgm_nodes= 0; 01164 01165 for(i=0; i < state->no_of_nodes; i++) { 01166 if(state->node_states[i].node_type == NDB_MGM_NODE_TYPE_NDB && 01167 state->node_states[i].version != 0){ 01168 master_id= state->node_states[i].dynamic_id; 01169 break; 01170 } 01171 } 01172 01173 for(i=0; i < state->no_of_nodes; i++) { 01174 switch(state->node_states[i].node_type) { 01175 case NDB_MGM_NODE_TYPE_API: 01176 api_nodes++; 01177 break; 01178 case NDB_MGM_NODE_TYPE_NDB: 01179 if (state->node_states[i].dynamic_id && 01180 state->node_states[i].dynamic_id < master_id) 01181 master_id= state->node_states[i].dynamic_id; 01182 ndb_nodes++; 01183 break; 01184 case NDB_MGM_NODE_TYPE_MGM: 01185 mgm_nodes++; 01186 break; 01187 case NDB_MGM_NODE_TYPE_UNKNOWN: 01188 ndbout << "Error: Unknown Node Type" << endl; 01189 return; 01190 } 01191 } 01192 01193 ndbout << "Cluster Configuration" << endl 01194 << "---------------------" << endl; 01195 print_nodes(state, it, "ndbd", ndb_nodes, NDB_MGM_NODE_TYPE_NDB, master_id); 01196 print_nodes(state, it, "ndb_mgmd", mgm_nodes, NDB_MGM_NODE_TYPE_MGM, 0); 01197 print_nodes(state, it, "mysqld", api_nodes, NDB_MGM_NODE_TYPE_API, 0); 01198 // ndbout << helpTextShow; 01199 return; 01200 } else if (strcasecmp(parameters, "PROPERTIES") == 0 || 01201 strcasecmp(parameters, "PROP") == 0) { 01202 ndbout << "SHOW PROPERTIES is not yet implemented." << endl; 01203 // ndbout << "_mgmtSrvr.getConfig()->print();" << endl; /* XXX */ 01204 } else if (strcasecmp(parameters, "CONFIGURATION") == 0 || 01205 strcasecmp(parameters, "CONFIG") == 0){ 01206 ndbout << "SHOW CONFIGURATION is not yet implemented." << endl; 01207 //nbout << "_mgmtSrvr.getConfig()->printConfigFile();" << endl; /* XXX */ 01208 } else if (strcasecmp(parameters, "PARAMETERS") == 0 || 01209 strcasecmp(parameters, "PARAMS") == 0 || 01210 strcasecmp(parameters, "PARAM") == 0) { 01211 ndbout << "SHOW PARAMETERS is not yet implemented." << endl; 01212 // ndbout << "_mgmtSrvr.getConfig()->getConfigInfo()->print();" 01213 // << endl; /* XXX */ 01214 } else { 01215 ndbout << "Invalid argument." << endl; 01216 } 01217 } 01218 01219 void 01220 CommandInterpreter::executeConnect(char* parameters) 01221 { 01222 disconnect(); 01223 if (!emptyString(parameters)) { 01224 m_constr= BaseString(parameters).trim().c_str(); 01225 } 01226 connect(); 01227 } 01228 01229 //***************************************************************************** 01230 //***************************************************************************** 01231 void 01232 CommandInterpreter::executeClusterLog(char* parameters) 01233 { 01234 DBUG_ENTER("CommandInterpreter::executeClusterLog"); 01235 int i; 01236 if (emptyString(parameters)) 01237 { 01238 ndbout << "Missing argument." << endl; 01239 DBUG_VOID_RETURN; 01240 } 01241 01242 enum ndb_mgm_event_severity severity = NDB_MGM_EVENT_SEVERITY_ALL; 01243 01244 char * tmpString = my_strdup(parameters,MYF(MY_WME)); 01245 My_auto_ptr<char> ap1(tmpString); 01246 char * tmpPtr = 0; 01247 char * item = strtok_r(tmpString, " ", &tmpPtr); 01248 int enable; 01249 01250 const unsigned int *enabled= ndb_mgm_get_logfilter(m_mgmsrv); 01251 if(enabled == NULL) { 01252 ndbout << "Couldn't get status" << endl; 01253 printError(); 01254 DBUG_VOID_RETURN; 01255 } 01256 01257 /******************** 01258 * CLUSTERLOG INFO 01259 ********************/ 01260 if (strcasecmp(item, "INFO") == 0) { 01261 DBUG_PRINT("info",("INFO")); 01262 if(enabled[0] == 0) 01263 { 01264 ndbout << "Cluster logging is disabled." << endl; 01265 DBUG_VOID_RETURN; 01266 } 01267 #if 0 01268 for(i = 0; i<7;i++) 01269 printf("enabled[%d] = %d\n", i, enabled[i]); 01270 #endif 01271 ndbout << "Severities enabled: "; 01272 for(i = 1; i < (int)NDB_MGM_EVENT_SEVERITY_ALL; i++) { 01273 const char *str= ndb_mgm_get_event_severity_string((ndb_mgm_event_severity)i); 01274 if (str == 0) 01275 { 01276 DBUG_ASSERT(false); 01277 continue; 01278 } 01279 if(enabled[i]) 01280 ndbout << BaseString(str).ndb_toupper() << " "; 01281 } 01282 ndbout << endl; 01283 DBUG_VOID_RETURN; 01284 01285 } 01286 else if (strcasecmp(item, "FILTER") == 0 || 01287 strcasecmp(item, "TOGGLE") == 0) 01288 { 01289 DBUG_PRINT("info",("TOGGLE")); 01290 enable= -1; 01291 } 01292 else if (strcasecmp(item, "OFF") == 0) 01293 { 01294 DBUG_PRINT("info",("OFF")); 01295 enable= 0; 01296 } else if (strcasecmp(item, "ON") == 0) { 01297 DBUG_PRINT("info",("ON")); 01298 enable= 1; 01299 } else { 01300 ndbout << "Invalid argument." << endl; 01301 DBUG_VOID_RETURN; 01302 } 01303 01304 int res_enable; 01305 item = strtok_r(NULL, " ", &tmpPtr); 01306 if (item == NULL) { 01307 res_enable= 01308 ndb_mgm_set_clusterlog_severity_filter(m_mgmsrv, 01309 NDB_MGM_EVENT_SEVERITY_ON, 01310 enable, NULL); 01311 if (res_enable < 0) 01312 { 01313 ndbout << "Couldn't set filter" << endl; 01314 printError(); 01315 DBUG_VOID_RETURN; 01316 } 01317 ndbout << "Cluster logging is " << (res_enable ? "enabled.":"disabled") << endl; 01318 DBUG_VOID_RETURN; 01319 } 01320 01321 do { 01322 severity= NDB_MGM_ILLEGAL_EVENT_SEVERITY; 01323 if (strcasecmp(item, "ALL") == 0) { 01324 severity = NDB_MGM_EVENT_SEVERITY_ALL; 01325 } else if (strcasecmp(item, "ALERT") == 0) { 01326 severity = NDB_MGM_EVENT_SEVERITY_ALERT; 01327 } else if (strcasecmp(item, "CRITICAL") == 0) { 01328 severity = NDB_MGM_EVENT_SEVERITY_CRITICAL; 01329 } else if (strcasecmp(item, "ERROR") == 0) { 01330 severity = NDB_MGM_EVENT_SEVERITY_ERROR; 01331 } else if (strcasecmp(item, "WARNING") == 0) { 01332 severity = NDB_MGM_EVENT_SEVERITY_WARNING; 01333 } else if (strcasecmp(item, "INFO") == 0) { 01334 severity = NDB_MGM_EVENT_SEVERITY_INFO; 01335 } else if (strcasecmp(item, "DEBUG") == 0) { 01336 severity = NDB_MGM_EVENT_SEVERITY_DEBUG; 01337 } else if (strcasecmp(item, "OFF") == 0 || 01338 strcasecmp(item, "ON") == 0) { 01339 if (enable < 0) // only makes sense with toggle 01340 severity = NDB_MGM_EVENT_SEVERITY_ON; 01341 } 01342 if (severity == NDB_MGM_ILLEGAL_EVENT_SEVERITY) { 01343 ndbout << "Invalid severity level: " << item << endl; 01344 DBUG_VOID_RETURN; 01345 } 01346 01347 res_enable= ndb_mgm_set_clusterlog_severity_filter(m_mgmsrv, severity, 01348 enable, NULL); 01349 if (res_enable < 0) 01350 { 01351 ndbout << "Couldn't set filter" << endl; 01352 printError(); 01353 DBUG_VOID_RETURN; 01354 } 01355 ndbout << BaseString(item).ndb_toupper().c_str() << " " << (res_enable ? "enabled":"disabled") << endl; 01356 01357 item = strtok_r(NULL, " ", &tmpPtr); 01358 } while(item != NULL); 01359 01360 DBUG_VOID_RETURN; 01361 } 01362 01363 //***************************************************************************** 01364 //***************************************************************************** 01365 01366 void 01367 CommandInterpreter::executeStop(int processId, const char *parameters, 01368 bool all) 01369 { 01370 Vector<BaseString> command_list; 01371 if (parameters) 01372 { 01373 BaseString tmp(parameters); 01374 tmp.split(command_list); 01375 for (unsigned i= 0; i < command_list.size();) 01376 command_list[i].c_str()[0] ? i++ : (command_list.erase(i),0); 01377 } 01378 if (all) 01379 executeStop(command_list, 0, 0, 0); 01380 else 01381 executeStop(command_list, 0, &processId, 1); 01382 } 01383 01384 void 01385 CommandInterpreter::executeStop(Vector<BaseString> &command_list, 01386 unsigned command_pos, 01387 int *node_ids, int no_of_nodes) 01388 { 01389 int need_disconnect; 01390 int abort= 0; 01391 for (; command_pos < command_list.size(); command_pos++) 01392 { 01393 const char *item= command_list[command_pos].c_str(); 01394 if (strcasecmp(item, "-A") == 0) 01395 { 01396 abort= 1; 01397 continue; 01398 } 01399 ndbout_c("Invalid option: %s. Expecting -A after STOP", 01400 item); 01401 return; 01402 } 01403 01404 int result= ndb_mgm_stop3(m_mgmsrv, no_of_nodes, node_ids, abort, 01405 &need_disconnect); 01406 if (result < 0) 01407 { 01408 ndbout_c("Shutdown failed."); 01409 printError(); 01410 } 01411 else 01412 { 01413 if (node_ids == 0) 01414 ndbout_c("NDB Cluster has shutdown."); 01415 else 01416 { 01417 ndbout << "Node"; 01418 for (int i= 0; i < no_of_nodes; i++) 01419 ndbout << " " << node_ids[i]; 01420 ndbout_c(" has shutdown."); 01421 } 01422 } 01423 01424 if(need_disconnect) 01425 { 01426 ndbout << "Disconnecting to allow Management Server to shutdown" << endl; 01427 disconnect(); 01428 } 01429 01430 } 01431 01432 void 01433 CommandInterpreter::executeEnterSingleUser(char* parameters) 01434 { 01435 strtok(parameters, " "); 01436 struct ndb_mgm_reply reply; 01437 char* id = strtok(NULL, " "); 01438 id = strtok(NULL, " "); 01439 id = strtok(NULL, "\0"); 01440 int nodeId = -1; 01441 if(id == 0 || sscanf(id, "%d", &nodeId) != 1){ 01442 ndbout_c("Invalid arguments: expected <NodeId>"); 01443 ndbout_c("Use SHOW to see what API nodes are configured"); 01444 return; 01445 } 01446 int result = ndb_mgm_enter_single_user(m_mgmsrv, nodeId, &reply); 01447 01448 if (result != 0) { 01449 ndbout_c("Entering single user mode for node %d failed", nodeId); 01450 printError(); 01451 } else { 01452 ndbout_c("Single user mode entered"); 01453 ndbout_c("Access is granted for API node %d only.", nodeId); 01454 } 01455 } 01456 01457 void 01458 CommandInterpreter::executeExitSingleUser(char* parameters) 01459 { 01460 int result = ndb_mgm_exit_single_user(m_mgmsrv, 0); 01461 if (result != 0) { 01462 ndbout_c("Exiting single user mode failed."); 01463 printError(); 01464 } else { 01465 ndbout_c("Exiting single user mode in progress."); 01466 ndbout_c("Use ALL STATUS or SHOW to see when single user mode has been exited."); 01467 } 01468 } 01469 01470 void 01471 CommandInterpreter::executeStart(int processId, const char* parameters, 01472 bool all) 01473 { 01474 int result; 01475 if(all) { 01476 result = ndb_mgm_start(m_mgmsrv, 0, 0); 01477 } else { 01478 result = ndb_mgm_start(m_mgmsrv, 1, &processId); 01479 } 01480 01481 if (result <= 0) { 01482 ndbout << "Start failed." << endl; 01483 printError(); 01484 } else 01485 { 01486 if(all) 01487 ndbout_c("NDB Cluster is being started."); 01488 else 01489 ndbout_c("Database node %d is being started.", processId); 01490 } 01491 } 01492 01493 void 01494 CommandInterpreter::executeRestart(int processId, const char* parameters, 01495 bool all) 01496 { 01497 Vector<BaseString> command_list; 01498 if (parameters) 01499 { 01500 BaseString tmp(parameters); 01501 tmp.split(command_list); 01502 for (unsigned i= 0; i < command_list.size();) 01503 command_list[i].c_str()[0] ? i++ : (command_list.erase(i),0); 01504 } 01505 if (all) 01506 executeRestart(command_list, 0, 0, 0); 01507 else 01508 executeRestart(command_list, 0, &processId, 1); 01509 } 01510 01511 void 01512 CommandInterpreter::executeRestart(Vector<BaseString> &command_list, 01513 unsigned command_pos, 01514 int *node_ids, int no_of_nodes) 01515 { 01516 int result; 01517 int nostart= 0; 01518 int initialstart= 0; 01519 int abort= 0; 01520 int need_disconnect= 0; 01521 01522 for (; command_pos < command_list.size(); command_pos++) 01523 { 01524 const char *item= command_list[command_pos].c_str(); 01525 if (strcasecmp(item, "-N") == 0) 01526 { 01527 nostart= 1; 01528 continue; 01529 } 01530 if (strcasecmp(item, "-I") == 0) 01531 { 01532 initialstart= 1; 01533 continue; 01534 } 01535 if (strcasecmp(item, "-A") == 0) 01536 { 01537 abort= 1; 01538 continue; 01539 } 01540 ndbout_c("Invalid option: %s. Expecting -A,-N or -I after RESTART", 01541 item); 01542 return; 01543 } 01544 01545 result= ndb_mgm_restart3(m_mgmsrv, no_of_nodes, node_ids, 01546 initialstart, nostart, abort, &need_disconnect); 01547 01548 if (result <= 0) { 01549 ndbout_c("Restart failed."); 01550 printError(); 01551 } 01552 else 01553 { 01554 if (node_ids == 0) 01555 ndbout_c("NDB Cluster is being restarted."); 01556 else 01557 { 01558 ndbout << "Node"; 01559 for (int i= 0; i < no_of_nodes; i++) 01560 ndbout << " " << node_ids[i]; 01561 ndbout_c(" is being restarted"); 01562 } 01563 if(need_disconnect) 01564 disconnect(); 01565 } 01566 } 01567 01568 void 01569 CommandInterpreter::executeDumpState(int processId, const char* parameters, 01570 bool all) 01571 { 01572 if(emptyString(parameters)){ 01573 ndbout << "Expected argument" << endl; 01574 return; 01575 } 01576 01577 Uint32 no = 0; 01578 int pars[25]; 01579 01580 char * tmpString = my_strdup(parameters,MYF(MY_WME)); 01581 My_auto_ptr<char> ap1(tmpString); 01582 char * tmpPtr = 0; 01583 char * item = strtok_r(tmpString, " ", &tmpPtr); 01584 while(item != NULL){ 01585 if (0x0 <= strtoll(item, NULL, 0) && strtoll(item, NULL, 0) <= 0xffffffff){ 01586 pars[no] = strtoll(item, NULL, 0); 01587 } else { 01588 ndbout << "Illegal value in argument to signal." << endl 01589 << "(Value must be between 0 and 0xffffffff.)" 01590 << endl; 01591 return; 01592 } 01593 no++; 01594 item = strtok_r(NULL, " ", &tmpPtr); 01595 } 01596 ndbout << "Sending dump signal with data:" << endl; 01597 for (Uint32 i=0; i<no; i++) { 01598 ndbout.setHexFormat(1) << pars[i] << " "; 01599 if (!(i+1 & 0x3)) ndbout << endl; 01600 } 01601 01602 struct ndb_mgm_reply reply; 01603 ndb_mgm_dump_state(m_mgmsrv, processId, pars, no, &reply); 01604 } 01605 01606 void 01607 CommandInterpreter::executeStatus(int processId, 01608 const char* parameters, bool all) 01609 { 01610 if (! emptyString(parameters)) { 01611 ndbout_c("No parameters expected to this command."); 01612 return; 01613 } 01614 01615 ndb_mgm_node_status status; 01616 Uint32 startPhase, version; 01617 bool system; 01618 01619 struct ndb_mgm_cluster_state *cl; 01620 cl = ndb_mgm_get_status(m_mgmsrv); 01621 if(cl == NULL) { 01622 ndbout_c("Cannot get status of node %d.", processId); 01623 printError(); 01624 return; 01625 } 01626 NdbAutoPtr<char> ap1((char*)cl); 01627 01628 int i = 0; 01629 while((i < cl->no_of_nodes) && cl->node_states[i].node_id != processId) 01630 i++; 01631 if(cl->node_states[i].node_id != processId) { 01632 ndbout << processId << ": Node not found" << endl; 01633 return; 01634 } 01635 status = cl->node_states[i].node_status; 01636 startPhase = cl->node_states[i].start_phase; 01637 version = cl->node_states[i].version; 01638 01639 ndbout << "Node " << processId << ": " << status_string(status); 01640 switch(status){ 01641 case NDB_MGM_NODE_STATUS_STARTING: 01642 ndbout << " (Phase " << startPhase << ")"; 01643 break; 01644 case NDB_MGM_NODE_STATUS_SHUTTING_DOWN: 01645 ndbout << " (Phase " << startPhase << ")"; 01646 break; 01647 default: 01648 break; 01649 } 01650 if(status != NDB_MGM_NODE_STATUS_NO_CONTACT) 01651 ndbout_c(" (Version %d.%d.%d)", 01652 getMajor(version) , 01653 getMinor(version), 01654 getBuild(version)); 01655 else 01656 ndbout << endl; 01657 } 01658 01659 01660 //***************************************************************************** 01661 //***************************************************************************** 01662 01663 void 01664 CommandInterpreter::executeLogLevel(int processId, const char* parameters, 01665 bool all) 01666 { 01667 (void) all; 01668 if (emptyString(parameters)) { 01669 ndbout << "Expected argument" << endl; 01670 return; 01671 } 01672 BaseString tmp(parameters); 01673 Vector<BaseString> spec; 01674 tmp.split(spec, "="); 01675 if(spec.size() != 2){ 01676 ndbout << "Invalid loglevel specification: " << parameters << endl; 01677 return; 01678 } 01679 01680 spec[0].trim().ndb_toupper(); 01681 int category = ndb_mgm_match_event_category(spec[0].c_str()); 01682 if(category == NDB_MGM_ILLEGAL_EVENT_CATEGORY){ 01683 category = atoi(spec[0].c_str()); 01684 if(category < NDB_MGM_MIN_EVENT_CATEGORY || 01685 category > NDB_MGM_MAX_EVENT_CATEGORY){ 01686 ndbout << "Unknown category: \"" << spec[0].c_str() << "\"" << endl; 01687 return; 01688 } 01689 } 01690 01691 int level = atoi(spec[1].c_str()); 01692 if(level < 0 || level > 15){ 01693 ndbout << "Invalid level: " << spec[1].c_str() << endl; 01694 return; 01695 } 01696 01697 ndbout << "Executing LOGLEVEL on node " << processId << flush; 01698 01699 struct ndb_mgm_reply reply; 01700 int result; 01701 result = ndb_mgm_set_loglevel_node(m_mgmsrv, 01702 processId, 01703 (ndb_mgm_event_category)category, 01704 level, 01705 &reply); 01706 01707 if (result < 0) { 01708 ndbout_c(" failed."); 01709 printError(); 01710 } else { 01711 ndbout_c(" OK!"); 01712 } 01713 01714 } 01715 01716 //***************************************************************************** 01717 //***************************************************************************** 01718 void CommandInterpreter::executeError(int processId, 01719 const char* parameters, bool /* all */) 01720 { 01721 if (emptyString(parameters)) { 01722 ndbout << "Missing error number." << endl; 01723 return; 01724 } 01725 01726 // Copy parameters since strtok will modify it 01727 char* newpar = my_strdup(parameters,MYF(MY_WME)); 01728 My_auto_ptr<char> ap1(newpar); 01729 char* firstParameter = strtok(newpar, " "); 01730 01731 int errorNo; 01732 if (! convert(firstParameter, errorNo)) { 01733 ndbout << "Expected an integer." << endl; 01734 return; 01735 } 01736 01737 char* allAfterFirstParameter = strtok(NULL, "\0"); 01738 if (! emptyString(allAfterFirstParameter)) { 01739 ndbout << "Nothing expected after error number." << endl; 01740 return; 01741 } 01742 01743 ndb_mgm_insert_error(m_mgmsrv, processId, errorNo, NULL); 01744 } 01745 01746 //***************************************************************************** 01747 //***************************************************************************** 01748 01749 void 01750 CommandInterpreter::executeLog(int processId, 01751 const char* parameters, bool all) 01752 { 01753 struct ndb_mgm_reply reply; 01754 Vector<const char *> blocks; 01755 if (! parseBlockSpecification(parameters, blocks)) { 01756 return; 01757 } 01758 int len=1; 01759 Uint32 i; 01760 for(i=0; i<blocks.size(); i++) { 01761 len += strlen(blocks[i]) + 1; 01762 } 01763 char * blockNames = (char*)my_malloc(len,MYF(MY_WME)); 01764 My_auto_ptr<char> ap1(blockNames); 01765 01766 blockNames[0] = 0; 01767 for(i=0; i<blocks.size(); i++) { 01768 strcat(blockNames, blocks[i]); 01769 strcat(blockNames, "|"); 01770 } 01771 01772 int result = ndb_mgm_log_signals(m_mgmsrv, 01773 processId, 01774 NDB_MGM_SIGNAL_LOG_MODE_INOUT, 01775 blockNames, 01776 &reply); 01777 if (result != 0) { 01778 ndbout_c("Execute LOG on node %d failed.", processId); 01779 printError(); 01780 } 01781 } 01782 01783 //***************************************************************************** 01784 //***************************************************************************** 01785 void 01786 CommandInterpreter::executeLogIn(int /* processId */, 01787 const char* parameters, bool /* all */) 01788 { 01789 ndbout << "Command LOGIN not implemented." << endl; 01790 } 01791 01792 //***************************************************************************** 01793 //***************************************************************************** 01794 void 01795 CommandInterpreter::executeLogOut(int /*processId*/, 01796 const char* parameters, bool /*all*/) 01797 { 01798 ndbout << "Command LOGOUT not implemented." << endl; 01799 } 01800 01801 //***************************************************************************** 01802 //***************************************************************************** 01803 void 01804 CommandInterpreter::executeLogOff(int /*processId*/, 01805 const char* parameters, bool /*all*/) 01806 { 01807 ndbout << "Command LOGOFF not implemented." << endl; 01808 } 01809 01810 //***************************************************************************** 01811 //***************************************************************************** 01812 void 01813 CommandInterpreter::executeTestOn(int processId, 01814 const char* parameters, bool /*all*/) 01815 { 01816 if (! emptyString(parameters)) { 01817 ndbout << "No parameters expected to this command." << endl; 01818 return; 01819 } 01820 struct ndb_mgm_reply reply; 01821 int result = ndb_mgm_start_signallog(m_mgmsrv, processId, &reply); 01822 if (result != 0) { 01823 ndbout_c("Execute TESTON failed."); 01824 printError(); 01825 } 01826 } 01827 01828 //***************************************************************************** 01829 //***************************************************************************** 01830 void 01831 CommandInterpreter::executeTestOff(int processId, 01832 const char* parameters, bool /*all*/) 01833 { 01834 if (! emptyString(parameters)) { 01835 ndbout << "No parameters expected to this command." << endl; 01836 return; 01837 } 01838 struct ndb_mgm_reply reply; 01839 int result = ndb_mgm_stop_signallog(m_mgmsrv, processId, &reply); 01840 if (result != 0) { 01841 ndbout_c("Execute TESTOFF failed."); 01842 printError(); 01843 } 01844 } 01845 01846 01847 //***************************************************************************** 01848 //***************************************************************************** 01849 void 01850 CommandInterpreter::executeSet(int /*processId*/, 01851 const char* parameters, bool /*all*/) 01852 { 01853 if (emptyString(parameters)) { 01854 ndbout << "Missing parameter name." << endl; 01855 return; 01856 } 01857 #if 0 01858 // Copy parameters since strtok will modify it 01859 char* newpar = my_strdup(parameters,MYF(MY_WME)); 01860 My_auto_ptr<char> ap1(newpar); 01861 char* configParameterName = strtok(newpar, " "); 01862 01863 char* allAfterParameterName = strtok(NULL, "\0"); 01864 if (emptyString(allAfterParameterName)) { 01865 ndbout << "Missing parameter value." << endl; 01866 return; 01867 } 01868 01869 char* value = strtok(allAfterParameterName, " "); 01870 01871 char* allAfterValue = strtok(NULL, "\0"); 01872 if (! emptyString(allAfterValue)) { 01873 ndbout << "Nothing expected after parameter value." << endl; 01874 return; 01875 } 01876 01877 bool configBackupFileUpdated; 01878 bool configPrimaryFileUpdated; 01879 01880 // TODO The handling of the primary and backup config files should be 01881 // analysed further. 01882 // How it should be handled if only the backup is possible to write. 01883 01884 int result = _mgmtSrvr.updateConfigParam(processId, configParameterName, 01885 value, configBackupFileUpdated, 01886 configPrimaryFileUpdated); 01887 if (result == 0) { 01888 if (configBackupFileUpdated && configPrimaryFileUpdated) { 01889 ndbout << "The configuration is updated." << endl; 01890 } 01891 else if (configBackupFileUpdated && !configPrimaryFileUpdated) { 01892 ndbout << "The configuration is updated but it was only possible " 01893 << "to update the backup configuration file, not the primary." 01894 << endl; 01895 } 01896 else { 01897 assert(false); 01898 } 01899 } 01900 else { 01901 ndbout << get_error_text(result) << endl; 01902 if (configBackupFileUpdated && configPrimaryFileUpdated) { 01903 ndbout << "The configuration files are however updated and " 01904 << "the value will be used next time the process is restarted." 01905 << endl; 01906 } 01907 else if (configBackupFileUpdated && !configPrimaryFileUpdated) { 01908 ndbout << "It was only possible to update the backup " 01909 << "configuration file, not the primary." << endl; 01910 } 01911 else if (!configBackupFileUpdated && !configPrimaryFileUpdated) { 01912 ndbout << "The configuration files are not updated." << endl; 01913 } 01914 else { 01915 // The primary is not tried to write if the write of backup file fails 01916 abort(); 01917 } 01918 } 01919 #endif 01920 } 01921 01922 //***************************************************************************** 01923 //***************************************************************************** 01924 void CommandInterpreter::executeGetStat(int /*processId*/, 01925 const char* parameters, bool /*all*/) 01926 { 01927 if (! emptyString(parameters)) { 01928 ndbout << "No parameters expected to this command." << endl; 01929 return; 01930 } 01931 01932 #if 0 01933 MgmtSrvr::Statistics statistics; 01934 int result = _mgmtSrvr.getStatistics(processId, statistics); 01935 if (result != 0) { 01936 ndbout << get_error_text(result) << endl; 01937 return; 01938 } 01939 #endif 01940 // Print statistic... 01941 /* 01942 ndbout << "Number of GETSTAT commands: " 01943 << statistics._test1 << endl; 01944 */ 01945 } 01946 01947 //***************************************************************************** 01948 //***************************************************************************** 01949 01950 void 01951 CommandInterpreter::executeEventReporting(int processId, 01952 const char* parameters, 01953 bool all) 01954 { 01955 if (emptyString(parameters)) { 01956 ndbout << "Expected argument" << endl; 01957 return; 01958 } 01959 BaseString tmp(parameters); 01960 Vector<BaseString> specs; 01961 tmp.split(specs, " "); 01962 01963 for (int i=0; i < specs.size(); i++) 01964 { 01965 Vector<BaseString> spec; 01966 specs[i].split(spec, "="); 01967 if(spec.size() != 2){ 01968 ndbout << "Invalid loglevel specification: " << specs[i] << endl; 01969 continue; 01970 } 01971 01972 spec[0].trim().ndb_toupper(); 01973 int category = ndb_mgm_match_event_category(spec[0].c_str()); 01974 if(category == NDB_MGM_ILLEGAL_EVENT_CATEGORY){ 01975 if(!convert(spec[0].c_str(), category) || 01976 category < NDB_MGM_MIN_EVENT_CATEGORY || 01977 category > NDB_MGM_MAX_EVENT_CATEGORY){ 01978 ndbout << "Unknown category: \"" << spec[0].c_str() << "\"" << endl; 01979 continue; 01980 } 01981 } 01982 01983 int level; 01984 if (!convert(spec[1].c_str(),level)) 01985 { 01986 ndbout << "Invalid level: " << spec[1].c_str() << endl; 01987 continue; 01988 } 01989 01990 ndbout << "Executing CLUSTERLOG " << spec[0] << "=" << spec[1] 01991 << " on node " << processId << flush; 01992 01993 struct ndb_mgm_reply reply; 01994 int result; 01995 result = ndb_mgm_set_loglevel_clusterlog(m_mgmsrv, 01996 processId, 01997 (ndb_mgm_event_category)category, 01998 level, 01999 &reply); 02000 02001 if (result != 0) { 02002 ndbout_c(" failed."); 02003 printError(); 02004 } else { 02005 ndbout_c(" OK!"); 02006 } 02007 } 02008 } 02009 02010 /***************************************************************************** 02011 * Backup 02012 *****************************************************************************/ 02013 int 02014 CommandInterpreter::executeStartBackup(char* parameters) 02015 { 02016 struct ndb_mgm_reply reply; 02017 unsigned int backupId; 02018 #if 0 02019 int filter[] = { 15, NDB_MGM_EVENT_CATEGORY_BACKUP, 0 }; 02020 int fd = ndb_mgm_listen_event(m_mgmsrv, filter); 02021 if (fd < 0) 02022 { 02023 ndbout << "Initializing start of backup failed" << endl; 02024 printError(); 02025 return fd; 02026 } 02027 #endif 02028 Vector<BaseString> args; 02029 { 02030 BaseString(parameters).split(args); 02031 for (unsigned i= 0; i < args.size(); i++) 02032 if (args[i].length() == 0) 02033 args.erase(i--); 02034 else 02035 args[i].ndb_toupper(); 02036 } 02037 int sz= args.size(); 02038 02039 int result; 02040 if (sz == 2 && 02041 args[1] == "NOWAIT") 02042 { 02043 result = ndb_mgm_start_backup(m_mgmsrv, 0, &backupId, &reply); 02044 } 02045 else if (sz == 1 || 02046 (sz == 3 && 02047 args[1] == "WAIT" && 02048 args[2] == "COMPLETED")) 02049 { 02050 ndbout_c("Waiting for completed, this may take several minutes"); 02051 result = ndb_mgm_start_backup(m_mgmsrv, 2, &backupId, &reply); 02052 } 02053 else if (sz == 3 && 02054 args[1] == "WAIT" && 02055 args[2] == "STARTED") 02056 { 02057 ndbout_c("Waiting for started, this may take several minutes"); 02058 result = ndb_mgm_start_backup(m_mgmsrv, 1, &backupId, &reply); 02059 } 02060 else 02061 { 02062 invalid_command(parameters); 02063 return -1; 02064 } 02065 02066 if (result != 0) { 02067 ndbout << "Start of backup failed" << endl; 02068 printError(); 02069 #if 0 02070 close(fd); 02071 #endif 02072 return result; 02073 } 02074 #if 0 02075 ndbout_c("Waiting for completed, this may take several minutes"); 02076 char *tmp; 02077 char buf[1024]; 02078 { 02079 SocketInputStream in(fd); 02080 int count = 0; 02081 do { 02082 tmp = in.gets(buf, 1024); 02083 if(tmp) 02084 { 02085 ndbout << tmp; 02086 unsigned int id; 02087 if(sscanf(tmp, "%*[^:]: Backup %d ", &id) == 1 && id == backupId){ 02088 count++; 02089 } 02090 } 02091 } while(count < 2); 02092 } 02093 02094 SocketInputStream in(fd, 10); 02095 do { 02096 tmp = in.gets(buf, 1024); 02097 if(tmp && tmp[0] != 0) 02098 { 02099 ndbout << tmp; 02100 } 02101 } while(tmp && tmp[0] != 0); 02102 02103 close(fd); 02104 #endif 02105 return 0; 02106 } 02107 02108 void 02109 CommandInterpreter::executeAbortBackup(char* parameters) 02110 { 02111 int bid = -1; 02112 struct ndb_mgm_reply reply; 02113 if (emptyString(parameters)) 02114 goto executeAbortBackupError1; 02115 02116 { 02117 strtok(parameters, " "); 02118 char* id = strtok(NULL, "\0"); 02119 if(id == 0 || sscanf(id, "%d", &bid) != 1) 02120 goto executeAbortBackupError1; 02121 } 02122 { 02123 int result= ndb_mgm_abort_backup(m_mgmsrv, bid, &reply); 02124 if (result != 0) { 02125 ndbout << "Abort of backup " << bid << " failed" << endl; 02126 printError(); 02127 } else { 02128 ndbout << "Abort of backup " << bid << " ordered" << endl; 02129 } 02130 } 02131 return; 02132 executeAbortBackupError1: 02133 ndbout << "Invalid arguments: expected <BackupId>" << endl; 02134 return; 02135 } 02136 02137 template class Vector<char const*>;
1.4.7

