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