/***************************************************************************** Copyright (c) 1994, 2009, Innobase Oy. 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 the Free Software Foundation; version 2 of the License. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA *****************************************************************************/ /**************************************************//** @file include/btr0btr.ic The B-tree Created 6/2/1994 Heikki Tuuri *******************************************************/ #include "mach0data.h" #ifndef UNIV_HOTBACKUP #include "mtr0mtr.h" #include "mtr0log.h" #include "page0zip.h" #define BTR_MAX_NODE_LEVEL 50 /*!< Maximum B-tree page level (not really a hard limit). Used in debug assertions in btr_page_set_level and btr_page_get_level_low */ /**************************************************************//** Gets a buffer page and declares its latching order level. */ UNIV_INLINE buf_block_t* btr_block_get( /*==========*/ ulint space, /*!< in: space id */ ulint zip_size, /*!< in: compressed page size in bytes or 0 for uncompressed pages */ ulint page_no, /*!< in: page number */ ulint mode, /*!< in: latch mode */ mtr_t* mtr) /*!< in: mtr */ { buf_block_t* block; block = buf_page_get(space, zip_size, page_no, mode, mtr); if (mode != RW_NO_LATCH) { buf_block_dbg_add_level(block, SYNC_TREE_NODE); } return(block); } /**************************************************************//** Gets a buffer page and declares its latching order level. */ UNIV_INLINE page_t* btr_page_get( /*=========*/ ulint space, /*!< in: space id */ ulint zip_size, /*!< in: compressed page size in bytes or 0 for uncompressed pages */ ulint page_no, /*!< in: page number */ ulint mode, /*!< in: latch mode */ mtr_t* mtr) /*!< in: mtr */ { return(buf_block_get_frame(btr_block_get(space, zip_size, page_no, mode, mtr))); } /**************************************************************//** Sets the index id field of a page. */ UNIV_INLINE void btr_page_set_index_id( /*==================*/ page_t* page, /*!< in: page to be created */ page_zip_des_t* page_zip,/*!< in: compressed page whose uncompressed part will be updated, or NULL */ dulint id, /*!< in: index id */ mtr_t* mtr) /*!< in: mtr */ { if (UNIV_LIKELY_NULL(page_zip)) { mach_write_to_8(page + (PAGE_HEADER + PAGE_INDEX_ID), id); page_zip_write_header(page_zip, page + (PAGE_HEADER + PAGE_INDEX_ID), 8, mtr); } else { mlog_write_dulint(page + (PAGE_HEADER + PAGE_INDEX_ID), id, mtr); } } #endif /* !UNIV_HOTBACKUP */ /**************************************************************//** Gets the index id field of a page. @return index id */ UNIV_INLINE dulint btr_page_get_index_id( /*==================*/ const page_t* page) /*!< in: index page */ { return(mach_read_from_8(page + PAGE_HEADER + PAGE_INDEX_ID)); } #ifndef UNIV_HOTBACKUP /********************************************************//** Gets the node level field in an index page. @return level, leaf level == 0 */ UNIV_INLINE ulint btr_page_get_level_low( /*===================*/ const page_t* page) /*!< in: index page */ { ulint level; ut_ad(page); level = mach_read_from_2(page + PAGE_HEADER + PAGE_LEVEL); ut_ad(level <= BTR_MAX_NODE_LEVEL); return(level); } /********************************************************//** Gets the node level field in an index page. @return level, leaf level == 0 */ UNIV_INLINE ulint btr_page_get_level( /*===============*/ const page_t* page, /*!< in: index page */ mtr_t* mtr __attribute__((unused))) /*!< in: mini-transaction handle */ { ut_ad(page && mtr); return(btr_page_get_level_low(page)); } /********************************************************//** Sets the node level field in an index page. */ UNIV_INLINE void btr_page_set_level( /*===============*/ page_t* page, /*!< in: index page */ page_zip_des_t* page_zip,/*!< in: compressed page whose uncompressed part will be updated, or NULL */ ulint level, /*!< in: level, leaf level == 0 */ mtr_t* mtr) /*!< in: mini-transaction handle */ { ut_ad(page && mtr); ut_ad(level <= BTR_MAX_NODE_LEVEL); if (UNIV_LIKELY_NULL(page_zip)) { mach_write_to_2(page + (PAGE_HEADER + PAGE_LEVEL), level); page_zip_write_header(page_zip, page + (PAGE_HEADER + PAGE_LEVEL), 2, mtr); } else { mlog_write_ulint(page + (PAGE_HEADER + PAGE_LEVEL), level, MLOG_2BYTES, mtr); } } /********************************************************//** Gets the next index page number. @return next page number */ UNIV_INLINE ulint btr_page_get_next( /*==============*/ const page_t* page, /*!< in: index page */ mtr_t* mtr __attribute__((unused))) /*!< in: mini-transaction handle */ { ut_ad(page && mtr); ut_ad(mtr_memo_contains_page(mtr, page, MTR_MEMO_PAGE_X_FIX) || mtr_memo_contains_page(mtr, page, MTR_MEMO_PAGE_S_FIX)); return(mach_read_from_4(page + FIL_PAGE_NEXT)); } /********************************************************//** Sets the next index page field. */ UNIV_INLINE void btr_page_set_next( /*==============*/ page_t* page, /*!< in: index page */ page_zip_des_t* page_zip,/*!< in: compressed page whose uncompressed part will be updated, or NULL */ ulint next, /*!< in: next page number */ mtr_t* mtr) /*!< in: mini-transaction handle */ { ut_ad(page && mtr); if (UNIV_LIKELY_NULL(page_zip)) { mach_write_to_4(page + FIL_PAGE_NEXT, next); page_zip_write_header(page_zip, page + FIL_PAGE_NEXT, 4, mtr); } else { mlog_write_ulint(page + FIL_PAGE_NEXT, next, MLOG_4BYTES, mtr); } } /********************************************************//** Gets the previous index page number. @return prev page number */ UNIV_INLINE ulint btr_page_get_prev( /*==============*/ const page_t* page, /*!< in: index page */ mtr_t* mtr __attribute__((unused))) /*!< in: mini-transaction handle */ { ut_ad(page && mtr); return(mach_read_from_4(page + FIL_PAGE_PREV)); } /********************************************************//** Sets the previous index page field. */ UNIV_INLINE void btr_page_set_prev( /*==============*/ page_t* page, /*!< in: index page */ page_zip_des_t* page_zip,/*!< in: compressed page whose uncompressed part will be updated, or NULL */ ulint prev, /*!< in: previous page number */ mtr_t* mtr) /*!< in: mini-transaction handle */ { ut_ad(page && mtr); if (UNIV_LIKELY_NULL(page_zip)) { mach_write_to_4(page + FIL_PAGE_PREV, prev); page_zip_write_header(page_zip, page + FIL_PAGE_PREV, 4, mtr); } else { mlog_write_ulint(page + FIL_PAGE_PREV, prev, MLOG_4BYTES, mtr); } } /**************************************************************//** Gets the child node file address in a node pointer. @return child node address */ UNIV_INLINE ulint btr_node_ptr_get_child_page_no( /*===========================*/ const rec_t* rec, /*!< in: node pointer record */ const ulint* offsets)/*!< in: array returned by rec_get_offsets() */ { const byte* field; ulint len; ulint page_no; ut_ad(!rec_offs_comp(offsets) || rec_get_node_ptr_flag(rec)); /* The child address is in the last field */ field = rec_get_nth_field(rec, offsets, rec_offs_n_fields(offsets) - 1, &len); ut_ad(len == 4); page_no = mach_read_from_4(field); if (UNIV_UNLIKELY(page_no == 0)) { fprintf(stderr, "InnoDB: a nonsensical page number 0" " in a node ptr record at offset %lu\n", (ulong) page_offset(rec)); buf_page_print(page_align(rec), 0); } return(page_no); } /**************************************************************//** Releases the latches on a leaf page and bufferunfixes it. */ UNIV_INLINE void btr_leaf_page_release( /*==================*/ buf_block_t* block, /*!< in: buffer block */ ulint latch_mode, /*!< in: BTR_SEARCH_LEAF or BTR_MODIFY_LEAF */ mtr_t* mtr) /*!< in: mtr */ { ut_ad(latch_mode == BTR_SEARCH_LEAF || latch_mode == BTR_MODIFY_LEAF); ut_ad(!mtr_memo_contains(mtr, block, MTR_MEMO_MODIFY)); mtr_memo_release(mtr, block, latch_mode == BTR_SEARCH_LEAF ? MTR_MEMO_PAGE_S_FIX : MTR_MEMO_PAGE_X_FIX); } #endif /* !UNIV_HOTBACKUP */