2517 lines
72 KiB
C++
2517 lines
72 KiB
C++
/* Copyright (C) 1979-1998 TcX AB & Monty Program KB & Detron HB
|
|
|
|
This software is distributed with NO WARRANTY OF ANY KIND. No author or
|
|
distributor accepts any responsibility for the consequences of using it, or
|
|
for whether it serves any particular purpose or works at all, unless he or
|
|
she says so in writing. Refer to the Free Public License (the "License")
|
|
for full details.
|
|
|
|
Every copy of this file must include a copy of the License, normally in a
|
|
plain ASCII text file named PUBLIC. The License grants you the right to
|
|
copy, modify and redistribute this file, but only under certain conditions
|
|
described in the License. Among other things, the License requires that
|
|
the copyright notice and this notice be preserved on all copies. */
|
|
|
|
#include "mysql_priv.h"
|
|
#include "sql_acl.h"
|
|
#include <m_ctype.h>
|
|
#include <nisam.h>
|
|
#include <thr_alarm.h>
|
|
#ifdef __cplusplus
|
|
extern "C" { // Because of SCO 3.2V4.2
|
|
#endif
|
|
#include <errno.h>
|
|
#include <sys/stat.h>
|
|
#ifndef __GNU_LIBRARY__
|
|
#define __GNU_LIBRARY__ // Skipp warnings in getopt.h
|
|
#endif
|
|
#include <getopt.h>
|
|
#ifdef HAVE_SYSENT
|
|
#include <sysent.h>
|
|
#endif
|
|
#ifdef HAVE_PWD_H
|
|
#include <pwd.h> // For getpwent
|
|
#endif
|
|
|
|
#ifndef __WIN32__
|
|
#include <sys/resource.h>
|
|
#ifdef HAVE_SYS_UN_H
|
|
# include <sys/un.h>
|
|
#endif
|
|
#include <netdb.h>
|
|
#ifdef HAVE_SELECT_H
|
|
# include <select.h>
|
|
#endif
|
|
#ifdef HAVE_SYS_SELECT_H
|
|
#include <sys/select.h>
|
|
#endif
|
|
#include <sys/utsname.h>
|
|
#else
|
|
#include <windows.h>
|
|
#endif // __WIN32__
|
|
#ifdef __cplusplus
|
|
}
|
|
#endif
|
|
|
|
#if defined(HAVE_LINUXTHREADS) && !defined(GLIBC2_STYLE_GETHOSTBYNAME_R)
|
|
#include <gnu/types.h>
|
|
#define THR_KILL_SIGNAL SIGINT
|
|
#else
|
|
#include <my_pthread.h> // For thr_setconcurency()
|
|
#define THR_KILL_SIGNAL SIGUSR2 // Can't use this with LinuxThreads
|
|
#endif
|
|
#if defined(HAVE_GETRLIMIT) && defined(RLIMIT_NOFILE) && !defined(__linux__) && !defined(HAVE_mit_thread)
|
|
#define SET_RLIMIT_NOFILE
|
|
#endif
|
|
|
|
#define MYSQL_KILL_SIGNAL SIGTERM
|
|
|
|
extern "C" ulong _my_cache_w_requests,_my_cache_write,_my_cache_r_requests,
|
|
_my_cache_read;
|
|
extern "C" uint _my_blocks_used,_my_blocks_changed;
|
|
extern "C" int my_file_opened,my_stream_opened;
|
|
|
|
#ifndef DBUG_OFF
|
|
#ifdef __WIN32__
|
|
static const char* default_dbug_option="d:t:i:O,\\mysqld.trace";
|
|
#else
|
|
static const char *default_dbug_option="d:t:i:o,/tmp/mysqld.trace";
|
|
#endif
|
|
#endif
|
|
|
|
#ifdef __NT__
|
|
static char szPipeName [ 257 ];
|
|
static SECURITY_ATTRIBUTES saPipeSecurity;
|
|
static SECURITY_DESCRIPTOR sdPipeDescriptor;
|
|
static HANDLE hPipe = INVALID_HANDLE_VALUE;
|
|
static pthread_cond_t COND_handler_count;
|
|
static uint handler_count;
|
|
#endif
|
|
#ifdef __WIN32__
|
|
static bool opt_console=0;
|
|
#endif
|
|
static Socket unix_sock= INVALID_SOCKET,ip_sock= INVALID_SOCKET;
|
|
static ulong back_log,connect_timeout;
|
|
static ulong opt_specialflag=SPECIAL_ENGLISH;
|
|
static ulong thread_id=1L;
|
|
static my_string opt_logname=0,opt_update_logname=0;
|
|
static char mysql_home[FN_REFLEN],pidfile_name[FN_REFLEN];
|
|
static pthread_cond_t COND_thread_count;
|
|
static pthread_attr_t connection_attrib;
|
|
static pthread_t select_thread;
|
|
static bool opt_log,opt_update_log,opt_noacl,opt_disable_networking=0,
|
|
opt_bootstrap=0;
|
|
static bool kill_in_progress=FALSE;
|
|
static struct rand_struct sql_rand;
|
|
static int cleanup_done;
|
|
static char **defaults_argv;
|
|
|
|
uint mysql_port;
|
|
uint test_flags,thread_count=0,select_errors=0;
|
|
uint thd_startup_options=OPTION_UPDATE_LOG;
|
|
uint current_pid,protocol_version=PROTOCOL_VERSION;
|
|
ulong keybuff_size,sortbuff_size,max_item_sort_length,table_cache_size,
|
|
max_join_size,join_buff_size,tmp_table_size,thread_stack,
|
|
net_wait_timeout,what_to_log= ~ (1L << (uint) COM_TIME);
|
|
bool opt_endinfo,low_priority_updates;
|
|
bool volatile abort_loop,select_thread_in_use,grant_option;
|
|
ulong refresh_version=1L; /* Increments on each reload */
|
|
ulong query_id=1L,long_query_count,long_query_time,aborted_threads,
|
|
aborted_connects;
|
|
ulong specialflag=0,opened_tables=0,created_tmp_tables=0;
|
|
ulong max_connections,max_connect_errors;
|
|
char mysql_real_data_home[FN_REFLEN],language[LIBLEN],reg_ext[FN_EXTLEN],
|
|
mysql_data_home[2],
|
|
blob_newline,f_fyllchar,max_sort_char,*mysqld_user,*mysqld_chroot;
|
|
char server_version[40]=MYSQL_SERVER_VERSION;
|
|
my_string first_keyword="first";
|
|
char **errmesg; /* Error messages */
|
|
byte last_ref[MAX_REFLENGTH]; /* Index ref of keys */
|
|
my_string mysql_unix_port=NULL,mysql_tmpdir=NULL;
|
|
ulong my_bind_addr; /* the address we bind to */
|
|
DATE_FORMAT dayord;
|
|
double log_10[32]; /* 10 potences */
|
|
I_List<THD> threads;
|
|
time_t start_time;
|
|
pthread_key(MEM_ROOT*,THR_MALLOC);
|
|
pthread_key(THD*, THR_THD);
|
|
pthread_key(NET*, THR_NET);
|
|
pthread_mutex_t LOCK_mysql_create_db, LOCK_Acl, LOCK_open, LOCK_thread_count,
|
|
LOCK_mapped_file, LOCK_status, LOCK_grant,LOCK_log;
|
|
|
|
pthread_cond_t COND_refresh;
|
|
pthread_t signal_thread;
|
|
|
|
|
|
#ifdef __WIN32__
|
|
#undef getpid
|
|
#include <process.h>
|
|
HANDLE hEventShutdown;
|
|
#include "nt_servc.h"
|
|
static NTService Service; // Service object for WinNT
|
|
#endif
|
|
|
|
static void *signal_hand(void *arg);
|
|
static void get_options(int argc,char **argv);
|
|
static char *get_relative_path(char *path);
|
|
static void fix_paths(void);
|
|
static pthread_handler_decl(handle_connections_sockets,arg);
|
|
static int bootstrap(void);
|
|
#ifdef __NT__
|
|
static pthread_handler_decl(handle_connections_namedpipes,arg);
|
|
static int get_service_parameters();
|
|
#endif
|
|
#ifdef SET_RLIMIT_NOFILE
|
|
static uint set_maximum_open_files(uint max_file_limit);
|
|
#endif
|
|
|
|
|
|
/****************************************************************************
|
|
** Code to end mysqld
|
|
****************************************************************************/
|
|
|
|
static void close_connections(void)
|
|
{
|
|
NET net;
|
|
DBUG_ENTER("close_connections");
|
|
|
|
/* kill first connection thread */
|
|
#if !defined(__WIN32__) && !defined(__EMX__)
|
|
VOID(pthread_mutex_lock(&LOCK_thread_count));
|
|
DBUG_PRINT("quit",("waiting for select thread: %lx",select_thread));
|
|
while (select_thread_in_use)
|
|
{
|
|
struct timespec abstime;
|
|
#ifndef DONT_USE_THR_ALARM
|
|
if (pthread_kill(select_thread,THR_CLIENT_ALARM))
|
|
break; // allready dead
|
|
#endif
|
|
#ifdef HAVE_TIMESPEC_TS_SEC
|
|
abstime.ts_sec=time(NULL)+1; // Bsd 2.1
|
|
abstime.ts_nsec=0;
|
|
#else
|
|
abstime.tv_sec=time(NULL)+1; // Linux or Solairs
|
|
abstime.tv_nsec=0;
|
|
#endif
|
|
VOID(pthread_cond_timedwait(&COND_thread_count,&LOCK_thread_count,
|
|
&abstime));
|
|
#ifdef AIX_3_2
|
|
if (ip_sock != INVALID_SOCKET)
|
|
{
|
|
VOID(shutdown(ip_sock,2));
|
|
VOID(closesocket(ip_sock));
|
|
VOID(shutdown(unix_sock,2));
|
|
VOID(closesocket(unix_sock));
|
|
VOID(unlink(mysql_unix_port));
|
|
ip_sock=unix_sock= INVALID_SOCKET;
|
|
}
|
|
#endif
|
|
}
|
|
VOID(pthread_mutex_unlock(&LOCK_thread_count));
|
|
#endif /* __WIN32__ */
|
|
|
|
/* Abort listening to new connections */
|
|
DBUG_PRINT("quit",("Closing sockets"));
|
|
if ( !opt_disable_networking )
|
|
{
|
|
if (ip_sock != INVALID_SOCKET)
|
|
{
|
|
VOID(shutdown(ip_sock,2));
|
|
VOID(closesocket(ip_sock));
|
|
ip_sock= INVALID_SOCKET;
|
|
}
|
|
}
|
|
#ifdef __NT__
|
|
if ( hPipe != INVALID_HANDLE_VALUE )
|
|
{
|
|
HANDLE hTempPipe = hPipe;
|
|
DBUG_PRINT( "quit", ("Closing named pipes") );
|
|
hPipe = INVALID_HANDLE_VALUE;
|
|
CancelIo( hTempPipe );
|
|
DisconnectNamedPipe( hTempPipe );
|
|
CloseHandle( hTempPipe );
|
|
}
|
|
#endif
|
|
#ifdef HAVE_SYS_UN_H
|
|
if (unix_sock != INVALID_SOCKET)
|
|
{
|
|
VOID(shutdown(unix_sock,2));
|
|
VOID(closesocket(unix_sock));
|
|
VOID(unlink(mysql_unix_port));
|
|
unix_sock= INVALID_SOCKET;
|
|
}
|
|
#endif
|
|
end_thr_alarm(); // Don't allow alarms
|
|
|
|
/* First signal all threads that it's time to die */
|
|
|
|
THD *tmp;
|
|
VOID(pthread_mutex_lock(&LOCK_thread_count)); // For unlink from list
|
|
|
|
I_List_iterator<THD> it(threads);
|
|
while ((tmp=it++))
|
|
{
|
|
DBUG_PRINT("quit",("Informing thread %ld that it's time to die",
|
|
tmp->thread_id));
|
|
tmp->killed=1;
|
|
if (tmp->mysys_var)
|
|
{
|
|
tmp->mysys_var->abort=1;
|
|
if (tmp->mysys_var->current_mutex)
|
|
{
|
|
pthread_mutex_lock(tmp->mysys_var->current_mutex);
|
|
pthread_cond_broadcast(tmp->mysys_var->current_cond);
|
|
pthread_mutex_unlock(tmp->mysys_var->current_mutex);
|
|
}
|
|
}
|
|
}
|
|
VOID(pthread_mutex_unlock(&LOCK_thread_count)); // For unlink from list
|
|
|
|
if (thread_count)
|
|
{
|
|
sleep(1); // Give threads time to die
|
|
}
|
|
|
|
/* Force remaining threads to die by closing the connection to the client */
|
|
|
|
VOID(my_net_init(&net, NET_TYPE_TCPIP, 0, (void*) 0));
|
|
for (;;)
|
|
{
|
|
DBUG_PRINT("quit",("Locking LOCK_thread_count"));
|
|
VOID(pthread_mutex_lock(&LOCK_thread_count)); // For unlink from list
|
|
if (!(tmp=threads.get()))
|
|
{
|
|
DBUG_PRINT("quit",("Unlocking LOCK_thread_count"));
|
|
VOID(pthread_mutex_unlock(&LOCK_thread_count));
|
|
break;
|
|
}
|
|
#ifndef __bsdi__ // Bug in BSDI kernel
|
|
if ((net.fd=tmp->net.fd) != INVALID_SOCKET)
|
|
{
|
|
net.nettype=tmp->net.nettype;
|
|
#ifdef __NT__
|
|
net.hPipe=tmp->net.hPipe;
|
|
#endif
|
|
sql_print_error(ER(ER_FORCING_CLOSE),my_progname,
|
|
tmp->thread_id,tmp->user);
|
|
close_connection(&net,0,0);
|
|
}
|
|
#endif
|
|
DBUG_PRINT("quit",("Unlocking LOCK_thread_count"));
|
|
VOID(pthread_mutex_unlock(&LOCK_thread_count));
|
|
}
|
|
net_end(&net);
|
|
/* All threads has now been aborted */
|
|
DBUG_PRINT("quit",("Waiting for threads to die (count=%u)",thread_count));
|
|
VOID(pthread_mutex_lock(&LOCK_thread_count));
|
|
while (thread_count)
|
|
{
|
|
VOID(pthread_cond_wait(&COND_thread_count,&LOCK_thread_count));
|
|
DBUG_PRINT("quit",("One thread died (count=%u)",thread_count));
|
|
}
|
|
VOID(pthread_mutex_unlock(&LOCK_thread_count));
|
|
|
|
mysql_log.close();
|
|
mysql_update_log.close();
|
|
DBUG_PRINT("quit",("close_connections thread"));
|
|
DBUG_VOID_RETURN;
|
|
}
|
|
|
|
/* Force server down. kill all connections and threads and exit */
|
|
|
|
#ifndef __WIN32__
|
|
static void *kill_server(void *sig_ptr)
|
|
#define RETURN_FROM_KILL_SERVER return 0
|
|
#else
|
|
static void __cdecl kill_server(int sig_ptr)
|
|
#define RETURN_FROM_KILL_SERVER return
|
|
#endif
|
|
{
|
|
int sig=(int) (long) sig_ptr; // This is passed a int
|
|
DBUG_ENTER("kill_server");
|
|
|
|
// if there is a signal during the kill in progress, we do not need
|
|
// another one
|
|
if (kill_in_progress) // Safety
|
|
RETURN_FROM_KILL_SERVER;
|
|
kill_in_progress=TRUE;
|
|
abort_loop=1;
|
|
signal(sig,SIG_IGN);
|
|
if (sig == MYSQL_KILL_SIGNAL || sig == 0)
|
|
sql_print_error(ER(ER_NORMAL_SHUTDOWN),my_progname);
|
|
else
|
|
sql_print_error(ER(ER_GOT_SIGNAL),my_progname,sig); /* purecov: inspected */
|
|
|
|
#if defined(USE_ONE_SIGNAL_HAND) && !defined(__WIN32__)
|
|
my_thread_init(); // If this is a new thread
|
|
#endif
|
|
close_connections();
|
|
sql_print_error(ER(ER_SHUTDOWN_COMPLETE),my_progname);
|
|
if (sig != MYSQL_KILL_SIGNAL && sig != 0)
|
|
unireg_abort(1); /* purecov: inspected */
|
|
else
|
|
unireg_end(0);
|
|
pthread_exit(0); /* purecov: deadcode */
|
|
RETURN_FROM_KILL_SERVER;
|
|
}
|
|
|
|
|
|
#ifdef USE_ONE_SIGNAL_HAND
|
|
pthread_handler_decl(kill_server_thread,arg)
|
|
{
|
|
my_thread_init(); // Initialize new thread
|
|
kill_server(0);
|
|
my_thread_end(); // Normally never reached
|
|
return 0;
|
|
}
|
|
#endif
|
|
|
|
static sig_handler print_signal_warning(int sig)
|
|
{
|
|
sql_print_error("Warning: Got signal %d from thread %d",
|
|
sig,my_thread_id());
|
|
#ifdef DONT_REMEMBER_SIGNAL
|
|
sigset(sig,print_signal_warning); /* int. thread system calls */
|
|
#endif
|
|
#ifndef __WIN32__
|
|
if (sig == SIGALRM)
|
|
alarm(2); /* reschedule alarm */
|
|
#endif
|
|
}
|
|
|
|
|
|
void unireg_end(int signal_number)
|
|
{
|
|
clean_up();
|
|
exit(0);
|
|
}
|
|
|
|
|
|
void unireg_abort(int exit_code)
|
|
{
|
|
sql_print_error("Aborting\n");
|
|
clean_up(); /* purecov: inspected */
|
|
exit(exit_code); /* purecov: inspected */
|
|
}
|
|
|
|
|
|
void clean_up(void)
|
|
{
|
|
DBUG_PRINT("exit",("clean_up"));
|
|
if (cleanup_done++)
|
|
return; /* purecov: inspected */
|
|
acl_free(1);
|
|
grant_free();
|
|
table_cache_free();
|
|
hostname_cache_free();
|
|
item_user_lock_free();
|
|
lex_free(); /* Free some memory */
|
|
#ifdef HAVE_DLOPEN
|
|
if (!opt_noacl)
|
|
udf_free();
|
|
#endif
|
|
end_key_cache(); /* This is usualy freed automaticly*/
|
|
VOID(ha_panic(HA_PANIC_CLOSE)); /* close all hash,misam and p_isam */
|
|
x_free((gptr) errmsg[ERRMAPP]); /* Free messages */
|
|
free_defaults(defaults_argv);
|
|
my_free(mysql_tmpdir,MYF(0));
|
|
my_end(opt_endinfo ? MY_CHECK_ERROR | MY_GIVE_INFO : 0);
|
|
} /* clean_up */
|
|
|
|
|
|
|
|
/****************************************************************************
|
|
** Init IP and UNIX socket
|
|
****************************************************************************/
|
|
|
|
static void set_ports()
|
|
{
|
|
char *env;
|
|
if (!mysql_port)
|
|
{ // Get port if not from commandline
|
|
struct servent *serv_ptr;
|
|
mysql_port = MYSQL_PORT;
|
|
if ((serv_ptr = getservbyname("mysql", "tcp")))
|
|
mysql_port = ntohs((u_short) serv_ptr->s_port); /* purecov: inspected */
|
|
if ((env = getenv("MYSQL_TCP_PORT")))
|
|
mysql_port = (uint) atoi(env); /* purecov: inspected */
|
|
}
|
|
if (!mysql_unix_port)
|
|
{
|
|
#ifdef __WIN32__
|
|
mysql_unix_port = MYSQL_NAMEDPIPE;
|
|
#else
|
|
mysql_unix_port = MYSQL_UNIX_ADDR;
|
|
#endif
|
|
if ((env = getenv("MYSQL_UNIX_PORT")))
|
|
mysql_unix_port = env; /* purecov: inspected */
|
|
}
|
|
}
|
|
|
|
/* Change to run as another user if started with --user */
|
|
|
|
static void set_user(const char *user)
|
|
{
|
|
#ifndef __WIN32__
|
|
struct passwd *ent;
|
|
|
|
// don't bother if we aren't superuser
|
|
if(geteuid())
|
|
return;
|
|
|
|
if(!(ent = getpwnam(user)))
|
|
{
|
|
sql_perror("getpwnam");
|
|
unireg_abort(1);
|
|
}
|
|
|
|
if (setuid(ent->pw_uid) == -1)
|
|
{
|
|
sql_perror("setuid");
|
|
unireg_abort(1);
|
|
}
|
|
#endif
|
|
}
|
|
|
|
/* Change root user if started with --chroot */
|
|
|
|
static void set_root(const char *path)
|
|
{
|
|
#if !defined(__WIN32__) && !defined(__EMX__)
|
|
if (chroot(path) == -1)
|
|
{
|
|
sql_perror("chroot");
|
|
unireg_abort(1);
|
|
}
|
|
#endif
|
|
}
|
|
|
|
static void server_init(void)
|
|
{
|
|
struct sockaddr_in IPaddr;
|
|
#ifdef HAVE_SYS_UN_H
|
|
struct sockaddr_un UNIXaddr;
|
|
#endif
|
|
int arg=1;
|
|
DBUG_ENTER("server_init");
|
|
|
|
#ifdef __WIN32__
|
|
if ( !opt_disable_networking )
|
|
{
|
|
WSADATA WsaData;
|
|
if (SOCKET_ERROR == WSAStartup (0x0101, &WsaData))
|
|
{
|
|
my_message(0,"WSAStartup Failed\n",MYF(0));
|
|
unireg_abort(1);
|
|
}
|
|
}
|
|
#endif /* __WIN32__ */
|
|
|
|
set_ports();
|
|
|
|
if (mysql_port != 0 && !opt_disable_networking && !opt_bootstrap)
|
|
{
|
|
DBUG_PRINT("general",("IP Socket is %d",mysql_port));
|
|
ip_sock = socket(AF_INET, SOCK_STREAM, 0);
|
|
if (ip_sock == INVALID_SOCKET)
|
|
{
|
|
DBUG_PRINT("error",("Got error: %d from socket()",socket_errno));
|
|
sql_perror(ER(ER_IPSOCK_ERROR)); /* purecov: tested */
|
|
unireg_abort(1); /* purecov: tested */
|
|
}
|
|
bzero((char*) &IPaddr, sizeof(IPaddr));
|
|
IPaddr.sin_family = AF_INET;
|
|
IPaddr.sin_addr.s_addr = my_bind_addr;
|
|
IPaddr.sin_port = (unsigned short) htons((unsigned short) mysql_port);
|
|
(void) setsockopt(ip_sock,SOL_SOCKET,SO_REUSEADDR,(char*)&arg,sizeof(arg));
|
|
for(;;)
|
|
{
|
|
if (bind(ip_sock, (struct sockaddr *)&IPaddr, sizeof(IPaddr)) >= 0)
|
|
break;
|
|
DBUG_PRINT("error",("Got error: %d from bind",socket_errno));
|
|
sql_perror("Can't start server: Bind on TCP/IP port");/* Had a loop here */
|
|
sql_print_error("Do you already have another mysqld server running on port: %d ?",mysql_port);
|
|
unireg_abort(1);
|
|
}
|
|
VOID(listen(ip_sock,(int) back_log));
|
|
}
|
|
|
|
if (mysqld_chroot)
|
|
set_root(mysqld_chroot);
|
|
if (mysqld_user)
|
|
set_user(mysqld_user);
|
|
|
|
#ifdef __NT__
|
|
/* create named pipe */
|
|
if (Service.IsNT() && mysql_unix_port[0] && !opt_bootstrap)
|
|
{
|
|
sprintf( szPipeName, "\\\\.\\pipe\\%s", mysql_unix_port );
|
|
ZeroMemory( &saPipeSecurity, sizeof(saPipeSecurity) );
|
|
ZeroMemory( &sdPipeDescriptor, sizeof(sdPipeDescriptor) );
|
|
if ( !InitializeSecurityDescriptor(&sdPipeDescriptor,
|
|
SECURITY_DESCRIPTOR_REVISION) )
|
|
{
|
|
sql_perror("Can't start server : Initialize security descriptor");
|
|
unireg_abort(1);
|
|
}
|
|
if (!SetSecurityDescriptorDacl(&sdPipeDescriptor, TRUE, NULL, FALSE))
|
|
{
|
|
sql_perror("Can't start server : Set security descriptor");
|
|
unireg_abort(1);
|
|
}
|
|
saPipeSecurity.nLength = sizeof( SECURITY_ATTRIBUTES );
|
|
saPipeSecurity.lpSecurityDescriptor = &sdPipeDescriptor;
|
|
saPipeSecurity.bInheritHandle = FALSE;
|
|
if ((hPipe = CreateNamedPipe(szPipeName,
|
|
PIPE_ACCESS_DUPLEX,
|
|
PIPE_TYPE_BYTE |
|
|
PIPE_READMODE_BYTE |
|
|
PIPE_WAIT,
|
|
PIPE_UNLIMITED_INSTANCES,
|
|
(int) net_buffer_length,
|
|
(int) net_buffer_length,
|
|
NMPWAIT_USE_DEFAULT_WAIT,
|
|
&saPipeSecurity )) == INVALID_HANDLE_VALUE)
|
|
{
|
|
LPVOID lpMsgBuf;
|
|
int error=GetLastError();
|
|
FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER |
|
|
FORMAT_MESSAGE_FROM_SYSTEM,
|
|
NULL, error, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
|
|
(LPTSTR) &lpMsgBuf, 0, NULL );
|
|
MessageBox( NULL, (LPTSTR) lpMsgBuf, "Error from CreateNamedPipe",
|
|
MB_OK|MB_ICONINFORMATION );
|
|
LocalFree( lpMsgBuf );
|
|
unireg_abort(1);
|
|
}
|
|
}
|
|
#endif
|
|
|
|
#if defined(HAVE_SYS_UN_H) && !defined(HAVE_mit_thread)
|
|
/*
|
|
** Create the UNIX socket
|
|
*/
|
|
if (mysql_unix_port[0] && !opt_bootstrap)
|
|
{
|
|
DBUG_PRINT("general",("UNIX Socket is %s",mysql_unix_port));
|
|
|
|
if ((unix_sock = socket(AF_UNIX, SOCK_STREAM, 0)) < 0)
|
|
{
|
|
sql_perror("Can't start server : UNIX Socket "); /* purecov: inspected */
|
|
unireg_abort(1); /* purecov: inspected */
|
|
}
|
|
bzero((char*) &UNIXaddr, sizeof(UNIXaddr));
|
|
UNIXaddr.sun_family = AF_UNIX;
|
|
strmov(UNIXaddr.sun_path, mysql_unix_port);
|
|
VOID(unlink(mysql_unix_port));
|
|
(void) setsockopt(unix_sock,SOL_SOCKET,SO_REUSEADDR,(char*)&arg,sizeof(arg));
|
|
umask(0);
|
|
if (bind(unix_sock, (struct sockaddr *)&UNIXaddr, sizeof(UNIXaddr)) < 0)
|
|
{
|
|
sql_perror("Can't start server : Bind on unix socket"); /* purecov: tested */
|
|
sql_print_error("Do you already have another mysqld server running on socket: %s ?",mysql_unix_port);
|
|
unireg_abort(1); /* purecov: tested */
|
|
}
|
|
umask(((~my_umask) & 0666));
|
|
#if defined(S_IFSOCK) && defined(SECURE_SOCKETS)
|
|
VOID(chmod(mysql_unix_port,S_IFSOCK)); /* Fix solaris 2.6 bug */
|
|
#endif
|
|
chmod(mysql_unix_port,0700);
|
|
VOID(listen(unix_sock,(int) back_log));
|
|
}
|
|
#endif
|
|
DBUG_PRINT("info",("server started"));
|
|
DBUG_VOID_RETURN;
|
|
}
|
|
|
|
|
|
void yyerror(char *s)
|
|
{
|
|
NET *net=my_pthread_getspecific_ptr(NET*,THR_NET);
|
|
char *yytext=(char*) current_lex->tok_start;
|
|
net_printf(net,ER_PARSE_ERROR, s, yytext ? (char*) yytext : "",
|
|
current_lex->yylineno);
|
|
}
|
|
|
|
|
|
void close_connection(NET *net,uint errcode,bool lock)
|
|
{
|
|
Socket fd;
|
|
DBUG_ENTER("close_connection");
|
|
DBUG_PRINT("enter",("fd: %ld error: '%s'",
|
|
(ulong) net->fd,
|
|
errcode ? ER(errcode) : ""));
|
|
if (lock)
|
|
VOID(pthread_mutex_lock(&LOCK_thread_count));
|
|
if ((fd=net->fd) != INVALID_SOCKET)
|
|
{
|
|
if (errcode)
|
|
send_error(net,errcode,ER(errcode)); /* purecov: inspected */
|
|
net->fd= INVALID_SOCKET; // Marker
|
|
#ifdef __NT__
|
|
if (net->nettype == NET_TYPE_NAMEDPIPE)
|
|
{
|
|
HANDLE hPipe = net->hPipe;
|
|
if ( hPipe != INVALID_HANDLE_VALUE )
|
|
{
|
|
net->hPipe = INVALID_HANDLE_VALUE;
|
|
CancelIo( hPipe );
|
|
DisconnectNamedPipe( hPipe );
|
|
CloseHandle( hPipe );
|
|
}
|
|
}
|
|
else
|
|
#endif
|
|
{
|
|
VOID(shutdown(fd,2));
|
|
VOID(closesocket(fd));
|
|
}
|
|
net_end(net);
|
|
}
|
|
if (lock)
|
|
VOID(pthread_mutex_unlock(&LOCK_thread_count));
|
|
DBUG_VOID_RETURN;
|
|
}
|
|
|
|
/* Called when a thread is aborted */
|
|
/* ARGSUSED */
|
|
|
|
sig_handler end_thread(int sig __attribute__((unused)))
|
|
{
|
|
THD *thd=current_thd;
|
|
DBUG_ENTER("end_thread");
|
|
if (thd)
|
|
{
|
|
VOID(pthread_mutex_lock(&LOCK_thread_count));
|
|
free_root(&thd->alloc);
|
|
thread_count--;
|
|
delete thd;
|
|
VOID(pthread_cond_signal(&COND_thread_count)); /* Tell main we are ready */
|
|
VOID(pthread_mutex_unlock(&LOCK_thread_count));
|
|
#ifndef DBUG_OFF
|
|
if (!(test_flags & TEST_NO_THREADS)) // For debugging under Linux
|
|
#endif
|
|
{
|
|
my_thread_end();
|
|
pthread_exit(0);
|
|
}
|
|
}
|
|
DBUG_VOID_RETURN; /* purecov: deadcode */
|
|
}
|
|
|
|
/*
|
|
** Aborts a thread nicely. Commes here on SIGPIPE
|
|
** TODO: One should have to fix that thr_alarm know about this
|
|
** thread too
|
|
*/
|
|
|
|
#ifdef THREAD_SPECIFIC_SIGPIPE
|
|
static sig_handler abort_thread(int sig __attribute__((unused)))
|
|
{
|
|
THD *thd=current_thd;
|
|
DBUG_ENTER("abort_thread");
|
|
if (thd)
|
|
thd->killed=1;
|
|
DBUG_VOID_RETURN;
|
|
}
|
|
#endif
|
|
|
|
/******************************************************************************
|
|
** Setup a signal thread with handles all signals
|
|
** Because linux doesn't support scemas use a mutex to check that
|
|
** the signal thread is ready before continuing
|
|
******************************************************************************/
|
|
|
|
#ifdef __WIN32__
|
|
static void init_signals(void)
|
|
{
|
|
int signals[7] = {SIGINT,SIGILL,SIGFPE,SIGSEGV,SIGTERM,SIGABRT } ;
|
|
for (uint i=0 ; i < 7 ; i++)
|
|
signal( signals[i], kill_server) ;
|
|
signal(SIGBREAK,SIG_IGN); //ignore SIGBREAK for NT
|
|
}
|
|
|
|
#elif defined(__EMX__)
|
|
static void sig_reload(int signo)
|
|
{
|
|
reload_acl_and_cache(~0); // Flush everything
|
|
signal(signo, SIG_ACK);
|
|
}
|
|
|
|
static void sig_kill(int signo)
|
|
{
|
|
if (!abort_loop)
|
|
{
|
|
abort_loop=1; // mark abort for threads
|
|
kill_server((void*) signo);
|
|
}
|
|
signal(signo, SIG_ACK);
|
|
}
|
|
|
|
static void init_signals(void)
|
|
{
|
|
signal(SIGQUIT, sig_kill);
|
|
signal(SIGKILL, sig_kill);
|
|
signal(SIGTERM, sig_kill);
|
|
signal(SIGINT, sig_kill);
|
|
signal(SIGHUP, sig_reload); // Flush everything
|
|
signal(SIGALRM, SIG_IGN);
|
|
signal(SIGBREAK,SIG_IGN);
|
|
signal_thread = pthread_self();
|
|
}
|
|
#else
|
|
|
|
static void init_signals(void)
|
|
{
|
|
sigset_t set;
|
|
pthread_attr_t thr_attr;
|
|
int error;
|
|
DBUG_ENTER("init_signals");
|
|
|
|
(void) sigset(THR_KILL_SIGNAL,end_thread);
|
|
(void) sigset(THR_SERVER_ALARM,print_signal_warning); // Should never be called!
|
|
#ifdef THREAD_SPECIFIC_SIGPIPE
|
|
(void) sigset(SIGPIPE,abort_thread);
|
|
sigaddset(&set,SIGPIPE);
|
|
#else
|
|
VOID(signal(SIGPIPE,SIG_IGN)); // Can't know which thread
|
|
#endif
|
|
(void) sigemptyset(&set);
|
|
sigaddset(&set,SIGINT);
|
|
sigaddset(&set,SIGQUIT);
|
|
sigaddset(&set,SIGTERM);
|
|
sigaddset(&set,SIGHUP);
|
|
signal(SIGTERM,SIG_DFL); // If it's blocked by parent
|
|
#ifdef SIGTSTP
|
|
sigaddset(&set,SIGTSTP);
|
|
#endif
|
|
sigaddset(&set,THR_SERVER_ALARM);
|
|
sigdelset(&set,THR_KILL_SIGNAL); // May be SIGINT
|
|
sigdelset(&set,THR_CLIENT_ALARM); // For alarms
|
|
(void) pthread_sigmask(SIG_SETMASK,&set,NULL);
|
|
|
|
VOID(pthread_attr_init(&thr_attr));
|
|
pthread_attr_setscope(&thr_attr,PTHREAD_SCOPE_SYSTEM);
|
|
VOID(pthread_attr_setdetachstate(&thr_attr,PTHREAD_CREATE_DETACHED));
|
|
if (!(opt_specialflag & SPECIAL_NO_PRIOR))
|
|
my_pthread_attr_setprio(&thr_attr,INTERRUPT_PRIOR);
|
|
pthread_attr_setstacksize(&thr_attr,32768);
|
|
|
|
VOID(pthread_mutex_lock(&LOCK_thread_count));
|
|
if ((error=pthread_create(&signal_thread,&thr_attr,signal_hand,0)))
|
|
{
|
|
sql_print_error("Can't create interrupt-thread (error %d, errno: %d)",
|
|
error,errno);
|
|
exit(1);
|
|
}
|
|
VOID(pthread_cond_wait(&COND_thread_count,&LOCK_thread_count));
|
|
pthread_mutex_unlock(&LOCK_thread_count);
|
|
|
|
VOID(pthread_attr_destroy(&thr_attr));
|
|
DBUG_VOID_RETURN;
|
|
}
|
|
|
|
|
|
/*
|
|
** This threads handles all signals and alarms
|
|
*/
|
|
|
|
/* ARGSUSED */
|
|
static void *signal_hand(void *arg __attribute__((unused)))
|
|
{
|
|
sigset_t set;
|
|
int sig;
|
|
my_thread_init(); // Init new thread
|
|
DBUG_ENTER("signal_hand");
|
|
|
|
init_thr_alarm(max_connections+3); // Setup alarm handler
|
|
#if SIGINT != THR_KILL_SIGNAL
|
|
(void) sigemptyset(&set); // Setup up SIGINT for debug
|
|
(void) sigaddset(&set,SIGINT); // For debugging
|
|
(void) pthread_sigmask(SIG_UNBLOCK,&set,NULL);
|
|
#endif
|
|
(void) sigemptyset(&set); // Setup up SIGINT for debug
|
|
#ifdef USE_ONE_SIGNAL_HAND
|
|
(void) sigaddset(&set,THR_SERVER_ALARM); // For alarms
|
|
#endif
|
|
(void) sigaddset(&set,SIGQUIT);
|
|
(void) sigaddset(&set,SIGTERM);
|
|
#if THR_CLIENT_ALARM != SIGHUP
|
|
(void) sigaddset(&set,SIGHUP);
|
|
#endif
|
|
(void) sigaddset(&set,SIGTSTP);
|
|
|
|
/* Save pid to this process (or thread on Linux) */
|
|
{
|
|
FILE *pidFile;
|
|
if ((pidFile = my_fopen(pidfile_name,O_WRONLY,MYF(MY_WME))))
|
|
{
|
|
fprintf(pidFile,"%lu",(ulong) getpid());
|
|
(void) my_fclose(pidFile,MYF(0));
|
|
(void) chmod(pidfile_name,0644);
|
|
}
|
|
}
|
|
(void) pthread_mutex_lock(&LOCK_thread_count);
|
|
(void) pthread_cond_signal(&COND_thread_count); /* continue init_signals */
|
|
pthread_mutex_unlock(&LOCK_thread_count);
|
|
|
|
for (;;)
|
|
{
|
|
int error;
|
|
while ((error=my_sigwait(&set,&sig)) == EINTR) ;
|
|
if (cleanup_done)
|
|
pthread_exit(0); // Safety
|
|
switch (sig) {
|
|
case SIGTERM:
|
|
case SIGQUIT:
|
|
case SIGKILL:
|
|
DBUG_PRINT("info",("Got signal: %d abort_loop: %d",sig,abort_loop));
|
|
if (!abort_loop)
|
|
{
|
|
abort_loop=1; // mark abort for threads
|
|
#ifdef USE_ONE_SIGNAL_HAND
|
|
pthread_t tmp;
|
|
if (!(opt_specialflag & SPECIAL_NO_PRIOR))
|
|
my_pthread_attr_setprio(&connection_attrib,INTERRUPT_PRIOR);
|
|
if (pthread_create(&tmp,&connection_attrib, kill_server_thread,
|
|
(void*) sig))
|
|
sql_print_error("Error: Can't create thread to kill server");
|
|
#else
|
|
kill_server((void*) sig); // MIT THREAD has a alarm thread
|
|
#endif
|
|
}
|
|
break;
|
|
case SIGHUP:
|
|
reload_acl_and_cache(~0); // Flush everything
|
|
mysql_print_status(); // Send debug some info
|
|
break;
|
|
#ifdef USE_ONE_SIGNAL_HAND
|
|
case THR_SERVER_ALARM:
|
|
process_alarm(sig); // Trigger alarms.
|
|
break;
|
|
#endif
|
|
default:
|
|
#ifdef EXTRA_DEBUG
|
|
sql_print_error("Warning: Got signal: %d, error: %d",sig,error); /* purecov: tested */
|
|
#endif
|
|
break; /* purecov: tested */
|
|
}
|
|
}
|
|
return(0); /* purecov: deadcode */
|
|
}
|
|
|
|
#endif /* __WIN32__*/
|
|
|
|
|
|
/* ARGSUSED */
|
|
static int my_message_sql(uint my_error, const char *str,
|
|
myf MyFlags __attribute__((unused)))
|
|
{
|
|
NET *net;
|
|
DBUG_ENTER("my_message_sql");
|
|
DBUG_PRINT("error",("Message: '%s'",str));
|
|
if ((net=my_pthread_getspecific_ptr(NET*,THR_NET)))
|
|
{
|
|
if (!net->last_error[0]) // Return only first message
|
|
{
|
|
strmake(net->last_error,str,sizeof(net->last_error)-1);
|
|
net->last_errno=my_error ? my_error : ER_UNKNOWN_ERROR;
|
|
}
|
|
}
|
|
else
|
|
sql_print_error("%s: %s",my_progname,str); /* purecov: inspected */
|
|
DBUG_RETURN(0);
|
|
}
|
|
|
|
#ifdef __WIN32__
|
|
#undef errno
|
|
#undef EINTR
|
|
#define errno WSAGetLastError()
|
|
#define EINTR WSAEINTR
|
|
|
|
struct utsname
|
|
{
|
|
char nodename[FN_REFLEN];
|
|
};
|
|
|
|
int uname(struct utsname *a)
|
|
{
|
|
return -1;
|
|
}
|
|
#endif
|
|
|
|
|
|
#ifdef __WIN32__
|
|
pthread_handler_decl(handle_shutdown,arg)
|
|
{
|
|
MSG msg;
|
|
my_thread_init();
|
|
|
|
/* this call should create the message queue for this thread */
|
|
PeekMessage(&msg, NULL, 1, 65534,PM_NOREMOVE);
|
|
|
|
if (WaitForSingleObject(hEventShutdown,INFINITE)==WAIT_OBJECT_0)
|
|
kill_server(MYSQL_KILL_SIGNAL);
|
|
return 0;
|
|
}
|
|
|
|
int __stdcall handle_kill(ulong ctrl_type)
|
|
{
|
|
if (ctrl_type == CTRL_CLOSE_EVENT ||
|
|
ctrl_type == CTRL_SHUTDOWN_EVENT)
|
|
{
|
|
kill_server(MYSQL_KILL_SIGNAL);
|
|
return TRUE;
|
|
}
|
|
return FALSE;
|
|
}
|
|
#endif
|
|
|
|
my_string load_default_groups[]= { "mysqld","server",0 };
|
|
|
|
#ifdef __WIN32__
|
|
int win_main(int argc, char **argv)
|
|
#else
|
|
int main(int argc, char **argv)
|
|
#endif
|
|
{
|
|
DEBUGGER_OFF;
|
|
char hostname[FN_REFLEN];
|
|
|
|
if(getuid() || geteuid())
|
|
{ fprintf(stderr,"Access denied\n");
|
|
exit(1);
|
|
}
|
|
|
|
my_umask=0660; // Default umask for new files
|
|
MY_INIT(argv[0]); // init my_sys library & pthreads
|
|
|
|
start_time=time((time_t*) 0);
|
|
if (gethostname(hostname,sizeof(hostname)-4) < 0)
|
|
strmov(hostname,"mysql");
|
|
strxmov(pidfile_name,hostname,".pid",NullS);
|
|
#ifndef DBUG_OFF
|
|
strcat(server_version,"-debug");
|
|
#endif
|
|
load_defaults("my",load_default_groups,&argc,&argv);
|
|
defaults_argv=argv;
|
|
mysql_tmpdir=getenv("TMPDIR"); /* Use this if possible */
|
|
#ifdef __WIN32__
|
|
if (!mysql_tmpdir)
|
|
mysql_tmpdir=getenv("TEMP");
|
|
if (!mysql_tmpdir)
|
|
mysql_tmpdir=getenv("TMP");
|
|
#endif
|
|
if (!mysql_tmpdir)
|
|
mysql_tmpdir=P_tmpdir; /* purecov: inspected */
|
|
|
|
#ifdef __NT__
|
|
/* service parameters can be overwritten by options */
|
|
if (get_service_parameters())
|
|
{
|
|
my_message( 0, "Can't read MySQL service parameters", MYF(0) );
|
|
exit( 1 );
|
|
}
|
|
#endif
|
|
get_options(argc,argv);
|
|
if (opt_log || opt_update_log)
|
|
strcat(server_version,"-log");
|
|
DBUG_PRINT("info",("%s Ver %s for %s on %s\n",my_progname,
|
|
server_version, SYSTEM_TYPE,MACHINE_TYPE));
|
|
|
|
if (!(opt_specialflag & SPECIAL_NO_PRIOR))
|
|
my_pthread_setprio(pthread_self(),CONNECT_PRIOR);
|
|
/* Parameter for threads created for connections */
|
|
VOID(pthread_attr_init(&connection_attrib));
|
|
VOID(pthread_attr_setdetachstate(&connection_attrib,
|
|
PTHREAD_CREATE_DETACHED));
|
|
pthread_attr_setstacksize(&connection_attrib,thread_stack);
|
|
|
|
if (!(opt_specialflag & SPECIAL_NO_PRIOR))
|
|
my_pthread_attr_setprio(&connection_attrib,WAIT_PRIOR);
|
|
pthread_attr_setscope(&connection_attrib, PTHREAD_SCOPE_SYSTEM);
|
|
|
|
VOID(pthread_cond_init(&COND_thread_count,NULL));
|
|
VOID(pthread_mutex_init(&LOCK_mysql_create_db,NULL));
|
|
VOID(pthread_mutex_init(&LOCK_Acl,NULL));
|
|
VOID(pthread_mutex_init(&LOCK_grant,NULL));
|
|
VOID(pthread_mutex_init(&LOCK_open,NULL));
|
|
VOID(pthread_mutex_init(&LOCK_thread_count,NULL));
|
|
VOID(pthread_mutex_init(&LOCK_mapped_file,NULL));
|
|
VOID(pthread_mutex_init(&LOCK_status,NULL));
|
|
VOID(pthread_mutex_init(&LOCK_log,NULL));
|
|
VOID(pthread_cond_init(&COND_refresh,NULL));
|
|
|
|
#ifdef SET_RLIMIT_NOFILE
|
|
/* connections and databases neads lots of files */
|
|
{
|
|
uint wanted_files=10+(uint) max(max_connections*5,
|
|
max_connections+table_cache_size*2);
|
|
uint files=set_maximum_open_files(wanted_files);
|
|
if (files && files < wanted_files) // Some systems return 0
|
|
{
|
|
max_connections= (ulong) (files-10)/5;
|
|
table_cache_size= (ulong) (files-10-max_connections)/2;
|
|
DBUG_PRINT("warning",
|
|
("Changed limits: max_connections: %ld table_cache: %ld",
|
|
max_connections,table_cache_size));
|
|
sql_print_error("Warning: Changed limits: max_connections: %ld table_cache: %ld",max_connections,table_cache_size);
|
|
}
|
|
}
|
|
#endif
|
|
unireg_init(opt_specialflag); /* Set up extern variabels */
|
|
init_errmessage(); /* Read error messages from file */
|
|
lex_init();
|
|
item_init();
|
|
mysys_uses_curses=0;
|
|
#ifdef USE_REGEX
|
|
regex_init();
|
|
#endif
|
|
select_thread=pthread_self();
|
|
select_thread_in_use=1;
|
|
|
|
/*
|
|
** We have enough space for fiddling with the argv, continue
|
|
*/
|
|
umask(((~my_umask) & 0666));
|
|
if (my_setwd(mysql_real_data_home,MYF(MY_WME)))
|
|
{
|
|
unireg_abort(1); /* purecov: inspected */
|
|
}
|
|
mysql_data_home[0]=FN_CURLIB; // all paths are relative from here
|
|
mysql_data_home[1]=0;
|
|
server_init();
|
|
table_cache_init();
|
|
hostname_cache_init();
|
|
randominit(&sql_rand,(ulong) start_time,(ulong) start_time/2);
|
|
|
|
/* Setup log files */
|
|
if (opt_log)
|
|
{
|
|
char tmp[FN_REFLEN];
|
|
if (!opt_logname)
|
|
{
|
|
strmov(strnmov(tmp,hostname,FN_REFLEN-5),".log");
|
|
opt_logname=tmp;
|
|
}
|
|
mysql_log.open(opt_logname,MYSQL_LOG::NORMAL);
|
|
}
|
|
if (opt_update_log)
|
|
mysql_update_log.open(opt_update_logname ? opt_update_logname :
|
|
hostname,MYSQL_LOG::NEW);
|
|
#ifdef __WIN32__
|
|
#define MYSQL_ERR_FILE "mysql.err"
|
|
if (!opt_console)
|
|
{
|
|
freopen(MYSQL_ERR_FILE,"a+",stdout);
|
|
freopen(MYSQL_ERR_FILE,"a+",stderr);
|
|
FreeConsole(); // Remove window
|
|
}
|
|
#endif
|
|
|
|
/*
|
|
init signals & alarm
|
|
After this we can't quit by a simple unireg_abort
|
|
*/
|
|
error_handler_hook = my_message_sql;
|
|
if (pthread_key_create(&THR_THD,NULL) || pthread_key_create(&THR_NET,NULL) ||
|
|
pthread_key_create(&THR_MALLOC,NULL))
|
|
{
|
|
sql_print_error(0,"Can't create thread-keys",MYF(0));
|
|
exit(1);
|
|
}
|
|
init_signals();
|
|
if (acl_init(opt_noacl))
|
|
{
|
|
select_thread_in_use=0;
|
|
(void) pthread_kill(signal_thread,MYSQL_KILL_SIGNAL);
|
|
(void) my_delete(pidfile_name,MYF(0)); // Not neaded anymore
|
|
exit(1);
|
|
}
|
|
if (!opt_noacl && !(specialflag & SPECIAL_NO_NEW_FUNC))
|
|
(void) grant_init();
|
|
|
|
#ifdef HAVE_DLOPEN
|
|
if (!opt_noacl)
|
|
udf_init();
|
|
#endif
|
|
|
|
if (opt_bootstrap)
|
|
exit(bootstrap());
|
|
#ifdef HAVE_THR_SETCONCURRENCY
|
|
VOID(thr_setconcurrency(20)); // We are iobound
|
|
#endif
|
|
#ifdef __WIN32__ //IRENA
|
|
{
|
|
hEventShutdown=CreateEvent(0, FALSE, FALSE, "MySqlShutdown");
|
|
pthread_t hThread;
|
|
if (pthread_create(&hThread,&connection_attrib,handle_shutdown,0))
|
|
sql_print_error("Warning: Can't create thread to handle shutdown requests");
|
|
|
|
// On "Stop Service" we have to do regular shutdown
|
|
Service.SetShutdownEvent(hEventShutdown);
|
|
}
|
|
#endif
|
|
|
|
printf(ER(ER_READY),my_progname,server_version,"");
|
|
fflush(stdout);
|
|
|
|
#ifdef __NT__
|
|
if (hPipe == INVALID_HANDLE_VALUE && !have_tcpip)
|
|
{
|
|
sql_print_error("TCP/IP must be installed on Win98 platforms");
|
|
}
|
|
else
|
|
{
|
|
pthread_mutex_lock(&LOCK_thread_count);
|
|
VOID(pthread_cond_init(&COND_handler_count,NULL));
|
|
{
|
|
pthread_t hThread;
|
|
handler_count=0;
|
|
if ( hPipe != INVALID_HANDLE_VALUE )
|
|
{
|
|
handler_count++;
|
|
if (pthread_create(&hThread,&connection_attrib,
|
|
handle_connections_namedpipes, 0))
|
|
{
|
|
sql_print_error("Warning: Can't create thread to handle named pipes");
|
|
handler_count--;
|
|
}
|
|
}
|
|
if (have_tcpip)
|
|
{
|
|
handler_count++;
|
|
if (pthread_create(&hThread,&connection_attrib,
|
|
handle_connections_sockets, 0))
|
|
{
|
|
sql_print_error("Warning: Can't create thread to handle named pipes");
|
|
handler_count--;
|
|
}
|
|
}
|
|
while (handler_count > 0)
|
|
{
|
|
pthread_cond_wait(&COND_handler_count,&LOCK_thread_count);
|
|
}
|
|
}
|
|
pthread_mutex_unlock(&LOCK_thread_count);
|
|
}
|
|
#else
|
|
handle_connections_sockets(0);
|
|
#endif /* __NT__ */
|
|
|
|
VOID(pthread_attr_destroy(&connection_attrib));
|
|
(void) my_delete(pidfile_name,MYF(0)); // Not neaded anymore
|
|
|
|
DBUG_PRINT("quit",("Exiting main thread"));
|
|
my_thread_end();
|
|
|
|
#ifndef __WIN32__
|
|
VOID(pthread_mutex_lock(&LOCK_thread_count));
|
|
select_thread_in_use=0; // For close_connections
|
|
VOID(pthread_cond_signal(&COND_thread_count));
|
|
VOID(pthread_mutex_unlock(&LOCK_thread_count));
|
|
#else
|
|
// remove the event, because it will not be valid anymore
|
|
Service.SetShutdownEvent(0);
|
|
if(hEventShutdown) CloseHandle(hEventShutdown);
|
|
// if it was started as service on NT try to stop the service
|
|
if(Service.IsNT())
|
|
Service.Stop();
|
|
#endif
|
|
|
|
pthread_exit(0);
|
|
return(0); /* purecov: deadcode */
|
|
}
|
|
|
|
|
|
#ifdef __WIN32__
|
|
/* ------------------------------------------------------------------------
|
|
main and thread entry function for Win32
|
|
(all this is needed only to run mysqld as a service on WinNT)
|
|
-------------------------------------------------------------------------- */
|
|
int mysql_service(void *p)
|
|
{
|
|
win_main(Service.my_argc, Service.my_argv);
|
|
return 0;
|
|
}
|
|
|
|
int main(int argc, char **argv)
|
|
{
|
|
// check environment variable OS
|
|
if (Service.GetOS()) // "OS" defined; Should be NT
|
|
{
|
|
if (argc == 2)
|
|
{
|
|
if (!strcmp(argv[1],"-install") || !strcmp(argv[1],"--install"))
|
|
{
|
|
char path[FN_REFLEN];
|
|
my_path(path, argv[0], ""); // Find name in path
|
|
fn_format(path,argv[0],path,"",1+4+16); // Force use of full path
|
|
if (!Service.Install("MySql","MySql",path))
|
|
MessageBox(NULL,"Failed to install Service","MySql",
|
|
MB_OK|MB_ICONSTOP);
|
|
return 0;
|
|
}
|
|
else if (!strcmp(argv[1],"-remove") || !strcmp(argv[1],"--remove"))
|
|
{
|
|
Service.Remove("MySql");
|
|
return 0;
|
|
}
|
|
}
|
|
else if (argc == 1) // No arguments; start as a service
|
|
{
|
|
// init service
|
|
long tmp=Service.Init("MySql",mysql_service);
|
|
return 0;
|
|
}
|
|
}
|
|
|
|
// This is a WIN95 machine or a start of mysqld as a standalone program
|
|
// we have to pass the arguments, in case of NT-service this will be done
|
|
// by ServiceMain()
|
|
|
|
Service.my_argc=argc;
|
|
Service.my_argv=argv;
|
|
mysql_service(NULL);
|
|
return 0;
|
|
}
|
|
/* ------------------------------------------------------------------------ */
|
|
#endif
|
|
|
|
|
|
static int bootstrap()
|
|
{
|
|
THD *thd= new THD;
|
|
int error;
|
|
thd->bootstrap=1;
|
|
thd->client_capabilities=0;
|
|
my_net_init(&thd->net,NET_TYPE_TCPIP, -1, 0);
|
|
thd->max_packet_length=thd->net.max_packet;
|
|
thd->master_access=~0;
|
|
thread_count++;
|
|
thd->real_id=pthread_self();
|
|
error=handle_bootstrap(thd);
|
|
net_end(&thd->net);
|
|
delete thd;
|
|
end_thr_alarm(); // Don't allow alarms
|
|
(void) my_delete(pidfile_name,MYF(0)); // Not neaded anymore
|
|
clean_up();
|
|
return error ? 1 : 0;
|
|
}
|
|
|
|
|
|
static void create_new_thread(THD *thd)
|
|
{
|
|
DBUG_ENTER("create_new_thread");
|
|
|
|
NET *net=&thd->net; // For easy ref
|
|
net->timeout = (uint) connect_timeout; // Timeout for read
|
|
if (protocol_version > 9)
|
|
net->return_errno=1;
|
|
|
|
/* don't allow too many connections */
|
|
if (thread_count >= max_connections+1 || abort_loop)
|
|
{
|
|
DBUG_PRINT("error",("too many connections"));
|
|
close_connection(net,ER_CON_COUNT_ERROR);
|
|
delete thd;
|
|
DBUG_VOID_RETURN;
|
|
}
|
|
|
|
if (pthread_mutex_lock(&LOCK_thread_count))
|
|
{
|
|
DBUG_PRINT("error",("Can't lock LOCK_thread_count"));
|
|
close_connection(net,ER_OUT_OF_RESOURCES);
|
|
delete thd;
|
|
DBUG_VOID_RETURN;
|
|
}
|
|
thd->thread_id=thread_id++;
|
|
for (uint i=0; i < 8 ; i++) // Generate password teststring
|
|
thd->scramble[i]= (char) (rnd(&sql_rand)*94+33);
|
|
thd->scramble[8]=0;
|
|
thd->rand=sql_rand;
|
|
threads.append(thd);
|
|
|
|
/* Start a new thread to handle connection */
|
|
|
|
#ifndef DBUG_OFF
|
|
if (test_flags & TEST_NO_THREADS) // For debugging under Linux
|
|
{
|
|
thread_count++;
|
|
thd->real_id=pthread_self();
|
|
VOID(pthread_mutex_unlock(&LOCK_thread_count));
|
|
handle_one_connection((void*) thd);
|
|
}
|
|
else
|
|
#endif
|
|
{
|
|
int error;
|
|
if ((error=pthread_create(&thd->real_id,&connection_attrib,
|
|
handle_one_connection,
|
|
(void*) thd)))
|
|
{
|
|
DBUG_PRINT("error",
|
|
("Can't create thread to handle request (error %d)",
|
|
error));
|
|
thd->killed=1; // Safety
|
|
VOID(pthread_mutex_unlock(&LOCK_thread_count));
|
|
net_printf(net,ER_CANT_CREATE_THREAD,error);
|
|
VOID(pthread_mutex_lock(&LOCK_thread_count));
|
|
close_connection(net,0,0);
|
|
delete thd;
|
|
VOID(pthread_mutex_unlock(&LOCK_thread_count));
|
|
DBUG_VOID_RETURN;
|
|
}
|
|
thread_count++;
|
|
VOID(pthread_mutex_unlock(&LOCK_thread_count));
|
|
}
|
|
DBUG_PRINT("info",(("Thread created")));
|
|
DBUG_VOID_RETURN;
|
|
}
|
|
|
|
|
|
/* Handle new connections and spawn new process to handle them */
|
|
|
|
pthread_handler_decl(handle_connections_sockets,arg)
|
|
{
|
|
Socket sock,new_sock;
|
|
uint error_count=0;
|
|
uint max_used_connection= (uint) (max(ip_sock,unix_sock)+1);
|
|
fd_set readFDs,clientFDs;
|
|
THD *thd;
|
|
struct sockaddr_in cAddr;
|
|
int ip_flags=0,socket_flags=0,flags;
|
|
#ifdef __WIN32__
|
|
my_thread_init();
|
|
#endif
|
|
DBUG_ENTER("handle_connections_sockets");
|
|
|
|
LINT_INIT(new_sock);
|
|
|
|
(void) my_pthread_getprio(pthread_self()); // For debugging
|
|
|
|
FD_ZERO(&clientFDs);
|
|
if (ip_sock != INVALID_SOCKET)
|
|
{
|
|
FD_SET(ip_sock,&clientFDs);
|
|
#ifdef HAVE_FCNTL
|
|
ip_flags = fcntl(ip_sock, F_GETFL, 0);
|
|
#endif
|
|
}
|
|
#ifdef HAVE_SYS_UN_H
|
|
FD_SET(unix_sock,&clientFDs);
|
|
socket_flags=fcntl(unix_sock, F_GETFL, 0);
|
|
#endif
|
|
|
|
DBUG_PRINT("general",("Waiting for connections."));
|
|
while (!abort_loop)
|
|
{
|
|
memcpy(&readFDs,&clientFDs,sizeof(readFDs));
|
|
#ifdef HPUX
|
|
if (select(max_used_connection,(int*) &readFDs,0,0,0) < 0)
|
|
continue;
|
|
#else
|
|
if (select((int) max_used_connection,&readFDs,0,0,0) < 0)
|
|
{
|
|
if (errno != EINTR)
|
|
{
|
|
if (!select_errors++ && !abort_loop) /* purecov: inspected */
|
|
sql_print_error("mysqld: Got error %d from select",errno); /* purecov: inspected */
|
|
}
|
|
continue;
|
|
}
|
|
#endif /* HPUX */
|
|
if (abort_loop)
|
|
break;
|
|
|
|
/*
|
|
** Is this a new connection request
|
|
*/
|
|
|
|
#ifdef HAVE_SYS_UN_H
|
|
if (FD_ISSET(unix_sock,&readFDs))
|
|
{
|
|
sock = unix_sock;
|
|
flags= socket_flags;
|
|
}
|
|
else
|
|
#endif
|
|
{
|
|
sock = ip_sock;
|
|
flags= ip_flags;
|
|
}
|
|
|
|
#if !defined(NO_FCNTL_NONBLOCK)
|
|
if (!(test_flags & TEST_BLOCKING))
|
|
{
|
|
#if defined(O_NONBLOCK)
|
|
fcntl(sock, F_SETFL, flags | O_NONBLOCK);
|
|
#elif defined(O_NDELAY)
|
|
fcntl(sock, F_SETFL, flags | O_NDELAY);
|
|
#endif
|
|
}
|
|
#endif /* NO_FCNTL_NONBLOCK */
|
|
for (uint retry=0; retry < MAX_ACCEPT_RETRY; retry++)
|
|
{
|
|
size_socket length=sizeof(struct sockaddr_in);
|
|
new_sock = accept(sock, (struct sockaddr *)&cAddr, &length);
|
|
if (new_sock != INVALID_SOCKET || (errno != EINTR && errno != EAGAIN))
|
|
break;
|
|
#if !defined(NO_FCNTL_NONBLOCK)
|
|
if (!(test_flags & TEST_BLOCKING))
|
|
{
|
|
if (retry == MAX_ACCEPT_RETRY - 1)
|
|
fcntl(sock, F_SETFL, flags); // Try without O_NONBLOCK
|
|
}
|
|
#endif
|
|
}
|
|
#if !defined(NO_FCNTL_NONBLOCK)
|
|
if (!(test_flags & TEST_BLOCKING))
|
|
fcntl(sock, F_SETFL, flags);
|
|
#endif
|
|
if (new_sock < 0)
|
|
{
|
|
if ((error_count++ & 255) == 0) // This can happen often
|
|
sql_perror("Error in accept");
|
|
if (errno == ENFILE || errno == EMFILE)
|
|
sleep(1); // Give other threads some time
|
|
continue;
|
|
}
|
|
{
|
|
size_socket dummyLen;
|
|
struct sockaddr dummy;
|
|
dummyLen = sizeof(struct sockaddr);
|
|
if (getsockname(new_sock,&dummy, &dummyLen) < 0)
|
|
{
|
|
sql_perror("Error on new connection socket");
|
|
VOID(shutdown(new_sock,2));
|
|
VOID(closesocket(new_sock));
|
|
continue;
|
|
}
|
|
}
|
|
|
|
/*
|
|
** Don't allow too many connections
|
|
*/
|
|
|
|
if (!(thd= new THD))
|
|
{
|
|
VOID(shutdown(new_sock,2)); VOID(closesocket(new_sock));
|
|
continue;
|
|
}
|
|
#ifdef __WIN32__
|
|
if (my_net_init(&thd->net, NET_TYPE_TCPIP, new_sock, 0))
|
|
#else
|
|
if (my_net_init(&thd->net,
|
|
new_sock == unix_sock ? NET_TYPE_SOCKET : NET_TYPE_TCPIP,
|
|
new_sock, 0))
|
|
#endif
|
|
{
|
|
VOID(shutdown(new_sock,2)); VOID(closesocket(new_sock));
|
|
delete thd;
|
|
continue;
|
|
}
|
|
if (sock == unix_sock)
|
|
{
|
|
if (!(thd->host=my_strdup(LOCAL_HOST,MYF(0))))
|
|
{
|
|
close_connection(&thd->net,ER_OUT_OF_RESOURCES);
|
|
delete thd;
|
|
continue;
|
|
}
|
|
}
|
|
create_new_thread(thd);
|
|
}
|
|
|
|
#ifdef __NT__
|
|
pthread_mutex_lock(&LOCK_thread_count);
|
|
handler_count--;
|
|
pthread_cond_signal(&COND_handler_count);
|
|
pthread_mutex_unlock(&LOCK_thread_count);
|
|
#endif
|
|
DBUG_RETURN(0);
|
|
}
|
|
|
|
|
|
#ifdef __NT__
|
|
pthread_handler_decl(handle_connections_namedpipes,arg)
|
|
{
|
|
HANDLE hConnectedPipe;
|
|
BOOL fConnected;
|
|
THD *thd;
|
|
my_thread_init();
|
|
DBUG_ENTER("handle_connections_namedpipes");
|
|
(void) my_pthread_getprio(pthread_self()); // For debugging
|
|
|
|
DBUG_PRINT("general",("Waiting for named pipe connections."));
|
|
while (!abort_loop)
|
|
{
|
|
/* wait for named pipe connection */
|
|
fConnected = ConnectNamedPipe( hPipe, NULL );
|
|
if (abort_loop)
|
|
break;
|
|
if ( !fConnected )
|
|
fConnected = GetLastError() == ERROR_PIPE_CONNECTED;
|
|
if ( !fConnected )
|
|
{
|
|
CloseHandle( hPipe );
|
|
if ((hPipe = CreateNamedPipe(szPipeName,
|
|
PIPE_ACCESS_DUPLEX,
|
|
PIPE_TYPE_BYTE |
|
|
PIPE_READMODE_BYTE |
|
|
PIPE_WAIT,
|
|
PIPE_UNLIMITED_INSTANCES,
|
|
(int) net_buffer_length,
|
|
(int) net_buffer_length,
|
|
NMPWAIT_USE_DEFAULT_WAIT,
|
|
&saPipeSecurity )) ==
|
|
INVALID_HANDLE_VALUE )
|
|
{
|
|
sql_perror("Can't create new named pipe!");
|
|
continue;
|
|
}
|
|
}
|
|
hConnectedPipe = hPipe;
|
|
/* create new pipe for new connection */
|
|
if ((hPipe = CreateNamedPipe(szPipeName,
|
|
PIPE_ACCESS_DUPLEX,
|
|
PIPE_TYPE_BYTE |
|
|
PIPE_READMODE_BYTE |
|
|
PIPE_WAIT,
|
|
PIPE_UNLIMITED_INSTANCES,
|
|
(int) net_buffer_length,
|
|
(int) net_buffer_length,
|
|
NMPWAIT_USE_DEFAULT_WAIT,
|
|
&saPipeSecurity)) ==
|
|
INVALID_HANDLE_VALUE)
|
|
{
|
|
sql_perror("Can't create new named pipe!");
|
|
DisconnectNamedPipe( hConnectedPipe );
|
|
CloseHandle( hConnectedPipe );
|
|
continue; // We have to try again
|
|
}
|
|
|
|
if ( !(thd = new THD))
|
|
{
|
|
DisconnectNamedPipe( hConnectedPipe );
|
|
CloseHandle( hConnectedPipe );
|
|
continue;
|
|
}
|
|
if (my_net_init(&thd->net, NET_TYPE_NAMEDPIPE, (Socket) 0,
|
|
&hConnectedPipe))
|
|
{
|
|
close_connection(&thd->net,ER_OUT_OF_RESOURCES);
|
|
delete thd;
|
|
continue;
|
|
}
|
|
/* host name is unknown */
|
|
thd->host = NULL;
|
|
create_new_thread(thd);
|
|
}
|
|
|
|
pthread_mutex_lock(&LOCK_thread_count);
|
|
handler_count--;
|
|
pthread_cond_signal(&COND_handler_count);
|
|
pthread_mutex_unlock(&LOCK_thread_count);
|
|
DBUG_RETURN(0);
|
|
}
|
|
#endif /* __NT__ */
|
|
|
|
|
|
|
|
/******************************************************************************
|
|
** handle start options
|
|
******************************************************************************/
|
|
|
|
enum options {OPT_ISAM_LOG=256,OPT_SKIP_NEW,OPT_SKIP_GRANT,
|
|
OPT_SKIP_LOCK,OPT_ENABLE_LOCK,
|
|
OPT_USE_LOCKING,OPT_SOCKET,OPT_UPDATE_LOG,
|
|
OPT_SKIP_RESOLVE,OPT_SKIP_NETWORKING,
|
|
OPT_BIND_ADDRESS,OPT_PID_FILE,OPT_SKIP_PRIOR,OPT_BIG_TABLES,
|
|
OPT_STANDALONE,OPT_ONE_THREAD,OPT_CONSOLE,
|
|
OPT_LOW_PRIORITY_UPDATES,OPT_SKIP_HOST_CACHE,OPT_LONG_FORMAT,
|
|
OPT_FLUSH, OPT_SAFE, OPT_BOOTSTRAP};
|
|
|
|
static struct option long_options[] =
|
|
{
|
|
{"basedir", required_argument, 0, 'b'},
|
|
{"big-tables", no_argument,0,(int) OPT_BIG_TABLES},
|
|
{"bind-address", required_argument, 0, OPT_BIND_ADDRESS},
|
|
{"bootstrap", no_argument,0,(int) OPT_BOOTSTRAP},
|
|
#ifdef __WIN32__
|
|
{"console", no_argument, 0, OPT_CONSOLE},
|
|
#endif
|
|
{"chroot", required_argument,0, 'r'},
|
|
{"datadir", required_argument, 0, 'h'},
|
|
#ifndef DBUG_OFF
|
|
{"debug", optional_argument, 0, '#'},
|
|
#endif
|
|
{"enable-locking", no_argument, 0, (int) OPT_ENABLE_LOCK},
|
|
{"exit-info", optional_argument, 0, 'T'},
|
|
#ifdef __WIN32__
|
|
{"flush", no_argument, 0, OPT_FLUSH},
|
|
#endif
|
|
{"help", no_argument, 0, '?'},
|
|
{"log", optional_argument, 0, 'l'},
|
|
{"language", required_argument, 0, 'L'},
|
|
{"log-isam", optional_argument, 0, (int) OPT_ISAM_LOG},
|
|
{"log-update",optional_argument, 0, (int) OPT_UPDATE_LOG},
|
|
{"log-long-format",no_argument, 0, (int) OPT_LONG_FORMAT},
|
|
{"low-priority-insert", no_argument, 0, (int) OPT_LOW_PRIORITY_UPDATES},
|
|
{"new", no_argument, 0, 'n'},
|
|
{"old-protocol", no_argument, 0, 'o'},
|
|
{"one-thread", no_argument, 0, OPT_ONE_THREAD},
|
|
{"pid-file", required_argument, 0, (int) OPT_PID_FILE},
|
|
{"port", required_argument, 0, 'P'},
|
|
{"safe-mode", no_argument, 0, (int) OPT_SAFE},
|
|
{"socket", required_argument, 0, (int) OPT_SOCKET},
|
|
{"set-variable",required_argument, 0, 'O'},
|
|
{"skip-grant-tables", no_argument,0,(int) OPT_SKIP_GRANT},
|
|
{"skip-locking", no_argument,0,(int) OPT_SKIP_LOCK},
|
|
{"skip-host-cache", no_argument,0,(int) OPT_SKIP_HOST_CACHE},
|
|
{"skip-name-resolve", no_argument,0,(int) OPT_SKIP_RESOLVE},
|
|
{"skip-new", no_argument, 0, (int) OPT_SKIP_NEW},
|
|
{"skip-networking", no_argument,0, (int) OPT_SKIP_NETWORKING},
|
|
{"skip-thread-priority", no_argument,0,(int) OPT_SKIP_PRIOR},
|
|
{"standalone", no_argument,0, (int) OPT_STANDALONE},
|
|
{"tmpdir", required_argument ,0, 't'},
|
|
{"use-locking", no_argument,0,(int) OPT_USE_LOCKING},
|
|
{"user", required_argument,0, 'u'},
|
|
{"version", no_argument, 0, 'V'},
|
|
{0, 0, 0, 0}
|
|
};
|
|
|
|
CHANGEABLE_VAR changeable_vars[] = {
|
|
{ "back_log", (long*) &back_log,5,1,65535,0,1},
|
|
{ "connect_timeout", (long*) &connect_timeout,CONNECT_TIMEOUT,1,65535,0,1},
|
|
{ "join_buffer", (long*) &join_buff_size,128*1024L,
|
|
IO_SIZE*2+MALLOC_OVERHEAD,~0L,MALLOC_OVERHEAD,IO_SIZE },
|
|
{ "key_buffer", (long*) &keybuff_size,KEY_CACHE_SIZE,MALLOC_OVERHEAD,
|
|
(long) ~0, MALLOC_OVERHEAD, IO_SIZE },
|
|
{ "long_query_time", (long*) &long_query_time,10,1,~0L,0,1},
|
|
{ "max_allowed_packet",(long*) &max_allowed_packet,1024*1024L,16384,~0L,
|
|
MALLOC_OVERHEAD,1024},
|
|
{ "max_connections", (long*) &max_connections,90,1,16384,0,1},
|
|
{ "max_connect_errors", (long*) &max_connect_errors,MAX_CONNECT_ERRORS,1,
|
|
~0L,0,1},
|
|
{ "max_join_size",(long*) &max_join_size,~0L,1,~0L,0,1},
|
|
{ "max_sort_length",(long*) &max_item_sort_length,1024,4,8192*1024L,0,1},
|
|
{ "net_buffer_length",(long*) &net_buffer_length,16384,1024,1024*1024L,
|
|
MALLOC_OVERHEAD,1024},
|
|
{ "record_buffer", (long*) &my_default_record_cache_size,128*1024L,
|
|
IO_SIZE*2+MALLOC_OVERHEAD,~0L,MALLOC_OVERHEAD,IO_SIZE },
|
|
{ "sort_buffer", (long*) &sortbuff_size,MAX_SORT_MEMORY,
|
|
MIN_SORT_MEMORY+MALLOC_OVERHEAD,~0L,MALLOC_OVERHEAD,1 },
|
|
{ "table_cache", (long*) &table_cache_size,64,1,16384,0,1},
|
|
{ "tmp_table_size", (long*) &tmp_table_size,1024*1024L,1024,~0L,
|
|
MALLOC_OVERHEAD,1},
|
|
{ "thread_stack", (long*) &thread_stack,1024*64,1024*32,~0L,0,1024},
|
|
{ "wait_timeout", (long*) &net_wait_timeout,NET_WAIT_TIMEOUT,1,~0L,0,1},
|
|
{ NullS,(long*) 0,0,0,0,0,0,} };
|
|
|
|
|
|
struct show_var_st init_vars[]= {
|
|
{"back_log", (char*) &back_log, SHOW_LONG},
|
|
{"connect_timeout", (char*) &connect_timeout, SHOW_LONG},
|
|
{"basedir", mysql_home,SHOW_CHAR},
|
|
{"datadir", mysql_real_data_home,SHOW_CHAR},
|
|
{"join_buffer", (char*) &join_buff_size, SHOW_LONG},
|
|
#ifdef __WIN32__
|
|
{"flush", (char*) &nisam_flush, SHOW_MY_BOOL},
|
|
#endif
|
|
{"key_buffer", (char*) &keybuff_size, SHOW_LONG},
|
|
{"language", language, SHOW_CHAR},
|
|
{"log", (char*) &opt_log, SHOW_BOOL},
|
|
{"long_query_time", (char*) &long_query_time, SHOW_LONG},
|
|
{"low_priority_updates", (char*) &low_priority_updates, SHOW_BOOL},
|
|
{"max_allowed_packet", (char*) &max_allowed_packet, SHOW_LONG},
|
|
{"max_connections", (char*) &max_connections, SHOW_LONG},
|
|
{"max_connect_errors", (char*) &max_connect_errors, SHOW_LONG},
|
|
{"max_join_size", (char*) &max_join_size, SHOW_LONG},
|
|
{"max_sort_length", (char*) &max_item_sort_length,SHOW_LONG},
|
|
{"net_buffer_length", (char*) &net_buffer_length, SHOW_LONG},
|
|
{"port", (char*) &mysql_port, SHOW_INT},
|
|
{"record_buffer", (char*) &my_default_record_cache_size,SHOW_LONG},
|
|
{"skip_locking", (char*) &my_disable_locking, SHOW_MY_BOOL},
|
|
{"socket", (char*) &mysql_unix_port, SHOW_CHAR_PTR},
|
|
{"sort_buffer", (char*) &sortbuff_size,SHOW_LONG},
|
|
{"table_cache", (char*) &table_cache_size,SHOW_LONG},
|
|
{"thread_stack", (char*) &thread_stack,SHOW_LONG},
|
|
{"tmp_table_size", (char*) &tmp_table_size,SHOW_LONG},
|
|
{"tmpdir",(char*) &mysql_tmpdir,SHOW_CHAR_PTR},
|
|
{"update_log",(char*) &opt_update_log,SHOW_BOOL},
|
|
{"wait_timeout",(char*) &net_wait_timeout,SHOW_LONG},
|
|
{NullS,NullS,SHOW_LONG}
|
|
};
|
|
|
|
struct show_var_st status_vars[]= {
|
|
{"Aborted_clients", (char*) &aborted_threads, SHOW_LONG},
|
|
{"Aborted_connects", (char*) &aborted_connects, SHOW_LONG},
|
|
{"Created_tmp_tables", (char*) &created_tmp_tables, SHOW_LONG},
|
|
{"Deletes", (char*) &ha_delete_count, SHOW_LONG},
|
|
{"Flush_commands", (char*) &refresh_version, SHOW_LONG_CONST},
|
|
{"Key_blocks_used", (char*) &_my_blocks_used, SHOW_LONG},
|
|
{"Key_read_requests", (char*) &_my_cache_r_requests, SHOW_LONG},
|
|
{"Key_reads", (char*) &_my_cache_read, SHOW_LONG},
|
|
{"Key_write_requests", (char*) &_my_cache_w_requests, SHOW_LONG},
|
|
{"Key_writes", (char*) &_my_cache_write, SHOW_LONG},
|
|
{"Not_flushed_key_blocks", (char*) &_my_blocks_changed, SHOW_LONG_CONST},
|
|
{"Open_tables", (char*) 0, SHOW_OPENTABLES},
|
|
{"Open_files", (char*) &my_file_opened, SHOW_LONG_CONST},
|
|
{"Open_streams", (char*) &my_stream_opened, SHOW_LONG_CONST},
|
|
{"Opened_tables", (char*) &opened_tables, SHOW_LONG},
|
|
{"Questions", (char*) 0, SHOW_QUESTION},
|
|
{"Read_key", (char*) &ha_read_key_count, SHOW_LONG},
|
|
{"Read_next", (char*) &ha_read_next_count, SHOW_LONG},
|
|
{"Read_rnd", (char*) &ha_read_rnd_count, SHOW_LONG},
|
|
{"Read_first", (char*) &ha_read_first_count, SHOW_LONG},
|
|
{"Running_threads", (char*) &thread_count, SHOW_LONG_CONST},
|
|
{"Slow_queries", (char*) &long_query_count, SHOW_LONG},
|
|
{"Uptime", (char*) 0, SHOW_STARTTIME},
|
|
{"Write", (char*) &ha_write_count, SHOW_LONG},
|
|
{NullS,NullS,SHOW_LONG}
|
|
};
|
|
|
|
static void print_version(void)
|
|
{
|
|
printf("%s Ver %s for %s on %s\n",my_progname,
|
|
server_version,SYSTEM_TYPE,MACHINE_TYPE);
|
|
}
|
|
|
|
static void usage(void)
|
|
{
|
|
print_version();
|
|
puts("Copyright (C) 1979-1998 TcX AB & Monty Program KB & Detron HB.");
|
|
puts("All rights reserved. Se the file PUBLIC for licence information.");
|
|
puts("This software comes with ABSOLUTELY NO WARRANTY: see the file PUBLIC for details.\n");
|
|
puts("Starts the mysql server\n");
|
|
|
|
printf("Usage: %s [OPTIONS]\n", my_progname);
|
|
puts("\n\
|
|
-b, --basedir=path Path to installation directory. All paths are\n\
|
|
usually resolved relative to this\n\
|
|
--big-tables Allow big result sets by saving all temporary sets\n\
|
|
on file (Solves most 'table full' errors)\n\
|
|
--bind-address=IP Ip address to bind to\n\
|
|
--bootstrap Used by mysql installation scripts\n\
|
|
--chroot=path Chroot mysqld daemon during startup\n\
|
|
-h, --datadir=path Path to the database root");
|
|
#ifndef DBUG_OFF
|
|
printf("\
|
|
-#, --debug[=...] Debug log. Default is '%s'\n",default_dbug_option);
|
|
#endif
|
|
puts("\
|
|
--enable-locking Enable system locking\n\
|
|
-T, --exit-info Print some debug info at exit\n\
|
|
-?, --help Display this help and exit\n\
|
|
-L, --language=... Client error messages in given language. May be\n\
|
|
given as a full path\n\
|
|
-l, --log[=file] Log connections and queries to file\n\
|
|
--log-update[=file] Log updates to file.# where # is a unique number\n\
|
|
if not given.\n\
|
|
--log-isam[=file] Log all isam changes to file\n\
|
|
--log-long-format Log some extra information to update log\n\
|
|
--low-priorty-insert Inserts has lower priority than selects\n\
|
|
--pid-file=path Pid file used by safe_mysqld\n\
|
|
-P, --port=... Port number to use for connection\n\
|
|
-n, --new Use very new possible 'unsafe' functions\n\
|
|
-o, --old-protocol Use the old (3.20) protocol\n\
|
|
--one-thread Only use one thread (for debugging under Linux)\n\
|
|
-O, --set-variable var=option\n\
|
|
Give a variable an value. --help lists variables\n\
|
|
-Sg, --skip-grant-tables\n\
|
|
Start without grant tables. This gives all users\n\
|
|
FULL ACCESS to all tables!\n\
|
|
--safe-mode Skip some optimize stages (for testing)\n\
|
|
--skip-locking Don't use system locking. To use isamchk one has\n\
|
|
to shut down the server.\n\
|
|
--skip-name-resolve Don't resolve hostnames.\n\
|
|
All hostnames are IP's or 'localhost'\n\
|
|
--skip-networking Don't allow connection with TCP/IP.\n\
|
|
--skip-new Don't use new, possible wrong routines.\n\
|
|
--skip-host-cache Don't cache host names\n\
|
|
--skip-thread-priority\n\
|
|
Don't give threads different priorities.\n\
|
|
--socket=... Socket file to use for connection\n\
|
|
-t, --tmpdir=path Path for temporary files\n\
|
|
--user=user_name Run mysqld daemon as user\n\
|
|
-V, --version output version information and exit\n");
|
|
#ifdef __WIN32__
|
|
puts("NT and Win32 specific options:\n\
|
|
--console Don't remove the console window\n\
|
|
--flush Flush tables to disk between SQL commands\n\
|
|
--install Install mysqld as a service (NT)\n\
|
|
--remove Remove mysqld from the service list (NT)\n\
|
|
--standalone Dummy option to start as a standalone program (NT)\n\
|
|
");
|
|
#endif
|
|
|
|
fix_paths();
|
|
set_ports();
|
|
printf("\
|
|
To see what values a running MySQL server is using, type\n\
|
|
'mysqladmin variables' instead of 'mysqld --help'.\n\
|
|
The default values (after parsing the command line arguments) are:\n\n");
|
|
|
|
printf("basedir: %s\n",mysql_home);
|
|
printf("datadir: %s\n",mysql_real_data_home);
|
|
printf("tmpdir: %s\n",mysql_tmpdir);
|
|
printf("language: %s\n",language);
|
|
printf("pid file: %s\n",pidfile_name);
|
|
if (opt_logname)
|
|
printf("logfile: %s\n",opt_logname);
|
|
if (opt_update_logname)
|
|
printf("update log: %s\n",opt_update_logname);
|
|
printf("TCP port: %d\n",mysql_port);
|
|
#if defined(HAVE_SYS_UN_H) && !defined(HAVE_mit_thread)
|
|
printf("Unix socket: %s\n",mysql_unix_port);
|
|
#endif
|
|
if (my_disable_locking)
|
|
puts("\nsystem locking is not in use");
|
|
if (opt_noacl)
|
|
puts("\nGrant tables are not used. All users have full access rights");
|
|
printf("\nPossible variables for option --set-variable (-O) are:\n");
|
|
for (uint i=0 ; changeable_vars[i].name ; i++)
|
|
printf("%-20s current value: %lu\n",
|
|
changeable_vars[i].name,
|
|
(ulong) *changeable_vars[i].varptr);
|
|
}
|
|
|
|
|
|
static void set_options(void)
|
|
{
|
|
char* tmpenv;
|
|
|
|
set_all_changeable_vars( changeable_vars );
|
|
#if !defined( my_pthread_setprio ) && !defined( HAVE_PTHREAD_SETSCHEDPARAM )
|
|
opt_specialflag |= SPECIAL_NO_PRIOR;
|
|
#endif
|
|
|
|
(void) strmov( language, LANGUAGE);
|
|
(void) strmov( mysql_real_data_home, get_relative_path(DATADIR));
|
|
if ( !(tmpenv = getenv("MY_BASEDIR_VERSION")) )
|
|
tmpenv = DEFAULT_MYSQL_HOME;
|
|
(void) strmov( mysql_home, tmpenv );
|
|
#if defined( HAVE_mit_thread ) || defined( __WIN32__ ) || defined( HAVE_LINUXTHREADS )
|
|
my_disable_locking = 1;
|
|
#endif
|
|
my_bind_addr = htonl( INADDR_ANY );
|
|
}
|
|
|
|
/* Initiates DEBUG - but no debugging here ! */
|
|
|
|
static void get_options(int argc,char **argv)
|
|
{
|
|
int c,option_index=0;
|
|
|
|
#ifndef __NT__
|
|
set_options();
|
|
#endif
|
|
|
|
while ((c=getopt_long(argc,argv,"b:h:#::T::?l::L:O:P:S::t:u:noVvI?",
|
|
long_options, &option_index)) != EOF)
|
|
{
|
|
switch(c) {
|
|
#ifndef DBUG_OFF
|
|
case '#':
|
|
DBUG_PUSH(optarg ? optarg : default_dbug_option);
|
|
opt_endinfo=1; /* unireg: memory allocation */
|
|
break;
|
|
#endif
|
|
case 'b':
|
|
strmov(mysql_home,optarg);
|
|
break;
|
|
case 'l':
|
|
opt_log=1;
|
|
opt_logname=optarg; // Use hostname.log if null
|
|
break;
|
|
case 'h':
|
|
strmov(mysql_real_data_home,optarg);
|
|
break;
|
|
case 'L':
|
|
strmov(language,optarg);
|
|
break;
|
|
case 'n':
|
|
opt_specialflag|= SPECIAL_NEW_FUNC;
|
|
break;
|
|
case 'o':
|
|
protocol_version=PROTOCOL_VERSION-1;
|
|
break;
|
|
case 'O':
|
|
if (set_changeable_var(optarg, changeable_vars))
|
|
{
|
|
usage();
|
|
exit(1);
|
|
}
|
|
break;
|
|
case 'P':
|
|
mysql_port= (unsigned int) atoi(optarg);
|
|
break;
|
|
case OPT_SOCKET:
|
|
mysql_unix_port= optarg;
|
|
break;
|
|
case 'r':
|
|
mysqld_chroot=optarg;
|
|
break;
|
|
case 't':
|
|
mysql_tmpdir=optarg;
|
|
break;
|
|
case 'u':
|
|
mysqld_user=optarg;
|
|
break;
|
|
case 'v':
|
|
case 'V':
|
|
print_version();
|
|
exit(0);
|
|
case 'I':
|
|
case '?':
|
|
usage();
|
|
exit(0);
|
|
case 'T':
|
|
test_flags= optarg ? (uint) atoi(optarg) : (uint) ~0;
|
|
opt_endinfo=1;
|
|
break;
|
|
case 'S':
|
|
if (!optarg)
|
|
opt_specialflag|= SPECIAL_NO_NEW_FUNC | SPECIAL_SAFE_MODE;
|
|
else if (!strcmp(optarg,"l"))
|
|
my_disable_locking=1;
|
|
else if (!strcmp(optarg,"g"))
|
|
opt_noacl=1;
|
|
else
|
|
{
|
|
usage();
|
|
exit(1);
|
|
}
|
|
break;
|
|
case (int) OPT_BIG_TABLES:
|
|
thd_startup_options|=OPTION_BIG_TABLES;
|
|
break;
|
|
case (int) OPT_ISAM_LOG:
|
|
if (optarg)
|
|
nisam_log_filename=optarg;
|
|
(void) ni_log(1);
|
|
break;
|
|
case (int) OPT_UPDATE_LOG:
|
|
opt_update_log=1;
|
|
opt_update_logname=optarg; // Use hostname.# if null
|
|
break;
|
|
case (int) OPT_SKIP_NEW:
|
|
opt_specialflag|= SPECIAL_NO_NEW_FUNC;
|
|
break;
|
|
case (int) OPT_SAFE:
|
|
opt_specialflag|= SPECIAL_SAFE_MODE;
|
|
break;
|
|
case (int) OPT_SKIP_PRIOR:
|
|
opt_specialflag|= SPECIAL_NO_PRIOR;
|
|
break;
|
|
case (int) OPT_SKIP_GRANT:
|
|
opt_noacl=1;
|
|
break;
|
|
case (int) OPT_SKIP_LOCK:
|
|
my_disable_locking=1;
|
|
break;
|
|
case (int) OPT_SKIP_HOST_CACHE:
|
|
opt_specialflag|= SPECIAL_NO_HOST_CACHE;
|
|
break;
|
|
case (int) OPT_ENABLE_LOCK:
|
|
my_disable_locking=0;
|
|
break;
|
|
case (int) OPT_USE_LOCKING:
|
|
my_disable_locking=0;
|
|
break;
|
|
case (int) OPT_SKIP_RESOLVE:
|
|
opt_specialflag|=SPECIAL_NO_RESOLVE;
|
|
break;
|
|
case (int) OPT_LONG_FORMAT:
|
|
opt_specialflag|=SPECIAL_LONG_LOG_FORMAT;
|
|
break;
|
|
case (int) OPT_SKIP_NETWORKING:
|
|
opt_disable_networking=1;
|
|
mysql_port=0;
|
|
break;
|
|
case (int) OPT_ONE_THREAD:
|
|
test_flags |= TEST_NO_THREADS;
|
|
break;
|
|
case (int) OPT_BIND_ADDRESS:
|
|
if (optarg && isdigit(optarg[0]))
|
|
{
|
|
my_bind_addr = (ulong) inet_addr(optarg);
|
|
}
|
|
else
|
|
{
|
|
struct hostent *ent;
|
|
if (!optarg || !optarg[0])
|
|
ent=gethostbyname(optarg);
|
|
else
|
|
{
|
|
char myhostname[255];
|
|
if (gethostname(myhostname,sizeof(myhostname)) < 0)
|
|
{
|
|
sql_perror("Can't start server: cannot get my own hostname!");
|
|
exit(1);
|
|
}
|
|
ent=gethostbyname(myhostname);
|
|
}
|
|
if (!ent)
|
|
{
|
|
sql_perror("Can't start server: cannot resolve hostname!");
|
|
exit(1);
|
|
}
|
|
my_bind_addr = (ulong) ((in_addr*)ent->h_addr_list[0])->s_addr;
|
|
}
|
|
break;
|
|
case (int) OPT_PID_FILE:
|
|
strmov(pidfile_name,optarg);
|
|
break;
|
|
case (int) OPT_STANDALONE: /* Dummy option for NT */
|
|
break;
|
|
#ifdef __WIN32__
|
|
case (int) OPT_CONSOLE:
|
|
opt_console=1;
|
|
break;
|
|
case (int) OPT_FLUSH:
|
|
nisam_flush=1;
|
|
break;
|
|
#endif
|
|
case OPT_LOW_PRIORITY_UPDATES:
|
|
thd_startup_options|=OPTION_LOW_PRIORITY_UPDATES;
|
|
low_priority_updates=1;
|
|
break;
|
|
case OPT_BOOTSTRAP:
|
|
opt_noacl=opt_bootstrap=1;
|
|
break;
|
|
default:
|
|
fprintf(stderr,"%s: Unrecognized option: %c\n",my_progname,c);
|
|
usage();
|
|
exit(1);
|
|
}
|
|
}
|
|
// Skipp empty arguments (from shell)
|
|
while (argc != optind && !argv[optind][0])
|
|
optind++;
|
|
if (argc != optind)
|
|
{
|
|
fprintf(stderr,"%s: Too many parameters\n",my_progname);
|
|
usage();
|
|
exit(1);
|
|
}
|
|
fix_paths();
|
|
}
|
|
|
|
|
|
#ifdef __NT__
|
|
|
|
#define KEY_SERVICE_PARAMETERS "SYSTEM\\CurrentControlSet\\Services\\MySql\\Parameters"
|
|
|
|
#define COPY_KEY_VALUE(value) if (copy_key_value(hParametersKey,&(value),lpszValue)) return 1
|
|
#define CHECK_KEY_TYPE(type,name) if ( type != dwKeyValueType ) { key_type_error(hParametersKey,name); return 1; }
|
|
#define SET_CHANGEABLE_VARVAL(varname) if (set_varval(hParametersKey,varname,szKeyValueName,dwKeyValueType,lpdwValue)) return 1;
|
|
|
|
static void key_type_error(HKEY hParametersKey,const char *szKeyValueName)
|
|
{
|
|
TCHAR szErrorMsg[512];
|
|
RegCloseKey( hParametersKey );
|
|
strxmov(szErrorMsg,TEXT("Value \""),
|
|
szKeyValueName,
|
|
TEXT("\" of registry key \"" KEY_SERVICE_PARAMETERS "\" has wrong type\n"),NullS);
|
|
fprintf(stderr, szErrorMsg); /* not unicode compatible */
|
|
}
|
|
|
|
static bool copy_key_value(HKEY hParametersKey, char **var, const char *value)
|
|
{
|
|
if (!(*var=my_strdup(value,MYF(MY_WME))))
|
|
{
|
|
RegCloseKey(hParametersKey);
|
|
fprintf(stderr, "Couldn't allocate memory for registry key value\n");
|
|
return 1;
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
static bool set_varval(HKEY hParametersKey,const char *var, const char *szKeyValueName, DWORD dwKeyValueType,
|
|
LPDWORD lpdwValue)
|
|
{
|
|
CHECK_KEY_TYPE(dwKeyValueType, szKeyValueName );
|
|
if (set_changeable_varval(var, *lpdwValue, changeable_vars))
|
|
{
|
|
TCHAR szErrorMsg [ 512 ];
|
|
RegCloseKey( hParametersKey );
|
|
strxmov(szErrorMsg,
|
|
TEXT("Value \""),
|
|
szKeyValueName,
|
|
TEXT("\" of registry key \"" KEY_SERVICE_PARAMETERS "\" is invalid\n"),NullS);
|
|
fprintf( stderr, szErrorMsg ); /* not unicode compatible */
|
|
return 1;
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
|
|
static int get_service_parameters()
|
|
{
|
|
DWORD dwLastError;
|
|
HKEY hParametersKey;
|
|
DWORD dwIndex;
|
|
TCHAR szKeyValueName [ 256 ];
|
|
DWORD dwKeyValueName;
|
|
DWORD dwKeyValueType;
|
|
BYTE bKeyValueBuffer [ 512 ];
|
|
DWORD dwKeyValueBuffer;
|
|
LPDWORD lpdwValue = (LPDWORD) &bKeyValueBuffer[0];
|
|
LPCTSTR lpszValue = (LPCTSTR) &bKeyValueBuffer[0];
|
|
|
|
set_options();
|
|
|
|
/* open parameters of service */
|
|
dwLastError = (DWORD) RegOpenKeyEx( HKEY_LOCAL_MACHINE,
|
|
TEXT(KEY_SERVICE_PARAMETERS), 0,
|
|
KEY_READ, &hParametersKey );
|
|
if ( dwLastError == ERROR_FILE_NOT_FOUND ) /* no parameters available */
|
|
return 0;
|
|
if ( dwLastError != ERROR_SUCCESS )
|
|
{
|
|
fprintf(stderr,"Can't open registry key \"" KEY_SERVICE_PARAMETERS "\" for reading\n" );
|
|
return 1;
|
|
}
|
|
|
|
/* enumerate all values of key */
|
|
dwIndex = 0;
|
|
dwKeyValueName = sizeof( szKeyValueName ) / sizeof( TCHAR );
|
|
dwKeyValueBuffer = sizeof( bKeyValueBuffer );
|
|
while ( (dwLastError = (DWORD) RegEnumValue(hParametersKey, dwIndex,
|
|
szKeyValueName, &dwKeyValueName,
|
|
NULL, &dwKeyValueType,
|
|
&bKeyValueBuffer[0],
|
|
&dwKeyValueBuffer))
|
|
!= ERROR_NO_MORE_ITEMS )
|
|
{
|
|
/* check if error occured */
|
|
if ( dwLastError != ERROR_SUCCESS )
|
|
{
|
|
RegCloseKey( hParametersKey );
|
|
fprintf( stderr, "Can't enumerate values of registry key \"" KEY_SERVICE_PARAMETERS "\"\n" );
|
|
return 1;
|
|
}
|
|
if ( lstrcmp(szKeyValueName, TEXT("BaseDir")) == 0 )
|
|
{
|
|
CHECK_KEY_TYPE( REG_SZ, szKeyValueName);
|
|
strmov( mysql_home, lpszValue ); /* not unicode compatible */
|
|
}
|
|
else if ( lstrcmp(szKeyValueName, TEXT("BindAddress")) == 0 )
|
|
{
|
|
CHECK_KEY_TYPE( REG_SZ, szKeyValueName);
|
|
|
|
my_bind_addr = (ulong) inet_addr( lpszValue );
|
|
if ( my_bind_addr == (ulong) INADDR_NONE )
|
|
{
|
|
struct hostent* ent;
|
|
|
|
if ( !(*lpszValue) )
|
|
{
|
|
char szHostName [ 256 ];
|
|
if ( gethostname(szHostName, sizeof(szHostName)) == SOCKET_ERROR )
|
|
{
|
|
RegCloseKey( hParametersKey );
|
|
fprintf( stderr, "Can't get my own hostname\n" );
|
|
return 1;
|
|
}
|
|
ent = gethostbyname( szHostName );
|
|
}
|
|
else ent = gethostbyname( lpszValue );
|
|
if ( !ent )
|
|
{
|
|
RegCloseKey( hParametersKey );
|
|
fprintf( stderr, "Can't resolve hostname!\n" );
|
|
return 1;
|
|
}
|
|
my_bind_addr = (ulong) ((in_addr*)ent->h_addr_list[0])->s_addr;
|
|
}
|
|
}
|
|
else if ( lstrcmp(szKeyValueName, TEXT("BigTables")) == 0 )
|
|
{
|
|
CHECK_KEY_TYPE( REG_DWORD, szKeyValueName);
|
|
if ( *lpdwValue )
|
|
thd_startup_options |= OPTION_BIG_TABLES;
|
|
else
|
|
thd_startup_options &= ~((ulong)OPTION_BIG_TABLES);
|
|
}
|
|
else if ( lstrcmp(szKeyValueName, TEXT("DataDir")) == 0 )
|
|
{
|
|
CHECK_KEY_TYPE( REG_SZ, szKeyValueName );
|
|
strmov( mysql_real_data_home, lpszValue ); /* not unicode compatible */
|
|
}
|
|
else if ( lstrcmp(szKeyValueName, TEXT("Locking")) == 0 )
|
|
{
|
|
CHECK_KEY_TYPE( REG_DWORD, szKeyValueName );
|
|
my_disable_locking = !(*lpdwValue);
|
|
}
|
|
else if ( lstrcmp(szKeyValueName, TEXT("LogFile")) == 0 )
|
|
{
|
|
CHECK_KEY_TYPE( REG_SZ, szKeyValueName );
|
|
opt_log = 1;
|
|
COPY_KEY_VALUE( opt_logname );
|
|
}
|
|
else if ( lstrcmp(szKeyValueName, TEXT("UpdateLogFile")) == 0 )
|
|
{
|
|
CHECK_KEY_TYPE( REG_SZ, szKeyValueName );
|
|
opt_update_log = 1;
|
|
COPY_KEY_VALUE( opt_update_logname );
|
|
}
|
|
else if ( lstrcmp(szKeyValueName, TEXT("ISAMLogFile")) == 0 )
|
|
{
|
|
CHECK_KEY_TYPE( REG_SZ, szKeyValueName );
|
|
COPY_KEY_VALUE( nisam_log_filename );
|
|
(void) ni_log( 1 );
|
|
}
|
|
else if ( lstrcmp(szKeyValueName, TEXT("LongLogFormat")) == 0 )
|
|
{
|
|
CHECK_KEY_TYPE( REG_DWORD, szKeyValueName );
|
|
if ( *lpdwValue )
|
|
opt_specialflag |= SPECIAL_LONG_LOG_FORMAT;
|
|
else
|
|
opt_specialflag &= ~((ulong)SPECIAL_LONG_LOG_FORMAT);
|
|
}
|
|
else if ( lstrcmp(szKeyValueName, TEXT("LowPriorityUpdates")) == 0 )
|
|
{
|
|
CHECK_KEY_TYPE( REG_DWORD, szKeyValueName );
|
|
if ( *lpdwValue )
|
|
{
|
|
thd_startup_options |= OPTION_LOW_PRIORITY_UPDATES;
|
|
low_priority_updates = 1;
|
|
}
|
|
else
|
|
{
|
|
thd_startup_options &= ~((ulong)OPTION_LOW_PRIORITY_UPDATES);
|
|
low_priority_updates = 0;
|
|
}
|
|
}
|
|
else if ( lstrcmp(szKeyValueName, TEXT("Port")) == 0 )
|
|
{
|
|
CHECK_KEY_TYPE( REG_DWORD, szKeyValueName );
|
|
mysql_port = (unsigned int) *lpdwValue;
|
|
}
|
|
else if ( lstrcmp(szKeyValueName, TEXT("OldProtocol")) == 0 )
|
|
{
|
|
CHECK_KEY_TYPE( REG_DWORD, szKeyValueName );
|
|
protocol_version = *lpdwValue ? PROTOCOL_VERSION - 1 : PROTOCOL_VERSION;
|
|
}
|
|
else if ( lstrcmp(szKeyValueName, TEXT("HostnameResolving")) == 0 )
|
|
{
|
|
CHECK_KEY_TYPE( REG_DWORD, szKeyValueName );
|
|
if ( !*lpdwValue )
|
|
opt_specialflag |= SPECIAL_NO_RESOLVE;
|
|
else
|
|
opt_specialflag &= ~((ulong)SPECIAL_NO_RESOLVE);
|
|
}
|
|
else if ( lstrcmp(szKeyValueName, TEXT("Networking")) == 0 )
|
|
{
|
|
CHECK_KEY_TYPE( REG_DWORD, szKeyValueName );
|
|
opt_disable_networking = !(*lpdwValue);
|
|
}
|
|
else if ( lstrcmp(szKeyValueName, TEXT("HostnameCaching")) == 0 )
|
|
{
|
|
CHECK_KEY_TYPE( REG_DWORD, szKeyValueName );
|
|
if ( !*lpdwValue )
|
|
opt_specialflag |= SPECIAL_NO_HOST_CACHE;
|
|
else
|
|
opt_specialflag &= ~((ulong)SPECIAL_NO_HOST_CACHE);
|
|
}
|
|
else if ( lstrcmp(szKeyValueName, TEXT("ThreadPriority")) == 0 )
|
|
{
|
|
CHECK_KEY_TYPE( REG_DWORD, szKeyValueName );
|
|
if ( !(*lpdwValue) )
|
|
opt_specialflag |= SPECIAL_NO_PRIOR;
|
|
else
|
|
opt_specialflag &= ~((ulong)SPECIAL_NO_PRIOR);
|
|
}
|
|
else if ( lstrcmp(szKeyValueName, TEXT("NamedPipe")) == 0 )
|
|
{
|
|
CHECK_KEY_TYPE( REG_SZ, szKeyValueName );
|
|
COPY_KEY_VALUE( mysql_unix_port );
|
|
}
|
|
else if ( lstrcmp(szKeyValueName, TEXT("TempDir")) == 0 )
|
|
{
|
|
CHECK_KEY_TYPE( REG_SZ, szKeyValueName );
|
|
COPY_KEY_VALUE( mysql_tmpdir );
|
|
}
|
|
else if ( lstrcmp(szKeyValueName, TEXT("FlushTables")) == 0 )
|
|
{
|
|
CHECK_KEY_TYPE( REG_DWORD, szKeyValueName );
|
|
nisam_flush = *lpdwValue ? 1 : 0;
|
|
}
|
|
else if ( lstrcmp(szKeyValueName, TEXT("BackLog")) == 0 )
|
|
{
|
|
SET_CHANGEABLE_VARVAL( "back_log" );
|
|
}
|
|
else if ( lstrcmp(szKeyValueName, TEXT("ConnectTimeout")) == 0 )
|
|
{
|
|
SET_CHANGEABLE_VARVAL( "connect_timeout" );
|
|
}
|
|
else if ( lstrcmp(szKeyValueName, TEXT("JoinBufferSize")) == 0 )
|
|
{
|
|
SET_CHANGEABLE_VARVAL( "join_buffer" );
|
|
}
|
|
else if ( lstrcmp(szKeyValueName, TEXT("KeyBufferSize")) == 0 )
|
|
{
|
|
SET_CHANGEABLE_VARVAL( "key_buffer" );
|
|
}
|
|
else if ( lstrcmp(szKeyValueName, TEXT("LongQueryTime")) == 0 )
|
|
{
|
|
SET_CHANGEABLE_VARVAL( "long_query_time" );
|
|
}
|
|
else if ( lstrcmp(szKeyValueName, TEXT("MaxAllowedPacket")) == 0 )
|
|
{
|
|
SET_CHANGEABLE_VARVAL( "max_allowed_packet" );
|
|
}
|
|
else if ( lstrcmp(szKeyValueName, TEXT("MaxConnections")) == 0 )
|
|
{
|
|
SET_CHANGEABLE_VARVAL( "max_connections" );
|
|
}
|
|
else if ( lstrcmp(szKeyValueName, TEXT("MaxConnectErrors")) == 0 )
|
|
{
|
|
SET_CHANGEABLE_VARVAL( "max_connect_errors" );
|
|
}
|
|
else if ( lstrcmp(szKeyValueName, TEXT("MaxJoinSize")) == 0 )
|
|
{
|
|
SET_CHANGEABLE_VARVAL( "max_join_size" );
|
|
}
|
|
else if ( lstrcmp(szKeyValueName, TEXT("MaxSortLength")) == 0 )
|
|
{
|
|
SET_CHANGEABLE_VARVAL( "max_sort_length" );
|
|
}
|
|
else if ( lstrcmp(szKeyValueName, TEXT("NetBufferLength")) == 0 )
|
|
{
|
|
SET_CHANGEABLE_VARVAL( "net_buffer_length" );
|
|
}
|
|
else if ( lstrcmp(szKeyValueName, TEXT("RecordBufferSize")) == 0 )
|
|
{
|
|
SET_CHANGEABLE_VARVAL( "record_buffer" );
|
|
}
|
|
else if ( lstrcmp(szKeyValueName, TEXT("SortBufferSize")) == 0 )
|
|
{
|
|
SET_CHANGEABLE_VARVAL( "sort_buffer" );
|
|
}
|
|
else if ( lstrcmp(szKeyValueName, TEXT("TableCacheSize")) == 0 )
|
|
{
|
|
SET_CHANGEABLE_VARVAL( "table_cache" );
|
|
}
|
|
else if ( lstrcmp(szKeyValueName, TEXT("TmpTableSize")) == 0 )
|
|
{
|
|
SET_CHANGEABLE_VARVAL( "tmp_table_size" );
|
|
}
|
|
else if ( lstrcmp(szKeyValueName, TEXT("ThreadStackSize")) == 0 )
|
|
{
|
|
SET_CHANGEABLE_VARVAL( "thread_stack" );
|
|
}
|
|
else if ( lstrcmp(szKeyValueName, TEXT("WaitTimeout")) == 0 )
|
|
{
|
|
SET_CHANGEABLE_VARVAL( "wait_timeout" );
|
|
}
|
|
else
|
|
{
|
|
TCHAR szErrorMsg [ 512 ];
|
|
RegCloseKey( hParametersKey );
|
|
lstrcpy( szErrorMsg, TEXT("Value \"") );
|
|
lstrcat( szErrorMsg, szKeyValueName );
|
|
lstrcat( szErrorMsg, TEXT("\" of registry key \"" KEY_SERVICE_PARAMETERS "\" is not defined by MySQL\n") );
|
|
fprintf( stderr, szErrorMsg ); /* not unicode compatible */
|
|
return 1;
|
|
}
|
|
|
|
dwIndex++;
|
|
dwKeyValueName = sizeof( szKeyValueName ) / sizeof( TCHAR );
|
|
dwKeyValueBuffer = sizeof( bKeyValueBuffer );
|
|
}
|
|
RegCloseKey( hParametersKey );
|
|
|
|
/* paths are fixed by method get_options() */
|
|
return 0;
|
|
}
|
|
#endif
|
|
|
|
|
|
static char *get_relative_path(char *path)
|
|
{
|
|
if (test_if_hard_path(path) && is_prefix(path,DEFAULT_MYSQL_HOME))
|
|
{
|
|
path+=strlen(DEFAULT_MYSQL_HOME);
|
|
while (*path == FN_LIBCHAR)
|
|
path++;
|
|
}
|
|
return path;
|
|
}
|
|
|
|
|
|
static void fix_paths(void)
|
|
{
|
|
(void) fn_format(mysql_home,mysql_home,"","",16); // Remove symlinks
|
|
convert_dirname(mysql_home);
|
|
convert_dirname(mysql_real_data_home);
|
|
convert_dirname(language);
|
|
(void) my_load_path(mysql_home,mysql_home,""); // Resolve current dir
|
|
(void) my_load_path(mysql_real_data_home,mysql_real_data_home,mysql_home);
|
|
(void) my_load_path(pidfile_name,pidfile_name,mysql_real_data_home);
|
|
|
|
char buff[FN_REFLEN],*sharedir=get_relative_path(SHAREDIR);
|
|
if (test_if_hard_path(sharedir))
|
|
strmov(buff,sharedir); /* purecov: tested */
|
|
else
|
|
strxmov(buff,mysql_home,sharedir,NullS);
|
|
convert_dirname(buff);
|
|
(void) my_load_path(language,language,buff);
|
|
|
|
/* Add '/' to TMPDIR if needed */
|
|
char *tmp=my_malloc(FN_REFLEN,MYF(MY_FAE));
|
|
if (tmp)
|
|
{
|
|
strmov(tmp,mysql_tmpdir);
|
|
mysql_tmpdir=tmp;
|
|
convert_dirname(mysql_tmpdir);
|
|
mysql_tmpdir=my_realloc(mysql_tmpdir,strlen(mysql_tmpdir)+1,
|
|
MYF(MY_HOLD_ON_ERROR));
|
|
}
|
|
}
|
|
|
|
|
|
#ifdef SET_RLIMIT_NOFILE
|
|
static uint set_maximum_open_files(uint max_file_limit)
|
|
{
|
|
struct rlimit rlimit;
|
|
ulong old_cur;
|
|
|
|
if (!getrlimit(RLIMIT_NOFILE,&rlimit))
|
|
{
|
|
old_cur=rlimit.rlim_cur;
|
|
if (rlimit.rlim_cur >= max_file_limit) // Nothing to do
|
|
return rlimit.rlim_cur; /* purecov: inspected */
|
|
rlimit.rlim_cur=rlimit.rlim_max=max_file_limit;
|
|
if (setrlimit(RLIMIT_NOFILE,&rlimit))
|
|
{
|
|
sql_print_error("Warning: setrlimit couldn't increase number of open files to more than %ld",
|
|
old_cur); /* purecov: inspected */
|
|
max_file_limit=old_cur;
|
|
}
|
|
else
|
|
{
|
|
VOID(getrlimit(RLIMIT_NOFILE,&rlimit));
|
|
if ((uint) rlimit.rlim_cur != max_file_limit)
|
|
sql_print_error("Warning: setrlimit returned ok, but didn't change limits. Max open files is %ld",
|
|
(ulong) rlimit.rlim_cur); /* purecov: inspected */
|
|
max_file_limit=rlimit.rlim_cur;
|
|
}
|
|
}
|
|
return max_file_limit;
|
|
}
|
|
#endif
|
|
|
|
|
|
/*****************************************************************************
|
|
** Instantiate templates
|
|
*****************************************************************************/
|
|
|
|
#ifdef __GNUC__
|
|
/* Used templates */
|
|
template class I_List<THD>;
|
|
#endif
|