summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--innobase/fsp/trash/FSP0FSP.C3100
-rw-r--r--innobase/include/usr0sess.h43
-rw-r--r--innobase/lock/lock0lock.c5
-rw-r--r--innobase/log/trash/log0trsh.c648
-rw-r--r--innobase/os/os0fileold.c1956
-rw-r--r--innobase/srv/srv0srv.c677
-rw-r--r--innobase/trx/trx0trx.c5
-rw-r--r--innobase/usr/usr0sess.c604
8 files changed, 8 insertions, 7030 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/include/usr0sess.h b/innobase/include/usr0sess.h
index 365f828ecfc..e277d801672 100644
--- a/innobase/include/usr0sess.h
+++ b/innobase/include/usr0sess.h
@@ -66,28 +66,6 @@ sess_open(
byte* addr_buf, /* in: client address */
ulint addr_len); /* in: client address length */
/*************************************************************************
-Closes a session, freeing the memory occupied by it. */
-
-void
-sess_close(
-/*=======*/
- sess_t* sess); /* in, own: session object */
-/*************************************************************************
-Raises an SQL error. */
-
-void
-sess_raise_error_low(
-/*=================*/
- trx_t* trx, /* in: transaction */
- ulint err_no, /* in: error number */
- ulint type, /* in: more info of the error, or 0 */
- dict_table_t* table, /* in: dictionary table or NULL */
- dict_index_t* index, /* in: table index or NULL */
- dtuple_t* tuple, /* in: tuple to insert or NULL */
- rec_t* rec, /* in: record or NULL */
- char* err_str);/* in: arbitrary null-terminated error string,
- or NULL */
-/*************************************************************************
Closes a session, freeing the memory occupied by it, if it is in a state
where it should be closed. */
@@ -117,16 +95,6 @@ sess_srv_msg_send_simple(
ulint rel_kernel); /* in: SESS_RELEASE_KERNEL or
SESS_NOT_RELEASE_KERNEL */
/***************************************************************************
-Processes a message from a client. NOTE: May release the kernel mutex
-temporarily. */
-
-void
-sess_receive_msg_rel_kernel(
-/*========================*/
- sess_t* sess, /* in: session */
- byte* str, /* in: message string */
- ulint len); /* in: message length */
-/***************************************************************************
When a command has been completed, this function sends the message about it
to the client. */
@@ -136,17 +104,6 @@ sess_command_completed_message(
sess_t* sess, /* in: session */
byte* msg, /* in: message buffer */
ulint len); /* in: message data length */
-/***********************************************************************
-Starts a new connection and a session, or starts a query based on a client
-message. This is called by a SRV_COM thread. */
-
-void
-sess_process_cli_msg(
-/*=================*/
- byte* str, /* in: message string */
- ulint len, /* in: string length */
- byte* addr, /* in: address string */
- ulint alen); /* in: address length */
/* The session handle. All fields are protected by the kernel mutex */
diff --git a/innobase/lock/lock0lock.c b/innobase/lock/lock0lock.c
index 4b39368c540..df5f45e3452 100644
--- a/innobase/lock/lock0lock.c
+++ b/innobase/lock/lock0lock.c
@@ -3063,11 +3063,6 @@ retry:
ut_a(strlen(lock_latest_err_buf) < 4100);
- /*
- sess_raise_error_low(trx, DB_DEADLOCK, lock->type_mode, table,
- index, NULL, NULL, NULL);
- */
-
return(TRUE);
}
diff --git a/innobase/log/trash/log0trsh.c b/innobase/log/trash/log0trsh.c
deleted file mode 100644
index 7f48118a0d1..00000000000
--- a/innobase/log/trash/log0trsh.c
+++ /dev/null
@@ -1,648 +0,0 @@
-/******************************************************
-Recovery
-
-(c) 1997 Innobase Oy
-
-Created 9/20/1997 Heikki Tuuri
-*******************************************************/
-
-#include "log0recv.h"
-
-#ifdef UNIV_NONINL
-#include "log0recv.ic"
-#endif
-
-#include "mem0mem.h"
-#include "buf0buf.h"
-#include "buf0flu.h"
-#include "srv0srv.h"
-
-/* Size of block reads when the log groups are scanned forward to do
-roll-forward */
-#define RECV_SCAN_SIZE (4 * UNIV_PAGE_SIZE)
-
-/* Size of block reads when the log groups are scanned backwards to synchronize
-them */
-#define RECV_BACK_SCAN_SIZE (4 * UNIV_PAGE_SIZE)
-
-recv_sys_t* recv_sys = NULL;
-
-recv_recover_page(block->frame, block->space, block->offset);
-
-/************************************************************
-Creates the recovery system. */
-
-void
-recv_sys_create(void)
-/*=================*/
-{
- ut_a(recv_sys == NULL);
-
- recv_sys = mem_alloc(sizeof(recv_t));
-
- mutex_create(&(recv_sys->mutex));
-
- recv_sys->hash = NULL;
- recv_sys->heap = NULL;
-}
-
-/************************************************************
-Inits the recovery system for a recovery operation. */
-
-void
-recv_sys_init(void)
-/*===============*/
-{
- recv_sys->hash = hash_create(buf_pool_get_curr_size() / 64);
- recv_sys->heap = mem_heap_create_in_buffer(256);
-}
-
-/************************************************************
-Empties the recovery system. */
-
-void
-recv_sys_empty(void)
-/*================*/
-{
- mutex_enter(&(recv_sys->mutex));
-
- hash_free(recv_sys->hash);
- mem_heap_free(recv_sys->heap);
-
- recv_sys->hash = NULL;
- recv_sys->heap = NULL;
-
- mutex_exit(&(recv_sys->mutex));
-}
-
-/***********************************************************
-For recovery purposes copies the log buffer to a group to synchronize log
-data. */
-static
-void
-recv_log_buf_flush(
-/*===============*/
- log_group_t* group, /* in: log group */
- dulint start_lsn, /* in: start lsn of the log data in
- the log buffer; must be divisible by
- OS_FILE_LOG_BLOCK_SIZE */
- dulint end_lsn) /* in: end lsn of the log data in the
- log buffer; must be divisible by
- OS_FILE_LOG_BLOCK_SIZE */
-{
- ulint len;
-
- ut_ad(mutex_own(&(log_sys->mutex)));
-
- len = ut_dulint_minus(end_lsn, start_lsn);
-
- log_group_write_buf(LOG_RECOVER, group, log_sys->buf, len, start_lsn,
- 0);
-}
-
-/***********************************************************
-Compares two buffers containing log segments and determines the highest lsn
-where they match, if any. */
-static
-dulint
-recv_log_bufs_cmp(
-/*==============*/
- /* out: if no match found, ut_dulint_zero or
- if start_lsn == LOG_START_LSN, returns
- LOG_START_LSN; otherwise the highest matching
- lsn */
- byte* recv_buf, /* in: buffer containing valid log data */
- byte* buf, /* in: buffer of data from a possibly
- incompletely written log group */
- dulint start_lsn, /* in: buffer start lsn, must be divisible
- by OS_FILE_LOG_BLOCK_SIZE and must be >=
- LOG_START_LSN */
- dulint end_lsn, /* in: buffer end lsn, must be divisible
- by OS_FILE_LOG_BLOCK_SIZE */
- dulint recovered_lsn) /* in: recovery succeeded up to this lsn */
-{
- ulint len;
- ulint offset;
- byte* log_block1;
- byte* log_block2;
- ulint no;
- ulint data_len;
-
- ut_ad(ut_dulint_cmp(start_lsn, LOG_START_LSN) >= 0);
-
- if (ut_dulint_cmp(end_lsn, recovered_lsn) > 0) {
- end_lsn = ut_dulint_align_up(recovered_lsn,
- OS_FILE_LOG_BLOCK_SIZE);
- }
-
- len = ut_dulint_minus(end_lsn, start_lsn);
-
- if (len == 0) {
-
- goto no_match;
- }
-
- ut_ad(len % OS_FILE_LOG_BLOCK_SIZE == 0);
-
- log_block1 = recv_buf + len;
- log_block2 = buf + len;
-
- for (;;) {
- log_block1 -= OS_FILE_LOG_BLOCK_SIZE;
- log_block2 -= OS_FILE_LOG_BLOCK_SIZE;
-
- no = log_block_get_hdr_no(log_block1);
- ut_a(no == log_block_get_trl_no(log_block1));
-
- if ((no == log_block_get_hdr_no(log_block2))
- && (no == log_block_get_trl_no(log_block2))) {
-
- /* Match found if the block is not corrupted */
-
- data_len = log_block_get_data_len(log_block2);
-
- if (0 == ut_memcmp(log_block1 + LOG_BLOCK_DATA,
- log_block2 + LOG_BLOCK_DATA,
- data_len - LOG_BLOCK_DATA)) {
-
- /* Match found */
-
- return(ut_dulint_add(start_lsn,
- log_block2 - buf + data_len));
- }
- }
-
- if (log_block1 == recv_buf) {
-
- /* No match found */
-
- break;
- }
- }
-no_match:
- if (ut_dulint_cmp(start_lsn, LOG_START_LSN) == 0) {
-
- return(LOG_START_LSN);
- }
-
- return(ut_dulint_zero);
-}
-
-/************************************************************
-Copies a log segment from the most up-to-date log group to the other log
-group, so that it contains the latest log data. */
-static
-void
-recv_copy_group(
-/*============*/
- log_group_t* up_to_date_group, /* in: the most up-to-date
- log group */
- log_group_t* group, /* in: copy to this log group */
- dulint_lsn recovered_lsn) /* in: recovery succeeded up
- to this lsn */
-{
- dulint start_lsn;
- dulint end_lsn;
- dulint match;
- byte* buf;
- byte* buf1;
-
- ut_ad(mutex_own(&(log_sys->mutex)));
-
- if (0 == ut_dulint_cmp(LOG_START_LSN, recovered_lsn)) {
-
- return;
- }
-
- ut_ad(RECV_BACK_SCAN_SIZE <= log_sys->buf_size);
-
- buf1 = mem_alloc(2 * RECV_BACK_SCAN_SIZE);
- buf = ut_align(buf, RECV_BACK_SCAN_SIZE););
-
- end_lsn = ut_dulint_align_up(recovered_lsn, RECV_BACK_SCAN_SIZE);
-
- match = ut_dulint_zero;
-
- for (;;) {
- if (ut_dulint_cmp(ut_dulint_add(LOG_START_LSN,
- RECV_BACK_SCAN_SIZE), end_lsn) >= 0) {
- start_lsn = LOG_START_LSN;
- } else {
- start_lsn = ut_dulint_subtract(end_lsn,
- RECV_BACK_SCAN_SIZE);
- }
-
- log_group_read_log_seg(LOG_RECOVER, buf, group, start_lsn,
- end_lsn);
- log_group_read_log_seg(LOG_RECOVER, log_sys->buf,
- up_to_date_group, start_lsn, end_lsn);
-
- match = recv_log_bufs_cmp(log_sys->buf, buf, start_lsn,
- end_lsn, recovered_lsn);
-
- if (ut_dulint_cmp(match, recovered_lsn) != 0) {
- recv_log_buf_flush(group, start_lsn, end_lsn);
- }
-
- if (!ut_dulint_zero(match)) {
-
- mem_free(buf1);
-
- return;
- }
-
- end_lsn = start_lsn;
- }
-}
-
-/************************************************************
-Copies a log segment from the most up-to-date log group to the other log
-groups, so that they all contain the latest log data. Also writes the info
-about the latest checkpoint to the groups, and inits the fields in the group
-memory structs to up-to-date values. */
-
-void
-recv_synchronize_groups(
-/*====================*/
- log_group_t* up_to_date_group, /* in: the most up-to-date
- log group */
- dulint_lsn recovered_lsn, /* in: recovery succeeded up
- to this lsn */
- log_group_t* max_checkpoint_group) /* in: the group with the most
- recent checkpoint info */
-{
- log_group_t* group;
-
- ut_ad(mutex_own(&(log_sys->mutex)));
-
- group = UT_LIST_GET_FIRST(log_sys->log_groups);
-
- while (group) {
- if (group != up_to_date_group) {
-
- /* Copy log data */
-
- recv_copy_group(group, up_to_date_group,
- recovered_lsn);
- }
-
- if (group != max_checkpoint_group) {
-
- /* Copy the checkpoint info to the group */
-
- log_group_checkpoint(group);
-
- mutex_exit(&(log_sys->mutex));
-
- /* Wait for the checkpoint write to complete */
- rw_lock_s_lock(&(log_sys->checkpoint_lock));
- rw_lock_s_unlock(&(log_sys->checkpoint_lock));
-
- mutex_enter(&(log_sys->mutex));
- }
-
- /* Update the fields in the group struct to correspond to
- recovered_lsn */
-
- log_group_set_fields(group, recovered_lsn);
-
- group = UT_LIST_GET_NEXT(log_groups, group);
- }
-}
-
-/************************************************************
-Looks for the maximum consistent checkpoint from the log groups. */
-static
-ulint
-recv_find_max_checkpoint(
-/*=====================*/
- /* out: error code or DB_SUCCESS */
- log_group_t** max_group, /* out: max group */
- ulint* max_field) /* out: LOG_CHECKPOINT_1 or
- LOG_CHECKPOINT_2 */
-{
- log_group_t* group;
- dulint max_no;
- dulint cp_no;
- ulint field;
- ulint fold;
- byte* buf;
-
- ut_ad(mutex_own(&(log_sys->mutex)));
-
- /* Look for the latest checkpoint from the log groups */
- group = UT_LIST_GET_FIRST(log_sys->log_groups);
-
- checkpoint_no = ut_dulint_zero;
- checkpoint_lsn = ut_dulint_zero;
- *max_group = NULL;
-
- buf = log_sys->checkpoint_buf;
-
- while (group) {
- group->state = LOG_GROUP_CORRUPTED;
-
- for (field = LOG_CHECKPOINT_1; field <= LOG_CHECKPOINT_2;
- field += LOG_CHECKPOINT_2 - LOG_CHECKPOINT_1) {
-
- log_group_read_checkpoint_info(group, field);
-
- /* Check the consistency of the checkpoint info */
- fold = ut_fold_binary(buf, LOG_CHECKPOINT_CHECKSUM_1);
-
- if (fold != mach_read_from_4(buf
- + LOG_CHECKPOINT_CHECKSUM_1)) {
- goto not_consistent;
- }
-
- fold = ut_fold_binary(buf + LOG_CHECKPOINT_LSN,
- LOG_CHECKPOINT_CHECKSUM_2
- - LOG_CHECKPOINT_LSN);
- if (fold != mach_read_from_4(buf
- + LOG_CHECKPOINT_CHECKSUM_2)) {
- goto not_consistent;
- }
-
- group->state = LOG_GROUP_OK;
-
- group->lsn = mach_read_from_8(buf
- + LOG_CHECKPOINT_LSN);
- group->lsn_offset = mach_read_from_4(buf
- + LOG_CHECKPOINT_OFFSET);
- group->lsn_file_count = mach_read_from_4(
- buf + LOG_CHECKPOINT_FILE_COUNT);
-
- cp_no = mach_read_from_8(buf + LOG_CHECKPOINT_NO);
-
- if (ut_dulint_cmp(cp_no, max_no) >= 0) {
- *max_group = group;
- *max_field = field;
- max_no = cp_no;
- }
-
- not_consistent:
- }
-
- group = UT_LIST_GET_NEXT(log_groups, group);
- }
-
- if (*max_group == NULL) {
-
- return(DB_ERROR);
- }
-
- return(DB_SUCCESS);
-}
-
-/***********************************************************
-Parses log records from a buffer and stores them to a hash table to wait
-merging to file pages. If the hash table becomes too big, merges automatically
-it to file pages. */
-static
-bool
-recv_parse_and_hash_log_recs(
-/*=========================*/
- /* out: TRUE if limit_lsn has been reached */
- byte* buf, /* in: buffer containing a log segment or
- garbage */
- ulint len, /* in: buffer length */
- dulint start_lsn, /* in: buffer start lsn */
- dulint limit_lsn, /* in: recover at least to this lsn */
- dulint* recovered_lsn) /* out: was able to parse up to this lsn */
-{
-
-}
-
-/************************************************************
-Recovers from a checkpoint. When this function returns, the database is able
-to start processing new user transactions, but the function
-recv_recovery_from_checkpoint_finish should be called later to complete
-the recovery and free the resources used in it. */
-
-ulint
-recv_recovery_from_checkpoint_start(
-/*================================*/
- /* out: error code or DB_SUCCESS */
- dulint limit_lsn) /* in: recover up to this lsn if possible */
-{
- log_group_t* max_cp_group;
- log_group_t* up_to_date_group;
- ulint max_cp_field;
- byte* buf;
- ulint err;
- dulint checkpoint_lsn;
- dulint checkpoint_no;
- dulint recovered_lsn;
- dulint old_lsn;
- dulint end_lsn;
- dulint start_lsn;
- bool finished;
- dulint flush_start_lsn;
-
- mutex_enter(&(log_sys->mutex));
-
- /* Look for the latest checkpoint from any of the log groups */
-
- err = recv_find_max_checkpoint(&max_cp_group, &max_cp_field);
-
- if (err != DB_SUCCESS) {
- mutex_exit(&(log_sys->mutex));
-
- return(err);
- }
-
- log_group_read_checkpoint_info(max_cp_group, max_cp_field);
-
- buf = log_sys->checkpoint_buf;
-
- checkpoint_lsn = mach_read_from_8(buf + LOG_CHECKPOINT_LSN);
- checkpoint_no = mach_read_from_8(buf + LOG_CHECKPOINT_NO);
-
- if (ut_dulint_cmp(limit_lsn, checkpoint_lsn) < 0) {
- mutex_exit(&(log_sys->mutex));
-
- return(DB_ERROR);
- }
-
- /* Start reading the log groups from the checkpoint lsn up. The
- variable flush_start_lsn tells a lsn up to which the log is known
- to be contiguously written in all log groups. */
-
- recovered_lsn = checkpoint_lsn;
- flush_start_lsn = ut_dulint_align_down(checkpoint_lsn,
- OS_FILE_LOG_BLOCK_SIZE);
- up_to_date_group = max_cp_group;
-
- ut_ad(RECV_SCAN_SIZE <= log_sys->buf_size);
-
- group = UT_LIST_GET_FIRST(log_sys->log_groups);
-
- while (group) {
- finished = FALSE;
-
- if (group->state == LOG_GROUP_CORRUPTED) {
- finished = TRUE;
- }
-
- start_lsn = flush_start_lsn;
-
- while (!finished) {
- end_lsn = ut_dulint_add(start_lsn, RECV_SCAN_SIZE);
-
- log_group_read_log_seg(LOG_RECOVER, log_sys->buf,
- group, start_lsn, end_lsn);
- old_lsn = recovered_lsn;
-
- finished = recv_parse_and_hash_log_recs(log_sys->buf,
- RECV_SCAN_SIZE, start_lsn,
- limit_lsn, &flush_start_lsn,
- &recovered_lsn);
-
- if (ut_dulint_cmp(recovered_lsn, old_lsn) > 0) {
-
- /* We found a more up-to-date group */
- up_to_date_group = group;
- }
-
- start_lsn = end_lsn;
- }
-
- group = UT_LIST_GET_NEXT(log_groups, group);
- }
-
- /* Delete possible corrupted or extra log records from all log
- groups */
-
- recv_truncate_groups(recovered_lsn);
-
- /* Synchronize the uncorrupted log groups to the most up-to-date log
- group; we may also have to copy checkpoint info to groups */
-
- log_sys->next_checkpoint_lsn = checkpoint_lsn;
- log_sys->next_checkpoint_no = checkpoint_no;
-
- recv_synchronize_groups(up_to_date_group, _lsn, max_cp_group);
-
- log_sys->next_checkpoint_no = ut_dulint_add(checkpoint_no, 1);
-
- /* The database is now ready to start almost normal processing of user
- transactions */
-
- return(DB_SUCCESS);
-}
-
-/************************************************************
-Completes recovery from a checkpoint. */
-
-void
-recv_recovery_from_checkpoint_finish(void)
-/*======================================*/
-{
- /* Rollback the uncommitted transactions which have no user session */
-
- trx_rollback_all_without_sess();
-
- /* Merge the hashed log records */
-
- recv_merge_hashed_log_recs();
-
- /* Free the resources of the recovery system */
-
- recv_sys_empty();
-}
-
-/****************************************************************
-Writes to the log a record about incrementing the row id counter. */
-UNIV_INLINE
-void
-log_write_row_id_incr_rec(void)
-/*===========================*/
-{
- log_t* log = log_sys;
- ulint data_len;
-
- mutex_enter(&(log->mutex));
-
- data_len = (log->buf_free % OS_FILE_LOG_BLOCK_SIZE) + 1;
-
- if (data_len >= OS_FILE_LOG_BLOCK_SIZE - LOG_BLOCK_TRL_SIZE) {
-
- /* The string does not fit within the current log block
- or the the block would become full */
-
- mutex_exit(&(log->mutex));
-
- log_write_row_id_incr_rec_slow();
-
- return;
- }
-
- *(log->buf + log->buf_free) = MLOG_INCR_ROW_ID | MLOG_SINGLE_REC_FLAG;
-
- log_block_set_data_len(ut_align_down(log->buf + log->buf_free,
- OS_FILE_LOG_BLOCK_SIZE),
- data_len);
-#ifdef UNIV_LOG_DEBUG
- log->old_buf_free = log->buf_free;
- log->old_lsn = log->lsn;
- log_check_log_recs(log->buf + log->buf_free, 1, log->lsn);
-#endif
- log->buf_free++;
-
- ut_ad(log->buf_free <= log->buf_size);
-
- UT_DULINT_INC(log->lsn);
-
- mutex_exit(&(log->mutex));
-}
-
-/****************************************************************
-Writes to the log a record about incrementing the row id counter. */
-static
-void
-log_write_row_id_incr_rec_slow(void)
-/*================================*/
-{
- byte type;
-
- log_reserve_and_open(1);
-
- type = MLOG_INCR_ROW_ID | MLOG_SINGLE_REC_FLAG;
-
- log_write_low(&type, 1);
-
- log_close();
-
- log_release();
-}
-
-/**************************************************************************
-Parses and applies a log record MLOG_SET_ROW_ID. */
-
-byte*
-dict_hdr_parse_set_row_id(
-/*======================*/
- /* out: end of log record or NULL */
- byte* ptr, /* in: buffer */
- byte* end_ptr,/* in: buffer end */
- page_t* page) /* in: page or NULL */
-{
- dulint dval;
-
- ptr = mach_dulint_parse_compressed(ptr, end_ptr, &dval);
-
- if (ptr == NULL) {
-
- return(NULL);
- }
-
- if (!page) {
-
- return(ptr);
- }
-
- mach_write_to_8(page + DICT_HDR + DICT_HDR_ROW_ID, dval);
-
- return(ptr);
-}
-
diff --git a/innobase/os/os0fileold.c b/innobase/os/os0fileold.c
deleted file mode 100644
index a9554727f0e..00000000000
--- a/innobase/os/os0fileold.c
+++ /dev/null
@@ -1,1956 +0,0 @@
-/******************************************************
-The interface to the operating system file i/o primitives
-
-(c) 1995 Innobase Oy
-
-Created 10/21/1995 Heikki Tuuri
-*******************************************************/
-
-#include "os0file.h"
-#include "os0sync.h"
-#include "ut0mem.h"
-
-#ifndef __WIN__
-#include <errno.h>
-#endif
-
-/* We use these mutexes to protect lseek + file i/o operation, if the
-OS does not provide an atomic pread or pwrite, or similar */
-#define OS_FILE_N_SEEK_MUTEXES 16
-os_mutex_t os_file_seek_mutexes[OS_FILE_N_SEEK_MUTEXES];
-
-/* In simulated aio, merge at most this many consecutive i/os */
-#define OS_AIO_MERGE_N_CONSECUTIVE 32
-
-/* If this flag is TRUE, then we will use the native aio of the
-OS (provided we compiled Innobase with it in), otherwise we will
-use simulated aio we build below with threads */
-
-bool os_aio_use_native_aio = FALSE;
-
-/* The aio array slot structure */
-typedef struct os_aio_slot_struct os_aio_slot_t;
-
-struct os_aio_slot_struct{
- bool is_read; /* TRUE if a read operation */
- ulint pos; /* index of the slot in the aio
- array */
- bool reserved; /* TRUE if this slot is reserved */
- ulint len; /* length of the block to read or
- write */
- byte* buf; /* buffer used in i/o */
- ulint type; /* OS_FILE_READ or OS_FILE_WRITE */
- ulint offset; /* 32 low bits of file offset in
- bytes */
- ulint offset_high; /* 32 high bits of file offset */
- os_file_t file; /* file where to read or write */
- char* name; /* file name or path */
- bool io_already_done;/* used only in simulated aio:
- TRUE if the physical i/o already
- made and only the slot message
- needs to be passed to the caller
- of os_aio_simulated_handle */
- void* message1; /* message which is given by the */
- void* message2; /* the requester of an aio operation
- and which can be used to identify
- which pending aio operation was
- completed */
-#ifdef WIN_ASYNC_IO
- OVERLAPPED control; /* Windows control block for the
- aio request */
-#elif defined(POSIX_ASYNC_IO)
- struct aiocb control; /* Posix control block for aio
- request */
-#endif
-};
-
-/* The aio array structure */
-typedef struct os_aio_array_struct os_aio_array_t;
-
-struct os_aio_array_struct{
- os_mutex_t mutex; /* the mutex protecting the aio array */
- os_event_t not_full; /* The event which is set to signaled
- state when there is space in the aio
- outside the ibuf segment */
- ulint n_slots; /* Total number of slots in the aio array.
- This must be divisible by n_threads. */
- ulint n_segments;/* Number of segments in the aio array of
- pending aio requests. A thread can wait
- separately for any one of the segments. */
- ulint n_reserved;/* Number of reserved slots in the
- aio array outside the ibuf segment */
- os_aio_slot_t* slots; /* Pointer to the slots in the array */
- os_event_t* events; /* Pointer to an array of event handles
- where we copied the handles from slots,
- in the same order. This can be used in
- WaitForMultipleObjects; used only in
- Windows */
-};
-
-/* Array of events used in simulated aio */
-os_event_t* os_aio_segment_wait_events = NULL;
-
-/* The aio arrays for non-ibuf i/o and ibuf i/o, as well as sync aio. These
-are NULL when the module has not yet been initialized. */
-os_aio_array_t* os_aio_read_array = NULL;
-os_aio_array_t* os_aio_write_array = NULL;
-os_aio_array_t* os_aio_ibuf_array = NULL;
-os_aio_array_t* os_aio_log_array = NULL;
-os_aio_array_t* os_aio_sync_array = NULL;
-
-ulint os_aio_n_segments = ULINT_UNDEFINED;
-
-/***************************************************************************
-Retrieves the last error number if an error occurs in a file io function.
-The number should be retrieved before any other OS calls (because they may
-overwrite the error number). If the number is not known to this program,
-the OS error number + 100 is returned. */
-
-ulint
-os_file_get_last_error(void)
-/*========================*/
- /* out: error number, or OS error number + 100 */
-{
- ulint err;
-
-#ifdef __WIN__
-
- err = (ulint) GetLastError();
-
- if (err == ERROR_FILE_NOT_FOUND) {
- return(OS_FILE_NOT_FOUND);
- } else if (err == ERROR_DISK_FULL) {
- return(OS_FILE_DISK_FULL);
- } else if (err == ERROR_FILE_EXISTS) {
- return(OS_FILE_ALREADY_EXISTS);
- } else {
- return(100 + err);
- }
-#else
- err = (ulint) errno;
-
- printf("%lu\n", err);
- perror("os0file:");
-
- if (err == ENOSPC ) {
- return(OS_FILE_DISK_FULL);
-#ifdef POSIX_ASYNC_IO
- } else if (err == EAGAIN) {
- return(OS_FILE_AIO_RESOURCES_RESERVED);
-#endif
- } else if (err == ENOENT) {
- return(OS_FILE_NOT_FOUND);
- } else if (err == EEXIST) {
- return(OS_FILE_ALREADY_EXISTS);
- } else {
- return(100 + err);
- }
-#endif
-}
-
-/********************************************************************
-Does error handling when a file operation fails. If we have run out
-of disk space, then the user can clean the disk. If we do not find
-a specified file, then the user can copy it to disk. */
-static
-bool
-os_file_handle_error(
-/*=================*/
- /* out: TRUE if we should retry the operation */
- os_file_t file, /* in: file pointer */
- char* name) /* in: name of a file or NULL */
-{
- int input_char;
- ulint err;
-
- err = os_file_get_last_error();
-
- if (err == OS_FILE_DISK_FULL) {
-ask_again:
- printf("\n");
- if (name) {
- printf(
- "Innobase encountered a problem with file %s.\n",
- name);
- }
- printf("Disk is full. Try to clean the disk to free space\n");
- printf("before answering the following: How to continue?\n");
- printf("(Y == freed some space: try again)\n");
- printf("(N == crash the database: will restart it)?\n");
-ask_with_no_question:
- input_char = getchar();
-
- if (input_char == (int) 'N') {
- ut_error;
-
- return(FALSE);
- } else if (input_char == (int) 'Y') {
-
- return(TRUE);
- } else if (input_char == (int) '\n') {
-
- goto ask_with_no_question;
- } else {
- goto ask_again;
- }
- } else if (err == OS_FILE_AIO_RESOURCES_RESERVED) {
-
- return(TRUE);
- } else {
- ut_error;
- }
-
- return(FALSE);
-}
-
-/********************************************************************
-Opens an existing file or creates a new. */
-
-os_file_t
-os_file_create(
-/*===========*/
- /* out, own: handle to the file, not defined if error,
- error number can be retrieved with os_get_last_error */
- char* name, /* in: name of the file or path as a null-terminated
- string */
- ulint create_mode, /* in: OS_FILE_OPEN if an existing file is opened
- (if does not exist, error), or OS_FILE_CREATE if a new
- file is created (if exists, error), OS_FILE_OVERWRITE
- if a new is created or an old overwritten */
- ulint purpose,/* in: OS_FILE_AIO, if asynchronous, non-buffered i/o
- is desired, OS_FILE_NORMAL, if any normal file */
- bool* success)/* out: TRUE if succeed, FALSE if error */
-{
-#ifdef __WIN__
- os_file_t file;
- DWORD create_flag;
- DWORD attributes;
- bool retry;
-
-try_again:
- ut_a(name);
-
- if (create_mode == OS_FILE_OPEN) {
- create_flag = OPEN_EXISTING;
- } else if (create_mode == OS_FILE_CREATE) {
- create_flag = CREATE_NEW;
- } else if (create_mode == OS_FILE_OVERWRITE) {
- create_flag = CREATE_ALWAYS;
- } else {
- create_flag = 0;
- ut_error;
- }
-
- if (purpose == OS_FILE_AIO) {
- /* use asynchronous (overlapped) io and no buffering
- of writes in the OS */
- attributes = 0;
-#ifdef WIN_ASYNC_IO
- if (os_aio_use_native_aio) {
- attributes = attributes | FILE_FLAG_OVERLAPPED;
- }
-#endif
-#ifdef UNIV_NON_BUFFERED_IO
- attributes = attributes | FILE_FLAG_NO_BUFFERING;
-#endif
- } else if (purpose == OS_FILE_NORMAL) {
- attributes = 0
-#ifdef UNIV_NON_BUFFERED_IO
- | FILE_FLAG_NO_BUFFERING
-#endif
- ;
- } else {
- attributes = 0;
- ut_error;
- }
-
- file = CreateFile(name,
- GENERIC_READ | GENERIC_WRITE, /* read and write
- access */
- FILE_SHARE_READ,/* file can be read by other
- processes */
- NULL, /* default security attributes */
- create_flag,
- attributes,
- NULL); /* no template file */
-
- if (file == INVALID_HANDLE_VALUE) {
- *success = FALSE;
-
- if (create_mode != OS_FILE_OPEN
- && os_file_get_last_error() == OS_FILE_DISK_FULL) {
-
- retry = os_file_handle_error(file, name);
-
- if (retry) {
- goto try_again;
- }
- }
- } else {
- *success = TRUE;
- }
-
- return(file);
-#else
- os_file_t file;
- int create_flag;
- bool retry;
-
-try_again:
- ut_a(name);
-
- if (create_mode == OS_FILE_OPEN) {
- create_flag = O_RDWR;
- } else if (create_mode == OS_FILE_CREATE) {
- create_flag = O_RDWR | O_CREAT | O_EXCL;
- } else if (create_mode == OS_FILE_OVERWRITE) {
- create_flag = O_RDWR | O_CREAT | O_TRUNC;
- } else {
- create_flag = 0;
- ut_error;
- }
-
- UT_NOT_USED(purpose);
-
- if (create_mode == OS_FILE_CREATE) {
-
- file = open(name, create_flag, S_IRWXU | S_IRWXG | S_IRWXO);
- } else {
- file = open(name, create_flag);
- }
-
- if (file == -1) {
- *success = FALSE;
-
- printf("Error in opening file %s, errno %lu\n", name,
- (ulint)errno);
- perror("os0file.c:");
-
- if (create_mode != OS_FILE_OPEN
- && errno == ENOSPC) {
-
- retry = os_file_handle_error(file, name);
-
- if (retry) {
- goto try_again;
- }
- }
- } else {
- *success = TRUE;
- }
-
- return(file);
-#endif
-}
-
-/***************************************************************************
-Closes a file handle. In case of error, error number can be retrieved with
-os_file_get_last_error. */
-
-bool
-os_file_close(
-/*==========*/
- /* out: TRUE if success */
- os_file_t file) /* in, own: handle to a file */
-{
-#ifdef __WIN__
- BOOL ret;
-
- ut_a(file);
-
- ret = CloseHandle(file);
-
- if (ret) {
- return(TRUE);
- }
-
- return(FALSE);
-#else
- int ret;
-
- ret = close(file);
-
- if (ret == -1) {
- return(FALSE);
- }
-
- return(TRUE);
-#endif
-}
-
-/***************************************************************************
-Gets a file size. */
-
-bool
-os_file_get_size(
-/*=============*/
- /* out: TRUE if success */
- os_file_t file, /* in: handle to a file */
- ulint* size, /* out: least significant 32 bits of file
- size */
- ulint* size_high)/* out: most significant 32 bits of size */
-{
-#ifdef __WIN__
- DWORD high;
- DWORD low;
-
- low = GetFileSize(file, &high);
-
- if ((low == 0xFFFFFFFF) && (GetLastError() != NO_ERROR)) {
- return(FALSE);
- }
-
- *size = low;
- *size_high = high;
-
- return(TRUE);
-#else
- *size = (ulint) lseek(file, 0, SEEK_END);
- *size_high = 0;
-
- return(TRUE);
-#endif
-}
-
-/***************************************************************************
-Sets a file size. This function can be used to extend or truncate a file. */
-
-bool
-os_file_set_size(
-/*=============*/
- /* out: TRUE if success */
- char* name, /* in: name of the file or path as a
- null-terminated string */
- os_file_t file, /* in: handle to a file */
- ulint size, /* in: least significant 32 bits of file
- size */
- ulint size_high)/* in: most significant 32 bits of size */
-{
-#ifdef __WIN__
- DWORD high;
- DWORD low;
- DWORD ret;
- BOOL ret2;
- DWORD err;
- bool retry;
-
-try_again:
- low = size;
- high = size_high;
-
- ret = SetFilePointer(file, low, &high, FILE_BEGIN);
-
- if (ret == 0xFFFFFFFF && GetLastError() != NO_ERROR) {
- err = GetLastError();
-
- goto error_handling;
- }
-
- ret2 = SetEndOfFile(file);
-
- if (ret2) {
- ret2 = os_file_flush(file);
- }
-
- if (ret2) {
- return(TRUE);
- }
-#else
- ulint offset;
- ulint n_bytes;
- ulint low;
- ssize_t ret;
- bool retry;
- ulint i;
- byte buf[UNIV_PAGE_SIZE * 8];
-
- /* Write buffer full of zeros */
- for (i = 0; i < UNIV_PAGE_SIZE * 8; i++) {
- buf[i] = '\0';
- }
-
-try_again:
- low = size;
-#if (UNIV_WORD_SIZE == 8)
- low = low + (size_high << 32);
-#endif
- while (offset < low) {
- if (low - offset < UNIV_PAGE_SIZE * 8) {
- n_bytes = low - offset;
- } else {
- n_bytes = UNIV_PAGE_SIZE * 8;
- }
-
- ret = pwrite(file, buf, n_bytes, offset);
-
- if (ret != n_bytes) {
- goto error_handling;
- }
- offset += n_bytes;
- }
-
- ret = os_file_flush(file);
-
- if (ret) {
- return(TRUE);
- }
-#endif
-
-error_handling:
- retry = os_file_handle_error(file, name);
-
- if (retry) {
- goto try_again;
- }
-
- ut_error;
-}
-
-/***************************************************************************
-Flushes the write buffers of a given file to the disk. */
-
-bool
-os_file_flush(
-/*==========*/
- /* out: TRUE if success */
- os_file_t file) /* in, own: handle to a file */
-{
-#ifdef __WIN__
- BOOL ret;
-
- ut_a(file);
-
- ret = FlushFileBuffers(file);
-
- if (ret) {
- return(TRUE);
- }
-
- return(FALSE);
-#else
- int ret;
-
- ret = fsync(file);
-
- if (ret == 0) {
- return(TRUE);
- }
-
- return(FALSE);
-#endif
-}
-
-
-#ifndef __WIN__
-/***********************************************************************
-Does a synchronous read operation in Posix. */
-static
-ssize_t
-os_file_pread(
-/*==========*/
- /* out: number of bytes read, -1 if error */
- os_file_t file, /* in: handle to a file */
- void* buf, /* in: buffer where to read */
- ulint n, /* in: number of bytes to read */
- ulint offset) /* in: offset from where to read */
-{
-#ifdef HAVE_PREAD
- return(pread(file, buf, n, (off_t) offset));
-#else
- ssize_t ret;
- ulint i;
-
- /* Protect the seek / read operation with a mutex */
- i = ((ulint) file) % OS_FILE_N_SEEK_MUTEXES;
-
- os_mutex_enter(os_file_seek_mutexes[i]);
-
- ret = lseek(file, (off_t) offset, 0);
-
- if (ret < 0) {
- os_mutex_exit(os_file_seek_mutexes[i]);
-
- return(ret);
- }
-
- ret = read(file, buf, n);
-
- os_mutex_exit(os_file_seek_mutexes[i]);
-
- return(ret);
-#endif
-}
-
-/***********************************************************************
-Does a synchronous write operation in Posix. */
-static
-ssize_t
-os_file_pwrite(
-/*===========*/
- /* out: number of bytes written, -1 if error */
- os_file_t file, /* in: handle to a file */
- void* buf, /* in: buffer from where to write */
- ulint n, /* in: number of bytes to write */
- ulint offset) /* in: offset where to write */
-{
-#ifdef HAVE_PWRITE
- return(pwrite(file, buf, n, (off_t) offset));
-#else
- ssize_t ret;
- ulint i;
-
- /* Protect the seek / write operation with a mutex */
- i = ((ulint) file) % OS_FILE_N_SEEK_MUTEXES;
-
- os_mutex_enter(os_file_seek_mutexes[i]);
-
- ret = lseek(file, (off_t) offset, 0);
-
- if (ret < 0) {
- os_mutex_exit(os_file_seek_mutexes[i]);
-
- return(ret);
- }
-
- ret = write(file, buf, n);
-
- os_mutex_exit(os_file_seek_mutexes[i]);
-
- return(ret);
-#endif
-}
-#endif
-
-/***********************************************************************
-Requests a synchronous positioned read operation. */
-
-bool
-os_file_read(
-/*=========*/
- /* out: TRUE if request was
- successful, FALSE if fail */
- os_file_t file, /* in: handle to a file */
- void* buf, /* in: buffer where to read */
- ulint offset, /* in: least significant 32 bits of file
- offset where to read */
- ulint offset_high, /* in: most significant 32 bits of
- offset */
- ulint n) /* in: number of bytes to read */
-{
-#ifdef __WIN__
- BOOL ret;
- DWORD len;
- DWORD ret2;
- DWORD err;
- DWORD low;
- DWORD high;
- bool retry;
- ulint i;
-
-try_again:
- ut_ad(file);
- ut_ad(buf);
- ut_ad(n > 0);
-
- low = offset;
- high = offset_high;
-
- /* Protect the seek / read operation with a mutex */
- i = ((ulint) file) % OS_FILE_N_SEEK_MUTEXES;
-
- os_mutex_enter(os_file_seek_mutexes[i]);
-
- ret2 = SetFilePointer(file, low, &high, FILE_BEGIN);
-
- if (ret2 == 0xFFFFFFFF && GetLastError() != NO_ERROR) {
- err = GetLastError();
-
- os_mutex_exit(os_file_seek_mutexes[i]);
-
- goto error_handling;
- }
-
- ret = ReadFile(file, buf, n, &len, NULL);
-
- os_mutex_exit(os_file_seek_mutexes[i]);
-
- if (ret && len == n) {
- return(TRUE);
- }
-
- err = GetLastError();
-#else
- bool retry;
- ssize_t ret;
- ulint i;
-
-#if (UNIV_WORD_SIZE == 8)
- offset = offset + (offset_high << 32);
-#endif
-try_again:
- /* Protect the seek / read operation with a mutex */
- i = ((ulint) file) % OS_FILE_N_SEEK_MUTEXES;
-
- os_mutex_enter(os_file_seek_mutexes[i]);
-
- ret = os_file_pread(file, buf, n, (off_t) offset);
-
- if (ret == n) {
- os_mutex_exit(os_file_seek_mutexes[i]);
-
- return(TRUE);
- }
-#endif
-error_handling:
- retry = os_file_handle_error(file, NULL);
-
- if (retry) {
- goto try_again;
- }
-
- ut_error;
-
- return(FALSE);
-}
-
-/***********************************************************************
-Requests a synchronous write operation. */
-
-bool
-os_file_write(
-/*==========*/
- /* out: TRUE if request was
- successful, FALSE if fail */
- char* name, /* in: name of the file or path as a
- null-terminated string */
- os_file_t file, /* in: handle to a file */
- void* buf, /* in: buffer from which to write */
- ulint offset, /* in: least significant 32 bits of file
- offset where to write */
- ulint offset_high, /* in: most significant 32 bits of
- offset */
- ulint n) /* in: number of bytes to write */
-{
-#ifdef __WIN__
- BOOL ret;
- DWORD len;
- DWORD ret2;
- DWORD err;
- DWORD low;
- DWORD high;
- bool retry;
- ulint i;
-
-try_again:
- ut_ad(file);
- ut_ad(buf);
- ut_ad(n > 0);
-
- low = offset;
- high = offset_high;
-
- /* Protect the seek / write operation with a mutex */
- i = ((ulint) file) % OS_FILE_N_SEEK_MUTEXES;
-
- os_mutex_enter(os_file_seek_mutexes[i]);
-
- ret2 = SetFilePointer(file, low, &high, FILE_BEGIN);
-
- if (ret2 == 0xFFFFFFFF && GetLastError() != NO_ERROR) {
- err = GetLastError();
-
- os_mutex_exit(os_file_seek_mutexes[i]);
-
- goto error_handling;
- }
-
- ret = WriteFile(file, buf, n, &len, NULL);
-
- os_mutex_exit(os_file_seek_mutexes[i]);
-
- if (ret && len == n) {
- return(TRUE);
- }
-#else
- bool retry;
- ssize_t ret;
-
-#if (UNIV_WORD_SIZE == 8)
- offset = offset + (offset_high << 32);
-#endif
-try_again:
- ret = pwrite(file, buf, n, (off_t) offset);
-
- if (ret == n) {
- return(TRUE);
- }
-#endif
-
-error_handling:
- retry = os_file_handle_error(file, name);
-
- if (retry) {
- goto try_again;
- }
-
- ut_error;
-
- return(FALSE);
-}
-
-/********************************************************************
-Returns a pointer to the nth slot in the aio array. */
-static
-os_aio_slot_t*
-os_aio_array_get_nth_slot(
-/*======================*/
- /* out: pointer to slot */
- os_aio_array_t* array, /* in: aio array */
- ulint index) /* in: index of the slot */
-{
- ut_a(index < array->n_slots);
-
- return((array->slots) + index);
-}
-
-/****************************************************************************
-Creates an aio wait array. */
-static
-os_aio_array_t*
-os_aio_array_create(
-/*================*/
- /* out, own: aio array */
- ulint n, /* in: maximum number of pending aio operations
- allowed; n must be divisible by n_segments */
- ulint n_segments) /* in: number of segments in the aio array */
-{
- os_aio_array_t* array;
- ulint i;
- os_aio_slot_t* slot;
-#ifdef WIN_ASYNC_IO
- OVERLAPPED* over;
-#endif
- ut_a(n > 0);
- ut_a(n_segments > 0);
- ut_a(n % n_segments == 0);
-
- array = ut_malloc(sizeof(os_aio_array_t));
-
- array->mutex = os_mutex_create(NULL);
- array->not_full = os_event_create(NULL);
- array->n_slots = n;
- array->n_segments = n_segments;
- array->n_reserved = 0;
- array->slots = ut_malloc(n * sizeof(os_aio_slot_t));
- array->events = ut_malloc(n * sizeof(os_event_t));
-
- for (i = 0; i < n; i++) {
- slot = os_aio_array_get_nth_slot(array, i);
-
- slot->pos = i;
- slot->reserved = FALSE;
-#ifdef WIN_ASYNC_IO
- over = &(slot->control);
-
- over->hEvent = os_event_create(NULL);
-
- *((array->events) + i) = over->hEvent;
-#elif defined(POSIX_ASYNC_IO)
- slot->ready = os_event_create(NULL);
-#endif
- }
-
- return(array);
-}
-
-/****************************************************************************
-Initializes the asynchronous io system. Creates separate aio array for
-non-ibuf read and write, a third aio array for the ibuf i/o, with just one
-segment, two aio arrays for log reads and writes with one segment, and a
-synchronous aio array of the specified size. The combined number of segments
-in the three first aio arrays is the parameter n_segments given to the
-function. The caller must create an i/o handler thread for each segment in
-the four first arrays, but not for the sync aio array. */
-
-void
-os_aio_init(
-/*========*/
- ulint n, /* in: maximum number of pending aio operations
- allowed; n must be divisible by n_segments */
- ulint n_segments, /* in: combined number of segments in the four
- first aio arrays; must be >= 4 */
- ulint n_slots_sync) /* in: number of slots in the sync aio array */
-{
- ulint n_read_segs;
- ulint n_write_segs;
- ulint n_per_seg;
- ulint i;
-
- ut_ad(n % n_segments == 0);
- ut_ad(n_segments >= 4);
-
- n_per_seg = n / n_segments;
- n_write_segs = (n_segments - 2) / 2;
- n_read_segs = n_segments - 2 - n_write_segs;
-
- os_aio_read_array = os_aio_array_create(n_read_segs * n_per_seg,
- n_read_segs);
- os_aio_write_array = os_aio_array_create(n_write_segs * n_per_seg,
- n_write_segs);
- os_aio_ibuf_array = os_aio_array_create(n_per_seg, 1);
-
- os_aio_log_array = os_aio_array_create(n_per_seg, 1);
-
- os_aio_sync_array = os_aio_array_create(n_slots_sync, 1);
-
- os_aio_n_segments = n_segments;
-
-#if !(defined(WIN_ASYNC_IO) || defined(POSIX_ASYNC_IO))
- os_aio_use_native_aio = FALSE;
-#endif
- os_aio_validate();
-
- for (i = 0; i < OS_FILE_N_SEEK_MUTEXES; i++) {
- os_file_seek_mutexes[i] = os_mutex_create(NULL);
- }
-
- os_aio_segment_wait_events = ut_malloc(n_segments * sizeof(void*));
-
- for (i = 0; i < n_segments; i++) {
- os_aio_segment_wait_events[i] = os_event_create(NULL);
- }
-}
-
-/**************************************************************************
-Calculates segment number for a slot. */
-static
-ulint
-os_aio_get_segment_no_from_slot(
-/*============================*/
- /* out: segment number (which is the number
- used by, for example, i/o-handler threads) */
- os_aio_array_t* array, /* in: aio wait array */
- os_aio_slot_t* slot) /* in: slot in this array */
-{
- ulint segment;
- ulint seg_len;
-
- if (array == os_aio_ibuf_array) {
- segment = 0;
-
- } else if (array == os_aio_log_array) {
- segment = 1;
-
- } else if (array == os_aio_read_array) {
- seg_len = os_aio_read_array->n_slots /
- os_aio_read_array->n_segments;
-
- segment = 2 + slot->pos / seg_len;
- } else {
- ut_a(array == os_aio_write_array);
- seg_len = os_aio_write_array->n_slots /
- os_aio_write_array->n_segments;
-
- segment = os_aio_read_array->n_segments + 2
- + slot->pos / seg_len;
- }
-
- return(segment);
-}
-
-/**************************************************************************
-Calculates local segment number and aio array from global segment number. */
-static
-ulint
-os_aio_get_array_and_local_segment(
-/*===============================*/
- /* out: local segment number within
- the aio array */
- os_aio_array_t** array, /* out: aio wait array */
- ulint global_segment)/* in: global segment number */
-{
- ulint segment;
-
- ut_a(global_segment < os_aio_n_segments);
-
- if (global_segment == 0) {
- *array = os_aio_ibuf_array;
- segment = 0;
-
- } else if (global_segment == 1) {
- *array = os_aio_log_array;
- segment = 0;
-
- } else if (global_segment < os_aio_read_array->n_segments + 2) {
- *array = os_aio_read_array;
-
- segment = global_segment - 2;
- } else {
- *array = os_aio_write_array;
-
- segment = global_segment - (os_aio_read_array->n_segments + 2);
- }
-
- return(segment);
-}
-
-/***********************************************************************
-Gets an integer value designating a specified aio array. This is used
-to give numbers to signals in Posix aio. */
-static
-ulint
-os_aio_get_array_no(
-/*================*/
- os_aio_array_t* array) /* in: aio array */
-{
- if (array == os_aio_ibuf_array) {
-
- return(0);
-
- } else if (array == os_aio_log_array) {
-
- return(1);
-
- } else if (array == os_aio_read_array) {
-
- return(2);
- } else if (array == os_aio_write_array) {
-
- return(3);
- } else {
- ut_a(0);
-
- return(0);
- }
-}
-
-/***********************************************************************
-Gets the aio array for its number. */
-static
-os_aio_array_t*
-os_aio_get_array_from_no(
-/*=====================*/
- /* out: aio array */
- ulint n) /* in: array number */
-{
- if (n == 0) {
- return(os_aio_ibuf_array);
- } else if (n == 1) {
-
- return(os_aio_log_array);
- } else if (n == 2) {
-
- return(os_aio_read_array);
- } else if (n == 3) {
-
- return(os_aio_write_array);
- } else {
- ut_a(0);
-
- return(NULL);
- }
-}
-
-/***********************************************************************
-Requests for a slot in the aio array. If no slot is available, waits until
-not_full-event becomes signaled. */
-static
-os_aio_slot_t*
-os_aio_array_reserve_slot(
-/*======================*/
- /* out: pointer to slot */
- ulint type, /* in: OS_FILE_READ or OS_FILE_WRITE */
- os_aio_array_t* array, /* in: aio array */
- void* message1,/* in: message to be passed along with
- the aio operation */
- void* message2,/* in: message to be passed along with
- the aio operation */
- os_file_t file, /* in: file handle */
- char* name, /* in: name of the file or path as a
- null-terminated string */
- void* buf, /* in: buffer where to read or from which
- to write */
- ulint offset, /* in: least significant 32 bits of file
- offset */
- ulint offset_high, /* in: most significant 32 bits of
- offset */
- ulint len) /* in: length of the block to read or write */
-{
- os_aio_slot_t* slot;
-#ifdef WIN_ASYNC_IO
- OVERLAPPED* control;
-#elif POSIX_ASYNC_IO
- struct aiocb* control;
- ulint type;
-#endif
- ulint i;
-loop:
- os_mutex_enter(array->mutex);
-
- if (array->n_reserved == array->n_slots) {
- os_mutex_exit(array->mutex);
- os_event_wait(array->not_full);
-
- goto loop;
- }
-
- for (i = 0;; i++) {
- slot = os_aio_array_get_nth_slot(array, i);
-
- if (slot->reserved == FALSE) {
- break;
- }
- }
-
- array->n_reserved++;
-
- if (array->n_reserved == array->n_slots) {
- os_event_reset(array->not_full);
- }
-
- slot->reserved = TRUE;
- slot->message1 = message1;
- slot->message2 = message2;
- slot->file = file;
- slot->name = name;
- slot->len = len;
- slot->type = type;
- slot->buf = buf;
- slot->offset = offset;
- slot->offset_high = offset_high;
- slot->io_already_done = FALSE;
-
-#ifdef WIN_ASYNC_IO
- control = &(slot->control);
- control->Offset = (DWORD)offset;
- control->OffsetHigh = (DWORD)offset_high;
- os_event_reset(control->hEvent);
-
-#elif POSIX_ASYNC_IO
-
-#if (UNIV_WORD_SIZE == 8)
- offset = offset + (offset_high << 32);
-#else
- ut_a(offset_high == 0);
-#endif
- control = &(slot->control);
- control->aio_fildes = file;
- control->aio_buf = buf;
- control->aio_nbytes = len;
- control->aio_offset = offset;
- control->aio_reqprio = 0;
- control->aio_sigevent.sigev_notify = SIGEV_SIGNAL;
- control->aio_sigevent.signo =
- SIGRTMAX + 1 + os_aio_get_array_no(array);
- /* TODO: How to choose the signal numbers? */
- control->aio_sigevent.sigev_value.sival_ptr = slot;
-#endif
- os_mutex_exit(array->mutex);
-
- return(slot);
-}
-
-/***********************************************************************
-Frees a slot in the aio array. */
-static
-void
-os_aio_array_free_slot(
-/*===================*/
- os_aio_array_t* array, /* in: aio array */
- os_aio_slot_t* slot) /* in: pointer to slot */
-{
- ut_ad(array);
- ut_ad(slot);
-
- os_mutex_enter(array->mutex);
-
- ut_ad(slot->reserved);
-
- slot->reserved = FALSE;
-
- array->n_reserved--;
-
- if (array->n_reserved == array->n_slots - 1) {
- os_event_set(array->not_full);
- }
-
-#ifdef WIN_ASYNC_IO
- os_event_reset(slot->control.hEvent);
-#endif
- os_mutex_exit(array->mutex);
-}
-
-/**************************************************************************
-Wakes up a simulated aio i/o-handler thread if it has something to do. */
-static
-void
-os_aio_simulated_wake_handler_thread(
-/*=================================*/
- ulint global_segment) /* in: the number of the segment in the aio
- arrays */
-{
- os_aio_array_t* array;
- ulint segment;
- os_aio_slot_t* slot;
- ulint n;
- ulint i;
-
- ut_ad(!os_aio_use_native_aio);
-
- segment = os_aio_get_array_and_local_segment(&array, global_segment);
-
- n = array->n_slots / array->n_segments;
-
- /* Look through n slots after the segment * n'th slot */
-
- os_mutex_enter(array->mutex);
-
- for (i = 0; i < n; i++) {
- slot = os_aio_array_get_nth_slot(array, i + segment * n);
-
- if (slot->reserved) {
- /* Found an i/o request */
-
- break;
- }
- }
-
- os_mutex_exit(array->mutex);
-
- if (i < n) {
- os_event_set(os_aio_segment_wait_events[global_segment]);
- }
-}
-
-/**************************************************************************
-Wakes up simulated aio i/o-handler threads if they have something to do. */
-
-void
-os_aio_simulated_wake_handler_threads(void)
-/*=======================================*/
-{
- ulint i;
-
- if (os_aio_use_native_aio) {
- /* We do not use simulated aio: do nothing */
-
- return;
- }
-
- for (i = 0; i < os_aio_n_segments; i++) {
- os_aio_simulated_wake_handler_thread(i);
- }
-}
-
-/***********************************************************************
-Requests an asynchronous i/o operation. */
-
-bool
-os_aio(
-/*===*/
- /* out: TRUE if request was queued
- successfully, FALSE if fail */
- ulint type, /* in: OS_FILE_READ or OS_FILE_WRITE */
- ulint mode, /* in: OS_AIO_NORMAL, ..., possibly ORed
- to OS_AIO_SIMULATED_WAKE_LATER: the
- last flag advises this function not to wake
- i/o-handler threads, but the caller will
- do the waking explicitly later, in this
- way the caller can post several requests in
- a batch; NOTE that the batch must not be
- so big that it exhausts the slots in aio
- arrays! NOTE that a simulated batch
- may introduce hidden chances of deadlocks,
- because i/os are not actually handled until
- all have been posted: use with great
- caution! */
- char* name, /* in: name of the file or path as a
- null-terminated string */
- os_file_t file, /* in: handle to a file */
- void* buf, /* in: buffer where to read or from which
- to write */
- ulint offset, /* in: least significant 32 bits of file
- offset where to read or write */
- ulint offset_high, /* in: most significant 32 bits of
- offset */
- ulint n, /* in: number of bytes to read or write */
- void* message1,/* in: messages for the aio handler (these
- can be used to identify a completed aio
- operation); if mode is OS_AIO_SYNC, these
- are ignored */
- void* message2)
-{
- os_aio_array_t* array;
- os_aio_slot_t* slot;
-#ifdef WIN_ASYNC_IO
- BOOL ret = TRUE;
- DWORD len = n;
- void* dummy_mess1;
- void* dummy_mess2;
-#endif
- ulint err = 0;
- bool retry;
- ulint wake_later;
-
- ut_ad(file);
- ut_ad(buf);
- ut_ad(n > 0);
- ut_ad(n % OS_FILE_LOG_BLOCK_SIZE == 0);
- ut_ad((ulint)buf % OS_FILE_LOG_BLOCK_SIZE == 0)
- ut_ad(offset % OS_FILE_LOG_BLOCK_SIZE == 0);
- ut_ad(os_aio_validate());
-
- wake_later = mode & OS_AIO_SIMULATED_WAKE_LATER;
- mode = mode & (~OS_AIO_SIMULATED_WAKE_LATER);
-
- if (mode == OS_AIO_SYNC
-#ifdef WIN_ASYNC_IO
- && !os_aio_use_native_aio
-#endif
- ) {
- /* This is actually an ordinary synchronous read or write:
- no need to use an i/o-handler thread. NOTE that if we use
- Windows async i/o, Windows does not allow us to use
- ordinary synchronous os_file_read etc. on the same file,
- therefore we have built a special mechanism for synchronous
- wait in the Windows case. */
-
- if (type == OS_FILE_READ) {
- return(os_file_read(file, buf, offset, offset_high, n));
- }
-
- ut_a(type == OS_FILE_WRITE);
-
- return(os_file_write(name, file, buf, offset, offset_high, n));
- }
-
-try_again:
- if (mode == OS_AIO_NORMAL) {
- if (type == OS_FILE_READ) {
- array = os_aio_read_array;
- } else {
- array = os_aio_write_array;
- }
- } else if (mode == OS_AIO_IBUF) {
- ut_ad(type == OS_FILE_READ);
-
- array = os_aio_ibuf_array;
- } else if (mode == OS_AIO_LOG) {
-
- array = os_aio_log_array;
- } else if (mode == OS_AIO_SYNC) {
- array = os_aio_sync_array;
- } else {
- ut_error;
- }
-
- slot = os_aio_array_reserve_slot(type, array, message1, message2, file,
- name, buf, offset, offset_high, n);
- if (type == OS_FILE_READ) {
- if (os_aio_use_native_aio) {
-#ifdef WIN_ASYNC_IO
- ret = ReadFile(file, buf, (DWORD)n, &len,
- &(slot->control));
-#elif defined(POSIX_ASYNC_IO)
- err = (ulint) aio_read(&(slot->control));
-#endif
- } else {
- if (!wake_later) {
- os_aio_simulated_wake_handler_thread(
- os_aio_get_segment_no_from_slot(array, slot));
- }
- }
- } else if (type == OS_FILE_WRITE) {
- if (os_aio_use_native_aio) {
-#ifdef WIN_ASYNC_IO
- ret = WriteFile(file, buf, (DWORD)n, &len,
- &(slot->control));
-#elif defined(POSIX_ASYNC_IO)
- err = (ulint) aio_write(&(slot->control));
-#endif
- } else {
- if (!wake_later) {
- os_aio_simulated_wake_handler_thread(
- os_aio_get_segment_no_from_slot(array, slot));
- }
- }
- } else {
- ut_error;
- }
-
-#ifdef WIN_ASYNC_IO
- if ((ret && len == n)
- || (!ret && GetLastError() == ERROR_IO_PENDING)) {
-
- /* aio was queued successfully! */
-
- if (mode == OS_AIO_SYNC) {
- /* We want a synchronous i/o operation on a file
- where we also use async i/o: in Windows we must
- use the same wait mechanism as for async i/o */
-
- return(os_aio_windows_handle(ULINT_UNDEFINED,
- slot->pos,
- &dummy_mess1, &dummy_mess2));
- }
-
- return(TRUE);
- }
-#else
- if (err == 0) {
- /* aio was queued successfully! */
-
- return(TRUE);
- }
-#endif
- os_aio_array_free_slot(array, slot);
-
- retry = os_file_handle_error(file, name);
-
- if (retry) {
-
- goto try_again;
- }
-
- ut_error;
-
- return(FALSE);
-}
-
-#ifdef WIN_ASYNC_IO
-/**************************************************************************
-This function is only used in Windows asynchronous i/o.
-Waits for an aio operation to complete. This function is used to wait the
-for completed requests. The aio array of pending requests is divided
-into segments. The thread specifies which segment or slot it wants to wait
-for. NOTE: this function will also take care of freeing the aio slot,
-therefore no other thread is allowed to do the freeing! */
-
-bool
-os_aio_windows_handle(
-/*==================*/
- /* out: TRUE if the aio operation succeeded */
- ulint segment, /* in: the number of the segment in the aio
- arrays to wait for; segment 0 is the ibuf
- i/o thread, segment 1 the log i/o thread,
- then follow the non-ibuf read threads, and as
- the last are the non-ibuf write threads; if
- this is ULINT_UNDEFINED, then it means that
- sync aio is used, and this parameter is
- ignored */
- ulint pos, /* this parameter is used only in sync aio:
- wait for the aio slot at this position */
- void** message1, /* out: the messages passed with the aio
- request; note that also in the case where
- the aio operation failed, these output
- parameters are valid and can be used to
- restart the operation, for example */
- void** message2)
-{
- os_aio_array_t* array;
- os_aio_slot_t* slot;
- ulint n;
- ulint i;
- bool ret_val;
- ulint err;
- BOOL ret;
- DWORD len;
-
- if (segment == ULINT_UNDEFINED) {
- array = os_aio_sync_array;
- segment = 0;
- } else {
- segment = os_aio_get_array_and_local_segment(&array, segment);
- }
-
- /* NOTE! We only access constant fields in os_aio_array. Therefore
- we do not have to acquire the protecting mutex yet */
-
- ut_ad(os_aio_validate());
- ut_ad(segment < array->n_segments);
-
- n = array->n_slots / array->n_segments;
-
- if (array == os_aio_sync_array) {
- ut_ad(pos < array->n_slots);
- os_event_wait(array->events[pos]);
- i = pos;
- } else {
- i = os_event_wait_multiple(n, (array->events) + segment * n);
- }
-
- os_mutex_enter(array->mutex);
-
- slot = os_aio_array_get_nth_slot(array, i + segment * n);
-
- ut_a(slot->reserved);
-
- ret = GetOverlappedResult(slot->file, &(slot->control), &len, TRUE);
-
- *message1 = slot->message1;
- *message2 = slot->message2;
-
- if (ret && len == slot->len) {
- ret_val = TRUE;
- } else {
- err = GetLastError();
- ut_error;
-
- ret_val = FALSE;
- }
-
- os_mutex_exit(array->mutex);
-
- os_aio_array_free_slot(array, slot);
-
- return(ret_val);
-}
-#endif
-
-#ifdef POSIX_ASYNC_IO
-/**************************************************************************
-This function is only used in Posix asynchronous i/o. Waits for an aio
-operation to complete. */
-
-bool
-os_aio_posix_handle(
-/*================*/
- /* out: TRUE if the aio operation succeeded */
- ulint array_no, /* in: array number 0 - 3 */
- void** message1, /* out: the messages passed with the aio
- request; note that also in the case where
- the aio operation failed, these output
- parameters are valid and can be used to
- restart the operation, for example */
- void** message2)
-{
- os_aio_array_t* array;
- os_aio_slot_t* slot;
- siginfo_t info;
- sigset_t sigset;
- int ret;
-
- sigemptyset(&sigset);
- sigaddset(&sigset, SIGRTMAX + 1 + array_no);
-
- ret = sigwaitinfo(&sigset, &info);
-
- if (ret != SIGRTMAX + 1 + array_no) {
-
- ut_a(0);
-
- return(FALSE);
- }
-
- array = os_aio_get_array_from_no(array_no);
-
- os_mutex_enter(array->mutex);
-
- slot = siginfo.si_value.sival_ptr;
-
- ut_a(slot->reserved);
-
- *message1 = slot->message1;
- *message2 = slot->message2;
-
- os_mutex_exit(array->mutex);
-
- os_aio_array_free_slot(array, slot);
-
- return(TRUE);
-}
-#endif
-
-/**************************************************************************
-Does simulated aio. This function should be called by an i/o-handler
-thread. */
-
-bool
-os_aio_simulated_handle(
-/*====================*/
- /* out: TRUE if the aio operation succeeded */
- ulint global_segment, /* in: the number of the segment in the aio
- arrays to wait for; segment 0 is the ibuf
- i/o thread, segment 1 the log i/o thread,
- then follow the non-ibuf read threads, and as
- the last are the non-ibuf write threads */
- void** message1, /* out: the messages passed with the aio
- request; note that also in the case where
- the aio operation failed, these output
- parameters are valid and can be used to
- restart the operation, for example */
- void** message2)
-{
- os_aio_array_t* array;
- ulint segment;
- os_aio_slot_t* slot;
- os_aio_slot_t* slot2;
- os_aio_slot_t* consecutive_ios[OS_AIO_MERGE_N_CONSECUTIVE];
- ulint n_consecutive;
- ulint total_len;
- ulint offs;
- byte* combined_buf;
- bool ret;
- ulint n;
- ulint i;
-
- segment = os_aio_get_array_and_local_segment(&array, global_segment);
-
-restart:
- /* NOTE! We only access constant fields in os_aio_array. Therefore
- we do not have to acquire the protecting mutex yet */
-
- ut_ad(os_aio_validate());
- ut_ad(segment < array->n_segments);
-
- n = array->n_slots / array->n_segments;
-
- /* Look through n slots after the segment * n'th slot */
-
- os_mutex_enter(array->mutex);
-
- /* Check if there is a slot for which the i/o has already been
- done */
-
- for (i = 0; i < n; i++) {
- slot = os_aio_array_get_nth_slot(array, i + segment * n);
-
- if (slot->reserved && slot->io_already_done) {
-
- goto slot_io_done;
- }
- }
-
- n_consecutive = 0;
-
- for (i = 0; i < n; i++) {
- slot = os_aio_array_get_nth_slot(array, i + segment * n);
-
- if (slot->reserved) {
- /* Found an i/o request */
- consecutive_ios[n_consecutive] = slot;
- n_consecutive++;
-
- break;
- }
- }
-
- /* Check if there are several consecutive blocks to read or write */
-
-consecutive_loop:
- for (i = 0; i < n; i++) {
- slot2 = os_aio_array_get_nth_slot(array, i + segment * n);
-
- if (slot2->reserved && slot2 != slot
- && slot2->offset == slot->offset + slot->len
- && slot->offset + slot->len > slot->offset /* check that
- sum does not wrap over */
- && slot2->offset_high == slot->offset_high
- && slot2->type == slot->type
- && slot2->file == slot->file) {
-
- /* Found a consecutive i/o request */
-
- consecutive_ios[n_consecutive] = slot2;
- n_consecutive++;
-
- slot = slot2;
-
- if (n_consecutive < OS_AIO_MERGE_N_CONSECUTIVE) {
-
- goto consecutive_loop;
- } else {
- break;
- }
- }
- }
-
- if (n_consecutive == 0) {
-
- /* No i/o requested at the moment */
-
- goto wait_for_io;
- }
-
- /* We have now collected n_consecutive i/o requests in the array;
- allocate a single buffer which can hold all data, and perform the
- i/o */
-
- total_len = 0;
- slot = consecutive_ios[0];
-
- for (i = 0; i < n_consecutive; i++) {
- total_len += consecutive_ios[i]->len;
- }
-
- if (n_consecutive == 1) {
- /* We can use the buffer of the i/o request */
- combined_buf = slot->buf;
- } else {
- combined_buf = ut_malloc(total_len);
-
- ut_a(combined_buf);
- }
-
- /* We release the array mutex for the time of the i/o: NOTE that
- this assumes that there is just one i/o-handler thread serving
- a single segment of slots! */
-
- os_mutex_exit(array->mutex);
-
- if (slot->type == OS_FILE_WRITE && n_consecutive > 1) {
- /* Copy the buffers to the combined buffer */
- offs = 0;
-
- for (i = 0; i < n_consecutive; i++) {
-
- ut_memcpy(combined_buf + offs, consecutive_ios[i]->buf,
- consecutive_ios[i]->len);
- offs += consecutive_ios[i]->len;
- }
- }
-
- /* Do the i/o with ordinary, synchronous i/o functions: */
- if (slot->type == OS_FILE_WRITE) {
- ret = os_file_write(slot->name, slot->file, combined_buf,
- slot->offset, slot->offset_high, total_len);
- } else {
- ret = os_file_read(slot->file, combined_buf,
- slot->offset, slot->offset_high, total_len);
- }
-
- ut_a(ret);
-
- if (slot->type == OS_FILE_READ && n_consecutive > 1) {
- /* Copy the combined buffer to individual buffers */
- offs = 0;
-
- for (i = 0; i < n_consecutive; i++) {
-
- ut_memcpy(consecutive_ios[i]->buf, combined_buf + offs,
- consecutive_ios[i]->len);
- offs += consecutive_ios[i]->len;
- }
- }
-
- if (n_consecutive > 1) {
- ut_free(combined_buf);
- }
-
- os_mutex_enter(array->mutex);
-
- /* Mark the i/os done in slots */
-
- for (i = 0; i < n_consecutive; i++) {
- consecutive_ios[i]->io_already_done = TRUE;
- }
-
- /* We return the messages for the first slot now, and if there were
- several slots, the messages will be returned with subsequent calls
- of this function */
-
-slot_io_done:
-
- ut_a(slot->reserved);
-
- *message1 = slot->message1;
- *message2 = slot->message2;
-
- os_mutex_exit(array->mutex);
-
- os_aio_array_free_slot(array, slot);
-
- return(ret);
-
-wait_for_io:
- /* We wait here until there again can be i/os in the segment
- of this thread */
-
- os_event_reset(os_aio_segment_wait_events[global_segment]);
-
- os_mutex_exit(array->mutex);
-
- os_event_wait(os_aio_segment_wait_events[global_segment]);
-
- goto restart;
-}
-
-/**************************************************************************
-Validates the consistency of an aio array. */
-static
-bool
-os_aio_array_validate(
-/*==================*/
- /* out: TRUE if ok */
- os_aio_array_t* array) /* in: aio wait array */
-{
- os_aio_slot_t* slot;
- ulint n_reserved = 0;
- ulint i;
-
- ut_a(array);
-
- os_mutex_enter(array->mutex);
-
- ut_a(array->n_slots > 0);
- ut_a(array->n_segments > 0);
-
- for (i = 0; i < array->n_slots; i++) {
- slot = os_aio_array_get_nth_slot(array, i);
-
- if (slot->reserved) {
- n_reserved++;
- ut_a(slot->len > 0);
- }
- }
-
- ut_a(array->n_reserved == n_reserved);
-
- os_mutex_exit(array->mutex);
-
- return(TRUE);
-}
-
-/**************************************************************************
-Validates the consistency the aio system. */
-
-bool
-os_aio_validate(void)
-/*=================*/
- /* out: TRUE if ok */
-{
- os_aio_array_validate(os_aio_read_array);
- os_aio_array_validate(os_aio_write_array);
- os_aio_array_validate(os_aio_ibuf_array);
- os_aio_array_validate(os_aio_log_array);
- os_aio_array_validate(os_aio_sync_array);
-
- return(TRUE);
-}
-
-/**************************************************************************
-Prints info of the aio arrays. */
-
-void
-os_aio_print(void)
-/*==============*/
-{
- os_aio_array_t* array;
- os_aio_slot_t* slot;
- ulint n_reserved;
- ulint i;
-
- array = os_aio_read_array;
-loop:
- ut_a(array);
-
- printf("INFO OF AN AIO ARRAY\n");
-
- os_mutex_enter(array->mutex);
-
- ut_a(array->n_slots > 0);
- ut_a(array->n_segments > 0);
-
- n_reserved = 0;
-
- for (i = 0; i < array->n_slots; i++) {
- slot = os_aio_array_get_nth_slot(array, i);
-
- if (slot->reserved) {
- n_reserved++;
- printf("Reserved slot, messages %lx %lx\n",
- slot->message1, slot->message2);
- ut_a(slot->len > 0);
- }
- }
-
- ut_a(array->n_reserved == n_reserved);
-
- printf("Total of %lu reserved aio slots\n", n_reserved);
-
- os_mutex_exit(array->mutex);
-
- if (array == os_aio_read_array) {
- array = os_aio_write_array;
-
- goto loop;
- }
-
- if (array == os_aio_write_array) {
- array = os_aio_ibuf_array;
-
- goto loop;
- }
-
- if (array == os_aio_ibuf_array) {
- array = os_aio_log_array;
-
- goto loop;
- }
-
- if (array == os_aio_log_array) {
- array = os_aio_sync_array;
-
- goto loop;
- }
-}
-
-/**************************************************************************
-Checks that all slots in the system have been freed, that is, there are
-no pending io operations. */
-
-bool
-os_aio_all_slots_free(void)
-/*=======================*/
- /* out: TRUE if all free */
-{
- os_aio_array_t* array;
- ulint n_res = 0;
-
- array = os_aio_read_array;
-
- os_mutex_enter(array->mutex);
-
- n_res += array->n_reserved;
-
- os_mutex_exit(array->mutex);
-
- array = os_aio_write_array;
-
- os_mutex_enter(array->mutex);
-
- n_res += array->n_reserved;
-
- os_mutex_exit(array->mutex);
-
- array = os_aio_ibuf_array;
-
- os_mutex_enter(array->mutex);
-
- n_res += array->n_reserved;
-
- os_mutex_exit(array->mutex);
-
- array = os_aio_log_array;
-
- os_mutex_enter(array->mutex);
-
- n_res += array->n_reserved;
-
- os_mutex_exit(array->mutex);
-
- array = os_aio_sync_array;
-
- os_mutex_enter(array->mutex);
-
- n_res += array->n_reserved;
-
- os_mutex_exit(array->mutex);
-
- if (n_res == 0) {
-
- return(TRUE);
- }
-
- return(FALSE);
-}
diff --git a/innobase/srv/srv0srv.c b/innobase/srv/srv0srv.c
index 8aba1b4f414..9f4c9228850 100644
--- a/innobase/srv/srv0srv.c
+++ b/innobase/srv/srv0srv.c
@@ -863,123 +863,6 @@ srv_release_max_if_no_queries(void)
mutex_exit(&kernel_mutex);
}
-#ifdef notdefined
-/***********************************************************************
-Releases one utility thread if no queries are active and
-the high-water mark 2 for the utility is exceeded. */
-static
-void
-srv_release_one_if_no_queries(void)
-/*===============================*/
-{
- ulint m;
- ulint type;
-
- mutex_enter(&kernel_mutex);
-
- if (srv_n_threads_active[SRV_COM] > 0) {
- mutex_exit(&kernel_mutex);
-
- return;
- }
-
- type = SRV_RECOVERY;
-
- m = 1;
-
- if ((srv_meter[type] > srv_meter_high_water2[type])
- && (srv_n_threads_active[type] < m)) {
-
- srv_release_threads(type, m - srv_n_threads_active[type]);
-
- printf("Releasing one background\n");
- }
-
- mutex_exit(&kernel_mutex);
-}
-
-/***********************************************************************
-Decrements the utility meter by the value given and suspends the calling
-thread, which must be an utility thread of the type given, if necessary. */
-static
-void
-srv_decrement_meter(
-/*================*/
- ulint type, /* in: utility type */
- ulint n) /* in: value to subtract from meter */
-{
- ulint opt;
- os_event_t event;
-
- mutex_enter(&kernel_mutex);
-
- if (srv_meter[type] < n) {
- srv_meter[type] = 0;
- } else {
- srv_meter[type] -= n;
- }
-
- opt = srv_max_n_utilities(type);
-
- if (opt < srv_n_threads_active[type]) {
-
- event = srv_suspend_thread();
- mutex_exit(&kernel_mutex);
-
- os_event_wait(event);
- } else {
- mutex_exit(&kernel_mutex);
- }
-}
-#endif
-
-/*************************************************************************
-Implements the server console. */
-
-ulint
-srv_console(
-/*========*/
- /* out: return code, not used */
- void* arg) /* in: argument, not used */
-{
- char command[256];
-
- UT_NOT_USED(arg);
-
- mutex_enter(&kernel_mutex);
- srv_table_reserve_slot(SRV_CONSOLE);
- mutex_exit(&kernel_mutex);
-
- os_event_wait(srv_sys->operational);
-
- for (;;) {
- scanf("%s", command);
-
- srv_inc_thread_count(SRV_CONSOLE);
-
- if (command[0] == 'c') {
- printf("Making checkpoint\n");
-
- log_make_checkpoint_at(ut_dulint_max, TRUE);
-
- printf("Checkpoint completed\n");
-
- } else if (command[0] == 'd') {
- srv_sim_disk_wait_pct = atoi(command + 1);
-
- printf(
- "Starting disk access simulation with pct %lu\n",
- srv_sim_disk_wait_pct);
- } else {
- printf("\nNot supported!\n");
- }
-
- srv_dec_thread_count(SRV_CONSOLE);
- }
-
- return(0);
-}
-
/*************************************************************************
Creates the first communication endpoint for the server. This
first call also initializes the com0com.* module. */
@@ -1008,69 +891,6 @@ srv_communication_init(
ut_a(ret == 0);
}
-#ifdef notdefined
-
-/*************************************************************************
-Implements the recovery utility. */
-static
-ulint
-srv_recovery_thread(
-/*================*/
- /* out: return code, not used */
- void* arg) /* in: not used */
-{
- ulint slot_no;
- os_event_t event;
-
- UT_NOT_USED(arg);
-
- slot_no = srv_table_reserve_slot(SRV_RECOVERY);
-
- os_event_wait(srv_sys->operational);
-
- for (;;) {
- /* Finish a possible recovery */
-
- srv_inc_thread_count(SRV_RECOVERY);
-
-/* recv_recovery_from_checkpoint_finish(); */
-
- srv_dec_thread_count(SRV_RECOVERY);
-
- mutex_enter(&kernel_mutex);
- event = srv_suspend_thread();
- mutex_exit(&kernel_mutex);
-
- /* Wait for somebody to release this thread; (currently, this
- should never be released) */
-
- os_event_wait(event);
- }
-
- return(0);
-}
-
-/*************************************************************************
-Implements the purge utility. */
-
-ulint
-srv_purge_thread(
-/*=============*/
- /* out: return code, not used */
- void* arg) /* in: not used */
-{
- UT_NOT_USED(arg);
-
- os_event_wait(srv_sys->operational);
-
- for (;;) {
- trx_purge();
- }
-
- return(0);
-}
-#endif /* notdefined */
-
/*************************************************************************
Creates the utility threads. */
@@ -1100,58 +920,6 @@ srv_create_utility_threads(void)
ut_a(thread); */
}
-#ifdef notdefined
-/*************************************************************************
-Implements the communication threads. */
-static
-ulint
-srv_com_thread(
-/*===========*/
- /* out: return code; not used */
- void* arg) /* in: not used */
-{
- byte* msg_buf;
- byte* addr_buf;
- ulint msg_len;
- ulint addr_len;
- ulint ret;
-
- UT_NOT_USED(arg);
-
- srv_table_reserve_slot(SRV_COM);
-
- os_event_wait(srv_sys->operational);
-
- msg_buf = mem_alloc(com_endpoint_get_max_size(srv_sys->endpoint));
- addr_buf = mem_alloc(COM_MAX_ADDR_LEN);
-
- for (;;) {
- ret = com_recvfrom(srv_sys->endpoint, msg_buf,
- com_endpoint_get_max_size(srv_sys->endpoint),
- &msg_len, (char*)addr_buf, COM_MAX_ADDR_LEN,
- &addr_len);
- ut_a(ret == 0);
-
- srv_inc_thread_count(SRV_COM);
-
- sess_process_cli_msg(msg_buf, msg_len, addr_buf, addr_len);
-
-/* srv_increment_meter(SRV_RECOVERY, 1); */
-
- srv_dec_thread_count(SRV_COM);
-
- /* Release one utility thread for each utility if
- high water mark 2 is exceeded and there are no
- active queries. This is done to utilize possible
- quiet time in the server. */
-
- srv_release_one_if_no_queries();
- }
-
- return(0);
-}
-#endif
-
/*************************************************************************
Creates the communication threads. */
@@ -1171,53 +939,6 @@ srv_create_com_threads(void)
}
}
-#ifdef notdefined
-/*************************************************************************
-Implements the worker threads. */
-static
-ulint
-srv_worker_thread(
-/*==============*/
- /* out: return code, not used */
- void* arg) /* in: not used */
-{
- os_event_t event;
-
- UT_NOT_USED(arg);
-
- srv_table_reserve_slot(SRV_WORKER);
-
- os_event_wait(srv_sys->operational);
-
- for (;;) {
- mutex_enter(&kernel_mutex);
- event = srv_suspend_thread();
- mutex_exit(&kernel_mutex);
-
- /* Wait for somebody to release this thread */
- os_event_wait(event);
-
- srv_inc_thread_count(SRV_WORKER);
-
- /* Check in the server task queue if there is work for this
- thread, and do the work */
-
- srv_que_task_queue_check();
-
- srv_dec_thread_count(SRV_WORKER);
-
- /* Release one utility thread for each utility if
- high water mark 2 is exceeded and there are no
- active queries. This is done to utilize possible
- quiet time in the server. */
-
- srv_release_one_if_no_queries();
- }
-
- return(0);
-}
-#endif
-
/*************************************************************************
Creates the worker threads. */
@@ -1238,404 +959,6 @@ srv_create_worker_threads(void)
}
}
-#ifdef notdefined
-/*************************************************************************
-Reads a keyword and a value from a file. */
-
-ulint
-srv_read_init_val(
-/*==============*/
- /* out: DB_SUCCESS or error code */
- FILE* initfile, /* in: file pointer */
- char* keyword, /* in: keyword before value(s), or NULL if
- no keyword read */
- char* str_buf, /* in/out: buffer for a string value to read,
- buffer size must be 10000 bytes, if NULL
- then not read */
- ulint* num_val, /* out: numerical value to read, if NULL
- then not read */
- ibool print_not_err) /* in: if TRUE, then we will not print
- error messages to console */
-{
- ulint ret;
- char scan_buf[10000];
-
- if (keyword == NULL) {
-
- goto skip_keyword;
- }
-
- ret = fscanf(initfile, "%9999s", scan_buf);
-
- if (ret == 0 || ret == EOF || 0 != ut_strcmp(scan_buf, keyword)) {
- if (print_not_err) {
-
- return(DB_ERROR);
- }
-
- printf("Error in InnoDB booting: keyword %s not found\n",
- keyword);
- printf("from the initfile!\n");
-
- return(DB_ERROR);
- }
-skip_keyword:
- if (num_val == NULL && str_buf == NULL) {
-
- return(DB_SUCCESS);
- }
-
- ret = fscanf(initfile, "%9999s", scan_buf);
-
- if (ret == EOF || ret == 0) {
- if (print_not_err) {
-
- return(DB_ERROR);
- }
-
- printf(
- "Error in InnoDB booting: could not read first value after %s\n",
- keyword);
- printf("from the initfile!\n");
-
- return(DB_ERROR);
- }
-
- if (str_buf) {
- ut_memcpy(str_buf, scan_buf, 10000);
-
- printf("init keyword %s value %s read\n", keyword, str_buf);
-
- if (!num_val) {
- return(DB_SUCCESS);
- }
-
- ret = fscanf(initfile, "%9999s", scan_buf);
-
- if (ret == EOF || ret == 0) {
-
- if (print_not_err) {
-
- return(DB_ERROR);
- }
-
- printf(
- "Error in InnoDB booting: could not read second value after %s\n",
- keyword);
- printf("from the initfile!\n");
-
- return(DB_ERROR);
- }
- }
-
- if (ut_strlen(scan_buf) > 9) {
-
- if (print_not_err) {
-
- return(DB_ERROR);
- }
-
- printf(
- "Error in InnoDB booting: numerical value too big after %s\n",
- keyword);
- printf("in the initfile!\n");
-
- return(DB_ERROR);
- }
-
- *num_val = (ulint)atoi(scan_buf);
-
- if (*num_val >= 1000000000) {
-
- if (print_not_err) {
-
- return(DB_ERROR);
- }
-
- printf(
- "Error in InnoDB booting: numerical value too big after %s\n",
- keyword);
- printf("in the initfile!\n");
-
- return(DB_ERROR);
- }
-
- printf("init keyword %s value %lu read\n", keyword, *num_val);
-
- return(DB_SUCCESS);
-}
-
-/*************************************************************************
-Reads keywords and values from an initfile. */
-
-ulint
-srv_read_initfile(
-/*==============*/
- /* out: DB_SUCCESS or error code */
- FILE* initfile) /* in: file pointer */
-{
- char str_buf[10000];
- ulint n;
- ulint i;
- ulint ulint_val;
- ulint val1;
- ulint val2;
- ulint err;
-
- err = srv_read_init_val(initfile, "INNOBASE_DATA_HOME_DIR",
- str_buf, NULL, FALSE);
- if (err != DB_SUCCESS) return(err);
-
- srv_data_home = ut_malloc(ut_strlen(str_buf) + 1);
- ut_memcpy(srv_data_home, str_buf, ut_strlen(str_buf) + 1);
-
- err = srv_read_init_val(initfile,"TABLESPACE_NUMBER_OF_DATA_FILES",
- NULL, &n, FALSE);
- if (err != DB_SUCCESS) return(err);
-
- srv_n_data_files = n;
-
- srv_data_file_names = ut_malloc(n * sizeof(char*));
- srv_data_file_sizes = ut_malloc(n * sizeof(ulint));
-
- for (i = 0; i < n; i++) {
- err = srv_read_init_val(initfile,
- "DATA_FILE_PATH_AND_SIZE_MB",
- str_buf, &ulint_val, FALSE);
- if (err != DB_SUCCESS) return(err);
-
- srv_data_file_names[i] = ut_malloc(ut_strlen(str_buf) + 1);
- ut_memcpy(srv_data_file_names[i], str_buf,
- ut_strlen(str_buf) + 1);
- srv_data_file_sizes[i] = ulint_val
- * ((1024 * 1024) / UNIV_PAGE_SIZE);
- }
-
- err = srv_read_init_val(initfile,
- "NUMBER_OF_MIRRORED_LOG_GROUPS", NULL,
- &srv_n_log_groups, FALSE);
- if (err != DB_SUCCESS) return(err);
-
- err = srv_read_init_val(initfile,
- "NUMBER_OF_LOG_FILES_IN_GROUP", NULL,
- &srv_n_log_files, FALSE);
- if (err != DB_SUCCESS) return(err);
-
- err = srv_read_init_val(initfile, "LOG_FILE_SIZE_KB", NULL,
- &srv_log_file_size, FALSE);
- if (err != DB_SUCCESS) return(err);
-
- srv_log_file_size = srv_log_file_size / (UNIV_PAGE_SIZE / 1024);
-
- srv_log_group_home_dirs = ut_malloc(srv_n_log_files * sizeof(char*));
-
- for (i = 0; i < srv_n_log_groups; i++) {
-
- err = srv_read_init_val(initfile,
- "INNOBASE_LOG_GROUP_HOME_DIR",
- str_buf, NULL, FALSE);
- if (err != DB_SUCCESS) return(err);
-
- srv_log_group_home_dirs[i] = ut_malloc(ut_strlen(str_buf) + 1);
- ut_memcpy(srv_log_group_home_dirs[i], str_buf,
- ut_strlen(str_buf) + 1);
- }
-
- err = srv_read_init_val(initfile, "INNOBASE_LOG_ARCH_DIR",
- str_buf, NULL, FALSE);
- if (err != DB_SUCCESS) return(err);
-
- srv_arch_dir = ut_malloc(ut_strlen(str_buf) + 1);
- ut_memcpy(srv_arch_dir, str_buf, ut_strlen(str_buf) + 1);
-
- err = srv_read_init_val(initfile, "LOG_ARCHIVE_ON(1/0)", NULL,
- &srv_log_archive_on, FALSE);
- if (err != DB_SUCCESS) return(err);
-
- err = srv_read_init_val(initfile, "LOG_BUFFER_SIZE_KB", NULL,
- &srv_log_buffer_size, FALSE);
- if (err != DB_SUCCESS) return(err);
-
- srv_log_buffer_size = srv_log_buffer_size / (UNIV_PAGE_SIZE / 1024);
-
- err = srv_read_init_val(initfile, "FLUSH_LOG_AT_TRX_COMMIT(1/0)", NULL,
- &srv_flush_log_at_trx_commit, FALSE);
- if (err != DB_SUCCESS) return(err);
-
- err = srv_read_init_val(initfile, "BUFFER_POOL_SIZE_MB", NULL,
- &srv_pool_size, FALSE);
- if (err != DB_SUCCESS) return(err);
-
- srv_pool_size = srv_pool_size * ((1024 * 1024) / UNIV_PAGE_SIZE);
-
- err = srv_read_init_val(initfile, "ADDITIONAL_MEM_POOL_SIZE_MB", NULL,
- &srv_mem_pool_size, FALSE);
- if (err != DB_SUCCESS) return(err);
-
- srv_mem_pool_size = srv_mem_pool_size * 1024 * 1024;
-
- srv_lock_table_size = 20 * srv_pool_size;
-
- err = srv_read_init_val(initfile, "NUMBER_OF_FILE_IO_THREADS", NULL,
- &srv_n_file_io_threads, FALSE);
- if (err != DB_SUCCESS) return(err);
-
- err = srv_read_init_val(initfile, "SRV_RECOVER_FROM_BACKUP",
- NULL, NULL, TRUE);
- if (err == DB_SUCCESS) {
- srv_archive_recovery = TRUE;
- srv_archive_recovery_limit_lsn = ut_dulint_max;
-
- err = srv_read_init_val(initfile, NULL, NULL, &val1, TRUE);
- err = srv_read_init_val(initfile, NULL, NULL, &val2, TRUE);
-
- if (err == DB_SUCCESS) {
- srv_archive_recovery_limit_lsn =
- ut_dulint_create(val1, val2);
- }
- }
-
- /* err = srv_read_init_val(initfile,
- "SYNC_NUMBER_OF_SPIN_WAIT_ROUNDS", NULL,
- &srv_n_spin_wait_rounds);
-
- err = srv_read_init_val(initfile, "SYNC_SPIN_WAIT_DELAY", NULL,
- &srv_spin_wait_delay); */
- return(DB_SUCCESS);
-}
-
-/*************************************************************************
-Reads keywords and a values from an initfile. In case of an error, exits
-from the process. */
-
-void
-srv_read_initfile(
-/*==============*/
- FILE* initfile) /* in: file pointer */
-{
- char str_buf[10000];
- ulint ulint_val;
-
- srv_read_init_val(initfile, FALSE, "SRV_ENDPOINT_NAME", str_buf,
- &ulint_val);
- ut_a(ut_strlen(str_buf) < COM_MAX_ADDR_LEN);
-
- ut_memcpy(srv_endpoint_name, str_buf, COM_MAX_ADDR_LEN);
-
- srv_read_init_val(initfile, TRUE, "SRV_N_COM_THREADS", str_buf,
- &srv_n_com_threads);
-
- srv_read_init_val(initfile, TRUE, "SRV_N_WORKER_THREADS", str_buf,
- &srv_n_worker_threads);
-
- srv_read_init_val(initfile, TRUE, "SYNC_N_SPIN_WAIT_ROUNDS", str_buf,
- &srv_n_spin_wait_rounds);
-
- srv_read_init_val(initfile, TRUE, "SYNC_SPIN_WAIT_DELAY", str_buf,
- &srv_spin_wait_delay);
-
- srv_read_init_val(initfile, TRUE, "THREAD_PRIORITY_BOOST", str_buf,
- &srv_priority_boost);
-
- srv_read_init_val(initfile, TRUE, "N_SPACES", str_buf, &srv_n_spaces);
- srv_read_init_val(initfile, TRUE, "N_FILES", str_buf, &srv_n_files);
- srv_read_init_val(initfile, TRUE, "FILE_SIZE", str_buf,
- &srv_file_size);
-
- srv_read_init_val(initfile, TRUE, "N_LOG_GROUPS", str_buf,
- &srv_n_log_groups);
- srv_read_init_val(initfile, TRUE, "N_LOG_FILES", str_buf,
- &srv_n_log_files);
- srv_read_init_val(initfile, TRUE, "LOG_FILE_SIZE", str_buf,
- &srv_log_file_size);
- srv_read_init_val(initfile, TRUE, "LOG_ARCHIVE_ON", str_buf,
- &srv_log_archive_on);
- srv_read_init_val(initfile, TRUE, "LOG_BUFFER_SIZE", str_buf,
- &srv_log_buffer_size);
- srv_read_init_val(initfile, TRUE, "FLUSH_LOG_AT_TRX_COMMIT", str_buf,
- &srv_flush_log_at_trx_commit);
-
-
- srv_read_init_val(initfile, TRUE, "POOL_SIZE", str_buf,
- &srv_pool_size);
- srv_read_init_val(initfile, TRUE, "MEM_POOL_SIZE", str_buf,
- &srv_mem_pool_size);
- srv_read_init_val(initfile, TRUE, "LOCK_TABLE_SIZE", str_buf,
- &srv_lock_table_size);
-
- srv_read_init_val(initfile, TRUE, "SIM_DISK_WAIT_PCT", str_buf,
- &srv_sim_disk_wait_pct);
-
- srv_read_init_val(initfile, TRUE, "SIM_DISK_WAIT_LEN", str_buf,
- &srv_sim_disk_wait_len);
-
- srv_read_init_val(initfile, TRUE, "SIM_DISK_WAIT_BY_YIELD", str_buf,
- &srv_sim_disk_wait_by_yield);
-
- srv_read_init_val(initfile, TRUE, "SIM_DISK_WAIT_BY_WAIT", str_buf,
- &srv_sim_disk_wait_by_wait);
-
- srv_read_init_val(initfile, TRUE, "MEASURE_CONTENTION", str_buf,
- &srv_measure_contention);
-
- srv_read_init_val(initfile, TRUE, "MEASURE_BY_SPIN", str_buf,
- &srv_measure_by_spin);
-
-
- srv_read_init_val(initfile, TRUE, "PRINT_THREAD_RELEASES", str_buf,
- &srv_print_thread_releases);
-
- srv_read_init_val(initfile, TRUE, "PRINT_LOCK_WAITS", str_buf,
- &srv_print_lock_waits);
- if (srv_print_lock_waits) {
- lock_print_waits = TRUE;
- }
-
- srv_read_init_val(initfile, TRUE, "PRINT_BUF_IO", str_buf,
- &srv_print_buf_io);
- if (srv_print_buf_io) {
- buf_debug_prints = TRUE;
- }
-
- srv_read_init_val(initfile, TRUE, "PRINT_LOG_IO", str_buf,
- &srv_print_log_io);
- if (srv_print_log_io) {
- log_debug_writes = TRUE;
- }
-
- srv_read_init_val(initfile, TRUE, "PRINT_PARSED_SQL", str_buf,
- &srv_print_parsed_sql);
- if (srv_print_parsed_sql) {
- pars_print_lexed = TRUE;
- }
-
- srv_read_init_val(initfile, TRUE, "PRINT_LATCH_WAITS", str_buf,
- &srv_print_latch_waits);
-
- srv_read_init_val(initfile, TRUE, "TEST_EXTRA_MUTEXES", str_buf,
- &srv_test_extra_mutexes);
- srv_read_init_val(initfile, TRUE, "TEST_NOCACHE", str_buf,
- &srv_test_nocache);
- srv_read_init_val(initfile, TRUE, "TEST_CACHE_EVICT", str_buf,
- &srv_test_cache_evict);
-
- srv_read_init_val(initfile, TRUE, "TEST_SYNC", str_buf,
- &srv_test_sync);
- srv_read_init_val(initfile, TRUE, "TEST_N_THREADS", str_buf,
- &srv_test_n_threads);
- srv_read_init_val(initfile, TRUE, "TEST_N_LOOPS", str_buf,
- &srv_test_n_loops);
- srv_read_init_val(initfile, TRUE, "TEST_N_FREE_RNDS", str_buf,
- &srv_test_n_free_rnds);
- srv_read_init_val(initfile, TRUE, "TEST_N_RESERVED_RNDS", str_buf,
- &srv_test_n_reserved_rnds);
- srv_read_init_val(initfile, TRUE, "TEST_N_MUTEXES", str_buf,
- &srv_test_n_mutexes);
- srv_read_init_val(initfile, TRUE, "TEST_ARRAY_SIZE", str_buf,
- &srv_test_array_size);
-}
-#endif
-
/*************************************************************************
Initializes the server. */
diff --git a/innobase/trx/trx0trx.c b/innobase/trx/trx0trx.c
index 47c39290b15..cbe7d8a648c 100644
--- a/innobase/trx/trx0trx.c
+++ b/innobase/trx/trx0trx.c
@@ -1147,8 +1147,6 @@ trx_sig_send(
ut_a(0);
- /* sess_raise_error_low(trx, 0, 0, NULL, NULL, NULL, NULL,
- "Incompatible signal"); */
return(FALSE);
}
@@ -1197,9 +1195,6 @@ trx_sig_send(
in the error state: */
ut_a(0);
-
- sess_raise_error_low(trx, 0, 0, NULL, NULL, NULL, NULL,
- (char *) "Signal from another session, or a break execution signal");
}
/* If there were no other signals ahead in the queue, try to start
diff --git a/innobase/usr/usr0sess.c b/innobase/usr/usr0sess.c
index 0335c8046e2..c024a51b0f4 100644
--- a/innobase/usr/usr0sess.c
+++ b/innobase/usr/usr0sess.c
@@ -29,6 +29,13 @@ Created 6/25/1996 Heikki Tuuri
sess_sys_t* sess_sys = NULL;
/*************************************************************************
+Closes a session, freeing the memory occupied by it. */
+static
+void
+sess_close(
+/*=======*/
+ sess_t* sess); /* in, own: session object */
+/*************************************************************************
Communicates an error message to the client. If sess->client_waits is not
TRUE, puts the session to error state and does not try to send the error
message. */
@@ -85,42 +92,6 @@ sess_cli_msg_set_sess(
mach_write_to_4(str + SESS_CLI_MSG_SESS_ID_CHECK, fold);
}
-/*************************************************************************
-Returns the session to which a message from a client is addressed.
-NOTE: this function does not assume that the message is uncorrupted. */
-static
-sess_t*
-sess_cli_msg_get_sess(
-/*==================*/
- /* out: session, NULL if not found */
- byte* str, /* in: message string */
- ulint len) /* in: message string length */
-{
- sess_t* sess;
- ulint fold;
- dulint id;
-
- ut_ad(mutex_own(&kernel_mutex));
-
- if (len < SESS_CLI_MSG_SESS_ID_CHECK + 4) {
-
- return(NULL);
- }
-
- id = mach_read_from_8(str + SESS_CLI_MSG_SESS_ID);
-
- fold = sess_id_fold(id);
-
- if (fold != mach_read_from_4(str + SESS_CLI_MSG_SESS_ID_CHECK)) {
-
- return(NULL);
- }
-
- HASH_SEARCH(hash, sess_sys->hash, fold, sess,
- UT_DULINT_EQ(id, sess->id));
- return(sess);
-}
-
/***************************************************************************
Decrements the reference count of a session and closes it, if desired. */
UNIV_INLINE
@@ -311,6 +282,7 @@ sess_open(
/*************************************************************************
Closes a session, freeing the memory occupied by it. */
+static
void
sess_close(
/*=======*/
@@ -595,330 +567,6 @@ sess_error_low(
NULL, NULL, NULL);
}
-/*************************************************************************
-Raises an SQL error. */
-
-void
-sess_raise_error_low(
-/*=================*/
- trx_t* trx, /* in: transaction */
- ulint err_no, /* in: error number */
- ulint type, /* in: more info of the error, or 0 */
- dict_table_t* table, /* in: dictionary table or NULL */
- dict_index_t* index, /* in: table index or NULL */
- dtuple_t* tuple, /* in: tuple to insert or NULL */
- rec_t* rec, /* in: record or NULL */
- char* err_str)/* in: arbitrary null-terminated error string,
- or NULL */
-{
- char* str;
- ulint len;
-
- ut_ad(mutex_own(&kernel_mutex));
-
- str = mem_alloc(64000);
-
- len = 0;
-
- len += sprintf(str + len, "Error number: %lu", err_no);
-
- if (type) {
- len += sprintf(str + len, ", type: %lu", type);
- }
-
- if (table) {
- len += sprintf(str + len, ", table: %s", table->name);
- }
-
- if (index) {
- len += sprintf(str + len, ", index: %s", index->name);
- }
-
- if (tuple) {
- len += sprintf(str + len, ", tuple:");
- len += dtuple_sprintf(str + len, 8192, tuple);
- }
-
- if (rec) {
- len += sprintf(str + len, ", record:");
- len += rec_sprintf(str + len, 8192, rec);
- }
-
- if (err_str) {
- len += sprintf(str + len, ", %s", err_str);
- }
-
- str[len] = '\0';
-
- ut_a(len < 64000);
-
- if (trx->sess) {
- sess_error_low(trx->sess, err_no, str);
- } else {
- mem_free(str);
- }
-}
-
-/***************************************************************************
-Processes a client message which is part of a bigger message. */
-static
-ibool
-sess_receive_msg_part(
-/*==================*/
- /* TRUE if message completed */
- sess_t* sess, /* in: session */
- byte* str, /* in: message string */
- ulint len) /* in: message length */
-{
- ulint cont;
-
- cont = sess_cli_msg_get_continue(str);
-
- ut_ad(cont != SESS_MSG_SINGLE_PART);
-
- if (cont == SESS_MSG_FIRST_PART) {
- if (sess->big_msg) {
- sess_error_low(sess, SESS_ERR_MSG_LOST, NULL);
-
- return(FALSE);
- }
-
- sess->big_msg_size = 1024 * sess_cli_msg_get_cont_size(str);
- sess->big_msg = mem_alloc(sess->big_msg_size);
-
- if (sess->big_msg == NULL) {
- sess_error_low(sess, SESS_ERR_OUT_OF_MEMORY, NULL);
-
- return(FALSE);
- }
-
- ut_memcpy(sess->big_msg, str, len);
- sess->big_msg_len = len;
-
- return(FALSE);
- } else {
- if (sess->big_msg == NULL) {
- sess_error_low(sess, SESS_ERR_MSG_LOST, NULL);
-
- return(FALSE);
- }
-
- ut_memcpy(sess->big_msg + sess->big_msg_len,
- str + SESS_CLI_MSG_DATA, len - SESS_CLI_MSG_DATA);
-
- sess->big_msg_len += len - SESS_CLI_MSG_DATA;
-
- if (cont == SESS_MSG_MIDDLE_PART) {
-
- return(FALSE);
- }
-
- return(TRUE);
- }
-}
-
-/***************************************************************************
-Processes a client message which requires SQL parsing. This function decodes
-the client message built in SQLPrepare. NOTE: The kernel mutex is temporarily
-released within this function. */
-static
-void
-sess_receive_prepare(
-/*=================*/
- sess_t* sess, /* in: session */
- byte* cli_msg,/* in: client message */
- ulint len) /* in: message length */
-{
- dulint error_count;
- que_t* graph;
- byte msg[ODBC_DATAGRAM_SIZE];
-
- UT_NOT_USED(len);
-
- ut_ad(mutex_own(&kernel_mutex));
-
- error_count = sess->error_count;
-
- /* Make sure the session object is not freed during the parsing */
-
- sess_refer_count_inc(sess);
-
- /* We release the kernel mutex before parsing the command: this is
- to reduce contention on the kernel mutex */
-
- mutex_exit(&kernel_mutex);
-
-/* printf("To parse query %s\n", (char*)(cli_msg + SESS_CLI_MSG_DATA)); */
-
- graph = pars_sql((char*)(cli_msg + SESS_CLI_MSG_DATA));
-
- mutex_enter(&kernel_mutex);
-
- if (graph == NULL) {
- /* Error in parsing */
- sess_error_low(sess, SESS_ERR_SQL_ERROR, NULL);
-
- sess_refer_count_dec(sess);
-
- ut_error;
-
- return;
- }
-
- if (!UT_DULINT_EQ(error_count, sess->error_count)) {
-
- /* An error, or an asyncronous signal on the session happened
- when the kernel mutex was not reserved: discard graph */
-
- graph->state = QUE_FORK_INVALID;
-
- que_graph_try_free(graph);
-
- sess_refer_count_dec(sess);
-
- ut_error;
-
- return;
- }
-
- UT_LIST_ADD_LAST(graphs, sess->graphs, graph);
-
- graph->id = sess->next_graph_id;
- sess->next_graph_id++;
-
- /* Tell the client that the preparation succeeded and communicate info
- about the possible query parameters: the message will be decoded in
- SQLPrepare */
-
- ut_ad(sess->client_waits);
-
- sess_srv_msg_init(sess, msg, SESS_SRV_SUCCESS);
-
- mach_write_to_4(msg + SESS_SRV_MSG_DATA, graph->id);
-
- mutex_exit(&kernel_mutex);
-
- len = pars_write_query_param_info(msg + SESS_SRV_MSG_DATA + 4, graph);
-
- mutex_enter(&kernel_mutex);
-
- sess_srv_msg_send(sess, msg, SESS_SRV_MSG_DATA + 4 + len,
- SESS_RELEASE_KERNEL);
- sess_refer_count_dec(sess);
-}
-
-/***************************************************************************
-Processes a client message which does not require SQL parsing. This function
-decodes the client message built in SQLExecute. */
-static
-void
-sess_receive_command(
-/*=================*/
- sess_t* sess, /* in: session */
- byte* cli_msg,/* in: client message */
- ulint len, /* in: message length */
- ulint type) /* in: message type */
-{
- proc_node_t* proc_node;
- call_node_t* call_node;
- dict_proc_t* dict_proc;
- que_thr_t* thr;
- que_t* graph;
- ulint stat_id;
-
- UT_NOT_USED(len);
- UT_NOT_USED(type);
-
- ut_ad(mutex_own(&kernel_mutex));
-
- sess->client_waits = TRUE;
-
- stat_id = mach_read_from_4(cli_msg + SESS_CLI_MSG_DATA);
-
- /* Look for the statement from the list of query graphs */
-
- graph = UT_LIST_GET_FIRST(sess->graphs);
-
- while (graph != NULL) {
-
- if (graph->id == stat_id) {
-
- break;
- }
-
- graph = UT_LIST_GET_NEXT(graphs, graph);
- }
-
- if (graph == NULL) {
- /* Could not find the right graph: error */
- sess_error_low(sess, SESS_ERR_STMT_NOT_FOUND, NULL);
-
- return;
- }
-
- if (graph->state != QUE_FORK_COMMAND_WAIT) {
- sess_error_low(sess, SESS_ERR_STMT_NOT_READY, NULL);
-
- return;
- }
-
-/* printf("To execute stat %lu\n", stat_id); */
-
- if (graph->fork_type == QUE_FORK_PROCEDURE_CALL) {
- /* It is a stored procedure call: retrieve a parsed copy of
- the procedure from the dictionary cache */
-
- mutex_exit(&kernel_mutex);
-
- call_node = que_fork_get_child(graph);
-
- graph = dict_procedure_reserve_parsed_copy(
- call_node->procedure_def);
- graph->trx = sess->trx;
-
- /* Retrieve the procedure input parameters from the message */
-
- pars_proc_read_input_params_from_buf(graph,
- cli_msg + SESS_CLI_MSG_DATA + 4);
- mutex_enter(&kernel_mutex);
- } else {
- /* It is a create procedure command: add the procedure to the
- dictionary cache */
- ut_ad(graph->fork_type == QUE_FORK_PROCEDURE);
-
- mutex_exit(&kernel_mutex);
-
- proc_node = que_fork_get_child(graph);
-
- dict_proc = dict_mem_procedure_create(proc_node->proc_id->name,
- proc_node->sym_tab->sql_string,
- graph);
-
- dict_procedure_add_to_cache(dict_proc);
-
- mutex_enter(&kernel_mutex);
-
- sess_srv_msg_send_simple(sess, SESS_SRV_SUCCESS,
- SESS_RELEASE_KERNEL);
- return;
- }
-
- /* Choose a query thread for execution */
- thr = que_fork_start_command(graph, SESS_COMM_EXECUTE, 0);
-
- ut_ad(thr);
-
- sess->trx->graph = graph;
-
- mutex_exit(&kernel_mutex);
-
- /* Run query threads with the kernel mutex released */
-
- que_run_threads(thr);
-
- mutex_enter(&kernel_mutex);
-}
-
/***************************************************************************
When a command has been completed, this function sends the message about it
to the client. */
@@ -936,239 +584,3 @@ sess_command_completed_message(
SESS_RELEASE_KERNEL);
mutex_exit(&kernel_mutex);
}
-
-/***************************************************************************
-Processes a break message from the client. */
-static
-void
-sess_receive_break(
-/*===============*/
- sess_t* sess) /* in: session */
-{
- ut_ad(mutex_own(&kernel_mutex));
-
- /* Rollback the latest incomplete SQL statement */
-
- sess_error_low(sess, SESS_ERR_BREAK_BY_CLIENT, NULL);
-}
-
-/***************************************************************************
-Processes a message from a client. NOTE: Releases the kernel mutex temporarily
-when parsing an SQL string. */
-
-void
-sess_receive_msg_rel_kernel(
-/*========================*/
- sess_t* sess, /* in: session */
- byte* str, /* in: message string */
- ulint len) /* in: message length */
-{
- dulint msg_no;
- ulint msg_type;
- ulint cont;
- ibool is_big_msg = FALSE;
- ibool client_waited;
-
- ut_ad(mutex_own(&kernel_mutex));
- ut_ad(!sess->disconnecting);
-
- client_waited = sess->client_waits;
-
- sess->client_waits = TRUE;
-
- if (sess->state == SESS_ERROR) {
-
- /* Send a buffered error message */
- sess_srv_msg_send_error(sess);
-
- return;
- }
-
- if (FALSE == sess_cli_msg_check_consistency(str, len)) {
- /* Message from the client was corrupted */
-
- sess_error_low(sess, SESS_ERR_MSG_CORRUPTED, NULL);
-
- return;
- }
-
- msg_no = sess_cli_msg_get_msg_no(str);
-
- UT_DULINT_INC(sess->msgs_recv);
-
- if (!UT_DULINT_EQ(msg_no, sess->msgs_recv)) {
-
- sess_error_low(sess, SESS_ERR_MSG_LOST, NULL);
-
- sess->msgs_recv = msg_no;
-
- return;
- }
-
- msg_type = sess_cli_msg_get_type(str);
-
- if (msg_type == SESS_CLI_BREAK_EXECUTION) {
-
- sess_receive_break(sess);
-
- return;
- }
-
- if (client_waited) {
- /* Client sent an extraneous message which is not a break
- command: an error */
-
- sess_error_low(sess, SESS_ERR_EXTRANEOUS_MSG, NULL);
-
- return;
- }
-
- /*-----------------------------------------------------------*/
- /* Handle big messages */
-
- cont = sess_cli_msg_get_continue(str);
-
- if (cont == SESS_MSG_SINGLE_PART) {
- if (sess->big_msg) {
-
- sess_error_low(sess, SESS_ERR_MSG_LOST, NULL);
-
- return;
- }
- } else {
- ut_error; /* Not in use */
-
- is_big_msg = sess_receive_msg_part(sess, str, len);
-
- if (is_big_msg) {
- str = sess->big_msg;
- len = sess->big_msg_len;
- sess->big_msg = NULL;
- } else {
- return;
- }
- }
-
- /*-----------------------------------------------------------*/
- /* The session has received a complete message from the client */
-
- ut_ad(!UT_LIST_GET_FIRST((sess->trx)->signals));
-
- if (msg_type == SESS_CLI_PREPARE) {
- /* Note that the kernel mutex is temporarily released when
- the SQL string is parsed */
-
- sess_receive_prepare(sess, str, len);
- } else {
- /* Note that the kernel mutex is temporarily released when the
- command is executed */
-
- sess_receive_command(sess, str, len, msg_type);
- }
-
- if (is_big_msg) {
- mem_free(str);
- }
-}
-
-/***********************************************************************
-Opens a new connection and creates a session. */
-static
-ibool
-sess_open_connection(
-/*=================*/
- byte* str, /* in: message string */
- ulint len, /* in: string length */
- byte* addr, /* in: user address string */
- ulint alen) /* in: user address length */
-{
- dulint sess_id;
- sess_t* sess;
-
- sess_id = mach_read_from_8(str + SESS_CLI_MSG_SESS_ID);
-
- if (!(UT_DULINT_EQ(sess_id, ut_dulint_zero))
- || !(sess_cli_msg_get_type(str) == SESS_CLI_CONNECT)) {
-
- /* It is not a valid connect message */
-
- return(FALSE);
- }
-
- ut_a(len == SESS_CLI_MSG_DATA);
-
- sess = sess_open(srv_sys->endpoint, addr, alen);
-
- sess_srv_msg_send_simple(sess, SESS_SRV_ACCEPT_CONNECT,
- SESS_NOT_RELEASE_KERNEL);
- return(TRUE);
-}
-
-/***********************************************************************
-Starts a new connection and a session, or starts a query based on a client
-message. This is called by a SRV_COM thread. */
-
-void
-sess_process_cli_msg(
-/*=================*/
- byte* str, /* in: message string */
- ulint len, /* in: string length */
- byte* addr, /* in: address string */
- ulint alen) /* in: address length */
-{
- sess_t* sess;
- ibool success;
-
- UT_NOT_USED(addr);
- UT_NOT_USED(alen);
-
- mutex_enter(&kernel_mutex);
-
- sess = sess_cli_msg_get_sess(str, len);
-
- if (sess == NULL) {
- /* There was no matching session */
-
- if (sess_cli_msg_check_consistency(str, len)) {
-
- /* As the message is consistent, it may be a connect
- message */
-
- /* printf("%s\n", addr); */
-
- success = sess_open_connection(str, len, addr, alen);
-
- if (success) {
- mutex_exit(&kernel_mutex);
-
- return;
- }
- }
-
- /* Could not make sense of the message: write an error entry
- to the system error log */
-
- /* srv_err_log_insert(
- "MESSAGE SENT TO AN UNKNOWN SESSION");*/
- ut_error;
-
- mutex_exit(&kernel_mutex);
-
- return;
- }
-
- if (sess->disconnecting) {
-
- /* srv_err_log_insert(
- "MESSAGE SENT TO A DISCONNECTING SESSION");*/
- ut_error;
-
- mutex_exit(&kernel_mutex);
-
- return;
- }
-
- sess_receive_msg_rel_kernel(sess, str, len);
-
- mutex_exit(&kernel_mutex);
-}