diff options
author | unknown <bell@desktop.sanja.is.com.ua> | 2007-08-13 22:54:29 +0300 |
---|---|---|
committer | unknown <bell@desktop.sanja.is.com.ua> | 2007-08-13 22:54:29 +0300 |
commit | 4cf6756eb0f29618646e2eadbd62804d81ff6a79 (patch) | |
tree | 4b5edc3771ab3f311a2bcb4094379f7d4e1d222e /storage | |
parent | fddf505081ac6984bbf8f7b1fd7a4bbc890ad35a (diff) | |
download | mariadb-git-4cf6756eb0f29618646e2eadbd62804d81ff6a79.tar.gz |
First LSN calls added for transaction log.
storage/maria/ma_checkpoint.c:
Definitions of LSN should be collected in
the one file (ma_loghandler_lsn.h)
storage/maria/ma_loghandler.c:
New calls to get first theoretical and first real LSN.
storage/maria/ma_loghandler.h:
New calls to get first theoretical and first real LSN.
storage/maria/ma_loghandler_lsn.h:
Defined yet another impossible LSN to indicate error.
storage/maria/ma_recovery.c:
The first LSN call changed.
storage/maria/maria_read_log.c:
The first LSN call changed.
storage/maria/unittest/Makefile.am:
New unittest added.
storage/maria/unittest/ma_test_loghandler_first_lsn-t.c:
New BitKeeper file ``storage/maria/unittest/ma_test_loghandler_first_lsn-t.c''
Diffstat (limited to 'storage')
-rw-r--r-- | storage/maria/ma_checkpoint.c | 2 | ||||
-rw-r--r-- | storage/maria/ma_loghandler.c | 120 | ||||
-rw-r--r-- | storage/maria/ma_loghandler.h | 3 | ||||
-rw-r--r-- | storage/maria/ma_loghandler_lsn.h | 2 | ||||
-rw-r--r-- | storage/maria/ma_recovery.c | 14 | ||||
-rw-r--r-- | storage/maria/maria_read_log.c | 7 | ||||
-rw-r--r-- | storage/maria/unittest/Makefile.am | 4 | ||||
-rw-r--r-- | storage/maria/unittest/ma_test_loghandler_first_lsn-t.c | 150 |
8 files changed, 294 insertions, 8 deletions
diff --git a/storage/maria/ma_checkpoint.c b/storage/maria/ma_checkpoint.c index b23d077897f..42b6c961b41 100644 --- a/storage/maria/ma_checkpoint.c +++ b/storage/maria/ma_checkpoint.c @@ -38,8 +38,8 @@ #include "transaction.h" #include "share.h" #include "log.h" +#include "ma_loghandler_lsn.h" -#define LSN_IMPOSSIBLE ((LSN)0) /* could also be called LSN_ERROR */ #define LSN_MAX ((LSN)ULONGLONG_MAX) /* diff --git a/storage/maria/ma_loghandler.c b/storage/maria/ma_loghandler.c index 22c49d61c91..1bd6d803064 100644 --- a/storage/maria/ma_loghandler.c +++ b/storage/maria/ma_loghandler.c @@ -5977,12 +5977,126 @@ void translog_deassign_id_from_share(MARIA_SHARE *share) /** + @brief check if such log file exists + + @param file_no number of the file to test + + @retval 0 no such file + @retval 1 there is file with such number +*/ + +my_bool translog_is_file(uint file_no) +{ + MY_STAT stat_buff; + char path[FN_REFLEN]; + return (test(my_stat(translog_filename_by_fileno(file_no, path), + &stat_buff, MYF(MY_WME)))); +} + + +/** @brief returns the LSN of the first record starting in this log - @note so far works only for the very first log created on this system + @retval LSN_ERROR Error + @retval LSN_IMPOSSIBLE no log + @retval # LSN of the first record */ -LSN first_lsn_in_log() +LSN translog_first_lsn_in_log() { - return MAKE_LSN(1, TRANSLOG_PAGE_SIZE + log_descriptor.page_overhead); + TRANSLOG_ADDRESS addr, horizon= translog_get_horizon(); + TRANSLOG_VALIDATOR_DATA data; + uint min_file= 1, max_file= LSN_FILE_NO(horizon); + uint chunk_type; + uint16 chunk_offset; + uchar *page; + TRANSLOG_SCANNER_DATA scanner; + DBUG_ENTER("translog_first_lsn_in_log"); + DBUG_PRINT("info", ("Horizon: (%lu,0x%lx)", + LSN_FILE_NO(addr), LSN_OFFSET(addr))); + + if (addr == MAKE_LSN(1, TRANSLOG_PAGE_SIZE)) + { + /* there is no first page yet */ + DBUG_RETURN(LSN_IMPOSSIBLE); + } + + + /*TODO: lock loghandler purger when it will be created */ + /* binary search for last file */ + while (min_file != max_file && min_file != (max_file - 1)) + { + uint test= (min_file + max_file) / 2; + DBUG_PRINT("info", ("min_file: %u test: %u max_file: %u", + min_file, test, max_file)); + if (test == max_file) + test--; + if (translog_is_file(test)) + max_file= test; + else + min_file= test; + } + + addr= MAKE_LSN(max_file, TRANSLOG_PAGE_SIZE); /* the first page of the file */ + data.addr= &addr; + if ((page= translog_get_page(&data, scanner.buffer)) == NULL || + (chunk_offset= translog_get_first_chunk_offset(page)) == 0) + DBUG_RETURN(LSN_ERROR); + addr+= chunk_offset; + if (addr == horizon) + DBUG_RETURN(LSN_IMPOSSIBLE); + translog_init_scanner(addr, 0, &scanner); + + chunk_type= scanner.page[scanner.page_offset] & TRANSLOG_CHUNK_TYPE; + DBUG_PRINT("info", ("type: %x byte: %x", (uint) chunk_type, + (uint) scanner.page[scanner.page_offset])); + while (chunk_type != TRANSLOG_CHUNK_LSN && + chunk_type != TRANSLOG_CHUNK_FIXED && + scanner.page[scanner.page_offset] != 0) + { + if (translog_get_next_chunk(&scanner)) + DBUG_RETURN(LSN_ERROR); + chunk_type= scanner.page[scanner.page_offset] & TRANSLOG_CHUNK_TYPE; + DBUG_PRINT("info", ("type: %x byte: %x", (uint) chunk_type, + (uint) scanner.page[scanner.page_offset])); + } + if (scanner.page[scanner.page_offset] == 0) + DBUG_RETURN(LSN_IMPOSSIBLE); /* reached page filler */ + DBUG_RETURN(scanner.page_addr + scanner.page_offset); +} + + +/** + @brief returns theoretical first LSN if first log is present + + @retval LSN_ERROR Error + @retval LSN_IMPOSSIBLE no log + @retval # LSN of the first record +*/ + +LSN translog_first_theoretical_lsn() +{ + TRANSLOG_ADDRESS addr= translog_get_horizon(); + uchar buffer[TRANSLOG_PAGE_SIZE], *page; + TRANSLOG_VALIDATOR_DATA data; + DBUG_ENTER("translog_first_theoretical_lsn"); + DBUG_PRINT("info", ("Horizon: (%lu,0x%lx)", + LSN_FILE_NO(addr), LSN_OFFSET(addr))); + + if (!translog_is_file(1)) + DBUG_RETURN(LSN_IMPOSSIBLE); + if (addr == MAKE_LSN(1, TRANSLOG_PAGE_SIZE)) + { + /* there is no first page yet */ + DBUG_RETURN(MAKE_LSN(1, TRANSLOG_PAGE_SIZE + + log_descriptor.page_overhead)); + } + + addr= MAKE_LSN(1, TRANSLOG_PAGE_SIZE); /* the first page of the file */ + data.addr= &addr; + if ((page= translog_get_page(&data, buffer)) == NULL) + DBUG_RETURN(LSN_ERROR); + + DBUG_RETURN(MAKE_LSN(1, TRANSLOG_PAGE_SIZE + + page_overhead[page[TRANSLOG_PAGE_FLAGS]])); } diff --git a/storage/maria/ma_loghandler.h b/storage/maria/ma_loghandler.h index db3d43e39f4..4bc4ed1fff9 100644 --- a/storage/maria/ma_loghandler.h +++ b/storage/maria/ma_loghandler.h @@ -266,7 +266,8 @@ extern my_bool translog_inited; #define SHARE_ID_MAX 65535 /* array's size */ -extern LSN first_lsn_in_log(); +extern LSN translog_first_lsn_in_log(); +extern LSN translog_first_theoretical_lsn(); /* record parts descriptor */ struct st_translog_parts diff --git a/storage/maria/ma_loghandler_lsn.h b/storage/maria/ma_loghandler_lsn.h index 9e1c4632fb0..df41ceec7c8 100644 --- a/storage/maria/ma_loghandler_lsn.h +++ b/storage/maria/ma_loghandler_lsn.h @@ -81,6 +81,8 @@ typedef LSN LSN_WITH_FLAGS; #define FILENO_IMPOSSIBLE 0 /**< log file's numbering starts at 1 */ #define LOG_OFFSET_IMPOSSIBLE 0 /**< log always has a header */ #define LSN_IMPOSSIBLE 0 +/* following LSN also is impossible */ +#define LSN_ERROR 1 /** @brief the maximum valid LSN. diff --git a/storage/maria/ma_recovery.c b/storage/maria/ma_recovery.c index 6ed47533fef..5ad8115be46 100644 --- a/storage/maria/ma_recovery.c +++ b/storage/maria/ma_recovery.c @@ -96,7 +96,19 @@ int maria_recover() maria_in_recovery= TRUE; if (last_checkpoint_lsn == LSN_IMPOSSIBLE) - from_lsn= first_lsn_in_log(); + { + from_lsn= translog_first_theoretical_lsn(); + /* + as far as we have not yet any checkpoint then the very first + log file should be present. + */ + DBUG_ASSERT(from_lsn != LSN_IMPOSSIBLE); + /* + @todo process eroror of getting checkpoint + if (from_lsn == ERROR_LSN) + ... + */ + } else { DBUG_ASSERT(0); /* not yet implemented */ diff --git a/storage/maria/maria_read_log.c b/storage/maria/maria_read_log.c index c594fe20490..7c344d5f25d 100644 --- a/storage/maria/maria_read_log.c +++ b/storage/maria/maria_read_log.c @@ -85,7 +85,12 @@ int main(int argc, char **argv) if (opt_only_display) printf("You are using --only-display, NOTHING will be written to disk\n"); - lsn= first_lsn_in_log(); /* LSN could be also --start-from-lsn=# */ + /* LSN could be also --start-from-lsn=# */ + lsn= translog_first_theoretical_lsn(); + /* + @todo process LSN_IMPOSSIBLE and LSN_ERROR values of + translog_first_theoretical_lsn() + */ fprintf(stdout, "TRACE of the last maria_read_log\n"); if (maria_apply_log(lsn, opt_display_and_apply, stdout)) diff --git a/storage/maria/unittest/Makefile.am b/storage/maria/unittest/Makefile.am index 2110a7a5d04..d544ecadb7f 100644 --- a/storage/maria/unittest/Makefile.am +++ b/storage/maria/unittest/Makefile.am @@ -43,7 +43,8 @@ noinst_PROGRAMS = ma_control_file-t trnman-t lockman2-t \ ma_test_loghandler_multithread-t \ ma_test_loghandler_pagecache-t \ ma_test_loghandler_long-t-big \ - ma_test_loghandler_noflush-t + ma_test_loghandler_noflush-t \ + ma_test_loghandler_first_lsn-t ma_test_loghandler_t_SOURCES = ma_test_loghandler-t.c ma_maria_log_cleanup.c ma_test_loghandler_multigroup_t_SOURCES = ma_test_loghandler_multigroup-t.c ma_maria_log_cleanup.c @@ -52,6 +53,7 @@ ma_test_loghandler_pagecache_t_SOURCES = ma_test_loghandler_pagecache-t.c ma_mar ma_test_loghandler_long_t_big_SOURCES = ma_test_loghandler-t.c ma_maria_log_cleanup.c ma_test_loghandler_long_t_big_CPPFLAGS = -DLONG_LOG_TEST ma_test_loghandler_noflush_t_SOURCES = ma_test_loghandler_noflush-t.c ma_maria_log_cleanup.c +ma_test_loghandler_first_lsn_t_SOURCES = ma_test_loghandler_first_lsn-t.c ma_maria_log_cleanup.c ma_pagecache_single_src = ma_pagecache_single.c test_file.c ma_pagecache_consist_src = ma_pagecache_consist.c test_file.c diff --git a/storage/maria/unittest/ma_test_loghandler_first_lsn-t.c b/storage/maria/unittest/ma_test_loghandler_first_lsn-t.c new file mode 100644 index 00000000000..6f9354ec94b --- /dev/null +++ b/storage/maria/unittest/ma_test_loghandler_first_lsn-t.c @@ -0,0 +1,150 @@ +#include "../maria_def.h" +#include <stdio.h> +#include <errno.h> +#include <tap.h> +#include "../trnman.h" + +extern my_bool maria_log_remove(); + +#ifndef DBUG_OFF +static const char *default_dbug_option; +#endif + +#define PCACHE_SIZE (1024*1024*10) +#define PCACHE_PAGE TRANSLOG_PAGE_SIZE +#define LOG_FILE_SIZE (1024L*1024L*1024L + 1024L*1024L*512) +#define LOG_FLAGS 0 + +static char *first_translog_file= (char*)"maria_log.00000001"; + +int main(int argc __attribute__((unused)), char *argv[]) +{ + uint pagen; + uchar long_tr_id[6]; + PAGECACHE pagecache; + LSN lsn, first_lsn, theor_lsn; + MY_STAT st; + LEX_STRING parts[TRANSLOG_INTERNAL_PARTS + 1]; + + MY_INIT(argv[0]); + + plan(2); + + bzero(&pagecache, sizeof(pagecache)); + maria_data_root= "."; + if (maria_log_remove()) + exit(1); + /* be sure that we have no logs in the directory*/ + if (my_stat(CONTROL_FILE_BASE_NAME, &st, MYF(0))) + my_delete(CONTROL_FILE_BASE_NAME, MYF(0)); + if (my_stat(first_translog_file, &st, MYF(0))) + my_delete(first_translog_file, MYF(0)); + + bzero(long_tr_id, 6); +#ifndef DBUG_OFF +#if defined(__WIN__) + default_dbug_option= "d:t:i:O,\\ma_test_loghandler.trace"; +#else + default_dbug_option= "d:t:i:o,/tmp/ma_test_loghandler.trace"; +#endif + if (argc > 1) + { + DBUG_SET(default_dbug_option); + DBUG_SET_INITIAL(default_dbug_option); + } +#endif + + if (ma_control_file_create_or_open(TRUE)) + { + fprintf(stderr, "Can't init control file (%d)\n", errno); + exit(1); + } + if ((pagen= init_pagecache(&pagecache, PCACHE_SIZE, 0, 0, + PCACHE_PAGE)) == 0) + { + fprintf(stderr, "Got error: init_pagecache() (errno: %d)\n", errno); + exit(1); + } + if (translog_init(".", LOG_FILE_SIZE, 50112, 0, &pagecache, LOG_FLAGS)) + { + fprintf(stderr, "Can't init loghandler (%d)\n", errno); + translog_destroy(); + exit(1); + } + example_loghandler_init(); + + theor_lsn= translog_first_theoretical_lsn(); + if (theor_lsn == 1) + { + fprintf(stderr, "Error reading the first log file."); + translog_destroy(); + exit(1); + } + if (theor_lsn == LSN_IMPOSSIBLE) + { + fprintf(stderr, "There is no first log file."); + translog_destroy(); + exit(1); + } + first_lsn= translog_first_lsn_in_log(); + if (first_lsn != LSN_IMPOSSIBLE) + { + fprintf(stderr, "Incorrect first lsn responce (%lu,0x%lx).", + (ulong) LSN_FILE_NO(first_lsn), + (ulong) LSN_OFFSET(first_lsn)); + translog_destroy(); + exit(1); + } + ok(1, "Empty log response"); + + + int4store(long_tr_id, 0); + parts[TRANSLOG_INTERNAL_PARTS + 0].str= (char*)long_tr_id; + parts[TRANSLOG_INTERNAL_PARTS + 0].length= 6; + if (translog_write_record(&lsn, + LOGREC_FIXED_RECORD_0LSN_EXAMPLE, + &dummy_transaction_object, NULL, 6, + TRANSLOG_INTERNAL_PARTS + 1, + parts, NULL)) + { + fprintf(stderr, "Can't write record #%lu\n", (ulong) 0); + translog_destroy(); + exit(1); + } + + theor_lsn= translog_first_theoretical_lsn(); + if (theor_lsn == 1) + { + fprintf(stderr, "Error reading the first log file\n"); + translog_destroy(); + exit(1); + } + if (theor_lsn == LSN_IMPOSSIBLE) + { + fprintf(stderr, "There is no first log file\n"); + translog_destroy(); + exit(1); + } + first_lsn= translog_first_lsn_in_log(); + if (first_lsn != theor_lsn) + { + fprintf(stderr, "Incorrect first lsn: (%lu,0x%lx) " + " theoretical first: (%lu,0x%lx)\n", + (ulong) LSN_FILE_NO(first_lsn), + (ulong) LSN_OFFSET(first_lsn), + (ulong) LSN_FILE_NO(theor_lsn), + (ulong) LSN_OFFSET(theor_lsn)); + translog_destroy(); + exit(1); + } + + ok(1, "Full log response"); + + translog_destroy(); + end_pagecache(&pagecache, 1); + ma_control_file_end(); + my_delete(CONTROL_FILE_BASE_NAME, MYF(0)); + my_delete(first_translog_file, MYF(0)); + + exit(0); +} |