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