My Project
binlog.h
00001 #ifndef BINLOG_H_INCLUDED
00002 /* Copyright (c) 2010, 2014, Oracle and/or its affiliates. All rights reserved.
00003 
00004    This program is free software; you can redistribute it and/or modify
00005    it under the terms of the GNU General Public License as published by
00006    the Free Software Foundation; version 2 of the License.
00007 
00008    This program is distributed in the hope that it will be useful,
00009    but WITHOUT ANY WARRANTY; without even the implied warranty of
00010    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00011    GNU General Public License for more details.
00012 
00013    You should have received a copy of the GNU General Public License
00014    along with this program; if not, write to the Free Software Foundation,
00015    51 Franklin Street, Suite 500, Boston, MA 02110-1335 USA */
00016 
00017 #define BINLOG_H_INCLUDED
00018 
00019 #include "mysqld.h"                             /* opt_relay_logname */
00020 #include "log_event.h"
00021 #include "log.h"
00022 
00023 class Relay_log_info;
00024 class Master_info;
00025 
00026 class Format_description_log_event;
00027 
00031 class Stage_manager {
00032 public:
00033   class Mutex_queue {
00034     friend class Stage_manager;
00035   public:
00036     Mutex_queue()
00037       : m_first(NULL), m_last(&m_first)
00038     {
00039     }
00040 
00041     void init(
00042 #ifdef HAVE_PSI_INTERFACE
00043               PSI_mutex_key key_LOCK_queue
00044 #endif
00045               ) {
00046       mysql_mutex_init(key_LOCK_queue, &m_lock, MY_MUTEX_INIT_FAST);
00047     }
00048 
00049     void deinit() {
00050       mysql_mutex_destroy(&m_lock);
00051     }
00052 
00053     bool is_empty() const {
00054       return m_first == NULL;
00055     }
00056 
00058     bool append(THD *first);
00059 
00065     THD *fetch_and_empty();
00066 
00067     std::pair<bool,THD*> pop_front();
00068 
00069   private:
00070     void lock() { mysql_mutex_lock(&m_lock); }
00071     void unlock() { mysql_mutex_unlock(&m_lock); }
00072 
00077     THD *m_first;
00078 
00085     THD **m_last;
00086 
00088     mysql_mutex_t m_lock;
00089   } __attribute__((aligned(CPU_LEVEL1_DCACHE_LINESIZE)));
00090 
00091 public:
00092   Stage_manager()
00093   {
00094   }
00095 
00096   ~Stage_manager()
00097   {
00098   }
00099 
00103   enum StageID {
00104     FLUSH_STAGE,
00105     SYNC_STAGE,
00106     COMMIT_STAGE,
00107     STAGE_COUNTER
00108   };
00109 
00110   void init(
00111 #ifdef HAVE_PSI_INTERFACE
00112             PSI_mutex_key key_LOCK_flush_queue,
00113             PSI_mutex_key key_LOCK_sync_queue,
00114             PSI_mutex_key key_LOCK_commit_queue,
00115             PSI_mutex_key key_LOCK_done,
00116             PSI_cond_key key_COND_done
00117 #endif
00118             )
00119   {
00120     mysql_mutex_init(key_LOCK_done, &m_lock_done, MY_MUTEX_INIT_FAST);
00121     mysql_cond_init(key_COND_done, &m_cond_done, NULL);
00122 #ifndef DBUG_OFF
00123     /* reuse key_COND_done 'cos a new PSI object would be wasteful in DBUG_ON */
00124     mysql_cond_init(key_COND_done, &m_cond_preempt, NULL);
00125 #endif
00126     m_queue[FLUSH_STAGE].init(
00127 #ifdef HAVE_PSI_INTERFACE
00128                               key_LOCK_flush_queue
00129 #endif
00130                               );
00131     m_queue[SYNC_STAGE].init(
00132 #ifdef HAVE_PSI_INTERFACE
00133                              key_LOCK_sync_queue
00134 #endif
00135                              );
00136     m_queue[COMMIT_STAGE].init(
00137 #ifdef HAVE_PSI_INTERFACE
00138                                key_LOCK_commit_queue
00139 #endif
00140                                );
00141   }
00142 
00143   void deinit()
00144   {
00145     for (size_t i = 0 ; i < STAGE_COUNTER ; ++i)
00146       m_queue[i].deinit();
00147     mysql_cond_destroy(&m_cond_done);
00148     mysql_mutex_destroy(&m_lock_done);
00149   }
00150 
00173   bool enroll_for(StageID stage, THD *first, mysql_mutex_t *stage_mutex);
00174 
00175   std::pair<bool,THD*> pop_front(StageID stage)
00176   {
00177     return m_queue[stage].pop_front();
00178   }
00179 
00180 #ifndef DBUG_OFF
00181 
00189   void clear_preempt_status(THD *head);
00190 #endif
00191 
00197   THD *fetch_queue_for(StageID stage) {
00198     DBUG_PRINT("debug", ("Fetching queue for stage %d", stage));
00199     return m_queue[stage].fetch_and_empty();
00200   }
00201 
00202   void signal_done(THD *queue) {
00203     mysql_mutex_lock(&m_lock_done);
00204     for (THD *thd= queue ; thd ; thd = thd->next_to_commit)
00205       thd->transaction.flags.pending= false;
00206     mysql_mutex_unlock(&m_lock_done);
00207     mysql_cond_broadcast(&m_cond_done);
00208   }
00209 
00210 private:
00218   Mutex_queue m_queue[STAGE_COUNTER];
00219 
00221   mysql_cond_t m_cond_done;
00222 
00224   mysql_mutex_t m_lock_done;
00225 #ifndef DBUG_OFF
00226 
00227   bool leader_await_preempt_status;
00228 
00230   mysql_cond_t m_cond_preempt;
00231 #endif
00232 };
00233 
00234 
00235 class MYSQL_BIN_LOG: public TC_LOG, private MYSQL_LOG
00236 {
00237  private:
00238 #ifdef HAVE_PSI_INTERFACE
00239 
00240   PSI_mutex_key m_key_LOCK_index;
00241 
00242   PSI_mutex_key m_key_COND_done;
00243 
00244   PSI_mutex_key m_key_LOCK_commit_queue;
00245   PSI_mutex_key m_key_LOCK_done;
00246   PSI_mutex_key m_key_LOCK_flush_queue;
00247   PSI_mutex_key m_key_LOCK_sync_queue;
00249   PSI_mutex_key m_key_LOCK_commit;
00251   PSI_mutex_key m_key_LOCK_sync;
00253   PSI_mutex_key m_key_LOCK_xids;
00255   PSI_cond_key m_key_update_cond;
00257   PSI_cond_key m_key_prep_xids_cond;
00259   PSI_file_key m_key_file_log;
00261   PSI_file_key m_key_file_log_index;
00262 #endif
00263   /* POSIX thread objects are inited by init_pthread_objects() */
00264   mysql_mutex_t LOCK_index;
00265   mysql_mutex_t LOCK_commit;
00266   mysql_mutex_t LOCK_sync;
00267   mysql_mutex_t LOCK_xids;
00268   mysql_cond_t update_cond;
00269   ulonglong bytes_written;
00270   IO_CACHE index_file;
00271   char index_file_name[FN_REFLEN];
00272   /*
00273     crash_safe_index_file is temp file used for guaranteeing
00274     index file crash safe when master server restarts.
00275   */
00276   IO_CACHE crash_safe_index_file;
00277   char crash_safe_index_file_name[FN_REFLEN];
00278   /*
00279     purge_file is a temp file used in purge_logs so that the index file
00280     can be updated before deleting files from disk, yielding better crash
00281     recovery. It is created on demand the first time purge_logs is called
00282     and then reused for subsequent calls. It is cleaned up in cleanup().
00283   */
00284   IO_CACHE purge_index_file;
00285   char purge_index_file_name[FN_REFLEN];
00286   /*
00287      The max size before rotation (usable only if log_type == LOG_BIN: binary
00288      logs and relay logs).
00289      For a binlog, max_size should be max_binlog_size.
00290      For a relay log, it should be max_relay_log_size if this is non-zero,
00291      max_binlog_size otherwise.
00292      max_size is set in init(), and dynamically changed (when one does SET
00293      GLOBAL MAX_BINLOG_SIZE|MAX_RELAY_LOG_SIZE) by fix_max_binlog_size and
00294      fix_max_relay_log_size).
00295   */
00296   ulong max_size;
00297 
00298   // current file sequence number for load data infile binary logging
00299   uint file_id;
00300   uint open_count;                              // For replication
00301   int readers_count;
00302 
00303   /* pointer to the sync period variable, for binlog this will be
00304      sync_binlog_period, for relay log this will be
00305      sync_relay_log_period
00306   */
00307   uint *sync_period_ptr;
00308   uint sync_counter;
00309 
00310   my_atomic_rwlock_t m_prep_xids_lock;
00311   mysql_cond_t m_prep_xids_cond;
00312   volatile int32 m_prep_xids;
00313 
00317   void inc_prep_xids(THD *thd) {
00318     DBUG_ENTER("MYSQL_BIN_LOG::inc_prep_xids");
00319     my_atomic_rwlock_wrlock(&m_prep_xids_lock);
00320 #ifndef DBUG_OFF
00321     int result= my_atomic_add32(&m_prep_xids, 1);
00322 #else
00323     (void) my_atomic_add32(&m_prep_xids, 1);
00324 #endif
00325     DBUG_PRINT("debug", ("m_prep_xids: %d", result + 1));
00326     my_atomic_rwlock_wrunlock(&m_prep_xids_lock);
00327     thd->transaction.flags.xid_written= true;
00328     DBUG_VOID_RETURN;
00329   }
00330 
00336   void dec_prep_xids(THD *thd) {
00337     DBUG_ENTER("MYSQL_BIN_LOG::dec_prep_xids");
00338     my_atomic_rwlock_wrlock(&m_prep_xids_lock);
00339     int32 result= my_atomic_add32(&m_prep_xids, -1);
00340     DBUG_PRINT("debug", ("m_prep_xids: %d", result - 1));
00341     my_atomic_rwlock_wrunlock(&m_prep_xids_lock);
00342     thd->transaction.flags.xid_written= false;
00343     /* If the old value was 1, it is zero now. */
00344     if (result == 1)
00345     {
00346       mysql_mutex_lock(&LOCK_xids);
00347       mysql_cond_signal(&m_prep_xids_cond);
00348       mysql_mutex_unlock(&LOCK_xids);
00349     }
00350     DBUG_VOID_RETURN;
00351   }
00352 
00353   int32 get_prep_xids() {
00354     my_atomic_rwlock_rdlock(&m_prep_xids_lock);
00355     int32 result= my_atomic_load32(&m_prep_xids);
00356     my_atomic_rwlock_rdunlock(&m_prep_xids_lock);
00357     return result;
00358   }
00359 
00360   inline uint get_sync_period()
00361   {
00362     return *sync_period_ptr;
00363   }
00364 
00365   int write_to_file(IO_CACHE *cache);
00366   /*
00367     This is used to start writing to a new log file. The difference from
00368     new_file() is locking. new_file_without_locking() does not acquire
00369     LOCK_log.
00370   */
00371   int new_file_without_locking(Format_description_log_event *extra_description_event);
00372   int new_file_impl(bool need_lock, Format_description_log_event *extra_description_event);
00373 
00375   Stage_manager stage_manager;
00376   void do_flush(THD *thd);
00377 
00378 public:
00379   using MYSQL_LOG::generate_name;
00380   using MYSQL_LOG::is_open;
00381 
00382   /* This is relay log */
00383   bool is_relay_log;
00384   ulong signal_cnt;  // update of the counter is checked by heartbeat
00385   uint8 checksum_alg_reset; // to contain a new value when binlog is rotated
00386   /*
00387     Holds the last seen in Relay-Log FD's checksum alg value.
00388     The initial value comes from the slave's local FD that heads
00389     the very first Relay-Log file. In the following the value may change
00390     with each received master's FD_m.
00391     Besides to be used in verification events that IO thread receives
00392     (except the 1st fake Rotate, see @c Master_info:: checksum_alg_before_fd), 
00393     the value specifies if/how to compute checksum for slave's local events
00394     and the first fake Rotate (R_f^1) coming from the master.
00395     R_f^1 needs logging checksum-compatibly with the RL's heading FD_s.
00396 
00397     Legends for the checksum related comments:
00398 
00399     FD     - Format-Description event,
00400     R      - Rotate event
00401     R_f    - the fake Rotate event
00402     E      - an arbirary event
00403 
00404     The underscore indexes for any event
00405     `_s'   indicates the event is generated by Slave
00406     `_m'   - by Master
00407 
00408     Two special underscore indexes of FD:
00409     FD_q   - Format Description event for queuing   (relay-logging)
00410     FD_e   - Format Description event for executing (relay-logging)
00411 
00412     Upper indexes:
00413     E^n    - n:th event is a sequence
00414 
00415     RL     - Relay Log
00416     (A)    - checksum algorithm descriptor value
00417     FD.(A) - the value of (A) in FD
00418   */
00419   uint8 relay_log_checksum_alg;
00420 
00421   MYSQL_BIN_LOG(uint *sync_period);
00422   /*
00423     note that there's no destructor ~MYSQL_BIN_LOG() !
00424     The reason is that we don't want it to be automatically called
00425     on exit() - but only during the correct shutdown process
00426   */
00427 
00428 #ifdef HAVE_PSI_INTERFACE
00429   void set_psi_keys(PSI_mutex_key key_LOCK_index,
00430                     PSI_mutex_key key_LOCK_commit,
00431                     PSI_mutex_key key_LOCK_commit_queue,
00432                     PSI_mutex_key key_LOCK_done,
00433                     PSI_mutex_key key_LOCK_flush_queue,
00434                     PSI_mutex_key key_LOCK_log,
00435                     PSI_mutex_key key_LOCK_sync,
00436                     PSI_mutex_key key_LOCK_sync_queue,
00437                     PSI_mutex_key key_LOCK_xids,
00438                     PSI_cond_key key_COND_done,
00439                     PSI_cond_key key_update_cond,
00440                     PSI_cond_key key_prep_xids_cond,
00441                     PSI_file_key key_file_log,
00442                     PSI_file_key key_file_log_index)
00443   {
00444     m_key_COND_done= key_COND_done;
00445 
00446     m_key_LOCK_commit_queue= key_LOCK_commit_queue;
00447     m_key_LOCK_done= key_LOCK_done;
00448     m_key_LOCK_flush_queue= key_LOCK_flush_queue;
00449     m_key_LOCK_sync_queue= key_LOCK_sync_queue;
00450 
00451     m_key_LOCK_index= key_LOCK_index;
00452     m_key_LOCK_log= key_LOCK_log;
00453     m_key_LOCK_commit= key_LOCK_commit;
00454     m_key_LOCK_sync= key_LOCK_sync;
00455     m_key_LOCK_xids= key_LOCK_xids;
00456     m_key_update_cond= key_update_cond;
00457     m_key_prep_xids_cond= key_prep_xids_cond;
00458     m_key_file_log= key_file_log;
00459     m_key_file_log_index= key_file_log_index;
00460   }
00461 #endif
00462 
00474   bool find_first_log_not_in_gtid_set(char *binlog_file_name,
00475                                       const Gtid_set *gtid_set,
00476                                       Gtid *first_gtid,
00477                                       const char **errmsg);
00478 
00497   bool init_gtid_sets(Gtid_set *gtid_set, Gtid_set *lost_groups,
00498                       Gtid *last_gtid, bool verify_checksum,
00499                       bool need_lock, bool is_server_starting= false);
00500 
00501   void set_previous_gtid_set(Gtid_set *previous_gtid_set_param)
00502   {
00503     previous_gtid_set= previous_gtid_set_param;
00504   }
00505 private:
00506   Gtid_set* previous_gtid_set;
00507 
00508   int open(const char *opt_name) { return open_binlog(opt_name); }
00509   bool change_stage(THD *thd, Stage_manager::StageID stage,
00510                     THD* queue, mysql_mutex_t *leave,
00511                     mysql_mutex_t *enter);
00512   std::pair<int,my_off_t> flush_thread_caches(THD *thd);
00513   int flush_cache_to_file(my_off_t *flush_end_pos);
00514   int finish_commit(THD *thd);
00515   std::pair<bool, bool> sync_binlog_file(bool force);
00516   void process_commit_stage_queue(THD *thd, THD *queue);
00517   void process_after_commit_stage_queue(THD *thd, THD *first);
00518   int process_flush_stage_queue(my_off_t *total_bytes_var, bool *rotate_var,
00519                                 THD **out_queue_var);
00520   int ordered_commit(THD *thd, bool all, bool skip_commit = false);
00521 public:
00522   int open_binlog(const char *opt_name);
00523   void close();
00524   enum_result commit(THD *thd, bool all);
00525   int rollback(THD *thd, bool all);
00526   int prepare(THD *thd, bool all);
00527   int recover(IO_CACHE *log, Format_description_log_event *fdle,
00528               my_off_t *valid_pos);
00529   int recover(IO_CACHE *log, Format_description_log_event *fdle);
00530 #if !defined(MYSQL_CLIENT)
00531 
00532   void update_thd_next_event_pos(THD *thd);
00533   int flush_and_set_pending_rows_event(THD *thd, Rows_log_event* event,
00534                                        bool is_transactional);
00535 
00536 #endif /* !defined(MYSQL_CLIENT) */
00537   void add_bytes_written(ulonglong inc)
00538   {
00539     bytes_written += inc;
00540   }
00541   void reset_bytes_written()
00542   {
00543     bytes_written = 0;
00544   }
00545   void harvest_bytes_written(ulonglong* counter)
00546   {
00547 #ifndef DBUG_OFF
00548     char buf1[22],buf2[22];
00549 #endif
00550     DBUG_ENTER("harvest_bytes_written");
00551     (*counter)+=bytes_written;
00552     DBUG_PRINT("info",("counter: %s  bytes_written: %s", llstr(*counter,buf1),
00553                        llstr(bytes_written,buf2)));
00554     bytes_written=0;
00555     DBUG_VOID_RETURN;
00556   }
00557   void set_max_size(ulong max_size_arg);
00558   void signal_update();
00559   int wait_for_update_relay_log(THD* thd, const struct timespec * timeout);
00560   int  wait_for_update_bin_log(THD* thd, const struct timespec * timeout);
00561 public:
00562   void init_pthread_objects();
00563   void cleanup();
00582   bool open_binlog(const char *log_name,
00583                    const char *new_name,
00584                    enum cache_type io_cache_type_arg,
00585                    ulong max_size,
00586                    bool null_created,
00587                    bool need_lock_index, bool need_sid_lock,
00588                    Format_description_log_event *extra_description_event);
00589   bool open_index_file(const char *index_file_name_arg,
00590                        const char *log_name, bool need_lock_index);
00591   /* Use this to start writing a new log file */
00592   int new_file(Format_description_log_event *extra_description_event);
00593 
00594   bool write_event(Log_event* event_info);
00595   bool write_cache(THD *thd, class binlog_cache_data *binlog_cache_data);
00596   int  do_write_cache(IO_CACHE *cache);
00597 
00598   void set_write_error(THD *thd, bool is_transactional);
00599   bool check_write_error(THD *thd);
00600   bool write_incident(THD *thd, bool need_lock_log,
00601                       bool do_flush_and_sync= true);
00602   bool write_incident(Incident_log_event *ev, bool need_lock_log,
00603                       bool do_flush_and_sync= true);
00604 
00605   void start_union_events(THD *thd, query_id_t query_id_param);
00606   void stop_union_events(THD *thd);
00607   bool is_query_in_union(THD *thd, query_id_t query_id_param);
00608 
00609 #ifdef HAVE_REPLICATION
00610   bool append_buffer(const char* buf, uint len, Master_info *mi);
00611   bool append_event(Log_event* ev, Master_info *mi);
00612 private:
00613   bool after_append_to_relay_log(Master_info *mi);
00614 #endif // ifdef HAVE_REPLICATION
00615 public:
00616 
00617   void make_log_name(char* buf, const char* log_ident);
00618   bool is_active(const char* log_file_name);
00619   int remove_logs_from_index(LOG_INFO* linfo, bool need_update_threads);
00620   int rotate(bool force_rotate, bool* check_purge);
00621   void purge();
00622   int rotate_and_purge(THD* thd, bool force_rotate);
00637   bool flush_and_sync(const bool force= false);
00638   int purge_logs(const char *to_log, bool included,
00639                  bool need_lock_index, bool need_update_threads,
00640                  ulonglong *decrease_log_space, bool auto_purge);
00641   int purge_logs_before_date(time_t purge_time, bool auto_purge);
00642   int purge_first_log(Relay_log_info* rli, bool included);
00643   int set_crash_safe_index_file_name(const char *base_file_name);
00644   int open_crash_safe_index_file();
00645   int close_crash_safe_index_file();
00646   int add_log_to_index(uchar* log_file_name, int name_len,
00647                        bool need_lock_index);
00648   int move_crash_safe_index_file_to_index_file(bool need_lock_index);
00649   int set_purge_index_file_name(const char *base_file_name);
00650   int open_purge_index_file(bool destroy);
00651   bool is_inited_purge_index_file();
00652   int close_purge_index_file();
00653   int clean_purge_index_file();
00654   int sync_purge_index_file();
00655   int register_purge_index_entry(const char* entry);
00656   int register_create_index_entry(const char* entry);
00657   int purge_index_entry(THD *thd, ulonglong *decrease_log_space,
00658                         bool need_lock_index);
00659   bool reset_logs(THD* thd);
00660   void close(uint exiting);
00661 
00662   // iterating through the log index file
00663   int find_log_pos(LOG_INFO* linfo, const char* log_name,
00664                    bool need_lock_index);
00665   int find_next_log(LOG_INFO* linfo, bool need_lock_index);
00666   int get_current_log(LOG_INFO* linfo);
00667   int raw_get_current_log(LOG_INFO* linfo);
00668   uint next_file_id();
00669   inline char* get_index_fname() { return index_file_name;}
00670   inline char* get_log_fname() { return log_file_name; }
00671   inline char* get_name() { return name; }
00672   inline mysql_mutex_t* get_log_lock() { return &LOCK_log; }
00673   inline mysql_cond_t* get_log_cond() { return &update_cond; }
00674   inline IO_CACHE* get_log_file() { return &log_file; }
00675 
00676   inline void lock_index() { mysql_mutex_lock(&LOCK_index);}
00677   inline void unlock_index() { mysql_mutex_unlock(&LOCK_index);}
00678   inline IO_CACHE *get_index_file() { return &index_file;}
00679   inline uint32 get_open_count() { return open_count; }
00680 };
00681 
00682 typedef struct st_load_file_info
00683 {
00684   THD* thd;
00685   my_off_t last_pos_in_file;
00686   bool wrote_create_file, log_delayed;
00687 } LOAD_FILE_INFO;
00688 
00689 extern MYSQL_PLUGIN_IMPORT MYSQL_BIN_LOG mysql_bin_log;
00690 
00691 bool trans_has_updated_trans_table(const THD* thd);
00692 bool stmt_has_updated_trans_table(const THD *thd);
00693 bool ending_trans(THD* thd, const bool all);
00694 bool ending_single_stmt_trans(THD* thd, const bool all);
00695 bool trans_cannot_safely_rollback(const THD* thd);
00696 bool stmt_cannot_safely_rollback(const THD* thd);
00697 
00698 int log_loaded_block(IO_CACHE* file);
00699 
00703 File open_binlog_file(IO_CACHE *log, const char *log_file_name,
00704                       const char **errmsg);
00705 int check_binlog_magic(IO_CACHE* log, const char** errmsg);
00706 bool purge_master_logs(THD* thd, const char* to_log);
00707 bool purge_master_logs_before_date(THD* thd, time_t purge_time);
00708 bool show_binlog_events(THD *thd, MYSQL_BIN_LOG *binary_log);
00709 bool mysql_show_binlog_events(THD* thd);
00710 void check_binlog_cache_size(THD *thd);
00711 void check_binlog_stmt_cache_size(THD *thd);
00712 bool binlog_enabled();
00713 void register_binlog_handler(THD *thd, bool trx);
00714 int gtid_empty_group_log_and_cleanup(THD *thd);
00715 
00716 extern const char *log_bin_index;
00717 extern const char *log_bin_basename;
00718 extern bool opt_binlog_order_commits;
00719 
00734 inline bool normalize_binlog_name(char *to, const char *from, bool is_relay_log)
00735 {
00736   DBUG_ENTER("normalize_binlog_name");
00737   bool error= false;
00738   char buff[FN_REFLEN];
00739   char *ptr= (char*) from;
00740   char *opt_name= is_relay_log ? opt_relay_logname : opt_bin_logname;
00741 
00742   DBUG_ASSERT(from);
00743 
00744   /* opt_name is not null and not empty and from is a relative path */
00745   if (opt_name && opt_name[0] && from && !test_if_hard_path(from))
00746   {
00747     // take the path from opt_name
00748     // take the filename from from 
00749     char log_dirpart[FN_REFLEN], log_dirname[FN_REFLEN];
00750     size_t log_dirpart_len, log_dirname_len;
00751     dirname_part(log_dirpart, opt_name, &log_dirpart_len);
00752     dirname_part(log_dirname, from, &log_dirname_len);
00753 
00754     /* log may be empty => relay-log or log-bin did not 
00755         hold paths, just filename pattern */
00756     if (log_dirpart_len > 0)
00757     {
00758       /* create the new path name */
00759       if(fn_format(buff, from+log_dirname_len, log_dirpart, "",
00760                    MYF(MY_UNPACK_FILENAME | MY_SAFE_PATH)) == NULL)
00761       {
00762         error= true;
00763         goto end;
00764       }
00765 
00766       ptr= buff;
00767     }
00768   }
00769 
00770   DBUG_ASSERT(ptr);
00771 
00772   if (ptr)
00773     strmake(to, ptr, strlen(ptr));
00774 
00775 end:
00776   DBUG_RETURN(error);
00777 }
00778 #endif /* BINLOG_H_INCLUDED */
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines