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