mirror of
https://github.com/MariaDB/server.git
synced 2025-01-20 05:52:27 +01:00
fec844aca8
Contains also: MDEV-10549 mysqld: sql/handler.cc:2692: int handler::ha_index_first(uchar*): Assertion `table_share->tmp_table != NO_TMP_TABLE || m_lock_type != 2' failed. (branch bb-10.2-jan) Unlike MySQL, InnoDB still uses THR_LOCK in MariaDB MDEV-10548 Some of the debug sync waits do not work with InnoDB 5.7 (branch bb-10.2-jan) enable tests that were fixed in MDEV-10549 MDEV-10548 Some of the debug sync waits do not work with InnoDB 5.7 (branch bb-10.2-jan) fix main.innodb_mysql_sync - re-enable online alter for partitioned innodb tables
351 lines
10 KiB
Text
351 lines
10 KiB
Text
/*****************************************************************************
|
|
|
|
Copyright (c) 1995, 2016, Oracle and/or its affiliates. All Rights Reserved.
|
|
Copyright (c) 2013, 2016, MariaDB Corporation.
|
|
|
|
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.,
|
|
51 Franklin Street, Suite 500, Boston, MA 02110-1335 USA
|
|
|
|
*****************************************************************************/
|
|
|
|
/**************************************************//**
|
|
@file include/fsp0fsp.ic
|
|
File space management
|
|
|
|
Created 12/18/1995 Heikki Tuuri
|
|
*******************************************************/
|
|
|
|
#ifndef UNIV_INNOCHECKSUM
|
|
|
|
/** Checks if a page address is an extent descriptor page address.
|
|
@param[in] page_id page id
|
|
@param[in] page_size page size
|
|
@return TRUE if a descriptor page */
|
|
UNIV_INLINE
|
|
ibool
|
|
fsp_descr_page(
|
|
const page_id_t& page_id,
|
|
const page_size_t& page_size)
|
|
{
|
|
return((page_id.page_no() & (page_size.physical() - 1))
|
|
== FSP_XDES_OFFSET);
|
|
}
|
|
|
|
/** Determine if the tablespace is compressed from tablespace flags.
|
|
@param[in] flags Tablespace flags
|
|
@return true if compressed, false if not compressed */
|
|
UNIV_INLINE
|
|
bool
|
|
fsp_flags_is_compressed(
|
|
ulint flags)
|
|
{
|
|
return(FSP_FLAGS_GET_ZIP_SSIZE(flags) != 0);
|
|
}
|
|
|
|
#define ACTUAL_SSIZE(ssize) (0 == ssize ? UNIV_PAGE_SSIZE_ORIG : ssize)
|
|
|
|
/** Determine if two tablespaces are equivalent or compatible.
|
|
@param[in] flags1 First tablespace flags
|
|
@param[in] flags2 Second tablespace flags
|
|
@return true the flags are compatible, false if not */
|
|
UNIV_INLINE
|
|
bool
|
|
fsp_flags_are_equal(
|
|
ulint flags1,
|
|
ulint flags2)
|
|
{
|
|
/* If either one of these flags is ULINT_UNDEFINED,
|
|
then they are not equal */
|
|
if (flags1 == ULINT_UNDEFINED || flags2 == ULINT_UNDEFINED) {
|
|
return(false);
|
|
}
|
|
|
|
if (!fsp_is_shared_tablespace(flags1) || !fsp_is_shared_tablespace(flags2)) {
|
|
/* At least one of these is a single-table tablespaces so all
|
|
flags must match. */
|
|
return(flags1 == flags2);
|
|
}
|
|
|
|
/* Both are shared tablespaces which can contain all formats.
|
|
But they must have the same logical and physical page size.
|
|
Once InnoDB can support multiple page sizes together,
|
|
the logical page size will not matter. */
|
|
ulint zip_ssize1 = ACTUAL_SSIZE(FSP_FLAGS_GET_ZIP_SSIZE(flags1));
|
|
ulint zip_ssize2 = ACTUAL_SSIZE(FSP_FLAGS_GET_ZIP_SSIZE(flags2));
|
|
ulint page_ssize1 = ACTUAL_SSIZE(FSP_FLAGS_GET_PAGE_SSIZE(flags1));
|
|
ulint page_ssize2 = ACTUAL_SSIZE(FSP_FLAGS_GET_PAGE_SSIZE(flags2));
|
|
|
|
return(zip_ssize1 == zip_ssize2 && page_ssize1 == page_ssize2);
|
|
}
|
|
|
|
/** Convert a page size, which is a power of 2, to an ssize, which is
|
|
the number of bit shifts from 512 to make that page size.
|
|
@param[in] page_size compressed page size in bytes
|
|
@return an ssize created from the page size provided. */
|
|
UNIV_INLINE
|
|
ulint
|
|
page_size_to_ssize(
|
|
ulint page_size)
|
|
{
|
|
ulint ssize;
|
|
|
|
for (ssize = UNIV_ZIP_SIZE_SHIFT_MIN;
|
|
((ulint) 1 << ssize) < page_size;
|
|
ssize++) {};
|
|
|
|
return(ssize - UNIV_ZIP_SIZE_SHIFT_MIN + 1);
|
|
}
|
|
|
|
/** Add the compressed page size to the tablespace flags.
|
|
@param[in] flags Tablespace flags
|
|
@param[in] page_size page sizes in bytes and compression flag.
|
|
@return tablespace flags after zip size is added */
|
|
UNIV_INLINE
|
|
ulint
|
|
fsp_flags_set_zip_size(
|
|
ulint flags,
|
|
const page_size_t& page_size)
|
|
{
|
|
if (!page_size.is_compressed()) {
|
|
return(flags);
|
|
}
|
|
|
|
/* Zip size should be a power of 2 between UNIV_ZIP_SIZE_MIN
|
|
and UNIV_ZIP_SIZE_MAX */
|
|
ut_ad(page_size.physical() >= UNIV_ZIP_SIZE_MIN);
|
|
ut_ad(page_size.physical() <= UNIV_ZIP_SIZE_MAX);
|
|
ut_ad(ut_is_2pow(page_size.physical()));
|
|
|
|
ulint ssize = page_size_to_ssize(page_size.physical());
|
|
|
|
ut_ad(ssize > 0);
|
|
ut_ad(ssize <= UNIV_PAGE_SSIZE_MAX);
|
|
|
|
flags |= (ssize << FSP_FLAGS_POS_ZIP_SSIZE);
|
|
|
|
ut_ad(fsp_flags_is_valid(flags));
|
|
|
|
return(flags);
|
|
}
|
|
|
|
/** Add the page size to the tablespace flags.
|
|
@param[in] flags Tablespace flags
|
|
@param[in] page_size page sizes in bytes and compression flag.
|
|
@return tablespace flags after page size is added */
|
|
UNIV_INLINE
|
|
ulint
|
|
fsp_flags_set_page_size(
|
|
ulint flags,
|
|
const page_size_t& page_size)
|
|
{
|
|
/* Page size should be a power of two between UNIV_PAGE_SIZE_MIN
|
|
and UNIV_PAGE_SIZE */
|
|
ut_ad(page_size.logical() >= UNIV_PAGE_SIZE_MIN);
|
|
ut_ad(page_size.logical() <= UNIV_PAGE_SIZE_MAX);
|
|
ut_ad(ut_is_2pow(page_size.logical()));
|
|
|
|
/* Remove this assert once we add support for different
|
|
page size per tablespace. Currently all tablespaces must
|
|
have a page size that is equal to innodb-page-size */
|
|
ut_ad(page_size.logical() == UNIV_PAGE_SIZE);
|
|
|
|
if (page_size.logical() == UNIV_PAGE_SIZE_ORIG) {
|
|
ut_ad(0 == FSP_FLAGS_GET_PAGE_SSIZE(flags));
|
|
|
|
} else {
|
|
ulint ssize = page_size_to_ssize(page_size.logical());
|
|
|
|
ut_ad(ssize);
|
|
ut_ad(ssize <= UNIV_PAGE_SSIZE_MAX);
|
|
|
|
flags |= (ssize << FSP_FLAGS_POS_PAGE_SSIZE);
|
|
}
|
|
|
|
ut_ad(fsp_flags_is_valid(flags));
|
|
|
|
return(flags);
|
|
}
|
|
|
|
/** Initialize an FSP flags integer.
|
|
@param[in] page_size page sizes in bytes and compression flag.
|
|
@param[in] atomic_blobs Used by Dynammic and Compressed.
|
|
@param[in] has_data_dir This tablespace is in a remote location.
|
|
@param[in] is_shared This tablespace can be shared by many tables.
|
|
@param[in] is_temporary This tablespace is temporary.
|
|
@param[in] is_encrypted This tablespace is encrypted.
|
|
@param[in] page_compressed Table uses page compression
|
|
@param[in] page_compression_level Page compression level
|
|
@param[in] atomic_writes Table uses atomic writes
|
|
@@return tablespace flags after initialization */
|
|
UNIV_INLINE
|
|
ulint
|
|
fsp_flags_init(
|
|
const page_size_t& page_size,
|
|
bool atomic_blobs,
|
|
bool has_data_dir,
|
|
bool is_shared,
|
|
bool is_temporary,
|
|
bool page_compression,
|
|
ulint page_compression_level,
|
|
ulint atomic_writes,
|
|
bool is_encrypted)
|
|
{
|
|
ut_ad(page_size.physical() <= page_size.logical());
|
|
ut_ad(!page_size.is_compressed() || atomic_blobs);
|
|
|
|
/* Page size should be a power of two between UNIV_PAGE_SIZE_MIN
|
|
and UNIV_PAGE_SIZE, but zip_size may be 0 if not compressed. */
|
|
ulint flags = fsp_flags_set_page_size(0, page_size);
|
|
|
|
if (atomic_blobs) {
|
|
flags |= FSP_FLAGS_MASK_POST_ANTELOPE
|
|
| FSP_FLAGS_MASK_ATOMIC_BLOBS;
|
|
}
|
|
|
|
/* If the zip_size is explicit and different from the default,
|
|
compressed row format is implied. */
|
|
flags = fsp_flags_set_zip_size(flags, page_size);
|
|
|
|
if (has_data_dir) {
|
|
flags |= FSP_FLAGS_MASK_DATA_DIR;
|
|
}
|
|
|
|
/* Shared tablespaces can hold all row formats, so we only mark the
|
|
POST_ANTELOPE and ATOMIC_BLOB bits if it is compressed. */
|
|
if (is_shared) {
|
|
ut_ad(!has_data_dir);
|
|
flags |= FSP_FLAGS_MASK_SHARED;
|
|
}
|
|
|
|
if (is_temporary) {
|
|
ut_ad(!has_data_dir);
|
|
flags |= FSP_FLAGS_MASK_TEMPORARY;
|
|
}
|
|
|
|
if (is_encrypted) {
|
|
flags |= FSP_FLAGS_MASK_ENCRYPTION;
|
|
}
|
|
|
|
/* In addition, tablespace flags also contain if the page
|
|
compression is used for this table. */
|
|
if (page_compression) {
|
|
flags |= FSP_FLAGS_SET_PAGE_COMPRESSION(flags, page_compression);
|
|
}
|
|
|
|
/* In addition, tablespace flags also contain page compression level
|
|
if page compression is used for this table. */
|
|
if (page_compression && page_compression_level) {
|
|
flags |= FSP_FLAGS_SET_PAGE_COMPRESSION_LEVEL(flags, page_compression_level);
|
|
}
|
|
|
|
/* In addition, tablespace flags also contain flag if atomic writes
|
|
is used for this table */
|
|
if (atomic_writes) {
|
|
flags |= FSP_FLAGS_SET_ATOMIC_WRITES(flags, atomic_writes);
|
|
}
|
|
|
|
ut_ad(fsp_flags_is_valid(flags));
|
|
|
|
return(flags);
|
|
}
|
|
|
|
/** Calculates the descriptor index within a descriptor page.
|
|
@param[in] page_size page size
|
|
@param[in] offset page offset
|
|
@return descriptor index */
|
|
UNIV_INLINE
|
|
ulint
|
|
xdes_calc_descriptor_index(
|
|
const page_size_t& page_size,
|
|
ulint offset)
|
|
{
|
|
return(ut_2pow_remainder(offset, page_size.physical())
|
|
/ FSP_EXTENT_SIZE);
|
|
}
|
|
|
|
/**********************************************************************//**
|
|
Gets a descriptor bit of a page.
|
|
@return TRUE if free */
|
|
UNIV_INLINE
|
|
ibool
|
|
xdes_get_bit(
|
|
/*=========*/
|
|
const xdes_t* descr, /*!< in: descriptor */
|
|
ulint bit, /*!< in: XDES_FREE_BIT or XDES_CLEAN_BIT */
|
|
ulint offset) /*!< in: page offset within extent:
|
|
0 ... FSP_EXTENT_SIZE - 1 */
|
|
{
|
|
ut_ad(offset < FSP_EXTENT_SIZE);
|
|
ut_ad(bit == XDES_FREE_BIT || bit == XDES_CLEAN_BIT);
|
|
|
|
ulint index = bit + XDES_BITS_PER_PAGE * offset;
|
|
|
|
ulint bit_index = index % 8;
|
|
ulint byte_index = index / 8;
|
|
|
|
return(ut_bit_get_nth(
|
|
mach_read_ulint(descr + XDES_BITMAP + byte_index,
|
|
MLOG_1BYTE),
|
|
bit_index));
|
|
}
|
|
|
|
/** Calculates the page where the descriptor of a page resides.
|
|
@param[in] page_size page size
|
|
@param[in] offset page offset
|
|
@return descriptor page offset */
|
|
UNIV_INLINE
|
|
ulint
|
|
xdes_calc_descriptor_page(
|
|
const page_size_t& page_size,
|
|
ulint offset)
|
|
{
|
|
#ifndef DOXYGEN /* Doxygen gets confused by these */
|
|
# if UNIV_PAGE_SIZE_MAX <= XDES_ARR_OFFSET \
|
|
+ (UNIV_PAGE_SIZE_MAX / FSP_EXTENT_SIZE_MAX) \
|
|
* XDES_SIZE_MAX
|
|
# error
|
|
# endif
|
|
# if UNIV_ZIP_SIZE_MIN <= XDES_ARR_OFFSET \
|
|
+ (UNIV_ZIP_SIZE_MIN / FSP_EXTENT_SIZE_MIN) \
|
|
* XDES_SIZE_MIN
|
|
# error
|
|
# endif
|
|
#endif /* !DOXYGEN */
|
|
|
|
ut_ad(UNIV_PAGE_SIZE > XDES_ARR_OFFSET
|
|
+ (UNIV_PAGE_SIZE / FSP_EXTENT_SIZE)
|
|
* XDES_SIZE);
|
|
ut_ad(UNIV_ZIP_SIZE_MIN > XDES_ARR_OFFSET
|
|
+ (UNIV_ZIP_SIZE_MIN / FSP_EXTENT_SIZE)
|
|
* XDES_SIZE);
|
|
|
|
#ifdef UNIV_DEBUG
|
|
if (page_size.is_compressed()) {
|
|
ut_a(page_size.physical() > XDES_ARR_OFFSET
|
|
+ (page_size.physical() / FSP_EXTENT_SIZE) * XDES_SIZE);
|
|
}
|
|
#endif /* UNIV_DEBUG */
|
|
|
|
return(ut_2pow_round(offset, page_size.physical()));
|
|
}
|
|
|
|
/** Calculates the descriptor array size.
|
|
@param[in] page_size page size
|
|
@return size of descriptor array */
|
|
UNIV_INLINE
|
|
ulint
|
|
xdes_arr_size(
|
|
const page_size_t& page_size)
|
|
{
|
|
return(page_size.physical()/FSP_EXTENT_SIZE);
|
|
}
|
|
#endif /* !UNIV_INNOCHECKSUM */
|