mirror of
https://github.com/MariaDB/server.git
synced 2026-05-16 20:07:13 +02:00
Added maria_commit() and maria_begin() to be used with external tests
Now ma_test1 -M -T and ma_test2 -M -T produces readable, applyable logs Note: The .MAD file is not binary identical after applying redo compare to a an original file. (This is becasue we don't have full information which function called PURGE_REDO_BLOCKS). To verify if a file was correctly applied, we now instead compare row checksums BitKeeper/etc/ignore: added storage/maria/tmp/* include/maria.h: Added maria_commit() and maria_begin() to be used with external tests storage/maria/ha_maria.cc: Ensure maria_def. is read in C mode storage/maria/ma_blockrec.c: Fixed redo handling. _ma_apply_redo_purge_blocks() updated to handle any number of purged blocks Removed code to make data file idenitcal after redo (can't easily be done). See changeset comments Now ma_test1 -M -T and ma_test2 -M -T produces readable, applyable logs storage/maria/ma_commit.c: More DBUG statements Moved variable declaration to start of function (portability fix) Added helper functions 'maria_commit()' and 'maria_begin()' storage/maria/ma_loghandler.c: Fixed wrong REDO_PURGE_BLOCKS initialization storage/maria/ma_recovery.c: Added UNDO_ROW_UPDATE Removed wrong setting of lsn (there was no lsn at the used position) Fixed REDO_PURGE_BLOCKS to handle any number of blocks storage/maria/ma_test1.c: Added transaction support (via maria_begin() & maria_commit()) to get a log that can be applied with maria_read_log storage/maria/ma_test2.c: Added transaction support (via maria_begin() & maria_commit()) to get a log that can be applied with maria_read_log storage/maria/ma_test_recovery: Create temporary files in maria/tmp Verify files with checksums instead of byte comparisons storage/maria/maria_chk.c: When using with -dss we only get filename, records and checksum. This is useful to do a quick comparision if a files is identical to another one. storage/maria/maria_def.h: Added ma_commit() storage/maria/maria_read_log.c: Added --help
This commit is contained in:
parent
d430e5bfc1
commit
f7b766c029
13 changed files with 259 additions and 136 deletions
|
|
@ -3045,3 +3045,6 @@ win/vs71cache.txt
|
|||
win/vs8cache.txt
|
||||
zlib/*.ds?
|
||||
zlib/*.vcproj
|
||||
maria_log_control
|
||||
storage/maria/tmp/*
|
||||
storage/maria/tmp/*
|
||||
|
|
|
|||
|
|
@ -300,7 +300,8 @@ extern ha_rows maria_records_in_range(struct st_maria_info *info, int inx,
|
|||
extern int maria_is_changed(struct st_maria_info *info);
|
||||
extern int maria_delete_all_rows(struct st_maria_info *info);
|
||||
extern uint maria_get_pointer_length(ulonglong file_length, uint def);
|
||||
|
||||
extern int maria_commit(struct st_maria_info *info);
|
||||
extern int maria_begin(struct st_maria_info *info);
|
||||
|
||||
/* this is used to pass to mysql_mariachk_table */
|
||||
|
||||
|
|
|
|||
|
|
@ -27,10 +27,11 @@
|
|||
#include "ha_maria.h"
|
||||
#include "trnman_public.h"
|
||||
|
||||
C_MODE_START
|
||||
#include "maria_def.h"
|
||||
#include "ma_rt_index.h"
|
||||
#include "ma_blockrec.h"
|
||||
#include "ma_commit.h"
|
||||
C_MODE_END
|
||||
|
||||
#define MARIA_CANNOT_ROLLBACK HA_NO_TRANSACTIONS
|
||||
#ifdef MARIA_CANNOT_ROLLBACK
|
||||
|
|
|
|||
|
|
@ -530,6 +530,21 @@ static inline uint start_of_next_entry(uchar *dir)
|
|||
}
|
||||
|
||||
|
||||
static inline uint end_of_previous_entry(uchar *dir, uchar *end)
|
||||
{
|
||||
uchar *pos;
|
||||
for (pos= dir + DIR_ENTRY_SIZE ; pos < end ; pos+= DIR_ENTRY_SIZE)
|
||||
{
|
||||
uint offset;
|
||||
if ((offset= uint2korr(pos)))
|
||||
{
|
||||
return offset + uint2korr(pos+2);
|
||||
}
|
||||
}
|
||||
return PAGE_HEADER_SIZE;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
Check that a region is all zero
|
||||
|
||||
|
|
@ -1438,7 +1453,7 @@ static my_bool free_full_pages(MARIA_HA *info, MARIA_ROW *row)
|
|||
log_data))
|
||||
DBUG_RETURN(1);
|
||||
|
||||
DBUG_RETURN (_ma_bitmap_free_full_pages(info, row->extents,
|
||||
DBUG_RETURN(_ma_bitmap_free_full_pages(info, row->extents,
|
||||
row->extents_count));
|
||||
}
|
||||
|
||||
|
|
@ -1457,6 +1472,7 @@ static my_bool free_full_pages(MARIA_HA *info, MARIA_ROW *row)
|
|||
static my_bool free_full_page_range(MARIA_HA *info, ulonglong page, uint count)
|
||||
{
|
||||
my_bool res= 0;
|
||||
DBUG_ENTER("free_full_page_range");
|
||||
|
||||
if (pagecache_delete_pages(info->s->pagecache, &info->dfile,
|
||||
page, count, PAGECACHE_LOCK_WRITE, 0))
|
||||
|
|
@ -1490,7 +1506,7 @@ static my_bool free_full_page_range(MARIA_HA *info, ulonglong page, uint count)
|
|||
count))
|
||||
res= 1;
|
||||
pthread_mutex_unlock(&info->s->bitmap.bitmap_lock);
|
||||
return res;
|
||||
DBUG_RETURN(res);
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -2470,7 +2486,7 @@ my_bool _ma_update_block_record(MARIA_HA *info, MARIA_RECORD_POS record_pos,
|
|||
/* Update cur_row, if someone calls update at once again */
|
||||
cur_row->head_length= new_row->total_length;
|
||||
|
||||
if (free_full_pages(info, cur_row))
|
||||
if (cur_row->extents_count && free_full_pages(info, cur_row))
|
||||
goto err;
|
||||
DBUG_RETURN(write_block_record(info, oldrec, record, new_row, blocks,
|
||||
1, &row_pos));
|
||||
|
|
@ -2492,9 +2508,9 @@ my_bool _ma_update_block_record(MARIA_HA *info, MARIA_RECORD_POS record_pos,
|
|||
}
|
||||
|
||||
/* Delete old row */
|
||||
if (delete_tails(info, cur_row->tail_positions))
|
||||
if (*cur_row->tail_positions && delete_tails(info, cur_row->tail_positions))
|
||||
goto err;
|
||||
if (free_full_pages(info, cur_row))
|
||||
if (cur_row->extents_count && free_full_pages(info, cur_row))
|
||||
goto err;
|
||||
if (_ma_bitmap_find_new_place(info, new_row, page, head_length, blocks))
|
||||
goto err;
|
||||
|
|
@ -4207,7 +4223,7 @@ uint _ma_apply_redo_insert_row_head_or_tail(MARIA_HA *info, LSN lsn,
|
|||
PAGE_SUFFIX_SIZE);
|
||||
empty_space= uint2korr(buff + EMPTY_SPACE_OFFSET);
|
||||
|
||||
if (max_entry >= rownr)
|
||||
if (max_entry <= rownr)
|
||||
{
|
||||
/* Add directory entry first in directory and data last on page */
|
||||
DBUG_ASSERT(max_entry == rownr);
|
||||
|
|
@ -4232,40 +4248,27 @@ uint _ma_apply_redo_insert_row_head_or_tail(MARIA_HA *info, LSN lsn,
|
|||
}
|
||||
else
|
||||
{
|
||||
/* reuse old empty entry */
|
||||
uchar *pos, *end, *end_data;
|
||||
DBUG_ASSERT(uint2korr(dir) == 0);
|
||||
if (uint2korr(dir))
|
||||
goto err; /* Should have been empty */
|
||||
/*
|
||||
reuse old entry. This is empty if the command was an insert and
|
||||
possible used if the command was an update.
|
||||
*/
|
||||
uchar *end_data;
|
||||
uint rec_end;
|
||||
|
||||
/* Find start of where we can put data */
|
||||
end= (buff + block_size - DIR_ENTRY_SIZE * max_entry -
|
||||
PAGE_SUFFIX_SIZE);
|
||||
for (pos= dir ; pos >= end ; pos-= DIR_ENTRY_SIZE)
|
||||
{
|
||||
if ((rec_offset= uint2korr(pos)))
|
||||
{
|
||||
rec_offset+= uint2korr(pos+2);
|
||||
break;
|
||||
}
|
||||
}
|
||||
DBUG_ASSERT(pos >= end);
|
||||
if (pos < end) /* Wrong directory */
|
||||
goto err;
|
||||
/* Add back space if we are reusing entry */
|
||||
empty_space+= uint2korr(dir+2);
|
||||
|
||||
/* find end data */
|
||||
end_data= end; /* Start of directory */
|
||||
end= (buff + block_size - PAGE_SUFFIX_SIZE);
|
||||
for (pos= dir ; pos < end ; pos+= DIR_ENTRY_SIZE)
|
||||
{
|
||||
uint offset;
|
||||
if ((offset= uint2korr(pos)))
|
||||
{
|
||||
end_data= buff + offset;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if ((uint) (end_data - (buff + rec_offset)) < data_length)
|
||||
/* Find first possible position where to put new data */
|
||||
end_data= (buff + block_size - PAGE_SUFFIX_SIZE -
|
||||
DIR_ENTRY_SIZE * max_entry);
|
||||
rec_offset= end_of_previous_entry(dir, end_data);
|
||||
if (rownr != max_entry -1)
|
||||
rec_end= start_of_next_entry(dir);
|
||||
else
|
||||
rec_end= (uint) (buff - end_data);
|
||||
DBUG_ASSERT(rec_end > rec_offset);
|
||||
|
||||
if ((uint) (rec_end - rec_offset) < data_length)
|
||||
{
|
||||
uint length;
|
||||
/* Not enough continues space, compact page to get more */
|
||||
|
|
@ -4397,70 +4400,53 @@ uint _ma_apply_redo_purge_blocks(MARIA_HA *info,
|
|||
{
|
||||
MARIA_SHARE *share= info->s;
|
||||
ulonglong page;
|
||||
uint page_range;
|
||||
uint res;
|
||||
uint page_range, ranges;
|
||||
uint res= 0;
|
||||
uchar *buff= info->keyread_buff;
|
||||
uint block_size= share->block_size;
|
||||
DBUG_ENTER("_ma_apply_redo_purge_blocks");
|
||||
|
||||
info->keyread_buff_used= 1;
|
||||
page_range= pagerange_korr(header);
|
||||
/* works only for a one-page range for now */
|
||||
DBUG_ASSERT(page_range == 1); // for now
|
||||
ranges= pagerange_korr(header);
|
||||
header+= PAGERANGE_STORE_SIZE;
|
||||
page= page_korr(header);
|
||||
header+= PAGE_STORE_SIZE;
|
||||
page_range= pagerange_korr(header);
|
||||
DBUG_ASSERT(page_range == 1); // for now
|
||||
|
||||
if (!(buff= pagecache_read(share->pagecache,
|
||||
&info->dfile,
|
||||
page, 0,
|
||||
buff, PAGECACHE_PLAIN_PAGE,
|
||||
PAGECACHE_LOCK_LEFT_UNLOCKED, 0)))
|
||||
DBUG_RETURN(my_errno);
|
||||
|
||||
if (lsn_korr(buff) >= lsn)
|
||||
while (ranges--)
|
||||
{
|
||||
/* Already applied */
|
||||
goto mark_free_in_bitmap;
|
||||
uint i;
|
||||
page= page_korr(header);
|
||||
header+= PAGE_STORE_SIZE;
|
||||
page_range= pagerange_korr(header);
|
||||
header+= PAGERANGE_STORE_SIZE;
|
||||
|
||||
for (i= 0; i < page_range ; i++)
|
||||
{
|
||||
if (!(buff= pagecache_read(share->pagecache,
|
||||
&info->dfile,
|
||||
page+i, 0,
|
||||
buff, PAGECACHE_PLAIN_PAGE,
|
||||
PAGECACHE_LOCK_LEFT_UNLOCKED, 0)))
|
||||
DBUG_RETURN(my_errno);
|
||||
|
||||
if (lsn_korr(buff) >= lsn)
|
||||
{
|
||||
/* Already applied */
|
||||
continue;
|
||||
}
|
||||
buff[PAGE_TYPE_OFFSET]= UNALLOCATED_PAGE;
|
||||
lsn_store(buff, lsn);
|
||||
if (pagecache_write(share->pagecache,
|
||||
&info->dfile, page+i, 0,
|
||||
buff, PAGECACHE_PLAIN_PAGE,
|
||||
PAGECACHE_LOCK_LEFT_UNLOCKED,
|
||||
PAGECACHE_PIN_LEFT_UNPINNED,
|
||||
PAGECACHE_WRITE_DELAY, 0))
|
||||
DBUG_RETURN(my_errno);
|
||||
}
|
||||
/** @todo leave bitmap lock to the bitmap code... */
|
||||
pthread_mutex_lock(&share->bitmap.bitmap_lock);
|
||||
res= _ma_reset_full_page_bits(info, &share->bitmap, page, page_range);
|
||||
pthread_mutex_unlock(&share->bitmap.bitmap_lock);
|
||||
if (res)
|
||||
DBUG_RETURN(res);
|
||||
}
|
||||
|
||||
buff[PAGE_TYPE_OFFSET]= UNALLOCATED_PAGE;
|
||||
|
||||
/*
|
||||
Strictly speaking, we don't need to zero the last directory entry of this
|
||||
page; setting the directory's count to zero is enough (it makes the last
|
||||
directory entry invisible, irrelevant).
|
||||
But as the "runtime" code (delete_head_or_tail()) called
|
||||
delete_dir_entry() which zeroed the entry, if we don't do it here, we get
|
||||
a difference between runtime and log-applying. Irrelevant, but it's
|
||||
time-consuming to differentiate irrelevant differences from relevant
|
||||
ones. So we remove the difference by zeroing the entry.
|
||||
*/
|
||||
{
|
||||
uint rownr= ((uint) ((uchar *) buff)[DIR_COUNT_OFFSET]) - 1;
|
||||
uchar *dir= (buff + block_size - DIR_ENTRY_SIZE * rownr -
|
||||
DIR_ENTRY_SIZE - PAGE_SUFFIX_SIZE);
|
||||
dir[0]= dir[1]= 0; /* Delete entry */
|
||||
}
|
||||
|
||||
buff[DIR_COUNT_OFFSET]= 0;
|
||||
|
||||
lsn_store(buff, lsn);
|
||||
if (pagecache_write(share->pagecache,
|
||||
&info->dfile, page, 0,
|
||||
buff, PAGECACHE_PLAIN_PAGE,
|
||||
PAGECACHE_LOCK_LEFT_UNLOCKED,
|
||||
PAGECACHE_PIN_LEFT_UNPINNED,
|
||||
PAGECACHE_WRITE_DELAY, 0))
|
||||
DBUG_RETURN(my_errno);
|
||||
|
||||
mark_free_in_bitmap:
|
||||
/** @todo leave bitmap lock to the bitmap code... */
|
||||
pthread_mutex_lock(&share->bitmap.bitmap_lock);
|
||||
res= _ma_reset_full_page_bits(info, &share->bitmap, page, 1);
|
||||
pthread_mutex_unlock(&share->bitmap.bitmap_lock);
|
||||
|
||||
DBUG_RETURN(res);
|
||||
DBUG_RETURN(0);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -28,8 +28,13 @@
|
|||
|
||||
int ma_commit(TRN *trn)
|
||||
{
|
||||
int res;
|
||||
LSN commit_lsn;
|
||||
LEX_STRING log_array[TRANSLOG_INTERNAL_PARTS];
|
||||
DBUG_ENTER("ma_commit");
|
||||
|
||||
if (trn->undo_lsn == 0) /* no work done, rollback (cheaper than commit) */
|
||||
return trnman_rollback_trn(trn);
|
||||
DBUG_RETURN(trnman_rollback_trn(trn));
|
||||
/*
|
||||
- if COMMIT record is written before trnman_commit_trn():
|
||||
if Checkpoint comes in the middle it will see trn is not committed,
|
||||
|
|
@ -45,27 +50,76 @@ int ma_commit(TRN *trn)
|
|||
issue (transaction's updates were made visible to other transactions).
|
||||
So we need to go the first way.
|
||||
*/
|
||||
|
||||
/**
|
||||
@todo RECOVERY share's state is written to disk only in
|
||||
maria_lock_database(), so COMMIT record is not the last record of the
|
||||
transaction! It is probably an issue. Recovery of the state is a problem
|
||||
not yet solved.
|
||||
*/
|
||||
LSN commit_lsn;
|
||||
LEX_STRING log_array[TRANSLOG_INTERNAL_PARTS];
|
||||
/*
|
||||
We do not store "thd->transaction.xid_state.xid" for now, it will be
|
||||
needed only when we support XA.
|
||||
*/
|
||||
return
|
||||
translog_write_record(&commit_lsn, LOGREC_COMMIT,
|
||||
trn, NULL, 0,
|
||||
sizeof(log_array)/sizeof(log_array[0]),
|
||||
log_array, NULL) ||
|
||||
translog_flush(commit_lsn) || trnman_commit_trn(trn);
|
||||
res= (translog_write_record(&commit_lsn, LOGREC_COMMIT,
|
||||
trn, NULL, 0,
|
||||
sizeof(log_array)/sizeof(log_array[0]),
|
||||
log_array, NULL) ||
|
||||
translog_flush(commit_lsn) ||
|
||||
trnman_commit_trn(trn));
|
||||
trn->undo_lsn= 0;
|
||||
/*
|
||||
Note: if trnman_commit_trn() fails above, we have already
|
||||
written the COMMIT record, so Checkpoint and Recovery will see the
|
||||
transaction as committed.
|
||||
*/
|
||||
DBUG_RETURN(res);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
@brief Writes a COMMIT record for a transaciton associated with a file
|
||||
|
||||
@param info Maria handler
|
||||
|
||||
@return Operation status
|
||||
@retval 0 ok
|
||||
@retval # error (disk error or out of memory)
|
||||
*/
|
||||
|
||||
int maria_commit(MARIA_HA *info)
|
||||
{
|
||||
return info->s->now_transactional ? ma_commit(info->trn) : 0;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
@brief Starts a transaction on a file handle
|
||||
|
||||
@param info Maria handler
|
||||
|
||||
@return Operation status
|
||||
@retval 0 ok
|
||||
@retval # Error code.
|
||||
*/
|
||||
|
||||
|
||||
int maria_begin(MARIA_HA *info)
|
||||
{
|
||||
DBUG_ENTER("maria_begin");
|
||||
|
||||
if (info->s->now_transactional)
|
||||
{
|
||||
TRN *trn;
|
||||
struct st_my_thread_var *mysys_var= my_thread_var;
|
||||
trn= trnman_new_trn(&mysys_var->mutex,
|
||||
&mysys_var->suspend,
|
||||
(char*) &mysys_var + STACK_DIRECTION *1024*128);
|
||||
if (unlikely(!trn))
|
||||
DBUG_RETURN(HA_ERR_OUT_OF_MEM);
|
||||
|
||||
DBUG_PRINT("info", ("TRN set to 0x%lx", (ulong) trn));
|
||||
info->trn= trn;
|
||||
}
|
||||
DBUG_RETURN(0);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -299,13 +299,9 @@ static LOG_DESC INIT_LOGREC_REDO_PURGE_ROW_TAIL=
|
|||
NULL, write_hook_for_redo, NULL, 0,
|
||||
"redo_purge_row_tail", LOGREC_NOT_LAST_IN_GROUP, NULL, NULL};
|
||||
|
||||
/* QQQ: TODO: variable and fixed size??? */
|
||||
static LOG_DESC INIT_LOGREC_REDO_PURGE_BLOCKS=
|
||||
{LOGRECTYPE_VARIABLE_LENGTH,
|
||||
FILEID_STORE_SIZE + PAGERANGE_STORE_SIZE +
|
||||
PAGE_STORE_SIZE + PAGERANGE_STORE_SIZE,
|
||||
FILEID_STORE_SIZE + PAGERANGE_STORE_SIZE +
|
||||
PAGE_STORE_SIZE + PAGERANGE_STORE_SIZE,
|
||||
{LOGRECTYPE_VARIABLE_LENGTH, 0,
|
||||
FILEID_STORE_SIZE + PAGERANGE_STORE_SIZE,
|
||||
NULL, write_hook_for_redo, NULL, 0,
|
||||
"redo_purge_blocks", LOGREC_NOT_LAST_IN_GROUP, NULL, NULL};
|
||||
|
||||
|
|
@ -5288,8 +5284,9 @@ translog_get_next_chunk(TRANSLOG_SCANNER_DATA *scanner)
|
|||
@param page_offset Offset of the first chunk in the page
|
||||
@param buff Buffer to be filled with header data
|
||||
@param scanner If present should be moved to the header page if
|
||||
it differ from LSN page
|
||||
@return Length of header or operation status
|
||||
it differ from LSN page
|
||||
|
||||
@return Length of header or operation status
|
||||
@retval RECHEADER_READ_ERROR error
|
||||
@retval # number of bytes in
|
||||
TRANSLOG_HEADER_BUFFER::header where
|
||||
|
|
@ -5311,7 +5308,6 @@ int translog_variable_length_header(uchar *page, translog_size_t page_offset,
|
|||
uint16 buffer_length= length;
|
||||
uint16 body_len;
|
||||
TRANSLOG_SCANNER_DATA internal_scanner;
|
||||
|
||||
DBUG_ENTER("translog_variable_length_header");
|
||||
|
||||
buff->record_length= translog_variable_record_1group_decode_len(&src);
|
||||
|
|
|
|||
|
|
@ -53,6 +53,7 @@ prototype_exec_hook(REDO_PURGE_BLOCKS);
|
|||
prototype_exec_hook(REDO_DELETE_ALL);
|
||||
prototype_exec_hook(UNDO_ROW_INSERT);
|
||||
prototype_exec_hook(UNDO_ROW_DELETE);
|
||||
prototype_exec_hook(UNDO_ROW_UPDATE);
|
||||
prototype_exec_hook(UNDO_ROW_PURGE);
|
||||
prototype_exec_hook(COMMIT);
|
||||
static int end_of_redo_phase();
|
||||
|
|
@ -197,6 +198,7 @@ int maria_apply_log(LSN lsn, my_bool apply, FILE *trace_file)
|
|||
install_exec_hook(REDO_DELETE_ALL);
|
||||
install_exec_hook(UNDO_ROW_INSERT);
|
||||
install_exec_hook(UNDO_ROW_DELETE);
|
||||
install_exec_hook(UNDO_ROW_UPDATE);
|
||||
install_exec_hook(UNDO_ROW_PURGE);
|
||||
install_exec_hook(COMMIT);
|
||||
|
||||
|
|
@ -512,9 +514,6 @@ prototype_exec_hook(REDO_CREATE_TABLE)
|
|||
ptr+= 2;
|
||||
/* set create_rename_lsn (for maria_read_log to be idempotent) */
|
||||
lsn_store(ptr + sizeof(info->s->state.header) + 2, rec->lsn);
|
||||
/* we also set is_of_lsn, like maria_create() does */
|
||||
lsn_store(ptr + sizeof(info->s->state.header) + 2 + LSN_STORE_SIZE,
|
||||
rec->lsn);
|
||||
if (my_pwrite(kfile, ptr,
|
||||
kfile_size_before_extension, 0, MYF(MY_NABP|MY_WME)) ||
|
||||
my_chsize(kfile, keystart, 0, MYF(MY_WME)))
|
||||
|
|
@ -766,7 +765,7 @@ end:
|
|||
prototype_exec_hook(REDO_INSERT_ROW_TAIL)
|
||||
{
|
||||
int error= 1;
|
||||
uchar *buff= NULL;
|
||||
uchar *buff;
|
||||
MARIA_HA *info= get_MARIA_HA_from_REDO_record(rec);
|
||||
if (info == NULL)
|
||||
goto end;
|
||||
|
|
@ -834,11 +833,24 @@ end:
|
|||
prototype_exec_hook(REDO_PURGE_BLOCKS)
|
||||
{
|
||||
int error= 1;
|
||||
uchar *buff;
|
||||
MARIA_HA *info= get_MARIA_HA_from_REDO_record(rec);
|
||||
if (info == NULL)
|
||||
goto end;
|
||||
enlarge_buffer(rec);
|
||||
|
||||
if (log_record_buffer.str == NULL ||
|
||||
translog_read_record(rec->lsn, 0, rec->record_length,
|
||||
log_record_buffer.str, NULL) !=
|
||||
rec->record_length)
|
||||
{
|
||||
fprintf(tracef, "Failed to read record\n");
|
||||
goto end;
|
||||
}
|
||||
|
||||
buff= log_record_buffer.str;
|
||||
if (_ma_apply_redo_purge_blocks(info, current_group_end_lsn,
|
||||
rec->header + FILEID_STORE_SIZE))
|
||||
buff + FILEID_STORE_SIZE))
|
||||
goto end;
|
||||
error= 0;
|
||||
end:
|
||||
|
|
@ -911,6 +923,23 @@ end:
|
|||
}
|
||||
|
||||
|
||||
prototype_exec_hook(UNDO_ROW_UPDATE)
|
||||
{
|
||||
int error= 1;
|
||||
MARIA_HA *info= get_MARIA_HA_from_UNDO_record(rec);
|
||||
if (info == NULL)
|
||||
goto end;
|
||||
all_active_trans[rec->short_trid].undo_lsn= rec->lsn;
|
||||
/*
|
||||
todo: instead of above, call write_hook_for_undo, it will also set
|
||||
first_undo_lsn
|
||||
*/
|
||||
error= 0;
|
||||
end:
|
||||
return error;
|
||||
}
|
||||
|
||||
|
||||
prototype_exec_hook(UNDO_ROW_PURGE)
|
||||
{
|
||||
int error= 1;
|
||||
|
|
|
|||
|
|
@ -66,7 +66,8 @@ int main(int argc,char *argv[])
|
|||
TRANSLOG_PAGE_SIZE) == 0) ||
|
||||
translog_init(maria_data_root, TRANSLOG_FILE_SIZE,
|
||||
0, 0, maria_log_pagecache,
|
||||
TRANSLOG_DEFAULT_FLAGS))
|
||||
TRANSLOG_DEFAULT_FLAGS) ||
|
||||
(transactional && trnman_init()))
|
||||
{
|
||||
fprintf(stderr, "Error in initialization");
|
||||
exit(1);
|
||||
|
|
@ -180,6 +181,8 @@ static int run_test(const char *filename)
|
|||
if (!silent)
|
||||
printf("- Writing key:s\n");
|
||||
|
||||
if (maria_begin(file))
|
||||
goto err;
|
||||
my_errno=0;
|
||||
row_count=deleted=0;
|
||||
for (i=49 ; i>=1 ; i-=2 )
|
||||
|
|
@ -266,8 +269,14 @@ static int run_test(const char *filename)
|
|||
|
||||
if (!silent)
|
||||
printf("- Reopening file\n");
|
||||
if (maria_close(file)) goto err;
|
||||
if (!(file=maria_open(filename,2,HA_OPEN_ABORT_IF_LOCKED))) goto err;
|
||||
if (maria_commit(file))
|
||||
goto err;
|
||||
if (maria_close(file))
|
||||
goto err;
|
||||
if (!(file=maria_open(filename,2,HA_OPEN_ABORT_IF_LOCKED)))
|
||||
goto err;
|
||||
if (maria_begin(file))
|
||||
goto err;
|
||||
if (!skip_delete)
|
||||
{
|
||||
if (!silent)
|
||||
|
|
@ -354,6 +363,8 @@ static int run_test(const char *filename)
|
|||
i-1,error,my_errno,read_record+1);
|
||||
}
|
||||
}
|
||||
if (maria_commit(file))
|
||||
goto err;
|
||||
if (maria_close(file))
|
||||
goto err;
|
||||
maria_end();
|
||||
|
|
|
|||
|
|
@ -244,13 +244,15 @@ int main(int argc, char *argv[])
|
|||
if (opt_quick_mode)
|
||||
maria_extra(file,HA_EXTRA_QUICK,0);
|
||||
|
||||
maria_begin(file);
|
||||
|
||||
for (i=0 ; i < recant ; i++)
|
||||
{
|
||||
ulong blob_length;
|
||||
#if 0
|
||||
/*
|
||||
Starting from i==72, there was a difference between runtime and
|
||||
log-appplying. This is now fixed, by not using non_header_data_len in
|
||||
log-applying. This is now fixed, by not using non_header_data_len in
|
||||
log-applying.
|
||||
*/
|
||||
if (i == 72) goto end;
|
||||
|
|
@ -890,6 +892,8 @@ int main(int argc, char *argv[])
|
|||
goto err;
|
||||
}
|
||||
end:
|
||||
if (maria_commit(file))
|
||||
goto err;
|
||||
if (maria_close(file))
|
||||
goto err;
|
||||
maria_panic(HA_PANIC_CLOSE); /* Should close log */
|
||||
|
|
|
|||
41
storage/maria/ma_test_recovery
Normal file → Executable file
41
storage/maria/ma_test_recovery
Normal file → Executable file
|
|
@ -1,3 +1,5 @@
|
|||
#!/bin/sh
|
||||
|
||||
set -e
|
||||
silent="-s"
|
||||
if [ -z "$maria_path" ]
|
||||
|
|
@ -5,6 +7,13 @@ then
|
|||
maria_path="."
|
||||
fi
|
||||
|
||||
tmp=$maria_path/tmp
|
||||
|
||||
if test '!' -d $tmp
|
||||
then
|
||||
mkdir $tmp
|
||||
fi
|
||||
|
||||
echo "MARIA RECOVERY TESTS - success is if exit code is 0"
|
||||
|
||||
# runs a program inserting/deleting rows, then moves the resulting table
|
||||
|
|
@ -14,28 +23,40 @@ echo "MARIA RECOVERY TESTS - success is if exit code is 0"
|
|||
|
||||
for prog in "$maria_path/ma_test1 $silent -M -T --skip-update -c" "$maria_path/ma_test2 $silent -L -K -W -P -M -T -g -c"
|
||||
do
|
||||
rm -f maria_log*
|
||||
rm -f maria_log.* maria_log_control
|
||||
echo "TEST WITH $prog"
|
||||
$prog
|
||||
# derive table's name from program's name
|
||||
table=`echo $prog | sed -e 's;.*ma_\(test[0-9]\).*;\1;' `
|
||||
$maria_path/maria_chk -dvv $table > maria_chk_message.good.txt 2>&1
|
||||
mv -f $table.MAD $table.MAD.good
|
||||
$maria_path/maria_chk -dvv $table > $tmp/maria_chk_message.good.txt 2>&1
|
||||
checksum=`$maria_path/maria_chk -dss $table`
|
||||
mv -f $table.MAD $tmp/$table.MAD.good
|
||||
rm $table.MAI
|
||||
echo "applying log"
|
||||
$maria_path/maria_read_log -a > maria_read_log_$table.txt
|
||||
cmp $table.MAD $table.MAD.good
|
||||
$maria_path/maria_chk -dvv $table > maria_chk_message.txt 2>&1
|
||||
$maria_path/maria_read_log -a > $tmp/maria_read_log_$table.txt
|
||||
$maria_path/maria_chk -dvv $table > $tmp/maria_chk_message.txt 2>&1
|
||||
|
||||
# QQ: Remove the following line when we also can recovert the index file
|
||||
$maria_path/maria_chk -s -r $table
|
||||
|
||||
$maria_path/maria_chk -s -e $table
|
||||
checksum2=`$maria_path/maria_chk -dss $table`
|
||||
if test "$checksum" != "$checksum2"
|
||||
then
|
||||
echo "checksum differs for $table before and after recovery"
|
||||
exit 1;
|
||||
fi
|
||||
# cmp $table.MAD $tmp/$table.MAD.good
|
||||
# When "recovery of the table's state" is ready, we can test it like this:
|
||||
# diff maria_chk_message.good.txt maria_chk_message.txt >maria_chk_diff.txt || true
|
||||
# if [ -s maria_chk_diff.txt ]
|
||||
# diff $tmp/maria_chk_message.good.txt $tmp/maria_chk_message.txt > $tmp/maria_chk_diff.txt || true
|
||||
# if [ -s $tmp/maria_chk_diff.txt ]
|
||||
# then
|
||||
# echo "Differences in maria_chk -dvv, recovery not yet perfect !"
|
||||
# echo "========DIFF START======="
|
||||
# cat maria_chk_diff.txt
|
||||
# cat $tmp/maria_chk_diff.txt
|
||||
# echo "========DIFF END======="
|
||||
# fi
|
||||
rm -f $table.* maria_chk_*.txt maria_read_log_$table.txt
|
||||
rm -f $table.* $tmp/maria_chk_*.txt $tmp/maria_read_log_$table.txt
|
||||
done
|
||||
|
||||
echo "ALL RECOVERY TESTS OK"
|
||||
|
|
|
|||
|
|
@ -115,7 +115,7 @@ int main(int argc, char **argv)
|
|||
(!(check_param.testflag & (T_REP | T_REP_BY_SORT | T_SORT_RECORDS |
|
||||
T_SORT_INDEX))))
|
||||
{
|
||||
uint old_testflag=check_param.testflag;
|
||||
ulonglong old_testflag=check_param.testflag;
|
||||
if (!(check_param.testflag & T_REP))
|
||||
check_param.testflag|= T_REP_BY_SORT;
|
||||
check_param.testflag&= ~T_EXTEND; /* Don't needed */
|
||||
|
|
@ -126,7 +126,8 @@ int main(int argc, char **argv)
|
|||
}
|
||||
else
|
||||
error|=new_error;
|
||||
if (argc && (!(check_param.testflag & T_SILENT) || check_param.testflag & T_INFO))
|
||||
if (argc && (!(check_param.testflag & T_SILENT) ||
|
||||
check_param.testflag & T_INFO))
|
||||
{
|
||||
puts("\n---------\n");
|
||||
VOID(fflush(stdout));
|
||||
|
|
@ -1236,6 +1237,16 @@ static void descript(HA_CHECK *param, register MARIA_HA *info, char *name)
|
|||
char llbuff[22],llbuff2[22];
|
||||
DBUG_ENTER("describe");
|
||||
|
||||
if (param->testflag & T_VERY_SILENT)
|
||||
{
|
||||
longlong checksum= info->state->checksum;
|
||||
if (!(share->options & (HA_OPTION_CHECKSUM | HA_OPTION_COMPRESS_RECORD)))
|
||||
checksum= 0;
|
||||
printf("%s %s %s\n", name, llstr(info->state->records,llbuff),
|
||||
llstr(checksum, llbuff2));
|
||||
DBUG_VOID_RETURN;
|
||||
}
|
||||
|
||||
printf("\nMARIA file: %s\n",name);
|
||||
printf("Record format: %s\n", record_formats[share->data_file_type]);
|
||||
printf("Character set: %s (%d)\n",
|
||||
|
|
|
|||
|
|
@ -894,6 +894,7 @@ void _ma_restore_status(void *param);
|
|||
void _ma_copy_status(void *to, void *from);
|
||||
my_bool _ma_check_status(void *param);
|
||||
void _ma_reset_status(MARIA_HA *maria);
|
||||
int ma_commit(struct st_transaction *trn);
|
||||
|
||||
extern MARIA_HA *_ma_test_if_reopen(char *filename);
|
||||
my_bool _ma_check_table_is_closed(const char *name, const char *where);
|
||||
|
|
|
|||
|
|
@ -113,6 +113,8 @@ end:
|
|||
|
||||
static struct my_option my_long_options[] =
|
||||
{
|
||||
{"help", '?', "Display this help and exit.",
|
||||
0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0},
|
||||
{"only-display", 'o', "display brief info about records's header",
|
||||
(uchar **) &opt_only_display, (uchar **) &opt_only_display, 0, GET_BOOL,
|
||||
NO_ARG,0, 0, 0, 0, 0, 0},
|
||||
|
|
@ -161,6 +163,9 @@ get_one_option(int optid __attribute__((unused)),
|
|||
char *argument __attribute__((unused)))
|
||||
{
|
||||
switch (optid) {
|
||||
case '?':
|
||||
usage();
|
||||
exit(0);
|
||||
#ifndef DBUG_OFF
|
||||
case '#':
|
||||
DBUG_SET_INITIAL(argument ? argument : default_dbug_option);
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue