diff --git a/mysql-test/lib/mtr_cases.pl b/mysql-test/lib/mtr_cases.pl index 4b0fad0f818..96cd2a898be 100644 --- a/mysql-test/lib/mtr_cases.pl +++ b/mysql-test/lib/mtr_cases.pl @@ -513,19 +513,10 @@ sub collect_one_test_case($$$$$$$$$) { my $suite_opts= shift; my $path= "$testdir/$elem"; - - # ---------------------------------------------------------------------- - # Skip some tests silently - # ---------------------------------------------------------------------- - - if ( $::opt_start_from and $tname lt $::opt_start_from ) - { - return; - } - + my $name= basename($suite) . ".$tname"; my $tinfo= {}; - $tinfo->{'name'}= basename($suite) . ".$tname"; + $tinfo->{'name'}= $name; $tinfo->{'result_file'}= "$resdir/$tname.result"; $tinfo->{'component_id'} = $component_id; push(@$cases, $tinfo); @@ -534,7 +525,7 @@ sub collect_one_test_case($$$$$$$$$) { # Skip some tests but include in list, just mark them to skip # ---------------------------------------------------------------------- - if ( $skip_test and $tname =~ /$skip_test/o ) + if ( $skip_test and ($tname =~ /$skip_test/o || $name =~ /$skip_test/o)) { $tinfo->{'skip'}= 1; return; diff --git a/mysql-test/mysql-test-run.pl b/mysql-test/mysql-test-run.pl index 0845b7c0f5f..81365e1df7e 100755 --- a/mysql-test/mysql-test-run.pl +++ b/mysql-test/mysql-test-run.pl @@ -3391,6 +3391,24 @@ sub run_testcase_check_skip_test($) { my ($tinfo)= @_; + # ---------------------------------------------------------------------- + # Skip some tests silently + # ---------------------------------------------------------------------- + + if ( $::opt_start_from ) + { + if ($tinfo->{'name'} eq $::opt_start_from ) + { + ## Found parting test. Run this test and all tests after this one + $::opt_start_from= ""; + } + else + { + $tinfo->{'result'}= 'MTR_RES_SKIPPED'; + return 1; + } + } + # ---------------------------------------------------------------------- # If marked to skip, just print out and return. # Note that a test case not marked as 'skip' can still be diff --git a/storage/maria/ma_bitmap.c b/storage/maria/ma_bitmap.c index ee3364bf59c..51b01b36386 100644 --- a/storage/maria/ma_bitmap.c +++ b/storage/maria/ma_bitmap.c @@ -167,10 +167,10 @@ static inline my_bool write_changed_bitmap(MARIA_SHARE *share, int res= pagecache_write(share->pagecache, &bitmap->file, bitmap->page, 0, (uchar*) bitmap->map, PAGECACHE_PLAIN_PAGE, - PAGECACHE_LOCK_WRITE, PAGECACHE_PIN, + PAGECACHE_LOCK_LEFT_UNLOCKED, PAGECACHE_PIN, PAGECACHE_WRITE_DELAY, &page_link.link, LSN_IMPOSSIBLE); - page_link.unlock= PAGECACHE_LOCK_WRITE_UNLOCK; + page_link.unlock= PAGECACHE_LOCK_LEFT_UNLOCKED; page_link.changed= 1; push_dynamic(&bitmap->pinned_pages, (void*) &page_link); DBUG_RETURN(res); @@ -281,6 +281,14 @@ my_bool _ma_bitmap_end(MARIA_SHARE *share) by this thread (ie, checking the changed flag is ok). The reason we check it again in the mutex is that if someone else did a flush at the same time, we don't have to do the write. + This is also ok for _ma_scan_init_block_record() which does not want to + miss rows: it cares only for committed rows, that is, rows for which there + was a commit before our transaction started; as commit and transaction's + start are protected by the same LOCK_trn_list mutex, we see memory at + least as new as at other transaction's commit time, so if the committed + rows caused bitmap->changed to be true, we see it; if we see 0 it really + means a flush happened since then. So, it's ok to read without bitmap's + mutex. RETURN 0 ok @@ -305,38 +313,6 @@ my_bool _ma_bitmap_flush(MARIA_SHARE *share) } -/* - @brief Send updated bitmap to the page cache if bitmap is free - - @note - This is used by reader threads which don't unpin things -*/ - -my_bool _ma_bitmap_wait_or_flush(MARIA_SHARE *share) -{ - my_bool res= 0; - MARIA_FILE_BITMAP *bitmap= &share->bitmap; - DBUG_ENTER("_ma_bitmap_flush"); - if (bitmap->changed) - { - pthread_mutex_lock(&bitmap->bitmap_lock); - while (bitmap->non_flushable && bitmap->changed) - { - DBUG_PRINT("info", ("waiting for bitmap to be flushable")); - pthread_cond_wait(&bitmap->bitmap_cond, &bitmap->bitmap_lock); - } - if (bitmap->changed) - { - bitmap->changed= 0; - res= write_changed_bitmap(share, bitmap); - } - pthread_mutex_unlock(&bitmap->bitmap_lock); - } - DBUG_RETURN(res); -} - - - /** Dirty-page filtering criteria for bitmap pages @@ -386,8 +362,11 @@ my_bool _ma_bitmap_flush_all(MARIA_SHARE *share) unpinned. We keep the mutex to preserve this situation, and flush to the file. */ - res= write_changed_bitmap(share, bitmap); - bitmap->changed= FALSE; + if (bitmap->changed) + { + res= write_changed_bitmap(share, bitmap); + bitmap->changed= FALSE; + } /* We do NOT use FLUSH_KEEP_LAZY because we must be sure that bitmap pages have been flushed. That's a condition of correctness of @@ -424,6 +403,8 @@ my_bool _ma_bitmap_flush_all(MARIA_SHARE *share) @return Operation status @retval 0 ok + + @note This unpins pages pinned by other threads. */ static void _ma_bitmap_unpin_all(MARIA_SHARE *share) @@ -437,7 +418,7 @@ static void _ma_bitmap_unpin_all(MARIA_SHARE *share) while (pinned_page-- != page_link) pagecache_unlock_by_link(share->pagecache, pinned_page->link, pinned_page->unlock, PAGECACHE_UNPIN, - LSN_IMPOSSIBLE, LSN_IMPOSSIBLE, TRUE); + LSN_IMPOSSIBLE, LSN_IMPOSSIBLE, TRUE, TRUE); bitmap->pinned_pages.elements= 0; DBUG_VOID_RETURN; } @@ -2139,8 +2120,8 @@ my_bool _ma_bitmap_set_full_page_bits(MARIA_HA *info, function first waits for the flush to be done. @note - info->non_flushable_state is set to 1 if we have incremented - bitmap->info->non_flushable and not yet decremented it. + this sets info->non_flushable_state to 1 if we have incremented + bitmap->non_flushable and not yet decremented it. @param share Table's share @param non_flushable_inc Increment of MARIA_FILE_BITMAP::non_flushable @@ -2151,20 +2132,21 @@ void _ma_bitmap_flushable(MARIA_HA *info, int non_flushable_inc) { MARIA_SHARE *share= info->s; MARIA_FILE_BITMAP *bitmap; + DBUG_ENTER("_ma_bitmap_flushable"); /* Not transactional tables are never automaticly flushed and needs no protection */ if (!share->now_transactional) - return; + DBUG_VOID_RETURN; bitmap= &share->bitmap; if (non_flushable_inc == -1) { pthread_mutex_lock(&bitmap->bitmap_lock); - DBUG_ASSERT((int) bitmap->non_flushable > 0 && - info->non_flushable_state == 1); + DBUG_ASSERT((int) bitmap->non_flushable > 0); + DBUG_ASSERT(info->non_flushable_state == 1); info->non_flushable_state= 0; if (--bitmap->non_flushable == 0) { @@ -2182,14 +2164,15 @@ void _ma_bitmap_flushable(MARIA_HA *info, int non_flushable_inc) } DBUG_PRINT("info", ("bitmap->non_flushable: %u", bitmap->non_flushable)); pthread_mutex_unlock(&bitmap->bitmap_lock); - return; + DBUG_VOID_RETURN; } - DBUG_ASSERT(non_flushable_inc == 1 && info->non_flushable_state == 0); + DBUG_ASSERT(non_flushable_inc == 1); + DBUG_ASSERT(info->non_flushable_state == 0); /* It is a read without mutex because only an optimization */ if (unlikely(bitmap->flush_all_requested)) { /* - _ma_bitmap_flush_all() is waiting for the bitmap to become + Some other thread is waiting for the bitmap to become flushable. Not the moment to make the bitmap unflushable or more unflushable; let's rather back off and wait. If we didn't do this, with multiple writers, there may always be one thread causing the bitmap to @@ -2214,6 +2197,7 @@ void _ma_bitmap_flushable(MARIA_HA *info, int non_flushable_inc) bitmap->non_flushable++; info->non_flushable_state= 1; DBUG_PRINT("info", ("bitmap->non_flushable: %u", bitmap->non_flushable)); + DBUG_VOID_RETURN; } @@ -2321,10 +2305,10 @@ my_bool _ma_bitmap_release_unused(MARIA_HA *info, MARIA_BITMAP_BLOCKS *blocks) goto err; } - if (info->s->now_transactional) + /* This duplicates ma_bitmap_flushable(-1) except it already has mutex */ + if (info->non_flushable_state) { - DBUG_ASSERT((int) bitmap->non_flushable >= 0 && - info->non_flushable_state); + DBUG_ASSERT((int) bitmap->non_flushable >= 0); info->non_flushable_state= 0; if (--bitmap->non_flushable == 0) { diff --git a/storage/maria/ma_blockrec.c b/storage/maria/ma_blockrec.c index 95697a4afce..ed4d98015b1 100644 --- a/storage/maria/ma_blockrec.c +++ b/storage/maria/ma_blockrec.c @@ -1964,7 +1964,7 @@ static my_bool write_tail(MARIA_HA *info, pagecache_unlock_by_link(share->pagecache, page_link->link, PAGECACHE_LOCK_WRITE_TO_READ, PAGECACHE_PIN_LEFT_PINNED, LSN_IMPOSSIBLE, - LSN_IMPOSSIBLE, 1); + LSN_IMPOSSIBLE, 1, FALSE); DBUG_ASSERT(page_link->changed); page_link->unlock= PAGECACHE_LOCK_READ_UNLOCK; res= 0; @@ -3026,7 +3026,7 @@ static my_bool write_block_record(MARIA_HA *info, pagecache_unlock_by_link(share->pagecache, page_link->link, PAGECACHE_LOCK_WRITE_TO_READ, PAGECACHE_PIN_LEFT_PINNED, LSN_IMPOSSIBLE, - LSN_IMPOSSIBLE, 1); + LSN_IMPOSSIBLE, 1, FALSE); page_link->unlock= PAGECACHE_LOCK_READ_UNLOCK; page_link->changed= 1; } @@ -4025,7 +4025,7 @@ static my_bool delete_head_or_tail(MARIA_HA *info, pagecache_unlock_by_link(share->pagecache, page_link.link, lock_at_write, PAGECACHE_PIN_LEFT_PINNED, LSN_IMPOSSIBLE, - LSN_IMPOSSIBLE, 1); + LSN_IMPOSSIBLE, 1, FALSE); page_link.unlock= lock_at_unpin; set_dynamic(&info->pinned_pages, (void*) &page_link, info->pinned_pages.elements-1); @@ -4982,10 +4982,12 @@ my_bool _ma_scan_init_block_record(MARIA_HA *info) info->scan.bitmap_pos= info->scan.bitmap_end; info->scan.bitmap_page= (pgcache_page_no_t) 0 - share->bitmap.pages_covered; /* - We have to flush bitmap as we will read the bitmap from the page cache - while scanning rows + We need to flush what's in memory (bitmap.map) to page cache otherwise, as + we are going to read bitmaps from page cache in table scan (see + _ma_scan_block_record()), we may miss recently inserted rows (bitmap page + in page cache would be too old). */ - DBUG_RETURN(_ma_bitmap_wait_or_flush(info->s)); + DBUG_RETURN(_ma_bitmap_flush(info->s)); } @@ -5141,7 +5143,9 @@ restart_record_read: if (end_of_data > info->scan.dir_end || offset < PAGE_HEADER_SIZE || length < share->base.min_block_length) { - DBUG_ASSERT(0); + DBUG_ASSERT(!(end_of_data > info->scan.dir_end)); + DBUG_ASSERT(!(offset < PAGE_HEADER_SIZE)); + DBUG_ASSERT(!(length < share->base.min_block_length)); goto err; } #endif @@ -6033,7 +6037,7 @@ uint _ma_apply_redo_insert_row_head_or_tail(MARIA_HA *info, LSN lsn, pagecache_unlock_by_link(share->pagecache, page_link.link, PAGECACHE_LOCK_WRITE_UNLOCK, PAGECACHE_UNPIN, LSN_IMPOSSIBLE, - LSN_IMPOSSIBLE, 0); + LSN_IMPOSSIBLE, 0, FALSE); DBUG_RETURN(0); } @@ -6123,7 +6127,7 @@ err: pagecache_unlock_by_link(share->pagecache, page_link.link, PAGECACHE_LOCK_WRITE_UNLOCK, PAGECACHE_UNPIN, LSN_IMPOSSIBLE, - LSN_IMPOSSIBLE, 0); + LSN_IMPOSSIBLE, 0, FALSE); _ma_mark_file_crashed(share); DBUG_RETURN((my_errno= error)); } @@ -6193,7 +6197,7 @@ uint _ma_apply_redo_purge_row_head_or_tail(MARIA_HA *info, LSN lsn, pagecache_unlock_by_link(share->pagecache, page_link.link, PAGECACHE_LOCK_WRITE_UNLOCK, PAGECACHE_UNPIN, LSN_IMPOSSIBLE, - LSN_IMPOSSIBLE, 0); + LSN_IMPOSSIBLE, 0, FALSE); DBUG_RETURN(0); } @@ -6221,7 +6225,7 @@ err: pagecache_unlock_by_link(share->pagecache, page_link.link, PAGECACHE_LOCK_WRITE_UNLOCK, PAGECACHE_UNPIN, LSN_IMPOSSIBLE, - LSN_IMPOSSIBLE, 0); + LSN_IMPOSSIBLE, 0, FALSE); _ma_mark_file_crashed(share); DBUG_RETURN((my_errno= error)); @@ -6325,7 +6329,7 @@ uint _ma_apply_redo_free_head_or_tail(MARIA_HA *info, LSN lsn, pagecache_unlock_by_link(share->pagecache, page_link.link, PAGECACHE_LOCK_WRITE_UNLOCK, PAGECACHE_UNPIN, LSN_IMPOSSIBLE, - LSN_IMPOSSIBLE, 0); + LSN_IMPOSSIBLE, 0, FALSE); goto err; } if (lsn_korr(buff) >= lsn) @@ -6334,7 +6338,7 @@ uint _ma_apply_redo_free_head_or_tail(MARIA_HA *info, LSN lsn, pagecache_unlock_by_link(share->pagecache, page_link.link, PAGECACHE_LOCK_WRITE_UNLOCK, PAGECACHE_UNPIN, LSN_IMPOSSIBLE, - LSN_IMPOSSIBLE, 0); + LSN_IMPOSSIBLE, 0, FALSE); } else { @@ -6474,7 +6478,7 @@ uint _ma_apply_redo_insert_row_blobs(MARIA_HA *info, pagecache_unlock_by_link(share->pagecache, page_link.link, PAGECACHE_LOCK_WRITE_UNLOCK, PAGECACHE_UNPIN, LSN_IMPOSSIBLE, - LSN_IMPOSSIBLE, 0); + LSN_IMPOSSIBLE, 0, FALSE); goto err; } /* @@ -6494,7 +6498,7 @@ uint _ma_apply_redo_insert_row_blobs(MARIA_HA *info, pagecache_unlock_by_link(share->pagecache, page_link.link, PAGECACHE_LOCK_WRITE_UNLOCK, PAGECACHE_UNPIN, LSN_IMPOSSIBLE, - LSN_IMPOSSIBLE, 0); + LSN_IMPOSSIBLE, 0, FALSE); continue; } } diff --git a/storage/maria/ma_blockrec.h b/storage/maria/ma_blockrec.h index 36d61852086..34f6a3e3008 100644 --- a/storage/maria/ma_blockrec.h +++ b/storage/maria/ma_blockrec.h @@ -182,7 +182,6 @@ maria_page_get_lsn(uchar *page, pgcache_page_no_t page_no, uchar* data_ptr); my_bool _ma_bitmap_init(MARIA_SHARE *share, File file); my_bool _ma_bitmap_end(MARIA_SHARE *share); my_bool _ma_bitmap_flush(MARIA_SHARE *share); -my_bool _ma_bitmap_wait_or_flush(MARIA_SHARE *share); my_bool _ma_bitmap_flush_all(MARIA_SHARE *share); void _ma_bitmap_reset_cache(MARIA_SHARE *share); my_bool _ma_bitmap_find_place(MARIA_HA *info, MARIA_ROW *row, diff --git a/storage/maria/ma_check.c b/storage/maria/ma_check.c index 84e6d7df154..bc177a942c9 100644 --- a/storage/maria/ma_check.c +++ b/storage/maria/ma_check.c @@ -3184,7 +3184,7 @@ static my_bool maria_zerofill_index(HA_CHECK *param, MARIA_HA *info, pagecache_unlock_by_link(share->pagecache, page_link.link, PAGECACHE_LOCK_WRITE_UNLOCK, PAGECACHE_UNPIN, LSN_IMPOSSIBLE, - LSN_IMPOSSIBLE, 0); + LSN_IMPOSSIBLE, 0, FALSE); _ma_check_print_error(param, "Page %9s: Got error %d when reading index file", llstr(pos, llbuff), my_errno); @@ -3218,7 +3218,7 @@ static my_bool maria_zerofill_index(HA_CHECK *param, MARIA_HA *info, pagecache_unlock_by_link(share->pagecache, page_link.link, PAGECACHE_LOCK_WRITE_UNLOCK, PAGECACHE_UNPIN, LSN_IMPOSSIBLE, - LSN_IMPOSSIBLE, 1); + LSN_IMPOSSIBLE, 1, FALSE); } if (flush_pagecache_blocks(share->pagecache, &share->kfile, FLUSH_FORCE_WRITE)) @@ -3342,7 +3342,7 @@ static my_bool maria_zerofill_data(HA_CHECK *param, MARIA_HA *info, pagecache_unlock_by_link(share->pagecache, page_link.link, PAGECACHE_LOCK_WRITE_UNLOCK, PAGECACHE_UNPIN, LSN_IMPOSSIBLE, - LSN_IMPOSSIBLE, 1); + LSN_IMPOSSIBLE, 1, FALSE); } DBUG_RETURN(_ma_bitmap_flush(share) || flush_pagecache_blocks(share->pagecache, &info->dfile, @@ -3352,7 +3352,7 @@ err: pagecache_unlock_by_link(share->pagecache, page_link.link, PAGECACHE_LOCK_WRITE_UNLOCK, PAGECACHE_UNPIN, LSN_IMPOSSIBLE, - LSN_IMPOSSIBLE, 0); + LSN_IMPOSSIBLE, 0, FALSE); DBUG_RETURN(1); } diff --git a/storage/maria/ma_key_recover.c b/storage/maria/ma_key_recover.c index 3787e69f4a0..3a40790b069 100644 --- a/storage/maria/ma_key_recover.c +++ b/storage/maria/ma_key_recover.c @@ -70,7 +70,7 @@ void _ma_unpin_all_pages(MARIA_HA *info, LSN undo_lsn) pagecache_unlock_by_link(info->s->pagecache, pinned_page->link, pinned_page->unlock, PAGECACHE_UNPIN, info->trn->rec_lsn, undo_lsn, - pinned_page->changed); + pinned_page->changed, FALSE); } info->pinned_pages.elements= 0; @@ -700,7 +700,7 @@ err: pagecache_unlock_by_link(share->pagecache, page_link.link, PAGECACHE_LOCK_WRITE_UNLOCK, PAGECACHE_UNPIN, LSN_IMPOSSIBLE, - LSN_IMPOSSIBLE, 0); + LSN_IMPOSSIBLE, 0, FALSE); DBUG_RETURN(result); } @@ -779,7 +779,7 @@ err: pagecache_unlock_by_link(share->pagecache, page_link.link, PAGECACHE_LOCK_WRITE_UNLOCK, PAGECACHE_UNPIN, LSN_IMPOSSIBLE, - LSN_IMPOSSIBLE, 0); + LSN_IMPOSSIBLE, 0, FALSE); DBUG_RETURN(result); } @@ -1047,7 +1047,7 @@ err: pagecache_unlock_by_link(share->pagecache, page_link.link, PAGECACHE_LOCK_WRITE_UNLOCK, PAGECACHE_UNPIN, LSN_IMPOSSIBLE, - LSN_IMPOSSIBLE, 0); + LSN_IMPOSSIBLE, 0, FALSE); if (result) _ma_mark_file_crashed(share); DBUG_RETURN(result); diff --git a/storage/maria/ma_loghandler.c b/storage/maria/ma_loghandler.c index f8b264fe450..5ed83356d30 100644 --- a/storage/maria/ma_loghandler.c +++ b/storage/maria/ma_loghandler.c @@ -3028,7 +3028,7 @@ static void translog_free_link(PAGECACHE_BLOCK_LINK *direct_link) if (direct_link) pagecache_unlock_by_link(log_descriptor.pagecache, direct_link, PAGECACHE_LOCK_READ_UNLOCK, PAGECACHE_UNPIN, - LSN_IMPOSSIBLE, LSN_IMPOSSIBLE, 0); + LSN_IMPOSSIBLE, LSN_IMPOSSIBLE, 0, FALSE); DBUG_VOID_RETURN; } diff --git a/storage/maria/ma_pagecache.c b/storage/maria/ma_pagecache.c index 8972ee94fc1..e56537eadb0 100644 --- a/storage/maria/ma_pagecache.c +++ b/storage/maria/ma_pagecache.c @@ -267,16 +267,21 @@ static void info_unlink(PAGECACHE_PIN_INFO *node) list the list where to find the thread thread thread ID (reference to the st_my_thread_var of the thread) + any return any thread of the list RETURN 0 - the thread was not found - pointer to the information node of the thread in the list + pointer to the information node of the thread in the list, or, if 'any', + to any thread of the list. */ static PAGECACHE_PIN_INFO *info_find(PAGECACHE_PIN_INFO *list, - struct st_my_thread_var *thread) + struct st_my_thread_var *thread, + my_bool any) { register PAGECACHE_PIN_INFO *i= list; + if (any) + return i; for(; i != 0; i= i->next) if (i->thread == thread) return i; @@ -2150,18 +2155,22 @@ static void add_pin(PAGECACHE_BLOCK_LINK *block) DBUG_VOID_RETURN; } -static void remove_pin(PAGECACHE_BLOCK_LINK *block) +static void remove_pin(PAGECACHE_BLOCK_LINK *block, my_bool any +#ifdef DBUG_OFF + __attribute__((unused)) +#endif + ) { DBUG_ENTER("remove_pin"); - DBUG_PRINT("enter", ("block: 0x%lx pins: %u", + DBUG_PRINT("enter", ("block: 0x%lx pins: %u any: %d", (ulong) block, - block->pins)); + block->pins, (int)any)); PCBLOCK_INFO(block); DBUG_ASSERT(block->pins > 0); block->pins--; #ifndef DBUG_OFF { - PAGECACHE_PIN_INFO *info= info_find(block->pin_list, my_thread_var); + PAGECACHE_PIN_INFO *info= info_find(block->pin_list, my_thread_var, any); DBUG_ASSERT(info != 0); info_unlink(info); my_free((uchar*) info, MYF(0)); @@ -2183,7 +2192,7 @@ static void info_remove_lock(PAGECACHE_BLOCK_LINK *block) { PAGECACHE_LOCK_INFO *info= (PAGECACHE_LOCK_INFO *)info_find((PAGECACHE_PIN_INFO *)block->lock_list, - my_thread_var); + my_thread_var, FALSE); DBUG_ASSERT(info != 0); info_unlink((PAGECACHE_PIN_INFO *)info); my_free((uchar*)info, MYF(0)); @@ -2192,7 +2201,7 @@ static void info_change_lock(PAGECACHE_BLOCK_LINK *block, my_bool wl) { PAGECACHE_LOCK_INFO *info= (PAGECACHE_LOCK_INFO *)info_find((PAGECACHE_PIN_INFO *)block->lock_list, - my_thread_var); + my_thread_var, FALSE); DBUG_ASSERT(info != 0); DBUG_ASSERT(info->write_lock != wl); info->write_lock= wl; @@ -2448,6 +2457,8 @@ static void release_rdlock(PAGECACHE_BLOCK_LINK *block) @param lock lock change mode @param pin pinchange mode @param file File handler requesting pin + @param any allow unpinning block pinned by any thread; possible + only if not locked, see pagecache_unlock_by_link() @retval 0 OK @retval 1 Try to lock the block failed @@ -2456,7 +2467,8 @@ static void release_rdlock(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, + my_bool any) { DBUG_ENTER("make_lock_and_pin"); @@ -2465,16 +2477,20 @@ static my_bool make_lock_and_pin(PAGECACHE *pagecache, if (block) { DBUG_PRINT("enter", ("block: 0x%lx (%u) wrlocks: %u rdlocks: %u " - "rdlocks_q: %u pins: %u lock: %s pin: %s", + "rdlocks_q: %u pins: %u lock: %s pin: %s any %d", (ulong)block, PCBLOCK_NUMBER(pagecache, block), block->wlocks, block->rlocks, block->rlocks_queue, block->pins, page_cache_page_lock_str[lock], - page_cache_page_pin_str[pin])); + page_cache_page_pin_str[pin], (int)any)); PCBLOCK_INFO(block); } #endif + DBUG_ASSERT(!any || + ((lock == PAGECACHE_LOCK_LEFT_UNLOCKED) && + (pin == PAGECACHE_UNPIN))); + switch (lock) { case PAGECACHE_LOCK_WRITE: /* free -> write */ /* Writelock and pin the buffer */ @@ -2500,7 +2516,7 @@ static my_bool make_lock_and_pin(PAGECACHE *pagecache, case PAGECACHE_LOCK_LEFT_READLOCKED: /* read -> read */ if (pin == PAGECACHE_UNPIN) { - remove_pin(block); + remove_pin(block, FALSE); } if (lock == PAGECACHE_LOCK_WRITE_TO_READ) { @@ -2529,7 +2545,7 @@ static my_bool make_lock_and_pin(PAGECACHE *pagecache, case PAGECACHE_LOCK_LEFT_UNLOCKED: /* free -> free */ if (pin == PAGECACHE_UNPIN) { - remove_pin(block); + remove_pin(block, any); } /* fall through */ case PAGECACHE_LOCK_LEFT_WRITELOCKED: /* write -> write */ @@ -2793,7 +2809,7 @@ void pagecache_unlock(PAGECACHE *pagecache, (ulong) block)); } - if (make_lock_and_pin(pagecache, block, lock, pin)) + if (make_lock_and_pin(pagecache, block, lock, pin, FALSE)) { DBUG_ASSERT(0); /* should not happend */ } @@ -2863,7 +2879,7 @@ void pagecache_unpin(PAGECACHE *pagecache, */ if (make_lock_and_pin(pagecache, block, PAGECACHE_LOCK_LEFT_READLOCKED, - PAGECACHE_UNPIN)) + PAGECACHE_UNPIN, FALSE)) DBUG_ASSERT(0); /* should not happend */ remove_reader(block); @@ -2886,15 +2902,22 @@ void pagecache_unpin(PAGECACHE *pagecache, @brief Unlock/unpin page and put LSN stamp if it need (uses direct block/page pointer) - @param pagecache pointer to a page cache data structure - @param link direct link to page (returned by read or write) - @param lock lock change - @param pin pin page + @param pagecache pointer to a page cache data structure + @param link direct link to page (returned by read or write) + @param lock lock change + @param pin pin page @param first_REDO_LSN_for_page do not set it if it is LSN_IMPOSSIBLE (0) - @param lsn if it is not LSN_IMPOSSIBLE and it is bigger then - LSN on the page it will be written on the page - @param was_changed should be true if the page was write locked with - direct link giving and the page was changed + @param lsn if it is not LSN_IMPOSSIBLE and it is bigger then + LSN on the page it will be written on the page + @param was_changed should be true if the page was write locked with + direct link giving and the page was changed + @param any allow unpinning block pinned by any thread; possible + only if not locked + + @note 'any' is a hack so that _ma_bitmap_unpin_all() is allowed to unpin + non-locked bitmap pages pinned by other threads. Because it always uses + PAGECACHE_LOCK_LEFT_UNLOCKED and PAGECACHE_UNPIN + (see write_changed_bitmap()), the hack is limited to these conditions. */ void pagecache_unlock_by_link(PAGECACHE *pagecache, @@ -2902,7 +2925,8 @@ void pagecache_unlock_by_link(PAGECACHE *pagecache, enum pagecache_page_lock lock, enum pagecache_page_pin pin, LSN first_REDO_LSN_for_page, - LSN lsn, my_bool was_changed) + LSN lsn, my_bool was_changed, + my_bool any) { DBUG_ENTER("pagecache_unlock_by_link"); DBUG_PRINT("enter", ("block: 0x%lx fd: %u page: %lu changed: %d %s %s", @@ -2922,7 +2946,7 @@ void pagecache_unlock_by_link(PAGECACHE *pagecache, if (pin == PAGECACHE_PIN_LEFT_UNPINNED && lock == PAGECACHE_LOCK_READ_UNLOCK) { - if (make_lock_and_pin(pagecache, block, lock, pin)) + if (make_lock_and_pin(pagecache, block, lock, pin, FALSE)) DBUG_ASSERT(0); /* should not happend */ DBUG_VOID_RETURN; } @@ -2976,7 +3000,7 @@ void pagecache_unlock_by_link(PAGECACHE *pagecache, (ulong) block)); } - if (make_lock_and_pin(pagecache, block, lock, pin)) + if (make_lock_and_pin(pagecache, block, lock, pin, any)) DBUG_ASSERT(0); /* should not happend */ /* @@ -3039,7 +3063,7 @@ void pagecache_unpin_by_link(PAGECACHE *pagecache, */ if (make_lock_and_pin(pagecache, block, PAGECACHE_LOCK_LEFT_READLOCKED, - PAGECACHE_UNPIN)) + PAGECACHE_UNPIN, FALSE)) DBUG_ASSERT(0); /* should not happend */ /* @@ -3190,7 +3214,7 @@ restart: block->type == PAGECACHE_EMPTY_PAGE) block->type= type; - if (make_lock_and_pin(pagecache, block, lock, pin)) + if (make_lock_and_pin(pagecache, block, lock, pin, FALSE)) { /* We failed to write lock the block, cache is unlocked, @@ -3334,7 +3358,7 @@ static my_bool pagecache_delete_internal(PAGECACHE *pagecache, /* Cache is locked, so we can relese page before freeing it */ if (make_lock_and_pin(pagecache, block, PAGECACHE_LOCK_WRITE_UNLOCK, - PAGECACHE_UNPIN)) + PAGECACHE_UNPIN, FALSE)) DBUG_ASSERT(0); DBUG_ASSERT(block->hash_link->requests > 0); page_link->requests--; @@ -3396,7 +3420,7 @@ my_bool pagecache_delete_by_link(PAGECACHE *pagecache, make_lock_and_pin() can't fail here, because we are keeping pin on the block and it can't be evicted (which is cause of lock fail and retry) */ - if (make_lock_and_pin(pagecache, block, lock, pin)) + if (make_lock_and_pin(pagecache, block, lock, pin, FALSE)) DBUG_ASSERT(0); /* @@ -3514,7 +3538,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, FALSE)) { /* We failed to writelock the block, cache is unlocked, and last write @@ -3736,7 +3760,7 @@ restart: write_lock_change_table[lock].new_lock, (need_lock_change ? write_pin_change_table[pin].new_pin : - pin))) + pin), FALSE)) { /* We failed to writelock the block, cache is unlocked, and last write @@ -3823,7 +3847,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, FALSE)) DBUG_ASSERT(0); } @@ -4034,7 +4058,7 @@ static int flush_cached_blocks(PAGECACHE *pagecache, DBUG_ASSERT(block->wlocks == 0); DBUG_ASSERT(block->pins == 0); if (make_lock_and_pin(pagecache, block, - PAGECACHE_LOCK_WRITE, PAGECACHE_PIN)) + PAGECACHE_LOCK_WRITE, PAGECACHE_PIN, FALSE)) DBUG_ASSERT(0); DBUG_ASSERT(block->pins == 1); @@ -4068,7 +4092,7 @@ static int flush_cached_blocks(PAGECACHE *pagecache, if (make_lock_and_pin(pagecache, block, PAGECACHE_LOCK_WRITE_UNLOCK, - PAGECACHE_UNPIN)) + PAGECACHE_UNPIN, FALSE)) DBUG_ASSERT(0); pagecache->global_cache_write++; diff --git a/storage/maria/ma_pagecache.h b/storage/maria/ma_pagecache.h index 3253d831942..821728ef374 100644 --- a/storage/maria/ma_pagecache.h +++ b/storage/maria/ma_pagecache.h @@ -242,7 +242,8 @@ extern void pagecache_unlock_by_link(PAGECACHE *pagecache, enum pagecache_page_lock lock, enum pagecache_page_pin pin, LSN first_REDO_LSN_for_page, - LSN lsn, my_bool was_changed); + LSN lsn, my_bool was_changed, + my_bool any); extern void pagecache_unpin(PAGECACHE *pagecache, PAGECACHE_FILE *file, pgcache_page_no_t pageno, diff --git a/storage/maria/ma_preload.c b/storage/maria/ma_preload.c index c453788ed49..6367d013f60 100644 --- a/storage/maria/ma_preload.c +++ b/storage/maria/ma_preload.c @@ -104,7 +104,7 @@ int maria_preload(MARIA_HA *info, ulonglong key_map, my_bool ignore_leaves) else /* otherwise it stays in cache: */ pagecache_unlock_by_link(share->pagecache, page_link, PAGECACHE_LOCK_WRITE_UNLOCK, PAGECACHE_UNPIN, - LSN_IMPOSSIBLE, LSN_IMPOSSIBLE, FALSE); + LSN_IMPOSSIBLE, LSN_IMPOSSIBLE, FALSE, FALSE); } my_free(buff, MYF(0)); diff --git a/storage/maria/unittest/ma_pagecache_rwconsist.c b/storage/maria/unittest/ma_pagecache_rwconsist.c index 42f476ebcf8..a1a22b5e18d 100644 --- a/storage/maria/unittest/ma_pagecache_rwconsist.c +++ b/storage/maria/unittest/ma_pagecache_rwconsist.c @@ -114,7 +114,7 @@ void reader(int num) check_page(buff, num); pagecache_unlock_by_link(&pagecache, link, PAGECACHE_LOCK_READ_UNLOCK, - PAGECACHE_UNPIN, 0, 0, 0); + PAGECACHE_UNPIN, 0, 0, 0, FALSE); { int lim= rand() % read_sleep_limit; int j; @@ -149,7 +149,7 @@ void writer(int num) check_page(buff, num); pagecache_unlock_by_link(&pagecache, link, PAGECACHE_LOCK_WRITE_UNLOCK, - PAGECACHE_UNPIN, 0, 0, 1); + PAGECACHE_UNPIN, 0, 0, 1, FALSE); SLEEP; } } diff --git a/storage/maria/unittest/ma_pagecache_single.c b/storage/maria/unittest/ma_pagecache_single.c index 627a7436525..53c820dcd2e 100644 --- a/storage/maria/unittest/ma_pagecache_single.c +++ b/storage/maria/unittest/ma_pagecache_single.c @@ -391,7 +391,7 @@ int simple_pin_no_lock_test() &link, LSN_IMPOSSIBLE); pagecache_unlock_by_link(&pagecache, link, PAGECACHE_LOCK_WRITE_UNLOCK, - PAGECACHE_PIN_LEFT_PINNED, 0, 0, 1); + PAGECACHE_PIN_LEFT_PINNED, 0, 0, 1, FALSE); if (!flush_pagecache_blocks(&pagecache, &file1, FLUSH_FORCE_WRITE)) { diag("Did not get error in flush_pagecache_blocks 3\n");