My Project
rpl_rli.h
00001 /* Copyright (c) 2005, 2015, Oracle and/or its affiliates. All rights reserved.
00002 
00003    This program is free software; you can redistribute it and/or modify
00004    it under the terms of the GNU General Public License as published by
00005    the Free Software Foundation; version 2 of the License.
00006 
00007    This program is distributed in the hope that it will be useful,
00008    but WITHOUT ANY WARRANTY; without even the implied warranty of
00009    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00010    GNU General Public License for more details.
00011 
00012    You should have received a copy of the GNU General Public License
00013    along with this program; if not, write to the Free Software Foundation,
00014    51 Franklin Street, Suite 500, Boston, MA 02110-1335 USA */
00015 
00016 #ifndef RPL_RLI_H
00017 #define RPL_RLI_H
00018 
00019 #include "sql_priv.h"
00020 #include "rpl_info.h"
00021 #include "rpl_utility.h"
00022 #include "rpl_tblmap.h"
00023 #include "rpl_reporting.h"
00024 #include "rpl_utility.h"
00025 #include "log.h"                         /* LOG_INFO */
00026 #include "binlog.h"                      /* MYSQL_BIN_LOG */
00027 #include "sql_class.h"                   /* THD */
00028 
00029 struct RPL_TABLE_LIST;
00030 class Master_info;
00031 extern uint sql_slave_skip_counter;
00032 
00033 /*******************************************************************************
00034 Replication SQL Thread
00035 
00036 Relay_log_info contains:
00037   - the current relay log
00038   - the current relay log offset
00039   - master log name
00040   - master log sequence corresponding to the last update
00041   - misc information specific to the SQL thread
00042 
00043 Relay_log_info is initialized from a repository, i.e. table or file, if there is
00044 one. Otherwise, data members are intialized with defaults by calling
00045 init_relay_log_info().
00046 
00047 The relay.info table/file shall be updated whenever: (i) the relay log file
00048 is rotated, (ii) SQL Thread is stopped, (iii) while processing a Xid_log_event,
00049 (iv) after a Query_log_event (i.e. commit or rollback) and (v) after processing
00050 any statement written to the binary log without a transaction context.
00051 
00052 The Xid_log_event is a commit for transactional engines and must be handled
00053 differently to provide reliability/data integrity. In this case, positions
00054 are updated within the context of the current transaction. So
00055 
00056   . If the relay.info is stored in a transactional repository and the server
00057   crashes before successfully committing the transaction the changes to the
00058   position table will be rolled back along with the data.
00059 
00060   . If the relay.info is stored in a non-transactional repository, for instance,
00061   a file or a system table created using MyIsam, and the server crashes before
00062   successfully committing the transaction the changes to the position table
00063   will not be rolled back but data will.
00064 
00065 In particular, when there are mixed transactions, i.e a transaction that updates
00066 both transaction and non-transactional engines, the Xid_log_event is still used
00067 but reliability/data integrity cannot be achieved as we shall explain in what
00068 follows.
00069 
00070 Changes to non-transactional engines, such as MyIsam, cannot be rolled back if a
00071 failure happens. For that reason, there is no point in updating the positions
00072 within the boundaries of any on-going transaction. This is true for both commit
00073 and rollback. If a failure happens after processing the pseudo-transaction but
00074 before updating the positions, the transaction will be re-executed when the
00075 slave is up most likely causing an error that needs to be manually circumvented.
00076 This is a well-known issue when non-transactional statements are executed.
00077 
00078 Specifically, if rolling back any transaction, positions are updated outside the
00079 transaction boundaries. However, there may be a problem in this scenario even
00080 when only transactional engines are updated. This happens because if there is a
00081 rollback and such transaction is written to the binary log, a non-transactional
00082 engine was updated or a temporary table was created or dropped within its
00083 boundaries.
00084 
00085 In particular, in both STATEMENT and MIXED logging formats, this happens because
00086 any temporary table is automatically dropped after a shutdown/startup.
00087 See BUG#26945 for further details.
00088 
00089 Statements written to the binary log outside the boundaries of a transaction are
00090 DDLs or maintenance commands which are not transactional. These means that they
00091 cannot be rolled back if a failure happens. In such cases, the positions are
00092 updated after processing the events. If a failure happens after processing the
00093 statement but before updating the positions, the statement will be
00094 re-executed when the slave is up most likely causing an error that needs to be
00095 manually circumvented. This is a well-known issue when non-transactional
00096 statements are executed.
00097 
00098 The --sync-relay-log-info does not have effect when a system table, either
00099 transactional or non-transactional is used.
00100 
00101 To correctly recovery from failures, one should combine transactional system
00102 tables along with the --relay-log-recovery.
00103 *******************************************************************************/
00104 class Relay_log_info : public Rpl_info
00105 {
00106   friend class Rpl_info_factory;
00107 
00108 public:
00112   enum enum_state_flag {
00114     IN_STMT,
00115 
00117     STATE_FLAGS_COUNT
00118   };
00119 
00120   /*
00121     The SQL thread owns one Relay_log_info, and each client that has
00122     executed a BINLOG statement owns one Relay_log_info. This function
00123     returns zero for the Relay_log_info object that belongs to the SQL
00124     thread and nonzero for Relay_log_info objects that belong to
00125     clients.
00126   */
00127   inline bool belongs_to_client()
00128   {
00129     DBUG_ASSERT(info_thd);
00130     return !info_thd->slave_thread;
00131   }
00132 
00133   /*
00134     If true, events with the same server id should be replicated. This
00135     field is set on creation of a relay log info structure by copying
00136     the value of ::replicate_same_server_id and can be overridden if
00137     necessary. For example of when this is done, check sql_binlog.cc,
00138     where the BINLOG statement can be used to execute "raw" events.
00139    */
00140   bool replicate_same_server_id;
00141 
00142   /*** The following variables can only be read when protect by data lock ****/
00143   /*
00144     cur_log_fd - file descriptor of the current read  relay log
00145   */
00146   File cur_log_fd;
00147   /*
00148     Protected with internal locks.
00149     Must get data_lock when resetting the logs.
00150   */
00151   MYSQL_BIN_LOG relay_log;
00152   LOG_INFO linfo;
00153 
00154   /*
00155    cur_log
00156      Pointer that either points at relay_log.get_log_file() or
00157      &rli->cache_buf, depending on whether the log is hot or there was
00158      the need to open a cold relay_log.
00159 
00160    cache_buf 
00161      IO_CACHE used when opening cold relay logs.
00162    */
00163   IO_CACHE cache_buf,*cur_log;
00164 
00165   /*
00166     Identifies when the recovery process is going on.
00167     See sql/slave.cc:init_recovery for further details.
00168   */
00169   bool is_relay_log_recovery;
00170 
00171   /* The following variables are safe to read any time */
00172 
00173   /*
00174     When we restart slave thread we need to have access to the previously
00175     created temporary tables. Modified only on init/end and by the SQL
00176     thread, read only by SQL thread.
00177   */
00178   TABLE *save_temporary_tables;
00179 
00180   /* parent Master_info structure */
00181   Master_info *mi;
00182 
00183   /*
00184     Needed to deal properly with cur_log getting closed and re-opened with
00185     a different log under our feet
00186   */
00187   uint32 cur_log_old_open_count;
00188 
00189   /*
00190     Let's call a group (of events) :
00191       - a transaction
00192       or
00193       - an autocommiting query + its associated events (INSERT_ID,
00194     TIMESTAMP...)
00195     We need these rli coordinates :
00196     - relay log name and position of the beginning of the group we currently are
00197     executing. Needed to know where we have to restart when replication has
00198     stopped in the middle of a group (which has been rolled back by the slave).
00199     - relay log name and position just after the event we have just
00200     executed. This event is part of the current group.
00201     Formerly we only had the immediately above coordinates, plus a 'pending'
00202     variable, but this dealt wrong with the case of a transaction starting on a
00203     relay log and finishing (commiting) on another relay log. Case which can
00204     happen when, for example, the relay log gets rotated because of
00205     max_binlog_size.
00206   */
00207 protected:
00208   char group_relay_log_name[FN_REFLEN];
00209   ulonglong group_relay_log_pos;
00210   char event_relay_log_name[FN_REFLEN];
00211   ulonglong event_relay_log_pos;
00212   ulonglong future_event_relay_log_pos;
00213 
00214   /*
00215      Original log name and position of the group we're currently executing
00216      (whose coordinates are group_relay_log_name/pos in the relay log)
00217      in the master's binlog. These concern the *group*, because in the master's
00218      binlog the log_pos that comes with each event is the position of the
00219      beginning of the group.
00220 
00221     Note: group_master_log_name, group_master_log_pos must only be
00222     written from the thread owning the Relay_log_info (SQL thread if
00223     !belongs_to_client(); client thread executing BINLOG statement if
00224     belongs_to_client()).
00225   */
00226   char group_master_log_name[FN_REFLEN];
00227   volatile my_off_t group_master_log_pos;
00228 
00229   /*
00230     When it commits, InnoDB internally stores the master log position it has
00231     processed so far; the position to store is the one of the end of the
00232     committing event (the COMMIT query event, or the event if in autocommit
00233     mode).
00234   */
00235 #if MYSQL_VERSION_ID < 40100
00236   ulonglong future_master_log_pos;
00237 #else
00238   ulonglong future_group_master_log_pos;
00239 #endif
00240 
00241 private:
00242   Gtid_set gtid_set;
00243   /* Last gtid retrieved by IO thread */
00244   Gtid last_retrieved_gtid;
00245 
00246 public:
00247   Gtid *get_last_retrieved_gtid() { return &last_retrieved_gtid; }
00248   void set_last_retrieved_gtid(Gtid gtid) { last_retrieved_gtid= gtid; }
00249   int add_logged_gtid(rpl_sidno sidno, rpl_gno gno)
00250   {
00251     int ret= 0;
00252     global_sid_lock->assert_some_lock();
00253     DBUG_ASSERT(sidno <= global_sid_map->get_max_sidno());
00254     gtid_set.ensure_sidno(sidno);
00255     if (gtid_set._add_gtid(sidno, gno) != RETURN_STATUS_OK)
00256       ret= 1;
00257     return ret;
00258   }
00259   const Gtid_set *get_gtid_set() const { return &gtid_set; }
00260 
00261   int init_relay_log_pos(const char* log,
00262                          ulonglong pos, bool need_data_lock,
00263                          const char** errmsg,
00264                          bool look_for_description_event);
00265 
00266   /*
00267     Handling of the relay_log_space_limit optional constraint.
00268     ignore_log_space_limit is used to resolve a deadlock between I/O and SQL
00269     threads, the SQL thread sets it to unblock the I/O thread and make it
00270     temporarily forget about the constraint.
00271   */
00272   ulonglong log_space_limit,log_space_total;
00273   bool ignore_log_space_limit;
00274 
00275   /*
00276     Used by the SQL thread to instructs the IO thread to rotate 
00277     the logs when the SQL thread needs to purge to release some
00278     disk space.
00279    */
00280   bool sql_force_rotate_relay;
00281 
00282   time_t last_master_timestamp;
00283 
00284   void clear_until_condition();
00285 
00290   void clear_sql_delay()
00291   {
00292     sql_delay= 0;
00293   }
00294 
00295   /*
00296     Needed for problems when slave stops and we want to restart it
00297     skipping one or more events in the master log that have caused
00298     errors, and have been manually applied by DBA already.
00299   */
00300   volatile uint32 slave_skip_counter;
00301   volatile ulong abort_pos_wait;        /* Incremented on change master */
00302   mysql_mutex_t log_space_lock;
00303   mysql_cond_t log_space_cond;
00304 
00305   /*
00306      Condition and its parameters from START SLAVE UNTIL clause.
00307      
00308      UNTIL condition is tested with is_until_satisfied() method that is
00309      called by exec_relay_log_event(). is_until_satisfied() caches the result
00310      of the comparison of log names because log names don't change very often;
00311      this cache is invalidated by parts of code which change log names with
00312      notify_*_log_name_updated() methods. (They need to be called only if SQL
00313      thread is running).
00314    */
00315   enum {UNTIL_NONE= 0, UNTIL_MASTER_POS, UNTIL_RELAY_POS,
00316         UNTIL_SQL_BEFORE_GTIDS, UNTIL_SQL_AFTER_GTIDS,
00317         UNTIL_SQL_AFTER_MTS_GAPS
00318 #ifndef DBUG_OFF
00319         , UNTIL_DONE
00320 #endif
00321 }
00322     until_condition;
00323   char until_log_name[FN_REFLEN];
00324   ulonglong until_log_pos;
00325   /* extension extracted from log_name and converted to int */
00326   ulong until_log_name_extension;
00333   Gtid_set until_sql_gtids;
00334   /*
00335     True if the current event is the first gtid event to be processed
00336     after executing START SLAVE UNTIL SQL_*_GTIDS.
00337   */
00338   bool until_sql_gtids_first_event;
00339   /* 
00340      Cached result of comparison of until_log_name and current log name
00341      -2 means unitialised, -1,0,1 are comarison results 
00342   */
00343   enum 
00344   { 
00345     UNTIL_LOG_NAMES_CMP_UNKNOWN= -2, UNTIL_LOG_NAMES_CMP_LESS= -1,
00346     UNTIL_LOG_NAMES_CMP_EQUAL= 0, UNTIL_LOG_NAMES_CMP_GREATER= 1
00347   } until_log_names_cmp_result;
00348 
00349   char cached_charset[6];
00350   /*
00351     trans_retries varies between 0 to slave_transaction_retries and counts how
00352     many times the slave has retried the present transaction; gets reset to 0
00353     when the transaction finally succeeds. retried_trans is a cumulative
00354     counter: how many times the slave has retried a transaction (any) since
00355     slave started.
00356   */
00357   ulong trans_retries, retried_trans;
00358 
00359   /*
00360     If the end of the hot relay log is made of master's events ignored by the
00361     slave I/O thread, these two keep track of the coords (in the master's
00362     binlog) of the last of these events seen by the slave I/O thread. If not,
00363     ign_master_log_name_end[0] == 0.
00364     As they are like a Rotate event read/written from/to the relay log, they
00365     are both protected by rli->relay_log.LOCK_log.
00366   */
00367   char ign_master_log_name_end[FN_REFLEN];
00368   ulonglong ign_master_log_pos_end;
00369 
00370   /* 
00371     Indentifies where the SQL Thread should create temporary files for the
00372     LOAD DATA INFILE. This is used for security reasons.
00373    */ 
00374   char slave_patternload_file[FN_REFLEN]; 
00375   size_t slave_patternload_file_size;
00376 
00380   struct timespec last_clock;
00381 
00387   inline void notify_group_relay_log_name_update()
00388   {
00389     if (until_condition==UNTIL_RELAY_POS)
00390       until_log_names_cmp_result= UNTIL_LOG_NAMES_CMP_UNKNOWN;
00391   }
00392 
00397   inline void notify_group_master_log_name_update()
00398   {
00399     if (until_condition==UNTIL_MASTER_POS)
00400       until_log_names_cmp_result= UNTIL_LOG_NAMES_CMP_UNKNOWN;
00401   }
00402   
00403   inline void inc_event_relay_log_pos()
00404   {
00405     event_relay_log_pos= future_event_relay_log_pos;
00406   }
00407 
00408   int inc_group_relay_log_pos(ulonglong log_pos,
00409                               bool need_data_lock);
00410 
00411   int wait_for_pos(THD* thd, String* log_name, longlong log_pos, 
00412                    longlong timeout);
00413   int wait_for_gtid_set(THD* thd, String* gtid, longlong timeout);
00414   void close_temporary_tables();
00415 
00416   /* Check if UNTIL condition is satisfied. See slave.cc for more. */
00417   bool is_until_satisfied(THD *thd, Log_event *ev);
00418   inline ulonglong until_pos()
00419   {
00420     return ((until_condition == UNTIL_MASTER_POS) ? group_master_log_pos :
00421             group_relay_log_pos);
00422   }
00423 
00424   RPL_TABLE_LIST *tables_to_lock;           /* RBR: Tables to lock  */
00425   uint tables_to_lock_count;        /* RBR: Count of tables to lock */
00426   table_mapping m_table_map;      /* RBR: Mapping table-id to table */
00427   /* RBR: Record Rows_query log event */
00428   Rows_query_log_event* rows_query_ev;
00429 
00430   bool get_table_data(TABLE *table_arg, table_def **tabledef_var, TABLE **conv_table_var) const
00431   {
00432     DBUG_ASSERT(tabledef_var && conv_table_var);
00433     for (TABLE_LIST *ptr= tables_to_lock ; ptr != NULL ; ptr= ptr->next_global)
00434       if (ptr->table == table_arg)
00435       {
00436         *tabledef_var= &static_cast<RPL_TABLE_LIST*>(ptr)->m_tabledef;
00437         *conv_table_var= static_cast<RPL_TABLE_LIST*>(ptr)->m_conv_table;
00438         DBUG_PRINT("debug", ("Fetching table data for table %s.%s:"
00439                              " tabledef: %p, conv_table: %p",
00440                              table_arg->s->db.str, table_arg->s->table_name.str,
00441                              *tabledef_var, *conv_table_var));
00442         return true;
00443       }
00444     return false;
00445   }
00446 
00453   void cached_charset_invalidate();
00454   bool cached_charset_compare(char *charset) const;
00455 
00456   void cleanup_context(THD *, bool);
00457   void slave_close_thread_tables(THD *);
00458   void clear_tables_to_lock();
00459   int purge_relay_logs(THD *thd, bool just_reset, const char** errmsg);
00460 
00461   /*
00462     Used to defer stopping the SQL thread to give it a chance
00463     to finish up the current group of events.
00464     The timestamp is set and reset in @c sql_slave_killed().
00465   */
00466   time_t last_event_start_time;
00467   /*
00468     A container to hold on Intvar-, Rand-, Uservar- log-events in case
00469     the slave is configured with table filtering rules.
00470     The withhold events are executed when their parent Query destiny is
00471     determined for execution as well.
00472   */
00473   Deferred_log_events *deferred_events;
00474 
00475   /*
00476     State of the container: true stands for IRU events gathering, 
00477     false does for execution, either deferred or direct.
00478   */
00479   bool deferred_events_collecting;
00480 
00481   /*****************************************************************************
00482     WL#5569 MTS
00483 
00484     legends:
00485     C  - Coordinator;
00486     W  - Worker;
00487     WQ - Worker Queue containing event assignments
00488   */
00489   DYNAMIC_ARRAY workers; // number's is determined by global slave_parallel_workers
00490   volatile ulong pending_jobs;
00491   mysql_mutex_t pending_jobs_lock;
00492   mysql_cond_t pending_jobs_cond;
00493   mysql_mutex_t exit_count_lock; // mutex of worker exit count
00494   ulong       mts_slave_worker_queue_len_max;
00495   ulonglong   mts_pending_jobs_size;      // actual mem usage by WQ:s
00496   ulonglong   mts_pending_jobs_size_max;  // max of WQ:s size forcing C to wait
00497   bool    mts_wq_oversize;      // C raises flag to wait some memory's released
00498   Slave_worker  *last_assigned_worker;// is set to a Worker at assigning a group
00499   /*
00500     master-binlog ordered queue of Slave_job_group descriptors of groups
00501     that are under processing. The queue size is @c checkpoint_group.
00502   */
00503   Slave_committed_queue *gaq;
00504   /*
00505     Container for references of involved partitions for the current event group
00506   */
00507   DYNAMIC_ARRAY curr_group_assigned_parts;
00508   DYNAMIC_ARRAY curr_group_da;  // deferred array to hold partition-info-free events
00509   bool curr_group_seen_gtid;   // current group started with Gtid-event or not
00510   bool curr_group_seen_begin;   // current group started with B-event or not
00511   bool curr_group_isolated;     // current group requires execution in isolation
00512   bool mts_end_group_sets_max_dbs; // flag indicates if partitioning info is discovered
00513   volatile ulong mts_wq_underrun_w_id;  // Id of a Worker whose queue is getting empty
00514   /* 
00515      Ongoing excessive overrun counter to correspond to number of events that
00516      are being scheduled while a WQ is close to be filled up.
00517      `Close' is defined as (100 - mts_worker_underrun_level) %.
00518      The counter is incremented each time a WQ get filled over that level
00519      and decremented when the level drops below.
00520      The counter therefore describes level of saturation that Workers 
00521      are experiencing and is used as a parameter to compute a nap time for
00522      Coordinator in order to avoid reaching WQ limits.
00523   */
00524   volatile long mts_wq_excess_cnt;
00525   long  mts_worker_underrun_level; // % of WQ size at which W is considered hungry
00526   ulong mts_coordinator_basic_nap; // C sleeps to avoid WQs overrun
00527   ulong opt_slave_parallel_workers; // cache for ::opt_slave_parallel_workers
00528   ulong slave_parallel_workers; // the one slave session time number of workers
00529   ulong exit_counter; // Number of workers contributed to max updated group index
00530   ulonglong max_updated_index;
00531   ulong recovery_parallel_workers; // number of workers while recovering
00532   uint checkpoint_seqno;  // counter of groups executed after the most recent CP
00533   uint checkpoint_group;  // cache for ::opt_mts_checkpoint_group
00534   MY_BITMAP recovery_groups;  // bitmap used during recovery
00535   bool recovery_groups_inited;
00536   ulong mts_recovery_group_cnt; // number of groups to execute at recovery
00537   ulong mts_recovery_index;     // running index of recoverable groups
00538   bool mts_recovery_group_seen_begin;
00539 
00540   /*
00541     While distibuting events basing on their properties MTS
00542     Coordinator changes its mts group status.
00543     Transition normally flowws to follow `=>' arrows on the diagram:
00544 
00545             +----------------------------+
00546             V                            |
00547     MTS_NOT_IN_GROUP =>                  |
00548         {MTS_IN_GROUP => MTS_END_GROUP --+} while (!killed) => MTS_KILLED_GROUP
00549       
00550     MTS_END_GROUP has `->' loop breaking link to MTS_NOT_IN_GROUP when
00551     Coordinator synchronizes with Workers by demanding them to
00552     complete their assignments.
00553   */
00554   enum
00555   {
00556     /* 
00557        no new events were scheduled after last synchronization,
00558        includes Single-Threaded-Slave case.
00559     */
00560     MTS_NOT_IN_GROUP,
00561 
00562     MTS_IN_GROUP,    /* at least one not-terminal event scheduled to a Worker */
00563     MTS_END_GROUP,   /* the last scheduled event is a terminal event */
00564     MTS_KILLED_GROUP /* Coordinator gave up to reach MTS_END_GROUP */
00565   } mts_group_status;
00566 
00567   /*
00568     MTS statistics:
00569   */
00570   ulonglong mts_events_assigned; // number of events (statements) scheduled
00571   ulonglong mts_groups_assigned; // number of groups (transactions) scheduled
00572   volatile ulong mts_wq_overrun_cnt; // counter of all mts_wq_excess_cnt increments
00573   ulong wq_size_waits_cnt;    // number of times C slept due to WQ:s oversize
00574   /*
00575     a counter for sleeps due to Coordinator 
00576     experienced waiting when Workers get hungry again
00577   */
00578   ulong mts_wq_no_underrun_cnt;
00579   ulong mts_wq_overfill_cnt;  // counter of C waited due to a WQ queue was full
00580   /* 
00581      A sorted array of the Workers' current assignement numbers to provide
00582      approximate view on Workers loading.
00583      The first row of the least occupied Worker is queried at assigning 
00584      a new partition. Is updated at checkpoint commit to the main RLI.
00585   */
00586   DYNAMIC_ARRAY least_occupied_workers;
00587   time_t mts_last_online_stat;
00588   /* end of MTS statistics */
00589 
00590   /* most of allocation in the coordinator rli is there */
00591   void init_workers(ulong);
00592 
00593   /* counterpart of the init */
00594   void deinit_workers();
00595 
00600   inline bool is_mts_recovery() const
00601   {
00602     return mts_recovery_group_cnt != 0;
00603   }
00604 
00605   inline void clear_mts_recovery_groups()
00606   {
00607     if (recovery_groups_inited)
00608     {
00609       bitmap_free(&recovery_groups);
00610       mts_recovery_group_cnt= 0;
00611       recovery_groups_inited= false;
00612     }
00613   }
00614 
00618   inline bool is_parallel_exec() const
00619   {
00620     bool ret= (slave_parallel_workers > 0) && !is_mts_recovery();
00621 
00622     DBUG_ASSERT(!ret || workers.elements > 0);
00623 
00624     return ret;
00625   }
00626 
00631   inline bool is_mts_in_group()
00632   {
00633     return is_parallel_exec() &&
00634       mts_group_status == MTS_IN_GROUP;
00635   }
00636 
00642   void reset_notified_relay_log_change();
00643 
00649   void reset_notified_checkpoint(ulong, time_t, bool);
00650 
00655   bool mts_finalize_recovery();
00656   /*
00657    * End of MTS section ******************************************************/
00658 
00659   /* The general cleanup that slave applier may need at the end of query. */
00660   inline void cleanup_after_query()
00661   {
00662     if (deferred_events)
00663       deferred_events->rewind();
00664   };
00665   /* The general cleanup that slave applier may need at the end of session. */
00666   void cleanup_after_session()
00667   {
00668     if (deferred_events)
00669       delete deferred_events;
00670   };
00671    
00685   int stmt_done(my_off_t event_log_pos);
00686 
00687 
00693   void set_flag(enum_state_flag flag)
00694   {
00695     m_flags |= (1UL << flag);
00696   }
00697 
00705   bool get_flag(enum_state_flag flag)
00706   {
00707     return m_flags & (1UL << flag);
00708   }
00709 
00715   void clear_flag(enum_state_flag flag)
00716   {
00717     m_flags &= ~(1UL << flag);
00718   }
00719 
00731   bool is_in_group() const {
00732     return (info_thd->variables.option_bits & OPTION_BEGIN) ||
00733       (m_flags & (1UL << IN_STMT)) ||
00734       /* If a SET GTID_NEXT was issued we are inside of a group */
00735       info_thd->owned_gtid.sidno;
00736   }
00737 
00738   int count_relay_log_space();
00739 
00740   int rli_init_info();
00741   void end_info();
00742   int flush_info(bool force= FALSE);
00743   int flush_current_log();
00744   void set_master_info(Master_info *info);
00745 
00746   inline ulonglong get_future_event_relay_log_pos() { return future_event_relay_log_pos; }
00747   inline void set_future_event_relay_log_pos(ulonglong log_pos)
00748   {
00749     future_event_relay_log_pos= log_pos;
00750   }
00751 
00752   inline const char* get_group_master_log_name() { return group_master_log_name; }
00753   inline ulonglong get_group_master_log_pos() { return group_master_log_pos; }
00754   inline void set_group_master_log_name(const char *log_file_name)
00755   {
00756      strmake(group_master_log_name,log_file_name, sizeof(group_master_log_name)-1);
00757   }
00758   inline void set_group_master_log_pos(ulonglong log_pos)
00759   {
00760     group_master_log_pos= log_pos;
00761   }
00762 
00763   inline const char* get_group_relay_log_name() { return group_relay_log_name; }
00764   inline ulonglong get_group_relay_log_pos() { return group_relay_log_pos; }
00765   inline void set_group_relay_log_name(const char *log_file_name)
00766   {
00767      strmake(group_relay_log_name,log_file_name, sizeof(group_relay_log_name)-1);
00768   }
00769   inline void set_group_relay_log_name(const char *log_file_name, size_t len)
00770   {
00771      strmake(group_relay_log_name, log_file_name, len);
00772   }
00773   inline void set_group_relay_log_pos(ulonglong log_pos)
00774   {
00775     group_relay_log_pos= log_pos;
00776   }
00777 
00778   inline const char* get_event_relay_log_name() { return event_relay_log_name; }
00779   inline ulonglong get_event_relay_log_pos() { return event_relay_log_pos; }
00780   inline void set_event_relay_log_name(const char *log_file_name)
00781   {
00782      strmake(event_relay_log_name,log_file_name, sizeof(event_relay_log_name)-1);
00783   }
00784   inline void set_event_relay_log_name(const char *log_file_name, size_t len)
00785   {
00786      strmake(event_relay_log_name,log_file_name, len);
00787   }
00788   inline void set_event_relay_log_pos(ulonglong log_pos)
00789   {
00790     event_relay_log_pos= log_pos;
00791   }
00792   inline const char* get_rpl_log_name()
00793   {
00794     return (group_master_log_name[0] ? group_master_log_name : "FIRST");
00795   }
00796 
00797 #if MYSQL_VERSION_ID < 40100
00798   inline ulonglong get_future_master_log_pos() { return future_master_log_pos; }
00799 #else
00800   inline ulonglong get_future_group_master_log_pos() { return future_group_master_log_pos; }
00801   inline void set_future_group_master_log_pos(ulonglong log_pos)
00802   {
00803     future_group_master_log_pos= log_pos;
00804   }
00805 #endif
00806 
00807   static size_t get_number_info_rli_fields();
00808 
00820   void start_sql_delay(time_t delay_end)
00821   {
00822     mysql_mutex_assert_owner(&data_lock);
00823     sql_delay_end= delay_end;
00824     THD_STAGE_INFO(info_thd, stage_sql_thd_waiting_until_delay);
00825   }
00826 
00827   int32 get_sql_delay() { return sql_delay; }
00828   void set_sql_delay(time_t _sql_delay) { sql_delay= _sql_delay; }
00829   time_t get_sql_delay_end() { return sql_delay_end; }
00830 
00831   Relay_log_info(bool is_slave_recovery
00832 #ifdef HAVE_PSI_INTERFACE
00833                  ,PSI_mutex_key *param_key_info_run_lock,
00834                  PSI_mutex_key *param_key_info_data_lock,
00835                  PSI_mutex_key *param_key_info_sleep_lock,
00836                  PSI_mutex_key *param_key_info_data_cond,
00837                  PSI_mutex_key *param_key_info_start_cond,
00838                  PSI_mutex_key *param_key_info_stop_cond,
00839                  PSI_mutex_key *param_key_info_sleep_cond
00840 #endif
00841                  , uint param_id
00842                 );
00843   virtual ~Relay_log_info();
00844 
00845   /*
00846     Determines if a warning message on unsafe execution was
00847     already printed out to avoid clutering the error log
00848     with several warning messages.
00849   */
00850   bool reported_unsafe_warning;
00851 
00852   time_t get_row_stmt_start_timestamp()
00853   {
00854     return row_stmt_start_timestamp;
00855   }
00856 
00857   time_t set_row_stmt_start_timestamp()
00858   {
00859     if (row_stmt_start_timestamp == 0)
00860       row_stmt_start_timestamp= my_time(0);
00861 
00862     return row_stmt_start_timestamp;
00863   }
00864 
00865   void reset_row_stmt_start_timestamp()
00866   {
00867     row_stmt_start_timestamp= 0;
00868   }
00869 
00870   void set_long_find_row_note_printed()
00871   {
00872     long_find_row_note_printed= true;
00873   }
00874 
00875   void unset_long_find_row_note_printed()
00876   {
00877     long_find_row_note_printed= false;
00878   }
00879 
00880   bool is_long_find_row_note_printed()
00881   {
00882     return long_find_row_note_printed;
00883   }
00884 
00885 public:
00890   virtual void set_rli_description_event(Format_description_log_event *fdle);
00891 
00895   Format_description_log_event *get_rli_description_event() const
00896   {
00897     return rli_description_event;
00898   }
00899 
00903   void adapt_to_master_version(Format_description_log_event *fdle);
00904   uchar slave_version_split[3]; // bytes of the slave server version
00905 
00906 protected:
00907   Format_description_log_event *rli_description_event;
00908 
00909 private:
00910 
00922   int sql_delay;
00923 
00932   time_t sql_delay_end;
00933 
00934   uint32 m_flags;
00935 
00936   /*
00937     Before the MASTER_DELAY parameter was added (WL#344), relay_log.info
00938     had 4 lines. Now it has 5 lines.
00939   */
00940   static const int LINES_IN_RELAY_LOG_INFO_WITH_DELAY= 5;
00941 
00942   /*
00943     Before the WL#5599, relay_log.info had 5 lines. Now it has 6 lines.
00944   */
00945   static const int LINES_IN_RELAY_LOG_INFO_WITH_WORKERS= 6;
00946 
00947   /*
00948     Before the Id was added (BUG#2334346), relay_log.info
00949     had 6 lines. Now it has 7 lines.
00950   */
00951   static const int LINES_IN_RELAY_LOG_INFO_WITH_ID= 7;
00952 
00953   bool read_info(Rpl_info_handler *from);
00954   bool write_info(Rpl_info_handler *to);
00955 
00956   Relay_log_info(const Relay_log_info& info);
00957   Relay_log_info& operator=(const Relay_log_info& info);
00958 
00959   /*
00960     Runtime state for printing a note when slave is taking
00961     too long while processing a row event.
00962    */
00963   time_t row_stmt_start_timestamp;
00964   bool long_find_row_note_printed;
00965 
00966   /*
00967     If on init_info() call error_on_rli_init_info is true that means
00968     that previous call to init_info() terminated with an error, RESET
00969     SLAVE must be executed and the problem fixed manually.
00970    */
00971   bool error_on_rli_init_info;
00972 };
00973 
00974 bool mysql_show_relaylog_events(THD* thd);
00975 
00980 inline bool is_mts_worker(const THD *thd)
00981 {
00982   return thd->system_thread == SYSTEM_THREAD_SLAVE_WORKER;
00983 }
00984 
00985 #endif /* RPL_RLI_H */
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines