void buf_LRU_print(void) /*===============*/ { buf_block_t* block; buf_frame_t* frame; ulint len; ut_ad(buf_pool); mutex_enter(&(buf_pool->mutex)); fprintf(stderr, "Pool ulint clock %lu\n", (ulong) buf_pool->ulint_clock); block = UT_LIST_GET_FIRST(buf_pool->LRU); len = 0; while (block != NULL) { fprintf(stderr, "BLOCK %lu ", (ulong) block->offset); if (block->old) { fputs("old ", stderr); } if (block->buf_fix_count) { fprintf(stderr, "buffix count %lu ", (ulong) block->buf_fix_count); } if (block->io_fix) { fprintf(stderr, "io_fix %lu ", (ulong) block->io_fix); } if (ut_dulint_cmp(block->oldest_modification, ut_dulint_zero) > 0) { fputs("modif. ", stderr); } frame = buf_block_get_frame(block); fprintf(stderr, "LRU pos %lu type %lu index id %lu ", (ulong) block->LRU_position, (ulong) fil_page_get_type(frame), (ulong) ut_dulint_get_low (btr_page_get_index_id(frame))); block = UT_LIST_GET_NEXT(LRU, block); if (++len == 10) { len = 0; putc('\n', stderr); } } mutex_exit(&(buf_pool->mutex)); }
/*********************************************************//** Moves the persistent cursor to the first record on the next page. Releases the latch on the current page, and bufferunfixes it. Note that there must not be modifications on the current page, as then the x-latch can be released only in mtr_commit. */ UNIV_INTERN void btr_pcur_move_to_next_page( /*=======================*/ btr_pcur_t* cursor, /*!< in: persistent cursor; must be on the last record of the current page */ mtr_t* mtr) /*!< in: mtr */ { ulint next_page_no; ulint space; ulint zip_size; page_t* page; buf_block_t* next_block; page_t* next_page; ut_a(cursor->pos_state == BTR_PCUR_IS_POSITIONED); ut_ad(cursor->latch_mode != BTR_NO_LATCHES); ut_ad(btr_pcur_is_after_last_on_page(cursor)); cursor->old_stored = BTR_PCUR_OLD_NOT_STORED; page = btr_pcur_get_page(cursor); next_page_no = btr_page_get_next(page, mtr); space = buf_block_get_space(btr_pcur_get_block(cursor)); zip_size = buf_block_get_zip_size(btr_pcur_get_block(cursor)); ut_ad(next_page_no != FIL_NULL); next_block = btr_block_get(space, zip_size, next_page_no, cursor->latch_mode, btr_pcur_get_btr_cur(cursor)->index, mtr); next_page = buf_block_get_frame(next_block); if (srv_pass_corrupt_table && !next_page) { btr_leaf_page_release(btr_pcur_get_block(cursor), cursor->latch_mode, mtr); btr_pcur_get_page_cur(cursor)->block = 0; btr_pcur_get_page_cur(cursor)->rec = 0; return; } ut_a(next_page); #ifdef UNIV_BTR_DEBUG ut_a(page_is_comp(next_page) == page_is_comp(page)); ut_a(btr_page_get_prev(next_page, mtr) == buf_block_get_page_no(btr_pcur_get_block(cursor))); #endif /* UNIV_BTR_DEBUG */ next_block->check_index_page_at_flush = TRUE; btr_leaf_page_release(btr_pcur_get_block(cursor), cursor->latch_mode, mtr); page_cur_set_before_first(next_block, btr_pcur_get_page_cur(cursor)); page_check_dir(next_page); }
/**********************************************************************//** Gets a pointer to the dictionary header and x-latches its page. @return pointer to the dictionary header, page x-latched */ UNIV_INTERN dict_hdr_t* dict_hdr_get( /*=========*/ mtr_t* mtr) /*!< in: mtr */ { buf_block_t* block; dict_hdr_t* header; block = buf_page_get(DICT_HDR_SPACE, 0, DICT_HDR_PAGE_NO, RW_X_LATCH, mtr); header = DICT_HDR + buf_block_get_frame(block); buf_block_dbg_add_level(block, SYNC_DICT_HEADER); return(header); }
/*******************************************************************//** Fills the "lock_data" member of i_s_locks_row_t object. If memory can not be allocated then FALSE is returned. @return FALSE if allocation fails */ static ibool fill_lock_data( /*===========*/ const char** lock_data,/*!< out: "lock_data" to fill */ const lock_t* lock, /*!< in: lock used to find the data */ ulint heap_no,/*!< in: rec num used to find the data */ trx_i_s_cache_t* cache) /*!< in/out: cache where to store volatile data */ { mtr_t mtr; const buf_block_t* block; const page_t* page; const rec_t* rec; ut_a(lock_get_type(lock) == LOCK_REC); mtr_start(&mtr); block = buf_page_try_get(lock_rec_get_space_id(lock), lock_rec_get_page_no(lock), &mtr); if (block == NULL) { *lock_data = NULL; mtr_commit(&mtr); return(TRUE); } page = (const page_t*) buf_block_get_frame(block); rec = page_find_rec_with_heap_no(page, heap_no); if (page_rec_is_infimum(rec)) { *lock_data = ha_storage_put_str_memlim( cache->storage, "infimum pseudo-record", MAX_ALLOWED_FOR_STORAGE(cache)); } else if (page_rec_is_supremum(rec)) { *lock_data = ha_storage_put_str_memlim( cache->storage, "supremum pseudo-record", MAX_ALLOWED_FOR_STORAGE(cache)); } else { const dict_index_t* index; ulint n_fields; mem_heap_t* heap; ulint offsets_onstack[REC_OFFS_NORMAL_SIZE]; ulint* offsets; char buf[TRX_I_S_LOCK_DATA_MAX_LEN]; ulint buf_used; ulint i; rec_offs_init(offsets_onstack); offsets = offsets_onstack; index = lock_rec_get_index(lock); n_fields = dict_index_get_n_unique(index); ut_a(n_fields > 0); heap = NULL; offsets = rec_get_offsets(rec, index, offsets, n_fields, &heap); /* format and store the data */ buf_used = 0; for (i = 0; i < n_fields; i++) { buf_used += put_nth_field( buf + buf_used, sizeof(buf) - buf_used, i, index, rec, offsets) - 1; } *lock_data = (const char*) ha_storage_put_memlim( cache->storage, buf, buf_used + 1, MAX_ALLOWED_FOR_STORAGE(cache)); if (UNIV_UNLIKELY(heap != NULL)) { /* this means that rec_get_offsets() has created a new heap and has stored offsets in it; check that this is really the case and free the heap */ ut_a(offsets != offsets_onstack); mem_heap_free(heap); } } mtr_commit(&mtr); if (*lock_data == NULL) { return(FALSE); } return(TRUE); }
/***********************************************************//** Purges an update of an existing record. Also purges an update of a delete marked record if that record contained an externally stored field. */ static void row_purge_upd_exist_or_extern_func( /*===============================*/ #ifdef UNIV_DEBUG const que_thr_t*thr, /*!< in: query thread */ #endif /* UNIV_DEBUG */ purge_node_t* node) /*!< in: row purge node */ { mem_heap_t* heap; dtuple_t* entry; dict_index_t* index; ibool is_insert; ulint rseg_id; ulint page_no; ulint offset; ulint i; mtr_t mtr; ut_ad(node); if (node->rec_type == TRX_UNDO_UPD_DEL_REC || (node->cmpl_info & UPD_NODE_NO_ORD_CHANGE)) { goto skip_secondaries; } heap = mem_heap_create(1024); while (node->index != NULL) { dict_table_skip_corrupt_index(node->index); if (!node->index) { break; } index = node->index; if (row_upd_changes_ord_field_binary(node->index, node->update, thr, NULL, NULL)) { /* Build the older version of the index entry */ entry = row_build_index_entry(node->row, NULL, index, heap); ut_a(entry); row_purge_remove_sec_if_poss(node, index, entry); } node->index = dict_table_get_next_index(node->index); } mem_heap_free(heap); skip_secondaries: /* Free possible externally stored fields */ for (i = 0; i < upd_get_n_fields(node->update); i++) { const upd_field_t* ufield = upd_get_nth_field(node->update, i); if (dfield_is_ext(&ufield->new_val)) { buf_block_t* block; ulint internal_offset; byte* data_field; /* We use the fact that new_val points to node->undo_rec and get thus the offset of dfield data inside the undo record. Then we can calculate from node->roll_ptr the file address of the new_val data */ internal_offset = ((const byte*) dfield_get_data(&ufield->new_val)) - node->undo_rec; ut_a(internal_offset < UNIV_PAGE_SIZE); trx_undo_decode_roll_ptr(node->roll_ptr, &is_insert, &rseg_id, &page_no, &offset); mtr_start(&mtr); /* We have to acquire an X-latch to the clustered index tree */ index = dict_table_get_first_index(node->table); mtr_x_lock(dict_index_get_lock(index), &mtr); /* NOTE: we must also acquire an X-latch to the root page of the tree. We will need it when we free pages from the tree. If the tree is of height 1, the tree X-latch does NOT protect the root page, because it is also a leaf page. Since we will have a latch on an undo log page, we would break the latching order if we would only later latch the root page of such a tree! */ btr_root_get(index, &mtr); /* We assume in purge of externally stored fields that the space id of the undo log record is 0! */ block = buf_page_get(0, 0, page_no, RW_X_LATCH, &mtr); buf_block_dbg_add_level(block, SYNC_TRX_UNDO_PAGE); data_field = buf_block_get_frame(block) + offset + internal_offset; ut_a(dfield_get_len(&ufield->new_val) >= BTR_EXTERN_FIELD_REF_SIZE); btr_free_externally_stored_field( index, data_field + dfield_get_len(&ufield->new_val) - BTR_EXTERN_FIELD_REF_SIZE, NULL, NULL, NULL, 0, RB_NONE, &mtr); mtr_commit(&mtr); } } }