175 lines
5.9 KiB
Plaintext
175 lines
5.9 KiB
Plaintext
/*****************************************************************************
|
|
|
|
Copyright (c) 1994, 2018, Oracle and/or its affiliates. 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, version 2.0, as published by the
|
|
Free Software Foundation.
|
|
|
|
This program is also distributed with certain software (including but not
|
|
limited to OpenSSL) that is licensed under separate terms, as designated in a
|
|
particular file or component or in included license documentation. The authors
|
|
of MySQL hereby grant you an additional permission to link the program and
|
|
your derivative works with the separately licensed software that they have
|
|
included with MySQL.
|
|
|
|
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, version 2.0,
|
|
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.,
|
|
51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
|
|
|
*****************************************************************************/
|
|
|
|
/** @file include/btr0cur.ic
|
|
The index tree cursor
|
|
|
|
Created 10/16/1994 Heikki Tuuri
|
|
*******************************************************/
|
|
|
|
#ifndef UNIV_HOTBACKUP
|
|
#endif /* !UNIV_HOTBACKUP */
|
|
#include "btr0btr.h"
|
|
|
|
#ifdef UNIV_DEBUG
|
|
#define LIMIT_OPTIMISTIC_INSERT_DEBUG(NREC, CODE) \
|
|
if (btr_cur_limit_optimistic_insert_debug > 1 && \
|
|
(NREC) >= (ulint)btr_cur_limit_optimistic_insert_debug) { \
|
|
CODE; \
|
|
}
|
|
#else
|
|
#define LIMIT_OPTIMISTIC_INSERT_DEBUG(NREC, CODE)
|
|
#endif /* UNIV_DEBUG */
|
|
|
|
#ifdef UNIV_DEBUG
|
|
/** Returns the page cursor component of a tree cursor.
|
|
@return pointer to page cursor component */
|
|
UNIV_INLINE
|
|
page_cur_t *btr_cur_get_page_cur(
|
|
const btr_cur_t *cursor) /*!< in: tree cursor */
|
|
{
|
|
return (&((btr_cur_t *)cursor)->page_cur);
|
|
}
|
|
|
|
/** Returns the buffer block on which the tree cursor is positioned.
|
|
@return pointer to buffer block */
|
|
UNIV_INLINE
|
|
buf_block_t *btr_cur_get_block(const btr_cur_t *cursor) /*!< in: tree cursor */
|
|
{
|
|
return (page_cur_get_block(btr_cur_get_page_cur(cursor)));
|
|
}
|
|
|
|
/** Returns the record pointer of a tree cursor.
|
|
@return pointer to record */
|
|
UNIV_INLINE
|
|
rec_t *btr_cur_get_rec(const btr_cur_t *cursor) /*!< in: tree cursor */
|
|
{
|
|
return (page_cur_get_rec(btr_cur_get_page_cur(cursor)));
|
|
}
|
|
#endif /* UNIV_DEBUG */
|
|
|
|
/** Returns the compressed page on which the tree cursor is positioned.
|
|
@return pointer to compressed page, or NULL if the page is not compressed */
|
|
UNIV_INLINE
|
|
page_zip_des_t *btr_cur_get_page_zip(btr_cur_t *cursor) /*!< in: tree cursor */
|
|
{
|
|
return (buf_block_get_page_zip(btr_cur_get_block(cursor)));
|
|
}
|
|
|
|
/** Returns the page of a tree cursor.
|
|
@return pointer to page */
|
|
UNIV_INLINE
|
|
page_t *btr_cur_get_page(btr_cur_t *cursor) /*!< in: tree cursor */
|
|
{
|
|
return (page_align(page_cur_get_rec(&(cursor->page_cur))));
|
|
}
|
|
|
|
/** Positions a tree cursor at a given record. */
|
|
UNIV_INLINE
|
|
void btr_cur_position(dict_index_t *index, /*!< in: index */
|
|
rec_t *rec, /*!< in: record in tree */
|
|
buf_block_t *block, /*!< in: buffer block of rec */
|
|
btr_cur_t *cursor) /*!< out: cursor */
|
|
{
|
|
ut_ad(page_align(rec) == block->frame);
|
|
|
|
page_cur_position(rec, block, btr_cur_get_page_cur(cursor));
|
|
|
|
cursor->index = index;
|
|
}
|
|
|
|
/** Checks if compressing an index page where a btr cursor is placed makes
|
|
sense.
|
|
@return true if compression is recommended */
|
|
UNIV_INLINE
|
|
ibool btr_cur_compress_recommendation(btr_cur_t *cursor, /*!< in: btr cursor */
|
|
mtr_t *mtr) /*!< in: mtr */
|
|
{
|
|
const page_t *page;
|
|
|
|
ut_ad(mtr_is_block_fix(mtr, btr_cur_get_block(cursor), MTR_MEMO_PAGE_X_FIX,
|
|
cursor->index->table));
|
|
|
|
page = btr_cur_get_page(cursor);
|
|
|
|
LIMIT_OPTIMISTIC_INSERT_DEBUG(page_get_n_recs(page) * 2, return (FALSE));
|
|
|
|
if ((page_get_data_size(page) < BTR_CUR_PAGE_COMPRESS_LIMIT(cursor->index)) ||
|
|
((btr_page_get_next(page, mtr) == FIL_NULL) &&
|
|
(btr_page_get_prev(page, mtr) == FIL_NULL))) {
|
|
/* The page fillfactor has dropped below a predefined
|
|
minimum value OR the level in the B-tree contains just
|
|
one page: we recommend compression if this is not the
|
|
root page. */
|
|
|
|
return (dict_index_get_page(cursor->index) != page_get_page_no(page));
|
|
}
|
|
|
|
return (FALSE);
|
|
}
|
|
|
|
/** Checks if the record on which the cursor is placed can be deleted without
|
|
making tree compression necessary (or, recommended).
|
|
@return true if can be deleted without recommended compression */
|
|
UNIV_INLINE
|
|
ibool btr_cur_can_delete_without_compress(
|
|
btr_cur_t *cursor, /*!< in: btr cursor */
|
|
ulint rec_size, /*!< in: rec_get_size(btr_cur_get_rec(cursor))*/
|
|
mtr_t *mtr) /*!< in: mtr */
|
|
{
|
|
page_t *page;
|
|
|
|
ut_ad(mtr_memo_contains(mtr, btr_cur_get_block(cursor), MTR_MEMO_PAGE_X_FIX));
|
|
|
|
page = btr_cur_get_page(cursor);
|
|
|
|
if ((page_get_data_size(page) - rec_size <
|
|
BTR_CUR_PAGE_COMPRESS_LIMIT(cursor->index)) ||
|
|
((btr_page_get_next(page, mtr) == FIL_NULL) &&
|
|
(btr_page_get_prev(page, mtr) == FIL_NULL)) ||
|
|
(page_get_n_recs(page) < 2)) {
|
|
/* The page fillfactor will drop below a predefined
|
|
minimum value, OR the level in the B-tree contains just
|
|
one page, OR the page will become empty: we recommend
|
|
compression if this is not the root page. */
|
|
|
|
return (dict_index_get_page(cursor->index) == page_get_page_no(page));
|
|
}
|
|
|
|
return (TRUE);
|
|
}
|
|
|
|
UNIV_INLINE
|
|
void btr_rec_set_deleted_flag(rec_t *rec, page_zip_des_t *page_zip,
|
|
ulint flag) {
|
|
if (page_rec_is_comp(rec)) {
|
|
rec_set_deleted_flag_new(rec, page_zip, flag);
|
|
} else {
|
|
ut_ad(!page_zip);
|
|
rec_set_deleted_flag_old(rec, flag);
|
|
}
|
|
}
|