📄 fsp0fsp.c
字号:
/**********************************************************************File space management(c) 1995 Innobase OyCreated 11/29/1995 Heikki Tuuri***********************************************************************/#include "fsp0fsp.h"#ifdef UNIV_NONINL#include "fsp0fsp.ic"#endif#include "buf0buf.h"#include "fil0fil.h"#include "sync0sync.h"#include "mtr0log.h"#include "fut0fut.h"#include "ut0byte.h"#include "srv0srv.h"#include "page0types.h"#include "ibuf0ibuf.h"#include "btr0btr.h"#include "btr0sea.h"#include "dict0boot.h"#include "dict0mem.h"#include "log0log.h"#define FSP_HEADER_OFFSET FIL_PAGE_DATA /* Offset of the space header within a file page *//* 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 thefirst page of a space. The space for this header is reserved in every extentdescriptor 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_LOWEST_NO_WRITE 16 /* The lowest page offset for which the page has not been written to disk (if it has been written, we know that the OS has really reserved the physical space for the page) */#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 */ /* FILE SEGMENT INODE ==================Segment inode which is created for each segment in a tablespace. NOTE: inpurge we assume that a segment having only one currently used page can befreed in a few steps, so that the freeing cannot fill the file buffer withbufferfixed 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 ut_dulint_zero, 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 ((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 /* EXTENT DESCRIPTOR =================File extent descriptor data structure: contains bits to tell which pages inthe 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. The "+ 7 ) / 8" part in thedefinition rounds the number of bytes upward. */#define XDES_SIZE (XDES_BITMAP + (FSP_EXTENT_SIZE * XDES_BITS_PER_PAGE + 7) / 8)/* Offset of the descriptor array on a descriptor page */#define XDES_ARR_OFFSET (FSP_HEADER_OFFSET + FSP_HEADER_SIZE) /**************************************************************************Returns an extent to the free list of a space. */staticvoidfsp_free_extent(/*============*/ ulint space, /* in: space id */ ulint page, /* in: page offset in the extent */ mtr_t* mtr); /* in: mtr *//**************************************************************************Frees an extent of a segment to the space free list. */staticvoidfseg_free_extent(/*=============*/ fseg_inode_t* seg_inode, /* in: segment inode */ ulint space, /* in: space id */ ulint page, /* in: page offset in the extent */ mtr_t* mtr); /* in: mtr handle *//**************************************************************************Calculates the number of pages reserved by a segment, and howmany pages are currently used. */staticulintfseg_n_reserved_pages_low(/*======================*/ /* out: number of reserved pages */ fseg_inode_t* header, /* in: segment inode */ ulint* used, /* out: number of pages used (<= reserved) */ mtr_t* mtr); /* in: mtr handle *//************************************************************************Marks a page used. The page must reside within the extents of the givensegment. */staticvoidfseg_mark_page_used(/*================*/ fseg_inode_t* seg_inode,/* in: segment inode */ ulint space, /* in: space id */ ulint page, /* in: page offset */ mtr_t* mtr); /* in: mtr *//**************************************************************************Returns the first extent descriptor for a segment. We think of the extentlists of the segment catenated in the order FSEG_FULL -> FSEG_NOT_FULL-> FSEG_FREE. */staticxdes_t*fseg_get_first_extent(/*==================*/ /* out: the first extent descriptor, or NULL if none */ fseg_inode_t* inode, /* in: segment inode */ mtr_t* mtr); /* in: mtr *//**************************************************************************Puts new extents to the free list ifthere are free extents above the free limit. If an extent happensto contain an extent descriptor page, the extent is put tothe FSP_FREE_FRAG list with the page marked as used. */staticvoidfsp_fill_free_list(/*===============*/ ibool init_space, /* in: TRUE if this is a single-table tablespace and we are only initing the tablespace's first extent descriptor page and ibuf bitmap page; then we do not allocate more extents */ ulint space, /* in: space */ fsp_header_t* header, /* in: space header */ mtr_t* mtr); /* in: mtr *//**************************************************************************Allocates a single free page from a segment. This function implementsthe intelligent allocation strategy which tries to minimize file spacefragmentation. */staticulintfseg_alloc_free_page_low(/*=====================*/ /* out: the allocated page number, FIL_NULL if no page could be allocated */ ulint space, /* in: space */ fseg_inode_t* seg_inode, /* in: segment inode */ 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 */ mtr_t* mtr); /* in: mtr handle *//**************************************************************************Reads the file space size stored in the header page. */ulintfsp_get_size_low(/*=============*/ /* out: tablespace size stored in the space header */ page_t* page) /* in: header page (page 0 in the tablespace) */{ return(mach_read_from_4(page + FSP_HEADER_OFFSET + FSP_SIZE));}/**************************************************************************Gets a pointer to the space header and x-locks its page. */UNIV_INLINEfsp_header_t*fsp_get_space_header(/*=================*/ /* out: pointer to the space header, page x-locked */ ulint id, /* in: space id */ mtr_t* mtr) /* in: mtr */{ fsp_header_t* header; ut_ad(mtr); header = FSP_HEADER_OFFSET + buf_page_get(id, 0, RW_X_LATCH, mtr);#ifdef UNIV_SYNC_DEBUG buf_page_dbg_add_level(header, SYNC_FSP_PAGE);#endif /* UNIV_SYNC_DEBUG */ return(header);}/**************************************************************************Gets a descriptor bit of a page. */UNIV_INLINEiboolxdes_get_bit(/*=========*/ /* out: TRUE if free */ 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 */ mtr_t* mtr) /* in: mtr */{ ulint index; ulint byte_index; ulint bit_index; ut_ad(mtr_memo_contains(mtr, buf_block_align(descr), MTR_MEMO_PAGE_X_FIX)); ut_ad((bit == XDES_FREE_BIT) || (bit == XDES_CLEAN_BIT)); ut_ad(offset < FSP_EXTENT_SIZE); index = bit + XDES_BITS_PER_PAGE * offset; byte_index = index / 8; bit_index = index % 8; return(ut_bit_get_nth( mtr_read_ulint(descr + XDES_BITMAP + byte_index, MLOG_1BYTE, mtr), bit_index)); } /**************************************************************************Sets a descriptor bit of a page. */UNIV_INLINEvoidxdes_set_bit(/*=========*/ 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 */ ibool val, /* in: bit value */ mtr_t* mtr) /* in: mtr */{ ulint index; ulint byte_index; ulint bit_index; ulint descr_byte; ut_ad(mtr_memo_contains(mtr, buf_block_align(descr), MTR_MEMO_PAGE_X_FIX)); ut_ad((bit == XDES_FREE_BIT) || (bit == XDES_CLEAN_BIT)); ut_ad(offset < FSP_EXTENT_SIZE); index = bit + XDES_BITS_PER_PAGE * offset; byte_index = index / 8; bit_index = index % 8; descr_byte = mtr_read_ulint(descr + XDES_BITMAP + byte_index, MLOG_1BYTE, mtr); descr_byte = ut_bit_set_nth(descr_byte, bit_index, val); mlog_write_ulint(descr + XDES_BITMAP + byte_index, descr_byte, MLOG_1BYTE, mtr);} /**************************************************************************Looks for a descriptor bit having the desired value. Starts from hintand scans upward; at the end of the extent the search is wrapped tothe start of the extent. */UNIV_INLINEulintxdes_find_bit(/*==========*/ /* out: bit index of the bit, ULINT_UNDEFINED if not found */ xdes_t* descr, /* in: descriptor */ ulint bit, /* in: XDES_FREE_BIT or XDES_CLEAN_BIT */ ibool val, /* in: desired bit value */ ulint hint, /* in: hint of which bit position would be desirable */ mtr_t* mtr) /* in: mtr */{ ulint i; ut_ad(descr && mtr); ut_ad(val <= TRUE); ut_ad(hint < FSP_EXTENT_SIZE); ut_ad(mtr_memo_contains(mtr, buf_block_align(descr), MTR_MEMO_PAGE_X_FIX)); for (i = hint; i < FSP_EXTENT_SIZE; i++) { if (val == xdes_get_bit(descr, bit, i, mtr)) { return(i); } } for (i = 0; i < hint; i++) { if (val == xdes_get_bit(descr, bit, i, mtr)) { return(i); } } return(ULINT_UNDEFINED); } /**************************************************************************Looks for a descriptor bit having the desired value. Scans the extent ina direction opposite to xdes_find_bit. */UNIV_INLINEulintxdes_find_bit_downward(/*===================*/ /* out: bit index of the bit, ULINT_UNDEFINED if not found */ xdes_t* descr, /* in: descriptor */ ulint bit, /* in: XDES_FREE_BIT or XDES_CLEAN_BIT */ ibool val, /* in: desired bit value */ ulint hint, /* in: hint of which bit position would be desirable */ mtr_t* mtr) /* in: mtr */{ ulint i; ut_ad(descr && mtr); ut_ad(val <= TRUE); ut_ad(hint < FSP_EXTENT_SIZE); ut_ad(mtr_memo_contains(mtr, buf_block_align(descr), MTR_MEMO_PAGE_X_FIX));
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -