1 /*
2    Copyright (c) 2003, 2019, Oracle and/or its affiliates. All rights reserved.
3 
4    This program is free software; you can redistribute it and/or modify
5    it under the terms of the GNU General Public License, version 2.0,
6    as published by the Free Software Foundation.
7 
8    This program is also distributed with certain software (including
9    but not limited to OpenSSL) that is licensed under separate terms,
10    as designated in a particular file or component or in included license
11    documentation.  The authors of MySQL hereby grant you an additional
12    permission to link the program and your derivative works with the
13    separately licensed software that they have included with MySQL.
14 
15    This program is distributed in the hope that it will be useful,
16    but WITHOUT ANY WARRANTY; without even the implied warranty of
17    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18    GNU General Public License, version 2.0, for more details.
19 
20    You should have received a copy of the GNU General Public License
21    along with this program; if not, write to the Free Software
22    Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301  USA
23 */
24 
25 #include <ndb_global.h>
26 
27 #include <LocalConfig.hpp>
28 
29 #include <NdbSleep.h>
30 #include <NdbTCP.h>
31 #include <mgmapi.h>
32 #include <mgmapi_internal.h>
33 #include <mgmapi_debug.h>
34 #include "mgmapi_configuration.hpp"
35 #include <socket_io.h>
36 #include <version.h>
37 
38 #include <NdbOut.hpp>
39 #include <SocketServer.hpp>
40 #include <SocketClient.hpp>
41 #include <Parser.hpp>
42 #include <OutputStream.hpp>
43 #include <InputStream.hpp>
44 #include <ConfigObject.hpp>
45 #include <ndb_base64.h>
46 
47 //#define MGMAPI_LOG
48 #define MGM_CMD(name, fun, desc) \
49  { name, \
50    0, \
51    ParserRow<ParserDummy>::Cmd, \
52    ParserRow<ParserDummy>::String, \
53    ParserRow<ParserDummy>::Optional, \
54    ParserRow<ParserDummy>::IgnoreMinMax, \
55    0, 0, \
56    fun, \
57    desc, 0 }
58 
59 #define MGM_ARG(name, type, opt, desc) \
60  { name, \
61    0, \
62    ParserRow<ParserDummy>::Arg, \
63    ParserRow<ParserDummy>::type, \
64    ParserRow<ParserDummy>::opt, \
65    ParserRow<ParserDummy>::IgnoreMinMax, \
66    0, 0, \
67    0, \
68    desc, 0 }
69 
70 #define MGM_END() \
71  { 0, \
72    0, \
73    ParserRow<ParserDummy>::End, \
74    ParserRow<ParserDummy>::Int, \
75    ParserRow<ParserDummy>::Optional, \
76    ParserRow<ParserDummy>::IgnoreMinMax, \
77    0, 0, \
78    0, \
79    0, 0 }
80 
81 class ParserDummy : private SocketServer::Session
82 {
83 public:
84   ParserDummy(NDB_SOCKET_TYPE sock);
85 };
86 
ParserDummy(NDB_SOCKET_TYPE sock)87 ParserDummy::ParserDummy(NDB_SOCKET_TYPE sock) : SocketServer::Session(sock)
88 {
89 }
90 
91 typedef Parser<ParserDummy> Parser_t;
92 
93 #define NDB_MGM_MAX_ERR_DESC_SIZE 256
94 
95 struct ndb_mgm_handle {
96   int cfg_i;
97 
98   int connected;
99   int last_error;
100   int last_error_line;
101   char last_error_desc[NDB_MGM_MAX_ERR_DESC_SIZE];
102   unsigned int timeout;
103 
104   NDB_SOCKET_TYPE socket;
105 
106   LocalConfig cfg;
107 
108 #ifdef MGMAPI_LOG
109   FILE* logfile;
110 #endif
111   FILE *errstream;
112   char *m_name;
113   int mgmd_version_major;
114   int mgmd_version_minor;
115   int mgmd_version_build;
116 
mgmd_versionndb_mgm_handle117   int mgmd_version(void) const {
118     // Must be connected
119     assert(connected);
120     // Check that version has been read
121     assert(mgmd_version_major >= 0 &&
122            mgmd_version_minor >= 0 &&
123            mgmd_version_build >= 0);
124     return NDB_MAKE_VERSION(mgmd_version_major,
125                             mgmd_version_minor,
126                             mgmd_version_build);
127   }
128 
129   char * m_bindaddress;
130   int m_bindaddress_port;
131   bool ignore_sigpipe;
132 };
133 
134 
135 /*
136   Check if version "curr" is new relative a list of given versions.
137 
138   curr is regarded new relative a list of versions if
139   either, curr is greater than or equal a version in list
140   with same major and minor version, or, curr is greater
141   than all versions in list.
142 
143   NOTE! The list of versions to check against must be listed
144   with the highest version first, and at most one entry per
145   major and minor version, and terminated with version 0
146 */
147 static inline
check_version_new(Uint32 curr,...)148 bool check_version_new(Uint32 curr, ...)
149 {
150   Uint32 version, last = ~0U;
151 
152   va_list versions;
153   va_start(versions, curr);
154   while ((version= va_arg(versions, Uint32)) != 0U)
155   {
156     // check that version list is descending
157     assert(version < last);
158     // check at most one entry per major.minor
159     assert(!(ndbGetMajor(version) == ndbGetMajor(last) && ndbGetMinor(version) == ndbGetMinor(last)));
160 
161     if (curr >= version)
162     {
163       va_end(versions);
164       if (last == ~0U)
165       {
166         return true; // curr is greater than all versions in list (or equal the first and greatest)
167       }
168       return ndbGetMajor(curr) == ndbGetMajor(version) && ndbGetMinor(curr) == ndbGetMinor(version);
169     }
170 
171     last = version;
172   }
173   va_end(versions);
174 
175   return false;
176 }
177 
178 
179 static
180 void
181 setError(NdbMgmHandle h, int error, int error_line, const char * msg, ...)
182  ATTRIBUTE_FORMAT(printf, 4, 5);
183 
184 static
185 void
setError(NdbMgmHandle h,int error,int error_line,const char * msg,...)186 setError(NdbMgmHandle h, int error, int error_line, const char * msg, ...)
187 {
188 
189   h->last_error = error;
190   h->last_error_line = error_line;
191 
192   va_list ap;
193   va_start(ap, msg);
194   BaseString::vsnprintf(h->last_error_desc, sizeof(h->last_error_desc), msg, ap);
195   va_end(ap);
196 }
197 
198 #define SET_ERROR(h, e, s) setError((h), (e), __LINE__, "%s", (s))
199 #define SET_ERROR_CMD(h, e, s, cmd, t) setError((h), (e), __LINE__, "cmd: %s, error: %s, timeout: %d", (cmd), (s), (t))
200 
201 #define CHECK_HANDLE(handle, ret) \
202   if(handle == 0) {   \
203     DBUG_RETURN(ret); \
204   }
205 
206 #define CHECK_CONNECTED(handle, ret) \
207   if (handle->connected != 1) { \
208     SET_ERROR(handle, NDB_MGM_SERVER_NOT_CONNECTED , ""); \
209     DBUG_RETURN(ret);                                     \
210   }
211 
212 #define CHECK_REPLY(handle, reply, ret) \
213   if (reply == NULL) { \
214     if(!handle->last_error) \
215       SET_ERROR(handle, NDB_MGM_ILLEGAL_SERVER_REPLY, ""); \
216     DBUG_RETURN(ret);                                    \
217   }
218 
219 #define CHECK_TIMEDOUT(in, out) \
220   if(in.timedout() || out.timedout()) \
221     SET_ERROR(handle, ETIMEDOUT, \
222               "Time out talking to management server");
223 
224 #define CHECK_TIMEDOUT_RET(h, in, out, ret, cmd) \
225   if(in.timedout() || out.timedout()) { \
226     SET_ERROR_CMD(h, ETIMEDOUT, \
227               "Time out talking to management server", cmd, h->timeout); \
228     ndb_mgm_disconnect_quiet(h); \
229     DBUG_RETURN(ret);            \
230   }
231 
232 /*****************************************************************************
233  * Handles
234  *****************************************************************************/
235 
236 extern "C"
237 NdbMgmHandle
ndb_mgm_create_handle()238 ndb_mgm_create_handle()
239 {
240   DBUG_ENTER("ndb_mgm_create_handle");
241   NdbMgmHandle h = (NdbMgmHandle)malloc(sizeof(ndb_mgm_handle));
242   if (!h)
243     DBUG_RETURN(NULL);
244 
245   h->connected       = 0;
246   h->last_error      = 0;
247   h->last_error_line = 0;
248   ndb_socket_invalidate(&(h->socket));
249   h->timeout         = 60000;
250   h->cfg_i           = -1;
251   h->errstream       = stdout;
252   h->m_name          = NULL;
253   h->m_bindaddress   = 0;
254   h->m_bindaddress_port = 0;
255   h->ignore_sigpipe  = true;
256 
257   strncpy(h->last_error_desc, "No error", NDB_MGM_MAX_ERR_DESC_SIZE);
258 
259   new (&(h->cfg)) LocalConfig;
260   h->cfg.init(0, 0);
261 
262 #ifdef MGMAPI_LOG
263   h->logfile = 0;
264 #endif
265 
266   h->mgmd_version_major= -1;
267   h->mgmd_version_minor= -1;
268   h->mgmd_version_build= -1;
269 
270   DBUG_PRINT("info", ("handle: 0x%lx", (long) h));
271   DBUG_RETURN(h);
272 }
273 
274 extern "C"
275 void
ndb_mgm_set_name(NdbMgmHandle handle,const char * name)276 ndb_mgm_set_name(NdbMgmHandle handle, const char *name)
277 {
278   free(handle->m_name);
279   handle->m_name= strdup(name);
280 }
281 
282 extern "C"
283 const char *
ndb_mgm_get_name(const NdbMgmHandle handle)284 ndb_mgm_get_name(const NdbMgmHandle handle)
285 {
286   return handle->m_name;
287 }
288 
289 extern "C"
290 int
ndb_mgm_set_connectstring(NdbMgmHandle handle,const char * connect_string)291 ndb_mgm_set_connectstring(NdbMgmHandle handle, const char* connect_string)
292 {
293   DBUG_ENTER("ndb_mgm_set_connectstring");
294   DBUG_PRINT("info", ("handle: 0x%lx", (long) handle));
295   handle->cfg.~LocalConfig();
296   new (&(handle->cfg)) LocalConfig;
297   if (!handle->cfg.init(connect_string, 0) ||
298       handle->cfg.ids.size() == 0)
299   {
300     handle->cfg.~LocalConfig();
301     new (&(handle->cfg)) LocalConfig;
302     handle->cfg.init(0, 0); /* reset the LocalConfig */
303     SET_ERROR(handle, NDB_MGM_ILLEGAL_CONNECT_STRING,
304               connect_string ? connect_string : "");
305     DBUG_RETURN(-1);
306   }
307   handle->cfg_i= -1;
308   handle->cfg.bind_address_port= handle->m_bindaddress_port;
309   handle->cfg.bind_address.assign(handle->m_bindaddress ? handle->m_bindaddress : "");
310   DBUG_RETURN(0);
311 }
312 
313 extern "C"
314 int
ndb_mgm_set_bindaddress(NdbMgmHandle handle,const char * arg)315 ndb_mgm_set_bindaddress(NdbMgmHandle handle, const char * arg)
316 {
317   DBUG_ENTER("ndb_mgm_set_bindaddress");
318   free(handle->m_bindaddress);
319 
320   if (arg)
321   {
322     handle->m_bindaddress = strdup(arg);
323     char *port = strchr(handle->m_bindaddress, ':');
324     if (port != 0)
325     {
326       handle->m_bindaddress_port = atoi(port+1);
327       *port = 0;
328     }
329     else
330       handle->m_bindaddress_port = 0;
331   }
332   else
333   {
334     handle->m_bindaddress = 0;
335     handle->m_bindaddress_port = 0;
336   }
337   if (handle->cfg.ids.size() != 0)
338   {
339     handle->cfg.bind_address_port= handle->m_bindaddress_port;
340     handle->cfg.bind_address.assign(handle->m_bindaddress ? handle->m_bindaddress : "");
341   }
342   DBUG_RETURN(0);
343 }
344 
345 extern "C"
346 int
ndb_mgm_set_ignore_sigpipe(NdbMgmHandle handle,int val)347 ndb_mgm_set_ignore_sigpipe(NdbMgmHandle handle, int val)
348 {
349   DBUG_ENTER("ndb_mgm_set_ignore_sigpipe");
350   CHECK_HANDLE(handle, -1);
351   if (handle->connected){
352     SET_ERROR(handle, EINVAL, "Can't change 'ignore_sigpipe' while connected");
353     DBUG_RETURN(-1);
354   }
355   handle->ignore_sigpipe = (val != 0);
356   DBUG_RETURN(0);
357 }
358 
359 /**
360  * Destroy a handle
361  */
362 extern "C"
363 void
ndb_mgm_destroy_handle(NdbMgmHandle * handle)364 ndb_mgm_destroy_handle(NdbMgmHandle * handle)
365 {
366   DBUG_ENTER("ndb_mgm_destroy_handle");
367   if(!handle)
368     DBUG_VOID_RETURN;
369   DBUG_PRINT("info", ("handle: 0x%lx", (long) (* handle)));
370   /**
371    * important! only disconnect if connected
372    * other code relies on this
373    */
374   if((* handle)->connected){
375     ndb_mgm_disconnect(* handle);
376   }
377 #ifdef MGMAPI_LOG
378   if ((* handle)->logfile != 0){
379     fclose((* handle)->logfile);
380     (* handle)->logfile = 0;
381   }
382 #endif
383   (*handle)->cfg.~LocalConfig();
384   free((*handle)->m_name);
385   free((*handle)->m_bindaddress);
386   free(*handle);
387   * handle = 0;
388   DBUG_VOID_RETURN;
389 }
390 
391 extern "C"
392 void
ndb_mgm_set_error_stream(NdbMgmHandle handle,FILE * file)393 ndb_mgm_set_error_stream(NdbMgmHandle handle, FILE * file)
394 {
395   handle->errstream = file;
396 }
397 
398 /*****************************************************************************
399  * Error handling
400  *****************************************************************************/
401 
402 /**
403  * Get latest error associated with a handle
404  */
405 extern "C"
406 int
ndb_mgm_get_latest_error(const NdbMgmHandle h)407 ndb_mgm_get_latest_error(const NdbMgmHandle h)
408 {
409   if (!h)
410     return NDB_MGM_ILLEGAL_SERVER_HANDLE;
411 
412   return h->last_error;
413 }
414 
415 extern "C"
416 const char *
ndb_mgm_get_latest_error_desc(const NdbMgmHandle h)417 ndb_mgm_get_latest_error_desc(const NdbMgmHandle h)
418 {
419   if (!h)
420     return "";
421   return h->last_error_desc;
422 }
423 
424 extern "C"
425 int
ndb_mgm_get_latest_error_line(const NdbMgmHandle h)426 ndb_mgm_get_latest_error_line(const NdbMgmHandle h)
427 {
428   if (!h)
429     return 0;
430   return h->last_error_line;
431 }
432 
433 extern "C"
434 const char *
ndb_mgm_get_latest_error_msg(const NdbMgmHandle h)435 ndb_mgm_get_latest_error_msg(const NdbMgmHandle h)
436 {
437   const int last_err = ndb_mgm_get_latest_error(h);
438 
439   for (int i=0; i<ndb_mgm_noOfErrorMsgs; i++) {
440     if (ndb_mgm_error_msgs[i].code == last_err)
441       return ndb_mgm_error_msgs[i].msg;
442   }
443 
444   return "Error"; // Unknown Error message
445 }
446 
447 
448 /*
449   ndb_mgm_call
450 
451   Send command, command arguments and any command bulk data to
452   ndb_mgmd.
453   Read and return result
454 
455   @param The mgmapi handle
456   @param List describing the expected reply
457   @param Name of the command to call
458   @param Arguments for the command
459   @param Any bulk data to send after the command
460 
461  */
462 static const Properties *
ndb_mgm_call(NdbMgmHandle handle,const ParserRow<ParserDummy> * command_reply,const char * cmd,const Properties * cmd_args,const char * cmd_bulk=NULL)463 ndb_mgm_call(NdbMgmHandle handle,
464              const ParserRow<ParserDummy> *command_reply,
465              const char *cmd, const Properties *cmd_args,
466              const char* cmd_bulk= NULL)
467 {
468   DBUG_ENTER("ndb_mgm_call");
469   DBUG_PRINT("enter",("handle->socket: " MY_SOCKET_FORMAT ", cmd: %s",
470 		      MY_SOCKET_FORMAT_VALUE(handle->socket), cmd));
471   SocketOutputStream out(handle->socket, handle->timeout);
472   SocketInputStream in(handle->socket, handle->timeout);
473 
474   out.println("%s", cmd);
475 #ifdef MGMAPI_LOG
476   /**
477    * Print command to  log file
478    */
479   FileOutputStream f(handle->logfile);
480   f.println("OUT: %s", cmd);
481 #endif
482 
483   if(cmd_args != NULL) {
484     Properties::Iterator iter(cmd_args);
485     const char *name;
486     while((name = iter.next()) != NULL) {
487       PropertiesType t;
488       Uint32 val_i;
489       Uint64 val_64;
490       BaseString val_s;
491 
492       cmd_args->getTypeOf(name, &t);
493       switch(t) {
494       case PropertiesType_Uint32:
495 	cmd_args->get(name, &val_i);
496 	out.println("%s: %u", name, val_i);
497 	break;
498       case PropertiesType_Uint64:
499 	cmd_args->get(name, &val_64);
500 	out.println("%s: %llu", name, val_64);
501 	break;
502       case PropertiesType_char:
503 	cmd_args->get(name, val_s);
504 	out.println("%s: %s", name, val_s.c_str());
505 	break;
506       case PropertiesType_Properties:
507 	DBUG_PRINT("info",("Ignoring PropertiesType_Properties."));
508 	/* Ignore */
509 	break;
510       default:
511 	DBUG_PRINT("info",("Ignoring PropertiesType: %d.",t));
512       }
513     }
514 #ifdef MGMAPI_LOG
515   /**
516    * Print arguments to  log file
517    */
518   cmd_args->print(handle->logfile, "OUT: ");
519 #endif
520   }
521   out.println("%s", "");
522 
523   if (cmd_bulk)
524   {
525     out.write(cmd_bulk, strlen(cmd_bulk));
526     out.write("\n", 1);
527   }
528 
529   CHECK_TIMEDOUT_RET(handle, in, out, NULL, cmd);
530 
531   Parser_t::Context ctx;
532   ParserDummy session(handle->socket);
533   Parser_t parser(command_reply, in);
534 
535   const Properties* p = parser.parse(ctx, session);
536   if (p == NULL){
537     if(!ndb_mgm_is_connected(handle)) {
538       CHECK_TIMEDOUT_RET(handle, in, out, NULL, cmd);
539       DBUG_RETURN(NULL);
540     }
541     else
542     {
543       CHECK_TIMEDOUT_RET(handle, in, out, NULL, cmd);
544       if(ctx.m_status==Parser_t::Eof
545 	 || ctx.m_status==Parser_t::NoLine)
546       {
547 	ndb_mgm_disconnect(handle);
548         CHECK_TIMEDOUT_RET(handle, in, out, NULL, cmd);
549 	DBUG_RETURN(NULL);
550       }
551       /**
552        * Print some info about why the parser returns NULL
553        */
554       fprintf(handle->errstream,
555 	      "Error in mgm protocol parser. cmd: >%s< status: %d curr: %s\n",
556 	      cmd, (Uint32)ctx.m_status,
557               (ctx.m_currentToken)?ctx.m_currentToken:"NULL");
558       DBUG_PRINT("info",("ctx.status: %d, ctx.m_currentToken: %s",
559 		         ctx.m_status, ctx.m_currentToken));
560     }
561   }
562 #ifdef MGMAPI_LOG
563   else {
564     /**
565      * Print reply to log file
566      */
567     p->print(handle->logfile, "IN: ");
568   }
569 #endif
570 
571   if(p && (in.timedout() || out.timedout()))
572     delete p;
573   CHECK_TIMEDOUT_RET(handle, in, out, NULL, cmd);
574   DBUG_RETURN(p);
575 }
576 
577 /*
578   ndb_mgm_call_slow
579 
580   Some commands are synchronous and known to take longer time
581   to complete(for example restart and stop). Increase the timeout
582   value before sending command if the timeout value is set lower
583   than what is normal.
584 
585   Unfortunately the restart or stop may take longer than the
586   defalt min timeout value selected, mgmapi users can workaround
587   this problem by setting an even larger timeout for all commands
588   or only around restart and stop.
589 
590 */
591 
592 static inline
593 const Properties *
ndb_mgm_call_slow(NdbMgmHandle handle,const ParserRow<ParserDummy> * command_reply,const char * cmd,const Properties * cmd_args,unsigned int min_timeout=5* 60* 1000,const char * cmd_bulk=NULL)594 ndb_mgm_call_slow(NdbMgmHandle handle,
595                   const ParserRow<ParserDummy> *command_reply,
596                   const char *cmd, const Properties *cmd_args,
597                   unsigned int min_timeout = 5*60*1000, // ms
598                   const char* cmd_bulk= NULL)
599 {
600   const unsigned int save_timeout = handle->timeout;
601   if (min_timeout > save_timeout)
602     handle->timeout = min_timeout;
603   const Properties* reply = ndb_mgm_call(handle, command_reply,
604                                          cmd, cmd_args, cmd_bulk);
605 
606   // Restore saved timeout value
607   handle->timeout = save_timeout;
608 
609   return reply;
610 }
611 
612 /**
613  * Returns true if connected
614  */
615 extern "C"
ndb_mgm_is_connected(NdbMgmHandle handle)616 int ndb_mgm_is_connected(NdbMgmHandle handle)
617 {
618   if(!handle)
619     return 0;
620 
621   if(handle->connected)
622   {
623     if(Ndb_check_socket_hup(handle->socket))
624     {
625       handle->connected= 0;
626       ndb_socket_close(handle->socket);
627       ndb_socket_invalidate(&handle->socket);
628     }
629   }
630   return handle->connected;
631 }
632 
633 extern "C"
ndb_mgm_set_connect_timeout(NdbMgmHandle handle,unsigned int seconds)634 int ndb_mgm_set_connect_timeout(NdbMgmHandle handle, unsigned int seconds)
635 {
636   return ndb_mgm_set_timeout(handle, seconds*1000);
637 }
638 
639 extern "C"
ndb_mgm_set_timeout(NdbMgmHandle handle,unsigned int timeout_ms)640 int ndb_mgm_set_timeout(NdbMgmHandle handle, unsigned int timeout_ms)
641 {
642   if(!handle)
643     return -1;
644 
645   handle->timeout= timeout_ms;
646   return 0;
647 }
648 
649 extern "C"
ndb_mgm_number_of_mgmd_in_connect_string(NdbMgmHandle handle)650 int ndb_mgm_number_of_mgmd_in_connect_string(NdbMgmHandle handle)
651 {
652   int count=0;
653   Uint32 i;
654   LocalConfig &cfg= handle->cfg;
655 
656   for (i = 0; i < cfg.ids.size(); i++)
657   {
658     if (cfg.ids[i].type != MgmId_TCP)
659       continue;
660     count++;
661   }
662   return count;
663 }
664 
665 static
ndb_mgm_set_version(NdbMgmHandle handle)666 int ndb_mgm_set_version(NdbMgmHandle handle)
667 {
668   DBUG_ENTER("ndb_mgm_set_version");
669   CHECK_HANDLE(handle, -1);
670   CHECK_CONNECTED(handle, -1);
671 
672   Properties args;
673   args.put("major", Uint32(NDB_VERSION_MAJOR));
674   args.put("minor", Uint32(NDB_VERSION_MINOR));
675   args.put("build", Uint32(NDB_VERSION_BUILD));
676 
677   const ParserRow<ParserDummy> set_clientversion_reply[] = {
678     MGM_CMD("set clientversion reply", NULL, ""),
679     MGM_ARG("result", String, Mandatory, "Error message"),
680     MGM_END()
681   };
682 
683   const Properties* reply =
684     ndb_mgm_call(handle, set_clientversion_reply, "set clientversion", &args);
685 
686   CHECK_REPLY(handle, reply, -1);
687 
688   BaseString result;
689   reply->get("result", result);
690   delete reply;
691 
692   if(result != "Ok") {
693     SET_ERROR(handle, NDB_MGM_ILLEGAL_SERVER_REPLY, result.c_str());
694     DBUG_RETURN(-1);
695   }
696 
697   DBUG_RETURN(0);
698 }
699 
700 static inline
get_mgmd_version(NdbMgmHandle handle)701 bool get_mgmd_version(NdbMgmHandle handle)
702 {
703   assert(handle->connected);
704 
705   if (handle->mgmd_version_major >= 0)
706     return true; // Already fetched version of mgmd
707 
708   char buf[2]; // Not used -> keep short
709   if (!ndb_mgm_get_version(handle,
710                            &(handle->mgmd_version_major),
711                            &(handle->mgmd_version_minor),
712                            &(handle->mgmd_version_build),
713                            sizeof(buf), buf))
714     return false;
715 
716   /* If MGMD supports it, tell it our version */
717   if (NDB_MAKE_VERSION(handle->mgmd_version_major,
718                        handle->mgmd_version_minor,
719                        handle->mgmd_version_build) >=
720       NDB_MAKE_VERSION(8,0,20))
721   {
722     //Inform MGMD of our version
723     //MGMD gained support for set version command in 8.0.20
724     if (ndb_mgm_set_version(handle) != 0)
725       return false;
726   }
727   return true;
728 }
729 
730 
731 /**
732  * Connect to a management server
733  * no_retries = 0, return immediately,
734  * no_retries < 0, retry infinitely,
735  * else retry no_retries times.
736  */
737 extern "C"
738 int
ndb_mgm_connect(NdbMgmHandle handle,int no_retries,int retry_delay_in_seconds,int verbose)739 ndb_mgm_connect(NdbMgmHandle handle, int no_retries,
740 		int retry_delay_in_seconds, int verbose)
741 {
742   DBUG_ENTER("ndb_mgm_connect");
743   CHECK_HANDLE(handle, -1);
744   SET_ERROR(handle, NDB_MGM_NO_ERROR, "Executing: ndb_mgm_connect");
745 
746 #ifdef MGMAPI_LOG
747   /**
748   * Open the log file
749   */
750   char logname[64];
751   BaseString::snprintf(logname, 64, "mgmapi.log");
752   handle->logfile = fopen(logname, "w");
753 #endif
754   char buf[1024];
755 
756 #if defined SIGPIPE && !defined _WIN32
757   if (handle->ignore_sigpipe)
758     (void)signal(SIGPIPE, SIG_IGN);
759 #endif
760 
761   /**
762    * Do connect
763    */
764   LocalConfig &cfg= handle->cfg;
765   NDB_SOCKET_TYPE sockfd;
766   ndb_socket_invalidate(&sockfd);
767   Uint32 i = Uint32(~0);
768   while (!ndb_socket_valid(sockfd))
769   {
770     // do all the mgmt servers
771     for (i = 0; i < cfg.ids.size(); i++)
772     {
773       if (cfg.ids[i].type != MgmId_TCP)
774 	continue;
775 
776       SocketClient s;
777       const char *bind_address= NULL;
778       unsigned short bind_address_port= 0;
779       s.set_connect_timeout(handle->timeout);
780       if (!s.init())
781       {
782         fprintf(handle->errstream,
783                 "Unable to create socket, "
784                 "while trying to connect with connect string: %s\n",
785                 cfg.makeConnectString(buf,sizeof(buf)));
786 
787         setError(handle, NDB_MGM_COULD_NOT_CONNECT_TO_SOCKET, __LINE__,
788                  "Unable to create socket, "
789                  "while trying to connect with connect string: %s\n",
790                  cfg.makeConnectString(buf,sizeof(buf)));
791         DBUG_RETURN(-1);
792       }
793       if (handle->m_bindaddress)
794       {
795         bind_address= handle->m_bindaddress;
796         bind_address_port= handle->m_bindaddress_port;
797       }
798       else if (cfg.ids[i].bind_address.length())
799       {
800         bind_address= cfg.ids[i].bind_address.c_str();
801         bind_address_port= cfg.ids[i].bind_address_port;
802       }
803       if (bind_address)
804       {
805         int err;
806         if ((err = s.bind(bind_address, bind_address_port)) != 0)
807         {
808           if (!handle->m_bindaddress)
809           {
810             // retry with next mgmt server
811             continue;
812           }
813           fprintf(handle->errstream,
814                   "Unable to bind local address '%s:%d' errno: %d, "
815                   "while trying to connect with connect string: '%s'\n",
816                   bind_address, (int)bind_address_port, err,
817                   cfg.makeConnectString(buf,sizeof(buf)));
818 
819           setError(handle, NDB_MGM_BIND_ADDRESS, __LINE__,
820                    "Unable to bind local address '%s:%d' errno: %d, "
821                    "while trying to connect with connect string: '%s'\n",
822                    bind_address, (int)bind_address_port, err,
823                    cfg.makeConnectString(buf,sizeof(buf)));
824           DBUG_RETURN(-1);
825         }
826       }
827       sockfd = s.connect(cfg.ids[i].name.c_str(), cfg.ids[i].port);
828       if (ndb_socket_valid(sockfd))
829 	break;
830     }
831     if (ndb_socket_valid(sockfd))
832       break;
833 #ifndef DBUG_OFF
834     {
835       DBUG_PRINT("info",("Unable to connect with connect string: %s",
836 			 cfg.makeConnectString(buf,sizeof(buf))));
837     }
838 #endif
839     if (verbose > 0) {
840       fprintf(handle->errstream,
841 	      "Unable to connect with connect string: %s\n",
842 	      cfg.makeConnectString(buf,sizeof(buf)));
843       verbose= -1;
844     }
845     if (no_retries == 0) {
846       setError(handle, NDB_MGM_COULD_NOT_CONNECT_TO_SOCKET, __LINE__,
847 	       "Unable to connect with connect string: %s",
848 	       cfg.makeConnectString(buf,sizeof(buf)));
849       if (verbose == -2)
850 	fprintf(handle->errstream, ", failed.\n");
851       DBUG_RETURN(-1);
852     }
853     if (verbose == -1) {
854       fprintf(handle->errstream, "Retrying every %d seconds",
855 	      retry_delay_in_seconds);
856       if (no_retries > 0)
857 	fprintf(handle->errstream, ". Attempts left:");
858       else
859 	fprintf(handle->errstream, ", until connected.");
860       fflush(handle->errstream);
861       verbose= -2;
862     }
863     if (no_retries > 0) {
864       if (verbose == -2) {
865 	fprintf(handle->errstream, " %d", no_retries);
866 	fflush(handle->errstream);
867       }
868       no_retries--;
869     }
870     else
871     {
872       // no_retries < 0, retrying infinitely
873       if (verbose == -2)
874       {
875         fprintf(handle->errstream, ".");
876         fflush(handle->errstream);
877       }
878     }
879     NdbSleep_SecSleep(retry_delay_in_seconds);
880   }
881   if (verbose == -2)
882   {
883     fprintf(handle->errstream, "\n");
884     fflush(handle->errstream);
885   }
886   handle->cfg_i = i;
887 
888   handle->socket    = sockfd;
889   handle->connected = 1;
890 
891   // Version of the connected ndb_mgmd is not yet known
892   handle->mgmd_version_major= -1;
893   handle->mgmd_version_minor= -1;
894   handle->mgmd_version_build= -1;
895 
896   DBUG_RETURN(0);
897 }
898 
899 /**
900  * Only used for low level testing
901  * Never to be used by end user.
902  * Or anybody who doesn't know exactly what they're doing.
903  */
904 extern "C"
905 ndb_native_socket_t
ndb_mgm_get_fd(NdbMgmHandle handle)906 ndb_mgm_get_fd(NdbMgmHandle handle)
907 {
908   return ndb_socket_get_native(handle->socket);
909 }
910 
911 /**
912  * Disconnect from mgm server without error checking
913  * Should be used internally only.
914  * e.g. on timeout, we leave NdbMgmHandle disconnected
915  */
916 extern "C"
917 int
ndb_mgm_disconnect_quiet(NdbMgmHandle handle)918 ndb_mgm_disconnect_quiet(NdbMgmHandle handle)
919 {
920   ndb_socket_close(handle->socket);
921   ndb_socket_invalidate(&(handle->socket));
922   handle->connected = 0;
923 
924   return 0;
925 }
926 
927 /**
928  * Disconnect from a mgm server
929  */
930 extern "C"
931 int
ndb_mgm_disconnect(NdbMgmHandle handle)932 ndb_mgm_disconnect(NdbMgmHandle handle)
933 {
934   DBUG_ENTER("ndb_mgm_disconnect");
935   CHECK_HANDLE(handle, -1);
936   SET_ERROR(handle, NDB_MGM_NO_ERROR, "Executing: ndb_mgm_disconnect");
937   CHECK_CONNECTED(handle, -1);
938 
939   DBUG_RETURN(ndb_mgm_disconnect_quiet(handle));
940 }
941 
942 struct ndb_mgm_type_atoi
943 {
944   const char * str;
945   const char * alias;
946   enum ndb_mgm_node_type value;
947 };
948 
949 static struct ndb_mgm_type_atoi type_values[] =
950 {
951   { "NDB", "ndbd", NDB_MGM_NODE_TYPE_NDB},
952   { "API", "mysqld", NDB_MGM_NODE_TYPE_API },
953   { "MGM", "ndb_mgmd", NDB_MGM_NODE_TYPE_MGM }
954 };
955 
956 const int no_of_type_values = (sizeof(type_values) /
957 			       sizeof(ndb_mgm_type_atoi));
958 
959 extern "C"
960 ndb_mgm_node_type
ndb_mgm_match_node_type(const char * type)961 ndb_mgm_match_node_type(const char * type)
962 {
963   if(type == 0)
964     return NDB_MGM_NODE_TYPE_UNKNOWN;
965 
966   for(int i = 0; i<no_of_type_values; i++)
967     if(strcmp(type, type_values[i].str) == 0)
968       return type_values[i].value;
969     else if(strcmp(type, type_values[i].alias) == 0)
970       return type_values[i].value;
971 
972   return NDB_MGM_NODE_TYPE_UNKNOWN;
973 }
974 
975 extern "C"
976 const char *
ndb_mgm_get_node_type_string(enum ndb_mgm_node_type type)977 ndb_mgm_get_node_type_string(enum ndb_mgm_node_type type)
978 {
979   for(int i = 0; i<no_of_type_values; i++)
980     if(type_values[i].value == type)
981       return type_values[i].str;
982   return 0;
983 }
984 
985 extern "C"
986 const char *
ndb_mgm_get_node_type_alias_string(enum ndb_mgm_node_type type,const char ** str)987 ndb_mgm_get_node_type_alias_string(enum ndb_mgm_node_type type, const char** str)
988 {
989   for(int i = 0; i<no_of_type_values; i++)
990     if(type_values[i].value == type)
991       {
992 	if (str)
993 	  *str= type_values[i].str;
994 	return type_values[i].alias;
995       }
996   return 0;
997 }
998 
999 struct ndb_mgm_status_atoi {
1000   const char * str;
1001   enum ndb_mgm_node_status value;
1002 };
1003 
1004 static struct ndb_mgm_status_atoi status_values[] =
1005 {
1006   { "UNKNOWN", NDB_MGM_NODE_STATUS_UNKNOWN },
1007   { "NO_CONTACT", NDB_MGM_NODE_STATUS_NO_CONTACT },
1008   { "NOT_STARTED", NDB_MGM_NODE_STATUS_NOT_STARTED },
1009   { "STARTING", NDB_MGM_NODE_STATUS_STARTING },
1010   { "STARTED", NDB_MGM_NODE_STATUS_STARTED },
1011   { "SHUTTING_DOWN", NDB_MGM_NODE_STATUS_SHUTTING_DOWN },
1012   { "RESTARTING", NDB_MGM_NODE_STATUS_RESTARTING },
1013   { "SINGLE USER MODE", NDB_MGM_NODE_STATUS_SINGLEUSER },
1014   { "SINGLE USER MODE", NDB_MGM_NODE_STATUS_SINGLEUSER },
1015   { "RESUME", NDB_MGM_NODE_STATUS_RESUME },
1016   { "CONNECTED", NDB_MGM_NODE_STATUS_CONNECTED }
1017 };
1018 
1019 const int no_of_status_values = (sizeof(status_values) /
1020 				 sizeof(ndb_mgm_status_atoi));
1021 
1022 extern "C"
1023 ndb_mgm_node_status
ndb_mgm_match_node_status(const char * status)1024 ndb_mgm_match_node_status(const char * status)
1025 {
1026   if(status == 0)
1027     return NDB_MGM_NODE_STATUS_UNKNOWN;
1028 
1029   for(int i = 0; i<no_of_status_values; i++)
1030     if(strcmp(status, status_values[i].str) == 0)
1031       return status_values[i].value;
1032 
1033   return NDB_MGM_NODE_STATUS_UNKNOWN;
1034 }
1035 
1036 extern "C"
1037 const char *
ndb_mgm_get_node_status_string(enum ndb_mgm_node_status status)1038 ndb_mgm_get_node_status_string(enum ndb_mgm_node_status status)
1039 {
1040   int i;
1041   for(i = 0; i<no_of_status_values; i++)
1042     if(status_values[i].value == status)
1043       return status_values[i].str;
1044 
1045   for(i = 0; i<no_of_status_values; i++)
1046     if(status_values[i].value == NDB_MGM_NODE_STATUS_UNKNOWN)
1047       return status_values[i].str;
1048 
1049   return 0;
1050 }
1051 
1052 static int
status_ackumulate(struct ndb_mgm_node_state * state,const char * field,const char * value)1053 status_ackumulate(struct ndb_mgm_node_state * state,
1054 		  const char * field,
1055 		  const char * value)
1056 {
1057   if(strcmp("type", field) == 0){
1058     state->node_type = ndb_mgm_match_node_type(value);
1059   } else if(strcmp("status", field) == 0){
1060     state->node_status = ndb_mgm_match_node_status(value);
1061   } else if(strcmp("startphase", field) == 0){
1062     state->start_phase = atoi(value);
1063   } else if(strcmp("dynamic_id", field) == 0){
1064     state->dynamic_id = atoi(value);
1065   } else if(strcmp("node_group", field) == 0){
1066     state->node_group = atoi(value);
1067   } else if(strcmp("version", field) == 0){
1068     state->version = atoi(value);
1069   } else if(strcmp("mysql_version", field) == 0){
1070     state->mysql_version = atoi(value);
1071   } else if(strcmp("connect_count", field) == 0){
1072     state->connect_count = atoi(value);
1073   } else if(strcmp("address", field) == 0){
1074     strncpy(state->connect_address, value, sizeof(state->connect_address));
1075     state->connect_address[sizeof(state->connect_address)-1]= 0;
1076   } else if(strcmp("is_single_user", field) == 0){
1077     state->is_single_user = atoi(value);
1078   } else {
1079     ndbout_c("Unknown field: %s", field);
1080   }
1081   return 0;
1082 }
1083 
1084 /**
1085  * Compare function for qsort() that sorts ndb_mgm_node_state in
1086  * node_id order
1087  */
1088 static int
cmp_state(const void * _a,const void * _b)1089 cmp_state(const void *_a, const void *_b)
1090 {
1091   struct ndb_mgm_node_state *a, *b;
1092 
1093   a = (struct ndb_mgm_node_state *)_a;
1094   b = (struct ndb_mgm_node_state *)_b;
1095 
1096   if (a->node_id > b->node_id)
1097     return 1;
1098   return -1;
1099 }
1100 
1101 extern "C"
1102 struct ndb_mgm_cluster_state *
ndb_mgm_get_status(NdbMgmHandle handle)1103 ndb_mgm_get_status(NdbMgmHandle handle)
1104 {
1105   return ndb_mgm_get_status2(handle, 0);
1106 }
1107 
1108 extern "C"
1109 struct ndb_mgm_cluster_state *
ndb_mgm_get_status2(NdbMgmHandle handle,const enum ndb_mgm_node_type types[])1110 ndb_mgm_get_status2(NdbMgmHandle handle, const enum ndb_mgm_node_type types[])
1111 {
1112   DBUG_ENTER("ndb_mgm_get_status2");
1113   CHECK_HANDLE(handle, NULL);
1114   SET_ERROR(handle, NDB_MGM_NO_ERROR, "Executing: ndb_mgm_get_status");
1115   CHECK_CONNECTED(handle, NULL);
1116 
1117   if (!get_mgmd_version(handle))
1118     DBUG_RETURN(NULL);
1119 
1120   char typestring[1024];
1121   typestring[0] = 0;
1122   if (types != 0)
1123   {
1124     int pos = 0;
1125     for (Uint32 i = 0; types[i] != NDB_MGM_NODE_TYPE_UNKNOWN; i++)
1126     {
1127       if (int(types[i]) < NDB_MGM_NODE_TYPE_MIN ||
1128           int(types[i]) > NDB_MGM_NODE_TYPE_MAX)
1129       {
1130         SET_ERROR(handle, EINVAL,
1131                   "Incorrect node type for ndb_mgm_get_status2");
1132         DBUG_RETURN(0);
1133       }
1134       /**
1135        * Check for duplicates
1136        */
1137       for (Int32 j = i - 1; j >= 0; j--)
1138       {
1139         if (types[i] == types[j])
1140         {
1141           SET_ERROR(handle, EINVAL,
1142                     "Duplicate types for ndb_mgm_get_status2");
1143           DBUG_RETURN(0);
1144         }
1145       }
1146 
1147       int left = sizeof(typestring) - pos;
1148       int len = BaseString::snprintf(typestring+pos, left, "%s ",
1149                                      ndb_mgm_get_node_type_string(types[i]));
1150 
1151       if (len >= left)
1152       {
1153         SET_ERROR(handle, EINVAL,
1154                   "Out of memory for type-string for ndb_mgm_get_status2");
1155         DBUG_RETURN(0);
1156       }
1157       pos += len;
1158     }
1159   }
1160 
1161   SocketOutputStream out(handle->socket, handle->timeout);
1162   SocketInputStream in(handle->socket, handle->timeout);
1163 
1164   const char *get_status_str = "get status";
1165   out.println("%s", get_status_str);
1166   if (types)
1167   {
1168     out.println("types: %s", typestring);
1169   }
1170   out.println("%s", "");
1171 
1172   CHECK_TIMEDOUT_RET(handle, in, out, NULL, get_status_str);
1173 
1174   char buf[1024];
1175   if(!in.gets(buf, sizeof(buf)))
1176   {
1177     CHECK_TIMEDOUT_RET(handle, in, out, NULL, get_status_str);
1178     SET_ERROR(handle, NDB_MGM_ILLEGAL_SERVER_REPLY, "Probably disconnected");
1179     DBUG_RETURN(NULL);
1180   }
1181   if(strcmp("node status\n", buf) != 0) {
1182     CHECK_TIMEDOUT_RET(handle, in, out, NULL, get_status_str);
1183     ndbout << in.timedout() << " " << out.timedout() << buf << endl;
1184     SET_ERROR(handle, NDB_MGM_ILLEGAL_NODE_STATUS, buf);
1185     DBUG_RETURN(NULL);
1186   }
1187   if(!in.gets(buf, sizeof(buf)))
1188   {
1189     CHECK_TIMEDOUT_RET(handle, in, out, NULL, get_status_str);
1190     SET_ERROR(handle, NDB_MGM_ILLEGAL_SERVER_REPLY, "Probably disconnected");
1191     DBUG_RETURN(NULL);
1192   }
1193 
1194   BaseString tmp(buf);
1195   Vector<BaseString> split;
1196   tmp.split(split, ":");
1197   if(split.size() != 2){
1198     CHECK_TIMEDOUT_RET(handle, in, out, NULL, get_status_str);
1199     SET_ERROR(handle, NDB_MGM_ILLEGAL_NODE_STATUS, buf);
1200     DBUG_RETURN(NULL);
1201   }
1202 
1203   if(!(split[0].trim() == "nodes")){
1204     SET_ERROR(handle, NDB_MGM_ILLEGAL_NODE_STATUS, buf);
1205     DBUG_RETURN(NULL);
1206   }
1207 
1208   const int noOfNodes = atoi(split[1].c_str());
1209 
1210   ndb_mgm_cluster_state *state = (ndb_mgm_cluster_state*)
1211     malloc(sizeof(ndb_mgm_cluster_state)+
1212 	   noOfNodes*(sizeof(ndb_mgm_node_state)+sizeof("000.000.000.000#")));
1213 
1214   if(!state)
1215   {
1216     SET_ERROR(handle, NDB_MGM_OUT_OF_MEMORY,
1217               "Allocating ndb_mgm_cluster_state");
1218     DBUG_RETURN(NULL);
1219   }
1220 
1221   state->no_of_nodes= noOfNodes;
1222   ndb_mgm_node_state * ptr = &state->node_states[0];
1223   int nodeId = 0;
1224   int i;
1225   for (i= 0; i < noOfNodes; i++) {
1226     state->node_states[i].connect_address[0]= 0;
1227     state->node_states[i].is_single_user = 0;
1228   }
1229   i = -1; ptr--;
1230   for(; i<noOfNodes; ){
1231     if(!in.gets(buf, sizeof(buf)))
1232     {
1233       free(state);
1234       if(in.timedout() || out.timedout())
1235         SET_ERROR(handle, ETIMEDOUT,
1236                   "Time out talking to management server");
1237       else
1238         SET_ERROR(handle, NDB_MGM_ILLEGAL_SERVER_REPLY,
1239                   "Probably disconnected");
1240       DBUG_RETURN(NULL);
1241     }
1242     tmp.assign(buf);
1243 
1244     if(tmp.trim() == ""){
1245       break;
1246     }
1247 
1248     Vector<BaseString> split2;
1249     tmp.split(split2, ":.", 4);
1250     if(split2.size() != 4)
1251       break;
1252 
1253     const int id = atoi(split2[1].c_str());
1254     if(id != nodeId){
1255       ptr++;
1256       i++;
1257       nodeId = id;
1258       ptr->node_id = id;
1259     }
1260 
1261     split2[3].trim(" \t\n");
1262 
1263     if(status_ackumulate(ptr,split2[2].c_str(), split2[3].c_str()) != 0) {
1264       break;
1265     }
1266   }
1267 
1268   if(i+1 != noOfNodes){
1269     free(state);
1270     CHECK_TIMEDOUT_RET(handle, in, out, NULL, get_status_str);
1271     SET_ERROR(handle, NDB_MGM_ILLEGAL_NODE_STATUS, "Node count mismatch");
1272     DBUG_RETURN(NULL);
1273   }
1274 
1275   qsort(state->node_states, state->no_of_nodes, sizeof(state->node_states[0]),
1276 	cmp_state);
1277   DBUG_RETURN(state);
1278 }
1279 
1280 extern "C"
1281 int
ndb_mgm_enter_single_user(NdbMgmHandle handle,unsigned int nodeId,struct ndb_mgm_reply *)1282 ndb_mgm_enter_single_user(NdbMgmHandle handle,
1283 			  unsigned int nodeId,
1284 			  struct ndb_mgm_reply* /*reply*/)
1285 {
1286   DBUG_ENTER("ndb_mgm_enter_single_user");
1287   CHECK_HANDLE(handle, -1);
1288   SET_ERROR(handle, NDB_MGM_NO_ERROR, "Executing: ndb_mgm_enter_single_user");
1289   const ParserRow<ParserDummy> enter_single_reply[] = {
1290     MGM_CMD("enter single user reply", NULL, ""),
1291     MGM_ARG("result", String, Mandatory, "Error message"),
1292     MGM_END()
1293   };
1294   CHECK_CONNECTED(handle, -1);
1295 
1296   Properties args;
1297   args.put("nodeId", nodeId);
1298   const Properties *reply;
1299   reply = ndb_mgm_call(handle, enter_single_reply, "enter single user", &args);
1300   CHECK_REPLY(handle, reply, -1);
1301 
1302   BaseString result;
1303   reply->get("result", result);
1304   if(strcmp(result.c_str(), "Ok") != 0) {
1305     SET_ERROR(handle, NDB_MGM_COULD_NOT_ENTER_SINGLE_USER_MODE,
1306 	      result.c_str());
1307     delete reply;
1308     DBUG_RETURN(-1);
1309   }
1310 
1311   delete reply;
1312   DBUG_RETURN(0);
1313 }
1314 
1315 
1316 extern "C"
1317 int
ndb_mgm_exit_single_user(NdbMgmHandle handle,struct ndb_mgm_reply *)1318 ndb_mgm_exit_single_user(NdbMgmHandle handle, struct ndb_mgm_reply* /*reply*/)
1319 {
1320   DBUG_ENTER("ndb_mgm_exit_single_user");
1321   CHECK_HANDLE(handle, -1);
1322   SET_ERROR(handle, NDB_MGM_NO_ERROR, "Executing: ndb_mgm_exit_single_user");
1323   const ParserRow<ParserDummy> exit_single_reply[] = {
1324     MGM_CMD("exit single user reply", NULL, ""),
1325     MGM_ARG("result", String, Mandatory, "Error message"),
1326     MGM_END()
1327   };
1328   CHECK_CONNECTED(handle, -1);
1329 
1330   const Properties *reply;
1331   reply = ndb_mgm_call(handle, exit_single_reply, "exit single user", 0);
1332   CHECK_REPLY(handle, reply, -1);
1333 
1334   const char * buf;
1335   reply->get("result", &buf);
1336   if(strcmp(buf,"Ok")!=0) {
1337     SET_ERROR(handle, NDB_MGM_COULD_NOT_EXIT_SINGLE_USER_MODE, buf);
1338     delete reply;
1339     DBUG_RETURN(-1);
1340   }
1341 
1342   delete reply;
1343   DBUG_RETURN(0);
1344 }
1345 
1346 extern "C"
1347 int
ndb_mgm_stop(NdbMgmHandle handle,int no_of_nodes,const int * node_list)1348 ndb_mgm_stop(NdbMgmHandle handle, int no_of_nodes, const int * node_list)
1349 {
1350   return ndb_mgm_stop2(handle, no_of_nodes, node_list, 0);
1351 }
1352 
1353 extern "C"
1354 int
ndb_mgm_stop2(NdbMgmHandle handle,int no_of_nodes,const int * node_list,int abort)1355 ndb_mgm_stop2(NdbMgmHandle handle, int no_of_nodes, const int * node_list,
1356 	      int abort)
1357 {
1358   int disconnect;
1359   return ndb_mgm_stop3(handle, no_of_nodes, node_list, abort, &disconnect);
1360 }
1361 
1362 extern "C"
1363 int
ndb_mgm_stop3(NdbMgmHandle handle,int no_of_nodes,const int * node_list,int abort,int * disconnect)1364 ndb_mgm_stop3(NdbMgmHandle handle, int no_of_nodes, const int * node_list,
1365 	      int abort, int *disconnect)
1366 {
1367   return ndb_mgm_stop4(handle, no_of_nodes, node_list, abort,
1368                        false, disconnect);
1369 }
1370 
1371 extern "C"
1372 int
ndb_mgm_stop4(NdbMgmHandle handle,int no_of_nodes,const int * node_list,int abort,int force,int * disconnect)1373 ndb_mgm_stop4(NdbMgmHandle handle, int no_of_nodes, const int * node_list,
1374 	      int abort, int force, int *disconnect)
1375 {
1376   DBUG_ENTER("ndb_mgm_stop4");
1377   CHECK_HANDLE(handle, -1);
1378   SET_ERROR(handle, NDB_MGM_NO_ERROR, "Executing: ndb_mgm_stop4");
1379   const ParserRow<ParserDummy> stop_reply_v1[] = {
1380     MGM_CMD("stop reply", NULL, ""),
1381     MGM_ARG("stopped", Int, Optional, "No of stopped nodes"),
1382     MGM_ARG("result", String, Mandatory, "Error message"),
1383     MGM_END()
1384   };
1385   const ParserRow<ParserDummy> stop_reply_v2[] = {
1386     MGM_CMD("stop reply", NULL, ""),
1387     MGM_ARG("stopped", Int, Optional, "No of stopped nodes"),
1388     MGM_ARG("result", String, Mandatory, "Error message"),
1389     MGM_ARG("disconnect", Int, Mandatory, "Need to disconnect"),
1390     MGM_END()
1391   };
1392 
1393   CHECK_CONNECTED(handle, -1);
1394 
1395   if (!get_mgmd_version(handle))
1396     DBUG_RETURN(-1);
1397 
1398   int use_v2= ((handle->mgmd_version_major==5)
1399     && (
1400         (handle->mgmd_version_minor==0 && handle->mgmd_version_build>=21)
1401         ||(handle->mgmd_version_minor==1 && handle->mgmd_version_build>=12)
1402         ||(handle->mgmd_version_minor>1)
1403         )
1404                )
1405     || (handle->mgmd_version_major>5);
1406 
1407   if(no_of_nodes < -1){
1408     SET_ERROR(handle, NDB_MGM_ILLEGAL_NUMBER_OF_NODES,
1409 	      "Negative number of nodes requested to stop");
1410     DBUG_RETURN(-1);
1411   }
1412 
1413   if(no_of_nodes <= 0){
1414     /**
1415      * All nodes should be stopped (all or just db)
1416      */
1417     Properties args;
1418     args.put("abort", abort);
1419     if(use_v2)
1420       args.put("stop", (no_of_nodes==-1)?"mgm,db":"db");
1421     // force has no effect, continue anyway for consistency
1422     const Properties *reply;
1423     if(use_v2)
1424       reply = ndb_mgm_call_slow(handle, stop_reply_v2, "stop all", &args);
1425     else
1426       reply = ndb_mgm_call_slow(handle, stop_reply_v1, "stop all", &args);
1427     CHECK_REPLY(handle, reply, -1);
1428 
1429     Uint32 stopped = 0;
1430     if(!reply->get("stopped", &stopped))
1431     {
1432       SET_ERROR(handle, NDB_MGM_STOP_FAILED,
1433 		"Could not get number of stopped nodes from mgm server");
1434       delete reply;
1435       DBUG_RETURN(-1);
1436     }
1437     if(use_v2)
1438       reply->get("disconnect", (Uint32*)disconnect);
1439     else
1440       *disconnect= 0;
1441     BaseString result;
1442     reply->get("result", result);
1443     if(strcmp(result.c_str(), "Ok") != 0) {
1444       SET_ERROR(handle, NDB_MGM_STOP_FAILED, result.c_str());
1445       delete reply;
1446       DBUG_RETURN(-1);
1447     }
1448     delete reply;
1449     DBUG_RETURN(stopped);
1450   }
1451 
1452   /**
1453    * A list of database nodes should be stopped
1454    */
1455   Properties args;
1456 
1457   BaseString node_list_str;
1458   node_list_str.assfmt("%d", node_list[0]);
1459   for(int node = 1; node < no_of_nodes; node++)
1460     node_list_str.appfmt(" %d", node_list[node]);
1461 
1462   args.put("node", node_list_str.c_str());
1463   args.put("abort", abort);
1464   if (check_version_new(handle->mgmd_version(),
1465                         NDB_MAKE_VERSION(7,1,8),
1466                         NDB_MAKE_VERSION(7,0,19),
1467                         0))
1468     args.put("force", force);
1469   else
1470     SET_ERROR(handle, NDB_MGM_STOP_FAILED,
1471 	      "The connected mgm server does not support 'stop --force'");
1472 
1473   const Properties *reply;
1474   if(use_v2)
1475     reply = ndb_mgm_call_slow(handle, stop_reply_v2, "stop v2", &args);
1476   else
1477     reply = ndb_mgm_call_slow(handle, stop_reply_v1, "stop", &args);
1478   CHECK_REPLY(handle, reply, -1);
1479 
1480   Uint32 stopped;
1481   if(!reply->get("stopped", &stopped))
1482   {
1483     SET_ERROR(handle, NDB_MGM_STOP_FAILED,
1484 	      "Could not get number of stopped nodes from mgm server");
1485     delete reply;
1486     DBUG_RETURN(-1);
1487   }
1488   if(use_v2)
1489     reply->get("disconnect", (Uint32*)disconnect);
1490   else
1491     *disconnect= 0;
1492   BaseString result;
1493   reply->get("result", result);
1494   if(strcmp(result.c_str(), "Ok") != 0) {
1495     SET_ERROR(handle, NDB_MGM_STOP_FAILED, result.c_str());
1496     delete reply;
1497     DBUG_RETURN(-1);
1498   }
1499   delete reply;
1500   DBUG_RETURN(stopped);
1501 }
1502 
1503 extern "C"
1504 int
ndb_mgm_restart(NdbMgmHandle handle,int no_of_nodes,const int * node_list)1505 ndb_mgm_restart(NdbMgmHandle handle, int no_of_nodes, const int *node_list)
1506 {
1507   return ndb_mgm_restart2(handle, no_of_nodes, node_list, 0, 0, 0);
1508 }
1509 
1510 extern "C"
1511 int
ndb_mgm_restart2(NdbMgmHandle handle,int no_of_nodes,const int * node_list,int initial,int nostart,int abort)1512 ndb_mgm_restart2(NdbMgmHandle handle, int no_of_nodes, const int * node_list,
1513 		 int initial, int nostart, int abort)
1514 {
1515   int disconnect;
1516 
1517   return ndb_mgm_restart3(handle, no_of_nodes, node_list, initial, nostart,
1518                           abort, &disconnect);
1519 }
1520 
1521 extern "C"
1522 int
ndb_mgm_restart3(NdbMgmHandle handle,int no_of_nodes,const int * node_list,int initial,int nostart,int abort,int * disconnect)1523 ndb_mgm_restart3(NdbMgmHandle handle, int no_of_nodes, const int * node_list,
1524 		 int initial, int nostart, int abort, int *disconnect)
1525 {
1526   return ndb_mgm_restart4(handle, no_of_nodes, node_list, initial,
1527                           nostart, abort, false, disconnect);
1528 }
1529 
1530 extern "C"
1531 int
ndb_mgm_restart4(NdbMgmHandle handle,int no_of_nodes,const int * node_list,int initial,int nostart,int abort,int force,int * disconnect)1532 ndb_mgm_restart4(NdbMgmHandle handle, int no_of_nodes, const int * node_list,
1533                  int initial, int nostart, int abort, int force,
1534                  int *disconnect)
1535 {
1536   DBUG_ENTER("ndb_mgm_restart");
1537   CHECK_HANDLE(handle, -1);
1538   SET_ERROR(handle, NDB_MGM_NO_ERROR, "Executing: ndb_mgm_restart4");
1539 
1540   const ParserRow<ParserDummy> restart_reply_v1[] = {
1541     MGM_CMD("restart reply", NULL, ""),
1542     MGM_ARG("result", String, Mandatory, "Error message"),
1543     MGM_ARG("restarted", Int, Optional, "No of restarted nodes"),
1544     MGM_END()
1545   };
1546   const ParserRow<ParserDummy> restart_reply_v2[] = {
1547     MGM_CMD("restart reply", NULL, ""),
1548     MGM_ARG("result", String, Mandatory, "Error message"),
1549     MGM_ARG("restarted", Int, Optional, "No of restarted nodes"),
1550     MGM_ARG("disconnect", Int, Optional, "Disconnect to apply"),
1551     MGM_END()
1552   };
1553 
1554   CHECK_CONNECTED(handle, -1);
1555 
1556   if (!get_mgmd_version(handle))
1557     DBUG_RETURN(-1);
1558 
1559   int use_v2= ((handle->mgmd_version_major==5)
1560     && (
1561         (handle->mgmd_version_minor==0 && handle->mgmd_version_build>=21)
1562         ||(handle->mgmd_version_minor==1 && handle->mgmd_version_build>=12)
1563         ||(handle->mgmd_version_minor>1)
1564         )
1565                )
1566     || (handle->mgmd_version_major>5);
1567 
1568   if(no_of_nodes < 0){
1569     SET_ERROR(handle, NDB_MGM_RESTART_FAILED,
1570 	      "Restart requested of negative number of nodes");
1571     DBUG_RETURN(-1);
1572   }
1573 
1574   if(no_of_nodes == 0) {
1575     Properties args;
1576     args.put("abort", abort);
1577     args.put("initialstart", initial);
1578     args.put("nostart", nostart);
1579     // force has no effect, continue anyway for consistency
1580     const Properties *reply =
1581       ndb_mgm_call_slow(handle, restart_reply_v1, "restart all", &args);
1582     CHECK_REPLY(handle, reply, -1);
1583 
1584     BaseString result;
1585     reply->get("result", result);
1586     if(strcmp(result.c_str(), "Ok") != 0) {
1587       SET_ERROR(handle, NDB_MGM_RESTART_FAILED, result.c_str());
1588       delete reply;
1589       DBUG_RETURN(-1);
1590     }
1591 
1592     Uint32 restarted;
1593     if(!reply->get("restarted", &restarted)){
1594       SET_ERROR(handle, NDB_MGM_RESTART_FAILED,
1595 		"Could not get restarted number of nodes from mgm server");
1596       delete reply;
1597       DBUG_RETURN(-1);
1598     }
1599     delete reply;
1600     DBUG_RETURN(restarted);
1601   }
1602 
1603   BaseString node_list_str;
1604   node_list_str.assfmt("%d", node_list[0]);
1605   for(int node = 1; node < no_of_nodes; node++)
1606     node_list_str.appfmt(" %d", node_list[node]);
1607 
1608   Properties args;
1609 
1610   args.put("node", node_list_str.c_str());
1611   args.put("abort", abort);
1612   args.put("initialstart", initial);
1613   args.put("nostart", nostart);
1614 
1615   if (check_version_new(handle->mgmd_version(),
1616                         NDB_MAKE_VERSION(7,1,8),
1617                         NDB_MAKE_VERSION(7,0,19),
1618                         0))
1619     args.put("force", force);
1620   else
1621     SET_ERROR(handle, NDB_MGM_RESTART_FAILED,
1622 	      "The connected mgm server does not support 'restart --force'");
1623 
1624   const Properties *reply;
1625   if(use_v2)
1626     reply = ndb_mgm_call_slow(handle, restart_reply_v2,
1627                               "restart node v2", &args);
1628   else
1629     reply = ndb_mgm_call_slow(handle, restart_reply_v1,
1630                               "restart node", &args);
1631   CHECK_REPLY(handle, reply, -1);
1632 
1633   BaseString result;
1634   reply->get("result", result);
1635   if(strcmp(result.c_str(), "Ok") != 0) {
1636     SET_ERROR(handle, NDB_MGM_RESTART_FAILED, result.c_str());
1637     delete reply;
1638     DBUG_RETURN(-1);
1639   }
1640   Uint32 restarted;
1641   reply->get("restarted", &restarted);
1642   if(use_v2)
1643     reply->get("disconnect", (Uint32*)disconnect);
1644   else
1645     *disconnect= 0;
1646   delete reply;
1647   DBUG_RETURN(restarted);
1648 }
1649 
1650 static const char *clusterlog_severity_names[]=
1651   { "enabled", "debug", "info", "warning", "error", "critical", "alert" };
1652 
1653 struct ndb_mgm_event_severities
1654 {
1655   const char* name;
1656   enum ndb_mgm_event_severity severity;
1657 } clusterlog_severities[] = {
1658   { clusterlog_severity_names[0], NDB_MGM_EVENT_SEVERITY_ON },
1659   { clusterlog_severity_names[1], NDB_MGM_EVENT_SEVERITY_DEBUG },
1660   { clusterlog_severity_names[2], NDB_MGM_EVENT_SEVERITY_INFO },
1661   { clusterlog_severity_names[3], NDB_MGM_EVENT_SEVERITY_WARNING },
1662   { clusterlog_severity_names[4], NDB_MGM_EVENT_SEVERITY_ERROR },
1663   { clusterlog_severity_names[5], NDB_MGM_EVENT_SEVERITY_CRITICAL },
1664   { clusterlog_severity_names[6], NDB_MGM_EVENT_SEVERITY_ALERT },
1665   { "all",                        NDB_MGM_EVENT_SEVERITY_ALL },
1666   { 0,                            NDB_MGM_ILLEGAL_EVENT_SEVERITY },
1667 };
1668 
1669 extern "C"
1670 ndb_mgm_event_severity
ndb_mgm_match_event_severity(const char * name)1671 ndb_mgm_match_event_severity(const char * name)
1672 {
1673   if(name == 0)
1674     return NDB_MGM_ILLEGAL_EVENT_SEVERITY;
1675 
1676   for(int i = 0; clusterlog_severities[i].name !=0 ; i++)
1677     if(native_strcasecmp(name, clusterlog_severities[i].name) == 0)
1678       return clusterlog_severities[i].severity;
1679 
1680   return NDB_MGM_ILLEGAL_EVENT_SEVERITY;
1681 }
1682 
1683 extern "C"
1684 const char *
ndb_mgm_get_event_severity_string(enum ndb_mgm_event_severity severity)1685 ndb_mgm_get_event_severity_string(enum ndb_mgm_event_severity severity)
1686 {
1687   int i= (int)severity;
1688   if (i >= 0 && i < (int)NDB_MGM_EVENT_SEVERITY_ALL)
1689     return clusterlog_severity_names[i];
1690   for(i = (int)NDB_MGM_EVENT_SEVERITY_ALL; clusterlog_severities[i].name != 0; i++)
1691     if(clusterlog_severities[i].severity == severity)
1692       return clusterlog_severities[i].name;
1693   return 0;
1694 }
1695 
1696 extern "C"
1697 int
ndb_mgm_get_clusterlog_severity_filter(NdbMgmHandle handle,struct ndb_mgm_severity * severity,unsigned int severity_size)1698 ndb_mgm_get_clusterlog_severity_filter(NdbMgmHandle handle,
1699 				       struct ndb_mgm_severity* severity,
1700 				       unsigned int severity_size)
1701 {
1702   DBUG_ENTER("ndb_mgm_get_clusterlog_severity_filter");
1703   CHECK_HANDLE(handle, -1);
1704   SET_ERROR(handle, NDB_MGM_NO_ERROR, "Executing: ndb_mgm_get_clusterlog_severity_filter");
1705   const ParserRow<ParserDummy> getinfo_reply[] = {
1706     MGM_CMD("clusterlog", NULL, ""),
1707     MGM_ARG(clusterlog_severity_names[0], Int, Mandatory, ""),
1708     MGM_ARG(clusterlog_severity_names[1], Int, Mandatory, ""),
1709     MGM_ARG(clusterlog_severity_names[2], Int, Mandatory, ""),
1710     MGM_ARG(clusterlog_severity_names[3], Int, Mandatory, ""),
1711     MGM_ARG(clusterlog_severity_names[4], Int, Mandatory, ""),
1712     MGM_ARG(clusterlog_severity_names[5], Int, Mandatory, ""),
1713     MGM_ARG(clusterlog_severity_names[6], Int, Mandatory, ""),
1714     MGM_END()
1715   };
1716   CHECK_CONNECTED(handle, -1);
1717 
1718   Properties args;
1719   const Properties *reply;
1720   reply = ndb_mgm_call(handle, getinfo_reply, "get info clusterlog", &args);
1721   CHECK_REPLY(handle, reply, -1);
1722 
1723   for(unsigned int i=0; i < severity_size; i++) {
1724     reply->get(clusterlog_severity_names[severity[i].category], &severity[i].value);
1725   }
1726   delete reply;
1727   DBUG_RETURN(severity_size);
1728 }
1729 
1730 extern "C"
1731 const unsigned int *
ndb_mgm_get_clusterlog_severity_filter_old(NdbMgmHandle handle)1732 ndb_mgm_get_clusterlog_severity_filter_old(NdbMgmHandle handle)
1733 {
1734   DBUG_ENTER("ndb_mgm_get_clusterlog_severity_filter_old");
1735   CHECK_HANDLE(handle, NULL);
1736   SET_ERROR(handle, NDB_MGM_NO_ERROR, "Executing: ndb_mgm_get_clusterlog_severity_filter");
1737   static unsigned int enabled[(int)NDB_MGM_EVENT_SEVERITY_ALL]=
1738     {0,0,0,0,0,0,0};
1739   const ParserRow<ParserDummy> getinfo_reply[] = {
1740     MGM_CMD("clusterlog", NULL, ""),
1741     MGM_ARG(clusterlog_severity_names[0], Int, Mandatory, ""),
1742     MGM_ARG(clusterlog_severity_names[1], Int, Mandatory, ""),
1743     MGM_ARG(clusterlog_severity_names[2], Int, Mandatory, ""),
1744     MGM_ARG(clusterlog_severity_names[3], Int, Mandatory, ""),
1745     MGM_ARG(clusterlog_severity_names[4], Int, Mandatory, ""),
1746     MGM_ARG(clusterlog_severity_names[5], Int, Mandatory, ""),
1747     MGM_ARG(clusterlog_severity_names[6], Int, Mandatory, ""),
1748     MGM_END()
1749   };
1750   CHECK_CONNECTED(handle, NULL);
1751 
1752   Properties args;
1753   const Properties *reply;
1754   reply = ndb_mgm_call(handle, getinfo_reply, "get info clusterlog", &args);
1755   CHECK_REPLY(handle, reply, NULL);
1756 
1757   for(int i=0; i < (int)NDB_MGM_EVENT_SEVERITY_ALL; i++) {
1758     reply->get(clusterlog_severity_names[i], &enabled[i]);
1759   }
1760   delete reply;
1761   DBUG_RETURN(enabled);
1762 }
1763 
1764 extern "C"
1765 int
ndb_mgm_set_clusterlog_severity_filter(NdbMgmHandle handle,enum ndb_mgm_event_severity severity,int enable,struct ndb_mgm_reply *)1766 ndb_mgm_set_clusterlog_severity_filter(NdbMgmHandle handle,
1767 				       enum ndb_mgm_event_severity severity,
1768 				       int enable,
1769 				       struct ndb_mgm_reply* /*reply*/)
1770 {
1771   DBUG_ENTER("ndb_mgm_set_clusterlog_severity_filter");
1772   CHECK_HANDLE(handle, -1);
1773   SET_ERROR(handle, NDB_MGM_NO_ERROR,
1774 	    "Executing: ndb_mgm_set_clusterlog_severity_filter");
1775   const ParserRow<ParserDummy> filter_reply[] = {
1776     MGM_CMD("set logfilter reply", NULL, ""),
1777     MGM_ARG("result", String, Mandatory, "Error message"),
1778     MGM_END()
1779   };
1780   int retval = -1;
1781   CHECK_CONNECTED(handle, -1);
1782 
1783   Properties args;
1784   args.put("level", severity);
1785   args.put("enable", enable);
1786 
1787   const Properties *reply;
1788   reply = ndb_mgm_call(handle, filter_reply, "set logfilter", &args);
1789   CHECK_REPLY(handle, reply, retval);
1790 
1791   BaseString result;
1792   reply->get("result", result);
1793 
1794   if (strcmp(result.c_str(), "1") == 0)
1795     retval = 1;
1796   else if (strcmp(result.c_str(), "0") == 0)
1797     retval = 0;
1798   else
1799   {
1800     SET_ERROR(handle, EINVAL, result.c_str());
1801   }
1802   delete reply;
1803   DBUG_RETURN(retval);
1804 }
1805 
1806 struct ndb_mgm_event_categories
1807 {
1808   const char* name;
1809   enum ndb_mgm_event_category category;
1810 } categories[] = {
1811   { "STARTUP", NDB_MGM_EVENT_CATEGORY_STARTUP },
1812   { "SHUTDOWN", NDB_MGM_EVENT_CATEGORY_SHUTDOWN },
1813   { "STATISTICS", NDB_MGM_EVENT_CATEGORY_STATISTIC },
1814   { "NODERESTART", NDB_MGM_EVENT_CATEGORY_NODE_RESTART },
1815   { "CONNECTION", NDB_MGM_EVENT_CATEGORY_CONNECTION },
1816   { "CHECKPOINT", NDB_MGM_EVENT_CATEGORY_CHECKPOINT },
1817   { "DEBUG", NDB_MGM_EVENT_CATEGORY_DEBUG },
1818   { "INFO", NDB_MGM_EVENT_CATEGORY_INFO },
1819   { "ERROR", NDB_MGM_EVENT_CATEGORY_ERROR },
1820   { "BACKUP", NDB_MGM_EVENT_CATEGORY_BACKUP },
1821   { "CONGESTION", NDB_MGM_EVENT_CATEGORY_CONGESTION },
1822   { "SCHEMA", NDB_MGM_EVENT_CATEGORY_SCHEMA },
1823   { 0, NDB_MGM_ILLEGAL_EVENT_CATEGORY }
1824 };
1825 
1826 extern "C"
1827 ndb_mgm_event_category
ndb_mgm_match_event_category(const char * status)1828 ndb_mgm_match_event_category(const char * status)
1829 {
1830   if(status == 0)
1831     return NDB_MGM_ILLEGAL_EVENT_CATEGORY;
1832 
1833   for(int i = 0; categories[i].name !=0 ; i++)
1834     if(strcmp(status, categories[i].name) == 0)
1835       return categories[i].category;
1836 
1837   return NDB_MGM_ILLEGAL_EVENT_CATEGORY;
1838 }
1839 
1840 extern "C"
1841 const char *
ndb_mgm_get_event_category_string(enum ndb_mgm_event_category status)1842 ndb_mgm_get_event_category_string(enum ndb_mgm_event_category status)
1843 {
1844   int i;
1845   for(i = 0; categories[i].name != 0; i++)
1846     if(categories[i].category == status)
1847       return categories[i].name;
1848 
1849   return 0;
1850 }
1851 
1852 static const char *clusterlog_names[]=
1853   { "startup", "shutdown", "statistics", "checkpoint", "noderestart", "connection", "info", "warning", "error", "congestion", "debug", "backup" };
1854 
1855 extern "C"
1856 int
ndb_mgm_get_clusterlog_loglevel(NdbMgmHandle handle,struct ndb_mgm_loglevel * loglevel,unsigned int loglevel_size)1857 ndb_mgm_get_clusterlog_loglevel(NdbMgmHandle handle,
1858 				struct ndb_mgm_loglevel* loglevel,
1859 				unsigned int loglevel_size)
1860 {
1861   DBUG_ENTER("ndb_mgm_get_clusterlog_loglevel");
1862   CHECK_HANDLE(handle, -1);
1863   SET_ERROR(handle, NDB_MGM_NO_ERROR, "Executing: ndb_mgm_get_clusterlog_loglevel");
1864   int loglevel_count = loglevel_size;
1865   const ParserRow<ParserDummy> getloglevel_reply[] = {
1866     MGM_CMD("get cluster loglevel", NULL, ""),
1867     MGM_ARG(clusterlog_names[0], Int, Mandatory, ""),
1868     MGM_ARG(clusterlog_names[1], Int, Mandatory, ""),
1869     MGM_ARG(clusterlog_names[2], Int, Mandatory, ""),
1870     MGM_ARG(clusterlog_names[3], Int, Mandatory, ""),
1871     MGM_ARG(clusterlog_names[4], Int, Mandatory, ""),
1872     MGM_ARG(clusterlog_names[5], Int, Mandatory, ""),
1873     MGM_ARG(clusterlog_names[6], Int, Mandatory, ""),
1874     MGM_ARG(clusterlog_names[7], Int, Mandatory, ""),
1875     MGM_ARG(clusterlog_names[8], Int, Mandatory, ""),
1876     MGM_ARG(clusterlog_names[9], Int, Mandatory, ""),
1877     MGM_ARG(clusterlog_names[10], Int, Mandatory, ""),
1878     MGM_ARG(clusterlog_names[11], Int, Mandatory, ""),
1879     MGM_END()
1880   };
1881   CHECK_CONNECTED(handle, -1);
1882 
1883   Properties args;
1884   const Properties *reply;
1885   reply = ndb_mgm_call(handle, getloglevel_reply, "get cluster loglevel", &args);
1886   CHECK_REPLY(handle, reply, -1);
1887 
1888   for(int i=0; i < loglevel_count; i++) {
1889     reply->get(clusterlog_names[loglevel[i].category], &loglevel[i].value);
1890   }
1891   delete reply;
1892   DBUG_RETURN(loglevel_count);
1893 }
1894 
1895 extern "C"
1896 const unsigned int *
ndb_mgm_get_clusterlog_loglevel_old(NdbMgmHandle handle)1897 ndb_mgm_get_clusterlog_loglevel_old(NdbMgmHandle handle)
1898 {
1899   DBUG_ENTER("ndb_mgm_get_clusterlog_loglevel_old");
1900   CHECK_HANDLE(handle, NULL);
1901   SET_ERROR(handle, NDB_MGM_NO_ERROR, "Executing: ndb_mgm_get_clusterlog_loglevel");
1902   int loglevel_count = CFG_MAX_LOGLEVEL - CFG_MIN_LOGLEVEL + 1 ;
1903   static unsigned int loglevel[CFG_MAX_LOGLEVEL - CFG_MIN_LOGLEVEL + 1] = {0,0,0,0,0,0,0,0,0,0,0,0};
1904   const ParserRow<ParserDummy> getloglevel_reply[] = {
1905     MGM_CMD("get cluster loglevel", NULL, ""),
1906     MGM_ARG(clusterlog_names[0], Int, Mandatory, ""),
1907     MGM_ARG(clusterlog_names[1], Int, Mandatory, ""),
1908     MGM_ARG(clusterlog_names[2], Int, Mandatory, ""),
1909     MGM_ARG(clusterlog_names[3], Int, Mandatory, ""),
1910     MGM_ARG(clusterlog_names[4], Int, Mandatory, ""),
1911     MGM_ARG(clusterlog_names[5], Int, Mandatory, ""),
1912     MGM_ARG(clusterlog_names[6], Int, Mandatory, ""),
1913     MGM_ARG(clusterlog_names[7], Int, Mandatory, ""),
1914     MGM_ARG(clusterlog_names[8], Int, Mandatory, ""),
1915     MGM_ARG(clusterlog_names[9], Int, Mandatory, ""),
1916     MGM_ARG(clusterlog_names[10], Int, Mandatory, ""),
1917     MGM_ARG(clusterlog_names[11], Int, Mandatory, ""),
1918     MGM_END()
1919   };
1920   CHECK_CONNECTED(handle, NULL);
1921 
1922   Properties args;
1923   const Properties *reply;
1924   reply = ndb_mgm_call(handle, getloglevel_reply, "get cluster loglevel", &args);
1925   CHECK_REPLY(handle, reply, NULL);
1926 
1927   for(int i=0; i < loglevel_count; i++) {
1928     reply->get(clusterlog_names[i], &loglevel[i]);
1929   }
1930   delete reply;
1931   DBUG_RETURN(loglevel);
1932 }
1933 
1934 extern "C"
1935 int
ndb_mgm_set_clusterlog_loglevel(NdbMgmHandle handle,int nodeId,enum ndb_mgm_event_category cat,int level,struct ndb_mgm_reply *)1936 ndb_mgm_set_clusterlog_loglevel(NdbMgmHandle handle, int nodeId,
1937 				enum ndb_mgm_event_category cat,
1938 				int level,
1939 				struct ndb_mgm_reply* /*reply*/)
1940 {
1941   DBUG_ENTER("ndb_mgm_set_clusterlog_loglevel");
1942   CHECK_HANDLE(handle, -1);
1943   SET_ERROR(handle, NDB_MGM_NO_ERROR,
1944 	    "Executing: ndb_mgm_set_clusterlog_loglevel");
1945   const ParserRow<ParserDummy> clusterlog_reply[] = {
1946     MGM_CMD("set cluster loglevel reply", NULL, ""),
1947     MGM_ARG("result", String, Mandatory, "Error message"),
1948     MGM_END()
1949   };
1950   CHECK_CONNECTED(handle, -1);
1951 
1952   Properties args;
1953   args.put("node", nodeId);
1954   args.put("category", cat);
1955   args.put("level", level);
1956 
1957   const Properties *reply;
1958   reply = ndb_mgm_call(handle, clusterlog_reply,
1959 		       "set cluster loglevel", &args);
1960   CHECK_REPLY(handle, reply, -1);
1961 
1962   DBUG_PRINT("enter",("node=%d, category=%d, level=%d", nodeId, cat, level));
1963 
1964   BaseString result;
1965   reply->get("result", result);
1966   if(strcmp(result.c_str(), "Ok") != 0) {
1967     SET_ERROR(handle, EINVAL, result.c_str());
1968     delete reply;
1969     DBUG_RETURN(-1);
1970   }
1971   delete reply;
1972   DBUG_RETURN(0);
1973 }
1974 
1975 extern "C"
1976 int
ndb_mgm_set_loglevel_node(NdbMgmHandle handle,int nodeId,enum ndb_mgm_event_category category,int level,struct ndb_mgm_reply *)1977 ndb_mgm_set_loglevel_node(NdbMgmHandle handle, int nodeId,
1978 			  enum ndb_mgm_event_category category,
1979 			  int level,
1980 			  struct ndb_mgm_reply* /*reply*/)
1981 {
1982   DBUG_ENTER("ndb_mgm_set_loglevel_node");
1983   CHECK_HANDLE(handle, -1);
1984   SET_ERROR(handle, NDB_MGM_NO_ERROR, "Executing: ndb_mgm_set_loglevel_node");
1985   const ParserRow<ParserDummy> loglevel_reply[] = {
1986     MGM_CMD("set loglevel reply", NULL, ""),
1987     MGM_ARG("result", String, Mandatory, "Error message"),
1988     MGM_END()
1989   };
1990   CHECK_CONNECTED(handle, -1);
1991 
1992   Properties args;
1993   args.put("node", nodeId);
1994   args.put("category", category);
1995   args.put("level", level);
1996   const Properties *reply;
1997   reply = ndb_mgm_call(handle, loglevel_reply, "set loglevel", &args);
1998   CHECK_REPLY(handle, reply, -1);
1999 
2000   BaseString result;
2001   reply->get("result", result);
2002   if(strcmp(result.c_str(), "Ok") != 0) {
2003     SET_ERROR(handle, EINVAL, result.c_str());
2004     delete reply;
2005     DBUG_RETURN(-1);
2006   }
2007 
2008   delete reply;
2009   DBUG_RETURN(0);
2010 }
2011 
2012 int
ndb_mgm_listen_event_internal(NdbMgmHandle handle,const int filter[],int parsable,NDB_SOCKET_TYPE * sock)2013 ndb_mgm_listen_event_internal(NdbMgmHandle handle, const int filter[],
2014 			      int parsable, NDB_SOCKET_TYPE* sock)
2015 {
2016   DBUG_ENTER("ndb_mgm_listen_event_internal");
2017   CHECK_HANDLE(handle, -1);
2018   SET_ERROR(handle, NDB_MGM_NO_ERROR, "Executing: ndb_mgm_listen_event");
2019   const ParserRow<ParserDummy> stat_reply[] = {
2020     MGM_CMD("listen event", NULL, ""),
2021     MGM_ARG("result", Int, Mandatory, "Error message"),
2022     MGM_ARG("msg", String, Optional, "Error message"),
2023     MGM_END()
2024   };
2025 
2026   const char *hostname= ndb_mgm_get_connected_host(handle);
2027   int port= ndb_mgm_get_connected_port(handle);
2028   const char *bind_address= ndb_mgm_get_connected_bind_address(handle);
2029   SocketClient s;
2030   s.set_connect_timeout(handle->timeout);
2031   if (!s.init())
2032   {
2033     fprintf(handle->errstream, "Unable to create socket");
2034     setError(handle, NDB_MGM_COULD_NOT_CONNECT_TO_SOCKET, __LINE__,
2035              "Unable to create socket");
2036     DBUG_RETURN(-1);
2037   }
2038   if (bind_address)
2039   {
2040     int err;
2041     if ((err = s.bind(bind_address, 0)) != 0)
2042     {
2043       fprintf(handle->errstream,
2044               "Unable to bind local address '%s:0' err: %d, errno: %d, "
2045               "while trying to connect with connect string: '%s:%d'\n",
2046               bind_address, err, errno, hostname, port);
2047       setError(handle, NDB_MGM_BIND_ADDRESS, __LINE__,
2048                "Unable to bind local address '%s:0' errno: %d, errno: %d, "
2049                "while trying to connect with connect string: '%s:%d'\n",
2050                bind_address, err, errno, hostname, port);
2051       DBUG_RETURN(-1);
2052     }
2053   }
2054   const NDB_SOCKET_TYPE sockfd = s.connect(hostname, port);
2055   if (!ndb_socket_valid(sockfd))
2056   {
2057     setError(handle, NDB_MGM_COULD_NOT_CONNECT_TO_SOCKET, __LINE__,
2058 	     "Unable to connect to");
2059     DBUG_RETURN(-2);
2060   }
2061 
2062   Properties args;
2063 
2064   if (parsable)
2065     args.put("parsable", parsable);
2066   {
2067     BaseString tmp;
2068     for(int i = 0; filter[i] != 0; i += 2){
2069       tmp.appfmt("%d=%d ", filter[i+1], filter[i]);
2070     }
2071     args.put("filter", tmp.c_str());
2072   }
2073 
2074   NDB_SOCKET_TYPE tmp = handle->socket;
2075   handle->socket = sockfd;
2076 
2077   const Properties *reply;
2078   reply = ndb_mgm_call(handle, stat_reply, "listen event", &args);
2079 
2080   handle->socket = tmp;
2081 
2082   if(reply == NULL) {
2083     ndb_socket_close(sockfd);
2084     CHECK_REPLY(handle, reply, -1);
2085   }
2086   delete reply;
2087 
2088   *sock= sockfd;
2089   DBUG_RETURN(1);
2090 }
2091 
2092 /*
2093   This API function causes ugly code in mgmapi - it returns native socket
2094   type as we can't force everybody to use our abstraction or break current
2095   applications.
2096  */
2097 extern "C"
2098 ndb_native_socket_t
ndb_mgm_listen_event(NdbMgmHandle handle,const int filter[])2099 ndb_mgm_listen_event(NdbMgmHandle handle, const int filter[])
2100 {
2101   NDB_SOCKET_TYPE s;
2102   if(ndb_mgm_listen_event_internal(handle,filter,0,&s)<0)
2103     ndb_socket_invalidate(&s);
2104   return ndb_socket_get_native(s);
2105 }
2106 
2107 extern "C"
2108 int
ndb_mgm_dump_state(NdbMgmHandle handle,int nodeId,const int * _args,int _num_args,struct ndb_mgm_reply *)2109 ndb_mgm_dump_state(NdbMgmHandle handle, int nodeId, const int * _args,
2110 		   int _num_args, struct ndb_mgm_reply* /* reply */)
2111 {
2112   DBUG_ENTER("ndb_mgm_dump_state");
2113   CHECK_HANDLE(handle, -1);
2114   SET_ERROR(handle, NDB_MGM_NO_ERROR, "Executing: ndb_mgm_dump_state");
2115   const ParserRow<ParserDummy> dump_state_reply[] = {
2116     MGM_CMD("dump state reply", NULL, ""),
2117     MGM_ARG("result", String, Mandatory, "Error message"),
2118     MGM_END()
2119   };
2120   CHECK_CONNECTED(handle, -1);
2121 
2122   char buf[256];
2123   buf[0] = 0;
2124   for (int i = 0; i < _num_args; i++){
2125     unsigned n = (unsigned)strlen(buf);
2126     if (n + 20 > sizeof(buf)) {
2127       SET_ERROR(handle, NDB_MGM_USAGE_ERROR, "arguments too long");
2128       DBUG_RETURN(-1);
2129     }
2130     sprintf(buf + n, "%s%d", i ? " " : "", _args[i]);
2131   }
2132 
2133   Properties args;
2134   args.put("node", nodeId);
2135   args.put("args", buf);
2136 
2137   const Properties *prop;
2138   prop = ndb_mgm_call(handle, dump_state_reply, "dump state", &args);
2139   CHECK_REPLY(handle, prop, -1);
2140 
2141   BaseString result;
2142   prop->get("result", result);
2143   if(strcmp(result.c_str(), "Ok") != 0) {
2144     SET_ERROR(handle, EINVAL, result.c_str());
2145     delete prop;
2146     DBUG_RETURN(-1);
2147   }
2148 
2149   delete prop;
2150   DBUG_RETURN(0);
2151 }
2152 
2153 extern "C"
2154 struct ndb_mgm_configuration *
ndb_mgm_get_configuration_from_node(NdbMgmHandle handle,int nodeid)2155 ndb_mgm_get_configuration_from_node(NdbMgmHandle handle,
2156                                     int nodeid)
2157 {
2158   return ndb_mgm_get_configuration2(handle, 0,
2159                                     NDB_MGM_NODE_TYPE_UNKNOWN, nodeid);
2160 }
2161 
2162 extern "C"
2163 int
ndb_mgm_start_signallog(NdbMgmHandle handle,int nodeId,struct ndb_mgm_reply * reply)2164 ndb_mgm_start_signallog(NdbMgmHandle handle, int nodeId,
2165 			struct ndb_mgm_reply* reply)
2166 {
2167   DBUG_ENTER("ndb_mgm_start_signallog");
2168   CHECK_HANDLE(handle, -1);
2169   SET_ERROR(handle, NDB_MGM_NO_ERROR, "Executing: ndb_mgm_start_signallog");
2170   const ParserRow<ParserDummy> start_signallog_reply[] = {
2171     MGM_CMD("start signallog reply", NULL, ""),
2172     MGM_ARG("result", String, Mandatory, "Error message"),
2173     MGM_END()
2174   };
2175   int retval = -1;
2176   CHECK_CONNECTED(handle, -1);
2177 
2178   Properties args;
2179   args.put("node", nodeId);
2180 
2181   const Properties *prop;
2182   prop = ndb_mgm_call(handle,
2183 		       start_signallog_reply,
2184 		       "start signallog",
2185 		       &args);
2186   CHECK_REPLY(handle, prop, -1);
2187 
2188   if(prop != NULL) {
2189     BaseString result;
2190     prop->get("result", result);
2191     if(strcmp(result.c_str(), "Ok") == 0) {
2192       retval = 0;
2193     } else {
2194       SET_ERROR(handle, EINVAL, result.c_str());
2195       retval = -1;
2196     }
2197     delete prop;
2198   }
2199 
2200   DBUG_RETURN(retval);
2201 }
2202 
2203 extern "C"
2204 int
ndb_mgm_stop_signallog(NdbMgmHandle handle,int nodeId,struct ndb_mgm_reply * reply)2205 ndb_mgm_stop_signallog(NdbMgmHandle handle, int nodeId,
2206 		       struct ndb_mgm_reply* reply)
2207 {
2208   DBUG_ENTER("ndb_mgm_stop_signallog");
2209   CHECK_HANDLE(handle, -1);
2210   SET_ERROR(handle, NDB_MGM_NO_ERROR, "Executing: ndb_mgm_stop_signallog");
2211   const ParserRow<ParserDummy> stop_signallog_reply[] = {
2212     MGM_CMD("stop signallog reply", NULL, ""),
2213     MGM_ARG("result", String, Mandatory, "Error message"),
2214     MGM_END()
2215   };
2216   int retval = -1;
2217   CHECK_CONNECTED(handle, -1);
2218 
2219   Properties args;
2220   args.put("node", nodeId);
2221 
2222   const Properties *prop;
2223   prop = ndb_mgm_call(handle, stop_signallog_reply, "stop signallog", &args);
2224   CHECK_REPLY(handle, prop, -1);
2225 
2226   if(prop != NULL) {
2227     BaseString result;
2228     prop->get("result", result);
2229     if(strcmp(result.c_str(), "Ok") == 0) {
2230       retval = 0;
2231     } else {
2232       SET_ERROR(handle, EINVAL, result.c_str());
2233       retval = -1;
2234     }
2235     delete prop;
2236   }
2237 
2238   DBUG_RETURN(retval);
2239 }
2240 
2241 struct ndb_mgm_signal_log_modes
2242 {
2243   const char* name;
2244   enum ndb_mgm_signal_log_mode mode;
2245 };
2246 
2247 extern "C"
2248 int
ndb_mgm_log_signals(NdbMgmHandle handle,int nodeId,enum ndb_mgm_signal_log_mode mode,const char * blockNames,struct ndb_mgm_reply * reply)2249 ndb_mgm_log_signals(NdbMgmHandle handle, int nodeId,
2250 		    enum ndb_mgm_signal_log_mode mode,
2251 		    const char* blockNames,
2252 		    struct ndb_mgm_reply* reply)
2253 {
2254   DBUG_ENTER("ndb_mgm_log_signals");
2255   CHECK_HANDLE(handle, -1);
2256   SET_ERROR(handle, NDB_MGM_NO_ERROR, "Executing: ndb_mgm_log_signals");
2257   const ParserRow<ParserDummy> stop_signallog_reply[] = {
2258     MGM_CMD("log signals reply", NULL, ""),
2259     MGM_ARG("result", String, Mandatory, "Error message"),
2260     MGM_END()
2261   };
2262   int retval = -1;
2263   CHECK_CONNECTED(handle, -1);
2264 
2265   Properties args;
2266   args.put("node", nodeId);
2267   args.put("blocks", blockNames);
2268 
2269   switch(mode) {
2270   case NDB_MGM_SIGNAL_LOG_MODE_IN:
2271     args.put("in", (Uint32)1);
2272     args.put("out", (Uint32)0);
2273     break;
2274   case NDB_MGM_SIGNAL_LOG_MODE_OUT:
2275     args.put("in", (Uint32)0);
2276     args.put("out", (Uint32)1);
2277     break;
2278   case NDB_MGM_SIGNAL_LOG_MODE_INOUT:
2279     args.put("in", (Uint32)1);
2280     args.put("out", (Uint32)1);
2281     break;
2282   case NDB_MGM_SIGNAL_LOG_MODE_OFF:
2283     args.put("in", (Uint32)0);
2284     args.put("out", (Uint32)0);
2285     break;
2286   }
2287 
2288   const Properties *prop;
2289   prop = ndb_mgm_call(handle, stop_signallog_reply, "log signals", &args);
2290   CHECK_REPLY(handle, prop, -1);
2291 
2292   if(prop != NULL) {
2293     BaseString result;
2294     prop->get("result", result);
2295     if(strcmp(result.c_str(), "Ok") == 0) {
2296       retval = 0;
2297     } else {
2298       SET_ERROR(handle, EINVAL, result.c_str());
2299       retval = -1;
2300     }
2301     delete prop;
2302   }
2303 
2304   DBUG_RETURN(retval);
2305 }
2306 
2307 extern "C"
2308 int
ndb_mgm_set_trace(NdbMgmHandle handle,int nodeId,int traceNumber,struct ndb_mgm_reply * reply)2309 ndb_mgm_set_trace(NdbMgmHandle handle, int nodeId, int traceNumber,
2310 		  struct ndb_mgm_reply* reply)
2311 {
2312   DBUG_ENTER("ndb_mgm_set_trace");
2313   CHECK_HANDLE(handle, -1);
2314   SET_ERROR(handle, NDB_MGM_NO_ERROR, "Executing: ndb_mgm_set_trace");
2315   const ParserRow<ParserDummy> set_trace_reply[] = {
2316     MGM_CMD("set trace reply", NULL, ""),
2317     MGM_ARG("result", String, Mandatory, "Error message"),
2318     MGM_END()
2319   };
2320   int retval = -1;
2321   CHECK_CONNECTED(handle, -1);
2322 
2323   Properties args;
2324   args.put("node", nodeId);
2325   args.put("trace", traceNumber);
2326 
2327   const Properties *prop;
2328   prop = ndb_mgm_call(handle, set_trace_reply, "set trace", &args);
2329   CHECK_REPLY(handle, prop, -1);
2330 
2331   if(prop != NULL) {
2332     BaseString result;
2333     prop->get("result", result);
2334     if(strcmp(result.c_str(), "Ok") == 0) {
2335       retval = 0;
2336     } else {
2337       SET_ERROR(handle, EINVAL, result.c_str());
2338       retval = -1;
2339     }
2340     delete prop;
2341   }
2342 
2343   DBUG_RETURN(retval);
2344 }
2345 
2346 int
ndb_mgm_insert_error_impl(NdbMgmHandle handle,int nodeId,int errorCode,int * extra,struct ndb_mgm_reply * reply)2347 ndb_mgm_insert_error_impl(NdbMgmHandle handle, int nodeId,
2348                           int errorCode,
2349                           int * extra,
2350                           struct ndb_mgm_reply* reply)
2351 {
2352   DBUG_ENTER("ndb_mgm_insert_error");
2353 
2354   CHECK_HANDLE(handle, -1);
2355   SET_ERROR(handle, NDB_MGM_NO_ERROR, "Executing: ndb_mgm_insert_error");
2356   const ParserRow<ParserDummy> insert_error_reply[] = {
2357     MGM_CMD("insert error reply", NULL, ""),
2358     MGM_ARG("result", String, Mandatory, "Error message"),
2359     MGM_END()
2360   };
2361   int retval = -1;
2362   CHECK_CONNECTED(handle, -1);
2363 
2364   Properties args;
2365   args.put("node", nodeId);
2366   args.put("error", errorCode);
2367   if (extra)
2368   {
2369     args.put("extra", * extra);
2370   }
2371 
2372   const Properties *prop;
2373   prop = ndb_mgm_call(handle, insert_error_reply, "insert error", &args);
2374   CHECK_REPLY(handle, prop, -1);
2375 
2376   if(prop != NULL) {
2377     BaseString result;
2378     prop->get("result", result);
2379     if(strcmp(result.c_str(), "Ok") == 0) {
2380       retval = 0;
2381     } else {
2382       SET_ERROR(handle, EINVAL, result.c_str());
2383       retval = -1;
2384     }
2385     delete prop;
2386   }
2387 
2388   DBUG_RETURN(retval);
2389 }
2390 
2391 extern "C"
2392 int
ndb_mgm_insert_error(NdbMgmHandle handle,int nodeId,int errorCode,struct ndb_mgm_reply * reply)2393 ndb_mgm_insert_error(NdbMgmHandle handle, int nodeId, int errorCode,
2394 		     struct ndb_mgm_reply* reply)
2395 {
2396   return ndb_mgm_insert_error_impl(handle, nodeId, errorCode, 0, reply);
2397 }
2398 
2399 extern "C"
2400 int
ndb_mgm_insert_error2(NdbMgmHandle handle,int nodeId,int errorCode,int extra,struct ndb_mgm_reply * reply)2401 ndb_mgm_insert_error2(NdbMgmHandle handle, int nodeId,
2402                       int errorCode, int extra,
2403 		     struct ndb_mgm_reply* reply)
2404 {
2405   return ndb_mgm_insert_error_impl(handle, nodeId, errorCode, &extra, reply);
2406 }
2407 
2408 extern "C"
2409 int
ndb_mgm_start(NdbMgmHandle handle,int no_of_nodes,const int * node_list)2410 ndb_mgm_start(NdbMgmHandle handle, int no_of_nodes, const int * node_list)
2411 {
2412   DBUG_ENTER("ndb_mgm_start");
2413   CHECK_HANDLE(handle, -1);
2414   SET_ERROR(handle, NDB_MGM_NO_ERROR, "Executing: ndb_mgm_start");
2415   const ParserRow<ParserDummy> start_reply[] = {
2416     MGM_CMD("start reply", NULL, ""),
2417     MGM_ARG("started", Int, Optional, "No of started nodes"),
2418     MGM_ARG("result", String, Mandatory, "Error message"),
2419     MGM_END()
2420   };
2421   int started = 0;
2422   CHECK_CONNECTED(handle, -1);
2423 
2424   if(no_of_nodes < 0){
2425     SET_ERROR(handle, EINVAL, "");
2426     DBUG_RETURN(-1);
2427   }
2428 
2429   if(no_of_nodes == 0){
2430     Properties args;
2431     const Properties *reply;
2432     reply = ndb_mgm_call(handle, start_reply, "start all", &args);
2433     CHECK_REPLY(handle, reply, -1);
2434 
2435     Uint32 count = 0;
2436     if(!reply->get("started", &count)){
2437       delete reply;
2438       DBUG_RETURN(-1);
2439     }
2440     delete reply;
2441     DBUG_RETURN(count);
2442   }
2443 
2444   for(int node = 0; node < no_of_nodes; node++) {
2445     Properties args;
2446     args.put("node", node_list[node]);
2447 
2448     const Properties *reply;
2449     reply = ndb_mgm_call(handle, start_reply, "start", &args);
2450 
2451     if(reply != NULL) {
2452       BaseString result;
2453       reply->get("result", result);
2454       if(strcmp(result.c_str(), "Ok") == 0) {
2455 	started++;
2456       } else {
2457 	SET_ERROR(handle, EINVAL, result.c_str());
2458 	delete reply;
2459         DBUG_RETURN(-1);
2460       }
2461     }
2462     delete reply;
2463   }
2464 
2465   DBUG_RETURN(started);
2466 }
2467 
2468 /*****************************************************************************
2469  * Backup
2470  *****************************************************************************/
2471 extern "C"
2472 int
ndb_mgm_start_backup3(NdbMgmHandle handle,int wait_completed,unsigned int * _backup_id,struct ndb_mgm_reply *,unsigned int input_backupId,unsigned int backuppoint)2473 ndb_mgm_start_backup3(NdbMgmHandle handle, int wait_completed,
2474 		     unsigned int* _backup_id,
2475 		     struct ndb_mgm_reply*, /*reply*/
2476 		     unsigned int input_backupId,
2477 		     unsigned int backuppoint)
2478 {
2479   DBUG_ENTER("ndb_mgm_start_backup");
2480 
2481   CHECK_HANDLE(handle, -1);
2482   SET_ERROR(handle, NDB_MGM_NO_ERROR, "Executing: ndb_mgm_start_backup");
2483   const ParserRow<ParserDummy> start_backup_reply[] = {
2484     MGM_CMD("start backup reply", NULL, ""),
2485     MGM_ARG("result", String, Mandatory, "Error message"),
2486     MGM_ARG("id", Int, Optional, "Id of the started backup"),
2487     MGM_END()
2488   };
2489   CHECK_CONNECTED(handle, -1);
2490 
2491   if (!get_mgmd_version(handle))
2492     DBUG_RETURN(-1);
2493 
2494   bool sendBackupPoint = (handle->mgmd_version() >= NDB_MAKE_VERSION(6,4,0));
2495 
2496   Properties args;
2497   args.put("completed", wait_completed);
2498   if(input_backupId > 0)
2499     args.put("backupid", input_backupId);
2500   if (sendBackupPoint)
2501     args.put("backuppoint", backuppoint);
2502 
2503   const Properties *reply;
2504   { // start backup can take some time, set timeout high
2505     int old_timeout= handle->timeout;
2506     if (wait_completed == 2)
2507       handle->timeout= 48*60*60*1000; // 48 hours
2508     else if (wait_completed == 1)
2509       handle->timeout= 10*60*1000; // 10 minutes
2510     reply = ndb_mgm_call(handle, start_backup_reply, "start backup", &args);
2511     handle->timeout= old_timeout;
2512   }
2513   CHECK_REPLY(handle, reply, -1);
2514 
2515   BaseString result;
2516   reply->get("result", result);
2517   reply->get("id", _backup_id);
2518   if(strcmp(result.c_str(), "Ok") != 0) {
2519     SET_ERROR(handle, NDB_MGM_COULD_NOT_START_BACKUP, result.c_str());
2520     delete reply;
2521     DBUG_RETURN(-1);
2522   }
2523 
2524   delete reply;
2525   DBUG_RETURN(0);
2526 }
2527 
2528 extern "C"
2529 int
ndb_mgm_start_backup2(NdbMgmHandle handle,int wait_completed,unsigned int * _backup_id,struct ndb_mgm_reply * reply,unsigned int input_backupId)2530 ndb_mgm_start_backup2(NdbMgmHandle handle, int wait_completed,
2531 		     unsigned int* _backup_id,
2532 		     struct ndb_mgm_reply* reply,
2533 		     unsigned int input_backupId)
2534 {
2535   return ndb_mgm_start_backup3(handle, wait_completed, _backup_id, reply, input_backupId, 0);
2536 }
2537 
2538 extern "C"
2539 int
ndb_mgm_start_backup(NdbMgmHandle handle,int wait_completed,unsigned int * _backup_id,struct ndb_mgm_reply * reply)2540 ndb_mgm_start_backup(NdbMgmHandle handle, int wait_completed,
2541 		     unsigned int* _backup_id,
2542 		     struct ndb_mgm_reply* reply)
2543 {
2544   return ndb_mgm_start_backup2(handle, wait_completed, _backup_id, reply, 0);
2545 }
2546 
2547 extern "C"
2548 int
ndb_mgm_abort_backup(NdbMgmHandle handle,unsigned int backupId,struct ndb_mgm_reply *)2549 ndb_mgm_abort_backup(NdbMgmHandle handle, unsigned int backupId,
2550 		     struct ndb_mgm_reply* /*reply*/)
2551 {
2552   DBUG_ENTER("ndb_mgm_abort_backup");
2553   CHECK_HANDLE(handle, -1);
2554   SET_ERROR(handle, NDB_MGM_NO_ERROR, "Executing: ndb_mgm_abort_backup");
2555   const ParserRow<ParserDummy> stop_backup_reply[] = {
2556     MGM_CMD("abort backup reply", NULL, ""),
2557     MGM_ARG("result", String, Mandatory, "Error message"),
2558     MGM_END()
2559   };
2560   CHECK_CONNECTED(handle, -1);
2561 
2562   Properties args;
2563   args.put("id", backupId);
2564 
2565   const Properties *prop;
2566   prop = ndb_mgm_call(handle, stop_backup_reply, "abort backup", &args);
2567   CHECK_REPLY(handle, prop, -1);
2568 
2569   const char * buf;
2570   prop->get("result", &buf);
2571   if(strcmp(buf,"Ok")!=0) {
2572     SET_ERROR(handle, NDB_MGM_COULD_NOT_ABORT_BACKUP, buf);
2573     delete prop;
2574     DBUG_RETURN(-1);
2575   }
2576 
2577   delete prop;
2578   DBUG_RETURN(0);
2579 }
2580 
2581 extern "C"
2582 struct ndb_mgm_configuration *
ndb_mgm_get_configuration2(NdbMgmHandle handle,unsigned int version,enum ndb_mgm_node_type nodetype,int from_node)2583 ndb_mgm_get_configuration2(NdbMgmHandle handle, unsigned int version,
2584                            enum ndb_mgm_node_type nodetype, int from_node)
2585 {
2586   DBUG_ENTER("ndb_mgm_get_configuration2");
2587 
2588   CHECK_HANDLE(handle, NULL);
2589   SET_ERROR(handle, NDB_MGM_NO_ERROR, "Executing: ndb_mgm_get_configuration");
2590   CHECK_CONNECTED(handle, NULL);
2591 
2592   if (!get_mgmd_version(handle))
2593     DBUG_RETURN(NULL);
2594 
2595   bool getConfigUsingNodetype =
2596     (handle->mgmd_version() >= NDB_MAKE_VERSION(6,4,0));
2597 
2598   Properties args;
2599   args.put("version", version);
2600   if (getConfigUsingNodetype)
2601   {
2602     args.put("nodetype", nodetype);
2603   }
2604 
2605   bool v2 = ndb_config_version_v2(handle->mgmd_version());
2606   if (from_node != 0)
2607   {
2608     if (check_version_new(handle->mgmd_version(),
2609                           NDB_MAKE_VERSION(7,1,16),
2610                           NDB_MAKE_VERSION(7,0,27),
2611                           0))
2612     {
2613       args.put("from_node", from_node);
2614     }
2615     else
2616     {
2617       SET_ERROR(handle, NDB_MGM_GET_CONFIG_FAILED,
2618                 "The mgm server does not support getting config from_node");
2619       DBUG_RETURN(0);
2620     }
2621   }
2622   else if (v2)
2623   {
2624     Uint32 node_id = ndb_mgm_get_configuration_nodeid(handle);
2625     args.put("node", node_id);
2626   }
2627 
2628   const ParserRow<ParserDummy> reply[] = {
2629     MGM_CMD("get config reply", NULL, ""),
2630     MGM_ARG("result", String, Mandatory, "Error message"),
2631     MGM_ARG("Content-Length", Int, Optional, "Content length in bytes"),
2632     MGM_ARG("Content-Type", String, Optional, "Type (octet-stream)"),
2633     MGM_ARG("Content-Transfer-Encoding", String, Optional, "Encoding(base64)"),
2634     MGM_END()
2635   };
2636 
2637   const Properties *prop;
2638   prop = v2 ?
2639     ndb_mgm_call(handle, reply, "get config_v2", &args) :
2640     ndb_mgm_call(handle, reply, "get config", &args);
2641   CHECK_REPLY(handle, prop, 0);
2642 
2643   do {
2644     const char * buf = "<unknown error>";
2645     if(!prop->get("result", &buf) || strcmp(buf, "Ok") != 0){
2646       fprintf(handle->errstream, "ERROR Message: %s\n\n", buf);
2647       SET_ERROR(handle, NDB_MGM_GET_CONFIG_FAILED, buf);
2648       break;
2649     }
2650 
2651     buf = "<Unspecified>";
2652     if(!prop->get("Content-Type", &buf) ||
2653        strcmp(buf, "ndbconfig/octet-stream") != 0){
2654       fprintf(handle->errstream, "Unhandled response type: %s\n", buf);
2655       break;
2656     }
2657 
2658     buf = "<Unspecified>";
2659     if(!prop->get("Content-Transfer-Encoding", &buf)
2660        || strcmp(buf, "base64") != 0){
2661       fprintf(handle->errstream, "Unhandled encoding: %s\n", buf);
2662       break;
2663     }
2664 
2665     buf = "<Content-Length Unspecified>";
2666     Uint32 len = 0;
2667     if(!prop->get("Content-Length", &len)){
2668       fprintf(handle->errstream, "Invalid response: %s\n\n", buf);
2669       break;
2670     }
2671 
2672     len += 1; // Trailing \n
2673 
2674     char* buf64 = new char[len];
2675     int read = 0;
2676     size_t start = 0;
2677     do {
2678       if((read = read_socket(handle->socket, handle->timeout,
2679 			     &buf64[start], (int)(len-start))) < 1){
2680 	delete[] buf64;
2681 	buf64 = 0;
2682         if(read==0)
2683           SET_ERROR(handle, ETIMEDOUT, "Timeout reading packed config");
2684         else
2685           SET_ERROR(handle, errno, "Error reading packed config");
2686         ndb_mgm_disconnect_quiet(handle);
2687 	break;
2688       }
2689       start += read;
2690     } while(start < len);
2691     if(buf64 == 0)
2692       break;
2693 
2694     void *tmp_data = malloc(base64_needed_decoded_length((size_t) (len - 1)));
2695     const int res = ndb_base64_decode(buf64, len-1, tmp_data, NULL);
2696     delete[] buf64;
2697     UtilBuffer tmp;
2698     tmp.append((void *) tmp_data, res);
2699     free(tmp_data);
2700     if (res < 0)
2701     {
2702       fprintf(handle->errstream, "Failed to decode buffer\n");
2703       break;
2704     }
2705 
2706     ConfigValuesFactory cvf;
2707     const int res2 = v2 ?
2708       cvf.unpack_v2_buf(tmp) :
2709       cvf.unpack_v1_buf(tmp);
2710     if(!res2){
2711       fprintf(handle->errstream, "Failed to unpack buffer\n");
2712       break;
2713     }
2714 
2715     delete prop;
2716     DBUG_RETURN((ndb_mgm_configuration*)cvf.getConfigValues());
2717   } while(0);
2718 
2719   delete prop;
2720   DBUG_RETURN(0);
2721 }
2722 
2723 extern "C"
2724 struct ndb_mgm_configuration *
ndb_mgm_get_configuration(NdbMgmHandle handle,unsigned int version)2725 ndb_mgm_get_configuration(NdbMgmHandle handle, unsigned int version)
2726 {
2727   return ndb_mgm_get_configuration2(handle, version,
2728                                     NDB_MGM_NODE_TYPE_UNKNOWN);
2729 }
2730 
2731 extern "C"
2732 void
ndb_mgm_destroy_configuration(struct ndb_mgm_configuration * cfg)2733 ndb_mgm_destroy_configuration(struct ndb_mgm_configuration *cfg)
2734 {
2735     delete cfg;
2736 }
2737 
2738 extern "C"
2739 int
ndb_mgm_set_configuration_nodeid(NdbMgmHandle handle,int nodeid)2740 ndb_mgm_set_configuration_nodeid(NdbMgmHandle handle, int nodeid)
2741 {
2742   DBUG_ENTER("ndb_mgm_set_configuration_nodeid");
2743   CHECK_HANDLE(handle, -1);
2744   handle->cfg._ownNodeId= nodeid;
2745   DBUG_RETURN(0);
2746 }
2747 
2748 extern "C"
2749 int
ndb_mgm_get_configuration_nodeid(NdbMgmHandle handle)2750 ndb_mgm_get_configuration_nodeid(NdbMgmHandle handle)
2751 {
2752   DBUG_ENTER("ndb_mgm_get_configuration_nodeid");
2753   CHECK_HANDLE(handle, 0); // Zero is an invalid nodeid
2754   DBUG_RETURN(handle->cfg._ownNodeId);
2755 }
2756 
2757 extern "C"
ndb_mgm_get_connected_port(NdbMgmHandle handle)2758 int ndb_mgm_get_connected_port(NdbMgmHandle handle)
2759 {
2760   if (handle->cfg_i >= 0)
2761     return handle->cfg.ids[handle->cfg_i].port;
2762   else
2763     return 0;
2764 }
2765 
2766 extern "C"
ndb_mgm_get_connected_host(NdbMgmHandle handle)2767 const char *ndb_mgm_get_connected_host(NdbMgmHandle handle)
2768 {
2769   if (handle->cfg_i >= 0)
2770     return handle->cfg.ids[handle->cfg_i].name.c_str();
2771   else
2772     return 0;
2773 }
2774 
2775 extern "C"
ndb_mgm_get_connectstring(NdbMgmHandle handle,char * buf,int buf_sz)2776 const char *ndb_mgm_get_connectstring(NdbMgmHandle handle, char *buf, int buf_sz)
2777 {
2778   return handle->cfg.makeConnectString(buf,buf_sz);
2779 }
2780 
2781 extern "C"
ndb_mgm_get_connected_bind_address(NdbMgmHandle handle)2782 const char *ndb_mgm_get_connected_bind_address(NdbMgmHandle handle)
2783 {
2784   if (handle->cfg_i >= 0)
2785   {
2786     if (handle->m_bindaddress)
2787       return handle->m_bindaddress;
2788     if (handle->cfg.ids[handle->cfg_i].bind_address.length())
2789       return handle->cfg.ids[handle->cfg_i].bind_address.c_str();
2790   }
2791   return 0;
2792 }
2793 
2794 extern "C"
2795 int
ndb_mgm_alloc_nodeid(NdbMgmHandle handle,unsigned int version,int nodetype,int log_event)2796 ndb_mgm_alloc_nodeid(NdbMgmHandle handle, unsigned int version, int nodetype,
2797                      int log_event)
2798 {
2799   DBUG_ENTER("ndb_mgm_alloc_nodeid");
2800   CHECK_HANDLE(handle, -1);
2801   SET_ERROR(handle, NDB_MGM_NO_ERROR, "Executing: ndb_mgm_alloc_nodeid");
2802   CHECK_CONNECTED(handle, -1);
2803   union { long l; char c[sizeof(long)]; } endian_check;
2804 
2805   endian_check.l = 1;
2806 
2807   int nodeid= handle->cfg._ownNodeId;
2808 
2809   Properties args;
2810   args.put("version", version);
2811   args.put("nodetype", nodetype);
2812   args.put("nodeid", nodeid);
2813   args.put("user", "mysqld");
2814   args.put("password", "mysqld");
2815   args.put("public key", "a public key");
2816   args.put("endian", (endian_check.c[sizeof(long)-1])?"big":"little");
2817   if (handle->m_name)
2818     args.put("name", handle->m_name);
2819   args.put("log_event", log_event);
2820 
2821   const ParserRow<ParserDummy> reply[]= {
2822     MGM_CMD("get nodeid reply", NULL, ""),
2823       MGM_ARG("error_code", Int, Optional, "Error code"),
2824       MGM_ARG("nodeid", Int, Optional, "Error message"),
2825       MGM_ARG("result", String, Mandatory, "Error message"),
2826     MGM_END()
2827   };
2828 
2829   const Properties *prop;
2830   prop= ndb_mgm_call(handle, reply, "get nodeid", &args);
2831   CHECK_REPLY(handle, prop, -1);
2832 
2833   nodeid= -1;
2834   do {
2835     const char * buf;
2836     if (!prop->get("result", &buf) || strcmp(buf, "Ok") != 0)
2837     {
2838       const char *hostname= ndb_mgm_get_connected_host(handle);
2839       unsigned port=  ndb_mgm_get_connected_port(handle);
2840       Uint32 error_code= NDB_MGM_ALLOCID_ERROR;
2841       prop->get("error_code", &error_code);
2842       setError(handle, error_code, __LINE__,
2843               "Could not alloc node id at %s port %d: %s",
2844                hostname, port, buf);
2845       break;
2846     }
2847     Uint32 _nodeid;
2848     if(!prop->get("nodeid", &_nodeid) != 0){
2849       fprintf(handle->errstream, "ERROR Message: <nodeid Unspecified>\n");
2850       break;
2851     }
2852     nodeid= _nodeid;
2853   }while(0);
2854 
2855   delete prop;
2856   DBUG_RETURN(nodeid);
2857 }
2858 
2859 extern "C"
2860 int
ndb_mgm_set_int_parameter(NdbMgmHandle handle,int node,int param,unsigned value,struct ndb_mgm_reply *)2861 ndb_mgm_set_int_parameter(NdbMgmHandle handle,
2862 			  int node,
2863 			  int param,
2864 			  unsigned value,
2865 			  struct ndb_mgm_reply*){
2866   DBUG_ENTER("ndb_mgm_set_int_parameter");
2867   CHECK_HANDLE(handle, -1);
2868   CHECK_CONNECTED(handle, -1);
2869 
2870   Properties args;
2871   args.put("node", node);
2872   args.put("param", param);
2873   args.put64("value", value);
2874 
2875   const ParserRow<ParserDummy> reply[]= {
2876     MGM_CMD("set parameter reply", NULL, ""),
2877     MGM_ARG("result", String, Mandatory, "Error message"),
2878     MGM_END()
2879   };
2880 
2881   const Properties *prop;
2882   prop= ndb_mgm_call(handle, reply, "set parameter", &args);
2883   CHECK_REPLY(handle, prop, -1);
2884 
2885   int res= -1;
2886   do {
2887     const char * buf;
2888     if(!prop->get("result", &buf) || strcmp(buf, "Ok") != 0){
2889       fprintf(handle->errstream, "ERROR Message: %s\n", buf);
2890       break;
2891     }
2892     res= 0;
2893   } while(0);
2894 
2895   delete prop;
2896   DBUG_RETURN(res);
2897 }
2898 
2899 extern "C"
2900 int
ndb_mgm_set_int64_parameter(NdbMgmHandle handle,int node,int param,unsigned long long value,struct ndb_mgm_reply *)2901 ndb_mgm_set_int64_parameter(NdbMgmHandle handle,
2902 			    int node,
2903 			    int param,
2904 			    unsigned long long value,
2905 			    struct ndb_mgm_reply*){
2906   DBUG_ENTER("ndb_mgm_set_int64_parameter");
2907   CHECK_HANDLE(handle, -1);
2908   CHECK_CONNECTED(handle, -1);
2909 
2910   Properties args;
2911   args.put("node", node);
2912   args.put("param", param);
2913   args.put64("value", value);
2914 
2915   const ParserRow<ParserDummy> reply[]= {
2916     MGM_CMD("set parameter reply", NULL, ""),
2917     MGM_ARG("result", String, Mandatory, "Error message"),
2918     MGM_END()
2919   };
2920 
2921   const Properties *prop;
2922   prop= ndb_mgm_call(handle, reply, "set parameter", &args);
2923   CHECK_REPLY(handle, prop, 0);
2924 
2925   if(prop == NULL) {
2926     SET_ERROR(handle, EIO, "Unable set parameter");
2927     DBUG_RETURN(-1);
2928   }
2929 
2930   int res= -1;
2931   do {
2932     const char * buf;
2933     if(!prop->get("result", &buf) || strcmp(buf, "Ok") != 0){
2934       fprintf(handle->errstream, "ERROR Message: %s\n", buf);
2935       break;
2936     }
2937     res= 0;
2938   } while(0);
2939 
2940   delete prop;
2941   DBUG_RETURN(res);
2942 }
2943 
2944 extern "C"
2945 int
ndb_mgm_set_string_parameter(NdbMgmHandle handle,int node,int param,const char * value,struct ndb_mgm_reply *)2946 ndb_mgm_set_string_parameter(NdbMgmHandle handle,
2947 			     int node,
2948 			     int param,
2949 			     const char * value,
2950 			     struct ndb_mgm_reply*){
2951   DBUG_ENTER("ndb_mgm_set_string_parameter");
2952   CHECK_HANDLE(handle, -1);
2953   CHECK_CONNECTED(handle, -1);
2954 
2955   Properties args;
2956   args.put("node", node);
2957   args.put("parameter", param);
2958   args.put("value", value);
2959 
2960   const ParserRow<ParserDummy> reply[]= {
2961     MGM_CMD("set parameter reply", NULL, ""),
2962     MGM_ARG("result", String, Mandatory, "Error message"),
2963     MGM_END()
2964   };
2965 
2966   const Properties *prop;
2967   prop= ndb_mgm_call(handle, reply, "set parameter", &args);
2968   CHECK_REPLY(handle, prop, 0);
2969 
2970   if(prop == NULL) {
2971     SET_ERROR(handle, EIO, "Unable set parameter");
2972     DBUG_RETURN(-1);
2973   }
2974 
2975   int res= -1;
2976   do {
2977     const char * buf;
2978     if(!prop->get("result", &buf) || strcmp(buf, "Ok") != 0){
2979       fprintf(handle->errstream, "ERROR Message: %s\n", buf);
2980       break;
2981     }
2982     res= 0;
2983   } while(0);
2984 
2985   delete prop;
2986   DBUG_RETURN(res);
2987 }
2988 
2989 extern "C"
2990 int
ndb_mgm_purge_stale_sessions(NdbMgmHandle handle,char ** purged)2991 ndb_mgm_purge_stale_sessions(NdbMgmHandle handle, char **purged)
2992 {
2993   DBUG_ENTER("ndb_mgm_purge_stale_sessions");
2994   CHECK_HANDLE(handle, -1);
2995   CHECK_CONNECTED(handle, -1);
2996 
2997   Properties args;
2998 
2999   const ParserRow<ParserDummy> reply[]= {
3000     MGM_CMD("purge stale sessions reply", NULL, ""),
3001     MGM_ARG("purged", String, Optional, ""),
3002     MGM_ARG("result", String, Mandatory, "Error message"),
3003     MGM_END()
3004   };
3005 
3006   const Properties *prop;
3007   prop= ndb_mgm_call(handle, reply, "purge stale sessions", &args);
3008   CHECK_REPLY(handle, prop, -1);
3009 
3010   if(prop == NULL) {
3011     SET_ERROR(handle, EIO, "Unable to purge stale sessions");
3012     DBUG_RETURN(-1);
3013   }
3014 
3015   int res= -1;
3016   do {
3017     const char * buf;
3018     if(!prop->get("result", &buf) || strcmp(buf, "Ok") != 0){
3019       fprintf(handle->errstream, "ERROR Message: %s\n", buf);
3020       break;
3021     }
3022     if (purged) {
3023       if (prop->get("purged", &buf))
3024 	*purged= strdup(buf);
3025       else
3026 	*purged= 0;
3027     }
3028     res= 0;
3029   } while(0);
3030   delete prop;
3031   DBUG_RETURN(res);
3032 }
3033 
3034 extern "C"
3035 int
ndb_mgm_check_connection(NdbMgmHandle handle)3036 ndb_mgm_check_connection(NdbMgmHandle handle)
3037 {
3038   DBUG_ENTER("ndb_mgm_check_connection");
3039   CHECK_HANDLE(handle, -1);
3040   CHECK_CONNECTED(handle, -1);
3041   SocketOutputStream out(handle->socket, handle->timeout);
3042   SocketInputStream in(handle->socket, handle->timeout);
3043   char buf[32];
3044   if (out.println("check connection"))
3045     goto ndb_mgm_check_connection_error;
3046 
3047   if (out.println("%s", ""))
3048     goto ndb_mgm_check_connection_error;
3049 
3050   in.gets(buf, sizeof(buf));
3051   if(strcmp("check connection reply\n", buf))
3052     goto ndb_mgm_check_connection_error;
3053 
3054   in.gets(buf, sizeof(buf));
3055   if(strcmp("result: Ok\n", buf))
3056     goto ndb_mgm_check_connection_error;
3057 
3058   in.gets(buf, sizeof(buf));
3059   if(strcmp("\n", buf))
3060     goto ndb_mgm_check_connection_error;
3061 
3062   DBUG_RETURN(0);
3063 
3064 ndb_mgm_check_connection_error:
3065   ndb_mgm_disconnect(handle);
3066   DBUG_RETURN(-1);
3067 }
3068 
3069 extern "C"
3070 int
ndb_mgm_set_connection_int_parameter(NdbMgmHandle handle,int node1,int node2,int param,int value,struct ndb_mgm_reply * mgmreply)3071 ndb_mgm_set_connection_int_parameter(NdbMgmHandle handle,
3072 				     int node1,
3073 				     int node2,
3074 				     int param,
3075 				     int value,
3076 				     struct ndb_mgm_reply* mgmreply){
3077   DBUG_ENTER("ndb_mgm_set_connection_int_parameter");
3078   CHECK_HANDLE(handle, -1);
3079   CHECK_CONNECTED(handle, -1);
3080 
3081   Properties args;
3082   args.put("node1", node1);
3083   args.put("node2", node2);
3084   args.put("param", param);
3085   args.put("value", (Uint32)value);
3086 
3087   const ParserRow<ParserDummy> reply[]= {
3088     MGM_CMD("set connection parameter reply", NULL, ""),
3089     MGM_ARG("message", String, Mandatory, "Error Message"),
3090     MGM_ARG("result", String, Mandatory, "Status Result"),
3091     MGM_END()
3092   };
3093 
3094   const Properties *prop;
3095   prop= ndb_mgm_call(handle, reply, "set connection parameter", &args);
3096   CHECK_REPLY(handle, prop, -1);
3097 
3098   int res= -1;
3099   do {
3100     const char * buf;
3101     if(!prop->get("result", &buf) || strcmp(buf, "Ok") != 0){
3102       fprintf(handle->errstream, "ERROR Message: %s\n", buf);
3103       break;
3104     }
3105     res= 0;
3106   } while(0);
3107 
3108   delete prop;
3109   DBUG_RETURN(res);
3110 }
3111 
3112 extern "C"
3113 int
ndb_mgm_get_connection_int_parameter(NdbMgmHandle handle,int node1,int node2,int param,int * value,struct ndb_mgm_reply * mgmreply)3114 ndb_mgm_get_connection_int_parameter(NdbMgmHandle handle,
3115 				     int node1,
3116 				     int node2,
3117 				     int param,
3118 				     int *value,
3119 				     struct ndb_mgm_reply* mgmreply){
3120   DBUG_ENTER("ndb_mgm_get_connection_int_parameter");
3121   CHECK_HANDLE(handle, -1);
3122   CHECK_CONNECTED(handle, -1);
3123 
3124   Properties args;
3125   args.put("node1", node1);
3126   args.put("node2", node2);
3127   args.put("param", param);
3128 
3129   const ParserRow<ParserDummy> reply[]= {
3130     MGM_CMD("get connection parameter reply", NULL, ""),
3131     MGM_ARG("value", Int, Mandatory, "Current Value"),
3132     MGM_ARG("result", String, Mandatory, "Result"),
3133     MGM_END()
3134   };
3135 
3136   const Properties *prop;
3137   prop = ndb_mgm_call(handle, reply, "get connection parameter", &args);
3138   CHECK_REPLY(handle, prop, -3);
3139 
3140   int res= -1;
3141   do {
3142     const char * buf;
3143     if(!prop->get("result", &buf) || strcmp(buf, "Ok") != 0){
3144       fprintf(handle->errstream, "ERROR Message: %s\n", buf);
3145       break;
3146     }
3147     res= 0;
3148   } while(0);
3149 
3150   if(!prop->get("value",(Uint32*)value)){
3151     fprintf(handle->errstream, "Unable to get value\n");
3152     res = -4;
3153   }
3154 
3155   delete prop;
3156   DBUG_RETURN(res);
3157 }
3158 
3159 extern "C"
3160 NDB_SOCKET_TYPE
ndb_mgm_convert_to_transporter(NdbMgmHandle * handle)3161 ndb_mgm_convert_to_transporter(NdbMgmHandle *handle)
3162 {
3163   DBUG_ENTER("ndb_mgm_convert_to_transporter");
3164   NDB_SOCKET_TYPE s;
3165 
3166   if(handle == 0)
3167   {
3168     SET_ERROR(*handle, NDB_MGM_ILLEGAL_SERVER_HANDLE, "");
3169     ndb_socket_invalidate(&s);
3170     DBUG_RETURN(s);
3171   }
3172 
3173   if ((*handle)->connected != 1)
3174   {
3175     SET_ERROR(*handle, NDB_MGM_SERVER_NOT_CONNECTED , "");
3176     ndb_socket_invalidate(&s);
3177     DBUG_RETURN(s);
3178   }
3179 
3180   (*handle)->connected= 0;   // we pretend we're disconnected
3181   s= (*handle)->socket;
3182 
3183   SocketOutputStream s_output(s, (*handle)->timeout);
3184   s_output.println("transporter connect");
3185   s_output.println("%s", "");
3186 
3187   ndb_mgm_destroy_handle(handle); // set connected=0, so won't disconnect
3188 
3189   DBUG_RETURN(s);
3190 }
3191 
3192 extern "C"
3193 Uint32
ndb_mgm_get_mgmd_nodeid(NdbMgmHandle handle)3194 ndb_mgm_get_mgmd_nodeid(NdbMgmHandle handle)
3195 {
3196   DBUG_ENTER("ndb_mgm_get_mgmd_nodeid");
3197   Uint32 nodeid=0;
3198 
3199   CHECK_HANDLE(handle, 0); // Zero is an invalid nodeid
3200   CHECK_CONNECTED(handle, 0); // Zero is an invalid nodeid
3201 
3202   Properties args;
3203 
3204   const ParserRow<ParserDummy> reply[]= {
3205     MGM_CMD("get mgmd nodeid reply", NULL, ""),
3206     MGM_ARG("nodeid", Int, Mandatory, "Node ID"),
3207     MGM_END()
3208   };
3209 
3210   const Properties *prop;
3211   prop = ndb_mgm_call(handle, reply, "get mgmd nodeid", &args);
3212   CHECK_REPLY(handle, prop, 0);
3213 
3214   if(!prop->get("nodeid",&nodeid)){
3215     fprintf(handle->errstream, "Unable to get value\n");
3216     DBUG_RETURN(0);
3217   }
3218 
3219   delete prop;
3220   DBUG_RETURN(nodeid);
3221 }
3222 
3223 extern "C"
ndb_mgm_report_event(NdbMgmHandle handle,Uint32 * data,Uint32 length)3224 int ndb_mgm_report_event(NdbMgmHandle handle, Uint32 *data, Uint32 length)
3225 {
3226   DBUG_ENTER("ndb_mgm_report_event");
3227   CHECK_HANDLE(handle, -1);
3228   CHECK_CONNECTED(handle, -1);
3229 
3230   Properties args;
3231   args.put("length", length);
3232   BaseString data_string;
3233 
3234   for (int i = 0; i < (int) length; i++)
3235     data_string.appfmt(" %lu", (ulong) data[i]);
3236 
3237   args.put("data", data_string.c_str());
3238 
3239   const ParserRow<ParserDummy> reply[]= {
3240     MGM_CMD("report event reply", NULL, ""),
3241     MGM_ARG("result", String, Mandatory, "Result"),
3242     MGM_END()
3243   };
3244 
3245   const Properties *prop;
3246   prop = ndb_mgm_call(handle, reply, "report event", &args);
3247   CHECK_REPLY(handle, prop, -1);
3248 
3249   delete prop;
3250   DBUG_RETURN(0);
3251 }
3252 
3253 extern "C"
ndb_mgm_end_session(NdbMgmHandle handle)3254 int ndb_mgm_end_session(NdbMgmHandle handle)
3255 {
3256   DBUG_ENTER("ndb_mgm_end_session");
3257   CHECK_HANDLE(handle, -1);
3258   CHECK_CONNECTED(handle, -1);
3259 
3260   SocketOutputStream s_output(handle->socket, handle->timeout);
3261   const char *end_session_str = "end session";
3262   s_output.println("%s", end_session_str);
3263   s_output.println("%s", "");
3264 
3265   SocketInputStream in(handle->socket, handle->timeout);
3266   char buf[32];
3267   in.gets(buf, sizeof(buf));
3268   CHECK_TIMEDOUT_RET(handle, in, s_output, -1, end_session_str);
3269 
3270   DBUG_RETURN(0);
3271 }
3272 
3273 extern "C"
ndb_mgm_get_version(NdbMgmHandle handle,int * major,int * minor,int * build,int len,char * str)3274 int ndb_mgm_get_version(NdbMgmHandle handle,
3275                         int *major, int *minor, int *build, int len, char* str)
3276 {
3277   DBUG_ENTER("ndb_mgm_get_version");
3278   CHECK_HANDLE(handle, -1);
3279   CHECK_CONNECTED(handle, -1);
3280 
3281   Properties args;
3282 
3283   const ParserRow<ParserDummy> reply[]= {
3284     MGM_CMD("version", NULL, ""),
3285     MGM_ARG("id", Int, Mandatory, "ID"),
3286     MGM_ARG("major", Int, Mandatory, "Major"),
3287     MGM_ARG("minor", Int, Mandatory, "Minor"),
3288     MGM_ARG("build", Int, Optional, "Build"),
3289     MGM_ARG("string", String, Mandatory, "String"),
3290     MGM_ARG("mysql_major", Int, Optional, "MySQL major"),
3291     MGM_ARG("mysql_minor", Int, Optional, "MySQL minor"),
3292     MGM_ARG("mysql_build", Int, Optional, "MySQL build"),
3293     MGM_END()
3294   };
3295 
3296   const Properties *prop;
3297   prop = ndb_mgm_call(handle, reply, "get version", &args);
3298   CHECK_REPLY(handle, prop, 0);
3299 
3300   Uint32 id;
3301   if(!prop->get("id",&id)){
3302     SET_ERROR(handle, NDB_MGM_ILLEGAL_SERVER_REPLY,
3303               "Unable to get version id");
3304     DBUG_RETURN(0);
3305   }
3306   *build= getBuild(id);
3307 
3308   if(!prop->get("major",(Uint32*)major)){
3309     SET_ERROR(handle, NDB_MGM_ILLEGAL_SERVER_REPLY,
3310               "Unable to get version major");
3311     DBUG_RETURN(0);
3312   }
3313 
3314   if(!prop->get("minor",(Uint32*)minor)){
3315     SET_ERROR(handle, NDB_MGM_ILLEGAL_SERVER_REPLY,
3316               "Unable to get version minor");
3317     DBUG_RETURN(0);
3318   }
3319 
3320   BaseString result;
3321   if(!prop->get("string", result)){
3322     SET_ERROR(handle, NDB_MGM_ILLEGAL_SERVER_REPLY,
3323               "Unable to get version string");
3324     DBUG_RETURN(0);
3325   }
3326 
3327   strncpy(str, result.c_str(), len);
3328 
3329   delete prop;
3330   DBUG_RETURN(1);
3331 }
3332 
3333 extern "C"
3334 Uint64
ndb_mgm_get_session_id(NdbMgmHandle handle)3335 ndb_mgm_get_session_id(NdbMgmHandle handle)
3336 {
3337   Uint64 session_id=0;
3338 
3339   DBUG_ENTER("ndb_mgm_get_session_id");
3340   CHECK_HANDLE(handle, 0);
3341   CHECK_CONNECTED(handle, 0);
3342 
3343   Properties args;
3344 
3345   const ParserRow<ParserDummy> reply[]= {
3346     MGM_CMD("get session id reply", NULL, ""),
3347     MGM_ARG("id", Int, Mandatory, "Node ID"),
3348     MGM_END()
3349   };
3350 
3351   const Properties *prop;
3352   prop = ndb_mgm_call(handle, reply, "get session id", &args);
3353   CHECK_REPLY(handle, prop, 0);
3354 
3355   if(!prop->get("id",&session_id)){
3356     fprintf(handle->errstream, "Unable to get session id\n");
3357     DBUG_RETURN(0);
3358   }
3359 
3360   delete prop;
3361   DBUG_RETURN(session_id);
3362 }
3363 
3364 extern "C"
3365 int
ndb_mgm_get_session(NdbMgmHandle handle,Uint64 id,struct NdbMgmSession * s,int * len)3366 ndb_mgm_get_session(NdbMgmHandle handle, Uint64 id,
3367                     struct NdbMgmSession *s, int *len)
3368 {
3369   int retval= 0;
3370   DBUG_ENTER("ndb_mgm_get_session");
3371   CHECK_HANDLE(handle, -1);
3372   CHECK_CONNECTED(handle, -1);
3373 
3374   Properties args;
3375   args.put("id", (Uint32)id);
3376 
3377   const ParserRow<ParserDummy> reply[]= {
3378     MGM_CMD("get session reply", NULL, ""),
3379     MGM_ARG("id", Int, Mandatory, "Node ID"),
3380     MGM_ARG("m_stopSelf", Int, Optional, "m_stopSelf"),
3381     MGM_ARG("m_stop", Int, Optional, "stop session"),
3382     MGM_ARG("nodeid", Int, Optional, "allocated node id"),
3383     MGM_ARG("parser_buffer_len", Int, Optional, "waiting in buffer"),
3384     MGM_ARG("parser_status", Int, Optional, "parser status"),
3385     MGM_END()
3386   };
3387 
3388   const Properties *prop;
3389   prop = ndb_mgm_call(handle, reply, "get session", &args);
3390   CHECK_REPLY(handle, prop, 0);
3391 
3392   Uint64 r_id;
3393   int rlen= 0;
3394 
3395   if(!prop->get("id",&r_id)){
3396     fprintf(handle->errstream, "Unable to get session id\n");
3397     goto err;
3398   }
3399 
3400   s->id= r_id;
3401   rlen+=sizeof(s->id);
3402 
3403   if(prop->get("m_stopSelf",&(s->m_stopSelf)))
3404     rlen+=sizeof(s->m_stopSelf);
3405   else
3406     goto err;
3407 
3408   if(prop->get("m_stop",&(s->m_stop)))
3409     rlen+=sizeof(s->m_stop);
3410   else
3411     goto err;
3412 
3413   if(prop->get("nodeid",&(s->nodeid)))
3414     rlen+=sizeof(s->nodeid);
3415   else
3416     goto err;
3417 
3418   if(prop->get("parser_buffer_len",&(s->parser_buffer_len)))
3419   {
3420     rlen+=sizeof(s->parser_buffer_len);
3421     if(prop->get("parser_status",&(s->parser_status)))
3422       rlen+=sizeof(s->parser_status);
3423   }
3424 
3425   *len= rlen;
3426   retval= 1;
3427 
3428 err:
3429   delete prop;
3430   DBUG_RETURN(retval);
3431 }
3432 
3433 extern "C"
3434 int
ndb_mgm_set_configuration(NdbMgmHandle h,ndb_mgm_configuration * c)3435 ndb_mgm_set_configuration(NdbMgmHandle h, ndb_mgm_configuration *c)
3436 {
3437   DBUG_ENTER("ndb_mgm_set_configuration");
3438   CHECK_HANDLE(h, -1);
3439   SET_ERROR(h, NDB_MGM_NO_ERROR, "Executing: ndb_mgm_set_configuration");
3440   CHECK_CONNECTED(h, -1);
3441 
3442   const ConfigValues * cfg = (ConfigValues*)c;
3443 
3444   UtilBuffer buf;
3445   bool v2 = ndb_config_version_v2(h->mgmd_version());
3446   bool ret = v2 ? cfg->pack_v2(buf) :
3447                   cfg->pack_v1(buf);
3448   if (!ret)
3449   {
3450     SET_ERROR(h, NDB_MGM_OUT_OF_MEMORY, "Packing config");
3451     DBUG_RETURN(-1);
3452   }
3453 
3454   BaseString encoded;
3455   /*
3456     The base64 encoded data of BaseString can be of max length (1024*1024)/3*4
3457     hence using int to store the length.
3458   */
3459   encoded.assfmt("%*s", (int)base64_needed_encoded_length(buf.length()), "Z");
3460   (void) base64_encode(buf.get_data(), buf.length(), (char*)encoded.c_str());
3461 
3462   Properties args;
3463   args.put("Content-Length", (Uint32)strlen(encoded.c_str()));
3464   args.put("Content-Type",  "ndbconfig/octet-stream");
3465   args.put("Content-Transfer-Encoding", "base64");
3466 
3467   const ParserRow<ParserDummy> set_config_reply[]= {
3468     MGM_CMD("set config reply", NULL, ""),
3469     MGM_ARG("result", String, Mandatory, "Result"),
3470     MGM_END()
3471   };
3472 
3473   const Properties *reply;
3474   const char *cmd_str = v2 ? "set config_v2" : "set config";
3475   reply= ndb_mgm_call(h, set_config_reply, cmd_str, &args,
3476                       encoded.c_str());
3477   CHECK_REPLY(h, reply, -1);
3478 
3479   BaseString result;
3480   reply->get("result",result);
3481 
3482   delete reply;
3483 
3484   if(strcmp(result.c_str(), "Ok") != 0) {
3485     SET_ERROR(h, NDB_MGM_CONFIG_CHANGE_FAILED, result.c_str());
3486     DBUG_RETURN(-1);
3487   }
3488 
3489   DBUG_RETURN(0);
3490 }
3491 
3492 
3493 extern "C"
ndb_mgm_create_nodegroup(NdbMgmHandle handle,int * nodes,int * ng,struct ndb_mgm_reply * mgmreply)3494 int ndb_mgm_create_nodegroup(NdbMgmHandle handle,
3495                              int *nodes,
3496                              int *ng,
3497                              struct ndb_mgm_reply* mgmreply)
3498 {
3499   DBUG_ENTER("ndb_mgm_create_nodegroup");
3500   CHECK_HANDLE(handle, -1);
3501   SET_ERROR(handle, NDB_MGM_NO_ERROR, "Executing: ndb_mgm_create_nodegroup");
3502   CHECK_CONNECTED(handle, -1);
3503 
3504   BaseString nodestr;
3505   for (int i = 0; nodes[i] != 0; i++)
3506     nodestr.appfmt("%u ", nodes[i]);
3507 
3508   Properties args;
3509   args.put("nodes", nodestr.c_str());
3510 
3511   const ParserRow<ParserDummy> reply[]= {
3512     MGM_CMD("create nodegroup reply", NULL, ""),
3513     MGM_ARG("ng", Int, Mandatory, "NG Id"),
3514     MGM_ARG("error_code", Int, Optional, "error_code"),
3515     MGM_ARG("result", String, Mandatory, "Result"),
3516     MGM_END()
3517   };
3518 
3519   const Properties *prop;
3520   prop = ndb_mgm_call(handle, reply, "create nodegroup", &args);
3521   CHECK_REPLY(handle, prop, -3);
3522 
3523   int res = 0;
3524   const char * buf = 0;
3525   if (!prop->get("result", &buf) || strcmp(buf, "Ok") != 0)
3526   {
3527     res = -1;
3528     Uint32 err = NDB_MGM_ILLEGAL_SERVER_REPLY;
3529     prop->get("error_code", &err);
3530     setError(handle, err, __LINE__, "%s", buf ? buf : "Illegal reply");
3531   }
3532   else if (!prop->get("ng",(Uint32*)ng))
3533   {
3534     res = -1;
3535     setError(handle, NDB_MGM_ILLEGAL_SERVER_REPLY, __LINE__,
3536              "Nodegroup not sent back in reply");
3537   }
3538 
3539   delete prop;
3540   DBUG_RETURN(res);
3541 }
3542 
3543 extern "C"
ndb_mgm_drop_nodegroup(NdbMgmHandle handle,int ng,struct ndb_mgm_reply * mgmreply)3544 int ndb_mgm_drop_nodegroup(NdbMgmHandle handle,
3545                            int ng,
3546                            struct ndb_mgm_reply* mgmreply)
3547 {
3548   DBUG_ENTER("ndb_mgm_drop_nodegroup");
3549   CHECK_HANDLE(handle, -1);
3550   SET_ERROR(handle, NDB_MGM_NO_ERROR, "Executing: ndb_mgm_create_nodegroup");
3551   CHECK_CONNECTED(handle, -1);
3552 
3553   Properties args;
3554   args.put("ng", ng);
3555 
3556   const ParserRow<ParserDummy> reply[]= {
3557     MGM_CMD("drop nodegroup reply", NULL, ""),
3558     MGM_ARG("error_code", Int, Optional, "error_code"),
3559     MGM_ARG("result", String, Mandatory, "Result"),
3560     MGM_END()
3561   };
3562 
3563   const Properties *prop;
3564   prop = ndb_mgm_call(handle, reply, "drop nodegroup", &args);
3565   CHECK_REPLY(handle, prop, -3);
3566 
3567   int res= 0;
3568   const char * buf = 0;
3569   if(!prop->get("result", &buf) || strcmp(buf, "Ok") != 0)
3570   {
3571     res = -1;
3572     Uint32 err = NDB_MGM_ILLEGAL_SERVER_REPLY;
3573     prop->get("error_code", &err);
3574     setError(handle, err, __LINE__, "%s", buf ? buf : "Illegal reply");
3575   }
3576 
3577   delete prop;
3578   DBUG_RETURN(res);
3579 }
3580 
3581 
_ndb_mgm_get_socket(NdbMgmHandle h)3582 NDB_SOCKET_TYPE _ndb_mgm_get_socket(NdbMgmHandle h)
3583 {
3584   return h->socket;
3585 }
3586 
3587 
3588 /*
3589   Compare function for qsort() to sort events in
3590   "source_node_id" order
3591 */
3592 
3593 static int
cmp_event(const void * _a,const void * _b)3594 cmp_event(const void *_a, const void *_b)
3595 {
3596   const ndb_logevent *a = (const ndb_logevent*)_a;
3597   const ndb_logevent *b = (const ndb_logevent*)_b;
3598 
3599   // So far all events are of same type
3600   assert(a->type == b->type);
3601 
3602   // Primarily sort on source_nodeid
3603   const unsigned diff = (a->source_nodeid - b->source_nodeid);
3604   if (diff)
3605     return diff;
3606 
3607   // Equal nodeid, go into more detailed compare
3608   // for some event types where order is important
3609   switch(a->type){
3610   case NDB_LE_MemoryUsage:
3611     // Return DataMemory before IndexMemory (ie. TUP vs ACC)
3612     return (b->MemoryUsage.block - a->MemoryUsage.block);
3613     break;
3614 
3615   default:
3616     break;
3617   }
3618 
3619   return 0;
3620 }
3621 
3622 NdbLogEventHandle
3623 ndb_mgm_create_logevent_handle_same_socket(NdbMgmHandle mh);
3624 
3625 // Free memory allocated by 'ndb_mgm_create_logevent_handle_same_socket'
3626 // without closing the socket
3627 static void
free_log_handle(NdbLogEventHandle log_handle)3628 free_log_handle(NdbLogEventHandle log_handle)
3629 {
3630   free(log_handle);
3631 }
3632 
3633 
3634 extern "C"
3635 struct ndb_mgm_events*
ndb_mgm_dump_events(NdbMgmHandle handle,enum Ndb_logevent_type type,int no_of_nodes,const int * node_list)3636 ndb_mgm_dump_events(NdbMgmHandle handle, enum Ndb_logevent_type type,
3637                     int no_of_nodes, const int * node_list)
3638 {
3639   DBUG_ENTER("ndb_mgm_dump_events");
3640   CHECK_HANDLE(handle, NULL);
3641   SET_ERROR(handle, NDB_MGM_NO_ERROR, "Executing: ndb_mgm_dump_events");
3642   CHECK_CONNECTED(handle, NULL);
3643 
3644   Properties args;
3645   args.put("type", (Uint32)type);
3646 
3647   if (no_of_nodes)
3648   {
3649     const char* separator = "";
3650     BaseString nodes;
3651     for(int node = 0; node < no_of_nodes; node++)
3652     {
3653       nodes.appfmt("%s%d", separator, node_list[node]);
3654       separator = ",";
3655     }
3656     args.put("nodes", nodes.c_str());
3657   }
3658 
3659   const ParserRow<ParserDummy> dump_events_reply[] = {
3660     MGM_CMD("dump events reply", NULL, ""),
3661     MGM_ARG("result", String, Mandatory, "Ok or error message"),
3662     MGM_ARG("events", Int, Optional, "Number of events that follows"),
3663     MGM_END()
3664   };
3665   const Properties *reply = ndb_mgm_call(handle, dump_events_reply,
3666                                          "dump events", &args);
3667   CHECK_REPLY(handle, reply, NULL);
3668 
3669   // Check the result for Ok or error
3670   const char * result;
3671   reply->get("result", &result);
3672   if (strcmp(result, "Ok") != 0) {
3673     SET_ERROR(handle, NDB_MGM_USAGE_ERROR, result);
3674     delete reply;
3675     DBUG_RETURN(NULL);
3676   }
3677 
3678   // Get number of events to read
3679   Uint32 num_events;
3680   if (!reply->get("events", &num_events))
3681   {
3682     SET_ERROR(handle, NDB_MGM_ILLEGAL_SERVER_REPLY,
3683               "Number of events missing");
3684     delete reply;
3685     DBUG_RETURN(NULL);
3686   }
3687 
3688   delete reply;
3689 
3690   // Read the streamed events
3691   ndb_mgm_events *events =
3692     (ndb_mgm_events*)
3693       malloc(sizeof(ndb_mgm_events) +
3694              num_events*sizeof(ndb_logevent));
3695   if(!events)
3696   {
3697     SET_ERROR(handle, NDB_MGM_OUT_OF_MEMORY,
3698               "Allocating ndb_mgm_events struct");
3699     DBUG_RETURN(NULL);
3700   }
3701 
3702   // Initialize log event handle to read the requested events
3703   NdbLogEventHandle log_handle =
3704     ndb_mgm_create_logevent_handle_same_socket(handle);
3705   if(!log_handle)
3706   {
3707     SET_ERROR(handle, NDB_MGM_OUT_OF_MEMORY, "Creating logevent handle");
3708     DBUG_RETURN(NULL);
3709   }
3710 
3711   Uint32 i = 0;
3712   while (i < num_events)
3713   {
3714     int res = ndb_logevent_get_next(log_handle,
3715                                     &(events->events[i]),
3716                                     handle->timeout);
3717     if (res == 0)
3718     {
3719       free(events);
3720       free_log_handle(log_handle);
3721       SET_ERROR(handle, ETIMEDOUT,
3722                 "Time out talking to management server");
3723       DBUG_RETURN(NULL);
3724     }
3725     if (res == -1)
3726     {
3727       free(events);
3728       free_log_handle(log_handle);
3729       SET_ERROR(handle,
3730                 ndb_logevent_get_latest_error(log_handle),
3731                 ndb_logevent_get_latest_error_msg(log_handle));
3732       DBUG_RETURN(NULL);
3733     }
3734 
3735     i++;
3736   }
3737   free_log_handle(log_handle);
3738 
3739   // Successfully parsed the list of events, sort on nodeid and return them
3740   events->no_of_events= num_events;
3741   qsort(events->events, events->no_of_events,
3742         sizeof(events->events[0]), cmp_event);
3743   DBUG_RETURN(events);
3744 }
3745 
3746 
3747 static
3748 int
set_dynamic_ports_batched(NdbMgmHandle handle,int nodeid,struct ndb_mgm_dynamic_port * ports,unsigned num_ports)3749 set_dynamic_ports_batched(NdbMgmHandle handle, int nodeid,
3750                           struct ndb_mgm_dynamic_port* ports,
3751                           unsigned num_ports)
3752 {
3753   DBUG_ENTER("set_dynamic_ports_batched");
3754 
3755   Properties args;
3756   args.put("node", (Uint32)nodeid);
3757   args.put("num_ports", (Uint32)num_ports);
3758 
3759   /*
3760     Build the list of nodeid/port pairs which is sent as
3761     name value pairs in bulk part of request
3762   */
3763   BaseString port_list;
3764   for(unsigned i = 0; i < num_ports; i++)
3765   {
3766     port_list.appfmt("%d=%d\n", ports[i].nodeid, ports[i].port);
3767   }
3768 
3769   const ParserRow<ParserDummy> set_ports_reply[] = {
3770     MGM_CMD("set ports reply", NULL, ""),
3771     MGM_ARG("result", String, Mandatory, "Ok or error message"),
3772     MGM_END()
3773   };
3774   const Properties *reply = ndb_mgm_call(handle, set_ports_reply,
3775                                          "set ports", &args,
3776                                          port_list.c_str());
3777   CHECK_REPLY(handle, reply, -1);
3778 
3779   // Check the result for Ok or error
3780   const char * result;
3781   reply->get("result", &result);
3782   if (strcmp(result, "Ok") != 0) {
3783     SET_ERROR(handle, NDB_MGM_USAGE_ERROR, result);
3784     delete reply;
3785     DBUG_RETURN(-1);
3786   }
3787 
3788   delete reply;
3789   DBUG_RETURN(0);
3790 }
3791 
3792 
3793 extern "C"
3794 int
ndb_mgm_set_dynamic_ports(NdbMgmHandle handle,int nodeid,struct ndb_mgm_dynamic_port * ports,unsigned num_ports)3795 ndb_mgm_set_dynamic_ports(NdbMgmHandle handle, int nodeid,
3796                           struct ndb_mgm_dynamic_port* ports,
3797                           unsigned num_ports)
3798 {
3799   DBUG_ENTER("ndb_mgm_set_dynamic_ports");
3800   DBUG_PRINT("enter", ("nodeid: %d, num_ports: %u", nodeid, num_ports));
3801   CHECK_HANDLE(handle, -1);
3802   SET_ERROR(handle, NDB_MGM_NO_ERROR, "Executing: ndb_mgm_set_dynamic_ports");
3803   CHECK_CONNECTED(handle, -1);
3804 
3805   if (num_ports == 0)
3806   {
3807     SET_ERROR(handle, NDB_MGM_USAGE_ERROR,
3808               "Illegal number of dynamic ports given in num_ports");
3809     DBUG_RETURN(-1);
3810   }
3811 
3812   // Check that the ports seems to contain reasonable numbers
3813   for (unsigned i = 0; i < num_ports; i++)
3814   {
3815     if (ports[i].nodeid == 0)
3816     {
3817       SET_ERROR(handle, NDB_MGM_USAGE_ERROR,
3818                 "Illegal nodeid specfied in ports array");
3819       DBUG_RETURN(-1);
3820     }
3821 
3822     if (ports[i].port >= 0)
3823     {
3824       // Only negative dynamic ports allowed
3825       SET_ERROR(handle, NDB_MGM_USAGE_ERROR,
3826                 "Illegal port specfied in ports array");
3827       DBUG_RETURN(-1);
3828     }
3829   }
3830 
3831   if (!get_mgmd_version(handle))
3832     DBUG_RETURN(-1);
3833 
3834   if (check_version_new(handle->mgmd_version(),
3835                         NDB_MAKE_VERSION(7,3,3),
3836                         NDB_MAKE_VERSION(7,2,14),
3837                         NDB_MAKE_VERSION(7,1,28),
3838                         NDB_MAKE_VERSION(7,0,40),
3839                         0))
3840   {
3841     // The ndb_mgmd supports reporting all ports at once
3842     DBUG_RETURN(set_dynamic_ports_batched(handle, nodeid,
3843                                           ports, num_ports));
3844   }
3845 
3846   // Report the ports one at a time
3847   for (unsigned i = 0; i < num_ports; i++)
3848   {
3849     struct ndb_mgm_reply mgm_reply;
3850     const int err = ndb_mgm_set_connection_int_parameter(handle,
3851                                                          nodeid,
3852                                                          ports[i].nodeid,
3853                                                          CFG_CONNECTION_SERVER_PORT,
3854                                                          ports[i].port,
3855                                                          &mgm_reply);
3856     if (err < 0)
3857     {
3858       setError(handle, handle->last_error, __LINE__,
3859                "Could not set dynamic port for %d->%d",
3860                nodeid, ports[i].nodeid);
3861       DBUG_RETURN(-1);
3862     }
3863   }
3864   DBUG_RETURN(0);
3865 }
3866 
3867 
3868 template class Vector<const ParserRow<ParserDummy>*>;
3869