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
33
#include <libdrizzle/my_time.h>
34
#include <drizzled/global.h>
35
#include <mysys/my_sys.h>
36
#include <mystrings/m_string.h>
37
#include <libdrizzle/drizzle.h>
38
#include <libdrizzle/errmsg.h>
39
#include <mysys/my_getopt.h>
40
/* That one is necessary for defines of OPTION_NO_FOREIGN_KEY_CHECKS etc */
41
#include <drizzled/log_event.h>
42
#include <libdrizzle/sql_common.h>
45
enum options_drizzlebinlog
47
OPT_CHARSETS_DIR=256, OPT_BASE64_OUTPUT_MODE,
48
OPT_DEBUG_CHECK, OPT_DEBUG_INFO, OPT_DRIZZLE_PROTOCOL,
49
OPT_SERVER_ID, OPT_SET_CHARSET, OPT_START_DATETIME,
50
OPT_START_POSITION, OPT_STOP_DATETIME, OPT_STOP_POSITION,
54
#define BIN_LOG_HEADER_SIZE 4
55
#define PROBE_HEADER_LEN (EVENT_LEN_OFFSET+4)
58
#define CLIENT_CAPABILITIES (CLIENT_LONG_PASSWORD | CLIENT_LONG_FLAG | CLIENT_LOCAL_FILES)
60
char server_version[SERVER_VERSION_LENGTH];
61
uint32_t server_id = 0;
63
// needed by net_serv.c
64
uint32_t bytes_sent = 0L, bytes_received = 0L;
65
uint32_t drizzled_net_retry_count = 10L;
66
uint32_t open_files_limit;
68
static uint opt_protocol= 0;
69
static FILE *result_file;
71
static const char *load_default_groups[]= { "drizzlebinlog","client",0 };
73
static void error(const char *format, ...) __attribute__((format(printf, 1, 2)));
74
static void warning(const char *format, ...) __attribute__((format(printf, 1, 2)));
76
static bool one_database=0, to_last_remote_log= 0, disable_log_bin= 0;
77
static bool opt_hexdump= 0;
78
const char *base64_output_mode_names[]= {"NEVER", "AUTO", "ALWAYS", NullS};
79
TYPELIB base64_output_mode_typelib=
80
{ array_elements(base64_output_mode_names) - 1, "",
81
base64_output_mode_names, NULL };
82
static enum_base64_output_mode opt_base64_output_mode= BASE64_OUTPUT_UNSPEC;
83
static const char *opt_base64_output_mode_str= NullS;
84
static const char* database= 0;
85
static bool force_opt= 0, short_form= 0, remote_opt= 0;
86
static bool debug_info_flag, debug_check_flag;
87
static bool force_if_open_opt= 1;
88
static uint64_t offset = 0;
89
static const char* host = 0;
91
static uint my_end_arg;
92
static const char* sock= 0;
93
static const char* user = 0;
94
static char* pass = 0;
95
static char *charset= 0;
97
static uint64_t start_position, stop_position;
98
#define start_position_mot ((my_off_t)start_position)
99
#define stop_position_mot ((my_off_t)stop_position)
101
static char *start_datetime_str, *stop_datetime_str;
102
static my_time_t start_datetime= 0, stop_datetime= MY_TIME_T_MAX;
103
static uint64_t rec_count= 0;
104
static short binlog_flags = 0;
105
static DRIZZLE *drizzle= NULL;
106
static const char* dirname_for_local_load= 0;
109
Pointer to the Format_description_log_event of the currently active binlog.
111
This will be changed each time a new Format_description_log_event is
112
found in the binlog. It is finally destroyed at program termination.
114
static Format_description_log_event* glob_description_event= NULL;
117
Exit status for functions in this file.
120
/** No error occurred and execution should continue. */
122
/** An error occurred and execution should stop. */
124
/** No error occurred but execution should stop. */
128
static Exit_status dump_local_log_entries(PRINT_EVENT_INFO *print_event_info,
129
const char* logname);
130
static Exit_status dump_remote_log_entries(PRINT_EVENT_INFO *print_event_info,
131
const char* logname);
132
static Exit_status dump_log_entries(const char* logname);
133
static Exit_status safe_connect();
136
class Load_log_processor
138
char target_dir_name[FN_REFLEN];
139
int target_dir_name_len;
142
When we see first event corresponding to some LOAD DATA statement in
143
binlog, we create temporary file to store data to be loaded.
144
We add name of this file to file_names array using its file_id as index.
145
If we have Create_file event (i.e. we have binary log in pre-5.0.3
146
format) we also store save event object to be able which is needed to
147
emit LOAD DATA statement when we will meet Exec_load_data event.
148
If we have Begin_load_query event we simply store 0 in
149
File_name_record::event field.
151
struct File_name_record
154
Create_file_log_event *event;
157
@todo Should be a map (e.g., a hash map), not an array. With the
158
present implementation, the number of elements in this array is
159
about the number of files loaded since the server started, which
160
may be big after a few years. We should be able to use existing
161
library data structures for this. /Sven
163
DYNAMIC_ARRAY file_names;
166
Looks for a non-existing filename by adding a numerical suffix to
167
the given base name, creates the generated file, and returns the
168
filename by modifying the filename argument.
170
@param[in,out] filename Base filename
172
@param[in,out] file_name_end Pointer to last character of
173
filename. The numerical suffix will be written to this position.
174
Note that there must be a least five bytes of allocated memory
177
@retval -1 Error (can't find new filename).
178
@retval >=0 Found file.
180
File create_unique_file(char *filename, char *file_name_end)
183
/* If we have to try more than 1000 times, something is seriously wrong */
184
for (uint version= 0; version<1000; version++)
186
sprintf(file_name_end,"-%x",version);
187
if ((res= my_create(filename,0,
188
O_CREAT|O_EXCL|O_BINARY|O_WRONLY,MYF(0)))!=-1)
195
Load_log_processor() {}
196
~Load_log_processor() {}
200
return init_dynamic_array(&file_names, sizeof(File_name_record),
201
100,100 CALLER_INFO);
204
void init_by_dir_name(const char *dir)
206
target_dir_name_len= (convert_dirname(target_dir_name, dir, NullS) -
209
void init_by_cur_dir()
211
if (my_getwd(target_dir_name,sizeof(target_dir_name),MYF(MY_WME)))
213
target_dir_name_len= strlen(target_dir_name);
217
File_name_record *ptr= (File_name_record *)file_names.buffer;
218
File_name_record *end= ptr + file_names.elements;
219
for (; ptr < end; ptr++)
223
my_free(ptr->fname, MYF(MY_WME));
225
memset(ptr, 0, sizeof(File_name_record));
229
delete_dynamic(&file_names);
233
Obtain Create_file event for LOAD DATA statement by its file_id
234
and remove it from this Load_log_processor's list of events.
236
Checks whether we have already seen a Create_file_log_event with
237
the given file_id. If yes, returns a pointer to the event and
238
removes the event from array describing active temporary files.
239
From this moment, the caller is responsible for freeing the memory
240
occupied by the event.
242
@param[in] file_id File id identifying LOAD DATA statement.
244
@return Pointer to Create_file_log_event, or NULL if we have not
245
seen any Create_file_log_event with this file_id.
247
Create_file_log_event *grab_event(uint file_id)
249
File_name_record *ptr;
250
Create_file_log_event *res;
252
if (file_id >= file_names.elements)
254
ptr= dynamic_element(&file_names, file_id, File_name_record*);
255
if ((res= ptr->event))
256
memset(ptr, 0, sizeof(File_name_record));
261
Obtain file name of temporary file for LOAD DATA statement by its
262
file_id and remove it from this Load_log_processor's list of events.
264
@param[in] file_id Identifier for the LOAD DATA statement.
266
Checks whether we have already seen Begin_load_query event for
267
this file_id. If yes, returns the file name of the corresponding
268
temporary file and removes the filename from the array of active
269
temporary files. From this moment, the caller is responsible for
270
freeing the memory occupied by this name.
272
@return String with the name of the temporary file, or NULL if we
273
have not seen any Begin_load_query_event with this file_id.
275
char *grab_fname(uint file_id)
277
File_name_record *ptr;
280
if (file_id >= file_names.elements)
282
ptr= dynamic_element(&file_names, file_id, File_name_record*);
286
memset(ptr, 0, sizeof(File_name_record));
290
Exit_status process(Create_file_log_event *ce);
291
Exit_status process(Begin_load_query_log_event *ce);
292
Exit_status process(Append_block_log_event *ae);
293
File prepare_new_file_for_old_format(Load_log_event *le, char *filename);
294
Exit_status load_old_format_file(NET* net, const char *server_fname,
295
uint server_fname_len, File file);
296
Exit_status process_first_event(const char *bname, uint blen,
298
uint block_len, uint file_id,
299
Create_file_log_event *ce);
304
Creates and opens a new temporary file in the directory specified by previous call to init_by_dir_name() or init_by_cur_dir().
306
@param[in] le The basename of the created file will start with the
307
basename of the file pointed to by this Load_log_event.
309
@param[out] filename Buffer to save the filename in.
311
@return File handle >= 0 on success, -1 on error.
313
File Load_log_processor::prepare_new_file_for_old_format(Load_log_event *le,
320
fn_format(filename, le->fname, target_dir_name, "", MY_REPLACE_DIR);
321
len= strlen(filename);
322
tail= filename + len;
324
if ((file= create_unique_file(filename,tail)) < 0)
326
error("Could not construct local filename %s.",filename);
330
le->set_fname_outside_temp_buf(filename,len+strlen(tail));
337
Reads a file from a server and saves it locally.
339
@param[in,out] net The server to read from.
341
@param[in] server_fname The name of the file that the server should
344
@param[in] server_fname_len The length of server_fname.
346
@param[in,out] file The file to write to.
348
@retval ERROR_STOP An error occurred - the program should terminate.
349
@retval OK_CONTINUE No error, the program should continue.
351
Exit_status Load_log_processor::load_old_format_file(NET* net,
352
const char*server_fname,
353
uint server_fname_len,
356
uchar buf[FN_REFLEN+1];
358
memcpy(buf + 1, server_fname, server_fname_len + 1);
359
if (my_net_write(net, buf, server_fname_len +2) || net_flush(net))
361
error("Failed requesting the remote dump of %s.", server_fname);
367
uint32_t packet_len = my_net_read(net);
370
if (my_net_write(net, (uchar*) "", 0) || net_flush(net))
372
error("Failed sending the ack packet.");
376
we just need to send something, as the server will read but
377
not examine the packet - this is because drizzle_load() sends
378
an OK when it is done
382
else if (packet_len == packet_error)
384
error("Failed reading a packet during the dump of %s.", server_fname);
388
if (packet_len > UINT_MAX)
390
error("Illegal length of packet read from net.");
393
if (my_write(file, (uchar*) net->read_pos,
394
(uint) packet_len, MYF(MY_WME|MY_NABP)))
403
Process the first event in the sequence of events representing a
406
Creates a temporary file to be used in LOAD DATA and writes first
407
block of data to it. Registers its file name (and optional
408
Create_file event) in the array of active temporary files.
410
@param bname Base name for temporary file to be created.
411
@param blen Base name length.
412
@param block First block of data to be loaded.
413
@param block_len First block length.
414
@param file_id Identifies the LOAD DATA statement.
415
@param ce Pointer to Create_file event object if we are processing
418
@retval ERROR_STOP An error occurred - the program should terminate.
419
@retval OK_CONTINUE No error, the program should continue.
421
Exit_status Load_log_processor::process_first_event(const char *bname,
426
Create_file_log_event *ce)
428
uint full_len= target_dir_name_len + blen + 9 + 9 + 1;
429
Exit_status retval= OK_CONTINUE;
432
File_name_record rec;
435
if (!(fname= (char*) my_malloc(full_len,MYF(MY_WME))))
437
error("Out of memory.");
442
memcpy(fname, target_dir_name, target_dir_name_len);
443
ptr= fname + target_dir_name_len;
444
memcpy(ptr,bname,blen);
446
ptr+= sprintf(ptr, "-%x", file_id);
448
if ((file= create_unique_file(fname,ptr)) < 0)
450
error("Could not construct local filename %s%s.",
451
target_dir_name,bname);
459
if (set_dynamic(&file_names, (uchar*)&rec, file_id))
461
error("Out of memory.");
467
ce->set_fname_outside_temp_buf(fname, strlen(fname));
469
if (my_write(file, (uchar*)block, block_len, MYF(MY_WME|MY_NABP)))
471
error("Failed writing to file.");
474
if (my_close(file, MYF(MY_WME)))
476
error("Failed closing file.");
484
Process the given Create_file_log_event.
486
@see Load_log_processor::process_first_event(const char*,uint,const char*,uint,uint,Create_file_log_event*)
488
@param ce Create_file_log_event to process.
490
@retval ERROR_STOP An error occurred - the program should terminate.
491
@retval OK_CONTINUE No error, the program should continue.
493
Exit_status Load_log_processor::process(Create_file_log_event *ce)
495
const char *bname= ce->fname + dirname_length(ce->fname);
496
uint blen= ce->fname_len - (bname-ce->fname);
498
return process_first_event(bname, blen, ce->block, ce->block_len,
504
Process the given Begin_load_query_log_event.
506
@see Load_log_processor::process_first_event(const char*,uint,const char*,uint,uint,Create_file_log_event*)
508
@param ce Begin_load_query_log_event to process.
510
@retval ERROR_STOP An error occurred - the program should terminate.
511
@retval OK_CONTINUE No error, the program should continue.
513
Exit_status Load_log_processor::process(Begin_load_query_log_event *blqe)
515
return process_first_event("SQL_LOAD_MB", 11, blqe->block, blqe->block_len,
521
Process the given Append_block_log_event.
523
Appends the chunk of the file contents specified by the event to the
524
file created by a previous Begin_load_query_log_event or
525
Create_file_log_event.
527
If the file_id for the event does not correspond to any file
528
previously registered through a Begin_load_query_log_event or
529
Create_file_log_event, this member function will print a warning and
530
return OK_CONTINUE. It is safe to return OK_CONTINUE, because no
531
query will be written for this event. We should not print an error
532
and fail, since the missing file_id could be because a (valid)
533
--start-position has been specified after the Begin/Create event but
534
before this Append event.
536
@param ae Append_block_log_event to process.
538
@retval ERROR_STOP An error occurred - the program should terminate.
540
@retval OK_CONTINUE No error, the program should continue.
542
Exit_status Load_log_processor::process(Append_block_log_event *ae)
545
const char* fname= ((ae->file_id < file_names.elements) ?
546
dynamic_element(&file_names, ae->file_id,
547
File_name_record*)->fname : 0);
552
Exit_status retval= OK_CONTINUE;
553
if (((file= my_open(fname,
554
O_APPEND|O_BINARY|O_WRONLY,MYF(MY_WME))) < 0))
556
error("Failed opening file %s", fname);
559
if (my_write(file,(uchar*)ae->block,ae->block_len,MYF(MY_WME|MY_NABP)))
561
error("Failed writing to file %s", fname);
564
if (my_close(file,MYF(MY_WME)))
566
error("Failed closing file %s", fname);
573
There is no Create_file event (a bad binlog or a big
574
--start-position). Assuming it's a big --start-position, we just do
575
nothing and print a warning.
577
warning("Ignoring Append_block as there is no "
578
"Create_file event for file_id: %u", ae->file_id);
583
static Load_log_processor load_processor;
587
Replace windows-style backslashes by forward slashes so it can be
588
consumed by the drizzle client, which requires Unix path.
590
@todo This is only useful under windows, so may be ifdef'ed out on
593
@todo If a Create_file_log_event contains a filename with a
594
backslash (valid under unix), then we have problems under windows.
597
@param[in,out] fname Filename to modify. The filename is modified
600
static void convert_path_to_forward_slashes(char *fname)
612
Indicates whether the given database should be filtered out,
613
according to the --database=X option.
615
@param log_dbname Name of database.
617
@return nonzero if the database with the given name should be
618
filtered out, 0 otherwise.
620
static bool shall_skip_database(const char *log_dbname)
622
return one_database &&
623
(log_dbname != NULL) &&
624
strcmp(log_dbname, database);
629
Prints the given event in base64 format.
631
The header is printed to the head cache and the body is printed to
632
the body cache of the print_event_info structure. This allows all
633
base64 events corresponding to the same statement to be joined into
634
one BINLOG statement.
636
@param[in] ev Log_event to print.
637
@param[in,out] result_file FILE to which the output will be written.
638
@param[in,out] print_event_info Parameters and context state
639
determining how to print.
641
@retval ERROR_STOP An error occurred - the program should terminate.
642
@retval OK_CONTINUE No error, the program should continue.
645
write_event_header_and_base64(Log_event *ev, FILE *result_file,
646
PRINT_EVENT_INFO *print_event_info)
648
IO_CACHE *head= &print_event_info->head_cache;
649
IO_CACHE *body= &print_event_info->body_cache;
652
/* Write header and base64 output to cache */
653
ev->print_header(head, print_event_info, false);
654
ev->print_base64(body, print_event_info, false);
656
/* Read data from cache and write to result file */
657
if (copy_event_cache_to_file_and_reinit(head, result_file) ||
658
copy_event_cache_to_file_and_reinit(body, result_file))
660
error("Error writing event to file.");
668
Print the given event, and either delete it or delegate the deletion
671
The deletion may be delegated in two cases: (1) the event is a
672
Format_description_log_event, and is saved in
673
glob_description_event; (2) the event is a Create_file_log_event,
674
and is saved in load_processor.
676
@param[in,out] print_event_info Parameters and context state
677
determining how to print.
678
@param[in] ev Log_event to process.
679
@param[in] pos Offset from beginning of binlog file.
680
@param[in] logname Name of input binlog.
682
@retval ERROR_STOP An error occurred - the program should terminate.
683
@retval OK_CONTINUE No error, the program should continue.
684
@retval OK_STOP No error, but the end of the specified range of
685
events to process has been reached and the program should terminate.
687
Exit_status process_event(PRINT_EVENT_INFO *print_event_info, Log_event *ev,
688
my_off_t pos, const char *logname)
691
Log_event_type ev_type= ev->get_type_code();
693
print_event_info->short_form= short_form;
694
Exit_status retval= OK_CONTINUE;
697
Format events are not concerned by --offset and such, we always need to
698
read them to be able to process the wanted events.
700
if (((rec_count >= offset) && ((my_time_t)(ev->when) >= start_datetime)) || (ev_type == FORMAT_DESCRIPTION_EVENT))
702
if (ev_type != FORMAT_DESCRIPTION_EVENT)
705
We have found an event after start_datetime, from now on print
706
everything (in case the binlog has timestamps increasing and
707
decreasing, we do this to avoid cutting the middle).
710
offset= 0; // print everything and protect against cycling rec_count
712
if (server_id && (server_id != ev->server_id))
713
/* skip just this event, continue processing the log. */
715
if (((my_time_t)(ev->when) >= stop_datetime)
716
|| (pos >= stop_position_mot))
718
/* end the program */
723
fprintf(result_file, "# at %s\n",llstr(pos,ll_buff));
726
print_event_info->hexdump_from= 0; /* Disabled */
728
print_event_info->hexdump_from= pos;
730
print_event_info->base64_output_mode= opt_base64_output_mode;
734
if (shall_skip_database(((Query_log_event*)ev)->db))
736
if (opt_base64_output_mode == BASE64_OUTPUT_ALWAYS)
738
if ((retval= write_event_header_and_base64(ev, result_file,
739
print_event_info)) !=
744
ev->print(result_file, print_event_info);
747
case CREATE_FILE_EVENT:
749
Create_file_log_event* ce= (Create_file_log_event*)ev;
751
We test if this event has to be ignored. If yes, we don't save
752
this event; this will have the good side-effect of ignoring all
753
related Append_block and Exec_load.
754
Note that Load event from 3.23 is not tested.
756
if (shall_skip_database(ce->db))
757
goto end; // Next event
759
We print the event, but with a leading '#': this is just to inform
760
the user of the original command; the command we want to execute
761
will be a derivation of this original command (we will change the
762
filename and use LOCAL), prepared in the 'case EXEC_LOAD_EVENT'
765
if (opt_base64_output_mode == BASE64_OUTPUT_ALWAYS)
767
if ((retval= write_event_header_and_base64(ce, result_file,
768
print_event_info)) !=
773
ce->print(result_file, print_event_info, true);
775
// If this binlog is not 3.23 ; why this test??
776
if (glob_description_event->binlog_version >= 3)
779
transfer the responsibility for destroying the event to
783
if ((retval= load_processor.process(ce)) != OK_CONTINUE)
789
case APPEND_BLOCK_EVENT:
791
Append_block_log_events can safely print themselves even if
792
the subsequent call load_processor.process fails, because the
793
output of Append_block_log_event::print is only a comment.
795
ev->print(result_file, print_event_info);
796
if ((retval= load_processor.process((Append_block_log_event*) ev)) !=
801
case EXEC_LOAD_EVENT:
803
ev->print(result_file, print_event_info);
804
Execute_load_log_event *exv= (Execute_load_log_event*)ev;
805
Create_file_log_event *ce= load_processor.grab_event(exv->file_id);
807
if ce is 0, it probably means that we have not seen the Create_file
808
event (a bad binlog, or most probably --start-position is after the
809
Create_file event). Print a warning comment.
814
We must not convert earlier, since the file is used by
815
my_open() in Load_log_processor::append().
817
convert_path_to_forward_slashes((char*) ce->fname);
818
ce->print(result_file, print_event_info, true);
819
my_free((char*)ce->fname,MYF(MY_WME));
823
warning("Ignoring Execute_load_log_event as there is no "
824
"Create_file event for file_id: %u", exv->file_id);
827
case FORMAT_DESCRIPTION_EVENT:
828
delete glob_description_event;
829
glob_description_event= (Format_description_log_event*) ev;
830
print_event_info->common_header_len=
831
glob_description_event->common_header_len;
832
ev->print(result_file, print_event_info);
833
ev->temp_buf= 0; // as the event ref is zeroed
835
We don't want this event to be deleted now, so let's hide it (I
836
(Guilhem) should later see if this triggers a non-serious Valgrind
837
error). Not serious error, because we will free description_event
841
if (!force_if_open_opt &&
842
(glob_description_event->flags & LOG_EVENT_BINLOG_IN_USE_F))
844
error("Attempting to dump binlog '%s', which was not closed properly. "
845
"Most probably, drizzled is still writing it, or it crashed. "
846
"Rerun with --force-if-open to ignore this problem.", logname);
850
case BEGIN_LOAD_QUERY_EVENT:
851
ev->print(result_file, print_event_info);
852
if ((retval= load_processor.process((Begin_load_query_log_event*) ev)) !=
856
case EXECUTE_LOAD_QUERY_EVENT:
858
Execute_load_query_log_event *exlq= (Execute_load_query_log_event*)ev;
859
char *fname= load_processor.grab_fname(exlq->file_id);
861
if (!shall_skip_database(exlq->db))
865
convert_path_to_forward_slashes(fname);
866
exlq->print(result_file, print_event_info, fname);
869
warning("Ignoring Execute_load_query since there is no "
870
"Begin_load_query event for file_id: %u", exlq->file_id);
874
my_free(fname, MYF(MY_WME));
877
case TABLE_MAP_EVENT:
878
case WRITE_ROWS_EVENT:
879
case DELETE_ROWS_EVENT:
880
case UPDATE_ROWS_EVENT:
881
case PRE_GA_WRITE_ROWS_EVENT:
882
case PRE_GA_DELETE_ROWS_EVENT:
883
case PRE_GA_UPDATE_ROWS_EVENT:
885
These events must be printed in base64 format, if printed.
886
base64 format requires a FD event to be safe, so if no FD
887
event has been printed, we give an error. Except if user
888
passed --short-form, because --short-form disables printing
891
if (!print_event_info->printed_fd_event && !short_form)
893
const char* type_str= ev->get_type_str();
894
if (opt_base64_output_mode == BASE64_OUTPUT_NEVER)
895
error("--base64-output=never specified, but binlog contains a "
896
"%s event which must be printed in base64.",
899
error("malformed binlog: it does not contain any "
900
"Format_description_log_event. I now found a %s event, which "
901
"is not safe to process without a "
902
"Format_description_log_event.",
908
ev->print(result_file, print_event_info);
919
Destroy the log_event object. If reading from a remote host,
920
set the temp_buf to NULL so that memory isn't freed twice.
932
static struct my_option my_long_options[] =
934
{"help", '?', "Display this help and exit.",
935
0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0},
936
{"base64-output", OPT_BASE64_OUTPUT_MODE,
937
"Determine when the output statements should be base64-encoded BINLOG "
938
"statements: 'never' disables it and works only for binlogs without "
939
"row-based events; 'auto' is the default and prints base64 only when "
940
"necessary (i.e., for row-based events and format description events); "
941
"'always' prints base64 whenever possible. 'always' is for debugging "
942
"only and should not be used in a production system. The default is "
943
"'auto'. --base64-output is a short form for --base64-output=always."
944
,(char**) &opt_base64_output_mode_str,
945
(char**) &opt_base64_output_mode_str,
946
0, GET_STR, OPT_ARG, 0, 0, 0, 0, 0, 0},
948
drizzlebinlog needs charsets knowledge, to be able to convert a charset
949
number found in binlog to a charset name (to be able to print things
951
SET @`a`:=_cp850 0x4DFC6C6C6572 COLLATE `cp850_general_ci`;
953
{"character-sets-dir", OPT_CHARSETS_DIR,
954
"Directory where character sets are.", (char**) &charsets_dir,
955
(char**) &charsets_dir, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
956
{"database", 'd', "List entries for just this database (local log only).",
957
(char**) &database, (char**) &database, 0, GET_STR_ALLOC, REQUIRED_ARG,
959
{"debug-check", OPT_DEBUG_CHECK, "Check memory and open file usage at exit .",
960
(char**) &debug_check_flag, (char**) &debug_check_flag, 0,
961
GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0},
962
{"debug-info", OPT_DEBUG_INFO, "Print some debug info at exit.",
963
(char**) &debug_info_flag, (char**) &debug_info_flag,
964
0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0},
965
{"disable-log-bin", 'D', "Disable binary log. This is useful, if you "
966
"enabled --to-last-log and are sending the output to the same DRIZZLE server. "
967
"This way you could avoid an endless loop. You would also like to use it "
968
"when restoring after a crash to avoid duplication of the statements you "
969
"already have. NOTE: you will need a SUPER privilege to use this option.",
970
(char**) &disable_log_bin, (char**) &disable_log_bin, 0, GET_BOOL,
971
NO_ARG, 0, 0, 0, 0, 0, 0},
972
{"force-if-open", 'F', "Force if binlog was not closed properly.",
973
(char**) &force_if_open_opt, (char**) &force_if_open_opt, 0, GET_BOOL, NO_ARG,
975
{"force-read", 'f', "Force reading unknown binlog events.",
976
(char**) &force_opt, (char**) &force_opt, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0,
978
{"hexdump", 'H', "Augment output with hexadecimal and ASCII event dump.",
979
(char**) &opt_hexdump, (char**) &opt_hexdump, 0, GET_BOOL, NO_ARG,
981
{"host", 'h', "Get the binlog from server.", (char**) &host, (char**) &host,
982
0, GET_STR_ALLOC, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
983
{"local-load", 'l', "Prepare local temporary files for LOAD DATA INFILE in the specified directory.",
984
(char**) &dirname_for_local_load, (char**) &dirname_for_local_load, 0,
985
GET_STR_ALLOC, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
986
{"offset", 'o', "Skip the first N entries.", (char**) &offset, (char**) &offset,
987
0, GET_ULL, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
988
{"password", 'p', "Password to connect to remote server.",
989
0, 0, 0, GET_STR, OPT_ARG, 0, 0, 0, 0, 0, 0},
990
{"port", 'P', "Port number to use for connection or 0 for default to, in "
991
"order of preference, my.cnf, $DRIZZLE_TCP_PORT, "
992
"built-in default (" STRINGIFY_ARG(DRIZZLE_PORT) ").",
993
(char**) &port, (char**) &port, 0, GET_INT, REQUIRED_ARG,
995
{"position", 'j', "Deprecated. Use --start-position instead.",
996
(char**) &start_position, (char**) &start_position, 0, GET_ULL,
997
REQUIRED_ARG, BIN_LOG_HEADER_SIZE, BIN_LOG_HEADER_SIZE,
998
/* COM_BINLOG_DUMP accepts only 4 bytes for the position */
999
(uint64_t)(~(uint32_t)0), 0, 0, 0},
1000
{"protocol", OPT_DRIZZLE_PROTOCOL,
1001
"The protocol of connection (tcp,socket,pipe,memory).",
1002
0, 0, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
1003
{"read-from-remote-server", 'R', "Read binary logs from a Drizzle server",
1004
(char**) &remote_opt, (char**) &remote_opt, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0,
1006
{"result-file", 'r', "Direct output to a given file.", 0, 0, 0, GET_STR,
1007
REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
1008
{"server-id", OPT_SERVER_ID,
1009
"Extract only binlog entries created by the server having the given id.",
1010
(char**) &server_id, (char**) &server_id, 0, GET_ULONG,
1011
REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
1012
{"set-charset", OPT_SET_CHARSET,
1013
"Add 'SET NAMES character_set' to the output.", (char**) &charset,
1014
(char**) &charset, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
1015
{"short-form", 's', "Just show regular queries: no extra info and no "
1016
"row-based events. This is for testing only, and should not be used in "
1017
"production systems. If you want to suppress base64-output, consider "
1018
"using --base64-output=never instead.",
1019
(char**) &short_form, (char**) &short_form, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0,
1021
{"socket", 'S', "Socket file to use for connection.",
1022
(char**) &sock, (char**) &sock, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0,
1024
{"start-datetime", OPT_START_DATETIME,
1025
"Start reading the binlog at first event having a datetime equal or "
1026
"posterior to the argument; the argument must be a date and time "
1027
"in the local time zone, in any format accepted by the Drizzle server "
1028
"for DATETIME and TIMESTAMP types, for example: 2004-12-25 11:25:56 "
1029
"(you should probably use quotes for your shell to set it properly).",
1030
(char**) &start_datetime_str, (char**) &start_datetime_str,
1031
0, GET_STR_ALLOC, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
1032
{"start-position", OPT_START_POSITION,
1033
"Start reading the binlog at position N. Applies to the first binlog "
1034
"passed on the command line.",
1035
(char**) &start_position, (char**) &start_position, 0, GET_ULL,
1036
REQUIRED_ARG, BIN_LOG_HEADER_SIZE, BIN_LOG_HEADER_SIZE,
1037
/* COM_BINLOG_DUMP accepts only 4 bytes for the position */
1038
(uint64_t)(~(uint32_t)0), 0, 0, 0},
1039
{"stop-datetime", OPT_STOP_DATETIME,
1040
"Stop reading the binlog at first event having a datetime equal or "
1041
"posterior to the argument; the argument must be a date and time "
1042
"in the local time zone, in any format accepted by the Drizzle server "
1043
"for DATETIME and TIMESTAMP types, for example: 2004-12-25 11:25:56 "
1044
"(you should probably use quotes for your shell to set it properly).",
1045
(char**) &stop_datetime_str, (char**) &stop_datetime_str,
1046
0, GET_STR_ALLOC, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
1047
{"stop-position", OPT_STOP_POSITION,
1048
"Stop reading the binlog at position N. Applies to the last binlog "
1049
"passed on the command line.",
1050
(char**) &stop_position, (char**) &stop_position, 0, GET_ULL,
1051
REQUIRED_ARG, (uint64_t)(~(my_off_t)0), BIN_LOG_HEADER_SIZE,
1052
(uint64_t)(~(my_off_t)0), 0, 0, 0},
1053
{"to-last-log", 't', "Requires -R. Will not stop at the end of the \
1054
requested binlog but rather continue printing until the end of the last \
1055
binlog of the DRIZZLE server. If you send the output to the same DRIZZLE server, \
1056
that may lead to an endless loop.",
1057
(char**) &to_last_remote_log, (char**) &to_last_remote_log, 0, GET_BOOL,
1058
NO_ARG, 0, 0, 0, 0, 0, 0},
1059
{"user", 'u', "Connect to the remote server as username.",
1060
(char**) &user, (char**) &user, 0, GET_STR_ALLOC, REQUIRED_ARG, 0, 0, 0, 0,
1062
{"version", 'V', "Print version and exit.", 0, 0, 0, GET_NO_ARG, NO_ARG, 0,
1064
{"open_files_limit", OPT_OPEN_FILES_LIMIT,
1065
"Used to reserve file descriptors for usage by this program",
1066
(char**) &open_files_limit, (char**) &open_files_limit, 0, GET_ULONG,
1067
REQUIRED_ARG, MY_NFILE, 8, OS_FILE_LIMIT, 0, 1, 0},
1068
{0, 0, 0, 0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0}
1073
Auxiliary function used by error() and warning().
1075
Prints the given text (normally "WARNING: " or "ERROR: "), followed
1076
by the given vprintf-style string, followed by a newline.
1078
@param format Printf-style format string.
1079
@param args List of arguments for the format string.
1080
@param msg Text to print before the string.
1082
static void error_or_warning(const char *format, va_list args, const char *msg)
1084
fprintf(stderr, "%s: ", msg);
1085
vfprintf(stderr, format, args);
1086
fprintf(stderr, "\n");
1090
Prints a message to stderr, prefixed with the text "ERROR: " and
1091
suffixed with a newline.
1093
@param format Printf-style format string, followed by printf
1096
static void error(const char *format,...)
1099
va_start(args, format);
1100
error_or_warning(format, args, "ERROR");
1106
This function is used in log_event.cc to report errors.
1108
@param format Printf-style format string, followed by printf
1111
static void sql_print_error(const char *format, ...) __attribute__((format(printf, 1, 2)));
1112
static void sql_print_error(const char *format,...)
1115
va_start(args, format);
1116
error_or_warning(format, args, "ERROR");
1121
Prints a message to stderr, prefixed with the text "WARNING: " and
1122
suffixed with a newline.
1124
@param format Printf-style format string, followed by printf
1127
static void warning(const char *format,...)
1130
va_start(args, format);
1131
error_or_warning(format, args, "WARNING");
1136
Frees memory for global variables in this file.
1138
static void cleanup()
1140
my_free(pass,MYF(MY_ALLOW_ZERO_PTR));
1141
my_free((char*) database, MYF(MY_ALLOW_ZERO_PTR));
1142
my_free((char*) host, MYF(MY_ALLOW_ZERO_PTR));
1143
my_free((char*) user, MYF(MY_ALLOW_ZERO_PTR));
1144
my_free((char*) dirname_for_local_load, MYF(MY_ALLOW_ZERO_PTR));
1146
delete glob_description_event;
1148
drizzle_close(drizzle);
1151
static void print_version()
1153
printf("%s Ver 3.3 for %s at %s\n", my_progname, SYSTEM_TYPE, MACHINE_TYPE);
1159
puts("By Monty and Sasha, for your professional use\n\
1160
This software comes with NO WARRANTY: This is free software,\n\
1161
and you are welcome to modify and redistribute it under the GPL license\n");
1164
Dumps a DRIZZLE binary log in a format usable for viewing or for piping to\n\
1165
the Drizzle command line client\n\n");
1166
printf("Usage: %s [options] log-files\n", my_progname);
1167
my_print_help(my_long_options);
1168
my_print_variables(my_long_options);
1172
static my_time_t convert_str_to_timestamp(const char* str)
1175
DRIZZLE_TIME l_time;
1176
long dummy_my_timezone;
1177
bool dummy_in_dst_time_gap;
1178
/* We require a total specification (date AND time) */
1179
if (str_to_datetime(str, strlen(str), &l_time, 0, &was_cut) !=
1180
DRIZZLE_TIMESTAMP_DATETIME || was_cut)
1182
error("Incorrect date and time argument: %s", str);
1186
Note that Feb 30th, Apr 31st cause no error messages and are mapped to
1187
the next existing day, like in drizzled. Maybe this could be changed when
1188
drizzled is changed too (with its "strict" mode?).
1191
my_system_gmt_sec(&l_time, &dummy_my_timezone, &dummy_in_dst_time_gap);
1195
get_one_option(int optid, const struct my_option *opt __attribute__((unused)),
1198
bool tty_password=0;
1206
my_free(pass,MYF(MY_ALLOW_ZERO_PTR));
1207
char *start=argument;
1208
pass= my_strdup(argument,MYF(MY_FAE));
1209
while (*argument) *argument++= 'x'; /* Destroy argument */
1211
start[1]=0; /* Cut length of argument */
1217
if (!(result_file = my_fopen(argument, O_WRONLY | O_BINARY, MYF(MY_WME))))
1223
case OPT_DRIZZLE_PROTOCOL:
1224
opt_protocol= find_type_or_exit(argument, &sql_protocol_typelib,
1227
case OPT_START_DATETIME:
1228
start_datetime= convert_str_to_timestamp(start_datetime_str);
1230
case OPT_STOP_DATETIME:
1231
stop_datetime= convert_str_to_timestamp(stop_datetime_str);
1233
case OPT_BASE64_OUTPUT_MODE:
1234
if (argument == NULL)
1235
opt_base64_output_mode= BASE64_OUTPUT_ALWAYS;
1238
opt_base64_output_mode= (enum_base64_output_mode)
1239
(find_type_or_exit(argument, &base64_output_mode_typelib, opt->name)-1);
1250
pass= get_tty_password(NullS);
1256
static int parse_args(int *argc, char*** argv)
1260
result_file = stdout;
1261
load_defaults("my",load_default_groups,argc,argv);
1262
if ((ho_error=handle_options(argc, argv, my_long_options, get_one_option)))
1264
if (debug_info_flag)
1265
my_end_arg= MY_CHECK_ERROR | MY_GIVE_INFO;
1266
if (debug_check_flag)
1267
my_end_arg= MY_CHECK_ERROR;
1273
Create and initialize the global drizzle object, and connect to the
1276
@retval ERROR_STOP An error occurred - the program should terminate.
1277
@retval OK_CONTINUE No error, the program should continue.
1279
static Exit_status safe_connect()
1281
drizzle= drizzle_create(NULL);
1285
error("Failed on drizzle_create.");
1290
drizzle_options(drizzle, DRIZZLE_OPT_PROTOCOL, (char*) &opt_protocol);
1291
if (!drizzle_connect(drizzle, host, user, pass, 0, port, sock, 0))
1293
error("Failed on connect: %s", drizzle_error(drizzle));
1296
drizzle->reconnect= 1;
1302
High-level function for dumping a named binlog.
1304
This function calls dump_remote_log_entries() or
1305
dump_local_log_entries() to do the job.
1307
@param[in] logname Name of input binlog.
1309
@retval ERROR_STOP An error occurred - the program should terminate.
1310
@retval OK_CONTINUE No error, the program should continue.
1311
@retval OK_STOP No error, but the end of the specified range of
1312
events to process has been reached and the program should terminate.
1314
static Exit_status dump_log_entries(const char* logname)
1317
PRINT_EVENT_INFO print_event_info;
1319
if (!print_event_info.init_ok())
1322
Set safe delimiter, to dump things
1323
like CREATE PROCEDURE safely
1325
fprintf(result_file, "DELIMITER /*!*/;\n");
1326
stpcpy(print_event_info.delimiter, "/*!*/;");
1328
rc= (remote_opt ? dump_remote_log_entries(&print_event_info, logname) :
1329
dump_local_log_entries(&print_event_info, logname));
1331
/* Set delimiter back to semicolon */
1332
fprintf(result_file, "DELIMITER ;\n");
1333
stpcpy(print_event_info.delimiter, ";");
1339
When reading a remote binlog, this function is used to grab the
1340
Format_description_log_event in the beginning of the stream.
1342
This is not as smart as check_header() (used for local log); it will
1343
not work for a binlog which mixes format. TODO: fix this.
1345
@retval ERROR_STOP An error occurred - the program should terminate.
1346
@retval OK_CONTINUE No error, the program should continue.
1348
static Exit_status check_master_version()
1350
DRIZZLE_RES* res = 0;
1352
const char* version;
1354
if (drizzle_query(drizzle, "SELECT VERSION()") ||
1355
!(res = drizzle_store_result(drizzle)))
1357
error("Could not find server version: "
1358
"Query failed when checking master version: %s", drizzle_error(drizzle));
1361
if (!(row = drizzle_fetch_row(res)))
1363
error("Could not find server version: "
1364
"Master returned no rows for SELECT VERSION().");
1368
if (!(version = row[0]))
1370
error("Could not find server version: "
1371
"Master reported NULL for the version.");
1375
delete glob_description_event;
1378
glob_description_event= new Format_description_log_event(1);
1381
glob_description_event= new Format_description_log_event(3);
1386
The server is soon going to send us its Format_description log
1387
event, unless it is a 5.0 server with 3.23 or 4.0 binlogs.
1388
So we first assume that this is 4.0 (which is enough to read the
1389
Format_desc event if one comes).
1391
glob_description_event= new Format_description_log_event(3);
1394
glob_description_event= NULL;
1395
error("Could not find server version: "
1396
"Master reported unrecognized Drizzle version '%s'.", version);
1399
if (!glob_description_event || !glob_description_event->is_valid())
1401
error("Failed creating Format_description_log_event; out of memory?");
1405
drizzle_free_result(res);
1409
drizzle_free_result(res);
1415
Requests binlog dump from a remote server and prints the events it
1418
@param[in,out] print_event_info Parameters and context state
1419
determining how to print.
1420
@param[in] logname Name of input binlog.
1422
@retval ERROR_STOP An error occurred - the program should terminate.
1423
@retval OK_CONTINUE No error, the program should continue.
1424
@retval OK_STOP No error, but the end of the specified range of
1425
events to process has been reached and the program should terminate.
1427
static Exit_status dump_remote_log_entries(PRINT_EVENT_INFO *print_event_info,
1428
const char* logname)
1435
my_off_t old_off= start_position_mot;
1436
char fname[FN_REFLEN+1];
1437
Exit_status retval= OK_CONTINUE;
1441
Even if we already read one binlog (case of >=2 binlogs on command line),
1442
we cannot re-use the same connection as before, because it is now dead
1443
(COM_BINLOG_DUMP kills the thread when it finishes).
1445
if ((retval= safe_connect()) != OK_CONTINUE)
1449
if ((retval= check_master_version()) != OK_CONTINUE)
1453
COM_BINLOG_DUMP accepts only 4 bytes for the position, so we are forced to
1456
int4store(buf, (uint32_t)start_position);
1457
int2store(buf + BIN_LOG_HEADER_SIZE, binlog_flags);
1459
size_t tlen = strlen(logname);
1460
if (tlen > UINT_MAX)
1462
error("Log name too long.");
1465
logname_len = (uint) tlen;
1466
int4store(buf + 6, 0);
1467
memcpy(buf + 10, logname, logname_len);
1468
if (simple_command(drizzle, COM_BINLOG_DUMP, buf, logname_len + 10, 1))
1470
error("Got fatal error sending the log dump command.");
1476
const char *error_msg;
1479
len= cli_safe_read(drizzle);
1480
if (len == packet_error)
1482
error("Got error reading packet from server: %s", drizzle_error(drizzle));
1485
if (len < 8 && net->read_pos[0] == 254)
1486
break; // end of data
1487
if (!(ev= Log_event::read_log_event((const char*) net->read_pos + 1 ,
1488
len - 1, &error_msg,
1489
glob_description_event)))
1491
error("Could not construct log event object: %s", error_msg);
1495
If reading from a remote host, ensure the temp_buf for the
1496
Log_event class is pointing to the incoming stream.
1499
ev->register_temp_buf((char*) net->read_pos + 1);
1501
Log_event_type type= ev->get_type_code();
1502
if (glob_description_event->binlog_version >= 3 ||
1503
(type != LOAD_EVENT && type != CREATE_FILE_EVENT))
1506
If this is a Rotate event, maybe it's the end of the requested binlog;
1507
in this case we are done (stop transfer).
1508
This is suitable for binlogs, not relay logs (but for now we don't read
1509
relay logs remotely because the server is not able to do that). If one
1510
day we read relay logs remotely, then we will have a problem with the
1511
detection below: relay logs contain Rotate events which are about the
1512
binlogs, so which would trigger the end-detection below.
1514
if (type == ROTATE_EVENT)
1516
Rotate_log_event *rev= (Rotate_log_event *)ev;
1518
If this is a fake Rotate event, and not about our log, we can stop
1519
transfer. If this a real Rotate event (so it's not about our log,
1520
it's in our log describing the next log), we print it (because it's
1521
part of our log) and then we will stop when we receive the fake one
1526
if (!to_last_remote_log)
1528
if ((rev->ident_len != logname_len) ||
1529
memcmp(rev->new_log_ident, logname, logname_len))
1531
return(OK_CONTINUE);
1534
Otherwise, this is a fake Rotate for our log, at the very
1535
beginning for sure. Skip it, because it was not in the original
1536
log. If we are running with to_last_remote_log, we print it,
1537
because it serves as a useful marker between binlogs then.
1541
len= 1; // fake Rotate, so don't increment old_off
1544
else if (type == FORMAT_DESCRIPTION_EVENT)
1547
This could be an fake Format_description_log_event that server
1548
(5.0+) automatically sends to a slave on connect, before sending
1549
a first event at the requested position. If this is the case,
1550
don't increment old_off. Real Format_description_log_event always
1551
starts from BIN_LOG_HEADER_SIZE position.
1553
if (old_off != BIN_LOG_HEADER_SIZE)
1554
len= 1; // fake event, don't increment old_off
1556
Exit_status retval= process_event(print_event_info, ev, old_off, logname);
1557
if (retval != OK_CONTINUE)
1562
Load_log_event *le= (Load_log_event*)ev;
1563
const char *old_fname= le->fname;
1564
uint old_len= le->fname_len;
1568
if ((file= load_processor.prepare_new_file_for_old_format(le,fname)) < 0)
1571
retval= process_event(print_event_info, ev, old_off, logname);
1572
if (retval != OK_CONTINUE)
1574
my_close(file,MYF(MY_WME));
1577
retval= load_processor.load_old_format_file(net,old_fname,old_len,file);
1578
my_close(file,MYF(MY_WME));
1579
if (retval != OK_CONTINUE)
1583
Let's adjust offset for remote log as for local log to produce
1584
similar text and to have --stop-position to work identically.
1589
return(OK_CONTINUE);
1594
Reads the @c Format_description_log_event from the beginning of a
1597
The @c Format_description_log_event is only read if it is outside
1598
the range specified with @c --start-position; otherwise, it will be
1599
seen later. If this is an old binlog, a fake @c
1600
Format_description_event is created. This also prints a @c
1601
Format_description_log_event to the output, unless we reach the
1602
--start-position range. In this case, it is assumed that a @c
1603
Format_description_log_event will be found when reading events the
1606
@param file The file to which a @c Format_description_log_event will
1609
@param[in,out] print_event_info Parameters and context state
1610
determining how to print.
1612
@param[in] logname Name of input binlog.
1614
@retval ERROR_STOP An error occurred - the program should terminate.
1615
@retval OK_CONTINUE No error, the program should continue.
1616
@retval OK_STOP No error, but the end of the specified range of
1617
events to process has been reached and the program should terminate.
1619
static Exit_status check_header(IO_CACHE* file,
1620
PRINT_EVENT_INFO *print_event_info,
1621
const char* logname)
1623
uchar header[BIN_LOG_HEADER_SIZE];
1624
uchar buf[PROBE_HEADER_LEN];
1625
uint64_t tmp_pos, pos;
1627
delete glob_description_event;
1628
if (!(glob_description_event= new Format_description_log_event(3)))
1630
error("Failed creating Format_description_log_event; out of memory?");
1634
pos= my_b_tell(file);
1635
my_b_seek(file, (my_off_t)0);
1636
if (my_b_read(file, header, sizeof(header)))
1638
error("Failed reading header; probably an empty file.");
1641
if (memcmp(header, BINLOG_MAGIC, sizeof(header)))
1643
error("File is not a binary log file.");
1648
Imagine we are running with --start-position=1000. We still need
1649
to know the binlog format's. So we still need to find, if there is
1650
one, the Format_desc event, or to know if this is a 3.23
1651
binlog. So we need to first read the first events of the log,
1652
those around offset 4. Even if we are reading a 3.23 binlog from
1653
the start (no --start-position): we need to know the header length
1654
(which is 13 in 3.23, 19 in 4.x) to be able to successfully print
1655
the first event (Start_log_event_v3). So even in this case, we
1656
need to "probe" the first bytes of the log *before* we do a real
1657
read_log_event(). Because read_log_event() needs to know the
1658
header's length to work fine.
1662
tmp_pos= my_b_tell(file); /* should be 4 the first time */
1663
if (my_b_read(file, buf, sizeof(buf)))
1667
error("Could not read entry at offset %"PRIu64": "
1668
"Error in log format or read error.", tmp_pos);
1672
Otherwise this is just EOF : this log currently contains 0-2
1673
events. Maybe it's going to be filled in the next
1674
milliseconds; then we are going to have a problem if this a
1675
3.23 log (imagine we are locally reading a 3.23 binlog which
1676
is being written presently): we won't know it in
1677
read_log_event() and will fail(). Similar problems could
1678
happen with hot relay logs if --start-position is used (but a
1679
--start-position which is posterior to the current size of the log).
1680
These are rare problems anyway (reading a hot log + when we
1681
read the first events there are not all there yet + when we
1682
read a bit later there are more events + using a strange
1689
/* always test for a Start_v3, even if no --start-position */
1690
if (buf[EVENT_TYPE_OFFSET] == START_EVENT_V3)
1692
/* This is 3.23 or 4.x */
1693
if (uint4korr(buf + EVENT_LEN_OFFSET) <
1694
(LOG_EVENT_MINIMAL_HEADER_LEN + START_V3_HEADER_LEN))
1696
/* This is 3.23 (format 1) */
1697
delete glob_description_event;
1698
if (!(glob_description_event= new Format_description_log_event(1)))
1700
error("Failed creating Format_description_log_event; "
1707
else if (tmp_pos >= start_position)
1709
else if (buf[EVENT_TYPE_OFFSET] == FORMAT_DESCRIPTION_EVENT)
1712
Format_description_log_event *new_description_event;
1713
my_b_seek(file, tmp_pos); /* seek back to event's start */
1714
if (!(new_description_event= (Format_description_log_event*)
1715
Log_event::read_log_event(file, glob_description_event)))
1716
/* EOF can't be hit here normally, so it's a real error */
1718
error("Could not read a Format_description_log_event event at "
1719
"offset %"PRIu64"; this could be a log format error or read error.",
1723
if (opt_base64_output_mode == BASE64_OUTPUT_AUTO
1724
|| opt_base64_output_mode == BASE64_OUTPUT_ALWAYS)
1727
process_event will delete *description_event and set it to
1728
the new one, so we should not do it ourselves in this
1731
Exit_status retval= process_event(print_event_info,
1732
new_description_event, tmp_pos,
1734
if (retval != OK_CONTINUE)
1739
delete glob_description_event;
1740
glob_description_event= new_description_event;
1743
else if (buf[EVENT_TYPE_OFFSET] == ROTATE_EVENT)
1746
my_b_seek(file, tmp_pos); /* seek back to event's start */
1747
if (!(ev= Log_event::read_log_event(file, glob_description_event)))
1749
/* EOF can't be hit here normally, so it's a real error */
1750
error("Could not read a Rotate_log_event event at offset "
1752
" this could be a log format error or read error.",
1762
my_b_seek(file, pos);
1768
Reads a local binlog and prints the events it sees.
1770
@param[in] logname Name of input binlog.
1772
@param[in,out] print_event_info Parameters and context state
1773
determining how to print.
1775
@retval ERROR_STOP An error occurred - the program should terminate.
1776
@retval OK_CONTINUE No error, the program should continue.
1777
@retval OK_STOP No error, but the end of the specified range of
1778
events to process has been reached and the program should terminate.
1780
static Exit_status dump_local_log_entries(PRINT_EVENT_INFO *print_event_info,
1781
const char* logname)
1784
IO_CACHE cache,*file= &cache;
1785
uchar tmp_buff[BIN_LOG_HEADER_SIZE];
1786
Exit_status retval= OK_CONTINUE;
1788
if (logname && strcmp(logname, "-") != 0)
1790
/* read from normal file */
1791
if ((fd = my_open(logname, O_RDONLY | O_BINARY, MYF(MY_WME))) < 0)
1793
if (init_io_cache(file, fd, 0, READ_CACHE, start_position_mot, 0,
1794
MYF(MY_WME | MY_NABP)))
1796
my_close(fd, MYF(MY_WME));
1799
if ((retval= check_header(file, print_event_info, logname)) != OK_CONTINUE)
1804
if (init_io_cache(file, fileno(stdin), 0, READ_CACHE, (my_off_t) 0,
1805
0, MYF(MY_WME | MY_NABP | MY_DONT_CHECK_FILESIZE)))
1807
error("Failed to init IO cache.");
1810
if ((retval= check_header(file, print_event_info, logname)) != OK_CONTINUE)
1814
/* skip 'start_position' characters from stdin */
1815
uchar buff[IO_SIZE];
1816
my_off_t length,tmp;
1817
for (length= start_position_mot ; length > 0 ; length-=tmp)
1819
tmp=min(length,sizeof(buff));
1820
if (my_b_read(file, buff, (uint) tmp))
1822
error("Failed reading from file.");
1829
if (!glob_description_event || !glob_description_event->is_valid())
1831
error("Invalid Format_description log event; could be out of memory.");
1835
if (!start_position && my_b_read(file, tmp_buff, BIN_LOG_HEADER_SIZE))
1837
error("Failed reading from file.");
1843
my_off_t old_off = my_b_tell(file);
1845
Log_event* ev = Log_event::read_log_event(file, glob_description_event);
1849
if binlog wasn't closed properly ("in use" flag is set) don't complain
1850
about a corruption, but treat it as EOF and move to the next binlog.
1852
if (glob_description_event->flags & LOG_EVENT_BINLOG_IN_USE_F)
1854
else if (file->error)
1856
error("Could not read entry at offset %s: "
1857
"Error in log format or read error.",
1858
llstr(old_off,llbuff));
1861
// file->error == 0 means EOF, that's OK, we break in this case
1864
if ((retval= process_event(print_event_info, ev, old_off, logname)) !=
1876
my_close(fd, MYF(MY_WME));
1882
int main(int argc, char** argv)
1884
char **defaults_argv;
1885
Exit_status retval= OK_CONTINUE;
1886
uint64_t save_stop_position;
1889
init_time(); // for time functions
1891
parse_args(&argc, (char***)&argv);
1897
free_defaults(defaults_argv);
1901
if (opt_base64_output_mode == BASE64_OUTPUT_UNSPEC)
1902
opt_base64_output_mode= BASE64_OUTPUT_AUTO;
1904
my_set_max_open_files(open_files_limit);
1908
if (!dirname_for_local_load)
1910
if (init_tmpdir(&tmpdir, 0))
1912
dirname_for_local_load= my_strdup(my_tmpdir(&tmpdir), MY_WME);
1915
if (load_processor.init())
1917
if (dirname_for_local_load)
1918
load_processor.init_by_dir_name(dirname_for_local_load);
1920
load_processor.init_by_cur_dir();
1922
fprintf(result_file,
1923
"/*!40019 SET @@session.max_insert_delayed_threads=0*/;\n");
1925
if (disable_log_bin)
1926
fprintf(result_file,
1927
"/*!32316 SET @OLD_SQL_LOG_BIN=@@SQL_LOG_BIN, SQL_LOG_BIN=0*/;\n");
1930
In drizzlebinlog|drizzle, don't want Drizzle to be disconnected after each
1931
transaction (which would be the case with GLOBAL.COMPLETION_TYPE==2).
1933
fprintf(result_file,
1934
"/*!50003 SET @OLD_COMPLETION_TYPE=@@COMPLETION_TYPE,"
1935
"COMPLETION_TYPE=0*/;\n");
1938
fprintf(result_file,
1939
"\n/*!40101 SET @OLD_CHARACTER_SET_CLIENT=@@CHARACTER_SET_CLIENT */;"
1940
"\n/*!40101 SET @OLD_CHARACTER_SET_RESULTS=@@CHARACTER_SET_RESULTS */;"
1941
"\n/*!40101 SET @OLD_COLLATION_CONNECTION=@@COLLATION_CONNECTION */;"
1942
"\n/*!40101 SET NAMES %s */;\n", charset);
1944
for (save_stop_position= stop_position, stop_position= ~(my_off_t)0 ;
1947
if (argc == 0) // last log, --stop-position applies
1948
stop_position= save_stop_position;
1949
if ((retval= dump_log_entries(*argv++)) != OK_CONTINUE)
1952
// For next log, --start-position does not apply
1953
start_position= BIN_LOG_HEADER_SIZE;
1957
Issue a ROLLBACK in case the last printed binlog was crashed and had half
1960
fprintf(result_file,
1961
"# End of log file\nROLLBACK /* added by drizzlebinlog */;\n"
1962
"/*!50003 SET COMPLETION_TYPE=@OLD_COMPLETION_TYPE*/;\n");
1963
if (disable_log_bin)
1964
fprintf(result_file, "/*!32316 SET SQL_LOG_BIN=@OLD_SQL_LOG_BIN*/;\n");
1967
fprintf(result_file,
1968
"/*!40101 SET CHARACTER_SET_CLIENT=@OLD_CHARACTER_SET_CLIENT */;\n"
1969
"/*!40101 SET CHARACTER_SET_RESULTS=@OLD_CHARACTER_SET_RESULTS */;\n"
1970
"/*!40101 SET COLLATION_CONNECTION=@OLD_COLLATION_CONNECTION */;\n");
1973
free_tmpdir(&tmpdir);
1974
if (result_file != stdout)
1975
my_fclose(result_file, MYF(0));
1977
free_defaults(defaults_argv);
1978
my_free_open_file_info();
1979
load_processor.destroy();
1982
exit(retval == ERROR_STOP ? 1 : 0);
1986
We must include this here as it's compiled with different options for
1990
#include <drizzled/log_event.cc>