1 /* Copyright (c) 2003-2007 MySQL AB
3 This program is free software; you can redistribute it and/or modify
4 it under the terms of the GNU General Public License as published by
5 the Free Software Foundation; version 2 of the License.
7 This program is distributed in the hope that it will be useful,
8 but WITHOUT ANY WARRANTY; without even the implied warranty of
9 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10 GNU General Public License for more details.
12 You should have received a copy of the GNU General Public License
13 along with this program; if not, write to the Free Software
14 Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA */
18 #include <my_global.h>
21 #include <thr_alarm.h>
28 #include "exit_codes.h"
30 #include "instance_map.h"
32 #include "mysql_manager_error.h"
33 #include "mysqld_error.h"
37 #include "thread_registry.h"
41 /**********************************************************************
42 {{{ Platform-specific implementation.
43 **********************************************************************/
46 void set_signals(sigset_t
*mask
)
50 sigaddset(mask
, SIGINT
);
51 sigaddset(mask
, SIGTERM
);
52 sigaddset(mask
, SIGPIPE
);
53 sigaddset(mask
, SIGHUP
);
54 signal(SIGPIPE
, SIG_IGN
);
57 We want this signal to be blocked in all theads but the signal
58 one. It is needed for the thr_alarm subsystem to work.
60 sigaddset(mask
,THR_SERVER_ALARM
);
62 /* all new threads will inherite this signal mask */
63 pthread_sigmask(SIG_BLOCK
, mask
, NULL
);
66 In our case the signal thread also implements functions of alarm thread.
67 Here we init alarm thread functionality. We suppose that we won't have
68 more then 10 alarms at the same time.
76 void onsignal(int signo
)
81 void set_signals(sigset_t
*set
)
83 signal(SIGINT
, onsignal
);
84 signal(SIGTERM
, onsignal
);
88 int my_sigwait(const sigset_t
*set
, int *sig
)
99 /**********************************************************************
101 **********************************************************************/
104 /**********************************************************************
105 {{{ Implementation of checking the actual thread model.
106 ***********************************************************************/
108 namespace { /* no-indent */
110 class ThreadModelChecker
: public Thread
118 inline bool is_linux_threads() const
120 return linux_threads
;
126 linux_threads
= main_pid
!= getpid();
134 bool check_if_linux_threads(bool *linux_threads
)
136 ThreadModelChecker checker
;
138 if (checker
.start() || checker
.join())
141 *linux_threads
= checker
.is_linux_threads();
148 /**********************************************************************
150 ***********************************************************************/
153 /**********************************************************************
154 Manager implementation
155 ***********************************************************************/
157 Guardian
*Manager::p_guardian
;
158 Instance_map
*Manager::p_instance_map
;
159 Thread_registry
*Manager::p_thread_registry
;
160 User_map
*Manager::p_user_map
;
163 bool Manager::linux_threads
;
168 Request shutdown of guardian and threads registered in Thread_registry.
174 void Manager::stop_all_threads()
177 Let Guardian thread know that it should break it's processing cycle,
180 p_guardian
->request_shutdown();
182 /* Stop all threads. */
183 p_thread_registry
->deliver_shutdown();
185 /* Set error status in the thread registry. */
186 p_thread_registry
->set_error_status();
191 Initialize user map and load password file.
201 bool Manager::init_user_map(User_map
*user_map
)
206 if (user_map
->init())
208 log_error("Manager: can not initialize user list: out of memory.");
212 err_code
= user_map
->load(Options::Main::password_file_name
, &err_msg
);
217 if (err_code
== ERR_PASSWORD_FILE_DOES_NOT_EXIST
&&
218 Options::Main::mysqld_safe_compatible
)
221 The password file does not exist, but we are running in
222 mysqld_safe-compatible mode. Continue, but complain in log.
225 log_info("Warning: password file does not exist, "
226 "nobody will be able to connect to Instance Manager.");
231 log_error("Manager: %s.", (const char *) err_msg
);
238 Main manager function.
244 This is an entry point to the main instance manager process:
245 start listener thread, write pid file and enter into signal handling.
246 See also comments in mysqlmanager.cc to picture general Instance Manager
250 main() returns exit status (exit code).
255 bool shutdown_complete
= FALSE
;
256 pid_t manager_pid
= getpid();
258 log_info("Manager: initializing...");
261 if (check_if_linux_threads(&linux_threads
))
263 log_error("Manager: can not determine thread model.");
267 log_info("Manager: detected threads model: %s.",
268 (const char *) (linux_threads
? "LINUX threads" : "POSIX threads"));
272 All objects created in the Manager object live as long as thread_registry
273 lives, and thread_registry is alive until there are working threads.
275 There are two main purposes of the Thread Registry:
276 1. Interrupt blocking I/O and signal condition variables in case of
278 2. Wait for detached threads before shutting down the main thread.
281 1. Handling shutdown can be done in more elegant manner by introducing
282 Event (or Condition) object with support of logical operations.
283 2. Using Thread Registry to wait for detached threads is definitely not
284 the best way, because when Thread Registry unregisters an thread, the
285 thread is still alive. Accurate way to wait for threads to stop is
286 not using detached threads and join all threads before shutdown.
289 Thread_registry thread_registry
;
291 Instance_map instance_map
;
292 Guardian
guardian(&thread_registry
, &instance_map
);
294 Listener
listener(&thread_registry
, &user_map
);
296 p_instance_map
= &instance_map
;
297 p_guardian
= &guardian
;
298 p_thread_registry
= &thread_registry
;
299 p_user_map
= &user_map
;
301 /* Initialize instance map. */
303 if (instance_map
.init())
305 log_error("Manager: can not initialize instance list: out of memory.");
309 /* Initialize user db. */
311 if (init_user_map(&user_map
))
312 return 1; /* logging has been already done. */
314 /* Write Instance Manager pid file. */
316 if (create_pid_file(Options::Main::pid_file_name
, manager_pid
))
317 return 1; /* necessary logging has been already done. */
319 log_info("Manager: pid file (%s) created.",
320 (const char *) Options::Main::pid_file_name
);
323 Initialize signals and alarm-infrastructure.
325 NOTE: To work nicely with LinuxThreads, the signal thread is the first
326 thread in the process.
328 NOTE: After init_thr_alarm() call it's possible to call thr_alarm()
329 (from different threads), that results in sending ALARM signal to the
330 alarm thread (which can be the main thread). That signal can interrupt
331 blocking calls. In other words, a blocking call can be interrupted in
332 the main thread after init_thr_alarm().
339 Create the guardian thread. The newly started thread will block until
340 we actually load instances.
342 NOTE: Guardian should be shutdown first. Only then all other threads
343 can be stopped. This should be done in this order because the guardian
344 is responsible for shutting down all the guarded instances, and this
347 NOTE: Guardian uses thr_alarm() when detects the current state of an
348 instance (is_running()), but this does not interfere with
349 flush_instances() call later in the code, because until
350 flush_instances() completes in the main thread, Guardian thread is not
351 permitted to process instances. And before flush_instances() has
352 completed, there are no instances to guard.
355 if (guardian
.start(Thread::DETACHED
))
357 log_error("Manager: can not start Guardian thread.");
361 /* Load instances. */
363 if (Manager::flush_instances())
365 log_error("Manager: can not init instances repository.");
370 /* Initialize the Listener. */
372 if (listener
.start(Thread::DETACHED
))
374 log_error("Manager: can not start Listener thread.");
380 After the list of guarded instances have been initialized,
381 Guardian should start them.
388 log_info("Manager: started.");
390 while (!shutdown_complete
)
395 if ((status
= my_sigwait(&mask
, &signo
)) != 0)
397 log_error("Manager: sigwait() failed");
403 The general idea in this loop is the following:
404 - we are waiting for SIGINT, SIGTERM -- signals that mean we should
406 - as shutdown signal is caught, we stop Guardian thread (by calling
407 Guardian::request_shutdown());
408 - as Guardian is stopped, it sends SIGTERM to this thread
409 (by calling Thread_registry::request_shutdown()), so that the
410 my_sigwait() above returns;
411 - as we catch the second SIGTERM, we send signals to all threads
412 registered in Thread_registry (by calling
413 Thread_registry::deliver_shutdown()) and waiting for threads to stop;
418 On some Darwin kernels SIGHUP is delivered along with most
419 signals. This is why we skip it's processing on these
420 platforms. For more details and test program see
421 Bug #14164 IM tests fail on MacOS X (powermacg5)
423 #ifdef IGNORE_SIGHUP_SIGQUIT
427 if (THR_SERVER_ALARM
== signo
)
428 process_alarm(signo
);
432 log_info("Manager: got shutdown signal.");
434 if (!guardian
.is_stopped())
436 guardian
.request_shutdown();
440 thread_registry
.deliver_shutdown();
441 shutdown_complete
= TRUE
;
446 log_info("Manager: finished.");
449 /* delete the pid file */
450 my_delete(Options::Main::pid_file_name
, MYF(0));
453 /* free alarm structures */
457 return thread_registry
.get_error_status() ? 1 : 0;
462 Re-read instance configuration file.
469 - clear the current list of instances. This removes both
470 running and stopped instances.
471 - load a new instance configuration from the file.
472 - pass on the new map to the guardian thread: it will start
473 all instances that are marked `guarded' and not yet started.
475 Note, as the check whether an instance is started is currently
476 very simple (returns TRUE if there is a MySQL server running
477 at the given port), this function has some peculiar
479 * if the port number of a running instance was changed, the
480 old instance is forgotten, even if it was running. The new
481 instance will be started at the new port.
482 * if the configuration was changed in a way that two
483 instances swapped their port numbers, the guardian thread
484 will not notice that and simply report that both instances
485 are configured successfully and running.
487 In order to avoid such side effects one should never call
488 FLUSH INSTANCES without prior stop of all running instances.
492 ER_OUT_OF_RESOURCES Not enough resources to complete the operation
493 ER_THERE_IS_ACTIVE_INSTACE If there is an active instance
496 int Manager::flush_instances()
498 p_instance_map
->lock();
500 if (p_instance_map
->is_there_active_instance())
502 p_instance_map
->unlock();
503 return ER_THERE_IS_ACTIVE_INSTACE
;
506 if (p_instance_map
->reset())
508 p_instance_map
->unlock();
509 return ER_OUT_OF_RESOURCES
;
512 if (p_instance_map
->load())
514 p_instance_map
->unlock();
516 /* Don't init guardian if we failed to load instances. */
517 return ER_OUT_OF_RESOURCES
;
520 get_guardian()->init();
521 get_guardian()->ping();
523 p_instance_map
->unlock();