mirror of
https://github.com/MariaDB/server.git
synced 2025-01-19 05:22:25 +01:00
8c5d5bc5de
Merged page compression feature to XtraDB storage engine. Added feature where page compression can use lz4 compression method (innodb_use_lz4, default OFF).
807 lines
31 KiB
C
807 lines
31 KiB
C
/*****************************************************************************
|
|
|
|
Copyright (c) 1995, 2012, Oracle and/or its affiliates. All Rights Reserved.
|
|
Copyright (c) 2013, SkySQL Ab. 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.,
|
|
51 Franklin Street, Suite 500, Boston, MA 02110-1335 USA
|
|
|
|
*****************************************************************************/
|
|
|
|
/**************************************************//**
|
|
@file include/fsp0fsp.h
|
|
File space management
|
|
|
|
Created 12/18/1995 Heikki Tuuri
|
|
*******************************************************/
|
|
|
|
#ifndef fsp0fsp_h
|
|
#define fsp0fsp_h
|
|
|
|
#include "univ.i"
|
|
|
|
#ifndef UNIV_INNOCHECKSUM
|
|
|
|
#include "mtr0mtr.h"
|
|
#include "fut0lst.h"
|
|
#include "ut0byte.h"
|
|
#include "page0types.h"
|
|
#include "fsp0types.h"
|
|
|
|
#endif /* !UNIV_INNOCHECKSUM */
|
|
|
|
/* @defgroup fsp_flags InnoDB Tablespace Flag Constants @{ */
|
|
|
|
/** Width of the POST_ANTELOPE flag */
|
|
#define FSP_FLAGS_WIDTH_POST_ANTELOPE 1
|
|
/** Number of flag bits used to indicate the tablespace zip page size */
|
|
#define FSP_FLAGS_WIDTH_ZIP_SSIZE 4
|
|
/** Width of the ATOMIC_BLOBS flag. The ability to break up a long
|
|
column into an in-record prefix and an externally stored part is available
|
|
to the two Barracuda row formats COMPRESSED and DYNAMIC. */
|
|
#define FSP_FLAGS_WIDTH_ATOMIC_BLOBS 1
|
|
/** Number of flag bits used to indicate the tablespace page size */
|
|
#define FSP_FLAGS_WIDTH_PAGE_SSIZE 4
|
|
/** Width of the DATA_DIR flag. This flag indicates that the tablespace
|
|
is found in a remote location, not the default data directory. */
|
|
#define FSP_FLAGS_WIDTH_DATA_DIR 1
|
|
/** Number of flag bits used to indicate the page compression and compression level */
|
|
#define FSP_FLAGS_WIDTH_PAGE_COMPRESSION 1
|
|
#define FSP_FLAGS_WIDTH_PAGE_COMPRESSION_LEVEL 4
|
|
/** Number of flag bits used to indicate atomic writes for this tablespace */
|
|
#define FSP_FLAGS_WIDTH_ATOMIC_WRITES 2
|
|
|
|
/** Width of all the currently known tablespace flags */
|
|
#define FSP_FLAGS_WIDTH (FSP_FLAGS_WIDTH_POST_ANTELOPE \
|
|
+ FSP_FLAGS_WIDTH_ZIP_SSIZE \
|
|
+ FSP_FLAGS_WIDTH_ATOMIC_BLOBS \
|
|
+ FSP_FLAGS_WIDTH_PAGE_SSIZE \
|
|
+ FSP_FLAGS_WIDTH_DATA_DIR \
|
|
+ FSP_FLAGS_WIDTH_PAGE_COMPRESSION \
|
|
+ FSP_FLAGS_WIDTH_PAGE_COMPRESSION_LEVEL \
|
|
+ FSP_FLAGS_WIDTH_ATOMIC_WRITES)
|
|
|
|
/** A mask of all the known/used bits in tablespace flags */
|
|
#define FSP_FLAGS_MASK (~(~0 << FSP_FLAGS_WIDTH))
|
|
|
|
/** Zero relative shift position of the POST_ANTELOPE field */
|
|
#define FSP_FLAGS_POS_POST_ANTELOPE 0
|
|
/** Zero relative shift position of the ZIP_SSIZE field */
|
|
#define FSP_FLAGS_POS_ZIP_SSIZE (FSP_FLAGS_POS_POST_ANTELOPE \
|
|
+ FSP_FLAGS_WIDTH_POST_ANTELOPE)
|
|
/** Zero relative shift position of the ATOMIC_BLOBS field */
|
|
#define FSP_FLAGS_POS_ATOMIC_BLOBS (FSP_FLAGS_POS_ZIP_SSIZE \
|
|
+ FSP_FLAGS_WIDTH_ZIP_SSIZE)
|
|
/** Note that these need to be before the page size to be compatible with
|
|
dictionary */
|
|
/** Zero relative shift position of the PAGE_COMPRESSION field */
|
|
#define FSP_FLAGS_POS_PAGE_COMPRESSION (FSP_FLAGS_POS_ATOMIC_BLOBS \
|
|
+ FSP_FLAGS_WIDTH_ATOMIC_BLOBS)
|
|
/** Zero relative shift position of the PAGE_COMPRESSION_LEVEL field */
|
|
#define FSP_FLAGS_POS_PAGE_COMPRESSION_LEVEL (FSP_FLAGS_POS_PAGE_COMPRESSION \
|
|
+ FSP_FLAGS_WIDTH_PAGE_COMPRESSION)
|
|
/** Zero relative shift position of the ATOMIC_WRITES field */
|
|
#define FSP_FLAGS_POS_ATOMIC_WRITES (FSP_FLAGS_POS_PAGE_COMPRESSION_LEVEL \
|
|
+ FSP_FLAGS_WIDTH_PAGE_COMPRESSION_LEVEL)
|
|
/** Zero relative shift position of the PAGE_SSIZE field */
|
|
#define FSP_FLAGS_POS_PAGE_SSIZE (FSP_FLAGS_POS_ATOMIC_WRITES \
|
|
+ FSP_FLAGS_WIDTH_ATOMIC_WRITES)
|
|
/** Zero relative shift position of the start of the DATA DIR bits */
|
|
#define FSP_FLAGS_POS_DATA_DIR (FSP_FLAGS_POS_PAGE_SSIZE \
|
|
+ FSP_FLAGS_WIDTH_PAGE_SSIZE)
|
|
/** Zero relative shift position of the start of the UNUSED bits */
|
|
#define FSP_FLAGS_POS_UNUSED (FSP_FLAGS_POS_DATA_DIR \
|
|
+ FSP_FLAGS_WIDTH_DATA_DIR)
|
|
|
|
/** Bit mask of the POST_ANTELOPE field */
|
|
#define FSP_FLAGS_MASK_POST_ANTELOPE \
|
|
((~(~0 << FSP_FLAGS_WIDTH_POST_ANTELOPE)) \
|
|
<< FSP_FLAGS_POS_POST_ANTELOPE)
|
|
/** Bit mask of the ZIP_SSIZE field */
|
|
#define FSP_FLAGS_MASK_ZIP_SSIZE \
|
|
((~(~0 << FSP_FLAGS_WIDTH_ZIP_SSIZE)) \
|
|
<< FSP_FLAGS_POS_ZIP_SSIZE)
|
|
/** Bit mask of the ATOMIC_BLOBS field */
|
|
#define FSP_FLAGS_MASK_ATOMIC_BLOBS \
|
|
((~(~0 << FSP_FLAGS_WIDTH_ATOMIC_BLOBS)) \
|
|
<< FSP_FLAGS_POS_ATOMIC_BLOBS)
|
|
/** Bit mask of the PAGE_SSIZE field */
|
|
#define FSP_FLAGS_MASK_PAGE_SSIZE \
|
|
((~(~0 << FSP_FLAGS_WIDTH_PAGE_SSIZE)) \
|
|
<< FSP_FLAGS_POS_PAGE_SSIZE)
|
|
/** Bit mask of the DATA_DIR field */
|
|
#define FSP_FLAGS_MASK_DATA_DIR \
|
|
((~(~0 << FSP_FLAGS_WIDTH_DATA_DIR)) \
|
|
<< FSP_FLAGS_POS_DATA_DIR)
|
|
/** Bit mask of the PAGE_COMPRESSION field */
|
|
#define FSP_FLAGS_MASK_PAGE_COMPRESSION \
|
|
((~(~0 << FSP_FLAGS_WIDTH_PAGE_COMPRESSION)) \
|
|
<< FSP_FLAGS_POS_PAGE_COMPRESSION)
|
|
/** Bit mask of the PAGE_COMPRESSION_LEVEL field */
|
|
#define FSP_FLAGS_MASK_PAGE_COMPRESSION_LEVEL \
|
|
((~(~0 << FSP_FLAGS_WIDTH_PAGE_COMPRESSION_LEVEL)) \
|
|
<< FSP_FLAGS_POS_PAGE_COMPRESSION_LEVEL)
|
|
/** Bit mask of the ATOMIC_WRITES field */
|
|
#define FSP_FLAGS_MASK_ATOMIC_WRITES \
|
|
((~(~0 << FSP_FLAGS_WIDTH_ATOMIC_WRITES)) \
|
|
<< FSP_FLAGS_POS_ATOMIC_WRITES)
|
|
|
|
|
|
/** Return the value of the POST_ANTELOPE field */
|
|
#define FSP_FLAGS_GET_POST_ANTELOPE(flags) \
|
|
((flags & FSP_FLAGS_MASK_POST_ANTELOPE) \
|
|
>> FSP_FLAGS_POS_POST_ANTELOPE)
|
|
/** Return the value of the ZIP_SSIZE field */
|
|
#define FSP_FLAGS_GET_ZIP_SSIZE(flags) \
|
|
((flags & FSP_FLAGS_MASK_ZIP_SSIZE) \
|
|
>> FSP_FLAGS_POS_ZIP_SSIZE)
|
|
/** Return the value of the ATOMIC_BLOBS field */
|
|
#define FSP_FLAGS_HAS_ATOMIC_BLOBS(flags) \
|
|
((flags & FSP_FLAGS_MASK_ATOMIC_BLOBS) \
|
|
>> FSP_FLAGS_POS_ATOMIC_BLOBS)
|
|
/** Return the value of the PAGE_SSIZE field */
|
|
#define FSP_FLAGS_GET_PAGE_SSIZE(flags) \
|
|
((flags & FSP_FLAGS_MASK_PAGE_SSIZE) \
|
|
>> FSP_FLAGS_POS_PAGE_SSIZE)
|
|
/** Return the value of the DATA_DIR field */
|
|
#define FSP_FLAGS_HAS_DATA_DIR(flags) \
|
|
((flags & FSP_FLAGS_MASK_DATA_DIR) \
|
|
>> FSP_FLAGS_POS_DATA_DIR)
|
|
/** Return the contents of the UNUSED bits */
|
|
#define FSP_FLAGS_GET_UNUSED(flags) \
|
|
(flags >> FSP_FLAGS_POS_UNUSED)
|
|
/** Return the value of the PAGE_COMPRESSION field */
|
|
#define FSP_FLAGS_GET_PAGE_COMPRESSION(flags) \
|
|
((flags & FSP_FLAGS_MASK_PAGE_COMPRESSION) \
|
|
>> FSP_FLAGS_POS_PAGE_COMPRESSION)
|
|
/** Return the value of the PAGE_COMPRESSION_LEVEL field */
|
|
#define FSP_FLAGS_GET_PAGE_COMPRESSION_LEVEL(flags) \
|
|
((flags & FSP_FLAGS_MASK_PAGE_COMPRESSION_LEVEL) \
|
|
>> FSP_FLAGS_POS_PAGE_COMPRESSION_LEVEL)
|
|
/** Return the value of the ATOMIC_WRITES field */
|
|
#define FSP_FLAGS_GET_ATOMIC_WRITES(flags) \
|
|
((flags & FSP_FLAGS_MASK_ATOMIC_WRITES) \
|
|
>> FSP_FLAGS_POS_ATOMIC_WRITES)
|
|
|
|
/** Set a PAGE_SSIZE into the correct bits in a given
|
|
tablespace flags. */
|
|
#define FSP_FLAGS_SET_PAGE_SSIZE(flags, ssize) \
|
|
(flags | (ssize << FSP_FLAGS_POS_PAGE_SSIZE))
|
|
|
|
/** Set a PAGE_COMPRESSION into the correct bits in a given
|
|
tablespace flags. */
|
|
#define FSP_FLAGS_SET_PAGE_COMPRESSION(flags, compression) \
|
|
(flags | (compression << FSP_FLAGS_POS_PAGE_COMPRESSION))
|
|
|
|
/** Set a PAGE_COMPRESSION_LEVEL into the correct bits in a given
|
|
tablespace flags. */
|
|
#define FSP_FLAGS_SET_PAGE_COMPRESSION_LEVEL(flags, level) \
|
|
(flags | (level << FSP_FLAGS_POS_PAGE_COMPRESSION_LEVEL))
|
|
/** Set a ATOMIC_WRITES into the correct bits in a given
|
|
tablespace flags. */
|
|
#define FSP_FLAGS_SET_ATOMIC_WRITES(flags, atomics) \
|
|
(flags | (atomics << FSP_FLAGS_POS_ATOMIC_WRITES))
|
|
|
|
/* @} */
|
|
|
|
/* @defgroup Tablespace Header Constants (moved from fsp0fsp.c) @{ */
|
|
|
|
/** Offset of the space header within a file page */
|
|
#define FSP_HEADER_OFFSET FIL_PAGE_DATA
|
|
|
|
/* The data structures in files are defined just as byte strings in C */
|
|
typedef byte fsp_header_t;
|
|
typedef byte xdes_t;
|
|
|
|
/* SPACE HEADER
|
|
============
|
|
|
|
File space header data structure: this data structure is contained in the
|
|
first page of a space. The space for this header is reserved in every extent
|
|
descriptor page, but used only in the first. */
|
|
|
|
/*-------------------------------------*/
|
|
#define FSP_SPACE_ID 0 /* space id */
|
|
#define FSP_NOT_USED 4 /* this field contained a value up to
|
|
which we know that the modifications
|
|
in the database have been flushed to
|
|
the file space; not used now */
|
|
#define FSP_SIZE 8 /* Current size of the space in
|
|
pages */
|
|
#define FSP_FREE_LIMIT 12 /* Minimum page number for which the
|
|
free list has not been initialized:
|
|
the pages >= this limit are, by
|
|
definition, free; note that in a
|
|
single-table tablespace where size
|
|
< 64 pages, this number is 64, i.e.,
|
|
we have initialized the space
|
|
about the first extent, but have not
|
|
physically allocted those pages to the
|
|
file */
|
|
#define FSP_SPACE_FLAGS 16 /* fsp_space_t.flags, similar to
|
|
dict_table_t::flags */
|
|
#define FSP_FRAG_N_USED 20 /* number of used pages in the
|
|
FSP_FREE_FRAG list */
|
|
#define FSP_FREE 24 /* list of free extents */
|
|
#define FSP_FREE_FRAG (24 + FLST_BASE_NODE_SIZE)
|
|
/* list of partially free extents not
|
|
belonging to any segment */
|
|
#define FSP_FULL_FRAG (24 + 2 * FLST_BASE_NODE_SIZE)
|
|
/* list of full extents not belonging
|
|
to any segment */
|
|
#define FSP_SEG_ID (24 + 3 * FLST_BASE_NODE_SIZE)
|
|
/* 8 bytes which give the first unused
|
|
segment id */
|
|
#define FSP_SEG_INODES_FULL (32 + 3 * FLST_BASE_NODE_SIZE)
|
|
/* list of pages containing segment
|
|
headers, where all the segment inode
|
|
slots are reserved */
|
|
#define FSP_SEG_INODES_FREE (32 + 4 * FLST_BASE_NODE_SIZE)
|
|
/* list of pages containing segment
|
|
headers, where not all the segment
|
|
header slots are reserved */
|
|
/*-------------------------------------*/
|
|
/* File space header size */
|
|
#define FSP_HEADER_SIZE (32 + 5 * FLST_BASE_NODE_SIZE)
|
|
|
|
#define FSP_FREE_ADD 4 /* this many free extents are added
|
|
to the free list from above
|
|
FSP_FREE_LIMIT at a time */
|
|
/* @} */
|
|
|
|
#ifndef UNIV_INNOCHECKSUM
|
|
|
|
/* @defgroup File Segment Inode Constants (moved from fsp0fsp.c) @{ */
|
|
|
|
/* FILE SEGMENT INODE
|
|
==================
|
|
|
|
Segment inode which is created for each segment in a tablespace. NOTE: in
|
|
purge we assume that a segment having only one currently used page can be
|
|
freed in a few steps, so that the freeing cannot fill the file buffer with
|
|
bufferfixed file pages. */
|
|
|
|
typedef byte fseg_inode_t;
|
|
|
|
#define FSEG_INODE_PAGE_NODE FSEG_PAGE_DATA
|
|
/* the list node for linking
|
|
segment inode pages */
|
|
|
|
#define FSEG_ARR_OFFSET (FSEG_PAGE_DATA + FLST_NODE_SIZE)
|
|
/*-------------------------------------*/
|
|
#define FSEG_ID 0 /* 8 bytes of segment id: if this is 0,
|
|
it means that the header is unused */
|
|
#define FSEG_NOT_FULL_N_USED 8
|
|
/* number of used segment pages in
|
|
the FSEG_NOT_FULL list */
|
|
#define FSEG_FREE 12
|
|
/* list of free extents of this
|
|
segment */
|
|
#define FSEG_NOT_FULL (12 + FLST_BASE_NODE_SIZE)
|
|
/* list of partially free extents */
|
|
#define FSEG_FULL (12 + 2 * FLST_BASE_NODE_SIZE)
|
|
/* list of full extents */
|
|
#define FSEG_MAGIC_N (12 + 3 * FLST_BASE_NODE_SIZE)
|
|
/* magic number used in debugging */
|
|
#define FSEG_FRAG_ARR (16 + 3 * FLST_BASE_NODE_SIZE)
|
|
/* array of individual pages
|
|
belonging to this segment in fsp
|
|
fragment extent lists */
|
|
#define FSEG_FRAG_ARR_N_SLOTS (FSP_EXTENT_SIZE / 2)
|
|
/* number of slots in the array for
|
|
the fragment pages */
|
|
#define FSEG_FRAG_SLOT_SIZE 4 /* a fragment page slot contains its
|
|
page number within space, FIL_NULL
|
|
means that the slot is not in use */
|
|
/*-------------------------------------*/
|
|
#define FSEG_INODE_SIZE \
|
|
(16 + 3 * FLST_BASE_NODE_SIZE \
|
|
+ FSEG_FRAG_ARR_N_SLOTS * FSEG_FRAG_SLOT_SIZE)
|
|
|
|
#define FSP_SEG_INODES_PER_PAGE(zip_size) \
|
|
(((zip_size ? zip_size : UNIV_PAGE_SIZE) \
|
|
- FSEG_ARR_OFFSET - 10) / FSEG_INODE_SIZE)
|
|
/* Number of segment inodes which fit on a
|
|
single page */
|
|
|
|
#define FSEG_MAGIC_N_VALUE 97937874
|
|
|
|
#define FSEG_FILLFACTOR 8 /* If this value is x, then if
|
|
the number of unused but reserved
|
|
pages in a segment is less than
|
|
reserved pages * 1/x, and there are
|
|
at least FSEG_FRAG_LIMIT used pages,
|
|
then we allow a new empty extent to
|
|
be added to the segment in
|
|
fseg_alloc_free_page. Otherwise, we
|
|
use unused pages of the segment. */
|
|
|
|
#define FSEG_FRAG_LIMIT FSEG_FRAG_ARR_N_SLOTS
|
|
/* If the segment has >= this many
|
|
used pages, it may be expanded by
|
|
allocating extents to the segment;
|
|
until that only individual fragment
|
|
pages are allocated from the space */
|
|
|
|
#define FSEG_FREE_LIST_LIMIT 40 /* If the reserved size of a segment
|
|
is at least this many extents, we
|
|
allow extents to be put to the free
|
|
list of the extent: at most
|
|
FSEG_FREE_LIST_MAX_LEN many */
|
|
#define FSEG_FREE_LIST_MAX_LEN 4
|
|
/* @} */
|
|
|
|
/* @defgroup Extent Descriptor Constants (moved from fsp0fsp.c) @{ */
|
|
|
|
/* EXTENT DESCRIPTOR
|
|
=================
|
|
|
|
File extent descriptor data structure: contains bits to tell which pages in
|
|
the extent are free and which contain old tuple version to clean. */
|
|
|
|
/*-------------------------------------*/
|
|
#define XDES_ID 0 /* The identifier of the segment
|
|
to which this extent belongs */
|
|
#define XDES_FLST_NODE 8 /* The list node data structure
|
|
for the descriptors */
|
|
#define XDES_STATE (FLST_NODE_SIZE + 8)
|
|
/* contains state information
|
|
of the extent */
|
|
#define XDES_BITMAP (FLST_NODE_SIZE + 12)
|
|
/* Descriptor bitmap of the pages
|
|
in the extent */
|
|
/*-------------------------------------*/
|
|
|
|
#define XDES_BITS_PER_PAGE 2 /* How many bits are there per page */
|
|
#define XDES_FREE_BIT 0 /* Index of the bit which tells if
|
|
the page is free */
|
|
#define XDES_CLEAN_BIT 1 /* NOTE: currently not used!
|
|
Index of the bit which tells if
|
|
there are old versions of tuples
|
|
on the page */
|
|
/* States of a descriptor */
|
|
#define XDES_FREE 1 /* extent is in free list of space */
|
|
#define XDES_FREE_FRAG 2 /* extent is in free fragment list of
|
|
space */
|
|
#define XDES_FULL_FRAG 3 /* extent is in full fragment list of
|
|
space */
|
|
#define XDES_FSEG 4 /* extent belongs to a segment */
|
|
|
|
/** File extent data structure size in bytes. */
|
|
#define XDES_SIZE \
|
|
(XDES_BITMAP \
|
|
+ UT_BITS_IN_BYTES(FSP_EXTENT_SIZE * XDES_BITS_PER_PAGE))
|
|
|
|
/** File extent data structure size in bytes for MAX page size. */
|
|
#define XDES_SIZE_MAX \
|
|
(XDES_BITMAP \
|
|
+ UT_BITS_IN_BYTES(FSP_EXTENT_SIZE_MAX * XDES_BITS_PER_PAGE))
|
|
|
|
/** File extent data structure size in bytes for MIN page size. */
|
|
#define XDES_SIZE_MIN \
|
|
(XDES_BITMAP \
|
|
+ UT_BITS_IN_BYTES(FSP_EXTENT_SIZE_MIN * XDES_BITS_PER_PAGE))
|
|
|
|
/** Offset of the descriptor array on a descriptor page */
|
|
#define XDES_ARR_OFFSET (FSP_HEADER_OFFSET + FSP_HEADER_SIZE)
|
|
|
|
/* @} */
|
|
|
|
/**********************************************************************//**
|
|
Initializes the file space system. */
|
|
UNIV_INTERN
|
|
void
|
|
fsp_init(void);
|
|
/*==========*/
|
|
/**********************************************************************//**
|
|
Gets the size of the system tablespace from the tablespace header. If
|
|
we do not have an auto-extending data file, this should be equal to
|
|
the size of the data files. If there is an auto-extending data file,
|
|
this can be smaller.
|
|
@return size in pages */
|
|
UNIV_INTERN
|
|
ulint
|
|
fsp_header_get_tablespace_size(void);
|
|
/*================================*/
|
|
/**********************************************************************//**
|
|
Reads the file space size stored in the header page.
|
|
@return tablespace size stored in the space header */
|
|
UNIV_INTERN
|
|
ulint
|
|
fsp_get_size_low(
|
|
/*=============*/
|
|
page_t* page); /*!< in: header page (page 0 in the tablespace) */
|
|
/**********************************************************************//**
|
|
Reads the space id from the first page of a tablespace.
|
|
@return space id, ULINT UNDEFINED if error */
|
|
UNIV_INTERN
|
|
ulint
|
|
fsp_header_get_space_id(
|
|
/*====================*/
|
|
const page_t* page); /*!< in: first page of a tablespace */
|
|
/**********************************************************************//**
|
|
Reads the space flags from the first page of a tablespace.
|
|
@return flags */
|
|
UNIV_INTERN
|
|
ulint
|
|
fsp_header_get_flags(
|
|
/*=================*/
|
|
const page_t* page); /*!< in: first page of a tablespace */
|
|
/**********************************************************************//**
|
|
Reads the compressed page size from the first page of a tablespace.
|
|
@return compressed page size in bytes, or 0 if uncompressed */
|
|
UNIV_INTERN
|
|
ulint
|
|
fsp_header_get_zip_size(
|
|
/*====================*/
|
|
const page_t* page); /*!< in: first page of a tablespace */
|
|
/**********************************************************************//**
|
|
Writes the space id and flags to a tablespace header. The flags contain
|
|
row type, physical/compressed page size, and logical/uncompressed page
|
|
size of the tablespace. */
|
|
UNIV_INTERN
|
|
void
|
|
fsp_header_init_fields(
|
|
/*===================*/
|
|
page_t* page, /*!< in/out: first page in the space */
|
|
ulint space_id, /*!< in: space id */
|
|
ulint flags); /*!< in: tablespace flags (FSP_SPACE_FLAGS):
|
|
0, or table->flags if newer than COMPACT */
|
|
/**********************************************************************//**
|
|
Initializes the space header of a new created space and creates also the
|
|
insert buffer tree root if space == 0. */
|
|
UNIV_INTERN
|
|
void
|
|
fsp_header_init(
|
|
/*============*/
|
|
ulint space, /*!< in: space id */
|
|
ulint size, /*!< in: current size in blocks */
|
|
mtr_t* mtr); /*!< in/out: mini-transaction */
|
|
/**********************************************************************//**
|
|
Increases the space size field of a space. */
|
|
UNIV_INTERN
|
|
void
|
|
fsp_header_inc_size(
|
|
/*================*/
|
|
ulint space, /*!< in: space id */
|
|
ulint size_inc, /*!< in: size increment in pages */
|
|
mtr_t* mtr); /*!< in/out: mini-transaction */
|
|
/**********************************************************************//**
|
|
Creates a new segment.
|
|
@return the block where the segment header is placed, x-latched, NULL
|
|
if could not create segment because of lack of space */
|
|
UNIV_INTERN
|
|
buf_block_t*
|
|
fseg_create(
|
|
/*========*/
|
|
ulint space, /*!< in: space id */
|
|
ulint page, /*!< in: page where the segment header is placed: if
|
|
this is != 0, the page must belong to another segment,
|
|
if this is 0, a new page will be allocated and it
|
|
will belong to the created segment */
|
|
ulint byte_offset, /*!< in: byte offset of the created segment header
|
|
on the page */
|
|
mtr_t* mtr); /*!< in/out: mini-transaction */
|
|
/**********************************************************************//**
|
|
Creates a new segment.
|
|
@return the block where the segment header is placed, x-latched, NULL
|
|
if could not create segment because of lack of space */
|
|
UNIV_INTERN
|
|
buf_block_t*
|
|
fseg_create_general(
|
|
/*================*/
|
|
ulint space, /*!< in: space id */
|
|
ulint page, /*!< in: page where the segment header is placed: if
|
|
this is != 0, the page must belong to another segment,
|
|
if this is 0, a new page will be allocated and it
|
|
will belong to the created segment */
|
|
ulint byte_offset, /*!< in: byte offset of the created segment header
|
|
on the page */
|
|
ibool has_done_reservation, /*!< in: TRUE if the caller has already
|
|
done the reservation for the pages with
|
|
fsp_reserve_free_extents (at least 2 extents: one for
|
|
the inode and the other for the segment) then there is
|
|
no need to do the check for this individual
|
|
operation */
|
|
mtr_t* mtr); /*!< in/out: mini-transaction */
|
|
/**********************************************************************//**
|
|
Calculates the number of pages reserved by a segment, and how many pages are
|
|
currently used.
|
|
@return number of reserved pages */
|
|
UNIV_INTERN
|
|
ulint
|
|
fseg_n_reserved_pages(
|
|
/*==================*/
|
|
fseg_header_t* header, /*!< in: segment header */
|
|
ulint* used, /*!< out: number of pages used (<= reserved) */
|
|
mtr_t* mtr); /*!< in/out: mini-transaction */
|
|
/**********************************************************************//**
|
|
Allocates a single free page from a segment. This function implements
|
|
the intelligent allocation strategy which tries to minimize
|
|
file space fragmentation.
|
|
@param[in/out] seg_header segment header
|
|
@param[in] hint hint of which page would be desirable
|
|
@param[in] direction if the new page is needed because
|
|
of an index page split, and records are
|
|
inserted there in order, into which
|
|
direction they go alphabetically: FSP_DOWN,
|
|
FSP_UP, FSP_NO_DIR
|
|
@param[in/out] mtr mini-transaction
|
|
@return X-latched block, or NULL if no page could be allocated */
|
|
#define fseg_alloc_free_page(seg_header, hint, direction, mtr) \
|
|
fseg_alloc_free_page_general(seg_header, hint, direction, \
|
|
FALSE, mtr, mtr)
|
|
/**********************************************************************//**
|
|
Allocates a single free page from a segment. This function implements
|
|
the intelligent allocation strategy which tries to minimize file space
|
|
fragmentation.
|
|
@retval NULL if no page could be allocated
|
|
@retval block, rw_lock_x_lock_count(&block->lock) == 1 if allocation succeeded
|
|
(init_mtr == mtr, or the page was not previously freed in mtr)
|
|
@retval block (not allocated or initialized) otherwise */
|
|
UNIV_INTERN
|
|
buf_block_t*
|
|
fseg_alloc_free_page_general(
|
|
/*=========================*/
|
|
fseg_header_t* seg_header,/*!< in/out: segment header */
|
|
ulint hint, /*!< in: hint of which page would be
|
|
desirable */
|
|
byte direction,/*!< in: if the new page is needed because
|
|
of an index page split, and records are
|
|
inserted there in order, into which
|
|
direction they go alphabetically: FSP_DOWN,
|
|
FSP_UP, FSP_NO_DIR */
|
|
ibool has_done_reservation, /*!< in: TRUE if the caller has
|
|
already done the reservation for the page
|
|
with fsp_reserve_free_extents, then there
|
|
is no need to do the check for this individual
|
|
page */
|
|
mtr_t* mtr, /*!< in/out: mini-transaction */
|
|
mtr_t* init_mtr)/*!< in/out: mtr or another mini-transaction
|
|
in which the page should be initialized.
|
|
If init_mtr!=mtr, but the page is already
|
|
latched in mtr, do not initialize the page. */
|
|
__attribute__((warn_unused_result, nonnull));
|
|
/**********************************************************************//**
|
|
Reserves free pages from a tablespace. All mini-transactions which may
|
|
use several pages from the tablespace should call this function beforehand
|
|
and reserve enough free extents so that they certainly will be able
|
|
to do their operation, like a B-tree page split, fully. Reservations
|
|
must be released with function fil_space_release_free_extents!
|
|
|
|
The alloc_type below has the following meaning: FSP_NORMAL means an
|
|
operation which will probably result in more space usage, like an
|
|
insert in a B-tree; FSP_UNDO means allocation to undo logs: if we are
|
|
deleting rows, then this allocation will in the long run result in
|
|
less space usage (after a purge); FSP_CLEANING means allocation done
|
|
in a physical record delete (like in a purge) or other cleaning operation
|
|
which will result in less space usage in the long run. We prefer the latter
|
|
two types of allocation: when space is scarce, FSP_NORMAL allocations
|
|
will not succeed, but the latter two allocations will succeed, if possible.
|
|
The purpose is to avoid dead end where the database is full but the
|
|
user cannot free any space because these freeing operations temporarily
|
|
reserve some space.
|
|
|
|
Single-table tablespaces whose size is < 32 pages are a special case. In this
|
|
function we would liberally reserve several 64 page extents for every page
|
|
split or merge in a B-tree. But we do not want to waste disk space if the table
|
|
only occupies < 32 pages. That is why we apply different rules in that special
|
|
case, just ensuring that there are 3 free pages available.
|
|
@return TRUE if we were able to make the reservation */
|
|
UNIV_INTERN
|
|
ibool
|
|
fsp_reserve_free_extents(
|
|
/*=====================*/
|
|
ulint* n_reserved,/*!< out: number of extents actually reserved; if we
|
|
return TRUE and the tablespace size is < 64 pages,
|
|
then this can be 0, otherwise it is n_ext */
|
|
ulint space, /*!< in: space id */
|
|
ulint n_ext, /*!< in: number of extents to reserve */
|
|
ulint alloc_type,/*!< in: FSP_NORMAL, FSP_UNDO, or FSP_CLEANING */
|
|
mtr_t* mtr); /*!< in: mini-transaction */
|
|
/**********************************************************************//**
|
|
This function should be used to get information on how much we still
|
|
will be able to insert new data to the database without running out the
|
|
tablespace. Only free extents are taken into account and we also subtract
|
|
the safety margin required by the above function fsp_reserve_free_extents.
|
|
@return available space in kB */
|
|
UNIV_INTERN
|
|
ullint
|
|
fsp_get_available_space_in_free_extents(
|
|
/*====================================*/
|
|
ulint space); /*!< in: space id */
|
|
/**********************************************************************//**
|
|
Frees a single page of a segment. */
|
|
UNIV_INTERN
|
|
void
|
|
fseg_free_page(
|
|
/*===========*/
|
|
fseg_header_t* seg_header, /*!< in: segment header */
|
|
ulint space, /*!< in: space id */
|
|
ulint page, /*!< in: page offset */
|
|
mtr_t* mtr); /*!< in/out: mini-transaction */
|
|
/**********************************************************************//**
|
|
Checks if a single page of a segment is free.
|
|
@return true if free */
|
|
UNIV_INTERN
|
|
bool
|
|
fseg_page_is_free(
|
|
/*==============*/
|
|
fseg_header_t* seg_header, /*!< in: segment header */
|
|
ulint space, /*!< in: space id */
|
|
ulint page) /*!< in: page offset */
|
|
__attribute__((nonnull, warn_unused_result));
|
|
/**********************************************************************//**
|
|
Frees part of a segment. This function can be used to free a segment
|
|
by repeatedly calling this function in different mini-transactions.
|
|
Doing the freeing in a single mini-transaction might result in
|
|
too big a mini-transaction.
|
|
@return TRUE if freeing completed */
|
|
UNIV_INTERN
|
|
ibool
|
|
fseg_free_step(
|
|
/*===========*/
|
|
fseg_header_t* header, /*!< in, own: segment header; NOTE: if the header
|
|
resides on the first page of the frag list
|
|
of the segment, this pointer becomes obsolete
|
|
after the last freeing step */
|
|
mtr_t* mtr); /*!< in/out: mini-transaction */
|
|
/**********************************************************************//**
|
|
Frees part of a segment. Differs from fseg_free_step because this function
|
|
leaves the header page unfreed.
|
|
@return TRUE if freeing completed, except the header page */
|
|
UNIV_INTERN
|
|
ibool
|
|
fseg_free_step_not_header(
|
|
/*======================*/
|
|
fseg_header_t* header, /*!< in: segment header which must reside on
|
|
the first fragment page of the segment */
|
|
mtr_t* mtr); /*!< in/out: mini-transaction */
|
|
/***********************************************************************//**
|
|
Checks if a page address is an extent descriptor page address.
|
|
@return TRUE if a descriptor page */
|
|
UNIV_INLINE
|
|
ibool
|
|
fsp_descr_page(
|
|
/*===========*/
|
|
ulint zip_size,/*!< in: compressed page size in bytes;
|
|
0 for uncompressed pages */
|
|
ulint page_no);/*!< in: page number */
|
|
/***********************************************************//**
|
|
Parses a redo log record of a file page init.
|
|
@return end of log record or NULL */
|
|
UNIV_INTERN
|
|
byte*
|
|
fsp_parse_init_file_page(
|
|
/*=====================*/
|
|
byte* ptr, /*!< in: buffer */
|
|
byte* end_ptr, /*!< in: buffer end */
|
|
buf_block_t* block); /*!< in: block or NULL */
|
|
/*******************************************************************//**
|
|
Validates the file space system and its segments.
|
|
@return TRUE if ok */
|
|
UNIV_INTERN
|
|
ibool
|
|
fsp_validate(
|
|
/*=========*/
|
|
ulint space); /*!< in: space id */
|
|
/*******************************************************************//**
|
|
Prints info of a file space. */
|
|
UNIV_INTERN
|
|
void
|
|
fsp_print(
|
|
/*======*/
|
|
ulint space); /*!< in: space id */
|
|
#ifdef UNIV_DEBUG
|
|
/*******************************************************************//**
|
|
Validates a segment.
|
|
@return TRUE if ok */
|
|
UNIV_INTERN
|
|
ibool
|
|
fseg_validate(
|
|
/*==========*/
|
|
fseg_header_t* header, /*!< in: segment header */
|
|
mtr_t* mtr); /*!< in/out: mini-transaction */
|
|
#endif /* UNIV_DEBUG */
|
|
#ifdef UNIV_BTR_PRINT
|
|
/*******************************************************************//**
|
|
Writes info of a segment. */
|
|
UNIV_INTERN
|
|
void
|
|
fseg_print(
|
|
/*=======*/
|
|
fseg_header_t* header, /*!< in: segment header */
|
|
mtr_t* mtr); /*!< in/out: mini-transaction */
|
|
#endif /* UNIV_BTR_PRINT */
|
|
|
|
/********************************************************************//**
|
|
Validate and return the tablespace flags, which are stored in the
|
|
tablespace header at offset FSP_SPACE_FLAGS. They should be 0 for
|
|
ROW_FORMAT=COMPACT and ROW_FORMAT=REDUNDANT. The newer row formats,
|
|
COMPRESSED and DYNAMIC, use a file format > Antelope so they should
|
|
have a file format number plus the DICT_TF_COMPACT bit set.
|
|
@return true if check ok */
|
|
UNIV_INLINE
|
|
bool
|
|
fsp_flags_is_valid(
|
|
/*===============*/
|
|
ulint flags) /*!< in: tablespace flags */
|
|
__attribute__((warn_unused_result, const));
|
|
/********************************************************************//**
|
|
Determine if the tablespace is compressed from dict_table_t::flags.
|
|
@return TRUE if compressed, FALSE if not compressed */
|
|
UNIV_INLINE
|
|
ibool
|
|
fsp_flags_is_compressed(
|
|
/*====================*/
|
|
ulint flags); /*!< in: tablespace flags */
|
|
|
|
/********************************************************************//**
|
|
Calculates the descriptor index within a descriptor page.
|
|
@return descriptor index */
|
|
UNIV_INLINE
|
|
ulint
|
|
xdes_calc_descriptor_index(
|
|
/*=======================*/
|
|
ulint zip_size, /*!< in: compressed page size in bytes;
|
|
0 for uncompressed pages */
|
|
ulint offset); /*!< in: page offset */
|
|
|
|
/**********************************************************************//**
|
|
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 */
|
|
|
|
/********************************************************************//**
|
|
Calculates the page where the descriptor of a page resides.
|
|
@return descriptor page offset */
|
|
UNIV_INLINE
|
|
ulint
|
|
xdes_calc_descriptor_page(
|
|
/*======================*/
|
|
ulint zip_size, /*!< in: compressed page size in bytes;
|
|
0 for uncompressed pages */
|
|
ulint offset); /*!< in: page offset */
|
|
|
|
#endif /* !UNIV_INNOCHECKSUM */
|
|
|
|
/********************************************************************//**
|
|
Extract the zip size from tablespace flags. A tablespace has only one
|
|
physical page size whether that page is compressed or not.
|
|
@return compressed page size of the file-per-table tablespace in bytes,
|
|
or zero if the table is not compressed. */
|
|
UNIV_INLINE
|
|
ulint
|
|
fsp_flags_get_zip_size(
|
|
/*====================*/
|
|
ulint flags); /*!< in: tablespace flags */
|
|
/********************************************************************//**
|
|
Extract the page size from tablespace flags.
|
|
@return page size of the tablespace in bytes */
|
|
UNIV_INLINE
|
|
ulint
|
|
fsp_flags_get_page_size(
|
|
/*====================*/
|
|
ulint flags); /*!< in: tablespace flags */
|
|
|
|
#ifndef UNIV_NONINL
|
|
#include "fsp0fsp.ic"
|
|
#endif
|
|
|
|
#endif
|