MySQL 5.6.14 Source Code Document
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
mysqlbinlog.cc
1 /*
2  Copyright (c) 2000, 2013, Oracle and/or its affiliates. All rights reserved.
3 
4  This program is free software; you can redistribute it and/or modify
5  it under the terms of the GNU General Public License as published by
6  the Free Software Foundation; version 2 of the License.
7 
8  This program is distributed in the hope that it will be useful,
9  but WITHOUT ANY WARRANTY; without even the implied warranty of
10  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11  GNU General Public License for more details.
12 
13  You should have received a copy of the GNU General Public License
14  along with this program; if not, write to the Free Software
15  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
16 */
17 
18 /*
19 
20  TODO: print the catalog (some USE catalog.db ????).
21 
22  Standalone program to read a MySQL binary log (or relay log).
23 
24  Should be able to read any file of these categories, even with
25  --start-position.
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.
29 */
30 
31 #define MYSQL_CLIENT
32 #undef MYSQL_SERVER
33 #include "client_priv.h"
34 #include "my_default.h"
35 #include <my_time.h>
36 /* That one is necessary for defines of OPTION_NO_FOREIGN_KEY_CHECKS etc */
37 #include "sql_priv.h"
38 #include <signal.h>
39 #include <my_dir.h>
40 
41 /*
42  error() is used in macro BINLOG_ERROR which is invoked in
43  rpl_gtid.h, hence the early forward declaration.
44 */
45 static void error(const char *format, ...) ATTRIBUTE_FORMAT(printf, 1, 2);
46 static void warning(const char *format, ...) ATTRIBUTE_FORMAT(printf, 1, 2);
47 
48 #include "rpl_gtid.h"
49 #include "log_event.h"
50 #include "log_event_old.h"
51 #include "sql_common.h"
52 #include "my_dir.h"
53 #include <welcome_copyright_notice.h> // ORACLE_WELCOME_COPYRIGHT_NOTICE
54 #include "sql_string.h"
55 #include "my_decimal.h"
56 #include "rpl_constants.h"
57 
58 #include <algorithm>
59 
60 using std::min;
61 using std::max;
62 
63 #define BIN_LOG_HEADER_SIZE 4U
64 #define PROBE_HEADER_LEN (EVENT_LEN_OFFSET+4)
65 #define INTVAR_DYNAMIC_INIT 16
66 #define INTVAR_DYNAMIC_INCR 1
67 
68 
69 #define CLIENT_CAPABILITIES (CLIENT_LONG_PASSWORD | CLIENT_LONG_FLAG | CLIENT_LOCAL_FILES)
70 
71 char server_version[SERVER_VERSION_LENGTH];
72 ulong server_id = 0;
73 /*
74  One statement can result in a sequence of several events: Intvar_log_events,
75  User_var_log_events, and Rand_log_events, followed by one
76  Query_log_event. If statements are filtered out, the filter has to be
77  checked for the Query_log_event. So we have to buffer the Intvar,
78  User_var, and Rand events and their corresponding log postions until we see
79  the Query_log_event. This dynamic array buff_ev is used to buffer a structure
80  which stores such an event and the corresponding log position.
81 */
82 
83 DYNAMIC_ARRAY buff_ev;
84 
85 // needed by net_serv.c
86 ulong bytes_sent = 0L, bytes_received = 0L;
87 ulong mysqld_net_retry_count = 10L;
88 ulong open_files_limit;
89 ulong opt_binlog_rows_event_max_size;
90 uint test_flags = 0;
91 static uint opt_protocol= 0;
92 static FILE *result_file;
93 
94 #ifndef DBUG_OFF
95 static const char* default_dbug_option = "d:t:o,/tmp/mysqlbinlog.trace";
96 #endif
97 static const char *load_default_groups[]= { "mysqlbinlog","client",0 };
98 
99 static my_bool one_database=0, disable_log_bin= 0;
100 static my_bool opt_hexdump= 0;
101 const char *base64_output_mode_names[]=
102 {"NEVER", "AUTO", "UNSPEC", "DECODE-ROWS", NullS};
103 TYPELIB base64_output_mode_typelib=
104  { array_elements(base64_output_mode_names) - 1, "",
105  base64_output_mode_names, NULL };
106 static enum_base64_output_mode opt_base64_output_mode= BASE64_OUTPUT_UNSPEC;
107 static char *opt_base64_output_mode_str= 0;
108 static my_bool opt_remote_alias= 0;
109 const char *remote_proto_names[]=
110 {"BINLOG-DUMP-NON-GTIDS", "BINLOG-DUMP-GTIDS", NullS};
111 TYPELIB remote_proto_typelib=
112  { array_elements(remote_proto_names) - 1, "",
113  remote_proto_names, NULL };
114 static enum enum_remote_proto {
115  BINLOG_DUMP_NON_GTID= 0,
116  BINLOG_DUMP_GTID= 1,
117  BINLOG_LOCAL= 2
118 } opt_remote_proto= BINLOG_LOCAL;
119 static char *opt_remote_proto_str= 0;
120 static char *database= 0;
121 static char *output_file= 0;
122 static my_bool force_opt= 0, short_form= 0;
123 static my_bool debug_info_flag, debug_check_flag;
124 static my_bool force_if_open_opt= 1, raw_mode= 0;
125 static my_bool to_last_remote_log= 0, stop_never= 0;
126 static my_bool opt_verify_binlog_checksum= 1;
127 static ulonglong offset = 0;
128 static uint stop_never_server_id= 1;
129 static char* host = 0;
130 static int port= 0;
131 static uint my_end_arg;
132 static const char* sock= 0;
133 static char *opt_plugin_dir= 0, *opt_default_auth= 0;
134 
135 #ifdef HAVE_SMEM
136 static char *shared_memory_base_name= 0;
137 #endif
138 static char* user = 0;
139 static char* pass = 0;
140 static char *opt_bind_addr = NULL;
141 static char *charset= 0;
142 
143 static uint verbose= 0;
144 
145 static ulonglong start_position, stop_position;
146 #define start_position_mot ((my_off_t)start_position)
147 #define stop_position_mot ((my_off_t)stop_position)
148 
149 static char *start_datetime_str, *stop_datetime_str;
150 static my_time_t start_datetime= 0, stop_datetime= MY_TIME_T_MAX;
151 static ulonglong rec_count= 0;
152 static ushort binlog_flags = 0;
153 static MYSQL* mysql = NULL;
154 static char* dirname_for_local_load= 0;
155 static uint opt_server_id_bits = 0;
156 static ulong opt_server_id_mask = 0;
157 Sid_map *global_sid_map= NULL;
158 Checkable_rwlock *global_sid_lock= NULL;
159 Gtid_set *gtid_set_included= NULL;
160 Gtid_set *gtid_set_excluded= NULL;
161 
162 
169 static Format_description_log_event* glob_description_event= NULL;
170 
174 enum Exit_status {
176  OK_CONTINUE= 0,
178  ERROR_STOP,
180  OK_STOP
181 };
182 
183 /*
184  Options that will be used to filter out events.
185 */
186 static char *opt_include_gtids_str= NULL,
187  *opt_exclude_gtids_str= NULL;
188 static my_bool opt_skip_gtids= 0;
189 static bool filter_based_on_gtids= false;
190 
191 static bool in_transaction= false;
192 static bool seen_gtids= false;
193 
194 static Exit_status dump_local_log_entries(PRINT_EVENT_INFO *print_event_info,
195  const char* logname);
196 static Exit_status dump_remote_log_entries(PRINT_EVENT_INFO *print_event_info,
197  const char* logname);
198 static Exit_status dump_log_entries(const char* logname);
199 static Exit_status safe_connect();
200 
201 /*
202  This strucure is used to store the event and the log postion of the events
203  which is later used to print the event details from correct log postions.
204  The Log_event *event is used to store the pointer to the current event and
205  the event_pos is used to store the current event log postion.
206 */
207 
209  {
210  Log_event *event;
211  my_off_t event_pos;
212  };
213 
214 struct buff_event_info buff_event;
215 
217 {
218  char target_dir_name[FN_REFLEN];
219  size_t target_dir_name_len;
220 
221  /*
222  When we see first event corresponding to some LOAD DATA statement in
223  binlog, we create temporary file to store data to be loaded.
224  We add name of this file to file_names array using its file_id as index.
225  If we have Create_file event (i.e. we have binary log in pre-5.0.3
226  format) we also store save event object to be able which is needed to
227  emit LOAD DATA statement when we will meet Exec_load_data event.
228  If we have Begin_load_query event we simply store 0 in
229  File_name_record::event field.
230  */
231  struct File_name_record
232  {
233  char *fname;
235  };
236  /*
237  @todo Should be a map (e.g., a hash map), not an array. With the
238  present implementation, the number of elements in this array is
239  about the number of files loaded since the server started, which
240  may be big after a few years. We should be able to use existing
241  library data structures for this. /Sven
242  */
243  DYNAMIC_ARRAY file_names;
244 
260  File create_unique_file(char *filename, char *file_name_end)
261  {
262  File res;
263  /* If we have to try more than 1000 times, something is seriously wrong */
264  for (uint version= 0; version<1000; version++)
265  {
266  sprintf(file_name_end,"-%x",version);
267  if ((res= my_create(filename,0,
268  O_CREAT|O_EXCL|O_BINARY|O_WRONLY,MYF(0)))!=-1)
269  return res;
270  }
271  return -1;
272  }
273 
274 public:
275  Load_log_processor() {}
276  ~Load_log_processor() {}
277 
278  int init()
279  {
280  return init_dynamic_array(&file_names, sizeof(File_name_record),
281  100, 100);
282  }
283 
284  void init_by_dir_name(const char *dir)
285  {
286  target_dir_name_len= (convert_dirname(target_dir_name, dir, NullS) -
287  target_dir_name);
288  }
289  void init_by_cur_dir()
290  {
291  if (my_getwd(target_dir_name,sizeof(target_dir_name),MYF(MY_WME)))
292  exit(1);
293  target_dir_name_len= strlen(target_dir_name);
294  }
295  void destroy()
296  {
297  File_name_record *ptr= (File_name_record *)file_names.buffer;
298  File_name_record *end= ptr + file_names.elements;
299  for (; ptr < end; ptr++)
300  {
301  if (ptr->fname)
302  {
303  my_free(ptr->fname);
304  delete ptr->event;
305  memset(ptr, 0, sizeof(File_name_record));
306  }
307  }
308 
309  delete_dynamic(&file_names);
310  }
311 
328  {
329  File_name_record *ptr;
331 
332  if (file_id >= file_names.elements)
333  return 0;
334  ptr= dynamic_element(&file_names, file_id, File_name_record*);
335  if ((res= ptr->event))
336  memset(ptr, 0, sizeof(File_name_record));
337  return res;
338  }
339 
355  char *grab_fname(uint file_id)
356  {
357  File_name_record *ptr;
358  char *res= 0;
359 
360  if (file_id >= file_names.elements)
361  return 0;
362  ptr= dynamic_element(&file_names, file_id, File_name_record*);
363  if (!ptr->event)
364  {
365  res= ptr->fname;
366  memset(ptr, 0, sizeof(File_name_record));
367  }
368  return res;
369  }
370  Exit_status process(Create_file_log_event *ce);
371  Exit_status process(Begin_load_query_log_event *ce);
372  Exit_status process(Append_block_log_event *ae);
373  File prepare_new_file_for_old_format(Load_log_event *le, char *filename);
374  Exit_status load_old_format_file(NET* net, const char *server_fname,
375  uint server_fname_len, File file);
376  Exit_status process_first_event(const char *bname, size_t blen,
377  const uchar *block,
378  size_t block_len, uint file_id,
380 };
381 
382 
394  char *filename)
395 {
396  size_t len;
397  char *tail;
398  File file;
399 
400  fn_format(filename, le->fname, target_dir_name, "", MY_REPLACE_DIR);
401  len= strlen(filename);
402  tail= filename + len;
403 
404  if ((file= create_unique_file(filename,tail)) < 0)
405  {
406  error("Could not construct local filename %s.",filename);
407  return -1;
408  }
409 
410  le->set_fname_outside_temp_buf(filename,len+(uint) strlen(tail));
411 
412  return file;
413 }
414 
415 
432  const char*server_fname,
433  uint server_fname_len,
434  File file)
435 {
436  uchar buf[FN_REFLEN+1];
437  buf[0] = 0;
438  memcpy(buf + 1, server_fname, server_fname_len + 1);
439  if (my_net_write(net, buf, server_fname_len +2) || net_flush(net))
440  {
441  error("Failed requesting the remote dump of %s.", server_fname);
442  return ERROR_STOP;
443  }
444 
445  for (;;)
446  {
447  ulong packet_len = my_net_read(net);
448  if (packet_len == 0)
449  {
450  if (my_net_write(net, (uchar*) "", 0) || net_flush(net))
451  {
452  error("Failed sending the ack packet.");
453  return ERROR_STOP;
454  }
455  /*
456  we just need to send something, as the server will read but
457  not examine the packet - this is because mysql_load() sends
458  an OK when it is done
459  */
460  break;
461  }
462  else if (packet_len == packet_error)
463  {
464  error("Failed reading a packet during the dump of %s.", server_fname);
465  return ERROR_STOP;
466  }
467 
468  if (packet_len > UINT_MAX)
469  {
470  error("Illegal length of packet read from net.");
471  return ERROR_STOP;
472  }
473  if (my_write(file, (uchar*) net->read_pos,
474  (uint) packet_len, MYF(MY_WME|MY_NABP)))
475  return ERROR_STOP;
476  }
477 
478  return OK_CONTINUE;
479 }
480 
481 
501 Exit_status Load_log_processor::process_first_event(const char *bname,
502  size_t blen,
503  const uchar *block,
504  size_t block_len,
505  uint file_id,
507 {
508  uint full_len= target_dir_name_len + blen + 9 + 9 + 1;
509  Exit_status retval= OK_CONTINUE;
510  char *fname, *ptr;
511  File file;
512  File_name_record rec;
513  DBUG_ENTER("Load_log_processor::process_first_event");
514 
515  if (!(fname= (char*) my_malloc(full_len,MYF(MY_WME))))
516  {
517  error("Out of memory.");
518  delete ce;
519  DBUG_RETURN(ERROR_STOP);
520  }
521 
522  memcpy(fname, target_dir_name, target_dir_name_len);
523  ptr= fname + target_dir_name_len;
524  memcpy(ptr,bname,blen);
525  ptr+= blen;
526  ptr+= sprintf(ptr, "-%x", file_id);
527 
528  if ((file= create_unique_file(fname,ptr)) < 0)
529  {
530  error("Could not construct local filename %s%s.",
531  target_dir_name,bname);
532  my_free(fname);
533  delete ce;
534  DBUG_RETURN(ERROR_STOP);
535  }
536 
537  rec.fname= fname;
538  rec.event= ce;
539 
540  /*
541  fname is freed in process_event()
542  after Execute_load_query_log_event or Execute_load_log_event
543  will have been processed, otherwise in Load_log_processor::destroy()
544  */
545  if (set_dynamic(&file_names, &rec, file_id))
546  {
547  error("Out of memory.");
548  my_free(fname);
549  delete ce;
550  DBUG_RETURN(ERROR_STOP);
551  }
552 
553  if (ce)
554  ce->set_fname_outside_temp_buf(fname, (uint) strlen(fname));
555 
556  if (my_write(file, (uchar*)block, block_len, MYF(MY_WME|MY_NABP)))
557  {
558  error("Failed writing to file.");
559  retval= ERROR_STOP;
560  }
561  if (my_close(file, MYF(MY_WME)))
562  {
563  error("Failed closing file.");
564  retval= ERROR_STOP;
565  }
566  DBUG_RETURN(retval);
567 }
568 
569 
581 {
582  const char *bname= ce->fname + dirname_length(ce->fname);
583  uint blen= ce->fname_len - (bname-ce->fname);
584 
585  return process_first_event(bname, blen, ce->block, ce->block_len,
586  ce->file_id, ce);
587 }
588 
589 
601 {
602  return process_first_event("SQL_LOAD_MB", 11, blqe->block, blqe->block_len,
603  blqe->file_id, 0);
604 }
605 
606 
630 {
631  DBUG_ENTER("Load_log_processor::process");
632  const char* fname= ((ae->file_id < file_names.elements) ?
633  dynamic_element(&file_names, ae->file_id,
634  File_name_record*)->fname : 0);
635 
636  if (fname)
637  {
638  File file;
639  Exit_status retval= OK_CONTINUE;
640  if (((file= my_open(fname,
641  O_APPEND|O_BINARY|O_WRONLY,MYF(MY_WME))) < 0))
642  {
643  error("Failed opening file %s", fname);
644  DBUG_RETURN(ERROR_STOP);
645  }
646  if (my_write(file,(uchar*)ae->block,ae->block_len,MYF(MY_WME|MY_NABP)))
647  {
648  error("Failed writing to file %s", fname);
649  retval= ERROR_STOP;
650  }
651  if (my_close(file,MYF(MY_WME)))
652  {
653  error("Failed closing file %s", fname);
654  retval= ERROR_STOP;
655  }
656  DBUG_RETURN(retval);
657  }
658 
659  /*
660  There is no Create_file event (a bad binlog or a big
661  --start-position). Assuming it's a big --start-position, we just do
662  nothing and print a warning.
663  */
664  warning("Ignoring Append_block as there is no "
665  "Create_file event for file_id: %u", ae->file_id);
666  DBUG_RETURN(OK_CONTINUE);
667 }
668 
669 
670 static Load_log_processor load_processor;
671 
672 
687 static void convert_path_to_forward_slashes(char *fname)
688 {
689  while (*fname)
690  {
691  if (*fname == '\\')
692  *fname= '/';
693  fname++;
694  }
695 }
696 
697 
707 static bool shall_skip_database(const char *log_dbname)
708 {
709  return one_database &&
710  (log_dbname != NULL) &&
711  strcmp(log_dbname, database);
712 }
713 
714 
725 static bool shall_skip_gtids(Log_event* ev)
726 {
727  bool filtered= false;
728 
729  switch (ev->get_type_code())
730  {
731  case GTID_LOG_EVENT:
732  case ANONYMOUS_GTID_LOG_EVENT:
733  {
734  Gtid_log_event *gtid= (Gtid_log_event *) ev;
735  if (opt_include_gtids_str != NULL)
736  {
737  filtered= filtered ||
738  !gtid_set_included->contains_gtid(gtid->get_sidno(true),
739  gtid->get_gno());
740  }
741 
742  if (opt_exclude_gtids_str != NULL)
743  {
744  filtered= filtered ||
745  gtid_set_excluded->contains_gtid(gtid->get_sidno(true),
746  gtid->get_gno());
747  }
748  filter_based_on_gtids= filtered;
749  filtered= filtered || opt_skip_gtids;
750  }
751  break;
752  /* Skip previous gtids if --skip-gtids is set. */
753  case PREVIOUS_GTIDS_LOG_EVENT:
754  filtered= opt_skip_gtids;
755  break;
756 
757  /*
758  Transaction boundaries reset the global filtering flag.
759 
760  Since in the relay log a transaction can span multiple
761  log files, we do not reset filter_based_on_gtids flag when
762  processing control events (they can appear in the middle
763  of a transaction). But then, if:
764 
765  FILE1: ... GTID BEGIN QUERY QUERY COMMIT ROTATE
766  FILE2: FD BEGIN QUERY QUERY COMMIT
767 
768  Events on the second file would not be outputted, even
769  though they should.
770  */
771  case XID_EVENT:
772  filtered= filter_based_on_gtids;
773  filter_based_on_gtids= false;
774  break;
775  case QUERY_EVENT:
776  filtered= filter_based_on_gtids;
777  if (((Query_log_event *)ev)->ends_group())
778  filter_based_on_gtids= false;
779  break;
780 
781  /*
782  Never skip STOP, FD, ROTATE, IGNORABLE or INCIDENT events.
783  SLAVE_EVENT and START_EVENT_V3 are there for completion.
784 
785  Although in the binlog transactions do not span multiple
786  log files, in the relay-log, that can happen. As such,
787  we need to explicitly state that we do not filter these
788  events, because there is a chance that they appear in the
789  middle of a filtered transaction, e.g.:
790 
791  FILE1: ... GTID BEGIN QUERY QUERY ROTATE
792  FILE2: FD QUERY QUERY COMMIT GTID BEGIN ...
793 
794  In this case, ROTATE and FD events should be processed and
795  outputted.
796  */
797  case START_EVENT_V3: /* for completion */
798  case SLAVE_EVENT: /* for completion */
799  case STOP_EVENT:
800  case FORMAT_DESCRIPTION_EVENT:
801  case ROTATE_EVENT:
802  case IGNORABLE_LOG_EVENT:
803  case INCIDENT_EVENT:
804  filtered= false;
805  break;
806  default:
807  filtered= filter_based_on_gtids;
808  break;
809  }
810 
811  return filtered;
812 }
813 
834 Exit_status process_event(PRINT_EVENT_INFO *print_event_info, Log_event *ev,
835  my_off_t pos, const char *logname)
836 {
837  char ll_buff[21];
838  Log_event_type ev_type= ev->get_type_code();
839  my_bool destroy_evt= TRUE;
840  DBUG_ENTER("process_event");
841  print_event_info->short_form= short_form;
842  Exit_status retval= OK_CONTINUE;
843  IO_CACHE *const head= &print_event_info->head_cache;
844 
845  /*
846  Format events are not concerned by --offset and such, we always need to
847  read them to be able to process the wanted events.
848  */
849  if (((rec_count >= offset) &&
850  ((my_time_t) (ev->when.tv_sec) >= start_datetime)) ||
851  (ev_type == FORMAT_DESCRIPTION_EVENT))
852  {
853  if (ev_type != FORMAT_DESCRIPTION_EVENT)
854  {
855  /*
856  We have found an event after start_datetime, from now on print
857  everything (in case the binlog has timestamps increasing and
858  decreasing, we do this to avoid cutting the middle).
859  */
860  start_datetime= 0;
861  offset= 0; // print everything and protect against cycling rec_count
862  /*
863  Skip events according to the --server-id flag. However, don't
864  skip format_description or rotate events, because they they
865  are really "global" events that are relevant for the entire
866  binlog, even if they have a server_id. Also, we have to read
867  the format_description event so that we can parse subsequent
868  events.
869  */
870  if (ev_type != ROTATE_EVENT &&
871  server_id && (server_id != ev->server_id))
872  goto end;
873  }
874  if (((my_time_t) (ev->when.tv_sec) >= stop_datetime)
875  || (pos >= stop_position_mot))
876  {
877  /* end the program */
878  retval= OK_STOP;
879  goto end;
880  }
881  if (!short_form)
882  my_b_printf(&print_event_info->head_cache,
883  "# at %s\n",llstr(pos,ll_buff));
884 
885  if (!opt_hexdump)
886  print_event_info->hexdump_from= 0; /* Disabled */
887  else
888  print_event_info->hexdump_from= pos;
889 
890  print_event_info->base64_output_mode= opt_base64_output_mode;
891 
892  DBUG_PRINT("debug", ("event_type: %s", ev->get_type_str()));
893 
894  if (shall_skip_gtids(ev))
895  goto end;
896 
897  switch (ev_type) {
898  case QUERY_EVENT:
899  {
900  bool parent_query_skips=
901  !((Query_log_event*) ev)->is_trans_keyword() &&
902  shall_skip_database(((Query_log_event*) ev)->db);
903  bool ends_group= ((Query_log_event*) ev)->ends_group();
904  bool starts_group= ((Query_log_event*) ev)->starts_group();
905 
906  for (uint i= 0; i < buff_ev.elements; i++)
907  {
908  buff_event_info pop_event_array= *dynamic_element(&buff_ev, i, buff_event_info *);
909  Log_event *temp_event= pop_event_array.event;
910  my_off_t temp_log_pos= pop_event_array.event_pos;
911  print_event_info->hexdump_from= (opt_hexdump ? temp_log_pos : 0);
912  if (!parent_query_skips)
913  temp_event->print(result_file, print_event_info);
914  delete temp_event;
915  }
916 
917  print_event_info->hexdump_from= (opt_hexdump ? pos : 0);
918  reset_dynamic(&buff_ev);
919 
920  if (parent_query_skips)
921  {
922  /*
923  Even though there would be no need to set the flag here,
924  since parent_query_skips is never true when handling "COMMIT"
925  statements in the Query_log_event, we still need to handle DDL,
926  which causes a commit itself.
927  */
928 
929  if (seen_gtids && !in_transaction && !starts_group && !ends_group)
930  {
931  /*
932  For DDLs, print the COMMIT right away.
933  */
934  fprintf(result_file, "COMMIT /* added by mysqlbinlog */%s\n", print_event_info->delimiter);
935  print_event_info->skipped_event_in_transaction= false;
936  in_transaction= false;
937  }
938  else
939  print_event_info->skipped_event_in_transaction= true;
940  goto end;
941  }
942 
943  if (ends_group)
944  {
945  in_transaction= false;
946  print_event_info->skipped_event_in_transaction= false;
947  }
948  else if (starts_group)
949  in_transaction= true;
950 
951  ev->print(result_file, print_event_info);
952  if (head->error == -1)
953  goto err;
954  break;
955 
956  destroy_evt= TRUE;
957  }
958 
959  case INTVAR_EVENT:
960  {
961  destroy_evt= FALSE;
962  buff_event.event= ev;
963  buff_event.event_pos= pos;
964  insert_dynamic(&buff_ev, (uchar*) &buff_event);
965  break;
966  }
967 
968  case RAND_EVENT:
969  {
970  destroy_evt= FALSE;
971  buff_event.event= ev;
972  buff_event.event_pos= pos;
973  insert_dynamic(&buff_ev, (uchar*) &buff_event);
974  break;
975  }
976 
977  case USER_VAR_EVENT:
978  {
979  destroy_evt= FALSE;
980  buff_event.event= ev;
981  buff_event.event_pos= pos;
982  insert_dynamic(&buff_ev, (uchar*) &buff_event);
983  break;
984  }
985 
986 
987  case CREATE_FILE_EVENT:
988  {
990  /*
991  We test if this event has to be ignored. If yes, we don't save
992  this event; this will have the good side-effect of ignoring all
993  related Append_block and Exec_load.
994  Note that Load event from 3.23 is not tested.
995  */
996  if (shall_skip_database(ce->db))
997  {
998  print_event_info->skipped_event_in_transaction= true;
999  goto end; // Next event
1000  }
1001  /*
1002  We print the event, but with a leading '#': this is just to inform
1003  the user of the original command; the command we want to execute
1004  will be a derivation of this original command (we will change the
1005  filename and use LOCAL), prepared in the 'case EXEC_LOAD_EVENT'
1006  below.
1007  */
1008  {
1009  ce->print(result_file, print_event_info, TRUE);
1010  if (head->error == -1)
1011  goto err;
1012  }
1013  // If this binlog is not 3.23 ; why this test??
1014  if (glob_description_event->binlog_version >= 3)
1015  {
1016  /*
1017  transfer the responsibility for destroying the event to
1018  load_processor
1019  */
1020  ev= NULL;
1021  if ((retval= load_processor.process(ce)) != OK_CONTINUE)
1022  goto end;
1023  }
1024  break;
1025  }
1026 
1027  case APPEND_BLOCK_EVENT:
1028  /*
1029  Append_block_log_events can safely print themselves even if
1030  the subsequent call load_processor.process fails, because the
1031  output of Append_block_log_event::print is only a comment.
1032  */
1033  ev->print(result_file, print_event_info);
1034  if (head->error == -1)
1035  goto err;
1036  if ((retval= load_processor.process((Append_block_log_event*) ev)) !=
1037  OK_CONTINUE)
1038  goto end;
1039  break;
1040 
1041  case EXEC_LOAD_EVENT:
1042  {
1043  ev->print(result_file, print_event_info);
1044  if (head->error == -1)
1045  goto err;
1047  Create_file_log_event *ce= load_processor.grab_event(exv->file_id);
1048  /*
1049  if ce is 0, it probably means that we have not seen the Create_file
1050  event (a bad binlog, or most probably --start-position is after the
1051  Create_file event). Print a warning comment.
1052  */
1053  if (ce)
1054  {
1055  /*
1056  We must not convert earlier, since the file is used by
1057  my_open() in Load_log_processor::append().
1058  */
1059  convert_path_to_forward_slashes((char*) ce->fname);
1060  ce->print(result_file, print_event_info, TRUE);
1061  my_free((void*)ce->fname);
1062  delete ce;
1063  if (head->error == -1)
1064  goto err;
1065  }
1066  else
1067  warning("Ignoring Execute_load_log_event as there is no "
1068  "Create_file event for file_id: %u", exv->file_id);
1069  break;
1070  }
1071  case FORMAT_DESCRIPTION_EVENT:
1072  delete glob_description_event;
1073  glob_description_event= (Format_description_log_event*) ev;
1074  print_event_info->common_header_len=
1075  glob_description_event->common_header_len;
1076  ev->print(result_file, print_event_info);
1077  if (head->error == -1)
1078  goto err;
1079  if (opt_remote_proto == BINLOG_LOCAL)
1080  {
1081  ev->free_temp_buf(); // free memory allocated in dump_local_log_entries
1082  }
1083  else
1084  {
1085  /*
1086  disassociate but not free dump_remote_log_entries time memory
1087  */
1088  ev->temp_buf= 0;
1089  }
1090  /*
1091  We don't want this event to be deleted now, so let's hide it (I
1092  (Guilhem) should later see if this triggers a non-serious Valgrind
1093  error). Not serious error, because we will free description_event
1094  later.
1095  */
1096  ev= 0;
1097  if (!force_if_open_opt &&
1098  (glob_description_event->flags & LOG_EVENT_BINLOG_IN_USE_F))
1099  {
1100  error("Attempting to dump binlog '%s', which was not closed properly. "
1101  "Most probably, mysqld is still writing it, or it crashed. "
1102  "Rerun with --force-if-open to ignore this problem.", logname);
1103  DBUG_RETURN(ERROR_STOP);
1104  }
1105  break;
1106  case BEGIN_LOAD_QUERY_EVENT:
1107  ev->print(result_file, print_event_info);
1108  if (head->error == -1)
1109  goto err;
1110  if ((retval= load_processor.process((Begin_load_query_log_event*) ev)) !=
1111  OK_CONTINUE)
1112  goto end;
1113  break;
1114  case EXECUTE_LOAD_QUERY_EVENT:
1115  {
1117  char *fname= load_processor.grab_fname(exlq->file_id);
1118 
1119  if (shall_skip_database(exlq->db))
1120  print_event_info->skipped_event_in_transaction= true;
1121  else
1122  {
1123  if (fname)
1124  {
1125  convert_path_to_forward_slashes(fname);
1126  exlq->print(result_file, print_event_info, fname);
1127  if (head->error == -1)
1128  {
1129  if (fname)
1130  my_free(fname);
1131  goto err;
1132  }
1133  }
1134  else
1135  warning("Ignoring Execute_load_query since there is no "
1136  "Begin_load_query event for file_id: %u", exlq->file_id);
1137  }
1138 
1139  if (fname)
1140  my_free(fname);
1141  break;
1142  }
1143  case TABLE_MAP_EVENT:
1144  {
1146  if (shall_skip_database(map->get_db_name()))
1147  {
1148  print_event_info->skipped_event_in_transaction= true;
1149  print_event_info->m_table_map_ignored.set_table(map->get_table_id(), map);
1150  destroy_evt= FALSE;
1151  goto end;
1152  }
1153  }
1154  case ROWS_QUERY_LOG_EVENT:
1155  case WRITE_ROWS_EVENT:
1156  case DELETE_ROWS_EVENT:
1157  case UPDATE_ROWS_EVENT:
1158  case WRITE_ROWS_EVENT_V1:
1159  case UPDATE_ROWS_EVENT_V1:
1160  case DELETE_ROWS_EVENT_V1:
1161  case PRE_GA_WRITE_ROWS_EVENT:
1162  case PRE_GA_DELETE_ROWS_EVENT:
1163  case PRE_GA_UPDATE_ROWS_EVENT:
1164  {
1165  bool stmt_end= FALSE;
1166  Table_map_log_event *ignored_map= NULL;
1167  if (ev_type == WRITE_ROWS_EVENT ||
1168  ev_type == DELETE_ROWS_EVENT ||
1169  ev_type == UPDATE_ROWS_EVENT ||
1170  ev_type == WRITE_ROWS_EVENT_V1 ||
1171  ev_type == DELETE_ROWS_EVENT_V1 ||
1172  ev_type == UPDATE_ROWS_EVENT_V1)
1173  {
1174  Rows_log_event *new_ev= (Rows_log_event*) ev;
1175  if (new_ev->get_flags(Rows_log_event::STMT_END_F))
1176  stmt_end= TRUE;
1177  ignored_map= print_event_info->m_table_map_ignored.get_table(new_ev->get_table_id());
1178  }
1179  else if (ev_type == PRE_GA_WRITE_ROWS_EVENT ||
1180  ev_type == PRE_GA_DELETE_ROWS_EVENT ||
1181  ev_type == PRE_GA_UPDATE_ROWS_EVENT)
1182  {
1183  Old_rows_log_event *old_ev= (Old_rows_log_event*) ev;
1184  if (old_ev->get_flags(Rows_log_event::STMT_END_F))
1185  stmt_end= TRUE;
1186  ignored_map= print_event_info->m_table_map_ignored.get_table(old_ev->get_table_id());
1187  }
1188 
1189  bool skip_event= (ignored_map != NULL);
1190  /*
1191  end of statement check:
1192  i) destroy/free ignored maps
1193  ii) if skip event
1194  a) set the unflushed_events flag to false
1195  b) since we are skipping the last event,
1196  append END-MARKER(') to body cache (if required)
1197  c) flush cache now
1198  */
1199  if (stmt_end)
1200  {
1201  /*
1202  Now is safe to clear ignored map (clear_tables will also
1203  delete original table map events stored in the map).
1204  */
1205  if (print_event_info->m_table_map_ignored.count() > 0)
1206  print_event_info->m_table_map_ignored.clear_tables();
1207 
1208  /*
1209  One needs to take into account an event that gets
1210  filtered but was last event in the statement. If this is
1211  the case, previous rows events that were written into
1212  IO_CACHEs still need to be copied from cache to
1213  result_file (as it would happen in ev->print(...) if
1214  event was not skipped).
1215  */
1216  if (skip_event)
1217  {
1218  // set the unflushed_events flag to false
1219  print_event_info->have_unflushed_events= FALSE;
1220 
1221  // append END-MARKER(') with delimiter
1222  IO_CACHE *const body_cache= &print_event_info->body_cache;
1223  if (my_b_tell(body_cache))
1224  my_b_printf(body_cache, "'%s\n", print_event_info->delimiter);
1225 
1226  // flush cache
1227  if ((copy_event_cache_to_file_and_reinit(&print_event_info->head_cache,
1228  result_file, stop_never /* flush result_file */) ||
1229  copy_event_cache_to_file_and_reinit(&print_event_info->body_cache,
1230  result_file, stop_never /* flush result_file */)))
1231  goto err;
1232  }
1233  }
1234 
1235  /* skip the event check */
1236  if (skip_event)
1237  {
1238  print_event_info->skipped_event_in_transaction= true;
1239  goto end;
1240  }
1241 
1242  /*
1243  These events must be printed in base64 format, if printed.
1244  base64 format requires a FD event to be safe, so if no FD
1245  event has been printed, we give an error. Except if user
1246  passed --short-form, because --short-form disables printing
1247  row events.
1248  */
1249  if (!print_event_info->printed_fd_event && !short_form &&
1250  ev_type != TABLE_MAP_EVENT && ev_type != ROWS_QUERY_LOG_EVENT &&
1251  opt_base64_output_mode != BASE64_OUTPUT_DECODE_ROWS)
1252  {
1253  const char* type_str= ev->get_type_str();
1254  if (opt_base64_output_mode == BASE64_OUTPUT_NEVER)
1255  error("--base64-output=never specified, but binlog contains a "
1256  "%s event which must be printed in base64.",
1257  type_str);
1258  else
1259  error("malformed binlog: it does not contain any "
1260  "Format_description_log_event. I now found a %s event, which "
1261  "is not safe to process without a "
1262  "Format_description_log_event.",
1263  type_str);
1264  goto err;
1265  }
1266 
1267  ev->print(result_file, print_event_info);
1268  print_event_info->have_unflushed_events= TRUE;
1269  /* Flush head and body cache to result_file */
1270  if (stmt_end)
1271  {
1272  print_event_info->have_unflushed_events= FALSE;
1273  if (copy_event_cache_to_file_and_reinit(&print_event_info->head_cache,
1274  result_file, stop_never /* flush result file */) ||
1275  copy_event_cache_to_file_and_reinit(&print_event_info->body_cache,
1276  result_file, stop_never /* flush result file */))
1277  goto err;
1278  goto end;
1279  }
1280  break;
1281  }
1282  case ANONYMOUS_GTID_LOG_EVENT:
1283  case GTID_LOG_EVENT:
1284  {
1285  seen_gtids= true;
1286  if (print_event_info->skipped_event_in_transaction == true)
1287  fprintf(result_file, "COMMIT /* added by mysqlbinlog */%s\n", print_event_info->delimiter);
1288  print_event_info->skipped_event_in_transaction= false;
1289 
1290  ev->print(result_file, print_event_info);
1291  if (head->error == -1)
1292  goto err;
1293  break;
1294  }
1295  case XID_EVENT:
1296  {
1297  in_transaction= false;
1298  print_event_info->skipped_event_in_transaction= false;
1299  ev->print(result_file, print_event_info);
1300  if (head->error == -1)
1301  goto err;
1302  break;
1303  }
1304  case ROTATE_EVENT:
1305  {
1306  Rotate_log_event *rev= (Rotate_log_event *) ev;
1307  /* no transaction context, gtids seen and not a fake rotate */
1308  if (seen_gtids)
1309  {
1310  /*
1311  Fake rotate events have 'when' set to zero. @c fake_rotate_event(...).
1312  */
1313  bool is_fake= (rev->when.tv_sec == 0);
1314  if (!in_transaction && !is_fake)
1315  {
1316  /*
1317  If processing multiple files, we must reset this flag,
1318  since there may be no gtids on the next one.
1319  */
1320  seen_gtids= false;
1321  fprintf(result_file, "SET @@SESSION.GTID_NEXT= 'AUTOMATIC' "
1322  "/* added by mysqlbinlog */ %s\n",
1323  print_event_info->delimiter);
1324  }
1325  }
1326  ev->print(result_file, print_event_info);
1327  if (head->error == -1)
1328  goto err;
1329  break;
1330  }
1331  case PREVIOUS_GTIDS_LOG_EVENT:
1332  if (one_database && !opt_skip_gtids)
1333  warning("The option --database has been used. It may filter "
1334  "parts of transactions, but will include the GTIDs in "
1335  "any case. If you want to exclude or include transactions, "
1336  "you should use the options --exclude-gtids or "
1337  "--include-gtids, respectively, instead.");
1338  /* fall through */
1339  default:
1340  ev->print(result_file, print_event_info);
1341  if (head->error == -1)
1342  goto err;
1343  }
1344  /* Flush head cache to result_file for every event */
1345  if (copy_event_cache_to_file_and_reinit(&print_event_info->head_cache,
1346  result_file, stop_never /* flush result_file */))
1347  goto err;
1348  }
1349 
1350  goto end;
1351 
1352 err:
1353  retval= ERROR_STOP;
1354 end:
1355  rec_count++;
1356  /*
1357  Destroy the log_event object. If reading from a remote host,
1358  set the temp_buf to NULL so that memory isn't freed twice.
1359  */
1360  if (ev)
1361  {
1362  if (opt_remote_proto != BINLOG_LOCAL)
1363  ev->temp_buf= 0;
1364  if (destroy_evt) /* destroy it later if not set (ignored table map) */
1365  delete ev;
1366  }
1367  DBUG_RETURN(retval);
1368 }
1369 
1370 
1371 static struct my_option my_long_options[] =
1372 {
1373  {"help", '?', "Display this help and exit.",
1374  0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0},
1375  {"base64-output", OPT_BASE64_OUTPUT_MODE,
1376  /* 'unspec' is not mentioned because it is just a placeholder. */
1377  "Determine when the output statements should be base64-encoded BINLOG "
1378  "statements: 'never' disables it and works only for binlogs without "
1379  "row-based events; 'decode-rows' decodes row events into commented pseudo-SQL "
1380  "statements if the --verbose option is also given; 'auto' prints base64 "
1381  "only when necessary (i.e., for row-based events and format description "
1382  "events). If no --base64-output[=name] option is given at all, the "
1383  "default is 'auto'.",
1384  &opt_base64_output_mode_str, &opt_base64_output_mode_str,
1385  0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
1386  {"bind-address", 0, "IP address to bind to.",
1387  (uchar**) &opt_bind_addr, (uchar**) &opt_bind_addr, 0, GET_STR,
1388  REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
1389  /*
1390  mysqlbinlog needs charsets knowledge, to be able to convert a charset
1391  number found in binlog to a charset name (to be able to print things
1392  like this:
1393  SET @`a`:=_cp850 0x4DFC6C6C6572 COLLATE `cp850_general_ci`;
1394  */
1395  {"character-sets-dir", OPT_CHARSETS_DIR,
1396  "Directory for character set files.", &charsets_dir,
1397  &charsets_dir, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
1398  {"database", 'd', "List entries for just this database (local log only).",
1399  &database, &database, 0, GET_STR_ALLOC, REQUIRED_ARG,
1400  0, 0, 0, 0, 0, 0},
1401 #ifndef DBUG_OFF
1402  {"debug", '#', "Output debug log.", &default_dbug_option,
1403  &default_dbug_option, 0, GET_STR, OPT_ARG, 0, 0, 0, 0, 0, 0},
1404 #endif
1405  {"debug-check", OPT_DEBUG_CHECK, "Check memory and open file usage at exit .",
1406  &debug_check_flag, &debug_check_flag, 0,
1407  GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0},
1408  {"debug-info", OPT_DEBUG_INFO, "Print some debug info at exit.",
1409  &debug_info_flag, &debug_info_flag,
1410  0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0},
1411  {"default_auth", OPT_DEFAULT_AUTH,
1412  "Default authentication client-side plugin to use.",
1413  &opt_default_auth, &opt_default_auth, 0,
1414  GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
1415  {"disable-log-bin", 'D', "Disable binary log. This is useful, if you "
1416  "enabled --to-last-log and are sending the output to the same MySQL server. "
1417  "This way you could avoid an endless loop. You would also like to use it "
1418  "when restoring after a crash to avoid duplication of the statements you "
1419  "already have. NOTE: you will need a SUPER privilege to use this option.",
1420  &disable_log_bin, &disable_log_bin, 0, GET_BOOL,
1421  NO_ARG, 0, 0, 0, 0, 0, 0},
1422  {"force-if-open", 'F', "Force if binlog was not closed properly.",
1423  &force_if_open_opt, &force_if_open_opt, 0, GET_BOOL, NO_ARG,
1424  1, 0, 0, 0, 0, 0},
1425  {"force-read", 'f', "Force reading unknown binlog events.",
1426  &force_opt, &force_opt, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0,
1427  0, 0},
1428  {"hexdump", 'H', "Augment output with hexadecimal and ASCII event dump.",
1429  &opt_hexdump, &opt_hexdump, 0, GET_BOOL, NO_ARG,
1430  0, 0, 0, 0, 0, 0},
1431  {"host", 'h', "Get the binlog from server.", &host, &host,
1432  0, GET_STR_ALLOC, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
1433  {"local-load", 'l', "Prepare local temporary files for LOAD DATA INFILE in the specified directory.",
1434  &dirname_for_local_load, &dirname_for_local_load, 0,
1435  GET_STR_ALLOC, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
1436  {"offset", 'o', "Skip the first N entries.", &offset, &offset,
1437  0, GET_ULL, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
1438  {"password", 'p', "Password to connect to remote server.",
1439  0, 0, 0, GET_PASSWORD, OPT_ARG, 0, 0, 0, 0, 0, 0},
1440  {"plugin_dir", OPT_PLUGIN_DIR, "Directory for client-side plugins.",
1441  &opt_plugin_dir, &opt_plugin_dir, 0,
1442  GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
1443  {"port", 'P', "Port number to use for connection or 0 for default to, in "
1444  "order of preference, my.cnf, $MYSQL_TCP_PORT, "
1445 #if MYSQL_PORT_DEFAULT == 0
1446  "/etc/services, "
1447 #endif
1448  "built-in default (" STRINGIFY_ARG(MYSQL_PORT) ").",
1449  &port, &port, 0, GET_INT, REQUIRED_ARG,
1450  0, 0, 0, 0, 0, 0},
1451  {"protocol", OPT_MYSQL_PROTOCOL,
1452  "The protocol to use for connection (tcp, socket, pipe, memory).",
1453  0, 0, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
1454  {"read-from-remote-server", 'R', "Read binary logs from a MySQL server. "
1455  "This is an alias for read-from-remote-master=BINLOG-DUMP-NON-GTIDS.",
1456  &opt_remote_alias, &opt_remote_alias, 0, GET_BOOL, NO_ARG,
1457  0, 0, 0, 0, 0, 0},
1458  {"read-from-remote-master", OPT_REMOTE_PROTO,
1459  "Read binary logs from a MySQL server through the COM_BINLOG_DUMP or "
1460  "COM_BINLOG_DUMP_GTID commands by setting the option to either "
1461  "BINLOG-DUMP-NON-GTIDS or BINLOG-DUMP-GTIDS, respectively. If "
1462  "--read-from-remote-master=BINLOG-DUMP-GTIDS is combined with "
1463  "--exclude-gtids, transactions can be filtered out on the master "
1464  "avoiding unnecessary network traffic.",
1465  &opt_remote_proto_str, &opt_remote_proto_str, 0, GET_STR, REQUIRED_ARG,
1466  0, 0, 0, 0, 0, 0},
1467  {"raw", OPT_RAW_OUTPUT, "Requires -R. Output raw binlog data instead of SQL "
1468  "statements, output is to log files.",
1469  &raw_mode, &raw_mode, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0,
1470  0, 0},
1471  {"result-file", 'r', "Direct output to a given file. With --raw this is a "
1472  "prefix for the file names.",
1473  &output_file, &output_file, 0, GET_STR, REQUIRED_ARG,
1474  0, 0, 0, 0, 0, 0},
1475  {"server-id", OPT_SERVER_ID,
1476  "Extract only binlog entries created by the server having the given id.",
1477  &server_id, &server_id, 0, GET_ULONG,
1478  REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
1479  {"server-id-bits", 0,
1480  "Set number of significant bits in server-id",
1481  &opt_server_id_bits, &opt_server_id_bits,
1482  /* Default + Max 32 bits, minimum 7 bits */
1483  0, GET_UINT, REQUIRED_ARG, 32, 7, 32, 0, 0, 0},
1484  {"set-charset", OPT_SET_CHARSET,
1485  "Add 'SET NAMES character_set' to the output.", &charset,
1486  &charset, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
1487 #ifdef HAVE_SMEM
1488  {"shared-memory-base-name", OPT_SHARED_MEMORY_BASE_NAME,
1489  "Base name of shared memory.", &shared_memory_base_name,
1490  &shared_memory_base_name,
1491  0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
1492 #endif
1493  {"short-form", 's', "Just show regular queries: no extra info and no "
1494  "row-based events. This is for testing only, and should not be used in "
1495  "production systems. If you want to suppress base64-output, consider "
1496  "using --base64-output=never instead.",
1497  &short_form, &short_form, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0,
1498  0, 0},
1499  {"socket", 'S', "The socket file to use for connection.",
1500  &sock, &sock, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0,
1501  0, 0},
1502  {"start-datetime", OPT_START_DATETIME,
1503  "Start reading the binlog at first event having a datetime equal or "
1504  "posterior to the argument; the argument must be a date and time "
1505  "in the local time zone, in any format accepted by the MySQL server "
1506  "for DATETIME and TIMESTAMP types, for example: 2004-12-25 11:25:56 "
1507  "(you should probably use quotes for your shell to set it properly).",
1508  &start_datetime_str, &start_datetime_str,
1509  0, GET_STR_ALLOC, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
1510  {"start-position", 'j',
1511  "Start reading the binlog at position N. Applies to the first binlog "
1512  "passed on the command line.",
1513  &start_position, &start_position, 0, GET_ULL,
1514  REQUIRED_ARG, BIN_LOG_HEADER_SIZE, BIN_LOG_HEADER_SIZE,
1515  /* COM_BINLOG_DUMP accepts only 4 bytes for the position */
1516  (ulonglong)(~(uint32)0), 0, 0, 0},
1517  {"stop-datetime", OPT_STOP_DATETIME,
1518  "Stop reading the binlog at first event having a datetime equal or "
1519  "posterior to the argument; the argument must be a date and time "
1520  "in the local time zone, in any format accepted by the MySQL server "
1521  "for DATETIME and TIMESTAMP types, for example: 2004-12-25 11:25:56 "
1522  "(you should probably use quotes for your shell to set it properly).",
1523  &stop_datetime_str, &stop_datetime_str,
1524  0, GET_STR_ALLOC, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
1525  {"stop-never", OPT_STOP_NEVER, "Wait for more data from the server "
1526  "instead of stopping at the end of the last log. Implicitly sets "
1527  "--to-last-log but instead of stopping at the end of the last log "
1528  "it continues to wait till the server disconnects.",
1529  &stop_never, &stop_never, 0,
1530  GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0},
1531  {"stop-never-slave-server-id", OPT_WAIT_SERVER_ID,
1532  "The slave server ID used for stop-never",
1533  &stop_never_server_id, &stop_never_server_id, 0,
1534  GET_UINT, REQUIRED_ARG, 65535, 1, 65535, 0, 0, 0},
1535  {"stop-position", OPT_STOP_POSITION,
1536  "Stop reading the binlog at position N. Applies to the last binlog "
1537  "passed on the command line.",
1538  &stop_position, &stop_position, 0, GET_ULL,
1539  REQUIRED_ARG, (longlong)(~(my_off_t)0), BIN_LOG_HEADER_SIZE,
1540  (ulonglong)(~(my_off_t)0), 0, 0, 0},
1541  {"to-last-log", 't', "Requires -R. Will not stop at the end of the "
1542  "requested binlog but rather continue printing until the end of the last "
1543  "binlog of the MySQL server. If you send the output to the same MySQL "
1544  "server, that may lead to an endless loop.",
1545  &to_last_remote_log, &to_last_remote_log, 0, GET_BOOL,
1546  NO_ARG, 0, 0, 0, 0, 0, 0},
1547  {"user", 'u', "Connect to the remote server as username.",
1548  &user, &user, 0, GET_STR_ALLOC, REQUIRED_ARG, 0, 0, 0, 0,
1549  0, 0},
1550  {"verbose", 'v', "Reconstruct pseudo-SQL statements out of row events. "
1551  "-v -v adds comments on column data types.",
1552  0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0},
1553  {"version", 'V', "Print version and exit.", 0, 0, 0, GET_NO_ARG, NO_ARG, 0,
1554  0, 0, 0, 0, 0},
1555  {"open_files_limit", OPT_OPEN_FILES_LIMIT,
1556  "Used to reserve file descriptors for use by this program.",
1557  &open_files_limit, &open_files_limit, 0, GET_ULONG,
1558  REQUIRED_ARG, MY_NFILE, 8, OS_FILE_LIMIT, 0, 1, 0},
1559  {"verify-binlog-checksum", 'c', "Verify checksum binlog events.",
1560  (uchar**) &opt_verify_binlog_checksum, (uchar**) &opt_verify_binlog_checksum,
1561  0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0},
1562  {"binlog-row-event-max-size", OPT_BINLOG_ROWS_EVENT_MAX_SIZE,
1563  "The maximum size of a row-based binary log event in bytes. Rows will be "
1564  "grouped into events smaller than this size if possible. "
1565  "This value must be a multiple of 256.",
1566  &opt_binlog_rows_event_max_size,
1567  &opt_binlog_rows_event_max_size, 0,
1568  GET_ULONG, REQUIRED_ARG,
1569  /* def_value 4GB */ UINT_MAX, /* min_value */ 256,
1570  /* max_value */ ULONG_MAX, /* sub_size */ 0,
1571  /* block_size */ 256, /* app_type */ 0},
1572  {"skip-gtids", OPT_MYSQLBINLOG_SKIP_GTIDS,
1573  "Do not print Global Transaction Identifier information "
1574  "(SET GTID_NEXT=... etc).",
1575  &opt_skip_gtids, &opt_skip_gtids, 0,
1576  GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0},
1577  {"include-gtids", OPT_MYSQLBINLOG_INCLUDE_GTIDS,
1578  "Print events whose Global Transaction Identifiers "
1579  "were provided.",
1580  &opt_include_gtids_str, &opt_include_gtids_str, 0,
1581  GET_STR_ALLOC, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
1582  {"exclude-gtids", OPT_MYSQLBINLOG_EXCLUDE_GTIDS,
1583  "Print all events but those whose Global Transaction "
1584  "Identifiers were provided.",
1585  &opt_exclude_gtids_str, &opt_exclude_gtids_str, 0,
1586  GET_STR_ALLOC, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
1587  {0, 0, 0, 0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0}
1588 };
1589 
1590 
1601 static void error_or_warning(const char *format, va_list args, const char *msg)
1602 {
1603  fprintf(stderr, "%s: ", msg);
1604  vfprintf(stderr, format, args);
1605  fprintf(stderr, "\n");
1606 }
1607 
1615 static void error(const char *format,...)
1616 {
1617  va_list args;
1618  va_start(args, format);
1619  error_or_warning(format, args, "ERROR");
1620  va_end(args);
1621 }
1622 
1623 
1630 static void sql_print_error(const char *format,...)
1631 {
1632  va_list args;
1633  va_start(args, format);
1634  error_or_warning(format, args, "ERROR");
1635  va_end(args);
1636 }
1637 
1645 static void warning(const char *format,...)
1646 {
1647  va_list args;
1648  va_start(args, format);
1649  error_or_warning(format, args, "WARNING");
1650  va_end(args);
1651 }
1652 
1656 static void cleanup()
1657 {
1658  my_free(pass);
1659  my_free(database);
1660  my_free(host);
1661  my_free(user);
1662  my_free(dirname_for_local_load);
1663 
1664  for (uint i= 0; i < buff_ev.elements; i++)
1665  {
1666  buff_event_info pop_event_array= *dynamic_element(&buff_ev, i, buff_event_info *);
1667  delete (pop_event_array.event);
1668  }
1669  delete_dynamic(&buff_ev);
1670 
1671  delete glob_description_event;
1672  if (mysql)
1673  mysql_close(mysql);
1674 }
1675 
1676 
1677 static void print_version()
1678 {
1679  printf("%s Ver 3.4 for %s at %s\n", my_progname, SYSTEM_TYPE, MACHINE_TYPE);
1680 }
1681 
1682 
1683 static void usage()
1684 {
1685  print_version();
1686  puts(ORACLE_WELCOME_COPYRIGHT_NOTICE("2000"));
1687  printf("\
1688 Dumps a MySQL binary log in a format usable for viewing or for piping to\n\
1689 the mysql command line client.\n\n");
1690  printf("Usage: %s [options] log-files\n", my_progname);
1691  my_print_help(my_long_options);
1692  my_print_variables(my_long_options);
1693 }
1694 
1695 
1696 static my_time_t convert_str_to_timestamp(const char* str)
1697 {
1698  MYSQL_TIME_STATUS status;
1699  MYSQL_TIME l_time;
1700  long dummy_my_timezone;
1701  my_bool dummy_in_dst_time_gap;
1702  /* We require a total specification (date AND time) */
1703  if (str_to_datetime(str, (uint) strlen(str), &l_time, 0, &status) ||
1704  l_time.time_type != MYSQL_TIMESTAMP_DATETIME || status.warnings)
1705  {
1706  error("Incorrect date and time argument: %s", str);
1707  exit(1);
1708  }
1709  /*
1710  Note that Feb 30th, Apr 31st cause no error messages and are mapped to
1711  the next existing day, like in mysqld. Maybe this could be changed when
1712  mysqld is changed too (with its "strict" mode?).
1713  */
1714  return
1715  my_system_gmt_sec(&l_time, &dummy_my_timezone, &dummy_in_dst_time_gap);
1716 }
1717 
1718 
1719 extern "C" my_bool
1720 get_one_option(int optid, const struct my_option *opt __attribute__((unused)),
1721  char *argument)
1722 {
1723  bool tty_password=0;
1724  switch (optid) {
1725 #ifndef DBUG_OFF
1726  case '#':
1727  DBUG_PUSH(argument ? argument : default_dbug_option);
1728  break;
1729 #endif
1730  case 'd':
1731  one_database = 1;
1732  break;
1733  case 'p':
1734  if (argument == disabled_my_option)
1735  argument= (char*) ""; // Don't require password
1736  if (argument)
1737  {
1738  my_free(pass);
1739  char *start=argument;
1740  pass= my_strdup(argument,MYF(MY_FAE));
1741  while (*argument) *argument++= 'x'; /* Destroy argument */
1742  if (*start)
1743  start[1]=0; /* Cut length of argument */
1744  }
1745  else
1746  tty_password=1;
1747  break;
1748  case 'R':
1749  opt_remote_alias= 1;
1750  opt_remote_proto= BINLOG_DUMP_NON_GTID;
1751  break;
1752  case OPT_REMOTE_PROTO:
1753  opt_remote_proto= (enum_remote_proto)
1754  (find_type_or_exit(argument, &remote_proto_typelib, opt->name) - 1);
1755  break;
1756  case OPT_MYSQL_PROTOCOL:
1757  opt_protocol= find_type_or_exit(argument, &sql_protocol_typelib,
1758  opt->name);
1759  break;
1760  case OPT_START_DATETIME:
1761  start_datetime= convert_str_to_timestamp(start_datetime_str);
1762  break;
1763  case OPT_STOP_DATETIME:
1764  stop_datetime= convert_str_to_timestamp(stop_datetime_str);
1765  break;
1766  case OPT_BASE64_OUTPUT_MODE:
1767  opt_base64_output_mode= (enum_base64_output_mode)
1768  (find_type_or_exit(argument, &base64_output_mode_typelib, opt->name)-1);
1769  break;
1770  case 'v':
1771  if (argument == disabled_my_option)
1772  verbose= 0;
1773  else
1774  verbose++;
1775  break;
1776  case 'V':
1777  print_version();
1778  exit(0);
1779  case OPT_STOP_NEVER:
1780  /* wait-for-data implicitly sets to-last-log */
1781  to_last_remote_log= 1;
1782  break;
1783  case '?':
1784  usage();
1785  exit(0);
1786  }
1787  if (tty_password)
1788  pass= get_tty_password(NullS);
1789 
1790  return 0;
1791 }
1792 
1793 
1794 static int parse_args(int *argc, char*** argv)
1795 {
1796  int ho_error;
1797 
1798  result_file = stdout;
1799  if ((ho_error=handle_options(argc, argv, my_long_options, get_one_option)))
1800  exit(ho_error);
1801  if (debug_info_flag)
1802  my_end_arg= MY_CHECK_ERROR | MY_GIVE_INFO;
1803  if (debug_check_flag)
1804  my_end_arg= MY_CHECK_ERROR;
1805  return 0;
1806 }
1807 
1808 
1816 static Exit_status safe_connect()
1817 {
1818  mysql= mysql_init(NULL);
1819 
1820  if (!mysql)
1821  {
1822  error("Failed on mysql_init.");
1823  return ERROR_STOP;
1824  }
1825 
1826  if (opt_plugin_dir && *opt_plugin_dir)
1827  mysql_options(mysql, MYSQL_PLUGIN_DIR, opt_plugin_dir);
1828 
1829  if (opt_default_auth && *opt_default_auth)
1830  mysql_options(mysql, MYSQL_DEFAULT_AUTH, opt_default_auth);
1831 
1832  if (opt_protocol)
1833  mysql_options(mysql, MYSQL_OPT_PROTOCOL, (char*) &opt_protocol);
1834  if (opt_bind_addr)
1835  mysql_options(mysql, MYSQL_OPT_BIND, opt_bind_addr);
1836 #ifdef HAVE_SMEM
1837  if (shared_memory_base_name)
1838  mysql_options(mysql, MYSQL_SHARED_MEMORY_BASE_NAME,
1839  shared_memory_base_name);
1840 #endif
1841  mysql_options(mysql, MYSQL_OPT_CONNECT_ATTR_RESET, 0);
1842  mysql_options4(mysql, MYSQL_OPT_CONNECT_ATTR_ADD,
1843  "program_name", "mysqlbinlog");
1844  if (!mysql_real_connect(mysql, host, user, pass, 0, port, sock, 0))
1845  {
1846  error("Failed on connect: %s", mysql_error(mysql));
1847  return ERROR_STOP;
1848  }
1849  mysql->reconnect= 1;
1850  return OK_CONTINUE;
1851 }
1852 
1853 
1867 static Exit_status dump_log_entries(const char* logname)
1868 {
1869  DBUG_ENTER("dump_log_entries");
1870 
1871  Exit_status rc= OK_CONTINUE;
1872  PRINT_EVENT_INFO print_event_info;
1873  if (!print_event_info.init_ok())
1874  DBUG_RETURN(ERROR_STOP);
1875  /*
1876  Set safe delimiter, to dump things
1877  like CREATE PROCEDURE safely
1878  */
1879  if (!raw_mode)
1880  {
1881  fprintf(result_file, "DELIMITER /*!*/;\n");
1882  }
1883  strmov(print_event_info.delimiter, "/*!*/;");
1884 
1885  print_event_info.verbose= short_form ? 0 : verbose;
1886 
1887  switch (opt_remote_proto)
1888  {
1889  case BINLOG_LOCAL:
1890  rc= dump_local_log_entries(&print_event_info, logname);
1891  break;
1892  case BINLOG_DUMP_NON_GTID:
1893  case BINLOG_DUMP_GTID:
1894  rc= dump_remote_log_entries(&print_event_info, logname);
1895  break;
1896  default:
1897  DBUG_ASSERT(0);
1898  break;
1899  }
1900 
1901  if (buff_ev.elements > 0)
1902  warning("The range of printed events ends with an Intvar_event, "
1903  "Rand_event or User_var_event with no matching Query_log_event. "
1904  "This might be because the last statement was not fully written "
1905  "to the log, or because you are using a --stop-position or "
1906  "--stop-datetime that refers to an event in the middle of a "
1907  "statement. The event(s) from the partial statement have not been "
1908  "written to output. ");
1909 
1910  else if (print_event_info.have_unflushed_events)
1911  warning("The range of printed events ends with a row event or "
1912  "a table map event that does not have the STMT_END_F "
1913  "flag set. This might be because the last statement "
1914  "was not fully written to the log, or because you are "
1915  "using a --stop-position or --stop-datetime that refers "
1916  "to an event in the middle of a statement. The event(s) "
1917  "from the partial statement have not been written to output.");
1918 
1919  /* Set delimiter back to semicolon */
1920  if (!raw_mode)
1921  {
1922  if (print_event_info.skipped_event_in_transaction)
1923  fprintf(result_file, "COMMIT /* added by mysqlbinlog */%s\n", print_event_info.delimiter);
1924 
1925  fprintf(result_file, "DELIMITER ;\n");
1926  strmov(print_event_info.delimiter, ";");
1927  }
1928  DBUG_RETURN(rc);
1929 }
1930 
1931 
1942 static Exit_status check_master_version()
1943 {
1944  DBUG_ENTER("check_master_version");
1945  MYSQL_RES* res = 0;
1946  MYSQL_ROW row;
1947  const char* version;
1948 
1949  if (mysql_query(mysql, "SELECT VERSION()") ||
1950  !(res = mysql_store_result(mysql)))
1951  {
1952  error("Could not find server version: "
1953  "Query failed when checking master version: %s", mysql_error(mysql));
1954  DBUG_RETURN(ERROR_STOP);
1955  }
1956  if (!(row = mysql_fetch_row(res)))
1957  {
1958  error("Could not find server version: "
1959  "Master returned no rows for SELECT VERSION().");
1960  goto err;
1961  }
1962 
1963  if (!(version = row[0]))
1964  {
1965  error("Could not find server version: "
1966  "Master reported NULL for the version.");
1967  goto err;
1968  }
1969  /*
1970  Make a notice to the server that this client
1971  is checksum-aware. It does not need the first fake Rotate
1972  necessary checksummed.
1973  That preference is specified below.
1974  */
1975  if (mysql_query(mysql, "SET @master_binlog_checksum='NONE'"))
1976  {
1977  error("Could not notify master about checksum awareness."
1978  "Master returned '%s'", mysql_error(mysql));
1979  goto err;
1980  }
1981  delete glob_description_event;
1982  switch (*version) {
1983  case '3':
1984  glob_description_event= new Format_description_log_event(1);
1985  break;
1986  case '4':
1987  glob_description_event= new Format_description_log_event(3);
1988  break;
1989  case '5':
1990  /*
1991  The server is soon going to send us its Format_description log
1992  event, unless it is a 5.0 server with 3.23 or 4.0 binlogs.
1993  So we first assume that this is 4.0 (which is enough to read the
1994  Format_desc event if one comes).
1995  */
1996  glob_description_event= new Format_description_log_event(3);
1997  break;
1998  default:
1999  glob_description_event= NULL;
2000  error("Could not find server version: "
2001  "Master reported unrecognized MySQL version '%s'.", version);
2002  goto err;
2003  }
2004  if (!glob_description_event || !glob_description_event->is_valid())
2005  {
2006  error("Failed creating Format_description_log_event; out of memory?");
2007  goto err;
2008  }
2009 
2010  mysql_free_result(res);
2011  DBUG_RETURN(OK_CONTINUE);
2012 
2013 err:
2014  mysql_free_result(res);
2015  DBUG_RETURN(ERROR_STOP);
2016 }
2017 
2018 
2032 static Exit_status dump_remote_log_entries(PRINT_EVENT_INFO *print_event_info,
2033  const char* logname)
2034 {
2035  uchar *command_buffer= NULL;
2036  size_t command_size= 0;
2037  ulong len= 0;
2038  uint logname_len= 0;
2039  uint server_id= 0;
2040  NET* net= NULL;
2041  my_off_t old_off= start_position_mot;
2042  char fname[FN_REFLEN + 1];
2043  char log_file_name[FN_REFLEN + 1];
2044  Exit_status retval= OK_CONTINUE;
2045  enum enum_server_command command= COM_END;
2046 
2047  DBUG_ENTER("dump_remote_log_entries");
2048 
2049  fname[0]= log_file_name[0]= 0;
2050 
2051  /*
2052  Even if we already read one binlog (case of >=2 binlogs on command line),
2053  we cannot re-use the same connection as before, because it is now dead
2054  (COM_BINLOG_DUMP kills the thread when it finishes).
2055  */
2056  if ((retval= safe_connect()) != OK_CONTINUE)
2057  DBUG_RETURN(retval);
2058  net= &mysql->net;
2059 
2060  if ((retval= check_master_version()) != OK_CONTINUE)
2061  DBUG_RETURN(retval);
2062 
2063  /*
2064  Fake a server ID to log continously. This will show as a
2065  slave on the mysql server.
2066  */
2067  server_id= ((to_last_remote_log && stop_never) ? stop_never_server_id : 0);
2068  size_t tlen = strlen(logname);
2069  if (tlen > UINT_MAX)
2070  {
2071  error("Log name too long.");
2072  DBUG_RETURN(ERROR_STOP);
2073  }
2074  const uint BINLOG_NAME_INFO_SIZE= logname_len= tlen;
2075 
2076  if (opt_remote_proto == BINLOG_DUMP_NON_GTID)
2077  {
2078  command= COM_BINLOG_DUMP;
2079  size_t allocation_size= ::BINLOG_POS_OLD_INFO_SIZE +
2080  BINLOG_NAME_INFO_SIZE + ::BINLOG_FLAGS_INFO_SIZE +
2081  ::BINLOG_SERVER_ID_INFO_SIZE + 1;
2082  if (!(command_buffer= (uchar *) my_malloc(allocation_size, MYF(MY_WME))))
2083  {
2084  error("Got fatal error allocating memory.");
2085  DBUG_RETURN(ERROR_STOP);
2086  }
2087  uchar* ptr_buffer= command_buffer;
2088 
2089  /*
2090  COM_BINLOG_DUMP accepts only 4 bytes for the position, so
2091  we are forced to cast to uint32.
2092  */
2093  int4store(ptr_buffer, (uint32) start_position);
2094  ptr_buffer+= ::BINLOG_POS_OLD_INFO_SIZE;
2095  int2store(ptr_buffer, binlog_flags);
2096  ptr_buffer+= ::BINLOG_FLAGS_INFO_SIZE;
2097  int4store(ptr_buffer, server_id);
2098  ptr_buffer+= ::BINLOG_SERVER_ID_INFO_SIZE;
2099  memcpy(ptr_buffer, logname, BINLOG_NAME_INFO_SIZE);
2100  ptr_buffer+= BINLOG_NAME_INFO_SIZE;
2101 
2102  command_size= ptr_buffer - command_buffer;
2103  DBUG_ASSERT(command_size == (allocation_size - 1));
2104  }
2105  else
2106  {
2107  command= COM_BINLOG_DUMP_GTID;
2108 
2109  global_sid_lock->rdlock();
2110 
2111  // allocate buffer
2112  size_t encoded_data_size= gtid_set_excluded->get_encoded_length();
2113  size_t allocation_size=
2114  ::BINLOG_FLAGS_INFO_SIZE + ::BINLOG_SERVER_ID_INFO_SIZE +
2115  ::BINLOG_NAME_SIZE_INFO_SIZE + BINLOG_NAME_INFO_SIZE +
2116  ::BINLOG_POS_INFO_SIZE + ::BINLOG_DATA_SIZE_INFO_SIZE +
2117  encoded_data_size + 1;
2118  if (!(command_buffer= (uchar *) my_malloc(allocation_size, MYF(MY_WME))))
2119  {
2120  error("Got fatal error allocating memory.");
2121  global_sid_lock->unlock();
2122  DBUG_RETURN(ERROR_STOP);
2123  }
2124  uchar* ptr_buffer= command_buffer;
2125 
2126  int2store(ptr_buffer, binlog_flags);
2127  ptr_buffer+= ::BINLOG_FLAGS_INFO_SIZE;
2128  int4store(ptr_buffer, server_id);
2129  ptr_buffer+= ::BINLOG_SERVER_ID_INFO_SIZE;
2130  int4store(ptr_buffer, BINLOG_NAME_INFO_SIZE);
2131  ptr_buffer+= ::BINLOG_NAME_SIZE_INFO_SIZE;
2132  memcpy(ptr_buffer, logname, BINLOG_NAME_INFO_SIZE);
2133  ptr_buffer+= BINLOG_NAME_INFO_SIZE;
2134  int8store(ptr_buffer, start_position);
2135  ptr_buffer+= ::BINLOG_POS_INFO_SIZE;
2136  int4store(ptr_buffer, encoded_data_size);
2137  ptr_buffer+= ::BINLOG_DATA_SIZE_INFO_SIZE;
2138  gtid_set_excluded->encode(ptr_buffer);
2139  ptr_buffer+= encoded_data_size;
2140 
2141  global_sid_lock->unlock();
2142 
2143  command_size= ptr_buffer - command_buffer;
2144  DBUG_ASSERT(command_size == (allocation_size - 1));
2145  }
2146 
2147  if (simple_command(mysql, command, command_buffer, command_size, 1))
2148  {
2149  error("Got fatal error sending the log dump command.");
2150  my_free(command_buffer);
2151  DBUG_RETURN(ERROR_STOP);
2152  }
2153  my_free(command_buffer);
2154 
2155  for (;;)
2156  {
2157  const char *error_msg= NULL;
2158  Log_event *ev= NULL;
2159  Log_event_type type= UNKNOWN_EVENT;
2160 
2161  len= cli_safe_read(mysql);
2162  if (len == packet_error)
2163  {
2164  error("Got error reading packet from server: %s", mysql_error(mysql));
2165  DBUG_RETURN(ERROR_STOP);
2166  }
2167  if (len < 8 && net->read_pos[0] == 254)
2168  break; // end of data
2169  DBUG_PRINT("info",( "len: %lu net->read_pos[5]: %d\n",
2170  len, net->read_pos[5]));
2171  /*
2172  In raw mode We only need the full event details if it is a
2173  ROTATE_EVENT or FORMAT_DESCRIPTION_EVENT
2174  */
2175 
2176  type= (Log_event_type) net->read_pos[1 + EVENT_TYPE_OFFSET];
2177 
2178  /*
2179  Ignore HEARBEAT events. They can show up if mysqlbinlog is
2180  running with:
2181 
2182  --read-from-remote-server
2183  --read-from-remote-master=BINLOG-DUMP-GTIDS'
2184  --stop-never
2185  --stop-never-slave-server-id
2186 
2187  i.e., acting as a fake slave.
2188  */
2189  if (type == HEARTBEAT_LOG_EVENT)
2190  continue;
2191 
2192  if (!raw_mode || (type == ROTATE_EVENT) || (type == FORMAT_DESCRIPTION_EVENT))
2193  {
2194  if (!(ev= Log_event::read_log_event((const char*) net->read_pos + 1 ,
2195  len - 1, &error_msg,
2196  glob_description_event,
2197  opt_verify_binlog_checksum)))
2198  {
2199  error("Could not construct log event object: %s", error_msg);
2200  DBUG_RETURN(ERROR_STOP);
2201  }
2202  /*
2203  If reading from a remote host, ensure the temp_buf for the
2204  Log_event class is pointing to the incoming stream.
2205  */
2206  ev->register_temp_buf((char *) net->read_pos + 1);
2207  }
2208  if (raw_mode || (type != LOAD_EVENT))
2209  {
2210  /*
2211  If this is a Rotate event, maybe it's the end of the requested binlog;
2212  in this case we are done (stop transfer).
2213  This is suitable for binlogs, not relay logs (but for now we don't read
2214  relay logs remotely because the server is not able to do that). If one
2215  day we read relay logs remotely, then we will have a problem with the
2216  detection below: relay logs contain Rotate events which are about the
2217  binlogs, so which would trigger the end-detection below.
2218  */
2219  if (type == ROTATE_EVENT)
2220  {
2221  Rotate_log_event *rev= (Rotate_log_event *)ev;
2222  /*
2223  If this is a fake Rotate event, and not about our log, we can stop
2224  transfer. If this a real Rotate event (so it's not about our log,
2225  it's in our log describing the next log), we print it (because it's
2226  part of our log) and then we will stop when we receive the fake one
2227  soon.
2228  */
2229  if (raw_mode)
2230  {
2231  if (output_file != 0)
2232  {
2233  my_snprintf(log_file_name, sizeof(log_file_name), "%s%s",
2234  output_file, rev->new_log_ident);
2235  }
2236  else
2237  {
2238  strmov(log_file_name, rev->new_log_ident);
2239  }
2240  }
2241 
2242  if (rev->when.tv_sec == 0)
2243  {
2244  if (!to_last_remote_log)
2245  {
2246  if ((rev->ident_len != logname_len) ||
2247  memcmp(rev->new_log_ident, logname, logname_len))
2248  {
2249  DBUG_RETURN(OK_CONTINUE);
2250  }
2251  /*
2252  Otherwise, this is a fake Rotate for our log, at the very
2253  beginning for sure. Skip it, because it was not in the original
2254  log. If we are running with to_last_remote_log, we print it,
2255  because it serves as a useful marker between binlogs then.
2256  */
2257  continue;
2258  }
2259  /*
2260  Reset the value of '# at pos' field shown against first event of
2261  next binlog file (fake rotate) picked by mysqlbinlog --to-last-log
2262  */
2263  old_off= start_position_mot;
2264  len= 1; // fake Rotate, so don't increment old_off
2265  }
2266  }
2267  else if (type == FORMAT_DESCRIPTION_EVENT)
2268  {
2269  /*
2270  This could be an fake Format_description_log_event that server
2271  (5.0+) automatically sends to a slave on connect, before sending
2272  a first event at the requested position. If this is the case,
2273  don't increment old_off. Real Format_description_log_event always
2274  starts from BIN_LOG_HEADER_SIZE position.
2275  */
2276  // fake event when not in raw mode, don't increment old_off
2277  if ((old_off != BIN_LOG_HEADER_SIZE) && (!raw_mode))
2278  len= 1;
2279  if (raw_mode)
2280  {
2281  if (result_file && (result_file != stdout))
2282  my_fclose(result_file, MYF(0));
2283  if (!(result_file = my_fopen(log_file_name, O_WRONLY | O_BINARY,
2284  MYF(MY_WME))))
2285  {
2286  error("Could not create log file '%s'", log_file_name);
2287  DBUG_RETURN(ERROR_STOP);
2288  }
2289  my_fwrite(result_file, (const uchar*) BINLOG_MAGIC,
2290  BIN_LOG_HEADER_SIZE, MYF(0));
2291  /*
2292  Need to handle these events correctly in raw mode too
2293  or this could get messy
2294  */
2295  delete glob_description_event;
2296  glob_description_event= (Format_description_log_event*) ev;
2297  print_event_info->common_header_len= glob_description_event->common_header_len;
2298  ev->temp_buf= 0;
2299  ev= 0;
2300  }
2301  }
2302 
2303  if (type == LOAD_EVENT)
2304  {
2305  DBUG_ASSERT(raw_mode);
2306  warning("Attempting to load a remote pre-4.0 binary log that contains "
2307  "LOAD DATA INFILE statements. The file will not be copied from "
2308  "the remote server. ");
2309  }
2310 
2311  if (raw_mode)
2312  {
2313  my_fwrite(result_file, net->read_pos + 1 , len - 1, MYF(0));
2314  if (ev)
2315  {
2316  ev->temp_buf=0;
2317  delete ev;
2318  }
2319  }
2320  else
2321  {
2322  retval= process_event(print_event_info, ev, old_off, logname);
2323  }
2324 
2325  if (retval != OK_CONTINUE)
2326  DBUG_RETURN(retval);
2327  }
2328  else
2329  {
2330  Load_log_event *le= (Load_log_event*)ev;
2331  const char *old_fname= le->fname;
2332  uint old_len= le->fname_len;
2333  File file;
2334 
2335  if ((file= load_processor.prepare_new_file_for_old_format(le,fname)) < 0)
2336  DBUG_RETURN(ERROR_STOP);
2337 
2338  retval= process_event(print_event_info, ev, old_off, logname);
2339  if (retval != OK_CONTINUE)
2340  {
2341  my_close(file,MYF(MY_WME));
2342  DBUG_RETURN(retval);
2343  }
2344  retval= load_processor.load_old_format_file(net,old_fname,old_len,file);
2345  my_close(file,MYF(MY_WME));
2346  if (retval != OK_CONTINUE)
2347  DBUG_RETURN(retval);
2348  }
2349  /*
2350  Let's adjust offset for remote log as for local log to produce
2351  similar text and to have --stop-position to work identically.
2352  */
2353  old_off+= len-1;
2354  }
2355 
2356  DBUG_RETURN(OK_CONTINUE);
2357 }
2358 
2359 
2386 static Exit_status check_header(IO_CACHE* file,
2387  PRINT_EVENT_INFO *print_event_info,
2388  const char* logname)
2389 {
2390  DBUG_ENTER("check_header");
2391  uchar header[BIN_LOG_HEADER_SIZE];
2392  uchar buf[PROBE_HEADER_LEN];
2393  my_off_t tmp_pos, pos;
2394  MY_STAT my_file_stat;
2395 
2396  delete glob_description_event;
2397  if (!(glob_description_event= new Format_description_log_event(3)))
2398  {
2399  error("Failed creating Format_description_log_event; out of memory?");
2400  DBUG_RETURN(ERROR_STOP);
2401  }
2402 
2403  pos= my_b_tell(file);
2404 
2405  /* fstat the file to check if the file is a regular file. */
2406  if (my_fstat(file->file, &my_file_stat, MYF(0)) == -1)
2407  {
2408  error("Unable to stat the file.");
2409  DBUG_RETURN(ERROR_STOP);
2410  }
2411  if ((my_file_stat.st_mode & S_IFMT) == S_IFREG)
2412  my_b_seek(file, (my_off_t)0);
2413 
2414  if (my_b_read(file, header, sizeof(header)))
2415  {
2416  error("Failed reading header; probably an empty file.");
2417  DBUG_RETURN(ERROR_STOP);
2418  }
2419  if (memcmp(header, BINLOG_MAGIC, sizeof(header)))
2420  {
2421  error("File is not a binary log file.");
2422  DBUG_RETURN(ERROR_STOP);
2423  }
2424 
2425  /*
2426  Imagine we are running with --start-position=1000. We still need
2427  to know the binlog format's. So we still need to find, if there is
2428  one, the Format_desc event, or to know if this is a 3.23
2429  binlog. So we need to first read the first events of the log,
2430  those around offset 4. Even if we are reading a 3.23 binlog from
2431  the start (no --start-position): we need to know the header length
2432  (which is 13 in 3.23, 19 in 4.x) to be able to successfully print
2433  the first event (Start_log_event_v3). So even in this case, we
2434  need to "probe" the first bytes of the log *before* we do a real
2435  read_log_event(). Because read_log_event() needs to know the
2436  header's length to work fine.
2437  */
2438  for(;;)
2439  {
2440  tmp_pos= my_b_tell(file); /* should be 4 the first time */
2441  if (my_b_read(file, buf, sizeof(buf)))
2442  {
2443  if (file->error)
2444  {
2445  error("Could not read entry at offset %llu: "
2446  "Error in log format or read error.", (ulonglong)tmp_pos);
2447  DBUG_RETURN(ERROR_STOP);
2448  }
2449  /*
2450  Otherwise this is just EOF : this log currently contains 0-2
2451  events. Maybe it's going to be filled in the next
2452  milliseconds; then we are going to have a problem if this a
2453  3.23 log (imagine we are locally reading a 3.23 binlog which
2454  is being written presently): we won't know it in
2455  read_log_event() and will fail(). Similar problems could
2456  happen with hot relay logs if --start-position is used (but a
2457  --start-position which is posterior to the current size of the log).
2458  These are rare problems anyway (reading a hot log + when we
2459  read the first events there are not all there yet + when we
2460  read a bit later there are more events + using a strange
2461  --start-position).
2462  */
2463  break;
2464  }
2465  else
2466  {
2467  DBUG_PRINT("info",("buf[EVENT_TYPE_OFFSET=%d]=%d",
2468  EVENT_TYPE_OFFSET, buf[EVENT_TYPE_OFFSET]));
2469  /* always test for a Start_v3, even if no --start-position */
2470  if (buf[EVENT_TYPE_OFFSET] == START_EVENT_V3)
2471  {
2472  /* This is 3.23 or 4.x */
2473  if (uint4korr(buf + EVENT_LEN_OFFSET) <
2474  (LOG_EVENT_MINIMAL_HEADER_LEN + START_V3_HEADER_LEN))
2475  {
2476  /* This is 3.23 (format 1) */
2477  delete glob_description_event;
2478  if (!(glob_description_event= new Format_description_log_event(1)))
2479  {
2480  error("Failed creating Format_description_log_event; "
2481  "out of memory?");
2482  DBUG_RETURN(ERROR_STOP);
2483  }
2484  }
2485  break;
2486  }
2487  else if (tmp_pos >= start_position)
2488  break;
2489  else if (buf[EVENT_TYPE_OFFSET] == FORMAT_DESCRIPTION_EVENT)
2490  {
2491  /* This is 5.0 */
2492  Format_description_log_event *new_description_event;
2493  my_b_seek(file, tmp_pos); /* seek back to event's start */
2494  if (!(new_description_event= (Format_description_log_event*)
2495  Log_event::read_log_event(file, glob_description_event,
2496  opt_verify_binlog_checksum)))
2497  /* EOF can't be hit here normally, so it's a real error */
2498  {
2499  error("Could not read a Format_description_log_event event at "
2500  "offset %llu; this could be a log format error or read error.",
2501  (ulonglong)tmp_pos);
2502  DBUG_RETURN(ERROR_STOP);
2503  }
2504  if (opt_base64_output_mode == BASE64_OUTPUT_AUTO)
2505  {
2506  /*
2507  process_event will delete *description_event and set it to
2508  the new one, so we should not do it ourselves in this
2509  case.
2510  */
2511  Exit_status retval= process_event(print_event_info,
2512  new_description_event, tmp_pos,
2513  logname);
2514  if (retval != OK_CONTINUE)
2515  DBUG_RETURN(retval);
2516  }
2517  else
2518  {
2519  delete glob_description_event;
2520  glob_description_event= new_description_event;
2521  }
2522  DBUG_PRINT("info",("Setting description_event"));
2523  }
2524  else if (buf[EVENT_TYPE_OFFSET] == ROTATE_EVENT)
2525  {
2526  Log_event *ev;
2527  my_b_seek(file, tmp_pos); /* seek back to event's start */
2528  if (!(ev= Log_event::read_log_event(file, glob_description_event,
2529  opt_verify_binlog_checksum)))
2530  {
2531  /* EOF can't be hit here normally, so it's a real error */
2532  error("Could not read a Rotate_log_event event at offset %llu;"
2533  " this could be a log format error or read error.",
2534  (ulonglong)tmp_pos);
2535  DBUG_RETURN(ERROR_STOP);
2536  }
2537  delete ev;
2538  }
2539  else
2540  break;
2541  }
2542  }
2543  my_b_seek(file, pos);
2544  DBUG_RETURN(OK_CONTINUE);
2545 }
2546 
2547 
2561 static Exit_status dump_local_log_entries(PRINT_EVENT_INFO *print_event_info,
2562  const char* logname)
2563 {
2564  File fd = -1;
2565  IO_CACHE cache,*file= &cache;
2566  uchar tmp_buff[BIN_LOG_HEADER_SIZE];
2567  Exit_status retval= OK_CONTINUE;
2568 
2569  if (logname && strcmp(logname, "-") != 0)
2570  {
2571  /* read from normal file */
2572  if ((fd = my_open(logname, O_RDONLY | O_BINARY, MYF(MY_WME))) < 0)
2573  return ERROR_STOP;
2574  if (init_io_cache(file, fd, 0, READ_CACHE, start_position_mot, 0,
2575  MYF(MY_WME | MY_NABP)))
2576  {
2577  my_close(fd, MYF(MY_WME));
2578  return ERROR_STOP;
2579  }
2580  if ((retval= check_header(file, print_event_info, logname)) != OK_CONTINUE)
2581  goto end;
2582  }
2583  else
2584  {
2585  /* read from stdin */
2586  /*
2587  Windows opens stdin in text mode by default. Certain characters
2588  such as CTRL-Z are interpeted as events and the read() method
2589  will stop. CTRL-Z is the EOF marker in Windows. to get past this
2590  you have to open stdin in binary mode. Setmode() is used to set
2591  stdin in binary mode. Errors on setting this mode result in
2592  halting the function and printing an error message to stderr.
2593  */
2594 #if defined (__WIN__) || (_WIN64)
2595  if (_setmode(fileno(stdin), O_BINARY) == -1)
2596  {
2597  error("Could not set binary mode on stdin.");
2598  return ERROR_STOP;
2599  }
2600 #endif
2601  if (init_io_cache(file, my_fileno(stdin), 0, READ_CACHE, (my_off_t) 0,
2602  0, MYF(MY_WME | MY_NABP | MY_DONT_CHECK_FILESIZE)))
2603  {
2604  error("Failed to init IO cache.");
2605  return ERROR_STOP;
2606  }
2607  if ((retval= check_header(file, print_event_info, logname)) != OK_CONTINUE)
2608  goto end;
2609  if (start_position)
2610  {
2611  /* skip 'start_position' characters from stdin */
2612  uchar buff[IO_SIZE];
2613  my_off_t length,tmp;
2614  for (length= start_position_mot ; length > 0 ; length-=tmp)
2615  {
2616  tmp= min<size_t>(length, sizeof(buff));
2617  if (my_b_read(file, buff, (uint) tmp))
2618  {
2619  error("Failed reading from file.");
2620  goto err;
2621  }
2622  }
2623  }
2624  }
2625 
2626  if (!glob_description_event || !glob_description_event->is_valid())
2627  {
2628  error("Invalid Format_description log event; could be out of memory.");
2629  goto err;
2630  }
2631 
2632  if (!start_position && my_b_read(file, tmp_buff, BIN_LOG_HEADER_SIZE))
2633  {
2634  error("Failed reading from file.");
2635  goto err;
2636  }
2637  for (;;)
2638  {
2639  char llbuff[21];
2640  my_off_t old_off = my_b_tell(file);
2641 
2642  Log_event* ev = Log_event::read_log_event(file, glob_description_event,
2643  opt_verify_binlog_checksum);
2644  if (!ev)
2645  {
2646  /*
2647  if binlog wasn't closed properly ("in use" flag is set) don't complain
2648  about a corruption, but treat it as EOF and move to the next binlog.
2649  */
2650  if (glob_description_event->flags & LOG_EVENT_BINLOG_IN_USE_F)
2651  file->error= 0;
2652  else if (file->error)
2653  {
2654  error("Could not read entry at offset %s: "
2655  "Error in log format or read error.",
2656  llstr(old_off,llbuff));
2657  goto err;
2658  }
2659  // file->error == 0 means EOF, that's OK, we break in this case
2660  goto end;
2661  }
2662  if ((retval= process_event(print_event_info, ev, old_off, logname)) !=
2663  OK_CONTINUE)
2664  goto end;
2665  }
2666 
2667  /* NOTREACHED */
2668 
2669 err:
2670  retval= ERROR_STOP;
2671 
2672 end:
2673  if (fd >= 0)
2674  my_close(fd, MYF(MY_WME));
2675  /*
2676  Since the end_io_cache() writes to the
2677  file errors may happen.
2678  */
2679  if (end_io_cache(file))
2680  retval= ERROR_STOP;
2681 
2682  return retval;
2683 }
2684 
2685 /* Post processing of arguments to check for conflicts and other setups */
2686 static int args_post_process(void)
2687 {
2688  DBUG_ENTER("args_post_process");
2689 
2690  if (opt_remote_alias && opt_remote_proto != BINLOG_DUMP_NON_GTID)
2691  {
2692  error("The option read-from-remote-server cannot be used when "
2693  "read-from-remote-master is defined and is not equal to "
2694  "BINLOG-DUMP-NON-GTIDS");
2695  DBUG_RETURN(ERROR_STOP);
2696  }
2697 
2698  if (raw_mode)
2699  {
2700  if (one_database)
2701  warning("The --database option is ignored with --raw mode");
2702 
2703  if (opt_remote_proto == BINLOG_LOCAL)
2704  {
2705  error("You need to set --read-from-remote-master={BINLOG_DUMP_NON_GTID, "
2706  "BINLOG_DUMP_GTID} for --raw mode");
2707  DBUG_RETURN(ERROR_STOP);
2708  }
2709 
2710  if (opt_remote_proto == BINLOG_DUMP_NON_GTID &&
2711  (opt_exclude_gtids_str != NULL || opt_include_gtids_str != NULL))
2712  {
2713  error("You cannot set --exclude-gtids or --include-gtids for --raw-mode "
2714  "when --read-from-remote-master=BINLOG_DUMP_NON_GTID");
2715  DBUG_RETURN(ERROR_STOP);
2716  }
2717 
2718  if (opt_remote_proto == BINLOG_DUMP_GTID && opt_include_gtids_str != NULL)
2719  {
2720  error("You cannot set --include-gtids for --raw-mode "
2721  "when --read-from-remote-master=BINLOG_DUMP_GTID for");
2722  DBUG_RETURN(ERROR_STOP);
2723  }
2724 
2725  if (stop_position != (ulonglong)(~(my_off_t)0))
2726  warning("The --stop-position option is ignored in raw mode");
2727 
2728  if (stop_datetime != MY_TIME_T_MAX)
2729  warning("The --stop-datetime option is ignored in raw mode");
2730  }
2731  else if (output_file)
2732  {
2733  if (!(result_file = my_fopen(output_file, O_WRONLY | O_BINARY, MYF(MY_WME))))
2734  {
2735  error("Could not create log file '%s'", output_file);
2736  DBUG_RETURN(ERROR_STOP);
2737  }
2738  }
2739 
2740  global_sid_lock->rdlock();
2741 
2742  if (opt_include_gtids_str != NULL)
2743  {
2744  if (gtid_set_included->add_gtid_text(opt_include_gtids_str) !=
2745  RETURN_STATUS_OK)
2746  {
2747  error("Could not configure --include-gtids '%s'", opt_include_gtids_str);
2748  global_sid_lock->unlock();
2749  DBUG_RETURN(ERROR_STOP);
2750  }
2751  }
2752 
2753  if (opt_exclude_gtids_str != NULL)
2754  {
2755  if (gtid_set_excluded->add_gtid_text(opt_exclude_gtids_str) !=
2756  RETURN_STATUS_OK)
2757  {
2758  error("Could not configure --exclude-gtids '%s'", opt_exclude_gtids_str);
2759  global_sid_lock->unlock();
2760  DBUG_RETURN(ERROR_STOP);
2761  }
2762  }
2763 
2764  global_sid_lock->unlock();
2765 
2766  DBUG_RETURN(OK_CONTINUE);
2767 }
2768 
2773 inline void gtid_client_cleanup()
2774 {
2775  delete global_sid_lock;
2776  delete global_sid_map;
2777  delete gtid_set_excluded;
2778  delete gtid_set_included;
2779  global_sid_lock= NULL;
2780  global_sid_map= NULL;
2781  gtid_set_excluded= NULL;
2782  gtid_set_included= NULL;
2783 }
2784 
2791 inline bool gtid_client_init()
2792 {
2793  bool res=
2794  (!(global_sid_lock= new Checkable_rwlock) ||
2795  !(global_sid_map= new Sid_map(global_sid_lock)) ||
2796  !(gtid_set_excluded= new Gtid_set(global_sid_map)) ||
2797  !(gtid_set_included= new Gtid_set(global_sid_map)));
2798  if (res)
2799  {
2800  gtid_client_cleanup();
2801  }
2802  return res;
2803 }
2804 
2805 int main(int argc, char** argv)
2806 {
2807  char **defaults_argv;
2808  Exit_status retval= OK_CONTINUE;
2809  ulonglong save_stop_position;
2810  MY_INIT(argv[0]);
2811  DBUG_ENTER("main");
2812  DBUG_PROCESS(argv[0]);
2813 
2814  my_init_time(); // for time functions
2815  /*
2816  A pointer of type Log_event can point to
2817  INTVAR
2818  USER_VAR
2819  RANDOM
2820  events, when we allocate a element of sizeof(Log_event*)
2821  for the DYNAMIC_ARRAY.
2822  */
2823 
2824  if((my_init_dynamic_array(&buff_ev, sizeof(buff_event_info),
2825  INTVAR_DYNAMIC_INIT, INTVAR_DYNAMIC_INCR)))
2826  exit(1);
2827 
2828  my_getopt_use_args_separator= TRUE;
2829  if (load_defaults("my", load_default_groups, &argc, &argv))
2830  exit(1);
2831  my_getopt_use_args_separator= FALSE;
2832  defaults_argv= argv;
2833 
2834  parse_args(&argc, &argv);
2835 
2836  if (!argc)
2837  {
2838  usage();
2839  free_defaults(defaults_argv);
2840  my_end(my_end_arg);
2841  exit(1);
2842  }
2843 
2844  if (gtid_client_init())
2845  {
2846  error("Could not initialize GTID structuress.");
2847  exit(1);
2848  }
2849 
2850  /* Check for argument conflicts and do any post-processing */
2851  if (args_post_process() == ERROR_STOP)
2852  exit(1);
2853 
2854  if (opt_base64_output_mode == BASE64_OUTPUT_UNSPEC)
2855  opt_base64_output_mode= BASE64_OUTPUT_AUTO;
2856 
2857  opt_server_id_mask = (opt_server_id_bits == 32)?
2858  ~ ulong(0) : (1 << opt_server_id_bits) -1;
2859 
2860  my_set_max_open_files(open_files_limit);
2861 
2862  MY_TMPDIR tmpdir;
2863  tmpdir.list= 0;
2864  if (!dirname_for_local_load)
2865  {
2866  if (init_tmpdir(&tmpdir, 0))
2867  exit(1);
2868  dirname_for_local_load= my_strdup(my_tmpdir(&tmpdir), MY_WME);
2869  }
2870 
2871  if (load_processor.init())
2872  exit(1);
2873  if (dirname_for_local_load)
2874  load_processor.init_by_dir_name(dirname_for_local_load);
2875  else
2876  load_processor.init_by_cur_dir();
2877 
2878  if (!raw_mode)
2879  {
2880  fprintf(result_file, "/*!50530 SET @@SESSION.PSEUDO_SLAVE_MODE=1*/;\n");
2881 
2882  fprintf(result_file,
2883  "/*!40019 SET @@session.max_insert_delayed_threads=0*/;\n");
2884 
2885  if (disable_log_bin)
2886  fprintf(result_file,
2887  "/*!32316 SET @OLD_SQL_LOG_BIN=@@SQL_LOG_BIN, SQL_LOG_BIN=0*/;\n");
2888 
2889  /*
2890  In mysqlbinlog|mysql, don't want mysql to be disconnected after each
2891  transaction (which would be the case with GLOBAL.COMPLETION_TYPE==2).
2892  */
2893  fprintf(result_file,
2894  "/*!50003 SET @OLD_COMPLETION_TYPE=@@COMPLETION_TYPE,"
2895  "COMPLETION_TYPE=0*/;\n");
2896 
2897  if (charset)
2898  fprintf(result_file,
2899  "\n/*!40101 SET @OLD_CHARACTER_SET_CLIENT=@@CHARACTER_SET_CLIENT */;"
2900  "\n/*!40101 SET @OLD_CHARACTER_SET_RESULTS=@@CHARACTER_SET_RESULTS */;"
2901  "\n/*!40101 SET @OLD_COLLATION_CONNECTION=@@COLLATION_CONNECTION */;"
2902  "\n/*!40101 SET NAMES %s */;\n", charset);
2903  }
2904 
2905  for (save_stop_position= stop_position, stop_position= ~(my_off_t)0 ;
2906  (--argc >= 0) ; )
2907  {
2908  if (argc == 0) // last log, --stop-position applies
2909  stop_position= save_stop_position;
2910  if ((retval= dump_log_entries(*argv++)) != OK_CONTINUE)
2911  break;
2912 
2913  // For next log, --start-position does not apply
2914  start_position= BIN_LOG_HEADER_SIZE;
2915  }
2916 
2917  if (!raw_mode)
2918  {
2919  /*
2920  Issue a ROLLBACK in case the last printed binlog was crashed and had half
2921  of transaction.
2922  */
2923  fprintf(result_file,
2924  "# End of log file\nROLLBACK /* added by mysqlbinlog */;\n"
2925  "/*!50003 SET COMPLETION_TYPE=@OLD_COMPLETION_TYPE*/;\n");
2926  if (disable_log_bin)
2927  fprintf(result_file, "/*!32316 SET SQL_LOG_BIN=@OLD_SQL_LOG_BIN*/;\n");
2928 
2929  if (charset)
2930  fprintf(result_file,
2931  "/*!40101 SET CHARACTER_SET_CLIENT=@OLD_CHARACTER_SET_CLIENT */;\n"
2932  "/*!40101 SET CHARACTER_SET_RESULTS=@OLD_CHARACTER_SET_RESULTS */;\n"
2933  "/*!40101 SET COLLATION_CONNECTION=@OLD_COLLATION_CONNECTION */;\n");
2934 
2935  fprintf(result_file, "/*!50530 SET @@SESSION.PSEUDO_SLAVE_MODE=0*/;\n");
2936  }
2937 
2938  if (tmpdir.list)
2939  free_tmpdir(&tmpdir);
2940  if (result_file && (result_file != stdout))
2941  my_fclose(result_file, MYF(0));
2942  cleanup();
2943 
2944  if (defaults_argv)
2945  free_defaults(defaults_argv);
2946  my_free_open_file_info();
2947  load_processor.destroy();
2948  /* We cannot free DBUG, it is used in global destructors after exit(). */
2949  my_end(my_end_arg | MY_DONT_FREE_DBUG);
2950  gtid_client_cleanup();
2951 
2952  exit(retval == ERROR_STOP ? 1 : 0);
2953  /* Keep compilers happy. */
2954  DBUG_RETURN(retval == ERROR_STOP ? 1 : 0);
2955 }
2956 
2957 /*
2958  We must include this here as it's compiled with different options for
2959  the server
2960 */
2961 
2962 #include "decimal.c"
2963 #include "my_decimal.cc"
2964 #include "log_event.cc"
2965 #include "log_event_old.cc"
2966 #include "rpl_utility.cc"
2967 #include "rpl_gtid_sid_map.cc"
2968 #include "rpl_gtid_misc.cc"
2969 #include "uuid.cc"
2970 #include "rpl_gtid_set.cc"
2971 #include "rpl_gtid_specification.cc"
2972 #include "rpl_tblmap.cc"