My Project
|
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 */