Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
M
MariaDB
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Analytics
Analytics
CI / CD
Repository
Value Stream
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
nexedi
MariaDB
Commits
26a1d888
Commit
26a1d888
authored
Oct 31, 2002
by
peter@mysql.com
Browse files
Options
Browse Files
Download
Plain Diff
Merge mysql.com:/home/pz/mysql/mysql-4.1-root
into mysql.com:/home/pz/mysql/mysql-4.1
parents
cc18dc72
9e3f16df
Changes
15
Hide whitespace changes
Inline
Side-by-side
Showing
15 changed files
with
1994 additions
and
1096 deletions
+1994
-1096
.bzrignore
.bzrignore
+13
-10
BitKeeper/etc/config
BitKeeper/etc/config
+1
-0
include/thr_lock.h
include/thr_lock.h
+4
-0
mysql-test/r/derived.result
mysql-test/r/derived.result
+6
-0
mysql-test/std_data/master-bin.001
mysql-test/std_data/master-bin.001
+0
-0
mysql-test/t/derived.test
mysql-test/t/derived.test
+2
-0
mysys/thr_lock.c
mysys/thr_lock.c
+4
-4
sql/lock.cc
sql/lock.cc
+11
-0
sql/log_event.cc
sql/log_event.cc
+1647
-1030
sql/log_event.h
sql/log_event.h
+97
-10
sql/sql_derived.cc
sql/sql_derived.cc
+2
-1
sql/sql_parse.cc
sql/sql_parse.cc
+7
-3
sql/sql_test.cc
sql/sql_test.cc
+111
-18
sql/sql_yacc.yy
sql/sql_yacc.yy
+0
-14
strings/longlong2str-x86.s
strings/longlong2str-x86.s
+89
-6
No files found.
.bzrignore
View file @
26a1d888
...
...
@@ -75,6 +75,7 @@ Makefile.in'
PENDING/*
TAGS
aclocal.m4
autom4te.cache/*
bdb/README
bdb/btree/btree_auto.c
bdb/build_unix/*
...
...
@@ -192,6 +193,7 @@ config.h.in
config.log
config.status
configure
configure.lineno
core
db-*.*.*
dbug/user.t
...
...
@@ -209,10 +211,13 @@ include/my_config.h
include/my_global.h
include/mysql_version.h
include/widec.h
innobase/autom4te.cache/*
innobase/configure.lineno
innobase/conftest.s1
innobase/conftest.subs
innobase/ib_config.h
innobase/ib_config.h.in
innobase/stamp-h1
isam/isamchk
isam/isamlog
isam/pack_isam
...
...
@@ -302,6 +307,7 @@ libmysqld/sql_db.cc
libmysqld/sql_delete.cc
libmysqld/sql_do.cc
libmysqld/sql_handler.cc
libmysqld/sql_help.cc
libmysqld/sql_insert.cc
libmysqld/sql_lex.cc
libmysqld/sql_list.cc
...
...
@@ -361,6 +367,8 @@ myisam/myisamchk
myisam/myisamlog
myisam/myisampack
myisam/rt_test
myisam/rt_test.MYD
myisam/rt_test.MYI
myisam/sp_test
myisam/test1.MYD
myisam/test1.MYI
...
...
@@ -405,6 +413,8 @@ repl-tests/test-repl/foo-dump-slave.master.
repl-tests/test-repl/sum-wlen-slave.master.
repl-tests/test-repl/sum-wlen-slave.master.re
repl-tests/test-repl/sum-wlen-slave.master.reje
scripts/fill_func_tables
scripts/fill_func_tables.sql
scripts/make_binary_distribution
scripts/msql2mysql
scripts/mysql_config
...
...
@@ -474,8 +484,11 @@ sql/sql_select.cc.orig
sql/sql_yacc.cc
sql/sql_yacc.h
sql/sql_yacc.yy.orig
sql_error.cc
sql_prepare.cc
stamp-h
stamp-h.in
stamp-h1
strings/conf_to_src
strings/ctype_autoconf.c
strings/ctype_extra_sources.c
...
...
@@ -503,13 +516,3 @@ vio/test-ssl
vio/test-sslclient
vio/test-sslserver
vio/viotest-ssl
sql_error.cc
sql_prepare.cc
autom4te.cache/*
innobase/autom4te.cache/*
configure.lineno
innobase/configure.lineno
innobase/stamp-h1
myisam/rt_test.MYD
myisam/rt_test.MYI
stamp-h1
BitKeeper/etc/config
View file @
26a1d888
...
...
@@ -69,4 +69,5 @@ pager:
hours:
[serg:]checkout:get
[arjen:]checkout:get
[nick:]checkout:get
checkout:edit
include/thr_lock.h
View file @
26a1d888
...
...
@@ -74,6 +74,7 @@ typedef struct st_thr_lock_data {
enum
thr_lock_type
type
;
ulong
thread_id
;
void
*
status_param
;
/* Param to status functions */
void
*
debug_print_param
;
}
THR_LOCK_DATA
;
struct
st_lock_list
{
...
...
@@ -97,6 +98,9 @@ typedef struct st_thr_lock {
}
THR_LOCK
;
extern
LIST
*
thr_lock_thread_list
;
extern
pthread_mutex_t
THR_LOCK_lock
;
my_bool
init_thr_lock
(
void
);
/* Must be called once/thread */
void
thr_lock_init
(
THR_LOCK
*
lock
);
void
thr_lock_delete
(
THR_LOCK
*
lock
);
...
...
mysql-test/r/derived.result
View file @
26a1d888
...
...
@@ -18,3 +18,9 @@ a y
3 3
3 3
drop table if exists t1.t2,t3;
select * from (select 1);
1
1
select a from (select 1 as a);
a
1
mysql-test/std_data/master-bin.001
deleted
100644 → 0
View file @
cc18dc72
File deleted
mysql-test/t/derived.test
View file @
26a1d888
...
...
@@ -9,3 +9,5 @@ CREATE TABLE t3 (a int not null, b char (10) not null);
insert
into
t3
values
(
3
,
'f'
),(
4
,
'y'
),(
5
,
'z'
),(
6
,
'c'
);
select
t1
.
a
,
t4
.
y
from
t1
,(
select
t2
.
a
as
y
from
t2
,(
select
t3
.
b
from
t3
where
t3
.
a
>
3
)
as
t5
where
t2
.
b
=
t5
.
b
)
as
t4
where
t1
.
a
=
t4
.
y
;
drop
table
if
exists
t1
.
t2
,
t3
;
select
*
from
(
select
1
);
select
a
from
(
select
1
as
a
);
mysys/thr_lock.c
View file @
26a1d888
...
...
@@ -91,7 +91,7 @@ enum thr_lock_type thr_upgraded_concurrent_insert_lock = TL_WRITE;
#define MAX_LOCKS 100
static
LIST
*
thread_list
;
/* List of threads in use */
LIST
*
thr_lock_
thread_list
;
/* List of threads in use */
ulong
max_write_lock_count
=
~
(
ulong
)
0L
;
static
inline
pthread_cond_t
*
get_cond
(
void
)
...
...
@@ -307,7 +307,7 @@ void thr_lock_init(THR_LOCK *lock)
pthread_mutex_lock
(
&
THR_LOCK_lock
);
/* Add to locks in use */
lock
->
list
.
data
=
(
void
*
)
lock
;
thr
ead_list
=
list_add
(
thread_list
,
&
lock
->
list
);
thr
_lock_thread_list
=
list_add
(
thr_lock_
thread_list
,
&
lock
->
list
);
pthread_mutex_unlock
(
&
THR_LOCK_lock
);
DBUG_VOID_RETURN
;
}
...
...
@@ -318,7 +318,7 @@ void thr_lock_delete(THR_LOCK *lock)
DBUG_ENTER
(
"thr_lock_delete"
);
VOID
(
pthread_mutex_destroy
(
&
lock
->
mutex
));
pthread_mutex_lock
(
&
THR_LOCK_lock
);
thr
ead_list
=
list_delete
(
thread_list
,
&
lock
->
list
);
thr
_lock_thread_list
=
list_delete
(
thr_lock_
thread_list
,
&
lock
->
list
);
pthread_mutex_unlock
(
&
THR_LOCK_lock
);
DBUG_VOID_RETURN
;
}
...
...
@@ -1061,7 +1061,7 @@ void thr_print_locks(void)
pthread_mutex_lock
(
&
THR_LOCK_lock
);
puts
(
"Current locks:"
);
for
(
list
=
thread_list
;
list
&&
count
++
<
MAX_THREADS
;
list
=
rest
(
list
))
for
(
list
=
thr
_lock_thr
ead_list
;
list
&&
count
++
<
MAX_THREADS
;
list
=
rest
(
list
))
{
THR_LOCK
*
lock
=
(
THR_LOCK
*
)
list
->
data
;
VOID
(
pthread_mutex_lock
(
&
lock
->
mutex
));
...
...
sql/lock.cc
View file @
26a1d888
...
...
@@ -69,6 +69,12 @@
#include "mysql_priv.h"
#include <hash.h>
#include <assert.h>
#include <ha_myisammrg.h>
#ifndef MASTER
#include "../srclib/myisammrg/myrg_def.h"
#else
#include "../myisammrg/myrg_def.h"
#endif
extern
HASH
open_cache
;
...
...
@@ -154,6 +160,7 @@ MYSQL_LOCK *mysql_lock_tables(THD *thd,TABLE **tables,uint count)
sql_lock
=
0
;
}
}
thd
->
lock_time
();
DBUG_RETURN
(
sql_lock
);
}
...
...
@@ -410,8 +417,12 @@ static MYSQL_LOCK *get_lock_data(THD *thd, TABLE **table_ptr, uint count,
return
0
;
}
}
THR_LOCK_DATA
**
org_locks
=
locks
;
locks
=
table
->
file
->
store_lock
(
thd
,
locks
,
get_old_locks
?
TL_IGNORE
:
lock_type
);
if
(
locks
)
for
(
;
org_locks
!=
locks
;
org_locks
++
)
(
*
org_locks
)
->
debug_print_param
=
(
void
*
)
table
;
}
return
sql_lock
;
}
...
...
sql/log_event.cc
View file @
26a1d888
...
...
@@ -26,6 +26,11 @@
#include <assert.h>
/*****************************************************************************
my_b_safe_write()
****************************************************************************/
inline
int
my_b_safe_write
(
IO_CACHE
*
file
,
const
byte
*
buf
,
int
len
)
{
...
...
@@ -40,6 +45,11 @@ inline int my_b_safe_write(IO_CACHE* file, const byte *buf,
return
my_b_write
(
file
,
buf
,
len
);
}
/*****************************************************************************
pretty_print_str()
****************************************************************************/
#ifdef MYSQL_CLIENT
static
void
pretty_print_str
(
FILE
*
file
,
char
*
str
,
int
len
)
{
...
...
@@ -63,16 +73,26 @@ static void pretty_print_str(FILE* file, char* str, int len)
}
fputc
(
'\''
,
file
);
}
#endif
#endif
// MYSQL_CLIENT
#ifndef MYSQL_CLIENT
/*****************************************************************************
ignored_error_code()
****************************************************************************/
#ifndef MYSQL_CLIENT
inline
int
ignored_error_code
(
int
err_code
)
{
return
use_slave_mask
&&
bitmap_is_set
(
&
slave_error_mask
,
err_code
);
}
#endif // !MYSQL_CLIENT
/*****************************************************************************
pretty_print_str()
****************************************************************************/
#ifndef MYSQL_CLIENT
static
void
pretty_print_str
(
String
*
packet
,
char
*
str
,
int
len
)
{
char
*
end
=
str
+
len
;
...
...
@@ -95,8 +115,14 @@ static void pretty_print_str(String* packet, char* str, int len)
}
packet
->
append
(
'\''
);
}
#endif // !MYSQL_CLIENT
/*****************************************************************************
slave_load_file_stem()
****************************************************************************/
#ifndef MYSQL_CLIENT
static
inline
char
*
slave_load_file_stem
(
char
*
buf
,
uint
file_id
,
int
event_server_id
)
{
...
...
@@ -108,9 +134,81 @@ static inline char* slave_load_file_stem(char*buf, uint file_id,
*
buf
++
=
'-'
;
return
int10_to_str
(
file_id
,
buf
,
10
);
}
#endif // !MYSQL_CLIENT
#endif
/*****************************************************************************
cleanup_load_tmpdir()
Delete all temporary files used for SQL_LOAD.
TODO
- When we get a 'server start' event, we should only remove
the files associated with the server id that just started.
Easily fixable by adding server_id as a prefix to the log files.
****************************************************************************/
#ifndef MYSQL_CLIENT
static
void
cleanup_load_tmpdir
()
{
MY_DIR
*
dirp
;
FILEINFO
*
file
;
uint
i
;
if
(
!
(
dirp
=
my_dir
(
slave_load_tmpdir
,
MYF
(
MY_WME
))))
return
;
for
(
i
=
0
;
i
<
(
uint
)
dirp
->
number_off_files
;
i
++
)
{
file
=
dirp
->
dir_entry
+
i
;
if
(
is_prefix
(
file
->
name
,
"SQL_LOAD-"
))
my_delete
(
file
->
name
,
MYF
(
0
));
}
my_dirend
(
dirp
);
}
#endif // !MYSQL_CLIENT
/*****************************************************************************
write_str()
****************************************************************************/
static
bool
write_str
(
IO_CACHE
*
file
,
char
*
str
,
byte
length
)
{
return
(
my_b_safe_write
(
file
,
&
length
,
1
)
||
my_b_safe_write
(
file
,
(
byte
*
)
str
,
(
int
)
length
));
}
/*****************************************************************************
read_str()
****************************************************************************/
static
inline
int
read_str
(
char
*
&
buf
,
char
*
buf_end
,
char
*
&
str
,
uint8
&
len
)
{
if
(
buf
+
(
uint
)
(
uchar
)
*
buf
>=
buf_end
)
return
1
;
len
=
(
uint8
)
*
buf
;
str
=
buf
+
1
;
buf
+=
(
uint
)
len
+
1
;
return
0
;
}
/*****************************************************************************
*****************************************************************************
Log_event methods
*****************************************************************************
****************************************************************************/
/*****************************************************************************
Log_event::get_type_str()
****************************************************************************/
const
char
*
Log_event
::
get_type_str
()
{
switch
(
get_type_code
())
{
...
...
@@ -131,6 +229,11 @@ const char* Log_event::get_type_str()
}
}
/*****************************************************************************
Log_event::Log_event()
****************************************************************************/
#ifndef MYSQL_CLIENT
Log_event
::
Log_event
(
THD
*
thd_arg
,
uint16
flags_arg
)
:
exec_time
(
0
),
flags
(
flags_arg
),
cached_event_len
(
0
),
...
...
@@ -139,46 +242,23 @@ Log_event::Log_event(THD* thd_arg, uint16 flags_arg)
if
(
thd
)
{
server_id
=
thd
->
server_id
;
when
=
thd
->
start_time
;
log_pos
=
thd
->
log_pos
;
when
=
thd
->
start_time
;
log_pos
=
thd
->
log_pos
;
}
else
{
server_id
=
::
server_id
;
when
=
time
(
NULL
);
log_pos
=
0
;
when
=
time
(
NULL
);
log_pos
=
0
;
}
}
#endif // !MYSQL_CLIENT
/*
Delete all temporary files used for SQL_LOAD.
TODO
- When we get a 'server start' event, we should only remove
the files associated with the server id that just started.
Easily fixable by adding server_id as a prefix to the log files.
*/
static
void
cleanup_load_tmpdir
()
{
MY_DIR
*
dirp
;
FILEINFO
*
file
;
uint
i
;
if
(
!
(
dirp
=
my_dir
(
slave_load_tmpdir
,
MYF
(
MY_WME
))))
return
;
for
(
i
=
0
;
i
<
(
uint
)
dirp
->
number_off_files
;
i
++
)
{
file
=
dirp
->
dir_entry
+
i
;
if
(
is_prefix
(
file
->
name
,
"SQL_LOAD-"
))
my_delete
(
file
->
name
,
MYF
(
0
));
}
my_dirend
(
dirp
);
}
/*****************************************************************************
#endif
Log_event::Log_event()
****************************************************************************/
Log_event
::
Log_event
(
const
char
*
buf
,
bool
old_format
)
:
cached_event_len
(
0
),
temp_buf
(
0
)
{
...
...
@@ -202,6 +282,11 @@ Log_event::Log_event(const char* buf, bool old_format)
#ifndef MYSQL_CLIENT
/*****************************************************************************
Log_event::exec_event()
****************************************************************************/
int
Log_event
::
exec_event
(
struct
st_relay_log_info
*
rli
)
{
if
(
rli
)
// QQ When is this not true ?
...
...
@@ -213,219 +298,73 @@ int Log_event::exec_event(struct st_relay_log_info* rli)
return
0
;
}
/*****************************************************************************
Log_event::pack_info()
****************************************************************************/
void
Log_event
::
pack_info
(
String
*
packet
)
{
net_store_data
(
packet
,
""
,
0
);
}
void
Query_log_event
::
pack_info
(
String
*
packet
)
{
char
buf
[
256
];
String
tmp
(
buf
,
sizeof
(
buf
),
system_charset_info
);
tmp
.
length
(
0
);
if
(
db
&&
db_len
)
{
tmp
.
append
(
"use `"
,
5
);
tmp
.
append
(
db
,
db_len
);
tmp
.
append
(
"`; "
,
3
);
}
/*****************************************************************************
if
(
query
&&
q_len
)
tmp
.
append
(
query
,
q_len
);
net_store_data
(
packet
,
(
char
*
)
tmp
.
ptr
(),
tmp
.
length
());
}
Log_event::init_show_field_list()
void
Start_log_event
::
pack_info
(
String
*
packet
)
****************************************************************************/
void
Log_event
::
init_show_field_list
(
List
<
Item
>*
field_list
)
{
char
buf1
[
256
];
String
tmp
(
buf1
,
sizeof
(
buf1
),
system_charset_info
);
tmp
.
length
(
0
);
char
buf
[
22
];
tmp
.
append
(
"Server ver: "
);
tmp
.
append
(
server_version
);
tmp
.
append
(
", Binlog ver: "
);
tmp
.
append
(
llstr
(
binlog_version
,
buf
));
net_store_data
(
packet
,
tmp
.
ptr
(),
tmp
.
length
());
field_list
->
push_back
(
new
Item_empty_string
(
"Log_name"
,
20
));
field_list
->
push_back
(
new
Item_empty_string
(
"Pos"
,
20
));
field_list
->
push_back
(
new
Item_empty_string
(
"Event_type"
,
20
));
field_list
->
push_back
(
new
Item_empty_string
(
"Server_id"
,
20
));
field_list
->
push_back
(
new
Item_empty_string
(
"Orig_log_pos"
,
20
));
field_list
->
push_back
(
new
Item_empty_string
(
"Info"
,
20
));
}
void
Load_log_event
::
pack_info
(
String
*
packet
)
{
char
buf
[
256
];
String
tmp
(
buf
,
sizeof
(
buf
),
system_charset_info
);
tmp
.
length
(
0
);
if
(
db
&&
db_len
)
{
tmp
.
append
(
"use "
);
tmp
.
append
(
db
,
db_len
);
tmp
.
append
(
"; "
,
2
);
}
/*****************************************************************************
tmp
.
append
(
"LOAD DATA INFILE '"
);
tmp
.
append
(
fname
,
fname_len
);
tmp
.
append
(
"' "
,
2
);
if
(
sql_ex
.
opt_flags
&&
REPLACE_FLAG
)
tmp
.
append
(
" REPLACE "
);
else
if
(
sql_ex
.
opt_flags
&&
IGNORE_FLAG
)
tmp
.
append
(
" IGNORE "
);
tmp
.
append
(
"INTO TABLE "
);
tmp
.
append
(
table_name
);
if
(
sql_ex
.
field_term_len
)
{
tmp
.
append
(
" FIELDS TERMINATED BY "
);
pretty_print_str
(
&
tmp
,
sql_ex
.
field_term
,
sql_ex
.
field_term_len
);
}
Log_event::net_send()
if
(
sql_ex
.
enclosed_len
)
{
if
(
sql_ex
.
opt_flags
&&
OPT_ENCLOSED_FLAG
)
tmp
.
append
(
" OPTIONALLY "
);
tmp
.
append
(
" ENCLOSED BY "
);
pretty_print_str
(
&
tmp
,
sql_ex
.
enclosed
,
sql_ex
.
enclosed_len
);
}
if
(
sql_ex
.
escaped_len
)
{
tmp
.
append
(
" ESCAPED BY "
);
pretty_print_str
(
&
tmp
,
sql_ex
.
escaped
,
sql_ex
.
escaped_len
);
}
if
(
sql_ex
.
line_term_len
)
{
tmp
.
append
(
" LINES TERMINATED BY "
);
pretty_print_str
(
&
tmp
,
sql_ex
.
line_term
,
sql_ex
.
line_term_len
);
}
Only called by SHOW BINLOG EVENTS
if
(
sql_ex
.
line_start_len
)
{
tmp
.
append
(
" LINES STARTING BY "
);
pretty_print_str
(
&
tmp
,
sql_ex
.
line_start
,
sql_ex
.
line_start_len
);
}
if
((
int
)
skip_lines
>
0
)
tmp
.
append
(
" IGNORE %ld LINES "
,
(
long
)
skip_lines
);
****************************************************************************/
int
Log_event
::
net_send
(
THD
*
thd
,
const
char
*
log_name
,
my_off_t
pos
)
{
String
*
packet
=
&
thd
->
packet
;
const
char
*
p
=
strrchr
(
log_name
,
FN_LIBCHAR
);
const
char
*
event_type
;
if
(
p
)
log_name
=
p
+
1
;
packet
->
length
(
0
);
net_store_data
(
packet
,
log_name
,
strlen
(
log_name
));
net_store_data
(
packet
,
(
longlong
)
pos
);
event_type
=
get_type_str
();
net_store_data
(
packet
,
event_type
,
strlen
(
event_type
));
net_store_data
(
packet
,
server_id
);
net_store_data
(
packet
,
(
longlong
)
log_pos
);
pack_info
(
packet
);
return
my_net_write
(
&
thd
->
net
,
(
char
*
)
packet
->
ptr
(),
packet
->
length
());
}
#endif // !MYSQL_CLIENT
if
(
num_fields
)
{
uint
i
;
const
char
*
field
=
fields
;
tmp
.
append
(
" ("
);
for
(
i
=
0
;
i
<
num_fields
;
i
++
)
{
if
(
i
)
tmp
.
append
(
" ,"
);
tmp
.
append
(
field
);
field
+=
field_lens
[
i
]
+
1
;
}
tmp
.
append
(
')'
);
}
net_store_data
(
packet
,
tmp
.
ptr
(),
tmp
.
length
());
}
void
Rotate_log_event
::
pack_info
(
String
*
packet
)
{
char
buf1
[
256
],
buf
[
22
];
String
tmp
(
buf1
,
sizeof
(
buf1
),
system_charset_info
);
tmp
.
length
(
0
);
tmp
.
append
(
new_log_ident
,
ident_len
);
tmp
.
append
(
";pos="
);
tmp
.
append
(
llstr
(
pos
,
buf
));
if
(
flags
&
LOG_EVENT_FORCED_ROTATE_F
)
tmp
.
append
(
"; forced by master"
);
net_store_data
(
packet
,
tmp
.
ptr
(),
tmp
.
length
());
}
void
Intvar_log_event
::
pack_info
(
String
*
packet
)
{
char
buf1
[
256
],
buf
[
22
];
String
tmp
(
buf1
,
sizeof
(
buf1
),
system_charset_info
);
tmp
.
length
(
0
);
tmp
.
append
(
get_var_type_name
());
tmp
.
append
(
'='
);
tmp
.
append
(
llstr
(
val
,
buf
));
net_store_data
(
packet
,
tmp
.
ptr
(),
tmp
.
length
());
}
void
Rand_log_event
::
pack_info
(
String
*
packet
)
{
char
buf1
[
256
],
buf
[
22
];
String
tmp
(
buf1
,
sizeof
(
buf1
),
system_charset_info
);
tmp
.
length
(
0
);
tmp
.
append
(
"randseed1="
);
tmp
.
append
(
llstr
(
seed1
,
buf
));
tmp
.
append
(
",randseed2="
);
tmp
.
append
(
llstr
(
seed2
,
buf
));
net_store_data
(
packet
,
tmp
.
ptr
(),
tmp
.
length
());
}
void
Slave_log_event
::
pack_info
(
String
*
packet
)
{
char
buf1
[
256
],
buf
[
22
],
*
end
;
String
tmp
(
buf1
,
sizeof
(
buf1
),
system_charset_info
);
tmp
.
length
(
0
);
tmp
.
append
(
"host="
);
tmp
.
append
(
master_host
);
tmp
.
append
(
",port="
);
end
=
int10_to_str
((
long
)
master_port
,
buf
,
10
);
tmp
.
append
(
buf
,
(
uint32
)
(
end
-
buf
));
tmp
.
append
(
",log="
);
tmp
.
append
(
master_log
);
tmp
.
append
(
",pos="
);
tmp
.
append
(
llstr
(
master_pos
,
buf
));
net_store_data
(
packet
,
tmp
.
ptr
(),
tmp
.
length
());
}
void
Log_event
::
init_show_field_list
(
List
<
Item
>*
field_list
)
{
field_list
->
push_back
(
new
Item_empty_string
(
"Log_name"
,
20
));
field_list
->
push_back
(
new
Item_empty_string
(
"Pos"
,
20
));
field_list
->
push_back
(
new
Item_empty_string
(
"Event_type"
,
20
));
field_list
->
push_back
(
new
Item_empty_string
(
"Server_id"
,
20
));
field_list
->
push_back
(
new
Item_empty_string
(
"Orig_log_pos"
,
20
));
field_list
->
push_back
(
new
Item_empty_string
(
"Info"
,
20
));
}
/*
* only called by SHOW BINLOG EVENTS
*/
int
Log_event
::
net_send
(
THD
*
thd
,
const
char
*
log_name
,
my_off_t
pos
)
{
String
*
packet
=
&
thd
->
packet
;
const
char
*
p
=
strrchr
(
log_name
,
FN_LIBCHAR
);
const
char
*
event_type
;
if
(
p
)
log_name
=
p
+
1
;
packet
->
length
(
0
);
net_store_data
(
packet
,
log_name
,
strlen
(
log_name
));
net_store_data
(
packet
,
(
longlong
)
pos
);
event_type
=
get_type_str
();
net_store_data
(
packet
,
event_type
,
strlen
(
event_type
));
net_store_data
(
packet
,
server_id
);
net_store_data
(
packet
,
(
longlong
)
log_pos
);
pack_info
(
packet
);
return
my_net_write
(
&
thd
->
net
,
(
char
*
)
packet
->
ptr
(),
packet
->
length
());
}
#endif
/* MYSQL_CLIENT */
int
Query_log_event
::
write
(
IO_CACHE
*
file
)
{
return
query
?
Log_event
::
write
(
file
)
:
-
1
;
}
/*****************************************************************************
Log_event::write()
****************************************************************************/
int
Log_event
::
write
(
IO_CACHE
*
file
)
{
return
(
write_header
(
file
)
||
write_data
(
file
))
?
-
1
:
0
;
}
/*****************************************************************************
Log_event::write_header()
****************************************************************************/
int
Log_event
::
write_header
(
IO_CACHE
*
file
)
{
char
buf
[
LOG_EVENT_HEADER_LEN
];
...
...
@@ -445,8 +384,13 @@ int Log_event::write_header(IO_CACHE* file)
return
(
my_b_safe_write
(
file
,
(
byte
*
)
buf
,
(
uint
)
(
pos
-
buf
)));
}
#ifndef MYSQL_CLIENT
/*****************************************************************************
Log_event::read_log_event()
****************************************************************************/
#ifndef MYSQL_CLIENT
int
Log_event
::
read_log_event
(
IO_CACHE
*
file
,
String
*
packet
,
pthread_mutex_t
*
log_lock
)
{
...
...
@@ -501,8 +445,7 @@ int Log_event::read_log_event(IO_CACHE* file, String* packet,
pthread_mutex_unlock
(
log_lock
);
DBUG_RETURN
(
result
);
}
#endif // MYSQL_CLIENT
#endif // !MYSQL_CLIENT
#ifndef MYSQL_CLIENT
#define UNLOCK_MUTEX if (log_lock) pthread_mutex_unlock(log_lock);
...
...
@@ -513,7 +456,13 @@ int Log_event::read_log_event(IO_CACHE* file, String* packet,
#define LOCK_MUTEX
#endif
// allocates memory - the caller is responsible for clean-up
/*****************************************************************************
Log_event::read_log_event()
Allocates memory--the caller is responsible for clean-up
****************************************************************************/
#ifndef MYSQL_CLIENT
Log_event
*
Log_event
::
read_log_event
(
IO_CACHE
*
file
,
pthread_mutex_t
*
log_lock
,
...
...
@@ -576,7 +525,11 @@ data_len=%d,event_type=%d",error,data_len,head[EVENT_TYPE_OFFSET]);
return
res
;
}
/*****************************************************************************
Log_event::read_log_event()
****************************************************************************/
Log_event
*
Log_event
::
read_log_event
(
const
char
*
buf
,
int
event_len
,
const
char
**
error
,
bool
old_format
)
{
...
...
@@ -642,8 +595,13 @@ Log_event* Log_event::read_log_event(const char* buf, int event_len,
return
ev
;
}
#ifdef MYSQL_CLIENT
/*****************************************************************************
Log_event::print_header()
****************************************************************************/
void
Log_event
::
print_header
(
FILE
*
file
)
{
char
llbuff
[
22
];
...
...
@@ -653,6 +611,11 @@ void Log_event::print_header(FILE* file)
llstr
(
log_pos
,
llbuff
));
}
/*****************************************************************************
Log_event::print_timestamp()
****************************************************************************/
void
Log_event
::
print_timestamp
(
FILE
*
file
,
time_t
*
ts
)
{
struct
tm
*
res
;
...
...
@@ -674,113 +637,91 @@ void Log_event::print_timestamp(FILE* file, time_t* ts)
res
->
tm_sec
);
}
#endif // MYSQL_CLIENT
void
Start_log_event
::
print
(
FILE
*
file
,
bool
short_form
,
char
*
last_db
)
{
if
(
short_form
)
return
;
/*****************************************************************************
print_header
(
file
);
fprintf
(
file
,
"
\t
Start: binlog v %d, server v %s created "
,
binlog_version
,
server_version
);
print_timestamp
(
file
,
(
time_t
*
)
&
created
);
fputc
(
'\n'
,
file
);
fflush
(
file
);
}
Log_event::set_log_pos()
void
Stop_log_event
::
print
(
FILE
*
file
,
bool
short_form
,
char
*
last_db
)
****************************************************************************/
#ifndef MYSQL_CLIENT
void
Log_event
::
set_log_pos
(
MYSQL_LOG
*
log
)
{
if
(
short_form
)
return
;
print_header
(
file
);
fprintf
(
file
,
"
\t
Stop
\n
"
);
fflush
(
file
);
if
(
!
log_pos
)
log_pos
=
my_b_tell
(
&
log
->
log_file
);
}
#endif // !MYSQL_CLIENT
void
Rotate_log_event
::
print
(
FILE
*
file
,
bool
short_form
,
char
*
last_db
)
{
char
buf
[
22
];
if
(
short_form
)
return
;
print_header
(
file
);
fprintf
(
file
,
"
\t
Rotate to "
);
if
(
new_log_ident
)
my_fwrite
(
file
,
(
byte
*
)
new_log_ident
,
(
uint
)
ident_len
,
MYF
(
MY_NABP
|
MY_WME
));
fprintf
(
file
,
" pos: %s"
,
llstr
(
pos
,
buf
));
if
(
flags
&
LOG_EVENT_FORCED_ROTATE_F
)
fprintf
(
file
,
" forced by master"
);
fputc
(
'\n'
,
file
);
fflush
(
file
);
}
#endif
/* #ifdef MYSQL_CLIENT */
/*****************************************************************************
*****************************************************************************
Query_log_event methods
Start_log_event
::
Start_log_event
(
const
char
*
buf
,
bool
old_format
)
:
Log_event
(
buf
,
old_format
)
{
buf
+=
(
old_format
)
?
OLD_HEADER_LEN
:
LOG_EVENT_HEADER_LEN
;
binlog_version
=
uint2korr
(
buf
+
ST_BINLOG_VER_OFFSET
);
memcpy
(
server_version
,
buf
+
ST_SERVER_VER_OFFSET
,
ST_SERVER_VER_LEN
);
created
=
uint4korr
(
buf
+
ST_CREATED_OFFSET
);
}
*****************************************************************************
****************************************************************************/
int
Start_log_event
::
write_data
(
IO_CACHE
*
file
)
{
char
buff
[
START_HEADER_LEN
];
int2store
(
buff
+
ST_BINLOG_VER_OFFSET
,
binlog_version
);
memcpy
(
buff
+
ST_SERVER_VER_OFFSET
,
server_version
,
ST_SERVER_VER_LEN
);
int4store
(
buff
+
ST_CREATED_OFFSET
,
created
);
return
(
my_b_safe_write
(
file
,
(
byte
*
)
buff
,
sizeof
(
buff
))
?
-
1
:
0
);
}
#ifndef MYSQL_CLIENT
/*****************************************************************************
Query_log_event::pack_info()
Rotate_log_event
::
Rotate_log_event
(
const
char
*
buf
,
int
event_len
,
bool
old_format
)
:
Log_event
(
buf
,
old_format
),
new_log_ident
(
NULL
),
alloced
(
0
)
****************************************************************************/
void
Query_log_event
::
pack_info
(
String
*
packet
)
{
// The caller will ensure that event_len is what we have at EVENT_LEN_OFFSET
int
header_size
=
(
old_format
)
?
OLD_HEADER_LEN
:
LOG_EVENT_HEADER_LEN
;
uint
ident_offset
;
if
(
event_len
<
header_size
)
return
;
buf
+=
header_size
;
if
(
old_format
)
{
ident_len
=
(
uint
)(
event_len
-
OLD_HEADER_LEN
);
pos
=
4
;
ident_offset
=
0
;
}
else
char
buf
[
256
];
String
tmp
(
buf
,
sizeof
(
buf
),
system_charset_info
);
tmp
.
length
(
0
);
if
(
db
&&
db_len
)
{
ident_len
=
(
uint
)(
event_len
-
ROTATE_EVENT_OVERHEAD
);
pos
=
uint8korr
(
buf
+
R_POS_OFFSET
);
ident_offset
=
ROTATE_HEADER_LEN
;
tmp
.
append
(
"use `"
,
5
);
tmp
.
append
(
db
,
db_len
);
tmp
.
append
(
"`; "
,
3
)
;
}
set_if_smaller
(
ident_len
,
FN_REFLEN
-
1
);
if
(
!
(
new_log_ident
=
my_strdup_with_length
((
byte
*
)
buf
+
ident_offset
,
(
uint
)
ident_len
,
MYF
(
MY_WME
))))
return
;
alloced
=
1
;
if
(
query
&&
q_len
)
tmp
.
append
(
query
,
q_len
);
net_store_data
(
packet
,
(
char
*
)
tmp
.
ptr
(),
tmp
.
length
());
}
#endif // !MYSQL_CLIENT
/*****************************************************************************
Query_log_event::write()
****************************************************************************/
int
Query_log_event
::
write
(
IO_CACHE
*
file
)
{
return
query
?
Log_event
::
write
(
file
)
:
-
1
;
}
/*****************************************************************************
int
Rotate_log_event
::
write_data
(
IO_CACHE
*
file
)
Query_log_event::write_data()
****************************************************************************/
int
Query_log_event
::
write_data
(
IO_CACHE
*
file
)
{
char
buf
[
ROTATE_HEADER_LEN
];
int8store
(
buf
,
pos
+
R_POS_OFFSET
);
return
(
my_b_safe_write
(
file
,
(
byte
*
)
buf
,
ROTATE_HEADER_LEN
)
||
my_b_safe_write
(
file
,
(
byte
*
)
new_log_ident
,
(
uint
)
ident_len
));
if
(
!
query
)
return
-
1
;
char
buf
[
QUERY_HEADER_LEN
];
int4store
(
buf
+
Q_THREAD_ID_OFFSET
,
thread_id
);
int4store
(
buf
+
Q_EXEC_TIME_OFFSET
,
exec_time
);
buf
[
Q_DB_LEN_OFFSET
]
=
(
char
)
db_len
;
int2store
(
buf
+
Q_ERR_CODE_OFFSET
,
error_code
);
return
(
my_b_safe_write
(
file
,
(
byte
*
)
buf
,
QUERY_HEADER_LEN
)
||
my_b_safe_write
(
file
,
(
db
)
?
(
byte
*
)
db
:
(
byte
*
)
""
,
db_len
+
1
)
||
my_b_safe_write
(
file
,
(
byte
*
)
query
,
q_len
))
?
-
1
:
0
;
}
/*****************************************************************************
Query_log_event::Query_log_event()
****************************************************************************/
#ifndef MYSQL_CLIENT
Query_log_event
::
Query_log_event
(
THD
*
thd_arg
,
const
char
*
query_arg
,
ulong
query_length
,
bool
using_trans
)
...
...
@@ -796,8 +737,13 @@ Query_log_event::Query_log_event(THD* thd_arg, const char* query_arg,
exec_time
=
(
ulong
)
(
end_time
-
thd
->
start_time
);
db_len
=
(
db
)
?
(
uint32
)
strlen
(
db
)
:
0
;
}
#endif
#endif // MYSQL_CLIENT
/*****************************************************************************
Query_log_event::Query_log_event()
****************************************************************************/
Query_log_event
::
Query_log_event
(
const
char
*
buf
,
int
event_len
,
bool
old_format
)
:
Log_event
(
buf
,
old_format
),
data_buf
(
0
),
query
(
NULL
),
db
(
NULL
)
...
...
@@ -833,9 +779,12 @@ Query_log_event::Query_log_event(const char* buf, int event_len,
*
((
char
*
)
query
+
q_len
)
=
0
;
}
/*****************************************************************************
#ifdef MYSQL_CLIENT
Query_log_event::print()
****************************************************************************/
#ifdef MYSQL_CLIENT
void
Query_log_event
::
print
(
FILE
*
file
,
bool
short_form
,
char
*
last_db
)
{
char
buff
[
40
],
*
end
;
// Enough for SET TIMESTAMP
...
...
@@ -863,233 +812,348 @@ void Query_log_event::print(FILE* file, bool short_form, char* last_db)
my_fwrite
(
file
,
(
byte
*
)
query
,
q_len
,
MYF
(
MY_NABP
|
MY_WME
));
fprintf
(
file
,
";
\n
"
);
}
#endif
#endif // MYSQL_CLIENT
int
Query_log_event
::
write_data
(
IO_CACHE
*
file
)
{
if
(
!
query
)
return
-
1
;
char
buf
[
QUERY_HEADER_LEN
];
int4store
(
buf
+
Q_THREAD_ID_OFFSET
,
thread_id
);
int4store
(
buf
+
Q_EXEC_TIME_OFFSET
,
exec_time
);
buf
[
Q_DB_LEN_OFFSET
]
=
(
char
)
db_len
;
int2store
(
buf
+
Q_ERR_CODE_OFFSET
,
error_code
);
/*****************************************************************************
return
(
my_b_safe_write
(
file
,
(
byte
*
)
buf
,
QUERY_HEADER_LEN
)
||
my_b_safe_write
(
file
,
(
db
)
?
(
byte
*
)
db
:
(
byte
*
)
""
,
db_len
+
1
)
||
my_b_safe_write
(
file
,
(
byte
*
)
query
,
q_len
))
?
-
1
:
0
;
}
Query_log_event::exec_event()
Intvar_log_event
::
Intvar_log_event
(
const
char
*
buf
,
bool
old_format
)
:
Log_event
(
buf
,
old_format
)
****************************************************************************/
#ifndef MYSQL_CLIENT
int
Query_log_event
::
exec_event
(
struct
st_relay_log_info
*
rli
)
{
buf
+=
(
old_format
)
?
OLD_HEADER_LEN
:
LOG_EVENT_HEADER_LEN
;
type
=
buf
[
I_TYPE_OFFSET
];
val
=
uint8korr
(
buf
+
I_VAL_OFFSET
);
}
int
expected_error
,
actual_error
=
0
;
init_sql_alloc
(
&
thd
->
mem_root
,
8192
,
0
);
thd
->
db
=
rewrite_db
((
char
*
)
db
);
const
char
*
Intvar_log_event
::
get_var_type_name
()
{
switch
(
type
)
{
case
LAST_INSERT_ID_EVENT
:
return
"LAST_INSERT_ID"
;
case
INSERT_ID_EVENT
:
return
"INSERT_ID"
;
default:
/* impossible */
return
"UNKNOWN"
;
/*
InnoDB internally stores the master log position it has processed so far;
position to store is really pos + pending + event_len
since we must store the pos of the END of the current log event
*/
rli
->
event_len
=
get_event_len
();
if
(
db_ok
(
thd
->
db
,
replicate_do_db
,
replicate_ignore_db
))
{
thd
->
query
=
(
char
*
)
query
;
thd
->
set_time
((
time_t
)
when
);
thd
->
current_tablenr
=
0
;
VOID
(
pthread_mutex_lock
(
&
LOCK_thread_count
));
thd
->
query_id
=
query_id
++
;
VOID
(
pthread_mutex_unlock
(
&
LOCK_thread_count
));
thd
->
query_error
=
0
;
// clear error
thd
->
net
.
last_errno
=
0
;
thd
->
net
.
last_error
[
0
]
=
0
;
thd
->
slave_proxy_id
=
thread_id
;
// for temp tables
/*
Sanity check to make sure the master did not get a really bad
error on the query.
*/
if
(
ignored_error_code
((
expected_error
=
error_code
))
||
!
check_expected_error
(
thd
,
rli
,
expected_error
))
{
mysql_log
.
write
(
thd
,
COM_QUERY
,
"%s"
,
thd
->
query
);
DBUG_PRINT
(
"query"
,(
"%s"
,
thd
->
query
));
mysql_parse
(
thd
,
thd
->
query
,
q_len
);
DBUG_PRINT
(
"info"
,(
"expected_error: %d last_errno: %d"
,
expected_error
,
thd
->
net
.
last_errno
));
if
((
expected_error
!=
(
actual_error
=
thd
->
net
.
last_errno
))
&&
expected_error
&&
!
ignored_error_code
(
actual_error
)
&&
!
ignored_error_code
(
expected_error
))
{
const
char
*
errmsg
=
"Slave: did not get the expected error\
running query from master - expected: '%s' (%d), got '%s' (%d)"
;
sql_print_error
(
errmsg
,
ER_SAFE
(
expected_error
),
expected_error
,
actual_error
?
thd
->
net
.
last_error
:
"no error"
,
actual_error
);
thd
->
query_error
=
1
;
}
else
if
(
expected_error
==
actual_error
||
ignored_error_code
(
actual_error
))
{
DBUG_PRINT
(
"info"
,(
"error ignored"
));
thd
->
query_error
=
0
;
*
rli
->
last_slave_error
=
0
;
rli
->
last_slave_errno
=
0
;
}
}
else
{
// master could be inconsistent, abort and tell DBA to check/fix it
thd
->
db
=
thd
->
query
=
0
;
thd
->
variables
.
convert_set
=
0
;
close_thread_tables
(
thd
);
free_root
(
&
thd
->
mem_root
,
0
);
return
1
;
}
}
thd
->
db
=
0
;
// prevent db from being freed
thd
->
query
=
0
;
// just to be sure
// assume no convert for next query unless set explictly
thd
->
variables
.
convert_set
=
0
;
close_thread_tables
(
thd
);
if
(
thd
->
query_error
||
thd
->
fatal_error
)
{
slave_print_error
(
rli
,
actual_error
,
"error '%s' on query '%s'"
,
actual_error
?
thd
->
net
.
last_error
:
"unexpected success or fatal error"
,
query
);
free_root
(
&
thd
->
mem_root
,
0
);
return
1
;
}
free_root
(
&
thd
->
mem_root
,
0
);
return
Log_event
::
exec_event
(
rli
);
}
#endif // !MYSQL_CLIENT
int
Intvar_log_event
::
write_data
(
IO_CACHE
*
file
)
{
char
buf
[
9
];
buf
[
I_TYPE_OFFSET
]
=
type
;
int8store
(
buf
+
I_VAL_OFFSET
,
val
);
return
my_b_safe_write
(
file
,
(
byte
*
)
buf
,
sizeof
(
buf
));
}
#ifdef MYSQL_CLIENT
void
Intvar_log_event
::
print
(
FILE
*
file
,
bool
short_form
,
char
*
last_db
)
{
char
llbuff
[
22
];
const
char
*
msg
;
LINT_INIT
(
msg
);
/*****************************************************************************
*****************************************************************************
if
(
!
short_form
)
{
print_header
(
file
);
fprintf
(
file
,
"
\t
Intvar
\n
"
);
}
Start_log_event methods
fprintf
(
file
,
"SET "
);
switch
(
type
)
{
case
LAST_INSERT_ID_EVENT
:
msg
=
"LAST_INSERT_ID"
;
break
;
case
INSERT_ID_EVENT
:
msg
=
"INSERT_ID"
;
break
;
}
fprintf
(
file
,
"%s=%s;
\n
"
,
msg
,
llstr
(
val
,
llbuff
));
fflush
(
file
);
}
#endif
*****************************************************************************
****************************************************************************/
/*****************************************************************************
*
* Rand log event
*
Start_log_event::pack_info()
****************************************************************************/
Rand_log_event
::
Rand_log_event
(
const
char
*
buf
,
bool
old_format
)
:
Log_event
(
buf
,
old_forma
t
)
#ifndef MYSQL_CLIENT
void
Start_log_event
::
pack_info
(
String
*
packe
t
)
{
buf
+=
(
old_format
)
?
OLD_HEADER_LEN
:
LOG_EVENT_HEADER_LEN
;
seed1
=
uint8korr
(
buf
+
RAND_SEED1_OFFSET
);
seed2
=
uint8korr
(
buf
+
RAND_SEED2_OFFSET
);
}
char
buf1
[
256
]
;
String
tmp
(
buf1
,
sizeof
(
buf1
),
system_charset_info
);
tmp
.
length
(
0
);
char
buf
[
22
];
int
Rand_log_event
::
write_data
(
IO_CACHE
*
file
)
{
char
buf
[
16
];
int8store
(
buf
+
RAND_SEED1_OFFSET
,
seed1
);
int8store
(
buf
+
RAND_SEED2_OFFSET
,
seed2
);
return
my_b_safe_write
(
file
,
(
byte
*
)
buf
,
sizeof
(
buf
));
tmp
.
append
(
"Server ver: "
);
tmp
.
append
(
server_version
);
tmp
.
append
(
", Binlog ver: "
);
tmp
.
append
(
llstr
(
binlog_version
,
buf
));
net_store_data
(
packet
,
tmp
.
ptr
(),
tmp
.
length
());
}
#endif // !MYSQL_CLIENT
/*****************************************************************************
Start_log_event::print()
****************************************************************************/
#ifdef MYSQL_CLIENT
void
Rand
_log_event
::
print
(
FILE
*
file
,
bool
short_form
,
char
*
last_db
)
void
Start
_log_event
::
print
(
FILE
*
file
,
bool
short_form
,
char
*
last_db
)
{
char
llbuff
[
22
];
if
(
!
short_form
)
{
print_header
(
file
);
fprintf
(
file
,
"
\t
Rand
\n
"
);
}
fprintf
(
file
,
"SET RAND SEED1=%s;
\n
"
,
llstr
(
seed1
,
llbuff
)
);
fp
rintf
(
file
,
"SET RAND SEED2=%s;
\n
"
,
llstr
(
seed2
,
llbuff
)
);
if
(
short_form
)
return
;
print_header
(
file
);
fprintf
(
file
,
"
\t
Start: binlog v %d, server v %s created "
,
binlog_version
,
server_version
);
print_timestamp
(
file
,
(
time_t
*
)
&
created
);
fp
utc
(
'\n'
,
file
);
fflush
(
file
);
}
#endif
#endif
// MYSQL_CLIENT
int
Load_log_event
::
write_data_header
(
IO_CACHE
*
file
)
{
char
buf
[
LOAD_HEADER_LEN
];
int4store
(
buf
+
L_THREAD_ID_OFFSET
,
thread_id
);
int4store
(
buf
+
L_EXEC_TIME_OFFSET
,
exec_time
);
int4store
(
buf
+
L_SKIP_LINES_OFFSET
,
skip_lines
);
buf
[
L_TBL_LEN_OFFSET
]
=
(
char
)
table_name_len
;
buf
[
L_DB_LEN_OFFSET
]
=
(
char
)
db_len
;
int4store
(
buf
+
L_NUM_FIELDS_OFFSET
,
num_fields
);
return
my_b_safe_write
(
file
,
(
byte
*
)
buf
,
LOAD_HEADER_LEN
);
}
/*****************************************************************************
int
Load_log_event
::
write_data_body
(
IO_CACHE
*
file
)
Start_log_event::Start_log_event()
****************************************************************************/
Start_log_event
::
Start_log_event
(
const
char
*
buf
,
bool
old_format
)
:
Log_event
(
buf
,
old_format
)
{
if
(
sql_ex
.
write_data
(
file
))
return
1
;
if
(
num_fields
&&
fields
&&
field_lens
)
{
if
(
my_b_safe_write
(
file
,
(
byte
*
)
field_lens
,
num_fields
)
||
my_b_safe_write
(
file
,
(
byte
*
)
fields
,
field_block_len
))
return
1
;
}
return
(
my_b_safe_write
(
file
,
(
byte
*
)
table_name
,
table_name_len
+
1
)
||
my_b_safe_write
(
file
,
(
byte
*
)
db
,
db_len
+
1
)
||
my_b_safe_write
(
file
,
(
byte
*
)
fname
,
fname_len
));
buf
+=
(
old_format
)
?
OLD_HEADER_LEN
:
LOG_EVENT_HEADER_LEN
;
binlog_version
=
uint2korr
(
buf
+
ST_BINLOG_VER_OFFSET
);
memcpy
(
server_version
,
buf
+
ST_SERVER_VER_OFFSET
,
ST_SERVER_VER_LEN
);
created
=
uint4korr
(
buf
+
ST_CREATED_OFFSET
);
}
/*****************************************************************************
Start_log_event::write_data()
static
bool
write_str
(
IO_CACHE
*
file
,
char
*
str
,
byte
length
)
****************************************************************************/
int
Start_log_event
::
write_data
(
IO_CACHE
*
file
)
{
return
(
my_b_safe_write
(
file
,
&
length
,
1
)
||
my_b_safe_write
(
file
,
(
byte
*
)
str
,
(
int
)
length
));
char
buff
[
START_HEADER_LEN
];
int2store
(
buff
+
ST_BINLOG_VER_OFFSET
,
binlog_version
);
memcpy
(
buff
+
ST_SERVER_VER_OFFSET
,
server_version
,
ST_SERVER_VER_LEN
);
int4store
(
buff
+
ST_CREATED_OFFSET
,
created
);
return
(
my_b_safe_write
(
file
,
(
byte
*
)
buff
,
sizeof
(
buff
))
?
-
1
:
0
);
}
/*****************************************************************************
int
sql_ex_info
::
write_data
(
IO_CACHE
*
file
)
{
if
(
new_format
())
Start_log_event::exec_event()
The master started
IMPLEMENTATION
- To handle the case where the master died without a stop event,
we clean up all temporary tables + locks that we got.
TODO
- Remove all active user locks
- If we have an active transaction at this point, the master died
in the middle while writing the transaction to the binary log.
In this case we should stop the slave.
****************************************************************************/
#ifndef MYSQL_CLIENT
int
Start_log_event
::
exec_event
(
struct
st_relay_log_info
*
rli
)
{
/* All temporary tables was deleted on the master */
close_temporary_tables
(
thd
);
/*
If we have old format, load_tmpdir is cleaned up by the I/O thread
*/
if
(
!
rli
->
mi
->
old_format
)
cleanup_load_tmpdir
();
return
Log_event
::
exec_event
(
rli
);
}
#endif // !MYSQL_CLIENT
/*****************************************************************************
*****************************************************************************
Load_log_event methods
*****************************************************************************
****************************************************************************/
/*****************************************************************************
Load_log_event::pack_info()
****************************************************************************/
#ifndef MYSQL_CLIENT
void
Load_log_event
::
pack_info
(
String
*
packet
)
{
char
buf
[
256
];
String
tmp
(
buf
,
sizeof
(
buf
),
system_charset_info
);
tmp
.
length
(
0
);
if
(
db
&&
db_len
)
{
return
(
write_str
(
file
,
field_term
,
field_term_len
)
||
write_str
(
file
,
enclosed
,
enclosed_len
)
||
write_str
(
file
,
line_term
,
line_term_len
)
||
write_str
(
file
,
line_start
,
line_start_len
)
||
write_str
(
file
,
escaped
,
escaped_len
)
||
my_b_safe_write
(
file
,(
byte
*
)
&
opt_flags
,
1
));
tmp
.
append
(
"use "
);
tmp
.
append
(
db
,
db_len
);
tmp
.
append
(
"; "
,
2
);
}
else
tmp
.
append
(
"LOAD DATA INFILE '"
);
tmp
.
append
(
fname
,
fname_len
);
tmp
.
append
(
"' "
,
2
);
if
(
sql_ex
.
opt_flags
&&
REPLACE_FLAG
)
tmp
.
append
(
" REPLACE "
);
else
if
(
sql_ex
.
opt_flags
&&
IGNORE_FLAG
)
tmp
.
append
(
" IGNORE "
);
tmp
.
append
(
"INTO TABLE "
);
tmp
.
append
(
table_name
);
if
(
sql_ex
.
field_term_len
)
{
old_sql_ex
old_ex
;
old_ex
.
field_term
=
*
field_term
;
old_ex
.
enclosed
=
*
enclosed
;
old_ex
.
line_term
=
*
line_term
;
old_ex
.
line_start
=
*
line_start
;
old_ex
.
escaped
=
*
escaped
;
old_ex
.
opt_flags
=
opt_flags
;
old_ex
.
empty_flags
=
empty_flags
;
return
my_b_safe_write
(
file
,
(
byte
*
)
&
old_ex
,
sizeof
(
old_ex
));
tmp
.
append
(
" FIELDS TERMINATED BY "
);
pretty_print_str
(
&
tmp
,
sql_ex
.
field_term
,
sql_ex
.
field_term_len
);
}
if
(
sql_ex
.
enclosed_len
)
{
if
(
sql_ex
.
opt_flags
&&
OPT_ENCLOSED_FLAG
)
tmp
.
append
(
" OPTIONALLY "
);
tmp
.
append
(
" ENCLOSED BY "
);
pretty_print_str
(
&
tmp
,
sql_ex
.
enclosed
,
sql_ex
.
enclosed_len
);
}
if
(
sql_ex
.
escaped_len
)
{
tmp
.
append
(
" ESCAPED BY "
);
pretty_print_str
(
&
tmp
,
sql_ex
.
escaped
,
sql_ex
.
escaped_len
);
}
if
(
sql_ex
.
line_term_len
)
{
tmp
.
append
(
" LINES TERMINATED BY "
);
pretty_print_str
(
&
tmp
,
sql_ex
.
line_term
,
sql_ex
.
line_term_len
);
}
if
(
sql_ex
.
line_start_len
)
{
tmp
.
append
(
" LINES STARTING BY "
);
pretty_print_str
(
&
tmp
,
sql_ex
.
line_start
,
sql_ex
.
line_start_len
);
}
if
((
int
)
skip_lines
>
0
)
tmp
.
append
(
" IGNORE %ld LINES "
,
(
long
)
skip_lines
);
if
(
num_fields
)
{
uint
i
;
const
char
*
field
=
fields
;
tmp
.
append
(
" ("
);
for
(
i
=
0
;
i
<
num_fields
;
i
++
)
{
if
(
i
)
tmp
.
append
(
" ,"
);
tmp
.
append
(
field
);
field
+=
field_lens
[
i
]
+
1
;
}
tmp
.
append
(
')'
);
}
net_store_data
(
packet
,
tmp
.
ptr
(),
tmp
.
length
());
}
#endif // !MYSQL_CLIENT
/*****************************************************************************
static
inline
int
read_str
(
char
*
&
buf
,
char
*
buf_end
,
char
*
&
str
,
uint8
&
len
)
Load_log_event::write_data_header()
****************************************************************************/
int
Load_log_event
::
write_data_header
(
IO_CACHE
*
file
)
{
if
(
buf
+
(
uint
)
(
uchar
)
*
buf
>=
buf_end
)
return
1
;
len
=
(
uint8
)
*
buf
;
str
=
buf
+
1
;
buf
+=
(
uint
)
len
+
1
;
return
0
;
char
buf
[
LOAD_HEADER_LEN
];
int4store
(
buf
+
L_THREAD_ID_OFFSET
,
thread_id
);
int4store
(
buf
+
L_EXEC_TIME_OFFSET
,
exec_time
);
int4store
(
buf
+
L_SKIP_LINES_OFFSET
,
skip_lines
);
buf
[
L_TBL_LEN_OFFSET
]
=
(
char
)
table_name_len
;
buf
[
L_DB_LEN_OFFSET
]
=
(
char
)
db_len
;
int4store
(
buf
+
L_NUM_FIELDS_OFFSET
,
num_fields
);
return
my_b_safe_write
(
file
,
(
byte
*
)
buf
,
LOAD_HEADER_LEN
);
}
/*****************************************************************************
char
*
sql_ex_info
::
init
(
char
*
buf
,
char
*
buf_end
,
bool
use_new_format
)
Load_log_event::write_data_body()
****************************************************************************/
int
Load_log_event
::
write_data_body
(
IO_CACHE
*
file
)
{
cached_new_format
=
use_new_format
;
if
(
use_new_format
)
{
empty_flags
=
0
;
/*
The code below assumes that buf will not disappear from
under our feet during the lifetime of the event. This assumption
holds true in the slave thread if the log is in new format, but is not
the case when we have old format because we will be reusing net buffer
to read the actual file before we write out the Create_file event.
*/
if
(
read_str
(
buf
,
buf_end
,
field_term
,
field_term_len
)
||
read_str
(
buf
,
buf_end
,
enclosed
,
enclosed_len
)
||
read_str
(
buf
,
buf_end
,
line_term
,
line_term_len
)
||
read_str
(
buf
,
buf_end
,
line_start
,
line_start_len
)
||
read_str
(
buf
,
buf_end
,
escaped
,
escaped_len
))
return
0
;
opt_flags
=
*
buf
++
;
}
else
if
(
sql_ex
.
write_data
(
file
))
return
1
;
if
(
num_fields
&&
fields
&&
field_lens
)
{
field_term_len
=
enclosed_len
=
line_term_len
=
line_start_len
=
escaped_len
=
1
;
field_term
=
buf
++
;
// Use first byte in string
enclosed
=
buf
++
;
line_term
=
buf
++
;
line_start
=
buf
++
;
escaped
=
buf
++
;
opt_flags
=
*
buf
++
;
empty_flags
=
*
buf
++
;
if
(
empty_flags
&
FIELD_TERM_EMPTY
)
field_term_len
=
0
;
if
(
empty_flags
&
ENCLOSED_EMPTY
)
enclosed_len
=
0
;
if
(
empty_flags
&
LINE_TERM_EMPTY
)
line_term_len
=
0
;
if
(
empty_flags
&
LINE_START_EMPTY
)
line_start_len
=
0
;
if
(
empty_flags
&
ESCAPED_EMPTY
)
escaped_len
=
0
;
if
(
my_b_safe_write
(
file
,
(
byte
*
)
field_lens
,
num_fields
)
||
my_b_safe_write
(
file
,
(
byte
*
)
fields
,
field_block_len
))
return
1
;
}
return
buf
;
return
(
my_b_safe_write
(
file
,
(
byte
*
)
table_name
,
table_name_len
+
1
)
||
my_b_safe_write
(
file
,
(
byte
*
)
db
,
db_len
+
1
)
||
my_b_safe_write
(
file
,
(
byte
*
)
fname
,
fname_len
));
}
/*****************************************************************************
Load_log_event::Load_log_event()
****************************************************************************/
#ifndef MYSQL_CLIENT
Load_log_event
::
Load_log_event
(
THD
*
thd
,
sql_exchange
*
ex
,
const
char
*
db_arg
,
const
char
*
table_name_arg
,
...
...
@@ -1162,14 +1226,16 @@ Load_log_event::Load_log_event(THD* thd, sql_exchange* ex,
field_lens
=
(
const
uchar
*
)
field_lens_buf
.
ptr
();
fields
=
fields_buf
.
ptr
();
}
#endif // !MYSQL_CLIENT
#endif
/*****************************************************************************
Load_log_event::Load_log_event()
/*
The caller must do buf[event_len] = 0 before he starts using the
constructed event.
*/
****************************************************************************/
Load_log_event
::
Load_log_event
(
const
char
*
buf
,
int
event_len
,
bool
old_format
)
:
Log_event
(
buf
,
old_format
),
num_fields
(
0
),
fields
(
0
),
...
...
@@ -1181,6 +1247,11 @@ Load_log_event::Load_log_event(const char* buf, int event_len,
copy_log_event
(
buf
,
event_len
,
old_format
);
}
/*****************************************************************************
Load_log_event::copy_log_event()
****************************************************************************/
int
Load_log_event
::
copy_log_event
(
const
char
*
buf
,
ulong
event_len
,
bool
old_format
)
{
...
...
@@ -1225,8 +1296,12 @@ int Load_log_event::copy_log_event(const char *buf, ulong event_len,
return
0
;
}
#ifdef MYSQL_CLIENT
/*****************************************************************************
Load_log_event::print()
****************************************************************************/
#ifdef MYSQL_CLIENT
void
Load_log_event
::
print
(
FILE
*
file
,
bool
short_form
,
char
*
last_db
)
{
if
(
!
short_form
)
...
...
@@ -1307,18 +1382,14 @@ void Load_log_event::print(FILE* file, bool short_form, char* last_db)
fprintf
(
file
,
";
\n
"
);
}
#endif
/* #ifdef MYSQL_CLIENT */
#ifndef MYSQL_CLIENT
void
Log_event
::
set_log_pos
(
MYSQL_LOG
*
log
)
{
if
(
!
log_pos
)
log_pos
=
my_b_tell
(
&
log
->
log_file
);
}
/*****************************************************************************
Load_log_event::set_fields()
****************************************************************************/
#ifndef MYSQL_CLIENT
void
Load_log_event
::
set_fields
(
List
<
Item
>
&
fields
)
{
uint
i
;
...
...
@@ -1329,589 +1400,690 @@ void Load_log_event::set_fields(List<Item> &fields)
field
+=
field_lens
[
i
]
+
1
;
}
}
#endif // !MYSQL_CLIENT
/*****************************************************************************
Slave_log_event
::
Slave_log_event
(
THD
*
thd_arg
,
struct
st_relay_log_info
*
rli
)
:
Log_event
(
thd_arg
),
mem_pool
(
0
),
master_host
(
0
)
Load_log_event::exec_event()
****************************************************************************/
#ifndef MYSQL_CLIENT
int
Load_log_event
::
exec_event
(
NET
*
net
,
struct
st_relay_log_info
*
rli
)
{
DBUG_ENTER
(
"Slave_log_event"
);
if
(
!
rli
->
inited
)
// QQ When can this happen ?
DBUG_VOID_RETURN
;
MASTER_INFO
*
mi
=
rli
->
mi
;
// TODO: re-write this better without holding both locks at the same time
pthread_mutex_lock
(
&
mi
->
data_lock
);
pthread_mutex_lock
(
&
rli
->
data_lock
);
master_host_len
=
strlen
(
mi
->
host
);
master_log_len
=
strlen
(
rli
->
master_log_name
);
// on OOM, just do not initialize the structure and print the error
if
((
mem_pool
=
(
char
*
)
my_malloc
(
get_data_size
()
+
1
,
MYF
(
MY_WME
))))
init_sql_alloc
(
&
thd
->
mem_root
,
8192
,
0
);
thd
->
db
=
rewrite_db
((
char
*
)
db
);
thd
->
query
=
0
;
thd
->
query_error
=
0
;
if
(
db_ok
(
thd
->
db
,
replicate_do_db
,
replicate_ignore_db
))
{
master_host
=
mem_pool
+
SL_MASTER_HOST_OFFSET
;
memcpy
(
master_host
,
mi
->
host
,
master_host_len
+
1
);
master_log
=
master_host
+
master_host_len
+
1
;
memcpy
(
master_log
,
rli
->
master_log_name
,
master_log_len
+
1
);
master_port
=
mi
->
port
;
master_pos
=
rli
->
master_log_pos
;
DBUG_PRINT
(
"info"
,
(
"master_log: %s pos: %d"
,
master_log
,
(
ulong
)
master_pos
));
thd
->
set_time
((
time_t
)
when
);
thd
->
current_tablenr
=
0
;
VOID
(
pthread_mutex_lock
(
&
LOCK_thread_count
));
thd
->
query_id
=
query_id
++
;
VOID
(
pthread_mutex_unlock
(
&
LOCK_thread_count
));
TABLE_LIST
tables
;
bzero
((
char
*
)
&
tables
,
sizeof
(
tables
));
tables
.
db
=
thd
->
db
;
tables
.
alias
=
tables
.
real_name
=
(
char
*
)
table_name
;
tables
.
lock_type
=
TL_WRITE
;
// the table will be opened in mysql_load
if
(
table_rules_on
&&
!
tables_ok
(
thd
,
&
tables
))
{
// TODO: this is a bug - this needs to be moved to the I/O thread
if
(
net
)
skip_load_data_infile
(
net
);
}
else
{
char
llbuff
[
22
];
enum
enum_duplicates
handle_dup
=
DUP_IGNORE
;
if
(
sql_ex
.
opt_flags
&&
REPLACE_FLAG
)
handle_dup
=
DUP_REPLACE
;
sql_exchange
ex
((
char
*
)
fname
,
sql_ex
.
opt_flags
&&
DUMPFILE_FLAG
);
String
field_term
(
sql_ex
.
field_term
,
sql_ex
.
field_term_len
,
system_charset_info
);
String
enclosed
(
sql_ex
.
enclosed
,
sql_ex
.
enclosed_len
,
system_charset_info
);
String
line_term
(
sql_ex
.
line_term
,
sql_ex
.
line_term_len
,
system_charset_info
);
String
line_start
(
sql_ex
.
line_start
,
sql_ex
.
line_start_len
,
system_charset_info
);
String
escaped
(
sql_ex
.
escaped
,
sql_ex
.
escaped_len
,
system_charset_info
);
ex
.
opt_enclosed
=
(
sql_ex
.
opt_flags
&
OPT_ENCLOSED_FLAG
);
if
(
sql_ex
.
empty_flags
&
FIELD_TERM_EMPTY
)
ex
.
field_term
->
length
(
0
);
ex
.
skip_lines
=
skip_lines
;
List
<
Item
>
fields
;
set_fields
(
fields
);
thd
->
slave_proxy_id
=
thd
->
thread_id
;
if
(
net
)
{
// mysql_load will use thd->net to read the file
thd
->
net
.
vio
=
net
->
vio
;
/*
Make sure the client does not get confused about the packet sequence
*/
thd
->
net
.
pkt_nr
=
net
->
pkt_nr
;
}
if
(
mysql_load
(
thd
,
&
ex
,
&
tables
,
fields
,
handle_dup
,
net
!=
0
,
TL_WRITE
))
thd
->
query_error
=
1
;
if
(
thd
->
cuted_fields
)
sql_print_error
(
"Slave: load data infile at position %s in log \
'%s' produced %d warning(s)"
,
llstr
(
rli
->
master_log_pos
,
llbuff
),
RPL_LOG_NAME
,
thd
->
cuted_fields
);
if
(
net
)
net
->
pkt_nr
=
thd
->
net
.
pkt_nr
;
}
}
else
sql_print_error
(
"Out of memory while recording slave event"
);
pthread_mutex_unlock
(
&
rli
->
data_lock
);
pthread_mutex_unlock
(
&
mi
->
data_lock
);
DBUG_VOID_RETURN
;
{
/*
We will just ask the master to send us /dev/null if we do not
want to load the data.
TODO: this a bug - needs to be done in I/O thread
*/
if
(
net
)
skip_load_data_infile
(
net
);
}
thd
->
net
.
vio
=
0
;
thd
->
db
=
0
;
// prevent db from being freed
close_thread_tables
(
thd
);
if
(
thd
->
query_error
)
{
int
sql_error
=
thd
->
net
.
last_errno
;
if
(
!
sql_error
)
sql_error
=
ER_UNKNOWN_ERROR
;
slave_print_error
(
rli
,
sql_error
,
"Slave: Error '%s' running load data infile "
,
ER_SAFE
(
sql_error
));
free_root
(
&
thd
->
mem_root
,
0
);
return
1
;
}
free_root
(
&
thd
->
mem_root
,
0
);
if
(
thd
->
fatal_error
)
{
sql_print_error
(
"Slave: Fatal error running LOAD DATA INFILE "
);
return
1
;
}
return
Log_event
::
exec_event
(
rli
);
}
#endif // !MYSQL_CLIENT
#endif
/* ! MYSQL_CLIENT */
/*****************************************************************************
*****************************************************************************
Slave_log_event
::~
Slave_log_event
()
Rotate_log_event methods
*****************************************************************************
****************************************************************************/
/*****************************************************************************
Rotate_log_event::pack_info()
****************************************************************************/
#ifndef MYSQL_CLIENT
void
Rotate_log_event
::
pack_info
(
String
*
packet
)
{
my_free
(
mem_pool
,
MYF
(
MY_ALLOW_ZERO_PTR
));
char
buf1
[
256
],
buf
[
22
];
String
tmp
(
buf1
,
sizeof
(
buf1
),
system_charset_info
);
tmp
.
length
(
0
);
tmp
.
append
(
new_log_ident
,
ident_len
);
tmp
.
append
(
";pos="
);
tmp
.
append
(
llstr
(
pos
,
buf
));
if
(
flags
&
LOG_EVENT_FORCED_ROTATE_F
)
tmp
.
append
(
"; forced by master"
);
net_store_data
(
packet
,
tmp
.
ptr
(),
tmp
.
length
());
}
#endif // !MYSQL_CLIENT
#ifdef MYSQL_CLIENT
/*****************************************************************************
void
Slave_log_event
::
print
(
FILE
*
file
,
bool
short_form
,
char
*
last_db
)
Rotate_log_event::print()
****************************************************************************/
#ifdef MYSQL_CLIENT
void
Rotate_log_event
::
print
(
FILE
*
file
,
bool
short_form
,
char
*
last_db
)
{
char
llbuf
f
[
22
];
char
bu
f
[
22
];
if
(
short_form
)
return
;
print_header
(
file
);
fprintf
(
file
,
"
\t
Rotate to "
);
if
(
new_log_ident
)
my_fwrite
(
file
,
(
byte
*
)
new_log_ident
,
(
uint
)
ident_len
,
MYF
(
MY_NABP
|
MY_WME
));
fprintf
(
file
,
" pos: %s"
,
llstr
(
pos
,
buf
));
if
(
flags
&
LOG_EVENT_FORCED_ROTATE_F
)
fprintf
(
file
,
" forced by master"
);
fputc
(
'\n'
,
file
);
fprintf
(
file
,
"Slave: master_host: '%s' master_port: %d \
master_log: '%s' master_pos: %s
\n
"
,
master_host
,
master_port
,
master_log
,
llstr
(
master_pos
,
llbuff
));
}
#endif
/* MYSQL_CLIENT */
int
Slave_log_event
::
get_data_size
()
{
return
master_host_len
+
master_log_len
+
1
+
SL_MASTER_HOST_OFFSET
;
fflush
(
file
);
}
#endif // MYSQL_CLIENT
int
Slave_log_event
::
write_data
(
IO_CACHE
*
file
)
{
int8store
(
mem_pool
+
SL_MASTER_POS_OFFSET
,
master_pos
);
int2store
(
mem_pool
+
SL_MASTER_PORT_OFFSET
,
master_port
);
// log and host are already there
return
my_b_safe_write
(
file
,
(
byte
*
)
mem_pool
,
get_data_size
());
}
/*****************************************************************************
Rotate_log_event::Rotate_log_event()
void
Slave_log_event
::
init_from_mem_pool
(
int
data_size
)
****************************************************************************/
Rotate_log_event
::
Rotate_log_event
(
const
char
*
buf
,
int
event_len
,
bool
old_format
)
:
Log_event
(
buf
,
old_format
),
new_log_ident
(
NULL
),
alloced
(
0
)
{
master_pos
=
uint8korr
(
mem_pool
+
SL_MASTER_POS_OFFSET
);
master_port
=
uint2korr
(
mem_pool
+
SL_MASTER_PORT_OFFSET
);
master_host
=
mem_pool
+
SL_MASTER_HOST_OFFSET
;
master_host_len
=
strlen
(
master_host
);
// safety
master_log
=
master_host
+
master_host_len
+
1
;
if
(
master_log
>
mem_pool
+
data_size
)
{
master_host
=
0
;
// The caller will ensure that event_len is what we have at EVENT_LEN_OFFSET
int
header_size
=
(
old_format
)
?
OLD_HEADER_LEN
:
LOG_EVENT_HEADER_LEN
;
uint
ident_offset
;
if
(
event_len
<
header_size
)
return
;
buf
+=
header_size
;
if
(
old_format
)
{
ident_len
=
(
uint
)(
event_len
-
OLD_HEADER_LEN
);
pos
=
4
;
ident_offset
=
0
;
}
master_log_len
=
strlen
(
master_log
);
}
Slave_log_event
::
Slave_log_event
(
const
char
*
buf
,
int
event_len
)
:
Log_event
(
buf
,
0
),
mem_pool
(
0
),
master_host
(
0
)
{
event_len
-=
LOG_EVENT_HEADER_LEN
;
if
(
event_len
<
0
)
return
;
if
(
!
(
mem_pool
=
(
char
*
)
my_malloc
(
event_len
+
1
,
MYF
(
MY_WME
))))
else
{
ident_len
=
(
uint
)(
event_len
-
ROTATE_EVENT_OVERHEAD
);
pos
=
uint8korr
(
buf
+
R_POS_OFFSET
);
ident_offset
=
ROTATE_HEADER_LEN
;
}
set_if_smaller
(
ident_len
,
FN_REFLEN
-
1
);
if
(
!
(
new_log_ident
=
my_strdup_with_length
((
byte
*
)
buf
+
ident_offset
,
(
uint
)
ident_len
,
MYF
(
MY_WME
))))
return
;
memcpy
(
mem_pool
,
buf
+
LOG_EVENT_HEADER_LEN
,
event_len
);
mem_pool
[
event_len
]
=
0
;
init_from_mem_pool
(
event_len
);
alloced
=
1
;
}
#ifndef MYSQL_CLIENT
Create_file_log_event
::
Create_file_log_event
(
THD
*
thd_arg
,
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
)
:
Load_log_event
(
thd_arg
,
ex
,
db_arg
,
table_name_arg
,
fields_arg
,
handle_dup
),
fake_base
(
0
),
block
(
block_arg
),
block_len
(
block_len_arg
),
file_id
(
thd_arg
->
file_id
=
mysql_bin_log
.
next_file_id
())
{
sql_ex
.
force_new_format
();
}
#endif
/*****************************************************************************
int
Create_file_log_event
::
write_data_body
(
IO_CACHE
*
file
)
{
int
res
;
if
((
res
=
Load_log_event
::
write_data_body
(
file
))
||
fake_base
)
return
res
;
return
(
my_b_safe_write
(
file
,
(
byte
*
)
""
,
1
)
||
my_b_safe_write
(
file
,
(
byte
*
)
block
,
block_len
));
}
Rotate_log_event::write_data()
int
Create_file_log_event
::
write_data_header
(
IO_CACHE
*
file
)
****************************************************************************/
int
Rotate_log_event
::
write_data
(
IO_CACHE
*
file
)
{
int
res
;
if
((
res
=
Load_log_event
::
write_data_header
(
file
))
||
fake_base
)
return
res
;
byte
buf
[
CREATE_FILE_HEADER_LEN
];
int4store
(
buf
+
CF_FILE_ID_OFFSET
,
file_id
);
return
my_b_safe_write
(
file
,
buf
,
CREATE_FILE_HEADER_LEN
);
char
buf
[
ROTATE_HEADER_LEN
];
int8store
(
buf
,
pos
+
R_POS_OFFSET
);
return
(
my_b_safe_write
(
file
,
(
byte
*
)
buf
,
ROTATE_HEADER_LEN
)
||
my_b_safe_write
(
file
,
(
byte
*
)
new_log_ident
,
(
uint
)
ident_len
));
}
int
Create_file_log_event
::
write_base
(
IO_CACHE
*
file
)
{
int
res
;
fake_base
=
1
;
// pretend we are Load event
res
=
write
(
file
);
fake_base
=
0
;
return
res
;
}
/*****************************************************************************
Create_file_log_event
::
Create_file_log_event
(
const
char
*
buf
,
int
len
,
bool
old_format
)
:
Load_log_event
(
buf
,
0
,
old_format
),
fake_base
(
0
),
block
(
0
),
inited_from_old
(
0
)
{
int
block_offset
;
if
(
copy_log_event
(
buf
,
len
,
old_format
))
return
;
if
(
!
old_format
)
{
file_id
=
uint4korr
(
buf
+
LOG_EVENT_HEADER_LEN
+
+
LOAD_HEADER_LEN
+
CF_FILE_ID_OFFSET
);
// + 1 for \0 terminating fname
block_offset
=
(
LOG_EVENT_HEADER_LEN
+
Load_log_event
::
get_data_size
()
+
CREATE_FILE_HEADER_LEN
+
1
);
if
(
len
<
block_offset
)
return
;
block
=
(
char
*
)
buf
+
block_offset
;
block_len
=
len
-
block_offset
;
}
else
{
sql_ex
.
force_new_format
();
inited_from_old
=
1
;
}
}
Rotate_log_event::exec_event()
Got a rotate log even from the master
IMPLEMENTATION
This is mainly used so that we can later figure out the logname and
position for the master.
#ifdef MYSQL_CLIENT
void
Create_file_log_event
::
print
(
FILE
*
file
,
bool
short_form
,
char
*
last_db
)
We can't rotate the slave as this will cause infinitive rotations
in a A -> B -> A setup.
RETURN VALUES
0 ok
****************************************************************************/
#ifndef MYSQL_CLIENT
int
Rotate_log_event
::
exec_event
(
struct
st_relay_log_info
*
rli
)
{
if
(
short_form
)
return
;
Load_log_event
::
print
(
file
,
1
,
last_db
);
fprintf
(
file
,
" file_id: %d block_len: %d
\n
"
,
file_id
,
block_len
);
char
*
log_name
=
rli
->
master_log_name
;
DBUG_ENTER
(
"Rotate_log_event::exec_event"
);
pthread_mutex_lock
(
&
rli
->
data_lock
);
memcpy
(
log_name
,
new_log_ident
,
ident_len
+
1
);
rli
->
master_log_pos
=
pos
;
rli
->
relay_log_pos
+=
get_event_len
();
DBUG_PRINT
(
"info"
,
(
"master_log_pos: %d"
,
(
ulong
)
rli
->
master_log_pos
));
pthread_mutex_unlock
(
&
rli
->
data_lock
);
pthread_cond_broadcast
(
&
rli
->
data_cond
);
flush_relay_log_info
(
rli
);
DBUG_RETURN
(
0
);
}
#endif
#endif // !MYSQL_CLIENT
/*****************************************************************************
*****************************************************************************
Intvar_log_event methods
*****************************************************************************
****************************************************************************/
/*****************************************************************************
Intvar_log_event::pack_info()
****************************************************************************/
#ifndef MYSQL_CLIENT
void
Create_file
_log_event
::
pack_info
(
String
*
packet
)
void
Intvar
_log_event
::
pack_info
(
String
*
packet
)
{
char
buf1
[
256
],
buf
[
22
],
*
end
;
char
buf1
[
256
],
buf
[
22
]
;
String
tmp
(
buf1
,
sizeof
(
buf1
),
system_charset_info
);
tmp
.
length
(
0
);
tmp
.
append
(
"db="
);
tmp
.
append
(
db
,
db_len
);
tmp
.
append
(
";table="
);
tmp
.
append
(
table_name
,
table_name_len
);
tmp
.
append
(
";file_id="
);
end
=
int10_to_str
((
long
)
file_id
,
buf
,
10
);
tmp
.
append
(
buf
,
(
uint32
)
(
end
-
buf
));
tmp
.
append
(
";block_len="
);
end
=
int10_to_str
((
long
)
block_len
,
buf
,
10
);
tmp
.
append
(
buf
,
(
uint32
)
(
end
-
buf
));
net_store_data
(
packet
,
(
char
*
)
tmp
.
ptr
(),
tmp
.
length
());
tmp
.
append
(
get_var_type_name
());
tmp
.
append
(
'='
);
tmp
.
append
(
llstr
(
val
,
buf
));
net_store_data
(
packet
,
tmp
.
ptr
(),
tmp
.
length
());
}
#endif
#endif
// !MYSQL_CLIENT
#ifndef MYSQL_CLIENT
Append_block_log_event
::
Append_block_log_event
(
THD
*
thd_arg
,
char
*
block_arg
,
uint
block_len_arg
)
:
Log_event
(
thd_arg
),
block
(
block_arg
),
block_len
(
block_len_arg
),
file_id
(
thd_arg
->
file_id
)
{
}
#endif
/*****************************************************************************
Append_block_log_event
::
Append_block_log_event
(
const
char
*
buf
,
int
len
)
:
Log_event
(
buf
,
0
),
block
(
0
)
{
if
((
uint
)
len
<
APPEND_BLOCK_EVENT_OVERHEAD
)
return
;
file_id
=
uint4korr
(
buf
+
LOG_EVENT_HEADER_LEN
+
AB_FILE_ID_OFFSET
);
block
=
(
char
*
)
buf
+
APPEND_BLOCK_EVENT_OVERHEAD
;
block_len
=
len
-
APPEND_BLOCK_EVENT_OVERHEAD
;
}
Intvar_log_event::Intvar_log_event()
int
Append_block_log_event
::
write_data
(
IO_CACHE
*
file
)
****************************************************************************/
Intvar_log_event
::
Intvar_log_event
(
const
char
*
buf
,
bool
old_format
)
:
Log_event
(
buf
,
old_format
)
{
byte
buf
[
APPEND_BLOCK_HEADER_LEN
];
int4store
(
buf
+
AB_FILE_ID_OFFSET
,
file_id
);
return
(
my_b_safe_write
(
file
,
buf
,
APPEND_BLOCK_HEADER_LEN
)
||
my_b_safe_write
(
file
,
(
byte
*
)
block
,
block_len
));
buf
+=
(
old_format
)
?
OLD_HEADER_LEN
:
LOG_EVENT_HEADER_LEN
;
type
=
buf
[
I_TYPE_OFFSET
];
val
=
uint8korr
(
buf
+
I_VAL_OFFSET
);
}
#ifdef MYSQL_CLIENT
void
Append_block_log_event
::
print
(
FILE
*
file
,
bool
short_form
,
char
*
last_db
)
{
if
(
short_form
)
return
;
print_header
(
file
);
fputc
(
'\n'
,
file
);
fprintf
(
file
,
"#Append_block: file_id: %d block_len: %d
\n
"
,
file_id
,
block_len
);
}
#endif
/*****************************************************************************
#ifndef MYSQL_CLIENT
void
Append_block_log_event
::
pack_info
(
String
*
packet
)
Intvar_log_event::get_var_type_name()
****************************************************************************/
const
char
*
Intvar_log_event
::
get_var_type_name
()
{
char
buf
[
256
];
uint
length
;
length
=
(
uint
)
my_sprintf
(
buf
,
(
buf
,
";file_id=%u;block_len=%u"
,
file_id
,
block_len
));
net_store_data
(
packet
,
buf
,
(
int32
)
length
);
switch
(
type
)
{
case
LAST_INSERT_ID_EVENT
:
return
"LAST_INSERT_ID"
;
case
INSERT_ID_EVENT
:
return
"INSERT_ID"
;
default:
/* impossible */
return
"UNKNOWN"
;
}
}
/*****************************************************************************
Delete_file_log_event
::
Delete_file_log_event
(
THD
*
thd_arg
)
:
Log_event
(
thd_arg
),
file_id
(
thd_arg
->
file_id
)
Intvar_log_event::write_data()
****************************************************************************/
int
Intvar_log_event
::
write_data
(
IO_CACHE
*
file
)
{
char
buf
[
9
];
buf
[
I_TYPE_OFFSET
]
=
type
;
int8store
(
buf
+
I_VAL_OFFSET
,
val
);
return
my_b_safe_write
(
file
,
(
byte
*
)
buf
,
sizeof
(
buf
));
}
#endif
/*****************************************************************************
Delete_file_log_event
::
Delete_file_log_event
(
const
char
*
buf
,
int
len
)
:
Log_event
(
buf
,
0
),
file_id
(
0
)
Intvar_log_event::print()
****************************************************************************/
#ifdef MYSQL_CLIENT
void
Intvar_log_event
::
print
(
FILE
*
file
,
bool
short_form
,
char
*
last_db
)
{
if
((
uint
)
len
<
DELETE_FILE_EVENT_OVERHEAD
)
return
;
file_id
=
uint4korr
(
buf
+
LOG_EVENT_HEADER_LEN
+
AB_FILE_ID_OFFSET
);
}
char
llbuff
[
22
];
const
char
*
msg
;
LINT_INIT
(
msg
);
if
(
!
short_form
)
{
print_header
(
file
);
fprintf
(
file
,
"
\t
Intvar
\n
"
);
}
int
Delete_file_log_event
::
write_data
(
IO_CACHE
*
file
)
{
byte
buf
[
DELETE_FILE_HEADER_LEN
];
int4store
(
buf
+
DF_FILE_ID_OFFSET
,
file_id
);
return
my_b_safe_write
(
file
,
buf
,
DELETE_FILE_HEADER_LEN
);
fprintf
(
file
,
"SET "
);
switch
(
type
)
{
case
LAST_INSERT_ID_EVENT
:
msg
=
"LAST_INSERT_ID"
;
break
;
case
INSERT_ID_EVENT
:
msg
=
"INSERT_ID"
;
break
;
}
fprintf
(
file
,
"%s=%s;
\n
"
,
msg
,
llstr
(
val
,
llbuff
));
fflush
(
file
);
}
#endif // MYSQL_CLIENT
#ifdef MYSQL_CLIENT
void
Delete_file_log_event
::
print
(
FILE
*
file
,
bool
short_form
,
char
*
last_db
)
{
if
(
short_form
)
return
;
print_header
(
file
);
fputc
(
'\n'
,
file
);
fprintf
(
file
,
"#Delete_file: file_id=%u
\n
"
,
file_id
);
}
#endif
/*****************************************************************************
Intvar_log_event::exec_event()
****************************************************************************/
#ifndef MYSQL_CLIENT
void
Delete_file_log_event
::
pack_info
(
String
*
packet
)
int
Intvar_log_event
::
exec_event
(
struct
st_relay_log_info
*
rli
)
{
char
buf
[
64
];
uint
length
;
length
=
(
uint
)
my_sprintf
(
buf
,
(
buf
,
";file_id=%u"
,
(
uint
)
file_id
));
net_store_data
(
packet
,
buf
,
(
int32
)
length
);
switch
(
type
)
{
case
LAST_INSERT_ID_EVENT
:
thd
->
last_insert_id_used
=
1
;
thd
->
last_insert_id
=
val
;
break
;
case
INSERT_ID_EVENT
:
thd
->
next_insert_id
=
val
;
break
;
}
rli
->
inc_pending
(
get_event_len
());
return
0
;
}
#endif
#endif
// !MYSQL_CLIENT
#ifndef MYSQL_CLIENT
Execute_load_log_event
::
Execute_load_log_event
(
THD
*
thd_arg
)
:
Log_event
(
thd_arg
),
file_id
(
thd_arg
->
file_id
)
{
}
#endif
/*****************************************************************************
*****************************************************************************
Execute_load_log_event
::
Execute_load_log_event
(
const
char
*
buf
,
int
len
)
:
Log_event
(
buf
,
0
),
file_id
(
0
)
{
if
((
uint
)
len
<
EXEC_LOAD_EVENT_OVERHEAD
)
return
;
file_id
=
uint4korr
(
buf
+
LOG_EVENT_HEADER_LEN
+
EL_FILE_ID_OFFSET
);
}
Rand_log_event methods
*****************************************************************************
****************************************************************************/
int
Execute_load_log_event
::
write_data
(
IO_CACHE
*
file
)
{
byte
buf
[
EXEC_LOAD_HEADER_LEN
];
int4store
(
buf
+
EL_FILE_ID_OFFSET
,
file_id
);
return
my_b_safe_write
(
file
,
buf
,
EXEC_LOAD_HEADER_LEN
);
}
/*****************************************************************************
#ifdef MYSQL_CLIENT
void
Execute_load_log_event
::
print
(
FILE
*
file
,
bool
short_form
,
char
*
last_db
)
Rand_log_event::pack_info()
****************************************************************************/
#ifndef MYSQL_CLIENT
void
Rand_log_event
::
pack_info
(
String
*
packet
)
{
if
(
short_form
)
return
;
print_header
(
file
);
fputc
(
'\n'
,
file
);
fprintf
(
file
,
"#Exec_load: file_id=%d
\n
"
,
file_id
);
char
buf1
[
256
],
buf
[
22
];
String
tmp
(
buf1
,
sizeof
(
buf1
),
system_charset_info
);
tmp
.
length
(
0
);
tmp
.
append
(
"randseed1="
);
tmp
.
append
(
llstr
(
seed1
,
buf
));
tmp
.
append
(
",randseed2="
);
tmp
.
append
(
llstr
(
seed2
,
buf
));
net_store_data
(
packet
,
tmp
.
ptr
(),
tmp
.
length
());
}
#endif
#ifndef MYSQL_CLIENT
void
Execute_load_log_event
::
pack_info
(
String
*
packet
)
#endif // !MYSQL_CLIENT
/*****************************************************************************
Rand_log_event::Rand_log_event()
****************************************************************************/
Rand_log_event
::
Rand_log_event
(
const
char
*
buf
,
bool
old_format
)
:
Log_event
(
buf
,
old_format
)
{
char
buf
[
64
];
uint
length
;
length
=
(
uint
)
my_sprintf
(
buf
,
(
buf
,
";file_id=%u"
,
(
uint
)
file_id
));
net_store_data
(
packet
,
buf
,
(
int32
)
length
);
buf
+=
(
old_format
)
?
OLD_HEADER_LEN
:
LOG_EVENT_HEADER_LEN
;
seed1
=
uint8korr
(
buf
+
RAND_SEED1_OFFSET
);
seed2
=
uint8korr
(
buf
+
RAND_SEED2_OFFSET
);
}
#endif
#ifndef MYSQL_CLIENT
int
Query_log_event
::
exec_event
(
struct
st_relay_log_info
*
rli
)
/*****************************************************************************
Rand_log_event::write_data()
****************************************************************************/
int
Rand_log_event
::
write_data
(
IO_CACHE
*
file
)
{
int
expected_error
,
actual_error
=
0
;
init_sql_alloc
(
&
thd
->
mem_root
,
8192
,
0
);
thd
->
db
=
rewrite_db
((
char
*
)
db
);
char
buf
[
16
];
int8store
(
buf
+
RAND_SEED1_OFFSET
,
seed1
);
int8store
(
buf
+
RAND_SEED2_OFFSET
,
seed2
);
return
my_b_safe_write
(
file
,
(
byte
*
)
buf
,
sizeof
(
buf
));
}
/*
InnoDB internally stores the master log position it has processed so far;
position to store is really pos + pending + event_len
since we must store the pos of the END of the current log event
*/
rli
->
event_len
=
get_event_len
();
/*****************************************************************************
if
(
db_ok
(
thd
->
db
,
replicate_do_db
,
replicate_ignore_db
))
{
thd
->
query
=
(
char
*
)
query
;
thd
->
set_time
((
time_t
)
when
);
thd
->
current_tablenr
=
0
;
VOID
(
pthread_mutex_lock
(
&
LOCK_thread_count
));
thd
->
query_id
=
query_id
++
;
VOID
(
pthread_mutex_unlock
(
&
LOCK_thread_count
));
thd
->
query_error
=
0
;
// clear error
thd
->
net
.
last_errno
=
0
;
thd
->
net
.
last_error
[
0
]
=
0
;
thd
->
slave_proxy_id
=
thread_id
;
// for temp tables
/*
Sanity check to make sure the master did not get a really bad
error on the query.
*/
if
(
ignored_error_code
((
expected_error
=
error_code
))
||
!
check_expected_error
(
thd
,
rli
,
expected_error
))
{
mysql_log
.
write
(
thd
,
COM_QUERY
,
"%s"
,
thd
->
query
);
DBUG_PRINT
(
"query"
,(
"%s"
,
thd
->
query
));
mysql_parse
(
thd
,
thd
->
query
,
q_len
);
DBUG_PRINT
(
"info"
,(
"expected_error: %d last_errno: %d"
,
expected_error
,
thd
->
net
.
last_errno
));
if
((
expected_error
!=
(
actual_error
=
thd
->
net
.
last_errno
))
&&
expected_error
&&
!
ignored_error_code
(
actual_error
)
&&
!
ignored_error_code
(
expected_error
))
{
const
char
*
errmsg
=
"Slave: did not get the expected error\
running query from master - expected: '%s' (%d), got '%s' (%d)"
;
sql_print_error
(
errmsg
,
ER_SAFE
(
expected_error
),
expected_error
,
actual_error
?
thd
->
net
.
last_error
:
"no error"
,
actual_error
);
thd
->
query_error
=
1
;
}
else
if
(
expected_error
==
actual_error
||
ignored_error_code
(
actual_error
))
{
DBUG_PRINT
(
"info"
,(
"error ignored"
));
thd
->
query_error
=
0
;
*
rli
->
last_slave_error
=
0
;
rli
->
last_slave_errno
=
0
;
}
}
else
{
// master could be inconsistent, abort and tell DBA to check/fix it
thd
->
db
=
thd
->
query
=
0
;
thd
->
variables
.
convert_set
=
0
;
close_thread_tables
(
thd
);
free_root
(
&
thd
->
mem_root
,
0
);
return
1
;
}
}
thd
->
db
=
0
;
// prevent db from being freed
thd
->
query
=
0
;
// just to be sure
// assume no convert for next query unless set explictly
thd
->
variables
.
convert_set
=
0
;
close_thread_tables
(
thd
);
if
(
thd
->
query_error
||
thd
->
fatal_error
)
Rand_log_event::print()
****************************************************************************/
#ifdef MYSQL_CLIENT
void
Rand_log_event
::
print
(
FILE
*
file
,
bool
short_form
,
char
*
last_db
)
{
char
llbuff
[
22
];
if
(
!
short_form
)
{
slave_print_error
(
rli
,
actual_error
,
"error '%s' on query '%s'"
,
actual_error
?
thd
->
net
.
last_error
:
"unexpected success or fatal error"
,
query
);
free_root
(
&
thd
->
mem_root
,
0
);
return
1
;
print_header
(
file
);
fprintf
(
file
,
"
\t
Rand
\n
"
);
}
free_root
(
&
thd
->
mem_root
,
0
);
return
Log_event
::
exec_event
(
rli
);
fprintf
(
file
,
"SET RAND SEED1=%s;
\n
"
,
llstr
(
seed1
,
llbuff
));
fprintf
(
file
,
"SET RAND SEED2=%s;
\n
"
,
llstr
(
seed2
,
llbuff
));
fflush
(
file
);
}
#endif // MYSQL_CLIENT
/*****************************************************************************
int
Load_log_event
::
exec_event
(
NET
*
net
,
struct
st_relay_log_info
*
rli
)
Rand_log_event::exec_event()
****************************************************************************/
#ifndef MYSQL_CLIENT
int
Rand_log_event
::
exec_event
(
struct
st_relay_log_info
*
rli
)
{
init_sql_alloc
(
&
thd
->
mem_root
,
8192
,
0
);
thd
->
db
=
rewrite_db
((
char
*
)
db
);
thd
->
query
=
0
;
thd
->
query_error
=
0
;
if
(
db_ok
(
thd
->
db
,
replicate_do_db
,
replicate_ignore_db
))
{
thd
->
set_time
((
time_t
)
when
);
thd
->
current_tablenr
=
0
;
VOID
(
pthread_mutex_lock
(
&
LOCK_thread_count
));
thd
->
query_id
=
query_id
++
;
VOID
(
pthread_mutex_unlock
(
&
LOCK_thread_count
));
thd
->
rand
.
seed1
=
seed1
;
thd
->
rand
.
seed2
=
seed2
;
rli
->
inc_pending
(
get_event_len
());
return
0
;
}
#endif // !MYSQL_CLIENT
TABLE_LIST
tables
;
bzero
((
char
*
)
&
tables
,
sizeof
(
tables
));
tables
.
db
=
thd
->
db
;
tables
.
alias
=
tables
.
real_name
=
(
char
*
)
table_name
;
tables
.
lock_type
=
TL_WRITE
;
// the table will be opened in mysql_load
if
(
table_rules_on
&&
!
tables_ok
(
thd
,
&
tables
))
{
// TODO: this is a bug - this needs to be moved to the I/O thread
if
(
net
)
skip_load_data_infile
(
net
);
}
else
{
char
llbuff
[
22
];
enum
enum_duplicates
handle_dup
=
DUP_IGNORE
;
if
(
sql_ex
.
opt_flags
&&
REPLACE_FLAG
)
handle_dup
=
DUP_REPLACE
;
sql_exchange
ex
((
char
*
)
fname
,
sql_ex
.
opt_flags
&&
DUMPFILE_FLAG
);
String
field_term
(
sql_ex
.
field_term
,
sql_ex
.
field_term_len
,
system_charset_info
);
String
enclosed
(
sql_ex
.
enclosed
,
sql_ex
.
enclosed_len
,
system_charset_info
);
String
line_term
(
sql_ex
.
line_term
,
sql_ex
.
line_term_len
,
system_charset_info
);
String
line_start
(
sql_ex
.
line_start
,
sql_ex
.
line_start_len
,
system_charset_info
);
String
escaped
(
sql_ex
.
escaped
,
sql_ex
.
escaped_len
,
system_charset_info
);
ex
.
opt_enclosed
=
(
sql_ex
.
opt_flags
&
OPT_ENCLOSED_FLAG
);
if
(
sql_ex
.
empty_flags
&
FIELD_TERM_EMPTY
)
ex
.
field_term
->
length
(
0
);
/*****************************************************************************
*****************************************************************************
ex
.
skip_lines
=
skip_lines
;
List
<
Item
>
fields
;
set_fields
(
fields
);
thd
->
slave_proxy_id
=
thd
->
thread_id
;
if
(
net
)
{
// mysql_load will use thd->net to read the file
thd
->
net
.
vio
=
net
->
vio
;
/*
Make sure the client does not get confused about the packet sequence
*/
thd
->
net
.
pkt_nr
=
net
->
pkt_nr
;
}
if
(
mysql_load
(
thd
,
&
ex
,
&
tables
,
fields
,
handle_dup
,
net
!=
0
,
TL_WRITE
))
thd
->
query_error
=
1
;
if
(
thd
->
cuted_fields
)
sql_print_error
(
"Slave: load data infile at position %s in log \
'%s' produced %d warning(s)"
,
llstr
(
rli
->
master_log_pos
,
llbuff
),
RPL_LOG_NAME
,
thd
->
cuted_fields
);
if
(
net
)
net
->
pkt_nr
=
thd
->
net
.
pkt_nr
;
}
}
else
{
/*
We will just ask the master to send us /dev/null if we do not
want to load the data.
TODO: this a bug - needs to be done in I/O thread
*/
if
(
net
)
skip_load_data_infile
(
net
);
}
thd
->
net
.
vio
=
0
;
thd
->
db
=
0
;
// prevent db from being freed
close_thread_tables
(
thd
);
if
(
thd
->
query_error
)
Slave_log_event methods
*****************************************************************************
****************************************************************************/
/*****************************************************************************
Slave_log_event::pack_info()
****************************************************************************/
#ifndef MYSQL_CLIENT
void
Slave_log_event
::
pack_info
(
String
*
packet
)
{
char
buf1
[
256
],
buf
[
22
],
*
end
;
String
tmp
(
buf1
,
sizeof
(
buf1
),
system_charset_info
);
tmp
.
length
(
0
);
tmp
.
append
(
"host="
);
tmp
.
append
(
master_host
);
tmp
.
append
(
",port="
);
end
=
int10_to_str
((
long
)
master_port
,
buf
,
10
);
tmp
.
append
(
buf
,
(
uint32
)
(
end
-
buf
));
tmp
.
append
(
",log="
);
tmp
.
append
(
master_log
);
tmp
.
append
(
",pos="
);
tmp
.
append
(
llstr
(
master_pos
,
buf
));
net_store_data
(
packet
,
tmp
.
ptr
(),
tmp
.
length
());
}
#endif // !MYSQL_CLIENT
/*****************************************************************************
Slave_log_event::Slave_log_event()
****************************************************************************/
#ifndef MYSQL_CLIENT
Slave_log_event
::
Slave_log_event
(
THD
*
thd_arg
,
struct
st_relay_log_info
*
rli
)
:
Log_event
(
thd_arg
),
mem_pool
(
0
),
master_host
(
0
)
{
DBUG_ENTER
(
"Slave_log_event"
);
if
(
!
rli
->
inited
)
// QQ When can this happen ?
DBUG_VOID_RETURN
;
MASTER_INFO
*
mi
=
rli
->
mi
;
// TODO: re-write this better without holding both locks at the same time
pthread_mutex_lock
(
&
mi
->
data_lock
);
pthread_mutex_lock
(
&
rli
->
data_lock
);
master_host_len
=
strlen
(
mi
->
host
);
master_log_len
=
strlen
(
rli
->
master_log_name
);
// on OOM, just do not initialize the structure and print the error
if
((
mem_pool
=
(
char
*
)
my_malloc
(
get_data_size
()
+
1
,
MYF
(
MY_WME
))))
{
int
sql_error
=
thd
->
net
.
last_errno
;
if
(
!
sql_error
)
sql_error
=
ER_UNKNOWN_ERROR
;
slave_print_error
(
rli
,
sql_error
,
"Slave: Error '%s' running load data infile "
,
ER_SAFE
(
sql_error
));
free_root
(
&
thd
->
mem_root
,
0
);
return
1
;
master_host
=
mem_pool
+
SL_MASTER_HOST_OFFSET
;
memcpy
(
master_host
,
mi
->
host
,
master_host_len
+
1
);
master_log
=
master_host
+
master_host_len
+
1
;
memcpy
(
master_log
,
rli
->
master_log_name
,
master_log_len
+
1
);
master_port
=
mi
->
port
;
master_pos
=
rli
->
master_log_pos
;
DBUG_PRINT
(
"info"
,
(
"master_log: %s pos: %d"
,
master_log
,
(
ulong
)
master_pos
));
}
free_root
(
&
thd
->
mem_root
,
0
);
if
(
thd
->
fatal_error
)
else
sql_print_error
(
"Out of memory while recording slave event"
);
pthread_mutex_unlock
(
&
rli
->
data_lock
);
pthread_mutex_unlock
(
&
mi
->
data_lock
);
DBUG_VOID_RETURN
;
}
#endif // !MYSQL_CLIENT
/*****************************************************************************
Slave_log_event dtor
****************************************************************************/
Slave_log_event
::~
Slave_log_event
()
{
my_free
(
mem_pool
,
MYF
(
MY_ALLOW_ZERO_PTR
));
}
/*****************************************************************************
Slave_log_event::print()
****************************************************************************/
#ifdef MYSQL_CLIENT
void
Slave_log_event
::
print
(
FILE
*
file
,
bool
short_form
,
char
*
last_db
)
{
char
llbuff
[
22
];
if
(
short_form
)
return
;
print_header
(
file
);
fputc
(
'\n'
,
file
);
fprintf
(
file
,
"Slave: master_host: '%s' master_port: %d \
master_log: '%s' master_pos: %s
\n
"
,
master_host
,
master_port
,
master_log
,
llstr
(
master_pos
,
llbuff
));
}
#endif // MYSQL_CLIENT
/*****************************************************************************
Slave_log_event::get_data_size()
****************************************************************************/
int
Slave_log_event
::
get_data_size
()
{
return
master_host_len
+
master_log_len
+
1
+
SL_MASTER_HOST_OFFSET
;
}
/*****************************************************************************
Slave_log_event::write_data()
****************************************************************************/
int
Slave_log_event
::
write_data
(
IO_CACHE
*
file
)
{
int8store
(
mem_pool
+
SL_MASTER_POS_OFFSET
,
master_pos
);
int2store
(
mem_pool
+
SL_MASTER_PORT_OFFSET
,
master_port
);
// log and host are already there
return
my_b_safe_write
(
file
,
(
byte
*
)
mem_pool
,
get_data_size
());
}
/*****************************************************************************
Slave_log_event::init_from_mem_pool()
****************************************************************************/
void
Slave_log_event
::
init_from_mem_pool
(
int
data_size
)
{
master_pos
=
uint8korr
(
mem_pool
+
SL_MASTER_POS_OFFSET
);
master_port
=
uint2korr
(
mem_pool
+
SL_MASTER_PORT_OFFSET
);
master_host
=
mem_pool
+
SL_MASTER_HOST_OFFSET
;
master_host_len
=
strlen
(
master_host
);
// safety
master_log
=
master_host
+
master_host_len
+
1
;
if
(
master_log
>
mem_pool
+
data_size
)
{
sql_print_error
(
"Slave: Fatal error running LOAD DATA INFILE "
)
;
return
1
;
master_host
=
0
;
return
;
}
master_log_len
=
strlen
(
master_log
);
}
return
Log_event
::
exec_event
(
rli
);
/*****************************************************************************
Slave_log_event::Slave_log_event()
****************************************************************************/
Slave_log_event
::
Slave_log_event
(
const
char
*
buf
,
int
event_len
)
:
Log_event
(
buf
,
0
),
mem_pool
(
0
),
master_host
(
0
)
{
event_len
-=
LOG_EVENT_HEADER_LEN
;
if
(
event_len
<
0
)
return
;
if
(
!
(
mem_pool
=
(
char
*
)
my_malloc
(
event_len
+
1
,
MYF
(
MY_WME
))))
return
;
memcpy
(
mem_pool
,
buf
+
LOG_EVENT_HEADER_LEN
,
event_len
);
mem_pool
[
event_len
]
=
0
;
init_from_mem_pool
(
event_len
);
}
/*****************************************************************************
/*
The master started
Slave_log_event::exec_event()
IMPLEMENTATION
- To handle the case where the master died without a stop event,
we clean up all temporary tables + locks that we got.
****************************************************************************/
#ifndef MYSQL_CLIENT
int
Slave_log_event
::
exec_event
(
struct
st_relay_log_info
*
rli
)
{
if
(
mysql_bin_log
.
is_open
())
mysql_bin_log
.
write
(
this
);
return
Log_event
::
exec_event
(
rli
);
}
#endif // !MYSQL_CLIENT
TODO
- Remove all active user locks
- If we have an active transaction at this point, the master died
in the middle while writing the transaction to the binary log.
In this case we should stop the slave.
*/
int
Start_log_event
::
exec_event
(
struct
st_relay_log_info
*
rli
)
{
/* All temporary tables was deleted on the master */
close_temporary_tables
(
thd
);
/*
If we have old format, load_tmpdir is cleaned up by the I/O thread
*/
if
(
!
rli
->
mi
->
old_format
)
cleanup_load_tmpdir
();
return
Log_event
::
exec_event
(
rli
);
/*****************************************************************************
*****************************************************************************
Stop_log_event methods
*****************************************************************************
****************************************************************************/
/*****************************************************************************
Stop_log_event::print()
****************************************************************************/
#ifdef MYSQL_CLIENT
void
Stop_log_event
::
print
(
FILE
*
file
,
bool
short_form
,
char
*
last_db
)
{
if
(
short_form
)
return
;
print_header
(
file
);
fprintf
(
file
,
"
\t
Stop
\n
"
);
fflush
(
file
);
}
#endif // MYSQL_CLIENT
/*****************************************************************************
Stop_log_event::exec_event()
/*
The master stopped. Clean up all temporary tables + locks that the
master may have set.
TODO
- Remove all active user locks
*/
****************************************************************************/
#ifndef MYSQL_CLIENT
int
Stop_log_event
::
exec_event
(
struct
st_relay_log_info
*
rli
)
{
// do not clean up immediately after rotate event
...
...
@@ -1931,70 +2103,156 @@ int Stop_log_event::exec_event(struct st_relay_log_info* rli)
flush_relay_log_info
(
rli
);
return
0
;
}
#endif // !MYSQL_CLIENT
/*
Got a rotate log even from the master
/*
****************************************************************************
*****************************************************************************
IMPLEMENTATION
This is mainly used so that we can later figure out the logname and
position for the master.
Create_file_log_event methods
We can't rotate the slave as this will cause infinitive rotations
in a A -> B -> A setup.
*****************************************************************************
****************************************************************************/
RETURN VALUES
0 ok
*/
/*****************************************************************************
int
Rotate_log_event
::
exec_event
(
struct
st_relay_log_info
*
rli
)
Create_file_log_event ctor
****************************************************************************/
#ifndef MYSQL_CLIENT
Create_file_log_event
::
Create_file_log_event
(
THD
*
thd_arg
,
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
)
:
Load_log_event
(
thd_arg
,
ex
,
db_arg
,
table_name_arg
,
fields_arg
,
handle_dup
),
fake_base
(
0
),
block
(
block_arg
),
block_len
(
block_len_arg
),
file_id
(
thd_arg
->
file_id
=
mysql_bin_log
.
next_file_id
())
{
char
*
log_name
=
rli
->
master_log_name
;
DBUG_ENTER
(
"Rotate_log_event::exec_event"
);
sql_ex
.
force_new_format
();
}
#endif // !MYSQL_CLIENT
pthread_mutex_lock
(
&
rli
->
data_lock
);
memcpy
(
log_name
,
new_log_ident
,
ident_len
+
1
);
rli
->
master_log_pos
=
pos
;
rli
->
relay_log_pos
+=
get_event_len
();
DBUG_PRINT
(
"info"
,
(
"master_log_pos: %d"
,
(
ulong
)
rli
->
master_log_pos
));
pthread_mutex_unlock
(
&
rli
->
data_lock
);
pthread_cond_broadcast
(
&
rli
->
data_cond
);
flush_relay_log_info
(
rli
);
DBUG_RETURN
(
0
);
/*****************************************************************************
Create_file_log_event::write_data_body()
****************************************************************************/
int
Create_file_log_event
::
write_data_body
(
IO_CACHE
*
file
)
{
int
res
;
if
((
res
=
Load_log_event
::
write_data_body
(
file
))
||
fake_base
)
return
res
;
return
(
my_b_safe_write
(
file
,
(
byte
*
)
""
,
1
)
||
my_b_safe_write
(
file
,
(
byte
*
)
block
,
block_len
));
}
/*****************************************************************************
Create_file_log_event::write_data_header()
int
Intvar_log_event
::
exec_event
(
struct
st_relay_log_info
*
rli
)
****************************************************************************/
int
Create_file_log_event
::
write_data_header
(
IO_CACHE
*
file
)
{
switch
(
type
)
{
case
LAST_INSERT_ID_EVENT
:
thd
->
last_insert_id_used
=
1
;
thd
->
last_insert_id
=
val
;
break
;
case
INSERT_ID_EVENT
:
thd
->
next_insert_id
=
val
;
break
;
int
res
;
if
((
res
=
Load_log_event
::
write_data_header
(
file
))
||
fake_base
)
return
res
;
byte
buf
[
CREATE_FILE_HEADER_LEN
];
int4store
(
buf
+
CF_FILE_ID_OFFSET
,
file_id
);
return
my_b_safe_write
(
file
,
buf
,
CREATE_FILE_HEADER_LEN
);
}
/*****************************************************************************
Create_file_log_event::write_base()
****************************************************************************/
int
Create_file_log_event
::
write_base
(
IO_CACHE
*
file
)
{
int
res
;
fake_base
=
1
;
// pretend we are Load event
res
=
write
(
file
);
fake_base
=
0
;
return
res
;
}
/*****************************************************************************
Create_file_log_event ctor
****************************************************************************/
Create_file_log_event
::
Create_file_log_event
(
const
char
*
buf
,
int
len
,
bool
old_format
)
:
Load_log_event
(
buf
,
0
,
old_format
),
fake_base
(
0
),
block
(
0
),
inited_from_old
(
0
)
{
int
block_offset
;
if
(
copy_log_event
(
buf
,
len
,
old_format
))
return
;
if
(
!
old_format
)
{
file_id
=
uint4korr
(
buf
+
LOG_EVENT_HEADER_LEN
+
+
LOAD_HEADER_LEN
+
CF_FILE_ID_OFFSET
);
// + 1 for \0 terminating fname
block_offset
=
(
LOG_EVENT_HEADER_LEN
+
Load_log_event
::
get_data_size
()
+
CREATE_FILE_HEADER_LEN
+
1
);
if
(
len
<
block_offset
)
return
;
block
=
(
char
*
)
buf
+
block_offset
;
block_len
=
len
-
block_offset
;
}
else
{
sql_ex
.
force_new_format
();
inited_from_old
=
1
;
}
rli
->
inc_pending
(
get_event_len
());
return
0
;
}
int
Rand_log_event
::
exec_event
(
struct
st_relay_log_info
*
rli
)
/*****************************************************************************
Create_file_log_event::print()
****************************************************************************/
#ifdef MYSQL_CLIENT
void
Create_file_log_event
::
print
(
FILE
*
file
,
bool
short_form
,
char
*
last_db
)
{
thd
->
rand
.
seed1
=
seed1
;
thd
->
rand
.
seed2
=
seed2
;
rli
->
inc_pending
(
get_event_len
()
);
return
0
;
if
(
short_form
)
return
;
Load_log_event
::
print
(
file
,
1
,
last_db
);
fprintf
(
file
,
" file_id: %d block_len: %d
\n
"
,
file_id
,
block_len
)
;
}
#endif // MYSQL_CLIENT
int
Slave_log_event
::
exec_event
(
struct
st_relay_log_info
*
rli
)
/*****************************************************************************
Create_file_log_event::pack_info()
****************************************************************************/
#ifndef MYSQL_CLIENT
void
Create_file_log_event
::
pack_info
(
String
*
packet
)
{
if
(
mysql_bin_log
.
is_open
())
mysql_bin_log
.
write
(
this
);
return
Log_event
::
exec_event
(
rli
);
char
buf1
[
256
],
buf
[
22
],
*
end
;
String
tmp
(
buf1
,
sizeof
(
buf1
),
system_charset_info
);
tmp
.
length
(
0
);
tmp
.
append
(
"db="
);
tmp
.
append
(
db
,
db_len
);
tmp
.
append
(
";table="
);
tmp
.
append
(
table_name
,
table_name_len
);
tmp
.
append
(
";file_id="
);
end
=
int10_to_str
((
long
)
file_id
,
buf
,
10
);
tmp
.
append
(
buf
,
(
uint32
)
(
end
-
buf
));
tmp
.
append
(
";block_len="
);
end
=
int10_to_str
((
long
)
block_len
,
buf
,
10
);
tmp
.
append
(
buf
,
(
uint32
)
(
end
-
buf
));
net_store_data
(
packet
,
(
char
*
)
tmp
.
ptr
(),
tmp
.
length
());
}
#endif // !MYSQL_CLIENT
/*****************************************************************************
Create_file_log_event::exec_event()
****************************************************************************/
#ifndef MYSQL_CLIENT
int
Create_file_log_event
::
exec_event
(
struct
st_relay_log_info
*
rli
)
{
char
fname_buf
[
FN_REFLEN
+
10
];
...
...
@@ -2051,20 +2309,100 @@ int Create_file_log_event::exec_event(struct st_relay_log_info* rli)
my_close
(
fd
,
MYF
(
0
));
return
error
?
1
:
Log_event
::
exec_event
(
rli
);
}
#endif // !MYSQL_CLIENT
int
Delete_file_log_event
::
exec_event
(
struct
st_relay_log_info
*
rli
)
/*****************************************************************************
*****************************************************************************
Append_block_log_event methods
*****************************************************************************
****************************************************************************/
/*****************************************************************************
Append_block_log_event ctor
****************************************************************************/
#ifndef MYSQL_CLIENT
Append_block_log_event
::
Append_block_log_event
(
THD
*
thd_arg
,
char
*
block_arg
,
uint
block_len_arg
)
:
Log_event
(
thd_arg
),
block
(
block_arg
),
block_len
(
block_len_arg
),
file_id
(
thd_arg
->
file_id
)
{
char
fname
[
FN_REFLEN
+
10
];
char
*
p
=
slave_load_file_stem
(
fname
,
file_id
,
server_id
);
memcpy
(
p
,
".data"
,
6
);
(
void
)
my_delete
(
fname
,
MYF
(
MY_WME
));
memcpy
(
p
,
".info"
,
6
);
(
void
)
my_delete
(
fname
,
MYF
(
MY_WME
));
if
(
mysql_bin_log
.
is_open
())
mysql_bin_log
.
write
(
this
);
return
Log_event
::
exec_event
(
rli
);
}
#endif // !MYSQL_CLIENT
/*****************************************************************************
Append_block_log_event ctor
****************************************************************************/
Append_block_log_event
::
Append_block_log_event
(
const
char
*
buf
,
int
len
)
:
Log_event
(
buf
,
0
),
block
(
0
)
{
if
((
uint
)
len
<
APPEND_BLOCK_EVENT_OVERHEAD
)
return
;
file_id
=
uint4korr
(
buf
+
LOG_EVENT_HEADER_LEN
+
AB_FILE_ID_OFFSET
);
block
=
(
char
*
)
buf
+
APPEND_BLOCK_EVENT_OVERHEAD
;
block_len
=
len
-
APPEND_BLOCK_EVENT_OVERHEAD
;
}
/*****************************************************************************
Append_block_log_event::write_data()
****************************************************************************/
int
Append_block_log_event
::
write_data
(
IO_CACHE
*
file
)
{
byte
buf
[
APPEND_BLOCK_HEADER_LEN
];
int4store
(
buf
+
AB_FILE_ID_OFFSET
,
file_id
);
return
(
my_b_safe_write
(
file
,
buf
,
APPEND_BLOCK_HEADER_LEN
)
||
my_b_safe_write
(
file
,
(
byte
*
)
block
,
block_len
));
}
/*****************************************************************************
Append_block_log_event::print()
****************************************************************************/
#ifdef MYSQL_CLIENT
void
Append_block_log_event
::
print
(
FILE
*
file
,
bool
short_form
,
char
*
last_db
)
{
if
(
short_form
)
return
;
print_header
(
file
);
fputc
(
'\n'
,
file
);
fprintf
(
file
,
"#Append_block: file_id: %d block_len: %d
\n
"
,
file_id
,
block_len
);
}
#endif // MYSQL_CLIENT
/*****************************************************************************
Append_block_log_event::pack_info()
****************************************************************************/
#ifndef MYSQL_CLIENT
void
Append_block_log_event
::
pack_info
(
String
*
packet
)
{
char
buf
[
256
];
uint
length
;
length
=
(
uint
)
my_sprintf
(
buf
,
(
buf
,
";file_id=%u;block_len=%u"
,
file_id
,
block_len
));
net_store_data
(
packet
,
buf
,
(
int32
)
length
);
}
#endif // !MYSQL_CLIENT
/*****************************************************************************
Append_block_log_event::exec_event()
****************************************************************************/
#ifndef MYSQL_CLIENT
int
Append_block_log_event
::
exec_event
(
struct
st_relay_log_info
*
rli
)
{
char
fname
[
FN_REFLEN
+
10
];
...
...
@@ -2092,7 +2430,191 @@ int Append_block_log_event::exec_event(struct st_relay_log_info* rli)
my_close
(
fd
,
MYF
(
0
));
return
error
?
error
:
Log_event
::
exec_event
(
rli
);
}
#endif // !MYSQL_CLIENT
/*****************************************************************************
*****************************************************************************
Delete_file_log_event methods
*****************************************************************************
****************************************************************************/
/*****************************************************************************
Delete_file_log_event ctor
****************************************************************************/
#ifndef MYSQL_CLIENT
Delete_file_log_event
::
Delete_file_log_event
(
THD
*
thd_arg
)
:
Log_event
(
thd_arg
),
file_id
(
thd_arg
->
file_id
)
{
}
#endif // !MYSQL_CLIENT
/*****************************************************************************
Delete_file_log_event ctor
****************************************************************************/
Delete_file_log_event
::
Delete_file_log_event
(
const
char
*
buf
,
int
len
)
:
Log_event
(
buf
,
0
),
file_id
(
0
)
{
if
((
uint
)
len
<
DELETE_FILE_EVENT_OVERHEAD
)
return
;
file_id
=
uint4korr
(
buf
+
LOG_EVENT_HEADER_LEN
+
AB_FILE_ID_OFFSET
);
}
/*****************************************************************************
Delete_file_log_event::write_data()
****************************************************************************/
int
Delete_file_log_event
::
write_data
(
IO_CACHE
*
file
)
{
byte
buf
[
DELETE_FILE_HEADER_LEN
];
int4store
(
buf
+
DF_FILE_ID_OFFSET
,
file_id
);
return
my_b_safe_write
(
file
,
buf
,
DELETE_FILE_HEADER_LEN
);
}
/*****************************************************************************
Delete_file_log_event::print()
****************************************************************************/
#ifdef MYSQL_CLIENT
void
Delete_file_log_event
::
print
(
FILE
*
file
,
bool
short_form
,
char
*
last_db
)
{
if
(
short_form
)
return
;
print_header
(
file
);
fputc
(
'\n'
,
file
);
fprintf
(
file
,
"#Delete_file: file_id=%u
\n
"
,
file_id
);
}
#endif // MYSQL_CLIENT
/*****************************************************************************
Delete_file_log_event::pack_info()
****************************************************************************/
#ifndef MYSQL_CLIENT
void
Delete_file_log_event
::
pack_info
(
String
*
packet
)
{
char
buf
[
64
];
uint
length
;
length
=
(
uint
)
my_sprintf
(
buf
,
(
buf
,
";file_id=%u"
,
(
uint
)
file_id
));
net_store_data
(
packet
,
buf
,
(
int32
)
length
);
}
#endif // !MYSQL_CLIENT
/*****************************************************************************
Delete_file_log_event::exec_event()
****************************************************************************/
#ifndef MYSQL_CLIENT
int
Delete_file_log_event
::
exec_event
(
struct
st_relay_log_info
*
rli
)
{
char
fname
[
FN_REFLEN
+
10
];
char
*
p
=
slave_load_file_stem
(
fname
,
file_id
,
server_id
);
memcpy
(
p
,
".data"
,
6
);
(
void
)
my_delete
(
fname
,
MYF
(
MY_WME
));
memcpy
(
p
,
".info"
,
6
);
(
void
)
my_delete
(
fname
,
MYF
(
MY_WME
));
if
(
mysql_bin_log
.
is_open
())
mysql_bin_log
.
write
(
this
);
return
Log_event
::
exec_event
(
rli
);
}
#endif // !MYSQL_CLIENT
/*****************************************************************************
*****************************************************************************
Execute_load_log_event methods
*****************************************************************************
****************************************************************************/
/*****************************************************************************
Execute_load_log_event ctor
****************************************************************************/
#ifndef MYSQL_CLIENT
Execute_load_log_event
::
Execute_load_log_event
(
THD
*
thd_arg
)
:
Log_event
(
thd_arg
),
file_id
(
thd_arg
->
file_id
)
{
}
#endif // !MYSQL_CLIENT
/*****************************************************************************
Execute_load_log_event ctor
****************************************************************************/
Execute_load_log_event
::
Execute_load_log_event
(
const
char
*
buf
,
int
len
)
:
Log_event
(
buf
,
0
),
file_id
(
0
)
{
if
((
uint
)
len
<
EXEC_LOAD_EVENT_OVERHEAD
)
return
;
file_id
=
uint4korr
(
buf
+
LOG_EVENT_HEADER_LEN
+
EL_FILE_ID_OFFSET
);
}
/*****************************************************************************
Execute_load_log_event::write_data()
****************************************************************************/
int
Execute_load_log_event
::
write_data
(
IO_CACHE
*
file
)
{
byte
buf
[
EXEC_LOAD_HEADER_LEN
];
int4store
(
buf
+
EL_FILE_ID_OFFSET
,
file_id
);
return
my_b_safe_write
(
file
,
buf
,
EXEC_LOAD_HEADER_LEN
);
}
/*****************************************************************************
Execute_load_log_event::print()
****************************************************************************/
#ifdef MYSQL_CLIENT
void
Execute_load_log_event
::
print
(
FILE
*
file
,
bool
short_form
,
char
*
last_db
)
{
if
(
short_form
)
return
;
print_header
(
file
);
fputc
(
'\n'
,
file
);
fprintf
(
file
,
"#Exec_load: file_id=%d
\n
"
,
file_id
);
}
#endif // MYSQL_CLIENT
/*****************************************************************************
Execute_load_log_event::pack_info()
****************************************************************************/
#ifndef MYSQL_CLIENT
void
Execute_load_log_event
::
pack_info
(
String
*
packet
)
{
char
buf
[
64
];
uint
length
;
length
=
(
uint
)
my_sprintf
(
buf
,
(
buf
,
";file_id=%u"
,
(
uint
)
file_id
));
net_store_data
(
packet
,
buf
,
(
int32
)
length
);
}
#endif // !MYSQL_CLIENT
/*****************************************************************************
Execute_load_log_event::exec_event()
****************************************************************************/
#ifndef MYSQL_CLIENT
int
Execute_load_log_event
::
exec_event
(
struct
st_relay_log_info
*
rli
)
{
char
fname
[
FN_REFLEN
+
10
];
...
...
@@ -2151,5 +2673,100 @@ int Execute_load_log_event::exec_event(struct st_relay_log_info* rli)
}
return
error
?
error
:
Log_event
::
exec_event
(
rli
);
}
#endif // !MYSQL_CLIENT
/*****************************************************************************
*****************************************************************************
sql_ex_info methods
*****************************************************************************
****************************************************************************/
/*****************************************************************************
sql_ex_info::write_data()
****************************************************************************/
int
sql_ex_info
::
write_data
(
IO_CACHE
*
file
)
{
if
(
new_format
())
{
return
(
write_str
(
file
,
field_term
,
field_term_len
)
||
write_str
(
file
,
enclosed
,
enclosed_len
)
||
write_str
(
file
,
line_term
,
line_term_len
)
||
write_str
(
file
,
line_start
,
line_start_len
)
||
write_str
(
file
,
escaped
,
escaped_len
)
||
my_b_safe_write
(
file
,(
byte
*
)
&
opt_flags
,
1
));
}
else
{
old_sql_ex
old_ex
;
old_ex
.
field_term
=
*
field_term
;
old_ex
.
enclosed
=
*
enclosed
;
old_ex
.
line_term
=
*
line_term
;
old_ex
.
line_start
=
*
line_start
;
old_ex
.
escaped
=
*
escaped
;
old_ex
.
opt_flags
=
opt_flags
;
old_ex
.
empty_flags
=
empty_flags
;
return
my_b_safe_write
(
file
,
(
byte
*
)
&
old_ex
,
sizeof
(
old_ex
));
}
}
/*****************************************************************************
sql_ex_info::init()
****************************************************************************/
char
*
sql_ex_info
::
init
(
char
*
buf
,
char
*
buf_end
,
bool
use_new_format
)
{
cached_new_format
=
use_new_format
;
if
(
use_new_format
)
{
empty_flags
=
0
;
/*
The code below assumes that buf will not disappear from
under our feet during the lifetime of the event. This assumption
holds true in the slave thread if the log is in new format, but is not
the case when we have old format because we will be reusing net buffer
to read the actual file before we write out the Create_file event.
*/
if
(
read_str
(
buf
,
buf_end
,
field_term
,
field_term_len
)
||
read_str
(
buf
,
buf_end
,
enclosed
,
enclosed_len
)
||
read_str
(
buf
,
buf_end
,
line_term
,
line_term_len
)
||
read_str
(
buf
,
buf_end
,
line_start
,
line_start_len
)
||
read_str
(
buf
,
buf_end
,
escaped
,
escaped_len
))
return
0
;
opt_flags
=
*
buf
++
;
}
else
{
field_term_len
=
enclosed_len
=
line_term_len
=
line_start_len
=
escaped_len
=
1
;
field_term
=
buf
++
;
// Use first byte in string
enclosed
=
buf
++
;
line_term
=
buf
++
;
line_start
=
buf
++
;
escaped
=
buf
++
;
opt_flags
=
*
buf
++
;
empty_flags
=
*
buf
++
;
if
(
empty_flags
&
FIELD_TERM_EMPTY
)
field_term_len
=
0
;
if
(
empty_flags
&
ENCLOSED_EMPTY
)
enclosed_len
=
0
;
if
(
empty_flags
&
LINE_TERM_EMPTY
)
line_term_len
=
0
;
if
(
empty_flags
&
LINE_START_EMPTY
)
line_start_len
=
0
;
if
(
empty_flags
&
ESCAPED_EMPTY
)
escaped_len
=
0
;
}
return
buf
;
}
#endif
/* !MYSQL_CLIENT */
sql/log_event.h
View file @
26a1d888
...
...
@@ -54,6 +54,11 @@
#define LINE_START_EMPTY 0x8
#define ESCAPED_EMPTY 0x10
/*****************************************************************************
old_sql_ex struct
****************************************************************************/
struct
old_sql_ex
{
char
field_term
;
...
...
@@ -67,6 +72,11 @@ struct old_sql_ex
#define NUM_LOAD_DELIM_STRS 5
/*****************************************************************************
sql_ex_info struct
****************************************************************************/
struct
sql_ex_info
{
char
*
field_term
;
...
...
@@ -99,13 +109,19 @@ struct sql_ex_info
}
};
/*
Binary log consists of events. Each event has a fixed length header,
followed by possibly variable ( depending on the type of event) length
data body. The data body consists of an optional fixed length segment
(post-header), and an optional variable length segment. See #defines and
comments below for the format specifics
*/
/*****************************************************************************
MySQL Binary Log
This log consists of events. Each event has a fixed-length header,
possibly followed by a variable length data body.
The data body consists of an optional fixed length segment (post-header)
and an optional variable length segment.
See the #defines below for the format specifics.
****************************************************************************/
/* event-specific post-header sizes */
#define LOG_EVENT_HEADER_LEN 19
...
...
@@ -221,6 +237,13 @@ class THD;
struct
st_relay_log_info
;
/*****************************************************************************
Log_event class
This is the abstract base class for binary log events.
****************************************************************************/
class
Log_event
{
public:
...
...
@@ -303,6 +326,13 @@ class Log_event
};
/*****************************************************************************
Query Log Event class
Logs SQL queries
****************************************************************************/
class
Query_log_event
:
public
Log_event
{
protected:
...
...
@@ -355,6 +385,11 @@ class Query_log_event: public Log_event
};
/*****************************************************************************
Slave Log Event class
****************************************************************************/
class
Slave_log_event
:
public
Log_event
{
protected:
...
...
@@ -384,6 +419,12 @@ class Slave_log_event: public Log_event
int
write_data
(
IO_CACHE
*
file
);
};
/*****************************************************************************
Load Log Event class
****************************************************************************/
class
Load_log_event
:
public
Log_event
{
protected:
...
...
@@ -446,6 +487,11 @@ class Load_log_event: public Log_event
extern
char
server_version
[
SERVER_VERSION_LENGTH
];
/*****************************************************************************
Start Log Event class
****************************************************************************/
class
Start_log_event
:
public
Log_event
{
public:
...
...
@@ -477,6 +523,13 @@ class Start_log_event: public Log_event
};
/*****************************************************************************
Intvar Log Event class
Logs special variables such as auto_increment values
****************************************************************************/
class
Intvar_log_event
:
public
Log_event
{
public:
...
...
@@ -503,9 +556,11 @@ class Intvar_log_event: public Log_event
};
/*****************************************************************************
*
* Rand log event class
*
Rand Log Event class
Logs random seed used by the next RAND()
****************************************************************************/
class
Rand_log_event
:
public
Log_event
{
...
...
@@ -531,6 +586,12 @@ class Rand_log_event: public Log_event
bool
is_valid
()
{
return
1
;
}
};
/*****************************************************************************
Stop Log Event class
****************************************************************************/
class
Stop_log_event
:
public
Log_event
{
public:
...
...
@@ -551,6 +612,13 @@ class Stop_log_event: public Log_event
};
/*****************************************************************************
Rotate Log Event class
This will be depricated when we move to using sequence ids.
****************************************************************************/
class
Rotate_log_event
:
public
Log_event
{
public:
...
...
@@ -585,6 +653,11 @@ class Rotate_log_event: public Log_event
/* the classes below are for the new LOAD DATA INFILE logging */
/*****************************************************************************
Create File Log Event class
****************************************************************************/
class
Create_file_log_event
:
public
Load_log_event
{
protected:
...
...
@@ -641,6 +714,11 @@ class Create_file_log_event: public Load_log_event
};
/*****************************************************************************
Append Block Log Event class
****************************************************************************/
class
Append_block_log_event
:
public
Log_event
{
public:
...
...
@@ -665,7 +743,11 @@ class Append_block_log_event: public Log_event
int
write_data
(
IO_CACHE
*
file
);
};
/*****************************************************************************
Delete File Log Event class
****************************************************************************/
class
Delete_file_log_event
:
public
Log_event
{
public:
...
...
@@ -687,6 +769,11 @@ class Delete_file_log_event: public Log_event
int
write_data
(
IO_CACHE
*
file
);
};
/*****************************************************************************
Execute Load Log Event class
****************************************************************************/
class
Execute_load_log_event
:
public
Log_event
{
public:
...
...
sql/sql_derived.cc
View file @
26a1d888
...
...
@@ -70,7 +70,7 @@ int mysql_derived(THD *thd, LEX *lex, SELECT_LEX_UNIT *unit, TABLE_LIST *t,
if
(
tables_is_opened
||
!
(
res
=
open_and_lock_tables
(
thd
,
tables
)))
{
if
(
tables
&&
setup_fields
(
thd
,
tables
,
item_list
,
0
,
0
,
1
))
if
(
setup_fields
(
thd
,
tables
,
item_list
,
0
,
0
,
1
))
{
res
=-
1
;
goto
exit
;
...
...
@@ -113,6 +113,7 @@ int mysql_derived(THD *thd, LEX *lex, SELECT_LEX_UNIT *unit, TABLE_LIST *t,
t
->
table
=
table
;
table
->
derived_select_number
=
sl
->
select_number
;
sl
->
exclude
();
t
->
db
=
(
tables
&&
tables
->
db
&&
tables
->
db
[
0
])
?
t
->
db
:
thd
->
db
;
t
->
derived
=
(
SELECT_LEX
*
)
0
;
// just in case ...
}
}
...
...
sql/sql_parse.cc
View file @
26a1d888
...
...
@@ -1388,10 +1388,14 @@ mysql_execute_command(THD *thd)
for
(
TABLE_LIST
*
cursor
=
tables
;
cursor
;
cursor
=
cursor
->
next
)
if
(
cursor
->
derived
&&
mysql_derived
(
thd
,
lex
,
if
(
cursor
->
derived
&&
(
res
=
mysql_derived
(
thd
,
lex
,
(
SELECT_LEX_UNIT
*
)
cursor
->
derived
,
cursor
,
0
))
cursor
,
0
)))
{
if
(
res
<
0
)
send_error
(
thd
,
thd
->
killed
?
ER_SERVER_SHUTDOWN
:
0
);
DBUG_VOID_RETURN
;
}
}
if
((
lex
->
select_lex
.
next_select_in_list
()
&&
lex
->
unit
.
create_total_list
(
thd
,
lex
,
&
tables
))
||
...
...
@@ -2781,7 +2785,7 @@ check_table_access(THD *thd, ulong want_access,TABLE_LIST *tables,
found
=
1
;
}
}
else
if
(
check_access
(
thd
,
want_access
,
tables
->
db
,
&
tables
->
grant
.
privilege
,
else
if
(
tables
->
db
&&
check_access
(
thd
,
want_access
,
tables
->
db
,
&
tables
->
grant
.
privilege
,
0
,
no_errors
))
return
TRUE
;
}
...
...
sql/sql_test.cc
View file @
26a1d888
...
...
@@ -26,6 +26,23 @@
/* Intern key cache variables */
extern
"C"
pthread_mutex_t
THR_LOCK_keycache
;
static
const
char
*
lock_descriptions
[]
=
{
"No lock"
,
"Low priority read lock"
,
"Shared Read lock"
,
"High priority read lock"
,
"Read lock without concurrent inserts"
,
"Write lock that allows other writers"
,
"Write lock, but allow reading"
,
"Concurrent insert lock"
,
"Lock Used by delayed insert"
,
"Low priority write lock"
,
"High priority write lock"
,
"Highest priority write lock"
};
#ifndef DBUG_OFF
void
...
...
@@ -45,29 +62,11 @@ print_where(COND *cond,const char *info)
DBUG_UNLOCK_FILE
;
}
}
/* This is for debugging purposes */
extern
HASH
open_cache
;
extern
TABLE
*
unused_tables
;
static
const
char
*
lock_descriptions
[]
=
{
"No lock"
,
"Low priority read lock"
,
"Shared Read lock"
,
"High priority read lock"
,
"Read lock without concurrent inserts"
,
"Write lock that allows other writers"
,
"Write lock, but allow reading"
,
"Concurrent insert lock"
,
"Lock Used by delayed insert"
,
"Low priority write lock"
,
"High priority write lock"
,
"Highest priority write lock"
};
void
print_cached_tables
(
void
)
{
uint
idx
,
count
,
unused
;
...
...
@@ -203,6 +202,99 @@ TEST_join(JOIN *join)
#endif
typedef
struct
st_debug_lock
{
ulong
thread_id
;
char
table_name
[
FN_REFLEN
];
bool
waiting
;
const
char
*
lock_text
;
enum
thr_lock_type
type
;
}
TABLE_LOCK_INFO
;
static
int
dl_compare
(
TABLE_LOCK_INFO
*
a
,
TABLE_LOCK_INFO
*
b
)
{
if
(
a
->
thread_id
>
b
->
thread_id
)
return
1
;
if
(
a
->
thread_id
<
b
->
thread_id
)
return
-
1
;
if
(
a
->
waiting
==
b
->
waiting
)
return
0
;
else
if
(
a
->
waiting
)
return
-
1
;
return
1
;
}
static
void
push_locks_into_array
(
DYNAMIC_ARRAY
*
ar
,
THR_LOCK_DATA
*
data
,
bool
wait
,
const
char
*
text
)
{
if
(
data
)
{
TABLE
*
table
=
(
TABLE
*
)
data
->
debug_print_param
;
if
(
table
&&
table
->
tmp_table
==
NO_TMP_TABLE
)
{
TABLE_LOCK_INFO
table_lock_info
;
table_lock_info
.
thread_id
=
table
->
in_use
->
thread_id
;
memcpy
(
table_lock_info
.
table_name
,
table
->
table_cache_key
,
table
->
key_length
);
table_lock_info
.
table_name
[
strlen
(
table_lock_info
.
table_name
)]
=
'.'
;
table_lock_info
.
waiting
=
wait
;
table_lock_info
.
lock_text
=
text
;
table_lock_info
.
type
=
table
->
reginfo
.
lock_type
;
// obtainable also from THR_LOCK_DATA
VOID
(
push_dynamic
(
ar
,(
gptr
)
&
table_lock_info
));
}
}
}
/*
Regarding MERGE tables:
For now, the best option is to use the common TABLE *pointer for all
cases; The drawback is that for MERGE tables we will see many locks
for the merge tables even if some of them are for individual tables.
The way to solve this is to add to 'THR_LOCK' structure a pointer to
the filename and use this when printing the data.
(We can for now ignore this and just print the same name for all merge
table parts; Please add the above as a comment to the display_lock
function so that we can easily add this if we ever need this.
*/
static
void
display_table_locks
(
void
)
{
LIST
*
list
;
DYNAMIC_ARRAY
saved_table_locks
;
VOID
(
my_init_dynamic_array
(
&
saved_table_locks
,
sizeof
(
TABLE_LOCK_INFO
),
open_cache
.
records
+
20
,
50
));
VOID
(
pthread_mutex_lock
(
&
THR_LOCK_lock
));
for
(
list
=
thr_lock_thread_list
;
list
;
list
=
rest
(
list
))
{
THR_LOCK
*
lock
=
(
THR_LOCK
*
)
list
->
data
;
VOID
(
pthread_mutex_lock
(
&
lock
->
mutex
));
push_locks_into_array
(
&
saved_table_locks
,
lock
->
write
.
data
,
false
,
"Locked - write"
);
push_locks_into_array
(
&
saved_table_locks
,
lock
->
write_wait
.
data
,
true
,
"Waiting - write"
);
push_locks_into_array
(
&
saved_table_locks
,
lock
->
read
.
data
,
false
,
"Locked - read"
);
push_locks_into_array
(
&
saved_table_locks
,
lock
->
read_wait
.
data
,
true
,
"Waiting - read"
);
VOID
(
pthread_mutex_unlock
(
&
lock
->
mutex
));
}
VOID
(
pthread_mutex_unlock
(
&
THR_LOCK_lock
));
if
(
!
saved_table_locks
.
elements
)
goto
end
;
qsort
((
gptr
)
dynamic_element
(
&
saved_table_locks
,
0
,
TABLE_LOCK_INFO
*
),
saved_table_locks
.
elements
,
sizeof
(
TABLE_LOCK_INFO
),(
qsort_cmp
)
dl_compare
);
freeze_size
(
&
saved_table_locks
);
puts
(
"
\n
Thread database.table_name Locked/Waiting Lock_type
\n
"
);
for
(
uint
i
=
0
;
i
<
saved_table_locks
.
elements
;
i
++
)
{
TABLE_LOCK_INFO
*
dl_ptr
=
dynamic_element
(
&
saved_table_locks
,
i
,
TABLE_LOCK_INFO
*
);
printf
(
"%-8ld%-28.28s%-22s%s
\n
"
,
dl_ptr
->
thread_id
,
dl_ptr
->
table_name
,
dl_ptr
->
lock_text
,
lock_descriptions
[(
int
)
dl_ptr
->
type
]);
}
puts
(
"
\n\n
"
);
end:
delete_dynamic
(
&
saved_table_locks
);
}
void
mysql_print_status
(
THD
*
thd
)
{
char
current_dir
[
FN_REFLEN
];
...
...
@@ -268,6 +360,7 @@ Next alarm time: %lu\n",
alarm_info
.
max_used_alarms
,
alarm_info
.
next_alarm_time
);
#endif
display_table_locks
();
fflush
(
stdout
);
if
(
thd
)
thd
->
proc_info
=
"malloc"
;
...
...
sql/sql_yacc.yy
View file @
26a1d888
...
...
@@ -1449,20 +1449,6 @@ slave:
lex->sql_command = SQLCOM_SLAVE_STOP;
lex->type = 0;
};
|
SLAVE START_SYM slave_thread_opts
{
LEX *lex=Lex;
lex->sql_command = SQLCOM_SLAVE_START;
lex->type = 0;
}
|
SLAVE STOP_SYM slave_thread_opts
{
LEX *lex=Lex;
lex->sql_command = SQLCOM_SLAVE_STOP;
lex->type = 0;
};
slave_thread_opts:
slave_thread_opt
...
...
strings/longlong2str-x86.s
View file @
26a1d888
...
...
@@ -64,7 +64,7 @@ longlong2str:
jne
.
L150
movb
$
48
,(%
edi
)
incl
%
edi
jmp
.
L1
64
jmp
.
L1
0_end
.
align
4
.
L150
:
...
...
@@ -81,9 +81,9 @@ longlong2str:
movl
%
eax
,%
ebp
movl
%
esi
,%
eax
divl
%
ebx
decl
%
ecx
movl
%
eax
,%
esi
#
quotent
in
ebp
:
esi
movb
_dig_vec
(%
edx
),%
al
#
al
is
faster
than
dl
decl
%
ecx
movb
%
al
,(%
ecx
)
#
store
value
in
buff
.
align
4
.
L155
:
...
...
@@ -91,7 +91,7 @@ longlong2str:
ja
.
L153
testl
%
esi
,%
esi
#
rest
value
jl
.
L153
je
.
L1
60
#
Ready
je
.
L1
0_mov
#
Ready
movl
%
esi
,%
eax
movl
$
_dig_vec
,%
ebp
.
align
4
...
...
@@ -105,14 +105,14 @@ longlong2str:
movb
%
dl
,(%
ecx
)
jne
.
L154
.
L1
60
:
.
L1
0_mov
:
movl
%
ecx
,%
esi
leal
92
(%
esp
),%
ecx
#
End
of
buffer
subl
%
esi
,%
ecx
rep
movsb
.
L1
64
:
.
L1
0_end
:
movl
%
edi
,%
eax
#
Pointer
to
end
null
movb
$
0
,(%
edi
)
#
Store
the
end
null
...
...
@@ -131,10 +131,93 @@ longlong2str:
.
Lfe3
:
.
size
longlong2str
,
.
Lfe3
-
longlong2str
#
#
This
is
almost
equal
to
the
above
,
except
that
we
can
do
the
final
#
loop
much
more
efficient
#
.
align
4
.
Ltmp
:
.
long
0xcccccccd
.
align
4
.
globl
longlong10_to_str
.
type
longlong10_str
,
@
function
longlong10_to_str
:
jmp
longlong2str
subl
$
80
,%
esp
pushl
%
ebp
pushl
%
esi
pushl
%
edi
pushl
%
ebx
movl
100
(%
esp
),%
esi
#
Lower
part
of
val
movl
104
(%
esp
),%
ebp
#
Higher
part
of
val
movl
108
(%
esp
),%
edi
#
get
dst
movl
112
(%
esp
),%
ebx
#
Radix
(
10
or
-
10
)
testl
%
ebx
,%
ebx
jge
.
L10_10
#
Positive
radix
negl
%
ebx
#
Change
radix
to
positive
(=
10
)
testl
%
ebp
,%
ebp
#
Test
if
negative
value
jge
.
L10_10
movb
$
45
,(%
edi
)
#
Add
sign
incl
%
edi
negl
%
esi
#
Change
sign
of
val
(
ebp
:
esi
)
adcl
$
0
,%
ebp
negl
%
ebp
.
align
4
.
L10_10
:
leal
92
(%
esp
),%
ecx
#
End
of
buffer
movl
%
esi
,%
eax
#
Test
if
zero
(
for
easy
loop
)
orl
%
ebp
,%
eax
jne
.
L10_30
#
Not
zero
#
Here
when
value
is
zero
movb
$
48
,(%
edi
)
incl
%
edi
jmp
.
L10_end
.
align
4
.
L10_20
:
#
val
is
stored
in
in
ebp
:
esi
movl
%
ebp
,%
eax
#
High
part
of
value
xorl
%
edx
,%
edx
divl
%
ebx
#
Divide
by
10
movl
%
eax
,%
ebp
movl
%
esi
,%
eax
divl
%
ebx
#
Divide
by
10
decl
%
ecx
movl
%
eax
,%
esi
#
quotent
in
ebp
:
esi
addl
$
48
,%
edx
#
Convert
to
ascii
movb
%
dl
,(%
ecx
)
#
store
value
in
buff
.
L10_30
:
testl
%
ebp
,%
ebp
ja
.
L10_20
testl
%
esi
,%
esi
#
rest
value
jl
.
L10_20
#
Unsigned
,
do
ulonglong
div
once
more
je
.
L10_mov
#
Ready
movl
%
esi
,%
ebx
#
Move
val
to
%
ebx
#
The
following
code
uses
some
tricks
to
change
division
by
10
to
#
multiplication
and
shifts
movl
.
Ltmp
,%
esi
#
set
%
esi
to
0xcccccccd
.
L10_40
:
movl
%
ebx
,%
eax
mull
%
esi
decl
%
ecx
shrl
$
3
,%
edx
leal
(%
edx
,%
edx
,
4
),%
eax
addl
%
eax
,%
eax
subb
%
al
,%
bl
#
%
bl
now
contains
val
%
10
addb
$
48
,%
bl
movb
%
bl
,(%
ecx
)
movl
%
edx
,%
ebx
testl
%
ebx
,%
ebx
jne
.
L10_40
jmp
.
L10_mov
#
Shared
end
with
longlong10_to_str
.
L10end
:
.
size
longlong10_to_str
,
.
L10end
-
longlong10_to_str
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment