Commit 0a2220b6 authored by unknown's avatar unknown

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

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


storage/maria/ma_loghandler.c:
  Auto merged
storage/maria/ma_loghandler.h:
  Auto merged
parents 7c273b82 bd02914a
...@@ -3045,3 +3045,6 @@ win/vs71cache.txt ...@@ -3045,3 +3045,6 @@ win/vs71cache.txt
win/vs8cache.txt win/vs8cache.txt
zlib/*.ds? zlib/*.ds?
zlib/*.vcproj 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, ...@@ -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_is_changed(struct st_maria_info *info);
extern int maria_delete_all_rows(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 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 */ /* this is used to pass to mysql_mariachk_table */
......
...@@ -22,6 +22,16 @@ ...@@ -22,6 +22,16 @@
/* My memory re allocator */ /* My memory re allocator */
/**
@brief wrapper around realloc()
@param oldpoint pointer to currently allocated area
@param size new size requested, must be >0
@param my_flags flags
@note if size==0 realloc() may return NULL; my_realloc() treats this as an
error which is not the intention of realloc()
*/
void* my_realloc(void* oldpoint, size_t size, myf my_flags) void* my_realloc(void* oldpoint, size_t size, myf my_flags)
{ {
void *point; void *point;
...@@ -29,6 +39,7 @@ void* my_realloc(void* oldpoint, size_t size, myf my_flags) ...@@ -29,6 +39,7 @@ void* my_realloc(void* oldpoint, size_t size, myf my_flags)
DBUG_PRINT("my",("ptr: 0x%lx size: %lu my_flags: %d", (long) oldpoint, DBUG_PRINT("my",("ptr: 0x%lx size: %lu my_flags: %d", (long) oldpoint,
(ulong) size, my_flags)); (ulong) size, my_flags));
DBUG_ASSERT(size > 0);
if (!oldpoint && (my_flags & MY_ALLOW_ZERO_PTR)) if (!oldpoint && (my_flags & MY_ALLOW_ZERO_PTR))
DBUG_RETURN(my_malloc(size,my_flags)); DBUG_RETURN(my_malloc(size,my_flags));
#ifdef USE_HALLOC #ifdef USE_HALLOC
......
...@@ -3418,6 +3418,17 @@ server."); ...@@ -3418,6 +3418,17 @@ server.");
using_update_log=1; using_update_log=1;
} }
/* call ha_init_key_cache() on all key caches to init them */
process_key_caches(&ha_init_key_cache);
/*
Maria's pagecache needs to be ready before Maria engine (Recovery uses
pagecache, and Checkpoint may happen at startup). Maria engine is taken up
in plugin_init().
*/
#ifdef WITH_MARIA_STORAGE_ENGINE
process_pagecaches(&ha_init_pagecache);
#endif /* WITH_MARIA_STORAGE_ENGINE */
/* Allow storage engine to give real error messages */ /* Allow storage engine to give real error messages */
if (ha_init_errors()) if (ha_init_errors())
DBUG_RETURN(1); DBUG_RETURN(1);
...@@ -3588,12 +3599,6 @@ server."); ...@@ -3588,12 +3599,6 @@ server.");
if (opt_myisam_log) if (opt_myisam_log)
(void) mi_log(1); (void) mi_log(1);
/* call ha_init_key_cache() on all key caches to init them */
process_key_caches(&ha_init_key_cache);
#ifdef WITH_MARIA_STORAGE_ENGINE
process_pagecaches(&ha_init_pagecache);
#endif /* WITH_MARIA_STORAGE_ENGINE */
#if defined(HAVE_MLOCKALL) && defined(MCL_CURRENT) && !defined(EMBEDDED_LIBRARY) #if defined(HAVE_MLOCKALL) && defined(MCL_CURRENT) && !defined(EMBEDDED_LIBRARY)
if (locked_in_memory && !getuid()) if (locked_in_memory && !getuid())
{ {
......
...@@ -27,11 +27,16 @@ ...@@ -27,11 +27,16 @@
#include "ha_maria.h" #include "ha_maria.h"
#include "trnman_public.h" #include "trnman_public.h"
C_MODE_START
#include "maria_def.h" #include "maria_def.h"
#include "ma_rt_index.h" #include "ma_rt_index.h"
#include "ma_blockrec.h" #include "ma_blockrec.h"
#include "ma_commit.h" C_MODE_END
/*
Note that in future versions, only *transactional* Maria tables can
rollback, so this flag should be up or down conditionally.
*/
#define MARIA_CANNOT_ROLLBACK HA_NO_TRANSACTIONS #define MARIA_CANNOT_ROLLBACK HA_NO_TRANSACTIONS
#ifdef MARIA_CANNOT_ROLLBACK #ifdef MARIA_CANNOT_ROLLBACK
#define trans_register_ha(A, B, C) do { /* nothing */ } while(0) #define trans_register_ha(A, B, C) do { /* nothing */ } while(0)
...@@ -2384,7 +2389,7 @@ static int ha_maria_init(void *p) ...@@ -2384,7 +2389,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_data_root= mysql_real_data_home; maria_data_root= mysql_real_data_home;
res= maria_init() || ma_control_file_create_or_open(TRUE) || res= maria_init() || ma_control_file_create_or_open() ||
(init_pagecache(maria_log_pagecache, (init_pagecache(maria_log_pagecache,
TRANSLOG_PAGECACHE_SIZE, 0, 0, TRANSLOG_PAGECACHE_SIZE, 0, 0,
TRANSLOG_PAGE_SIZE) == 0) || TRANSLOG_PAGE_SIZE) == 0) ||
......
...@@ -512,15 +512,19 @@ static my_bool _ma_read_bitmap_page(MARIA_SHARE *share, ...@@ -512,15 +512,19 @@ static my_bool _ma_read_bitmap_page(MARIA_SHARE *share,
MARIA_FILE_BITMAP *bitmap, MARIA_FILE_BITMAP *bitmap,
ulonglong page) ulonglong page)
{ {
my_off_t position= page * bitmap->block_size; my_off_t end_of_page= (page + 1) * bitmap->block_size;
my_bool res; my_bool res;
DBUG_ENTER("_ma_read_bitmap_page"); DBUG_ENTER("_ma_read_bitmap_page");
DBUG_ASSERT(page % bitmap->pages_covered == 0); DBUG_ASSERT(page % bitmap->pages_covered == 0);
bitmap->page= page; bitmap->page= page;
if (position >= share->state.state.data_file_length) if (end_of_page > share->state.state.data_file_length)
{ {
share->state.state.data_file_length= position + bitmap->block_size; /*
Inexistent or half-created page (could be crash in the middle of
_ma_bitmap_create_first(), before appending maria_bitmap_marker).
*/
share->state.state.data_file_length= end_of_page;
bzero(bitmap->map, bitmap->block_size); bzero(bitmap->map, bitmap->block_size);
memcpy(bitmap->map + bitmap->block_size - sizeof(maria_bitmap_marker), memcpy(bitmap->map + bitmap->block_size - sizeof(maria_bitmap_marker),
maria_bitmap_marker, sizeof(maria_bitmap_marker)); maria_bitmap_marker, sizeof(maria_bitmap_marker));
...@@ -2047,7 +2051,8 @@ int _ma_bitmap_create_first(MARIA_SHARE *share) ...@@ -2047,7 +2051,8 @@ int _ma_bitmap_create_first(MARIA_SHARE *share)
{ {
uint block_size= share->bitmap.block_size; uint block_size= share->bitmap.block_size;
File file= share->bitmap.file.file; File file= share->bitmap.file.file;
if (my_chsize(file, block_size, 0, MYF(MY_WME)) || if (my_chsize(file, block_size - sizeof(maria_bitmap_marker),
0, MYF(MY_WME)) ||
my_pwrite(file, maria_bitmap_marker, sizeof(maria_bitmap_marker), my_pwrite(file, maria_bitmap_marker, sizeof(maria_bitmap_marker),
block_size - sizeof(maria_bitmap_marker), block_size - sizeof(maria_bitmap_marker),
MYF(MY_NABP | MY_WME))) MYF(MY_NABP | MY_WME)))
......
This diff is collapsed.
...@@ -2046,15 +2046,8 @@ int maria_repair(HA_CHECK *param, register MARIA_HA *info, ...@@ -2046,15 +2046,8 @@ int maria_repair(HA_CHECK *param, register MARIA_HA *info,
goto err; goto err;
} }
_ma_reset_status(sort_info.new_info); _ma_reset_status(sort_info.new_info);
#ifdef ASK_MONTY /* cf maria_create() */
/**
@todo ASK_MONTY
without this call, a REPAIR on an empty table leaves the data file of
size 0, which sounds reasonable.
*/
if (_ma_initialize_data_file(sort_info.new_info->s, new_file)) if (_ma_initialize_data_file(sort_info.new_info->s, new_file))
goto err; goto err;
#endif
block_record= 1; block_record= 1;
} }
} }
......
...@@ -28,8 +28,13 @@ ...@@ -28,8 +28,13 @@
int ma_commit(TRN *trn) 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) */ 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 COMMIT record is written before trnman_commit_trn():
if Checkpoint comes in the middle it will see trn is not committed, if Checkpoint comes in the middle it will see trn is not committed,
...@@ -45,27 +50,75 @@ int ma_commit(TRN *trn) ...@@ -45,27 +50,75 @@ int ma_commit(TRN *trn)
issue (transaction's updates were made visible to other transactions). issue (transaction's updates were made visible to other transactions).
So we need to go the first way. So we need to go the first way.
*/ */
/** /**
@todo RECOVERY share's state is written to disk only in @todo RECOVERY share's state is written to disk only in
maria_lock_database(), so COMMIT record is not the last record of the 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 transaction! It is probably an issue. Recovery of the state is a problem
not yet solved. 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 We do not store "thd->transaction.xid_state.xid" for now, it will be
needed only when we support XA. needed only when we support XA.
*/ */
return res= (translog_write_record(&commit_lsn, LOGREC_COMMIT,
translog_write_record(&commit_lsn, LOGREC_COMMIT,
trn, NULL, 0, trn, NULL, 0,
sizeof(log_array)/sizeof(log_array[0]), sizeof(log_array)/sizeof(log_array[0]),
log_array, NULL) || log_array, NULL) ||
translog_flush(commit_lsn) || trnman_commit_trn(trn); translog_flush(commit_lsn) ||
trnman_commit_trn(trn));
/* /*
Note: if trnman_commit_trn() fails above, we have already Note: if trnman_commit_trn() fails above, we have already
written the COMMIT record, so Checkpoint and Recovery will see the written the COMMIT record, so Checkpoint and Recovery will see the
transaction as committed. 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);
} }
...@@ -41,6 +41,10 @@ ...@@ -41,6 +41,10 @@
#define CONTROL_FILE_SIZE (CONTROL_FILE_FILENO_OFFSET + CONTROL_FILE_FILENO_SIZE) #define CONTROL_FILE_SIZE (CONTROL_FILE_FILENO_OFFSET + CONTROL_FILE_FILENO_SIZE)
/* This module owns these two vars. */ /* This module owns these two vars. */
/**
This LSN serves for the two-checkpoint rule, and also to find the
checkpoint record when doing a recovery.
*/
LSN last_checkpoint_lsn= LSN_IMPOSSIBLE; LSN last_checkpoint_lsn= LSN_IMPOSSIBLE;
uint32 last_logno= FILENO_IMPOSSIBLE; uint32 last_logno= FILENO_IMPOSSIBLE;
...@@ -68,8 +72,6 @@ static int control_file_fd= -1; ...@@ -68,8 +72,6 @@ static int control_file_fd= -1;
the last_checkpoint_lsn and last_logno global variables. the last_checkpoint_lsn and last_logno global variables.
Called at engine's start. Called at engine's start.
@param create_if_missing
@note @note
The format of the control file is: The format of the control file is:
4 bytes: magic string 4 bytes: magic string
...@@ -78,11 +80,13 @@ static int control_file_fd= -1; ...@@ -78,11 +80,13 @@ static int control_file_fd= -1;
4 bytes: offset in log where last checkpoint is 4 bytes: offset in log where last checkpoint is
4 bytes: number of last log 4 bytes: number of last log
@note If in recovery, file is not created
@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(my_bool create_if_missing) CONTROL_FILE_ERROR ma_control_file_create_or_open()
{ {
char buffer[CONTROL_FILE_SIZE]; char buffer[CONTROL_FILE_SIZE];
char name[FN_REFLEN]; char name[FN_REFLEN];
...@@ -111,7 +115,8 @@ CONTROL_FILE_ERROR ma_control_file_create_or_open(my_bool create_if_missing) ...@@ -111,7 +115,8 @@ CONTROL_FILE_ERROR ma_control_file_create_or_open(my_bool create_if_missing)
if (create_file) if (create_file)
{ {
if (!create_if_missing) /* in a recovery, we expect to find a control file */
if (maria_in_recovery)
DBUG_RETURN(CONTROL_FILE_MISSING); DBUG_RETURN(CONTROL_FILE_MISSING);
if ((control_file_fd= my_create(name, 0, if ((control_file_fd= my_create(name, 0,
open_flags, MYF(MY_SYNC_DIR))) < 0) open_flags, MYF(MY_SYNC_DIR))) < 0)
......
...@@ -61,7 +61,7 @@ extern "C" { ...@@ -61,7 +61,7 @@ extern "C" {
If present, reads it to find out last checkpoint's LSN and last log. If present, reads it to find out last checkpoint's LSN and last log.
Called at engine's start. Called at engine's start.
*/ */
CONTROL_FILE_ERROR ma_control_file_create_or_open(my_bool); CONTROL_FILE_ERROR ma_control_file_create_or_open();
/* /*
Write information durably to the control file. Write information durably to the control file.
Called when we have created a new log (after syncing this log's creation) Called when we have created a new log (after syncing this log's creation)
......
...@@ -664,6 +664,14 @@ int maria_create(const char *name, enum data_file_type datafile_type, ...@@ -664,6 +664,14 @@ int maria_create(const char *name, enum data_file_type datafile_type,
share.base.keystart = share.state.state.key_file_length= share.base.keystart = share.state.state.key_file_length=
MY_ALIGN(info_length, maria_block_size); MY_ALIGN(info_length, maria_block_size);
if (share.data_file_type == BLOCK_RECORD)
{
/*
we are going to create a first bitmap page, set data_file_length
to reflect this, before the state goes to disk
*/
share.state.state.data_file_length= maria_block_size;
}
share.base.max_key_block_length= maria_block_size; share.base.max_key_block_length= maria_block_size;
share.base.max_key_length=ALIGN_SIZE(max_key_length+4); share.base.max_key_length=ALIGN_SIZE(max_key_length+4);
share.base.records=ci->max_rows; share.base.records=ci->max_rows;
...@@ -1041,36 +1049,8 @@ int maria_create(const char *name, enum data_file_type datafile_type, ...@@ -1041,36 +1049,8 @@ int maria_create(const char *name, enum data_file_type datafile_type,
goto err; goto err;
errpos=3; errpos=3;
/**
@todo ASK_MONTY
QQ: this sets data_file_length from 0 to 8192, but we wrote the state
already to the index file (because:
- log record is built from index header so state must be written before
log record
- data file must be created after log record, so that "missing log
record" implies "unusable table").
When we wrote the state, we hadn't called ma_initialize_data_file(), so
the data_file_length is 0!
Thus, we below create a 8192-byte data file, but its recorded size is 0,
so next time we read the bitmap (a maria_write() for example) we'll
overwrite the bitmap we just created below.
It's not very efficient.
It also makes maria_chk_size() print
Size of datafile is: 8192 Should be: 0
on a freshly created table (run "check.test" with a Maria table).
Why do we absolutely want to create a 8192-byte page for a freshly
created, empty table? Why don't we leave the data file empty?
Removing the call below at least removes the maria_chk_size() issue.
Monty wrote on IRC, about a size of 0:
"This basically ok; The first block is a bitmap that may or may not
exists", but later he asked that the first block always exists.???
*/
#ifdef ASK_MONTY
if (_ma_initialize_data_file(&share, dfile)) if (_ma_initialize_data_file(&share, dfile))
goto err; goto err;
#endif
} }
/* Enlarge files */ /* Enlarge files */
......
...@@ -159,7 +159,7 @@ struct st_translog_descriptor ...@@ -159,7 +159,7 @@ struct st_translog_descriptor
LSN flushed; LSN flushed;
/* Last LSN sent to the disk (but maybe not written yet) */ /* Last LSN sent to the disk (but maybe not written yet) */
LSN sent_to_file; LSN sent_to_file;
/* All what is after this addess is not sent to disk yet */ /* All what is after this address is not sent to disk yet */
TRANSLOG_ADDRESS in_buffers_only; TRANSLOG_ADDRESS in_buffers_only;
pthread_mutex_t sent_to_file_lock; pthread_mutex_t sent_to_file_lock;
...@@ -306,13 +306,9 @@ static LOG_DESC INIT_LOGREC_REDO_PURGE_ROW_TAIL= ...@@ -306,13 +306,9 @@ static LOG_DESC INIT_LOGREC_REDO_PURGE_ROW_TAIL=
NULL, write_hook_for_redo, NULL, 0, NULL, write_hook_for_redo, NULL, 0,
"redo_purge_row_tail", LOGREC_NOT_LAST_IN_GROUP, NULL, NULL}; "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= static LOG_DESC INIT_LOGREC_REDO_PURGE_BLOCKS=
{LOGRECTYPE_VARIABLE_LENGTH, {LOGRECTYPE_VARIABLE_LENGTH, 0,
FILEID_STORE_SIZE + PAGERANGE_STORE_SIZE + FILEID_STORE_SIZE + PAGERANGE_STORE_SIZE,
PAGE_STORE_SIZE + PAGERANGE_STORE_SIZE,
FILEID_STORE_SIZE + PAGERANGE_STORE_SIZE +
PAGE_STORE_SIZE + PAGERANGE_STORE_SIZE,
NULL, write_hook_for_redo, NULL, 0, NULL, write_hook_for_redo, NULL, 0,
"redo_purge_blocks", LOGREC_NOT_LAST_IN_GROUP, NULL, NULL}; "redo_purge_blocks", LOGREC_NOT_LAST_IN_GROUP, NULL, NULL};
...@@ -682,7 +678,7 @@ static my_bool translog_max_lsn_to_header(File file, LSN lsn) ...@@ -682,7 +678,7 @@ static my_bool translog_max_lsn_to_header(File file, LSN lsn)
typedef struct st_loghandler_file_info typedef struct st_loghandler_file_info
{ {
/* /*
LSN_IPOSSIBLE for current file and max LSN which parts stored in the LSN_IMPOSSIBLE for current file and max LSN which parts stored in the
file for all other (finished) files. file for all other (finished) files.
*/ */
LSN max_lsn; LSN max_lsn;
...@@ -824,7 +820,7 @@ static void translog_mark_file_unfinished(uint32 file) ...@@ -824,7 +820,7 @@ static void translog_mark_file_unfinished(uint32 file)
goto end; goto end;
} }
for (place= log_descriptor.unfinished_files.elements; for (place= log_descriptor.unfinished_files.elements - 1;
place >= 0; place >= 0;
place--) place--)
{ {
...@@ -5301,6 +5297,7 @@ translog_get_next_chunk(TRANSLOG_SCANNER_DATA *scanner) ...@@ -5301,6 +5297,7 @@ translog_get_next_chunk(TRANSLOG_SCANNER_DATA *scanner)
@param buff Buffer to be filled with header data @param buff Buffer to be filled with header data
@param scanner If present should be moved to the header page if @param scanner If present should be moved to the header page if
it differ from LSN page it differ from LSN page
@return Length of header or operation status @return Length of header or operation status
@retval RECHEADER_READ_ERROR error @retval RECHEADER_READ_ERROR error
@retval # number of bytes in @retval # number of bytes in
...@@ -5323,7 +5320,6 @@ int translog_variable_length_header(uchar *page, translog_size_t page_offset, ...@@ -5323,7 +5320,6 @@ int translog_variable_length_header(uchar *page, translog_size_t page_offset,
uint16 buffer_length= length; uint16 buffer_length= length;
uint16 body_len; uint16 body_len;
TRANSLOG_SCANNER_DATA internal_scanner; TRANSLOG_SCANNER_DATA internal_scanner;
DBUG_ENTER("translog_variable_length_header"); DBUG_ENTER("translog_variable_length_header");
buff->record_length= translog_variable_record_1group_decode_len(&src); buff->record_length= translog_variable_record_1group_decode_len(&src);
...@@ -6174,7 +6170,7 @@ static my_bool write_hook_for_redo(enum translog_record_type type ...@@ -6174,7 +6170,7 @@ static my_bool write_hook_for_redo(enum translog_record_type type
non-transactional log records (REPAIR, CREATE, RENAME, DROP) should not non-transactional log records (REPAIR, CREATE, RENAME, DROP) should not
call this hook; we trust them but verify ;) call this hook; we trust them but verify ;)
*/ */
DBUG_ASSERT(!(maria_multi_threaded && (trn->trid == 0))); DBUG_ASSERT(trn->trid != 0);
/* /*
If the hook stays so simple, it would be faster to pass If the hook stays so simple, it would be faster to pass
!trn->rec_lsn ? trn->rec_lsn : some_dummy_lsn !trn->rec_lsn ? trn->rec_lsn : some_dummy_lsn
...@@ -6203,7 +6199,7 @@ static my_bool write_hook_for_undo(enum translog_record_type type ...@@ -6203,7 +6199,7 @@ static my_bool write_hook_for_undo(enum translog_record_type type
struct st_translog_parts *parts struct st_translog_parts *parts
__attribute__ ((unused))) __attribute__ ((unused)))
{ {
DBUG_ASSERT(!(maria_multi_threaded && (trn->trid == 0))); DBUG_ASSERT(trn->trid != 0);
trn->undo_lsn= *lsn; trn->undo_lsn= *lsn;
if (unlikely(LSN_WITH_FLAGS_TO_LSN(trn->first_undo_lsn) == 0)) if (unlikely(LSN_WITH_FLAGS_TO_LSN(trn->first_undo_lsn) == 0))
trn->first_undo_lsn= trn->first_undo_lsn=
...@@ -6316,6 +6312,17 @@ void translog_deassign_id_from_share(MARIA_SHARE *share) ...@@ -6316,6 +6312,17 @@ void translog_deassign_id_from_share(MARIA_SHARE *share)
} }
void translog_assign_id_to_share_from_recovery(MARIA_SHARE *share,
uint16 id)
{
DBUG_ASSERT(maria_in_recovery && !maria_multi_threaded);
DBUG_ASSERT(share->data_file_type == BLOCK_RECORD);
DBUG_ASSERT(share->id == 0);
DBUG_ASSERT(id_to_share[id] == NULL);
id_to_share[share->id= id]= share;
}
/** /**
@brief check if such log file exists @brief check if such log file exists
......
...@@ -260,6 +260,9 @@ extern TRANSLOG_ADDRESS translog_get_horizon(); ...@@ -260,6 +260,9 @@ extern TRANSLOG_ADDRESS translog_get_horizon();
extern int translog_assign_id_to_share(struct st_maria_share *share, extern int translog_assign_id_to_share(struct st_maria_share *share,
struct st_transaction *trn); struct st_transaction *trn);
extern void translog_deassign_id_from_share(struct st_maria_share *share); extern void translog_deassign_id_from_share(struct st_maria_share *share);
extern void
translog_assign_id_to_share_from_recovery(struct st_maria_share *share,
uint16 id);
extern my_bool translog_inited; extern my_bool translog_inited;
/* /*
......
...@@ -84,6 +84,9 @@ typedef LSN LSN_WITH_FLAGS; ...@@ -84,6 +84,9 @@ typedef LSN LSN_WITH_FLAGS;
/* following LSN also is impossible */ /* following LSN also is impossible */
#define LSN_ERROR 1 #define LSN_ERROR 1
/** @brief some impossible LSN serve as markers */
#define LSN_REPAIRED_BY_MARIA_CHK ((LSN)1)
/** /**
@brief the maximum valid LSN. @brief the maximum valid LSN.
Unlike ULONGLONG_MAX, it can be safely used in comparison with valid LSNs Unlike ULONGLONG_MAX, it can be safely used in comparison with valid LSNs
......
...@@ -171,7 +171,8 @@ static MARIA_HA *maria_clone_internal(MARIA_SHARE *share, int mode, ...@@ -171,7 +171,8 @@ static MARIA_HA *maria_clone_internal(MARIA_SHARE *share, int mode,
share->delay_key_write=1; share->delay_key_write=1;
info.state= &share->state.state; /* Change global values by default */ info.state= &share->state.state; /* Change global values by default */
info.trn= &dummy_transaction_object; if (!share->base.born_transactional) /* but for transactional ones ... */
info.trn= &dummy_transaction_object; /* ... force crash if no trn given */
pthread_mutex_unlock(&share->intern_lock); pthread_mutex_unlock(&share->intern_lock);
/* Allocate buffer for one record */ /* Allocate buffer for one record */
...@@ -600,18 +601,35 @@ MARIA_HA *maria_open(const char *name, int mode, uint open_flags) ...@@ -600,18 +601,35 @@ MARIA_HA *maria_open(const char *name, int mode, uint open_flags)
if (share->base.born_transactional) if (share->base.born_transactional)
{ {
share->page_type= PAGECACHE_LSN_PAGE; share->page_type= PAGECACHE_LSN_PAGE;
#ifdef ENABLE_WHEN_WE_HAVE_TRANS_ROW_ID /* QQ */
share->base_length+= TRANS_ROW_EXTRA_HEADER_SIZE; share->base_length+= TRANS_ROW_EXTRA_HEADER_SIZE;
if (unlikely((share->state.create_rename_lsn == (LSN)ULONGLONG_MAX) && #endif
(open_flags & HA_OPEN_FROM_SQL_LAYER))) if (share->state.create_rename_lsn == LSN_REPAIRED_BY_MARIA_CHK)
{ {
/* /*
This table was repaired with maria_chk. Past log records should be Was repaired with maria_chk, maybe later maria_pack-ed. Some sort of
ignored, future log records should not: we define the present. import into the server. It starts its existence (from the point of
view of the server, including server's recovery) now.
*/ */
if ((open_flags & HA_OPEN_FROM_SQL_LAYER) || maria_in_recovery)
{
share->state.create_rename_lsn= translog_get_horizon(); share->state.create_rename_lsn= translog_get_horizon();
_ma_update_create_rename_lsn_on_disk(share, TRUE); _ma_update_create_rename_lsn_on_disk(share, TRUE);
} }
} }
else if (!LSN_VALID(share->state.create_rename_lsn) &&
!(open_flags & HA_OPEN_FOR_REPAIR))
{
/*
If in Recovery, it will not work. If LSN is invalid and not
LSN_REPAIRED_BY_MARIA_CHK, header must be corrupted.
In both cases, must repair.
*/
my_errno=((share->state.changed & STATE_CRASHED_ON_REPAIR) ?
HA_ERR_CRASHED_ON_REPAIR : HA_ERR_CRASHED_ON_USAGE);
goto err;
}
}
else else
share->page_type= PAGECACHE_PLAIN_PAGE; share->page_type= PAGECACHE_PLAIN_PAGE;
share->now_transactional= share->base.born_transactional; share->now_transactional= share->base.born_transactional;
...@@ -699,6 +717,14 @@ MARIA_HA *maria_open(const char *name, int mode, uint open_flags) ...@@ -699,6 +717,14 @@ MARIA_HA *maria_open(const char *name, int mode, uint open_flags)
{ {
share->lock.get_status=_ma_get_status; share->lock.get_status=_ma_get_status;
share->lock.copy_status=_ma_copy_status; share->lock.copy_status=_ma_copy_status;
/**
@todo RECOVERY
INSERT DELAYED and concurrent inserts are currently disabled for
transactional tables; when enabled again, we should re-evaluate
what problems the call to _ma_update_status() by
thr_reschedule_write_lock() can do (it may hurt Checkpoint as it
would be without intern_lock, and it modifies the state).
*/
share->lock.update_status=_ma_update_status; share->lock.update_status=_ma_update_status;
share->lock.restore_status=_ma_restore_status; share->lock.restore_status=_ma_restore_status;
share->lock.check_status=_ma_check_status; share->lock.check_status=_ma_check_status;
...@@ -958,6 +984,7 @@ uint _ma_state_info_write(File file, MARIA_STATE_INFO *state, uint pWrite) ...@@ -958,6 +984,7 @@ uint _ma_state_info_write(File file, MARIA_STATE_INFO *state, uint pWrite)
uchar buff[MARIA_STATE_INFO_SIZE + MARIA_STATE_EXTRA_SIZE]; uchar buff[MARIA_STATE_INFO_SIZE + MARIA_STATE_EXTRA_SIZE];
uchar *ptr=buff; uchar *ptr=buff;
uint i, keys= (uint) state->header.keys; uint i, keys= (uint) state->header.keys;
size_t res;
DBUG_ENTER("_ma_state_info_write"); DBUG_ENTER("_ma_state_info_write");
memcpy_fixed(ptr,&state->header,sizeof(state->header)); memcpy_fixed(ptr,&state->header,sizeof(state->header));
...@@ -1013,11 +1040,12 @@ uint _ma_state_info_write(File file, MARIA_STATE_INFO *state, uint pWrite) ...@@ -1013,11 +1040,12 @@ uint _ma_state_info_write(File file, MARIA_STATE_INFO *state, uint pWrite)
} }
} }
if (pWrite & 1) res= (pWrite & 1) ?
DBUG_RETURN(my_pwrite(file, buff, (size_t) (ptr-buff), 0L, my_pwrite(file, buff, (size_t) (ptr-buff), 0L,
MYF(MY_NABP | MY_THREADSAFE)) != 0); MYF(MY_NABP | MY_THREADSAFE)) :
DBUG_RETURN(my_write(file, buff, (size_t) (ptr-buff), my_write(file, buff, (size_t) (ptr-buff),
MYF(MY_NABP)) != 0); MYF(MY_NABP));
DBUG_RETURN(res != 0);
} }
...@@ -1072,6 +1100,16 @@ uchar *_ma_state_info_read(uchar *ptr, MARIA_STATE_INFO *state) ...@@ -1072,6 +1100,16 @@ uchar *_ma_state_info_read(uchar *ptr, MARIA_STATE_INFO *state)
} }
/**
@brief Fills the state by reading its copy on disk.
@note Does nothing in single user mode.
@param file file to read from
@param state state which will be filled
@param pRead if true, use my_pread(), otherwise my_read()
*/
uint _ma_state_info_read_dsk(File file, MARIA_STATE_INFO *state, my_bool pRead) uint _ma_state_info_read_dsk(File file, MARIA_STATE_INFO *state, my_bool pRead)
{ {
char buff[MARIA_STATE_INFO_SIZE + MARIA_STATE_EXTRA_SIZE]; char buff[MARIA_STATE_INFO_SIZE + MARIA_STATE_EXTRA_SIZE];
......
This diff is collapsed.
...@@ -25,5 +25,6 @@ ...@@ -25,5 +25,6 @@
C_MODE_START C_MODE_START
int maria_recover(); int maria_recover();
int maria_apply_log(LSN lsn, my_bool applyn, FILE *trace_file); int maria_apply_log(LSN lsn, my_bool apply, FILE *trace_file,
my_bool execute_undo_phase);
C_MODE_END C_MODE_END
...@@ -66,7 +66,8 @@ int main(int argc,char *argv[]) ...@@ -66,7 +66,8 @@ int main(int argc,char *argv[])
TRANSLOG_PAGE_SIZE) == 0) || TRANSLOG_PAGE_SIZE) == 0) ||
translog_init(maria_data_root, TRANSLOG_FILE_SIZE, translog_init(maria_data_root, TRANSLOG_FILE_SIZE,
0, 0, maria_log_pagecache, 0, 0, maria_log_pagecache,
TRANSLOG_DEFAULT_FLAGS)) TRANSLOG_DEFAULT_FLAGS) ||
(transactional && trnman_init()))
{ {
fprintf(stderr, "Error in initialization"); fprintf(stderr, "Error in initialization");
exit(1); exit(1);
...@@ -180,6 +181,8 @@ static int run_test(const char *filename) ...@@ -180,6 +181,8 @@ static int run_test(const char *filename)
if (!silent) if (!silent)
printf("- Writing key:s\n"); printf("- Writing key:s\n");
if (maria_begin(file))
goto err;
my_errno=0; my_errno=0;
row_count=deleted=0; row_count=deleted=0;
for (i=49 ; i>=1 ; i-=2 ) for (i=49 ; i>=1 ; i-=2 )
...@@ -266,8 +269,14 @@ static int run_test(const char *filename) ...@@ -266,8 +269,14 @@ static int run_test(const char *filename)
if (!silent) if (!silent)
printf("- Reopening file\n"); printf("- Reopening file\n");
if (maria_close(file)) goto err; if (maria_commit(file))
if (!(file=maria_open(filename,2,HA_OPEN_ABORT_IF_LOCKED))) goto err; 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 (!skip_delete)
{ {
if (!silent) if (!silent)
...@@ -354,6 +363,8 @@ static int run_test(const char *filename) ...@@ -354,6 +363,8 @@ static int run_test(const char *filename)
i-1,error,my_errno,read_record+1); i-1,error,my_errno,read_record+1);
} }
} }
if (maria_commit(file))
goto err;
if (maria_close(file)) if (maria_close(file))
goto err; goto err;
maria_end(); maria_end();
...@@ -622,7 +633,7 @@ static struct my_option my_long_options[] = ...@@ -622,7 +633,7 @@ static struct my_option my_long_options[] =
0, 0, 0, 0, 0, 0}, 0, 0, 0, 0, 0, 0},
{"unique", 'C', "Undocumented", (uchar**) &opt_unique, {"unique", 'C', "Undocumented", (uchar**) &opt_unique,
(uchar**) &opt_unique, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0}, (uchar**) &opt_unique, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0},
{"update-rows", 'u', "Undocumented", (uchar**) &update_count, {"update-rows", 'u', "Max number of rows to update", (uchar**) &update_count,
(uchar**) &update_count, 0, GET_UINT, REQUIRED_ARG, 1000, 0, 0, 0, 0, 0}, (uchar**) &update_count, 0, GET_UINT, REQUIRED_ARG, 1000, 0, 0, 0, 0, 0},
{"verbose", 'v', "Be more verbose", (uchar**) &verbose, {"verbose", 'v', "Be more verbose", (uchar**) &verbose,
(uchar**) &verbose, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0}, (uchar**) &verbose, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0},
......
...@@ -244,13 +244,15 @@ int main(int argc, char *argv[]) ...@@ -244,13 +244,15 @@ int main(int argc, char *argv[])
if (opt_quick_mode) if (opt_quick_mode)
maria_extra(file,HA_EXTRA_QUICK,0); maria_extra(file,HA_EXTRA_QUICK,0);
maria_begin(file);
for (i=0 ; i < recant ; i++) for (i=0 ; i < recant ; i++)
{ {
ulong blob_length; ulong blob_length;
#if 0 #if 0
/* /*
Starting from i==72, there was a difference between runtime and 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. log-applying.
*/ */
if (i == 72) goto end; if (i == 72) goto end;
...@@ -890,8 +892,14 @@ int main(int argc, char *argv[]) ...@@ -890,8 +892,14 @@ int main(int argc, char *argv[])
goto err; goto err;
} }
end: end:
if (maria_commit(file))
goto err;
if (maria_close(file)) if (maria_close(file))
{
file= 0;
goto err; goto err;
}
file= 0;
maria_panic(HA_PANIC_CLOSE); /* Should close log */ maria_panic(HA_PANIC_CLOSE); /* Should close log */
if (!silent) if (!silent)
{ {
...@@ -933,7 +941,11 @@ reads: %10lu\n", ...@@ -933,7 +941,11 @@ reads: %10lu\n",
err: err:
printf("got error: %d when using MARIA-database\n",my_errno); printf("got error: %d when using MARIA-database\n",my_errno);
if (file) if (file)
{
if (maria_commit(file))
goto err;
VOID(maria_close(file)); VOID(maria_close(file));
}
maria_end(); maria_end();
return(1); return(1);
} /* main */ } /* main */
......
...@@ -143,6 +143,10 @@ run_repair_tests() ...@@ -143,6 +143,10 @@ run_repair_tests()
$maria_path/maria_chk$suffix -se test2 $maria_path/maria_chk$suffix -se test2
$maria_path/maria_chk$suffix -s --parallel-recover --quick test2 $maria_path/maria_chk$suffix -s --parallel-recover --quick test2
$maria_path/maria_chk$suffix -se test2 $maria_path/maria_chk$suffix -se test2
$maria_path/ma_test2$suffix $silent -c $row_type
$maria_path/maria_chk$suffix -se test2
$maria_path/maria_chk$suffix -sr test2
$maria_path/maria_chk$suffix -se test2
} }
run_pack_tests() run_pack_tests()
......
#!/bin/sh
set -e set -e
silent="-s" silent="-s"
if [ -z "$maria_path" ] if [ -z "$maria_path" ]
...@@ -5,6 +7,13 @@ then ...@@ -5,6 +7,13 @@ then
maria_path="." maria_path="."
fi fi
tmp=$maria_path/tmp
if test '!' -d $tmp
then
mkdir $tmp
fi
echo "MARIA RECOVERY TESTS - success is if exit code is 0" echo "MARIA RECOVERY TESTS - success is if exit code is 0"
# runs a program inserting/deleting rows, then moves the resulting table # runs a program inserting/deleting rows, then moves the resulting table
...@@ -12,30 +21,44 @@ echo "MARIA RECOVERY TESTS - success is if exit code is 0" ...@@ -12,30 +21,44 @@ echo "MARIA RECOVERY TESTS - success is if exit code is 0"
# identical to the saved original. # identical to the saved original.
# Does not test the index file as we don't have logging for it yet. # Does not test the index file as we don't have logging for it yet.
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" for prog in "$maria_path/ma_test1 $silent -M -T -c" "$maria_path/ma_test2 $silent -L -K -W -P -M -T -c" "$maria_path/ma_test2 $silent -M -T -c -b"
do do
rm -f maria_log* rm -f maria_log.* maria_log_control
echo "TEST WITH $prog" echo "TEST WITH $prog"
$prog $prog
# derive table's name from program's name # derive table's name from program's name
table=`echo $prog | sed -e 's;.*ma_\(test[0-9]\).*;\1;' ` table=`echo $prog | sed -e 's;.*ma_\(test[0-9]\).*;\1;' `
$maria_path/maria_chk -dvv $table > maria_chk_message.good.txt 2>&1 $maria_path/maria_chk -dvv $table > $tmp/maria_chk_message.good.txt 2>&1
mv -f $table.MAD $table.MAD.good checksum=`$maria_path/maria_chk -dss $table`
mv -f $table.MAD $tmp/$table.MAD.good
rm $table.MAI rm $table.MAI
echo "applying log" echo "applying log"
$maria_path/maria_read_log -a > maria_read_log_$table.txt $maria_path/maria_read_log -a > $tmp/maria_read_log_$table.txt
cmp $table.MAD $table.MAD.good $maria_path/maria_chk -dvv $table > $tmp/maria_chk_message.txt 2>&1
$maria_path/maria_chk -dvv $table > maria_chk_message.txt 2>&1
cmp $table.MAD $tmp/$table.MAD.good
# 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
# When "recovery of the table's state" is ready, we can test it like this: # 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 # diff $tmp/maria_chk_message.good.txt $tmp/maria_chk_message.txt > $tmp/maria_chk_diff.txt || true
# if [ -s maria_chk_diff.txt ] # if [ -s $tmp/maria_chk_diff.txt ]
# then # then
# echo "Differences in maria_chk -dvv, recovery not yet perfect !" # echo "Differences in maria_chk -dvv, recovery not yet perfect !"
# echo "========DIFF START=======" # echo "========DIFF START======="
# cat maria_chk_diff.txt # cat $tmp/maria_chk_diff.txt
# echo "========DIFF END=======" # echo "========DIFF END======="
# fi # 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 done
echo "ALL RECOVERY TESTS OK" echo "ALL RECOVERY TESTS OK"
...@@ -115,7 +115,7 @@ int main(int argc, char **argv) ...@@ -115,7 +115,7 @@ int main(int argc, char **argv)
(!(check_param.testflag & (T_REP | T_REP_BY_SORT | T_SORT_RECORDS | (!(check_param.testflag & (T_REP | T_REP_BY_SORT | T_SORT_RECORDS |
T_SORT_INDEX)))) T_SORT_INDEX))))
{ {
uint old_testflag=check_param.testflag; ulonglong old_testflag=check_param.testflag;
if (!(check_param.testflag & T_REP)) if (!(check_param.testflag & T_REP))
check_param.testflag|= T_REP_BY_SORT; check_param.testflag|= T_REP_BY_SORT;
check_param.testflag&= ~T_EXTEND; /* Don't needed */ check_param.testflag&= ~T_EXTEND; /* Don't needed */
...@@ -126,7 +126,8 @@ int main(int argc, char **argv) ...@@ -126,7 +126,8 @@ int main(int argc, char **argv)
} }
else else
error|=new_error; 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"); puts("\n---------\n");
VOID(fflush(stdout)); VOID(fflush(stdout));
...@@ -1034,7 +1035,7 @@ static int maria_chk(HA_CHECK *param, char *filename) ...@@ -1034,7 +1035,7 @@ static int maria_chk(HA_CHECK *param, char *filename)
that it will have to find and store it. that it will have to find and store it.
*/ */
if (share->base.born_transactional) if (share->base.born_transactional)
share->state.create_rename_lsn= (LSN)ULONGLONG_MAX; share->state.create_rename_lsn= LSN_REPAIRED_BY_MARIA_CHK;
if ((param->testflag & (T_REP_BY_SORT | T_REP_PARALLEL)) && if ((param->testflag & (T_REP_BY_SORT | T_REP_PARALLEL)) &&
(maria_is_any_key_active(share->state.key_map) || (maria_is_any_key_active(share->state.key_map) ||
(rep_quick && !param->keys_in_use && !recreate)) && (rep_quick && !param->keys_in_use && !recreate)) &&
...@@ -1236,6 +1237,16 @@ static void descript(HA_CHECK *param, register MARIA_HA *info, char *name) ...@@ -1236,6 +1237,16 @@ static void descript(HA_CHECK *param, register MARIA_HA *info, char *name)
char llbuff[22],llbuff2[22]; char llbuff[22],llbuff2[22];
DBUG_ENTER("describe"); 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("\nMARIA file: %s\n",name);
printf("Record format: %s\n", record_formats[share->data_file_type]); printf("Record format: %s\n", record_formats[share->data_file_type]);
printf("Character set: %s (%d)\n", printf("Character set: %s (%d)\n",
......
...@@ -894,6 +894,7 @@ void _ma_restore_status(void *param); ...@@ -894,6 +894,7 @@ void _ma_restore_status(void *param);
void _ma_copy_status(void *to, void *from); void _ma_copy_status(void *to, void *from);
my_bool _ma_check_status(void *param); my_bool _ma_check_status(void *param);
void _ma_reset_status(MARIA_HA *maria); void _ma_reset_status(MARIA_HA *maria);
#include "ma_commit.h"
extern MARIA_HA *_ma_test_if_reopen(char *filename); extern MARIA_HA *_ma_test_if_reopen(char *filename);
my_bool _ma_check_table_is_closed(const char *name, const char *where); my_bool _ma_check_table_is_closed(const char *name, const char *where);
......
...@@ -51,7 +51,7 @@ int main(int argc, char **argv) ...@@ -51,7 +51,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(FALSE)) if (ma_control_file_create_or_open())
{ {
fprintf(stderr, "Can't open control file (%d)\n", errno); fprintf(stderr, "Can't open control file (%d)\n", errno);
goto err; goto err;
...@@ -93,7 +93,8 @@ int main(int argc, char **argv) ...@@ -93,7 +93,8 @@ int main(int argc, char **argv)
*/ */
fprintf(stdout, "TRACE of the last maria_read_log\n"); fprintf(stdout, "TRACE of the last maria_read_log\n");
if (maria_apply_log(lsn, opt_display_and_apply, stdout)) /* Until we have UNDO records, no UNDO phase */
if (maria_apply_log(lsn, opt_display_and_apply, stdout, FALSE))
goto err; goto err;
fprintf(stdout, "%s: SUCCESS\n", my_progname); fprintf(stdout, "%s: SUCCESS\n", my_progname);
...@@ -113,6 +114,8 @@ int main(int argc, char **argv) ...@@ -113,6 +114,8 @@ int main(int argc, char **argv)
static struct my_option my_long_options[] = 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", {"only-display", 'o', "display brief info about records's header",
(uchar **) &opt_only_display, (uchar **) &opt_only_display, 0, GET_BOOL, (uchar **) &opt_only_display, (uchar **) &opt_only_display, 0, GET_BOOL,
NO_ARG,0, 0, 0, 0, 0, 0}, NO_ARG,0, 0, 0, 0, 0, 0},
...@@ -161,6 +164,9 @@ get_one_option(int optid __attribute__((unused)), ...@@ -161,6 +164,9 @@ get_one_option(int optid __attribute__((unused)),
char *argument __attribute__((unused))) char *argument __attribute__((unused)))
{ {
switch (optid) { switch (optid) {
case '?':
usage();
exit(0);
#ifndef DBUG_OFF #ifndef DBUG_OFF
case '#': case '#':
DBUG_SET_INITIAL(argument ? argument : default_dbug_option); DBUG_SET_INITIAL(argument ? argument : default_dbug_option);
......
...@@ -18,6 +18,7 @@ ...@@ -18,6 +18,7 @@
#include <my_sys.h> #include <my_sys.h>
#include <m_string.h> #include <m_string.h>
#include "trnman.h" #include "trnman.h"
#include "ma_control_file.h"
/* /*
status variables: status variables:
...@@ -708,3 +709,29 @@ my_bool trnman_collect_transactions(LEX_STRING *str_act, LEX_STRING *str_com, ...@@ -708,3 +709,29 @@ my_bool trnman_collect_transactions(LEX_STRING *str_act, LEX_STRING *str_com,
pthread_mutex_unlock(&LOCK_trn_list); pthread_mutex_unlock(&LOCK_trn_list);
DBUG_RETURN(error); DBUG_RETURN(error);
} }
TRN *trnman_recreate_trn_from_recovery(uint16 shortid, TrID longid)
{
TrID old_trid_generator= global_trid_generator;
TRN *trn;
DBUG_ASSERT(maria_in_recovery && !maria_multi_threaded);
if (unlikely((trn= trnman_new_trn(NULL, NULL, NULL)) == NULL))
return NULL;
/* deallocate excessive allocations of trnman_new_trn() */
global_trid_generator= old_trid_generator;
set_if_bigger(global_trid_generator, longid);
short_trid_to_active_trn[trn->short_id]= 0;
DBUG_ASSERT(short_trid_to_active_trn[shortid] == NULL);
short_trid_to_active_trn[shortid]= trn;
trn->trid= longid;
trn->short_id= shortid;
return trn;
}
TRN *trnman_get_any_trn()
{
TRN *trn= active_list_min.next;
return (trn != &active_list_max) ? trn : NULL;
}
...@@ -53,6 +53,8 @@ uint trnman_increment_locked_tables(TRN *trn); ...@@ -53,6 +53,8 @@ uint trnman_increment_locked_tables(TRN *trn);
uint trnman_decrement_locked_tables(TRN *trn); uint trnman_decrement_locked_tables(TRN *trn);
my_bool trnman_has_locked_tables(TRN *trn); my_bool trnman_has_locked_tables(TRN *trn);
void trnman_reset_locked_tables(TRN *trn); void trnman_reset_locked_tables(TRN *trn);
TRN *trnman_recreate_trn_from_recovery(uint16 shortid, TrID longid);
TRN *trnman_get_any_trn();
C_MODE_END C_MODE_END
#endif #endif
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment