mirror of
https://github.com/MariaDB/server.git
synced 2025-05-28 13:01:41 +03:00

Some simple optimzations, more comments and indentation changes. Add ` around database in 'use database' in binary log. Moved max_error_count and max_warning_count to variables struct. Removed SHOW_WARNS_COUNT and SHOW_ERRORS_COUNT calls. Changed string functions to use character set of first string argument as default return characterset (Each string function can change the above assumption if needed)
606 lines
16 KiB
C++
606 lines
16 KiB
C++
/*
|
|
* Copyright (c) 2000
|
|
* SWsoft company
|
|
*
|
|
* This material is provided "as is", with absolutely no warranty expressed
|
|
* or implied. Any use is at your own risk.
|
|
*
|
|
* Permission to use or copy this software for any purpose is hereby granted
|
|
* without fee, provided the above notices are retained on all copies.
|
|
* Permission to modify the code and to distribute modified code is granted,
|
|
* provided the above notices are retained, and a notice that the code was
|
|
* modified is included with the above copyright notice.
|
|
*
|
|
|
|
This code was modified by the MySQL team
|
|
*/
|
|
|
|
/*
|
|
The following is needed to not cause conflicts when we include mysqld.cc
|
|
*/
|
|
|
|
#define main main1
|
|
#define mysql_unix_port mysql_inix_port1
|
|
#define mysql_port mysql_port1
|
|
|
|
#if defined (__WIN__)
|
|
#include "../sql/mysqld.cpp"
|
|
#else
|
|
#include "../sql/mysqld.cc"
|
|
#endif
|
|
|
|
#define SCRAMBLE_LENGTH 8
|
|
C_MODE_START
|
|
#include "lib_vio.c"
|
|
|
|
static int check_connections1(THD * thd);
|
|
static int check_connections2(THD * thd);
|
|
static bool check_user(THD *thd, enum_server_command command,
|
|
const char *user, const char *passwd, const char *db,
|
|
bool check_count);
|
|
char * get_mysql_home(){ return mysql_home;};
|
|
char * get_mysql_real_data_home(){ return mysql_real_data_home;};
|
|
|
|
bool lib_dispatch_command(enum enum_server_command command, NET *net,
|
|
const char *arg, ulong length)
|
|
{
|
|
THD *thd=(THD *) net->vio->dest_thd;
|
|
thd->store_globals(); // Fix if more than one connect
|
|
thd->net.last_error[0]=0; // Clear error message
|
|
thd->net.last_errno=0;
|
|
|
|
net_new_transaction(&thd->net);
|
|
return dispatch_command(command, thd, (char *) arg, length + 1);
|
|
}
|
|
|
|
|
|
void lib_connection_phase(NET * net, int phase)
|
|
{
|
|
THD * thd;
|
|
thd = (THD *)(net->vio->dest_thd);
|
|
if (thd)
|
|
{
|
|
switch (phase)
|
|
{
|
|
case 2:
|
|
check_connections2(thd);
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
C_MODE_END
|
|
|
|
|
|
void start_embedded_conn1(NET * net)
|
|
{
|
|
THD * thd = new THD;
|
|
my_net_init(&thd->net,NULL);
|
|
/* if (protocol_version>9) */
|
|
thd->net.return_errno=1;
|
|
thd->thread_id = thread_id++;
|
|
|
|
Vio * v = net->vio;
|
|
if (!v)
|
|
{
|
|
v = vio_new(0,VIO_CLOSED,0);
|
|
net->vio = v;
|
|
}
|
|
if (v)
|
|
{
|
|
v -> dest_thd = thd;
|
|
}
|
|
thd->net.vio = v;
|
|
if (thd->store_globals())
|
|
{
|
|
fprintf(stderr,"store_globals failed.\n");
|
|
return;
|
|
}
|
|
|
|
thd->mysys_var=my_thread_var;
|
|
thd->dbug_thread_id=my_thread_id();
|
|
thd->thread_stack= (char*) &thd;
|
|
|
|
if (thd->variables.max_join_size == (ulong) HA_POS_ERROR)
|
|
thd->options |= OPTION_BIG_SELECTS;
|
|
|
|
thd->proc_info=0; // Remove 'login'
|
|
thd->command=COM_SLEEP;
|
|
thd->version=refresh_version;
|
|
thd->set_time();
|
|
init_sql_alloc(&thd->mem_root,8192,8192);
|
|
|
|
check_connections1(thd);
|
|
}
|
|
|
|
|
|
|
|
|
|
static int
|
|
check_connections1(THD *thd)
|
|
{
|
|
uint connect_errors=0;
|
|
NET *net= &thd->net;
|
|
/*
|
|
** store the connection details
|
|
*/
|
|
DBUG_PRINT("info", (("check_connections called by thread %d"),
|
|
thd->thread_id));
|
|
DBUG_PRINT("general",("New connection received on %s",
|
|
vio_description(net->vio)));
|
|
if (!thd->host) // If TCP/IP connection
|
|
{
|
|
thd->host=(char*) localhost;
|
|
}
|
|
else /* Hostname given means that the connection was on a socket */
|
|
{
|
|
DBUG_PRINT("general",("Host: %s",thd->host));
|
|
thd->ip=0;
|
|
bzero((char*) &thd->remote,sizeof(struct sockaddr));
|
|
}
|
|
//vio_keepalive(net->vio, TRUE);
|
|
|
|
/* nasty, but any other way? */
|
|
uint pkt_len = 0;
|
|
|
|
char buff[80],*end;
|
|
int client_flags = CLIENT_LONG_FLAG | CLIENT_CONNECT_WITH_DB |
|
|
CLIENT_TRANSACTIONS;
|
|
LINT_INIT(pkt_len);
|
|
|
|
end=strmov(buff,server_version)+1;
|
|
int4store((uchar*) end,thd->thread_id);
|
|
end+=4;
|
|
memcpy(end,thd->scramble,SCRAMBLE_LENGTH+1);
|
|
end+=SCRAMBLE_LENGTH +1;
|
|
int2store(end,client_flags);
|
|
end[2]=MY_CHARSET_CURRENT;
|
|
|
|
#define MIN_HANDSHAKE_SIZE 6
|
|
|
|
int2store(end+3,thd->server_status);
|
|
bzero(end+5,13);
|
|
end+=18;
|
|
if (net_write_command(net,protocol_version, buff,
|
|
(uint) (end-buff)))
|
|
{
|
|
inc_host_errors(&thd->remote.sin_addr);
|
|
return(ER_HANDSHAKE_ERROR);
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
static int
|
|
check_connections2(THD * thd)
|
|
{
|
|
uint connect_errors=0;
|
|
uint pkt_len = 0;
|
|
NET * net = &thd -> net;
|
|
if (protocol_version>9) net -> return_errno=1;
|
|
|
|
if ( (pkt_len=my_net_read(net)) == packet_error ||
|
|
pkt_len < MIN_HANDSHAKE_SIZE)
|
|
{
|
|
inc_host_errors(&thd->remote.sin_addr);
|
|
return(ER_HANDSHAKE_ERROR);
|
|
}
|
|
|
|
#ifdef _CUSTOMCONFIG_
|
|
#include "_cust_sql_parse.h"
|
|
#endif
|
|
if (connect_errors)
|
|
reset_host_errors(&thd->remote.sin_addr);
|
|
if (thd->packet.alloc(thd->variables.net_buffer_length))
|
|
return(ER_OUT_OF_RESOURCES);
|
|
|
|
thd->client_capabilities=uint2korr(net->read_pos);
|
|
|
|
thd->max_client_packet_length=uint3korr(net->read_pos+2);
|
|
char *user= (char*) net->read_pos+5;
|
|
char *passwd= strend(user)+1;
|
|
char *db=0;
|
|
if (passwd[0] && strlen(passwd) != SCRAMBLE_LENGTH)
|
|
return ER_HANDSHAKE_ERROR;
|
|
if (thd->client_capabilities & CLIENT_CONNECT_WITH_DB)
|
|
db=strend(passwd)+1;
|
|
if (thd->client_capabilities & CLIENT_TRANSACTIONS)
|
|
thd->net.return_status= &thd->server_status;
|
|
net->read_timeout=thd->variables.net_read_timeout;
|
|
if (check_user(thd,COM_CONNECT, user, passwd, db, 1))
|
|
return (-1);
|
|
thd->password=test(passwd[0]);
|
|
return 0;
|
|
}
|
|
|
|
static bool check_user(THD *thd,enum_server_command command, const char *user,
|
|
const char *passwd, const char *db, bool check_count)
|
|
{
|
|
NET *net= &thd->net;
|
|
USER_RESOURCES ur;
|
|
thd->db=0;
|
|
|
|
if (!(thd->user = my_strdup(user, MYF(0))))
|
|
{
|
|
send_error(net,ER_OUT_OF_RESOURCES);
|
|
return 1;
|
|
}
|
|
thd->master_access=acl_getroot(thd, thd->host, thd->ip, thd->user,
|
|
passwd, thd->scramble, &thd->priv_user,
|
|
protocol_version == 9 ||
|
|
!(thd->client_capabilities &
|
|
CLIENT_LONG_PASSWORD),&ur);
|
|
DBUG_PRINT("info",
|
|
("Capabilities: %d packet_length: %d Host: '%s' User: '%s' Using password: %s Access: %u db: '%s'",
|
|
thd->client_capabilities, thd->max_client_packet_length,
|
|
thd->host_or_ip, thd->priv_user,
|
|
passwd[0] ? "yes": "no",
|
|
thd->master_access, thd->db ? thd->db : "*none*"));
|
|
if (thd->master_access & NO_ACCESS)
|
|
{
|
|
net_printf(net, ER_ACCESS_DENIED_ERROR,
|
|
thd->user,
|
|
thd->host_or_ip,
|
|
passwd[0] ? ER(ER_YES) : ER(ER_NO));
|
|
mysql_log.write(thd,COM_CONNECT,ER(ER_ACCESS_DENIED_ERROR),
|
|
thd->user,
|
|
thd->host_or_ip,
|
|
passwd[0] ? ER(ER_YES) : ER(ER_NO));
|
|
return(1); // Error already given
|
|
}
|
|
if (check_count)
|
|
{
|
|
VOID(pthread_mutex_lock(&LOCK_thread_count));
|
|
bool tmp=(thread_count - delayed_insert_threads >= max_connections &&
|
|
!(thd->master_access & PROCESS_ACL));
|
|
VOID(pthread_mutex_unlock(&LOCK_thread_count));
|
|
if (tmp)
|
|
{ // Too many connections
|
|
send_error(net, ER_CON_COUNT_ERROR);
|
|
return(1);
|
|
}
|
|
}
|
|
mysql_log.write(thd,command,
|
|
(thd->priv_user == thd->user ?
|
|
(char*) "%s@%s on %s" :
|
|
(char*) "%s@%s as anonymous on %s"),
|
|
user,
|
|
thd->host_or_ip,
|
|
db ? db : (char*) "");
|
|
thd->db_access=0;
|
|
if (db && db[0])
|
|
return test(mysql_change_db(thd,db));
|
|
else
|
|
send_ok(net); // Ready to handle questions
|
|
return 0; // ok
|
|
}
|
|
|
|
|
|
extern "C"
|
|
{
|
|
|
|
static my_bool inited, org_my_init_done;
|
|
ulong max_allowed_packet, net_buffer_length;
|
|
|
|
int STDCALL mysql_server_init(int argc, char **argv, char **groups)
|
|
{
|
|
char glob_hostname[FN_REFLEN];
|
|
|
|
/* This mess is to allow people to call the init function without
|
|
* having to mess with a fake argv */
|
|
int *argcp;
|
|
char ***argvp;
|
|
int fake_argc = 1;
|
|
char *fake_argv[] = { (char *)"", 0 };
|
|
const char *fake_groups[] = { "server", "embedded", 0 };
|
|
if (argc)
|
|
{
|
|
argcp = &argc;
|
|
argvp = (char***) &argv;
|
|
}
|
|
else
|
|
{
|
|
argcp = &fake_argc;
|
|
argvp = (char ***) &fake_argv;
|
|
}
|
|
if (!groups)
|
|
groups = (char**) fake_groups;
|
|
|
|
my_umask=0660; // Default umask for new files
|
|
my_umask_dir=0700; // Default umask for new directories
|
|
|
|
/* Only call MY_INIT() if it hasn't been called before */
|
|
if (!inited)
|
|
{
|
|
inited=1;
|
|
org_my_init_done=my_init_done;
|
|
}
|
|
if (!org_my_init_done)
|
|
{
|
|
MY_INIT((char *)"mysql_embedded"); // init my_sys library & pthreads
|
|
}
|
|
|
|
tzset(); // Set tzname
|
|
|
|
start_time=time((time_t*) 0);
|
|
#ifdef HAVE_TZNAME
|
|
#if defined(HAVE_LOCALTIME_R) && defined(_REENTRANT)
|
|
{
|
|
struct tm tm_tmp;
|
|
localtime_r(&start_time,&tm_tmp);
|
|
strmov(time_zone,tzname[tm_tmp.tm_isdst != 0 ? 1 : 0]);
|
|
}
|
|
#else
|
|
{
|
|
struct tm *start_tm;
|
|
start_tm=localtime(&start_time);
|
|
strmov(time_zone,tzname[start_tm->tm_isdst != 0 ? 1 : 0]);
|
|
}
|
|
#endif
|
|
#endif
|
|
|
|
if (gethostname(glob_hostname,sizeof(glob_hostname)-4) < 0)
|
|
strmov(glob_hostname,"mysql");
|
|
#ifndef DBUG_OFF
|
|
strxmov(strend(server_version),MYSQL_SERVER_SUFFIX,"-debug",NullS);
|
|
#else
|
|
strmov(strend(server_version),MYSQL_SERVER_SUFFIX);
|
|
#endif
|
|
load_defaults("my", (const char **) groups, argcp, argvp);
|
|
defaults_argv=*argvp;
|
|
|
|
/* Get default temporary directory */
|
|
opt_mysql_tmpdir=getenv("TMPDIR"); /* Use this if possible */
|
|
#if defined( __WIN__) || defined(OS2)
|
|
if (!opt_mysql_tmpdir)
|
|
opt_mysql_tmpdir=getenv("TEMP");
|
|
if (!opt_mysql_tmpdir)
|
|
opt_mysql_tmpdir=getenv("TMP");
|
|
#endif
|
|
if (!opt_mysql_tmpdir || !opt_mysql_tmpdir[0])
|
|
opt_mysql_tmpdir=(char*) P_tmpdir; /* purecov: inspected */
|
|
|
|
set_options();
|
|
get_options(*argcp, *argvp);
|
|
|
|
if (opt_log || opt_update_log || opt_slow_log || opt_bin_log)
|
|
strcat(server_version,"-log");
|
|
DBUG_PRINT("info",("%s Ver %s for %s on %s\n",my_progname,
|
|
server_version, SYSTEM_TYPE,MACHINE_TYPE));
|
|
|
|
/* These must be set early */
|
|
|
|
(void) pthread_mutex_init(&LOCK_mysql_create_db,MY_MUTEX_INIT_SLOW);
|
|
(void) pthread_mutex_init(&LOCK_Acl,MY_MUTEX_INIT_SLOW);
|
|
(void) pthread_mutex_init(&LOCK_grant,MY_MUTEX_INIT_FAST);
|
|
(void) pthread_mutex_init(&LOCK_open,MY_MUTEX_INIT_FAST);
|
|
(void) pthread_mutex_init(&LOCK_thread_count,MY_MUTEX_INIT_FAST);
|
|
(void) pthread_mutex_init(&LOCK_mapped_file,MY_MUTEX_INIT_SLOW);
|
|
(void) pthread_mutex_init(&LOCK_status,MY_MUTEX_INIT_FAST);
|
|
(void) pthread_mutex_init(&LOCK_error_log,MY_MUTEX_INIT_FAST);
|
|
(void) pthread_mutex_init(&LOCK_delayed_insert,MY_MUTEX_INIT_FAST);
|
|
(void) pthread_mutex_init(&LOCK_delayed_status,MY_MUTEX_INIT_FAST);
|
|
(void) pthread_mutex_init(&LOCK_delayed_create,MY_MUTEX_INIT_SLOW);
|
|
(void) pthread_mutex_init(&LOCK_manager,MY_MUTEX_INIT_FAST);
|
|
(void) pthread_mutex_init(&LOCK_crypt,MY_MUTEX_INIT_FAST);
|
|
(void) pthread_mutex_init(&LOCK_bytes_sent,MY_MUTEX_INIT_FAST);
|
|
(void) pthread_mutex_init(&LOCK_bytes_received,MY_MUTEX_INIT_FAST);
|
|
(void) pthread_mutex_init(&LOCK_timezone,MY_MUTEX_INIT_FAST);
|
|
(void) pthread_mutex_init(&LOCK_user_conn, MY_MUTEX_INIT_FAST);
|
|
(void) pthread_mutex_init(&LOCK_rpl_status, MY_MUTEX_INIT_FAST);
|
|
(void) pthread_mutex_init(&LOCK_active_mi, MY_MUTEX_INIT_FAST);
|
|
(void) pthread_mutex_init(&LOCK_global_system_variables, MY_MUTEX_INIT_FAST);
|
|
(void) pthread_cond_init(&COND_thread_count,NULL);
|
|
(void) pthread_cond_init(&COND_refresh,NULL);
|
|
(void) pthread_cond_init(&COND_thread_cache,NULL);
|
|
(void) pthread_cond_init(&COND_flush_thread_cache,NULL);
|
|
(void) pthread_cond_init(&COND_manager,NULL);
|
|
(void) pthread_cond_init(&COND_rpl_status, NULL);
|
|
|
|
if (set_default_charset_by_name(sys_charset.value, MYF(MY_WME)))
|
|
{
|
|
mysql_server_end();
|
|
return 1;
|
|
}
|
|
charsets_list = list_charsets(MYF(MY_CS_COMPILED|MY_CS_CONFIG));
|
|
|
|
/* 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);
|
|
pthread_attr_setscope(&connection_attrib, PTHREAD_SCOPE_SYSTEM);
|
|
|
|
#if defined( SET_RLIMIT_NOFILE) || defined( OS2)
|
|
/* connections and databases needs lots of files */
|
|
{
|
|
uint wanted_files=10+(uint) max(max_connections*5,
|
|
max_connections+table_cache_size*2);
|
|
set_if_bigger(wanted_files, open_files_limit);
|
|
// Note that some system returns 0 if we succeed here:
|
|
uint files=set_maximum_open_files(wanted_files);
|
|
if (files && files < wanted_files && ! open_files_limit)
|
|
{
|
|
max_connections= (ulong) min((files-10),max_connections);
|
|
table_cache_size= (ulong) max((files-10-max_connections)/2,64);
|
|
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();
|
|
set_var_init();
|
|
mysys_uses_curses=0;
|
|
#ifdef USE_REGEX
|
|
regex_init();
|
|
#endif
|
|
if (use_temp_pool && bitmap_init(&temp_pool,1024,1))
|
|
{
|
|
mysql_server_end();
|
|
return 1;
|
|
}
|
|
|
|
/*
|
|
We have enough space for fiddling with the argv, continue
|
|
*/
|
|
umask(((~my_umask) & 0666));
|
|
table_cache_init();
|
|
hostname_cache_init();
|
|
query_cache_result_size_limit(query_cache_limit);
|
|
query_cache_resize(query_cache_size);
|
|
randominit(&sql_rand,(ulong) start_time,(ulong) start_time/2);
|
|
reset_floating_point_exceptions();
|
|
init_thr_lock();
|
|
init_slave_list();
|
|
|
|
/* Setup log files */
|
|
if (opt_log)
|
|
open_log(&mysql_log, glob_hostname, opt_logname, ".log", NullS,
|
|
LOG_NORMAL);
|
|
if (opt_update_log)
|
|
{
|
|
open_log(&mysql_update_log, glob_hostname, opt_update_logname, "",
|
|
NullS, LOG_NEW);
|
|
using_update_log=1;
|
|
}
|
|
|
|
if (opt_slow_log)
|
|
open_log(&mysql_slow_log, glob_hostname, opt_slow_logname, "-slow.log",
|
|
NullS, LOG_NORMAL);
|
|
if (ha_init())
|
|
{
|
|
sql_print_error("Can't init databases");
|
|
exit(1);
|
|
}
|
|
ha_key_cache();
|
|
#if defined(HAVE_MLOCKALL) && defined(MCL_CURRENT)
|
|
if (locked_in_memory && !geteuid())
|
|
{
|
|
if (mlockall(MCL_CURRENT))
|
|
{
|
|
sql_print_error("Warning: Failed to lock memory. Errno: %d\n",errno);
|
|
}
|
|
else
|
|
locked_in_memory=1;
|
|
}
|
|
#else
|
|
locked_in_memory=0;
|
|
#endif
|
|
|
|
if (opt_myisam_log)
|
|
(void) mi_log( 1 );
|
|
ft_init_stopwords(ft_precompiled_stopwords);
|
|
|
|
/*
|
|
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("Can't create thread-keys");
|
|
exit(1);
|
|
}
|
|
opt_noacl = 1; // No permissions
|
|
if (acl_init(opt_noacl))
|
|
{
|
|
mysql_server_end();
|
|
return 1;
|
|
}
|
|
if (!opt_noacl)
|
|
(void) grant_init();
|
|
init_max_user_conn();
|
|
|
|
#ifdef HAVE_DLOPEN
|
|
if (!opt_noacl)
|
|
udf_init();
|
|
#endif
|
|
|
|
if (opt_bin_log)
|
|
{
|
|
if (!opt_bin_logname)
|
|
{
|
|
char tmp[FN_REFLEN];
|
|
/* TODO: The following should be using fn_format(); We just need to
|
|
first change fn_format() to cut the file name if it's too long.
|
|
*/
|
|
strmake(tmp,glob_hostname,FN_REFLEN-5);
|
|
strmov(strcend(tmp,'.'),"-bin");
|
|
opt_bin_logname=my_strdup(tmp,MYF(MY_WME));
|
|
}
|
|
open_log(&mysql_bin_log, glob_hostname, opt_bin_logname, "-bin",
|
|
opt_binlog_index_name, LOG_BIN);
|
|
using_update_log=1;
|
|
}
|
|
|
|
(void) thr_setconcurrency(concurrency); // 10 by default
|
|
|
|
if (
|
|
#ifdef HAVE_BERKELEY_DB
|
|
!berkeley_skip ||
|
|
#endif
|
|
(flush_time && flush_time != ~(ulong) 0L))
|
|
{
|
|
pthread_t hThread;
|
|
if (pthread_create(&hThread,&connection_attrib,handle_manager,0))
|
|
sql_print_error("Warning: Can't create thread to manage maintenance");
|
|
}
|
|
|
|
/*
|
|
Update mysqld variables from client variables if set
|
|
The client variables are set also by get_one_option() in mysqld.cc
|
|
*/
|
|
if (max_allowed_packet)
|
|
global_system_variables.max_allowed_packet= max_allowed_packet;
|
|
if (net_buffer_length)
|
|
global_system_variables.net_buffer_length= net_buffer_length;
|
|
return 0;
|
|
}
|
|
|
|
|
|
void STDCALL mysql_server_end()
|
|
{
|
|
clean_up(0);
|
|
#ifdef THREAD
|
|
/* Don't call my_thread_end() if the application is using MY_INIT() */
|
|
if (!org_my_init_done)
|
|
my_thread_end();
|
|
#endif
|
|
/* If library called my_init(), free memory allocated by it */
|
|
if (!org_my_init_done)
|
|
my_end(0);
|
|
}
|
|
|
|
my_bool STDCALL mysql_thread_init()
|
|
{
|
|
#ifdef THREAD
|
|
return my_thread_init();
|
|
#else
|
|
return 0;
|
|
#endif
|
|
}
|
|
|
|
void STDCALL mysql_thread_end()
|
|
{
|
|
#ifdef THREAD
|
|
my_thread_end();
|
|
#endif
|
|
}
|
|
|
|
void start_embedded_connection(NET * net)
|
|
{
|
|
start_embedded_conn1(net);
|
|
}
|
|
|
|
void end_embedded_connection(NET * net)
|
|
{
|
|
THD *thd = (THD *) net->vio->dest_thd;
|
|
delete thd;
|
|
}
|
|
|
|
} /* extern "C" */
|