1 /*
2 Copyright (c) 2003, 2010, Oracle and/or its affiliates. All rights reserved.
3
4 This program is free software; you can redistribute it and/or modify
5 it under the terms of the GNU General Public License, 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 <uucode.h>
28 #include <socket_io.h>
29 #include <util/version.h>
30 #include <mgmapi.h>
31 #include <EventLogger.hpp>
32 #include <signaldata/SetLogLevelOrd.hpp>
33 #include <LogLevel.hpp>
34 #include <BaseString.hpp>
35
36 #include <ConfigValues.hpp>
37 #include <mgmapi_configuration.hpp>
38 #include <Vector.hpp>
39 #include "Services.hpp"
40 #include "../mgmapi/ndb_logevent.hpp"
41
42 #include "ndb_mgmd_error.h"
43
44 #include <ndb_base64.h>
45 #include <ndberror.h>
46
47 extern bool g_StopServer;
48 extern bool g_RestartServer;
49 extern EventLogger * g_eventLogger;
50
51 /**
52 const char * name;
53 const char * realName;
54 const Type type;
55 const ArgType argType;
56 const ArgRequired argRequired;
57 const ArgMinMax argMinMax;
58 const int minVal;
59 const int maxVal;
60 void (T::* function)(const class Properties & args);
61 const char * description;
62 */
63
64 #define MGM_CMD(name, fun, desc) \
65 { name, \
66 0, \
67 ParserRow<MgmApiSession>::Cmd, \
68 ParserRow<MgmApiSession>::String, \
69 ParserRow<MgmApiSession>::Optional, \
70 ParserRow<MgmApiSession>::IgnoreMinMax, \
71 0, 0, \
72 fun, \
73 desc, 0 }
74
75 #define MGM_ARG(name, type, opt, desc) \
76 { name, \
77 0, \
78 ParserRow<MgmApiSession>::Arg, \
79 ParserRow<MgmApiSession>::type, \
80 ParserRow<MgmApiSession>::opt, \
81 ParserRow<MgmApiSession>::IgnoreMinMax, \
82 0, 0, \
83 0, \
84 desc, 0 }
85
86 #define MGM_ARG2(name, type, opt, min, max, desc) \
87 { name, \
88 0, \
89 ParserRow<MgmApiSession>::Arg, \
90 ParserRow<MgmApiSession>::type, \
91 ParserRow<MgmApiSession>::opt, \
92 ParserRow<MgmApiSession>::IgnoreMinMax, \
93 min, max, \
94 0, \
95 desc, 0 }
96
97 #define MGM_END() \
98 { 0, \
99 0, \
100 ParserRow<MgmApiSession>::Arg, \
101 ParserRow<MgmApiSession>::Int, \
102 ParserRow<MgmApiSession>::Optional, \
103 ParserRow<MgmApiSession>::IgnoreMinMax, \
104 0, 0, \
105 0, \
106 0, 0 }
107
108 #define MGM_CMD_ALIAS(name, realName, fun) \
109 { name, \
110 realName, \
111 ParserRow<MgmApiSession>::CmdAlias, \
112 ParserRow<MgmApiSession>::Int, \
113 ParserRow<MgmApiSession>::Optional, \
114 ParserRow<MgmApiSession>::IgnoreMinMax, \
115 0, 0, \
116 0, \
117 0, 0 }
118
119 #define MGM_ARG_ALIAS(name, realName, fun) \
120 { name, \
121 realName, \
122 ParserRow<MgmApiSession>::ArgAlias, \
123 ParserRow<MgmApiSession>::Int, \
124 ParserRow<MgmApiSession>::Optional, \
125 ParserRow<MgmApiSession>::IgnoreMinMax, \
126 0, 0, \
127 0, \
128 0, 0 }
129
130 const
131 ParserRow<MgmApiSession> commands[] = {
132 MGM_CMD("get config", &MgmApiSession::getConfig, ""),
133 MGM_ARG("version", Int, Mandatory, "Configuration version number"),
134 MGM_ARG("node", Int, Optional, "Node ID"),
135 MGM_ARG("nodetype", Int, Optional, "Type of requesting node"),
136 MGM_ARG("from_node", Int, Optional, "Node to get config from"),
137
138 MGM_CMD("get nodeid", &MgmApiSession::get_nodeid, ""),
139 MGM_ARG("version", Int, Mandatory, "Configuration version number"),
140 MGM_ARG("nodetype", Int, Mandatory, "Node type"),
141 MGM_ARG("transporter", String, Optional, "Transporter type"),
142 MGM_ARG("nodeid", Int, Optional, "Node ID"),
143 MGM_ARG("user", String, Mandatory, "Password"),
144 MGM_ARG("password", String, Mandatory, "Password"),
145 MGM_ARG("public key", String, Mandatory, "Public key"),
146 MGM_ARG("endian", String, Optional, "Endianness"),
147 MGM_ARG("name", String, Optional, "Name of connection"),
148 MGM_ARG("timeout", Int, Optional, "Timeout in seconds"),
149 MGM_ARG("log_event", Int, Optional, "Log failure in cluster log"),
150
151 MGM_CMD("get version", &MgmApiSession::getVersion, ""),
152
153 MGM_CMD("get status", &MgmApiSession::getStatus, ""),
154 MGM_ARG("types", String, Optional, "Types"),
155
156 MGM_CMD("get info clusterlog", &MgmApiSession::getInfoClusterLog, ""),
157 MGM_CMD("get cluster loglevel", &MgmApiSession::getClusterLogLevel, ""),
158
159 MGM_CMD("restart node", &MgmApiSession::restart_v1, ""),
160 MGM_ARG("node", String, Mandatory, "Nodes to restart"),
161 MGM_ARG("initialstart", Int, Optional, "Initial start"),
162 MGM_ARG("nostart", Int, Optional, "No start"),
163 MGM_ARG("abort", Int, Optional, "Abort"),
164
165 MGM_CMD("restart node v2", &MgmApiSession::restart_v2, ""),
166 MGM_ARG("node", String, Mandatory, "Nodes to restart"),
167 MGM_ARG("initialstart", Int, Optional, "Initial start"),
168 MGM_ARG("nostart", Int, Optional, "No start"),
169 MGM_ARG("abort", Int, Optional, "Abort"),
170 MGM_ARG("force", Int, Optional, "Force"),
171
172 MGM_CMD("restart all", &MgmApiSession::restartAll, ""),
173 MGM_ARG("initialstart", Int, Optional, "Initial start"),
174 MGM_ARG("nostart", Int, Optional, "No start"),
175 MGM_ARG("abort", Int, Optional, "Abort"),
176
177 MGM_CMD("insert error", &MgmApiSession::insertError, ""),
178 MGM_ARG("node", Int, Mandatory, "Node to receive error"),
179 MGM_ARG("error", Int, Mandatory, "Errorcode to insert"),
180
181 MGM_CMD("set trace", &MgmApiSession::setTrace, ""),
182 MGM_ARG("node", Int, Mandatory, "Node"),
183 MGM_ARG("trace", Int, Mandatory, "Trace number"),
184
185 MGM_CMD("log signals", &MgmApiSession::logSignals, ""),
186 MGM_ARG("node", Int, Mandatory, "Node"),
187 MGM_ARG("blocks", String, Mandatory, "Blocks (space separated)"),
188 MGM_ARG("in", Int, Mandatory, "Log input signals"),
189 MGM_ARG("out", Int, Mandatory, "Log output signals"),
190
191 MGM_CMD("start signallog", &MgmApiSession::startSignalLog, ""),
192 MGM_ARG("node", Int, Mandatory, "Node"),
193
194 MGM_CMD("stop signallog", &MgmApiSession::stopSignalLog, ""),
195 MGM_ARG("node", Int, Mandatory, "Node"),
196
197 MGM_CMD("dump state", &MgmApiSession::dumpState, ""),
198 MGM_ARG("node", Int, Mandatory ,"Node"),
199 MGM_ARG("args", String, Mandatory, "Args(space separated int's)"),
200
201 MGM_CMD("start backup", &MgmApiSession::startBackup, ""),
202 MGM_ARG("completed", Int, Optional ,"Wait until completed"),
203 MGM_ARG("backupid", Int, Optional ,"User input backup id"),
204 MGM_ARG("backuppoint", Int, Optional ,"backup snapshot at start time or complete time"),
205
206 MGM_CMD("abort backup", &MgmApiSession::abortBackup, ""),
207 MGM_ARG("id", Int, Mandatory, "Backup id"),
208
209 MGM_CMD("stop", &MgmApiSession::stop_v1, ""),
210 MGM_ARG("node", String, Mandatory, "Node"),
211 MGM_ARG("abort", Int, Mandatory, "Node"),
212
213 MGM_CMD("stop v2", &MgmApiSession::stop_v2, ""),
214 MGM_ARG("node", String, Mandatory, "Node"),
215 MGM_ARG("abort", Int, Mandatory, "Node"),
216 MGM_ARG("force", Int, Optional, "Force"),
217
218 MGM_CMD("stop all", &MgmApiSession::stopAll, ""),
219 MGM_ARG("abort", Int, Mandatory, "Node"),
220 MGM_ARG("stop", String, Optional, "MGM/DB or both"),
221
222 MGM_CMD("enter single user", &MgmApiSession::enterSingleUser, ""),
223 MGM_ARG("nodeId", Int, Mandatory, "Node"),
224
225 MGM_CMD("exit single user", &MgmApiSession::exitSingleUser, ""),
226
227
228 MGM_CMD("start", &MgmApiSession::start, ""),
229 MGM_ARG("node", Int, Mandatory, "Node"),
230
231 MGM_CMD("start all", &MgmApiSession::startAll, ""),
232
233 MGM_CMD("bye", &MgmApiSession::bye, ""),
234
235 MGM_CMD("end session", &MgmApiSession::endSession, ""),
236
237 MGM_CMD("set loglevel", &MgmApiSession::setLogLevel, ""),
238 MGM_ARG("node", Int, Mandatory, "Node"),
239 MGM_ARG("category", Int, Mandatory, "Event category"),
240 MGM_ARG("level", Int, Mandatory, "Log level (0-15)"),
241
242 MGM_CMD("set cluster loglevel", &MgmApiSession::setClusterLogLevel, ""),
243 MGM_ARG("node", Int, Mandatory, "Node"),
244 MGM_ARG("category", Int, Mandatory, "Event category"),
245 MGM_ARG("level", Int, Mandatory, "Log level (0-15)"),
246
247 MGM_CMD("set logfilter", &MgmApiSession::setLogFilter, ""),
248 MGM_ARG("level", Int, Mandatory, "Severety level"),
249 MGM_ARG("enable", Int, Mandatory, "1=disable, 0=enable, -1=toggle"),
250
251 MGM_CMD("set parameter", &MgmApiSession::setParameter, ""),
252 MGM_ARG("node", Int, Mandatory, "Node"),
253 MGM_ARG("parameter", Int, Mandatory, "Parameter"),
254 MGM_ARG("value", String, Mandatory, "Value"),
255
256 MGM_CMD("set connection parameter",
257 &MgmApiSession::setConnectionParameter, ""),
258 MGM_ARG("node1", Int, Mandatory, "Node1 ID"),
259 MGM_ARG("node2", Int, Mandatory, "Node2 ID"),
260 MGM_ARG("param", Int, Mandatory, "Parameter"),
261 MGM_ARG("value", Int, Mandatory, "Value"),
262
263 MGM_CMD("get connection parameter",
264 &MgmApiSession::getConnectionParameter, ""),
265 MGM_ARG("node1", Int, Mandatory, "Node1 ID"),
266 MGM_ARG("node2", Int, Mandatory, "Node2 ID"),
267 MGM_ARG("param", Int, Mandatory, "Parameter"),
268
269 MGM_CMD("listen event", &MgmApiSession::listen_event, ""),
270 MGM_ARG("node", Int, Optional, "Node"),
271 MGM_ARG("parsable", Int, Optional, "Parsable"),
272 MGM_ARG("filter", String, Mandatory, "Event category"),
273
274 MGM_CMD("purge stale sessions", &MgmApiSession::purge_stale_sessions, ""),
275
276 MGM_CMD("check connection", &MgmApiSession::check_connection, ""),
277
278 MGM_CMD("transporter connect", &MgmApiSession::transporter_connect, ""),
279
280 MGM_CMD("get mgmd nodeid", &MgmApiSession::get_mgmd_nodeid, ""),
281
282 MGM_CMD("report event", &MgmApiSession::report_event, ""),
283 MGM_ARG("length", Int, Mandatory, "Length"),
284 MGM_ARG("data", String, Mandatory, "Data"),
285
286 MGM_CMD("list sessions", &MgmApiSession::listSessions, ""),
287
288 MGM_CMD("get session id", &MgmApiSession::getSessionId, ""),
289
290 MGM_CMD("get session", &MgmApiSession::getSession, ""),
291 MGM_ARG("id", Int, Mandatory, "SessionID"),
292
293 MGM_CMD("set config", &MgmApiSession::setConfig, ""),
294 MGM_ARG("Content-Length", Int, Mandatory, "Length of config"),
295 MGM_ARG("Content-Type", String, Mandatory, "Type of config"),
296 MGM_ARG("Content-Transfer-Encoding", String, Mandatory, "encoding"),
297
298 MGM_CMD("create nodegroup", &MgmApiSession::create_nodegroup, ""),
299 MGM_ARG("nodes", String, Mandatory, "Nodes"),
300
301 MGM_CMD("drop nodegroup", &MgmApiSession::drop_nodegroup, ""),
302 MGM_ARG("ng", Int, Mandatory, "Nodegroup"),
303
304 MGM_CMD("show config", &MgmApiSession::showConfig, ""),
305 MGM_ARG("Section", String, Optional, "Section name"),
306 MGM_ARG("NodeId", Int, Optional, "Nodeid"),
307 MGM_ARG("Name", String, Optional, "Parameter name"),
308
309 MGM_CMD("reload config", &MgmApiSession::reloadConfig, ""),
310 MGM_ARG("config_filename", String, Optional, "Reload from path"),
311 MGM_ARG("mycnf", Int, Optional, "Reload from my.cnf"),
312 MGM_ARG("force", Int, Optional, "Force reload"),
313
314 MGM_CMD("show variables", &MgmApiSession::show_variables, ""),
315
316 MGM_CMD("dump events", &MgmApiSession::dump_events, ""),
317 MGM_ARG("type", Int, Mandatory, "Type of event"),
318 MGM_ARG("nodes", String, Optional, "Nodes to include"),
319
320 MGM_END()
321 };
322
323 struct PurgeStruct
324 {
325 NodeBitmask free_nodes;/* free nodes as reported
326 * by ndbd in apiRegReqConf
327 */
328 BaseString *str;
329 NDB_TICKS tick;
330 };
331
332 extern int g_errorInsert;
333 #define ERROR_INSERTED(x) (g_errorInsert == x || m_errorInsert == x)
334
335 #define SLEEP_ERROR_INSERTED(x) if(ERROR_INSERTED(x)){NdbSleep_SecSleep(10);}
336
MgmApiSession(class MgmtSrvr & mgm,NDB_SOCKET_TYPE sock,Uint64 session_id)337 MgmApiSession::MgmApiSession(class MgmtSrvr & mgm, NDB_SOCKET_TYPE sock, Uint64 session_id)
338 : SocketServer::Session(sock), m_mgmsrv(mgm), m_name("unknown:0")
339 {
340 DBUG_ENTER("MgmApiSession::MgmApiSession");
341 m_input = new SocketInputStream(sock, SOCKET_TIMEOUT);
342 m_output = new BufferedSockOutputStream(sock, SOCKET_TIMEOUT);
343 m_parser = new Parser_t(commands, *m_input, true, true, true);
344 m_allocated_resources= new MgmtSrvr::Allocated_resources(m_mgmsrv);
345 m_stopSelf= 0;
346 m_ctx= NULL;
347 m_session_id= session_id;
348 m_mutex= NdbMutex_Create();
349 m_errorInsert= 0;
350
351 struct sockaddr_in addr;
352 SOCKET_SIZE_TYPE addrlen= sizeof(addr);
353 if (my_getpeername(sock, (struct sockaddr*)&addr, &addrlen) == 0)
354 m_name.assfmt("%s:%d", inet_ntoa(addr.sin_addr), ntohs(addr.sin_port));
355 DBUG_PRINT("info", ("new connection from: %s", m_name.c_str()));
356
357 DBUG_VOID_RETURN;
358 }
359
~MgmApiSession()360 MgmApiSession::~MgmApiSession()
361 {
362 DBUG_ENTER("MgmApiSession::~MgmApiSession");
363 if (m_input)
364 delete m_input;
365 if (m_output)
366 delete m_output;
367 if (m_parser)
368 delete m_parser;
369 if (m_allocated_resources)
370 delete m_allocated_resources;
371 if(my_socket_valid(m_socket))
372 {
373 NDB_CLOSE_SOCKET(m_socket);
374 my_socket_invalidate(&m_socket);
375 }
376 if(m_stopSelf < 0)
377 g_RestartServer= true;
378 if(m_stopSelf)
379 g_StopServer= true;
380 NdbMutex_Destroy(m_mutex);
381 DBUG_VOID_RETURN;
382 }
383
384 void
runSession()385 MgmApiSession::runSession()
386 {
387 DBUG_ENTER("MgmApiSession::runSession");
388
389 g_eventLogger->debug("%s: Connected!", name());
390
391 Parser_t::Context ctx;
392 ctx.m_mutex= m_mutex;
393 m_ctx= &ctx;
394 bool stop= false;
395 while(!stop) {
396 NdbMutex_Lock(m_mutex);
397
398 m_input->reset_timeout();
399 m_output->reset_timeout();
400
401 if (m_parser->run(ctx, *this))
402 {
403 stop= m_stop; // Has session been stopped
404 assert(ctx.m_status == Parser_t::Ok);
405 }
406 else
407 {
408 stop= m_stop; // Has session been stopped
409 const char* msg= NULL;
410 switch(ctx.m_status) {
411 case Parser_t::Eof: // Client disconnected
412 stop= true;
413 g_eventLogger->debug("%s: Eof!", name());
414 break;
415
416 case Parser_t::ExternalStop: // Stopped by other thread
417 stop= true;
418 g_eventLogger->debug("%s: ExternalStop!", name());
419 break;
420
421 case Parser_t::NoLine: // Normal read timeout
422 case Parser_t::EmptyLine:
423 break;
424
425 case Parser_t::UnknownCommand: msg= "Unknown command"; break;
426 case Parser_t::UnknownArgument: msg= "Unknown argument"; break;
427 case Parser_t::TypeMismatch: msg= "Type mismatch"; break;
428 case Parser_t::InvalidArgumentFormat: msg= "Invalid arg. format"; break;
429 case Parser_t::UnknownArgumentType: msg= "Unknown argument type"; break;
430 case Parser_t::ArgumentGivenTwice: msg= "Argument given twice"; break;
431 case Parser_t::MissingMandatoryArgument: msg= "Missing arg."; break;
432
433 case Parser_t::Ok: // Should never happen here
434 case Parser_t::CommandWithoutFunction:
435 abort();
436 break;
437 }
438
439 if (msg){
440 g_eventLogger->debug("%s: %s, '%s'",
441 name(),
442 msg,
443 ctx.m_currentToken != 0 ?
444 ctx.m_currentToken : "<NULL>");
445
446 // Send result to client
447 m_output->println("result: %s, '%s'",
448 msg,
449 ctx.m_currentToken != 0 ?
450 ctx.m_currentToken : "<NULL>");
451 m_output->print("\n");
452 }
453 }
454
455 NdbMutex_Unlock(m_mutex);
456
457 // Send output from command to the client
458 m_output->flush();
459
460 }
461
462 g_eventLogger->debug("%s: Stopped!", name());
463
464 NdbMutex_Lock(m_mutex);
465 m_ctx= NULL;
466 if(my_socket_valid(m_socket))
467 {
468 my_socket_close(m_socket);
469 my_socket_invalidate(&m_socket);
470 }
471 NdbMutex_Unlock(m_mutex);
472
473 g_eventLogger->debug("%s: Disconnected!", name());
474
475 DBUG_VOID_RETURN;
476 }
477
478 void
get_nodeid(Parser_t::Context &,const class Properties & args)479 MgmApiSession::get_nodeid(Parser_t::Context &,
480 const class Properties &args)
481 {
482 Uint32 version, nodeid= 0, nodetype= 0xff;
483 Uint32 timeout= 20; // default seconds timeout
484 const char * transporter;
485 const char * user;
486 const char * password;
487 const char * public_key;
488 const char * endian= NULL;
489 const char * name= NULL;
490 Uint32 log_event= 1;
491 bool log_event_version;
492 union { long l; char c[sizeof(long)]; } endian_check;
493
494 args.get("version", &version);
495 args.get("nodetype", &nodetype);
496 args.get("transporter", &transporter);
497 args.get("nodeid", &nodeid);
498 args.get("user", &user);
499 args.get("password", &password);
500 args.get("public key", &public_key);
501 args.get("endian", &endian);
502 args.get("name", &name);
503 args.get("timeout", &timeout);
504 /* for backwards compatability keep track if client uses new protocol */
505 log_event_version= args.get("log_event", &log_event);
506
507 m_output->println("get nodeid reply");
508
509 endian_check.l = 1;
510 if(endian
511 && strcmp(endian,(endian_check.c[sizeof(long)-1])?"big":"little")!=0) {
512 m_output->println("result: Node does not have the same endianness as the management server.");
513 m_output->println("%s", "");
514 return;
515 }
516
517 bool compatible;
518 switch (nodetype) {
519 case NODE_TYPE_MGM:
520 case NODE_TYPE_API:
521 compatible = ndbCompatible_mgmt_api(NDB_VERSION, version);
522 break;
523 case NODE_TYPE_DB:
524 compatible = ndbCompatible_mgmt_ndb(NDB_VERSION, version);
525 break;
526 default:
527 m_output->println("result: unknown nodetype %d", nodetype);
528 m_output->println("%s", "");
529 return;
530 }
531
532 struct sockaddr_in addr;
533 SOCKET_SIZE_TYPE addrlen= sizeof(addr);
534 int r = my_getpeername(m_socket, (struct sockaddr*)&addr, &addrlen);
535 if (r != 0 ) {
536 m_output->println("result: getpeername(" MY_SOCKET_FORMAT \
537 ") failed, err= %d",
538 MY_SOCKET_FORMAT_VALUE(m_socket), r);
539 m_output->println("%s", "");
540 return;
541 }
542
543 /* Check nodeid parameter */
544 if (nodeid > MAX_NODES_ID)
545 {
546 m_output->println("result: illegal nodeid %u", nodeid);
547 m_output->println("%s", "");
548 return;
549 }
550
551 NodeId tmp= nodeid;
552 if(tmp == 0 || !m_allocated_resources->is_reserved(tmp)){
553 BaseString error_string;
554 int error_code;
555 NDB_TICKS tick= 0;
556 /* only report error on second attempt as not to clog the cluster log */
557 while (!m_mgmsrv.alloc_node_id(&tmp, (enum ndb_mgm_node_type)nodetype,
558 (struct sockaddr*)&addr, &addrlen,
559 error_code, error_string,
560 tick == 0 ? 0 : log_event,
561 timeout))
562 {
563 /* NDB_MGM_ALLOCID_CONFIG_MISMATCH is a non retriable error */
564 if (tick == 0 && error_code != NDB_MGM_ALLOCID_CONFIG_MISMATCH)
565 {
566 // attempt to free any timed out reservations
567 tick= NdbTick_CurrentMillisecond();
568 struct PurgeStruct ps;
569 m_mgmsrv.get_connected_nodes(ps.free_nodes);
570 // invert connected_nodes to get free nodes
571 ps.free_nodes.bitXORC(NodeBitmask());
572 ps.str= 0;
573 ps.tick= tick;
574 m_mgmsrv.get_socket_server()->
575 foreachSession(stop_session_if_timed_out,&ps);
576 m_mgmsrv.get_socket_server()->checkSessions();
577 error_string = "";
578 continue;
579 }
580 const char *alias;
581 const char *str;
582 alias= ndb_mgm_get_node_type_alias_string((enum ndb_mgm_node_type)
583 nodetype, &str);
584 m_output->println("result: %s", error_string.c_str());
585 /* only use error_code protocol if client knows about it */
586 if (log_event_version)
587 m_output->println("error_code: %d", error_code);
588 m_output->println("%s", "");
589 return;
590 }
591 }
592
593 #if 0
594 if (!compatible){
595 m_output->println(cmd);
596 m_output->println("result: incompatible version mgmt 0x%x and node 0x%x",
597 NDB_VERSION, version);
598 m_output->println("%s", "");
599 return;
600 }
601 #endif
602
603 m_output->println("nodeid: %u", tmp);
604 m_output->println("result: Ok");
605 m_output->println("%s", "");
606 m_allocated_resources->reserve_node(tmp, timeout*1000);
607
608 if (name)
609 g_eventLogger->info("Node %d: %s", tmp, name);
610
611 return;
612 }
613
614 void
getConfig(Parser_t::Context &,const class Properties & args)615 MgmApiSession::getConfig(Parser_t::Context &,
616 const class Properties &args)
617 {
618 Uint32 nodetype = NDB_MGM_NODE_TYPE_UNKNOWN;
619 Uint32 from_node = 0;
620
621 // Ignoring mandatory parameter "version"
622 // Ignoring optional parameter "node"
623 args.get("nodetype", &nodetype);
624 args.get("from_node", &from_node);
625
626 SLEEP_ERROR_INSERTED(1);
627 m_output->println("get config reply");
628
629 BaseString pack64, error;
630
631 UtilBuffer packed;
632
633 bool success = (from_node > 0) ?
634 m_mgmsrv.get_packed_config_from_node(from_node,
635 pack64, error) :
636 m_mgmsrv.get_packed_config((ndb_mgm_node_type)nodetype,
637 pack64, error);
638
639 if (!success)
640 {
641 m_output->println("result: %s", error.c_str());
642 m_output->print("\n");
643 return;
644 }
645
646 m_output->println("result: Ok");
647 m_output->println("Content-Length: %u", pack64.length());
648 m_output->println("Content-Type: ndbconfig/octet-stream");
649 SLEEP_ERROR_INSERTED(2);
650 m_output->println("Content-Transfer-Encoding: base64");
651 m_output->print("\n");
652
653 if(ERROR_INSERTED(3))
654 {
655 // Return only half the packed config
656 BaseString half64 = pack64.substr(0, pack64.length());
657 m_output->println(half64.c_str());
658 return;
659 }
660 m_output->println(pack64.c_str());
661 m_output->print("\n");
662 return;
663 }
664
665 void
insertError(Parser<MgmApiSession>::Context &,Properties const & args)666 MgmApiSession::insertError(Parser<MgmApiSession>::Context &,
667 Properties const &args) {
668 Uint32 node = 0, error = 0;
669 int result= 0;
670
671 args.get("node", &node);
672 args.get("error", &error);
673
674 if(node==m_mgmsrv.getOwnNodeId()
675 && error < MGM_ERROR_MAX_INJECT_SESSION_ONLY)
676 {
677 m_errorInsert= error;
678 if(error==0)
679 g_errorInsert= error;
680 }
681 else
682 {
683 result= m_mgmsrv.insertError(node, error);
684 }
685
686 m_output->println("insert error reply");
687 if(result != 0)
688 m_output->println("result: %s", get_error_text(result));
689 else
690 m_output->println("result: Ok");
691 m_output->println("%s", "");
692 }
693
694 void
setTrace(Parser<MgmApiSession>::Context &,Properties const & args)695 MgmApiSession::setTrace(Parser<MgmApiSession>::Context &,
696 Properties const &args) {
697 Uint32 node = 0, trace = 0;
698
699 args.get("node", &node);
700 args.get("trace", &trace);
701
702 int result = m_mgmsrv.setTraceNo(node, trace);
703
704 m_output->println("set trace reply");
705 if(result != 0)
706 m_output->println("result: %s", get_error_text(result));
707 else
708 m_output->println("result: Ok");
709 m_output->println("%s", "");
710 }
711
712 void
getVersion(Parser<MgmApiSession>::Context &,Properties const &)713 MgmApiSession::getVersion(Parser<MgmApiSession>::Context &,
714 Properties const &) {
715 m_output->println("version");
716 m_output->println("id: %d", NDB_VERSION_D);
717 m_output->println("major: %d", NDB_VERSION_MAJOR);
718 m_output->println("minor: %d", NDB_VERSION_MINOR);
719 m_output->println("build: %d", NDB_VERSION_BUILD);
720 m_output->println("string: %s", m_mgmsrv.get_version_string());
721 m_output->println("mysql_major: %d", NDB_MYSQL_VERSION_MAJOR);
722 m_output->println("mysql_minor: %d", NDB_MYSQL_VERSION_MINOR);
723 m_output->println("mysql_build: %d", NDB_MYSQL_VERSION_BUILD);
724 m_output->println("%s", "");
725 }
726
727 void
startBackup(Parser<MgmApiSession>::Context &,Properties const & args)728 MgmApiSession::startBackup(Parser<MgmApiSession>::Context &,
729 Properties const &args) {
730 DBUG_ENTER("MgmApiSession::startBackup");
731 unsigned backupId;
732 unsigned input_backupId= 0;
733 unsigned backuppoint= 0;
734 Uint32 completed= 2;
735 int result;
736
737 args.get("completed", &completed);
738
739 if(args.contains("backupid"))
740 args.get("backupid", &input_backupId);
741 if(args.contains("backuppoint"))
742 args.get("backuppoint", &backuppoint);
743
744 result = m_mgmsrv.startBackup(backupId, completed, input_backupId, backuppoint);
745
746 m_output->println("start backup reply");
747 if(result != 0)
748 {
749 m_output->println("result: %s", get_error_text(result));
750 }
751 else{
752 m_output->println("result: Ok");
753 if (completed)
754 m_output->println("id: %d", backupId);
755 }
756 m_output->println("%s", "");
757 DBUG_VOID_RETURN;
758 }
759
760 void
abortBackup(Parser<MgmApiSession>::Context &,Properties const & args)761 MgmApiSession::abortBackup(Parser<MgmApiSession>::Context &,
762 Properties const &args) {
763 Uint32 id = 0;
764
765 args.get("id", &id);
766
767 int result = m_mgmsrv.abortBackup(id);
768
769 m_output->println("abort backup reply");
770 if(result != 0)
771 m_output->println("result: %s", get_error_text(result));
772 else
773 m_output->println("result: Ok");
774 m_output->println("%s", "");
775 }
776
777 /*****************************************************************************/
778
779 void
dumpState(Parser<MgmApiSession>::Context &,Properties const & args)780 MgmApiSession::dumpState(Parser<MgmApiSession>::Context &,
781 Properties const &args) {
782 Uint32 node;
783 BaseString args_str;
784
785 args.get("node", &node);
786 args.get("args", args_str);
787
788 int result = m_mgmsrv.dumpState(node, args_str.c_str());
789 m_output->println("dump state reply");
790 if(result != 0)
791 m_output->println("result: %s", get_error_text(result));
792 else
793 m_output->println("result: Ok");
794 m_output->println("%s", "");
795 }
796
797
798 void
bye(Parser<MgmApiSession>::Context &,Properties const &)799 MgmApiSession::bye(Parser<MgmApiSession>::Context &,
800 Properties const &) {
801 m_stop = true;
802 }
803
804 void
endSession(Parser<MgmApiSession>::Context &,Properties const &)805 MgmApiSession::endSession(Parser<MgmApiSession>::Context &,
806 Properties const &) {
807 if(m_allocated_resources)
808 delete m_allocated_resources;
809
810 m_allocated_resources= new MgmtSrvr::Allocated_resources(m_mgmsrv);
811
812 SLEEP_ERROR_INSERTED(4);
813 m_output->println("end session reply");
814 }
815
816 void
getClusterLogLevel(Parser<MgmApiSession>::Context &,Properties const &)817 MgmApiSession::getClusterLogLevel(Parser<MgmApiSession>::Context & , Properties const &) {
818 const char* names[] = { "startup",
819 "shutdown",
820 "statistics",
821 "checkpoint",
822 "noderestart",
823 "connection",
824 "info",
825 "warning",
826 "error",
827 "congestion",
828 "debug",
829 "backup" };
830
831 int loglevel_count = (CFG_MAX_LOGLEVEL - CFG_MIN_LOGLEVEL + 1) ;
832 LogLevel::EventCategory category;
833
834 m_output->println("get cluster loglevel");
835 for(int i = 0; i < loglevel_count; i++) {
836 category = (LogLevel::EventCategory) i;
837 m_output->println("%s: %d", names[i], m_mgmsrv.m_event_listner[0].m_logLevel.getLogLevel(category));
838 }
839 m_output->println("%s", "");
840 }
841
842 void
setClusterLogLevel(Parser<MgmApiSession>::Context &,Properties const & args)843 MgmApiSession::setClusterLogLevel(Parser<MgmApiSession>::Context &,
844 Properties const &args) {
845 Uint32 node, level, cat;
846 BaseString errorString;
847 DBUG_ENTER("MgmApiSession::setClusterLogLevel");
848 args.get("node", &node);
849 args.get("category", &cat);
850 args.get("level", &level);
851
852 DBUG_PRINT("enter",("node=%d, category=%d, level=%d", node, cat, level));
853
854 m_output->println("set cluster loglevel reply");
855
856 if(level > NDB_MGM_MAX_LOGLEVEL) {
857 m_output->println("result: Invalid loglevel %d", level);
858 m_output->println("%s", "");
859 DBUG_VOID_RETURN;
860 }
861
862 LogLevel::EventCategory category=
863 (LogLevel::EventCategory)(cat-(int)CFG_MIN_LOGLEVEL);
864
865 m_mgmsrv.m_event_listner.lock();
866 if (m_mgmsrv.m_event_listner[0].m_logLevel.setLogLevel(category,level))
867 {
868 m_output->println("result: Invalid category %d", category);
869 m_output->println("%s", "");
870 m_mgmsrv.m_event_listner.unlock();
871 DBUG_VOID_RETURN;
872 }
873 m_mgmsrv.m_event_listner.unlock();
874
875 {
876 LogLevel tmp;
877 m_mgmsrv.m_event_listner.update_max_log_level(tmp);
878 }
879
880 m_output->println("result: Ok");
881 m_output->println("%s", "");
882 DBUG_VOID_RETURN;
883 }
884
885 void
setLogLevel(Parser<MgmApiSession>::Context &,Properties const & args)886 MgmApiSession::setLogLevel(Parser<MgmApiSession>::Context &,
887 Properties const &args) {
888 Uint32 node = 0, level = 0, cat;
889 BaseString errorString;
890 SetLogLevelOrd logLevel;
891 logLevel.clear();
892 args.get("node", &node);
893 args.get("category", &cat);
894 args.get("level", &level);
895
896 if(level > NDB_MGM_MAX_LOGLEVEL) {
897 m_output->println("set loglevel reply");
898 m_output->println("result: Invalid loglevel: %s", errorString.c_str());
899 m_output->println("%s", "");
900 return;
901 }
902
903 LogLevel::EventCategory category=
904 (LogLevel::EventCategory)(cat-(int)CFG_MIN_LOGLEVEL);
905
906 {
907 LogLevel ll;
908 ll.setLogLevel(category,level);
909 m_mgmsrv.m_event_listner.update_max_log_level(ll);
910 }
911
912 m_output->println("set loglevel reply");
913 m_output->println("result: Ok");
914 m_output->println("%s", "");
915 }
916
917 void
stopSignalLog(Parser<MgmApiSession>::Context &,Properties const & args)918 MgmApiSession::stopSignalLog(Parser<MgmApiSession>::Context &,
919 Properties const &args) {
920 Uint32 node;
921
922 args.get("node", &node);
923
924 int result = m_mgmsrv.stopSignalTracing(node);
925
926 m_output->println("stop signallog");
927 if(result != 0)
928 m_output->println("result: %s", get_error_text(result));
929 else
930 m_output->println("result: Ok");
931 m_output->println("%s", "");
932 }
933
934 void
restart_v1(Parser<MgmApiSession>::Context &,Properties const & args)935 MgmApiSession::restart_v1(Parser<MgmApiSession>::Context &,
936 Properties const &args) {
937 restart(args,1);
938 }
939
940 void
restart_v2(Parser<MgmApiSession>::Context &,Properties const & args)941 MgmApiSession::restart_v2(Parser<MgmApiSession>::Context &,
942 Properties const &args) {
943 restart(args,2);
944 }
945
946 void
restart(Properties const & args,int version)947 MgmApiSession::restart(Properties const &args, int version) {
948 Uint32
949 nostart = 0,
950 initialstart = 0,
951 abort = 0, force = 0;
952 char *nodes_str;
953 Vector<NodeId> nodes;
954
955 args.get("initialstart", &initialstart);
956 args.get("nostart", &nostart);
957 args.get("abort", &abort);
958 args.get("node", (const char **)&nodes_str);
959 args.get("force", &force);
960
961 char *p, *last;
962 for((p = strtok_r(nodes_str, " ", &last));
963 p;
964 (p = strtok_r(NULL, " ", &last))) {
965 nodes.push_back(atoi(p));
966 }
967
968 int restarted = 0;
969 int result= m_mgmsrv.restartNodes(nodes,
970 &restarted,
971 nostart != 0,
972 initialstart != 0,
973 abort != 0,
974 force != 0,
975 &m_stopSelf);
976
977 if (force &&
978 (result == NODE_SHUTDOWN_WOULD_CAUSE_SYSTEM_CRASH ||
979 result == UNSUPPORTED_NODE_SHUTDOWN))
980 {
981 // Force restart by restarting all nodes
982 result = m_mgmsrv.restartDB(nostart, initialstart, false, &restarted);
983 }
984
985 m_output->println("restart reply");
986 if(result != 0){
987 m_output->println("result: %d-%s", result, get_error_text(result));
988 } else
989 m_output->println("result: Ok");
990 m_output->println("restarted: %d", restarted);
991 if(version>1)
992 m_output->println("disconnect: %d", (m_stopSelf)?1:0);
993 m_output->println("%s", "");
994 }
995
996 void
restartAll(Parser<MgmApiSession>::Context &,Properties const & args)997 MgmApiSession::restartAll(Parser<MgmApiSession>::Context &,
998 Properties const &args)
999 {
1000 Uint32 nostart = 0;
1001 Uint32 initialstart = 0;
1002 Uint32 abort = 0;
1003
1004 args.get("initialstart", &initialstart);
1005 args.get("abort", &abort);
1006 args.get("nostart", &nostart);
1007
1008 int count = 0;
1009 int result = m_mgmsrv.restartDB(nostart, initialstart, abort, &count);
1010
1011 m_output->println("restart reply");
1012 if(result != 0)
1013 m_output->println("result: %s", get_error_text(result));
1014 else
1015 m_output->println("result: Ok");
1016 m_output->println("restarted: %d", count);
1017 m_output->println("%s", "");
1018 }
1019
1020 static void
printNodeStatus(OutputStream * output,MgmtSrvr & mgmsrv,enum ndb_mgm_node_type type)1021 printNodeStatus(OutputStream *output,
1022 MgmtSrvr &mgmsrv,
1023 enum ndb_mgm_node_type type) {
1024 NodeId nodeId = 0;
1025 while(mgmsrv.getNextNodeId(&nodeId, type)) {
1026 enum ndb_mgm_node_status status;
1027 Uint32 startPhase = 0,
1028 version = 0, mysql_version = 0,
1029 dynamicId = 0,
1030 nodeGroup = 0,
1031 connectCount = 0;
1032 bool system;
1033 const char *address= NULL;
1034 mgmsrv.status(nodeId, &status, &version, &mysql_version, &startPhase,
1035 &system, &dynamicId, &nodeGroup, &connectCount,
1036 &address);
1037 output->println("node.%d.type: %s",
1038 nodeId,
1039 ndb_mgm_get_node_type_string(type));
1040 output->println("node.%d.status: %s",
1041 nodeId,
1042 ndb_mgm_get_node_status_string(status));
1043 output->println("node.%d.version: %d", nodeId, version);
1044 output->println("node.%d.mysql_version: %d", nodeId, mysql_version);
1045 output->println("node.%d.startphase: %d", nodeId, startPhase);
1046 output->println("node.%d.dynamic_id: %d", nodeId, dynamicId);
1047 output->println("node.%d.node_group: %d", nodeId, nodeGroup);
1048 output->println("node.%d.connect_count: %d", nodeId, connectCount);
1049 output->println("node.%d.address: %s", nodeId, address ? address : "");
1050 }
1051 }
1052
1053 void
getStatus(Parser<MgmApiSession>::Context &,Properties const & args)1054 MgmApiSession::getStatus(Parser<MgmApiSession>::Context &,
1055 Properties const & args) {
1056 Uint32 i;
1057 int noOfNodes = 0;
1058 BaseString typestring;
1059
1060 enum ndb_mgm_node_type types[10];
1061 if (args.get("types", typestring))
1062 {
1063 Vector<BaseString> tmp;
1064 typestring.split(tmp, " ");
1065 for (i = 0; i < tmp.size(); i++)
1066 {
1067 types[i] = ndb_mgm_match_node_type(tmp[i].c_str());
1068 }
1069 types[i] = NDB_MGM_NODE_TYPE_UNKNOWN;
1070 }
1071 else
1072 {
1073 types[0] = NDB_MGM_NODE_TYPE_NDB;
1074 types[1] = NDB_MGM_NODE_TYPE_MGM;
1075 types[2] = NDB_MGM_NODE_TYPE_API;
1076 types[3] = NDB_MGM_NODE_TYPE_UNKNOWN;
1077 }
1078
1079 for (i = 0; types[i] != NDB_MGM_NODE_TYPE_UNKNOWN; i++)
1080 {
1081 NodeId nodeId = 0;
1082 while(m_mgmsrv.getNextNodeId(&nodeId, types[i]))
1083 noOfNodes++;
1084 }
1085
1086 SLEEP_ERROR_INSERTED(5);
1087 m_output->println("node status");
1088 SLEEP_ERROR_INSERTED(6);
1089 m_output->println("nodes: %d", noOfNodes);
1090 for (i = 0; types[i] != NDB_MGM_NODE_TYPE_UNKNOWN; i++)
1091 {
1092 SLEEP_ERROR_INSERTED(int(7+i));
1093 printNodeStatus(m_output, m_mgmsrv, types[i]);
1094 }
1095 m_output->println("%s", "");
1096 }
1097
1098
1099 static bool
isEventLogFilterEnabled(int severity)1100 isEventLogFilterEnabled(int severity)
1101 {
1102 return g_eventLogger->isEnable((Logger::LoggerLevel)severity);
1103 }
1104
1105 void
getInfoClusterLog(Parser<MgmApiSession>::Context &,Properties const &)1106 MgmApiSession::getInfoClusterLog(Parser<MgmApiSession>::Context &,
1107 Properties const &) {
1108 const char* names[] = { "enabled",
1109 "debug",
1110 "info",
1111 "warning",
1112 "error",
1113 "critical",
1114 "alert" };
1115
1116 m_output->println("clusterlog");
1117 for(int i = 0; i < 7; i++) {
1118 m_output->println("%s: %d",
1119 names[i],
1120 isEventLogFilterEnabled(i));
1121 }
1122 m_output->println("%s", "");
1123 }
1124
1125 void
stop_v1(Parser<MgmApiSession>::Context &,Properties const & args)1126 MgmApiSession::stop_v1(Parser<MgmApiSession>::Context &,
1127 Properties const &args) {
1128 stop(args,1);
1129 }
1130
1131 void
stop_v2(Parser<MgmApiSession>::Context &,Properties const & args)1132 MgmApiSession::stop_v2(Parser<MgmApiSession>::Context &,
1133 Properties const &args) {
1134 stop(args,2);
1135 }
1136
1137 void
stop(Properties const & args,int version)1138 MgmApiSession::stop(Properties const &args, int version) {
1139 Uint32 abort, force = 0;
1140 char *nodes_str;
1141 Vector<NodeId> nodes;
1142
1143 args.get("node", (const char **)&nodes_str);
1144 if(nodes_str == NULL)
1145 {
1146 m_output->println("stop reply");
1147 m_output->println("result: empty node list");
1148 m_output->println("%s", "");
1149 return;
1150 }
1151 args.get("abort", &abort);
1152 args.get("force", &force);
1153
1154 char *p, *last;
1155 for((p = strtok_r(nodes_str, " ", &last));
1156 p;
1157 (p = strtok_r(NULL, " ", &last))) {
1158 nodes.push_back(atoi(p));
1159 }
1160
1161 int stopped= 0;
1162 int result= 0;
1163 if (nodes.size())
1164 {
1165 result= m_mgmsrv.stopNodes(nodes, &stopped, abort != 0, force != 0,
1166 &m_stopSelf);
1167
1168 if (force &&
1169 (result == NODE_SHUTDOWN_WOULD_CAUSE_SYSTEM_CRASH ||
1170 result == UNSUPPORTED_NODE_SHUTDOWN))
1171 {
1172 // Force stop and shutdown all remaining nodes
1173 result = m_mgmsrv.shutdownDB(&stopped, false);
1174 }
1175 }
1176
1177 m_output->println("stop reply");
1178 if(result != 0)
1179 m_output->println("result: %s", get_error_text(result));
1180 else
1181 m_output->println("result: Ok");
1182 m_output->println("stopped: %d", stopped);
1183 if(version>1)
1184 m_output->println("disconnect: %d", (m_stopSelf)?1:0);
1185 m_output->println("%s", "");
1186 }
1187
1188 void
stopAll(Parser<MgmApiSession>::Context &,Properties const & args)1189 MgmApiSession::stopAll(Parser<MgmApiSession>::Context &,
1190 Properties const &args) {
1191 int stopped[2] = {0,0};
1192 Uint32 abort;
1193 args.get("abort", &abort);
1194
1195 BaseString stop;
1196 const char* tostop= "db";
1197 int ver=1;
1198 if (args.get("stop", stop))
1199 {
1200 tostop= stop.c_str();
1201 ver= 2;
1202 }
1203
1204 int result= 0;
1205 if(strstr(tostop,"db"))
1206 result= m_mgmsrv.shutdownDB(&stopped[0], abort != 0);
1207 if(!result && strstr(tostop,"mgm"))
1208 result= m_mgmsrv.shutdownMGM(&stopped[1], abort!=0, &m_stopSelf);
1209
1210 m_output->println("stop reply");
1211 if(result != 0)
1212 m_output->println("result: %s", get_error_text(result));
1213 else
1214 m_output->println("result: Ok");
1215 m_output->println("stopped: %d", stopped[0]+stopped[1]);
1216 if(ver >1)
1217 m_output->println("disconnect: %d", (m_stopSelf)?1:0);
1218 m_output->println("%s", "");
1219 }
1220
1221 void
enterSingleUser(Parser<MgmApiSession>::Context &,Properties const & args)1222 MgmApiSession::enterSingleUser(Parser<MgmApiSession>::Context &,
1223 Properties const &args) {
1224 int stopped = 0;
1225 Uint32 nodeId = 0;
1226 int result= 0;
1227 args.get("nodeId", &nodeId);
1228
1229 result = m_mgmsrv.enterSingleUser(&stopped, nodeId);
1230 m_output->println("enter single user reply");
1231 if(result != 0) {
1232 m_output->println("result: %s", get_error_text(result));
1233 }
1234 else {
1235 m_output->println("result: Ok");
1236 }
1237 m_output->println("%s", "");
1238 }
1239
1240 void
exitSingleUser(Parser<MgmApiSession>::Context &,Properties const & args)1241 MgmApiSession::exitSingleUser(Parser<MgmApiSession>::Context &,
1242 Properties const &args) {
1243 int stopped = 0;
1244 int result = m_mgmsrv.exitSingleUser(&stopped, false);
1245 m_output->println("exit single user reply");
1246 if(result != 0)
1247 m_output->println("result: %s", get_error_text(result));
1248 else
1249 m_output->println("result: Ok");
1250 m_output->println("%s", "");
1251 }
1252
1253
1254 void
startSignalLog(Parser<MgmApiSession>::Context &,Properties const & args)1255 MgmApiSession::startSignalLog(Parser<MgmApiSession>::Context &,
1256 Properties const &args) {
1257 Uint32 node;
1258
1259 args.get("node", &node);
1260
1261 int result = m_mgmsrv.startSignalTracing(node);
1262
1263 m_output->println("start signallog reply");
1264 if(result != 0)
1265 m_output->println("result: %s", get_error_text(result));
1266 else
1267 m_output->println("result: Ok");
1268 m_output->println("%s", "");
1269 }
1270
1271 void
logSignals(Parser<MgmApiSession>::Context &,Properties const & args)1272 MgmApiSession::logSignals(Parser<MgmApiSession>::Context &,
1273 Properties const &args) {
1274 Uint32 node = 0, in = 0, out = 0;
1275 // BaseString blocks;
1276 BaseString blockList;
1277 char * blockName;
1278 args.get("node", &node);
1279 args.get("in", &in);
1280 args.get("out", &out);
1281 args.get("blocks", blockList);
1282 // fast fix - pekka
1283 char buf[200];
1284 BaseString::snprintf(buf, 200, "%s", blockList.c_str());
1285 Vector<BaseString> blocks;
1286
1287 blockName=strtok(buf,"|");
1288 while( blockName != NULL)
1289 {
1290 blocks.push_back(blockName);
1291 blockName=strtok(NULL,"|");
1292 }
1293
1294
1295 if(in > 1 || out > 1)
1296 return; /* Invalid arguments */
1297
1298 const MgmtSrvr::LogMode modes[] = {
1299 MgmtSrvr::Off,
1300 MgmtSrvr::Out,
1301 MgmtSrvr::In,
1302 MgmtSrvr::InOut,
1303 };
1304 MgmtSrvr::LogMode mode = modes[in<<1 | out];
1305
1306 int result = m_mgmsrv.setSignalLoggingMode(node, mode, blocks);
1307
1308 m_output->println("log signals reply");
1309 if(result != 0)
1310 m_output->println("result: %s", get_error_text(result));
1311 else
1312 m_output->println("result: Ok");
1313 m_output->println("%s", "");
1314 }
1315
1316 void
start(Parser<MgmApiSession>::Context &,Properties const & args)1317 MgmApiSession::start(Parser<MgmApiSession>::Context &,
1318 Properties const &args) {
1319 Uint32 node;
1320
1321 args.get("node", &node);
1322
1323 int result = m_mgmsrv.start(node);
1324
1325 m_output->println("start reply");
1326 if(result != 0)
1327 m_output->println("result: %s", get_error_text(result));
1328 else
1329 m_output->println("result: Ok");
1330 m_output->println("%s", "");
1331 }
1332
1333 void
startAll(Parser<MgmApiSession>::Context &,Properties const &)1334 MgmApiSession::startAll(Parser<MgmApiSession>::Context &,
1335 Properties const &) {
1336 NodeId node = 0;
1337 int started = 0;
1338
1339 while(m_mgmsrv.getNextNodeId(&node, NDB_MGM_NODE_TYPE_NDB))
1340 if(m_mgmsrv.start(node) == 0)
1341 started++;
1342
1343 m_output->println("start reply");
1344 m_output->println("result: Ok");
1345 m_output->println("started: %d", started);
1346 m_output->println("%s", "");
1347 }
1348
1349
1350 static bool
setEventLogFilter(int severity,int enable)1351 setEventLogFilter(int severity, int enable)
1352 {
1353 Logger::LoggerLevel level = (Logger::LoggerLevel)severity;
1354 if (enable > 0) {
1355 g_eventLogger->enable(level);
1356 } else if (enable == 0) {
1357 g_eventLogger->disable(level);
1358 }
1359 else
1360 {
1361 /* enable is < 0 => toggle the filter value */
1362 if (g_eventLogger->isEnable(level))
1363 g_eventLogger->disable(level);
1364 else
1365 g_eventLogger->enable(level);
1366 }
1367 return g_eventLogger->isEnable(level);
1368 }
1369
1370
1371 void
setLogFilter(Parser_t::Context & ctx,const class Properties & args)1372 MgmApiSession::setLogFilter(Parser_t::Context &ctx,
1373 const class Properties &args) {
1374 Uint32 severity;
1375 Uint32 enable;
1376
1377 args.get("level", &severity);
1378 args.get("enable", &enable);
1379
1380 bool result = setEventLogFilter(severity, enable);
1381
1382 m_output->println("set logfilter reply");
1383 m_output->println("result: %d", result);
1384 m_output->println("%s", "");
1385 }
1386
1387 #ifdef NOT_USED
1388
1389 static NdbOut&
operator <<(NdbOut & out,const LogLevel & ll)1390 operator<<(NdbOut& out, const LogLevel & ll)
1391 {
1392 out << "[LogLevel: ";
1393 for(size_t i = 0; i<LogLevel::LOGLEVEL_CATEGORIES; i++)
1394 out << ll.getLogLevel((LogLevel::EventCategory)i) << " ";
1395 out << "]";
1396 return out;
1397 }
1398 #endif
1399
1400
1401 static void
logevent2str(BaseString & str,int eventType,const Uint32 * theData,Uint32 len,NodeId nodeId,Uint32 timeval,char * pretty_text,size_t pretty_text_size)1402 logevent2str(BaseString& str, int eventType,
1403 const Uint32* theData,
1404 Uint32 len,
1405 NodeId nodeId, Uint32 timeval,
1406 char* pretty_text, size_t pretty_text_size)
1407 {
1408 str.assign("log event reply\n");
1409 str.appfmt("type=%d\n", eventType);
1410 str.appfmt("time=%d\n", timeval);
1411 str.appfmt("source_nodeid=%d\n", nodeId);
1412 unsigned i;
1413 for (i = 0; ndb_logevent_body[i].token; i++)
1414 {
1415 if ( ndb_logevent_body[i].type == eventType)
1416 break;
1417 }
1418
1419 if (ndb_logevent_body[i].token)
1420 {
1421 do {
1422 int val= theData[ndb_logevent_body[i].index];
1423 if (ndb_logevent_body[i].index_fn)
1424 val= (*(ndb_logevent_body[i].index_fn))(val);
1425 str.appfmt("%s=%d\n",ndb_logevent_body[i].token, val);
1426 if(strcmp(ndb_logevent_body[i].token,"error") == 0)
1427 {
1428 int pretty_text_len= strlen(pretty_text);
1429 if(pretty_text_size-pretty_text_len-3 > 0)
1430 {
1431 BaseString::snprintf(pretty_text+pretty_text_len, 4 , " - ");
1432 ndb_error_string(val, pretty_text+(pretty_text_len+3),
1433 pretty_text_size-pretty_text_len-3);
1434 }
1435 }
1436 } while (ndb_logevent_body[++i].type == eventType);
1437 }
1438 else
1439 {
1440 str.append("data=");
1441 for (i = 1; i<len; i++)
1442 str.appfmt("%u ", theData[i]);
1443 str.append("\n");
1444 }
1445 }
1446
1447
1448 void
log(int eventType,const Uint32 * theData,Uint32 len,NodeId nodeId)1449 Ndb_mgmd_event_service::log(int eventType, const Uint32* theData,
1450 Uint32 len, NodeId nodeId){
1451
1452 Uint32 threshold;
1453 LogLevel::EventCategory cat;
1454 Logger::LoggerLevel severity;
1455 EventLoggerBase::EventTextFunction textF;
1456 int i, n;
1457 DBUG_ENTER("Ndb_mgmd_event_service::log");
1458 DBUG_PRINT("enter",("eventType=%d, nodeid=%d", eventType, nodeId));
1459
1460 if (EventLoggerBase::event_lookup(eventType,cat,threshold,severity,textF))
1461 DBUG_VOID_RETURN;
1462
1463 // Generate the message for pretty format clients
1464 char pretty_text[512];
1465 EventLogger::getText(pretty_text, sizeof(pretty_text),
1466 textF, theData, len, nodeId);
1467
1468 // Generate the message for parseable format clients
1469 // and if there is a field named "error" append the ndb_error_string
1470 // for that error number to the end of the pretty format message
1471 BaseString str;
1472 logevent2str(str, eventType, theData, len, nodeId, 0,
1473 pretty_text, sizeof(pretty_text));
1474
1475 Vector<NDB_SOCKET_TYPE> copy;
1476 m_clients.lock();
1477 for(i = m_clients.size() - 1; i >= 0; i--)
1478 {
1479 if(threshold <= m_clients[i].m_logLevel.getLogLevel(cat))
1480 {
1481 if(!my_socket_valid(m_clients[i].m_socket))
1482 continue;
1483
1484 SocketOutputStream out(m_clients[i].m_socket);
1485
1486 int r;
1487 if (m_clients[i].m_parsable)
1488 r= out.println(str.c_str());
1489 else
1490 r= out.println(pretty_text);
1491
1492 if (r<0)
1493 {
1494 copy.push_back(m_clients[i].m_socket);
1495 m_clients.erase(i, false);
1496 }
1497 }
1498 }
1499 m_clients.unlock();
1500
1501 if ((n= (int)copy.size()))
1502 {
1503 for(i= 0; i < n; i++)
1504 NDB_CLOSE_SOCKET(copy[i]);
1505
1506 LogLevel tmp; tmp.clear();
1507 m_clients.lock();
1508 for(i= m_clients.size() - 1; i >= 0; i--)
1509 tmp.set_max(m_clients[i].m_logLevel);
1510 m_clients.unlock();
1511 update_log_level(tmp);
1512 }
1513 DBUG_VOID_RETURN;
1514 }
1515
1516 void
update_max_log_level(const LogLevel & log_level)1517 Ndb_mgmd_event_service::update_max_log_level(const LogLevel &log_level)
1518 {
1519 LogLevel tmp = log_level;
1520 m_clients.lock();
1521 for(int i = m_clients.size() - 1; i >= 0; i--)
1522 tmp.set_max(m_clients[i].m_logLevel);
1523 m_clients.unlock();
1524 update_log_level(tmp);
1525 }
1526
1527 void
update_log_level(const LogLevel & tmp)1528 Ndb_mgmd_event_service::update_log_level(const LogLevel &tmp)
1529 {
1530 m_logLevel = tmp;
1531 EventSubscribeReq req;
1532 req.assign(tmp);
1533 // send update to all nodes
1534 req.blockRef = 0;
1535 m_mgmsrv->m_log_level_requests.push_back(req);
1536 }
1537
1538 void
check_listeners()1539 Ndb_mgmd_event_service::check_listeners()
1540 {
1541 int i, n= 0;
1542 DBUG_ENTER("Ndb_mgmd_event_service::check_listeners");
1543 m_clients.lock();
1544 for(i= m_clients.size() - 1; i >= 0; i--)
1545 {
1546 if(!my_socket_valid(m_clients[i].m_socket))
1547 continue;
1548
1549 SocketOutputStream out(m_clients[i].m_socket);
1550
1551 DBUG_PRINT("info",("%d " MY_SOCKET_FORMAT,
1552 i,
1553 MY_SOCKET_FORMAT_VALUE(m_clients[i].m_socket)));
1554
1555 if(out.println("<PING>") < 0)
1556 {
1557 NDB_CLOSE_SOCKET(m_clients[i].m_socket);
1558 m_clients.erase(i, false);
1559 n=1;
1560 }
1561 }
1562 if (n)
1563 {
1564 LogLevel tmp; tmp.clear();
1565 for(i= m_clients.size() - 1; i >= 0; i--)
1566 tmp.set_max(m_clients[i].m_logLevel);
1567 update_log_level(tmp);
1568 }
1569 m_clients.unlock();
1570 DBUG_VOID_RETURN;
1571 }
1572
1573 void
add_listener(const Event_listener & client)1574 Ndb_mgmd_event_service::add_listener(const Event_listener& client)
1575 {
1576 DBUG_ENTER("Ndb_mgmd_event_service::add_listener");
1577 DBUG_PRINT("enter",("client.m_socket: " MY_SOCKET_FORMAT,
1578 MY_SOCKET_FORMAT_VALUE(client.m_socket)));
1579
1580 check_listeners();
1581
1582 m_clients.push_back(client);
1583 update_max_log_level(client.m_logLevel);
1584
1585 DBUG_VOID_RETURN;
1586 }
1587
1588 void
stop_sessions()1589 Ndb_mgmd_event_service::stop_sessions(){
1590 m_clients.lock();
1591 for(int i = m_clients.size() - 1; i >= 0; i--){
1592 if(my_socket_valid(m_clients[i].m_socket))
1593 {
1594 NDB_CLOSE_SOCKET(m_clients[i].m_socket);
1595 m_clients.erase(i);
1596 }
1597 }
1598 m_clients.unlock();
1599 }
1600
1601 void
setParameter(Parser_t::Context &,Properties const & args)1602 MgmApiSession::setParameter(Parser_t::Context &,
1603 Properties const &args)
1604 {
1605 Uint32 node, param;
1606 BaseString value;
1607 args.get("node", &node);
1608 args.get("parameter", ¶m);
1609 args.get("value", value);
1610
1611 BaseString result;
1612 int ret = m_mgmsrv.setDbParameter(node,
1613 param,
1614 value.c_str(),
1615 result);
1616
1617 m_output->println("set parameter reply");
1618 m_output->println("message: %s", result.c_str());
1619 m_output->println("result: %d", ret);
1620 m_output->println("%s", "");
1621 }
1622
1623 void
setConnectionParameter(Parser_t::Context & ctx,Properties const & args)1624 MgmApiSession::setConnectionParameter(Parser_t::Context &ctx,
1625 Properties const &args)
1626 {
1627 Uint32 node1, node2, param, value;
1628 args.get("node1", &node1);
1629 args.get("node2", &node2);
1630 args.get("param", ¶m);
1631 args.get("value", &value);
1632
1633 BaseString result;
1634 int ret = m_mgmsrv.setConnectionDbParameter(node1,
1635 node2,
1636 param,
1637 value,
1638 result);
1639
1640 m_output->println("set connection parameter reply");
1641 m_output->println("message: %s", result.c_str());
1642 m_output->println("result: %s", (ret>0)?"Ok":"Failed");
1643 m_output->println("%s", "");
1644 }
1645
1646 void
getConnectionParameter(Parser_t::Context & ctx,Properties const & args)1647 MgmApiSession::getConnectionParameter(Parser_t::Context &ctx,
1648 Properties const &args)
1649 {
1650 Uint32 node1, node2, param;
1651 int value = 0;
1652
1653 args.get("node1", &node1);
1654 args.get("node2", &node2);
1655 args.get("param", ¶m);
1656
1657 BaseString result;
1658 int ret = m_mgmsrv.getConnectionDbParameter(node1,
1659 node2,
1660 param,
1661 &value,
1662 result);
1663
1664 m_output->println("get connection parameter reply");
1665 m_output->println("value: %d", value);
1666 m_output->println("result: %s", (ret>0)?"Ok":result.c_str());
1667 m_output->println("%s", "");
1668 }
1669
1670 void
listen_event(Parser<MgmApiSession>::Context & ctx,Properties const & args)1671 MgmApiSession::listen_event(Parser<MgmApiSession>::Context & ctx,
1672 Properties const & args) {
1673 Uint32 parsable= 0;
1674 BaseString node, param, value;
1675 args.get("node", node);
1676 args.get("filter", param);
1677 args.get("parsable", &parsable);
1678
1679 int result = 0;
1680 BaseString msg;
1681
1682 Ndb_mgmd_event_service::Event_listener le;
1683 le.m_parsable = parsable;
1684 le.m_socket = m_socket;
1685
1686 Vector<BaseString> list;
1687 param.trim();
1688 param.split(list, " ,");
1689 for(size_t i = 0; i<list.size(); i++){
1690 Vector<BaseString> spec;
1691 list[i].trim();
1692 list[i].split(spec, "=:");
1693 if(spec.size() != 2){
1694 msg.appfmt("Invalid filter specification: >%s< >%s< %d",
1695 param.c_str(), list[i].c_str(), spec.size());
1696 result = -1;
1697 goto done;
1698 }
1699
1700 spec[0].trim().ndb_toupper();
1701 int category = ndb_mgm_match_event_category(spec[0].c_str());
1702 if(category == NDB_MGM_ILLEGAL_EVENT_CATEGORY){
1703 category = atoi(spec[0].c_str());
1704 if(category < NDB_MGM_MIN_EVENT_CATEGORY ||
1705 category > NDB_MGM_MAX_EVENT_CATEGORY){
1706 msg.appfmt("Unknown category: >%s<", spec[0].c_str());
1707 result = -1;
1708 goto done;
1709 }
1710 }
1711
1712 int level = atoi(spec[1].c_str());
1713 if(level < 0 || level > NDB_MGM_MAX_LOGLEVEL){
1714 msg.appfmt("Invalid level: >%s<", spec[1].c_str());
1715 result = -1;
1716 goto done;
1717 }
1718 category -= CFG_MIN_LOGLEVEL;
1719 le.m_logLevel.setLogLevel((LogLevel::EventCategory)category, level);
1720 }
1721
1722 if(list.size() == 0){
1723 msg.appfmt("Empty filter specification");
1724 result = -1;
1725 goto done;
1726 }
1727
1728 done:
1729 m_output->println("listen event");
1730 m_output->println("result: %d", result);
1731 if(result != 0)
1732 m_output->println("msg: %s", msg.c_str());
1733 m_output->println("%s", "");
1734
1735 if(result==0)
1736 {
1737 m_mgmsrv.m_event_listner.add_listener(le);
1738 m_stop = true;
1739 my_socket_invalidate(&m_socket);
1740 }
1741 }
1742
1743 void
stop_session_if_not_connected(SocketServer::Session * _s,void * data)1744 MgmApiSession::stop_session_if_not_connected(SocketServer::Session *_s, void *data)
1745 {
1746 MgmApiSession *s= (MgmApiSession *)_s;
1747 struct PurgeStruct &ps= *(struct PurgeStruct *)data;
1748 if (s->m_allocated_resources->is_reserved(ps.free_nodes))
1749 {
1750 if (ps.str)
1751 ps.str->appfmt(" %d", s->m_allocated_resources->get_nodeid());
1752 s->stopSession();
1753 }
1754 }
1755
1756 void
stop_session_if_timed_out(SocketServer::Session * _s,void * data)1757 MgmApiSession::stop_session_if_timed_out(SocketServer::Session *_s, void *data)
1758 {
1759 MgmApiSession *s= (MgmApiSession *)_s;
1760 struct PurgeStruct &ps= *(struct PurgeStruct *)data;
1761 if (s->m_allocated_resources->is_reserved(ps.free_nodes) &&
1762 s->m_allocated_resources->is_timed_out(ps.tick))
1763 {
1764 s->stopSession();
1765 }
1766 }
1767
1768 void
purge_stale_sessions(Parser_t::Context & ctx,const class Properties & args)1769 MgmApiSession::purge_stale_sessions(Parser_t::Context &ctx,
1770 const class Properties &args)
1771 {
1772 struct PurgeStruct ps;
1773 BaseString str;
1774 ps.str = &str;
1775
1776 m_mgmsrv.get_connected_nodes(ps.free_nodes);
1777 ps.free_nodes.bitXORC(NodeBitmask()); // invert connected_nodes to get free nodes
1778
1779 m_mgmsrv.get_socket_server()->foreachSession(stop_session_if_not_connected,&ps);
1780 m_mgmsrv.get_socket_server()->checkSessions();
1781
1782 m_output->println("purge stale sessions reply");
1783 if (str.length() > 0)
1784 m_output->println("purged:%s",str.c_str());
1785 m_output->println("result: Ok");
1786 m_output->println("%s", "");
1787 }
1788
1789 void
check_connection(Parser_t::Context & ctx,const class Properties & args)1790 MgmApiSession::check_connection(Parser_t::Context &ctx,
1791 const class Properties &args)
1792 {
1793 SLEEP_ERROR_INSERTED(1);
1794 m_output->println("check connection reply");
1795 SLEEP_ERROR_INSERTED(2);
1796 m_output->println("result: Ok");
1797 SLEEP_ERROR_INSERTED(3);
1798 m_output->println("%s", "");
1799 }
1800
1801 void
transporter_connect(Parser_t::Context & ctx,Properties const & args)1802 MgmApiSession::transporter_connect(Parser_t::Context &ctx,
1803 Properties const &args)
1804 {
1805 BaseString errormsg;
1806 if (!m_mgmsrv.transporter_connect(m_socket, errormsg))
1807 {
1808 // Connection not allowed or failed
1809 g_eventLogger->warning("Failed to convert connection "
1810 "from '%s' to transporter: %s",
1811 name(),
1812 errormsg.c_str());
1813 // Close the socket to indicate failure to other side
1814 }
1815 else
1816 {
1817 /*
1818 Conversion to transporter suceeded
1819 Stop this session thread and release resources
1820 but don't close the socket, it's been taken over
1821 by the transporter
1822 */
1823 my_socket_invalidate(&m_socket); // so nobody closes it
1824 }
1825
1826 m_stop= true; // Stop the session
1827 }
1828
1829 void
get_mgmd_nodeid(Parser_t::Context & ctx,Properties const & args)1830 MgmApiSession::get_mgmd_nodeid(Parser_t::Context &ctx,
1831 Properties const &args)
1832 {
1833 m_output->println("get mgmd nodeid reply");
1834 m_output->println("nodeid:%u",m_mgmsrv.getOwnNodeId());
1835 SLEEP_ERROR_INSERTED(1);
1836
1837 m_output->println("%s", "");
1838 }
1839
1840 void
report_event(Parser_t::Context & ctx,Properties const & args)1841 MgmApiSession::report_event(Parser_t::Context &ctx,
1842 Properties const &args)
1843 {
1844 Uint32 length;
1845 const char *data_string;
1846 Uint32 data[25];
1847
1848 args.get("length", &length);
1849 args.get("data", &data_string);
1850
1851 BaseString tmp(data_string);
1852 Vector<BaseString> item;
1853 tmp.split(item, " ");
1854 for (int i = 0; (Uint32) i < length ; i++)
1855 {
1856 sscanf(item[i].c_str(), "%u", data+i);
1857 }
1858
1859 m_mgmsrv.eventReport(data, length);
1860 m_output->println("report event reply");
1861 m_output->println("result: ok");
1862 m_output->println("%s", "");
1863 }
1864
1865 void
create_nodegroup(Parser_t::Context & ctx,Properties const & args)1866 MgmApiSession::create_nodegroup(Parser_t::Context &ctx,
1867 Properties const &args)
1868 {
1869 int res = 0;
1870 BaseString nodestr;
1871 BaseString retval;
1872 int ng = -1;
1873 Vector<int> nodes;
1874 BaseString result("Ok");
1875
1876 args.get("nodes", nodestr);
1877 Vector<BaseString> list;
1878 nodestr.split(list, " ");
1879 for (Uint32 i = 0; i < list.size() ; i++)
1880 {
1881 int res;
1882 int node;
1883 if ((res = sscanf(list[i].c_str(), "%u", &node)) != 1)
1884 {
1885 nodes.clear();
1886 result = "FAIL: Invalid format for nodes";
1887 break;
1888 }
1889 nodes.push_back(node);
1890 }
1891
1892 res = m_mgmsrv.createNodegroup(nodes.getBase(), nodes.size(), &ng);
1893
1894 m_output->println("create nodegroup reply");
1895 m_output->println("ng: %d", ng);
1896 if (res)
1897 {
1898 m_output->println("error_code: %d", res);
1899 m_output->println("result: %d-%s", res, get_error_text(res));
1900 }
1901 else
1902 {
1903 m_output->println("result: Ok");
1904 }
1905 m_output->println("%s", "");
1906 }
1907
1908 void
drop_nodegroup(Parser_t::Context & ctx,Properties const & args)1909 MgmApiSession::drop_nodegroup(Parser_t::Context &ctx,
1910 Properties const &args)
1911 {
1912 BaseString result("Ok");
1913
1914 unsigned ng;
1915 args.get("ng", &ng);
1916
1917 int res;
1918 if((res = m_mgmsrv.dropNodegroup(ng)) != 0)
1919 {
1920 result.assfmt("error: %d", res);
1921 }
1922
1923 //end:
1924 m_output->println("drop nodegroup reply");
1925 m_output->println("result: %s", result.c_str());
1926 m_output->println("%s", "");
1927 }
1928
1929 void
list_session(SocketServer::Session * _s,void * data)1930 MgmApiSession::list_session(SocketServer::Session *_s, void *data)
1931 {
1932 MgmApiSession *s= (MgmApiSession *)_s;
1933 MgmApiSession *lister= (MgmApiSession*) data;
1934
1935 if(s!=lister)
1936 NdbMutex_Lock(s->m_mutex);
1937
1938 Uint64 id= s->m_session_id;
1939 lister->m_output->println("session: %llu",id);
1940 lister->m_output->println("session.%llu.m_stopSelf: %d",id,s->m_stopSelf);
1941 lister->m_output->println("session.%llu.m_stop: %d",id,s->m_stop);
1942 lister->m_output->println("session.%llu.allocated.nodeid: %d",id,s->m_allocated_resources->get_nodeid());
1943 if(s->m_ctx)
1944 {
1945 int l= strlen(s->m_ctx->m_tokenBuffer);
1946 char *buf= (char*) malloc(2*l+1);
1947 char *b= buf;
1948 for(int i=0; i<l;i++)
1949 if(s->m_ctx->m_tokenBuffer[i]=='\n')
1950 {
1951 *b++='\\';
1952 *b++='n';
1953 }
1954 else
1955 {
1956 *b++= s->m_ctx->m_tokenBuffer[i];
1957 }
1958 *b= '\0';
1959
1960 lister->m_output->println("session.%llu.parser.buffer.len: %u",id,l);
1961 lister->m_output->println("session.%llu.parser.buffer: %s",id,buf);
1962 lister->m_output->println("session.%llu.parser.status: %d",id,s->m_ctx->m_status);
1963
1964 free(buf);
1965 }
1966
1967 if(s!=lister)
1968 NdbMutex_Unlock(s->m_mutex);
1969 }
1970
1971 void
listSessions(Parser_t::Context & ctx,Properties const & args)1972 MgmApiSession::listSessions(Parser_t::Context &ctx,
1973 Properties const &args) {
1974 m_mgmsrv.get_socket_server()->foreachSession(list_session,(void*)this);
1975
1976 m_output->println("%s", "");
1977 }
1978
1979 void
getSessionId(Parser_t::Context & ctx,Properties const & args)1980 MgmApiSession::getSessionId(Parser_t::Context &ctx,
1981 Properties const &args) {
1982 m_output->println("get session id reply");
1983 m_output->println("id: %llu",m_session_id);
1984 m_output->println("%s", "");
1985 }
1986
1987 struct get_session_param {
1988 MgmApiSession *l;
1989 Uint64 id;
1990 int found;
1991 };
1992
1993 void
get_session(SocketServer::Session * _s,void * data)1994 MgmApiSession::get_session(SocketServer::Session *_s, void *data)
1995 {
1996 struct get_session_param *p= (struct get_session_param*)data;
1997 MgmApiSession *s= (MgmApiSession *)_s;
1998
1999 if(s!=p->l)
2000 NdbMutex_Lock(s->m_mutex);
2001
2002 if(p->id != s->m_session_id)
2003 {
2004 if(s!=p->l)
2005 NdbMutex_Unlock(s->m_mutex);
2006 return;
2007 }
2008
2009 p->found= true;
2010 p->l->m_output->println("id: %llu",s->m_session_id);
2011 p->l->m_output->println("m_stopSelf: %d",s->m_stopSelf);
2012 p->l->m_output->println("m_stop: %d",s->m_stop);
2013 p->l->m_output->println("nodeid: %d",s->m_allocated_resources->get_nodeid());
2014 if(s->m_ctx)
2015 {
2016 int l= strlen(s->m_ctx->m_tokenBuffer);
2017 p->l->m_output->println("parser_buffer_len: %u",l);
2018 p->l->m_output->println("parser_status: %d",s->m_ctx->m_status);
2019 }
2020
2021 if(s!=p->l)
2022 NdbMutex_Unlock(s->m_mutex);
2023 }
2024
2025 void
getSession(Parser_t::Context & ctx,Properties const & args)2026 MgmApiSession::getSession(Parser_t::Context &ctx,
2027 Properties const &args) {
2028 Uint64 id;
2029 struct get_session_param p;
2030
2031 args.get("id", &id);
2032
2033 p.l= this;
2034 p.id= id;
2035 p.found= false;
2036
2037 m_output->println("get session reply");
2038 m_mgmsrv.get_socket_server()->foreachSession(get_session,(void*)&p);
2039
2040 if(p.found==false)
2041 m_output->println("id: 0");
2042
2043 m_output->println("%s", "");
2044 }
2045
2046
2047 static bool
clear_dynamic_ports_from_config(Config * config)2048 clear_dynamic_ports_from_config(Config* config)
2049 {
2050 ConfigIter iter(config, CFG_SECTION_CONNECTION);
2051
2052 for(;iter.valid();iter.next()) {
2053 Uint32 n1, n2;
2054 if (iter.get(CFG_CONNECTION_NODE_1, &n1) != 0 &&
2055 iter.get(CFG_CONNECTION_NODE_2, &n2) != 0)
2056 return false;
2057
2058 Uint32 port_value;
2059 if (iter.get(CFG_CONNECTION_SERVER_PORT, &port_value) != 0)
2060 return false;
2061
2062 int port = (int)port_value;
2063 if (port < 0)
2064 {
2065 // Found a dynamic port with value in config, clear it by updating
2066 // the already existing value
2067 Uint32 zero_port = 0;
2068 ConfigValues::Iterator i2(config->m_configValues->m_config,
2069 iter.m_config);
2070 if (!i2.set(CFG_CONNECTION_SERVER_PORT, zero_port))
2071 return false;
2072 }
2073 }
2074 return true;
2075 }
2076
2077
setConfig(Parser_t::Context & ctx,Properties const & args)2078 void MgmApiSession::setConfig(Parser_t::Context &ctx, Properties const &args)
2079 {
2080 BaseString result("Ok");
2081 Uint32 len64 = 0;
2082
2083 {
2084 const char* buf;
2085 args.get("Content-Type", &buf);
2086 if(strcmp(buf, "ndbconfig/octet-stream")) {
2087 result.assfmt("Unhandled content type '%s'", buf);
2088 goto done;
2089 }
2090
2091 args.get("Content-Transfer-Encoding", &buf);
2092 if(strcmp(buf, "base64")) {
2093 result.assfmt("Unhandled content encoding '%s'", buf);
2094 goto done;
2095 }
2096 }
2097
2098 args.get("Content-Length", &len64);
2099 if(len64 ==0 || len64 > (1024*1024)) {
2100 result.assfmt("Illegal config length size %d", len64);
2101 goto done;
2102 }
2103 len64 += 1; // Trailing \n
2104
2105 {
2106 char* buf64 = new char[len64];
2107 int r = 0;
2108 size_t start = 0;
2109 do {
2110 if((r= read_socket(m_socket,
2111 SOCKET_TIMEOUT,
2112 &buf64[start],
2113 len64-start)) < 1)
2114 {
2115 delete[] buf64;
2116 result.assfmt("read_socket failed, errno: %d", errno);
2117 goto done;
2118 }
2119 start += r;
2120 } while(start < len64);
2121
2122 char* decoded = new char[base64_needed_decoded_length((size_t)len64 - 1)];
2123 int decoded_len= ndb_base64_decode(buf64, len64-1, decoded, NULL);
2124 delete[] buf64;
2125
2126 ConfigValuesFactory cvf;
2127 if(!cvf.unpack(decoded, decoded_len))
2128 {
2129 delete[] decoded;
2130 result.assfmt("Failed to unpack config");
2131 goto done;
2132 }
2133 delete[] decoded;
2134
2135 Config new_config(cvf.getConfigValues());
2136
2137 // Remove any dynamic ports from the new config
2138 if (!clear_dynamic_ports_from_config(&new_config))
2139 {
2140 result.assfmt("INTERNAL ERROR: Failed to clear dynamic "
2141 "ports from config");
2142 goto done;
2143 }
2144
2145 (void)m_mgmsrv.change_config(new_config, result);
2146 }
2147
2148 done:
2149
2150 m_output->println("set config reply");
2151 m_output->println("result: %s", result.c_str());
2152 m_output->println("%s", "");
2153 }
2154
2155
showConfig(Parser_t::Context & ctx,Properties const & args)2156 void MgmApiSession::showConfig(Parser_t::Context &ctx, Properties const &args)
2157 {
2158 const char* section = NULL;
2159 const char* name = NULL;
2160 Uint32 nodeid = 0;
2161
2162 args.get("Section", §ion);
2163 args.get("NodeId", &nodeid);
2164 args.get("Name", &name);
2165
2166 NdbOut socket_out(*m_output, false /* turn off autoflush */);
2167 m_output->println("show config reply");
2168 m_mgmsrv.print_config(section, nodeid, name,
2169 socket_out);
2170 m_output->println("%s", "");
2171 }
2172
2173
2174 void
reloadConfig(Parser_t::Context &,const class Properties & args)2175 MgmApiSession::reloadConfig(Parser_t::Context &,
2176 const class Properties &args)
2177 {
2178 const char* config_filename= NULL;
2179 Uint32 mycnf = 0;
2180
2181 args.get("config_filename", &config_filename);
2182 args.get("mycnf", &mycnf);
2183
2184 g_eventLogger->debug("config_filename: %s, mycnf: %s",
2185 str_null(config_filename),
2186 yes_no(mycnf));
2187
2188 m_output->println("reload config reply");
2189
2190 BaseString msg;
2191 if (!m_mgmsrv.reload_config(config_filename, (mycnf != 0), msg))
2192 m_output->println("result: %s", msg.c_str());
2193 else
2194 m_output->println("result: Ok");
2195
2196 m_output->println("%s", "");
2197 }
2198
2199
2200 void
show_variables(Parser_t::Context &,const class Properties & args)2201 MgmApiSession::show_variables(Parser_t::Context &,
2202 const class Properties &args)
2203 {
2204 m_output->println("show variables reply");
2205 NdbOut socket_out(*m_output, false /* turn off autoflush */);
2206 m_mgmsrv.show_variables(socket_out);
2207 m_output->println("%s", "");
2208 }
2209
2210
2211 static bool
valid_nodes(const NdbNodeBitmask & nodes,unsigned max_nodeid)2212 valid_nodes(const NdbNodeBitmask& nodes, unsigned max_nodeid)
2213 {
2214 unsigned nodeid = 0;
2215 while((nodeid = nodes.find(nodeid)) != NdbNodeBitmask::NotFound)
2216 {
2217 if (nodeid == 0 || nodeid > max_nodeid)
2218 return false;
2219 nodeid++;
2220 }
2221 return true;
2222 }
2223
2224
2225 #include <signaldata/DumpStateOrd.hpp>
2226 #include "../common/util/parse_mask.hpp"
2227
2228 static const
2229 struct dump_request {
2230 Ndb_logevent_type type;
2231 DumpStateOrd::DumpStateType dump_type;
2232 // Number of reports to wait for from each node
2233 Uint32 reports_per_node;
2234 } dump_requests [] =
2235 {
2236 { NDB_LE_BackupStatus,
2237 DumpStateOrd::BackupStatus,
2238 1 },
2239
2240 { NDB_LE_MemoryUsage,
2241 DumpStateOrd::DumpPageMemory,
2242 2},
2243
2244 { NDB_LE_SavedEvent,
2245 DumpStateOrd::DumpEventLog,
2246 0},
2247
2248 { NDB_LE_ILLEGAL_TYPE, (DumpStateOrd::DumpStateType)0, 0 }
2249 };
2250
2251 void
dump_events(Parser_t::Context &,const class Properties & args)2252 MgmApiSession::dump_events(Parser_t::Context &,
2253 const class Properties &args)
2254 {
2255 m_output->println("dump events reply");
2256
2257 // Check "type" argument
2258 Uint32 type;
2259 args.get("type", &type);
2260
2261 const dump_request* request = dump_requests;
2262
2263 for (; request->type != NDB_LE_ILLEGAL_TYPE; request++)
2264 {
2265 if (request->type == (Ndb_logevent_type)type)
2266 break;
2267 }
2268
2269 if (request->type == NDB_LE_ILLEGAL_TYPE)
2270 {
2271 m_output->println("result: ndb_logevent_type %u not supported", type);
2272 m_output->println("%s", "");
2273 return;
2274 }
2275
2276 // Check "nodes" argument
2277 NdbNodeBitmask nodes;
2278 const char* nodes_str = NULL;
2279 args.get("nodes", &nodes_str);
2280 if (nodes_str)
2281 {
2282 int res = parse_mask(nodes_str, nodes);
2283 if (res < 0 || !valid_nodes(nodes, MAX_NDB_NODES-1))
2284 {
2285 m_output->println("result: invalid nodes: '%s'", nodes_str);
2286 m_output->println("%s", "");
2287 return;
2288 }
2289 }
2290
2291 // Request the events
2292 Vector<SimpleSignal> events;
2293 if (!m_mgmsrv.request_events(nodes,
2294 request->reports_per_node,
2295 request->dump_type,
2296 events))
2297 {
2298 m_output->println("result: failed to dump events");
2299 m_output->println("%s", "");
2300 return;
2301 }
2302
2303 // Return result
2304 m_output->println("result: Ok");
2305 m_output->println("events: %u", events.size());
2306 m_output->println("%s", ""); // Empty line between header and first event
2307 for (unsigned i = 0; i < events.size(); i++)
2308 {
2309 const EventReport * const event =
2310 (const EventReport*)events[i].getDataPtrSend();
2311 const NodeId nodeid = refToNode(events[i].header.theSendersBlockRef);
2312
2313 // Check correct EVENT_REP type returned
2314 assert(event->getEventType() == request->type);
2315
2316 BaseString str;
2317 char pretty_text[512];
2318 Uint32 tmpData[256];
2319 const Uint32 * dataPtr = events[i].getDataPtr();
2320 Uint32 dataLen = events[i].getLength();
2321 if (events[i].header.m_noOfSections == 1)
2322 {
2323 if (dataLen + events[i].ptr[0].sz > NDB_ARRAY_SIZE(tmpData))
2324 {
2325 events[i].ptr[0].sz = NDB_ARRAY_SIZE(tmpData) - dataLen;
2326 }
2327 memcpy(tmpData, dataPtr, 4 * dataLen);
2328 memcpy(tmpData + dataLen, events[i].ptr[0].p, 4*events[i].ptr[0].sz);
2329 dataPtr = tmpData;
2330 dataLen += events[i].ptr[0].sz;
2331 }
2332 logevent2str(str,
2333 event->getEventType(),
2334 dataPtr,
2335 dataLen,
2336 nodeid, 0,
2337 pretty_text, sizeof(pretty_text));
2338
2339 m_output->println("%s", str.c_str());
2340 }
2341 }
2342
2343
2344 template class MutexVector<int>;
2345 template class Vector<ParserRow<MgmApiSession> const*>;
2346 template class Vector<NDB_SOCKET_TYPE>;
2347 template class Vector<SimpleSignal>;
2348