=== modified file 'storage/innobase/ibuf/ibuf0ibuf.c' --- storage/innobase/ibuf/ibuf0ibuf.c revid:marko.makela@oracle.com-20100809085837-s1nfx6gjf7l6ttab +++ storage/innobase/ibuf/ibuf0ibuf.c 2010-08-09 12:52:41 +0000 @@ -2484,7 +2484,6 @@ ibuf_contract_ext( ulint page_nos[IBUF_MAX_N_PAGES_MERGED]; ulint space_ids[IBUF_MAX_N_PAGES_MERGED]; ib_int64_t space_versions[IBUF_MAX_N_PAGES_MERGED]; - ulint n_stored; ulint sum_sizes; mtr_t mtr; @@ -2493,7 +2492,7 @@ ibuf_contract_ext( mutex_enter(&ibuf_mutex); - if (ibuf->empty) { + if (UNIV_UNLIKELY(ibuf->empty)) { mutex_exit(&ibuf_mutex); ibuf_is_empty: @@ -2523,7 +2522,6 @@ ibuf_is_empty: position within the leaf */ btr_pcur_open_at_rnd_pos(ibuf->index, BTR_SEARCH_LEAF, &pcur, &mtr); - mutex_exit(&ibuf_mutex); ut_ad(page_validate(btr_pcur_get_page(&pcur), ibuf->index)); @@ -2535,6 +2533,7 @@ ibuf_is_empty: in the loop in ibuf_contract_for_n_pages. */ ibuf->empty = TRUE; + mutex_exit(&ibuf_mutex); ibuf_exit(); @@ -2544,12 +2543,13 @@ ibuf_is_empty: goto ibuf_is_empty; } + mutex_exit(&ibuf_mutex); sum_sizes = ibuf_get_merge_page_nos(TRUE, btr_pcur_get_rec(&pcur), space_ids, space_versions, - page_nos, &n_stored); + page_nos, n_pages); #if 0 /* defined UNIV_IBUF_DEBUG */ fprintf(stderr, "Ibuf contract sync %lu pages %lu volume %lu\n", - sync, n_stored, sum_sizes); + sync, *n_pages, sum_sizes); #endif ibuf_exit(); @@ -2557,8 +2557,7 @@ ibuf_is_empty: btr_pcur_close(&pcur); buf_read_ibuf_merge_pages(sync, space_ids, space_versions, page_nos, - n_stored); - *n_pages = n_stored; + *n_pages); return(sum_sizes + 1); } @@ -2628,33 +2627,33 @@ ibuf_contract_after_insert( ibool sync; ulint sum_sizes; ulint size; + ulint max_size; - mutex_enter(&ibuf_mutex); - - if (ibuf->size < ibuf->max_size + IBUF_CONTRACT_ON_INSERT_NON_SYNC) { - mutex_exit(&ibuf_mutex); + /* Perform dirty reads of ibuf->size and ibuf->max_size, to + reduce ibuf_mutex contention. ibuf->max_size remains constant + after ibuf_init_at_db_start(), but ibuf->size should be + protected by ibuf_mutex. Given that ibuf->size fits in a + machine word, this should be OK; at worst we are doing some + excessive ibuf_contract() or occasionally skipping a + ibuf_contract(). */ + size = ibuf->size; + max_size = ibuf->max_size; + if (size < max_size + IBUF_CONTRACT_ON_INSERT_NON_SYNC) { return; } - sync = FALSE; - - if (ibuf->size >= ibuf->max_size + IBUF_CONTRACT_ON_INSERT_SYNC) { - - sync = TRUE; - } - - mutex_exit(&ibuf_mutex); + sync = (size >= max_size + IBUF_CONTRACT_ON_INSERT_SYNC); /* Contract at least entry_size many bytes */ sum_sizes = 0; size = 1; - while ((size > 0) && (sum_sizes < entry_size)) { + do { size = ibuf_contract(sync); sum_sizes += size; - } + } while (size > 0 && sum_sizes < entry_size); } /*********************************************************************//** @@ -3311,7 +3310,6 @@ ibuf_insert_low( ulint n_stored; mtr_t mtr; mtr_t bitmap_mtr; - ibool too_big; ut_a(!dict_index_is_clust(index)); ut_ad(dtuple_check_typed(entry)); @@ -3323,11 +3321,14 @@ ibuf_insert_low( do_merge = FALSE; - mutex_enter(&ibuf_mutex); - too_big = ibuf->size >= ibuf->max_size + IBUF_CONTRACT_DO_NOT_INSERT; - mutex_exit(&ibuf_mutex); - - if (too_big) { + /* Perform dirty reads of ibuf->size and ibuf->max_size, to + reduce ibuf_mutex contention. ibuf->max_size remains constant + after ibuf_init_at_db_start(), but ibuf->size should be + protected by ibuf_mutex. Given that ibuf->size fits in a + machine word, this should be OK; at worst we are doing some + excessive ibuf_contract() or occasionally skipping a + ibuf_contract(). */ + if (ibuf->size >= ibuf->max_size + IBUF_CONTRACT_DO_NOT_INSERT) { /* Insert buffer is now too big, contract it but do not try to insert */ @@ -3538,6 +3539,7 @@ bitmap_fail: thr_get_trx(thr)->id, &mtr); } + /* The following updates ibuf->empty as well. */ ibuf_size_update(root, &mtr); } @@ -3566,14 +3568,14 @@ function_exit: mem_heap_free(heap); if (err == DB_SUCCESS) { - mutex_enter(&ibuf_mutex); - - ibuf->empty = FALSE; - - mutex_exit(&ibuf_mutex); - if (mode == BTR_MODIFY_TREE) { ibuf_contract_after_insert(entry_size); + } else { + /* For BTR_MODIFY_TREE, ibuf->empty was + already set in ibuf_size_update(). */ + mutex_enter(&ibuf_mutex); + ibuf->empty = FALSE; + mutex_exit(&ibuf_mutex); } } @@ -4108,6 +4110,7 @@ ibuf_delete_rec( if (!ibuf_restore_pos(space, page_no, search_tuple, BTR_MODIFY_TREE, pcur, mtr)) { + mutex_exit(&ibuf_mutex); goto func_exit; } @@ -4121,10 +4124,10 @@ ibuf_delete_rec( ibuf_count_set(space, page_no, ibuf_count_get(space, page_no) - 1); #endif ibuf_size_update(root, mtr); + mutex_exit(&ibuf_mutex); btr_pcur_commit_specify_mtr(pcur, mtr); func_exit: - mutex_exit(&ibuf_mutex); btr_pcur_close(pcur); return(TRUE);