Commit fc81fdb4 authored by monty@tik.mysql.fi's avatar monty@tik.mysql.fi

Redefinition of myisam_bulk_insert_tree_size

Removed new error message
Fixed test case for varbinary
Threads are again killable in "merge_buffers"
Cleanup of sql_repl.cc
SHOW OPEN TABLES now works when no tables are opened
parent ca771c46
...@@ -22266,11 +22266,11 @@ The buffer that is allocated when sorting the index when doing a ...@@ -22266,11 +22266,11 @@ The buffer that is allocated when sorting the index when doing a
@code{ALTER TABLE}. @code{ALTER TABLE}.
@item @code{myisam_bulk_insert_tree_size} @item @code{myisam_bulk_insert_tree_size}
@strong{MySQL} uses special tree-like cache to make bulk inserts (that is, @code{MyISAM} uses special tree-like cache to make bulk inserts (that is,
@code{INSERT ... SELECT}, @code{INSERT ... SELECT},
@code{INSERT ... VALUES (...), (...), ...}, and @code{INSERT ... VALUES (...), (...), ...}, and
@code{LOAD DATA INFILE}) faster. This variable limits @code{LOAD DATA INFILE}) faster. This variable limits
the size of the cache tree in bytes @strong{per thread, per index}. the size of the cache tree in bytes @strong{per thread, per table}.
Default value is 8 MB. Default value is 8 MB.
@item @code{myisam_max_extra_sort_file_size}. @item @code{myisam_max_extra_sort_file_size}.
...@@ -23960,7 +23960,7 @@ The following options to @code{mysqld} can be used to change the behavior of ...@@ -23960,7 +23960,7 @@ The following options to @code{mysqld} can be used to change the behavior of
@item @code{--delay-key-write-for-all-tables} @tab Don't flush key buffers between writes for any MyISAM table @item @code{--delay-key-write-for-all-tables} @tab Don't flush key buffers between writes for any MyISAM table
@item @code{-O myisam_max_extra_sort_file_size=#} @tab Used to help @strong{MySQL} to decide when to use the slow but safe key cache index create method. @strong{NOTE} that this parameter is given in megabytes! @item @code{-O myisam_max_extra_sort_file_size=#} @tab Used to help @strong{MySQL} to decide when to use the slow but safe key cache index create method. @strong{NOTE} that this parameter is given in megabytes!
@item @code{-O myisam_max_sort_file_size=#} @tab Don't use the fast sort index method to created index if the temporary file would get bigger than this. @strong{NOTE} that this paramter is given in megabytes! @item @code{-O myisam_max_sort_file_size=#} @tab Don't use the fast sort index method to created index if the temporary file would get bigger than this. @strong{NOTE} that this paramter is given in megabytes!
@item @code{-O myisam_bulk_insert_tree_size=#} @tab Size of tree cache used in bulk insert optimization. @strong{NOTE} that this is a limit @strong{per index}! @item @code{-O myisam_bulk_insert_tree_size=#} @tab Size of tree cache used in bulk insert optimization. @strong{NOTE} that this is the total size used for all index in one table.
@end multitable @end multitable
The automatic recovery is activated if you start @code{mysqld} with The automatic recovery is activated if you start @code{mysqld} with
...@@ -34,19 +34,13 @@ int main(int argc, char **argv) ...@@ -34,19 +34,13 @@ int main(int argc, char **argv)
exit(1); exit(1);
} }
if (!(sock = mysql_connect(&mysql,NULL,0,0))) if (!(sock = mysql_real_connect(&mysql,NULL,NULL,NULL,argv[1],0,NULL,0)))
{ {
fprintf(stderr,"Couldn't connect to engine!\n%s\n",mysql_error(&mysql)); fprintf(stderr,"Couldn't connect to engine!\n%s\n",mysql_error(&mysql));
perror(""); perror("");
exit(1); exit(1);
} }
if (mysql_select_db(sock,argv[1]))
{
fprintf(stderr,"Couldn't select database %s!\n%s\n",argv[1],
mysql_error(sock));
}
num = atoi(argv[2]); num = atoi(argv[2]);
count = 0; count = 0;
while (count < num) while (count < num)
......
...@@ -126,24 +126,30 @@ typedef struct st_mysql_data { ...@@ -126,24 +126,30 @@ typedef struct st_mysql_data {
struct st_mysql_options { struct st_mysql_options {
unsigned int connect_timeout,client_flag; unsigned int connect_timeout,client_flag;
my_bool compress,named_pipe;
my_bool rpl_probe; /* on connect, find out the replication
role of the server, and establish connections
to all the peers */
my_bool rpl_parse; /* each call to mysql_real_query() will parse
it to tell if it is a read or a write, and
direct it to the slave or the master */
my_bool no_master_reads; /* if set, never read from
a master,only from slave, when doing
a read that is replication-aware */
unsigned int port; unsigned int port;
char *host,*init_command,*user,*password,*unix_socket,*db; char *host,*init_command,*user,*password,*unix_socket,*db;
char *my_cnf_file,*my_cnf_group, *charset_dir, *charset_name; char *my_cnf_file,*my_cnf_group, *charset_dir, *charset_name;
my_bool use_ssl; /* if to use SSL or not */
char *ssl_key; /* PEM key file */ char *ssl_key; /* PEM key file */
char *ssl_cert; /* PEM cert file */ char *ssl_cert; /* PEM cert file */
char *ssl_ca; /* PEM CA file */ char *ssl_ca; /* PEM CA file */
char *ssl_capath; /* PEM directory of CA-s? */ char *ssl_capath; /* PEM directory of CA-s? */
my_bool use_ssl; /* if to use SSL or not */
my_bool compress,named_pipe;
/*
on connect, find out the replication role of the server, and
establish connections to all the peers
*/
my_bool rpl_probe;
/*
each call to mysql_real_query() will parse it to tell if it is a read
or a write, and direct it to the slave or the master
*/
my_bool rpl_parse;
/*
if set, never read from a master,only from slave, when doing
a read that is replication-aware
*/
my_bool no_master_reads;
}; };
enum mysql_option { MYSQL_OPT_CONNECT_TIMEOUT, MYSQL_OPT_COMPRESS, enum mysql_option { MYSQL_OPT_CONNECT_TIMEOUT, MYSQL_OPT_COMPRESS,
...@@ -154,12 +160,13 @@ enum mysql_option { MYSQL_OPT_CONNECT_TIMEOUT, MYSQL_OPT_COMPRESS, ...@@ -154,12 +160,13 @@ enum mysql_option { MYSQL_OPT_CONNECT_TIMEOUT, MYSQL_OPT_COMPRESS,
enum mysql_status { MYSQL_STATUS_READY,MYSQL_STATUS_GET_RESULT, enum mysql_status { MYSQL_STATUS_READY,MYSQL_STATUS_GET_RESULT,
MYSQL_STATUS_USE_RESULT}; MYSQL_STATUS_USE_RESULT};
/* there are three types of queries - the ones that have to go to /*
the master, the ones that go to a slave, and the adminstrative There are three types of queries - the ones that have to go to
type which must happen on the pivot connectioin the master, the ones that go to a slave, and the adminstrative
type which must happen on the pivot connectioin
*/ */
enum mysql_rpl_type { MYSQL_RPL_MASTER, MYSQL_RPL_SLAVE, enum mysql_rpl_type { MYSQL_RPL_MASTER, MYSQL_RPL_SLAVE,
MYSQL_RPL_ADMIN }; MYSQL_RPL_ADMIN };
typedef struct st_mysql { typedef struct st_mysql {
...@@ -191,15 +198,13 @@ typedef struct st_mysql { ...@@ -191,15 +198,13 @@ typedef struct st_mysql {
struct st_mysql* master, *next_slave; struct st_mysql* master, *next_slave;
struct st_mysql* last_used_slave; /* needed for round-robin slave pick */ struct st_mysql* last_used_slave; /* needed for round-robin slave pick */
struct st_mysql* last_used_con; /* needed for send/read/store/use /* needed for send/read/store/use result to work correctly with replication */
result to work struct st_mysql* last_used_con;
correctly with replication /*
*/ Set if this is the original connection, not a master or a slave we have
my_bool rpl_pivot; /* set if this is the original connection, added though mysql_rpl_probe() or mysql_set_master()/ mysql_add_slave()
not a master or a slave we have added though */
mysql_rpl_probe() or mysql_set_master()/ my_bool rpl_pivot;
mysql_add_slave()
*/
} MYSQL; } MYSQL;
...@@ -246,11 +251,8 @@ int STDCALL mysql_ssl_set(MYSQL *mysql, const char *key, ...@@ -246,11 +251,8 @@ int STDCALL mysql_ssl_set(MYSQL *mysql, const char *key,
char * STDCALL mysql_ssl_cipher(MYSQL *mysql); char * STDCALL mysql_ssl_cipher(MYSQL *mysql);
int STDCALL mysql_ssl_clear(MYSQL *mysql); int STDCALL mysql_ssl_clear(MYSQL *mysql);
#endif /* HAVE_OPENSSL */ #endif /* HAVE_OPENSSL */
MYSQL * STDCALL mysql_connect(MYSQL *mysql, const char *host,
const char *user, const char *passwd);
my_bool STDCALL mysql_change_user(MYSQL *mysql, const char *user, my_bool STDCALL mysql_change_user(MYSQL *mysql, const char *user,
const char *passwd, const char *db); const char *passwd, const char *db);
#if MYSQL_VERSION_ID >= 32200
MYSQL * STDCALL mysql_real_connect(MYSQL *mysql, const char *host, MYSQL * STDCALL mysql_real_connect(MYSQL *mysql, const char *host,
const char *user, const char *user,
const char *passwd, const char *passwd,
...@@ -258,14 +260,6 @@ MYSQL * STDCALL mysql_real_connect(MYSQL *mysql, const char *host, ...@@ -258,14 +260,6 @@ MYSQL * STDCALL mysql_real_connect(MYSQL *mysql, const char *host,
unsigned int port, unsigned int port,
const char *unix_socket, const char *unix_socket,
unsigned int clientflag); unsigned int clientflag);
#else
MYSQL * STDCALL mysql_real_connect(MYSQL *mysql, const char *host,
const char *user,
const char *passwd,
unsigned int port,
const char *unix_socket,
unsigned int clientflag);
#endif
void STDCALL mysql_close(MYSQL *sock); void STDCALL mysql_close(MYSQL *sock);
int STDCALL mysql_select_db(MYSQL *mysql, const char *db); int STDCALL mysql_select_db(MYSQL *mysql, const char *db);
int STDCALL mysql_query(MYSQL *mysql, const char *q); int STDCALL mysql_query(MYSQL *mysql, const char *q);
...@@ -285,8 +279,10 @@ int STDCALL mysql_slave_query(MYSQL *mysql, const char *q, ...@@ -285,8 +279,10 @@ int STDCALL mysql_slave_query(MYSQL *mysql, const char *q,
int STDCALL mysql_slave_send_query(MYSQL *mysql, const char *q, int STDCALL mysql_slave_send_query(MYSQL *mysql, const char *q,
unsigned int length); unsigned int length);
/* enable/disable parsing of all queries to decide /*
if they go on master or slave */ enable/disable parsing of all queries to decide if they go on master or
slave
*/
void STDCALL mysql_enable_rpl_parse(MYSQL* mysql); void STDCALL mysql_enable_rpl_parse(MYSQL* mysql);
void STDCALL mysql_disable_rpl_parse(MYSQL* mysql); void STDCALL mysql_disable_rpl_parse(MYSQL* mysql);
/* get the value of the parse flag */ /* get the value of the parse flag */
...@@ -305,17 +301,14 @@ int STDCALL mysql_rpl_probe(MYSQL* mysql); ...@@ -305,17 +301,14 @@ int STDCALL mysql_rpl_probe(MYSQL* mysql);
/* set the master, close/free the old one, if it is not a pivot */ /* set the master, close/free the old one, if it is not a pivot */
int STDCALL mysql_set_master(MYSQL* mysql, const char* host, int STDCALL mysql_set_master(MYSQL* mysql, const char* host,
unsigned int port, unsigned int port,
const char* user, const char* user,
const char* passwd); const char* passwd);
int STDCALL mysql_add_slave(MYSQL* mysql, const char* host, int STDCALL mysql_add_slave(MYSQL* mysql, const char* host,
unsigned int port, unsigned int port,
const char* user, const char* user,
const char* passwd); const char* passwd);
int STDCALL mysql_create_db(MYSQL *mysql, const char *DB);
int STDCALL mysql_drop_db(MYSQL *mysql, const char *DB);
int STDCALL mysql_shutdown(MYSQL *mysql); int STDCALL mysql_shutdown(MYSQL *mysql);
int STDCALL mysql_dump_debug_info(MYSQL *mysql); int STDCALL mysql_dump_debug_info(MYSQL *mysql);
int STDCALL mysql_refresh(MYSQL *mysql, int STDCALL mysql_refresh(MYSQL *mysql,
...@@ -364,9 +357,15 @@ char * STDCALL mysql_odbc_escape_string(MYSQL *mysql, ...@@ -364,9 +357,15 @@ char * STDCALL mysql_odbc_escape_string(MYSQL *mysql,
void STDCALL myodbc_remove_escape(MYSQL *mysql,char *name); void STDCALL myodbc_remove_escape(MYSQL *mysql,char *name);
unsigned int STDCALL mysql_thread_safe(void); unsigned int STDCALL mysql_thread_safe(void);
#define mysql_reload(mysql) mysql_refresh((mysql),REFRESH_GRANT) #define mysql_reload(mysql) mysql_refresh((mysql),REFRESH_GRANT)
#ifndef USE_OLD_FUNCTIONS
MYSQL * STDCALL mysql_connect(MYSQL *mysql, const char *host,
const char *user, const char *passwd);
int STDCALL mysql_create_db(MYSQL *mysql, const char *DB);
int STDCALL mysql_drop_db(MYSQL *mysql, const char *DB);
#endif
/* new api functions */ /* new api functions */
#define HAVE_MYSQL_REAL_CONNECT #define HAVE_MYSQL_REAL_CONNECT
......
...@@ -212,6 +212,5 @@ ...@@ -212,6 +212,5 @@
#define ER_CREATE_DB_WITH_READ_LOCK 1209 #define ER_CREATE_DB_WITH_READ_LOCK 1209
#define ER_CONNECT_TO_MASTER 1210 #define ER_CONNECT_TO_MASTER 1210
#define ER_QUERY_ON_MASTER 1211 #define ER_QUERY_ON_MASTER 1211
#define ER_SHOW_BINLOG_EVENTS 1212 #define ER_ERROR_WHEN_EXECUTING_COMMAND 1212
#define ER_SHOW_NEW_MASTER 1213 #define ER_ERROR_MESSAGES 213
#define ER_ERROR_MESSAGES 214
...@@ -770,8 +770,9 @@ int _mi_init_bulk_insert(MI_INFO *info) ...@@ -770,8 +770,9 @@ int _mi_init_bulk_insert(MI_INFO *info)
if (info->bulk_insert) if (info->bulk_insert)
return 0; return 0;
info->bulk_insert=(TREE *)my_malloc( info->bulk_insert=(TREE *)
(sizeof(TREE)+sizeof(bulk_insert_param))*share->base.keys, MYF(0)); my_malloc((sizeof(TREE)+sizeof(bulk_insert_param))*share->base.keys,
MYF(0));
if (!info->bulk_insert) if (!info->bulk_insert)
return HA_ERR_OUT_OF_MEM; return HA_ERR_OUT_OF_MEM;
...@@ -785,9 +786,10 @@ int _mi_init_bulk_insert(MI_INFO *info) ...@@ -785,9 +786,10 @@ int _mi_init_bulk_insert(MI_INFO *info)
if (!(key->flag & HA_NOSAME) && share->base.auto_key != i+1 if (!(key->flag & HA_NOSAME) && share->base.auto_key != i+1
&& test(share->state.key_map & ((ulonglong) 1 << i))) && test(share->state.key_map & ((ulonglong) 1 << i)))
{ {
init_tree(& info->bulk_insert[i], 0, myisam_bulk_insert_tree_size, 0, init_tree(& info->bulk_insert[i], 0,
(qsort_cmp2)keys_compare, 0, myisam_bulk_insert_tree_size / share->base.keys, 0,
(tree_element_free) keys_free, (void *)params); (qsort_cmp2)keys_compare, 0,
(tree_element_free) keys_free, (void *)params);
} }
else else
info->bulk_insert[i].root=0; info->bulk_insert[i].root=0;
......
...@@ -21,7 +21,7 @@ drop table t1; ...@@ -21,7 +21,7 @@ drop table t1;
# #
--error 1064 --error 1064
select x'hello'; select x'hello';
--error 1064 --error 1054
select 0xfg; select 0xfg;
# #
......
...@@ -97,7 +97,8 @@ void init_tree(TREE *tree, uint default_alloc_size, uint memory_limit, ...@@ -97,7 +97,8 @@ void init_tree(TREE *tree, uint default_alloc_size, uint memory_limit,
DBUG_ENTER("init_tree"); DBUG_ENTER("init_tree");
DBUG_PRINT("enter",("tree: %lx size: %d",tree,size)); DBUG_PRINT("enter",("tree: %lx size: %d",tree,size));
default_alloc_size=DEFAULT_ALLOC_SIZE; if (!default_alloc_size)
default_alloc_size= DEFAULT_ALLOC_SIZE;
bzero((gptr) &tree->null_element,sizeof(tree->null_element)); bzero((gptr) &tree->null_element,sizeof(tree->null_element));
tree->root= &tree->null_element; tree->root= &tree->null_element;
tree->compare=compare; tree->compare=compare;
......
...@@ -86,11 +86,10 @@ ha_rows filesort(TABLE *table, SORT_FIELD *sortorder, uint s_length, ...@@ -86,11 +86,10 @@ ha_rows filesort(TABLE *table, SORT_FIELD *sortorder, uint s_length,
my_b_clear(&tempfile); my_b_clear(&tempfile);
buffpek= (BUFFPEK *) NULL; sort_keys= (uchar **) NULL; error= 1; buffpek= (BUFFPEK *) NULL; sort_keys= (uchar **) NULL; error= 1;
maxbuffer=1; maxbuffer=1;
bzero((char*) &param,sizeof(param));
param.ref_length= table->file->ref_length; param.ref_length= table->file->ref_length;
param.sort_length=sortlength(sortorder,s_length)+ param.ref_length; param.sort_length=sortlength(sortorder,s_length)+ param.ref_length;
param.max_rows= max_rows; param.max_rows= max_rows;
param.examined_rows=0;
param.unique_buff=0;
if (select && select->quick) if (select && select->quick)
{ {
...@@ -686,9 +685,16 @@ int merge_buffers(SORTPARAM *param, IO_CACHE *from_file, ...@@ -686,9 +685,16 @@ int merge_buffers(SORTPARAM *param, IO_CACHE *from_file,
BUFFPEK *buffpek,**refpek; BUFFPEK *buffpek,**refpek;
QUEUE queue; QUEUE queue;
qsort2_cmp cmp; qsort2_cmp cmp;
volatile bool *killed= &current_thd->killed;
bool not_killable;
DBUG_ENTER("merge_buffers"); DBUG_ENTER("merge_buffers");
statistic_increment(filesort_merge_passes, &LOCK_status); statistic_increment(filesort_merge_passes, &LOCK_status);
if (param->not_killable)
{
killed= &not_killable;
not_killable=0;
}
error=0; error=0;
offset=(sort_length=param->sort_length)-param->ref_length; offset=(sort_length=param->sort_length)-param->ref_length;
...@@ -738,6 +744,10 @@ int merge_buffers(SORTPARAM *param, IO_CACHE *from_file, ...@@ -738,6 +744,10 @@ int merge_buffers(SORTPARAM *param, IO_CACHE *from_file,
while (queue.elements > 1) while (queue.elements > 1)
{ {
if (*killed)
{
error=1; goto err; /* purecov: inspected */
}
for (;;) for (;;)
{ {
buffpek=(BUFFPEK*) queue_top(&queue); buffpek=(BUFFPEK*) queue_top(&queue);
......
...@@ -245,9 +245,9 @@ public: ...@@ -245,9 +245,9 @@ public:
int get_data_size() int get_data_size()
{ {
return q_len + db_len + 2 + return q_len + db_len + 2 +
sizeof(uint32) // thread_id 4 // thread_id
+ sizeof(uint32) // exec_time + 4 // exec_time
+ sizeof(uint16) // error_code + 2 // error_code
; ;
} }
......
...@@ -222,5 +222,4 @@ ...@@ -222,5 +222,4 @@
"CREATE DATABASE not allowed while thread is holding global read lock", "CREATE DATABASE not allowed while thread is holding global read lock",
"Error connecting to master: %-.128s", "Error connecting to master: %-.128s",
"Error running query on master: %-.128s", "Error running query on master: %-.128s",
"Error in SHOW BINLOG EVENTS: %-.128s", "Error when executing command %s: %-.128s",
"Error in SHOW NEW MASTER: %-.128s",
...@@ -216,5 +216,4 @@ ...@@ -216,5 +216,4 @@
"CREATE DATABASE not allowed while thread is holding global read lock", "CREATE DATABASE not allowed while thread is holding global read lock",
"Error connecting to master: %-.128s", "Error connecting to master: %-.128s",
"Error running query on master: %-.128s", "Error running query on master: %-.128s",
"Error in SHOW BINLOG EVENTS: %-.128s", "Error when executing command %s: %-.128s",
"Error in SHOW NEW MASTER: %-.128s",
...@@ -213,5 +213,4 @@ ...@@ -213,5 +213,4 @@
"CREATE DATABASE not allowed while thread is holding global read lock", "CREATE DATABASE not allowed while thread is holding global read lock",
"Error connecting to master: %-.128s", "Error connecting to master: %-.128s",
"Error running query on master: %-.128s", "Error running query on master: %-.128s",
"Error in SHOW BINLOG EVENTS: %-.128s", "Error when executing command %s: %-.128s",
"Error in SHOW NEW MASTER: %-.128s",
...@@ -213,5 +213,4 @@ ...@@ -213,5 +213,4 @@
"CREATE DATABASE not allowed while thread is holding global read lock", "CREATE DATABASE not allowed while thread is holding global read lock",
"Error connecting to master: %-.128s", "Error connecting to master: %-.128s",
"Error running query on master: %-.128s", "Error running query on master: %-.128s",
"Error in SHOW BINLOG EVENTS: %-.128s", "Error when executing command %s: %-.128s",
"Error in SHOW NEW MASTER: %-.128s",
...@@ -217,5 +217,4 @@ ...@@ -217,5 +217,4 @@
"CREATE DATABASE not allowed while thread is holding global read lock", "CREATE DATABASE not allowed while thread is holding global read lock",
"Error connecting to master: %-.128s", "Error connecting to master: %-.128s",
"Error running query on master: %-.128s", "Error running query on master: %-.128s",
"Error in SHOW BINLOG EVENTS: %-.128s", "Error when executing command %s: %-.128s",
"Error in SHOW NEW MASTER: %-.128s",
...@@ -213,5 +213,4 @@ ...@@ -213,5 +213,4 @@
"CREATE DATABASE not allowed while thread is holding global read lock", "CREATE DATABASE not allowed while thread is holding global read lock",
"Error connecting to master: %-.128s", "Error connecting to master: %-.128s",
"Error running query on master: %-.128s", "Error running query on master: %-.128s",
"Error in SHOW BINLOG EVENTS: %-.128s", "Error when executing command %s: %-.128s",
"Error in SHOW NEW MASTER: %-.128s",
...@@ -216,5 +216,4 @@ ...@@ -216,5 +216,4 @@
"CREATE DATABASE not allowed while thread is holding global read lock", "CREATE DATABASE not allowed while thread is holding global read lock",
"Error connecting to master: %-.128s", "Error connecting to master: %-.128s",
"Error running query on master: %-.128s", "Error running query on master: %-.128s",
"Error in SHOW BINLOG EVENTS: %-.128s", "Error when executing command %s: %-.128s",
"Error in SHOW NEW MASTER: %-.128s",
...@@ -213,5 +213,4 @@ ...@@ -213,5 +213,4 @@
"CREATE DATABASE not allowed while thread is holding global read lock", "CREATE DATABASE not allowed while thread is holding global read lock",
"Error connecting to master: %-.128s", "Error connecting to master: %-.128s",
"Error running query on master: %-.128s", "Error running query on master: %-.128s",
"Error in SHOW BINLOG EVENTS: %-.128s", "Error when executing command %s: %-.128s",
"Error in SHOW NEW MASTER: %-.128s",
...@@ -215,5 +215,4 @@ ...@@ -215,5 +215,4 @@
"CREATE DATABASE not allowed while thread is holding global read lock", "CREATE DATABASE not allowed while thread is holding global read lock",
"Error connecting to master: %-.128s", "Error connecting to master: %-.128s",
"Error running query on master: %-.128s", "Error running query on master: %-.128s",
"Error in SHOW BINLOG EVENTS: %-.128s", "Error when executing command %s: %-.128s",
"Error in SHOW NEW MASTER: %-.128s",
...@@ -213,5 +213,4 @@ ...@@ -213,5 +213,4 @@
"CREATE DATABASE not allowed while thread is holding global read lock", "CREATE DATABASE not allowed while thread is holding global read lock",
"Error connecting to master: %-.128s", "Error connecting to master: %-.128s",
"Error running query on master: %-.128s", "Error running query on master: %-.128s",
"Error in SHOW BINLOG EVENTS: %-.128s", "Error when executing command %s: %-.128s",
"Error in SHOW NEW MASTER: %-.128s",
...@@ -215,5 +215,4 @@ ...@@ -215,5 +215,4 @@
"CREATE DATABASE not allowed while thread is holding global read lock", "CREATE DATABASE not allowed while thread is holding global read lock",
"Error connecting to master: %-.128s", "Error connecting to master: %-.128s",
"Error running query on master: %-.128s", "Error running query on master: %-.128s",
"Error in SHOW BINLOG EVENTS: %-.128s", "Error when executing command %s: %-.128s",
"Error in SHOW NEW MASTER: %-.128s",
...@@ -213,5 +213,4 @@ ...@@ -213,5 +213,4 @@
"CREATE DATABASE not allowed while thread is holding global read lock", "CREATE DATABASE not allowed while thread is holding global read lock",
"Error connecting to master: %-.128s", "Error connecting to master: %-.128s",
"Error running query on master: %-.128s", "Error running query on master: %-.128s",
"Error in SHOW BINLOG EVENTS: %-.128s", "Error when executing command %s: %-.128s",
"Error in SHOW NEW MASTER: %-.128s",
...@@ -215,5 +215,4 @@ ...@@ -215,5 +215,4 @@
"CREATE DATABASE not allowed while thread is holding global read lock", "CREATE DATABASE not allowed while thread is holding global read lock",
"Error connecting to master: %-.128s", "Error connecting to master: %-.128s",
"Error running query on master: %-.128s", "Error running query on master: %-.128s",
"Error in SHOW BINLOG EVENTS: %-.128s", "Error when executing command %s: %-.128s",
"Error in SHOW NEW MASTER: %-.128s",
...@@ -215,5 +215,4 @@ ...@@ -215,5 +215,4 @@
"CREATE DATABASE not allowed while thread is holding global read lock", "CREATE DATABASE not allowed while thread is holding global read lock",
"Error connecting to master: %-.128s", "Error connecting to master: %-.128s",
"Error running query on master: %-.128s", "Error running query on master: %-.128s",
"Error in SHOW BINLOG EVENTS: %-.128s", "Error when executing command %s: %-.128s",
"Error in SHOW NEW MASTER: %-.128s",
...@@ -217,5 +217,4 @@ ...@@ -217,5 +217,4 @@
"CREATE DATABASE not allowed while thread is holding global read lock", "CREATE DATABASE not allowed while thread is holding global read lock",
"Error connecting to master: %-.128s", "Error connecting to master: %-.128s",
"Error running query on master: %-.128s", "Error running query on master: %-.128s",
"Error in SHOW BINLOG EVENTS: %-.128s", "Error when executing command %s: %-.128s",
"Error in SHOW NEW MASTER: %-.128s",
...@@ -213,5 +213,4 @@ ...@@ -213,5 +213,4 @@
"CREATE DATABASE not allowed while thread is holding global read lock", "CREATE DATABASE not allowed while thread is holding global read lock",
"Error connecting to master: %-.128s", "Error connecting to master: %-.128s",
"Error running query on master: %-.128s", "Error running query on master: %-.128s",
"Error in SHOW BINLOG EVENTS: %-.128s", "Error when executing command %s: %-.128s",
"Error in SHOW NEW MASTER: %-.128s",
...@@ -217,5 +217,4 @@ ...@@ -217,5 +217,4 @@
"CREATE DATABASE not allowed while thread is holding global read lock", "CREATE DATABASE not allowed while thread is holding global read lock",
"Error connecting to master: %-.128s", "Error connecting to master: %-.128s",
"Error running query on master: %-.128s", "Error running query on master: %-.128s",
"Error in SHOW BINLOG EVENTS: %-.128s", "Error when executing command %s: %-.128s",
"Error in SHOW NEW MASTER: %-.128s",
...@@ -216,5 +216,4 @@ ...@@ -216,5 +216,4 @@
"CREATE DATABASE not allowed while thread is holding global read lock", "CREATE DATABASE not allowed while thread is holding global read lock",
"Error connecting to master: %-.128s", "Error connecting to master: %-.128s",
"Error running query on master: %-.128s", "Error running query on master: %-.128s",
"Error in SHOW BINLOG EVENTS: %-.128s", "Error when executing command %s: %-.128s",
"Error in SHOW NEW MASTER: %-.128s",
...@@ -221,5 +221,4 @@ ...@@ -221,5 +221,4 @@
"CREATE DATABASE not allowed while thread is holding global read lock", "CREATE DATABASE not allowed while thread is holding global read lock",
"Error connecting to master: %-.128s", "Error connecting to master: %-.128s",
"Error running query on master: %-.128s", "Error running query on master: %-.128s",
"Error in SHOW BINLOG EVENTS: %-.128s", "Error when executing command %s: %-.128s",
"Error in SHOW NEW MASTER: %-.128s",
...@@ -214,5 +214,4 @@ ...@@ -214,5 +214,4 @@
"CREATE DATABASE not allowed while thread is holding global read lock", "CREATE DATABASE not allowed while thread is holding global read lock",
"Error connecting to master: %-.128s", "Error connecting to master: %-.128s",
"Error running query on master: %-.128s", "Error running query on master: %-.128s",
"Error in SHOW BINLOG EVENTS: %-.128s", "Error when executing command %s: %-.128s",
"Error in SHOW NEW MASTER: %-.128s",
...@@ -209,9 +209,8 @@ ...@@ -209,9 +209,8 @@
"Lock wait timeout exceeded", "Lock wait timeout exceeded",
"The total number of locks exceeds the lock table size", "The total number of locks exceeds the lock table size",
"Update locks cannot be acquired during a READ UNCOMMITTED transaction", "Update locks cannot be acquired during a READ UNCOMMITTED transaction",
"DROP DATABASE not allowed while thread is holding global read lock", "DROP DATABASE är inte tillåtet när man har ett globalt läs-lås",
"CREATE DATABASE not allowed while thread is holding global read lock", "CREATE DATABASE är inte tillåtet när man har ett globalt läs-lås",
"Error connecting to master: %-.128s", "Fick fel vid anslutning till master: %-.128s",
"Error running query on master: %-.128s", "Fick fel vid utförande av command på mastern: %-.128s",
"Error in SHOW BINLOG EVENTS: %-.128s", "Fick fel vid utförande av %s: %-.128s",
"Error in SHOW NEW MASTER: %-.128s",
...@@ -421,7 +421,7 @@ public: ...@@ -421,7 +421,7 @@ public:
virtual int prepare(List<Item> &list) { return 0; } virtual int prepare(List<Item> &list) { return 0; }
virtual bool send_fields(List<Item> &list,uint flag)=0; virtual bool send_fields(List<Item> &list,uint flag)=0;
virtual bool send_data(List<Item> &items)=0; virtual bool send_data(List<Item> &items)=0;
virtual void initialize_tables (JOIN *join=0) {}; virtual void initialize_tables (JOIN *join=0) {}
virtual void send_error(uint errcode,const char *err)=0; virtual void send_error(uint errcode,const char *err)=0;
virtual bool send_eof()=0; virtual bool send_eof()=0;
virtual void abort() {} virtual void abort() {}
......
/* Copyright (C) 2000 MySQL AB & MySQL Finland AB & TCX DataKonsult AB & Sinisa /* Copyright (C) 2000 MySQL AB
This program is free software; you can redistribute it and/or modify This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by it under the terms of the GNU General Public License as published by
...@@ -316,14 +316,14 @@ multi_delete::multi_delete(THD *thd_arg, TABLE_LIST *dt, ...@@ -316,14 +316,14 @@ multi_delete::multi_delete(THD *thd_arg, TABLE_LIST *dt,
#endif #endif
(void) dt->table->file->extra(HA_EXTRA_NO_READCHECK); (void) dt->table->file->extra(HA_EXTRA_NO_READCHECK);
(void) dt->table->file->extra(HA_EXTRA_NO_KEYREAD);
/* Don't use key read with MULTI-TABLE-DELETE */ /* Don't use key read with MULTI-TABLE-DELETE */
(void) dt->table->file->extra(HA_EXTRA_NO_KEYREAD);
dt->table->used_keys=0; dt->table->used_keys=0;
for (dt=dt->next ; dt ; dt=dt->next,counter++) for (dt=dt->next ; dt ; dt=dt->next,counter++)
{ {
TABLE *table=dt->table; TABLE *table=dt->table;
(void) dt->table->file->extra(HA_EXTRA_NO_READCHECK); (void) dt->table->file->extra(HA_EXTRA_NO_READCHECK);
(void) dt->table->file->extra(HA_EXTRA_NO_KEYREAD); (void) dt->table->file->extra(HA_EXTRA_NO_KEYREAD);
#ifdef SINISAS_STRIP #ifdef SINISAS_STRIP
tempfiles[counter]=(IO_CACHE *) sql_alloc(sizeof(IO_CACHE)); tempfiles[counter]=(IO_CACHE *) sql_alloc(sizeof(IO_CACHE));
if (open_cached_file(tempfiles[counter], mysql_tmpdir,TEMP_PREFIX, if (open_cached_file(tempfiles[counter], mysql_tmpdir,TEMP_PREFIX,
...@@ -366,50 +366,38 @@ multi_delete::prepare(List<Item> &values) ...@@ -366,50 +366,38 @@ multi_delete::prepare(List<Item> &values)
DBUG_RETURN(0); DBUG_RETURN(0);
} }
inline static void
link_in_list(SQL_LIST *list,byte *element,byte **next)
{
list->elements++;
(*list->next)=element;
list->next=next;
*next=0;
}
void void
multi_delete::initialize_tables(JOIN *join) multi_delete::initialize_tables(JOIN *join)
{ {
SQL_LIST *new_list=(SQL_LIST *) sql_alloc(sizeof(SQL_LIST)); TABLE_LIST *walk;
new_list->elements=0; new_list->first=0; table_map tables_to_delete_from=0;
new_list->next= (byte**) &(new_list->first); for (walk= delete_tables ; walk ; walk=walk->next)
tables_to_delete_from|= walk->table->map;
walk= delete_tables;
for (JOIN_TAB *tab=join->join_tab, *end=join->join_tab+join->tables; for (JOIN_TAB *tab=join->join_tab, *end=join->join_tab+join->tables;
tab < end; tab < end;
tab++) tab++)
{ {
TABLE_LIST *walk; if (tab->table->map & tables_to_delete_from)
for (walk=(TABLE_LIST*) delete_tables ; walk ; walk=walk->next)
if (!strcmp(tab->table->path,walk->table->path))
break;
if (walk) // Table need not be the one to be deleted
{ {
register TABLE_LIST *ptr = (TABLE_LIST *) sql_alloc(sizeof(TABLE_LIST)); /* We are going to delete from this table */
memcpy(ptr,walk,sizeof(TABLE_LIST)); ptr->next=0; walk->table=tab->table;
link_in_list(new_list,(byte*) ptr,(byte**) &ptr->next); walk=walk->next;
} }
} }
delete_tables=(TABLE_LIST *)new_list->first;
return;
} }
multi_delete::~multi_delete() multi_delete::~multi_delete()
{ {
/* Add back EXTRA_READCHECK; In 4.0.1 we shouldn't need this anymore */ /* Add back EXTRA_READCHECK; In 4.0.1 we shouldn't need this anymore */
for (table_being_deleted=delete_tables ; for (table_being_deleted=delete_tables ;
table_being_deleted ; table_being_deleted ;
table_being_deleted=table_being_deleted->next) table_being_deleted=table_being_deleted->next)
{ (void) table_being_deleted->table->file->extra(HA_EXTRA_READCHECK);
VOID(table_being_deleted->table->file->extra(HA_EXTRA_READCHECK));
}
for (uint counter = 0; counter < num_of_tables-1; counter++) for (uint counter = 0; counter < num_of_tables-1; counter++)
{ {
if (tempfiles[counter]) if (tempfiles[counter])
......
/* Copyright (C) 2000 MySQL AB & MySQL Finland AB & TCX DataKonsult AB /* Copyright (C) 2000 MySQL AB & MySQL Finland AB & TCX DataKonsult AB & Sasha
This program is free software; you can redistribute it and/or modify This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by it under the terms of the GNU General Public License as published by
...@@ -76,13 +76,8 @@ static int fake_rotate_event(NET* net, String* packet, char* log_file_name, ...@@ -76,13 +76,8 @@ static int fake_rotate_event(NET* net, String* packet, char* log_file_name,
char header[LOG_EVENT_HEADER_LEN], buf[ROTATE_HEADER_LEN]; char header[LOG_EVENT_HEADER_LEN], buf[ROTATE_HEADER_LEN];
memset(header, 0, 4); // when does not matter memset(header, 0, 4); // when does not matter
header[EVENT_TYPE_OFFSET] = ROTATE_EVENT; header[EVENT_TYPE_OFFSET] = ROTATE_EVENT;
char* p = strrchr(log_file_name, FN_LIBCHAR);
// find the last slash
if(p)
p++;
else
p = log_file_name;
char* p = log_file_name+dirname_length(log_file_name);
uint ident_len = (uint) strlen(p); uint ident_len = (uint) strlen(p);
ulong event_len = ident_len + ROTATE_EVENT_OVERHEAD; ulong event_len = ident_len + ROTATE_EVENT_OVERHEAD;
int4store(header + SERVER_ID_OFFSET, server_id); int4store(header + SERVER_ID_OFFSET, server_id);
...@@ -93,59 +88,55 @@ static int fake_rotate_event(NET* net, String* packet, char* log_file_name, ...@@ -93,59 +88,55 @@ static int fake_rotate_event(NET* net, String* packet, char* log_file_name,
int8store(buf, 4); // tell slave to skip magic number int8store(buf, 4); // tell slave to skip magic number
packet->append(buf, ROTATE_HEADER_LEN); packet->append(buf, ROTATE_HEADER_LEN);
packet->append(p,ident_len); packet->append(p,ident_len);
if(my_net_write(net, (char*)packet->ptr(), packet->length())) if (my_net_write(net, (char*)packet->ptr(), packet->length()))
{ {
*errmsg = "failed on my_net_write()"; *errmsg = "failed on my_net_write()";
return -1; return -1;
} }
return 0; return 0;
} }
#define get_object(p, obj) \
{\
uint len = (uint)*p++; \
if (p + len > p_end || len >= sizeof(obj)) \
goto err; \
strmake(obj,(char*) p,len); \
p+= len; \
}\
int register_slave(THD* thd, uchar* packet, uint packet_length) int register_slave(THD* thd, uchar* packet, uint packet_length)
{ {
uint len; uint len;
SLAVE_INFO* si, *old_si; SLAVE_INFO *si, *old_si;
int res = 1; int res = 1;
uchar* p = packet, *p_end = packet + packet_length; uchar* p = packet, *p_end = packet + packet_length;
if(check_access(thd, FILE_ACL, any_db)) if (check_access(thd, FILE_ACL, any_db))
return 1; return 1;
if(!(si = (SLAVE_INFO*)my_malloc(sizeof(SLAVE_INFO), MYF(MY_WME)))) if (!(si = (SLAVE_INFO*)my_malloc(sizeof(SLAVE_INFO), MYF(MY_WME))))
goto err; goto err;
si->server_id = uint4korr(p); si->server_id = uint4korr(p);
p += 4; p += 4;
len = (uint)*p++; get_object(p,si->host);
if(p + len > p_end || len > sizeof(si->host) - 1) get_object(p,si->user);
goto err; get_object(p,si->password);
memcpy(si->host, p, len);
si->host[len] = 0;
p += len;
len = *p++;
if(p + len > p_end || len > sizeof(si->user) - 1)
goto err;
memcpy(si->user, p, len);
si->user[len] = 0;
p += len;
len = *p++;
if(p + len > p_end || len > sizeof(si->password) - 1)
goto err;
memcpy(si->password, p, len);
si->password[len] = 0;
p += len;
si->port = uint2korr(p); si->port = uint2korr(p);
pthread_mutex_lock(&LOCK_slave_list); pthread_mutex_lock(&LOCK_slave_list);
if((old_si = (SLAVE_INFO*)hash_search(&slave_list, if ((old_si = (SLAVE_INFO*)hash_search(&slave_list,
(byte*)&si->server_id, 4))) (byte*)&si->server_id, 4)))
hash_delete(&slave_list, (byte*)old_si); hash_delete(&slave_list, (byte*)old_si);
res = hash_insert(&slave_list, (byte*)si); res = hash_insert(&slave_list, (byte*) si);
pthread_mutex_unlock(&LOCK_slave_list); pthread_mutex_unlock(&LOCK_slave_list);
return res; return res;
err: err:
if(si) if (si)
my_free((byte*)si, MYF(MY_WME)); my_free((byte*)si, MYF(MY_WME));
return res; return res;
} }
...@@ -156,10 +147,10 @@ static int send_file(THD *thd) ...@@ -156,10 +147,10 @@ static int send_file(THD *thd)
NET* net = &thd->net; NET* net = &thd->net;
int fd = -1,bytes, error = 1; int fd = -1,bytes, error = 1;
char fname[FN_REFLEN+1]; char fname[FN_REFLEN+1];
char *buf;
const char *errmsg = 0; const char *errmsg = 0;
int old_timeout; int old_timeout;
uint packet_len; uint packet_len;
char buf[IO_SIZE]; // It's safe to alloc this
DBUG_ENTER("send_file"); DBUG_ENTER("send_file");
// the client might be slow loading the data, give him wait_timeout to do // the client might be slow loading the data, give him wait_timeout to do
...@@ -167,40 +158,32 @@ static int send_file(THD *thd) ...@@ -167,40 +158,32 @@ static int send_file(THD *thd)
old_timeout = thd->net.timeout; old_timeout = thd->net.timeout;
thd->net.timeout = thd->inactive_timeout; thd->net.timeout = thd->inactive_timeout;
// spare the stack
if(!(buf = alloc_root(&thd->mem_root,IO_SIZE)))
{
errmsg = "Out of memory";
goto err;
}
// we need net_flush here because the client will not know it needs to send // we need net_flush here because the client will not know it needs to send
// us the file name until it has processed the load event entry // us the file name until it has processed the load event entry
if (net_flush(net) || (packet_len = my_net_read(net)) == packet_error) if (net_flush(net) || (packet_len = my_net_read(net)) == packet_error)
{ {
errmsg = "Failed reading file name"; errmsg = "while reading file name";
goto err; goto err;
} }
*((char*)net->read_pos + packet_len) = 0; // terminate with \0 // terminate with \0 for fn_format
//for fn_format *((char*)net->read_pos + packet_len) = 0;
fn_format(fname, (char*)net->read_pos + 1, "", "", 4); fn_format(fname, (char*) net->read_pos + 1, "", "", 4);
// this is needed to make replicate-ignore-db // this is needed to make replicate-ignore-db
if (!strcmp(fname,"/dev/null")) if (!strcmp(fname,"/dev/null"))
goto end; goto end;
if ((fd = my_open(fname, O_RDONLY, MYF(MY_WME))) < 0) if ((fd = my_open(fname, O_RDONLY, MYF(0))) < 0)
{ {
errmsg = "Failed on my_open()"; errmsg = "on open of file";
goto err; goto err;
} }
while ((bytes = (int) my_read(fd, (byte*) buf, IO_SIZE, while ((bytes = (int) my_read(fd, (byte*) buf, IO_SIZE, MYF(0))) > 0)
MYF(MY_WME))) > 0)
{ {
if (my_net_write(net, buf, bytes)) if (my_net_write(net, buf, bytes))
{ {
errmsg = "Failed on my_net_write()"; errmsg = "while writing data to client";
goto err; goto err;
} }
} }
...@@ -209,18 +192,18 @@ static int send_file(THD *thd) ...@@ -209,18 +192,18 @@ static int send_file(THD *thd)
if (my_net_write(net, "", 0) || net_flush(net) || if (my_net_write(net, "", 0) || net_flush(net) ||
(my_net_read(net) == packet_error)) (my_net_read(net) == packet_error))
{ {
errmsg = "failed negotiating file transfer close"; errmsg = "while negotiating file transfer close";
goto err; goto err;
} }
error = 0; error = 0;
err: err:
thd->net.timeout = old_timeout; thd->net.timeout = old_timeout;
if(fd >= 0) if (fd >= 0)
(void) my_close(fd, MYF(MY_WME)); (void) my_close(fd, MYF(0));
if (errmsg) if (errmsg)
{ {
sql_print_error("failed in send_file() : %s", errmsg); sql_print_error("Failed in send_file() %s", errmsg);
DBUG_PRINT("error", (errmsg)); DBUG_PRINT("error", (errmsg));
} }
DBUG_RETURN(error); DBUG_RETURN(error);
...@@ -228,34 +211,37 @@ static int send_file(THD *thd) ...@@ -228,34 +211,37 @@ static int send_file(THD *thd)
File open_binlog(IO_CACHE *log, const char *log_file_name, File open_binlog(IO_CACHE *log, const char *log_file_name,
const char **errmsg) const char **errmsg)
{ {
File file; File file;
char magic[4]; char magic[4];
if ((file = my_open(log_file_name, O_RDONLY | O_BINARY, MYF(MY_WME))) < 0 || if ((file = my_open(log_file_name, O_RDONLY | O_BINARY, MYF(MY_WME))) < 0 ||
init_io_cache(log, file, IO_SIZE*2, READ_CACHE, 0, 0, init_io_cache(log, file, IO_SIZE*2, READ_CACHE, 0, 0,
MYF(MY_WME))) MYF(MY_WME)))
{ {
*errmsg = "Could not open log file"; // This will not be sent *errmsg = "Could not open log file"; // This will not be sent
goto err; goto err;
} }
if (my_b_read(log, (byte*) magic, sizeof(magic))) if (my_b_read(log, (byte*) magic, sizeof(magic)))
{ {
*errmsg = "I/O error reading binlog magic number"; *errmsg = "I/O error reading the header from the binary log";
goto err; goto err;
} }
if (memcmp(magic, BINLOG_MAGIC, 4)) if (memcmp(magic, BINLOG_MAGIC, sizeof(magic)))
{ {
*errmsg = "Binlog has bad magic number, fire your magician"; *errmsg = "Binlog has bad magic number; It's not a binary log file that can be used by this version of MySQL";
goto err; goto err;
} }
return file; return file;
err: err:
if (file > 0) if (file >= 0)
{
my_close(file,MYF(0)); my_close(file,MYF(0));
end_io_cache(log); end_io_cache(log);
}
return -1; return -1;
} }
...@@ -263,26 +249,26 @@ err: ...@@ -263,26 +249,26 @@ err:
void adjust_linfo_offsets(my_off_t purge_offset) void adjust_linfo_offsets(my_off_t purge_offset)
{ {
THD *tmp; THD *tmp;
pthread_mutex_lock(&LOCK_thread_count); pthread_mutex_lock(&LOCK_thread_count);
I_List_iterator<THD> it(threads); I_List_iterator<THD> it(threads);
while((tmp=it++))
{
LOG_INFO* linfo;
if((linfo = tmp->current_linfo))
{
pthread_mutex_lock(&linfo->lock);
// no big deal if we just started reading the log
// nothing to adjust
if(linfo->index_file_offset < purge_offset)
linfo->fatal = (linfo->index_file_offset != 0);
else
linfo->index_file_offset -= purge_offset;
pthread_mutex_unlock(&linfo->lock);
}
}
while ((tmp=it++))
{
LOG_INFO* linfo;
if ((linfo = tmp->current_linfo))
{
pthread_mutex_lock(&linfo->lock);
// Why (monty): I don't understand this comment
// no big deal if we just started reading the log
// nothing to adjust
if (linfo->index_file_offset < purge_offset)
linfo->fatal = (linfo->index_file_offset != 0);
else
linfo->index_file_offset -= purge_offset;
pthread_mutex_unlock(&linfo->lock);
}
}
pthread_mutex_unlock(&LOCK_thread_count); pthread_mutex_unlock(&LOCK_thread_count);
} }
...@@ -292,21 +278,21 @@ bool log_in_use(const char* log_name) ...@@ -292,21 +278,21 @@ bool log_in_use(const char* log_name)
int log_name_len = strlen(log_name) + 1; int log_name_len = strlen(log_name) + 1;
THD *tmp; THD *tmp;
bool result = 0; bool result = 0;
pthread_mutex_lock(&LOCK_thread_count); pthread_mutex_lock(&LOCK_thread_count);
I_List_iterator<THD> it(threads); I_List_iterator<THD> it(threads);
while((tmp=it++)) while ((tmp=it++))
{
LOG_INFO* linfo;
if ((linfo = tmp->current_linfo))
{ {
LOG_INFO* linfo; pthread_mutex_lock(&linfo->lock);
if((linfo = tmp->current_linfo)) result = !memcmp(log_name, linfo->log_file_name, log_name_len);
{ pthread_mutex_unlock(&linfo->lock);
pthread_mutex_lock(&linfo->lock); if (result) break;
result = !memcmp(log_name, linfo->log_file_name, log_name_len); }
pthread_mutex_unlock(&linfo->lock); }
if(result) break;
}
}
pthread_mutex_unlock(&LOCK_thread_count); pthread_mutex_unlock(&LOCK_thread_count);
return result; return result;
...@@ -316,35 +302,35 @@ bool log_in_use(const char* log_name) ...@@ -316,35 +302,35 @@ bool log_in_use(const char* log_name)
int purge_master_logs(THD* thd, const char* to_log) int purge_master_logs(THD* thd, const char* to_log)
{ {
char search_file_name[FN_REFLEN]; char search_file_name[FN_REFLEN];
const char* errmsg = 0;
mysql_bin_log.make_log_name(search_file_name, to_log); mysql_bin_log.make_log_name(search_file_name, to_log);
int res = mysql_bin_log.purge_logs(thd, search_file_name); int res = mysql_bin_log.purge_logs(thd, search_file_name);
const char* errmsg = 0;
switch(res) switch(res) {
{ case 0: break;
case 0: break; case LOG_INFO_EOF: errmsg = "Target log not found in binlog index"; break;
case LOG_INFO_EOF: errmsg = "Target log not found in binlog index"; break; case LOG_INFO_IO: errmsg = "I/O error reading log index file"; break;
case LOG_INFO_IO: errmsg = "I/O error reading log index file"; break; case LOG_INFO_INVALID: errmsg = "Server configuration does not permit \
case LOG_INFO_INVALID: errmsg = "Server configuration does not permit \
binlog purge"; break; binlog purge"; break;
case LOG_INFO_SEEK: errmsg = "Failed on fseek()"; break; case LOG_INFO_SEEK: errmsg = "Failed on fseek()"; break;
case LOG_INFO_PURGE_NO_ROTATE: errmsg = "Cannot purge unrotatable log"; case LOG_INFO_PURGE_NO_ROTATE: errmsg = "Cannot purge unrotatable log";
break; break;
case LOG_INFO_MEM: errmsg = "Out of memory"; break; case LOG_INFO_MEM: errmsg = "Out of memory"; break;
case LOG_INFO_FATAL: errmsg = "Fatal error during purge"; break; case LOG_INFO_FATAL: errmsg = "Fatal error during purge"; break;
case LOG_INFO_IN_USE: errmsg = "A purgeable log is in use, will not purge"; case LOG_INFO_IN_USE: errmsg = "A purgeable log is in use, will not purge";
break; break;
default: default: errmsg = "Unknown error during purge"; break;
errmsg = "Unknown error during purge"; break; }
}
if (errmsg)
if(errmsg) {
{ send_error(&thd->net, 0, errmsg);
send_error(&thd->net, 0, errmsg); return 1;
return 1; }
}
else else
send_ok(&thd->net); send_ok(&thd->net);
return 0; return 0;
} }
...@@ -362,7 +348,7 @@ void mysql_binlog_send(THD* thd, char* log_ident, ulong pos, ushort flags) ...@@ -362,7 +348,7 @@ void mysql_binlog_send(THD* thd, char* log_ident, ulong pos, ushort flags)
NET* net = &thd->net; NET* net = &thd->net;
#ifndef DBUG_OFF #ifndef DBUG_OFF
int left_events = max_binlog_dump_events; int left_events = max_binlog_dump_events;
#endif #endif
DBUG_ENTER("mysql_binlog_send"); DBUG_ENTER("mysql_binlog_send");
#ifndef DBUG_OFF #ifndef DBUG_OFF
...@@ -371,26 +357,26 @@ void mysql_binlog_send(THD* thd, char* log_ident, ulong pos, ushort flags) ...@@ -371,26 +357,26 @@ void mysql_binlog_send(THD* thd, char* log_ident, ulong pos, ushort flags)
errmsg = "Master failed COM_BINLOG_DUMP to test if slave can recover"; errmsg = "Master failed COM_BINLOG_DUMP to test if slave can recover";
goto err; goto err;
} }
#endif #endif
bzero((char*) &log,sizeof(log)); bzero((char*) &log,sizeof(log));
if(!mysql_bin_log.is_open()) if (!mysql_bin_log.is_open())
{ {
errmsg = "Binary log is not open"; errmsg = "Binary log is not open";
goto err; goto err;
} }
if(!server_id_supplied) if (!server_id_supplied)
{ {
errmsg = "Misconfigured master - server id was not set"; errmsg = "Misconfigured master - server id was not set";
goto err; goto err;
} }
if (log_ident[0]) if (log_ident[0])
mysql_bin_log.make_log_name(search_file_name, log_ident); mysql_bin_log.make_log_name(search_file_name, log_ident);
else else
search_file_name[0] = 0; search_file_name[0] = 0;
linfo.index_file_offset = 0; linfo.index_file_offset = 0;
thd->current_linfo = &linfo; thd->current_linfo = &linfo;
...@@ -409,17 +395,17 @@ void mysql_binlog_send(THD* thd, char* log_ident, ulong pos, ushort flags) ...@@ -409,17 +395,17 @@ void mysql_binlog_send(THD* thd, char* log_ident, ulong pos, ushort flags)
impossible position"; impossible position";
goto err; goto err;
} }
my_b_seek(&log, pos); // Seek will done on next read my_b_seek(&log, pos); // Seek will done on next read
packet->length(0); packet->length(0);
packet->append("\0", 1);
// we need to start a packet with something other than 255 // we need to start a packet with something other than 255
// to distiquish it from error // to distiquish it from error
packet->append("\0", 1);
// tell the client log name with a fake rotate_event
// if we are at the start of the log // if we are at the start of the log
if(pos == 4) if (pos == 4)
{ {
// tell the client log name with a fake rotate_event
if (fake_rotate_event(net, packet, log_file_name, &errmsg)) if (fake_rotate_event(net, packet, log_file_name, &errmsg))
goto err; goto err;
packet->length(0); packet->length(0);
...@@ -429,17 +415,17 @@ impossible position"; ...@@ -429,17 +415,17 @@ impossible position";
while (!net->error && net->vio != 0 && !thd->killed) while (!net->error && net->vio != 0 && !thd->killed)
{ {
pthread_mutex_t *log_lock = mysql_bin_log.get_log_lock(); pthread_mutex_t *log_lock = mysql_bin_log.get_log_lock();
while (!(error = Log_event::read_log_event(&log, packet, log_lock))) while (!(error = Log_event::read_log_event(&log, packet, log_lock)))
{ {
#ifndef DBUG_OFF #ifndef DBUG_OFF
if(max_binlog_dump_events && !left_events--) if (max_binlog_dump_events && !left_events--)
{ {
net_flush(net); net_flush(net);
errmsg = "Debugging binlog dump abort"; errmsg = "Debugging binlog dump abort";
goto err; goto err;
} }
#endif #endif
if (my_net_write(net, (char*)packet->ptr(), packet->length()) ) if (my_net_write(net, (char*)packet->ptr(), packet->length()) )
{ {
errmsg = "Failed on my_net_write()"; errmsg = "Failed on my_net_write()";
...@@ -449,7 +435,7 @@ impossible position"; ...@@ -449,7 +435,7 @@ impossible position";
(*packet)[LOG_EVENT_OFFSET+1] )); (*packet)[LOG_EVENT_OFFSET+1] ));
if ((*packet)[LOG_EVENT_OFFSET+1] == LOAD_EVENT) if ((*packet)[LOG_EVENT_OFFSET+1] == LOAD_EVENT)
{ {
if(send_file(thd)) if (send_file(thd))
{ {
errmsg = "failed in send_file()"; errmsg = "failed in send_file()";
goto err; goto err;
...@@ -458,15 +444,14 @@ impossible position"; ...@@ -458,15 +444,14 @@ impossible position";
packet->length(0); packet->length(0);
packet->append("\0",1); packet->append("\0",1);
} }
if (error != LOG_READ_EOF) if (error != LOG_READ_EOF)
{ {
switch(error) switch(error) {
{ case LOG_READ_BOGUS:
case LOG_READ_BOGUS:
errmsg = "bogus data in log event"; errmsg = "bogus data in log event";
break; break;
case LOG_READ_TOO_LARGE: case LOG_READ_TOO_LARGE:
errmsg = "log event entry exceeded max_allowed_packet -\ errmsg = "log event entry exceeded max_allowed_packet -\
increase max_allowed_packet on master"; increase max_allowed_packet on master";
break; break;
...@@ -486,12 +471,12 @@ impossible position"; ...@@ -486,12 +471,12 @@ impossible position";
goto err; goto err;
} }
if(!(flags & BINLOG_DUMP_NON_BLOCK) && if (!(flags & BINLOG_DUMP_NON_BLOCK) &&
mysql_bin_log.is_active(log_file_name)) mysql_bin_log.is_active(log_file_name))
{
// block until there is more data in the log // block until there is more data in the log
// unless non-blocking mode requested // unless non-blocking mode requested
{ if (net_flush(net))
if(net_flush(net))
{ {
errmsg = "failed on net_flush()"; errmsg = "failed on net_flush()";
goto err; goto err;
...@@ -515,13 +500,13 @@ impossible position"; ...@@ -515,13 +500,13 @@ impossible position";
bool read_packet = 0, fatal_error = 0; bool read_packet = 0, fatal_error = 0;
#ifndef DBUG_OFF #ifndef DBUG_OFF
if(max_binlog_dump_events && !left_events--) if (max_binlog_dump_events && !left_events--)
{ {
net_flush(net); net_flush(net);
errmsg = "Debugging binlog dump abort"; errmsg = "Debugging binlog dump abort";
goto err; goto err;
} }
#endif #endif
// no one will update the log while we are reading // no one will update the log while we are reading
// now, but we'll be quick and just read one record // now, but we'll be quick and just read one record
...@@ -550,18 +535,18 @@ impossible position"; ...@@ -550,18 +535,18 @@ impossible position";
thd->proc_info= proc_info; thd->proc_info= proc_info;
pthread_mutex_unlock(&thd->mysys_var->mutex); pthread_mutex_unlock(&thd->mysys_var->mutex);
if(read_packet) if (read_packet)
{ {
thd->proc_info = "sending update to slave"; thd->proc_info = "sending update to slave";
if(my_net_write(net, (char*)packet->ptr(), packet->length()) ) if (my_net_write(net, (char*)packet->ptr(), packet->length()) )
{ {
errmsg = "Failed on my_net_write()"; errmsg = "Failed on my_net_write()";
goto err; goto err;
} }
if((*packet)[LOG_EVENT_OFFSET+1] == LOAD_EVENT) if ((*packet)[LOG_EVENT_OFFSET+1] == LOAD_EVENT)
{ {
if(send_file(thd)) if (send_file(thd))
{ {
errmsg = "failed in send_file()"; errmsg = "failed in send_file()";
goto err; goto err;
...@@ -573,7 +558,7 @@ impossible position"; ...@@ -573,7 +558,7 @@ impossible position";
// we hit EOF pretty quick // we hit EOF pretty quick
} }
if(fatal_error) if (fatal_error)
{ {
errmsg = "error reading log entry"; errmsg = "error reading log entry";
goto err; goto err;
...@@ -586,8 +571,7 @@ impossible position"; ...@@ -586,8 +571,7 @@ impossible position";
bool loop_breaker = 0; bool loop_breaker = 0;
// need this to break out of the for loop from switch // need this to break out of the for loop from switch
thd->proc_info = "switching to next log"; thd->proc_info = "switching to next log";
switch(mysql_bin_log.find_next_log(&linfo)) switch (mysql_bin_log.find_next_log(&linfo)) {
{
case LOG_INFO_EOF: case LOG_INFO_EOF:
loop_breaker = (flags & BINLOG_DUMP_NON_BLOCK); loop_breaker = (flags & BINLOG_DUMP_NON_BLOCK);
break; break;
...@@ -598,12 +582,12 @@ impossible position"; ...@@ -598,12 +582,12 @@ impossible position";
goto err; goto err;
} }
if(loop_breaker) if (loop_breaker)
break; break;
end_io_cache(&log); end_io_cache(&log);
(void) my_close(file, MYF(MY_WME)); (void) my_close(file, MYF(MY_WME));
// fake Rotate_log event just in case it did not make it to the log // fake Rotate_log event just in case it did not make it to the log
// otherwise the slave make get confused about the offset // otherwise the slave make get confused about the offset
if ((file=open_binlog(&log, log_file_name, &errmsg)) < 0 || if ((file=open_binlog(&log, log_file_name, &errmsg)) < 0 ||
...@@ -617,13 +601,14 @@ impossible position"; ...@@ -617,13 +601,14 @@ impossible position";
end_io_cache(&log); end_io_cache(&log);
(void)my_close(file, MYF(MY_WME)); (void)my_close(file, MYF(MY_WME));
send_eof(&thd->net); send_eof(&thd->net);
thd->proc_info = "waiting to finalize termination"; thd->proc_info = "waiting to finalize termination";
pthread_mutex_lock(&LOCK_thread_count); pthread_mutex_lock(&LOCK_thread_count);
thd->current_linfo = 0; thd->current_linfo = 0;
pthread_mutex_unlock(&LOCK_thread_count); pthread_mutex_unlock(&LOCK_thread_count);
DBUG_VOID_RETURN; DBUG_VOID_RETURN;
err: err:
thd->proc_info = "waiting to finalize termination"; thd->proc_info = "waiting to finalize termination";
end_io_cache(&log); end_io_cache(&log);
...@@ -643,50 +628,52 @@ impossible position"; ...@@ -643,50 +628,52 @@ impossible position";
int start_slave(THD* thd , bool net_report) int start_slave(THD* thd , bool net_report)
{ {
if(!thd) thd = current_thd;
NET* net = &thd->net;
int slave_errno = 0; int slave_errno = 0;
if (!thd) thd = current_thd;
NET* net = &thd->net;
if (check_access(thd, PROCESS_ACL, any_db)) if (check_access(thd, PROCESS_ACL, any_db))
return 1; return 1;
pthread_mutex_lock(&LOCK_slave); pthread_mutex_lock(&LOCK_slave);
if(!slave_running) if (!slave_running)
{
if (init_master_info(&glob_mi))
slave_errno = ER_MASTER_INFO;
else if (server_id_supplied && *glob_mi.host)
{ {
if(init_master_info(&glob_mi)) pthread_t hThread;
slave_errno = ER_MASTER_INFO; if (pthread_create(&hThread, &connection_attrib, handle_slave, 0))
else if(server_id_supplied && *glob_mi.host) {
{ slave_errno = ER_SLAVE_THREAD;
pthread_t hThread; }
if(pthread_create(&hThread, &connection_attrib, handle_slave, 0)) while (!slave_running) // slave might already be running by now
{ pthread_cond_wait(&COND_slave_start, &LOCK_slave);
slave_errno = ER_SLAVE_THREAD;
}
while(!slave_running) // slave might already be running by now
pthread_cond_wait(&COND_slave_start, &LOCK_slave);
}
else
slave_errno = ER_BAD_SLAVE;
} }
else
slave_errno = ER_BAD_SLAVE;
}
else else
slave_errno = ER_SLAVE_MUST_STOP; slave_errno = ER_SLAVE_MUST_STOP;
pthread_mutex_unlock(&LOCK_slave); pthread_mutex_unlock(&LOCK_slave);
if(slave_errno) if (slave_errno)
{ {
if(net_report) send_error(net, slave_errno); if (net_report) send_error(net, slave_errno);
return 1; return 1;
} }
else if(net_report) else if (net_report)
send_ok(net); send_ok(net);
return 0; return 0;
} }
int stop_slave(THD* thd, bool net_report ) int stop_slave(THD* thd, bool net_report )
{ {
if(!thd) thd = current_thd;
NET* net = &thd->net;
int slave_errno = 0; int slave_errno = 0;
if (!thd) thd = current_thd;
NET* net = &thd->net;
if (check_access(thd, PROCESS_ACL, any_db)) if (check_access(thd, PROCESS_ACL, any_db))
return 1; return 1;
...@@ -697,11 +684,11 @@ int stop_slave(THD* thd, bool net_report ) ...@@ -697,11 +684,11 @@ int stop_slave(THD* thd, bool net_report )
thr_alarm_kill(slave_real_id); thr_alarm_kill(slave_real_id);
#ifdef SIGNAL_WITH_VIO_CLOSE #ifdef SIGNAL_WITH_VIO_CLOSE
slave_thd->close_active_vio(); slave_thd->close_active_vio();
#endif #endif
// do not abort the slave in the middle of a query, so we do not set // do not abort the slave in the middle of a query, so we do not set
// thd->killed for the slave thread // thd->killed for the slave thread
thd->proc_info = "waiting for slave to die"; thd->proc_info = "waiting for slave to die";
while(slave_running) while (slave_running)
pthread_cond_wait(&COND_slave_stopped, &LOCK_slave); pthread_cond_wait(&COND_slave_stopped, &LOCK_slave);
} }
else else
...@@ -710,17 +697,19 @@ int stop_slave(THD* thd, bool net_report ) ...@@ -710,17 +697,19 @@ int stop_slave(THD* thd, bool net_report )
pthread_mutex_unlock(&LOCK_slave); pthread_mutex_unlock(&LOCK_slave);
thd->proc_info = 0; thd->proc_info = 0;
if(slave_errno) if (slave_errno)
{ {
if(net_report) send_error(net, slave_errno); if (net_report)
return 1; send_error(net, slave_errno);
} return 1;
else if(net_report) }
else if (net_report)
send_ok(net); send_ok(net);
return 0; return 0;
} }
void reset_slave() void reset_slave()
{ {
MY_STAT stat_area; MY_STAT stat_area;
...@@ -728,115 +717,113 @@ void reset_slave() ...@@ -728,115 +717,113 @@ void reset_slave()
bool slave_was_running ; bool slave_was_running ;
pthread_mutex_lock(&LOCK_slave); pthread_mutex_lock(&LOCK_slave);
if((slave_was_running = slave_running)) if ((slave_was_running = slave_running))
{ {
pthread_mutex_unlock(&LOCK_slave); pthread_mutex_unlock(&LOCK_slave);
stop_slave(0,0); stop_slave(0,0);
} }
else else
pthread_mutex_unlock(&LOCK_slave); pthread_mutex_unlock(&LOCK_slave);
end_master_info(&glob_mi); end_master_info(&glob_mi);
fn_format(fname, master_info_file, mysql_data_home, "", 4+32); fn_format(fname, master_info_file, mysql_data_home, "", 4+32);
if(my_stat(fname, &stat_area, MYF(0))) if (my_stat(fname, &stat_area, MYF(0)) && my_delete(fname, MYF(MY_WME)))
if(my_delete(fname, MYF(MY_WME))) return;
return; if (slave_was_running)
if(slave_was_running)
start_slave(0,0); start_slave(0,0);
} }
void kill_zombie_dump_threads(uint32 slave_server_id) void kill_zombie_dump_threads(uint32 slave_server_id)
{ {
pthread_mutex_lock(&LOCK_thread_count); pthread_mutex_lock(&LOCK_thread_count);
I_List_iterator<THD> it(threads); I_List_iterator<THD> it(threads);
THD *tmp; THD *tmp;
while((tmp=it++)) while ((tmp=it++))
{
if (tmp->command == COM_BINLOG_DUMP &&
tmp->server_id == slave_server_id)
{ {
if(tmp->command == COM_BINLOG_DUMP && // here we do not call kill_one_thread()
tmp->server_id == slave_server_id) // it will be slow because it will iterate through the list
{ // again. Plus it double-locks LOCK_thread_count, which
// here we do not call kill_one_thread() // make safe_mutex complain and abort
// it will be slow because it will iterate through the list // so we just to our own thread murder
// again. Plus it double-locks LOCK_thread_count, which
// make safe_mutex complain and abort thr_alarm_kill(tmp->real_id);
// so we just to our own thread murder tmp->killed = 1;
pthread_mutex_lock(&tmp->mysys_var->mutex);
thr_alarm_kill(tmp->real_id); tmp->mysys_var->abort = 1;
tmp->killed = 1; if (tmp->mysys_var->current_mutex)
pthread_mutex_lock(&tmp->mysys_var->mutex); {
tmp->mysys_var->abort = 1; pthread_mutex_lock(tmp->mysys_var->current_mutex);
if(tmp->mysys_var->current_mutex) pthread_cond_broadcast(tmp->mysys_var->current_cond);
{ pthread_mutex_unlock(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->mutex);
pthread_mutex_unlock(tmp->mysys_var->current_mutex); }
} }
pthread_mutex_unlock(&tmp->mysys_var->mutex); pthread_mutex_unlock(&LOCK_thread_count);
}
}
pthread_mutex_unlock(&LOCK_thread_count);
} }
int change_master(THD* thd) int change_master(THD* thd)
{ {
bool slave_was_running; bool slave_was_running;
// kill slave thread // kill slave thread
pthread_mutex_lock(&LOCK_slave); pthread_mutex_lock(&LOCK_slave);
if((slave_was_running = slave_running)) if ((slave_was_running = slave_running))
{ {
abort_slave = 1; abort_slave = 1;
thr_alarm_kill(slave_real_id); thr_alarm_kill(slave_real_id);
thd->proc_info = "waiting for slave to die"; thd->proc_info = "waiting for slave to die";
while(slave_running) while (slave_running)
pthread_cond_wait(&COND_slave_stopped, &LOCK_slave); // wait until done pthread_cond_wait(&COND_slave_stopped, &LOCK_slave); // wait until done
} }
pthread_mutex_unlock(&LOCK_slave); pthread_mutex_unlock(&LOCK_slave);
thd->proc_info = "changing master"; thd->proc_info = "changing master";
LEX_MASTER_INFO* lex_mi = &thd->lex.mi; LEX_MASTER_INFO* lex_mi = &thd->lex.mi;
if(init_master_info(&glob_mi)) if (init_master_info(&glob_mi))
{ {
send_error(&thd->net, 0, "Could not initialize master info"); send_error(&thd->net, 0, "Could not initialize master info");
return 1; return 1;
} }
pthread_mutex_lock(&glob_mi.lock); pthread_mutex_lock(&glob_mi.lock);
if((lex_mi->host || lex_mi->port) && !lex_mi->log_file_name && !lex_mi->pos) if ((lex_mi->host || lex_mi->port) && !lex_mi->log_file_name && !lex_mi->pos)
{ {
// if we change host or port, we must reset the postion // if we change host or port, we must reset the postion
glob_mi.log_file_name[0] = 0; glob_mi.log_file_name[0] = 0;
glob_mi.pos = 4; // skip magic number glob_mi.pos = 4; // skip magic number
glob_mi.pending = 0; glob_mi.pending = 0;
} }
if(lex_mi->log_file_name) if (lex_mi->log_file_name)
strmake(glob_mi.log_file_name, lex_mi->log_file_name, strmake(glob_mi.log_file_name, lex_mi->log_file_name,
sizeof(glob_mi.log_file_name)); sizeof(glob_mi.log_file_name));
if(lex_mi->pos) if (lex_mi->pos)
{ {
glob_mi.pos = lex_mi->pos; glob_mi.pos = lex_mi->pos;
glob_mi.pending = 0; glob_mi.pending = 0;
} }
if(lex_mi->host) if (lex_mi->host)
{ strmake(glob_mi.host, lex_mi->host, sizeof(glob_mi.host));
strmake(glob_mi.host, lex_mi->host, sizeof(glob_mi.host)); if (lex_mi->user)
}
if(lex_mi->user)
strmake(glob_mi.user, lex_mi->user, sizeof(glob_mi.user)); strmake(glob_mi.user, lex_mi->user, sizeof(glob_mi.user));
if(lex_mi->password) if (lex_mi->password)
strmake(glob_mi.password, lex_mi->password, sizeof(glob_mi.password)); strmake(glob_mi.password, lex_mi->password, sizeof(glob_mi.password));
if(lex_mi->port) if (lex_mi->port)
glob_mi.port = lex_mi->port; glob_mi.port = lex_mi->port;
if(lex_mi->connect_retry) if (lex_mi->connect_retry)
glob_mi.connect_retry = lex_mi->connect_retry; glob_mi.connect_retry = lex_mi->connect_retry;
flush_master_info(&glob_mi); flush_master_info(&glob_mi);
pthread_mutex_unlock(&glob_mi.lock); pthread_mutex_unlock(&glob_mi.lock);
thd->proc_info = "starting slave"; thd->proc_info = "starting slave";
if(slave_was_running) if (slave_was_running)
start_slave(0,0); start_slave(0,0);
thd->proc_info = 0; thd->proc_info = 0;
...@@ -844,9 +831,10 @@ int change_master(THD* thd) ...@@ -844,9 +831,10 @@ int change_master(THD* thd)
return 0; return 0;
} }
void reset_master() void reset_master()
{ {
if(!mysql_bin_log.is_open()) if (!mysql_bin_log.is_open())
{ {
my_error(ER_FLUSH_MASTER_BINLOG_CLOSED, MYF(ME_BELL+ME_WAITTANG)); my_error(ER_FLUSH_MASTER_BINLOG_CLOSED, MYF(ME_BELL+ME_WAITTANG));
return; return;
...@@ -865,9 +853,9 @@ void reset_master() ...@@ -865,9 +853,9 @@ void reset_master()
mysql_bin_log.close(1); // exiting close mysql_bin_log.close(1); // exiting close
my_delete(mysql_bin_log.get_index_fname(), MYF(MY_WME)); my_delete(mysql_bin_log.get_index_fname(), MYF(MY_WME));
mysql_bin_log.open(opt_bin_logname,LOG_BIN); mysql_bin_log.open(opt_bin_logname,LOG_BIN);
} }
int cmp_master_pos(const char* log_file_name1, ulonglong log_pos1, int cmp_master_pos(const char* log_file_name1, ulonglong log_pos1,
const char* log_file_name2, ulonglong log_pos2) const char* log_file_name2, ulonglong log_pos2)
{ {
...@@ -881,6 +869,7 @@ int cmp_master_pos(const char* log_file_name1, ulonglong log_pos1, ...@@ -881,6 +869,7 @@ int cmp_master_pos(const char* log_file_name1, ulonglong log_pos1,
return -1; return -1;
} }
static inline int cmp_master_pos(Slave_log_event* sev, LEX_MASTER_INFO* mi) static inline int cmp_master_pos(Slave_log_event* sev, LEX_MASTER_INFO* mi)
{ {
return cmp_master_pos(sev->master_log, sev->master_pos, mi->log_file_name, return cmp_master_pos(sev->master_log, sev->master_pos, mi->log_file_name,
...@@ -891,7 +880,7 @@ static int find_target_pos(LEX_MASTER_INFO* mi, IO_CACHE* log, char* errmsg) ...@@ -891,7 +880,7 @@ static int find_target_pos(LEX_MASTER_INFO* mi, IO_CACHE* log, char* errmsg)
{ {
uint32 log_seq = mi->last_log_seq; uint32 log_seq = mi->last_log_seq;
uint32 target_server_id = mi->server_id; uint32 target_server_id = mi->server_id;
for (;;) for (;;)
{ {
Log_event* ev; Log_event* ev;
...@@ -899,7 +888,7 @@ static int find_target_pos(LEX_MASTER_INFO* mi, IO_CACHE* log, char* errmsg) ...@@ -899,7 +888,7 @@ static int find_target_pos(LEX_MASTER_INFO* mi, IO_CACHE* log, char* errmsg)
{ {
if (log->error > 0) if (log->error > 0)
strmov(errmsg, "Binary log truncated in the middle of event"); strmov(errmsg, "Binary log truncated in the middle of event");
else if(log->error < 0) else if (log->error < 0)
strmov(errmsg, "I/O error reading binary log"); strmov(errmsg, "I/O error reading binary log");
else else
strmov(errmsg, "Could not find target event in the binary log"); strmov(errmsg, "Could not find target event in the binary log");
...@@ -917,16 +906,6 @@ static int find_target_pos(LEX_MASTER_INFO* mi, IO_CACHE* log, char* errmsg) ...@@ -917,16 +906,6 @@ static int find_target_pos(LEX_MASTER_INFO* mi, IO_CACHE* log, char* errmsg)
} }
} }
static void copy_base_name(char* dest, char* src)
{
char* p;
p = strrchr(src, FN_LIBCHAR);
if (p)
p++;
else
p = src;
strmov(dest, p);
}
int translate_master(THD* thd, LEX_MASTER_INFO* mi, char* errmsg) int translate_master(THD* thd, LEX_MASTER_INFO* mi, char* errmsg)
{ {
...@@ -941,7 +920,7 @@ int translate_master(THD* thd, LEX_MASTER_INFO* mi, char* errmsg) ...@@ -941,7 +920,7 @@ int translate_master(THD* thd, LEX_MASTER_INFO* mi, char* errmsg)
int error = 1; int error = 1;
int cmp_res; int cmp_res;
LINT_INIT(cmp_res); LINT_INIT(cmp_res);
if (!mysql_bin_log.is_open()) if (!mysql_bin_log.is_open())
{ {
strmov(errmsg,"Binary log is not open"); strmov(errmsg,"Binary log is not open");
...@@ -953,8 +932,18 @@ int translate_master(THD* thd, LEX_MASTER_INFO* mi, char* errmsg) ...@@ -953,8 +932,18 @@ int translate_master(THD* thd, LEX_MASTER_INFO* mi, char* errmsg)
strmov(errmsg, "Misconfigured master - server id was not set"); strmov(errmsg, "Misconfigured master - server id was not set");
return 1; return 1;
} }
linfo.index_file_offset = 0; linfo.index_file_offset = 0;
/*
WARNING: POSSIBLE BUG:
Sasha, you are setting an uninitialized linfo into
thd->current_linfo.
What will happen if some other thread calls log_in_use() or
adjust_linfo_offsets() after the next instruction as linfo may
contain anything ?
*/
thd->current_linfo = &linfo; thd->current_linfo = &linfo;
search_file_name[0] = 0; search_file_name[0] = 0;
...@@ -963,48 +952,40 @@ int translate_master(THD* thd, LEX_MASTER_INFO* mi, char* errmsg) ...@@ -963,48 +952,40 @@ int translate_master(THD* thd, LEX_MASTER_INFO* mi, char* errmsg)
strmov(errmsg,"Could not find first log"); strmov(errmsg,"Could not find first log");
return 1; return 1;
} }
bzero((char*) &log,sizeof(log)); bzero((char*) &log,sizeof(log));
log_lock = mysql_bin_log.get_log_lock(); log_lock = mysql_bin_log.get_log_lock();
pthread_mutex_lock(log_lock); pthread_mutex_lock(log_lock);
for (;;) for (;;)
{ {
if ((file=open_binlog(&log, linfo.log_file_name, &errmsg_p)) < 0) if ((file=open_binlog(&log, linfo.log_file_name, &errmsg_p)) < 0)
{ {
pthread_mutex_unlock(log_lock);
strmov(errmsg, errmsg_p); strmov(errmsg, errmsg_p);
goto err; goto err;
} }
if (!(sev = find_slave_event(&log, linfo.log_file_name, errmsg))) if (!(sev = find_slave_event(&log, linfo.log_file_name, errmsg)))
{
pthread_mutex_unlock(log_lock);
goto err; goto err;
}
cmp_res = cmp_master_pos(sev, mi); cmp_res = cmp_master_pos(sev, mi);
delete sev; delete sev;
if(!cmp_res) if (!cmp_res)
{ {
pthread_mutex_unlock(log_lock); /* Copy basename */
copy_base_name(mi->log_file_name, linfo.log_file_name); fn_format(mi->log_file_name, linfo.log_file_name, "","",1);
mi->pos = my_b_tell(&log); mi->pos = my_b_tell(&log);
goto mi_inited; goto mi_inited;
} }
else if (cmp_res > 0)
if (!last_pos && cmp_res > 0)
{
pthread_mutex_unlock(log_lock);
strmov(errmsg, "Slave event in first log points past the \
target position");
goto err;
}
if (last_pos && cmp_res > 0)
{ {
if (!last_pos)
{
strmov(errmsg,
"Slave event in first log points past the target position");
goto err;
}
end_io_cache(&log); end_io_cache(&log);
(void) my_close(file, MYF(MY_WME)); (void) my_close(file, MYF(MY_WME));
if (init_io_cache(&log, (file = last_file), IO_SIZE, READ_CACHE, 0, 0, if (init_io_cache(&log, (file = last_file), IO_SIZE, READ_CACHE, 0, 0,
...@@ -1013,15 +994,13 @@ target position"); ...@@ -1013,15 +994,13 @@ target position");
errmsg[0] = 0; errmsg[0] = 0;
goto err; goto err;
} }
break;
goto found_log;
} }
strmov(last_log_name, linfo.log_file_name); strmov(last_log_name, linfo.log_file_name);
last_pos = my_b_tell(&log); last_pos = my_b_tell(&log);
switch (mysql_bin_log.find_next_log(&linfo)) switch (mysql_bin_log.find_next_log(&linfo)) {
{
case LOG_INFO_EOF: case LOG_INFO_EOF:
if (last_file >= 0) if (last_file >= 0)
(void)my_close(last_file, MYF(MY_WME)); (void)my_close(last_file, MYF(MY_WME));
...@@ -1030,29 +1009,26 @@ target position"); ...@@ -1030,29 +1009,26 @@ target position");
case 0: case 0:
break; break;
default: default:
pthread_mutex_unlock(log_lock);
strmov(errmsg, "Error reading log index"); strmov(errmsg, "Error reading log index");
goto err; goto err;
} }
end_io_cache(&log); end_io_cache(&log);
if (last_file >= 0) if (last_file >= 0)
(void) my_close(last_file, MYF(MY_WME)); (void) my_close(last_file, MYF(MY_WME));
last_file = file; last_file = file;
} }
found_log: found_log:
my_b_seek(&log, last_pos); my_b_seek(&log, last_pos);
if (find_target_pos(mi,&log,errmsg)) if (find_target_pos(mi,&log,errmsg))
{
pthread_mutex_unlock(log_lock);
goto err; goto err;
} fn_format(mi->log_file_name, last_log_name, "","",1); /* Copy basename */
pthread_mutex_unlock(log_lock);
copy_base_name(mi->log_file_name, last_log_name); mi_inited:
mi_inited:
error = 0; error = 0;
err: err:
pthread_mutex_unlock(log_lock);
end_io_cache(&log); end_io_cache(&log);
pthread_mutex_lock(&LOCK_thread_count); pthread_mutex_lock(&LOCK_thread_count);
thd->current_linfo = 0; thd->current_linfo = 0;
...@@ -1078,9 +1054,8 @@ static Slave_log_event* find_slave_event(IO_CACHE* log, ...@@ -1078,9 +1054,8 @@ static Slave_log_event* find_slave_event(IO_CACHE* log,
(char*)log_file_name); (char*)log_file_name);
return 0; return 0;
} }
delete ev; delete ev;
if (!(ev = Log_event::read_log_event(log, 0))) if (!(ev = Log_event::read_log_event(log, 0)))
{ {
my_vsnprintf(errmsg, SLAVE_ERRMSG_SIZE, my_vsnprintf(errmsg, SLAVE_ERRMSG_SIZE,
...@@ -1101,20 +1076,23 @@ static Slave_log_event* find_slave_event(IO_CACHE* log, ...@@ -1101,20 +1076,23 @@ static Slave_log_event* find_slave_event(IO_CACHE* log,
return (Slave_log_event*)ev; return (Slave_log_event*)ev;
} }
int show_new_master(THD* thd) int show_new_master(THD* thd)
{ {
DBUG_ENTER("show_new_master"); DBUG_ENTER("show_new_master");
List<Item> field_list; List<Item> field_list;
char errmsg[SLAVE_ERRMSG_SIZE]; char errmsg[SLAVE_ERRMSG_SIZE];
LEX_MASTER_INFO* lex_mi = &thd->lex.mi; LEX_MASTER_INFO* lex_mi = &thd->lex.mi;
errmsg[0]=0; // Safety
if (translate_master(thd, lex_mi, errmsg)) if (translate_master(thd, lex_mi, errmsg))
{ {
if (errmsg[0]) if (errmsg[0])
net_printf(&thd->net, ER_SHOW_NEW_MASTER, errmsg); net_printf(&thd->net, ER_ERROR_WHEN_EXECUTING_COMMAND,
"SHOW NEW MASTER", errmsg);
else else
send_error(&thd->net, 0); send_error(&thd->net, 0);
DBUG_RETURN(1); DBUG_RETURN(1);
} }
else else
...@@ -1142,11 +1120,11 @@ int show_binlog_events(THD* thd) ...@@ -1142,11 +1120,11 @@ int show_binlog_events(THD* thd)
const char* errmsg = 0; const char* errmsg = 0;
IO_CACHE log; IO_CACHE log;
File file = -1; File file = -1;
Log_event::init_show_field_list(&field_list); Log_event::init_show_field_list(&field_list);
if (send_fields(thd, field_list, 1)) if (send_fields(thd, field_list, 1))
DBUG_RETURN(-1); DBUG_RETURN(-1);
if (mysql_bin_log.is_open()) if (mysql_bin_log.is_open())
{ {
LOG_INFO linfo; LOG_INFO linfo;
...@@ -1156,7 +1134,7 @@ int show_binlog_events(THD* thd) ...@@ -1156,7 +1134,7 @@ int show_binlog_events(THD* thd)
const char* log_file_name = lex_mi->log_file_name; const char* log_file_name = lex_mi->log_file_name;
Log_event* ev; Log_event* ev;
ulong pos = (ulong) lex_mi->pos; ulong pos = (ulong) lex_mi->pos;
limit_start = thd->lex.select->offset_limit; limit_start = thd->lex.select->offset_limit;
limit_end = thd->lex.select->select_limit + limit_start; limit_end = thd->lex.select->select_limit + limit_start;
...@@ -1167,7 +1145,7 @@ int show_binlog_events(THD* thd) ...@@ -1167,7 +1145,7 @@ int show_binlog_events(THD* thd)
linfo.index_file_offset = 0; linfo.index_file_offset = 0;
thd->current_linfo = &linfo; thd->current_linfo = &linfo;
if (mysql_bin_log.find_first_log(&linfo, search_file_name)) if (mysql_bin_log.find_first_log(&linfo, search_file_name))
{ {
errmsg = "Could not find target log"; errmsg = "Could not find target log";
...@@ -1186,19 +1164,18 @@ int show_binlog_events(THD* thd) ...@@ -1186,19 +1164,18 @@ int show_binlog_events(THD* thd)
pthread_mutex_lock(mysql_bin_log.get_log_lock()); pthread_mutex_lock(mysql_bin_log.get_log_lock());
my_b_seek(&log, pos); my_b_seek(&log, pos);
for (event_count = 0; for (event_count = 0; (ev = Log_event::read_log_event(&log, 0)); )
(ev = Log_event::read_log_event(&log, 0));)
{ {
if (event_count >= limit_start && if (event_count >= limit_start &&
ev->net_send(thd, linfo.log_file_name, pos)) ev->net_send(thd, linfo.log_file_name, pos))
{ {
errmsg = "Net error"; errmsg = "Net error";
delete ev; delete ev;
pthread_mutex_unlock(mysql_bin_log.get_log_lock()); pthread_mutex_unlock(mysql_bin_log.get_log_lock());
goto err; goto err;
} }
pos = my_b_tell(&log); pos = my_b_tell(&log);
delete ev; delete ev;
if (++event_count >= limit_end) if (++event_count >= limit_end)
...@@ -1210,7 +1187,7 @@ int show_binlog_events(THD* thd) ...@@ -1210,7 +1187,7 @@ int show_binlog_events(THD* thd)
errmsg = "Wrong offset or I/O error"; errmsg = "Wrong offset or I/O error";
goto err; goto err;
} }
pthread_mutex_unlock(mysql_bin_log.get_log_lock()); pthread_mutex_unlock(mysql_bin_log.get_log_lock());
} }
...@@ -1220,10 +1197,11 @@ err: ...@@ -1220,10 +1197,11 @@ err:
end_io_cache(&log); end_io_cache(&log);
(void) my_close(file, MYF(MY_WME)); (void) my_close(file, MYF(MY_WME));
} }
if (errmsg) if (errmsg)
{ {
net_printf(&thd->net, ER_SHOW_BINLOG_EVENTS, errmsg); net_printf(&thd->net, ER_ERROR_WHEN_EXECUTING_COMMAND,
"SHOW BINLOG EVENTS", errmsg);
DBUG_RETURN(1); DBUG_RETURN(1);
} }
...@@ -1234,38 +1212,38 @@ err: ...@@ -1234,38 +1212,38 @@ err:
int show_slave_hosts(THD* thd) int show_slave_hosts(THD* thd)
{ {
DBUG_ENTER("show_slave_hosts");
List<Item> field_list; List<Item> field_list;
NET* net = &thd->net;
String* packet = &thd->packet;
DBUG_ENTER("show_slave_hosts");
field_list.push_back(new Item_empty_string("Server_id", 20)); field_list.push_back(new Item_empty_string("Server_id", 20));
field_list.push_back(new Item_empty_string("Host", 20)); field_list.push_back(new Item_empty_string("Host", 20));
if(opt_show_slave_auth_info) if (opt_show_slave_auth_info)
{ {
field_list.push_back(new Item_empty_string("User",20)); field_list.push_back(new Item_empty_string("User",20));
field_list.push_back(new Item_empty_string("Password",20)); field_list.push_back(new Item_empty_string("Password",20));
} }
field_list.push_back(new Item_empty_string("Port",20)); field_list.push_back(new Item_empty_string("Port",20));
if(send_fields(thd, field_list, 1)) if (send_fields(thd, field_list, 1))
DBUG_RETURN(-1); DBUG_RETURN(-1);
String* packet = &thd->packet;
uint i;
NET* net = &thd->net;
pthread_mutex_lock(&LOCK_slave_list); pthread_mutex_lock(&LOCK_slave_list);
for(i = 0; i < slave_list.records; ++i) for (uint i = 0; i < slave_list.records; ++i)
{ {
SLAVE_INFO* si = (SLAVE_INFO*)hash_element(&slave_list, i); SLAVE_INFO* si = (SLAVE_INFO*) hash_element(&slave_list, i);
packet->length(0); packet->length(0);
net_store_data(packet, si->server_id); net_store_data(packet, si->server_id);
net_store_data(packet, si->host); net_store_data(packet, si->host);
if(opt_show_slave_auth_info) if (opt_show_slave_auth_info)
{ {
net_store_data(packet, si->user); net_store_data(packet, si->user);
net_store_data(packet, si->password); net_store_data(packet, si->password);
} }
net_store_data(packet, (uint)si->port); net_store_data(packet, (uint)si->port);
if(my_net_write(net, (char*)packet->ptr(), packet->length())) if (my_net_write(net, (char*)packet->ptr(), packet->length()))
{ {
pthread_mutex_unlock(&LOCK_slave_list); pthread_mutex_unlock(&LOCK_slave_list);
DBUG_RETURN(-1); DBUG_RETURN(-1);
...@@ -1276,6 +1254,7 @@ int show_slave_hosts(THD* thd) ...@@ -1276,6 +1254,7 @@ int show_slave_hosts(THD* thd)
DBUG_RETURN(0); DBUG_RETURN(0);
} }
int show_binlog_info(THD* thd) int show_binlog_info(THD* thd)
{ {
DBUG_ENTER("show_binlog_info"); DBUG_ENTER("show_binlog_info");
...@@ -1285,36 +1264,37 @@ int show_binlog_info(THD* thd) ...@@ -1285,36 +1264,37 @@ int show_binlog_info(THD* thd)
field_list.push_back(new Item_empty_string("Binlog_do_db",20)); field_list.push_back(new Item_empty_string("Binlog_do_db",20));
field_list.push_back(new Item_empty_string("Binlog_ignore_db",20)); field_list.push_back(new Item_empty_string("Binlog_ignore_db",20));
if(send_fields(thd, field_list, 1)) if (send_fields(thd, field_list, 1))
DBUG_RETURN(-1); DBUG_RETURN(-1);
String* packet = &thd->packet; String* packet = &thd->packet;
packet->length(0); packet->length(0);
if(mysql_bin_log.is_open()) if (mysql_bin_log.is_open())
{ {
LOG_INFO li; LOG_INFO li;
mysql_bin_log.get_current_log(&li); mysql_bin_log.get_current_log(&li);
int dir_len = dirname_length(li.log_file_name); int dir_len = dirname_length(li.log_file_name);
net_store_data(packet, li.log_file_name + dir_len); net_store_data(packet, li.log_file_name + dir_len);
net_store_data(packet, (longlong)li.pos); net_store_data(packet, (longlong)li.pos);
net_store_data(packet, &binlog_do_db); net_store_data(packet, &binlog_do_db);
net_store_data(packet, &binlog_ignore_db); net_store_data(packet, &binlog_ignore_db);
} }
else else
{ {
net_store_null(packet); net_store_null(packet);
net_store_null(packet); net_store_null(packet);
net_store_null(packet); net_store_null(packet);
net_store_null(packet); net_store_null(packet);
} }
if(my_net_write(&thd->net, (char*)thd->packet.ptr(), packet->length())) if (my_net_write(&thd->net, (char*)thd->packet.ptr(), packet->length()))
DBUG_RETURN(-1); DBUG_RETURN(-1);
send_eof(&thd->net); send_eof(&thd->net);
DBUG_RETURN(0); DBUG_RETURN(0);
} }
int show_binlogs(THD* thd) int show_binlogs(THD* thd)
{ {
const char* errmsg = 0; const char* errmsg = 0;
...@@ -1325,20 +1305,20 @@ int show_binlogs(THD* thd) ...@@ -1325,20 +1305,20 @@ int show_binlogs(THD* thd)
String* packet = &thd->packet; String* packet = &thd->packet;
IO_CACHE io_cache; IO_CACHE io_cache;
uint length; uint length;
if(!mysql_bin_log.is_open()) if (!mysql_bin_log.is_open())
{ {
errmsg = "binlog is not open"; errmsg = "binlog is not open";
goto err; goto err;
} }
field_list.push_back(new Item_empty_string("Log_name", 128)); field_list.push_back(new Item_empty_string("Log_name", 128));
if(send_fields(thd, field_list, 1)) if (send_fields(thd, field_list, 1))
{ {
sql_print_error("Failed in send_fields"); sql_print_error("Failed in send_fields");
return 1; return 1;
} }
mysql_bin_log.lock_index(); mysql_bin_log.lock_index();
index_file = mysql_bin_log.get_index_file(); index_file = mysql_bin_log.get_index_file();
if (index_file < 0) if (index_file < 0)
...@@ -1358,7 +1338,7 @@ int show_binlogs(THD* thd) ...@@ -1358,7 +1338,7 @@ int show_binlogs(THD* thd)
int dir_len = dirname_length(fname); int dir_len = dirname_length(fname);
packet->length(0); packet->length(0);
net_store_data(packet, fname + dir_len, length-dir_len); net_store_data(packet, fname + dir_len, length-dir_len);
if(my_net_write(net, (char*) packet->ptr(), packet->length())) if (my_net_write(net, (char*) packet->ptr(), packet->length()))
{ {
sql_print_error("Failed in my_net_write"); sql_print_error("Failed in my_net_write");
end_io_cache(&io_cache); end_io_cache(&io_cache);
...@@ -1366,10 +1346,10 @@ int show_binlogs(THD* thd) ...@@ -1366,10 +1346,10 @@ int show_binlogs(THD* thd)
return 1; return 1;
} }
} }
mysql_bin_log.unlock_index(); mysql_bin_log.unlock_index();
end_io_cache(&io_cache); end_io_cache(&io_cache);
send_eof(net); send_eof(net);
return 0; return 0;
err2: err2:
...@@ -1380,9 +1360,10 @@ err: ...@@ -1380,9 +1360,10 @@ err:
return 1; return 1;
} }
int connect_to_master(THD *thd, MYSQL* mysql, MASTER_INFO* mi) int connect_to_master(THD *thd, MYSQL* mysql, MASTER_INFO* mi)
{ {
if(!mc_mysql_connect(mysql, mi->host, mi->user, mi->password, 0, if (!mc_mysql_connect(mysql, mi->host, mi->user, mi->password, 0,
mi->port, 0, 0)) mi->port, 0, 0))
{ {
sql_print_error("Connection to master failed: %s", sql_print_error("Connection to master failed: %s",
...@@ -1392,68 +1373,73 @@ int connect_to_master(THD *thd, MYSQL* mysql, MASTER_INFO* mi) ...@@ -1392,68 +1373,73 @@ int connect_to_master(THD *thd, MYSQL* mysql, MASTER_INFO* mi)
return 0; return 0;
} }
static inline void cleanup_mysql_results(MYSQL_RES* db_res, static inline void cleanup_mysql_results(MYSQL_RES* db_res,
MYSQL_RES** cur, MYSQL_RES** start) MYSQL_RES** cur, MYSQL_RES** start)
{ {
for( ; cur >= start; --cur) for( ; cur >= start; --cur)
if(*cur) {
if (*cur)
mc_mysql_free_result(*cur); mc_mysql_free_result(*cur);
}
mc_mysql_free_result(db_res); mc_mysql_free_result(db_res);
} }
static inline int fetch_db_tables(THD* thd, MYSQL* mysql, const char* db, static inline int fetch_db_tables(THD* thd, MYSQL* mysql, const char* db,
MYSQL_RES* table_res) MYSQL_RES* table_res)
{ {
MYSQL_ROW row; MYSQL_ROW row;
for( row = mc_mysql_fetch_row(table_res); row; for( row = mc_mysql_fetch_row(table_res); row;
row = mc_mysql_fetch_row(table_res)) row = mc_mysql_fetch_row(table_res))
{ {
TABLE_LIST table; TABLE_LIST table;
const char* table_name = row[0]; const char* table_name = row[0];
int error; int error;
if(table_rules_on) if (table_rules_on)
{ {
table.next = 0; table.next = 0;
table.db = (char*)db; table.db = (char*)db;
table.real_name = (char*)table_name; table.real_name = (char*)table_name;
table.updating = 1; table.updating = 1;
if(!tables_ok(thd, &table)) if (!tables_ok(thd, &table))
continue; continue;
} }
if((error = fetch_nx_table(thd, db, table_name, &glob_mi, mysql))) if ((error = fetch_nx_table(thd, db, table_name, &glob_mi, mysql)))
return error; return error;
} }
return 0; return 0;
} }
int load_master_data(THD* thd) int load_master_data(THD* thd)
{ {
MYSQL mysql; MYSQL mysql;
MYSQL_RES* master_status_res = 0; MYSQL_RES* master_status_res = 0;
bool slave_was_running = 0; bool slave_was_running = 0;
int error = 0; int error = 0;
mc_mysql_init(&mysql); mc_mysql_init(&mysql);
pthread_mutex_lock(&LOCK_slave);
// we do not want anyone messing with the slave at all for the entire // we do not want anyone messing with the slave at all for the entire
// duration of the data load; // duration of the data load;
pthread_mutex_lock(&LOCK_slave);
// first, kill the slave // first, kill the slave
if((slave_was_running = slave_running)) if ((slave_was_running = slave_running))
{ {
abort_slave = 1; abort_slave = 1;
thr_alarm_kill(slave_real_id); thr_alarm_kill(slave_real_id);
thd->proc_info = "waiting for slave to die"; thd->proc_info = "waiting for slave to die";
while(slave_running) while (slave_running)
pthread_cond_wait(&COND_slave_stopped, &LOCK_slave); // wait until done pthread_cond_wait(&COND_slave_stopped, &LOCK_slave); // wait until done
} }
if(connect_to_master(thd, &mysql, &glob_mi))
if (connect_to_master(thd, &mysql, &glob_mi))
{ {
net_printf(&thd->net, error = ER_CONNECT_TO_MASTER, net_printf(&thd->net, error = ER_CONNECT_TO_MASTER,
mc_mysql_error(&mysql)); mc_mysql_error(&mysql));
...@@ -1465,21 +1451,21 @@ int load_master_data(THD* thd) ...@@ -1465,21 +1451,21 @@ int load_master_data(THD* thd)
MYSQL_RES *db_res, **table_res, **table_res_end, **cur_table_res; MYSQL_RES *db_res, **table_res, **table_res_end, **cur_table_res;
uint num_dbs; uint num_dbs;
MYSQL_ROW row; MYSQL_ROW row;
if(mc_mysql_query(&mysql, "show databases", 0) || if (mc_mysql_query(&mysql, "show databases", 0) ||
!(db_res = mc_mysql_store_result(&mysql))) !(db_res = mc_mysql_store_result(&mysql)))
{ {
net_printf(&thd->net, error = ER_QUERY_ON_MASTER, net_printf(&thd->net, error = ER_QUERY_ON_MASTER,
mc_mysql_error(&mysql)); mc_mysql_error(&mysql));
goto err; goto err;
} }
if(!(num_dbs = mc_mysql_num_rows(db_res))) if (!(num_dbs = mc_mysql_num_rows(db_res)))
goto err; goto err;
// in theory, the master could have no databases at all // in theory, the master could have no databases at all
// and run with skip-grant // and run with skip-grant
if(!(table_res = (MYSQL_RES**)thd->alloc(num_dbs * sizeof(MYSQL_RES*)))) if (!(table_res = (MYSQL_RES**)thd->alloc(num_dbs * sizeof(MYSQL_RES*))))
{ {
net_printf(&thd->net, error = ER_OUTOFMEMORY); net_printf(&thd->net, error = ER_OUTOFMEMORY);
goto err; goto err;
...@@ -1489,46 +1475,48 @@ int load_master_data(THD* thd) ...@@ -1489,46 +1475,48 @@ int load_master_data(THD* thd)
// capabilities - to be replaced once online backup is working // capabilities - to be replaced once online backup is working
// we wait to issue FLUSH TABLES WITH READ LOCK for as long as we // we wait to issue FLUSH TABLES WITH READ LOCK for as long as we
// can to minimize the lock time // can to minimize the lock time
if(mc_mysql_query(&mysql, "FLUSH TABLES WITH READ LOCK", 0) if (mc_mysql_query(&mysql, "FLUSH TABLES WITH READ LOCK", 0) ||
|| mc_mysql_query(&mysql, "SHOW MASTER STATUS",0) || mc_mysql_query(&mysql, "SHOW MASTER STATUS",0) ||
!(master_status_res = mc_mysql_store_result(&mysql))) !(master_status_res = mc_mysql_store_result(&mysql)))
{ {
net_printf(&thd->net, error = ER_QUERY_ON_MASTER, net_printf(&thd->net, error = ER_QUERY_ON_MASTER,
mc_mysql_error(&mysql)); mc_mysql_error(&mysql));
goto err; goto err;
} }
// go through every table in every database, and if the replication // go through every table in every database, and if the replication
// rules allow replicating it, get it // rules allow replicating it, get it
table_res_end = table_res + num_dbs; table_res_end = table_res + num_dbs;
for(cur_table_res = table_res; cur_table_res < table_res_end; for(cur_table_res = table_res; cur_table_res < table_res_end;
++cur_table_res) cur_table_res++)
{ {
MYSQL_ROW row = mc_mysql_fetch_row(db_res);
// since we know how many rows we have, this can never be NULL // since we know how many rows we have, this can never be NULL
MYSQL_ROW row = mc_mysql_fetch_row(db_res);
char* db = row[0]; char* db = row[0];
int drop_error = 0; int drop_error;
// do not replicate databases excluded by rules /*
// also skip mysql database - in most cases the user will Do not replicate databases excluded by rules
// mess up and not exclude mysql database with the rules when also skip mysql database - in most cases the user will
// he actually means to - in this case, he is up for a surprise if mess up and not exclude mysql database with the rules when
// his priv tables get dropped and downloaded from master he actually means to - in this case, he is up for a surprise if
// TO DO - add special option, not enabled his priv tables get dropped and downloaded from master
// by default, to allow inclusion of mysql database into load TO DO - add special option, not enabled
// data from master by default, to allow inclusion of mysql database into load
if(!db_ok(db, replicate_do_db, replicate_ignore_db) || data from master
*/
if (!db_ok(db, replicate_do_db, replicate_ignore_db) ||
!strcmp(db,"mysql")) !strcmp(db,"mysql"))
{ {
*cur_table_res = 0; *cur_table_res = 0;
continue; continue;
} }
if((drop_error = mysql_rm_db(0, db, 1)) || if ((drop_error = mysql_rm_db(0, db, 1)) ||
mysql_create_db(0, db, 0)) mysql_create_db(0, db, 0))
{ {
error = (drop_error) ? ER_DB_DROP_DELETE : ER_CANT_CREATE_DB; error = (drop_error) ? ER_DB_DROP_DELETE : ER_CANT_CREATE_DB;
net_printf(&thd->net, error, db, my_error); net_printf(&thd->net, error, db, my_error);
...@@ -1536,8 +1524,8 @@ int load_master_data(THD* thd) ...@@ -1536,8 +1524,8 @@ int load_master_data(THD* thd)
goto err; goto err;
} }
if(mc_mysql_select_db(&mysql, db) || if (mc_mysql_select_db(&mysql, db) ||
mc_mysql_query(&mysql, "show tables", 0) || mc_mysql_query(&mysql, "show tables", 0) ||
!(*cur_table_res = mc_mysql_store_result(&mysql))) !(*cur_table_res = mc_mysql_store_result(&mysql)))
{ {
net_printf(&thd->net, error = ER_QUERY_ON_MASTER, net_printf(&thd->net, error = ER_QUERY_ON_MASTER,
...@@ -1546,7 +1534,7 @@ int load_master_data(THD* thd) ...@@ -1546,7 +1534,7 @@ int load_master_data(THD* thd)
goto err; goto err;
} }
if((error = fetch_db_tables(thd, &mysql, db, *cur_table_res))) if ((error = fetch_db_tables(thd, &mysql, db, *cur_table_res)))
{ {
// we do not report the error - fetch_db_tables handles it // we do not report the error - fetch_db_tables handles it
cleanup_mysql_results(db_res, cur_table_res, table_res); cleanup_mysql_results(db_res, cur_table_res, table_res);
...@@ -1557,44 +1545,44 @@ int load_master_data(THD* thd) ...@@ -1557,44 +1545,44 @@ int load_master_data(THD* thd)
cleanup_mysql_results(db_res, cur_table_res - 1, table_res); cleanup_mysql_results(db_res, cur_table_res - 1, table_res);
// adjust position in the master // adjust position in the master
if(master_status_res) if (master_status_res)
{ {
MYSQL_ROW row = mc_mysql_fetch_row(master_status_res); MYSQL_ROW row = mc_mysql_fetch_row(master_status_res);
// we need this check because the master may not be running with /*
// log-bin, but it will still allow us to do all the steps We need this check because the master may not be running with
// of LOAD DATA FROM MASTER - no reason to forbid it, really, log-bin, but it will still allow us to do all the steps
// although it does not make much sense for the user to do it of LOAD DATA FROM MASTER - no reason to forbid it, really,
if(row[0] && row[1]) although it does not make much sense for the user to do it
*/
if (row[0] && row[1])
{ {
strmake(glob_mi.log_file_name, row[0], sizeof(glob_mi.log_file_name)); strmake(glob_mi.log_file_name, row[0], sizeof(glob_mi.log_file_name));
glob_mi.pos = atoi(row[1]); // atoi() is ok, since offset is <= 1GB glob_mi.pos = atoi(row[1]); // atoi() is ok, since offset is <= 1GB
if(glob_mi.pos < 4) if (glob_mi.pos < 4)
glob_mi.pos = 4; // don't hit the magic number glob_mi.pos = 4; // don't hit the magic number
glob_mi.pending = 0; glob_mi.pending = 0;
flush_master_info(&glob_mi); flush_master_info(&glob_mi);
} }
mc_mysql_free_result(master_status_res); mc_mysql_free_result(master_status_res);
} }
if(mc_mysql_query(&mysql, "UNLOCK TABLES", 0)) if (mc_mysql_query(&mysql, "UNLOCK TABLES", 0))
{ {
net_printf(&thd->net, error = ER_QUERY_ON_MASTER, net_printf(&thd->net, error = ER_QUERY_ON_MASTER,
mc_mysql_error(&mysql)); mc_mysql_error(&mysql));
goto err; goto err;
} }
} }
err:
err:
pthread_mutex_unlock(&LOCK_slave); pthread_mutex_unlock(&LOCK_slave);
if(slave_was_running) if (slave_was_running)
start_slave(0, 0); start_slave(0, 0);
mc_mysql_close(&mysql); // safe to call since we always do mc_mysql_init() mc_mysql_close(&mysql); // safe to call since we always do mc_mysql_init()
if(!error) if (!error)
send_ok(&thd->net); send_ok(&thd->net);
return error; return error;
} }
...@@ -110,7 +110,7 @@ int mysqld_show_open_tables(THD *thd,const char *wild) ...@@ -110,7 +110,7 @@ int mysqld_show_open_tables(THD *thd,const char *wild)
if (send_fields(thd,field_list,1)) if (send_fields(thd,field_list,1))
DBUG_RETURN(1); DBUG_RETURN(1);
if (!(open_list=list_open_tables(thd,wild))) if (!(open_list=list_open_tables(thd,wild)) && thd->fatal_error)
DBUG_RETURN(-1); DBUG_RETURN(-1);
for ( ; open_list ; open_list=open_list->next) for ( ; open_list ; open_list=open_list->next)
......
...@@ -37,6 +37,7 @@ typedef struct st_sort_param { ...@@ -37,6 +37,7 @@ typedef struct st_sort_param {
SORT_FIELD *local_sortorder; SORT_FIELD *local_sortorder;
SORT_FIELD *end; SORT_FIELD *end;
uchar *unique_buff; uchar *unique_buff;
bool not_killable;
#ifdef USE_STRCOLL #ifdef USE_STRCOLL
char* tmp_buffer; char* tmp_buffer;
#endif #endif
......
...@@ -128,10 +128,12 @@ bool Unique::get(TABLE *table) ...@@ -128,10 +128,12 @@ bool Unique::get(TABLE *table)
return 1; return 1;
reinit_io_cache(outfile,WRITE_CACHE,0L,0,0); reinit_io_cache(outfile,WRITE_CACHE,0L,0,0);
bzero((char*) &sort_param,sizeof(sort_param));
sort_param.max_rows= elements; sort_param.max_rows= elements;
sort_param.sort_form=table; sort_param.sort_form=table;
sort_param.sort_length=sort_param.ref_length=tree.size_of_element; sort_param.sort_length=sort_param.ref_length=tree.size_of_element;
sort_param.keys= max_in_memory_size / sort_param.sort_length; sort_param.keys= max_in_memory_size / sort_param.sort_length;
sort_param.not_killable=1;
if (!(sort_buffer=(uchar*) my_malloc((sort_param.keys+1) * if (!(sort_buffer=(uchar*) my_malloc((sort_param.keys+1) *
sort_param.sort_length, sort_param.sort_length,
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment