summaryrefslogtreecommitdiff
path: root/client
diff options
context:
space:
mode:
authorunknown <gbichot@dl145h.mysql.com>2007-02-23 22:23:54 +0100
committerunknown <gbichot@dl145h.mysql.com>2007-02-23 22:23:54 +0100
commit6f6951d21867a2d71de414d21becf55feb3792b1 (patch)
treed70fb171b2521ed63ca7f3dec32e9a62453f00a0 /client
parent8777e35a144cbf51e0dc3ee6d621bc9711c1ea07 (diff)
downloadmariadb-git-6f6951d21867a2d71de414d21becf55feb3792b1.tar.gz
Fix for BUG#25628: "mysqlbinlog crashes while processing binary logs".
mysqlbinlog prints all row-based events of a single statement as a single "BINLOG" statement containing the concatenation of those events. Big (i.e. >64k) concatenations of row-based events (e.g. Write_rows_log_event) caused mysqlbinlog's IO_CACHE to overflow to a temporary file but the IO_CACHE had not been inited with open_cached_file(), so it tried to create a temporary file in an uninitialized directory (thus failing to create, then to write; some OS errors were printed, and it finally segfaulted). After fixing this, it appeared that mysqlbinlog was printing only a piece of big concatenations of row-based events (it printed at most the size of the IO_CACHE's buffer i.e. 64k); that caused data loss at restore. We fix and test that. Last, mysqlbinlog's printouts looked a bit strange with the informative header (#-prefixed) of groupped Rows_log_event all on one line, so we insert \n. After that, a small bug in the --hexdump code appeared (only if the string to hex-print had its length a multiple of 16), we fix it. client/mysqlbinlog.cc: if we write to IO_CACHE more than can fit into its memory buffer, it will try to overflow into a file; for that to work, IO_CACHE must be inited via open_cached_file(). mysql-test/r/mysqlbinlog_base64.result: result update mysql-test/t/mysqlbinlog_base64.test: test for BUG#25628: test that mysqlbinlog does not have OS errors with big concatenations of row-based events (e.g. Write_rows_log_event), and prints those concatenations entirely (testing by piping the output back into the server and comparing data). mysys/mf_iocache2.c: my_b_copy_to_file() had a problem: it assumed that bytes_in_cache are all the bytes to copy to the file, while it only tells how many bytes are in the buffer; so the code forgot to copy what had already overflown into a temporary file. Thus any big event was printed only partially by mysqlbinlog (loss of data at restore). The fix is inspired by MYSQL_BIN_LOG::write_cache(). sql/log_event.cc: Several Table_map/Write_rows events generated by one single statement get groupped together in mysqlbinlog's output; it printed things like #718 7:30:51 server id 12 end_log_pos 988 Write_rows: table id 17#718 7:30:51 server id 12 #718 7:30:51 server id 12 end_log_pos 988 Write_rows: table id 17#718 7:30:51 server id 12 end_log_pos 1413 <cut> It didn't look nice to have printouts glued like this without line breaks. Adding a line break. Doing this, when using --hexdump the result was: #718 7:30:51 server id 12 end_log_pos 988 # <hexdump output> # Write_rows: table id 17 which is correct; unfortunately if the hex dump had only full lines (i.e the string to print in hex had its length a multiple of 16), then the # in front of Write_rows was not printed. Fixed. sql/log_event.h: removing strcpy() (one less function call). If we write to IO_CACHE more than can fit into its memory buffer, it will try to overflow into a file; for that to work, IO_CACHE must be inited via open_cached_file(). open_cached_file(), like init_io_cache(), can fail; we make sure to catch this constructor's problem via the init_ok() method.
Diffstat (limited to 'client')
-rw-r--r--client/mysqlbinlog.cc10
1 files changed, 5 insertions, 5 deletions
diff --git a/client/mysqlbinlog.cc b/client/mysqlbinlog.cc
index 8242a481c5b..8d63ec56a30 100644
--- a/client/mysqlbinlog.cc
+++ b/client/mysqlbinlog.cc
@@ -487,18 +487,15 @@ write_event_header_and_base64(Log_event *ev, FILE *result_file,
DBUG_ENTER("write_event_header_and_base64");
/* Write header and base64 output to cache */
IO_CACHE result_cache;
- if (init_io_cache(&result_cache, -1, 0, WRITE_CACHE, 0L, FALSE,
- MYF(MY_WME | MY_NABP)))
- {
+ if (open_cached_file(&result_cache, NULL, NULL, 0, MYF(MY_WME | MY_NABP)))
return 1;
- }
ev->print_header(&result_cache, print_event_info, FALSE);
ev->print_base64(&result_cache, print_event_info, FALSE);
/* Read data from cache and write to result file */
my_b_copy_to_file(&result_cache, result_file);
- end_io_cache(&result_cache);
+ close_cached_file(&result_cache);
DBUG_RETURN(0);
}
@@ -1016,6 +1013,9 @@ static int dump_log_entries(const char* logname)
{
int rc;
PRINT_EVENT_INFO print_event_info;
+
+ if (!print_event_info.init_ok())
+ return 1;
/*
Set safe delimiter, to dump things
like CREATE PROCEDURE safely