diff --git a/mysql-test/r/maria-purge.result b/mysql-test/r/maria-purge.result new file mode 100644 index 00000000000..6c3e709f343 --- /dev/null +++ b/mysql-test/r/maria-purge.result @@ -0,0 +1,82 @@ +set global storage_engine=maria; +set session storage_engine=maria; +drop table if exists t1,t2; +SET SQL_WARNINGS=1; +CREATE TABLE t1 ( +STRING_DATA char(255) default NULL +); +CREATE TABLE t2 ( +STRING_DATA char(255) default NULL +); +INSERT INTO t1 VALUES ('AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA'); +INSERT INTO t1 VALUES ('DDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDD'); +insert into t2 select * from t1; +insert into t1 select * from t2; +insert into t2 select * from t1; +insert into t1 select * from t2; +insert into t2 select * from t1; +insert into t1 select * from t2; +insert into t2 select * from t1; +insert into t1 select * from t2; +insert into t2 select * from t1; +insert into t1 select * from t2; +insert into t2 select * from t1; +insert into t1 select * from t2; +insert into t2 select * from t1; +insert into t1 select * from t2; +insert into t2 select * from t1; +insert into t1 select * from t2; +insert into t2 select * from t1; +insert into t1 select * from t2; +insert into t2 select * from t1; +insert into t1 select * from t2; +insert into t2 select * from t1; +insert into t1 select * from t2; +insert into t2 select * from t1; +insert into t1 select * from t2; +set global maria_checkpoint_interval=2; +SHOW ENGINE maria logs; +Type Name Status +maria master-data/maria_log.00000001 in use +set global maria_log_file_size=16777216; +select @@global.maria_log_file_size; +@@global.maria_log_file_size +16777216 +SHOW ENGINE maria logs; +Type Name Status +maria master-data/maria_log.00000002 in use +set global maria_log_file_size=8388608; +select @@global.maria_log_file_size; +@@global.maria_log_file_size +8388608 +set global maria_log_purge_type=at_flush; +insert into t1 select * from t2; +SHOW ENGINE maria logs; +Type Name Status +maria master-data/maria_log.00000002 free +maria master-data/maria_log.00000003 free +maria master-data/maria_log.00000004 free +maria master-data/maria_log.00000005 in use +flush logs; +SHOW ENGINE maria logs; +Type Name Status +maria master-data/maria_log.00000005 in use +set global maria_log_file_size=16777216; +set global maria_log_purge_type=external; +insert into t1 select * from t2; +SHOW ENGINE maria logs; +Type Name Status +maria master-data/maria_log.00000005 free +maria master-data/maria_log.00000006 in use +flush logs; +SHOW ENGINE maria logs; +Type Name Status +maria master-data/maria_log.00000005 free +maria master-data/maria_log.00000006 in use +set global maria_log_purge_type=immediate; +insert into t1 select * from t2; +SHOW ENGINE maria logs; +Type Name Status +maria master-data/maria_log.00000007 in use +maria master-data/maria_log.00000008 in use +drop table t1, t2; diff --git a/mysql-test/r/maria.result b/mysql-test/r/maria.result index 8f873fef230..4cbdb094efc 100644 --- a/mysql-test/r/maria.result +++ b/mysql-test/r/maria.result @@ -2048,6 +2048,8 @@ show variables like 'maria%'; Variable_name Value maria_block_size 8192 maria_checkpoint_interval 30 +maria_log_file_size 1073741824 +maria_log_purge_type immediate maria_max_sort_file_size 9223372036853727232 maria_pagecache_age_threshold 300 maria_pagecache_buffer_size 8384512 diff --git a/mysql-test/t/maria-purge.test b/mysql-test/t/maria-purge.test new file mode 100644 index 00000000000..607255c311c --- /dev/null +++ b/mysql-test/t/maria-purge.test @@ -0,0 +1,95 @@ +-- source include/have_maria.inc +-- source include/big_test.inc +let $default=`select @@global.storage_engine`; +set global storage_engine=maria; +set session storage_engine=maria; +let $def_logsize=`select @@global.maria_log_file_size`; +let $def_checkinterval=`select @@global.maria_checkpoint_interval`; + +# Initialise +--disable_warnings +drop table if exists t1,t2; +--enable_warnings +SET SQL_WARNINGS=1; + +CREATE TABLE t1 ( + STRING_DATA char(255) default NULL +); +CREATE TABLE t2 ( + STRING_DATA char(255) default NULL +); + +INSERT INTO t1 VALUES ('AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA'); +INSERT INTO t1 VALUES ('DDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDD'); +insert into t2 select * from t1; +insert into t1 select * from t2; +insert into t2 select * from t1; +insert into t1 select * from t2; +insert into t2 select * from t1; +insert into t1 select * from t2; +insert into t2 select * from t1; +insert into t1 select * from t2; +insert into t2 select * from t1; +insert into t1 select * from t2; +insert into t2 select * from t1; +insert into t1 select * from t2; +insert into t2 select * from t1; +insert into t1 select * from t2; +insert into t2 select * from t1; +insert into t1 select * from t2; +insert into t2 select * from t1; +insert into t1 select * from t2; +insert into t2 select * from t1; +insert into t1 select * from t2; +insert into t2 select * from t1; +insert into t1 select * from t2; +insert into t2 select * from t1; +insert into t1 select * from t2; + + +set global maria_checkpoint_interval=2; +--replace_regex /Size +[0-9]+ ; .+master-data/master-data/ +SHOW ENGINE maria logs; +set global maria_log_file_size=16777216; +select @@global.maria_log_file_size; +sleep 7; +--replace_regex /Size +[0-9]+ ; .+master-data/master-data/ +SHOW ENGINE maria logs; +set global maria_log_file_size=8388608; +select @@global.maria_log_file_size; + +set global maria_log_purge_type=at_flush; +insert into t1 select * from t2; +sleep 7; +--replace_regex /Size +[0-9]+ ; .+master-data/master-data/ +SHOW ENGINE maria logs; +flush logs; +--replace_regex /Size +[0-9]+ ; .+master-data/master-data/ +SHOW ENGINE maria logs; + +set global maria_log_file_size=16777216; +set global maria_log_purge_type=external; +insert into t1 select * from t2; +sleep 7; +--replace_regex /Size +[0-9]+ ; .+master-data/master-data/ +SHOW ENGINE maria logs; +flush logs; +--replace_regex /Size +[0-9]+ ; .+master-data/master-data/ +SHOW ENGINE maria logs; + +set global maria_log_purge_type=immediate; +insert into t1 select * from t2; +sleep 7; +--replace_regex /Size +[0-9]+ ; .+master-data/master-data/ +SHOW ENGINE maria logs; + +drop table t1, t2; + +--disable_result_log +--disable_query_log +set global maria_log_purge_type=immediate; +eval set global storage_engine=$default; +eval set global maria_log_file_size=$def_logsize; +eval set global maria_checkpoint_interval=$def_checkinterval; +--enable_result_log +--enable_query_log diff --git a/storage/maria/ha_maria.cc b/storage/maria/ha_maria.cc index 70958ca042c..606710f1f6c 100644 --- a/storage/maria/ha_maria.cc +++ b/storage/maria/ha_maria.cc @@ -22,6 +22,7 @@ #include "mysql_priv.h" #include #include +#include #include #include #include "ha_maria.h" @@ -81,6 +82,16 @@ TYPELIB maria_stats_method_typelib= maria_stats_method_names, NULL }; +/* transactions log purge mode */ +const char *maria_translog_purge_type_names[]= +{ + "immediate", "external", "at_flush", NullS +}; +TYPELIB maria_translog_purge_type_typelib= +{ + array_elements(maria_translog_purge_type_names) - 1, "", + maria_translog_purge_type_names, NULL +}; const char *maria_sync_log_dir_names[]= { "NEVER", "NEWFILE", "ALWAYS", NullS @@ -97,6 +108,9 @@ static ulong checkpoint_interval; static void update_checkpoint_interval(MYSQL_THD thd, struct st_mysql_sys_var *var, void *var_ptr, void *save); +static void update_log_file_size(MYSQL_THD thd, + struct st_mysql_sys_var *var, + void *var_ptr, void *save); static MYSQL_SYSVAR_ULONG(block_size, maria_block_size, PLUGIN_VAR_RQCMDARG | PLUGIN_VAR_READONLY, @@ -110,6 +124,20 @@ static MYSQL_SYSVAR_ULONG(checkpoint_interval, checkpoint_interval, " 0 means 'no automatic checkpoints'.", NULL, update_checkpoint_interval, 30, 0, UINT_MAX, 1); +static MYSQL_SYSVAR_ULONG(log_file_size, log_file_size, + PLUGIN_VAR_RQCMDARG, + "Limit for transaction log size", + NULL, update_log_file_size, TRANSLOG_FILE_SIZE, + TRANSLOG_MIN_FILE_SIZE, 0xffffffffL, TRANSLOG_PAGE_SIZE); + +static MYSQL_SYSVAR_ENUM(log_purge_type, log_purge_type, + PLUGIN_VAR_RQCMDARG, + "Specifies how maria transactional log will be purged. " + "Possible values of name are \"immediate\", \"external\" " + "and \"at_flush\"", + NULL, NULL, TRANSLOG_PURGE_IMMIDIATE, + &maria_translog_purge_type_typelib); + static MYSQL_SYSVAR_ULONGLONG(max_sort_file_size, maria_max_temp_length, PLUGIN_VAR_RQCMDARG, "Don't use the fast sort index method to created index if the " @@ -2415,6 +2443,109 @@ static int maria_rollback(handlerton *hton __attribute__ ((unused)), } + +/** + @brief flush log handler + + @param hton maria handlerton (unused) + + @retval FALSE OK + @retval TRUE Error +*/ + +bool maria_flush_logs(handlerton *hton) +{ + return test(translog_purge_at_flush()); +} + + +#define SHOW_MSG_LEN (FN_REFLEN + 20) +/** + @brief show status handler + + @param hton maria handlerton + @param thd thread handler + @param print print function + @param stat type of status +*/ + +bool maria_show_status(handlerton *hton, + THD *thd, + stat_print_fn *print, + enum ha_stat_type stat) +{ + char engine_name[]= "maria"; + switch (stat) + { + case HA_ENGINE_LOGS: + { + TRANSLOG_ADDRESS horizon= translog_get_horizon(); + uint32 last_file= LSN_FILE_NO(horizon); + uint32 first_needed= translog_get_first_needed_file(); + uint32 first_file= translog_get_first_file(horizon); + uint32 i; + const char unknown[]= "unknown"; + const char needed[]= "in use"; + const char unneeded[]= "free"; + char path[FN_REFLEN]; + + if (first_file == 0) + { + const char error[]= "error"; + print(thd, engine_name, sizeof(engine_name), + STRING_WITH_LEN(""), error, sizeof(error)); + break; + } + + for (i= first_file; i <= last_file; i++) + { + char *file; + const char *status; + uint length, status_len; + MY_STAT stat_buff, *stat; + const char error[]= "can't stat"; + char object[SHOW_MSG_LEN]; + file= translog_filename_by_fileno(i, path); + if (!(stat= my_stat(file, &stat_buff, MYF(MY_WME)))) + { + status= error; + status_len= sizeof(error); + length= snprintf(object, SHOW_MSG_LEN, "Size unknown ; %s", file); + } + else + { + if (first_needed == 0) + { + status= unknown; + status_len= sizeof(unknown); + } + else if (i < first_needed) + { + status= unneeded; + status_len= sizeof(unneeded); + } + else + { + status= needed; + status_len= sizeof(needed); + } + length= snprintf(object, SHOW_MSG_LEN, "Size %12lu ; %s", + (ulong) stat->st_size, file); + } + + print(thd, engine_name, sizeof(engine_name), + object, length, status, status_len); + } + break; + } + case HA_ENGINE_STATUS: + case HA_ENGINE_MUTEX: + default: + break; + } + return 0; +} + static int ha_maria_init(void *p) { int res; @@ -2425,6 +2556,8 @@ static int ha_maria_init(void *p) maria_hton->panic= maria_hton_panic; maria_hton->commit= maria_commit; maria_hton->rollback= maria_rollback; + maria_hton->flush_logs= maria_flush_logs; + maria_hton->show_status= maria_show_status; /* TODO: decide if we support Maria being used for log tables */ maria_hton->flags= HTON_CAN_RECREATE | HTON_SUPPORT_LOG_TABLES; bzero(maria_log_pagecache, sizeof(*maria_log_pagecache)); @@ -2437,7 +2570,7 @@ static int ha_maria_init(void *p) !init_pagecache(maria_log_pagecache, TRANSLOG_PAGECACHE_SIZE, 0, 0, TRANSLOG_PAGE_SIZE, 0) || - translog_init(maria_data_root, TRANSLOG_FILE_SIZE, + translog_init(maria_data_root, log_file_size, MYSQL_VERSION_ID, server_id, maria_log_pagecache, TRANSLOG_DEFAULT_FLAGS) || maria_recover() || @@ -2525,6 +2658,8 @@ my_bool ha_maria::register_query_cache_table(THD *thd, char *table_name, static struct st_mysql_sys_var* system_variables[]= { MYSQL_SYSVAR(block_size), MYSQL_SYSVAR(checkpoint_interval), + MYSQL_SYSVAR(log_file_size), + MYSQL_SYSVAR(log_purge_type), MYSQL_SYSVAR(max_sort_file_size), MYSQL_SYSVAR(pagecache_age_threshold), MYSQL_SYSVAR(pagecache_buffer_size), @@ -2549,6 +2684,19 @@ static void update_checkpoint_interval(MYSQL_THD thd, ma_checkpoint_init(*(ulong *)var_ptr= (ulong)(*(long *)save)); } +/** + @brief Updates the transaction log file limit. +*/ + +static void update_log_file_size(MYSQL_THD thd, + struct st_mysql_sys_var *var, + void *var_ptr, void *save) +{ + uint32 size= (uint32)((ulong)(*(long *)save)); + translog_set_file_size(size); + *(ulong *)var_ptr= size; +} + static SHOW_VAR status_variables[]= { {"Maria_pagecache_blocks_not_flushed", (char*) &maria_pagecache_var.global_blocks_changed, SHOW_LONG_NOFLUSH}, {"Maria_pagecache_blocks_unused", (char*) &maria_pagecache_var.blocks_unused, SHOW_LONG_NOFLUSH}, diff --git a/storage/maria/ma_checkpoint.c b/storage/maria/ma_checkpoint.c index f9a3e668851..c20612e343e 100644 --- a/storage/maria/ma_checkpoint.c +++ b/storage/maria/ma_checkpoint.c @@ -278,10 +278,8 @@ static int really_execute_checkpoint(void) be robust against that: remember a few previous checkpoints in the control file, and not purge logs immediately... Think about it. */ -#if 0 /* purging/keeping will be an option */ if (translog_purge(log_low_water_mark)) ma_message_no_user(0, "log purging failed"); -#endif goto end; diff --git a/storage/maria/ma_loghandler.c b/storage/maria/ma_loghandler.c index 9914626ea81..54dac38d729 100644 --- a/storage/maria/ma_loghandler.c +++ b/storage/maria/ma_loghandler.c @@ -29,7 +29,7 @@ /* number of opened log files in the pagecache (should be at least 2) */ #define OPENED_FILES_NUM 3 -/* records buffer size (should be LOG_PAGE_SIZE * n) */ +/* records buffer size (should be TRANSLOG_PAGE_SIZE * n) */ #define TRANSLOG_WRITE_BUFFER (1024*1024) /* min chunk length */ #define TRANSLOG_MIN_CHUNK 3 @@ -214,6 +214,11 @@ struct st_translog_descriptor pthread_mutex_t unfinished_files_lock; DYNAMIC_ARRAY unfinished_files; + /* + minimum number of still need file calculeted during last + translog_purge call + */ + uint32 min_need_file; /* Purger data: minimum file in the log (or 0 if unknown) */ uint32 min_file_number; /* Protect purger from many calls and it's data */ @@ -224,6 +229,8 @@ struct st_translog_descriptor static struct st_translog_descriptor log_descriptor; +ulong log_purge_type= TRANSLOG_PURGE_IMMIDIATE; +ulong log_file_size= TRANSLOG_FILE_SIZE; ulong sync_log_dir= TRANSLOG_SYNC_DIR_NEWFILE; /* Marker for end of log */ @@ -661,18 +668,16 @@ static void translog_check_cursor(struct st_buffer_cursor *cursor) #endif /* - Get file name of the log by log number + @brief Get file name of the log by log number - SYNOPSIS - translog_filename_by_fileno() - file_no Number of the log we want to open - path Pointer to buffer where file name will be + @param file_no Number of the log we want to open + @param path Pointer to buffer where file name will be stored (must be FN_REFLEN bytes at least) - RETURN - pointer to path + + @return pointer to path */ -static char *translog_filename_by_fileno(uint32 file_no, char *path) +char *translog_filename_by_fileno(uint32 file_no, char *path) { char buff[11], *end; uint length; @@ -682,7 +687,7 @@ static char *translog_filename_by_fileno(uint32 file_no, char *path) /* log_descriptor.directory is already formated */ end= strxmov(path, log_descriptor.directory, "maria_log.0000000", NullS); length= (uint) (int10_to_str(file_no, buff, 10) - buff); - strmov(end-length+1, buff); + strmov(end - length +1, buff); DBUG_PRINT("info", ("Path: '%s' path: 0x%lx", path, (ulong) path)); DBUG_RETURN(path); @@ -2822,6 +2827,9 @@ my_bool translog_init(const char *directory, my_bool version_changed= 0; DBUG_ENTER("translog_init"); DBUG_ASSERT(translog_inited == 0); + compile_time_assert(TRANSLOG_MIN_FILE_SIZE > + TRANSLOG_WRITE_BUFFER * TRANSLOG_BUFFERS_NO); + compile_time_assert(TRANSLOG_WRITE_BUFFER % TRANSLOG_PAGE_SIZE == 0); loghandler_init(); /* Safe to do many times */ @@ -2839,6 +2847,7 @@ my_bool translog_init(const char *directory, sizeof(struct st_file_counter), 10, 10)) DBUG_RETURN(1); + log_descriptor.min_need_file= 0; log_descriptor.min_file_number= 0; log_descriptor.last_lsn_checked= LSN_IMPOSSIBLE; @@ -2854,9 +2863,12 @@ my_bool translog_init(const char *directory, } log_descriptor.in_buffers_only= LSN_IMPOSSIBLE; + DBUG_ASSERT(log_file_max_size % TRANSLOG_PAGE_SIZE == 0 && + log_file_max_size >= TRANSLOG_MIN_FILE_SIZE && + log_file_max_size <= 0xffffffffL); /* max size of one log size (for new logs creation) */ - log_descriptor.log_file_max_size= - log_file_max_size - (log_file_max_size % TRANSLOG_PAGE_SIZE); + log_file_size= log_descriptor.log_file_max_size= + log_file_max_size; /* server version */ log_descriptor.server_version= server_version; /* server ID */ @@ -6988,7 +7000,7 @@ LSN translog_first_lsn_in_log() /** - @brief returns theoretical first LSN if first log is present + @brief Returns theoretical first LSN if first log is present @retval LSN_ERROR Error @retval LSN_IMPOSSIBLE no log @@ -7024,7 +7036,7 @@ LSN translog_first_theoretical_lsn() /** - @brief Check given low water mark and purge files if it is need + @brief Checks given low water mark and purge files if it is need @param low the last (minimum) address which is need @@ -7047,7 +7059,6 @@ my_bool translog_purge(TRANSLOG_ADDRESS low) uint32 i; uint32 min_file= translog_first_file(horizon, 1); DBUG_ASSERT(min_file != 0); /* log is already started */ - for(i= min_file; i < last_need_file && rc == 0; i++) { LSN lsn= translog_get_file_max_lsn_stored(i); @@ -7061,14 +7072,144 @@ my_bool translog_purge(TRANSLOG_ADDRESS low) if (cmp_translog_addr(lsn, low) >= 0) break; DBUG_PRINT("info", ("purge file %lu", (ulong) i)); + if (log_purge_type == TRANSLOG_PURGE_IMMIDIATE) { char path[FN_REFLEN], *file_name; file_name= translog_filename_by_fileno(i, path); rc= test(my_delete(file_name, MYF(MY_WME))); } } + if (unlikely(rc == 1)) + log_descriptor.min_need_file= 0; /* impossible value */ + else + log_descriptor.min_need_file= i; + } + + translog_mutex_unlock(&log_descriptor.purger_lock); + DBUG_RETURN(rc); +} + + +/** + @brief Purges files by stored min need file in case of + "ondemend" purge type + + @note This function do real work only if it is "ondemend" purge type + and translog_purge() was called at least once and last time without + errors + + @retval 0 OK + @retval 1 Error +*/ + +my_bool translog_purge_at_flush() +{ + uint32 i, min_file; + int rc= 0; + DBUG_ENTER("translog_purge_at_flush"); + DBUG_ASSERT(translog_inited == 1); + + if (log_purge_type != TRANSLOG_PURGE_ONDEMAND) + { + DBUG_PRINT("info", ("It is not \"at_flush\" => exit")); + DBUG_RETURN(0); + } + + translog_mutex_lock(&log_descriptor.purger_lock); + + if (unlikely(log_descriptor.min_need_file == 0)) + { + DBUG_PRINT("info", ("No info about min need file => exit")); + translog_mutex_unlock(&log_descriptor.purger_lock); + DBUG_RETURN(0); + } + + min_file= translog_first_file(translog_get_horizon(), 1); + DBUG_ASSERT(min_file != 0); /* log is already started */ + for(i= min_file; i < log_descriptor.min_need_file && rc == 0; i++) + { + char path[FN_REFLEN], *file_name; + DBUG_PRINT("info", ("purge file %lu\n", (ulong) i)); + file_name= translog_filename_by_fileno(i, path); + rc= test(my_delete(file_name, MYF(MY_WME))); } pthread_mutex_unlock(&log_descriptor.purger_lock); DBUG_RETURN(rc); } + + +/** + @brief Gets min file number + + @param horizon the end of the log + + @retval minimum file number + @retval 0 no files found +*/ + +uint32 translog_get_first_file(TRANSLOG_ADDRESS horizon) +{ + return translog_first_file(horizon, 0); +} + + +/** + @brief Gets min file number which is needed + + @retval minimum file number + @retval 0 unknown +*/ + +uint32 translog_get_first_needed_file() +{ + uint32 file_no; + translog_mutex_lock(&log_descriptor.purger_lock); + file_no= log_descriptor.min_need_file; + translog_mutex_unlock(&log_descriptor.purger_lock); + return file_no; +} + + +/** + @brief Gets transaction log file size + + @return transaction log file size +*/ + +uint32 translog_get_file_size() +{ + uint32 res; + translog_lock(); + res= log_descriptor.log_file_max_size; + translog_unlock(); + return (res); +} + + +/** + @brief Sets transaction log file size + + @return Returns actually set transaction log size +*/ + +void translog_set_file_size(uint32 size) +{ + DBUG_ENTER("translog_set_file_size"); + translog_lock(); + DBUG_PRINT("enter", ("Size: %lu", (ulong) size)); + DBUG_ASSERT(size % TRANSLOG_PAGE_SIZE == 0 && + size >= TRANSLOG_MIN_FILE_SIZE && + size <= 0xffffffffL); + log_descriptor.log_file_max_size= size; + /* if current file longer then finish it*/ + if (LSN_OFFSET(log_descriptor.horizon) >= log_descriptor.log_file_max_size) + { + struct st_translog_buffer *old_buffer= log_descriptor.bc.buffer; + translog_buffer_next(&log_descriptor.horizon, &log_descriptor.bc, 1); + translog_buffer_unlock(old_buffer); + } + translog_unlock(); + DBUG_VOID_RETURN; +} + diff --git a/storage/maria/ma_loghandler.h b/storage/maria/ma_loghandler.h index 5669f422496..42959fb2a7f 100644 --- a/storage/maria/ma_loghandler.h +++ b/storage/maria/ma_loghandler.h @@ -17,9 +17,11 @@ #define _ma_loghandler_h /* transaction log default cache size (TODO: make it global variable) */ -#define TRANSLOG_PAGECACHE_SIZE 1024*1024*2 -/* transaction log default file size (TODO: make it global variable) */ -#define TRANSLOG_FILE_SIZE 1024*1024*1024 +#define TRANSLOG_PAGECACHE_SIZE (1024*1024*2) +/* transaction log default file size */ +#define TRANSLOG_FILE_SIZE (1024*1024*1024) +/* minimum possible transaction log size */ +#define TRANSLOG_MIN_FILE_SIZE (1024*1024*8) /* transaction log default flags (TODO: make it global variable) */ #define TRANSLOG_DEFAULT_FLAGS 0 @@ -308,6 +310,11 @@ extern my_bool translog_inited; extern LSN translog_first_lsn_in_log(); extern LSN translog_first_theoretical_lsn(); extern LSN translog_next_LSN(TRANSLOG_ADDRESS addr, TRANSLOG_ADDRESS horizon); +extern my_bool translog_purge_at_flush(); +extern uint32 translog_get_first_file(TRANSLOG_ADDRESS horizon); +extern uint32 translog_get_first_needed_file(); +extern char *translog_filename_by_fileno(uint32 file_no, char *path); +extern void translog_set_file_size(uint32 size); /* record parts descriptor */ struct st_translog_parts @@ -389,6 +396,15 @@ typedef struct st_log_record_type_descriptor extern LOG_DESC log_record_type_descriptor[LOGREC_NUMBER_OF_TYPES]; +typedef enum +{ + TRANSLOG_PURGE_IMMIDIATE, + TRANSLOG_PURGE_EXTERNAL, + TRANSLOG_PURGE_ONDEMAND +} enum_maria_translog_purge_type; +extern ulong log_purge_type; +extern ulong log_file_size; + typedef enum { TRANSLOG_SYNC_DIR_NEVER, diff --git a/storage/maria/ma_recovery.c b/storage/maria/ma_recovery.c index ebc60f550ba..94cfc881f70 100644 --- a/storage/maria/ma_recovery.c +++ b/storage/maria/ma_recovery.c @@ -2890,8 +2890,9 @@ static void print_redo_phase_progress(TRANSLOG_ADDRESS addr) cur_logno= LSN_FILE_NO(addr); cur_offset= LSN_OFFSET(addr); local_remainder= (cur_logno == end_logno) ? (end_offset - cur_offset) : - (TRANSLOG_FILE_SIZE - cur_offset + - max(end_logno - cur_logno - 1, 0) * TRANSLOG_FILE_SIZE + end_offset); + (((longlong)log_file_size) - cur_offset + + max(end_logno - cur_logno - 1, 0) * ((longlong)log_file_size) + + end_offset); if (initial_remainder == (ulonglong)(-1)) initial_remainder= local_remainder; percentage_done= ((initial_remainder - local_remainder) * ULL(100) / diff --git a/storage/maria/unittest/ma_test_loghandler-t.c b/storage/maria/unittest/ma_test_loghandler-t.c index a5a85c2e589..6c0b8614285 100644 --- a/storage/maria/unittest/ma_test_loghandler-t.c +++ b/storage/maria/unittest/ma_test_loghandler-t.c @@ -18,12 +18,12 @@ static TRN *trn= &dummy_transaction_object; #ifdef LONG_LOG_TEST #define LOG_FLAGS 0 -#define LOG_FILE_SIZE (1024L*1024L) +#define LOG_FILE_SIZE (1024L*1024L*8) #define ITERATIONS (1600*4) #else #define LOG_FLAGS (TRANSLOG_SECTOR_PROTECTION | TRANSLOG_PAGE_CRC) -#define LOG_FILE_SIZE (1024L*1024L*3L) +#define LOG_FILE_SIZE (1024L*1024L*8L) #define ITERATIONS 1600 #endif