1
/* Copyright (C) 2001-2004 DRIZZLE 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 Drizzle 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.
31
#define DRIZZLE_CLIENT
36
#include <libdrizzle/my_time.h>
37
#include <drizzled/global.h>
38
#include <mysys/my_sys.h>
39
#include <mystrings/m_string.h>
40
#include <libdrizzle/drizzle.h>
41
#include <libdrizzle/errmsg.h>
42
#include <mysys/my_getopt.h>
43
/* That one is necessary for defines of OPTION_NO_FOREIGN_KEY_CHECKS etc */
44
#include <drizzled/log_event.h>
45
#include <libdrizzle/sql_common.h>
49
enum options_drizzlebinlog
51
OPT_CHARSETS_DIR=256, OPT_BASE64_OUTPUT_MODE,
52
OPT_DEBUG_CHECK, OPT_DEBUG_INFO, OPT_DRIZZLE_PROTOCOL,
53
OPT_SERVER_ID, OPT_SET_CHARSET, OPT_START_DATETIME,
54
OPT_START_POSITION, OPT_STOP_DATETIME, OPT_STOP_POSITION,
58
#define BIN_LOG_HEADER_SIZE 4
59
#define PROBE_HEADER_LEN (EVENT_LEN_OFFSET+4)
62
#define CLIENT_CAPABILITIES (CLIENT_LONG_PASSWORD | CLIENT_LONG_FLAG | CLIENT_LOCAL_FILES)
64
char server_version[SERVER_VERSION_LENGTH];
65
uint32_t server_id = 0;
67
// needed by net_serv.c
68
uint32_t bytes_sent = 0L, bytes_received = 0L;
69
uint32_t drizzled_net_retry_count = 10L;
70
uint32_t open_files_limit;
72
static uint opt_protocol= 0;
73
static FILE *result_file;
75
static const char *load_default_groups[]= { "drizzlebinlog","client",0 };
77
static void error(const char *format, ...) __attribute__((format(printf, 1, 2)));
78
static void warning(const char *format, ...) __attribute__((format(printf, 1, 2)));
80
static bool one_database=0, to_last_remote_log= 0, disable_log_bin= 0;
81
static bool opt_hexdump= 0;
82
const char *base64_output_mode_names[]= {"NEVER", "AUTO", "ALWAYS", NullS};
83
TYPELIB base64_output_mode_typelib=
84
{ array_elements(base64_output_mode_names) - 1, "",
85
base64_output_mode_names, NULL };
86
static enum_base64_output_mode opt_base64_output_mode= BASE64_OUTPUT_UNSPEC;
87
static const char *opt_base64_output_mode_str= NullS;
88
static const char* database= 0;
89
static bool force_opt= 0, short_form= 0, remote_opt= 0;
90
static bool debug_info_flag, debug_check_flag;
91
static bool force_if_open_opt= 1;
92
static uint64_t offset = 0;
93
static const char* host = 0;
95
static uint my_end_arg;
96
static const char* sock= 0;
97
static const char* user = 0;
98
static char* pass = 0;
99
static char *charset= 0;
101
static uint64_t start_position, stop_position;
102
#define start_position_mot ((my_off_t)start_position)
103
#define stop_position_mot ((my_off_t)stop_position)
105
static char *start_datetime_str, *stop_datetime_str;
106
static my_time_t start_datetime= 0, stop_datetime= MY_TIME_T_MAX;
107
static uint64_t rec_count= 0;
108
static short binlog_flags = 0;
109
static DRIZZLE *drizzle= NULL;
110
static const char* dirname_for_local_load= 0;
113
Pointer to the Format_description_log_event of the currently active binlog.
115
This will be changed each time a new Format_description_log_event is
116
found in the binlog. It is finally destroyed at program termination.
118
static Format_description_log_event* glob_description_event= NULL;
121
Exit status for functions in this file.
124
/** No error occurred and execution should continue. */
126
/** An error occurred and execution should stop. */
128
/** No error occurred but execution should stop. */
132
static Exit_status dump_local_log_entries(PRINT_EVENT_INFO *print_event_info,
133
const char* logname);
134
static Exit_status dump_remote_log_entries(PRINT_EVENT_INFO *print_event_info,
135
const char* logname);
136
static Exit_status dump_log_entries(const char* logname);
137
static Exit_status safe_connect();
140
class Load_log_processor
142
char target_dir_name[FN_REFLEN];
143
int target_dir_name_len;
146
When we see first event corresponding to some LOAD DATA statement in
147
binlog, we create temporary file to store data to be loaded.
148
We add name of this file to file_names map using its file_id as index.
149
If we have Create_file event (i.e. we have binary log in pre-5.0.3
150
format) we also store save event object to be able which is needed to
151
emit LOAD DATA statement when we will meet Exec_load_data event.
152
If we have Begin_load_query event we simply store 0 in
153
File_name_record::event field.
155
struct File_name_record
158
Create_file_log_event *event;
161
map<unsigned int, File_name_record *> file_names;
164
Looks for a non-existing filename by adding a numerical suffix to
165
the given base name, creates the generated file, and returns the
166
filename by modifying the filename argument.
168
@param[in,out] filename Base filename
170
@param[in,out] file_name_end Pointer to last character of
171
filename. The numerical suffix will be written to this position.
172
Note that there must be a least five bytes of allocated memory
175
@retval -1 Error (can't find new filename).
176
@retval >=0 Found file.
178
File create_unique_file(char *filename, char *file_name_end)
181
/* If we have to try more than 1000 times, something is seriously wrong */
182
for (uint version= 0; version<1000; version++)
184
sprintf(file_name_end,"-%x",version);
185
if ((res= my_create(filename,0,
186
O_CREAT|O_EXCL|O_BINARY|O_WRONLY,MYF(0)))!=-1)
193
Load_log_processor() {}
194
~Load_log_processor() {}
196
void init_by_dir_name(const char *dir)
198
target_dir_name_len= (convert_dirname(target_dir_name, dir, NullS) -
201
void init_by_cur_dir()
203
if (my_getwd(target_dir_name,sizeof(target_dir_name),MYF(MY_WME)))
205
target_dir_name_len= strlen(target_dir_name);
209
// TODO: Is this necessary? Can't we make the map dtor do this for us?
210
map<unsigned int, File_name_record *>::iterator i;
211
for ( i= file_names.begin() ; i != file_names.end() ; i++)
213
File_name_record *record_to_delete = file_names[i->first];
214
if (record_to_delete->fname)
216
free(record_to_delete->fname);
217
delete record_to_delete->event;
219
file_names.erase(i->first);
224
Obtain Create_file event for LOAD DATA statement by its file_id
225
and remove it from this Load_log_processor's list of events.
227
Checks whether we have already seen a Create_file_log_event with
228
the given file_id. If yes, returns a pointer to the event and
229
removes the event from array describing active temporary files.
230
From this moment, the caller is responsible for freeing the memory
231
occupied by the event.
233
@param[in] file_id File id identifying LOAD DATA statement.
235
@return Pointer to Create_file_log_event, or NULL if we have not
236
seen any Create_file_log_event with this file_id.
238
Create_file_log_event *grab_event(uint file_id)
240
File_name_record *ptr;
242
if ((ptr= file_names[file_id]))
244
file_names.erase(file_id);
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 ((ptr= file_names[file_id]))
271
if (ptr->event != NULL)
274
file_names.erase(file_id);
280
Exit_status process(Create_file_log_event *ce);
281
Exit_status process(Begin_load_query_log_event *ce);
282
Exit_status process(Append_block_log_event *ae);
283
File prepare_new_file_for_old_format(Load_log_event *le, char *filename);
284
Exit_status load_old_format_file(NET* net, const char *server_fname,
285
uint server_fname_len, File file);
286
Exit_status process_first_event(const char *bname, uint blen,
288
uint block_len, uint file_id,
289
Create_file_log_event *ce);
294
Creates and opens a new temporary file in the directory specified by previous call to init_by_dir_name() or init_by_cur_dir().
296
@param[in] le The basename of the created file will start with the
297
basename of the file pointed to by this Load_log_event.
299
@param[out] filename Buffer to save the filename in.
301
@return File handle >= 0 on success, -1 on error.
303
File Load_log_processor::prepare_new_file_for_old_format(Load_log_event *le,
310
fn_format(filename, le->fname, target_dir_name, "", MY_REPLACE_DIR);
311
len= strlen(filename);
312
tail= filename + len;
314
if ((file= create_unique_file(filename,tail)) < 0)
316
error("Could not construct local filename %s.",filename);
320
le->set_fname_outside_temp_buf(filename,len+strlen(tail));
327
Reads a file from a server and saves it locally.
329
@param[in,out] net The server to read from.
331
@param[in] server_fname The name of the file that the server should
334
@param[in] server_fname_len The length of server_fname.
336
@param[in,out] file The file to write to.
338
@retval ERROR_STOP An error occurred - the program should terminate.
339
@retval OK_CONTINUE No error, the program should continue.
341
Exit_status Load_log_processor::load_old_format_file(NET* net,
342
const char*server_fname,
343
uint server_fname_len,
346
uchar buf[FN_REFLEN+1];
348
memcpy(buf + 1, server_fname, server_fname_len + 1);
349
if (my_net_write(net, buf, server_fname_len +2) || net_flush(net))
351
error("Failed requesting the remote dump of %s.", server_fname);
357
uint32_t packet_len = my_net_read(net);
360
if (my_net_write(net, (uchar*) "", 0) || net_flush(net))
362
error("Failed sending the ack packet.");
366
we just need to send something, as the server will read but
367
not examine the packet - this is because drizzle_load() sends
368
an OK when it is done
372
else if (packet_len == packet_error)
374
error("Failed reading a packet during the dump of %s.", server_fname);
378
if (packet_len > UINT_MAX)
380
error("Illegal length of packet read from net.");
383
if (my_write(file, (uchar*) net->read_pos,
384
(uint) packet_len, MYF(MY_WME|MY_NABP)))
393
Process the first event in the sequence of events representing a
396
Creates a temporary file to be used in LOAD DATA and writes first
397
block of data to it. Registers its file name (and optional
398
Create_file event) in the array of active temporary files.
400
@param bname Base name for temporary file to be created.
401
@param blen Base name length.
402
@param block First block of data to be loaded.
403
@param block_len First block length.
404
@param file_id Identifies the LOAD DATA statement.
405
@param ce Pointer to Create_file event object if we are processing
408
@retval ERROR_STOP An error occurred - the program should terminate.
409
@retval OK_CONTINUE No error, the program should continue.
411
Exit_status Load_log_processor::process_first_event(const char *bname,
416
Create_file_log_event *ce)
418
uint full_len= target_dir_name_len + blen + 9 + 9 + 1;
419
Exit_status retval= OK_CONTINUE;
422
File_name_record *rec;
425
if (!(fname= (char*) my_malloc(full_len,MYF(MY_WME))))
427
error("Out of memory.");
432
memcpy(fname, target_dir_name, target_dir_name_len);
433
ptr= fname + target_dir_name_len;
434
memcpy(ptr,bname,blen);
436
ptr+= sprintf(ptr, "-%x", file_id);
438
if ((file= create_unique_file(fname,ptr)) < 0)
440
error("Could not construct local filename %s%s.",
441
target_dir_name,bname);
446
rec= (File_name_record *)malloc(sizeof(File_name_record));
450
file_names[file_id]= rec;
453
ce->set_fname_outside_temp_buf(fname, strlen(fname));
455
if (my_write(file, (uchar*)block, block_len, MYF(MY_WME|MY_NABP)))
457
error("Failed writing to file.");
460
if (my_close(file, MYF(MY_WME)))
462
error("Failed closing file.");
470
Process the given Create_file_log_event.
472
@see Load_log_processor::process_first_event(const char*,uint,const char*,uint,uint,Create_file_log_event*)
474
@param ce Create_file_log_event to process.
476
@retval ERROR_STOP An error occurred - the program should terminate.
477
@retval OK_CONTINUE No error, the program should continue.
479
Exit_status Load_log_processor::process(Create_file_log_event *ce)
481
const char *bname= ce->fname + dirname_length(ce->fname);
482
uint blen= ce->fname_len - (bname-ce->fname);
484
return process_first_event(bname, blen, ce->block, ce->block_len,
490
Process the given Begin_load_query_log_event.
492
@see Load_log_processor::process_first_event(const char*,uint,const char*,uint,uint,Create_file_log_event*)
494
@param ce Begin_load_query_log_event to process.
496
@retval ERROR_STOP An error occurred - the program should terminate.
497
@retval OK_CONTINUE No error, the program should continue.
499
Exit_status Load_log_processor::process(Begin_load_query_log_event *blqe)
501
return process_first_event("SQL_LOAD_MB", 11, blqe->block, blqe->block_len,
507
Process the given Append_block_log_event.
509
Appends the chunk of the file contents specified by the event to the
510
file created by a previous Begin_load_query_log_event or
511
Create_file_log_event.
513
If the file_id for the event does not correspond to any file
514
previously registered through a Begin_load_query_log_event or
515
Create_file_log_event, this member function will print a warning and
516
return OK_CONTINUE. It is safe to return OK_CONTINUE, because no
517
query will be written for this event. We should not print an error
518
and fail, since the missing file_id could be because a (valid)
519
--start-position has been specified after the Begin/Create event but
520
before this Append event.
522
@param ae Append_block_log_event to process.
524
@retval ERROR_STOP An error occurred - the program should terminate.
526
@retval OK_CONTINUE No error, the program should continue.
528
Exit_status Load_log_processor::process(Append_block_log_event *ae)
532
const char* fname= 0;
533
File_name_record *ptr= file_names[ae->file_id];
542
Exit_status retval= OK_CONTINUE;
543
if (((file= my_open(fname,
544
O_APPEND|O_BINARY|O_WRONLY,MYF(MY_WME))) < 0))
546
error("Failed opening file %s", fname);
549
if (my_write(file,(uchar*)ae->block,ae->block_len,MYF(MY_WME|MY_NABP)))
551
error("Failed writing to file %s", fname);
554
if (my_close(file,MYF(MY_WME)))
556
error("Failed closing file %s", fname);
563
There is no Create_file event (a bad binlog or a big
564
--start-position). Assuming it's a big --start-position, we just do
565
nothing and print a warning.
567
warning("Ignoring Append_block as there is no "
568
"Create_file event for file_id: %u", ae->file_id);
573
static Load_log_processor load_processor;
577
Replace windows-style backslashes by forward slashes so it can be
578
consumed by the drizzle client, which requires Unix path.
580
@todo This is only useful under windows, so may be ifdef'ed out on
583
@todo If a Create_file_log_event contains a filename with a
584
backslash (valid under unix), then we have problems under windows.
587
@param[in,out] fname Filename to modify. The filename is modified
590
static void convert_path_to_forward_slashes(char *fname)
602
Indicates whether the given database should be filtered out,
603
according to the --database=X option.
605
@param log_dbname Name of database.
607
@return nonzero if the database with the given name should be
608
filtered out, 0 otherwise.
610
static bool shall_skip_database(const char *log_dbname)
612
return one_database &&
613
(log_dbname != NULL) &&
614
strcmp(log_dbname, database);
619
Prints the given event in base64 format.
621
The header is printed to the head cache and the body is printed to
622
the body cache of the print_event_info structure. This allows all
623
base64 events corresponding to the same statement to be joined into
624
one BINLOG statement.
626
@param[in] ev Log_event to print.
627
@param[in,out] result_file FILE to which the output will be written.
628
@param[in,out] print_event_info Parameters and context state
629
determining how to print.
631
@retval ERROR_STOP An error occurred - the program should terminate.
632
@retval OK_CONTINUE No error, the program should continue.
635
write_event_header_and_base64(Log_event *ev, FILE *result_file,
636
PRINT_EVENT_INFO *print_event_info)
638
IO_CACHE *head= &print_event_info->head_cache;
639
IO_CACHE *body= &print_event_info->body_cache;
642
/* Write header and base64 output to cache */
643
ev->print_header(head, print_event_info, false);
644
ev->print_base64(body, print_event_info, false);
646
/* Read data from cache and write to result file */
647
if (copy_event_cache_to_file_and_reinit(head, result_file) ||
648
copy_event_cache_to_file_and_reinit(body, result_file))
650
error("Error writing event to file.");
658
Print the given event, and either delete it or delegate the deletion
661
The deletion may be delegated in two cases: (1) the event is a
662
Format_description_log_event, and is saved in
663
glob_description_event; (2) the event is a Create_file_log_event,
664
and is saved in load_processor.
666
@param[in,out] print_event_info Parameters and context state
667
determining how to print.
668
@param[in] ev Log_event to process.
669
@param[in] pos Offset from beginning of binlog file.
670
@param[in] logname Name of input binlog.
672
@retval ERROR_STOP An error occurred - the program should terminate.
673
@retval OK_CONTINUE No error, the program should continue.
674
@retval OK_STOP No error, but the end of the specified range of
675
events to process has been reached and the program should terminate.
677
Exit_status process_event(PRINT_EVENT_INFO *print_event_info, Log_event *ev,
678
my_off_t pos, const char *logname)
681
Log_event_type ev_type= ev->get_type_code();
683
print_event_info->short_form= short_form;
684
Exit_status retval= OK_CONTINUE;
687
Format events are not concerned by --offset and such, we always need to
688
read them to be able to process the wanted events.
690
if (((rec_count >= offset) && ((my_time_t)(ev->when) >= start_datetime)) || (ev_type == FORMAT_DESCRIPTION_EVENT))
692
if (ev_type != FORMAT_DESCRIPTION_EVENT)
695
We have found an event after start_datetime, from now on print
696
everything (in case the binlog has timestamps increasing and
697
decreasing, we do this to avoid cutting the middle).
700
offset= 0; // print everything and protect against cycling rec_count
702
if (server_id && (server_id != ev->server_id))
703
/* skip just this event, continue processing the log. */
705
if (((my_time_t)(ev->when) >= stop_datetime)
706
|| (pos >= stop_position_mot))
708
/* end the program */
713
fprintf(result_file, "# at %s\n",llstr(pos,ll_buff));
716
print_event_info->hexdump_from= 0; /* Disabled */
718
print_event_info->hexdump_from= pos;
720
print_event_info->base64_output_mode= opt_base64_output_mode;
724
if (shall_skip_database(((Query_log_event*)ev)->db))
726
if (opt_base64_output_mode == BASE64_OUTPUT_ALWAYS)
728
if ((retval= write_event_header_and_base64(ev, result_file,
729
print_event_info)) !=
734
ev->print(result_file, print_event_info);
737
case CREATE_FILE_EVENT:
739
Create_file_log_event* ce= (Create_file_log_event*)ev;
741
We test if this event has to be ignored. If yes, we don't save
742
this event; this will have the good side-effect of ignoring all
743
related Append_block and Exec_load.
744
Note that Load event from 3.23 is not tested.
746
if (shall_skip_database(ce->db))
747
goto end; // Next event
749
We print the event, but with a leading '#': this is just to inform
750
the user of the original command; the command we want to execute
751
will be a derivation of this original command (we will change the
752
filename and use LOCAL), prepared in the 'case EXEC_LOAD_EVENT'
755
if (opt_base64_output_mode == BASE64_OUTPUT_ALWAYS)
757
if ((retval= write_event_header_and_base64(ce, result_file,
758
print_event_info)) !=
763
ce->print(result_file, print_event_info, true);
765
// If this binlog is not 3.23 ; why this test??
766
if (glob_description_event->binlog_version >= 3)
769
transfer the responsibility for destroying the event to
773
if ((retval= load_processor.process(ce)) != OK_CONTINUE)
779
case APPEND_BLOCK_EVENT:
781
Append_block_log_events can safely print themselves even if
782
the subsequent call load_processor.process fails, because the
783
output of Append_block_log_event::print is only a comment.
785
ev->print(result_file, print_event_info);
786
if ((retval= load_processor.process((Append_block_log_event*) ev)) !=
791
case EXEC_LOAD_EVENT:
793
ev->print(result_file, print_event_info);
794
Execute_load_log_event *exv= (Execute_load_log_event*)ev;
795
Create_file_log_event *ce= load_processor.grab_event(exv->file_id);
797
if ce is 0, it probably means that we have not seen the Create_file
798
event (a bad binlog, or most probably --start-position is after the
799
Create_file event). Print a warning comment.
804
We must not convert earlier, since the file is used by
805
my_open() in Load_log_processor::append().
807
convert_path_to_forward_slashes((char*) ce->fname);
808
ce->print(result_file, print_event_info, true);
809
my_free((char*)ce->fname,MYF(MY_WME));
813
warning("Ignoring Execute_load_log_event as there is no "
814
"Create_file event for file_id: %u", exv->file_id);
817
case FORMAT_DESCRIPTION_EVENT:
818
delete glob_description_event;
819
glob_description_event= (Format_description_log_event*) ev;
820
print_event_info->common_header_len=
821
glob_description_event->common_header_len;
822
ev->print(result_file, print_event_info);
823
ev->temp_buf= 0; // as the event ref is zeroed
825
We don't want this event to be deleted now, so let's hide it (I
826
(Guilhem) should later see if this triggers a non-serious Valgrind
827
error). Not serious error, because we will free description_event
831
if (!force_if_open_opt &&
832
(glob_description_event->flags & LOG_EVENT_BINLOG_IN_USE_F))
834
error("Attempting to dump binlog '%s', which was not closed properly. "
835
"Most probably, drizzled is still writing it, or it crashed. "
836
"Rerun with --force-if-open to ignore this problem.", logname);
840
case BEGIN_LOAD_QUERY_EVENT:
841
ev->print(result_file, print_event_info);
842
if ((retval= load_processor.process((Begin_load_query_log_event*) ev)) !=
846
case EXECUTE_LOAD_QUERY_EVENT:
848
Execute_load_query_log_event *exlq= (Execute_load_query_log_event*)ev;
849
char *fname= load_processor.grab_fname(exlq->file_id);
851
if (!shall_skip_database(exlq->db))
855
convert_path_to_forward_slashes(fname);
856
exlq->print(result_file, print_event_info, fname);
859
warning("Ignoring Execute_load_query since there is no "
860
"Begin_load_query event for file_id: %u", exlq->file_id);
864
my_free(fname, MYF(MY_WME));
867
case TABLE_MAP_EVENT:
868
case WRITE_ROWS_EVENT:
869
case DELETE_ROWS_EVENT:
870
case UPDATE_ROWS_EVENT:
871
case PRE_GA_WRITE_ROWS_EVENT:
872
case PRE_GA_DELETE_ROWS_EVENT:
873
case PRE_GA_UPDATE_ROWS_EVENT:
875
These events must be printed in base64 format, if printed.
876
base64 format requires a FD event to be safe, so if no FD
877
event has been printed, we give an error. Except if user
878
passed --short-form, because --short-form disables printing
881
if (!print_event_info->printed_fd_event && !short_form)
883
const char* type_str= ev->get_type_str();
884
if (opt_base64_output_mode == BASE64_OUTPUT_NEVER)
885
error("--base64-output=never specified, but binlog contains a "
886
"%s event which must be printed in base64.",
889
error("malformed binlog: it does not contain any "
890
"Format_description_log_event. I now found a %s event, which "
891
"is not safe to process without a "
892
"Format_description_log_event.",
898
ev->print(result_file, print_event_info);
909
Destroy the log_event object. If reading from a remote host,
910
set the temp_buf to NULL so that memory isn't freed twice.
922
static struct my_option my_long_options[] =
924
{"help", '?', "Display this help and exit.",
925
0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0},
926
{"base64-output", OPT_BASE64_OUTPUT_MODE,
927
"Determine when the output statements should be base64-encoded BINLOG "
928
"statements: 'never' disables it and works only for binlogs without "
929
"row-based events; 'auto' is the default and prints base64 only when "
930
"necessary (i.e., for row-based events and format description events); "
931
"'always' prints base64 whenever possible. 'always' is for debugging "
932
"only and should not be used in a production system. The default is "
933
"'auto'. --base64-output is a short form for --base64-output=always."
934
,(char**) &opt_base64_output_mode_str,
935
(char**) &opt_base64_output_mode_str,
936
0, GET_STR, OPT_ARG, 0, 0, 0, 0, 0, 0},
938
drizzlebinlog needs charsets knowledge, to be able to convert a charset
939
number found in binlog to a charset name (to be able to print things
941
SET @`a`:=_cp850 0x4DFC6C6C6572 COLLATE `cp850_general_ci`;
943
{"character-sets-dir", OPT_CHARSETS_DIR,
944
"Directory where character sets are.", (char**) &charsets_dir,
945
(char**) &charsets_dir, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
946
{"database", 'd', "List entries for just this database (local log only).",
947
(char**) &database, (char**) &database, 0, GET_STR_ALLOC, REQUIRED_ARG,
949
{"debug-check", OPT_DEBUG_CHECK, "Check memory and open file usage at exit .",
950
(char**) &debug_check_flag, (char**) &debug_check_flag, 0,
951
GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0},
952
{"debug-info", OPT_DEBUG_INFO, "Print some debug info at exit.",
953
(char**) &debug_info_flag, (char**) &debug_info_flag,
954
0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0},
955
{"disable-log-bin", 'D', "Disable binary log. This is useful, if you "
956
"enabled --to-last-log and are sending the output to the same DRIZZLE server. "
957
"This way you could avoid an endless loop. You would also like to use it "
958
"when restoring after a crash to avoid duplication of the statements you "
959
"already have. NOTE: you will need a SUPER privilege to use this option.",
960
(char**) &disable_log_bin, (char**) &disable_log_bin, 0, GET_BOOL,
961
NO_ARG, 0, 0, 0, 0, 0, 0},
962
{"force-if-open", 'F', "Force if binlog was not closed properly.",
963
(char**) &force_if_open_opt, (char**) &force_if_open_opt, 0, GET_BOOL, NO_ARG,
965
{"force-read", 'f', "Force reading unknown binlog events.",
966
(char**) &force_opt, (char**) &force_opt, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0,
968
{"hexdump", 'H', "Augment output with hexadecimal and ASCII event dump.",
969
(char**) &opt_hexdump, (char**) &opt_hexdump, 0, GET_BOOL, NO_ARG,
971
{"host", 'h', "Get the binlog from server.", (char**) &host, (char**) &host,
972
0, GET_STR_ALLOC, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
973
{"local-load", 'l', "Prepare local temporary files for LOAD DATA INFILE in the specified directory.",
974
(char**) &dirname_for_local_load, (char**) &dirname_for_local_load, 0,
975
GET_STR_ALLOC, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
976
{"offset", 'o', "Skip the first N entries.", (char**) &offset, (char**) &offset,
977
0, GET_ULL, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
978
{"password", 'p', "Password to connect to remote server.",
979
0, 0, 0, GET_STR, OPT_ARG, 0, 0, 0, 0, 0, 0},
980
{"port", 'P', "Port number to use for connection or 0 for default to, in "
981
"order of preference, my.cnf, $DRIZZLE_TCP_PORT, "
982
"built-in default (" STRINGIFY_ARG(DRIZZLE_PORT) ").",
983
(char**) &port, (char**) &port, 0, GET_INT, REQUIRED_ARG,
985
{"position", 'j', "Deprecated. Use --start-position instead.",
986
(char**) &start_position, (char**) &start_position, 0, GET_ULL,
987
REQUIRED_ARG, BIN_LOG_HEADER_SIZE, BIN_LOG_HEADER_SIZE,
988
/* COM_BINLOG_DUMP accepts only 4 bytes for the position */
989
(uint64_t)(~(uint32_t)0), 0, 0, 0},
990
{"protocol", OPT_DRIZZLE_PROTOCOL,
991
"The protocol of connection (tcp,socket,pipe,memory).",
992
0, 0, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
993
{"read-from-remote-server", 'R', "Read binary logs from a Drizzle server",
994
(char**) &remote_opt, (char**) &remote_opt, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0,
996
{"result-file", 'r', "Direct output to a given file.", 0, 0, 0, GET_STR,
997
REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
998
{"server-id", OPT_SERVER_ID,
999
"Extract only binlog entries created by the server having the given id.",
1000
(char**) &server_id, (char**) &server_id, 0, GET_ULONG,
1001
REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
1002
{"set-charset", OPT_SET_CHARSET,
1003
"Add 'SET NAMES character_set' to the output.", (char**) &charset,
1004
(char**) &charset, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
1005
{"short-form", 's', "Just show regular queries: no extra info and no "
1006
"row-based events. This is for testing only, and should not be used in "
1007
"production systems. If you want to suppress base64-output, consider "
1008
"using --base64-output=never instead.",
1009
(char**) &short_form, (char**) &short_form, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0,
1011
{"socket", 'S', "Socket file to use for connection.",
1012
(char**) &sock, (char**) &sock, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0,
1014
{"start-datetime", OPT_START_DATETIME,
1015
"Start reading the binlog at first event having a datetime equal or "
1016
"posterior to the argument; the argument must be a date and time "
1017
"in the local time zone, in any format accepted by the Drizzle server "
1018
"for DATETIME and TIMESTAMP types, for example: 2004-12-25 11:25:56 "
1019
"(you should probably use quotes for your shell to set it properly).",
1020
(char**) &start_datetime_str, (char**) &start_datetime_str,
1021
0, GET_STR_ALLOC, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
1022
{"start-position", OPT_START_POSITION,
1023
"Start reading the binlog at position N. Applies to the first binlog "
1024
"passed on the command line.",
1025
(char**) &start_position, (char**) &start_position, 0, GET_ULL,
1026
REQUIRED_ARG, BIN_LOG_HEADER_SIZE, BIN_LOG_HEADER_SIZE,
1027
/* COM_BINLOG_DUMP accepts only 4 bytes for the position */
1028
(uint64_t)(~(uint32_t)0), 0, 0, 0},
1029
{"stop-datetime", OPT_STOP_DATETIME,
1030
"Stop reading the binlog at first event having a datetime equal or "
1031
"posterior to the argument; the argument must be a date and time "
1032
"in the local time zone, in any format accepted by the Drizzle server "
1033
"for DATETIME and TIMESTAMP types, for example: 2004-12-25 11:25:56 "
1034
"(you should probably use quotes for your shell to set it properly).",
1035
(char**) &stop_datetime_str, (char**) &stop_datetime_str,
1036
0, GET_STR_ALLOC, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
1037
{"stop-position", OPT_STOP_POSITION,
1038
"Stop reading the binlog at position N. Applies to the last binlog "
1039
"passed on the command line.",
1040
(char**) &stop_position, (char**) &stop_position, 0, GET_ULL,
1041
REQUIRED_ARG, (uint64_t)(~(my_off_t)0), BIN_LOG_HEADER_SIZE,
1042
(uint64_t)(~(my_off_t)0), 0, 0, 0},
1043
{"to-last-log", 't', "Requires -R. Will not stop at the end of the \
1044
requested binlog but rather continue printing until the end of the last \
1045
binlog of the DRIZZLE server. If you send the output to the same DRIZZLE server, \
1046
that may lead to an endless loop.",
1047
(char**) &to_last_remote_log, (char**) &to_last_remote_log, 0, GET_BOOL,
1048
NO_ARG, 0, 0, 0, 0, 0, 0},
1049
{"user", 'u', "Connect to the remote server as username.",
1050
(char**) &user, (char**) &user, 0, GET_STR_ALLOC, REQUIRED_ARG, 0, 0, 0, 0,
1052
{"version", 'V', "Print version and exit.", 0, 0, 0, GET_NO_ARG, NO_ARG, 0,
1054
{"open_files_limit", OPT_OPEN_FILES_LIMIT,
1055
"Used to reserve file descriptors for usage by this program",
1056
(char**) &open_files_limit, (char**) &open_files_limit, 0, GET_ULONG,
1057
REQUIRED_ARG, MY_NFILE, 8, OS_FILE_LIMIT, 0, 1, 0},
1058
{0, 0, 0, 0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0}
1063
Auxiliary function used by error() and warning().
1065
Prints the given text (normally "WARNING: " or "ERROR: "), followed
1066
by the given vprintf-style string, followed by a newline.
1068
@param format Printf-style format string.
1069
@param args List of arguments for the format string.
1070
@param msg Text to print before the string.
1072
static void error_or_warning(const char *format, va_list args, const char *msg)
1074
fprintf(stderr, "%s: ", msg);
1075
vfprintf(stderr, format, args);
1076
fprintf(stderr, "\n");
1080
Prints a message to stderr, prefixed with the text "ERROR: " and
1081
suffixed with a newline.
1083
@param format Printf-style format string, followed by printf
1086
static void error(const char *format,...)
1089
va_start(args, format);
1090
error_or_warning(format, args, "ERROR");
1096
This function is used in log_event.cc to report errors.
1098
@param format Printf-style format string, followed by printf
1101
static void sql_print_error(const char *format, ...) __attribute__((format(printf, 1, 2)));
1102
static void sql_print_error(const char *format,...)
1105
va_start(args, format);
1106
error_or_warning(format, args, "ERROR");
1111
Prints a message to stderr, prefixed with the text "WARNING: " and
1112
suffixed with a newline.
1114
@param format Printf-style format string, followed by printf
1117
static void warning(const char *format,...)
1120
va_start(args, format);
1121
error_or_warning(format, args, "WARNING");
1126
Frees memory for global variables in this file.
1128
static void cleanup()
1130
my_free(pass,MYF(MY_ALLOW_ZERO_PTR));
1131
my_free((char*) database, MYF(MY_ALLOW_ZERO_PTR));
1132
my_free((char*) host, MYF(MY_ALLOW_ZERO_PTR));
1133
my_free((char*) user, MYF(MY_ALLOW_ZERO_PTR));
1134
my_free((char*) dirname_for_local_load, MYF(MY_ALLOW_ZERO_PTR));
1136
delete glob_description_event;
1138
drizzle_close(drizzle);
1141
static void print_version()
1143
printf("%s Ver 3.3 for %s at %s\n", my_progname, SYSTEM_TYPE, MACHINE_TYPE);
1149
puts("By Monty and Sasha, for your professional use\n\
1150
This software comes with NO WARRANTY: This is free software,\n\
1151
and you are welcome to modify and redistribute it under the GPL license\n");
1154
Dumps a DRIZZLE binary log in a format usable for viewing or for piping to\n\
1155
the Drizzle command line client\n\n");
1156
printf("Usage: %s [options] log-files\n", my_progname);
1157
my_print_help(my_long_options);
1158
my_print_variables(my_long_options);
1162
static my_time_t convert_str_to_timestamp(const char* str)
1165
DRIZZLE_TIME l_time;
1166
long dummy_my_timezone;
1167
bool dummy_in_dst_time_gap;
1168
/* We require a total specification (date AND time) */
1169
if (str_to_datetime(str, strlen(str), &l_time, 0, &was_cut) !=
1170
DRIZZLE_TIMESTAMP_DATETIME || was_cut)
1172
error("Incorrect date and time argument: %s", str);
1176
Note that Feb 30th, Apr 31st cause no error messages and are mapped to
1177
the next existing day, like in drizzled. Maybe this could be changed when
1178
drizzled is changed too (with its "strict" mode?).
1181
my_system_gmt_sec(&l_time, &dummy_my_timezone, &dummy_in_dst_time_gap);
1185
get_one_option(int optid, const struct my_option *opt __attribute__((unused)),
1188
bool tty_password=0;
1196
my_free(pass,MYF(MY_ALLOW_ZERO_PTR));
1197
char *start=argument;
1198
pass= my_strdup(argument,MYF(MY_FAE));
1199
while (*argument) *argument++= 'x'; /* Destroy argument */
1201
start[1]=0; /* Cut length of argument */
1207
if (!(result_file = my_fopen(argument, O_WRONLY | O_BINARY, MYF(MY_WME))))
1213
case OPT_DRIZZLE_PROTOCOL:
1214
opt_protocol= find_type_or_exit(argument, &sql_protocol_typelib,
1217
case OPT_START_DATETIME:
1218
start_datetime= convert_str_to_timestamp(start_datetime_str);
1220
case OPT_STOP_DATETIME:
1221
stop_datetime= convert_str_to_timestamp(stop_datetime_str);
1223
case OPT_BASE64_OUTPUT_MODE:
1224
if (argument == NULL)
1225
opt_base64_output_mode= BASE64_OUTPUT_ALWAYS;
1228
opt_base64_output_mode= (enum_base64_output_mode)
1229
(find_type_or_exit(argument, &base64_output_mode_typelib, opt->name)-1);
1240
pass= get_tty_password(NullS);
1246
static int parse_args(int *argc, char*** argv)
1250
result_file = stdout;
1251
load_defaults("my",load_default_groups,argc,argv);
1252
if ((ho_error=handle_options(argc, argv, my_long_options, get_one_option)))
1254
if (debug_info_flag)
1255
my_end_arg= MY_CHECK_ERROR | MY_GIVE_INFO;
1256
if (debug_check_flag)
1257
my_end_arg= MY_CHECK_ERROR;
1263
Create and initialize the global drizzle object, and connect to the
1266
@retval ERROR_STOP An error occurred - the program should terminate.
1267
@retval OK_CONTINUE No error, the program should continue.
1269
static Exit_status safe_connect()
1271
drizzle= drizzle_create(NULL);
1275
error("Failed on drizzle_create.");
1280
drizzle_options(drizzle, DRIZZLE_OPT_PROTOCOL, (char*) &opt_protocol);
1281
if (!drizzle_connect(drizzle, host, user, pass, 0, port, sock, 0))
1283
error("Failed on connect: %s", drizzle_error(drizzle));
1286
drizzle->reconnect= 1;
1292
High-level function for dumping a named binlog.
1294
This function calls dump_remote_log_entries() or
1295
dump_local_log_entries() to do the job.
1297
@param[in] logname Name of input binlog.
1299
@retval ERROR_STOP An error occurred - the program should terminate.
1300
@retval OK_CONTINUE No error, the program should continue.
1301
@retval OK_STOP No error, but the end of the specified range of
1302
events to process has been reached and the program should terminate.
1304
static Exit_status dump_log_entries(const char* logname)
1307
PRINT_EVENT_INFO print_event_info;
1309
if (!print_event_info.init_ok())
1312
Set safe delimiter, to dump things
1313
like CREATE PROCEDURE safely
1315
fprintf(result_file, "DELIMITER /*!*/;\n");
1316
stpcpy(print_event_info.delimiter, "/*!*/;");
1318
rc= (remote_opt ? dump_remote_log_entries(&print_event_info, logname) :
1319
dump_local_log_entries(&print_event_info, logname));
1321
/* Set delimiter back to semicolon */
1322
fprintf(result_file, "DELIMITER ;\n");
1323
stpcpy(print_event_info.delimiter, ";");
1329
When reading a remote binlog, this function is used to grab the
1330
Format_description_log_event in the beginning of the stream.
1332
This is not as smart as check_header() (used for local log); it will
1333
not work for a binlog which mixes format. TODO: fix this.
1335
@retval ERROR_STOP An error occurred - the program should terminate.
1336
@retval OK_CONTINUE No error, the program should continue.
1338
static Exit_status check_master_version()
1340
DRIZZLE_RES* res = 0;
1342
const char* version;
1344
if (drizzle_query(drizzle, "SELECT VERSION()") ||
1345
!(res = drizzle_store_result(drizzle)))
1347
error("Could not find server version: "
1348
"Query failed when checking master version: %s", drizzle_error(drizzle));
1351
if (!(row = drizzle_fetch_row(res)))
1353
error("Could not find server version: "
1354
"Master returned no rows for SELECT VERSION().");
1358
if (!(version = row[0]))
1360
error("Could not find server version: "
1361
"Master reported NULL for the version.");
1365
delete glob_description_event;
1368
glob_description_event= new Format_description_log_event(1);
1371
glob_description_event= new Format_description_log_event(3);
1376
The server is soon going to send us its Format_description log
1377
event, unless it is a 5.0 server with 3.23 or 4.0 binlogs.
1378
So we first assume that this is 4.0 (which is enough to read the
1379
Format_desc event if one comes).
1381
glob_description_event= new Format_description_log_event(3);
1384
glob_description_event= NULL;
1385
error("Could not find server version: "
1386
"Master reported unrecognized Drizzle version '%s'.", version);
1389
if (!glob_description_event || !glob_description_event->is_valid())
1391
error("Failed creating Format_description_log_event; out of memory?");
1395
drizzle_free_result(res);
1399
drizzle_free_result(res);
1405
Requests binlog dump from a remote server and prints the events it
1408
@param[in,out] print_event_info Parameters and context state
1409
determining how to print.
1410
@param[in] logname Name of input binlog.
1412
@retval ERROR_STOP An error occurred - the program should terminate.
1413
@retval OK_CONTINUE No error, the program should continue.
1414
@retval OK_STOP No error, but the end of the specified range of
1415
events to process has been reached and the program should terminate.
1417
static Exit_status dump_remote_log_entries(PRINT_EVENT_INFO *print_event_info,
1418
const char* logname)
1425
my_off_t old_off= start_position_mot;
1426
char fname[FN_REFLEN+1];
1427
Exit_status retval= OK_CONTINUE;
1431
Even if we already read one binlog (case of >=2 binlogs on command line),
1432
we cannot re-use the same connection as before, because it is now dead
1433
(COM_BINLOG_DUMP kills the thread when it finishes).
1435
if ((retval= safe_connect()) != OK_CONTINUE)
1439
if ((retval= check_master_version()) != OK_CONTINUE)
1443
COM_BINLOG_DUMP accepts only 4 bytes for the position, so we are forced to
1446
int4store(buf, (uint32_t)start_position);
1447
int2store(buf + BIN_LOG_HEADER_SIZE, binlog_flags);
1449
size_t tlen = strlen(logname);
1450
if (tlen > UINT_MAX)
1452
error("Log name too long.");
1455
logname_len = (uint) tlen;
1456
int4store(buf + 6, 0);
1457
memcpy(buf + 10, logname, logname_len);
1458
if (simple_command(drizzle, COM_BINLOG_DUMP, buf, logname_len + 10, 1))
1460
error("Got fatal error sending the log dump command.");
1466
const char *error_msg;
1469
len= cli_safe_read(drizzle);
1470
if (len == packet_error)
1472
error("Got error reading packet from server: %s", drizzle_error(drizzle));
1475
if (len < 8 && net->read_pos[0] == 254)
1476
break; // end of data
1477
if (!(ev= Log_event::read_log_event((const char*) net->read_pos + 1 ,
1478
len - 1, &error_msg,
1479
glob_description_event)))
1481
error("Could not construct log event object: %s", error_msg);
1485
If reading from a remote host, ensure the temp_buf for the
1486
Log_event class is pointing to the incoming stream.
1489
ev->register_temp_buf((char*) net->read_pos + 1);
1491
Log_event_type type= ev->get_type_code();
1492
if (glob_description_event->binlog_version >= 3 ||
1493
(type != LOAD_EVENT && type != CREATE_FILE_EVENT))
1496
If this is a Rotate event, maybe it's the end of the requested binlog;
1497
in this case we are done (stop transfer).
1498
This is suitable for binlogs, not relay logs (but for now we don't read
1499
relay logs remotely because the server is not able to do that). If one
1500
day we read relay logs remotely, then we will have a problem with the
1501
detection below: relay logs contain Rotate events which are about the
1502
binlogs, so which would trigger the end-detection below.
1504
if (type == ROTATE_EVENT)
1506
Rotate_log_event *rev= (Rotate_log_event *)ev;
1508
If this is a fake Rotate event, and not about our log, we can stop
1509
transfer. If this a real Rotate event (so it's not about our log,
1510
it's in our log describing the next log), we print it (because it's
1511
part of our log) and then we will stop when we receive the fake one
1516
if (!to_last_remote_log)
1518
if ((rev->ident_len != logname_len) ||
1519
memcmp(rev->new_log_ident, logname, logname_len))
1521
return(OK_CONTINUE);
1524
Otherwise, this is a fake Rotate for our log, at the very
1525
beginning for sure. Skip it, because it was not in the original
1526
log. If we are running with to_last_remote_log, we print it,
1527
because it serves as a useful marker between binlogs then.
1531
len= 1; // fake Rotate, so don't increment old_off
1534
else if (type == FORMAT_DESCRIPTION_EVENT)
1537
This could be an fake Format_description_log_event that server
1538
(5.0+) automatically sends to a slave on connect, before sending
1539
a first event at the requested position. If this is the case,
1540
don't increment old_off. Real Format_description_log_event always
1541
starts from BIN_LOG_HEADER_SIZE position.
1543
if (old_off != BIN_LOG_HEADER_SIZE)
1544
len= 1; // fake event, don't increment old_off
1546
Exit_status retval= process_event(print_event_info, ev, old_off, logname);
1547
if (retval != OK_CONTINUE)
1552
Load_log_event *le= (Load_log_event*)ev;
1553
const char *old_fname= le->fname;
1554
uint old_len= le->fname_len;
1558
if ((file= load_processor.prepare_new_file_for_old_format(le,fname)) < 0)
1561
retval= process_event(print_event_info, ev, old_off, logname);
1562
if (retval != OK_CONTINUE)
1564
my_close(file,MYF(MY_WME));
1567
retval= load_processor.load_old_format_file(net,old_fname,old_len,file);
1568
my_close(file,MYF(MY_WME));
1569
if (retval != OK_CONTINUE)
1573
Let's adjust offset for remote log as for local log to produce
1574
similar text and to have --stop-position to work identically.
1579
return(OK_CONTINUE);
1584
Reads the @c Format_description_log_event from the beginning of a
1587
The @c Format_description_log_event is only read if it is outside
1588
the range specified with @c --start-position; otherwise, it will be
1589
seen later. If this is an old binlog, a fake @c
1590
Format_description_event is created. This also prints a @c
1591
Format_description_log_event to the output, unless we reach the
1592
--start-position range. In this case, it is assumed that a @c
1593
Format_description_log_event will be found when reading events the
1596
@param file The file to which a @c Format_description_log_event will
1599
@param[in,out] print_event_info Parameters and context state
1600
determining how to print.
1602
@param[in] logname Name of input binlog.
1604
@retval ERROR_STOP An error occurred - the program should terminate.
1605
@retval OK_CONTINUE No error, the program should continue.
1606
@retval OK_STOP No error, but the end of the specified range of
1607
events to process has been reached and the program should terminate.
1609
static Exit_status check_header(IO_CACHE* file,
1610
PRINT_EVENT_INFO *print_event_info,
1611
const char* logname)
1613
uchar header[BIN_LOG_HEADER_SIZE];
1614
uchar buf[PROBE_HEADER_LEN];
1615
uint64_t tmp_pos, pos;
1617
delete glob_description_event;
1618
if (!(glob_description_event= new Format_description_log_event(3)))
1620
error("Failed creating Format_description_log_event; out of memory?");
1624
pos= my_b_tell(file);
1625
my_b_seek(file, (my_off_t)0);
1626
if (my_b_read(file, header, sizeof(header)))
1628
error("Failed reading header; probably an empty file.");
1631
if (memcmp(header, BINLOG_MAGIC, sizeof(header)))
1633
error("File is not a binary log file.");
1638
Imagine we are running with --start-position=1000. We still need
1639
to know the binlog format's. So we still need to find, if there is
1640
one, the Format_desc event, or to know if this is a 3.23
1641
binlog. So we need to first read the first events of the log,
1642
those around offset 4. Even if we are reading a 3.23 binlog from
1643
the start (no --start-position): we need to know the header length
1644
(which is 13 in 3.23, 19 in 4.x) to be able to successfully print
1645
the first event (Start_log_event_v3). So even in this case, we
1646
need to "probe" the first bytes of the log *before* we do a real
1647
read_log_event(). Because read_log_event() needs to know the
1648
header's length to work fine.
1652
tmp_pos= my_b_tell(file); /* should be 4 the first time */
1653
if (my_b_read(file, buf, sizeof(buf)))
1657
error("Could not read entry at offset %"PRIu64": "
1658
"Error in log format or read error.", tmp_pos);
1662
Otherwise this is just EOF : this log currently contains 0-2
1663
events. Maybe it's going to be filled in the next
1664
milliseconds; then we are going to have a problem if this a
1665
3.23 log (imagine we are locally reading a 3.23 binlog which
1666
is being written presently): we won't know it in
1667
read_log_event() and will fail(). Similar problems could
1668
happen with hot relay logs if --start-position is used (but a
1669
--start-position which is posterior to the current size of the log).
1670
These are rare problems anyway (reading a hot log + when we
1671
read the first events there are not all there yet + when we
1672
read a bit later there are more events + using a strange
1679
/* always test for a Start_v3, even if no --start-position */
1680
if (buf[EVENT_TYPE_OFFSET] == START_EVENT_V3)
1682
/* This is 3.23 or 4.x */
1683
if (uint4korr(buf + EVENT_LEN_OFFSET) <
1684
(LOG_EVENT_MINIMAL_HEADER_LEN + START_V3_HEADER_LEN))
1686
/* This is 3.23 (format 1) */
1687
delete glob_description_event;
1688
if (!(glob_description_event= new Format_description_log_event(1)))
1690
error("Failed creating Format_description_log_event; "
1697
else if (tmp_pos >= start_position)
1699
else if (buf[EVENT_TYPE_OFFSET] == FORMAT_DESCRIPTION_EVENT)
1702
Format_description_log_event *new_description_event;
1703
my_b_seek(file, tmp_pos); /* seek back to event's start */
1704
if (!(new_description_event= (Format_description_log_event*)
1705
Log_event::read_log_event(file, glob_description_event)))
1706
/* EOF can't be hit here normally, so it's a real error */
1708
error("Could not read a Format_description_log_event event at "
1709
"offset %"PRIu64"; this could be a log format error or read error.",
1713
if (opt_base64_output_mode == BASE64_OUTPUT_AUTO
1714
|| opt_base64_output_mode == BASE64_OUTPUT_ALWAYS)
1717
process_event will delete *description_event and set it to
1718
the new one, so we should not do it ourselves in this
1721
Exit_status retval= process_event(print_event_info,
1722
new_description_event, tmp_pos,
1724
if (retval != OK_CONTINUE)
1729
delete glob_description_event;
1730
glob_description_event= new_description_event;
1733
else if (buf[EVENT_TYPE_OFFSET] == ROTATE_EVENT)
1736
my_b_seek(file, tmp_pos); /* seek back to event's start */
1737
if (!(ev= Log_event::read_log_event(file, glob_description_event)))
1739
/* EOF can't be hit here normally, so it's a real error */
1740
error("Could not read a Rotate_log_event event at offset "
1742
" this could be a log format error or read error.",
1752
my_b_seek(file, pos);
1758
Reads a local binlog and prints the events it sees.
1760
@param[in] logname Name of input binlog.
1762
@param[in,out] print_event_info Parameters and context state
1763
determining how to print.
1765
@retval ERROR_STOP An error occurred - the program should terminate.
1766
@retval OK_CONTINUE No error, the program should continue.
1767
@retval OK_STOP No error, but the end of the specified range of
1768
events to process has been reached and the program should terminate.
1770
static Exit_status dump_local_log_entries(PRINT_EVENT_INFO *print_event_info,
1771
const char* logname)
1774
IO_CACHE cache,*file= &cache;
1775
uchar tmp_buff[BIN_LOG_HEADER_SIZE];
1776
Exit_status retval= OK_CONTINUE;
1778
if (logname && strcmp(logname, "-") != 0)
1780
/* read from normal file */
1781
if ((fd = my_open(logname, O_RDONLY | O_BINARY, MYF(MY_WME))) < 0)
1783
if (init_io_cache(file, fd, 0, READ_CACHE, start_position_mot, 0,
1784
MYF(MY_WME | MY_NABP)))
1786
my_close(fd, MYF(MY_WME));
1789
if ((retval= check_header(file, print_event_info, logname)) != OK_CONTINUE)
1794
if (init_io_cache(file, fileno(stdin), 0, READ_CACHE, (my_off_t) 0,
1795
0, MYF(MY_WME | MY_NABP | MY_DONT_CHECK_FILESIZE)))
1797
error("Failed to init IO cache.");
1800
if ((retval= check_header(file, print_event_info, logname)) != OK_CONTINUE)
1804
/* skip 'start_position' characters from stdin */
1805
uchar buff[IO_SIZE];
1806
my_off_t length,tmp;
1807
for (length= start_position_mot ; length > 0 ; length-=tmp)
1809
tmp=min(length,sizeof(buff));
1810
if (my_b_read(file, buff, (uint) tmp))
1812
error("Failed reading from file.");
1819
if (!glob_description_event || !glob_description_event->is_valid())
1821
error("Invalid Format_description log event; could be out of memory.");
1825
if (!start_position && my_b_read(file, tmp_buff, BIN_LOG_HEADER_SIZE))
1827
error("Failed reading from file.");
1833
my_off_t old_off = my_b_tell(file);
1835
Log_event* ev = Log_event::read_log_event(file, glob_description_event);
1839
if binlog wasn't closed properly ("in use" flag is set) don't complain
1840
about a corruption, but treat it as EOF and move to the next binlog.
1842
if (glob_description_event->flags & LOG_EVENT_BINLOG_IN_USE_F)
1844
else if (file->error)
1846
error("Could not read entry at offset %s: "
1847
"Error in log format or read error.",
1848
llstr(old_off,llbuff));
1851
// file->error == 0 means EOF, that's OK, we break in this case
1854
if ((retval= process_event(print_event_info, ev, old_off, logname)) !=
1866
my_close(fd, MYF(MY_WME));
1872
int main(int argc, char** argv)
1874
char **defaults_argv;
1875
Exit_status retval= OK_CONTINUE;
1876
uint64_t save_stop_position;
1879
init_time(); // for time functions
1881
parse_args(&argc, (char***)&argv);
1887
free_defaults(defaults_argv);
1891
if (opt_base64_output_mode == BASE64_OUTPUT_UNSPEC)
1892
opt_base64_output_mode= BASE64_OUTPUT_AUTO;
1894
my_set_max_open_files(open_files_limit);
1898
if (!dirname_for_local_load)
1900
if (init_tmpdir(&tmpdir, 0))
1902
dirname_for_local_load= my_strdup(my_tmpdir(&tmpdir), MY_WME);
1905
if (dirname_for_local_load)
1906
load_processor.init_by_dir_name(dirname_for_local_load);
1908
load_processor.init_by_cur_dir();
1910
fprintf(result_file,
1911
"/*!40019 SET @@session.max_insert_delayed_threads=0*/;\n");
1913
if (disable_log_bin)
1914
fprintf(result_file,
1915
"/*!32316 SET @OLD_SQL_LOG_BIN=@@SQL_LOG_BIN, SQL_LOG_BIN=0*/;\n");
1918
In drizzlebinlog|drizzle, don't want Drizzle to be disconnected after each
1919
transaction (which would be the case with GLOBAL.COMPLETION_TYPE==2).
1921
fprintf(result_file,
1922
"/*!50003 SET @OLD_COMPLETION_TYPE=@@COMPLETION_TYPE,"
1923
"COMPLETION_TYPE=0*/;\n");
1926
fprintf(result_file,
1927
"\n/*!40101 SET @OLD_CHARACTER_SET_CLIENT=@@CHARACTER_SET_CLIENT */;"
1928
"\n/*!40101 SET @OLD_CHARACTER_SET_RESULTS=@@CHARACTER_SET_RESULTS */;"
1929
"\n/*!40101 SET @OLD_COLLATION_CONNECTION=@@COLLATION_CONNECTION */;"
1930
"\n/*!40101 SET NAMES %s */;\n", charset);
1932
for (save_stop_position= stop_position, stop_position= ~(my_off_t)0 ;
1935
if (argc == 0) // last log, --stop-position applies
1936
stop_position= save_stop_position;
1937
if ((retval= dump_log_entries(*argv++)) != OK_CONTINUE)
1940
// For next log, --start-position does not apply
1941
start_position= BIN_LOG_HEADER_SIZE;
1945
Issue a ROLLBACK in case the last printed binlog was crashed and had half
1948
fprintf(result_file,
1949
"# End of log file\nROLLBACK /* added by drizzlebinlog */;\n"
1950
"/*!50003 SET COMPLETION_TYPE=@OLD_COMPLETION_TYPE*/;\n");
1951
if (disable_log_bin)
1952
fprintf(result_file, "/*!32316 SET SQL_LOG_BIN=@OLD_SQL_LOG_BIN*/;\n");
1955
fprintf(result_file,
1956
"/*!40101 SET CHARACTER_SET_CLIENT=@OLD_CHARACTER_SET_CLIENT */;\n"
1957
"/*!40101 SET CHARACTER_SET_RESULTS=@OLD_CHARACTER_SET_RESULTS */;\n"
1958
"/*!40101 SET COLLATION_CONNECTION=@OLD_COLLATION_CONNECTION */;\n");
1961
free_tmpdir(&tmpdir);
1962
if (result_file != stdout)
1963
my_fclose(result_file, MYF(0));
1965
free_defaults(defaults_argv);
1966
my_free_open_file_info();
1967
load_processor.destroy();
1970
exit(retval == ERROR_STOP ? 1 : 0);
1974
We must include this here as it's compiled with different options for
1978
#include <drizzled/log_event.cc>