Commit 771296eb authored by unknown's avatar unknown

Manageable transactional log purge and file size

support added to maria.


mysql-test/r/maria.result:
  New variables added.
storage/maria/ha_maria.cc:
  Variable for transactional log purge method added.
  Variable for transactional log size added.
  SHOW for engine logs added.
  Log flush purge logs in case of "ondemand" type of
    log processing.
storage/maria/ma_checkpoint.c:
  log purge call enabled.
storage/maria/ma_loghandler.c:
  Support for different methods of log purge added.
  Functions for getting information about logs state added.
  Functions for getting/setting log size.
storage/maria/ma_loghandler.h:
  Fixed defines.
  Functions for for transactional log mannegment added.
storage/maria/ma_recovery.c:
  Dependence on TRANSLOG_FILE_SIZE removed.
mysql-test/r/maria-purge.result:
  New BitKeeper file ``mysql-test/r/maria-purge.result''
mysql-test/t/maria-purge.test:
  New BitKeeper file ``mysql-test/t/maria-purge.test''
parent 1cede432
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;
...@@ -1977,6 +1977,8 @@ show variables like 'maria%'; ...@@ -1977,6 +1977,8 @@ show variables like 'maria%';
Variable_name Value Variable_name Value
maria_block_size 8192 maria_block_size 8192
maria_checkpoint_interval 30 maria_checkpoint_interval 30
maria_log_file_size 1073741824
maria_log_purge_type immediate
maria_max_sort_file_size 9223372036853727232 maria_max_sort_file_size 9223372036853727232
maria_pagecache_age_threshold 300 maria_pagecache_age_threshold 300
maria_pagecache_buffer_size 8384512 maria_pagecache_buffer_size 8384512
......
-- 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
...@@ -22,6 +22,7 @@ ...@@ -22,6 +22,7 @@
#include "mysql_priv.h" #include "mysql_priv.h"
#include <mysql/plugin.h> #include <mysql/plugin.h>
#include <m_ctype.h> #include <m_ctype.h>
#include <my_dir.h>
#include <myisampack.h> #include <myisampack.h>
#include <my_bit.h> #include <my_bit.h>
#include "ha_maria.h" #include "ha_maria.h"
...@@ -81,11 +82,25 @@ TYPELIB maria_stats_method_typelib= ...@@ -81,11 +82,25 @@ TYPELIB maria_stats_method_typelib=
maria_stats_method_names, NULL 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
};
/** @brief Interval between background checkpoints in seconds */ /** @brief Interval between background checkpoints in seconds */
static ulong checkpoint_interval; static ulong checkpoint_interval;
static void update_checkpoint_interval(MYSQL_THD thd, static void update_checkpoint_interval(MYSQL_THD thd,
struct st_mysql_sys_var *var, struct st_mysql_sys_var *var,
void *var_ptr, void *save); 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, static MYSQL_SYSVAR_ULONG(block_size, maria_block_size,
PLUGIN_VAR_RQCMDARG | PLUGIN_VAR_READONLY, PLUGIN_VAR_RQCMDARG | PLUGIN_VAR_READONLY,
...@@ -99,6 +114,20 @@ static MYSQL_SYSVAR_ULONG(checkpoint_interval, checkpoint_interval, ...@@ -99,6 +114,20 @@ static MYSQL_SYSVAR_ULONG(checkpoint_interval, checkpoint_interval,
" 0 means 'no automatic checkpoints'.", " 0 means 'no automatic checkpoints'.",
NULL, update_checkpoint_interval, 30, 0, UINT_MAX, 1); 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, static MYSQL_SYSVAR_ULONGLONG(max_sort_file_size,
maria_max_temp_length, PLUGIN_VAR_RQCMDARG, maria_max_temp_length, PLUGIN_VAR_RQCMDARG,
"Don't use the fast sort index method to created index if the " "Don't use the fast sort index method to created index if the "
...@@ -2417,6 +2446,109 @@ static int maria_rollback(handlerton *hton __attribute__ ((unused)), ...@@ -2417,6 +2446,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) static int ha_maria_init(void *p)
{ {
int res; int res;
...@@ -2427,6 +2559,8 @@ static int ha_maria_init(void *p) ...@@ -2427,6 +2559,8 @@ static int ha_maria_init(void *p)
maria_hton->panic= maria_hton_panic; maria_hton->panic= maria_hton_panic;
maria_hton->commit= maria_commit; maria_hton->commit= maria_commit;
maria_hton->rollback= maria_rollback; 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 */ /* TODO: decide if we support Maria being used for log tables */
maria_hton->flags= HTON_CAN_RECREATE | HTON_SUPPORT_LOG_TABLES; maria_hton->flags= HTON_CAN_RECREATE | HTON_SUPPORT_LOG_TABLES;
bzero(maria_log_pagecache, sizeof(*maria_log_pagecache)); bzero(maria_log_pagecache, sizeof(*maria_log_pagecache));
...@@ -2438,7 +2572,7 @@ static int ha_maria_init(void *p) ...@@ -2438,7 +2572,7 @@ static int ha_maria_init(void *p)
(init_pagecache(maria_log_pagecache, (init_pagecache(maria_log_pagecache,
TRANSLOG_PAGECACHE_SIZE, 0, 0, TRANSLOG_PAGECACHE_SIZE, 0, 0,
TRANSLOG_PAGE_SIZE) == 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, MYSQL_VERSION_ID, server_id, maria_log_pagecache,
TRANSLOG_DEFAULT_FLAGS) || TRANSLOG_DEFAULT_FLAGS) ||
maria_recover() || maria_recover() ||
...@@ -2526,6 +2660,8 @@ my_bool ha_maria::register_query_cache_table(THD *thd, char *table_name, ...@@ -2526,6 +2660,8 @@ my_bool ha_maria::register_query_cache_table(THD *thd, char *table_name,
static struct st_mysql_sys_var* system_variables[]= { static struct st_mysql_sys_var* system_variables[]= {
MYSQL_SYSVAR(block_size), MYSQL_SYSVAR(block_size),
MYSQL_SYSVAR(checkpoint_interval), MYSQL_SYSVAR(checkpoint_interval),
MYSQL_SYSVAR(log_file_size),
MYSQL_SYSVAR(log_purge_type),
MYSQL_SYSVAR(max_sort_file_size), MYSQL_SYSVAR(max_sort_file_size),
MYSQL_SYSVAR(pagecache_age_threshold), MYSQL_SYSVAR(pagecache_age_threshold),
MYSQL_SYSVAR(pagecache_buffer_size), MYSQL_SYSVAR(pagecache_buffer_size),
...@@ -2549,6 +2685,19 @@ static void update_checkpoint_interval(MYSQL_THD thd, ...@@ -2549,6 +2685,19 @@ static void update_checkpoint_interval(MYSQL_THD thd,
ma_checkpoint_init(*(ulong *)var_ptr= (ulong)(*(long *)save)); 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));
size= translog_set_file_size(size);
*(ulong *)var_ptr= size;
}
static SHOW_VAR status_variables[]= { static SHOW_VAR status_variables[]= {
{"Maria_pagecache_blocks_not_flushed", (char*) &maria_pagecache_var.global_blocks_changed, SHOW_LONG}, {"Maria_pagecache_blocks_not_flushed", (char*) &maria_pagecache_var.global_blocks_changed, SHOW_LONG},
{"Maria_pagecache_blocks_unused", (char*) &maria_pagecache_var.blocks_unused, SHOW_LONG}, {"Maria_pagecache_blocks_unused", (char*) &maria_pagecache_var.blocks_unused, SHOW_LONG},
......
...@@ -280,10 +280,8 @@ static int really_execute_checkpoint(void) ...@@ -280,10 +280,8 @@ static int really_execute_checkpoint(void)
be robust against that: remember a few previous checkpoints in the be robust against that: remember a few previous checkpoints in the
control file, and not purge logs immediately... Think about it. 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)) if (translog_purge(log_low_water_mark))
fprintf(stderr, "Maria engine: log purge failed\n"); /* not deadly */ fprintf(stderr, "Maria engine: log purge failed\n"); /* not deadly */
#endif
goto end; goto end;
......
...@@ -199,6 +199,11 @@ struct st_translog_descriptor ...@@ -199,6 +199,11 @@ struct st_translog_descriptor
pthread_mutex_t unfinished_files_lock; pthread_mutex_t unfinished_files_lock;
DYNAMIC_ARRAY unfinished_files; 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) */ /* Purger data: minimum file in the log (or 0 if unknown) */
uint32 min_file_number; uint32 min_file_number;
/* Protect purger from many calls and it's data */ /* Protect purger from many calls and it's data */
...@@ -209,6 +214,9 @@ struct st_translog_descriptor ...@@ -209,6 +214,9 @@ struct st_translog_descriptor
static struct st_translog_descriptor log_descriptor; static struct st_translog_descriptor log_descriptor;
ulong log_purge_type= TRANSLOG_PURGE_IMMIDIATE;
ulong log_file_size= TRANSLOG_FILE_SIZE;
/* Marker for end of log */ /* Marker for end of log */
static uchar end_of_log= 0; static uchar end_of_log= 0;
#define END_OF_LOG &end_of_log #define END_OF_LOG &end_of_log
...@@ -647,18 +655,16 @@ static void translog_check_cursor(struct st_buffer_cursor *cursor) ...@@ -647,18 +655,16 @@ static void translog_check_cursor(struct st_buffer_cursor *cursor)
#endif #endif
/* /*
Get file name of the log by log number @brief Get file name of the log by log number
SYNOPSIS @param file_no Number of the log we want to open
translog_filename_by_fileno() @param path Pointer to buffer where file name will be
file_no Number of the log we want to open
path Pointer to buffer where file name will be
stored (must be FN_REFLEN bytes at least) 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; char buff[11], *end;
uint length; uint length;
...@@ -668,7 +674,7 @@ static char *translog_filename_by_fileno(uint32 file_no, char *path) ...@@ -668,7 +674,7 @@ static char *translog_filename_by_fileno(uint32 file_no, char *path)
/* log_descriptor.directory is already formated */ /* log_descriptor.directory is already formated */
end= strxmov(path, log_descriptor.directory, "maria_log.0000000", NullS); end= strxmov(path, log_descriptor.directory, "maria_log.0000000", NullS);
length= (uint) (int10_to_str(file_no, buff, 10) - buff); 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_PRINT("info", ("Path: '%s' path: 0x%lx", path, (ulong) path));
DBUG_RETURN(path); DBUG_RETURN(path);
...@@ -2726,6 +2732,18 @@ static my_bool translog_truncate_log(TRANSLOG_ADDRESS addr) ...@@ -2726,6 +2732,18 @@ static my_bool translog_truncate_log(TRANSLOG_ADDRESS addr)
DBUG_RETURN(0); DBUG_RETURN(0);
} }
/**
@brief round correctly transaction log size
@return maximum possible log size less or equal then given one
*/
static uint32 translog_round_log_size(uint32 size)
{
size= (size - (size % TRANSLOG_PAGE_SIZE));
return max(size, TRANSLOG_MIN_FILE_SIZE);
}
/* /*
Initialize transaction log Initialize transaction log
...@@ -2776,6 +2794,7 @@ my_bool translog_init(const char *directory, ...@@ -2776,6 +2794,7 @@ my_bool translog_init(const char *directory,
sizeof(struct st_file_counter), sizeof(struct st_file_counter),
10, 10 CALLER_INFO)) 10, 10 CALLER_INFO))
DBUG_RETURN(1); DBUG_RETURN(1);
log_descriptor.min_need_file= 0;
log_descriptor.min_file_number= 0; log_descriptor.min_file_number= 0;
log_descriptor.last_lsn_checked= LSN_IMPOSSIBLE; log_descriptor.last_lsn_checked= LSN_IMPOSSIBLE;
...@@ -2792,8 +2811,8 @@ my_bool translog_init(const char *directory, ...@@ -2792,8 +2811,8 @@ my_bool translog_init(const char *directory,
log_descriptor.in_buffers_only= LSN_IMPOSSIBLE; log_descriptor.in_buffers_only= LSN_IMPOSSIBLE;
/* max size of one log size (for new logs creation) */ /* max size of one log size (for new logs creation) */
log_descriptor.log_file_max_size= log_file_size= log_descriptor.log_file_max_size=
log_file_max_size - (log_file_max_size % TRANSLOG_PAGE_SIZE); translog_round_log_size(log_file_max_size);
/* server version */ /* server version */
log_descriptor.server_version= server_version; log_descriptor.server_version= server_version;
/* server ID */ /* server ID */
...@@ -6769,7 +6788,7 @@ my_bool translog_is_file(uint file_no) ...@@ -6769,7 +6788,7 @@ my_bool translog_is_file(uint file_no)
static uint32 translog_first_file(TRANSLOG_ADDRESS horizon, int is_protected) static uint32 translog_first_file(TRANSLOG_ADDRESS horizon, int is_protected)
{ {
uint min_file= 1, max_file; uint min_file= 0, max_file;
DBUG_ENTER("translog_first_file"); DBUG_ENTER("translog_first_file");
if (!is_protected) if (!is_protected)
translog_mutex_lock(&log_descriptor.purger_lock); translog_mutex_lock(&log_descriptor.purger_lock);
...@@ -6943,7 +6962,7 @@ LSN translog_first_lsn_in_log() ...@@ -6943,7 +6962,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_ERROR Error
@retval LSN_IMPOSSIBLE no log @retval LSN_IMPOSSIBLE no log
...@@ -6979,7 +6998,7 @@ LSN translog_first_theoretical_lsn() ...@@ -6979,7 +6998,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 @param low the last (minimum) address which is need
...@@ -7002,7 +7021,6 @@ my_bool translog_purge(TRANSLOG_ADDRESS low) ...@@ -7002,7 +7021,6 @@ my_bool translog_purge(TRANSLOG_ADDRESS low)
uint32 i; uint32 i;
uint32 min_file= translog_first_file(horizon, 1); uint32 min_file= translog_first_file(horizon, 1);
DBUG_ASSERT(min_file != 0); /* log is already started */ DBUG_ASSERT(min_file != 0); /* log is already started */
for(i= min_file; i < last_need_file && rc == 0; i++) for(i= min_file; i < last_need_file && rc == 0; i++)
{ {
LSN lsn= translog_get_file_max_lsn_stored(i); LSN lsn= translog_get_file_max_lsn_stored(i);
...@@ -7016,14 +7034,140 @@ my_bool translog_purge(TRANSLOG_ADDRESS low) ...@@ -7016,14 +7034,140 @@ my_bool translog_purge(TRANSLOG_ADDRESS low)
if (cmp_translog_addr(lsn, low) >= 0) if (cmp_translog_addr(lsn, low) >= 0)
break; break;
DBUG_PRINT("info", ("purge file %lu", (ulong) i)); DBUG_PRINT("info", ("purge file %lu", (ulong) i));
if (log_purge_type == TRANSLOG_PURGE_IMMIDIATE)
{ {
char path[FN_REFLEN], *file_name; char path[FN_REFLEN], *file_name;
file_name= translog_filename_by_fileno(i, path); file_name= translog_filename_by_fileno(i, path);
rc= test(my_delete(file_name, MYF(MY_WME))); 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); translog_mutex_unlock(&log_descriptor.purger_lock);
DBUG_RETURN(rc); 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)));
}
translog_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
*/
uint32 translog_set_file_size(uint32 size)
{
uint32 res;
translog_lock();
res= log_descriptor.log_file_max_size= translog_round_log_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();
return (res);
}
...@@ -17,9 +17,11 @@ ...@@ -17,9 +17,11 @@
#define _ma_loghandler_h #define _ma_loghandler_h
/* transaction log default cache size (TODO: make it global variable) */ /* transaction log default cache size (TODO: make it global variable) */
#define TRANSLOG_PAGECACHE_SIZE 1024*1024*2 #define TRANSLOG_PAGECACHE_SIZE (1024*1024*2)
/* transaction log default file size (TODO: make it global variable) */ /* transaction log default file size */
#define TRANSLOG_FILE_SIZE 1024*1024*1024 #define TRANSLOG_FILE_SIZE (1024*1024*1024)
/* minimum possible transaction log size */
#define TRANSLOG_MIN_FILE_SIZE (1024*1024*4)
/* transaction log default flags (TODO: make it global variable) */ /* transaction log default flags (TODO: make it global variable) */
#define TRANSLOG_DEFAULT_FLAGS 0 #define TRANSLOG_DEFAULT_FLAGS 0
...@@ -290,6 +292,12 @@ extern my_bool translog_inited; ...@@ -290,6 +292,12 @@ extern my_bool translog_inited;
extern LSN translog_first_lsn_in_log(); extern LSN translog_first_lsn_in_log();
extern LSN translog_first_theoretical_lsn(); extern LSN translog_first_theoretical_lsn();
extern LSN translog_next_LSN(TRANSLOG_ADDRESS addr, TRANSLOG_ADDRESS horizon); 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 uint32 translog_get_file_size();
extern uint32 translog_set_file_size(uint32 size);
/* record parts descriptor */ /* record parts descriptor */
struct st_translog_parts struct st_translog_parts
...@@ -374,5 +382,14 @@ typedef struct st_log_record_type_descriptor ...@@ -374,5 +382,14 @@ typedef struct st_log_record_type_descriptor
extern LOG_DESC log_record_type_descriptor[LOGREC_NUMBER_OF_TYPES]; extern LOG_DESC log_record_type_descriptor[LOGREC_NUMBER_OF_TYPES];
#endif #endif
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;
C_MODE_END C_MODE_END
#endif #endif
...@@ -2336,8 +2336,9 @@ static void print_redo_phase_progress(TRANSLOG_ADDRESS addr) ...@@ -2336,8 +2336,9 @@ static void print_redo_phase_progress(TRANSLOG_ADDRESS addr)
int cur_offset= LSN_OFFSET(addr); int cur_offset= LSN_OFFSET(addr);
ulonglong remainder; ulonglong remainder;
remainder= (cur_logno == end_logno) ? (end_offset - cur_offset) : remainder= (cur_logno == end_logno) ? (end_offset - cur_offset) :
(TRANSLOG_FILE_SIZE - cur_offset + (((longlong)log_file_size) - cur_offset +
max(end_logno - cur_logno - 1, 0) * TRANSLOG_FILE_SIZE + end_offset); max(end_logno - cur_logno - 1, 0) * ((longlong)log_file_size) +
end_offset);
if (initial_remainder == (ulonglong)(-1)) if (initial_remainder == (ulonglong)(-1))
initial_remainder= remainder; initial_remainder= remainder;
int percentage_done= int percentage_done=
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment