diff options
Diffstat (limited to 'storage/maria/ma_locking.c')
-rw-r--r-- | storage/maria/ma_locking.c | 103 |
1 files changed, 79 insertions, 24 deletions
diff --git a/storage/maria/ma_locking.c b/storage/maria/ma_locking.c index 8d2d3c0ad6e..9bab4cdfe0e 100644 --- a/storage/maria/ma_locking.c +++ b/storage/maria/ma_locking.c @@ -80,9 +80,8 @@ int maria_lock_database(MARIA_HA *info, int lock_type) { if (end_io_cache(&info->rec_cache)) { - error=my_errno; - maria_print_error(info->s, HA_ERR_CRASHED); - maria_mark_crashed(info); + error= my_errno; + _ma_set_fatal_error(share, error); } } if (!count) @@ -104,7 +103,7 @@ int maria_lock_database(MARIA_HA *info, int lock_type) mysql_rwlock_unlock(&share->mmap_lock); } #endif -#ifdef EXTERNAL_LOCKING +#ifdef MARIA_EXTERNAL_LOCKING share->state.process= share->last_process=share->this_process; share->state.unique= info->last_unique= info->this_unique; share->state.update_count= info->last_loop= ++info->this_loop; @@ -129,10 +128,7 @@ int maria_lock_database(MARIA_HA *info, int lock_type) else share->not_flushed=1; if (error) - { - maria_print_error(info->s, HA_ERR_CRASHED); - maria_mark_crashed(info); - } + _ma_set_fatal_error(share, error); } } info->opt_flag&= ~(READ_CACHE_USED | WRITE_CACHE_USED); @@ -307,7 +303,7 @@ int _ma_writeinfo(register MARIA_HA *info, uint operation) { /* Two threads can't be here */ olderror= my_errno; /* Remember last error */ -#ifdef EXTERNAL_LOCKING +#ifdef MARIA_EXTERNAL_LOCKING /* The following only makes sense if we want to be allow two different processes access the same table at the same time @@ -345,7 +341,7 @@ int _ma_writeinfo(register MARIA_HA *info, uint operation) int _ma_test_if_changed(register MARIA_HA *info) { -#ifdef EXTERNAL_LOCKING +#ifdef MARIA_EXTERNAL_LOCKING MARIA_SHARE *share= info->s; if (share->state.process != share->last_process || share->state.unique != info->last_unique || @@ -390,12 +386,39 @@ int _ma_test_if_changed(register MARIA_HA *info) #define _MA_ALREADY_MARKED_FILE_CHANGED \ ((share->state.changed & STATE_CHANGED) && share->global_changed) -int _ma_mark_file_changed(MARIA_HA *info) +int _ma_mark_file_changed(register MARIA_SHARE *share) +{ + if (!share->base.born_transactional) + { + if (!_MA_ALREADY_MARKED_FILE_CHANGED) + return _ma_mark_file_changed_now(share); + } + else + { + /* + For transactional tables, the table is marked changed when the first page + is written. Here we just mark the state to be updated so that caller + can do 'anaylze table' and find that is has changed before any pages + are written. + */ + if (! test_all_bits(share->state.changed, + (STATE_CHANGED | STATE_NOT_ANALYZED | + STATE_NOT_OPTIMIZED_KEYS))) + { + mysql_mutex_lock(&share->intern_lock); + share->state.changed|=(STATE_CHANGED | STATE_NOT_ANALYZED | + STATE_NOT_OPTIMIZED_KEYS); + mysql_mutex_unlock(&share->intern_lock); + } + } + return 0; +} + +int _ma_mark_file_changed_now(register MARIA_SHARE *share) { uchar buff[3]; - register MARIA_SHARE *share= info->s; int error= 1; - DBUG_ENTER("_ma_mark_file_changed"); + DBUG_ENTER("_ma_mark_file_changed_now"); if (_MA_ALREADY_MARKED_FILE_CHANGED) DBUG_RETURN(0); @@ -406,7 +429,7 @@ int _ma_mark_file_changed(MARIA_HA *info) STATE_NOT_OPTIMIZED_KEYS); if (!share->global_changed) { - share->global_changed=1; + share->changed= share->global_changed= 1; share->state.open_count++; } /* @@ -434,7 +457,7 @@ int _ma_mark_file_changed(MARIA_HA *info) !(share->state.changed & STATE_NOT_MOVABLE)) { /* Lock table to current installation */ - if (_ma_set_uuid(info, 0) || + if (_ma_set_uuid(share, 0) || (share->state.create_rename_lsn == LSN_NEEDS_NEW_STATE_LSNS && _ma_update_state_lsns_sub(share, LSN_IMPOSSIBLE, trnman_get_min_trid(), @@ -476,22 +499,31 @@ my_bool _ma_check_if_zero(uchar *pos, size_t length) call. In these context the following code should be safe! */ -int _ma_decrement_open_count(MARIA_HA *info) +int _ma_decrement_open_count(MARIA_HA *info, my_bool lock_tables) { uchar buff[2]; register MARIA_SHARE *share= info->s; int lock_error=0,write_error=0; + DBUG_ENTER("_ma_decrement_open_count"); + if (share->global_changed) { uint old_lock=info->lock_type; share->global_changed=0; - lock_error= my_disable_locking ? 0 : maria_lock_database(info, F_WRLCK); + lock_error= (my_disable_locking || ! lock_tables ? 0 : + maria_lock_database(info, F_WRLCK)); /* Its not fatal even if we couldn't get the lock ! */ if (share->state.open_count > 0) { share->state.open_count--; share->changed= 1; /* We have to update state */ - if (!share->temporary) + /* + For temporary tables that will just be deleted, we don't have + to decrement state. For transactional tables the state will be + updated in maria_close(). + */ + + if (!share->temporary && !share->now_transactional) { mi_int2store(buff,share->state.open_count); write_error= (int) my_pwrite(share->kfile.file, buff, sizeof(buff), @@ -500,10 +532,10 @@ int _ma_decrement_open_count(MARIA_HA *info) MYF(MY_NABP)); } } - if (!lock_error && !my_disable_locking) + if (!lock_error && !my_disable_locking && lock_tables) lock_error=maria_lock_database(info,old_lock); } - return test(lock_error || write_error); + DBUG_RETURN(test(lock_error || write_error)); } @@ -528,17 +560,40 @@ void _ma_mark_file_crashed(MARIA_SHARE *share) DBUG_VOID_RETURN; } +/* + Handle a fatal error + + - Mark the table as crashed + - Print an error message, if we had not issued an error message before + that the table had been crashed. + - set my_errno to error + - If 'maria_assert_if_crashed_table is set, then assert. +*/ + +void _ma_set_fatal_error(MARIA_SHARE *share, int error) +{ + DBUG_PRINT("error", ("error: %d", error)); + maria_mark_crashed_share(share); + if (!(share->state.changed & STATE_CRASHED_PRINTED)) + { + share->state.changed|= STATE_CRASHED_PRINTED; + maria_print_error(share, error); + } + my_errno= error; + DBUG_ASSERT(!maria_assert_if_crashed_table); +} + /** @brief Set uuid of for a Maria file @fn _ma_set_uuid() - @param info Maria handler + @param share Maria share @param reset_uuid Instead of setting file to maria_uuid, set it to 0 to mark it as movable */ -my_bool _ma_set_uuid(MARIA_HA *info, my_bool reset_uuid) +my_bool _ma_set_uuid(MARIA_SHARE *share, my_bool reset_uuid) { uchar buff[MY_UUID_SIZE], *uuid; @@ -548,7 +603,7 @@ my_bool _ma_set_uuid(MARIA_HA *info, my_bool reset_uuid) bzero(buff, sizeof(buff)); uuid= buff; } - return (my_bool) my_pwrite(info->s->kfile.file, uuid, MY_UUID_SIZE, - mi_uint2korr(info->s->state.header.base_pos), + return (my_bool) my_pwrite(share->kfile.file, uuid, MY_UUID_SIZE, + mi_uint2korr(share->state.header.base_pos), MYF(MY_NABP)); } |