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