Commit 1ec645bd authored by unknown's avatar unknown

Merge desktop.sanja.is.com.ua:/home/bell/mysql/bk/mysql-maria

into  desktop.sanja.is.com.ua:/home/bell/mysql/bk/work-maria-logpurge


mysql-test/r/maria.result:
  Auto merged
storage/maria/ma_checkpoint.c:
  Auto merged
storage/maria/ma_recovery.c:
  Auto merged
storage/maria/ha_maria.cc:
  Merge
storage/maria/ma_loghandler.c:
  Merge
storage/maria/ma_loghandler.h:
  Merge
parents f8b7f8be 771296eb
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;
...@@ -2048,6 +2048,8 @@ show variables like 'maria%'; ...@@ -2048,6 +2048,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,6 +82,16 @@ TYPELIB maria_stats_method_typelib= ...@@ -81,6 +82,16 @@ 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
};
const char *maria_sync_log_dir_names[]= const char *maria_sync_log_dir_names[]=
{ {
"NEVER", "NEWFILE", "ALWAYS", NullS "NEVER", "NEWFILE", "ALWAYS", NullS
...@@ -97,6 +108,9 @@ static ulong checkpoint_interval; ...@@ -97,6 +108,9 @@ 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,
...@@ -110,6 +124,20 @@ static MYSQL_SYSVAR_ULONG(checkpoint_interval, checkpoint_interval, ...@@ -110,6 +124,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 "
...@@ -2415,6 +2443,109 @@ static int maria_rollback(handlerton *hton __attribute__ ((unused)), ...@@ -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) static int ha_maria_init(void *p)
{ {
int res; int res;
...@@ -2425,6 +2556,8 @@ static int ha_maria_init(void *p) ...@@ -2425,6 +2556,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));
...@@ -2437,7 +2570,7 @@ static int ha_maria_init(void *p) ...@@ -2437,7 +2570,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() ||
...@@ -2525,6 +2658,8 @@ my_bool ha_maria::register_query_cache_table(THD *thd, char *table_name, ...@@ -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[]= { 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 +2684,19 @@ static void update_checkpoint_interval(MYSQL_THD thd, ...@@ -2549,6 +2684,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_NOFLUSH}, {"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}, {"Maria_pagecache_blocks_unused", (char*) &maria_pagecache_var.blocks_unused, SHOW_LONG_NOFLUSH},
......
...@@ -278,10 +278,8 @@ static int really_execute_checkpoint(void) ...@@ -278,10 +278,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))
ma_message_no_user(0, "log purging failed"); ma_message_no_user(0, "log purging failed");
#endif
goto end; goto end;
......
...@@ -238,6 +238,11 @@ struct st_translog_descriptor ...@@ -238,6 +238,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 */
...@@ -248,6 +253,8 @@ struct st_translog_descriptor ...@@ -248,6 +253,8 @@ 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;
ulong sync_log_dir= TRANSLOG_SYNC_DIR_NEWFILE; ulong sync_log_dir= TRANSLOG_SYNC_DIR_NEWFILE;
/* Marker for end of log */ /* Marker for end of log */
...@@ -678,18 +685,16 @@ static void translog_check_cursor(struct st_buffer_cursor *cursor) ...@@ -678,18 +685,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;
...@@ -699,7 +704,7 @@ static char *translog_filename_by_fileno(uint32 file_no, char *path) ...@@ -699,7 +704,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);
...@@ -2807,6 +2812,18 @@ static my_bool translog_truncate_log(TRANSLOG_ADDRESS addr) ...@@ -2807,6 +2812,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
...@@ -2857,6 +2874,7 @@ my_bool translog_init(const char *directory, ...@@ -2857,6 +2874,7 @@ my_bool translog_init(const char *directory,
sizeof(struct st_file_counter), sizeof(struct st_file_counter),
10, 10)) 10, 10))
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;
...@@ -2873,8 +2891,8 @@ my_bool translog_init(const char *directory, ...@@ -2873,8 +2891,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 */
...@@ -6833,7 +6851,7 @@ my_bool translog_is_file(uint file_no) ...@@ -6833,7 +6851,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);
...@@ -7007,7 +7025,7 @@ LSN translog_first_lsn_in_log() ...@@ -7007,7 +7025,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
...@@ -7043,7 +7061,7 @@ LSN translog_first_theoretical_lsn() ...@@ -7043,7 +7061,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
...@@ -7066,7 +7084,6 @@ my_bool translog_purge(TRANSLOG_ADDRESS low) ...@@ -7066,7 +7084,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);
...@@ -7080,14 +7097,140 @@ my_bool translog_purge(TRANSLOG_ADDRESS low) ...@@ -7080,14 +7097,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);
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); translog_mutex_unlock(&log_descriptor.purger_lock);
DBUG_RETURN(rc); 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
...@@ -307,6 +309,12 @@ extern my_bool translog_inited; ...@@ -307,6 +309,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
...@@ -388,6 +396,15 @@ typedef struct st_log_record_type_descriptor ...@@ -388,6 +396,15 @@ 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];
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 typedef enum
{ {
TRANSLOG_SYNC_DIR_NEVER, TRANSLOG_SYNC_DIR_NEVER,
......
...@@ -2877,8 +2877,9 @@ static void print_redo_phase_progress(TRANSLOG_ADDRESS addr) ...@@ -2877,8 +2877,9 @@ static void print_redo_phase_progress(TRANSLOG_ADDRESS addr)
cur_logno= LSN_FILE_NO(addr); cur_logno= LSN_FILE_NO(addr);
cur_offset= LSN_OFFSET(addr); cur_offset= LSN_OFFSET(addr);
local_remainder= (cur_logno == end_logno) ? (end_offset - cur_offset) : local_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= local_remainder; initial_remainder= local_remainder;
percentage_done= ((initial_remainder - local_remainder) * ULL(100) / percentage_done= ((initial_remainder - local_remainder) * ULL(100) /
......
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