diff options
author | unknown <monty@mysql.com/narttu.mysql.fi> | 2007-09-03 12:05:17 +0300 |
---|---|---|
committer | unknown <monty@mysql.com/narttu.mysql.fi> | 2007-09-03 12:05:17 +0300 |
commit | 5183a4b00b0cadf74b9ed5c92734617ec3c9270b (patch) | |
tree | d34a2a57d2e6f1023cb9107320bc8028ed338a4a /storage/maria | |
parent | f5a8966ddeecda767ca1f3bb92f748670d837ef6 (diff) | |
download | mariadb-git-5183a4b00b0cadf74b9ed5c92734617ec3c9270b.tar.gz |
Fixed several bugs found by running *.test with maria engine
Renamed HA_EXTRA_PREAPRE_FOR_DELETE to HA_EXTRA_PERPARE_FOR_DROP
Added HA_EXTRA_PREPARE_FOR_RENAME (as we in the code before used HA_EXTRA_PREPARE_FOR_DELETE also for renames which confused things)
Allow multiple write locks for same page by same file handle
Don't write table state if table is not changed
include/my_base.h:
Renamed HA_EXTRA_PREAPRE_FOR_DELETE to HA_EXTRA_PERPARE_FOR_DROP
Added HA_EXTRA_PREPARE_FOR_RENAME (as we in the code before used HA_EXTRA_PREPARE_FOR_DELETE also for renames which confused things)
mysql-test/r/maria.result:
More tests of things that failed in other tests
mysql-test/t/maria.test:
More tests of things that failed in other tests
sql/ha_partition.cc:
HA_EXTRA_PREPARE_FOR_DELETE -> HA_EXTRA_PREPARE_FOR_DROP
Use HA_EXTRA_PREPARE_FOR_RENAME for renames
sql/ha_partition.h:
HA_EXTRA_PREPARE_FOR_DELETE -> HA_EXTRA_PREPARE_FOR_DROP
Use HA_EXTRA_PREPARE_FOR_RENAME for renames
sql/lock.cc:
Fixed comment
sql/sql_table.cc:
Fixed wrong usage of HA_EXTRA_PREAPRE_FOR_DELETE
storage/maria/ha_maria.cc:
Added missing _ma_renable_logging_for_table() (When using with ALTER TABLE + repair index)
Enabled fast generation of index
storage/maria/ma_bitmap.c:
Fixed bug when resetting full pages when page was a tail page
storage/maria/ma_blockrec.c:
Fixed several bugs found by running *.test with maria engine:
During update we keep old changed pages locked with a write lock to be able to reuse them.
- Fixed bug with allocated but not used tail part
- Fixed bug with blob that only had tail part
- Fixed bug when update reused a page (needed multiple write locks for same page)
- Fixed bug when first extent was a tail block
storage/maria/ma_check.c:
Better error message when bitmap is destroyed
storage/maria/ma_close.c:
Only write status if file was changed.
Fixed bug when maria_chk -e file_name changed the file.
storage/maria/ma_dynrec.c:
Removed not used argument to _ma_state_info_read_dsk
storage/maria/ma_extra.c:
HA_EXTRA_PREPARE_FOR_DELETE -> HA_EXTRA_PREPARE_FOR_DROP
Use HA_EXTRA_PREPARE_FOR_RENAME for renames
Only ignore flushing of pages for DROP (not rename)
storage/maria/ma_locking.c:
Removed not used argument to _ma_state_info_read_dsk
storage/maria/ma_open.c:
Removed not used argument to _ma_state_info_read_dsk
storage/maria/ma_pagecache.c:
Allow multiple write locks for same page by same file handle
(Not yet complete, Sanja will fix)
storage/maria/ma_recovery.c:
HA_EXTRA_PREPARE_FOR_DELETE -> HA_EXTRA_PREPARE_FOR_DROP
storage/maria/maria_def.h:
Removed not used argument to _ma_state_info_read_dsk
storage/myisam/mi_extra.c:
HA_EXTRA_PREPARE_FOR_DELETE -> HA_EXTRA_PREPARE_FOR_DROP
Use HA_EXTRA_PREPARE_FOR_RENAME for renames
Only ignore flushing of pages for DROP (not rename)
storage/myisammrg/ha_myisammrg.cc:
HA_EXTRA_PREPARE_FOR_DELETE -> HA_EXTRA_PREPARE_FOR_DROP
Use HA_EXTRA_PREPARE_FOR_RENAME for renames
Diffstat (limited to 'storage/maria')
-rw-r--r-- | storage/maria/ha_maria.cc | 14 | ||||
-rw-r--r-- | storage/maria/ma_bitmap.c | 20 | ||||
-rw-r--r-- | storage/maria/ma_blockrec.c | 96 | ||||
-rw-r--r-- | storage/maria/ma_check.c | 7 | ||||
-rw-r--r-- | storage/maria/ma_close.c | 3 | ||||
-rw-r--r-- | storage/maria/ma_dynrec.c | 2 | ||||
-rw-r--r-- | storage/maria/ma_extra.c | 7 | ||||
-rw-r--r-- | storage/maria/ma_locking.c | 6 | ||||
-rw-r--r-- | storage/maria/ma_open.c | 9 | ||||
-rwxr-xr-x | storage/maria/ma_pagecache.c | 59 | ||||
-rw-r--r-- | storage/maria/ma_recovery.c | 2 | ||||
-rw-r--r-- | storage/maria/maria_def.h | 3 |
12 files changed, 141 insertions, 87 deletions
diff --git a/storage/maria/ha_maria.cc b/storage/maria/ha_maria.cc index c2fa0ec14b1..55ce800d596 100644 --- a/storage/maria/ha_maria.cc +++ b/storage/maria/ha_maria.cc @@ -1324,7 +1324,10 @@ int ha_maria::repair(THD *thd, HA_CHECK ¶m, bool do_optimize) } thd->proc_info= old_proc_info; if (!thd->locked_tables) + { + _ma_reenable_logging_for_table(file->s); maria_lock_database(file, F_UNLCK); + } DBUG_RETURN(error ? HA_ADMIN_FAILED : !optimize_done ? HA_ADMIN_ALREADY_DONE : HA_ADMIN_OK); } @@ -1624,10 +1627,8 @@ void ha_maria::start_bulk_insert(ha_rows rows) if (!rows || (rows > MARIA_MIN_ROWS_TO_USE_WRITE_CACHE)) maria_extra(file, HA_EXTRA_WRITE_CACHE, (void*) &size); - can_enable_indexes= maria_is_all_keys_active(file->s->state.key_map, - file->s->base.keys); - /* TODO: Remove when we have repair() working */ - can_enable_indexes= 0; + can_enable_indexes= (maria_is_all_keys_active(file->s->state.key_map, + file->s->base.keys)); if (!(specialflag & SPECIAL_SAFE_MODE)) { @@ -1640,9 +1641,8 @@ void ha_maria::start_bulk_insert(ha_rows rows) if (file->state->records == 0 && can_enable_indexes && (!rows || rows >= MARIA_MIN_ROWS_TO_DISABLE_INDEXES)) maria_disable_non_unique_index(file, rows); - else - if (!file->bulk_insert && - (!rows || rows >= MARIA_MIN_ROWS_TO_USE_BULK_INSERT)) + else if (!file->bulk_insert && + (!rows || rows >= MARIA_MIN_ROWS_TO_USE_BULK_INSERT)) { maria_init_bulk_insert(file, thd->variables.bulk_insert_buff_size, rows); } diff --git a/storage/maria/ma_bitmap.c b/storage/maria/ma_bitmap.c index 66377172877..2a2308637b6 100644 --- a/storage/maria/ma_bitmap.c +++ b/storage/maria/ma_bitmap.c @@ -451,6 +451,10 @@ static void _ma_print_bitmap(MARIA_FILE_BITMAP *bitmap) fprintf(DBUG_FILE,"\nBitmap page changes at page %lu\n", (ulong) bitmap->page); + DBUG_ASSERT(memcmp(bitmap->map + bitmap->block_size - + sizeof(maria_bitmap_marker), + maria_bitmap_marker, sizeof(maria_bitmap_marker)) == 0); + page= (ulong) bitmap->page+1; for (pos= bitmap->map, org_pos= bitmap->map + bitmap->block_size ; pos < end ; @@ -536,14 +540,14 @@ static my_bool _ma_read_bitmap_page(MARIA_SHARE *share, } bitmap->used_size= bitmap->total_size; DBUG_ASSERT(share->pagecache->block_size == bitmap->block_size); - res= (pagecache_read(share->pagecache, + res= ((pagecache_read(share->pagecache, (PAGECACHE_FILE*)&bitmap->file, page, 0, (uchar*) bitmap->map, PAGECACHE_PLAIN_PAGE, - PAGECACHE_LOCK_LEFT_UNLOCKED, 0) == NULL) | - memcmp(bitmap->map + bitmap->block_size - - sizeof(maria_bitmap_marker), - maria_bitmap_marker, sizeof(maria_bitmap_marker)); + PAGECACHE_LOCK_LEFT_UNLOCKED, 0) == NULL) || + memcmp(bitmap->map + bitmap->block_size - + sizeof(maria_bitmap_marker), + maria_bitmap_marker, sizeof(maria_bitmap_marker))); #ifndef DBUG_OFF if (!res) memcpy(bitmap->map + bitmap->block_size, bitmap->map, bitmap->block_size); @@ -1838,11 +1842,15 @@ my_bool _ma_bitmap_release_unused(MARIA_HA *info, MARIA_BITMAP_BLOCKS *blocks) /* Handle all full pages and tail pages (for head page and blob) */ for (block++; block < end; block++) { + uint page_count; if (!block->page_count) continue; /* Skip 'filler blocks' */ + page_count= block->page_count; if (block->used & BLOCKUSED_TAIL) { + /* The bitmap page is only one page */ + page_count= 1; if (block->used & BLOCKUSED_USED) { DBUG_PRINT("info", ("tail empty_space: %u", block->empty_space)); @@ -1861,7 +1869,7 @@ my_bool _ma_bitmap_release_unused(MARIA_HA *info, MARIA_BITMAP_BLOCKS *blocks) } if (!(block->used & BLOCKUSED_USED) && _ma_reset_full_page_bits(info, bitmap, - block->page, block->page_count)) + block->page, page_count)) goto err; } pthread_mutex_unlock(&info->s->bitmap.bitmap_lock); diff --git a/storage/maria/ma_blockrec.c b/storage/maria/ma_blockrec.c index 555949dfa84..7f29f075463 100644 --- a/storage/maria/ma_blockrec.c +++ b/storage/maria/ma_blockrec.c @@ -288,8 +288,10 @@ typedef struct st_maria_extent_cursor uint extent_count; /* <> 0 if current extent is a tail page; Set while using cursor */ uint tail; + /* Position for tail on tail page */ + uint tail_row_nr; /* - <> 1 if we are working on the first extent (i.e., the one that is store in + == 1 if we are working on the first extent (i.e., the one that is stored in the row header, not an extent that is stored as part of the row data). */ my_bool first_extent; @@ -299,7 +301,7 @@ typedef struct st_maria_extent_cursor static my_bool delete_tails(MARIA_HA *info, MARIA_RECORD_POS *tails); static my_bool delete_head_or_tail(MARIA_HA *info, ulonglong page, uint record_number, - my_bool head); + my_bool head, my_bool from_update); static void _ma_print_directory(uchar *buff, uint block_size); static void compact_page(uchar *buff, uint block_size, uint rownr, my_bool extend_block); @@ -461,7 +463,7 @@ my_bool _ma_init_block_record(MARIA_HA *info) /* The following should be big enough for all purposes */ if (my_init_dynamic_array(&info->pinned_pages, sizeof(MARIA_PINNED_PAGE), - max(info->s->base.blobs + 2, + max(info->s->base.blobs*2 + 4, MARIA_MAX_TREE_LEVELS*2), 16)) goto err; row->base_length= new_row->base_length= info->s->base_length; @@ -840,6 +842,7 @@ static void calc_record_size(MARIA_HA *info, const uchar *record, MARIA_COLUMNDEF *column, *end_column; uint *null_field_lengths= row->null_field_lengths; ulong *blob_lengths= row->blob_lengths; + DBUG_ENTER("calc_record_size"); row->normal_length= row->char_length= row->varchar_length= row->blob_length= row->extents_count= 0; @@ -968,6 +971,9 @@ static void calc_record_size(MARIA_HA *info, const uchar *record, row->total_length= (row->head_length + row->blob_length); if (row->total_length < share->base.min_row_length) row->total_length= share->base.min_row_length; + DBUG_PRINT("exit", ("head_length: %lu total_length: %lu", + (ulong) row->head_length, (ulong) row->total_length)); + DBUG_VOID_RETURN; } @@ -1395,6 +1401,7 @@ static my_bool write_full_pages(MARIA_HA *info, DBUG_PRINT("enter", ("length: %lu page: %lu page_count: %lu", (ulong) length, (ulong) block->page, (ulong) block->page_count)); + DBUG_ASSERT((block->page_count & TAIL_BIT) == 0); info->keyread_buff_used= 1; page= block->page; @@ -1938,13 +1945,10 @@ static my_bool write_block_record(MARIA_HA *info, ulong length; ulong data_length= (tmp_data - info->rec_buff); -#ifdef MONTY_WILL_KNOW #ifdef SANITY_CHECKS - if (cur_block->sub_blocks == 1) + if (head_block->sub_blocks == 1) goto crashed; /* no reserved full or tails */ #endif -#endif - /* Find out where to write tail for non-blob fields. @@ -2073,6 +2077,11 @@ static my_bool write_block_record(MARIA_HA *info, length)) goto disk_err; tmp_data-= length; /* Remove the tail */ + if (tmp_data == info->rec_buff) + { + /* We have no full blocks to write for the head part */ + tmp_data_used= 0; + } /* Store the tail position for the non-blob fields */ if (head_tail_block == head_block + 1) @@ -2319,8 +2328,8 @@ static my_bool write_block_record(MARIA_HA *info, if (block[block->sub_blocks - 1].used & BLOCKUSED_TAIL) blob_length-= (blob_length % FULL_PAGE_SIZE(block_size)); - if (write_full_pages(info, info->trn->undo_lsn, block, - blob_pos, blob_length)) + if (blob_length && write_full_pages(info, info->trn->undo_lsn, block, + blob_pos, blob_length)) goto disk_err; block+= block->sub_blocks; } @@ -2356,8 +2365,11 @@ disk_err: @todo RECOVERY we should distinguish below between log write error and table write error. The former should stop Maria immediately, the latter should mark the table corrupted. - */ - /* Unpin all pinned pages to not cause problems for disk cache */ + */ + /* + Unpin all pinned pages to not cause problems for disk cache. This is + safe to call even if we already called _ma_unpin_all_pages() above. + */ _ma_unpin_all_pages(info, 0); DBUG_RETURN(1); @@ -2445,7 +2457,8 @@ my_bool _ma_write_abort_block_record(MARIA_HA *info) if (delete_head_or_tail(info, ma_recordpos_to_page(info->cur_row.lastpos), - ma_recordpos_to_dir_entry(info->cur_row.lastpos), 1)) + ma_recordpos_to_dir_entry(info->cur_row.lastpos), 1, + 0)) res= 1; for (block= blocks->block + 1, end= block + blocks->count - 1; block < end; block++) @@ -2457,7 +2470,7 @@ my_bool _ma_write_abort_block_record(MARIA_HA *info) write_block_record() */ if (delete_head_or_tail(info, block->page, block->page_count & ~TAIL_BIT, - 0)) + 0, 0)) res= 1; } else if (block->used & BLOCKUSED_USED) @@ -2533,7 +2546,6 @@ my_bool _ma_update_block_record(MARIA_HA *info, MARIA_RECORD_POS record_pos, ulonglong page; struct st_row_pos_info row_pos; MARIA_SHARE *share= info->s; - my_bool res; DBUG_ENTER("_ma_update_block_record"); DBUG_PRINT("enter", ("rowid: %lu", (long) record_pos)); @@ -2621,8 +2633,8 @@ my_bool _ma_update_block_record(MARIA_HA *info, MARIA_RECORD_POS record_pos, row_pos.dir= dir; row_pos.data= buff + uint2korr(dir); row_pos.length= head_length; - res= write_block_record(info, oldrec, record, new_row, blocks, 1, &row_pos); - DBUG_RETURN(res); + DBUG_RETURN(write_block_record(info, oldrec, record, new_row, blocks, 1, + &row_pos)); err: _ma_unpin_all_pages(info, 0); @@ -2710,6 +2722,9 @@ static int delete_dir_entry(uchar *buff, uint block_size, uint record_number, info Maria handler page Page (not file offset!) on which the row is head 1 if this is a head page + from_update 1 if we are called from update. In this case we + leave the page as write locked as we may put + the new row into the old position. NOTES Uses info->keyread_buff @@ -2721,7 +2736,7 @@ static int delete_dir_entry(uchar *buff, uint block_size, uint record_number, static my_bool delete_head_or_tail(MARIA_HA *info, ulonglong page, uint record_number, - my_bool head) + my_bool head, my_bool from_update) { MARIA_SHARE *share= info->s; uint empty_space; @@ -2730,6 +2745,7 @@ static my_bool delete_head_or_tail(MARIA_HA *info, LSN lsn; MARIA_PINNED_PAGE page_link; int res; + enum pagecache_page_lock lock_at_write, lock_at_unpin; DBUG_ENTER("delete_head_or_tail"); info->keyread_buff_used= 1; @@ -2743,6 +2759,17 @@ static my_bool delete_head_or_tail(MARIA_HA *info, page_link.unlock= PAGECACHE_LOCK_WRITE_UNLOCK; push_dynamic(&info->pinned_pages, (void*) &page_link); + if (from_update) + { + lock_at_write= PAGECACHE_LOCK_LEFT_WRITELOCKED; + lock_at_unpin= PAGECACHE_LOCK_WRITE_UNLOCK; + } + else + { + lock_at_write= PAGECACHE_LOCK_WRITE_TO_READ; + lock_at_unpin= PAGECACHE_LOCK_READ_UNLOCK; + } + res= delete_dir_entry(buff, block_size, record_number, &empty_space); if (res < 0) DBUG_RETURN(1); @@ -2769,7 +2796,7 @@ static my_bool delete_head_or_tail(MARIA_HA *info, if (pagecache_write(share->pagecache, &info->dfile, page, 0, buff, share->page_type, - PAGECACHE_LOCK_WRITE_TO_READ, + lock_at_write, PAGECACHE_PIN_LEFT_PINNED, PAGECACHE_WRITE_DELAY, &page_link.link)) DBUG_RETURN(1); @@ -2797,15 +2824,15 @@ static my_bool delete_head_or_tail(MARIA_HA *info, if (pagecache_write(share->pagecache, &info->dfile, page, 0, buff, share->page_type, - PAGECACHE_LOCK_WRITE_TO_READ, + lock_at_write, PAGECACHE_PIN_LEFT_PINNED, PAGECACHE_WRITE_DELAY, &page_link.link)) DBUG_RETURN(1); DBUG_ASSERT(empty_space >= info->s->bitmap.sizes[0]); } - /* Change the lock used when we read the page */ - page_link.unlock= PAGECACHE_LOCK_READ_UNLOCK; + /* The page is pinned with a read lock */ + page_link.unlock= lock_at_unpin; set_dynamic(&info->pinned_pages, (void*) &page_link, info->pinned_pages.elements-1); @@ -2838,7 +2865,7 @@ static my_bool delete_tails(MARIA_HA *info, MARIA_RECORD_POS *tails) { if (delete_head_or_tail(info, ma_recordpos_to_page(*tails), - ma_recordpos_to_dir_entry(*tails), 0)) + ma_recordpos_to_dir_entry(*tails), 0, 1)) res= 1; } DBUG_RETURN(res); @@ -2863,7 +2890,7 @@ my_bool _ma_delete_block_record(MARIA_HA *info, const uchar *record) page= ma_recordpos_to_page(info->cur_row.lastpos); record_number= ma_recordpos_to_dir_entry(info->cur_row.lastpos); - if (delete_head_or_tail(info, page, record_number, 1) || + if (delete_head_or_tail(info, page, record_number, 1, 0) || delete_tails(info, info->cur_row.tail_positions)) goto err; @@ -2987,8 +3014,14 @@ static void init_extent(MARIA_EXTENT_CURSOR *extent, uchar *extent_info, extent->extent_count= extents; extent->page= page_korr(extent_info); /* First extent */ page_count= uint2korr(extent_info + ROW_EXTENT_PAGE_SIZE); - extent->page_count= page_count & ~TAIL_BIT; extent->tail= page_count & TAIL_BIT; + if (extent->tail) + { + extent->page_count= 1; + extent->tail_row_nr= page_count & ~TAIL_BIT; + } + else + extent->page_count= page_count; extent->tail_positions= tail_positions; } @@ -3030,12 +3063,15 @@ static uchar *read_next_extent(MARIA_HA *info, MARIA_EXTENT_CURSOR *extent, if (!page_count) goto crashed; extent->tail= page_count & TAIL_BIT; - extent->page_count= (page_count & ~TAIL_BIT); - extent->first_extent= 0; + if (extent->tail) + extent->tail_row_nr= page_count & ~TAIL_BIT; + else + extent->page_count= page_count; DBUG_PRINT("info",("New extent. Page: %lu page_count: %u tail_flag: %d", (ulong) extent->page, extent->page_count, extent->tail != 0)); } + extent->first_extent= 0; DBUG_ASSERT(share->pagecache->block_size == share->block_size); if (!(buff= pagecache_read(share->pagecache, @@ -3059,16 +3095,16 @@ static uchar *read_next_extent(MARIA_HA *info, MARIA_EXTENT_CURSOR *extent, info->cur_row.full_page_count++; /* For maria_chk */ DBUG_RETURN(extent->data_start= buff + LSN_SIZE + PAGE_TYPE_SIZE); } - /* Found tail. page_count is in this case the position in the tail page */ + /* Found tail */ if ((buff[PAGE_TYPE_OFFSET] & PAGE_TYPE_MASK) != TAIL_PAGE) goto crashed; *(extent->tail_positions++)= ma_recordpos(extent->page, - extent->page_count); + extent->tail_row_nr); info->cur_row.tail_count++; /* For maria_chk */ if (!(data= get_record_position(buff, share->block_size, - extent->page_count, + extent->tail_row_nr, end_of_data))) goto crashed; extent->data_start= data; @@ -3124,7 +3160,7 @@ static my_bool read_long_data(MARIA_HA *info, uchar *to, ulong length, This may change in the future, which is why we have the loop written the way it's written. */ - if (length > (ulong) (*end_of_data - *data)) + if (extent->first_extent && length > (ulong) (*end_of_data - *data)) *end_of_data= *data; for(;;) diff --git a/storage/maria/ma_check.c b/storage/maria/ma_check.c index 1ac1fb3454f..a5e64cb555c 100644 --- a/storage/maria/ma_check.c +++ b/storage/maria/ma_check.c @@ -1706,8 +1706,13 @@ static int check_block_record(HA_CHECK *param, MARIA_HA *info, int extend, full_dir ? 0 : empty_space, &bitmap_pattern)) { + if (bitmap_pattern == ~(uint) 0) + _ma_check_print_error(param, + "Page: %9s: Wrong bitmap for data on page", + llstr(pos, llbuff)); + else _ma_check_print_error(param, - "Page %9s: Wrong data in bitmap. Page_type: %d empty_space: %u Bitmap: %d", + "Page %9s: Wrong data in bitmap. Page_type: %d empty_space: %u Bitmap-bits: %d", llstr(pos, llbuff), page_type, empty_space, bitmap_pattern); if (param->err_count++ > MAXERR || !(param->testflag & T_VERBOSE)) diff --git a/storage/maria/ma_close.c b/storage/maria/ma_close.c index a9d31a6c75f..cc9f0005a4d 100644 --- a/storage/maria/ma_close.c +++ b/storage/maria/ma_close.c @@ -65,6 +65,7 @@ int maria_close(register MARIA_HA *info) if (flag) { + /* Last close of file; Flush everything */ if (share->kfile.file >= 0) { if ((*share->once_end)(share)) @@ -87,7 +88,7 @@ int maria_close(register MARIA_HA *info) may be using the file at this point IF using --external-locking, which does not apply to Maria. */ - if (share->mode != O_RDONLY) + if (share->changed) _ma_state_info_write(share->kfile.file, &share->state, 1); if (my_close(share->kfile.file, MYF(0))) error= my_errno; diff --git a/storage/maria/ma_dynrec.c b/storage/maria/ma_dynrec.c index 246f9787b09..52ade04db98 100644 --- a/storage/maria/ma_dynrec.c +++ b/storage/maria/ma_dynrec.c @@ -1694,7 +1694,7 @@ int _ma_read_rnd_dynamic_record(MARIA_HA *info, { /* Check if changed */ info_read=1; info->rec_cache.seek_not_done=1; - if (_ma_state_info_read_dsk(share->kfile.file, &share->state, 1)) + if (_ma_state_info_read_dsk(share->kfile.file, &share->state)) goto panic; } if (filepos >= info->state->data_file_length) diff --git a/storage/maria/ma_extra.c b/storage/maria/ma_extra.c index 0ee5990844b..a3fb9569290 100644 --- a/storage/maria/ma_extra.c +++ b/storage/maria/ma_extra.c @@ -264,8 +264,8 @@ int maria_extra(MARIA_HA *info, enum ha_extra_function function, share->last_version= 0L; /* Impossible version */ pthread_mutex_unlock(&THR_LOCK_maria); break; - case HA_EXTRA_PREPARE_FOR_DELETE: - /* QQ: suggest to rename it to "PREPARE_FOR_DROP" */ + case HA_EXTRA_PREPARE_FOR_DROP: + case HA_EXTRA_PREPARE_FOR_RENAME: pthread_mutex_lock(&THR_LOCK_maria); share->last_version= 0L; /* Impossible version */ #ifdef __WIN__ @@ -284,7 +284,8 @@ int maria_extra(MARIA_HA *info, enum ha_extra_function function, Does ENABLE KEYS rebuild them too? */ if (flush_pagecache_blocks(share->pagecache, &share->kfile, - FLUSH_IGNORE_CHANGED)) + (function == HA_EXTRA_PREPARE_FOR_DROP ? + FLUSH_IGNORE_CHANGED : FLUSH_RELEASE))) { error=my_errno; share->changed=1; diff --git a/storage/maria/ma_locking.c b/storage/maria/ma_locking.c index f709d7e5759..dad4071edf8 100644 --- a/storage/maria/ma_locking.c +++ b/storage/maria/ma_locking.c @@ -153,7 +153,7 @@ int maria_lock_database(MARIA_HA *info, int lock_type) } if (!share->r_locks && !share->w_locks) { - if (_ma_state_info_read_dsk(share->kfile.file, &share->state, 1)) + if (_ma_state_info_read_dsk(share->kfile.file, &share->state)) { error=my_errno; break; @@ -181,7 +181,7 @@ int maria_lock_database(MARIA_HA *info, int lock_type) { if (!share->r_locks) { - if (_ma_state_info_read_dsk(share->kfile.file, &share->state, 1)) + if (_ma_state_info_read_dsk(share->kfile.file, &share->state)) { error=my_errno; break; @@ -364,7 +364,7 @@ int _ma_readinfo(register MARIA_HA *info, int lock_type, int check_keybuffer) MARIA_SHARE *share=info->s; if (!share->tot_locks) { - if (_ma_state_info_read_dsk(share->kfile.file, &share->state, 1)) + if (_ma_state_info_read_dsk(share->kfile.file, &share->state)) { int error=my_errno ? my_errno : -1; my_errno=error; diff --git a/storage/maria/ma_open.c b/storage/maria/ma_open.c index 6cdfadf5d6d..4c623ac56f3 100644 --- a/storage/maria/ma_open.c +++ b/storage/maria/ma_open.c @@ -1110,18 +1110,13 @@ uchar *_ma_state_info_read(uchar *ptr, MARIA_STATE_INFO *state) @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) { char buff[MARIA_STATE_INFO_SIZE + MARIA_STATE_EXTRA_SIZE]; if (!maria_single_user) { - if (pRead) - { - if (my_pread(file, buff, state->state_length,0L, MYF(MY_NABP))) - return 1; - } - else if (my_read(file, buff, state->state_length,MYF(MY_NABP))) + if (my_pread(file, buff, state->state_length, 0L, MYF(MY_NABP))) return 1; _ma_state_info_read(buff, state); } diff --git a/storage/maria/ma_pagecache.c b/storage/maria/ma_pagecache.c index eb1d1ad9b0a..735f1aeb504 100755 --- a/storage/maria/ma_pagecache.c +++ b/storage/maria/ma_pagecache.c @@ -300,23 +300,24 @@ struct st_pagecache_block_link *next_changed, **prev_changed; /* for lists of file dirty/clean blocks */ struct st_pagecache_hash_link *hash_link; /* backward ptr to referring hash_link */ +#ifndef DBUG_OFF + PAGECACHE_PIN_INFO *pin_list; + PAGECACHE_LOCK_INFO *lock_list; +#endif + KEYCACHE_CONDVAR *condvar; /* condition variable for 'no readers' event */ + uchar *buffer; /* buffer for the block page */ + PAGECACHE_FILE *write_locker; + ulonglong last_hit_time; /* timestamp of the last hit */ WQUEUE wqueue[COND_SIZE]; /* queues on waiting requests for new/old pages */ uint requests; /* number of requests for the block */ - uchar *buffer; /* buffer for the block page */ uint status; /* state of the block */ uint pins; /* pin counter */ -#ifndef DBUG_OFF - PAGECACHE_PIN_INFO *pin_list; - PAGECACHE_LOCK_INFO *lock_list; -#endif enum PCBLOCK_TEMPERATURE temperature; /* block temperature: cold, warm, hot */ enum pagecache_page_type type; /* type of the block */ uint hits_left; /* number of hits left until promotion */ - ulonglong last_hit_time; /* timestamp of the last hit */ /** @brief LSN when first became dirty; LSN_MAX means "not yet set" */ LSN rec_lsn; - KEYCACHE_CONDVAR *condvar; /* condition variable for 'no readers' event */ }; #ifndef DBUG_OFF @@ -2147,6 +2148,9 @@ static void info_change_lock(PAGECACHE_BLOCK_LINK *block, my_bool wl) get_wrlock() pagecache pointer to a page cache data structure block the block to work with + user_file Unique handler per handler file. Used to check if + we request many write locks withing the same + statement RETURN 0 - OK @@ -2154,7 +2158,8 @@ static void info_change_lock(PAGECACHE_BLOCK_LINK *block, my_bool wl) */ static my_bool get_wrlock(PAGECACHE *pagecache, - PAGECACHE_BLOCK_LINK *block) + PAGECACHE_BLOCK_LINK *block, + PAGECACHE_FILE *user_file) { PAGECACHE_FILE file= block->hash_link->file; pgcache_page_no_t pageno= block->hash_link->pageno; @@ -2165,7 +2170,7 @@ static my_bool get_wrlock(PAGECACHE *pagecache, file.file, block->hash_link->file.file, pageno, block->hash_link->pageno)); PCBLOCK_INFO(block); - while (block->status & PCBLOCK_WRLOCK) + while ((block->status & PCBLOCK_WRLOCK) && block->write_locker != user_file) { /* Lock failed we will wait */ #ifdef THREAD @@ -2197,9 +2202,9 @@ static my_bool get_wrlock(PAGECACHE *pagecache, DBUG_RETURN(1); } } - DBUG_ASSERT(block->pins == 0); /* we are doing it by global cache mutex protection, so it is OK */ block->status|= PCBLOCK_WRLOCK; + block->write_locker= user_file; DBUG_PRINT("info", ("WR lock set, block 0x%lx", (ulong)block)); DBUG_RETURN(0); } @@ -2223,6 +2228,8 @@ static void release_wrlock(PAGECACHE_BLOCK_LINK *block) PCBLOCK_INFO(block); DBUG_ASSERT(block->status & PCBLOCK_WRLOCK); DBUG_ASSERT(block->pins > 0); + if (block->pins > 1) + DBUG_VOID_RETURN; /* Multiple write locked */ block->status&= ~PCBLOCK_WRLOCK; DBUG_PRINT("info", ("WR lock reset, block 0x%lx", (ulong)block)); #ifdef THREAD @@ -2244,6 +2251,7 @@ static void release_wrlock(PAGECACHE_BLOCK_LINK *block) block the block to work with lock lock change mode pin pinchange mode + file File handler requesting pin RETURN 0 - OK @@ -2253,7 +2261,8 @@ static void release_wrlock(PAGECACHE_BLOCK_LINK *block) static my_bool make_lock_and_pin(PAGECACHE *pagecache, PAGECACHE_BLOCK_LINK *block, enum pagecache_page_lock lock, - enum pagecache_page_pin pin) + enum pagecache_page_pin pin, + PAGECACHE_FILE *file) { DBUG_ENTER("make_lock_and_pin"); @@ -2274,7 +2283,7 @@ static my_bool make_lock_and_pin(PAGECACHE *pagecache, switch (lock) { case PAGECACHE_LOCK_WRITE: /* free -> write */ /* Writelock and pin the buffer */ - if (get_wrlock(pagecache, block)) + if (get_wrlock(pagecache, block, file)) { /* can't lock => need retry */ goto retry; @@ -2291,6 +2300,7 @@ static my_bool make_lock_and_pin(PAGECACHE *pagecache, implementation) */ release_wrlock(block); + /* fall through */ case PAGECACHE_LOCK_READ_UNLOCK: /* read -> free */ case PAGECACHE_LOCK_LEFT_READLOCKED: /* read -> read */ if (pin == PAGECACHE_UNPIN) @@ -2549,7 +2559,7 @@ void pagecache_unlock(PAGECACHE *pagecache, if (lsn != LSN_IMPOSSIBLE) check_and_set_lsn(pagecache, lsn, block); - if (make_lock_and_pin(pagecache, block, lock, pin)) + if (make_lock_and_pin(pagecache, block, lock, pin, file)) { DBUG_ASSERT(0); /* should not happend */ } @@ -2617,7 +2627,7 @@ void pagecache_unpin(PAGECACHE *pagecache, */ if (make_lock_and_pin(pagecache, block, PAGECACHE_LOCK_LEFT_READLOCKED, - PAGECACHE_UNPIN)) + PAGECACHE_UNPIN, file)) DBUG_ASSERT(0); /* should not happend */ remove_reader(block); @@ -2678,7 +2688,7 @@ void pagecache_unlock_by_link(PAGECACHE *pagecache, lock == PAGECACHE_LOCK_READ_UNLOCK) { /* block do not need here so we do not provide it */ - if (make_lock_and_pin(pagecache, 0, lock, pin)) + if (make_lock_and_pin(pagecache, 0, lock, pin, 0)) DBUG_ASSERT(0); /* should not happend */ DBUG_VOID_RETURN; } @@ -2710,7 +2720,7 @@ void pagecache_unlock_by_link(PAGECACHE *pagecache, if (lsn != LSN_IMPOSSIBLE) check_and_set_lsn(pagecache, lsn, block); - if (make_lock_and_pin(pagecache, block, lock, pin)) + if (make_lock_and_pin(pagecache, block, lock, pin, 0)) DBUG_ASSERT(0); /* should not happend */ /* @@ -2772,7 +2782,7 @@ void pagecache_unpin_by_link(PAGECACHE *pagecache, */ if (make_lock_and_pin(pagecache, block, PAGECACHE_LOCK_LEFT_READLOCKED, - PAGECACHE_UNPIN)) + PAGECACHE_UNPIN, 0)) DBUG_ASSERT(0); /* should not happend */ /* @@ -2889,7 +2899,7 @@ restart: validator, validator_data); DBUG_PRINT("info", ("read is done")); } - if (make_lock_and_pin(pagecache, block, lock, pin)) + if (make_lock_and_pin(pagecache, block, lock, pin, file)) { /* We failed to write lock the block, cache is unlocked, @@ -3009,7 +3019,7 @@ restart: if (pin == PAGECACHE_PIN) reg_requests(pagecache, block, 1); DBUG_ASSERT(block != 0); - if (make_lock_and_pin(pagecache, block, lock, pin)) + if (make_lock_and_pin(pagecache, block, lock, pin, file)) { /* We failed to writelock the block, cache is unlocked, and last write @@ -3059,7 +3069,7 @@ restart: /* Cache is locked, so we can relese page before freeing it */ make_lock_and_pin(pagecache, block, PAGECACHE_LOCK_WRITE_UNLOCK, - PAGECACHE_UNPIN); + PAGECACHE_UNPIN, file); DBUG_ASSERT(link->requests > 0); link->requests--; /* See NOTE for pagecache_unlock about registering requests. */ @@ -3254,7 +3264,7 @@ restart: write_lock_change_table[lock].new_lock, (need_lock_change ? write_pin_change_table[pin].new_pin : - pin))) + pin), file)) { /* We failed to writelock the block, cache is unlocked, and last write @@ -3307,7 +3317,6 @@ restart: } } - if (need_lock_change) { /* @@ -3316,7 +3325,7 @@ restart: */ if (make_lock_and_pin(pagecache, block, write_lock_change_table[lock].unlock_lock, - write_pin_change_table[pin].unlock_pin)) + write_pin_change_table[pin].unlock_pin, file)) DBUG_ASSERT(0); } @@ -3474,7 +3483,7 @@ static int flush_cached_blocks(PAGECACHE *pagecache, DBUG_ASSERT((block->status & PCBLOCK_WRLOCK) == 0); DBUG_ASSERT(block->pins == 0); if (make_lock_and_pin(pagecache, block, - PAGECACHE_LOCK_WRITE, PAGECACHE_PIN)) + PAGECACHE_LOCK_WRITE, PAGECACHE_PIN, 0)) DBUG_ASSERT(0); KEYCACHE_DBUG_PRINT("flush_cached_blocks", @@ -3497,7 +3506,7 @@ static int flush_cached_blocks(PAGECACHE *pagecache, make_lock_and_pin(pagecache, block, PAGECACHE_LOCK_WRITE_UNLOCK, - PAGECACHE_UNPIN); + PAGECACHE_UNPIN, 0); pagecache->global_cache_write++; if (error) diff --git a/storage/maria/ma_recovery.c b/storage/maria/ma_recovery.c index b45346725e6..d5d758da4d6 100644 --- a/storage/maria/ma_recovery.c +++ b/storage/maria/ma_recovery.c @@ -507,7 +507,7 @@ prototype_exec_hook(REDO_DROP_TABLE) this table should not be used anymore, and (only on Windows) to close open files so they can be deleted */ - if (maria_extra(info, HA_EXTRA_PREPARE_FOR_DELETE, NULL) || + if (maria_extra(info, HA_EXTRA_PREPARE_FOR_DROP, NULL) || maria_close(info)) goto end; info= NULL; diff --git a/storage/maria/maria_def.h b/storage/maria/maria_def.h index ab2546b72f3..f5e143fe6f8 100644 --- a/storage/maria/maria_def.h +++ b/storage/maria/maria_def.h @@ -864,8 +864,7 @@ extern uint _ma_nommap_pwrite(MARIA_HA *info, uchar *Buffer, uint _ma_state_info_write(File file, MARIA_STATE_INFO *state, uint pWrite); uchar *_ma_state_info_read(uchar *ptr, MARIA_STATE_INFO *state); -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); uint _ma_base_info_write(File file, MARIA_BASE_INFO *base); int _ma_keyseg_write(File file, const HA_KEYSEG *keyseg); char *_ma_keyseg_read(char *ptr, HA_KEYSEG *keyseg); |