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