1 /* 2 Copyright (c) 2003, 2020, 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 #ifndef MgmtSrvr_H 26 #define MgmtSrvr_H 27 28 #include "Config.hpp" 29 #include "ConfigSubscriber.hpp" 30 31 #include <mgmapi.h> 32 #include <Vector.hpp> 33 #include <NodeBitmask.hpp> 34 #include <ndb_version.h> 35 #include <EventLogger.hpp> 36 37 #include <SignalSender.hpp> 38 39 #define MGM_ERROR_MAX_INJECT_SESSION_ONLY 10000 40 41 class SetLogLevelOrd; 42 43 class Ndb_mgmd_event_service : public EventLoggerBase 44 { 45 friend class MgmtSrvr; 46 public: 47 struct Event_listener : public EventLoggerBase { Event_listenerNdb_mgmd_event_service::Event_listener48 Event_listener() {} 49 NDB_SOCKET_TYPE m_socket; 50 Uint32 m_parsable; 51 }; 52 53 private: 54 class MgmtSrvr * m_mgmsrv; 55 MutexVector<Event_listener> m_clients; 56 public: Ndb_mgmd_event_service(class MgmtSrvr * m)57 Ndb_mgmd_event_service(class MgmtSrvr * m) : m_clients(5) { 58 m_mgmsrv = m; 59 } 60 ~Ndb_mgmd_event_service()61 ~Ndb_mgmd_event_service() 62 { 63 stop_sessions(); 64 } 65 66 void add_listener(const Event_listener&); 67 void check_listeners(); 68 void update_max_log_level(const LogLevel&); 69 void update_log_level(const LogLevel&); 70 71 void log(int eventType, const Uint32* theData, Uint32 len, NodeId nodeId); 72 73 void stop_sessions(); 74 operator [](unsigned i)75 Event_listener& operator[](unsigned i) { return m_clients[i]; } operator [](unsigned i) const76 const Event_listener& operator[](unsigned i) const { return m_clients[i]; } lock()77 void lock() { m_clients.lock(); } unlock()78 void unlock(){ m_clients.unlock(); } 79 }; 80 81 82 83 /** 84 @class MgmtSrvr 85 @brief Main class for the management server. 86 */ 87 class MgmtSrvr : private ConfigSubscriber, public trp_client { 88 89 public: 90 /** 91 * This enum specifies the different signal loggig modes possible to set 92 * with the setSignalLoggingMode method. 93 */ 94 enum LogMode {In, Out, InOut, Off}; 95 96 /** 97 @struct MgmtOpts 98 @brief Options used to control how the management server is started 99 */ 100 101 struct MgmtOpts { 102 int daemon; 103 int non_interactive; 104 int interactive; 105 const char* config_filename; 106 int mycnf; 107 int config_cache; 108 const char* bind_address; 109 int no_nodeid_checks; 110 int print_full_config; 111 const char* configdir; 112 int verbose; MgmtOptsMgmtSrvr::MgmtOpts113 MgmtOpts() : configdir(MYSQLCLUSTERDIR) {} 114 int reload; 115 int initial; 116 NodeBitmask nowait_nodes; 117 }; 118 119 MgmtSrvr(); // Not implemented 120 MgmtSrvr(const MgmtSrvr&); // Not implemented 121 MgmtSrvr(const MgmtOpts&); 122 123 ~MgmtSrvr(); 124 125 private: 126 /* Function used from 'init' */ 127 const char* check_configdir() const; 128 129 public: 130 /* 131 To be called after constructor. 132 */ 133 bool init(); 134 135 /* 136 To be called after 'init', starts up the services 137 this server will expose 138 */ 139 bool start(void); 140 private: 141 /* Functions used from 'start' */ 142 bool start_transporter(const Config*); 143 bool start_mgm_service(const Config*); 144 bool connect_to_self(void); 145 146 public: 147 getOwnNodeId() const148 NodeId getOwnNodeId() const {return _ownNodeId;} 149 150 /** 151 * Get status on a node. 152 * address may point to a common area (e.g. from inet_addr) 153 * There is no guarentee that it is preserved across calls. 154 * Copy the string if you are not going to use it immediately. 155 */ 156 int status(int nodeId, 157 ndb_mgm_node_status * status, 158 Uint32 * version, 159 Uint32 * mysql_version, 160 Uint32 * phase, 161 bool * systemShutdown, 162 Uint32 * dynamicId, 163 Uint32 * nodeGroup, 164 Uint32 * connectCount, 165 const char **address, 166 char *addr_buf, 167 size_t addr_buf_size, 168 bool* is_single_user); 169 170 /** 171 * Stop a list of nodes 172 */ 173 int stopNodes(const Vector<NodeId> &node_ids, int *stopCount, bool abort, 174 bool force, int *stopSelf); 175 176 int shutdownMGM(int *stopCount, bool abort, int *stopSelf); 177 178 /** 179 * shutdown the DB nodes 180 */ 181 int shutdownDB(int * cnt = 0, bool abort = false); 182 183 /** 184 * Maintenance on the system 185 */ 186 int enterSingleUser(int * cnt = 0, Uint32 singleuserNodeId = 0); 187 188 189 /** 190 * Resume from maintenance on the system 191 */ 192 int exitSingleUser(int * cnt = 0, bool abort = false); 193 194 /** 195 * Start DB process by sending START_ORD to it. 196 * @param processId Id of the DB process to start 197 * @return 0 if succeeded, otherwise: as stated above, plus: 198 */ 199 int sendSTART_ORD(int processId); 200 201 /** 202 * Restart a list of nodes 203 */ 204 int restartNodes(const Vector<NodeId> &node_ids, 205 int *stopCount, bool nostart, 206 bool initialStart, bool abort, bool force, 207 int *stopSelf, 208 unsigned int num_secs_to_wait_for_node = 120); 209 210 /** 211 * Restart all DB nodes 212 */ 213 int restartDB(bool nostart, bool initialStart, 214 bool abort = false, 215 int * stopCount = 0, 216 unsigned int num_secs_to_wait_for_node = 120); 217 218 /** 219 * Backup functionallity 220 */ 221 int startBackup(Uint32& backupId, int waitCompleted= 2, Uint32 input_backupId= 0, Uint32 backuppoint= 0); 222 int abortBackup(Uint32 backupId); 223 int performBackup(Uint32* backupId); 224 225 //************************************************************************** 226 // Description: Set event report level for a DB process 227 // Parameters: 228 // processId: Id of the DB process 229 // level: Event report level 230 // isResend: Flag to indicate for resending log levels during node restart 231 // Returns: 0 if succeeded, otherwise: as stated above, plus: 232 // INVALID_LEVEL 233 //************************************************************************** 234 235 int setEventReportingLevelImpl(int processId, const EventSubscribeReq& ll); 236 int setNodeLogLevelImpl(int processId, const SetLogLevelOrd & ll); 237 238 /** 239 * Insert an error in a DB process. 240 * @param processId Id of the DB process 241 * @param errorNo The error number. > 0. 242 * @return 0 if succeeded, otherwise: as stated above, plus: 243 * INVALID_ERROR_NUMBER 244 */ 245 int insertError(int processId, int errorNo, Uint32 * extra = 0); 246 247 248 249 int setTraceNo(int processId, int traceNo); 250 //************************************************************************** 251 // Description: Set trace number in a DB process. 252 // Parameters: 253 // processId: Id of the DB process 254 // trace: Trace number 255 // Returns: 0 if succeeded, otherwise: as stated above, plus: 256 // INVALID_TRACE_NUMBER 257 //************************************************************************** 258 259 260 int setSignalLoggingMode(int processId, LogMode mode, 261 const Vector<BaseString> &blocks); 262 setSignalLoggingMode(int processId,LogMode mode,BaseString & block)263 int setSignalLoggingMode(int processId, LogMode mode, 264 BaseString &block) { 265 Vector<BaseString> v; 266 v.push_back(block); 267 return setSignalLoggingMode(processId, mode, v); 268 } 269 //************************************************************************** 270 // Description: Set signal logging mode for blocks in a DB process. 271 // Parameters: 272 // processId: Id of the DB process 273 // mode: The log mode 274 // blocks: Which blocks to be affected (container of strings) 275 // Returns: 0 if succeeded, otherwise: as stated above, plus: 276 // INVALID_BLOCK_NAME 277 //************************************************************************** 278 279 280 int startSignalTracing(int processId); 281 //************************************************************************** 282 // Description: Start signal tracing for a DB process. 283 // Parameters: 284 // processId: Id of the DB process 285 // Returns: 0 if succeeded, otherwise: as stated above. 286 //************************************************************************** 287 288 289 int stopSignalTracing(int processId); 290 //************************************************************************** 291 // Description: Stop signal tracing for a DB process. 292 // Parameters: 293 // processId: Id of the DB process 294 // Returns: 0 if succeeded, otherwise: as stated above. 295 //************************************************************************** 296 297 /** 298 * Dump State 299 */ 300 int dumpStateSelf(const Uint32 args[], Uint32 no); 301 int dumpState(int processId, const Uint32 args[], Uint32 argNo); 302 int dumpState(int processId, const char* args); 303 304 /** 305 * Get next node id (node id gt than _nodeId) 306 * of specified type and save it in _nodeId 307 * 308 * @return false if none found 309 */ 310 bool getNextNodeId(NodeId * _nodeId, enum ndb_mgm_node_type type) const ; 311 312 bool change_config(Config& new_config, BaseString& msg); 313 314 /** 315 * Get error text 316 * 317 * @param errorCode Error code to get a match error text for. 318 * @return The error text. 319 */ 320 const char* getErrorText(int errorCode, char *buf, int buf_sz); 321 322 private: 323 void config_changed(NodeId, const Config*); 324 void setClusterLog(const Config* conf); 325 void configure_eventlogger(const BaseString& logdestination) const; 326 /** 327 * Make cluster logging asynchronous/synchronous 328 * when g_eventLogger is set up the next time. 329 * @param async_cluster_logging true for async logging, 330 * false for sync logging 331 */ 332 void set_async_cluster_logging(bool async_cluster_logging); 333 public: 334 335 /** 336 * Returns the port number where MgmApiService is started 337 * @return port number. 338 */ getPort() const339 int getPort() const { return m_port; } 340 341 int setDbParameter(int node, int parameter, const char * value, BaseString&); 342 int setConnectionDbParameter(int node1, int node2, int param, int value, 343 BaseString& msg); 344 345 struct DynPortSpec { 346 int node; /* The node which should use below port */ 347 int port; /* The port to use */ 348 }; 349 bool setDynamicPorts(int node, DynPortSpec ports[], 350 unsigned num_ports, BaseString &msg); 351 int getConnectionDbParameter(int node1, int node2, int param, 352 int *value, BaseString& msg); 353 354 bool transporter_connect(NDB_SOCKET_TYPE sockfd, 355 BaseString& errormsg, 356 bool& close_with_reset); 357 get_socket_server()358 SocketServer *get_socket_server() { return &m_socket_server; } 359 360 int createNodegroup(int *nodes, int count, int *ng); 361 int dropNodegroup(int ng); 362 363 int startSchemaTrans(SignalSender& ss, NodeId & out_nodeId, 364 Uint32 transId, Uint32 & out_transKey); 365 int endSchemaTrans(SignalSender& ss, NodeId nodeId, 366 Uint32 transId, Uint32 transKey, Uint32 flags); 367 368 private: 369 int guess_master_node(SignalSender&); 370 371 void status_api(int nodeId, 372 ndb_mgm_node_status& node_status, 373 Uint32& version, Uint32& mysql_version, 374 const char **address, 375 char *addr_buf, 376 size_t addr_buf_size, 377 bool& is_single_user); 378 void status_mgmd(NodeId node_id, 379 ndb_mgm_node_status& node_status, 380 Uint32& version, Uint32& mysql_version, 381 const char **address, 382 char *addr_buf, 383 size_t addr_buf_size, 384 bool& is_single_user); 385 386 int sendVersionReq(int processId, 387 Uint32 &version, 388 Uint32& mysql_version, 389 const char **address, 390 char *addr_buf, 391 size_t addr_buf_size, 392 bool& is_single_user); 393 394 int sendStopMgmd(NodeId nodeId, 395 bool abort, 396 bool stop, 397 bool restart, 398 bool nostart, 399 bool initialStart); 400 401 int sendall_STOP_REQ(NodeBitmask &stoppedNodes, 402 bool abort, 403 bool stop, 404 bool restart, 405 bool nostart, 406 bool initialStart); 407 408 int sendSTOP_REQ(const Vector<NodeId> &node_ids, 409 NodeBitmask &stoppedNodes, 410 bool abort, 411 bool stop, 412 bool restart, 413 bool nostart, 414 bool initialStart, 415 int *stopSelf); 416 417 /** 418 * Check if it is possible to send a signal to a (DB) process 419 * 420 * @param nodeId Id of the node to send to 421 * @return 0 OK, 1 process dead, 2 API or MGMT process, 3 not configured 422 */ 423 int okToSendTo(NodeId nodeId, bool unCond = false); 424 425 bool is_any_node_starting(void); 426 bool is_any_node_stopping(void); 427 bool is_any_node_alive(void); 428 bool is_any_node_in_started_state(void); 429 bool is_cluster_single_user(void); 430 bool are_all_nodes_in_cmvmi_state(void); 431 bool isTimeUp(const NDB_TICKS startTime, 432 const Uint64 delay, 433 const Uint64 startInterval); 434 435 //************************************************************************** 436 437 const MgmtOpts& m_opts; 438 BlockNumber _blockNumber; 439 NodeId _ownNodeId; 440 Uint32 m_port; 441 SocketServer m_socket_server; 442 443 NdbMutex* m_local_config_mutex; 444 const Config* m_local_config; 445 446 BlockReference _ownReference; 447 448 class ConfigManager* m_config_manager; 449 450 bool m_need_restart; 451 452 struct in_addr m_connect_address[MAX_NODES]; 453 const char *get_connect_address(NodeId node_id, 454 char *addr_buf, 455 size_t addr_buf_size); 456 void clear_connect_address_cache(NodeId nodeid); 457 458 /** 459 * trp_client interface 460 */ 461 virtual void trp_deliver_signal(const NdbApiSignal* signal, 462 const struct LinearSectionPtr ptr[3]); 463 virtual void trp_node_status(Uint32 nodeId, Uint32 event); 464 465 /** 466 * An event from <i>nodeId</i> has arrived 467 */ 468 void eventReport(const Uint32 * theSignalData, 469 Uint32 len, 470 const Uint32 * theData); 471 472 class TransporterFacade * theFacade; 473 474 bool _isStopThread; 475 int _logLevelThreadSleep; 476 MutexVector<NodeId> m_started_nodes; 477 MutexVector<EventSubscribeReq> m_log_level_requests; 478 LogLevel m_nodeLogLevel[MAX_NODES]; 479 enum ndb_mgm_node_type nodeTypes[MAX_NODES]; 480 friend class MgmApiSession; 481 friend class Ndb_mgmd_event_service; 482 Ndb_mgmd_event_service m_event_listner; 483 484 NodeId m_master_node; 485 486 ndb_mgm_node_type getNodeType(NodeId) const; 487 488 /** 489 * Handles the thread wich upon a 'Node is started' event will 490 * set the node's previous loglevel settings. 491 */ 492 struct NdbThread* _logLevelThread; 493 static void *logLevelThread_C(void *); 494 void logLevelThreadRun(); 495 void report_unknown_signal(SimpleSignal *signal); 496 497 void make_sync_req(SignalSender& ss, Uint32 nodeId); 498 public: 499 /* Get copy of configuration packed with base64 */ 500 bool get_packed_config(ndb_mgm_node_type nodetype, 501 BaseString& buf64, 502 BaseString& error, 503 bool v2, 504 Uint32 node_id); 505 506 /* Get copy of configuration packed with base64 from node nodeid */ 507 bool get_packed_config_from_node(NodeId nodeid, 508 BaseString& buf64, 509 BaseString& error, 510 bool v2); 511 512 void print_config(const char* section_filter = NULL, 513 NodeId nodeid_filter = 0, 514 const char* param_filter = NULL, 515 NdbOut& out = ndbout); 516 517 bool reload_config(const char* config_filename, 518 bool mycnf, BaseString& msg); 519 520 void show_variables(NdbOut& out = ndbout); 521 522 private: 523 class NodeIdReservations { 524 struct Reservation { 525 NDB_TICKS m_start; 526 unsigned m_timeout; // Milliseconds 527 }; 528 Reservation m_reservations[MAX_NODES]; 529 public: 530 NodeIdReservations(); 531 void check_array(NodeId n) const; 532 bool get(NodeId n) const; 533 void set(NodeId n, unsigned timeout); 534 void clear(NodeId n); 535 BaseString pretty_str() const; 536 bool has_timedout(NodeId n, NDB_TICKS now) const; 537 } m_reserved_nodes; 538 NdbMutex* m_reserved_nodes_mutex; 539 540 void release_local_nodeid_reservation(NodeId nodeid); 541 struct PossibleNode 542 { 543 unsigned id; 544 BaseString host; 545 bool exact_match; 546 }; 547 int alloc_node_id_req(NodeId free_node_id, 548 ndb_mgm_node_type type, 549 Uint32 timeout_ms); 550 int try_alloc(NodeId id, 551 ndb_mgm_node_type type, 552 Uint32 timeout_ms, 553 int& error_code, 554 BaseString& error_string); 555 int try_alloc_from_list(NodeId& nodeid, 556 ndb_mgm_node_type type, 557 Uint32 timeout_ms, 558 Vector<PossibleNode>& nodes_info, 559 int& error_code, 560 BaseString& error_string); 561 int find_node_type(NodeId nodeid, 562 ndb_mgm_node_type type, 563 const struct sockaddr* client_addr, 564 Vector<PossibleNode>& nodes_info, 565 int& error_code, BaseString& error_string); 566 bool alloc_node_id_impl(NodeId& nodeid, 567 ndb_mgm_node_type type, 568 const struct sockaddr* client_addr, 569 int& error_code, BaseString& error_string, 570 Uint32 timeout_s = 20); 571 public: 572 /* 573 Nodeid allocation 574 - MGM will never allocate a nodeid since either there is 575 only one(and thus it's nodeid is well known by looking 576 in config) or when running with two or more, they will 577 have nodeid specified on command line when starting. 578 - API nodes will always allocate a nodeid in the data nodes 579 since those have transporter connections with hearbeat 580 mechanism and can thus detect when the allocation should 581 be cleared. 582 - NDB nodes will prefer to allocate a nodeid in the data nodes 583 since the allocations will then be known by all connected 584 nodes(as well as hearbeat). But in order to startup a 585 nodeid can also be reserved locally in the mgmtsrvr node 586 only, such a reservations is cleared as soon as the 587 data node has connected via transporter to the mgmtsrvr. 588 */ 589 bool alloc_node_id(NodeId& nodeid, 590 ndb_mgm_node_type type, 591 const struct sockaddr* client_addr, 592 int& error_code, BaseString& error_string, 593 bool log_event = true, 594 Uint32 timeout_s = 20); 595 596 private: 597 BaseString m_version_string; 598 bool m_async_cluster_logging; 599 public: get_version_string(void) const600 const char* get_version_string(void) const { 601 return m_version_string.c_str(); 602 } 603 604 bool request_events(NdbNodeBitmask nodes, Uint32 reports_per_node, 605 Uint32 dump_type, 606 Vector<SimpleSignal>& events); 607 }; 608 609 #endif // MgmtSrvr_H 610