1
/* Copyright (C) 2001-2004 MySQL AB
3
This program is free software; you can redistribute it and/or modify
4
it under the terms of the GNU General Public License as published by
5
the Free Software Foundation; version 2 of the License.
7
This program is distributed in the hope that it will be useful,
8
but WITHOUT ANY WARRANTY; without even the implied warranty of
9
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10
GNU General Public License for more details.
12
You should have received a copy of the GNU General Public License
13
along with this program; if not, write to the Free Software
14
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
18
TODO: print the catalog (some USE catalog.db ????).
20
Standalone program to read a MySQL binary log (or relay log);
21
can read files produced by 3.23, 4.x, 5.0 servers.
23
Can read binlogs from 3.23/4.x/5.0 and relay logs from 4.x/5.0.
24
Should be able to read any file of these categories, even with
26
An important fact: the Format_desc event of the log is at most the 3rd event
27
of the log; if it is the 3rd then there is this combination:
28
Format_desc_of_slave, Rotate_of_master, Format_desc_of_master.
33
#include "client_priv.h"
35
/* That one is necessary for defines of OPTION_NO_FOREIGN_KEY_CHECKS etc */
36
#include "mysql_priv.h"
37
#include "log_event.h"
38
#include "sql_common.h"
40
#define BIN_LOG_HEADER_SIZE 4
41
#define PROBE_HEADER_LEN (EVENT_LEN_OFFSET+4)
44
#define CLIENT_CAPABILITIES (CLIENT_LONG_PASSWORD | CLIENT_LONG_FLAG | CLIENT_LOCAL_FILES)
46
char server_version[SERVER_VERSION_LENGTH];
49
// needed by net_serv.c
50
ulong bytes_sent = 0L, bytes_received = 0L;
51
ulong mysqld_net_retry_count = 10L;
52
ulong open_files_limit;
54
static uint opt_protocol= 0;
55
static FILE *result_file;
58
static const char* default_dbug_option = "d:t:o,/tmp/mysqlbinlog.trace";
60
static const char *load_default_groups[]= { "mysqlbinlog","client",0 };
62
static void error(const char *format, ...) ATTRIBUTE_FORMAT(printf, 1, 2);
63
static void warning(const char *format, ...) ATTRIBUTE_FORMAT(printf, 1, 2);
65
static bool one_database=0, to_last_remote_log= 0, disable_log_bin= 0;
66
static bool opt_hexdump= 0;
67
const char *base64_output_mode_names[]= {"NEVER", "AUTO", "ALWAYS", NullS};
68
TYPELIB base64_output_mode_typelib=
69
{ array_elements(base64_output_mode_names) - 1, "",
70
base64_output_mode_names, NULL };
71
static enum_base64_output_mode opt_base64_output_mode= BASE64_OUTPUT_UNSPEC;
72
static const char *opt_base64_output_mode_str= NullS;
73
static const char* database= 0;
74
static my_bool force_opt= 0, short_form= 0, remote_opt= 0;
75
static my_bool debug_info_flag, debug_check_flag;
76
static my_bool force_if_open_opt= 1;
77
static ulonglong offset = 0;
78
static const char* host = 0;
80
static uint my_end_arg;
81
static const char* sock= 0;
82
static const char* user = 0;
83
static char* pass = 0;
84
static char *charset= 0;
86
static ulonglong start_position, stop_position;
87
#define start_position_mot ((my_off_t)start_position)
88
#define stop_position_mot ((my_off_t)stop_position)
90
static char *start_datetime_str, *stop_datetime_str;
91
static my_time_t start_datetime= 0, stop_datetime= MY_TIME_T_MAX;
92
static ulonglong rec_count= 0;
93
static short binlog_flags = 0;
94
static MYSQL* mysql = NULL;
95
static const char* dirname_for_local_load= 0;
98
Pointer to the Format_description_log_event of the currently active binlog.
100
This will be changed each time a new Format_description_log_event is
101
found in the binlog. It is finally destroyed at program termination.
103
static Format_description_log_event* glob_description_event= NULL;
106
Exit status for functions in this file.
109
/** No error occurred and execution should continue. */
111
/** An error occurred and execution should stop. */
113
/** No error occurred but execution should stop. */
117
static Exit_status dump_local_log_entries(PRINT_EVENT_INFO *print_event_info,
118
const char* logname);
119
static Exit_status dump_remote_log_entries(PRINT_EVENT_INFO *print_event_info,
120
const char* logname);
121
static Exit_status dump_log_entries(const char* logname);
122
static Exit_status safe_connect();
125
class Load_log_processor
127
char target_dir_name[FN_REFLEN];
128
int target_dir_name_len;
131
When we see first event corresponding to some LOAD DATA statement in
132
binlog, we create temporary file to store data to be loaded.
133
We add name of this file to file_names array using its file_id as index.
134
If we have Create_file event (i.e. we have binary log in pre-5.0.3
135
format) we also store save event object to be able which is needed to
136
emit LOAD DATA statement when we will meet Exec_load_data event.
137
If we have Begin_load_query event we simply store 0 in
138
File_name_record::event field.
140
struct File_name_record
143
Create_file_log_event *event;
146
@todo Should be a map (e.g., a hash map), not an array. With the
147
present implementation, the number of elements in this array is
148
about the number of files loaded since the server started, which
149
may be big after a few years. We should be able to use existing
150
library data structures for this. /Sven
152
DYNAMIC_ARRAY file_names;
155
Looks for a non-existing filename by adding a numerical suffix to
156
the given base name, creates the generated file, and returns the
157
filename by modifying the filename argument.
159
@param[in,out] filename Base filename
161
@param[in,out] file_name_end Pointer to last character of
162
filename. The numerical suffix will be written to this position.
163
Note that there must be a least five bytes of allocated memory
166
@retval -1 Error (can't find new filename).
167
@retval >=0 Found file.
169
File create_unique_file(char *filename, char *file_name_end)
172
/* If we have to try more than 1000 times, something is seriously wrong */
173
for (uint version= 0; version<1000; version++)
175
sprintf(file_name_end,"-%x",version);
176
if ((res= my_create(filename,0,
177
O_CREAT|O_EXCL|O_BINARY|O_WRONLY,MYF(0)))!=-1)
184
Load_log_processor() {}
185
~Load_log_processor() {}
189
return init_dynamic_array(&file_names, sizeof(File_name_record),
190
100,100 CALLER_INFO);
193
void init_by_dir_name(const char *dir)
195
target_dir_name_len= (convert_dirname(target_dir_name, dir, NullS) -
198
void init_by_cur_dir()
200
if (my_getwd(target_dir_name,sizeof(target_dir_name),MYF(MY_WME)))
202
target_dir_name_len= strlen(target_dir_name);
206
File_name_record *ptr= (File_name_record *)file_names.buffer;
207
File_name_record *end= ptr + file_names.elements;
208
for (; ptr < end; ptr++)
212
my_free(ptr->fname, MYF(MY_WME));
214
bzero((char *)ptr, sizeof(File_name_record));
218
delete_dynamic(&file_names);
222
Obtain Create_file event for LOAD DATA statement by its file_id
223
and remove it from this Load_log_processor's list of events.
225
Checks whether we have already seen a Create_file_log_event with
226
the given file_id. If yes, returns a pointer to the event and
227
removes the event from array describing active temporary files.
228
From this moment, the caller is responsible for freeing the memory
229
occupied by the event.
231
@param[in] file_id File id identifying LOAD DATA statement.
233
@return Pointer to Create_file_log_event, or NULL if we have not
234
seen any Create_file_log_event with this file_id.
236
Create_file_log_event *grab_event(uint file_id)
238
File_name_record *ptr;
239
Create_file_log_event *res;
241
if (file_id >= file_names.elements)
243
ptr= dynamic_element(&file_names, file_id, File_name_record*);
244
if ((res= ptr->event))
245
bzero((char *)ptr, sizeof(File_name_record));
250
Obtain file name of temporary file for LOAD DATA statement by its
251
file_id and remove it from this Load_log_processor's list of events.
253
@param[in] file_id Identifier for the LOAD DATA statement.
255
Checks whether we have already seen Begin_load_query event for
256
this file_id. If yes, returns the file name of the corresponding
257
temporary file and removes the filename from the array of active
258
temporary files. From this moment, the caller is responsible for
259
freeing the memory occupied by this name.
261
@return String with the name of the temporary file, or NULL if we
262
have not seen any Begin_load_query_event with this file_id.
264
char *grab_fname(uint file_id)
266
File_name_record *ptr;
269
if (file_id >= file_names.elements)
271
ptr= dynamic_element(&file_names, file_id, File_name_record*);
275
bzero((char *)ptr, sizeof(File_name_record));
279
Exit_status process(Create_file_log_event *ce);
280
Exit_status process(Begin_load_query_log_event *ce);
281
Exit_status process(Append_block_log_event *ae);
282
File prepare_new_file_for_old_format(Load_log_event *le, char *filename);
283
Exit_status load_old_format_file(NET* net, const char *server_fname,
284
uint server_fname_len, File file);
285
Exit_status process_first_event(const char *bname, uint blen,
287
uint block_len, uint file_id,
288
Create_file_log_event *ce);
293
Creates and opens a new temporary file in the directory specified by previous call to init_by_dir_name() or init_by_cur_dir().
295
@param[in] le The basename of the created file will start with the
296
basename of the file pointed to by this Load_log_event.
298
@param[out] filename Buffer to save the filename in.
300
@return File handle >= 0 on success, -1 on error.
302
File Load_log_processor::prepare_new_file_for_old_format(Load_log_event *le,
309
fn_format(filename, le->fname, target_dir_name, "", MY_REPLACE_DIR);
310
len= strlen(filename);
311
tail= filename + len;
313
if ((file= create_unique_file(filename,tail)) < 0)
315
error("Could not construct local filename %s.",filename);
319
le->set_fname_outside_temp_buf(filename,len+strlen(tail));
326
Reads a file from a server and saves it locally.
328
@param[in,out] net The server to read from.
330
@param[in] server_fname The name of the file that the server should
333
@param[in] server_fname_len The length of server_fname.
335
@param[in,out] file The file to write to.
337
@retval ERROR_STOP An error occurred - the program should terminate.
338
@retval OK_CONTINUE No error, the program should continue.
340
Exit_status Load_log_processor::load_old_format_file(NET* net,
341
const char*server_fname,
342
uint server_fname_len,
345
uchar buf[FN_REFLEN+1];
347
memcpy(buf + 1, server_fname, server_fname_len + 1);
348
if (my_net_write(net, buf, server_fname_len +2) || net_flush(net))
350
error("Failed requesting the remote dump of %s.", server_fname);
356
ulong packet_len = my_net_read(net);
359
if (my_net_write(net, (uchar*) "", 0) || net_flush(net))
361
error("Failed sending the ack packet.");
365
we just need to send something, as the server will read but
366
not examine the packet - this is because mysql_load() sends
367
an OK when it is done
371
else if (packet_len == packet_error)
373
error("Failed reading a packet during the dump of %s.", server_fname);
377
if (packet_len > UINT_MAX)
379
error("Illegal length of packet read from net.");
382
if (my_write(file, (uchar*) net->read_pos,
383
(uint) packet_len, MYF(MY_WME|MY_NABP)))
392
Process the first event in the sequence of events representing a
395
Creates a temporary file to be used in LOAD DATA and writes first
396
block of data to it. Registers its file name (and optional
397
Create_file event) in the array of active temporary files.
399
@param bname Base name for temporary file to be created.
400
@param blen Base name length.
401
@param block First block of data to be loaded.
402
@param block_len First block length.
403
@param file_id Identifies the LOAD DATA statement.
404
@param ce Pointer to Create_file event object if we are processing
407
@retval ERROR_STOP An error occurred - the program should terminate.
408
@retval OK_CONTINUE No error, the program should continue.
410
Exit_status Load_log_processor::process_first_event(const char *bname,
415
Create_file_log_event *ce)
417
uint full_len= target_dir_name_len + blen + 9 + 9 + 1;
418
Exit_status retval= OK_CONTINUE;
421
File_name_record rec;
422
DBUG_ENTER("Load_log_processor::process_first_event");
424
if (!(fname= (char*) my_malloc(full_len,MYF(MY_WME))))
426
error("Out of memory.");
428
DBUG_RETURN(ERROR_STOP);
431
memcpy(fname, target_dir_name, target_dir_name_len);
432
ptr= fname + target_dir_name_len;
433
memcpy(ptr,bname,blen);
435
ptr+= my_sprintf(ptr, (ptr, "-%x", file_id));
437
if ((file= create_unique_file(fname,ptr)) < 0)
439
error("Could not construct local filename %s%s.",
440
target_dir_name,bname);
442
DBUG_RETURN(ERROR_STOP);
448
if (set_dynamic(&file_names, (uchar*)&rec, file_id))
450
error("Out of memory.");
452
DBUG_RETURN(ERROR_STOP);
456
ce->set_fname_outside_temp_buf(fname, strlen(fname));
458
if (my_write(file, (uchar*)block, block_len, MYF(MY_WME|MY_NABP)))
460
error("Failed writing to file.");
463
if (my_close(file, MYF(MY_WME)))
465
error("Failed closing file.");
473
Process the given Create_file_log_event.
475
@see Load_log_processor::process_first_event(const char*,uint,const char*,uint,uint,Create_file_log_event*)
477
@param ce Create_file_log_event to process.
479
@retval ERROR_STOP An error occurred - the program should terminate.
480
@retval OK_CONTINUE No error, the program should continue.
482
Exit_status Load_log_processor::process(Create_file_log_event *ce)
484
const char *bname= ce->fname + dirname_length(ce->fname);
485
uint blen= ce->fname_len - (bname-ce->fname);
487
return process_first_event(bname, blen, ce->block, ce->block_len,
493
Process the given Begin_load_query_log_event.
495
@see Load_log_processor::process_first_event(const char*,uint,const char*,uint,uint,Create_file_log_event*)
497
@param ce Begin_load_query_log_event to process.
499
@retval ERROR_STOP An error occurred - the program should terminate.
500
@retval OK_CONTINUE No error, the program should continue.
502
Exit_status Load_log_processor::process(Begin_load_query_log_event *blqe)
504
return process_first_event("SQL_LOAD_MB", 11, blqe->block, blqe->block_len,
510
Process the given Append_block_log_event.
512
Appends the chunk of the file contents specified by the event to the
513
file created by a previous Begin_load_query_log_event or
514
Create_file_log_event.
516
If the file_id for the event does not correspond to any file
517
previously registered through a Begin_load_query_log_event or
518
Create_file_log_event, this member function will print a warning and
519
return OK_CONTINUE. It is safe to return OK_CONTINUE, because no
520
query will be written for this event. We should not print an error
521
and fail, since the missing file_id could be because a (valid)
522
--start-position has been specified after the Begin/Create event but
523
before this Append event.
525
@param ae Append_block_log_event to process.
527
@retval ERROR_STOP An error occurred - the program should terminate.
529
@retval OK_CONTINUE No error, the program should continue.
531
Exit_status Load_log_processor::process(Append_block_log_event *ae)
533
DBUG_ENTER("Load_log_processor::process");
534
const char* fname= ((ae->file_id < file_names.elements) ?
535
dynamic_element(&file_names, ae->file_id,
536
File_name_record*)->fname : 0);
541
Exit_status retval= OK_CONTINUE;
542
if (((file= my_open(fname,
543
O_APPEND|O_BINARY|O_WRONLY,MYF(MY_WME))) < 0))
545
error("Failed opening file %s", fname);
546
DBUG_RETURN(ERROR_STOP);
548
if (my_write(file,(uchar*)ae->block,ae->block_len,MYF(MY_WME|MY_NABP)))
550
error("Failed writing to file %s", fname);
553
if (my_close(file,MYF(MY_WME)))
555
error("Failed closing file %s", fname);
562
There is no Create_file event (a bad binlog or a big
563
--start-position). Assuming it's a big --start-position, we just do
564
nothing and print a warning.
566
warning("Ignoring Append_block as there is no "
567
"Create_file event for file_id: %u", ae->file_id);
568
DBUG_RETURN(OK_CONTINUE);
572
static Load_log_processor load_processor;
576
Replace windows-style backslashes by forward slashes so it can be
577
consumed by the mysql client, which requires Unix path.
579
@todo This is only useful under windows, so may be ifdef'ed out on
582
@todo If a Create_file_log_event contains a filename with a
583
backslash (valid under unix), then we have problems under windows.
586
@param[in,out] fname Filename to modify. The filename is modified
589
static void convert_path_to_forward_slashes(char *fname)
601
Indicates whether the given database should be filtered out,
602
according to the --database=X option.
604
@param log_dbname Name of database.
606
@return nonzero if the database with the given name should be
607
filtered out, 0 otherwise.
609
static bool shall_skip_database(const char *log_dbname)
611
return one_database &&
612
(log_dbname != NULL) &&
613
strcmp(log_dbname, database);
618
Prints the given event in base64 format.
620
The header is printed to the head cache and the body is printed to
621
the body cache of the print_event_info structure. This allows all
622
base64 events corresponding to the same statement to be joined into
623
one BINLOG statement.
625
@param[in] ev Log_event to print.
626
@param[in,out] result_file FILE to which the output will be written.
627
@param[in,out] print_event_info Parameters and context state
628
determining how to print.
630
@retval ERROR_STOP An error occurred - the program should terminate.
631
@retval OK_CONTINUE No error, the program should continue.
634
write_event_header_and_base64(Log_event *ev, FILE *result_file,
635
PRINT_EVENT_INFO *print_event_info)
637
IO_CACHE *head= &print_event_info->head_cache;
638
IO_CACHE *body= &print_event_info->body_cache;
639
DBUG_ENTER("write_event_header_and_base64");
641
/* Write header and base64 output to cache */
642
ev->print_header(head, print_event_info, FALSE);
643
ev->print_base64(body, print_event_info, FALSE);
645
/* Read data from cache and write to result file */
646
if (copy_event_cache_to_file_and_reinit(head, result_file) ||
647
copy_event_cache_to_file_and_reinit(body, result_file))
649
error("Error writing event to file.");
650
DBUG_RETURN(ERROR_STOP);
652
DBUG_RETURN(OK_CONTINUE);
657
Print the given event, and either delete it or delegate the deletion
660
The deletion may be delegated in two cases: (1) the event is a
661
Format_description_log_event, and is saved in
662
glob_description_event; (2) the event is a Create_file_log_event,
663
and is saved in load_processor.
665
@param[in,out] print_event_info Parameters and context state
666
determining how to print.
667
@param[in] ev Log_event to process.
668
@param[in] pos Offset from beginning of binlog file.
669
@param[in] logname Name of input binlog.
671
@retval ERROR_STOP An error occurred - the program should terminate.
672
@retval OK_CONTINUE No error, the program should continue.
673
@retval OK_STOP No error, but the end of the specified range of
674
events to process has been reached and the program should terminate.
676
Exit_status process_event(PRINT_EVENT_INFO *print_event_info, Log_event *ev,
677
my_off_t pos, const char *logname)
680
Log_event_type ev_type= ev->get_type_code();
681
DBUG_ENTER("process_event");
682
print_event_info->short_form= short_form;
683
Exit_status retval= OK_CONTINUE;
686
Format events are not concerned by --offset and such, we always need to
687
read them to be able to process the wanted events.
689
if (((rec_count >= offset) && ((my_time_t)(ev->when) >= start_datetime)) || (ev_type == FORMAT_DESCRIPTION_EVENT))
691
if (ev_type != FORMAT_DESCRIPTION_EVENT)
694
We have found an event after start_datetime, from now on print
695
everything (in case the binlog has timestamps increasing and
696
decreasing, we do this to avoid cutting the middle).
699
offset= 0; // print everything and protect against cycling rec_count
701
if (server_id && (server_id != ev->server_id))
702
/* skip just this event, continue processing the log. */
704
if (((my_time_t)(ev->when) >= stop_datetime)
705
|| (pos >= stop_position_mot))
707
/* end the program */
712
fprintf(result_file, "# at %s\n",llstr(pos,ll_buff));
715
print_event_info->hexdump_from= 0; /* Disabled */
717
print_event_info->hexdump_from= pos;
719
print_event_info->base64_output_mode= opt_base64_output_mode;
721
DBUG_PRINT("debug", ("event_type: %s", ev->get_type_str()));
725
if (shall_skip_database(((Query_log_event*)ev)->db))
727
if (opt_base64_output_mode == BASE64_OUTPUT_ALWAYS)
729
if ((retval= write_event_header_and_base64(ev, result_file,
730
print_event_info)) !=
735
ev->print(result_file, print_event_info);
738
case CREATE_FILE_EVENT:
740
Create_file_log_event* ce= (Create_file_log_event*)ev;
742
We test if this event has to be ignored. If yes, we don't save
743
this event; this will have the good side-effect of ignoring all
744
related Append_block and Exec_load.
745
Note that Load event from 3.23 is not tested.
747
if (shall_skip_database(ce->db))
748
goto end; // Next event
750
We print the event, but with a leading '#': this is just to inform
751
the user of the original command; the command we want to execute
752
will be a derivation of this original command (we will change the
753
filename and use LOCAL), prepared in the 'case EXEC_LOAD_EVENT'
756
if (opt_base64_output_mode == BASE64_OUTPUT_ALWAYS)
758
if ((retval= write_event_header_and_base64(ce, result_file,
759
print_event_info)) !=
764
ce->print(result_file, print_event_info, TRUE);
766
// If this binlog is not 3.23 ; why this test??
767
if (glob_description_event->binlog_version >= 3)
770
transfer the responsibility for destroying the event to
774
if ((retval= load_processor.process(ce)) != OK_CONTINUE)
780
case APPEND_BLOCK_EVENT:
782
Append_block_log_events can safely print themselves even if
783
the subsequent call load_processor.process fails, because the
784
output of Append_block_log_event::print is only a comment.
786
ev->print(result_file, print_event_info);
787
if ((retval= load_processor.process((Append_block_log_event*) ev)) !=
792
case EXEC_LOAD_EVENT:
794
ev->print(result_file, print_event_info);
795
Execute_load_log_event *exv= (Execute_load_log_event*)ev;
796
Create_file_log_event *ce= load_processor.grab_event(exv->file_id);
798
if ce is 0, it probably means that we have not seen the Create_file
799
event (a bad binlog, or most probably --start-position is after the
800
Create_file event). Print a warning comment.
805
We must not convert earlier, since the file is used by
806
my_open() in Load_log_processor::append().
808
convert_path_to_forward_slashes((char*) ce->fname);
809
ce->print(result_file, print_event_info, TRUE);
810
my_free((char*)ce->fname,MYF(MY_WME));
814
warning("Ignoring Execute_load_log_event as there is no "
815
"Create_file event for file_id: %u", exv->file_id);
818
case FORMAT_DESCRIPTION_EVENT:
819
delete glob_description_event;
820
glob_description_event= (Format_description_log_event*) ev;
821
print_event_info->common_header_len=
822
glob_description_event->common_header_len;
823
ev->print(result_file, print_event_info);
824
ev->temp_buf= 0; // as the event ref is zeroed
826
We don't want this event to be deleted now, so let's hide it (I
827
(Guilhem) should later see if this triggers a non-serious Valgrind
828
error). Not serious error, because we will free description_event
832
if (!force_if_open_opt &&
833
(glob_description_event->flags & LOG_EVENT_BINLOG_IN_USE_F))
835
error("Attempting to dump binlog '%s', which was not closed properly. "
836
"Most probably, mysqld is still writing it, or it crashed. "
837
"Rerun with --force-if-open to ignore this problem.", logname);
838
DBUG_RETURN(ERROR_STOP);
841
case BEGIN_LOAD_QUERY_EVENT:
842
ev->print(result_file, print_event_info);
843
if ((retval= load_processor.process((Begin_load_query_log_event*) ev)) !=
847
case EXECUTE_LOAD_QUERY_EVENT:
849
Execute_load_query_log_event *exlq= (Execute_load_query_log_event*)ev;
850
char *fname= load_processor.grab_fname(exlq->file_id);
852
if (!shall_skip_database(exlq->db))
856
convert_path_to_forward_slashes(fname);
857
exlq->print(result_file, print_event_info, fname);
860
warning("Ignoring Execute_load_query since there is no "
861
"Begin_load_query event for file_id: %u", exlq->file_id);
865
my_free(fname, MYF(MY_WME));
868
case TABLE_MAP_EVENT:
869
case WRITE_ROWS_EVENT:
870
case DELETE_ROWS_EVENT:
871
case UPDATE_ROWS_EVENT:
872
case PRE_GA_WRITE_ROWS_EVENT:
873
case PRE_GA_DELETE_ROWS_EVENT:
874
case PRE_GA_UPDATE_ROWS_EVENT:
876
These events must be printed in base64 format, if printed.
877
base64 format requires a FD event to be safe, so if no FD
878
event has been printed, we give an error. Except if user
879
passed --short-form, because --short-form disables printing
882
if (!print_event_info->printed_fd_event && !short_form)
884
const char* type_str= ev->get_type_str();
885
if (opt_base64_output_mode == BASE64_OUTPUT_NEVER)
886
error("--base64-output=never specified, but binlog contains a "
887
"%s event which must be printed in base64.",
890
error("malformed binlog: it does not contain any "
891
"Format_description_log_event. I now found a %s event, which "
892
"is not safe to process without a "
893
"Format_description_log_event.",
899
ev->print(result_file, print_event_info);
910
Destroy the log_event object. If reading from a remote host,
911
set the temp_buf to NULL so that memory isn't freed twice.
923
static struct my_option my_long_options[] =
925
{"help", '?', "Display this help and exit.",
926
0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0},
928
{"autoclose", OPT_AUTO_CLOSE, "Auto close the screen on exit for Netware.",
929
0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0},
931
{"base64-output", OPT_BASE64_OUTPUT_MODE,
932
"Determine when the output statements should be base64-encoded BINLOG "
933
"statements: 'never' disables it and works only for binlogs without "
934
"row-based events; 'auto' is the default and prints base64 only when "
935
"necessary (i.e., for row-based events and format description events); "
936
"'always' prints base64 whenever possible. 'always' is for debugging "
937
"only and should not be used in a production system. The default is "
938
"'auto'. --base64-output is a short form for --base64-output=always."
939
,(uchar**) &opt_base64_output_mode_str,
940
(uchar**) &opt_base64_output_mode_str,
941
0, GET_STR, OPT_ARG, 0, 0, 0, 0, 0, 0},
943
mysqlbinlog needs charsets knowledge, to be able to convert a charset
944
number found in binlog to a charset name (to be able to print things
946
SET @`a`:=_cp850 0x4DFC6C6C6572 COLLATE `cp850_general_ci`;
948
{"character-sets-dir", OPT_CHARSETS_DIR,
949
"Directory where character sets are.", (uchar**) &charsets_dir,
950
(uchar**) &charsets_dir, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
951
{"database", 'd', "List entries for just this database (local log only).",
952
(uchar**) &database, (uchar**) &database, 0, GET_STR_ALLOC, REQUIRED_ARG,
955
{"debug", '#', "Output debug log.", (uchar**) &default_dbug_option,
956
(uchar**) &default_dbug_option, 0, GET_STR, OPT_ARG, 0, 0, 0, 0, 0, 0},
958
{"debug-check", OPT_DEBUG_CHECK, "Check memory and open file usage at exit .",
959
(uchar**) &debug_check_flag, (uchar**) &debug_check_flag, 0,
960
GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0},
961
{"debug-info", OPT_DEBUG_INFO, "Print some debug info at exit.",
962
(uchar**) &debug_info_flag, (uchar**) &debug_info_flag,
963
0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0},
964
{"disable-log-bin", 'D', "Disable binary log. This is useful, if you "
965
"enabled --to-last-log and are sending the output to the same MySQL server. "
966
"This way you could avoid an endless loop. You would also like to use it "
967
"when restoring after a crash to avoid duplication of the statements you "
968
"already have. NOTE: you will need a SUPER privilege to use this option.",
969
(uchar**) &disable_log_bin, (uchar**) &disable_log_bin, 0, GET_BOOL,
970
NO_ARG, 0, 0, 0, 0, 0, 0},
971
{"force-if-open", 'F', "Force if binlog was not closed properly.",
972
(uchar**) &force_if_open_opt, (uchar**) &force_if_open_opt, 0, GET_BOOL, NO_ARG,
974
{"force-read", 'f', "Force reading unknown binlog events.",
975
(uchar**) &force_opt, (uchar**) &force_opt, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0,
977
{"hexdump", 'H', "Augment output with hexadecimal and ASCII event dump.",
978
(uchar**) &opt_hexdump, (uchar**) &opt_hexdump, 0, GET_BOOL, NO_ARG,
980
{"host", 'h', "Get the binlog from server.", (uchar**) &host, (uchar**) &host,
981
0, GET_STR_ALLOC, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
982
{"local-load", 'l', "Prepare local temporary files for LOAD DATA INFILE in the specified directory.",
983
(uchar**) &dirname_for_local_load, (uchar**) &dirname_for_local_load, 0,
984
GET_STR_ALLOC, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
985
{"offset", 'o', "Skip the first N entries.", (uchar**) &offset, (uchar**) &offset,
986
0, GET_ULL, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
987
{"password", 'p', "Password to connect to remote server.",
988
0, 0, 0, GET_STR, OPT_ARG, 0, 0, 0, 0, 0, 0},
989
{"port", 'P', "Port number to use for connection or 0 for default to, in "
990
"order of preference, my.cnf, $MYSQL_TCP_PORT, "
991
#if MYSQL_PORT_DEFAULT == 0
994
"built-in default (" STRINGIFY_ARG(MYSQL_PORT) ").",
995
(uchar**) &port, (uchar**) &port, 0, GET_INT, REQUIRED_ARG,
997
{"position", 'j', "Deprecated. Use --start-position instead.",
998
(uchar**) &start_position, (uchar**) &start_position, 0, GET_ULL,
999
REQUIRED_ARG, BIN_LOG_HEADER_SIZE, BIN_LOG_HEADER_SIZE,
1000
/* COM_BINLOG_DUMP accepts only 4 bytes for the position */
1001
(ulonglong)(~(uint32)0), 0, 0, 0},
1002
{"protocol", OPT_MYSQL_PROTOCOL,
1003
"The protocol of connection (tcp,socket,pipe,memory).",
1004
0, 0, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
1005
{"read-from-remote-server", 'R', "Read binary logs from a MySQL server",
1006
(uchar**) &remote_opt, (uchar**) &remote_opt, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0,
1008
{"result-file", 'r', "Direct output to a given file.", 0, 0, 0, GET_STR,
1009
REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
1010
{"server-id", OPT_SERVER_ID,
1011
"Extract only binlog entries created by the server having the given id.",
1012
(uchar**) &server_id, (uchar**) &server_id, 0, GET_ULONG,
1013
REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
1014
{"set-charset", OPT_SET_CHARSET,
1015
"Add 'SET NAMES character_set' to the output.", (uchar**) &charset,
1016
(uchar**) &charset, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
1017
{"short-form", 's', "Just show regular queries: no extra info and no "
1018
"row-based events. This is for testing only, and should not be used in "
1019
"production systems. If you want to suppress base64-output, consider "
1020
"using --base64-output=never instead.",
1021
(uchar**) &short_form, (uchar**) &short_form, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0,
1023
{"socket", 'S', "Socket file to use for connection.",
1024
(uchar**) &sock, (uchar**) &sock, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0,
1026
{"start-datetime", OPT_START_DATETIME,
1027
"Start reading the binlog at first event having a datetime equal or "
1028
"posterior to the argument; the argument must be a date and time "
1029
"in the local time zone, in any format accepted by the MySQL server "
1030
"for DATETIME and TIMESTAMP types, for example: 2004-12-25 11:25:56 "
1031
"(you should probably use quotes for your shell to set it properly).",
1032
(uchar**) &start_datetime_str, (uchar**) &start_datetime_str,
1033
0, GET_STR_ALLOC, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
1034
{"start-position", OPT_START_POSITION,
1035
"Start reading the binlog at position N. Applies to the first binlog "
1036
"passed on the command line.",
1037
(uchar**) &start_position, (uchar**) &start_position, 0, GET_ULL,
1038
REQUIRED_ARG, BIN_LOG_HEADER_SIZE, BIN_LOG_HEADER_SIZE,
1039
/* COM_BINLOG_DUMP accepts only 4 bytes for the position */
1040
(ulonglong)(~(uint32)0), 0, 0, 0},
1041
{"stop-datetime", OPT_STOP_DATETIME,
1042
"Stop reading the binlog at first event having a datetime equal or "
1043
"posterior to the argument; the argument must be a date and time "
1044
"in the local time zone, in any format accepted by the MySQL server "
1045
"for DATETIME and TIMESTAMP types, for example: 2004-12-25 11:25:56 "
1046
"(you should probably use quotes for your shell to set it properly).",
1047
(uchar**) &stop_datetime_str, (uchar**) &stop_datetime_str,
1048
0, GET_STR_ALLOC, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
1049
{"stop-position", OPT_STOP_POSITION,
1050
"Stop reading the binlog at position N. Applies to the last binlog "
1051
"passed on the command line.",
1052
(uchar**) &stop_position, (uchar**) &stop_position, 0, GET_ULL,
1053
REQUIRED_ARG, (ulonglong)(~(my_off_t)0), BIN_LOG_HEADER_SIZE,
1054
(ulonglong)(~(my_off_t)0), 0, 0, 0},
1055
{"to-last-log", 't', "Requires -R. Will not stop at the end of the \
1056
requested binlog but rather continue printing until the end of the last \
1057
binlog of the MySQL server. If you send the output to the same MySQL server, \
1058
that may lead to an endless loop.",
1059
(uchar**) &to_last_remote_log, (uchar**) &to_last_remote_log, 0, GET_BOOL,
1060
NO_ARG, 0, 0, 0, 0, 0, 0},
1061
{"user", 'u', "Connect to the remote server as username.",
1062
(uchar**) &user, (uchar**) &user, 0, GET_STR_ALLOC, REQUIRED_ARG, 0, 0, 0, 0,
1064
{"version", 'V', "Print version and exit.", 0, 0, 0, GET_NO_ARG, NO_ARG, 0,
1066
{"open_files_limit", OPT_OPEN_FILES_LIMIT,
1067
"Used to reserve file descriptors for usage by this program",
1068
(uchar**) &open_files_limit, (uchar**) &open_files_limit, 0, GET_ULONG,
1069
REQUIRED_ARG, MY_NFILE, 8, OS_FILE_LIMIT, 0, 1, 0},
1070
{0, 0, 0, 0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0}
1075
Auxiliary function used by error() and warning().
1077
Prints the given text (normally "WARNING: " or "ERROR: "), followed
1078
by the given vprintf-style string, followed by a newline.
1080
@param format Printf-style format string.
1081
@param args List of arguments for the format string.
1082
@param msg Text to print before the string.
1084
static void error_or_warning(const char *format, va_list args, const char *msg)
1086
fprintf(stderr, "%s: ", msg);
1087
vfprintf(stderr, format, args);
1088
fprintf(stderr, "\n");
1092
Prints a message to stderr, prefixed with the text "ERROR: " and
1093
suffixed with a newline.
1095
@param format Printf-style format string, followed by printf
1098
static void error(const char *format,...)
1101
va_start(args, format);
1102
error_or_warning(format, args, "ERROR");
1108
This function is used in log_event.cc to report errors.
1110
@param format Printf-style format string, followed by printf
1113
static void sql_print_error(const char *format,...)
1116
va_start(args, format);
1117
error_or_warning(format, args, "ERROR");
1122
Prints a message to stderr, prefixed with the text "WARNING: " and
1123
suffixed with a newline.
1125
@param format Printf-style format string, followed by printf
1128
static void warning(const char *format,...)
1131
va_start(args, format);
1132
error_or_warning(format, args, "WARNING");
1137
Frees memory for global variables in this file.
1139
static void cleanup()
1141
my_free(pass,MYF(MY_ALLOW_ZERO_PTR));
1142
my_free((char*) database, MYF(MY_ALLOW_ZERO_PTR));
1143
my_free((char*) host, MYF(MY_ALLOW_ZERO_PTR));
1144
my_free((char*) user, MYF(MY_ALLOW_ZERO_PTR));
1145
my_free((char*) dirname_for_local_load, MYF(MY_ALLOW_ZERO_PTR));
1147
delete glob_description_event;
1152
#include <help_start.h>
1154
static void print_version()
1156
printf("%s Ver 3.3 for %s at %s\n", my_progname, SYSTEM_TYPE, MACHINE_TYPE);
1157
NETWARE_SET_SCREEN_MODE(1);
1164
puts("By Monty and Sasha, for your professional use\n\
1165
This software comes with NO WARRANTY: This is free software,\n\
1166
and you are welcome to modify and redistribute it under the GPL license\n");
1169
Dumps a MySQL binary log in a format usable for viewing or for piping to\n\
1170
the mysql command line client\n\n");
1171
printf("Usage: %s [options] log-files\n", my_progname);
1172
my_print_help(my_long_options);
1173
my_print_variables(my_long_options);
1177
static my_time_t convert_str_to_timestamp(const char* str)
1181
long dummy_my_timezone;
1182
my_bool dummy_in_dst_time_gap;
1183
/* We require a total specification (date AND time) */
1184
if (str_to_datetime(str, strlen(str), &l_time, 0, &was_cut) !=
1185
MYSQL_TIMESTAMP_DATETIME || was_cut)
1187
error("Incorrect date and time argument: %s", str);
1191
Note that Feb 30th, Apr 31st cause no error messages and are mapped to
1192
the next existing day, like in mysqld. Maybe this could be changed when
1193
mysqld is changed too (with its "strict" mode?).
1196
my_system_gmt_sec(&l_time, &dummy_my_timezone, &dummy_in_dst_time_gap);
1199
#include <help_end.h>
1202
get_one_option(int optid, const struct my_option *opt __attribute__((unused)),
1205
bool tty_password=0;
1208
case OPT_AUTO_CLOSE:
1209
setscreenmode(SCR_AUTOCLOSE_ON_EXIT);
1214
DBUG_PUSH(argument ? argument : default_dbug_option);
1223
my_free(pass,MYF(MY_ALLOW_ZERO_PTR));
1224
char *start=argument;
1225
pass= my_strdup(argument,MYF(MY_FAE));
1226
while (*argument) *argument++= 'x'; /* Destroy argument */
1228
start[1]=0; /* Cut length of argument */
1234
if (!(result_file = my_fopen(argument, O_WRONLY | O_BINARY, MYF(MY_WME))))
1240
case OPT_MYSQL_PROTOCOL:
1241
opt_protocol= find_type_or_exit(argument, &sql_protocol_typelib,
1244
case OPT_START_DATETIME:
1245
start_datetime= convert_str_to_timestamp(start_datetime_str);
1247
case OPT_STOP_DATETIME:
1248
stop_datetime= convert_str_to_timestamp(stop_datetime_str);
1250
case OPT_BASE64_OUTPUT_MODE:
1251
if (argument == NULL)
1252
opt_base64_output_mode= BASE64_OUTPUT_ALWAYS;
1255
opt_base64_output_mode= (enum_base64_output_mode)
1256
(find_type_or_exit(argument, &base64_output_mode_typelib, opt->name)-1);
1267
pass= get_tty_password(NullS);
1273
static int parse_args(int *argc, char*** argv)
1277
result_file = stdout;
1278
load_defaults("my",load_default_groups,argc,argv);
1279
if ((ho_error=handle_options(argc, argv, my_long_options, get_one_option)))
1281
if (debug_info_flag)
1282
my_end_arg= MY_CHECK_ERROR | MY_GIVE_INFO;
1283
if (debug_check_flag)
1284
my_end_arg= MY_CHECK_ERROR;
1290
Create and initialize the global mysql object, and connect to the
1293
@retval ERROR_STOP An error occurred - the program should terminate.
1294
@retval OK_CONTINUE No error, the program should continue.
1296
static Exit_status safe_connect()
1298
mysql= mysql_init(NULL);
1302
error("Failed on mysql_init.");
1307
mysql_options(mysql, MYSQL_OPT_PROTOCOL, (char*) &opt_protocol);
1308
if (!mysql_real_connect(mysql, host, user, pass, 0, port, sock, 0))
1310
error("Failed on connect: %s", mysql_error(mysql));
1313
mysql->reconnect= 1;
1319
High-level function for dumping a named binlog.
1321
This function calls dump_remote_log_entries() or
1322
dump_local_log_entries() to do the job.
1324
@param[in] logname Name of input binlog.
1326
@retval ERROR_STOP An error occurred - the program should terminate.
1327
@retval OK_CONTINUE No error, the program should continue.
1328
@retval OK_STOP No error, but the end of the specified range of
1329
events to process has been reached and the program should terminate.
1331
static Exit_status dump_log_entries(const char* logname)
1334
PRINT_EVENT_INFO print_event_info;
1336
if (!print_event_info.init_ok())
1339
Set safe delimiter, to dump things
1340
like CREATE PROCEDURE safely
1342
fprintf(result_file, "DELIMITER /*!*/;\n");
1343
strmov(print_event_info.delimiter, "/*!*/;");
1345
rc= (remote_opt ? dump_remote_log_entries(&print_event_info, logname) :
1346
dump_local_log_entries(&print_event_info, logname));
1348
/* Set delimiter back to semicolon */
1349
fprintf(result_file, "DELIMITER ;\n");
1350
strmov(print_event_info.delimiter, ";");
1356
When reading a remote binlog, this function is used to grab the
1357
Format_description_log_event in the beginning of the stream.
1359
This is not as smart as check_header() (used for local log); it will
1360
not work for a binlog which mixes format. TODO: fix this.
1362
@retval ERROR_STOP An error occurred - the program should terminate.
1363
@retval OK_CONTINUE No error, the program should continue.
1365
static Exit_status check_master_version()
1369
const char* version;
1371
if (mysql_query(mysql, "SELECT VERSION()") ||
1372
!(res = mysql_store_result(mysql)))
1374
error("Could not find server version: "
1375
"Query failed when checking master version: %s", mysql_error(mysql));
1378
if (!(row = mysql_fetch_row(res)))
1380
error("Could not find server version: "
1381
"Master returned no rows for SELECT VERSION().");
1385
if (!(version = row[0]))
1387
error("Could not find server version: "
1388
"Master reported NULL for the version.");
1392
delete glob_description_event;
1395
glob_description_event= new Format_description_log_event(1);
1398
glob_description_event= new Format_description_log_event(3);
1403
The server is soon going to send us its Format_description log
1404
event, unless it is a 5.0 server with 3.23 or 4.0 binlogs.
1405
So we first assume that this is 4.0 (which is enough to read the
1406
Format_desc event if one comes).
1408
glob_description_event= new Format_description_log_event(3);
1411
glob_description_event= NULL;
1412
error("Could not find server version: "
1413
"Master reported unrecognized MySQL version '%s'.", version);
1416
if (!glob_description_event || !glob_description_event->is_valid())
1418
error("Failed creating Format_description_log_event; out of memory?");
1422
mysql_free_result(res);
1426
mysql_free_result(res);
1432
Requests binlog dump from a remote server and prints the events it
1435
@param[in,out] print_event_info Parameters and context state
1436
determining how to print.
1437
@param[in] logname Name of input binlog.
1439
@retval ERROR_STOP An error occurred - the program should terminate.
1440
@retval OK_CONTINUE No error, the program should continue.
1441
@retval OK_STOP No error, but the end of the specified range of
1442
events to process has been reached and the program should terminate.
1444
static Exit_status dump_remote_log_entries(PRINT_EVENT_INFO *print_event_info,
1445
const char* logname)
1452
my_off_t old_off= start_position_mot;
1453
char fname[FN_REFLEN+1];
1454
Exit_status retval= OK_CONTINUE;
1455
DBUG_ENTER("dump_remote_log_entries");
1458
Even if we already read one binlog (case of >=2 binlogs on command line),
1459
we cannot re-use the same connection as before, because it is now dead
1460
(COM_BINLOG_DUMP kills the thread when it finishes).
1462
if ((retval= safe_connect()) != OK_CONTINUE)
1463
DBUG_RETURN(retval);
1466
if ((retval= check_master_version()) != OK_CONTINUE)
1467
DBUG_RETURN(retval);
1470
COM_BINLOG_DUMP accepts only 4 bytes for the position, so we are forced to
1473
int4store(buf, (uint32)start_position);
1474
int2store(buf + BIN_LOG_HEADER_SIZE, binlog_flags);
1476
size_t tlen = strlen(logname);
1477
if (tlen > UINT_MAX)
1479
error("Log name too long.");
1480
DBUG_RETURN(ERROR_STOP);
1482
logname_len = (uint) tlen;
1483
int4store(buf + 6, 0);
1484
memcpy(buf + 10, logname, logname_len);
1485
if (simple_command(mysql, COM_BINLOG_DUMP, buf, logname_len + 10, 1))
1487
error("Got fatal error sending the log dump command.");
1488
DBUG_RETURN(ERROR_STOP);
1493
const char *error_msg;
1496
len= cli_safe_read(mysql);
1497
if (len == packet_error)
1499
error("Got error reading packet from server: %s", mysql_error(mysql));
1500
DBUG_RETURN(ERROR_STOP);
1502
if (len < 8 && net->read_pos[0] == 254)
1503
break; // end of data
1504
DBUG_PRINT("info",( "len: %lu net->read_pos[5]: %d\n",
1505
len, net->read_pos[5]));
1506
if (!(ev= Log_event::read_log_event((const char*) net->read_pos + 1 ,
1507
len - 1, &error_msg,
1508
glob_description_event)))
1510
error("Could not construct log event object: %s", error_msg);
1511
DBUG_RETURN(ERROR_STOP);
1514
If reading from a remote host, ensure the temp_buf for the
1515
Log_event class is pointing to the incoming stream.
1518
ev->register_temp_buf((char*) net->read_pos + 1);
1520
Log_event_type type= ev->get_type_code();
1521
if (glob_description_event->binlog_version >= 3 ||
1522
(type != LOAD_EVENT && type != CREATE_FILE_EVENT))
1525
If this is a Rotate event, maybe it's the end of the requested binlog;
1526
in this case we are done (stop transfer).
1527
This is suitable for binlogs, not relay logs (but for now we don't read
1528
relay logs remotely because the server is not able to do that). If one
1529
day we read relay logs remotely, then we will have a problem with the
1530
detection below: relay logs contain Rotate events which are about the
1531
binlogs, so which would trigger the end-detection below.
1533
if (type == ROTATE_EVENT)
1535
Rotate_log_event *rev= (Rotate_log_event *)ev;
1537
If this is a fake Rotate event, and not about our log, we can stop
1538
transfer. If this a real Rotate event (so it's not about our log,
1539
it's in our log describing the next log), we print it (because it's
1540
part of our log) and then we will stop when we receive the fake one
1545
if (!to_last_remote_log)
1547
if ((rev->ident_len != logname_len) ||
1548
memcmp(rev->new_log_ident, logname, logname_len))
1550
DBUG_RETURN(OK_CONTINUE);
1553
Otherwise, this is a fake Rotate for our log, at the very
1554
beginning for sure. Skip it, because it was not in the original
1555
log. If we are running with to_last_remote_log, we print it,
1556
because it serves as a useful marker between binlogs then.
1560
len= 1; // fake Rotate, so don't increment old_off
1563
else if (type == FORMAT_DESCRIPTION_EVENT)
1566
This could be an fake Format_description_log_event that server
1567
(5.0+) automatically sends to a slave on connect, before sending
1568
a first event at the requested position. If this is the case,
1569
don't increment old_off. Real Format_description_log_event always
1570
starts from BIN_LOG_HEADER_SIZE position.
1572
if (old_off != BIN_LOG_HEADER_SIZE)
1573
len= 1; // fake event, don't increment old_off
1575
Exit_status retval= process_event(print_event_info, ev, old_off, logname);
1576
if (retval != OK_CONTINUE)
1577
DBUG_RETURN(retval);
1581
Load_log_event *le= (Load_log_event*)ev;
1582
const char *old_fname= le->fname;
1583
uint old_len= le->fname_len;
1587
if ((file= load_processor.prepare_new_file_for_old_format(le,fname)) < 0)
1588
DBUG_RETURN(ERROR_STOP);
1590
retval= process_event(print_event_info, ev, old_off, logname);
1591
if (retval != OK_CONTINUE)
1593
my_close(file,MYF(MY_WME));
1594
DBUG_RETURN(retval);
1596
retval= load_processor.load_old_format_file(net,old_fname,old_len,file);
1597
my_close(file,MYF(MY_WME));
1598
if (retval != OK_CONTINUE)
1599
DBUG_RETURN(retval);
1602
Let's adjust offset for remote log as for local log to produce
1603
similar text and to have --stop-position to work identically.
1608
DBUG_RETURN(OK_CONTINUE);
1613
Reads the @c Format_description_log_event from the beginning of a
1616
The @c Format_description_log_event is only read if it is outside
1617
the range specified with @c --start-position; otherwise, it will be
1618
seen later. If this is an old binlog, a fake @c
1619
Format_description_event is created. This also prints a @c
1620
Format_description_log_event to the output, unless we reach the
1621
--start-position range. In this case, it is assumed that a @c
1622
Format_description_log_event will be found when reading events the
1625
@param file The file to which a @c Format_description_log_event will
1628
@param[in,out] print_event_info Parameters and context state
1629
determining how to print.
1631
@param[in] logname Name of input binlog.
1633
@retval ERROR_STOP An error occurred - the program should terminate.
1634
@retval OK_CONTINUE No error, the program should continue.
1635
@retval OK_STOP No error, but the end of the specified range of
1636
events to process has been reached and the program should terminate.
1638
static Exit_status check_header(IO_CACHE* file,
1639
PRINT_EVENT_INFO *print_event_info,
1640
const char* logname)
1642
uchar header[BIN_LOG_HEADER_SIZE];
1643
uchar buf[PROBE_HEADER_LEN];
1644
my_off_t tmp_pos, pos;
1646
delete glob_description_event;
1647
if (!(glob_description_event= new Format_description_log_event(3)))
1649
error("Failed creating Format_description_log_event; out of memory?");
1653
pos= my_b_tell(file);
1654
my_b_seek(file, (my_off_t)0);
1655
if (my_b_read(file, header, sizeof(header)))
1657
error("Failed reading header; probably an empty file.");
1660
if (memcmp(header, BINLOG_MAGIC, sizeof(header)))
1662
error("File is not a binary log file.");
1667
Imagine we are running with --start-position=1000. We still need
1668
to know the binlog format's. So we still need to find, if there is
1669
one, the Format_desc event, or to know if this is a 3.23
1670
binlog. So we need to first read the first events of the log,
1671
those around offset 4. Even if we are reading a 3.23 binlog from
1672
the start (no --start-position): we need to know the header length
1673
(which is 13 in 3.23, 19 in 4.x) to be able to successfully print
1674
the first event (Start_log_event_v3). So even in this case, we
1675
need to "probe" the first bytes of the log *before* we do a real
1676
read_log_event(). Because read_log_event() needs to know the
1677
header's length to work fine.
1681
tmp_pos= my_b_tell(file); /* should be 4 the first time */
1682
if (my_b_read(file, buf, sizeof(buf)))
1686
error("Could not read entry at offset %llu: "
1687
"Error in log format or read error.", (ulonglong)tmp_pos);
1691
Otherwise this is just EOF : this log currently contains 0-2
1692
events. Maybe it's going to be filled in the next
1693
milliseconds; then we are going to have a problem if this a
1694
3.23 log (imagine we are locally reading a 3.23 binlog which
1695
is being written presently): we won't know it in
1696
read_log_event() and will fail(). Similar problems could
1697
happen with hot relay logs if --start-position is used (but a
1698
--start-position which is posterior to the current size of the log).
1699
These are rare problems anyway (reading a hot log + when we
1700
read the first events there are not all there yet + when we
1701
read a bit later there are more events + using a strange
1708
DBUG_PRINT("info",("buf[EVENT_TYPE_OFFSET=%d]=%d",
1709
EVENT_TYPE_OFFSET, buf[EVENT_TYPE_OFFSET]));
1710
/* always test for a Start_v3, even if no --start-position */
1711
if (buf[EVENT_TYPE_OFFSET] == START_EVENT_V3)
1713
/* This is 3.23 or 4.x */
1714
if (uint4korr(buf + EVENT_LEN_OFFSET) <
1715
(LOG_EVENT_MINIMAL_HEADER_LEN + START_V3_HEADER_LEN))
1717
/* This is 3.23 (format 1) */
1718
delete glob_description_event;
1719
if (!(glob_description_event= new Format_description_log_event(1)))
1721
error("Failed creating Format_description_log_event; "
1728
else if (tmp_pos >= start_position)
1730
else if (buf[EVENT_TYPE_OFFSET] == FORMAT_DESCRIPTION_EVENT)
1733
Format_description_log_event *new_description_event;
1734
my_b_seek(file, tmp_pos); /* seek back to event's start */
1735
if (!(new_description_event= (Format_description_log_event*)
1736
Log_event::read_log_event(file, glob_description_event)))
1737
/* EOF can't be hit here normally, so it's a real error */
1739
error("Could not read a Format_description_log_event event at "
1740
"offset %llu; this could be a log format error or read error.",
1741
(ulonglong)tmp_pos);
1744
if (opt_base64_output_mode == BASE64_OUTPUT_AUTO
1745
|| opt_base64_output_mode == BASE64_OUTPUT_ALWAYS)
1748
process_event will delete *description_event and set it to
1749
the new one, so we should not do it ourselves in this
1752
Exit_status retval= process_event(print_event_info,
1753
new_description_event, tmp_pos,
1755
if (retval != OK_CONTINUE)
1760
delete glob_description_event;
1761
glob_description_event= new_description_event;
1763
DBUG_PRINT("info",("Setting description_event"));
1765
else if (buf[EVENT_TYPE_OFFSET] == ROTATE_EVENT)
1768
my_b_seek(file, tmp_pos); /* seek back to event's start */
1769
if (!(ev= Log_event::read_log_event(file, glob_description_event)))
1771
/* EOF can't be hit here normally, so it's a real error */
1772
error("Could not read a Rotate_log_event event at offset %llu;"
1773
" this could be a log format error or read error.",
1774
(ulonglong)tmp_pos);
1783
my_b_seek(file, pos);
1789
Reads a local binlog and prints the events it sees.
1791
@param[in] logname Name of input binlog.
1793
@param[in,out] print_event_info Parameters and context state
1794
determining how to print.
1796
@retval ERROR_STOP An error occurred - the program should terminate.
1797
@retval OK_CONTINUE No error, the program should continue.
1798
@retval OK_STOP No error, but the end of the specified range of
1799
events to process has been reached and the program should terminate.
1801
static Exit_status dump_local_log_entries(PRINT_EVENT_INFO *print_event_info,
1802
const char* logname)
1805
IO_CACHE cache,*file= &cache;
1806
uchar tmp_buff[BIN_LOG_HEADER_SIZE];
1807
Exit_status retval= OK_CONTINUE;
1809
if (logname && strcmp(logname, "-") != 0)
1811
/* read from normal file */
1812
if ((fd = my_open(logname, O_RDONLY | O_BINARY, MYF(MY_WME))) < 0)
1814
if (init_io_cache(file, fd, 0, READ_CACHE, start_position_mot, 0,
1815
MYF(MY_WME | MY_NABP)))
1817
my_close(fd, MYF(MY_WME));
1820
if ((retval= check_header(file, print_event_info, logname)) != OK_CONTINUE)
1825
/* read from stdin */
1827
Windows opens stdin in text mode by default. Certain characters
1828
such as CTRL-Z are interpeted as events and the read() method
1829
will stop. CTRL-Z is the EOF marker in Windows. to get past this
1830
you have to open stdin in binary mode. Setmode() is used to set
1831
stdin in binary mode. Errors on setting this mode result in
1832
halting the function and printing an error message to stderr.
1834
#if defined (__WIN__) || (_WIN64)
1835
if (_setmode(fileno(stdin), O_BINARY) == -1)
1837
error("Could not set binary mode on stdin.");
1841
if (init_io_cache(file, fileno(stdin), 0, READ_CACHE, (my_off_t) 0,
1842
0, MYF(MY_WME | MY_NABP | MY_DONT_CHECK_FILESIZE)))
1844
error("Failed to init IO cache.");
1847
if ((retval= check_header(file, print_event_info, logname)) != OK_CONTINUE)
1851
/* skip 'start_position' characters from stdin */
1852
uchar buff[IO_SIZE];
1853
my_off_t length,tmp;
1854
for (length= start_position_mot ; length > 0 ; length-=tmp)
1856
tmp=min(length,sizeof(buff));
1857
if (my_b_read(file, buff, (uint) tmp))
1859
error("Failed reading from file.");
1866
if (!glob_description_event || !glob_description_event->is_valid())
1868
error("Invalid Format_description log event; could be out of memory.");
1872
if (!start_position && my_b_read(file, tmp_buff, BIN_LOG_HEADER_SIZE))
1874
error("Failed reading from file.");
1880
my_off_t old_off = my_b_tell(file);
1882
Log_event* ev = Log_event::read_log_event(file, glob_description_event);
1886
if binlog wasn't closed properly ("in use" flag is set) don't complain
1887
about a corruption, but treat it as EOF and move to the next binlog.
1889
if (glob_description_event->flags & LOG_EVENT_BINLOG_IN_USE_F)
1891
else if (file->error)
1893
error("Could not read entry at offset %s: "
1894
"Error in log format or read error.",
1895
llstr(old_off,llbuff));
1898
// file->error == 0 means EOF, that's OK, we break in this case
1901
if ((retval= process_event(print_event_info, ev, old_off, logname)) !=
1913
my_close(fd, MYF(MY_WME));
1919
int main(int argc, char** argv)
1921
char **defaults_argv;
1922
Exit_status retval= OK_CONTINUE;
1923
ulonglong save_stop_position;
1926
DBUG_PROCESS(argv[0]);
1928
init_time(); // for time functions
1930
parse_args(&argc, (char***)&argv);
1936
free_defaults(defaults_argv);
1940
if (opt_base64_output_mode == BASE64_OUTPUT_UNSPEC)
1941
opt_base64_output_mode= BASE64_OUTPUT_AUTO;
1943
my_set_max_open_files(open_files_limit);
1947
if (!dirname_for_local_load)
1949
if (init_tmpdir(&tmpdir, 0))
1951
dirname_for_local_load= my_strdup(my_tmpdir(&tmpdir), MY_WME);
1954
if (load_processor.init())
1956
if (dirname_for_local_load)
1957
load_processor.init_by_dir_name(dirname_for_local_load);
1959
load_processor.init_by_cur_dir();
1961
fprintf(result_file,
1962
"/*!40019 SET @@session.max_insert_delayed_threads=0*/;\n");
1964
if (disable_log_bin)
1965
fprintf(result_file,
1966
"/*!32316 SET @OLD_SQL_LOG_BIN=@@SQL_LOG_BIN, SQL_LOG_BIN=0*/;\n");
1969
In mysqlbinlog|mysql, don't want mysql to be disconnected after each
1970
transaction (which would be the case with GLOBAL.COMPLETION_TYPE==2).
1972
fprintf(result_file,
1973
"/*!50003 SET @OLD_COMPLETION_TYPE=@@COMPLETION_TYPE,"
1974
"COMPLETION_TYPE=0*/;\n");
1977
fprintf(result_file,
1978
"\n/*!40101 SET @OLD_CHARACTER_SET_CLIENT=@@CHARACTER_SET_CLIENT */;"
1979
"\n/*!40101 SET @OLD_CHARACTER_SET_RESULTS=@@CHARACTER_SET_RESULTS */;"
1980
"\n/*!40101 SET @OLD_COLLATION_CONNECTION=@@COLLATION_CONNECTION */;"
1981
"\n/*!40101 SET NAMES %s */;\n", charset);
1983
for (save_stop_position= stop_position, stop_position= ~(my_off_t)0 ;
1986
if (argc == 0) // last log, --stop-position applies
1987
stop_position= save_stop_position;
1988
if ((retval= dump_log_entries(*argv++)) != OK_CONTINUE)
1991
// For next log, --start-position does not apply
1992
start_position= BIN_LOG_HEADER_SIZE;
1996
Issue a ROLLBACK in case the last printed binlog was crashed and had half
1999
fprintf(result_file,
2000
"# End of log file\nROLLBACK /* added by mysqlbinlog */;\n"
2001
"/*!50003 SET COMPLETION_TYPE=@OLD_COMPLETION_TYPE*/;\n");
2002
if (disable_log_bin)
2003
fprintf(result_file, "/*!32316 SET SQL_LOG_BIN=@OLD_SQL_LOG_BIN*/;\n");
2006
fprintf(result_file,
2007
"/*!40101 SET CHARACTER_SET_CLIENT=@OLD_CHARACTER_SET_CLIENT */;\n"
2008
"/*!40101 SET CHARACTER_SET_RESULTS=@OLD_CHARACTER_SET_RESULTS */;\n"
2009
"/*!40101 SET COLLATION_CONNECTION=@OLD_COLLATION_CONNECTION */;\n");
2012
free_tmpdir(&tmpdir);
2013
if (result_file != stdout)
2014
my_fclose(result_file, MYF(0));
2016
free_defaults(defaults_argv);
2017
my_free_open_file_info();
2018
load_processor.destroy();
2019
/* We cannot free DBUG, it is used in global destructors after exit(). */
2020
my_end(my_end_arg | MY_DONT_FREE_DBUG);
2022
exit(retval == ERROR_STOP ? 1 : 0);
2023
/* Keep compilers happy. */
2024
DBUG_RETURN(retval == ERROR_STOP ? 1 : 0);
2028
We must include this here as it's compiled with different options for
2032
#include "my_decimal.h"
2033
#include "decimal.c"
2034
#include "my_decimal.cc"
2035
#include "log_event.cc"