summaryrefslogtreecommitdiff
path: root/ndb/src/mgmsrv/CommandInterpreter.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'ndb/src/mgmsrv/CommandInterpreter.cpp')
-rw-r--r--ndb/src/mgmsrv/CommandInterpreter.cpp1240
1 files changed, 1240 insertions, 0 deletions
diff --git a/ndb/src/mgmsrv/CommandInterpreter.cpp b/ndb/src/mgmsrv/CommandInterpreter.cpp
new file mode 100644
index 00000000000..1e608c05042
--- /dev/null
+++ b/ndb/src/mgmsrv/CommandInterpreter.cpp
@@ -0,0 +1,1240 @@
+/* Copyright (C) 2003 MySQL AB
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
+
+#include "CommandInterpreter.hpp"
+
+#include <string.h>
+#include <ctype.h>
+
+#include "MgmtSrvr.hpp"
+#include "MgmtErrorReporter.hpp"
+#include <NdbOut.hpp>
+#include "convertStrToInt.hpp"
+#include <EventLogger.hpp>
+#include <signaldata/SetLogLevelOrd.hpp>
+#include "ConfigInfo.hpp"
+
+extern "C"
+#include <version.h>
+
+
+static const char* helpTexts[] = {
+ "HELP Print help text",
+ "HELP SHOW Help for the SHOW command",
+#ifdef VM_TRACE // DEBUG ONLY
+ "HELP DEBUG Help for debug compiled version",
+#endif
+ "SHOW Print information about cluster",
+ "SHOW CONFIG Print configuration",
+ "SHOW PARAMETERS Print configuration parameters",
+ "START BACKUP Start backup\n"
+ "ABORT BACKUP <backup id> Aborts backup\n"
+ "CLUSTERLOG ON Enable Cluster logging",
+ "CLUSTERLOG OFF Disable Cluster logging",
+ "CLUSTERLOG FILTER <severity> Toggle severity filter on/off",
+ "CLUSTERLOG INFO Print cluster log information",
+ "{<id>|ALL} START Start DB node (started with -n)",
+ "{<id>|ALL} RESTART [-n] [-i] Restart DB node",
+ "{<id>|ALL} STOP Stop DB node",
+ "{<id>|ALL} STATUS Print status",
+ "{<id>|ALL} CLUSTERLOG {<category>=<level>}+ Set log level for cluster log",
+ "QUIT Quit management server",
+};
+static const int noOfHelpTexts = sizeof(helpTexts)/sizeof(const char*);
+
+static const char* helpTextShow =
+"SHOW prints NDB Cluster information\n\n"
+"SHOW Print information about cluster\n"
+"SHOW CONFIG Print configuration (in initial config file format)\n"
+"SHOW PARAMETERS Print information about configuration parameters\n\n"
+;
+
+#ifdef VM_TRACE // DEBUG ONLY
+static const char* helpTextDebug =
+"SHOW PROPERTIES Print config properties object\n"
+"{<id>|ALL} LOGLEVEL {<category>=<level>}+ Set log level\n"
+"{<id>|ALL} ERROR <errorNo> Inject error into NDB node\n"
+"{<id>|ALL} TRACE <traceNo> Set trace number\n"
+"{<id>|ALL} LOG [BLOCK = {ALL|<block>+}] Set logging on in & out signals\n"
+"{<id>|ALL} LOGIN [BLOCK = {ALL|<block>+}] Set logging on in signals\n"
+"{<id>|ALL} LOGOUT [BLOCK = {ALL|<block>+}] Set logging on out signals\n"
+"{<id>|ALL} LOGOFF [BLOCK = {ALL|<block>+}] Unset signal logging\n"
+"{<id>|ALL} TESTON Start signal logging\n"
+"{<id>|ALL} TESTOFF Stop signal logging\n"
+"{<id>|ALL} SET <configParamName> <value> Update configuration variable\n"
+"{<id>|ALL} DUMP <arg> Dump system state to cluster.log\n"
+"{<id>|ALL} GETSTAT Print statistics\n"
+"\n"
+;
+#endif
+
+
+
+//******************************************************************************
+//******************************************************************************
+CommandInterpreter::CommandInterpreter(MgmtSrvr& mgmtSrvr) :
+ _mgmtSrvr(mgmtSrvr) {
+
+ // _mgmtSrvr.setCallback(CmdBackupCallback);
+}
+
+
+bool emptyString(const char* s) {
+ if (s == NULL) {
+ return true;
+ }
+
+ for (unsigned int i = 0; i < strlen(s); ++i) {
+ if (! isspace(s[i])) {
+ return false;
+ }
+ }
+
+ return true;
+}
+
+class AutoPtr {
+public:
+ AutoPtr(void * ptr) : m_ptr(ptr) {}
+ ~AutoPtr() { free(m_ptr);}
+private:
+ void * m_ptr;
+};
+
+//*****************************************************************************
+//*****************************************************************************
+int CommandInterpreter::readAndExecute() {
+
+ char* _line = readline_gets();
+ char * line;
+ if(_line == NULL) {
+ ndbout << endl;
+ return true;
+ }
+
+ line = strdup(_line);
+
+ AutoPtr ptr(line);
+
+ if (emptyString(line)) {
+ return true;
+ }
+
+ for (unsigned int i = 0; i < strlen(line); ++i) {
+ line[i] = toupper(line[i]);
+ }
+
+ // if there is anything in the line proceed
+ char* firstToken = strtok(line, " ");
+ char* allAfterFirstToken = strtok(NULL, "\0");
+
+ if (strcmp(firstToken, "HELP") == 0) {
+ executeHelp(allAfterFirstToken);
+ return true;
+ }
+ else if (strcmp(firstToken, "?") == 0) {
+ executeHelp(allAfterFirstToken);
+ return true;
+ }
+ else if (strcmp(firstToken, "SHOW") == 0) {
+ executeShow(allAfterFirstToken);
+ return true;
+ }
+ else if (strcmp(firstToken, "CLUSTERLOG") == 0) {
+ executeClusterLog(allAfterFirstToken);
+ return true;
+ }
+ else if(strcmp(firstToken, "START") == 0 &&
+ allAfterFirstToken != 0 &&
+ strncmp(allAfterFirstToken, "BACKUP", sizeof("BACKUP") - 1) == 0){
+ executeStartBackup(allAfterFirstToken);
+ return true;
+ }
+ else if(strcmp(firstToken, "ABORT") == 0 &&
+ allAfterFirstToken != 0 &&
+ strncmp(allAfterFirstToken, "BACKUP", sizeof("BACKUP") - 1) == 0){
+ executeAbortBackup(allAfterFirstToken);
+ return true;
+ }
+
+ else if(strcmp(firstToken, "ENTER") == 0 &&
+ allAfterFirstToken != 0 &&
+ strncmp(allAfterFirstToken, "SINGLE USER MODE ",
+ sizeof("SINGLE USER MODE") - 1) == 0){
+ executeEnterSingleUser(allAfterFirstToken);
+ return true;
+ }
+
+ else if(strcmp(firstToken, "EXIT") == 0 &&
+ allAfterFirstToken != 0 &&
+ strncmp(allAfterFirstToken, "SINGLE USER MODE ",
+ sizeof("SINGLE USER MODE") - 1) == 0){
+ executeExitSingleUser(allAfterFirstToken);
+ return true;
+ }
+
+ else if (strcmp(firstToken, "ALL") == 0) {
+ analyseAfterFirstToken(-1, allAfterFirstToken);
+ }
+ else if(strcmp(firstToken, "QUIT") == 0 ||
+ strcmp(firstToken, "EXIT") == 0 ||
+ strcmp(firstToken, "BYE") == 0){
+ return false;
+ } else {
+ // First token should be a digit, process ID
+
+ int processId;
+ if (! convert(firstToken, processId)) {
+ ndbout << "Invalid command: " << _line << "." << endl;
+ ndbout << "Type HELP for help." << endl << endl;
+ return true;
+ }
+ if (processId < 0) {
+ ndbout << "Invalid process ID: " << firstToken << "." << endl;
+ return true;
+ }
+
+ analyseAfterFirstToken(processId, allAfterFirstToken);
+
+ } // else
+ return true;
+}
+
+
+static const CommandInterpreter::CommandFunctionPair commands[] = {
+ { "START", &CommandInterpreter::executeStart }
+ ,{ "RESTART", &CommandInterpreter::executeRestart }
+ ,{ "STOP", &CommandInterpreter::executeStop }
+ ,{ "STATUS", &CommandInterpreter::executeStatus }
+ ,{ "LOGLEVEL", &CommandInterpreter::executeLogLevel }
+#ifdef ERROR_INSERT
+ ,{ "ERROR", &CommandInterpreter::executeError }
+#endif
+ ,{ "TRACE", &CommandInterpreter::executeTrace }
+ ,{ "LOG", &CommandInterpreter::executeLog }
+ ,{ "LOGIN", &CommandInterpreter::executeLogIn }
+ ,{ "LOGOUT", &CommandInterpreter::executeLogOut }
+ ,{ "LOGOFF", &CommandInterpreter::executeLogOff }
+ ,{ "TESTON", &CommandInterpreter::executeTestOn }
+ ,{ "TESTOFF", &CommandInterpreter::executeTestOff }
+ ,{ "CLUSTERLOG", &CommandInterpreter::executeEventReporting }
+ ,{ "DUMP", &CommandInterpreter::executeDumpState }
+ ,{ "JONAS", &CommandInterpreter::jonas }
+};
+
+
+//*****************************************************************************
+//*****************************************************************************
+void
+CommandInterpreter::analyseAfterFirstToken(int processId,
+ char* allAfterFirstToken) {
+
+ if (emptyString(allAfterFirstToken)) {
+ if (processId == -1) {
+ ndbout << "Expected a command after ALL." << endl;
+ }
+ else {
+ ndbout << "Expected a command after process ID." << endl;
+ }
+ return;
+ }
+
+
+ char* secondToken = strtok(allAfterFirstToken, " ");
+ char* allAfterSecondToken = strtok(NULL, "\0");
+
+ const int tmpSize = sizeof(commands)/sizeof(CommandFunctionPair);
+ ExecuteFunction fun = 0;
+ const char * command = 0;
+ for(int i = 0; i<tmpSize; i++){
+ if(strcmp(secondToken, commands[i].command) == 0){
+ fun = commands[i].executeFunction;
+ command = commands[i].command;
+ break;
+ }
+ }
+
+ if(fun == 0){
+ ndbout << "Invalid command: " << secondToken << "." << endl;
+ ndbout << "Type HELP for help." << endl << endl;
+ return;
+ }
+
+ if(processId == -1){
+ executeForAll(command, fun, allAfterSecondToken);
+ } else {
+ if(strcmp(command, "STATUS") != 0)
+ ndbout << "Executing " << command << " on node: "
+ << processId << endl << endl;
+ (this->*fun)(processId, allAfterSecondToken, false);
+ ndbout << endl;
+ }
+}
+
+void
+CommandInterpreter::executeForAll(const char * cmd, ExecuteFunction fun,
+ const char * allAfterSecondToken){
+
+ NodeId nodeId = 0;
+ if(strcmp(cmd, "STOP") == 0 ||
+ strcmp(cmd, "RESTART") == 0){
+ ndbout << "Executing " << cmd << " on all nodes" << endl << "\n";
+ (this->*fun)(nodeId, allAfterSecondToken, true);
+ } else {
+ while(_mgmtSrvr.getNextNodeId(&nodeId, NDB_MGM_NODE_TYPE_NDB)){
+ if(strcmp(cmd, "STATUS") != 0)
+ ndbout << "Executing " << cmd << " on node: "
+ << nodeId << endl << endl;
+ (this->*fun)(nodeId, allAfterSecondToken, true);
+ ndbout << endl;
+ } // for
+ }
+}
+
+//*****************************************************************************
+//*****************************************************************************
+bool CommandInterpreter::parseBlockSpecification(const char* allAfterLog,
+ Vector<BaseString>& blocks) {
+
+ // Parse: [BLOCK = {ALL|<blockName>+}]
+
+ if (emptyString(allAfterLog)) {
+ return true;
+ }
+
+ // Copy allAfterLog since strtok will modify it
+ char* newAllAfterLog = strdup(allAfterLog);
+ char* firstTokenAfterLog = strtok(newAllAfterLog, " ");
+ for (unsigned int i = 0; i < strlen(firstTokenAfterLog); ++i) {
+ firstTokenAfterLog[i] = toupper(firstTokenAfterLog[i]);
+ }
+
+ if (strcmp(firstTokenAfterLog, "BLOCK") != 0) {
+ ndbout << "Unexpected value: " << firstTokenAfterLog
+ << ". Expected BLOCK." << endl;
+ free(newAllAfterLog);
+ return false;
+ }
+
+ char* allAfterFirstToken = strtok(NULL, "\0");
+ if (emptyString(allAfterFirstToken)) {
+ ndbout << "Expected =." << endl;
+ free(newAllAfterLog);
+ return false;
+ }
+
+ char* secondTokenAfterLog = strtok(allAfterFirstToken, " ");
+ if (strcmp(secondTokenAfterLog, "=") != 0) {
+ ndbout << "Unexpected value: " << secondTokenAfterLog
+ << ". Expected =." << endl;
+ free(newAllAfterLog);
+ return false;
+ }
+
+ char* blockName = strtok(NULL, " ");
+ bool all = false;
+ if (blockName != NULL && (strcmp(blockName, "ALL") == 0)) {
+ all = true;
+ }
+ while (blockName != NULL) {
+ blocks.push_back(BaseString(blockName));
+ blockName = strtok(NULL, " ");
+ }
+
+ if (blocks.size() == 0) {
+ ndbout << "No block specified." << endl;
+ free(newAllAfterLog);
+ return false;
+ }
+ if (blocks.size() > 1 && all) {
+ // More than "ALL" specified
+ ndbout << "Nothing expected after ALL." << endl;
+ free(newAllAfterLog);
+ return false;
+ }
+
+ free(newAllAfterLog);
+ return true;
+}
+
+
+
+//******************************************************************************
+//******************************************************************************
+void CommandInterpreter::executeHelp(char* parameters) {
+
+ (void)parameters; // Don't want compiler warning
+
+ if (emptyString(parameters)) {
+ for (int i = 0; i<noOfHelpTexts; i++) {
+ ndbout << helpTexts[i] << endl;
+ }
+
+ ndbout << endl
+ << "<severity> = "
+ << "ALERT | CRITICAL | ERROR | WARNING | INFO | DEBUG"
+ << endl;
+
+ ndbout << "<category> = ";
+ for(Uint32 i = 0; i<EventLogger::noOfEventCategoryNames; i++){
+ ndbout << EventLogger::eventCategoryNames[i].name;
+ if (i < EventLogger::noOfEventCategoryNames - 1) {
+ ndbout << " | ";
+ }
+ }
+ ndbout << endl;
+
+ ndbout << "<level> = " << "0 - 15"
+ << endl;
+
+ ndbout << endl;
+ } else if (strcmp(parameters, "SHOW") == 0) {
+ ndbout << helpTextShow;
+#ifdef VM_TRACE // DEBUG ONLY
+ } else if (strcmp(parameters, "DEBUG") == 0) {
+ ndbout << helpTextDebug;
+#endif
+ } else {
+ ndbout << "Invalid argument." << endl;
+ }
+}
+
+//*****************************************************************************
+//*****************************************************************************
+
+void CommandInterpreter::executeShow(char* parameters) {
+
+ if (emptyString(parameters)) {
+ ndbout << "Cluster Configuration" << endl
+ << "---------------------" << endl;
+
+ NodeId nodeId = 0;
+ ndbout << _mgmtSrvr.getNodeCount(NDB_MGM_NODE_TYPE_NDB)
+ << " NDB Node(s) with"
+ << endl;
+ while (_mgmtSrvr.getNextNodeId(&nodeId, NDB_MGM_NODE_TYPE_NDB)){
+ ndbout << " Node Id = " << nodeId << endl;
+ }
+ ndbout << endl;
+
+ nodeId = 0;
+ ndbout << _mgmtSrvr.getNodeCount(NDB_MGM_NODE_TYPE_API)
+ << " API Node(s) with"
+ << endl;
+ while (_mgmtSrvr.getNextNodeId(&nodeId, NDB_MGM_NODE_TYPE_API)){
+ ndbout << " Node Id = " << nodeId << endl;
+ }
+ ndbout << endl;
+
+ nodeId = 0;
+ ndbout << _mgmtSrvr.getNodeCount(NDB_MGM_NODE_TYPE_MGM)
+ << " MGM Node(s) with"
+ << endl;
+ while (_mgmtSrvr.getNextNodeId(&nodeId, NDB_MGM_NODE_TYPE_MGM)){
+ ndbout << " Node Id = " << nodeId << endl;
+ }
+ ndbout << endl;
+
+ ndbout << helpTextShow;
+
+ return;
+ } else if (strcmp(parameters, "PROPERTIES") == 0 ||
+ strcmp(parameters, "PROP") == 0) {
+ _mgmtSrvr.getConfig()->print();
+ } else if (strcmp(parameters, "CONFIGURATION") == 0 ||
+ strcmp(parameters, "CONFIG") == 0){
+ _mgmtSrvr.getConfig()->printConfigFile();
+ } else if (strcmp(parameters, "PARAMETERS") == 0 ||
+ strcmp(parameters, "PARAMS") == 0 ||
+ strcmp(parameters, "PARAM") == 0) {
+ _mgmtSrvr.getConfig()->getConfigInfo()->print();
+ } else {
+ ndbout << "Invalid argument." << endl;
+ }
+}
+
+
+//*****************************************************************************
+//*****************************************************************************
+void CommandInterpreter::executeClusterLog(char* parameters) {
+
+ if (parameters != 0 && strlen(parameters) != 0) {
+ int severity = 7;
+ int isOk = true;
+ char name[12];
+ bool noArgs = false;
+
+ char * tmpString = strdup(parameters);
+ char * tmpPtr = 0;
+ char * item = strtok_r(tmpString, " ", &tmpPtr);
+
+ /********************
+ * CLUSTERLOG FILTER
+ ********************/
+ if (strcmp(item, "FILTER") == 0) {
+
+ item = strtok_r(NULL, " ", &tmpPtr);
+ if (item == NULL) {
+ noArgs = true;
+ }
+ while (item != NULL) {
+ snprintf(name, 12, item);
+
+ if (strcmp(item, "ALL") == 0) {
+ severity = 7;
+ } else if (strcmp(item, "ALERT") == 0) {
+ severity = 6;
+ } else if (strcmp(item, "CRITICAL") == 0) {
+ severity = 5;
+ } else if (strcmp(item, "ERROR") == 0) {
+ severity = 4;
+ } else if (strcmp(item, "WARNING") == 0) {
+ severity = 3;
+ } else if (strcmp(item, "INFO") == 0) {
+ severity = 2;
+ } else if (strcmp(item, "DEBUG") == 0) {
+ severity = 1;
+ } else if (strcmp(item, "OFF") == 0) {
+ severity = 0;
+ } else {
+ isOk = false;
+ }
+
+ item = strtok_r(NULL, " ", &tmpPtr);
+ } // while(item != NULL){
+ free(tmpString);
+
+ if (noArgs) {
+ ndbout << "Missing argument(s)." << endl;
+ } else if (isOk) {
+ if (_mgmtSrvr.setEventLogFilter(severity)) {
+ if(strcmp(name, "ALL") == 0 || strcmp(name, "all") == 0) {
+ ndbout << "All severities levels enabled." << endl;
+ } else if(strcmp(name, "OFF") == 0 || strcmp(name, "off") == 0) {
+ ndbout << "Cluster logging disabled." << endl;
+ } else {
+ ndbout << name << " events enabled." << endl;
+ }
+ } else {
+ if(strcmp(name, "ALL") == 0) {
+ ndbout << "All severities levels disabled." << endl;
+ } else if(strcmp(name, "OFF") == 0) {
+ ndbout << "Cluster logging enabled." << endl;
+ } else {
+ ndbout << name << " events disabled." << endl;
+ }
+ }
+ } else {
+ ndbout << "Invalid severity level." << endl;
+ }
+
+ /********************
+ * CLUSTERLOG INFO
+ ********************/
+ } else if (strcmp(item, "INFO") == 0) {
+ const char* names[] = {"DEBUG", "INFO", "WARNING", "ERROR",
+ "CRITICAL", "ALERT"};
+ if (_mgmtSrvr.isEventLogFilterEnabled(0)) { // OFF
+ ndbout << "Cluster logging is disabled." << endl;
+ }
+
+ ndbout << "Severities enabled: ";
+ for (int i = 0; i < 6; i++) {
+ if (_mgmtSrvr.isEventLogFilterEnabled(i + 1)) {
+ ndbout << names[i] << " ";
+ }
+ }
+ ndbout << endl;
+
+ /********************
+ * CLUSTERLOG OFF
+ ********************/
+ } else if (strcmp(item, "OFF") == 0) {
+ if (!_mgmtSrvr.isEventLogFilterEnabled(0)) { // ON
+ if (_mgmtSrvr.setEventLogFilter(0));
+ ndbout << "Cluster logging is disabled." << endl;
+ } else {
+ ndbout << "Cluster logging is already disabled." << endl;
+ }
+
+ /********************
+ * CLUSTERLOG ON
+ ********************/
+ } else if (strcmp(item, "ON") == 0) {
+ if (_mgmtSrvr.isEventLogFilterEnabled(0)) { // OFF
+ if (_mgmtSrvr.setEventLogFilter(0));
+ ndbout << "Cluster logging is enabled." << endl;
+ } else {
+ ndbout << "Cluster logging is already enabled." << endl;
+ }
+
+ } else {
+ ndbout << "Invalid argument." << endl;
+ }
+
+ } else {
+ ndbout << "Missing argument." << endl;
+ }
+}
+
+void
+stopCallback(int nodeId, void * anyData, int errCode){
+ if(errCode == 0){
+ if(nodeId == 0)
+ ndbout << "\nCluster has shutdown" << endl;
+ else
+ ndbout << "\nNode " << nodeId << " has shutdown" << endl;
+ } else {
+ MgmtSrvr * mgm = (MgmtSrvr *)anyData;
+ ndbout << "Node " << nodeId << " has not shutdown: "
+ << mgm->getErrorText(errCode) << endl;
+ }
+}
+
+void
+versionCallback(int nodeId, int version, void * anyData, int errCode){
+ if(errCode == 0){
+ MgmtSrvr * mgm = (MgmtSrvr *)anyData;
+ switch(mgm->getNodeType(nodeId)){
+ case NDB_MGM_NODE_TYPE_MGM:
+ {
+ ndbout << "MGMT node:\t" << nodeId << " ";
+ ndbout_c(" (Version %d.%d.%d)",
+ getMajor(version) ,
+ getMinor(version),
+ getBuild(version));
+ }
+ break;
+ case NDB_MGM_NODE_TYPE_NDB:
+ {
+ ndbout << "DB node:\t" << nodeId << " ";
+ if(version == 0)
+ ndbout << "(no version information available)" << endl;
+ else {
+ ndbout_c(" (Version %d.%d.%d)",
+ getMajor(version) ,
+ getMinor(version),
+ getBuild(version));
+ }
+ }
+ break;
+ case NDB_MGM_NODE_TYPE_API:
+ {
+ ndbout << "API node:\t" << nodeId << " ";
+ if(version == 0)
+ ndbout << "(no version information available)" << endl;
+ else {
+ ndbout_c(" (Version %d.%d.%d)",
+ getMajor(version) ,
+ getMinor(version),
+ getBuild(version));
+ }
+
+ }
+ break;
+ };
+
+ } else {
+ MgmtSrvr * mgm = (MgmtSrvr *)anyData;
+ ndbout << mgm->getErrorText(errCode) << endl;
+ }
+}
+
+//*****************************************************************************
+//*****************************************************************************
+void CommandInterpreter::executeStop(int processId,
+ const char* parameters, bool all) {
+
+ (void)parameters; // Don't want compiler warning
+
+ int result = 0;
+ if(all)
+ result = _mgmtSrvr.stop((int *)0, false, stopCallback, this);
+ else
+ result = _mgmtSrvr.stopNode(processId, false, stopCallback, this);
+
+ if(result != 0)
+ ndbout << _mgmtSrvr.getErrorText(result) << endl;
+}
+
+
+void CommandInterpreter::executeStart(int processId, const char* parameters,
+ bool all) {
+ (void)all; // Don't want compiler warning
+
+ if (! emptyString(parameters)) {
+ ndbout << "No parameters expected to this command." << endl;
+ return;
+ }
+
+ int result = _mgmtSrvr.start(processId);
+ if (result != 0) {
+ ndbout << _mgmtSrvr.getErrorText(result) << endl;
+ }
+}
+
+void
+CommandInterpreter::executeRestart(int processId, const char* parameters,
+ bool all) {
+
+ bool nostart = false;
+ bool initialstart = false;
+
+ if(parameters != 0 && strlen(parameters) != 0){
+ char * tmpString = strdup(parameters);
+ char * tmpPtr = 0;
+ char * item = strtok_r(tmpString, " ", &tmpPtr);
+ while(item != NULL){
+ if(strcmp(item, "-N") == 0)
+ nostart = true;
+ if(strcmp(item, "-I") == 0)
+ initialstart = true;
+ item = strtok_r(NULL, " ", &tmpPtr);
+ }
+ free(tmpString);
+ }
+ int result;
+ if(all)
+ result = _mgmtSrvr.restart(nostart, initialstart, false,
+ 0, stopCallback, this);
+ else
+ result = _mgmtSrvr.restartNode(processId, nostart, initialstart, false,
+ stopCallback,
+ this);
+ if (result != 0) {
+ ndbout << _mgmtSrvr.getErrorText(result) << endl;
+ }
+}
+
+void
+CommandInterpreter::executeDumpState(int processId, const char* parameters,
+ bool all) {
+
+ (void)all; // Don't want compiler warning
+
+ if(parameters == 0 || strlen(parameters) == 0){
+ ndbout << "Expected argument" << endl;
+ return;
+ }
+
+ Uint32 no = 0;
+ Uint32 pars[25];
+
+ char * tmpString = strdup(parameters);
+ char * tmpPtr = 0;
+ char * item = strtok_r(tmpString, " ", &tmpPtr);
+ while(item != NULL){
+ if (0x0 <= strtoll(item, NULL, 0) && strtoll(item, NULL, 0) <= 0xffffffff) {
+ pars[no] = strtoll(item, NULL, 0);
+ } else {
+ ndbout << "Illegal value in argument to signal." << endl
+ << "(Value must be between 0 and 0xffffffff.)"
+ << endl;
+ return;
+ }
+ no++;
+ item = strtok_r(NULL, " ", &tmpPtr);
+ }
+ ndbout << "Sending dump signal with data:" << endl;
+ for (Uint32 i=0; i<no; i++) {
+ ndbout.setHexFormat(1) << pars[i] << " ";
+ if (!(i+1 & 0x3)) ndbout << endl;
+ }
+ free(tmpString);
+ int result = _mgmtSrvr.dumpState(processId, pars, no);
+ if (result != 0) {
+ ndbout << _mgmtSrvr.getErrorText(result) << endl;
+ }
+}
+
+void CommandInterpreter::executeStatus(int processId,
+ const char* parameters, bool all) {
+
+ (void)all; // Don't want compiler warning
+
+ if (! emptyString(parameters)) {
+ ndbout << "No parameters expected to this command." << endl;
+ return;
+ }
+
+ ndb_mgm_node_status status;
+ Uint32 startPhase, version, dynamicId, nodeGroup;
+ bool system;
+ int result = _mgmtSrvr.status(processId,
+ &status, &version, &startPhase, &system,
+ &dynamicId, &nodeGroup);
+ if(result != 0){
+ ndbout << _mgmtSrvr.getErrorText(result) << endl;
+ return;
+ }
+
+ ndbout << "Node " << processId << ": ";
+ switch(status){
+ case NDB_MGM_NODE_STATUS_NO_CONTACT:
+ ndbout << "No contact" << endl;
+ break;
+ case NDB_MGM_NODE_STATUS_NOT_STARTED:
+ ndbout << "Not started" ;
+ break;
+ case NDB_MGM_NODE_STATUS_STARTING:
+ ndbout << "Starting (Start phase " << startPhase << ")" ;
+ break;
+ case NDB_MGM_NODE_STATUS_STARTED:
+ ndbout << "Started" ;
+ break;
+ case NDB_MGM_NODE_STATUS_SHUTTING_DOWN:
+ ndbout << "Shutting down " << (system == false ? "node" : "system")
+ << " (Phase " << startPhase << ")"
+ ;
+ break;
+ case NDB_MGM_NODE_STATUS_RESTARTING:
+ ndbout << "Restarting" ;
+ break;
+ case NDB_MGM_NODE_STATUS_SINGLEUSER:
+ ndbout << "Single user mode" ;
+ break;
+ default:
+ ndbout << "Unknown state" ;
+ break;
+ }
+ if(status != NDB_MGM_NODE_STATUS_NO_CONTACT){
+
+ ndbout_c(" (Version %d.%d.%d)",
+ getMajor(version) ,
+ getMinor(version),
+ getBuild(version));
+
+ // NOTE It's possible to print dynamicId and nodeGroup here ...
+ // ndbout << ", " <<dynamicId<<", "<<nodeGroup<<endl;
+ }
+}
+
+
+
+//*****************************************************************************
+//*****************************************************************************
+void CommandInterpreter::executeLogLevel(int processId,
+ const char* parameters, bool all) {
+ (void)all; // Don't want compiler warning
+ SetLogLevelOrd logLevel; logLevel.clear();
+
+ if (emptyString(parameters) || (strcmp(parameters, "ALL") == 0)) {
+ for(Uint32 i = 0; i<EventLogger::noOfEventCategoryNames; i++)
+ logLevel.setLogLevel(EventLogger::eventCategoryNames[i].category, 7);
+ } else {
+
+ char * tmpString = strdup(parameters);
+ char * tmpPtr = 0;
+ char * item = strtok_r(tmpString, ", ", &tmpPtr);
+ while(item != NULL){
+ char categoryTxt[255];
+ int level;
+ const int m = sscanf(item, "%[^=]=%d", categoryTxt, &level);
+ if(m != 2){
+ free(tmpString);
+ ndbout << "Invalid loglevel specification category=level" << endl;
+ return;
+ }
+ LogLevel::EventCategory cat;
+ if(!EventLogger::matchEventCategory(categoryTxt,
+ &cat)){
+ ndbout << "Invalid loglevel specification, unknown category: "
+ << categoryTxt << endl;
+ free(tmpString);
+ return ;
+ }
+ if(level < 0 || level > 15){
+ ndbout << "Invalid loglevel specification row, level 0-15" << endl;
+ free(tmpString);
+ return ;
+ }
+ logLevel.setLogLevel(cat, level);
+
+ item = strtok_r(NULL, ", ", &tmpPtr);
+ }
+ free(tmpString);
+ }
+
+ int result = _mgmtSrvr.setNodeLogLevel(processId, logLevel);
+ if (result != 0) {
+ ndbout << _mgmtSrvr.getErrorText(result) << endl;
+ }
+}
+
+
+
+//*****************************************************************************
+//*****************************************************************************
+void CommandInterpreter::executeError(int processId,
+ const char* parameters, bool all) {
+
+ (void)all; // Don't want compiler warning
+
+ if (emptyString(parameters)) {
+ ndbout << "Missing error number." << endl;
+ return;
+ }
+ // Copy parameters since strtok will modify it
+ char* newpar = strdup(parameters);
+ char* firstParameter = strtok(newpar, " ");
+
+ int errorNo;
+ if (! convert(firstParameter, errorNo)) {
+ ndbout << "Expected an integer." << endl;
+ free(newpar);
+ return;
+ }
+
+ char* allAfterFirstParameter = strtok(NULL, "\0");
+ if (! emptyString(allAfterFirstParameter)) {
+ ndbout << "Nothing expected after error number." << endl;
+ free(newpar);
+ return;
+ }
+
+ int result = _mgmtSrvr.insertError(processId, errorNo);
+ if (result != 0) {
+ ndbout << _mgmtSrvr.getErrorText(result) << endl;
+ }
+ free(newpar);
+}
+
+
+
+//******************************************************************************
+//******************************************************************************
+void CommandInterpreter::executeTrace(int processId,
+ const char* parameters, bool all) {
+
+ (void)all; // Don't want compiler warning
+
+ if (emptyString(parameters)) {
+ ndbout << "Missing trace number." << endl;
+ return;
+ }
+
+ char* newpar = strdup(parameters);
+ char* firstParameter = strtok(newpar, " ");
+
+
+ int traceNo;
+ if (! convert(firstParameter, traceNo)) {
+ ndbout << "Expected an integer." << endl;
+ free(newpar);
+ return;
+ }
+
+ char* allAfterFirstParameter = strtok(NULL, "\0");
+
+ if (! emptyString(allAfterFirstParameter)) {
+ ndbout << "Nothing expected after trace number." << endl;
+ free(newpar);
+ return;
+ }
+
+ int result = _mgmtSrvr.setTraceNo(processId, traceNo);
+ if (result != 0) {
+ ndbout << _mgmtSrvr.getErrorText(result) << endl;
+ }
+ free(newpar);
+}
+
+
+
+//******************************************************************************
+//******************************************************************************
+void CommandInterpreter::executeLog(int processId,
+ const char* parameters, bool all) {
+
+ (void)all; // Don't want compiler warning
+
+ Vector<BaseString> blocks;
+ if (! parseBlockSpecification(parameters, blocks)) {
+ return;
+ }
+
+ int result = _mgmtSrvr.setSignalLoggingMode(processId, MgmtSrvr::InOut, blocks);
+ if (result != 0) {
+ ndbout << _mgmtSrvr.getErrorText(result) << endl;
+ }
+
+}
+
+
+
+//******************************************************************************
+//******************************************************************************
+void CommandInterpreter::executeLogIn(int processId,
+ const char* parameters, bool all) {
+
+ (void)all; // Don't want compiler warning
+
+ Vector<BaseString> blocks;
+ if (! parseBlockSpecification(parameters, blocks)) {
+ return;
+ }
+
+ int result = _mgmtSrvr.setSignalLoggingMode(processId, MgmtSrvr::In, blocks);
+ if (result != 0) {
+ ndbout << _mgmtSrvr.getErrorText(result) << endl;
+ }
+}
+
+//******************************************************************************
+//******************************************************************************
+void CommandInterpreter::executeLogOut(int processId,
+ const char* parameters, bool all) {
+
+ (void)all; // Don't want compiler warning
+
+ Vector<BaseString> blocks;
+ if (! parseBlockSpecification(parameters, blocks)) {
+ return;
+ }
+
+
+ int result = _mgmtSrvr.setSignalLoggingMode(processId, MgmtSrvr::Out, blocks);
+ if (result != 0) {
+ ndbout << _mgmtSrvr.getErrorText(result) << endl;
+ }
+
+}
+
+
+//******************************************************************************
+//******************************************************************************
+void CommandInterpreter::executeLogOff(int processId,
+ const char* parameters, bool all) {
+
+ (void)all; // Don't want compiler warning
+
+ Vector<BaseString> blocks;
+ if (! parseBlockSpecification(parameters, blocks)) {
+ return;
+ }
+
+
+ int result = _mgmtSrvr.setSignalLoggingMode(processId, MgmtSrvr::Off, blocks);
+ if (result != 0) {
+ ndbout << _mgmtSrvr.getErrorText(result) << endl;
+ }
+
+}
+
+//******************************************************************************
+//******************************************************************************
+void CommandInterpreter::executeTestOn(int processId,
+ const char* parameters, bool all) {
+
+ (void)all; // Don't want compiler warning
+
+ if (! emptyString(parameters)) {
+ ndbout << "No parameters expected to this command." << endl;
+ return;
+ }
+
+ int result = _mgmtSrvr.startSignalTracing(processId);
+ if (result != 0) {
+ ndbout << _mgmtSrvr.getErrorText(result) << endl;
+ }
+
+}
+
+//******************************************************************************
+//******************************************************************************
+void CommandInterpreter::executeTestOff(int processId,
+ const char* parameters, bool all) {
+
+ (void)all; // Don't want compiler warning
+
+ if (! emptyString(parameters)) {
+ ndbout << "No parameters expected to this command." << endl;
+ return;
+ }
+
+ int result = _mgmtSrvr.stopSignalTracing(processId);
+ if (result != 0) {
+ ndbout << _mgmtSrvr.getErrorText(result) << endl;
+ }
+
+}
+
+//*****************************************************************************
+//*****************************************************************************
+void CommandInterpreter::executeEventReporting(int processId,
+ const char* parameters,
+ bool all) {
+ (void)all; // Don't want compiler warning
+ SetLogLevelOrd logLevel; logLevel.clear();
+
+ if (emptyString(parameters) || (strcmp(parameters, "ALL") == 0)) {
+ for(Uint32 i = 0; i<EventLogger::noOfEventCategoryNames; i++)
+ logLevel.setLogLevel(EventLogger::eventCategoryNames[i].category, 7);
+ } else {
+
+ char * tmpString = strdup(parameters);
+ char * tmpPtr = 0;
+ char * item = strtok_r(tmpString, ", ", &tmpPtr);
+ while(item != NULL){
+ char categoryTxt[255];
+ int level;
+ const int m = sscanf(item, "%[^=]=%d", categoryTxt, &level);
+ if(m != 2){
+ free(tmpString);
+ ndbout << "Invalid loglevel specification category=level" << endl;
+ return;
+ }
+ LogLevel::EventCategory cat;
+ if(!EventLogger::matchEventCategory(categoryTxt,
+ &cat)){
+ ndbout << "Invalid loglevel specification, unknown category: "
+ << categoryTxt << endl;
+ free(tmpString);
+ return ;
+ }
+ if(level < 0 || level > 15){
+ ndbout << "Invalid loglevel specification row, level 0-15" << endl;
+ free(tmpString);
+ return ;
+ }
+ logLevel.setLogLevel(cat, level);
+
+ item = strtok_r(NULL, ", ", &tmpPtr);
+ }
+ free(tmpString);
+ }
+ ndbout_c("processId %d", processId);
+ int result = _mgmtSrvr.setEventReportingLevel(processId, logLevel);
+ if (result != 0) {
+ ndbout << _mgmtSrvr.getErrorText(result) << endl;
+ }
+}
+
+void
+CommandInterpreter::executeStartBackup(char* parameters) {
+ Uint32 backupId;
+ int result = _mgmtSrvr.startBackup(backupId);
+ if (result != 0) {
+ ndbout << _mgmtSrvr.getErrorText(result) << endl;
+ } else {
+ // ndbout << "Start of backup ordered" << endl;
+ }
+}
+
+void
+CommandInterpreter::executeAbortBackup(char* parameters) {
+ strtok(parameters, " ");
+ char* id = strtok(NULL, "\0");
+ int bid = -1;
+ if(id == 0 || sscanf(id, "%d", &bid) != 1){
+ ndbout << "Invalid arguments: expected <BackupId>" << endl;
+ return;
+ }
+ int result = _mgmtSrvr.abortBackup(bid);
+ if (result != 0) {
+ ndbout << _mgmtSrvr.getErrorText(result) << endl;
+ } else {
+ ndbout << "Abort of backup " << bid << " ordered" << endl;
+ }
+}
+
+
+
+void
+CommandInterpreter::executeEnterSingleUser(char* parameters) {
+ strtok(parameters, " ");
+ char* id = strtok(NULL, " ");
+ id = strtok(NULL, " ");
+ id = strtok(NULL, "\0");
+ int nodeId = -1;
+ if(id == 0 || sscanf(id, "%d", &nodeId) != 1){
+ ndbout << "Invalid arguments: expected <NodeId>" << endl;
+ return;
+ }
+ int result = _mgmtSrvr.enterSingleUser(0, nodeId,0,0);
+ if (result != 0) {
+ ndbout << _mgmtSrvr.getErrorText(result) << endl;
+ } else {
+ ndbout << "Entering single user mode, granting access for node "
+ << nodeId << " OK." << endl;
+ }
+}
+
+void CommandInterpreter::executeExitSingleUser(char* parameters) {
+ _mgmtSrvr.exitSingleUser(0,0,0,0);
+}
+
+
+#include <NdbApiSignal.hpp>
+
+void
+CommandInterpreter::jonas(int processId, const char* parameters, bool all) {
+
+ MgmtSrvr::Area51 tmp = _mgmtSrvr.getStuff();
+
+ NdbApiSignal signal(0);
+ Uint32 * theData = signal.getDataPtrSend();
+ Uint32 data[25];
+ Uint32 sec0[70];
+ Uint32 sec1[123];
+
+ data[0] = 12;
+ data[1] = 13;
+
+ for(Uint32 i = 0; i<70; i++)
+ sec0[i] = i;
+
+ for(Uint32 i = 0; i<123; i++)
+ sec1[i] = 70+i;
+
+ signal.set(0, CMVMI, GSN_TESTSIG, 3);
+ signal.m_noOfSections = 2;
+ signal.m_fragmentInfo = 1;
+
+ LinearSectionPtr ptr[3];
+
+ theData[0] = 3;
+ theData[1] = 0;
+ theData[2] = 7; // FragmentId
+
+ ptr[0].sz = 2;
+ ptr[0].p = &data[0];
+
+ ptr[1].sz = 60;
+ ptr[1].p = &sec0[0];
+
+ tmp.theFacade->lock_mutex();
+ tmp.theRegistry->prepareSend(&signal, 1, theData, processId, ptr);
+ tmp.theFacade->unlock_mutex();
+
+ signal.set(0, CMVMI, GSN_TESTSIG, 3);
+ signal.m_noOfSections = 2;
+ signal.m_fragmentInfo = 3;
+
+ theData[0] = 0;
+ theData[1] = 1;
+ theData[2] = 7; // FragmentId
+
+ ptr[0].sz = 10;
+ ptr[0].p = &sec0[60];
+
+ ptr[1].sz = 123;
+ ptr[1].p = &sec1[0];
+
+ tmp.theFacade->lock_mutex();
+ tmp.theRegistry->prepareSend(&signal, 1, theData, processId, ptr);
+ tmp.theFacade->unlock_mutex();
+}