1/***************************************************************************** 2 3Copyright (c) 1994, 2018, Oracle and/or its affiliates. All Rights Reserved. 4 5This program is free software; you can redistribute it and/or modify it under 6the terms of the GNU General Public License, version 2.0, as published by the 7Free Software Foundation. 8 9This program is also distributed with certain software (including but not 10limited to OpenSSL) that is licensed under separate terms, as designated in a 11particular file or component or in included license documentation. The authors 12of MySQL hereby grant you an additional permission to link the program and 13your derivative works with the separately licensed software that they have 14included with MySQL. 15 16This program is distributed in the hope that it will be useful, but WITHOUT 17ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS 18FOR A PARTICULAR PURPOSE. See the GNU General Public License, version 2.0, 19for more details. 20 21You should have received a copy of the GNU General Public License along with 22this program; if not, write to the Free Software Foundation, Inc., 2351 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA 24 25*****************************************************************************/ 26 27/** @file include/btr0cur.ic 28 The index tree cursor 29 30 Created 10/16/1994 Heikki Tuuri 31 *******************************************************/ 32 33#ifndef UNIV_HOTBACKUP 34#endif /* !UNIV_HOTBACKUP */ 35#include "btr0btr.h" 36 37#ifdef UNIV_DEBUG 38#define LIMIT_OPTIMISTIC_INSERT_DEBUG(NREC, CODE) \ 39 if (btr_cur_limit_optimistic_insert_debug > 1 && \ 40 (NREC) >= (ulint)btr_cur_limit_optimistic_insert_debug) { \ 41 CODE; \ 42 } 43#else 44#define LIMIT_OPTIMISTIC_INSERT_DEBUG(NREC, CODE) 45#endif /* UNIV_DEBUG */ 46 47#ifdef UNIV_DEBUG 48/** Returns the page cursor component of a tree cursor. 49 @return pointer to page cursor component */ 50UNIV_INLINE 51page_cur_t *btr_cur_get_page_cur( 52 const btr_cur_t *cursor) /*!< in: tree cursor */ 53{ 54 return (&((btr_cur_t *)cursor)->page_cur); 55} 56 57/** Returns the buffer block on which the tree cursor is positioned. 58 @return pointer to buffer block */ 59UNIV_INLINE 60buf_block_t *btr_cur_get_block(const btr_cur_t *cursor) /*!< in: tree cursor */ 61{ 62 return (page_cur_get_block(btr_cur_get_page_cur(cursor))); 63} 64 65/** Returns the record pointer of a tree cursor. 66 @return pointer to record */ 67UNIV_INLINE 68rec_t *btr_cur_get_rec(const btr_cur_t *cursor) /*!< in: tree cursor */ 69{ 70 return (page_cur_get_rec(btr_cur_get_page_cur(cursor))); 71} 72#endif /* UNIV_DEBUG */ 73 74/** Returns the compressed page on which the tree cursor is positioned. 75 @return pointer to compressed page, or NULL if the page is not compressed */ 76UNIV_INLINE 77page_zip_des_t *btr_cur_get_page_zip(btr_cur_t *cursor) /*!< in: tree cursor */ 78{ 79 return (buf_block_get_page_zip(btr_cur_get_block(cursor))); 80} 81 82/** Returns the page of a tree cursor. 83 @return pointer to page */ 84UNIV_INLINE 85page_t *btr_cur_get_page(btr_cur_t *cursor) /*!< in: tree cursor */ 86{ 87 return (page_align(page_cur_get_rec(&(cursor->page_cur)))); 88} 89 90/** Positions a tree cursor at a given record. */ 91UNIV_INLINE 92void btr_cur_position(dict_index_t *index, /*!< in: index */ 93 rec_t *rec, /*!< in: record in tree */ 94 buf_block_t *block, /*!< in: buffer block of rec */ 95 btr_cur_t *cursor) /*!< out: cursor */ 96{ 97 ut_ad(page_align(rec) == block->frame); 98 99 page_cur_position(rec, block, btr_cur_get_page_cur(cursor)); 100 101 cursor->index = index; 102} 103 104/** Checks if compressing an index page where a btr cursor is placed makes 105 sense. 106 @return true if compression is recommended */ 107UNIV_INLINE 108ibool btr_cur_compress_recommendation(btr_cur_t *cursor, /*!< in: btr cursor */ 109 mtr_t *mtr) /*!< in: mtr */ 110{ 111 const page_t *page; 112 113 ut_ad(mtr_is_block_fix(mtr, btr_cur_get_block(cursor), MTR_MEMO_PAGE_X_FIX, 114 cursor->index->table)); 115 116 page = btr_cur_get_page(cursor); 117 118 LIMIT_OPTIMISTIC_INSERT_DEBUG(page_get_n_recs(page) * 2, return (FALSE)); 119 120 if ((page_get_data_size(page) < BTR_CUR_PAGE_COMPRESS_LIMIT(cursor->index)) || 121 ((btr_page_get_next(page, mtr) == FIL_NULL) && 122 (btr_page_get_prev(page, mtr) == FIL_NULL))) { 123 /* The page fillfactor has dropped below a predefined 124 minimum value OR the level in the B-tree contains just 125 one page: we recommend compression if this is not the 126 root page. */ 127 128 return (dict_index_get_page(cursor->index) != page_get_page_no(page)); 129 } 130 131 return (FALSE); 132} 133 134/** Checks if the record on which the cursor is placed can be deleted without 135 making tree compression necessary (or, recommended). 136 @return true if can be deleted without recommended compression */ 137UNIV_INLINE 138ibool btr_cur_can_delete_without_compress( 139 btr_cur_t *cursor, /*!< in: btr cursor */ 140 ulint rec_size, /*!< in: rec_get_size(btr_cur_get_rec(cursor))*/ 141 mtr_t *mtr) /*!< in: mtr */ 142{ 143 page_t *page; 144 145 ut_ad(mtr_memo_contains(mtr, btr_cur_get_block(cursor), MTR_MEMO_PAGE_X_FIX)); 146 147 page = btr_cur_get_page(cursor); 148 149 if ((page_get_data_size(page) - rec_size < 150 BTR_CUR_PAGE_COMPRESS_LIMIT(cursor->index)) || 151 ((btr_page_get_next(page, mtr) == FIL_NULL) && 152 (btr_page_get_prev(page, mtr) == FIL_NULL)) || 153 (page_get_n_recs(page) < 2)) { 154 /* The page fillfactor will drop below a predefined 155 minimum value, OR the level in the B-tree contains just 156 one page, OR the page will become empty: we recommend 157 compression if this is not the root page. */ 158 159 return (dict_index_get_page(cursor->index) == page_get_page_no(page)); 160 } 161 162 return (TRUE); 163} 164 165UNIV_INLINE 166void btr_rec_set_deleted_flag(rec_t *rec, page_zip_des_t *page_zip, 167 ulint flag) { 168 if (page_rec_is_comp(rec)) { 169 rec_set_deleted_flag_new(rec, page_zip, flag); 170 } else { 171 ut_ad(!page_zip); 172 rec_set_deleted_flag_old(rec, flag); 173 } 174} 175