1  /* Copyright (c) 2003, 2010, Oracle and/or its affiliates. All rights reserved.
2 
3    This program is free software; you can redistribute it and/or modify
4    it under the terms of the GNU General Public License as published by
5    the Free Software Foundation; version 2 of the License.
6 
7    This program is distributed in the hope that it will be useful,
8    but WITHOUT ANY WARRANTY; without even the implied warranty of
9    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
10    GNU General Public License for more details.
11 
12    You should have received a copy of the GNU General Public License
13    along with this program; if not, write to the Free Software
14    Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA */
15 
16 #include <ndb_global.h>
17 #include <my_sys.h>
18 
19 #include <LocalConfig.hpp>
20 #include <NdbAutoPtr.hpp>
21 
22 #include <NdbSleep.h>
23 #include <NdbTCP.h>
24 #include <mgmapi.h>
25 #include <mgmapi_internal.h>
26 #include <mgmapi_debug.h>
27 #include "mgmapi_configuration.hpp"
28 #include <socket_io.h>
29 #include <version.h>
30 
31 #include <NdbOut.hpp>
32 #include <SocketServer.hpp>
33 #include <SocketClient.hpp>
34 #include <Parser.hpp>
35 #include <OutputStream.hpp>
36 #include <InputStream.hpp>
37 
38 #include <base64.h>
39 
40 #define MGM_CMD(name, fun, desc) \
41  { name, \
42    0, \
43    ParserRow<ParserDummy>::Cmd, \
44    ParserRow<ParserDummy>::String, \
45    ParserRow<ParserDummy>::Optional, \
46    ParserRow<ParserDummy>::IgnoreMinMax, \
47    0, 0, \
48    fun, \
49    desc, 0 }
50 
51 #define MGM_ARG(name, type, opt, desc) \
52  { name, \
53    0, \
54    ParserRow<ParserDummy>::Arg, \
55    ParserRow<ParserDummy>::type, \
56    ParserRow<ParserDummy>::opt, \
57    ParserRow<ParserDummy>::IgnoreMinMax, \
58    0, 0, \
59    0, \
60    desc, 0 }
61 
62 #define MGM_END() \
63  { 0, \
64    0, \
65    ParserRow<ParserDummy>::Arg, \
66    ParserRow<ParserDummy>::Int, \
67    ParserRow<ParserDummy>::Optional, \
68    ParserRow<ParserDummy>::IgnoreMinMax, \
69    0, 0, \
70    0, \
71    0, 0 }
72 
73 class ParserDummy : private SocketServer::Session
74 {
75 public:
76   ParserDummy(NDB_SOCKET_TYPE sock);
77 };
78 
ParserDummy(NDB_SOCKET_TYPE sock)79 ParserDummy::ParserDummy(NDB_SOCKET_TYPE sock) : SocketServer::Session(sock)
80 {
81 }
82 
83 typedef Parser<ParserDummy> Parser_t;
84 
85 #define NDB_MGM_MAX_ERR_DESC_SIZE 256
86 
87 struct ndb_mgm_handle {
88   int cfg_i;
89 
90   int connected;
91   int last_error;
92   int last_error_line;
93   char last_error_desc[NDB_MGM_MAX_ERR_DESC_SIZE];
94   unsigned int timeout;
95 
96   NDB_SOCKET_TYPE socket;
97 
98   LocalConfig cfg;
99 
100 #ifdef MGMAPI_LOG
101   FILE* logfile;
102 #endif
103   FILE *errstream;
104   char *m_name;
105   int mgmd_version_major;
106   int mgmd_version_minor;
107   int mgmd_version_build;
108   char * m_bindaddress;
109 };
110 
111 #define SET_ERROR(h, e, s) setError(h, e, __LINE__, s)
112 
113 static
114 void
setError(NdbMgmHandle h,int error,int error_line,const char * msg,...)115 setError(NdbMgmHandle h, int error, int error_line, const char * msg, ...){
116 
117   h->last_error = error;  \
118   h->last_error_line = error_line;
119 
120   va_list ap;
121   va_start(ap, msg);
122   BaseString::vsnprintf(h->last_error_desc, sizeof(h->last_error_desc), msg, ap);
123   va_end(ap);
124 }
125 
126 #define CHECK_HANDLE(handle, ret) \
127   if(handle == 0) { \
128     SET_ERROR(handle, NDB_MGM_ILLEGAL_SERVER_HANDLE, ""); \
129     return ret; \
130   }
131 
132 #define CHECK_CONNECTED(handle, ret) \
133   if (handle->connected != 1) { \
134     SET_ERROR(handle, NDB_MGM_SERVER_NOT_CONNECTED , ""); \
135     return ret; \
136   }
137 
138 #define CHECK_REPLY(handle, reply, ret) \
139   if(reply == NULL) { \
140     if(!handle->last_error) \
141       SET_ERROR(handle, NDB_MGM_ILLEGAL_SERVER_REPLY, ""); \
142     return ret; \
143   }
144 
145 #define DBUG_CHECK_REPLY(handle, reply, ret) \
146   if (reply == NULL) { \
147     if(!handle->last_error) \
148       SET_ERROR(handle, NDB_MGM_ILLEGAL_SERVER_REPLY, ""); \
149     DBUG_RETURN(ret);                                    \
150   }
151 
152 #define CHECK_TIMEDOUT(in, out) \
153   if(in.timedout() || out.timedout()) \
154     SET_ERROR(handle, ETIMEDOUT, \
155               "Time out talking to management server");
156 
157 #define CHECK_TIMEDOUT_RET(h, in, out, ret) \
158   if(in.timedout() || out.timedout()) { \
159     SET_ERROR(handle, ETIMEDOUT, \
160               "Time out talking to management server"); \
161     ndb_mgm_disconnect_quiet(h); \
162     return ret; \
163   }
164 
165 #define DBUG_CHECK_TIMEDOUT_RET(h, in, out, ret) \
166   if(in.timedout() || out.timedout()) { \
167     SET_ERROR(handle, ETIMEDOUT, \
168               "Time out talking to management server"); \
169     ndb_mgm_disconnect_quiet(h); \
170     DBUG_RETURN(ret); \
171   }
172 
173 /*****************************************************************************
174  * Handles
175  *****************************************************************************/
176 
177 extern "C"
178 NdbMgmHandle
ndb_mgm_create_handle()179 ndb_mgm_create_handle()
180 {
181   DBUG_ENTER("ndb_mgm_create_handle");
182   NdbMgmHandle h     =
183     (NdbMgmHandle)my_malloc(sizeof(ndb_mgm_handle),MYF(MY_WME));
184   h->connected       = 0;
185   h->last_error      = 0;
186   h->last_error_line = 0;
187   h->socket          = NDB_INVALID_SOCKET;
188   h->timeout         = 60000;
189   h->cfg_i           = -1;
190   h->errstream       = stdout;
191   h->m_name          = 0;
192   h->m_bindaddress   = 0;
193 
194   strncpy(h->last_error_desc, "No error", NDB_MGM_MAX_ERR_DESC_SIZE);
195 
196   new (&(h->cfg)) LocalConfig;
197   h->cfg.init(0, 0);
198 
199 #ifdef MGMAPI_LOG
200   h->logfile = 0;
201 #endif
202 
203   h->mgmd_version_major= -1;
204   h->mgmd_version_minor= -1;
205   h->mgmd_version_build= -1;
206 
207   DBUG_PRINT("info", ("handle: 0x%lx", (long) h));
208   DBUG_RETURN(h);
209 }
210 
211 extern "C"
212 void
ndb_mgm_set_name(NdbMgmHandle handle,const char * name)213 ndb_mgm_set_name(NdbMgmHandle handle, const char *name)
214 {
215   my_free(handle->m_name);
216   handle->m_name= my_strdup(name, MYF(MY_WME));
217 }
218 
219 extern "C"
220 int
ndb_mgm_set_connectstring(NdbMgmHandle handle,const char * mgmsrv)221 ndb_mgm_set_connectstring(NdbMgmHandle handle, const char * mgmsrv)
222 {
223   DBUG_ENTER("ndb_mgm_set_connectstring");
224   DBUG_PRINT("info", ("handle: 0x%lx", (long) handle));
225   handle->cfg.~LocalConfig();
226   new (&(handle->cfg)) LocalConfig;
227   if (!handle->cfg.init(mgmsrv, 0) ||
228       handle->cfg.ids.size() == 0)
229   {
230     handle->cfg.~LocalConfig();
231     new (&(handle->cfg)) LocalConfig;
232     handle->cfg.init(0, 0); /* reset the LocalConfig */
233     SET_ERROR(handle, NDB_MGM_ILLEGAL_CONNECT_STRING, mgmsrv ? mgmsrv : "");
234     DBUG_RETURN(-1);
235   }
236   handle->cfg_i= -1;
237   DBUG_RETURN(0);
238 }
239 
240 extern "C"
241 int
ndb_mgm_set_bindaddress(NdbMgmHandle handle,const char * arg)242 ndb_mgm_set_bindaddress(NdbMgmHandle handle, const char * arg)
243 {
244   DBUG_ENTER("ndb_mgm_set_bindaddress");
245   if (handle->m_bindaddress)
246     free(handle->m_bindaddress);
247 
248   if (arg)
249     handle->m_bindaddress = strdup(arg);
250   else
251     handle->m_bindaddress = 0;
252 
253   DBUG_RETURN(0);
254 }
255 
256 /**
257  * Destroy a handle
258  */
259 extern "C"
260 void
ndb_mgm_destroy_handle(NdbMgmHandle * handle)261 ndb_mgm_destroy_handle(NdbMgmHandle * handle)
262 {
263   DBUG_ENTER("ndb_mgm_destroy_handle");
264   if(!handle)
265     DBUG_VOID_RETURN;
266   DBUG_PRINT("info", ("handle: 0x%lx", (long) (* handle)));
267   /**
268    * important! only disconnect if connected
269    * other code relies on this
270    */
271   if((* handle)->connected){
272     ndb_mgm_disconnect(* handle);
273   }
274 #ifdef MGMAPI_LOG
275   if ((* handle)->logfile != 0){
276     fclose((* handle)->logfile);
277     (* handle)->logfile = 0;
278   }
279 #endif
280   (*handle)->cfg.~LocalConfig();
281   my_free((*handle)->m_name);
282   if ((*handle)->m_bindaddress)
283     free((*handle)->m_bindaddress);
284   my_free(* handle);
285   * handle = 0;
286   DBUG_VOID_RETURN;
287 }
288 
289 extern "C"
290 void
ndb_mgm_set_error_stream(NdbMgmHandle handle,FILE * file)291 ndb_mgm_set_error_stream(NdbMgmHandle handle, FILE * file)
292 {
293   handle->errstream = file;
294 }
295 
296 /*****************************************************************************
297  * Error handling
298  *****************************************************************************/
299 
300 /**
301  * Get latest error associated with a handle
302  */
303 extern "C"
304 int
ndb_mgm_get_latest_error(const NdbMgmHandle h)305 ndb_mgm_get_latest_error(const NdbMgmHandle h)
306 {
307   return h->last_error;
308 }
309 
310 extern "C"
311 const char *
ndb_mgm_get_latest_error_desc(const NdbMgmHandle h)312 ndb_mgm_get_latest_error_desc(const NdbMgmHandle h){
313   return h->last_error_desc;
314 }
315 
316 extern "C"
317 int
ndb_mgm_get_latest_error_line(const NdbMgmHandle h)318 ndb_mgm_get_latest_error_line(const NdbMgmHandle h)
319 {
320   return h->last_error_line;
321 }
322 
323 extern "C"
324 const char *
ndb_mgm_get_latest_error_msg(const NdbMgmHandle h)325 ndb_mgm_get_latest_error_msg(const NdbMgmHandle h)
326 {
327   for (int i=0; i<ndb_mgm_noOfErrorMsgs; i++) {
328     if (ndb_mgm_error_msgs[i].code == h->last_error)
329       return ndb_mgm_error_msgs[i].msg;
330   }
331 
332   return "Error"; // Unknown Error message
333 }
334 
335 /*
336  * Call an operation, and return the reply
337  */
338 static const Properties *
ndb_mgm_call(NdbMgmHandle handle,const ParserRow<ParserDummy> * command_reply,const char * cmd,const Properties * cmd_args)339 ndb_mgm_call(NdbMgmHandle handle, const ParserRow<ParserDummy> *command_reply,
340 	     const char *cmd, const Properties *cmd_args)
341 {
342   DBUG_ENTER("ndb_mgm_call");
343   DBUG_PRINT("enter",("handle->socket: %d, cmd: %s",
344 		      handle->socket, cmd));
345   SocketOutputStream out(handle->socket, handle->timeout);
346   SocketInputStream in(handle->socket, handle->timeout);
347 
348   out.println(cmd);
349 #ifdef MGMAPI_LOG
350   /**
351    * Print command to  log file
352    */
353   FileOutputStream f(handle->logfile);
354   f.println("OUT: %s", cmd);
355 #endif
356 
357   if(cmd_args != NULL) {
358     Properties::Iterator iter(cmd_args);
359     const char *name;
360     while((name = iter.next()) != NULL) {
361       PropertiesType t;
362       Uint32 val_i;
363       Uint64 val_64;
364       BaseString val_s;
365 
366       cmd_args->getTypeOf(name, &t);
367       switch(t) {
368       case PropertiesType_Uint32:
369 	cmd_args->get(name, &val_i);
370 	out.println("%s: %d", name, val_i);
371 	break;
372       case PropertiesType_Uint64:
373 	cmd_args->get(name, &val_64);
374 	out.println("%s: %Ld", name, val_64);
375 	break;
376       case PropertiesType_char:
377 	cmd_args->get(name, val_s);
378 	out.println("%s: %s", name, val_s.c_str());
379 	break;
380       case PropertiesType_Properties:
381 	DBUG_PRINT("info",("Ignoring PropertiesType_Properties."));
382 	/* Ignore */
383 	break;
384       default:
385 	DBUG_PRINT("info",("Ignoring PropertiesType: %d.",t));
386       }
387     }
388 #ifdef MGMAPI_LOG
389   /**
390    * Print arguments to  log file
391    */
392   cmd_args->print(handle->logfile, "OUT: ");
393 #endif
394   }
395   out.println("");
396 
397   DBUG_CHECK_TIMEDOUT_RET(handle, in, out, NULL);
398 
399   Parser_t::Context ctx;
400   ParserDummy session(handle->socket);
401   Parser_t parser(command_reply, in, true, true, true);
402 
403   const Properties* p = parser.parse(ctx, session);
404   if (p == NULL){
405     if(!ndb_mgm_is_connected(handle)) {
406       DBUG_CHECK_TIMEDOUT_RET(handle, in, out, NULL);
407       DBUG_RETURN(NULL);
408     }
409     else
410     {
411       DBUG_CHECK_TIMEDOUT_RET(handle, in, out, NULL);
412       if(ctx.m_status==Parser_t::Eof
413 	 || ctx.m_status==Parser_t::NoLine)
414       {
415 	ndb_mgm_disconnect(handle);
416         DBUG_CHECK_TIMEDOUT_RET(handle, in, out, NULL);
417 	DBUG_RETURN(NULL);
418       }
419       /**
420        * Print some info about why the parser returns NULL
421        */
422       fprintf(handle->errstream,
423 	      "Error in mgm protocol parser. cmd: >%s< status: %d curr: %s\n",
424 	      cmd, (Uint32)ctx.m_status,
425               (ctx.m_currentToken)?ctx.m_currentToken:"NULL");
426       DBUG_PRINT("info",("ctx.status: %d, ctx.m_currentToken: %s",
427 		         ctx.m_status, ctx.m_currentToken));
428     }
429   }
430 #ifdef MGMAPI_LOG
431   else {
432     /**
433      * Print reply to log file
434      */
435     p->print(handle->logfile, "IN: ");
436   }
437 #endif
438 
439   if(p && (in.timedout() || out.timedout()))
440     delete p;
441   DBUG_CHECK_TIMEDOUT_RET(handle, in, out, NULL);
442   DBUG_RETURN(p);
443 }
444 
445 /**
446  * Returns true if connected
447  */
448 extern "C"
ndb_mgm_is_connected(NdbMgmHandle handle)449 int ndb_mgm_is_connected(NdbMgmHandle handle)
450 {
451   if(!handle)
452     return 0;
453 
454   if(handle->connected)
455   {
456     if(Ndb_check_socket_hup(handle->socket))
457     {
458       handle->connected= 0;
459       NDB_CLOSE_SOCKET(handle->socket);
460     }
461   }
462   return handle->connected;
463 }
464 
465 extern "C"
ndb_mgm_set_connect_timeout(NdbMgmHandle handle,unsigned int seconds)466 int ndb_mgm_set_connect_timeout(NdbMgmHandle handle, unsigned int seconds)
467 {
468   return ndb_mgm_set_timeout(handle, seconds*1000);
469   return 0;
470 }
471 
472 extern "C"
ndb_mgm_set_timeout(NdbMgmHandle handle,unsigned int timeout_ms)473 int ndb_mgm_set_timeout(NdbMgmHandle handle, unsigned int timeout_ms)
474 {
475   if(!handle)
476     return -1;
477 
478   handle->timeout= timeout_ms;
479   return 0;
480 }
481 
482 extern "C"
ndb_mgm_number_of_mgmd_in_connect_string(NdbMgmHandle handle)483 int ndb_mgm_number_of_mgmd_in_connect_string(NdbMgmHandle handle)
484 {
485   int count=0;
486   Uint32 i;
487   LocalConfig &cfg= handle->cfg;
488 
489   for (i = 0; i < cfg.ids.size(); i++)
490   {
491     if (cfg.ids[i].type != MgmId_TCP)
492       continue;
493     count++;
494   }
495   return count;
496 }
497 
498 /**
499  * Connect to a management server
500  */
501 extern "C"
502 int
ndb_mgm_connect(NdbMgmHandle handle,int no_retries,int retry_delay_in_seconds,int verbose)503 ndb_mgm_connect(NdbMgmHandle handle, int no_retries,
504 		int retry_delay_in_seconds, int verbose)
505 {
506   SET_ERROR(handle, NDB_MGM_NO_ERROR, "Executing: ndb_mgm_connect");
507   CHECK_HANDLE(handle, -1);
508 
509   DBUG_ENTER("ndb_mgm_connect");
510 #ifdef MGMAPI_LOG
511   /**
512   * Open the log file
513   */
514   char logname[64];
515   BaseString::snprintf(logname, 64, "mgmapi.log");
516   handle->logfile = fopen(logname, "w");
517 #endif
518   char buf[1024];
519 
520   /**
521    * Do connect
522    */
523   LocalConfig &cfg= handle->cfg;
524   NDB_SOCKET_TYPE sockfd= NDB_INVALID_SOCKET;
525   Uint32 i;
526   SocketClient s(0, 0);
527   s.set_connect_timeout((handle->timeout+999)/1000);
528   if (!s.init())
529   {
530     fprintf(handle->errstream,
531 	    "Unable to create socket, "
532 	    "while trying to connect with connect string: %s\n",
533 	    cfg.makeConnectString(buf,sizeof(buf)));
534 
535     setError(handle, NDB_MGM_COULD_NOT_CONNECT_TO_SOCKET, __LINE__,
536 	    "Unable to create socket, "
537 	    "while trying to connect with connect string: %s\n",
538 	    cfg.makeConnectString(buf,sizeof(buf)));
539     DBUG_RETURN(-1);
540   }
541 
542   if (handle->m_bindaddress)
543   {
544     BaseString::snprintf(buf, sizeof(buf), handle->m_bindaddress);
545     unsigned short portno = 0;
546     char * port = strchr(buf, ':');
547     if (port != 0)
548     {
549       portno = atoi(port+1);
550       * port = 0;
551     }
552     int err;
553     if ((err = s.bind(buf, portno)) != 0)
554     {
555       fprintf(handle->errstream,
556 	      "Unable to bind local address %s errno: %d, "
557 	      "while trying to connect with connect string: %s\n",
558 	      handle->m_bindaddress, err,
559 	      cfg.makeConnectString(buf,sizeof(buf)));
560 
561       setError(handle, NDB_MGM_BIND_ADDRESS, __LINE__,
562 	       "Unable to bind local address %s errno: %d, "
563 	       "while trying to connect with connect string: %s\n",
564 	       handle->m_bindaddress, err,
565 	       cfg.makeConnectString(buf,sizeof(buf)));
566       DBUG_RETURN(-1);
567     }
568   }
569 
570   while (sockfd == NDB_INVALID_SOCKET)
571   {
572     // do all the mgmt servers
573     for (i = 0; i < cfg.ids.size(); i++)
574     {
575       if (cfg.ids[i].type != MgmId_TCP)
576 	continue;
577       sockfd = s.connect(cfg.ids[i].name.c_str(), cfg.ids[i].port);
578       if (sockfd != NDB_INVALID_SOCKET)
579 	break;
580     }
581     if (sockfd != NDB_INVALID_SOCKET)
582       break;
583 #ifndef DBUG_OFF
584     {
585       DBUG_PRINT("info",("Unable to connect with connect string: %s",
586 			 cfg.makeConnectString(buf,sizeof(buf))));
587     }
588 #endif
589     if (verbose > 0) {
590       fprintf(handle->errstream,
591 	      "Unable to connect with connect string: %s\n",
592 	      cfg.makeConnectString(buf,sizeof(buf)));
593       verbose= -1;
594     }
595     if (no_retries == 0) {
596       setError(handle, NDB_MGM_COULD_NOT_CONNECT_TO_SOCKET, __LINE__,
597 	       "Unable to connect with connect string: %s",
598 	       cfg.makeConnectString(buf,sizeof(buf)));
599       if (verbose == -2)
600 	fprintf(handle->errstream, ", failed.\n");
601       DBUG_RETURN(-1);
602     }
603     if (verbose == -1) {
604       fprintf(handle->errstream, "Retrying every %d seconds",
605 	      retry_delay_in_seconds);
606       if (no_retries > 0)
607 	fprintf(handle->errstream, ". Attempts left:");
608       else
609 	fprintf(handle->errstream, ", until connected.");
610       fflush(handle->errstream);
611       verbose= -2;
612     }
613     if (no_retries > 0) {
614       if (verbose == -2) {
615 	fprintf(handle->errstream, " %d", no_retries);
616 	fflush(handle->errstream);
617       }
618       no_retries--;
619     }
620     NdbSleep_SecSleep(retry_delay_in_seconds);
621   }
622   if (verbose == -2)
623   {
624     fprintf(handle->errstream, "\n");
625     fflush(handle->errstream);
626   }
627   handle->cfg_i = i;
628 
629   handle->socket    = sockfd;
630   handle->connected = 1;
631 
632   DBUG_RETURN(0);
633 }
634 
635 /**
636  * Only used for low level testing
637  * Never to be used by end user.
638  * Or anybody who doesn't know exactly what they're doing.
639  */
640 extern "C"
641 int
ndb_mgm_get_fd(NdbMgmHandle handle)642 ndb_mgm_get_fd(NdbMgmHandle handle)
643 {
644   return handle->socket;
645 }
646 
647 /**
648  * Disconnect from mgm server without error checking
649  * Should be used internally only.
650  * e.g. on timeout, we leave NdbMgmHandle disconnected
651  */
652 extern "C"
653 int
ndb_mgm_disconnect_quiet(NdbMgmHandle handle)654 ndb_mgm_disconnect_quiet(NdbMgmHandle handle)
655 {
656   NDB_CLOSE_SOCKET(handle->socket);
657   handle->socket = NDB_INVALID_SOCKET;
658   handle->connected = 0;
659 
660   return 0;
661 }
662 
663 /**
664  * Disconnect from a mgm server
665  */
666 extern "C"
667 int
ndb_mgm_disconnect(NdbMgmHandle handle)668 ndb_mgm_disconnect(NdbMgmHandle handle)
669 {
670   SET_ERROR(handle, NDB_MGM_NO_ERROR, "Executing: ndb_mgm_disconnect");
671   CHECK_HANDLE(handle, -1);
672   CHECK_CONNECTED(handle, -1);
673 
674   return ndb_mgm_disconnect_quiet(handle);
675 }
676 
677 struct ndb_mgm_type_atoi
678 {
679   const char * str;
680   const char * alias;
681   enum ndb_mgm_node_type value;
682 };
683 
684 static struct ndb_mgm_type_atoi type_values[] =
685 {
686   { "NDB", "ndbd", NDB_MGM_NODE_TYPE_NDB},
687   { "API", "mysqld", NDB_MGM_NODE_TYPE_API },
688   { "MGM", "ndb_mgmd", NDB_MGM_NODE_TYPE_MGM }
689 };
690 
691 const int no_of_type_values = (sizeof(type_values) /
692 			       sizeof(ndb_mgm_type_atoi));
693 
694 extern "C"
695 ndb_mgm_node_type
ndb_mgm_match_node_type(const char * type)696 ndb_mgm_match_node_type(const char * type)
697 {
698   if(type == 0)
699     return NDB_MGM_NODE_TYPE_UNKNOWN;
700 
701   for(int i = 0; i<no_of_type_values; i++)
702     if(strcmp(type, type_values[i].str) == 0)
703       return type_values[i].value;
704     else if(strcmp(type, type_values[i].alias) == 0)
705       return type_values[i].value;
706 
707   return NDB_MGM_NODE_TYPE_UNKNOWN;
708 }
709 
710 extern "C"
711 const char *
ndb_mgm_get_node_type_string(enum ndb_mgm_node_type type)712 ndb_mgm_get_node_type_string(enum ndb_mgm_node_type type)
713 {
714   for(int i = 0; i<no_of_type_values; i++)
715     if(type_values[i].value == type)
716       return type_values[i].str;
717   return 0;
718 }
719 
720 extern "C"
721 const char *
ndb_mgm_get_node_type_alias_string(enum ndb_mgm_node_type type,const char ** str)722 ndb_mgm_get_node_type_alias_string(enum ndb_mgm_node_type type, const char** str)
723 {
724   for(int i = 0; i<no_of_type_values; i++)
725     if(type_values[i].value == type)
726       {
727 	if (str)
728 	  *str= type_values[i].str;
729 	return type_values[i].alias;
730       }
731   return 0;
732 }
733 
734 struct ndb_mgm_status_atoi {
735   const char * str;
736   enum ndb_mgm_node_status value;
737 };
738 
739 static struct ndb_mgm_status_atoi status_values[] =
740 {
741   { "UNKNOWN", NDB_MGM_NODE_STATUS_UNKNOWN },
742   { "NO_CONTACT", NDB_MGM_NODE_STATUS_NO_CONTACT },
743   { "NOT_STARTED", NDB_MGM_NODE_STATUS_NOT_STARTED },
744   { "STARTING", NDB_MGM_NODE_STATUS_STARTING },
745   { "STARTED", NDB_MGM_NODE_STATUS_STARTED },
746   { "SHUTTING_DOWN", NDB_MGM_NODE_STATUS_SHUTTING_DOWN },
747   { "RESTARTING", NDB_MGM_NODE_STATUS_RESTARTING },
748   { "SINGLE USER MODE", NDB_MGM_NODE_STATUS_SINGLEUSER }
749 };
750 
751 const int no_of_status_values = (sizeof(status_values) /
752 				 sizeof(ndb_mgm_status_atoi));
753 
754 extern "C"
755 ndb_mgm_node_status
ndb_mgm_match_node_status(const char * status)756 ndb_mgm_match_node_status(const char * status)
757 {
758   if(status == 0)
759     return NDB_MGM_NODE_STATUS_UNKNOWN;
760 
761   for(int i = 0; i<no_of_status_values; i++)
762     if(strcmp(status, status_values[i].str) == 0)
763       return status_values[i].value;
764 
765   return NDB_MGM_NODE_STATUS_UNKNOWN;
766 }
767 
768 extern "C"
769 const char *
ndb_mgm_get_node_status_string(enum ndb_mgm_node_status status)770 ndb_mgm_get_node_status_string(enum ndb_mgm_node_status status)
771 {
772   int i;
773   for(i = 0; i<no_of_status_values; i++)
774     if(status_values[i].value == status)
775       return status_values[i].str;
776 
777   for(i = 0; i<no_of_status_values; i++)
778     if(status_values[i].value == NDB_MGM_NODE_STATUS_UNKNOWN)
779       return status_values[i].str;
780 
781   return 0;
782 }
783 
784 static int
status_ackumulate(struct ndb_mgm_node_state * state,const char * field,const char * value)785 status_ackumulate(struct ndb_mgm_node_state * state,
786 		  const char * field,
787 		  const char * value)
788 {
789   if(strcmp("type", field) == 0){
790     state->node_type = ndb_mgm_match_node_type(value);
791   } else if(strcmp("status", field) == 0){
792     state->node_status = ndb_mgm_match_node_status(value);
793   } else if(strcmp("startphase", field) == 0){
794     state->start_phase = atoi(value);
795   } else if(strcmp("dynamic_id", field) == 0){
796     state->dynamic_id = atoi(value);
797   } else if(strcmp("node_group", field) == 0){
798     state->node_group = atoi(value);
799   } else if(strcmp("version", field) == 0){
800     state->version = atoi(value);
801   } else if(strcmp("connect_count", field) == 0){
802     state->connect_count = atoi(value);
803   } else if(strcmp("address", field) == 0){
804     strncpy(state->connect_address, value, sizeof(state->connect_address));
805     state->connect_address[sizeof(state->connect_address)-1]= 0;
806   } else {
807     ndbout_c("Unknown field: %s", field);
808   }
809   return 0;
810 }
811 
812 /**
813  * Compare function for qsort() that sorts ndb_mgm_node_state in
814  * node_id order
815  */
816 static int
cmp_state(const void * _a,const void * _b)817 cmp_state(const void *_a, const void *_b)
818 {
819   struct ndb_mgm_node_state *a, *b;
820 
821   a = (struct ndb_mgm_node_state *)_a;
822   b = (struct ndb_mgm_node_state *)_b;
823 
824   if (a->node_id > b->node_id)
825     return 1;
826   return -1;
827 }
828 
829 extern "C"
830 struct ndb_mgm_cluster_state *
ndb_mgm_get_status(NdbMgmHandle handle)831 ndb_mgm_get_status(NdbMgmHandle handle)
832 {
833   SET_ERROR(handle, NDB_MGM_NO_ERROR, "Executing: ndb_mgm_get_status");
834   CHECK_HANDLE(handle, NULL);
835   CHECK_CONNECTED(handle, NULL);
836 
837   SocketOutputStream out(handle->socket, handle->timeout);
838   SocketInputStream in(handle->socket, handle->timeout);
839 
840   out.println("get status");
841   out.println("");
842 
843   CHECK_TIMEDOUT_RET(handle, in, out, NULL);
844 
845   char buf[1024];
846   if(!in.gets(buf, sizeof(buf)))
847   {
848     CHECK_TIMEDOUT_RET(handle, in, out, NULL);
849     SET_ERROR(handle, NDB_MGM_ILLEGAL_SERVER_REPLY, "Probably disconnected");
850     return NULL;
851   }
852   if(strcmp("node status\n", buf) != 0) {
853     CHECK_TIMEDOUT_RET(handle, in, out, NULL);
854     ndbout << in.timedout() << " " << out.timedout() << buf << endl;
855     SET_ERROR(handle, NDB_MGM_ILLEGAL_NODE_STATUS, buf);
856     return NULL;
857   }
858   if(!in.gets(buf, sizeof(buf)))
859   {
860     CHECK_TIMEDOUT_RET(handle, in, out, NULL);
861     SET_ERROR(handle, NDB_MGM_ILLEGAL_SERVER_REPLY, "Probably disconnected");
862     return NULL;
863   }
864 
865   BaseString tmp(buf);
866   Vector<BaseString> split;
867   tmp.split(split, ":");
868   if(split.size() != 2){
869     CHECK_TIMEDOUT_RET(handle, in, out, NULL);
870     SET_ERROR(handle, NDB_MGM_ILLEGAL_NODE_STATUS, buf);
871     return NULL;
872   }
873 
874   if(!(split[0].trim() == "nodes")){
875     SET_ERROR(handle, NDB_MGM_ILLEGAL_NODE_STATUS, buf);
876     return NULL;
877   }
878 
879   const int noOfNodes = atoi(split[1].c_str());
880 
881   ndb_mgm_cluster_state *state = (ndb_mgm_cluster_state*)
882     malloc(sizeof(ndb_mgm_cluster_state)+
883 	   noOfNodes*(sizeof(ndb_mgm_node_state)+sizeof("000.000.000.000#")));
884 
885   if(!state)
886   {
887     SET_ERROR(handle, NDB_MGM_OUT_OF_MEMORY,
888               "Allocating ndb_mgm_cluster_state");
889     return NULL;
890   }
891 
892   state->no_of_nodes= noOfNodes;
893   ndb_mgm_node_state * ptr = &state->node_states[0];
894   int nodeId = 0;
895   int i;
896   for (i= 0; i < noOfNodes; i++) {
897     state->node_states[i].connect_address[0]= 0;
898   }
899   i = -1; ptr--;
900   for(; i<noOfNodes; ){
901     if(!in.gets(buf, sizeof(buf)))
902     {
903       free(state);
904       if(in.timedout() || out.timedout())
905         SET_ERROR(handle, ETIMEDOUT,
906                   "Time out talking to management server");
907       else
908         SET_ERROR(handle, NDB_MGM_ILLEGAL_SERVER_REPLY,
909                   "Probably disconnected");
910       return NULL;
911     }
912     tmp.assign(buf);
913 
914     if(tmp.trim() == ""){
915       break;
916     }
917 
918     Vector<BaseString> split2;
919     tmp.split(split2, ":.", 4);
920     if(split2.size() != 4)
921       break;
922 
923     const int id = atoi(split2[1].c_str());
924     if(id != nodeId){
925       ptr++;
926       i++;
927       nodeId = id;
928       ptr->node_id = id;
929     }
930 
931     split2[3].trim(" \t\n");
932 
933     if(status_ackumulate(ptr,split2[2].c_str(), split2[3].c_str()) != 0) {
934       break;
935     }
936   }
937 
938   if(i+1 != noOfNodes){
939     free(state);
940     CHECK_TIMEDOUT_RET(handle, in, out, NULL);
941     SET_ERROR(handle, NDB_MGM_ILLEGAL_NODE_STATUS, "Node count mismatch");
942     return NULL;
943   }
944 
945   qsort(state->node_states, state->no_of_nodes, sizeof(state->node_states[0]),
946 	cmp_state);
947   return state;
948 }
949 
950 extern "C"
951 int
ndb_mgm_enter_single_user(NdbMgmHandle handle,unsigned int nodeId,struct ndb_mgm_reply *)952 ndb_mgm_enter_single_user(NdbMgmHandle handle,
953 			  unsigned int nodeId,
954 			  struct ndb_mgm_reply* /*reply*/)
955 {
956   SET_ERROR(handle, NDB_MGM_NO_ERROR, "Executing: ndb_mgm_enter_single_user");
957   const ParserRow<ParserDummy> enter_single_reply[] = {
958     MGM_CMD("enter single user reply", NULL, ""),
959     MGM_ARG("result", String, Mandatory, "Error message"),
960     MGM_END()
961   };
962   CHECK_HANDLE(handle, -1);
963   CHECK_CONNECTED(handle, -1);
964 
965   Properties args;
966   args.put("nodeId", nodeId);
967   const Properties *reply;
968   reply = ndb_mgm_call(handle, enter_single_reply, "enter single user", &args);
969   CHECK_REPLY(handle, reply, -1);
970 
971   BaseString result;
972   reply->get("result", result);
973   if(strcmp(result.c_str(), "Ok") != 0) {
974     SET_ERROR(handle, NDB_MGM_COULD_NOT_ENTER_SINGLE_USER_MODE,
975 	      result.c_str());
976     delete reply;
977     return -1;
978   }
979 
980   delete reply;
981   return 0;
982 }
983 
984 
985 extern "C"
986 int
ndb_mgm_exit_single_user(NdbMgmHandle handle,struct ndb_mgm_reply *)987 ndb_mgm_exit_single_user(NdbMgmHandle handle, struct ndb_mgm_reply* /*reply*/)
988 {
989   SET_ERROR(handle, NDB_MGM_NO_ERROR, "Executing: ndb_mgm_exit_single_user");
990   const ParserRow<ParserDummy> exit_single_reply[] = {
991     MGM_CMD("exit single user reply", NULL, ""),
992     MGM_ARG("result", String, Mandatory, "Error message"),
993     MGM_END()
994   };
995   CHECK_HANDLE(handle, -1);
996   CHECK_CONNECTED(handle, -1);
997 
998   const Properties *reply;
999   reply = ndb_mgm_call(handle, exit_single_reply, "exit single user", 0);
1000   CHECK_REPLY(handle, reply, -1);
1001 
1002   const char * buf;
1003   reply->get("result", &buf);
1004   if(strcmp(buf,"Ok")!=0) {
1005     SET_ERROR(handle, NDB_MGM_COULD_NOT_EXIT_SINGLE_USER_MODE, buf);
1006     delete reply;
1007     return -1;
1008   }
1009 
1010   delete reply;
1011   return 0;
1012 }
1013 
1014 extern "C"
1015 int
ndb_mgm_stop(NdbMgmHandle handle,int no_of_nodes,const int * node_list)1016 ndb_mgm_stop(NdbMgmHandle handle, int no_of_nodes, const int * node_list)
1017 {
1018   SET_ERROR(handle, NDB_MGM_NO_ERROR, "Executing: ndb_mgm_stop");
1019   return ndb_mgm_stop2(handle, no_of_nodes, node_list, 0);
1020 }
1021 
1022 extern "C"
1023 int
ndb_mgm_stop2(NdbMgmHandle handle,int no_of_nodes,const int * node_list,int abort)1024 ndb_mgm_stop2(NdbMgmHandle handle, int no_of_nodes, const int * node_list,
1025 	      int abort)
1026 {
1027   int disconnect;
1028   return ndb_mgm_stop3(handle, no_of_nodes, node_list, abort, &disconnect);
1029 }
1030 
1031 
1032 extern "C"
1033 int
ndb_mgm_stop3(NdbMgmHandle handle,int no_of_nodes,const int * node_list,int abort,int * disconnect)1034 ndb_mgm_stop3(NdbMgmHandle handle, int no_of_nodes, const int * node_list,
1035 	      int abort, int *disconnect)
1036 {
1037   SET_ERROR(handle, NDB_MGM_NO_ERROR, "Executing: ndb_mgm_stop3");
1038   const ParserRow<ParserDummy> stop_reply_v1[] = {
1039     MGM_CMD("stop reply", NULL, ""),
1040     MGM_ARG("stopped", Int, Optional, "No of stopped nodes"),
1041     MGM_ARG("result", String, Mandatory, "Error message"),
1042     MGM_END()
1043   };
1044   const ParserRow<ParserDummy> stop_reply_v2[] = {
1045     MGM_CMD("stop reply", NULL, ""),
1046     MGM_ARG("stopped", Int, Optional, "No of stopped nodes"),
1047     MGM_ARG("result", String, Mandatory, "Error message"),
1048     MGM_ARG("disconnect", Int, Mandatory, "Need to disconnect"),
1049     MGM_END()
1050   };
1051 
1052   CHECK_HANDLE(handle, -1);
1053   CHECK_CONNECTED(handle, -1);
1054 
1055   if(handle->mgmd_version_build==-1)
1056   {
1057     char verstr[50];
1058     if(!ndb_mgm_get_version(handle,
1059                         &(handle->mgmd_version_major),
1060                         &(handle->mgmd_version_minor),
1061                         &(handle->mgmd_version_build),
1062                         sizeof(verstr),
1063                             verstr))
1064     {
1065       return -1;
1066     }
1067   }
1068   int use_v2= ((handle->mgmd_version_major==5)
1069     && (
1070         (handle->mgmd_version_minor==0 && handle->mgmd_version_build>=21)
1071         ||(handle->mgmd_version_minor==1 && handle->mgmd_version_build>=12)
1072         ||(handle->mgmd_version_minor>1)
1073         )
1074                )
1075     || (handle->mgmd_version_major>5);
1076 
1077   if(no_of_nodes < -1){
1078     SET_ERROR(handle, NDB_MGM_ILLEGAL_NUMBER_OF_NODES,
1079 	      "Negative number of nodes requested to stop");
1080     return -1;
1081   }
1082 
1083   Uint32 stoppedNoOfNodes = 0;
1084   if(no_of_nodes <= 0){
1085     /**
1086      * All nodes should be stopped (all or just db)
1087      */
1088     Properties args;
1089     args.put("abort", abort);
1090     if(use_v2)
1091       args.put("stop", (no_of_nodes==-1)?"mgm,db":"db");
1092     const Properties *reply;
1093     if(use_v2)
1094       reply = ndb_mgm_call(handle, stop_reply_v2, "stop all", &args);
1095     else
1096       reply = ndb_mgm_call(handle, stop_reply_v1, "stop all", &args);
1097     CHECK_REPLY(handle, reply, -1);
1098 
1099     if(!reply->get("stopped", &stoppedNoOfNodes)){
1100       SET_ERROR(handle, NDB_MGM_STOP_FAILED,
1101 		"Could not get number of stopped nodes from mgm server");
1102       delete reply;
1103       return -1;
1104     }
1105     if(use_v2)
1106       reply->get("disconnect", (Uint32*)disconnect);
1107     else
1108       *disconnect= 0;
1109     BaseString result;
1110     reply->get("result", result);
1111     if(strcmp(result.c_str(), "Ok") != 0) {
1112       SET_ERROR(handle, NDB_MGM_STOP_FAILED, result.c_str());
1113       delete reply;
1114       return -1;
1115     }
1116     delete reply;
1117     return stoppedNoOfNodes;
1118   }
1119 
1120   /**
1121    * A list of database nodes should be stopped
1122    */
1123   Properties args;
1124 
1125   BaseString node_list_str;
1126   node_list_str.assfmt("%d", node_list[0]);
1127   for(int node = 1; node < no_of_nodes; node++)
1128     node_list_str.appfmt(" %d", node_list[node]);
1129 
1130   args.put("node", node_list_str.c_str());
1131   args.put("abort", abort);
1132 
1133   const Properties *reply;
1134   if(use_v2)
1135     reply = ndb_mgm_call(handle, stop_reply_v2, "stop v2", &args);
1136   else
1137     reply = ndb_mgm_call(handle, stop_reply_v1, "stop", &args);
1138 
1139   CHECK_REPLY(handle, reply, stoppedNoOfNodes);
1140   if(!reply->get("stopped", &stoppedNoOfNodes)){
1141     SET_ERROR(handle, NDB_MGM_STOP_FAILED,
1142 	      "Could not get number of stopped nodes from mgm server");
1143     delete reply;
1144     return -1;
1145   }
1146   if(use_v2)
1147     reply->get("disconnect", (Uint32*)disconnect);
1148   else
1149     *disconnect= 0;
1150   BaseString result;
1151   reply->get("result", result);
1152   if(strcmp(result.c_str(), "Ok") != 0) {
1153     SET_ERROR(handle, NDB_MGM_STOP_FAILED, result.c_str());
1154     delete reply;
1155     return -1;
1156   }
1157   delete reply;
1158   return stoppedNoOfNodes;
1159 }
1160 
1161 extern "C"
1162 int
ndb_mgm_restart(NdbMgmHandle handle,int no_of_nodes,const int * node_list)1163 ndb_mgm_restart(NdbMgmHandle handle, int no_of_nodes, const int *node_list)
1164 {
1165   SET_ERROR(handle, NDB_MGM_NO_ERROR, "Executing: ndb_mgm_restart");
1166   return ndb_mgm_restart2(handle, no_of_nodes, node_list, 0, 0, 0);
1167 }
1168 
1169 extern "C"
1170 int
ndb_mgm_restart2(NdbMgmHandle handle,int no_of_nodes,const int * node_list,int initial,int nostart,int abort)1171 ndb_mgm_restart2(NdbMgmHandle handle, int no_of_nodes, const int * node_list,
1172 		 int initial, int nostart, int abort)
1173 {
1174   int disconnect;
1175 
1176   return ndb_mgm_restart3(handle, no_of_nodes, node_list, initial, nostart,
1177                           abort, &disconnect);
1178 }
1179 
1180 extern "C"
1181 int
ndb_mgm_restart3(NdbMgmHandle handle,int no_of_nodes,const int * node_list,int initial,int nostart,int abort,int * disconnect)1182 ndb_mgm_restart3(NdbMgmHandle handle, int no_of_nodes, const int * node_list,
1183 		 int initial, int nostart, int abort, int *disconnect)
1184 {
1185   SET_ERROR(handle, NDB_MGM_NO_ERROR, "Executing: ndb_mgm_restart3");
1186   Uint32 restarted = 0;
1187   const ParserRow<ParserDummy> restart_reply_v1[] = {
1188     MGM_CMD("restart reply", NULL, ""),
1189     MGM_ARG("result", String, Mandatory, "Error message"),
1190     MGM_ARG("restarted", Int, Optional, "No of restarted nodes"),
1191     MGM_END()
1192   };
1193   const ParserRow<ParserDummy> restart_reply_v2[] = {
1194     MGM_CMD("restart reply", NULL, ""),
1195     MGM_ARG("result", String, Mandatory, "Error message"),
1196     MGM_ARG("restarted", Int, Optional, "No of restarted nodes"),
1197     MGM_ARG("disconnect", Int, Optional, "Disconnect to apply"),
1198     MGM_END()
1199   };
1200 
1201   CHECK_HANDLE(handle, -1);
1202   CHECK_CONNECTED(handle, -1);
1203 
1204   if(handle->mgmd_version_build==-1)
1205   {
1206     char verstr[50];
1207     if(!ndb_mgm_get_version(handle,
1208                         &(handle->mgmd_version_major),
1209                         &(handle->mgmd_version_minor),
1210                         &(handle->mgmd_version_build),
1211                         sizeof(verstr),
1212                             verstr))
1213     {
1214       return -1;
1215     }
1216   }
1217   int use_v2= ((handle->mgmd_version_major==5)
1218     && (
1219         (handle->mgmd_version_minor==0 && handle->mgmd_version_build>=21)
1220         ||(handle->mgmd_version_minor==1 && handle->mgmd_version_build>=12)
1221         ||(handle->mgmd_version_minor>1)
1222         )
1223                )
1224     || (handle->mgmd_version_major>5);
1225 
1226   if(no_of_nodes < 0){
1227     SET_ERROR(handle, NDB_MGM_RESTART_FAILED,
1228 	      "Restart requested of negative number of nodes");
1229     return -1;
1230   }
1231 
1232   if(no_of_nodes == 0) {
1233     Properties args;
1234     args.put("abort", abort);
1235     args.put("initialstart", initial);
1236     args.put("nostart", nostart);
1237     const Properties *reply;
1238     const int timeout = handle->timeout;
1239     handle->timeout= 5*60*1000; // 5 minutes
1240     reply = ndb_mgm_call(handle, restart_reply_v1, "restart all", &args);
1241     handle->timeout= timeout;
1242     CHECK_REPLY(handle, reply, -1);
1243 
1244     BaseString result;
1245     reply->get("result", result);
1246     if(strcmp(result.c_str(), "Ok") != 0) {
1247       SET_ERROR(handle, NDB_MGM_RESTART_FAILED, result.c_str());
1248       delete reply;
1249       return -1;
1250     }
1251     if(!reply->get("restarted", &restarted)){
1252       SET_ERROR(handle, NDB_MGM_RESTART_FAILED,
1253 		"Could not get restarted number of nodes from mgm server");
1254       delete reply;
1255       return -1;
1256     }
1257     delete reply;
1258     return restarted;
1259   }
1260 
1261   BaseString node_list_str;
1262   node_list_str.assfmt("%d", node_list[0]);
1263   for(int node = 1; node < no_of_nodes; node++)
1264     node_list_str.appfmt(" %d", node_list[node]);
1265 
1266   Properties args;
1267 
1268   args.put("node", node_list_str.c_str());
1269   args.put("abort", abort);
1270   args.put("initialstart", initial);
1271   args.put("nostart", nostart);
1272 
1273   const Properties *reply;
1274   const int timeout = handle->timeout;
1275   handle->timeout= 5*60*1000; // 5 minutes
1276   if(use_v2)
1277     reply = ndb_mgm_call(handle, restart_reply_v2, "restart node v2", &args);
1278   else
1279     reply = ndb_mgm_call(handle, restart_reply_v1, "restart node", &args);
1280   handle->timeout= timeout;
1281   if(reply != NULL) {
1282     BaseString result;
1283     reply->get("result", result);
1284     if(strcmp(result.c_str(), "Ok") != 0) {
1285       SET_ERROR(handle, NDB_MGM_RESTART_FAILED, result.c_str());
1286       delete reply;
1287       return -1;
1288     }
1289     reply->get("restarted", &restarted);
1290     if(use_v2)
1291       reply->get("disconnect", (Uint32*)disconnect);
1292     else
1293       *disconnect= 0;
1294     delete reply;
1295   }
1296 
1297   return restarted;
1298 }
1299 
1300 static const char *clusterlog_severity_names[]=
1301   { "enabled", "debug", "info", "warning", "error", "critical", "alert" };
1302 
1303 struct ndb_mgm_event_severities
1304 {
1305   const char* name;
1306   enum ndb_mgm_event_severity severity;
1307 } clusterlog_severities[] = {
1308   { clusterlog_severity_names[0], NDB_MGM_EVENT_SEVERITY_ON },
1309   { clusterlog_severity_names[1], NDB_MGM_EVENT_SEVERITY_DEBUG },
1310   { clusterlog_severity_names[2], NDB_MGM_EVENT_SEVERITY_INFO },
1311   { clusterlog_severity_names[3], NDB_MGM_EVENT_SEVERITY_WARNING },
1312   { clusterlog_severity_names[4], NDB_MGM_EVENT_SEVERITY_ERROR },
1313   { clusterlog_severity_names[5], NDB_MGM_EVENT_SEVERITY_CRITICAL },
1314   { clusterlog_severity_names[6], NDB_MGM_EVENT_SEVERITY_ALERT },
1315   { "all",                        NDB_MGM_EVENT_SEVERITY_ALL },
1316   { 0,                            NDB_MGM_ILLEGAL_EVENT_SEVERITY },
1317 };
1318 
1319 extern "C"
1320 ndb_mgm_event_severity
ndb_mgm_match_event_severity(const char * name)1321 ndb_mgm_match_event_severity(const char * name)
1322 {
1323   if(name == 0)
1324     return NDB_MGM_ILLEGAL_EVENT_SEVERITY;
1325 
1326   for(int i = 0; clusterlog_severities[i].name !=0 ; i++)
1327     if(strcasecmp(name, clusterlog_severities[i].name) == 0)
1328       return clusterlog_severities[i].severity;
1329 
1330   return NDB_MGM_ILLEGAL_EVENT_SEVERITY;
1331 }
1332 
1333 extern "C"
1334 const char *
ndb_mgm_get_event_severity_string(enum ndb_mgm_event_severity severity)1335 ndb_mgm_get_event_severity_string(enum ndb_mgm_event_severity severity)
1336 {
1337   int i= (int)severity;
1338   if (i >= 0 && i < (int)NDB_MGM_EVENT_SEVERITY_ALL)
1339     return clusterlog_severity_names[i];
1340   for(i = (int)NDB_MGM_EVENT_SEVERITY_ALL; clusterlog_severities[i].name != 0; i++)
1341     if(clusterlog_severities[i].severity == severity)
1342       return clusterlog_severities[i].name;
1343   return 0;
1344 }
1345 
1346 extern "C"
1347 int
ndb_mgm_get_clusterlog_severity_filter(NdbMgmHandle handle,struct ndb_mgm_severity * severity,unsigned int severity_size)1348 ndb_mgm_get_clusterlog_severity_filter(NdbMgmHandle handle,
1349 				       struct ndb_mgm_severity* severity,
1350 				       unsigned int severity_size)
1351 {
1352   SET_ERROR(handle, NDB_MGM_NO_ERROR, "Executing: ndb_mgm_get_clusterlog_severity_filter");
1353   const ParserRow<ParserDummy> getinfo_reply[] = {
1354     MGM_CMD("clusterlog", NULL, ""),
1355     MGM_ARG(clusterlog_severity_names[0], Int, Mandatory, ""),
1356     MGM_ARG(clusterlog_severity_names[1], Int, Mandatory, ""),
1357     MGM_ARG(clusterlog_severity_names[2], Int, Mandatory, ""),
1358     MGM_ARG(clusterlog_severity_names[3], Int, Mandatory, ""),
1359     MGM_ARG(clusterlog_severity_names[4], Int, Mandatory, ""),
1360     MGM_ARG(clusterlog_severity_names[5], Int, Mandatory, ""),
1361     MGM_ARG(clusterlog_severity_names[6], Int, Mandatory, ""),
1362   };
1363   CHECK_HANDLE(handle, -1);
1364   CHECK_CONNECTED(handle, -1);
1365 
1366   Properties args;
1367   const Properties *reply;
1368   reply = ndb_mgm_call(handle, getinfo_reply, "get info clusterlog", &args);
1369   CHECK_REPLY(handle, reply, -1);
1370 
1371   for(unsigned int i=0; i < severity_size; i++) {
1372     reply->get(clusterlog_severity_names[severity[i].category], &severity[i].value);
1373   }
1374   return severity_size;
1375 }
1376 
1377 extern "C"
1378 const unsigned int *
ndb_mgm_get_clusterlog_severity_filter_old(NdbMgmHandle handle)1379 ndb_mgm_get_clusterlog_severity_filter_old(NdbMgmHandle handle)
1380 {
1381   SET_ERROR(handle, NDB_MGM_NO_ERROR, "Executing: ndb_mgm_get_clusterlog_severity_filter");
1382   static unsigned int enabled[(int)NDB_MGM_EVENT_SEVERITY_ALL]=
1383     {0,0,0,0,0,0,0};
1384   const ParserRow<ParserDummy> getinfo_reply[] = {
1385     MGM_CMD("clusterlog", NULL, ""),
1386     MGM_ARG(clusterlog_severity_names[0], Int, Mandatory, ""),
1387     MGM_ARG(clusterlog_severity_names[1], Int, Mandatory, ""),
1388     MGM_ARG(clusterlog_severity_names[2], Int, Mandatory, ""),
1389     MGM_ARG(clusterlog_severity_names[3], Int, Mandatory, ""),
1390     MGM_ARG(clusterlog_severity_names[4], Int, Mandatory, ""),
1391     MGM_ARG(clusterlog_severity_names[5], Int, Mandatory, ""),
1392     MGM_ARG(clusterlog_severity_names[6], Int, Mandatory, ""),
1393   };
1394   CHECK_HANDLE(handle, NULL);
1395   CHECK_CONNECTED(handle, NULL);
1396 
1397   Properties args;
1398   const Properties *reply;
1399   reply = ndb_mgm_call(handle, getinfo_reply, "get info clusterlog", &args);
1400   CHECK_REPLY(handle, reply, NULL);
1401 
1402   for(int i=0; i < (int)NDB_MGM_EVENT_SEVERITY_ALL; i++) {
1403     reply->get(clusterlog_severity_names[i], &enabled[i]);
1404   }
1405   return enabled;
1406 }
1407 
1408 extern "C"
1409 int
ndb_mgm_set_clusterlog_severity_filter(NdbMgmHandle handle,enum ndb_mgm_event_severity severity,int enable,struct ndb_mgm_reply *)1410 ndb_mgm_set_clusterlog_severity_filter(NdbMgmHandle handle,
1411 				       enum ndb_mgm_event_severity severity,
1412 				       int enable,
1413 				       struct ndb_mgm_reply* /*reply*/)
1414 {
1415   SET_ERROR(handle, NDB_MGM_NO_ERROR,
1416 	    "Executing: ndb_mgm_set_clusterlog_severity_filter");
1417   const ParserRow<ParserDummy> filter_reply[] = {
1418     MGM_CMD("set logfilter reply", NULL, ""),
1419     MGM_ARG("result", String, Mandatory, "Error message"),
1420     MGM_END()
1421   };
1422   int retval = -1;
1423   CHECK_HANDLE(handle, -1);
1424   CHECK_CONNECTED(handle, -1);
1425 
1426   Properties args;
1427   args.put("level", severity);
1428   args.put("enable", enable);
1429 
1430   const Properties *reply;
1431   reply = ndb_mgm_call(handle, filter_reply, "set logfilter", &args);
1432   CHECK_REPLY(handle, reply, retval);
1433 
1434   BaseString result;
1435   reply->get("result", result);
1436 
1437   if (strcmp(result.c_str(), "1") == 0)
1438     retval = 1;
1439   else if (strcmp(result.c_str(), "0") == 0)
1440     retval = 0;
1441   else
1442   {
1443     SET_ERROR(handle, EINVAL, result.c_str());
1444   }
1445   delete reply;
1446   return retval;
1447 }
1448 
1449 struct ndb_mgm_event_categories
1450 {
1451   const char* name;
1452   enum ndb_mgm_event_category category;
1453 } categories[] = {
1454   { "STARTUP", NDB_MGM_EVENT_CATEGORY_STARTUP },
1455   { "SHUTDOWN", NDB_MGM_EVENT_CATEGORY_SHUTDOWN },
1456   { "STATISTICS", NDB_MGM_EVENT_CATEGORY_STATISTIC },
1457   { "NODERESTART", NDB_MGM_EVENT_CATEGORY_NODE_RESTART },
1458   { "CONNECTION", NDB_MGM_EVENT_CATEGORY_CONNECTION },
1459   { "CHECKPOINT", NDB_MGM_EVENT_CATEGORY_CHECKPOINT },
1460   { "DEBUG", NDB_MGM_EVENT_CATEGORY_DEBUG },
1461   { "INFO", NDB_MGM_EVENT_CATEGORY_INFO },
1462   { "ERROR", NDB_MGM_EVENT_CATEGORY_ERROR },
1463   { "BACKUP", NDB_MGM_EVENT_CATEGORY_BACKUP },
1464   { "CONGESTION", NDB_MGM_EVENT_CATEGORY_CONGESTION },
1465   { 0, NDB_MGM_ILLEGAL_EVENT_CATEGORY }
1466 };
1467 
1468 extern "C"
1469 ndb_mgm_event_category
ndb_mgm_match_event_category(const char * status)1470 ndb_mgm_match_event_category(const char * status)
1471 {
1472   if(status == 0)
1473     return NDB_MGM_ILLEGAL_EVENT_CATEGORY;
1474 
1475   for(int i = 0; categories[i].name !=0 ; i++)
1476     if(strcmp(status, categories[i].name) == 0)
1477       return categories[i].category;
1478 
1479   return NDB_MGM_ILLEGAL_EVENT_CATEGORY;
1480 }
1481 
1482 extern "C"
1483 const char *
ndb_mgm_get_event_category_string(enum ndb_mgm_event_category status)1484 ndb_mgm_get_event_category_string(enum ndb_mgm_event_category status)
1485 {
1486   int i;
1487   for(i = 0; categories[i].name != 0; i++)
1488     if(categories[i].category == status)
1489       return categories[i].name;
1490 
1491   return 0;
1492 }
1493 
1494 static const char *clusterlog_names[]=
1495   { "startup", "shutdown", "statistics", "checkpoint", "noderestart", "connection", "info", "warning", "error", "congestion", "debug", "backup" };
1496 
1497 extern "C"
1498 int
ndb_mgm_get_clusterlog_loglevel(NdbMgmHandle handle,struct ndb_mgm_loglevel * loglevel,unsigned int loglevel_size)1499 ndb_mgm_get_clusterlog_loglevel(NdbMgmHandle handle,
1500 				struct ndb_mgm_loglevel* loglevel,
1501 				unsigned int loglevel_size)
1502 {
1503   SET_ERROR(handle, NDB_MGM_NO_ERROR, "Executing: ndb_mgm_get_clusterlog_loglevel");
1504   int loglevel_count = loglevel_size;
1505   const ParserRow<ParserDummy> getloglevel_reply[] = {
1506     MGM_CMD("get cluster loglevel", NULL, ""),
1507     MGM_ARG(clusterlog_names[0], Int, Mandatory, ""),
1508     MGM_ARG(clusterlog_names[1], Int, Mandatory, ""),
1509     MGM_ARG(clusterlog_names[2], Int, Mandatory, ""),
1510     MGM_ARG(clusterlog_names[3], Int, Mandatory, ""),
1511     MGM_ARG(clusterlog_names[4], Int, Mandatory, ""),
1512     MGM_ARG(clusterlog_names[5], Int, Mandatory, ""),
1513     MGM_ARG(clusterlog_names[6], Int, Mandatory, ""),
1514     MGM_ARG(clusterlog_names[7], Int, Mandatory, ""),
1515     MGM_ARG(clusterlog_names[8], Int, Mandatory, ""),
1516     MGM_ARG(clusterlog_names[9], Int, Mandatory, ""),
1517     MGM_ARG(clusterlog_names[10], Int, Mandatory, ""),
1518     MGM_ARG(clusterlog_names[11], Int, Mandatory, ""),
1519   };
1520   CHECK_HANDLE(handle, -1);
1521   CHECK_CONNECTED(handle, -1);
1522 
1523   Properties args;
1524   const Properties *reply;
1525   reply = ndb_mgm_call(handle, getloglevel_reply, "get cluster loglevel", &args);
1526   CHECK_REPLY(handle, reply, -1);
1527 
1528   for(int i=0; i < loglevel_count; i++) {
1529     reply->get(clusterlog_names[loglevel[i].category], &loglevel[i].value);
1530   }
1531   return loglevel_count;
1532 }
1533 
1534 extern "C"
1535 const unsigned int *
ndb_mgm_get_clusterlog_loglevel_old(NdbMgmHandle handle)1536 ndb_mgm_get_clusterlog_loglevel_old(NdbMgmHandle handle)
1537 {
1538   SET_ERROR(handle, NDB_MGM_NO_ERROR, "Executing: ndb_mgm_get_clusterlog_loglevel");
1539   int loglevel_count = CFG_MAX_LOGLEVEL - CFG_MIN_LOGLEVEL + 1 ;
1540   static unsigned int loglevel[CFG_MAX_LOGLEVEL - CFG_MIN_LOGLEVEL + 1] = {0,0,0,0,0,0,0,0,0,0,0,0};
1541   const ParserRow<ParserDummy> getloglevel_reply[] = {
1542     MGM_CMD("get cluster loglevel", NULL, ""),
1543     MGM_ARG(clusterlog_names[0], Int, Mandatory, ""),
1544     MGM_ARG(clusterlog_names[1], Int, Mandatory, ""),
1545     MGM_ARG(clusterlog_names[2], Int, Mandatory, ""),
1546     MGM_ARG(clusterlog_names[3], Int, Mandatory, ""),
1547     MGM_ARG(clusterlog_names[4], Int, Mandatory, ""),
1548     MGM_ARG(clusterlog_names[5], Int, Mandatory, ""),
1549     MGM_ARG(clusterlog_names[6], Int, Mandatory, ""),
1550     MGM_ARG(clusterlog_names[7], Int, Mandatory, ""),
1551     MGM_ARG(clusterlog_names[8], Int, Mandatory, ""),
1552     MGM_ARG(clusterlog_names[9], Int, Mandatory, ""),
1553     MGM_ARG(clusterlog_names[10], Int, Mandatory, ""),
1554     MGM_ARG(clusterlog_names[11], Int, Mandatory, ""),
1555   };
1556   CHECK_HANDLE(handle, NULL);
1557   CHECK_CONNECTED(handle, NULL);
1558 
1559   Properties args;
1560   const Properties *reply;
1561   reply = ndb_mgm_call(handle, getloglevel_reply, "get cluster loglevel", &args);
1562   CHECK_REPLY(handle, reply, NULL);
1563 
1564   for(int i=0; i < loglevel_count; i++) {
1565     reply->get(clusterlog_names[i], &loglevel[i]);
1566   }
1567   return loglevel;
1568 }
1569 
1570 extern "C"
1571 int
ndb_mgm_set_clusterlog_loglevel(NdbMgmHandle handle,int nodeId,enum ndb_mgm_event_category cat,int level,struct ndb_mgm_reply *)1572 ndb_mgm_set_clusterlog_loglevel(NdbMgmHandle handle, int nodeId,
1573 				enum ndb_mgm_event_category cat,
1574 				int level,
1575 				struct ndb_mgm_reply* /*reply*/)
1576 {
1577   SET_ERROR(handle, NDB_MGM_NO_ERROR,
1578 	    "Executing: ndb_mgm_set_clusterlog_loglevel");
1579   const ParserRow<ParserDummy> clusterlog_reply[] = {
1580     MGM_CMD("set cluster loglevel reply", NULL, ""),
1581     MGM_ARG("result", String, Mandatory, "Error message"),
1582     MGM_END()
1583   };
1584   CHECK_HANDLE(handle, -1);
1585   CHECK_CONNECTED(handle, -1);
1586 
1587   Properties args;
1588   args.put("node", nodeId);
1589   args.put("category", cat);
1590   args.put("level", level);
1591 
1592   const Properties *reply;
1593   reply = ndb_mgm_call(handle, clusterlog_reply,
1594 		       "set cluster loglevel", &args);
1595   CHECK_REPLY(handle, reply, -1);
1596 
1597   DBUG_ENTER("ndb_mgm_set_clusterlog_loglevel");
1598   DBUG_PRINT("enter",("node=%d, category=%d, level=%d", nodeId, cat, level));
1599 
1600   BaseString result;
1601   reply->get("result", result);
1602   if(strcmp(result.c_str(), "Ok") != 0) {
1603     SET_ERROR(handle, EINVAL, result.c_str());
1604     delete reply;
1605     DBUG_RETURN(-1);
1606   }
1607   delete reply;
1608   DBUG_RETURN(0);
1609 }
1610 
1611 extern "C"
1612 int
ndb_mgm_set_loglevel_node(NdbMgmHandle handle,int nodeId,enum ndb_mgm_event_category category,int level,struct ndb_mgm_reply *)1613 ndb_mgm_set_loglevel_node(NdbMgmHandle handle, int nodeId,
1614 			  enum ndb_mgm_event_category category,
1615 			  int level,
1616 			  struct ndb_mgm_reply* /*reply*/)
1617 {
1618   SET_ERROR(handle, NDB_MGM_NO_ERROR, "Executing: ndb_mgm_set_loglevel_node");
1619   const ParserRow<ParserDummy> loglevel_reply[] = {
1620     MGM_CMD("set loglevel reply", NULL, ""),
1621     MGM_ARG("result", String, Mandatory, "Error message"),
1622     MGM_END()
1623   };
1624   CHECK_HANDLE(handle, -1);
1625   CHECK_CONNECTED(handle, -1);
1626 
1627   Properties args;
1628   args.put("node", nodeId);
1629   args.put("category", category);
1630   args.put("level", level);
1631   const Properties *reply;
1632   reply = ndb_mgm_call(handle, loglevel_reply, "set loglevel", &args);
1633   CHECK_REPLY(handle, reply, -1);
1634 
1635   BaseString result;
1636   reply->get("result", result);
1637   if(strcmp(result.c_str(), "Ok") != 0) {
1638     SET_ERROR(handle, EINVAL, result.c_str());
1639     delete reply;
1640     return -1;
1641   }
1642 
1643   delete reply;
1644   return 0;
1645 }
1646 
1647 int
ndb_mgm_listen_event_internal(NdbMgmHandle handle,const int filter[],int parsable)1648 ndb_mgm_listen_event_internal(NdbMgmHandle handle, const int filter[],
1649 			      int parsable)
1650 {
1651   SET_ERROR(handle, NDB_MGM_NO_ERROR, "Executing: ndb_mgm_listen_event");
1652   const ParserRow<ParserDummy> stat_reply[] = {
1653     MGM_CMD("listen event", NULL, ""),
1654     MGM_ARG("result", Int, Mandatory, "Error message"),
1655     MGM_ARG("msg", String, Optional, "Error message"),
1656     MGM_END()
1657   };
1658   CHECK_HANDLE(handle, -1);
1659 
1660   const char *hostname= ndb_mgm_get_connected_host(handle);
1661   int port= ndb_mgm_get_connected_port(handle);
1662   SocketClient s(hostname, port);
1663   const NDB_SOCKET_TYPE sockfd = s.connect();
1664   if (sockfd == NDB_INVALID_SOCKET) {
1665     setError(handle, NDB_MGM_COULD_NOT_CONNECT_TO_SOCKET, __LINE__,
1666 	     "Unable to connect to");
1667     return -1;
1668   }
1669 
1670   Properties args;
1671 
1672   if (parsable)
1673     args.put("parsable", parsable);
1674   {
1675     BaseString tmp;
1676     for(int i = 0; filter[i] != 0; i += 2){
1677       tmp.appfmt("%d=%d ", filter[i+1], filter[i]);
1678     }
1679     args.put("filter", tmp.c_str());
1680   }
1681 
1682   int tmp = handle->socket;
1683   handle->socket = sockfd;
1684 
1685   const Properties *reply;
1686   reply = ndb_mgm_call(handle, stat_reply, "listen event", &args);
1687 
1688   handle->socket = tmp;
1689 
1690   if(reply == NULL) {
1691     close(sockfd);
1692     CHECK_REPLY(handle, reply, -1);
1693   }
1694   delete reply;
1695   return sockfd;
1696 }
1697 
1698 extern "C"
1699 int
ndb_mgm_listen_event(NdbMgmHandle handle,const int filter[])1700 ndb_mgm_listen_event(NdbMgmHandle handle, const int filter[])
1701 {
1702   return ndb_mgm_listen_event_internal(handle,filter,0);
1703 }
1704 
1705 extern "C"
1706 int
ndb_mgm_dump_state(NdbMgmHandle handle,int nodeId,const int * _args,int _num_args,struct ndb_mgm_reply *)1707 ndb_mgm_dump_state(NdbMgmHandle handle, int nodeId, const int * _args,
1708 		   int _num_args, struct ndb_mgm_reply* /* reply */)
1709 {
1710   SET_ERROR(handle, NDB_MGM_NO_ERROR, "Executing: ndb_mgm_dump_state");
1711   const ParserRow<ParserDummy> dump_state_reply[] = {
1712     MGM_CMD("dump state reply", NULL, ""),
1713     MGM_ARG("result", String, Mandatory, "Error message"),
1714     MGM_END()
1715   };
1716   CHECK_HANDLE(handle, -1);
1717   CHECK_CONNECTED(handle, -1);
1718 
1719   char buf[256];
1720   buf[0] = 0;
1721   for (int i = 0; i < _num_args; i++){
1722     unsigned n = strlen(buf);
1723     if (n + 20 > sizeof(buf)) {
1724       SET_ERROR(handle, NDB_MGM_USAGE_ERROR, "arguments too long");
1725       return -1;
1726     }
1727     sprintf(buf + n, "%s%d", i ? " " : "", _args[i]);
1728   }
1729 
1730   Properties args;
1731   args.put("node", nodeId);
1732   args.put("args", buf);
1733 
1734   const Properties *prop;
1735   prop = ndb_mgm_call(handle, dump_state_reply, "dump state", &args);
1736   CHECK_REPLY(handle, prop, -1);
1737 
1738   BaseString result;
1739   prop->get("result", result);
1740   if(strcmp(result.c_str(), "Ok") != 0) {
1741     SET_ERROR(handle, EINVAL, result.c_str());
1742     delete prop;
1743     return -1;
1744   }
1745 
1746   delete prop;
1747   return 0;
1748 }
1749 
1750 extern "C"
1751 int
ndb_mgm_start_signallog(NdbMgmHandle handle,int nodeId,struct ndb_mgm_reply * reply)1752 ndb_mgm_start_signallog(NdbMgmHandle handle, int nodeId,
1753 			struct ndb_mgm_reply* reply)
1754 {
1755   SET_ERROR(handle, NDB_MGM_NO_ERROR, "Executing: ndb_mgm_start_signallog");
1756   const ParserRow<ParserDummy> start_signallog_reply[] = {
1757     MGM_CMD("start signallog reply", NULL, ""),
1758     MGM_ARG("result", String, Mandatory, "Error message"),
1759     MGM_END()
1760   };
1761   int retval = -1;
1762   CHECK_HANDLE(handle, -1);
1763   CHECK_CONNECTED(handle, -1);
1764 
1765   Properties args;
1766   args.put("node", nodeId);
1767 
1768   const Properties *prop;
1769   prop = ndb_mgm_call(handle,
1770 		       start_signallog_reply,
1771 		       "start signallog",
1772 		       &args);
1773   CHECK_REPLY(handle, prop, -1);
1774 
1775   if(prop != NULL) {
1776     BaseString result;
1777     prop->get("result", result);
1778     if(strcmp(result.c_str(), "Ok") == 0) {
1779       retval = 0;
1780     } else {
1781       SET_ERROR(handle, EINVAL, result.c_str());
1782       retval = -1;
1783     }
1784     delete prop;
1785   }
1786 
1787   return retval;
1788 }
1789 
1790 extern "C"
1791 int
ndb_mgm_stop_signallog(NdbMgmHandle handle,int nodeId,struct ndb_mgm_reply * reply)1792 ndb_mgm_stop_signallog(NdbMgmHandle handle, int nodeId,
1793 		       struct ndb_mgm_reply* reply)
1794 {
1795   SET_ERROR(handle, NDB_MGM_NO_ERROR, "Executing: ndb_mgm_stop_signallog");
1796   const ParserRow<ParserDummy> stop_signallog_reply[] = {
1797     MGM_CMD("stop signallog reply", NULL, ""),
1798     MGM_ARG("result", String, Mandatory, "Error message"),
1799     MGM_END()
1800   };
1801   int retval = -1;
1802   CHECK_HANDLE(handle, -1);
1803   CHECK_CONNECTED(handle, -1);
1804 
1805   Properties args;
1806   args.put("node", nodeId);
1807 
1808   const Properties *prop;
1809   prop = ndb_mgm_call(handle, stop_signallog_reply, "stop signallog", &args);
1810   CHECK_REPLY(handle, prop, -1);
1811 
1812   if(prop != NULL) {
1813     BaseString result;
1814     prop->get("result", result);
1815     if(strcmp(result.c_str(), "Ok") == 0) {
1816       retval = 0;
1817     } else {
1818       SET_ERROR(handle, EINVAL, result.c_str());
1819       retval = -1;
1820     }
1821     delete prop;
1822   }
1823 
1824   return retval;
1825 }
1826 
1827 struct ndb_mgm_signal_log_modes
1828 {
1829   const char* name;
1830   enum ndb_mgm_signal_log_mode mode;
1831 };
1832 
1833 extern "C"
1834 int
ndb_mgm_log_signals(NdbMgmHandle handle,int nodeId,enum ndb_mgm_signal_log_mode mode,const char * blockNames,struct ndb_mgm_reply * reply)1835 ndb_mgm_log_signals(NdbMgmHandle handle, int nodeId,
1836 		    enum ndb_mgm_signal_log_mode mode,
1837 		    const char* blockNames,
1838 		    struct ndb_mgm_reply* reply)
1839 {
1840   SET_ERROR(handle, NDB_MGM_NO_ERROR, "Executing: ndb_mgm_log_signals");
1841   const ParserRow<ParserDummy> stop_signallog_reply[] = {
1842     MGM_CMD("log signals reply", NULL, ""),
1843     MGM_ARG("result", String, Mandatory, "Error message"),
1844     MGM_END()
1845   };
1846   int retval = -1;
1847   CHECK_HANDLE(handle, -1);
1848   CHECK_CONNECTED(handle, -1);
1849 
1850   Properties args;
1851   args.put("node", nodeId);
1852   args.put("blocks", blockNames);
1853 
1854   switch(mode) {
1855   case NDB_MGM_SIGNAL_LOG_MODE_IN:
1856     args.put("in", (Uint32)1);
1857     args.put("out", (Uint32)0);
1858     break;
1859   case NDB_MGM_SIGNAL_LOG_MODE_OUT:
1860     args.put("in", (Uint32)0);
1861     args.put("out", (Uint32)1);
1862     break;
1863   case NDB_MGM_SIGNAL_LOG_MODE_INOUT:
1864     args.put("in", (Uint32)1);
1865     args.put("out", (Uint32)1);
1866     break;
1867   case NDB_MGM_SIGNAL_LOG_MODE_OFF:
1868     args.put("in", (Uint32)0);
1869     args.put("out", (Uint32)0);
1870     break;
1871   }
1872 
1873   const Properties *prop;
1874   prop = ndb_mgm_call(handle, stop_signallog_reply, "log signals", &args);
1875   CHECK_REPLY(handle, prop, -1);
1876 
1877   if(prop != NULL) {
1878     BaseString result;
1879     prop->get("result", result);
1880     if(strcmp(result.c_str(), "Ok") == 0) {
1881       retval = 0;
1882     } else {
1883       SET_ERROR(handle, EINVAL, result.c_str());
1884       retval = -1;
1885     }
1886     delete prop;
1887   }
1888 
1889   return retval;
1890 }
1891 
1892 extern "C"
1893 int
ndb_mgm_set_trace(NdbMgmHandle handle,int nodeId,int traceNumber,struct ndb_mgm_reply * reply)1894 ndb_mgm_set_trace(NdbMgmHandle handle, int nodeId, int traceNumber,
1895 		  struct ndb_mgm_reply* reply)
1896 {
1897   SET_ERROR(handle, NDB_MGM_NO_ERROR, "Executing: ndb_mgm_set_trace");
1898   const ParserRow<ParserDummy> set_trace_reply[] = {
1899     MGM_CMD("set trace reply", NULL, ""),
1900     MGM_ARG("result", String, Mandatory, "Error message"),
1901     MGM_END()
1902   };
1903   int retval = -1;
1904   CHECK_HANDLE(handle, -1);
1905   CHECK_CONNECTED(handle, -1);
1906 
1907   Properties args;
1908   args.put("node", nodeId);
1909   args.put("trace", traceNumber);
1910 
1911   const Properties *prop;
1912   prop = ndb_mgm_call(handle, set_trace_reply, "set trace", &args);
1913   CHECK_REPLY(handle, prop, -1);
1914 
1915   if(prop != NULL) {
1916     BaseString result;
1917     prop->get("result", result);
1918     if(strcmp(result.c_str(), "Ok") == 0) {
1919       retval = 0;
1920     } else {
1921       SET_ERROR(handle, EINVAL, result.c_str());
1922       retval = -1;
1923     }
1924     delete prop;
1925   }
1926 
1927   return retval;
1928 }
1929 
1930 extern "C"
1931 int
ndb_mgm_insert_error(NdbMgmHandle handle,int nodeId,int errorCode,struct ndb_mgm_reply * reply)1932 ndb_mgm_insert_error(NdbMgmHandle handle, int nodeId, int errorCode,
1933 		     struct ndb_mgm_reply* reply)
1934 {
1935   SET_ERROR(handle, NDB_MGM_NO_ERROR, "Executing: ndb_mgm_insert_error");
1936   const ParserRow<ParserDummy> insert_error_reply[] = {
1937     MGM_CMD("insert error reply", NULL, ""),
1938     MGM_ARG("result", String, Mandatory, "Error message"),
1939     MGM_END()
1940   };
1941   int retval = -1;
1942   CHECK_HANDLE(handle, -1);
1943   CHECK_CONNECTED(handle, -1);
1944 
1945   Properties args;
1946   args.put("node", nodeId);
1947   args.put("error", errorCode);
1948 
1949   const Properties *prop;
1950   prop = ndb_mgm_call(handle, insert_error_reply, "insert error", &args);
1951   CHECK_REPLY(handle, prop, -1);
1952 
1953   if(prop != NULL) {
1954     BaseString result;
1955     prop->get("result", result);
1956     if(strcmp(result.c_str(), "Ok") == 0) {
1957       retval = 0;
1958     } else {
1959       SET_ERROR(handle, EINVAL, result.c_str());
1960       retval = -1;
1961     }
1962     delete prop;
1963   }
1964 
1965   return retval;
1966 }
1967 
1968 extern "C"
1969 int
ndb_mgm_start(NdbMgmHandle handle,int no_of_nodes,const int * node_list)1970 ndb_mgm_start(NdbMgmHandle handle, int no_of_nodes, const int * node_list)
1971 {
1972   SET_ERROR(handle, NDB_MGM_NO_ERROR, "Executing: ndb_mgm_start");
1973   const ParserRow<ParserDummy> start_reply[] = {
1974     MGM_CMD("start reply", NULL, ""),
1975     MGM_ARG("started", Int, Optional, "No of started nodes"),
1976     MGM_ARG("result", String, Mandatory, "Error message"),
1977     MGM_END()
1978   };
1979   int started = 0;
1980   CHECK_HANDLE(handle, -1);
1981   CHECK_CONNECTED(handle, -1);
1982 
1983   if(no_of_nodes < 0){
1984     SET_ERROR(handle, EINVAL, "");
1985     return -1;
1986   }
1987 
1988   if(no_of_nodes == 0){
1989     Properties args;
1990     const Properties *reply;
1991     reply = ndb_mgm_call(handle, start_reply, "start all", &args);
1992     CHECK_REPLY(handle, reply, -1);
1993 
1994     Uint32 count = 0;
1995     if(!reply->get("started", &count)){
1996       delete reply;
1997       return -1;
1998     }
1999     delete reply;
2000     return count;
2001   }
2002 
2003   for(int node = 0; node < no_of_nodes; node++) {
2004     Properties args;
2005     args.put("node", node_list[node]);
2006 
2007     const Properties *reply;
2008     reply = ndb_mgm_call(handle, start_reply, "start", &args);
2009 
2010     if(reply != NULL) {
2011       BaseString result;
2012       reply->get("result", result);
2013       if(strcmp(result.c_str(), "Ok") == 0) {
2014 	started++;
2015       } else {
2016 	SET_ERROR(handle, EINVAL, result.c_str());
2017 	delete reply;
2018 	return -1;
2019       }
2020     }
2021     delete reply;
2022   }
2023 
2024   return started;
2025 }
2026 
2027 /*****************************************************************************
2028  * Backup
2029  *****************************************************************************/
2030 extern "C"
2031 int
ndb_mgm_start_backup(NdbMgmHandle handle,int wait_completed,unsigned int * _backup_id,struct ndb_mgm_reply *)2032 ndb_mgm_start_backup(NdbMgmHandle handle, int wait_completed,
2033 		     unsigned int* _backup_id,
2034 		     struct ndb_mgm_reply* /*reply*/)
2035 {
2036   SET_ERROR(handle, NDB_MGM_NO_ERROR, "Executing: ndb_mgm_start_backup");
2037   const ParserRow<ParserDummy> start_backup_reply[] = {
2038     MGM_CMD("start backup reply", NULL, ""),
2039     MGM_ARG("result", String, Mandatory, "Error message"),
2040     MGM_ARG("id", Int, Optional, "Id of the started backup"),
2041     MGM_END()
2042   };
2043   CHECK_HANDLE(handle, -1);
2044   CHECK_CONNECTED(handle, -1);
2045 
2046   Properties args;
2047   args.put("completed", wait_completed);
2048   const Properties *reply;
2049   { // start backup can take some time, set timeout high
2050     Uint64 old_timeout= handle->timeout;
2051     if (wait_completed == 2)
2052       handle->timeout= 48*60*60*1000; // 48 hours
2053     else if (wait_completed == 1)
2054       handle->timeout= 10*60*1000; // 10 minutes
2055     reply = ndb_mgm_call(handle, start_backup_reply, "start backup", &args);
2056     handle->timeout= old_timeout;
2057   }
2058   CHECK_REPLY(handle, reply, -1);
2059 
2060   BaseString result;
2061   reply->get("result", result);
2062   reply->get("id", _backup_id);
2063   if(strcmp(result.c_str(), "Ok") != 0) {
2064     SET_ERROR(handle, NDB_MGM_COULD_NOT_START_BACKUP, result.c_str());
2065     delete reply;
2066     return -1;
2067   }
2068 
2069   delete reply;
2070   return 0;
2071 }
2072 
2073 extern "C"
2074 int
ndb_mgm_abort_backup(NdbMgmHandle handle,unsigned int backupId,struct ndb_mgm_reply *)2075 ndb_mgm_abort_backup(NdbMgmHandle handle, unsigned int backupId,
2076 		     struct ndb_mgm_reply* /*reply*/)
2077 {
2078   SET_ERROR(handle, NDB_MGM_NO_ERROR, "Executing: ndb_mgm_abort_backup");
2079   const ParserRow<ParserDummy> stop_backup_reply[] = {
2080     MGM_CMD("abort backup reply", NULL, ""),
2081     MGM_ARG("result", String, Mandatory, "Error message"),
2082     MGM_END()
2083   };
2084   CHECK_HANDLE(handle, -1);
2085   CHECK_CONNECTED(handle, -1);
2086 
2087   Properties args;
2088   args.put("id", backupId);
2089 
2090   const Properties *prop;
2091   prop = ndb_mgm_call(handle, stop_backup_reply, "abort backup", &args);
2092   CHECK_REPLY(handle, prop, -1);
2093 
2094   const char * buf;
2095   prop->get("result", &buf);
2096   if(strcmp(buf,"Ok")!=0) {
2097     SET_ERROR(handle, NDB_MGM_COULD_NOT_ABORT_BACKUP, buf);
2098     delete prop;
2099     return -1;
2100   }
2101 
2102   delete prop;
2103   return 0;
2104 }
2105 
2106 extern "C"
2107 struct ndb_mgm_configuration *
ndb_mgm_get_configuration(NdbMgmHandle handle,unsigned int version)2108 ndb_mgm_get_configuration(NdbMgmHandle handle, unsigned int version) {
2109   SET_ERROR(handle, NDB_MGM_NO_ERROR, "Executing: ndb_mgm_get_configuration");
2110   CHECK_HANDLE(handle, 0);
2111   CHECK_CONNECTED(handle, 0);
2112 
2113   Properties args;
2114   args.put("version", version);
2115 
2116   const ParserRow<ParserDummy> reply[] = {
2117     MGM_CMD("get config reply", NULL, ""),
2118     MGM_ARG("result", String, Mandatory, "Error message"),
2119     MGM_ARG("Content-Length", Int, Optional, "Content length in bytes"),
2120     MGM_ARG("Content-Type", String, Optional, "Type (octet-stream)"),
2121     MGM_ARG("Content-Transfer-Encoding", String, Optional, "Encoding(base64)"),
2122     MGM_END()
2123   };
2124 
2125   const Properties *prop;
2126   prop = ndb_mgm_call(handle, reply, "get config", &args);
2127   CHECK_REPLY(handle, prop, 0);
2128 
2129   do {
2130     const char * buf;
2131     if(!prop->get("result", &buf) || strcmp(buf, "Ok") != 0){
2132       fprintf(handle->errstream, "ERROR Message: %s\n\n", buf);
2133       break;
2134     }
2135 
2136     buf = "<Unspecified>";
2137     if(!prop->get("Content-Type", &buf) ||
2138        strcmp(buf, "ndbconfig/octet-stream") != 0){
2139       fprintf(handle->errstream, "Unhandled response type: %s\n", buf);
2140       break;
2141     }
2142 
2143     buf = "<Unspecified>";
2144     if(!prop->get("Content-Transfer-Encoding", &buf)
2145        || strcmp(buf, "base64") != 0){
2146       fprintf(handle->errstream, "Unhandled encoding: %s\n", buf);
2147       break;
2148     }
2149 
2150     buf = "<Content-Length Unspecified>";
2151     Uint32 len = 0;
2152     if(!prop->get("Content-Length", &len)){
2153       fprintf(handle->errstream, "Invalid response: %s\n\n", buf);
2154       break;
2155     }
2156 
2157     len += 1; // Trailing \n
2158 
2159     char* buf64 = new char[len];
2160     int read = 0;
2161     size_t start = 0;
2162     do {
2163       if((read = read_socket(handle->socket, handle->timeout,
2164 			     &buf64[start], len-start)) < 1){
2165 	delete[] buf64;
2166 	buf64 = 0;
2167         if(read==0)
2168           SET_ERROR(handle, ETIMEDOUT, "Timeout reading packed config");
2169         else
2170           SET_ERROR(handle, errno, "Error reading packed config");
2171         ndb_mgm_disconnect_quiet(handle);
2172 	break;
2173       }
2174       start += read;
2175     } while(start < len);
2176     if(buf64 == 0)
2177       break;
2178 
2179     void *tmp_data = malloc(base64_needed_decoded_length((size_t) (len - 1)));
2180     const int res = base64_decode(buf64, len-1, tmp_data, NULL);
2181     delete[] buf64;
2182     UtilBuffer tmp;
2183     tmp.append((void *) tmp_data, res);
2184     free(tmp_data);
2185     if (res < 0)
2186     {
2187       fprintf(handle->errstream, "Failed to decode buffer\n");
2188       break;
2189     }
2190 
2191     ConfigValuesFactory cvf;
2192     const int res2 = cvf.unpack(tmp);
2193     if(!res2){
2194       fprintf(handle->errstream, "Failed to unpack buffer\n");
2195       break;
2196     }
2197 
2198     delete prop;
2199     return (ndb_mgm_configuration*)cvf.getConfigValues();
2200   } while(0);
2201 
2202   delete prop;
2203   return 0;
2204 }
2205 
2206 extern "C"
2207 void
ndb_mgm_destroy_configuration(struct ndb_mgm_configuration * cfg)2208 ndb_mgm_destroy_configuration(struct ndb_mgm_configuration *cfg)
2209 {
2210   if (cfg) {
2211     ((ConfigValues *)cfg)->~ConfigValues();
2212     free((void *)cfg);
2213   }
2214 }
2215 
2216 extern "C"
2217 int
ndb_mgm_set_configuration_nodeid(NdbMgmHandle handle,int nodeid)2218 ndb_mgm_set_configuration_nodeid(NdbMgmHandle handle, int nodeid)
2219 {
2220   CHECK_HANDLE(handle, -1);
2221   handle->cfg._ownNodeId= nodeid;
2222   return 0;
2223 }
2224 
2225 extern "C"
2226 int
ndb_mgm_get_configuration_nodeid(NdbMgmHandle handle)2227 ndb_mgm_get_configuration_nodeid(NdbMgmHandle handle)
2228 {
2229   CHECK_HANDLE(handle, 0);
2230   return handle->cfg._ownNodeId;
2231 }
2232 
2233 extern "C"
ndb_mgm_get_connected_port(NdbMgmHandle handle)2234 int ndb_mgm_get_connected_port(NdbMgmHandle handle)
2235 {
2236   if (handle->cfg_i >= 0)
2237     return handle->cfg.ids[handle->cfg_i].port;
2238   else
2239     return 0;
2240 }
2241 
2242 extern "C"
ndb_mgm_get_connected_host(NdbMgmHandle handle)2243 const char *ndb_mgm_get_connected_host(NdbMgmHandle handle)
2244 {
2245   if (handle->cfg_i >= 0)
2246     return handle->cfg.ids[handle->cfg_i].name.c_str();
2247   else
2248     return 0;
2249 }
2250 
2251 extern "C"
ndb_mgm_get_connectstring(NdbMgmHandle handle,char * buf,int buf_sz)2252 const char *ndb_mgm_get_connectstring(NdbMgmHandle handle, char *buf, int buf_sz)
2253 {
2254   return handle->cfg.makeConnectString(buf,buf_sz);
2255 }
2256 
2257 extern "C"
2258 int
ndb_mgm_alloc_nodeid(NdbMgmHandle handle,unsigned int version,int nodetype,int log_event)2259 ndb_mgm_alloc_nodeid(NdbMgmHandle handle, unsigned int version, int nodetype,
2260                      int log_event)
2261 {
2262   CHECK_HANDLE(handle, 0);
2263   CHECK_CONNECTED(handle, 0);
2264   union { long l; char c[sizeof(long)]; } endian_check;
2265 
2266   endian_check.l = 1;
2267 
2268   int nodeid= handle->cfg._ownNodeId;
2269 
2270   Properties args;
2271   args.put("version", version);
2272   args.put("nodetype", nodetype);
2273   args.put("nodeid", nodeid);
2274   args.put("user", "mysqld");
2275   args.put("password", "mysqld");
2276   args.put("public key", "a public key");
2277   args.put("endian", (endian_check.c[sizeof(long)-1])?"big":"little");
2278   if (handle->m_name)
2279     args.put("name", handle->m_name);
2280   args.put("log_event", log_event);
2281 
2282   const ParserRow<ParserDummy> reply[]= {
2283     MGM_CMD("get nodeid reply", NULL, ""),
2284       MGM_ARG("error_code", Int, Optional, "Error code"),
2285       MGM_ARG("nodeid", Int, Optional, "Error message"),
2286       MGM_ARG("result", String, Mandatory, "Error message"),
2287     MGM_END()
2288   };
2289 
2290   const Properties *prop;
2291   prop= ndb_mgm_call(handle, reply, "get nodeid", &args);
2292   CHECK_REPLY(handle, prop, -1);
2293 
2294   nodeid= -1;
2295   do {
2296     const char * buf;
2297     if (!prop->get("result", &buf) || strcmp(buf, "Ok") != 0)
2298     {
2299       const char *hostname= ndb_mgm_get_connected_host(handle);
2300       unsigned port=  ndb_mgm_get_connected_port(handle);
2301       BaseString err;
2302       Uint32 error_code= NDB_MGM_ALLOCID_ERROR;
2303       err.assfmt("Could not alloc node id at %s port %d: %s",
2304 		 hostname, port, buf);
2305       prop->get("error_code", &error_code);
2306       setError(handle, error_code, __LINE__, err.c_str());
2307       break;
2308     }
2309     Uint32 _nodeid;
2310     if(!prop->get("nodeid", &_nodeid) != 0){
2311       fprintf(handle->errstream, "ERROR Message: <nodeid Unspecified>\n");
2312       break;
2313     }
2314     nodeid= _nodeid;
2315   }while(0);
2316 
2317   delete prop;
2318   return nodeid;
2319 }
2320 
2321 extern "C"
2322 int
ndb_mgm_set_int_parameter(NdbMgmHandle handle,int node,int param,unsigned value,struct ndb_mgm_reply *)2323 ndb_mgm_set_int_parameter(NdbMgmHandle handle,
2324 			  int node,
2325 			  int param,
2326 			  unsigned value,
2327 			  struct ndb_mgm_reply*){
2328   CHECK_HANDLE(handle, 0);
2329   CHECK_CONNECTED(handle, 0);
2330 
2331   Properties args;
2332   args.put("node", node);
2333   args.put("param", param);
2334   args.put("value", value);
2335 
2336   const ParserRow<ParserDummy> reply[]= {
2337     MGM_CMD("set parameter reply", NULL, ""),
2338     MGM_ARG("result", String, Mandatory, "Error message"),
2339     MGM_END()
2340   };
2341 
2342   const Properties *prop;
2343   prop= ndb_mgm_call(handle, reply, "set parameter", &args);
2344   CHECK_REPLY(handle, prop, -1);
2345 
2346   int res= -1;
2347   do {
2348     const char * buf;
2349     if(!prop->get("result", &buf) || strcmp(buf, "Ok") != 0){
2350       fprintf(handle->errstream, "ERROR Message: %s\n", buf);
2351       break;
2352     }
2353     res= 0;
2354   } while(0);
2355 
2356   delete prop;
2357   return res;
2358 }
2359 
2360 extern "C"
2361 int
ndb_mgm_set_int64_parameter(NdbMgmHandle handle,int node,int param,unsigned long long value,struct ndb_mgm_reply *)2362 ndb_mgm_set_int64_parameter(NdbMgmHandle handle,
2363 			    int node,
2364 			    int param,
2365 			    unsigned long long value,
2366 			    struct ndb_mgm_reply*){
2367   CHECK_HANDLE(handle, 0);
2368   CHECK_CONNECTED(handle, 0);
2369 
2370   Properties args;
2371   args.put("node", node);
2372   args.put("param", param);
2373   args.put("value", value);
2374 
2375   const ParserRow<ParserDummy> reply[]= {
2376     MGM_CMD("set parameter reply", NULL, ""),
2377     MGM_ARG("result", String, Mandatory, "Error message"),
2378     MGM_END()
2379   };
2380 
2381   const Properties *prop;
2382   prop= ndb_mgm_call(handle, reply, "set parameter", &args);
2383   CHECK_REPLY(handle, prop, 0);
2384 
2385   if(prop == NULL) {
2386     SET_ERROR(handle, EIO, "Unable set parameter");
2387     return -1;
2388   }
2389 
2390   int res= -1;
2391   do {
2392     const char * buf;
2393     if(!prop->get("result", &buf) || strcmp(buf, "Ok") != 0){
2394       fprintf(handle->errstream, "ERROR Message: %s\n", buf);
2395       break;
2396     }
2397     res= 0;
2398   } while(0);
2399 
2400   delete prop;
2401   return res;
2402 }
2403 
2404 extern "C"
2405 int
ndb_mgm_set_string_parameter(NdbMgmHandle handle,int node,int param,const char * value,struct ndb_mgm_reply *)2406 ndb_mgm_set_string_parameter(NdbMgmHandle handle,
2407 			     int node,
2408 			     int param,
2409 			     const char * value,
2410 			     struct ndb_mgm_reply*){
2411   CHECK_HANDLE(handle, 0);
2412   CHECK_CONNECTED(handle, 0);
2413 
2414   Properties args;
2415   args.put("node", node);
2416   args.put("parameter", param);
2417   args.put("value", value);
2418 
2419   const ParserRow<ParserDummy> reply[]= {
2420     MGM_CMD("set parameter reply", NULL, ""),
2421     MGM_ARG("result", String, Mandatory, "Error message"),
2422     MGM_END()
2423   };
2424 
2425   const Properties *prop;
2426   prop= ndb_mgm_call(handle, reply, "set parameter", &args);
2427   CHECK_REPLY(handle, prop, 0);
2428 
2429   if(prop == NULL) {
2430     SET_ERROR(handle, EIO, "Unable set parameter");
2431     return -1;
2432   }
2433 
2434   int res= -1;
2435   do {
2436     const char * buf;
2437     if(!prop->get("result", &buf) || strcmp(buf, "Ok") != 0){
2438       fprintf(handle->errstream, "ERROR Message: %s\n", buf);
2439       break;
2440     }
2441     res= 0;
2442   } while(0);
2443 
2444   delete prop;
2445   return res;
2446 }
2447 
2448 extern "C"
2449 int
ndb_mgm_purge_stale_sessions(NdbMgmHandle handle,char ** purged)2450 ndb_mgm_purge_stale_sessions(NdbMgmHandle handle, char **purged){
2451   CHECK_HANDLE(handle, 0);
2452   CHECK_CONNECTED(handle, 0);
2453 
2454   Properties args;
2455 
2456   const ParserRow<ParserDummy> reply[]= {
2457     MGM_CMD("purge stale sessions reply", NULL, ""),
2458     MGM_ARG("purged", String, Optional, ""),
2459     MGM_ARG("result", String, Mandatory, "Error message"),
2460     MGM_END()
2461   };
2462 
2463   const Properties *prop;
2464   prop= ndb_mgm_call(handle, reply, "purge stale sessions", &args);
2465   CHECK_REPLY(handle, prop, -1);
2466 
2467   if(prop == NULL) {
2468     SET_ERROR(handle, EIO, "Unable to purge stale sessions");
2469     return -1;
2470   }
2471 
2472   int res= -1;
2473   do {
2474     const char * buf;
2475     if(!prop->get("result", &buf) || strcmp(buf, "Ok") != 0){
2476       fprintf(handle->errstream, "ERROR Message: %s\n", buf);
2477       break;
2478     }
2479     if (purged) {
2480       if (prop->get("purged", &buf))
2481 	*purged= strdup(buf);
2482       else
2483 	*purged= 0;
2484     }
2485     res= 0;
2486   } while(0);
2487   delete prop;
2488   return res;
2489 }
2490 
2491 extern "C"
2492 int
ndb_mgm_check_connection(NdbMgmHandle handle)2493 ndb_mgm_check_connection(NdbMgmHandle handle){
2494   CHECK_HANDLE(handle, 0);
2495   CHECK_CONNECTED(handle, 0);
2496   SocketOutputStream out(handle->socket, handle->timeout);
2497   SocketInputStream in(handle->socket, handle->timeout);
2498   char buf[32];
2499   if (out.println("check connection"))
2500     goto ndb_mgm_check_connection_error;
2501 
2502   if (out.println(""))
2503     goto ndb_mgm_check_connection_error;
2504 
2505   in.gets(buf, sizeof(buf));
2506   if(strcmp("check connection reply\n", buf))
2507     goto ndb_mgm_check_connection_error;
2508 
2509   in.gets(buf, sizeof(buf));
2510   if(strcmp("result: Ok\n", buf))
2511     goto ndb_mgm_check_connection_error;
2512 
2513   in.gets(buf, sizeof(buf));
2514   if(strcmp("\n", buf))
2515     goto ndb_mgm_check_connection_error;
2516 
2517   return 0;
2518 
2519 ndb_mgm_check_connection_error:
2520   ndb_mgm_disconnect(handle);
2521   return -1;
2522 }
2523 
2524 extern "C"
2525 int
ndb_mgm_set_connection_int_parameter(NdbMgmHandle handle,int node1,int node2,int param,int value,struct ndb_mgm_reply * mgmreply)2526 ndb_mgm_set_connection_int_parameter(NdbMgmHandle handle,
2527 				     int node1,
2528 				     int node2,
2529 				     int param,
2530 				     int value,
2531 				     struct ndb_mgm_reply* mgmreply){
2532   CHECK_HANDLE(handle, 0);
2533   CHECK_CONNECTED(handle, 0);
2534   DBUG_ENTER("ndb_mgm_set_connection_int_parameter");
2535 
2536   Properties args;
2537   args.put("node1", node1);
2538   args.put("node2", node2);
2539   args.put("param", param);
2540   args.put("value", (Uint32)value);
2541 
2542   const ParserRow<ParserDummy> reply[]= {
2543     MGM_CMD("set connection parameter reply", NULL, ""),
2544     MGM_ARG("message", String, Mandatory, "Error Message"),
2545     MGM_ARG("result", String, Mandatory, "Status Result"),
2546     MGM_END()
2547   };
2548 
2549   const Properties *prop;
2550   prop= ndb_mgm_call(handle, reply, "set connection parameter", &args);
2551   DBUG_CHECK_REPLY(handle, prop, -1);
2552 
2553   int res= -1;
2554   do {
2555     const char * buf;
2556     if(!prop->get("result", &buf) || strcmp(buf, "Ok") != 0){
2557       fprintf(handle->errstream, "ERROR Message: %s\n", buf);
2558       break;
2559     }
2560     res= 0;
2561   } while(0);
2562 
2563   delete prop;
2564   DBUG_RETURN(res);
2565 }
2566 
2567 extern "C"
2568 int
ndb_mgm_get_connection_int_parameter(NdbMgmHandle handle,int node1,int node2,int param,int * value,struct ndb_mgm_reply * mgmreply)2569 ndb_mgm_get_connection_int_parameter(NdbMgmHandle handle,
2570 				     int node1,
2571 				     int node2,
2572 				     int param,
2573 				     int *value,
2574 				     struct ndb_mgm_reply* mgmreply){
2575   CHECK_HANDLE(handle, -1);
2576   CHECK_CONNECTED(handle, -2);
2577   DBUG_ENTER("ndb_mgm_get_connection_int_parameter");
2578 
2579   Properties args;
2580   args.put("node1", node1);
2581   args.put("node2", node2);
2582   args.put("param", param);
2583 
2584   const ParserRow<ParserDummy> reply[]= {
2585     MGM_CMD("get connection parameter reply", NULL, ""),
2586     MGM_ARG("value", Int, Mandatory, "Current Value"),
2587     MGM_ARG("result", String, Mandatory, "Result"),
2588     MGM_END()
2589   };
2590 
2591   const Properties *prop;
2592   prop = ndb_mgm_call(handle, reply, "get connection parameter", &args);
2593   DBUG_CHECK_REPLY(handle, prop, -3);
2594 
2595   int res= -1;
2596   do {
2597     const char * buf;
2598     if(!prop->get("result", &buf) || strcmp(buf, "Ok") != 0){
2599       fprintf(handle->errstream, "ERROR Message: %s\n", buf);
2600       break;
2601     }
2602     res= 0;
2603   } while(0);
2604 
2605   if(!prop->get("value",(Uint32*)value)){
2606     fprintf(handle->errstream, "Unable to get value\n");
2607     res = -4;
2608   }
2609 
2610   delete prop;
2611   DBUG_RETURN(res);
2612 }
2613 
2614 extern "C"
2615 NDB_SOCKET_TYPE
ndb_mgm_convert_to_transporter(NdbMgmHandle * handle)2616 ndb_mgm_convert_to_transporter(NdbMgmHandle *handle)
2617 {
2618   NDB_SOCKET_TYPE s;
2619 
2620   CHECK_HANDLE((*handle), NDB_INVALID_SOCKET);
2621   CHECK_CONNECTED((*handle), NDB_INVALID_SOCKET);
2622 
2623   (*handle)->connected= 0;   // we pretend we're disconnected
2624   s= (*handle)->socket;
2625 
2626   SocketOutputStream s_output(s, (*handle)->timeout);
2627   s_output.println("transporter connect");
2628   s_output.println("");
2629 
2630   ndb_mgm_destroy_handle(handle); // set connected=0, so won't disconnect
2631 
2632   return s;
2633 }
2634 
2635 extern "C"
2636 Uint32
ndb_mgm_get_mgmd_nodeid(NdbMgmHandle handle)2637 ndb_mgm_get_mgmd_nodeid(NdbMgmHandle handle)
2638 {
2639   Uint32 nodeid=0;
2640 
2641   CHECK_HANDLE(handle, 0);
2642   CHECK_CONNECTED(handle, 0);
2643   DBUG_ENTER("ndb_mgm_get_mgmd_nodeid");
2644 
2645   Properties args;
2646 
2647   const ParserRow<ParserDummy> reply[]= {
2648     MGM_CMD("get mgmd nodeid reply", NULL, ""),
2649     MGM_ARG("nodeid", Int, Mandatory, "Node ID"),
2650     MGM_END()
2651   };
2652 
2653   const Properties *prop;
2654   prop = ndb_mgm_call(handle, reply, "get mgmd nodeid", &args);
2655   DBUG_CHECK_REPLY(handle, prop, 0);
2656 
2657   if(!prop->get("nodeid",&nodeid)){
2658     fprintf(handle->errstream, "Unable to get value\n");
2659     return 0;
2660   }
2661 
2662   delete prop;
2663   DBUG_RETURN(nodeid);
2664 }
2665 
2666 extern "C"
ndb_mgm_report_event(NdbMgmHandle handle,Uint32 * data,Uint32 length)2667 int ndb_mgm_report_event(NdbMgmHandle handle, Uint32 *data, Uint32 length)
2668 {
2669   CHECK_HANDLE(handle, 0);
2670   CHECK_CONNECTED(handle, 0);
2671   DBUG_ENTER("ndb_mgm_report_event");
2672 
2673   Properties args;
2674   args.put("length", length);
2675   BaseString data_string;
2676 
2677   for (int i = 0; i < (int) length; i++)
2678     data_string.appfmt(" %lu", (ulong) data[i]);
2679 
2680   args.put("data", data_string.c_str());
2681 
2682   const ParserRow<ParserDummy> reply[]= {
2683     MGM_CMD("report event reply", NULL, ""),
2684     MGM_ARG("result", String, Mandatory, "Result"),
2685     MGM_END()
2686   };
2687 
2688   const Properties *prop;
2689   prop = ndb_mgm_call(handle, reply, "report event", &args);
2690   DBUG_CHECK_REPLY(handle, prop, -1);
2691 
2692   DBUG_RETURN(0);
2693 }
2694 
2695 extern "C"
ndb_mgm_end_session(NdbMgmHandle handle)2696 int ndb_mgm_end_session(NdbMgmHandle handle)
2697 {
2698   CHECK_HANDLE(handle, 0);
2699   CHECK_CONNECTED(handle, 0);
2700   DBUG_ENTER("ndb_mgm_end_session");
2701 
2702   SocketOutputStream s_output(handle->socket, handle->timeout);
2703   s_output.println("end session");
2704   s_output.println("");
2705 
2706   SocketInputStream in(handle->socket, handle->timeout);
2707   char buf[32];
2708   in.gets(buf, sizeof(buf));
2709   CHECK_TIMEDOUT_RET(handle, in, s_output, -1);
2710 
2711   DBUG_RETURN(0);
2712 }
2713 
2714 extern "C"
ndb_mgm_get_version(NdbMgmHandle handle,int * major,int * minor,int * build,int len,char * str)2715 int ndb_mgm_get_version(NdbMgmHandle handle,
2716                         int *major, int *minor, int *build, int len, char* str)
2717 {
2718   DBUG_ENTER("ndb_mgm_get_version");
2719   CHECK_HANDLE(handle, 0);
2720   CHECK_CONNECTED(handle, 0);
2721 
2722   Properties args;
2723 
2724   const ParserRow<ParserDummy> reply[]= {
2725     MGM_CMD("version", NULL, ""),
2726     MGM_ARG("id", Int, Mandatory, "ID"),
2727     MGM_ARG("major", Int, Mandatory, "Major"),
2728     MGM_ARG("minor", Int, Mandatory, "Minor"),
2729     MGM_ARG("string", String, Mandatory, "String"),
2730     MGM_END()
2731   };
2732 
2733   const Properties *prop;
2734   prop = ndb_mgm_call(handle, reply, "get version", &args);
2735   CHECK_REPLY(handle, prop, 0);
2736 
2737   Uint32 id;
2738   if(!prop->get("id",&id)){
2739     fprintf(handle->errstream, "Unable to get value\n");
2740     return 0;
2741   }
2742   *build= getBuild(id);
2743 
2744   if(!prop->get("major",(Uint32*)major)){
2745     fprintf(handle->errstream, "Unable to get value\n");
2746     return 0;
2747   }
2748 
2749   if(!prop->get("minor",(Uint32*)minor)){
2750     fprintf(handle->errstream, "Unable to get value\n");
2751     return 0;
2752   }
2753 
2754   BaseString result;
2755   if(!prop->get("string", result)){
2756     fprintf(handle->errstream, "Unable to get value\n");
2757     return 0;
2758   }
2759 
2760   strncpy(str, result.c_str(), len);
2761 
2762   delete prop;
2763   DBUG_RETURN(1);
2764 }
2765 
2766 extern "C"
2767 Uint64
ndb_mgm_get_session_id(NdbMgmHandle handle)2768 ndb_mgm_get_session_id(NdbMgmHandle handle)
2769 {
2770   Uint64 session_id=0;
2771 
2772   DBUG_ENTER("ndb_mgm_get_session_id");
2773   CHECK_HANDLE(handle, 0);
2774   CHECK_CONNECTED(handle, 0);
2775 
2776   Properties args;
2777 
2778   const ParserRow<ParserDummy> reply[]= {
2779     MGM_CMD("get session id reply", NULL, ""),
2780     MGM_ARG("id", Int, Mandatory, "Node ID"),
2781     MGM_END()
2782   };
2783 
2784   const Properties *prop;
2785   prop = ndb_mgm_call(handle, reply, "get session id", &args);
2786   CHECK_REPLY(handle, prop, 0);
2787 
2788   if(!prop->get("id",&session_id)){
2789     fprintf(handle->errstream, "Unable to get session id\n");
2790     return 0;
2791   }
2792 
2793   delete prop;
2794   DBUG_RETURN(session_id);
2795 }
2796 
2797 extern "C"
2798 int
ndb_mgm_get_session(NdbMgmHandle handle,Uint64 id,struct NdbMgmSession * s,int * len)2799 ndb_mgm_get_session(NdbMgmHandle handle, Uint64 id,
2800                     struct NdbMgmSession *s, int *len)
2801 {
2802   int retval= 0;
2803   DBUG_ENTER("ndb_mgm_get_session");
2804   CHECK_HANDLE(handle, 0);
2805   CHECK_CONNECTED(handle, 0);
2806 
2807   Properties args;
2808   args.put("id", id);
2809 
2810   const ParserRow<ParserDummy> reply[]= {
2811     MGM_CMD("get session reply", NULL, ""),
2812     MGM_ARG("id", Int, Mandatory, "Node ID"),
2813     MGM_ARG("m_stopSelf", Int, Optional, "m_stopSelf"),
2814     MGM_ARG("m_stop", Int, Optional, "stop session"),
2815     MGM_ARG("nodeid", Int, Optional, "allocated node id"),
2816     MGM_ARG("parser_buffer_len", Int, Optional, "waiting in buffer"),
2817     MGM_ARG("parser_status", Int, Optional, "parser status"),
2818     MGM_END()
2819   };
2820 
2821   const Properties *prop;
2822   prop = ndb_mgm_call(handle, reply, "get session", &args);
2823   CHECK_REPLY(handle, prop, 0);
2824 
2825   Uint64 r_id;
2826   int rlen= 0;
2827 
2828   if(!prop->get("id",&r_id)){
2829     fprintf(handle->errstream, "Unable to get session id\n");
2830     goto err;
2831   }
2832 
2833   s->id= r_id;
2834   rlen+=sizeof(s->id);
2835 
2836   if(prop->get("m_stopSelf",&(s->m_stopSelf)))
2837     rlen+=sizeof(s->m_stopSelf);
2838   else
2839     goto err;
2840 
2841   if(prop->get("m_stop",&(s->m_stop)))
2842     rlen+=sizeof(s->m_stop);
2843   else
2844     goto err;
2845 
2846   if(prop->get("nodeid",&(s->nodeid)))
2847     rlen+=sizeof(s->nodeid);
2848   else
2849     goto err;
2850 
2851   if(prop->get("parser_buffer_len",&(s->parser_buffer_len)))
2852   {
2853     rlen+=sizeof(s->parser_buffer_len);
2854     if(prop->get("parser_status",&(s->parser_status)))
2855       rlen+=sizeof(s->parser_status);
2856   }
2857 
2858   *len= rlen;
2859   retval= 1;
2860 
2861 err:
2862   delete prop;
2863   DBUG_RETURN(retval);
2864 }
2865 
2866 template class Vector<const ParserRow<ParserDummy>*>;
2867