diff options
author | Michael Widenius <monty@askmonty.org> | 2010-11-02 17:22:57 +0200 |
---|---|---|
committer | Michael Widenius <monty@askmonty.org> | 2010-11-02 17:22:57 +0200 |
commit | 20acfbf30da2eca66f9e5d602d50ac18e38272b8 (patch) | |
tree | fb1ae595de49f155045afa021b4037b07305096c /storage | |
parent | c6b19ea001965b350df1248c33f709127d2c7e47 (diff) | |
download | mariadb-git-20acfbf30da2eca66f9e5d602d50ac18e38272b8.tar.gz |
Fix for: LP #634955: Assert in _ma_update_at_original_place()
Added locking of lock mutex when updating status in external_unlock() for Aria and MyISAM tables.
Fixed that 'source' command doesn't cause mysql command line tool to exit on error.
DEBUG_EXECUTE() and DEBUG_EVALUATE_IF() should not execute things based on wildcards. (Allows one to run --debug with mysql-test-run scripts that uses @debug)
Fixed several core dump, deadlock and crashed table bugs in handling of LOCK TABLE with MERGE tables:
- Added priority of locks to avoid crashes with MERGE tables.
- Added thr_lock_merge() to allow one to merge two results of thr_lock().
Fixed 'not found row' bug in REPLACE with Aria tables.
Mark MyISAM tables that are part of MERGE with HA_OPEN_MERGE_TABLE and set the locks to have priority THR_LOCK_MERGE_PRIV.
- By sorting MERGE tables last in thr_multi_unlock() it's safer to release and relock them many times (can happen when TRIGGERS are created)
Avoid printing (null) in debug file (to easier find out wrong NULL pointer usage with %s).
client/mysql.cc:
Fixed that 'source' command doesn't cause mysql command line tool to exit on error.
client/mysqltest.cc:
Don't send NULL to fn_format(). (Can cause crash on Solaris when using --debug)
dbug/dbug.c:
DEBUG_EXECUTE() and DEBUG_EVALUATE_IF() should not execute things based on wildcards.
include/my_base.h:
Added flag to signal if one opens a MERGE table.
Added extra() command to signal that one is not part of a MERGE table anymore.
include/thr_lock.h:
Added priority for locks (needed to fix bug in thr_lock when using MERGE tables)
Added option to thr_unlock() if get_status() should be called.
Added prototype for thr_merge_locks().
mysql-test/mysql-test-run.pl:
Ignore crashed table warnings for tables named 'crashed'.
mysql-test/r/merge.result:
Renamed triggers to make debugging easier.
Added some CHECK TABLES to catch errors earlier.
Additional tests.
mysql-test/r/merge_debug.result:
Test of error handling when reopening MERGE tables.
mysql-test/r/udf_query_cache.result:
Added missing flush status
mysql-test/suite/parts/r/partition_repair_myisam.result:
Update results
mysql-test/t/merge.test:
Renamed triggers to make debugging easier.
Added some CHECK TABLES to catch errors earlier.
Additional tests.
mysql-test/t/merge_debug.test:
Test of error handling when reopening MERGE tables.
mysql-test/t/udf_query_cache.test:
Added missing flush status
mysys/my_getopt.c:
Removed not used variable
mysys/my_symlink2.c:
Changed (null) to (NULL) to make it easier to find NULL arguments to DBUG_PRINT() functions.
(On linux, NULL to sprintf is printed 'null')
mysys/thr_lock.c:
Added priority of locks to avoid crashes with MERGE tables.
Added thr_lock_merge() to allow one to merge two results of thr_lock().
- This is needed for MyISAM as all locked table must share the same status. If not, you will not see newly inserted rows in other instances of the table.
If calling thr_unlock() with THR_UNLOCK_UPDATE_STATUS, call update_status() and restore_status() for the locks. This is needed in some rare cases where we call thr_unlock() followed by thr_lock() without calling external_unlock/external_lock in between.
Simplify loop in thr_multi_lock().
Added 'start_trans', which is called at end of thr_multi_lock() when all locks are taken.
- This was needed by Aria to ensure that transaction is started when we got all locks, not at get_status(). Without this, some rows could not be visible when we lock two tables at the same time, causing REPLACE using two tables to fail unexpectedly.
sql/handler.cc:
Add an assert() in handler::print_error() for "impossible errors" (like table is crashed) when --debug-assert-if-crashed-table is used.
sql/lock.cc:
Simplify mysql_lock_tables() code if get_lock_data() returns 0 locks.
Added new parameter to thr_multi_unlock()
In mysql_unlock_read_tables(), call first externa_unlock(), then thr_multi_unlock(); This is same order as we do in mysql_unlock_tables().
Don't abort locks in mysql_lock_abort() for merged tables when a MERGE table is deleted; Would cause a spin lock.
Added call to thr_merge_locks() in mysql_lock_merge() to ensure consistency in thr_locks().
- New locks of same type and table is stored after the old lock to ensure that we get the status from the original lock.
sql/mysql_priv.h:
Added debug_assert_if_crashed_table
sql/mysqld.cc:
Added --debug-assert-if-crashed-table
sql/parse_file.cc:
Don't print '(null)' in DBUG_PRINT of no dir given
sql/set_var.cc:
Increase default size of buffer for @debug variable.
sql/sql_base.cc:
In case of error from reopen_table() in reopen_tables(), call unlock_open_table() and restart loop.
- This fixed bug when we twice deleted same table from open_cache.
Don't take name lock for already name locked table in open_unireg_entry().
- Fixed bug when doing repair in reopen_table().
- In detach_merge_children(), always detach if 'clear_refs' is given. We can't trust parent->children_attached as this function can be called twice, first time with clear_refs set to 0.
sql/sql_class.cc:
Changed printing of (null) to "" in set_thd_proc_info()
sql/sql_parse.cc:
Added DBUG
sql/sql_trigger.cc:
Don't call unlink_open_table() if reopen_table() fails as the table may already be freed.
storage/maria/ma_bitmap.c:
Fixed DBUG_ASSERT() in allocate_tail()
storage/maria/ma_blockrec.c:
Fixed wrong calculation of row length for very small rows in undo_row_update().
- Fixes ASSERT() when doing undo.
storage/maria/ma_blockrec.h:
Added _ma_block_start_trans() and _ma_block_start_trans_no_versioning()
storage/maria/ma_locking.c:
Call _ma_update_status_with_lock() when releasing write locks.
- Fixes potential problem with updating status without the proper lock.
storage/maria/ma_open.c:
Changed to use start_trans() instead of get_status() to ensure that we see all rows in all locked tables when we got the locks.
- Fixed 'not found row' bug in REPLACE with Aria tables.
storage/maria/ma_state.c:
Added _ma_update_status_with_lock() and _ma_block_start_trans().
This is to ensure that we see all rows in all locked tables when we got the locks.
storage/maria/ma_state.h:
Added _ma_update_status_with_lock()
storage/maria/ma_write.c:
More DBUG_PRINT
storage/myisam/mi_check.c:
Fixed error message
storage/myisam/mi_extra.c:
Added HA_EXTRA_DETACH_CHILD:
- Detach MyISAM table to not be part of MERGE table (remove flag & lock priority).
storage/myisam/mi_locking.c:
Call mi_update_status_with_lock() when releasing write locks.
- Fixes potential problem with updating status without the proper lock.
Change to use new HA_OPEN_MERGE_TABLE flag to test if MERGE table.
Added mi_fix_status(), called by thr_merge().
storage/myisam/mi_open.c:
Added marker if part of MERGE table.
Call mi_fix_status() in thr_lock() for transactional tables.
storage/myisam/myisamdef.h:
Change my_once_flag to uint, as it stored different values than just 0/1
Added 'open_flag' to store state given to mi_open()
storage/myisammrg/ha_myisammrg.cc:
Add THR_LOCK_MERGE_PRIV to THR_LOCK_DATA to get MERGE locks sorted after other types of locks.
storage/myisammrg/myrg_locking.c:
Remove windows specific code.
storage/myisammrg/myrg_open.c:
Use HA_OPEN_MERGE_TABLE to mi_open().
Set HA_OPEN_MERGE_TABLE for linked MyISAM tables.
storage/xtradb/buf/buf0buf.c:
Fixed compiler warning
storage/xtradb/buf/buf0lru.c:
Initialize variable that could be used not initialized.
Diffstat (limited to 'storage')
-rw-r--r-- | storage/maria/ma_bitmap.c | 6 | ||||
-rw-r--r-- | storage/maria/ma_blockrec.c | 5 | ||||
-rw-r--r-- | storage/maria/ma_blockrec.h | 3 | ||||
-rw-r--r-- | storage/maria/ma_locking.c | 2 | ||||
-rw-r--r-- | storage/maria/ma_open.c | 4 | ||||
-rw-r--r-- | storage/maria/ma_state.c | 58 | ||||
-rw-r--r-- | storage/maria/ma_state.h | 1 | ||||
-rw-r--r-- | storage/maria/ma_write.c | 7 | ||||
-rw-r--r-- | storage/myisam/mi_check.c | 2 | ||||
-rw-r--r-- | storage/myisam/mi_extra.c | 5 | ||||
-rw-r--r-- | storage/myisam/mi_locking.c | 66 | ||||
-rw-r--r-- | storage/myisam/mi_open.c | 4 | ||||
-rw-r--r-- | storage/myisam/myisamdef.h | 7 | ||||
-rw-r--r-- | storage/myisammrg/ha_myisammrg.cc | 4 | ||||
-rw-r--r-- | storage/myisammrg/myrg_locking.c | 11 | ||||
-rw-r--r-- | storage/myisammrg/myrg_open.c | 10 | ||||
-rw-r--r-- | storage/xtradb/buf/buf0buf.c | 2 | ||||
-rw-r--r-- | storage/xtradb/buf/buf0lru.c | 2 |
18 files changed, 144 insertions, 55 deletions
diff --git a/storage/maria/ma_bitmap.c b/storage/maria/ma_bitmap.c index d8b7a9b9a99..c96e0bd7a86 100644 --- a/storage/maria/ma_bitmap.c +++ b/storage/maria/ma_bitmap.c @@ -1016,7 +1016,11 @@ static my_bool allocate_tail(MARIA_FILE_BITMAP *bitmap, uint size, DBUG_PRINT("enter", ("size: %u", size)); LINT_INIT(best_pos); - DBUG_ASSERT(size <= MAX_TAIL_SIZE(bitmap->block_size)); + /* + We have to add DIR_ENTRY_SIZE here as this is not part of the data size + See call to allocate_tail() in find_tail(). + */ + DBUG_ASSERT(size <= MAX_TAIL_SIZE(bitmap->block_size) + DIR_ENTRY_SIZE); for (; data < end; data += 6) { diff --git a/storage/maria/ma_blockrec.c b/storage/maria/ma_blockrec.c index 92ec916a9d1..bc2b1d5187f 100644 --- a/storage/maria/ma_blockrec.c +++ b/storage/maria/ma_blockrec.c @@ -2823,6 +2823,10 @@ static my_bool write_block_record(MARIA_HA *info, data+= diff_length; head_length= share->base.min_block_length; } + /* + If this is a redo entry (ie, undo_lsn != LSN_ERROR) then we should have + written exactly head_length bytes (same as original record). + */ DBUG_ASSERT(undo_lsn == LSN_ERROR || head_length == row_pos->length); int2store(row_pos->dir + 2, head_length); /* update empty space at start of block */ @@ -7161,6 +7165,7 @@ my_bool _ma_apply_undo_row_update(MARIA_HA *info, LSN undo_lsn, header+= HA_CHECKSUM_STORE_SIZE; } length_on_head_page= uint2korr(header); + set_if_bigger(length_on_head_page, share->base.min_block_length); header+= 2; extent_count= pagerange_korr(header); header+= PAGERANGE_STORE_SIZE; diff --git a/storage/maria/ma_blockrec.h b/storage/maria/ma_blockrec.h index c39b0af73ad..d18b20aa387 100644 --- a/storage/maria/ma_blockrec.h +++ b/storage/maria/ma_blockrec.h @@ -281,7 +281,8 @@ my_bool write_hook_for_commit(enum translog_record_type type, TRN *trn, MARIA_HA *tbl_info, LSN *lsn, void *hook_arg); void _ma_block_get_status(void *param, my_bool concurrent_insert); -void _ma_block_get_status_no_versioning(void *param, my_bool concurrent_ins); +my_bool _ma_block_start_trans(void* param); +my_bool _ma_block_start_trans_no_versioning(void *param); void _ma_block_update_status(void *param); void _ma_block_restore_status(void *param); my_bool _ma_block_check_status(void *param); diff --git a/storage/maria/ma_locking.c b/storage/maria/ma_locking.c index b355d7bc792..6bb308e5959 100644 --- a/storage/maria/ma_locking.c +++ b/storage/maria/ma_locking.c @@ -63,7 +63,7 @@ int maria_lock_database(MARIA_HA *info, int lock_type) { count= --share->w_locks; if (share->lock.update_status) - (*share->lock.update_status)(info); + _ma_update_status_with_lock(info); } --share->tot_locks; if (info->lock_type == F_WRLCK && !share->w_locks) diff --git a/storage/maria/ma_open.c b/storage/maria/ma_open.c index 30d099d939a..63e1801a39a 100644 --- a/storage/maria/ma_open.c +++ b/storage/maria/ma_open.c @@ -874,8 +874,8 @@ MARIA_HA *maria_open(const char *name, int mode, uint open_flags) share->have_versioning= 1; share->row_is_visible= _ma_row_visible_transactional_table; share->lock.get_status= _ma_block_get_status; - share->lock.update_status= _ma_block_update_status; share->lock.check_status= _ma_block_check_status; + share->lock.start_trans= _ma_block_start_trans; /* We can for the moment only allow multiple concurrent inserts only if there is no auto-increment key. To lift this restriction @@ -903,7 +903,7 @@ MARIA_HA *maria_open(const char *name, int mode, uint open_flags) else if (share->now_transactional) { DBUG_ASSERT(share->data_file_type == BLOCK_RECORD); - share->lock.get_status= _ma_block_get_status_no_versioning; + share->lock.start_trans= _ma_block_start_trans_no_versioning; } } #endif diff --git a/storage/maria/ma_state.c b/storage/maria/ma_state.c index c7eee7d511d..ca94d58264b 100644 --- a/storage/maria/ma_state.c +++ b/storage/maria/ma_state.c @@ -335,6 +335,25 @@ void _ma_update_status(void* param) } +/* + Same as ma_update_status() but take a lock in the table lock, to protect + against someone calling ma_get_status() from thr_lock() at the same time. +*/ + +void _ma_update_status_with_lock(MARIA_HA *info) +{ + my_bool locked= 0; + if (info->state == &info->state_save) + { + locked= 1; + pthread_mutex_lock(&info->s->lock.mutex); + } + (*info->s->lock.update_status)(info); + if (locked) + pthread_mutex_unlock(&info->s->lock.mutex); +} + + void _ma_restore_status(void *param) { MARIA_HA *info= (MARIA_HA*) param; @@ -585,7 +604,13 @@ void _ma_block_get_status(void* param, my_bool concurrent_insert) { DBUG_ASSERT(info->lock.type != TL_WRITE_CONCURRENT_INSERT); } + DBUG_VOID_RETURN; +} + +my_bool _ma_block_start_trans(void* param) +{ + MARIA_HA *info=(MARIA_HA*) param; if (info->s->lock_key_trees) { /* @@ -593,24 +618,22 @@ void _ma_block_get_status(void* param, my_bool concurrent_insert) out of memory conditions) TODO: Fix this by having one extra state pre-allocated */ - (void) _ma_setup_live_state(info); + return _ma_setup_live_state(info); } - else + + /* + Info->trn is set if this table is already handled and we are + called from maria_versioning() + */ + if (info->s->base.born_transactional && !info->trn) { /* - Info->trn is set if this table is already handled and we are - called from maria_versioning() + Assume for now that this doesn't fail (It can only fail in + out of memory conditions) */ - if (info->s->base.born_transactional && !info->trn) - { - /* - Assume for now that this doesn't fail (It can only fail in - out of memory conditions) - */ - (void) maria_create_trn_hook(info); - } + return maria_create_trn_hook(info) != 0; } - DBUG_VOID_RETURN; + return 0; } @@ -639,13 +662,10 @@ my_bool _ma_block_check_status(void *param __attribute__((unused))) /* Get status when transactional but not versioned */ -void _ma_block_get_status_no_versioning(void* param, - my_bool concurrent_insert - __attribute__((unused))) +my_bool _ma_block_start_trans_no_versioning(void* param) { MARIA_HA *info=(MARIA_HA*) param; DBUG_ENTER("_ma_block_get_status_no_version"); - DBUG_PRINT("enter", ("concurrent_insert %d", concurrent_insert)); DBUG_ASSERT(info->s->base.born_transactional); info->state->changed= 0; /* from _ma_reset_update_flag() */ @@ -655,9 +675,9 @@ void _ma_block_get_status_no_versioning(void* param, Assume for now that this doesn't fail (It can only fail in out of memory conditions) */ - (void) maria_create_trn_hook(info); + DBUG_RETURN(maria_create_trn_hook(info)); } - DBUG_VOID_RETURN; + DBUG_RETURN(0); } diff --git a/storage/maria/ma_state.h b/storage/maria/ma_state.h index f3317f0084a..03ce5c2ea8c 100644 --- a/storage/maria/ma_state.h +++ b/storage/maria/ma_state.h @@ -62,6 +62,7 @@ MARIA_STATE_HISTORY *_ma_remove_not_visible_states(MARIA_STATE_HISTORY void _ma_reset_state(MARIA_HA *info); void _ma_get_status(void* param, my_bool concurrent_insert); void _ma_update_status(void* param); +void _ma_update_status_with_lock(MARIA_HA *info); void _ma_restore_status(void *param); void _ma_copy_status(void* to, void *from); void _ma_reset_update_flag(void *param, my_bool concurrent_insert); diff --git a/storage/maria/ma_write.c b/storage/maria/ma_write.c index 7ea73d17b9b..02eeec754ee 100644 --- a/storage/maria/ma_write.c +++ b/storage/maria/ma_write.c @@ -678,7 +678,6 @@ static int w_search(register MARIA_HA *info, uint32 comp_flag, MARIA_KEY *key, } else /* not HA_FULLTEXT, normal HA_NOSAME key */ { - DBUG_PRINT("warning", ("Duplicate key")); /* TODO When the index will support true versioning - with multiple @@ -696,6 +695,12 @@ static int w_search(register MARIA_HA *info, uint32 comp_flag, MARIA_KEY *key, info->dup_key_trid= _ma_trid_from_key(&tmp_key); info->dup_key_pos= dup_key_pos; my_errno= HA_ERR_FOUND_DUPP_KEY; + DBUG_PRINT("warning", + ("Duplicate key. dup_key_trid: %lu pos %lu visible: %d", + (ulong) info->dup_key_trid, + (ulong) info->dup_key_pos, + info->trn ? trnman_can_read_from(info->trn, + info->dup_key_trid) : 2)); goto err; } } diff --git a/storage/myisam/mi_check.c b/storage/myisam/mi_check.c index 7096c03cf7d..8f732db234c 100644 --- a/storage/myisam/mi_check.c +++ b/storage/myisam/mi_check.c @@ -1337,7 +1337,7 @@ int chk_data_link(HA_CHECK *param, MI_INFO *info, my_bool extend) if (splits != info->s->state.split) { mi_check_print_warning(param, - "Found %10s key parts. Should be: %s", + "Found %10s parts. Should be: %s", llstr(splits,llbuff), llstr(info->s->state.split,llbuff2)); } diff --git a/storage/myisam/mi_extra.c b/storage/myisam/mi_extra.c index 3b14e5eb98e..4c5a65f900f 100644 --- a/storage/myisam/mi_extra.c +++ b/storage/myisam/mi_extra.c @@ -390,6 +390,11 @@ int mi_extra(MI_INFO *info, enum ha_extra_function function, void *extra_arg) share->is_log_table= TRUE; pthread_mutex_unlock(&share->intern_lock); break; + case HA_EXTRA_DETACH_CHILD: /* When used with MERGE tables */ + info->open_flag&= ~HA_OPEN_MERGE_TABLE; + info->lock.priority&= ~THR_LOCK_MERGE_PRIV; + break; + case HA_EXTRA_KEY_CACHE: case HA_EXTRA_NO_KEY_CACHE: default: diff --git a/storage/myisam/mi_locking.c b/storage/myisam/mi_locking.c index 40a04293731..19ec8337539 100644 --- a/storage/myisam/mi_locking.c +++ b/storage/myisam/mi_locking.c @@ -22,6 +22,8 @@ #include "ftdefs.h" +static void mi_update_status_with_lock(MI_INFO *info); + /* lock table by F_UNLCK, F_RDLCK or F_WRLCK */ int mi_lock_database(MI_INFO *info, int lock_type) @@ -62,7 +64,7 @@ int mi_lock_database(MI_INFO *info, int lock_type) else { count= --share->w_locks; - mi_update_status(info); + mi_update_status_with_lock(info); } --share->tot_locks; if (info->lock_type == F_WRLCK && !share->w_locks && @@ -244,7 +246,7 @@ int mi_lock_database(MI_INFO *info, int lock_type) a crash on windows if the table is renamed and later on referenced by the merge table. */ - if( info->owned_by_merge && (info->s)->kfile < 0 ) + if ((info->open_flags & HA_OPEN_MERGE_TABLE) && (info->s)->kfile < 0) { error = HA_ERR_NO_SUCH_TABLE; } @@ -273,9 +275,11 @@ void mi_get_status(void* param, my_bool concurrent_insert) { MI_INFO *info=(MI_INFO*) param; DBUG_ENTER("mi_get_status"); - DBUG_PRINT("info",("key_file: %ld data_file: %ld concurrent_insert: %d", - (long) info->s->state.state.key_file_length, - (long) info->s->state.state.data_file_length, + DBUG_PRINT("info",("name: %s key_file: %lu data_file: %lu rows: %lu concurrent_insert: %d", + info->s->index_file_name, + (ulong) info->s->state.state.key_file_length, + (ulong) info->s->state.state.data_file_length, + (ulong) info->s->state.state.records, concurrent_insert)); #ifndef DBUG_OFF if (info->state->key_file_length > info->s->state.state.key_file_length || @@ -306,9 +310,11 @@ void mi_update_status(void* param) if (info->state == &info->save_state) { #ifndef DBUG_OFF - DBUG_PRINT("info",("updating status: key_file: %ld data_file: %ld", - (long) info->state->key_file_length, - (long) info->state->data_file_length)); + DBUG_PRINT("info", + ("updating status: key_file: %lu data_file: %lu rows: %lu", + (ulong) info->state->key_file_length, + (ulong) info->state->data_file_length, + (ulong) info->state->records)); if (info->state->key_file_length < info->s->state.state.key_file_length || info->state->data_file_length < info->s->state.state.data_file_length) DBUG_PRINT("warning",("old info: key_file: %ld data_file: %ld", @@ -342,6 +348,24 @@ void mi_update_status(void* param) DBUG_VOID_RETURN; } +/* + Same as mi_update_status() but take a lock in the table lock, to protect + against someone calling mi_get_status() from thr_lock() at the same time. +*/ + +static void mi_update_status_with_lock(MI_INFO *info) +{ + my_bool locked= 0; + if (info->state == &info->save_state) + { + locked= 1; + pthread_mutex_lock(&info->s->lock.mutex); + } + mi_update_status(info); + if (locked) + pthread_mutex_unlock(&info->s->lock.mutex); +} + void mi_restore_status(void *param) { @@ -407,6 +431,32 @@ my_bool mi_check_status(void *param) } +/** + Fix status for thr_lock_merge() + + @param org_table + @param new_table that should point on org_lock. new_table is 0 + in case this is the first occurence of the table in the lock + structure. +*/ + +void mi_fix_status(MI_INFO *org_table, MI_INFO *new_table) +{ + DBUG_ENTER("mi_fix_status"); + if (!new_table) + { + /* First in group. Set state as in mi_get_status() */ + org_table->state= &org_table->save_state; + } + else + { + /* Set new_table to use state from org_table (first lock of this table) */ + new_table->state= org_table->state; + } + DBUG_VOID_RETURN; +} + + /**************************************************************************** ** functions to read / write the state ****************************************************************************/ diff --git a/storage/myisam/mi_open.c b/storage/myisam/mi_open.c index e4240dec90c..9fc82846e91 100644 --- a/storage/myisam/mi_open.c +++ b/storage/myisam/mi_open.c @@ -119,7 +119,7 @@ MI_INFO *mi_open(const char *name, int mode, uint open_flags) dflt_key_cache); DBUG_EXECUTE_IF("myisam_pretend_crashed_table_on_open", - if (strstr(name, "/t1")) + if (strstr(name, "/crashed")) { my_errno= HA_ERR_CRASHED; goto err; @@ -556,6 +556,7 @@ MI_INFO *mi_open(const char *name, int mode, uint open_flags) share->lock.update_status=mi_update_status; share->lock.restore_status= mi_restore_status; share->lock.check_status=mi_check_status; + share->lock.fix_status= (void (*)(void *, void *)) mi_fix_status; } } #endif @@ -606,6 +607,7 @@ MI_INFO *mi_open(const char *name, int mode, uint open_flags) info.s=share; info.lastpos= HA_OFFSET_ERROR; info.update= (short) (HA_STATE_NEXT_FOUND+HA_STATE_PREV_FOUND); + info.open_flag= open_flags; info.opt_flag=READ_CHECK_USED; info.this_unique= (ulong) info.dfile; /* Uniq number in process */ if (share->data_file_type == COMPRESSED_RECORD) diff --git a/storage/myisam/myisamdef.h b/storage/myisam/myisamdef.h index 3262808803c..e03f88b1a1f 100644 --- a/storage/myisam/myisamdef.h +++ b/storage/myisam/myisamdef.h @@ -274,7 +274,9 @@ struct st_myisam_info */ ulong packed_length, blob_length; /* Length of found, packed record */ int dfile; /* The datafile */ + uint open_flag; /* Parameters for open */ uint opt_flag; /* Optim. for space/speed */ + uint once_flags; /* For MYISAMMRG */ uint update; /* If file changed since open */ int lastinx; /* Last used index */ uint lastkey_length; /* Length of key in lastkey */ @@ -300,10 +302,6 @@ struct st_myisam_info my_bool page_changed; /* If info->buff has to be reread for rnext */ my_bool buff_used; - my_bool once_flags; /* For MYISAMMRG */ -#ifdef __WIN__ - my_bool owned_by_merge; /* This MyISAM table is part of a merge union */ -#endif #ifdef THREAD THR_LOCK_DATA lock; #endif @@ -712,6 +710,7 @@ void mi_update_status(void *param); void mi_restore_status(void *param); void mi_copy_status(void *to, void *from); my_bool mi_check_status(void *param); +void mi_fix_status(MI_INFO *org_table, MI_INFO *new_table); void mi_disable_non_unique_index(MI_INFO *info, ha_rows rows); extern MI_INFO *test_if_reopen(char *filename); diff --git a/storage/myisammrg/ha_myisammrg.cc b/storage/myisammrg/ha_myisammrg.cc index 30be1d34e2a..99513e2267f 100644 --- a/storage/myisammrg/ha_myisammrg.cc +++ b/storage/myisammrg/ha_myisammrg.cc @@ -86,8 +86,6 @@ On parent open the storage engine structures are allocated and initialized. They stay with the open table until its final close. - - */ #ifdef USE_PRAGMA_IMPLEMENTATION @@ -1070,6 +1068,8 @@ THR_LOCK_DATA **ha_myisammrg::store_lock(THD *thd, open_table != file->end_table ; open_table++) { + open_table->table->lock.priority|= THR_LOCK_MERGE_PRIV; + *(to++)= &open_table->table->lock; if (lock_type != TL_IGNORE && open_table->table->lock.type == TL_UNLOCK) open_table->table->lock.type=lock_type; diff --git a/storage/myisammrg/myrg_locking.c b/storage/myisammrg/myrg_locking.c index 4f1e3f844a1..a414cee7bb8 100644 --- a/storage/myisammrg/myrg_locking.c +++ b/storage/myisammrg/myrg_locking.c @@ -27,15 +27,8 @@ int myrg_lock_database(MYRG_INFO *info, int lock_type) error=0; for (file=info->open_tables ; file != info->end_table ; file++) { -#ifdef __WIN__ - /* - Make sure this table is marked as owned by a merge table. - The semaphore is never released as long as table remains - in memory. This should be refactored into a more generic - approach (observer pattern) - */ - (file->table)->owned_by_merge = TRUE; -#endif + DBUG_ASSERT(file->table->open_flag & HA_OPEN_MERGE_TABLE); + if ((new_error=mi_lock_database(file->table,lock_type))) { error=new_error; diff --git a/storage/myisammrg/myrg_open.c b/storage/myisammrg/myrg_open.c index 17c9b4ba4d1..ba452854808 100644 --- a/storage/myisammrg/myrg_open.c +++ b/storage/myisammrg/myrg_open.c @@ -27,8 +27,9 @@ if handle_locking is 0 then exit with error if some table is locked if handle_locking is 1 then wait if table is locked - NOTE: This function is not used in the MySQL server. It is for - MERGE use independent from MySQL. Currently there is some code + NOTE: This function is only used in the MySQL server when a + table is cloned. It is also used for usage of MERGE + independent from MySQL. Currently there is some code duplication between myrg_open() and myrg_parent_open() + myrg_attach_children(). Please duplicate changes in these functions or make common sub-functions. @@ -93,7 +94,8 @@ MYRG_INFO *myrg_open(const char *name, int mode, int handle_locking) } else fn_format(buff, buff, "", "", 0); - if (!(isam=mi_open(buff,mode,(handle_locking?HA_OPEN_WAIT_IF_LOCKED:0)))) + if (!(isam=mi_open(buff,mode,(handle_locking?HA_OPEN_WAIT_IF_LOCKED:0) | + HA_OPEN_MERGE_TABLE))) { if (handle_locking & HA_OPEN_FOR_REPAIR) { @@ -430,6 +432,8 @@ int myrg_attach_children(MYRG_INFO *m_info, int handle_locking, m_info->open_tables[child_nr].table= myisam; m_info->open_tables[child_nr].file_offset= (my_off_t) file_offset; file_offset+= myisam->state->data_file_length; + /* Mark as MERGE table */ + myisam->open_flag|= HA_OPEN_MERGE_TABLE; /* Check table definition match. */ if (m_info->reclength != myisam->s->base.reclength) diff --git a/storage/xtradb/buf/buf0buf.c b/storage/xtradb/buf/buf0buf.c index 55ff207cf11..1c08bd6d0bf 100644 --- a/storage/xtradb/buf/buf0buf.c +++ b/storage/xtradb/buf/buf0buf.c @@ -1116,7 +1116,7 @@ init_again: if (shm_info->buf_pool_backup.LRU_old) shm_info->buf_pool_backup.LRU_old = (buf_page_t*)((byte*)(shm_info->buf_pool_backup.LRU_old) - + (((void*)shm_info->buf_pool_backup.LRU_old > previous_frame_address) + + (((byte*)shm_info->buf_pool_backup.LRU_old > previous_frame_address) ? logi_offset : blocks_offset)); UT_LIST_OFFSET(unzip_LRU, buf_block_t, shm_info->buf_pool_backup.unzip_LRU, diff --git a/storage/xtradb/buf/buf0lru.c b/storage/xtradb/buf/buf0lru.c index 79c7c0d3bbe..94828940fd4 100644 --- a/storage/xtradb/buf/buf0lru.c +++ b/storage/xtradb/buf/buf0lru.c @@ -2265,7 +2265,7 @@ buf_LRU_file_restore(void) ulint req = 0; ibool terminated = FALSE; ibool ret = FALSE; - dump_record_t* records; + dump_record_t* records= 0; ulint size; ulint size_high; ulint length; |