1 /* Copyright (c) 2003, 2010, Oracle and/or its affiliates. All rights reserved.
2
3 This program is free software; you can redistribute it and/or modify
4 it under the terms of the GNU General Public License as published by
5 the Free Software Foundation; version 2 of the License.
6
7 This program is distributed in the hope that it will be useful,
8 but WITHOUT ANY WARRANTY; without even the implied warranty of
9 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10 GNU General Public License for more details.
11
12 You should have received a copy of the GNU General Public License
13 along with this program; if not, write to the Free Software
14 Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA */
15
16 #include <ndb_global.h>
17 #include <my_sys.h>
18
19 #include <LocalConfig.hpp>
20 #include <NdbAutoPtr.hpp>
21
22 #include <NdbSleep.h>
23 #include <NdbTCP.h>
24 #include <mgmapi.h>
25 #include <mgmapi_internal.h>
26 #include <mgmapi_debug.h>
27 #include "mgmapi_configuration.hpp"
28 #include <socket_io.h>
29 #include <version.h>
30
31 #include <NdbOut.hpp>
32 #include <SocketServer.hpp>
33 #include <SocketClient.hpp>
34 #include <Parser.hpp>
35 #include <OutputStream.hpp>
36 #include <InputStream.hpp>
37
38 #include <base64.h>
39
40 #define MGM_CMD(name, fun, desc) \
41 { name, \
42 0, \
43 ParserRow<ParserDummy>::Cmd, \
44 ParserRow<ParserDummy>::String, \
45 ParserRow<ParserDummy>::Optional, \
46 ParserRow<ParserDummy>::IgnoreMinMax, \
47 0, 0, \
48 fun, \
49 desc, 0 }
50
51 #define MGM_ARG(name, type, opt, desc) \
52 { name, \
53 0, \
54 ParserRow<ParserDummy>::Arg, \
55 ParserRow<ParserDummy>::type, \
56 ParserRow<ParserDummy>::opt, \
57 ParserRow<ParserDummy>::IgnoreMinMax, \
58 0, 0, \
59 0, \
60 desc, 0 }
61
62 #define MGM_END() \
63 { 0, \
64 0, \
65 ParserRow<ParserDummy>::Arg, \
66 ParserRow<ParserDummy>::Int, \
67 ParserRow<ParserDummy>::Optional, \
68 ParserRow<ParserDummy>::IgnoreMinMax, \
69 0, 0, \
70 0, \
71 0, 0 }
72
73 class ParserDummy : private SocketServer::Session
74 {
75 public:
76 ParserDummy(NDB_SOCKET_TYPE sock);
77 };
78
ParserDummy(NDB_SOCKET_TYPE sock)79 ParserDummy::ParserDummy(NDB_SOCKET_TYPE sock) : SocketServer::Session(sock)
80 {
81 }
82
83 typedef Parser<ParserDummy> Parser_t;
84
85 #define NDB_MGM_MAX_ERR_DESC_SIZE 256
86
87 struct ndb_mgm_handle {
88 int cfg_i;
89
90 int connected;
91 int last_error;
92 int last_error_line;
93 char last_error_desc[NDB_MGM_MAX_ERR_DESC_SIZE];
94 unsigned int timeout;
95
96 NDB_SOCKET_TYPE socket;
97
98 LocalConfig cfg;
99
100 #ifdef MGMAPI_LOG
101 FILE* logfile;
102 #endif
103 FILE *errstream;
104 char *m_name;
105 int mgmd_version_major;
106 int mgmd_version_minor;
107 int mgmd_version_build;
108 char * m_bindaddress;
109 };
110
111 #define SET_ERROR(h, e, s) setError(h, e, __LINE__, s)
112
113 static
114 void
setError(NdbMgmHandle h,int error,int error_line,const char * msg,...)115 setError(NdbMgmHandle h, int error, int error_line, const char * msg, ...){
116
117 h->last_error = error; \
118 h->last_error_line = error_line;
119
120 va_list ap;
121 va_start(ap, msg);
122 BaseString::vsnprintf(h->last_error_desc, sizeof(h->last_error_desc), msg, ap);
123 va_end(ap);
124 }
125
126 #define CHECK_HANDLE(handle, ret) \
127 if(handle == 0) { \
128 SET_ERROR(handle, NDB_MGM_ILLEGAL_SERVER_HANDLE, ""); \
129 return ret; \
130 }
131
132 #define CHECK_CONNECTED(handle, ret) \
133 if (handle->connected != 1) { \
134 SET_ERROR(handle, NDB_MGM_SERVER_NOT_CONNECTED , ""); \
135 return ret; \
136 }
137
138 #define CHECK_REPLY(handle, reply, ret) \
139 if(reply == NULL) { \
140 if(!handle->last_error) \
141 SET_ERROR(handle, NDB_MGM_ILLEGAL_SERVER_REPLY, ""); \
142 return ret; \
143 }
144
145 #define DBUG_CHECK_REPLY(handle, reply, ret) \
146 if (reply == NULL) { \
147 if(!handle->last_error) \
148 SET_ERROR(handle, NDB_MGM_ILLEGAL_SERVER_REPLY, ""); \
149 DBUG_RETURN(ret); \
150 }
151
152 #define CHECK_TIMEDOUT(in, out) \
153 if(in.timedout() || out.timedout()) \
154 SET_ERROR(handle, ETIMEDOUT, \
155 "Time out talking to management server");
156
157 #define CHECK_TIMEDOUT_RET(h, in, out, ret) \
158 if(in.timedout() || out.timedout()) { \
159 SET_ERROR(handle, ETIMEDOUT, \
160 "Time out talking to management server"); \
161 ndb_mgm_disconnect_quiet(h); \
162 return ret; \
163 }
164
165 #define DBUG_CHECK_TIMEDOUT_RET(h, in, out, ret) \
166 if(in.timedout() || out.timedout()) { \
167 SET_ERROR(handle, ETIMEDOUT, \
168 "Time out talking to management server"); \
169 ndb_mgm_disconnect_quiet(h); \
170 DBUG_RETURN(ret); \
171 }
172
173 /*****************************************************************************
174 * Handles
175 *****************************************************************************/
176
177 extern "C"
178 NdbMgmHandle
ndb_mgm_create_handle()179 ndb_mgm_create_handle()
180 {
181 DBUG_ENTER("ndb_mgm_create_handle");
182 NdbMgmHandle h =
183 (NdbMgmHandle)my_malloc(sizeof(ndb_mgm_handle),MYF(MY_WME));
184 h->connected = 0;
185 h->last_error = 0;
186 h->last_error_line = 0;
187 h->socket = NDB_INVALID_SOCKET;
188 h->timeout = 60000;
189 h->cfg_i = -1;
190 h->errstream = stdout;
191 h->m_name = 0;
192 h->m_bindaddress = 0;
193
194 strncpy(h->last_error_desc, "No error", NDB_MGM_MAX_ERR_DESC_SIZE);
195
196 new (&(h->cfg)) LocalConfig;
197 h->cfg.init(0, 0);
198
199 #ifdef MGMAPI_LOG
200 h->logfile = 0;
201 #endif
202
203 h->mgmd_version_major= -1;
204 h->mgmd_version_minor= -1;
205 h->mgmd_version_build= -1;
206
207 DBUG_PRINT("info", ("handle: 0x%lx", (long) h));
208 DBUG_RETURN(h);
209 }
210
211 extern "C"
212 void
ndb_mgm_set_name(NdbMgmHandle handle,const char * name)213 ndb_mgm_set_name(NdbMgmHandle handle, const char *name)
214 {
215 my_free(handle->m_name);
216 handle->m_name= my_strdup(name, MYF(MY_WME));
217 }
218
219 extern "C"
220 int
ndb_mgm_set_connectstring(NdbMgmHandle handle,const char * mgmsrv)221 ndb_mgm_set_connectstring(NdbMgmHandle handle, const char * mgmsrv)
222 {
223 DBUG_ENTER("ndb_mgm_set_connectstring");
224 DBUG_PRINT("info", ("handle: 0x%lx", (long) handle));
225 handle->cfg.~LocalConfig();
226 new (&(handle->cfg)) LocalConfig;
227 if (!handle->cfg.init(mgmsrv, 0) ||
228 handle->cfg.ids.size() == 0)
229 {
230 handle->cfg.~LocalConfig();
231 new (&(handle->cfg)) LocalConfig;
232 handle->cfg.init(0, 0); /* reset the LocalConfig */
233 SET_ERROR(handle, NDB_MGM_ILLEGAL_CONNECT_STRING, mgmsrv ? mgmsrv : "");
234 DBUG_RETURN(-1);
235 }
236 handle->cfg_i= -1;
237 DBUG_RETURN(0);
238 }
239
240 extern "C"
241 int
ndb_mgm_set_bindaddress(NdbMgmHandle handle,const char * arg)242 ndb_mgm_set_bindaddress(NdbMgmHandle handle, const char * arg)
243 {
244 DBUG_ENTER("ndb_mgm_set_bindaddress");
245 if (handle->m_bindaddress)
246 free(handle->m_bindaddress);
247
248 if (arg)
249 handle->m_bindaddress = strdup(arg);
250 else
251 handle->m_bindaddress = 0;
252
253 DBUG_RETURN(0);
254 }
255
256 /**
257 * Destroy a handle
258 */
259 extern "C"
260 void
ndb_mgm_destroy_handle(NdbMgmHandle * handle)261 ndb_mgm_destroy_handle(NdbMgmHandle * handle)
262 {
263 DBUG_ENTER("ndb_mgm_destroy_handle");
264 if(!handle)
265 DBUG_VOID_RETURN;
266 DBUG_PRINT("info", ("handle: 0x%lx", (long) (* handle)));
267 /**
268 * important! only disconnect if connected
269 * other code relies on this
270 */
271 if((* handle)->connected){
272 ndb_mgm_disconnect(* handle);
273 }
274 #ifdef MGMAPI_LOG
275 if ((* handle)->logfile != 0){
276 fclose((* handle)->logfile);
277 (* handle)->logfile = 0;
278 }
279 #endif
280 (*handle)->cfg.~LocalConfig();
281 my_free((*handle)->m_name);
282 if ((*handle)->m_bindaddress)
283 free((*handle)->m_bindaddress);
284 my_free(* handle);
285 * handle = 0;
286 DBUG_VOID_RETURN;
287 }
288
289 extern "C"
290 void
ndb_mgm_set_error_stream(NdbMgmHandle handle,FILE * file)291 ndb_mgm_set_error_stream(NdbMgmHandle handle, FILE * file)
292 {
293 handle->errstream = file;
294 }
295
296 /*****************************************************************************
297 * Error handling
298 *****************************************************************************/
299
300 /**
301 * Get latest error associated with a handle
302 */
303 extern "C"
304 int
ndb_mgm_get_latest_error(const NdbMgmHandle h)305 ndb_mgm_get_latest_error(const NdbMgmHandle h)
306 {
307 return h->last_error;
308 }
309
310 extern "C"
311 const char *
ndb_mgm_get_latest_error_desc(const NdbMgmHandle h)312 ndb_mgm_get_latest_error_desc(const NdbMgmHandle h){
313 return h->last_error_desc;
314 }
315
316 extern "C"
317 int
ndb_mgm_get_latest_error_line(const NdbMgmHandle h)318 ndb_mgm_get_latest_error_line(const NdbMgmHandle h)
319 {
320 return h->last_error_line;
321 }
322
323 extern "C"
324 const char *
ndb_mgm_get_latest_error_msg(const NdbMgmHandle h)325 ndb_mgm_get_latest_error_msg(const NdbMgmHandle h)
326 {
327 for (int i=0; i<ndb_mgm_noOfErrorMsgs; i++) {
328 if (ndb_mgm_error_msgs[i].code == h->last_error)
329 return ndb_mgm_error_msgs[i].msg;
330 }
331
332 return "Error"; // Unknown Error message
333 }
334
335 /*
336 * Call an operation, and return the reply
337 */
338 static const Properties *
ndb_mgm_call(NdbMgmHandle handle,const ParserRow<ParserDummy> * command_reply,const char * cmd,const Properties * cmd_args)339 ndb_mgm_call(NdbMgmHandle handle, const ParserRow<ParserDummy> *command_reply,
340 const char *cmd, const Properties *cmd_args)
341 {
342 DBUG_ENTER("ndb_mgm_call");
343 DBUG_PRINT("enter",("handle->socket: %d, cmd: %s",
344 handle->socket, cmd));
345 SocketOutputStream out(handle->socket, handle->timeout);
346 SocketInputStream in(handle->socket, handle->timeout);
347
348 out.println(cmd);
349 #ifdef MGMAPI_LOG
350 /**
351 * Print command to log file
352 */
353 FileOutputStream f(handle->logfile);
354 f.println("OUT: %s", cmd);
355 #endif
356
357 if(cmd_args != NULL) {
358 Properties::Iterator iter(cmd_args);
359 const char *name;
360 while((name = iter.next()) != NULL) {
361 PropertiesType t;
362 Uint32 val_i;
363 Uint64 val_64;
364 BaseString val_s;
365
366 cmd_args->getTypeOf(name, &t);
367 switch(t) {
368 case PropertiesType_Uint32:
369 cmd_args->get(name, &val_i);
370 out.println("%s: %d", name, val_i);
371 break;
372 case PropertiesType_Uint64:
373 cmd_args->get(name, &val_64);
374 out.println("%s: %Ld", name, val_64);
375 break;
376 case PropertiesType_char:
377 cmd_args->get(name, val_s);
378 out.println("%s: %s", name, val_s.c_str());
379 break;
380 case PropertiesType_Properties:
381 DBUG_PRINT("info",("Ignoring PropertiesType_Properties."));
382 /* Ignore */
383 break;
384 default:
385 DBUG_PRINT("info",("Ignoring PropertiesType: %d.",t));
386 }
387 }
388 #ifdef MGMAPI_LOG
389 /**
390 * Print arguments to log file
391 */
392 cmd_args->print(handle->logfile, "OUT: ");
393 #endif
394 }
395 out.println("");
396
397 DBUG_CHECK_TIMEDOUT_RET(handle, in, out, NULL);
398
399 Parser_t::Context ctx;
400 ParserDummy session(handle->socket);
401 Parser_t parser(command_reply, in, true, true, true);
402
403 const Properties* p = parser.parse(ctx, session);
404 if (p == NULL){
405 if(!ndb_mgm_is_connected(handle)) {
406 DBUG_CHECK_TIMEDOUT_RET(handle, in, out, NULL);
407 DBUG_RETURN(NULL);
408 }
409 else
410 {
411 DBUG_CHECK_TIMEDOUT_RET(handle, in, out, NULL);
412 if(ctx.m_status==Parser_t::Eof
413 || ctx.m_status==Parser_t::NoLine)
414 {
415 ndb_mgm_disconnect(handle);
416 DBUG_CHECK_TIMEDOUT_RET(handle, in, out, NULL);
417 DBUG_RETURN(NULL);
418 }
419 /**
420 * Print some info about why the parser returns NULL
421 */
422 fprintf(handle->errstream,
423 "Error in mgm protocol parser. cmd: >%s< status: %d curr: %s\n",
424 cmd, (Uint32)ctx.m_status,
425 (ctx.m_currentToken)?ctx.m_currentToken:"NULL");
426 DBUG_PRINT("info",("ctx.status: %d, ctx.m_currentToken: %s",
427 ctx.m_status, ctx.m_currentToken));
428 }
429 }
430 #ifdef MGMAPI_LOG
431 else {
432 /**
433 * Print reply to log file
434 */
435 p->print(handle->logfile, "IN: ");
436 }
437 #endif
438
439 if(p && (in.timedout() || out.timedout()))
440 delete p;
441 DBUG_CHECK_TIMEDOUT_RET(handle, in, out, NULL);
442 DBUG_RETURN(p);
443 }
444
445 /**
446 * Returns true if connected
447 */
448 extern "C"
ndb_mgm_is_connected(NdbMgmHandle handle)449 int ndb_mgm_is_connected(NdbMgmHandle handle)
450 {
451 if(!handle)
452 return 0;
453
454 if(handle->connected)
455 {
456 if(Ndb_check_socket_hup(handle->socket))
457 {
458 handle->connected= 0;
459 NDB_CLOSE_SOCKET(handle->socket);
460 }
461 }
462 return handle->connected;
463 }
464
465 extern "C"
ndb_mgm_set_connect_timeout(NdbMgmHandle handle,unsigned int seconds)466 int ndb_mgm_set_connect_timeout(NdbMgmHandle handle, unsigned int seconds)
467 {
468 return ndb_mgm_set_timeout(handle, seconds*1000);
469 return 0;
470 }
471
472 extern "C"
ndb_mgm_set_timeout(NdbMgmHandle handle,unsigned int timeout_ms)473 int ndb_mgm_set_timeout(NdbMgmHandle handle, unsigned int timeout_ms)
474 {
475 if(!handle)
476 return -1;
477
478 handle->timeout= timeout_ms;
479 return 0;
480 }
481
482 extern "C"
ndb_mgm_number_of_mgmd_in_connect_string(NdbMgmHandle handle)483 int ndb_mgm_number_of_mgmd_in_connect_string(NdbMgmHandle handle)
484 {
485 int count=0;
486 Uint32 i;
487 LocalConfig &cfg= handle->cfg;
488
489 for (i = 0; i < cfg.ids.size(); i++)
490 {
491 if (cfg.ids[i].type != MgmId_TCP)
492 continue;
493 count++;
494 }
495 return count;
496 }
497
498 /**
499 * Connect to a management server
500 */
501 extern "C"
502 int
ndb_mgm_connect(NdbMgmHandle handle,int no_retries,int retry_delay_in_seconds,int verbose)503 ndb_mgm_connect(NdbMgmHandle handle, int no_retries,
504 int retry_delay_in_seconds, int verbose)
505 {
506 SET_ERROR(handle, NDB_MGM_NO_ERROR, "Executing: ndb_mgm_connect");
507 CHECK_HANDLE(handle, -1);
508
509 DBUG_ENTER("ndb_mgm_connect");
510 #ifdef MGMAPI_LOG
511 /**
512 * Open the log file
513 */
514 char logname[64];
515 BaseString::snprintf(logname, 64, "mgmapi.log");
516 handle->logfile = fopen(logname, "w");
517 #endif
518 char buf[1024];
519
520 /**
521 * Do connect
522 */
523 LocalConfig &cfg= handle->cfg;
524 NDB_SOCKET_TYPE sockfd= NDB_INVALID_SOCKET;
525 Uint32 i;
526 SocketClient s(0, 0);
527 s.set_connect_timeout((handle->timeout+999)/1000);
528 if (!s.init())
529 {
530 fprintf(handle->errstream,
531 "Unable to create socket, "
532 "while trying to connect with connect string: %s\n",
533 cfg.makeConnectString(buf,sizeof(buf)));
534
535 setError(handle, NDB_MGM_COULD_NOT_CONNECT_TO_SOCKET, __LINE__,
536 "Unable to create socket, "
537 "while trying to connect with connect string: %s\n",
538 cfg.makeConnectString(buf,sizeof(buf)));
539 DBUG_RETURN(-1);
540 }
541
542 if (handle->m_bindaddress)
543 {
544 BaseString::snprintf(buf, sizeof(buf), handle->m_bindaddress);
545 unsigned short portno = 0;
546 char * port = strchr(buf, ':');
547 if (port != 0)
548 {
549 portno = atoi(port+1);
550 * port = 0;
551 }
552 int err;
553 if ((err = s.bind(buf, portno)) != 0)
554 {
555 fprintf(handle->errstream,
556 "Unable to bind local address %s errno: %d, "
557 "while trying to connect with connect string: %s\n",
558 handle->m_bindaddress, err,
559 cfg.makeConnectString(buf,sizeof(buf)));
560
561 setError(handle, NDB_MGM_BIND_ADDRESS, __LINE__,
562 "Unable to bind local address %s errno: %d, "
563 "while trying to connect with connect string: %s\n",
564 handle->m_bindaddress, err,
565 cfg.makeConnectString(buf,sizeof(buf)));
566 DBUG_RETURN(-1);
567 }
568 }
569
570 while (sockfd == NDB_INVALID_SOCKET)
571 {
572 // do all the mgmt servers
573 for (i = 0; i < cfg.ids.size(); i++)
574 {
575 if (cfg.ids[i].type != MgmId_TCP)
576 continue;
577 sockfd = s.connect(cfg.ids[i].name.c_str(), cfg.ids[i].port);
578 if (sockfd != NDB_INVALID_SOCKET)
579 break;
580 }
581 if (sockfd != NDB_INVALID_SOCKET)
582 break;
583 #ifndef DBUG_OFF
584 {
585 DBUG_PRINT("info",("Unable to connect with connect string: %s",
586 cfg.makeConnectString(buf,sizeof(buf))));
587 }
588 #endif
589 if (verbose > 0) {
590 fprintf(handle->errstream,
591 "Unable to connect with connect string: %s\n",
592 cfg.makeConnectString(buf,sizeof(buf)));
593 verbose= -1;
594 }
595 if (no_retries == 0) {
596 setError(handle, NDB_MGM_COULD_NOT_CONNECT_TO_SOCKET, __LINE__,
597 "Unable to connect with connect string: %s",
598 cfg.makeConnectString(buf,sizeof(buf)));
599 if (verbose == -2)
600 fprintf(handle->errstream, ", failed.\n");
601 DBUG_RETURN(-1);
602 }
603 if (verbose == -1) {
604 fprintf(handle->errstream, "Retrying every %d seconds",
605 retry_delay_in_seconds);
606 if (no_retries > 0)
607 fprintf(handle->errstream, ". Attempts left:");
608 else
609 fprintf(handle->errstream, ", until connected.");
610 fflush(handle->errstream);
611 verbose= -2;
612 }
613 if (no_retries > 0) {
614 if (verbose == -2) {
615 fprintf(handle->errstream, " %d", no_retries);
616 fflush(handle->errstream);
617 }
618 no_retries--;
619 }
620 NdbSleep_SecSleep(retry_delay_in_seconds);
621 }
622 if (verbose == -2)
623 {
624 fprintf(handle->errstream, "\n");
625 fflush(handle->errstream);
626 }
627 handle->cfg_i = i;
628
629 handle->socket = sockfd;
630 handle->connected = 1;
631
632 DBUG_RETURN(0);
633 }
634
635 /**
636 * Only used for low level testing
637 * Never to be used by end user.
638 * Or anybody who doesn't know exactly what they're doing.
639 */
640 extern "C"
641 int
ndb_mgm_get_fd(NdbMgmHandle handle)642 ndb_mgm_get_fd(NdbMgmHandle handle)
643 {
644 return handle->socket;
645 }
646
647 /**
648 * Disconnect from mgm server without error checking
649 * Should be used internally only.
650 * e.g. on timeout, we leave NdbMgmHandle disconnected
651 */
652 extern "C"
653 int
ndb_mgm_disconnect_quiet(NdbMgmHandle handle)654 ndb_mgm_disconnect_quiet(NdbMgmHandle handle)
655 {
656 NDB_CLOSE_SOCKET(handle->socket);
657 handle->socket = NDB_INVALID_SOCKET;
658 handle->connected = 0;
659
660 return 0;
661 }
662
663 /**
664 * Disconnect from a mgm server
665 */
666 extern "C"
667 int
ndb_mgm_disconnect(NdbMgmHandle handle)668 ndb_mgm_disconnect(NdbMgmHandle handle)
669 {
670 SET_ERROR(handle, NDB_MGM_NO_ERROR, "Executing: ndb_mgm_disconnect");
671 CHECK_HANDLE(handle, -1);
672 CHECK_CONNECTED(handle, -1);
673
674 return ndb_mgm_disconnect_quiet(handle);
675 }
676
677 struct ndb_mgm_type_atoi
678 {
679 const char * str;
680 const char * alias;
681 enum ndb_mgm_node_type value;
682 };
683
684 static struct ndb_mgm_type_atoi type_values[] =
685 {
686 { "NDB", "ndbd", NDB_MGM_NODE_TYPE_NDB},
687 { "API", "mysqld", NDB_MGM_NODE_TYPE_API },
688 { "MGM", "ndb_mgmd", NDB_MGM_NODE_TYPE_MGM }
689 };
690
691 const int no_of_type_values = (sizeof(type_values) /
692 sizeof(ndb_mgm_type_atoi));
693
694 extern "C"
695 ndb_mgm_node_type
ndb_mgm_match_node_type(const char * type)696 ndb_mgm_match_node_type(const char * type)
697 {
698 if(type == 0)
699 return NDB_MGM_NODE_TYPE_UNKNOWN;
700
701 for(int i = 0; i<no_of_type_values; i++)
702 if(strcmp(type, type_values[i].str) == 0)
703 return type_values[i].value;
704 else if(strcmp(type, type_values[i].alias) == 0)
705 return type_values[i].value;
706
707 return NDB_MGM_NODE_TYPE_UNKNOWN;
708 }
709
710 extern "C"
711 const char *
ndb_mgm_get_node_type_string(enum ndb_mgm_node_type type)712 ndb_mgm_get_node_type_string(enum ndb_mgm_node_type type)
713 {
714 for(int i = 0; i<no_of_type_values; i++)
715 if(type_values[i].value == type)
716 return type_values[i].str;
717 return 0;
718 }
719
720 extern "C"
721 const char *
ndb_mgm_get_node_type_alias_string(enum ndb_mgm_node_type type,const char ** str)722 ndb_mgm_get_node_type_alias_string(enum ndb_mgm_node_type type, const char** str)
723 {
724 for(int i = 0; i<no_of_type_values; i++)
725 if(type_values[i].value == type)
726 {
727 if (str)
728 *str= type_values[i].str;
729 return type_values[i].alias;
730 }
731 return 0;
732 }
733
734 struct ndb_mgm_status_atoi {
735 const char * str;
736 enum ndb_mgm_node_status value;
737 };
738
739 static struct ndb_mgm_status_atoi status_values[] =
740 {
741 { "UNKNOWN", NDB_MGM_NODE_STATUS_UNKNOWN },
742 { "NO_CONTACT", NDB_MGM_NODE_STATUS_NO_CONTACT },
743 { "NOT_STARTED", NDB_MGM_NODE_STATUS_NOT_STARTED },
744 { "STARTING", NDB_MGM_NODE_STATUS_STARTING },
745 { "STARTED", NDB_MGM_NODE_STATUS_STARTED },
746 { "SHUTTING_DOWN", NDB_MGM_NODE_STATUS_SHUTTING_DOWN },
747 { "RESTARTING", NDB_MGM_NODE_STATUS_RESTARTING },
748 { "SINGLE USER MODE", NDB_MGM_NODE_STATUS_SINGLEUSER }
749 };
750
751 const int no_of_status_values = (sizeof(status_values) /
752 sizeof(ndb_mgm_status_atoi));
753
754 extern "C"
755 ndb_mgm_node_status
ndb_mgm_match_node_status(const char * status)756 ndb_mgm_match_node_status(const char * status)
757 {
758 if(status == 0)
759 return NDB_MGM_NODE_STATUS_UNKNOWN;
760
761 for(int i = 0; i<no_of_status_values; i++)
762 if(strcmp(status, status_values[i].str) == 0)
763 return status_values[i].value;
764
765 return NDB_MGM_NODE_STATUS_UNKNOWN;
766 }
767
768 extern "C"
769 const char *
ndb_mgm_get_node_status_string(enum ndb_mgm_node_status status)770 ndb_mgm_get_node_status_string(enum ndb_mgm_node_status status)
771 {
772 int i;
773 for(i = 0; i<no_of_status_values; i++)
774 if(status_values[i].value == status)
775 return status_values[i].str;
776
777 for(i = 0; i<no_of_status_values; i++)
778 if(status_values[i].value == NDB_MGM_NODE_STATUS_UNKNOWN)
779 return status_values[i].str;
780
781 return 0;
782 }
783
784 static int
status_ackumulate(struct ndb_mgm_node_state * state,const char * field,const char * value)785 status_ackumulate(struct ndb_mgm_node_state * state,
786 const char * field,
787 const char * value)
788 {
789 if(strcmp("type", field) == 0){
790 state->node_type = ndb_mgm_match_node_type(value);
791 } else if(strcmp("status", field) == 0){
792 state->node_status = ndb_mgm_match_node_status(value);
793 } else if(strcmp("startphase", field) == 0){
794 state->start_phase = atoi(value);
795 } else if(strcmp("dynamic_id", field) == 0){
796 state->dynamic_id = atoi(value);
797 } else if(strcmp("node_group", field) == 0){
798 state->node_group = atoi(value);
799 } else if(strcmp("version", field) == 0){
800 state->version = atoi(value);
801 } else if(strcmp("connect_count", field) == 0){
802 state->connect_count = atoi(value);
803 } else if(strcmp("address", field) == 0){
804 strncpy(state->connect_address, value, sizeof(state->connect_address));
805 state->connect_address[sizeof(state->connect_address)-1]= 0;
806 } else {
807 ndbout_c("Unknown field: %s", field);
808 }
809 return 0;
810 }
811
812 /**
813 * Compare function for qsort() that sorts ndb_mgm_node_state in
814 * node_id order
815 */
816 static int
cmp_state(const void * _a,const void * _b)817 cmp_state(const void *_a, const void *_b)
818 {
819 struct ndb_mgm_node_state *a, *b;
820
821 a = (struct ndb_mgm_node_state *)_a;
822 b = (struct ndb_mgm_node_state *)_b;
823
824 if (a->node_id > b->node_id)
825 return 1;
826 return -1;
827 }
828
829 extern "C"
830 struct ndb_mgm_cluster_state *
ndb_mgm_get_status(NdbMgmHandle handle)831 ndb_mgm_get_status(NdbMgmHandle handle)
832 {
833 SET_ERROR(handle, NDB_MGM_NO_ERROR, "Executing: ndb_mgm_get_status");
834 CHECK_HANDLE(handle, NULL);
835 CHECK_CONNECTED(handle, NULL);
836
837 SocketOutputStream out(handle->socket, handle->timeout);
838 SocketInputStream in(handle->socket, handle->timeout);
839
840 out.println("get status");
841 out.println("");
842
843 CHECK_TIMEDOUT_RET(handle, in, out, NULL);
844
845 char buf[1024];
846 if(!in.gets(buf, sizeof(buf)))
847 {
848 CHECK_TIMEDOUT_RET(handle, in, out, NULL);
849 SET_ERROR(handle, NDB_MGM_ILLEGAL_SERVER_REPLY, "Probably disconnected");
850 return NULL;
851 }
852 if(strcmp("node status\n", buf) != 0) {
853 CHECK_TIMEDOUT_RET(handle, in, out, NULL);
854 ndbout << in.timedout() << " " << out.timedout() << buf << endl;
855 SET_ERROR(handle, NDB_MGM_ILLEGAL_NODE_STATUS, buf);
856 return NULL;
857 }
858 if(!in.gets(buf, sizeof(buf)))
859 {
860 CHECK_TIMEDOUT_RET(handle, in, out, NULL);
861 SET_ERROR(handle, NDB_MGM_ILLEGAL_SERVER_REPLY, "Probably disconnected");
862 return NULL;
863 }
864
865 BaseString tmp(buf);
866 Vector<BaseString> split;
867 tmp.split(split, ":");
868 if(split.size() != 2){
869 CHECK_TIMEDOUT_RET(handle, in, out, NULL);
870 SET_ERROR(handle, NDB_MGM_ILLEGAL_NODE_STATUS, buf);
871 return NULL;
872 }
873
874 if(!(split[0].trim() == "nodes")){
875 SET_ERROR(handle, NDB_MGM_ILLEGAL_NODE_STATUS, buf);
876 return NULL;
877 }
878
879 const int noOfNodes = atoi(split[1].c_str());
880
881 ndb_mgm_cluster_state *state = (ndb_mgm_cluster_state*)
882 malloc(sizeof(ndb_mgm_cluster_state)+
883 noOfNodes*(sizeof(ndb_mgm_node_state)+sizeof("000.000.000.000#")));
884
885 if(!state)
886 {
887 SET_ERROR(handle, NDB_MGM_OUT_OF_MEMORY,
888 "Allocating ndb_mgm_cluster_state");
889 return NULL;
890 }
891
892 state->no_of_nodes= noOfNodes;
893 ndb_mgm_node_state * ptr = &state->node_states[0];
894 int nodeId = 0;
895 int i;
896 for (i= 0; i < noOfNodes; i++) {
897 state->node_states[i].connect_address[0]= 0;
898 }
899 i = -1; ptr--;
900 for(; i<noOfNodes; ){
901 if(!in.gets(buf, sizeof(buf)))
902 {
903 free(state);
904 if(in.timedout() || out.timedout())
905 SET_ERROR(handle, ETIMEDOUT,
906 "Time out talking to management server");
907 else
908 SET_ERROR(handle, NDB_MGM_ILLEGAL_SERVER_REPLY,
909 "Probably disconnected");
910 return NULL;
911 }
912 tmp.assign(buf);
913
914 if(tmp.trim() == ""){
915 break;
916 }
917
918 Vector<BaseString> split2;
919 tmp.split(split2, ":.", 4);
920 if(split2.size() != 4)
921 break;
922
923 const int id = atoi(split2[1].c_str());
924 if(id != nodeId){
925 ptr++;
926 i++;
927 nodeId = id;
928 ptr->node_id = id;
929 }
930
931 split2[3].trim(" \t\n");
932
933 if(status_ackumulate(ptr,split2[2].c_str(), split2[3].c_str()) != 0) {
934 break;
935 }
936 }
937
938 if(i+1 != noOfNodes){
939 free(state);
940 CHECK_TIMEDOUT_RET(handle, in, out, NULL);
941 SET_ERROR(handle, NDB_MGM_ILLEGAL_NODE_STATUS, "Node count mismatch");
942 return NULL;
943 }
944
945 qsort(state->node_states, state->no_of_nodes, sizeof(state->node_states[0]),
946 cmp_state);
947 return state;
948 }
949
950 extern "C"
951 int
ndb_mgm_enter_single_user(NdbMgmHandle handle,unsigned int nodeId,struct ndb_mgm_reply *)952 ndb_mgm_enter_single_user(NdbMgmHandle handle,
953 unsigned int nodeId,
954 struct ndb_mgm_reply* /*reply*/)
955 {
956 SET_ERROR(handle, NDB_MGM_NO_ERROR, "Executing: ndb_mgm_enter_single_user");
957 const ParserRow<ParserDummy> enter_single_reply[] = {
958 MGM_CMD("enter single user reply", NULL, ""),
959 MGM_ARG("result", String, Mandatory, "Error message"),
960 MGM_END()
961 };
962 CHECK_HANDLE(handle, -1);
963 CHECK_CONNECTED(handle, -1);
964
965 Properties args;
966 args.put("nodeId", nodeId);
967 const Properties *reply;
968 reply = ndb_mgm_call(handle, enter_single_reply, "enter single user", &args);
969 CHECK_REPLY(handle, reply, -1);
970
971 BaseString result;
972 reply->get("result", result);
973 if(strcmp(result.c_str(), "Ok") != 0) {
974 SET_ERROR(handle, NDB_MGM_COULD_NOT_ENTER_SINGLE_USER_MODE,
975 result.c_str());
976 delete reply;
977 return -1;
978 }
979
980 delete reply;
981 return 0;
982 }
983
984
985 extern "C"
986 int
ndb_mgm_exit_single_user(NdbMgmHandle handle,struct ndb_mgm_reply *)987 ndb_mgm_exit_single_user(NdbMgmHandle handle, struct ndb_mgm_reply* /*reply*/)
988 {
989 SET_ERROR(handle, NDB_MGM_NO_ERROR, "Executing: ndb_mgm_exit_single_user");
990 const ParserRow<ParserDummy> exit_single_reply[] = {
991 MGM_CMD("exit single user reply", NULL, ""),
992 MGM_ARG("result", String, Mandatory, "Error message"),
993 MGM_END()
994 };
995 CHECK_HANDLE(handle, -1);
996 CHECK_CONNECTED(handle, -1);
997
998 const Properties *reply;
999 reply = ndb_mgm_call(handle, exit_single_reply, "exit single user", 0);
1000 CHECK_REPLY(handle, reply, -1);
1001
1002 const char * buf;
1003 reply->get("result", &buf);
1004 if(strcmp(buf,"Ok")!=0) {
1005 SET_ERROR(handle, NDB_MGM_COULD_NOT_EXIT_SINGLE_USER_MODE, buf);
1006 delete reply;
1007 return -1;
1008 }
1009
1010 delete reply;
1011 return 0;
1012 }
1013
1014 extern "C"
1015 int
ndb_mgm_stop(NdbMgmHandle handle,int no_of_nodes,const int * node_list)1016 ndb_mgm_stop(NdbMgmHandle handle, int no_of_nodes, const int * node_list)
1017 {
1018 SET_ERROR(handle, NDB_MGM_NO_ERROR, "Executing: ndb_mgm_stop");
1019 return ndb_mgm_stop2(handle, no_of_nodes, node_list, 0);
1020 }
1021
1022 extern "C"
1023 int
ndb_mgm_stop2(NdbMgmHandle handle,int no_of_nodes,const int * node_list,int abort)1024 ndb_mgm_stop2(NdbMgmHandle handle, int no_of_nodes, const int * node_list,
1025 int abort)
1026 {
1027 int disconnect;
1028 return ndb_mgm_stop3(handle, no_of_nodes, node_list, abort, &disconnect);
1029 }
1030
1031
1032 extern "C"
1033 int
ndb_mgm_stop3(NdbMgmHandle handle,int no_of_nodes,const int * node_list,int abort,int * disconnect)1034 ndb_mgm_stop3(NdbMgmHandle handle, int no_of_nodes, const int * node_list,
1035 int abort, int *disconnect)
1036 {
1037 SET_ERROR(handle, NDB_MGM_NO_ERROR, "Executing: ndb_mgm_stop3");
1038 const ParserRow<ParserDummy> stop_reply_v1[] = {
1039 MGM_CMD("stop reply", NULL, ""),
1040 MGM_ARG("stopped", Int, Optional, "No of stopped nodes"),
1041 MGM_ARG("result", String, Mandatory, "Error message"),
1042 MGM_END()
1043 };
1044 const ParserRow<ParserDummy> stop_reply_v2[] = {
1045 MGM_CMD("stop reply", NULL, ""),
1046 MGM_ARG("stopped", Int, Optional, "No of stopped nodes"),
1047 MGM_ARG("result", String, Mandatory, "Error message"),
1048 MGM_ARG("disconnect", Int, Mandatory, "Need to disconnect"),
1049 MGM_END()
1050 };
1051
1052 CHECK_HANDLE(handle, -1);
1053 CHECK_CONNECTED(handle, -1);
1054
1055 if(handle->mgmd_version_build==-1)
1056 {
1057 char verstr[50];
1058 if(!ndb_mgm_get_version(handle,
1059 &(handle->mgmd_version_major),
1060 &(handle->mgmd_version_minor),
1061 &(handle->mgmd_version_build),
1062 sizeof(verstr),
1063 verstr))
1064 {
1065 return -1;
1066 }
1067 }
1068 int use_v2= ((handle->mgmd_version_major==5)
1069 && (
1070 (handle->mgmd_version_minor==0 && handle->mgmd_version_build>=21)
1071 ||(handle->mgmd_version_minor==1 && handle->mgmd_version_build>=12)
1072 ||(handle->mgmd_version_minor>1)
1073 )
1074 )
1075 || (handle->mgmd_version_major>5);
1076
1077 if(no_of_nodes < -1){
1078 SET_ERROR(handle, NDB_MGM_ILLEGAL_NUMBER_OF_NODES,
1079 "Negative number of nodes requested to stop");
1080 return -1;
1081 }
1082
1083 Uint32 stoppedNoOfNodes = 0;
1084 if(no_of_nodes <= 0){
1085 /**
1086 * All nodes should be stopped (all or just db)
1087 */
1088 Properties args;
1089 args.put("abort", abort);
1090 if(use_v2)
1091 args.put("stop", (no_of_nodes==-1)?"mgm,db":"db");
1092 const Properties *reply;
1093 if(use_v2)
1094 reply = ndb_mgm_call(handle, stop_reply_v2, "stop all", &args);
1095 else
1096 reply = ndb_mgm_call(handle, stop_reply_v1, "stop all", &args);
1097 CHECK_REPLY(handle, reply, -1);
1098
1099 if(!reply->get("stopped", &stoppedNoOfNodes)){
1100 SET_ERROR(handle, NDB_MGM_STOP_FAILED,
1101 "Could not get number of stopped nodes from mgm server");
1102 delete reply;
1103 return -1;
1104 }
1105 if(use_v2)
1106 reply->get("disconnect", (Uint32*)disconnect);
1107 else
1108 *disconnect= 0;
1109 BaseString result;
1110 reply->get("result", result);
1111 if(strcmp(result.c_str(), "Ok") != 0) {
1112 SET_ERROR(handle, NDB_MGM_STOP_FAILED, result.c_str());
1113 delete reply;
1114 return -1;
1115 }
1116 delete reply;
1117 return stoppedNoOfNodes;
1118 }
1119
1120 /**
1121 * A list of database nodes should be stopped
1122 */
1123 Properties args;
1124
1125 BaseString node_list_str;
1126 node_list_str.assfmt("%d", node_list[0]);
1127 for(int node = 1; node < no_of_nodes; node++)
1128 node_list_str.appfmt(" %d", node_list[node]);
1129
1130 args.put("node", node_list_str.c_str());
1131 args.put("abort", abort);
1132
1133 const Properties *reply;
1134 if(use_v2)
1135 reply = ndb_mgm_call(handle, stop_reply_v2, "stop v2", &args);
1136 else
1137 reply = ndb_mgm_call(handle, stop_reply_v1, "stop", &args);
1138
1139 CHECK_REPLY(handle, reply, stoppedNoOfNodes);
1140 if(!reply->get("stopped", &stoppedNoOfNodes)){
1141 SET_ERROR(handle, NDB_MGM_STOP_FAILED,
1142 "Could not get number of stopped nodes from mgm server");
1143 delete reply;
1144 return -1;
1145 }
1146 if(use_v2)
1147 reply->get("disconnect", (Uint32*)disconnect);
1148 else
1149 *disconnect= 0;
1150 BaseString result;
1151 reply->get("result", result);
1152 if(strcmp(result.c_str(), "Ok") != 0) {
1153 SET_ERROR(handle, NDB_MGM_STOP_FAILED, result.c_str());
1154 delete reply;
1155 return -1;
1156 }
1157 delete reply;
1158 return stoppedNoOfNodes;
1159 }
1160
1161 extern "C"
1162 int
ndb_mgm_restart(NdbMgmHandle handle,int no_of_nodes,const int * node_list)1163 ndb_mgm_restart(NdbMgmHandle handle, int no_of_nodes, const int *node_list)
1164 {
1165 SET_ERROR(handle, NDB_MGM_NO_ERROR, "Executing: ndb_mgm_restart");
1166 return ndb_mgm_restart2(handle, no_of_nodes, node_list, 0, 0, 0);
1167 }
1168
1169 extern "C"
1170 int
ndb_mgm_restart2(NdbMgmHandle handle,int no_of_nodes,const int * node_list,int initial,int nostart,int abort)1171 ndb_mgm_restart2(NdbMgmHandle handle, int no_of_nodes, const int * node_list,
1172 int initial, int nostart, int abort)
1173 {
1174 int disconnect;
1175
1176 return ndb_mgm_restart3(handle, no_of_nodes, node_list, initial, nostart,
1177 abort, &disconnect);
1178 }
1179
1180 extern "C"
1181 int
ndb_mgm_restart3(NdbMgmHandle handle,int no_of_nodes,const int * node_list,int initial,int nostart,int abort,int * disconnect)1182 ndb_mgm_restart3(NdbMgmHandle handle, int no_of_nodes, const int * node_list,
1183 int initial, int nostart, int abort, int *disconnect)
1184 {
1185 SET_ERROR(handle, NDB_MGM_NO_ERROR, "Executing: ndb_mgm_restart3");
1186 Uint32 restarted = 0;
1187 const ParserRow<ParserDummy> restart_reply_v1[] = {
1188 MGM_CMD("restart reply", NULL, ""),
1189 MGM_ARG("result", String, Mandatory, "Error message"),
1190 MGM_ARG("restarted", Int, Optional, "No of restarted nodes"),
1191 MGM_END()
1192 };
1193 const ParserRow<ParserDummy> restart_reply_v2[] = {
1194 MGM_CMD("restart reply", NULL, ""),
1195 MGM_ARG("result", String, Mandatory, "Error message"),
1196 MGM_ARG("restarted", Int, Optional, "No of restarted nodes"),
1197 MGM_ARG("disconnect", Int, Optional, "Disconnect to apply"),
1198 MGM_END()
1199 };
1200
1201 CHECK_HANDLE(handle, -1);
1202 CHECK_CONNECTED(handle, -1);
1203
1204 if(handle->mgmd_version_build==-1)
1205 {
1206 char verstr[50];
1207 if(!ndb_mgm_get_version(handle,
1208 &(handle->mgmd_version_major),
1209 &(handle->mgmd_version_minor),
1210 &(handle->mgmd_version_build),
1211 sizeof(verstr),
1212 verstr))
1213 {
1214 return -1;
1215 }
1216 }
1217 int use_v2= ((handle->mgmd_version_major==5)
1218 && (
1219 (handle->mgmd_version_minor==0 && handle->mgmd_version_build>=21)
1220 ||(handle->mgmd_version_minor==1 && handle->mgmd_version_build>=12)
1221 ||(handle->mgmd_version_minor>1)
1222 )
1223 )
1224 || (handle->mgmd_version_major>5);
1225
1226 if(no_of_nodes < 0){
1227 SET_ERROR(handle, NDB_MGM_RESTART_FAILED,
1228 "Restart requested of negative number of nodes");
1229 return -1;
1230 }
1231
1232 if(no_of_nodes == 0) {
1233 Properties args;
1234 args.put("abort", abort);
1235 args.put("initialstart", initial);
1236 args.put("nostart", nostart);
1237 const Properties *reply;
1238 const int timeout = handle->timeout;
1239 handle->timeout= 5*60*1000; // 5 minutes
1240 reply = ndb_mgm_call(handle, restart_reply_v1, "restart all", &args);
1241 handle->timeout= timeout;
1242 CHECK_REPLY(handle, reply, -1);
1243
1244 BaseString result;
1245 reply->get("result", result);
1246 if(strcmp(result.c_str(), "Ok") != 0) {
1247 SET_ERROR(handle, NDB_MGM_RESTART_FAILED, result.c_str());
1248 delete reply;
1249 return -1;
1250 }
1251 if(!reply->get("restarted", &restarted)){
1252 SET_ERROR(handle, NDB_MGM_RESTART_FAILED,
1253 "Could not get restarted number of nodes from mgm server");
1254 delete reply;
1255 return -1;
1256 }
1257 delete reply;
1258 return restarted;
1259 }
1260
1261 BaseString node_list_str;
1262 node_list_str.assfmt("%d", node_list[0]);
1263 for(int node = 1; node < no_of_nodes; node++)
1264 node_list_str.appfmt(" %d", node_list[node]);
1265
1266 Properties args;
1267
1268 args.put("node", node_list_str.c_str());
1269 args.put("abort", abort);
1270 args.put("initialstart", initial);
1271 args.put("nostart", nostart);
1272
1273 const Properties *reply;
1274 const int timeout = handle->timeout;
1275 handle->timeout= 5*60*1000; // 5 minutes
1276 if(use_v2)
1277 reply = ndb_mgm_call(handle, restart_reply_v2, "restart node v2", &args);
1278 else
1279 reply = ndb_mgm_call(handle, restart_reply_v1, "restart node", &args);
1280 handle->timeout= timeout;
1281 if(reply != NULL) {
1282 BaseString result;
1283 reply->get("result", result);
1284 if(strcmp(result.c_str(), "Ok") != 0) {
1285 SET_ERROR(handle, NDB_MGM_RESTART_FAILED, result.c_str());
1286 delete reply;
1287 return -1;
1288 }
1289 reply->get("restarted", &restarted);
1290 if(use_v2)
1291 reply->get("disconnect", (Uint32*)disconnect);
1292 else
1293 *disconnect= 0;
1294 delete reply;
1295 }
1296
1297 return restarted;
1298 }
1299
1300 static const char *clusterlog_severity_names[]=
1301 { "enabled", "debug", "info", "warning", "error", "critical", "alert" };
1302
1303 struct ndb_mgm_event_severities
1304 {
1305 const char* name;
1306 enum ndb_mgm_event_severity severity;
1307 } clusterlog_severities[] = {
1308 { clusterlog_severity_names[0], NDB_MGM_EVENT_SEVERITY_ON },
1309 { clusterlog_severity_names[1], NDB_MGM_EVENT_SEVERITY_DEBUG },
1310 { clusterlog_severity_names[2], NDB_MGM_EVENT_SEVERITY_INFO },
1311 { clusterlog_severity_names[3], NDB_MGM_EVENT_SEVERITY_WARNING },
1312 { clusterlog_severity_names[4], NDB_MGM_EVENT_SEVERITY_ERROR },
1313 { clusterlog_severity_names[5], NDB_MGM_EVENT_SEVERITY_CRITICAL },
1314 { clusterlog_severity_names[6], NDB_MGM_EVENT_SEVERITY_ALERT },
1315 { "all", NDB_MGM_EVENT_SEVERITY_ALL },
1316 { 0, NDB_MGM_ILLEGAL_EVENT_SEVERITY },
1317 };
1318
1319 extern "C"
1320 ndb_mgm_event_severity
ndb_mgm_match_event_severity(const char * name)1321 ndb_mgm_match_event_severity(const char * name)
1322 {
1323 if(name == 0)
1324 return NDB_MGM_ILLEGAL_EVENT_SEVERITY;
1325
1326 for(int i = 0; clusterlog_severities[i].name !=0 ; i++)
1327 if(strcasecmp(name, clusterlog_severities[i].name) == 0)
1328 return clusterlog_severities[i].severity;
1329
1330 return NDB_MGM_ILLEGAL_EVENT_SEVERITY;
1331 }
1332
1333 extern "C"
1334 const char *
ndb_mgm_get_event_severity_string(enum ndb_mgm_event_severity severity)1335 ndb_mgm_get_event_severity_string(enum ndb_mgm_event_severity severity)
1336 {
1337 int i= (int)severity;
1338 if (i >= 0 && i < (int)NDB_MGM_EVENT_SEVERITY_ALL)
1339 return clusterlog_severity_names[i];
1340 for(i = (int)NDB_MGM_EVENT_SEVERITY_ALL; clusterlog_severities[i].name != 0; i++)
1341 if(clusterlog_severities[i].severity == severity)
1342 return clusterlog_severities[i].name;
1343 return 0;
1344 }
1345
1346 extern "C"
1347 int
ndb_mgm_get_clusterlog_severity_filter(NdbMgmHandle handle,struct ndb_mgm_severity * severity,unsigned int severity_size)1348 ndb_mgm_get_clusterlog_severity_filter(NdbMgmHandle handle,
1349 struct ndb_mgm_severity* severity,
1350 unsigned int severity_size)
1351 {
1352 SET_ERROR(handle, NDB_MGM_NO_ERROR, "Executing: ndb_mgm_get_clusterlog_severity_filter");
1353 const ParserRow<ParserDummy> getinfo_reply[] = {
1354 MGM_CMD("clusterlog", NULL, ""),
1355 MGM_ARG(clusterlog_severity_names[0], Int, Mandatory, ""),
1356 MGM_ARG(clusterlog_severity_names[1], Int, Mandatory, ""),
1357 MGM_ARG(clusterlog_severity_names[2], Int, Mandatory, ""),
1358 MGM_ARG(clusterlog_severity_names[3], Int, Mandatory, ""),
1359 MGM_ARG(clusterlog_severity_names[4], Int, Mandatory, ""),
1360 MGM_ARG(clusterlog_severity_names[5], Int, Mandatory, ""),
1361 MGM_ARG(clusterlog_severity_names[6], Int, Mandatory, ""),
1362 };
1363 CHECK_HANDLE(handle, -1);
1364 CHECK_CONNECTED(handle, -1);
1365
1366 Properties args;
1367 const Properties *reply;
1368 reply = ndb_mgm_call(handle, getinfo_reply, "get info clusterlog", &args);
1369 CHECK_REPLY(handle, reply, -1);
1370
1371 for(unsigned int i=0; i < severity_size; i++) {
1372 reply->get(clusterlog_severity_names[severity[i].category], &severity[i].value);
1373 }
1374 return severity_size;
1375 }
1376
1377 extern "C"
1378 const unsigned int *
ndb_mgm_get_clusterlog_severity_filter_old(NdbMgmHandle handle)1379 ndb_mgm_get_clusterlog_severity_filter_old(NdbMgmHandle handle)
1380 {
1381 SET_ERROR(handle, NDB_MGM_NO_ERROR, "Executing: ndb_mgm_get_clusterlog_severity_filter");
1382 static unsigned int enabled[(int)NDB_MGM_EVENT_SEVERITY_ALL]=
1383 {0,0,0,0,0,0,0};
1384 const ParserRow<ParserDummy> getinfo_reply[] = {
1385 MGM_CMD("clusterlog", NULL, ""),
1386 MGM_ARG(clusterlog_severity_names[0], Int, Mandatory, ""),
1387 MGM_ARG(clusterlog_severity_names[1], Int, Mandatory, ""),
1388 MGM_ARG(clusterlog_severity_names[2], Int, Mandatory, ""),
1389 MGM_ARG(clusterlog_severity_names[3], Int, Mandatory, ""),
1390 MGM_ARG(clusterlog_severity_names[4], Int, Mandatory, ""),
1391 MGM_ARG(clusterlog_severity_names[5], Int, Mandatory, ""),
1392 MGM_ARG(clusterlog_severity_names[6], Int, Mandatory, ""),
1393 };
1394 CHECK_HANDLE(handle, NULL);
1395 CHECK_CONNECTED(handle, NULL);
1396
1397 Properties args;
1398 const Properties *reply;
1399 reply = ndb_mgm_call(handle, getinfo_reply, "get info clusterlog", &args);
1400 CHECK_REPLY(handle, reply, NULL);
1401
1402 for(int i=0; i < (int)NDB_MGM_EVENT_SEVERITY_ALL; i++) {
1403 reply->get(clusterlog_severity_names[i], &enabled[i]);
1404 }
1405 return enabled;
1406 }
1407
1408 extern "C"
1409 int
ndb_mgm_set_clusterlog_severity_filter(NdbMgmHandle handle,enum ndb_mgm_event_severity severity,int enable,struct ndb_mgm_reply *)1410 ndb_mgm_set_clusterlog_severity_filter(NdbMgmHandle handle,
1411 enum ndb_mgm_event_severity severity,
1412 int enable,
1413 struct ndb_mgm_reply* /*reply*/)
1414 {
1415 SET_ERROR(handle, NDB_MGM_NO_ERROR,
1416 "Executing: ndb_mgm_set_clusterlog_severity_filter");
1417 const ParserRow<ParserDummy> filter_reply[] = {
1418 MGM_CMD("set logfilter reply", NULL, ""),
1419 MGM_ARG("result", String, Mandatory, "Error message"),
1420 MGM_END()
1421 };
1422 int retval = -1;
1423 CHECK_HANDLE(handle, -1);
1424 CHECK_CONNECTED(handle, -1);
1425
1426 Properties args;
1427 args.put("level", severity);
1428 args.put("enable", enable);
1429
1430 const Properties *reply;
1431 reply = ndb_mgm_call(handle, filter_reply, "set logfilter", &args);
1432 CHECK_REPLY(handle, reply, retval);
1433
1434 BaseString result;
1435 reply->get("result", result);
1436
1437 if (strcmp(result.c_str(), "1") == 0)
1438 retval = 1;
1439 else if (strcmp(result.c_str(), "0") == 0)
1440 retval = 0;
1441 else
1442 {
1443 SET_ERROR(handle, EINVAL, result.c_str());
1444 }
1445 delete reply;
1446 return retval;
1447 }
1448
1449 struct ndb_mgm_event_categories
1450 {
1451 const char* name;
1452 enum ndb_mgm_event_category category;
1453 } categories[] = {
1454 { "STARTUP", NDB_MGM_EVENT_CATEGORY_STARTUP },
1455 { "SHUTDOWN", NDB_MGM_EVENT_CATEGORY_SHUTDOWN },
1456 { "STATISTICS", NDB_MGM_EVENT_CATEGORY_STATISTIC },
1457 { "NODERESTART", NDB_MGM_EVENT_CATEGORY_NODE_RESTART },
1458 { "CONNECTION", NDB_MGM_EVENT_CATEGORY_CONNECTION },
1459 { "CHECKPOINT", NDB_MGM_EVENT_CATEGORY_CHECKPOINT },
1460 { "DEBUG", NDB_MGM_EVENT_CATEGORY_DEBUG },
1461 { "INFO", NDB_MGM_EVENT_CATEGORY_INFO },
1462 { "ERROR", NDB_MGM_EVENT_CATEGORY_ERROR },
1463 { "BACKUP", NDB_MGM_EVENT_CATEGORY_BACKUP },
1464 { "CONGESTION", NDB_MGM_EVENT_CATEGORY_CONGESTION },
1465 { 0, NDB_MGM_ILLEGAL_EVENT_CATEGORY }
1466 };
1467
1468 extern "C"
1469 ndb_mgm_event_category
ndb_mgm_match_event_category(const char * status)1470 ndb_mgm_match_event_category(const char * status)
1471 {
1472 if(status == 0)
1473 return NDB_MGM_ILLEGAL_EVENT_CATEGORY;
1474
1475 for(int i = 0; categories[i].name !=0 ; i++)
1476 if(strcmp(status, categories[i].name) == 0)
1477 return categories[i].category;
1478
1479 return NDB_MGM_ILLEGAL_EVENT_CATEGORY;
1480 }
1481
1482 extern "C"
1483 const char *
ndb_mgm_get_event_category_string(enum ndb_mgm_event_category status)1484 ndb_mgm_get_event_category_string(enum ndb_mgm_event_category status)
1485 {
1486 int i;
1487 for(i = 0; categories[i].name != 0; i++)
1488 if(categories[i].category == status)
1489 return categories[i].name;
1490
1491 return 0;
1492 }
1493
1494 static const char *clusterlog_names[]=
1495 { "startup", "shutdown", "statistics", "checkpoint", "noderestart", "connection", "info", "warning", "error", "congestion", "debug", "backup" };
1496
1497 extern "C"
1498 int
ndb_mgm_get_clusterlog_loglevel(NdbMgmHandle handle,struct ndb_mgm_loglevel * loglevel,unsigned int loglevel_size)1499 ndb_mgm_get_clusterlog_loglevel(NdbMgmHandle handle,
1500 struct ndb_mgm_loglevel* loglevel,
1501 unsigned int loglevel_size)
1502 {
1503 SET_ERROR(handle, NDB_MGM_NO_ERROR, "Executing: ndb_mgm_get_clusterlog_loglevel");
1504 int loglevel_count = loglevel_size;
1505 const ParserRow<ParserDummy> getloglevel_reply[] = {
1506 MGM_CMD("get cluster loglevel", NULL, ""),
1507 MGM_ARG(clusterlog_names[0], Int, Mandatory, ""),
1508 MGM_ARG(clusterlog_names[1], Int, Mandatory, ""),
1509 MGM_ARG(clusterlog_names[2], Int, Mandatory, ""),
1510 MGM_ARG(clusterlog_names[3], Int, Mandatory, ""),
1511 MGM_ARG(clusterlog_names[4], Int, Mandatory, ""),
1512 MGM_ARG(clusterlog_names[5], Int, Mandatory, ""),
1513 MGM_ARG(clusterlog_names[6], Int, Mandatory, ""),
1514 MGM_ARG(clusterlog_names[7], Int, Mandatory, ""),
1515 MGM_ARG(clusterlog_names[8], Int, Mandatory, ""),
1516 MGM_ARG(clusterlog_names[9], Int, Mandatory, ""),
1517 MGM_ARG(clusterlog_names[10], Int, Mandatory, ""),
1518 MGM_ARG(clusterlog_names[11], Int, Mandatory, ""),
1519 };
1520 CHECK_HANDLE(handle, -1);
1521 CHECK_CONNECTED(handle, -1);
1522
1523 Properties args;
1524 const Properties *reply;
1525 reply = ndb_mgm_call(handle, getloglevel_reply, "get cluster loglevel", &args);
1526 CHECK_REPLY(handle, reply, -1);
1527
1528 for(int i=0; i < loglevel_count; i++) {
1529 reply->get(clusterlog_names[loglevel[i].category], &loglevel[i].value);
1530 }
1531 return loglevel_count;
1532 }
1533
1534 extern "C"
1535 const unsigned int *
ndb_mgm_get_clusterlog_loglevel_old(NdbMgmHandle handle)1536 ndb_mgm_get_clusterlog_loglevel_old(NdbMgmHandle handle)
1537 {
1538 SET_ERROR(handle, NDB_MGM_NO_ERROR, "Executing: ndb_mgm_get_clusterlog_loglevel");
1539 int loglevel_count = CFG_MAX_LOGLEVEL - CFG_MIN_LOGLEVEL + 1 ;
1540 static unsigned int loglevel[CFG_MAX_LOGLEVEL - CFG_MIN_LOGLEVEL + 1] = {0,0,0,0,0,0,0,0,0,0,0,0};
1541 const ParserRow<ParserDummy> getloglevel_reply[] = {
1542 MGM_CMD("get cluster loglevel", NULL, ""),
1543 MGM_ARG(clusterlog_names[0], Int, Mandatory, ""),
1544 MGM_ARG(clusterlog_names[1], Int, Mandatory, ""),
1545 MGM_ARG(clusterlog_names[2], Int, Mandatory, ""),
1546 MGM_ARG(clusterlog_names[3], Int, Mandatory, ""),
1547 MGM_ARG(clusterlog_names[4], Int, Mandatory, ""),
1548 MGM_ARG(clusterlog_names[5], Int, Mandatory, ""),
1549 MGM_ARG(clusterlog_names[6], Int, Mandatory, ""),
1550 MGM_ARG(clusterlog_names[7], Int, Mandatory, ""),
1551 MGM_ARG(clusterlog_names[8], Int, Mandatory, ""),
1552 MGM_ARG(clusterlog_names[9], Int, Mandatory, ""),
1553 MGM_ARG(clusterlog_names[10], Int, Mandatory, ""),
1554 MGM_ARG(clusterlog_names[11], Int, Mandatory, ""),
1555 };
1556 CHECK_HANDLE(handle, NULL);
1557 CHECK_CONNECTED(handle, NULL);
1558
1559 Properties args;
1560 const Properties *reply;
1561 reply = ndb_mgm_call(handle, getloglevel_reply, "get cluster loglevel", &args);
1562 CHECK_REPLY(handle, reply, NULL);
1563
1564 for(int i=0; i < loglevel_count; i++) {
1565 reply->get(clusterlog_names[i], &loglevel[i]);
1566 }
1567 return loglevel;
1568 }
1569
1570 extern "C"
1571 int
ndb_mgm_set_clusterlog_loglevel(NdbMgmHandle handle,int nodeId,enum ndb_mgm_event_category cat,int level,struct ndb_mgm_reply *)1572 ndb_mgm_set_clusterlog_loglevel(NdbMgmHandle handle, int nodeId,
1573 enum ndb_mgm_event_category cat,
1574 int level,
1575 struct ndb_mgm_reply* /*reply*/)
1576 {
1577 SET_ERROR(handle, NDB_MGM_NO_ERROR,
1578 "Executing: ndb_mgm_set_clusterlog_loglevel");
1579 const ParserRow<ParserDummy> clusterlog_reply[] = {
1580 MGM_CMD("set cluster loglevel reply", NULL, ""),
1581 MGM_ARG("result", String, Mandatory, "Error message"),
1582 MGM_END()
1583 };
1584 CHECK_HANDLE(handle, -1);
1585 CHECK_CONNECTED(handle, -1);
1586
1587 Properties args;
1588 args.put("node", nodeId);
1589 args.put("category", cat);
1590 args.put("level", level);
1591
1592 const Properties *reply;
1593 reply = ndb_mgm_call(handle, clusterlog_reply,
1594 "set cluster loglevel", &args);
1595 CHECK_REPLY(handle, reply, -1);
1596
1597 DBUG_ENTER("ndb_mgm_set_clusterlog_loglevel");
1598 DBUG_PRINT("enter",("node=%d, category=%d, level=%d", nodeId, cat, level));
1599
1600 BaseString result;
1601 reply->get("result", result);
1602 if(strcmp(result.c_str(), "Ok") != 0) {
1603 SET_ERROR(handle, EINVAL, result.c_str());
1604 delete reply;
1605 DBUG_RETURN(-1);
1606 }
1607 delete reply;
1608 DBUG_RETURN(0);
1609 }
1610
1611 extern "C"
1612 int
ndb_mgm_set_loglevel_node(NdbMgmHandle handle,int nodeId,enum ndb_mgm_event_category category,int level,struct ndb_mgm_reply *)1613 ndb_mgm_set_loglevel_node(NdbMgmHandle handle, int nodeId,
1614 enum ndb_mgm_event_category category,
1615 int level,
1616 struct ndb_mgm_reply* /*reply*/)
1617 {
1618 SET_ERROR(handle, NDB_MGM_NO_ERROR, "Executing: ndb_mgm_set_loglevel_node");
1619 const ParserRow<ParserDummy> loglevel_reply[] = {
1620 MGM_CMD("set loglevel reply", NULL, ""),
1621 MGM_ARG("result", String, Mandatory, "Error message"),
1622 MGM_END()
1623 };
1624 CHECK_HANDLE(handle, -1);
1625 CHECK_CONNECTED(handle, -1);
1626
1627 Properties args;
1628 args.put("node", nodeId);
1629 args.put("category", category);
1630 args.put("level", level);
1631 const Properties *reply;
1632 reply = ndb_mgm_call(handle, loglevel_reply, "set loglevel", &args);
1633 CHECK_REPLY(handle, reply, -1);
1634
1635 BaseString result;
1636 reply->get("result", result);
1637 if(strcmp(result.c_str(), "Ok") != 0) {
1638 SET_ERROR(handle, EINVAL, result.c_str());
1639 delete reply;
1640 return -1;
1641 }
1642
1643 delete reply;
1644 return 0;
1645 }
1646
1647 int
ndb_mgm_listen_event_internal(NdbMgmHandle handle,const int filter[],int parsable)1648 ndb_mgm_listen_event_internal(NdbMgmHandle handle, const int filter[],
1649 int parsable)
1650 {
1651 SET_ERROR(handle, NDB_MGM_NO_ERROR, "Executing: ndb_mgm_listen_event");
1652 const ParserRow<ParserDummy> stat_reply[] = {
1653 MGM_CMD("listen event", NULL, ""),
1654 MGM_ARG("result", Int, Mandatory, "Error message"),
1655 MGM_ARG("msg", String, Optional, "Error message"),
1656 MGM_END()
1657 };
1658 CHECK_HANDLE(handle, -1);
1659
1660 const char *hostname= ndb_mgm_get_connected_host(handle);
1661 int port= ndb_mgm_get_connected_port(handle);
1662 SocketClient s(hostname, port);
1663 const NDB_SOCKET_TYPE sockfd = s.connect();
1664 if (sockfd == NDB_INVALID_SOCKET) {
1665 setError(handle, NDB_MGM_COULD_NOT_CONNECT_TO_SOCKET, __LINE__,
1666 "Unable to connect to");
1667 return -1;
1668 }
1669
1670 Properties args;
1671
1672 if (parsable)
1673 args.put("parsable", parsable);
1674 {
1675 BaseString tmp;
1676 for(int i = 0; filter[i] != 0; i += 2){
1677 tmp.appfmt("%d=%d ", filter[i+1], filter[i]);
1678 }
1679 args.put("filter", tmp.c_str());
1680 }
1681
1682 int tmp = handle->socket;
1683 handle->socket = sockfd;
1684
1685 const Properties *reply;
1686 reply = ndb_mgm_call(handle, stat_reply, "listen event", &args);
1687
1688 handle->socket = tmp;
1689
1690 if(reply == NULL) {
1691 close(sockfd);
1692 CHECK_REPLY(handle, reply, -1);
1693 }
1694 delete reply;
1695 return sockfd;
1696 }
1697
1698 extern "C"
1699 int
ndb_mgm_listen_event(NdbMgmHandle handle,const int filter[])1700 ndb_mgm_listen_event(NdbMgmHandle handle, const int filter[])
1701 {
1702 return ndb_mgm_listen_event_internal(handle,filter,0);
1703 }
1704
1705 extern "C"
1706 int
ndb_mgm_dump_state(NdbMgmHandle handle,int nodeId,const int * _args,int _num_args,struct ndb_mgm_reply *)1707 ndb_mgm_dump_state(NdbMgmHandle handle, int nodeId, const int * _args,
1708 int _num_args, struct ndb_mgm_reply* /* reply */)
1709 {
1710 SET_ERROR(handle, NDB_MGM_NO_ERROR, "Executing: ndb_mgm_dump_state");
1711 const ParserRow<ParserDummy> dump_state_reply[] = {
1712 MGM_CMD("dump state reply", NULL, ""),
1713 MGM_ARG("result", String, Mandatory, "Error message"),
1714 MGM_END()
1715 };
1716 CHECK_HANDLE(handle, -1);
1717 CHECK_CONNECTED(handle, -1);
1718
1719 char buf[256];
1720 buf[0] = 0;
1721 for (int i = 0; i < _num_args; i++){
1722 unsigned n = strlen(buf);
1723 if (n + 20 > sizeof(buf)) {
1724 SET_ERROR(handle, NDB_MGM_USAGE_ERROR, "arguments too long");
1725 return -1;
1726 }
1727 sprintf(buf + n, "%s%d", i ? " " : "", _args[i]);
1728 }
1729
1730 Properties args;
1731 args.put("node", nodeId);
1732 args.put("args", buf);
1733
1734 const Properties *prop;
1735 prop = ndb_mgm_call(handle, dump_state_reply, "dump state", &args);
1736 CHECK_REPLY(handle, prop, -1);
1737
1738 BaseString result;
1739 prop->get("result", result);
1740 if(strcmp(result.c_str(), "Ok") != 0) {
1741 SET_ERROR(handle, EINVAL, result.c_str());
1742 delete prop;
1743 return -1;
1744 }
1745
1746 delete prop;
1747 return 0;
1748 }
1749
1750 extern "C"
1751 int
ndb_mgm_start_signallog(NdbMgmHandle handle,int nodeId,struct ndb_mgm_reply * reply)1752 ndb_mgm_start_signallog(NdbMgmHandle handle, int nodeId,
1753 struct ndb_mgm_reply* reply)
1754 {
1755 SET_ERROR(handle, NDB_MGM_NO_ERROR, "Executing: ndb_mgm_start_signallog");
1756 const ParserRow<ParserDummy> start_signallog_reply[] = {
1757 MGM_CMD("start signallog reply", NULL, ""),
1758 MGM_ARG("result", String, Mandatory, "Error message"),
1759 MGM_END()
1760 };
1761 int retval = -1;
1762 CHECK_HANDLE(handle, -1);
1763 CHECK_CONNECTED(handle, -1);
1764
1765 Properties args;
1766 args.put("node", nodeId);
1767
1768 const Properties *prop;
1769 prop = ndb_mgm_call(handle,
1770 start_signallog_reply,
1771 "start signallog",
1772 &args);
1773 CHECK_REPLY(handle, prop, -1);
1774
1775 if(prop != NULL) {
1776 BaseString result;
1777 prop->get("result", result);
1778 if(strcmp(result.c_str(), "Ok") == 0) {
1779 retval = 0;
1780 } else {
1781 SET_ERROR(handle, EINVAL, result.c_str());
1782 retval = -1;
1783 }
1784 delete prop;
1785 }
1786
1787 return retval;
1788 }
1789
1790 extern "C"
1791 int
ndb_mgm_stop_signallog(NdbMgmHandle handle,int nodeId,struct ndb_mgm_reply * reply)1792 ndb_mgm_stop_signallog(NdbMgmHandle handle, int nodeId,
1793 struct ndb_mgm_reply* reply)
1794 {
1795 SET_ERROR(handle, NDB_MGM_NO_ERROR, "Executing: ndb_mgm_stop_signallog");
1796 const ParserRow<ParserDummy> stop_signallog_reply[] = {
1797 MGM_CMD("stop signallog reply", NULL, ""),
1798 MGM_ARG("result", String, Mandatory, "Error message"),
1799 MGM_END()
1800 };
1801 int retval = -1;
1802 CHECK_HANDLE(handle, -1);
1803 CHECK_CONNECTED(handle, -1);
1804
1805 Properties args;
1806 args.put("node", nodeId);
1807
1808 const Properties *prop;
1809 prop = ndb_mgm_call(handle, stop_signallog_reply, "stop signallog", &args);
1810 CHECK_REPLY(handle, prop, -1);
1811
1812 if(prop != NULL) {
1813 BaseString result;
1814 prop->get("result", result);
1815 if(strcmp(result.c_str(), "Ok") == 0) {
1816 retval = 0;
1817 } else {
1818 SET_ERROR(handle, EINVAL, result.c_str());
1819 retval = -1;
1820 }
1821 delete prop;
1822 }
1823
1824 return retval;
1825 }
1826
1827 struct ndb_mgm_signal_log_modes
1828 {
1829 const char* name;
1830 enum ndb_mgm_signal_log_mode mode;
1831 };
1832
1833 extern "C"
1834 int
ndb_mgm_log_signals(NdbMgmHandle handle,int nodeId,enum ndb_mgm_signal_log_mode mode,const char * blockNames,struct ndb_mgm_reply * reply)1835 ndb_mgm_log_signals(NdbMgmHandle handle, int nodeId,
1836 enum ndb_mgm_signal_log_mode mode,
1837 const char* blockNames,
1838 struct ndb_mgm_reply* reply)
1839 {
1840 SET_ERROR(handle, NDB_MGM_NO_ERROR, "Executing: ndb_mgm_log_signals");
1841 const ParserRow<ParserDummy> stop_signallog_reply[] = {
1842 MGM_CMD("log signals reply", NULL, ""),
1843 MGM_ARG("result", String, Mandatory, "Error message"),
1844 MGM_END()
1845 };
1846 int retval = -1;
1847 CHECK_HANDLE(handle, -1);
1848 CHECK_CONNECTED(handle, -1);
1849
1850 Properties args;
1851 args.put("node", nodeId);
1852 args.put("blocks", blockNames);
1853
1854 switch(mode) {
1855 case NDB_MGM_SIGNAL_LOG_MODE_IN:
1856 args.put("in", (Uint32)1);
1857 args.put("out", (Uint32)0);
1858 break;
1859 case NDB_MGM_SIGNAL_LOG_MODE_OUT:
1860 args.put("in", (Uint32)0);
1861 args.put("out", (Uint32)1);
1862 break;
1863 case NDB_MGM_SIGNAL_LOG_MODE_INOUT:
1864 args.put("in", (Uint32)1);
1865 args.put("out", (Uint32)1);
1866 break;
1867 case NDB_MGM_SIGNAL_LOG_MODE_OFF:
1868 args.put("in", (Uint32)0);
1869 args.put("out", (Uint32)0);
1870 break;
1871 }
1872
1873 const Properties *prop;
1874 prop = ndb_mgm_call(handle, stop_signallog_reply, "log signals", &args);
1875 CHECK_REPLY(handle, prop, -1);
1876
1877 if(prop != NULL) {
1878 BaseString result;
1879 prop->get("result", result);
1880 if(strcmp(result.c_str(), "Ok") == 0) {
1881 retval = 0;
1882 } else {
1883 SET_ERROR(handle, EINVAL, result.c_str());
1884 retval = -1;
1885 }
1886 delete prop;
1887 }
1888
1889 return retval;
1890 }
1891
1892 extern "C"
1893 int
ndb_mgm_set_trace(NdbMgmHandle handle,int nodeId,int traceNumber,struct ndb_mgm_reply * reply)1894 ndb_mgm_set_trace(NdbMgmHandle handle, int nodeId, int traceNumber,
1895 struct ndb_mgm_reply* reply)
1896 {
1897 SET_ERROR(handle, NDB_MGM_NO_ERROR, "Executing: ndb_mgm_set_trace");
1898 const ParserRow<ParserDummy> set_trace_reply[] = {
1899 MGM_CMD("set trace reply", NULL, ""),
1900 MGM_ARG("result", String, Mandatory, "Error message"),
1901 MGM_END()
1902 };
1903 int retval = -1;
1904 CHECK_HANDLE(handle, -1);
1905 CHECK_CONNECTED(handle, -1);
1906
1907 Properties args;
1908 args.put("node", nodeId);
1909 args.put("trace", traceNumber);
1910
1911 const Properties *prop;
1912 prop = ndb_mgm_call(handle, set_trace_reply, "set trace", &args);
1913 CHECK_REPLY(handle, prop, -1);
1914
1915 if(prop != NULL) {
1916 BaseString result;
1917 prop->get("result", result);
1918 if(strcmp(result.c_str(), "Ok") == 0) {
1919 retval = 0;
1920 } else {
1921 SET_ERROR(handle, EINVAL, result.c_str());
1922 retval = -1;
1923 }
1924 delete prop;
1925 }
1926
1927 return retval;
1928 }
1929
1930 extern "C"
1931 int
ndb_mgm_insert_error(NdbMgmHandle handle,int nodeId,int errorCode,struct ndb_mgm_reply * reply)1932 ndb_mgm_insert_error(NdbMgmHandle handle, int nodeId, int errorCode,
1933 struct ndb_mgm_reply* reply)
1934 {
1935 SET_ERROR(handle, NDB_MGM_NO_ERROR, "Executing: ndb_mgm_insert_error");
1936 const ParserRow<ParserDummy> insert_error_reply[] = {
1937 MGM_CMD("insert error reply", NULL, ""),
1938 MGM_ARG("result", String, Mandatory, "Error message"),
1939 MGM_END()
1940 };
1941 int retval = -1;
1942 CHECK_HANDLE(handle, -1);
1943 CHECK_CONNECTED(handle, -1);
1944
1945 Properties args;
1946 args.put("node", nodeId);
1947 args.put("error", errorCode);
1948
1949 const Properties *prop;
1950 prop = ndb_mgm_call(handle, insert_error_reply, "insert error", &args);
1951 CHECK_REPLY(handle, prop, -1);
1952
1953 if(prop != NULL) {
1954 BaseString result;
1955 prop->get("result", result);
1956 if(strcmp(result.c_str(), "Ok") == 0) {
1957 retval = 0;
1958 } else {
1959 SET_ERROR(handle, EINVAL, result.c_str());
1960 retval = -1;
1961 }
1962 delete prop;
1963 }
1964
1965 return retval;
1966 }
1967
1968 extern "C"
1969 int
ndb_mgm_start(NdbMgmHandle handle,int no_of_nodes,const int * node_list)1970 ndb_mgm_start(NdbMgmHandle handle, int no_of_nodes, const int * node_list)
1971 {
1972 SET_ERROR(handle, NDB_MGM_NO_ERROR, "Executing: ndb_mgm_start");
1973 const ParserRow<ParserDummy> start_reply[] = {
1974 MGM_CMD("start reply", NULL, ""),
1975 MGM_ARG("started", Int, Optional, "No of started nodes"),
1976 MGM_ARG("result", String, Mandatory, "Error message"),
1977 MGM_END()
1978 };
1979 int started = 0;
1980 CHECK_HANDLE(handle, -1);
1981 CHECK_CONNECTED(handle, -1);
1982
1983 if(no_of_nodes < 0){
1984 SET_ERROR(handle, EINVAL, "");
1985 return -1;
1986 }
1987
1988 if(no_of_nodes == 0){
1989 Properties args;
1990 const Properties *reply;
1991 reply = ndb_mgm_call(handle, start_reply, "start all", &args);
1992 CHECK_REPLY(handle, reply, -1);
1993
1994 Uint32 count = 0;
1995 if(!reply->get("started", &count)){
1996 delete reply;
1997 return -1;
1998 }
1999 delete reply;
2000 return count;
2001 }
2002
2003 for(int node = 0; node < no_of_nodes; node++) {
2004 Properties args;
2005 args.put("node", node_list[node]);
2006
2007 const Properties *reply;
2008 reply = ndb_mgm_call(handle, start_reply, "start", &args);
2009
2010 if(reply != NULL) {
2011 BaseString result;
2012 reply->get("result", result);
2013 if(strcmp(result.c_str(), "Ok") == 0) {
2014 started++;
2015 } else {
2016 SET_ERROR(handle, EINVAL, result.c_str());
2017 delete reply;
2018 return -1;
2019 }
2020 }
2021 delete reply;
2022 }
2023
2024 return started;
2025 }
2026
2027 /*****************************************************************************
2028 * Backup
2029 *****************************************************************************/
2030 extern "C"
2031 int
ndb_mgm_start_backup(NdbMgmHandle handle,int wait_completed,unsigned int * _backup_id,struct ndb_mgm_reply *)2032 ndb_mgm_start_backup(NdbMgmHandle handle, int wait_completed,
2033 unsigned int* _backup_id,
2034 struct ndb_mgm_reply* /*reply*/)
2035 {
2036 SET_ERROR(handle, NDB_MGM_NO_ERROR, "Executing: ndb_mgm_start_backup");
2037 const ParserRow<ParserDummy> start_backup_reply[] = {
2038 MGM_CMD("start backup reply", NULL, ""),
2039 MGM_ARG("result", String, Mandatory, "Error message"),
2040 MGM_ARG("id", Int, Optional, "Id of the started backup"),
2041 MGM_END()
2042 };
2043 CHECK_HANDLE(handle, -1);
2044 CHECK_CONNECTED(handle, -1);
2045
2046 Properties args;
2047 args.put("completed", wait_completed);
2048 const Properties *reply;
2049 { // start backup can take some time, set timeout high
2050 Uint64 old_timeout= handle->timeout;
2051 if (wait_completed == 2)
2052 handle->timeout= 48*60*60*1000; // 48 hours
2053 else if (wait_completed == 1)
2054 handle->timeout= 10*60*1000; // 10 minutes
2055 reply = ndb_mgm_call(handle, start_backup_reply, "start backup", &args);
2056 handle->timeout= old_timeout;
2057 }
2058 CHECK_REPLY(handle, reply, -1);
2059
2060 BaseString result;
2061 reply->get("result", result);
2062 reply->get("id", _backup_id);
2063 if(strcmp(result.c_str(), "Ok") != 0) {
2064 SET_ERROR(handle, NDB_MGM_COULD_NOT_START_BACKUP, result.c_str());
2065 delete reply;
2066 return -1;
2067 }
2068
2069 delete reply;
2070 return 0;
2071 }
2072
2073 extern "C"
2074 int
ndb_mgm_abort_backup(NdbMgmHandle handle,unsigned int backupId,struct ndb_mgm_reply *)2075 ndb_mgm_abort_backup(NdbMgmHandle handle, unsigned int backupId,
2076 struct ndb_mgm_reply* /*reply*/)
2077 {
2078 SET_ERROR(handle, NDB_MGM_NO_ERROR, "Executing: ndb_mgm_abort_backup");
2079 const ParserRow<ParserDummy> stop_backup_reply[] = {
2080 MGM_CMD("abort backup reply", NULL, ""),
2081 MGM_ARG("result", String, Mandatory, "Error message"),
2082 MGM_END()
2083 };
2084 CHECK_HANDLE(handle, -1);
2085 CHECK_CONNECTED(handle, -1);
2086
2087 Properties args;
2088 args.put("id", backupId);
2089
2090 const Properties *prop;
2091 prop = ndb_mgm_call(handle, stop_backup_reply, "abort backup", &args);
2092 CHECK_REPLY(handle, prop, -1);
2093
2094 const char * buf;
2095 prop->get("result", &buf);
2096 if(strcmp(buf,"Ok")!=0) {
2097 SET_ERROR(handle, NDB_MGM_COULD_NOT_ABORT_BACKUP, buf);
2098 delete prop;
2099 return -1;
2100 }
2101
2102 delete prop;
2103 return 0;
2104 }
2105
2106 extern "C"
2107 struct ndb_mgm_configuration *
ndb_mgm_get_configuration(NdbMgmHandle handle,unsigned int version)2108 ndb_mgm_get_configuration(NdbMgmHandle handle, unsigned int version) {
2109 SET_ERROR(handle, NDB_MGM_NO_ERROR, "Executing: ndb_mgm_get_configuration");
2110 CHECK_HANDLE(handle, 0);
2111 CHECK_CONNECTED(handle, 0);
2112
2113 Properties args;
2114 args.put("version", version);
2115
2116 const ParserRow<ParserDummy> reply[] = {
2117 MGM_CMD("get config reply", NULL, ""),
2118 MGM_ARG("result", String, Mandatory, "Error message"),
2119 MGM_ARG("Content-Length", Int, Optional, "Content length in bytes"),
2120 MGM_ARG("Content-Type", String, Optional, "Type (octet-stream)"),
2121 MGM_ARG("Content-Transfer-Encoding", String, Optional, "Encoding(base64)"),
2122 MGM_END()
2123 };
2124
2125 const Properties *prop;
2126 prop = ndb_mgm_call(handle, reply, "get config", &args);
2127 CHECK_REPLY(handle, prop, 0);
2128
2129 do {
2130 const char * buf;
2131 if(!prop->get("result", &buf) || strcmp(buf, "Ok") != 0){
2132 fprintf(handle->errstream, "ERROR Message: %s\n\n", buf);
2133 break;
2134 }
2135
2136 buf = "<Unspecified>";
2137 if(!prop->get("Content-Type", &buf) ||
2138 strcmp(buf, "ndbconfig/octet-stream") != 0){
2139 fprintf(handle->errstream, "Unhandled response type: %s\n", buf);
2140 break;
2141 }
2142
2143 buf = "<Unspecified>";
2144 if(!prop->get("Content-Transfer-Encoding", &buf)
2145 || strcmp(buf, "base64") != 0){
2146 fprintf(handle->errstream, "Unhandled encoding: %s\n", buf);
2147 break;
2148 }
2149
2150 buf = "<Content-Length Unspecified>";
2151 Uint32 len = 0;
2152 if(!prop->get("Content-Length", &len)){
2153 fprintf(handle->errstream, "Invalid response: %s\n\n", buf);
2154 break;
2155 }
2156
2157 len += 1; // Trailing \n
2158
2159 char* buf64 = new char[len];
2160 int read = 0;
2161 size_t start = 0;
2162 do {
2163 if((read = read_socket(handle->socket, handle->timeout,
2164 &buf64[start], len-start)) < 1){
2165 delete[] buf64;
2166 buf64 = 0;
2167 if(read==0)
2168 SET_ERROR(handle, ETIMEDOUT, "Timeout reading packed config");
2169 else
2170 SET_ERROR(handle, errno, "Error reading packed config");
2171 ndb_mgm_disconnect_quiet(handle);
2172 break;
2173 }
2174 start += read;
2175 } while(start < len);
2176 if(buf64 == 0)
2177 break;
2178
2179 void *tmp_data = malloc(base64_needed_decoded_length((size_t) (len - 1)));
2180 const int res = base64_decode(buf64, len-1, tmp_data, NULL);
2181 delete[] buf64;
2182 UtilBuffer tmp;
2183 tmp.append((void *) tmp_data, res);
2184 free(tmp_data);
2185 if (res < 0)
2186 {
2187 fprintf(handle->errstream, "Failed to decode buffer\n");
2188 break;
2189 }
2190
2191 ConfigValuesFactory cvf;
2192 const int res2 = cvf.unpack(tmp);
2193 if(!res2){
2194 fprintf(handle->errstream, "Failed to unpack buffer\n");
2195 break;
2196 }
2197
2198 delete prop;
2199 return (ndb_mgm_configuration*)cvf.getConfigValues();
2200 } while(0);
2201
2202 delete prop;
2203 return 0;
2204 }
2205
2206 extern "C"
2207 void
ndb_mgm_destroy_configuration(struct ndb_mgm_configuration * cfg)2208 ndb_mgm_destroy_configuration(struct ndb_mgm_configuration *cfg)
2209 {
2210 if (cfg) {
2211 ((ConfigValues *)cfg)->~ConfigValues();
2212 free((void *)cfg);
2213 }
2214 }
2215
2216 extern "C"
2217 int
ndb_mgm_set_configuration_nodeid(NdbMgmHandle handle,int nodeid)2218 ndb_mgm_set_configuration_nodeid(NdbMgmHandle handle, int nodeid)
2219 {
2220 CHECK_HANDLE(handle, -1);
2221 handle->cfg._ownNodeId= nodeid;
2222 return 0;
2223 }
2224
2225 extern "C"
2226 int
ndb_mgm_get_configuration_nodeid(NdbMgmHandle handle)2227 ndb_mgm_get_configuration_nodeid(NdbMgmHandle handle)
2228 {
2229 CHECK_HANDLE(handle, 0);
2230 return handle->cfg._ownNodeId;
2231 }
2232
2233 extern "C"
ndb_mgm_get_connected_port(NdbMgmHandle handle)2234 int ndb_mgm_get_connected_port(NdbMgmHandle handle)
2235 {
2236 if (handle->cfg_i >= 0)
2237 return handle->cfg.ids[handle->cfg_i].port;
2238 else
2239 return 0;
2240 }
2241
2242 extern "C"
ndb_mgm_get_connected_host(NdbMgmHandle handle)2243 const char *ndb_mgm_get_connected_host(NdbMgmHandle handle)
2244 {
2245 if (handle->cfg_i >= 0)
2246 return handle->cfg.ids[handle->cfg_i].name.c_str();
2247 else
2248 return 0;
2249 }
2250
2251 extern "C"
ndb_mgm_get_connectstring(NdbMgmHandle handle,char * buf,int buf_sz)2252 const char *ndb_mgm_get_connectstring(NdbMgmHandle handle, char *buf, int buf_sz)
2253 {
2254 return handle->cfg.makeConnectString(buf,buf_sz);
2255 }
2256
2257 extern "C"
2258 int
ndb_mgm_alloc_nodeid(NdbMgmHandle handle,unsigned int version,int nodetype,int log_event)2259 ndb_mgm_alloc_nodeid(NdbMgmHandle handle, unsigned int version, int nodetype,
2260 int log_event)
2261 {
2262 CHECK_HANDLE(handle, 0);
2263 CHECK_CONNECTED(handle, 0);
2264 union { long l; char c[sizeof(long)]; } endian_check;
2265
2266 endian_check.l = 1;
2267
2268 int nodeid= handle->cfg._ownNodeId;
2269
2270 Properties args;
2271 args.put("version", version);
2272 args.put("nodetype", nodetype);
2273 args.put("nodeid", nodeid);
2274 args.put("user", "mysqld");
2275 args.put("password", "mysqld");
2276 args.put("public key", "a public key");
2277 args.put("endian", (endian_check.c[sizeof(long)-1])?"big":"little");
2278 if (handle->m_name)
2279 args.put("name", handle->m_name);
2280 args.put("log_event", log_event);
2281
2282 const ParserRow<ParserDummy> reply[]= {
2283 MGM_CMD("get nodeid reply", NULL, ""),
2284 MGM_ARG("error_code", Int, Optional, "Error code"),
2285 MGM_ARG("nodeid", Int, Optional, "Error message"),
2286 MGM_ARG("result", String, Mandatory, "Error message"),
2287 MGM_END()
2288 };
2289
2290 const Properties *prop;
2291 prop= ndb_mgm_call(handle, reply, "get nodeid", &args);
2292 CHECK_REPLY(handle, prop, -1);
2293
2294 nodeid= -1;
2295 do {
2296 const char * buf;
2297 if (!prop->get("result", &buf) || strcmp(buf, "Ok") != 0)
2298 {
2299 const char *hostname= ndb_mgm_get_connected_host(handle);
2300 unsigned port= ndb_mgm_get_connected_port(handle);
2301 BaseString err;
2302 Uint32 error_code= NDB_MGM_ALLOCID_ERROR;
2303 err.assfmt("Could not alloc node id at %s port %d: %s",
2304 hostname, port, buf);
2305 prop->get("error_code", &error_code);
2306 setError(handle, error_code, __LINE__, err.c_str());
2307 break;
2308 }
2309 Uint32 _nodeid;
2310 if(!prop->get("nodeid", &_nodeid) != 0){
2311 fprintf(handle->errstream, "ERROR Message: <nodeid Unspecified>\n");
2312 break;
2313 }
2314 nodeid= _nodeid;
2315 }while(0);
2316
2317 delete prop;
2318 return nodeid;
2319 }
2320
2321 extern "C"
2322 int
ndb_mgm_set_int_parameter(NdbMgmHandle handle,int node,int param,unsigned value,struct ndb_mgm_reply *)2323 ndb_mgm_set_int_parameter(NdbMgmHandle handle,
2324 int node,
2325 int param,
2326 unsigned value,
2327 struct ndb_mgm_reply*){
2328 CHECK_HANDLE(handle, 0);
2329 CHECK_CONNECTED(handle, 0);
2330
2331 Properties args;
2332 args.put("node", node);
2333 args.put("param", param);
2334 args.put("value", value);
2335
2336 const ParserRow<ParserDummy> reply[]= {
2337 MGM_CMD("set parameter reply", NULL, ""),
2338 MGM_ARG("result", String, Mandatory, "Error message"),
2339 MGM_END()
2340 };
2341
2342 const Properties *prop;
2343 prop= ndb_mgm_call(handle, reply, "set parameter", &args);
2344 CHECK_REPLY(handle, prop, -1);
2345
2346 int res= -1;
2347 do {
2348 const char * buf;
2349 if(!prop->get("result", &buf) || strcmp(buf, "Ok") != 0){
2350 fprintf(handle->errstream, "ERROR Message: %s\n", buf);
2351 break;
2352 }
2353 res= 0;
2354 } while(0);
2355
2356 delete prop;
2357 return res;
2358 }
2359
2360 extern "C"
2361 int
ndb_mgm_set_int64_parameter(NdbMgmHandle handle,int node,int param,unsigned long long value,struct ndb_mgm_reply *)2362 ndb_mgm_set_int64_parameter(NdbMgmHandle handle,
2363 int node,
2364 int param,
2365 unsigned long long value,
2366 struct ndb_mgm_reply*){
2367 CHECK_HANDLE(handle, 0);
2368 CHECK_CONNECTED(handle, 0);
2369
2370 Properties args;
2371 args.put("node", node);
2372 args.put("param", param);
2373 args.put("value", value);
2374
2375 const ParserRow<ParserDummy> reply[]= {
2376 MGM_CMD("set parameter reply", NULL, ""),
2377 MGM_ARG("result", String, Mandatory, "Error message"),
2378 MGM_END()
2379 };
2380
2381 const Properties *prop;
2382 prop= ndb_mgm_call(handle, reply, "set parameter", &args);
2383 CHECK_REPLY(handle, prop, 0);
2384
2385 if(prop == NULL) {
2386 SET_ERROR(handle, EIO, "Unable set parameter");
2387 return -1;
2388 }
2389
2390 int res= -1;
2391 do {
2392 const char * buf;
2393 if(!prop->get("result", &buf) || strcmp(buf, "Ok") != 0){
2394 fprintf(handle->errstream, "ERROR Message: %s\n", buf);
2395 break;
2396 }
2397 res= 0;
2398 } while(0);
2399
2400 delete prop;
2401 return res;
2402 }
2403
2404 extern "C"
2405 int
ndb_mgm_set_string_parameter(NdbMgmHandle handle,int node,int param,const char * value,struct ndb_mgm_reply *)2406 ndb_mgm_set_string_parameter(NdbMgmHandle handle,
2407 int node,
2408 int param,
2409 const char * value,
2410 struct ndb_mgm_reply*){
2411 CHECK_HANDLE(handle, 0);
2412 CHECK_CONNECTED(handle, 0);
2413
2414 Properties args;
2415 args.put("node", node);
2416 args.put("parameter", param);
2417 args.put("value", value);
2418
2419 const ParserRow<ParserDummy> reply[]= {
2420 MGM_CMD("set parameter reply", NULL, ""),
2421 MGM_ARG("result", String, Mandatory, "Error message"),
2422 MGM_END()
2423 };
2424
2425 const Properties *prop;
2426 prop= ndb_mgm_call(handle, reply, "set parameter", &args);
2427 CHECK_REPLY(handle, prop, 0);
2428
2429 if(prop == NULL) {
2430 SET_ERROR(handle, EIO, "Unable set parameter");
2431 return -1;
2432 }
2433
2434 int res= -1;
2435 do {
2436 const char * buf;
2437 if(!prop->get("result", &buf) || strcmp(buf, "Ok") != 0){
2438 fprintf(handle->errstream, "ERROR Message: %s\n", buf);
2439 break;
2440 }
2441 res= 0;
2442 } while(0);
2443
2444 delete prop;
2445 return res;
2446 }
2447
2448 extern "C"
2449 int
ndb_mgm_purge_stale_sessions(NdbMgmHandle handle,char ** purged)2450 ndb_mgm_purge_stale_sessions(NdbMgmHandle handle, char **purged){
2451 CHECK_HANDLE(handle, 0);
2452 CHECK_CONNECTED(handle, 0);
2453
2454 Properties args;
2455
2456 const ParserRow<ParserDummy> reply[]= {
2457 MGM_CMD("purge stale sessions reply", NULL, ""),
2458 MGM_ARG("purged", String, Optional, ""),
2459 MGM_ARG("result", String, Mandatory, "Error message"),
2460 MGM_END()
2461 };
2462
2463 const Properties *prop;
2464 prop= ndb_mgm_call(handle, reply, "purge stale sessions", &args);
2465 CHECK_REPLY(handle, prop, -1);
2466
2467 if(prop == NULL) {
2468 SET_ERROR(handle, EIO, "Unable to purge stale sessions");
2469 return -1;
2470 }
2471
2472 int res= -1;
2473 do {
2474 const char * buf;
2475 if(!prop->get("result", &buf) || strcmp(buf, "Ok") != 0){
2476 fprintf(handle->errstream, "ERROR Message: %s\n", buf);
2477 break;
2478 }
2479 if (purged) {
2480 if (prop->get("purged", &buf))
2481 *purged= strdup(buf);
2482 else
2483 *purged= 0;
2484 }
2485 res= 0;
2486 } while(0);
2487 delete prop;
2488 return res;
2489 }
2490
2491 extern "C"
2492 int
ndb_mgm_check_connection(NdbMgmHandle handle)2493 ndb_mgm_check_connection(NdbMgmHandle handle){
2494 CHECK_HANDLE(handle, 0);
2495 CHECK_CONNECTED(handle, 0);
2496 SocketOutputStream out(handle->socket, handle->timeout);
2497 SocketInputStream in(handle->socket, handle->timeout);
2498 char buf[32];
2499 if (out.println("check connection"))
2500 goto ndb_mgm_check_connection_error;
2501
2502 if (out.println(""))
2503 goto ndb_mgm_check_connection_error;
2504
2505 in.gets(buf, sizeof(buf));
2506 if(strcmp("check connection reply\n", buf))
2507 goto ndb_mgm_check_connection_error;
2508
2509 in.gets(buf, sizeof(buf));
2510 if(strcmp("result: Ok\n", buf))
2511 goto ndb_mgm_check_connection_error;
2512
2513 in.gets(buf, sizeof(buf));
2514 if(strcmp("\n", buf))
2515 goto ndb_mgm_check_connection_error;
2516
2517 return 0;
2518
2519 ndb_mgm_check_connection_error:
2520 ndb_mgm_disconnect(handle);
2521 return -1;
2522 }
2523
2524 extern "C"
2525 int
ndb_mgm_set_connection_int_parameter(NdbMgmHandle handle,int node1,int node2,int param,int value,struct ndb_mgm_reply * mgmreply)2526 ndb_mgm_set_connection_int_parameter(NdbMgmHandle handle,
2527 int node1,
2528 int node2,
2529 int param,
2530 int value,
2531 struct ndb_mgm_reply* mgmreply){
2532 CHECK_HANDLE(handle, 0);
2533 CHECK_CONNECTED(handle, 0);
2534 DBUG_ENTER("ndb_mgm_set_connection_int_parameter");
2535
2536 Properties args;
2537 args.put("node1", node1);
2538 args.put("node2", node2);
2539 args.put("param", param);
2540 args.put("value", (Uint32)value);
2541
2542 const ParserRow<ParserDummy> reply[]= {
2543 MGM_CMD("set connection parameter reply", NULL, ""),
2544 MGM_ARG("message", String, Mandatory, "Error Message"),
2545 MGM_ARG("result", String, Mandatory, "Status Result"),
2546 MGM_END()
2547 };
2548
2549 const Properties *prop;
2550 prop= ndb_mgm_call(handle, reply, "set connection parameter", &args);
2551 DBUG_CHECK_REPLY(handle, prop, -1);
2552
2553 int res= -1;
2554 do {
2555 const char * buf;
2556 if(!prop->get("result", &buf) || strcmp(buf, "Ok") != 0){
2557 fprintf(handle->errstream, "ERROR Message: %s\n", buf);
2558 break;
2559 }
2560 res= 0;
2561 } while(0);
2562
2563 delete prop;
2564 DBUG_RETURN(res);
2565 }
2566
2567 extern "C"
2568 int
ndb_mgm_get_connection_int_parameter(NdbMgmHandle handle,int node1,int node2,int param,int * value,struct ndb_mgm_reply * mgmreply)2569 ndb_mgm_get_connection_int_parameter(NdbMgmHandle handle,
2570 int node1,
2571 int node2,
2572 int param,
2573 int *value,
2574 struct ndb_mgm_reply* mgmreply){
2575 CHECK_HANDLE(handle, -1);
2576 CHECK_CONNECTED(handle, -2);
2577 DBUG_ENTER("ndb_mgm_get_connection_int_parameter");
2578
2579 Properties args;
2580 args.put("node1", node1);
2581 args.put("node2", node2);
2582 args.put("param", param);
2583
2584 const ParserRow<ParserDummy> reply[]= {
2585 MGM_CMD("get connection parameter reply", NULL, ""),
2586 MGM_ARG("value", Int, Mandatory, "Current Value"),
2587 MGM_ARG("result", String, Mandatory, "Result"),
2588 MGM_END()
2589 };
2590
2591 const Properties *prop;
2592 prop = ndb_mgm_call(handle, reply, "get connection parameter", &args);
2593 DBUG_CHECK_REPLY(handle, prop, -3);
2594
2595 int res= -1;
2596 do {
2597 const char * buf;
2598 if(!prop->get("result", &buf) || strcmp(buf, "Ok") != 0){
2599 fprintf(handle->errstream, "ERROR Message: %s\n", buf);
2600 break;
2601 }
2602 res= 0;
2603 } while(0);
2604
2605 if(!prop->get("value",(Uint32*)value)){
2606 fprintf(handle->errstream, "Unable to get value\n");
2607 res = -4;
2608 }
2609
2610 delete prop;
2611 DBUG_RETURN(res);
2612 }
2613
2614 extern "C"
2615 NDB_SOCKET_TYPE
ndb_mgm_convert_to_transporter(NdbMgmHandle * handle)2616 ndb_mgm_convert_to_transporter(NdbMgmHandle *handle)
2617 {
2618 NDB_SOCKET_TYPE s;
2619
2620 CHECK_HANDLE((*handle), NDB_INVALID_SOCKET);
2621 CHECK_CONNECTED((*handle), NDB_INVALID_SOCKET);
2622
2623 (*handle)->connected= 0; // we pretend we're disconnected
2624 s= (*handle)->socket;
2625
2626 SocketOutputStream s_output(s, (*handle)->timeout);
2627 s_output.println("transporter connect");
2628 s_output.println("");
2629
2630 ndb_mgm_destroy_handle(handle); // set connected=0, so won't disconnect
2631
2632 return s;
2633 }
2634
2635 extern "C"
2636 Uint32
ndb_mgm_get_mgmd_nodeid(NdbMgmHandle handle)2637 ndb_mgm_get_mgmd_nodeid(NdbMgmHandle handle)
2638 {
2639 Uint32 nodeid=0;
2640
2641 CHECK_HANDLE(handle, 0);
2642 CHECK_CONNECTED(handle, 0);
2643 DBUG_ENTER("ndb_mgm_get_mgmd_nodeid");
2644
2645 Properties args;
2646
2647 const ParserRow<ParserDummy> reply[]= {
2648 MGM_CMD("get mgmd nodeid reply", NULL, ""),
2649 MGM_ARG("nodeid", Int, Mandatory, "Node ID"),
2650 MGM_END()
2651 };
2652
2653 const Properties *prop;
2654 prop = ndb_mgm_call(handle, reply, "get mgmd nodeid", &args);
2655 DBUG_CHECK_REPLY(handle, prop, 0);
2656
2657 if(!prop->get("nodeid",&nodeid)){
2658 fprintf(handle->errstream, "Unable to get value\n");
2659 return 0;
2660 }
2661
2662 delete prop;
2663 DBUG_RETURN(nodeid);
2664 }
2665
2666 extern "C"
ndb_mgm_report_event(NdbMgmHandle handle,Uint32 * data,Uint32 length)2667 int ndb_mgm_report_event(NdbMgmHandle handle, Uint32 *data, Uint32 length)
2668 {
2669 CHECK_HANDLE(handle, 0);
2670 CHECK_CONNECTED(handle, 0);
2671 DBUG_ENTER("ndb_mgm_report_event");
2672
2673 Properties args;
2674 args.put("length", length);
2675 BaseString data_string;
2676
2677 for (int i = 0; i < (int) length; i++)
2678 data_string.appfmt(" %lu", (ulong) data[i]);
2679
2680 args.put("data", data_string.c_str());
2681
2682 const ParserRow<ParserDummy> reply[]= {
2683 MGM_CMD("report event reply", NULL, ""),
2684 MGM_ARG("result", String, Mandatory, "Result"),
2685 MGM_END()
2686 };
2687
2688 const Properties *prop;
2689 prop = ndb_mgm_call(handle, reply, "report event", &args);
2690 DBUG_CHECK_REPLY(handle, prop, -1);
2691
2692 DBUG_RETURN(0);
2693 }
2694
2695 extern "C"
ndb_mgm_end_session(NdbMgmHandle handle)2696 int ndb_mgm_end_session(NdbMgmHandle handle)
2697 {
2698 CHECK_HANDLE(handle, 0);
2699 CHECK_CONNECTED(handle, 0);
2700 DBUG_ENTER("ndb_mgm_end_session");
2701
2702 SocketOutputStream s_output(handle->socket, handle->timeout);
2703 s_output.println("end session");
2704 s_output.println("");
2705
2706 SocketInputStream in(handle->socket, handle->timeout);
2707 char buf[32];
2708 in.gets(buf, sizeof(buf));
2709 CHECK_TIMEDOUT_RET(handle, in, s_output, -1);
2710
2711 DBUG_RETURN(0);
2712 }
2713
2714 extern "C"
ndb_mgm_get_version(NdbMgmHandle handle,int * major,int * minor,int * build,int len,char * str)2715 int ndb_mgm_get_version(NdbMgmHandle handle,
2716 int *major, int *minor, int *build, int len, char* str)
2717 {
2718 DBUG_ENTER("ndb_mgm_get_version");
2719 CHECK_HANDLE(handle, 0);
2720 CHECK_CONNECTED(handle, 0);
2721
2722 Properties args;
2723
2724 const ParserRow<ParserDummy> reply[]= {
2725 MGM_CMD("version", NULL, ""),
2726 MGM_ARG("id", Int, Mandatory, "ID"),
2727 MGM_ARG("major", Int, Mandatory, "Major"),
2728 MGM_ARG("minor", Int, Mandatory, "Minor"),
2729 MGM_ARG("string", String, Mandatory, "String"),
2730 MGM_END()
2731 };
2732
2733 const Properties *prop;
2734 prop = ndb_mgm_call(handle, reply, "get version", &args);
2735 CHECK_REPLY(handle, prop, 0);
2736
2737 Uint32 id;
2738 if(!prop->get("id",&id)){
2739 fprintf(handle->errstream, "Unable to get value\n");
2740 return 0;
2741 }
2742 *build= getBuild(id);
2743
2744 if(!prop->get("major",(Uint32*)major)){
2745 fprintf(handle->errstream, "Unable to get value\n");
2746 return 0;
2747 }
2748
2749 if(!prop->get("minor",(Uint32*)minor)){
2750 fprintf(handle->errstream, "Unable to get value\n");
2751 return 0;
2752 }
2753
2754 BaseString result;
2755 if(!prop->get("string", result)){
2756 fprintf(handle->errstream, "Unable to get value\n");
2757 return 0;
2758 }
2759
2760 strncpy(str, result.c_str(), len);
2761
2762 delete prop;
2763 DBUG_RETURN(1);
2764 }
2765
2766 extern "C"
2767 Uint64
ndb_mgm_get_session_id(NdbMgmHandle handle)2768 ndb_mgm_get_session_id(NdbMgmHandle handle)
2769 {
2770 Uint64 session_id=0;
2771
2772 DBUG_ENTER("ndb_mgm_get_session_id");
2773 CHECK_HANDLE(handle, 0);
2774 CHECK_CONNECTED(handle, 0);
2775
2776 Properties args;
2777
2778 const ParserRow<ParserDummy> reply[]= {
2779 MGM_CMD("get session id reply", NULL, ""),
2780 MGM_ARG("id", Int, Mandatory, "Node ID"),
2781 MGM_END()
2782 };
2783
2784 const Properties *prop;
2785 prop = ndb_mgm_call(handle, reply, "get session id", &args);
2786 CHECK_REPLY(handle, prop, 0);
2787
2788 if(!prop->get("id",&session_id)){
2789 fprintf(handle->errstream, "Unable to get session id\n");
2790 return 0;
2791 }
2792
2793 delete prop;
2794 DBUG_RETURN(session_id);
2795 }
2796
2797 extern "C"
2798 int
ndb_mgm_get_session(NdbMgmHandle handle,Uint64 id,struct NdbMgmSession * s,int * len)2799 ndb_mgm_get_session(NdbMgmHandle handle, Uint64 id,
2800 struct NdbMgmSession *s, int *len)
2801 {
2802 int retval= 0;
2803 DBUG_ENTER("ndb_mgm_get_session");
2804 CHECK_HANDLE(handle, 0);
2805 CHECK_CONNECTED(handle, 0);
2806
2807 Properties args;
2808 args.put("id", id);
2809
2810 const ParserRow<ParserDummy> reply[]= {
2811 MGM_CMD("get session reply", NULL, ""),
2812 MGM_ARG("id", Int, Mandatory, "Node ID"),
2813 MGM_ARG("m_stopSelf", Int, Optional, "m_stopSelf"),
2814 MGM_ARG("m_stop", Int, Optional, "stop session"),
2815 MGM_ARG("nodeid", Int, Optional, "allocated node id"),
2816 MGM_ARG("parser_buffer_len", Int, Optional, "waiting in buffer"),
2817 MGM_ARG("parser_status", Int, Optional, "parser status"),
2818 MGM_END()
2819 };
2820
2821 const Properties *prop;
2822 prop = ndb_mgm_call(handle, reply, "get session", &args);
2823 CHECK_REPLY(handle, prop, 0);
2824
2825 Uint64 r_id;
2826 int rlen= 0;
2827
2828 if(!prop->get("id",&r_id)){
2829 fprintf(handle->errstream, "Unable to get session id\n");
2830 goto err;
2831 }
2832
2833 s->id= r_id;
2834 rlen+=sizeof(s->id);
2835
2836 if(prop->get("m_stopSelf",&(s->m_stopSelf)))
2837 rlen+=sizeof(s->m_stopSelf);
2838 else
2839 goto err;
2840
2841 if(prop->get("m_stop",&(s->m_stop)))
2842 rlen+=sizeof(s->m_stop);
2843 else
2844 goto err;
2845
2846 if(prop->get("nodeid",&(s->nodeid)))
2847 rlen+=sizeof(s->nodeid);
2848 else
2849 goto err;
2850
2851 if(prop->get("parser_buffer_len",&(s->parser_buffer_len)))
2852 {
2853 rlen+=sizeof(s->parser_buffer_len);
2854 if(prop->get("parser_status",&(s->parser_status)))
2855 rlen+=sizeof(s->parser_status);
2856 }
2857
2858 *len= rlen;
2859 retval= 1;
2860
2861 err:
2862 delete prop;
2863 DBUG_RETURN(retval);
2864 }
2865
2866 template class Vector<const ParserRow<ParserDummy>*>;
2867