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:
unknown 2002-01-19 22:46:25 -07:00
commit 1e0f2b7a42
39 changed files with 2998 additions and 1568 deletions

View file

@ -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

View file

@ -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

View file

@ -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)

View file

@ -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)))
{

View file

@ -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

View file

@ -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);

View file

@ -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(*)

View file

@ -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
View 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

View file

@ -0,0 +1 @@
-O max_binlog_size=2048

View file

@ -1 +1,2 @@
rm -f $MYSQL_TEST_DIR/var/slave-data/master.info
rm -f $MYSQL_TEST_DIR/var/slave-data/*relay*

View file

@ -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

View file

@ -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;

View file

@ -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);
}
}

View file

@ -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 */

View file

@ -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();
}

View file

@ -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;
}

View file

@ -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},

View file

@ -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);

File diff suppressed because it is too large Load diff

View file

@ -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

View file

@ -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");

View file

@ -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

View file

@ -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;

View file

@ -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;

View file

@ -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);

File diff suppressed because it is too large Load diff

View file

@ -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

View file

@ -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);

View file

@ -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)
{

View file

@ -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;

View file

@ -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

View file

@ -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;
}

View file

@ -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
{

View file

@ -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;

View file

@ -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(&current_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
{

View file

@ -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 */

View file

@ -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
View 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