summaryrefslogtreecommitdiff
path: root/innobase/fsp
diff options
context:
space:
mode:
authorunknown <monty@mashka.mysql.fi>2004-02-20 17:43:02 +0200
committerunknown <monty@mashka.mysql.fi>2004-02-20 17:43:02 +0200
commit8b2b219fb5e1374abdd816d9d0911d37087c86a5 (patch)
treee13a23a1c9f28ed5eb2d903ba59a153cda3355ac /innobase/fsp
parent51a6b4f47ad03031105b0f8ac810d522a804695e (diff)
parent9bc5cdba41a0d2bc3c391469b14168f82e636a6b (diff)
downloadmariadb-git-8b2b219fb5e1374abdd816d9d0911d37087c86a5.tar.gz
merge with 4.0 to get security fixes and latest bug fixes
BitKeeper/etc/logging_ok: auto-union configure.in: Auto merged BitKeeper/deleted/.del-mini_client.cc~8677895ec8169183: Auto merged VC++Files/mysql.dsw: Auto merged VC++Files/mysys/mysys.dsp: Auto merged innobase/buf/buf0buf.c: Auto merged innobase/include/srv0start.h: Auto merged innobase/lock/lock0lock.c: Auto merged innobase/mem/mem0dbg.c: Auto merged innobase/que/que0que.c: Auto merged innobase/srv/srv0start.c: Auto merged innobase/sync/sync0rw.c: Auto merged innobase/sync/sync0sync.c: Auto merged innobase/trx/trx0trx.c: Auto merged libmysql/manager.c: Auto merged sql/ha_innodb.cc: Auto merged sql/sql_load.cc: Auto merged sql/sql_yacc.yy: Auto merged sql/unireg.cc: Auto merged VC++Files/sql/mysqld.dsp: Removed wrong define USE_SYMLINK include/config-win.h: Use original code innobase/srv/srv0srv.c: merge innobase/usr/usr0sess.c: merge libmysql/libmysql.c: merge mysql-test/r/func_test.result: merge mysql-test/t/func_test.test: merge sql/log.cc: merge sql/mysqld.cc: merge
Diffstat (limited to 'innobase/fsp')
-rw-r--r--innobase/fsp/trash/FSP0FSP.C3100
-rw-r--r--innobase/fsp/ts/del.c891
-rw-r--r--innobase/fsp/ts/makefile16
-rw-r--r--innobase/fsp/ts/tsfsp.c1234
4 files changed, 0 insertions, 5241 deletions
diff --git a/innobase/fsp/trash/FSP0FSP.C b/innobase/fsp/trash/FSP0FSP.C
deleted file mode 100644
index b0add437bff..00000000000
--- a/innobase/fsp/trash/FSP0FSP.C
+++ /dev/null
@@ -1,3100 +0,0 @@
-/**********************************************************************
-File-space management
-
-(c) 1995 Innobase Oy
-
-Created 11/29/1995 Heikki Tuuri
-***********************************************************************/
-
-#include "fsp0fsp.h"
-
-#include "buf0buf.h"
-#include "fil0fil.h"
-#include "sync0sync.h"
-#include "mtr0log.h"
-#include "fut0fut.h"
-#include "ut0byte.h"
-
-/* The data structures in files are defined just as byte strings in C */
-typedef byte fsp_header_t;
-typedef byte xdes_t;
-typedef byte fseg_page_header_t;
-
-/* Rw-latch protecting the whole file space system */
-rw_lock_t fsp_latch;
-
-
-/* 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_HEADER_OFFSET FIL_PAGE_DATA /* Offset of the space header
- within a file page */
-/*-------------------------------------*/
-#define FSP_SIZE 0 /* Current
- size of the space in pages */
-#define FSP_FREE_LIMIT 4 /* Minimum page number for which
- the free list has not been initialized:
- the pages >= this limit are, by
- definition, free */
-#define FSP_LOWEST_NO_WRITE 8 /* 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 12 /* number of used pages in
- the FSP_FREE_FRAG list */
-#define FSP_FREE 16 /* list of free extents */
-#define FSP_FREE_FRAG (16 + FLST_BASE_NODE_SIZE)
- /* list of partially free extents not
- belonging to any segment */
-#define FSP_FULL_FRAG (16 + 2 * FLST_BASE_NODE_SIZE)
- /* list of full extents not belonging
- to any segment */
-#define FSP_SEG_ID (16 + 3 * FLST_BASE_NODE_SIZE)
- /* 8 bytes which give the first
-#define FSP_SEG_HDRS_FULL (24 + 3 * FLST_BASE_NODE_SIZE)
- /* list of pages containing segment
- headers, where all the segment header
- slots are reserved */
-#define FSP_SEG_HDRS_FREE (24 + 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 (24 + 4 * 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 */
-
-
-/* SEGMENT HEADER
- ==============
-
-Segment header which is created for each segment in a tablespace, on a
-page of its own. 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. */
-
-#define FSEG_HDR_PAGE_NODE FSEG_PAGE_DATA
- /* the list node for linking
- segment header 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_HEADER_SIZE (16 + 3 * FLST_BASE_NODE_SIZE +\
- FSEG_FRAG_ARR_N_SLOTS * FSEG_FRAG_SLOT_SIZE)
-
-#define FSP_SEG_HDRS_PER_PAGE ((UNIV_PAGE_SIZE - FSEG_ARR_OFFSET - 10)\
- / FSEG_HEADER_SIZE)
- /* Number of segment headers 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_N_ARR_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 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 /* 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*/
-
-/* Number of pages described in a single descriptor page:
-currently each page description takes less than
-1 byte. */
-#define XDES_DESCRIBED_PER_PAGE UNIV_PAGE_SIZE
-
-/* File extent data structure size in bytes. The "+ 7 ) / 8"
-part in the definition 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. */
-static
-void
-fsp_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. */
-static
-void
-fseg_free_extent(
-/*=============*/
- fseg_header_t* seg_header, /* in: segment header */
- 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 how
-many pages are currently used. */
-static
-ulint
-fseg_n_reserved_pages_low(
-/*======================*/
- /* out: number of reserved pages */
- fseg_header_t* header, /* in: segment header */
- 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 given
-segment. */
-static
-void
-fseg_mark_page_used(
-/*================*/
- fseg_header_t* seg_header,/* in: segment header */
- ulint space, /* in: space id */
- ulint page, /* in: page offset */
- mtr_t* mtr); /* in: mtr */
-/**************************************************************************
-Frees a single page of a segment. */
-static
-void
-fseg_free_page_low(
-/*===============*/
- fseg_header_t* seg_header, /* in: segment header */
- ulint space, /* in: space id */
- ulint page, /* in: page offset */
- mtr_t* mtr); /* in: mtr handle */
-/**************************************************************************
-Returns the first extent descriptor for a segment. We think of the extent
-lists of the segment catenated in the order FSEG_FULL -> FSEG_NOT_FULL
--> FSEG_FREE. */
-static
-xdes_t*
-fseg_get_first_extent(
-/*==================*/
- /* out: the first extent descriptor, or NULL if
- none */
- fseg_header_t* header, /* in: segment header */
- mtr_t* mtr); /* in: mtr */
-/**************************************************************************
-Puts new extents to the free list if
-there are free extents above the free limit. If an extent happens
-to contain an extent descriptor page, the extent is put to
-the FSP_FREE_FRAG list with the page marked as used. */
-static
-void
-fsp_fill_free_list(
-/*===============*/
- ulint space, /* in: space */
- fsp_header_t* header, /* in: space header */
- mtr_t* mtr); /* in: mtr */
-
-/**************************************************************************
-Gets a descriptor bit of a page. */
-UNIV_INLINE
-bool
-xdes_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_LOCK));
- 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_INLINE
-void
-xdes_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 */
- bool 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_LOCK));
- 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 hint
-and scans upward; at the end of the extent the search is wrapped to
-the start of the extent. */
-UNIV_INLINE
-ulint
-xdes_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 */
- bool 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_LOCK));
-
- 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 in
-a direction opposite to xdes_find_bit. */
-UNIV_INLINE
-ulint
-xdes_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 */
- bool 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_LOCK));
-
- for (i = hint + 1; i > 0; i--) {
- if (val == xdes_get_bit(descr, bit, i - 1, mtr)) {
- return(i - 1);
- }
- }
-
- for (i = FSP_EXTENT_SIZE - 1; i > hint; i--) {
- if (val == xdes_get_bit(descr, bit, i, mtr)) {
- return(i);
- }
- }
-
- return(ULINT_UNDEFINED);
-}
-
-/**************************************************************************
-Returns the number of used pages in a descriptor. */
-UNIV_INLINE
-ulint
-xdes_get_n_used(
-/*============*/
- /* out: number of pages used */
- xdes_t* descr, /* in: descriptor */
- mtr_t* mtr) /* in: mtr */
-{
- ulint i;
- ulint count = 0;
-
- ut_ad(descr && mtr);
- ut_ad(mtr_memo_contains(mtr, buf_block_align(descr),
- MTR_MEMO_PAGE_X_LOCK));
-
- for (i = 0; i < FSP_EXTENT_SIZE; i++) {
- if (FALSE == xdes_get_bit(descr, XDES_FREE_BIT, i, mtr)) {
- count++;
- }
- }
-
- return(count);
-}
-
-/**************************************************************************
-Returns true if extent contains no used pages. */
-UNIV_INLINE
-bool
-xdes_is_free(
-/*=========*/
- /* out: TRUE if totally free */
- xdes_t* descr, /* in: descriptor */
- mtr_t* mtr) /* in: mtr */
-{
- if (0 == xdes_get_n_used(descr, mtr)) {
- return(TRUE);
- } else {
- return(FALSE);
- }
-}
-
-/**************************************************************************
-Returns true if extent contains no free pages. */
-UNIV_INLINE
-bool
-xdes_is_full(
-/*=========*/
- /* out: TRUE if full */
- xdes_t* descr, /* in: descriptor */
- mtr_t* mtr) /* in: mtr */
-{
- if (FSP_EXTENT_SIZE == xdes_get_n_used(descr, mtr)) {
- return(TRUE);
- } else {
- return(FALSE);
- }
-}
-
-/**************************************************************************
-Sets the state of an xdes. */
-UNIV_INLINE
-void
-xdes_set_state(
-/*===========*/
- xdes_t* descr, /* in: descriptor */
- ulint state, /* in: state to set */
- mtr_t* mtr) /* in: mtr handle */
-{
- ut_ad(descr && mtr);
- ut_ad(state >= XDES_FREE);
- ut_ad(state <= XDES_FSEG);
- ut_ad(mtr_memo_contains(mtr, buf_block_align(descr),
- MTR_MEMO_PAGE_X_LOCK));
-
- mlog_write_ulint(descr + XDES_STATE, state, MLOG_4BYTES, mtr);
-}
-
-/**************************************************************************
-Gets the state of an xdes. */
-UNIV_INLINE
-ulint
-xdes_get_state(
-/*===========*/
- /* out: state */
- xdes_t* descr, /* in: descriptor */
- mtr_t* mtr) /* in: mtr handle */
-{
- ut_ad(descr && mtr);
- ut_ad(mtr_memo_contains(mtr, buf_block_align(descr),
- MTR_MEMO_PAGE_X_LOCK));
-
- return(mtr_read_ulint(descr + XDES_STATE, MLOG_4BYTES, mtr));
-}
-
-/**************************************************************************
-Inits an extent descriptor to free and clean state. */
-UNIV_INLINE
-void
-xdes_init(
-/*======*/
- xdes_t* descr, /* in: descriptor */
- mtr_t* mtr) /* in: mtr */
-{
- ulint i;
-
- ut_ad(descr && mtr);
- ut_ad(mtr_memo_contains(mtr, buf_block_align(descr),
- MTR_MEMO_PAGE_X_LOCK));
-
- for (i = 0; i < FSP_EXTENT_SIZE; i++) {
- xdes_set_bit(descr, XDES_FREE_BIT, i, TRUE, mtr);
- xdes_set_bit(descr, XDES_CLEAN_BIT, i, TRUE, mtr);
- }
-
- xdes_set_state(descr, XDES_FREE, mtr);
-}
-
-/************************************************************************
-Calculates the page where the descriptor of a page resides. */
-UNIV_INLINE
-ulint
-xdes_calc_descriptor_page(
-/*======================*/
- /* out: descriptor page offset */
- ulint offset) /* in: page offset */
-{
- ut_ad(UNIV_PAGE_SIZE > XDES_ARR_OFFSET
- + (XDES_DESCRIBED_PER_PAGE / FSP_EXTENT_SIZE) * XDES_SIZE);
-
- return(ut_2pow_round(offset, XDES_DESCRIBED_PER_PAGE));
-}
-
-/************************************************************************
-Calculates the descriptor index within a descriptor page. */
-UNIV_INLINE
-ulint
-xdes_calc_descriptor_index(
-/*=======================*/
- /* out: descriptor index */
- ulint offset) /* in: page offset */
-{
- return(ut_2pow_remainder(offset, XDES_DESCRIBED_PER_PAGE) /
- FSP_EXTENT_SIZE);
-}
-
-/************************************************************************
-Gets pointer to a the extent descriptor of a page. The page where the
-extent descriptor resides is x-locked. If the page offset is equal to the free
-limit of the space, adds new extents from above the free limit
-to the space free list, if not free limit == space size. This adding
-is necessary to make the descriptor defined, as they are uninitialized
-above the free limit. */
-UNIV_INLINE
-xdes_t*
-xdes_get_descriptor_with_space_hdr(
-/*===============================*/
- /* out: pointer to the extent descriptor,
- NULL if the page does not exist in the
- space or if offset > free limit */
- fsp_header_t* sp_header,/* in: 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;
- buf_block_t* buf_page;
- ulint descr_page_no;
- page_t* descr_page;
-
- ut_ad(mtr);
- ut_ad(mtr_memo_contains(mtr, &fsp_latch, MTR_MEMO_X_LOCK));
-
- /* Read free limit and space size */
- limit = mtr_read_ulint(sp_header + FSP_FREE_LIMIT, MLOG_4BYTES, mtr);
- size = mtr_read_ulint(sp_header + FSP_SIZE, MLOG_4BYTES, mtr);
-
- /* If offset is >= size or > limit, return NULL */
- if ((offset >= size) || (offset > limit)) {
- return(NULL);
- }
-
- /* If offset is == limit, fill free list of the space. */
- if (offset == limit) {
- fsp_fill_free_list(space, sp_header, mtr);
- }
-
- descr_page_no = xdes_calc_descriptor_page(offset);
-
- if (descr_page_no == 0) {
- /* It is on the space header page */
-
- descr_page = buf_frame_align(sp_header);
- } else {
-
- buf_page = buf_page_get(space, descr_page_no, mtr);
- buf_page_x_lock(buf_page, mtr);
- descr_page = buf_block_get_frame(buf_page);
- }
-
- return(descr_page + XDES_ARR_OFFSET
- + XDES_SIZE * xdes_calc_descriptor_index(offset));
-}
-
-/************************************************************************
-Gets pointer to a the extent descriptor of a page. The page where the
-extent descriptor resides is x-locked. If the page offset is equal to the free
-limit of the space, adds new extents from above the free limit
-to the space free list, if not free limit == space size. This adding
-is necessary to make the descriptor defined, as they are uninitialized
-above the free limit. */
-static
-xdes_t*
-xdes_get_descriptor(
-/*================*/
- /* out: pointer to the extent descriptor,
- NULL if the page does not exist in the
- space or if offset > free limit */
- 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 */
-{
- fsp_header_t* sp_header;
- buf_block_t* block;
-
- block = buf_page_get(space, 0, mtr); /* get space header */
- sp_header = FSP_HEADER_OFFSET + buf_block_get_frame(block);
- buf_page_x_lock(block, mtr);
-
- return(xdes_get_descriptor_with_space_hdr(sp_header, space, offset,
- mtr));
-}
-
-/************************************************************************
-Gets pointer to a the extent descriptor if the file address
-of the descriptor list node is known. The page where the
-extent descriptor resides is x-locked. */
-UNIV_INLINE
-xdes_t*
-xdes_lst_get_descriptor(
-/*====================*/
- /* out: pointer to the extent descriptor */
- ulint space, /* in: space id */
- fil_addr_t lst_node,/* in: file address of the list node
- contained in the descriptor */
- mtr_t* mtr) /* in: mtr handle */
-{
- xdes_t* descr;
-
- ut_ad(mtr);
- ut_ad(mtr_memo_contains(mtr, &fsp_latch, MTR_MEMO_X_LOCK));
-
- descr = fut_get_ptr_x_lock(space, lst_node, mtr) - XDES_FLST_NODE;
-
- return(descr);
-}
-
-/************************************************************************
-Gets pointer to the next descriptor in a descriptor list and x-locks
-its page. */
-UNIV_INLINE
-xdes_t*
-xdes_lst_get_next(
-/*==============*/
- xdes_t* descr, /* in: pointer to a descriptor */
- mtr_t* mtr) /* in: mtr handle */
-{
- ulint space;
-
- ut_ad(mtr && descr);
-
- space = buf_page_get_space(buf_block_align(descr));
-
- return(xdes_lst_get_descriptor(space,
- flst_get_next_addr(descr + XDES_FLST_NODE, mtr), mtr));
-}
-
-/************************************************************************
-Returns page offset of the first page in extent described by a descriptor.
-*/
-UNIV_INLINE
-ulint
-xdes_get_offset(
-/*============*/
- /* out: offset of the first page in extent */
- xdes_t* descr) /* in: extent descriptor */
-{
- buf_block_t* buf_page;
-
- ut_ad(descr);
-
- buf_page = buf_block_align(descr);
-
- return(buf_page_get_offset(buf_page)
- + ((descr - buf_frame_align(descr) - XDES_ARR_OFFSET)
- / XDES_SIZE)
- * FSP_EXTENT_SIZE);
-}
-
-/**************************************************************************
-Gets a pointer to the space header and x-locks its page. */
-UNIV_INLINE
-fsp_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 */
-{
- buf_block_t* block;
-
- ut_ad(mtr);
-
- block = buf_page_get(id, 0, mtr);
-
- buf_page_x_lock(block, mtr);
-
- return(FSP_HEADER_OFFSET + buf_block_get_frame(block));
-}
-
-/**************************************************************************
-Initializes the file space system mutex. */
-
-void
-fsp_init(void)
-/*==========*/
-{
- rw_lock_create(&fsp_latch);
-}
-
-/**************************************************************************
-Initializes the space header of a new created space. */
-
-void
-fsp_header_init(
-/*============*/
- ulint space, /* in: space id */
- ulint size, /* in: current size in blocks */
- mtr_t* mtr) /* in: mini-transaction handle */
-{
- fsp_header_t* header;
-
- ut_ad(mtr);
-
- mtr_x_lock(&fsp_latch, mtr);
-
- header = fsp_get_space_header(space, mtr);
-
- mlog_write_ulint(header + FSP_SIZE, size, MLOG_4BYTES, mtr);
- mlog_write_ulint(header + FSP_FREE_LIMIT, 0, MLOG_4BYTES, mtr);
- mlog_write_ulint(header + FSP_LOWEST_NO_WRITE, 0, MLOG_4BYTES, mtr);
- mlog_write_ulint(header + FSP_FRAG_N_USED, 0, MLOG_4BYTES, mtr);
-
- flst_init(header + FSP_FREE, mtr);
- flst_init(header + FSP_FREE_FRAG, mtr);
- flst_init(header + FSP_FULL_FRAG, mtr);
- flst_init(header + FSP_SEG_HDRS_FULL, mtr);
- flst_init(header + FSP_SEG_HDRS_FREE, mtr);
-
- mlog_write_dulint(header + FSP_SEG_ID, ut_dulint_create(0, 1),
- MLOG_8BYTES, mtr);
-}
-
-/**************************************************************************
-Increases the space size field of a space. */
-
-void
-fsp_header_inc_size(
-/*================*/
- ulint space, /* in: space id */
- ulint size_inc,/* in: size increment in pages */
- mtr_t* mtr) /* in: mini-transaction handle */
-{
- fsp_header_t* header;
- ulint size;
-
- ut_ad(mtr);
-
- mtr_x_lock(&fsp_latch, mtr);
-
- header = fsp_get_space_header(space, mtr);
-
- size = mtr_read_ulint(header + FSP_SIZE, MLOG_4BYTES, mtr);
- mlog_write_ulint(header + FSP_SIZE, size + size_inc, MLOG_4BYTES, mtr);
-}
-
-/**************************************************************************
-Puts new extents to the free list if there are free extents above the free
-limit. If an extent happens to contain an extent descriptor page, the extent
-is put to the FSP_FREE_FRAG list with the page marked as used. */
-static
-void
-fsp_fill_free_list(
-/*===============*/
- ulint space, /* in: space */
- fsp_header_t* header, /* in: space header */
- mtr_t* mtr) /* in: mtr */
-{
- ulint limit;
- ulint size;
- ulint i;
- xdes_t* descr;
- ulint count = 0;
- ulint frag_n_used;
-
- ut_ad(header && mtr);
-
- /* Check if we can fill free list from above the free list limit */
- size = mtr_read_ulint(header + FSP_SIZE, MLOG_4BYTES, mtr);
- limit = mtr_read_ulint(header + FSP_FREE_LIMIT, MLOG_4BYTES, mtr);
-
- i = limit;
- while ((i + FSP_EXTENT_SIZE <= size) && (count < FSP_FREE_ADD)) {
- mlog_write_ulint(header + FSP_FREE_LIMIT,
- i + FSP_EXTENT_SIZE, MLOG_4BYTES, mtr);
-
- descr = xdes_get_descriptor_with_space_hdr(header, space, i,
- mtr);
- xdes_init(descr, mtr);
-
- ut_ad(XDES_DESCRIBED_PER_PAGE % FSP_EXTENT_SIZE == 0);
-
- if (0 == i % XDES_DESCRIBED_PER_PAGE) {
- /* The first page in the extent is a descriptor page:
- mark it used */
- xdes_set_bit(descr, XDES_FREE_BIT, 0, FALSE, mtr);
- xdes_set_state(descr, XDES_FREE_FRAG, mtr);
- flst_add_last(header + FSP_FREE_FRAG,
- descr + XDES_FLST_NODE, mtr);
- frag_n_used = mtr_read_ulint(header + FSP_FRAG_N_USED,
- MLOG_4BYTES, mtr);
- mlog_write_ulint(header + FSP_FRAG_N_USED,
- frag_n_used + 1,
- MLOG_4BYTES, mtr);
- } else {
- flst_add_last(header + FSP_FREE,
- descr + XDES_FLST_NODE, mtr);
- count++;
- }
- i += FSP_EXTENT_SIZE;
- }
-}
-
-/**************************************************************************
-Allocates a new free extent. */
-static
-xdes_t*
-fsp_alloc_free_extent(
-/*==================*/
- /* out: extent descriptor, NULL if cannot
- be allocated */
- ulint space, /* in: space id */
- ulint hint, /* in: hint of which extent would be
- desirable: any page offset in the extent
- goes; the hint must not be > FSP_FREE_LIMIT */
- mtr_t* mtr) /* in: mtr */
-{
- fsp_header_t* header;
- fil_addr_t first;
- xdes_t* descr;
-
- ut_ad(mtr);
-
- header = fsp_get_space_header(space, mtr);
-
- descr = xdes_get_descriptor_with_space_hdr(header, space, hint, mtr);
-
- if (descr && (xdes_get_state(descr, mtr) == XDES_FREE)) {
- /* Ok, we can take this extent */
- } else {
- /* Take the first extent in the free list */
- first = flst_get_first(header + FSP_FREE, mtr);
-
- if (fil_addr_is_null(first)) {
- fsp_fill_free_list(space, header, mtr);
- first = flst_get_first(header + FSP_FREE, mtr);
- }
-
- if (fil_addr_is_null(first)) {
- return(NULL); /* No free extents left */
- }
-
- descr = xdes_lst_get_descriptor(space, first, mtr);
- }
-
- flst_remove(header + FSP_FREE, descr + XDES_FLST_NODE, mtr);
-
- return(descr);
-}
-
-/**************************************************************************
-Allocates a single free page from a space. The page is marked as used. */
-static
-ulint
-fsp_alloc_free_page(
-/*================*/
- /* out: the page offset, FIL_NULL
- if no page could be allocated */
- ulint space, /* in: space id */
- ulint hint, /* in: hint of which page would be desirable */
- mtr_t* mtr) /* in: mtr handle */
-{
- fsp_header_t* header;
- fil_addr_t first;
- xdes_t* descr;
- ulint free;
- ulint frag_n_used;
-
- ut_ad(mtr);
-
- header = fsp_get_space_header(space, mtr);
-
- /* Get the hinted descriptor */
- descr = xdes_get_descriptor_with_space_hdr(header, space, hint, mtr);
-
- if (descr && (xdes_get_state(descr, mtr) == XDES_FREE_FRAG)) {
- /* Ok, we can take this extent */
- } else {
- /* Else take the first extent in free_frag list */
- first = flst_get_first(header + FSP_FREE_FRAG, mtr);
-
- if (fil_addr_is_null(first)) {
- /* There are no partially full fragments: allocate
- a free extent and add it to the FREE_FRAG
- list. NOTE that the allocation may have as a
- side-effect that an extent containing a descriptor
- page is added to the FREE_FRAG list. But we will
- allocate our page from the allocated free extent. */
-
- descr = fsp_alloc_free_extent(space, hint, mtr);
-
- if (descr == NULL) {
- /* No free space left */
- return(FIL_NULL);
- }
-
- xdes_set_state(descr, XDES_FREE_FRAG, mtr);
- flst_add_last(header + FSP_FREE_FRAG,
- descr + XDES_FLST_NODE, mtr);
- } else {
- descr = xdes_lst_get_descriptor(space, first, mtr);
- }
-
- /* Reset the hint */
- hint = 0;
- }
-
- /* Now we have in descr an extent with at least one free page.
- Look for a free page in the extent. */
- free = xdes_find_bit(descr, XDES_FREE_BIT, TRUE,
- hint % FSP_EXTENT_SIZE, mtr);
- ut_a(free != ULINT_UNDEFINED);
-
- 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);
- }
- return(xdes_get_offset(descr) + free);
-}
-
-/**************************************************************************
-Frees a single page of a space. The page is marked as free and clean. */
-static
-void
-fsp_free_page(
-/*==========*/
- ulint space, /* in: space id */
- ulint page, /* in: page offset */
- mtr_t* mtr) /* in: mtr handle */
-{
- fsp_header_t* header;
- xdes_t* descr;
- ulint state;
- ulint frag_n_used;
-
- ut_ad(mtr);
-
- header = fsp_get_space_header(space, mtr);
-
- descr = xdes_get_descriptor_with_space_hdr(header, space, page, mtr);
-
- state = xdes_get_state(descr, mtr);
-
- ut_a((state == XDES_FREE_FRAG) || (state == XDES_FULL_FRAG));
-
- ut_a(xdes_get_bit(descr, XDES_FREE_BIT, page % FSP_EXTENT_SIZE, mtr)
- == FALSE);
-
- xdes_set_bit(descr, XDES_FREE_BIT, page % FSP_EXTENT_SIZE, TRUE, mtr);
- xdes_set_bit(descr, XDES_CLEAN_BIT, page % FSP_EXTENT_SIZE, TRUE, mtr);
-
- frag_n_used = mtr_read_ulint(header + FSP_FRAG_N_USED,
- MLOG_4BYTES, mtr);
-
- if (state == XDES_FULL_FRAG) {
- /* The fragment was full: move it to another list */
- flst_remove(header + FSP_FULL_FRAG,
- descr + XDES_FLST_NODE, mtr);
- xdes_set_state(descr, XDES_FREE_FRAG, mtr);
- flst_add_last(header + FSP_FREE_FRAG,
- descr + XDES_FLST_NODE, mtr);
- mlog_write_ulint(header + FSP_FRAG_N_USED,
- frag_n_used + FSP_EXTENT_SIZE - 1,
- MLOG_4BYTES, mtr);
- } else {
- ut_a(frag_n_used > 0);
- mlog_write_ulint(header + FSP_FRAG_N_USED, frag_n_used - 1,
- MLOG_4BYTES, mtr);
- }
-
- if (xdes_is_free(descr, mtr)) {
- /* The extent has become free: move it to another list */
- flst_remove(header + FSP_FREE_FRAG,
- descr + XDES_FLST_NODE, mtr);
- fsp_free_extent(space, page, mtr);
- }
-}
-
-/**************************************************************************
-Returns an extent to the free list of a space. */
-static
-void
-fsp_free_extent(
-/*============*/
- ulint space, /* in: space id */
- ulint page, /* in: page offset in the extent */
- mtr_t* mtr) /* in: mtr */
-{
- fsp_header_t* header;
- xdes_t* descr;
-
- ut_ad(mtr);
-
- header = fsp_get_space_header(space, mtr);
-
- descr = xdes_get_descriptor_with_space_hdr(header, space, page, mtr);
-
- ut_a(xdes_get_state(descr, mtr) != XDES_FREE);
-
- xdes_init(descr, mtr);
-
- flst_add_last(header + FSP_FREE, descr + XDES_FLST_NODE, mtr);
-}
-
-/**************************************************************************
-Looks for an unused segment header on a segment header page. */
-UNIV_INLINE
-fseg_header_t*
-fsp_seg_hdr_page_get_nth_hdr(
-/*=========================*/
- /* out: segment header */
- page_t* page, /* in: segment header page */
- ulint i, /* in: search forward starting from this index */
- mtr_t* mtr) /* in: mini-transaction handle */
-{
- ut_ad(i < FSP_SEG_HDRS_PER_PAGE);
- ut_ad(mtr_memo_contains(mtr, page, MTR_MEMO_PAGE_X_LOCK));
-
- return(page + FSEG_ARR_OFFSET + FSEG_HEADER_SIZE * i);
-}
-
-/**************************************************************************
-Looks for a used segment header on a segment header page. */
-static
-ulint
-fsp_seg_hdr_page_find_used(
-/*=======================*/
- /* out: segment header index, or ULINT_UNDEFINED
- if not found */
- page_t* page, /* in: segment header page */
- mtr_t* mtr) /* in: mini-transaction handle */
-{
- ulint i;
- fseg_header_t* header;
-
- for (i = 0; i < FSP_SEG_HDRS_PER_PAGE; i++) {
-
- header = fsp_seg_hdr_page_get_nth_hdr(page, i, mtr);
-
- if (ut_dulint_cmp(mach_read_from_8(header + FSEG_ID),
- ut_dulint_zero) != 0) {
- /* This is used */
-
- return(i);
- }
- }
-
- return(ULINT_UNDEFINED);
-}
-
-/**************************************************************************
-Looks for an unused segment header on a segment header page. */
-static
-ulint
-fsp_seg_hdr_page_find_free(
-/*=======================*/
- /* out: segment header index, or ULINT_UNDEFINED
- if not found */
- page_t* page, /* in: segment header page */
- ulint j, /* in: search forward starting from this index */
- mtr_t* mtr) /* in: mini-transaction handle */
-{
- ulint i;
- fseg_header_t* header;
-
- for (i = j; i < FSP_SEG_HDRS_PER_PAGE; i++) {
-
- header = fsp_seg_hdr_page_get_nth_hdr(page, i, mtr);
-
- if (ut_dulint_cmp(mach_read_from_8(header + FSEG_ID),
- ut_dulint_zero) == 0) {
- /* This is unused */
-
- return(i);
- }
- }
-
- return(ULINT_UNDEFINED);
-}
-
-/**************************************************************************
-Allocates a new file segment header page. */
-static
-bool
-fsp_alloc_seg_hdr_page(
-/*===================*/
- /* out: TRUE if could be allocated */
- fsp_header_t* space_header, /* in: space header */
- mtr_t* mtr) /* in: mini-transaction handle */
-{
- buf_block_t* block;
- ulint page_no;
- page_t* page;
- fseg_header_t* header;
- ulint i;
-
- page_no = fsp_alloc_free_page(buf_frame_get_space(space_header),
- 0, mtr);
- if (page_no == FIL_NULL) {
-
- return(FALSE);
- }
-
- block = buf_page_get(buf_frame_get_space(space_header), page_no, mtr);
-
- buf_page_x_lock(block, mtr);
-
- page = buf_block_get_frame(block);
-
- for (i = 0; i < FSP_SEG_HDRS_PER_PAGE; i++) {
-
- header = fsp_seg_hdr_page_get_nth_hdr(page, i, mtr);
-
- mlog_write_dulint(header + FSEG_ID, ut_dulint_zero,
- MLOG_8BYTES, mtr);
- }
-
- flst_add_last(space_header + FSP_SEG_HDRS_FREE,
- page + FSEG_HDR_PAGE_NODE, mtr);
- return(TRUE);
-}
-
-/**************************************************************************
-Allocates a new file segment header. */
-static
-fseg_header_t*
-fsp_alloc_seg_header(
-/*=================*/
- /* out: segment header, or NULL if
- not enough space */
- fsp_header_t* space_header, /* in: space header */
- mtr_t* mtr) /* in: mini-transaction handle */
-{
- buf_block_t* block;
- ulint page_no;
- page_t* page;
- fseg_header_t* header;
- ulint n;
- bool success;
-
- if (flst_get_len(space_header + FSP_SEG_HDRS_FREE, mtr) == 0) {
- /* Allocate a new segment header page */
-
- success = fsp_alloc_seg_hdr_page(space_header, mtr);
-
- if (!success) {
-
- return(NULL);
- }
- }
-
- page_no = flst_get_first(space_header + FSP_SEG_HDRS_FREE, mtr).page;
-
- block = buf_page_get(buf_frame_get_space(space_header), page_no, mtr);
-
- buf_page_x_lock(block, mtr);
-
- page = buf_block_get_frame(block);
-
- n = fsp_seg_hdr_page_find_free(page, 0, mtr);
-
- ut_a(n != ULINT_UNDEFINED);
-
- header = fsp_seg_hdr_page_get_nth_hdr(page, n, mtr);
-
- if (ULINT_UNDEFINED == fsp_seg_hdr_page_find_free(page, n + 1, mtr)) {
-
- /* There are no other unused headers left on the page: move it
- to another list */
-
- flst_remove(space_header + FSP_SEG_HDRS_FREE,
- page + FSEG_HDR_PAGE_NODE, mtr);
-
- flst_add_last(space_header + FSP_SEG_HDRS_FULL,
- page + FSEG_HDR_PAGE_NODE, mtr);
- }
-
- return(header);
-}
-
-/**************************************************************************
-Frees a file segment header. */
-static
-void
-fsp_free_seg_header(
-/*================*/
- ulint space, /* in: space id */
- fseg_header_t* header, /* in: segment header */
- mtr_t* mtr) /* in: mini-transaction handle */
-{
- page_t* page;
- fsp_header_t* space_header;
-
- page = buf_frame_align(header);
-
- space_header = fsp_get_space_header(space, mtr);
-
- ut_ad(mach_read_from_4(header + FSEG_MAGIC_N) == FSEG_MAGIC_N_VALUE);
-
- if (ULINT_UNDEFINED == fsp_seg_hdr_page_find_free(page, mtr)) {
-
- /* Move the page to another list */
-
- flst_remove(space_header + FSP_SEG_HDRS_FULL,
- page + FSEG_HDR_PAGE_NODE, mtr);
-
- flst_add_last(space_header + FSP_SEG_HDRS_FREE,
- page + FSEG_HDR_PAGE_NODE, mtr);
- }
-
- mlog_write_dulint(header + FSEG_ID, ut_dulint_zero, MLOG_8BYTES, mtr);
- mlog_write_ulint(header + FSEG_MAGIC_N, 0, MLOG_4BYTES, mtr);
-
- if (ULINT_UNDEFINED == fsp_seg_hdr_page_find_used(page, mtr)) {
-
- /* There are no other used headers left on the page: free it */
-
- flst_remove(space_header + FSP_SEG_HDRS_FREE,
- page + FSEG_HDR_PAGE_NODE, mtr);
-
- fsp_free_page(space, page_no, mtr);
- }
-}
-
-/**************************************************************************
-Gets the page number from the nth fragment page slot. */
-UNIV_INLINE
-ulint
-fseg_get_nth_frag_page_no(
-/*======================*/
- /* out: page number, FIL_NULL if not in use */
- fseg_header_t* header, /* in: segment header */
- ulint n, /* in: slot index */
- mtr_t* mtr) /* in: mtr handle */
-{
- ut_ad(header && mtr);
- ut_ad(n < FSEG_FRAG_ARR_N_SLOTS);
- ut_ad(mtr_memo_contains(mtr, buf_block_align(header),
- MTR_MEMO_PAGE_X_LOCK));
-
- return(mach_read_from_4(header + FSEG_FRAG_ARR
- + n * FSEG_FRAG_SLOT_SIZE));
-}
-
-/**************************************************************************
-Sets the page number in the nth fragment page slot. */
-UNIV_INLINE
-void
-fseg_set_nth_frag_page_no(
-/*======================*/
- fseg_header_t* header, /* in: segment header */
- ulint n, /* in: slot index */
- ulint page_no,/* in: page number to set */
- mtr_t* mtr) /* in: mtr handle */
-{
- ut_ad(header && mtr);
- ut_ad(n < FSEG_FRAG_ARR_N_SLOTS);
- ut_ad(mtr_memo_contains(mtr, buf_block_align(header),
- MTR_MEMO_PAGE_X_LOCK));
-
- mlog_write_ulint(header + FSEG_FRAG_ARR + n * FSEG_FRAG_SLOT_SIZE,
- page_no, MLOG_4BYTES, mtr);
-}
-
-/**************************************************************************
-Finds a fragment page slot which is free. */
-static
-ulint
-fseg_find_free_frag_page_slot(
-/*==========================*/
- /* out: slot index; ULINT_UNDEFINED if none
- found */
- fseg_header_t* header, /* in: segment header */
- mtr_t* mtr) /* in: mtr handle */
-{
- ulint i;
- ulint page_no;
-
- ut_ad(header && mtr);
-
- for (i = 0; i < FSEG_FRAG_ARR_N_SLOTS; i++) {
- page_no = fseg_get_nth_frag_page_no(header, i, mtr);
-
- if (page_no == FIL_NULL) {
-
- return(i);
- }
- }
- return(ULINT_UNDEFINED);
-}
-
-/**************************************************************************
-Finds a fragment page slot which is used and last in the array. */
-static
-ulint
-fseg_find_last_used_frag_page_slot(
-/*===============================*/
- /* out: slot index; ULINT_UNDEFINED if none
- found */
- fseg_header_t* header, /* in: segment header */
- mtr_t* mtr) /* in: mtr handle */
-{
- ulint i;
- ulint page_no;
-
- ut_ad(header && mtr);
-
- for (i = 0; i < FSEG_FRAG_ARR_N_SLOTS; i++) {
- page_no = fseg_get_nth_frag_page_no(header,
- FSEG_ARR_N_SLOTS - i - 1, mtr);
-
- if (page_no != FIL_NULL) {
-
- return(i);
- }
- }
- return(ULINT_UNDEFINED);
-}
-
-/**************************************************************************
-Calculates reserved fragment page slots. */
-static
-ulint
-fseg_get_n_frag_pages(
-/*==================*/
- /* out: number of fragment pages */
- fseg_header_t* header, /* in: segment header */
- mtr_t* mtr) /* in: mtr handle */
-{
- ulint i;
- ulint count = 0;
-
- ut_ad(header && mtr);
-
- for (i = 0; i < FSEG_FRAG_ARR_N_SLOTS; i++) {
- if (FIL_NULL != fseg_get_nth_frag_page_no(header, i, mtr)) {
- count++;
- }
- }
- return(count);
-}
-
-/**************************************************************************
-Creates a new segment. */
-
-ulint
-fseg_create(
-/*========*/
- /* out: the page number where the segment header is
- placed, FIL_NULL if could not create segment because
- lack of space */
- ulint space, /* in: space id */
- ulint* offset, /* out: byte offset of the segment header on its
- page */
- mtr_t* mtr) /* in: mtr */
-{
- buf_block_t* block;
- buf_frame_t* frame;
- fsp_header_t* space_header;
- fseg_header_t* header;
- dulint seg_id;
- ulint i;
-
- ut_ad(mtr);
-
- mtr_x_lock(&fsp_latch, mtr);
-
- space_header = fsp_get_space_header(space, mtr);
-
- header = fsp_alloc_seg_header(space_header, mtr);
-
- if (header == NULL) {
-
- return(FIL_NULL);
- }
-
- /* Read the next segment id from space header and increment the
- value in space header */
-
- seg_id = mtr_read_dulint(space_header + FSP_SEG_ID, MLOG_8BYTES, mtr);
-
- mlog_write_dulint(space_header + FSP_SEG_ID, ut_dulint_add(seg_id, 1),
- MLOG_8BYTES, mtr);
-
- mlog_write_dulint(header + FSEG_ID, seg_id, MLOG_8BYTES, mtr);
- mlog_write_ulint(header + FSEG_NOT_FULL_N_USED, 0, MLOG_4BYTES, mtr);
-
- flst_init(header + FSEG_FREE, mtr);
- flst_init(header + FSEG_NOT_FULL, mtr);
- flst_init(header + FSEG_FULL, mtr);
-
- mlog_write_ulint(header + FSEG_MAGIC_N, FSEG_MAGIC_N_VALUE,
- MLOG_4BYTES, mtr);
- for (i = 0; i < FSEG_FRAG_ARR_N_SLOTS; i++) {
- fseg_set_nth_frag_page_no(header, i, FIL_NULL, mtr);
- }
-
- *offset = header - buf_frame_align(header);
- return(buf_frame_get_page(buf_frame_align(header)));
-}
-
-/**************************************************************************
-Calculates the number of pages reserved by a segment, and how
-many pages are currently used. */
-
-ulint
-fseg_n_reserved_pages(
-/*==================*/
- /* out: number of reserved pages */
- fseg_header_t* header, /* in: segment header */
- ulint* used, /* out: number of pages used (<= reserved) */
- mtr_t* mtr) /* in: mtr handle */
-{
- ulint ret;
-
- mtr_x_lock(&fsp_latch, mtr);
-
- ret = fseg_n_reserved_pages_low(header, used, mtr);
-
- return(ret);
-}
-
-/**************************************************************************
-Calculates the number of pages reserved by a segment, and how
-many pages are currently used. */
-static
-ulint
-fseg_n_reserved_pages_low(
-/*======================*/
- /* out: number of reserved pages */
- fseg_header_t* header, /* in: segment header */
- ulint* used, /* out: number of pages used (<= reserved) */
- mtr_t* mtr) /* in: mtr handle */
-{
- ulint ret;
-
- ut_ad(header && used && mtr);
- ut_ad(mtr_memo_contains(mtr, buf_block_align(header),
- MTR_MEMO_BUF_FIX));
-
- buf_page_x_lock(buf_block_align(header), mtr);
-
- *used = mtr_read_ulint(header + FSEG_NOT_FULL_N_USED, MLOG_4BYTES, mtr)
- + FSP_EXTENT_SIZE * flst_get_len(header + FSEG_FULL, mtr)
- + fseg_get_n_frag_pages(header, mtr);
-
- ret = fseg_get_n_frag_pages(header, mtr)
- + FSP_EXTENT_SIZE * flst_get_len(header + FSEG_FREE, mtr)
- + FSP_EXTENT_SIZE * flst_get_len(header + FSEG_NOT_FULL, mtr)
- + FSP_EXTENT_SIZE * flst_get_len(header + FSEG_FULL, mtr);
-
- return(ret);
-}
-
-/*************************************************************************
-Tries to fill the free list of a segment with consecutive free extents.
-This happens if the segment is big enough to allowextents in the free list,
-the free list is empty, and the extents can be allocated consecutively from
-the hint onward. */
-static
-void
-fseg_fill_free_list(
-/*================*/
- fseg_header_t* header, /* in: segment header */
- ulint space, /* in: space id */
- ulint hint, /* in: hint which extent would be good as
- the first extent */
- mtr_t* mtr) /* in: mtr */
-{
- xdes_t* descr;
- ulint i;
- dulint seg_id;
- ulint reserved;
- ulint used;
-
- ut_ad(header && mtr);
-
- buf_page_x_lock(buf_block_align(header), mtr);
-
- reserved = fseg_n_reserved_pages_low(header, &used, mtr);
-
- if (reserved < FSEG_FREE_LIST_LIMIT * FSP_EXTENT_SIZE) {
- /* The segment is too small to allow extents in free list */
-
- return;
- }
-
- if (flst_get_len(header + FSEG_FREE, mtr) > 0) {
- /* Free list is not empty */
-
- return;
- }
-
- for (i = 0; i < FSEG_FREE_LIST_MAX_LEN; i++) {
- descr = xdes_get_descriptor(space, hint, mtr);
-
- if ((descr == NULL) ||
- (XDES_FREE != xdes_get_state(descr, mtr))) {
- /* We cannot allocate the desired extent: stop */
-
- return;
- }
-
- descr = fsp_alloc_free_extent(space, hint, mtr);
-
- xdes_set_state(descr, XDES_FSEG, mtr);
-
- seg_id = mtr_read_dulint(header + FSEG_ID, MLOG_8BYTES, mtr);
- mlog_write_dulint(descr + XDES_ID, seg_id, MLOG_8BYTES, mtr);
-
- flst_add_last(header + FSEG_FREE, descr + XDES_FLST_NODE, mtr);
- hint += FSP_EXTENT_SIZE;
- }
-}
-
-/*************************************************************************
-Allocates a free extent for the segment: looks first in the
-free list of the segment, then tries to allocate from the space free
-list. NOTE that the extent returned is still placed in the segment free
-list, not taken off it! */
-static
-xdes_t*
-fseg_alloc_free_extent(
-/*===================*/
- /* out: allocated extent, still placed in the
- segment free list, NULL if could
- not be allocated */
- fseg_header_t* header, /* in: segment header */
- ulint space, /* in: space id */
- mtr_t* mtr) /* in: mtr */
-{
- xdes_t* descr;
- dulint seg_id;
- fil_addr_t first;
-
- buf_page_x_lock(buf_block_align(header), mtr);
-
- if (flst_get_len(header + FSEG_FREE, mtr) > 0) {
- /* Segment free list is not empty, allocate from it */
-
- first = flst_get_first(header + FSEG_FREE, mtr);
-
- descr = xdes_lst_get_descriptor(space, first, mtr);
- } else {
- /* Segment free list was empty, allocate from space */
- descr = fsp_alloc_free_extent(space, 0, mtr);
-
- if (descr == NULL) {
- return(NULL);
- }
-
- seg_id = mtr_read_dulint(header + FSEG_ID, MLOG_8BYTES, mtr);
-
- xdes_set_state(descr, XDES_FSEG, mtr);
- mlog_write_dulint(descr + XDES_ID, seg_id, MLOG_8BYTES, mtr);
- flst_add_last(header + FSEG_FREE,
- descr + XDES_FLST_NODE, mtr);
-
- /* Try to fill the segment free list */
- fseg_fill_free_list(header, space,
- xdes_get_offset(descr) + FSP_EXTENT_SIZE, mtr);
- }
-
- return(descr);
-}
-
-/**************************************************************************
-Allocates a single free page from a segment. This function implements
-the intelligent allocation strategy which tries to minimize file space
-fragmentation. */
-
-ulint
-fseg_alloc_free_page(
-/*=================*/
- /* out: the allocated page offset
- FIL_NULL if no page could be allocated */
- 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 */
-{
- buf_block_t* block;
- dulint seg_id;
- fseg_page_header_t* page_header;
- ulint space;
- ulint used;
- ulint reserved;
- fil_addr_t first;
- xdes_t* descr; /* extent of the hinted page */
- ulint ret_page; /* the allocated page offset, FIL_NULL
- if could not be allocated */
- buf_block_t* ret_buf_page;
- buf_frame_t* ret_frame;
- xdes_t* ret_descr; /* the extent of the allocated page */
- ulint n;
- bool frag_page_allocated = FALSE;
-
- ut_ad(seg_header && mtr);
- ut_ad((direction >= FSP_UP) && (direction <= FSP_NO_DIR));
-
- mtr_x_lock(&fsp_latch, mtr);
-
- block = buf_block_align(seg_header);
- buf_page_x_lock(block, mtr);
-
- space = buf_page_get_space(block);
-
- seg_id = mtr_read_dulint(seg_header + FSEG_ID, MLOG_8BYTES, mtr);
-
- ut_ad(ut_dulint_cmp(seg_id, ut_dulint_zero) > 0);
-
- reserved = fseg_n_reserved_pages_low(seg_header, &used, mtr);
-
- descr = xdes_get_descriptor(space, hint, mtr);
-
- if (descr == NULL) {
- /* Hint outside space or too high above free limit:
- reset hint */
- hint = 0;
- descr = xdes_get_descriptor(space, hint, mtr);
- }
-
- /* In the big if-else below we look for ret_page and ret_descr */
- /*-------------------------------------------------------------*/
- if ((xdes_get_state(descr, mtr) == XDES_FSEG)
- && (0 == ut_dulint_cmp(mtr_read_dulint(descr + XDES_ID,
- MLOG_8BYTES, mtr),
- seg_id))
- && (xdes_get_bit(descr, XDES_FREE_BIT,
- hint % FSP_EXTENT_SIZE, mtr) == TRUE)) {
-
- /* 1. We can take the hinted page
- =================================*/
- ret_descr = descr;
- ret_page = hint;
- /*-------------------------------------------------------------*/
- } 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
- =========================================================
- the hinted page
- ===============*/
- ret_descr = fsp_alloc_free_extent(space, hint, mtr);
-
- ut_a(ret_descr == descr);
-
- xdes_set_state(ret_descr, XDES_FSEG, mtr);
- mlog_write_dulint(ret_descr + XDES_ID, seg_id, MLOG_8BYTES,
- mtr);
- flst_add_last(seg_header + FSEG_FREE,
- ret_descr + XDES_FLST_NODE, mtr);
-
- /* Try to fill the segment free list */
- fseg_fill_free_list(seg_header, space,
- hint + FSP_EXTENT_SIZE, mtr);
- ret_page = hint;
- /*-------------------------------------------------------------*/
- } else if ((direction != FSP_NO_DIR)
- && ((reserved - used) < reserved / FSEG_FILLFACTOR)
- && (used >= FSEG_FRAG_LIMIT)
- && (NULL != (ret_descr =
- fseg_alloc_free_extent(seg_header, space, mtr)))) {
-
- /* 3. We take any free extent (which was already assigned above
- ===============================================================
- in the if-condition to ret_descr) and take the lowest or
- ========================================================
- highest page in it, depending on the direction
- ==============================================*/
- ret_page = xdes_get_offset(ret_descr);
- if (direction == FSP_DOWN) {
- ret_page += FSP_EXTENT_SIZE - 1;
- }
- /*-------------------------------------------------------------*/
- } else if ((xdes_get_state(descr, mtr) == XDES_FSEG)
- && (0 == ut_dulint_cmp(mtr_read_dulint(descr + XDES_ID,
- MLOG_8BYTES, mtr),
- seg_id))
- && (!xdes_is_full(descr, mtr))) {
-
- /* 4. We can take the page from the same extent as the
- ======================================================
- hinted page (and the extent already belongs to the
- ==================================================
- segment)
- ========*/
- ret_descr = descr;
- ret_page = xdes_get_offset(ret_descr) +
- xdes_find_bit(ret_descr, XDES_FREE_BIT, TRUE,
- hint % FSP_EXTENT_SIZE, mtr);
- /*-------------------------------------------------------------*/
- } else if (reserved - used > 0) {
- /* 5. We take any unused page from the segment
- ==============================================*/
- if (flst_get_len(seg_header + FSEG_NOT_FULL, mtr) > 0) {
- first = flst_get_first(seg_header + FSEG_NOT_FULL,
- mtr);
- } else if (flst_get_len(seg_header + FSEG_FREE, mtr) > 0) {
- first = flst_get_first(seg_header + FSEG_FREE, mtr);
- } else {
- ut_error;
- }
-
- ret_descr = xdes_lst_get_descriptor(space, first, mtr);
- ret_page = xdes_get_offset(ret_descr) +
- xdes_find_bit(ret_descr, XDES_FREE_BIT, TRUE,
- 0, mtr);
- /*-------------------------------------------------------------*/
- } else if (used < FSEG_FRAG_LIMIT) {
- /* 6. We allocate an individual page from the space
- ===================================================*/
- ret_page = fsp_alloc_free_page(space, 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 */
- n = fseg_find_free_frag_page_slot(seg_header, mtr);
- ut_a(n != FIL_NULL);
-
- fseg_set_nth_frag_page_no(seg_header, n, ret_page,
- mtr);
- }
- /*-------------------------------------------------------------*/
- } else {
- /* 7. We allocate a new extent and take its first page
- ======================================================*/
- ret_descr = fseg_alloc_free_extent(seg_header, space, mtr);
-
- if (ret_descr == NULL) {
- ret_page = FIL_NULL;
- } else {
- ret_page = xdes_get_offset(ret_descr);
- }
- }
-
- if (ret_page == FIL_NULL) {
- /* Page could not be allocated */
-
- return(FIL_NULL);
- }
-
- /* Initialize the allocated page to buffer pool, so that it can be
- obtained immediately with buf_page_get without need for disk read */
-
- ret_buf_page = buf_page_create(space, ret_page, mtr);
-
- if (!frag_page_allocated) {
- /* 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. */
-
- ut_ad(xdes_get_descriptor(space, ret_page, mtr) == ret_descr);
- ut_ad(xdes_get_bit(ret_descr, XDES_FREE_BIT,
- ret_page % FSP_EXTENT_SIZE, mtr) == TRUE);
-
- fseg_mark_page_used(seg_header, space, ret_page, mtr);
- }
-
- return(ret_page);
-}
-
-/************************************************************************
-Marks a page used. The page must reside within the extents of the given
-segment. */
-static
-void
-fseg_mark_page_used(
-/*================*/
- fseg_header_t* seg_header,/* in: segment header */
- ulint space, /* in: space id */
- ulint page, /* in: page offset */
- mtr_t* mtr) /* in: mtr */
-{
- xdes_t* descr;
- ulint not_full_n_used;
-
- ut_ad(seg_header && mtr);
-
- descr = xdes_get_descriptor(space, page, mtr);
-
- ut_ad(mtr_read_ulint(seg_header + FSEG_ID, MLOG_4BYTES, mtr) ==
- mtr_read_ulint(descr + XDES_ID, MLOG_4BYTES, mtr));
-
- if (xdes_is_free(descr, mtr)) {
- /* We move the extent from the free list to the
- NOT_FULL list */
- flst_remove(seg_header + FSEG_FREE,
- descr + XDES_FLST_NODE, mtr);
- flst_add_last(seg_header + FSEG_NOT_FULL,
- descr + XDES_FLST_NODE, mtr);
- }
-
- ut_ad(xdes_get_bit(descr, XDES_FREE_BIT, page % FSP_EXTENT_SIZE, mtr)
- == TRUE);
-
- /* We mark the page as used */
- xdes_set_bit(descr, XDES_FREE_BIT, page % FSP_EXTENT_SIZE, FALSE, mtr);
-
- not_full_n_used = mtr_read_ulint(seg_header + FSEG_NOT_FULL_N_USED,
- MLOG_4BYTES, mtr);
-
- not_full_n_used++;
- mlog_write_ulint(seg_header + FSEG_NOT_FULL_N_USED,
- not_full_n_used, MLOG_4BYTES, mtr);
-
- if (xdes_is_full(descr, mtr)) {
- /* We move the extent from the NOT_FULL list to the
- FULL list */
- flst_remove(seg_header + FSEG_NOT_FULL,
- descr + XDES_FLST_NODE, mtr);
- flst_add_last(seg_header + FSEG_FULL,
- descr + XDES_FLST_NODE, mtr);
-
- mlog_write_ulint(seg_header + FSEG_NOT_FULL_N_USED,
- not_full_n_used - FSP_EXTENT_SIZE,
- MLOG_4BYTES, mtr);
- }
-}
-
-/**************************************************************************
-Frees a single page of a segment. */
-
-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: mtr handle */
-{
- mtr_x_lock(&fsp_latch, mtr);
-
- fseg_free_page_low(seg_header, space, page, mtr);
-}
-
-/**************************************************************************
-Frees a single page of a segment. */
-static
-void
-fseg_free_page_low(
-/*===============*/
- fseg_header_t* seg_header, /* in: segment header */
- ulint space, /* in: space id */
- ulint page, /* in: page offset */
- mtr_t* mtr) /* in: mtr handle */
-{
- buf_block_t* block;
- xdes_t* descr;
- ulint used;
- ulint not_full_n_used;
- ulint state;
- buf_block_t* buf_page;
- buf_frame_t* buf_frame;
- ulint i;
-
- ut_ad(seg_header && mtr);
-
- block = buf_block_align(seg_header);
- buf_page_x_lock(block, mtr);
-
- descr = xdes_get_descriptor(space, page, mtr);
-
- ut_a(descr);
- ut_a(xdes_get_bit(descr, XDES_FREE_BIT, page % FSP_EXTENT_SIZE, mtr)
- == FALSE);
-
- state = xdes_get_state(descr, mtr);
-
- if (state != XDES_FSEG) {
- /* The page is in the fragment pages of the segment */
-
- for (i = 0;; i++) {
- if (fseg_get_nth_frag_page_no(seg_header, i, mtr)
- == page) {
-
- fseg_set_nth_frag_page_no(seg_header, i,
- FIL_NULL, mtr);
- break;
- }
- }
-
- fsp_free_page(space, page, mtr);
-
- return;
- }
-
- /* If we get here, the page is in some extent of the segment */
- ut_a(0 == ut_dulint_cmp(
- mtr_read_dulint(descr + XDES_ID, MLOG_8BYTES, mtr),
- mtr_read_dulint(seg_header + FSEG_ID, MLOG_8BYTES, mtr)));
-
- not_full_n_used = mtr_read_ulint(seg_header + FSEG_NOT_FULL_N_USED,
- MLOG_4BYTES, mtr);
- if (xdes_is_full(descr, mtr)) {
- /* The fragment is full: move it to another list */
- flst_remove(seg_header + FSEG_FULL,
- descr + XDES_FLST_NODE, mtr);
- flst_add_last(seg_header + FSEG_NOT_FULL,
- descr + XDES_FLST_NODE, mtr);
- mlog_write_ulint(seg_header + FSEG_NOT_FULL_N_USED,
- not_full_n_used + FSP_EXTENT_SIZE - 1,
- MLOG_4BYTES, mtr);
- } else {
- ut_a(not_full_n_used > 0);
- mlog_write_ulint(seg_header + FSEG_NOT_FULL_N_USED,
- not_full_n_used - 1,
- MLOG_4BYTES, mtr);
- }
-
- xdes_set_bit(descr, XDES_FREE_BIT, page % FSP_EXTENT_SIZE, TRUE, mtr);
- xdes_set_bit(descr, XDES_CLEAN_BIT, page % FSP_EXTENT_SIZE, TRUE, mtr);
-
- if (xdes_is_free(descr, mtr)) {
- /* The extent has become free: free it to space */
- flst_remove(seg_header + FSEG_NOT_FULL,
- descr + XDES_FLST_NODE, mtr);
- fsp_free_extent(space, page, mtr);
- }
-}
-
-/**************************************************************************
-Frees an extent of a segment to the space free list. */
-static
-void
-fseg_free_extent(
-/*=============*/
- fseg_header_t* seg_header, /* in: segment header */
- ulint space, /* in: space id */
- ulint page, /* in: page offset in the extent */
- mtr_t* mtr) /* in: mtr handle */
-{
- buf_block_t* block;
- xdes_t* descr;
- ulint not_full_n_used;
- ulint descr_n_used;
-
- ut_ad(seg_header && mtr);
-
- block = buf_block_align(seg_header);
- buf_page_x_lock(block, mtr);
-
- descr = xdes_get_descriptor(space, page, mtr);
-
- ut_a(xdes_get_state(descr, mtr) == XDES_FSEG);
- ut_a(0 == ut_dulint_cmp(
- mtr_read_dulint(descr + XDES_ID, MLOG_8BYTES, mtr),
- mtr_read_dulint(seg_header + FSEG_ID, MLOG_8BYTES, mtr)));
-
- if (xdes_is_full(descr, mtr)) {
- flst_remove(seg_header + FSEG_FULL,
- descr + XDES_FLST_NODE, mtr);
- } else if (xdes_is_free(descr, mtr)) {
- flst_remove(seg_header + FSEG_FREE,
- descr + XDES_FLST_NODE, mtr);
- } else {
- flst_remove(seg_header + FSEG_NOT_FULL,
- descr + XDES_FLST_NODE, mtr);
-
- not_full_n_used = mtr_read_ulint(
- seg_header + FSEG_NOT_FULL_N_USED,
- MLOG_4BYTES, mtr);
-
- descr_n_used = xdes_get_n_used(descr, mtr);
- ut_a(not_full_n_used >= descr_n_used);
- mlog_write_ulint(seg_header + FSEG_NOT_FULL_N_USED,
- not_full_n_used - descr_n_used,
- MLOG_4BYTES, mtr);
- }
- fsp_free_extent(space, page, mtr);
-}
-
-/**************************************************************************
-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. */
-
-bool
-fseg_free_step(
-/*===========*/
- /* out: TRUE if freeing completed */
- ulint space, /* in: segment space id */
- ulint page_no,/* in: segment header page number */
- ulint offset, /* in: segment header byte offset on page */
- mtr_t* mtr) /* in: mtr */
-{
- buf_block_t* block;
- ulint n;
- ulint page;
- xdes_t* descr;
- fseg_header_t* header;
- fil_addr_t header_addr;
-
- header_addr.page = page_no;
- header_addr.boffset = offset;
-
- mtr_x_lock(&fsp_latch, mtr);
-
- header = fut_get_ptr_x_lock(space, header_addr, mtr);
-
- descr = fseg_get_first_extent(header, mtr);
-
- if (descr != NULL) {
- /* Free the extent held by the segment */
- page = xdes_get_offset(descr);
-
- fseg_free_extent(header, space, page, mtr);
-
- return(FALSE);
- }
-
- /* Free a frag page */
-
- n = fseg_get_last_used_frag_page_slot(header, mtr);
-
- if (n == ULINT_UNDEFINED) {
- /* Freeing completed: free the segment header */
- fsp_free_seg_header(space, header, mtr);
-
- return(TRUE);
- }
-
- fseg_free_page_low(header, space,
- fseg_get_nth_frag_page_no(header, n, mtr), mtr);
-
- return(FALSE);
-}
-
-/***********************************************************************
-Frees a segment. The freeing is performed in several mini-transactions,
-so that there is no danger of bufferfixing too many buffer pages. */
-
-void
-fseg_free(
-/*======*/
- ulint space, /* in: space id */
- ulint page_no,/* in: page number where the segment header is
- placed */
- ulint offset) /* in: byte offset of the segment header on that
- page */
-{
- mtr_t mtr;
- buf_block_t* block;
- bool finished;
-
- for (;;) {
- mtr_start(&mtr);
-
- block = buf_page_get(space, page_no, &mtr);
-
- finished = fseg_free_step(space, page_no, offset, &mtr);
-
- mtr_commit(&mtr);
-
- if (finished) {
- break;
- }
- }
-}
-
-/**************************************************************************
-Returns the first extent descriptor for a segment. We think of the extent
-lists of the segment catenated in the order FSEG_FULL -> FSEG_NOT_FULL
--> FSEG_FREE. */
-static
-xdes_t*
-fseg_get_first_extent(
-/*==================*/
- /* out: the first extent descriptor, or NULL if
- none */
- fseg_header_t* header, /* in: segment header */
- mtr_t* mtr) /* in: mtr */
-{
- buf_block_t* block;
- fil_addr_t first;
- ulint space;
- xdes_t* descr;
-
- ut_ad(header && mtr);
-
- block = buf_block_align(header);
- buf_page_x_lock(block, mtr);
-
- space = buf_page_get_space(block);
-
- first = fil_addr_null;
-
- if (flst_get_len(header + FSEG_FULL, mtr) > 0) {
- first = flst_get_first(header + FSEG_FULL, mtr);
- } else if (flst_get_len(header + FSEG_NOT_FULL, mtr) > 0) {
- first = flst_get_first(header + FSEG_NOT_FULL, mtr);
- } else if (flst_get_len(header + FSEG_FREE, mtr) > 0) {
- first = flst_get_first(header + FSEG_FREE, mtr);
- }
-
- if (first.page == FIL_NULL) {
- return(NULL);
- } else {
- descr = xdes_lst_get_descriptor(space, first, mtr);
- return(descr);
- }
-}
-
-#ifdef notdefined
-
-/**************************************************************************
-Returns the last non-free extent descriptor for a segment. We think of
-the extent lists of the segment catenated in the order FSEG_FULL ->
-FSEG_NOT_FULL -> FSEG_FREE. */
-static
-xdes_t*
-fseg_get_last_non_free_extent(
-/*==========================*/
- /* out: the last extent descriptor, or NULL if
- none */
- fseg_header_t* header, /* in: segment header */
- mtr_t* mtr) /* in: mtr */
-{
- buf_block_t* block;
- fil_addr_t last;
- ulint space;
- xdes_t* descr;
-
- ut_ad(header && mtr);
-
- block = buf_block_align(header);
- buf_page_x_lock(block, mtr);
-
- space = buf_page_get_space(block);
-
- last = fil_addr_null;
-
- if (flst_get_len(header + FSEG_NOT_FULL, mtr) > 0) {
- last = flst_get_last(header + FSEG_NOT_FULL, mtr);
- } else if (flst_get_len(header + FSEG_FULL, mtr) > 0) {
- last = flst_get_last(header + FSEG_FULL, mtr);
- }
-
- if (last.page == FIL_NULL) {
- return(NULL);
- } else {
- descr = xdes_lst_get_descriptor(space, last, mtr);
- return(descr);
- }
-}
-
-/**************************************************************************
-Returns the next extent descriptor for a segment. We think of the extent
-lists of the segment catenated in the order FSEG_FULL -> FSEG_NOT_FULL
--> FSEG_FREE. */
-static
-xdes_t*
-fseg_get_next_extent(
-/*=================*/
- /* out: next extent descriptor, or NULL if
- none */
- fseg_header_t* header, /* in: segment header */
- xdes_t* descr, /* in: previous extent descriptor */
- mtr_t* mtr) /* in: mtr */
-{
- fil_addr_t next_addr;
- buf_block_t* block;
- ulint space;
-
- ut_ad(header && descr && mtr);
-
- block = buf_block_align(header);
- buf_page_x_lock(block, mtr);
-
- space = buf_page_get_space(block);
-
- next_addr = flst_get_next_addr(descr + XDES_FLST_NODE, mtr);
-
- if (next_addr.page == FIL_NULL) {
- /* This is the last extent in the list. */
- if (xdes_is_full(descr, mtr)) {
- /* descr is in FSEG_FULL list */
- if (flst_get_len(header + FSEG_NOT_FULL, mtr) > 0) {
- next_addr = flst_get_first(header
- + FSEG_NOT_FULL, mtr);
- } else if (flst_get_len(header + FSEG_FREE, mtr) > 0) {
- next_addr = flst_get_first(header
- + FSEG_FREE, mtr);
- }
- } else if (!xdes_is_full(descr, mtr)
- && !xdes_is_free(descr, mtr)) {
- /* descr is in FSEG_NOT_FULL list */
- if (flst_get_len(header + FSEG_FREE, mtr) > 0) {
- next_addr = flst_get_first(header
- + FSEG_FREE, mtr);
- }
- }
- }
-
- if (next_addr.page != FIL_NULL) {
- descr = xdes_lst_get_descriptor(space, next_addr, mtr);
- ut_ad(descr);
- return(descr);
- } else {
- return(NULL);
- }
-}
-
-/**************************************************************************
-Returns the previous extent descriptor for a segment. We think of the extent
-lists of the segment catenated in the order FSEG_FULL -> FSEG_NOT_FULL
--> FSEG_FREE. */
-static
-xdes_t*
-fseg_get_prev_extent(
-/*=================*/
- /* out: previous extent descriptor, or NULL if
- none */
- fseg_header_t* header, /* in: segment header */
- xdes_t* descr, /* in: extent descriptor */
- mtr_t* mtr) /* in: mtr */
-{
- fil_addr_t prev_addr;
- buf_block_t* block;
- ulint space;
-
- ut_ad(header && descr && mtr);
-
- block = buf_block_align(header);
- buf_page_x_lock(block, mtr);
-
- space = buf_page_get_space(block);
-
- prev_addr = flst_get_prev_addr(descr + XDES_FLST_NODE, mtr);
-
- if (prev_addr.page == FIL_NULL) {
- /* This is the first extent in the list. */
- if (xdes_is_free(descr, mtr)) {
- /* descr is in FSEG_FREE list */
- if (flst_get_len(header + FSEG_NOT_FULL, mtr) > 0) {
- prev_addr = flst_get_last(header
- + FSEG_NOT_FULL, mtr);
- } else if (flst_get_len(header + FSEG_FULL, mtr) > 0) {
- prev_addr = flst_get_last(header
- + FSEG_FULL, mtr);
- }
- } else if (!xdes_is_full(descr, mtr)
- && !xdes_is_free(descr, mtr)) {
- /* descr is in FSEG_NOT_FULL list */
- if (flst_get_len(header + FSEG_FULL, mtr) > 0) {
- prev_addr = flst_get_last(header
- + FSEG_FULL, mtr);
- }
- }
- }
-
- if (prev_addr.page != FIL_NULL) {
- descr = xdes_lst_get_descriptor(space, prev_addr, mtr);
- ut_ad(descr);
- return(descr);
- } else {
- return(NULL);
- }
-}
-
-/*************************************************************************
-Gets the first used page number in the given extent assigned to a
-specific segment, or its successors, in the order defined in
-fsp_get_next_extent. */
-static
-ulint
-fseg_extent_get_next_page_no(
-/*=========================*/
- /* next used page number in the given extent
- or a successor of it, FIL_NULL if no page
- found */
- fseg_header_t* header, /* in: segment header */
- xdes_t* descr, /* in: extent descriptor, if this is NULL, the
- function returns FIL_NULL */
- mtr_t* mtr) /* in: mtr */
-{
- ulint bit;
-
- UT_NOT_USED(header);
- ut_ad((descr == NULL) || (xdes_get_state(descr, mtr) == XDES_FSEG));
-
- for (;;) {
- if (descr == NULL) {
- return(FIL_NULL);
- }
-
- bit = xdes_find_bit(descr, XDES_FREE_BIT, FALSE, 0, mtr);
-
- if (bit == ULINT_UNDEFINED) {
- /* No page found in this extent: the extent is in
- FSEG_FREE list, thus, no used page can be found
- in successors */
- return(FIL_NULL);
- } else {
- return(xdes_get_offset(descr) + bit);
- }
- }
-}
-
-/*************************************************************************
-Gets the last used page number in the given extent assigned to a
-specific segment, or its predecessor extents, in the order defined in
-fsp_get_next_extent. If the page cannot be found from the extents,
-the last page of the fragment list is returned, or FIL_NULL if it is
-empty.*/
-static
-ulint
-fseg_extent_get_prev_page_no(
-/*=========================*/
- /* previous used page number in the given
- extent or a predecessor, FIL_NULL
- if no page found */
- fseg_header_t* header, /* in: segment header */
- xdes_t* descr, /* in: extent descriptor, if this is NULL, the
- function returns the last page of the fragment
- list, if any */
- mtr_t* mtr) /* in: mtr */
-{
- ulint prev_page_no;
- ulint bit;
- fil_addr_t last_frag_page_addr;
-
- ut_ad((descr == NULL) || (xdes_get_state(descr, mtr) == XDES_FSEG));
-
- for (;;) {
- if (descr == NULL) {
- prev_page_no = FIL_NULL;
- break;
- }
-
- bit = xdes_find_bit_downward(descr, XDES_FREE_BIT, FALSE,
- FSP_EXTENT_SIZE - 1, mtr);
-
- if (bit == ULINT_UNDEFINED) {
- descr = fseg_get_prev_extent(header, descr, mtr);
- } else {
- prev_page_no = xdes_get_offset(descr) + bit;
- break;
- }
- }
-
- if (prev_page_no == FIL_NULL) {
- last_frag_page_addr = flst_get_last(header + FSEG_FRAG, mtr);
- prev_page_no = last_frag_page_addr.page;
- }
-
- return(prev_page_no);
-}
-
-/**************************************************************************
-Returns the page number of the first segment page. If no pages have been
-freed from the segment, and the pages were allocated with the hint page
-number always one greater than previous page, then it is guaranteed that
-this function returns the first allocated page. */
-
-ulint
-fseg_get_first_page_no(
-/*===================*/
- /* out: page number, FIL_NULL if no
- page found */
- fseg_header_t* header, /* in: segment header */
- mtr_t* mtr) /* in: mtr */
-{
- buf_block_t* block;
- ulint first_page_no;
- xdes_t* descr;
- fil_addr_t first_frag_page_addr;
-
- ut_ad(header);
-
- mtr_x_lock(&fsp_latch, mtr);
-
- block = buf_block_align(header);
- buf_page_x_lock(block, mtr);
-
- /* Find first page */
- first_frag_page_addr = flst_get_first(header + FSEG_FRAG, mtr);
- first_page_no = first_frag_page_addr.page;
-
- if (first_page_no == FIL_NULL) {
- descr = fseg_get_first_extent(header, mtr);
- first_page_no = fseg_extent_get_next_page_no(header, descr,
- mtr);
- }
-
- return(first_page_no);
-}
-
-/**************************************************************************
-Returns the page number of the last segment page. If no pages have been
-freed from the segment, and the pages were allocated with the hint page
-number always one greater than previous page, then it is guaranteed that
-this function returns the last allocated page. */
-
-ulint
-fseg_get_last_page_no(
-/*==================*/
- /* out: page number, FIL_NULL if no
- page found */
- fseg_header_t* header, /* in: segment header */
- mtr_t* mtr) /* in: mtr */
-{
- buf_block_t* block;
- ulint last_page_no;
- xdes_t* descr;
-
- ut_ad(header);
-
- mtr_x_lock(&fsp_latch, mtr);
-
- block = buf_block_align(header);
- buf_page_x_lock(block, mtr);
-
- descr = fseg_get_last_non_free_extent(header, mtr);
- last_page_no = fseg_extent_get_prev_page_no(header, descr, mtr);
-
- return(last_page_no);
-}
-
-/**************************************************************************
-Returns the page number of the next segment page. If no pages have been
-freed from the segment, and the pages were allocated with the hint page
-number always one greater than previous page, then it is guaranteed that
-this function steps the pages through in the order they were allocated
-to the segment. */
-
-ulint
-fseg_get_next_page_no(
-/*==================*/
- /* out: page number, FIL_NULL if no
- page left */
- fseg_header_t* header, /* in: segment header */
- ulint page_no,/* in: previous page number */
- mtr_t* mtr) /* in: mtr */
-{
- buf_block_t* block;
- buf_frame_t* frame;
- ulint space;
- ulint next_page_no;
- xdes_t* descr;
- ulint bit;
- fil_addr_t next_frag_page_addr;
- fseg_page_header_t* page_header;
-
- ut_ad(header);
-
- mtr_x_lock(&fsp_latch, mtr);
-
- block = buf_block_align(header);
- buf_page_x_lock(block, mtr);
-
- space = buf_page_get_space(block);
-
- descr = xdes_get_descriptor(space, page_no, mtr);
- ut_ad(xdes_get_bit(descr, XDES_FREE_BIT,
- page_no % FSP_EXTENT_SIZE, mtr) == FALSE);
-
- if (xdes_get_state(descr, mtr) == XDES_FSEG) {
- /* The extent of the current page belongs to the segment */
- bit = xdes_find_bit(descr, XDES_FREE_BIT, FALSE,
- (page_no + 1) % FSP_EXTENT_SIZE,
- mtr);
- if ((bit == ULINT_UNDEFINED)
- || (bit <= (page_no % FSP_EXTENT_SIZE))) {
- /* No higher address pages in this extent */
- descr = fseg_get_next_extent(header, descr, mtr);
- next_page_no = fseg_extent_get_next_page_no(
- header, descr, mtr);
- } else {
- next_page_no = xdes_get_offset(descr) + bit;
- }
- } else {
- /* Current page is a fragment page */
- block = buf_page_get(space, page_no, mtr);
- buf_page_x_lock(block, mtr);
- frame = buf_block_get_frame(block);
- page_header = frame + FSEG_PAGE_HEADER_OFFSET;
- next_frag_page_addr = flst_get_next_addr(
- page_header + FSEG_PAGE_FRAG_NODE,
- mtr);
-
- next_page_no = next_frag_page_addr.page;
- if (next_page_no == FIL_NULL) {
- descr = fseg_get_first_extent(header, mtr);
- next_page_no = fseg_extent_get_next_page_no(
- header, descr, mtr);
- }
- }
- return(next_page_no);
-}
-
-/**************************************************************************
-Returns the page number of the previous segment page. If no pages have been
-freed from the segment, and the pages were allocated with the hint page
-number always one greater than the previous page, then it is guaranteed that
-this function steps through the pages in the order opposite to the allocation
-order of the pages. */
-
-ulint
-fseg_get_prev_page_no(
-/*==================*/
- /* out: page number, FIL_NULL if no page
- left */
- fseg_header_t* header, /* in: segment header */
- ulint page_no,/* in: page number */
- mtr_t* mtr) /* in: mtr */
-{
- buf_block_t* block;
- buf_frame_t* frame;
- ulint space;
- ulint prev_page_no;
- xdes_t* descr;
- ulint bit;
- fil_addr_t prev_frag_page_addr;
- fseg_page_header_t* page_header;
-
- ut_ad(header);
-
- mtr_x_lock(&fsp_latch, mtr);
-
- block = buf_block_align(header);
- buf_page_x_lock(block, mtr);
-
- space = buf_page_get_space(block);
-
- descr = xdes_get_descriptor(space, page_no, mtr);
- ut_ad(xdes_get_bit(descr, XDES_FREE_BIT,
- page_no % FSP_EXTENT_SIZE, mtr) == FALSE);
-
- if (xdes_get_state(descr, mtr) == XDES_FSEG) {
- /* The extent of the current page belongs to the segment */
- bit = xdes_find_bit_downward(descr, XDES_FREE_BIT, FALSE,
- (page_no - 1) % FSP_EXTENT_SIZE,
- mtr);
- if ((bit == ULINT_UNDEFINED)
- || (bit >= (page_no % FSP_EXTENT_SIZE))) {
- /* No lower address pages in this extent */
- descr = fseg_get_prev_extent(header, descr, mtr);
- prev_page_no = fseg_extent_get_prev_page_no(
- header, descr, mtr);
- } else {
- prev_page_no = xdes_get_offset(descr) + bit;
- }
- } else {
- /* Current page is a fragment page */
- block = buf_page_get(space, page_no, mtr);
- buf_page_x_lock(block, mtr);
- frame = buf_block_get_frame(block);
- page_header = frame + FSEG_PAGE_HEADER_OFFSET;
- prev_frag_page_addr = flst_get_prev_addr(
- page_header + FSEG_PAGE_FRAG_NODE,
- mtr);
-
- prev_page_no = prev_frag_page_addr.page;
- }
- return(prev_page_no);
-}
-
-#endif
-
-/***********************************************************************
-Validates a segment. */
-static
-bool
-fseg_validate_low(
-/*==============*/
- /* out: TRUE if ok */
- fseg_header_t* header, /* in: segment header */
- mtr_t* mtr2) /* in: mtr */
-{
- ulint space;
- dulint seg_id;
- mtr_t mtr;
- xdes_t* descr;
- fil_addr_t node_addr;
- ulint n_used = 0;
- ulint n_used2 = 0;
- flst_node_t* node;
- buf_frame_t* frame;
- fseg_page_header_t* page_header;
-
- ut_ad(mtr_memo_contains(mtr2, buf_block_align(header),
- MTR_MEMO_BUF_FIX));
- buf_page_x_lock(buf_block_align(header), mtr2);
-
- space = buf_page_get_space(buf_block_align(header));
-
- seg_id = mtr_read_dulint(header + FSEG_ID, MLOG_8BYTES, mtr2);
- n_used = mtr_read_ulint(header + FSEG_NOT_FULL_N_USED,
- MLOG_4BYTES, mtr2);
-
- flst_validate(header + FSEG_FRAG, mtr2);
- flst_validate(header + FSEG_FREE, mtr2);
- flst_validate(header + FSEG_NOT_FULL, mtr2);
- flst_validate(header + FSEG_FULL, mtr2);
-
- /* Validate FSEG_FREE list */
- node_addr = flst_get_first(header + FSEG_FREE, mtr2);
-
- while (!fil_addr_is_null(node_addr)) {
- mtr_start(&mtr);
- mtr_x_lock(&fsp_latch, &mtr);
-
- descr = xdes_lst_get_descriptor(space, node_addr, &mtr);
-
- ut_a(xdes_get_n_used(descr, &mtr) == 0);
- ut_a(xdes_get_state(descr, &mtr) == XDES_FSEG);
- ut_a(0 == ut_dulint_cmp(
- mtr_read_dulint(descr + XDES_ID, MLOG_8BYTES,
- &mtr), seg_id));
-
- node_addr = flst_get_next_addr(descr + XDES_FLST_NODE, &mtr);
- mtr_commit(&mtr);
- }
-
- /* Validate FSEG_NOT_FULL list */
-
- node_addr = flst_get_first(header + FSEG_NOT_FULL, mtr2);
-
- while (!fil_addr_is_null(node_addr)) {
- mtr_start(&mtr);
- mtr_x_lock(&fsp_latch, &mtr);
-
- descr = xdes_lst_get_descriptor(space, node_addr, &mtr);
-
- ut_a(xdes_get_n_used(descr, &mtr) > 0);
- ut_a(xdes_get_n_used(descr, &mtr) < FSP_EXTENT_SIZE);
- ut_a(xdes_get_state(descr, &mtr) == XDES_FSEG);
- ut_a(0 == ut_dulint_cmp(
- mtr_read_dulint(descr + XDES_ID, MLOG_8BYTES,
- &mtr), seg_id));
-
- n_used2 += xdes_get_n_used(descr, &mtr);
-
- node_addr = flst_get_next_addr(descr + XDES_FLST_NODE, &mtr);
- mtr_commit(&mtr);
- }
-
- /* Validate FSEG_FULL list */
-
- node_addr = flst_get_first(header + FSEG_FULL, mtr2);
-
- while (!fil_addr_is_null(node_addr)) {
- mtr_start(&mtr);
- mtr_x_lock(&fsp_latch, &mtr);
-
- descr = xdes_lst_get_descriptor(space, node_addr, &mtr);
-
- ut_a(xdes_get_n_used(descr, &mtr) == FSP_EXTENT_SIZE);
- ut_a(xdes_get_state(descr, &mtr) == XDES_FSEG);
- ut_a(0 == ut_dulint_cmp(
- mtr_read_dulint(descr + XDES_ID, MLOG_8BYTES,
- &mtr), seg_id));
-
- node_addr = flst_get_next_addr(descr + XDES_FLST_NODE, &mtr);
- mtr_commit(&mtr);
- }
-
- /* Validate FSEG_FRAG list */
- node_addr = flst_get_first(header + FSEG_FRAG, mtr2);
-
- while (!fil_addr_is_null(node_addr)) {
- mtr_start(&mtr);
- mtr_x_lock(&fsp_latch, &mtr);
-
- node = fut_get_ptr_x_lock(space, node_addr, &mtr);
- frame = buf_frame_align(node);
- page_header = frame + FSEG_PAGE_HEADER_OFFSET;
- ut_a(0 == ut_dulint_cmp(
- mtr_read_dulint(page_header + FSEG_PAGE_SEG_ID,
- MLOG_8BYTES, &mtr), seg_id));
-
- node_addr = flst_get_next_addr(node, &mtr);
- mtr_commit(&mtr);
- }
-
- ut_a(n_used == n_used2);
-
- return(TRUE);
-}
-
-/***********************************************************************
-Validates a segment. */
-
-bool
-fseg_validate(
-/*==========*/
- /* out: TRUE if ok */
- fseg_header_t* header, /* in: segment header */
- mtr_t* mtr2) /* in: mtr */
-{
- bool ret;
-
- mtr_x_lock(&fsp_latch, mtr2);
- ret = fseg_validate_low(header, mtr2);
-
- return(ret);
-}
-
-/***********************************************************************
-Writes info of a segment. */
-static
-void
-fseg_print_low(
-/*===========*/
- fseg_header_t* header, /* in: segment header */
- mtr_t* mtr) /* in: mtr */
-{
- ulint space;
- ulint seg_id_low;
- ulint seg_id_high;
- ulint n_used;
- ulint n_frag;
- ulint n_free;
- ulint n_not_full;
- ulint n_full;
- ulint reserved;
- ulint used;
- ulint page_no;
-
- ut_ad(mtr_memo_contains(mtr, buf_block_align(header),
- MTR_MEMO_BUF_FIX));
- buf_page_x_lock(buf_block_align(header), mtr);
-
- space = buf_page_get_space(buf_block_align(header));
- page_no = buf_page_get_offset(buf_block_align(header));
-
- reserved = fseg_n_reserved_pages_low(header, &used, mtr);
-
- seg_id_low = ut_dulint_get_low(mtr_read_dulint(header + FSEG_ID,
- MLOG_8BYTES, mtr));
- seg_id_high = ut_dulint_get_high(mtr_read_dulint(header + FSEG_ID,
- MLOG_8BYTES, mtr));
-
- n_used = mtr_read_ulint(header + FSEG_NOT_FULL_N_USED,
- MLOG_4BYTES, mtr);
-
- n_frag = flst_get_len(header + FSEG_FRAG, mtr);
- n_free = flst_get_len(header + FSEG_FREE, mtr);
- n_not_full = flst_get_len(header + FSEG_NOT_FULL, mtr);
- n_full = flst_get_len(header + FSEG_FULL, mtr);
-
- printf(
- "SEGMENT id %lu %lu space %lu; page %lu; res %lu used %lu; full ext %lu\n",
- seg_id_high, seg_id_low, space, page_no, reserved, used,
- n_full);
- printf(
- "fragm pages %lu; free extents %lu; not full extents %lu: pages %lu\n",
- n_frag, n_free, n_not_full, n_used);
-}
-
-/***********************************************************************
-Writes info of a segment. */
-
-void
-fseg_print(
-/*=======*/
- fseg_header_t* header, /* in: segment header */
- mtr_t* mtr) /* in: mtr */
-{
- mtr_x_lock(&fsp_latch, mtr);
-
- fseg_print_low(header, mtr);
-}
-
-/***********************************************************************
-Validates the file space system and its segments. */
-
-bool
-fsp_validate(
-/*=========*/
- /* out: TRUE if ok */
- ulint space) /* in: space id */
-{
- fsp_header_t* header;
- fseg_header_t* seg_header;
- ulint size;
- ulint free_limit;
- ulint frag_n_used;
- mtr_t mtr;
- mtr_t mtr2;
- xdes_t* descr;
- fil_addr_t node_addr;
- ulint descr_count = 0;
- ulint n_used = 0;
- ulint n_used2 = 0;
- ulint n_full_frag_pages;
-
- /* Start first a mini-transaction mtr2 to lock out all other threads
- from the fsp system */
- mtr_start(&mtr2);
- mtr_x_lock(&fsp_latch, &mtr2);
-
- mtr_start(&mtr);
- mtr_x_lock(&fsp_latch, &mtr);
-
- header = fsp_get_space_header(space, &mtr);
-
- size = mtr_read_ulint(header + FSP_SIZE, MLOG_4BYTES, &mtr);
- free_limit = mtr_read_ulint(header + FSP_FREE_LIMIT,
- MLOG_4BYTES, &mtr);
- frag_n_used = mtr_read_ulint(header + FSP_FRAG_N_USED,
- MLOG_4BYTES, &mtr);
-
- n_full_frag_pages = FSP_EXTENT_SIZE *
- flst_get_len(header + FSP_FULL_FRAG, &mtr);
-
- ut_a(free_limit <= size);
-
- flst_validate(header + FSP_FREE, &mtr);
- flst_validate(header + FSP_FREE_FRAG, &mtr);
- flst_validate(header + FSP_FULL_FRAG, &mtr);
- flst_validate(header + FSP_SEGS, &mtr);
-
- mtr_commit(&mtr);
-
- /* Validate FSP_FREE list */
- mtr_start(&mtr);
- mtr_x_lock(&fsp_latch, &mtr);
-
- header = fsp_get_space_header(space, &mtr);
- node_addr = flst_get_first(header + FSP_FREE, &mtr);
-
- mtr_commit(&mtr);
-
- while (!fil_addr_is_null(node_addr)) {
- mtr_start(&mtr);
- mtr_x_lock(&fsp_latch, &mtr);
-
- descr_count++;
- descr = xdes_lst_get_descriptor(space, node_addr, &mtr);
-
- ut_a(xdes_get_n_used(descr, &mtr) == 0);
- ut_a(xdes_get_state(descr, &mtr) == XDES_FREE);
-
- node_addr = flst_get_next_addr(descr + XDES_FLST_NODE, &mtr);
- mtr_commit(&mtr);
- }
-
- /* Validate FSP_FREE_FRAG list */
- mtr_start(&mtr);
- mtr_x_lock(&fsp_latch, &mtr);
-
- header = fsp_get_space_header(space, &mtr);
- node_addr = flst_get_first(header + FSP_FREE_FRAG, &mtr);
-
- mtr_commit(&mtr);
-
- while (!fil_addr_is_null(node_addr)) {
- mtr_start(&mtr);
- mtr_x_lock(&fsp_latch, &mtr);
-
- descr_count++;
- descr = xdes_lst_get_descriptor(space, node_addr, &mtr);
-
- ut_a(xdes_get_n_used(descr, &mtr) > 0);
- ut_a(xdes_get_n_used(descr, &mtr) < FSP_EXTENT_SIZE);
- ut_a(xdes_get_state(descr, &mtr) == XDES_FREE_FRAG);
-
- n_used += xdes_get_n_used(descr, &mtr);
- node_addr = flst_get_next_addr(descr + XDES_FLST_NODE, &mtr);
-
- mtr_commit(&mtr);
- }
-
- /* Validate FSP_FULL_FRAG list */
- mtr_start(&mtr);
- mtr_x_lock(&fsp_latch, &mtr);
-
- header = fsp_get_space_header(space, &mtr);
- node_addr = flst_get_first(header + FSP_FULL_FRAG, &mtr);
-
- mtr_commit(&mtr);
-
- while (!fil_addr_is_null(node_addr)) {
- mtr_start(&mtr);
- mtr_x_lock(&fsp_latch, &mtr);
-
- descr_count++;
- descr = xdes_lst_get_descriptor(space, node_addr, &mtr);
-
- ut_a(xdes_get_n_used(descr, &mtr) == FSP_EXTENT_SIZE);
- ut_a(xdes_get_state(descr, &mtr) == XDES_FULL_FRAG);
-
- node_addr = flst_get_next_addr(descr + XDES_FLST_NODE, &mtr);
- mtr_commit(&mtr);
- }
-
- /* Validate segments */
- mtr_start(&mtr);
- mtr_x_lock(&fsp_latch, &mtr);
-
- header = fsp_get_space_header(space, &mtr);
- node_addr = flst_get_first(header + FSP_SEGS, &mtr);
-
- mtr_commit(&mtr);
-
- while (!fil_addr_is_null(node_addr)) {
- mtr_start(&mtr);
- mtr_x_lock(&fsp_latch, &mtr);
-
- seg_header = fut_get_ptr_x_lock(space, node_addr,
- &mtr) - FSEG_FLST_NODE;
- fseg_validate_low(seg_header, &mtr);
-
- descr_count += flst_get_len(seg_header + FSEG_FREE, &mtr);
- descr_count += flst_get_len(seg_header + FSEG_FULL, &mtr);
- descr_count += flst_get_len(seg_header + FSEG_NOT_FULL, &mtr);
-
- n_used2 += flst_get_len(seg_header + FSEG_FRAG, &mtr);
-
- node_addr = flst_get_next_addr(seg_header + FSEG_FLST_NODE,
- &mtr);
- mtr_commit(&mtr);
- }
-
- ut_a(descr_count * FSP_EXTENT_SIZE == free_limit);
- ut_a(n_used + n_full_frag_pages
- == n_used2 + (free_limit + XDES_DESCRIBED_PER_PAGE - 1)
- / XDES_DESCRIBED_PER_PAGE);
- ut_a(frag_n_used == n_used);
-
- mtr_commit(&mtr2);
- return(TRUE);
-}
-
-/***********************************************************************
-Prints info of a file space. */
-
-void
-fsp_print(
-/*======*/
- ulint space) /* in: space id */
-{
- fsp_header_t* header;
- fseg_header_t* seg_header;
- ulint size;
- ulint free_limit;
- ulint frag_n_used;
- mtr_t mtr;
- mtr_t mtr2;
- fil_addr_t node_addr;
- ulint n_free;
- ulint n_free_frag;
- ulint n_full_frag;
- ulint n_segs;
- ulint seg_id_low;
- ulint seg_id_high;
-
- /* Start first a mini-transaction mtr2 to lock out all other threads
- from the fsp system */
- mtr_start(&mtr2);
- mtr_x_lock(&fsp_latch, &mtr2);
-
- mtr_start(&mtr);
- mtr_x_lock(&fsp_latch, &mtr);
-
- header = fsp_get_space_header(space, &mtr);
-
- size = mtr_read_ulint(header + FSP_SIZE, MLOG_4BYTES, &mtr);
- free_limit = mtr_read_ulint(header + FSP_FREE_LIMIT,
- MLOG_4BYTES, &mtr);
- frag_n_used = mtr_read_ulint(header + FSP_FRAG_N_USED,
- MLOG_4BYTES, &mtr);
-
- n_free = flst_get_len(header + FSP_FREE, &mtr);
- n_free_frag = flst_get_len(header + FSP_FREE_FRAG, &mtr);
- n_full_frag = flst_get_len(header + FSP_FULL_FRAG, &mtr);
- n_segs = flst_get_len(header + FSP_SEGS, &mtr);
- seg_id_low = ut_dulint_get_low(mtr_read_dulint(header + FSP_SEG_ID,
- MLOG_8BYTES, &mtr));
- seg_id_high = ut_dulint_get_high(mtr_read_dulint(header + FSP_SEG_ID,
- MLOG_8BYTES, &mtr));
-
- printf("FILE SPACE INFO: id %lu\n", space);
-
- printf("size %lu, free limit %lu, free extents %lu\n",
- size, free_limit, n_free);
- printf(
- "not full frag extents %lu: used pages %lu, full frag extents %lu\n",
- n_free_frag, frag_n_used, n_full_frag);
-
- printf("number of segments %lu, first seg id not used %lu %lu\n",
- n_segs, seg_id_high, seg_id_low);
-
- /* Print segments */
- node_addr = flst_get_first(header + FSP_SEGS, &mtr);
-
- mtr_commit(&mtr);
-
- while (!fil_addr_is_null(node_addr)) {
- mtr_start(&mtr);
- mtr_x_lock(&fsp_latch, &mtr);
-
- seg_header = fut_get_ptr_x_lock(space, node_addr,
- &mtr) - FSEG_FLST_NODE;
- fseg_print_low(seg_header, &mtr);
-
- node_addr = flst_get_next_addr(seg_header + FSEG_FLST_NODE,
- &mtr);
- mtr_commit(&mtr);
- }
-
- mtr_commit(&mtr2);
-}
-
diff --git a/innobase/fsp/ts/del.c b/innobase/fsp/ts/del.c
deleted file mode 100644
index 885797bdc76..00000000000
--- a/innobase/fsp/ts/del.c
+++ /dev/null
@@ -1,891 +0,0 @@
-/************************************************************************
-The test module for the file system and buffer manager
-
-(c) 1995 Innobase Oy
-
-Created 11/16/1995 Heikki Tuuri
-*************************************************************************/
-
-#include "string.h"
-
-#include "os0thread.h"
-#include "os0file.h"
-#include "ut0ut.h"
-#include "ut0byte.h"
-#include "sync0sync.h"
-#include "mem0mem.h"
-#include "fil0fil.h"
-#include "..\buf0buf.h"
-#include "..\buf0buf.h1"
-#include "..\buf0buf.h2"
-#include "..\buf0flu.h"
-#include "..\buf0lru.h"
-#include "mtr0buf.h"
-#include "mtr0log.h"
-#include "fsp0fsp.h"
-#include "log0log.h"
-
-os_file_t files[1000];
-
-mutex_t ios_mutex;
-ulint ios;
-ulint n[5];
-
-
-/************************************************************************
-Io-handler thread function. */
-
-ulint
-handler_thread(
-/*===========*/
- void* arg)
-{
- ulint segment;
- void* mess;
- ulint i;
- bool ret;
-
- segment = *((ulint*)arg);
-
- printf("Thread %lu starts\n", segment);
-
- for (i = 0;; i++) {
- ret = fil_aio_wait(segment, &mess);
- ut_a(ret);
-
- buf_page_io_complete((buf_block_t*)mess);
-
- mutex_enter(&ios_mutex);
- ios++;
- mutex_exit(&ios_mutex);
-
- }
-
- return(0);
-}
-
-/************************************************************************
-Creates the test database files. */
-
-void
-create_db(void)
-/*===========*/
-{
- ulint i;
- buf_block_t* block;
- byte* frame;
- ulint j;
- ulint tm, oldtm;
- mtr_t mtr;
-
- oldtm = ut_clock();
-
- for (i = 0; i < 1; i++) {
- for (j = 0; j < 4096; j++) {
- mtr_start(&mtr);
- if (j == 0) {
- fsp_header_init(i, 4096, &mtr);
-
- block = mtr_page_get(i, j, NULL, &mtr);
- } else {
- block = mtr_page_create(i, j, &mtr);
- }
-
- frame = buf_block_get_frame(block);
-
- mtr_page_x_lock(block, &mtr);
-
- mlog_write_ulint(frame + FIL_PAGE_PREV,
- j - 1, MLOG_4BYTES, &mtr);
-
- mlog_write_ulint(frame + FIL_PAGE_NEXT,
- j + 1, MLOG_4BYTES, &mtr);
-
- mlog_write_ulint(frame + FIL_PAGE_OFFSET,
- j, MLOG_4BYTES, &mtr);
-
- mtr_commit(&mtr);
- }
- }
-
- tm = ut_clock();
- printf("Wall clock time for test %lu milliseconds\n", tm - oldtm);
-
- /* Flush the pool of dirty pages by reading low-offset pages */
- for (i = 0; i < 1000; i++) {
-
- mtr_start(&mtr);
- block = mtr_page_get(0, i, NULL, &mtr);
-
- frame = buf_block_get_frame(block);
-
- mtr_page_s_lock(block, &mtr);
-
- ut_a(mtr_read_ulint(frame + FIL_PAGE_OFFSET, MLOG_4BYTES,
- &mtr) == i);
-
- mtr_commit(&mtr);
- }
-
- os_thread_sleep(1000000);
-
- ut_a(buf_all_freed());
-}
-
-/*************************************************************************
-Creates the files for the file system test and inserts them to
-the file system. */
-
-void
-create_files(void)
-/*==============*/
-{
- bool ret;
- ulint i, k;
- char name[20];
- os_thread_t thr[5];
- os_thread_id_t id[5];
-
- strcpy(name, "j:\\tsfile1");
-
- for (k = 0; k < 1; k++) {
- for (i = 0; i < 4; i++) {
-
- name[9] = (char)((ulint)'0' + i);
-
- files[i] = os_file_create(name, OS_FILE_CREATE,
- OS_FILE_TABLESPACE, &ret);
-
- if (ret == FALSE) {
- ut_a(os_file_get_last_error() ==
- OS_FILE_ALREADY_EXISTS);
-
- files[i] = os_file_create(
- name, OS_FILE_OPEN,
- OS_FILE_TABLESPACE, &ret);
-
- ut_a(ret);
- }
-
- ret = os_file_set_size(files[i], 4096 * 8192, 0);
- ut_a(ret);
-
- ret = os_file_close(files[i]);
- ut_a(ret);
-
- if (i == 0) {
- fil_space_create("noname", k, OS_FILE_TABLESPACE);
- }
-
- ut_a(fil_validate());
-
- fil_node_create(name, 4096, k);
- }
- }
-
- ios = 0;
-
- mutex_create(&ios_mutex);
-
- for (i = 0; i < 5; i++) {
- n[i] = i;
-
- thr[i] = os_thread_create(handler_thread, n + i, id + i);
- }
-}
-
-/************************************************************************
-Reads the test database files. */
-
-void
-test1(void)
-/*=======*/
-{
- ulint i, j, k;
- buf_block_t* block;
- byte* frame;
- ulint tm, oldtm;
-
- buf_flush_batch(BUF_FLUSH_LIST, 1000);
-
- os_thread_sleep(1000000);
-
- buf_all_freed();
-
- oldtm = ut_clock();
-
- for (k = 0; k < 1; k++) {
- for (i = 0; i < 1; i++) {
- for (j = 0; j < 409; j++) {
- block = buf_page_get(i, j, NULL);
-
- frame = buf_block_get_frame(block);
-
- buf_page_s_lock(block);
-
- ut_a(*((ulint*)(frame + 16)) == j);
-
- buf_page_s_unlock(block);
-
- buf_page_release(block);
- }
- }
- }
-
- tm = ut_clock();
- printf("Wall clock time for test %lu milliseconds\n", tm - oldtm);
-
-}
-
-/************************************************************************
-Reads the test database files. */
-
-void
-test2(void)
-/*=======*/
-{
- ulint i, j, k, rnd;
- buf_block_t* block;
- byte* frame;
- ulint tm, oldtm;
-
- oldtm = ut_clock();
-
- rnd = 123;
-
- for (k = 0; k < 100; k++) {
- rnd += 23651;
- rnd = rnd % 4096;
-
- i = rnd / 4096;
- j = rnd % 2048;
-
- block = buf_page_get(i, j, NULL);
-
- frame = buf_block_get_frame(block);
-
- buf_page_s_lock(block);
-
- ut_a(*((ulint*)(frame + 16)) == j);
-
- buf_page_s_unlock(block);
-
- buf_page_release(block);
- }
-
- tm = ut_clock();
- printf("Wall clock time for random read %lu milliseconds\n",
- tm - oldtm);
-}
-
-/************************************************************************
-Reads the test database files. */
-
-void
-test4(void)
-/*=======*/
-{
- ulint i, j, k, rnd;
- buf_block_t* block;
- byte* frame;
- ulint tm, oldtm;
-
- /* Flush the pool of high-offset pages */
- for (i = 0; i < 1000; i++) {
-
- block = buf_page_get(0, i, NULL);
-
- frame = buf_block_get_frame(block);
-
- buf_page_s_lock(block);
-
- ut_a(*((ulint*)(frame + 16)) == i);
-
- buf_page_s_unlock(block);
-
- buf_page_release(block);
- }
-
- printf("Test starts\n");
-
- oldtm = ut_clock();
-
- rnd = 123;
-
- for (k = 0; k < 400; k++) {
-
- rnd += 4357;
-
- i = 0;
- j = 1001 + rnd % 3000;
-
- block = buf_page_get(i, j, NULL);
-
- frame = buf_block_get_frame(block);
-
- buf_page_s_lock(block);
-
- ut_a(*((ulint*)(frame + 16)) == j);
-
- buf_page_s_unlock(block);
-
- buf_page_release(block);
- }
-
- tm = ut_clock();
- printf(
- "Wall clock time for %lu random no read-ahead %lu milliseconds\n",
- k, tm - oldtm);
-
- /* Flush the pool of high-offset pages */
- for (i = 0; i < 1000; i++) {
-
- block = buf_page_get(0, i, NULL);
-
- frame = buf_block_get_frame(block);
-
- buf_page_s_lock(block);
-
- ut_a(*((ulint*)(frame + 16)) == i);
-
- buf_page_s_unlock(block);
-
- buf_page_release(block);
- }
-
- printf("Test starts\n");
-
- oldtm = ut_clock();
-
- rnd = 123;
-
- for (k = 0; k < 400; k++) {
-
- rnd += 4357;
-
- i = 0;
- j = 1001 + rnd % 400;
-
- block = buf_page_get(i, j, NULL);
-
- frame = buf_block_get_frame(block);
-
- buf_page_s_lock(block);
-
- ut_a(*((ulint*)(frame + 16)) == j);
-
- buf_page_s_unlock(block);
-
- buf_page_release(block);
- }
-
- tm = ut_clock();
- printf(
- "Wall clock time for %lu random read-ahead %lu milliseconds\n",
- k, tm - oldtm);
-
-}
-
-/************************************************************************
-Tests speed of CPU algorithms. */
-
-void
-test3(void)
-/*=======*/
-{
- ulint i, j;
- buf_block_t* block;
- ulint tm, oldtm;
-
- for (i = 0; i < 400; i++) {
-
- block = buf_page_get(0, i, NULL);
-
- buf_page_release(block);
- }
-
- os_thread_sleep(2000000);
-
- oldtm = ut_clock();
-
- for (j = 0; j < 500; j++) {
- for (i = 0; i < 200; i++) {
-
- block = buf_page_get(0, i, NULL);
-
-/*
- buf_page_s_lock(block);
-
- buf_page_s_unlock(block);
-*/
-
- buf_page_release(block);
-
- }
- }
-
- tm = ut_clock();
- printf("Wall clock time for %lu page get-release %lu milliseconds\n",
- i * j, tm - oldtm);
-
- oldtm = ut_clock();
-
- for (j = 0; j < 500; j++) {
- for (i = 0; i < 200; i++) {
-
- buf_page_get(0, i, NULL);
-/*
- buf_page_s_lock(block);
-
- buf_page_s_unlock(block);
-*/
- buf_page_release(block);
- }
- }
-
- tm = ut_clock();
- printf("Wall clock time for %lu block get-release %lu milliseconds\n",
- i * j, tm - oldtm);
-
-
- oldtm = ut_clock();
-
- for (i = 0; i < 100000; i++) {
- block = buf_block_alloc();
- buf_block_free(block);
- }
-
- tm = ut_clock();
- printf("Wall clock time for %lu block alloc-free %lu milliseconds\n",
- i, tm - oldtm);
-
- ha_print_info(buf_pool->page_hash);
-}
-
-/************************************************************************
-Frees the spaces in the file system. */
-
-void
-free_system(void)
-/*=============*/
-{
- ulint i;
-
- for (i = 0; i < 1; i++) {
- fil_space_free(i);
- }
-}
-
-/************************************************************************
-Test for file space management. */
-
-void
-test5(void)
-/*=======*/
-{
- mtr_t mtr;
- ulint seg_page;
- ulint new_page;
- ulint seg_page2;
- ulint new_page2;
- buf_block_t* block;
- bool finished;
- ulint i;
- ulint reserved;
- ulint used;
- ulint tm, oldtm;
-
- os_thread_sleep(1000000);
-
- buf_validate();
-
- buf_print();
-
- mtr_start(&mtr);
-
- seg_page = fseg_create(0, 0, 1000, 555, &mtr);
-
- mtr_commit(&mtr);
-
- os_thread_sleep(1000000);
- buf_validate();
- printf("Segment created: header page %lu\n", seg_page);
-
- mtr_start(&mtr);
-
- block = mtr_page_get(0, seg_page, NULL, &mtr);
-
- new_page = fseg_alloc_free_page(buf_block_get_frame(block) + 1000,
- 2, FSP_UP, &mtr);
-
- mtr_commit(&mtr);
-
- buf_validate();
- buf_print();
- printf("Segment page allocated %lu\n", new_page);
-
- finished = FALSE;
-
- while (!finished) {
-
- mtr_start(&mtr);
-
- block = mtr_page_get(0, seg_page, NULL, &mtr);
-
- finished = fseg_free_step(
- buf_block_get_frame(block) + 1000, &mtr);
-
- mtr_commit(&mtr);
- }
-
- /***********************************************/
- os_thread_sleep(1000000);
- buf_validate();
- buf_print();
- mtr_start(&mtr);
-
- seg_page = fseg_create(0, 0, 1000, 557, &mtr);
-
- mtr_commit(&mtr);
-
- ut_a(seg_page == 1);
-
- printf("Segment created: header page %lu\n", seg_page);
-
- new_page = seg_page;
- for (i = 0; i < 1023; i++) {
-
- mtr_start(&mtr);
-
- block = mtr_page_get(0, seg_page, NULL, &mtr);
-
- new_page = fseg_alloc_free_page(
- buf_block_get_frame(block) + 1000,
- new_page + 1, FSP_UP, &mtr);
- if (i < FSP_EXTENT_SIZE - 1) {
- ut_a(new_page == 2 + i);
- } else {
- ut_a(new_page == i + FSP_EXTENT_SIZE + 1);
- }
-
- printf("%lu %lu; ", i, new_page);
- if (i % 10 == 0) {
- printf("\n");
- }
-
- mtr_commit(&mtr);
- }
-
- buf_print();
- buf_validate();
-
- mtr_start(&mtr);
-
- block = mtr_page_get(0, seg_page, NULL, &mtr);
-
- mtr_page_s_lock(block, &mtr);
-
- reserved = fseg_n_reserved_pages(buf_block_get_frame(block) + 1000,
- &used, &mtr);
-
- ut_a(used == 1024);
- ut_a(reserved >= 1024);
-
- printf("Pages used in segment %lu reserved by segment %lu \n",
- used, reserved);
-
- mtr_commit(&mtr);
-
- finished = FALSE;
-
- while (!finished) {
-
- mtr_start(&mtr);
-
- block = mtr_page_get(0, seg_page, NULL, &mtr);
-
- finished = fseg_free_step(
- buf_block_get_frame(block) + 1000, &mtr);
-
- mtr_commit(&mtr);
- }
-
- buf_print();
- buf_validate();
-
- /***********************************************/
-
- mtr_start(&mtr);
-
- seg_page = fseg_create(0, 0, 1000, 557, &mtr);
-
- mtr_commit(&mtr);
-
- ut_a(seg_page == 1);
-
- mtr_start(&mtr);
-
- seg_page2 = fseg_create(0, 0, 1000, 558, &mtr);
-
- mtr_commit(&mtr);
-
- ut_a(seg_page2 == 2);
-
- new_page = seg_page;
- new_page2 = seg_page2;
-
- for (;;) {
-
- mtr_start(&mtr);
-
- block = mtr_page_get(0, seg_page, NULL, &mtr);
-
- new_page = fseg_alloc_free_page(
- buf_block_get_frame(block) + 1000,
- new_page + 1, FSP_UP, &mtr);
-
- printf("1:%lu %lu; ", i, new_page);
- if (i % 10 == 0) {
- printf("\n");
- }
-
- new_page = fseg_alloc_free_page(
- buf_block_get_frame(block) + 1000,
- new_page + 1, FSP_UP, &mtr);
-
- printf("1:%lu %lu; ", i, new_page);
- if (i % 10 == 0) {
- printf("\n");
- }
-
- mtr_commit(&mtr);
-
- mtr_start(&mtr);
-
- block = mtr_page_get(0, seg_page2, NULL, &mtr);
-
- new_page2 = fseg_alloc_free_page(
- buf_block_get_frame(block) + 1000,
- new_page2 + 1, FSP_UP, &mtr);
-
- printf("2:%lu %lu; ", i, new_page2);
- if (i % 10 == 0) {
- printf("\n");
- }
-
- mtr_commit(&mtr);
-
- if (new_page2 == FIL_NULL) {
- break;
- }
- }
-
- mtr_start(&mtr);
-
- block = mtr_page_get(0, seg_page, NULL, &mtr);
-
- mtr_page_s_lock(block, &mtr);
-
- reserved = fseg_n_reserved_pages(buf_block_get_frame(block) + 1000,
- &used, &mtr);
-
- printf("Pages used in segment 1 %lu, reserved by segment %lu \n",
- used, reserved);
-
- mtr_commit(&mtr);
-
- mtr_start(&mtr);
-
- block = mtr_page_get(0, seg_page2, NULL, &mtr);
-
- mtr_page_s_lock(block, &mtr);
-
- reserved = fseg_n_reserved_pages(buf_block_get_frame(block) + 1000,
- &used, &mtr);
-
- printf("Pages used in segment 2 %lu, reserved by segment %lu \n",
- used, reserved);
-
- mtr_commit(&mtr);
-
- for (;;) {
-
- mtr_start(&mtr);
-
- block = mtr_page_get(0, seg_page, NULL, &mtr);
-
- fseg_free_step(
- buf_block_get_frame(block) + 1000, &mtr);
-
- block = mtr_page_get(0, seg_page2, NULL, &mtr);
-
- finished = fseg_free_step(
- buf_block_get_frame(block) + 1000, &mtr);
-
- mtr_commit(&mtr);
-
- if (finished) {
- break;
- }
- }
-
- mtr_start(&mtr);
-
- seg_page2 = fseg_create(0, 0, 1000, 558, &mtr);
-
- mtr_commit(&mtr);
-
- i = 0;
- for (;;) {
- mtr_start(&mtr);
-
- block = mtr_page_get(0, seg_page2, NULL, &mtr);
-
- new_page2 = fseg_alloc_free_page(
- buf_block_get_frame(block) + 1000,
- 557, FSP_DOWN, &mtr);
-
- printf("%lu %lu; ", i, new_page2);
- mtr_commit(&mtr);
-
- if (new_page2 == FIL_NULL) {
- break;
- }
- i++;
- }
-
- for (;;) {
-
- mtr_start(&mtr);
-
- block = mtr_page_get(0, seg_page, NULL, &mtr);
-
- finished = fseg_free_step(
- buf_block_get_frame(block) + 1000, &mtr);
-
- mtr_commit(&mtr);
-
- if (finished) {
- break;
- }
- }
-
- for (;;) {
-
- mtr_start(&mtr);
-
- block = mtr_page_get(0, seg_page2, NULL, &mtr);
-
- finished = fseg_free_step(
- buf_block_get_frame(block) + 1000, &mtr);
-
- mtr_commit(&mtr);
-
- if (finished) {
- break;
- }
- }
-
-
- /***************************************/
-
- oldtm = ut_clock();
-
- for (i = 0; i < 1000; i++) {
- mtr_start(&mtr);
-
- seg_page = fseg_create(0, 0, 1000, 555, &mtr);
-
- mtr_commit(&mtr);
-
- mtr_start(&mtr);
-
- block = mtr_page_get(0, seg_page, NULL, &mtr);
-
- new_page = fseg_alloc_free_page(buf_block_get_frame(block) + 1000,
- 2, FSP_UP, &mtr);
-
- mtr_commit(&mtr);
-
- finished = FALSE;
-
- while (!finished) {
-
- mtr_start(&mtr);
-
- block = mtr_page_get(0, seg_page, NULL, &mtr);
-
- finished = fseg_free_step(
- buf_block_get_frame(block) + 1000, &mtr);
-
- mtr_commit(&mtr);
- }
- }
-
- tm = ut_clock();
- printf("Wall clock time for %lu seg crea+free %lu millisecs\n",
- i, tm - oldtm);
-
- buf_validate();
-
- buf_flush_batch(BUF_FLUSH_LIST, 500);
-
- os_thread_sleep(1000000);
-
- buf_all_freed();
-}
-
-
-/************************************************************************
-Main test function. */
-
-void
-main(void)
-/*======*/
-{
- ulint tm, oldtm;
- ulint n;
-
- oldtm = ut_clock();
-
- os_aio_init(160, 5);
- sync_init();
- mem_init();
- fil_init(26); /* Allow 25 open files at a time */
- buf_pool_init(1000, 1000);
- log_init();
-
- buf_validate();
-
- ut_a(fil_validate());
-
- create_files();
-
- create_db();
-
- buf_validate();
-
- test5();
-/*
- test1();
-
- test3();
-
- test4();
-
- test2();
-*/
- buf_validate();
-
- n = buf_flush_batch(BUF_FLUSH_LIST, 500);
-
- os_thread_sleep(1000000);
-
- buf_all_freed();
-
- free_system();
-
- tm = ut_clock();
- printf("Wall clock time for test %lu milliseconds\n", tm - oldtm);
- printf("TESTS COMPLETED SUCCESSFULLY!\n");
-}
diff --git a/innobase/fsp/ts/makefile b/innobase/fsp/ts/makefile
deleted file mode 100644
index cd56e791b31..00000000000
--- a/innobase/fsp/ts/makefile
+++ /dev/null
@@ -1,16 +0,0 @@
-
-
-
-include ..\..\makefile.i
-
-tsfsp: ..\fsp.lib tsfsp.c
- $(CCOM) $(CFL) -I.. -I..\.. ..\..\btr.lib ..\..\trx.lib ..\..\pars.lib ..\..\que.lib ..\..\lock.lib ..\..\row.lib ..\..\read.lib ..\..\srv.lib ..\..\com.lib ..\..\usr.lib ..\..\thr.lib ..\..\fut.lib ..\fsp.lib ..\..\page.lib ..\..\dyn.lib ..\..\mtr.lib ..\..\log.lib ..\..\rem.lib ..\..\fil.lib ..\..\buf.lib ..\..\dict.lib ..\..\data.lib ..\..\mach.lib ..\..\ha.lib ..\..\ut.lib ..\..\sync.lib ..\..\mem.lib ..\..\os.lib tsfsp.c $(LFL)
-
-
-
-
-
-
-
-
-
diff --git a/innobase/fsp/ts/tsfsp.c b/innobase/fsp/ts/tsfsp.c
deleted file mode 100644
index ba6a35ebc69..00000000000
--- a/innobase/fsp/ts/tsfsp.c
+++ /dev/null
@@ -1,1234 +0,0 @@
-/************************************************************************
-The test module for file space management
-
-(c) 1996 Innobase Oy
-
-Created 1/4/1996 Heikki Tuuri
-*************************************************************************/
-
-#include "string.h"
-
-#include "os0thread.h"
-#include "os0file.h"
-#include "ut0ut.h"
-#include "ut0byte.h"
-#include "sync0sync.h"
-#include "mem0mem.h"
-#include "fil0fil.h"
-#include "mach0data.h"
-#include "buf0buf.h"
-#include "buf0flu.h"
-#include "log0log.h"
-#include "fut0lst.h"
-#include "fut0fut.h"
-#include "mtr0mtr.h"
-#include "mtr0log.h"
-#include "..\fsp0fsp.h"
-
-os_file_t files[1000];
-
-mutex_t ios_mutex;
-ulint ios;
-ulint n[10];
-
-mutex_t incs_mutex;
-ulint incs;
-ulint page_nos[10000];
-
-#define N_SPACES 1
-#define N_FILES 2
-#define FILE_SIZE 1000 /* must be > 512 */
-#define POOL_SIZE 1000
-#define COUNTER_OFFSET 1500
-
-#define LOOP_SIZE 150
-#define N_THREADS 5
-
-
-ulint zero = 0;
-
-buf_block_t* bl_arr[POOL_SIZE];
-
-/************************************************************************
-Io-handler thread function. */
-
-ulint
-handler_thread(
-/*===========*/
- void* arg)
-{
- ulint segment;
- void* mess;
- ulint i;
- bool ret;
-
- segment = *((ulint*)arg);
-
- printf("Io handler thread %lu starts\n", segment);
-
- for (i = 0;; i++) {
- ret = fil_aio_wait(segment, &mess);
- ut_a(ret);
-
- buf_page_io_complete((buf_block_t*)mess);
-
- mutex_enter(&ios_mutex);
- ios++;
- mutex_exit(&ios_mutex);
-
- }
-
- return(0);
-}
-
-/*************************************************************************
-Creates the files for the file system test and inserts them to
-the file system. */
-
-void
-create_files(void)
-/*==============*/
-{
- bool ret;
- ulint i, k;
- char name[20];
- os_thread_t thr[5];
- os_thread_id_t id[5];
-
- printf("--------------------------------------------------------\n");
- printf("Create or open database files\n");
-
- strcpy(name, "tsfile00");
-
- for (k = 0; k < N_SPACES; k++) {
- for (i = 0; i < N_FILES; i++) {
-
- name[6] = (char)((ulint)'0' + k);
- name[7] = (char)((ulint)'0' + i);
-
- files[i] = os_file_create(name, OS_FILE_CREATE,
- OS_FILE_TABLESPACE, &ret);
-
- if (ret == FALSE) {
- ut_a(os_file_get_last_error() ==
- OS_FILE_ALREADY_EXISTS);
-
- files[i] = os_file_create(
- name, OS_FILE_OPEN,
- OS_FILE_TABLESPACE, &ret);
-
- ut_a(ret);
- }
-
- ret = os_file_close(files[i]);
- ut_a(ret);
-
- if (i == 0) {
- fil_space_create(name, k, OS_FILE_TABLESPACE);
- }
-
- ut_a(fil_validate());
-
- fil_node_create(name, FILE_SIZE, k);
- }
- }
-
- ios = 0;
-
- mutex_create(&ios_mutex);
-
- for (i = 0; i < 5; i++) {
- n[i] = i;
-
- thr[i] = os_thread_create(handler_thread, n + i, id + i);
- }
-}
-
-/************************************************************************
-Creates the test database files. */
-
-void
-create_db(void)
-/*===========*/
-{
- ulint i;
- buf_block_t* block;
- byte* frame;
- ulint j;
- ulint tm, oldtm;
- mtr_t mtr;
-
- printf("--------------------------------------------------------\n");
- printf("Write database pages\n");
-
- oldtm = ut_clock();
-
- for (i = 0; i < N_SPACES; i++) {
- for (j = 0; j < FILE_SIZE * N_FILES; j++) {
- mtr_start(&mtr);
-
- block = buf_page_create(i, j, &mtr);
-
- frame = buf_block_get_frame(block);
-
- buf_page_x_lock(block, &mtr);
-
- if (j > FILE_SIZE * N_FILES
- - 64 * 2 - 1) {
- mlog_write_ulint(frame + FIL_PAGE_PREV, j - 5,
- MLOG_4BYTES, &mtr);
- mlog_write_ulint(frame + FIL_PAGE_NEXT, j - 7,
- MLOG_4BYTES, &mtr);
- } else {
- mlog_write_ulint(frame + FIL_PAGE_PREV, j - 1,
- MLOG_4BYTES, &mtr);
- mlog_write_ulint(frame + FIL_PAGE_NEXT, j + 1,
- MLOG_4BYTES, &mtr);
- }
-
- mlog_write_ulint(frame + FIL_PAGE_OFFSET, j,
- MLOG_4BYTES, &mtr);
- mlog_write_ulint(frame + FIL_PAGE_SPACE, i,
- MLOG_4BYTES, &mtr);
- mlog_write_ulint(frame + COUNTER_OFFSET, 0,
- MLOG_4BYTES, &mtr);
-
- mtr_commit(&mtr);
- }
- }
-
- tm = ut_clock();
- printf("Wall clock time for test %lu milliseconds\n", tm - oldtm);
-}
-
-/************************************************************************
-Reads the test database files. */
-
-void
-test1(void)
-/*=======*/
-{
- ulint i, j, k;
- buf_block_t* block;
- byte* frame;
- ulint tm, oldtm;
- mtr_t mtr;
-
- printf("--------------------------------------------------------\n");
- printf("TEST 1. Read linearly database files\n");
-
- oldtm = ut_clock();
-
- for (k = 0; k < 1; k++) {
- for (i = 0; i < N_SPACES; i++) {
- for (j = 0; j < N_FILES * FILE_SIZE; j++) {
- mtr_start(&mtr);
-
- block = buf_page_get(i, j, &mtr);
-
- frame = buf_block_get_frame(block);
-
- buf_page_s_lock(block, &mtr);
-
- ut_a(mtr_read_ulint(frame + FIL_PAGE_OFFSET,
- MLOG_4BYTES, &mtr)
- == j);
- ut_a(mtr_read_ulint(frame + FIL_PAGE_SPACE,
- MLOG_4BYTES, &mtr)
- == i);
-
- mtr_commit(&mtr);
- }
- }
- }
-
- tm = ut_clock();
- printf("Wall clock time for %lu pages %lu milliseconds\n",
- k * i * j, tm - oldtm);
- buf_validate();
-}
-
-/************************************************************************
-Test for file-based lists. */
-
-void
-test2(void)
-/*=======*/
-{
- mtr_t mtr;
- buf_frame_t* frame;
- buf_block_t* block;
- ulint i;
- flst_base_node_t* base1;
- fil_addr_t base_addr1;
- flst_base_node_t* base2;
- fil_addr_t base_addr2;
- flst_node_t* node;
- fil_addr_t node_addr;
- flst_node_t* node2;
- fil_addr_t node_addr2;
- flst_node_t* node3;
- fil_addr_t node_addr3;
-
-#define BPAGE 10
-#define BASE1 300
-#define BASE2 500
-#define NODE1 800
-#define NODE2 900
-#define NODE3 1000
-#define NODE4 1100
-#define INDEX 30
-
- buf_validate();
-
- mtr_start(&mtr);
-
- block = buf_page_get(0, BPAGE, &mtr);
- frame = buf_block_get_frame(block);
-
- flst_init(frame + BASE1, &mtr);
- flst_init(frame + BASE2, &mtr);
-
- mtr_commit(&mtr);
-
- printf("-------------------------------------------\n");
- printf("TEST 2. Test of file-based two-way lists \n");
-
- base_addr1.page = BPAGE;
- base_addr1.boffset = BASE1;
-
- base_addr2.page = BPAGE;
- base_addr2.boffset = BASE2;
-
- printf(
- "Add 1000 elements in list1 in reversed order and in list2 in order\n");
- for (i = 0; i < 1000; i++) {
- mtr_start(&mtr);
-
- base1 = fut_get_ptr(0, base_addr1, &mtr);
- base2 = fut_get_ptr(0, base_addr2, &mtr);
-
- block = buf_page_get(0, i, &mtr);
- frame = buf_block_get_frame(block);
-
- buf_page_x_lock(block, &mtr);
-
- flst_add_first(base1, frame + NODE1, &mtr);
- mlog_write_ulint(frame + NODE1 + INDEX, i,
- MLOG_4BYTES, &mtr);
- flst_add_last(base2, frame + NODE2, &mtr);
- mlog_write_ulint(frame + NODE2 + INDEX, i,
- MLOG_4BYTES, &mtr);
-
- mtr_commit(&mtr);
- }
-
- mtr_start(&mtr);
-
- base1 = fut_get_ptr(0, base_addr1, &mtr);
- base2 = fut_get_ptr(0, base_addr2, &mtr);
-
- flst_validate(base1, &mtr);
- flst_validate(base2, &mtr);
-
- flst_print(base1, &mtr);
- flst_print(base2, &mtr);
-
- mtr_commit(&mtr);
-
- mtr_start(&mtr);
-
- base1 = fut_get_ptr_s_lock(0, base_addr1, &mtr);
-
- node_addr = flst_get_first(base1, &mtr);
-
- mtr_commit(&mtr);
-
- printf("Check order of elements in list1\n");
- for (i = 0; i < 1000; i++) {
- mtr_start(&mtr);
- ut_a(!fil_addr_is_null(node_addr));
-
- node = fut_get_ptr_x_lock(0, node_addr, &mtr);
-
- ut_a(mtr_read_ulint(node + INDEX, MLOG_4BYTES, &mtr) ==
- 999 - i);
-
- node_addr = flst_get_next_addr(node, &mtr);
- mtr_commit(&mtr);
- }
-
- ut_a(fil_addr_is_null(node_addr));
-
- mtr_start(&mtr);
-
- base2 = fut_get_ptr_s_lock(0, base_addr2, &mtr);
-
- node_addr = flst_get_first(base2, &mtr);
-
- mtr_commit(&mtr);
-
- printf("Check order of elements in list2\n");
- for (i = 0; i < 1000; i++) {
- mtr_start(&mtr);
- ut_a(!fil_addr_is_null(node_addr));
-
- node = fut_get_ptr_x_lock(0, node_addr, &mtr);
-
- ut_a(mtr_read_ulint(node + INDEX, MLOG_4BYTES, &mtr)
- == i);
-
- node_addr = flst_get_next_addr(node, &mtr);
- mtr_commit(&mtr);
- }
-
- ut_a(fil_addr_is_null(node_addr));
-
- mtr_start(&mtr);
-
- base1 = fut_get_ptr(0, base_addr1, &mtr);
- base2 = fut_get_ptr(0, base_addr2, &mtr);
-
- flst_validate(base1, &mtr);
- flst_validate(base2, &mtr);
-
- mtr_commit(&mtr);
-
- mtr_start(&mtr);
-
- base1 = fut_get_ptr_s_lock(0, base_addr1, &mtr);
-
- node_addr = flst_get_first(base1, &mtr);
-
- mtr_commit(&mtr);
-
- for (i = 0; i < 500; i++) {
- mtr_start(&mtr);
- ut_a(!fil_addr_is_null(node_addr));
-
- node = fut_get_ptr_x_lock(0, node_addr, &mtr);
-
- node_addr = flst_get_next_addr(node, &mtr);
- mtr_commit(&mtr);
- }
-
- printf("Add 200 elements to the middle of list1\n");
- for (i = 0; i < 100; i++) {
- mtr_start(&mtr);
-
- node = fut_get_ptr_x_lock(0, node_addr, &mtr);
-
- node_addr2.page = i;
- node_addr2.boffset = NODE3;
- node2 = fut_get_ptr_x_lock(0, node_addr2, &mtr);
-
- node_addr3.page = i;
- node_addr3.boffset = NODE4;
- node3 = fut_get_ptr_x_lock(0, node_addr3, &mtr);
-
- mlog_write_ulint(node2 + INDEX, 99 - i, MLOG_4BYTES, &mtr);
-
- block = buf_page_get(0, BPAGE, &mtr);
- frame = buf_block_get_frame(block);
-
- base1 = frame + BASE1;
-
- flst_insert_after(base1, node, node2, &mtr);
- flst_insert_before(base1, node3, node, &mtr);
-
- if (i % 17 == 0) {
- flst_validate(base1, &mtr);
- }
- mtr_commit(&mtr);
- }
-
- printf("Check that 100 of the inserted nodes are in order\n");
- mtr_start(&mtr);
- ut_a(!fil_addr_is_null(node_addr));
-
- node = fut_get_ptr_x_lock(0, node_addr, &mtr);
-
- node_addr = flst_get_next_addr(node, &mtr);
- mtr_commit(&mtr);
-
- for (i = 0; i < 100; i++) {
- mtr_start(&mtr);
- ut_a(!fil_addr_is_null(node_addr));
-
- node = fut_get_ptr_x_lock(0, node_addr, &mtr);
-
- ut_a(mtr_read_ulint(node + INDEX, MLOG_4BYTES, &mtr)
- == i);
-
- node_addr = flst_get_next_addr(node, &mtr);
- mtr_commit(&mtr);
- }
-
- printf("Remove 899 elements from the middle of list1\n");
- mtr_start(&mtr);
-
- base1 = fut_get_ptr_x_lock(0, base_addr1, &mtr);
-
- node_addr = flst_get_first(base1, &mtr);
-
- flst_print(base1, &mtr);
- mtr_commit(&mtr);
-
- for (i = 0; i < 300; i++) {
- mtr_start(&mtr);
- ut_a(!fil_addr_is_null(node_addr));
-
- node = fut_get_ptr_x_lock(0, node_addr, &mtr);
-
- node_addr = flst_get_next_addr(node, &mtr);
- mtr_commit(&mtr);
- }
-
- for (i = 0; i < 899; i++) {
-
- mtr_start(&mtr);
-
- base1 = fut_get_ptr_x_lock(0, base_addr1, &mtr);
-
- node_addr = flst_get_first(base1, &mtr);
-
- node = fut_get_ptr_x_lock(0, node_addr, &mtr);
-
- node_addr = flst_get_next_addr(node, &mtr);
-
- ut_a(!fil_addr_is_null(node_addr));
-
- node2 = fut_get_ptr_x_lock(0, node_addr, &mtr);
-
- flst_remove(base1, node2, &mtr);
-
- if (i % 17 == 0) {
- flst_validate(base1, &mtr);
- }
-
- mtr_commit(&mtr);
- }
-
- printf("Remove 301 elements from the start of list1\n");
- for (i = 0; i < 301; i++) {
-
- mtr_start(&mtr);
-
- base1 = fut_get_ptr_x_lock(0, base_addr1, &mtr);
-
- node_addr = flst_get_first(base1, &mtr);
-
- node = fut_get_ptr_x_lock(0, node_addr, &mtr);
-
- flst_remove(base1, node, &mtr);
-
- if (i % 17 == 0) {
- flst_validate(base1, &mtr);
- }
-
- mtr_commit(&mtr);
- }
-
- mtr_start(&mtr);
-
- base1 = fut_get_ptr_x_lock(0, base_addr1, &mtr);
-
- ut_a(flst_get_len(base1, &mtr) == 0);
- flst_print(base1, &mtr);
-
- mtr_commit(&mtr);
-}
-
-/************************************************************************
-Inits space header of space 0. */
-
-void
-init_space(void)
-/*============*/
-{
- mtr_t mtr;
-
- printf("Init space header\n");
-
- mtr_start(&mtr);
-
- fsp_header_init(0, FILE_SIZE * N_FILES, &mtr);
-
- mtr_commit(&mtr);
-}
-
-/************************************************************************
-Test for file space management. */
-
-void
-test5(void)
-/*=======*/
-{
- mtr_t mtr;
- ulint seg_page;
- ulint new_page;
- ulint seg_page2;
- ulint new_page2;
- ulint seg_page3;
- buf_block_t* block;
- bool finished;
- ulint i;
- ulint reserved;
- ulint used;
- ulint tm, oldtm;
-
- buf_validate();
-
- fsp_validate(0);
- fsp_print(0);
-
- mtr_start(&mtr);
-
- seg_page = fseg_create(0, 0, 1000, &mtr);
-
- mtr_commit(&mtr);
-
- fsp_validate(0);
-
- buf_validate();
- printf("Segment created: header page %lu, byte offset %lu\n",
- seg_page, 1000);
- fsp_print(0);
-
- mtr_start(&mtr);
-
- block = buf_page_get(0, seg_page, &mtr);
-
- new_page = fseg_alloc_free_page(buf_block_get_frame(block) + 1000,
- 2, FSP_UP, &mtr);
-
- mtr_commit(&mtr);
-
- fsp_print(0);
- fsp_validate(0);
- buf_validate();
- printf("Segment page allocated %lu\n", new_page);
-
-
- mtr_start(&mtr);
-
- block = buf_page_get(0, seg_page, &mtr);
-
- fseg_free_page(buf_block_get_frame(block) + 1000,
- 0, new_page, &mtr);
-
- mtr_commit(&mtr);
-
- fsp_validate(0);
- printf("Segment page freed %lu\n", new_page);
-
- finished = FALSE;
-
- while (!finished) {
-
- mtr_start(&mtr);
-
- block = buf_page_get(0, seg_page, &mtr);
-
- finished = fseg_free_step(
- buf_block_get_frame(block) + 1000, &mtr);
-
- mtr_commit(&mtr);
- }
- fsp_validate(0);
-
- /***********************************************/
- buf_validate();
- mtr_start(&mtr);
-
- seg_page = fseg_create(0, 0, 1000, &mtr);
-
- mtr_commit(&mtr);
-
- ut_a(seg_page == 2);
-
- printf("Segment created: header page %lu\n", seg_page);
-
- new_page = seg_page;
- for (i = 0; i < 511; i++) {
-
- mtr_start(&mtr);
-
- block = buf_page_get(0, seg_page, &mtr);
-
- new_page = fseg_alloc_free_page(
- buf_block_get_frame(block) + 1000,
- new_page + 1, FSP_UP, &mtr);
- printf("%lu %lu; ", i, new_page);
- if (i % 10 == 0) {
- printf("\n");
- }
-
- mtr_commit(&mtr);
-
- if (i % 117 == 0) {
- fsp_validate(0);
- }
- }
-
- fsp_validate(0);
- buf_validate();
-
- mtr_start(&mtr);
-
- block = buf_page_get(0, seg_page, &mtr);
-
- reserved = fseg_n_reserved_pages(buf_block_get_frame(block) + 1000,
- &used, &mtr);
-
- ut_a(used == 512);
- ut_a(reserved >= 512);
-
- printf("Pages used in segment %lu reserved by segment %lu \n",
- used, reserved);
-
- mtr_commit(&mtr);
-
- finished = FALSE;
-
- while (!finished) {
- i++;
-
- mtr_start(&mtr);
-
- block = buf_page_get(0, seg_page, &mtr);
-
- finished = fseg_free_step(
- buf_block_get_frame(block) + 1000, &mtr);
-
- mtr_commit(&mtr);
-
- if (i % 117 == 0) {
- fsp_validate(0);
- }
- }
-
- fsp_validate(0);
- buf_validate();
-
- /***********************************************/
-
- mtr_start(&mtr);
-
- seg_page = fseg_create(0, 0, 1000, &mtr);
-
- mtr_commit(&mtr);
-
- ut_a(seg_page == 2);
-
- mtr_start(&mtr);
-
- seg_page2 = fseg_create(0, 0, 1000, &mtr);
-
- mtr_commit(&mtr);
-
- ut_a(seg_page2 == 3);
-
- new_page = seg_page;
- new_page2 = seg_page2;
-
- for (;;) {
-
- mtr_start(&mtr);
-
- block = buf_page_get(0, seg_page, &mtr);
-
- new_page = fseg_alloc_free_page(
- buf_block_get_frame(block) + 1000,
- new_page + 1, FSP_UP, &mtr);
-
- printf("1:%lu %lu; ", i, new_page);
- if (i % 10 == 0) {
- printf("\n");
- }
-
- new_page = fseg_alloc_free_page(
- buf_block_get_frame(block) + 1000,
- new_page + 1, FSP_UP, &mtr);
-
- printf("1:%lu %lu; ", i, new_page);
- if (i % 10 == 0) {
- printf("\n");
- }
-
- mtr_commit(&mtr);
-
- i++;
- if (i % 217 == 0) {
- fsp_validate(0);
- }
-
- mtr_start(&mtr);
-
- block = buf_page_get(0, seg_page2, &mtr);
-
- new_page2 = fseg_alloc_free_page(
- buf_block_get_frame(block) + 1000,
- new_page2 + 1, FSP_DOWN, &mtr);
-
- printf("2:%lu %lu; ", i, new_page2);
- if (i % 10 == 0) {
- printf("\n");
- }
-
- mtr_commit(&mtr);
-
- if (new_page2 == FIL_NULL) {
- break;
- }
- }
-
- mtr_start(&mtr);
-
- block = buf_page_get(0, seg_page, &mtr);
-
- reserved = fseg_n_reserved_pages(buf_block_get_frame(block) + 1000,
- &used, &mtr);
-
- printf("Pages used in segment 1 %lu, reserved by segment %lu \n",
- used, reserved);
-
- mtr_commit(&mtr);
- fsp_validate(0);
-
- mtr_start(&mtr);
-
- block = buf_page_get(0, seg_page2, &mtr);
-
- reserved = fseg_n_reserved_pages(buf_block_get_frame(block) + 1000,
- &used, &mtr);
-
- printf("Pages used in segment 2 %lu, reserved by segment %lu \n",
- used, reserved);
-
- mtr_commit(&mtr);
-
- fsp_print(0);
-
- for (;;) {
-
- i++;
- mtr_start(&mtr);
-
- block = buf_page_get(0, seg_page, &mtr);
-
- fseg_free_step(
- buf_block_get_frame(block) + 1000, &mtr);
-
- block = buf_page_get(0, seg_page2, &mtr);
-
- finished = fseg_free_step(
- buf_block_get_frame(block) + 1000, &mtr);
-
- mtr_commit(&mtr);
-
- if (finished) {
- break;
- }
-
- if (i % 117 == 0) {
- fsp_validate(0);
- }
- }
-
- fsp_validate(0);
-
- mtr_start(&mtr);
-
- seg_page3 = fseg_create(0, 0, 1000, &mtr);
- page_nos[0] = seg_page3;
- new_page2 = seg_page3;
-
- mtr_commit(&mtr);
-
- for (i = 1; i < 250; i++) {
- mtr_start(&mtr);
-
- block = buf_page_get(0, seg_page3, &mtr);
-
- new_page2 = fseg_alloc_free_page(
- buf_block_get_frame(block) + 1000,
- new_page2 + 1, FSP_UP, &mtr);
- page_nos[i] = new_page2;
-
- mtr_commit(&mtr);
- }
-
- /*************************************************/
-
- mtr_start(&mtr);
-
- fseg_create(0, seg_page3, 1500, &mtr);
-
- mtr_commit(&mtr);
-
- for (i = 0; i < 250; i++) {
- mtr_start(&mtr);
-
- block = buf_page_get(0, seg_page3, &mtr);
-
- new_page2 = fseg_alloc_free_page(
- buf_block_get_frame(block) + 1500,
- new_page2 + 1, FSP_UP, &mtr);
- page_nos[i] = new_page2;
-
- mtr_commit(&mtr);
- }
-
- printf("---------------------------------------------------------\n");
- printf("TEST 5A13. Test free_step.\n");
-
- fseg_free(0, seg_page3, 1500);
-
- printf("---------------------------------------------------------\n");
- printf("TEST 5A3. Test free_step.\n");
-
- for (;;) {
-
- mtr_start(&mtr);
-
- block = buf_page_get(0, seg_page3, &mtr);
-
- finished = fseg_free_step(
- buf_block_get_frame(block) + 1000, &mtr);
-
- mtr_commit(&mtr);
-
- if (finished) {
- break;
- }
- }
-
- /***************************************************/
-
- mtr_start(&mtr);
-
- seg_page2 = fseg_create(0, 0, 1000, &mtr);
- page_nos[0] = seg_page2;
- new_page2 = seg_page2;
-
- mtr_commit(&mtr);
-
- i = 1;
- for (;;) {
- mtr_start(&mtr);
-
- block = buf_page_get(0, seg_page2, &mtr);
-
- new_page2 = fseg_alloc_free_page(
- buf_block_get_frame(block) + 1000,
- new_page2 + 1, FSP_UP, &mtr);
- page_nos[i] = new_page2;
-/*
- printf("%lu %lu; ", i, new_page2);
-*/
- mtr_commit(&mtr);
-
- if (new_page2 == FIL_NULL) {
- break;
- }
- i++;
- }
-
- printf("---------------------------------------------------------\n");
- printf("TEST 5D. Test free_step.\n");
-
- for (;;) {
-
- mtr_start(&mtr);
-
- block = buf_page_get(0, seg_page, &mtr);
-
- finished = fseg_free_step(
- buf_block_get_frame(block) + 1000, &mtr);
-
- mtr_commit(&mtr);
-
- if (finished) {
- break;
- }
- }
-
- for (;;) {
-
- mtr_start(&mtr);
-
- block = buf_page_get(0, seg_page2, &mtr);
-
- finished = fseg_free_step(
- buf_block_get_frame(block) + 1000, &mtr);
-
- mtr_commit(&mtr);
-
- if (finished) {
- break;
- }
- }
-
-
- /***************************************/
-
- oldtm = ut_clock();
-
- fsp_validate(0);
-
- for (i = 0; i < 10; i++) {
- mtr_start(&mtr);
-
- seg_page = fseg_create(0, 0, 1000, &mtr);
-
- mtr_commit(&mtr);
-
- mtr_start(&mtr);
-
- block = buf_page_get(0, seg_page, &mtr);
-
- new_page = fseg_alloc_free_page(buf_block_get_frame(block) + 1000,
- 3, FSP_UP, &mtr);
-
- mtr_commit(&mtr);
-
- finished = FALSE;
-
- while (!finished) {
-
- mtr_start(&mtr);
-
- block = buf_page_get(0, seg_page, &mtr);
-
- finished = fseg_free_step(
- buf_block_get_frame(block) + 1000, &mtr);
-
- mtr_commit(&mtr);
- }
- }
-
- tm = ut_clock();
- printf("Wall clock time for %lu seg crea+free %lu millisecs\n",
- i, tm - oldtm);
-
- buf_validate();
- fsp_validate(0);
- fsp_print(0);
-
- buf_flush_batch(BUF_FLUSH_LIST, 2000);
- os_thread_sleep(3000000);
-
-/* buf_print(); */
- buf_all_freed();
-}
-
-/************************************************************************
-Random test thread function. */
-
-ulint
-random_thread(
-/*===========*/
- void* arg)
-{
- ulint n;
- ulint i, j, t, p, sp, d, b;
- ulint s;
- ulint arr[FILE_SIZE * N_FILES];
- ulint seg_page;
- fseg_header_t* seg_header;
- fil_addr_t seg_addr;
- byte dir;
- ulint k;
- mtr_t mtr;
- bool finished;
- ulint used;
- ulint reserved;
-
- n = *((ulint*)arg);
- n = os_thread_get_curr_id();
-
- printf("Random test thread %lu starts\n", n);
-
- for (i = 0; i < 30; i++) {
- t = ut_rnd_gen_ulint() % 10;
- s = ut_rnd_gen_ulint() % FILE_SIZE * N_FILES;
- p = 0;
- sp = ut_rnd_gen_ulint() % N_SPACES;
- d = ut_rnd_gen_ulint() % 3;
- b = ut_rnd_gen_ulint() % 3;
-
- if (i % 10 == 0) {
- printf("Thr %lu round %lu starts\n", n, i);
- }
- ut_a(buf_validate());
-
- if (t != 0) {
- do {
- mtr_start(&mtr);
- seg_page = fseg_create(sp, p, 1000, &mtr);
- mtr_commit(&mtr);
- } while (seg_page == FIL_NULL);
-
- seg_addr.page = seg_page;
- seg_addr.boffset = 1000;
-
- k = 0;
- j = 0;
- while (j < s) {
- j++;
- if (d == 0) {
- dir = FSP_DOWN;
- } else if (d == 1) {
- dir = FSP_NO_DIR;
- } else {
- dir = FSP_UP;
- }
- mtr_start(&mtr);
- seg_header = fut_get_ptr(sp, seg_addr, &mtr);
-
- if (b != 0) {
- arr[k] = fseg_alloc_free_page(seg_header,
- p, dir, &mtr);
- k++;
- } else if (k > 0) {
- fseg_free_page(seg_header, sp, arr[k - 1],
- &mtr);
- k--;
- }
-
- mtr_commit(&mtr);
- if ((k > 0) && (arr[k - 1] == FIL_NULL)) {
- k--;
- break;
- }
- if (p > 0) {
- p = arr[k - 1] + dir - 1;
- }
- if (j % 577 == 0) {
- if (k > 0) {
- p = arr[k / 2] + 1;
- } else {
- p = 0;
- }
- d = ut_rnd_gen_ulint() % 3;
- b = ut_rnd_gen_ulint() % 3;
- }
- }
- finished = FALSE;
- mtr_start(&mtr);
-
- seg_header = fut_get_ptr(sp, seg_addr, &mtr);
-
- reserved = fseg_n_reserved_pages(seg_header,
- &used, &mtr);
-
- printf("Pages used in segment %lu reserved by segment %lu \n",
- used, reserved);
-
- mtr_commit(&mtr);
-
- printf("Thread %lu starts releasing seg %lu size %lu\n", n,
- seg_addr.page, k);
- while (!finished) {
- mtr_start(&mtr);
- seg_header = fut_get_ptr(sp, seg_addr, &mtr);
-
- finished = fseg_free_step(seg_header, &mtr);
- mtr_commit(&mtr);
- }
- } else {
- fsp_print(sp);
- printf("Thread %lu validates fsp\n", n);
- fsp_validate(sp);
- buf_validate();
- }
- } /* for i */
- printf("\nRandom test thread %lu exits\n", os_thread_get_curr_id());
- return(0);
-}
-
-/*************************************************************************
-Performs random operations on the buffer with several threads. */
-
-void
-test6(void)
-/*=======*/
-{
- ulint i;
- os_thread_t thr[N_THREADS + 1];
- os_thread_id_t id[N_THREADS + 1];
- ulint n[N_THREADS + 1];
-
- printf("--------------------------------------------------------\n");
- printf("TEST 6. Random multi-thread test on the buffer \n");
-
- incs = 0;
- mutex_create(&incs_mutex);
-
- for (i = 0; i < N_THREADS; i++) {
- n[i] = i;
-
- thr[i] = os_thread_create(random_thread, n + i, id + i);
- }
-
- for (i = 0; i < N_THREADS; i++) {
- os_thread_wait(thr[i]);
- }
-}
-
-/************************************************************************
-Main test function. */
-
-void
-main(void)
-/*======*/
-{
- ulint tm, oldtm;
-
- oldtm = ut_clock();
-
- os_aio_init(160, 5);
- sync_init();
- mem_init();
- fil_init(26); /* Allow 25 open files at a time */
- buf_pool_init(POOL_SIZE, POOL_SIZE);
- log_init();
- fsp_init();
-
- buf_validate();
-
- ut_a(fil_validate());
-
- create_files();
-
- create_db();
-
- buf_validate();
-
-/* test1(); */
-/* buf_validate(); */
-/*
- test2();
- buf_validate();
-*/
- init_space();
-
- test5();
- buf_validate();
-
-/* test6(); */
-
- buf_flush_batch(BUF_FLUSH_LIST, POOL_SIZE + 1);
-/* buf_print(); */
- buf_validate();
-
- os_thread_sleep(1000000);
-
-/* buf_print(); */
- buf_all_freed();
-
- tm = ut_clock();
- printf("Wall clock time for test %lu milliseconds\n", tm - oldtm);
- printf("TESTS COMPLETED SUCCESSFULLY!\n");
-}