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

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 "CommandInterpreter.hpp"
  14. #include <string.h>
  15. #include <ctype.h>
  16. #include "MgmtSrvr.hpp"
  17. #include "MgmtErrorReporter.hpp"
  18. #include <NdbOut.hpp>
  19. #include "convertStrToInt.hpp"
  20. #include <EventLogger.hpp>
  21. #include <signaldata/SetLogLevelOrd.hpp>
  22. #include "ConfigInfo.hpp"
  23. #include <version.h>
  24. #include <m_string.h>
  25. //******************************************************************************
  26. //******************************************************************************
  27. CommandInterpreter::CommandInterpreter(MgmtSrvr& mgmtSrvr) :
  28.   _mgmtSrvr(mgmtSrvr) {
  29. }
  30. bool emptyString(const char* s) {
  31.   if (s == NULL) {
  32.     return true;
  33.   }
  34.   for (unsigned int i = 0; i < strlen(s); ++i) {
  35.     if (! isspace(s[i])) {
  36.       return false;
  37.     }
  38.   }
  39.   return true;
  40. }
  41. class AutoPtr {
  42. public:
  43.   AutoPtr(void * ptr) : m_ptr(ptr) {}
  44.   ~AutoPtr() { free(m_ptr);}
  45. private:
  46.   void * m_ptr;
  47. };
  48. const char *CommandInterpreter::get_error_text(int err_no)
  49. {
  50.   return _mgmtSrvr.getErrorText(err_no, m_err_str, sizeof(m_err_str));
  51. }
  52. //*****************************************************************************
  53. //*****************************************************************************
  54. int CommandInterpreter::readAndExecute() {
  55.   char* _line = readline_gets(); 
  56.   char * line;
  57.   if(_line == NULL) {
  58.     ndbout << endl;
  59.     return true;
  60.   }
  61.   line = strdup(_line);
  62.   
  63.   AutoPtr ptr(line);
  64.   
  65.   if (emptyString(line)) {
  66.     return true;
  67.   }
  68.   
  69.   for (unsigned int i = 0; i < strlen(line); ++i) {
  70.     line[i] = toupper(line[i]);
  71.   }
  72.   // if there is anything in the line proceed
  73.   char* firstToken = strtok(line, " ");
  74.   char* allAfterFirstToken = strtok(NULL, "");
  75.   
  76.   if (strcmp(firstToken, "ALL") == 0) {
  77.     analyseAfterFirstToken(-1, allAfterFirstToken);
  78.   } 
  79.   else if(strcmp(firstToken, "QUIT") == 0 ||
  80.   strcmp(firstToken, "EXIT") == 0 ||
  81.   strcmp(firstToken, "BYE") == 0){
  82.     return false;
  83.   } else {
  84.     // First token should be a digit, process ID
  85.     
  86.     int processId;
  87.     if (! convert(firstToken, processId)) {
  88.       ndbout << "Invalid command: " << _line << "." << endl;
  89.       return true;
  90.     }
  91.     if (processId < 0) {
  92.       ndbout << "Invalid process ID: " << firstToken << "." << endl;
  93.       return true;
  94.     }
  95.     
  96.     analyseAfterFirstToken(processId, allAfterFirstToken);
  97.     
  98.   } // else
  99.   return true;
  100. }
  101. static const CommandInterpreter::CommandFunctionPair commands[] = {
  102.   { "TRACE", &CommandInterpreter::executeTrace }
  103.   ,{ "LOGIN", &CommandInterpreter::executeLogIn }
  104.   ,{ "LOGOUT", &CommandInterpreter::executeLogOut }
  105.   ,{ "LOGOFF", &CommandInterpreter::executeLogOff }
  106. };
  107. //*****************************************************************************
  108. //*****************************************************************************
  109. void
  110. CommandInterpreter::analyseAfterFirstToken(int processId,
  111.    char* allAfterFirstToken) {
  112.   
  113.   if (emptyString(allAfterFirstToken)) {
  114.     if (processId == -1) {
  115.       ndbout << "Expected a command after ALL." << endl;
  116.     }
  117.     else {
  118.       ndbout << "Expected a command after process ID." << endl;
  119.     }
  120.     return;
  121.   }
  122.   
  123.   char* secondToken = strtok(allAfterFirstToken, " ");
  124.   char* allAfterSecondToken = strtok(NULL, "");
  125.   const int tmpSize = sizeof(commands)/sizeof(CommandFunctionPair);
  126.   ExecuteFunction fun = 0;
  127.   const char * command = 0;
  128.   for(int i = 0; i<tmpSize; i++){
  129.     if(strcmp(secondToken, commands[i].command) == 0){
  130.       fun = commands[i].executeFunction;
  131.       command = commands[i].command;
  132.       break;
  133.     }
  134.   }
  135.   
  136.   if(fun == 0){
  137.     ndbout << "Invalid command: " << secondToken << "." << endl;
  138.     return;
  139.   }
  140.   
  141.   if(processId == -1){
  142.     executeForAll(command, fun, allAfterSecondToken);
  143.   } else {
  144.     ndbout << "Executing " << command << " on node: " 
  145.    << processId << endl << endl;
  146.     (this->*fun)(processId, allAfterSecondToken, false);
  147.     ndbout << endl;
  148.   }
  149. }
  150. void
  151. CommandInterpreter::executeForAll(const char * cmd, ExecuteFunction fun, 
  152.   const char * allAfterSecondToken){
  153.   NodeId nodeId = 0;
  154.   while(_mgmtSrvr.getNextNodeId(&nodeId, NDB_MGM_NODE_TYPE_NDB)){
  155.     ndbout << "Executing " << cmd << " on node: " 
  156.    << nodeId << endl << endl;
  157.     (this->*fun)(nodeId, allAfterSecondToken, true);
  158.     ndbout << endl;
  159.   }
  160. }
  161. //*****************************************************************************
  162. //*****************************************************************************
  163. bool CommandInterpreter::parseBlockSpecification(const char* allAfterLog,
  164.  Vector<BaseString>& blocks) {
  165.   
  166.   // Parse: [BLOCK = {ALL|<blockName>+}]
  167.   if (emptyString(allAfterLog)) {
  168.     return true;
  169.   }
  170.   // Copy allAfterLog since strtok will modify it  
  171.   char* newAllAfterLog = strdup(allAfterLog);
  172.   char* firstTokenAfterLog = strtok(newAllAfterLog, " ");
  173.   for (unsigned int i = 0; i < strlen(firstTokenAfterLog); ++i) {
  174.     firstTokenAfterLog[i] = toupper(firstTokenAfterLog[i]);
  175.   }
  176.   
  177.   if (strcmp(firstTokenAfterLog, "BLOCK") != 0) {
  178.     ndbout << "Unexpected value: " << firstTokenAfterLog 
  179.    << ". Expected BLOCK." << endl;
  180.     free(newAllAfterLog);
  181.     return false;
  182.   }
  183.   char* allAfterFirstToken = strtok(NULL, "");
  184.   if (emptyString(allAfterFirstToken)) {
  185.     ndbout << "Expected =." << endl;
  186.     free(newAllAfterLog);
  187.     return false;
  188.   }
  189.   char* secondTokenAfterLog = strtok(allAfterFirstToken, " ");
  190.   if (strcmp(secondTokenAfterLog, "=") != 0) {
  191.     ndbout << "Unexpected value: " << secondTokenAfterLog 
  192.    << ". Expected =." << endl;
  193.     free(newAllAfterLog);
  194.     return false;
  195.   }
  196.   char* blockName = strtok(NULL, " ");
  197.   bool all = false;
  198.   if (blockName != NULL && (strcmp(blockName, "ALL") == 0)) {
  199.     all = true;
  200.   }
  201.   while (blockName != NULL) {
  202.     blocks.push_back(BaseString(blockName));
  203.     blockName = strtok(NULL, " ");
  204.   }
  205.   if (blocks.size() == 0) {
  206.     ndbout << "No block specified." << endl;
  207.     free(newAllAfterLog);
  208.     return false;
  209.   }
  210.   if (blocks.size() > 1 && all) {
  211.     // More than "ALL" specified
  212.     ndbout << "Nothing expected after ALL." << endl;
  213.     free(newAllAfterLog);
  214.     return false;
  215.   }
  216.   
  217.   free(newAllAfterLog);
  218.   return true;
  219. }
  220. void CommandInterpreter::executeLogIn(int processId, 
  221.       const char* parameters, bool all) {
  222.   (void)all;  // Don't want compiler warning
  223.   Vector<BaseString> blocks;
  224.   if (! parseBlockSpecification(parameters, blocks)) {
  225.     return;
  226.   }
  227.   int result = _mgmtSrvr.setSignalLoggingMode(processId, MgmtSrvr::In, blocks);
  228.   if (result != 0) {
  229.     ndbout << get_error_text(result) << endl;
  230.   }
  231. }
  232. //******************************************************************************
  233. //******************************************************************************
  234. void CommandInterpreter::executeLogOut(int processId, 
  235.        const char* parameters, bool all) {
  236.   (void)all;  // Don't want compiler warning
  237.   Vector<BaseString> blocks;
  238.   if (! parseBlockSpecification(parameters, blocks)) {
  239.     return;
  240.   }
  241.   int result = _mgmtSrvr.setSignalLoggingMode(processId, MgmtSrvr::Out, blocks);
  242.   if (result != 0) {
  243.     ndbout << get_error_text(result) << endl;
  244.   }
  245. }
  246. //******************************************************************************
  247. //******************************************************************************
  248. void CommandInterpreter::executeLogOff(int processId, 
  249.        const char* parameters, bool all) {
  250.   (void)all;  // Don't want compiler warning 
  251.   Vector<BaseString> blocks;
  252.   if (! parseBlockSpecification(parameters, blocks)) {
  253.     return;
  254.   }
  255.   int result = _mgmtSrvr.setSignalLoggingMode(processId, MgmtSrvr::Off, blocks);
  256.   if (result != 0) {
  257.     ndbout << get_error_text(result) << endl;
  258.   }
  259. }
  260. void CommandInterpreter::executeTrace(int processId, 
  261.       const char* parameters, bool all) {
  262.   (void)all;  // Don't want compiler warning
  263.   if (emptyString(parameters)) {
  264.     ndbout << "Missing trace number." << endl;
  265.     return;
  266.   }
  267.   char* newpar = strdup(parameters);
  268.   char* firstParameter = strtok(newpar, " ");
  269.   int traceNo;
  270.   if (! convert(firstParameter, traceNo)) {
  271.     ndbout << "Expected an integer." << endl;
  272.     free(newpar);
  273.     return;
  274.   }
  275.   char* allAfterFirstParameter = strtok(NULL, "");  
  276.   if (! emptyString(allAfterFirstParameter)) {
  277.     ndbout << "Nothing expected after trace number." << endl;
  278.     free(newpar);
  279.     return;
  280.   }
  281.   int result = _mgmtSrvr.setTraceNo(processId, traceNo);
  282.   if (result != 0) {
  283.     ndbout << get_error_text(result) << endl;
  284.   }
  285.   free(newpar);
  286. }