Store maximum transaction id into control file at clean shutdown.
This can serve to maria_chk to check that trids found in rows and keys are not too big. Also used by Recovery when logs are lost. Options --require-control-file, --datadir, --log-dir (yes, the dashes are inconsistent but I imitated mysqld --datadir and --maria-log-dir) for maria_chk. Lock control file _before_ reading its content. storage/maria/ha_maria.cc: new prototype storage/maria/ma_check.c: A function to find the max trid in the system (consults transaction manager and control file), to check tables. storage/maria/ma_checkpoint.c: new prototype storage/maria/ma_control_file.c: Store max trid into control file, in a backward-compatible way (can still read old control files). Parameter to ma_control_file_open(), to not create the log if it's missing (maria_chk needs that). Lock control file _before_ reading its content. Fix for a segfault when reading an old control file (bzero() with a negative second argument) storage/maria/ma_control_file.h: changes to the control file module's API storage/maria/ma_init.c: When Maria shuts down cleanly, store max trid into control file. storage/maria/ma_loghandler.c: new prototype storage/maria/ma_recovery.c: During recovery, consult max trid stored in control file, in case it is bigger than what we found in log (case of logs manually removed by user). storage/maria/ma_test1.c: new prototype storage/maria/ma_test2.c: new prototype storage/maria/maria_chk.c: New option --require-control-file (abort if control file not found), --datadir (path for control file (and for logs if --log-dir not specified)), --log-dir (path for logs). Try to open control file when maria_chk starts. storage/maria/maria_read_log.c: new prototype storage/maria/trnman.c: A new function to know max trid in transaction manager storage/maria/trnman_public.h: New function storage/maria/unittest/ma_control_file-t.c: new prototypes. Testing storing and retrieving the max trid to/from control file storage/maria/unittest/ma_test_loghandler-t.c: new prototype storage/maria/unittest/ma_test_loghandler_first_lsn-t.c: new prototype storage/maria/unittest/ma_test_loghandler_max_lsn-t.c: new prototype storage/maria/unittest/ma_test_loghandler_multigroup-t.c: new prototype storage/maria/unittest/ma_test_loghandler_multithread-t.c: new prototype storage/maria/unittest/ma_test_loghandler_noflush-t.c: new prototype storage/maria/unittest/ma_test_loghandler_nologs-t.c: new prototype storage/maria/unittest/ma_test_loghandler_pagecache-t.c: new prototype storage/maria/unittest/ma_test_loghandler_purge-t.c: new prototype
This commit is contained in:
parent
42f970de3c
commit
722a8ebe5b
@ -2768,7 +2768,7 @@ static int ha_maria_init(void *p)
|
|||||||
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));
|
||||||
maria_tmpdir= &mysql_tmpdir_list; /* For REDO */
|
maria_tmpdir= &mysql_tmpdir_list; /* For REDO */
|
||||||
res= maria_init() || ma_control_file_create_or_open() ||
|
res= maria_init() || ma_control_file_open(TRUE) ||
|
||||||
!init_pagecache(maria_pagecache,
|
!init_pagecache(maria_pagecache,
|
||||||
(size_t) pagecache_buffer_size, pagecache_division_limit,
|
(size_t) pagecache_buffer_size, pagecache_division_limit,
|
||||||
pagecache_age_threshold, maria_block_size, 0) ||
|
pagecache_age_threshold, maria_block_size, 0) ||
|
||||||
|
@ -98,6 +98,7 @@ static void report_keypage_fault(HA_CHECK *param, MARIA_HA *info,
|
|||||||
static my_bool create_new_data_handle(MARIA_SORT_PARAM *param, File new_file);
|
static my_bool create_new_data_handle(MARIA_SORT_PARAM *param, File new_file);
|
||||||
static my_bool _ma_flush_table_files_before_swap(HA_CHECK *param,
|
static my_bool _ma_flush_table_files_before_swap(HA_CHECK *param,
|
||||||
MARIA_HA *info);
|
MARIA_HA *info);
|
||||||
|
static TrID max_trid_in_system(void);
|
||||||
|
|
||||||
|
|
||||||
void maria_chk_init(HA_CHECK *param)
|
void maria_chk_init(HA_CHECK *param)
|
||||||
@ -6444,3 +6445,21 @@ static void report_keypage_fault(HA_CHECK *param, MARIA_HA *info,
|
|||||||
"error: %d",
|
"error: %d",
|
||||||
llstr(position / block_size, buff), my_errno);
|
llstr(position / block_size, buff), my_errno);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
When we want to check a table, we verify that the transaction ids of rows
|
||||||
|
and keys are not bigger than the biggest id generated by Maria so far, which
|
||||||
|
is returned by the function below.
|
||||||
|
|
||||||
|
@note If control file is not open, 0 may be returned; to not confuse
|
||||||
|
this with a valid max trid of 0, the caller should notice that it failed to
|
||||||
|
open the control file (ma_control_file_inited() can serve for that).
|
||||||
|
*/
|
||||||
|
|
||||||
|
static TrID max_trid_in_system(void)
|
||||||
|
{
|
||||||
|
TrID id= trnman_get_max_trid(); /* 0 if transac manager not initialized */
|
||||||
|
/* 'id' may be far bigger, if last shutdown is old */
|
||||||
|
return max(id, max_trid_in_control_file);
|
||||||
|
}
|
||||||
|
@ -244,8 +244,8 @@ static int really_execute_checkpoint(void)
|
|||||||
such hook would be called before translog_flush (and we must be sure
|
such hook would be called before translog_flush (and we must be sure
|
||||||
that log was flushed before we write to the control file).
|
that log was flushed before we write to the control file).
|
||||||
*/
|
*/
|
||||||
if (unlikely(ma_control_file_write_and_force(lsn, FILENO_IMPOSSIBLE,
|
if (unlikely(ma_control_file_write_and_force(lsn, last_logno,
|
||||||
CONTROL_FILE_UPDATE_ONLY_LSN)))
|
max_trid_in_control_file)))
|
||||||
{
|
{
|
||||||
translog_unlock();
|
translog_unlock();
|
||||||
goto err;
|
goto err;
|
||||||
|
@ -77,8 +77,9 @@ one should increment the control file version number.
|
|||||||
#define CF_LSN_SIZE LSN_STORE_SIZE
|
#define CF_LSN_SIZE LSN_STORE_SIZE
|
||||||
#define CF_FILENO_OFFSET (CF_LSN_OFFSET + CF_LSN_SIZE)
|
#define CF_FILENO_OFFSET (CF_LSN_OFFSET + CF_LSN_SIZE)
|
||||||
#define CF_FILENO_SIZE 4
|
#define CF_FILENO_SIZE 4
|
||||||
|
#define CF_MAX_TRID_OFFSET (CF_FILENO_OFFSET + CF_FILENO_SIZE)
|
||||||
#define CF_CHANGEABLE_TOTAL_SIZE (CF_FILENO_OFFSET + CF_FILENO_SIZE)
|
#define CF_MAX_TRID_SIZE TRANSID_SIZE
|
||||||
|
#define CF_CHANGEABLE_TOTAL_SIZE (CF_MAX_TRID_OFFSET + CF_MAX_TRID_SIZE)
|
||||||
|
|
||||||
/*
|
/*
|
||||||
The following values should not be changed, except when changing version
|
The following values should not be changed, except when changing version
|
||||||
@ -100,6 +101,11 @@ one should increment the control file version number.
|
|||||||
*/
|
*/
|
||||||
LSN last_checkpoint_lsn= LSN_IMPOSSIBLE;
|
LSN last_checkpoint_lsn= LSN_IMPOSSIBLE;
|
||||||
uint32 last_logno= FILENO_IMPOSSIBLE;
|
uint32 last_logno= FILENO_IMPOSSIBLE;
|
||||||
|
/**
|
||||||
|
The maximum transaction id given to a transaction. It is only updated at
|
||||||
|
clean shutdown (in case of crash, logs have better information).
|
||||||
|
*/
|
||||||
|
TrID max_trid_in_control_file= 0;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@brief If log's lock should be asserted when writing to control file.
|
@brief If log's lock should be asserted when writing to control file.
|
||||||
@ -131,9 +137,6 @@ static CONTROL_FILE_ERROR create_control_file(const char *name,
|
|||||||
uchar buffer[CF_CREATE_TIME_TOTAL_SIZE];
|
uchar buffer[CF_CREATE_TIME_TOTAL_SIZE];
|
||||||
DBUG_ENTER("maria_create_control_file");
|
DBUG_ENTER("maria_create_control_file");
|
||||||
|
|
||||||
/* in a recovery, we expect to find a control file */
|
|
||||||
if (maria_in_recovery)
|
|
||||||
DBUG_RETURN(CONTROL_FILE_MISSING);
|
|
||||||
if ((control_file_fd= my_create(name, 0,
|
if ((control_file_fd= my_create(name, 0,
|
||||||
open_flags,
|
open_flags,
|
||||||
MYF(MY_SYNC_DIR | MY_WME))) < 0)
|
MYF(MY_SYNC_DIR | MY_WME))) < 0)
|
||||||
@ -164,7 +167,7 @@ static CONTROL_FILE_ERROR create_control_file(const char *name,
|
|||||||
|
|
||||||
if (my_pwrite(control_file_fd, buffer, cf_create_time_size,
|
if (my_pwrite(control_file_fd, buffer, cf_create_time_size,
|
||||||
0, MYF(MY_FNABP | MY_WME)))
|
0, MYF(MY_FNABP | MY_WME)))
|
||||||
DBUG_RETURN(1);
|
DBUG_RETURN(CONTROL_FILE_UNKNOWN_ERROR);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
To be safer we should make sure that there are no logs or data/index
|
To be safer we should make sure that there are no logs or data/index
|
||||||
@ -184,10 +187,50 @@ static CONTROL_FILE_ERROR create_control_file(const char *name,
|
|||||||
|
|
||||||
/* init the file with these "undefined" values */
|
/* init the file with these "undefined" values */
|
||||||
DBUG_RETURN(ma_control_file_write_and_force(LSN_IMPOSSIBLE,
|
DBUG_RETURN(ma_control_file_write_and_force(LSN_IMPOSSIBLE,
|
||||||
FILENO_IMPOSSIBLE,
|
FILENO_IMPOSSIBLE, 0));
|
||||||
CONTROL_FILE_UPDATE_ALL));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
Locks control file exclusively. This is kept for the duration of the engine
|
||||||
|
process, to prevent another Maria instance to write to our logs or control
|
||||||
|
file.
|
||||||
|
*/
|
||||||
|
|
||||||
|
static int lock_control_file(const char *name)
|
||||||
|
{
|
||||||
|
uint retry= 0;
|
||||||
|
/*
|
||||||
|
On Windows, my_lock() uses locking() which is mandatory locking and so
|
||||||
|
prevents maria-recovery.test from copying the control file. And in case of
|
||||||
|
crash, it may take a while for Windows to unlock file, causing downtime.
|
||||||
|
*/
|
||||||
|
/**
|
||||||
|
@todo BUG We should explore my_sopen(_SH_DENYWRD) to open or create the
|
||||||
|
file under Windows.
|
||||||
|
*/
|
||||||
|
#ifndef __WIN__
|
||||||
|
/*
|
||||||
|
We can't here use the automatic wait in my_lock() as the alarm thread
|
||||||
|
may not yet exists.
|
||||||
|
*/
|
||||||
|
while (my_lock(control_file_fd, F_WRLCK, 0L, F_TO_EOF,
|
||||||
|
MYF(MY_SEEK_NOT_DONE | MY_FORCE_LOCK | MY_NO_WAIT)))
|
||||||
|
{
|
||||||
|
if (retry == 0)
|
||||||
|
my_printf_error(HA_ERR_INITIALIZATION,
|
||||||
|
"Can't lock maria control file '%s' for exclusive use, "
|
||||||
|
"error: %d. Will retry for %d seconds", 0,
|
||||||
|
name, my_errno, MARIA_MAX_CONTROL_FILE_LOCK_RETRY);
|
||||||
|
if (retry++ > MARIA_MAX_CONTROL_FILE_LOCK_RETRY)
|
||||||
|
return 1;
|
||||||
|
sleep(1);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@brief Initialize control file subsystem
|
@brief Initialize control file subsystem
|
||||||
|
|
||||||
@ -200,24 +243,24 @@ static CONTROL_FILE_ERROR create_control_file(const char *name,
|
|||||||
The format of the control file is defined in the comments and defines
|
The format of the control file is defined in the comments and defines
|
||||||
at the start of this file.
|
at the start of this file.
|
||||||
|
|
||||||
@note If in recovery, file is not created
|
@param create_if_missing create file if not found
|
||||||
|
|
||||||
@return Operation status
|
@return Operation status
|
||||||
@retval 0 OK
|
@retval 0 OK
|
||||||
@retval 1 Error (in which case the file is left closed)
|
@retval 1 Error (in which case the file is left closed)
|
||||||
*/
|
*/
|
||||||
|
|
||||||
CONTROL_FILE_ERROR ma_control_file_create_or_open()
|
CONTROL_FILE_ERROR ma_control_file_open(my_bool create_if_missing)
|
||||||
{
|
{
|
||||||
uchar buffer[CF_MAX_SIZE];
|
uchar buffer[CF_MAX_SIZE];
|
||||||
char name[FN_REFLEN], errmsg_buff[256];
|
char name[FN_REFLEN], errmsg_buff[256];
|
||||||
const char *errmsg;
|
const char *errmsg, *lock_failed_errmsg= "Could not get an exclusive lock;"
|
||||||
|
" file is probably in use by another process";
|
||||||
uint new_cf_create_time_size, new_cf_changeable_size, new_block_size;
|
uint new_cf_create_time_size, new_cf_changeable_size, new_block_size;
|
||||||
uint retry;
|
|
||||||
my_off_t file_size;
|
my_off_t file_size;
|
||||||
int open_flags= O_BINARY | /*O_DIRECT |*/ O_RDWR;
|
int open_flags= O_BINARY | /*O_DIRECT |*/ O_RDWR;
|
||||||
int error= CONTROL_FILE_UNKNOWN_ERROR;
|
int error= CONTROL_FILE_UNKNOWN_ERROR;
|
||||||
DBUG_ENTER("ma_control_file_create_or_open");
|
DBUG_ENTER("ma_control_file_open");
|
||||||
|
|
||||||
/*
|
/*
|
||||||
If you change sizes in the #defines, you at least have to change the
|
If you change sizes in the #defines, you at least have to change the
|
||||||
@ -236,12 +279,25 @@ CONTROL_FILE_ERROR ma_control_file_create_or_open()
|
|||||||
|
|
||||||
if (my_access(name,F_OK))
|
if (my_access(name,F_OK))
|
||||||
{
|
{
|
||||||
if (create_control_file(name, open_flags))
|
CONTROL_FILE_ERROR create_error;
|
||||||
|
if (!create_if_missing)
|
||||||
{
|
{
|
||||||
|
error= CONTROL_FILE_MISSING;
|
||||||
|
errmsg= "Can't find file";
|
||||||
|
goto err;
|
||||||
|
}
|
||||||
|
if ((create_error= create_control_file(name, open_flags)))
|
||||||
|
{
|
||||||
|
error= create_error;
|
||||||
errmsg= "Can't create file";
|
errmsg= "Can't create file";
|
||||||
goto err;
|
goto err;
|
||||||
}
|
}
|
||||||
goto lock_file;
|
if (lock_control_file(name))
|
||||||
|
{
|
||||||
|
errmsg= lock_failed_errmsg;
|
||||||
|
goto err;
|
||||||
|
}
|
||||||
|
goto ok;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Otherwise, file exists */
|
/* Otherwise, file exists */
|
||||||
@ -252,6 +308,12 @@ CONTROL_FILE_ERROR ma_control_file_create_or_open()
|
|||||||
goto err;
|
goto err;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (lock_control_file(name)) /* lock it before reading content */
|
||||||
|
{
|
||||||
|
errmsg= lock_failed_errmsg;
|
||||||
|
goto err;
|
||||||
|
}
|
||||||
|
|
||||||
file_size= my_seek(control_file_fd, 0, SEEK_END, MYF(MY_WME));
|
file_size= my_seek(control_file_fd, 0, SEEK_END, MYF(MY_WME));
|
||||||
if (file_size == MY_FILEPOS_ERROR)
|
if (file_size == MY_FILEPOS_ERROR)
|
||||||
{
|
{
|
||||||
@ -343,7 +405,7 @@ CONTROL_FILE_ERROR ma_control_file_create_or_open()
|
|||||||
uint4korr(buffer + new_cf_create_time_size))
|
uint4korr(buffer + new_cf_create_time_size))
|
||||||
{
|
{
|
||||||
error= CONTROL_FILE_BAD_CHECKSUM;
|
error= CONTROL_FILE_BAD_CHECKSUM;
|
||||||
errmsg= "Changeable part (end of control file) checksum missmatch";
|
errmsg= "Changeable part (end of control file) checksum mismatch";
|
||||||
goto err;
|
goto err;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -353,57 +415,29 @@ CONTROL_FILE_ERROR ma_control_file_create_or_open()
|
|||||||
last_checkpoint_lsn= lsn_korr(buffer + new_cf_create_time_size +
|
last_checkpoint_lsn= lsn_korr(buffer + new_cf_create_time_size +
|
||||||
CF_LSN_OFFSET);
|
CF_LSN_OFFSET);
|
||||||
last_logno= uint4korr(buffer + new_cf_create_time_size + CF_FILENO_OFFSET);
|
last_logno= uint4korr(buffer + new_cf_create_time_size + CF_FILENO_OFFSET);
|
||||||
|
if (new_cf_changeable_size >= (CF_MAX_TRID_OFFSET + CF_MAX_TRID_SIZE))
|
||||||
|
max_trid_in_control_file=
|
||||||
|
transid_korr(buffer + new_cf_create_time_size + CF_MAX_TRID_OFFSET);
|
||||||
|
|
||||||
lock_file:
|
ok:
|
||||||
retry= 0;
|
|
||||||
|
|
||||||
/*
|
|
||||||
On Windows, my_lock() uses locking() which is mandatory locking and so
|
|
||||||
prevents maria-recovery.test from copying the control file. And in case of
|
|
||||||
crash, it may take a while for Windows to unlock file, causing downtime.
|
|
||||||
*/
|
|
||||||
/**
|
|
||||||
@todo BUG We should explore my_sopen(_SH_DENYWRD) to open or create the
|
|
||||||
file under Windows.
|
|
||||||
*/
|
|
||||||
#ifndef __WIN__
|
|
||||||
/*
|
|
||||||
We can't here use the automatic wait in my_lock() as the alarm thread
|
|
||||||
may not yet exists.
|
|
||||||
*/
|
|
||||||
while (my_lock(control_file_fd, F_WRLCK, 0L, F_TO_EOF,
|
|
||||||
MYF(MY_SEEK_NOT_DONE | MY_FORCE_LOCK | MY_NO_WAIT)))
|
|
||||||
{
|
|
||||||
if (retry == 0)
|
|
||||||
my_printf_error(HA_ERR_INITIALIZATION,
|
|
||||||
"Can't lock maria control file '%s' for exclusive use, "
|
|
||||||
"error: %d. Will retry for %d seconds", 0,
|
|
||||||
name, my_errno, MARIA_MAX_CONTROL_FILE_LOCK_RETRY);
|
|
||||||
if (retry++ > MARIA_MAX_CONTROL_FILE_LOCK_RETRY)
|
|
||||||
{
|
|
||||||
errmsg= "Could not get an exclusive lock; file is probably in use by another process";
|
|
||||||
goto err;
|
|
||||||
}
|
|
||||||
sleep(1);
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
DBUG_RETURN(0);
|
DBUG_RETURN(0);
|
||||||
|
|
||||||
err:
|
err:
|
||||||
my_printf_error(HA_ERR_INITIALIZATION,
|
my_printf_error(HA_ERR_INITIALIZATION,
|
||||||
"Error when trying to use maria control file '%s': %s", 0,
|
"Error when trying to use maria control file '%s': %s", 0,
|
||||||
name, errmsg);
|
name, errmsg);
|
||||||
ma_control_file_end();
|
ma_control_file_end(); /* will unlock file if needed */
|
||||||
DBUG_RETURN(error);
|
DBUG_RETURN(error);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Write information durably to the control file; stores this information into
|
Write information durably to the control file; stores this information into
|
||||||
the last_checkpoint_lsn and last_logno global variables.
|
the last_checkpoint_lsn, last_logno, max_trid_in_control_file global
|
||||||
Called when we have created a new log (after syncing this log's creation)
|
variables.
|
||||||
and when we have written a checkpoint (after syncing this log record).
|
Called when we have created a new log (after syncing this log's creation),
|
||||||
|
when we have written a checkpoint (after syncing this log record), and at
|
||||||
|
shutdown (for storing trid in case logs are soon removed by user).
|
||||||
Variables last_checkpoint_lsn and last_logno must be protected by caller
|
Variables last_checkpoint_lsn and last_logno must be protected by caller
|
||||||
using log's lock, unless this function is called at startup.
|
using log's lock, unless this function is called at startup.
|
||||||
|
|
||||||
@ -411,13 +445,7 @@ err:
|
|||||||
ma_control_file_write_and_force()
|
ma_control_file_write_and_force()
|
||||||
checkpoint_lsn LSN of last checkpoint
|
checkpoint_lsn LSN of last checkpoint
|
||||||
logno last log file number
|
logno last log file number
|
||||||
objs_to_write which of the arguments should be used as new values
|
trid maximum transaction longid.
|
||||||
(for example, CF_UPDATE_ONLY_LSN will not
|
|
||||||
write the logno argument to the control file and will
|
|
||||||
not update the last_logno global variable); can be:
|
|
||||||
CF_UPDATE_ALL
|
|
||||||
CF_UPDATE_ONLY_LSN
|
|
||||||
CF_UPDATE_ONLY_LOGNO.
|
|
||||||
|
|
||||||
NOTE
|
NOTE
|
||||||
We always want to do one single my_pwrite() here to be as atomic as
|
We always want to do one single my_pwrite() here to be as atomic as
|
||||||
@ -428,11 +456,10 @@ err:
|
|||||||
1 - Error
|
1 - Error
|
||||||
*/
|
*/
|
||||||
|
|
||||||
int ma_control_file_write_and_force(const LSN checkpoint_lsn, uint32 logno,
|
int ma_control_file_write_and_force(LSN checkpoint_lsn, uint32 logno,
|
||||||
uint objs_to_write)
|
TrID trid)
|
||||||
{
|
{
|
||||||
char buffer[CF_MAX_SIZE];
|
uchar buffer[CF_MAX_SIZE];
|
||||||
my_bool update_checkpoint_lsn= FALSE, update_logno= FALSE;
|
|
||||||
uint32 sum;
|
uint32 sum;
|
||||||
DBUG_ENTER("ma_control_file_write_and_force");
|
DBUG_ENTER("ma_control_file_write_and_force");
|
||||||
|
|
||||||
@ -442,48 +469,38 @@ int ma_control_file_write_and_force(const LSN checkpoint_lsn, uint32 logno,
|
|||||||
translog_lock_handler_assert_owner();
|
translog_lock_handler_assert_owner();
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
if (objs_to_write == CONTROL_FILE_UPDATE_ONLY_LSN)
|
lsn_store(buffer + CF_LSN_OFFSET, checkpoint_lsn);
|
||||||
update_checkpoint_lsn= TRUE;
|
int4store(buffer + CF_FILENO_OFFSET, logno);
|
||||||
else if (objs_to_write == CONTROL_FILE_UPDATE_ONLY_LOGNO)
|
transid_store(buffer + CF_MAX_TRID_OFFSET, trid);
|
||||||
update_logno= TRUE;
|
|
||||||
else if (objs_to_write == CONTROL_FILE_UPDATE_ALL)
|
|
||||||
update_checkpoint_lsn= update_logno= TRUE;
|
|
||||||
else /* incorrect value of objs_to_write */
|
|
||||||
DBUG_ASSERT(0);
|
|
||||||
|
|
||||||
if (update_checkpoint_lsn)
|
|
||||||
lsn_store(buffer + CF_LSN_OFFSET, checkpoint_lsn);
|
|
||||||
else /* store old value == change nothing */
|
|
||||||
lsn_store(buffer + CF_LSN_OFFSET, last_checkpoint_lsn);
|
|
||||||
|
|
||||||
if (update_logno)
|
|
||||||
int4store(buffer + CF_FILENO_OFFSET, logno);
|
|
||||||
else
|
|
||||||
int4store(buffer + CF_FILENO_OFFSET, last_logno);
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Clear unknown part of changeable part.
|
Clear unknown part of changeable part, if bigger than ours.
|
||||||
Other option would be to remember the original values in the file
|
Other option would be to remember the original values in the file
|
||||||
and copy them here, but this should be safer.
|
and copy them here, but this should be safer.
|
||||||
*/
|
*/
|
||||||
bzero(buffer + CF_CHANGEABLE_TOTAL_SIZE,
|
if (cf_changeable_size > CF_CHANGEABLE_TOTAL_SIZE)
|
||||||
cf_changeable_size - CF_CHANGEABLE_TOTAL_SIZE);
|
bzero(buffer + CF_CHANGEABLE_TOTAL_SIZE,
|
||||||
|
cf_changeable_size - CF_CHANGEABLE_TOTAL_SIZE);
|
||||||
|
|
||||||
/* Checksum is stored first */
|
/* Checksum is stored first */
|
||||||
compile_time_assert(CF_CHECKSUM_OFFSET == 0);
|
compile_time_assert(CF_CHECKSUM_OFFSET == 0);
|
||||||
sum= my_checksum(0, (const uchar *) buffer + CF_CHECKSUM_SIZE,
|
sum= my_checksum(0, buffer + CF_CHECKSUM_SIZE,
|
||||||
cf_changeable_size - CF_CHECKSUM_SIZE);
|
cf_changeable_size - CF_CHECKSUM_SIZE);
|
||||||
int4store(buffer, sum);
|
int4store(buffer, sum);
|
||||||
|
|
||||||
if (my_pwrite(control_file_fd, (uchar *) buffer, cf_changeable_size,
|
/**
|
||||||
|
@todo BUG by reusing the cf_changeable_size of the old control file (from
|
||||||
|
an old server), it does not write the new parts featured by the running
|
||||||
|
server (like max_trid), is it expected?
|
||||||
|
*/
|
||||||
|
if (my_pwrite(control_file_fd, buffer, cf_changeable_size,
|
||||||
cf_create_time_size, MYF(MY_FNABP | MY_WME)) ||
|
cf_create_time_size, MYF(MY_FNABP | MY_WME)) ||
|
||||||
my_sync(control_file_fd, MYF(MY_WME)))
|
my_sync(control_file_fd, MYF(MY_WME)))
|
||||||
DBUG_RETURN(1);
|
DBUG_RETURN(1);
|
||||||
|
|
||||||
if (update_checkpoint_lsn)
|
last_checkpoint_lsn= checkpoint_lsn;
|
||||||
last_checkpoint_lsn= checkpoint_lsn;
|
last_logno= logno;
|
||||||
if (update_logno)
|
max_trid_in_control_file= trid;
|
||||||
last_logno= logno;
|
|
||||||
|
|
||||||
DBUG_RETURN(0);
|
DBUG_RETURN(0);
|
||||||
}
|
}
|
||||||
@ -496,7 +513,7 @@ int ma_control_file_write_and_force(const LSN checkpoint_lsn, uint32 logno,
|
|||||||
ma_control_file_end()
|
ma_control_file_end()
|
||||||
*/
|
*/
|
||||||
|
|
||||||
int ma_control_file_end()
|
int ma_control_file_end(void)
|
||||||
{
|
{
|
||||||
int close_error;
|
int close_error;
|
||||||
DBUG_ENTER("ma_control_file_end");
|
DBUG_ENTER("ma_control_file_end");
|
||||||
@ -521,8 +538,19 @@ int ma_control_file_end()
|
|||||||
*/
|
*/
|
||||||
last_checkpoint_lsn= LSN_IMPOSSIBLE;
|
last_checkpoint_lsn= LSN_IMPOSSIBLE;
|
||||||
last_logno= FILENO_IMPOSSIBLE;
|
last_logno= FILENO_IMPOSSIBLE;
|
||||||
|
max_trid_in_control_file= 0;
|
||||||
|
|
||||||
DBUG_RETURN(close_error);
|
DBUG_RETURN(close_error);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
Tells if control file is initialized.
|
||||||
|
*/
|
||||||
|
|
||||||
|
my_bool ma_control_file_inited(void)
|
||||||
|
{
|
||||||
|
return (control_file_fd >= 0);
|
||||||
|
}
|
||||||
|
|
||||||
#endif /* EXTRACT_DEFINITIONS */
|
#endif /* EXTRACT_DEFINITIONS */
|
||||||
|
@ -42,6 +42,8 @@ extern LSN last_checkpoint_lsn;
|
|||||||
*/
|
*/
|
||||||
extern uint32 last_logno;
|
extern uint32 last_logno;
|
||||||
|
|
||||||
|
extern TrID max_trid_in_control_file;
|
||||||
|
|
||||||
extern my_bool maria_multi_threaded, maria_in_recovery;
|
extern my_bool maria_multi_threaded, maria_in_recovery;
|
||||||
|
|
||||||
typedef enum enum_control_file_error {
|
typedef enum enum_control_file_error {
|
||||||
@ -58,33 +60,10 @@ typedef enum enum_control_file_error {
|
|||||||
CONTROL_FILE_UNKNOWN_ERROR /* any other error */
|
CONTROL_FILE_UNKNOWN_ERROR /* any other error */
|
||||||
} CONTROL_FILE_ERROR;
|
} CONTROL_FILE_ERROR;
|
||||||
|
|
||||||
#define CONTROL_FILE_UPDATE_ALL 0
|
C_MODE_START
|
||||||
#define CONTROL_FILE_UPDATE_ONLY_LSN 1
|
CONTROL_FILE_ERROR ma_control_file_open(my_bool create_if_missing);
|
||||||
#define CONTROL_FILE_UPDATE_ONLY_LOGNO 2
|
int ma_control_file_write_and_force(LSN checkpoint_lsn, uint32 logno, TrID trid);
|
||||||
|
int ma_control_file_end(void);
|
||||||
#ifdef __cplusplus
|
my_bool ma_control_file_inited(void);
|
||||||
extern "C" {
|
C_MODE_END
|
||||||
#endif
|
|
||||||
|
|
||||||
/*
|
|
||||||
Looks for the control file. If none and creation was requested, creates file.
|
|
||||||
If present, reads it to find out last checkpoint's LSN and last log.
|
|
||||||
Called at engine's start.
|
|
||||||
*/
|
|
||||||
CONTROL_FILE_ERROR ma_control_file_create_or_open();
|
|
||||||
/*
|
|
||||||
Write information durably to the control file.
|
|
||||||
Called when we have created a new log (after syncing this log's creation)
|
|
||||||
and when we have written a checkpoint (after syncing this log record).
|
|
||||||
*/
|
|
||||||
int ma_control_file_write_and_force(const LSN checkpoint_lsn, uint32 logno,
|
|
||||||
uint objs_to_write);
|
|
||||||
|
|
||||||
|
|
||||||
/* Free resources taken by control file subsystem */
|
|
||||||
int ma_control_file_end();
|
|
||||||
|
|
||||||
#ifdef __cplusplus
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
#endif
|
#endif
|
||||||
|
@ -52,9 +52,20 @@ void maria_end(void)
|
|||||||
{
|
{
|
||||||
if (maria_inited)
|
if (maria_inited)
|
||||||
{
|
{
|
||||||
|
TrID trid;
|
||||||
maria_inited= maria_multi_threaded= FALSE;
|
maria_inited= maria_multi_threaded= FALSE;
|
||||||
ft_free_stopwords();
|
ft_free_stopwords();
|
||||||
ma_checkpoint_end();
|
ma_checkpoint_end();
|
||||||
|
if (ma_control_file_inited() &&
|
||||||
|
((trid= trnman_get_max_trid()) > max_trid_in_control_file))
|
||||||
|
{
|
||||||
|
/*
|
||||||
|
Store max transaction id into control file, in case logs are removed
|
||||||
|
by user, or maria_chk wants to check tables (it cannot access max trid
|
||||||
|
from the log, as it cannot process REDOs).
|
||||||
|
*/
|
||||||
|
ma_control_file_write_and_force(last_checkpoint_lsn, last_logno, trid);
|
||||||
|
}
|
||||||
trnman_destroy();
|
trnman_destroy();
|
||||||
if (translog_status == TRANSLOG_OK)
|
if (translog_status == TRANSLOG_OK)
|
||||||
translog_destroy();
|
translog_destroy();
|
||||||
|
@ -1519,8 +1519,8 @@ static my_bool translog_create_new_file()
|
|||||||
if (translog_write_file_header())
|
if (translog_write_file_header())
|
||||||
DBUG_RETURN(1);
|
DBUG_RETURN(1);
|
||||||
|
|
||||||
if (ma_control_file_write_and_force(LSN_IMPOSSIBLE, file_no,
|
if (ma_control_file_write_and_force(last_checkpoint_lsn, file_no,
|
||||||
CONTROL_FILE_UPDATE_ONLY_LOGNO))
|
max_trid_in_control_file))
|
||||||
{
|
{
|
||||||
translog_stop_writing();
|
translog_stop_writing();
|
||||||
DBUG_RETURN(1);
|
DBUG_RETURN(1);
|
||||||
@ -3697,7 +3697,7 @@ my_bool translog_init_with_table(const char *directory,
|
|||||||
log_descriptor.open_files.elements);
|
log_descriptor.open_files.elements);
|
||||||
|
|
||||||
if (ma_control_file_write_and_force(checkpoint_lsn, start_file_num,
|
if (ma_control_file_write_and_force(checkpoint_lsn, start_file_num,
|
||||||
CONTROL_FILE_UPDATE_ALL))
|
max_trid_in_control_file))
|
||||||
DBUG_RETURN(1);
|
DBUG_RETURN(1);
|
||||||
/* assign buffer 0 */
|
/* assign buffer 0 */
|
||||||
translog_start_buffer(log_descriptor.buffers, &log_descriptor.bc, 0);
|
translog_start_buffer(log_descriptor.buffers, &log_descriptor.bc, 0);
|
||||||
|
@ -2509,6 +2509,14 @@ static uint end_of_redo_phase(my_bool prepare_for_undo_phase)
|
|||||||
|
|
||||||
llstr(max_long_trid, llbuf);
|
llstr(max_long_trid, llbuf);
|
||||||
tprint(tracef, "Maximum transaction long id seen: %s\n", llbuf);
|
tprint(tracef, "Maximum transaction long id seen: %s\n", llbuf);
|
||||||
|
llstr(max_trid_in_control_file, llbuf);
|
||||||
|
tprint(tracef, "Maximum transaction long id seen in control file: %s\n",
|
||||||
|
llbuf);
|
||||||
|
/*
|
||||||
|
If logs were deleted, or lost, trid in control file is needed to set
|
||||||
|
trnman's generator:
|
||||||
|
*/
|
||||||
|
set_if_bigger(max_long_trid, max_trid_in_control_file);
|
||||||
if (prepare_for_undo_phase && trnman_init(max_long_trid))
|
if (prepare_for_undo_phase && trnman_init(max_long_trid))
|
||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
|
@ -77,7 +77,7 @@ int main(int argc,char *argv[])
|
|||||||
if (maria_init() ||
|
if (maria_init() ||
|
||||||
(init_pagecache(maria_pagecache, maria_block_size * 16, 0, 0,
|
(init_pagecache(maria_pagecache, maria_block_size * 16, 0, 0,
|
||||||
maria_block_size, MY_WME) == 0) ||
|
maria_block_size, MY_WME) == 0) ||
|
||||||
ma_control_file_create_or_open() ||
|
ma_control_file_open(TRUE) ||
|
||||||
(init_pagecache(maria_log_pagecache,
|
(init_pagecache(maria_log_pagecache,
|
||||||
TRANSLOG_PAGECACHE_SIZE, 0, 0,
|
TRANSLOG_PAGECACHE_SIZE, 0, 0,
|
||||||
TRANSLOG_PAGE_SIZE, MY_WME) == 0) ||
|
TRANSLOG_PAGE_SIZE, MY_WME) == 0) ||
|
||||||
|
@ -83,7 +83,7 @@ int main(int argc, char *argv[])
|
|||||||
if (maria_init() ||
|
if (maria_init() ||
|
||||||
(init_pagecache(maria_pagecache, pagecache_size, 0, 0,
|
(init_pagecache(maria_pagecache, pagecache_size, 0, 0,
|
||||||
maria_block_size, MY_WME) == 0) ||
|
maria_block_size, MY_WME) == 0) ||
|
||||||
ma_control_file_create_or_open() ||
|
ma_control_file_open(TRUE) ||
|
||||||
(init_pagecache(maria_log_pagecache,
|
(init_pagecache(maria_log_pagecache,
|
||||||
TRANSLOG_PAGECACHE_SIZE, 0, 0,
|
TRANSLOG_PAGECACHE_SIZE, 0, 0,
|
||||||
TRANSLOG_PAGE_SIZE, MY_WME) == 0) ||
|
TRANSLOG_PAGE_SIZE, MY_WME) == 0) ||
|
||||||
|
@ -37,11 +37,11 @@ SET_STACK_SIZE(9000) /* Minimum stack size for program */
|
|||||||
static uint decode_bits;
|
static uint decode_bits;
|
||||||
static char **default_argv;
|
static char **default_argv;
|
||||||
static const char *load_default_groups[]= { "maria_chk", 0 };
|
static const char *load_default_groups[]= { "maria_chk", 0 };
|
||||||
static const char *set_collation_name, *opt_tmpdir;
|
static const char *set_collation_name, *opt_tmpdir, *opt_log_dir;
|
||||||
static CHARSET_INFO *set_collation;
|
static CHARSET_INFO *set_collation;
|
||||||
static int stopwords_inited= 0;
|
static int stopwords_inited= 0;
|
||||||
static MY_TMPDIR maria_chk_tmpdir;
|
static MY_TMPDIR maria_chk_tmpdir;
|
||||||
static my_bool opt_transaction_logging, opt_debug;
|
static my_bool opt_transaction_logging, opt_debug, opt_require_control_file;
|
||||||
|
|
||||||
static const char *type_names[]=
|
static const char *type_names[]=
|
||||||
{
|
{
|
||||||
@ -97,7 +97,7 @@ int main(int argc, char **argv)
|
|||||||
int error;
|
int error;
|
||||||
MY_INIT(argv[0]);
|
MY_INIT(argv[0]);
|
||||||
|
|
||||||
maria_data_root= (char *)".";
|
opt_log_dir= maria_data_root= (char *)".";
|
||||||
maria_chk_init(&check_param);
|
maria_chk_init(&check_param);
|
||||||
check_param.opt_lock_memory= 1; /* Lock memory if possible */
|
check_param.opt_lock_memory= 1; /* Lock memory if possible */
|
||||||
check_param.using_global_keycache = 0;
|
check_param.using_global_keycache = 0;
|
||||||
@ -110,20 +110,30 @@ int main(int argc, char **argv)
|
|||||||
If we are doing a repair, user may want to store this repair into the log
|
If we are doing a repair, user may want to store this repair into the log
|
||||||
so that the log has a complete history and can be used to replay.
|
so that the log has a complete history and can be used to replay.
|
||||||
*/
|
*/
|
||||||
if (opt_transaction_logging && (check_param.testflag & T_REP_ANY) &&
|
if (opt_transaction_logging && (check_param.testflag & T_REP_ANY))
|
||||||
(ma_control_file_create_or_open() ||
|
|
||||||
init_pagecache(maria_log_pagecache,
|
|
||||||
TRANSLOG_PAGECACHE_SIZE, 0, 0,
|
|
||||||
TRANSLOG_PAGE_SIZE, MY_WME) == 0 ||
|
|
||||||
translog_init(maria_data_root, TRANSLOG_FILE_SIZE,
|
|
||||||
0, 0, maria_log_pagecache,
|
|
||||||
TRANSLOG_DEFAULT_FLAGS, 0)))
|
|
||||||
{
|
{
|
||||||
_ma_check_print_error(&check_param,
|
if (ma_control_file_open(FALSE) ||
|
||||||
"Can't initialize transaction logging. Run "
|
init_pagecache(maria_log_pagecache,
|
||||||
"recovery with switch --skip-transaction-log");
|
TRANSLOG_PAGECACHE_SIZE, 0, 0,
|
||||||
error= 1;
|
TRANSLOG_PAGE_SIZE, MY_WME) == 0 ||
|
||||||
argc= 1; /* Force loop out */
|
translog_init(opt_log_dir, TRANSLOG_FILE_SIZE,
|
||||||
|
0, 0, maria_log_pagecache,
|
||||||
|
TRANSLOG_DEFAULT_FLAGS, 0))
|
||||||
|
{
|
||||||
|
_ma_check_print_error(&check_param,
|
||||||
|
"Can't initialize transaction logging. Run "
|
||||||
|
"recovery with switch --skip-transaction-log");
|
||||||
|
error= 1;
|
||||||
|
goto end;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (ma_control_file_open(FALSE) && opt_require_control_file)
|
||||||
|
{
|
||||||
|
error= 1;
|
||||||
|
goto end;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
while (--argc >= 0)
|
while (--argc >= 0)
|
||||||
@ -156,6 +166,7 @@ int main(int argc, char **argv)
|
|||||||
VOID(fflush(stdout));
|
VOID(fflush(stdout));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
end:
|
||||||
if (check_param.total_files > 1)
|
if (check_param.total_files > 1)
|
||||||
{ /* Only if descript */
|
{ /* Only if descript */
|
||||||
char buff[22],buff2[22];
|
char buff[22],buff2[22];
|
||||||
@ -183,7 +194,8 @@ enum options_mc {
|
|||||||
OPT_SORT_KEY_BLOCKS, OPT_DECODE_BITS, OPT_FT_MIN_WORD_LEN,
|
OPT_SORT_KEY_BLOCKS, OPT_DECODE_BITS, OPT_FT_MIN_WORD_LEN,
|
||||||
OPT_FT_MAX_WORD_LEN, OPT_FT_STOPWORD_FILE,
|
OPT_FT_MAX_WORD_LEN, OPT_FT_STOPWORD_FILE,
|
||||||
OPT_MAX_RECORD_LENGTH, OPT_AUTO_CLOSE, OPT_STATS_METHOD, OPT_TRANSACTION_LOG,
|
OPT_MAX_RECORD_LENGTH, OPT_AUTO_CLOSE, OPT_STATS_METHOD, OPT_TRANSACTION_LOG,
|
||||||
OPT_SKIP_SAFEMALLOC, OPT_ZEROFILL_KEEP_LSN
|
OPT_SKIP_SAFEMALLOC, OPT_ZEROFILL_KEEP_LSN, OPT_REQUIRE_CONTROL_FILE,
|
||||||
|
OPT_LOG_DIR, OPT_DATADIR
|
||||||
};
|
};
|
||||||
|
|
||||||
static struct my_option my_long_options[] =
|
static struct my_option my_long_options[] =
|
||||||
@ -249,6 +261,13 @@ static struct my_option my_long_options[] =
|
|||||||
(uchar**) &check_param.keys_in_use,
|
(uchar**) &check_param.keys_in_use,
|
||||||
(uchar**) &check_param.keys_in_use,
|
(uchar**) &check_param.keys_in_use,
|
||||||
0, GET_ULL, REQUIRED_ARG, -1, 0, 0, 0, 0, 0},
|
0, GET_ULL, REQUIRED_ARG, -1, 0, 0, 0, 0, 0},
|
||||||
|
{"datadir", OPT_DATADIR,
|
||||||
|
"Path for control file (and logs if --log-dir not used).",
|
||||||
|
(uchar**) &maria_data_root, 0, 0, GET_STR, REQUIRED_ARG,
|
||||||
|
0, 0, 0, 0, 0, 0},
|
||||||
|
{"log-dir", OPT_LOG_DIR,
|
||||||
|
"Path for log files.",
|
||||||
|
(uchar**) &opt_log_dir, 0, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
|
||||||
{"max-record-length", OPT_MAX_RECORD_LENGTH,
|
{"max-record-length", OPT_MAX_RECORD_LENGTH,
|
||||||
"Skip rows bigger than this if maria_chk can't allocate memory to hold it",
|
"Skip rows bigger than this if maria_chk can't allocate memory to hold it",
|
||||||
(uchar**) &check_param.max_record_length,
|
(uchar**) &check_param.max_record_length,
|
||||||
@ -274,6 +293,10 @@ static struct my_option my_long_options[] =
|
|||||||
{"sort-recover", 'n',
|
{"sort-recover", 'n',
|
||||||
"Force recovering with sorting even if the temporary file was very big.",
|
"Force recovering with sorting even if the temporary file was very big.",
|
||||||
0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0},
|
0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0},
|
||||||
|
{ "require-control-file", OPT_REQUIRE_CONTROL_FILE,
|
||||||
|
"Abort if cannot find control file",
|
||||||
|
(uchar**)&opt_require_control_file, 0, 0, GET_BOOL, NO_ARG,
|
||||||
|
0, 0, 0, 0, 0, 0},
|
||||||
#ifdef DEBUG
|
#ifdef DEBUG
|
||||||
{"start-check-pos", OPT_START_CHECK_POS,
|
{"start-check-pos", OPT_START_CHECK_POS,
|
||||||
"No help available.",
|
"No help available.",
|
||||||
|
@ -56,7 +56,7 @@ int main(int argc, char **argv)
|
|||||||
goto err;
|
goto err;
|
||||||
}
|
}
|
||||||
/* we don't want to create a control file, it MUST exist */
|
/* we don't want to create a control file, it MUST exist */
|
||||||
if (ma_control_file_create_or_open())
|
if (ma_control_file_open(FALSE))
|
||||||
{
|
{
|
||||||
fprintf(stderr, "Can't open control file (%d)\n", errno);
|
fprintf(stderr, "Can't open control file (%d)\n", errno);
|
||||||
goto err;
|
goto err;
|
||||||
|
@ -745,3 +745,18 @@ TRN *trnman_get_any_trn()
|
|||||||
TRN *trn= active_list_min.next;
|
TRN *trn= active_list_min.next;
|
||||||
return (trn != &active_list_max) ? trn : NULL;
|
return (trn != &active_list_max) ? trn : NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
Returns maximum transaction id given to a transaction so far.
|
||||||
|
*/
|
||||||
|
TrID trnman_get_max_trid()
|
||||||
|
{
|
||||||
|
TrID id;
|
||||||
|
if (short_trid_to_active_trn == NULL)
|
||||||
|
return 0;
|
||||||
|
pthread_mutex_lock(&LOCK_trn_list);
|
||||||
|
id= global_trid_generator;
|
||||||
|
pthread_mutex_unlock(&LOCK_trn_list);
|
||||||
|
return id;
|
||||||
|
}
|
||||||
|
@ -54,7 +54,8 @@ uint trnman_decrement_locked_tables(TRN *trn);
|
|||||||
uint trnman_has_locked_tables(TRN *trn);
|
uint trnman_has_locked_tables(TRN *trn);
|
||||||
void trnman_reset_locked_tables(TRN *trn, uint locked_tables);
|
void trnman_reset_locked_tables(TRN *trn, uint locked_tables);
|
||||||
TRN *trnman_recreate_trn_from_recovery(uint16 shortid, TrID longid);
|
TRN *trnman_recreate_trn_from_recovery(uint16 shortid, TrID longid);
|
||||||
TRN *trnman_get_any_trn();
|
TRN *trnman_get_any_trn(void);
|
||||||
|
TrID trnman_get_max_trid(void);
|
||||||
#define TRANSID_SIZE 6
|
#define TRANSID_SIZE 6
|
||||||
#define transid_store(dst, id) int6store(dst,id)
|
#define transid_store(dst, id) int6store(dst,id)
|
||||||
#define transid_korr(P) uint6korr(P)
|
#define transid_korr(P) uint6korr(P)
|
||||||
|
@ -42,36 +42,39 @@
|
|||||||
char file_name[FN_REFLEN];
|
char file_name[FN_REFLEN];
|
||||||
|
|
||||||
/* The values we'll set and expect the control file module to return */
|
/* The values we'll set and expect the control file module to return */
|
||||||
LSN expect_checkpoint_lsn;
|
LSN expect_checkpoint_lsn;
|
||||||
uint32 expect_logno;
|
uint32 expect_logno;
|
||||||
|
TrID expect_max_trid;
|
||||||
|
|
||||||
static int delete_file(myf my_flags);
|
static int delete_file(myf my_flags);
|
||||||
/*
|
/*
|
||||||
Those are test-specific wrappers around the module's API functions: after
|
Those are test-specific wrappers around the module's API functions: after
|
||||||
calling the module's API functions they perform checks on the result.
|
calling the module's API functions they perform checks on the result.
|
||||||
*/
|
*/
|
||||||
static int close_file(); /* wraps ma_control_file_end */
|
static int close_file(void); /* wraps ma_control_file_end */
|
||||||
static int create_or_open_file(); /* wraps ma_control_file_open_or_create */
|
/* wraps ma_control_file_open_or_create */
|
||||||
static int write_file(); /* wraps ma_control_file_write_and_force */
|
static int open_file(void);
|
||||||
|
/* wraps ma_control_file_write_and_force */
|
||||||
|
static int write_file(LSN checkpoint_lsn, uint32 logno, TrID trid);
|
||||||
|
|
||||||
/* Tests */
|
/* Tests */
|
||||||
static int test_one_log();
|
static int test_one_log(void);
|
||||||
static int test_five_logs();
|
static int test_five_logs_and_max_trid(void);
|
||||||
static int test_3_checkpoints_and_2_logs();
|
static int test_3_checkpoints_and_2_logs(void);
|
||||||
static int test_binary_content();
|
static int test_binary_content(void);
|
||||||
static int test_start_stop();
|
static int test_start_stop(void);
|
||||||
static int test_2_open_and_2_close();
|
static int test_2_open_and_2_close(void);
|
||||||
static int test_bad_magic_string();
|
static int test_bad_magic_string(void);
|
||||||
static int test_bad_checksum();
|
static int test_bad_checksum(void);
|
||||||
static int test_bad_hchecksum();
|
static int test_bad_hchecksum(void);
|
||||||
static int test_future_size();
|
static int test_future_size(void);
|
||||||
static int test_bad_blocksize();
|
static int test_bad_blocksize(void);
|
||||||
static int test_bad_size();
|
static int test_bad_size(void);
|
||||||
|
|
||||||
/* Utility */
|
/* Utility */
|
||||||
static int verify_module_values_match_expected();
|
static int verify_module_values_match_expected(void);
|
||||||
static int verify_module_values_are_impossible();
|
static int verify_module_values_are_impossible(void);
|
||||||
static void usage();
|
static void usage(void);
|
||||||
static void get_options(int argc, char *argv[]);
|
static void get_options(int argc, char *argv[]);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -83,10 +86,10 @@ static void get_options(int argc, char *argv[]);
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
#define RET_ERR_UNLESS(expr) \
|
#define RET_ERR_UNLESS(expr) \
|
||||||
{if (!(expr)) {diag("line %d: failure: '%s'", __LINE__, #expr); return 1;}}
|
{if (!(expr)) {diag("line %d: failure: '%s'", __LINE__, #expr); assert(0);return 1;}}
|
||||||
|
|
||||||
|
|
||||||
/* Used to ignore error messages from ma_control_file_create_or_open */
|
/* Used to ignore error messages from ma_control_file_open() */
|
||||||
|
|
||||||
static int my_ignore_message(uint error __attribute__((unused)),
|
static int my_ignore_message(uint error __attribute__((unused)),
|
||||||
const char *str __attribute__((unused)),
|
const char *str __attribute__((unused)),
|
||||||
@ -101,13 +104,13 @@ int (*default_error_handler_hook)(uint my_err, const char *str,
|
|||||||
myf MyFlags) = 0;
|
myf MyFlags) = 0;
|
||||||
|
|
||||||
|
|
||||||
/* like ma_control_file_create_or_open(), but without error messages */
|
/* like ma_control_file_open(), but without error messages */
|
||||||
|
|
||||||
static CONTROL_FILE_ERROR local_ma_control_file_create_or_open(void)
|
static CONTROL_FILE_ERROR local_ma_control_file_open(void)
|
||||||
{
|
{
|
||||||
CONTROL_FILE_ERROR error;
|
CONTROL_FILE_ERROR error;
|
||||||
error_handler_hook= my_ignore_message;
|
error_handler_hook= my_ignore_message;
|
||||||
error= ma_control_file_create_or_open();
|
error= ma_control_file_open(TRUE);
|
||||||
error_handler_hook= default_error_handler_hook;
|
error_handler_hook= default_error_handler_hook;
|
||||||
return error;
|
return error;
|
||||||
}
|
}
|
||||||
@ -133,7 +136,8 @@ int main(int argc,char *argv[])
|
|||||||
|
|
||||||
diag("Tests of normal conditions");
|
diag("Tests of normal conditions");
|
||||||
ok(0 == test_one_log(), "test of creating one log");
|
ok(0 == test_one_log(), "test of creating one log");
|
||||||
ok(0 == test_five_logs(), "test of creating five logs");
|
ok(0 == test_five_logs_and_max_trid(),
|
||||||
|
"test of creating five logs and many transactions");
|
||||||
ok(0 == test_3_checkpoints_and_2_logs(),
|
ok(0 == test_3_checkpoints_and_2_logs(),
|
||||||
"test of creating three checkpoints and two logs");
|
"test of creating three checkpoints and two logs");
|
||||||
ok(0 == test_binary_content(), "test of the binary content of the file");
|
ok(0 == test_binary_content(), "test of the binary content of the file");
|
||||||
@ -163,19 +167,20 @@ static int delete_file(myf my_flags)
|
|||||||
my_delete(file_name, my_flags);
|
my_delete(file_name, my_flags);
|
||||||
expect_checkpoint_lsn= LSN_IMPOSSIBLE;
|
expect_checkpoint_lsn= LSN_IMPOSSIBLE;
|
||||||
expect_logno= FILENO_IMPOSSIBLE;
|
expect_logno= FILENO_IMPOSSIBLE;
|
||||||
|
expect_max_trid= 0;
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Verifies that global values last_checkpoint_lsn and last_logno (belonging
|
Verifies that global values last_checkpoint_lsn, last_logno,
|
||||||
to the module) match what we expect.
|
max_trid_in_control_file (belonging to the module) match what we expect.
|
||||||
*/
|
*/
|
||||||
static int verify_module_values_match_expected()
|
static int verify_module_values_match_expected(void)
|
||||||
{
|
{
|
||||||
RET_ERR_UNLESS(last_logno == expect_logno);
|
RET_ERR_UNLESS(last_logno == expect_logno);
|
||||||
RET_ERR_UNLESS(last_checkpoint_lsn ==
|
RET_ERR_UNLESS(last_checkpoint_lsn == expect_checkpoint_lsn);
|
||||||
expect_checkpoint_lsn);
|
RET_ERR_UNLESS(max_trid_in_control_file == expect_max_trid);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -184,16 +189,16 @@ static int verify_module_values_match_expected()
|
|||||||
Verifies that global values last_checkpoint_lsn and last_logno (belonging
|
Verifies that global values last_checkpoint_lsn and last_logno (belonging
|
||||||
to the module) are impossible (this is used when the file has been closed).
|
to the module) are impossible (this is used when the file has been closed).
|
||||||
*/
|
*/
|
||||||
static int verify_module_values_are_impossible()
|
static int verify_module_values_are_impossible(void)
|
||||||
{
|
{
|
||||||
RET_ERR_UNLESS(last_logno == FILENO_IMPOSSIBLE);
|
RET_ERR_UNLESS(last_logno == FILENO_IMPOSSIBLE);
|
||||||
RET_ERR_UNLESS(last_checkpoint_lsn ==
|
RET_ERR_UNLESS(last_checkpoint_lsn == LSN_IMPOSSIBLE);
|
||||||
LSN_IMPOSSIBLE);
|
RET_ERR_UNLESS(max_trid_in_control_file == 0);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static int close_file()
|
static int close_file(void)
|
||||||
{
|
{
|
||||||
/* Simulate shutdown */
|
/* Simulate shutdown */
|
||||||
ma_control_file_end();
|
ma_control_file_end();
|
||||||
@ -202,94 +207,81 @@ static int close_file()
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int create_or_open_file()
|
static int open_file(void)
|
||||||
{
|
{
|
||||||
RET_ERR_UNLESS(local_ma_control_file_create_or_open() == CONTROL_FILE_OK);
|
RET_ERR_UNLESS(local_ma_control_file_open() == CONTROL_FILE_OK);
|
||||||
/* Check that the module reports expected information */
|
/* Check that the module reports expected information */
|
||||||
RET_ERR_UNLESS(verify_module_values_match_expected() == 0);
|
RET_ERR_UNLESS(verify_module_values_match_expected() == 0);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int write_file(const LSN checkpoint_lsn,
|
static int write_file(LSN checkpoint_lsn, uint32 logno, TrID trid)
|
||||||
uint32 logno,
|
|
||||||
uint objs_to_write)
|
|
||||||
{
|
{
|
||||||
RET_ERR_UNLESS(ma_control_file_write_and_force(checkpoint_lsn, logno,
|
RET_ERR_UNLESS(ma_control_file_write_and_force(checkpoint_lsn, logno, trid)
|
||||||
objs_to_write) == 0);
|
== 0);
|
||||||
/* Check that the module reports expected information */
|
/* Check that the module reports expected information */
|
||||||
RET_ERR_UNLESS(verify_module_values_match_expected() == 0);
|
RET_ERR_UNLESS(verify_module_values_match_expected() == 0);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int test_one_log()
|
static int test_one_log(void)
|
||||||
{
|
{
|
||||||
uint objs_to_write;
|
RET_ERR_UNLESS(open_file() == CONTROL_FILE_OK);
|
||||||
|
|
||||||
RET_ERR_UNLESS(create_or_open_file() == CONTROL_FILE_OK);
|
|
||||||
objs_to_write= CONTROL_FILE_UPDATE_ONLY_LOGNO;
|
|
||||||
expect_logno= 123;
|
expect_logno= 123;
|
||||||
RET_ERR_UNLESS(write_file(LSN_IMPOSSIBLE,
|
RET_ERR_UNLESS(write_file(last_checkpoint_lsn, expect_logno,
|
||||||
expect_logno,
|
max_trid_in_control_file) == 0);
|
||||||
objs_to_write) == 0);
|
|
||||||
RET_ERR_UNLESS(close_file() == 0);
|
RET_ERR_UNLESS(close_file() == 0);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int test_five_logs()
|
static int test_five_logs_and_max_trid(void)
|
||||||
{
|
{
|
||||||
uint objs_to_write;
|
|
||||||
uint i;
|
uint i;
|
||||||
|
|
||||||
RET_ERR_UNLESS(create_or_open_file() == CONTROL_FILE_OK);
|
RET_ERR_UNLESS(open_file() == CONTROL_FILE_OK);
|
||||||
objs_to_write= CONTROL_FILE_UPDATE_ONLY_LOGNO;
|
|
||||||
expect_logno= 100;
|
expect_logno= 100;
|
||||||
|
expect_max_trid= ULL(14111978111);
|
||||||
for (i= 0; i<5; i++)
|
for (i= 0; i<5; i++)
|
||||||
{
|
{
|
||||||
expect_logno*= 3;
|
expect_logno*= 3;
|
||||||
RET_ERR_UNLESS(write_file(LSN_IMPOSSIBLE, expect_logno,
|
RET_ERR_UNLESS(write_file(last_checkpoint_lsn, expect_logno,
|
||||||
objs_to_write) == 0);
|
expect_max_trid) == 0);
|
||||||
}
|
}
|
||||||
RET_ERR_UNLESS(close_file() == 0);
|
RET_ERR_UNLESS(close_file() == 0);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int test_3_checkpoints_and_2_logs()
|
static int test_3_checkpoints_and_2_logs(void)
|
||||||
{
|
{
|
||||||
uint objs_to_write;
|
|
||||||
/*
|
/*
|
||||||
Simulate one checkpoint, one log creation, two checkpoints, one
|
Simulate one checkpoint, one log creation, two checkpoints, one
|
||||||
log creation.
|
log creation.
|
||||||
*/
|
*/
|
||||||
RET_ERR_UNLESS(create_or_open_file() == CONTROL_FILE_OK);
|
RET_ERR_UNLESS(open_file() == CONTROL_FILE_OK);
|
||||||
objs_to_write= CONTROL_FILE_UPDATE_ONLY_LSN;
|
|
||||||
expect_checkpoint_lsn= MAKE_LSN(5, 10000);
|
expect_checkpoint_lsn= MAKE_LSN(5, 10000);
|
||||||
RET_ERR_UNLESS(write_file(expect_checkpoint_lsn,
|
RET_ERR_UNLESS(write_file(expect_checkpoint_lsn, expect_logno,
|
||||||
expect_logno, objs_to_write) == 0);
|
max_trid_in_control_file) == 0);
|
||||||
|
|
||||||
objs_to_write= CONTROL_FILE_UPDATE_ONLY_LOGNO;
|
|
||||||
expect_logno= 17;
|
expect_logno= 17;
|
||||||
RET_ERR_UNLESS(write_file(expect_checkpoint_lsn,
|
RET_ERR_UNLESS(write_file(expect_checkpoint_lsn, expect_logno,
|
||||||
expect_logno, objs_to_write) == 0);
|
max_trid_in_control_file) == 0);
|
||||||
|
|
||||||
objs_to_write= CONTROL_FILE_UPDATE_ONLY_LSN;
|
|
||||||
expect_checkpoint_lsn= MAKE_LSN(17, 20000);
|
expect_checkpoint_lsn= MAKE_LSN(17, 20000);
|
||||||
RET_ERR_UNLESS(write_file(expect_checkpoint_lsn,
|
RET_ERR_UNLESS(write_file(expect_checkpoint_lsn, expect_logno,
|
||||||
expect_logno, objs_to_write) == 0);
|
max_trid_in_control_file) == 0);
|
||||||
|
|
||||||
objs_to_write= CONTROL_FILE_UPDATE_ONLY_LSN;
|
|
||||||
expect_checkpoint_lsn= MAKE_LSN(17, 45000);
|
expect_checkpoint_lsn= MAKE_LSN(17, 45000);
|
||||||
RET_ERR_UNLESS(write_file(expect_checkpoint_lsn,
|
RET_ERR_UNLESS(write_file(expect_checkpoint_lsn, expect_logno,
|
||||||
expect_logno, objs_to_write) == 0);
|
max_trid_in_control_file) == 0);
|
||||||
|
|
||||||
objs_to_write= CONTROL_FILE_UPDATE_ONLY_LOGNO;
|
|
||||||
expect_logno= 19;
|
expect_logno= 19;
|
||||||
RET_ERR_UNLESS(write_file(expect_checkpoint_lsn,
|
RET_ERR_UNLESS(write_file(expect_checkpoint_lsn, expect_logno,
|
||||||
expect_logno, objs_to_write) == 0);
|
max_trid_in_control_file) == 0);
|
||||||
RET_ERR_UNLESS(close_file() == 0);
|
RET_ERR_UNLESS(close_file() == 0);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int test_binary_content()
|
static int test_binary_content(void)
|
||||||
{
|
{
|
||||||
uint i;
|
uint i;
|
||||||
int fd;
|
int fd;
|
||||||
@ -310,7 +302,7 @@ static int test_binary_content()
|
|||||||
MYF(MY_WME))) >= 0);
|
MYF(MY_WME))) >= 0);
|
||||||
RET_ERR_UNLESS(my_read(fd, buffer, 45, MYF(MY_FNABP | MY_WME)) == 0);
|
RET_ERR_UNLESS(my_read(fd, buffer, 45, MYF(MY_FNABP | MY_WME)) == 0);
|
||||||
RET_ERR_UNLESS(my_close(fd, MYF(MY_WME)) == 0);
|
RET_ERR_UNLESS(my_close(fd, MYF(MY_WME)) == 0);
|
||||||
RET_ERR_UNLESS(create_or_open_file() == CONTROL_FILE_OK);
|
RET_ERR_UNLESS(open_file() == CONTROL_FILE_OK);
|
||||||
i= uint3korr(buffer + 34 );
|
i= uint3korr(buffer + 34 );
|
||||||
RET_ERR_UNLESS(i == LSN_FILE_NO(last_checkpoint_lsn));
|
RET_ERR_UNLESS(i == LSN_FILE_NO(last_checkpoint_lsn));
|
||||||
i= uint4korr(buffer + 37);
|
i= uint4korr(buffer + 37);
|
||||||
@ -321,35 +313,35 @@ static int test_binary_content()
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int test_start_stop()
|
static int test_start_stop(void)
|
||||||
{
|
{
|
||||||
/* TEST5: Simulate start/nothing/stop/start/nothing/stop/start */
|
/* TEST5: Simulate start/nothing/stop/start/nothing/stop/start */
|
||||||
|
|
||||||
RET_ERR_UNLESS(create_or_open_file() == CONTROL_FILE_OK);
|
RET_ERR_UNLESS(open_file() == CONTROL_FILE_OK);
|
||||||
RET_ERR_UNLESS(close_file() == 0);
|
RET_ERR_UNLESS(close_file() == 0);
|
||||||
RET_ERR_UNLESS(create_or_open_file() == CONTROL_FILE_OK);
|
RET_ERR_UNLESS(open_file() == CONTROL_FILE_OK);
|
||||||
RET_ERR_UNLESS(close_file() == 0);
|
RET_ERR_UNLESS(close_file() == 0);
|
||||||
RET_ERR_UNLESS(create_or_open_file() == CONTROL_FILE_OK);
|
RET_ERR_UNLESS(open_file() == CONTROL_FILE_OK);
|
||||||
RET_ERR_UNLESS(close_file() == 0);
|
RET_ERR_UNLESS(close_file() == 0);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int test_2_open_and_2_close()
|
static int test_2_open_and_2_close(void)
|
||||||
{
|
{
|
||||||
RET_ERR_UNLESS(create_or_open_file() == CONTROL_FILE_OK);
|
RET_ERR_UNLESS(open_file() == CONTROL_FILE_OK);
|
||||||
RET_ERR_UNLESS(create_or_open_file() == CONTROL_FILE_OK);
|
RET_ERR_UNLESS(open_file() == CONTROL_FILE_OK);
|
||||||
RET_ERR_UNLESS(close_file() == 0);
|
RET_ERR_UNLESS(close_file() == 0);
|
||||||
RET_ERR_UNLESS(close_file() == 0);
|
RET_ERR_UNLESS(close_file() == 0);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static int test_bad_magic_string()
|
static int test_bad_magic_string(void)
|
||||||
{
|
{
|
||||||
uchar buffer[4];
|
uchar buffer[4];
|
||||||
int fd;
|
int fd;
|
||||||
|
|
||||||
RET_ERR_UNLESS(create_or_open_file() == CONTROL_FILE_OK);
|
RET_ERR_UNLESS(open_file() == CONTROL_FILE_OK);
|
||||||
RET_ERR_UNLESS(close_file() == 0);
|
RET_ERR_UNLESS(close_file() == 0);
|
||||||
|
|
||||||
/* Corrupt magic string */
|
/* Corrupt magic string */
|
||||||
@ -361,22 +353,22 @@ static int test_bad_magic_string()
|
|||||||
MYF(MY_FNABP | MY_WME)) == 0);
|
MYF(MY_FNABP | MY_WME)) == 0);
|
||||||
|
|
||||||
/* Check that control file module sees the problem */
|
/* Check that control file module sees the problem */
|
||||||
RET_ERR_UNLESS(local_ma_control_file_create_or_open() ==
|
RET_ERR_UNLESS(local_ma_control_file_open() ==
|
||||||
CONTROL_FILE_BAD_MAGIC_STRING);
|
CONTROL_FILE_BAD_MAGIC_STRING);
|
||||||
/* Restore magic string */
|
/* Restore magic string */
|
||||||
RET_ERR_UNLESS(my_pwrite(fd, buffer, 4, 0, MYF(MY_FNABP | MY_WME)) == 0);
|
RET_ERR_UNLESS(my_pwrite(fd, buffer, 4, 0, MYF(MY_FNABP | MY_WME)) == 0);
|
||||||
RET_ERR_UNLESS(my_close(fd, MYF(MY_WME)) == 0);
|
RET_ERR_UNLESS(my_close(fd, MYF(MY_WME)) == 0);
|
||||||
RET_ERR_UNLESS(create_or_open_file() == CONTROL_FILE_OK);
|
RET_ERR_UNLESS(open_file() == CONTROL_FILE_OK);
|
||||||
RET_ERR_UNLESS(close_file() == 0);
|
RET_ERR_UNLESS(close_file() == 0);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int test_bad_checksum()
|
static int test_bad_checksum(void)
|
||||||
{
|
{
|
||||||
uchar buffer[4];
|
uchar buffer[4];
|
||||||
int fd;
|
int fd;
|
||||||
|
|
||||||
RET_ERR_UNLESS(create_or_open_file() == CONTROL_FILE_OK);
|
RET_ERR_UNLESS(open_file() == CONTROL_FILE_OK);
|
||||||
RET_ERR_UNLESS(close_file() == 0);
|
RET_ERR_UNLESS(close_file() == 0);
|
||||||
|
|
||||||
/* Corrupt checksum */
|
/* Corrupt checksum */
|
||||||
@ -387,7 +379,7 @@ static int test_bad_checksum()
|
|||||||
buffer[0]+= 3; /* mangle checksum */
|
buffer[0]+= 3; /* mangle checksum */
|
||||||
RET_ERR_UNLESS(my_pwrite(fd, buffer, 1, 30, MYF(MY_FNABP | MY_WME)) == 0);
|
RET_ERR_UNLESS(my_pwrite(fd, buffer, 1, 30, MYF(MY_FNABP | MY_WME)) == 0);
|
||||||
/* Check that control file module sees the problem */
|
/* Check that control file module sees the problem */
|
||||||
RET_ERR_UNLESS(local_ma_control_file_create_or_open() ==
|
RET_ERR_UNLESS(local_ma_control_file_open() ==
|
||||||
CONTROL_FILE_BAD_CHECKSUM);
|
CONTROL_FILE_BAD_CHECKSUM);
|
||||||
/* Restore checksum */
|
/* Restore checksum */
|
||||||
buffer[0]-= 3;
|
buffer[0]-= 3;
|
||||||
@ -398,22 +390,22 @@ static int test_bad_checksum()
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static int test_bad_blocksize()
|
static int test_bad_blocksize(void)
|
||||||
{
|
{
|
||||||
maria_block_size<<= 1;
|
maria_block_size<<= 1;
|
||||||
/* Check that control file module sees the problem */
|
/* Check that control file module sees the problem */
|
||||||
RET_ERR_UNLESS(local_ma_control_file_create_or_open() ==
|
RET_ERR_UNLESS(local_ma_control_file_open() ==
|
||||||
CONTROL_FILE_WRONG_BLOCKSIZE);
|
CONTROL_FILE_WRONG_BLOCKSIZE);
|
||||||
/* Restore blocksize */
|
/* Restore blocksize */
|
||||||
maria_block_size>>= 1;
|
maria_block_size>>= 1;
|
||||||
|
|
||||||
RET_ERR_UNLESS(create_or_open_file() == CONTROL_FILE_OK);
|
RET_ERR_UNLESS(open_file() == CONTROL_FILE_OK);
|
||||||
RET_ERR_UNLESS(close_file() == 0);
|
RET_ERR_UNLESS(close_file() == 0);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static int test_future_size()
|
static int test_future_size(void)
|
||||||
{
|
{
|
||||||
/*
|
/*
|
||||||
Here we check ability to add fields only so we can use
|
Here we check ability to add fields only so we can use
|
||||||
@ -455,18 +447,18 @@ static int test_future_size()
|
|||||||
CF_CHANGEABLE_TOTAL_SIZE + 2,
|
CF_CHANGEABLE_TOTAL_SIZE + 2,
|
||||||
0, MYF(MY_FNABP | MY_WME)) == 0);
|
0, MYF(MY_FNABP | MY_WME)) == 0);
|
||||||
RET_ERR_UNLESS(my_close(fd, MYF(MY_WME)) == 0);
|
RET_ERR_UNLESS(my_close(fd, MYF(MY_WME)) == 0);
|
||||||
RET_ERR_UNLESS(create_or_open_file() == CONTROL_FILE_OK);
|
RET_ERR_UNLESS(open_file() == CONTROL_FILE_OK);
|
||||||
RET_ERR_UNLESS(close_file() == 0);
|
RET_ERR_UNLESS(close_file() == 0);
|
||||||
|
|
||||||
return(0);
|
return(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int test_bad_hchecksum()
|
static int test_bad_hchecksum(void)
|
||||||
{
|
{
|
||||||
uchar buffer[4];
|
uchar buffer[4];
|
||||||
int fd;
|
int fd;
|
||||||
|
|
||||||
RET_ERR_UNLESS(create_or_open_file() == CONTROL_FILE_OK);
|
RET_ERR_UNLESS(open_file() == CONTROL_FILE_OK);
|
||||||
RET_ERR_UNLESS(close_file() == 0);
|
RET_ERR_UNLESS(close_file() == 0);
|
||||||
|
|
||||||
/* Corrupt checksum */
|
/* Corrupt checksum */
|
||||||
@ -477,7 +469,7 @@ static int test_bad_hchecksum()
|
|||||||
buffer[0]+= 3; /* mangle checksum */
|
buffer[0]+= 3; /* mangle checksum */
|
||||||
RET_ERR_UNLESS(my_pwrite(fd, buffer, 1, 26, MYF(MY_FNABP | MY_WME)) == 0);
|
RET_ERR_UNLESS(my_pwrite(fd, buffer, 1, 26, MYF(MY_FNABP | MY_WME)) == 0);
|
||||||
/* Check that control file module sees the problem */
|
/* Check that control file module sees the problem */
|
||||||
RET_ERR_UNLESS(local_ma_control_file_create_or_open() ==
|
RET_ERR_UNLESS(local_ma_control_file_open() ==
|
||||||
CONTROL_FILE_BAD_HEAD_CHECKSUM);
|
CONTROL_FILE_BAD_HEAD_CHECKSUM);
|
||||||
/* Restore checksum */
|
/* Restore checksum */
|
||||||
buffer[0]-= 3;
|
buffer[0]-= 3;
|
||||||
@ -488,7 +480,7 @@ static int test_bad_hchecksum()
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static int test_bad_size()
|
static int test_bad_size(void)
|
||||||
{
|
{
|
||||||
uchar buffer[]=
|
uchar buffer[]=
|
||||||
"123456789012345678901234567890123456789012345678901234567890123456";
|
"123456789012345678901234567890123456789012345678901234567890123456";
|
||||||
@ -501,20 +493,20 @@ static int test_bad_size()
|
|||||||
MYF(MY_WME))) >= 0);
|
MYF(MY_WME))) >= 0);
|
||||||
RET_ERR_UNLESS(my_write(fd, buffer, 10, MYF(MY_FNABP | MY_WME)) == 0);
|
RET_ERR_UNLESS(my_write(fd, buffer, 10, MYF(MY_FNABP | MY_WME)) == 0);
|
||||||
/* Check that control file module sees the problem */
|
/* Check that control file module sees the problem */
|
||||||
RET_ERR_UNLESS(local_ma_control_file_create_or_open() ==
|
RET_ERR_UNLESS(local_ma_control_file_open() ==
|
||||||
CONTROL_FILE_TOO_SMALL);
|
CONTROL_FILE_TOO_SMALL);
|
||||||
for (i= 0; i < 8; i++)
|
for (i= 0; i < 8; i++)
|
||||||
{
|
{
|
||||||
RET_ERR_UNLESS(my_write(fd, buffer, 66, MYF(MY_FNABP | MY_WME)) == 0);
|
RET_ERR_UNLESS(my_write(fd, buffer, 66, MYF(MY_FNABP | MY_WME)) == 0);
|
||||||
}
|
}
|
||||||
/* Check that control file module sees the problem */
|
/* Check that control file module sees the problem */
|
||||||
RET_ERR_UNLESS(local_ma_control_file_create_or_open() ==
|
RET_ERR_UNLESS(local_ma_control_file_open() ==
|
||||||
CONTROL_FILE_TOO_BIG);
|
CONTROL_FILE_TOO_BIG);
|
||||||
RET_ERR_UNLESS(my_close(fd, MYF(MY_WME)) == 0);
|
RET_ERR_UNLESS(my_close(fd, MYF(MY_WME)) == 0);
|
||||||
|
|
||||||
/* Leave a correct control file */
|
/* Leave a correct control file */
|
||||||
RET_ERR_UNLESS(delete_file(MYF(MY_WME)) == 0);
|
RET_ERR_UNLESS(delete_file(MYF(MY_WME)) == 0);
|
||||||
RET_ERR_UNLESS(create_or_open_file() == CONTROL_FILE_OK);
|
RET_ERR_UNLESS(open_file() == CONTROL_FILE_OK);
|
||||||
RET_ERR_UNLESS(close_file() == 0);
|
RET_ERR_UNLESS(close_file() == 0);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
@ -535,7 +527,7 @@ static struct my_option my_long_options[] =
|
|||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
static void version()
|
static void version(void)
|
||||||
{
|
{
|
||||||
printf("ma_control_file_test: unit test for the control file "
|
printf("ma_control_file_test: unit test for the control file "
|
||||||
"module of the Maria storage engine. Ver 1.0 \n");
|
"module of the Maria storage engine. Ver 1.0 \n");
|
||||||
@ -575,7 +567,7 @@ static void get_options(int argc, char *argv[])
|
|||||||
} /* get options */
|
} /* get options */
|
||||||
|
|
||||||
|
|
||||||
static void usage()
|
static void usage(void)
|
||||||
{
|
{
|
||||||
printf("Usage: %s [options]\n\n", my_progname);
|
printf("Usage: %s [options]\n\n", my_progname);
|
||||||
my_print_help(my_long_options);
|
my_print_help(my_long_options);
|
||||||
|
@ -196,7 +196,7 @@ int main(int argc __attribute__((unused)), char *argv[])
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
if (ma_control_file_create_or_open(TRUE))
|
if (ma_control_file_open(TRUE))
|
||||||
{
|
{
|
||||||
fprintf(stderr, "Can't init control file (%d)\n", errno);
|
fprintf(stderr, "Can't init control file (%d)\n", errno);
|
||||||
exit(1);
|
exit(1);
|
||||||
|
@ -67,7 +67,7 @@ int main(int argc __attribute__((unused)), char *argv[])
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
if (ma_control_file_create_or_open(TRUE))
|
if (ma_control_file_open(TRUE))
|
||||||
{
|
{
|
||||||
fprintf(stderr, "Can't init control file (%d)\n", errno);
|
fprintf(stderr, "Can't init control file (%d)\n", errno);
|
||||||
exit(1);
|
exit(1);
|
||||||
|
@ -64,7 +64,7 @@ int main(int argc __attribute__((unused)), char *argv[])
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
if (ma_control_file_create_or_open(TRUE))
|
if (ma_control_file_open(TRUE))
|
||||||
{
|
{
|
||||||
fprintf(stderr, "Can't init control file (%d)\n", errno);
|
fprintf(stderr, "Can't init control file (%d)\n", errno);
|
||||||
exit(1);
|
exit(1);
|
||||||
|
@ -184,7 +184,7 @@ int main(int argc __attribute__((unused)), char *argv[])
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
if (ma_control_file_create_or_open(TRUE))
|
if (ma_control_file_open(TRUE))
|
||||||
{
|
{
|
||||||
fprintf(stderr, "Can't init control file (%d)\n", errno);
|
fprintf(stderr, "Can't init control file (%d)\n", errno);
|
||||||
exit(1);
|
exit(1);
|
||||||
@ -348,7 +348,7 @@ int main(int argc __attribute__((unused)), char *argv[])
|
|||||||
end_pagecache(&pagecache, 1);
|
end_pagecache(&pagecache, 1);
|
||||||
ma_control_file_end();
|
ma_control_file_end();
|
||||||
|
|
||||||
if (ma_control_file_create_or_open(TRUE))
|
if (ma_control_file_open(TRUE))
|
||||||
{
|
{
|
||||||
fprintf(stderr, "pass2: Can't init control file (%d)\n", errno);
|
fprintf(stderr, "pass2: Can't init control file (%d)\n", errno);
|
||||||
exit(1);
|
exit(1);
|
||||||
|
@ -283,7 +283,7 @@ int main(int argc __attribute__((unused)),
|
|||||||
|
|
||||||
my_thread_global_init();
|
my_thread_global_init();
|
||||||
|
|
||||||
if (ma_control_file_create_or_open(TRUE))
|
if (ma_control_file_open(TRUE))
|
||||||
{
|
{
|
||||||
fprintf(stderr, "Can't init control file (%d)\n", errno);
|
fprintf(stderr, "Can't init control file (%d)\n", errno);
|
||||||
exit(1);
|
exit(1);
|
||||||
|
@ -70,7 +70,7 @@ int main(int argc __attribute__((unused)), char *argv[])
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
if (ma_control_file_create_or_open(TRUE))
|
if (ma_control_file_open(TRUE))
|
||||||
{
|
{
|
||||||
fprintf(stderr, "Can't init control file (%d)\n", errno);
|
fprintf(stderr, "Can't init control file (%d)\n", errno);
|
||||||
exit(1);
|
exit(1);
|
||||||
|
@ -67,7 +67,7 @@ int main(int argc __attribute__((unused)), char *argv[])
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
if (ma_control_file_create_or_open(TRUE))
|
if (ma_control_file_open(TRUE))
|
||||||
{
|
{
|
||||||
fprintf(stderr, "Can't init control file (%d)\n", errno);
|
fprintf(stderr, "Can't init control file (%d)\n", errno);
|
||||||
exit(1);
|
exit(1);
|
||||||
@ -140,7 +140,7 @@ int main(int argc __attribute__((unused)), char *argv[])
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (ma_control_file_create_or_open(TRUE))
|
if (ma_control_file_open(TRUE))
|
||||||
{
|
{
|
||||||
fprintf(stderr, "Can't init control file (%d)\n", errno);
|
fprintf(stderr, "Can't init control file (%d)\n", errno);
|
||||||
exit(1);
|
exit(1);
|
||||||
|
@ -95,7 +95,7 @@ int main(int argc __attribute__((unused)), char *argv[])
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
if (ma_control_file_create_or_open(TRUE))
|
if (ma_control_file_open(TRUE))
|
||||||
{
|
{
|
||||||
fprintf(stderr, "Can't init control file (%d)\n", errno);
|
fprintf(stderr, "Can't init control file (%d)\n", errno);
|
||||||
exit(1);
|
exit(1);
|
||||||
|
@ -67,7 +67,7 @@ int main(int argc __attribute__((unused)), char *argv[])
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
if (ma_control_file_create_or_open(TRUE))
|
if (ma_control_file_open(TRUE))
|
||||||
{
|
{
|
||||||
fprintf(stderr, "Can't init control file (%d)\n", errno);
|
fprintf(stderr, "Can't init control file (%d)\n", errno);
|
||||||
exit(1);
|
exit(1);
|
||||||
|
Loading…
x
Reference in New Issue
Block a user