diff options
author | unknown <guilhem@gbichot3.local> | 2007-06-26 22:30:09 +0200 |
---|---|---|
committer | unknown <guilhem@gbichot3.local> | 2007-06-26 22:30:09 +0200 |
commit | 1e73169a82f86fa2fdaf43e7601705eb9a81cb85 (patch) | |
tree | 5a964e73ff7445d109428aa4193dcb014ca94fb4 | |
parent | 79672e8c44804fd9b877f51c6e9e054d90ed3d04 (diff) | |
download | mariadb-git-1e73169a82f86fa2fdaf43e7601705eb9a81cb85.tar.gz |
WL#3072 - Maria recovery
fixes for build failures; copyrights; small bugfixes and comments
mysys/Makefile.am:
missing .h breaks building from tarball
storage/maria/ma_loghandler.c:
applying Serg's bugfix of trnman_new_trid() to translog_assign_id_to_share()
storage/maria/ma_loghandler.h:
copyright
storage/maria/ma_loghandler_lsn.h:
copyright
storage/maria/maria_read_log.c:
fix for compiler warnings. Comments.
Close tables when program ends.
-rw-r--r-- | mysys/Makefile.am | 2 | ||||
-rw-r--r-- | storage/maria/ma_loghandler.c | 35 | ||||
-rw-r--r-- | storage/maria/ma_loghandler.h | 18 | ||||
-rw-r--r-- | storage/maria/ma_loghandler_lsn.h | 15 | ||||
-rw-r--r-- | storage/maria/maria_read_log.c | 66 |
5 files changed, 106 insertions, 30 deletions
diff --git a/mysys/Makefile.am b/mysys/Makefile.am index cd84e09a60e..60aa59fd3eb 100644 --- a/mysys/Makefile.am +++ b/mysys/Makefile.am @@ -20,7 +20,7 @@ INCLUDES = @ZLIB_INCLUDES@ -I$(top_builddir)/include \ -I$(top_srcdir)/include -I$(srcdir) pkglib_LIBRARIES = libmysys.a LDADD = libmysys.a $(top_builddir)/strings/libmystrings.a $(top_builddir)/dbug/libdbug.a -noinst_HEADERS = mysys_priv.h my_static.h +noinst_HEADERS = mysys_priv.h my_static.h my_safehash.h libmysys_a_SOURCES = my_init.c my_getwd.c mf_getdate.c my_mmap.c \ mf_path.c mf_loadpath.c my_file.c \ my_open.c my_create.c my_dup.c my_seek.c my_read.c \ diff --git a/storage/maria/ma_loghandler.c b/storage/maria/ma_loghandler.c index 6f238ef4055..79bf44046b1 100644 --- a/storage/maria/ma_loghandler.c +++ b/storage/maria/ma_loghandler.c @@ -177,7 +177,6 @@ my_bool translog_inited= 0; #include <my_atomic.h> /* an array that maps id of a MARIA_SHARE to this MARIA_SHARE */ static MARIA_SHARE **id_to_share= NULL; -#define SHARE_ID_MAX 65535 /* array's size */ /* lock for id_to_share */ static my_atomic_rwlock_t LOCK_id_to_share; @@ -2282,8 +2281,8 @@ my_bool translog_init(const char *directory, structures for generating 2-byte ids: */ my_atomic_rwlock_init(&LOCK_id_to_share); - id_to_share= (MARIA_SHARE **) my_malloc(SHARE_ID_MAX*sizeof(MARIA_SHARE*), - MYF(MY_WME|MY_ZEROFILL)); + id_to_share= (MARIA_SHARE **) my_malloc(SHARE_ID_MAX * sizeof(MARIA_SHARE*), + MYF(MY_WME | MY_ZEROFILL)); if (unlikely(!id_to_share)) DBUG_RETURN(1); id_to_share--; /* min id is 1 */ @@ -5682,21 +5681,23 @@ int translog_assign_id_to_share(MARIA_SHARE *share, TRN *trn) if (likely(share->id == 0)) { /* Inspired by set_short_trid() of trnman.c */ - int i= share->kfile.file % SHARE_ID_MAX + 1; - my_atomic_rwlock_wrlock(&LOCK_id_to_share); - /** - @todo RECOVERY BUG: if all slots are used, and we're using rwlocks - above, we will never exit the loop. To be discussed with Serg. - */ - for ( ; ; i= i % SHARE_ID_MAX + 1) /* the range is [1..SHARE_ID_MAX] */ + uint i= share->kfile.file % SHARE_ID_MAX + 1; + do { - void *tmp= NULL; - if (id_to_share[i] == NULL && - my_atomic_casptr((void **)&id_to_share[i], &tmp, share)) - break; - } - my_atomic_rwlock_wrunlock(&LOCK_id_to_share); - share->id= (uint16)i; + my_atomic_rwlock_wrlock(&LOCK_id_to_share); + for ( ; i <= SHARE_ID_MAX ; i++) /* the range is [1..SHARE_ID_MAX] */ + { + void *tmp= NULL; + if (id_to_share[i] == NULL && + my_atomic_casptr((void **)&id_to_share[i], &tmp, share)) + { + share->id= (uint16)i; + break; + } + } + my_atomic_rwlock_wrunlock(&LOCK_id_to_share); + i= 1; /* scan the whole array */ + } while (share->id == 0); DBUG_PRINT("info", ("id_to_share: 0x%lx -> %u", (ulong)share, i)); LSN lsn; LEX_STRING log_array[TRANSLOG_INTERNAL_PARTS + 2]; diff --git a/storage/maria/ma_loghandler.h b/storage/maria/ma_loghandler.h index 22b8cca3a08..f2bfd2c9d7e 100644 --- a/storage/maria/ma_loghandler.h +++ b/storage/maria/ma_loghandler.h @@ -1,4 +1,17 @@ -// TODO copyright +/* Copyright (C) 2007 MySQL AB & Sanja Belkin + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; version 2 of the License. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #ifndef _ma_loghandler_h #define _ma_loghandler_h @@ -251,6 +264,9 @@ extern my_bool translog_inited; all the rest added because of recovery; should we make ma_loghandler_for_recovery.h ? */ + +#define SHARE_ID_MAX 65535 /* array's size */ + extern LSN first_lsn_in_log(); /* record parts descriptor */ diff --git a/storage/maria/ma_loghandler_lsn.h b/storage/maria/ma_loghandler_lsn.h index af7594e3b00..34cb7616b74 100644 --- a/storage/maria/ma_loghandler_lsn.h +++ b/storage/maria/ma_loghandler_lsn.h @@ -1,3 +1,18 @@ +/* Copyright (C) 2007 MySQL AB & Sanja Belkin + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; version 2 of the License. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ + #ifndef _ma_loghandler_lsn_h #define _ma_loghandler_lsn_h diff --git a/storage/maria/maria_read_log.c b/storage/maria/maria_read_log.c index e654b8ea2ac..c8263495fbc 100644 --- a/storage/maria/maria_read_log.c +++ b/storage/maria/maria_read_log.c @@ -48,7 +48,9 @@ static int display_and_apply_record(const LOG_DESC *log_desc, #define prototype_exec_hook(R) \ static int exec_LOGREC_ ## R(const TRANSLOG_HEADER_BUFFER *rec) prototype_exec_hook(LONG_TRANSACTION_ID); +#ifdef MARIA_CHECKPOINT prototype_exec_hook(CHECKPOINT); +#endif prototype_exec_hook(REDO_CREATE_TABLE); prototype_exec_hook(FILE_ID); prototype_exec_hook(REDO_INSERT_ROW_HEAD); @@ -128,7 +130,9 @@ int main(int argc, char **argv) log_record_type_descriptor[LOGREC_ ## R].record_execute_in_redo_phase= \ exec_LOGREC_ ## R; install_exec_hook(LONG_TRANSACTION_ID); +#ifdef MARIA_CHECKPOINT install_exec_hook(CHECKPOINT); +#endif install_exec_hook(REDO_CREATE_TABLE); install_exec_hook(FILE_ID); install_exec_hook(REDO_INSERT_ROW_HEAD); @@ -337,10 +341,11 @@ static void display_record_position(const LOG_DESC *log_desc, if number==0, we're going over records which we had already seen and which form a group, so we indent below the group's end record */ - printf("%sRecord #%u LSN (%lu,0x%lx) short_trid %u %s(num_type:%u)\n", + printf("%sRec#%u LSN (%lu,0x%lx) short_trid %u %s(num_type:%u) len %lu\n", number ? "" : " ", number, (ulong) LSN_FILE_NO(rec->lsn), (ulong) LSN_OFFSET(rec->lsn), - rec->short_trid, log_desc->name, rec->type); + rec->short_trid, log_desc->name, rec->type, + (ulong)rec->record_length); } @@ -367,6 +372,7 @@ prototype_exec_hook(LONG_TRANSACTION_ID) TrID long_trid= all_active_trans[sid].long_trid; /* abort group of this trn (must be of before a crash) */ LSN gslsn= all_active_trans[sid].group_start_lsn; + char llbuf[22]; if (gslsn != LSN_IMPOSSIBLE) { printf("Group at LSN (%lu,0x%lx) short_trid %u aborted\n", @@ -378,16 +384,18 @@ prototype_exec_hook(LONG_TRANSACTION_ID) LSN ulsn= all_active_trans[sid].undo_lsn; if (ulsn != LSN_IMPOSSIBLE) { - fprintf(stderr, "Found an old transaction long_trid %llu short_trid %u" + llstr(long_trid, llbuf); + fprintf(stderr, "Found an old transaction long_trid %s short_trid %u" " with same short id as this new transaction, and has neither" - " committed nor rollback (undo_lsn: (%lu,0x%lx))\n", long_trid, + " committed nor rollback (undo_lsn: (%lu,0x%lx))\n", llbuf, sid, (ulong) LSN_FILE_NO(ulsn), (ulong) LSN_OFFSET(ulsn)); goto err; } } long_trid= uint6korr(rec->header); all_active_trans[sid].long_trid= long_trid; - printf("Transaction long_trid %lu short_trid %u starts\n", long_trid, sid); + llstr(long_trid, llbuf); + printf("Transaction long_trid %s short_trid %u starts\n", llbuf, sid); goto end; err: DBUG_ASSERT(0); @@ -396,11 +404,14 @@ end: return 0; } + +#ifdef MARIA_CHECKPOINT prototype_exec_hook(CHECKPOINT) { /* the only checkpoint we care about was found via control file, ignore */ return 0; } +#endif prototype_exec_hook(REDO_CREATE_TABLE) @@ -600,9 +611,11 @@ prototype_exec_hook(REDO_INSERT_ROW_HEAD) uint16 sid; ulonglong page; MARIA_HA *info; + char llbuf[22]; sid= fileid_korr(rec->header); page= page_korr(rec->header + FILEID_STORE_SIZE); - printf("For page %llu of table of short id %u", page, sid); + llstr(page, llbuf); + printf("For page %s of table of short id %u", llbuf, sid); info= all_tables[sid]; if (info == NULL) { @@ -623,6 +636,16 @@ prototype_exec_hook(REDO_INSERT_ROW_HEAD) assume we have made no checkpoint). */ printf(", applying record\n"); + /* + If REDO's LSN is > page's LSN (read from disk), we are going to modify the + page and change its LSN. The normal runtime code stores the UNDO's LSN + into the page; but here storing the REDO's LSN (rec->lsn) is more + straightforward and should not cause any problem (we are not writing to + the log here, so don't have to "flush up to UNDO's LSN"). + If the UNDO's LSN is desired, it can be found, as we saw the UNDO record + before deciding to execute this REDO; UNDO's LSN could simply be stored in + all_trans[rec->short_trid].group_end_lsn for this. + */ DBUG_ASSERT("Monty" == "this is the place"); end: /* as we don't have apply working: */ @@ -635,14 +658,15 @@ prototype_exec_hook(COMMIT) uint16 sid= rec->short_trid; TrID long_trid= all_active_trans[sid].long_trid; LSN gslsn= all_active_trans[sid].group_start_lsn; - + char llbuf[22]; if (long_trid == 0) { printf("We don't know about transaction short_trid %u;" "it probably committed long ago, forget it\n", sid); return 0; } - printf("Transaction long_trid %lu short_trid %u committed", long_trid, sid); + llstr(long_trid, llbuf); + printf("Transaction long_trid %s short_trid %u committed", llbuf, sid); if (gslsn != LSN_IMPOSSIBLE) { /* @@ -671,7 +695,7 @@ prototype_exec_hook(COMMIT) /* Just to inform about any aborted groups or unfinished transactions */ static void end_of_redo_phase() { - uint sid; + uint sid, unfinished= 0; for (sid= 0; sid <= SHORT_TRID_MAX; sid++) { TrID long_trid= all_active_trans[sid].long_trid; @@ -679,8 +703,12 @@ static void end_of_redo_phase() if (long_trid == 0) continue; if (all_active_trans[sid].undo_lsn != LSN_IMPOSSIBLE) - printf("Transaction long_trid %lu short_trid %u unfinished\n", - long_trid, sid); + { + char llbuf[22]; + llstr(long_trid, llbuf); + printf("Transaction long_trid %s short_trid %u unfinished\n", + llbuf, sid); + } if (gslsn != LSN_IMPOSSIBLE) { printf("Group at LSN (%lu,0x%lx) short_trid %u aborted\n", @@ -694,4 +722,20 @@ static void end_of_redo_phase() */ #endif } + /* + We don't close tables if there are some unfinished transactions, because + closing tables normally requires that all unfinished transactions on them + be rolled back. + For example, closing will soon write the state to disk and when doing that + it will think this is a committed state, but it may not be. + */ + if (unfinished == 0) + { + for (sid= 0; sid <= SHORT_TRID_MAX; sid++) + { + MARIA_HA *info= all_tables[sid]; + if (info != NULL) + maria_close(info); + } + } } |