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

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 <ctype.h>
  15. #include <uucode.h>
  16. #include <socket_io.h>
  17. #include <ndb_version.h>
  18. #include <mgmapi.h>
  19. #include <EventLogger.hpp>
  20. #include <signaldata/SetLogLevelOrd.hpp>
  21. #include <LogLevel.hpp>
  22. #include <BaseString.hpp>
  23. #include <Base64.hpp>
  24. #include <ConfigValues.hpp>
  25. #include <mgmapi_configuration.hpp>
  26. #include <Vector.hpp>
  27. #include "Services.hpp"
  28. extern bool g_StopServer;
  29. static const unsigned int MAX_READ_TIMEOUT = 1000 ;
  30. static const unsigned int MAX_WRITE_TIMEOUT = 100 ;
  31. /**
  32.    const char * name;
  33.    const char * realName;
  34.    const Type type;
  35.    const ArgType argType;
  36.    const ArgRequired argRequired;
  37.    const ArgMinMax argMinMax;
  38.    const int minVal;
  39.    const int maxVal;
  40.    void (T::* function)(const class Properties & args);
  41.    const char * description;
  42. */
  43. #define MGM_CMD(name, fun, desc) 
  44.  { name, 
  45.    0, 
  46.    ParserRow<MgmApiSession>::Cmd, 
  47.    ParserRow<MgmApiSession>::String, 
  48.    ParserRow<MgmApiSession>::Optional, 
  49.    ParserRow<MgmApiSession>::IgnoreMinMax, 
  50.    0, 0, 
  51.    fun, 
  52.    desc, 0 }
  53. #define MGM_ARG(name, type, opt, desc) 
  54.  { name, 
  55.    0, 
  56.    ParserRow<MgmApiSession>::Arg, 
  57.    ParserRow<MgmApiSession>::type, 
  58.    ParserRow<MgmApiSession>::opt, 
  59.    ParserRow<MgmApiSession>::IgnoreMinMax, 
  60.    0, 0, 
  61.    0, 
  62.   desc, 0 }
  63. #define MGM_ARG2(name, type, opt, min, max, desc) 
  64.  { name, 
  65.    0, 
  66.    ParserRow<MgmApiSession>::Arg, 
  67.    ParserRow<MgmApiSession>::type, 
  68.    ParserRow<MgmApiSession>::opt, 
  69.    ParserRow<MgmApiSession>::IgnoreMinMax, 
  70.    min, max, 
  71.    0, 
  72.   desc, 0 }
  73. #define MGM_END() 
  74.  { 0, 
  75.    0, 
  76.    ParserRow<MgmApiSession>::Arg, 
  77.    ParserRow<MgmApiSession>::Int, 
  78.    ParserRow<MgmApiSession>::Optional, 
  79.    ParserRow<MgmApiSession>::IgnoreMinMax, 
  80.    0, 0, 
  81.    0, 
  82.    0, 0 }
  83. #define MGM_CMD_ALIAS(name, realName, fun) 
  84.  { name, 
  85.    realName, 
  86.    ParserRow<MgmApiSession>::CmdAlias, 
  87.    ParserRow<MgmApiSession>::Int, 
  88.    ParserRow<MgmApiSession>::Optional, 
  89.    ParserRow<MgmApiSession>::IgnoreMinMax, 
  90.    0, 0, 
  91.    0, 
  92.    0, 0 }
  93. #define MGM_ARG_ALIAS(name, realName, fun) 
  94.  { name, 
  95.    realName, 
  96.    ParserRow<MgmApiSession>::ArgAlias, 
  97.    ParserRow<MgmApiSession>::Int, 
  98.    ParserRow<MgmApiSession>::Optional, 
  99.    ParserRow<MgmApiSession>::IgnoreMinMax, 
  100.    0, 0, 
  101.    0, 
  102.    0, 0 }
  103. const
  104. ParserRow<MgmApiSession> commands[] = {
  105.   MGM_CMD("get statport", &MgmApiSession::getStatPort, ""),
  106.   
  107.   MGM_CMD("get config", &MgmApiSession::getConfig, ""),
  108.     MGM_ARG("version", Int, Mandatory, "Configuration version number"),
  109.     MGM_ARG("node", Int, Optional, "Node ID"),
  110.   MGM_CMD("get nodeid", &MgmApiSession::get_nodeid, ""),
  111.     MGM_ARG("version", Int, Mandatory, "Configuration version number"),
  112.     MGM_ARG("nodetype", Int, Mandatory, "Node type"),
  113.     MGM_ARG("transporter", String, Optional, "Transporter type"),
  114.     MGM_ARG("nodeid", Int, Optional, "Node ID"),
  115.     MGM_ARG("user", String, Mandatory, "Password"),
  116.     MGM_ARG("password", String, Mandatory, "Password"),
  117.     MGM_ARG("public key", String, Mandatory, "Public key"),
  118.     MGM_ARG("endian", String, Optional, "Endianness"),
  119.   MGM_CMD("get version", &MgmApiSession::getVersion, ""),
  120.   
  121.   MGM_CMD("get status", &MgmApiSession::getStatus, ""),
  122.   MGM_CMD("get info clusterlog", &MgmApiSession::getInfoClusterLog, ""),
  123.   MGM_CMD("restart node", &MgmApiSession::restart, ""),
  124.     MGM_ARG("node", String, Mandatory, "Nodes to restart"),
  125.     MGM_ARG("initialstart", Int, Optional, "Initial start"),
  126.     MGM_ARG("nostart", Int, Optional, "No start"),
  127.     MGM_ARG("abort", Int, Optional, "Abort"),
  128.   MGM_CMD("restart all", &MgmApiSession::restartAll, ""),
  129.     MGM_ARG("initialstart", Int, Optional, "Initial start"),
  130.     MGM_ARG("nostart", Int, Optional, "No start"),
  131.     MGM_ARG("abort", Int, Optional, "Abort"),
  132.   MGM_CMD("insert error", &MgmApiSession::insertError, ""),
  133.     MGM_ARG("node", Int, Mandatory, "Node to receive error"),
  134.     MGM_ARG("error", Int, Mandatory, "Errorcode to insert"),
  135.   MGM_CMD("set trace", &MgmApiSession::setTrace, ""),
  136.     MGM_ARG("node", Int, Mandatory, "Node"),
  137.     MGM_ARG("trace", Int, Mandatory, "Trace number"),
  138.   MGM_CMD("log signals", &MgmApiSession::logSignals, ""),
  139.     MGM_ARG("node", Int, Mandatory, "Node"),
  140.     MGM_ARG("blocks", String, Mandatory, "Blocks (space separated)"),
  141.     MGM_ARG("in", Int, Mandatory, "Log input signals"),
  142.     MGM_ARG("out", Int, Mandatory, "Log output signals"),
  143.   MGM_CMD("start signallog", &MgmApiSession::startSignalLog, ""),
  144.     MGM_ARG("node", Int, Mandatory, "Node"),
  145.   MGM_CMD("stop signallog", &MgmApiSession::stopSignalLog, ""),
  146.     MGM_ARG("node", Int, Mandatory, "Node"),
  147.   MGM_CMD("dump state", &MgmApiSession::dumpState, ""),
  148.     MGM_ARG("node", Int, Mandatory ,"Node"),
  149.     MGM_ARG("args", String, Mandatory, "Args(space separated int's)"),
  150.   MGM_CMD("start backup", &MgmApiSession::startBackup, ""),
  151.     MGM_ARG("completed", Int, Optional ,"Wait until completed"),
  152.   MGM_CMD("abort backup", &MgmApiSession::abortBackup, ""),
  153.     MGM_ARG("id", Int, Mandatory, "Backup id"),
  154.   /**
  155.    *  Global Replication
  156.    */
  157.   MGM_CMD("rep", &MgmApiSession::repCommand, ""),
  158.     MGM_ARG("request", Int, Mandatory, "Command"),
  159.   MGM_CMD("stop", &MgmApiSession::stop, ""),
  160.     MGM_ARG("node", String, Mandatory, "Node"),
  161.     MGM_ARG("abort", Int, Mandatory, "Node"),
  162.   MGM_CMD("stop all", &MgmApiSession::stopAll, ""),
  163.     MGM_ARG("abort", Int, Mandatory, "Node"),
  164.   
  165.   MGM_CMD("enter single user", &MgmApiSession::enterSingleUser, ""),
  166.     MGM_ARG("nodeId", Int, Mandatory, "Node"),
  167.   
  168.   MGM_CMD("exit single user", &MgmApiSession::exitSingleUser, ""),
  169.   
  170.   MGM_CMD("start", &MgmApiSession::start, ""),
  171.     MGM_ARG("node", Int, Mandatory, "Node"),
  172.   MGM_CMD("start all", &MgmApiSession::startAll, ""),
  173.   MGM_CMD("bye", &MgmApiSession::bye, ""),
  174.   MGM_CMD("set loglevel", &MgmApiSession::setLogLevel, ""),
  175.     MGM_ARG("node", Int, Mandatory, "Node"),
  176.     MGM_ARG("category", Int, Mandatory, "Event category"),
  177.     MGM_ARG("level", Int, Mandatory, "Log level (0-15)"),
  178.   MGM_CMD("set cluster loglevel", &MgmApiSession::setClusterLogLevel, ""),
  179.     MGM_ARG("node", Int, Mandatory, "Node"),
  180.     MGM_ARG("category", Int, Mandatory, "Event category"),
  181.     MGM_ARG("level", Int, Mandatory, "Log level (0-15)"),
  182.   MGM_CMD("set logfilter", &MgmApiSession::setLogFilter, ""),
  183.     MGM_ARG("level", Int, Mandatory, "Severety level"),
  184.     MGM_ARG("enable", Int, Mandatory, "1=disable, 0=enable, -1=toggle"),
  185.   MGM_CMD("set parameter", &MgmApiSession::setParameter, ""),
  186.     MGM_ARG("node", String, Mandatory, "Node"),
  187.     MGM_ARG("parameter", String, Mandatory, "Parameter"),
  188.     MGM_ARG("value", String, Mandatory, "Value"),
  189.   MGM_CMD("listen event", &MgmApiSession::listen_event, ""),
  190.     MGM_ARG("node", Int, Optional, "Node"),  
  191.     MGM_ARG("filter", String, Mandatory, "Event category"),
  192.   MGM_CMD("purge stale sessions", &MgmApiSession::purge_stale_sessions, ""),
  193.   MGM_CMD("check connection", &MgmApiSession::check_connection, ""),
  194.   MGM_END()
  195. };
  196. MgmApiSession::MgmApiSession(class MgmtSrvr & mgm, NDB_SOCKET_TYPE sock)
  197.   : SocketServer::Session(sock), m_mgmsrv(mgm)
  198. {
  199.   DBUG_ENTER("MgmApiSession::MgmApiSession");
  200.   m_input = new SocketInputStream(sock);
  201.   m_output = new SocketOutputStream(sock);
  202.   m_parser = new Parser_t(commands, *m_input, true, true, true);
  203.   m_allocated_resources= new MgmtSrvr::Allocated_resources(m_mgmsrv);
  204.   DBUG_VOID_RETURN;
  205. }
  206. MgmApiSession::~MgmApiSession()
  207. {
  208.   DBUG_ENTER("MgmApiSession::~MgmApiSession");
  209.   if (m_input)
  210.     delete m_input;
  211.   if (m_output)
  212.     delete m_output;
  213.   if (m_parser)
  214.     delete m_parser;
  215.   if (m_allocated_resources)
  216.     delete m_allocated_resources;
  217.   if(m_socket != NDB_INVALID_SOCKET)
  218.   {
  219.     NDB_CLOSE_SOCKET(m_socket);
  220.     m_socket= NDB_INVALID_SOCKET;
  221.   }
  222.   DBUG_VOID_RETURN;
  223. }
  224. void
  225. MgmApiSession::runSession()
  226. {
  227.   DBUG_ENTER("MgmApiSession::runSession");
  228.   Parser_t::Context ctx;
  229.   while(!m_stop) {
  230.     m_parser->run(ctx, *this);
  231.     if(ctx.m_currentToken == 0)
  232.       break;
  233.     switch(ctx.m_status) {
  234.     case Parser_t::UnknownCommand:
  235. #ifdef MGM_GET_CONFIG_BACKWARDS_COMPAT
  236.       /* Backwards compatibility for old NDBs that still use
  237.        * the old "GET CONFIG" command.
  238.        */
  239.   size_t i;
  240.       for(i=0; i<strlen(ctx.m_currentToken); i++)
  241. ctx.m_currentToken[i] = toupper(ctx.m_currentToken[i]);
  242.       if(strncmp("GET CONFIG ", 
  243.  ctx.m_currentToken,
  244.  strlen("GET CONFIG ")) == 0)
  245. getConfig_old(ctx);
  246. #endif /* MGM_GET_CONFIG_BACKWARDS_COMPAT */
  247.       break;
  248.     default:
  249.       break;
  250.     }
  251.   }
  252.   if(m_socket != NDB_INVALID_SOCKET)
  253.   {
  254.     NDB_CLOSE_SOCKET(m_socket);
  255.     m_socket= NDB_INVALID_SOCKET;
  256.   }
  257.   DBUG_VOID_RETURN;
  258. }
  259. #ifdef MGM_GET_CONFIG_BACKWARDS_COMPAT
  260. void
  261. MgmApiSession::getConfig_old(Parser_t::Context &ctx) {
  262.   Properties args;
  263.   Uint32 version, node;
  264.   if(sscanf(ctx.m_currentToken, "GET CONFIG %d %d",
  265.     (int *)&version, (int *)&node) != 2) {
  266.     m_output->println("Expected 2 arguments for GET CONFIG");
  267.     return;
  268.   }
  269.   /* Put arguments in properties object so we can call the real function */  
  270.   args.put("version", version);
  271.   args.put("node", node);
  272.   getConfig_common(ctx, args, true);
  273. }
  274. #endif /* MGM_GET_CONFIG_BACKWARDS_COMPAT */
  275. void
  276. MgmApiSession::getConfig(Parser_t::Context &ctx, 
  277.  const class Properties &args) {
  278.   getConfig_common(ctx, args);
  279. }
  280. static Properties *
  281. backward(const char * base, const Properties* reply){
  282.   Properties * ret = new Properties();
  283.   Properties::Iterator it(reply);
  284.   for(const char * name = it.first(); name != 0; name=it.next()){
  285.     PropertiesType type;
  286.     reply->getTypeOf(name, &type);
  287.     switch(type){
  288.     case PropertiesType_Uint32:{
  289.       Uint32 val;
  290.       reply->get(name, &val);
  291.       ret->put(name, val);
  292.     }
  293.       break;
  294.     case PropertiesType_char:
  295.       {
  296. const char * val;
  297. reply->get(name, &val);
  298. ret->put(name, val);
  299. if(!strcmp(name, "Type") && !strcmp(val, "DB")){
  300.   ret->put("NoOfDiskBufferPages", (unsigned)0);
  301.   ret->put("NoOfDiskFiles", (unsigned)0);
  302.   ret->put("NoOfDiskClusters", (unsigned)0);
  303.   ret->put("NoOfFreeDiskClusters", (unsigned)0);
  304.   ret->put("NoOfDiskClustersPerDiskFile", (unsigned)0);
  305.   ret->put("NoOfConcurrentCheckpointsDuringRestart", (unsigned)1);
  306.   ret->put("NoOfConcurrentCheckpointsAfterRestart", (unsigned)1);
  307.   ret->put("NoOfConcurrentProcessesHandleTakeover", (unsigned)1);
  308. }
  309.       }
  310.       break;
  311.     case PropertiesType_Properties:
  312.       {
  313. const Properties * recurse;
  314. reply->get(name, &recurse);
  315. Properties * val = backward(name, recurse);
  316. ret->put(name, val);
  317.       }
  318.       break;
  319.     case PropertiesType_Uint64:
  320.       break;
  321.     }
  322.   }
  323.   return ret;
  324. }
  325. void
  326. MgmApiSession::get_nodeid(Parser_t::Context &,
  327.   const class Properties &args)
  328. {
  329.   const char *cmd= "get nodeid reply";
  330.   Uint32 version, nodeid= 0, nodetype= 0xff;
  331.   const char * transporter;
  332.   const char * user;
  333.   const char * password;
  334.   const char * public_key;
  335.   const char * endian= NULL;
  336.   union { long l; char c[sizeof(long)]; } endian_check;
  337.   args.get("version", &version);
  338.   args.get("nodetype", &nodetype);
  339.   args.get("transporter", &transporter);
  340.   args.get("nodeid", &nodeid);
  341.   args.get("user", &user);
  342.   args.get("password", &password);
  343.   args.get("public key", &public_key);
  344.   args.get("endian", &endian);
  345.   endian_check.l = 1;
  346.   if(endian 
  347.      && strcmp(endian,(endian_check.c[sizeof(long)-1])?"big":"little")!=0) {
  348.     m_output->println(cmd);
  349.     m_output->println("result: Node does not have the same endianness as the management server.");
  350.     m_output->println("");
  351.     return;
  352.   }
  353.   bool compatible;
  354.   switch (nodetype) {
  355.   case NODE_TYPE_MGM:
  356.   case NODE_TYPE_API:
  357.     compatible = ndbCompatible_mgmt_api(NDB_VERSION, version);
  358.     break;
  359.   case NODE_TYPE_DB:
  360.     compatible = ndbCompatible_mgmt_ndb(NDB_VERSION, version);
  361.     break;
  362.   default:
  363.     m_output->println(cmd);
  364.     m_output->println("result: unknown nodetype %d", nodetype);
  365.     m_output->println("");
  366.     return;
  367.   }
  368.   struct sockaddr addr;
  369.   SOCKET_SIZE_TYPE addrlen= sizeof(addr);
  370.   int r = getpeername(m_socket, &addr, &addrlen);
  371.   if (r != 0 ) {
  372.     m_output->println(cmd);
  373.     m_output->println("result: getpeername(%d) failed, err= %d", m_socket, r);
  374.     m_output->println("");
  375.     return;
  376.   }
  377.   NodeId tmp= nodeid;
  378.   if(tmp == 0 || !m_allocated_resources->is_reserved(tmp)){
  379.     BaseString error_string;
  380.     if (!m_mgmsrv.alloc_node_id(&tmp, (enum ndb_mgm_node_type)nodetype, 
  381. &addr, &addrlen, error_string)){
  382.       const char *alias;
  383.       const char *str;
  384.       alias= ndb_mgm_get_node_type_alias_string((enum ndb_mgm_node_type)
  385. nodetype, &str);
  386.       m_output->println(cmd);
  387.       m_output->println("result: %s", error_string.c_str());
  388.       m_output->println("");
  389.       return;
  390.     }
  391.   }    
  392.   
  393. #if 0
  394.   if (!compatible){
  395.     m_output->println(cmd);
  396.     m_output->println("result: incompatible version mgmt 0x%x and node 0x%x",
  397.       NDB_VERSION, version);
  398.     m_output->println("");
  399.     return;
  400.   }
  401. #endif
  402.   
  403.   m_output->println(cmd);
  404.   m_output->println("nodeid: %u", tmp);
  405.   m_output->println("result: Ok");
  406.   m_output->println("");
  407.   m_allocated_resources->reserve_node(tmp);
  408.   
  409.   return;
  410. }
  411. void
  412. MgmApiSession::getConfig_common(Parser_t::Context &,
  413. const class Properties &args,
  414. bool compat) {
  415.   Uint32 version, node = 0;
  416.   args.get("version", &version);
  417.   args.get("node", &node);
  418.   const Config *conf = m_mgmsrv.getConfig();
  419.   if(conf == NULL) {
  420.     m_output->println("get config reply");
  421.     m_output->println("result: Could not fetch configuration");
  422.     m_output->println("");
  423.     return;
  424.   }
  425.   if(version > 0 && version < makeVersion(3, 5, 0) && compat){
  426.     Properties *reply = backward("", conf->m_oldConfig);
  427.     reply->put("Version", version);
  428.     reply->put("LocalNodeId", node);
  429.     backward("", reply);
  430.     //reply->print();
  431.     
  432.     const Uint32 size = reply->getPackedSize();
  433.     Uint32 *buffer = new Uint32[size/4+1];
  434.     
  435.     reply->pack(buffer);
  436.     delete reply;
  437.     
  438.     const int uurows = (size + 44)/45;
  439.     char * uubuf = new char[uurows * 62+5];
  440.       
  441.     const int uusz = uuencode_mem(uubuf, (char *)buffer, size);
  442.     delete[] buffer;
  443.       
  444.     m_output->println("GET CONFIG %d %d %d %d %d",
  445.       0, version, node, size, uusz);
  446.     
  447.     m_output->println("begin 664 Ndb_cfg.bin");
  448.       
  449.     /* XXX Need to write directly to the socket, because the uubuf is not
  450.      * NUL-terminated. This could/should probably be done in a nicer way.
  451.      */
  452.     write_socket(m_socket, MAX_WRITE_TIMEOUT, uubuf, uusz);
  453.     delete[] uubuf;
  454.       
  455.     m_output->println("end");
  456.     m_output->println("");
  457.     return;
  458.   }
  459.   if(compat){
  460.     m_output->println("GET CONFIG %d %d %d %d %d",1, version, 0, 0, 0);
  461.     return;
  462.   }
  463.   if(node != 0){
  464.     bool compatible;
  465.     switch (m_mgmsrv.getNodeType(node)) {
  466.     case NDB_MGM_NODE_TYPE_NDB:
  467.       compatible = ndbCompatible_mgmt_ndb(NDB_VERSION, version);
  468.       break;
  469.     case NDB_MGM_NODE_TYPE_API:
  470.     case NDB_MGM_NODE_TYPE_MGM:
  471.       compatible = ndbCompatible_mgmt_api(NDB_VERSION, version);
  472.       break;
  473.     default:
  474.       m_output->println("get config");
  475.       m_output->println("result: unrecognignized node type");
  476.       m_output->println("");
  477.       return;
  478.     }
  479.     
  480.     if (!compatible){
  481.       m_output->println("get config");
  482.       m_output->println("result: incompatible version mgmt 0x%x and node 0x%x",
  483. NDB_VERSION, version);
  484.       m_output->println("");
  485.       return;
  486.     }
  487.   }  
  488.   
  489.   const ConfigValues * cfg = &conf->m_configValues->m_config;
  490.   const Uint32 size = cfg->getPackedSize();
  491.   
  492.   UtilBuffer src;
  493.   cfg->pack(src);
  494.   
  495.   BaseString str;
  496.   int res = base64_encode(src, str);
  497.   
  498.   m_output->println("get config reply");
  499.   m_output->println("result: Ok");
  500.   m_output->println("Content-Length: %d", str.length());
  501.   m_output->println("Content-Type: ndbconfig/octet-stream");
  502.   m_output->println("Content-Transfer-Encoding: base64");
  503.   m_output->println("");
  504.   m_output->println(str.c_str());
  505.   return;
  506. }
  507. void
  508. MgmApiSession::getStatPort(Parser_t::Context &, 
  509.    const class Properties &) {
  510.   m_output->println("get statport reply");
  511.   m_output->println("tcpport: %d", 0);
  512.   m_output->println("");
  513. }
  514. void
  515. MgmApiSession::insertError(Parser<MgmApiSession>::Context &,
  516.    Properties const &args) {
  517.   Uint32 node = 0, error = 0;
  518.   args.get("node", &node);
  519.   args.get("error", &error);
  520.   int result = m_mgmsrv.insertError(node, error);
  521.   m_output->println("insert error reply");
  522.   if(result != 0)
  523.     m_output->println("result: %s", get_error_text(result));
  524.   else
  525.     m_output->println("result: Ok");
  526.   m_output->println("");
  527. }
  528. void
  529. MgmApiSession::setTrace(Parser<MgmApiSession>::Context &,
  530. Properties const &args) {
  531.   Uint32 node = 0, trace = 0;
  532.   args.get("node", &node);
  533.   args.get("trace", &trace);
  534.   int result = m_mgmsrv.setTraceNo(node, trace);
  535.   m_output->println("set trace reply");
  536.   if(result != 0)
  537.     m_output->println("result: %s", get_error_text(result));
  538.   else
  539.     m_output->println("result: Ok");
  540.   m_output->println("");
  541. }
  542. void
  543. MgmApiSession::getVersion(Parser<MgmApiSession>::Context &,
  544.   Properties const &) {
  545.   m_output->println("version");
  546.   m_output->println("id: %d", NDB_VERSION);
  547.   m_output->println("major: %d", getMajor(NDB_VERSION));
  548.   m_output->println("minor: %d", getMinor(NDB_VERSION));
  549.   m_output->println("string: %s", NDB_VERSION_STRING);
  550.   m_output->println("");
  551. }
  552. void
  553. MgmApiSession::startBackup(Parser<MgmApiSession>::Context &,
  554.    Properties const &args) {
  555.   DBUG_ENTER("MgmApiSession::startBackup");
  556.   unsigned backupId;
  557.   Uint32 completed= 2;
  558.   int result;
  559.   args.get("completed", &completed);
  560.   result = m_mgmsrv.startBackup(backupId, completed);
  561.   m_output->println("start backup reply");
  562.   if(result != 0)
  563.   {
  564.     m_output->println("result: %s", get_error_text(result));
  565.   }
  566.   else{
  567.     m_output->println("result: Ok");
  568.     m_output->println("id: %d", backupId);
  569.   }
  570.   m_output->println("");
  571.   DBUG_VOID_RETURN;
  572. }
  573. void
  574. MgmApiSession::abortBackup(Parser<MgmApiSession>::Context &,
  575.    Properties const &args) {
  576.   Uint32 id = 0;
  577.   args.get("id", &id);
  578.   int result = m_mgmsrv.abortBackup(id);
  579.   m_output->println("abort backup reply");
  580.   if(result != 0)
  581.     m_output->println("result: %s", get_error_text(result));
  582.   else
  583.     m_output->println("result: Ok");
  584.   m_output->println("");
  585. }
  586. /*****************************************************************************
  587.  * Global Replication
  588.  *****************************************************************************/
  589. void
  590. MgmApiSession::repCommand(Parser<MgmApiSession>::Context &,
  591.   Properties const &args) {
  592.   
  593.   Uint32 request = 0;
  594.   args.get("request", &request);
  595.   
  596.   Uint32 repReqId;
  597.   int result = m_mgmsrv.repCommand(&repReqId, request, true);
  598.   
  599.   m_output->println("global replication reply");
  600.   if(result != 0)
  601.     m_output->println("result: %s", get_error_text(result));
  602.   else{
  603.     m_output->println("result: Ok");
  604.     m_output->println("id: %d", repReqId);
  605.   }
  606.   m_output->println("");
  607. }
  608. /*****************************************************************************/
  609. void
  610. MgmApiSession::dumpState(Parser<MgmApiSession>::Context &,
  611.  Properties const &args) {
  612.   Uint32 node;
  613.   BaseString args_str;
  614.   args.get("node", &node);
  615.   args.get("args", args_str);
  616.   int result = m_mgmsrv.dumpState(node, args_str.c_str());
  617.   m_output->println("dump state reply");
  618.   if(result != 0)
  619.     m_output->println("result: %s", get_error_text(result));
  620.   else
  621.     m_output->println("result: Ok");
  622.   m_output->println("");
  623. }
  624. void
  625. MgmApiSession::bye(Parser<MgmApiSession>::Context &,
  626.    Properties const &) {
  627.   m_stop = true;
  628. }
  629. void
  630. MgmApiSession::setClusterLogLevel(Parser<MgmApiSession>::Context &,
  631.   Properties const &args) {
  632.   const char *reply= "set cluster loglevel reply";
  633.   Uint32 node, level, cat;
  634.   BaseString errorString;
  635.   SetLogLevelOrd logLevel;
  636.   int result;
  637.   DBUG_ENTER("MgmApiSession::setClusterLogLevel");
  638.   args.get("node", &node);
  639.   args.get("category", &cat);
  640.   args.get("level", &level);
  641.   DBUG_PRINT("enter",("node=%d, category=%d, level=%d", node, cat, level));
  642.   /* XXX should use constants for this value */
  643.   if(level > 15) {
  644.     m_output->println(reply);
  645.     m_output->println("result: Invalid loglevel %d", level);
  646.     m_output->println("");
  647.     DBUG_VOID_RETURN;
  648.   }
  649.   LogLevel::EventCategory category= 
  650.     (LogLevel::EventCategory)(cat-(int)CFG_MIN_LOGLEVEL);
  651.   m_mgmsrv.m_event_listner.lock();
  652.   if (m_mgmsrv.m_event_listner[0].m_logLevel.setLogLevel(category,level))
  653.   {
  654.     m_output->println(reply);
  655.     m_output->println("result: Invalid category %d", category);
  656.     m_output->println("");
  657.     m_mgmsrv.m_event_listner.unlock();
  658.     DBUG_VOID_RETURN;
  659.   }
  660.   m_mgmsrv.m_event_listner.unlock();
  661.   {
  662.     LogLevel ll;
  663.     ll.setLogLevel(category,level);
  664.     m_mgmsrv.m_event_listner.update_max_log_level(ll);
  665.   }
  666.   m_output->println(reply);
  667.   m_output->println("result: Ok");
  668.   m_output->println("");
  669.   DBUG_VOID_RETURN;
  670. }
  671. void
  672. MgmApiSession::setLogLevel(Parser<MgmApiSession>::Context &,
  673.    Properties const &args) {
  674.   Uint32 node = 0, level = 0, cat;
  675.   BaseString errorString;
  676.   SetLogLevelOrd logLevel;
  677.   int result;
  678.   logLevel.clear();
  679.   args.get("node", &node);
  680.   args.get("category", &cat);
  681.   args.get("level", &level);
  682.   /* XXX should use constants for this value */
  683.   if(level > 15) {
  684.     m_output->println("set loglevel reply");
  685.     m_output->println("result: Invalid loglevel", errorString.c_str());
  686.     m_output->println("");
  687.     return;
  688.   }
  689.   LogLevel::EventCategory category= 
  690.     (LogLevel::EventCategory)(cat-(int)CFG_MIN_LOGLEVEL);
  691.   {
  692.     LogLevel ll;
  693.     ll.setLogLevel(category,level);
  694.     m_mgmsrv.m_event_listner.update_max_log_level(ll);
  695.   }
  696.   m_output->println("set loglevel reply");
  697.   m_output->println("result: Ok");
  698.   m_output->println("");
  699. }
  700. void
  701. MgmApiSession::stopSignalLog(Parser<MgmApiSession>::Context &,
  702.      Properties const &args) {
  703.   Uint32 node;
  704.   args.get("node", &node);
  705.   int result = m_mgmsrv.stopSignalTracing(node);
  706.   m_output->println("stop signallog");
  707.   if(result != 0)
  708.     m_output->println("result: %s", get_error_text(result));
  709.   else
  710.     m_output->println("result: Ok");
  711.   m_output->println("");
  712. }
  713. void
  714. MgmApiSession::restart(Parser<MgmApiSession>::Context &,
  715.        Properties const &args) {
  716.   Uint32
  717.     nostart = 0,
  718.     initialstart = 0,
  719.     abort = 0;
  720.   char *nodes_str;
  721.   Vector<NodeId> nodes;
  722.     
  723.   args.get("initialstart", &initialstart);
  724.   args.get("nostart", &nostart);
  725.   args.get("abort", &abort);
  726.   args.get("node", (const char **)&nodes_str);
  727.   char *p, *last;
  728.   for((p = strtok_r(nodes_str, " ", &last));
  729.       p;
  730.       (p = strtok_r(NULL, " ", &last))) {
  731.     nodes.push_back(atoi(p));
  732.   }
  733.   int restarted = 0;
  734.   int result = 0;
  735.   for(size_t i = 0; i < nodes.size(); i++)
  736.     if((result = m_mgmsrv.restartNode(nodes[i],
  737.       nostart != 0,
  738.       initialstart != 0,
  739.       abort != 0)) == 0)
  740.       restarted++;
  741.   
  742.   m_output->println("restart reply");
  743.   if(result != 0){
  744.     m_output->println("result: %d-%s", result, get_error_text(result));
  745.   } else
  746.     m_output->println("result: Ok");
  747.   m_output->println("restarted: %d", restarted);
  748.   m_output->println("");
  749. }
  750. void
  751. MgmApiSession::restartAll(Parser<MgmApiSession>::Context &, 
  752.   Properties const &args)
  753. {
  754.   Uint32 nostart = 0;
  755.   Uint32 initialstart = 0;
  756.   Uint32 abort = 0;
  757.   
  758.   args.get("initialstart", &initialstart);
  759.   args.get("abort", &abort);
  760.   args.get("nostart", &nostart);
  761.   
  762.   int count = 0;
  763.   int result = m_mgmsrv.restart(nostart, initialstart, abort, &count);
  764.   m_output->println("restart reply");
  765.   if(result != 0)
  766.     m_output->println("result: %s", get_error_text(result));
  767.   else
  768.     m_output->println("result: Ok");
  769.   m_output->println("restarted: %d", count);
  770.   m_output->println("");
  771. }
  772. static void
  773. printNodeStatus(OutputStream *output,
  774. MgmtSrvr &mgmsrv,
  775. enum ndb_mgm_node_type type) {
  776.   NodeId nodeId = 0;
  777.   while(mgmsrv.getNextNodeId(&nodeId, type)) {
  778.     enum ndb_mgm_node_status status;
  779.     Uint32 startPhase = 0, 
  780.       version = 0, 
  781.       dynamicId = 0, 
  782.       nodeGroup = 0,
  783.       connectCount = 0;
  784.     bool system;
  785.     const char *address= NULL;
  786.     mgmsrv.status(nodeId, &status, &version, &startPhase,
  787.   &system, &dynamicId, &nodeGroup, &connectCount,
  788.   &address);
  789.     output->println("node.%d.type: %s",
  790.       nodeId,
  791.       ndb_mgm_get_node_type_string(type));
  792.     output->println("node.%d.status: %s",
  793.       nodeId,
  794.       ndb_mgm_get_node_status_string(status));
  795.     output->println("node.%d.version: %d", nodeId, version);
  796.     output->println("node.%d.startphase: %d", nodeId, startPhase);
  797.     output->println("node.%d.dynamic_id: %d", nodeId, dynamicId);
  798.     output->println("node.%d.node_group: %d", nodeId, nodeGroup);
  799.     output->println("node.%d.connect_count: %d", nodeId, connectCount);
  800.     output->println("node.%d.address: %s", nodeId, address ? address : "");
  801.   }
  802. }
  803. void
  804. MgmApiSession::getStatus(Parser<MgmApiSession>::Context &,
  805.  Properties const &) {
  806.   int noOfNodes = 0;
  807.   NodeId nodeId = 0;
  808.   while(m_mgmsrv.getNextNodeId(&nodeId, NDB_MGM_NODE_TYPE_NDB)){
  809.     noOfNodes++;
  810.   }
  811.   nodeId = 0;
  812.   while(m_mgmsrv.getNextNodeId(&nodeId, NDB_MGM_NODE_TYPE_API)){
  813.     noOfNodes++;
  814.   }
  815.   nodeId = 0;
  816.   while(m_mgmsrv.getNextNodeId(&nodeId, NDB_MGM_NODE_TYPE_MGM)){
  817.     noOfNodes++;
  818.   }
  819.   
  820.   m_output->println("node status");
  821.   m_output->println("nodes: %d", noOfNodes);
  822.   printNodeStatus(m_output, m_mgmsrv, NDB_MGM_NODE_TYPE_NDB);
  823.   printNodeStatus(m_output, m_mgmsrv, NDB_MGM_NODE_TYPE_MGM);
  824.   printNodeStatus(m_output, m_mgmsrv, NDB_MGM_NODE_TYPE_API);
  825.   nodeId = 0;
  826.   m_output->println("");
  827. }
  828. void
  829. MgmApiSession::getInfoClusterLog(Parser<MgmApiSession>::Context &,
  830.     Properties const &) {
  831.   const char* names[] = { "enabled",
  832.   "debug",
  833.   "info",
  834.   "warning",
  835.   "error",
  836.   "critical",
  837.   "alert" };
  838.   
  839.   m_output->println("clusterlog");
  840.   for(int i = 0; i < 7; i++) {
  841.     m_output->println("%s: %d",
  842.       names[i], m_mgmsrv.isEventLogFilterEnabled(i));
  843.   }
  844.   m_output->println("");
  845. }
  846. void
  847. MgmApiSession::stop(Parser<MgmApiSession>::Context &,
  848.     Properties const &args) {
  849.   Uint32 abort;
  850.   char *nodes_str;
  851.   Vector<NodeId> nodes;
  852.   args.get("node", (const char **)&nodes_str);
  853.   if(nodes_str == NULL)
  854.     return;
  855.   args.get("abort", &abort);
  856.   char *p, *last;
  857.   for((p = strtok_r(nodes_str, " ", &last));
  858.       p;
  859.       (p = strtok_r(NULL, " ", &last))) {
  860.     nodes.push_back(atoi(p));
  861.   }
  862.   int stop_self= 0;
  863.   size_t i;
  864.   for(i=0; i < nodes.size(); i++) {
  865.     if (nodes[i] == m_mgmsrv.getOwnNodeId()) {
  866.       stop_self= 1;
  867.       if (i != nodes.size()-1) {
  868. m_output->println("stop reply");
  869. m_output->println("result: server must be stopped last");
  870. m_output->println("");
  871. return;
  872.       }
  873.     }
  874.   }
  875.   int stopped = 0, result = 0;
  876.   
  877.   for(i=0; i < nodes.size(); i++)
  878.     if (nodes[i] != m_mgmsrv.getOwnNodeId()) {
  879.       if((result = m_mgmsrv.stopNode(nodes[i], abort != 0)) == 0)
  880. stopped++;
  881.     } else
  882.       stopped++;
  883.   m_output->println("stop reply");
  884.   if(result != 0)
  885.     m_output->println("result: %s", get_error_text(result));
  886.   else
  887.     m_output->println("result: Ok");
  888.   m_output->println("stopped: %d", stopped);
  889.   m_output->println("");
  890.   if (stop_self)
  891.     g_StopServer= true;
  892. }
  893. void
  894. MgmApiSession::stopAll(Parser<MgmApiSession>::Context &,
  895.       Properties const &args) {
  896.   int stopped = 0;
  897.   Uint32 abort;
  898.   args.get("abort", &abort);
  899.   int result = m_mgmsrv.stop(&stopped, abort != 0);
  900.   m_output->println("stop reply");
  901.   if(result != 0)
  902.     m_output->println("result: %s", get_error_text(result));
  903.   else
  904.     m_output->println("result: Ok");
  905.   m_output->println("stopped: %d", stopped);
  906.   m_output->println("");
  907. }
  908. void
  909. MgmApiSession::enterSingleUser(Parser<MgmApiSession>::Context &,
  910.   Properties const &args) {
  911.   int stopped = 0;
  912.   Uint32 nodeId = 0;
  913.   args.get("nodeId", &nodeId);
  914.   int result = m_mgmsrv.enterSingleUser(&stopped, nodeId);
  915.   m_output->println("enter single user reply");
  916.   if(result != 0) {
  917.     m_output->println("result: %s", get_error_text(result));
  918.   }
  919.   else {
  920.     m_output->println("result: Ok");
  921.   }
  922.   m_output->println("");
  923. }
  924. void
  925. MgmApiSession::exitSingleUser(Parser<MgmApiSession>::Context &,
  926.       Properties const &args) {
  927.   int stopped = 0;
  928.   int result = m_mgmsrv.exitSingleUser(&stopped, false);
  929.   m_output->println("exit single user reply");
  930.   if(result != 0)
  931.     m_output->println("result: %s", get_error_text(result));
  932.   else
  933.     m_output->println("result: Ok");
  934.   m_output->println("");
  935. }
  936. void
  937. MgmApiSession::startSignalLog(Parser<MgmApiSession>::Context &,
  938.       Properties const &args) {
  939.   Uint32 node;
  940.   args.get("node", &node);
  941.   int result = m_mgmsrv.startSignalTracing(node);
  942.   m_output->println("start signallog reply");
  943.   if(result != 0)
  944.     m_output->println("result: %s", get_error_text(result));
  945.   else
  946.     m_output->println("result: Ok");
  947.   m_output->println("");
  948. }
  949. void
  950. MgmApiSession::logSignals(Parser<MgmApiSession>::Context &,
  951.    Properties const &args) {
  952.   Uint32 node = 0, in = 0, out = 0;
  953.   //  BaseString blocks;
  954.   BaseString blockList;
  955.   char * blockName;
  956.   args.get("node", &node);
  957.   args.get("in", &in);
  958.   args.get("out", &out);
  959.   args.get("blocks", blockList);
  960.   // fast fix - pekka
  961.   char buf[200];
  962.   BaseString::snprintf(buf, 200, "%s", blockList.c_str());
  963.   Vector<BaseString> blocks;  
  964.   blockName=strtok(buf,"|");
  965.   while( blockName != NULL)
  966.     {
  967.       blocks.push_back(blockName);
  968.       blockName=strtok(NULL,"|");
  969.     }
  970.   
  971.   if(in > 1 || out > 1)
  972.     return; /* Invalid arguments */
  973.   
  974.   const MgmtSrvr::LogMode modes[] = {
  975.     MgmtSrvr::Off,
  976.     MgmtSrvr::Out,
  977.     MgmtSrvr::In,
  978.     MgmtSrvr::InOut,
  979.   };
  980.   MgmtSrvr::LogMode mode = modes[in<<1 | out];
  981.   int result = m_mgmsrv.setSignalLoggingMode(node, mode, blocks);
  982.   m_output->println("log signals reply");
  983.   if(result != 0)
  984.     m_output->println("result: %s", get_error_text(result));
  985.   else
  986.     m_output->println("result: Ok");
  987.   m_output->println("");
  988. }
  989. void
  990. MgmApiSession::start(Parser<MgmApiSession>::Context &,
  991.      Properties const &args) {
  992.   Uint32 node;
  993.   args.get("node", &node);
  994.   
  995.   int result = m_mgmsrv.start(node);
  996.   m_output->println("start reply");
  997.   if(result != 0)
  998.     m_output->println("result: %s", get_error_text(result));
  999.   else
  1000.     m_output->println("result: Ok");
  1001.   m_output->println("");
  1002. }
  1003. void
  1004. MgmApiSession::startAll(Parser<MgmApiSession>::Context &,
  1005. Properties const &) {
  1006.   NodeId node = 0;
  1007.   int started = 0;
  1008.   while(m_mgmsrv.getNextNodeId(&node, NDB_MGM_NODE_TYPE_NDB))
  1009.     if(m_mgmsrv.start(node) == 0)
  1010.       started++;
  1011.   m_output->println("start reply");
  1012.   m_output->println("result: Ok");
  1013.   m_output->println("started: %d", started);
  1014.   m_output->println("");
  1015. }
  1016. void
  1017. MgmApiSession::setLogFilter(Parser_t::Context &ctx,
  1018.     const class Properties &args) {
  1019.   Uint32 level;
  1020.   Uint32 enable;
  1021.   args.get("level", &level);
  1022.   args.get("enable", &enable);
  1023.   int result = m_mgmsrv.setEventLogFilter(level, enable);
  1024.   m_output->println("set logfilter reply");
  1025.   m_output->println("result: %d", result);
  1026.   m_output->println("");
  1027. }
  1028. static NdbOut&
  1029. operator<<(NdbOut& out, const LogLevel & ll)
  1030. {
  1031.   out << "[LogLevel: ";
  1032.   for(size_t i = 0; i<LogLevel::LOGLEVEL_CATEGORIES; i++)
  1033.     out << ll.getLogLevel((LogLevel::EventCategory)i) << " ";
  1034.   out << "]";
  1035.   return out;
  1036. }
  1037. void
  1038. Ndb_mgmd_event_service::log(int eventType, const Uint32* theData, NodeId nodeId){
  1039.   
  1040.   Uint32 threshold;
  1041.   LogLevel::EventCategory cat;
  1042.   Logger::LoggerLevel severity;
  1043.   int i, n;
  1044.   DBUG_ENTER("Ndb_mgmd_event_service::log");
  1045.   DBUG_PRINT("enter",("eventType=%d, nodeid=%d", eventType, nodeId));
  1046.   if (EventLoggerBase::event_lookup(eventType,cat,threshold,severity))
  1047.     DBUG_VOID_RETURN;
  1048.   char m_text[256];
  1049.   EventLogger::getText(m_text, sizeof(m_text), eventType, theData, nodeId);
  1050.   Vector<NDB_SOCKET_TYPE> copy; 
  1051.   m_clients.lock();
  1052.   for(i = m_clients.size() - 1; i >= 0; i--)
  1053.   {
  1054.     if(threshold <= m_clients[i].m_logLevel.getLogLevel(cat))
  1055.     {
  1056.       int fd= m_clients[i].m_socket;
  1057.       if(fd != NDB_INVALID_SOCKET &&
  1058.  println_socket(fd, MAX_WRITE_TIMEOUT, m_text) == -1)
  1059.       {
  1060. copy.push_back(fd);
  1061. m_clients.erase(i, false);
  1062.       }
  1063.     }
  1064.   }
  1065.   m_clients.unlock();
  1066.   
  1067.   if ((n= (int)copy.size()))
  1068.   {
  1069.     for(i= 0; i < n; i++)
  1070.       NDB_CLOSE_SOCKET(copy[i]);
  1071.     LogLevel tmp; tmp.clear();
  1072.     m_clients.lock();
  1073.     for(i= m_clients.size() - 1; i >= 0; i--)
  1074.       tmp.set_max(m_clients[i].m_logLevel);
  1075.     m_clients.unlock();
  1076.     update_log_level(tmp);
  1077.   }
  1078.   DBUG_VOID_RETURN;
  1079. }
  1080. void
  1081. Ndb_mgmd_event_service::update_max_log_level(const LogLevel &log_level)
  1082. {
  1083.   LogLevel tmp= m_logLevel;
  1084.   tmp.set_max(log_level);
  1085.   update_log_level(tmp);
  1086. }
  1087. void
  1088. Ndb_mgmd_event_service::update_log_level(const LogLevel &tmp)
  1089. {
  1090.   if(!(tmp == m_logLevel)){
  1091.     m_logLevel = tmp;
  1092.     EventSubscribeReq req;
  1093.     req = tmp;
  1094.     req.blockRef = 0;
  1095.     m_mgmsrv->m_log_level_requests.push_back(req);
  1096.   }
  1097. }
  1098. void
  1099. Ndb_mgmd_event_service::check_listeners()
  1100. {
  1101.   int i, n= 0;
  1102.   DBUG_ENTER("Ndb_mgmd_event_service::check_listeners");
  1103.   m_clients.lock();
  1104.   for(i= m_clients.size() - 1; i >= 0; i--)
  1105.   {
  1106.     int fd= m_clients[i].m_socket;
  1107.     DBUG_PRINT("info",("%d %d",i,fd));
  1108.     char buf[1];
  1109.     buf[0]=0;
  1110.     if (fd != NDB_INVALID_SOCKET &&
  1111. println_socket(fd,MAX_WRITE_TIMEOUT,"<PING>") == -1)
  1112.     {
  1113.       NDB_CLOSE_SOCKET(fd);
  1114.       m_clients.erase(i, false);
  1115.       n=1;
  1116.     }
  1117.   }
  1118.   if (n)
  1119.   {
  1120.     LogLevel tmp; tmp.clear();
  1121.     for(i= m_clients.size() - 1; i >= 0; i--)
  1122.       tmp.set_max(m_clients[i].m_logLevel);
  1123.     update_log_level(tmp);
  1124.   }
  1125.   m_clients.unlock();
  1126.   DBUG_VOID_RETURN;
  1127. }
  1128. void
  1129. Ndb_mgmd_event_service::add_listener(const Event_listener& client)
  1130. {
  1131.   DBUG_ENTER("Ndb_mgmd_event_service::add_listener");
  1132.   DBUG_PRINT("enter",("client.m_socket: %d", client.m_socket));
  1133.   check_listeners();
  1134.   m_clients.push_back(client);
  1135.   update_max_log_level(client.m_logLevel);
  1136.   DBUG_VOID_RETURN;
  1137. }
  1138. void
  1139. Ndb_mgmd_event_service::stop_sessions(){
  1140.   m_clients.lock();
  1141.   for(int i = m_clients.size() - 1; i >= 0; i--){
  1142.     if(m_clients[i].m_socket != NDB_INVALID_SOCKET){
  1143.       NDB_CLOSE_SOCKET(m_clients[i].m_socket);
  1144.       m_clients.erase(i);
  1145.     }
  1146.   }
  1147.   m_clients.unlock();
  1148. }
  1149. void
  1150. MgmApiSession::setParameter(Parser_t::Context &,
  1151.     Properties const &args) {
  1152.   BaseString node, param, value;
  1153.   args.get("node", node);
  1154.   args.get("parameter", param);
  1155.   args.get("value", value);
  1156.   
  1157.   BaseString result;
  1158.   int ret = m_mgmsrv.setDbParameter(atoi(node.c_str()), 
  1159.     atoi(param.c_str()),
  1160.     value.c_str(),
  1161.     result);
  1162.   
  1163.   m_output->println("set parameter reply");
  1164.   m_output->println("message: %s", result.c_str());
  1165.   m_output->println("result: %d", ret);
  1166.   m_output->println("");
  1167. }
  1168. void
  1169. MgmApiSession::listen_event(Parser<MgmApiSession>::Context & ctx,
  1170.     Properties const & args) {
  1171.   
  1172.   BaseString node, param, value;
  1173.   args.get("node", node);
  1174.   args.get("filter", param);
  1175.   int result = 0;
  1176.   BaseString msg;
  1177.   Ndb_mgmd_event_service::Event_listener le;
  1178.   le.m_socket = m_socket;
  1179.   Vector<BaseString> list;
  1180.   param.trim();
  1181.   param.split(list, " ,");
  1182.   for(size_t i = 0; i<list.size(); i++){
  1183.     Vector<BaseString> spec;
  1184.     list[i].trim();
  1185.     list[i].split(spec, "=:");
  1186.     if(spec.size() != 2){
  1187.       msg.appfmt("Invalid filter specification: >%s< >%s< %d", 
  1188.  param.c_str(), list[i].c_str(), spec.size());
  1189.       result = -1;
  1190.       goto done;
  1191.     }
  1192.     spec[0].trim().ndb_toupper();
  1193.     int category = ndb_mgm_match_event_category(spec[0].c_str());
  1194.     if(category == NDB_MGM_ILLEGAL_EVENT_CATEGORY){
  1195.       category = atoi(spec[0].c_str());
  1196.       if(category < NDB_MGM_MIN_EVENT_CATEGORY ||
  1197.  category > NDB_MGM_MAX_EVENT_CATEGORY){
  1198. msg.appfmt("Unknown category: >%s<", spec[0].c_str());
  1199. result = -1;
  1200. goto done;
  1201.       }
  1202.     }
  1203.     
  1204.     int level = atoi(spec[1].c_str());
  1205.     if(level < 0 || level > 15){
  1206.       msg.appfmt("Invalid level: >%s<", spec[1].c_str());
  1207.       result = -1;
  1208.       goto done;
  1209.     }
  1210.     category -= CFG_MIN_LOGLEVEL;
  1211.     le.m_logLevel.setLogLevel((LogLevel::EventCategory)category, level);
  1212.   }
  1213.   
  1214.   if(list.size() == 0){
  1215.     msg.appfmt("Empty filter specification");
  1216.     result = -1;
  1217.     goto done;
  1218.   }
  1219.   
  1220.   m_mgmsrv.m_event_listner.add_listener(le);
  1221.   
  1222.   m_stop = true;
  1223.   m_socket = NDB_INVALID_SOCKET;
  1224. done:
  1225.   m_output->println("listen event");
  1226.   m_output->println("result: %d", result);
  1227.   if(result != 0)
  1228.     m_output->println("msg: %s", msg.c_str());
  1229.   m_output->println("");
  1230. }
  1231. struct PurgeStruct
  1232. {
  1233.   NodeBitmask free_nodes;/* free nodes as reported
  1234.   * by ndbd in apiRegReqConf
  1235.   */
  1236.   BaseString *str;
  1237. };
  1238. void
  1239. MgmApiSession::stop_session_if_not_connected(SocketServer::Session *_s, void *data)
  1240. {
  1241.   MgmApiSession *s= (MgmApiSession *)_s;
  1242.   struct PurgeStruct &ps= *(struct PurgeStruct *)data;
  1243.   if (s->m_allocated_resources->is_reserved(ps.free_nodes))
  1244.   {
  1245.     ps.str->appfmt(" %d", s->m_allocated_resources->get_nodeid());
  1246.     s->stopSession();
  1247.   }
  1248. }
  1249. void
  1250. MgmApiSession::purge_stale_sessions(Parser_t::Context &ctx,
  1251.     const class Properties &args)
  1252. {
  1253.   struct PurgeStruct ps;
  1254.   BaseString str;
  1255.   ps.str = &str;
  1256.   m_mgmsrv.get_connected_nodes(ps.free_nodes);
  1257.   ps.free_nodes.bitXORC(NodeBitmask()); // invert connected_nodes to get free nodes
  1258.   m_mgmsrv.get_socket_server()->foreachSession(stop_session_if_not_connected,&ps);
  1259.   m_output->println("purge stale sessions reply");
  1260.   if (str.length() > 0)
  1261.     m_output->println("purged:%s",str.c_str());
  1262.   m_output->println("result: Ok");
  1263.   m_output->println("");
  1264. }
  1265. void
  1266. MgmApiSession::check_connection(Parser_t::Context &ctx,
  1267. const class Properties &args)
  1268. {
  1269.   m_output->println("check connection reply");
  1270.   m_output->println("result: Ok");
  1271.   m_output->println("");
  1272. }
  1273. template class MutexVector<int>;
  1274. template class Vector<ParserRow<MgmApiSession> const*>;
  1275. template class Vector<unsigned short>;