summaryrefslogtreecommitdiff
path: root/server-tools/instance-manager/manager.cc
diff options
context:
space:
mode:
Diffstat (limited to 'server-tools/instance-manager/manager.cc')
-rw-r--r--server-tools/instance-manager/manager.cc260
1 files changed, 143 insertions, 117 deletions
diff --git a/server-tools/instance-manager/manager.cc b/server-tools/instance-manager/manager.cc
index 4bd298eedec..a002902bd56 100644
--- a/server-tools/instance-manager/manager.cc
+++ b/server-tools/instance-manager/manager.cc
@@ -37,33 +37,6 @@
#include "user_map.h"
-int create_pid_file(const char *pid_file_name, int pid)
-{
- FILE *pid_file;
-
- if (!(pid_file= my_fopen(pid_file_name, O_WRONLY | O_CREAT | O_BINARY,
- MYF(0))))
- {
- log_error("Error: can not create pid file '%s': %s (errno: %d)",
- (const char *) pid_file_name,
- (const char *) strerror(errno),
- (int) errno);
- return 1;
- }
-
- if (fprintf(pid_file, "%d\n", (int) pid) <= 0)
- {
- log_error("Error: can not write to pid file '%s': %s (errno: %d)",
- (const char *) pid_file_name,
- (const char *) strerror(errno),
- (int) errno);
- return 1;
- }
-
- my_fclose(pid_file, MYF(0));
-
- return 0;
-}
#ifndef __WIN__
void set_signals(sigset_t *mask)
@@ -120,19 +93,79 @@ int my_sigwait(const sigset_t *set, int *sig)
#endif
-void stop_all(Guardian_thread *guardian, Thread_registry *registry)
+/**********************************************************************
+ Implementation of checking the actual thread model.
+***********************************************************************/
+
+namespace { /* no-indent */
+
+class ThreadModelChecker: public Thread
+{
+public:
+ ThreadModelChecker()
+ :main_pid(getpid())
+ { }
+
+public:
+ inline bool is_linux_threads() const
+ {
+ return linux_threads;
+ }
+
+protected:
+ virtual void run()
+ {
+ linux_threads= main_pid != getpid();
+ }
+
+private:
+ pid_t main_pid;
+ bool linux_threads;
+};
+
+bool check_if_linux_threads(bool *linux_threads)
+{
+ ThreadModelChecker checker;
+
+ if (checker.start() || checker.join())
+ return TRUE;
+
+ *linux_threads= checker.is_linux_threads();
+
+ return FALSE;
+}
+
+}
+
+
+/**********************************************************************
+ Manager implementation
+***********************************************************************/
+
+Guardian *Manager::p_guardian;
+Instance_map *Manager::p_instance_map;
+Thread_registry *Manager::p_thread_registry;
+User_map *Manager::p_user_map;
+
+#ifndef __WIN__
+bool Manager::linux_threads;
+#endif // __WIN__
+
+
+void Manager::stop_all_threads()
{
/*
Let guardian thread know that it should break it's processing cycle,
once it wakes up.
*/
- guardian->request_shutdown();
+ p_guardian->request_shutdown();
/* wake guardian */
- pthread_cond_signal(&guardian->COND_guardian);
+ pthread_cond_signal(&p_guardian->COND_guardian);
/* stop all threads */
- registry->deliver_shutdown();
+ p_thread_registry->deliver_shutdown();
}
+
/*
manager - entry point to the main instance manager process: start
listener thread, write pid file and enter into signal handling.
@@ -142,11 +175,24 @@ void stop_all(Guardian_thread *guardian, Thread_registry *registry)
TODO: how about returning error status.
*/
-void manager()
+int Manager::main()
{
int err_code;
+ int rc= 1;
const char *err_msg;
bool shutdown_complete= FALSE;
+ pid_t manager_pid= getpid();
+
+#ifndef __WIN__
+ if (check_if_linux_threads(&linux_threads))
+ {
+ log_error("Can not determine thread model.");
+ return 1;
+ }
+
+ log_info("Detected threads model: %s.",
+ (const char *) (linux_threads ? "LINUX threads" : "POSIX threads"));
+#endif // __WIN__
Thread_registry thread_registry;
/*
@@ -156,31 +202,31 @@ void manager()
*/
User_map user_map;
- Instance_map instance_map(Options::Main::default_mysqld_path,
- thread_registry);
- Guardian_thread guardian_thread(thread_registry,
- &instance_map,
- Options::Main::monitoring_interval);
+ Instance_map instance_map;
+ Guardian guardian(&thread_registry, &instance_map,
+ Options::Main::monitoring_interval);
- Listener_thread_args listener_args(thread_registry, user_map, instance_map);
+ Listener listener(&thread_registry, &user_map);
- manager_pid= getpid();
- instance_map.guardian= &guardian_thread;
+ p_instance_map= &instance_map;
+ p_guardian= instance_map.guardian= &guardian;
+ p_thread_registry= &thread_registry;
+ p_user_map= &user_map;
/* Initialize instance map. */
if (instance_map.init())
{
- log_error("Error: can not initialize instance list: out of memory.");
- return;
+ log_error("Can not initialize instance list: out of memory.");
+ return 1;
}
/* Initialize user map and load password file. */
if (user_map.init())
{
- log_error("Error: can not initialize user list: out of memory.");
- return;
+ log_error("Can not initialize user list: out of memory.");
+ return 1;
}
if ((err_code= user_map.load(Options::Main::password_file_name, &err_msg)))
@@ -193,13 +239,13 @@ void manager()
mysqld_safe-compatible mode. Continue, but complain in log.
*/
- log_error("Warning: password file does not exist, "
- "nobody will be able to connect to Instance Manager.");
+ log_info("Warning: password file does not exist, "
+ "nobody will be able to connect to Instance Manager.");
}
else
{
- log_error("Error: %s.", (const char *) err_msg);
- return;
+ log_error("%s.", (const char *) err_msg);
+ return 1;
}
}
@@ -210,7 +256,7 @@ void manager()
(int) manager_pid);
if (create_pid_file(Options::Main::pid_file_name, manager_pid))
- return; /* necessary logging has been already done. */
+ return 1; /* necessary logging has been already done. */
/*
Initialize signals and alarm-infrastructure.
@@ -218,49 +264,36 @@ void manager()
NOTE: To work nicely with LinuxThreads, the signal thread is the first
thread in the process.
- NOTE:
- After init_thr_alarm() call it's possible to call thr_alarm() (from
- different threads), that results in sending ALARM signal to the alarm
- thread (which can be the main thread). That signal can interrupt
- blocking calls.
-
- In other words, a blocking call can be interrupted in the main thread
- after init_thr_alarm().
+ NOTE: After init_thr_alarm() call it's possible to call thr_alarm()
+ (from different threads), that results in sending ALARM signal to the
+ alarm thread (which can be the main thread). That signal can interrupt
+ blocking calls. In other words, a blocking call can be interrupted in
+ the main thread after init_thr_alarm().
*/
sigset_t mask;
set_signals(&mask);
- /* create guardian thread */
+ /*
+ Create the guardian thread. The newly started thread will block until
+ we actually load instances.
+
+ NOTE: Guardian should be shutdown first. Only then all other threads
+ can be stopped. This should be done in this order because the guardian
+ is responsible for shutting down all the guarded instances, and this
+ is a long operation.
+
+ NOTE: Guardian uses thr_alarm() when detects the current state of an
+ instance (is_running()), but this does not interfere with
+ flush_instances() call later in the code, because until
+ flush_instances() completes in the main thread, Guardian thread is not
+ permitted to process instances. And before flush_instances() has
+ completed, there are no instances to guard.
+ */
+ if (guardian.start(Thread::DETACHED))
{
- pthread_t guardian_thd_id;
- pthread_attr_t guardian_thd_attr;
- int rc;
-
- /*
- NOTE: Guardian should be shutdown first. Only then all other threads
- need to be stopped. This should be done, as guardian is responsible
- for shutting down the instances, and this is a long operation.
-
- NOTE: Guardian uses thr_alarm() when detects current state of
- instances (is_running()), but it is not interfere with
- flush_instances() later in the code, because until flush_instances()
- complete in the main thread, Guardian thread is not permitted to
- process instances. And before flush_instances() there is no instances
- to proceed.
- */
-
- pthread_attr_init(&guardian_thd_attr);
- pthread_attr_setdetachstate(&guardian_thd_attr, PTHREAD_CREATE_DETACHED);
- rc= set_stacksize_n_create_thread(&guardian_thd_id, &guardian_thd_attr,
- guardian, &guardian_thread);
- pthread_attr_destroy(&guardian_thd_attr);
- if (rc)
- {
- log_error("manager(): set_stacksize_n_create_thread(guardian) failed");
- goto err;
- }
-
+ log_error("Can not start Guardian thread.");
+ goto err;
}
/* Load instances. */
@@ -276,40 +309,30 @@ void manager()
if (flush_instances_status)
{
- log_error("Cannot init instances repository. This might be caused by "
- "the wrong config file options. For instance, missing mysqld "
- "binary. Aborting.");
- stop_all(&guardian_thread, &thread_registry);
+ log_error("Can not init instances repository.");
+ stop_all_threads();
goto err;
}
}
- /* create the listener */
+ /* Initialize the Listener. */
+
+ if (listener.start(Thread::DETACHED))
{
- pthread_t listener_thd_id;
- pthread_attr_t listener_thd_attr;
- int rc;
-
- pthread_attr_init(&listener_thd_attr);
- pthread_attr_setdetachstate(&listener_thd_attr, PTHREAD_CREATE_DETACHED);
- rc= set_stacksize_n_create_thread(&listener_thd_id, &listener_thd_attr,
- listener, &listener_args);
- pthread_attr_destroy(&listener_thd_attr);
- if (rc)
- {
- log_error("manager(): set_stacksize_n_create_thread(listener) failed");
- stop_all(&guardian_thread, &thread_registry);
- goto err;
- }
+ log_error("Can not start Listener thread.");
+ stop_all_threads();
+ goto err;
}
/*
After the list of guarded instances have been initialized,
Guardian should start them.
*/
- pthread_cond_signal(&guardian_thread.COND_guardian);
+ pthread_cond_signal(&guardian.COND_guardian);
- log_info("Main loop: started.");
+ /* Main loop. */
+
+ log_info("Manager: started.");
while (!shutdown_complete)
{
@@ -319,7 +342,7 @@ void manager()
if ((status= my_sigwait(&mask, &signo)) != 0)
{
log_error("sigwait() failed");
- stop_all(&guardian_thread, &thread_registry);
+ stop_all_threads();
goto err;
}
@@ -328,8 +351,8 @@ void manager()
- we are waiting for SIGINT, SIGTERM -- signals that mean we should
shutdown;
- as shutdown signal is caught, we stop Guardian thread (by calling
- Guardian_thread::request_shutdown());
- - as Guardian_thread is stopped, it sends SIGTERM to this thread
+ Guardian::request_shutdown());
+ - as Guardian is stopped, it sends SIGTERM to this thread
(by calling Thread_registry::request_shutdown()), so that the
my_sigwait() above returns;
- as we catch the second SIGTERM, we send signals to all threads
@@ -345,7 +368,7 @@ void manager()
Bug #14164 IM tests fail on MacOS X (powermacg5)
*/
#ifdef IGNORE_SIGHUP_SIGQUIT
- if ( SIGHUP == signo )
+ if (SIGHUP == signo)
continue;
#endif
if (THR_SERVER_ALARM == signo)
@@ -353,12 +376,12 @@ void manager()
else
#endif
{
- log_info("Main loop: got shutdown signal.");
+ log_info("Manager: got shutdown signal.");
- if (!guardian_thread.is_stopped())
+ if (!guardian.is_stopped())
{
- guardian_thread.request_shutdown();
- pthread_cond_signal(&guardian_thread.COND_guardian);
+ guardian.request_shutdown();
+ pthread_cond_signal(&guardian.COND_guardian);
}
else
{
@@ -368,7 +391,9 @@ void manager()
}
}
- log_info("Main loop: finished.");
+ log_info("Manager: finished.");
+
+ rc= 0;
err:
/* delete the pid file */
@@ -379,4 +404,5 @@ err:
end_thr_alarm(1);
/* don't pthread_exit to kill all threads who did not shut down in time */
#endif
+ return rc;
}