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