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

MySQL数据库

开发平台:

Visual C++

  1. /* Copyright (C) 2003 MySQL AB
  2.    This program is free software; you can redistribute it and/or modify
  3.    it under the terms of the GNU General Public License as published by
  4.    the Free Software Foundation; either version 2 of the License, or
  5.    (at your option) any later version.
  6.    This program is distributed in the hope that it will be useful,
  7.    but WITHOUT ANY WARRANTY; without even the implied warranty of
  8.    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  9.    GNU General Public License for more details.
  10.    You should have received a copy of the GNU General Public License
  11.    along with this program; if not, write to the Free Software
  12.    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA */
  13. #include <ndb_global.h>
  14. #include <my_sys.h>
  15. #include <LocalConfig.hpp>
  16. #include <NdbAutoPtr.hpp>
  17. #include <NdbSleep.h>
  18. #include <NdbTCP.h>
  19. #include "mgmapi.h"
  20. #include "mgmapi_debug.h"
  21. #include "mgmapi_configuration.hpp"
  22. #include <socket_io.h>
  23. #include <NdbOut.hpp>
  24. #include <SocketServer.hpp>
  25. #include <SocketClient.hpp>
  26. #include <Parser.hpp>
  27. #include <OutputStream.hpp>
  28. #include <InputStream.hpp>
  29. #include <Base64.hpp>
  30. #define MGM_CMD(name, fun, desc) 
  31.  { name, 
  32.    0, 
  33.    ParserRow<ParserDummy>::Cmd, 
  34.    ParserRow<ParserDummy>::String, 
  35.    ParserRow<ParserDummy>::Optional, 
  36.    ParserRow<ParserDummy>::IgnoreMinMax, 
  37.    0, 0, 
  38.    fun, 
  39.    desc, 0 }
  40. #define MGM_ARG(name, type, opt, desc) 
  41.  { name, 
  42.    0, 
  43.    ParserRow<ParserDummy>::Arg, 
  44.    ParserRow<ParserDummy>::type, 
  45.    ParserRow<ParserDummy>::opt, 
  46.    ParserRow<ParserDummy>::IgnoreMinMax, 
  47.    0, 0, 
  48.    0, 
  49.    desc, 0 }
  50. #define MGM_END() 
  51.  { 0, 
  52.    0, 
  53.    ParserRow<ParserDummy>::Arg, 
  54.    ParserRow<ParserDummy>::Int, 
  55.    ParserRow<ParserDummy>::Optional, 
  56.    ParserRow<ParserDummy>::IgnoreMinMax, 
  57.    0, 0, 
  58.    0, 
  59.    0, 0 }
  60. class ParserDummy : private SocketServer::Session 
  61. {
  62. public:
  63.   ParserDummy(NDB_SOCKET_TYPE sock);
  64. };
  65. ParserDummy::ParserDummy(NDB_SOCKET_TYPE sock) : SocketServer::Session(sock) 
  66. {
  67. }
  68. typedef Parser<ParserDummy> Parser_t;
  69. #define NDB_MGM_MAX_ERR_DESC_SIZE 256
  70. struct ndb_mgm_handle {
  71.   int cfg_i;
  72.   
  73.   int connected;
  74.   int last_error;
  75.   int last_error_line;
  76.   char last_error_desc[NDB_MGM_MAX_ERR_DESC_SIZE];
  77.   int read_timeout;
  78.   int write_timeout;
  79.   NDB_SOCKET_TYPE socket;
  80.   LocalConfig cfg;
  81. #ifdef MGMAPI_LOG
  82.   FILE* logfile;
  83. #endif
  84.   FILE *errstream;
  85. };
  86. #define SET_ERROR(h, e, s) setError(h, e, __LINE__, s)
  87. static
  88. void
  89. setError(NdbMgmHandle h, int error, int error_line, const char * msg, ...){
  90.   h->last_error = error;  
  91.   h->last_error_line = error_line;
  92.   va_list ap;
  93.   va_start(ap, msg);
  94.   BaseString::vsnprintf(h->last_error_desc, sizeof(h->last_error_desc), msg, ap);
  95.   va_end(ap);
  96. }
  97. #define CHECK_HANDLE(handle, ret) 
  98.   if(handle == 0) { 
  99.     SET_ERROR(handle, NDB_MGM_ILLEGAL_SERVER_HANDLE, ""); 
  100.     return ret; 
  101.   } 
  102. #define CHECK_CONNECTED(handle, ret) 
  103.   if (handle->connected != 1) { 
  104.     SET_ERROR(handle, NDB_MGM_SERVER_NOT_CONNECTED , ""); 
  105.     return ret; 
  106.   }
  107. #define CHECK_REPLY(reply, ret) 
  108.   if(reply == NULL) { 
  109.     SET_ERROR(handle, NDB_MGM_ILLEGAL_SERVER_REPLY, ""); 
  110.     return ret; 
  111.   }
  112. /*****************************************************************************
  113.  * Handles
  114.  *****************************************************************************/
  115. extern "C"
  116. NdbMgmHandle
  117. ndb_mgm_create_handle()
  118. {
  119.   DBUG_ENTER("ndb_mgm_create_handle");
  120.   NdbMgmHandle h     =
  121.     (NdbMgmHandle)my_malloc(sizeof(ndb_mgm_handle),MYF(MY_WME));
  122.   h->connected       = 0;
  123.   h->last_error      = 0;
  124.   h->last_error_line = 0;
  125.   h->socket          = NDB_INVALID_SOCKET;
  126.   h->read_timeout    = 50000;
  127.   h->write_timeout   = 100;
  128.   h->cfg_i           = 0;
  129.   h->errstream       = stdout;
  130.   strncpy(h->last_error_desc, "No error", NDB_MGM_MAX_ERR_DESC_SIZE);
  131.   new (&(h->cfg)) LocalConfig;
  132.   h->cfg.init(0, 0);
  133. #ifdef MGMAPI_LOG
  134.   h->logfile = 0;
  135. #endif
  136.   DBUG_PRINT("exit",("ret: %lx", h));
  137.   DBUG_RETURN(h);
  138. }
  139. extern "C"
  140. int
  141. ndb_mgm_set_connectstring(NdbMgmHandle handle, const char * mgmsrv)
  142. {
  143.   handle->cfg.~LocalConfig();
  144.   new (&(handle->cfg)) LocalConfig;
  145.   if (!handle->cfg.init(mgmsrv, 0) ||
  146.       handle->cfg.ids.size() == 0)
  147.   {
  148.     handle->cfg.~LocalConfig();
  149.     new (&(handle->cfg)) LocalConfig;
  150.     handle->cfg.init(0, 0); /* reset the LocalCongig */
  151.     SET_ERROR(handle, NDB_MGM_ILLEGAL_CONNECT_STRING, "");
  152.     return -1;
  153.   }
  154.   handle->cfg_i= 0;
  155.   return 0;
  156. }
  157. /**
  158.  * Destroy a handle
  159.  */
  160. extern "C"
  161. void
  162. ndb_mgm_destroy_handle(NdbMgmHandle * handle)
  163. {
  164.   DBUG_ENTER("ndb_mgm_destroy_handle");
  165.   if(!handle)
  166.     return;
  167.   DBUG_PRINT("enter",("*handle: %lx", *handle));
  168.   if((* handle)->connected){
  169.     ndb_mgm_disconnect(* handle);
  170.   }
  171. #ifdef MGMAPI_LOG
  172.   if ((* handle)->logfile != 0){
  173.     fclose((* handle)->logfile);
  174.     (* handle)->logfile = 0;
  175.   }
  176. #endif
  177.   (*handle)->cfg.~LocalConfig();
  178.   my_free((char*)* handle,MYF(MY_ALLOW_ZERO_PTR));
  179.   * handle = 0;
  180.   DBUG_VOID_RETURN;
  181. }
  182. extern "C" 
  183. void
  184. ndb_mgm_set_error_stream(NdbMgmHandle handle, FILE * file)
  185. {
  186.   handle->errstream = file;
  187. }
  188. /*****************************************************************************
  189.  * Error handling
  190.  *****************************************************************************/
  191. /**
  192.  * Get latest error associated with a handle
  193.  */
  194. extern "C"
  195. int
  196. ndb_mgm_get_latest_error(const NdbMgmHandle h)
  197. {
  198.   return h->last_error;
  199. }
  200. extern "C"
  201. const char *
  202. ndb_mgm_get_latest_error_desc(const NdbMgmHandle h){
  203.   return h->last_error_desc;
  204. }
  205. extern "C"
  206. int
  207. ndb_mgm_get_latest_error_line(const NdbMgmHandle h)
  208. {
  209.   return h->last_error_line;
  210. }
  211. extern "C"
  212. const char *
  213. ndb_mgm_get_latest_error_msg(const NdbMgmHandle h)
  214. {
  215.   for (int i=0; i<ndb_mgm_noOfErrorMsgs; i++) {
  216.     if (ndb_mgm_error_msgs[i].code == h->last_error)
  217.       return ndb_mgm_error_msgs[i].msg;
  218.   }
  219.   return "Error"; // Unknown Error message
  220. }
  221. /*
  222.  * Call an operation, and return the reply
  223.  */
  224. static const Properties *
  225. ndb_mgm_call(NdbMgmHandle handle, const ParserRow<ParserDummy> *command_reply,
  226.      const char *cmd, const Properties *cmd_args) 
  227. {
  228.   DBUG_ENTER("ndb_mgm_call");
  229.   DBUG_PRINT("enter",("handle->socket: %d, cmd: %s",
  230.       handle->socket, cmd));
  231.   SocketOutputStream out(handle->socket);
  232.   SocketInputStream in(handle->socket, handle->read_timeout);
  233.   out.println(cmd);
  234. #ifdef MGMAPI_LOG
  235.   /** 
  236.    * Print command to  log file
  237.    */
  238.   FileOutputStream f(handle->logfile);
  239.   f.println("OUT: %s", cmd);
  240. #endif
  241.   if(cmd_args != NULL) {
  242.     Properties::Iterator iter(cmd_args);
  243.     const char *name;
  244.     while((name = iter.next()) != NULL) {
  245.       PropertiesType t;
  246.       Uint32 val_i;
  247.       Uint64 val_64;
  248.       BaseString val_s;
  249.       cmd_args->getTypeOf(name, &t);
  250.       switch(t) {
  251.       case PropertiesType_Uint32:
  252. cmd_args->get(name, &val_i);
  253. out.println("%s: %d", name, val_i);
  254. break;
  255.       case PropertiesType_Uint64:
  256. cmd_args->get(name, &val_64);
  257. out.println("%s: %Ld", name, val_64);
  258. break;
  259.       case PropertiesType_char:
  260. cmd_args->get(name, val_s);
  261. out.println("%s: %s", name, val_s.c_str());
  262. break;
  263.       case PropertiesType_Properties:
  264. /* Ignore */
  265. break;
  266.       }
  267.     }
  268. #ifdef MGMAPI_LOG
  269.   /** 
  270.    * Print arguments to  log file
  271.    */
  272.   cmd_args->print(handle->logfile, "OUT: ");
  273. #endif
  274.   }
  275.   out.println("");
  276.   Parser_t::Context ctx;
  277.   ParserDummy session(handle->socket);
  278.   Parser_t parser(command_reply, in, true, true, true);
  279. #if 1
  280.   const Properties* p = parser.parse(ctx, session);
  281.   if (p == NULL){
  282.     /**
  283.      * Print some info about why the parser returns NULL
  284.      */
  285.     DBUG_PRINT("info",("ctx.status: %d, ctx.m_currentToken: %s",
  286.        ctx.m_status, ctx.m_currentToken));
  287.     //ndbout << " status=" << ctx.m_status << ", curr="
  288.     //<< ctx.m_currentToken << endl;
  289.   } 
  290. #ifdef MGMAPI_LOG
  291.   else {
  292.     /** 
  293.      * Print reply to log file
  294.      */
  295.     p->print(handle->logfile, "IN: ");
  296.   }
  297. #endif
  298.   DBUG_RETURN(p);
  299. #else
  300.   DBUG_RETURN(parser.parse(ctx, session));
  301. #endif
  302. }
  303. /**
  304.  * Connect to a management server
  305.  */
  306. extern "C"
  307. int
  308. ndb_mgm_connect(NdbMgmHandle handle, int no_retries,
  309. int retry_delay_in_seconds, int verbose)
  310. {
  311.   SET_ERROR(handle, NDB_MGM_NO_ERROR, "Executing: ndb_mgm_connect");
  312.   CHECK_HANDLE(handle, -1);
  313. #ifdef MGMAPI_LOG
  314.   /**
  315.   * Open the log file
  316.   */
  317.   char logname[64];
  318.   BaseString::snprintf(logname, 64, "mgmapi.log");
  319.   handle->logfile = fopen(logname, "w");
  320. #endif
  321.   /**
  322.    * Do connect
  323.    */
  324.   LocalConfig &cfg= handle->cfg;
  325.   NDB_SOCKET_TYPE sockfd= NDB_INVALID_SOCKET;
  326.   Uint32 i;
  327.   while (sockfd == NDB_INVALID_SOCKET)
  328.   {
  329.     // do all the mgmt servers
  330.     for (i = 0; i < cfg.ids.size(); i++)
  331.     {
  332.       if (cfg.ids[i].type != MgmId_TCP)
  333. continue;
  334.       SocketClient s(cfg.ids[i].name.c_str(), cfg.ids[i].port);
  335.       sockfd = s.connect();
  336.       if (sockfd != NDB_INVALID_SOCKET)
  337. break;
  338.     }
  339.     if (sockfd != NDB_INVALID_SOCKET)
  340.       break;
  341.     if (verbose > 0) {
  342.       char buf[1024];
  343.       fprintf(handle->errstream, "Unable to connect with connect string: %sn",
  344.       cfg.makeConnectString(buf,sizeof(buf)));
  345.       verbose= -1;
  346.     }
  347.     if (no_retries == 0) {
  348.       char buf[1024];
  349.       setError(handle, NDB_MGM_COULD_NOT_CONNECT_TO_SOCKET, __LINE__,
  350.        "Unable to connect with connect string: %s",
  351.        cfg.makeConnectString(buf,sizeof(buf)));
  352.       if (verbose == -2)
  353. fprintf(handle->errstream, ", failed.n");
  354.       return -1;
  355.     }
  356.     if (verbose == -1) {
  357.       fprintf(handle->errstream, "Retrying every %d seconds", 
  358.       retry_delay_in_seconds);
  359.       if (no_retries > 0)
  360. fprintf(handle->errstream, ". Attempts left:");
  361.       else
  362. fprintf(handle->errstream, ", until connected.");
  363.       fflush(handle->errstream);
  364.       verbose= -2;
  365.     }
  366.     if (no_retries > 0) {
  367.       if (verbose == -2) {
  368. fprintf(handle->errstream, " %d", no_retries);
  369. fflush(handle->errstream);
  370.       }
  371.       no_retries--;
  372.     }
  373.     NdbSleep_SecSleep(retry_delay_in_seconds);
  374.   }
  375.   if (verbose == -2)
  376.   {
  377.     fprintf(handle->errstream, "n");
  378.     fflush(handle->errstream);
  379.   }
  380.   handle->cfg_i = i;
  381.   
  382.   handle->socket    = sockfd;
  383.   handle->connected = 1;
  384.   return 0;
  385. }
  386. /**
  387.  * Disconnect from a mgm server
  388.  */
  389. extern "C"
  390. int
  391. ndb_mgm_disconnect(NdbMgmHandle handle)
  392. {
  393.   SET_ERROR(handle, NDB_MGM_NO_ERROR, "Executing: ndb_mgm_disconnect");
  394.   CHECK_HANDLE(handle, -1);
  395.   CHECK_CONNECTED(handle, -1);
  396.   NDB_CLOSE_SOCKET(handle->socket);
  397.   handle->socket = NDB_INVALID_SOCKET;
  398.   handle->connected = 0;
  399.   return 0;
  400. }
  401. struct ndb_mgm_type_atoi 
  402. {
  403.   const char * str;
  404.   const char * alias;
  405.   enum ndb_mgm_node_type value;
  406. };
  407. static struct ndb_mgm_type_atoi type_values[] = 
  408. {
  409.   { "NDB", "ndbd", NDB_MGM_NODE_TYPE_NDB},
  410.   { "API", "mysqld", NDB_MGM_NODE_TYPE_API },
  411.   { "MGM", "ndb_mgmd", NDB_MGM_NODE_TYPE_MGM }
  412. };
  413. const int no_of_type_values = (sizeof(type_values) / 
  414.        sizeof(ndb_mgm_type_atoi));
  415. extern "C"
  416. ndb_mgm_node_type
  417. ndb_mgm_match_node_type(const char * type)
  418. {
  419.   if(type == 0)
  420.     return NDB_MGM_NODE_TYPE_UNKNOWN;
  421.   
  422.   for(int i = 0; i<no_of_type_values; i++)
  423.     if(strcmp(type, type_values[i].str) == 0)
  424.       return type_values[i].value;
  425.     else if(strcmp(type, type_values[i].alias) == 0)
  426.       return type_values[i].value;
  427.   
  428.   return NDB_MGM_NODE_TYPE_UNKNOWN;
  429. }
  430. extern "C"
  431. const char * 
  432. ndb_mgm_get_node_type_string(enum ndb_mgm_node_type type)
  433. {
  434.   for(int i = 0; i<no_of_type_values; i++)
  435.     if(type_values[i].value == type)
  436.       return type_values[i].str;
  437.   return 0;
  438. }
  439. extern "C"
  440. const char * 
  441. ndb_mgm_get_node_type_alias_string(enum ndb_mgm_node_type type, const char** str)
  442. {
  443.   for(int i = 0; i<no_of_type_values; i++)
  444.     if(type_values[i].value == type)
  445.       {
  446. if (str)
  447.   *str= type_values[i].str;
  448. return type_values[i].alias;
  449.       }
  450.   return 0;
  451. }
  452. struct ndb_mgm_status_atoi {
  453.   const char * str;
  454.   enum ndb_mgm_node_status value;
  455. };
  456. static struct ndb_mgm_status_atoi status_values[] = 
  457. {
  458.   { "UNKNOWN", NDB_MGM_NODE_STATUS_UNKNOWN },
  459.   { "NO_CONTACT", NDB_MGM_NODE_STATUS_NO_CONTACT },
  460.   { "NOT_STARTED", NDB_MGM_NODE_STATUS_NOT_STARTED },
  461.   { "STARTING", NDB_MGM_NODE_STATUS_STARTING },
  462.   { "STARTED", NDB_MGM_NODE_STATUS_STARTED },
  463.   { "SHUTTING_DOWN", NDB_MGM_NODE_STATUS_SHUTTING_DOWN },
  464.   { "RESTARTING", NDB_MGM_NODE_STATUS_RESTARTING },
  465.   { "SINGLE USER MODE", NDB_MGM_NODE_STATUS_SINGLEUSER }
  466. };
  467. const int no_of_status_values = (sizeof(status_values) / 
  468.  sizeof(ndb_mgm_status_atoi));
  469. extern "C"
  470. ndb_mgm_node_status
  471. ndb_mgm_match_node_status(const char * status)
  472. {
  473.   if(status == 0)
  474.     return NDB_MGM_NODE_STATUS_UNKNOWN;
  475.   
  476.   for(int i = 0; i<no_of_status_values; i++)
  477.     if(strcmp(status, status_values[i].str) == 0)
  478.       return status_values[i].value;
  479.   return NDB_MGM_NODE_STATUS_UNKNOWN;
  480. }
  481. extern "C"
  482. const char * 
  483. ndb_mgm_get_node_status_string(enum ndb_mgm_node_status status)
  484. {
  485.   int i;
  486.   for(i = 0; i<no_of_status_values; i++)
  487.     if(status_values[i].value == status)
  488.       return status_values[i].str;
  489.   for(i = 0; i<no_of_status_values; i++)
  490.     if(status_values[i].value == NDB_MGM_NODE_STATUS_UNKNOWN)
  491.       return status_values[i].str;
  492.   
  493.   return 0;
  494. }
  495. static int
  496. status_ackumulate(struct ndb_mgm_node_state * state,
  497.   const char * field,
  498.   const char * value)
  499. {
  500.   if(strcmp("type", field) == 0){
  501.     state->node_type = ndb_mgm_match_node_type(value);
  502.   } else if(strcmp("status", field) == 0){
  503.     state->node_status = ndb_mgm_match_node_status(value);
  504.   } else if(strcmp("startphase", field) == 0){
  505.     state->start_phase = atoi(value);
  506.   } else if(strcmp("dynamic_id", field) == 0){
  507.     state->dynamic_id = atoi(value);
  508.   } else if(strcmp("node_group", field) == 0){
  509.     state->node_group = atoi(value);
  510.   } else if(strcmp("version", field) == 0){
  511.     state->version = atoi(value);
  512.   } else if(strcmp("connect_count", field) == 0){
  513.     state->connect_count = atoi(value);    
  514.   } else if(strcmp("address", field) == 0){
  515.     strncpy(state->connect_address, value, sizeof(state->connect_address));
  516.     state->connect_address[sizeof(state->connect_address)-1]= 0;
  517.   } else {
  518.     ndbout_c("Unknown field: %s", field);
  519.   }
  520.   return 0;
  521. }
  522. /**
  523.  * Compare function for qsort() that sorts ndb_mgm_node_state in
  524.  * node_id order
  525.  */
  526. static int
  527. cmp_state(const void *_a, const void *_b) 
  528. {
  529.   struct ndb_mgm_node_state *a, *b;
  530.   a = (struct ndb_mgm_node_state *)_a;
  531.   b = (struct ndb_mgm_node_state *)_b;
  532.   if (a->node_id > b->node_id)
  533.     return 1;
  534.   return -1;
  535. }
  536. extern "C"
  537. struct ndb_mgm_cluster_state * 
  538. ndb_mgm_get_status(NdbMgmHandle handle)
  539. {
  540.   SET_ERROR(handle, NDB_MGM_NO_ERROR, "Executing: ndb_mgm_get_status");
  541.   CHECK_HANDLE(handle, NULL);
  542.   CHECK_CONNECTED(handle, NULL);
  543.   SocketOutputStream out(handle->socket);
  544.   SocketInputStream in(handle->socket, handle->read_timeout);
  545.   out.println("get status");
  546.   out.println("");
  547.   char buf[1024];
  548.   in.gets(buf, sizeof(buf));
  549.   if(buf[strlen(buf)-1] == 'n')
  550.     buf[strlen(buf)-1] = '';
  551.   if(strcmp("node status", buf) != 0) {
  552.     SET_ERROR(handle, NDB_MGM_ILLEGAL_NODE_STATUS, buf);
  553.     return NULL;
  554.   }
  555.   in.gets(buf, sizeof(buf));
  556.   if(buf[strlen(buf)-1] == 'n')
  557.     buf[strlen(buf)-1] = '';
  558.   
  559.   BaseString tmp(buf);
  560.   Vector<BaseString> split;
  561.   tmp.split(split, ":");
  562.   if(split.size() != 2){
  563.     return NULL;
  564.   }
  565.  
  566.   if(!(split[0].trim() == "nodes")){
  567.     return NULL;
  568.   }
  569.   const int noOfNodes = atoi(split[1].c_str());
  570.   ndb_mgm_cluster_state *state = (ndb_mgm_cluster_state*)
  571.     malloc(sizeof(ndb_mgm_cluster_state)+
  572.    noOfNodes*(sizeof(ndb_mgm_node_state)+sizeof("000.000.000.000#")));
  573.   state->hostname= 0;
  574.   state->no_of_nodes= noOfNodes;
  575.   ndb_mgm_node_state * ptr = &state->node_states[0];
  576.   int nodeId = 0;
  577.   int i;
  578.   for (i= 0; i < noOfNodes; i++) {
  579.     state->node_states[i].connect_address[0]= 0;
  580.   }
  581.   i = -1; ptr--;
  582.   for(; i<noOfNodes; ){
  583.     in.gets(buf, sizeof(buf));
  584.     tmp.assign(buf);
  585.     if(tmp.trim() == ""){
  586.       break;
  587.     }
  588.     
  589.     Vector<BaseString> split;
  590.     tmp.split(split, ":.", 4);
  591.     if(split.size() != 4)
  592.       break;
  593.     
  594.     const int id = atoi(split[1].c_str());
  595.     if(id != nodeId){
  596.       ptr++;
  597.       i++;
  598.       nodeId = id;
  599.       ptr->node_id = id;
  600.     }
  601.     split[3].trim(" tn");
  602.     if(status_ackumulate(ptr,split[2].c_str(), split[3].c_str()) != 0) {
  603.       break;
  604.     }
  605.   }
  606.   if(i+1 != noOfNodes){
  607.     free(state);
  608.     return NULL;
  609.   }
  610.   qsort(state->node_states, state->no_of_nodes, sizeof(state->node_states[0]),
  611. cmp_state);
  612.   return state;
  613. }
  614. extern "C"
  615. int 
  616. ndb_mgm_enter_single_user(NdbMgmHandle handle,
  617.   unsigned int nodeId,
  618.   struct ndb_mgm_reply* /*reply*/) 
  619. {
  620.   SET_ERROR(handle, NDB_MGM_NO_ERROR, "Executing: ndb_mgm_enter_single_user");
  621.   const ParserRow<ParserDummy> enter_single_reply[] = {
  622.     MGM_CMD("enter single user reply", NULL, ""),
  623.     MGM_ARG("result", String, Mandatory, "Error message"),
  624.     MGM_END()
  625.   };
  626.   CHECK_HANDLE(handle, -1);
  627.   CHECK_CONNECTED(handle, -1);
  628.   Properties args;
  629.   args.put("nodeId", nodeId);
  630.   const Properties *reply;
  631.   reply = ndb_mgm_call(handle, enter_single_reply, "enter single user", &args);
  632.   CHECK_REPLY(reply, -1);
  633.   BaseString result;
  634.   reply->get("result", result);
  635.   if(strcmp(result.c_str(), "Ok") != 0) {
  636.     SET_ERROR(handle, NDB_MGM_COULD_NOT_ENTER_SINGLE_USER_MODE, 
  637.       result.c_str());
  638.     delete reply;
  639.     return -1;
  640.   }
  641.   delete reply;
  642.   return 0;
  643. }
  644. extern "C"
  645. int 
  646. ndb_mgm_exit_single_user(NdbMgmHandle handle, struct ndb_mgm_reply* /*reply*/) 
  647. {
  648.   SET_ERROR(handle, NDB_MGM_NO_ERROR, "Executing: ndb_mgm_exit_single_user");
  649.   const ParserRow<ParserDummy> exit_single_reply[] = {
  650.     MGM_CMD("exit single user reply", NULL, ""),
  651.     MGM_ARG("result", String, Mandatory, "Error message"),
  652.     MGM_END()
  653.   };
  654.   CHECK_HANDLE(handle, -1);
  655.   CHECK_CONNECTED(handle, -1);
  656.   const Properties *reply;
  657.   reply = ndb_mgm_call(handle, exit_single_reply, "exit single user", 0);
  658.   CHECK_REPLY(reply, -1);
  659.   const char * buf;
  660.   reply->get("result", &buf);
  661.   if(strcmp(buf,"Ok")!=0) {
  662.     SET_ERROR(handle, NDB_MGM_COULD_NOT_EXIT_SINGLE_USER_MODE, buf);
  663.     delete reply;    
  664.     return -1;
  665.   }
  666.   delete reply;
  667.   return 0;
  668. }
  669. extern "C"
  670. int 
  671. ndb_mgm_stop(NdbMgmHandle handle, int no_of_nodes, const int * node_list)
  672. {
  673.   SET_ERROR(handle, NDB_MGM_NO_ERROR, "Executing: ndb_mgm_stop");
  674.   return ndb_mgm_stop2(handle, no_of_nodes, node_list, 0);
  675. }
  676. extern "C"
  677. int 
  678. ndb_mgm_stop2(NdbMgmHandle handle, int no_of_nodes, const int * node_list,
  679.       int abort)
  680. {
  681.   SET_ERROR(handle, NDB_MGM_NO_ERROR, "Executing: ndb_mgm_stop2");
  682.   const ParserRow<ParserDummy> stop_reply[] = {
  683.     MGM_CMD("stop reply", NULL, ""),
  684.     MGM_ARG("stopped", Int, Optional, "No of stopped nodes"),
  685.     MGM_ARG("result", String, Mandatory, "Error message"),
  686.     MGM_END()
  687.   };
  688.   CHECK_HANDLE(handle, -1);
  689.   CHECK_CONNECTED(handle, -1);
  690.   if(no_of_nodes < 0){
  691.     SET_ERROR(handle, NDB_MGM_ILLEGAL_NUMBER_OF_NODES, 
  692.       "Negative number of nodes requested to stop");
  693.     return -1;
  694.   }
  695.   Uint32 stoppedNoOfNodes = 0;
  696.   if(no_of_nodes == 0){
  697.     /**
  698.      * All database nodes should be stopped
  699.      */
  700.     Properties args;
  701.     args.put("abort", abort);
  702.     const Properties *reply;
  703.     reply = ndb_mgm_call(handle, stop_reply, "stop all", &args);
  704.     CHECK_REPLY(reply, -1);
  705.     if(!reply->get("stopped", &stoppedNoOfNodes)){
  706.       SET_ERROR(handle, NDB_MGM_STOP_FAILED, 
  707. "Could not get number of stopped nodes from mgm server");
  708.       delete reply;
  709.       return -1;
  710.     }
  711.     BaseString result;
  712.     reply->get("result", result);
  713.     if(strcmp(result.c_str(), "Ok") != 0) {
  714.       SET_ERROR(handle, NDB_MGM_STOP_FAILED, result.c_str());
  715.       delete reply;
  716.       return -1;
  717.     }
  718.     delete reply;
  719.     return stoppedNoOfNodes;
  720.   }
  721.   /**
  722.    * A list of database nodes should be stopped
  723.    */
  724.   Properties args;
  725.   BaseString node_list_str;
  726.   node_list_str.assfmt("%d", node_list[0]);
  727.   for(int node = 1; node < no_of_nodes; node++)
  728.     node_list_str.appfmt(" %d", node_list[node]);
  729.   
  730.   args.put("node", node_list_str.c_str());
  731.   args.put("abort", abort);
  732.   const Properties *reply;
  733.   reply = ndb_mgm_call(handle, stop_reply, "stop", &args);
  734.   CHECK_REPLY(reply, stoppedNoOfNodes);
  735.   if(!reply->get("stopped", &stoppedNoOfNodes)){
  736.     SET_ERROR(handle, NDB_MGM_STOP_FAILED, 
  737.       "Could not get number of stopped nodes from mgm server");
  738.     delete reply;
  739.     return -1;
  740.   }
  741.   BaseString result;
  742.   reply->get("result", result);
  743.   if(strcmp(result.c_str(), "Ok") != 0) {
  744.     SET_ERROR(handle, NDB_MGM_STOP_FAILED, result.c_str());
  745.     delete reply;
  746.     return -1;
  747.   }
  748.   delete reply;
  749.   return stoppedNoOfNodes;
  750. }
  751. extern "C"
  752. int
  753. ndb_mgm_restart2(NdbMgmHandle handle, int no_of_nodes, const int * node_list,
  754.  int initial, int nostart, int abort)
  755. {
  756.   SET_ERROR(handle, NDB_MGM_NO_ERROR, "Executing: ndb_mgm_restart2");
  757.   Uint32 restarted = 0;
  758.   const ParserRow<ParserDummy> restart_reply[] = {
  759.     MGM_CMD("restart reply", NULL, ""),
  760.     MGM_ARG("result", String, Mandatory, "Error message"),
  761.     MGM_ARG("restarted", Int, Optional, "No of restarted nodes"),
  762.     MGM_END()
  763.   };
  764.   CHECK_HANDLE(handle, -1);
  765.   CHECK_CONNECTED(handle, -1);
  766.   
  767.   if(no_of_nodes < 0){
  768.     SET_ERROR(handle, NDB_MGM_RESTART_FAILED, 
  769.       "Restart requested of negative number of nodes");
  770.     return -1;
  771.   }
  772.   
  773.   if(no_of_nodes == 0) {
  774.     Properties args;    
  775.     args.put("abort", abort);
  776.     args.put("initialstart", initial);
  777.     args.put("nostart", nostart);
  778.     const Properties *reply;
  779.     const int timeout = handle->read_timeout;
  780.     handle->read_timeout= 5*60*1000; // 5 minutes
  781.     reply = ndb_mgm_call(handle, restart_reply, "restart all", &args);
  782.     handle->read_timeout= timeout;
  783.     CHECK_REPLY(reply, -1);
  784.     BaseString result;
  785.     reply->get("result", result);
  786.     if(strcmp(result.c_str(), "Ok") != 0) {
  787.       SET_ERROR(handle, NDB_MGM_RESTART_FAILED, result.c_str());
  788.       delete reply;
  789.       return -1;
  790.     }
  791.     if(!reply->get("restarted", &restarted)){
  792.       SET_ERROR(handle, NDB_MGM_RESTART_FAILED, 
  793. "Could not get restarted number of nodes from mgm server");
  794.       delete reply;
  795.       return -1;
  796.     }
  797.     delete reply;
  798.     return restarted;
  799.   }      
  800.   BaseString node_list_str;
  801.   node_list_str.assfmt("%d", node_list[0]);
  802.   for(int node = 1; node < no_of_nodes; node++)
  803.     node_list_str.appfmt(" %d", node_list[node]);
  804.   Properties args;
  805.   
  806.   args.put("node", node_list_str.c_str());
  807.   args.put("abort", abort);
  808.   args.put("initialstart", initial);
  809.   args.put("nostart", nostart);
  810.   const Properties *reply;
  811.   const int timeout = handle->read_timeout;
  812.   handle->read_timeout= 5*60*1000; // 5 minutes
  813.   reply = ndb_mgm_call(handle, restart_reply, "restart node", &args);
  814.   handle->read_timeout= timeout;
  815.   if(reply != NULL) {
  816.     BaseString result;
  817.     reply->get("result", result);
  818.     if(strcmp(result.c_str(), "Ok") != 0) {
  819.       SET_ERROR(handle, NDB_MGM_RESTART_FAILED, result.c_str());
  820.       delete reply;
  821.       return -1;
  822.     }
  823.     reply->get("restarted", &restarted);
  824.     delete reply;
  825.   } 
  826.   
  827.   return restarted;
  828. }
  829. extern "C"
  830. int
  831. ndb_mgm_restart(NdbMgmHandle handle, int no_of_nodes, const int *node_list) 
  832. {
  833.   SET_ERROR(handle, NDB_MGM_NO_ERROR, "Executing: ndb_mgm_restart");
  834.   return ndb_mgm_restart2(handle, no_of_nodes, node_list, 0, 0, 0);
  835. }
  836. static const char *clusterlog_level_names[]=
  837.   { "enabled", "debug", "info", "warning", "error", "critical", "alert" };
  838. struct ndb_mgm_clusterlog_levels 
  839. {
  840.   const char* name;
  841.   enum ndb_mgm_clusterlog_level level;
  842. } clusterlog_levels[] = {
  843.   { clusterlog_level_names[0], NDB_MGM_CLUSTERLOG_ON },
  844.   { clusterlog_level_names[1], NDB_MGM_CLUSTERLOG_DEBUG },
  845.   { clusterlog_level_names[2], NDB_MGM_CLUSTERLOG_INFO },
  846.   { clusterlog_level_names[3], NDB_MGM_CLUSTERLOG_WARNING },
  847.   { clusterlog_level_names[4], NDB_MGM_CLUSTERLOG_ERROR },
  848.   { clusterlog_level_names[5], NDB_MGM_CLUSTERLOG_CRITICAL },
  849.   { clusterlog_level_names[6], NDB_MGM_CLUSTERLOG_ALERT },
  850.   { "all",                     NDB_MGM_CLUSTERLOG_ALL },
  851.   { 0,                         NDB_MGM_ILLEGAL_CLUSTERLOG_LEVEL },
  852. };
  853. extern "C"
  854. ndb_mgm_clusterlog_level
  855. ndb_mgm_match_clusterlog_level(const char * name)
  856. {
  857.   if(name == 0)
  858.     return NDB_MGM_ILLEGAL_CLUSTERLOG_LEVEL;
  859.   
  860.   for(int i = 0; clusterlog_levels[i].name !=0 ; i++)
  861.     if(strcasecmp(name, clusterlog_levels[i].name) == 0)
  862.       return clusterlog_levels[i].level;
  863.   return NDB_MGM_ILLEGAL_CLUSTERLOG_LEVEL;
  864. }
  865. extern "C"
  866. const char * 
  867. ndb_mgm_get_clusterlog_level_string(enum ndb_mgm_clusterlog_level level)
  868. {
  869.   int i= (int)level;
  870.   if (i >= 0 && i < (int)NDB_MGM_CLUSTERLOG_ALL)
  871.     return clusterlog_level_names[i];
  872.   for(i = (int)NDB_MGM_CLUSTERLOG_ALL; clusterlog_levels[i].name != 0; i++)
  873.     if(clusterlog_levels[i].level == level)
  874.       return clusterlog_levels[i].name;
  875.   return 0;
  876. }
  877. extern "C"
  878. unsigned int *
  879. ndb_mgm_get_logfilter(NdbMgmHandle handle) 
  880. {
  881.   SET_ERROR(handle, NDB_MGM_NO_ERROR, "Executing: ndb_mgm_get_logfilter");
  882.   static Uint32 enabled[(int)NDB_MGM_CLUSTERLOG_ALL] = {0,0,0,0,0,0,0};
  883.   const ParserRow<ParserDummy> getinfo_reply[] = {
  884.     MGM_CMD("clusterlog", NULL, ""),
  885.     MGM_ARG(clusterlog_level_names[0], Int, Mandatory, ""),
  886.     MGM_ARG(clusterlog_level_names[1], Int, Mandatory, ""),
  887.     MGM_ARG(clusterlog_level_names[2], Int, Mandatory, ""),
  888.     MGM_ARG(clusterlog_level_names[3], Int, Mandatory, ""),
  889.     MGM_ARG(clusterlog_level_names[4], Int, Mandatory, ""),
  890.     MGM_ARG(clusterlog_level_names[5], Int, Mandatory, ""),
  891.     MGM_ARG(clusterlog_level_names[6], Int, Mandatory, ""),
  892.   };
  893.   CHECK_HANDLE(handle, NULL);
  894.   CHECK_CONNECTED(handle, NULL);
  895.   Properties args;
  896.   const Properties *reply;
  897.   reply = ndb_mgm_call(handle, getinfo_reply, "get info clusterlog", &args);
  898.   CHECK_REPLY(reply, NULL);
  899.   
  900.   for(int i=0; i < (int)NDB_MGM_CLUSTERLOG_ALL; i++) {
  901.     reply->get(clusterlog_level_names[i], &enabled[i]);
  902.   }
  903.   return enabled;
  904. }
  905. extern "C"
  906. int 
  907. ndb_mgm_filter_clusterlog(NdbMgmHandle handle, 
  908.   enum ndb_mgm_clusterlog_level level,
  909.   int enable,
  910.   struct ndb_mgm_reply* /*reply*/) 
  911. {
  912.   SET_ERROR(handle, NDB_MGM_NO_ERROR, "Executing: ndb_mgm_filter_clusterlog");
  913.   const ParserRow<ParserDummy> filter_reply[] = {
  914.     MGM_CMD("set logfilter reply", NULL, ""),
  915.     MGM_ARG("result", String, Mandatory, "Error message"),
  916.     MGM_END()
  917.   };
  918.   int retval = -1;
  919.   CHECK_HANDLE(handle, -1);
  920.   CHECK_CONNECTED(handle, -1);
  921.   Properties args;
  922.   args.put("level", level);
  923.   args.put("enable", enable);
  924.   
  925.   const Properties *reply;
  926.   reply = ndb_mgm_call(handle, filter_reply, "set logfilter", &args);
  927.   CHECK_REPLY(reply, retval);
  928.   BaseString result;
  929.   reply->get("result", result);
  930.   if (strcmp(result.c_str(), "1") == 0)
  931.     retval = 1;
  932.   else if (strcmp(result.c_str(), "0") == 0)
  933.     retval = 0;
  934.   else
  935.   {
  936.     SET_ERROR(handle, EINVAL, result.c_str());
  937.   }
  938.   delete reply;
  939.   return retval;
  940. }
  941. struct ndb_mgm_event_categories 
  942. {
  943.   const char* name;
  944.   enum ndb_mgm_event_category category;
  945. } categories[] = {
  946.   { "STARTUP", NDB_MGM_EVENT_CATEGORY_STARTUP },
  947.   { "SHUTDOWN", NDB_MGM_EVENT_CATEGORY_SHUTDOWN },
  948.   { "STATISTICS", NDB_MGM_EVENT_CATEGORY_STATISTIC },
  949.   { "NODERESTART", NDB_MGM_EVENT_CATEGORY_NODE_RESTART },
  950.   { "CONNECTION", NDB_MGM_EVENT_CATEGORY_CONNECTION },
  951.   { "CHECKPOINT", NDB_MGM_EVENT_CATEGORY_CHECKPOINT },
  952.   { "DEBUG", NDB_MGM_EVENT_CATEGORY_DEBUG },
  953.   { "INFO", NDB_MGM_EVENT_CATEGORY_INFO },
  954.   { "ERROR", NDB_MGM_EVENT_CATEGORY_ERROR },
  955.   { "GREP", NDB_MGM_EVENT_CATEGORY_GREP },
  956.   { "BACKUP", NDB_MGM_EVENT_CATEGORY_BACKUP },
  957.   { 0, NDB_MGM_ILLEGAL_EVENT_CATEGORY }
  958. };
  959. extern "C"
  960. ndb_mgm_event_category
  961. ndb_mgm_match_event_category(const char * status)
  962. {
  963.   if(status == 0)
  964.     return NDB_MGM_ILLEGAL_EVENT_CATEGORY;
  965.   
  966.   for(int i = 0; categories[i].name !=0 ; i++)
  967.     if(strcmp(status, categories[i].name) == 0)
  968.       return categories[i].category;
  969.   return NDB_MGM_ILLEGAL_EVENT_CATEGORY;
  970. }
  971. extern "C"
  972. const char * 
  973. ndb_mgm_get_event_category_string(enum ndb_mgm_event_category status)
  974. {
  975.   int i;
  976.   for(i = 0; categories[i].name != 0; i++)
  977.     if(categories[i].category == status)
  978.       return categories[i].name;
  979.   
  980.   return 0;
  981. }
  982. extern "C"
  983. int 
  984. ndb_mgm_set_loglevel_clusterlog(NdbMgmHandle handle, int nodeId,
  985. enum ndb_mgm_event_category cat,
  986. int level,
  987. struct ndb_mgm_reply* /*reply*/) 
  988. {
  989.   SET_ERROR(handle, NDB_MGM_NO_ERROR, 
  990.     "Executing: ndb_mgm_set_loglevel_clusterlog");
  991.   const ParserRow<ParserDummy> clusterlog_reply[] = {
  992.     MGM_CMD("set cluster loglevel reply", NULL, ""),
  993.     MGM_ARG("result", String, Mandatory, "Error message"),
  994.     MGM_END()
  995.   };
  996.   CHECK_HANDLE(handle, -1);
  997.   CHECK_CONNECTED(handle, -1);
  998.   Properties args;
  999.   args.put("node", nodeId);
  1000.   args.put("category", cat);
  1001.   args.put("level", level);
  1002.   
  1003.   const Properties *reply;
  1004.   reply = ndb_mgm_call(handle, clusterlog_reply, 
  1005.        "set cluster loglevel", &args);
  1006.   CHECK_REPLY(reply, -1);
  1007.   
  1008.   DBUG_ENTER("ndb_mgm_set_loglevel_clusterlog");
  1009.   DBUG_PRINT("enter",("node=%d, category=%d, level=%d", nodeId, cat, level));
  1010.   BaseString result;
  1011.   reply->get("result", result);
  1012.   if(strcmp(result.c_str(), "Ok") != 0) {
  1013.     SET_ERROR(handle, EINVAL, result.c_str());
  1014.     delete reply;
  1015.     DBUG_RETURN(-1);
  1016.   }
  1017.   delete reply;
  1018.   DBUG_RETURN(0);
  1019. }
  1020. extern "C"
  1021. int 
  1022. ndb_mgm_set_loglevel_node(NdbMgmHandle handle, int nodeId,
  1023.   enum ndb_mgm_event_category category,
  1024.   int level,
  1025.   struct ndb_mgm_reply* /*reply*/) 
  1026. {
  1027.   SET_ERROR(handle, NDB_MGM_NO_ERROR, "Executing: ndb_mgm_set_loglevel_node");
  1028.   const ParserRow<ParserDummy> loglevel_reply[] = {
  1029.     MGM_CMD("set loglevel reply", NULL, ""),
  1030.     MGM_ARG("result", String, Mandatory, "Error message"),
  1031.     MGM_END()
  1032.   };
  1033.   CHECK_HANDLE(handle, -1);
  1034.   CHECK_CONNECTED(handle, -1);
  1035.   Properties args;
  1036.   args.put("node", nodeId);
  1037.   args.put("category", category);
  1038.   args.put("level", level);
  1039.   const Properties *reply;
  1040.   reply = ndb_mgm_call(handle, loglevel_reply, "set loglevel", &args);
  1041.   CHECK_REPLY(reply, -1);
  1042.   BaseString result;
  1043.   reply->get("result", result);
  1044.   if(strcmp(result.c_str(), "Ok") != 0) {
  1045.     SET_ERROR(handle, EINVAL, result.c_str());
  1046.     delete reply;
  1047.     return -1;
  1048.   }
  1049.   delete reply;
  1050.   return 0;
  1051. }
  1052. extern "C"
  1053. int
  1054. ndb_mgm_listen_event(NdbMgmHandle handle, int filter[])
  1055. {
  1056.   SET_ERROR(handle, NDB_MGM_NO_ERROR, "Executing: ndb_mgm_listen_event");
  1057.   const ParserRow<ParserDummy> stat_reply[] = {
  1058.     MGM_CMD("listen event", NULL, ""),
  1059.     MGM_ARG("result", Int, Mandatory, "Error message"),
  1060.     MGM_ARG("msg", String, Optional, "Error message"),
  1061.     MGM_END()
  1062.   };
  1063.   CHECK_HANDLE(handle, -1);
  1064.   
  1065.   const char *hostname= ndb_mgm_get_connected_host(handle);
  1066.   int port= ndb_mgm_get_connected_port(handle);
  1067.   SocketClient s(hostname, port);
  1068.   const NDB_SOCKET_TYPE sockfd = s.connect();
  1069.   if (sockfd == NDB_INVALID_SOCKET) {
  1070.     setError(handle, NDB_MGM_COULD_NOT_CONNECT_TO_SOCKET, __LINE__,
  1071.      "Unable to connect to");
  1072.     return -1;
  1073.   }
  1074.   Properties args;
  1075.   {
  1076.     BaseString tmp;
  1077.     for(int i = 0; filter[i] != 0; i += 2){
  1078.       tmp.appfmt("%d=%d ", filter[i+1], filter[i]);
  1079.     }
  1080.     args.put("filter", tmp.c_str());
  1081.   }
  1082.   
  1083.   int tmp = handle->socket;
  1084.   handle->socket = sockfd;
  1085.   
  1086.   const Properties *reply;
  1087.   reply = ndb_mgm_call(handle, stat_reply, "listen event", &args);
  1088.   
  1089.   handle->socket = tmp;
  1090.   
  1091.   CHECK_REPLY(reply, -1);
  1092.   return sockfd;
  1093. }
  1094. extern "C"
  1095. int 
  1096. ndb_mgm_get_stat_port(NdbMgmHandle handle, struct ndb_mgm_reply* /*reply*/)
  1097. {
  1098.   SET_ERROR(handle, NDB_MGM_NO_ERROR, "Executing: ndb_mgm_get_stat_port");
  1099.   const ParserRow<ParserDummy> stat_reply[] = {
  1100.     MGM_CMD("error", NULL, ""),
  1101.     MGM_ARG("result", String, Mandatory, "Error message"),
  1102.     MGM_CMD("get statport reply", NULL, ""),
  1103.     MGM_ARG("tcpport", Int, Mandatory, "TCP port for statistics"),
  1104.     MGM_END()
  1105.   };
  1106.   CHECK_HANDLE(handle, -1);
  1107.   CHECK_CONNECTED(handle, -1);
  1108.   
  1109.   Properties args;
  1110.   const Properties *reply;
  1111.   reply = ndb_mgm_call(handle, stat_reply, "get statport", &args);
  1112.   CHECK_REPLY(reply, -1);
  1113.   Uint32 port;
  1114.   reply->get("tcpport", &port);
  1115.   delete reply;
  1116.   return port;
  1117. }
  1118. extern "C"
  1119. int 
  1120. ndb_mgm_dump_state(NdbMgmHandle handle, int nodeId, int* _args,
  1121.    int _num_args, struct ndb_mgm_reply* /* reply */) 
  1122. {
  1123.   SET_ERROR(handle, NDB_MGM_NO_ERROR, "Executing: ndb_mgm_dump_state");
  1124.   const ParserRow<ParserDummy> dump_state_reply[] = {
  1125.     MGM_CMD("dump state reply", NULL, ""),
  1126.     MGM_ARG("result", String, Mandatory, "Error message"),
  1127.     MGM_END()
  1128.   };
  1129.   CHECK_HANDLE(handle, -1);
  1130.   CHECK_CONNECTED(handle, -1);
  1131.   char buf[256];
  1132.   buf[0] = 0;
  1133.   for (int i = 0; i < _num_args; i++){
  1134.     unsigned n = strlen(buf);
  1135.     if (n + 20 > sizeof(buf)) {
  1136.       SET_ERROR(handle, NDB_MGM_USAGE_ERROR, "arguments too long");
  1137.       return -1;
  1138.     }
  1139.     sprintf(buf + n, "%s%d", i ? " " : "", _args[i]);
  1140.   }
  1141.   Properties args;
  1142.   args.put("node", nodeId);
  1143.   args.put("args", buf);
  1144.   const Properties *prop;
  1145.   prop = ndb_mgm_call(handle, dump_state_reply, "dump state", &args);
  1146.   CHECK_REPLY(prop, -1);
  1147.   BaseString result;
  1148.   prop->get("result", result);
  1149.   if(strcmp(result.c_str(), "Ok") != 0) {
  1150.     SET_ERROR(handle, EINVAL, result.c_str());
  1151.     delete prop;
  1152.     return -1;
  1153.   }
  1154.   delete prop;
  1155.   return 0;
  1156. }
  1157. extern "C"
  1158. int 
  1159. ndb_mgm_start_signallog(NdbMgmHandle handle, int nodeId, 
  1160. struct ndb_mgm_reply* reply) 
  1161. {
  1162.   SET_ERROR(handle, NDB_MGM_NO_ERROR, "Executing: ndb_mgm_start_signallog");
  1163.   const ParserRow<ParserDummy> start_signallog_reply[] = {
  1164.     MGM_CMD("start signallog reply", NULL, ""),
  1165.     MGM_ARG("result", String, Mandatory, "Error message"),
  1166.     MGM_END()
  1167.   };
  1168.   int retval = -1;
  1169.   CHECK_HANDLE(handle, -1);
  1170.   CHECK_CONNECTED(handle, -1);
  1171.   Properties args;
  1172.   args.put("node", nodeId);
  1173.   const Properties *prop;
  1174.   prop = ndb_mgm_call(handle,
  1175.        start_signallog_reply,
  1176.        "start signallog",
  1177.        &args);
  1178.   if(prop != NULL) {
  1179.     BaseString result;
  1180.     prop->get("result", result);
  1181.     if(strcmp(result.c_str(), "Ok") == 0) {
  1182.       retval = 0;
  1183.     } else {
  1184.       SET_ERROR(handle, EINVAL, result.c_str());
  1185.       retval = -1;
  1186.     }
  1187.     delete prop;
  1188.   }
  1189.   return retval;
  1190. }
  1191. extern "C"
  1192. int 
  1193. ndb_mgm_stop_signallog(NdbMgmHandle handle, int nodeId,
  1194.        struct ndb_mgm_reply* reply) 
  1195. {
  1196.   SET_ERROR(handle, NDB_MGM_NO_ERROR, "Executing: ndb_mgm_stop_signallog");
  1197.   const ParserRow<ParserDummy> stop_signallog_reply[] = {
  1198.     MGM_CMD("stop signallog reply", NULL, ""),
  1199.     MGM_ARG("result", String, Mandatory, "Error message"),
  1200.     MGM_END()
  1201.   };
  1202.   int retval = -1;
  1203.   CHECK_HANDLE(handle, -1);
  1204.   CHECK_CONNECTED(handle, -1);
  1205.   
  1206.   Properties args;
  1207.   args.put("node", nodeId);
  1208.   const Properties *prop;
  1209.   prop = ndb_mgm_call(handle, stop_signallog_reply, "stop signallog", &args);
  1210.   if(prop != NULL) {
  1211.     BaseString result;
  1212.     prop->get("result", result);
  1213.     if(strcmp(result.c_str(), "Ok") == 0) {
  1214.       retval = 0;
  1215.     } else {
  1216.       SET_ERROR(handle, EINVAL, result.c_str());
  1217.       retval = -1;
  1218.     }
  1219.     delete prop;
  1220.   }
  1221.   return retval;
  1222. }
  1223. struct ndb_mgm_signal_log_modes 
  1224. {
  1225.   const char* name;
  1226.   enum ndb_mgm_signal_log_mode mode;
  1227. };
  1228. extern "C"
  1229. int 
  1230. ndb_mgm_log_signals(NdbMgmHandle handle, int nodeId, 
  1231.     enum ndb_mgm_signal_log_mode mode, 
  1232.     const char* blockNames,
  1233.     struct ndb_mgm_reply* reply) 
  1234. {
  1235.   SET_ERROR(handle, NDB_MGM_NO_ERROR, "Executing: ndb_mgm_log_signals");
  1236.   const ParserRow<ParserDummy> stop_signallog_reply[] = {
  1237.     MGM_CMD("log signals reply", NULL, ""),
  1238.     MGM_ARG("result", String, Mandatory, "Error message"),
  1239.     MGM_END()
  1240.   };
  1241.   int retval = -1;
  1242.   CHECK_HANDLE(handle, -1);
  1243.   CHECK_CONNECTED(handle, -1);
  1244.   Properties args;
  1245.   args.put("node", nodeId);
  1246.   args.put("blocks", blockNames);
  1247.   switch(mode) {
  1248.   case NDB_MGM_SIGNAL_LOG_MODE_IN:
  1249.     args.put("in", (Uint32)1);
  1250.     args.put("out", (Uint32)0);
  1251.     break;
  1252.   case NDB_MGM_SIGNAL_LOG_MODE_OUT:
  1253.     args.put("in", (Uint32)0);
  1254.     args.put("out", (Uint32)1);
  1255.     break;
  1256.   case NDB_MGM_SIGNAL_LOG_MODE_INOUT:
  1257.     args.put("in", (Uint32)1);
  1258.     args.put("out", (Uint32)1);
  1259.     break;
  1260.   case NDB_MGM_SIGNAL_LOG_MODE_OFF:
  1261.     args.put("in", (Uint32)0);
  1262.     args.put("out", (Uint32)0);
  1263.     break;
  1264.   }
  1265.   const Properties *prop;
  1266.   prop = ndb_mgm_call(handle, stop_signallog_reply, "log signals", &args);
  1267.   if(prop != NULL) {
  1268.     BaseString result;
  1269.     prop->get("result", result);
  1270.     if(strcmp(result.c_str(), "Ok") == 0) {
  1271.       retval = 0;
  1272.     } else {
  1273.       SET_ERROR(handle, EINVAL, result.c_str());
  1274.       retval = -1;
  1275.     }
  1276.     delete prop;
  1277.   }
  1278.   return retval;
  1279. }
  1280. extern "C"
  1281. int 
  1282. ndb_mgm_set_trace(NdbMgmHandle handle, int nodeId, int traceNumber,
  1283.   struct ndb_mgm_reply* reply) 
  1284. {
  1285.   SET_ERROR(handle, NDB_MGM_NO_ERROR, "Executing: ndb_mgm_set_trace");
  1286.   const ParserRow<ParserDummy> set_trace_reply[] = {
  1287.     MGM_CMD("set trace reply", NULL, ""),
  1288.     MGM_ARG("result", String, Mandatory, "Error message"),
  1289.     MGM_END()
  1290.   };
  1291.   int retval = -1;
  1292.   CHECK_HANDLE(handle, -1);
  1293.   CHECK_CONNECTED(handle, -1);
  1294.   Properties args;
  1295.   args.put("node", nodeId);
  1296.   args.put("trace", traceNumber);
  1297.   const Properties *prop;
  1298.   prop = ndb_mgm_call(handle, set_trace_reply, "set trace", &args);
  1299.   if(prop != NULL) {
  1300.     BaseString result;
  1301.     prop->get("result", result);
  1302.     if(strcmp(result.c_str(), "Ok") == 0) {
  1303.       retval = 0;
  1304.     } else {
  1305.       SET_ERROR(handle, EINVAL, result.c_str());
  1306.       retval = -1;
  1307.     }
  1308.     delete prop;
  1309.   }
  1310.   return retval;
  1311. }
  1312. extern "C"
  1313. int 
  1314. ndb_mgm_insert_error(NdbMgmHandle handle, int nodeId, int errorCode,
  1315.      struct ndb_mgm_reply* reply) 
  1316. {
  1317.   SET_ERROR(handle, NDB_MGM_NO_ERROR, "Executing: ndb_mgm_insert_error");
  1318.   const ParserRow<ParserDummy> insert_error_reply[] = {
  1319.     MGM_CMD("insert error reply", NULL, ""),
  1320.     MGM_ARG("result", String, Mandatory, "Error message"),
  1321.     MGM_END()
  1322.   };
  1323.   int retval = -1;
  1324.   CHECK_HANDLE(handle, -1);
  1325.   CHECK_CONNECTED(handle, -1);
  1326.   Properties args;
  1327.   args.put("node", nodeId);
  1328.   args.put("error", errorCode);
  1329.   const Properties *prop;
  1330.   prop = ndb_mgm_call(handle, insert_error_reply, "insert error", &args);
  1331.   if(prop != NULL) {
  1332.     BaseString result;
  1333.     prop->get("result", result);
  1334.     if(strcmp(result.c_str(), "Ok") == 0) {
  1335.       retval = 0;
  1336.     } else {
  1337.       SET_ERROR(handle, EINVAL, result.c_str());
  1338.       retval = -1;
  1339.     }
  1340.     delete prop;
  1341.   }
  1342.   return retval;
  1343. }
  1344. extern "C"
  1345. int 
  1346. ndb_mgm_start(NdbMgmHandle handle, int no_of_nodes, const int * node_list)
  1347. {
  1348.   SET_ERROR(handle, NDB_MGM_NO_ERROR, "Executing: ndb_mgm_start");
  1349.   const ParserRow<ParserDummy> start_reply[] = {
  1350.     MGM_CMD("start reply", NULL, ""),
  1351.     MGM_ARG("started", Int, Optional, "No of started nodes"),
  1352.     MGM_ARG("result", String, Mandatory, "Error message"),
  1353.     MGM_END()
  1354.   };
  1355.   int started = 0;
  1356.   CHECK_HANDLE(handle, -1);
  1357.   CHECK_CONNECTED(handle, -1);
  1358.   if(no_of_nodes < 0){
  1359.     SET_ERROR(handle, EINVAL, "");
  1360.     return -1;
  1361.   }
  1362.   if(no_of_nodes == 0){
  1363.     Properties args;
  1364.     const Properties *reply;
  1365.     reply = ndb_mgm_call(handle, start_reply, "start all", &args);
  1366.     CHECK_REPLY(reply, -1);
  1367.     Uint32 count = 0;
  1368.     if(!reply->get("started", &count)){
  1369.       delete reply;
  1370.       return -1;
  1371.     }
  1372.     delete reply;
  1373.     return count;
  1374.   }
  1375.   for(int node = 0; node < no_of_nodes; node++) {
  1376.     Properties args;
  1377.     args.put("node", node_list[node]);
  1378.     const Properties *reply;
  1379.     reply = ndb_mgm_call(handle, start_reply, "start", &args);
  1380.     if(reply != NULL) {
  1381.       BaseString result;
  1382.       reply->get("result", result);
  1383.       if(strcmp(result.c_str(), "Ok") == 0) {
  1384. started++;
  1385.       } else {
  1386. SET_ERROR(handle, EINVAL, result.c_str());
  1387. delete reply;
  1388. return -1;
  1389.       }
  1390.     }
  1391.     delete reply;
  1392.   }
  1393.   return started;
  1394. }
  1395. /*****************************************************************************
  1396.  * Backup
  1397.  *****************************************************************************/
  1398. extern "C"
  1399. int 
  1400. ndb_mgm_start_backup(NdbMgmHandle handle, int wait_completed,
  1401.      unsigned int* _backup_id,
  1402.      struct ndb_mgm_reply* /*reply*/) 
  1403. {
  1404.   SET_ERROR(handle, NDB_MGM_NO_ERROR, "Executing: ndb_mgm_start_backup");
  1405.   const ParserRow<ParserDummy> start_backup_reply[] = {
  1406.     MGM_CMD("start backup reply", NULL, ""),
  1407.     MGM_ARG("result", String, Mandatory, "Error message"),
  1408.     MGM_ARG("id", Int, Optional, "Id of the started backup"),
  1409.     MGM_END()
  1410.   };
  1411.   CHECK_HANDLE(handle, -1);
  1412.   CHECK_CONNECTED(handle, -1);
  1413.   Properties args;
  1414.   args.put("completed", wait_completed);
  1415.   const Properties *reply;
  1416.   { // start backup can take some time, set timeout high
  1417.     Uint64 old_timeout= handle->read_timeout;
  1418.     if (wait_completed == 2)
  1419.       handle->read_timeout= 48*60*60*1000; // 48 hours
  1420.     else if (wait_completed == 1)
  1421.       handle->read_timeout= 10*60*1000; // 10 minutes
  1422.     reply = ndb_mgm_call(handle, start_backup_reply, "start backup", &args);
  1423.     handle->read_timeout= old_timeout;
  1424.   }
  1425.   CHECK_REPLY(reply, -1);
  1426.   BaseString result;
  1427.   reply->get("result", result);
  1428.   reply->get("id", _backup_id);
  1429.   if(strcmp(result.c_str(), "Ok") != 0) {
  1430.     SET_ERROR(handle, NDB_MGM_COULD_NOT_START_BACKUP, result.c_str());
  1431.     delete reply;
  1432.     return -1;
  1433.   }
  1434.   delete reply;
  1435.   return 0;
  1436. }
  1437. extern "C"
  1438. int
  1439. ndb_mgm_abort_backup(NdbMgmHandle handle, unsigned int backupId,
  1440.      struct ndb_mgm_reply* /*reply*/) 
  1441. {
  1442.   SET_ERROR(handle, NDB_MGM_NO_ERROR, "Executing: ndb_mgm_abort_backup");
  1443.   const ParserRow<ParserDummy> stop_backup_reply[] = {
  1444.     MGM_CMD("abort backup reply", NULL, ""),
  1445.     MGM_ARG("result", String, Mandatory, "Error message"),    
  1446.     MGM_END()
  1447.   };
  1448.   CHECK_HANDLE(handle, -1);
  1449.   CHECK_CONNECTED(handle, -1);
  1450.   
  1451.   Properties args;
  1452.   args.put("id", backupId);
  1453.   const Properties *prop;
  1454.   prop = ndb_mgm_call(handle, stop_backup_reply, "abort backup", &args);
  1455.   CHECK_REPLY(prop, -1);
  1456.   const char * buf;
  1457.   prop->get("result", &buf);
  1458.   if(strcmp(buf,"Ok")!=0) {
  1459.     SET_ERROR(handle, NDB_MGM_COULD_NOT_ABORT_BACKUP, buf);
  1460.     delete prop;    
  1461.     return -1;
  1462.   }
  1463.   delete prop;
  1464.   return 0;
  1465. }
  1466. extern "C"
  1467. struct ndb_mgm_configuration *
  1468. ndb_mgm_get_configuration(NdbMgmHandle handle, unsigned int version) {
  1469.   CHECK_HANDLE(handle, 0);
  1470.   CHECK_CONNECTED(handle, 0);
  1471.   Properties args;
  1472.   args.put("version", version);
  1473.   const ParserRow<ParserDummy> reply[] = {
  1474.     MGM_CMD("get config reply", NULL, ""),
  1475.     MGM_ARG("result", String, Mandatory, "Error message"),    
  1476.     MGM_ARG("Content-Length", Int, Optional, "Content length in bytes"),
  1477.     MGM_ARG("Content-Type", String, Optional, "Type (octet-stream)"),
  1478.     MGM_ARG("Content-Transfer-Encoding", String, Optional, "Encoding(base64)"),
  1479.     MGM_END()
  1480.   };
  1481.   
  1482.   const Properties *prop;
  1483.   prop = ndb_mgm_call(handle, reply, "get config", &args);
  1484.   CHECK_REPLY(prop, 0);
  1485.   
  1486.   do {
  1487.     const char * buf;
  1488.     if(!prop->get("result", &buf) || strcmp(buf, "Ok") != 0){
  1489.       fprintf(handle->errstream, "ERROR Message: %snn", buf);
  1490.       break;
  1491.     }
  1492.     buf = "<Unspecified>";
  1493.     if(!prop->get("Content-Type", &buf) || 
  1494.        strcmp(buf, "ndbconfig/octet-stream") != 0){
  1495.       fprintf(handle->errstream, "Unhandled response type: %sn", buf);
  1496.       break;
  1497.     }
  1498.     buf = "<Unspecified>";
  1499.     if(!prop->get("Content-Transfer-Encoding", &buf) 
  1500.        || strcmp(buf, "base64") != 0){
  1501.       fprintf(handle->errstream, "Unhandled encoding: %sn", buf);
  1502.       break;
  1503.     }
  1504.     buf = "<Content-Length Unspecified>";
  1505.     Uint32 len = 0;
  1506.     if(!prop->get("Content-Length", &len)){
  1507.       fprintf(handle->errstream, "Invalid response: %snn", buf);
  1508.       break;
  1509.     }
  1510.     len += 1; // Trailing n
  1511.         
  1512.     char* buf64 = new char[len];
  1513.     int read = 0;
  1514.     size_t start = 0;
  1515.     do {
  1516.       if((read = read_socket(handle->socket, handle->read_timeout, 
  1517.      &buf64[start], len-start)) == -1){
  1518. delete[] buf64; 
  1519. buf64 = 0;
  1520. break;
  1521.       }
  1522.       start += read;
  1523.     } while(start < len);
  1524.     if(buf64 == 0)
  1525.       break;
  1526.     
  1527.     UtilBuffer tmp;
  1528.     const int res = base64_decode(buf64, len-1, tmp);
  1529.     delete[] buf64; 
  1530.     if(res != 0){
  1531.       fprintf(handle->errstream, "Failed to decode buffern");
  1532.       break;
  1533.     }
  1534.     ConfigValuesFactory cvf;
  1535.     const int res2 = cvf.unpack(tmp);
  1536.     if(!res2){
  1537.       fprintf(handle->errstream, "Failed to unpack buffern");
  1538.       break;
  1539.     }
  1540.     delete prop;
  1541.     return (ndb_mgm_configuration*)cvf.m_cfg;
  1542.   } while(0);
  1543.   delete prop;
  1544.   return 0;
  1545. }
  1546. extern "C"
  1547. void
  1548. ndb_mgm_destroy_configuration(struct ndb_mgm_configuration *cfg)
  1549. {
  1550.   if (cfg) {
  1551.     ((ConfigValues *)cfg)->~ConfigValues();
  1552.     free((void *)cfg);
  1553.   }
  1554. }
  1555. extern "C"
  1556. int
  1557. ndb_mgm_set_configuration_nodeid(NdbMgmHandle handle, int nodeid)
  1558. {
  1559.   CHECK_HANDLE(handle, -1);
  1560.   handle->cfg._ownNodeId= nodeid;
  1561.   return 0;
  1562. }
  1563. extern "C"
  1564. int
  1565. ndb_mgm_get_configuration_nodeid(NdbMgmHandle handle)
  1566. {
  1567.   CHECK_HANDLE(handle, 0);
  1568.   return handle->cfg._ownNodeId;
  1569. }
  1570. extern "C"
  1571. int ndb_mgm_get_connected_port(NdbMgmHandle handle)
  1572. {
  1573.   return handle->cfg.ids[handle->cfg_i].port;
  1574. }
  1575. extern "C"
  1576. const char *ndb_mgm_get_connected_host(NdbMgmHandle handle)
  1577. {
  1578.   return handle->cfg.ids[handle->cfg_i].name.c_str();
  1579. }
  1580. extern "C"
  1581. const char *ndb_mgm_get_connectstring(NdbMgmHandle handle, char *buf, int buf_sz)
  1582. {
  1583.   return handle->cfg.makeConnectString(buf,buf_sz);
  1584. }
  1585. extern "C"
  1586. int
  1587. ndb_mgm_alloc_nodeid(NdbMgmHandle handle, unsigned int version, int nodetype)
  1588. {
  1589.   CHECK_HANDLE(handle, 0);
  1590.   CHECK_CONNECTED(handle, 0);
  1591.   union { long l; char c[sizeof(long)]; } endian_check;
  1592.   endian_check.l = 1;
  1593.   int nodeid= handle->cfg._ownNodeId;
  1594.   Properties args;
  1595.   args.put("version", version);
  1596.   args.put("nodetype", nodetype);
  1597.   args.put("nodeid", nodeid);
  1598.   args.put("user", "mysqld");
  1599.   args.put("password", "mysqld");
  1600.   args.put("public key", "a public key");
  1601.   args.put("endian", (endian_check.c[sizeof(long)-1])?"big":"little");
  1602.   const ParserRow<ParserDummy> reply[]= {
  1603.     MGM_CMD("get nodeid reply", NULL, ""),
  1604.       MGM_ARG("nodeid", Int, Optional, "Error message"),
  1605.       MGM_ARG("result", String, Mandatory, "Error message"),
  1606.     MGM_END()
  1607.   };
  1608.   
  1609.   const Properties *prop;
  1610.   prop= ndb_mgm_call(handle, reply, "get nodeid", &args);
  1611.   CHECK_REPLY(prop, -1);
  1612.   nodeid= -1;
  1613.   do {
  1614.     const char * buf;
  1615.     if(!prop->get("result", &buf) || strcmp(buf, "Ok") != 0){
  1616.       const char *hostname= ndb_mgm_get_connected_host(handle);
  1617.       unsigned port=  ndb_mgm_get_connected_port(handle);
  1618.       BaseString err;
  1619.       err.assfmt("Could not alloc node id at %s port %d: %s",
  1620.  hostname, port, buf);
  1621.       setError(handle, NDB_MGM_COULD_NOT_CONNECT_TO_SOCKET, __LINE__,
  1622.        err.c_str());
  1623.       break;
  1624.     }
  1625.     Uint32 _nodeid;
  1626.     if(!prop->get("nodeid", &_nodeid) != 0){
  1627.       fprintf(handle->errstream, "ERROR Message: <nodeid Unspecified>n");
  1628.       break;
  1629.     }
  1630.     nodeid= _nodeid;
  1631.   }while(0);
  1632.   delete prop;
  1633.   return nodeid;
  1634. }
  1635. /*****************************************************************************
  1636.  * Global Replication
  1637.  ******************************************************************************/
  1638. extern "C"
  1639. int 
  1640. ndb_mgm_rep_command(NdbMgmHandle handle, unsigned int request,
  1641.     unsigned int* replication_id,
  1642.     struct ndb_mgm_reply* /*reply*/) 
  1643. {
  1644.   SET_ERROR(handle, NDB_MGM_NO_ERROR, "Executing: ndb_mgm_rep_command");
  1645.   const ParserRow<ParserDummy> replication_reply[] = {
  1646.     MGM_CMD("global replication reply", NULL, ""),
  1647.     MGM_ARG("result", String, Mandatory, "Error message"),
  1648.     MGM_ARG("id", Int, Optional, "Id of global replication"),
  1649.     MGM_END()
  1650.   };
  1651.   CHECK_HANDLE(handle, -1);
  1652.   CHECK_CONNECTED(handle, -1);
  1653.   Properties args;
  1654.   args.put("request", request);
  1655.   const Properties *reply;
  1656.   reply = ndb_mgm_call(handle, replication_reply, "rep", &args);
  1657.   CHECK_REPLY(reply, -1);
  1658.   
  1659.   const char * result;
  1660.   reply->get("result", &result);
  1661.   reply->get("id", replication_id);
  1662.   if(strcmp(result,"Ok")!=0) {
  1663.     delete reply;
  1664.     return -1;
  1665.   }
  1666.   delete reply;
  1667.   return 0;
  1668. }
  1669. extern "C"
  1670. int
  1671. ndb_mgm_set_int_parameter(NdbMgmHandle handle,
  1672.   int node, 
  1673.   int param,
  1674.   unsigned value,
  1675.   struct ndb_mgm_reply*){
  1676.   CHECK_HANDLE(handle, 0);
  1677.   CHECK_CONNECTED(handle, 0);
  1678.   
  1679.   Properties args;
  1680.   args.put("node: ", node);
  1681.   args.put("param: ", param);
  1682.   args.put("value: ", value);
  1683.   
  1684.   const ParserRow<ParserDummy> reply[]= {
  1685.     MGM_CMD("set parameter reply", NULL, ""),
  1686.     MGM_ARG("result", String, Mandatory, "Error message"),
  1687.     MGM_END()
  1688.   };
  1689.   
  1690.   const Properties *prop;
  1691.   prop= ndb_mgm_call(handle, reply, "set parameter", &args);
  1692.   CHECK_REPLY(prop, -1);
  1693.   int res= -1;
  1694.   do {
  1695.     const char * buf;
  1696.     if(!prop->get("result", &buf) || strcmp(buf, "Ok") != 0){
  1697.       fprintf(handle->errstream, "ERROR Message: %sn", buf);
  1698.       break;
  1699.     }
  1700.     res= 0;
  1701.   } while(0);
  1702.   
  1703.   delete prop;
  1704.   return res;
  1705. }
  1706. extern "C"
  1707. int 
  1708. ndb_mgm_set_int64_parameter(NdbMgmHandle handle,
  1709.     int node, 
  1710.     int param,
  1711.     unsigned long long value,
  1712.     struct ndb_mgm_reply*){
  1713.   CHECK_HANDLE(handle, 0);
  1714.   CHECK_CONNECTED(handle, 0);
  1715.   
  1716.   Properties args;
  1717.   args.put("node: ", node);
  1718.   args.put("param: ", param);
  1719.   args.put("value: ", value);
  1720.   
  1721.   const ParserRow<ParserDummy> reply[]= {
  1722.     MGM_CMD("set parameter reply", NULL, ""),
  1723.     MGM_ARG("result", String, Mandatory, "Error message"),
  1724.     MGM_END()
  1725.   };
  1726.   
  1727.   const Properties *prop;
  1728.   prop= ndb_mgm_call(handle, reply, "set parameter", &args);
  1729.   
  1730.   if(prop == NULL) {
  1731.     SET_ERROR(handle, EIO, "Unable set parameter");
  1732.     return -1;
  1733.   }
  1734.   int res= -1;
  1735.   do {
  1736.     const char * buf;
  1737.     if(!prop->get("result", &buf) || strcmp(buf, "Ok") != 0){
  1738.       fprintf(handle->errstream, "ERROR Message: %sn", buf);
  1739.       break;
  1740.     }
  1741.     res= 0;
  1742.   } while(0);
  1743.   
  1744.   delete prop;
  1745.   return res;
  1746. }
  1747. extern "C"
  1748. int
  1749. ndb_mgm_set_string_parameter(NdbMgmHandle handle,
  1750.      int node, 
  1751.      int param,
  1752.      const char * value,
  1753.      struct ndb_mgm_reply*){
  1754.   CHECK_HANDLE(handle, 0);
  1755.   CHECK_CONNECTED(handle, 0);
  1756.   
  1757.   Properties args;
  1758.   args.put("node: ", node);
  1759.   args.put("parameter: ", param);
  1760.   args.put("value: ", value);
  1761.   
  1762.   const ParserRow<ParserDummy> reply[]= {
  1763.     MGM_CMD("set parameter reply", NULL, ""),
  1764.     MGM_ARG("result", String, Mandatory, "Error message"),
  1765.     MGM_END()
  1766.   };
  1767.   
  1768.   const Properties *prop;
  1769.   prop= ndb_mgm_call(handle, reply, "set parameter", &args);
  1770.   
  1771.   if(prop == NULL) {
  1772.     SET_ERROR(handle, EIO, "Unable set parameter");
  1773.     return -1;
  1774.   }
  1775.   int res= -1;
  1776.   do {
  1777.     const char * buf;
  1778.     if(!prop->get("result", &buf) || strcmp(buf, "Ok") != 0){
  1779.       fprintf(handle->errstream, "ERROR Message: %sn", buf);
  1780.       break;
  1781.     }
  1782.     res= 0;
  1783.   } while(0);
  1784.   
  1785.   delete prop;
  1786.   return res;
  1787. }
  1788. extern "C"
  1789. int
  1790. ndb_mgm_purge_stale_sessions(NdbMgmHandle handle, char **purged){
  1791.   CHECK_HANDLE(handle, 0);
  1792.   CHECK_CONNECTED(handle, 0);
  1793.   
  1794.   Properties args;
  1795.   
  1796.   const ParserRow<ParserDummy> reply[]= {
  1797.     MGM_CMD("purge stale sessions reply", NULL, ""),
  1798.     MGM_ARG("purged", String, Optional, ""),
  1799.     MGM_ARG("result", String, Mandatory, "Error message"),
  1800.     MGM_END()
  1801.   };
  1802.   
  1803.   const Properties *prop;
  1804.   prop= ndb_mgm_call(handle, reply, "purge stale sessions", &args);
  1805.   
  1806.   if(prop == NULL) {
  1807.     SET_ERROR(handle, EIO, "Unable to purge stale sessions");
  1808.     return -1;
  1809.   }
  1810.   int res= -1;
  1811.   do {
  1812.     const char * buf;
  1813.     if(!prop->get("result", &buf) || strcmp(buf, "Ok") != 0){
  1814.       fprintf(handle->errstream, "ERROR Message: %sn", buf);
  1815.       break;
  1816.     }
  1817.     if (purged) {
  1818.       if (prop->get("purged", &buf))
  1819. *purged= strdup(buf);
  1820.       else
  1821. *purged= 0;
  1822.     }
  1823.     res= 0;
  1824.   } while(0);
  1825.   delete prop;
  1826.   return res;
  1827. }
  1828. extern "C"
  1829. int
  1830. ndb_mgm_check_connection(NdbMgmHandle handle){
  1831.   CHECK_HANDLE(handle, 0);
  1832.   CHECK_CONNECTED(handle, 0);
  1833.   SocketOutputStream out(handle->socket);
  1834.   SocketInputStream in(handle->socket, handle->read_timeout);
  1835.   char buf[32];
  1836.   if (out.println("check connection"))
  1837.     goto ndb_mgm_check_connection_error;
  1838.   if (out.println(""))
  1839.     goto ndb_mgm_check_connection_error;
  1840.   in.gets(buf, sizeof(buf));
  1841.   if(strcmp("check connection replyn", buf))
  1842.     goto ndb_mgm_check_connection_error;
  1843.   in.gets(buf, sizeof(buf));
  1844.   if(strcmp("result: Okn", buf))
  1845.     goto ndb_mgm_check_connection_error;
  1846.   in.gets(buf, sizeof(buf));
  1847.   if(strcmp("n", buf))
  1848.     goto ndb_mgm_check_connection_error;
  1849.   return 0;
  1850. ndb_mgm_check_connection_error:
  1851.   ndb_mgm_disconnect(handle);
  1852.   return -1;
  1853. }
  1854. template class Vector<const ParserRow<ParserDummy>*>;