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