1 /*
2    Copyright (c) 2003, 2010, Oracle and/or its affiliates. All rights reserved.
3 
4    This program is free software; you can redistribute it and/or modify
5    it under the terms of the GNU General Public License, version 2.0,
6    as published by the Free Software Foundation.
7 
8    This program is also distributed with certain software (including
9    but not limited to OpenSSL) that is licensed under separate terms,
10    as designated in a particular file or component or in included license
11    documentation.  The authors of MySQL hereby grant you an additional
12    permission to link the program and your derivative works with the
13    separately licensed software that they have included with MySQL.
14 
15    This program is distributed in the hope that it will be useful,
16    but WITHOUT ANY WARRANTY; without even the implied warranty of
17    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18    GNU General Public License, version 2.0, for more details.
19 
20    You should have received a copy of the GNU General Public License
21    along with this program; if not, write to the Free Software
22    Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301  USA
23 */
24 
25 #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   // some compilers need all of this
86   class Allocated_resources;
87   friend class Allocated_resources;
88   class Allocated_resources {
89   public:
90     Allocated_resources(class MgmtSrvr &m);
91     ~Allocated_resources();
92     // methods to reserve/allocate resources which
93     // will be freed when running destructor
94     void reserve_node(NodeId id, NDB_TICKS timeout);
95     bool is_timed_out(NDB_TICKS tick);
is_reserved(NodeId nodeId)96     bool is_reserved(NodeId nodeId) { return m_reserved_nodes.get(nodeId); }
is_reserved(NodeBitmask mask)97     bool is_reserved(NodeBitmask mask) { return !mask.bitAND(m_reserved_nodes).isclear(); }
isclear()98     bool isclear() { return m_reserved_nodes.isclear(); }
99     NodeId get_nodeid() const;
100   private:
101     MgmtSrvr &m_mgmsrv;
102     NodeBitmask m_reserved_nodes;
103     NDB_TICKS m_alloc_timeout;
104   };
105 
106   /**
107    *   This enum specifies the different signal loggig modes possible to set
108    *   with the setSignalLoggingMode method.
109    */
110   enum LogMode {In, Out, InOut, Off};
111 
112   /**
113      @struct MgmtOpts
114      @brief Options used to control how the management server is started
115   */
116 
117   struct MgmtOpts {
118     int daemon;
119     int non_interactive;
120     int interactive;
121     const char* config_filename;
122     int mycnf;
123     int config_cache;
124     const char* bind_address;
125     int no_nodeid_checks;
126     int print_full_config;
127     const char* configdir;
128     int verbose;
MgmtOptsMgmtSrvr::MgmtOpts129     MgmtOpts() : configdir(MYSQLCLUSTERDIR) {};
130     int reload;
131     int initial;
132     NodeBitmask nowait_nodes;
133   };
134 
135   MgmtSrvr(); // Not implemented
136   MgmtSrvr(const MgmtSrvr&); // Not implemented
137   MgmtSrvr(const MgmtOpts&);
138 
139   ~MgmtSrvr();
140 
141 private:
142   /* Function used from 'init' */
143   const char* check_configdir() const;
144 
145 public:
146   /*
147     To be called after constructor.
148   */
149   bool init();
150 
151   /*
152     To be called after 'init', starts up the services
153     this server will expose
154    */
155   bool start(void);
156 private:
157   /* Functions used from 'start' */
158   bool start_transporter(const Config*);
159   bool start_mgm_service(const Config*);
160   bool connect_to_self(void);
161 
162 public:
163 
getOwnNodeId() const164   NodeId getOwnNodeId() const {return _ownNodeId;};
165 
166   /**
167    * Get status on a node.
168    * address may point to a common area (e.g. from inet_addr)
169    * There is no guarentee that it is preserved across calls.
170    * Copy the string if you are not going to use it immediately.
171    */
172   int status(int nodeId,
173 	     ndb_mgm_node_status * status,
174 	     Uint32 * version,
175 	     Uint32 * mysql_version,
176 	     Uint32 * phase,
177 	     bool * systemShutdown,
178 	     Uint32 * dynamicId,
179 	     Uint32 * nodeGroup,
180 	     Uint32 * connectCount,
181 	     const char **address);
182 
183   /**
184    *   Stop a list of nodes
185    */
186   int stopNodes(const Vector<NodeId> &node_ids, int *stopCount, bool abort,
187                 bool force, int *stopSelf);
188 
189   int shutdownMGM(int *stopCount, bool abort, int *stopSelf);
190 
191   /**
192    * shutdown the DB nodes
193    */
194   int shutdownDB(int * cnt = 0, bool abort = false);
195 
196   /**
197    *   Maintenance on the system
198    */
199   int enterSingleUser(int * cnt = 0, Uint32 singleuserNodeId = 0);
200 
201 
202   /**
203    *   Resume from maintenance on the system
204    */
205   int exitSingleUser(int * cnt = 0, bool abort = false);
206 
207   /**
208    *   Start DB process.
209    *   @param   processId: Id of the DB process to start
210    *   @return 0 if succeeded, otherwise: as stated above, plus:
211    */
212  int start(int processId);
213 
214   /**
215    *   Restart a list of nodes
216    */
217   int restartNodes(const Vector<NodeId> &node_ids,
218                    int *stopCount, bool nostart,
219                    bool initialStart, bool abort, bool force,
220                    int *stopSelf);
221 
222   /**
223    *   Restart all DB nodes
224    */
225   int restartDB(bool nostart, bool initialStart,
226                 bool abort = false,
227                 int * stopCount = 0);
228 
229   /**
230    * Backup functionallity
231    */
232   int startBackup(Uint32& backupId, int waitCompleted= 2, Uint32 input_backupId= 0, Uint32 backuppoint= 0);
233   int abortBackup(Uint32 backupId);
234   int performBackup(Uint32* backupId);
235 
236   //**************************************************************************
237   // Description: Set event report level for a DB process
238   // Parameters:
239   //  processId: Id of the DB process
240   //  level: Event report level
241   //  isResend: Flag to indicate for resending log levels during node restart
242   // Returns: 0 if succeeded, otherwise: as stated above, plus:
243   //  INVALID_LEVEL
244   //**************************************************************************
245 
246   int setEventReportingLevelImpl(int processId, const EventSubscribeReq& ll);
247   int setNodeLogLevelImpl(int processId, const SetLogLevelOrd & ll);
248 
249   /**
250    *   Insert an error in a DB process.
251    *   @param   processId: Id of the DB process
252    *   @param   errorNo: The error number. > 0.
253    *   @return  0 if succeeded, otherwise: as stated above, plus:
254    *            INVALID_ERROR_NUMBER
255    */
256   int insertError(int processId, int errorNo);
257 
258 
259 
260   int setTraceNo(int processId, int traceNo);
261   //**************************************************************************
262   // Description: Set trace number in a DB process.
263   // Parameters:
264   //  processId: Id of the DB process
265   //  trace: Trace number
266   // Returns: 0 if succeeded, otherwise: as stated above, plus:
267   //  INVALID_TRACE_NUMBER
268   //**************************************************************************
269 
270 
271   int setSignalLoggingMode(int processId, LogMode mode,
272 			   const Vector<BaseString> &blocks);
273 
setSignalLoggingMode(int processId,LogMode mode,BaseString & block)274   int setSignalLoggingMode(int processId, LogMode mode,
275 			   BaseString &block) {
276     Vector<BaseString> v;
277     v.push_back(block);
278     return setSignalLoggingMode(processId, mode, v);
279   }
280   //**************************************************************************
281   // Description: Set signal logging mode for blocks in a DB process.
282   // Parameters:
283   //  processId: Id of the DB process
284   //  mode: The log mode
285   //  blocks: Which blocks to be affected (container of strings)
286   // Returns: 0 if succeeded, otherwise: as stated above, plus:
287   //  INVALID_BLOCK_NAME
288   //**************************************************************************
289 
290 
291   int startSignalTracing(int processId);
292   //**************************************************************************
293   // Description: Start signal tracing for a DB process.
294   // Parameters:
295   //  processId: Id of the DB process
296   // Returns: 0 if succeeded, otherwise: as stated above.
297   //**************************************************************************
298 
299 
300   int stopSignalTracing(int processId);
301   //**************************************************************************
302   // Description: Stop signal tracing for a DB process.
303   // Parameters:
304   //  processId: Id of the DB process
305   // Returns: 0 if succeeded, otherwise: as stated above.
306   //**************************************************************************
307 
308   /**
309    *   Dump State
310    */
311   int dumpState(int processId, const Uint32 args[], Uint32 argNo);
312   int dumpState(int processId, const char* args);
313 
314   /**
315    * Get next node id (node id gt than _nodeId)
316    *  of specified type and save it in _nodeId
317    *
318    *   @return false if none found
319    */
320   bool getNextNodeId(NodeId * _nodeId, enum ndb_mgm_node_type type) const ;
321   bool alloc_node_id(NodeId * _nodeId, enum ndb_mgm_node_type type,
322 		     const struct sockaddr *client_addr,
323                      SOCKET_SIZE_TYPE *client_addr_len,
324 		     int &error_code, BaseString &error_string,
325                      int log_event = 1,
326 		     int timeout_s = 20);
327 
328   bool change_config(Config& new_config, BaseString& msg);
329 
330   /**
331    *   Get error text
332    *
333    *   @param   errorCode: Error code to get a match error text for.
334    *   @return  The error text.
335    */
336   const char* getErrorText(int errorCode, char *buf, int buf_sz);
337 
338 private:
339   void config_changed(NodeId, const Config*);
340   void setClusterLog(const Config* conf);
341 public:
342 
343   /**
344    * Returns the port number where MgmApiService is started
345    * @return port number.
346    */
getPort() const347   int getPort() const { return m_port; };
348 
349   int setDbParameter(int node, int parameter, const char * value, BaseString&);
350   int setConnectionDbParameter(int node1, int node2, int param, int value,
351 			       BaseString& msg);
352   int getConnectionDbParameter(int node1, int node2, int param,
353 			       int *value, BaseString& msg);
354 
355   bool transporter_connect(NDB_SOCKET_TYPE sockfd, BaseString& errormsg);
356 
357   const char *get_connect_address(Uint32 node_id);
358   void get_connected_nodes(NodeBitmask &connected_nodes) const;
get_socket_server()359   SocketServer *get_socket_server() { return &m_socket_server; }
360 
361   void updateStatus();
362 
363   int createNodegroup(int *nodes, int count, int *ng);
364   int dropNodegroup(int ng);
365 
366   int startSchemaTrans(SignalSender& ss, NodeId & out_nodeId,
367                        Uint32 transId, Uint32 & out_transKey);
368   int endSchemaTrans(SignalSender& ss, NodeId nodeId,
369                      Uint32 transId, Uint32 transKey, Uint32 flags);
370 
371 private:
372   int guess_master_node(SignalSender&);
373 
374   void status_api(int nodeId,
375                   ndb_mgm_node_status& node_status,
376                   Uint32& version, Uint32& mysql_version,
377                   const char **address);
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 
383   int sendVersionReq(int processId, Uint32 &version,
384                      Uint32& mysql_version, const char **address);
385 
386   int sendStopMgmd(NodeId nodeId,
387                    bool abort,
388                    bool stop,
389                    bool restart,
390                    bool nostart,
391                    bool initialStart);
392 
393   int sendall_STOP_REQ(NodeBitmask &stoppedNodes,
394                        bool abort,
395                        bool stop,
396                        bool restart,
397                        bool nostart,
398                        bool initialStart);
399 
400   int sendSTOP_REQ(const Vector<NodeId> &node_ids,
401 		   NodeBitmask &stoppedNodes,
402 		   bool abort,
403 		   bool stop,
404 		   bool restart,
405 		   bool nostart,
406 		   bool initialStart,
407                    int *stopSelf);
408 
409   /**
410    *   Check if it is possible to send a signal to a (DB) process
411    *
412    *   @param   processId: Id of the process to send to
413    *   @return  0 OK, 1 process dead, 2 API or MGMT process, 3 not configured
414    */
415   int okToSendTo(NodeId nodeId, bool unCond = false);
416 
417   /**
418    *   Get block number for a block
419    *
420    *   @param   blockName: Block to get number for
421    *   @return  -1 if block not found, otherwise block number
422    */
423   int getBlockNumber(const BaseString &blockName);
424 
425   int alloc_node_id_req(NodeId free_node_id,
426                         enum ndb_mgm_node_type type,
427                         Uint32 timeout_ms);
428 
429   bool is_any_node_starting(void);
430   bool is_any_node_stopping(void);
431   bool is_cluster_single_user(void);
432 
433   //**************************************************************************
434 
435   const MgmtOpts& m_opts;
436   int _blockNumber;
437   NodeId _ownNodeId;
438   Uint32 m_port;
439   SocketServer m_socket_server;
440 
441   NdbMutex* m_local_config_mutex;
442   const Config* m_local_config;
443 
444   NdbMutex *m_node_id_mutex;
445 
446   BlockReference _ownReference;
447 
448   class ConfigManager* m_config_manager;
449 
450   bool m_need_restart;
451 
452   NodeBitmask m_reserved_nodes;
453   struct in_addr m_connect_address[MAX_NODES];
454 
455   /**
456    * trp_client interface
457    */
458   virtual void trp_deliver_signal(const NdbApiSignal* signal,
459                                   const struct LinearSectionPtr ptr[3]);
460   virtual void trp_node_status(Uint32 nodeId, Uint32 event);
461 
462   /**
463    * An event from <i>nodeId</i> has arrived
464    */
465   void eventReport(const Uint32 * theData, Uint32 len);
466 
467   class TransporterFacade * theFacade;
468 
469   bool _isStopThread;
470   int _logLevelThreadSleep;
471   MutexVector<NodeId> m_started_nodes;
472   MutexVector<EventSubscribeReq> m_log_level_requests;
473   LogLevel m_nodeLogLevel[MAX_NODES];
474   enum ndb_mgm_node_type nodeTypes[MAX_NODES];
475   friend class MgmApiSession;
476   friend class Ndb_mgmd_event_service;
477   Ndb_mgmd_event_service m_event_listner;
478 
479   NodeId m_master_node;
480 
481   ndb_mgm_node_type getNodeType(NodeId) const;
482 
483   /**
484    * Handles the thread wich upon a 'Node is started' event will
485    * set the node's previous loglevel settings.
486    */
487   struct NdbThread* _logLevelThread;
488   static void *logLevelThread_C(void *);
489   void logLevelThreadRun();
490   void report_unknown_signal(SimpleSignal *signal);
491 
492   void make_sync_req(SignalSender& ss, Uint32 nodeId);
493 public:
494   /* Get copy of configuration packed with base64 */
495   bool get_packed_config(ndb_mgm_node_type nodetype,
496                          BaseString& buf64, BaseString& error);
497 
498   /* Get copy of configuration packed with base64 from node nodeid */
499   bool get_packed_config_from_node(NodeId nodeid,
500                          BaseString& buf64, BaseString& error);
501 
502   void print_config(const char* section_filter = NULL,
503                     NodeId nodeid_filter = 0,
504                     const char* param_filter = NULL,
505                     NdbOut& out = ndbout);
506 
507   bool reload_config(const char* config_filename,
508                      bool mycnf, BaseString& msg);
509 
510   void show_variables(NdbOut& out = ndbout);
511 
512   struct nodeid_and_host
513   {
514     unsigned id;
515     BaseString host;
516   };
517   int find_node_type(unsigned node_id, enum ndb_mgm_node_type type,
518                      const struct sockaddr *client_addr,
519                      NodeBitmask &nodes,
520                      NodeBitmask &exact_nodes,
521                      Vector<nodeid_and_host> &nodes_info,
522                      int &error_code, BaseString &error_string);
523   int try_alloc(unsigned id,  const char *, enum ndb_mgm_node_type type,
524                 const struct sockaddr *client_addr, Uint32 timeout_ms);
525 
526   BaseString m_version_string;
get_version_string(void) const527   const char* get_version_string(void) const {
528     return m_version_string.c_str();
529   }
530 
531   bool request_events(NdbNodeBitmask nodes, Uint32 reports_per_node,
532                       Uint32 dump_type,
533                       Vector<SimpleSignal>& events);
534 };
535 
536 #endif // MgmtSrvr_H
537