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
Analytics
Analytics
Repository
Value Stream
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Commits
Issue Boards
Open sidebar
Kirill Smelkov
mariadb
Commits
fec70c97
Commit
fec70c97
authored
May 05, 2006
by
petr@mysql.com
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
WL#3153 "Split logs". Recommit with post-review fixes
parent
55ccf0fe
Changes
11
Show whitespace changes
Inline
Side-by-side
Showing
11 changed files
with
691 additions
and
481 deletions
+691
-481
sql/ha_ndbcluster_binlog.cc
sql/ha_ndbcluster_binlog.cc
+2
-2
sql/log.cc
sql/log.cc
+590
-414
sql/log.h
sql/log.h
+84
-51
sql/log_event.h
sql/log_event.h
+1
-1
sql/mysql_priv.h
sql/mysql_priv.h
+1
-1
sql/mysqld.cc
sql/mysqld.cc
+3
-3
sql/rpl_injector.cc
sql/rpl_injector.cc
+1
-1
sql/rpl_injector.h
sql/rpl_injector.h
+2
-2
sql/rpl_rli.h
sql/rpl_rli.h
+1
-1
sql/slave.cc
sql/slave.cc
+4
-3
sql/slave.h
sql/slave.h
+2
-2
No files found.
sql/ha_ndbcluster_binlog.cc
View file @
fec70c97
...
...
@@ -428,7 +428,7 @@ static void ndbcluster_binlog_wait(THD *thd)
}
/*
Called from MYSQL_LOG::reset_logs in log.cc when binlog is emptied
Called from MYSQL_
BIN_
LOG::reset_logs in log.cc when binlog is emptied
*/
static
int
ndbcluster_reset_logs
(
THD
*
thd
)
{
...
...
@@ -452,7 +452,7 @@ static int ndbcluster_reset_logs(THD *thd)
}
/*
Called from MYSQL_LOG::purge_logs in log.cc when the binlog "file"
Called from MYSQL_
BIN_
LOG::purge_logs in log.cc when the binlog "file"
is removed
*/
...
...
sql/log.cc
View file @
fec70c97
...
...
@@ -42,7 +42,7 @@ extern char *opt_logname, *opt_slow_logname;
LOGGER
logger
;
MYSQL_LOG
mysql_bin_log
;
MYSQL_
BIN_
LOG
mysql_bin_log
;
ulong
sync_binlog_counter
=
0
;
static
bool
test_if_number
(
const
char
*
str
,
...
...
@@ -557,9 +557,8 @@ void Log_to_file_event_handler::cleanup()
void
Log_to_file_event_handler
::
flush
()
{
/* reopen log files */
mysql_log
.
new_file
(
1
);
mysql_slow_log
.
new_file
(
1
);
mysql_log
.
reopen_file
();
mysql_slow_log
.
reopen_file
();
}
/*
...
...
@@ -1054,7 +1053,7 @@ void Log_to_csv_event_handler::
/*
this function is mostly a placeholder.
conceptually, binlog initialization (now mostly done in MYSQL_LOG::open)
conceptually, binlog initialization (now mostly done in MYSQL_
BIN_
LOG::open)
should be moved here.
*/
...
...
@@ -1128,7 +1127,7 @@ static int binlog_prepare(THD *thd, bool all)
do nothing.
just pretend we can do 2pc, so that MySQL won't
switch to 1pc.
real work will be done in MYSQL_LOG::log()
real work will be done in MYSQL_
BIN_
LOG::log()
*/
return
0
;
}
...
...
@@ -1144,7 +1143,7 @@ static int binlog_commit(THD *thd, bool all)
if
(
trx_data
->
empty
())
{
// we're here because trans_log was flushed in MYSQL_LOG::log()
// we're here because trans_log was flushed in MYSQL_
BIN_
LOG::log()
DBUG_RETURN
(
0
);
}
Query_log_event
qev
(
thd
,
STRING_WITH_LEN
(
"COMMIT"
),
TRUE
,
FALSE
);
...
...
@@ -1382,12 +1381,125 @@ static int find_uniq_filename(char *name)
}
void
MYSQL_LOG
::
init
(
enum_log_type
log_type_arg
,
enum
cache_type
io_cache_type_arg
)
{
DBUG_ENTER
(
"MYSQL_LOG::init"
);
log_type
=
log_type_arg
;
io_cache_type
=
io_cache_type_arg
;
DBUG_PRINT
(
"info"
,(
"log_type: %d"
,
log_type
));
DBUG_VOID_RETURN
;
}
/*
Open a (new) log file.
SYNOPSIS
open()
log_name The name of the log to open
log_type_arg The type of the log. E.g. LOG_NORMAL
new_name The new name for the logfile. This is only needed
when the method is used to open the binlog file.
io_cache_type_arg The type of the IO_CACHE to use for this log file
DESCRIPTION
Open the logfile, init IO_CACHE and write startup messages
(in case of general and slow query logs).
RETURN VALUES
0 ok
1 error
*/
bool
MYSQL_LOG
::
open
(
const
char
*
log_name
,
enum_log_type
log_type_arg
,
const
char
*
new_name
,
enum
cache_type
io_cache_type_arg
)
{
char
buff
[
FN_REFLEN
];
File
file
=
-
1
;
int
open_flags
=
O_CREAT
|
O_BINARY
;
DBUG_ENTER
(
"MYSQL_LOG::open"
);
DBUG_PRINT
(
"enter"
,
(
"log_type: %d"
,
(
int
)
log_type_arg
));
write_error
=
0
;
init
(
log_type_arg
,
io_cache_type_arg
);
if
(
!
(
name
=
my_strdup
(
log_name
,
MYF
(
MY_WME
))))
{
name
=
(
char
*
)
log_name
;
// for the error message
goto
err
;
}
if
(
new_name
)
strmov
(
log_file_name
,
new_name
);
else
if
(
generate_new_name
(
log_file_name
,
name
))
goto
err
;
if
(
io_cache_type
==
SEQ_READ_APPEND
)
open_flags
|=
O_RDWR
|
O_APPEND
;
else
open_flags
|=
O_WRONLY
|
(
log_type
==
LOG_BIN
?
0
:
O_APPEND
);
db
[
0
]
=
0
;
if
((
file
=
my_open
(
log_file_name
,
open_flags
,
MYF
(
MY_WME
|
ME_WAITTANG
)))
<
0
||
init_io_cache
(
&
log_file
,
file
,
IO_SIZE
,
io_cache_type
,
my_tell
(
file
,
MYF
(
MY_WME
)),
0
,
MYF
(
MY_WME
|
MY_NABP
|
((
log_type
==
LOG_BIN
)
?
MY_WAIT_IF_FULL
:
0
))))
goto
err
;
switch
(
log_type
)
{
case
LOG_NORMAL
:
{
char
*
end
;
int
len
=
my_snprintf
(
buff
,
sizeof
(
buff
),
"%s, Version: %s. "
#ifdef EMBEDDED_LIBRARY
"embedded library
\n
"
,
my_progname
,
server_version
#elif __NT__
"started with:
\n
TCP Port: %d, Named Pipe: %s
\n
"
,
my_progname
,
server_version
,
mysqld_port
,
mysqld_unix_port
#else
"started with:
\n
Tcp port: %d Unix socket: %s
\n
"
,
my_progname
,
server_version
,
mysqld_port
,
mysqld_unix_port
#endif
);
end
=
strnmov
(
buff
+
len
,
"Time Id Command Argument
\n
"
,
sizeof
(
buff
)
-
len
);
if
(
my_b_write
(
&
log_file
,
(
byte
*
)
buff
,
(
uint
)
(
end
-
buff
))
||
flush_io_cache
(
&
log_file
))
goto
err
;
break
;
}
case
LOG_CLOSED
:
// Impossible
case
LOG_TO_BE_OPENED
:
DBUG_ASSERT
(
1
);
break
;
}
DBUG_RETURN
(
0
);
err:
sql_print_error
(
"Could not use %s for logging (error %d). \
Turning logging off for the whole duration of the MySQL server process. \
To turn it on again: fix the cause, \
shutdown the MySQL server and restart it."
,
name
,
errno
);
if
(
file
>=
0
)
my_close
(
file
,
MYF
(
0
));
end_io_cache
(
&
log_file
);
safeFree
(
name
);
log_type
=
LOG_CLOSED
;
DBUG_RETURN
(
1
);
}
MYSQL_LOG
::
MYSQL_LOG
()
:
bytes_written
(
0
),
last_time
(
0
),
query_start
(
0
),
name
(
0
),
prepared_xids
(
0
),
log_type
(
LOG_CLOSED
),
file_id
(
1
),
open_count
(
1
),
write_error
(
FALSE
),
inited
(
FALSE
),
need_start_event
(
TRUE
),
m_table_map_version
(
0
),
description_event_for_exec
(
0
),
description_event_for_queue
(
0
)
:
name
(
0
),
log_type
(
LOG_CLOSED
),
write_error
(
FALSE
),
inited
(
FALSE
),
last_time
(
0
)
{
/*
We don't want to initialize LOCK_Log here as such initialization depends on
...
...
@@ -1395,9 +1507,54 @@ MYSQL_LOG::MYSQL_LOG()
called only in main(). Doing initialization here would make it happen
before main().
*/
index_file_name
[
0
]
=
0
;
bzero
((
char
*
)
&
log_file
,
sizeof
(
log_file
));
bzero
((
char
*
)
&
index_file
,
sizeof
(
index_file
));
bzero
((
char
*
)
&
log_file
,
sizeof
(
log_file
));
}
void
MYSQL_LOG
::
init_pthread_objects
()
{
DBUG_ASSERT
(
inited
==
0
);
inited
=
1
;
(
void
)
pthread_mutex_init
(
&
LOCK_log
,
MY_MUTEX_INIT_SLOW
);
}
/*
Close the log file
SYNOPSIS
close()
exiting Bitmask. For the slow and general logs the only used bit is
LOG_CLOSE_TO_BE_OPENED. This is used if we intend to call
open at once after close.
NOTES
One can do an open on the object at once after doing a close.
The internal structures are not freed until cleanup() is called
*/
void
MYSQL_LOG
::
close
(
uint
exiting
)
{
// One can't set log_type here!
DBUG_ENTER
(
"MYSQL_LOG::close"
);
DBUG_PRINT
(
"enter"
,(
"exiting: %d"
,
(
int
)
exiting
));
if
(
log_type
!=
LOG_CLOSED
&&
log_type
!=
LOG_TO_BE_OPENED
)
{
end_io_cache
(
&
log_file
);
if
(
my_sync
(
log_file
.
file
,
MYF
(
MY_WME
))
&&
!
write_error
)
{
write_error
=
1
;
sql_print_error
(
ER
(
ER_ERROR_ON_WRITE
),
name
,
errno
);
}
if
(
my_close
(
log_file
.
file
,
MYF
(
MY_WME
))
&&
!
write_error
)
{
write_error
=
1
;
sql_print_error
(
ER
(
ER_ERROR_ON_WRITE
),
name
,
errno
);
}
}
log_type
=
(
exiting
&
LOG_CLOSE_TO_BE_OPENED
)
?
LOG_TO_BE_OPENED
:
LOG_CLOSED
;
safeFree
(
name
);
DBUG_VOID_RETURN
;
}
/* this is called only once */
...
...
@@ -1408,17 +1565,57 @@ void MYSQL_LOG::cleanup()
if
(
inited
)
{
inited
=
0
;
close
(
LOG_CLOSE_INDEX
|
LOG_CLOSE_STOP_EVENT
);
delete
description_event_for_queue
;
delete
description_event_for_exec
;
(
void
)
pthread_mutex_destroy
(
&
LOCK_log
);
(
void
)
pthread_mutex_destroy
(
&
LOCK_index
);
(
void
)
pthread_cond_destroy
(
&
update_cond
);
close
(
0
);
}
DBUG_VOID_RETURN
;
}
/*
Reopen the log file
SYNOPSIS
reopen_file()
DESCRIPTION
Reopen the log file. The method is used during FLUSH LOGS
and locks LOCK_log mutex
*/
void
MYSQL_LOG
::
reopen_file
()
{
enum_log_type
save_log_type
;
char
*
save_name
;
DBUG_ENTER
(
"MYSQL_LOG::reopen_file"
);
if
(
!
is_open
())
{
DBUG_PRINT
(
"info"
,(
"log is closed"
));
DBUG_VOID_RETURN
;
}
pthread_mutex_lock
(
&
LOCK_log
);
save_name
=
name
;
save_log_type
=
log_type
;
name
=
0
;
// Don't free name
close
(
LOG_CLOSE_TO_BE_OPENED
);
/*
Note that at this point, log_type != LOG_CLOSED (important for is_open()).
*/
open
(
save_name
,
save_log_type
,
0
,
io_cache_type
);
my_free
(
save_name
,
MYF
(
0
));
pthread_mutex_unlock
(
&
LOCK_log
);
DBUG_VOID_RETURN
;
}
int
MYSQL_LOG
::
generate_new_name
(
char
*
new_name
,
const
char
*
log_name
)
{
fn_format
(
new_name
,
log_name
,
mysql_data_home
,
""
,
4
);
...
...
@@ -1437,30 +1634,242 @@ int MYSQL_LOG::generate_new_name(char *new_name, const char *log_name)
}
void
MYSQL_LOG
::
init
(
enum_log_type
log_type_arg
,
enum
cache_type
io_cache_type_arg
,
bool
no_auto_events_arg
,
ulong
max_size_arg
)
/*
Write a command to traditional general log file
SYNOPSIS
write()
event_time command start timestamp
user_host the pointer to the string with user@host info
user_host_len length of the user_host string. this is computed once
and passed to all general log event handlers
thread_id Id of the thread, issued a query
command_type the type of the command being logged
command_type_len the length of the string above
sql_text the very text of the query being executed
sql_text_len the length of sql_text string
DESCRIPTION
Log given command to to normal (not rotable) log file
RETURN
FASE - OK
TRUE - error occured
*/
bool
MYSQL_GENERAL_LOG
::
write
(
time_t
event_time
,
const
char
*
user_host
,
uint
user_host_len
,
int
thread_id
,
const
char
*
command_type
,
uint
command_type_len
,
const
char
*
sql_text
,
uint
sql_text_len
)
{
DBUG_ENTER
(
"MYSQL_LOG::init"
);
log_type
=
log_type_arg
;
io_cache_type
=
io_cache_type_arg
;
no_auto_events
=
no_auto_events_arg
;
max_size
=
max_size_arg
;
DBUG_PRINT
(
"info"
,(
"log_type: %d max_size: %lu"
,
log_type
,
max_size
));
DBUG_VOID_RETURN
;
char
buff
[
32
];
uint
length
=
0
;
char
time_buff
[
MAX_TIME_SIZE
];
struct
tm
start
;
uint
time_buff_len
=
0
;
/* Test if someone closed between the is_open test and lock */
if
(
is_open
())
{
/* Note that my_b_write() assumes it knows the length for this */
if
(
event_time
!=
last_time
)
{
last_time
=
event_time
;
localtime_r
(
&
event_time
,
&
start
);
time_buff_len
=
my_snprintf
(
time_buff
,
MAX_TIME_SIZE
,
"%02d%02d%02d %2d:%02d:%02d"
,
start
.
tm_year
%
100
,
start
.
tm_mon
+
1
,
start
.
tm_mday
,
start
.
tm_hour
,
start
.
tm_min
,
start
.
tm_sec
);
if
(
my_b_write
(
&
log_file
,
(
byte
*
)
&
time_buff
,
time_buff_len
))
goto
err
;
}
else
if
(
my_b_write
(
&
log_file
,
(
byte
*
)
"
\t\t
"
,
2
)
<
0
)
goto
err
;
/* command_type, thread_id */
length
=
my_snprintf
(
buff
,
32
,
"%5ld "
,
thread_id
);
if
(
my_b_write
(
&
log_file
,
(
byte
*
)
buff
,
length
))
goto
err
;
if
(
my_b_write
(
&
log_file
,
(
byte
*
)
command_type
,
command_type_len
))
goto
err
;
if
(
my_b_write
(
&
log_file
,
(
byte
*
)
"
\t
"
,
1
))
goto
err
;
/* sql_text */
if
(
my_b_write
(
&
log_file
,
(
byte
*
)
sql_text
,
sql_text_len
))
goto
err
;
if
(
my_b_write
(
&
log_file
,
(
byte
*
)
"
\n
"
,
1
)
||
flush_io_cache
(
&
log_file
))
goto
err
;
}
return
FALSE
;
err:
if
(
!
write_error
)
{
write_error
=
1
;
sql_print_error
(
ER
(
ER_ERROR_ON_WRITE
),
name
,
errno
);
}
return
TRUE
;
}
void
MYSQL_LOG
::
init_pthread_objects
()
/*
Log a query to the traditional slow log file
SYNOPSIS
write()
thd THD of the query
current_time current timestamp
query_start_arg command start timestamp
user_host the pointer to the string with user@host info
user_host_len length of the user_host string. this is computed once
and passed to all general log event handlers
query_time Amount of time the query took to execute (in seconds)
lock_time Amount of time the query was locked (in seconds)
is_command The flag, which determines, whether the sql_text is a
query or an administrator command.
sql_text the very text of the query or administrator command
processed
sql_text_len the length of sql_text string
DESCRIPTION
Log a query to the slow log file.
RETURN
FALSE - OK
TRUE - error occured
*/
bool
MYSQL_SLOW_LOG
::
write
(
THD
*
thd
,
time_t
current_time
,
time_t
query_start_arg
,
const
char
*
user_host
,
uint
user_host_len
,
longlong
query_time
,
longlong
lock_time
,
bool
is_command
,
const
char
*
sql_text
,
uint
sql_text_len
)
{
DBUG_ASSERT
(
inited
==
0
);
inited
=
1
;
(
void
)
pthread_mutex_init
(
&
LOCK_log
,
MY_MUTEX_INIT_SLOW
);
(
void
)
pthread_mutex_init
(
&
LOCK_index
,
MY_MUTEX_INIT_SLOW
);
(
void
)
pthread_cond_init
(
&
update_cond
,
0
);
bool
error
=
0
;
DBUG_ENTER
(
"MYSQL_SLOW_LOG::write"
);
if
(
!
is_open
())
DBUG_RETURN
(
0
);
if
(
is_open
())
{
// Safety agains reopen
int
tmp_errno
=
0
;
char
buff
[
80
],
*
end
;
uint
buff_len
;
end
=
buff
;
if
(
!
(
specialflag
&
SPECIAL_SHORT_LOG_FORMAT
))
{
Security_context
*
sctx
=
thd
->
security_ctx
;
if
(
current_time
!=
last_time
)
{
last_time
=
current_time
;
struct
tm
start
;
localtime_r
(
&
current_time
,
&
start
);
buff_len
=
my_snprintf
(
buff
,
sizeof
buff
,
"# Time: %02d%02d%02d %2d:%02d:%02d
\n
"
,
start
.
tm_year
%
100
,
start
.
tm_mon
+
1
,
start
.
tm_mday
,
start
.
tm_hour
,
start
.
tm_min
,
start
.
tm_sec
);
/* Note that my_b_write() assumes it knows the length for this */
if
(
my_b_write
(
&
log_file
,
(
byte
*
)
buff
,
buff_len
))
tmp_errno
=
errno
;
}
if
(
my_b_printf
(
&
log_file
,
"# User@Host: "
,
sizeof
(
"# User@Host: "
)
-
1
)
!=
sizeof
(
"# User@Host: "
)
-
1
)
tmp_errno
=
errno
;
if
(
my_b_printf
(
&
log_file
,
user_host
,
user_host_len
)
!=
user_host_len
)
tmp_errno
=
errno
;
if
(
my_b_write
(
&
log_file
,
(
byte
*
)
"
\n
"
,
1
))
tmp_errno
=
errno
;
}
/* For slow query log */
if
(
my_b_printf
(
&
log_file
,
"# Query_time: %lu Lock_time: %lu"
" Rows_sent: %lu Rows_examined: %lu
\n
"
,
(
ulong
)
query_time
,
(
ulong
)
lock_time
,
(
ulong
)
thd
->
sent_row_count
,
(
ulong
)
thd
->
examined_row_count
)
==
(
uint
)
-
1
)
tmp_errno
=
errno
;
if
(
thd
->
db
&&
strcmp
(
thd
->
db
,
db
))
{
// Database changed
if
(
my_b_printf
(
&
log_file
,
"use %s;
\n
"
,
thd
->
db
)
==
(
uint
)
-
1
)
tmp_errno
=
errno
;
strmov
(
db
,
thd
->
db
);
}
if
(
thd
->
last_insert_id_used
)
{
end
=
strmov
(
end
,
",last_insert_id="
);
end
=
longlong10_to_str
((
longlong
)
thd
->
current_insert_id
,
end
,
-
10
);
}
// Save value if we do an insert.
if
(
thd
->
insert_id_used
)
{
if
(
!
(
specialflag
&
SPECIAL_SHORT_LOG_FORMAT
))
{
end
=
strmov
(
end
,
",insert_id="
);
end
=
longlong10_to_str
((
longlong
)
thd
->
last_insert_id
,
end
,
-
10
);
}
}
/*
This info used to show up randomly, depending on whether the query
checked the query start time or not. now we always write current
timestamp to the slow log
*/
end
=
strmov
(
end
,
",timestamp="
);
end
=
int10_to_str
((
long
)
current_time
,
end
,
10
);
if
(
end
!=
buff
)
{
*
end
++=
';'
;
*
end
=
'\n'
;
if
(
my_b_write
(
&
log_file
,
(
byte
*
)
"SET "
,
4
)
||
my_b_write
(
&
log_file
,
(
byte
*
)
buff
+
1
,
(
uint
)
(
end
-
buff
)))
tmp_errno
=
errno
;
}
if
(
is_command
)
{
end
=
strxmov
(
buff
,
"# administrator command: "
,
NullS
);
buff_len
=
(
ulong
)
(
end
-
buff
);
my_b_write
(
&
log_file
,
(
byte
*
)
buff
,
buff_len
);
}
if
(
my_b_write
(
&
log_file
,
(
byte
*
)
sql_text
,
sql_text_len
)
||
my_b_write
(
&
log_file
,
(
byte
*
)
";
\n
"
,
2
)
||
flush_io_cache
(
&
log_file
))
tmp_errno
=
errno
;
if
(
tmp_errno
)
{
error
=
1
;
if
(
!
write_error
)
{
write_error
=
1
;
sql_print_error
(
ER
(
ER_ERROR_ON_WRITE
),
name
,
error
);
}
}
}
DBUG_RETURN
(
error
);
}
const
char
*
MYSQL_LOG
::
generate_name
(
const
char
*
log_name
,
const
char
*
suffix
,
bool
strip_ext
,
char
*
buff
)
...
...
@@ -1471,22 +1880,78 @@ const char *MYSQL_LOG::generate_name(const char *log_name,
TODO: The following should be using fn_format(); We just need to
first change fn_format() to cut the file name if it's too long.
*/
strmake
(
buff
,
glob_hostname
,
FN_REFLEN
-
5
);
strmov
(
fn_ext
(
buff
),
suffix
);
strmake
(
buff
,
glob_hostname
,
FN_REFLEN
-
5
);
strmov
(
fn_ext
(
buff
),
suffix
);
return
(
const
char
*
)
buff
;
}
// get rid of extension if the log is binary to avoid problems
if
(
strip_ext
)
{
char
*
p
=
fn_ext
(
log_name
);
uint
length
=
(
uint
)
(
p
-
log_name
);
strmake
(
buff
,
log_name
,
min
(
length
,
FN_REFLEN
));
char
*
p
=
fn_ext
(
log_name
);
uint
length
=
(
uint
)
(
p
-
log_name
);
strmake
(
buff
,
log_name
,
min
(
length
,
FN_REFLEN
));
return
(
const
char
*
)
buff
;
}
return
log_name
;
}
bool
MYSQL_LOG
::
open_index_file
(
const
char
*
index_file_name_arg
,
MYSQL_BIN_LOG
::
MYSQL_BIN_LOG
()
:
bytes_written
(
0
),
prepared_xids
(
0
),
file_id
(
1
),
open_count
(
1
),
need_start_event
(
TRUE
),
m_table_map_version
(
0
),
description_event_for_exec
(
0
),
description_event_for_queue
(
0
)
{
/*
We don't want to initialize locks here as such initialization depends on
safe_mutex (when using safe_mutex) which depends on MY_INIT(), which is
called only in main(). Doing initialization here would make it happen
before main().
*/
index_file_name
[
0
]
=
0
;
bzero
((
char
*
)
&
index_file
,
sizeof
(
index_file
));
}
/* this is called only once */
void
MYSQL_BIN_LOG
::
cleanup
()
{
DBUG_ENTER
(
"cleanup"
);
if
(
inited
)
{
inited
=
0
;
close
(
LOG_CLOSE_INDEX
|
LOG_CLOSE_STOP_EVENT
);
delete
description_event_for_queue
;
delete
description_event_for_exec
;
(
void
)
pthread_mutex_destroy
(
&
LOCK_log
);
(
void
)
pthread_mutex_destroy
(
&
LOCK_index
);
(
void
)
pthread_cond_destroy
(
&
update_cond
);
}
DBUG_VOID_RETURN
;
}
/* Init binlog-specific vars */
void
MYSQL_BIN_LOG
::
init
(
bool
no_auto_events_arg
,
ulong
max_size_arg
)
{
DBUG_ENTER
(
"MYSQL_BIN_LOG::init"
);
no_auto_events
=
no_auto_events_arg
;
max_size
=
max_size_arg
;
DBUG_PRINT
(
"info"
,(
"max_size: %lu"
,
max_size
));
DBUG_VOID_RETURN
;
}
void
MYSQL_BIN_LOG
::
init_pthread_objects
()
{
DBUG_ASSERT
(
inited
==
0
);
inited
=
1
;
(
void
)
pthread_mutex_init
(
&
LOCK_log
,
MY_MUTEX_INIT_SLOW
);
(
void
)
pthread_mutex_init
(
&
LOCK_index
,
MY_MUTEX_INIT_SLOW
);
(
void
)
pthread_cond_init
(
&
update_cond
,
0
);
}
bool
MYSQL_BIN_LOG
::
open_index_file
(
const
char
*
index_file_name_arg
,
const
char
*
log_name
)
{
File
index_file_nr
=
-
1
;
...
...
@@ -1523,10 +1988,10 @@ bool MYSQL_LOG::open_index_file(const char *index_file_name_arg,
/*
Open a (new) log file.
Open a (new)
bin
log file.
DESCRIPTION
-
If binary logs, also open the index file and r
egister the new
-
Open the log file and the index file. R
egister the new
file name in it
- When calling this when the file is in use, you must have a locks
on LOCK_log and LOCK_index.
...
...
@@ -1536,7 +2001,7 @@ bool MYSQL_LOG::open_index_file(const char *index_file_name_arg,
1 error
*/
bool
MYSQL_LOG
::
open
(
const
char
*
log_name
,
bool
MYSQL_
BIN_
LOG
::
open
(
const
char
*
log_name
,
enum_log_type
log_type_arg
,
const
char
*
new_name
,
enum
cache_type
io_cache_type_arg
,
...
...
@@ -1545,85 +2010,24 @@ bool MYSQL_LOG::open(const char *log_name,
bool
null_created_arg
)
{
char
buff
[
FN_REFLEN
];
File
file
=
-
1
;
int
open_flags
=
O_CREAT
|
O_BINARY
;
DBUG_ENTER
(
"MYSQL_LOG::open"
);
DBUG_PRINT
(
"enter"
,(
"log_type: %d"
,(
int
)
log_type_arg
));
last_time
=
query_start
=
0
;
write_error
=
0
;
init
(
log_type_arg
,
io_cache_type_arg
,
no_auto_events_arg
,
max_size_arg
);
if
(
!
(
name
=
my_strdup
(
log_name
,
MYF
(
MY_WME
))))
{
name
=
(
char
*
)
log_name
;
// for the error message
goto
err
;
}
if
(
new_name
)
strmov
(
log_file_name
,
new_name
);
else
if
(
generate_new_name
(
log_file_name
,
name
))
goto
err
;
if
(
io_cache_type
==
SEQ_READ_APPEND
)
open_flags
|=
O_RDWR
|
O_APPEND
;
else
open_flags
|=
O_WRONLY
|
(
log_type
==
LOG_BIN
?
0
:
O_APPEND
);
db
[
0
]
=
0
;
open_count
++
;
if
((
file
=
my_open
(
log_file_name
,
open_flags
,
MYF
(
MY_WME
|
ME_WAITTANG
)))
<
0
||
init_io_cache
(
&
log_file
,
file
,
IO_SIZE
,
io_cache_type
,
my_tell
(
file
,
MYF
(
MY_WME
)),
0
,
MYF
(
MY_WME
|
MY_NABP
|
((
log_type
==
LOG_BIN
)
?
MY_WAIT_IF_FULL
:
0
))))
goto
err
;
switch
(
log_type
)
{
case
LOG_NORMAL
:
{
char
*
end
;
int
len
=
my_snprintf
(
buff
,
sizeof
(
buff
),
"%s, Version: %s. "
#ifdef EMBEDDED_LIBRARY
"embedded library
\n
"
,
my_progname
,
server_version
#elif __NT__
"started with:
\n
TCP Port: %d, Named Pipe: %s
\n
"
,
my_progname
,
server_version
,
mysqld_port
,
mysqld_unix_port
#else
"started with:
\n
Tcp port: %d Unix socket: %s
\n
"
,
my_progname
,
server_version
,
mysqld_port
,
mysqld_unix_port
#endif
);
end
=
strnmov
(
buff
+
len
,
"Time Id Command Argument
\n
"
,
sizeof
(
buff
)
-
len
);
if
(
my_b_write
(
&
log_file
,
(
byte
*
)
buff
,(
uint
)
(
end
-
buff
))
||
flush_io_cache
(
&
log_file
))
goto
err
;
break
;
}
case
LOG_NEW
:
{
uint
len
;
time_t
skr
=
time
(
NULL
);
struct
tm
tm_tmp
;
File
file
=
-
1
;
int
open_flags
=
O_CREAT
|
O_BINARY
;
DBUG_ENTER
(
"MYSQL_BIN_LOG::open"
);
DBUG_PRINT
(
"enter"
,(
"log_type: %d"
,(
int
)
log_type_arg
));
last_time
=
0
;
write_error
=
0
;
/* open the main log file */
if
(
MYSQL_LOG
::
open
(
log_name
,
log_type_arg
,
new_name
,
io_cache_type_arg
))
DBUG_RETURN
(
1
);
/* all warnings issued */
init
(
no_auto_events_arg
,
max_size_arg
);
open_count
++
;
DBUG_ASSERT
(
log_type
==
LOG_BIN
);
localtime_r
(
&
skr
,
&
tm_tmp
);
len
=
my_snprintf
(
buff
,
sizeof
(
buff
),
"# %s, Version: %s at %02d%02d%02d %2d:%02d:%02d
\n
"
,
my_progname
,
server_version
,
tm_tmp
.
tm_year
%
100
,
tm_tmp
.
tm_mon
+
1
,
tm_tmp
.
tm_mday
,
tm_tmp
.
tm_hour
,
tm_tmp
.
tm_min
,
tm_tmp
.
tm_sec
);
if
(
my_b_write
(
&
log_file
,
(
byte
*
)
buff
,
len
)
||
flush_io_cache
(
&
log_file
))
goto
err
;
break
;
}
case
LOG_BIN
:
{
bool
write_file_name_to_index_file
=
0
;
...
...
@@ -1714,12 +2118,6 @@ bool MYSQL_LOG::open(const char *log_name,
my_sync
(
index_file
.
file
,
MYF
(
MY_WME
)))
goto
err
;
}
break
;
}
case
LOG_CLOSED
:
// Impossible
case
LOG_TO_BE_OPENED
:
DBUG_ASSERT
(
1
);
break
;
}
DBUG_RETURN
(
0
);
...
...
@@ -1738,7 +2136,7 @@ shutdown the MySQL server and restart it.", name, errno);
}
int
MYSQL_LOG
::
get_current_log
(
LOG_INFO
*
linfo
)
int
MYSQL_
BIN_
LOG
::
get_current_log
(
LOG_INFO
*
linfo
)
{
pthread_mutex_lock
(
&
LOCK_log
);
strmake
(
linfo
->
log_file_name
,
log_file_name
,
sizeof
(
linfo
->
log_file_name
)
-
1
);
...
...
@@ -1825,7 +2223,7 @@ err:
LOG_INFO_IO Got IO error while reading file
*/
int
MYSQL_LOG
::
find_log_pos
(
LOG_INFO
*
linfo
,
const
char
*
log_name
,
int
MYSQL_
BIN_
LOG
::
find_log_pos
(
LOG_INFO
*
linfo
,
const
char
*
log_name
,
bool
need_lock
)
{
int
error
=
0
;
...
...
@@ -1899,7 +2297,7 @@ int MYSQL_LOG::find_log_pos(LOG_INFO *linfo, const char *log_name,
LOG_INFO_IO Got IO error while reading file
*/
int
MYSQL_LOG
::
find_next_log
(
LOG_INFO
*
linfo
,
bool
need_lock
)
int
MYSQL_
BIN_
LOG
::
find_next_log
(
LOG_INFO
*
linfo
,
bool
need_lock
)
{
int
error
=
0
;
uint
length
;
...
...
@@ -1947,7 +2345,7 @@ err:
1 error
*/
bool
MYSQL_LOG
::
reset_logs
(
THD
*
thd
)
bool
MYSQL_
BIN_
LOG
::
reset_logs
(
THD
*
thd
)
{
LOG_INFO
linfo
;
bool
error
=
0
;
...
...
@@ -2047,7 +2445,7 @@ err:
#ifdef HAVE_REPLICATION
int
MYSQL_LOG
::
purge_first_log
(
struct
st_relay_log_info
*
rli
,
bool
included
)
int
MYSQL_
BIN_
LOG
::
purge_first_log
(
struct
st_relay_log_info
*
rli
,
bool
included
)
{
int
error
;
DBUG_ENTER
(
"purge_first_log"
);
...
...
@@ -2123,7 +2521,7 @@ err:
Update log index_file
*/
int
MYSQL_LOG
::
update_log_index
(
LOG_INFO
*
log_info
,
bool
need_update_threads
)
int
MYSQL_
BIN_
LOG
::
update_log_index
(
LOG_INFO
*
log_info
,
bool
need_update_threads
)
{
if
(
copy_up_file_and_fill
(
&
index_file
,
log_info
->
index_file_start_offset
))
return
LOG_INFO_IO
;
...
...
@@ -2156,7 +2554,7 @@ int MYSQL_LOG::update_log_index(LOG_INFO* log_info, bool need_update_threads)
LOG_INFO_EOF to_log not found
*/
int
MYSQL_LOG
::
purge_logs
(
const
char
*
to_log
,
int
MYSQL_
BIN_
LOG
::
purge_logs
(
const
char
*
to_log
,
bool
included
,
bool
need_mutex
,
bool
need_update_threads
,
...
...
@@ -2242,7 +2640,7 @@ err:
LOG_INFO_PURGE_NO_ROTATE Binary file that can't be rotated
*/
int
MYSQL_LOG
::
purge_logs_before_date
(
time_t
purge_time
)
int
MYSQL_
BIN_
LOG
::
purge_logs_before_date
(
time_t
purge_time
)
{
int
error
;
LOG_INFO
log_info
;
...
...
@@ -2301,7 +2699,7 @@ err:
If file name will be longer then FN_REFLEN it will be truncated
*/
void
MYSQL_LOG
::
make_log_name
(
char
*
buf
,
const
char
*
log_ident
)
void
MYSQL_
BIN_
LOG
::
make_log_name
(
char
*
buf
,
const
char
*
log_ident
)
{
uint
dir_len
=
dirname_length
(
log_file_name
);
if
(
dir_len
>
FN_REFLEN
)
...
...
@@ -2315,29 +2713,49 @@ void MYSQL_LOG::make_log_name(char* buf, const char* log_ident)
Check if we are writing/reading to the given log file
*/
bool
MYSQL_LOG
::
is_active
(
const
char
*
log_file_name_arg
)
bool
MYSQL_
BIN_
LOG
::
is_active
(
const
char
*
log_file_name_arg
)
{
return
!
strcmp
(
log_file_name
,
log_file_name_arg
);
}
/*
Wrappers around new_file_impl to avoid using argument
to control locking. The argument 1) less readable 2) breaks
incapsulation 3) allows external access to the class without
a lock (which is not possible with private new_file_without_locking
method).
*/
void
MYSQL_BIN_LOG
::
new_file
()
{
new_file_impl
(
1
);
}
void
MYSQL_BIN_LOG
::
new_file_without_locking
()
{
new_file_impl
(
0
);
}
/*
Start writing to a new log file or reopen the old file
SYNOPSIS
new_file()
new_file
_impl
()
need_lock Set to 1 if caller has not locked LOCK_log
NOTE
The new file name is stored last in the index file
*/
void
MYSQL_
LOG
::
new_file
(
bool
need_lock
)
void
MYSQL_
BIN_LOG
::
new_file_impl
(
bool
need_lock
)
{
char
new_name
[
FN_REFLEN
],
*
new_name_ptr
,
*
old_name
;
enum_log_type
save_log_type
;
DBUG_ENTER
(
"MYSQL_
LOG::new_file
"
);
DBUG_ENTER
(
"MYSQL_
BIN_LOG::new_file_impl
"
);
if
(
!
is_open
())
{
DBUG_PRINT
(
"info"
,(
"log is closed"
));
...
...
@@ -2433,11 +2851,11 @@ end:
}
bool
MYSQL_LOG
::
append
(
Log_event
*
ev
)
bool
MYSQL_
BIN_
LOG
::
append
(
Log_event
*
ev
)
{
bool
error
=
0
;
pthread_mutex_lock
(
&
LOCK_log
);
DBUG_ENTER
(
"MYSQL_LOG::append"
);
DBUG_ENTER
(
"MYSQL_
BIN_
LOG::append"
);
DBUG_ASSERT
(
log_file
.
type
==
SEQ_READ_APPEND
);
/*
...
...
@@ -2452,7 +2870,7 @@ bool MYSQL_LOG::append(Log_event* ev)
bytes_written
+=
ev
->
data_written
;
DBUG_PRINT
(
"info"
,(
"max_size: %lu"
,
max_size
));
if
((
uint
)
my_b_append_tell
(
&
log_file
)
>
max_size
)
new_file
(
0
);
new_file
_without_locking
(
);
err:
pthread_mutex_unlock
(
&
LOCK_log
);
...
...
@@ -2461,10 +2879,10 @@ err:
}
bool
MYSQL_LOG
::
appendv
(
const
char
*
buf
,
uint
len
,...)
bool
MYSQL_
BIN_
LOG
::
appendv
(
const
char
*
buf
,
uint
len
,...)
{
bool
error
=
0
;
DBUG_ENTER
(
"MYSQL_LOG::appendv"
);
DBUG_ENTER
(
"MYSQL_
BIN_
LOG::appendv"
);
va_list
(
args
);
va_start
(
args
,
len
);
...
...
@@ -2482,7 +2900,7 @@ bool MYSQL_LOG::appendv(const char* buf, uint len,...)
}
while
((
buf
=
va_arg
(
args
,
const
char
*
))
&&
(
len
=
va_arg
(
args
,
uint
)));
DBUG_PRINT
(
"info"
,(
"max_size: %lu"
,
max_size
));
if
((
uint
)
my_b_append_tell
(
&
log_file
)
>
max_size
)
new_file
(
0
);
new_file
_without_locking
(
);
err:
if
(
!
error
)
...
...
@@ -2491,99 +2909,7 @@ err:
}
/*
Write a command to traditional general log file
SYNOPSIS
write()
event_time command start timestamp
user_host the pointer to the string with user@host info
user_host_len length of the user_host string. this is computed once
and passed to all general log event handlers
thread_id Id of the thread, issued a query
command_type the type of the command being logged
command_type_len the length of the string above
sql_text the very text of the query being executed
sql_text_len the length of sql_text string
DESCRIPTION
Log given command to to normal (not rotable) log file
RETURN
FASE - OK
TRUE - error occured
*/
bool
MYSQL_LOG
::
write
(
time_t
event_time
,
const
char
*
user_host
,
uint
user_host_len
,
int
thread_id
,
const
char
*
command_type
,
uint
command_type_len
,
const
char
*
sql_text
,
uint
sql_text_len
)
{
char
buff
[
32
];
uint
length
=
0
;
char
time_buff
[
MAX_TIME_SIZE
];
struct
tm
start
;
uint
time_buff_len
=
0
;
/* Test if someone closed between the is_open test and lock */
if
(
is_open
())
{
/* Note that my_b_write() assumes it knows the length for this */
if
(
event_time
!=
last_time
)
{
last_time
=
event_time
;
localtime_r
(
&
event_time
,
&
start
);
time_buff_len
=
my_snprintf
(
time_buff
,
MAX_TIME_SIZE
,
"%02d%02d%02d %2d:%02d:%02d"
,
start
.
tm_year
%
100
,
start
.
tm_mon
+
1
,
start
.
tm_mday
,
start
.
tm_hour
,
start
.
tm_min
,
start
.
tm_sec
);
if
(
my_b_write
(
&
log_file
,
(
byte
*
)
&
time_buff
,
time_buff_len
))
goto
err
;
}
else
if
(
my_b_write
(
&
log_file
,
(
byte
*
)
"
\t\t
"
,
2
)
<
0
)
goto
err
;
/* command_type, thread_id */
length
=
my_snprintf
(
buff
,
32
,
"%5ld "
,
thread_id
);
if
(
my_b_write
(
&
log_file
,
(
byte
*
)
buff
,
length
))
goto
err
;
if
(
my_b_write
(
&
log_file
,
(
byte
*
)
command_type
,
command_type_len
))
goto
err
;
if
(
my_b_write
(
&
log_file
,
(
byte
*
)
"
\t
"
,
1
))
goto
err
;
/* sql_text */
if
(
my_b_write
(
&
log_file
,
(
byte
*
)
sql_text
,
sql_text_len
))
goto
err
;
if
(
my_b_write
(
&
log_file
,
(
byte
*
)
"
\n
"
,
1
)
||
flush_io_cache
(
&
log_file
))
goto
err
;
}
return
FALSE
;
err:
if
(
!
write_error
)
{
write_error
=
1
;
sql_print_error
(
ER
(
ER_ERROR_ON_WRITE
),
name
,
errno
);
}
return
TRUE
;
}
bool
MYSQL_LOG
::
flush_and_sync
()
bool
MYSQL_BIN_LOG
::
flush_and_sync
()
{
int
err
=
0
,
fd
=
log_file
.
file
;
safe_mutex_assert_owner
(
&
LOCK_log
);
...
...
@@ -2597,7 +2923,7 @@ bool MYSQL_LOG::flush_and_sync()
return
err
;
}
void
MYSQL_LOG
::
start_union_events
(
THD
*
thd
)
void
MYSQL_
BIN_
LOG
::
start_union_events
(
THD
*
thd
)
{
DBUG_ASSERT
(
!
thd
->
binlog_evt_union
.
do_union
);
thd
->
binlog_evt_union
.
do_union
=
TRUE
;
...
...
@@ -2606,13 +2932,13 @@ void MYSQL_LOG::start_union_events(THD *thd)
thd
->
binlog_evt_union
.
first_query_id
=
thd
->
query_id
;
}
void
MYSQL_LOG
::
stop_union_events
(
THD
*
thd
)
void
MYSQL_
BIN_
LOG
::
stop_union_events
(
THD
*
thd
)
{
DBUG_ASSERT
(
thd
->
binlog_evt_union
.
do_union
);
thd
->
binlog_evt_union
.
do_union
=
FALSE
;
}
bool
MYSQL_LOG
::
is_query_in_union
(
THD
*
thd
,
query_id_t
query_id_param
)
bool
MYSQL_
BIN_
LOG
::
is_query_in_union
(
THD
*
thd
,
query_id_t
query_id_param
)
{
return
(
thd
->
binlog_evt_union
.
do_union
&&
query_id_param
>=
thd
->
binlog_evt_union
.
first_query_id
);
...
...
@@ -2716,9 +3042,10 @@ THD::binlog_set_pending_rows_event(Rows_log_event* ev)
(either cached binlog if transaction, or disk binlog). Sets a new pending
event.
*/
int
MYSQL_LOG
::
flush_and_set_pending_rows_event
(
THD
*
thd
,
Rows_log_event
*
event
)
int
MYSQL_BIN_LOG
::
flush_and_set_pending_rows_event
(
THD
*
thd
,
Rows_log_event
*
event
)
{
DBUG_ENTER
(
"MYSQL_LOG::flush_and_set_pending_rows_event(event)"
);
DBUG_ENTER
(
"MYSQL_
BIN_
LOG::flush_and_set_pending_rows_event(event)"
);
DBUG_ASSERT
(
thd
->
current_stmt_binlog_row_based
&&
mysql_bin_log
.
is_open
());
DBUG_PRINT
(
"enter"
,
(
"event=%p"
,
event
));
...
...
@@ -2801,11 +3128,11 @@ int MYSQL_LOG::flush_and_set_pending_rows_event(THD *thd, Rows_log_event* event)
Write an event to the binary log
*/
bool
MYSQL_LOG
::
write
(
Log_event
*
event_info
)
bool
MYSQL_
BIN_
LOG
::
write
(
Log_event
*
event_info
)
{
THD
*
thd
=
event_info
->
thd
;
bool
error
=
1
;
DBUG_ENTER
(
"MYSQL_LOG::write(Log_event *)"
);
DBUG_ENTER
(
"MYSQL_
BIN_
LOG::write(Log_event *)"
);
if
(
thd
->
binlog_evt_union
.
do_union
)
{
...
...
@@ -3014,14 +3341,14 @@ bool general_log_print(THD *thd, enum enum_server_command command,
return
error
;
}
void
MYSQL_LOG
::
rotate_and_purge
(
uint
flags
)
void
MYSQL_
BIN_
LOG
::
rotate_and_purge
(
uint
flags
)
{
if
(
!
(
flags
&
RP_LOCK_LOG_IS_ALREADY_LOCKED
))
pthread_mutex_lock
(
&
LOCK_log
);
if
((
flags
&
RP_FORCE_ROTATE
)
||
(
my_b_tell
(
&
log_file
)
>=
(
my_off_t
)
max_size
))
{
new_file
(
0
);
new_file
_without_locking
(
);
#ifdef HAVE_REPLICATION
if
(
expire_logs_days
)
{
...
...
@@ -3035,7 +3362,7 @@ void MYSQL_LOG::rotate_and_purge(uint flags)
pthread_mutex_unlock
(
&
LOCK_log
);
}
uint
MYSQL_LOG
::
next_file_id
()
uint
MYSQL_
BIN_
LOG
::
next_file_id
()
{
uint
res
;
pthread_mutex_lock
(
&
LOCK_log
);
...
...
@@ -3066,9 +3393,9 @@ uint MYSQL_LOG::next_file_id()
that the same updates are run on the slave.
*/
bool
MYSQL_LOG
::
write
(
THD
*
thd
,
IO_CACHE
*
cache
,
Log_event
*
commit_event
)
bool
MYSQL_
BIN_
LOG
::
write
(
THD
*
thd
,
IO_CACHE
*
cache
,
Log_event
*
commit_event
)
{
DBUG_ENTER
(
"MYSQL_LOG::write(THD *, IO_CACHE *, Log_event *)"
);
DBUG_ENTER
(
"MYSQL_
BIN_
LOG::write(THD *, IO_CACHE *, Log_event *)"
);
VOID
(
pthread_mutex_lock
(
&
LOCK_log
));
if
(
likely
(
is_open
()))
// Should always be true
...
...
@@ -3163,148 +3490,6 @@ err:
}
/*
Log a query to the traditional slow log file
SYNOPSIS
write()
thd THD of the query
current_time current timestamp
query_start_arg command start timestamp
user_host the pointer to the string with user@host info
user_host_len length of the user_host string. this is computed once
and passed to all general log event handlers
query_time Amount of time the query took to execute (in seconds)
lock_time Amount of time the query was locked (in seconds)
is_command The flag, which determines, whether the sql_text is a
query or an administrator command.
sql_text the very text of the query or administrator command
processed
sql_text_len the length of sql_text string
DESCRIPTION
Log a query to the slow log file.
RETURN
FALSE - OK
TRUE - error occured
*/
bool
MYSQL_LOG
::
write
(
THD
*
thd
,
time_t
current_time
,
time_t
query_start_arg
,
const
char
*
user_host
,
uint
user_host_len
,
longlong
query_time
,
longlong
lock_time
,
bool
is_command
,
const
char
*
sql_text
,
uint
sql_text_len
)
{
bool
error
=
0
;
DBUG_ENTER
(
"MYSQL_LOG::write"
);
if
(
!
is_open
())
DBUG_RETURN
(
0
);
if
(
is_open
())
{
// Safety agains reopen
int
tmp_errno
=
0
;
char
buff
[
80
],
*
end
;
uint
buff_len
;
end
=
buff
;
if
(
!
(
specialflag
&
SPECIAL_SHORT_LOG_FORMAT
))
{
Security_context
*
sctx
=
thd
->
security_ctx
;
if
(
current_time
!=
last_time
)
{
last_time
=
current_time
;
struct
tm
start
;
localtime_r
(
&
current_time
,
&
start
);
buff_len
=
my_snprintf
(
buff
,
sizeof
buff
,
"# Time: %02d%02d%02d %2d:%02d:%02d
\n
"
,
start
.
tm_year
%
100
,
start
.
tm_mon
+
1
,
start
.
tm_mday
,
start
.
tm_hour
,
start
.
tm_min
,
start
.
tm_sec
);
/* Note that my_b_write() assumes it knows the length for this */
if
(
my_b_write
(
&
log_file
,
(
byte
*
)
buff
,
buff_len
))
tmp_errno
=
errno
;
}
if
(
my_b_printf
(
&
log_file
,
"# User@Host: "
,
sizeof
(
"# User@Host: "
)
-
1
))
tmp_errno
=
errno
;
if
(
my_b_printf
(
&
log_file
,
user_host
,
user_host_len
))
tmp_errno
=
errno
;
if
(
my_b_write
(
&
log_file
,
(
byte
*
)
"
\n
"
,
1
))
tmp_errno
=
errno
;
}
/* For slow query log */
if
(
my_b_printf
(
&
log_file
,
"# Query_time: %lu Lock_time: %lu"
" Rows_sent: %lu Rows_examined: %lu
\n
"
,
(
ulong
)
query_time
,
(
ulong
)
lock_time
,
(
ulong
)
thd
->
sent_row_count
,
(
ulong
)
thd
->
examined_row_count
)
==
(
uint
)
-
1
)
tmp_errno
=
errno
;
if
(
thd
->
db
&&
strcmp
(
thd
->
db
,
db
))
{
// Database changed
if
(
my_b_printf
(
&
log_file
,
"use %s;
\n
"
,
thd
->
db
)
==
(
uint
)
-
1
)
tmp_errno
=
errno
;
strmov
(
db
,
thd
->
db
);
}
if
(
thd
->
last_insert_id_used
)
{
end
=
strmov
(
end
,
",last_insert_id="
);
end
=
longlong10_to_str
((
longlong
)
thd
->
current_insert_id
,
end
,
-
10
);
}
// Save value if we do an insert.
if
(
thd
->
insert_id_used
)
{
if
(
!
(
specialflag
&
SPECIAL_SHORT_LOG_FORMAT
))
{
end
=
strmov
(
end
,
",insert_id="
);
end
=
longlong10_to_str
((
longlong
)
thd
->
last_insert_id
,
end
,
-
10
);
}
}
/*
This info used to show up randomly, depending on whether the query
checked the query start time or not. now we always write current
timestamp to the slow log
*/
end
=
strmov
(
end
,
",timestamp="
);
end
=
int10_to_str
((
long
)
current_time
,
end
,
10
);
if
(
end
!=
buff
)
{
*
end
++=
';'
;
*
end
=
'\n'
;
if
(
my_b_write
(
&
log_file
,
(
byte
*
)
"SET "
,
4
)
||
my_b_write
(
&
log_file
,
(
byte
*
)
buff
+
1
,(
uint
)
(
end
-
buff
)))
tmp_errno
=
errno
;
}
if
(
is_command
)
{
end
=
strxmov
(
buff
,
"# administrator command: "
,
NullS
);
buff_len
=
(
ulong
)
(
end
-
buff
);
my_b_write
(
&
log_file
,
(
byte
*
)
buff
,
buff_len
);
}
if
(
my_b_write
(
&
log_file
,
(
byte
*
)
sql_text
,
sql_text_len
)
||
my_b_write
(
&
log_file
,
(
byte
*
)
";
\n
"
,
2
)
||
flush_io_cache
(
&
log_file
))
tmp_errno
=
errno
;
if
(
tmp_errno
)
{
error
=
1
;
if
(
!
write_error
)
{
write_error
=
1
;
sql_print_error
(
ER
(
ER_ERROR_ON_WRITE
),
name
,
error
);
}
}
}
DBUG_RETURN
(
error
);
}
/*
Wait until we get a signal that the binary log has been updated
...
...
@@ -3321,7 +3506,7 @@ bool MYSQL_LOG::write(THD *thd, time_t current_time, time_t query_start_arg,
THD::enter_cond() (see NOTES in sql_class.h).
*/
void
MYSQL_LOG
::
wait_for_update
(
THD
*
thd
,
bool
is_slave
)
void
MYSQL_
BIN_
LOG
::
wait_for_update
(
THD
*
thd
,
bool
is_slave
)
{
const
char
*
old_msg
;
DBUG_ENTER
(
"wait_for_update"
);
...
...
@@ -3354,9 +3539,9 @@ void MYSQL_LOG::wait_for_update(THD* thd, bool is_slave)
The internal structures are not freed until cleanup() is called
*/
void
MYSQL_LOG
::
close
(
uint
exiting
)
void
MYSQL_
BIN_
LOG
::
close
(
uint
exiting
)
{
// One can't set log_type here!
DBUG_ENTER
(
"MYSQL_LOG::close"
);
DBUG_ENTER
(
"MYSQL_
BIN_
LOG::close"
);
DBUG_PRINT
(
"enter"
,(
"exiting: %d"
,
(
int
)
exiting
));
if
(
log_type
!=
LOG_CLOSED
&&
log_type
!=
LOG_TO_BE_OPENED
)
{
...
...
@@ -3370,7 +3555,6 @@ void MYSQL_LOG::close(uint exiting)
signal_update
();
}
#endif
/* HAVE_REPLICATION */
end_io_cache
(
&
log_file
);
/* don't pwrite in a file opened with O_APPEND - it doesn't work */
if
(
log_file
.
type
==
WRITE_CACHE
&&
log_type
==
LOG_BIN
)
...
...
@@ -3380,16 +3564,8 @@ void MYSQL_LOG::close(uint exiting)
my_pwrite
(
log_file
.
file
,
&
flags
,
1
,
offset
,
MYF
(
0
));
}
if
(
my_sync
(
log_file
.
file
,
MYF
(
MY_WME
))
&&
!
write_error
)
{
write_error
=
1
;
sql_print_error
(
ER
(
ER_ERROR_ON_WRITE
),
name
,
errno
);
}
if
(
my_close
(
log_file
.
file
,
MYF
(
MY_WME
))
&&
!
write_error
)
{
write_error
=
1
;
sql_print_error
(
ER
(
ER_ERROR_ON_WRITE
),
name
,
errno
);
}
/* this will cleanup IO_CACHE, sync and close the file */
MYSQL_LOG
::
close
(
exiting
);
}
/*
...
...
@@ -3412,7 +3588,7 @@ void MYSQL_LOG::close(uint exiting)
}
void
MYSQL_LOG
::
set_max_size
(
ulong
max_size_arg
)
void
MYSQL_
BIN_
LOG
::
set_max_size
(
ulong
max_size_arg
)
{
/*
We need to take locks, otherwise this may happen:
...
...
@@ -3421,7 +3597,7 @@ void MYSQL_LOG::set_max_size(ulong max_size_arg)
uses the old_max_size argument, so max_size_arg has been overwritten and
it's like if the SET command was never run.
*/
DBUG_ENTER
(
"MYSQL_LOG::set_max_size"
);
DBUG_ENTER
(
"MYSQL_
BIN_
LOG::set_max_size"
);
pthread_mutex_lock
(
&
LOCK_log
);
if
(
is_open
())
max_size
=
max_size_arg
;
...
...
@@ -3570,9 +3746,9 @@ bool flush_error_log()
return
result
;
}
void
MYSQL_LOG
::
signal_update
()
void
MYSQL_
BIN_
LOG
::
signal_update
()
{
DBUG_ENTER
(
"MYSQL_LOG::signal_update"
);
DBUG_ENTER
(
"MYSQL_
BIN_
LOG::signal_update"
);
pthread_cond_broadcast
(
&
update_cond
);
DBUG_VOID_RETURN
;
}
...
...
@@ -4175,7 +4351,7 @@ int TC_LOG::using_heuristic_recover()
}
/****** transaction coordinator log for 2pc - binlog() based solution ******/
#define TC_LOG_BINLOG MYSQL_LOG
#define TC_LOG_BINLOG MYSQL_
BIN_
LOG
/*
TODO keep in-memory list of prepared transactions
...
...
sql/log.h
View file @
fec70c97
...
...
@@ -147,33 +147,89 @@ typedef struct st_log_info
class
Log_event
;
class
Rows_log_event
;
enum
enum_log_type
{
LOG_CLOSED
,
LOG_TO_BE_OPENED
,
LOG_NORMAL
,
LOG_
NEW
,
LOG_
BIN
};
enum
enum_log_type
{
LOG_CLOSED
,
LOG_TO_BE_OPENED
,
LOG_NORMAL
,
LOG_BIN
};
/*
TODO split MYSQL_LOG into base MYSQL_LOG and
MYSQL_QUERY_LOG, MYSQL_SLOW_LOG, MYSQL_BIN_LOG
most of the code from MYSQL_LOG should be in the MYSQL_BIN_LOG
only (TC_LOG included)
TODO use mmap instead of IO_CACHE for binlog
(mmap+fsync is two times faster than write+fsync)
*/
class
MYSQL_LOG
:
public
TC_LOG
class
MYSQL_LOG
{
public:
MYSQL_LOG
();
void
init_pthread_objects
();
void
cleanup
();
void
reopen_file
();
bool
open
(
const
char
*
log_name
,
enum_log_type
log_type
,
const
char
*
new_name
,
enum
cache_type
io_cache_type_arg
);
void
init
(
enum_log_type
log_type_arg
,
enum
cache_type
io_cache_type_arg
);
void
close
(
uint
exiting
);
inline
bool
is_open
()
{
return
log_type
!=
LOG_CLOSED
;
}
const
char
*
generate_name
(
const
char
*
log_name
,
const
char
*
suffix
,
bool
strip_ext
,
char
*
buff
);
int
generate_new_name
(
char
*
new_name
,
const
char
*
log_name
);
protected:
/* LOCK_log is inited by init_pthread_objects() */
pthread_mutex_t
LOCK_log
;
char
*
name
;
char
log_file_name
[
FN_REFLEN
];
char
time_buff
[
20
],
db
[
NAME_LEN
+
1
];
bool
write_error
,
inited
;
IO_CACHE
log_file
;
volatile
enum_log_type
log_type
;
enum
cache_type
io_cache_type
;
time_t
last_time
;
friend
class
Log_event
;
};
class
MYSQL_GENERAL_LOG
:
public
MYSQL_LOG
{
public:
MYSQL_GENERAL_LOG
()
{}
/* get rid of gcc warning */
bool
write
(
time_t
event_time
,
const
char
*
user_host
,
uint
user_host_len
,
int
thread_id
,
const
char
*
command_type
,
uint
command_type_len
,
const
char
*
sql_text
,
uint
sql_text_len
);
bool
open_query_log
(
const
char
*
log_name
)
{
char
buf
[
FN_REFLEN
];
return
open
(
generate_name
(
log_name
,
".log"
,
0
,
buf
),
LOG_NORMAL
,
0
,
WRITE_CACHE
);
}
};
class
MYSQL_SLOW_LOG
:
public
MYSQL_LOG
{
public:
MYSQL_SLOW_LOG
()
{}
/* get rid of gcc warning */
bool
write
(
THD
*
thd
,
time_t
current_time
,
time_t
query_start_arg
,
const
char
*
user_host
,
uint
user_host_len
,
longlong
query_time
,
longlong
lock_time
,
bool
is_command
,
const
char
*
sql_text
,
uint
sql_text_len
);
bool
open_slow_log
(
const
char
*
log_name
)
{
char
buf
[
FN_REFLEN
];
return
open
(
generate_name
(
log_name
,
"-slow.log"
,
0
,
buf
),
LOG_NORMAL
,
0
,
WRITE_CACHE
);
}
};
class
MYSQL_BIN_LOG
:
public
TC_LOG
,
private
MYSQL_LOG
{
private:
/* LOCK_log and LOCK_index are inited by init_pthread_objects() */
pthread_mutex_t
LOCK_
log
,
LOCK_
index
;
pthread_mutex_t
LOCK_index
;
pthread_mutex_t
LOCK_prep_xids
;
pthread_cond_t
COND_prep_xids
;
pthread_cond_t
update_cond
;
ulonglong
bytes_written
;
time_t
last_time
,
query_start
;
IO_CACHE
log_file
;
IO_CACHE
index_file
;
char
*
name
;
char
time_buff
[
20
],
db
[
NAME_LEN
+
1
];
char
log_file_name
[
FN_REFLEN
],
index_file_name
[
FN_REFLEN
];
char
index_file_name
[
FN_REFLEN
];
/*
The max size before rotation (usable only if log_type == LOG_BIN: binary
logs and relay logs).
...
...
@@ -186,13 +242,10 @@ class MYSQL_LOG: public TC_LOG
*/
ulong
max_size
;
ulong
prepared_xids
;
/* for tc log - number of xids to remember */
volatile
enum_log_type
log_type
;
enum
cache_type
io_cache_type
;
// current file sequence number for load data infile binary logging
uint
file_id
;
uint
open_count
;
// For replication
int
readers_count
;
bool
write_error
,
inited
;
bool
need_start_event
;
/*
no_auto_events means we don't want any of these automatic events :
...
...
@@ -202,13 +255,20 @@ class MYSQL_LOG: public TC_LOG
In 5.0 it's 0 for relay logs too!
*/
bool
no_auto_events
;
friend
class
Log_event
;
ulonglong
m_table_map_version
;
int
write_to_file
(
IO_CACHE
*
cache
);
/*
This is used to start writing to a new log file. The difference from
new_file() is locking. new_file_without_locking() does not acquire
LOCK_log.
*/
void
new_file_without_locking
();
void
new_file_impl
(
bool
need_lock
);
public:
MYSQL_LOG
::
generate_name
;
/*
These describe the log's format. This is used only for relay logs.
_for_exec is used by the SQL thread, _for_queue by the I/O thread. It's
...
...
@@ -220,9 +280,9 @@ public:
Format_description_log_event
*
description_event_for_exec
,
*
description_event_for_queue
;
MYSQL_LOG
();
MYSQL_
BIN_
LOG
();
/*
note that there's no destructor ~MYSQL_LOG() !
note that there's no destructor ~MYSQL_
BIN_
LOG() !
The reason is that we don't want it to be automatically called
on exit() - but only during the correct shutdown process
*/
...
...
@@ -264,9 +324,7 @@ public:
void
signal_update
();
void
wait_for_update
(
THD
*
thd
,
bool
master_or_slave
);
void
set_need_start_event
()
{
need_start_event
=
1
;
}
void
init
(
enum_log_type
log_type_arg
,
enum
cache_type
io_cache_type_arg
,
bool
no_auto_events_arg
,
ulong
max_size
);
void
init
(
bool
no_auto_events_arg
,
ulong
max_size
);
void
init_pthread_objects
();
void
cleanup
();
bool
open
(
const
char
*
log_name
,
...
...
@@ -275,35 +333,10 @@ public:
enum
cache_type
io_cache_type_arg
,
bool
no_auto_events_arg
,
ulong
max_size
,
bool
null_created
);
const
char
*
generate_name
(
const
char
*
log_name
,
const
char
*
suffix
,
bool
strip_ext
,
char
*
buff
);
/* simplified open_xxx wrappers for the gigantic open above */
bool
open_query_log
(
const
char
*
log_name
)
{
char
buf
[
FN_REFLEN
];
return
open
(
generate_name
(
log_name
,
".log"
,
0
,
buf
),
LOG_NORMAL
,
0
,
WRITE_CACHE
,
0
,
0
,
0
);
}
bool
open_slow_log
(
const
char
*
log_name
)
{
char
buf
[
FN_REFLEN
];
return
open
(
generate_name
(
log_name
,
"-slow.log"
,
0
,
buf
),
LOG_NORMAL
,
0
,
WRITE_CACHE
,
0
,
0
,
0
);
}
bool
open_index_file
(
const
char
*
index_file_name_arg
,
const
char
*
log_name
);
void
new_file
(
bool
need_lock
);
/* log a command to the old-fashioned general log */
bool
write
(
time_t
event_time
,
const
char
*
user_host
,
uint
user_host_len
,
int
thread_id
,
const
char
*
command_type
,
uint
command_type_len
,
const
char
*
sql_text
,
uint
sql_text_len
);
/* log a query to the old-fashioned slow query log */
bool
write
(
THD
*
thd
,
time_t
current_time
,
time_t
query_start_arg
,
const
char
*
user_host
,
uint
user_host_len
,
longlong
query_time
,
longlong
lock_time
,
bool
is_command
,
const
char
*
sql_text
,
uint
sql_text_len
);
/* Use this to start writing a new log file */
void
new_file
();
bool
write
(
Log_event
*
event_info
);
// binary log write
bool
write
(
THD
*
thd
,
IO_CACHE
*
cache
,
Log_event
*
commit_event
);
...
...
@@ -319,7 +352,6 @@ public:
bool
appendv
(
const
char
*
buf
,
uint
len
,...);
bool
append
(
Log_event
*
ev
);
int
generate_new_name
(
char
*
new_name
,
const
char
*
old_name
);
void
make_log_name
(
char
*
buf
,
const
char
*
log_ident
);
bool
is_active
(
const
char
*
log_file_name
);
int
update_log_index
(
LOG_INFO
*
linfo
,
bool
need_update_threads
);
...
...
@@ -416,7 +448,8 @@ public:
class
Log_to_file_event_handler
:
public
Log_event_handler
{
MYSQL_LOG
mysql_log
,
mysql_slow_log
;
MYSQL_GENERAL_LOG
mysql_log
;
MYSQL_SLOW_LOG
mysql_slow_log
;
bool
is_initialized
;
public:
Log_to_file_event_handler
()
:
is_initialized
(
FALSE
)
...
...
sql/log_event.h
View file @
fec70c97
...
...
@@ -470,7 +470,7 @@ enum Int_event_type
#ifndef MYSQL_CLIENT
class
String
;
class
MYSQL_LOG
;
class
MYSQL_
BIN_
LOG
;
class
THD
;
#endif
...
...
sql/mysql_priv.h
View file @
fec70c97
...
...
@@ -1525,7 +1525,7 @@ extern char *default_tz_name;
extern
my_bool
opt_large_pages
;
extern
uint
opt_large_page_size
;
extern
MYSQL_LOG
mysql_bin_log
;
extern
MYSQL_
BIN_
LOG
mysql_bin_log
;
extern
LOGGER
logger
;
extern
TABLE_LIST
general_log
,
slow_log
;
extern
FILE
*
bootstrap_file
;
...
...
sql/mysqld.cc
View file @
fec70c97
...
...
@@ -2610,10 +2610,10 @@ static int init_common_variables(const char *conf_file_name, int argc,
global_system_variables
.
time_zone
=
my_tz_SYSTEM
;
/*
Init mutexes for the global MYSQL_LOG objects.
Init mutexes for the global MYSQL_
BIN_
LOG objects.
As safe_mutex depends on what MY_INIT() does, we can't init the mutexes of
global MYSQL_
LOGs in their constructors, because then they would be inited
before MY_INIT(). So we do it here.
global MYSQL_
BIN_LOGs in their constructors, because then they would be
inited
before MY_INIT(). So we do it here.
*/
mysql_bin_log
.
init_pthread_objects
();
...
...
sql/rpl_injector.cc
View file @
fec70c97
...
...
@@ -25,7 +25,7 @@
/* inline since it's called below */
inline
injector
::
transaction
::
transaction
(
MYSQL_LOG
*
log
,
THD
*
thd
)
injector
::
transaction
::
transaction
(
MYSQL_
BIN_
LOG
*
log
,
THD
*
thd
)
:
m_state
(
START_STATE
),
m_thd
(
thd
)
{
/*
...
...
sql/rpl_injector.h
View file @
fec70c97
...
...
@@ -26,7 +26,7 @@
/* Forward declarations */
class
handler
;
class
MYSQL_LOG
;
class
MYSQL_
BIN_
LOG
;
class
st_table
;
typedef
st_table
TABLE
;
...
...
@@ -219,7 +219,7 @@ public:
private:
/* Only the injector may construct these object */
transaction
(
MYSQL_LOG
*
,
THD
*
);
transaction
(
MYSQL_
BIN_
LOG
*
,
THD
*
);
void
swap
(
transaction
&
o
)
{
/* std::swap(m_start_pos, o.m_start_pos); */
...
...
sql/rpl_rli.h
View file @
fec70c97
...
...
@@ -69,7 +69,7 @@ typedef struct st_relay_log_info
Protected with internal locks.
Must get data_lock when resetting the logs.
*/
MYSQL_LOG
relay_log
;
MYSQL_
BIN_
LOG
relay_log
;
LOG_INFO
linfo
;
IO_CACHE
cache_buf
,
*
cur_log
;
...
...
sql/slave.cc
View file @
fec70c97
...
...
@@ -4570,7 +4570,7 @@ static Log_event* next_event(RELAY_LOG_INFO* rli)
When the relay log is created when the I/O thread starts, easy: the
master will send the description event and we will queue it.
But if the relay log is created by new_file(): then the solution is:
MYSQL_LOG::open() will write the buffered description event.
MYSQL_
BIN_
LOG::open() will write the buffered description event.
*/
if
((
ev
=
Log_event
::
read_log_event
(
cur_log
,
0
,
rli
->
relay_log
.
description_event_for_exec
)))
...
...
@@ -4832,7 +4832,8 @@ err:
Rotate a relay log (this is used only by FLUSH LOGS; the automatic rotation
because of size is simpler because when we do it we already have all relevant
locks; here we don't, so this function is mainly taking locks).
Returns nothing as we cannot catch any error (MYSQL_LOG::new_file() is void).
Returns nothing as we cannot catch any error (MYSQL_BIN_LOG::new_file()
is void).
*/
void
rotate_relay_log
(
MASTER_INFO
*
mi
)
...
...
@@ -4854,7 +4855,7 @@ void rotate_relay_log(MASTER_INFO* mi)
}
/* If the relay log is closed, new_file() will do nothing. */
rli
->
relay_log
.
new_file
(
1
);
rli
->
relay_log
.
new_file
();
/*
We harvest now, because otherwise BIN_LOG_HEADER_SIZE will not immediately
...
...
sql/slave.h
View file @
fec70c97
...
...
@@ -73,7 +73,7 @@
run_lock protects all information about the run state: slave_running, and the
existence of the I/O thread (to stop/start it, you need this mutex).
data_lock protects some moving members of the struct: counters (log name,
position) and relay log (MYSQL_LOG object).
position) and relay log (MYSQL_
BIN_
LOG object).
In RELAY_LOG_INFO: run_lock, data_lock
see MASTER_INFO
...
...
@@ -81,7 +81,7 @@
Order of acquisition: if you want to have LOCK_active_mi and a run_lock, you
must acquire LOCK_active_mi first.
In MYSQL_LOG: LOCK_log, LOCK_index of the binlog and the relay log
In MYSQL_
BIN_
LOG: LOCK_log, LOCK_index of the binlog and the relay log
LOCK_log: when you write to it. LOCK_index: when you create/delete a binlog
(so that you have to update the .index file).
*/
...
...
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