@ -312,9 +312,8 @@ fsp_fill_free_list(
descriptor page and ibuf bitmap page ;
then we do not allocate more extents */
ulint space , /*!< in: space */
fsp_header_t * header , /*!< in/out: space header */
mtr_t * mtr ) /*!< in/out: mini-transaction */
__attribute__ ( ( nonnull ) ) ;
fsp_header_t * header , /*!< in: space header */
mtr_t * mtr ) ; /*!< in: mtr */
/**********************************************************************/ /**
Allocates a single free page from a segment . This function implements
the intelligent allocation strategy which tries to minimize file space
@ -334,13 +333,7 @@ fseg_alloc_free_page_low(
inserted there in order , into which
direction they go alphabetically : FSP_DOWN ,
FSP_UP , FSP_NO_DIR */
mtr_t * mtr , /*!< in/out: mini-transaction */
mtr_t * init_mtr ) /*!< in/out: mini-transaction in which the
page should be initialized
( may be the same as mtr ) , or NULL if it
should not be initialized ( the page at hint
was previously freed in mtr ) */
__attribute__ ( ( warn_unused_result , nonnull ( 3 , 6 ) ) ) ;
mtr_t * mtr ) ; /*!< in/out: mini-transaction */
# endif /* !UNIV_HOTBACKUP */
/**********************************************************************/ /**
@ -708,18 +701,17 @@ list, if not free limit == space size. This adding is necessary to make the
descriptor defined , as they are uninitialized above the free limit .
@ return pointer to the extent descriptor , NULL if the page does not
exist in the space or if the offset exceeds the free limit */
UNIV_INLINE __attribute__ ( ( nonnull , warn_unused_result ) )
UNIV_INLINE
xdes_t *
xdes_get_descriptor_with_space_hdr (
/*===============================*/
fsp_header_t * sp_header , /*!< in/out: space header, x-latched
in mtr */
ulint space , /*!< in: space id */
ulint offset , /*!< in: page offset; if equal
to the free limit , we try to
add new extents to the space
free list */
mtr_t * mtr ) /*!< in/out: mini-transaction */
fsp_header_t * sp_header , /*!< in/out: space header, x-latched */
ulint space , /*!< in: space id */
ulint offset , /*!< in: page offset;
if equal to the free limit ,
we try to add new extents to
the space free list */
mtr_t * mtr ) /*!< in: mtr handle */
{
ulint limit ;
ulint size ;
@ -727,9 +719,11 @@ xdes_get_descriptor_with_space_hdr(
ulint descr_page_no ;
page_t * descr_page ;
ut_ad ( mtr ) ;
ut_ad ( mtr_memo_contains ( mtr , fil_space_get_latch ( space , NULL ) ,
MTR_MEMO_X_LOCK ) ) ;
ut_ad ( mtr_memo_contains_page ( mtr , sp_header , MTR_MEMO_PAGE_X_FIX ) ) ;
ut_ad ( mtr_memo_contains_page ( mtr , sp_header , MTR_MEMO_PAGE_S_FIX )
| | mtr_memo_contains_page ( mtr , sp_header , MTR_MEMO_PAGE_X_FIX ) ) ;
ut_ad ( page_offset ( sp_header ) = = FSP_HEADER_OFFSET ) ;
/* Read free limit and space size */
limit = mach_read_from_4 ( sp_header + FSP_FREE_LIMIT ) ;
@ -779,7 +773,7 @@ is necessary to make the descriptor defined, as they are uninitialized
above the free limit .
@ return pointer to the extent descriptor , NULL if the page does not
exist in the space or if the offset exceeds the free limit */
static __attribute__ ( ( nonnull , warn_unused_result ) )
static
xdes_t *
xdes_get_descriptor (
/*================*/
@ -788,7 +782,7 @@ xdes_get_descriptor(
or 0 for uncompressed pages */
ulint offset , /*!< in: page offset; if equal to the free limit,
we try to add new extents to the space free list */
mtr_t * mtr ) /*!< in/out: mini-transaction */
mtr_t * mtr ) /*!< in: mtr handle */
{
buf_block_t * block ;
fsp_header_t * sp_header ;
@ -1166,14 +1160,14 @@ fsp_header_get_tablespace_size(void)
Tries to extend a single - table tablespace so that a page would fit in the
data file .
@ return TRUE if success */
static __attribute__ ( ( nonnull , warn_unused_result ) )
static
ibool
fsp_try_extend_data_file_with_pages (
/*================================*/
ulint space , /*!< in: space */
ulint page_no , /*!< in: page number */
fsp_header_t * header , /*!< in/out : space header */
mtr_t * mtr ) /*!< in/out : mini- transaction */
fsp_header_t * header , /*!< in: space header */
mtr_t * mtr ) /*!< in: mtr */
{
ibool success ;
ulint actual_size ;
@ -1198,7 +1192,7 @@ fsp_try_extend_data_file_with_pages(
/***********************************************************************/ /**
Tries to extend the last data file of a tablespace if it is auto - extending .
@ return FALSE if not auto - extending */
static __attribute__ ( ( nonnull ) )
static
ibool
fsp_try_extend_data_file (
/*=====================*/
@ -1208,8 +1202,8 @@ fsp_try_extend_data_file(
the actual file size rounded down to
megabyte */
ulint space , /*!< in: space */
fsp_header_t * header , /*!< in/out : space header */
mtr_t * mtr ) /*!< in/out : mini- transaction */
fsp_header_t * header , /*!< in: space header */
mtr_t * mtr ) /*!< in: mtr */
{
ulint size ;
ulint zip_size ;
@ -1345,7 +1339,7 @@ fsp_fill_free_list(
then we do not allocate more extents */
ulint space , /*!< in: space */
fsp_header_t * header , /*!< in/out: space header */
mtr_t * mtr ) /*!< in/out : mini- transaction */
mtr_t * mtr ) /*!< in: mtr */
{
ulint limit ;
ulint size ;
@ -1543,47 +1537,10 @@ fsp_alloc_free_extent(
return ( descr ) ;
}
/**********************************************************************/ /**
Allocates a single free page from a space . */
static __attribute__ ( ( nonnull ) )
void
fsp_alloc_from_free_frag (
/*=====================*/
fsp_header_t * header , /*!< in/out: tablespace header */
xdes_t * descr , /*!< in/out: extent descriptor */
ulint bit , /*!< in: slot to allocate in the extent */
mtr_t * mtr ) /*!< in/out: mini-transaction */
{
ulint frag_n_used ;
ut_ad ( xdes_get_state ( descr , mtr ) = = XDES_FREE_FRAG ) ;
ut_a ( xdes_get_bit ( descr , XDES_FREE_BIT , bit , mtr ) ) ;
xdes_set_bit ( descr , XDES_FREE_BIT , bit , FALSE , mtr ) ;
/* Update the FRAG_N_USED field */
frag_n_used = mtr_read_ulint ( header + FSP_FRAG_N_USED , MLOG_4BYTES ,
mtr ) ;
frag_n_used + + ;
mlog_write_ulint ( header + FSP_FRAG_N_USED , frag_n_used , MLOG_4BYTES ,
mtr ) ;
if ( xdes_is_full ( descr , mtr ) ) {
/* The fragment is full: move it to another list */
flst_remove ( header + FSP_FREE_FRAG , descr + XDES_FLST_NODE ,
mtr ) ;
xdes_set_state ( descr , XDES_FULL_FRAG , mtr ) ;
flst_add_last ( header + FSP_FULL_FRAG , descr + XDES_FLST_NODE ,
mtr ) ;
mlog_write_ulint ( header + FSP_FRAG_N_USED ,
frag_n_used - FSP_EXTENT_SIZE , MLOG_4BYTES ,
mtr ) ;
}
}
/**********************************************************************/ /**
Allocates a single free page from a space . The page is marked as used .
@ return the page offset , FIL_NULL if no page could be allocated */
static __attribute__ ( ( nonnull , warn_unused_result ) )
static
ulint
fsp_alloc_free_page (
/*================*/
@ -1591,22 +1548,19 @@ fsp_alloc_free_page(
ulint zip_size , /*!< in: compressed page size in bytes
or 0 for uncompressed pages */
ulint hint , /*!< in: hint of which page would be desirable */
mtr_t * mtr , /*!< in/out: mini-transaction */
mtr_t * init_mtr ) /*!< in/out: mini-transaction in which the
page should be initialized
( may be the same as mtr ) */
mtr_t * mtr ) /*!< in/out: mini-transaction */
{
fsp_header_t * header ;
fil_addr_t first ;
xdes_t * descr ;
buf_block_t * block ;
ulint free ;
ulint frag_n_used ;
ulint page_no ;
ulint space_size ;
ibool success ;
ut_ad ( mtr ) ;
ut_ad ( init_mtr ) ;
header = fsp_get_space_header ( space , zip_size , mtr ) ;
@ -1688,19 +1642,38 @@ fsp_alloc_free_page(
}
}
fsp_alloc_from_free_frag ( header , descr , free , mtr ) ;
xdes_set_bit ( descr , XDES_FREE_BIT , free , FALSE , mtr ) ;
/* Update the FRAG_N_USED field */
frag_n_used = mtr_read_ulint ( header + FSP_FRAG_N_USED , MLOG_4BYTES ,
mtr ) ;
frag_n_used + + ;
mlog_write_ulint ( header + FSP_FRAG_N_USED , frag_n_used , MLOG_4BYTES ,
mtr ) ;
if ( xdes_is_full ( descr , mtr ) ) {
/* The fragment is full: move it to another list */
flst_remove ( header + FSP_FREE_FRAG , descr + XDES_FLST_NODE ,
mtr ) ;
xdes_set_state ( descr , XDES_FULL_FRAG , mtr ) ;
flst_add_last ( header + FSP_FULL_FRAG , descr + XDES_FLST_NODE ,
mtr ) ;
mlog_write_ulint ( header + FSP_FRAG_N_USED ,
frag_n_used - FSP_EXTENT_SIZE , MLOG_4BYTES ,
mtr ) ;
}
/* Initialize the allocated page to the buffer pool, so that it can
be obtained immediately with buf_page_get without need for a disk
read . */
buf_page_create ( space , page_no , zip_size , init_mtr ) ;
buf_page_create ( space , page_no , zip_size , mtr ) ;
block = buf_page_get ( space , zip_size , page_no , RW_X_LATCH , init_mtr ) ;
block = buf_page_get ( space , zip_size , page_no , RW_X_LATCH , mtr ) ;
buf_block_dbg_add_level ( block , SYNC_FSP_PAGE ) ;
/* Prior contents of the page should be ignored */
fsp_init_file_page ( block , init_mtr ) ;
fsp_init_file_page ( block , mtr ) ;
return ( page_no ) ;
}
@ -1936,7 +1909,7 @@ fsp_alloc_seg_inode_page(
zip_size = dict_table_flags_to_zip_size (
mach_read_from_4 ( FSP_SPACE_FLAGS + space_header ) ) ;
page_no = fsp_alloc_free_page ( space , zip_size , 0 , mtr , mtr ) ;
page_no = fsp_alloc_free_page ( space , zip_size , 0 , mtr ) ;
if ( page_no = = FIL_NULL ) {
@ -2350,7 +2323,7 @@ fseg_create_general(
if ( page = = 0 ) {
page = fseg_alloc_free_page_low ( space , zip_size ,
inode , 0 , FSP_UP , mtr , mtr ) ;
inode , 0 , FSP_UP , mtr ) ;
if ( page = = FIL_NULL ) {
@ -2606,12 +2579,7 @@ fseg_alloc_free_page_low(
inserted there in order , into which
direction they go alphabetically : FSP_DOWN ,
FSP_UP , FSP_NO_DIR */
mtr_t * mtr , /*!< in/out: mini-transaction */
mtr_t * init_mtr ) /*!< in/out: mini-transaction in which the
page should be initialized
( may be the same as mtr ) , or NULL if it
should not be initialized ( the page at hint
was previously freed in mtr ) */
mtr_t * mtr ) /*!< in/out: mini-transaction */
{
fsp_header_t * space_header ;
ulint space_size ;
@ -2622,6 +2590,7 @@ fseg_alloc_free_page_low(
ulint ret_page ; /*!< the allocated page offset, FIL_NULL
if could not be allocated */
xdes_t * ret_descr ; /*!< the extent of the allocated page */
ibool frag_page_allocated = FALSE ;
ibool success ;
ulint n ;
@ -2643,8 +2612,6 @@ fseg_alloc_free_page_low(
if ( descr = = NULL ) {
/* Hint outside space or too high above free limit: reset
hint */
ut_a ( init_mtr ) ;
/* The file space header page is always allocated. */
hint = 0 ;
descr = xdes_get_descriptor ( space , zip_size , hint , mtr ) ;
}
@ -2656,20 +2623,15 @@ fseg_alloc_free_page_low(
mtr ) , seg_id ) )
& & ( xdes_get_bit ( descr , XDES_FREE_BIT ,
hint % FSP_EXTENT_SIZE , mtr ) = = TRUE ) ) {
take_hinted_page :
/* 1. We can take the hinted page
= = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = */
ret_descr = descr ;
ret_page = hint ;
/* Skip the check for extending the tablespace. If the
page hint were not within the size of the tablespace ,
we would have got ( descr = = NULL ) above and reset the hint . */
goto got_hinted_page ;
/*-----------------------------------------------------------*/
} else if ( xdes_get_state ( descr , mtr ) = = XDES_FREE
& & ( ! init_mtr
| | ( ( reserved - used < reserved / FSEG_FILLFACTOR )
& & used > = FSEG_FRAG_LIMIT ) ) ) {
} else if ( ( xdes_get_state ( descr , mtr ) = = XDES_FREE )
& & ( ( reserved - used ) < reserved / FSEG_FILLFACTOR )
& & ( used > = FSEG_FRAG_LIMIT ) ) {
/* 2. We allocate the free extent from space and can take
= = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =
@ -2687,20 +2649,8 @@ take_hinted_page:
/* Try to fill the segment free list */
fseg_fill_free_list ( seg_inode , space , zip_size ,
hint + FSP_EXTENT_SIZE , mtr ) ;
goto take_hinted_page ;
/*-----------------------------------------------------------*/
} else if ( ! init_mtr ) {
ut_a ( xdes_get_state ( descr , mtr ) = = XDES_FREE_FRAG ) ;
fsp_alloc_from_free_frag ( space_header , descr ,
hint % FSP_EXTENT_SIZE , mtr ) ;
ret_page = hint ;
ret_descr = NULL ;
/* Put the page in the fragment page array of the segment */
n = fseg_find_free_frag_page_slot ( seg_inode , mtr ) ;
ut_a ( n ! = FIL_NULL ) ;
fseg_set_nth_frag_page_no ( seg_inode , n , ret_page , mtr ) ;
goto got_hinted_page ;
/*-----------------------------------------------------------*/
} else if ( ( direction ! = FSP_NO_DIR )
& & ( ( reserved - used ) < reserved / FSEG_FILLFACTOR )
& & ( used > = FSEG_FRAG_LIMIT )
@ -2760,10 +2710,11 @@ take_hinted_page:
} else if ( used < FSEG_FRAG_LIMIT ) {
/* 6. We allocate an individual page from the space
= = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = */
ret_page = fsp_alloc_free_page ( space , zip_size , hint ,
mtr , init_mtr ) ;
ret_page = fsp_alloc_free_page ( space , zip_size , hint , mtr ) ;
ret_descr = NULL ;
frag_page_allocated = TRUE ;
if ( ret_page ! = FIL_NULL ) {
/* Put the page in the fragment page array of the
segment */
@ -2773,10 +2724,6 @@ take_hinted_page:
fseg_set_nth_frag_page_no ( seg_inode , n , ret_page ,
mtr ) ;
}
/* fsp_alloc_free_page() invoked fsp_init_file_page()
already . */
return ( ret_page ) ;
/*-----------------------------------------------------------*/
} else {
/* 7. We allocate a new extent and take its first page
@ -2824,34 +2771,26 @@ take_hinted_page:
}
}
got_hinted_page :
{
if ( ! frag_page_allocated ) {
/* Initialize the allocated page to buffer pool, so that it
can be obtained immediately with buf_page_get without need
for a disk read */
buf_block_t * block ;
ulint zip_size = dict_table_flags_to_zip_size (
mach_read_from_4 ( FSP_SPACE_FLAGS + space_header ) ) ;
mtr_t * block_mtr = init_mtr ? init_mtr : mtr ;
block = buf_page_create ( space , ret_page , zip_size , block_ mtr) ;
block = buf_page_create ( space , ret_page , zip_size , mtr ) ;
buf_block_dbg_add_level ( block , SYNC_FSP_PAGE ) ;
if ( UNIV_UNLIKELY ( block ! = buf_page_get ( space , zip_size ,
ret_page , RW_X_LATCH ,
block_ mtr) ) ) {
mtr ) ) ) {
ut_error ;
}
if ( init_mtr ) {
/* The prior contents of the page should be ignored */
fsp_init_file_page ( block , init_mtr ) ;
}
}
/* The prior contents of the page should be ignored */
fsp_init_file_page ( block , mtr ) ;
/* ret_descr == NULL if the block was allocated from free_frag
( XDES_FREE_FRAG ) */
if ( ret_descr ! = NULL ) {
/* At this point we know the extent and the page offset.
The extent is still in the appropriate list ( FSEG_NOT_FULL
or FSEG_FREE ) , and the page is not yet marked as used . */
@ -2888,11 +2827,7 @@ fseg_alloc_free_page_general(
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 handle */
mtr_t * init_mtr ) /*!< in/out: mtr or another mini-transaction
in which the page should be initialized ,
or NULL if this is a " fake allocation " of
a page that was previously freed in mtr */
mtr_t * mtr ) /*!< in/out: mini-transaction */
{
fseg_inode_t * inode ;
ulint space ;
@ -2934,8 +2869,7 @@ fseg_alloc_free_page_general(
}
page_no = fseg_alloc_free_page_low ( space , zip_size ,
inode , hint , direction ,
mtr , init_mtr ) ;
inode , hint , direction , mtr ) ;
if ( ! has_done_reservation ) {
fil_space_release_free_extents ( space , n_reserved ) ;
}
@ -2943,6 +2877,28 @@ fseg_alloc_free_page_general(
return ( page_no ) ;
}
/**********************************************************************/ /**
Allocates a single free page from a segment . This function implements
the intelligent allocation strategy which tries to minimize file space
fragmentation .
@ return allocated page offset , FIL_NULL if no page could be allocated */
UNIV_INTERN
ulint
fseg_alloc_free_page (
/*=================*/
fseg_header_t * seg_header , /*!< in: 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 */
mtr_t * mtr ) /*!< in: mtr handle */
{
return ( fseg_alloc_free_page_general ( seg_header , hint , direction ,
FALSE , mtr ) ) ;
}
/**********************************************************************/ /**
Checks that we have at least 2 frag pages free in the first extent of a
single - table tablespace , and they are also physically initialized to the data