mirror of
https://github.com/MariaDB/server.git
synced 2025-01-16 03:52:35 +01:00
Ugly merge! But I am not done yet - there are a number of things I need to fix
before I can push BitKeeper/etc/ignore: auto-union Makefile.am: Auto merged include/my_sys.h: Auto merged libmysqld/lib_sql.cc: Auto merged mysql-test/t/rpl_log.test: Auto merged mysys/mf_iocache.c: Auto merged mysys/mf_iocache2.c: Auto merged mysys/thr_mutex.c: Auto merged sql/item_func.cc: Auto merged sql/lex.h: Auto merged sql/mini_client.cc: Auto merged sql/mini_client.h: Auto merged sql/mysql_priv.h: Auto merged sql/repl_failsafe.cc: Auto merged sql/sql_class.cc: Auto merged sql/sql_lex.h: Auto merged sql/sql_show.cc: Auto merged sql/stacktrace.c: Auto merged sql/structs.h: Auto merged mysql-test/r/rpl000014.result: merge mysql-test/r/rpl000015.result: merge mysql-test/r/rpl000016.result: merge mysql-test/r/rpl_log.result: merge sql/log.cc: merge sql/log_event.cc: merge sql/log_event.h: merge sql/mysqld.cc: merge sql/slave.cc: merge sql/slave.h: merge sql/sql_class.h: merge sql/sql_parse.cc: merge sql/sql_repl.cc: merge sql/sql_yacc.yy: merge
This commit is contained in:
commit
1e0f2b7a42
39 changed files with 2998 additions and 1568 deletions
|
@ -245,6 +245,7 @@ libmysqld/get_password.c
|
|||
libmysqld/ha_berkeley.cc
|
||||
libmysqld/ha_heap.cc
|
||||
libmysqld/ha_innobase.cc
|
||||
libmysqld/ha_innodb.cc
|
||||
libmysqld/ha_isam.cc
|
||||
libmysqld/ha_isammrg.cc
|
||||
libmysqld/ha_myisam.cc
|
||||
|
@ -344,7 +345,13 @@ mysql-test/gmon.out
|
|||
mysql-test/install_test_db
|
||||
mysql-test/mysql-test-run
|
||||
mysql-test/r/*.reject
|
||||
mysql-test/r/rpl000002.eval
|
||||
mysql-test/r/rpl000014.eval
|
||||
mysql-test/r/rpl000015.eval
|
||||
mysql-test/r/rpl000016.eval
|
||||
mysql-test/r/rpl_log.eval
|
||||
mysql-test/r/slave-running.eval
|
||||
mysql-test/r/slave-stopped.eval
|
||||
mysql-test/share/mysql
|
||||
mysql-test/var/*
|
||||
mysql.kdevprj
|
||||
|
@ -451,4 +458,3 @@ vio/test-ssl
|
|||
vio/test-sslclient
|
||||
vio/test-sslserver
|
||||
vio/viotest-ssl
|
||||
libmysqld/ha_innodb.cc
|
||||
|
|
|
@ -75,14 +75,11 @@ bin-dist: all
|
|||
$(top_builddir)/scripts/make_binary_distribution
|
||||
|
||||
tags:
|
||||
rm -f TAGS
|
||||
find -not -path \*SCCS\* -and \
|
||||
\( -name \*.cc -or -name \*.h -or -name \*.yy -or -name \*.c \) \
|
||||
-print -exec etags -o TAGS --append {} \;
|
||||
|
||||
support-files/build-tags
|
||||
.PHONY: init-db bin-dist
|
||||
|
||||
# Test installation
|
||||
|
||||
test:
|
||||
cd mysql-test ; ./mysql-test-run
|
||||
|
||||
|
|
|
@ -293,35 +293,105 @@ typedef int (*IO_CACHE_CALLBACK)(struct st_io_cache*);
|
|||
|
||||
typedef struct st_io_cache /* Used when cacheing files */
|
||||
{
|
||||
/* pos_in_file is offset in file corresponding to the first byte of
|
||||
byte* buffer. end_of_file is the offset of end of file for READ_CACHE
|
||||
and WRITE_CACHE. For SEQ_READ_APPEND it the maximum of the actual
|
||||
end of file and the position represented by read_end.
|
||||
*/
|
||||
my_off_t pos_in_file,end_of_file;
|
||||
/* read_pos points to current read position in the buffer
|
||||
read_end is the non-inclusive boundary in the buffer for the currently
|
||||
valid read area
|
||||
buffer is the read buffer
|
||||
not sure about request_pos except that it is used in async_io
|
||||
*/
|
||||
byte *read_pos,*read_end,*buffer,*request_pos;
|
||||
/* write_buffer is used only in WRITE caches and in SEQ_READ_APPEND to
|
||||
buffer writes
|
||||
append_read_pos is only used in SEQ_READ_APPEND, and points to the
|
||||
current read position in the write buffer. Note that reads in
|
||||
SEQ_READ_APPEND caches can happen from both read buffer (byte* buffer),
|
||||
and write buffer (byte* write_buffer).
|
||||
write_pos points to current write position in the write buffer and
|
||||
write_end is the non-inclusive boundary of the valid write area
|
||||
*/
|
||||
byte *write_buffer, *append_read_pos, *write_pos, *write_end;
|
||||
/* current_pos and current_end are convenience variables used by
|
||||
my_b_tell() and other routines that need to know the current offset
|
||||
current_pos points to &write_pos, and current_end to &write_end in a
|
||||
WRITE_CACHE, and &read_pos and &read_end respectively otherwise
|
||||
*/
|
||||
byte **current_pos, **current_end;
|
||||
/* The lock is for append buffer used in READ_APPEND cache */
|
||||
/* The lock is for append buffer used in SEQ_READ_APPEND cache */
|
||||
#ifdef THREAD
|
||||
pthread_mutex_t append_buffer_lock;
|
||||
/* need mutex copying from append buffer to read buffer */
|
||||
#endif
|
||||
#endif
|
||||
/* a caller will use my_b_read() macro to read from the cache
|
||||
if the data is already in cache, it will be simply copied with
|
||||
memcpy() and internal variables will be accordinging updated with
|
||||
no functions invoked. However, if the data is not fully in the cache,
|
||||
my_b_read() will call read_function to fetch the data. read_function
|
||||
must never be invoked directly
|
||||
*/
|
||||
int (*read_function)(struct st_io_cache *,byte *,uint);
|
||||
/* same idea as in the case of read_function, except my_b_write() needs to
|
||||
be replaced with my_b_append() for a SEQ_READ_APPEND cache
|
||||
*/
|
||||
int (*write_function)(struct st_io_cache *,const byte *,uint);
|
||||
/* specifies the type of the cache. Depending on the type of the cache
|
||||
certain operations might not be available and yield unpredicatable
|
||||
results. Details to be documented later
|
||||
*/
|
||||
enum cache_type type;
|
||||
/* callbacks when the actual read I/O happens */
|
||||
/* callbacks when the actual read I/O happens. These were added and
|
||||
are currently used for binary logging of LOAD DATA INFILE - when a
|
||||
block is read from the file, we create a block create/append event, and
|
||||
when IO_CACHE is closed, we create an end event. These functions could,
|
||||
of course be used for other things
|
||||
*/
|
||||
IO_CACHE_CALLBACK pre_read;
|
||||
IO_CACHE_CALLBACK post_read;
|
||||
IO_CACHE_CALLBACK pre_close;
|
||||
void* arg; /* for use by pre/post_read */
|
||||
char *file_name; /* if used with 'open_cached_file' */
|
||||
char *dir,*prefix;
|
||||
File file;
|
||||
File file; /* file descriptor */
|
||||
/* seek_not_done is set by my_b_seek() to inform the upcoming read/write
|
||||
operation that a seek needs to be preformed prior to the actual I/O
|
||||
error is 0 if the cache operation was successful, -1 if there was a
|
||||
"hard" error, and the actual number of I/O-ed bytes if the read/write was
|
||||
partial
|
||||
*/
|
||||
int seek_not_done,error;
|
||||
/* buffer_length is the size of memory allocated for buffer or write_buffer
|
||||
read_length is the same as buffer_length except when we use async io
|
||||
not sure why we need it
|
||||
*/
|
||||
uint buffer_length,read_length;
|
||||
myf myflags; /* Flags used to my_read/my_write */
|
||||
/*
|
||||
alloced_buffer is 1 if the buffer was allocated by init_io_cache() and
|
||||
0 if it was supplied by the user
|
||||
Currently READ_NET is the only one that will use a buffer allocated
|
||||
somewhere else
|
||||
*/
|
||||
my_bool alloced_buffer;
|
||||
/* init_count is incremented every time we call init_io_cache()
|
||||
It is not reset in end_io_cache(). This variable
|
||||
was introduced for slave relay logs - RELAY_LOG_INFO stores a pointer
|
||||
to IO_CACHE that could in some cases refer to the IO_CACHE of the
|
||||
currently active relay log. The IO_CACHE then could be closed,
|
||||
re-opened and start pointing to a different log file. In that case,
|
||||
we could not know reliably if this happened without init_count
|
||||
one must be careful with bzero() prior to the subsequent init_io_cache()
|
||||
call
|
||||
*/
|
||||
int init_count;
|
||||
#ifdef HAVE_AIOWAIT
|
||||
/* as inidicated by ifdef, this is for async I/O, we will have
|
||||
Sinisa comment this some time
|
||||
*/
|
||||
uint inited;
|
||||
my_off_t aio_read_pos;
|
||||
my_aio_result aio_result;
|
||||
|
@ -366,6 +436,8 @@ typedef int (*qsort2_cmp)(const void *, const void *, const void *);
|
|||
|
||||
#define my_b_tell(info) ((info)->pos_in_file + \
|
||||
(uint) (*(info)->current_pos - (info)->request_pos))
|
||||
#define my_b_append_tell(info) ((info)->end_of_file + \
|
||||
(uint) ((info)->write_pos - (info)->write_buffer))
|
||||
|
||||
#define my_b_bytes_in_cache(info) (uint) (*(info)->current_end - \
|
||||
*(info)->current_pos)
|
||||
|
|
|
@ -402,8 +402,8 @@ int STDCALL mysql_server_init(int argc, char **argv, char **groups)
|
|||
(void) pthread_mutex_init(&LOCK_bytes_sent,MY_MUTEX_INIT_FAST);
|
||||
(void) pthread_mutex_init(&LOCK_bytes_received,MY_MUTEX_INIT_FAST);
|
||||
(void) pthread_mutex_init(&LOCK_timezone,MY_MUTEX_INIT_FAST);
|
||||
(void) pthread_mutex_init(&LOCK_binlog_update, MY_MUTEX_INIT_FAST); // QQ NOT USED
|
||||
(void) pthread_mutex_init(&LOCK_slave, MY_MUTEX_INIT_FAST);
|
||||
(void) pthread_mutex_init(&LOCK_slave_io, MY_MUTEX_INIT_FAST);
|
||||
(void) pthread_mutex_init(&LOCK_slave_sql, MY_MUTEX_INIT_FAST);
|
||||
(void) pthread_mutex_init(&LOCK_server_id, MY_MUTEX_INIT_FAST);
|
||||
(void) pthread_mutex_init(&LOCK_user_conn, MY_MUTEX_INIT_FAST);
|
||||
(void) pthread_cond_init(&COND_thread_count,NULL);
|
||||
|
@ -412,8 +412,11 @@ int STDCALL mysql_server_init(int argc, char **argv, char **groups)
|
|||
(void) pthread_cond_init(&COND_flush_thread_cache,NULL);
|
||||
(void) pthread_cond_init(&COND_manager,NULL);
|
||||
(void) pthread_cond_init(&COND_binlog_update, NULL);
|
||||
(void) pthread_cond_init(&COND_slave_stopped, NULL);
|
||||
(void) pthread_cond_init(&COND_slave_start, NULL);
|
||||
(void) pthread_cond_init(&COND_slave_log_update, NULL);
|
||||
(void) pthread_cond_init(&COND_slave_sql_stop, NULL);
|
||||
(void) pthread_cond_init(&COND_slave_sql_start, NULL);
|
||||
(void) pthread_cond_init(&COND_slave_sql_stop, NULL);
|
||||
(void) pthread_cond_init(&COND_slave_sql_start, NULL);
|
||||
|
||||
if (set_default_charset_by_name(default_charset, MYF(MY_WME)))
|
||||
{
|
||||
|
|
|
@ -7,22 +7,22 @@ show master status;
|
|||
File Position Binlog_do_db Binlog_ignore_db
|
||||
master-bin.001 79
|
||||
show slave status;
|
||||
Master_Host Master_User Master_Port Connect_retry Log_File Pos Slave_Running Replicate_do_db Replicate_ignore_db Last_errno Last_error Skip_counter Last_log_seq
|
||||
127.0.0.1 root MASTER_PORT 1 master-bin.001 79 Yes 0 0 1
|
||||
Master_Host Master_User Master_Port Connect_retry Master_Log_File Read_Master_Log_Pos Relay_Log_File Relay_Log_Pos Relay_Master_Log_File Slave_IO_Running Slave_SQL_Running Replicate_do_db Replicate_ignore_db Last_errno Last_error Skip_counter Exec_master_log_pos
|
||||
127.0.0.1 root 9306 1 master-bin.001 79 mysql-relay-bin.002 120 master-bin.001 Yes Yes 0 0 79
|
||||
change master to master_log_pos=73;
|
||||
slave stop;
|
||||
change master to master_log_pos=73;
|
||||
show slave status;
|
||||
Master_Host Master_User Master_Port Connect_retry Log_File Pos Slave_Running Replicate_do_db Replicate_ignore_db Last_errno Last_error Skip_counter Last_log_seq
|
||||
127.0.0.1 root MASTER_PORT 1 master-bin.001 73 No 0 0 1
|
||||
Master_Host Master_User Master_Port Connect_retry Master_Log_File Read_Master_Log_Pos Relay_Log_File Relay_Log_Pos Relay_Master_Log_File Slave_IO_Running Slave_SQL_Running Replicate_do_db Replicate_ignore_db Last_errno Last_error Skip_counter Exec_master_log_pos
|
||||
127.0.0.1 root 9306 1 master-bin.001 73 mysql-relay-bin.001 4 master-bin.001 No No 0 0 73
|
||||
slave start;
|
||||
show slave status;
|
||||
Master_Host Master_User Master_Port Connect_retry Log_File Pos Slave_Running Replicate_do_db Replicate_ignore_db Last_errno Last_error Skip_counter Last_log_seq
|
||||
127.0.0.1 root MASTER_PORT 1 master-bin.001 73 Yes 0 0 1
|
||||
Master_Host Master_User Master_Port Connect_retry Master_Log_File Read_Master_Log_Pos Relay_Log_File Relay_Log_Pos Relay_Master_Log_File Slave_IO_Running Slave_SQL_Running Replicate_do_db Replicate_ignore_db Last_errno Last_error Skip_counter Exec_master_log_pos
|
||||
127.0.0.1 root 9306 1 master-bin.001 73 mysql-relay-bin.001 4 master-bin.001 Yes Yes 0 0 73
|
||||
change master to master_log_pos=173;
|
||||
show slave status;
|
||||
Master_Host Master_User Master_Port Connect_retry Log_File Pos Slave_Running Replicate_do_db Replicate_ignore_db Last_errno Last_error Skip_counter Last_log_seq
|
||||
127.0.0.1 root MASTER_PORT 1 master-bin.001 173 Yes 0 0 1
|
||||
Master_Host Master_User Master_Port Connect_retry Master_Log_File Read_Master_Log_Pos Relay_Log_File Relay_Log_Pos Relay_Master_Log_File Slave_IO_Running Slave_SQL_Running Replicate_do_db Replicate_ignore_db Last_errno Last_error Skip_counter Exec_master_log_pos
|
||||
127.0.0.1 root 9306 1 master-bin.001 173 mysql-relay-bin.001 4 master-bin.001 Yes Yes 0 0 173
|
||||
show master status;
|
||||
File Position Binlog_do_db Binlog_ignore_db
|
||||
master-bin.001 79
|
||||
|
|
|
@ -4,21 +4,21 @@ File Position Binlog_do_db Binlog_ignore_db
|
|||
master-bin.001 79
|
||||
reset slave;
|
||||
show slave status;
|
||||
Master_Host Master_User Master_Port Connect_retry Log_File Pos Slave_Running Replicate_do_db Replicate_ignore_db Last_errno Last_error Skip_counter Last_log_seq
|
||||
0 0 0 No 0 0 0
|
||||
Master_Host Master_User Master_Port Connect_retry Master_Log_File Read_Master_Log_Pos Relay_Log_File Relay_Log_Pos Relay_Master_Log_File Slave_IO_Running Slave_SQL_Running Replicate_do_db Replicate_ignore_db Last_errno Last_error Skip_counter Exec_master_log_pos
|
||||
0 0 0 0 No No 0 0 0
|
||||
change master to master_host='127.0.0.1';
|
||||
show slave status;
|
||||
Master_Host Master_User Master_Port Connect_retry Log_File Pos Slave_Running Replicate_do_db Replicate_ignore_db Last_errno Last_error Skip_counter Last_log_seq
|
||||
127.0.0.1 test MASTER_PORT 60 4 No 0 0 0
|
||||
Master_Host Master_User Master_Port Connect_retry Master_Log_File Read_Master_Log_Pos Relay_Log_File Relay_Log_Pos Relay_Master_Log_File Slave_IO_Running Slave_SQL_Running Replicate_do_db Replicate_ignore_db Last_errno Last_error Skip_counter Exec_master_log_pos
|
||||
127.0.0.1 test 3306 60 4 mysql-relay-bin.001 4 No No 0 0 0
|
||||
change master to master_host='127.0.0.1',master_user='root',
|
||||
master_password='',master_port=MASTER_PORT;
|
||||
master_password='',master_port=9306;
|
||||
show slave status;
|
||||
Master_Host Master_User Master_Port Connect_retry Log_File Pos Slave_Running Replicate_do_db Replicate_ignore_db Last_errno Last_error Skip_counter Last_log_seq
|
||||
127.0.0.1 root MASTER_PORT 60 4 No 0 0 0
|
||||
Master_Host Master_User Master_Port Connect_retry Master_Log_File Read_Master_Log_Pos Relay_Log_File Relay_Log_Pos Relay_Master_Log_File Slave_IO_Running Slave_SQL_Running Replicate_do_db Replicate_ignore_db Last_errno Last_error Skip_counter Exec_master_log_pos
|
||||
127.0.0.1 root 9306 60 4 mysql-relay-bin.001 4 No No 0 0 0
|
||||
slave start;
|
||||
show slave status;
|
||||
Master_Host Master_User Master_Port Connect_retry Log_File Pos Slave_Running Replicate_do_db Replicate_ignore_db Last_errno Last_error Skip_counter Last_log_seq
|
||||
127.0.0.1 root MASTER_PORT 60 master-bin.001 79 Yes 0 0 1
|
||||
Master_Host Master_User Master_Port Connect_retry Master_Log_File Read_Master_Log_Pos Relay_Log_File Relay_Log_Pos Relay_Master_Log_File Slave_IO_Running Slave_SQL_Running Replicate_do_db Replicate_ignore_db Last_errno Last_error Skip_counter Exec_master_log_pos
|
||||
127.0.0.1 root 9306 60 master-bin.001 79 mysql-relay-bin.001 120 master-bin.001 Yes Yes 0 0 79
|
||||
drop table if exists t1;
|
||||
create table t1 (n int);
|
||||
insert into t1 values (10),(45),(90);
|
||||
|
|
|
@ -2,11 +2,11 @@ slave start;
|
|||
Could not initialize master info structure, check permisions on master.info
|
||||
slave start;
|
||||
Could not initialize master info structure, check permisions on master.info
|
||||
change master to master_host='127.0.0.1',master_port=MASTER_PORT,
|
||||
change master to master_host='127.0.0.1',master_port=9306,
|
||||
master_user='root';
|
||||
Could not initialize master info
|
||||
reset slave;
|
||||
change master to master_host='127.0.0.1',master_port=MASTER_PORT,
|
||||
change master to master_host='127.0.0.1',master_port=9306,
|
||||
master_user='root';
|
||||
reset master;
|
||||
slave start;
|
||||
|
@ -14,8 +14,8 @@ drop table if exists t1;
|
|||
create table t1 (s text);
|
||||
insert into t1 values('Could not break slave'),('Tried hard');
|
||||
show slave status;
|
||||
Master_Host Master_User Master_Port Connect_retry Log_File Pos Slave_Running Replicate_do_db Replicate_ignore_db Last_errno Last_error Skip_counter Last_log_seq
|
||||
127.0.0.1 root MASTER_PORT 60 master-bin.001 234 Yes 0 0 3
|
||||
Master_Host Master_User Master_Port Connect_retry Master_Log_File Read_Master_Log_Pos Relay_Log_File Relay_Log_Pos Relay_Master_Log_File Slave_IO_Running Slave_SQL_Running Replicate_do_db Replicate_ignore_db Last_errno Last_error Skip_counter Exec_master_log_pos
|
||||
127.0.0.1 root 9306 60 master-bin.001 234 mysql-relay-bin.001 275 master-bin.001 Yes Yes 0 0 234
|
||||
select * from t1;
|
||||
s
|
||||
Could not break slave
|
||||
|
@ -42,8 +42,8 @@ Log_name
|
|||
master-bin.003
|
||||
insert into t2 values (65);
|
||||
show slave status;
|
||||
Master_Host Master_User Master_Port Connect_retry Log_File Pos Slave_Running Replicate_do_db Replicate_ignore_db Last_errno Last_error Skip_counter Last_log_seq
|
||||
127.0.0.1 root MASTER_PORT 60 master-bin.003 155 Yes 0 0 3
|
||||
Master_Host Master_User Master_Port Connect_retry Master_Log_File Read_Master_Log_Pos Relay_Log_File Relay_Log_Pos Relay_Master_Log_File Slave_IO_Running Slave_SQL_Running Replicate_do_db Replicate_ignore_db Last_errno Last_error Skip_counter Exec_master_log_pos
|
||||
127.0.0.1 root 9306 60 master-bin.003 155 mysql-relay-bin.001 793 master-bin.003 Yes Yes 0 0 155
|
||||
select * from t2;
|
||||
m
|
||||
34
|
||||
|
@ -65,8 +65,8 @@ master-bin.006 445
|
|||
slave stop;
|
||||
slave start;
|
||||
show slave status;
|
||||
Master_Host Master_User Master_Port Connect_retry Log_File Pos Slave_Running Replicate_do_db Replicate_ignore_db Last_errno Last_error Skip_counter Last_log_seq
|
||||
127.0.0.1 root MASTER_PORT 60 master-bin.006 445 Yes 0 0 7
|
||||
Master_Host Master_User Master_Port Connect_retry Master_Log_File Read_Master_Log_Pos Relay_Log_File Relay_Log_Pos Relay_Master_Log_File Slave_IO_Running Slave_SQL_Running Replicate_do_db Replicate_ignore_db Last_errno Last_error Skip_counter Exec_master_log_pos
|
||||
127.0.0.1 root 9306 60 master-bin.006 445 mysql-relay-bin.004 1376 master-bin.006 Yes Yes 0 0 445
|
||||
lock tables t3 read;
|
||||
select count(*) from t3 where n >= 4;
|
||||
count(*)
|
||||
|
|
|
@ -15,48 +15,48 @@ create table t1 (word char(20) not null);
|
|||
load data infile '../../std_data/words.dat' into table t1;
|
||||
drop table t1;
|
||||
show binlog events;
|
||||
Log_name Pos Event_type Server_id Log_seq Info
|
||||
master-bin.001 4 Start 1 1 Server ver: VERSION, Binlog ver: 2
|
||||
master-bin.001 79 Query 1 2 use test; create table t1(n int not null auto_increment primary key)
|
||||
master-bin.001 172 Intvar 1 3 INSERT_ID=1
|
||||
master-bin.001 200 Query 1 4 use test; insert into t1 values (NULL)
|
||||
master-bin.001 263 Query 1 5 use test; drop table t1
|
||||
master-bin.001 311 Query 1 6 use test; create table t1 (word char(20) not null)
|
||||
master-bin.001 386 Create_file 1 7 db=test;table=t1;file_id=1;block_len=81
|
||||
master-bin.001 556 Exec_load 1 8 ;file_id=1
|
||||
master-bin.001 579 Query 1 9 use test; drop table t1
|
||||
Log_name Pos Event_type Server_id Orig_log_pos Info
|
||||
master-bin.001 4 Start 1 4 Server ver: 4.0.1-alpha-debug-log, Binlog ver: 3
|
||||
master-bin.001 79 Query 1 79 use test; create table t1(n int not null auto_increment primary key)
|
||||
master-bin.001 172 Intvar 1 172 INSERT_ID=1
|
||||
master-bin.001 200 Query 1 200 use test; insert into t1 values (NULL)
|
||||
master-bin.001 263 Query 1 263 use test; drop table t1
|
||||
master-bin.001 311 Query 1 311 use test; create table t1 (word char(20) not null)
|
||||
master-bin.001 386 Create_file 1 386 db=test;table=t1;file_id=1;block_len=81
|
||||
master-bin.001 556 Exec_load 1 556 ;file_id=1
|
||||
master-bin.001 579 Query 1 579 use test; drop table t1
|
||||
show binlog events from 79 limit 1;
|
||||
Log_name Pos Event_type Server_id Log_seq Info
|
||||
master-bin.001 79 Query 1 2 use test; create table t1(n int not null auto_increment primary key)
|
||||
Log_name Pos Event_type Server_id Orig_log_pos Info
|
||||
master-bin.001 79 Query 1 79 use test; create table t1(n int not null auto_increment primary key)
|
||||
show binlog events from 79 limit 2;
|
||||
Log_name Pos Event_type Server_id Log_seq Info
|
||||
master-bin.001 79 Query 1 2 use test; create table t1(n int not null auto_increment primary key)
|
||||
master-bin.001 172 Intvar 1 3 INSERT_ID=1
|
||||
Log_name Pos Event_type Server_id Orig_log_pos Info
|
||||
master-bin.001 79 Query 1 79 use test; create table t1(n int not null auto_increment primary key)
|
||||
master-bin.001 172 Intvar 1 172 INSERT_ID=1
|
||||
show binlog events from 79 limit 2,1;
|
||||
Log_name Pos Event_type Server_id Log_seq Info
|
||||
master-bin.001 200 Query 1 4 use test; insert into t1 values (NULL)
|
||||
Log_name Pos Event_type Server_id Orig_log_pos Info
|
||||
master-bin.001 200 Query 1 200 use test; insert into t1 values (NULL)
|
||||
flush logs;
|
||||
create table t1 (n int);
|
||||
insert into t1 values (1);
|
||||
drop table t1;
|
||||
show binlog events;
|
||||
Log_name Pos Event_type Server_id Log_seq Info
|
||||
master-bin.001 4 Start 1 1 Server ver: VERSION, Binlog ver: 2
|
||||
master-bin.001 79 Query 1 2 use test; create table t1(n int not null auto_increment primary key)
|
||||
master-bin.001 172 Intvar 1 3 INSERT_ID=1
|
||||
master-bin.001 200 Query 1 4 use test; insert into t1 values (NULL)
|
||||
master-bin.001 263 Query 1 5 use test; drop table t1
|
||||
master-bin.001 311 Query 1 6 use test; create table t1 (word char(20) not null)
|
||||
master-bin.001 386 Create_file 1 7 db=test;table=t1;file_id=1;block_len=81
|
||||
master-bin.001 556 Exec_load 1 8 ;file_id=1
|
||||
master-bin.001 579 Query 1 9 use test; drop table t1
|
||||
master-bin.001 627 Rotate 1 10 master-bin.002;pos=4
|
||||
master-bin.001 668 Stop 1 11
|
||||
Log_name Pos Event_type Server_id Orig_log_pos Info
|
||||
master-bin.001 4 Start 1 4 Server ver: 4.0.1-alpha-debug-log, Binlog ver: 3
|
||||
master-bin.001 79 Query 1 79 use test; create table t1(n int not null auto_increment primary key)
|
||||
master-bin.001 172 Intvar 1 172 INSERT_ID=1
|
||||
master-bin.001 200 Query 1 200 use test; insert into t1 values (NULL)
|
||||
master-bin.001 263 Query 1 263 use test; drop table t1
|
||||
master-bin.001 311 Query 1 311 use test; create table t1 (word char(20) not null)
|
||||
master-bin.001 386 Create_file 1 386 db=test;table=t1;file_id=1;block_len=81
|
||||
master-bin.001 556 Exec_load 1 556 ;file_id=1
|
||||
master-bin.001 579 Query 1 579 use test; drop table t1
|
||||
master-bin.001 627 Rotate 1 627 master-bin.002;pos=4
|
||||
master-bin.001 668 Stop 1 668
|
||||
show binlog events in 'master-bin.002';
|
||||
Log_name Pos Event_type Server_id Log_seq Info
|
||||
master-bin.002 4 Query 1 1 use test; create table t1 (n int)
|
||||
master-bin.002 62 Query 1 2 use test; insert into t1 values (1)
|
||||
master-bin.002 122 Query 1 3 use test; drop table t1
|
||||
Log_name Pos Event_type Server_id Orig_log_pos Info
|
||||
master-bin.002 4 Query 1 4 use test; create table t1 (n int)
|
||||
master-bin.002 62 Query 1 62 use test; insert into t1 values (1)
|
||||
master-bin.002 122 Query 1 122 use test; drop table t1
|
||||
show master logs;
|
||||
Log_name
|
||||
master-bin.001
|
||||
|
@ -67,32 +67,45 @@ Log_name
|
|||
slave-bin.001
|
||||
slave-bin.002
|
||||
show binlog events in 'slave-bin.001' from 4;
|
||||
Log_name Pos Event_type Server_id Orig_log_pos Info
|
||||
slave-bin.001 4 Start 2 4 Server ver: 4.0.1-alpha-debug-log, Binlog ver: 3
|
||||
slave-bin.001 79 Slave 2 79 host=127.0.0.1,port=9306,log=master-bin.001,pos=4
|
||||
slave-bin.001 132 Query 1 79 use test; create table t1(n int not null auto_increment primary key)
|
||||
slave-bin.001 225 Intvar 1 200 INSERT_ID=1
|
||||
slave-bin.001 253 Query 1 200 use test; insert into t1 values (NULL)
|
||||
slave-bin.001 316 Query 1 263 use test; drop table t1
|
||||
slave-bin.001 364 Query 1 311 use test; create table t1 (word char(20) not null)
|
||||
slave-bin.001 439 Create_file 1 386 db=test;table=t1;file_id=1;block_len=81
|
||||
slave-bin.001 618 Exec_load 1 556 ;file_id=1
|
||||
slave-bin.001 641 Query 1 579 use test; drop table t1
|
||||
slave-bin.001 689 Rotate 1 627 slave-bin.002;pos=4; forced by master
|
||||
slave-bin.001 729 Stop 2 729
|
||||
show binlog events in 'slave-bin.002' from 4;
|
||||
Log_name Pos Event_type Server_id Log_seq Info
|
||||
slave-bin.002 4 Slave 2 10 host=127.0.0.1,port=MASTER_PORT,log=master-bin.002,pos=4
|
||||
slave-bin.002 57 Query 1 1 use test; create table t1 (n int)
|
||||
slave-bin.002 115 Query 1 2 use test; insert into t1 values (1)
|
||||
slave-bin.002 175 Query 1 3 use test; drop table t1
|
||||
Log_name Pos Event_type Server_id Orig_log_pos Info
|
||||
slave-bin.002 4 Slave 2 627 host=127.0.0.1,port=9306,log=master-bin.002,pos=4
|
||||
slave-bin.002 57 Query 1 4 use test; create table t1 (n int)
|
||||
slave-bin.002 115 Query 1 62 use test; insert into t1 values (1)
|
||||
slave-bin.002 175 Query 1 122 use test; drop table t1
|
||||
show slave status;
|
||||
Master_Host Master_User Master_Port Connect_retry Log_File Pos Slave_Running Replicate_do_db Replicate_ignore_db Last_errno Last_error Skip_counter Last_log_seq
|
||||
127.0.0.1 root MASTER_PORT 1 master-bin.002 170 Yes 0 0 3
|
||||
Master_Host Master_User Master_Port Connect_retry Master_Log_File Read_Master_Log_Pos Relay_Log_File Relay_Log_Pos Relay_Master_Log_File Slave_IO_Running Slave_SQL_Running Replicate_do_db Replicate_ignore_db Last_errno Last_error Skip_counter Exec_master_log_pos
|
||||
127.0.0.1 root 9306 1 master-bin.002 170 mysql-relay-bin.002 935 master-bin.002 Yes Yes 0 0 170
|
||||
show new master for slave with master_log_file='master-bin.001' and
|
||||
master_log_pos=4 and master_log_seq=1 and master_server_id=1;
|
||||
master_log_pos=4 and master_server_id=1;
|
||||
Log_name Log_pos
|
||||
slave-bin.001 132
|
||||
show new master for slave with master_log_file='master-bin.001' and
|
||||
master_log_pos=79 and master_log_seq=2 and master_server_id=1;
|
||||
master_log_pos=79 and master_server_id=1;
|
||||
Log_name Log_pos
|
||||
slave-bin.001 225
|
||||
show new master for slave with master_log_file='master-bin.001' and
|
||||
master_log_pos=311 and master_log_seq=6 and master_server_id=1;
|
||||
master_log_pos=311 and master_server_id=1;
|
||||
Log_name Log_pos
|
||||
slave-bin.001 439
|
||||
show new master for slave with master_log_file='master-bin.002' and
|
||||
master_log_pos=4 and master_log_seq=1 and master_server_id=1;
|
||||
master_log_pos=4 and master_server_id=1;
|
||||
Log_name Log_pos
|
||||
slave-bin.002 57
|
||||
show new master for slave with master_log_file='master-bin.002' and
|
||||
master_log_pos=137 and master_log_seq=3 and master_server_id=1;
|
||||
master_log_pos=122 and master_server_id=1;
|
||||
Log_name Log_pos
|
||||
slave-bin.002 223
|
||||
|
|
8
mysql-test/resolve-stack
Executable file
8
mysql-test/resolve-stack
Executable file
|
@ -0,0 +1,8 @@
|
|||
#! /bin/sh
|
||||
# A shortcut for resolving stacks when debugging when
|
||||
# we cannot duplicate the crash in a debugger and have to
|
||||
# resort to using stack traces
|
||||
|
||||
nm --numeric-sort ../sql/mysqld > var/tmp/mysqld.sym
|
||||
echo "Please type or paste the numeric stack trace,Ctrl-C to quit:"
|
||||
../extra/resolve_stack_dump -s var/tmp/mysqld.sym
|
1
mysql-test/t/rpl000016-slave.opt
Normal file
1
mysql-test/t/rpl000016-slave.opt
Normal file
|
@ -0,0 +1 @@
|
|||
-O max_binlog_size=2048
|
|
@ -1 +1,2 @@
|
|||
rm -f $MYSQL_TEST_DIR/var/slave-data/master.info
|
||||
rm -f $MYSQL_TEST_DIR/var/slave-data/*relay*
|
||||
|
|
|
@ -1,3 +1,4 @@
|
|||
rm -f $MYSQL_TEST_DIR/var/slave-data/*relay*
|
||||
cat > $MYSQL_TEST_DIR/var/slave-data/master.info <<EOF
|
||||
master-bin.001
|
||||
4
|
||||
|
|
|
@ -46,12 +46,12 @@ show binlog events in 'slave-bin.002' from 4;
|
|||
--replace_result 3306 MASTER_PORT 9306 MASTER_PORT 3334 MASTER_PORT 3336 MASTER_PORT
|
||||
show slave status;
|
||||
show new master for slave with master_log_file='master-bin.001' and
|
||||
master_log_pos=4 and master_log_seq=1 and master_server_id=1;
|
||||
master_log_pos=4 and master_server_id=1;
|
||||
show new master for slave with master_log_file='master-bin.001' and
|
||||
master_log_pos=79 and master_log_seq=2 and master_server_id=1;
|
||||
master_log_pos=79 and master_server_id=1;
|
||||
show new master for slave with master_log_file='master-bin.001' and
|
||||
master_log_pos=311 and master_log_seq=6 and master_server_id=1;
|
||||
master_log_pos=311 and master_server_id=1;
|
||||
show new master for slave with master_log_file='master-bin.002' and
|
||||
master_log_pos=4 and master_log_seq=1 and master_server_id=1;
|
||||
master_log_pos=4 and master_server_id=1;
|
||||
show new master for slave with master_log_file='master-bin.002' and
|
||||
master_log_pos=137 and master_log_seq=3 and master_server_id=1;
|
||||
master_log_pos=122 and master_server_id=1;
|
||||
|
|
|
@ -122,6 +122,8 @@ int init_io_cache(IO_CACHE *info, File file, uint cachesize,
|
|||
info->pos_in_file= seek_offset;
|
||||
info->pre_close = info->pre_read = info->post_read = 0;
|
||||
info->arg = 0;
|
||||
info->init_count++; /* we assume the user had set it to 0 prior to
|
||||
first call */
|
||||
info->alloced_buffer = 0;
|
||||
info->buffer=0;
|
||||
info->seek_not_done= test(file >= 0);
|
||||
|
@ -446,11 +448,13 @@ int _my_b_seq_read(register IO_CACHE *info, byte *Buffer, uint Count)
|
|||
info->end_of_file)
|
||||
goto read_append_buffer;
|
||||
|
||||
if (info->seek_not_done)
|
||||
{ /* File touched, do seek */
|
||||
VOID(my_seek(info->file,pos_in_file,MY_SEEK_SET,MYF(0)));
|
||||
info->seek_not_done=0;
|
||||
}
|
||||
/*
|
||||
With read-append cache we must always do a seek before we read,
|
||||
because the write could have moved the file pointer astray
|
||||
*/
|
||||
VOID(my_seek(info->file,pos_in_file,MY_SEEK_SET,MYF(0)));
|
||||
info->seek_not_done=0;
|
||||
|
||||
diff_length=(uint) (pos_in_file & (IO_SIZE-1));
|
||||
|
||||
/* now the second stage begins - read from file descriptor */
|
||||
|
@ -506,6 +510,13 @@ int _my_b_seq_read(register IO_CACHE *info, byte *Buffer, uint Count)
|
|||
memcpy(Buffer,info->buffer,(size_t) length);
|
||||
Count -= length;
|
||||
Buffer += length;
|
||||
|
||||
/*
|
||||
added the line below to make
|
||||
DBUG_ASSERT(pos_in_file==info->end_of_file) pass.
|
||||
otherwise this does not appear to be needed
|
||||
*/
|
||||
pos_in_file += length;
|
||||
goto read_append_buffer;
|
||||
}
|
||||
}
|
||||
|
@ -527,10 +538,13 @@ read_append_buffer:
|
|||
/* First copy the data to Count */
|
||||
uint len_in_buff = (uint) (info->write_pos - info->append_read_pos);
|
||||
uint copy_len;
|
||||
uint transfer_len;
|
||||
|
||||
DBUG_ASSERT(info->append_read_pos <= info->write_pos);
|
||||
DBUG_ASSERT(pos_in_file == info->end_of_file);
|
||||
|
||||
/*
|
||||
TODO: figure out if the below assert is needed or correct.
|
||||
*/
|
||||
DBUG_ASSERT(pos_in_file == info->end_of_file);
|
||||
copy_len=min(Count, len_in_buff);
|
||||
memcpy(Buffer, info->append_read_pos, copy_len);
|
||||
info->append_read_pos += copy_len;
|
||||
|
@ -540,11 +554,12 @@ read_append_buffer:
|
|||
|
||||
/* Fill read buffer with data from write buffer */
|
||||
memcpy(info->buffer, info->append_read_pos,
|
||||
(size_t) (len_in_buff - copy_len));
|
||||
(size_t) (transfer_len=len_in_buff - copy_len));
|
||||
info->read_pos= info->buffer;
|
||||
info->read_end= info->buffer+(len_in_buff - copy_len);
|
||||
info->read_end= info->buffer+transfer_len;
|
||||
info->append_read_pos=info->write_pos;
|
||||
info->pos_in_file+=len_in_buff;
|
||||
info->pos_in_file=pos_in_file+copy_len;
|
||||
info->end_of_file+=len_in_buff;
|
||||
}
|
||||
unlock_append_buffer(info);
|
||||
return Count ? 1 : 0;
|
||||
|
@ -886,12 +901,10 @@ int flush_io_cache(IO_CACHE *info)
|
|||
if ((length=(uint) (info->write_pos - info->write_buffer)))
|
||||
{
|
||||
pos_in_file=info->pos_in_file;
|
||||
if (append_cache)
|
||||
{
|
||||
pos_in_file=info->end_of_file;
|
||||
info->seek_not_done=1;
|
||||
}
|
||||
if (info->seek_not_done)
|
||||
/* if we have append cache, we always open the file with
|
||||
O_APPEND which moves the pos to EOF automatically on every write
|
||||
*/
|
||||
if (!append_cache && info->seek_not_done)
|
||||
{ /* File touched, do seek */
|
||||
if (my_seek(info->file,pos_in_file,MY_SEEK_SET,MYF(0)) ==
|
||||
MY_FILEPOS_ERROR)
|
||||
|
@ -901,20 +914,24 @@ int flush_io_cache(IO_CACHE *info)
|
|||
if (!append_cache)
|
||||
info->seek_not_done=0;
|
||||
}
|
||||
info->write_pos= info->write_buffer;
|
||||
if (!append_cache)
|
||||
info->pos_in_file+=length;
|
||||
info->write_end= (info->write_buffer+info->buffer_length-
|
||||
((pos_in_file+length) & (IO_SIZE-1)));
|
||||
|
||||
/* Set this to be used if we are using SEQ_READ_APPEND */
|
||||
info->append_read_pos = info->write_buffer;
|
||||
if (my_write(info->file,info->write_buffer,length,
|
||||
info->myflags | MY_NABP))
|
||||
info->error= -1;
|
||||
else
|
||||
info->error= 0;
|
||||
set_if_bigger(info->end_of_file,(pos_in_file+length));
|
||||
if (!append_cache)
|
||||
{
|
||||
set_if_bigger(info->end_of_file,(pos_in_file+length));
|
||||
}
|
||||
else
|
||||
info->end_of_file+=(info->write_pos-info->append_read_pos);
|
||||
|
||||
info->append_read_pos=info->write_pos=info->write_buffer;
|
||||
DBUG_RETURN(info->error);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -31,12 +31,26 @@
|
|||
|
||||
void my_b_seek(IO_CACHE *info,my_off_t pos)
|
||||
{
|
||||
my_off_t offset = (pos - info->pos_in_file);
|
||||
my_off_t offset;
|
||||
DBUG_ENTER("my_b_seek");
|
||||
DBUG_PRINT("enter",("pos: %lu", (ulong) pos));
|
||||
|
||||
if (info->type == READ_CACHE)
|
||||
/*
|
||||
TODO: verify that it is OK to do seek in the non-append
|
||||
area in SEQ_READ_APPEND cache
|
||||
*/
|
||||
/* TODO:
|
||||
a) see if this always works
|
||||
b) see if there is a better way to make it work
|
||||
*/
|
||||
if (info->type == SEQ_READ_APPEND)
|
||||
flush_io_cache(info);
|
||||
|
||||
offset=(pos - info->pos_in_file);
|
||||
|
||||
if (info->type == READ_CACHE || info->type == SEQ_READ_APPEND)
|
||||
{
|
||||
/* TODO: explain why this works if pos < info->pos_in_file */
|
||||
if ((ulonglong) offset < (ulonglong) (info->read_end - info->buffer))
|
||||
{
|
||||
/* The read is in the current buffer; Reuse it */
|
||||
|
|
|
@ -69,7 +69,8 @@ int safe_mutex_lock(safe_mutex_t *mp,const char *file, uint line)
|
|||
}
|
||||
if (mp->count++)
|
||||
{
|
||||
fprintf(stderr,"safe_mutex: Error in thread libray: Got mutex at %s, line %d more than 1 time\n", file,line);
|
||||
fprintf(stderr,"safe_mutex: Error in thread libray: Got mutex at %s, \
|
||||
line %d more than 1 time\n", file,line);
|
||||
fflush(stderr);
|
||||
abort();
|
||||
}
|
||||
|
|
|
@ -1453,11 +1453,13 @@ longlong Item_master_pos_wait::val_int()
|
|||
return 0;
|
||||
}
|
||||
ulong pos = (ulong)args[1]->val_int();
|
||||
if ((event_count = glob_mi.wait_for_pos(thd, log_name, pos)) == -1)
|
||||
LOCK_ACTIVE_MI;
|
||||
if ((event_count = active_mi->rli.wait_for_pos(thd, log_name, pos)) == -1)
|
||||
{
|
||||
null_value = 1;
|
||||
event_count=0;
|
||||
}
|
||||
UNLOCK_ACTIVE_MI;
|
||||
return event_count;
|
||||
}
|
||||
|
||||
|
|
|
@ -222,7 +222,6 @@ static SYMBOL symbols[] = {
|
|||
{ "MASTER_HOST", SYM(MASTER_HOST_SYM),0,0},
|
||||
{ "MASTER_LOG_FILE", SYM(MASTER_LOG_FILE_SYM),0,0},
|
||||
{ "MASTER_LOG_POS", SYM(MASTER_LOG_POS_SYM),0,0},
|
||||
{ "MASTER_LOG_SEQ", SYM(MASTER_LOG_SEQ_SYM),0,0},
|
||||
{ "MASTER_PASSWORD", SYM(MASTER_PASSWORD_SYM),0,0},
|
||||
{ "MASTER_PORT", SYM(MASTER_PORT_SYM),0,0},
|
||||
{ "MASTER_SERVER_ID", SYM(MASTER_SERVER_ID_SYM),0,0},
|
||||
|
|
338
sql/log.cc
338
sql/log.cc
|
@ -1,15 +1,15 @@
|
|||
/* Copyright (C) 2000 MySQL AB & MySQL Finland AB & TCX DataKonsult AB
|
||||
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
|
||||
|
@ -29,6 +29,7 @@
|
|||
#include <my_dir.h>
|
||||
#include <stdarg.h>
|
||||
#include <m_ctype.h> // For test_if_number
|
||||
#include <assert.h>
|
||||
|
||||
MYSQL_LOG mysql_log,mysql_update_log,mysql_slow_log,mysql_bin_log;
|
||||
extern I_List<i_string> binlog_do_db, binlog_ignore_db;
|
||||
|
@ -81,7 +82,7 @@ static int find_uniq_filename(char *name)
|
|||
|
||||
MYSQL_LOG::MYSQL_LOG(): last_time(0), query_start(0),index_file(-1),
|
||||
name(0), log_type(LOG_CLOSED),write_error(0),
|
||||
inited(0), log_seq(1), file_id(1),no_rotate(0),
|
||||
inited(0), file_id(1),no_rotate(0),
|
||||
need_start_event(1)
|
||||
{
|
||||
/*
|
||||
|
@ -112,7 +113,7 @@ void MYSQL_LOG::set_index_file_name(const char* index_file_name)
|
|||
|
||||
|
||||
int MYSQL_LOG::generate_new_name(char *new_name, const char *log_name)
|
||||
{
|
||||
{
|
||||
if (log_type == LOG_NORMAL)
|
||||
fn_format(new_name,log_name,mysql_data_home,"",4);
|
||||
else
|
||||
|
@ -138,15 +139,18 @@ bool MYSQL_LOG::open_index( int options)
|
|||
}
|
||||
|
||||
void MYSQL_LOG::init(enum_log_type log_type_arg,
|
||||
enum cache_type io_cache_type_arg)
|
||||
enum cache_type io_cache_type_arg,
|
||||
bool no_auto_events_arg)
|
||||
{
|
||||
log_type = log_type_arg;
|
||||
io_cache_type = io_cache_type_arg;
|
||||
no_auto_events = no_auto_events_arg;
|
||||
if (!inited)
|
||||
{
|
||||
inited=1;
|
||||
(void) pthread_mutex_init(&LOCK_log,MY_MUTEX_INIT_SLOW);
|
||||
(void) pthread_mutex_init(&LOCK_index, MY_MUTEX_INIT_SLOW);
|
||||
(void) pthread_cond_init(&update_cond, 0);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -160,32 +164,38 @@ void MYSQL_LOG::close_index()
|
|||
}
|
||||
|
||||
void MYSQL_LOG::open(const char *log_name, enum_log_type log_type_arg,
|
||||
const char *new_name)
|
||||
const char *new_name, enum cache_type io_cache_type_arg,
|
||||
bool no_auto_events_arg)
|
||||
{
|
||||
MY_STAT tmp_stat;
|
||||
char buff[512];
|
||||
File file= -1;
|
||||
bool do_magic;
|
||||
|
||||
int open_flags = O_CREAT | O_APPEND | O_BINARY;
|
||||
if (!inited && log_type_arg == LOG_BIN && *fn_ext(log_name))
|
||||
no_rotate = 1;
|
||||
init(log_type_arg);
|
||||
|
||||
init(log_type_arg,io_cache_type_arg,no_auto_events_arg);
|
||||
|
||||
if (!(name=my_strdup(log_name,MYF(MY_WME))))
|
||||
goto err;
|
||||
if (new_name)
|
||||
strmov(log_file_name,new_name);
|
||||
else if (generate_new_name(log_file_name, name))
|
||||
goto err;
|
||||
|
||||
|
||||
if (io_cache_type == SEQ_READ_APPEND)
|
||||
open_flags |= O_RDWR;
|
||||
else
|
||||
open_flags |= O_WRONLY;
|
||||
|
||||
if (log_type == LOG_BIN && !index_file_name[0])
|
||||
fn_format(index_file_name, name, mysql_data_home, ".index", 6);
|
||||
|
||||
|
||||
db[0]=0;
|
||||
do_magic = ((log_type == LOG_BIN) && !my_stat(log_file_name,
|
||||
&tmp_stat, MYF(0)));
|
||||
|
||||
if ((file=my_open(log_file_name,O_CREAT | O_APPEND | O_WRONLY | O_BINARY,
|
||||
|
||||
if ((file=my_open(log_file_name,open_flags,
|
||||
MYF(MY_WME | ME_WAITTANG))) < 0 ||
|
||||
init_io_cache(&log_file, file, IO_SIZE, io_cache_type,
|
||||
my_tell(file,MYF(MY_WME)), 0, MYF(MY_WME | MY_NABP)))
|
||||
|
@ -235,11 +245,10 @@ void MYSQL_LOG::open(const char *log_name, enum_log_type log_type_arg,
|
|||
open_index(O_APPEND | O_RDWR | O_CREAT))
|
||||
goto err;
|
||||
|
||||
log_seq = 1;
|
||||
if (need_start_event)
|
||||
if (need_start_event && !no_auto_events)
|
||||
{
|
||||
Start_log_event s;
|
||||
s.set_log_seq(0, this);
|
||||
s.set_log_pos(this);
|
||||
s.write(&log_file);
|
||||
need_start_event=0;
|
||||
}
|
||||
|
@ -264,9 +273,7 @@ err:
|
|||
end_io_cache(&log_file);
|
||||
x_free(name); name=0;
|
||||
log_type=LOG_CLOSED;
|
||||
|
||||
return;
|
||||
|
||||
}
|
||||
|
||||
int MYSQL_LOG::get_current_log(LOG_INFO* linfo)
|
||||
|
@ -279,7 +286,8 @@ int MYSQL_LOG::get_current_log(LOG_INFO* linfo)
|
|||
}
|
||||
|
||||
// if log_name is "" we stop at the first entry
|
||||
int MYSQL_LOG::find_first_log(LOG_INFO* linfo, const char* log_name)
|
||||
int MYSQL_LOG::find_first_log(LOG_INFO* linfo, const char* log_name,
|
||||
bool need_mutex)
|
||||
{
|
||||
if (index_file < 0)
|
||||
return LOG_INFO_INVALID;
|
||||
|
@ -290,7 +298,8 @@ int MYSQL_LOG::find_first_log(LOG_INFO* linfo, const char* log_name)
|
|||
|
||||
// mutex needed because we need to make sure the file pointer does not move
|
||||
// from under our feet
|
||||
pthread_mutex_lock(&LOCK_index);
|
||||
if (need_mutex)
|
||||
pthread_mutex_lock(&LOCK_index);
|
||||
if (init_io_cache(&io_cache, index_file, IO_SIZE, READ_CACHE, (my_off_t) 0,
|
||||
0, MYF(MY_WME)))
|
||||
{
|
||||
|
@ -319,14 +328,15 @@ int MYSQL_LOG::find_first_log(LOG_INFO* linfo, const char* log_name)
|
|||
error = 0;
|
||||
|
||||
err:
|
||||
pthread_mutex_unlock(&LOCK_index);
|
||||
if (need_mutex)
|
||||
pthread_mutex_unlock(&LOCK_index);
|
||||
end_io_cache(&io_cache);
|
||||
return error;
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
int MYSQL_LOG::find_next_log(LOG_INFO* linfo)
|
||||
int MYSQL_LOG::find_next_log(LOG_INFO* linfo, bool need_lock)
|
||||
{
|
||||
// mutex needed because we need to make sure the file pointer does not move
|
||||
// from under our feet
|
||||
|
@ -335,8 +345,8 @@ int MYSQL_LOG::find_next_log(LOG_INFO* linfo)
|
|||
char* fname = linfo->log_file_name;
|
||||
IO_CACHE io_cache;
|
||||
uint length;
|
||||
|
||||
pthread_mutex_lock(&LOCK_index);
|
||||
if (need_lock)
|
||||
pthread_mutex_lock(&LOCK_index);
|
||||
if (init_io_cache(&io_cache, index_file, IO_SIZE,
|
||||
READ_CACHE, (my_off_t) linfo->index_file_offset, 0,
|
||||
MYF(MY_WME)))
|
||||
|
@ -354,11 +364,125 @@ int MYSQL_LOG::find_next_log(LOG_INFO* linfo)
|
|||
error = 0;
|
||||
|
||||
err:
|
||||
pthread_mutex_unlock(&LOCK_index);
|
||||
if (need_lock)
|
||||
pthread_mutex_unlock(&LOCK_index);
|
||||
end_io_cache(&io_cache);
|
||||
return error;
|
||||
}
|
||||
|
||||
int MYSQL_LOG::reset_logs(THD* thd)
|
||||
{
|
||||
LOG_INFO linfo;
|
||||
int error=0;
|
||||
const char* save_name;
|
||||
enum_log_type save_log_type;
|
||||
pthread_mutex_lock(&LOCK_log);
|
||||
if (find_first_log(&linfo,""))
|
||||
{
|
||||
error=1;
|
||||
goto err;
|
||||
}
|
||||
|
||||
for(;;)
|
||||
{
|
||||
my_delete(linfo.log_file_name, MYF(MY_WME));
|
||||
if (find_next_log(&linfo))
|
||||
break;
|
||||
}
|
||||
save_name=name;
|
||||
name=0;
|
||||
save_log_type=log_type;
|
||||
close(1);
|
||||
my_delete(index_file_name, MYF(MY_WME));
|
||||
if (thd && !thd->slave_thread)
|
||||
need_start_event=1;
|
||||
open(save_name,save_log_type,0,io_cache_type,no_auto_events);
|
||||
my_free((gptr)save_name,MYF(0));
|
||||
err:
|
||||
pthread_mutex_unlock(&LOCK_log);
|
||||
return error;
|
||||
}
|
||||
|
||||
int MYSQL_LOG::purge_first_log(struct st_relay_log_info* rli)
|
||||
{
|
||||
// pre-conditions
|
||||
DBUG_ASSERT(is_open());
|
||||
DBUG_ASSERT(index_file >= 0);
|
||||
DBUG_ASSERT(rli->slave_running == 1);
|
||||
DBUG_ASSERT(!strcmp(rli->linfo.log_file_name,rli->relay_log_name));
|
||||
// assume that we have previously read the first log and
|
||||
// stored it in rli->relay_log_name
|
||||
DBUG_ASSERT(rli->linfo.index_file_offset ==
|
||||
strlen(rli->relay_log_name) + 1);
|
||||
|
||||
int tmp_fd;
|
||||
|
||||
|
||||
char* fname, *io_buf;
|
||||
int error = 0;
|
||||
if (!(fname = (char*)my_malloc(IO_SIZE+FN_REFLEN, MYF(MY_WME))))
|
||||
return 1;
|
||||
pthread_mutex_lock(&LOCK_index);
|
||||
my_seek(index_file,rli->linfo.index_file_offset,
|
||||
MY_SEEK_SET, MYF(MY_WME));
|
||||
io_buf = fname + FN_REFLEN;
|
||||
strxmov(fname,rli->relay_log_name,".tmp",NullS);
|
||||
|
||||
if ((tmp_fd = my_open(fname,O_CREAT|O_BINARY|O_RDWR, MYF(MY_WME))) < 0)
|
||||
{
|
||||
error = 1;
|
||||
goto err;
|
||||
}
|
||||
for (;;)
|
||||
{
|
||||
int bytes_read;
|
||||
bytes_read = my_read(index_file, io_buf, IO_SIZE, MYF(0));
|
||||
if (bytes_read < 0) // error
|
||||
{
|
||||
error=1;
|
||||
goto err;
|
||||
}
|
||||
if (!bytes_read)
|
||||
break; // end of file
|
||||
// otherwise, we've read something and need to write it out
|
||||
if (my_write(tmp_fd, io_buf, bytes_read, MYF(MY_WME|MY_NABP)))
|
||||
{
|
||||
error=1;
|
||||
goto err;
|
||||
}
|
||||
}
|
||||
err:
|
||||
if (tmp_fd)
|
||||
my_close(tmp_fd, MYF(MY_WME));
|
||||
if (error)
|
||||
my_delete(fname, MYF(0)); // do not report error if the file is not there
|
||||
else
|
||||
{
|
||||
my_close(index_file, MYF(MY_WME));
|
||||
if (my_rename(fname,index_file_name,MYF(MY_WME)) ||
|
||||
(index_file=my_open(index_file_name,O_BINARY|O_RDWR|O_APPEND,
|
||||
MYF(MY_WME)))<0 ||
|
||||
my_delete(rli->relay_log_name, MYF(MY_WME)))
|
||||
error=1;
|
||||
if ((error=find_first_log(&rli->linfo,"",0/*no mutex*/)))
|
||||
{
|
||||
char buff[22];
|
||||
sql_print_error("next log error=%d,offset=%s,log=%s",error,
|
||||
llstr(rli->linfo.index_file_offset,buff),
|
||||
rli->linfo.log_file_name);
|
||||
goto err2;
|
||||
}
|
||||
rli->relay_log_pos = 4;
|
||||
strnmov(rli->relay_log_name,rli->linfo.log_file_name,
|
||||
sizeof(rli->relay_log_name));
|
||||
}
|
||||
// no need to free io_buf because we allocated both fname and io_buf in
|
||||
// one malloc()
|
||||
err2:
|
||||
pthread_mutex_unlock(&LOCK_index);
|
||||
my_free(fname, MYF(MY_WME));
|
||||
return error;
|
||||
}
|
||||
|
||||
int MYSQL_LOG::purge_logs(THD* thd, const char* to_log)
|
||||
{
|
||||
|
@ -373,9 +497,9 @@ int MYSQL_LOG::purge_logs(THD* thd, const char* to_log)
|
|||
my_off_t purge_offset ;
|
||||
LINT_INIT(purge_offset);
|
||||
IO_CACHE io_cache;
|
||||
|
||||
|
||||
pthread_mutex_lock(&LOCK_index);
|
||||
|
||||
|
||||
if (init_io_cache(&io_cache,index_file, IO_SIZE*2, READ_CACHE, (my_off_t) 0,
|
||||
0, MYF(MY_WME)))
|
||||
{
|
||||
|
@ -388,16 +512,15 @@ int MYSQL_LOG::purge_logs(THD* thd, const char* to_log)
|
|||
goto err;
|
||||
}
|
||||
logs_to_purge_inited = 1;
|
||||
|
||||
|
||||
if (init_dynamic_array(&logs_to_keep, sizeof(char*), 1024, 1024))
|
||||
{
|
||||
error = LOG_INFO_MEM;
|
||||
goto err;
|
||||
}
|
||||
logs_to_keep_inited = 1;
|
||||
|
||||
|
||||
for(;;)
|
||||
|
||||
for (;;)
|
||||
{
|
||||
my_off_t init_purge_offset= my_b_tell(&io_cache);
|
||||
if (!(fname_len=my_b_gets(&io_cache, fname, FN_REFLEN)))
|
||||
|
@ -409,19 +532,19 @@ int MYSQL_LOG::purge_logs(THD* thd, const char* to_log)
|
|||
}
|
||||
|
||||
fname[--fname_len]=0; // kill \n
|
||||
if(!memcmp(fname, to_log, fname_len + 1 ))
|
||||
if (!memcmp(fname, to_log, fname_len + 1 ))
|
||||
{
|
||||
found_log = 1;
|
||||
purge_offset = init_purge_offset;
|
||||
}
|
||||
|
||||
|
||||
// if one of the logs before the target is in use
|
||||
if(!found_log && log_in_use(fname))
|
||||
if (!found_log && log_in_use(fname))
|
||||
{
|
||||
error = LOG_INFO_IN_USE;
|
||||
goto err;
|
||||
}
|
||||
|
||||
|
||||
if (!(p = sql_memdup(fname, fname_len+1)) ||
|
||||
insert_dynamic(found_log ? &logs_to_keep : &logs_to_purge,
|
||||
(gptr) &p))
|
||||
|
@ -430,22 +553,22 @@ int MYSQL_LOG::purge_logs(THD* thd, const char* to_log)
|
|||
goto err;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
end_io_cache(&io_cache);
|
||||
if(!found_log)
|
||||
if (!found_log)
|
||||
{
|
||||
error = LOG_INFO_EOF;
|
||||
goto err;
|
||||
}
|
||||
|
||||
for(i = 0; i < logs_to_purge.elements; i++)
|
||||
|
||||
for (i = 0; i < logs_to_purge.elements; i++)
|
||||
{
|
||||
char* l;
|
||||
get_dynamic(&logs_to_purge, (gptr)&l, i);
|
||||
if (my_delete(l, MYF(MY_WME)))
|
||||
sql_print_error("Error deleting %s during purge", l);
|
||||
}
|
||||
|
||||
|
||||
// if we get killed -9 here, the sysadmin would have to do a small
|
||||
// vi job on the log index file after restart - otherwise, this should
|
||||
// be safe
|
||||
|
@ -461,9 +584,9 @@ during log purge for write");
|
|||
#else
|
||||
my_close(index_file, MYF(MY_WME));
|
||||
my_delete(index_file_name, MYF(MY_WME));
|
||||
if(!(index_file = my_open(index_file_name,
|
||||
if ((index_file = my_open(index_file_name,
|
||||
O_CREAT | O_BINARY | O_RDWR | O_APPEND,
|
||||
MYF(MY_WME))))
|
||||
MYF(MY_WME)))<0)
|
||||
{
|
||||
sql_print_error("Could not re-open the binlog index file \
|
||||
during log purge for write");
|
||||
|
@ -471,8 +594,8 @@ during log purge for write");
|
|||
goto err;
|
||||
}
|
||||
#endif
|
||||
|
||||
for(i = 0; i < logs_to_keep.elements; i++)
|
||||
|
||||
for (i = 0; i < logs_to_keep.elements; i++)
|
||||
{
|
||||
char* l;
|
||||
get_dynamic(&logs_to_keep, (gptr)&l, i);
|
||||
|
@ -490,15 +613,14 @@ during log purge for write");
|
|||
|
||||
err:
|
||||
pthread_mutex_unlock(&LOCK_index);
|
||||
if(logs_to_purge_inited)
|
||||
if (logs_to_purge_inited)
|
||||
delete_dynamic(&logs_to_purge);
|
||||
if(logs_to_keep_inited)
|
||||
if (logs_to_keep_inited)
|
||||
delete_dynamic(&logs_to_keep);
|
||||
end_io_cache(&io_cache);
|
||||
return error;
|
||||
}
|
||||
|
||||
|
||||
// we assume that buf has at least FN_REFLEN bytes alloced
|
||||
void MYSQL_LOG::make_log_name(char* buf, const char* log_ident)
|
||||
{
|
||||
|
@ -509,7 +631,7 @@ void MYSQL_LOG::make_log_name(char* buf, const char* log_ident)
|
|||
int ident_len = (uint) strlen(log_ident);
|
||||
if (dir_len + ident_len + 1 > FN_REFLEN)
|
||||
return; // protection agains malicious buffer overflow
|
||||
|
||||
|
||||
memcpy(buf, log_file_name, dir_len);
|
||||
// copy filename + end null
|
||||
memcpy(buf + dir_len, log_ident, ident_len + 1);
|
||||
|
@ -543,30 +665,36 @@ void MYSQL_LOG::new_file(bool inside_mutex)
|
|||
}
|
||||
if (log_type == LOG_BIN)
|
||||
{
|
||||
/*
|
||||
We log the whole file name for log file as the user may decide
|
||||
to change base names at some point.
|
||||
*/
|
||||
THD* thd = current_thd;
|
||||
Rotate_log_event r(thd,new_name+dirname_length(new_name));
|
||||
r.set_log_seq(0, this);
|
||||
if (!no_auto_events)
|
||||
{
|
||||
/*
|
||||
We log the whole file name for log file as the user may decide
|
||||
to change base names at some point.
|
||||
*/
|
||||
THD* thd = current_thd;
|
||||
Rotate_log_event r(thd,new_name+dirname_length(new_name));
|
||||
r.set_log_pos(this);
|
||||
|
||||
/*
|
||||
This log rotation could have been initiated by a master of
|
||||
the slave running with log-bin we set the flag on rotate
|
||||
event to prevent inifinite log rotation loop
|
||||
*/
|
||||
if (thd && slave_thd && thd == slave_thd)
|
||||
r.flags |= LOG_EVENT_FORCED_ROTATE_F;
|
||||
r.write(&log_file);
|
||||
VOID(pthread_cond_broadcast(&COND_binlog_update));
|
||||
/*
|
||||
This log rotation could have been initiated by a master of
|
||||
the slave running with log-bin we set the flag on rotate
|
||||
event to prevent inifinite log rotation loop
|
||||
*/
|
||||
if (thd && thd->slave_thread)
|
||||
r.flags |= LOG_EVENT_FORCED_ROTATE_F;
|
||||
r.write(&log_file);
|
||||
}
|
||||
// update needs to be signaled even if there is no rotate event
|
||||
// log rotation should give the waiting thread a signal to
|
||||
// discover EOF and move on to the next log
|
||||
signal_update();
|
||||
}
|
||||
else
|
||||
strmov(new_name, old_name); // Reopen old file name
|
||||
}
|
||||
name=0;
|
||||
close();
|
||||
open(old_name, log_type, new_name);
|
||||
open(old_name, log_type, new_name, io_cache_type, no_auto_events);
|
||||
my_free(old_name,MYF(0));
|
||||
last_time=query_start=0;
|
||||
write_error=0;
|
||||
|
@ -575,6 +703,31 @@ void MYSQL_LOG::new_file(bool inside_mutex)
|
|||
}
|
||||
}
|
||||
|
||||
bool MYSQL_LOG::appendv(const char* buf, uint len,...)
|
||||
{
|
||||
bool error = 0;
|
||||
va_list(args);
|
||||
va_start(args,len);
|
||||
|
||||
pthread_mutex_lock(&LOCK_log);
|
||||
do
|
||||
{
|
||||
if (my_b_append(&log_file,buf,len))
|
||||
{
|
||||
error = 1;
|
||||
break;
|
||||
}
|
||||
if ((uint)my_b_append_tell(&log_file) > max_binlog_size)
|
||||
{
|
||||
new_file(1);
|
||||
}
|
||||
} while ((buf=va_arg(args,const char*)) && (len=va_arg(args,uint)));
|
||||
|
||||
if (!error)
|
||||
signal_update();
|
||||
pthread_mutex_unlock(&LOCK_log);
|
||||
return error;
|
||||
}
|
||||
|
||||
bool MYSQL_LOG::write(THD *thd,enum enum_server_command command,
|
||||
const char *format,...)
|
||||
|
@ -661,7 +814,7 @@ bool MYSQL_LOG::write(Log_event* event_info)
|
|||
/* In most cases this is only called if 'is_open()' is true */
|
||||
bool error=0;
|
||||
bool should_rotate = 0;
|
||||
|
||||
|
||||
if (!inited) // Can't use mutex if not init
|
||||
return 0;
|
||||
VOID(pthread_mutex_lock(&LOCK_log));
|
||||
|
@ -684,11 +837,12 @@ bool MYSQL_LOG::write(Log_event* event_info)
|
|||
return 0;
|
||||
}
|
||||
error=1;
|
||||
|
||||
// no check for auto events flag here - this write method should
|
||||
// never be called if auto-events are enabled
|
||||
if (thd && thd->last_insert_id_used)
|
||||
{
|
||||
Intvar_log_event e(thd,(uchar)LAST_INSERT_ID_EVENT,thd->last_insert_id);
|
||||
e.set_log_seq(thd, this);
|
||||
e.set_log_pos(this);
|
||||
if (thd->server_id)
|
||||
e.server_id = thd->server_id;
|
||||
if (e.write(file))
|
||||
|
@ -697,7 +851,7 @@ bool MYSQL_LOG::write(Log_event* event_info)
|
|||
if (thd && thd->insert_id_used)
|
||||
{
|
||||
Intvar_log_event e(thd,(uchar)INSERT_ID_EVENT,thd->last_insert_id);
|
||||
e.set_log_seq(thd, this);
|
||||
e.set_log_pos(this);
|
||||
if (thd->server_id)
|
||||
e.server_id = thd->server_id;
|
||||
if (e.write(file))
|
||||
|
@ -712,12 +866,12 @@ bool MYSQL_LOG::write(Log_event* event_info)
|
|||
// just in case somebody wants it later
|
||||
thd->query_length = (uint)(p - buf);
|
||||
Query_log_event e(thd, buf);
|
||||
e.set_log_seq(thd, this);
|
||||
e.set_log_pos(this);
|
||||
if (e.write(file))
|
||||
goto err;
|
||||
thd->query_length = save_query_length; // clean up
|
||||
}
|
||||
event_info->set_log_seq(thd, this);
|
||||
event_info->set_log_pos(this);
|
||||
if (event_info->write(file) ||
|
||||
file == &log_file && flush_io_cache(file))
|
||||
goto err;
|
||||
|
@ -734,7 +888,7 @@ err:
|
|||
write_error=1;
|
||||
}
|
||||
if (file == &log_file)
|
||||
VOID(pthread_cond_broadcast(&COND_binlog_update));
|
||||
signal_update();
|
||||
}
|
||||
if (should_rotate)
|
||||
new_file(1); // inside mutex
|
||||
|
@ -761,11 +915,11 @@ bool MYSQL_LOG::write(IO_CACHE *cache)
|
|||
{
|
||||
VOID(pthread_mutex_lock(&LOCK_log));
|
||||
bool error=1;
|
||||
|
||||
|
||||
if (is_open())
|
||||
{
|
||||
uint length;
|
||||
|
||||
//QQ: this looks like a bug - why READ_CACHE?
|
||||
if (reinit_io_cache(cache, READ_CACHE, 0, 0, 0))
|
||||
{
|
||||
sql_print_error(ER(ER_ERROR_ON_WRITE), cache->file_name, errno);
|
||||
|
@ -800,10 +954,10 @@ err:
|
|||
if (error)
|
||||
write_error=1;
|
||||
else
|
||||
VOID(pthread_cond_broadcast(&COND_binlog_update));
|
||||
|
||||
signal_update();
|
||||
|
||||
VOID(pthread_mutex_unlock(&LOCK_log));
|
||||
|
||||
|
||||
return error;
|
||||
}
|
||||
|
||||
|
@ -930,21 +1084,37 @@ bool MYSQL_LOG::write(THD *thd,const char *query, uint query_length,
|
|||
return error;
|
||||
}
|
||||
|
||||
void MYSQL_LOG:: wait_for_update(THD* thd)
|
||||
{
|
||||
const char* old_msg = thd->enter_cond(&update_cond, &LOCK_log,
|
||||
"Slave: waiting for binlog update");
|
||||
pthread_cond_wait(&update_cond, &LOCK_log);
|
||||
// this is not a bug - we unlock the mutex for the caller, and expect him
|
||||
// to lock it and then not unlock it upon return. This is a rather odd
|
||||
// way of doing things, but this is the cleanest way I could think of to
|
||||
// solve the race deadlock caused by THD::awake() first acquiring mysys_var
|
||||
// mutex and then the current mutex, while wait_for_update being called with
|
||||
// the current mutex already aquired and THD::exit_cond() trying to acquire
|
||||
// mysys_var mutex. We do need the mutex to be acquired prior to the
|
||||
// invocation of wait_for_update in all cases, so mutex acquisition inside
|
||||
// wait_for_update() is not an option
|
||||
pthread_mutex_unlock(&LOCK_log);
|
||||
thd->exit_cond(old_msg);
|
||||
}
|
||||
|
||||
void MYSQL_LOG::close(bool exiting)
|
||||
{ // One can't set log_type here!
|
||||
if (is_open())
|
||||
{
|
||||
File file=log_file.file;
|
||||
if (log_type == LOG_BIN)
|
||||
if (log_type == LOG_BIN && !no_auto_events)
|
||||
{
|
||||
Stop_log_event s;
|
||||
s.set_log_seq(0, this);
|
||||
s.set_log_pos(this);
|
||||
s.write(&log_file);
|
||||
VOID(pthread_cond_broadcast(&COND_binlog_update));
|
||||
signal_update();
|
||||
}
|
||||
end_io_cache(&log_file);
|
||||
if (my_close(file,MYF(0)) < 0 && ! write_error)
|
||||
if (my_close(log_file.file,MYF(0)) < 0 && ! write_error)
|
||||
{
|
||||
write_error=1;
|
||||
sql_print_error(ER(ER_ERROR_ON_WRITE),name,errno);
|
||||
|
|
519
sql/log_event.cc
519
sql/log_event.cc
File diff suppressed because it is too large
Load diff
331
sql/log_event.h
331
sql/log_event.h
|
@ -1,15 +1,15 @@
|
|||
/* Copyright (C) 2000 MySQL AB & MySQL Finland AB & TCX DataKonsult AB
|
||||
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
|
||||
|
@ -34,7 +34,7 @@
|
|||
#define LOG_READ_TOO_LARGE -7
|
||||
|
||||
#define LOG_EVENT_OFFSET 4
|
||||
#define BINLOG_VERSION 2
|
||||
#define BINLOG_VERSION 3
|
||||
|
||||
/* we could have used SERVER_VERSION_LENGTH, but this introduces an
|
||||
obscure dependency - if somebody decided to change SERVER_VERSION_LENGTH
|
||||
|
@ -77,7 +77,7 @@ struct sql_ex_info
|
|||
char opt_flags;
|
||||
char empty_flags;
|
||||
int cached_new_format;
|
||||
|
||||
|
||||
// store in new format even if old is possible
|
||||
void force_new_format() { cached_new_format = 1;}
|
||||
int data_size() { return new_format() ?
|
||||
|
@ -120,7 +120,7 @@ struct sql_ex_info
|
|||
#define EVENT_TYPE_OFFSET 4
|
||||
#define SERVER_ID_OFFSET 5
|
||||
#define EVENT_LEN_OFFSET 9
|
||||
#define LOG_SEQ_OFFSET 13
|
||||
#define LOG_POS_OFFSET 13
|
||||
#define FLAGS_OFFSET 17
|
||||
|
||||
/* start event post-header */
|
||||
|
@ -206,7 +206,7 @@ class THD;
|
|||
|
||||
extern uint32 server_id;
|
||||
|
||||
struct st_master_info;
|
||||
struct st_relay_log_info;
|
||||
|
||||
class Log_event
|
||||
{
|
||||
|
@ -214,7 +214,7 @@ public:
|
|||
time_t when;
|
||||
ulong exec_time;
|
||||
uint32 server_id;
|
||||
uint32 log_seq;
|
||||
uint32 log_pos;
|
||||
uint16 flags;
|
||||
int cached_event_len;
|
||||
char* temp_buf;
|
||||
|
@ -231,7 +231,7 @@ public:
|
|||
{
|
||||
my_free((gptr) ptr, MYF(MY_WME|MY_ALLOW_ZERO_PTR));
|
||||
}
|
||||
|
||||
|
||||
int write(IO_CACHE* file);
|
||||
int write_header(IO_CACHE* file);
|
||||
virtual int write_data(IO_CACHE* file)
|
||||
|
@ -244,51 +244,55 @@ public:
|
|||
virtual bool is_valid() = 0;
|
||||
virtual bool get_cache_stmt() { return 0; }
|
||||
Log_event(const char* buf, bool old_format);
|
||||
#ifndef MYSQL_CLIENT
|
||||
Log_event(THD* thd_arg, uint16 flags_arg = 0);
|
||||
#endif
|
||||
virtual ~Log_event() { free_temp_buf();}
|
||||
void register_temp_buf(char* buf) { temp_buf = buf; }
|
||||
void free_temp_buf()
|
||||
{
|
||||
if (temp_buf)
|
||||
{
|
||||
my_free(temp_buf, MYF(0));
|
||||
temp_buf = 0;
|
||||
if (temp_buf)
|
||||
{
|
||||
my_free(temp_buf, MYF(0));
|
||||
temp_buf = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
virtual int get_data_size() { return 0;}
|
||||
virtual int get_data_body_offset() { return 0; }
|
||||
int get_event_len() { return cached_event_len ? cached_event_len :
|
||||
(cached_event_len = LOG_EVENT_HEADER_LEN + get_data_size()); }
|
||||
|
||||
#ifdef MYSQL_CLIENT
|
||||
virtual void print(FILE* file, bool short_form = 0, char* last_db = 0) = 0;
|
||||
void print_timestamp(FILE* file, time_t *ts = 0);
|
||||
void print_header(FILE* file);
|
||||
#endif
|
||||
|
||||
#ifndef MYSQL_CLIENT
|
||||
// if mutex is 0, the read will proceed without mutex
|
||||
static Log_event* read_log_event(IO_CACHE* file,
|
||||
pthread_mutex_t* log_lock,
|
||||
bool old_format);
|
||||
#else // avoid having to link mysqlbinlog against libpthread
|
||||
static Log_event* read_log_event(IO_CACHE* file, bool old_format);
|
||||
#endif
|
||||
static Log_event* read_log_event(const char* buf, int event_len,
|
||||
const char **error, bool old_format);
|
||||
const char* get_type_str();
|
||||
|
||||
#ifndef MYSQL_CLIENT
|
||||
// if mutex is 0, the read will proceed without mutex
|
||||
Log_event(THD* thd_arg, uint16 flags_arg = 0);
|
||||
static Log_event* read_log_event(IO_CACHE* file,
|
||||
pthread_mutex_t* log_lock,
|
||||
bool old_format);
|
||||
static int read_log_event(IO_CACHE* file, String* packet,
|
||||
pthread_mutex_t* log_lock);
|
||||
void set_log_seq(THD* thd, MYSQL_LOG* log);
|
||||
void set_log_pos(MYSQL_LOG* log);
|
||||
virtual void pack_info(String* packet);
|
||||
int net_send(THD* thd, const char* log_name, my_off_t pos);
|
||||
static void init_show_field_list(List<Item>* field_list);
|
||||
virtual int exec_event(struct st_master_info* mi);
|
||||
virtual int exec_event(struct st_relay_log_info* rli);
|
||||
virtual const char* get_db()
|
||||
{
|
||||
return thd ? thd->db : 0;
|
||||
}
|
||||
#else
|
||||
// avoid having to link mysqlbinlog against libpthread
|
||||
static Log_event* read_log_event(IO_CACHE* file, bool old_format);
|
||||
|
||||
virtual void print(FILE* file, bool short_form = 0, char* last_db = 0) = 0;
|
||||
void print_timestamp(FILE* file, time_t *ts = 0);
|
||||
void print_header(FILE* file);
|
||||
#endif
|
||||
|
||||
|
||||
};
|
||||
|
||||
|
||||
|
@ -299,26 +303,21 @@ protected:
|
|||
public:
|
||||
const char* query;
|
||||
const char* db;
|
||||
/*
|
||||
If we already know the length of the query string
|
||||
we pass it here, so we would not have to call strlen()
|
||||
otherwise, set it to 0, in which case, we compute it with strlen()
|
||||
*/
|
||||
uint32 q_len;
|
||||
uint32 q_len; // if we already know the length of the query string
|
||||
// we pass it here, so we would not have to call strlen()
|
||||
// otherwise, set it to 0, in which case, we compute it with strlen()
|
||||
uint32 db_len;
|
||||
uint16 error_code;
|
||||
ulong thread_id;
|
||||
#ifndef MYSQL_CLIENT
|
||||
#if !defined(MYSQL_CLIENT)
|
||||
bool cache_stmt;
|
||||
|
||||
Query_log_event(THD* thd_arg, const char* query_arg,
|
||||
bool using_trans=0);
|
||||
const char* get_db() { return db; }
|
||||
void pack_info(String* packet);
|
||||
int exec_event(struct st_master_info* mi);
|
||||
int exec_event(struct st_relay_log_info* rli);
|
||||
bool get_cache_stmt() { return cache_stmt; }
|
||||
#else
|
||||
void print(FILE* file, bool short_form = 0, char* last_db = 0);
|
||||
#endif
|
||||
|
||||
Query_log_event(const char* buf, int event_len, bool old_format);
|
||||
|
@ -341,6 +340,9 @@ public:
|
|||
+ 2 // error_code
|
||||
;
|
||||
}
|
||||
#ifdef MYSQL_CLIENT
|
||||
void print(FILE* file, bool short_form = 0, char* last_db = 0);
|
||||
#endif
|
||||
};
|
||||
|
||||
class Slave_log_event: public Log_event
|
||||
|
@ -350,22 +352,24 @@ protected:
|
|||
void init_from_mem_pool(int data_size);
|
||||
public:
|
||||
char* master_host;
|
||||
char* master_log;
|
||||
ulonglong master_pos;
|
||||
int master_host_len;
|
||||
int master_log_len;
|
||||
uint16 master_port;
|
||||
char* master_log;
|
||||
int master_log_len;
|
||||
ulonglong master_pos;
|
||||
|
||||
#ifndef MYSQL_CLIENT
|
||||
Slave_log_event(THD* thd_arg, struct st_relay_log_info* rli);
|
||||
void pack_info(String* packet);
|
||||
int exec_event(struct st_relay_log_info* rli);
|
||||
#endif
|
||||
|
||||
Slave_log_event(const char* buf, int event_len);
|
||||
~Slave_log_event();
|
||||
int get_data_size();
|
||||
bool is_valid() { return master_host != 0; }
|
||||
Log_event_type get_type_code() { return SLAVE_EVENT; }
|
||||
#ifndef MYSQL_CLIENT
|
||||
Slave_log_event(THD* thd_arg, struct st_master_info* mi);
|
||||
void pack_info(String* packet);
|
||||
int exec_event(struct st_master_info* mi);
|
||||
#else
|
||||
#ifdef MYSQL_CLIENT
|
||||
void print(FILE* file, bool short_form = 0, char* last_db = 0);
|
||||
#endif
|
||||
int write_data(IO_CACHE* file );
|
||||
|
@ -378,37 +382,36 @@ protected:
|
|||
int copy_log_event(const char *buf, ulong event_len, bool old_format);
|
||||
|
||||
public:
|
||||
const char* fields;
|
||||
const uchar* field_lens;
|
||||
const char* table_name;
|
||||
const char* db;
|
||||
const char* fname;
|
||||
ulong thread_id;
|
||||
uint32 table_name_len;
|
||||
uint32 db_len;
|
||||
uint32 fname_len;
|
||||
uint32 num_fields;
|
||||
const char* fields;
|
||||
const uchar* field_lens;
|
||||
uint32 field_block_len;
|
||||
|
||||
const char* table_name;
|
||||
const char* db;
|
||||
const char* fname;
|
||||
uint32 skip_lines;
|
||||
sql_ex_info sql_ex;
|
||||
|
||||
#ifndef MYSQL_CLIENT
|
||||
|
||||
#if !defined(MYSQL_CLIENT)
|
||||
String field_lens_buf;
|
||||
String fields_buf;
|
||||
|
||||
|
||||
Load_log_event(THD* thd, sql_exchange* ex, const char* db_arg,
|
||||
const char* table_name_arg,
|
||||
List<Item>& fields_arg, enum enum_duplicates handle_dup);
|
||||
void set_fields(List<Item> &fields_arg);
|
||||
void pack_info(String* packet);
|
||||
const char* get_db() { return db; }
|
||||
int exec_event(struct st_master_info* mi)
|
||||
{
|
||||
return exec_event(thd->slave_net,mi);
|
||||
}
|
||||
int exec_event(NET* net, struct st_master_info* mi);
|
||||
#else
|
||||
void print(FILE* file, bool short_form = 0, char* last_db = 0);
|
||||
int exec_event(struct st_relay_log_info* rli)
|
||||
{
|
||||
return exec_event(thd->slave_net,rli);
|
||||
}
|
||||
int exec_event(NET* net, struct st_relay_log_info* rli);
|
||||
#endif
|
||||
|
||||
Load_log_event(const char* buf, int event_len, bool old_format);
|
||||
|
@ -431,6 +434,9 @@ public:
|
|||
;
|
||||
}
|
||||
int get_data_body_offset() { return LOAD_EVENT_OVERHEAD; }
|
||||
#ifdef MYSQL_CLIENT
|
||||
void print(FILE* file, bool short_form = 0, char* last_db = 0);
|
||||
#endif
|
||||
};
|
||||
|
||||
extern char server_version[SERVER_VERSION_LENGTH];
|
||||
|
@ -441,7 +447,13 @@ public:
|
|||
uint32 created;
|
||||
uint16 binlog_version;
|
||||
char server_version[ST_SERVER_VER_LEN];
|
||||
|
||||
#ifndef MYSQL_CLIENT
|
||||
Start_log_event() :Log_event((THD*)0),binlog_version(BINLOG_VERSION)
|
||||
{
|
||||
created = (uint32) when;
|
||||
memcpy(server_version, ::server_version, ST_SERVER_VER_LEN);
|
||||
}
|
||||
#endif
|
||||
Start_log_event(const char* buf, bool old_format);
|
||||
~Start_log_event() {}
|
||||
Log_event_type get_type_code() { return START_EVENT;}
|
||||
|
@ -452,14 +464,10 @@ public:
|
|||
return START_HEADER_LEN;
|
||||
}
|
||||
#ifndef MYSQL_CLIENT
|
||||
Start_log_event() :Log_event((THD*)0),binlog_version(BINLOG_VERSION)
|
||||
{
|
||||
created = (uint32) when;
|
||||
memcpy(server_version, ::server_version, ST_SERVER_VER_LEN);
|
||||
}
|
||||
void pack_info(String* packet);
|
||||
int exec_event(struct st_master_info* mi);
|
||||
#else
|
||||
int exec_event(struct st_relay_log_info* rli);
|
||||
#endif
|
||||
#ifdef MYSQL_CLIENT
|
||||
void print(FILE* file, bool short_form = 0, char* last_db = 0);
|
||||
#endif
|
||||
};
|
||||
|
@ -469,7 +477,11 @@ class Intvar_log_event: public Log_event
|
|||
public:
|
||||
ulonglong val;
|
||||
uchar type;
|
||||
|
||||
#ifndef MYSQL_CLIENT
|
||||
Intvar_log_event(THD* thd_arg,uchar type_arg, ulonglong val_arg)
|
||||
:Log_event(thd_arg),val(val_arg),type(type_arg)
|
||||
{}
|
||||
#endif
|
||||
Intvar_log_event(const char* buf, bool old_format);
|
||||
~Intvar_log_event() {}
|
||||
Log_event_type get_type_code() { return INTVAR_EVENT;}
|
||||
|
@ -478,12 +490,11 @@ public:
|
|||
int write_data(IO_CACHE* file);
|
||||
bool is_valid() { return 1; }
|
||||
#ifndef MYSQL_CLIENT
|
||||
Intvar_log_event(THD* thd_arg,uchar type_arg, ulonglong val_arg)
|
||||
:Log_event(thd_arg),val(val_arg),type(type_arg)
|
||||
{}
|
||||
void pack_info(String* packet);
|
||||
int exec_event(struct st_master_info* mi);
|
||||
#else
|
||||
int exec_event(struct st_relay_log_info* rli);
|
||||
#endif
|
||||
|
||||
#ifdef MYSQL_CLIENT
|
||||
void print(FILE* file, bool short_form = 0, char* last_db = 0);
|
||||
#endif
|
||||
};
|
||||
|
@ -491,6 +502,10 @@ public:
|
|||
class Stop_log_event: public Log_event
|
||||
{
|
||||
public:
|
||||
#ifndef MYSQL_CLIENT
|
||||
Stop_log_event() :Log_event((THD*)0)
|
||||
{}
|
||||
#endif
|
||||
Stop_log_event(const char* buf, bool old_format):Log_event(buf,
|
||||
old_format)
|
||||
{
|
||||
|
@ -498,11 +513,11 @@ public:
|
|||
~Stop_log_event() {}
|
||||
Log_event_type get_type_code() { return STOP_EVENT;}
|
||||
bool is_valid() { return 1; }
|
||||
#ifndef MYSQL_CLIENT
|
||||
Stop_log_event() :Log_event((THD*)0) {}
|
||||
int exec_event(struct st_master_info* mi);
|
||||
#else
|
||||
#ifdef MYSQL_CLIENT
|
||||
void print(FILE* file, bool short_form = 0, char* last_db = 0);
|
||||
#endif
|
||||
#ifndef MYSQL_CLIENT
|
||||
int exec_event(struct st_relay_log_info* rli);
|
||||
#endif
|
||||
};
|
||||
|
||||
|
@ -510,10 +525,19 @@ class Rotate_log_event: public Log_event
|
|||
{
|
||||
public:
|
||||
const char* new_log_ident;
|
||||
uchar ident_len;
|
||||
ulonglong pos;
|
||||
uint8 ident_len;
|
||||
bool alloced;
|
||||
|
||||
#ifndef MYSQL_CLIENT
|
||||
Rotate_log_event(THD* thd_arg, const char* new_log_ident_arg,
|
||||
uint ident_len_arg = 0,ulonglong pos_arg = 4) :
|
||||
Log_event(thd_arg),
|
||||
new_log_ident(new_log_ident_arg),
|
||||
ident_len(ident_len_arg ? ident_len_arg :
|
||||
(uint) strlen(new_log_ident_arg)), pos(pos_arg),
|
||||
alloced(0)
|
||||
{}
|
||||
#endif
|
||||
Rotate_log_event(const char* buf, int event_len, bool old_format);
|
||||
~Rotate_log_event()
|
||||
{
|
||||
|
@ -524,88 +548,77 @@ public:
|
|||
int get_data_size() { return ident_len + ROTATE_HEADER_LEN;}
|
||||
bool is_valid() { return new_log_ident != 0; }
|
||||
int write_data(IO_CACHE* file);
|
||||
#ifndef MYSQL_CLIENT
|
||||
Rotate_log_event(THD* thd_arg, const char* new_log_ident_arg,
|
||||
uint8 ident_len_arg = 0,ulonglong pos_arg = 4) :
|
||||
Log_event(thd_arg), new_log_ident(new_log_ident_arg),
|
||||
pos(pos_arg),
|
||||
ident_len(ident_len_arg ? ident_len_arg :
|
||||
(uint8) strlen(new_log_ident_arg)),
|
||||
alloced(0)
|
||||
{}
|
||||
void pack_info(String* packet);
|
||||
int exec_event(struct st_master_info* mi);
|
||||
#else
|
||||
#ifdef MYSQL_CLIENT
|
||||
void print(FILE* file, bool short_form = 0, char* last_db = 0);
|
||||
#endif
|
||||
#ifndef MYSQL_CLIENT
|
||||
void pack_info(String* packet);
|
||||
int exec_event(struct st_relay_log_info* rli);
|
||||
#endif
|
||||
};
|
||||
|
||||
|
||||
/* the classes below are for the new LOAD DATA INFILE logging */
|
||||
|
||||
class Create_file_log_event: public Load_log_event
|
||||
{
|
||||
protected:
|
||||
/*
|
||||
Pretend we are Load event, so we can write out just
|
||||
our Load part - used on the slave when writing event out to
|
||||
SQL_LOAD-*.info file
|
||||
*/
|
||||
// pretend we are Load event, so we can write out just
|
||||
// our Load part - used on the slave when writing event out to
|
||||
// SQL_LOAD-*.info file
|
||||
bool fake_base;
|
||||
public:
|
||||
char* block;
|
||||
uint block_len;
|
||||
uint file_id;
|
||||
|
||||
Create_file_log_event(const char* buf, int event_len);
|
||||
~Create_file_log_event()
|
||||
{
|
||||
}
|
||||
Log_event_type get_type_code()
|
||||
{
|
||||
return fake_base ? Load_log_event::get_type_code() : CREATE_FILE_EVENT;
|
||||
}
|
||||
int get_data_size()
|
||||
{
|
||||
return (fake_base ? Load_log_event::get_data_size() :
|
||||
Load_log_event::get_data_size() +
|
||||
4 + 1 + block_len);
|
||||
}
|
||||
int get_data_body_offset()
|
||||
{
|
||||
return (fake_base ? LOAD_EVENT_OVERHEAD:
|
||||
LOAD_EVENT_OVERHEAD + CREATE_FILE_HEADER_LEN);
|
||||
}
|
||||
bool is_valid() { return block != 0; }
|
||||
int write_data_header(IO_CACHE* file);
|
||||
int write_data_body(IO_CACHE* file);
|
||||
/*
|
||||
Cut out Create_file extentions and write it as Load event - used on the
|
||||
slave.
|
||||
*/
|
||||
int write_base(IO_CACHE* file);
|
||||
|
||||
#ifndef MYSQL_CLIENT
|
||||
Create_file_log_event(THD* thd, sql_exchange* ex, const char* db_arg,
|
||||
const char* table_name_arg,
|
||||
List<Item>& fields_arg,
|
||||
enum enum_duplicates handle_dup,
|
||||
char* block_arg, uint block_len_arg);
|
||||
void pack_info(String* packet);
|
||||
int exec_event(struct st_master_info* mi);
|
||||
#else
|
||||
#endif
|
||||
|
||||
Create_file_log_event(const char* buf, int event_len);
|
||||
~Create_file_log_event()
|
||||
{
|
||||
}
|
||||
Log_event_type get_type_code()
|
||||
{
|
||||
return fake_base ? Load_log_event::get_type_code() : CREATE_FILE_EVENT;
|
||||
}
|
||||
int get_data_size() { return fake_base ? Load_log_event::get_data_size() :
|
||||
Load_log_event::get_data_size() +
|
||||
4 + 1 + block_len;}
|
||||
int get_data_body_offset() { return fake_base ? LOAD_EVENT_OVERHEAD:
|
||||
LOAD_EVENT_OVERHEAD + CREATE_FILE_HEADER_LEN; }
|
||||
bool is_valid() { return block != 0; }
|
||||
int write_data_header(IO_CACHE* file);
|
||||
int write_data_body(IO_CACHE* file);
|
||||
int write_base(IO_CACHE* file); // cut out Create_file extentions and
|
||||
// write it as Load event - used on the slave
|
||||
|
||||
#ifdef MYSQL_CLIENT
|
||||
void print(FILE* file, bool short_form = 0, char* last_db = 0);
|
||||
#endif
|
||||
#ifndef MYSQL_CLIENT
|
||||
void pack_info(String* packet);
|
||||
int exec_event(struct st_relay_log_info* rli);
|
||||
#endif
|
||||
};
|
||||
|
||||
|
||||
class Append_block_log_event: public Log_event
|
||||
{
|
||||
public:
|
||||
char* block;
|
||||
uint block_len;
|
||||
uint file_id;
|
||||
|
||||
|
||||
#ifndef MYSQL_CLIENT
|
||||
Append_block_log_event(THD* thd, char* block_arg,
|
||||
uint block_len_arg);
|
||||
int exec_event(struct st_relay_log_info* rli);
|
||||
#endif
|
||||
|
||||
Append_block_log_event(const char* buf, int event_len);
|
||||
~Append_block_log_event()
|
||||
{
|
||||
|
@ -615,22 +628,23 @@ public:
|
|||
bool is_valid() { return block != 0; }
|
||||
int write_data(IO_CACHE* file);
|
||||
|
||||
#ifndef MYSQL_CLIENT
|
||||
Append_block_log_event(THD* thd, char* block_arg,
|
||||
uint block_len_arg);
|
||||
int exec_event(struct st_master_info* mi);
|
||||
void pack_info(String* packet);
|
||||
#else
|
||||
#ifdef MYSQL_CLIENT
|
||||
void print(FILE* file, bool short_form = 0, char* last_db = 0);
|
||||
#endif
|
||||
#ifndef MYSQL_CLIENT
|
||||
void pack_info(String* packet);
|
||||
#endif
|
||||
};
|
||||
|
||||
|
||||
class Delete_file_log_event: public Log_event
|
||||
{
|
||||
public:
|
||||
uint file_id;
|
||||
|
||||
|
||||
#ifndef MYSQL_CLIENT
|
||||
Delete_file_log_event(THD* thd);
|
||||
#endif
|
||||
|
||||
Delete_file_log_event(const char* buf, int event_len);
|
||||
~Delete_file_log_event()
|
||||
{
|
||||
|
@ -640,20 +654,24 @@ public:
|
|||
bool is_valid() { return file_id != 0; }
|
||||
int write_data(IO_CACHE* file);
|
||||
|
||||
#ifndef MYSQL_CLIENT
|
||||
Delete_file_log_event(THD* thd);
|
||||
void pack_info(String* packet);
|
||||
int exec_event(struct st_master_info* mi);
|
||||
#else
|
||||
#ifdef MYSQL_CLIENT
|
||||
void print(FILE* file, bool short_form = 0, char* last_db = 0);
|
||||
#endif
|
||||
#ifndef MYSQL_CLIENT
|
||||
void pack_info(String* packet);
|
||||
int exec_event(struct st_relay_log_info* rli);
|
||||
#endif
|
||||
};
|
||||
|
||||
class Execute_load_log_event: public Log_event
|
||||
{
|
||||
public:
|
||||
uint file_id;
|
||||
|
||||
|
||||
#ifndef MYSQL_CLIENT
|
||||
Execute_load_log_event(THD* thd);
|
||||
#endif
|
||||
|
||||
Execute_load_log_event(const char* buf, int event_len);
|
||||
~Execute_load_log_event()
|
||||
{
|
||||
|
@ -663,13 +681,16 @@ public:
|
|||
bool is_valid() { return file_id != 0; }
|
||||
int write_data(IO_CACHE* file);
|
||||
|
||||
#ifndef MYSQL_CLIENT
|
||||
Execute_load_log_event(THD* thd);
|
||||
void pack_info(String* packet);
|
||||
int exec_event(struct st_master_info* mi);
|
||||
#else
|
||||
#ifdef MYSQL_CLIENT
|
||||
void print(FILE* file, bool short_form = 0, char* last_db = 0);
|
||||
#endif
|
||||
#ifndef MYSQL_CLIENT
|
||||
void pack_info(String* packet);
|
||||
int exec_event(struct st_relay_log_info* rli);
|
||||
#endif
|
||||
};
|
||||
|
||||
#endif /* _LOG_EVENT_H */
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
|
|
|
@ -89,7 +89,7 @@ static MYSQL_FIELD *unpack_fields(MYSQL_DATA *data,MEM_ROOT *alloc,uint fields,
|
|||
my_bool default_value,
|
||||
my_bool long_flag_protocol);
|
||||
|
||||
static void mc_end_server(MYSQL *mysql);
|
||||
void mc_end_server(MYSQL *mysql);
|
||||
static int mc_sock_connect(File s, const struct sockaddr *name, uint namelen, uint to);
|
||||
static void mc_free_old_query(MYSQL *mysql);
|
||||
static int mc_send_file_to_server(MYSQL *mysql, const char *filename);
|
||||
|
@ -194,8 +194,7 @@ HANDLE create_named_pipe(NET *net, uint connect_timeout, char **arg_host,
|
|||
** Init MySQL structure or allocate one
|
||||
****************************************************************************/
|
||||
|
||||
MYSQL * STDCALL
|
||||
mc_mysql_init(MYSQL *mysql)
|
||||
MYSQL *mc_mysql_init(MYSQL *mysql)
|
||||
{
|
||||
init_client_errs();
|
||||
if (!mysql)
|
||||
|
@ -217,7 +216,7 @@ mc_mysql_init(MYSQL *mysql)
|
|||
** Shut down connection
|
||||
**************************************************************************/
|
||||
|
||||
static void
|
||||
void
|
||||
mc_end_server(MYSQL *mysql)
|
||||
{
|
||||
DBUG_ENTER("mc_end_server");
|
||||
|
@ -339,7 +338,7 @@ static int mc_sock_connect(my_socket s, const struct sockaddr *name,
|
|||
** or packet is an error message
|
||||
*****************************************************************************/
|
||||
|
||||
ulong STDCALL
|
||||
ulong
|
||||
mc_net_safe_read(MYSQL *mysql)
|
||||
{
|
||||
NET *net= &mysql->net;
|
||||
|
@ -400,17 +399,17 @@ max_allowed_packet on this server");
|
|||
}
|
||||
|
||||
|
||||
char * STDCALL mc_mysql_error(MYSQL *mysql)
|
||||
char * mc_mysql_error(MYSQL *mysql)
|
||||
{
|
||||
return (mysql)->net.last_error;
|
||||
}
|
||||
|
||||
int STDCALL mc_mysql_errno(MYSQL *mysql)
|
||||
int mc_mysql_errno(MYSQL *mysql)
|
||||
{
|
||||
return (mysql)->net.last_errno;
|
||||
}
|
||||
|
||||
my_bool STDCALL mc_mysql_reconnect(MYSQL *mysql)
|
||||
my_bool mc_mysql_reconnect(MYSQL *mysql)
|
||||
{
|
||||
MYSQL tmp_mysql;
|
||||
DBUG_ENTER("mc_mysql_reconnect");
|
||||
|
@ -440,7 +439,7 @@ my_bool STDCALL mc_mysql_reconnect(MYSQL *mysql)
|
|||
|
||||
|
||||
|
||||
int STDCALL
|
||||
int
|
||||
mc_simple_command(MYSQL *mysql,enum enum_server_command command,
|
||||
const char *arg, uint length, my_bool skipp_check)
|
||||
{
|
||||
|
@ -493,7 +492,7 @@ mc_simple_command(MYSQL *mysql,enum enum_server_command command,
|
|||
}
|
||||
|
||||
|
||||
MYSQL * STDCALL
|
||||
MYSQL *
|
||||
mc_mysql_connect(MYSQL *mysql,const char *host, const char *user,
|
||||
const char *passwd, const char *db,
|
||||
uint port, const char *unix_socket,uint client_flag)
|
||||
|
@ -844,7 +843,7 @@ error:
|
|||
** NB! Errors are not reported until you do mysql_real_connect.
|
||||
**************************************************************************
|
||||
*/
|
||||
int STDCALL
|
||||
int
|
||||
mysql_ssl_clear(MYSQL *mysql)
|
||||
{
|
||||
my_free(mysql->options.ssl_key, MYF(MY_ALLOW_ZERO_PTR));
|
||||
|
@ -867,7 +866,7 @@ mysql_ssl_clear(MYSQL *mysql)
|
|||
** If handle is alloced by mysql connect free it.
|
||||
*************************************************************************/
|
||||
|
||||
void STDCALL
|
||||
void
|
||||
mc_mysql_close(MYSQL *mysql)
|
||||
{
|
||||
DBUG_ENTER("mysql_close");
|
||||
|
@ -898,7 +897,7 @@ mc_mysql_close(MYSQL *mysql)
|
|||
DBUG_VOID_RETURN;
|
||||
}
|
||||
|
||||
void STDCALL mc_mysql_free_result(MYSQL_RES *result)
|
||||
void mc_mysql_free_result(MYSQL_RES *result)
|
||||
{
|
||||
DBUG_ENTER("mc_mysql_free_result");
|
||||
DBUG_PRINT("enter",("mysql_res: %lx",result));
|
||||
|
@ -976,13 +975,13 @@ mc_unpack_fields(MYSQL_DATA *data,MEM_ROOT *alloc,uint fields,
|
|||
DBUG_RETURN(result);
|
||||
}
|
||||
|
||||
int STDCALL
|
||||
int
|
||||
mc_mysql_send_query(MYSQL* mysql, const char* query, uint length)
|
||||
{
|
||||
return mc_simple_command(mysql, COM_QUERY, query, length, 1);
|
||||
}
|
||||
|
||||
int STDCALL mc_mysql_read_query_result(MYSQL *mysql)
|
||||
int mc_mysql_read_query_result(MYSQL *mysql)
|
||||
{
|
||||
uchar *pos;
|
||||
ulong field_count;
|
||||
|
@ -1030,7 +1029,7 @@ get_info:
|
|||
DBUG_RETURN(0);
|
||||
}
|
||||
|
||||
int STDCALL mc_mysql_query(MYSQL *mysql, const char *query, uint length)
|
||||
int mc_mysql_query(MYSQL *mysql, const char *query, uint length)
|
||||
{
|
||||
DBUG_ENTER("mysql_real_query");
|
||||
DBUG_PRINT("enter",("handle: %lx",mysql));
|
||||
|
@ -1281,17 +1280,17 @@ static int mc_read_one_row(MYSQL *mysql,uint fields,MYSQL_ROW row,
|
|||
return 0;
|
||||
}
|
||||
|
||||
my_ulonglong STDCALL mc_mysql_num_rows(MYSQL_RES *res)
|
||||
my_ulonglong mc_mysql_num_rows(MYSQL_RES *res)
|
||||
{
|
||||
return res->row_count;
|
||||
}
|
||||
|
||||
unsigned int STDCALL mc_mysql_num_fields(MYSQL_RES *res)
|
||||
unsigned int mc_mysql_num_fields(MYSQL_RES *res)
|
||||
{
|
||||
return res->field_count;
|
||||
}
|
||||
|
||||
void STDCALL mc_mysql_data_seek(MYSQL_RES *result, my_ulonglong row)
|
||||
void mc_mysql_data_seek(MYSQL_RES *result, my_ulonglong row)
|
||||
{
|
||||
MYSQL_ROWS *tmp=0;
|
||||
DBUG_PRINT("info",("mysql_data_seek(%ld)",(long) row));
|
||||
|
@ -1301,7 +1300,7 @@ void STDCALL mc_mysql_data_seek(MYSQL_RES *result, my_ulonglong row)
|
|||
result->data_cursor = tmp;
|
||||
}
|
||||
|
||||
MYSQL_ROW STDCALL mc_mysql_fetch_row(MYSQL_RES *res)
|
||||
MYSQL_ROW mc_mysql_fetch_row(MYSQL_RES *res)
|
||||
{
|
||||
DBUG_ENTER("mc_mysql_fetch_row");
|
||||
if (!res->data)
|
||||
|
@ -1336,7 +1335,7 @@ MYSQL_ROW STDCALL mc_mysql_fetch_row(MYSQL_RES *res)
|
|||
}
|
||||
}
|
||||
|
||||
int STDCALL mc_mysql_select_db(MYSQL *mysql, const char *db)
|
||||
int mc_mysql_select_db(MYSQL *mysql, const char *db)
|
||||
{
|
||||
int error;
|
||||
DBUG_ENTER("mysql_select_db");
|
||||
|
@ -1350,7 +1349,7 @@ int STDCALL mc_mysql_select_db(MYSQL *mysql, const char *db)
|
|||
}
|
||||
|
||||
|
||||
MYSQL_RES * STDCALL mc_mysql_store_result(MYSQL *mysql)
|
||||
MYSQL_RES *mc_mysql_store_result(MYSQL *mysql)
|
||||
{
|
||||
MYSQL_RES *result;
|
||||
DBUG_ENTER("mysql_store_result");
|
||||
|
|
|
@ -18,40 +18,34 @@
|
|||
#define _MINI_CLIENT_H
|
||||
|
||||
|
||||
MYSQL* STDCALL
|
||||
mc_mysql_connect(MYSQL *mysql,const char *host, const char *user,
|
||||
MYSQL* mc_mysql_connect(MYSQL *mysql,const char *host, const char *user,
|
||||
const char *passwd, const char *db,
|
||||
uint port, const char *unix_socket,uint client_flag);
|
||||
|
||||
int STDCALL
|
||||
mc_simple_command(MYSQL *mysql,enum enum_server_command command, const char *arg,
|
||||
int mc_simple_command(MYSQL *mysql,enum enum_server_command command, const char *arg,
|
||||
uint length, my_bool skipp_check);
|
||||
void STDCALL
|
||||
mc_mysql_close(MYSQL *mysql);
|
||||
void mc_mysql_close(MYSQL *mysql);
|
||||
|
||||
MYSQL * STDCALL
|
||||
mc_mysql_init(MYSQL *mysql);
|
||||
MYSQL * mc_mysql_init(MYSQL *mysql);
|
||||
|
||||
void STDCALL
|
||||
mc_mysql_debug(const char *debug);
|
||||
void mc_mysql_debug(const char *debug);
|
||||
|
||||
ulong STDCALL
|
||||
mc_net_safe_read(MYSQL *mysql);
|
||||
ulong mc_net_safe_read(MYSQL *mysql);
|
||||
|
||||
char * STDCALL mc_mysql_error(MYSQL *mysql);
|
||||
int STDCALL mc_mysql_errno(MYSQL *mysql);
|
||||
my_bool STDCALL mc_mysql_reconnect(MYSQL* mysql);
|
||||
char * mc_mysql_error(MYSQL *mysql);
|
||||
int mc_mysql_errno(MYSQL *mysql);
|
||||
my_bool mc_mysql_reconnect(MYSQL* mysql);
|
||||
|
||||
int STDCALL mc_mysql_send_query(MYSQL* mysql, const char* query, uint length);
|
||||
int STDCALL mc_mysql_read_query_result(MYSQL *mysql);
|
||||
int STDCALL mc_mysql_query(MYSQL *mysql, const char *query, uint length);
|
||||
MYSQL_RES * STDCALL mc_mysql_store_result(MYSQL *mysql);
|
||||
void STDCALL mc_mysql_free_result(MYSQL_RES *result);
|
||||
void STDCALL mc_mysql_data_seek(MYSQL_RES *result, my_ulonglong row);
|
||||
my_ulonglong STDCALL mc_mysql_num_rows(MYSQL_RES *res);
|
||||
unsigned int STDCALL mc_mysql_num_fields(MYSQL_RES *res);
|
||||
int mc_mysql_send_query(MYSQL* mysql, const char* query, uint length);
|
||||
int mc_mysql_read_query_result(MYSQL *mysql);
|
||||
int mc_mysql_query(MYSQL *mysql, const char *query, uint length);
|
||||
MYSQL_RES * mc_mysql_store_result(MYSQL *mysql);
|
||||
void mc_mysql_free_result(MYSQL_RES *result);
|
||||
void mc_mysql_data_seek(MYSQL_RES *result, my_ulonglong row);
|
||||
my_ulonglong mc_mysql_num_rows(MYSQL_RES *res);
|
||||
unsigned int mc_mysql_num_fields(MYSQL_RES *res);
|
||||
MYSQL_ROW STDCALL mc_mysql_fetch_row(MYSQL_RES *res);
|
||||
int STDCALL mc_mysql_select_db(MYSQL *mysql, const char *db);
|
||||
|
||||
int mc_mysql_select_db(MYSQL *mysql, const char *db);
|
||||
void mc_end_server(MYSQL *mysql);
|
||||
|
||||
#endif
|
||||
|
|
|
@ -540,6 +540,10 @@ void sql_print_error(const char *format,...)
|
|||
__attribute__ ((format (printf, 1, 2)));
|
||||
bool fn_format_relative_to_data_home(my_string to, const char *name,
|
||||
const char *dir, const char *extension);
|
||||
void open_log(MYSQL_LOG *log, const char *hostname,
|
||||
const char *opt_name, const char *extension,
|
||||
enum_log_type type, bool read_append = 0,
|
||||
bool no_auto_events = 0);
|
||||
|
||||
extern uint32 server_id;
|
||||
extern char *mysql_data_home,server_version[SERVER_VERSION_LENGTH],
|
||||
|
@ -572,9 +576,8 @@ extern pthread_mutex_t LOCK_mysql_create_db,LOCK_Acl,LOCK_open,
|
|||
LOCK_thread_count,LOCK_mapped_file,LOCK_user_locks, LOCK_status,
|
||||
LOCK_grant, LOCK_error_log, LOCK_delayed_insert,
|
||||
LOCK_delayed_status, LOCK_delayed_create, LOCK_crypt, LOCK_timezone,
|
||||
LOCK_binlog_update, LOCK_slave, LOCK_server_id, LOCK_slave_list;
|
||||
extern pthread_cond_t COND_refresh,COND_thread_count, COND_binlog_update,
|
||||
COND_slave_stopped, COND_slave_start;
|
||||
LOCK_server_id, LOCK_slave_list, LOCK_active_mi;
|
||||
extern pthread_cond_t COND_refresh,COND_thread_count;
|
||||
extern pthread_attr_t connection_attrib;
|
||||
extern bool opt_endinfo, using_udf_functions, locked_in_memory,
|
||||
opt_using_transactions, use_temp_pool, mysql_embedded;
|
||||
|
@ -611,6 +614,7 @@ extern struct show_var_st init_vars[];
|
|||
extern struct show_var_st status_vars[];
|
||||
extern enum db_type default_table_type;
|
||||
extern enum enum_tx_isolation default_tx_isolation;
|
||||
extern char glob_hostname[FN_REFLEN];
|
||||
|
||||
#ifndef __WIN__
|
||||
extern pthread_t signal_thread;
|
||||
|
|
|
@ -211,7 +211,7 @@ SHOW_COMP_OPTION have_openssl=SHOW_OPTION_NO;
|
|||
SHOW_COMP_OPTION have_symlink=SHOW_OPTION_YES;
|
||||
|
||||
|
||||
static bool opt_skip_slave_start = 0; // If set, slave is not autostarted
|
||||
bool opt_skip_slave_start = 0; // If set, slave is not autostarted
|
||||
static bool opt_do_pstack = 0;
|
||||
static ulong opt_specialflag=SPECIAL_ENGLISH;
|
||||
static ulong back_log,connect_timeout,concurrency;
|
||||
|
@ -231,8 +231,6 @@ bool opt_sql_bin_update = 0, opt_log_slave_updates = 0, opt_safe_show_db=0,
|
|||
volatile bool mqh_used = 0;
|
||||
FILE *bootstrap_file=0;
|
||||
int segfaulted = 0; // ensure we do not enter SIGSEGV handler twice
|
||||
extern MASTER_INFO glob_mi;
|
||||
extern int init_master_info(MASTER_INFO* mi);
|
||||
|
||||
/*
|
||||
If sql_bin_update is true, SQL_LOG_UPDATE and SQL_LOG_BIN are kept in sync,
|
||||
|
@ -244,7 +242,7 @@ static struct rand_struct sql_rand;
|
|||
static int cleanup_done;
|
||||
static char **defaults_argv,time_zone[30];
|
||||
static const char *default_table_type_name;
|
||||
static char glob_hostname[FN_REFLEN];
|
||||
char glob_hostname[FN_REFLEN];
|
||||
|
||||
#include "sslopt-vars.h"
|
||||
#ifdef HAVE_OPENSSL
|
||||
|
@ -283,9 +281,11 @@ volatile ulong cached_thread_count=0;
|
|||
|
||||
// replication parameters, if master_host is not NULL, we are a slave
|
||||
my_string master_user = (char*) "test", master_password = 0, master_host=0,
|
||||
master_info_file = (char*) "master.info", master_ssl_key=0, master_ssl_cert=0;
|
||||
master_info_file = (char*) "master.info",
|
||||
relay_log_info_file = (char*) "relay-log.info",
|
||||
master_ssl_key=0, master_ssl_cert=0;
|
||||
my_string report_user = 0, report_password = 0, report_host=0;
|
||||
|
||||
|
||||
const char *localhost=LOCAL_HOST;
|
||||
const char *delayed_user="DELAYED";
|
||||
uint master_port = MYSQL_PORT, master_connect_retry = 60;
|
||||
|
@ -315,7 +315,7 @@ ulong max_connections,max_insert_delayed_threads,max_used_connections,
|
|||
ulong thread_id=1L,current_pid;
|
||||
ulong slow_launch_threads = 0;
|
||||
ulong myisam_max_sort_file_size, myisam_max_extra_sort_file_size;
|
||||
|
||||
|
||||
char mysql_real_data_home[FN_REFLEN],
|
||||
language[LIBLEN],reg_ext[FN_EXTLEN],
|
||||
default_charset[LIBLEN],mysql_charsets_dir[FN_REFLEN], *charsets_list,
|
||||
|
@ -330,6 +330,7 @@ bool mysql_embedded=1;
|
|||
#endif
|
||||
|
||||
char *opt_bin_logname = 0; // this one needs to be seen in sql_parse.cc
|
||||
char *opt_relay_logname = 0, *opt_relaylog_index_name=0;
|
||||
char server_version[SERVER_VERSION_LENGTH]=MYSQL_SERVER_VERSION;
|
||||
const char *first_keyword="first";
|
||||
const char **errmesg; /* Error messages */
|
||||
|
@ -365,8 +366,8 @@ pthread_mutex_t LOCK_mysql_create_db, LOCK_Acl, LOCK_open, LOCK_thread_count,
|
|||
LOCK_error_log,
|
||||
LOCK_delayed_insert, LOCK_delayed_status, LOCK_delayed_create,
|
||||
LOCK_crypt, LOCK_bytes_sent, LOCK_bytes_received,
|
||||
LOCK_binlog_update, LOCK_slave, LOCK_server_id,
|
||||
LOCK_user_conn, LOCK_slave_list;
|
||||
LOCK_server_id,
|
||||
LOCK_user_conn, LOCK_slave_list, LOCK_active_mi;
|
||||
|
||||
Query_cache query_cache;
|
||||
|
||||
|
@ -776,6 +777,7 @@ void clean_up(bool print_message)
|
|||
my_free(allocated_mysql_tmpdir,MYF(MY_ALLOW_ZERO_PTR));
|
||||
my_free(slave_load_tmpdir,MYF(MY_ALLOW_ZERO_PTR));
|
||||
x_free(opt_bin_logname);
|
||||
x_free(opt_relay_logname);
|
||||
bitmap_free(&temp_pool);
|
||||
free_max_user_conn();
|
||||
end_slave_list();
|
||||
|
@ -1112,6 +1114,8 @@ void end_thread(THD *thd, bool put_in_cache)
|
|||
DBUG_PRINT("info", ("sending a broadcast"))
|
||||
|
||||
/* Tell main we are ready */
|
||||
// TODO: explain why we broadcast outside of the lock or
|
||||
// fix the bug - Sasha
|
||||
(void) pthread_mutex_unlock(&LOCK_thread_count);
|
||||
(void) pthread_cond_broadcast(&COND_thread_count);
|
||||
DBUG_PRINT("info", ("unlocked thread_count mutex"))
|
||||
|
@ -1244,7 +1248,7 @@ static sig_handler handle_segfault(int sig)
|
|||
fprintf(stderr, "Fatal signal %d while backtracing\n", sig);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
|
||||
segfaulted = 1;
|
||||
fprintf(stderr,"\
|
||||
mysqld got signal %d;\n\
|
||||
|
@ -1267,7 +1271,7 @@ key_buffer_size + (record_buffer + sort_buffer)*max_connections = %ld K\n\
|
|||
bytes of memory\n", (keybuff_size + (my_default_record_cache_size +
|
||||
sortbuff_size) * max_connections)/ 1024);
|
||||
fprintf(stderr, "Hope that's ok; if not, decrease some variables in the equation.\n\n");
|
||||
|
||||
|
||||
#if defined(HAVE_LINUXTHREADS)
|
||||
if (sizeof(char*) == 4 && thread_count > UNSAFE_DEFAULT_LINUX_THREADS)
|
||||
{
|
||||
|
@ -1283,6 +1287,7 @@ the thread stack. Please read http://www.mysql.com/doc/L/i/Linux.html\n\n",
|
|||
#ifdef HAVE_STACKTRACE
|
||||
if(!(test_flags & TEST_NO_STACKTRACE))
|
||||
{
|
||||
fprintf(stderr,"thd=%p\n",thd);
|
||||
print_stacktrace(thd ? (gptr) thd->thread_stack : (gptr) 0,
|
||||
thread_stack);
|
||||
}
|
||||
|
@ -1612,9 +1617,10 @@ const char *load_default_groups[]= { "mysqld","server",0 };
|
|||
char *libwrapName=NULL;
|
||||
#endif
|
||||
|
||||
static void open_log(MYSQL_LOG *log, const char *hostname,
|
||||
void open_log(MYSQL_LOG *log, const char *hostname,
|
||||
const char *opt_name, const char *extension,
|
||||
enum_log_type type)
|
||||
enum_log_type type, bool read_append,
|
||||
bool no_auto_events)
|
||||
{
|
||||
char tmp[FN_REFLEN];
|
||||
if (!opt_name || !opt_name[0])
|
||||
|
@ -1638,7 +1644,8 @@ static void open_log(MYSQL_LOG *log, const char *hostname,
|
|||
opt_name=tmp;
|
||||
}
|
||||
}
|
||||
log->open(opt_name,type);
|
||||
log->open(opt_name,type,0,(read_append) ? SEQ_READ_APPEND : WRITE_CACHE,
|
||||
no_auto_events);
|
||||
}
|
||||
|
||||
|
||||
|
@ -1734,19 +1741,15 @@ int main(int argc, char **argv)
|
|||
(void) pthread_mutex_init(&LOCK_bytes_sent,MY_MUTEX_INIT_FAST);
|
||||
(void) pthread_mutex_init(&LOCK_bytes_received,MY_MUTEX_INIT_FAST);
|
||||
(void) pthread_mutex_init(&LOCK_timezone,MY_MUTEX_INIT_FAST);
|
||||
(void) pthread_mutex_init(&LOCK_binlog_update, MY_MUTEX_INIT_FAST); // QQ NOT USED
|
||||
(void) pthread_mutex_init(&LOCK_slave, MY_MUTEX_INIT_FAST);
|
||||
(void) pthread_mutex_init(&LOCK_server_id, MY_MUTEX_INIT_FAST);
|
||||
(void) pthread_mutex_init(&LOCK_user_conn, MY_MUTEX_INIT_FAST);
|
||||
(void) pthread_mutex_init(&LOCK_rpl_status, MY_MUTEX_INIT_FAST);
|
||||
(void) pthread_mutex_init(&LOCK_active_mi, MY_MUTEX_INIT_FAST);
|
||||
(void) pthread_cond_init(&COND_thread_count,NULL);
|
||||
(void) pthread_cond_init(&COND_refresh,NULL);
|
||||
(void) pthread_cond_init(&COND_thread_cache,NULL);
|
||||
(void) pthread_cond_init(&COND_flush_thread_cache,NULL);
|
||||
(void) pthread_cond_init(&COND_manager,NULL);
|
||||
(void) pthread_cond_init(&COND_binlog_update, NULL);
|
||||
(void) pthread_cond_init(&COND_slave_stopped, NULL);
|
||||
(void) pthread_cond_init(&COND_slave_start, NULL);
|
||||
(void) pthread_cond_init(&COND_rpl_status, NULL);
|
||||
init_signals();
|
||||
|
||||
|
@ -1846,20 +1849,9 @@ int main(int argc, char **argv)
|
|||
LOG_NEW);
|
||||
using_update_log=1;
|
||||
}
|
||||
|
||||
/*
|
||||
make sure slave thread gets started if server_id is set,
|
||||
valid master.info is present, and master_host has not been specified
|
||||
*/
|
||||
if (server_id && !master_host)
|
||||
{
|
||||
char fname[FN_REFLEN+128];
|
||||
MY_STAT stat_area;
|
||||
fn_format(fname, master_info_file, mysql_data_home, "", 4+16+32);
|
||||
if (my_stat(fname, &stat_area, MYF(0)) && !init_master_info(&glob_mi))
|
||||
master_host = glob_mi.host;
|
||||
}
|
||||
|
||||
|
||||
init_slave();
|
||||
|
||||
if (opt_bin_log && !server_id)
|
||||
{
|
||||
server_id= !master_host ? 1 : 2;
|
||||
|
@ -2012,17 +2004,6 @@ The server will not act as a slave.");
|
|||
sql_print_error("Warning: Can't create thread to manage maintenance");
|
||||
}
|
||||
|
||||
// slave thread
|
||||
if (master_host)
|
||||
{
|
||||
pthread_t hThread;
|
||||
if (!opt_skip_slave_start &&
|
||||
pthread_create(&hThread, &connection_attrib, handle_slave, 0))
|
||||
sql_print_error("Warning: Can't create thread to handle slave");
|
||||
else if(opt_skip_slave_start)
|
||||
init_master_info(&glob_mi);
|
||||
}
|
||||
|
||||
printf(ER(ER_READY),my_progname,server_version,"");
|
||||
fflush(stdout);
|
||||
|
||||
|
@ -2693,7 +2674,8 @@ enum options {
|
|||
OPT_SHOW_SLAVE_AUTH_INFO, OPT_OLD_RPL_COMPAT,
|
||||
OPT_SLAVE_LOAD_TMPDIR, OPT_NO_MIX_TYPE,
|
||||
OPT_RPL_RECOVERY_RANK,OPT_INIT_RPL_ROLE,
|
||||
OPT_DES_KEY_FILE, OPT_SLAVE_SKIP_ERRORS
|
||||
OPT_RELAY_LOG, OPT_RELAY_LOG_INDEX, OPT_RELAY_LOG_INFO_FILE,
|
||||
OPT_SLAVE_SKIP_ERRORS, OPT_DES_KEY_FILE
|
||||
};
|
||||
|
||||
static struct option long_options[] = {
|
||||
|
@ -2819,6 +2801,8 @@ static struct option long_options[] = {
|
|||
{"report-password", required_argument, 0, (int) OPT_REPORT_PASSWORD},
|
||||
{"report-port", required_argument, 0, (int) OPT_REPORT_PORT},
|
||||
{"rpl-recovery-rank", required_argument, 0, (int) OPT_RPL_RECOVERY_RANK},
|
||||
{"relay-log", required_argument, 0, (int) OPT_RELAY_LOG},
|
||||
{"relay-log-index", required_argument, 0, (int) OPT_RELAY_LOG_INDEX},
|
||||
{"safe-mode", no_argument, 0, (int) OPT_SAFE},
|
||||
{"safe-show-database", no_argument, 0, (int) OPT_SAFE_SHOW_DB},
|
||||
{"safe-user-create", no_argument, 0, (int) OPT_SAFE_USER_CREATE},
|
||||
|
@ -2842,6 +2826,8 @@ static struct option long_options[] = {
|
|||
{"skip-stack-trace", no_argument, 0, (int) OPT_SKIP_STACK_TRACE},
|
||||
{"skip-symlink", no_argument, 0, (int) OPT_SKIP_SYMLINKS},
|
||||
{"skip-thread-priority", no_argument, 0, (int) OPT_SKIP_PRIOR},
|
||||
{"relay-log-info-file", required_argument, 0,
|
||||
(int) OPT_RELAY_LOG_INFO_FILE},
|
||||
{"slave-load-tmpdir", required_argument, 0, (int) OPT_SLAVE_LOAD_TMPDIR},
|
||||
{"slave-skip-errors", required_argument, 0,
|
||||
(int) OPT_SLAVE_SKIP_ERRORS},
|
||||
|
@ -3265,8 +3251,8 @@ struct show_var_st status_vars[]= {
|
|||
{"Select_range", (char*) &select_range_count, SHOW_LONG},
|
||||
{"Select_range_check", (char*) &select_range_check_count, SHOW_LONG},
|
||||
{"Select_scan", (char*) &select_scan_count, SHOW_LONG},
|
||||
{"Slave_running", (char*) &slave_running, SHOW_BOOL},
|
||||
{"Slave_open_temp_tables", (char*) &slave_open_temp_tables, SHOW_LONG},
|
||||
{"Slave_running", (char*) 0, SHOW_SLAVE_RUNNING},
|
||||
{"Slow_launch_threads", (char*) &slow_launch_threads, SHOW_LONG},
|
||||
{"Slow_queries", (char*) &long_query_count, SHOW_LONG},
|
||||
{"Sort_merge_passes", (char*) &filesort_merge_passes, SHOW_LONG},
|
||||
|
@ -3678,6 +3664,14 @@ static void get_options(int argc,char **argv)
|
|||
opt_update_log=1;
|
||||
opt_update_logname=optarg; // Use hostname.# if null
|
||||
break;
|
||||
case (int) OPT_RELAY_LOG_INDEX:
|
||||
opt_relaylog_index_name = optarg;
|
||||
break;
|
||||
case (int) OPT_RELAY_LOG:
|
||||
x_free(opt_relay_logname);
|
||||
if (optarg && optarg[0])
|
||||
opt_relay_logname=my_strdup(optarg,MYF(0));
|
||||
break;
|
||||
case (int) OPT_BIN_LOG_INDEX:
|
||||
opt_binlog_index_name = optarg;
|
||||
break;
|
||||
|
@ -3838,7 +3832,7 @@ static void get_options(int argc,char **argv)
|
|||
opt_slow_log=1;
|
||||
opt_slow_logname=optarg;
|
||||
break;
|
||||
case (int) OPT_SKIP_SLAVE_START:
|
||||
case (int)OPT_SKIP_SLAVE_START:
|
||||
opt_skip_slave_start = 1;
|
||||
break;
|
||||
case (int) OPT_SKIP_NEW:
|
||||
|
@ -4143,6 +4137,9 @@ static void get_options(int argc,char **argv)
|
|||
case OPT_MASTER_INFO_FILE:
|
||||
master_info_file=optarg;
|
||||
break;
|
||||
case OPT_RELAY_LOG_INFO_FILE:
|
||||
relay_log_info_file=optarg;
|
||||
break;
|
||||
case OPT_MASTER_PORT:
|
||||
master_port= atoi(optarg);
|
||||
break;
|
||||
|
|
|
@ -201,7 +201,7 @@ void end_slave_list()
|
|||
|
||||
static int find_target_pos(LEX_MASTER_INFO* mi, IO_CACHE* log, char* errmsg)
|
||||
{
|
||||
uint32 log_seq = mi->last_log_seq;
|
||||
uint32 log_pos = mi->pos;
|
||||
uint32 target_server_id = mi->server_id;
|
||||
|
||||
for (;;)
|
||||
|
@ -219,7 +219,7 @@ static int find_target_pos(LEX_MASTER_INFO* mi, IO_CACHE* log, char* errmsg)
|
|||
return 1;
|
||||
}
|
||||
|
||||
if (ev->log_seq == log_seq && ev->server_id == target_server_id)
|
||||
if (ev->log_pos == log_pos && ev->server_id == target_server_id)
|
||||
{
|
||||
delete ev;
|
||||
mi->pos = my_b_tell(log);
|
||||
|
@ -529,7 +529,7 @@ pthread_handler_decl(handle_failsafe_rpl,arg)
|
|||
const char* msg = thd->enter_cond(&COND_rpl_status,
|
||||
&LOCK_rpl_status, "Waiting for request");
|
||||
pthread_cond_wait(&COND_rpl_status, &LOCK_rpl_status);
|
||||
thd->proc_info="Processling request";
|
||||
thd->proc_info="Processing request";
|
||||
while (!break_req_chain)
|
||||
{
|
||||
switch (rpl_status)
|
||||
|
@ -632,10 +632,9 @@ static inline void cleanup_mysql_results(MYSQL_RES* db_res,
|
|||
|
||||
|
||||
static inline int fetch_db_tables(THD* thd, MYSQL* mysql, const char* db,
|
||||
MYSQL_RES* table_res)
|
||||
MYSQL_RES* table_res, MASTER_INFO* mi)
|
||||
{
|
||||
MYSQL_ROW row;
|
||||
|
||||
for( row = mc_mysql_fetch_row(table_res); row;
|
||||
row = mc_mysql_fetch_row(table_res))
|
||||
{
|
||||
|
@ -651,11 +650,9 @@ static inline int fetch_db_tables(THD* thd, MYSQL* mysql, const char* db,
|
|||
if (!tables_ok(thd, &table))
|
||||
continue;
|
||||
}
|
||||
|
||||
if ((error = fetch_nx_table(thd, db, table_name, &glob_mi, mysql)))
|
||||
if ((error = fetch_master_table(thd, db, table_name, mi, mysql)))
|
||||
return error;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -666,25 +663,26 @@ int load_master_data(THD* thd)
|
|||
MYSQL_RES* master_status_res = 0;
|
||||
bool slave_was_running = 0;
|
||||
int error = 0;
|
||||
|
||||
const char* errmsg=0;
|
||||
int restart_thread_mask;
|
||||
mc_mysql_init(&mysql);
|
||||
|
||||
// we do not want anyone messing with the slave at all for the entire
|
||||
// duration of the data load;
|
||||
pthread_mutex_lock(&LOCK_slave);
|
||||
|
||||
// first, kill the slave
|
||||
if ((slave_was_running = slave_running))
|
||||
LOCK_ACTIVE_MI;
|
||||
lock_slave_threads(active_mi);
|
||||
init_thread_mask(&restart_thread_mask,active_mi,0 /*not inverse*/);
|
||||
if (restart_thread_mask &&
|
||||
(error=terminate_slave_threads(active_mi,restart_thread_mask,
|
||||
1 /*skip lock*/)))
|
||||
{
|
||||
abort_slave = 1;
|
||||
KICK_SLAVE;
|
||||
thd->proc_info = "waiting for slave to die";
|
||||
while (slave_running)
|
||||
pthread_cond_wait(&COND_slave_stopped, &LOCK_slave); // wait until done
|
||||
send_error(&thd->net,error);
|
||||
unlock_slave_threads(active_mi);
|
||||
UNLOCK_ACTIVE_MI;
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
if (connect_to_master(thd, &mysql, &glob_mi))
|
||||
|
||||
if (connect_to_master(thd, &mysql, active_mi))
|
||||
{
|
||||
net_printf(&thd->net, error = ER_CONNECT_TO_MASTER,
|
||||
mc_mysql_error(&mysql));
|
||||
|
@ -746,7 +744,7 @@ int load_master_data(THD* thd)
|
|||
mess up and not exclude mysql database with the rules when
|
||||
he actually means to - in this case, he is up for a surprise if
|
||||
his priv tables get dropped and downloaded from master
|
||||
TO DO - add special option, not enabled
|
||||
TODO - add special option, not enabled
|
||||
by default, to allow inclusion of mysql database into load
|
||||
data from master
|
||||
*/
|
||||
|
@ -776,7 +774,7 @@ int load_master_data(THD* thd)
|
|||
goto err;
|
||||
}
|
||||
|
||||
if ((error = fetch_db_tables(thd, &mysql, db, *cur_table_res)))
|
||||
if ((error = fetch_db_tables(thd,&mysql,db,*cur_table_res,active_mi)))
|
||||
{
|
||||
// we do not report the error - fetch_db_tables handles it
|
||||
cleanup_mysql_results(db_res, cur_table_res, table_res);
|
||||
|
@ -799,14 +797,15 @@ int load_master_data(THD* thd)
|
|||
*/
|
||||
if (row[0] && row[1])
|
||||
{
|
||||
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
|
||||
if (glob_mi.pos < 4)
|
||||
glob_mi.pos = 4; // don't hit the magic number
|
||||
glob_mi.pending = 0;
|
||||
flush_master_info(&glob_mi);
|
||||
strmake(active_mi->master_log_name, row[0],
|
||||
sizeof(active_mi->master_log_name));
|
||||
// atoi() is ok, since offset is <= 1GB
|
||||
active_mi->master_log_pos = atoi(row[1]);
|
||||
if (active_mi->master_log_pos < 4)
|
||||
active_mi->master_log_pos = 4; // don't hit the magic number
|
||||
active_mi->rli.pending = 0;
|
||||
flush_master_info(active_mi);
|
||||
}
|
||||
|
||||
mc_mysql_free_result(master_status_res);
|
||||
}
|
||||
|
||||
|
@ -817,11 +816,35 @@ int load_master_data(THD* thd)
|
|||
goto err;
|
||||
}
|
||||
}
|
||||
thd->proc_info="purging old relay logs";
|
||||
if (purge_relay_logs(&active_mi->rli,0 /* not only reset, but also reinit*/,
|
||||
&errmsg))
|
||||
{
|
||||
send_error(&thd->net, 0, "Failed purging old relay logs");
|
||||
unlock_slave_threads(active_mi);
|
||||
UNLOCK_ACTIVE_MI;
|
||||
return 1;
|
||||
}
|
||||
pthread_mutex_lock(&active_mi->rli.data_lock);
|
||||
active_mi->rli.master_log_pos = active_mi->master_log_pos;
|
||||
strnmov(active_mi->rli.master_log_name,active_mi->master_log_name,
|
||||
sizeof(active_mi->rli.master_log_name));
|
||||
pthread_cond_broadcast(&active_mi->rli.data_cond);
|
||||
pthread_mutex_unlock(&active_mi->rli.data_lock);
|
||||
thd->proc_info = "starting slave";
|
||||
if (restart_thread_mask)
|
||||
{
|
||||
error=start_slave_threads(0 /* mutex not needed*/,
|
||||
1 /* wait for start*/,
|
||||
active_mi,master_info_file,relay_log_info_file,
|
||||
restart_thread_mask);
|
||||
}
|
||||
|
||||
err:
|
||||
pthread_mutex_unlock(&LOCK_slave);
|
||||
if (slave_was_running)
|
||||
start_slave(0, 0);
|
||||
unlock_slave_threads(active_mi);
|
||||
UNLOCK_ACTIVE_MI;
|
||||
thd->proc_info = 0;
|
||||
|
||||
mc_mysql_close(&mysql); // safe to call since we always do mc_mysql_init()
|
||||
if (!error)
|
||||
send_ok(&thd->net);
|
||||
|
|
1772
sql/slave.cc
1772
sql/slave.cc
File diff suppressed because it is too large
Load diff
356
sql/slave.h
356
sql/slave.h
|
@ -2,70 +2,265 @@
|
|||
#define SLAVE_H
|
||||
|
||||
#include "mysql.h"
|
||||
#include "my_list.h"
|
||||
#define SLAVE_NET_TIMEOUT 3600
|
||||
#define MAX_SLAVE_ERROR 2000
|
||||
#define MAX_SLAVE_ERRMSG 1024
|
||||
|
||||
/*
|
||||
The replication is accomplished by starting two threads - I/O
|
||||
thread, and SQL thread. I/O thread is associated with its
|
||||
MASTER_INFO struct, so MASTER_INFO can be viewed as I/O thread
|
||||
descriptor. SQL thread is associated with RELAY_LOG_INFO struct.
|
||||
|
||||
I/O thread reads maintains a connection to the master, and reads log
|
||||
events from the master as they arrive, queueing them by writing them
|
||||
out into the temporary slave binary log (relay log). The SQL thread,
|
||||
in turn, reads the slave binary log executing each event.
|
||||
|
||||
Relay log is needed to be able to handle situations when there is a large
|
||||
backlog of unprocessed events from the master (eg. one particular update
|
||||
takes a day to finish), and to be able to restart the slave server without
|
||||
having to re-read the master updates.
|
||||
*/
|
||||
|
||||
extern ulong slave_net_timeout, master_retry_count;
|
||||
extern MY_BITMAP slave_error_mask;
|
||||
extern bool use_slave_mask;
|
||||
extern char* slave_load_tmpdir;
|
||||
extern my_string master_info_file,relay_log_info_file;
|
||||
extern my_string opt_relay_logname, opt_relaylog_index_name;
|
||||
extern bool opt_skip_slave_start;
|
||||
struct st_master_info;
|
||||
|
||||
#define LOCK_ACTIVE_MI { pthread_mutex_lock(&LOCK_active_mi); \
|
||||
++active_mi_in_use; \
|
||||
pthread_mutex_unlock(&LOCK_active_mi);}
|
||||
|
||||
#define UNLOCK_ACTIVE_MI { pthread_mutex_lock(&LOCK_active_mi); \
|
||||
--active_mi_in_use; \
|
||||
pthread_mutex_unlock(&LOCK_active_mi); }
|
||||
|
||||
/*
|
||||
st_relay_log_info contains information on the current relay log and
|
||||
relay log offset, and master log name and log sequence corresponding to the
|
||||
last update. Additionally, misc information specific to the SQL thread is
|
||||
included.
|
||||
|
||||
st_relay_log_info is initialized from the slave.info file if such exists.
|
||||
Otherwise, data members are intialized with defaults. The initialization is
|
||||
done with init_relay_log_info() call.
|
||||
|
||||
The format of slave.info file:
|
||||
|
||||
relay_log_name
|
||||
relay_log_pos
|
||||
master_log_name
|
||||
master_log_pos
|
||||
|
||||
To clean up, call end_relay_log_info()
|
||||
*/
|
||||
typedef struct st_relay_log_info
|
||||
{
|
||||
// info_fd - file descriptor of the info file. set only during
|
||||
// initialization or clean up - safe to read anytime
|
||||
// cur_log_fd - file descriptor of the current read relay log, protected by
|
||||
// data_lock
|
||||
File info_fd,cur_log_fd;
|
||||
|
||||
// IO_CACHE of the info file - set only during init or end, safe to read
|
||||
// anytime
|
||||
IO_CACHE info_file;
|
||||
|
||||
// name of current read relay log - protected by data_lock
|
||||
char relay_log_name[FN_REFLEN];
|
||||
|
||||
// master log name corresponding to current read position - protected by
|
||||
// data lock
|
||||
char master_log_name[FN_REFLEN];
|
||||
|
||||
// original log position of last processed event - protected by data_lock
|
||||
volatile uint32 master_log_pos;
|
||||
|
||||
// when we restart slave thread we need to have access to the previously
|
||||
// created temporary tables. Modified only on init/end and by the SQL
|
||||
// thread, read only by SQL thread, need no mutex
|
||||
TABLE* save_temporary_tables;
|
||||
|
||||
// relay_log_pos - current offset in the relay log - protected by data_lock
|
||||
// pending - in some cases we do not increment offset immediately after
|
||||
// processing an event, because the following event needs to be processed
|
||||
// atomically together with this one ( so far, there is only one type of
|
||||
// such event - Intvar_event that sets auto_increment value). However, once
|
||||
// both events have been processed, we need to increment by the cumulative
|
||||
// offset. pending stored the extra offset to be added to the position.
|
||||
ulonglong relay_log_pos,pending;
|
||||
|
||||
// standard lock acquistion order to avoid deadlocks:
|
||||
// run_lock, data_lock, relay_log.LOCK_log,relay_log.LOCK_index
|
||||
pthread_mutex_t data_lock,run_lock;
|
||||
|
||||
// start_cond is broadcast when SQL thread is started
|
||||
// stop_cond - when stopped
|
||||
// data_cond - when data protected by data_lock changes
|
||||
pthread_cond_t start_cond,stop_cond,data_cond;
|
||||
|
||||
// if not set, the value of other members of the structure are undefined
|
||||
bool inited;
|
||||
|
||||
// parent master info structure
|
||||
struct st_master_info *mi;
|
||||
|
||||
// protected with internal locks
|
||||
// must get data_lock when resetting the logs
|
||||
MYSQL_LOG relay_log;
|
||||
LOG_INFO linfo;
|
||||
IO_CACHE cache_buf,*cur_log;
|
||||
|
||||
/* needed to deal properly with cur_log getting closed and re-opened with
|
||||
a different log under our feet
|
||||
*/
|
||||
int cur_log_init_count;
|
||||
|
||||
volatile bool abort_slave, slave_running;
|
||||
// needed for problems when slave stops and
|
||||
// we want to restart it skipping one or more events in the master log that
|
||||
// have caused errors, and have been manually applied by DBA already
|
||||
volatile uint32 slave_skip_counter;
|
||||
#ifndef DBUG_OFF
|
||||
int events_till_abort;
|
||||
#endif
|
||||
int last_slave_errno;
|
||||
char last_slave_error[MAX_SLAVE_ERRMSG];
|
||||
THD* sql_thd;
|
||||
bool log_pos_current;
|
||||
|
||||
st_relay_log_info():info_fd(-1),cur_log_fd(-1),inited(0),
|
||||
cur_log_init_count(0),
|
||||
log_pos_current(0)
|
||||
{
|
||||
relay_log_name[0] = master_log_name[0] = 0;
|
||||
pthread_mutex_init(&run_lock, MY_MUTEX_INIT_FAST);
|
||||
pthread_mutex_init(&data_lock, MY_MUTEX_INIT_FAST);
|
||||
pthread_cond_init(&data_cond, NULL);
|
||||
pthread_cond_init(&start_cond, NULL);
|
||||
pthread_cond_init(&stop_cond, NULL);
|
||||
}
|
||||
~st_relay_log_info()
|
||||
{
|
||||
pthread_mutex_destroy(&run_lock);
|
||||
pthread_mutex_destroy(&data_lock);
|
||||
pthread_cond_destroy(&data_cond);
|
||||
pthread_cond_destroy(&start_cond);
|
||||
pthread_cond_destroy(&stop_cond);
|
||||
}
|
||||
inline void inc_pending(ulonglong val)
|
||||
{
|
||||
pending += val;
|
||||
}
|
||||
// TODO: this probably needs to be fixed
|
||||
inline void inc_pos(ulonglong val, uint32 log_pos, bool skip_lock=0)
|
||||
{
|
||||
if (!skip_lock)
|
||||
pthread_mutex_lock(&data_lock);
|
||||
relay_log_pos += val+pending;
|
||||
pending = 0;
|
||||
if (log_pos)
|
||||
master_log_pos = log_pos+val;
|
||||
pthread_cond_broadcast(&data_cond);
|
||||
if (!skip_lock)
|
||||
pthread_mutex_unlock(&data_lock);
|
||||
}
|
||||
// thread safe read of position - not needed if we are in the slave thread,
|
||||
// but required otherwise
|
||||
inline void read_pos(ulonglong& var)
|
||||
{
|
||||
pthread_mutex_lock(&data_lock);
|
||||
var = relay_log_pos;
|
||||
pthread_mutex_unlock(&data_lock);
|
||||
}
|
||||
|
||||
int wait_for_pos(THD* thd, String* log_name, ulonglong log_pos);
|
||||
} RELAY_LOG_INFO;
|
||||
|
||||
// repopen_relay_log() is called when we notice that the current "hot" log
|
||||
// got rotated under our feet
|
||||
IO_CACHE* reopen_relay_log(RELAY_LOG_INFO* rli, const char** errmsg);
|
||||
Log_event* next_event(RELAY_LOG_INFO* rli);
|
||||
|
||||
/* st_master_info contains information about how to connect to a master,
|
||||
current master log name, and current log offset, as well as misc
|
||||
control variables
|
||||
|
||||
st_master_info is initialized once from the master.info file if such
|
||||
exists. Otherwise, data members corresponding to master.info fields are
|
||||
initialized with defaults specified by master-* options. The initialization
|
||||
is done through init_master_info() call.
|
||||
|
||||
The format of master.info file:
|
||||
|
||||
log_name
|
||||
log_pos
|
||||
master_host
|
||||
master_user
|
||||
master_pass
|
||||
master_port
|
||||
master_connect_retry
|
||||
|
||||
To write out the contents of master.info file to disk ( needed every
|
||||
time we read and queue data from the master ), a call to
|
||||
flush_master_info() is required.
|
||||
|
||||
To clean up, call end_master_info()
|
||||
|
||||
*/
|
||||
|
||||
typedef struct st_master_info
|
||||
{
|
||||
char log_file_name[FN_REFLEN];
|
||||
ulonglong pos,pending;
|
||||
File fd; // we keep the file open, so we need to remember the file pointer
|
||||
char master_log_name[FN_REFLEN];
|
||||
|
||||
ulonglong master_log_pos;
|
||||
File fd;
|
||||
IO_CACHE file;
|
||||
|
||||
// the variables below are needed because we can change masters on the fly
|
||||
char host[HOSTNAME_LENGTH+1];
|
||||
char user[USERNAME_LENGTH+1];
|
||||
char password[HASH_PASSWORD_LENGTH+1];
|
||||
uint port;
|
||||
uint connect_retry;
|
||||
uint32 last_log_seq; // log sequence number of last processed event
|
||||
pthread_mutex_t lock;
|
||||
pthread_cond_t cond;
|
||||
pthread_mutex_t data_lock,run_lock;
|
||||
pthread_cond_t data_cond,start_cond,stop_cond;
|
||||
bool inited;
|
||||
bool old_format; /* master binlog is in 3.23 format */
|
||||
|
||||
st_master_info():pending(0),fd(-1),last_log_seq(0),inited(0),
|
||||
old_format(0)
|
||||
RELAY_LOG_INFO rli;
|
||||
#ifndef DBUG_OFF
|
||||
int events_till_abort;
|
||||
#endif
|
||||
volatile bool abort_slave, slave_running;
|
||||
THD* io_thd;
|
||||
|
||||
st_master_info():fd(-1),inited(0),
|
||||
old_format(0),io_thd(0)
|
||||
{
|
||||
host[0] = 0; user[0] = 0; password[0] = 0;
|
||||
pthread_mutex_init(&lock, MY_MUTEX_INIT_FAST);
|
||||
pthread_cond_init(&cond, NULL);
|
||||
pthread_mutex_init(&run_lock, MY_MUTEX_INIT_FAST);
|
||||
pthread_mutex_init(&data_lock, MY_MUTEX_INIT_FAST);
|
||||
pthread_cond_init(&data_cond, NULL);
|
||||
pthread_cond_init(&start_cond, NULL);
|
||||
pthread_cond_init(&stop_cond, NULL);
|
||||
}
|
||||
|
||||
~st_master_info()
|
||||
{
|
||||
pthread_mutex_destroy(&lock);
|
||||
pthread_cond_destroy(&cond);
|
||||
}
|
||||
inline void inc_pending(ulonglong val)
|
||||
{
|
||||
pending += val;
|
||||
}
|
||||
inline void inc_pos(ulonglong val, uint32 log_seq)
|
||||
{
|
||||
pthread_mutex_lock(&lock);
|
||||
pos += val + pending;
|
||||
pending = 0;
|
||||
last_log_seq = log_seq;
|
||||
pthread_cond_broadcast(&cond);
|
||||
pthread_mutex_unlock(&lock);
|
||||
}
|
||||
// thread safe read of position - not needed if we are in the slave thread,
|
||||
// but required otherwise
|
||||
inline void read_pos(ulonglong& var)
|
||||
{
|
||||
pthread_mutex_lock(&lock);
|
||||
var = pos;
|
||||
pthread_mutex_unlock(&lock);
|
||||
pthread_mutex_destroy(&run_lock);
|
||||
pthread_mutex_destroy(&data_lock);
|
||||
pthread_cond_destroy(&data_cond);
|
||||
pthread_cond_destroy(&start_cond);
|
||||
pthread_cond_destroy(&stop_cond);
|
||||
}
|
||||
|
||||
int wait_for_pos(THD* thd, String* log_name, ulonglong log_pos);
|
||||
} MASTER_INFO;
|
||||
|
||||
int queue_event(MASTER_INFO* mi,const char* buf,uint event_len);
|
||||
|
||||
typedef struct st_table_rule_ent
|
||||
{
|
||||
char* db;
|
||||
|
@ -77,22 +272,52 @@ typedef struct st_table_rule_ent
|
|||
#define TABLE_RULE_ARR_SIZE 16
|
||||
#define MAX_SLAVE_ERRMSG 1024
|
||||
|
||||
#define RPL_LOG_NAME (glob_mi.log_file_name[0] ? glob_mi.log_file_name :\
|
||||
#define RPL_LOG_NAME (rli->master_log_name[0] ? rli->master_log_name :\
|
||||
"FIRST")
|
||||
#define IO_RPL_LOG_NAME (mi->master_log_name[0] ? mi->master_log_name :\
|
||||
"FIRST")
|
||||
|
||||
/* masks for start/stop operations on io and sql slave threads */
|
||||
#define SLAVE_IO 1
|
||||
#define SLAVE_SQL 2
|
||||
#define SLAVE_FORCE_ALL 4 /* if this is set, if first gives an
|
||||
error, second will be tried. Otherwise,
|
||||
if first fails, we fail
|
||||
*/
|
||||
|
||||
int init_slave();
|
||||
int flush_master_info(MASTER_INFO* mi);
|
||||
int flush_relay_log_info(RELAY_LOG_INFO* rli);
|
||||
int register_slave_on_master(MYSQL* mysql);
|
||||
int terminate_slave_threads(MASTER_INFO* mi, int thread_mask,
|
||||
bool skip_lock = 0);
|
||||
int terminate_slave_thread(THD* thd, pthread_mutex_t* term_mutex,
|
||||
pthread_mutex_t* cond_lock,
|
||||
pthread_cond_t* term_cond,
|
||||
volatile bool* slave_running);
|
||||
int start_slave_threads(bool need_slave_mutex, bool wait_for_start,
|
||||
MASTER_INFO* mi, const char* master_info_fname,
|
||||
const char* slave_info_fname, int thread_mask);
|
||||
/* cond_lock is usually same as start_lock. It is needed for the case when
|
||||
start_lock is 0 which happens if start_slave_thread() is called already
|
||||
inside the start_lock section, but at the same time we want a
|
||||
pthread_cond_wait() on start_cond,start_lock
|
||||
*/
|
||||
int start_slave_thread(pthread_handler h_func, pthread_mutex_t* start_lock,
|
||||
pthread_mutex_t *cond_lock,
|
||||
pthread_cond_t* start_cond,
|
||||
volatile bool* slave_running,
|
||||
MASTER_INFO* mi);
|
||||
|
||||
int mysql_table_dump(THD* thd, const char* db,
|
||||
const char* tbl_name, int fd = -1);
|
||||
// if fd is -1, dump to NET
|
||||
|
||||
int fetch_nx_table(THD* thd, const char* db_name, const char* table_name,
|
||||
int fetch_master_table(THD* thd, const char* db_name, const char* table_name,
|
||||
MASTER_INFO* mi, MYSQL* mysql);
|
||||
// retrieve non-exitent table from master
|
||||
|
||||
int show_master_info(THD* thd);
|
||||
int show_master_info(THD* thd, MASTER_INFO* mi);
|
||||
int show_binlog_info(THD* thd);
|
||||
|
||||
int tables_ok(THD* thd, TABLE_LIST* tables);
|
||||
|
@ -107,30 +332,32 @@ int add_table_rule(HASH* h, const char* table_spec);
|
|||
int add_wild_table_rule(DYNAMIC_ARRAY* a, const char* table_spec);
|
||||
void init_table_rule_hash(HASH* h, bool* h_inited);
|
||||
void init_table_rule_array(DYNAMIC_ARRAY* a, bool* a_inited);
|
||||
void init_slave_skip_errors(char* arg);
|
||||
char* rewrite_db(char* db);
|
||||
int check_expected_error(THD* thd, int error_code);
|
||||
int check_expected_error(THD* thd, RELAY_LOG_INFO* rli, int error_code);
|
||||
void skip_load_data_infile(NET* net);
|
||||
void slave_print_error(int err_code, const char* msg, ...);
|
||||
void end_slave(); // clean up
|
||||
int init_master_info(MASTER_INFO* mi);
|
||||
void end_master_info(MASTER_INFO* mi);
|
||||
extern bool opt_log_slave_updates ;
|
||||
pthread_handler_decl(handle_slave,arg);
|
||||
extern bool volatile abort_loop, abort_slave, slave_running;
|
||||
extern uint32 slave_skip_counter;
|
||||
// needed for problems when slave stops and
|
||||
// we want to restart it skipping one or more events in the master log that
|
||||
// have caused errors, and have been manually applied by DBA already
|
||||
void slave_print_error(RELAY_LOG_INFO* rli,int err_code, const char* msg, ...);
|
||||
|
||||
extern int last_slave_errno;
|
||||
#ifndef DBUG_OFF
|
||||
extern int events_till_abort;
|
||||
#endif
|
||||
extern char last_slave_error[MAX_SLAVE_ERRMSG];
|
||||
extern pthread_t slave_real_id;
|
||||
extern THD* slave_thd;
|
||||
extern MASTER_INFO glob_mi;
|
||||
void end_slave(); // clean up
|
||||
int init_master_info(MASTER_INFO* mi, const char* master_info_fname,
|
||||
const char* slave_info_fname);
|
||||
void end_master_info(MASTER_INFO* mi);
|
||||
int init_relay_log_info(RELAY_LOG_INFO* rli, const char* info_fname);
|
||||
void end_relay_log_info(RELAY_LOG_INFO* rli);
|
||||
void lock_slave_threads(MASTER_INFO* mi);
|
||||
void unlock_slave_threads(MASTER_INFO* mi);
|
||||
void init_thread_mask(int* mask,MASTER_INFO* mi,bool inverse);
|
||||
int init_relay_log_pos(RELAY_LOG_INFO* rli,const char* log,ulonglong pos,
|
||||
bool need_data_lock, const char** errmsg);
|
||||
|
||||
int purge_relay_logs(RELAY_LOG_INFO* rli,bool just_reset,const char** errmsg);
|
||||
|
||||
extern bool opt_log_slave_updates ;
|
||||
pthread_handler_decl(handle_slave_io,arg);
|
||||
pthread_handler_decl(handle_slave_sql,arg);
|
||||
extern bool volatile abort_loop;
|
||||
extern MASTER_INFO main_mi, *active_mi; // active_mi for multi-master
|
||||
extern volatile int active_mi_in_use;
|
||||
extern LIST master_list;
|
||||
extern HASH replicate_do_table, replicate_ignore_table;
|
||||
extern DYNAMIC_ARRAY replicate_wild_do_table, replicate_wild_ignore_table;
|
||||
extern bool do_table_inited, ignore_table_inited,
|
||||
|
@ -144,10 +371,13 @@ extern int disconnect_slave_event_count, abort_slave_event_count ;
|
|||
// the master variables are defaults read from my.cnf or command line
|
||||
extern uint master_port, master_connect_retry, report_port;
|
||||
extern my_string master_user, master_password, master_host,
|
||||
master_info_file, report_user, report_host, report_password;
|
||||
master_info_file, relay_log_info_file, report_user, report_host,
|
||||
report_password;
|
||||
|
||||
extern I_List<i_string> replicate_do_db, replicate_ignore_db;
|
||||
extern I_List<i_string_pair> replicate_rewrite_db;
|
||||
extern I_List<THD> threads;
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
|
|
|
@ -98,7 +98,6 @@ THD::THD():user_time(0),fatal_error(0),last_insert_id_used(0),
|
|||
current_linfo = 0;
|
||||
slave_thread = 0;
|
||||
slave_proxy_id = 0;
|
||||
log_seq = 0;
|
||||
file_id = 0;
|
||||
cond_count=0;
|
||||
convert_set=0;
|
||||
|
@ -119,6 +118,7 @@ THD::THD():user_time(0),fatal_error(0),last_insert_id_used(0),
|
|||
where="field list";
|
||||
server_id = ::server_id;
|
||||
slave_net = 0;
|
||||
log_pos = 0;
|
||||
server_status=SERVER_STATUS_AUTOCOMMIT;
|
||||
update_lock_default= low_priority_updates ? TL_WRITE_LOW_PRIORITY : TL_WRITE;
|
||||
options=thd_startup_options;
|
||||
|
@ -217,10 +217,11 @@ THD::~THD()
|
|||
DBUG_VOID_RETURN;
|
||||
}
|
||||
|
||||
void THD::prepare_to_die()
|
||||
void THD::awake(bool prepare_to_die)
|
||||
{
|
||||
if (prepare_to_die)
|
||||
killed = 1;
|
||||
thr_alarm_kill(real_id);
|
||||
killed = 1;
|
||||
#ifdef SIGNAL_WITH_VIO_CLOSE
|
||||
close_active_vio();
|
||||
#endif
|
||||
|
@ -229,6 +230,10 @@ void THD::prepare_to_die()
|
|||
pthread_mutex_lock(&mysys_var->mutex);
|
||||
if (!system_thread) // Don't abort locks
|
||||
mysys_var->abort=1;
|
||||
// this broadcast could be up in the air if the victim thread
|
||||
// exits the cond in the time between read and broadcast, but that is
|
||||
// ok since all we want to do is to make the victim thread get out
|
||||
// of waiting on current_cond
|
||||
if (mysys_var->current_cond)
|
||||
{
|
||||
pthread_mutex_lock(mysys_var->current_mutex);
|
||||
|
|
124
sql/sql_class.h
124
sql/sql_class.h
|
@ -21,6 +21,8 @@
|
|||
#pragma interface /* gcc class implementation */
|
||||
#endif
|
||||
|
||||
// TODO: create log.h and move all the log header stuff there
|
||||
|
||||
class Query_log_event;
|
||||
class Load_log_event;
|
||||
class Slave_log_event;
|
||||
|
@ -40,6 +42,8 @@ enum enum_log_type { LOG_CLOSED, LOG_NORMAL, LOG_NEW, LOG_BIN };
|
|||
#define LOG_INFO_FATAL -7
|
||||
#define LOG_INFO_IN_USE -8
|
||||
|
||||
struct st_relay_log_info;
|
||||
|
||||
typedef struct st_log_info
|
||||
{
|
||||
char log_file_name[FN_REFLEN];
|
||||
|
@ -64,8 +68,6 @@ class MYSQL_LOG {
|
|||
char time_buff[20],db[NAME_LEN+1];
|
||||
char log_file_name[FN_REFLEN],index_file_name[FN_REFLEN];
|
||||
bool write_error,inited;
|
||||
uint32 log_seq; // current event sequence number
|
||||
// needed this for binlog
|
||||
uint file_id; // current file sequence number for load data infile
|
||||
// binary logging
|
||||
bool no_rotate; // for binlog - if log name can never change
|
||||
|
@ -74,36 +76,52 @@ class MYSQL_LOG {
|
|||
// purging
|
||||
enum cache_type io_cache_type;
|
||||
bool need_start_event;
|
||||
pthread_cond_t update_cond;
|
||||
bool no_auto_events; // for relay binlog
|
||||
friend class Log_event;
|
||||
|
||||
public:
|
||||
MYSQL_LOG();
|
||||
~MYSQL_LOG();
|
||||
pthread_mutex_t* get_log_lock() { return &LOCK_log; }
|
||||
IO_CACHE* get_log_file() { return &log_file; }
|
||||
void signal_update() { pthread_cond_broadcast(&update_cond);}
|
||||
void wait_for_update(THD* thd);
|
||||
void set_need_start_event() { need_start_event = 1; }
|
||||
void set_index_file_name(const char* index_file_name = 0);
|
||||
void init(enum_log_type log_type_arg,
|
||||
enum cache_type io_cache_type_arg = WRITE_CACHE);
|
||||
enum cache_type io_cache_type_arg = WRITE_CACHE,
|
||||
bool no_auto_events_arg = 0);
|
||||
void open(const char *log_name,enum_log_type log_type,
|
||||
const char *new_name=0);
|
||||
const char *new_name, enum cache_type io_cache_type_arg,
|
||||
bool no_auto_events_arg);
|
||||
void new_file(bool inside_mutex = 0);
|
||||
bool open_index(int options);
|
||||
void close_index();
|
||||
bool write(THD *thd, enum enum_server_command command,const char *format,...);
|
||||
bool write(THD *thd, enum enum_server_command command,
|
||||
const char *format,...);
|
||||
bool write(THD *thd, const char *query, uint query_length,
|
||||
time_t query_start=0);
|
||||
bool write(Log_event* event_info); // binary log write
|
||||
bool write(IO_CACHE *cache);
|
||||
|
||||
//v stands for vector
|
||||
//invoked as appendv(buf1,len1,buf2,len2,...,bufn,lenn,0)
|
||||
bool appendv(const char* buf,uint len,...);
|
||||
|
||||
int generate_new_name(char *new_name,const char *old_name);
|
||||
void make_log_name(char* buf, const char* log_ident);
|
||||
bool is_active(const char* log_file_name);
|
||||
int purge_logs(THD* thd, const char* to_log);
|
||||
int purge_first_log(struct st_relay_log_info* rli);
|
||||
int reset_logs(THD* thd);
|
||||
void close(bool exiting = 0); // if we are exiting, we also want to close the
|
||||
// index file
|
||||
|
||||
// iterating through the log index file
|
||||
int find_first_log(LOG_INFO* linfo, const char* log_name);
|
||||
int find_next_log(LOG_INFO* linfo);
|
||||
int find_first_log(LOG_INFO* linfo, const char* log_name,
|
||||
bool need_mutex=1);
|
||||
int find_next_log(LOG_INFO* linfo, bool need_mutex=1);
|
||||
int get_current_log(LOG_INFO* linfo);
|
||||
uint next_file_id();
|
||||
|
||||
|
@ -228,33 +246,73 @@ public:
|
|||
};
|
||||
|
||||
|
||||
/****************************************************************************
|
||||
** every connection is handled by a thread with a THD
|
||||
****************************************************************************/
|
||||
|
||||
class delayed_insert;
|
||||
|
||||
/* For each client connection we create a separate thread with THD serving as
|
||||
a thread/connection descriptor */
|
||||
|
||||
class THD :public ilink {
|
||||
public:
|
||||
NET net;
|
||||
LEX lex;
|
||||
MEM_ROOT mem_root;
|
||||
HASH user_vars;
|
||||
String packet; /* Room for 1 row */
|
||||
struct sockaddr_in remote;
|
||||
struct rand_struct rand;
|
||||
char *query,*thread_stack;
|
||||
char *host,*user,*priv_user,*db,*ip;
|
||||
const char *proc_info, *host_or_ip;
|
||||
uint client_capabilities,sql_mode,max_packet_length;
|
||||
uint master_access,db_access;
|
||||
TABLE *open_tables,*temporary_tables, *handler_tables;
|
||||
NET net; // client connection descriptor
|
||||
LEX lex; // parse tree descriptor
|
||||
MEM_ROOT mem_root; // memory allocation pool
|
||||
HASH user_vars; // hash for user variables
|
||||
String packet; // dynamic string buffer used for network I/O
|
||||
struct sockaddr_in remote; // client socket address
|
||||
struct rand_struct rand; // used for authentication
|
||||
|
||||
/* query points to the current query,
|
||||
thread_stack is a pointer to the stack frame of handle_one_connection(),
|
||||
which is called first in the thread for handling a client
|
||||
*/
|
||||
char *query,*thread_stack;
|
||||
/*
|
||||
host - host of the client
|
||||
user - user of the client, set to NULL until the user has been read from
|
||||
the connection
|
||||
priv_user - not sure why we have it, but it is set to "boot" when we run
|
||||
with --bootstrap
|
||||
db - currently selected database
|
||||
ip - client IP
|
||||
*/
|
||||
|
||||
char *host,*user,*priv_user,*db,*ip;
|
||||
/* proc_info points to a string that will show in the Info column of
|
||||
SHOW PROCESSLIST output
|
||||
host_or_ip points to host if host is available, otherwise points to ip
|
||||
*/
|
||||
const char *proc_info, *host_or_ip;
|
||||
|
||||
/*
|
||||
client_capabilities has flags describing what the client can do
|
||||
sql_mode determines if certain non-standard SQL behaviour should be
|
||||
enabled
|
||||
max_packet_length - supposed to be maximum packet length the client
|
||||
can handle, but it currently appears to be assigned but never used
|
||||
except for one debugging statement
|
||||
*/
|
||||
uint client_capabilities,sql_mode,max_packet_length;
|
||||
|
||||
/*
|
||||
master_access - privillege descriptor mask for system threads
|
||||
db_access - privillege descriptor mask for regular threads
|
||||
*/
|
||||
uint master_access,db_access;
|
||||
|
||||
/*
|
||||
open_tables - list of regular tables in use by this thread
|
||||
temporary_tables - list of temp tables in use by this thread
|
||||
handler_tables - list of tables that were opened with HANDLER OPEN
|
||||
and are still in use by this thread
|
||||
*/
|
||||
TABLE *open_tables,*temporary_tables, *handler_tables;
|
||||
// TODO: document the variables below
|
||||
MYSQL_LOCK *lock,*locked_tables;
|
||||
ULL *ull;
|
||||
ULL *ull;
|
||||
struct st_my_thread_var *mysys_var;
|
||||
enum enum_server_command command;
|
||||
uint32 server_id;
|
||||
uint32 log_seq;
|
||||
uint32 server_id;
|
||||
uint32 file_id; // for LOAD DATA INFILE
|
||||
uint32 file_id; // for LOAD DATA INFILE
|
||||
const char *where;
|
||||
time_t start_time,time_after_lock,user_time;
|
||||
|
@ -312,6 +370,8 @@ public:
|
|||
*/
|
||||
ulong slave_proxy_id;
|
||||
NET* slave_net; // network connection from slave -> m.
|
||||
uint32 log_pos;
|
||||
|
||||
THD();
|
||||
~THD();
|
||||
void cleanup(void);
|
||||
|
@ -333,14 +393,14 @@ public:
|
|||
{
|
||||
pthread_mutex_lock(&active_vio_lock);
|
||||
if(active_vio)
|
||||
{
|
||||
vio_close(active_vio);
|
||||
active_vio = 0;
|
||||
}
|
||||
{
|
||||
vio_close(active_vio);
|
||||
active_vio = 0;
|
||||
}
|
||||
pthread_mutex_unlock(&active_vio_lock);
|
||||
}
|
||||
#endif
|
||||
void prepare_to_die();
|
||||
void awake(bool prepare_to_die);
|
||||
inline const char* enter_cond(pthread_cond_t *cond, pthread_mutex_t* mutex,
|
||||
const char* msg)
|
||||
{
|
||||
|
|
|
@ -95,7 +95,6 @@ typedef struct st_lex_master_info
|
|||
{
|
||||
char* host, *user, *password,*log_file_name;
|
||||
uint port, connect_retry;
|
||||
ulong last_log_seq;
|
||||
ulonglong pos;
|
||||
ulong server_id;
|
||||
} LEX_MASTER_INFO;
|
||||
|
|
|
@ -1359,14 +1359,18 @@ mysql_execute_command(void)
|
|||
{
|
||||
if (check_access(thd, PROCESS_ACL, any_db))
|
||||
goto error;
|
||||
res = change_master(thd);
|
||||
LOCK_ACTIVE_MI;
|
||||
res = change_master(thd,active_mi);
|
||||
UNLOCK_ACTIVE_MI;
|
||||
break;
|
||||
}
|
||||
case SQLCOM_SHOW_SLAVE_STAT:
|
||||
{
|
||||
if (check_process_priv(thd))
|
||||
goto error;
|
||||
res = show_master_info(thd);
|
||||
LOCK_ACTIVE_MI;
|
||||
res = show_master_info(thd,active_mi);
|
||||
UNLOCK_ACTIVE_MI;
|
||||
break;
|
||||
}
|
||||
case SQLCOM_SHOW_MASTER_STAT:
|
||||
|
@ -1376,15 +1380,15 @@ mysql_execute_command(void)
|
|||
res = show_binlog_info(thd);
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
case SQLCOM_LOAD_MASTER_DATA: // sync with master
|
||||
if (check_process_priv(thd))
|
||||
goto error;
|
||||
res = load_master_data(thd);
|
||||
break;
|
||||
|
||||
|
||||
case SQLCOM_LOAD_MASTER_TABLE:
|
||||
|
||||
{
|
||||
if (!tables->db)
|
||||
tables->db=thd->db;
|
||||
if (check_access(thd,CREATE_ACL,tables->db,&tables->grant.privilege))
|
||||
|
@ -1404,12 +1408,16 @@ mysql_execute_command(void)
|
|||
net_printf(&thd->net,ER_WRONG_TABLE_NAME,tables->name);
|
||||
break;
|
||||
}
|
||||
|
||||
if (fetch_nx_table(thd, tables->db, tables->real_name, &glob_mi, 0))
|
||||
break; // fetch_nx_table did send the error to the client
|
||||
send_ok(&thd->net);
|
||||
LOCK_ACTIVE_MI;
|
||||
// fetch_master_table will send the error to the client on failure
|
||||
if (!fetch_master_table(thd, tables->db, tables->real_name,
|
||||
active_mi, 0))
|
||||
{
|
||||
send_ok(&thd->net);
|
||||
}
|
||||
UNLOCK_ACTIVE_MI;
|
||||
break;
|
||||
|
||||
}
|
||||
case SQLCOM_CREATE_TABLE:
|
||||
if (!tables->db)
|
||||
tables->db=thd->db;
|
||||
|
@ -1509,12 +1517,19 @@ mysql_execute_command(void)
|
|||
break;
|
||||
|
||||
case SQLCOM_SLAVE_START:
|
||||
start_slave(thd);
|
||||
{
|
||||
LOCK_ACTIVE_MI;
|
||||
start_slave(thd,active_mi,1 /* net report*/);
|
||||
UNLOCK_ACTIVE_MI;
|
||||
break;
|
||||
}
|
||||
case SQLCOM_SLAVE_STOP:
|
||||
stop_slave(thd);
|
||||
{
|
||||
LOCK_ACTIVE_MI;
|
||||
stop_slave(thd,active_mi,1/* net report*/);
|
||||
UNLOCK_ACTIVE_MI;
|
||||
break;
|
||||
|
||||
}
|
||||
case SQLCOM_ALTER_TABLE:
|
||||
#if defined(DONT_ALLOW_SHOW_COMMANDS)
|
||||
send_error(&thd->net,ER_NOT_ALLOWED_COMMAND); /* purecov: inspected */
|
||||
|
@ -3204,6 +3219,7 @@ bool reload_acl_and_cache(THD *thd, ulong options, TABLE_LIST *tables)
|
|||
bool result=0;
|
||||
|
||||
select_errors=0; /* Write if more errors */
|
||||
// TODO: figure out what's up with the commented out line below
|
||||
// mysql_log.flush(); // Flush log
|
||||
if (options & REFRESH_GRANT)
|
||||
{
|
||||
|
@ -3244,16 +3260,22 @@ bool reload_acl_and_cache(THD *thd, ulong options, TABLE_LIST *tables)
|
|||
if (options & REFRESH_THREADS)
|
||||
flush_thread_cache();
|
||||
if (options & REFRESH_MASTER)
|
||||
reset_master();
|
||||
if (options & REFRESH_SLAVE)
|
||||
reset_slave();
|
||||
if (reset_master(thd))
|
||||
result=1;
|
||||
#ifdef OPENSSL
|
||||
if (options & REFRESH_DES_KEY_FILE)
|
||||
{
|
||||
if (des_key_file)
|
||||
result=load_des_key_file(des_key_file);
|
||||
}
|
||||
if (options & REFRESH_DES_KEY_FILE)
|
||||
{
|
||||
if (des_key_file)
|
||||
result=load_des_key_file(des_key_file);
|
||||
}
|
||||
#endif
|
||||
if (options & REFRESH_SLAVE)
|
||||
{
|
||||
LOCK_ACTIVE_MI;
|
||||
if (reset_slave(active_mi))
|
||||
result=1;
|
||||
UNLOCK_ACTIVE_MI;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
|
@ -3271,7 +3293,7 @@ void kill_one_thread(THD *thd, ulong id)
|
|||
if ((thd->master_access & PROCESS_ACL) ||
|
||||
!strcmp(thd->user,tmp->user))
|
||||
{
|
||||
tmp->prepare_to_die();
|
||||
tmp->awake(1 /*prepare to die*/);
|
||||
error=0;
|
||||
}
|
||||
else
|
||||
|
|
336
sql/sql_repl.cc
336
sql/sql_repl.cc
|
@ -23,9 +23,9 @@
|
|||
#include "mini_client.h"
|
||||
#include <thr_alarm.h>
|
||||
#include <my_dir.h>
|
||||
#include <assert.h>
|
||||
|
||||
extern const char* any_db;
|
||||
extern pthread_handler_decl(handle_slave,arg);
|
||||
|
||||
#ifndef DBUG_OFF
|
||||
int max_binlog_dump_events = 0; // unlimited
|
||||
|
@ -33,6 +33,26 @@ bool opt_sporadic_binlog_dump_fail = 0;
|
|||
static int binlog_dump_count = 0;
|
||||
#endif
|
||||
|
||||
int check_binlog_magic(IO_CACHE* log, const char** errmsg)
|
||||
{
|
||||
char magic[4];
|
||||
DBUG_ASSERT(my_b_tell(log) == 0);
|
||||
|
||||
if (my_b_read(log, (byte*) magic, sizeof(magic)))
|
||||
{
|
||||
*errmsg = "I/O error reading the header from the binary log";
|
||||
sql_print_error("%s, errno=%d, io cache code=%d", *errmsg, my_errno,
|
||||
log->error);
|
||||
return 1;
|
||||
}
|
||||
if (memcmp(magic, BINLOG_MAGIC, sizeof(magic)))
|
||||
{
|
||||
*errmsg = "Binlog has bad magic number; It's not a binary log file that can be used by this version of MySQL";
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int fake_rotate_event(NET* net, String* packet, char* log_file_name,
|
||||
const char**errmsg)
|
||||
{
|
||||
|
@ -46,7 +66,10 @@ static int fake_rotate_event(NET* net, String* packet, char* log_file_name,
|
|||
int4store(header + SERVER_ID_OFFSET, server_id);
|
||||
int4store(header + EVENT_LEN_OFFSET, event_len);
|
||||
int2store(header + FLAGS_OFFSET, 0);
|
||||
int4store(header + LOG_SEQ_OFFSET, 0);
|
||||
|
||||
// TODO: check what problems this may cause and fix them
|
||||
int4store(header + LOG_POS_OFFSET, 0);
|
||||
|
||||
packet->append(header, sizeof(header));
|
||||
/* We need to split the next statement because of problem with cxx */
|
||||
int4store(buf,4); // tell slave to skip magic number
|
||||
|
@ -133,7 +156,6 @@ File open_binlog(IO_CACHE *log, const char *log_file_name,
|
|||
const char **errmsg)
|
||||
{
|
||||
File file;
|
||||
char magic[4];
|
||||
|
||||
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,
|
||||
|
@ -142,19 +164,8 @@ File open_binlog(IO_CACHE *log, const char *log_file_name,
|
|||
*errmsg = "Could not open log file"; // This will not be sent
|
||||
goto err;
|
||||
}
|
||||
|
||||
if (my_b_read(log, (byte*) magic, sizeof(magic)))
|
||||
{
|
||||
*errmsg = "I/O error reading the header from the binary log";
|
||||
sql_print_error("%s, errno=%d, io cache code=%d", *errmsg, my_errno,
|
||||
log->error);
|
||||
if (check_binlog_magic(log,errmsg))
|
||||
goto err;
|
||||
}
|
||||
if (memcmp(magic, BINLOG_MAGIC, sizeof(magic)))
|
||||
{
|
||||
*errmsg = "Binlog has bad magic number; It's not a binary log file that can be used by this version of MySQL";
|
||||
goto err;
|
||||
}
|
||||
return file;
|
||||
|
||||
err:
|
||||
|
@ -366,7 +377,8 @@ impossible position";
|
|||
packet->length(0);
|
||||
packet->append("\0",1);
|
||||
}
|
||||
|
||||
// TODO: now that we are logging the offset, check to make sure
|
||||
// the recorded offset and the actual match
|
||||
if (error != LOG_READ_EOF)
|
||||
{
|
||||
switch(error) {
|
||||
|
@ -410,13 +422,6 @@ impossible position";
|
|||
// to signal us
|
||||
{
|
||||
log.error=0;
|
||||
|
||||
// tell the kill thread how to wake us up
|
||||
thd->mysys_var->current_mutex = log_lock;
|
||||
thd->mysys_var->current_cond = &COND_binlog_update;
|
||||
const char* proc_info = thd->proc_info;
|
||||
thd->proc_info = "Slave connection: waiting for binlog update";
|
||||
|
||||
bool read_packet = 0, fatal_error = 0;
|
||||
|
||||
#ifndef DBUG_OFF
|
||||
|
@ -431,32 +436,30 @@ impossible position";
|
|||
// no one will update the log while we are reading
|
||||
// now, but we'll be quick and just read one record
|
||||
pthread_mutex_lock(log_lock);
|
||||
switch (Log_event::read_log_event(&log, packet, (pthread_mutex_t*) 0))
|
||||
switch (Log_event::read_log_event(&log, packet, (pthread_mutex_t*)0))
|
||||
{
|
||||
case 0:
|
||||
pthread_mutex_unlock(log_lock);
|
||||
read_packet = 1;
|
||||
// we read successfully, so we'll need to send it to the
|
||||
// slave
|
||||
break;
|
||||
case LOG_READ_EOF:
|
||||
DBUG_PRINT("wait",("waiting for data on binary log"));
|
||||
DBUG_PRINT("wait",("waiting for data in binary log"));
|
||||
// wait_for_update unlocks the log lock - needed to avoid race
|
||||
if (!thd->killed)
|
||||
pthread_cond_wait(&COND_binlog_update, log_lock);
|
||||
mysql_bin_log.wait_for_update(thd);
|
||||
else
|
||||
pthread_mutex_unlock(log_lock);
|
||||
DBUG_PRINT("wait",("binary log received update"));
|
||||
break;
|
||||
|
||||
default:
|
||||
pthread_mutex_unlock(log_lock);
|
||||
fatal_error = 1;
|
||||
break;
|
||||
}
|
||||
pthread_mutex_unlock(log_lock);
|
||||
|
||||
pthread_mutex_lock(&thd->mysys_var->mutex);
|
||||
thd->mysys_var->current_mutex= 0;
|
||||
thd->mysys_var->current_cond= 0;
|
||||
thd->proc_info= proc_info;
|
||||
pthread_mutex_unlock(&thd->mysys_var->mutex);
|
||||
|
||||
|
||||
if (read_packet)
|
||||
{
|
||||
thd->proc_info = "sending update to slave";
|
||||
|
@ -548,39 +551,37 @@ impossible position";
|
|||
DBUG_VOID_RETURN;
|
||||
}
|
||||
|
||||
int start_slave(THD* thd , bool net_report)
|
||||
int start_slave(THD* thd , MASTER_INFO* mi, bool net_report)
|
||||
{
|
||||
int slave_errno = 0;
|
||||
if (!thd) thd = current_thd;
|
||||
NET* net = &thd->net;
|
||||
|
||||
int thread_mask;
|
||||
|
||||
if (check_access(thd, PROCESS_ACL, any_db))
|
||||
return 1;
|
||||
pthread_mutex_lock(&LOCK_slave);
|
||||
if (!slave_running)
|
||||
lock_slave_threads(mi); // this allows us to cleanly read slave_running
|
||||
init_thread_mask(&thread_mask,mi,1 /* inverse */);
|
||||
if (thread_mask)
|
||||
{
|
||||
if (init_master_info(&glob_mi))
|
||||
slave_errno = ER_MASTER_INFO;
|
||||
else if (server_id_supplied && *glob_mi.host)
|
||||
{
|
||||
pthread_t hThread;
|
||||
if (pthread_create(&hThread, &connection_attrib, handle_slave, 0))
|
||||
{
|
||||
slave_errno = ER_SLAVE_THREAD;
|
||||
}
|
||||
while (!slave_running) // slave might already be running by now
|
||||
pthread_cond_wait(&COND_slave_start, &LOCK_slave);
|
||||
}
|
||||
if (server_id_supplied && (!mi->inited || (mi->inited && *mi->host)))
|
||||
slave_errno = start_slave_threads(0 /*no mutex */,
|
||||
1 /* wait for start */,
|
||||
mi,
|
||||
master_info_file,relay_log_info_file,
|
||||
thread_mask);
|
||||
else
|
||||
slave_errno = ER_BAD_SLAVE;
|
||||
}
|
||||
else
|
||||
slave_errno = ER_SLAVE_MUST_STOP;
|
||||
|
||||
pthread_mutex_unlock(&LOCK_slave);
|
||||
|
||||
unlock_slave_threads(mi);
|
||||
|
||||
if (slave_errno)
|
||||
{
|
||||
if (net_report) send_error(net, slave_errno);
|
||||
if (net_report)
|
||||
send_error(net, slave_errno);
|
||||
return 1;
|
||||
}
|
||||
else if (net_report)
|
||||
|
@ -589,8 +590,7 @@ int start_slave(THD* thd , bool net_report)
|
|||
return 0;
|
||||
}
|
||||
|
||||
|
||||
int stop_slave(THD* thd, bool net_report )
|
||||
int stop_slave(THD* thd, MASTER_INFO* mi, bool net_report )
|
||||
{
|
||||
int slave_errno = 0;
|
||||
if (!thd) thd = current_thd;
|
||||
|
@ -598,32 +598,14 @@ int stop_slave(THD* thd, bool net_report )
|
|||
|
||||
if (check_access(thd, PROCESS_ACL, any_db))
|
||||
return 1;
|
||||
|
||||
pthread_mutex_lock(&LOCK_slave);
|
||||
if (slave_running)
|
||||
{
|
||||
abort_slave = 1;
|
||||
KICK_SLAVE;
|
||||
// do not abort the slave in the middle of a query, so we do not set
|
||||
// thd->killed for the slave thread
|
||||
thd->proc_info = "waiting for slave to die";
|
||||
while (slave_running)
|
||||
{
|
||||
/*
|
||||
There is a small chance that slave thread might miss the first
|
||||
alarm. To protect againts it, resend the signal until it reacts
|
||||
*/
|
||||
struct timespec abstime;
|
||||
set_timespec(abstime, 2);
|
||||
pthread_cond_timedwait(&COND_slave_stopped, &LOCK_slave, &abstime);
|
||||
if (slave_running)
|
||||
KICK_SLAVE;
|
||||
}
|
||||
}
|
||||
else
|
||||
slave_errno = ER_SLAVE_NOT_RUNNING;
|
||||
|
||||
pthread_mutex_unlock(&LOCK_slave);
|
||||
thd->proc_info = "Killing slave";
|
||||
int thread_mask;
|
||||
lock_slave_threads(mi);
|
||||
init_thread_mask(&thread_mask,mi,0 /* not inverse*/);
|
||||
slave_errno = (thread_mask) ?
|
||||
terminate_slave_threads(mi,thread_mask,
|
||||
1 /*skip lock */) : ER_SLAVE_NOT_RUNNING;
|
||||
unlock_slave_threads(mi);
|
||||
thd->proc_info = 0;
|
||||
|
||||
if (slave_errno)
|
||||
|
@ -638,31 +620,43 @@ int stop_slave(THD* thd, bool net_report )
|
|||
return 0;
|
||||
}
|
||||
|
||||
|
||||
void reset_slave()
|
||||
int reset_slave(MASTER_INFO* mi)
|
||||
{
|
||||
MY_STAT stat_area;
|
||||
char fname[FN_REFLEN];
|
||||
bool slave_was_running ;
|
||||
|
||||
pthread_mutex_lock(&LOCK_slave);
|
||||
if ((slave_was_running = slave_running))
|
||||
{
|
||||
pthread_mutex_unlock(&LOCK_slave);
|
||||
stop_slave(0,0);
|
||||
}
|
||||
else
|
||||
pthread_mutex_unlock(&LOCK_slave);
|
||||
|
||||
end_master_info(&glob_mi);
|
||||
int restart_thread_mask = 0,error=0;
|
||||
const char* errmsg=0;
|
||||
|
||||
lock_slave_threads(mi);
|
||||
init_thread_mask(&restart_thread_mask,mi,0 /* not inverse */);
|
||||
if ((error=terminate_slave_threads(mi,restart_thread_mask,1 /*skip lock*/))
|
||||
|| (error=purge_relay_logs(&mi->rli,1 /*just reset*/,&errmsg)))
|
||||
goto err;
|
||||
|
||||
end_master_info(mi);
|
||||
fn_format(fname, master_info_file, mysql_data_home, "", 4+32);
|
||||
if (my_stat(fname, &stat_area, MYF(0)) && my_delete(fname, MYF(MY_WME)))
|
||||
return;
|
||||
if (slave_was_running)
|
||||
start_slave(0,0);
|
||||
{
|
||||
error=1;
|
||||
goto err;
|
||||
}
|
||||
fn_format(fname, relay_log_info_file, mysql_data_home, "", 4+32);
|
||||
if (my_stat(fname, &stat_area, MYF(0)) && my_delete(fname, MYF(MY_WME)))
|
||||
{
|
||||
error=1;
|
||||
goto err;
|
||||
}
|
||||
if (restart_thread_mask)
|
||||
error=start_slave_threads(0 /* mutex not needed*/,
|
||||
1 /* wait for start*/,
|
||||
mi,master_info_file,relay_log_info_file,
|
||||
restart_thread_mask);
|
||||
// TODO: fix error messages so they get to the client
|
||||
err:
|
||||
unlock_slave_threads(mi);
|
||||
return error;
|
||||
}
|
||||
|
||||
|
||||
void kill_zombie_dump_threads(uint32 slave_server_id)
|
||||
{
|
||||
pthread_mutex_lock(&LOCK_thread_count);
|
||||
|
@ -681,119 +675,114 @@ void kill_zombie_dump_threads(uint32 slave_server_id)
|
|||
make safe_mutex complain and abort.
|
||||
We just to do kill the thread ourselves.
|
||||
*/
|
||||
|
||||
thr_alarm_kill(tmp->real_id);
|
||||
tmp->killed = 1;
|
||||
tmp->mysys_var->abort = 1;
|
||||
pthread_mutex_lock(&tmp->mysys_var->mutex);
|
||||
if (tmp->mysys_var->current_cond)
|
||||
{
|
||||
pthread_mutex_lock(tmp->mysys_var->current_mutex);
|
||||
pthread_cond_broadcast(tmp->mysys_var->current_cond);
|
||||
pthread_mutex_unlock(tmp->mysys_var->current_mutex);
|
||||
}
|
||||
pthread_mutex_unlock(&tmp->mysys_var->mutex);
|
||||
tmp->awake(1/*prepare to die*/);
|
||||
}
|
||||
}
|
||||
pthread_mutex_unlock(&LOCK_thread_count);
|
||||
}
|
||||
|
||||
|
||||
int change_master(THD* thd)
|
||||
int change_master(THD* thd, MASTER_INFO* mi)
|
||||
{
|
||||
bool slave_was_running;
|
||||
int error=0,restart_thread_mask;
|
||||
const char* errmsg=0;
|
||||
|
||||
// kill slave thread
|
||||
pthread_mutex_lock(&LOCK_slave);
|
||||
if ((slave_was_running = slave_running))
|
||||
lock_slave_threads(mi);
|
||||
init_thread_mask(&restart_thread_mask,mi,0 /*not inverse*/);
|
||||
if (restart_thread_mask &&
|
||||
(error=terminate_slave_threads(mi,
|
||||
restart_thread_mask,
|
||||
1 /*skip lock*/)))
|
||||
{
|
||||
abort_slave = 1;
|
||||
KICK_SLAVE;
|
||||
thd->proc_info = "waiting for slave to die";
|
||||
while (slave_running)
|
||||
pthread_cond_wait(&COND_slave_stopped, &LOCK_slave); // wait until done
|
||||
send_error(&thd->net,error);
|
||||
unlock_slave_threads(mi);
|
||||
return 1;
|
||||
}
|
||||
pthread_mutex_unlock(&LOCK_slave);
|
||||
thd->proc_info = "changing master";
|
||||
LEX_MASTER_INFO* lex_mi = &thd->lex.mi;
|
||||
|
||||
if (init_master_info(&glob_mi))
|
||||
// TODO: see if needs re-write
|
||||
if (init_master_info(mi,master_info_file,relay_log_info_file))
|
||||
{
|
||||
send_error(&thd->net, 0, "Could not initialize master info");
|
||||
unlock_slave_threads(mi);
|
||||
return 1;
|
||||
}
|
||||
|
||||
pthread_mutex_lock(&glob_mi.lock);
|
||||
pthread_mutex_lock(&mi->data_lock);
|
||||
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
|
||||
glob_mi.log_file_name[0] = 0;
|
||||
glob_mi.pos = 4; // skip magic number
|
||||
glob_mi.pending = 0;
|
||||
mi->master_log_name[0] = 0;
|
||||
mi->master_log_pos = 4; // skip magic number
|
||||
mi->rli.pending = 0;
|
||||
}
|
||||
|
||||
if (lex_mi->log_file_name)
|
||||
strmake(glob_mi.log_file_name, lex_mi->log_file_name,
|
||||
sizeof(glob_mi.log_file_name));
|
||||
strmake(mi->master_log_name, lex_mi->log_file_name,
|
||||
sizeof(mi->master_log_name));
|
||||
if (lex_mi->pos)
|
||||
{
|
||||
glob_mi.pos = lex_mi->pos;
|
||||
glob_mi.pending = 0;
|
||||
mi->master_log_pos = lex_mi->pos;
|
||||
mi->rli.pending = 0;
|
||||
}
|
||||
|
||||
if (lex_mi->host)
|
||||
strmake(glob_mi.host, lex_mi->host, sizeof(glob_mi.host));
|
||||
strmake(mi->host, lex_mi->host, sizeof(mi->host));
|
||||
if (lex_mi->user)
|
||||
strmake(glob_mi.user, lex_mi->user, sizeof(glob_mi.user));
|
||||
strmake(mi->user, lex_mi->user, sizeof(mi->user));
|
||||
if (lex_mi->password)
|
||||
strmake(glob_mi.password, lex_mi->password, sizeof(glob_mi.password));
|
||||
strmake(mi->password, lex_mi->password, sizeof(mi->password));
|
||||
if (lex_mi->port)
|
||||
glob_mi.port = lex_mi->port;
|
||||
mi->port = lex_mi->port;
|
||||
if (lex_mi->connect_retry)
|
||||
glob_mi.connect_retry = lex_mi->connect_retry;
|
||||
mi->connect_retry = lex_mi->connect_retry;
|
||||
|
||||
flush_master_info(mi);
|
||||
pthread_mutex_unlock(&mi->data_lock);
|
||||
thd->proc_info="purging old relay logs";
|
||||
if (purge_relay_logs(&mi->rli,0 /* not only reset, but also reinit*/,
|
||||
&errmsg))
|
||||
{
|
||||
send_error(&thd->net, 0, "Failed purging old relay logs");
|
||||
unlock_slave_threads(mi);
|
||||
return 1;
|
||||
}
|
||||
pthread_mutex_lock(&mi->rli.data_lock);
|
||||
mi->rli.master_log_pos = mi->master_log_pos;
|
||||
strnmov(mi->rli.master_log_name,mi->master_log_name,
|
||||
sizeof(mi->rli.master_log_name));
|
||||
if (!mi->rli.master_log_name[0]) // uninitialized case
|
||||
mi->rli.master_log_pos=0;
|
||||
pthread_cond_broadcast(&mi->rli.data_cond);
|
||||
pthread_mutex_unlock(&mi->rli.data_lock);
|
||||
|
||||
flush_master_info(&glob_mi);
|
||||
pthread_mutex_unlock(&glob_mi.lock);
|
||||
thd->proc_info = "starting slave";
|
||||
if (slave_was_running)
|
||||
start_slave(0,0);
|
||||
if (restart_thread_mask)
|
||||
error=start_slave_threads(0 /* mutex not needed*/,
|
||||
1 /* wait for start*/,
|
||||
mi,master_info_file,relay_log_info_file,
|
||||
restart_thread_mask);
|
||||
err:
|
||||
unlock_slave_threads(mi);
|
||||
thd->proc_info = 0;
|
||||
|
||||
send_ok(&thd->net);
|
||||
if (error)
|
||||
send_error(&thd->net,error);
|
||||
else
|
||||
send_ok(&thd->net);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
void reset_master()
|
||||
int reset_master(THD* thd)
|
||||
{
|
||||
if (!mysql_bin_log.is_open())
|
||||
{
|
||||
my_error(ER_FLUSH_MASTER_BINLOG_CLOSED, MYF(ME_BELL+ME_WAITTANG));
|
||||
return;
|
||||
return 1;
|
||||
}
|
||||
|
||||
LOG_INFO linfo;
|
||||
pthread_mutex_t* log_lock = mysql_bin_log.get_log_lock();
|
||||
pthread_mutex_lock(log_lock);
|
||||
if (mysql_bin_log.find_first_log(&linfo, ""))
|
||||
{
|
||||
pthread_mutex_unlock(log_lock);
|
||||
return;
|
||||
}
|
||||
|
||||
for(;;)
|
||||
{
|
||||
my_delete(linfo.log_file_name, MYF(MY_WME));
|
||||
if (mysql_bin_log.find_next_log(&linfo))
|
||||
break;
|
||||
}
|
||||
mysql_bin_log.close(1); // exiting close
|
||||
my_delete(mysql_bin_log.get_index_fname(), MYF(MY_WME));
|
||||
mysql_bin_log.set_need_start_event();
|
||||
mysql_bin_log.open(opt_bin_logname,LOG_BIN);
|
||||
pthread_mutex_unlock(log_lock);
|
||||
return mysql_bin_log.reset_logs(thd);
|
||||
}
|
||||
|
||||
|
||||
int cmp_master_pos(const char* log_file_name1, ulonglong log_pos1,
|
||||
const char* log_file_name2, ulonglong log_pos2)
|
||||
{
|
||||
|
@ -880,6 +869,7 @@ int show_binlog_events(THD* thd)
|
|||
if (event_count < limit_end && log.error)
|
||||
{
|
||||
errmsg = "Wrong offset or I/O error";
|
||||
pthread_mutex_unlock(mysql_bin_log.get_log_lock());
|
||||
goto err;
|
||||
}
|
||||
|
||||
|
@ -1012,11 +1002,11 @@ err:
|
|||
int log_loaded_block(IO_CACHE* file)
|
||||
{
|
||||
LOAD_FILE_INFO* lf_info;
|
||||
ulong block_len ;
|
||||
uint block_len ;
|
||||
|
||||
/* file->request_pos contains position where we started last read */
|
||||
byte *buffer = file->request_pos;
|
||||
if (!(block_len = (ulong) (file->read_end - buffer)))
|
||||
char* buffer = (char*) file->request_pos;
|
||||
if (!(block_len = file->read_end - buffer))
|
||||
return 0;
|
||||
lf_info = (LOAD_FILE_INFO*)file->arg;
|
||||
if (lf_info->last_pos_in_file != HA_POS_ERROR &&
|
||||
|
@ -1025,14 +1015,14 @@ int log_loaded_block(IO_CACHE* file)
|
|||
lf_info->last_pos_in_file = file->pos_in_file;
|
||||
if (lf_info->wrote_create_file)
|
||||
{
|
||||
Append_block_log_event a(lf_info->thd, (char*) buffer, block_len);
|
||||
Append_block_log_event a(lf_info->thd, buffer, block_len);
|
||||
mysql_bin_log.write(&a);
|
||||
}
|
||||
else
|
||||
{
|
||||
Create_file_log_event c(lf_info->thd,lf_info->ex,lf_info->db,
|
||||
lf_info->table_name, *lf_info->fields,
|
||||
lf_info->handle_dup, (char*) buffer,
|
||||
lf_info->handle_dup, buffer,
|
||||
block_len);
|
||||
mysql_bin_log.write(&c);
|
||||
lf_info->wrote_create_file = 1;
|
||||
|
@ -1040,3 +1030,5 @@ int log_loaded_block(IO_CACHE* file)
|
|||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -26,30 +26,26 @@ extern int max_binlog_dump_events;
|
|||
extern bool opt_sporadic_binlog_dump_fail;
|
||||
#endif
|
||||
|
||||
#ifdef SIGNAL_WITH_VIO_CLOSE
|
||||
#define KICK_SLAVE { slave_thd->close_active_vio(); \
|
||||
thr_alarm_kill(slave_real_id); }
|
||||
#else
|
||||
#define KICK_SLAVE thr_alarm_kill(slave_real_id);
|
||||
#endif
|
||||
#define KICK_SLAVE(thd) thd->awake(0 /* do not prepare to die*/);
|
||||
|
||||
File open_binlog(IO_CACHE *log, const char *log_file_name,
|
||||
const char **errmsg);
|
||||
|
||||
int start_slave(THD* thd = 0, bool net_report = 1);
|
||||
int stop_slave(THD* thd = 0, bool net_report = 1);
|
||||
int change_master(THD* thd);
|
||||
int start_slave(THD* thd, MASTER_INFO* mi, bool net_report);
|
||||
int stop_slave(THD* thd, MASTER_INFO* mi, bool net_report);
|
||||
int change_master(THD* thd, MASTER_INFO* mi);
|
||||
int show_binlog_events(THD* thd);
|
||||
int cmp_master_pos(const char* log_file_name1, ulonglong log_pos1,
|
||||
const char* log_file_name2, ulonglong log_pos2);
|
||||
void reset_slave();
|
||||
void reset_master();
|
||||
int reset_slave(MASTER_INFO* mi);
|
||||
int reset_master(THD* thd);
|
||||
int purge_master_logs(THD* thd, const char* to_log);
|
||||
bool log_in_use(const char* log_name);
|
||||
void adjust_linfo_offsets(my_off_t purge_offset);
|
||||
int show_binlogs(THD* thd);
|
||||
extern int init_master_info(MASTER_INFO* mi);
|
||||
void kill_zombie_dump_threads(uint32 slave_server_id);
|
||||
int check_binlog_magic(IO_CACHE* log, const char** errmsg);
|
||||
|
||||
typedef struct st_load_file_info
|
||||
{
|
||||
|
|
|
@ -1177,6 +1177,15 @@ int mysqld_show(THD *thd, const char *wild, show_var_st *variables)
|
|||
case SHOW_RPL_STATUS:
|
||||
net_store_data(&packet2, rpl_status_type[(int)rpl_status]);
|
||||
break;
|
||||
case SHOW_SLAVE_RUNNING:
|
||||
{
|
||||
LOCK_ACTIVE_MI;
|
||||
net_store_data(&packet2, (active_mi->slave_running &&
|
||||
active_mi->rli.slave_running)
|
||||
? "ON" : "OFF");
|
||||
UNLOCK_ACTIVE_MI;
|
||||
break;
|
||||
}
|
||||
case SHOW_OPENTABLES:
|
||||
net_store_data(&packet2,(uint32) cached_tables());
|
||||
break;
|
||||
|
|
|
@ -2530,17 +2530,15 @@ show_param:
|
|||
YYABORT;
|
||||
}
|
||||
| NEW_SYM MASTER_SYM FOR_SYM SLAVE WITH MASTER_LOG_FILE_SYM EQ
|
||||
TEXT_STRING AND MASTER_LOG_POS_SYM EQ ulonglong_num AND
|
||||
MASTER_LOG_SEQ_SYM EQ ULONG_NUM AND MASTER_SERVER_ID_SYM EQ
|
||||
TEXT_STRING AND MASTER_LOG_POS_SYM EQ ulonglong_num
|
||||
AND MASTER_SERVER_ID_SYM EQ
|
||||
ULONG_NUM
|
||||
{
|
||||
LEX *lex=Lex;
|
||||
lex->sql_command = SQLCOM_SHOW_NEW_MASTER;
|
||||
lex->mi.log_file_name = $8.str;
|
||||
lex->mi.pos = $12;
|
||||
lex->mi.last_log_seq = $16;
|
||||
lex->mi.server_id = $20;
|
||||
}
|
||||
{
|
||||
Lex->sql_command = SQLCOM_SHOW_NEW_MASTER;
|
||||
Lex->mi.log_file_name = $8.str;
|
||||
Lex->mi.pos = $12;
|
||||
Lex->mi.server_id = $16;
|
||||
}
|
||||
| MASTER_SYM LOGS_SYM
|
||||
{
|
||||
Lex->sql_command = SQLCOM_SHOW_BINLOGS;
|
||||
|
@ -3176,12 +3174,18 @@ option_value:
|
|||
}
|
||||
| SQL_SLAVE_SKIP_COUNTER equal ULONG_NUM
|
||||
{
|
||||
pthread_mutex_lock(&LOCK_slave);
|
||||
if (slave_running)
|
||||
LOCK_ACTIVE_MI;
|
||||
pthread_mutex_lock(&active_mi->rli.run_lock);
|
||||
if (active_mi->rli.slave_running)
|
||||
send_error(¤t_thd->net, ER_SLAVE_MUST_STOP);
|
||||
else
|
||||
slave_skip_counter = $3;
|
||||
pthread_mutex_unlock(&LOCK_slave);
|
||||
{
|
||||
pthread_mutex_lock(&active_mi->rli.data_lock);
|
||||
active_mi->rli.slave_skip_counter = $3;
|
||||
pthread_mutex_unlock(&active_mi->rli.data_lock);
|
||||
}
|
||||
pthread_mutex_unlock(&active_mi->rli.run_lock);
|
||||
UNLOCK_ACTIVE_MI;
|
||||
}
|
||||
| ident equal DEFAULT
|
||||
{
|
||||
|
|
|
@ -123,7 +123,7 @@ terribly wrong...\n");
|
|||
}
|
||||
#endif /* __alpha__ */
|
||||
|
||||
if (!stack_bottom)
|
||||
if (!stack_bottom || (gptr) stack_bottom > (gptr) &fp)
|
||||
{
|
||||
ulong tmp= min(0x10000,thread_stack);
|
||||
/* Assume that the stack starts at the previous even 65K */
|
||||
|
|
|
@ -140,7 +140,7 @@ enum SHOW_TYPE { SHOW_LONG,SHOW_CHAR,SHOW_INT,SHOW_CHAR_PTR,SHOW_BOOL,
|
|||
,SHOW_SSL_CTX_SESS_TIMEOUTS, SHOW_SSL_CTX_SESS_CACHE_FULL
|
||||
,SHOW_SSL_GET_CIPHER_LIST
|
||||
#endif /* HAVE_OPENSSL */
|
||||
,SHOW_RPL_STATUS
|
||||
,SHOW_RPL_STATUS, SHOW_SLAVE_RUNNING
|
||||
};
|
||||
|
||||
enum SHOW_COMP_OPTION { SHOW_OPTION_YES, SHOW_OPTION_NO, SHOW_OPTION_DISABLED};
|
||||
|
|
9
support-files/build-tags
Executable file
9
support-files/build-tags
Executable file
|
@ -0,0 +1,9 @@
|
|||
#! /bin/sh
|
||||
|
||||
rm -f TAGS
|
||||
filter='\.cc$\|\.c$\|\.h$\|\.yy$'
|
||||
files=`bk -r sfiles -gU | grep $filter `
|
||||
for f in $files ;
|
||||
do
|
||||
etags -o TAGS --append $f
|
||||
done
|
Loading…
Reference in a new issue