/* Copyright (C) 2004 MySQL AB This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #ifdef __GNUC__ #pragma implementation #endif #include "instance.h" #include "mysql_manager_error.h" #include "log.h" #include "instance_map.h" #include <my_sys.h> #include <signal.h> #include <m_string.h> #include <sys/wait.h> /* The method starts an instance. SYNOPSYS start() RETURN 0 ok ER_CANNOT_START_INSTANCE Cannot start instance ER_INSTANCE_ALREADY_STARTED The instance on the specified port/socket is already started */ int Instance::start() { pid_t pid; if (!is_running()) { if ((pid= options.get_pid()) != 0) /* check the pidfile */ if (options.unlink_pidfile()) /* remove stalled pidfile */ log_error("cannot remove pidfile for instance %i, this might be \ since IM lacks permmissions or hasn't found the pidifle", options.instance_name); log_info("starting instance %s", options.instance_name); switch (pid= fork()) { case 0: execv(options.mysqld_path, options.argv); exit(1); case -1: return ER_CANNOT_START_INSTANCE; default: return 0; } } /* the instance is started already */ return ER_INSTANCE_ALREADY_STARTED; } int Instance::cleanup() { return 0; } Instance::~Instance() { pthread_mutex_destroy(&LOCK_instance); } bool Instance::is_running() { MYSQL mysql; uint port= 0; const char *socket= NULL; const char *password= "321rarepassword213"; const char *username= "645rareusername945"; const char *access_denied_message= "Access denied for user"; bool return_val; if (options.mysqld_port) port= atoi(strchr(options.mysqld_port, '=') + 1); if (options.mysqld_socket) socket= strchr(options.mysqld_socket, '=') + 1; pthread_mutex_lock(&LOCK_instance); mysql_init(&mysql); /* try to connect to a server with the fake username/password pair */ if (mysql_real_connect(&mysql, LOCAL_HOST, username, password, NullS, port, socket, 0)) { /* Very strange. We have successfully connected to the server using bullshit as username/password. Write a warning to the logfile. */ log_info("The Instance Manager was able to log into you server \ with faked compiled-in password while checking server status. \ Looks like something is wrong."); mysql_close(&mysql); pthread_mutex_unlock(&LOCK_instance); return_val= TRUE; /* server is alive */ } else { if (!strncmp(access_denied_message, mysql_error(&mysql), sizeof(access_denied_message)-1)) { return_val= TRUE; } else return_val= FALSE; } mysql_close(&mysql); pthread_mutex_unlock(&LOCK_instance); return return_val; } /* Stop an instance. SYNOPSYS stop() RETURN: 0 ok ER_INSTANCE_IS_NOT_STARTED Looks like the instance it is not started ER_STOP_INSTANCE mysql_shutdown reported an error */ int Instance::stop() { pid_t pid; struct timespec timeout; int waitchild= DEFAULT_SHUTDOWN_DELAY; if (options.shutdown_delay != NULL) waitchild= atoi(options.shutdown_delay); if ((pid= options.get_pid()) != 0) /* get pid from pidfile */ { /* If we cannot kill mysqld, then it has propably crashed. Let us try to remove staled pidfile and return succes as mysqld is probably stopped */ if (kill(pid, SIGTERM)) { if (options.unlink_pidfile()) log_error("cannot remove pidfile for instance %i, this might be \ since IM lacks permmissions or hasn't found the pidifle", options.instance_name); return 0; } /* sleep on condition to wait for SIGCHLD */ timeout.tv_sec= time(NULL) + waitchild; timeout.tv_nsec= 0; if (pthread_mutex_lock(&instance_map->pid_cond.LOCK_pid)) goto err; /* perhaps this should be procecced differently */ while (options.get_pid() != 0) /* while server isn't stopped */ { int status; status= pthread_cond_timedwait(&instance_map->pid_cond.COND_pid, &instance_map->pid_cond.LOCK_pid, &timeout); if (status == ETIMEDOUT) break; } pthread_mutex_unlock(&instance_map->pid_cond.LOCK_pid); if (!kill(pid, SIGKILL)) { log_error("The instance %s has been stopped forsibly. Normally \ it should not happed. Probably the instance has been \ hanging. You should also check your IM setup", options.instance_name); } return 0; } return ER_INSTANCE_IS_NOT_STARTED; err: return ER_STOP_INSTANCE; } /* We execute this function to initialize instance parameters. Return value: 0 - ok. 1 - unable to init DYNAMIC_ARRAY. */ int Instance::init(const char *name_arg) { pthread_mutex_init(&LOCK_instance, 0); return options.init(name_arg); } int Instance::complete_initialization(Instance_map *instance_map_arg) { instance_map= instance_map_arg; return 0; }