📄 ibuf0ibuf.c
字号:
/ IBUF_MERGE_THRESHOLD)) { space_ids[*n_stored] = prev_space_id; space_versions[*n_stored] = fil_space_get_version( prev_space_id); page_nos[*n_stored] = prev_page_no; (*n_stored)++; sum_volumes += volume_for_page; } if (rec_space_id != first_space_id || rec_page_no / IBUF_MERGE_AREA != first_page_no / IBUF_MERGE_AREA) { break; } volume_for_page = 0; } if (rec_page_no == 1 && rec_space_id == 0) { /* Supremum record */ break; } rec_volume = ibuf_rec_get_volume(rec); volume_for_page += rec_volume; prev_page_no = rec_page_no; prev_space_id = rec_space_id; rec = page_rec_get_next(rec); }#ifdef UNIV_IBUF_DEBUG ut_a(*n_stored <= IBUF_MAX_N_PAGES_MERGED);#endif/* fprintf(stderr, "Ibuf merge batch %lu pages %lu volume\n", *n_stored, sum_volumes); */ return(sum_volumes);}/*************************************************************************Contracts insert buffer trees by reading pages to the buffer pool. */staticulintibuf_contract_ext(/*==============*/ /* out: a lower limit for the combined size in bytes of entries which will be merged from ibuf trees to the pages read, 0 if ibuf is empty */ ulint* n_pages,/* out: number of pages to which merged */ ibool sync) /* in: TRUE if the caller wants to wait for the issued read with the highest tablespace address to complete */{ ulint rnd_pos; ibuf_data_t* data; btr_pcur_t pcur; ulint space; ibool all_trees_empty; ulint page_nos[IBUF_MAX_N_PAGES_MERGED]; ulint space_ids[IBUF_MAX_N_PAGES_MERGED]; ib_longlong space_versions[IBUF_MAX_N_PAGES_MERGED]; ulint n_stored; ulint sum_sizes; mtr_t mtr; *n_pages = 0;loop: ut_ad(!ibuf_inside()); mutex_enter(&ibuf_mutex); ut_ad(ibuf_validate_low()); /* Choose an ibuf tree at random (though there really is only one tree in the current implementation) */ ibuf_rnd += 865558671; rnd_pos = ibuf_rnd % ibuf->size; all_trees_empty = TRUE; data = UT_LIST_GET_FIRST(ibuf->data_list); for (;;) { if (!data->empty) { all_trees_empty = FALSE; if (rnd_pos < data->size) { break; } rnd_pos -= data->size; } data = UT_LIST_GET_NEXT(data_list, data); if (data == NULL) { if (all_trees_empty) { mutex_exit(&ibuf_mutex); return(0); } data = UT_LIST_GET_FIRST(ibuf->data_list); } } ut_ad(data); space = data->index->space; ut_a(space == 0); /* We currently only have an ibuf tree in space 0 */ mtr_start(&mtr); ibuf_enter(); /* Open a cursor to a randomly chosen leaf of the tree, at a random position within the leaf */ btr_pcur_open_at_rnd_pos(data->index, BTR_SEARCH_LEAF, &pcur, &mtr); if (0 == page_get_n_recs(btr_pcur_get_page(&pcur))) { /* This tree is empty */ data->empty = TRUE; ibuf_exit(); mtr_commit(&mtr); btr_pcur_close(&pcur); mutex_exit(&ibuf_mutex); goto loop; } 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);#ifdef UNIV_IBUF_DEBUG /* fprintf(stderr, "Ibuf contract sync %lu pages %lu volume %lu\n", sync, n_stored, sum_sizes); */#endif ibuf_exit(); mtr_commit(&mtr); btr_pcur_close(&pcur); buf_read_ibuf_merge_pages(sync, space_ids, space_versions, page_nos, n_stored); *n_pages = n_stored; return(sum_sizes + 1);}/*************************************************************************Contracts insert buffer trees by reading pages to the buffer pool. */ulintibuf_contract(/*==========*/ /* out: a lower limit for the combined size in bytes of entries which will be merged from ibuf trees to the pages read, 0 if ibuf is empty */ ibool sync) /* in: TRUE if the caller wants to wait for the issued read with the highest tablespace address to complete */{ ulint n_pages; return(ibuf_contract_ext(&n_pages, sync));}/*************************************************************************Contracts insert buffer trees by reading pages to the buffer pool. */ulintibuf_contract_for_n_pages(/*======================*/ /* out: a lower limit for the combined size in bytes of entries which will be merged from ibuf trees to the pages read, 0 if ibuf is empty */ ibool sync, /* in: TRUE if the caller wants to wait for the issued read with the highest tablespace address to complete */ ulint n_pages)/* in: try to read at least this many pages to the buffer pool and merge the ibuf contents to them */{ ulint sum_bytes = 0; ulint sum_pages = 0; ulint n_bytes; ulint n_pag2; while (sum_pages < n_pages) { n_bytes = ibuf_contract_ext(&n_pag2, sync); if (n_bytes == 0) { return(sum_bytes); } sum_bytes += n_bytes; sum_pages += n_pag2; } return(sum_bytes);}/*************************************************************************Contract insert buffer trees after insert if they are too big. */UNIV_INLINEvoidibuf_contract_after_insert(/*=======================*/ ulint entry_size) /* in: size of a record which was inserted into an ibuf tree */{ ibool sync; ulint sum_sizes; ulint size; mutex_enter(&ibuf_mutex); if (ibuf->size < ibuf->max_size + IBUF_CONTRACT_ON_INSERT_NON_SYNC) { mutex_exit(&ibuf_mutex); return; } sync = FALSE; if (ibuf->size >= ibuf->max_size + IBUF_CONTRACT_ON_INSERT_SYNC) { sync = TRUE; } mutex_exit(&ibuf_mutex); /* Contract at least entry_size many bytes */ sum_sizes = 0; size = 1; while ((size > 0) && (sum_sizes < entry_size)) { size = ibuf_contract(sync); sum_sizes += size; }}/*************************************************************************Gets an upper limit for the combined size of entries buffered in the insertbuffer for a given page. */ulintibuf_get_volume_buffered(/*=====================*/ /* out: upper limit for the volume of buffered inserts for the index page, in bytes; we may also return UNIV_PAGE_SIZE, if the entries for the index page span on several pages in the insert buffer */ btr_pcur_t* pcur, /* in: pcur positioned at a place in an insert buffer tree where we would insert an entry for the index page whose number is page_no, latch mode has to be BTR_MODIFY_PREV or BTR_MODIFY_TREE */ ulint space, /* in: space id */ ulint page_no,/* in: page number of an index page */ mtr_t* mtr) /* in: mtr */{ ulint volume; rec_t* rec; page_t* page; ulint prev_page_no; page_t* prev_page; ulint next_page_no; page_t* next_page; ut_a(trx_sys_multiple_tablespace_format); ut_ad((pcur->latch_mode == BTR_MODIFY_PREV) || (pcur->latch_mode == BTR_MODIFY_TREE)); /* Count the volume of records earlier in the alphabetical order than pcur */ volume = 0; rec = btr_pcur_get_rec(pcur); page = buf_frame_align(rec); if (page_rec_is_supremum(rec)) { rec = page_rec_get_prev(rec); } for (;;) { if (page_rec_is_infimum(rec)) { break; } if (page_no != ibuf_rec_get_page_no(rec) || space != ibuf_rec_get_space(rec)) { goto count_later; } volume += ibuf_rec_get_volume(rec); rec = page_rec_get_prev(rec); } /* Look at the previous page */ prev_page_no = btr_page_get_prev(page, mtr); if (prev_page_no == FIL_NULL) { goto count_later; } prev_page = buf_page_get(0, prev_page_no, RW_X_LATCH, mtr);#ifdef UNIV_SYNC_DEBUG buf_page_dbg_add_level(prev_page, SYNC_TREE_NODE);#endif /* UNIV_SYNC_DEBUG */ rec = page_get_supremum_rec(prev_page); rec = page_rec_get_prev(rec); for (;;) { if (page_rec_is_infimum(rec)) { /* We cannot go to yet a previous page, because we do not have the x-latch on it, and cannot acquire one because of the latching order: we have to give up */ return(UNIV_PAGE_SIZE); } if (page_no != ibuf_rec_get_page_no(rec) || space != ibuf_rec_get_space(rec)) { goto count_later; } volume += ibuf_rec_get_volume(rec); rec = page_rec_get_prev(rec); } count_later: rec = btr_pcur_get_rec(pcur); if (!page_rec_is_supremum(rec)) { rec = page_rec_get_next(rec); } for (;;) { if (page_rec_is_supremum(rec)) { break; } if (page_no != ibuf_rec_get_page_no(rec) || space != ibuf_rec_get_space(rec)) { return(volume); } volume += ibuf_rec_get_volume(rec); rec = page_rec_get_next(rec); } /* Look at the next page */ next_page_no = btr_page_get_next(page, mtr); if (next_page_no == FIL_NULL) { return(volume); } next_page = buf_page_get(0, next_page_no, RW_X_LATCH, mtr);#ifdef UNIV_SYNC_DEBUG buf_page_dbg_add_level(next_page, SYNC_TREE_NODE);#endif /* UNIV_SYNC_DEBUG */ rec = page_get_infimum_rec(next_page); rec = page_rec_get_next(rec); for (;;) { if (page_rec_is_supremum(rec)) { /* We give up */ return(UNIV_PAGE_SIZE); } if (page_no != ibuf_rec_get_page_no(rec) || space != ibuf_rec_get_space(rec)) { return(volume); } volume += ibuf_rec_get_volume(rec); rec = page_rec_get_next(rec); }}/*************************************************************************Reads the biggest tablespace id from the high end of the insert buffertree and updates the counter in fil_system. */voidibuf_update_max_tablespace_id(void)/*===============================*/{ ulint max_space_id; rec_t* rec; byte* field; ulint len; ibuf_data_t* ibuf_data; dict_index_t* ibuf_index; btr_pcur_t pcur; mtr_t mtr; ibuf_data = fil_space_get_ibuf_data(0); ibuf_index = ibuf_data->index; ut_a(!ibuf_index->table->comp); ibuf_enter(); mtr_start(&mtr); btr_pcur_open_at_index_side(FALSE, ibuf_index, BTR_SEARCH_LEAF, &pcur, TRUE, &mtr); btr_pcur_move_to_prev(&pcur, &mtr); if (btr_pcur_is_before_first_on_page(&pcur, &mtr)) { /* The tree is empty */ max_space_id = 0; } else { rec = btr_pcur_get_rec(&pcur); field = rec_get_nth_field_old(rec, 0, &len); ut_a(len == 4); max_space_id = mach_read_from_4(field); } mtr_commit(&mtr); ibuf_exit(); /* printf("Maximum space id in insert buffer %lu\n", max_space_id); */ fil_set_max_space_id_if_bigger(max_space_id);}/*************************************************************************Makes an index insert to the insert buffer, instead of directly to the diskpage, if this is possible. */staticulintibuf_insert_low(/*============*/ /* out: DB_SUCCESS, DB_FAIL, DB_STRONG_FAIL */ ulint mode, /* in: BTR_MODIFY_PREV or BTR_MODIFY_TREE */ dtuple_t* entry, /* in: index entry to insert */ dict_index_t* index, /* in: index where to insert; must not be unique or clustered */ ulint space, /* in: space id where to insert */ ulint page_no,/* in: page number where to insert */ que_thr_t* thr) /* in: query thread */{ big_rec_t* dummy_big_rec; ulint entry_size;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -