diff options
author | Georgi Kodinov <Georgi.Kodinov@Oracle.com> | 2012-04-10 14:23:17 +0300 |
---|---|---|
committer | Georgi Kodinov <Georgi.Kodinov@Oracle.com> | 2012-04-10 14:23:17 +0300 |
commit | 7fa28bcf568f6873346a4c222bb95a60556876e9 (patch) | |
tree | 2238a3d5fa70dcbe2a1e176ceef8ce7394842463 /storage | |
parent | 1d860ec51a3414259d349efba3dec68c295c79a2 (diff) | |
parent | 20459a71e3e0d5d6607bde122f27f752de053dd4 (diff) | |
download | mariadb-git-7fa28bcf568f6873346a4c222bb95a60556876e9.tar.gz |
merge mysql-5.5->mysql-5.5-security
Diffstat (limited to 'storage')
-rw-r--r-- | storage/innobase/buf/buf0lru.c | 414 | ||||
-rw-r--r-- | storage/innobase/fil/fil0fil.c | 13 | ||||
-rw-r--r-- | storage/innobase/handler/ha_innodb.cc | 97 | ||||
-rw-r--r-- | storage/innobase/include/buf0lru.h | 11 | ||||
-rw-r--r-- | storage/innobase/include/buf0types.h | 9 | ||||
-rw-r--r-- | storage/innobase/include/fil0fil.h | 4 | ||||
-rw-r--r-- | storage/innobase/include/trx0purge.h | 4 | ||||
-rw-r--r-- | storage/innobase/row/row0mysql.c | 5 | ||||
-rw-r--r-- | storage/innobase/trx/trx0purge.c | 2 | ||||
-rw-r--r-- | storage/perfschema/pfs_instr.cc | 49 |
10 files changed, 455 insertions, 153 deletions
diff --git a/storage/innobase/buf/buf0lru.c b/storage/innobase/buf/buf0lru.c index 15b0ad40aaa..8e787fdba17 100644 --- a/storage/innobase/buf/buf0lru.c +++ b/storage/innobase/buf/buf0lru.c @@ -335,39 +335,275 @@ next_page: } /******************************************************************//** +While flushing (or removing dirty) pages from a tablespace we don't +want to hog the CPU and resources. Release the buffer pool and block +mutex and try to force a context switch. Then reacquire the same mutexes. +The current page is "fixed" before the release of the mutexes and then +"unfixed" again once we have reacquired the mutexes. */ +static +void +buf_flush_yield( +/*============*/ + buf_pool_t* buf_pool, /*!< in/out: buffer pool instance */ + buf_page_t* bpage) /*!< in/out: current page */ +{ + mutex_t* block_mutex; + + ut_ad(buf_pool_mutex_own(buf_pool)); + ut_ad(buf_page_in_file(bpage)); + + block_mutex = buf_page_get_mutex(bpage); + + mutex_enter(block_mutex); + /* "Fix" the block so that the position cannot be + changed after we release the buffer pool and + block mutexes. */ + buf_page_set_sticky(bpage); + + /* Now it is safe to release the buf_pool->mutex. */ + buf_pool_mutex_exit(buf_pool); + + mutex_exit(block_mutex); + /* Try and force a context switch. */ + os_thread_yield(); + + buf_pool_mutex_enter(buf_pool); + + mutex_enter(block_mutex); + /* "Unfix" the block now that we have both the + buffer pool and block mutex again. */ + buf_page_unset_sticky(bpage); + mutex_exit(block_mutex); +} + +/******************************************************************//** +If we have hogged the resources for too long then release the buffer +pool and flush list mutex and do a thread yield. Set the current page +to "sticky" so that it is not relocated during the yield. +@return TRUE if yielded */ +static +ibool +buf_flush_try_yield( +/*================*/ + buf_pool_t* buf_pool, /*!< in/out: buffer pool instance */ + buf_page_t* bpage, /*!< in/out: bpage to remove */ + ulint processed) /*!< in: number of pages processed */ +{ + /* Every BUF_LRU_DROP_SEARCH_SIZE iterations in the + loop we release buf_pool->mutex to let other threads + do their job but only if the block is not IO fixed. This + ensures that the block stays in its position in the + flush_list. */ + + if (bpage != NULL + && processed >= BUF_LRU_DROP_SEARCH_SIZE + && buf_page_get_io_fix(bpage) == BUF_IO_NONE) { + + buf_flush_list_mutex_exit(buf_pool); + + /* Release the buffer pool and block mutex + to give the other threads a go. */ + + buf_flush_yield(buf_pool, bpage); + + buf_flush_list_mutex_enter(buf_pool); + + /* Should not have been removed from the flush + list during the yield. However, this check is + not sufficient to catch a remove -> add. */ + + ut_ad(bpage->in_flush_list); + + return(TRUE); + } + + return(FALSE); +} + +/******************************************************************//** +Removes a single page from a given tablespace inside a specific +buffer pool instance. +@return TRUE if page was removed. */ +static +ibool +buf_flush_or_remove_page( +/*=====================*/ + buf_pool_t* buf_pool, /*!< in/out: buffer pool instance */ + buf_page_t* bpage) /*!< in/out: bpage to remove */ +{ + mutex_t* block_mutex; + ibool processed = FALSE; + + ut_ad(buf_pool_mutex_own(buf_pool)); + ut_ad(buf_flush_list_mutex_own(buf_pool)); + + block_mutex = buf_page_get_mutex(bpage); + + /* bpage->space and bpage->io_fix are protected by + buf_pool->mutex and block_mutex. It is safe to check + them while holding buf_pool->mutex only. */ + + if (buf_page_get_io_fix(bpage) != BUF_IO_NONE) { + + /* We cannot remove this page during this scan + yet; maybe the system is currently reading it + in, or flushing the modifications to the file */ + + } else { + + /* We have to release the flush_list_mutex to obey the + latching order. We are however guaranteed that the page + will stay in the flush_list because buf_flush_remove() + needs buf_pool->mutex as well (for the non-flush case). */ + + buf_flush_list_mutex_exit(buf_pool); + + mutex_enter(block_mutex); + + ut_ad(bpage->oldest_modification != 0); + + if (bpage->buf_fix_count == 0) { + + buf_flush_remove(bpage); + + processed = TRUE; + } + + mutex_exit(block_mutex); + + buf_flush_list_mutex_enter(buf_pool); + } + + ut_ad(!mutex_own(block_mutex)); + + return(processed); +} + +/******************************************************************//** Remove all dirty pages belonging to a given tablespace inside a specific buffer pool instance when we are deleting the data file(s) of that tablespace. The pages still remain a part of LRU and are evicted from -the list as they age towards the tail of the LRU. */ +the list as they age towards the tail of the LRU. +@return TRUE if all freed. */ +static +ibool +buf_flush_or_remove_pages( +/*======================*/ + buf_pool_t* buf_pool, /*!< buffer pool instance */ + ulint id) /*!< in: target space id for which + to remove or flush pages */ +{ + buf_page_t* prev; + buf_page_t* bpage; + ulint processed = 0; + ibool all_freed = TRUE; + + buf_flush_list_mutex_enter(buf_pool); + + for (bpage = UT_LIST_GET_LAST(buf_pool->flush_list); + bpage != NULL; + bpage = prev) { + + ut_a(buf_page_in_file(bpage)); + ut_ad(bpage->in_flush_list); + + /* Save the previous link because once we free the + page we can't rely on the links. */ + + prev = UT_LIST_GET_PREV(list, bpage); + + if (buf_page_get_space(bpage) != id) { + + /* Skip this block, as it does not belong to + the target space. */ + + } else if (!buf_flush_or_remove_page(buf_pool, bpage)) { + + /* Remove was unsuccessful, we have to try again + by scanning the entire list from the end. */ + + all_freed = FALSE; + } + + ++processed; + + /* Yield if we have hogged the CPU and mutexes for too long. */ + if (buf_flush_try_yield(buf_pool, prev, processed)) { + + /* Reset the batch size counter if we had to yield. */ + + processed = 0; + } + + } + + buf_flush_list_mutex_exit(buf_pool); + + return(all_freed); +} + +/******************************************************************//** +Remove or flush all the dirty pages that belong to a given tablespace +inside a specific buffer pool instance. The pages will remain in the LRU +list and will be evicted from the LRU list as they age and move towards +the tail of the LRU list. */ static void -buf_LRU_remove_dirty_pages_for_tablespace( -/*======================================*/ +buf_flush_dirty_pages( +/*==================*/ + buf_pool_t* buf_pool, /*!< buffer pool instance */ + ulint id) /*!< in: space id */ +{ + ibool all_freed; + + do { + buf_pool_mutex_enter(buf_pool); + + all_freed = buf_flush_or_remove_pages(buf_pool, id); + + buf_pool_mutex_exit(buf_pool); + + ut_ad(buf_flush_validate(buf_pool)); + + if (!all_freed) { + os_thread_sleep(20000); + } + + } while (!all_freed); +} + +/******************************************************************//** +Remove all pages that belong to a given tablespace inside a specific +buffer pool instance when we are DISCARDing the tablespace. */ +static +void +buf_LRU_remove_all_pages( +/*=====================*/ buf_pool_t* buf_pool, /*!< buffer pool instance */ ulint id) /*!< in: space id */ { buf_page_t* bpage; ibool all_freed; - ulint i; scan_again: buf_pool_mutex_enter(buf_pool); - buf_flush_list_mutex_enter(buf_pool); all_freed = TRUE; - for (bpage = UT_LIST_GET_LAST(buf_pool->flush_list), i = 0; - bpage != NULL; ++i) { + for (bpage = UT_LIST_GET_LAST(buf_pool->LRU); + bpage != NULL; + /* No op */) { buf_page_t* prev_bpage; mutex_t* block_mutex = NULL; ut_a(buf_page_in_file(bpage)); + ut_ad(bpage->in_LRU_list); - prev_bpage = UT_LIST_GET_PREV(list, bpage); + prev_bpage = UT_LIST_GET_PREV(LRU, bpage); /* bpage->space and bpage->io_fix are protected by - buf_pool->mutex and block_mutex. It is safe to check + buf_pool->mutex and the block_mutex. It is safe to check them while holding buf_pool->mutex only. */ if (buf_page_get_space(bpage) != id) { @@ -381,83 +617,87 @@ scan_again: all_freed = FALSE; goto next_page; - } + } else { - /* We have to release the flush_list_mutex to obey the - latching order. We are however guaranteed that the page - will stay in the flush_list because buf_flush_remove() - needs buf_pool->mutex as well. */ - buf_flush_list_mutex_exit(buf_pool); - block_mutex = buf_page_get_mutex(bpage); - mutex_enter(block_mutex); + block_mutex = buf_page_get_mutex(bpage); + mutex_enter(block_mutex); - if (bpage->buf_fix_count > 0) { - mutex_exit(block_mutex); - buf_flush_list_mutex_enter(buf_pool); + if (bpage->buf_fix_count > 0) { - /* We cannot remove this page during - this scan yet; maybe the system is - currently reading it in, or flushing - the modifications to the file */ + mutex_exit(block_mutex); - all_freed = FALSE; - goto next_page; - } + /* We cannot remove this page during + this scan yet; maybe the system is + currently reading it in, or flushing + the modifications to the file */ - ut_ad(bpage->oldest_modification != 0); + all_freed = FALSE; - buf_flush_remove(bpage); + goto next_page; + } + } - mutex_exit(block_mutex); - buf_flush_list_mutex_enter(buf_pool); -next_page: - bpage = prev_bpage; + ut_ad(mutex_own(block_mutex)); - if (!bpage) { - break; +#ifdef UNIV_DEBUG + if (buf_debug_prints) { + fprintf(stderr, + "Dropping space %lu page %lu\n", + (ulong) buf_page_get_space(bpage), + (ulong) buf_page_get_page_no(bpage)); } +#endif + if (buf_page_get_state(bpage) != BUF_BLOCK_FILE_PAGE) { + /* Do nothing, because the adaptive hash index + covers uncompressed pages only. */ + } else if (((buf_block_t*) bpage)->index) { + ulint page_no; + ulint zip_size; - /* Every BUF_LRU_DROP_SEARCH_SIZE iterations in the - loop we release buf_pool->mutex to let other threads - do their job. */ - if (i < BUF_LRU_DROP_SEARCH_SIZE) { - continue; + buf_pool_mutex_exit(buf_pool); + + zip_size = buf_page_get_zip_size(bpage); + page_no = buf_page_get_page_no(bpage); + + mutex_exit(block_mutex); + + /* Note that the following call will acquire + and release block->lock X-latch. */ + + btr_search_drop_page_hash_when_freed( + id, zip_size, page_no); + + goto scan_again; } - /* We IO-fix the block to make sure that the block - stays in its position in the flush_list. */ - if (buf_page_get_io_fix(bpage) != BUF_IO_NONE) { - /* Block is already IO-fixed. We don't - want to change the value. Lets leave - this block alone. */ - continue; + if (bpage->oldest_modification != 0) { + buf_flush_remove(bpage); } - buf_flush_list_mutex_exit(buf_pool); - block_mutex = buf_page_get_mutex(bpage); - mutex_enter(block_mutex); - buf_page_set_sticky(bpage); - mutex_exit(block_mutex); + ut_ad(!bpage->in_flush_list); - /* Now it is safe to release the buf_pool->mutex. */ - buf_pool_mutex_exit(buf_pool); - os_thread_yield(); - buf_pool_mutex_enter(buf_pool); + /* Remove from the LRU list. */ - mutex_enter(block_mutex); - buf_page_unset_sticky(bpage); - mutex_exit(block_mutex); + if (buf_LRU_block_remove_hashed_page(bpage, TRUE) + != BUF_BLOCK_ZIP_FREE) { - buf_flush_list_mutex_enter(buf_pool); - ut_ad(bpage->in_flush_list); + buf_LRU_block_free_hashed_page((buf_block_t*) bpage); + mutex_exit(block_mutex); + + } else { + /* The block_mutex should have been released + by buf_LRU_block_remove_hashed_page() when it + returns BUF_BLOCK_ZIP_FREE. */ + ut_ad(block_mutex == &buf_pool->zip_mutex); + } - i = 0; + ut_ad(!mutex_own(block_mutex)); + +next_page: + bpage = prev_bpage; } buf_pool_mutex_exit(buf_pool); - buf_flush_list_mutex_exit(buf_pool); - - ut_ad(buf_flush_validate(buf_pool)); if (!all_freed) { os_thread_sleep(20000); @@ -467,28 +707,46 @@ next_page: } /******************************************************************//** -Invalidates all pages belonging to a given tablespace when we are deleting -the data file(s) of that tablespace. */ +Removes all pages belonging to a given tablespace. */ UNIV_INTERN void -buf_LRU_invalidate_tablespace( +buf_LRU_flush_or_remove_pages( /*==========================*/ - ulint id) /*!< in: space id */ + ulint id, /*!< in: space id */ + enum buf_remove_t buf_remove)/*!< in: remove or flush + strategy */ { - ulint i; + ulint i; - /* Before we attempt to drop pages one by one we first - attempt to drop page hash index entries in batches to make - it more efficient. The batching attempt is a best effort - attempt and does not guarantee that all pages hash entries - will be dropped. We get rid of remaining page hash entries - one by one below. */ for (i = 0; i < srv_buf_pool_instances; i++) { buf_pool_t* buf_pool; buf_pool = buf_pool_from_array(i); - buf_LRU_drop_page_hash_for_tablespace(buf_pool, id); - buf_LRU_remove_dirty_pages_for_tablespace(buf_pool, id); + + switch (buf_remove) { + case BUF_REMOVE_ALL_NO_WRITE: + /* A DISCARD tablespace case. Remove AHI entries + and evict all pages from LRU. */ + + /* Before we attempt to drop pages hash entries + one by one we first attempt to drop page hash + index entries in batches to make it more + efficient. The batching attempt is a best effort + attempt and does not guarantee that all pages + hash entries will be dropped. We get rid of + remaining page hash entries one by one below. */ + buf_LRU_drop_page_hash_for_tablespace(buf_pool, id); + buf_LRU_remove_all_pages(buf_pool, id); + break; + + case BUF_REMOVE_FLUSH_NO_WRITE: + /* A DROP table case. AHI entries are already + removed. No need to evict all pages from LRU + list. Just evict pages from flush list without + writing. */ + buf_flush_dirty_pages(buf_pool, id); + break; + } } } diff --git a/storage/innobase/fil/fil0fil.c b/storage/innobase/fil/fil0fil.c index d8ad5c4f432..2390333b393 100644 --- a/storage/innobase/fil/fil0fil.c +++ b/storage/innobase/fil/fil0fil.c @@ -2159,7 +2159,7 @@ fil_op_log_parse_or_replay( switch (type) { case MLOG_FILE_DELETE: if (fil_tablespace_exists_in_mem(space_id)) { - ut_a(fil_delete_tablespace(space_id)); + ut_a(fil_delete_tablespace(space_id, TRUE)); } break; @@ -2229,7 +2229,9 @@ UNIV_INTERN ibool fil_delete_tablespace( /*==================*/ - ulint id) /*!< in: space id */ + ulint id, /*!< in: space id */ + ibool evict_all) /*!< in: TRUE if we want all pages + evicted from LRU. */ { ibool success; fil_space_t* space; @@ -2351,7 +2353,10 @@ try_again: completely and permanently. The flag is_being_deleted also prevents fil_flush() from being applied to this tablespace. */ - buf_LRU_invalidate_tablespace(id); + buf_LRU_flush_or_remove_pages( + id, evict_all + ? BUF_REMOVE_ALL_NO_WRITE + : BUF_REMOVE_FLUSH_NO_WRITE); #endif /* printf("Deleting tablespace %s id %lu\n", space->name, id); */ @@ -2439,7 +2444,7 @@ fil_discard_tablespace( { ibool success; - success = fil_delete_tablespace(id); + success = fil_delete_tablespace(id, TRUE); if (!success) { fprintf(stderr, diff --git a/storage/innobase/handler/ha_innodb.cc b/storage/innobase/handler/ha_innodb.cc index 9625fdab8e9..dcfac0e0205 100644 --- a/storage/innobase/handler/ha_innodb.cc +++ b/storage/innobase/handler/ha_innodb.cc @@ -1450,70 +1450,87 @@ values we want to reserve for multi-value inserts e.g., INSERT INTO T VALUES(), (), (); -innobase_next_autoinc() will be called with increment set to -n * 3 where autoinc_lock_mode != TRADITIONAL because we want -to reserve 3 values for the multi-value INSERT above. +innobase_next_autoinc() will be called with increment set to 3 where +autoinc_lock_mode != TRADITIONAL because we want to reserve 3 values for +the multi-value INSERT above. @return the next value */ static ulonglong innobase_next_autoinc( /*==================*/ ulonglong current, /*!< in: Current value */ - ulonglong increment, /*!< in: increment current by */ + ulonglong need, /*!< in: count of values needed */ + ulonglong step, /*!< in: AUTOINC increment step */ ulonglong offset, /*!< in: AUTOINC offset */ ulonglong max_value) /*!< in: max value for type */ { ulonglong next_value; + ulonglong block = need * step; /* Should never be 0. */ - ut_a(increment > 0); + ut_a(need > 0); + ut_a(block > 0); + ut_a(max_value > 0); + + /* Current value should never be greater than the maximum. */ + ut_a(current <= max_value); /* According to MySQL documentation, if the offset is greater than - the increment then the offset is ignored. */ - if (offset > increment) { + the step then the offset is ignored. */ + if (offset > block) { offset = 0; } - if (max_value <= current) { + /* Check for overflow. */ + if (block >= max_value + || offset > max_value + || current == max_value + || max_value - offset <= offset) { + next_value = max_value; - } else if (offset <= 1) { - /* Offset 0 and 1 are the same, because there must be at - least one node in the system. */ - if (max_value - current <= increment) { + } else { + ut_a(max_value > current); + + ulonglong free = max_value - current; + + if (free < offset || free - offset <= block) { next_value = max_value; } else { - next_value = current + increment; + next_value = 0; } - } else if (max_value > current) { + } + + if (next_value == 0) { + ulonglong next; + if (current > offset) { - next_value = ((current - offset) / increment) + 1; + next = (current - offset) / step; } else { - next_value = ((offset - current) / increment) + 1; + next = (offset - current) / step; } - ut_a(increment > 0); - ut_a(next_value > 0); - + ut_a(max_value > next); + next_value = next * step; /* Check for multiplication overflow. */ - if (increment > (max_value / next_value)) { + ut_a(next_value >= next); + ut_a(max_value > next_value); - next_value = max_value; - } else { - next_value *= increment; + /* Check for overflow */ + if (max_value - next_value >= block) { - ut_a(max_value >= next_value); + next_value += block; - /* Check for overflow. */ - if (max_value - next_value <= offset) { - next_value = max_value; - } else { + if (max_value - next_value >= offset) { next_value += offset; + } else { + next_value = max_value; } + } else { + next_value = max_value; } - } else { - next_value = max_value; } + ut_a(next_value != 0); ut_a(next_value <= max_value); return(next_value); @@ -3749,7 +3766,7 @@ ha_innobase::innobase_initialize_autoinc() nor the offset, so use a default increment of 1. */ auto_inc = innobase_next_autoinc( - read_auto_inc, 1, 1, col_max_value); + read_auto_inc, 1, 1, 0, col_max_value); break; } @@ -5249,15 +5266,16 @@ set_max_autoinc: if (auto_inc <= col_max_value) { ut_a(prebuilt->autoinc_increment > 0); - ulonglong need; ulonglong offset; + ulonglong increment; offset = prebuilt->autoinc_offset; - need = prebuilt->autoinc_increment; + increment = prebuilt->autoinc_increment; auto_inc = innobase_next_autoinc( auto_inc, - need, offset, col_max_value); + 1, increment, offset, + col_max_value); err = innobase_set_max_autoinc( auto_inc); @@ -5525,14 +5543,14 @@ ha_innobase::update_row( if (auto_inc <= col_max_value && auto_inc != 0) { - ulonglong need; ulonglong offset; + ulonglong increment; offset = prebuilt->autoinc_offset; - need = prebuilt->autoinc_increment; + increment = prebuilt->autoinc_increment; auto_inc = innobase_next_autoinc( - auto_inc, need, offset, col_max_value); + auto_inc, 1, increment, offset, col_max_value); error = innobase_set_max_autoinc(auto_inc); } @@ -10145,16 +10163,15 @@ ha_innobase::get_auto_increment( /* With old style AUTOINC locking we only update the table's AUTOINC counter after attempting to insert the row. */ if (innobase_autoinc_lock_mode != AUTOINC_OLD_STYLE_LOCKING) { - ulonglong need; ulonglong current; ulonglong next_value; current = *first_value > col_max_value ? autoinc : *first_value; - need = *nb_reserved_values * increment; /* Compute the last value in the interval */ next_value = innobase_next_autoinc( - current, need, offset, col_max_value); + current, *nb_reserved_values, increment, offset, + col_max_value); prebuilt->autoinc_last_value = next_value; diff --git a/storage/innobase/include/buf0lru.h b/storage/innobase/include/buf0lru.h index eb40621abbe..9ecb9de2afe 100644 --- a/storage/innobase/include/buf0lru.h +++ b/storage/innobase/include/buf0lru.h @@ -64,15 +64,14 @@ These are low-level functions #define BUF_LRU_FREE_SEARCH_LEN(b) (5 + 2 * BUF_READ_AHEAD_AREA(b)) /******************************************************************//** -Invalidates all pages belonging to a given tablespace when we are deleting -the data file(s) of that tablespace. A PROBLEM: if readahead is being started, -what guarantees that it will not try to read in pages after this operation has -completed? */ +Removes all pages belonging to a given tablespace. */ UNIV_INTERN void -buf_LRU_invalidate_tablespace( +buf_LRU_flush_or_remove_pages( /*==========================*/ - ulint id); /*!< in: space id */ + ulint id, /*!< in: space id */ + enum buf_remove_t buf_remove);/*!< in: remove or flush + strategy */ #if defined UNIV_DEBUG || defined UNIV_BUF_DEBUG /********************************************************************//** Insert a compressed block into buf_pool->zip_clean in the LRU order. */ diff --git a/storage/innobase/include/buf0types.h b/storage/innobase/include/buf0types.h index 12b9e22f673..2916f39f3fe 100644 --- a/storage/innobase/include/buf0types.h +++ b/storage/innobase/include/buf0types.h @@ -63,6 +63,15 @@ enum buf_io_fix { the flush_list */ }; +/** Algorithm to remove the pages for a tablespace from the buffer pool. +@See buf_LRU_flush_or_remove_pages(). */ +enum buf_remove_t { + BUF_REMOVE_ALL_NO_WRITE, /*!< Remove all pages from the buffer + pool, don't write or sync to disk */ + BUF_REMOVE_FLUSH_NO_WRITE /*!< Remove only, from the flush list, + don't write or sync to disk */ +}; + /** Parameters of binary buddy system for compressed pages (buf0buddy.h) */ /* @{ */ #define BUF_BUDDY_LOW_SHIFT PAGE_ZIP_MIN_SIZE_SHIFT diff --git a/storage/innobase/include/fil0fil.h b/storage/innobase/include/fil0fil.h index bd9d6e6ebba..610bd4b0e5c 100644 --- a/storage/innobase/include/fil0fil.h +++ b/storage/innobase/include/fil0fil.h @@ -397,7 +397,9 @@ UNIV_INTERN ibool fil_delete_tablespace( /*==================*/ - ulint id); /*!< in: space id */ + ulint id, /*!< in: space id */ + ibool evict_all); /*!< in: TRUE if we want all pages + evicted from LRU. */ #ifndef UNIV_HOTBACKUP /*******************************************************************//** Discards a single-table tablespace. The tablespace must be cached in the diff --git a/storage/innobase/include/trx0purge.h b/storage/innobase/include/trx0purge.h index 0b83a76cab7..2bd9e64476b 100644 --- a/storage/innobase/include/trx0purge.h +++ b/storage/innobase/include/trx0purge.h @@ -143,9 +143,9 @@ struct trx_purge_struct{ obtaining an s-latch here. */ read_view_t* view; /*!< The purge will not remove undo logs which are >= this view (purge view) */ - ulint n_pages_handled;/*!< Approximate number of undo log + ulonglong n_pages_handled;/*!< Approximate number of undo log pages processed in purge */ - ulint handle_limit; /*!< Target of how many pages to get + ulonglong handle_limit; /*!< Target of how many pages to get processed in the current purge */ /*------------------------------*/ /* The following two fields form the 'purge pointer' which advances diff --git a/storage/innobase/row/row0mysql.c b/storage/innobase/row/row0mysql.c index 73666d59742..20e8c13ea70 100644 --- a/storage/innobase/row/row0mysql.c +++ b/storage/innobase/row/row0mysql.c @@ -1999,7 +1999,8 @@ err_exit: case DB_TOO_MANY_CONCURRENT_TRXS: /* We already have .ibd file here. it should be deleted. */ - if (table->space && !fil_delete_tablespace(table->space)) { + if (table->space && !fil_delete_tablespace(table->space, + FALSE)) { ut_print_timestamp(stderr); fprintf(stderr, " InnoDB: Error: not able to" @@ -3438,7 +3439,7 @@ check_next_foreign: "InnoDB: of table "); ut_print_name(stderr, trx, TRUE, name); fprintf(stderr, ".\n"); - } else if (!fil_delete_tablespace(space_id)) { + } else if (!fil_delete_tablespace(space_id, FALSE)) { fprintf(stderr, "InnoDB: We removed now the InnoDB" " internal data dictionary entry\n" diff --git a/storage/innobase/trx/trx0purge.c b/storage/innobase/trx/trx0purge.c index 2370d3deab0..96f01ea81b5 100644 --- a/storage/innobase/trx/trx0purge.c +++ b/storage/innobase/trx/trx0purge.c @@ -1202,7 +1202,7 @@ trx_purge( (ulong) purge_sys->n_pages_handled); } - return(purge_sys->n_pages_handled - old_pages_handled); + return((ulint) (purge_sys->n_pages_handled - old_pages_handled)); } /******************************************************************//** diff --git a/storage/perfschema/pfs_instr.cc b/storage/perfschema/pfs_instr.cc index a877ea61198..c83628cb7cd 100644 --- a/storage/perfschema/pfs_instr.cc +++ b/storage/perfschema/pfs_instr.cc @@ -1,4 +1,4 @@ -/* Copyright (c) 2008, 2010, Oracle and/or its affiliates. All rights reserved. +/* Copyright (c) 2008, 2012, Oracle and/or its affiliates. All rights reserved. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -802,6 +802,22 @@ void destroy_thread(PFS_thread *pfs) } /** + Get the hash pins for @filename_hash. + @param thread The running thread. + @returns The LF_HASH pins for the thread. +*/ +LF_PINS* get_filename_hash_pins(PFS_thread *thread) +{ + if (unlikely(thread->m_filename_hash_pins == NULL)) + { + if (! filename_hash_inited) + return NULL; + thread->m_filename_hash_pins= lf_hash_get_pins(&filename_hash); + } + return thread->m_filename_hash_pins; +} + +/** Find or create instrumentation for a file instance by file name. @param thread the executing instrumented thread @param klass the file class @@ -816,23 +832,13 @@ find_or_create_file(PFS_thread *thread, PFS_file_class *klass, PFS_file *pfs; PFS_scan scan; - if (! filename_hash_inited) + LF_PINS *pins= get_filename_hash_pins(thread); + if (unlikely(pins == NULL)) { - /* File instrumentation can be turned off. */ file_lost++; return NULL; } - if (unlikely(thread->m_filename_hash_pins == NULL)) - { - thread->m_filename_hash_pins= lf_hash_get_pins(&filename_hash); - if (unlikely(thread->m_filename_hash_pins == NULL)) - { - file_lost++; - return NULL; - } - } - char safe_buffer[FN_REFLEN]; const char *safe_filename; @@ -904,7 +910,7 @@ find_or_create_file(PFS_thread *thread, PFS_file_class *klass, /* Append the unresolved file name to the resolved path */ char *ptr= buffer + strlen(buffer); char *buf_end= &buffer[sizeof(buffer)-1]; - if (buf_end > ptr) + if ((buf_end > ptr) && (*(ptr-1) != FN_LIBCHAR)) *ptr++= FN_LIBCHAR; if (buf_end > ptr) strncpy(ptr, safe_filename + dirlen, buf_end - ptr); @@ -918,16 +924,18 @@ find_or_create_file(PFS_thread *thread, PFS_file_class *klass, const uint retry_max= 3; search: entry= reinterpret_cast<PFS_file**> - (lf_hash_search(&filename_hash, thread->m_filename_hash_pins, + (lf_hash_search(&filename_hash, pins, normalized_filename, normalized_length)); if (entry && (entry != MY_ERRPTR)) { pfs= *entry; pfs->m_file_stat.m_open_count++; - lf_hash_search_unpin(thread->m_filename_hash_pins); + lf_hash_search_unpin(pins); return pfs; } + lf_hash_search_unpin(pins); + /* filename is not constant, just using it for noise on create */ uint random= randomized_index(filename, file_max); @@ -954,7 +962,7 @@ search: reset_single_stat_link(&pfs->m_wait_stat); int res; - res= lf_hash_insert(&filename_hash, thread->m_filename_hash_pins, + res= lf_hash_insert(&filename_hash, pins, &pfs); if (likely(res == 0)) { @@ -1006,9 +1014,12 @@ void release_file(PFS_file *pfs) void destroy_file(PFS_thread *thread, PFS_file *pfs) { DBUG_ASSERT(thread != NULL); - DBUG_ASSERT(thread->m_filename_hash_pins != NULL); DBUG_ASSERT(pfs != NULL); - lf_hash_delete(&filename_hash, thread->m_filename_hash_pins, + + LF_PINS *pins= get_filename_hash_pins(thread); + DBUG_ASSERT(pins != NULL); + + lf_hash_delete(&filename_hash, pins, pfs->m_filename, pfs->m_filename_length); pfs->m_lock.allocated_to_free(); } |