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