CommandInterpreter.cpp
上传用户:romrleung
上传日期:2022-05-23
资源大小:18897k
文件大小:65k
源码类别:

MySQL数据库

开发平台:

Visual C++

  1. /* Copyright (C) 2003 MySQL AB
  2.    This program is free software; you can redistribute it and/or modify
  3.    it under the terms of the GNU General Public License as published by
  4.    the Free Software Foundation; either version 2 of the License, or
  5.    (at your option) any later version.
  6.    This program is distributed in the hope that it will be useful,
  7.    but WITHOUT ANY WARRANTY; without even the implied warranty of
  8.    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  9.    GNU General Public License for more details.
  10.    You should have received a copy of the GNU General Public License
  11.    along with this program; if not, write to the Free Software
  12.    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA */
  13. #include <ndb_global.h>
  14. #include <my_sys.h>
  15. //#define HAVE_GLOBAL_REPLICATION
  16. #include <Vector.hpp>
  17. #ifdef  HAVE_GLOBAL_REPLICATION
  18. #include "../rep/repapi/repapi.h"
  19. #endif
  20. #include <mgmapi.h>
  21. class MgmtSrvr;
  22. /** 
  23.  *  @class CommandInterpreter
  24.  *  @brief Reads command line in management client
  25.  *
  26.  *  This class has one public method which reads a command line 
  27.  *  from a stream. It then interpret that commmand line and calls a suitable 
  28.  *  method in the MgmtSrvr class which executes the command.
  29.  *
  30.  *  For command syntax, see the HELP command.
  31.  */ 
  32. class CommandInterpreter {
  33. public:
  34.   /**
  35.    *   Constructor
  36.    *   @param mgmtSrvr: Management server to use when executing commands
  37.    */
  38.   CommandInterpreter(const char *, int verbose);
  39.   ~CommandInterpreter();
  40.   
  41.   /**
  42.    *   Reads one line from the stream, parse the line to find 
  43.    *   a command and then calls a suitable method which executes 
  44.    *   the command.
  45.    *
  46.    *   @return true until quit/bye/exit has been typed
  47.    */
  48.   int execute(const char *_line, int _try_reconnect=-1, int *error= 0);
  49. private:
  50.   void printError();
  51.   int execute_impl(const char *_line);
  52.   /**
  53.    *   Analyse the command line, after the first token.
  54.    *
  55.    *   @param  processId:           DB process id to send command to or -1 if
  56.    *                                command will be sent to all DB processes.
  57.    *   @param  allAfterFirstToken:  What the client gave after the 
  58.    *                                first token on the command line
  59.    */
  60.   void analyseAfterFirstToken(int processId, char* allAfterFirstTokenCstr);
  61.   /**
  62.    *   Parse the block specification part of the LOG* commands,
  63.    *   things after LOG*: [BLOCK = {ALL|<blockName>+}]
  64.    *
  65.    *   @param  allAfterLog: What the client gave after the second token 
  66.    *                        (LOG*) on the command line
  67.    *   @param  blocks, OUT: ALL or name of all the blocks
  68.    *   @return: true if correct syntax, otherwise false
  69.    */
  70.   bool parseBlockSpecification(const char* allAfterLog, 
  71.        Vector<const char*>& blocks);
  72.   
  73.   /**
  74.    *   A bunch of execute functions: Executes one of the commands
  75.    *
  76.    *   @param  processId:   DB process id to send command to
  77.    *   @param  parameters:  What the client gave after the command name 
  78.    *                        on the command line.
  79.    *   For example if complete input from user is: "1 LOGLEVEL 22" then the
  80.    *   parameters argument is the string with everything after LOGLEVEL, in
  81.    *   this case "22". Each function is responsible to check the parameters
  82.    *   argument.
  83.    */
  84.   void executeHelp(char* parameters);
  85.   void executeShow(char* parameters);
  86.   void executeConnect(char* parameters);
  87.   void executePurge(char* parameters);
  88.   int  executeShutdown(char* parameters);
  89.   void executeRun(char* parameters);
  90.   void executeInfo(char* parameters);
  91.   void executeClusterLog(char* parameters);
  92. public:
  93.   void executeStop(int processId, const char* parameters, bool all);
  94.   void executeEnterSingleUser(char* parameters);
  95.   void executeExitSingleUser(char* parameters);
  96.   void executeStart(int processId, const char* parameters, bool all);
  97.   void executeRestart(int processId, const char* parameters, bool all);
  98.   void executeLogLevel(int processId, const char* parameters, bool all);
  99.   void executeError(int processId, const char* parameters, bool all);
  100.   void executeLog(int processId, const char* parameters, bool all);
  101.   void executeLogIn(int processId, const char* parameters, bool all);
  102.   void executeLogOut(int processId, const char* parameters, bool all);
  103.   void executeLogOff(int processId, const char* parameters, bool all);
  104.   void executeTestOn(int processId, const char* parameters, bool all);
  105.   void executeTestOff(int processId, const char* parameters, bool all);
  106.   void executeSet(int processId, const char* parameters, bool all);
  107.   void executeGetStat(int processId, const char* parameters, bool all);
  108.   void executeStatus(int processId, const char* parameters, bool all);
  109.   void executeEventReporting(int processId, const char* parameters, bool all);
  110.   void executeDumpState(int processId, const char* parameters, bool all);
  111.   int executeStartBackup(char * parameters);
  112.   void executeAbortBackup(char * parameters);
  113.   void executeRep(char* parameters);
  114.   void executeCpc(char * parameters);
  115. public:
  116.   bool connect();
  117.   bool disconnect();
  118.   /**
  119.    * A execute function definition
  120.    */
  121. public:
  122.   typedef void (CommandInterpreter::* ExecuteFunction)(int processId, 
  123.        const char * param, 
  124.        bool all);
  125.   
  126.   struct CommandFunctionPair {
  127.     const char * command;
  128.     ExecuteFunction executeFunction;
  129.   };
  130. private:
  131.   /**
  132.    * 
  133.    */
  134.   void executeForAll(const char * cmd, 
  135.      ExecuteFunction fun,
  136.      const char * param);
  137.   NdbMgmHandle m_mgmsrv;
  138.   NdbMgmHandle m_mgmsrv2;
  139.   bool m_connected;
  140.   int m_verbose;
  141.   int try_reconnect;
  142.   int m_error;
  143. #ifdef HAVE_GLOBAL_REPLICATION  
  144.   NdbRepHandle m_repserver;
  145.   const char *rep_host;
  146.   bool rep_connected;
  147. #endif
  148.   struct NdbThread* m_event_thread;
  149. };
  150. /*
  151.  * Facade object for CommandInterpreter
  152.  */
  153. #include "ndb_mgmclient.hpp"
  154. #include "ndb_mgmclient.h"
  155. Ndb_mgmclient::Ndb_mgmclient(const char *host,int verbose)
  156. {
  157.   m_cmd= new CommandInterpreter(host,verbose);
  158. }
  159. Ndb_mgmclient::~Ndb_mgmclient()
  160. {
  161.   delete m_cmd;
  162. }
  163. int Ndb_mgmclient::execute(const char *_line, int _try_reconnect, int *error)
  164. {
  165.   return m_cmd->execute(_line,_try_reconnect,error);
  166. }
  167. int
  168. Ndb_mgmclient::disconnect()
  169. {
  170.   return m_cmd->disconnect();
  171. }
  172. extern "C" {
  173.   Ndb_mgmclient_handle ndb_mgmclient_handle_create(const char *connect_string)
  174.   {
  175.     return (Ndb_mgmclient_handle) new Ndb_mgmclient(connect_string);
  176.   }
  177.   int ndb_mgmclient_execute(Ndb_mgmclient_handle h, int argc, char** argv)
  178.   {
  179.     return ((Ndb_mgmclient*)h)->execute(argc, argv, 1);
  180.   }
  181.   int ndb_mgmclient_handle_destroy(Ndb_mgmclient_handle h)
  182.   {
  183.     delete (Ndb_mgmclient*)h;
  184.     return 0;
  185.   }
  186. }
  187. /*
  188.  * The CommandInterpreter
  189.  */
  190. #include <mgmapi.h>
  191. #include <mgmapi_debug.h>
  192. #include <version.h>
  193. #include <NdbAutoPtr.hpp>
  194. #include <NdbOut.hpp>
  195. #include <NdbSleep.h>
  196. #include <NdbMem.h>
  197. #include <EventLogger.hpp>
  198. #include <signaldata/SetLogLevelOrd.hpp>
  199. #include <signaldata/GrepImpl.hpp>
  200. #ifdef HAVE_GLOBAL_REPLICATION
  201. #endif // HAVE_GLOBAL_REPLICATION
  202. #include "MgmtErrorReporter.hpp"
  203. #include <Parser.hpp>
  204. #include <SocketServer.hpp>
  205. #include <util/InputStream.hpp>
  206. #include <util/OutputStream.hpp>
  207. int Ndb_mgmclient::execute(int argc, char** argv, int _try_reconnect, int *error)
  208. {
  209.   if (argc <= 0)
  210.     return 0;
  211.   BaseString _line(argv[0]);
  212.   for (int i= 1; i < argc; i++)
  213.   {
  214.     _line.appfmt(" %s", argv[i]);
  215.   }
  216.   return m_cmd->execute(_line.c_str(),_try_reconnect, error);
  217. }
  218. /*****************************************************************************
  219.  * HELP
  220.  *****************************************************************************/
  221. static const char* helpText =
  222. "---------------------------------------------------------------------------n"
  223. " NDB Cluster -- Management Client -- Helpn"
  224. "---------------------------------------------------------------------------n"
  225. "HELP                                   Print help textn"
  226. "HELP SHOW                              Help for SHOW commandn"
  227. #ifdef HAVE_GLOBAL_REPLICATION
  228. "HELP REPLICATION                       Help for global replicationn"
  229. #endif // HAVE_GLOBAL_REPLICATION
  230. #ifdef VM_TRACE // DEBUG ONLY
  231. "HELP DEBUG                             Help for debug compiled versionn"
  232. #endif
  233. "SHOW                                   Print information about clustern"
  234. #if 0
  235. "SHOW CONFIG                            Print configurationn"
  236. "SHOW PARAMETERS                        Print configuration parametersn"
  237. #endif
  238. "START BACKUP [NOWAIT | WAIT STARTED | WAIT COMPLETED]n"
  239. "                                       Start backup (default WAIT COMPLETED)n"
  240. "ABORT BACKUP <backup id>               Abort backupn"
  241. "SHUTDOWN                               Shutdown all processes in clustern"
  242. "CLUSTERLOG ON [<severity>] ...         Enable Cluster loggingn"
  243. "CLUSTERLOG OFF [<severity>] ...        Disable Cluster loggingn"
  244. "CLUSTERLOG TOGGLE [<severity>] ...     Toggle severity filter on/offn"
  245. "CLUSTERLOG INFO                        Print cluster log informationn"
  246. "<id> START                             Start DB node (started with -n)n"
  247. "<id> RESTART [-n] [-i]                 Restart DB noden"
  248. "<id> STOP                              Stop DB noden"
  249. "ENTER SINGLE USER MODE <api-node>      Enter single user moden"
  250. "EXIT SINGLE USER MODE                  Exit single user moden"
  251. "<id> STATUS                            Print statusn"
  252. "<id> CLUSTERLOG {<category>=<level>}+  Set log level for cluster logn"
  253. #ifdef HAVE_GLOBAL_REPLICATION
  254. "REP CONNECT <host:port>                Connect to REP server on host:portn"
  255. #endif
  256. "PURGE STALE SESSIONS                   Reset reserved nodeid's in the mgmt servern"
  257. "CONNECT [<connectstring>]              Connect to management server (reconnect if already connected)n"
  258. "QUIT                                   Quit management clientn"
  259. ;
  260. static const char* helpTextShow =
  261. "---------------------------------------------------------------------------n"
  262. " NDB Cluster -- Management Client -- Help for SHOW commandn"
  263. "---------------------------------------------------------------------------n"
  264. "SHOW prints NDB Cluster informationnn"
  265. "SHOW               Print information about clustern" 
  266. #if 0
  267. "SHOW CONFIG        Print configuration (in initial config file format)n" 
  268. "SHOW PARAMETERS    Print information about configuration parametersnn"
  269. #endif
  270. ;
  271. #ifdef HAVE_GLOBAL_REPLICATION
  272. static const char* helpTextRep =
  273. "---------------------------------------------------------------------------n"
  274. " NDB Cluster -- Management Client -- Help for Global Replicationn"
  275. "---------------------------------------------------------------------------n"
  276. "Commands should be executed on the standby NDB Clustern"
  277. "These features are in an experimental release state.n"
  278. "n"
  279. "Simple Commands:n"
  280. "REP START              Start Global Replicationn" 
  281. "REP START REQUESTOR    Start Global Replication Requestorn" 
  282. "REP STATUS             Show Global Replication statusn" 
  283. "REP STOP               Stop Global Replicationn"
  284. "REP STOP REQUESTOR     Stop Global Replication Requestorn"
  285. "n" 
  286. "Advanced Commands:n"
  287. "REP START <protocol>   Starts protocoln"
  288. "REP STOP <protocol>    Stops protocoln"
  289. "<protocol> = TRANSFER | APPLY | DELETEn"
  290. "n"
  291. #ifdef VM_TRACE // DEBUG ONLY
  292. "Debugging commands:n"
  293. "REP DELETE             Removes epochs stored in primary and standy systemsn"
  294. "REP DROP <tableid>     Drop a table in SS identified by table idn"
  295. "REP SLOWSTOP           Stop Replication (Tries to synchonize with primary)n" 
  296. "REP FASTSTOP           Stop Replication (Stops in consistent state)n" 
  297. "<component> = SUBSCRIPTIONn"
  298. "              METALOG | METASCAN | DATALOG | DATASCANn"
  299. "              REQUESTOR | TRANSFER | APPLY | DELETEn"
  300. #endif
  301. ;
  302. #endif // HAVE_GLOBAL_REPLICATION
  303. #ifdef VM_TRACE // DEBUG ONLY
  304. static const char* helpTextDebug =
  305. "---------------------------------------------------------------------------n"
  306. " NDB Cluster -- Management Client -- Help for Debugging (Internal use only)n"
  307. "---------------------------------------------------------------------------n"
  308. "SHOW PROPERTIES                       Print config properties objectn"
  309. "<id> LOGLEVEL {<category>=<level>}+   Set log leveln"
  310. #ifdef ERROR_INSERT
  311. "<id> ERROR <errorNo>                  Inject error into NDB noden"
  312. #endif
  313. "<id> LOG [BLOCK = {ALL|<block>+}]     Set logging on in & out signalsn"
  314. "<id> LOGIN [BLOCK = {ALL|<block>+}]   Set logging on in signalsn"
  315. "<id> LOGOUT [BLOCK = {ALL|<block>+}]  Set logging on out signalsn"
  316. "<id> LOGOFF [BLOCK = {ALL|<block>+}]  Unset signal loggingn"
  317. "<id> TESTON                           Start signal loggingn"
  318. "<id> TESTOFF                          Stop signal loggingn"
  319. "<id> SET <configParamName> <value>    Update configuration variablen"
  320. "<id> DUMP <arg>                       Dump system state to cluster.logn"
  321. "<id> GETSTAT                          Print statisticsn"
  322. "n"
  323. "<id>       = ALL | Any database node idn"
  324. ;
  325. #endif
  326. static bool
  327. convert(const char* s, int& val) {
  328.   
  329.   if (s == NULL)
  330.     return false;
  331.   if (strlen(s) == 0)
  332.     return false;
  333.   errno = 0;
  334.   char* p;
  335.   long v = strtol(s, &p, 10);
  336.   if (errno != 0)
  337.     return false;
  338.   if (p != &s[strlen(s)])
  339.     return false;
  340.   
  341.   val = v;
  342.   return true;
  343. }
  344. /*
  345.  * Constructor
  346.  */
  347. CommandInterpreter::CommandInterpreter(const char *_host,int verbose) 
  348.   : m_verbose(verbose)
  349. {
  350.   m_mgmsrv = ndb_mgm_create_handle();
  351.   if(m_mgmsrv == NULL) {
  352.     ndbout_c("Cannot create handle to management server.");
  353.     exit(-1);
  354.   }
  355.   m_mgmsrv2 = ndb_mgm_create_handle();
  356.   if(m_mgmsrv2 == NULL) {
  357.     ndbout_c("Cannot create handle to management server.");
  358.     exit(-1);
  359.   }
  360.   if (ndb_mgm_set_connectstring(m_mgmsrv, _host))
  361.   {
  362.     printError();
  363.     exit(-1);
  364.   }
  365.   m_connected= false;
  366.   m_event_thread= 0;
  367.   try_reconnect = 0;
  368. #ifdef HAVE_GLOBAL_REPLICATION
  369.   rep_host = NULL;
  370.   m_repserver = NULL;
  371.   rep_connected = false;
  372. #endif
  373. }
  374. /*
  375.  * Destructor
  376.  */
  377. CommandInterpreter::~CommandInterpreter() 
  378. {
  379.   disconnect();
  380.   ndb_mgm_destroy_handle(&m_mgmsrv);
  381.   ndb_mgm_destroy_handle(&m_mgmsrv2);
  382. }
  383. static bool 
  384. emptyString(const char* s) 
  385. {
  386.   if (s == NULL) {
  387.     return true;
  388.   }
  389.   for (unsigned int i = 0; i < strlen(s); ++i) {
  390.     if (! isspace(s[i])) {
  391.       return false;
  392.     }
  393.   }
  394.   return true;
  395. }
  396. void
  397. CommandInterpreter::printError() 
  398. {
  399.   if (ndb_mgm_check_connection(m_mgmsrv))
  400.   {
  401.     m_connected= false;
  402.     disconnect();
  403.   }
  404.   ndbout_c("* %5d: %s", 
  405.    ndb_mgm_get_latest_error(m_mgmsrv),
  406.    ndb_mgm_get_latest_error_msg(m_mgmsrv));
  407.   ndbout_c("*        %s", ndb_mgm_get_latest_error_desc(m_mgmsrv));
  408. }
  409. //*****************************************************************************
  410. //*****************************************************************************
  411. static int do_event_thread;
  412. static void*
  413. event_thread_run(void* m)
  414. {
  415.   DBUG_ENTER("event_thread_run");
  416.   NdbMgmHandle handle= *(NdbMgmHandle*)m;
  417.   int filter[] = { 15, NDB_MGM_EVENT_CATEGORY_BACKUP, 0 };
  418.   int fd = ndb_mgm_listen_event(handle, filter);
  419.   if (fd != NDB_INVALID_SOCKET)
  420.   {
  421.     do_event_thread= 1;
  422.     char *tmp= 0;
  423.     char buf[1024];
  424.     SocketInputStream in(fd,10);
  425.     do {
  426.       if (tmp == 0) NdbSleep_MilliSleep(10);
  427.       if((tmp = in.gets(buf, 1024)))
  428.       {
  429. const char ping_token[]= "<PING>";
  430. if (memcmp(ping_token,tmp,sizeof(ping_token)-1))
  431.   ndbout << tmp;
  432.       }
  433.     } while(do_event_thread);
  434.     NDB_CLOSE_SOCKET(fd);
  435.   }
  436.   else
  437.   {
  438.     do_event_thread= -1;
  439.   }
  440.   DBUG_RETURN(NULL);
  441. }
  442. bool
  443. CommandInterpreter::connect() 
  444. {
  445.   DBUG_ENTER("CommandInterpreter::connect");
  446.   if(!m_connected)
  447.   {
  448.     if(!ndb_mgm_connect(m_mgmsrv, try_reconnect-1, 5, 1))
  449.     {
  450.       const char *host= ndb_mgm_get_connected_host(m_mgmsrv);
  451.       unsigned port= ndb_mgm_get_connected_port(m_mgmsrv);
  452.       if(!ndb_mgm_set_connectstring(m_mgmsrv2,
  453.     BaseString(host).appfmt(":%d",port).c_str())
  454.  &&
  455.  !ndb_mgm_connect(m_mgmsrv2, try_reconnect-1, 5, 1))
  456.       {
  457. assert(m_event_thread == 0);
  458. assert(do_event_thread == 0);
  459. do_event_thread= 0;
  460. m_event_thread = NdbThread_Create(event_thread_run,
  461.   (void**)&m_mgmsrv2,
  462.   32768,
  463.   "CommandInterpreted_event_thread",
  464.   NDB_THREAD_PRIO_LOW);
  465. if (m_event_thread != 0)
  466. {
  467.   int iter= 1000; // try for 30 seconds
  468.   while(do_event_thread == 0 &&
  469. iter-- > 0)
  470.     NdbSleep_MilliSleep(30);
  471. }
  472. if (m_event_thread == 0 ||
  473.     do_event_thread == 0 ||
  474.     do_event_thread == -1)
  475. {
  476.   DBUG_PRINT("info",("Warning, event thread startup failed, "
  477.      "degraded printouts as result, errno=%d",
  478.      errno));
  479.   printf("Warning, event thread startup failed, "
  480.  "degraded printouts as result, errno=%dn", errno);
  481.   do_event_thread= 0;
  482.   if (m_event_thread)
  483.   {
  484.     void *res;
  485.     NdbThread_WaitFor(m_event_thread, &res);
  486.     NdbThread_Destroy(&m_event_thread);
  487.   }
  488.   ndb_mgm_disconnect(m_mgmsrv2);
  489. }
  490.       }
  491.       else
  492.       {
  493. printf("Warning, event connect failed, degraded printouts as resultn");
  494.       }
  495.       m_connected= true;
  496.       DBUG_PRINT("info",("Connected to Management Server at: %s:%d",
  497.  host,port));
  498.       if (m_verbose)
  499.       {
  500. printf("Connected to Management Server at: %s:%dn",
  501.        host, port);
  502.       }
  503.     }
  504.   }
  505.   DBUG_RETURN(m_connected);
  506. }
  507. bool 
  508. CommandInterpreter::disconnect() 
  509. {
  510.   DBUG_ENTER("CommandInterpreter::disconnect");
  511.   if (m_event_thread) {
  512.     void *res;
  513.     do_event_thread= 0;
  514.     NdbThread_WaitFor(m_event_thread, &res);
  515.     NdbThread_Destroy(&m_event_thread);
  516.     m_event_thread= 0;
  517.     ndb_mgm_disconnect(m_mgmsrv2);
  518.   }
  519.   if (m_connected)
  520.   {
  521.     if (ndb_mgm_disconnect(m_mgmsrv) == -1) {
  522.       ndbout_c("Could not disconnect from management server");
  523.       printError();
  524.     }
  525.     m_connected= false;
  526.   }
  527.   DBUG_RETURN(true);
  528. }
  529. //*****************************************************************************
  530. //*****************************************************************************
  531. int 
  532. CommandInterpreter::execute(const char *_line, int _try_reconnect,
  533.     int *error) 
  534. {
  535.   if (_try_reconnect >= 0)
  536.     try_reconnect=_try_reconnect;
  537.   int result= execute_impl(_line);
  538.   if (error)
  539.     *error= m_error;
  540.   return result;
  541. }
  542. static void
  543. invalid_command(const char *cmd)
  544. {
  545.   ndbout << "Invalid command: " << cmd << endl;
  546.   ndbout << "Type HELP for help." << endl << endl;
  547. }
  548. int 
  549. CommandInterpreter::execute_impl(const char *_line) 
  550. {
  551.   DBUG_ENTER("CommandInterpreter::execute_impl");
  552.   DBUG_PRINT("enter",("line="%s"",_line));
  553.   m_error= 0;
  554.   char * line;
  555.   if(_line == NULL) {
  556.     DBUG_RETURN(false);
  557.   }
  558.   line = my_strdup(_line,MYF(MY_WME));
  559.   My_auto_ptr<char> ptr(line);
  560.   int do_continue;
  561.   do {
  562.     do_continue= 0;
  563.     BaseString::trim(line," t");
  564.     if (line[0] == 0 ||
  565. line[0] == '#')
  566.     {
  567.       DBUG_RETURN(true);
  568.     }
  569.     // for mysql client compatability remove trailing ';'
  570.     {
  571.       unsigned last= strlen(line)-1;
  572.       if (line[last] == ';')
  573.       {
  574. line[last]= 0;
  575. do_continue= 1;
  576.       }
  577.     }
  578.   } while (do_continue);
  579.   // if there is anything in the line proceed
  580.   char* firstToken = strtok(line, " ");
  581.   char* allAfterFirstToken = strtok(NULL, "");
  582.   
  583.   if (strcasecmp(firstToken, "HELP") == 0 ||
  584.       strcasecmp(firstToken, "?") == 0) {
  585.     executeHelp(allAfterFirstToken);
  586.     DBUG_RETURN(true);
  587.   }
  588.   else if (strcasecmp(firstToken, "CONNECT") == 0) {
  589.     executeConnect(allAfterFirstToken);
  590.     DBUG_RETURN(true);
  591.   }
  592.   else if (strcasecmp(firstToken, "SLEEP") == 0) {
  593.     if (allAfterFirstToken)
  594.       sleep(atoi(allAfterFirstToken));
  595.     DBUG_RETURN(true);
  596.   }
  597.   else if((strcasecmp(firstToken, "QUIT") == 0 ||
  598.   strcasecmp(firstToken, "EXIT") == 0 ||
  599.   strcasecmp(firstToken, "BYE") == 0) && 
  600.   allAfterFirstToken == NULL){
  601.     DBUG_RETURN(false);
  602.   }
  603.   if (!connect())
  604.     DBUG_RETURN(true);
  605.   if (strcasecmp(firstToken, "SHOW") == 0) {
  606.     executeShow(allAfterFirstToken);
  607.     DBUG_RETURN(true);
  608.   }
  609.   else if (strcasecmp(firstToken, "SHUTDOWN") == 0) {
  610.     m_error= executeShutdown(allAfterFirstToken);
  611.     DBUG_RETURN(true);
  612.   }
  613.   else if (strcasecmp(firstToken, "CLUSTERLOG") == 0){
  614.     executeClusterLog(allAfterFirstToken);
  615.     DBUG_RETURN(true);
  616.   }
  617.   else if(strcasecmp(firstToken, "START") == 0 &&
  618.   allAfterFirstToken != NULL &&
  619.   strncasecmp(allAfterFirstToken, "BACKUP", sizeof("BACKUP") - 1) == 0){
  620.     m_error= executeStartBackup(allAfterFirstToken);
  621.     DBUG_RETURN(true);
  622.   }
  623.   else if(strcasecmp(firstToken, "ABORT") == 0 &&
  624.   allAfterFirstToken != NULL &&
  625.   strncasecmp(allAfterFirstToken, "BACKUP", sizeof("BACKUP") - 1) == 0){
  626.     executeAbortBackup(allAfterFirstToken);
  627.     DBUG_RETURN(true);
  628.   }
  629.   else if (strcasecmp(firstToken, "PURGE") == 0) {
  630.     executePurge(allAfterFirstToken);
  631.     DBUG_RETURN(true);
  632.   } 
  633. #ifdef HAVE_GLOBAL_REPLICATION
  634.   else if(strcasecmp(firstToken, "REPLICATION") == 0 ||
  635.   strcasecmp(firstToken, "REP") == 0) {
  636.     executeRep(allAfterFirstToken);
  637.     DBUG_RETURN(true);
  638.   }
  639. #endif // HAVE_GLOBAL_REPLICATION
  640.   else if(strcasecmp(firstToken, "ENTER") == 0 &&
  641.   allAfterFirstToken != NULL &&
  642.   strncasecmp(allAfterFirstToken, "SINGLE USER MODE ", 
  643.   sizeof("SINGLE USER MODE") - 1) == 0){
  644.     executeEnterSingleUser(allAfterFirstToken);
  645.     DBUG_RETURN(true);
  646.   }
  647.   else if(strcasecmp(firstToken, "EXIT") == 0 &&
  648.   allAfterFirstToken != NULL &&
  649.   strncasecmp(allAfterFirstToken, "SINGLE USER MODE ", 
  650.   sizeof("SINGLE USER MODE") - 1) == 0){
  651.     executeExitSingleUser(allAfterFirstToken);
  652.     DBUG_RETURN(true);
  653.   }
  654.   else if (strcasecmp(firstToken, "ALL") == 0) {
  655.     analyseAfterFirstToken(-1, allAfterFirstToken);
  656.   } else {
  657.     /**
  658.      * First token should be a digit, node ID
  659.      */
  660.     int nodeId;
  661.     if (! convert(firstToken, nodeId)) {
  662.       invalid_command(_line);
  663.       DBUG_RETURN(true);
  664.     }
  665.     if (nodeId <= 0) {
  666.       ndbout << "Invalid node ID: " << firstToken << "." << endl;
  667.       DBUG_RETURN(true);
  668.     }
  669.     
  670.     analyseAfterFirstToken(nodeId, allAfterFirstToken);
  671.     
  672.   }
  673.   DBUG_RETURN(true);
  674. }
  675. /**
  676.  * List of commands used as second command argument
  677.  */
  678. static const CommandInterpreter::CommandFunctionPair commands[] = {
  679.   { "START", &CommandInterpreter::executeStart }
  680.   ,{ "RESTART", &CommandInterpreter::executeRestart }
  681.   ,{ "STOP", &CommandInterpreter::executeStop }
  682.   ,{ "STATUS", &CommandInterpreter::executeStatus }
  683.   ,{ "LOGLEVEL", &CommandInterpreter::executeLogLevel }
  684.   ,{ "CLUSTERLOG", &CommandInterpreter::executeEventReporting }
  685. #ifdef ERROR_INSERT
  686.   ,{ "ERROR", &CommandInterpreter::executeError }
  687. #endif
  688.   ,{ "LOG", &CommandInterpreter::executeLog }
  689.   ,{ "LOGIN", &CommandInterpreter::executeLogIn }
  690.   ,{ "LOGOUT", &CommandInterpreter::executeLogOut }
  691.   ,{ "LOGOFF", &CommandInterpreter::executeLogOff }
  692.   ,{ "TESTON", &CommandInterpreter::executeTestOn }
  693.   ,{ "TESTOFF", &CommandInterpreter::executeTestOff }
  694.   ,{ "SET", &CommandInterpreter::executeSet }
  695.   ,{ "GETSTAT", &CommandInterpreter::executeGetStat }
  696.   ,{ "DUMP", &CommandInterpreter::executeDumpState }
  697. };
  698. //*****************************************************************************
  699. //*****************************************************************************
  700. void
  701. CommandInterpreter::analyseAfterFirstToken(int processId,
  702.    char* allAfterFirstToken) {
  703.   
  704.   if (emptyString(allAfterFirstToken)) {
  705.     ndbout << "Expected a command after "
  706.    << ((processId == -1) ? "ALL." : "node ID.") << endl;
  707.     return;
  708.   }
  709.   
  710.   char* secondToken = strtok(allAfterFirstToken, " ");
  711.   char* allAfterSecondToken = strtok(NULL, "");
  712.   const int tmpSize = sizeof(commands)/sizeof(CommandFunctionPair);
  713.   ExecuteFunction fun = 0;
  714.   const char * command = 0;
  715.   for(int i = 0; i<tmpSize; i++){
  716.     if(strcasecmp(secondToken, commands[i].command) == 0){
  717.       fun = commands[i].executeFunction;
  718.       command = commands[i].command;
  719.       break;
  720.     }
  721.   }
  722.   
  723.   if(fun == 0){
  724.     invalid_command(secondToken);
  725.     return;
  726.   }
  727.   
  728.   if(processId == -1){
  729.     executeForAll(command, fun, allAfterSecondToken);
  730.   } else {
  731.     (this->*fun)(processId, allAfterSecondToken, false);
  732.   }
  733.   ndbout << endl;
  734. }
  735. /**
  736.  * Get next nodeid larger than the give node_id. node_id will be
  737.  * set to the next node_id in the list. node_id should be set
  738.  * to 0 (zero) on the first call.
  739.  *
  740.  * @param handle the NDB management handle
  741.  * @param node_id last node_id retreived, 0 at first call
  742.  * @param type type of node to look for
  743.  * @return 1 if a node was found, 0 if no more node exist
  744.  */
  745. static 
  746. int 
  747. get_next_nodeid(struct ndb_mgm_cluster_state *cl,
  748. int *node_id,
  749. enum ndb_mgm_node_type type)
  750. {
  751.   int i;
  752.   
  753.   if(cl == NULL)
  754.     return 0;
  755.   
  756.   i=0;
  757.   while((i < cl->no_of_nodes)) {
  758.     if((*node_id < cl->node_states[i].node_id) &&
  759.        (cl->node_states[i].node_type == type)) {
  760.       
  761.       if(i >= cl->no_of_nodes)
  762. return 0;
  763.       
  764.       *node_id = cl->node_states[i].node_id;
  765.       return 1;
  766.     }
  767.     i++;
  768.   }
  769.   
  770.   return 0;
  771. }
  772. void
  773. CommandInterpreter::executeForAll(const char * cmd, ExecuteFunction fun, 
  774.   const char * allAfterSecondToken)
  775. {
  776.   int nodeId = 0;
  777.   if(strcasecmp(cmd, "STOP") == 0) {
  778.     ndbout_c("Executing STOP on all nodes.");
  779.     (this->*fun)(nodeId, allAfterSecondToken, true);
  780.   } else if(strcasecmp(cmd, "RESTART") == 0) {
  781.     ndbout_c("Executing RESTART on all nodes.");
  782.     ndbout_c("Starting shutdown. This may take a while. Please wait...");
  783.     (this->*fun)(nodeId, allAfterSecondToken, true);
  784.     ndbout_c("Trying to start all nodes of system.");
  785.     ndbout_c("Use ALL STATUS to see the system start-up phases.");
  786.   } else {
  787.     struct ndb_mgm_cluster_state *cl= ndb_mgm_get_status(m_mgmsrv);
  788.     if(cl == 0){
  789.       ndbout_c("Unable get status from management server");
  790.       printError();
  791.       return;
  792.     }
  793.     NdbAutoPtr<char> ap1((char*)cl);
  794.     while(get_next_nodeid(cl, &nodeId, NDB_MGM_NODE_TYPE_NDB))
  795.       (this->*fun)(nodeId, allAfterSecondToken, true);
  796.   }
  797. }
  798. //*****************************************************************************
  799. //*****************************************************************************
  800. bool 
  801. CommandInterpreter::parseBlockSpecification(const char* allAfterLog,
  802.     Vector<const char*>& blocks) 
  803. {
  804.   // Parse: [BLOCK = {ALL|<blockName>+}]
  805.   if (emptyString(allAfterLog)) {
  806.     return true;
  807.   }
  808.   // Copy allAfterLog since strtok will modify it  
  809.   char* newAllAfterLog = my_strdup(allAfterLog,MYF(MY_WME));
  810.   My_auto_ptr<char> ap1(newAllAfterLog);
  811.   char* firstTokenAfterLog = strtok(newAllAfterLog, " ");
  812.   for (unsigned int i = 0; i < strlen(firstTokenAfterLog); ++i) {
  813.     firstTokenAfterLog[i] = toupper(firstTokenAfterLog[i]);
  814.   }
  815.   
  816.   if (strcasecmp(firstTokenAfterLog, "BLOCK") != 0) {
  817.     ndbout << "Unexpected value: " << firstTokenAfterLog 
  818.    << ". Expected BLOCK." << endl;
  819.     return false;
  820.   }
  821.   char* allAfterFirstToken = strtok(NULL, "");
  822.   if (emptyString(allAfterFirstToken)) {
  823.     ndbout << "Expected =." << endl;
  824.     return false;
  825.   }
  826.   char* secondTokenAfterLog = strtok(allAfterFirstToken, " ");
  827.   if (strcasecmp(secondTokenAfterLog, "=") != 0) {
  828.     ndbout << "Unexpected value: " << secondTokenAfterLog 
  829.    << ". Expected =." << endl;
  830.     return false;
  831.   }
  832.   char* blockName = strtok(NULL, " ");
  833.   bool all = false;
  834.   if (blockName != NULL && (strcasecmp(blockName, "ALL") == 0)) {
  835.     all = true;
  836.   }
  837.   while (blockName != NULL) {
  838.     blocks.push_back(strdup(blockName));
  839.     blockName = strtok(NULL, " ");
  840.   }
  841.   if (blocks.size() == 0) {
  842.     ndbout << "No block specified." << endl;
  843.     return false;
  844.   }
  845.   if (blocks.size() > 1 && all) {
  846.     // More than "ALL" specified
  847.     ndbout << "Nothing expected after ALL." << endl;
  848.     return false;
  849.   }
  850.   
  851.   return true;
  852. }
  853. /*****************************************************************************
  854.  * HELP
  855.  *****************************************************************************/
  856. void 
  857. CommandInterpreter::executeHelp(char* parameters)
  858. {
  859.   if (emptyString(parameters)) {
  860.     ndbout << helpText;
  861.     ndbout << endl 
  862.    << "<severity> = " 
  863.    << "ALERT | CRITICAL | ERROR | WARNING | INFO | DEBUG"
  864.    << endl;
  865.     ndbout << "<category> = ";
  866.     for(int i = CFG_MIN_LOGLEVEL; i <= CFG_MAX_LOGLEVEL; i++){
  867.       const char *str= ndb_mgm_get_event_category_string((ndb_mgm_event_category)i);
  868.       if (str) {
  869. if (i != CFG_MIN_LOGLEVEL)
  870.   ndbout << " | ";
  871. ndbout << str;
  872.       }
  873.     }
  874.     ndbout << endl;
  875.     ndbout << "<level>    = " << "0 - 15" << endl;
  876.     ndbout << "<id>       = " << "ALL | Any database node id" << endl;
  877.     ndbout << endl;
  878.   } else if (strcasecmp(parameters, "SHOW") == 0) {
  879.     ndbout << helpTextShow;
  880. #ifdef HAVE_GLOBAL_REPLICATION
  881.   } else if (strcasecmp(parameters, "REPLICATION") == 0 ||
  882.      strcasecmp(parameters, "REP") == 0) {
  883.     ndbout << helpTextRep;
  884. #endif // HAVE_GLOBAL_REPLICATION
  885. #ifdef VM_TRACE // DEBUG ONLY
  886.   } else if (strcasecmp(parameters, "DEBUG") == 0) {
  887.     ndbout << helpTextDebug;
  888. #endif
  889.   } else {
  890.     invalid_command(parameters);
  891.   }
  892. }
  893. /*****************************************************************************
  894.  * SHUTDOWN
  895.  *****************************************************************************/
  896. int
  897. CommandInterpreter::executeShutdown(char* parameters) 
  898.   ndb_mgm_cluster_state *state = ndb_mgm_get_status(m_mgmsrv);
  899.   if(state == NULL) {
  900.     ndbout_c("Could not get status");
  901.     printError();
  902.     return 1;
  903.   }
  904.   NdbAutoPtr<char> ap1((char*)state);
  905.   int result = 0;
  906.   result = ndb_mgm_stop(m_mgmsrv, 0, 0);
  907.   if (result < 0) {
  908.     ndbout << "Shutdown off NDB Cluster storage node(s) failed." << endl;
  909.     printError();
  910.     return result;
  911.   }
  912.   ndbout << result << " NDB Cluster storage node(s) have shutdown." << endl;
  913.   int mgm_id= 0;
  914.   for(int i=0; i < state->no_of_nodes; i++) {
  915.     if(state->node_states[i].node_type == NDB_MGM_NODE_TYPE_MGM &&
  916.        state->node_states[i].version != 0){
  917.       if (mgm_id == 0)
  918. mgm_id= state->node_states[i].node_id;
  919.       else {
  920. ndbout << "Unable to locate management server, "
  921.        << "shutdown manually with <id> STOP"
  922.        << endl;
  923. return 1;
  924.       }
  925.     }
  926.   }
  927.   result = ndb_mgm_stop(m_mgmsrv, 1, &mgm_id);
  928.   if (result <= 0) {
  929.     ndbout << "Shutdown of NDB Cluster management server failed." << endl;
  930.     printError();
  931.     if (result == 0)
  932.       return 1;
  933.     return result;
  934.   }
  935.   m_connected= false;
  936.   disconnect();
  937.   ndbout << "NDB Cluster management server shutdown." << endl;
  938.   return 0;
  939. }
  940. /*****************************************************************************
  941.  * SHOW
  942.  *****************************************************************************/
  943. static
  944. const char *status_string(ndb_mgm_node_status status)
  945. {
  946.   switch(status){
  947.   case NDB_MGM_NODE_STATUS_NO_CONTACT:
  948.     return "not connected";
  949.   case NDB_MGM_NODE_STATUS_NOT_STARTED:
  950.     return "not started";
  951.   case NDB_MGM_NODE_STATUS_STARTING:
  952.     return "starting";
  953.   case NDB_MGM_NODE_STATUS_STARTED:
  954.     return "started";
  955.   case NDB_MGM_NODE_STATUS_SHUTTING_DOWN:
  956.     return "shutting down";
  957.   case NDB_MGM_NODE_STATUS_RESTARTING:
  958.     return "restarting";
  959.   case NDB_MGM_NODE_STATUS_SINGLEUSER:
  960.     return "single user mode";
  961.   default:
  962.     return "unknown state";
  963.   }
  964. }
  965. static void
  966. print_nodes(ndb_mgm_cluster_state *state, ndb_mgm_configuration_iterator *it,
  967.     const char *proc_name, int no_proc, ndb_mgm_node_type type,
  968.     int master_id)
  969.   int i;
  970.   ndbout << "[" << proc_name
  971.  << "(" << ndb_mgm_get_node_type_string(type) << ")]t"
  972.  << no_proc << " node(s)" << endl;
  973.   for(i=0; i < state->no_of_nodes; i++) {
  974.     struct ndb_mgm_node_state *node_state= &(state->node_states[i]);
  975.     if(node_state->node_type == type) {
  976.       int node_id= node_state->node_id;
  977.       ndbout << "id=" << node_id;
  978.       if(node_state->version != 0) {
  979. const char *hostname= node_state->connect_address;
  980. if (hostname == 0
  981.     || strlen(hostname) == 0
  982.     || strcasecmp(hostname,"0.0.0.0") == 0)
  983.   ndbout << " ";
  984. else
  985.   ndbout << "t@" << hostname;
  986. ndbout << "  (Version: "
  987.        << getMajor(node_state->version) << "."
  988.        << getMinor(node_state->version) << "."
  989.        << getBuild(node_state->version);
  990. if (type == NDB_MGM_NODE_TYPE_NDB) {
  991.   if (node_state->node_status != NDB_MGM_NODE_STATUS_STARTED) {
  992.     ndbout << ", " << status_string(node_state->node_status);
  993.   }
  994.   if (node_state->node_group >= 0) {
  995.     ndbout << ", Nodegroup: " << node_state->node_group;
  996.     if (node_state->dynamic_id == master_id)
  997.       ndbout << ", Master";
  998.   }
  999. }
  1000. ndbout << ")" << endl;
  1001.       } else {
  1002. ndb_mgm_first(it);
  1003. if(ndb_mgm_find(it, CFG_NODE_ID, node_id) == 0){
  1004.   const char *config_hostname= 0;
  1005.   ndb_mgm_get_string_parameter(it, CFG_NODE_HOST, &config_hostname);
  1006.   if (config_hostname == 0 || config_hostname[0] == 0)
  1007.     config_hostname= "any host";
  1008.   ndbout_c(" (not connected, accepting connect from %s)",
  1009.    config_hostname);
  1010. }
  1011. else
  1012. {
  1013.   ndbout_c("Unable to find node with id: %d", node_id);
  1014. }
  1015.       }
  1016.     }
  1017.   }
  1018.   ndbout << endl;
  1019. }
  1020. void
  1021. CommandInterpreter::executePurge(char* parameters) 
  1022.   int command_ok= 0;
  1023.   do {
  1024.     if (emptyString(parameters))
  1025.       break;
  1026.     char* firstToken = strtok(parameters, " ");
  1027.     char* nextToken = strtok(NULL, " ");
  1028.     if (strcasecmp(firstToken,"STALE") == 0 &&
  1029. nextToken &&
  1030. strcasecmp(nextToken, "SESSIONS") == 0) {
  1031.       command_ok= 1;
  1032.       break;
  1033.     }
  1034.   } while(0);
  1035.   if (!command_ok) {
  1036.     ndbout_c("Unexpected command, expected: PURGE STALE SESSIONS");
  1037.     return;
  1038.   }
  1039.   int i;
  1040.   char *str;
  1041.   
  1042.   if (ndb_mgm_purge_stale_sessions(m_mgmsrv, &str)) {
  1043.     ndbout_c("Command failed");
  1044.     return;
  1045.   }
  1046.   if (str) {
  1047.     ndbout_c("Purged sessions with node id's: %s", str);
  1048.     free(str);
  1049.   }
  1050.   else
  1051.   {
  1052.     ndbout_c("No sessions purged");
  1053.   }
  1054. }
  1055. void
  1056. CommandInterpreter::executeShow(char* parameters) 
  1057.   int i;
  1058.   if (emptyString(parameters)) {
  1059.     ndb_mgm_cluster_state *state = ndb_mgm_get_status(m_mgmsrv);
  1060.     if(state == NULL) {
  1061.       ndbout_c("Could not get status");
  1062.       printError();
  1063.       return;
  1064.     }
  1065.     NdbAutoPtr<char> ap1((char*)state);
  1066.     ndb_mgm_configuration * conf = ndb_mgm_get_configuration(m_mgmsrv,0);
  1067.     if(conf == 0){
  1068.       ndbout_c("Could not get configuration");
  1069.       printError();
  1070.       return;
  1071.     }
  1072.     ndb_mgm_configuration_iterator * it;
  1073.     it = ndb_mgm_create_configuration_iterator((struct ndb_mgm_configuration *)conf, CFG_SECTION_NODE);
  1074.     if(it == 0){
  1075.       ndbout_c("Unable to create config iterator");
  1076.       return;
  1077.     }
  1078.     NdbAutoPtr<ndb_mgm_configuration_iterator> ptr(it);
  1079.     int
  1080.       master_id= 0,
  1081.       ndb_nodes= 0,
  1082.       api_nodes= 0,
  1083.       mgm_nodes= 0;
  1084.     for(i=0; i < state->no_of_nodes; i++) {
  1085.       if(state->node_states[i].node_type == NDB_MGM_NODE_TYPE_NDB &&
  1086.  state->node_states[i].version != 0){
  1087. master_id= state->node_states[i].dynamic_id;
  1088. break;
  1089.       }
  1090.     }
  1091.     
  1092.     for(i=0; i < state->no_of_nodes; i++) {
  1093.       switch(state->node_states[i].node_type) {
  1094.       case NDB_MGM_NODE_TYPE_API:
  1095. api_nodes++;
  1096. break;
  1097.       case NDB_MGM_NODE_TYPE_NDB:
  1098. if (state->node_states[i].dynamic_id &&
  1099.     state->node_states[i].dynamic_id < master_id)
  1100.   master_id= state->node_states[i].dynamic_id;
  1101. ndb_nodes++;
  1102. break;
  1103.       case NDB_MGM_NODE_TYPE_MGM:
  1104. mgm_nodes++;
  1105. break;
  1106.       case NDB_MGM_NODE_TYPE_UNKNOWN:
  1107.         ndbout << "Error: Unknown Node Type" << endl;
  1108.         return;
  1109.       case NDB_MGM_NODE_TYPE_REP:
  1110. abort();
  1111.       }
  1112.     }
  1113.     ndbout << "Cluster Configuration" << endl
  1114.    << "---------------------" << endl;
  1115.     print_nodes(state, it, "ndbd",     ndb_nodes, NDB_MGM_NODE_TYPE_NDB, master_id);
  1116.     print_nodes(state, it, "ndb_mgmd", mgm_nodes, NDB_MGM_NODE_TYPE_MGM, 0);
  1117.     print_nodes(state, it, "mysqld",   api_nodes, NDB_MGM_NODE_TYPE_API, 0);
  1118.     //    ndbout << helpTextShow;
  1119.     return;
  1120.   } else if (strcasecmp(parameters, "PROPERTIES") == 0 ||
  1121.      strcasecmp(parameters, "PROP") == 0) {
  1122.     ndbout << "SHOW PROPERTIES is not yet implemented." << endl;
  1123.     //  ndbout << "_mgmtSrvr.getConfig()->print();" << endl; /* XXX */
  1124.   } else if (strcasecmp(parameters, "CONFIGURATION") == 0 ||
  1125.      strcasecmp(parameters, "CONFIG") == 0){
  1126.     ndbout << "SHOW CONFIGURATION is not yet implemented." << endl;
  1127.     //nbout << "_mgmtSrvr.getConfig()->printConfigFile();" << endl; /* XXX */
  1128.   } else if (strcasecmp(parameters, "PARAMETERS") == 0 ||
  1129.      strcasecmp(parameters, "PARAMS") == 0 ||
  1130.      strcasecmp(parameters, "PARAM") == 0) {
  1131.     ndbout << "SHOW PARAMETERS is not yet implemented." << endl;
  1132.     //    ndbout << "_mgmtSrvr.getConfig()->getConfigInfo()->print();" 
  1133.     //           << endl; /* XXX */
  1134.   } else {
  1135.     ndbout << "Invalid argument." << endl;
  1136.   }
  1137. }
  1138. void
  1139. CommandInterpreter::executeConnect(char* parameters) 
  1140. {
  1141.   disconnect();
  1142.   if (!emptyString(parameters)) {
  1143.     if (ndb_mgm_set_connectstring(m_mgmsrv,
  1144.   BaseString(parameters).trim().c_str()))
  1145.     {
  1146.       printError();
  1147.       return;
  1148.     }
  1149.   }
  1150.   connect();
  1151. }
  1152. //*****************************************************************************
  1153. //*****************************************************************************
  1154. void 
  1155. CommandInterpreter::executeClusterLog(char* parameters) 
  1156. {
  1157.   DBUG_ENTER("CommandInterpreter::executeClusterLog");
  1158.   int i;
  1159.   if (emptyString(parameters))
  1160.   {
  1161.     ndbout << "Missing argument." << endl;
  1162.     DBUG_VOID_RETURN;
  1163.   }
  1164.   enum ndb_mgm_clusterlog_level severity = NDB_MGM_CLUSTERLOG_ALL;
  1165.     
  1166.   char * tmpString = my_strdup(parameters,MYF(MY_WME));
  1167.   My_auto_ptr<char> ap1(tmpString);
  1168.   char * tmpPtr = 0;
  1169.   char * item = strtok_r(tmpString, " ", &tmpPtr);
  1170.   int enable;
  1171.   Uint32 *enabled = ndb_mgm_get_logfilter(m_mgmsrv);
  1172.   if(enabled == NULL) {
  1173.     ndbout << "Couldn't get status" << endl;
  1174.     printError();
  1175.     DBUG_VOID_RETURN;
  1176.   }
  1177.   /********************
  1178.    * CLUSTERLOG INFO
  1179.    ********************/
  1180.   if (strcasecmp(item, "INFO") == 0) {
  1181.     DBUG_PRINT("info",("INFO"));
  1182.     if(enabled[0] == 0)
  1183.     {
  1184.       ndbout << "Cluster logging is disabled." << endl;
  1185.       DBUG_VOID_RETURN;
  1186.     }
  1187. #if 0 
  1188.     for(i = 0; i<7;i++)
  1189.       printf("enabled[%d] = %dn", i, enabled[i]);
  1190. #endif
  1191.     ndbout << "Severities enabled: ";
  1192.     for(i = 1; i < (int)NDB_MGM_CLUSTERLOG_ALL; i++) {
  1193.       const char *str= ndb_mgm_get_clusterlog_level_string((ndb_mgm_clusterlog_level)i);
  1194.       if (str == 0)
  1195.       {
  1196. DBUG_ASSERT(false);
  1197. continue;
  1198.       }
  1199.       if(enabled[i])
  1200. ndbout << BaseString(str).ndb_toupper() << " ";
  1201.     }
  1202.     ndbout << endl;
  1203.     DBUG_VOID_RETURN;
  1204.   } 
  1205.   else if (strcasecmp(item, "FILTER") == 0 ||
  1206.    strcasecmp(item, "TOGGLE") == 0)
  1207.   {
  1208.     DBUG_PRINT("info",("TOGGLE"));
  1209.     enable= -1;
  1210.   } 
  1211.   else if (strcasecmp(item, "OFF") == 0) 
  1212.   {
  1213.     DBUG_PRINT("info",("OFF"));
  1214.     enable= 0;
  1215.   } else if (strcasecmp(item, "ON") == 0) {
  1216.     DBUG_PRINT("info",("ON"));
  1217.     enable= 1;
  1218.   } else {
  1219.     ndbout << "Invalid argument." << endl;
  1220.     DBUG_VOID_RETURN;
  1221.   }
  1222.   int res_enable;
  1223.   item = strtok_r(NULL, " ", &tmpPtr);
  1224.   if (item == NULL) {
  1225.     res_enable= ndb_mgm_filter_clusterlog(m_mgmsrv,
  1226.   NDB_MGM_CLUSTERLOG_ON, enable, NULL);
  1227.     if (res_enable < 0)
  1228.     {
  1229.       ndbout << "Couldn't set filter" << endl;
  1230.       printError();
  1231.       DBUG_VOID_RETURN;
  1232.     }
  1233.     ndbout << "Cluster logging is " << (res_enable ? "enabled.":"disabled") << endl;
  1234.     DBUG_VOID_RETURN;
  1235.   }
  1236.   do {
  1237.     severity= NDB_MGM_ILLEGAL_CLUSTERLOG_LEVEL;
  1238.     if (strcasecmp(item, "ALL") == 0) {
  1239.       severity = NDB_MGM_CLUSTERLOG_ALL;
  1240.     } else if (strcasecmp(item, "ALERT") == 0) {
  1241.       severity = NDB_MGM_CLUSTERLOG_ALERT;
  1242.     } else if (strcasecmp(item, "CRITICAL") == 0) { 
  1243.       severity = NDB_MGM_CLUSTERLOG_CRITICAL;
  1244.     } else if (strcasecmp(item, "ERROR") == 0) {
  1245.       severity = NDB_MGM_CLUSTERLOG_ERROR;
  1246.     } else if (strcasecmp(item, "WARNING") == 0) {
  1247.       severity = NDB_MGM_CLUSTERLOG_WARNING;
  1248.     } else if (strcasecmp(item, "INFO") == 0) {
  1249.       severity = NDB_MGM_CLUSTERLOG_INFO;
  1250.     } else if (strcasecmp(item, "DEBUG") == 0) {
  1251.       severity = NDB_MGM_CLUSTERLOG_DEBUG;
  1252.     } else if (strcasecmp(item, "OFF") == 0 ||
  1253.        strcasecmp(item, "ON") == 0) {
  1254.       if (enable < 0) // only makes sense with toggle
  1255. severity = NDB_MGM_CLUSTERLOG_ON;
  1256.     }
  1257.     if (severity == NDB_MGM_ILLEGAL_CLUSTERLOG_LEVEL) {
  1258.       ndbout << "Invalid severity level: " << item << endl;
  1259.       DBUG_VOID_RETURN;
  1260.     }
  1261.     res_enable = ndb_mgm_filter_clusterlog(m_mgmsrv, severity, enable, NULL);
  1262.     if (res_enable < 0)
  1263.     {
  1264.       ndbout << "Couldn't set filter" << endl;
  1265.       printError();
  1266.       DBUG_VOID_RETURN;
  1267.     }
  1268.     ndbout << BaseString(item).ndb_toupper().c_str() << " " << (res_enable ? "enabled":"disabled") << endl;
  1269.     item = strtok_r(NULL, " ", &tmpPtr);
  1270.   } while(item != NULL);
  1271.   DBUG_VOID_RETURN;
  1272. //*****************************************************************************
  1273. //*****************************************************************************
  1274. void
  1275. CommandInterpreter::executeStop(int processId, const char *, bool all) 
  1276. {
  1277.   int result = 0;
  1278.   if(all) {
  1279.     result = ndb_mgm_stop(m_mgmsrv, 0, 0);
  1280.   } else {
  1281.     result = ndb_mgm_stop(m_mgmsrv, 1, &processId);
  1282.   }
  1283.   if (result < 0) {
  1284.     ndbout << "Shutdown failed." << endl;
  1285.     printError();
  1286.   } else
  1287.     {
  1288.       if(all)
  1289. ndbout << "NDB Cluster has shutdown." << endl;
  1290.       else
  1291. ndbout << "Node " << processId << " has shutdown." << endl;
  1292.     }
  1293. }
  1294. void
  1295. CommandInterpreter::executeEnterSingleUser(char* parameters) 
  1296. {
  1297.   strtok(parameters, " ");
  1298.   struct ndb_mgm_reply reply;
  1299.   char* id = strtok(NULL, " ");
  1300.   id = strtok(NULL, " ");
  1301.   id = strtok(NULL, "");
  1302.   int nodeId = -1;
  1303.   if(id == 0 || sscanf(id, "%d", &nodeId) != 1){
  1304.     ndbout_c("Invalid arguments: expected <NodeId>");
  1305.     ndbout_c("Use SHOW to see what API nodes are configured");
  1306.     return;
  1307.   }
  1308.   int result = ndb_mgm_enter_single_user(m_mgmsrv, nodeId, &reply);
  1309.   
  1310.   if (result != 0) {
  1311.     ndbout_c("Entering single user mode for node %d failed", nodeId);
  1312.     printError();
  1313.   } else {
  1314.     ndbout_c("Single user mode entered");
  1315.     ndbout_c("Access is granted for API node %d only.", nodeId);
  1316.   }
  1317. }
  1318. void 
  1319. CommandInterpreter::executeExitSingleUser(char* parameters) 
  1320. {
  1321.   int result = ndb_mgm_exit_single_user(m_mgmsrv, 0);
  1322.   if (result != 0) {
  1323.     ndbout_c("Exiting single user mode failed.");
  1324.     printError();
  1325.   } else {
  1326.     ndbout_c("Exiting single user mode in progress.");
  1327.     ndbout_c("Use ALL STATUS or SHOW to see when single user mode has been exited.");
  1328.   }
  1329. }
  1330. void
  1331. CommandInterpreter::executeStart(int processId, const char* parameters,
  1332.  bool all) 
  1333. {
  1334.   int result;
  1335.   if(all) {
  1336.     result = ndb_mgm_start(m_mgmsrv, 0, 0);
  1337.   } else {
  1338.     result = ndb_mgm_start(m_mgmsrv, 1, &processId);
  1339.   }
  1340.   if (result <= 0) {
  1341.     ndbout << "Start failed." << endl;
  1342.     printError();
  1343.   } else
  1344.     {
  1345.       if(all)
  1346. ndbout_c("NDB Cluster is being started.");
  1347.       else
  1348. ndbout_c("Database node %d is being started.", processId);
  1349.     }
  1350. }
  1351. void
  1352. CommandInterpreter::executeRestart(int processId, const char* parameters,
  1353.    bool all) 
  1354. {
  1355.   int result;
  1356.   int nostart = 0;
  1357.   int initialstart = 0;
  1358.   int abort = 0;
  1359.   if(parameters != 0 && strlen(parameters) != 0){
  1360.     char * tmpString = my_strdup(parameters,MYF(MY_WME));
  1361.     My_auto_ptr<char> ap1(tmpString);
  1362.     char * tmpPtr = 0;
  1363.     char * item = strtok_r(tmpString, " ", &tmpPtr);
  1364.     while(item != NULL){
  1365.       if(strcasecmp(item, "-N") == 0)
  1366. nostart = 1;
  1367.       if(strcasecmp(item, "-I") == 0)
  1368. initialstart = 1;
  1369.       if(strcasecmp(item, "-A") == 0)
  1370. abort = 1;
  1371.       item = strtok_r(NULL, " ", &tmpPtr);
  1372.     }
  1373.   }
  1374.   if(all) {
  1375.     result = ndb_mgm_restart2(m_mgmsrv, 0, NULL, initialstart, nostart, abort);
  1376.   } else {
  1377.     int v[1];
  1378.     v[0] = processId;
  1379.     result = ndb_mgm_restart2(m_mgmsrv, 1, v, initialstart, nostart, abort);
  1380.   }
  1381.   
  1382.   if (result <= 0) {
  1383.     ndbout.println("Restart failed.", result);
  1384.     printError();
  1385.   } else
  1386.     {
  1387.       if(all)
  1388. ndbout << "NDB Cluster is being restarted." << endl;
  1389.       else
  1390. ndbout_c("Node %d is being restarted.", processId);
  1391.     }
  1392. }
  1393. void
  1394. CommandInterpreter::executeDumpState(int processId, const char* parameters,
  1395.      bool all) 
  1396. {
  1397.   if(emptyString(parameters)){
  1398.     ndbout << "Expected argument" << endl;
  1399.     return;
  1400.   }
  1401.   Uint32 no = 0;
  1402.   int pars[25];
  1403.   
  1404.   char * tmpString = my_strdup(parameters,MYF(MY_WME));
  1405.   My_auto_ptr<char> ap1(tmpString);
  1406.   char * tmpPtr = 0;
  1407.   char * item = strtok_r(tmpString, " ", &tmpPtr);
  1408.   while(item != NULL){
  1409.     if (0x0 <= strtoll(item, NULL, 0) && strtoll(item, NULL, 0) <= 0xffffffff){
  1410.       pars[no] = strtoll(item, NULL, 0); 
  1411.     } else {
  1412.       ndbout << "Illegal value in argument to signal." << endl
  1413.      << "(Value must be between 0 and 0xffffffff.)" 
  1414.      << endl;
  1415.       return;
  1416.     }
  1417.     no++;
  1418.     item = strtok_r(NULL, " ", &tmpPtr);
  1419.   }
  1420.   ndbout << "Sending dump signal with data:" << endl;
  1421.   for (Uint32 i=0; i<no; i++) {
  1422.     ndbout.setHexFormat(1) << pars[i] << " ";
  1423.     if (!(i+1 & 0x3)) ndbout << endl;
  1424.   }
  1425.   
  1426.   struct ndb_mgm_reply reply;
  1427.   ndb_mgm_dump_state(m_mgmsrv, processId, pars, no, &reply);
  1428. }
  1429. void 
  1430. CommandInterpreter::executeStatus(int processId, 
  1431.   const char* parameters, bool all) 
  1432. {
  1433.   if (! emptyString(parameters)) {
  1434.     ndbout_c("No parameters expected to this command.");
  1435.     return;
  1436.   }
  1437.   ndb_mgm_node_status status;
  1438.   Uint32 startPhase, version;
  1439.   bool system;
  1440.   
  1441.   struct ndb_mgm_cluster_state *cl;
  1442.   cl = ndb_mgm_get_status(m_mgmsrv);
  1443.   if(cl == NULL) {
  1444.     ndbout_c("Cannot get status of node %d.", processId);
  1445.     printError();
  1446.     return;
  1447.   }
  1448.   NdbAutoPtr<char> ap1((char*)cl);
  1449.   int i = 0;
  1450.   while((i < cl->no_of_nodes) && cl->node_states[i].node_id != processId)
  1451.     i++;
  1452.   if(cl->node_states[i].node_id != processId) {
  1453.     ndbout << processId << ": Node not found" << endl;
  1454.     return;
  1455.   }
  1456.   status = cl->node_states[i].node_status;
  1457.   startPhase = cl->node_states[i].start_phase;
  1458.   version = cl->node_states[i].version;
  1459.   ndbout << "Node " << processId << ": " << status_string(status);
  1460.   switch(status){
  1461.   case NDB_MGM_NODE_STATUS_STARTING:
  1462.     ndbout << " (Phase " << startPhase << ")";
  1463.     break;
  1464.   case NDB_MGM_NODE_STATUS_SHUTTING_DOWN:
  1465.     ndbout << " (Phase " << startPhase << ")";
  1466.     break;
  1467.   default:
  1468.     break;
  1469.   }
  1470.   if(status != NDB_MGM_NODE_STATUS_NO_CONTACT)
  1471.     ndbout_c(" (Version %d.%d.%d)", 
  1472.      getMajor(version) ,
  1473.      getMinor(version),
  1474.      getBuild(version));
  1475.   else
  1476.     ndbout << endl;
  1477. }
  1478. //*****************************************************************************
  1479. //*****************************************************************************
  1480. void 
  1481. CommandInterpreter::executeLogLevel(int processId, const char* parameters, 
  1482.     bool all) 
  1483. {
  1484.   (void) all;
  1485.   if (emptyString(parameters)) {
  1486.     ndbout << "Expected argument" << endl;
  1487.     return;
  1488.   } 
  1489.   BaseString tmp(parameters);
  1490.   Vector<BaseString> spec;
  1491.   tmp.split(spec, "=");
  1492.   if(spec.size() != 2){
  1493.     ndbout << "Invalid loglevel specification: " << parameters << endl;
  1494.     return;
  1495.   }
  1496.   spec[0].trim().ndb_toupper();
  1497.   int category = ndb_mgm_match_event_category(spec[0].c_str());
  1498.   if(category == NDB_MGM_ILLEGAL_EVENT_CATEGORY){
  1499.     category = atoi(spec[0].c_str());
  1500.     if(category < NDB_MGM_MIN_EVENT_CATEGORY ||
  1501.        category > NDB_MGM_MAX_EVENT_CATEGORY){
  1502.       ndbout << "Unknown category: "" << spec[0].c_str() << """ << endl;
  1503.       return;
  1504.     }
  1505.   }
  1506.   
  1507.   int level = atoi(spec[1].c_str());
  1508.   if(level < 0 || level > 15){
  1509.     ndbout << "Invalid level: " << spec[1].c_str() << endl;
  1510.     return;
  1511.   }
  1512.   
  1513.   ndbout << "Executing LOGLEVEL on node " << processId << flush;
  1514.   struct ndb_mgm_reply reply;
  1515.   int result;
  1516.   result = ndb_mgm_set_loglevel_node(m_mgmsrv, 
  1517.      processId,
  1518.      (ndb_mgm_event_category)category,
  1519.      level, 
  1520.      &reply);
  1521.   
  1522.   if (result < 0) {
  1523.     ndbout_c(" failed.");
  1524.     printError();
  1525.   } else {
  1526.     ndbout_c(" OK!");
  1527.   }  
  1528.   
  1529. }
  1530. //*****************************************************************************
  1531. //*****************************************************************************
  1532. void CommandInterpreter::executeError(int processId, 
  1533.       const char* parameters, bool /* all */) 
  1534. {
  1535.   if (emptyString(parameters)) {
  1536.     ndbout << "Missing error number." << endl;
  1537.     return;
  1538.   }
  1539.   // Copy parameters since strtok will modify it
  1540.   char* newpar = my_strdup(parameters,MYF(MY_WME)); 
  1541.   My_auto_ptr<char> ap1(newpar);
  1542.   char* firstParameter = strtok(newpar, " ");
  1543.   int errorNo;
  1544.   if (! convert(firstParameter, errorNo)) {
  1545.     ndbout << "Expected an integer." << endl;
  1546.     return;
  1547.   }
  1548.   char* allAfterFirstParameter = strtok(NULL, "");
  1549.   if (! emptyString(allAfterFirstParameter)) {
  1550.     ndbout << "Nothing expected after error number." << endl;
  1551.     return;
  1552.   }
  1553.   ndb_mgm_insert_error(m_mgmsrv, processId, errorNo, NULL);
  1554. }
  1555. //*****************************************************************************
  1556. //*****************************************************************************
  1557. void 
  1558. CommandInterpreter::executeLog(int processId,
  1559.        const char* parameters, bool all) 
  1560. {
  1561.   struct ndb_mgm_reply reply;
  1562.   Vector<const char *> blocks;
  1563.   if (! parseBlockSpecification(parameters, blocks)) {
  1564.     return;
  1565.   }
  1566.   int len=1;
  1567.   Uint32 i;
  1568.   for(i=0; i<blocks.size(); i++) {
  1569.     len += strlen(blocks[i]) + 1;
  1570.   }
  1571.   char * blockNames = (char*)my_malloc(len,MYF(MY_WME));
  1572.   My_auto_ptr<char> ap1(blockNames);
  1573.   
  1574.   blockNames[0] = 0;
  1575.   for(i=0; i<blocks.size(); i++) {
  1576.     strcat(blockNames, blocks[i]);
  1577.     strcat(blockNames, "|");
  1578.   }
  1579.   
  1580.   int result = ndb_mgm_log_signals(m_mgmsrv,
  1581.    processId, 
  1582.    NDB_MGM_SIGNAL_LOG_MODE_INOUT, 
  1583.    blockNames,
  1584.    &reply);
  1585.   if (result != 0) {
  1586.     ndbout_c("Execute LOG on node %d failed.", processId);
  1587.     printError();
  1588.   }
  1589. }
  1590. //*****************************************************************************
  1591. //*****************************************************************************
  1592. void 
  1593. CommandInterpreter::executeLogIn(int /* processId */,
  1594.  const char* parameters, bool /* all */) 
  1595. {
  1596.   ndbout << "Command LOGIN not implemented." << endl;
  1597. }
  1598. //*****************************************************************************
  1599. //*****************************************************************************
  1600. void 
  1601. CommandInterpreter::executeLogOut(int /*processId*/, 
  1602.   const char* parameters, bool /*all*/) 
  1603. {
  1604.   ndbout << "Command LOGOUT not implemented." << endl;
  1605. }
  1606. //*****************************************************************************
  1607. //*****************************************************************************
  1608. void 
  1609. CommandInterpreter::executeLogOff(int /*processId*/,
  1610.   const char* parameters, bool /*all*/) 
  1611. {
  1612.   ndbout << "Command LOGOFF not implemented." << endl;
  1613. }
  1614. //*****************************************************************************
  1615. //*****************************************************************************
  1616. void 
  1617. CommandInterpreter::executeTestOn(int processId,
  1618.   const char* parameters, bool /*all*/) 
  1619. {
  1620.   if (! emptyString(parameters)) {
  1621.     ndbout << "No parameters expected to this command." << endl;
  1622.     return;
  1623.   }
  1624.   struct ndb_mgm_reply reply;
  1625.   int result = ndb_mgm_start_signallog(m_mgmsrv, processId, &reply);
  1626.   if (result != 0) {
  1627.     ndbout_c("Execute TESTON failed.");
  1628.     printError();
  1629.   }
  1630. }
  1631. //*****************************************************************************
  1632. //*****************************************************************************
  1633. void 
  1634. CommandInterpreter::executeTestOff(int processId,
  1635.    const char* parameters, bool /*all*/) 
  1636. {
  1637.   if (! emptyString(parameters)) {
  1638.     ndbout << "No parameters expected to this command." << endl;
  1639.     return;
  1640.   }
  1641.   struct ndb_mgm_reply reply;
  1642.   int result = ndb_mgm_stop_signallog(m_mgmsrv, processId, &reply);
  1643.   if (result != 0) {
  1644.     ndbout_c("Execute TESTOFF failed.");
  1645.     printError();
  1646.   }
  1647. }
  1648. //*****************************************************************************
  1649. //*****************************************************************************
  1650. void 
  1651. CommandInterpreter::executeSet(int /*processId*/, 
  1652.        const char* parameters, bool /*all*/) 
  1653. {
  1654.   if (emptyString(parameters)) {
  1655.     ndbout << "Missing parameter name." << endl;
  1656.     return;
  1657.   }
  1658. #if 0
  1659.   // Copy parameters since strtok will modify it
  1660.   char* newpar = my_strdup(parameters,MYF(MY_WME));
  1661.   My_auto_ptr<char> ap1(newpar);
  1662.   char* configParameterName = strtok(newpar, " ");
  1663.   char* allAfterParameterName = strtok(NULL, "");
  1664.   if (emptyString(allAfterParameterName)) {
  1665.     ndbout << "Missing parameter value." << endl;
  1666.     return;
  1667.   }
  1668.   char* value = strtok(allAfterParameterName, " ");
  1669.   char* allAfterValue = strtok(NULL, "");
  1670.   if (! emptyString(allAfterValue)) {
  1671.     ndbout << "Nothing expected after parameter value." << endl;
  1672.     return;
  1673.   }
  1674.   bool configBackupFileUpdated;
  1675.   bool configPrimaryFileUpdated;
  1676.   
  1677.   // TODO The handling of the primary and backup config files should be 
  1678.   // analysed further.
  1679.   // How it should be handled if only the backup is possible to write.
  1680.   int result = _mgmtSrvr.updateConfigParam(processId, configParameterName, 
  1681.    value, configBackupFileUpdated, 
  1682.    configPrimaryFileUpdated);
  1683.   if (result == 0) {
  1684.     if (configBackupFileUpdated && configPrimaryFileUpdated) {
  1685.       ndbout << "The configuration is updated." << endl;
  1686.     }
  1687.     else if (configBackupFileUpdated && !configPrimaryFileUpdated) {
  1688.       ndbout << "The configuration is updated but it was only possible " 
  1689.      << "to update the backup configuration file, not the primary." 
  1690.      << endl;
  1691.     }
  1692.     else {
  1693.       assert(false);
  1694.     }
  1695.   }
  1696.   else {
  1697.     ndbout << get_error_text(result) << endl;
  1698.     if (configBackupFileUpdated && configPrimaryFileUpdated) {
  1699.       ndbout << "The configuration files are however updated and "
  1700.      << "the value will be used next time the process is restarted." 
  1701.      << endl;
  1702.     }
  1703.     else if (configBackupFileUpdated && !configPrimaryFileUpdated) {
  1704.       ndbout << "It was only possible to update the backup "
  1705.      << "configuration file, not the primary." << endl;
  1706.     }
  1707.     else if (!configBackupFileUpdated && !configPrimaryFileUpdated) {
  1708.       ndbout << "The configuration files are not updated." << endl;
  1709.     }
  1710.     else {
  1711.       // The primary is not tried to write if the write of backup file fails
  1712.       abort();
  1713.     }
  1714.   }
  1715. #endif
  1716. }
  1717. //*****************************************************************************
  1718. //*****************************************************************************
  1719. void CommandInterpreter::executeGetStat(int /*processId*/,
  1720. const char* parameters, bool /*all*/) 
  1721. {
  1722.   if (! emptyString(parameters)) {
  1723.     ndbout << "No parameters expected to this command." << endl;
  1724.     return;
  1725.   }
  1726. #if 0
  1727.   MgmtSrvr::Statistics statistics;
  1728.   int result = _mgmtSrvr.getStatistics(processId, statistics);
  1729.   if (result != 0) {
  1730.     ndbout << get_error_text(result) << endl;
  1731.     return;
  1732.   }
  1733. #endif
  1734.   // Print statistic...
  1735.   /*
  1736.   ndbout << "Number of GETSTAT commands: " 
  1737.   << statistics._test1 << endl;
  1738.   */
  1739. }
  1740. //*****************************************************************************
  1741. //*****************************************************************************
  1742.  
  1743. void 
  1744. CommandInterpreter::executeEventReporting(int processId,
  1745.   const char* parameters, 
  1746.   bool all) 
  1747. {
  1748.   if (emptyString(parameters)) {
  1749.     ndbout << "Expected argument" << endl;
  1750.     return;
  1751.   }
  1752.   BaseString tmp(parameters);
  1753.   Vector<BaseString> specs;
  1754.   tmp.split(specs, " ");
  1755.   for (int i=0; i < specs.size(); i++)
  1756.   {
  1757.     Vector<BaseString> spec;
  1758.     specs[i].split(spec, "=");
  1759.     if(spec.size() != 2){
  1760.       ndbout << "Invalid loglevel specification: " << specs[i] << endl;
  1761.       continue;
  1762.     }
  1763.     spec[0].trim().ndb_toupper();
  1764.     int category = ndb_mgm_match_event_category(spec[0].c_str());
  1765.     if(category == NDB_MGM_ILLEGAL_EVENT_CATEGORY){
  1766.       if(!convert(spec[0].c_str(), category) ||
  1767.  category < NDB_MGM_MIN_EVENT_CATEGORY ||
  1768.  category > NDB_MGM_MAX_EVENT_CATEGORY){
  1769. ndbout << "Unknown category: "" << spec[0].c_str() << """ << endl;
  1770. continue;
  1771.       }
  1772.     }
  1773.     int level;
  1774.     if (!convert(spec[1].c_str(),level))
  1775.     {
  1776.       ndbout << "Invalid level: " << spec[1].c_str() << endl;
  1777.       continue;
  1778.     }
  1779.     ndbout << "Executing CLUSTERLOG " << spec[0] << "=" << spec[1]
  1780.    << " on node " << processId << flush;
  1781.     struct ndb_mgm_reply reply;
  1782.     int result;
  1783.     result = ndb_mgm_set_loglevel_clusterlog(m_mgmsrv, 
  1784.      processId,
  1785.      (ndb_mgm_event_category)category,
  1786.      level, 
  1787.      &reply);
  1788.   
  1789.     if (result != 0) {
  1790.       ndbout_c(" failed."); 
  1791.       printError();
  1792.     } else {
  1793.       ndbout_c(" OK!"); 
  1794.     }
  1795.   }
  1796. }
  1797. /*****************************************************************************
  1798.  * Backup
  1799.  *****************************************************************************/
  1800. int
  1801. CommandInterpreter::executeStartBackup(char* parameters)
  1802. {
  1803.   struct ndb_mgm_reply reply;
  1804.   unsigned int backupId;
  1805. #if 0
  1806.   int filter[] = { 15, NDB_MGM_EVENT_CATEGORY_BACKUP, 0 };
  1807.   int fd = ndb_mgm_listen_event(m_mgmsrv, filter);
  1808.   if (fd < 0)
  1809.   {
  1810.     ndbout << "Initializing start of backup failed" << endl;
  1811.     printError();
  1812.     return fd;
  1813.   }
  1814. #endif
  1815.   Vector<BaseString> args;
  1816.   {
  1817.     BaseString(parameters).split(args);
  1818.     for (unsigned i= 0; i < args.size(); i++)
  1819.       if (args[i].length() == 0)
  1820. args.erase(i--);
  1821.       else
  1822. args[i].ndb_toupper();
  1823.   }
  1824.   int sz= args.size();
  1825.   int result;
  1826.   if (sz == 2 &&
  1827.       args[1] == "NOWAIT")
  1828.   {
  1829.     result = ndb_mgm_start_backup(m_mgmsrv, 0, &backupId, &reply);
  1830.   }
  1831.   else if (sz == 1 ||
  1832.    (sz == 3 &&
  1833.     args[1] == "WAIT" &&
  1834.     args[2] == "COMPLETED"))
  1835.   {
  1836.     ndbout_c("Waiting for completed, this may take several minutes");
  1837.     result = ndb_mgm_start_backup(m_mgmsrv, 2, &backupId, &reply);
  1838.   }
  1839.   else if (sz == 3 &&
  1840.    args[1] == "WAIT" &&
  1841.    args[2] == "STARTED")
  1842.   {
  1843.     ndbout_c("Waiting for started, this may take several minutes");
  1844.     result = ndb_mgm_start_backup(m_mgmsrv, 1, &backupId, &reply);
  1845.   }
  1846.   else
  1847.   {
  1848.     invalid_command(parameters);
  1849.     return -1;
  1850.   }
  1851.   if (result != 0) {
  1852.     ndbout << "Start of backup failed" << endl;
  1853.     printError();
  1854. #if 0
  1855.     close(fd);
  1856. #endif
  1857.     return result;
  1858.   }
  1859. #if 0
  1860.   ndbout_c("Waiting for completed, this may take several minutes");
  1861.   char *tmp;
  1862.   char buf[1024];
  1863.   {
  1864.     SocketInputStream in(fd);
  1865.     int count = 0;
  1866.     do {
  1867.       tmp = in.gets(buf, 1024);
  1868.       if(tmp)
  1869.       {
  1870. ndbout << tmp;
  1871. unsigned int id;
  1872. if(sscanf(tmp, "%*[^:]: Backup %d ", &id) == 1 && id == backupId){
  1873.   count++;
  1874. }
  1875.       }
  1876.     } while(count < 2);
  1877.   }
  1878.   SocketInputStream in(fd, 10);
  1879.   do {
  1880.     tmp = in.gets(buf, 1024);
  1881.     if(tmp && tmp[0] != 0)
  1882.     {
  1883.       ndbout << tmp;
  1884.     }
  1885.   } while(tmp && tmp[0] != 0);
  1886.   close(fd);
  1887. #endif  
  1888.   return 0;
  1889. }
  1890. void
  1891. CommandInterpreter::executeAbortBackup(char* parameters) 
  1892. {
  1893.   int bid = -1;
  1894.   struct ndb_mgm_reply reply;
  1895.   if (emptyString(parameters))
  1896.     goto executeAbortBackupError1;
  1897.   {
  1898.     strtok(parameters, " ");
  1899.     char* id = strtok(NULL, "");
  1900.     if(id == 0 || sscanf(id, "%d", &bid) != 1)
  1901.       goto executeAbortBackupError1;
  1902.   }
  1903.   {
  1904.     int result= ndb_mgm_abort_backup(m_mgmsrv, bid, &reply);
  1905.     if (result != 0) {
  1906.       ndbout << "Abort of backup " << bid << " failed" << endl;
  1907.       printError();
  1908.     } else {
  1909.       ndbout << "Abort of backup " << bid << " ordered" << endl;
  1910.     }
  1911.   }
  1912.   return;
  1913.  executeAbortBackupError1:
  1914.   ndbout << "Invalid arguments: expected <BackupId>" << endl;
  1915.   return;
  1916. }
  1917. #ifdef HAVE_GLOBAL_REPLICATION
  1918. /*****************************************************************************
  1919.  * Global Replication
  1920.  *
  1921.  * For information about the different commands, see
  1922.  * GrepReq::Request in file signaldata/grepImpl.cpp.
  1923.  *
  1924.  * Below are commands as of 2003-07-05 (may change!):
  1925.  * START = 0,            ///< Start Global Replication (all phases)
  1926.  * START_METALOG = 1,    ///< Start Global Replication (all phases)
  1927.  * START_METASCAN = 2,   ///< Start Global Replication (all phases)
  1928.  * START_DATALOG = 3,    ///< Start Global Replication (all phases)
  1929.  * START_DATASCAN = 4,   ///< Start Global Replication (all phases)
  1930.  * START_REQUESTOR = 5,  ///< Start Global Replication (all phases)
  1931.  * ABORT = 6,            ///< Immediate stop (removes subscription)
  1932.  * SLOW_STOP = 7,        ///< Stop after finishing applying current GCI epoch
  1933.  * FAST_STOP = 8,        ///< Stop after finishing applying all PS GCI epochs
  1934.  * START_TRANSFER = 9,   ///< Start SS-PS transfer
  1935.  * STOP_TRANSFER = 10,   ///< Stop SS-PS transfer
  1936.  * START_APPLY = 11,     ///< Start applying GCI epochs in SS
  1937.  * STOP_APPLY = 12,      ///< Stop applying GCI epochs in SS
  1938.  * STATUS = 13,           ///< Status
  1939.  * START_SUBSCR = 14,
  1940.  * REMOVE_BUFFERS = 15,
  1941.  * DROP_TABLE = 16
  1942.  *****************************************************************************/
  1943. void
  1944. CommandInterpreter::executeRep(char* parameters) 
  1945. {
  1946.   if (emptyString(parameters)) {
  1947.     ndbout << helpTextRep;
  1948.     return;
  1949.   }
  1950.   char * line = my_strdup(parameters,MYF(MY_WME));
  1951.   My_auto_ptr<char> ap1((char*)line);
  1952.   char * firstToken = strtok(line, " ");
  1953.   
  1954.   struct ndb_rep_reply  reply;
  1955.   unsigned int          repId;
  1956.   if (!strcasecmp(firstToken, "CONNECT")) {
  1957.     char * host = strtok(NULL, "");
  1958.     for (unsigned int i = 0; i < strlen(host); ++i) {
  1959.       host[i] = tolower(host[i]);
  1960.     }
  1961.     
  1962.     if(host == NULL)
  1963.     {
  1964.       ndbout_c("host:port must be specified.");
  1965.       return;
  1966.     }
  1967.     
  1968.     if(rep_connected) {
  1969.       if(m_repserver != NULL) {
  1970. ndb_rep_disconnect(m_repserver);
  1971. rep_connected = false;
  1972.       }       
  1973.     }
  1974.           
  1975.     if(m_repserver == NULL)
  1976.       m_repserver = ndb_rep_create_handle();
  1977.     if(ndb_rep_connect(m_repserver, host) < 0)
  1978.       ndbout_c("Failed to connect to %s", host); 
  1979.     else
  1980.       rep_connected=true;
  1981.     return;
  1982.     
  1983.     if(!rep_connected) {
  1984.       ndbout_c("Not connected to REP server");
  1985.     }
  1986.   }
  1987.     
  1988.   /********
  1989.    * START 
  1990.    ********/
  1991.   if (!strcasecmp(firstToken, "START")) {
  1992.     
  1993.     unsigned int          req;
  1994.     char *startType = strtok(NULL, "");
  1995.     
  1996.     if (startType == NULL) {                
  1997.       req = GrepReq::START;
  1998.     } else if (!strcasecmp(startType, "SUBSCRIPTION")) {  
  1999.       req = GrepReq::START_SUBSCR;
  2000.     } else if (!strcasecmp(startType, "METALOG")) { 
  2001.       req = GrepReq::START_METALOG;
  2002.     } else if (!strcasecmp(startType, "METASCAN")) {
  2003.       req = GrepReq::START_METASCAN;
  2004.     } else if (!strcasecmp(startType, "DATALOG")) {
  2005.       req = GrepReq::START_DATALOG;
  2006.     } else if (!strcasecmp(startType, "DATASCAN")) {
  2007.       req = GrepReq::START_DATASCAN;
  2008.     } else if (!strcasecmp(startType, "REQUESTOR")) {
  2009.       req = GrepReq::START_REQUESTOR;
  2010.     } else if (!strcasecmp(startType, "TRANSFER")) {
  2011.       req = GrepReq::START_TRANSFER;
  2012.     } else if (!strcasecmp(startType, "APPLY")) {
  2013.       req = GrepReq::START_APPLY;
  2014.     } else if (!strcasecmp(startType, "DELETE")) {
  2015.       req = GrepReq::START_DELETE;
  2016.     } else {
  2017.       ndbout_c("Illegal argument to command 'REPLICATION START'");
  2018.       return;
  2019.     }
  2020.     int result = ndb_rep_command(m_repserver, req, &repId, &reply);
  2021.     
  2022.     if (result != 0) {
  2023.       ndbout << "Start of Global Replication failed" << endl;
  2024.     } else {
  2025.       ndbout << "Start of Global Replication ordered" << endl;
  2026.     }
  2027.     return;
  2028.   }
  2029.   /********
  2030.    * STOP
  2031.    ********/
  2032.   if (!strcasecmp(firstToken, "STOP")) {    
  2033.     unsigned int          req;
  2034.     char *startType = strtok(NULL, " ");
  2035.     unsigned int epoch = 0;
  2036.     
  2037.     if (startType == NULL) {                 
  2038.       /**
  2039.        * Stop immediately
  2040.        */
  2041.       req = GrepReq::STOP;
  2042.     } else if (!strcasecmp(startType, "EPOCH")) {  
  2043.       char *strEpoch = strtok(NULL, "");
  2044.       if(strEpoch == NULL) {
  2045. ndbout_c("Epoch expected!");
  2046. return;
  2047.       }
  2048.       req = GrepReq::STOP;
  2049.       epoch=atoi(strEpoch);      
  2050.     } else if (!strcasecmp(startType, "SUBSCRIPTION")) {  
  2051.       req = GrepReq::STOP_SUBSCR;
  2052.     } else if (!strcasecmp(startType, "METALOG")) { 
  2053.       req = GrepReq::STOP_METALOG;
  2054.     } else if (!strcasecmp(startType, "METASCAN")) {
  2055.       req = GrepReq::STOP_METASCAN;
  2056.     } else if (!strcasecmp(startType, "DATALOG")) {
  2057.       req = GrepReq::STOP_DATALOG;
  2058.     } else if (!strcasecmp(startType, "DATASCAN")) {
  2059.       req = GrepReq::STOP_DATASCAN;
  2060.     } else if (!strcasecmp(startType, "REQUESTOR")) {
  2061.       req = GrepReq::STOP_REQUESTOR;
  2062.     } else if (!strcasecmp(startType, "TRANSFER")) {
  2063.       req = GrepReq::STOP_TRANSFER;
  2064.     } else if (!strcasecmp(startType, "APPLY")) {
  2065.       req = GrepReq::STOP_APPLY;
  2066.     } else if (!strcasecmp(startType, "DELETE")) {
  2067.       req = GrepReq::STOP_DELETE;
  2068.     } else {
  2069.       ndbout_c("Illegal argument to command 'REPLICATION STOP'");
  2070.       return;
  2071.     }
  2072.     int result = ndb_rep_command(m_repserver, req, &repId, &reply, epoch);
  2073.     
  2074.     if (result != 0) {
  2075.       ndbout << "Stop command failed" << endl;
  2076.     } else {
  2077.       ndbout << "Stop ordered" << endl;
  2078.     }
  2079.     return;
  2080.   }
  2081.   /*********
  2082.    * STATUS
  2083.    *********/
  2084.   if (!strcasecmp(firstToken, "STATUS")) {
  2085.     struct rep_state repstate;
  2086.     int result = 
  2087.       ndb_rep_get_status(m_repserver, &repId, &reply, &repstate);
  2088.     
  2089.     if (result != 0) {
  2090.       ndbout << "Status request of Global Replication failed" << endl;
  2091.     } else {
  2092.       ndbout << "Status request of Global Replication ordered" << endl;
  2093.       ndbout << "See printout at one of the DB nodes" << endl;
  2094.       ndbout << "(Better status report is under development.)" << endl;
  2095.       ndbout << " SubscriptionId " << repstate.subid 
  2096.      << " SubscriptionKey " << repstate.subkey << endl;
  2097.     }
  2098.     return;
  2099.   }
  2100.   /*********
  2101.    * QUERY (see repapi.h for querable counters)
  2102.    *********/
  2103.   if (!strcasecmp(firstToken, "QUERY")) {
  2104.     char *query = strtok(NULL, "");
  2105.     int queryCounter=-1;
  2106.     if(query != NULL) {
  2107.       queryCounter = atoi(query);
  2108.     }
  2109.     struct rep_state repstate;
  2110.     unsigned repId = 0;
  2111.     int result = ndb_rep_query(m_repserver, (QueryCounter)queryCounter,
  2112.        &repId, &reply, &repstate);
  2113.     
  2114.     if (result != 0) {
  2115.       ndbout << "Query repserver failed" << endl;
  2116.     } else {
  2117.       ndbout << "Query repserver sucessful" << endl;
  2118.       ndbout_c("repstate : QueryCounter %d, f=%d l=%d"
  2119.        " nodegroups %d" , 
  2120.        repstate.queryCounter,
  2121.        repstate.first[0], repstate.last[0],
  2122.        repstate.no_of_nodegroups );
  2123.     }
  2124.     return;
  2125.   }
  2126. }
  2127. #endif // HAVE_GLOBAL_REPLICATION
  2128. template class Vector<char const*>;