mirror of
https://github.com/MariaDB/server.git
synced 2026-05-15 03:17:20 +02:00
move to storage/innobase
This commit is contained in:
parent
1645930d0b
commit
6d06fbbd1d
360 changed files with 0 additions and 0 deletions
1304
storage/innobase/include/api0api.h
Normal file
1304
storage/innobase/include/api0api.h
Normal file
File diff suppressed because it is too large
Load diff
78
storage/innobase/include/api0misc.h
Normal file
78
storage/innobase/include/api0misc.h
Normal file
|
|
@ -0,0 +1,78 @@
|
|||
/*****************************************************************************
|
||||
|
||||
Copyright (c) 2008, 2012, Oracle and/or its affiliates. All Rights Reserved.
|
||||
|
||||
This program is free software; you can redistribute it and/or modify it under
|
||||
the terms of the GNU General Public License as published by the Free Software
|
||||
Foundation; version 2 of the License.
|
||||
|
||||
This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
|
||||
FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License along with
|
||||
this program; if not, write to the Free Software Foundation, Inc.,
|
||||
51 Franklin Street, Suite 500, Boston, MA 02110-1335 USA
|
||||
|
||||
*****************************************************************************/
|
||||
|
||||
/**************************************************//**
|
||||
@file include/api0misc.h
|
||||
InnoDB Native API
|
||||
|
||||
3/20/2011 Jimmy Yang extracted from Embedded InnoDB
|
||||
2008 Created by Sunny Bains
|
||||
*******************************************************/
|
||||
|
||||
#ifndef api0misc_h
|
||||
#define api0misc_h
|
||||
|
||||
#include "univ.i"
|
||||
#include "os0file.h"
|
||||
#include "que0que.h"
|
||||
#include "trx0trx.h"
|
||||
|
||||
/** Whether binlog is enabled for applications using InnoDB APIs */
|
||||
extern my_bool ib_binlog_enabled;
|
||||
|
||||
/** Whether MySQL MDL is enabled for applications using InnoDB APIs */
|
||||
extern my_bool ib_mdl_enabled;
|
||||
|
||||
/** Whether InnoDB row lock is disabled for applications using InnoDB APIs */
|
||||
extern my_bool ib_disable_row_lock;
|
||||
|
||||
/** configure value for transaction isolation level */
|
||||
extern ulong ib_trx_level_setting;
|
||||
|
||||
/** configure value for background commit interval (in seconds) */
|
||||
extern ulong ib_bk_commit_interval;
|
||||
|
||||
/********************************************************************
|
||||
Handles user errors and lock waits detected by the database engine.
|
||||
@return TRUE if it was a lock wait and we should continue running
|
||||
the query thread */
|
||||
UNIV_INTERN
|
||||
ibool
|
||||
ib_handle_errors(
|
||||
/*=============*/
|
||||
dberr_t* new_err, /*!< out: possible new error
|
||||
encountered in lock wait, or if
|
||||
no new error, the value of
|
||||
trx->error_state at the entry of this
|
||||
function */
|
||||
trx_t* trx, /*!< in: transaction */
|
||||
que_thr_t* thr, /*!< in: query thread */
|
||||
trx_savept_t* savept); /*!< in: savepoint or NULL */
|
||||
|
||||
/*************************************************************************
|
||||
Sets a lock on a table.
|
||||
@return error code or DB_SUCCESS */
|
||||
UNIV_INTERN
|
||||
dberr_t
|
||||
ib_trx_lock_table_with_retry(
|
||||
/*=========================*/
|
||||
trx_t* trx, /*!< in/out: transaction */
|
||||
dict_table_t* table, /*!< in: table to lock */
|
||||
enum lock_mode mode); /*!< in: lock mode */
|
||||
|
||||
#endif /* api0misc_h */
|
||||
773
storage/innobase/include/btr0btr.h
Normal file
773
storage/innobase/include/btr0btr.h
Normal file
|
|
@ -0,0 +1,773 @@
|
|||
/*****************************************************************************
|
||||
|
||||
Copyright (c) 1994, 2013, Oracle and/or its affiliates. All Rights Reserved.
|
||||
Copyright (c) 2012, Facebook Inc.
|
||||
|
||||
This program is free software; you can redistribute it and/or modify it under
|
||||
the terms of the GNU General Public License as published by the Free Software
|
||||
Foundation; version 2 of the License.
|
||||
|
||||
This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
|
||||
FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License along with
|
||||
this program; if not, write to the Free Software Foundation, Inc.,
|
||||
51 Franklin Street, Suite 500, Boston, MA 02110-1335 USA
|
||||
|
||||
*****************************************************************************/
|
||||
|
||||
/**************************************************//**
|
||||
@file include/btr0btr.h
|
||||
The B-tree
|
||||
|
||||
Created 6/2/1994 Heikki Tuuri
|
||||
*******************************************************/
|
||||
|
||||
#ifndef btr0btr_h
|
||||
#define btr0btr_h
|
||||
|
||||
#include "univ.i"
|
||||
|
||||
#include "dict0dict.h"
|
||||
#include "data0data.h"
|
||||
#include "page0cur.h"
|
||||
#include "mtr0mtr.h"
|
||||
#include "btr0types.h"
|
||||
|
||||
#ifndef UNIV_HOTBACKUP
|
||||
/** Maximum record size which can be stored on a page, without using the
|
||||
special big record storage structure */
|
||||
#define BTR_PAGE_MAX_REC_SIZE (UNIV_PAGE_SIZE / 2 - 200)
|
||||
|
||||
/** @brief Maximum depth of a B-tree in InnoDB.
|
||||
|
||||
Note that this isn't a maximum as such; none of the tree operations
|
||||
avoid producing trees bigger than this. It is instead a "max depth
|
||||
that other code must work with", useful for e.g. fixed-size arrays
|
||||
that must store some information about each level in a tree. In other
|
||||
words: if a B-tree with bigger depth than this is encountered, it is
|
||||
not acceptable for it to lead to mysterious memory corruption, but it
|
||||
is acceptable for the program to die with a clear assert failure. */
|
||||
#define BTR_MAX_LEVELS 100
|
||||
|
||||
/** Latching modes for btr_cur_search_to_nth_level(). */
|
||||
enum btr_latch_mode {
|
||||
/** Search a record on a leaf page and S-latch it. */
|
||||
BTR_SEARCH_LEAF = RW_S_LATCH,
|
||||
/** (Prepare to) modify a record on a leaf page and X-latch it. */
|
||||
BTR_MODIFY_LEAF = RW_X_LATCH,
|
||||
/** Obtain no latches. */
|
||||
BTR_NO_LATCHES = RW_NO_LATCH,
|
||||
/** Start modifying the entire B-tree. */
|
||||
BTR_MODIFY_TREE = 33,
|
||||
/** Continue modifying the entire B-tree. */
|
||||
BTR_CONT_MODIFY_TREE = 34,
|
||||
/** Search the previous record. */
|
||||
BTR_SEARCH_PREV = 35,
|
||||
/** Modify the previous record. */
|
||||
BTR_MODIFY_PREV = 36
|
||||
};
|
||||
|
||||
/* BTR_INSERT, BTR_DELETE and BTR_DELETE_MARK are mutually exclusive. */
|
||||
|
||||
/** If this is ORed to btr_latch_mode, it means that the search tuple
|
||||
will be inserted to the index, at the searched position.
|
||||
When the record is not in the buffer pool, try to use the insert buffer. */
|
||||
#define BTR_INSERT 512
|
||||
|
||||
/** This flag ORed to btr_latch_mode says that we do the search in query
|
||||
optimization */
|
||||
#define BTR_ESTIMATE 1024
|
||||
|
||||
/** This flag ORed to BTR_INSERT says that we can ignore possible
|
||||
UNIQUE definition on secondary indexes when we decide if we can use
|
||||
the insert buffer to speed up inserts */
|
||||
#define BTR_IGNORE_SEC_UNIQUE 2048
|
||||
|
||||
/** Try to delete mark the record at the searched position using the
|
||||
insert/delete buffer when the record is not in the buffer pool. */
|
||||
#define BTR_DELETE_MARK 4096
|
||||
|
||||
/** Try to purge the record at the searched position using the insert/delete
|
||||
buffer when the record is not in the buffer pool. */
|
||||
#define BTR_DELETE 8192
|
||||
|
||||
/** In the case of BTR_SEARCH_LEAF or BTR_MODIFY_LEAF, the caller is
|
||||
already holding an S latch on the index tree */
|
||||
#define BTR_ALREADY_S_LATCHED 16384
|
||||
|
||||
#define BTR_LATCH_MODE_WITHOUT_FLAGS(latch_mode) \
|
||||
((latch_mode) & ~(BTR_INSERT \
|
||||
| BTR_DELETE_MARK \
|
||||
| BTR_DELETE \
|
||||
| BTR_ESTIMATE \
|
||||
| BTR_IGNORE_SEC_UNIQUE \
|
||||
| BTR_ALREADY_S_LATCHED))
|
||||
#endif /* UNIV_HOTBACKUP */
|
||||
|
||||
/**************************************************************//**
|
||||
Report that an index page is corrupted. */
|
||||
UNIV_INTERN
|
||||
void
|
||||
btr_corruption_report(
|
||||
/*==================*/
|
||||
const buf_block_t* block, /*!< in: corrupted block */
|
||||
const dict_index_t* index) /*!< in: index tree */
|
||||
UNIV_COLD __attribute__((nonnull));
|
||||
|
||||
/** Assert that a B-tree page is not corrupted.
|
||||
@param block buffer block containing a B-tree page
|
||||
@param index the B-tree index */
|
||||
#define btr_assert_not_corrupted(block, index) \
|
||||
if ((ibool) !!page_is_comp(buf_block_get_frame(block)) \
|
||||
!= dict_table_is_comp((index)->table)) { \
|
||||
btr_corruption_report(block, index); \
|
||||
ut_error; \
|
||||
}
|
||||
|
||||
#ifndef UNIV_HOTBACKUP
|
||||
#ifdef UNIV_BLOB_DEBUG
|
||||
# include "ut0rbt.h"
|
||||
/** An index->blobs entry for keeping track of off-page column references */
|
||||
struct btr_blob_dbg_t
|
||||
{
|
||||
unsigned blob_page_no:32; /*!< first BLOB page number */
|
||||
unsigned ref_page_no:32; /*!< referring page number */
|
||||
unsigned ref_heap_no:16; /*!< referring heap number */
|
||||
unsigned ref_field_no:10; /*!< referring field number */
|
||||
unsigned owner:1; /*!< TRUE if BLOB owner */
|
||||
unsigned always_owner:1; /*!< TRUE if always
|
||||
has been the BLOB owner;
|
||||
reset to TRUE on B-tree
|
||||
page splits and merges */
|
||||
unsigned del:1; /*!< TRUE if currently
|
||||
delete-marked */
|
||||
};
|
||||
|
||||
/**************************************************************//**
|
||||
Add a reference to an off-page column to the index->blobs map. */
|
||||
UNIV_INTERN
|
||||
void
|
||||
btr_blob_dbg_add_blob(
|
||||
/*==================*/
|
||||
const rec_t* rec, /*!< in: clustered index record */
|
||||
ulint field_no, /*!< in: number of off-page column */
|
||||
ulint page_no, /*!< in: start page of the column */
|
||||
dict_index_t* index, /*!< in/out: index tree */
|
||||
const char* ctx) /*!< in: context (for logging) */
|
||||
__attribute__((nonnull));
|
||||
/**************************************************************//**
|
||||
Display the references to off-page columns.
|
||||
This function is to be called from a debugger,
|
||||
for example when a breakpoint on ut_dbg_assertion_failed is hit. */
|
||||
UNIV_INTERN
|
||||
void
|
||||
btr_blob_dbg_print(
|
||||
/*===============*/
|
||||
const dict_index_t* index) /*!< in: index tree */
|
||||
__attribute__((nonnull));
|
||||
/**************************************************************//**
|
||||
Check that there are no references to off-page columns from or to
|
||||
the given page. Invoked when freeing or clearing a page.
|
||||
@return TRUE when no orphan references exist */
|
||||
UNIV_INTERN
|
||||
ibool
|
||||
btr_blob_dbg_is_empty(
|
||||
/*==================*/
|
||||
dict_index_t* index, /*!< in: index */
|
||||
ulint page_no) /*!< in: page number */
|
||||
__attribute__((nonnull, warn_unused_result));
|
||||
|
||||
/**************************************************************//**
|
||||
Modify the 'deleted' flag of a record. */
|
||||
UNIV_INTERN
|
||||
void
|
||||
btr_blob_dbg_set_deleted_flag(
|
||||
/*==========================*/
|
||||
const rec_t* rec, /*!< in: record */
|
||||
dict_index_t* index, /*!< in/out: index */
|
||||
const ulint* offsets,/*!< in: rec_get_offs(rec, index) */
|
||||
ibool del) /*!< in: TRUE=deleted, FALSE=exists */
|
||||
__attribute__((nonnull));
|
||||
/**************************************************************//**
|
||||
Change the ownership of an off-page column. */
|
||||
UNIV_INTERN
|
||||
void
|
||||
btr_blob_dbg_owner(
|
||||
/*===============*/
|
||||
const rec_t* rec, /*!< in: record */
|
||||
dict_index_t* index, /*!< in/out: index */
|
||||
const ulint* offsets,/*!< in: rec_get_offs(rec, index) */
|
||||
ulint i, /*!< in: ith field in rec */
|
||||
ibool own) /*!< in: TRUE=owned, FALSE=disowned */
|
||||
__attribute__((nonnull));
|
||||
/** Assert that there are no BLOB references to or from the given page. */
|
||||
# define btr_blob_dbg_assert_empty(index, page_no) \
|
||||
ut_a(btr_blob_dbg_is_empty(index, page_no))
|
||||
#else /* UNIV_BLOB_DEBUG */
|
||||
# define btr_blob_dbg_add_blob(rec, field_no, page, index, ctx) ((void) 0)
|
||||
# define btr_blob_dbg_set_deleted_flag(rec, index, offsets, del)((void) 0)
|
||||
# define btr_blob_dbg_owner(rec, index, offsets, i, val) ((void) 0)
|
||||
# define btr_blob_dbg_assert_empty(index, page_no) ((void) 0)
|
||||
#endif /* UNIV_BLOB_DEBUG */
|
||||
|
||||
/**************************************************************//**
|
||||
Gets the root node of a tree and x-latches it.
|
||||
@return root page, x-latched */
|
||||
UNIV_INTERN
|
||||
page_t*
|
||||
btr_root_get(
|
||||
/*=========*/
|
||||
const dict_index_t* index, /*!< in: index tree */
|
||||
mtr_t* mtr) /*!< in: mtr */
|
||||
__attribute__((nonnull));
|
||||
|
||||
/**************************************************************//**
|
||||
Checks and adjusts the root node of a tree during IMPORT TABLESPACE.
|
||||
@return error code, or DB_SUCCESS */
|
||||
UNIV_INTERN
|
||||
dberr_t
|
||||
btr_root_adjust_on_import(
|
||||
/*======================*/
|
||||
const dict_index_t* index) /*!< in: index tree */
|
||||
__attribute__((nonnull, warn_unused_result));
|
||||
|
||||
/**************************************************************//**
|
||||
Gets the height of the B-tree (the level of the root, when the leaf
|
||||
level is assumed to be 0). The caller must hold an S or X latch on
|
||||
the index.
|
||||
@return tree height (level of the root) */
|
||||
UNIV_INTERN
|
||||
ulint
|
||||
btr_height_get(
|
||||
/*===========*/
|
||||
dict_index_t* index, /*!< in: index tree */
|
||||
mtr_t* mtr) /*!< in/out: mini-transaction */
|
||||
__attribute__((nonnull, warn_unused_result));
|
||||
/**************************************************************//**
|
||||
Gets a buffer page and declares its latching order level. */
|
||||
UNIV_INLINE
|
||||
buf_block_t*
|
||||
btr_block_get_func(
|
||||
/*===============*/
|
||||
ulint space, /*!< in: space id */
|
||||
ulint zip_size, /*!< in: compressed page size in bytes
|
||||
or 0 for uncompressed pages */
|
||||
ulint page_no, /*!< in: page number */
|
||||
ulint mode, /*!< in: latch mode */
|
||||
const char* file, /*!< in: file name */
|
||||
ulint line, /*!< in: line where called */
|
||||
# ifdef UNIV_SYNC_DEBUG
|
||||
const dict_index_t* index, /*!< in: index tree, may be NULL
|
||||
if it is not an insert buffer tree */
|
||||
# endif /* UNIV_SYNC_DEBUG */
|
||||
mtr_t* mtr); /*!< in/out: mini-transaction */
|
||||
# ifdef UNIV_SYNC_DEBUG
|
||||
/** Gets a buffer page and declares its latching order level.
|
||||
@param space tablespace identifier
|
||||
@param zip_size compressed page size in bytes or 0 for uncompressed pages
|
||||
@param page_no page number
|
||||
@param mode latch mode
|
||||
@param index index tree, may be NULL if not the insert buffer tree
|
||||
@param mtr mini-transaction handle
|
||||
@return the block descriptor */
|
||||
# define btr_block_get(space,zip_size,page_no,mode,index,mtr) \
|
||||
btr_block_get_func(space,zip_size,page_no,mode, \
|
||||
__FILE__,__LINE__,index,mtr)
|
||||
# else /* UNIV_SYNC_DEBUG */
|
||||
/** Gets a buffer page and declares its latching order level.
|
||||
@param space tablespace identifier
|
||||
@param zip_size compressed page size in bytes or 0 for uncompressed pages
|
||||
@param page_no page number
|
||||
@param mode latch mode
|
||||
@param idx index tree, may be NULL if not the insert buffer tree
|
||||
@param mtr mini-transaction handle
|
||||
@return the block descriptor */
|
||||
# define btr_block_get(space,zip_size,page_no,mode,idx,mtr) \
|
||||
btr_block_get_func(space,zip_size,page_no,mode,__FILE__,__LINE__,mtr)
|
||||
# endif /* UNIV_SYNC_DEBUG */
|
||||
/** Gets a buffer page and declares its latching order level.
|
||||
@param space tablespace identifier
|
||||
@param zip_size compressed page size in bytes or 0 for uncompressed pages
|
||||
@param page_no page number
|
||||
@param mode latch mode
|
||||
@param idx index tree, may be NULL if not the insert buffer tree
|
||||
@param mtr mini-transaction handle
|
||||
@return the uncompressed page frame */
|
||||
# define btr_page_get(space,zip_size,page_no,mode,idx,mtr) \
|
||||
buf_block_get_frame(btr_block_get(space,zip_size,page_no,mode,idx,mtr))
|
||||
#endif /* !UNIV_HOTBACKUP */
|
||||
/**************************************************************//**
|
||||
Gets the index id field of a page.
|
||||
@return index id */
|
||||
UNIV_INLINE
|
||||
index_id_t
|
||||
btr_page_get_index_id(
|
||||
/*==================*/
|
||||
const page_t* page) /*!< in: index page */
|
||||
__attribute__((nonnull, pure, warn_unused_result));
|
||||
#ifndef UNIV_HOTBACKUP
|
||||
/********************************************************//**
|
||||
Gets the node level field in an index page.
|
||||
@return level, leaf level == 0 */
|
||||
UNIV_INLINE
|
||||
ulint
|
||||
btr_page_get_level_low(
|
||||
/*===================*/
|
||||
const page_t* page) /*!< in: index page */
|
||||
__attribute__((nonnull, pure, warn_unused_result));
|
||||
#define btr_page_get_level(page, mtr) btr_page_get_level_low(page)
|
||||
/********************************************************//**
|
||||
Gets the next index page number.
|
||||
@return next page number */
|
||||
UNIV_INLINE
|
||||
ulint
|
||||
btr_page_get_next(
|
||||
/*==============*/
|
||||
const page_t* page, /*!< in: index page */
|
||||
mtr_t* mtr) /*!< in: mini-transaction handle */
|
||||
__attribute__((nonnull, warn_unused_result));
|
||||
/********************************************************//**
|
||||
Gets the previous index page number.
|
||||
@return prev page number */
|
||||
UNIV_INLINE
|
||||
ulint
|
||||
btr_page_get_prev(
|
||||
/*==============*/
|
||||
const page_t* page, /*!< in: index page */
|
||||
mtr_t* mtr) /*!< in: mini-transaction handle */
|
||||
__attribute__((nonnull, warn_unused_result));
|
||||
/*************************************************************//**
|
||||
Gets pointer to the previous user record in the tree. It is assumed
|
||||
that the caller has appropriate latches on the page and its neighbor.
|
||||
@return previous user record, NULL if there is none */
|
||||
UNIV_INTERN
|
||||
rec_t*
|
||||
btr_get_prev_user_rec(
|
||||
/*==================*/
|
||||
rec_t* rec, /*!< in: record on leaf level */
|
||||
mtr_t* mtr) /*!< in: mtr holding a latch on the page, and if
|
||||
needed, also to the previous page */
|
||||
__attribute__((nonnull, warn_unused_result));
|
||||
/*************************************************************//**
|
||||
Gets pointer to the next user record in the tree. It is assumed
|
||||
that the caller has appropriate latches on the page and its neighbor.
|
||||
@return next user record, NULL if there is none */
|
||||
UNIV_INTERN
|
||||
rec_t*
|
||||
btr_get_next_user_rec(
|
||||
/*==================*/
|
||||
rec_t* rec, /*!< in: record on leaf level */
|
||||
mtr_t* mtr) /*!< in: mtr holding a latch on the page, and if
|
||||
needed, also to the next page */
|
||||
__attribute__((nonnull, warn_unused_result));
|
||||
/**************************************************************//**
|
||||
Releases the latch on a leaf page and bufferunfixes it. */
|
||||
UNIV_INLINE
|
||||
void
|
||||
btr_leaf_page_release(
|
||||
/*==================*/
|
||||
buf_block_t* block, /*!< in: buffer block */
|
||||
ulint latch_mode, /*!< in: BTR_SEARCH_LEAF or
|
||||
BTR_MODIFY_LEAF */
|
||||
mtr_t* mtr) /*!< in: mtr */
|
||||
__attribute__((nonnull));
|
||||
/**************************************************************//**
|
||||
Gets the child node file address in a node pointer.
|
||||
NOTE: the offsets array must contain all offsets for the record since
|
||||
we read the last field according to offsets and assume that it contains
|
||||
the child page number. In other words offsets must have been retrieved
|
||||
with rec_get_offsets(n_fields=ULINT_UNDEFINED).
|
||||
@return child node address */
|
||||
UNIV_INLINE
|
||||
ulint
|
||||
btr_node_ptr_get_child_page_no(
|
||||
/*===========================*/
|
||||
const rec_t* rec, /*!< in: node pointer record */
|
||||
const ulint* offsets)/*!< in: array returned by rec_get_offsets() */
|
||||
__attribute__((nonnull, pure, warn_unused_result));
|
||||
/************************************************************//**
|
||||
Creates the root node for a new index tree.
|
||||
@return page number of the created root, FIL_NULL if did not succeed */
|
||||
UNIV_INTERN
|
||||
ulint
|
||||
btr_create(
|
||||
/*=======*/
|
||||
ulint type, /*!< in: type of the index */
|
||||
ulint space, /*!< in: space where created */
|
||||
ulint zip_size,/*!< in: compressed page size in bytes
|
||||
or 0 for uncompressed pages */
|
||||
index_id_t index_id,/*!< in: index id */
|
||||
dict_index_t* index, /*!< in: index */
|
||||
mtr_t* mtr) /*!< in: mini-transaction handle */
|
||||
__attribute__((nonnull));
|
||||
/************************************************************//**
|
||||
Frees a B-tree except the root page, which MUST be freed after this
|
||||
by calling btr_free_root. */
|
||||
UNIV_INTERN
|
||||
void
|
||||
btr_free_but_not_root(
|
||||
/*==================*/
|
||||
ulint space, /*!< in: space where created */
|
||||
ulint zip_size, /*!< in: compressed page size in bytes
|
||||
or 0 for uncompressed pages */
|
||||
ulint root_page_no); /*!< in: root page number */
|
||||
/************************************************************//**
|
||||
Frees the B-tree root page. Other tree MUST already have been freed. */
|
||||
UNIV_INTERN
|
||||
void
|
||||
btr_free_root(
|
||||
/*==========*/
|
||||
ulint space, /*!< in: space where created */
|
||||
ulint zip_size, /*!< in: compressed page size in bytes
|
||||
or 0 for uncompressed pages */
|
||||
ulint root_page_no, /*!< in: root page number */
|
||||
mtr_t* mtr) /*!< in/out: mini-transaction */
|
||||
__attribute__((nonnull));
|
||||
/*************************************************************//**
|
||||
Makes tree one level higher by splitting the root, and inserts
|
||||
the tuple. It is assumed that mtr contains an x-latch on the tree.
|
||||
NOTE that the operation of this function must always succeed,
|
||||
we cannot reverse it: therefore enough free disk space must be
|
||||
guaranteed to be available before this function is called.
|
||||
@return inserted record */
|
||||
UNIV_INTERN
|
||||
rec_t*
|
||||
btr_root_raise_and_insert(
|
||||
/*======================*/
|
||||
ulint flags, /*!< in: undo logging and locking flags */
|
||||
btr_cur_t* cursor, /*!< in: cursor at which to insert: must be
|
||||
on the root page; when the function returns,
|
||||
the cursor is positioned on the predecessor
|
||||
of the inserted record */
|
||||
ulint** offsets,/*!< out: offsets on inserted record */
|
||||
mem_heap_t** heap, /*!< in/out: pointer to memory heap
|
||||
that can be emptied, or NULL */
|
||||
const dtuple_t* tuple, /*!< in: tuple to insert */
|
||||
ulint n_ext, /*!< in: number of externally stored columns */
|
||||
mtr_t* mtr) /*!< in: mtr */
|
||||
__attribute__((nonnull, warn_unused_result));
|
||||
/*************************************************************//**
|
||||
Reorganizes an index page.
|
||||
|
||||
IMPORTANT: On success, the caller will have to update IBUF_BITMAP_FREE
|
||||
if this is a compressed leaf page in a secondary index. This has to
|
||||
be done either within the same mini-transaction, or by invoking
|
||||
ibuf_reset_free_bits() before mtr_commit(). On uncompressed pages,
|
||||
IBUF_BITMAP_FREE is unaffected by reorganization.
|
||||
|
||||
@retval true if the operation was successful
|
||||
@retval false if it is a compressed page, and recompression failed */
|
||||
UNIV_INTERN
|
||||
bool
|
||||
btr_page_reorganize_low(
|
||||
/*====================*/
|
||||
bool recovery,/*!< in: true if called in recovery:
|
||||
locks should not be updated, i.e.,
|
||||
there cannot exist locks on the
|
||||
page, and a hash index should not be
|
||||
dropped: it cannot exist */
|
||||
ulint z_level,/*!< in: compression level to be used
|
||||
if dealing with compressed page */
|
||||
page_cur_t* cursor, /*!< in/out: page cursor */
|
||||
dict_index_t* index, /*!< in: the index tree of the page */
|
||||
mtr_t* mtr) /*!< in/out: mini-transaction */
|
||||
__attribute__((nonnull, warn_unused_result));
|
||||
/*************************************************************//**
|
||||
Reorganizes an index page.
|
||||
|
||||
IMPORTANT: On success, the caller will have to update IBUF_BITMAP_FREE
|
||||
if this is a compressed leaf page in a secondary index. This has to
|
||||
be done either within the same mini-transaction, or by invoking
|
||||
ibuf_reset_free_bits() before mtr_commit(). On uncompressed pages,
|
||||
IBUF_BITMAP_FREE is unaffected by reorganization.
|
||||
|
||||
@retval true if the operation was successful
|
||||
@retval false if it is a compressed page, and recompression failed */
|
||||
UNIV_INTERN
|
||||
bool
|
||||
btr_page_reorganize(
|
||||
/*================*/
|
||||
page_cur_t* cursor, /*!< in/out: page cursor */
|
||||
dict_index_t* index, /*!< in: the index tree of the page */
|
||||
mtr_t* mtr) /*!< in/out: mini-transaction */
|
||||
__attribute__((nonnull));
|
||||
/*************************************************************//**
|
||||
Decides if the page should be split at the convergence point of
|
||||
inserts converging to left.
|
||||
@return TRUE if split recommended */
|
||||
UNIV_INTERN
|
||||
ibool
|
||||
btr_page_get_split_rec_to_left(
|
||||
/*===========================*/
|
||||
btr_cur_t* cursor, /*!< in: cursor at which to insert */
|
||||
rec_t** split_rec)/*!< out: if split recommended,
|
||||
the first record on upper half page,
|
||||
or NULL if tuple should be first */
|
||||
__attribute__((nonnull, warn_unused_result));
|
||||
/*************************************************************//**
|
||||
Decides if the page should be split at the convergence point of
|
||||
inserts converging to right.
|
||||
@return TRUE if split recommended */
|
||||
UNIV_INTERN
|
||||
ibool
|
||||
btr_page_get_split_rec_to_right(
|
||||
/*============================*/
|
||||
btr_cur_t* cursor, /*!< in: cursor at which to insert */
|
||||
rec_t** split_rec)/*!< out: if split recommended,
|
||||
the first record on upper half page,
|
||||
or NULL if tuple should be first */
|
||||
__attribute__((nonnull, warn_unused_result));
|
||||
/*************************************************************//**
|
||||
Splits an index page to halves and inserts the tuple. It is assumed
|
||||
that mtr holds an x-latch to the index tree. NOTE: the tree x-latch is
|
||||
released within this function! NOTE that the operation of this
|
||||
function must always succeed, we cannot reverse it: therefore enough
|
||||
free disk space (2 pages) must be guaranteed to be available before
|
||||
this function is called.
|
||||
|
||||
@return inserted record */
|
||||
UNIV_INTERN
|
||||
rec_t*
|
||||
btr_page_split_and_insert(
|
||||
/*======================*/
|
||||
ulint flags, /*!< in: undo logging and locking flags */
|
||||
btr_cur_t* cursor, /*!< in: cursor at which to insert; when the
|
||||
function returns, the cursor is positioned
|
||||
on the predecessor of the inserted record */
|
||||
ulint** offsets,/*!< out: offsets on inserted record */
|
||||
mem_heap_t** heap, /*!< in/out: pointer to memory heap
|
||||
that can be emptied, or NULL */
|
||||
const dtuple_t* tuple, /*!< in: tuple to insert */
|
||||
ulint n_ext, /*!< in: number of externally stored columns */
|
||||
mtr_t* mtr) /*!< in: mtr */
|
||||
__attribute__((nonnull, warn_unused_result));
|
||||
/*******************************************************//**
|
||||
Inserts a data tuple to a tree on a non-leaf level. It is assumed
|
||||
that mtr holds an x-latch on the tree. */
|
||||
UNIV_INTERN
|
||||
void
|
||||
btr_insert_on_non_leaf_level_func(
|
||||
/*==============================*/
|
||||
ulint flags, /*!< in: undo logging and locking flags */
|
||||
dict_index_t* index, /*!< in: index */
|
||||
ulint level, /*!< in: level, must be > 0 */
|
||||
dtuple_t* tuple, /*!< in: the record to be inserted */
|
||||
const char* file, /*!< in: file name */
|
||||
ulint line, /*!< in: line where called */
|
||||
mtr_t* mtr) /*!< in: mtr */
|
||||
__attribute__((nonnull));
|
||||
# define btr_insert_on_non_leaf_level(f,i,l,t,m) \
|
||||
btr_insert_on_non_leaf_level_func(f,i,l,t,__FILE__,__LINE__,m)
|
||||
#endif /* !UNIV_HOTBACKUP */
|
||||
/****************************************************************//**
|
||||
Sets a record as the predefined minimum record. */
|
||||
UNIV_INTERN
|
||||
void
|
||||
btr_set_min_rec_mark(
|
||||
/*=================*/
|
||||
rec_t* rec, /*!< in/out: record */
|
||||
mtr_t* mtr) /*!< in: mtr */
|
||||
__attribute__((nonnull));
|
||||
#ifndef UNIV_HOTBACKUP
|
||||
/*************************************************************//**
|
||||
Deletes on the upper level the node pointer to a page. */
|
||||
UNIV_INTERN
|
||||
void
|
||||
btr_node_ptr_delete(
|
||||
/*================*/
|
||||
dict_index_t* index, /*!< in: index tree */
|
||||
buf_block_t* block, /*!< in: page whose node pointer is deleted */
|
||||
mtr_t* mtr) /*!< in: mtr */
|
||||
__attribute__((nonnull));
|
||||
#ifdef UNIV_DEBUG
|
||||
/************************************************************//**
|
||||
Checks that the node pointer to a page is appropriate.
|
||||
@return TRUE */
|
||||
UNIV_INTERN
|
||||
ibool
|
||||
btr_check_node_ptr(
|
||||
/*===============*/
|
||||
dict_index_t* index, /*!< in: index tree */
|
||||
buf_block_t* block, /*!< in: index page */
|
||||
mtr_t* mtr) /*!< in: mtr */
|
||||
__attribute__((nonnull, warn_unused_result));
|
||||
#endif /* UNIV_DEBUG */
|
||||
/*************************************************************//**
|
||||
Tries to merge the page first to the left immediate brother if such a
|
||||
brother exists, and the node pointers to the current page and to the
|
||||
brother reside on the same page. If the left brother does not satisfy these
|
||||
conditions, looks at the right brother. If the page is the only one on that
|
||||
level lifts the records of the page to the father page, thus reducing the
|
||||
tree height. It is assumed that mtr holds an x-latch on the tree and on the
|
||||
page. If cursor is on the leaf level, mtr must also hold x-latches to
|
||||
the brothers, if they exist.
|
||||
@return TRUE on success */
|
||||
UNIV_INTERN
|
||||
ibool
|
||||
btr_compress(
|
||||
/*=========*/
|
||||
btr_cur_t* cursor, /*!< in/out: cursor on the page to merge
|
||||
or lift; the page must not be empty:
|
||||
when deleting records, use btr_discard_page()
|
||||
if the page would become empty */
|
||||
ibool adjust, /*!< in: TRUE if should adjust the
|
||||
cursor position even if compression occurs */
|
||||
mtr_t* mtr) /*!< in/out: mini-transaction */
|
||||
__attribute__((nonnull));
|
||||
/*************************************************************//**
|
||||
Discards a page from a B-tree. This is used to remove the last record from
|
||||
a B-tree page: the whole page must be removed at the same time. This cannot
|
||||
be used for the root page, which is allowed to be empty. */
|
||||
UNIV_INTERN
|
||||
void
|
||||
btr_discard_page(
|
||||
/*=============*/
|
||||
btr_cur_t* cursor, /*!< in: cursor on the page to discard: not on
|
||||
the root page */
|
||||
mtr_t* mtr) /*!< in: mtr */
|
||||
__attribute__((nonnull));
|
||||
#endif /* !UNIV_HOTBACKUP */
|
||||
/****************************************************************//**
|
||||
Parses the redo log record for setting an index record as the predefined
|
||||
minimum record.
|
||||
@return end of log record or NULL */
|
||||
UNIV_INTERN
|
||||
byte*
|
||||
btr_parse_set_min_rec_mark(
|
||||
/*=======================*/
|
||||
byte* ptr, /*!< in: buffer */
|
||||
byte* end_ptr,/*!< in: buffer end */
|
||||
ulint comp, /*!< in: nonzero=compact page format */
|
||||
page_t* page, /*!< in: page or NULL */
|
||||
mtr_t* mtr) /*!< in: mtr or NULL */
|
||||
__attribute__((nonnull(1,2), warn_unused_result));
|
||||
/***********************************************************//**
|
||||
Parses a redo log record of reorganizing a page.
|
||||
@return end of log record or NULL */
|
||||
UNIV_INTERN
|
||||
byte*
|
||||
btr_parse_page_reorganize(
|
||||
/*======================*/
|
||||
byte* ptr, /*!< in: buffer */
|
||||
byte* end_ptr,/*!< in: buffer end */
|
||||
dict_index_t* index, /*!< in: record descriptor */
|
||||
bool compressed,/*!< in: true if compressed page */
|
||||
buf_block_t* block, /*!< in: page to be reorganized, or NULL */
|
||||
mtr_t* mtr) /*!< in: mtr or NULL */
|
||||
__attribute__((nonnull(1,2,3), warn_unused_result));
|
||||
#ifndef UNIV_HOTBACKUP
|
||||
/**************************************************************//**
|
||||
Gets the number of pages in a B-tree.
|
||||
@return number of pages, or ULINT_UNDEFINED if the index is unavailable */
|
||||
UNIV_INTERN
|
||||
ulint
|
||||
btr_get_size(
|
||||
/*=========*/
|
||||
dict_index_t* index, /*!< in: index */
|
||||
ulint flag, /*!< in: BTR_N_LEAF_PAGES or BTR_TOTAL_SIZE */
|
||||
mtr_t* mtr) /*!< in/out: mini-transaction where index
|
||||
is s-latched */
|
||||
__attribute__((nonnull, warn_unused_result));
|
||||
/**************************************************************//**
|
||||
Allocates a new file page to be used in an index tree. NOTE: we assume
|
||||
that the caller has made the reservation for free extents!
|
||||
@retval NULL if no page could be allocated
|
||||
@retval block, rw_lock_x_lock_count(&block->lock) == 1 if allocation succeeded
|
||||
(init_mtr == mtr, or the page was not previously freed in mtr)
|
||||
@retval block (not allocated or initialized) otherwise */
|
||||
UNIV_INTERN
|
||||
buf_block_t*
|
||||
btr_page_alloc(
|
||||
/*===========*/
|
||||
dict_index_t* index, /*!< in: index tree */
|
||||
ulint hint_page_no, /*!< in: hint of a good page */
|
||||
byte file_direction, /*!< in: direction where a possible
|
||||
page split is made */
|
||||
ulint level, /*!< in: level where the page is placed
|
||||
in the tree */
|
||||
mtr_t* mtr, /*!< in/out: mini-transaction
|
||||
for the allocation */
|
||||
mtr_t* init_mtr) /*!< in/out: mini-transaction
|
||||
for x-latching and initializing
|
||||
the page */
|
||||
__attribute__((nonnull, warn_unused_result));
|
||||
/**************************************************************//**
|
||||
Frees a file page used in an index tree. NOTE: cannot free field external
|
||||
storage pages because the page must contain info on its level. */
|
||||
UNIV_INTERN
|
||||
void
|
||||
btr_page_free(
|
||||
/*==========*/
|
||||
dict_index_t* index, /*!< in: index tree */
|
||||
buf_block_t* block, /*!< in: block to be freed, x-latched */
|
||||
mtr_t* mtr) /*!< in: mtr */
|
||||
__attribute__((nonnull));
|
||||
/**************************************************************//**
|
||||
Frees a file page used in an index tree. Can be used also to BLOB
|
||||
external storage pages, because the page level 0 can be given as an
|
||||
argument. */
|
||||
UNIV_INTERN
|
||||
void
|
||||
btr_page_free_low(
|
||||
/*==============*/
|
||||
dict_index_t* index, /*!< in: index tree */
|
||||
buf_block_t* block, /*!< in: block to be freed, x-latched */
|
||||
ulint level, /*!< in: page level */
|
||||
mtr_t* mtr) /*!< in: mtr */
|
||||
__attribute__((nonnull));
|
||||
#ifdef UNIV_BTR_PRINT
|
||||
/*************************************************************//**
|
||||
Prints size info of a B-tree. */
|
||||
UNIV_INTERN
|
||||
void
|
||||
btr_print_size(
|
||||
/*===========*/
|
||||
dict_index_t* index) /*!< in: index tree */
|
||||
__attribute__((nonnull));
|
||||
/**************************************************************//**
|
||||
Prints directories and other info of all nodes in the index. */
|
||||
UNIV_INTERN
|
||||
void
|
||||
btr_print_index(
|
||||
/*============*/
|
||||
dict_index_t* index, /*!< in: index */
|
||||
ulint width) /*!< in: print this many entries from start
|
||||
and end */
|
||||
__attribute__((nonnull));
|
||||
#endif /* UNIV_BTR_PRINT */
|
||||
/************************************************************//**
|
||||
Checks the size and number of fields in a record based on the definition of
|
||||
the index.
|
||||
@return TRUE if ok */
|
||||
UNIV_INTERN
|
||||
ibool
|
||||
btr_index_rec_validate(
|
||||
/*===================*/
|
||||
const rec_t* rec, /*!< in: index record */
|
||||
const dict_index_t* index, /*!< in: index */
|
||||
ibool dump_on_error) /*!< in: TRUE if the function
|
||||
should print hex dump of record
|
||||
and page on error */
|
||||
__attribute__((nonnull, warn_unused_result));
|
||||
/**************************************************************//**
|
||||
Checks the consistency of an index tree.
|
||||
@return TRUE if ok */
|
||||
UNIV_INTERN
|
||||
bool
|
||||
btr_validate_index(
|
||||
/*===============*/
|
||||
dict_index_t* index, /*!< in: index */
|
||||
const trx_t* trx) /*!< in: transaction or 0 */
|
||||
__attribute__((nonnull(1), warn_unused_result));
|
||||
|
||||
#define BTR_N_LEAF_PAGES 1
|
||||
#define BTR_TOTAL_SIZE 2
|
||||
#endif /* !UNIV_HOTBACKUP */
|
||||
|
||||
#ifndef UNIV_NONINL
|
||||
#include "btr0btr.ic"
|
||||
#endif
|
||||
|
||||
#endif
|
||||
290
storage/innobase/include/btr0btr.ic
Normal file
290
storage/innobase/include/btr0btr.ic
Normal file
|
|
@ -0,0 +1,290 @@
|
|||
/*****************************************************************************
|
||||
|
||||
Copyright (c) 1994, 2012, Oracle and/or its affiliates. All Rights Reserved.
|
||||
|
||||
This program is free software; you can redistribute it and/or modify it under
|
||||
the terms of the GNU General Public License as published by the Free Software
|
||||
Foundation; version 2 of the License.
|
||||
|
||||
This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
|
||||
FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License along with
|
||||
this program; if not, write to the Free Software Foundation, Inc.,
|
||||
51 Franklin Street, Suite 500, Boston, MA 02110-1335 USA
|
||||
|
||||
*****************************************************************************/
|
||||
|
||||
/**************************************************//**
|
||||
@file include/btr0btr.ic
|
||||
The B-tree
|
||||
|
||||
Created 6/2/1994 Heikki Tuuri
|
||||
*******************************************************/
|
||||
|
||||
#include "mach0data.h"
|
||||
#ifndef UNIV_HOTBACKUP
|
||||
#include "mtr0mtr.h"
|
||||
#include "mtr0log.h"
|
||||
#include "page0zip.h"
|
||||
|
||||
#define BTR_MAX_NODE_LEVEL 50 /*!< Maximum B-tree page level
|
||||
(not really a hard limit).
|
||||
Used in debug assertions
|
||||
in btr_page_set_level and
|
||||
btr_page_get_level_low */
|
||||
|
||||
/**************************************************************//**
|
||||
Gets a buffer page and declares its latching order level. */
|
||||
UNIV_INLINE
|
||||
buf_block_t*
|
||||
btr_block_get_func(
|
||||
/*===============*/
|
||||
ulint space, /*!< in: space id */
|
||||
ulint zip_size, /*!< in: compressed page size in bytes
|
||||
or 0 for uncompressed pages */
|
||||
ulint page_no, /*!< in: page number */
|
||||
ulint mode, /*!< in: latch mode */
|
||||
const char* file, /*!< in: file name */
|
||||
ulint line, /*!< in: line where called */
|
||||
#ifdef UNIV_SYNC_DEBUG
|
||||
const dict_index_t* index, /*!< in: index tree, may be NULL
|
||||
if it is not an insert buffer tree */
|
||||
#endif /* UNIV_SYNC_DEBUG */
|
||||
mtr_t* mtr) /*!< in/out: mtr */
|
||||
{
|
||||
buf_block_t* block;
|
||||
|
||||
block = buf_page_get_gen(space, zip_size, page_no, mode,
|
||||
NULL, BUF_GET, file, line, mtr);
|
||||
|
||||
if (mode != RW_NO_LATCH) {
|
||||
|
||||
buf_block_dbg_add_level(
|
||||
block, index != NULL && dict_index_is_ibuf(index)
|
||||
? SYNC_IBUF_TREE_NODE : SYNC_TREE_NODE);
|
||||
}
|
||||
|
||||
return(block);
|
||||
}
|
||||
|
||||
/**************************************************************//**
|
||||
Sets the index id field of a page. */
|
||||
UNIV_INLINE
|
||||
void
|
||||
btr_page_set_index_id(
|
||||
/*==================*/
|
||||
page_t* page, /*!< in: page to be created */
|
||||
page_zip_des_t* page_zip,/*!< in: compressed page whose uncompressed
|
||||
part will be updated, or NULL */
|
||||
index_id_t id, /*!< in: index id */
|
||||
mtr_t* mtr) /*!< in: mtr */
|
||||
{
|
||||
if (page_zip) {
|
||||
mach_write_to_8(page + (PAGE_HEADER + PAGE_INDEX_ID), id);
|
||||
page_zip_write_header(page_zip,
|
||||
page + (PAGE_HEADER + PAGE_INDEX_ID),
|
||||
8, mtr);
|
||||
} else {
|
||||
mlog_write_ull(page + (PAGE_HEADER + PAGE_INDEX_ID), id, mtr);
|
||||
}
|
||||
}
|
||||
#endif /* !UNIV_HOTBACKUP */
|
||||
|
||||
/**************************************************************//**
|
||||
Gets the index id field of a page.
|
||||
@return index id */
|
||||
UNIV_INLINE
|
||||
index_id_t
|
||||
btr_page_get_index_id(
|
||||
/*==================*/
|
||||
const page_t* page) /*!< in: index page */
|
||||
{
|
||||
return(mach_read_from_8(page + PAGE_HEADER + PAGE_INDEX_ID));
|
||||
}
|
||||
|
||||
#ifndef UNIV_HOTBACKUP
|
||||
/********************************************************//**
|
||||
Gets the node level field in an index page.
|
||||
@return level, leaf level == 0 */
|
||||
UNIV_INLINE
|
||||
ulint
|
||||
btr_page_get_level_low(
|
||||
/*===================*/
|
||||
const page_t* page) /*!< in: index page */
|
||||
{
|
||||
ulint level;
|
||||
|
||||
ut_ad(page);
|
||||
|
||||
level = mach_read_from_2(page + PAGE_HEADER + PAGE_LEVEL);
|
||||
|
||||
ut_ad(level <= BTR_MAX_NODE_LEVEL);
|
||||
|
||||
return(level);
|
||||
}
|
||||
|
||||
/********************************************************//**
|
||||
Sets the node level field in an index page. */
|
||||
UNIV_INLINE
|
||||
void
|
||||
btr_page_set_level(
|
||||
/*===============*/
|
||||
page_t* page, /*!< in: index page */
|
||||
page_zip_des_t* page_zip,/*!< in: compressed page whose uncompressed
|
||||
part will be updated, or NULL */
|
||||
ulint level, /*!< in: level, leaf level == 0 */
|
||||
mtr_t* mtr) /*!< in: mini-transaction handle */
|
||||
{
|
||||
ut_ad(page && mtr);
|
||||
ut_ad(level <= BTR_MAX_NODE_LEVEL);
|
||||
|
||||
if (page_zip) {
|
||||
mach_write_to_2(page + (PAGE_HEADER + PAGE_LEVEL), level);
|
||||
page_zip_write_header(page_zip,
|
||||
page + (PAGE_HEADER + PAGE_LEVEL),
|
||||
2, mtr);
|
||||
} else {
|
||||
mlog_write_ulint(page + (PAGE_HEADER + PAGE_LEVEL), level,
|
||||
MLOG_2BYTES, mtr);
|
||||
}
|
||||
}
|
||||
|
||||
/********************************************************//**
|
||||
Gets the next index page number.
|
||||
@return next page number */
|
||||
UNIV_INLINE
|
||||
ulint
|
||||
btr_page_get_next(
|
||||
/*==============*/
|
||||
const page_t* page, /*!< in: index page */
|
||||
mtr_t* mtr __attribute__((unused)))
|
||||
/*!< in: mini-transaction handle */
|
||||
{
|
||||
ut_ad(page && mtr);
|
||||
ut_ad(mtr_memo_contains_page(mtr, page, MTR_MEMO_PAGE_X_FIX)
|
||||
|| mtr_memo_contains_page(mtr, page, MTR_MEMO_PAGE_S_FIX));
|
||||
|
||||
return(mach_read_from_4(page + FIL_PAGE_NEXT));
|
||||
}
|
||||
|
||||
/********************************************************//**
|
||||
Sets the next index page field. */
|
||||
UNIV_INLINE
|
||||
void
|
||||
btr_page_set_next(
|
||||
/*==============*/
|
||||
page_t* page, /*!< in: index page */
|
||||
page_zip_des_t* page_zip,/*!< in: compressed page whose uncompressed
|
||||
part will be updated, or NULL */
|
||||
ulint next, /*!< in: next page number */
|
||||
mtr_t* mtr) /*!< in: mini-transaction handle */
|
||||
{
|
||||
ut_ad(page && mtr);
|
||||
|
||||
if (page_zip) {
|
||||
mach_write_to_4(page + FIL_PAGE_NEXT, next);
|
||||
page_zip_write_header(page_zip, page + FIL_PAGE_NEXT, 4, mtr);
|
||||
} else {
|
||||
mlog_write_ulint(page + FIL_PAGE_NEXT, next, MLOG_4BYTES, mtr);
|
||||
}
|
||||
}
|
||||
|
||||
/********************************************************//**
|
||||
Gets the previous index page number.
|
||||
@return prev page number */
|
||||
UNIV_INLINE
|
||||
ulint
|
||||
btr_page_get_prev(
|
||||
/*==============*/
|
||||
const page_t* page, /*!< in: index page */
|
||||
mtr_t* mtr __attribute__((unused))) /*!< in: mini-transaction handle */
|
||||
{
|
||||
ut_ad(page && mtr);
|
||||
|
||||
return(mach_read_from_4(page + FIL_PAGE_PREV));
|
||||
}
|
||||
|
||||
/********************************************************//**
|
||||
Sets the previous index page field. */
|
||||
UNIV_INLINE
|
||||
void
|
||||
btr_page_set_prev(
|
||||
/*==============*/
|
||||
page_t* page, /*!< in: index page */
|
||||
page_zip_des_t* page_zip,/*!< in: compressed page whose uncompressed
|
||||
part will be updated, or NULL */
|
||||
ulint prev, /*!< in: previous page number */
|
||||
mtr_t* mtr) /*!< in: mini-transaction handle */
|
||||
{
|
||||
ut_ad(page && mtr);
|
||||
|
||||
if (page_zip) {
|
||||
mach_write_to_4(page + FIL_PAGE_PREV, prev);
|
||||
page_zip_write_header(page_zip, page + FIL_PAGE_PREV, 4, mtr);
|
||||
} else {
|
||||
mlog_write_ulint(page + FIL_PAGE_PREV, prev, MLOG_4BYTES, mtr);
|
||||
}
|
||||
}
|
||||
|
||||
/**************************************************************//**
|
||||
Gets the child node file address in a node pointer.
|
||||
NOTE: the offsets array must contain all offsets for the record since
|
||||
we read the last field according to offsets and assume that it contains
|
||||
the child page number. In other words offsets must have been retrieved
|
||||
with rec_get_offsets(n_fields=ULINT_UNDEFINED).
|
||||
@return child node address */
|
||||
UNIV_INLINE
|
||||
ulint
|
||||
btr_node_ptr_get_child_page_no(
|
||||
/*===========================*/
|
||||
const rec_t* rec, /*!< in: node pointer record */
|
||||
const ulint* offsets)/*!< in: array returned by rec_get_offsets() */
|
||||
{
|
||||
const byte* field;
|
||||
ulint len;
|
||||
ulint page_no;
|
||||
|
||||
ut_ad(!rec_offs_comp(offsets) || rec_get_node_ptr_flag(rec));
|
||||
|
||||
/* The child address is in the last field */
|
||||
field = rec_get_nth_field(rec, offsets,
|
||||
rec_offs_n_fields(offsets) - 1, &len);
|
||||
|
||||
ut_ad(len == 4);
|
||||
|
||||
page_no = mach_read_from_4(field);
|
||||
|
||||
if (page_no == 0) {
|
||||
fprintf(stderr,
|
||||
"InnoDB: a nonsensical page number 0"
|
||||
" in a node ptr record at offset %lu\n",
|
||||
(ulong) page_offset(rec));
|
||||
buf_page_print(page_align(rec), 0, 0);
|
||||
ut_ad(0);
|
||||
}
|
||||
|
||||
return(page_no);
|
||||
}
|
||||
|
||||
/**************************************************************//**
|
||||
Releases the latches on a leaf page and bufferunfixes it. */
|
||||
UNIV_INLINE
|
||||
void
|
||||
btr_leaf_page_release(
|
||||
/*==================*/
|
||||
buf_block_t* block, /*!< in: buffer block */
|
||||
ulint latch_mode, /*!< in: BTR_SEARCH_LEAF or
|
||||
BTR_MODIFY_LEAF */
|
||||
mtr_t* mtr) /*!< in: mtr */
|
||||
{
|
||||
ut_ad(latch_mode == BTR_SEARCH_LEAF || latch_mode == BTR_MODIFY_LEAF);
|
||||
ut_ad(!mtr_memo_contains(mtr, block, MTR_MEMO_MODIFY));
|
||||
|
||||
mtr_memo_release(mtr, block,
|
||||
latch_mode == BTR_SEARCH_LEAF
|
||||
? MTR_MEMO_PAGE_S_FIX
|
||||
: MTR_MEMO_PAGE_X_FIX);
|
||||
}
|
||||
#endif /* !UNIV_HOTBACKUP */
|
||||
937
storage/innobase/include/btr0cur.h
Normal file
937
storage/innobase/include/btr0cur.h
Normal file
|
|
@ -0,0 +1,937 @@
|
|||
/*****************************************************************************
|
||||
|
||||
Copyright (c) 1994, 2014, Oracle and/or its affiliates. All Rights Reserved.
|
||||
|
||||
This program is free software; you can redistribute it and/or modify it under
|
||||
the terms of the GNU General Public License as published by the Free Software
|
||||
Foundation; version 2 of the License.
|
||||
|
||||
This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
|
||||
FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License along with
|
||||
this program; if not, write to the Free Software Foundation, Inc.,
|
||||
51 Franklin Street, Suite 500, Boston, MA 02110-1335 USA
|
||||
|
||||
*****************************************************************************/
|
||||
|
||||
/**************************************************//**
|
||||
@file include/btr0cur.h
|
||||
The index tree cursor
|
||||
|
||||
Created 10/16/1994 Heikki Tuuri
|
||||
*******************************************************/
|
||||
|
||||
#ifndef btr0cur_h
|
||||
#define btr0cur_h
|
||||
|
||||
#include "univ.i"
|
||||
#include "dict0dict.h"
|
||||
#include "page0cur.h"
|
||||
#include "btr0types.h"
|
||||
|
||||
/** Mode flags for btr_cur operations; these can be ORed */
|
||||
enum {
|
||||
/** do no undo logging */
|
||||
BTR_NO_UNDO_LOG_FLAG = 1,
|
||||
/** do no record lock checking */
|
||||
BTR_NO_LOCKING_FLAG = 2,
|
||||
/** sys fields will be found in the update vector or inserted
|
||||
entry */
|
||||
BTR_KEEP_SYS_FLAG = 4,
|
||||
/** btr_cur_pessimistic_update() must keep cursor position
|
||||
when moving columns to big_rec */
|
||||
BTR_KEEP_POS_FLAG = 8,
|
||||
/** the caller is creating the index or wants to bypass the
|
||||
index->info.online creation log */
|
||||
BTR_CREATE_FLAG = 16,
|
||||
/** the caller of btr_cur_optimistic_update() or
|
||||
btr_cur_update_in_place() will take care of
|
||||
updating IBUF_BITMAP_FREE */
|
||||
BTR_KEEP_IBUF_BITMAP = 32
|
||||
};
|
||||
|
||||
#ifndef UNIV_HOTBACKUP
|
||||
#include "que0types.h"
|
||||
#include "row0types.h"
|
||||
#include "ha0ha.h"
|
||||
|
||||
#define BTR_CUR_ADAPT
|
||||
#define BTR_CUR_HASH_ADAPT
|
||||
|
||||
#ifdef UNIV_DEBUG
|
||||
/*********************************************************//**
|
||||
Returns the page cursor component of a tree cursor.
|
||||
@return pointer to page cursor component */
|
||||
UNIV_INLINE
|
||||
page_cur_t*
|
||||
btr_cur_get_page_cur(
|
||||
/*=================*/
|
||||
const btr_cur_t* cursor);/*!< in: tree cursor */
|
||||
/*********************************************************//**
|
||||
Returns the buffer block on which the tree cursor is positioned.
|
||||
@return pointer to buffer block */
|
||||
UNIV_INLINE
|
||||
buf_block_t*
|
||||
btr_cur_get_block(
|
||||
/*==============*/
|
||||
const btr_cur_t* cursor);/*!< in: tree cursor */
|
||||
/*********************************************************//**
|
||||
Returns the record pointer of a tree cursor.
|
||||
@return pointer to record */
|
||||
UNIV_INLINE
|
||||
rec_t*
|
||||
btr_cur_get_rec(
|
||||
/*============*/
|
||||
const btr_cur_t* cursor);/*!< in: tree cursor */
|
||||
#else /* UNIV_DEBUG */
|
||||
# define btr_cur_get_page_cur(cursor) (&(cursor)->page_cur)
|
||||
# define btr_cur_get_block(cursor) ((cursor)->page_cur.block)
|
||||
# define btr_cur_get_rec(cursor) ((cursor)->page_cur.rec)
|
||||
#endif /* UNIV_DEBUG */
|
||||
/*********************************************************//**
|
||||
Returns the compressed page on which the tree cursor is positioned.
|
||||
@return pointer to compressed page, or NULL if the page is not compressed */
|
||||
UNIV_INLINE
|
||||
page_zip_des_t*
|
||||
btr_cur_get_page_zip(
|
||||
/*=================*/
|
||||
btr_cur_t* cursor);/*!< in: tree cursor */
|
||||
/*********************************************************//**
|
||||
Invalidates a tree cursor by setting record pointer to NULL. */
|
||||
UNIV_INLINE
|
||||
void
|
||||
btr_cur_invalidate(
|
||||
/*===============*/
|
||||
btr_cur_t* cursor);/*!< in: tree cursor */
|
||||
/*********************************************************//**
|
||||
Returns the page of a tree cursor.
|
||||
@return pointer to page */
|
||||
UNIV_INLINE
|
||||
page_t*
|
||||
btr_cur_get_page(
|
||||
/*=============*/
|
||||
btr_cur_t* cursor);/*!< in: tree cursor */
|
||||
/*********************************************************//**
|
||||
Returns the index of a cursor.
|
||||
@param cursor b-tree cursor
|
||||
@return index */
|
||||
#define btr_cur_get_index(cursor) ((cursor)->index)
|
||||
/*********************************************************//**
|
||||
Positions a tree cursor at a given record. */
|
||||
UNIV_INLINE
|
||||
void
|
||||
btr_cur_position(
|
||||
/*=============*/
|
||||
dict_index_t* index, /*!< in: index */
|
||||
rec_t* rec, /*!< in: record in tree */
|
||||
buf_block_t* block, /*!< in: buffer block of rec */
|
||||
btr_cur_t* cursor);/*!< in: cursor */
|
||||
/********************************************************************//**
|
||||
Searches an index tree and positions a tree cursor on a given level.
|
||||
NOTE: n_fields_cmp in tuple must be set so that it cannot be compared
|
||||
to node pointer page number fields on the upper levels of the tree!
|
||||
Note that if mode is PAGE_CUR_LE, which is used in inserts, then
|
||||
cursor->up_match and cursor->low_match both will have sensible values.
|
||||
If mode is PAGE_CUR_GE, then up_match will a have a sensible value. */
|
||||
UNIV_INTERN
|
||||
void
|
||||
btr_cur_search_to_nth_level(
|
||||
/*========================*/
|
||||
dict_index_t* index, /*!< in: index */
|
||||
ulint level, /*!< in: the tree level of search */
|
||||
const dtuple_t* tuple, /*!< in: data tuple; NOTE: n_fields_cmp in
|
||||
tuple must be set so that it cannot get
|
||||
compared to the node ptr page number field! */
|
||||
ulint mode, /*!< in: PAGE_CUR_L, ...;
|
||||
NOTE that if the search is made using a unique
|
||||
prefix of a record, mode should be PAGE_CUR_LE,
|
||||
not PAGE_CUR_GE, as the latter may end up on
|
||||
the previous page of the record! Inserts
|
||||
should always be made using PAGE_CUR_LE to
|
||||
search the position! */
|
||||
ulint latch_mode, /*!< in: BTR_SEARCH_LEAF, ..., ORed with
|
||||
at most one of BTR_INSERT, BTR_DELETE_MARK,
|
||||
BTR_DELETE, or BTR_ESTIMATE;
|
||||
cursor->left_block is used to store a pointer
|
||||
to the left neighbor page, in the cases
|
||||
BTR_SEARCH_PREV and BTR_MODIFY_PREV;
|
||||
NOTE that if has_search_latch
|
||||
is != 0, we maybe do not have a latch set
|
||||
on the cursor page, we assume
|
||||
the caller uses his search latch
|
||||
to protect the record! */
|
||||
btr_cur_t* cursor, /*!< in/out: tree cursor; the cursor page is
|
||||
s- or x-latched, but see also above! */
|
||||
ulint has_search_latch,/*!< in: latch mode the caller
|
||||
currently has on btr_search_latch:
|
||||
RW_S_LATCH, or 0 */
|
||||
const char* file, /*!< in: file name */
|
||||
ulint line, /*!< in: line where called */
|
||||
mtr_t* mtr); /*!< in: mtr */
|
||||
/*****************************************************************//**
|
||||
Opens a cursor at either end of an index. */
|
||||
UNIV_INTERN
|
||||
void
|
||||
btr_cur_open_at_index_side_func(
|
||||
/*============================*/
|
||||
bool from_left, /*!< in: true if open to the low end,
|
||||
false if to the high end */
|
||||
dict_index_t* index, /*!< in: index */
|
||||
ulint latch_mode, /*!< in: latch mode */
|
||||
btr_cur_t* cursor, /*!< in/out: cursor */
|
||||
ulint level, /*!< in: level to search for
|
||||
(0=leaf) */
|
||||
const char* file, /*!< in: file name */
|
||||
ulint line, /*!< in: line where called */
|
||||
mtr_t* mtr) /*!< in/out: mini-transaction */
|
||||
__attribute__((nonnull));
|
||||
#define btr_cur_open_at_index_side(f,i,l,c,lv,m) \
|
||||
btr_cur_open_at_index_side_func(f,i,l,c,lv,__FILE__,__LINE__,m)
|
||||
/**********************************************************************//**
|
||||
Positions a cursor at a randomly chosen position within a B-tree. */
|
||||
UNIV_INTERN
|
||||
void
|
||||
btr_cur_open_at_rnd_pos_func(
|
||||
/*=========================*/
|
||||
dict_index_t* index, /*!< in: index */
|
||||
ulint latch_mode, /*!< in: BTR_SEARCH_LEAF, ... */
|
||||
btr_cur_t* cursor, /*!< in/out: B-tree cursor */
|
||||
const char* file, /*!< in: file name */
|
||||
ulint line, /*!< in: line where called */
|
||||
mtr_t* mtr); /*!< in: mtr */
|
||||
#define btr_cur_open_at_rnd_pos(i,l,c,m) \
|
||||
btr_cur_open_at_rnd_pos_func(i,l,c,__FILE__,__LINE__,m)
|
||||
/*************************************************************//**
|
||||
Tries to perform an insert to a page in an index tree, next to cursor.
|
||||
It is assumed that mtr holds an x-latch on the page. The operation does
|
||||
not succeed if there is too little space on the page. If there is just
|
||||
one record on the page, the insert will always succeed; this is to
|
||||
prevent trying to split a page with just one record.
|
||||
@return DB_SUCCESS, DB_WAIT_LOCK, DB_FAIL, or error number */
|
||||
UNIV_INTERN
|
||||
dberr_t
|
||||
btr_cur_optimistic_insert(
|
||||
/*======================*/
|
||||
ulint flags, /*!< in: undo logging and locking flags: if not
|
||||
zero, the parameters index and thr should be
|
||||
specified */
|
||||
btr_cur_t* cursor, /*!< in: cursor on page after which to insert;
|
||||
cursor stays valid */
|
||||
ulint** offsets,/*!< out: offsets on *rec */
|
||||
mem_heap_t** heap, /*!< in/out: pointer to memory heap, or NULL */
|
||||
dtuple_t* entry, /*!< in/out: entry to insert */
|
||||
rec_t** rec, /*!< out: pointer to inserted record if
|
||||
succeed */
|
||||
big_rec_t** big_rec,/*!< out: big rec vector whose fields have to
|
||||
be stored externally by the caller, or
|
||||
NULL */
|
||||
ulint n_ext, /*!< in: number of externally stored columns */
|
||||
que_thr_t* thr, /*!< in: query thread or NULL */
|
||||
mtr_t* mtr) /*!< in/out: mini-transaction;
|
||||
if this function returns DB_SUCCESS on
|
||||
a leaf page of a secondary index in a
|
||||
compressed tablespace, the caller must
|
||||
mtr_commit(mtr) before latching
|
||||
any further pages */
|
||||
__attribute__((nonnull(2,3,4,5,6,7,10), warn_unused_result));
|
||||
/*************************************************************//**
|
||||
Performs an insert on a page of an index tree. It is assumed that mtr
|
||||
holds an x-latch on the tree and on the cursor page. If the insert is
|
||||
made on the leaf level, to avoid deadlocks, mtr must also own x-latches
|
||||
to brothers of page, if those brothers exist.
|
||||
@return DB_SUCCESS or error number */
|
||||
UNIV_INTERN
|
||||
dberr_t
|
||||
btr_cur_pessimistic_insert(
|
||||
/*=======================*/
|
||||
ulint flags, /*!< in: undo logging and locking flags: if not
|
||||
zero, the parameter thr should be
|
||||
specified; if no undo logging is specified,
|
||||
then the caller must have reserved enough
|
||||
free extents in the file space so that the
|
||||
insertion will certainly succeed */
|
||||
btr_cur_t* cursor, /*!< in: cursor after which to insert;
|
||||
cursor stays valid */
|
||||
ulint** offsets,/*!< out: offsets on *rec */
|
||||
mem_heap_t** heap, /*!< in/out: pointer to memory heap
|
||||
that can be emptied, or NULL */
|
||||
dtuple_t* entry, /*!< in/out: entry to insert */
|
||||
rec_t** rec, /*!< out: pointer to inserted record if
|
||||
succeed */
|
||||
big_rec_t** big_rec,/*!< out: big rec vector whose fields have to
|
||||
be stored externally by the caller, or
|
||||
NULL */
|
||||
ulint n_ext, /*!< in: number of externally stored columns */
|
||||
que_thr_t* thr, /*!< in: query thread or NULL */
|
||||
mtr_t* mtr) /*!< in/out: mini-transaction */
|
||||
__attribute__((nonnull(2,3,4,5,6,7,10), warn_unused_result));
|
||||
/*************************************************************//**
|
||||
See if there is enough place in the page modification log to log
|
||||
an update-in-place.
|
||||
|
||||
@retval false if out of space; IBUF_BITMAP_FREE will be reset
|
||||
outside mtr if the page was recompressed
|
||||
@retval true if enough place;
|
||||
|
||||
IMPORTANT: The caller will have to update IBUF_BITMAP_FREE if this is
|
||||
a secondary index leaf page. This has to be done either within the
|
||||
same mini-transaction, or by invoking ibuf_reset_free_bits() before
|
||||
mtr_commit(mtr). */
|
||||
UNIV_INTERN
|
||||
bool
|
||||
btr_cur_update_alloc_zip_func(
|
||||
/*==========================*/
|
||||
page_zip_des_t* page_zip,/*!< in/out: compressed page */
|
||||
page_cur_t* cursor, /*!< in/out: B-tree page cursor */
|
||||
dict_index_t* index, /*!< in: the index corresponding to cursor */
|
||||
#ifdef UNIV_DEBUG
|
||||
ulint* offsets,/*!< in/out: offsets of the cursor record */
|
||||
#endif /* UNIV_DEBUG */
|
||||
ulint length, /*!< in: size needed */
|
||||
bool create, /*!< in: true=delete-and-insert,
|
||||
false=update-in-place */
|
||||
mtr_t* mtr) /*!< in/out: mini-transaction */
|
||||
__attribute__((nonnull, warn_unused_result));
|
||||
#ifdef UNIV_DEBUG
|
||||
# define btr_cur_update_alloc_zip(page_zip,cursor,index,offsets,len,cr,mtr) \
|
||||
btr_cur_update_alloc_zip_func(page_zip,cursor,index,offsets,len,cr,mtr)
|
||||
#else /* UNIV_DEBUG */
|
||||
# define btr_cur_update_alloc_zip(page_zip,cursor,index,offsets,len,cr,mtr) \
|
||||
btr_cur_update_alloc_zip_func(page_zip,cursor,index,len,cr,mtr)
|
||||
#endif /* UNIV_DEBUG */
|
||||
/*************************************************************//**
|
||||
Updates a record when the update causes no size changes in its fields.
|
||||
@return locking or undo log related error code, or
|
||||
@retval DB_SUCCESS on success
|
||||
@retval DB_ZIP_OVERFLOW if there is not enough space left
|
||||
on the compressed page (IBUF_BITMAP_FREE was reset outside mtr) */
|
||||
UNIV_INTERN
|
||||
dberr_t
|
||||
btr_cur_update_in_place(
|
||||
/*====================*/
|
||||
ulint flags, /*!< in: undo logging and locking flags */
|
||||
btr_cur_t* cursor, /*!< in: cursor on the record to update;
|
||||
cursor stays valid and positioned on the
|
||||
same record */
|
||||
ulint* offsets,/*!< in/out: offsets on cursor->page_cur.rec */
|
||||
const upd_t* update, /*!< in: update vector */
|
||||
ulint cmpl_info,/*!< in: compiler info on secondary index
|
||||
updates */
|
||||
que_thr_t* thr, /*!< in: query thread */
|
||||
trx_id_t trx_id, /*!< in: transaction id */
|
||||
mtr_t* mtr) /*!< in/out: mini-transaction; if this
|
||||
is a secondary index, the caller must
|
||||
mtr_commit(mtr) before latching any
|
||||
further pages */
|
||||
__attribute__((warn_unused_result, nonnull));
|
||||
/***********************************************************//**
|
||||
Writes a redo log record of updating a record in-place. */
|
||||
UNIV_INTERN
|
||||
void
|
||||
btr_cur_update_in_place_log(
|
||||
/*========================*/
|
||||
ulint flags, /*!< in: flags */
|
||||
const rec_t* rec, /*!< in: record */
|
||||
dict_index_t* index, /*!< in: index of the record */
|
||||
const upd_t* update, /*!< in: update vector */
|
||||
trx_id_t trx_id, /*!< in: transaction id */
|
||||
roll_ptr_t roll_ptr, /*!< in: roll ptr */
|
||||
mtr_t* mtr) /*!< in: mtr */
|
||||
__attribute__((nonnull));
|
||||
/*************************************************************//**
|
||||
Tries to update a record on a page in an index tree. It is assumed that mtr
|
||||
holds an x-latch on the page. The operation does not succeed if there is too
|
||||
little space on the page or if the update would result in too empty a page,
|
||||
so that tree compression is recommended.
|
||||
@return error code, including
|
||||
@retval DB_SUCCESS on success
|
||||
@retval DB_OVERFLOW if the updated record does not fit
|
||||
@retval DB_UNDERFLOW if the page would become too empty
|
||||
@retval DB_ZIP_OVERFLOW if there is not enough space left
|
||||
on the compressed page */
|
||||
UNIV_INTERN
|
||||
dberr_t
|
||||
btr_cur_optimistic_update(
|
||||
/*======================*/
|
||||
ulint flags, /*!< in: undo logging and locking flags */
|
||||
btr_cur_t* cursor, /*!< in: cursor on the record to update;
|
||||
cursor stays valid and positioned on the
|
||||
same record */
|
||||
ulint** offsets,/*!< out: offsets on cursor->page_cur.rec */
|
||||
mem_heap_t** heap, /*!< in/out: pointer to NULL or memory heap */
|
||||
const upd_t* update, /*!< in: update vector; this must also
|
||||
contain trx id and roll ptr fields */
|
||||
ulint cmpl_info,/*!< in: compiler info on secondary index
|
||||
updates */
|
||||
que_thr_t* thr, /*!< in: query thread */
|
||||
trx_id_t trx_id, /*!< in: transaction id */
|
||||
mtr_t* mtr) /*!< in/out: mini-transaction; if this
|
||||
is a secondary index, the caller must
|
||||
mtr_commit(mtr) before latching any
|
||||
further pages */
|
||||
__attribute__((warn_unused_result, nonnull));
|
||||
/*************************************************************//**
|
||||
Performs an update of a record on a page of a tree. It is assumed
|
||||
that mtr holds an x-latch on the tree and on the cursor page. If the
|
||||
update is made on the leaf level, to avoid deadlocks, mtr must also
|
||||
own x-latches to brothers of page, if those brothers exist.
|
||||
@return DB_SUCCESS or error code */
|
||||
UNIV_INTERN
|
||||
dberr_t
|
||||
btr_cur_pessimistic_update(
|
||||
/*=======================*/
|
||||
ulint flags, /*!< in: undo logging, locking, and rollback
|
||||
flags */
|
||||
btr_cur_t* cursor, /*!< in/out: cursor on the record to update;
|
||||
cursor may become invalid if *big_rec == NULL
|
||||
|| !(flags & BTR_KEEP_POS_FLAG) */
|
||||
ulint** offsets,/*!< out: offsets on cursor->page_cur.rec */
|
||||
mem_heap_t** offsets_heap,
|
||||
/*!< in/out: pointer to memory heap
|
||||
that can be emptied, or NULL */
|
||||
mem_heap_t* entry_heap,
|
||||
/*!< in/out: memory heap for allocating
|
||||
big_rec and the index tuple */
|
||||
big_rec_t** big_rec,/*!< out: big rec vector whose fields have to
|
||||
be stored externally by the caller, or NULL */
|
||||
const upd_t* update, /*!< in: update vector; this is allowed also
|
||||
contain trx id and roll ptr fields, but
|
||||
the values in update vector have no effect */
|
||||
ulint cmpl_info,/*!< in: compiler info on secondary index
|
||||
updates */
|
||||
que_thr_t* thr, /*!< in: query thread */
|
||||
trx_id_t trx_id, /*!< in: transaction id */
|
||||
mtr_t* mtr) /*!< in/out: mini-transaction; must be committed
|
||||
before latching any further pages */
|
||||
__attribute__((warn_unused_result, nonnull));
|
||||
/***********************************************************//**
|
||||
Marks a clustered index record deleted. Writes an undo log record to
|
||||
undo log on this delete marking. Writes in the trx id field the id
|
||||
of the deleting transaction, and in the roll ptr field pointer to the
|
||||
undo log record created.
|
||||
@return DB_SUCCESS, DB_LOCK_WAIT, or error number */
|
||||
UNIV_INTERN
|
||||
dberr_t
|
||||
btr_cur_del_mark_set_clust_rec(
|
||||
/*===========================*/
|
||||
buf_block_t* block, /*!< in/out: buffer block of the record */
|
||||
rec_t* rec, /*!< in/out: record */
|
||||
dict_index_t* index, /*!< in: clustered index of the record */
|
||||
const ulint* offsets,/*!< in: rec_get_offsets(rec) */
|
||||
que_thr_t* thr, /*!< in: query thread */
|
||||
mtr_t* mtr) /*!< in/out: mini-transaction */
|
||||
__attribute__((nonnull, warn_unused_result));
|
||||
/***********************************************************//**
|
||||
Sets a secondary index record delete mark to TRUE or FALSE.
|
||||
@return DB_SUCCESS, DB_LOCK_WAIT, or error number */
|
||||
UNIV_INTERN
|
||||
dberr_t
|
||||
btr_cur_del_mark_set_sec_rec(
|
||||
/*=========================*/
|
||||
ulint flags, /*!< in: locking flag */
|
||||
btr_cur_t* cursor, /*!< in: cursor */
|
||||
ibool val, /*!< in: value to set */
|
||||
que_thr_t* thr, /*!< in: query thread */
|
||||
mtr_t* mtr) /*!< in/out: mini-transaction */
|
||||
__attribute__((nonnull, warn_unused_result));
|
||||
/*************************************************************//**
|
||||
Tries to compress a page of the tree if it seems useful. It is assumed
|
||||
that mtr holds an x-latch on the tree and on the cursor page. To avoid
|
||||
deadlocks, mtr must also own x-latches to brothers of page, if those
|
||||
brothers exist. NOTE: it is assumed that the caller has reserved enough
|
||||
free extents so that the compression will always succeed if done!
|
||||
@return TRUE if compression occurred */
|
||||
UNIV_INTERN
|
||||
ibool
|
||||
btr_cur_compress_if_useful(
|
||||
/*=======================*/
|
||||
btr_cur_t* cursor, /*!< in/out: cursor on the page to compress;
|
||||
cursor does not stay valid if compression
|
||||
occurs */
|
||||
ibool adjust, /*!< in: TRUE if should adjust the
|
||||
cursor position even if compression occurs */
|
||||
mtr_t* mtr) /*!< in/out: mini-transaction */
|
||||
__attribute__((nonnull));
|
||||
/*******************************************************//**
|
||||
Removes the record on which the tree cursor is positioned. It is assumed
|
||||
that the mtr has an x-latch on the page where the cursor is positioned,
|
||||
but no latch on the whole tree.
|
||||
@return TRUE if success, i.e., the page did not become too empty */
|
||||
UNIV_INTERN
|
||||
ibool
|
||||
btr_cur_optimistic_delete_func(
|
||||
/*===========================*/
|
||||
btr_cur_t* cursor, /*!< in: cursor on the record to delete;
|
||||
cursor stays valid: if deletion succeeds,
|
||||
on function exit it points to the successor
|
||||
of the deleted record */
|
||||
# ifdef UNIV_DEBUG
|
||||
ulint flags, /*!< in: BTR_CREATE_FLAG or 0 */
|
||||
# endif /* UNIV_DEBUG */
|
||||
mtr_t* mtr) /*!< in: mtr; if this function returns
|
||||
TRUE on a leaf page of a secondary
|
||||
index, the mtr must be committed
|
||||
before latching any further pages */
|
||||
__attribute__((nonnull, warn_unused_result));
|
||||
# ifdef UNIV_DEBUG
|
||||
# define btr_cur_optimistic_delete(cursor, flags, mtr) \
|
||||
btr_cur_optimistic_delete_func(cursor, flags, mtr)
|
||||
# else /* UNIV_DEBUG */
|
||||
# define btr_cur_optimistic_delete(cursor, flags, mtr) \
|
||||
btr_cur_optimistic_delete_func(cursor, mtr)
|
||||
# endif /* UNIV_DEBUG */
|
||||
/*************************************************************//**
|
||||
Removes the record on which the tree cursor is positioned. Tries
|
||||
to compress the page if its fillfactor drops below a threshold
|
||||
or if it is the only page on the level. It is assumed that mtr holds
|
||||
an x-latch on the tree and on the cursor page. To avoid deadlocks,
|
||||
mtr must also own x-latches to brothers of page, if those brothers
|
||||
exist.
|
||||
@return TRUE if compression occurred */
|
||||
UNIV_INTERN
|
||||
ibool
|
||||
btr_cur_pessimistic_delete(
|
||||
/*=======================*/
|
||||
dberr_t* err, /*!< out: DB_SUCCESS or DB_OUT_OF_FILE_SPACE;
|
||||
the latter may occur because we may have
|
||||
to update node pointers on upper levels,
|
||||
and in the case of variable length keys
|
||||
these may actually grow in size */
|
||||
ibool has_reserved_extents, /*!< in: TRUE if the
|
||||
caller has already reserved enough free
|
||||
extents so that he knows that the operation
|
||||
will succeed */
|
||||
btr_cur_t* cursor, /*!< in: cursor on the record to delete;
|
||||
if compression does not occur, the cursor
|
||||
stays valid: it points to successor of
|
||||
deleted record on function exit */
|
||||
ulint flags, /*!< in: BTR_CREATE_FLAG or 0 */
|
||||
enum trx_rb_ctx rb_ctx, /*!< in: rollback context */
|
||||
mtr_t* mtr) /*!< in: mtr */
|
||||
__attribute__((nonnull));
|
||||
#endif /* !UNIV_HOTBACKUP */
|
||||
/***********************************************************//**
|
||||
Parses a redo log record of updating a record in-place.
|
||||
@return end of log record or NULL */
|
||||
UNIV_INTERN
|
||||
byte*
|
||||
btr_cur_parse_update_in_place(
|
||||
/*==========================*/
|
||||
byte* ptr, /*!< in: buffer */
|
||||
byte* end_ptr,/*!< in: buffer end */
|
||||
page_t* page, /*!< in/out: page or NULL */
|
||||
page_zip_des_t* page_zip,/*!< in/out: compressed page, or NULL */
|
||||
dict_index_t* index); /*!< in: index corresponding to page */
|
||||
/****************************************************************//**
|
||||
Parses the redo log record for delete marking or unmarking of a clustered
|
||||
index record.
|
||||
@return end of log record or NULL */
|
||||
UNIV_INTERN
|
||||
byte*
|
||||
btr_cur_parse_del_mark_set_clust_rec(
|
||||
/*=================================*/
|
||||
byte* ptr, /*!< in: buffer */
|
||||
byte* end_ptr,/*!< in: buffer end */
|
||||
page_t* page, /*!< in/out: page or NULL */
|
||||
page_zip_des_t* page_zip,/*!< in/out: compressed page, or NULL */
|
||||
dict_index_t* index); /*!< in: index corresponding to page */
|
||||
/****************************************************************//**
|
||||
Parses the redo log record for delete marking or unmarking of a secondary
|
||||
index record.
|
||||
@return end of log record or NULL */
|
||||
UNIV_INTERN
|
||||
byte*
|
||||
btr_cur_parse_del_mark_set_sec_rec(
|
||||
/*===============================*/
|
||||
byte* ptr, /*!< in: buffer */
|
||||
byte* end_ptr,/*!< in: buffer end */
|
||||
page_t* page, /*!< in/out: page or NULL */
|
||||
page_zip_des_t* page_zip);/*!< in/out: compressed page, or NULL */
|
||||
#ifndef UNIV_HOTBACKUP
|
||||
/*******************************************************************//**
|
||||
Estimates the number of rows in a given index range.
|
||||
@return estimated number of rows */
|
||||
UNIV_INTERN
|
||||
ib_int64_t
|
||||
btr_estimate_n_rows_in_range(
|
||||
/*=========================*/
|
||||
dict_index_t* index, /*!< in: index */
|
||||
const dtuple_t* tuple1, /*!< in: range start, may also be empty tuple */
|
||||
ulint mode1, /*!< in: search mode for range start */
|
||||
const dtuple_t* tuple2, /*!< in: range end, may also be empty tuple */
|
||||
ulint mode2); /*!< in: search mode for range end */
|
||||
/*******************************************************************//**
|
||||
Estimates the number of different key values in a given index, for
|
||||
each n-column prefix of the index where 1 <= n <= dict_index_get_n_unique(index).
|
||||
The estimates are stored in the array index->stat_n_diff_key_vals[] (indexed
|
||||
0..n_uniq-1) and the number of pages that were sampled is saved in
|
||||
index->stat_n_sample_sizes[].
|
||||
If innodb_stats_method is nulls_ignored, we also record the number of
|
||||
non-null values for each prefix and stored the estimates in
|
||||
array index->stat_n_non_null_key_vals. */
|
||||
UNIV_INTERN
|
||||
void
|
||||
btr_estimate_number_of_different_key_vals(
|
||||
/*======================================*/
|
||||
dict_index_t* index); /*!< in: index */
|
||||
|
||||
/** Gets the externally stored size of a record, in units of a database page.
|
||||
@param[in] rec record
|
||||
@param[in] offsets array returned by rec_get_offsets()
|
||||
@return externally stored part, in units of a database page */
|
||||
|
||||
ulint
|
||||
btr_rec_get_externally_stored_len(
|
||||
const rec_t* rec,
|
||||
const ulint* offsets);
|
||||
|
||||
/*******************************************************************//**
|
||||
Marks non-updated off-page fields as disowned by this record. The ownership
|
||||
must be transferred to the updated record which is inserted elsewhere in the
|
||||
index tree. In purge only the owner of externally stored field is allowed
|
||||
to free the field. */
|
||||
UNIV_INTERN
|
||||
void
|
||||
btr_cur_disown_inherited_fields(
|
||||
/*============================*/
|
||||
page_zip_des_t* page_zip,/*!< in/out: compressed page whose uncompressed
|
||||
part will be updated, or NULL */
|
||||
rec_t* rec, /*!< in/out: record in a clustered index */
|
||||
dict_index_t* index, /*!< in: index of the page */
|
||||
const ulint* offsets,/*!< in: array returned by rec_get_offsets() */
|
||||
const upd_t* update, /*!< in: update vector */
|
||||
mtr_t* mtr) /*!< in/out: mini-transaction */
|
||||
__attribute__((nonnull(2,3,4,5,6)));
|
||||
|
||||
/** Operation code for btr_store_big_rec_extern_fields(). */
|
||||
enum blob_op {
|
||||
/** Store off-page columns for a freshly inserted record */
|
||||
BTR_STORE_INSERT = 0,
|
||||
/** Store off-page columns for an insert by update */
|
||||
BTR_STORE_INSERT_UPDATE,
|
||||
/** Store off-page columns for an update */
|
||||
BTR_STORE_UPDATE
|
||||
};
|
||||
|
||||
/*******************************************************************//**
|
||||
Determine if an operation on off-page columns is an update.
|
||||
@return TRUE if op != BTR_STORE_INSERT */
|
||||
UNIV_INLINE
|
||||
ibool
|
||||
btr_blob_op_is_update(
|
||||
/*==================*/
|
||||
enum blob_op op) /*!< in: operation */
|
||||
__attribute__((warn_unused_result));
|
||||
|
||||
/*******************************************************************//**
|
||||
Stores the fields in big_rec_vec to the tablespace and puts pointers to
|
||||
them in rec. The extern flags in rec will have to be set beforehand.
|
||||
The fields are stored on pages allocated from leaf node
|
||||
file segment of the index tree.
|
||||
@return DB_SUCCESS or DB_OUT_OF_FILE_SPACE */
|
||||
UNIV_INTERN
|
||||
dberr_t
|
||||
btr_store_big_rec_extern_fields(
|
||||
/*============================*/
|
||||
dict_index_t* index, /*!< in: index of rec; the index tree
|
||||
MUST be X-latched */
|
||||
buf_block_t* rec_block, /*!< in/out: block containing rec */
|
||||
rec_t* rec, /*!< in/out: record */
|
||||
const ulint* offsets, /*!< in: rec_get_offsets(rec, index);
|
||||
the "external storage" flags in offsets
|
||||
will not correspond to rec when
|
||||
this function returns */
|
||||
const big_rec_t*big_rec_vec, /*!< in: vector containing fields
|
||||
to be stored externally */
|
||||
mtr_t* btr_mtr, /*!< in: mtr containing the
|
||||
latches to the clustered index */
|
||||
enum blob_op op) /*! in: operation code */
|
||||
__attribute__((nonnull, warn_unused_result));
|
||||
|
||||
/*******************************************************************//**
|
||||
Frees the space in an externally stored field to the file space
|
||||
management if the field in data is owned the externally stored field,
|
||||
in a rollback we may have the additional condition that the field must
|
||||
not be inherited. */
|
||||
UNIV_INTERN
|
||||
void
|
||||
btr_free_externally_stored_field(
|
||||
/*=============================*/
|
||||
dict_index_t* index, /*!< in: index of the data, the index
|
||||
tree MUST be X-latched; if the tree
|
||||
height is 1, then also the root page
|
||||
must be X-latched! (this is relevant
|
||||
in the case this function is called
|
||||
from purge where 'data' is located on
|
||||
an undo log page, not an index
|
||||
page) */
|
||||
byte* field_ref, /*!< in/out: field reference */
|
||||
const rec_t* rec, /*!< in: record containing field_ref, for
|
||||
page_zip_write_blob_ptr(), or NULL */
|
||||
const ulint* offsets, /*!< in: rec_get_offsets(rec, index),
|
||||
or NULL */
|
||||
page_zip_des_t* page_zip, /*!< in: compressed page corresponding
|
||||
to rec, or NULL if rec == NULL */
|
||||
ulint i, /*!< in: field number of field_ref;
|
||||
ignored if rec == NULL */
|
||||
enum trx_rb_ctx rb_ctx, /*!< in: rollback context */
|
||||
mtr_t* local_mtr); /*!< in: mtr containing the latch to
|
||||
data an an X-latch to the index
|
||||
tree */
|
||||
/*******************************************************************//**
|
||||
Copies the prefix of an externally stored field of a record. The
|
||||
clustered index record must be protected by a lock or a page latch.
|
||||
@return the length of the copied field, or 0 if the column was being
|
||||
or has been deleted */
|
||||
UNIV_INTERN
|
||||
ulint
|
||||
btr_copy_externally_stored_field_prefix(
|
||||
/*====================================*/
|
||||
byte* buf, /*!< out: the field, or a prefix of it */
|
||||
ulint len, /*!< in: length of buf, in bytes */
|
||||
ulint zip_size,/*!< in: nonzero=compressed BLOB page size,
|
||||
zero for uncompressed BLOBs */
|
||||
const byte* data, /*!< in: 'internally' stored part of the
|
||||
field containing also the reference to
|
||||
the external part; must be protected by
|
||||
a lock or a page latch */
|
||||
ulint local_len);/*!< in: length of data, in bytes */
|
||||
/*******************************************************************//**
|
||||
Copies an externally stored field of a record to mem heap. The
|
||||
clustered index record must be protected by a lock or a page latch.
|
||||
@return the whole field copied to heap */
|
||||
UNIV_INTERN
|
||||
byte*
|
||||
btr_copy_externally_stored_field(
|
||||
/*=============================*/
|
||||
ulint* len, /*!< out: length of the whole field */
|
||||
const byte* data, /*!< in: 'internally' stored part of the
|
||||
field containing also the reference to
|
||||
the external part; must be protected by
|
||||
a lock or a page latch */
|
||||
ulint zip_size,/*!< in: nonzero=compressed BLOB page size,
|
||||
zero for uncompressed BLOBs */
|
||||
ulint local_len,/*!< in: length of data */
|
||||
mem_heap_t* heap); /*!< in: mem heap */
|
||||
/*******************************************************************//**
|
||||
Copies an externally stored field of a record to mem heap.
|
||||
@return the field copied to heap, or NULL if the field is incomplete */
|
||||
UNIV_INTERN
|
||||
byte*
|
||||
btr_rec_copy_externally_stored_field(
|
||||
/*=================================*/
|
||||
const rec_t* rec, /*!< in: record in a clustered index;
|
||||
must be protected by a lock or a page latch */
|
||||
const ulint* offsets,/*!< in: array returned by rec_get_offsets() */
|
||||
ulint zip_size,/*!< in: nonzero=compressed BLOB page size,
|
||||
zero for uncompressed BLOBs */
|
||||
ulint no, /*!< in: field number */
|
||||
ulint* len, /*!< out: length of the field */
|
||||
mem_heap_t* heap); /*!< in: mem heap */
|
||||
/*******************************************************************//**
|
||||
Flags the data tuple fields that are marked as extern storage in the
|
||||
update vector. We use this function to remember which fields we must
|
||||
mark as extern storage in a record inserted for an update.
|
||||
@return number of flagged external columns */
|
||||
UNIV_INTERN
|
||||
ulint
|
||||
btr_push_update_extern_fields(
|
||||
/*==========================*/
|
||||
dtuple_t* tuple, /*!< in/out: data tuple */
|
||||
const upd_t* update, /*!< in: update vector */
|
||||
mem_heap_t* heap) /*!< in: memory heap */
|
||||
__attribute__((nonnull));
|
||||
/***********************************************************//**
|
||||
Sets a secondary index record's delete mark to the given value. This
|
||||
function is only used by the insert buffer merge mechanism. */
|
||||
UNIV_INTERN
|
||||
void
|
||||
btr_cur_set_deleted_flag_for_ibuf(
|
||||
/*==============================*/
|
||||
rec_t* rec, /*!< in/out: record */
|
||||
page_zip_des_t* page_zip, /*!< in/out: compressed page
|
||||
corresponding to rec, or NULL
|
||||
when the tablespace is
|
||||
uncompressed */
|
||||
ibool val, /*!< in: value to set */
|
||||
mtr_t* mtr); /*!< in/out: mini-transaction */
|
||||
/*######################################################################*/
|
||||
|
||||
/** In the pessimistic delete, if the page data size drops below this
|
||||
limit, merging it to a neighbor is tried */
|
||||
#define BTR_CUR_PAGE_COMPRESS_LIMIT (UNIV_PAGE_SIZE / 2)
|
||||
|
||||
/** A slot in the path array. We store here info on a search path down the
|
||||
tree. Each slot contains data on a single level of the tree. */
|
||||
|
||||
struct btr_path_t{
|
||||
ulint nth_rec; /*!< index of the record
|
||||
where the page cursor stopped on
|
||||
this level (index in alphabetical
|
||||
order); value ULINT_UNDEFINED
|
||||
denotes array end */
|
||||
ulint n_recs; /*!< number of records on the page */
|
||||
ulint page_no; /*!< no of the page containing the record */
|
||||
ulint page_level; /*!< level of the page, if later we fetch
|
||||
the page under page_no and it is no different
|
||||
level then we know that the tree has been
|
||||
reorganized */
|
||||
};
|
||||
|
||||
#define BTR_PATH_ARRAY_N_SLOTS 250 /*!< size of path array (in slots) */
|
||||
|
||||
/** Values for the flag documenting the used search method */
|
||||
enum btr_cur_method {
|
||||
BTR_CUR_HASH = 1, /*!< successful shortcut using
|
||||
the hash index */
|
||||
BTR_CUR_HASH_FAIL, /*!< failure using hash, success using
|
||||
binary search: the misleading hash
|
||||
reference is stored in the field
|
||||
hash_node, and might be necessary to
|
||||
update */
|
||||
BTR_CUR_BINARY, /*!< success using the binary search */
|
||||
BTR_CUR_INSERT_TO_IBUF, /*!< performed the intended insert to
|
||||
the insert buffer */
|
||||
BTR_CUR_DEL_MARK_IBUF, /*!< performed the intended delete
|
||||
mark in the insert/delete buffer */
|
||||
BTR_CUR_DELETE_IBUF, /*!< performed the intended delete in
|
||||
the insert/delete buffer */
|
||||
BTR_CUR_DELETE_REF /*!< row_purge_poss_sec() failed */
|
||||
};
|
||||
|
||||
/** The tree cursor: the definition appears here only for the compiler
|
||||
to know struct size! */
|
||||
struct btr_cur_t {
|
||||
dict_index_t* index; /*!< index where positioned */
|
||||
page_cur_t page_cur; /*!< page cursor */
|
||||
purge_node_t* purge_node; /*!< purge node, for BTR_DELETE */
|
||||
buf_block_t* left_block; /*!< this field is used to store
|
||||
a pointer to the left neighbor
|
||||
page, in the cases
|
||||
BTR_SEARCH_PREV and
|
||||
BTR_MODIFY_PREV */
|
||||
/*------------------------------*/
|
||||
que_thr_t* thr; /*!< this field is only used
|
||||
when btr_cur_search_to_nth_level
|
||||
is called for an index entry
|
||||
insertion: the calling query
|
||||
thread is passed here to be
|
||||
used in the insert buffer */
|
||||
/*------------------------------*/
|
||||
/** The following fields are used in
|
||||
btr_cur_search_to_nth_level to pass information: */
|
||||
/* @{ */
|
||||
enum btr_cur_method flag; /*!< Search method used */
|
||||
ulint tree_height; /*!< Tree height if the search is done
|
||||
for a pessimistic insert or update
|
||||
operation */
|
||||
ulint up_match; /*!< If the search mode was PAGE_CUR_LE,
|
||||
the number of matched fields to the
|
||||
the first user record to the right of
|
||||
the cursor record after
|
||||
btr_cur_search_to_nth_level;
|
||||
for the mode PAGE_CUR_GE, the matched
|
||||
fields to the first user record AT THE
|
||||
CURSOR or to the right of it;
|
||||
NOTE that the up_match and low_match
|
||||
values may exceed the correct values
|
||||
for comparison to the adjacent user
|
||||
record if that record is on a
|
||||
different leaf page! (See the note in
|
||||
row_ins_duplicate_error_in_clust.) */
|
||||
ulint up_bytes; /*!< number of matched bytes to the
|
||||
right at the time cursor positioned;
|
||||
only used internally in searches: not
|
||||
defined after the search */
|
||||
ulint low_match; /*!< if search mode was PAGE_CUR_LE,
|
||||
the number of matched fields to the
|
||||
first user record AT THE CURSOR or
|
||||
to the left of it after
|
||||
btr_cur_search_to_nth_level;
|
||||
NOT defined for PAGE_CUR_GE or any
|
||||
other search modes; see also the NOTE
|
||||
in up_match! */
|
||||
ulint low_bytes; /*!< number of matched bytes to the
|
||||
right at the time cursor positioned;
|
||||
only used internally in searches: not
|
||||
defined after the search */
|
||||
ulint n_fields; /*!< prefix length used in a hash
|
||||
search if hash_node != NULL */
|
||||
ulint n_bytes; /*!< hash prefix bytes if hash_node !=
|
||||
NULL */
|
||||
ulint fold; /*!< fold value used in the search if
|
||||
flag is BTR_CUR_HASH */
|
||||
/* @} */
|
||||
btr_path_t* path_arr; /*!< in estimating the number of
|
||||
rows in range, we store in this array
|
||||
information of the path through
|
||||
the tree */
|
||||
};
|
||||
|
||||
/** If pessimistic delete fails because of lack of file space, there
|
||||
is still a good change of success a little later. Try this many
|
||||
times. */
|
||||
#define BTR_CUR_RETRY_DELETE_N_TIMES 100
|
||||
/** If pessimistic delete fails because of lack of file space, there
|
||||
is still a good change of success a little later. Sleep this many
|
||||
microseconds between retries. */
|
||||
#define BTR_CUR_RETRY_SLEEP_TIME 50000
|
||||
|
||||
/** The reference in a field for which data is stored on a different page.
|
||||
The reference is at the end of the 'locally' stored part of the field.
|
||||
'Locally' means storage in the index record.
|
||||
We store locally a long enough prefix of each column so that we can determine
|
||||
the ordering parts of each index record without looking into the externally
|
||||
stored part. */
|
||||
/*-------------------------------------- @{ */
|
||||
#define BTR_EXTERN_SPACE_ID 0 /*!< space id where stored */
|
||||
#define BTR_EXTERN_PAGE_NO 4 /*!< page no where stored */
|
||||
#define BTR_EXTERN_OFFSET 8 /*!< offset of BLOB header
|
||||
on that page */
|
||||
#define BTR_EXTERN_LEN 12 /*!< 8 bytes containing the
|
||||
length of the externally
|
||||
stored part of the BLOB.
|
||||
The 2 highest bits are
|
||||
reserved to the flags below. */
|
||||
/*-------------------------------------- @} */
|
||||
/* #define BTR_EXTERN_FIELD_REF_SIZE 20 // moved to btr0types.h */
|
||||
|
||||
/** The most significant bit of BTR_EXTERN_LEN (i.e., the most
|
||||
significant bit of the byte at smallest address) is set to 1 if this
|
||||
field does not 'own' the externally stored field; only the owner field
|
||||
is allowed to free the field in purge! */
|
||||
#define BTR_EXTERN_OWNER_FLAG 128
|
||||
/** If the second most significant bit of BTR_EXTERN_LEN (i.e., the
|
||||
second most significant bit of the byte at smallest address) is 1 then
|
||||
it means that the externally stored field was inherited from an
|
||||
earlier version of the row. In rollback we are not allowed to free an
|
||||
inherited external field. */
|
||||
#define BTR_EXTERN_INHERITED_FLAG 64
|
||||
|
||||
/** Number of searches down the B-tree in btr_cur_search_to_nth_level(). */
|
||||
extern ulint btr_cur_n_non_sea;
|
||||
/** Number of successful adaptive hash index lookups in
|
||||
btr_cur_search_to_nth_level(). */
|
||||
extern ulint btr_cur_n_sea;
|
||||
/** Old value of btr_cur_n_non_sea. Copied by
|
||||
srv_refresh_innodb_monitor_stats(). Referenced by
|
||||
srv_printf_innodb_monitor(). */
|
||||
extern ulint btr_cur_n_non_sea_old;
|
||||
/** Old value of btr_cur_n_sea. Copied by
|
||||
srv_refresh_innodb_monitor_stats(). Referenced by
|
||||
srv_printf_innodb_monitor(). */
|
||||
extern ulint btr_cur_n_sea_old;
|
||||
#endif /* !UNIV_HOTBACKUP */
|
||||
|
||||
#ifdef UNIV_DEBUG
|
||||
/* Flag to limit optimistic insert records */
|
||||
extern uint btr_cur_limit_optimistic_insert_debug;
|
||||
#endif /* UNIV_DEBUG */
|
||||
|
||||
#ifndef UNIV_NONINL
|
||||
#include "btr0cur.ic"
|
||||
#endif
|
||||
|
||||
#endif
|
||||
223
storage/innobase/include/btr0cur.ic
Normal file
223
storage/innobase/include/btr0cur.ic
Normal file
|
|
@ -0,0 +1,223 @@
|
|||
/*****************************************************************************
|
||||
|
||||
Copyright (c) 1994, 2014, Oracle and/or its affiliates. All Rights Reserved.
|
||||
|
||||
This program is free software; you can redistribute it and/or modify it under
|
||||
the terms of the GNU General Public License as published by the Free Software
|
||||
Foundation; version 2 of the License.
|
||||
|
||||
This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
|
||||
FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License along with
|
||||
this program; if not, write to the Free Software Foundation, Inc.,
|
||||
51 Franklin Street, Suite 500, Boston, MA 02110-1335 USA
|
||||
|
||||
*****************************************************************************/
|
||||
|
||||
/**************************************************//**
|
||||
@file include/btr0cur.ic
|
||||
The index tree cursor
|
||||
|
||||
Created 10/16/1994 Heikki Tuuri
|
||||
*******************************************************/
|
||||
|
||||
#ifndef UNIV_HOTBACKUP
|
||||
#include "btr0btr.h"
|
||||
|
||||
#ifdef UNIV_DEBUG
|
||||
# define LIMIT_OPTIMISTIC_INSERT_DEBUG(NREC, CODE)\
|
||||
if (btr_cur_limit_optimistic_insert_debug > 1\
|
||||
&& (NREC) >= (ulint)btr_cur_limit_optimistic_insert_debug) {\
|
||||
CODE;\
|
||||
}
|
||||
#else
|
||||
# define LIMIT_OPTIMISTIC_INSERT_DEBUG(NREC, CODE)
|
||||
#endif /* UNIV_DEBUG */
|
||||
|
||||
#ifdef UNIV_DEBUG
|
||||
/*********************************************************//**
|
||||
Returns the page cursor component of a tree cursor.
|
||||
@return pointer to page cursor component */
|
||||
UNIV_INLINE
|
||||
page_cur_t*
|
||||
btr_cur_get_page_cur(
|
||||
/*=================*/
|
||||
const btr_cur_t* cursor) /*!< in: tree cursor */
|
||||
{
|
||||
return(&((btr_cur_t*) cursor)->page_cur);
|
||||
}
|
||||
|
||||
/*********************************************************//**
|
||||
Returns the buffer block on which the tree cursor is positioned.
|
||||
@return pointer to buffer block */
|
||||
UNIV_INLINE
|
||||
buf_block_t*
|
||||
btr_cur_get_block(
|
||||
/*==============*/
|
||||
const btr_cur_t* cursor) /*!< in: tree cursor */
|
||||
{
|
||||
return(page_cur_get_block(btr_cur_get_page_cur(cursor)));
|
||||
}
|
||||
|
||||
/*********************************************************//**
|
||||
Returns the record pointer of a tree cursor.
|
||||
@return pointer to record */
|
||||
UNIV_INLINE
|
||||
rec_t*
|
||||
btr_cur_get_rec(
|
||||
/*============*/
|
||||
const btr_cur_t* cursor) /*!< in: tree cursor */
|
||||
{
|
||||
return(page_cur_get_rec(btr_cur_get_page_cur(cursor)));
|
||||
}
|
||||
#endif /* UNIV_DEBUG */
|
||||
|
||||
/*********************************************************//**
|
||||
Returns the compressed page on which the tree cursor is positioned.
|
||||
@return pointer to compressed page, or NULL if the page is not compressed */
|
||||
UNIV_INLINE
|
||||
page_zip_des_t*
|
||||
btr_cur_get_page_zip(
|
||||
/*=================*/
|
||||
btr_cur_t* cursor) /*!< in: tree cursor */
|
||||
{
|
||||
return(buf_block_get_page_zip(btr_cur_get_block(cursor)));
|
||||
}
|
||||
|
||||
/*********************************************************//**
|
||||
Invalidates a tree cursor by setting record pointer to NULL. */
|
||||
UNIV_INLINE
|
||||
void
|
||||
btr_cur_invalidate(
|
||||
/*===============*/
|
||||
btr_cur_t* cursor) /*!< in: tree cursor */
|
||||
{
|
||||
page_cur_invalidate(&(cursor->page_cur));
|
||||
}
|
||||
|
||||
/*********************************************************//**
|
||||
Returns the page of a tree cursor.
|
||||
@return pointer to page */
|
||||
UNIV_INLINE
|
||||
page_t*
|
||||
btr_cur_get_page(
|
||||
/*=============*/
|
||||
btr_cur_t* cursor) /*!< in: tree cursor */
|
||||
{
|
||||
return(page_align(page_cur_get_rec(&(cursor->page_cur))));
|
||||
}
|
||||
|
||||
/*********************************************************//**
|
||||
Positions a tree cursor at a given record. */
|
||||
UNIV_INLINE
|
||||
void
|
||||
btr_cur_position(
|
||||
/*=============*/
|
||||
dict_index_t* index, /*!< in: index */
|
||||
rec_t* rec, /*!< in: record in tree */
|
||||
buf_block_t* block, /*!< in: buffer block of rec */
|
||||
btr_cur_t* cursor) /*!< out: cursor */
|
||||
{
|
||||
ut_ad(page_align(rec) == block->frame);
|
||||
|
||||
page_cur_position(rec, block, btr_cur_get_page_cur(cursor));
|
||||
|
||||
cursor->index = index;
|
||||
}
|
||||
|
||||
/*********************************************************************//**
|
||||
Checks if compressing an index page where a btr cursor is placed makes
|
||||
sense.
|
||||
@return TRUE if compression is recommended */
|
||||
UNIV_INLINE
|
||||
ibool
|
||||
btr_cur_compress_recommendation(
|
||||
/*============================*/
|
||||
btr_cur_t* cursor, /*!< in: btr cursor */
|
||||
mtr_t* mtr) /*!< in: mtr */
|
||||
{
|
||||
const page_t* page;
|
||||
|
||||
ut_ad(mtr_memo_contains(mtr, btr_cur_get_block(cursor),
|
||||
MTR_MEMO_PAGE_X_FIX));
|
||||
|
||||
page = btr_cur_get_page(cursor);
|
||||
|
||||
LIMIT_OPTIMISTIC_INSERT_DEBUG(page_get_n_recs(page) * 2,
|
||||
return(FALSE));
|
||||
|
||||
if ((page_get_data_size(page) < BTR_CUR_PAGE_COMPRESS_LIMIT)
|
||||
|| ((btr_page_get_next(page, mtr) == FIL_NULL)
|
||||
&& (btr_page_get_prev(page, mtr) == FIL_NULL))) {
|
||||
|
||||
/* The page fillfactor has dropped below a predefined
|
||||
minimum value OR the level in the B-tree contains just
|
||||
one page: we recommend compression if this is not the
|
||||
root page. */
|
||||
|
||||
return(dict_index_get_page(cursor->index)
|
||||
!= page_get_page_no(page));
|
||||
}
|
||||
|
||||
return(FALSE);
|
||||
}
|
||||
|
||||
/*********************************************************************//**
|
||||
Checks if the record on which the cursor is placed can be deleted without
|
||||
making tree compression necessary (or, recommended).
|
||||
@return TRUE if can be deleted without recommended compression */
|
||||
UNIV_INLINE
|
||||
ibool
|
||||
btr_cur_can_delete_without_compress(
|
||||
/*================================*/
|
||||
btr_cur_t* cursor, /*!< in: btr cursor */
|
||||
ulint rec_size,/*!< in: rec_get_size(btr_cur_get_rec(cursor))*/
|
||||
mtr_t* mtr) /*!< in: mtr */
|
||||
{
|
||||
page_t* page;
|
||||
|
||||
ut_ad(mtr_memo_contains(mtr, btr_cur_get_block(cursor),
|
||||
MTR_MEMO_PAGE_X_FIX));
|
||||
|
||||
page = btr_cur_get_page(cursor);
|
||||
|
||||
if ((page_get_data_size(page) - rec_size < BTR_CUR_PAGE_COMPRESS_LIMIT)
|
||||
|| ((btr_page_get_next(page, mtr) == FIL_NULL)
|
||||
&& (btr_page_get_prev(page, mtr) == FIL_NULL))
|
||||
|| (page_get_n_recs(page) < 2)) {
|
||||
|
||||
/* The page fillfactor will drop below a predefined
|
||||
minimum value, OR the level in the B-tree contains just
|
||||
one page, OR the page will become empty: we recommend
|
||||
compression if this is not the root page. */
|
||||
|
||||
return(dict_index_get_page(cursor->index)
|
||||
== page_get_page_no(page));
|
||||
}
|
||||
|
||||
return(TRUE);
|
||||
}
|
||||
|
||||
/*******************************************************************//**
|
||||
Determine if an operation on off-page columns is an update.
|
||||
@return TRUE if op != BTR_STORE_INSERT */
|
||||
UNIV_INLINE
|
||||
ibool
|
||||
btr_blob_op_is_update(
|
||||
/*==================*/
|
||||
enum blob_op op) /*!< in: operation */
|
||||
{
|
||||
switch (op) {
|
||||
case BTR_STORE_INSERT:
|
||||
return(FALSE);
|
||||
case BTR_STORE_INSERT_UPDATE:
|
||||
case BTR_STORE_UPDATE:
|
||||
return(TRUE);
|
||||
}
|
||||
|
||||
ut_ad(0);
|
||||
return(FALSE);
|
||||
}
|
||||
#endif /* !UNIV_HOTBACKUP */
|
||||
548
storage/innobase/include/btr0pcur.h
Normal file
548
storage/innobase/include/btr0pcur.h
Normal file
|
|
@ -0,0 +1,548 @@
|
|||
/*****************************************************************************
|
||||
|
||||
Copyright (c) 1996, 2013, Oracle and/or its affiliates. All Rights Reserved.
|
||||
|
||||
This program is free software; you can redistribute it and/or modify it under
|
||||
the terms of the GNU General Public License as published by the Free Software
|
||||
Foundation; version 2 of the License.
|
||||
|
||||
This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
|
||||
FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License along with
|
||||
this program; if not, write to the Free Software Foundation, Inc.,
|
||||
51 Franklin Street, Suite 500, Boston, MA 02110-1335 USA
|
||||
|
||||
*****************************************************************************/
|
||||
|
||||
/**************************************************//**
|
||||
@file include/btr0pcur.h
|
||||
The index tree persistent cursor
|
||||
|
||||
Created 2/23/1996 Heikki Tuuri
|
||||
*******************************************************/
|
||||
|
||||
#ifndef btr0pcur_h
|
||||
#define btr0pcur_h
|
||||
|
||||
#include "univ.i"
|
||||
#include "dict0dict.h"
|
||||
#include "data0data.h"
|
||||
#include "mtr0mtr.h"
|
||||
#include "page0cur.h"
|
||||
#include "btr0cur.h"
|
||||
#include "btr0btr.h"
|
||||
#include "btr0types.h"
|
||||
|
||||
/* Relative positions for a stored cursor position */
|
||||
#define BTR_PCUR_ON 1
|
||||
#define BTR_PCUR_BEFORE 2
|
||||
#define BTR_PCUR_AFTER 3
|
||||
/* Note that if the tree is not empty, btr_pcur_store_position does not
|
||||
use the following, but only uses the above three alternatives, where the
|
||||
position is stored relative to a specific record: this makes implementation
|
||||
of a scroll cursor easier */
|
||||
#define BTR_PCUR_BEFORE_FIRST_IN_TREE 4 /* in an empty tree */
|
||||
#define BTR_PCUR_AFTER_LAST_IN_TREE 5 /* in an empty tree */
|
||||
|
||||
/**************************************************************//**
|
||||
Allocates memory for a persistent cursor object and initializes the cursor.
|
||||
@return own: persistent cursor */
|
||||
UNIV_INTERN
|
||||
btr_pcur_t*
|
||||
btr_pcur_create_for_mysql(void);
|
||||
/*============================*/
|
||||
|
||||
/**************************************************************//**
|
||||
Resets a persistent cursor object, freeing ::old_rec_buf if it is
|
||||
allocated and resetting the other members to their initial values. */
|
||||
UNIV_INTERN
|
||||
void
|
||||
btr_pcur_reset(
|
||||
/*===========*/
|
||||
btr_pcur_t* cursor);/*!< in, out: persistent cursor */
|
||||
|
||||
/**************************************************************//**
|
||||
Frees the memory for a persistent cursor object. */
|
||||
UNIV_INTERN
|
||||
void
|
||||
btr_pcur_free_for_mysql(
|
||||
/*====================*/
|
||||
btr_pcur_t* cursor); /*!< in, own: persistent cursor */
|
||||
/**************************************************************//**
|
||||
Copies the stored position of a pcur to another pcur. */
|
||||
UNIV_INTERN
|
||||
void
|
||||
btr_pcur_copy_stored_position(
|
||||
/*==========================*/
|
||||
btr_pcur_t* pcur_receive, /*!< in: pcur which will receive the
|
||||
position info */
|
||||
btr_pcur_t* pcur_donate); /*!< in: pcur from which the info is
|
||||
copied */
|
||||
/**************************************************************//**
|
||||
Sets the old_rec_buf field to NULL. */
|
||||
UNIV_INLINE
|
||||
void
|
||||
btr_pcur_init(
|
||||
/*==========*/
|
||||
btr_pcur_t* pcur); /*!< in: persistent cursor */
|
||||
/**************************************************************//**
|
||||
Initializes and opens a persistent cursor to an index tree. It should be
|
||||
closed with btr_pcur_close. */
|
||||
UNIV_INLINE
|
||||
void
|
||||
btr_pcur_open_low(
|
||||
/*==============*/
|
||||
dict_index_t* index, /*!< in: index */
|
||||
ulint level, /*!< in: level in the btree */
|
||||
const dtuple_t* tuple, /*!< in: tuple on which search done */
|
||||
ulint mode, /*!< in: PAGE_CUR_L, ...;
|
||||
NOTE that if the search is made using a unique
|
||||
prefix of a record, mode should be
|
||||
PAGE_CUR_LE, not PAGE_CUR_GE, as the latter
|
||||
may end up on the previous page from the
|
||||
record! */
|
||||
ulint latch_mode,/*!< in: BTR_SEARCH_LEAF, ... */
|
||||
btr_pcur_t* cursor, /*!< in: memory buffer for persistent cursor */
|
||||
const char* file, /*!< in: file name */
|
||||
ulint line, /*!< in: line where called */
|
||||
mtr_t* mtr); /*!< in: mtr */
|
||||
#define btr_pcur_open(i,t,md,l,c,m) \
|
||||
btr_pcur_open_low(i,0,t,md,l,c,__FILE__,__LINE__,m)
|
||||
/**************************************************************//**
|
||||
Opens an persistent cursor to an index tree without initializing the
|
||||
cursor. */
|
||||
UNIV_INLINE
|
||||
void
|
||||
btr_pcur_open_with_no_init_func(
|
||||
/*============================*/
|
||||
dict_index_t* index, /*!< in: index */
|
||||
const dtuple_t* tuple, /*!< in: tuple on which search done */
|
||||
ulint mode, /*!< in: PAGE_CUR_L, ...;
|
||||
NOTE that if the search is made using a unique
|
||||
prefix of a record, mode should be
|
||||
PAGE_CUR_LE, not PAGE_CUR_GE, as the latter
|
||||
may end up on the previous page of the
|
||||
record! */
|
||||
ulint latch_mode,/*!< in: BTR_SEARCH_LEAF, ...;
|
||||
NOTE that if has_search_latch != 0 then
|
||||
we maybe do not acquire a latch on the cursor
|
||||
page, but assume that the caller uses his
|
||||
btr search latch to protect the record! */
|
||||
btr_pcur_t* cursor, /*!< in: memory buffer for persistent cursor */
|
||||
ulint has_search_latch,/*!< in: latch mode the caller
|
||||
currently has on btr_search_latch:
|
||||
RW_S_LATCH, or 0 */
|
||||
const char* file, /*!< in: file name */
|
||||
ulint line, /*!< in: line where called */
|
||||
mtr_t* mtr); /*!< in: mtr */
|
||||
#define btr_pcur_open_with_no_init(ix,t,md,l,cur,has,m) \
|
||||
btr_pcur_open_with_no_init_func(ix,t,md,l,cur,has,__FILE__,__LINE__,m)
|
||||
|
||||
/*****************************************************************//**
|
||||
Opens a persistent cursor at either end of an index. */
|
||||
UNIV_INLINE
|
||||
void
|
||||
btr_pcur_open_at_index_side(
|
||||
/*========================*/
|
||||
bool from_left, /*!< in: true if open to the low end,
|
||||
false if to the high end */
|
||||
dict_index_t* index, /*!< in: index */
|
||||
ulint latch_mode, /*!< in: latch mode */
|
||||
btr_pcur_t* pcur, /*!< in/out: cursor */
|
||||
bool init_pcur, /*!< in: whether to initialize pcur */
|
||||
ulint level, /*!< in: level to search for
|
||||
(0=leaf) */
|
||||
mtr_t* mtr) /*!< in/out: mini-transaction */
|
||||
__attribute__((nonnull));
|
||||
/**************************************************************//**
|
||||
Gets the up_match value for a pcur after a search.
|
||||
@return number of matched fields at the cursor or to the right if
|
||||
search mode was PAGE_CUR_GE, otherwise undefined */
|
||||
UNIV_INLINE
|
||||
ulint
|
||||
btr_pcur_get_up_match(
|
||||
/*==================*/
|
||||
const btr_pcur_t* cursor); /*!< in: persistent cursor */
|
||||
/**************************************************************//**
|
||||
Gets the low_match value for a pcur after a search.
|
||||
@return number of matched fields at the cursor or to the right if
|
||||
search mode was PAGE_CUR_LE, otherwise undefined */
|
||||
UNIV_INLINE
|
||||
ulint
|
||||
btr_pcur_get_low_match(
|
||||
/*===================*/
|
||||
const btr_pcur_t* cursor); /*!< in: persistent cursor */
|
||||
/**************************************************************//**
|
||||
If mode is PAGE_CUR_G or PAGE_CUR_GE, opens a persistent cursor on the first
|
||||
user record satisfying the search condition, in the case PAGE_CUR_L or
|
||||
PAGE_CUR_LE, on the last user record. If no such user record exists, then
|
||||
in the first case sets the cursor after last in tree, and in the latter case
|
||||
before first in tree. The latching mode must be BTR_SEARCH_LEAF or
|
||||
BTR_MODIFY_LEAF. */
|
||||
UNIV_INTERN
|
||||
void
|
||||
btr_pcur_open_on_user_rec_func(
|
||||
/*===========================*/
|
||||
dict_index_t* index, /*!< in: index */
|
||||
const dtuple_t* tuple, /*!< in: tuple on which search done */
|
||||
ulint mode, /*!< in: PAGE_CUR_L, ... */
|
||||
ulint latch_mode, /*!< in: BTR_SEARCH_LEAF or
|
||||
BTR_MODIFY_LEAF */
|
||||
btr_pcur_t* cursor, /*!< in: memory buffer for persistent
|
||||
cursor */
|
||||
const char* file, /*!< in: file name */
|
||||
ulint line, /*!< in: line where called */
|
||||
mtr_t* mtr); /*!< in: mtr */
|
||||
#define btr_pcur_open_on_user_rec(i,t,md,l,c,m) \
|
||||
btr_pcur_open_on_user_rec_func(i,t,md,l,c,__FILE__,__LINE__,m)
|
||||
/**********************************************************************//**
|
||||
Positions a cursor at a randomly chosen position within a B-tree. */
|
||||
UNIV_INLINE
|
||||
void
|
||||
btr_pcur_open_at_rnd_pos_func(
|
||||
/*==========================*/
|
||||
dict_index_t* index, /*!< in: index */
|
||||
ulint latch_mode, /*!< in: BTR_SEARCH_LEAF, ... */
|
||||
btr_pcur_t* cursor, /*!< in/out: B-tree pcur */
|
||||
const char* file, /*!< in: file name */
|
||||
ulint line, /*!< in: line where called */
|
||||
mtr_t* mtr); /*!< in: mtr */
|
||||
#define btr_pcur_open_at_rnd_pos(i,l,c,m) \
|
||||
btr_pcur_open_at_rnd_pos_func(i,l,c,__FILE__,__LINE__,m)
|
||||
/**************************************************************//**
|
||||
Frees the possible memory heap of a persistent cursor and sets the latch
|
||||
mode of the persistent cursor to BTR_NO_LATCHES.
|
||||
WARNING: this function does not release the latch on the page where the
|
||||
cursor is currently positioned. The latch is acquired by the
|
||||
"move to next/previous" family of functions. Since recursive shared locks
|
||||
are not allowed, you must take care (if using the cursor in S-mode) to
|
||||
manually release the latch by either calling
|
||||
btr_leaf_page_release(btr_pcur_get_block(&pcur), pcur.latch_mode, mtr)
|
||||
or by committing the mini-transaction right after btr_pcur_close().
|
||||
A subsequent attempt to crawl the same page in the same mtr would cause
|
||||
an assertion failure. */
|
||||
UNIV_INLINE
|
||||
void
|
||||
btr_pcur_close(
|
||||
/*===========*/
|
||||
btr_pcur_t* cursor); /*!< in: persistent cursor */
|
||||
/**************************************************************//**
|
||||
The position of the cursor is stored by taking an initial segment of the
|
||||
record the cursor is positioned on, before, or after, and copying it to the
|
||||
cursor data structure, or just setting a flag if the cursor id before the
|
||||
first in an EMPTY tree, or after the last in an EMPTY tree. NOTE that the
|
||||
page where the cursor is positioned must not be empty if the index tree is
|
||||
not totally empty! */
|
||||
UNIV_INTERN
|
||||
void
|
||||
btr_pcur_store_position(
|
||||
/*====================*/
|
||||
btr_pcur_t* cursor, /*!< in: persistent cursor */
|
||||
mtr_t* mtr); /*!< in: mtr */
|
||||
/**************************************************************//**
|
||||
Restores the stored position of a persistent cursor bufferfixing the page and
|
||||
obtaining the specified latches. If the cursor position was saved when the
|
||||
(1) cursor was positioned on a user record: this function restores the position
|
||||
to the last record LESS OR EQUAL to the stored record;
|
||||
(2) cursor was positioned on a page infimum record: restores the position to
|
||||
the last record LESS than the user record which was the successor of the page
|
||||
infimum;
|
||||
(3) cursor was positioned on the page supremum: restores to the first record
|
||||
GREATER than the user record which was the predecessor of the supremum.
|
||||
(4) cursor was positioned before the first or after the last in an empty tree:
|
||||
restores to before first or after the last in the tree.
|
||||
@return TRUE if the cursor position was stored when it was on a user
|
||||
record and it can be restored on a user record whose ordering fields
|
||||
are identical to the ones of the original user record */
|
||||
UNIV_INTERN
|
||||
ibool
|
||||
btr_pcur_restore_position_func(
|
||||
/*===========================*/
|
||||
ulint latch_mode, /*!< in: BTR_SEARCH_LEAF, ... */
|
||||
btr_pcur_t* cursor, /*!< in: detached persistent cursor */
|
||||
const char* file, /*!< in: file name */
|
||||
ulint line, /*!< in: line where called */
|
||||
mtr_t* mtr); /*!< in: mtr */
|
||||
#define btr_pcur_restore_position(l,cur,mtr) \
|
||||
btr_pcur_restore_position_func(l,cur,__FILE__,__LINE__,mtr)
|
||||
/*********************************************************//**
|
||||
Gets the rel_pos field for a cursor whose position has been stored.
|
||||
@return BTR_PCUR_ON, ... */
|
||||
UNIV_INLINE
|
||||
ulint
|
||||
btr_pcur_get_rel_pos(
|
||||
/*=================*/
|
||||
const btr_pcur_t* cursor);/*!< in: persistent cursor */
|
||||
/**************************************************************//**
|
||||
Commits the mtr and sets the pcur latch mode to BTR_NO_LATCHES,
|
||||
that is, the cursor becomes detached.
|
||||
Function btr_pcur_store_position should be used before calling this,
|
||||
if restoration of cursor is wanted later. */
|
||||
UNIV_INLINE
|
||||
void
|
||||
btr_pcur_commit_specify_mtr(
|
||||
/*========================*/
|
||||
btr_pcur_t* pcur, /*!< in: persistent cursor */
|
||||
mtr_t* mtr); /*!< in: mtr to commit */
|
||||
/*********************************************************//**
|
||||
Moves the persistent cursor to the next record in the tree. If no records are
|
||||
left, the cursor stays 'after last in tree'.
|
||||
@return TRUE if the cursor was not after last in tree */
|
||||
UNIV_INLINE
|
||||
ibool
|
||||
btr_pcur_move_to_next(
|
||||
/*==================*/
|
||||
btr_pcur_t* cursor, /*!< in: persistent cursor; NOTE that the
|
||||
function may release the page latch */
|
||||
mtr_t* mtr); /*!< in: mtr */
|
||||
/*********************************************************//**
|
||||
Moves the persistent cursor to the previous record in the tree. If no records
|
||||
are left, the cursor stays 'before first in tree'.
|
||||
@return TRUE if the cursor was not before first in tree */
|
||||
UNIV_INTERN
|
||||
ibool
|
||||
btr_pcur_move_to_prev(
|
||||
/*==================*/
|
||||
btr_pcur_t* cursor, /*!< in: persistent cursor; NOTE that the
|
||||
function may release the page latch */
|
||||
mtr_t* mtr); /*!< in: mtr */
|
||||
/*********************************************************//**
|
||||
Moves the persistent cursor to the last record on the same page. */
|
||||
UNIV_INLINE
|
||||
void
|
||||
btr_pcur_move_to_last_on_page(
|
||||
/*==========================*/
|
||||
btr_pcur_t* cursor, /*!< in: persistent cursor */
|
||||
mtr_t* mtr); /*!< in: mtr */
|
||||
/*********************************************************//**
|
||||
Moves the persistent cursor to the next user record in the tree. If no user
|
||||
records are left, the cursor ends up 'after last in tree'.
|
||||
@return TRUE if the cursor moved forward, ending on a user record */
|
||||
UNIV_INLINE
|
||||
ibool
|
||||
btr_pcur_move_to_next_user_rec(
|
||||
/*===========================*/
|
||||
btr_pcur_t* cursor, /*!< in: persistent cursor; NOTE that the
|
||||
function may release the page latch */
|
||||
mtr_t* mtr); /*!< in: mtr */
|
||||
/*********************************************************//**
|
||||
Moves the persistent cursor to the first record on the next page.
|
||||
Releases the latch on the current page, and bufferunfixes it.
|
||||
Note that there must not be modifications on the current page,
|
||||
as then the x-latch can be released only in mtr_commit. */
|
||||
UNIV_INTERN
|
||||
void
|
||||
btr_pcur_move_to_next_page(
|
||||
/*=======================*/
|
||||
btr_pcur_t* cursor, /*!< in: persistent cursor; must be on the
|
||||
last record of the current page */
|
||||
mtr_t* mtr); /*!< in: mtr */
|
||||
/*********************************************************//**
|
||||
Moves the persistent cursor backward if it is on the first record
|
||||
of the page. Releases the latch on the current page, and bufferunfixes
|
||||
it. Note that to prevent a possible deadlock, the operation first
|
||||
stores the position of the cursor, releases the leaf latch, acquires
|
||||
necessary latches and restores the cursor position again before returning.
|
||||
The alphabetical position of the cursor is guaranteed to be sensible
|
||||
on return, but it may happen that the cursor is not positioned on the
|
||||
last record of any page, because the structure of the tree may have
|
||||
changed while the cursor had no latches. */
|
||||
UNIV_INTERN
|
||||
void
|
||||
btr_pcur_move_backward_from_page(
|
||||
/*=============================*/
|
||||
btr_pcur_t* cursor, /*!< in: persistent cursor, must be on the
|
||||
first record of the current page */
|
||||
mtr_t* mtr); /*!< in: mtr */
|
||||
#ifdef UNIV_DEBUG
|
||||
/*********************************************************//**
|
||||
Returns the btr cursor component of a persistent cursor.
|
||||
@return pointer to btr cursor component */
|
||||
UNIV_INLINE
|
||||
btr_cur_t*
|
||||
btr_pcur_get_btr_cur(
|
||||
/*=================*/
|
||||
const btr_pcur_t* cursor); /*!< in: persistent cursor */
|
||||
/*********************************************************//**
|
||||
Returns the page cursor component of a persistent cursor.
|
||||
@return pointer to page cursor component */
|
||||
UNIV_INLINE
|
||||
page_cur_t*
|
||||
btr_pcur_get_page_cur(
|
||||
/*==================*/
|
||||
const btr_pcur_t* cursor); /*!< in: persistent cursor */
|
||||
/*********************************************************//**
|
||||
Returns the page of a persistent cursor.
|
||||
@return pointer to the page */
|
||||
UNIV_INLINE
|
||||
page_t*
|
||||
btr_pcur_get_page(
|
||||
/*==============*/
|
||||
const btr_pcur_t* cursor);/*!< in: persistent cursor */
|
||||
/*********************************************************//**
|
||||
Returns the buffer block of a persistent cursor.
|
||||
@return pointer to the block */
|
||||
UNIV_INLINE
|
||||
buf_block_t*
|
||||
btr_pcur_get_block(
|
||||
/*===============*/
|
||||
const btr_pcur_t* cursor);/*!< in: persistent cursor */
|
||||
/*********************************************************//**
|
||||
Returns the record of a persistent cursor.
|
||||
@return pointer to the record */
|
||||
UNIV_INLINE
|
||||
rec_t*
|
||||
btr_pcur_get_rec(
|
||||
/*=============*/
|
||||
const btr_pcur_t* cursor);/*!< in: persistent cursor */
|
||||
#else /* UNIV_DEBUG */
|
||||
# define btr_pcur_get_btr_cur(cursor) (&(cursor)->btr_cur)
|
||||
# define btr_pcur_get_page_cur(cursor) (&(cursor)->btr_cur.page_cur)
|
||||
# define btr_pcur_get_page(cursor) ((cursor)->btr_cur.page_cur.block->frame)
|
||||
# define btr_pcur_get_block(cursor) ((cursor)->btr_cur.page_cur.block)
|
||||
# define btr_pcur_get_rec(cursor) ((cursor)->btr_cur.page_cur.rec)
|
||||
#endif /* UNIV_DEBUG */
|
||||
/*********************************************************//**
|
||||
Checks if the persistent cursor is on a user record. */
|
||||
UNIV_INLINE
|
||||
ibool
|
||||
btr_pcur_is_on_user_rec(
|
||||
/*====================*/
|
||||
const btr_pcur_t* cursor);/*!< in: persistent cursor */
|
||||
/*********************************************************//**
|
||||
Checks if the persistent cursor is after the last user record on
|
||||
a page. */
|
||||
UNIV_INLINE
|
||||
ibool
|
||||
btr_pcur_is_after_last_on_page(
|
||||
/*===========================*/
|
||||
const btr_pcur_t* cursor);/*!< in: persistent cursor */
|
||||
/*********************************************************//**
|
||||
Checks if the persistent cursor is before the first user record on
|
||||
a page. */
|
||||
UNIV_INLINE
|
||||
ibool
|
||||
btr_pcur_is_before_first_on_page(
|
||||
/*=============================*/
|
||||
const btr_pcur_t* cursor);/*!< in: persistent cursor */
|
||||
/*********************************************************//**
|
||||
Checks if the persistent cursor is before the first user record in
|
||||
the index tree. */
|
||||
UNIV_INLINE
|
||||
ibool
|
||||
btr_pcur_is_before_first_in_tree(
|
||||
/*=============================*/
|
||||
btr_pcur_t* cursor, /*!< in: persistent cursor */
|
||||
mtr_t* mtr); /*!< in: mtr */
|
||||
/*********************************************************//**
|
||||
Checks if the persistent cursor is after the last user record in
|
||||
the index tree. */
|
||||
UNIV_INLINE
|
||||
ibool
|
||||
btr_pcur_is_after_last_in_tree(
|
||||
/*===========================*/
|
||||
btr_pcur_t* cursor, /*!< in: persistent cursor */
|
||||
mtr_t* mtr); /*!< in: mtr */
|
||||
/*********************************************************//**
|
||||
Moves the persistent cursor to the next record on the same page. */
|
||||
UNIV_INLINE
|
||||
void
|
||||
btr_pcur_move_to_next_on_page(
|
||||
/*==========================*/
|
||||
btr_pcur_t* cursor);/*!< in/out: persistent cursor */
|
||||
/*********************************************************//**
|
||||
Moves the persistent cursor to the previous record on the same page. */
|
||||
UNIV_INLINE
|
||||
void
|
||||
btr_pcur_move_to_prev_on_page(
|
||||
/*==========================*/
|
||||
btr_pcur_t* cursor);/*!< in/out: persistent cursor */
|
||||
/*********************************************************//**
|
||||
Moves the persistent cursor to the infimum record on the same page. */
|
||||
UNIV_INLINE
|
||||
void
|
||||
btr_pcur_move_before_first_on_page(
|
||||
/*===============================*/
|
||||
btr_pcur_t* cursor); /*!< in/out: persistent cursor */
|
||||
|
||||
/** Position state of persistent B-tree cursor. */
|
||||
enum pcur_pos_t {
|
||||
/** The persistent cursor is not positioned. */
|
||||
BTR_PCUR_NOT_POSITIONED = 0,
|
||||
/** The persistent cursor was previously positioned.
|
||||
TODO: currently, the state can be BTR_PCUR_IS_POSITIONED,
|
||||
though it really should be BTR_PCUR_WAS_POSITIONED,
|
||||
because we have no obligation to commit the cursor with
|
||||
mtr; similarly latch_mode may be out of date. This can
|
||||
lead to problems if btr_pcur is not used the right way;
|
||||
all current code should be ok. */
|
||||
BTR_PCUR_WAS_POSITIONED,
|
||||
/** The persistent cursor is positioned by optimistic get to the same
|
||||
record as it was positioned at. Not used for rel_pos == BTR_PCUR_ON.
|
||||
It may need adjustment depending on previous/current search direction
|
||||
and rel_pos. */
|
||||
BTR_PCUR_IS_POSITIONED_OPTIMISTIC,
|
||||
/** The persistent cursor is positioned by index search.
|
||||
Or optimistic get for rel_pos == BTR_PCUR_ON. */
|
||||
BTR_PCUR_IS_POSITIONED
|
||||
};
|
||||
|
||||
/* The persistent B-tree cursor structure. This is used mainly for SQL
|
||||
selects, updates, and deletes. */
|
||||
|
||||
struct btr_pcur_t{
|
||||
btr_cur_t btr_cur; /*!< a B-tree cursor */
|
||||
ulint latch_mode; /*!< see TODO note below!
|
||||
BTR_SEARCH_LEAF, BTR_MODIFY_LEAF,
|
||||
BTR_MODIFY_TREE, or BTR_NO_LATCHES,
|
||||
depending on the latching state of
|
||||
the page and tree where the cursor is
|
||||
positioned; BTR_NO_LATCHES means that
|
||||
the cursor is not currently positioned:
|
||||
we say then that the cursor is
|
||||
detached; it can be restored to
|
||||
attached if the old position was
|
||||
stored in old_rec */
|
||||
ulint old_stored; /*!< BTR_PCUR_OLD_STORED
|
||||
or BTR_PCUR_OLD_NOT_STORED */
|
||||
rec_t* old_rec; /*!< if cursor position is stored,
|
||||
contains an initial segment of the
|
||||
latest record cursor was positioned
|
||||
either on, before, or after */
|
||||
ulint old_n_fields; /*!< number of fields in old_rec */
|
||||
ulint rel_pos; /*!< BTR_PCUR_ON, BTR_PCUR_BEFORE, or
|
||||
BTR_PCUR_AFTER, depending on whether
|
||||
cursor was on, before, or after the
|
||||
old_rec record */
|
||||
buf_block_t* block_when_stored;/* buffer block when the position was
|
||||
stored */
|
||||
ib_uint64_t modify_clock; /*!< the modify clock value of the
|
||||
buffer block when the cursor position
|
||||
was stored */
|
||||
enum pcur_pos_t pos_state; /*!< btr_pcur_store_position() and
|
||||
btr_pcur_restore_position() state. */
|
||||
ulint search_mode; /*!< PAGE_CUR_G, ... */
|
||||
trx_t* trx_if_known; /*!< the transaction, if we know it;
|
||||
otherwise this field is not defined;
|
||||
can ONLY BE USED in error prints in
|
||||
fatal assertion failures! */
|
||||
/*-----------------------------*/
|
||||
/* NOTE that the following fields may possess dynamically allocated
|
||||
memory which should be freed if not needed anymore! */
|
||||
|
||||
byte* old_rec_buf; /*!< NULL, or a dynamically allocated
|
||||
buffer for old_rec */
|
||||
ulint buf_size; /*!< old_rec_buf size if old_rec_buf
|
||||
is not NULL */
|
||||
};
|
||||
|
||||
#define BTR_PCUR_OLD_STORED 908467085
|
||||
#define BTR_PCUR_OLD_NOT_STORED 122766467
|
||||
|
||||
#ifndef UNIV_NONINL
|
||||
#include "btr0pcur.ic"
|
||||
#endif
|
||||
|
||||
#endif
|
||||
606
storage/innobase/include/btr0pcur.ic
Normal file
606
storage/innobase/include/btr0pcur.ic
Normal file
|
|
@ -0,0 +1,606 @@
|
|||
/*****************************************************************************
|
||||
|
||||
Copyright (c) 1996, 2013, Oracle and/or its affiliates. All Rights Reserved.
|
||||
|
||||
This program is free software; you can redistribute it and/or modify it under
|
||||
the terms of the GNU General Public License as published by the Free Software
|
||||
Foundation; version 2 of the License.
|
||||
|
||||
This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
|
||||
FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License along with
|
||||
this program; if not, write to the Free Software Foundation, Inc.,
|
||||
51 Franklin Street, Suite 500, Boston, MA 02110-1335 USA
|
||||
|
||||
*****************************************************************************/
|
||||
|
||||
/**************************************************//**
|
||||
@file include/btr0pcur.ic
|
||||
The index tree persistent cursor
|
||||
|
||||
Created 2/23/1996 Heikki Tuuri
|
||||
*******************************************************/
|
||||
|
||||
|
||||
/*********************************************************//**
|
||||
Gets the rel_pos field for a cursor whose position has been stored.
|
||||
@return BTR_PCUR_ON, ... */
|
||||
UNIV_INLINE
|
||||
ulint
|
||||
btr_pcur_get_rel_pos(
|
||||
/*=================*/
|
||||
const btr_pcur_t* cursor) /*!< in: persistent cursor */
|
||||
{
|
||||
ut_ad(cursor);
|
||||
ut_ad(cursor->old_rec);
|
||||
ut_ad(cursor->old_stored == BTR_PCUR_OLD_STORED);
|
||||
ut_ad(cursor->pos_state == BTR_PCUR_WAS_POSITIONED
|
||||
|| cursor->pos_state == BTR_PCUR_IS_POSITIONED);
|
||||
|
||||
return(cursor->rel_pos);
|
||||
}
|
||||
|
||||
#ifdef UNIV_DEBUG
|
||||
/*********************************************************//**
|
||||
Returns the btr cursor component of a persistent cursor.
|
||||
@return pointer to btr cursor component */
|
||||
UNIV_INLINE
|
||||
btr_cur_t*
|
||||
btr_pcur_get_btr_cur(
|
||||
/*=================*/
|
||||
const btr_pcur_t* cursor) /*!< in: persistent cursor */
|
||||
{
|
||||
const btr_cur_t* btr_cur = &cursor->btr_cur;
|
||||
return((btr_cur_t*) btr_cur);
|
||||
}
|
||||
|
||||
/*********************************************************//**
|
||||
Returns the page cursor component of a persistent cursor.
|
||||
@return pointer to page cursor component */
|
||||
UNIV_INLINE
|
||||
page_cur_t*
|
||||
btr_pcur_get_page_cur(
|
||||
/*==================*/
|
||||
const btr_pcur_t* cursor) /*!< in: persistent cursor */
|
||||
{
|
||||
return(btr_cur_get_page_cur(btr_pcur_get_btr_cur(cursor)));
|
||||
}
|
||||
|
||||
/*********************************************************//**
|
||||
Returns the page of a persistent cursor.
|
||||
@return pointer to the page */
|
||||
UNIV_INLINE
|
||||
page_t*
|
||||
btr_pcur_get_page(
|
||||
/*==============*/
|
||||
const btr_pcur_t* cursor) /*!< in: persistent cursor */
|
||||
{
|
||||
ut_ad(cursor->pos_state == BTR_PCUR_IS_POSITIONED);
|
||||
|
||||
return(btr_cur_get_page(btr_pcur_get_btr_cur(cursor)));
|
||||
}
|
||||
|
||||
/*********************************************************//**
|
||||
Returns the buffer block of a persistent cursor.
|
||||
@return pointer to the block */
|
||||
UNIV_INLINE
|
||||
buf_block_t*
|
||||
btr_pcur_get_block(
|
||||
/*===============*/
|
||||
const btr_pcur_t* cursor) /*!< in: persistent cursor */
|
||||
{
|
||||
ut_ad(cursor->pos_state == BTR_PCUR_IS_POSITIONED);
|
||||
|
||||
return(btr_cur_get_block(btr_pcur_get_btr_cur(cursor)));
|
||||
}
|
||||
|
||||
/*********************************************************//**
|
||||
Returns the record of a persistent cursor.
|
||||
@return pointer to the record */
|
||||
UNIV_INLINE
|
||||
rec_t*
|
||||
btr_pcur_get_rec(
|
||||
/*=============*/
|
||||
const btr_pcur_t* cursor) /*!< in: persistent cursor */
|
||||
{
|
||||
ut_ad(cursor->pos_state == BTR_PCUR_IS_POSITIONED);
|
||||
ut_ad(cursor->latch_mode != BTR_NO_LATCHES);
|
||||
|
||||
return(btr_cur_get_rec(btr_pcur_get_btr_cur(cursor)));
|
||||
}
|
||||
#endif /* UNIV_DEBUG */
|
||||
|
||||
/**************************************************************//**
|
||||
Gets the up_match value for a pcur after a search.
|
||||
@return number of matched fields at the cursor or to the right if
|
||||
search mode was PAGE_CUR_GE, otherwise undefined */
|
||||
UNIV_INLINE
|
||||
ulint
|
||||
btr_pcur_get_up_match(
|
||||
/*==================*/
|
||||
const btr_pcur_t* cursor) /*!< in: persistent cursor */
|
||||
{
|
||||
const btr_cur_t* btr_cursor;
|
||||
|
||||
ut_ad((cursor->pos_state == BTR_PCUR_WAS_POSITIONED)
|
||||
|| (cursor->pos_state == BTR_PCUR_IS_POSITIONED));
|
||||
|
||||
btr_cursor = btr_pcur_get_btr_cur(cursor);
|
||||
|
||||
ut_ad(btr_cursor->up_match != ULINT_UNDEFINED);
|
||||
|
||||
return(btr_cursor->up_match);
|
||||
}
|
||||
|
||||
/**************************************************************//**
|
||||
Gets the low_match value for a pcur after a search.
|
||||
@return number of matched fields at the cursor or to the right if
|
||||
search mode was PAGE_CUR_LE, otherwise undefined */
|
||||
UNIV_INLINE
|
||||
ulint
|
||||
btr_pcur_get_low_match(
|
||||
/*===================*/
|
||||
const btr_pcur_t* cursor) /*!< in: persistent cursor */
|
||||
{
|
||||
const btr_cur_t* btr_cursor;
|
||||
|
||||
ut_ad((cursor->pos_state == BTR_PCUR_WAS_POSITIONED)
|
||||
|| (cursor->pos_state == BTR_PCUR_IS_POSITIONED));
|
||||
|
||||
btr_cursor = btr_pcur_get_btr_cur(cursor);
|
||||
ut_ad(btr_cursor->low_match != ULINT_UNDEFINED);
|
||||
|
||||
return(btr_cursor->low_match);
|
||||
}
|
||||
|
||||
/*********************************************************//**
|
||||
Checks if the persistent cursor is after the last user record on
|
||||
a page. */
|
||||
UNIV_INLINE
|
||||
ibool
|
||||
btr_pcur_is_after_last_on_page(
|
||||
/*===========================*/
|
||||
const btr_pcur_t* cursor) /*!< in: persistent cursor */
|
||||
{
|
||||
ut_ad(cursor->pos_state == BTR_PCUR_IS_POSITIONED);
|
||||
ut_ad(cursor->latch_mode != BTR_NO_LATCHES);
|
||||
|
||||
return(page_cur_is_after_last(btr_pcur_get_page_cur(cursor)));
|
||||
}
|
||||
|
||||
/*********************************************************//**
|
||||
Checks if the persistent cursor is before the first user record on
|
||||
a page. */
|
||||
UNIV_INLINE
|
||||
ibool
|
||||
btr_pcur_is_before_first_on_page(
|
||||
/*=============================*/
|
||||
const btr_pcur_t* cursor) /*!< in: persistent cursor */
|
||||
{
|
||||
ut_ad(cursor->pos_state == BTR_PCUR_IS_POSITIONED);
|
||||
ut_ad(cursor->latch_mode != BTR_NO_LATCHES);
|
||||
|
||||
return(page_cur_is_before_first(btr_pcur_get_page_cur(cursor)));
|
||||
}
|
||||
|
||||
/*********************************************************//**
|
||||
Checks if the persistent cursor is on a user record. */
|
||||
UNIV_INLINE
|
||||
ibool
|
||||
btr_pcur_is_on_user_rec(
|
||||
/*====================*/
|
||||
const btr_pcur_t* cursor) /*!< in: persistent cursor */
|
||||
{
|
||||
ut_ad(cursor->pos_state == BTR_PCUR_IS_POSITIONED);
|
||||
ut_ad(cursor->latch_mode != BTR_NO_LATCHES);
|
||||
|
||||
if (btr_pcur_is_before_first_on_page(cursor)
|
||||
|| btr_pcur_is_after_last_on_page(cursor)) {
|
||||
|
||||
return(FALSE);
|
||||
}
|
||||
|
||||
return(TRUE);
|
||||
}
|
||||
|
||||
/*********************************************************//**
|
||||
Checks if the persistent cursor is before the first user record in
|
||||
the index tree. */
|
||||
UNIV_INLINE
|
||||
ibool
|
||||
btr_pcur_is_before_first_in_tree(
|
||||
/*=============================*/
|
||||
btr_pcur_t* cursor, /*!< in: persistent cursor */
|
||||
mtr_t* mtr) /*!< in: mtr */
|
||||
{
|
||||
ut_ad(cursor->pos_state == BTR_PCUR_IS_POSITIONED);
|
||||
ut_ad(cursor->latch_mode != BTR_NO_LATCHES);
|
||||
|
||||
if (btr_page_get_prev(btr_pcur_get_page(cursor), mtr) != FIL_NULL) {
|
||||
|
||||
return(FALSE);
|
||||
}
|
||||
|
||||
return(page_cur_is_before_first(btr_pcur_get_page_cur(cursor)));
|
||||
}
|
||||
|
||||
/*********************************************************//**
|
||||
Checks if the persistent cursor is after the last user record in
|
||||
the index tree. */
|
||||
UNIV_INLINE
|
||||
ibool
|
||||
btr_pcur_is_after_last_in_tree(
|
||||
/*===========================*/
|
||||
btr_pcur_t* cursor, /*!< in: persistent cursor */
|
||||
mtr_t* mtr) /*!< in: mtr */
|
||||
{
|
||||
ut_ad(cursor->pos_state == BTR_PCUR_IS_POSITIONED);
|
||||
ut_ad(cursor->latch_mode != BTR_NO_LATCHES);
|
||||
|
||||
if (btr_page_get_next(btr_pcur_get_page(cursor), mtr) != FIL_NULL) {
|
||||
|
||||
return(FALSE);
|
||||
}
|
||||
|
||||
return(page_cur_is_after_last(btr_pcur_get_page_cur(cursor)));
|
||||
}
|
||||
|
||||
/*********************************************************//**
|
||||
Moves the persistent cursor to the next record on the same page. */
|
||||
UNIV_INLINE
|
||||
void
|
||||
btr_pcur_move_to_next_on_page(
|
||||
/*==========================*/
|
||||
btr_pcur_t* cursor) /*!< in/out: persistent cursor */
|
||||
{
|
||||
ut_ad(cursor->pos_state == BTR_PCUR_IS_POSITIONED);
|
||||
ut_ad(cursor->latch_mode != BTR_NO_LATCHES);
|
||||
|
||||
page_cur_move_to_next(btr_pcur_get_page_cur(cursor));
|
||||
|
||||
cursor->old_stored = BTR_PCUR_OLD_NOT_STORED;
|
||||
}
|
||||
|
||||
/*********************************************************//**
|
||||
Moves the persistent cursor to the previous record on the same page. */
|
||||
UNIV_INLINE
|
||||
void
|
||||
btr_pcur_move_to_prev_on_page(
|
||||
/*==========================*/
|
||||
btr_pcur_t* cursor) /*!< in/out: persistent cursor */
|
||||
{
|
||||
ut_ad(cursor->pos_state == BTR_PCUR_IS_POSITIONED);
|
||||
ut_ad(cursor->latch_mode != BTR_NO_LATCHES);
|
||||
|
||||
page_cur_move_to_prev(btr_pcur_get_page_cur(cursor));
|
||||
|
||||
cursor->old_stored = BTR_PCUR_OLD_NOT_STORED;
|
||||
}
|
||||
|
||||
/*********************************************************//**
|
||||
Moves the persistent cursor to the last record on the same page. */
|
||||
UNIV_INLINE
|
||||
void
|
||||
btr_pcur_move_to_last_on_page(
|
||||
/*==========================*/
|
||||
btr_pcur_t* cursor, /*!< in: persistent cursor */
|
||||
mtr_t* mtr) /*!< in: mtr */
|
||||
{
|
||||
UT_NOT_USED(mtr);
|
||||
ut_ad(cursor->latch_mode != BTR_NO_LATCHES);
|
||||
|
||||
page_cur_set_after_last(btr_pcur_get_block(cursor),
|
||||
btr_pcur_get_page_cur(cursor));
|
||||
|
||||
cursor->old_stored = BTR_PCUR_OLD_NOT_STORED;
|
||||
}
|
||||
|
||||
/*********************************************************//**
|
||||
Moves the persistent cursor to the next user record in the tree. If no user
|
||||
records are left, the cursor ends up 'after last in tree'.
|
||||
@return TRUE if the cursor moved forward, ending on a user record */
|
||||
UNIV_INLINE
|
||||
ibool
|
||||
btr_pcur_move_to_next_user_rec(
|
||||
/*===========================*/
|
||||
btr_pcur_t* cursor, /*!< in: persistent cursor; NOTE that the
|
||||
function may release the page latch */
|
||||
mtr_t* mtr) /*!< in: mtr */
|
||||
{
|
||||
ut_ad(cursor->pos_state == BTR_PCUR_IS_POSITIONED);
|
||||
ut_ad(cursor->latch_mode != BTR_NO_LATCHES);
|
||||
cursor->old_stored = BTR_PCUR_OLD_NOT_STORED;
|
||||
loop:
|
||||
if (btr_pcur_is_after_last_on_page(cursor)) {
|
||||
|
||||
if (btr_pcur_is_after_last_in_tree(cursor, mtr)) {
|
||||
|
||||
return(FALSE);
|
||||
}
|
||||
|
||||
btr_pcur_move_to_next_page(cursor, mtr);
|
||||
} else {
|
||||
btr_pcur_move_to_next_on_page(cursor);
|
||||
}
|
||||
|
||||
if (btr_pcur_is_on_user_rec(cursor)) {
|
||||
|
||||
return(TRUE);
|
||||
}
|
||||
|
||||
goto loop;
|
||||
}
|
||||
|
||||
/*********************************************************//**
|
||||
Moves the persistent cursor to the next record in the tree. If no records are
|
||||
left, the cursor stays 'after last in tree'.
|
||||
@return TRUE if the cursor was not after last in tree */
|
||||
UNIV_INLINE
|
||||
ibool
|
||||
btr_pcur_move_to_next(
|
||||
/*==================*/
|
||||
btr_pcur_t* cursor, /*!< in: persistent cursor; NOTE that the
|
||||
function may release the page latch */
|
||||
mtr_t* mtr) /*!< in: mtr */
|
||||
{
|
||||
ut_ad(cursor->pos_state == BTR_PCUR_IS_POSITIONED);
|
||||
ut_ad(cursor->latch_mode != BTR_NO_LATCHES);
|
||||
|
||||
cursor->old_stored = BTR_PCUR_OLD_NOT_STORED;
|
||||
|
||||
if (btr_pcur_is_after_last_on_page(cursor)) {
|
||||
|
||||
if (btr_pcur_is_after_last_in_tree(cursor, mtr)) {
|
||||
|
||||
return(FALSE);
|
||||
}
|
||||
|
||||
btr_pcur_move_to_next_page(cursor, mtr);
|
||||
|
||||
return(TRUE);
|
||||
}
|
||||
|
||||
btr_pcur_move_to_next_on_page(cursor);
|
||||
|
||||
return(TRUE);
|
||||
}
|
||||
|
||||
/**************************************************************//**
|
||||
Commits the mtr and sets the pcur latch mode to BTR_NO_LATCHES,
|
||||
that is, the cursor becomes detached.
|
||||
Function btr_pcur_store_position should be used before calling this,
|
||||
if restoration of cursor is wanted later. */
|
||||
UNIV_INLINE
|
||||
void
|
||||
btr_pcur_commit_specify_mtr(
|
||||
/*========================*/
|
||||
btr_pcur_t* pcur, /*!< in: persistent cursor */
|
||||
mtr_t* mtr) /*!< in: mtr to commit */
|
||||
{
|
||||
ut_ad(pcur->pos_state == BTR_PCUR_IS_POSITIONED);
|
||||
|
||||
pcur->latch_mode = BTR_NO_LATCHES;
|
||||
|
||||
mtr_commit(mtr);
|
||||
|
||||
pcur->pos_state = BTR_PCUR_WAS_POSITIONED;
|
||||
}
|
||||
|
||||
/**************************************************************//**
|
||||
Sets the old_rec_buf field to NULL. */
|
||||
UNIV_INLINE
|
||||
void
|
||||
btr_pcur_init(
|
||||
/*==========*/
|
||||
btr_pcur_t* pcur) /*!< in: persistent cursor */
|
||||
{
|
||||
pcur->old_stored = BTR_PCUR_OLD_NOT_STORED;
|
||||
pcur->old_rec_buf = NULL;
|
||||
pcur->old_rec = NULL;
|
||||
}
|
||||
|
||||
/**************************************************************//**
|
||||
Initializes and opens a persistent cursor to an index tree. It should be
|
||||
closed with btr_pcur_close. */
|
||||
UNIV_INLINE
|
||||
void
|
||||
btr_pcur_open_low(
|
||||
/*==============*/
|
||||
dict_index_t* index, /*!< in: index */
|
||||
ulint level, /*!< in: level in the btree */
|
||||
const dtuple_t* tuple, /*!< in: tuple on which search done */
|
||||
ulint mode, /*!< in: PAGE_CUR_L, ...;
|
||||
NOTE that if the search is made using a unique
|
||||
prefix of a record, mode should be
|
||||
PAGE_CUR_LE, not PAGE_CUR_GE, as the latter
|
||||
may end up on the previous page from the
|
||||
record! */
|
||||
ulint latch_mode,/*!< in: BTR_SEARCH_LEAF, ... */
|
||||
btr_pcur_t* cursor, /*!< in: memory buffer for persistent cursor */
|
||||
const char* file, /*!< in: file name */
|
||||
ulint line, /*!< in: line where called */
|
||||
mtr_t* mtr) /*!< in: mtr */
|
||||
{
|
||||
btr_cur_t* btr_cursor;
|
||||
|
||||
/* Initialize the cursor */
|
||||
|
||||
btr_pcur_init(cursor);
|
||||
|
||||
cursor->latch_mode = BTR_LATCH_MODE_WITHOUT_FLAGS(latch_mode);
|
||||
cursor->search_mode = mode;
|
||||
|
||||
/* Search with the tree cursor */
|
||||
|
||||
btr_cursor = btr_pcur_get_btr_cur(cursor);
|
||||
|
||||
btr_cur_search_to_nth_level(index, level, tuple, mode, latch_mode,
|
||||
btr_cursor, 0, file, line, mtr);
|
||||
cursor->pos_state = BTR_PCUR_IS_POSITIONED;
|
||||
|
||||
cursor->trx_if_known = NULL;
|
||||
}
|
||||
|
||||
/**************************************************************//**
|
||||
Opens an persistent cursor to an index tree without initializing the
|
||||
cursor. */
|
||||
UNIV_INLINE
|
||||
void
|
||||
btr_pcur_open_with_no_init_func(
|
||||
/*============================*/
|
||||
dict_index_t* index, /*!< in: index */
|
||||
const dtuple_t* tuple, /*!< in: tuple on which search done */
|
||||
ulint mode, /*!< in: PAGE_CUR_L, ...;
|
||||
NOTE that if the search is made using a unique
|
||||
prefix of a record, mode should be
|
||||
PAGE_CUR_LE, not PAGE_CUR_GE, as the latter
|
||||
may end up on the previous page of the
|
||||
record! */
|
||||
ulint latch_mode,/*!< in: BTR_SEARCH_LEAF, ...;
|
||||
NOTE that if has_search_latch != 0 then
|
||||
we maybe do not acquire a latch on the cursor
|
||||
page, but assume that the caller uses his
|
||||
btr search latch to protect the record! */
|
||||
btr_pcur_t* cursor, /*!< in: memory buffer for persistent cursor */
|
||||
ulint has_search_latch,/*!< in: latch mode the caller
|
||||
currently has on btr_search_latch:
|
||||
RW_S_LATCH, or 0 */
|
||||
const char* file, /*!< in: file name */
|
||||
ulint line, /*!< in: line where called */
|
||||
mtr_t* mtr) /*!< in: mtr */
|
||||
{
|
||||
btr_cur_t* btr_cursor;
|
||||
|
||||
cursor->latch_mode = latch_mode;
|
||||
cursor->search_mode = mode;
|
||||
|
||||
/* Search with the tree cursor */
|
||||
|
||||
btr_cursor = btr_pcur_get_btr_cur(cursor);
|
||||
|
||||
btr_cur_search_to_nth_level(index, 0, tuple, mode, latch_mode,
|
||||
btr_cursor, has_search_latch,
|
||||
file, line, mtr);
|
||||
cursor->pos_state = BTR_PCUR_IS_POSITIONED;
|
||||
|
||||
cursor->old_stored = BTR_PCUR_OLD_NOT_STORED;
|
||||
|
||||
cursor->trx_if_known = NULL;
|
||||
}
|
||||
|
||||
/*****************************************************************//**
|
||||
Opens a persistent cursor at either end of an index. */
|
||||
UNIV_INLINE
|
||||
void
|
||||
btr_pcur_open_at_index_side(
|
||||
/*========================*/
|
||||
bool from_left, /*!< in: true if open to the low end,
|
||||
false if to the high end */
|
||||
dict_index_t* index, /*!< in: index */
|
||||
ulint latch_mode, /*!< in: latch mode */
|
||||
btr_pcur_t* pcur, /*!< in/out: cursor */
|
||||
bool init_pcur, /*!< in: whether to initialize pcur */
|
||||
ulint level, /*!< in: level to search for
|
||||
(0=leaf) */
|
||||
mtr_t* mtr) /*!< in/out: mini-transaction */
|
||||
{
|
||||
pcur->latch_mode = BTR_LATCH_MODE_WITHOUT_FLAGS(latch_mode);
|
||||
|
||||
pcur->search_mode = from_left ? PAGE_CUR_G : PAGE_CUR_L;
|
||||
|
||||
if (init_pcur) {
|
||||
btr_pcur_init(pcur);
|
||||
}
|
||||
|
||||
btr_cur_open_at_index_side(from_left, index, latch_mode,
|
||||
btr_pcur_get_btr_cur(pcur), level, mtr);
|
||||
pcur->pos_state = BTR_PCUR_IS_POSITIONED;
|
||||
|
||||
pcur->old_stored = BTR_PCUR_OLD_NOT_STORED;
|
||||
|
||||
pcur->trx_if_known = NULL;
|
||||
}
|
||||
|
||||
/**********************************************************************//**
|
||||
Positions a cursor at a randomly chosen position within a B-tree. */
|
||||
UNIV_INLINE
|
||||
void
|
||||
btr_pcur_open_at_rnd_pos_func(
|
||||
/*==========================*/
|
||||
dict_index_t* index, /*!< in: index */
|
||||
ulint latch_mode, /*!< in: BTR_SEARCH_LEAF, ... */
|
||||
btr_pcur_t* cursor, /*!< in/out: B-tree pcur */
|
||||
const char* file, /*!< in: file name */
|
||||
ulint line, /*!< in: line where called */
|
||||
mtr_t* mtr) /*!< in: mtr */
|
||||
{
|
||||
/* Initialize the cursor */
|
||||
|
||||
cursor->latch_mode = latch_mode;
|
||||
cursor->search_mode = PAGE_CUR_G;
|
||||
|
||||
btr_pcur_init(cursor);
|
||||
|
||||
btr_cur_open_at_rnd_pos_func(index, latch_mode,
|
||||
btr_pcur_get_btr_cur(cursor),
|
||||
file, line, mtr);
|
||||
cursor->pos_state = BTR_PCUR_IS_POSITIONED;
|
||||
cursor->old_stored = BTR_PCUR_OLD_NOT_STORED;
|
||||
|
||||
cursor->trx_if_known = NULL;
|
||||
}
|
||||
|
||||
/**************************************************************//**
|
||||
Frees the possible memory heap of a persistent cursor and sets the latch
|
||||
mode of the persistent cursor to BTR_NO_LATCHES.
|
||||
WARNING: this function does not release the latch on the page where the
|
||||
cursor is currently positioned. The latch is acquired by the
|
||||
"move to next/previous" family of functions. Since recursive shared locks
|
||||
are not allowed, you must take care (if using the cursor in S-mode) to
|
||||
manually release the latch by either calling
|
||||
btr_leaf_page_release(btr_pcur_get_block(&pcur), pcur.latch_mode, mtr)
|
||||
or by committing the mini-transaction right after btr_pcur_close().
|
||||
A subsequent attempt to crawl the same page in the same mtr would cause
|
||||
an assertion failure. */
|
||||
UNIV_INLINE
|
||||
void
|
||||
btr_pcur_close(
|
||||
/*===========*/
|
||||
btr_pcur_t* cursor) /*!< in: persistent cursor */
|
||||
{
|
||||
if (cursor->old_rec_buf != NULL) {
|
||||
|
||||
mem_free(cursor->old_rec_buf);
|
||||
|
||||
cursor->old_rec = NULL;
|
||||
cursor->old_rec_buf = NULL;
|
||||
}
|
||||
|
||||
cursor->btr_cur.page_cur.rec = NULL;
|
||||
cursor->btr_cur.page_cur.block = NULL;
|
||||
cursor->old_rec = NULL;
|
||||
cursor->old_stored = BTR_PCUR_OLD_NOT_STORED;
|
||||
|
||||
cursor->latch_mode = BTR_NO_LATCHES;
|
||||
cursor->pos_state = BTR_PCUR_NOT_POSITIONED;
|
||||
|
||||
cursor->trx_if_known = NULL;
|
||||
}
|
||||
|
||||
/*********************************************************//**
|
||||
Moves the persistent cursor to the infimum record on the same page. */
|
||||
UNIV_INLINE
|
||||
void
|
||||
btr_pcur_move_before_first_on_page(
|
||||
/*===============================*/
|
||||
btr_pcur_t* cursor) /*!< in/out: persistent cursor */
|
||||
{
|
||||
ut_ad(cursor->latch_mode != BTR_NO_LATCHES);
|
||||
|
||||
page_cur_set_before_first(btr_pcur_get_block(cursor),
|
||||
btr_pcur_get_page_cur(cursor));
|
||||
|
||||
cursor->old_stored = BTR_PCUR_OLD_NOT_STORED;
|
||||
}
|
||||
288
storage/innobase/include/btr0sea.h
Normal file
288
storage/innobase/include/btr0sea.h
Normal file
|
|
@ -0,0 +1,288 @@
|
|||
/*****************************************************************************
|
||||
|
||||
Copyright (c) 1996, 2011, Oracle and/or its affiliates. All Rights Reserved.
|
||||
|
||||
This program is free software; you can redistribute it and/or modify it under
|
||||
the terms of the GNU General Public License as published by the Free Software
|
||||
Foundation; version 2 of the License.
|
||||
|
||||
This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
|
||||
FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License along with
|
||||
this program; if not, write to the Free Software Foundation, Inc.,
|
||||
51 Franklin Street, Suite 500, Boston, MA 02110-1335 USA
|
||||
|
||||
*****************************************************************************/
|
||||
|
||||
/********************************************************************//**
|
||||
@file include/btr0sea.h
|
||||
The index tree adaptive search
|
||||
|
||||
Created 2/17/1996 Heikki Tuuri
|
||||
*************************************************************************/
|
||||
|
||||
#ifndef btr0sea_h
|
||||
#define btr0sea_h
|
||||
|
||||
#include "univ.i"
|
||||
|
||||
#include "rem0rec.h"
|
||||
#include "dict0dict.h"
|
||||
#include "btr0types.h"
|
||||
#include "mtr0mtr.h"
|
||||
#include "ha0ha.h"
|
||||
|
||||
/*****************************************************************//**
|
||||
Creates and initializes the adaptive search system at a database start. */
|
||||
UNIV_INTERN
|
||||
void
|
||||
btr_search_sys_create(
|
||||
/*==================*/
|
||||
ulint hash_size); /*!< in: hash index hash table size */
|
||||
/*****************************************************************//**
|
||||
Frees the adaptive search system at a database shutdown. */
|
||||
UNIV_INTERN
|
||||
void
|
||||
btr_search_sys_free(void);
|
||||
/*=====================*/
|
||||
|
||||
/********************************************************************//**
|
||||
Disable the adaptive hash search system and empty the index. */
|
||||
UNIV_INTERN
|
||||
void
|
||||
btr_search_disable(void);
|
||||
/*====================*/
|
||||
/********************************************************************//**
|
||||
Enable the adaptive hash search system. */
|
||||
UNIV_INTERN
|
||||
void
|
||||
btr_search_enable(void);
|
||||
/*====================*/
|
||||
|
||||
/********************************************************************//**
|
||||
Returns search info for an index.
|
||||
@return search info; search mutex reserved */
|
||||
UNIV_INLINE
|
||||
btr_search_t*
|
||||
btr_search_get_info(
|
||||
/*================*/
|
||||
dict_index_t* index) /*!< in: index */
|
||||
__attribute__((nonnull));
|
||||
/*****************************************************************//**
|
||||
Creates and initializes a search info struct.
|
||||
@return own: search info struct */
|
||||
UNIV_INTERN
|
||||
btr_search_t*
|
||||
btr_search_info_create(
|
||||
/*===================*/
|
||||
mem_heap_t* heap); /*!< in: heap where created */
|
||||
/*****************************************************************//**
|
||||
Returns the value of ref_count. The value is protected by
|
||||
btr_search_latch.
|
||||
@return ref_count value. */
|
||||
UNIV_INTERN
|
||||
ulint
|
||||
btr_search_info_get_ref_count(
|
||||
/*==========================*/
|
||||
btr_search_t* info); /*!< in: search info. */
|
||||
/*********************************************************************//**
|
||||
Updates the search info. */
|
||||
UNIV_INLINE
|
||||
void
|
||||
btr_search_info_update(
|
||||
/*===================*/
|
||||
dict_index_t* index, /*!< in: index of the cursor */
|
||||
btr_cur_t* cursor);/*!< in: cursor which was just positioned */
|
||||
/******************************************************************//**
|
||||
Tries to guess the right search position based on the hash search info
|
||||
of the index. Note that if mode is PAGE_CUR_LE, which is used in inserts,
|
||||
and the function returns TRUE, then cursor->up_match and cursor->low_match
|
||||
both have sensible values.
|
||||
@return TRUE if succeeded */
|
||||
UNIV_INTERN
|
||||
ibool
|
||||
btr_search_guess_on_hash(
|
||||
/*=====================*/
|
||||
dict_index_t* index, /*!< in: index */
|
||||
btr_search_t* info, /*!< in: index search info */
|
||||
const dtuple_t* tuple, /*!< in: logical record */
|
||||
ulint mode, /*!< in: PAGE_CUR_L, ... */
|
||||
ulint latch_mode, /*!< in: BTR_SEARCH_LEAF, ... */
|
||||
btr_cur_t* cursor, /*!< out: tree cursor */
|
||||
ulint has_search_latch,/*!< in: latch mode the caller
|
||||
currently has on btr_search_latch:
|
||||
RW_S_LATCH, RW_X_LATCH, or 0 */
|
||||
mtr_t* mtr); /*!< in: mtr */
|
||||
/********************************************************************//**
|
||||
Moves or deletes hash entries for moved records. If new_page is already hashed,
|
||||
then the hash index for page, if any, is dropped. If new_page is not hashed,
|
||||
and page is hashed, then a new hash index is built to new_page with the same
|
||||
parameters as page (this often happens when a page is split). */
|
||||
UNIV_INTERN
|
||||
void
|
||||
btr_search_move_or_delete_hash_entries(
|
||||
/*===================================*/
|
||||
buf_block_t* new_block, /*!< in: records are copied
|
||||
to this page */
|
||||
buf_block_t* block, /*!< in: index page from which
|
||||
records were copied, and the
|
||||
copied records will be deleted
|
||||
from this page */
|
||||
dict_index_t* index); /*!< in: record descriptor */
|
||||
/********************************************************************//**
|
||||
Drops a page hash index. */
|
||||
UNIV_INTERN
|
||||
void
|
||||
btr_search_drop_page_hash_index(
|
||||
/*============================*/
|
||||
buf_block_t* block); /*!< in: block containing index page,
|
||||
s- or x-latched, or an index page
|
||||
for which we know that
|
||||
block->buf_fix_count == 0 */
|
||||
/********************************************************************//**
|
||||
Drops a possible page hash index when a page is evicted from the buffer pool
|
||||
or freed in a file segment. */
|
||||
UNIV_INTERN
|
||||
void
|
||||
btr_search_drop_page_hash_when_freed(
|
||||
/*=================================*/
|
||||
ulint space, /*!< in: space id */
|
||||
ulint zip_size, /*!< in: compressed page size in bytes
|
||||
or 0 for uncompressed pages */
|
||||
ulint page_no); /*!< in: page number */
|
||||
/********************************************************************//**
|
||||
Updates the page hash index when a single record is inserted on a page. */
|
||||
UNIV_INTERN
|
||||
void
|
||||
btr_search_update_hash_node_on_insert(
|
||||
/*==================================*/
|
||||
btr_cur_t* cursor);/*!< in: cursor which was positioned to the
|
||||
place to insert using btr_cur_search_...,
|
||||
and the new record has been inserted next
|
||||
to the cursor */
|
||||
/********************************************************************//**
|
||||
Updates the page hash index when a single record is inserted on a page. */
|
||||
UNIV_INTERN
|
||||
void
|
||||
btr_search_update_hash_on_insert(
|
||||
/*=============================*/
|
||||
btr_cur_t* cursor);/*!< in: cursor which was positioned to the
|
||||
place to insert using btr_cur_search_...,
|
||||
and the new record has been inserted next
|
||||
to the cursor */
|
||||
/********************************************************************//**
|
||||
Updates the page hash index when a single record is deleted from a page. */
|
||||
UNIV_INTERN
|
||||
void
|
||||
btr_search_update_hash_on_delete(
|
||||
/*=============================*/
|
||||
btr_cur_t* cursor);/*!< in: cursor which was positioned on the
|
||||
record to delete using btr_cur_search_...,
|
||||
the record is not yet deleted */
|
||||
#if defined UNIV_AHI_DEBUG || defined UNIV_DEBUG
|
||||
/********************************************************************//**
|
||||
Validates the search system.
|
||||
@return TRUE if ok */
|
||||
UNIV_INTERN
|
||||
ibool
|
||||
btr_search_validate(void);
|
||||
/*======================*/
|
||||
#endif /* defined UNIV_AHI_DEBUG || defined UNIV_DEBUG */
|
||||
|
||||
/** The search info struct in an index */
|
||||
struct btr_search_t{
|
||||
ulint ref_count; /*!< Number of blocks in this index tree
|
||||
that have search index built
|
||||
i.e. block->index points to this index.
|
||||
Protected by btr_search_latch except
|
||||
when during initialization in
|
||||
btr_search_info_create(). */
|
||||
|
||||
/* @{ The following fields are not protected by any latch.
|
||||
Unfortunately, this means that they must be aligned to
|
||||
the machine word, i.e., they cannot be turned into bit-fields. */
|
||||
buf_block_t* root_guess;/*!< the root page frame when it was last time
|
||||
fetched, or NULL */
|
||||
ulint hash_analysis; /*!< when this exceeds
|
||||
BTR_SEARCH_HASH_ANALYSIS, the hash
|
||||
analysis starts; this is reset if no
|
||||
success noticed */
|
||||
ibool last_hash_succ; /*!< TRUE if the last search would have
|
||||
succeeded, or did succeed, using the hash
|
||||
index; NOTE that the value here is not exact:
|
||||
it is not calculated for every search, and the
|
||||
calculation itself is not always accurate! */
|
||||
ulint n_hash_potential;
|
||||
/*!< number of consecutive searches
|
||||
which would have succeeded, or did succeed,
|
||||
using the hash index;
|
||||
the range is 0 .. BTR_SEARCH_BUILD_LIMIT + 5 */
|
||||
/* @} */
|
||||
/*---------------------- @{ */
|
||||
ulint n_fields; /*!< recommended prefix length for hash search:
|
||||
number of full fields */
|
||||
ulint n_bytes; /*!< recommended prefix: number of bytes in
|
||||
an incomplete field
|
||||
@see BTR_PAGE_MAX_REC_SIZE */
|
||||
ibool left_side; /*!< TRUE or FALSE, depending on whether
|
||||
the leftmost record of several records with
|
||||
the same prefix should be indexed in the
|
||||
hash index */
|
||||
/*---------------------- @} */
|
||||
#ifdef UNIV_SEARCH_PERF_STAT
|
||||
ulint n_hash_succ; /*!< number of successful hash searches thus
|
||||
far */
|
||||
ulint n_hash_fail; /*!< number of failed hash searches */
|
||||
ulint n_patt_succ; /*!< number of successful pattern searches thus
|
||||
far */
|
||||
ulint n_searches; /*!< number of searches */
|
||||
#endif /* UNIV_SEARCH_PERF_STAT */
|
||||
#ifdef UNIV_DEBUG
|
||||
ulint magic_n; /*!< magic number @see BTR_SEARCH_MAGIC_N */
|
||||
/** value of btr_search_t::magic_n, used in assertions */
|
||||
# define BTR_SEARCH_MAGIC_N 1112765
|
||||
#endif /* UNIV_DEBUG */
|
||||
};
|
||||
|
||||
/** The hash index system */
|
||||
struct btr_search_sys_t{
|
||||
hash_table_t* hash_index; /*!< the adaptive hash index,
|
||||
mapping dtuple_fold values
|
||||
to rec_t pointers on index pages */
|
||||
};
|
||||
|
||||
/** The adaptive hash index */
|
||||
extern btr_search_sys_t* btr_search_sys;
|
||||
|
||||
#ifdef UNIV_SEARCH_PERF_STAT
|
||||
/** Number of successful adaptive hash index lookups */
|
||||
extern ulint btr_search_n_succ;
|
||||
/** Number of failed adaptive hash index lookups */
|
||||
extern ulint btr_search_n_hash_fail;
|
||||
#endif /* UNIV_SEARCH_PERF_STAT */
|
||||
|
||||
/** After change in n_fields or n_bytes in info, this many rounds are waited
|
||||
before starting the hash analysis again: this is to save CPU time when there
|
||||
is no hope in building a hash index. */
|
||||
#define BTR_SEARCH_HASH_ANALYSIS 17
|
||||
|
||||
/** Limit of consecutive searches for trying a search shortcut on the search
|
||||
pattern */
|
||||
#define BTR_SEARCH_ON_PATTERN_LIMIT 3
|
||||
|
||||
/** Limit of consecutive searches for trying a search shortcut using
|
||||
the hash index */
|
||||
#define BTR_SEARCH_ON_HASH_LIMIT 3
|
||||
|
||||
/** We do this many searches before trying to keep the search latch
|
||||
over calls from MySQL. If we notice someone waiting for the latch, we
|
||||
again set this much timeout. This is to reduce contention. */
|
||||
#define BTR_SEA_TIMEOUT 10000
|
||||
|
||||
#ifndef UNIV_NONINL
|
||||
#include "btr0sea.ic"
|
||||
#endif
|
||||
|
||||
#endif
|
||||
82
storage/innobase/include/btr0sea.ic
Normal file
82
storage/innobase/include/btr0sea.ic
Normal file
|
|
@ -0,0 +1,82 @@
|
|||
/*****************************************************************************
|
||||
|
||||
Copyright (c) 1996, 2011, Oracle and/or its affiliates. All Rights Reserved.
|
||||
|
||||
This program is free software; you can redistribute it and/or modify it under
|
||||
the terms of the GNU General Public License as published by the Free Software
|
||||
Foundation; version 2 of the License.
|
||||
|
||||
This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
|
||||
FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License along with
|
||||
this program; if not, write to the Free Software Foundation, Inc.,
|
||||
51 Franklin Street, Suite 500, Boston, MA 02110-1335 USA
|
||||
|
||||
*****************************************************************************/
|
||||
|
||||
/********************************************************************//**
|
||||
@file include/btr0sea.ic
|
||||
The index tree adaptive search
|
||||
|
||||
Created 2/17/1996 Heikki Tuuri
|
||||
*************************************************************************/
|
||||
|
||||
#include "dict0mem.h"
|
||||
#include "btr0cur.h"
|
||||
#include "buf0buf.h"
|
||||
|
||||
/*********************************************************************//**
|
||||
Updates the search info. */
|
||||
UNIV_INTERN
|
||||
void
|
||||
btr_search_info_update_slow(
|
||||
/*========================*/
|
||||
btr_search_t* info, /*!< in/out: search info */
|
||||
btr_cur_t* cursor);/*!< in: cursor which was just positioned */
|
||||
|
||||
/********************************************************************//**
|
||||
Returns search info for an index.
|
||||
@return search info; search mutex reserved */
|
||||
UNIV_INLINE
|
||||
btr_search_t*
|
||||
btr_search_get_info(
|
||||
/*================*/
|
||||
dict_index_t* index) /*!< in: index */
|
||||
{
|
||||
return(index->search_info);
|
||||
}
|
||||
|
||||
/*********************************************************************//**
|
||||
Updates the search info. */
|
||||
UNIV_INLINE
|
||||
void
|
||||
btr_search_info_update(
|
||||
/*===================*/
|
||||
dict_index_t* index, /*!< in: index of the cursor */
|
||||
btr_cur_t* cursor) /*!< in: cursor which was just positioned */
|
||||
{
|
||||
btr_search_t* info;
|
||||
|
||||
#ifdef UNIV_SYNC_DEBUG
|
||||
ut_ad(!rw_lock_own(&btr_search_latch, RW_LOCK_SHARED));
|
||||
ut_ad(!rw_lock_own(&btr_search_latch, RW_LOCK_EX));
|
||||
#endif /* UNIV_SYNC_DEBUG */
|
||||
|
||||
info = btr_search_get_info(index);
|
||||
|
||||
info->hash_analysis++;
|
||||
|
||||
if (info->hash_analysis < BTR_SEARCH_HASH_ANALYSIS) {
|
||||
|
||||
/* Do nothing */
|
||||
|
||||
return;
|
||||
|
||||
}
|
||||
|
||||
ut_ad(cursor->flag != BTR_CUR_HASH);
|
||||
|
||||
btr_search_info_update_slow(info, cursor);
|
||||
}
|
||||
203
storage/innobase/include/btr0types.h
Normal file
203
storage/innobase/include/btr0types.h
Normal file
|
|
@ -0,0 +1,203 @@
|
|||
/*****************************************************************************
|
||||
|
||||
Copyright (c) 1996, 2011, Oracle and/or its affiliates. All Rights Reserved.
|
||||
|
||||
This program is free software; you can redistribute it and/or modify it under
|
||||
the terms of the GNU General Public License as published by the Free Software
|
||||
Foundation; version 2 of the License.
|
||||
|
||||
This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
|
||||
FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License along with
|
||||
this program; if not, write to the Free Software Foundation, Inc.,
|
||||
51 Franklin Street, Suite 500, Boston, MA 02110-1335 USA
|
||||
|
||||
*****************************************************************************/
|
||||
|
||||
/********************************************************************//**
|
||||
@file include/btr0types.h
|
||||
The index tree general types
|
||||
|
||||
Created 2/17/1996 Heikki Tuuri
|
||||
*************************************************************************/
|
||||
|
||||
#ifndef btr0types_h
|
||||
#define btr0types_h
|
||||
|
||||
#include "univ.i"
|
||||
|
||||
#include "rem0types.h"
|
||||
#include "page0types.h"
|
||||
#include "sync0rw.h"
|
||||
|
||||
/** Persistent cursor */
|
||||
struct btr_pcur_t;
|
||||
/** B-tree cursor */
|
||||
struct btr_cur_t;
|
||||
/** B-tree search information for the adaptive hash index */
|
||||
struct btr_search_t;
|
||||
|
||||
#ifndef UNIV_HOTBACKUP
|
||||
|
||||
/** @brief The latch protecting the adaptive search system
|
||||
|
||||
This latch protects the
|
||||
(1) hash index;
|
||||
(2) columns of a record to which we have a pointer in the hash index;
|
||||
|
||||
but does NOT protect:
|
||||
|
||||
(3) next record offset field in a record;
|
||||
(4) next or previous records on the same page.
|
||||
|
||||
Bear in mind (3) and (4) when using the hash index.
|
||||
*/
|
||||
extern rw_lock_t* btr_search_latch_temp;
|
||||
|
||||
#endif /* UNIV_HOTBACKUP */
|
||||
|
||||
/** The latch protecting the adaptive search system */
|
||||
#define btr_search_latch (*btr_search_latch_temp)
|
||||
|
||||
/** Flag: has the search system been enabled?
|
||||
Protected by btr_search_latch. */
|
||||
extern char btr_search_enabled;
|
||||
|
||||
#ifdef UNIV_BLOB_DEBUG
|
||||
# include "buf0types.h"
|
||||
/** An index->blobs entry for keeping track of off-page column references */
|
||||
struct btr_blob_dbg_t;
|
||||
|
||||
/** Insert to index->blobs a reference to an off-page column.
|
||||
@param index the index tree
|
||||
@param b the reference
|
||||
@param ctx context (for logging) */
|
||||
UNIV_INTERN
|
||||
void
|
||||
btr_blob_dbg_rbt_insert(
|
||||
/*====================*/
|
||||
dict_index_t* index, /*!< in/out: index tree */
|
||||
const btr_blob_dbg_t* b, /*!< in: the reference */
|
||||
const char* ctx) /*!< in: context (for logging) */
|
||||
__attribute__((nonnull));
|
||||
|
||||
/** Remove from index->blobs a reference to an off-page column.
|
||||
@param index the index tree
|
||||
@param b the reference
|
||||
@param ctx context (for logging) */
|
||||
UNIV_INTERN
|
||||
void
|
||||
btr_blob_dbg_rbt_delete(
|
||||
/*====================*/
|
||||
dict_index_t* index, /*!< in/out: index tree */
|
||||
const btr_blob_dbg_t* b, /*!< in: the reference */
|
||||
const char* ctx) /*!< in: context (for logging) */
|
||||
__attribute__((nonnull));
|
||||
|
||||
/**************************************************************//**
|
||||
Add to index->blobs any references to off-page columns from a record.
|
||||
@return number of references added */
|
||||
UNIV_INTERN
|
||||
ulint
|
||||
btr_blob_dbg_add_rec(
|
||||
/*=================*/
|
||||
const rec_t* rec, /*!< in: record */
|
||||
dict_index_t* index, /*!< in/out: index */
|
||||
const ulint* offsets,/*!< in: offsets */
|
||||
const char* ctx) /*!< in: context (for logging) */
|
||||
__attribute__((nonnull));
|
||||
/**************************************************************//**
|
||||
Remove from index->blobs any references to off-page columns from a record.
|
||||
@return number of references removed */
|
||||
UNIV_INTERN
|
||||
ulint
|
||||
btr_blob_dbg_remove_rec(
|
||||
/*====================*/
|
||||
const rec_t* rec, /*!< in: record */
|
||||
dict_index_t* index, /*!< in/out: index */
|
||||
const ulint* offsets,/*!< in: offsets */
|
||||
const char* ctx) /*!< in: context (for logging) */
|
||||
__attribute__((nonnull));
|
||||
/**************************************************************//**
|
||||
Count and add to index->blobs any references to off-page columns
|
||||
from records on a page.
|
||||
@return number of references added */
|
||||
UNIV_INTERN
|
||||
ulint
|
||||
btr_blob_dbg_add(
|
||||
/*=============*/
|
||||
const page_t* page, /*!< in: rewritten page */
|
||||
dict_index_t* index, /*!< in/out: index */
|
||||
const char* ctx) /*!< in: context (for logging) */
|
||||
__attribute__((nonnull));
|
||||
/**************************************************************//**
|
||||
Count and remove from index->blobs any references to off-page columns
|
||||
from records on a page.
|
||||
Used when reorganizing a page, before copying the records.
|
||||
@return number of references removed */
|
||||
UNIV_INTERN
|
||||
ulint
|
||||
btr_blob_dbg_remove(
|
||||
/*================*/
|
||||
const page_t* page, /*!< in: b-tree page */
|
||||
dict_index_t* index, /*!< in/out: index */
|
||||
const char* ctx) /*!< in: context (for logging) */
|
||||
__attribute__((nonnull));
|
||||
/**************************************************************//**
|
||||
Restore in index->blobs any references to off-page columns
|
||||
Used when page reorganize fails due to compressed page overflow. */
|
||||
UNIV_INTERN
|
||||
void
|
||||
btr_blob_dbg_restore(
|
||||
/*=================*/
|
||||
const page_t* npage, /*!< in: page that failed to compress */
|
||||
const page_t* page, /*!< in: copy of original page */
|
||||
dict_index_t* index, /*!< in/out: index */
|
||||
const char* ctx) /*!< in: context (for logging) */
|
||||
__attribute__((nonnull));
|
||||
|
||||
/** Operation that processes the BLOB references of an index record
|
||||
@param[in] rec record on index page
|
||||
@param[in/out] index the index tree of the record
|
||||
@param[in] offsets rec_get_offsets(rec,index)
|
||||
@param[in] ctx context (for logging)
|
||||
@return number of BLOB references processed */
|
||||
typedef ulint (*btr_blob_dbg_op_f)
|
||||
(const rec_t* rec,dict_index_t* index,const ulint* offsets,const char* ctx);
|
||||
|
||||
/**************************************************************//**
|
||||
Count and process all references to off-page columns on a page.
|
||||
@return number of references processed */
|
||||
UNIV_INTERN
|
||||
ulint
|
||||
btr_blob_dbg_op(
|
||||
/*============*/
|
||||
const page_t* page, /*!< in: B-tree leaf page */
|
||||
const rec_t* rec, /*!< in: record to start from
|
||||
(NULL to process the whole page) */
|
||||
dict_index_t* index, /*!< in/out: index */
|
||||
const char* ctx, /*!< in: context (for logging) */
|
||||
const btr_blob_dbg_op_f op) /*!< in: operation on records */
|
||||
__attribute__((nonnull(1,3,4,5)));
|
||||
#else /* UNIV_BLOB_DEBUG */
|
||||
# define btr_blob_dbg_add_rec(rec, index, offsets, ctx) ((void) 0)
|
||||
# define btr_blob_dbg_add(page, index, ctx) ((void) 0)
|
||||
# define btr_blob_dbg_remove_rec(rec, index, offsets, ctx) ((void) 0)
|
||||
# define btr_blob_dbg_remove(page, index, ctx) ((void) 0)
|
||||
# define btr_blob_dbg_restore(npage, page, index, ctx) ((void) 0)
|
||||
# define btr_blob_dbg_op(page, rec, index, ctx, op) ((void) 0)
|
||||
#endif /* UNIV_BLOB_DEBUG */
|
||||
|
||||
/** The size of a reference to data stored on a different page.
|
||||
The reference is stored at the end of the prefix of the field
|
||||
in the index record. */
|
||||
#define BTR_EXTERN_FIELD_REF_SIZE 20
|
||||
|
||||
/** A BLOB field reference full of zero, for use in assertions and tests.
|
||||
Initially, BLOB field references are set to zero, in
|
||||
dtuple_convert_big_rec(). */
|
||||
extern const byte field_ref_zero[BTR_EXTERN_FIELD_REF_SIZE];
|
||||
|
||||
#endif
|
||||
77
storage/innobase/include/buf0buddy.h
Normal file
77
storage/innobase/include/buf0buddy.h
Normal file
|
|
@ -0,0 +1,77 @@
|
|||
/*****************************************************************************
|
||||
|
||||
Copyright (c) 2006, 2011, Oracle and/or its affiliates. All Rights Reserved.
|
||||
|
||||
This program is free software; you can redistribute it and/or modify it under
|
||||
the terms of the GNU General Public License as published by the Free Software
|
||||
Foundation; version 2 of the License.
|
||||
|
||||
This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
|
||||
FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License along with
|
||||
this program; if not, write to the Free Software Foundation, Inc.,
|
||||
51 Franklin Street, Suite 500, Boston, MA 02110-1335 USA
|
||||
|
||||
*****************************************************************************/
|
||||
|
||||
/**************************************************//**
|
||||
@file include/buf0buddy.h
|
||||
Binary buddy allocator for compressed pages
|
||||
|
||||
Created December 2006 by Marko Makela
|
||||
*******************************************************/
|
||||
|
||||
#ifndef buf0buddy_h
|
||||
#define buf0buddy_h
|
||||
|
||||
#ifdef UNIV_MATERIALIZE
|
||||
# undef UNIV_INLINE
|
||||
# define UNIV_INLINE
|
||||
#endif
|
||||
|
||||
#include "univ.i"
|
||||
#include "buf0types.h"
|
||||
|
||||
/**********************************************************************//**
|
||||
Allocate a block. The thread calling this function must hold
|
||||
buf_pool->mutex and must not hold buf_pool->zip_mutex or any
|
||||
block->mutex. The buf_pool->mutex may be released and reacquired.
|
||||
This function should only be used for allocating compressed page frames.
|
||||
@return allocated block, never NULL */
|
||||
UNIV_INLINE
|
||||
byte*
|
||||
buf_buddy_alloc(
|
||||
/*============*/
|
||||
buf_pool_t* buf_pool, /*!< in/out: buffer pool in which
|
||||
the page resides */
|
||||
ulint size, /*!< in: compressed page size
|
||||
(between UNIV_ZIP_SIZE_MIN and
|
||||
UNIV_PAGE_SIZE) */
|
||||
ibool* lru) /*!< in: pointer to a variable
|
||||
that will be assigned TRUE if
|
||||
storage was allocated from the
|
||||
LRU list and buf_pool->mutex was
|
||||
temporarily released */
|
||||
__attribute__((malloc, nonnull));
|
||||
|
||||
/**********************************************************************//**
|
||||
Deallocate a block. */
|
||||
UNIV_INLINE
|
||||
void
|
||||
buf_buddy_free(
|
||||
/*===========*/
|
||||
buf_pool_t* buf_pool, /*!< in/out: buffer pool in which
|
||||
the block resides */
|
||||
void* buf, /*!< in: block to be freed, must not
|
||||
be pointed to by the buffer pool */
|
||||
ulint size) /*!< in: block size,
|
||||
up to UNIV_PAGE_SIZE */
|
||||
__attribute__((nonnull));
|
||||
|
||||
#ifndef UNIV_NONINL
|
||||
# include "buf0buddy.ic"
|
||||
#endif
|
||||
|
||||
#endif /* buf0buddy_h */
|
||||
143
storage/innobase/include/buf0buddy.ic
Normal file
143
storage/innobase/include/buf0buddy.ic
Normal file
|
|
@ -0,0 +1,143 @@
|
|||
/*****************************************************************************
|
||||
|
||||
Copyright (c) 2006, 2011, Oracle and/or its affiliates. All Rights Reserved.
|
||||
|
||||
This program is free software; you can redistribute it and/or modify it under
|
||||
the terms of the GNU General Public License as published by the Free Software
|
||||
Foundation; version 2 of the License.
|
||||
|
||||
This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
|
||||
FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License along with
|
||||
this program; if not, write to the Free Software Foundation, Inc.,
|
||||
51 Franklin Street, Suite 500, Boston, MA 02110-1335 USA
|
||||
|
||||
*****************************************************************************/
|
||||
|
||||
/**************************************************//**
|
||||
@file include/buf0buddy.ic
|
||||
Binary buddy allocator for compressed pages
|
||||
|
||||
Created December 2006 by Marko Makela
|
||||
*******************************************************/
|
||||
|
||||
#ifdef UNIV_MATERIALIZE
|
||||
# undef UNIV_INLINE
|
||||
# define UNIV_INLINE
|
||||
#endif
|
||||
|
||||
#include "buf0buf.h"
|
||||
#include "buf0buddy.h"
|
||||
#include "ut0ut.h"
|
||||
#include "sync0sync.h"
|
||||
|
||||
/**********************************************************************//**
|
||||
Allocate a block. The thread calling this function must hold
|
||||
buf_pool->mutex and must not hold buf_pool->zip_mutex or any block->mutex.
|
||||
The buf_pool_mutex may be released and reacquired.
|
||||
@return allocated block, never NULL */
|
||||
UNIV_INTERN
|
||||
void*
|
||||
buf_buddy_alloc_low(
|
||||
/*================*/
|
||||
buf_pool_t* buf_pool, /*!< in/out: buffer pool instance */
|
||||
ulint i, /*!< in: index of buf_pool->zip_free[],
|
||||
or BUF_BUDDY_SIZES */
|
||||
ibool* lru) /*!< in: pointer to a variable that
|
||||
will be assigned TRUE if storage was
|
||||
allocated from the LRU list and
|
||||
buf_pool->mutex was temporarily
|
||||
released */
|
||||
__attribute__((malloc, nonnull));
|
||||
|
||||
/**********************************************************************//**
|
||||
Deallocate a block. */
|
||||
UNIV_INTERN
|
||||
void
|
||||
buf_buddy_free_low(
|
||||
/*===============*/
|
||||
buf_pool_t* buf_pool, /*!< in: buffer pool instance */
|
||||
void* buf, /*!< in: block to be freed, must not be
|
||||
pointed to by the buffer pool */
|
||||
ulint i) /*!< in: index of buf_pool->zip_free[],
|
||||
or BUF_BUDDY_SIZES */
|
||||
__attribute__((nonnull));
|
||||
|
||||
/**********************************************************************//**
|
||||
Get the index of buf_pool->zip_free[] for a given block size.
|
||||
@return index of buf_pool->zip_free[], or BUF_BUDDY_SIZES */
|
||||
UNIV_INLINE
|
||||
ulint
|
||||
buf_buddy_get_slot(
|
||||
/*===============*/
|
||||
ulint size) /*!< in: block size */
|
||||
{
|
||||
ulint i;
|
||||
ulint s;
|
||||
|
||||
ut_ad(size >= UNIV_ZIP_SIZE_MIN);
|
||||
|
||||
for (i = 0, s = BUF_BUDDY_LOW; s < size; i++, s <<= 1) {
|
||||
}
|
||||
|
||||
ut_ad(i <= BUF_BUDDY_SIZES);
|
||||
return(i);
|
||||
}
|
||||
|
||||
/**********************************************************************//**
|
||||
Allocate a block. The thread calling this function must hold
|
||||
buf_pool->mutex and must not hold buf_pool->zip_mutex or any
|
||||
block->mutex. The buf_pool->mutex may be released and reacquired.
|
||||
This function should only be used for allocating compressed page frames.
|
||||
@return allocated block, never NULL */
|
||||
UNIV_INLINE
|
||||
byte*
|
||||
buf_buddy_alloc(
|
||||
/*============*/
|
||||
buf_pool_t* buf_pool, /*!< in/out: buffer pool in which
|
||||
the page resides */
|
||||
ulint size, /*!< in: compressed page size
|
||||
(between UNIV_ZIP_SIZE_MIN and
|
||||
UNIV_PAGE_SIZE) */
|
||||
ibool* lru) /*!< in: pointer to a variable
|
||||
that will be assigned TRUE if
|
||||
storage was allocated from the
|
||||
LRU list and buf_pool->mutex was
|
||||
temporarily released */
|
||||
{
|
||||
ut_ad(buf_pool_mutex_own(buf_pool));
|
||||
ut_ad(ut_is_2pow(size));
|
||||
ut_ad(size >= UNIV_ZIP_SIZE_MIN);
|
||||
ut_ad(size <= UNIV_PAGE_SIZE);
|
||||
|
||||
return((byte*) buf_buddy_alloc_low(buf_pool, buf_buddy_get_slot(size),
|
||||
lru));
|
||||
}
|
||||
|
||||
/**********************************************************************//**
|
||||
Deallocate a block. */
|
||||
UNIV_INLINE
|
||||
void
|
||||
buf_buddy_free(
|
||||
/*===========*/
|
||||
buf_pool_t* buf_pool, /*!< in/out: buffer pool in which
|
||||
the block resides */
|
||||
void* buf, /*!< in: block to be freed, must not
|
||||
be pointed to by the buffer pool */
|
||||
ulint size) /*!< in: block size,
|
||||
up to UNIV_PAGE_SIZE */
|
||||
{
|
||||
ut_ad(buf_pool_mutex_own(buf_pool));
|
||||
ut_ad(ut_is_2pow(size));
|
||||
ut_ad(size >= UNIV_ZIP_SIZE_MIN);
|
||||
ut_ad(size <= UNIV_PAGE_SIZE);
|
||||
|
||||
buf_buddy_free_low(buf_pool, buf, buf_buddy_get_slot(size));
|
||||
}
|
||||
|
||||
#ifdef UNIV_MATERIALIZE
|
||||
# undef UNIV_INLINE
|
||||
# define UNIV_INLINE UNIV_INLINE_ORIGINAL
|
||||
#endif
|
||||
2179
storage/innobase/include/buf0buf.h
Normal file
2179
storage/innobase/include/buf0buf.h
Normal file
File diff suppressed because it is too large
Load diff
1460
storage/innobase/include/buf0buf.ic
Normal file
1460
storage/innobase/include/buf0buf.ic
Normal file
File diff suppressed because it is too large
Load diff
88
storage/innobase/include/buf0checksum.h
Normal file
88
storage/innobase/include/buf0checksum.h
Normal file
|
|
@ -0,0 +1,88 @@
|
|||
/*****************************************************************************
|
||||
|
||||
Copyright (c) 1995, 2011, Oracle and/or its affiliates. All Rights Reserved.
|
||||
|
||||
This program is free software; you can redistribute it and/or modify it under
|
||||
the terms of the GNU General Public License as published by the Free Software
|
||||
Foundation; version 2 of the License.
|
||||
|
||||
This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
|
||||
FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License along with
|
||||
this program; if not, write to the Free Software Foundation, Inc.,
|
||||
51 Franklin Street, Suite 500, Boston, MA 02110-1335 USA
|
||||
|
||||
*****************************************************************************/
|
||||
|
||||
/**************************************************//**
|
||||
@file buf/buf0checksum.h
|
||||
Buffer pool checksum functions, also linked from /extra/innochecksum.cc
|
||||
|
||||
Created Aug 11, 2011 Vasil Dimov
|
||||
*******************************************************/
|
||||
|
||||
#ifndef buf0checksum_h
|
||||
#define buf0checksum_h
|
||||
|
||||
#include "univ.i"
|
||||
|
||||
#ifndef UNIV_INNOCHECKSUM
|
||||
|
||||
#include "buf0types.h"
|
||||
|
||||
#endif /* !UNIV_INNOCHECKSUM */
|
||||
|
||||
/********************************************************************//**
|
||||
Calculates a page CRC32 which is stored to the page when it is written
|
||||
to a file. Note that we must be careful to calculate the same value on
|
||||
32-bit and 64-bit architectures.
|
||||
@return checksum */
|
||||
UNIV_INTERN
|
||||
ib_uint32_t
|
||||
buf_calc_page_crc32(
|
||||
/*================*/
|
||||
const byte* page); /*!< in: buffer page */
|
||||
|
||||
/********************************************************************//**
|
||||
Calculates a page checksum which is stored to the page when it is written
|
||||
to a file. Note that we must be careful to calculate the same value on
|
||||
32-bit and 64-bit architectures.
|
||||
@return checksum */
|
||||
UNIV_INTERN
|
||||
ulint
|
||||
buf_calc_page_new_checksum(
|
||||
/*=======================*/
|
||||
const byte* page); /*!< in: buffer page */
|
||||
|
||||
/********************************************************************//**
|
||||
In versions < 4.0.14 and < 4.1.1 there was a bug that the checksum only
|
||||
looked at the first few bytes of the page. This calculates that old
|
||||
checksum.
|
||||
NOTE: we must first store the new formula checksum to
|
||||
FIL_PAGE_SPACE_OR_CHKSUM before calculating and storing this old checksum
|
||||
because this takes that field as an input!
|
||||
@return checksum */
|
||||
UNIV_INTERN
|
||||
ulint
|
||||
buf_calc_page_old_checksum(
|
||||
/*=======================*/
|
||||
const byte* page); /*!< in: buffer page */
|
||||
|
||||
#ifndef UNIV_INNOCHECKSUM
|
||||
|
||||
/********************************************************************//**
|
||||
Return a printable string describing the checksum algorithm.
|
||||
@return algorithm name */
|
||||
UNIV_INTERN
|
||||
const char*
|
||||
buf_checksum_algorithm_name(
|
||||
/*========================*/
|
||||
srv_checksum_algorithm_t algo); /*!< in: algorithm */
|
||||
|
||||
extern ulong srv_checksum_algorithm;
|
||||
|
||||
#endif /* !UNIV_INNOCHECKSUM */
|
||||
|
||||
#endif /* buf0checksum_h */
|
||||
162
storage/innobase/include/buf0dblwr.h
Normal file
162
storage/innobase/include/buf0dblwr.h
Normal file
|
|
@ -0,0 +1,162 @@
|
|||
/*****************************************************************************
|
||||
|
||||
Copyright (c) 1995, 2014, Oracle and/or its affiliates. All Rights Reserved.
|
||||
|
||||
This program is free software; you can redistribute it and/or modify it under
|
||||
the terms of the GNU General Public License as published by the Free Software
|
||||
Foundation; version 2 of the License.
|
||||
|
||||
This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
|
||||
FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License along with
|
||||
this program; if not, write to the Free Software Foundation, Inc.,
|
||||
51 Franklin Street, Suite 500, Boston, MA 02110-1335 USA
|
||||
|
||||
*****************************************************************************/
|
||||
|
||||
/**************************************************//**
|
||||
@file include/buf0dblwr.h
|
||||
Doublewrite buffer module
|
||||
|
||||
Created 2011/12/19 Inaam Rana
|
||||
*******************************************************/
|
||||
|
||||
#ifndef buf0dblwr_h
|
||||
#define buf0dblwr_h
|
||||
|
||||
#include "univ.i"
|
||||
#include "ut0byte.h"
|
||||
#include "log0log.h"
|
||||
#include "log0recv.h"
|
||||
|
||||
#ifndef UNIV_HOTBACKUP
|
||||
|
||||
/** Doublewrite system */
|
||||
extern buf_dblwr_t* buf_dblwr;
|
||||
/** Set to TRUE when the doublewrite buffer is being created */
|
||||
extern ibool buf_dblwr_being_created;
|
||||
|
||||
/****************************************************************//**
|
||||
Creates the doublewrite buffer to a new InnoDB installation. The header of the
|
||||
doublewrite buffer is placed on the trx system header page. */
|
||||
UNIV_INTERN
|
||||
void
|
||||
buf_dblwr_create(void);
|
||||
/*==================*/
|
||||
|
||||
/****************************************************************//**
|
||||
At a database startup initializes the doublewrite buffer memory structure if
|
||||
we already have a doublewrite buffer created in the data files. If we are
|
||||
upgrading to an InnoDB version which supports multiple tablespaces, then this
|
||||
function performs the necessary update operations. If we are in a crash
|
||||
recovery, this function loads the pages from double write buffer into memory. */
|
||||
void
|
||||
buf_dblwr_init_or_load_pages(
|
||||
/*=========================*/
|
||||
os_file_t file,
|
||||
char* path,
|
||||
bool load_corrupt_pages);
|
||||
|
||||
/****************************************************************//**
|
||||
Process the double write buffer pages. */
|
||||
void
|
||||
buf_dblwr_process(void);
|
||||
/*===================*/
|
||||
|
||||
/****************************************************************//**
|
||||
frees doublewrite buffer. */
|
||||
UNIV_INTERN
|
||||
void
|
||||
buf_dblwr_free(void);
|
||||
/*================*/
|
||||
/********************************************************************//**
|
||||
Updates the doublewrite buffer when an IO request is completed. */
|
||||
UNIV_INTERN
|
||||
void
|
||||
buf_dblwr_update(
|
||||
/*=============*/
|
||||
const buf_page_t* bpage, /*!< in: buffer block descriptor */
|
||||
buf_flush_t flush_type);/*!< in: flush type */
|
||||
/****************************************************************//**
|
||||
Determines if a page number is located inside the doublewrite buffer.
|
||||
@return TRUE if the location is inside the two blocks of the
|
||||
doublewrite buffer */
|
||||
UNIV_INTERN
|
||||
ibool
|
||||
buf_dblwr_page_inside(
|
||||
/*==================*/
|
||||
ulint page_no); /*!< in: page number */
|
||||
/********************************************************************//**
|
||||
Posts a buffer page for writing. If the doublewrite memory buffer is
|
||||
full, calls buf_dblwr_flush_buffered_writes and waits for for free
|
||||
space to appear. */
|
||||
UNIV_INTERN
|
||||
void
|
||||
buf_dblwr_add_to_batch(
|
||||
/*====================*/
|
||||
buf_page_t* bpage); /*!< in: buffer block to write */
|
||||
/********************************************************************//**
|
||||
Flushes possible buffered writes from the doublewrite memory buffer to disk,
|
||||
and also wakes up the aio thread if simulated aio is used. It is very
|
||||
important to call this function after a batch of writes has been posted,
|
||||
and also when we may have to wait for a page latch! Otherwise a deadlock
|
||||
of threads can occur. */
|
||||
UNIV_INTERN
|
||||
void
|
||||
buf_dblwr_flush_buffered_writes(void);
|
||||
/*=================================*/
|
||||
/********************************************************************//**
|
||||
Writes a page to the doublewrite buffer on disk, sync it, then write
|
||||
the page to the datafile and sync the datafile. This function is used
|
||||
for single page flushes. If all the buffers allocated for single page
|
||||
flushes in the doublewrite buffer are in use we wait here for one to
|
||||
become free. We are guaranteed that a slot will become free because any
|
||||
thread that is using a slot must also release the slot before leaving
|
||||
this function. */
|
||||
UNIV_INTERN
|
||||
void
|
||||
buf_dblwr_write_single_page(
|
||||
/*========================*/
|
||||
buf_page_t* bpage, /*!< in: buffer block to write */
|
||||
bool sync); /*!< in: true if sync IO requested */
|
||||
|
||||
/** Doublewrite control struct */
|
||||
struct buf_dblwr_t{
|
||||
ib_mutex_t mutex; /*!< mutex protecting the first_free
|
||||
field and write_buf */
|
||||
ulint block1; /*!< the page number of the first
|
||||
doublewrite block (64 pages) */
|
||||
ulint block2; /*!< page number of the second block */
|
||||
ulint first_free;/*!< first free position in write_buf
|
||||
measured in units of UNIV_PAGE_SIZE */
|
||||
ulint b_reserved;/*!< number of slots currently reserved
|
||||
for batch flush. */
|
||||
os_event_t b_event;/*!< event where threads wait for a
|
||||
batch flush to end. */
|
||||
ulint s_reserved;/*!< number of slots currently
|
||||
reserved for single page flushes. */
|
||||
os_event_t s_event;/*!< event where threads wait for a
|
||||
single page flush slot. */
|
||||
bool* in_use; /*!< flag used to indicate if a slot is
|
||||
in use. Only used for single page
|
||||
flushes. */
|
||||
bool batch_running;/*!< set to TRUE if currently a batch
|
||||
is being written from the doublewrite
|
||||
buffer. */
|
||||
byte* write_buf;/*!< write buffer used in writing to the
|
||||
doublewrite buffer, aligned to an
|
||||
address divisible by UNIV_PAGE_SIZE
|
||||
(which is required by Windows aio) */
|
||||
byte* write_buf_unaligned;/*!< pointer to write_buf,
|
||||
but unaligned */
|
||||
buf_page_t** buf_block_arr;/*!< array to store pointers to
|
||||
the buffer blocks which have been
|
||||
cached to write_buf */
|
||||
};
|
||||
|
||||
|
||||
#endif /* UNIV_HOTBACKUP */
|
||||
|
||||
#endif
|
||||
72
storage/innobase/include/buf0dump.h
Normal file
72
storage/innobase/include/buf0dump.h
Normal file
|
|
@ -0,0 +1,72 @@
|
|||
/*****************************************************************************
|
||||
|
||||
Copyright (c) 2011, 2011, Oracle and/or its affiliates. All Rights Reserved.
|
||||
|
||||
This program is free software; you can redistribute it and/or modify it under
|
||||
the terms of the GNU General Public License as published by the Free Software
|
||||
Foundation; version 2 of the License.
|
||||
|
||||
This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
|
||||
FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License along with
|
||||
this program; if not, write to the Free Software Foundation, Inc.,
|
||||
51 Franklin Street, Suite 500, Boston, MA 02110-1335 USA
|
||||
|
||||
*****************************************************************************/
|
||||
|
||||
/**************************************************//**
|
||||
@file buf/buf0dump.h
|
||||
Implements a buffer pool dump/load.
|
||||
|
||||
Created April 08, 2011 Vasil Dimov
|
||||
*******************************************************/
|
||||
|
||||
#ifndef buf0dump_h
|
||||
#define buf0dump_h
|
||||
|
||||
#include "univ.i"
|
||||
|
||||
/*****************************************************************//**
|
||||
Wakes up the buffer pool dump/load thread and instructs it to start
|
||||
a dump. This function is called by MySQL code via buffer_pool_dump_now()
|
||||
and it should return immediately because the whole MySQL is frozen during
|
||||
its execution. */
|
||||
UNIV_INTERN
|
||||
void
|
||||
buf_dump_start();
|
||||
/*============*/
|
||||
|
||||
/*****************************************************************//**
|
||||
Wakes up the buffer pool dump/load thread and instructs it to start
|
||||
a load. This function is called by MySQL code via buffer_pool_load_now()
|
||||
and it should return immediately because the whole MySQL is frozen during
|
||||
its execution. */
|
||||
UNIV_INTERN
|
||||
void
|
||||
buf_load_start();
|
||||
/*============*/
|
||||
|
||||
/*****************************************************************//**
|
||||
Aborts a currently running buffer pool load. This function is called by
|
||||
MySQL code via buffer_pool_load_abort() and it should return immediately
|
||||
because the whole MySQL is frozen during its execution. */
|
||||
UNIV_INTERN
|
||||
void
|
||||
buf_load_abort();
|
||||
/*============*/
|
||||
|
||||
/*****************************************************************//**
|
||||
This is the main thread for buffer pool dump/load. It waits for an
|
||||
event and when waked up either performs a dump or load and sleeps
|
||||
again.
|
||||
@return this function does not return, it calls os_thread_exit() */
|
||||
extern "C" UNIV_INTERN
|
||||
os_thread_ret_t
|
||||
DECLARE_THREAD(buf_dump_thread)(
|
||||
/*============================*/
|
||||
void* arg); /*!< in: a dummy parameter
|
||||
required by os_thread_create */
|
||||
|
||||
#endif /* buf0dump_h */
|
||||
286
storage/innobase/include/buf0flu.h
Normal file
286
storage/innobase/include/buf0flu.h
Normal file
|
|
@ -0,0 +1,286 @@
|
|||
/*****************************************************************************
|
||||
|
||||
Copyright (c) 1995, 2013, Oracle and/or its affiliates. All Rights Reserved.
|
||||
|
||||
This program is free software; you can redistribute it and/or modify it under
|
||||
the terms of the GNU General Public License as published by the Free Software
|
||||
Foundation; version 2 of the License.
|
||||
|
||||
This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
|
||||
FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License along with
|
||||
this program; if not, write to the Free Software Foundation, Inc.,
|
||||
51 Franklin Street, Suite 500, Boston, MA 02110-1335 USA
|
||||
|
||||
*****************************************************************************/
|
||||
|
||||
/**************************************************//**
|
||||
@file include/buf0flu.h
|
||||
The database buffer pool flush algorithm
|
||||
|
||||
Created 11/5/1995 Heikki Tuuri
|
||||
*******************************************************/
|
||||
|
||||
#ifndef buf0flu_h
|
||||
#define buf0flu_h
|
||||
|
||||
#include "univ.i"
|
||||
#include "ut0byte.h"
|
||||
#include "log0log.h"
|
||||
#ifndef UNIV_HOTBACKUP
|
||||
#include "mtr0types.h"
|
||||
#include "buf0types.h"
|
||||
|
||||
/** Flag indicating if the page_cleaner is in active state. */
|
||||
extern ibool buf_page_cleaner_is_active;
|
||||
|
||||
/********************************************************************//**
|
||||
Remove a block from the flush list of modified blocks. */
|
||||
UNIV_INTERN
|
||||
void
|
||||
buf_flush_remove(
|
||||
/*=============*/
|
||||
buf_page_t* bpage); /*!< in: pointer to the block in question */
|
||||
/*******************************************************************//**
|
||||
Relocates a buffer control block on the flush_list.
|
||||
Note that it is assumed that the contents of bpage has already been
|
||||
copied to dpage. */
|
||||
UNIV_INTERN
|
||||
void
|
||||
buf_flush_relocate_on_flush_list(
|
||||
/*=============================*/
|
||||
buf_page_t* bpage, /*!< in/out: control block being moved */
|
||||
buf_page_t* dpage); /*!< in/out: destination block */
|
||||
/********************************************************************//**
|
||||
Updates the flush system data structures when a write is completed. */
|
||||
UNIV_INTERN
|
||||
void
|
||||
buf_flush_write_complete(
|
||||
/*=====================*/
|
||||
buf_page_t* bpage); /*!< in: pointer to the block in question */
|
||||
#endif /* !UNIV_HOTBACKUP */
|
||||
/********************************************************************//**
|
||||
Initializes a page for writing to the tablespace. */
|
||||
UNIV_INTERN
|
||||
void
|
||||
buf_flush_init_for_writing(
|
||||
/*=======================*/
|
||||
byte* page, /*!< in/out: page */
|
||||
void* page_zip_, /*!< in/out: compressed page, or NULL */
|
||||
lsn_t newest_lsn); /*!< in: newest modification lsn
|
||||
to the page */
|
||||
#ifndef UNIV_HOTBACKUP
|
||||
# if defined UNIV_DEBUG || defined UNIV_IBUF_DEBUG
|
||||
/********************************************************************//**
|
||||
Writes a flushable page asynchronously from the buffer pool to a file.
|
||||
NOTE: buf_pool->mutex and block->mutex must be held upon entering this
|
||||
function, and they will be released by this function after flushing.
|
||||
This is loosely based on buf_flush_batch() and buf_flush_page().
|
||||
@return TRUE if the page was flushed and the mutexes released */
|
||||
UNIV_INTERN
|
||||
ibool
|
||||
buf_flush_page_try(
|
||||
/*===============*/
|
||||
buf_pool_t* buf_pool, /*!< in/out: buffer pool instance */
|
||||
buf_block_t* block) /*!< in/out: buffer control block */
|
||||
__attribute__((nonnull, warn_unused_result));
|
||||
# endif /* UNIV_DEBUG || UNIV_IBUF_DEBUG */
|
||||
/*******************************************************************//**
|
||||
This utility flushes dirty blocks from the end of the flush list of
|
||||
all buffer pool instances.
|
||||
NOTE: The calling thread is not allowed to own any latches on pages!
|
||||
@return true if a batch was queued successfully for each buffer pool
|
||||
instance. false if another batch of same type was already running in
|
||||
at least one of the buffer pool instance */
|
||||
UNIV_INTERN
|
||||
bool
|
||||
buf_flush_list(
|
||||
/*===========*/
|
||||
ulint min_n, /*!< in: wished minimum mumber of blocks
|
||||
flushed (it is not guaranteed that the
|
||||
actual number is that big, though) */
|
||||
lsn_t lsn_limit, /*!< in the case BUF_FLUSH_LIST all
|
||||
blocks whose oldest_modification is
|
||||
smaller than this should be flushed
|
||||
(if their number does not exceed
|
||||
min_n), otherwise ignored */
|
||||
ulint* n_processed); /*!< out: the number of pages
|
||||
which were processed is passed
|
||||
back to caller. Ignored if NULL */
|
||||
/******************************************************************//**
|
||||
This function picks up a single dirty page from the tail of the LRU
|
||||
list, flushes it, removes it from page_hash and LRU list and puts
|
||||
it on the free list. It is called from user threads when they are
|
||||
unable to find a replacable page at the tail of the LRU list i.e.:
|
||||
when the background LRU flushing in the page_cleaner thread is not
|
||||
fast enough to keep pace with the workload.
|
||||
@return TRUE if success. */
|
||||
UNIV_INTERN
|
||||
ibool
|
||||
buf_flush_single_page_from_LRU(
|
||||
/*===========================*/
|
||||
buf_pool_t* buf_pool); /*!< in/out: buffer pool instance */
|
||||
/******************************************************************//**
|
||||
Waits until a flush batch of the given type ends */
|
||||
UNIV_INTERN
|
||||
void
|
||||
buf_flush_wait_batch_end(
|
||||
/*=====================*/
|
||||
buf_pool_t* buf_pool, /*!< in: buffer pool instance */
|
||||
buf_flush_t type); /*!< in: BUF_FLUSH_LRU
|
||||
or BUF_FLUSH_LIST */
|
||||
/******************************************************************//**
|
||||
Waits until a flush batch of the given type ends. This is called by
|
||||
a thread that only wants to wait for a flush to end but doesn't do
|
||||
any flushing itself. */
|
||||
UNIV_INTERN
|
||||
void
|
||||
buf_flush_wait_batch_end_wait_only(
|
||||
/*===============================*/
|
||||
buf_pool_t* buf_pool, /*!< in: buffer pool instance */
|
||||
buf_flush_t type); /*!< in: BUF_FLUSH_LRU
|
||||
or BUF_FLUSH_LIST */
|
||||
/********************************************************************//**
|
||||
This function should be called at a mini-transaction commit, if a page was
|
||||
modified in it. Puts the block to the list of modified blocks, if it not
|
||||
already in it. */
|
||||
UNIV_INLINE
|
||||
void
|
||||
buf_flush_note_modification(
|
||||
/*========================*/
|
||||
buf_block_t* block, /*!< in: block which is modified */
|
||||
mtr_t* mtr); /*!< in: mtr */
|
||||
/********************************************************************//**
|
||||
This function should be called when recovery has modified a buffer page. */
|
||||
UNIV_INLINE
|
||||
void
|
||||
buf_flush_recv_note_modification(
|
||||
/*=============================*/
|
||||
buf_block_t* block, /*!< in: block which is modified */
|
||||
lsn_t start_lsn, /*!< in: start lsn of the first mtr in a
|
||||
set of mtr's */
|
||||
lsn_t end_lsn); /*!< in: end lsn of the last mtr in the
|
||||
set of mtr's */
|
||||
/********************************************************************//**
|
||||
Returns TRUE if the file page block is immediately suitable for replacement,
|
||||
i.e., transition FILE_PAGE => NOT_USED allowed.
|
||||
@return TRUE if can replace immediately */
|
||||
UNIV_INTERN
|
||||
ibool
|
||||
buf_flush_ready_for_replace(
|
||||
/*========================*/
|
||||
buf_page_t* bpage); /*!< in: buffer control block, must be
|
||||
buf_page_in_file(bpage) and in the LRU list */
|
||||
/******************************************************************//**
|
||||
page_cleaner thread tasked with flushing dirty pages from the buffer
|
||||
pools. As of now we'll have only one instance of this thread.
|
||||
@return a dummy parameter */
|
||||
extern "C" UNIV_INTERN
|
||||
os_thread_ret_t
|
||||
DECLARE_THREAD(buf_flush_page_cleaner_thread)(
|
||||
/*==========================================*/
|
||||
void* arg); /*!< in: a dummy parameter required by
|
||||
os_thread_create */
|
||||
/*********************************************************************//**
|
||||
Clears up tail of the LRU lists:
|
||||
* Put replaceable pages at the tail of LRU to the free list
|
||||
* Flush dirty pages at the tail of LRU to the disk
|
||||
The depth to which we scan each buffer pool is controlled by dynamic
|
||||
config parameter innodb_LRU_scan_depth.
|
||||
@return total pages flushed */
|
||||
UNIV_INTERN
|
||||
ulint
|
||||
buf_flush_LRU_tail(void);
|
||||
/*====================*/
|
||||
/*********************************************************************//**
|
||||
Wait for any possible LRU flushes that are in progress to end. */
|
||||
UNIV_INTERN
|
||||
void
|
||||
buf_flush_wait_LRU_batch_end(void);
|
||||
/*==============================*/
|
||||
|
||||
#if defined UNIV_DEBUG || defined UNIV_BUF_DEBUG
|
||||
/******************************************************************//**
|
||||
Validates the flush list.
|
||||
@return TRUE if ok */
|
||||
UNIV_INTERN
|
||||
ibool
|
||||
buf_flush_validate(
|
||||
/*===============*/
|
||||
buf_pool_t* buf_pool);
|
||||
#endif /* UNIV_DEBUG || UNIV_BUF_DEBUG */
|
||||
|
||||
/********************************************************************//**
|
||||
Initialize the red-black tree to speed up insertions into the flush_list
|
||||
during recovery process. Should be called at the start of recovery
|
||||
process before any page has been read/written. */
|
||||
UNIV_INTERN
|
||||
void
|
||||
buf_flush_init_flush_rbt(void);
|
||||
/*==========================*/
|
||||
|
||||
/********************************************************************//**
|
||||
Frees up the red-black tree. */
|
||||
UNIV_INTERN
|
||||
void
|
||||
buf_flush_free_flush_rbt(void);
|
||||
/*==========================*/
|
||||
|
||||
/********************************************************************//**
|
||||
Writes a flushable page asynchronously from the buffer pool to a file.
|
||||
NOTE: in simulated aio we must call
|
||||
os_aio_simulated_wake_handler_threads after we have posted a batch of
|
||||
writes! NOTE: buf_pool->mutex and buf_page_get_mutex(bpage) must be
|
||||
held upon entering this function, and they will be released by this
|
||||
function if it returns true.
|
||||
@return TRUE if the page was flushed */
|
||||
UNIV_INTERN
|
||||
bool
|
||||
buf_flush_page(
|
||||
/*===========*/
|
||||
buf_pool_t* buf_pool, /*!< in: buffer pool instance */
|
||||
buf_page_t* bpage, /*!< in: buffer control block */
|
||||
buf_flush_t flush_type, /*!< in: type of flush */
|
||||
bool sync); /*!< in: true if sync IO request */
|
||||
/********************************************************************//**
|
||||
Returns true if the block is modified and ready for flushing.
|
||||
@return true if can flush immediately */
|
||||
UNIV_INTERN
|
||||
bool
|
||||
buf_flush_ready_for_flush(
|
||||
/*======================*/
|
||||
buf_page_t* bpage, /*!< in: buffer control block, must be
|
||||
buf_page_in_file(bpage) */
|
||||
buf_flush_t flush_type)/*!< in: type of flush */
|
||||
__attribute__((warn_unused_result));
|
||||
|
||||
#ifdef UNIV_DEBUG
|
||||
/******************************************************************//**
|
||||
Check if there are any dirty pages that belong to a space id in the flush
|
||||
list in a particular buffer pool.
|
||||
@return number of dirty pages present in a single buffer pool */
|
||||
UNIV_INTERN
|
||||
ulint
|
||||
buf_pool_get_dirty_pages_count(
|
||||
/*===========================*/
|
||||
buf_pool_t* buf_pool, /*!< in: buffer pool */
|
||||
ulint id); /*!< in: space id to check */
|
||||
/******************************************************************//**
|
||||
Check if there are any dirty pages that belong to a space id in the flush list.
|
||||
@return count of dirty pages present in all the buffer pools */
|
||||
UNIV_INTERN
|
||||
ulint
|
||||
buf_flush_get_dirty_pages_count(
|
||||
/*============================*/
|
||||
ulint id); /*!< in: space id to check */
|
||||
#endif /* UNIV_DEBUG */
|
||||
|
||||
#endif /* !UNIV_HOTBACKUP */
|
||||
|
||||
#ifndef UNIV_NONINL
|
||||
#include "buf0flu.ic"
|
||||
#endif
|
||||
|
||||
#endif
|
||||
139
storage/innobase/include/buf0flu.ic
Normal file
139
storage/innobase/include/buf0flu.ic
Normal file
|
|
@ -0,0 +1,139 @@
|
|||
/*****************************************************************************
|
||||
|
||||
Copyright (c) 1995, 2009, Oracle and/or its affiliates. All Rights Reserved.
|
||||
|
||||
This program is free software; you can redistribute it and/or modify it under
|
||||
the terms of the GNU General Public License as published by the Free Software
|
||||
Foundation; version 2 of the License.
|
||||
|
||||
This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
|
||||
FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License along with
|
||||
this program; if not, write to the Free Software Foundation, Inc.,
|
||||
51 Franklin Street, Suite 500, Boston, MA 02110-1335 USA
|
||||
|
||||
*****************************************************************************/
|
||||
|
||||
/**************************************************//**
|
||||
@file include/buf0flu.ic
|
||||
The database buffer pool flush algorithm
|
||||
|
||||
Created 11/5/1995 Heikki Tuuri
|
||||
*******************************************************/
|
||||
|
||||
#ifndef UNIV_HOTBACKUP
|
||||
#include "buf0buf.h"
|
||||
#include "mtr0mtr.h"
|
||||
#include "srv0srv.h"
|
||||
|
||||
/********************************************************************//**
|
||||
Inserts a modified block into the flush list. */
|
||||
UNIV_INTERN
|
||||
void
|
||||
buf_flush_insert_into_flush_list(
|
||||
/*=============================*/
|
||||
buf_pool_t* buf_pool, /*!< buffer pool instance */
|
||||
buf_block_t* block, /*!< in/out: block which is modified */
|
||||
lsn_t lsn); /*!< in: oldest modification */
|
||||
/********************************************************************//**
|
||||
Inserts a modified block into the flush list in the right sorted position.
|
||||
This function is used by recovery, because there the modifications do not
|
||||
necessarily come in the order of lsn's. */
|
||||
UNIV_INTERN
|
||||
void
|
||||
buf_flush_insert_sorted_into_flush_list(
|
||||
/*====================================*/
|
||||
buf_pool_t* buf_pool, /*!< buffer pool instance */
|
||||
buf_block_t* block, /*!< in/out: block which is modified */
|
||||
lsn_t lsn); /*!< in: oldest modification */
|
||||
|
||||
/********************************************************************//**
|
||||
This function should be called at a mini-transaction commit, if a page was
|
||||
modified in it. Puts the block to the list of modified blocks, if it is not
|
||||
already in it. */
|
||||
UNIV_INLINE
|
||||
void
|
||||
buf_flush_note_modification(
|
||||
/*========================*/
|
||||
buf_block_t* block, /*!< in: block which is modified */
|
||||
mtr_t* mtr) /*!< in: mtr */
|
||||
{
|
||||
buf_pool_t* buf_pool = buf_pool_from_block(block);
|
||||
|
||||
ut_ad(!srv_read_only_mode);
|
||||
ut_ad(buf_block_get_state(block) == BUF_BLOCK_FILE_PAGE);
|
||||
ut_ad(block->page.buf_fix_count > 0);
|
||||
#ifdef UNIV_SYNC_DEBUG
|
||||
ut_ad(rw_lock_own(&(block->lock), RW_LOCK_EX));
|
||||
#endif /* UNIV_SYNC_DEBUG */
|
||||
|
||||
ut_ad(!buf_pool_mutex_own(buf_pool));
|
||||
ut_ad(!buf_flush_list_mutex_own(buf_pool));
|
||||
ut_ad(!mtr->made_dirty || log_flush_order_mutex_own());
|
||||
|
||||
ut_ad(mtr->start_lsn != 0);
|
||||
ut_ad(mtr->modifications);
|
||||
|
||||
mutex_enter(&block->mutex);
|
||||
ut_ad(block->page.newest_modification <= mtr->end_lsn);
|
||||
|
||||
block->page.newest_modification = mtr->end_lsn;
|
||||
|
||||
if (!block->page.oldest_modification) {
|
||||
ut_a(mtr->made_dirty);
|
||||
ut_ad(log_flush_order_mutex_own());
|
||||
buf_flush_insert_into_flush_list(
|
||||
buf_pool, block, mtr->start_lsn);
|
||||
} else {
|
||||
ut_ad(block->page.oldest_modification <= mtr->start_lsn);
|
||||
}
|
||||
|
||||
mutex_exit(&block->mutex);
|
||||
|
||||
srv_stats.buf_pool_write_requests.inc();
|
||||
}
|
||||
|
||||
/********************************************************************//**
|
||||
This function should be called when recovery has modified a buffer page. */
|
||||
UNIV_INLINE
|
||||
void
|
||||
buf_flush_recv_note_modification(
|
||||
/*=============================*/
|
||||
buf_block_t* block, /*!< in: block which is modified */
|
||||
lsn_t start_lsn, /*!< in: start lsn of the first mtr in a
|
||||
set of mtr's */
|
||||
lsn_t end_lsn) /*!< in: end lsn of the last mtr in the
|
||||
set of mtr's */
|
||||
{
|
||||
buf_pool_t* buf_pool = buf_pool_from_block(block);
|
||||
|
||||
ut_ad(!srv_read_only_mode);
|
||||
ut_ad(buf_block_get_state(block) == BUF_BLOCK_FILE_PAGE);
|
||||
ut_ad(block->page.buf_fix_count > 0);
|
||||
#ifdef UNIV_SYNC_DEBUG
|
||||
ut_ad(rw_lock_own(&(block->lock), RW_LOCK_EX));
|
||||
#endif /* UNIV_SYNC_DEBUG */
|
||||
|
||||
ut_ad(!buf_pool_mutex_own(buf_pool));
|
||||
ut_ad(!buf_flush_list_mutex_own(buf_pool));
|
||||
ut_ad(log_flush_order_mutex_own());
|
||||
|
||||
ut_ad(start_lsn != 0);
|
||||
ut_ad(block->page.newest_modification <= end_lsn);
|
||||
|
||||
mutex_enter(&block->mutex);
|
||||
block->page.newest_modification = end_lsn;
|
||||
|
||||
if (!block->page.oldest_modification) {
|
||||
buf_flush_insert_sorted_into_flush_list(
|
||||
buf_pool, block, start_lsn);
|
||||
} else {
|
||||
ut_ad(block->page.oldest_modification <= start_lsn);
|
||||
}
|
||||
|
||||
mutex_exit(&block->mutex);
|
||||
|
||||
}
|
||||
#endif /* !UNIV_HOTBACKUP */
|
||||
310
storage/innobase/include/buf0lru.h
Normal file
310
storage/innobase/include/buf0lru.h
Normal file
|
|
@ -0,0 +1,310 @@
|
|||
/*****************************************************************************
|
||||
|
||||
Copyright (c) 1995, 2013, Oracle and/or its affiliates. All Rights Reserved.
|
||||
|
||||
This program is free software; you can redistribute it and/or modify it under
|
||||
the terms of the GNU General Public License as published by the Free Software
|
||||
Foundation; version 2 of the License.
|
||||
|
||||
This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
|
||||
FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License along with
|
||||
this program; if not, write to the Free Software Foundation, Inc.,
|
||||
51 Franklin Street, Suite 500, Boston, MA 02110-1335 USA
|
||||
|
||||
*****************************************************************************/
|
||||
|
||||
/**************************************************//**
|
||||
@file include/buf0lru.h
|
||||
The database buffer pool LRU replacement algorithm
|
||||
|
||||
Created 11/5/1995 Heikki Tuuri
|
||||
*******************************************************/
|
||||
|
||||
#ifndef buf0lru_h
|
||||
#define buf0lru_h
|
||||
|
||||
#include "univ.i"
|
||||
#ifndef UNIV_HOTBACKUP
|
||||
#include "ut0byte.h"
|
||||
#include "buf0types.h"
|
||||
|
||||
// Forward declaration
|
||||
struct trx_t;
|
||||
|
||||
/******************************************************************//**
|
||||
Returns TRUE if less than 25 % of the buffer pool is available. This can be
|
||||
used in heuristics to prevent huge transactions eating up the whole buffer
|
||||
pool for their locks.
|
||||
@return TRUE if less than 25 % of buffer pool left */
|
||||
UNIV_INTERN
|
||||
ibool
|
||||
buf_LRU_buf_pool_running_out(void);
|
||||
/*==============================*/
|
||||
|
||||
/*#######################################################################
|
||||
These are low-level functions
|
||||
#########################################################################*/
|
||||
|
||||
/** Minimum LRU list length for which the LRU_old pointer is defined */
|
||||
#define BUF_LRU_OLD_MIN_LEN 512 /* 8 megabytes of 16k pages */
|
||||
|
||||
/******************************************************************//**
|
||||
Flushes all dirty pages or removes all pages belonging
|
||||
to a given tablespace. A PROBLEM: if readahead is being started, what
|
||||
guarantees that it will not try to read in pages after this operation
|
||||
has completed? */
|
||||
UNIV_INTERN
|
||||
void
|
||||
buf_LRU_flush_or_remove_pages(
|
||||
/*==========================*/
|
||||
ulint id, /*!< in: space id */
|
||||
buf_remove_t buf_remove, /*!< in: remove or flush strategy */
|
||||
const trx_t* trx); /*!< to check if the operation must
|
||||
be interrupted */
|
||||
|
||||
#if defined UNIV_DEBUG || defined UNIV_BUF_DEBUG
|
||||
/********************************************************************//**
|
||||
Insert a compressed block into buf_pool->zip_clean in the LRU order. */
|
||||
UNIV_INTERN
|
||||
void
|
||||
buf_LRU_insert_zip_clean(
|
||||
/*=====================*/
|
||||
buf_page_t* bpage); /*!< in: pointer to the block in question */
|
||||
#endif /* UNIV_DEBUG || UNIV_BUF_DEBUG */
|
||||
|
||||
/******************************************************************//**
|
||||
Try to free a block. If bpage is a descriptor of a compressed-only
|
||||
page, the descriptor object will be freed as well.
|
||||
|
||||
NOTE: If this function returns true, it will temporarily
|
||||
release buf_pool->mutex. Furthermore, the page frame will no longer be
|
||||
accessible via bpage.
|
||||
|
||||
The caller must hold buf_pool->mutex and must not hold any
|
||||
buf_page_get_mutex() when calling this function.
|
||||
@return true if freed, false otherwise. */
|
||||
UNIV_INTERN
|
||||
bool
|
||||
buf_LRU_free_page(
|
||||
/*==============*/
|
||||
buf_page_t* bpage, /*!< in: block to be freed */
|
||||
bool zip) /*!< in: true if should remove also the
|
||||
compressed page of an uncompressed page */
|
||||
__attribute__((nonnull));
|
||||
/******************************************************************//**
|
||||
Try to free a replaceable block.
|
||||
@return TRUE if found and freed */
|
||||
UNIV_INTERN
|
||||
ibool
|
||||
buf_LRU_scan_and_free_block(
|
||||
/*========================*/
|
||||
buf_pool_t* buf_pool, /*!< in: buffer pool instance */
|
||||
ibool scan_all) /*!< in: scan whole LRU list
|
||||
if TRUE, otherwise scan only
|
||||
'old' blocks. */
|
||||
__attribute__((nonnull,warn_unused_result));
|
||||
/******************************************************************//**
|
||||
Returns a free block from the buf_pool. The block is taken off the
|
||||
free list. If it is empty, returns NULL.
|
||||
@return a free control block, or NULL if the buf_block->free list is empty */
|
||||
UNIV_INTERN
|
||||
buf_block_t*
|
||||
buf_LRU_get_free_only(
|
||||
/*==================*/
|
||||
buf_pool_t* buf_pool); /*!< buffer pool instance */
|
||||
/******************************************************************//**
|
||||
Returns a free block from the buf_pool. The block is taken off the
|
||||
free list. If it is empty, blocks are moved from the end of the
|
||||
LRU list to the free list.
|
||||
This function is called from a user thread when it needs a clean
|
||||
block to read in a page. Note that we only ever get a block from
|
||||
the free list. Even when we flush a page or find a page in LRU scan
|
||||
we put it to free list to be used.
|
||||
* iteration 0:
|
||||
* get a block from free list, success:done
|
||||
* if there is an LRU flush batch in progress:
|
||||
* wait for batch to end: retry free list
|
||||
* if buf_pool->try_LRU_scan is set
|
||||
* scan LRU up to srv_LRU_scan_depth to find a clean block
|
||||
* the above will put the block on free list
|
||||
* success:retry the free list
|
||||
* flush one dirty page from tail of LRU to disk
|
||||
* the above will put the block on free list
|
||||
* success: retry the free list
|
||||
* iteration 1:
|
||||
* same as iteration 0 except:
|
||||
* scan whole LRU list
|
||||
* scan LRU list even if buf_pool->try_LRU_scan is not set
|
||||
* iteration > 1:
|
||||
* same as iteration 1 but sleep 100ms
|
||||
@return the free control block, in state BUF_BLOCK_READY_FOR_USE */
|
||||
UNIV_INTERN
|
||||
buf_block_t*
|
||||
buf_LRU_get_free_block(
|
||||
/*===================*/
|
||||
buf_pool_t* buf_pool) /*!< in/out: buffer pool instance */
|
||||
__attribute__((nonnull,warn_unused_result));
|
||||
/******************************************************************//**
|
||||
Determines if the unzip_LRU list should be used for evicting a victim
|
||||
instead of the general LRU list.
|
||||
@return TRUE if should use unzip_LRU */
|
||||
UNIV_INTERN
|
||||
ibool
|
||||
buf_LRU_evict_from_unzip_LRU(
|
||||
/*=========================*/
|
||||
buf_pool_t* buf_pool);
|
||||
/******************************************************************//**
|
||||
Puts a block back to the free list. */
|
||||
UNIV_INTERN
|
||||
void
|
||||
buf_LRU_block_free_non_file_page(
|
||||
/*=============================*/
|
||||
buf_block_t* block); /*!< in: block, must not contain a file page */
|
||||
/******************************************************************//**
|
||||
Adds a block to the LRU list. Please make sure that the zip_size is
|
||||
already set into the page zip when invoking the function, so that we
|
||||
can get correct zip_size from the buffer page when adding a block
|
||||
into LRU */
|
||||
UNIV_INTERN
|
||||
void
|
||||
buf_LRU_add_block(
|
||||
/*==============*/
|
||||
buf_page_t* bpage, /*!< in: control block */
|
||||
ibool old); /*!< in: TRUE if should be put to the old
|
||||
blocks in the LRU list, else put to the
|
||||
start; if the LRU list is very short, added to
|
||||
the start regardless of this parameter */
|
||||
/******************************************************************//**
|
||||
Adds a block to the LRU list of decompressed zip pages. */
|
||||
UNIV_INTERN
|
||||
void
|
||||
buf_unzip_LRU_add_block(
|
||||
/*====================*/
|
||||
buf_block_t* block, /*!< in: control block */
|
||||
ibool old); /*!< in: TRUE if should be put to the end
|
||||
of the list, else put to the start */
|
||||
/******************************************************************//**
|
||||
Moves a block to the start of the LRU list. */
|
||||
UNIV_INTERN
|
||||
void
|
||||
buf_LRU_make_block_young(
|
||||
/*=====================*/
|
||||
buf_page_t* bpage); /*!< in: control block */
|
||||
/******************************************************************//**
|
||||
Moves a block to the end of the LRU list. */
|
||||
UNIV_INTERN
|
||||
void
|
||||
buf_LRU_make_block_old(
|
||||
/*===================*/
|
||||
buf_page_t* bpage); /*!< in: control block */
|
||||
/**********************************************************************//**
|
||||
Updates buf_pool->LRU_old_ratio.
|
||||
@return updated old_pct */
|
||||
UNIV_INTERN
|
||||
ulint
|
||||
buf_LRU_old_ratio_update(
|
||||
/*=====================*/
|
||||
uint old_pct,/*!< in: Reserve this percentage of
|
||||
the buffer pool for "old" blocks. */
|
||||
ibool adjust);/*!< in: TRUE=adjust the LRU list;
|
||||
FALSE=just assign buf_pool->LRU_old_ratio
|
||||
during the initialization of InnoDB */
|
||||
/********************************************************************//**
|
||||
Update the historical stats that we are collecting for LRU eviction
|
||||
policy at the end of each interval. */
|
||||
UNIV_INTERN
|
||||
void
|
||||
buf_LRU_stat_update(void);
|
||||
/*=====================*/
|
||||
|
||||
/******************************************************************//**
|
||||
Remove one page from LRU list and put it to free list */
|
||||
UNIV_INTERN
|
||||
void
|
||||
buf_LRU_free_one_page(
|
||||
/*==================*/
|
||||
buf_page_t* bpage) /*!< in/out: block, must contain a file page and
|
||||
be in a state where it can be freed; there
|
||||
may or may not be a hash index to the page */
|
||||
__attribute__((nonnull));
|
||||
|
||||
#if defined UNIV_DEBUG || defined UNIV_BUF_DEBUG
|
||||
/**********************************************************************//**
|
||||
Validates the LRU list.
|
||||
@return TRUE */
|
||||
UNIV_INTERN
|
||||
ibool
|
||||
buf_LRU_validate(void);
|
||||
/*==================*/
|
||||
#endif /* UNIV_DEBUG || UNIV_BUF_DEBUG */
|
||||
#if defined UNIV_DEBUG_PRINT || defined UNIV_DEBUG || defined UNIV_BUF_DEBUG
|
||||
/**********************************************************************//**
|
||||
Prints the LRU list. */
|
||||
UNIV_INTERN
|
||||
void
|
||||
buf_LRU_print(void);
|
||||
/*===============*/
|
||||
#endif /* UNIV_DEBUG_PRINT || UNIV_DEBUG || UNIV_BUF_DEBUG */
|
||||
|
||||
/** @name Heuristics for detecting index scan @{ */
|
||||
/** The denominator of buf_pool->LRU_old_ratio. */
|
||||
#define BUF_LRU_OLD_RATIO_DIV 1024
|
||||
/** Maximum value of buf_pool->LRU_old_ratio.
|
||||
@see buf_LRU_old_adjust_len
|
||||
@see buf_pool->LRU_old_ratio_update */
|
||||
#define BUF_LRU_OLD_RATIO_MAX BUF_LRU_OLD_RATIO_DIV
|
||||
/** Minimum value of buf_pool->LRU_old_ratio.
|
||||
@see buf_LRU_old_adjust_len
|
||||
@see buf_pool->LRU_old_ratio_update
|
||||
The minimum must exceed
|
||||
(BUF_LRU_OLD_TOLERANCE + 5) * BUF_LRU_OLD_RATIO_DIV / BUF_LRU_OLD_MIN_LEN. */
|
||||
#define BUF_LRU_OLD_RATIO_MIN 51
|
||||
|
||||
#if BUF_LRU_OLD_RATIO_MIN >= BUF_LRU_OLD_RATIO_MAX
|
||||
# error "BUF_LRU_OLD_RATIO_MIN >= BUF_LRU_OLD_RATIO_MAX"
|
||||
#endif
|
||||
#if BUF_LRU_OLD_RATIO_MAX > BUF_LRU_OLD_RATIO_DIV
|
||||
# error "BUF_LRU_OLD_RATIO_MAX > BUF_LRU_OLD_RATIO_DIV"
|
||||
#endif
|
||||
|
||||
/** Move blocks to "new" LRU list only if the first access was at
|
||||
least this many milliseconds ago. Not protected by any mutex or latch. */
|
||||
extern uint buf_LRU_old_threshold_ms;
|
||||
/* @} */
|
||||
|
||||
/** @brief Statistics for selecting the LRU list for eviction.
|
||||
|
||||
These statistics are not 'of' LRU but 'for' LRU. We keep count of I/O
|
||||
and page_zip_decompress() operations. Based on the statistics we decide
|
||||
if we want to evict from buf_pool->unzip_LRU or buf_pool->LRU. */
|
||||
struct buf_LRU_stat_t
|
||||
{
|
||||
ulint io; /**< Counter of buffer pool I/O operations. */
|
||||
ulint unzip; /**< Counter of page_zip_decompress operations. */
|
||||
};
|
||||
|
||||
/** Current operation counters. Not protected by any mutex.
|
||||
Cleared by buf_LRU_stat_update(). */
|
||||
extern buf_LRU_stat_t buf_LRU_stat_cur;
|
||||
|
||||
/** Running sum of past values of buf_LRU_stat_cur.
|
||||
Updated by buf_LRU_stat_update(). Protected by buf_pool->mutex. */
|
||||
extern buf_LRU_stat_t buf_LRU_stat_sum;
|
||||
|
||||
/********************************************************************//**
|
||||
Increments the I/O counter in buf_LRU_stat_cur. */
|
||||
#define buf_LRU_stat_inc_io() buf_LRU_stat_cur.io++
|
||||
/********************************************************************//**
|
||||
Increments the page_zip_decompress() counter in buf_LRU_stat_cur. */
|
||||
#define buf_LRU_stat_inc_unzip() buf_LRU_stat_cur.unzip++
|
||||
|
||||
#ifndef UNIV_NONINL
|
||||
#include "buf0lru.ic"
|
||||
#endif
|
||||
|
||||
#endif /* !UNIV_HOTBACKUP */
|
||||
|
||||
#endif
|
||||
25
storage/innobase/include/buf0lru.ic
Normal file
25
storage/innobase/include/buf0lru.ic
Normal file
|
|
@ -0,0 +1,25 @@
|
|||
/*****************************************************************************
|
||||
|
||||
Copyright (c) 1995, 2009, Oracle and/or its affiliates. All Rights Reserved.
|
||||
|
||||
This program is free software; you can redistribute it and/or modify it under
|
||||
the terms of the GNU General Public License as published by the Free Software
|
||||
Foundation; version 2 of the License.
|
||||
|
||||
This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
|
||||
FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License along with
|
||||
this program; if not, write to the Free Software Foundation, Inc.,
|
||||
51 Franklin Street, Suite 500, Boston, MA 02110-1335 USA
|
||||
|
||||
*****************************************************************************/
|
||||
|
||||
/**************************************************//**
|
||||
@file include/buf0lru.ic
|
||||
The database buffer replacement algorithm
|
||||
|
||||
Created 11/5/1995 Heikki Tuuri
|
||||
*******************************************************/
|
||||
|
||||
177
storage/innobase/include/buf0rea.h
Normal file
177
storage/innobase/include/buf0rea.h
Normal file
|
|
@ -0,0 +1,177 @@
|
|||
/*****************************************************************************
|
||||
|
||||
Copyright (c) 1995, 2013, Oracle and/or its affiliates. All Rights Reserved.
|
||||
|
||||
This program is free software; you can redistribute it and/or modify it under
|
||||
the terms of the GNU General Public License as published by the Free Software
|
||||
Foundation; version 2 of the License.
|
||||
|
||||
This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
|
||||
FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License along with
|
||||
this program; if not, write to the Free Software Foundation, Inc.,
|
||||
51 Franklin Street, Suite 500, Boston, MA 02110-1335 USA
|
||||
|
||||
*****************************************************************************/
|
||||
|
||||
/**************************************************//**
|
||||
@file include/buf0rea.h
|
||||
The database buffer read
|
||||
|
||||
Created 11/5/1995 Heikki Tuuri
|
||||
*******************************************************/
|
||||
|
||||
#ifndef buf0rea_h
|
||||
#define buf0rea_h
|
||||
|
||||
#include "univ.i"
|
||||
#include "buf0types.h"
|
||||
|
||||
/********************************************************************//**
|
||||
High-level function which reads a page asynchronously from a file to the
|
||||
buffer buf_pool if it is not already there. Sets the io_fix flag and sets
|
||||
an exclusive lock on the buffer frame. The flag is cleared and the x-lock
|
||||
released by the i/o-handler thread.
|
||||
@return TRUE if page has been read in, FALSE in case of failure */
|
||||
UNIV_INTERN
|
||||
ibool
|
||||
buf_read_page(
|
||||
/*==========*/
|
||||
ulint space, /*!< in: space id */
|
||||
ulint zip_size,/*!< in: compressed page size in bytes, or 0 */
|
||||
ulint offset);/*!< in: page number */
|
||||
/********************************************************************//**
|
||||
High-level function which reads a page asynchronously from a file to the
|
||||
buffer buf_pool if it is not already there. Sets the io_fix flag and sets
|
||||
an exclusive lock on the buffer frame. The flag is cleared and the x-lock
|
||||
released by the i/o-handler thread.
|
||||
@return TRUE if page has been read in, FALSE in case of failure */
|
||||
UNIV_INTERN
|
||||
ibool
|
||||
buf_read_page_async(
|
||||
/*================*/
|
||||
ulint space, /*!< in: space id */
|
||||
ulint offset);/*!< in: page number */
|
||||
/********************************************************************//**
|
||||
Applies a random read-ahead in buf_pool if there are at least a threshold
|
||||
value of accessed pages from the random read-ahead area. Does not read any
|
||||
page, not even the one at the position (space, offset), if the read-ahead
|
||||
mechanism is not activated. NOTE 1: the calling thread may own latches on
|
||||
pages: to avoid deadlocks this function must be written such that it cannot
|
||||
end up waiting for these latches! NOTE 2: the calling thread must want
|
||||
access to the page given: this rule is set to prevent unintended read-aheads
|
||||
performed by ibuf routines, a situation which could result in a deadlock if
|
||||
the OS does not support asynchronous i/o.
|
||||
@return number of page read requests issued; NOTE that if we read ibuf
|
||||
pages, it may happen that the page at the given page number does not
|
||||
get read even if we return a positive value!
|
||||
@return number of page read requests issued */
|
||||
UNIV_INTERN
|
||||
ulint
|
||||
buf_read_ahead_random(
|
||||
/*==================*/
|
||||
ulint space, /*!< in: space id */
|
||||
ulint zip_size, /*!< in: compressed page size in bytes,
|
||||
or 0 */
|
||||
ulint offset, /*!< in: page number of a page which
|
||||
the current thread wants to access */
|
||||
ibool inside_ibuf); /*!< in: TRUE if we are inside ibuf
|
||||
routine */
|
||||
/********************************************************************//**
|
||||
Applies linear read-ahead if in the buf_pool the page is a border page of
|
||||
a linear read-ahead area and all the pages in the area have been accessed.
|
||||
Does not read any page if the read-ahead mechanism is not activated. Note
|
||||
that the algorithm looks at the 'natural' adjacent successor and
|
||||
predecessor of the page, which on the leaf level of a B-tree are the next
|
||||
and previous page in the chain of leaves. To know these, the page specified
|
||||
in (space, offset) must already be present in the buf_pool. Thus, the
|
||||
natural way to use this function is to call it when a page in the buf_pool
|
||||
is accessed the first time, calling this function just after it has been
|
||||
bufferfixed.
|
||||
NOTE 1: as this function looks at the natural predecessor and successor
|
||||
fields on the page, what happens, if these are not initialized to any
|
||||
sensible value? No problem, before applying read-ahead we check that the
|
||||
area to read is within the span of the space, if not, read-ahead is not
|
||||
applied. An uninitialized value may result in a useless read operation, but
|
||||
only very improbably.
|
||||
NOTE 2: the calling thread may own latches on pages: to avoid deadlocks this
|
||||
function must be written such that it cannot end up waiting for these
|
||||
latches!
|
||||
NOTE 3: the calling thread must want access to the page given: this rule is
|
||||
set to prevent unintended read-aheads performed by ibuf routines, a situation
|
||||
which could result in a deadlock if the OS does not support asynchronous io.
|
||||
@return number of page read requests issued */
|
||||
UNIV_INTERN
|
||||
ulint
|
||||
buf_read_ahead_linear(
|
||||
/*==================*/
|
||||
ulint space, /*!< in: space id */
|
||||
ulint zip_size, /*!< in: compressed page size in bytes, or 0 */
|
||||
ulint offset, /*!< in: page number; see NOTE 3 above */
|
||||
ibool inside_ibuf); /*!< in: TRUE if we are inside ibuf routine */
|
||||
/********************************************************************//**
|
||||
Issues read requests for pages which the ibuf module wants to read in, in
|
||||
order to contract the insert buffer tree. Technically, this function is like
|
||||
a read-ahead function. */
|
||||
UNIV_INTERN
|
||||
void
|
||||
buf_read_ibuf_merge_pages(
|
||||
/*======================*/
|
||||
bool sync, /*!< in: true if the caller
|
||||
wants this function to wait
|
||||
for the highest address page
|
||||
to get read in, before this
|
||||
function returns */
|
||||
const ulint* space_ids, /*!< in: array of space ids */
|
||||
const ib_int64_t* space_versions,/*!< in: the spaces must have
|
||||
this version number
|
||||
(timestamp), otherwise we
|
||||
discard the read; we use this
|
||||
to cancel reads if DISCARD +
|
||||
IMPORT may have changed the
|
||||
tablespace size */
|
||||
const ulint* page_nos, /*!< in: array of page numbers
|
||||
to read, with the highest page
|
||||
number the last in the
|
||||
array */
|
||||
ulint n_stored); /*!< in: number of elements
|
||||
in the arrays */
|
||||
/********************************************************************//**
|
||||
Issues read requests for pages which recovery wants to read in. */
|
||||
UNIV_INTERN
|
||||
void
|
||||
buf_read_recv_pages(
|
||||
/*================*/
|
||||
ibool sync, /*!< in: TRUE if the caller
|
||||
wants this function to wait
|
||||
for the highest address page
|
||||
to get read in, before this
|
||||
function returns */
|
||||
ulint space, /*!< in: space id */
|
||||
ulint zip_size, /*!< in: compressed page size in
|
||||
bytes, or 0 */
|
||||
const ulint* page_nos, /*!< in: array of page numbers
|
||||
to read, with the highest page
|
||||
number the last in the
|
||||
array */
|
||||
ulint n_stored); /*!< in: number of page numbers
|
||||
in the array */
|
||||
|
||||
/** The size in pages of the area which the read-ahead algorithms read if
|
||||
invoked */
|
||||
#define BUF_READ_AHEAD_AREA(b) \
|
||||
ut_min(64, ut_2_power_up((b)->curr_size / 32))
|
||||
|
||||
/** @name Modes used in read-ahead @{ */
|
||||
/** read only pages belonging to the insert buffer tree */
|
||||
#define BUF_READ_IBUF_PAGES_ONLY 131
|
||||
/** read any page */
|
||||
#define BUF_READ_ANY_PAGE 132
|
||||
/** read any page, but ignore (return an error) if a page does not exist
|
||||
instead of crashing like BUF_READ_ANY_PAGE does */
|
||||
#define BUF_READ_IGNORE_NONEXISTENT_PAGES 1024
|
||||
/* @} */
|
||||
|
||||
#endif
|
||||
120
storage/innobase/include/buf0types.h
Normal file
120
storage/innobase/include/buf0types.h
Normal file
|
|
@ -0,0 +1,120 @@
|
|||
/*****************************************************************************
|
||||
|
||||
Copyright (c) 1995, 2013, Oracle and/or its affiliates. All Rights Reserved
|
||||
|
||||
This program is free software; you can redistribute it and/or modify it under
|
||||
the terms of the GNU General Public License as published by the Free Software
|
||||
Foundation; version 2 of the License.
|
||||
|
||||
This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
|
||||
FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License along with
|
||||
this program; if not, write to the Free Software Foundation, Inc.,
|
||||
51 Franklin Street, Suite 500, Boston, MA 02110-1335 USA
|
||||
|
||||
*****************************************************************************/
|
||||
|
||||
/**************************************************//**
|
||||
@file include/buf0types.h
|
||||
The database buffer pool global types for the directory
|
||||
|
||||
Created 11/17/1995 Heikki Tuuri
|
||||
*******************************************************/
|
||||
|
||||
#ifndef buf0types_h
|
||||
#define buf0types_h
|
||||
|
||||
#if defined(INNODB_PAGE_ATOMIC_REF_COUNT) && defined(HAVE_ATOMIC_BUILTINS)
|
||||
#define PAGE_ATOMIC_REF_COUNT
|
||||
#endif /* INNODB_PAGE_ATOMIC_REF_COUNT && HAVE_ATOMIC_BUILTINS */
|
||||
|
||||
/** Buffer page (uncompressed or compressed) */
|
||||
struct buf_page_t;
|
||||
/** Buffer block for which an uncompressed page exists */
|
||||
struct buf_block_t;
|
||||
/** Buffer pool chunk comprising buf_block_t */
|
||||
struct buf_chunk_t;
|
||||
/** Buffer pool comprising buf_chunk_t */
|
||||
struct buf_pool_t;
|
||||
/** Buffer pool statistics struct */
|
||||
struct buf_pool_stat_t;
|
||||
/** Buffer pool buddy statistics struct */
|
||||
struct buf_buddy_stat_t;
|
||||
/** Doublewrite memory struct */
|
||||
struct buf_dblwr_t;
|
||||
|
||||
/** A buffer frame. @see page_t */
|
||||
typedef byte buf_frame_t;
|
||||
|
||||
/** Flags for flush types */
|
||||
enum buf_flush_t {
|
||||
BUF_FLUSH_LRU = 0, /*!< flush via the LRU list */
|
||||
BUF_FLUSH_LIST, /*!< flush via the flush list
|
||||
of dirty blocks */
|
||||
BUF_FLUSH_SINGLE_PAGE, /*!< flush via the LRU list
|
||||
but only a single page */
|
||||
BUF_FLUSH_N_TYPES /*!< index of last element + 1 */
|
||||
};
|
||||
|
||||
/** Algorithm to remove the pages for a tablespace from the buffer pool.
|
||||
See buf_LRU_flush_or_remove_pages(). */
|
||||
enum buf_remove_t {
|
||||
BUF_REMOVE_ALL_NO_WRITE, /*!< Remove all pages from the buffer
|
||||
pool, don't write or sync to disk */
|
||||
BUF_REMOVE_FLUSH_NO_WRITE, /*!< Remove only, from the flush list,
|
||||
don't write or sync to disk */
|
||||
BUF_REMOVE_FLUSH_WRITE /*!< Flush dirty pages to disk only
|
||||
don't remove from the buffer pool */
|
||||
};
|
||||
|
||||
/** Flags for io_fix types */
|
||||
enum buf_io_fix {
|
||||
BUF_IO_NONE = 0, /**< no pending I/O */
|
||||
BUF_IO_READ, /**< read pending */
|
||||
BUF_IO_WRITE, /**< write pending */
|
||||
BUF_IO_PIN /**< disallow relocation of
|
||||
block and its removal of from
|
||||
the flush_list */
|
||||
};
|
||||
|
||||
/** Alternatives for srv_checksum_algorithm, which can be changed by
|
||||
setting innodb_checksum_algorithm */
|
||||
enum srv_checksum_algorithm_t {
|
||||
SRV_CHECKSUM_ALGORITHM_CRC32, /*!< Write crc32, allow crc32,
|
||||
innodb or none when reading */
|
||||
SRV_CHECKSUM_ALGORITHM_STRICT_CRC32, /*!< Write crc32, allow crc32
|
||||
when reading */
|
||||
SRV_CHECKSUM_ALGORITHM_INNODB, /*!< Write innodb, allow crc32,
|
||||
innodb or none when reading */
|
||||
SRV_CHECKSUM_ALGORITHM_STRICT_INNODB, /*!< Write innodb, allow
|
||||
innodb when reading */
|
||||
SRV_CHECKSUM_ALGORITHM_NONE, /*!< Write none, allow crc32,
|
||||
innodb or none when reading */
|
||||
SRV_CHECKSUM_ALGORITHM_STRICT_NONE /*!< Write none, allow none
|
||||
when reading */
|
||||
};
|
||||
|
||||
/** Parameters of binary buddy system for compressed pages (buf0buddy.h) */
|
||||
/* @{ */
|
||||
/** Zip shift value for the smallest page size */
|
||||
#define BUF_BUDDY_LOW_SHIFT UNIV_ZIP_SIZE_SHIFT_MIN
|
||||
|
||||
/** Smallest buddy page size */
|
||||
#define BUF_BUDDY_LOW (1U << BUF_BUDDY_LOW_SHIFT)
|
||||
|
||||
/** Actual number of buddy sizes based on current page size */
|
||||
#define BUF_BUDDY_SIZES (UNIV_PAGE_SIZE_SHIFT - BUF_BUDDY_LOW_SHIFT)
|
||||
|
||||
/** Maximum number of buddy sizes based on the max page size */
|
||||
#define BUF_BUDDY_SIZES_MAX (UNIV_PAGE_SIZE_SHIFT_MAX \
|
||||
- BUF_BUDDY_LOW_SHIFT)
|
||||
|
||||
/** twice the maximum block size of the buddy system;
|
||||
the underlying memory is aligned by this amount:
|
||||
this must be equal to UNIV_PAGE_SIZE */
|
||||
#define BUF_BUDDY_HIGH (BUF_BUDDY_LOW << BUF_BUDDY_SIZES)
|
||||
/* @} */
|
||||
|
||||
#endif /* buf0types.h */
|
||||
536
storage/innobase/include/data0data.h
Normal file
536
storage/innobase/include/data0data.h
Normal file
|
|
@ -0,0 +1,536 @@
|
|||
/*****************************************************************************
|
||||
|
||||
Copyright (c) 1994, 2012, Oracle and/or its affiliates. All Rights Reserved.
|
||||
|
||||
This program is free software; you can redistribute it and/or modify it under
|
||||
the terms of the GNU General Public License as published by the Free Software
|
||||
Foundation; version 2 of the License.
|
||||
|
||||
This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
|
||||
FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License along with
|
||||
this program; if not, write to the Free Software Foundation, Inc.,
|
||||
51 Franklin Street, Suite 500, Boston, MA 02110-1335 USA
|
||||
|
||||
*****************************************************************************/
|
||||
|
||||
/********************************************************************//**
|
||||
@file include/data0data.h
|
||||
SQL data field and tuple
|
||||
|
||||
Created 5/30/1994 Heikki Tuuri
|
||||
*************************************************************************/
|
||||
|
||||
#ifndef data0data_h
|
||||
#define data0data_h
|
||||
|
||||
#include "univ.i"
|
||||
|
||||
#include "data0types.h"
|
||||
#include "data0type.h"
|
||||
#include "mem0mem.h"
|
||||
#include "dict0types.h"
|
||||
|
||||
/** Storage for overflow data in a big record, that is, a clustered
|
||||
index record which needs external storage of data fields */
|
||||
struct big_rec_t;
|
||||
|
||||
#ifdef UNIV_DEBUG
|
||||
/*********************************************************************//**
|
||||
Gets pointer to the type struct of SQL data field.
|
||||
@return pointer to the type struct */
|
||||
UNIV_INLINE
|
||||
dtype_t*
|
||||
dfield_get_type(
|
||||
/*============*/
|
||||
const dfield_t* field) /*!< in: SQL data field */
|
||||
__attribute__((nonnull, warn_unused_result));
|
||||
/*********************************************************************//**
|
||||
Gets pointer to the data in a field.
|
||||
@return pointer to data */
|
||||
UNIV_INLINE
|
||||
void*
|
||||
dfield_get_data(
|
||||
/*============*/
|
||||
const dfield_t* field) /*!< in: field */
|
||||
__attribute__((nonnull, warn_unused_result));
|
||||
#else /* UNIV_DEBUG */
|
||||
# define dfield_get_type(field) (&(field)->type)
|
||||
# define dfield_get_data(field) ((field)->data)
|
||||
#endif /* UNIV_DEBUG */
|
||||
/*********************************************************************//**
|
||||
Sets the type struct of SQL data field. */
|
||||
UNIV_INLINE
|
||||
void
|
||||
dfield_set_type(
|
||||
/*============*/
|
||||
dfield_t* field, /*!< in: SQL data field */
|
||||
const dtype_t* type) /*!< in: pointer to data type struct */
|
||||
__attribute__((nonnull));
|
||||
/*********************************************************************//**
|
||||
Gets length of field data.
|
||||
@return length of data; UNIV_SQL_NULL if SQL null data */
|
||||
UNIV_INLINE
|
||||
ulint
|
||||
dfield_get_len(
|
||||
/*===========*/
|
||||
const dfield_t* field) /*!< in: field */
|
||||
__attribute__((nonnull, warn_unused_result));
|
||||
/*********************************************************************//**
|
||||
Sets length in a field. */
|
||||
UNIV_INLINE
|
||||
void
|
||||
dfield_set_len(
|
||||
/*===========*/
|
||||
dfield_t* field, /*!< in: field */
|
||||
ulint len) /*!< in: length or UNIV_SQL_NULL */
|
||||
__attribute__((nonnull));
|
||||
/*********************************************************************//**
|
||||
Determines if a field is SQL NULL
|
||||
@return nonzero if SQL null data */
|
||||
UNIV_INLINE
|
||||
ulint
|
||||
dfield_is_null(
|
||||
/*===========*/
|
||||
const dfield_t* field) /*!< in: field */
|
||||
__attribute__((nonnull, warn_unused_result));
|
||||
/*********************************************************************//**
|
||||
Determines if a field is externally stored
|
||||
@return nonzero if externally stored */
|
||||
UNIV_INLINE
|
||||
ulint
|
||||
dfield_is_ext(
|
||||
/*==========*/
|
||||
const dfield_t* field) /*!< in: field */
|
||||
__attribute__((nonnull, warn_unused_result));
|
||||
/*********************************************************************//**
|
||||
Sets the "external storage" flag */
|
||||
UNIV_INLINE
|
||||
void
|
||||
dfield_set_ext(
|
||||
/*===========*/
|
||||
dfield_t* field) /*!< in/out: field */
|
||||
__attribute__((nonnull));
|
||||
/*********************************************************************//**
|
||||
Sets pointer to the data and length in a field. */
|
||||
UNIV_INLINE
|
||||
void
|
||||
dfield_set_data(
|
||||
/*============*/
|
||||
dfield_t* field, /*!< in: field */
|
||||
const void* data, /*!< in: data */
|
||||
ulint len) /*!< in: length or UNIV_SQL_NULL */
|
||||
__attribute__((nonnull(1)));
|
||||
/*********************************************************************//**
|
||||
Sets a data field to SQL NULL. */
|
||||
UNIV_INLINE
|
||||
void
|
||||
dfield_set_null(
|
||||
/*============*/
|
||||
dfield_t* field) /*!< in/out: field */
|
||||
__attribute__((nonnull));
|
||||
/**********************************************************************//**
|
||||
Writes an SQL null field full of zeros. */
|
||||
UNIV_INLINE
|
||||
void
|
||||
data_write_sql_null(
|
||||
/*================*/
|
||||
byte* data, /*!< in: pointer to a buffer of size len */
|
||||
ulint len) /*!< in: SQL null size in bytes */
|
||||
__attribute__((nonnull));
|
||||
/*********************************************************************//**
|
||||
Copies the data and len fields. */
|
||||
UNIV_INLINE
|
||||
void
|
||||
dfield_copy_data(
|
||||
/*=============*/
|
||||
dfield_t* field1, /*!< out: field to copy to */
|
||||
const dfield_t* field2) /*!< in: field to copy from */
|
||||
__attribute__((nonnull));
|
||||
/*********************************************************************//**
|
||||
Copies a data field to another. */
|
||||
UNIV_INLINE
|
||||
void
|
||||
dfield_copy(
|
||||
/*========*/
|
||||
dfield_t* field1, /*!< out: field to copy to */
|
||||
const dfield_t* field2) /*!< in: field to copy from */
|
||||
__attribute__((nonnull));
|
||||
/*********************************************************************//**
|
||||
Copies the data pointed to by a data field. */
|
||||
UNIV_INLINE
|
||||
void
|
||||
dfield_dup(
|
||||
/*=======*/
|
||||
dfield_t* field, /*!< in/out: data field */
|
||||
mem_heap_t* heap) /*!< in: memory heap where allocated */
|
||||
__attribute__((nonnull));
|
||||
#ifndef UNIV_HOTBACKUP
|
||||
/*********************************************************************//**
|
||||
Tests if two data fields are equal.
|
||||
If len==0, tests the data length and content for equality.
|
||||
If len>0, tests the first len bytes of the content for equality.
|
||||
@return TRUE if both fields are NULL or if they are equal */
|
||||
UNIV_INLINE
|
||||
ibool
|
||||
dfield_datas_are_binary_equal(
|
||||
/*==========================*/
|
||||
const dfield_t* field1, /*!< in: field */
|
||||
const dfield_t* field2, /*!< in: field */
|
||||
ulint len) /*!< in: maximum prefix to compare,
|
||||
or 0 to compare the whole field length */
|
||||
__attribute__((nonnull, warn_unused_result));
|
||||
/*********************************************************************//**
|
||||
Tests if dfield data length and content is equal to the given.
|
||||
@return TRUE if equal */
|
||||
UNIV_INLINE
|
||||
ibool
|
||||
dfield_data_is_binary_equal(
|
||||
/*========================*/
|
||||
const dfield_t* field, /*!< in: field */
|
||||
ulint len, /*!< in: data length or UNIV_SQL_NULL */
|
||||
const byte* data) /*!< in: data */
|
||||
__attribute__((nonnull, warn_unused_result));
|
||||
#endif /* !UNIV_HOTBACKUP */
|
||||
/*********************************************************************//**
|
||||
Gets number of fields in a data tuple.
|
||||
@return number of fields */
|
||||
UNIV_INLINE
|
||||
ulint
|
||||
dtuple_get_n_fields(
|
||||
/*================*/
|
||||
const dtuple_t* tuple) /*!< in: tuple */
|
||||
__attribute__((nonnull, warn_unused_result));
|
||||
#ifdef UNIV_DEBUG
|
||||
/*********************************************************************//**
|
||||
Gets nth field of a tuple.
|
||||
@return nth field */
|
||||
UNIV_INLINE
|
||||
dfield_t*
|
||||
dtuple_get_nth_field(
|
||||
/*=================*/
|
||||
const dtuple_t* tuple, /*!< in: tuple */
|
||||
ulint n); /*!< in: index of field */
|
||||
#else /* UNIV_DEBUG */
|
||||
# define dtuple_get_nth_field(tuple, n) ((tuple)->fields + (n))
|
||||
#endif /* UNIV_DEBUG */
|
||||
/*********************************************************************//**
|
||||
Gets info bits in a data tuple.
|
||||
@return info bits */
|
||||
UNIV_INLINE
|
||||
ulint
|
||||
dtuple_get_info_bits(
|
||||
/*=================*/
|
||||
const dtuple_t* tuple) /*!< in: tuple */
|
||||
__attribute__((nonnull, warn_unused_result));
|
||||
/*********************************************************************//**
|
||||
Sets info bits in a data tuple. */
|
||||
UNIV_INLINE
|
||||
void
|
||||
dtuple_set_info_bits(
|
||||
/*=================*/
|
||||
dtuple_t* tuple, /*!< in: tuple */
|
||||
ulint info_bits) /*!< in: info bits */
|
||||
__attribute__((nonnull));
|
||||
/*********************************************************************//**
|
||||
Gets number of fields used in record comparisons.
|
||||
@return number of fields used in comparisons in rem0cmp.* */
|
||||
UNIV_INLINE
|
||||
ulint
|
||||
dtuple_get_n_fields_cmp(
|
||||
/*====================*/
|
||||
const dtuple_t* tuple) /*!< in: tuple */
|
||||
__attribute__((nonnull, warn_unused_result));
|
||||
/*********************************************************************//**
|
||||
Gets number of fields used in record comparisons. */
|
||||
UNIV_INLINE
|
||||
void
|
||||
dtuple_set_n_fields_cmp(
|
||||
/*====================*/
|
||||
dtuple_t* tuple, /*!< in: tuple */
|
||||
ulint n_fields_cmp) /*!< in: number of fields used in
|
||||
comparisons in rem0cmp.* */
|
||||
__attribute__((nonnull));
|
||||
|
||||
/* Estimate the number of bytes that are going to be allocated when
|
||||
creating a new dtuple_t object */
|
||||
#define DTUPLE_EST_ALLOC(n_fields) \
|
||||
(sizeof(dtuple_t) + (n_fields) * sizeof(dfield_t))
|
||||
|
||||
/**********************************************************//**
|
||||
Creates a data tuple from an already allocated chunk of memory.
|
||||
The size of the chunk must be at least DTUPLE_EST_ALLOC(n_fields).
|
||||
The default value for number of fields used in record comparisons
|
||||
for this tuple is n_fields.
|
||||
@return created tuple (inside buf) */
|
||||
UNIV_INLINE
|
||||
dtuple_t*
|
||||
dtuple_create_from_mem(
|
||||
/*===================*/
|
||||
void* buf, /*!< in, out: buffer to use */
|
||||
ulint buf_size, /*!< in: buffer size */
|
||||
ulint n_fields) /*!< in: number of fields */
|
||||
__attribute__((nonnull, warn_unused_result));
|
||||
|
||||
/**********************************************************//**
|
||||
Creates a data tuple to a memory heap. The default value for number
|
||||
of fields used in record comparisons for this tuple is n_fields.
|
||||
@return own: created tuple */
|
||||
UNIV_INLINE
|
||||
dtuple_t*
|
||||
dtuple_create(
|
||||
/*==========*/
|
||||
mem_heap_t* heap, /*!< in: memory heap where the tuple
|
||||
is created, DTUPLE_EST_ALLOC(n_fields)
|
||||
bytes will be allocated from this heap */
|
||||
ulint n_fields)/*!< in: number of fields */
|
||||
__attribute__((nonnull, malloc));
|
||||
|
||||
/*********************************************************************//**
|
||||
Sets number of fields used in a tuple. Normally this is set in
|
||||
dtuple_create, but if you want later to set it smaller, you can use this. */
|
||||
UNIV_INTERN
|
||||
void
|
||||
dtuple_set_n_fields(
|
||||
/*================*/
|
||||
dtuple_t* tuple, /*!< in: tuple */
|
||||
ulint n_fields) /*!< in: number of fields */
|
||||
__attribute__((nonnull));
|
||||
/*********************************************************************//**
|
||||
Copies a data tuple to another. This is a shallow copy; if a deep copy
|
||||
is desired, dfield_dup() will have to be invoked on each field.
|
||||
@return own: copy of tuple */
|
||||
UNIV_INLINE
|
||||
dtuple_t*
|
||||
dtuple_copy(
|
||||
/*========*/
|
||||
const dtuple_t* tuple, /*!< in: tuple to copy from */
|
||||
mem_heap_t* heap) /*!< in: memory heap
|
||||
where the tuple is created */
|
||||
__attribute__((nonnull, malloc));
|
||||
/**********************************************************//**
|
||||
The following function returns the sum of data lengths of a tuple. The space
|
||||
occupied by the field structs or the tuple struct is not counted.
|
||||
@return sum of data lens */
|
||||
UNIV_INLINE
|
||||
ulint
|
||||
dtuple_get_data_size(
|
||||
/*=================*/
|
||||
const dtuple_t* tuple, /*!< in: typed data tuple */
|
||||
ulint comp) /*!< in: nonzero=ROW_FORMAT=COMPACT */
|
||||
__attribute__((nonnull));
|
||||
/*********************************************************************//**
|
||||
Computes the number of externally stored fields in a data tuple.
|
||||
@return number of fields */
|
||||
UNIV_INLINE
|
||||
ulint
|
||||
dtuple_get_n_ext(
|
||||
/*=============*/
|
||||
const dtuple_t* tuple) /*!< in: tuple */
|
||||
__attribute__((nonnull));
|
||||
/************************************************************//**
|
||||
Compare two data tuples, respecting the collation of character fields.
|
||||
@return 1, 0 , -1 if tuple1 is greater, equal, less, respectively,
|
||||
than tuple2 */
|
||||
UNIV_INTERN
|
||||
int
|
||||
dtuple_coll_cmp(
|
||||
/*============*/
|
||||
const dtuple_t* tuple1, /*!< in: tuple 1 */
|
||||
const dtuple_t* tuple2) /*!< in: tuple 2 */
|
||||
__attribute__((nonnull, warn_unused_result));
|
||||
/************************************************************//**
|
||||
Folds a prefix given as the number of fields of a tuple.
|
||||
@return the folded value */
|
||||
UNIV_INLINE
|
||||
ulint
|
||||
dtuple_fold(
|
||||
/*========*/
|
||||
const dtuple_t* tuple, /*!< in: the tuple */
|
||||
ulint n_fields,/*!< in: number of complete fields to fold */
|
||||
ulint n_bytes,/*!< in: number of bytes to fold in an
|
||||
incomplete last field */
|
||||
index_id_t tree_id)/*!< in: index tree id */
|
||||
__attribute__((nonnull, pure, warn_unused_result));
|
||||
/*******************************************************************//**
|
||||
Sets types of fields binary in a tuple. */
|
||||
UNIV_INLINE
|
||||
void
|
||||
dtuple_set_types_binary(
|
||||
/*====================*/
|
||||
dtuple_t* tuple, /*!< in: data tuple */
|
||||
ulint n) /*!< in: number of fields to set */
|
||||
__attribute__((nonnull));
|
||||
/**********************************************************************//**
|
||||
Checks if a dtuple contains an SQL null value.
|
||||
@return TRUE if some field is SQL null */
|
||||
UNIV_INLINE
|
||||
ibool
|
||||
dtuple_contains_null(
|
||||
/*=================*/
|
||||
const dtuple_t* tuple) /*!< in: dtuple */
|
||||
__attribute__((nonnull, warn_unused_result));
|
||||
/**********************************************************//**
|
||||
Checks that a data field is typed. Asserts an error if not.
|
||||
@return TRUE if ok */
|
||||
UNIV_INTERN
|
||||
ibool
|
||||
dfield_check_typed(
|
||||
/*===============*/
|
||||
const dfield_t* field) /*!< in: data field */
|
||||
__attribute__((nonnull, warn_unused_result));
|
||||
/**********************************************************//**
|
||||
Checks that a data tuple is typed. Asserts an error if not.
|
||||
@return TRUE if ok */
|
||||
UNIV_INTERN
|
||||
ibool
|
||||
dtuple_check_typed(
|
||||
/*===============*/
|
||||
const dtuple_t* tuple) /*!< in: tuple */
|
||||
__attribute__((nonnull, warn_unused_result));
|
||||
/**********************************************************//**
|
||||
Checks that a data tuple is typed.
|
||||
@return TRUE if ok */
|
||||
UNIV_INTERN
|
||||
ibool
|
||||
dtuple_check_typed_no_assert(
|
||||
/*=========================*/
|
||||
const dtuple_t* tuple) /*!< in: tuple */
|
||||
__attribute__((nonnull, warn_unused_result));
|
||||
#ifdef UNIV_DEBUG
|
||||
/**********************************************************//**
|
||||
Validates the consistency of a tuple which must be complete, i.e,
|
||||
all fields must have been set.
|
||||
@return TRUE if ok */
|
||||
UNIV_INTERN
|
||||
ibool
|
||||
dtuple_validate(
|
||||
/*============*/
|
||||
const dtuple_t* tuple) /*!< in: tuple */
|
||||
__attribute__((nonnull, warn_unused_result));
|
||||
#endif /* UNIV_DEBUG */
|
||||
/*************************************************************//**
|
||||
Pretty prints a dfield value according to its data type. */
|
||||
UNIV_INTERN
|
||||
void
|
||||
dfield_print(
|
||||
/*=========*/
|
||||
const dfield_t* dfield) /*!< in: dfield */
|
||||
__attribute__((nonnull));
|
||||
/*************************************************************//**
|
||||
Pretty prints a dfield value according to its data type. Also the hex string
|
||||
is printed if a string contains non-printable characters. */
|
||||
UNIV_INTERN
|
||||
void
|
||||
dfield_print_also_hex(
|
||||
/*==================*/
|
||||
const dfield_t* dfield) /*!< in: dfield */
|
||||
__attribute__((nonnull));
|
||||
/**********************************************************//**
|
||||
The following function prints the contents of a tuple. */
|
||||
UNIV_INTERN
|
||||
void
|
||||
dtuple_print(
|
||||
/*=========*/
|
||||
FILE* f, /*!< in: output stream */
|
||||
const dtuple_t* tuple) /*!< in: tuple */
|
||||
__attribute__((nonnull));
|
||||
/**************************************************************//**
|
||||
Moves parts of long fields in entry to the big record vector so that
|
||||
the size of tuple drops below the maximum record size allowed in the
|
||||
database. Moves data only from those fields which are not necessary
|
||||
to determine uniquely the insertion place of the tuple in the index.
|
||||
@return own: created big record vector, NULL if we are not able to
|
||||
shorten the entry enough, i.e., if there are too many fixed-length or
|
||||
short fields in entry or the index is clustered */
|
||||
UNIV_INTERN
|
||||
big_rec_t*
|
||||
dtuple_convert_big_rec(
|
||||
/*===================*/
|
||||
dict_index_t* index, /*!< in: index */
|
||||
dtuple_t* entry, /*!< in/out: index entry */
|
||||
ulint* n_ext) /*!< in/out: number of
|
||||
externally stored columns */
|
||||
__attribute__((nonnull, malloc, warn_unused_result));
|
||||
/**************************************************************//**
|
||||
Puts back to entry the data stored in vector. Note that to ensure the
|
||||
fields in entry can accommodate the data, vector must have been created
|
||||
from entry with dtuple_convert_big_rec. */
|
||||
UNIV_INTERN
|
||||
void
|
||||
dtuple_convert_back_big_rec(
|
||||
/*========================*/
|
||||
dict_index_t* index, /*!< in: index */
|
||||
dtuple_t* entry, /*!< in: entry whose data was put to vector */
|
||||
big_rec_t* vector) /*!< in, own: big rec vector; it is
|
||||
freed in this function */
|
||||
__attribute__((nonnull));
|
||||
/**************************************************************//**
|
||||
Frees the memory in a big rec vector. */
|
||||
UNIV_INLINE
|
||||
void
|
||||
dtuple_big_rec_free(
|
||||
/*================*/
|
||||
big_rec_t* vector) /*!< in, own: big rec vector; it is
|
||||
freed in this function */
|
||||
__attribute__((nonnull));
|
||||
|
||||
/*######################################################################*/
|
||||
|
||||
/** Structure for an SQL data field */
|
||||
struct dfield_t{
|
||||
void* data; /*!< pointer to data */
|
||||
unsigned ext:1; /*!< TRUE=externally stored, FALSE=local */
|
||||
unsigned len:32; /*!< data length; UNIV_SQL_NULL if SQL null */
|
||||
dtype_t type; /*!< type of data */
|
||||
};
|
||||
|
||||
/** Structure for an SQL data tuple of fields (logical record) */
|
||||
struct dtuple_t {
|
||||
ulint info_bits; /*!< info bits of an index record:
|
||||
the default is 0; this field is used
|
||||
if an index record is built from
|
||||
a data tuple */
|
||||
ulint n_fields; /*!< number of fields in dtuple */
|
||||
ulint n_fields_cmp; /*!< number of fields which should
|
||||
be used in comparison services
|
||||
of rem0cmp.*; the index search
|
||||
is performed by comparing only these
|
||||
fields, others are ignored; the
|
||||
default value in dtuple creation is
|
||||
the same value as n_fields */
|
||||
dfield_t* fields; /*!< fields */
|
||||
UT_LIST_NODE_T(dtuple_t) tuple_list;
|
||||
/*!< data tuples can be linked into a
|
||||
list using this field */
|
||||
#ifdef UNIV_DEBUG
|
||||
ulint magic_n; /*!< magic number, used in
|
||||
debug assertions */
|
||||
/** Value of dtuple_t::magic_n */
|
||||
# define DATA_TUPLE_MAGIC_N 65478679
|
||||
#endif /* UNIV_DEBUG */
|
||||
};
|
||||
|
||||
/** A slot for a field in a big rec vector */
|
||||
struct big_rec_field_t {
|
||||
ulint field_no; /*!< field number in record */
|
||||
ulint len; /*!< stored data length, in bytes */
|
||||
const void* data; /*!< stored data */
|
||||
};
|
||||
|
||||
/** Storage format for overflow data in a big record, that is, a
|
||||
clustered index record which needs external storage of data fields */
|
||||
struct big_rec_t {
|
||||
mem_heap_t* heap; /*!< memory heap from which
|
||||
allocated */
|
||||
ulint n_fields; /*!< number of stored fields */
|
||||
big_rec_field_t*fields; /*!< stored fields */
|
||||
};
|
||||
|
||||
#ifndef UNIV_NONINL
|
||||
#include "data0data.ic"
|
||||
#endif
|
||||
|
||||
#endif
|
||||
649
storage/innobase/include/data0data.ic
Normal file
649
storage/innobase/include/data0data.ic
Normal file
|
|
@ -0,0 +1,649 @@
|
|||
/*****************************************************************************
|
||||
|
||||
Copyright (c) 1994, 2012, Oracle and/or its affiliates. All Rights Reserved.
|
||||
|
||||
This program is free software; you can redistribute it and/or modify it under
|
||||
the terms of the GNU General Public License as published by the Free Software
|
||||
Foundation; version 2 of the License.
|
||||
|
||||
This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
|
||||
FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License along with
|
||||
this program; if not, write to the Free Software Foundation, Inc.,
|
||||
51 Franklin Street, Suite 500, Boston, MA 02110-1335 USA
|
||||
|
||||
*****************************************************************************/
|
||||
|
||||
/********************************************************************//**
|
||||
@file include/data0data.ic
|
||||
SQL data field and tuple
|
||||
|
||||
Created 5/30/1994 Heikki Tuuri
|
||||
*************************************************************************/
|
||||
|
||||
#include "mem0mem.h"
|
||||
#include "ut0rnd.h"
|
||||
|
||||
#ifdef UNIV_DEBUG
|
||||
/** Dummy variable to catch access to uninitialized fields. In the
|
||||
debug version, dtuple_create() will make all fields of dtuple_t point
|
||||
to data_error. */
|
||||
extern byte data_error;
|
||||
|
||||
/*********************************************************************//**
|
||||
Gets pointer to the type struct of SQL data field.
|
||||
@return pointer to the type struct */
|
||||
UNIV_INLINE
|
||||
dtype_t*
|
||||
dfield_get_type(
|
||||
/*============*/
|
||||
const dfield_t* field) /*!< in: SQL data field */
|
||||
{
|
||||
ut_ad(field);
|
||||
|
||||
return((dtype_t*) &(field->type));
|
||||
}
|
||||
#endif /* UNIV_DEBUG */
|
||||
|
||||
/*********************************************************************//**
|
||||
Sets the type struct of SQL data field. */
|
||||
UNIV_INLINE
|
||||
void
|
||||
dfield_set_type(
|
||||
/*============*/
|
||||
dfield_t* field, /*!< in: SQL data field */
|
||||
const dtype_t* type) /*!< in: pointer to data type struct */
|
||||
{
|
||||
ut_ad(field && type);
|
||||
|
||||
field->type = *type;
|
||||
}
|
||||
|
||||
#ifdef UNIV_DEBUG
|
||||
/*********************************************************************//**
|
||||
Gets pointer to the data in a field.
|
||||
@return pointer to data */
|
||||
UNIV_INLINE
|
||||
void*
|
||||
dfield_get_data(
|
||||
/*============*/
|
||||
const dfield_t* field) /*!< in: field */
|
||||
{
|
||||
ut_ad(field);
|
||||
ut_ad((field->len == UNIV_SQL_NULL)
|
||||
|| (field->data != &data_error));
|
||||
|
||||
return((void*) field->data);
|
||||
}
|
||||
#endif /* UNIV_DEBUG */
|
||||
|
||||
/*********************************************************************//**
|
||||
Gets length of field data.
|
||||
@return length of data; UNIV_SQL_NULL if SQL null data */
|
||||
UNIV_INLINE
|
||||
ulint
|
||||
dfield_get_len(
|
||||
/*===========*/
|
||||
const dfield_t* field) /*!< in: field */
|
||||
{
|
||||
ut_ad(field);
|
||||
ut_ad((field->len == UNIV_SQL_NULL)
|
||||
|| (field->data != &data_error));
|
||||
|
||||
return(field->len);
|
||||
}
|
||||
|
||||
/*********************************************************************//**
|
||||
Sets length in a field. */
|
||||
UNIV_INLINE
|
||||
void
|
||||
dfield_set_len(
|
||||
/*===========*/
|
||||
dfield_t* field, /*!< in: field */
|
||||
ulint len) /*!< in: length or UNIV_SQL_NULL */
|
||||
{
|
||||
ut_ad(field);
|
||||
#ifdef UNIV_VALGRIND_DEBUG
|
||||
if (len != UNIV_SQL_NULL) UNIV_MEM_ASSERT_RW(field->data, len);
|
||||
#endif /* UNIV_VALGRIND_DEBUG */
|
||||
|
||||
field->ext = 0;
|
||||
field->len = len;
|
||||
}
|
||||
|
||||
/*********************************************************************//**
|
||||
Determines if a field is SQL NULL
|
||||
@return nonzero if SQL null data */
|
||||
UNIV_INLINE
|
||||
ulint
|
||||
dfield_is_null(
|
||||
/*===========*/
|
||||
const dfield_t* field) /*!< in: field */
|
||||
{
|
||||
ut_ad(field);
|
||||
|
||||
return(field->len == UNIV_SQL_NULL);
|
||||
}
|
||||
|
||||
/*********************************************************************//**
|
||||
Determines if a field is externally stored
|
||||
@return nonzero if externally stored */
|
||||
UNIV_INLINE
|
||||
ulint
|
||||
dfield_is_ext(
|
||||
/*==========*/
|
||||
const dfield_t* field) /*!< in: field */
|
||||
{
|
||||
ut_ad(field);
|
||||
|
||||
return(field->ext);
|
||||
}
|
||||
|
||||
/*********************************************************************//**
|
||||
Sets the "external storage" flag */
|
||||
UNIV_INLINE
|
||||
void
|
||||
dfield_set_ext(
|
||||
/*===========*/
|
||||
dfield_t* field) /*!< in/out: field */
|
||||
{
|
||||
ut_ad(field);
|
||||
|
||||
field->ext = 1;
|
||||
}
|
||||
|
||||
/*********************************************************************//**
|
||||
Sets pointer to the data and length in a field. */
|
||||
UNIV_INLINE
|
||||
void
|
||||
dfield_set_data(
|
||||
/*============*/
|
||||
dfield_t* field, /*!< in: field */
|
||||
const void* data, /*!< in: data */
|
||||
ulint len) /*!< in: length or UNIV_SQL_NULL */
|
||||
{
|
||||
ut_ad(field);
|
||||
|
||||
#ifdef UNIV_VALGRIND_DEBUG
|
||||
if (len != UNIV_SQL_NULL) UNIV_MEM_ASSERT_RW(data, len);
|
||||
#endif /* UNIV_VALGRIND_DEBUG */
|
||||
field->data = (void*) data;
|
||||
field->ext = 0;
|
||||
field->len = len;
|
||||
}
|
||||
|
||||
/*********************************************************************//**
|
||||
Sets a data field to SQL NULL. */
|
||||
UNIV_INLINE
|
||||
void
|
||||
dfield_set_null(
|
||||
/*============*/
|
||||
dfield_t* field) /*!< in/out: field */
|
||||
{
|
||||
dfield_set_data(field, NULL, UNIV_SQL_NULL);
|
||||
}
|
||||
|
||||
/*********************************************************************//**
|
||||
Copies the data and len fields. */
|
||||
UNIV_INLINE
|
||||
void
|
||||
dfield_copy_data(
|
||||
/*=============*/
|
||||
dfield_t* field1, /*!< out: field to copy to */
|
||||
const dfield_t* field2) /*!< in: field to copy from */
|
||||
{
|
||||
ut_ad(field1 && field2);
|
||||
|
||||
field1->data = field2->data;
|
||||
field1->len = field2->len;
|
||||
field1->ext = field2->ext;
|
||||
}
|
||||
|
||||
/*********************************************************************//**
|
||||
Copies a data field to another. */
|
||||
UNIV_INLINE
|
||||
void
|
||||
dfield_copy(
|
||||
/*========*/
|
||||
dfield_t* field1, /*!< out: field to copy to */
|
||||
const dfield_t* field2) /*!< in: field to copy from */
|
||||
{
|
||||
*field1 = *field2;
|
||||
}
|
||||
|
||||
/*********************************************************************//**
|
||||
Copies the data pointed to by a data field. */
|
||||
UNIV_INLINE
|
||||
void
|
||||
dfield_dup(
|
||||
/*=======*/
|
||||
dfield_t* field, /*!< in/out: data field */
|
||||
mem_heap_t* heap) /*!< in: memory heap where allocated */
|
||||
{
|
||||
if (!dfield_is_null(field)) {
|
||||
UNIV_MEM_ASSERT_RW(field->data, field->len);
|
||||
field->data = mem_heap_dup(heap, field->data, field->len);
|
||||
}
|
||||
}
|
||||
|
||||
#ifndef UNIV_HOTBACKUP
|
||||
/*********************************************************************//**
|
||||
Tests if two data fields are equal.
|
||||
If len==0, tests the data length and content for equality.
|
||||
If len>0, tests the first len bytes of the content for equality.
|
||||
@return TRUE if both fields are NULL or if they are equal */
|
||||
UNIV_INLINE
|
||||
ibool
|
||||
dfield_datas_are_binary_equal(
|
||||
/*==========================*/
|
||||
const dfield_t* field1, /*!< in: field */
|
||||
const dfield_t* field2, /*!< in: field */
|
||||
ulint len) /*!< in: maximum prefix to compare,
|
||||
or 0 to compare the whole field length */
|
||||
{
|
||||
ulint len2 = len;
|
||||
|
||||
if (field1->len == UNIV_SQL_NULL || len == 0 || field1->len < len) {
|
||||
len = field1->len;
|
||||
}
|
||||
|
||||
if (field2->len == UNIV_SQL_NULL || len2 == 0 || field2->len < len2) {
|
||||
len2 = field2->len;
|
||||
}
|
||||
|
||||
return(len == len2
|
||||
&& (len == UNIV_SQL_NULL
|
||||
|| !memcmp(field1->data, field2->data, len)));
|
||||
}
|
||||
|
||||
/*********************************************************************//**
|
||||
Tests if dfield data length and content is equal to the given.
|
||||
@return TRUE if equal */
|
||||
UNIV_INLINE
|
||||
ibool
|
||||
dfield_data_is_binary_equal(
|
||||
/*========================*/
|
||||
const dfield_t* field, /*!< in: field */
|
||||
ulint len, /*!< in: data length or UNIV_SQL_NULL */
|
||||
const byte* data) /*!< in: data */
|
||||
{
|
||||
return(len == dfield_get_len(field)
|
||||
&& (len == UNIV_SQL_NULL
|
||||
|| !memcmp(dfield_get_data(field), data, len)));
|
||||
}
|
||||
#endif /* !UNIV_HOTBACKUP */
|
||||
|
||||
/*********************************************************************//**
|
||||
Gets info bits in a data tuple.
|
||||
@return info bits */
|
||||
UNIV_INLINE
|
||||
ulint
|
||||
dtuple_get_info_bits(
|
||||
/*=================*/
|
||||
const dtuple_t* tuple) /*!< in: tuple */
|
||||
{
|
||||
ut_ad(tuple);
|
||||
|
||||
return(tuple->info_bits);
|
||||
}
|
||||
|
||||
/*********************************************************************//**
|
||||
Sets info bits in a data tuple. */
|
||||
UNIV_INLINE
|
||||
void
|
||||
dtuple_set_info_bits(
|
||||
/*=================*/
|
||||
dtuple_t* tuple, /*!< in: tuple */
|
||||
ulint info_bits) /*!< in: info bits */
|
||||
{
|
||||
ut_ad(tuple);
|
||||
|
||||
tuple->info_bits = info_bits;
|
||||
}
|
||||
|
||||
/*********************************************************************//**
|
||||
Gets number of fields used in record comparisons.
|
||||
@return number of fields used in comparisons in rem0cmp.* */
|
||||
UNIV_INLINE
|
||||
ulint
|
||||
dtuple_get_n_fields_cmp(
|
||||
/*====================*/
|
||||
const dtuple_t* tuple) /*!< in: tuple */
|
||||
{
|
||||
ut_ad(tuple);
|
||||
|
||||
return(tuple->n_fields_cmp);
|
||||
}
|
||||
|
||||
/*********************************************************************//**
|
||||
Sets number of fields used in record comparisons. */
|
||||
UNIV_INLINE
|
||||
void
|
||||
dtuple_set_n_fields_cmp(
|
||||
/*====================*/
|
||||
dtuple_t* tuple, /*!< in: tuple */
|
||||
ulint n_fields_cmp) /*!< in: number of fields used in
|
||||
comparisons in rem0cmp.* */
|
||||
{
|
||||
ut_ad(tuple);
|
||||
ut_ad(n_fields_cmp <= tuple->n_fields);
|
||||
|
||||
tuple->n_fields_cmp = n_fields_cmp;
|
||||
}
|
||||
|
||||
/*********************************************************************//**
|
||||
Gets number of fields in a data tuple.
|
||||
@return number of fields */
|
||||
UNIV_INLINE
|
||||
ulint
|
||||
dtuple_get_n_fields(
|
||||
/*================*/
|
||||
const dtuple_t* tuple) /*!< in: tuple */
|
||||
{
|
||||
ut_ad(tuple);
|
||||
|
||||
return(tuple->n_fields);
|
||||
}
|
||||
|
||||
#ifdef UNIV_DEBUG
|
||||
/*********************************************************************//**
|
||||
Gets nth field of a tuple.
|
||||
@return nth field */
|
||||
UNIV_INLINE
|
||||
dfield_t*
|
||||
dtuple_get_nth_field(
|
||||
/*=================*/
|
||||
const dtuple_t* tuple, /*!< in: tuple */
|
||||
ulint n) /*!< in: index of field */
|
||||
{
|
||||
ut_ad(tuple);
|
||||
ut_ad(n < tuple->n_fields);
|
||||
|
||||
return((dfield_t*) tuple->fields + n);
|
||||
}
|
||||
#endif /* UNIV_DEBUG */
|
||||
|
||||
/**********************************************************//**
|
||||
Creates a data tuple from an already allocated chunk of memory.
|
||||
The size of the chunk must be at least DTUPLE_EST_ALLOC(n_fields).
|
||||
The default value for number of fields used in record comparisons
|
||||
for this tuple is n_fields.
|
||||
@return created tuple (inside buf) */
|
||||
UNIV_INLINE
|
||||
dtuple_t*
|
||||
dtuple_create_from_mem(
|
||||
/*===================*/
|
||||
void* buf, /*!< in, out: buffer to use */
|
||||
ulint buf_size, /*!< in: buffer size */
|
||||
ulint n_fields) /*!< in: number of fields */
|
||||
{
|
||||
dtuple_t* tuple;
|
||||
|
||||
ut_ad(buf != NULL);
|
||||
ut_a(buf_size >= DTUPLE_EST_ALLOC(n_fields));
|
||||
|
||||
tuple = (dtuple_t*) buf;
|
||||
tuple->info_bits = 0;
|
||||
tuple->n_fields = n_fields;
|
||||
tuple->n_fields_cmp = n_fields;
|
||||
tuple->fields = (dfield_t*) &tuple[1];
|
||||
|
||||
#ifdef UNIV_DEBUG
|
||||
tuple->magic_n = DATA_TUPLE_MAGIC_N;
|
||||
|
||||
{ /* In the debug version, initialize fields to an error value */
|
||||
ulint i;
|
||||
|
||||
for (i = 0; i < n_fields; i++) {
|
||||
dfield_t* field;
|
||||
|
||||
field = dtuple_get_nth_field(tuple, i);
|
||||
|
||||
dfield_set_len(field, UNIV_SQL_NULL);
|
||||
field->data = &data_error;
|
||||
dfield_get_type(field)->mtype = DATA_ERROR;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
UNIV_MEM_ASSERT_W(tuple->fields, n_fields * sizeof *tuple->fields);
|
||||
UNIV_MEM_INVALID(tuple->fields, n_fields * sizeof *tuple->fields);
|
||||
return(tuple);
|
||||
}
|
||||
|
||||
/**********************************************************//**
|
||||
Creates a data tuple to a memory heap. The default value for number
|
||||
of fields used in record comparisons for this tuple is n_fields.
|
||||
@return own: created tuple */
|
||||
UNIV_INLINE
|
||||
dtuple_t*
|
||||
dtuple_create(
|
||||
/*==========*/
|
||||
mem_heap_t* heap, /*!< in: memory heap where the tuple
|
||||
is created, DTUPLE_EST_ALLOC(n_fields)
|
||||
bytes will be allocated from this heap */
|
||||
ulint n_fields) /*!< in: number of fields */
|
||||
{
|
||||
void* buf;
|
||||
ulint buf_size;
|
||||
dtuple_t* tuple;
|
||||
|
||||
ut_ad(heap);
|
||||
|
||||
buf_size = DTUPLE_EST_ALLOC(n_fields);
|
||||
buf = mem_heap_alloc(heap, buf_size);
|
||||
|
||||
tuple = dtuple_create_from_mem(buf, buf_size, n_fields);
|
||||
|
||||
return(tuple);
|
||||
}
|
||||
|
||||
/*********************************************************************//**
|
||||
Copies a data tuple to another. This is a shallow copy; if a deep copy
|
||||
is desired, dfield_dup() will have to be invoked on each field.
|
||||
@return own: copy of tuple */
|
||||
UNIV_INLINE
|
||||
dtuple_t*
|
||||
dtuple_copy(
|
||||
/*========*/
|
||||
const dtuple_t* tuple, /*!< in: tuple to copy from */
|
||||
mem_heap_t* heap) /*!< in: memory heap
|
||||
where the tuple is created */
|
||||
{
|
||||
ulint n_fields = dtuple_get_n_fields(tuple);
|
||||
dtuple_t* new_tuple = dtuple_create(heap, n_fields);
|
||||
ulint i;
|
||||
|
||||
for (i = 0; i < n_fields; i++) {
|
||||
dfield_copy(dtuple_get_nth_field(new_tuple, i),
|
||||
dtuple_get_nth_field(tuple, i));
|
||||
}
|
||||
|
||||
return(new_tuple);
|
||||
}
|
||||
|
||||
/**********************************************************//**
|
||||
The following function returns the sum of data lengths of a tuple. The space
|
||||
occupied by the field structs or the tuple struct is not counted. Neither
|
||||
is possible space in externally stored parts of the field.
|
||||
@return sum of data lengths */
|
||||
UNIV_INLINE
|
||||
ulint
|
||||
dtuple_get_data_size(
|
||||
/*=================*/
|
||||
const dtuple_t* tuple, /*!< in: typed data tuple */
|
||||
ulint comp) /*!< in: nonzero=ROW_FORMAT=COMPACT */
|
||||
{
|
||||
const dfield_t* field;
|
||||
ulint n_fields;
|
||||
ulint len;
|
||||
ulint i;
|
||||
ulint sum = 0;
|
||||
|
||||
ut_ad(tuple);
|
||||
ut_ad(dtuple_check_typed(tuple));
|
||||
ut_ad(tuple->magic_n == DATA_TUPLE_MAGIC_N);
|
||||
|
||||
n_fields = tuple->n_fields;
|
||||
|
||||
for (i = 0; i < n_fields; i++) {
|
||||
field = dtuple_get_nth_field(tuple, i);
|
||||
len = dfield_get_len(field);
|
||||
|
||||
if (len == UNIV_SQL_NULL) {
|
||||
len = dtype_get_sql_null_size(dfield_get_type(field),
|
||||
comp);
|
||||
}
|
||||
|
||||
sum += len;
|
||||
}
|
||||
|
||||
return(sum);
|
||||
}
|
||||
|
||||
/*********************************************************************//**
|
||||
Computes the number of externally stored fields in a data tuple.
|
||||
@return number of externally stored fields */
|
||||
UNIV_INLINE
|
||||
ulint
|
||||
dtuple_get_n_ext(
|
||||
/*=============*/
|
||||
const dtuple_t* tuple) /*!< in: tuple */
|
||||
{
|
||||
ulint n_ext = 0;
|
||||
ulint n_fields = tuple->n_fields;
|
||||
ulint i;
|
||||
|
||||
ut_ad(tuple);
|
||||
ut_ad(dtuple_check_typed(tuple));
|
||||
ut_ad(tuple->magic_n == DATA_TUPLE_MAGIC_N);
|
||||
|
||||
for (i = 0; i < n_fields; i++) {
|
||||
n_ext += dtuple_get_nth_field(tuple, i)->ext;
|
||||
}
|
||||
|
||||
return(n_ext);
|
||||
}
|
||||
|
||||
/*******************************************************************//**
|
||||
Sets types of fields binary in a tuple. */
|
||||
UNIV_INLINE
|
||||
void
|
||||
dtuple_set_types_binary(
|
||||
/*====================*/
|
||||
dtuple_t* tuple, /*!< in: data tuple */
|
||||
ulint n) /*!< in: number of fields to set */
|
||||
{
|
||||
dtype_t* dfield_type;
|
||||
ulint i;
|
||||
|
||||
for (i = 0; i < n; i++) {
|
||||
dfield_type = dfield_get_type(dtuple_get_nth_field(tuple, i));
|
||||
dtype_set(dfield_type, DATA_BINARY, 0, 0);
|
||||
}
|
||||
}
|
||||
|
||||
/************************************************************//**
|
||||
Folds a prefix given as the number of fields of a tuple.
|
||||
@return the folded value */
|
||||
UNIV_INLINE
|
||||
ulint
|
||||
dtuple_fold(
|
||||
/*========*/
|
||||
const dtuple_t* tuple, /*!< in: the tuple */
|
||||
ulint n_fields,/*!< in: number of complete fields to fold */
|
||||
ulint n_bytes,/*!< in: number of bytes to fold in an
|
||||
incomplete last field */
|
||||
index_id_t tree_id)/*!< in: index tree id */
|
||||
{
|
||||
const dfield_t* field;
|
||||
ulint i;
|
||||
const byte* data;
|
||||
ulint len;
|
||||
ulint fold;
|
||||
|
||||
ut_ad(tuple);
|
||||
ut_ad(tuple->magic_n == DATA_TUPLE_MAGIC_N);
|
||||
ut_ad(dtuple_check_typed(tuple));
|
||||
|
||||
fold = ut_fold_ull(tree_id);
|
||||
|
||||
for (i = 0; i < n_fields; i++) {
|
||||
field = dtuple_get_nth_field(tuple, i);
|
||||
|
||||
data = (const byte*) dfield_get_data(field);
|
||||
len = dfield_get_len(field);
|
||||
|
||||
if (len != UNIV_SQL_NULL) {
|
||||
fold = ut_fold_ulint_pair(fold,
|
||||
ut_fold_binary(data, len));
|
||||
}
|
||||
}
|
||||
|
||||
if (n_bytes > 0) {
|
||||
field = dtuple_get_nth_field(tuple, i);
|
||||
|
||||
data = (const byte*) dfield_get_data(field);
|
||||
len = dfield_get_len(field);
|
||||
|
||||
if (len != UNIV_SQL_NULL) {
|
||||
if (len > n_bytes) {
|
||||
len = n_bytes;
|
||||
}
|
||||
|
||||
fold = ut_fold_ulint_pair(fold,
|
||||
ut_fold_binary(data, len));
|
||||
}
|
||||
}
|
||||
|
||||
return(fold);
|
||||
}
|
||||
|
||||
/**********************************************************************//**
|
||||
Writes an SQL null field full of zeros. */
|
||||
UNIV_INLINE
|
||||
void
|
||||
data_write_sql_null(
|
||||
/*================*/
|
||||
byte* data, /*!< in: pointer to a buffer of size len */
|
||||
ulint len) /*!< in: SQL null size in bytes */
|
||||
{
|
||||
memset(data, 0, len);
|
||||
}
|
||||
|
||||
/**********************************************************************//**
|
||||
Checks if a dtuple contains an SQL null value.
|
||||
@return TRUE if some field is SQL null */
|
||||
UNIV_INLINE
|
||||
ibool
|
||||
dtuple_contains_null(
|
||||
/*=================*/
|
||||
const dtuple_t* tuple) /*!< in: dtuple */
|
||||
{
|
||||
ulint n;
|
||||
ulint i;
|
||||
|
||||
n = dtuple_get_n_fields(tuple);
|
||||
|
||||
for (i = 0; i < n; i++) {
|
||||
if (dfield_is_null(dtuple_get_nth_field(tuple, i))) {
|
||||
|
||||
return(TRUE);
|
||||
}
|
||||
}
|
||||
|
||||
return(FALSE);
|
||||
}
|
||||
|
||||
/**************************************************************//**
|
||||
Frees the memory in a big rec vector. */
|
||||
UNIV_INLINE
|
||||
void
|
||||
dtuple_big_rec_free(
|
||||
/*================*/
|
||||
big_rec_t* vector) /*!< in, own: big rec vector; it is
|
||||
freed in this function */
|
||||
{
|
||||
mem_heap_free(vector->heap);
|
||||
}
|
||||
544
storage/innobase/include/data0type.h
Normal file
544
storage/innobase/include/data0type.h
Normal file
|
|
@ -0,0 +1,544 @@
|
|||
/*****************************************************************************
|
||||
|
||||
Copyright (c) 1996, 2012, Oracle and/or its affiliates. All Rights Reserved.
|
||||
|
||||
This program is free software; you can redistribute it and/or modify it under
|
||||
the terms of the GNU General Public License as published by the Free Software
|
||||
Foundation; version 2 of the License.
|
||||
|
||||
This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
|
||||
FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License along with
|
||||
this program; if not, write to the Free Software Foundation, Inc.,
|
||||
51 Franklin Street, Suite 500, Boston, MA 02110-1335 USA
|
||||
|
||||
*****************************************************************************/
|
||||
|
||||
/**************************************************//**
|
||||
@file include/data0type.h
|
||||
Data types
|
||||
|
||||
Created 1/16/1996 Heikki Tuuri
|
||||
*******************************************************/
|
||||
|
||||
#ifndef data0type_h
|
||||
#define data0type_h
|
||||
|
||||
#include "univ.i"
|
||||
|
||||
extern ulint data_mysql_default_charset_coll;
|
||||
#define DATA_MYSQL_LATIN1_SWEDISH_CHARSET_COLL 8
|
||||
#define DATA_MYSQL_BINARY_CHARSET_COLL 63
|
||||
|
||||
/* SQL data type struct */
|
||||
struct dtype_t;
|
||||
|
||||
/* SQL Like operator comparison types */
|
||||
enum ib_like_t {
|
||||
IB_LIKE_EXACT, /* e.g. STRING */
|
||||
IB_LIKE_PREFIX, /* e.g., STRING% */
|
||||
IB_LIKE_SUFFIX, /* e.g., %STRING */
|
||||
IB_LIKE_SUBSTR, /* e.g., %STRING% */
|
||||
IB_LIKE_REGEXP /* Future */
|
||||
};
|
||||
|
||||
/*-------------------------------------------*/
|
||||
/* The 'MAIN TYPE' of a column */
|
||||
#define DATA_MISSING 0 /* missing column */
|
||||
#define DATA_VARCHAR 1 /* character varying of the
|
||||
latin1_swedish_ci charset-collation; note
|
||||
that the MySQL format for this, DATA_BINARY,
|
||||
DATA_VARMYSQL, is also affected by whether the
|
||||
'precise type' contains
|
||||
DATA_MYSQL_TRUE_VARCHAR */
|
||||
#define DATA_CHAR 2 /* fixed length character of the
|
||||
latin1_swedish_ci charset-collation */
|
||||
#define DATA_FIXBINARY 3 /* binary string of fixed length */
|
||||
#define DATA_BINARY 4 /* binary string */
|
||||
#define DATA_BLOB 5 /* binary large object, or a TEXT type;
|
||||
if prtype & DATA_BINARY_TYPE == 0, then this is
|
||||
actually a TEXT column (or a BLOB created
|
||||
with < 4.0.14; since column prefix indexes
|
||||
came only in 4.0.14, the missing flag in BLOBs
|
||||
created before that does not cause any harm) */
|
||||
#define DATA_INT 6 /* integer: can be any size 1 - 8 bytes */
|
||||
#define DATA_SYS_CHILD 7 /* address of the child page in node pointer */
|
||||
#define DATA_SYS 8 /* system column */
|
||||
|
||||
/* Data types >= DATA_FLOAT must be compared using the whole field, not as
|
||||
binary strings */
|
||||
|
||||
#define DATA_FLOAT 9
|
||||
#define DATA_DOUBLE 10
|
||||
#define DATA_DECIMAL 11 /* decimal number stored as an ASCII string */
|
||||
#define DATA_VARMYSQL 12 /* any charset varying length char */
|
||||
#define DATA_MYSQL 13 /* any charset fixed length char */
|
||||
/* NOTE that 4.1.1 used DATA_MYSQL and
|
||||
DATA_VARMYSQL for all character sets, and the
|
||||
charset-collation for tables created with it
|
||||
can also be latin1_swedish_ci */
|
||||
#define DATA_MTYPE_MAX 63 /* dtype_store_for_order_and_null_size()
|
||||
requires the values are <= 63 */
|
||||
/*-------------------------------------------*/
|
||||
/* The 'PRECISE TYPE' of a column */
|
||||
/*
|
||||
Tables created by a MySQL user have the following convention:
|
||||
|
||||
- In the least significant byte in the precise type we store the MySQL type
|
||||
code (not applicable for system columns).
|
||||
|
||||
- In the second least significant byte we OR flags DATA_NOT_NULL,
|
||||
DATA_UNSIGNED, DATA_BINARY_TYPE.
|
||||
|
||||
- In the third least significant byte of the precise type of string types we
|
||||
store the MySQL charset-collation code. In DATA_BLOB columns created with
|
||||
< 4.0.14 we do not actually know if it is a BLOB or a TEXT column. Since there
|
||||
are no indexes on prefixes of BLOB or TEXT columns in < 4.0.14, this is no
|
||||
problem, though.
|
||||
|
||||
Note that versions < 4.1.2 or < 5.0.1 did not store the charset code to the
|
||||
precise type, since the charset was always the default charset of the MySQL
|
||||
installation. If the stored charset code is 0 in the system table SYS_COLUMNS
|
||||
of InnoDB, that means that the default charset of this MySQL installation
|
||||
should be used.
|
||||
|
||||
When loading a table definition from the system tables to the InnoDB data
|
||||
dictionary cache in main memory, InnoDB versions >= 4.1.2 and >= 5.0.1 check
|
||||
if the stored charset-collation is 0, and if that is the case and the type is
|
||||
a non-binary string, replace that 0 by the default charset-collation code of
|
||||
this MySQL installation. In short, in old tables, the charset-collation code
|
||||
in the system tables on disk can be 0, but in in-memory data structures
|
||||
(dtype_t), the charset-collation code is always != 0 for non-binary string
|
||||
types.
|
||||
|
||||
In new tables, in binary string types, the charset-collation code is the
|
||||
MySQL code for the 'binary charset', that is, != 0.
|
||||
|
||||
For binary string types and for DATA_CHAR, DATA_VARCHAR, and for those
|
||||
DATA_BLOB which are binary or have the charset-collation latin1_swedish_ci,
|
||||
InnoDB performs all comparisons internally, without resorting to the MySQL
|
||||
comparison functions. This is to save CPU time.
|
||||
|
||||
InnoDB's own internal system tables have different precise types for their
|
||||
columns, and for them the precise type is usually not used at all.
|
||||
*/
|
||||
|
||||
#define DATA_ENGLISH 4 /* English language character string: this
|
||||
is a relic from pre-MySQL time and only used
|
||||
for InnoDB's own system tables */
|
||||
#define DATA_ERROR 111 /* another relic from pre-MySQL time */
|
||||
|
||||
#define DATA_MYSQL_TYPE_MASK 255 /* AND with this mask to extract the MySQL
|
||||
type from the precise type */
|
||||
#define DATA_MYSQL_TRUE_VARCHAR 15 /* MySQL type code for the >= 5.0.3
|
||||
format true VARCHAR */
|
||||
|
||||
/* Precise data types for system columns and the length of those columns;
|
||||
NOTE: the values must run from 0 up in the order given! All codes must
|
||||
be less than 256 */
|
||||
#define DATA_ROW_ID 0 /* row id: a 48-bit integer */
|
||||
#define DATA_ROW_ID_LEN 6 /* stored length for row id */
|
||||
|
||||
#define DATA_TRX_ID 1 /* transaction id: 6 bytes */
|
||||
#define DATA_TRX_ID_LEN 6
|
||||
|
||||
#define DATA_ROLL_PTR 2 /* rollback data pointer: 7 bytes */
|
||||
#define DATA_ROLL_PTR_LEN 7
|
||||
|
||||
#define DATA_N_SYS_COLS 3 /* number of system columns defined above */
|
||||
|
||||
#define DATA_FTS_DOC_ID 3 /* Used as FTS DOC ID column */
|
||||
|
||||
#define DATA_SYS_PRTYPE_MASK 0xF /* mask to extract the above from prtype */
|
||||
|
||||
/* Flags ORed to the precise data type */
|
||||
#define DATA_NOT_NULL 256 /* this is ORed to the precise type when
|
||||
the column is declared as NOT NULL */
|
||||
#define DATA_UNSIGNED 512 /* this id ORed to the precise type when
|
||||
we have an unsigned integer type */
|
||||
#define DATA_BINARY_TYPE 1024 /* if the data type is a binary character
|
||||
string, this is ORed to the precise type:
|
||||
this only holds for tables created with
|
||||
>= MySQL-4.0.14 */
|
||||
/* #define DATA_NONLATIN1 2048 This is a relic from < 4.1.2 and < 5.0.1.
|
||||
In earlier versions this was set for some
|
||||
BLOB columns.
|
||||
*/
|
||||
#define DATA_LONG_TRUE_VARCHAR 4096 /* this is ORed to the precise data
|
||||
type when the column is true VARCHAR where
|
||||
MySQL uses 2 bytes to store the data len;
|
||||
for shorter VARCHARs MySQL uses only 1 byte */
|
||||
/*-------------------------------------------*/
|
||||
|
||||
/* This many bytes we need to store the type information affecting the
|
||||
alphabetical order for a single field and decide the storage size of an
|
||||
SQL null*/
|
||||
#define DATA_ORDER_NULL_TYPE_BUF_SIZE 4
|
||||
/* In the >= 4.1.x storage format we add 2 bytes more so that we can also
|
||||
store the charset-collation number; one byte is left unused, though */
|
||||
#define DATA_NEW_ORDER_NULL_TYPE_BUF_SIZE 6
|
||||
|
||||
/* Maximum multi-byte character length in bytes, plus 1 */
|
||||
#define DATA_MBMAX 5
|
||||
|
||||
/* Pack mbminlen, mbmaxlen to mbminmaxlen. */
|
||||
#define DATA_MBMINMAXLEN(mbminlen, mbmaxlen) \
|
||||
((mbmaxlen) * DATA_MBMAX + (mbminlen))
|
||||
/* Get mbminlen from mbminmaxlen. Cast the result of UNIV_EXPECT to ulint
|
||||
because in GCC it returns a long. */
|
||||
#define DATA_MBMINLEN(mbminmaxlen) ((ulint) \
|
||||
UNIV_EXPECT(((mbminmaxlen) % DATA_MBMAX), \
|
||||
1))
|
||||
/* Get mbmaxlen from mbminmaxlen. */
|
||||
#define DATA_MBMAXLEN(mbminmaxlen) ((ulint) ((mbminmaxlen) / DATA_MBMAX))
|
||||
|
||||
/* We now support 15 bits (up to 32767) collation number */
|
||||
#define MAX_CHAR_COLL_NUM 32767
|
||||
|
||||
/* Mask to get the Charset Collation number (0x7fff) */
|
||||
#define CHAR_COLL_MASK MAX_CHAR_COLL_NUM
|
||||
|
||||
#ifndef UNIV_HOTBACKUP
|
||||
/*********************************************************************//**
|
||||
Gets the MySQL type code from a dtype.
|
||||
@return MySQL type code; this is NOT an InnoDB type code! */
|
||||
UNIV_INLINE
|
||||
ulint
|
||||
dtype_get_mysql_type(
|
||||
/*=================*/
|
||||
const dtype_t* type); /*!< in: type struct */
|
||||
/*********************************************************************//**
|
||||
Determine how many bytes the first n characters of the given string occupy.
|
||||
If the string is shorter than n characters, returns the number of bytes
|
||||
the characters in the string occupy.
|
||||
@return length of the prefix, in bytes */
|
||||
UNIV_INTERN
|
||||
ulint
|
||||
dtype_get_at_most_n_mbchars(
|
||||
/*========================*/
|
||||
ulint prtype, /*!< in: precise type */
|
||||
ulint mbminmaxlen, /*!< in: minimum and maximum length of
|
||||
a multi-byte character */
|
||||
ulint prefix_len, /*!< in: length of the requested
|
||||
prefix, in characters, multiplied by
|
||||
dtype_get_mbmaxlen(dtype) */
|
||||
ulint data_len, /*!< in: length of str (in bytes) */
|
||||
const char* str); /*!< in: the string whose prefix
|
||||
length is being determined */
|
||||
#endif /* !UNIV_HOTBACKUP */
|
||||
/*********************************************************************//**
|
||||
Checks if a data main type is a string type. Also a BLOB is considered a
|
||||
string type.
|
||||
@return TRUE if string type */
|
||||
UNIV_INTERN
|
||||
ibool
|
||||
dtype_is_string_type(
|
||||
/*=================*/
|
||||
ulint mtype); /*!< in: InnoDB main data type code: DATA_CHAR, ... */
|
||||
/*********************************************************************//**
|
||||
Checks if a type is a binary string type. Note that for tables created with
|
||||
< 4.0.14, we do not know if a DATA_BLOB column is a BLOB or a TEXT column. For
|
||||
those DATA_BLOB columns this function currently returns FALSE.
|
||||
@return TRUE if binary string type */
|
||||
UNIV_INTERN
|
||||
ibool
|
||||
dtype_is_binary_string_type(
|
||||
/*========================*/
|
||||
ulint mtype, /*!< in: main data type */
|
||||
ulint prtype);/*!< in: precise type */
|
||||
/*********************************************************************//**
|
||||
Checks if a type is a non-binary string type. That is, dtype_is_string_type is
|
||||
TRUE and dtype_is_binary_string_type is FALSE. Note that for tables created
|
||||
with < 4.0.14, we do not know if a DATA_BLOB column is a BLOB or a TEXT column.
|
||||
For those DATA_BLOB columns this function currently returns TRUE.
|
||||
@return TRUE if non-binary string type */
|
||||
UNIV_INTERN
|
||||
ibool
|
||||
dtype_is_non_binary_string_type(
|
||||
/*============================*/
|
||||
ulint mtype, /*!< in: main data type */
|
||||
ulint prtype);/*!< in: precise type */
|
||||
/*********************************************************************//**
|
||||
Sets a data type structure. */
|
||||
UNIV_INLINE
|
||||
void
|
||||
dtype_set(
|
||||
/*======*/
|
||||
dtype_t* type, /*!< in: type struct to init */
|
||||
ulint mtype, /*!< in: main data type */
|
||||
ulint prtype, /*!< in: precise type */
|
||||
ulint len); /*!< in: precision of type */
|
||||
/*********************************************************************//**
|
||||
Copies a data type structure. */
|
||||
UNIV_INLINE
|
||||
void
|
||||
dtype_copy(
|
||||
/*=======*/
|
||||
dtype_t* type1, /*!< in: type struct to copy to */
|
||||
const dtype_t* type2); /*!< in: type struct to copy from */
|
||||
/*********************************************************************//**
|
||||
Gets the SQL main data type.
|
||||
@return SQL main data type */
|
||||
UNIV_INLINE
|
||||
ulint
|
||||
dtype_get_mtype(
|
||||
/*============*/
|
||||
const dtype_t* type); /*!< in: data type */
|
||||
/*********************************************************************//**
|
||||
Gets the precise data type.
|
||||
@return precise data type */
|
||||
UNIV_INLINE
|
||||
ulint
|
||||
dtype_get_prtype(
|
||||
/*=============*/
|
||||
const dtype_t* type); /*!< in: data type */
|
||||
#ifndef UNIV_HOTBACKUP
|
||||
/*********************************************************************//**
|
||||
Compute the mbminlen and mbmaxlen members of a data type structure. */
|
||||
UNIV_INLINE
|
||||
void
|
||||
dtype_get_mblen(
|
||||
/*============*/
|
||||
ulint mtype, /*!< in: main type */
|
||||
ulint prtype, /*!< in: precise type (and collation) */
|
||||
ulint* mbminlen, /*!< out: minimum length of a
|
||||
multi-byte character */
|
||||
ulint* mbmaxlen); /*!< out: maximum length of a
|
||||
multi-byte character */
|
||||
/*********************************************************************//**
|
||||
Gets the MySQL charset-collation code for MySQL string types.
|
||||
@return MySQL charset-collation code */
|
||||
UNIV_INLINE
|
||||
ulint
|
||||
dtype_get_charset_coll(
|
||||
/*===================*/
|
||||
ulint prtype);/*!< in: precise data type */
|
||||
/*********************************************************************//**
|
||||
Forms a precise type from the < 4.1.2 format precise type plus the
|
||||
charset-collation code.
|
||||
@return precise type, including the charset-collation code */
|
||||
UNIV_INTERN
|
||||
ulint
|
||||
dtype_form_prtype(
|
||||
/*==============*/
|
||||
ulint old_prtype, /*!< in: the MySQL type code and the flags
|
||||
DATA_BINARY_TYPE etc. */
|
||||
ulint charset_coll); /*!< in: MySQL charset-collation code */
|
||||
/*********************************************************************//**
|
||||
Determines if a MySQL string type is a subset of UTF-8. This function
|
||||
may return false negatives, in case further character-set collation
|
||||
codes are introduced in MySQL later.
|
||||
@return TRUE if a subset of UTF-8 */
|
||||
UNIV_INLINE
|
||||
ibool
|
||||
dtype_is_utf8(
|
||||
/*==========*/
|
||||
ulint prtype);/*!< in: precise data type */
|
||||
#endif /* !UNIV_HOTBACKUP */
|
||||
/*********************************************************************//**
|
||||
Gets the type length.
|
||||
@return fixed length of the type, in bytes, or 0 if variable-length */
|
||||
UNIV_INLINE
|
||||
ulint
|
||||
dtype_get_len(
|
||||
/*==========*/
|
||||
const dtype_t* type); /*!< in: data type */
|
||||
#ifndef UNIV_HOTBACKUP
|
||||
/*********************************************************************//**
|
||||
Gets the minimum length of a character, in bytes.
|
||||
@return minimum length of a char, in bytes, or 0 if this is not a
|
||||
character type */
|
||||
UNIV_INLINE
|
||||
ulint
|
||||
dtype_get_mbminlen(
|
||||
/*===============*/
|
||||
const dtype_t* type); /*!< in: type */
|
||||
/*********************************************************************//**
|
||||
Gets the maximum length of a character, in bytes.
|
||||
@return maximum length of a char, in bytes, or 0 if this is not a
|
||||
character type */
|
||||
UNIV_INLINE
|
||||
ulint
|
||||
dtype_get_mbmaxlen(
|
||||
/*===============*/
|
||||
const dtype_t* type); /*!< in: type */
|
||||
/*********************************************************************//**
|
||||
Sets the minimum and maximum length of a character, in bytes. */
|
||||
UNIV_INLINE
|
||||
void
|
||||
dtype_set_mbminmaxlen(
|
||||
/*==================*/
|
||||
dtype_t* type, /*!< in/out: type */
|
||||
ulint mbminlen, /*!< in: minimum length of a char,
|
||||
in bytes, or 0 if this is not
|
||||
a character type */
|
||||
ulint mbmaxlen); /*!< in: maximum length of a char,
|
||||
in bytes, or 0 if this is not
|
||||
a character type */
|
||||
/*********************************************************************//**
|
||||
Gets the padding character code for the type.
|
||||
@return padding character code, or ULINT_UNDEFINED if no padding specified */
|
||||
UNIV_INLINE
|
||||
ulint
|
||||
dtype_get_pad_char(
|
||||
/*===============*/
|
||||
ulint mtype, /*!< in: main type */
|
||||
ulint prtype); /*!< in: precise type */
|
||||
#endif /* !UNIV_HOTBACKUP */
|
||||
/***********************************************************************//**
|
||||
Returns the size of a fixed size data type, 0 if not a fixed size type.
|
||||
@return fixed size, or 0 */
|
||||
UNIV_INLINE
|
||||
ulint
|
||||
dtype_get_fixed_size_low(
|
||||
/*=====================*/
|
||||
ulint mtype, /*!< in: main type */
|
||||
ulint prtype, /*!< in: precise type */
|
||||
ulint len, /*!< in: length */
|
||||
ulint mbminmaxlen, /*!< in: minimum and maximum length of a
|
||||
multibyte character, in bytes */
|
||||
ulint comp); /*!< in: nonzero=ROW_FORMAT=COMPACT */
|
||||
#ifndef UNIV_HOTBACKUP
|
||||
/***********************************************************************//**
|
||||
Returns the minimum size of a data type.
|
||||
@return minimum size */
|
||||
UNIV_INLINE
|
||||
ulint
|
||||
dtype_get_min_size_low(
|
||||
/*===================*/
|
||||
ulint mtype, /*!< in: main type */
|
||||
ulint prtype, /*!< in: precise type */
|
||||
ulint len, /*!< in: length */
|
||||
ulint mbminmaxlen); /*!< in: minimum and maximum length of a
|
||||
multibyte character */
|
||||
/***********************************************************************//**
|
||||
Returns the maximum size of a data type. Note: types in system tables may be
|
||||
incomplete and return incorrect information.
|
||||
@return maximum size */
|
||||
UNIV_INLINE
|
||||
ulint
|
||||
dtype_get_max_size_low(
|
||||
/*===================*/
|
||||
ulint mtype, /*!< in: main type */
|
||||
ulint len); /*!< in: length */
|
||||
#endif /* !UNIV_HOTBACKUP */
|
||||
/***********************************************************************//**
|
||||
Returns the ROW_FORMAT=REDUNDANT stored SQL NULL size of a type.
|
||||
For fixed length types it is the fixed length of the type, otherwise 0.
|
||||
@return SQL null storage size in ROW_FORMAT=REDUNDANT */
|
||||
UNIV_INLINE
|
||||
ulint
|
||||
dtype_get_sql_null_size(
|
||||
/*====================*/
|
||||
const dtype_t* type, /*!< in: type */
|
||||
ulint comp); /*!< in: nonzero=ROW_FORMAT=COMPACT */
|
||||
#ifndef UNIV_HOTBACKUP
|
||||
/**********************************************************************//**
|
||||
Reads to a type the stored information which determines its alphabetical
|
||||
ordering and the storage size of an SQL NULL value. */
|
||||
UNIV_INLINE
|
||||
void
|
||||
dtype_read_for_order_and_null_size(
|
||||
/*===============================*/
|
||||
dtype_t* type, /*!< in: type struct */
|
||||
const byte* buf); /*!< in: buffer for the stored order info */
|
||||
/**********************************************************************//**
|
||||
Stores for a type the information which determines its alphabetical ordering
|
||||
and the storage size of an SQL NULL value. This is the >= 4.1.x storage
|
||||
format. */
|
||||
UNIV_INLINE
|
||||
void
|
||||
dtype_new_store_for_order_and_null_size(
|
||||
/*====================================*/
|
||||
byte* buf, /*!< in: buffer for
|
||||
DATA_NEW_ORDER_NULL_TYPE_BUF_SIZE
|
||||
bytes where we store the info */
|
||||
const dtype_t* type, /*!< in: type struct */
|
||||
ulint prefix_len);/*!< in: prefix length to
|
||||
replace type->len, or 0 */
|
||||
/**********************************************************************//**
|
||||
Reads to a type the stored information which determines its alphabetical
|
||||
ordering and the storage size of an SQL NULL value. This is the 4.1.x storage
|
||||
format. */
|
||||
UNIV_INLINE
|
||||
void
|
||||
dtype_new_read_for_order_and_null_size(
|
||||
/*===================================*/
|
||||
dtype_t* type, /*!< in: type struct */
|
||||
const byte* buf); /*!< in: buffer for stored type order info */
|
||||
|
||||
/*********************************************************************//**
|
||||
Returns the type's SQL name (e.g. BIGINT UNSIGNED) from mtype,prtype,len
|
||||
@return the SQL type name */
|
||||
UNIV_INLINE
|
||||
char*
|
||||
dtype_sql_name(
|
||||
/*===========*/
|
||||
unsigned mtype, /*!< in: mtype */
|
||||
unsigned prtype, /*!< in: prtype */
|
||||
unsigned len, /*!< in: len */
|
||||
char* name, /*!< out: SQL name */
|
||||
unsigned name_sz);/*!< in: size of the name buffer */
|
||||
|
||||
#endif /* !UNIV_HOTBACKUP */
|
||||
|
||||
/*********************************************************************//**
|
||||
Validates a data type structure.
|
||||
@return TRUE if ok */
|
||||
UNIV_INTERN
|
||||
ibool
|
||||
dtype_validate(
|
||||
/*===========*/
|
||||
const dtype_t* type); /*!< in: type struct to validate */
|
||||
/*********************************************************************//**
|
||||
Prints a data type structure. */
|
||||
UNIV_INTERN
|
||||
void
|
||||
dtype_print(
|
||||
/*========*/
|
||||
const dtype_t* type); /*!< in: type */
|
||||
|
||||
/* Structure for an SQL data type.
|
||||
If you add fields to this structure, be sure to initialize them everywhere.
|
||||
This structure is initialized in the following functions:
|
||||
dtype_set()
|
||||
dtype_read_for_order_and_null_size()
|
||||
dtype_new_read_for_order_and_null_size()
|
||||
sym_tab_add_null_lit() */
|
||||
|
||||
struct dtype_t{
|
||||
unsigned prtype:32; /*!< precise type; MySQL data
|
||||
type, charset code, flags to
|
||||
indicate nullability,
|
||||
signedness, whether this is a
|
||||
binary string, whether this is
|
||||
a true VARCHAR where MySQL
|
||||
uses 2 bytes to store the length */
|
||||
unsigned mtype:8; /*!< main data type */
|
||||
|
||||
/* the remaining fields do not affect alphabetical ordering: */
|
||||
|
||||
unsigned len:16; /*!< length; for MySQL data this
|
||||
is field->pack_length(),
|
||||
except that for a >= 5.0.3
|
||||
type true VARCHAR this is the
|
||||
maximum byte length of the
|
||||
string data (in addition to
|
||||
the string, MySQL uses 1 or 2
|
||||
bytes to store the string length) */
|
||||
#ifndef UNIV_HOTBACKUP
|
||||
unsigned mbminmaxlen:5; /*!< minimum and maximum length of a
|
||||
character, in bytes;
|
||||
DATA_MBMINMAXLEN(mbminlen,mbmaxlen);
|
||||
mbminlen=DATA_MBMINLEN(mbminmaxlen);
|
||||
mbmaxlen=DATA_MBMINLEN(mbminmaxlen) */
|
||||
#endif /* !UNIV_HOTBACKUP */
|
||||
};
|
||||
|
||||
#ifndef UNIV_NONINL
|
||||
#include "data0type.ic"
|
||||
#endif
|
||||
|
||||
#endif
|
||||
711
storage/innobase/include/data0type.ic
Normal file
711
storage/innobase/include/data0type.ic
Normal file
|
|
@ -0,0 +1,711 @@
|
|||
/*****************************************************************************
|
||||
|
||||
Copyright (c) 1996, 2012, Oracle and/or its affiliates. All Rights Reserved.
|
||||
|
||||
This program is free software; you can redistribute it and/or modify it under
|
||||
the terms of the GNU General Public License as published by the Free Software
|
||||
Foundation; version 2 of the License.
|
||||
|
||||
This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
|
||||
FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License along with
|
||||
this program; if not, write to the Free Software Foundation, Inc.,
|
||||
51 Franklin Street, Suite 500, Boston, MA 02110-1335 USA
|
||||
|
||||
*****************************************************************************/
|
||||
|
||||
/**************************************************//**
|
||||
@file include/data0type.ic
|
||||
Data types
|
||||
|
||||
Created 1/16/1996 Heikki Tuuri
|
||||
*******************************************************/
|
||||
|
||||
#include <string.h> /* strlen() */
|
||||
|
||||
#include "mach0data.h"
|
||||
#ifndef UNIV_HOTBACKUP
|
||||
# include "ha_prototypes.h"
|
||||
|
||||
/*********************************************************************//**
|
||||
Gets the MySQL charset-collation code for MySQL string types.
|
||||
@return MySQL charset-collation code */
|
||||
UNIV_INLINE
|
||||
ulint
|
||||
dtype_get_charset_coll(
|
||||
/*===================*/
|
||||
ulint prtype) /*!< in: precise data type */
|
||||
{
|
||||
return((prtype >> 16) & CHAR_COLL_MASK);
|
||||
}
|
||||
|
||||
/*********************************************************************//**
|
||||
Determines if a MySQL string type is a subset of UTF-8. This function
|
||||
may return false negatives, in case further character-set collation
|
||||
codes are introduced in MySQL later.
|
||||
@return TRUE if a subset of UTF-8 */
|
||||
UNIV_INLINE
|
||||
ibool
|
||||
dtype_is_utf8(
|
||||
/*==========*/
|
||||
ulint prtype) /*!< in: precise data type */
|
||||
{
|
||||
/* These codes have been copied from strings/ctype-extra.c
|
||||
and strings/ctype-utf8.c. */
|
||||
switch (dtype_get_charset_coll(prtype)) {
|
||||
case 11: /* ascii_general_ci */
|
||||
case 65: /* ascii_bin */
|
||||
case 33: /* utf8_general_ci */
|
||||
case 83: /* utf8_bin */
|
||||
case 254: /* utf8_general_cs */
|
||||
return(TRUE);
|
||||
}
|
||||
|
||||
return(FALSE);
|
||||
}
|
||||
|
||||
/*********************************************************************//**
|
||||
Gets the MySQL type code from a dtype.
|
||||
@return MySQL type code; this is NOT an InnoDB type code! */
|
||||
UNIV_INLINE
|
||||
ulint
|
||||
dtype_get_mysql_type(
|
||||
/*=================*/
|
||||
const dtype_t* type) /*!< in: type struct */
|
||||
{
|
||||
return(type->prtype & 0xFFUL);
|
||||
}
|
||||
|
||||
/*********************************************************************//**
|
||||
Compute the mbminlen and mbmaxlen members of a data type structure. */
|
||||
UNIV_INLINE
|
||||
void
|
||||
dtype_get_mblen(
|
||||
/*============*/
|
||||
ulint mtype, /*!< in: main type */
|
||||
ulint prtype, /*!< in: precise type (and collation) */
|
||||
ulint* mbminlen, /*!< out: minimum length of a
|
||||
multi-byte character */
|
||||
ulint* mbmaxlen) /*!< out: maximum length of a
|
||||
multi-byte character */
|
||||
{
|
||||
if (dtype_is_string_type(mtype)) {
|
||||
innobase_get_cset_width(dtype_get_charset_coll(prtype),
|
||||
mbminlen, mbmaxlen);
|
||||
ut_ad(*mbminlen <= *mbmaxlen);
|
||||
ut_ad(*mbminlen < DATA_MBMAX);
|
||||
ut_ad(*mbmaxlen < DATA_MBMAX);
|
||||
} else {
|
||||
*mbminlen = *mbmaxlen = 0;
|
||||
}
|
||||
}
|
||||
|
||||
/*********************************************************************//**
|
||||
Sets the minimum and maximum length of a character, in bytes. */
|
||||
UNIV_INLINE
|
||||
void
|
||||
dtype_set_mbminmaxlen(
|
||||
/*==================*/
|
||||
dtype_t* type, /*!< in/out: type */
|
||||
ulint mbminlen, /*!< in: minimum length of a char,
|
||||
in bytes, or 0 if this is not
|
||||
a character type */
|
||||
ulint mbmaxlen) /*!< in: maximum length of a char,
|
||||
in bytes, or 0 if this is not
|
||||
a character type */
|
||||
{
|
||||
ut_ad(mbminlen < DATA_MBMAX);
|
||||
ut_ad(mbmaxlen < DATA_MBMAX);
|
||||
ut_ad(mbminlen <= mbmaxlen);
|
||||
|
||||
type->mbminmaxlen = DATA_MBMINMAXLEN(mbminlen, mbmaxlen);
|
||||
}
|
||||
|
||||
/*********************************************************************//**
|
||||
Compute the mbminlen and mbmaxlen members of a data type structure. */
|
||||
UNIV_INLINE
|
||||
void
|
||||
dtype_set_mblen(
|
||||
/*============*/
|
||||
dtype_t* type) /*!< in/out: type */
|
||||
{
|
||||
ulint mbminlen;
|
||||
ulint mbmaxlen;
|
||||
|
||||
dtype_get_mblen(type->mtype, type->prtype, &mbminlen, &mbmaxlen);
|
||||
dtype_set_mbminmaxlen(type, mbminlen, mbmaxlen);
|
||||
|
||||
ut_ad(dtype_validate(type));
|
||||
}
|
||||
#else /* !UNIV_HOTBACKUP */
|
||||
# define dtype_set_mblen(type) (void) 0
|
||||
#endif /* !UNIV_HOTBACKUP */
|
||||
|
||||
/*********************************************************************//**
|
||||
Sets a data type structure. */
|
||||
UNIV_INLINE
|
||||
void
|
||||
dtype_set(
|
||||
/*======*/
|
||||
dtype_t* type, /*!< in: type struct to init */
|
||||
ulint mtype, /*!< in: main data type */
|
||||
ulint prtype, /*!< in: precise type */
|
||||
ulint len) /*!< in: precision of type */
|
||||
{
|
||||
ut_ad(type);
|
||||
ut_ad(mtype <= DATA_MTYPE_MAX);
|
||||
|
||||
type->mtype = mtype;
|
||||
type->prtype = prtype;
|
||||
type->len = len;
|
||||
|
||||
dtype_set_mblen(type);
|
||||
}
|
||||
|
||||
/*********************************************************************//**
|
||||
Copies a data type structure. */
|
||||
UNIV_INLINE
|
||||
void
|
||||
dtype_copy(
|
||||
/*=======*/
|
||||
dtype_t* type1, /*!< in: type struct to copy to */
|
||||
const dtype_t* type2) /*!< in: type struct to copy from */
|
||||
{
|
||||
*type1 = *type2;
|
||||
|
||||
ut_ad(dtype_validate(type1));
|
||||
}
|
||||
|
||||
/*********************************************************************//**
|
||||
Gets the SQL main data type.
|
||||
@return SQL main data type */
|
||||
UNIV_INLINE
|
||||
ulint
|
||||
dtype_get_mtype(
|
||||
/*============*/
|
||||
const dtype_t* type) /*!< in: data type */
|
||||
{
|
||||
ut_ad(type);
|
||||
|
||||
return(type->mtype);
|
||||
}
|
||||
|
||||
/*********************************************************************//**
|
||||
Gets the precise data type.
|
||||
@return precise data type */
|
||||
UNIV_INLINE
|
||||
ulint
|
||||
dtype_get_prtype(
|
||||
/*=============*/
|
||||
const dtype_t* type) /*!< in: data type */
|
||||
{
|
||||
ut_ad(type);
|
||||
|
||||
return(type->prtype);
|
||||
}
|
||||
|
||||
/*********************************************************************//**
|
||||
Gets the type length.
|
||||
@return fixed length of the type, in bytes, or 0 if variable-length */
|
||||
UNIV_INLINE
|
||||
ulint
|
||||
dtype_get_len(
|
||||
/*==========*/
|
||||
const dtype_t* type) /*!< in: data type */
|
||||
{
|
||||
ut_ad(type);
|
||||
|
||||
return(type->len);
|
||||
}
|
||||
|
||||
#ifndef UNIV_HOTBACKUP
|
||||
/*********************************************************************//**
|
||||
Gets the minimum length of a character, in bytes.
|
||||
@return minimum length of a char, in bytes, or 0 if this is not a
|
||||
character type */
|
||||
UNIV_INLINE
|
||||
ulint
|
||||
dtype_get_mbminlen(
|
||||
/*===============*/
|
||||
const dtype_t* type) /*!< in: type */
|
||||
{
|
||||
ut_ad(type);
|
||||
return(DATA_MBMINLEN(type->mbminmaxlen));
|
||||
}
|
||||
/*********************************************************************//**
|
||||
Gets the maximum length of a character, in bytes.
|
||||
@return maximum length of a char, in bytes, or 0 if this is not a
|
||||
character type */
|
||||
UNIV_INLINE
|
||||
ulint
|
||||
dtype_get_mbmaxlen(
|
||||
/*===============*/
|
||||
const dtype_t* type) /*!< in: type */
|
||||
{
|
||||
ut_ad(type);
|
||||
return(DATA_MBMAXLEN(type->mbminmaxlen));
|
||||
}
|
||||
|
||||
/*********************************************************************//**
|
||||
Gets the padding character code for a type.
|
||||
@return padding character code, or ULINT_UNDEFINED if no padding specified */
|
||||
UNIV_INLINE
|
||||
ulint
|
||||
dtype_get_pad_char(
|
||||
/*===============*/
|
||||
ulint mtype, /*!< in: main type */
|
||||
ulint prtype) /*!< in: precise type */
|
||||
{
|
||||
switch (mtype) {
|
||||
case DATA_FIXBINARY:
|
||||
case DATA_BINARY:
|
||||
if (dtype_get_charset_coll(prtype)
|
||||
== DATA_MYSQL_BINARY_CHARSET_COLL) {
|
||||
/* Starting from 5.0.18, do not pad
|
||||
VARBINARY or BINARY columns. */
|
||||
return(ULINT_UNDEFINED);
|
||||
}
|
||||
/* Fall through */
|
||||
case DATA_CHAR:
|
||||
case DATA_VARCHAR:
|
||||
case DATA_MYSQL:
|
||||
case DATA_VARMYSQL:
|
||||
/* Space is the padding character for all char and binary
|
||||
strings, and starting from 5.0.3, also for TEXT strings. */
|
||||
|
||||
return(0x20);
|
||||
case DATA_BLOB:
|
||||
if (!(prtype & DATA_BINARY_TYPE)) {
|
||||
return(0x20);
|
||||
}
|
||||
/* Fall through */
|
||||
default:
|
||||
/* No padding specified */
|
||||
return(ULINT_UNDEFINED);
|
||||
}
|
||||
}
|
||||
|
||||
/**********************************************************************//**
|
||||
Stores for a type the information which determines its alphabetical ordering
|
||||
and the storage size of an SQL NULL value. This is the >= 4.1.x storage
|
||||
format. */
|
||||
UNIV_INLINE
|
||||
void
|
||||
dtype_new_store_for_order_and_null_size(
|
||||
/*====================================*/
|
||||
byte* buf, /*!< in: buffer for
|
||||
DATA_NEW_ORDER_NULL_TYPE_BUF_SIZE
|
||||
bytes where we store the info */
|
||||
const dtype_t* type, /*!< in: type struct */
|
||||
ulint prefix_len)/*!< in: prefix length to
|
||||
replace type->len, or 0 */
|
||||
{
|
||||
#if 6 != DATA_NEW_ORDER_NULL_TYPE_BUF_SIZE
|
||||
#error "6 != DATA_NEW_ORDER_NULL_TYPE_BUF_SIZE"
|
||||
#endif
|
||||
ulint len;
|
||||
|
||||
ut_ad(type);
|
||||
ut_ad(type->mtype >= DATA_VARCHAR);
|
||||
ut_ad(type->mtype <= DATA_MYSQL);
|
||||
|
||||
buf[0] = (byte)(type->mtype & 0xFFUL);
|
||||
|
||||
if (type->prtype & DATA_BINARY_TYPE) {
|
||||
buf[0] |= 128;
|
||||
}
|
||||
|
||||
/* In versions < 4.1.2 we had: if (type->prtype & DATA_NONLATIN1) {
|
||||
buf[0] |= 64;
|
||||
}
|
||||
*/
|
||||
|
||||
buf[1] = (byte)(type->prtype & 0xFFUL);
|
||||
|
||||
len = prefix_len ? prefix_len : type->len;
|
||||
|
||||
mach_write_to_2(buf + 2, len & 0xFFFFUL);
|
||||
|
||||
ut_ad(dtype_get_charset_coll(type->prtype) <= MAX_CHAR_COLL_NUM);
|
||||
mach_write_to_2(buf + 4, dtype_get_charset_coll(type->prtype));
|
||||
|
||||
if (type->prtype & DATA_NOT_NULL) {
|
||||
buf[4] |= 128;
|
||||
}
|
||||
}
|
||||
|
||||
/**********************************************************************//**
|
||||
Reads to a type the stored information which determines its alphabetical
|
||||
ordering and the storage size of an SQL NULL value. This is the < 4.1.x
|
||||
storage format. */
|
||||
UNIV_INLINE
|
||||
void
|
||||
dtype_read_for_order_and_null_size(
|
||||
/*===============================*/
|
||||
dtype_t* type, /*!< in: type struct */
|
||||
const byte* buf) /*!< in: buffer for stored type order info */
|
||||
{
|
||||
#if 4 != DATA_ORDER_NULL_TYPE_BUF_SIZE
|
||||
# error "4 != DATA_ORDER_NULL_TYPE_BUF_SIZE"
|
||||
#endif
|
||||
|
||||
type->mtype = buf[0] & 63;
|
||||
type->prtype = buf[1];
|
||||
|
||||
if (buf[0] & 128) {
|
||||
type->prtype |= DATA_BINARY_TYPE;
|
||||
}
|
||||
|
||||
type->len = mach_read_from_2(buf + 2);
|
||||
|
||||
type->prtype = dtype_form_prtype(type->prtype,
|
||||
data_mysql_default_charset_coll);
|
||||
dtype_set_mblen(type);
|
||||
}
|
||||
|
||||
/**********************************************************************//**
|
||||
Reads to a type the stored information which determines its alphabetical
|
||||
ordering and the storage size of an SQL NULL value. This is the >= 4.1.x
|
||||
storage format. */
|
||||
UNIV_INLINE
|
||||
void
|
||||
dtype_new_read_for_order_and_null_size(
|
||||
/*===================================*/
|
||||
dtype_t* type, /*!< in: type struct */
|
||||
const byte* buf) /*!< in: buffer for stored type order info */
|
||||
{
|
||||
ulint charset_coll;
|
||||
|
||||
#if 6 != DATA_NEW_ORDER_NULL_TYPE_BUF_SIZE
|
||||
#error "6 != DATA_NEW_ORDER_NULL_TYPE_BUF_SIZE"
|
||||
#endif
|
||||
|
||||
type->mtype = buf[0] & 63;
|
||||
type->prtype = buf[1];
|
||||
|
||||
if (buf[0] & 128) {
|
||||
type->prtype |= DATA_BINARY_TYPE;
|
||||
}
|
||||
|
||||
if (buf[4] & 128) {
|
||||
type->prtype |= DATA_NOT_NULL;
|
||||
}
|
||||
|
||||
type->len = mach_read_from_2(buf + 2);
|
||||
|
||||
charset_coll = mach_read_from_2(buf + 4) & CHAR_COLL_MASK;
|
||||
|
||||
if (dtype_is_string_type(type->mtype)) {
|
||||
ut_a(charset_coll <= MAX_CHAR_COLL_NUM);
|
||||
|
||||
if (charset_coll == 0) {
|
||||
/* This insert buffer record was inserted with MySQL
|
||||
version < 4.1.2, and the charset-collation code was not
|
||||
explicitly stored to dtype->prtype at that time. It
|
||||
must be the default charset-collation of this MySQL
|
||||
installation. */
|
||||
|
||||
charset_coll = data_mysql_default_charset_coll;
|
||||
}
|
||||
|
||||
type->prtype = dtype_form_prtype(type->prtype, charset_coll);
|
||||
}
|
||||
dtype_set_mblen(type);
|
||||
}
|
||||
|
||||
/*********************************************************************//**
|
||||
Returns the type's SQL name (e.g. BIGINT UNSIGNED) from mtype,prtype,len
|
||||
@return the SQL type name */
|
||||
UNIV_INLINE
|
||||
char*
|
||||
dtype_sql_name(
|
||||
/*===========*/
|
||||
unsigned mtype, /*!< in: mtype */
|
||||
unsigned prtype, /*!< in: prtype */
|
||||
unsigned len, /*!< in: len */
|
||||
char* name, /*!< out: SQL name */
|
||||
unsigned name_sz)/*!< in: size of the name buffer */
|
||||
{
|
||||
|
||||
#define APPEND_UNSIGNED() \
|
||||
do { \
|
||||
if (prtype & DATA_UNSIGNED) { \
|
||||
ut_snprintf(name + strlen(name), \
|
||||
name_sz - strlen(name), \
|
||||
" UNSIGNED"); \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
ut_snprintf(name, name_sz, "UNKNOWN");
|
||||
|
||||
switch (mtype) {
|
||||
case DATA_INT:
|
||||
switch (len) {
|
||||
case 1:
|
||||
ut_snprintf(name, name_sz, "TINYINT");
|
||||
break;
|
||||
case 2:
|
||||
ut_snprintf(name, name_sz, "SMALLINT");
|
||||
break;
|
||||
case 3:
|
||||
ut_snprintf(name, name_sz, "MEDIUMINT");
|
||||
break;
|
||||
case 4:
|
||||
ut_snprintf(name, name_sz, "INT");
|
||||
break;
|
||||
case 8:
|
||||
ut_snprintf(name, name_sz, "BIGINT");
|
||||
break;
|
||||
}
|
||||
APPEND_UNSIGNED();
|
||||
break;
|
||||
case DATA_FLOAT:
|
||||
ut_snprintf(name, name_sz, "FLOAT");
|
||||
APPEND_UNSIGNED();
|
||||
break;
|
||||
case DATA_DOUBLE:
|
||||
ut_snprintf(name, name_sz, "DOUBLE");
|
||||
APPEND_UNSIGNED();
|
||||
break;
|
||||
case DATA_FIXBINARY:
|
||||
ut_snprintf(name, name_sz, "BINARY(%u)", len);
|
||||
break;
|
||||
case DATA_CHAR:
|
||||
case DATA_MYSQL:
|
||||
ut_snprintf(name, name_sz, "CHAR(%u)", len);
|
||||
break;
|
||||
case DATA_VARCHAR:
|
||||
case DATA_VARMYSQL:
|
||||
ut_snprintf(name, name_sz, "VARCHAR(%u)", len);
|
||||
break;
|
||||
case DATA_BINARY:
|
||||
ut_snprintf(name, name_sz, "VARBINARY(%u)", len);
|
||||
break;
|
||||
case DATA_BLOB:
|
||||
switch (len) {
|
||||
case 9:
|
||||
ut_snprintf(name, name_sz, "TINYBLOB");
|
||||
break;
|
||||
case 10:
|
||||
ut_snprintf(name, name_sz, "BLOB");
|
||||
break;
|
||||
case 11:
|
||||
ut_snprintf(name, name_sz, "MEDIUMBLOB");
|
||||
break;
|
||||
case 12:
|
||||
ut_snprintf(name, name_sz, "LONGBLOB");
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (prtype & DATA_NOT_NULL) {
|
||||
ut_snprintf(name + strlen(name),
|
||||
name_sz - strlen(name),
|
||||
" NOT NULL");
|
||||
}
|
||||
|
||||
return(name);
|
||||
}
|
||||
|
||||
#endif /* !UNIV_HOTBACKUP */
|
||||
|
||||
/***********************************************************************//**
|
||||
Returns the size of a fixed size data type, 0 if not a fixed size type.
|
||||
@return fixed size, or 0 */
|
||||
UNIV_INLINE
|
||||
ulint
|
||||
dtype_get_fixed_size_low(
|
||||
/*=====================*/
|
||||
ulint mtype, /*!< in: main type */
|
||||
ulint prtype, /*!< in: precise type */
|
||||
ulint len, /*!< in: length */
|
||||
ulint mbminmaxlen, /*!< in: minimum and maximum length of
|
||||
a multibyte character, in bytes */
|
||||
ulint comp) /*!< in: nonzero=ROW_FORMAT=COMPACT */
|
||||
{
|
||||
switch (mtype) {
|
||||
case DATA_SYS:
|
||||
#ifdef UNIV_DEBUG
|
||||
switch (prtype & DATA_MYSQL_TYPE_MASK) {
|
||||
case DATA_ROW_ID:
|
||||
ut_ad(len == DATA_ROW_ID_LEN);
|
||||
break;
|
||||
case DATA_TRX_ID:
|
||||
ut_ad(len == DATA_TRX_ID_LEN);
|
||||
break;
|
||||
case DATA_ROLL_PTR:
|
||||
ut_ad(len == DATA_ROLL_PTR_LEN);
|
||||
break;
|
||||
default:
|
||||
ut_ad(0);
|
||||
return(0);
|
||||
}
|
||||
#endif /* UNIV_DEBUG */
|
||||
case DATA_CHAR:
|
||||
case DATA_FIXBINARY:
|
||||
case DATA_INT:
|
||||
case DATA_FLOAT:
|
||||
case DATA_DOUBLE:
|
||||
return(len);
|
||||
case DATA_MYSQL:
|
||||
#ifndef UNIV_HOTBACKUP
|
||||
if (prtype & DATA_BINARY_TYPE) {
|
||||
return(len);
|
||||
} else if (!comp) {
|
||||
return(len);
|
||||
} else {
|
||||
#ifdef UNIV_DEBUG
|
||||
ulint i_mbminlen, i_mbmaxlen;
|
||||
|
||||
innobase_get_cset_width(
|
||||
dtype_get_charset_coll(prtype),
|
||||
&i_mbminlen, &i_mbmaxlen);
|
||||
|
||||
ut_ad(DATA_MBMINMAXLEN(i_mbminlen, i_mbmaxlen)
|
||||
== mbminmaxlen);
|
||||
#endif /* UNIV_DEBUG */
|
||||
if (DATA_MBMINLEN(mbminmaxlen)
|
||||
== DATA_MBMAXLEN(mbminmaxlen)) {
|
||||
return(len);
|
||||
}
|
||||
}
|
||||
#else /* !UNIV_HOTBACKUP */
|
||||
return(len);
|
||||
#endif /* !UNIV_HOTBACKUP */
|
||||
/* fall through for variable-length charsets */
|
||||
case DATA_VARCHAR:
|
||||
case DATA_BINARY:
|
||||
case DATA_DECIMAL:
|
||||
case DATA_VARMYSQL:
|
||||
case DATA_BLOB:
|
||||
return(0);
|
||||
default:
|
||||
ut_error;
|
||||
}
|
||||
|
||||
return(0);
|
||||
}
|
||||
|
||||
#ifndef UNIV_HOTBACKUP
|
||||
/***********************************************************************//**
|
||||
Returns the minimum size of a data type.
|
||||
@return minimum size */
|
||||
UNIV_INLINE
|
||||
ulint
|
||||
dtype_get_min_size_low(
|
||||
/*===================*/
|
||||
ulint mtype, /*!< in: main type */
|
||||
ulint prtype, /*!< in: precise type */
|
||||
ulint len, /*!< in: length */
|
||||
ulint mbminmaxlen) /*!< in: minimum and maximum length of a
|
||||
multi-byte character */
|
||||
{
|
||||
switch (mtype) {
|
||||
case DATA_SYS:
|
||||
#ifdef UNIV_DEBUG
|
||||
switch (prtype & DATA_MYSQL_TYPE_MASK) {
|
||||
case DATA_ROW_ID:
|
||||
ut_ad(len == DATA_ROW_ID_LEN);
|
||||
break;
|
||||
case DATA_TRX_ID:
|
||||
ut_ad(len == DATA_TRX_ID_LEN);
|
||||
break;
|
||||
case DATA_ROLL_PTR:
|
||||
ut_ad(len == DATA_ROLL_PTR_LEN);
|
||||
break;
|
||||
default:
|
||||
ut_ad(0);
|
||||
return(0);
|
||||
}
|
||||
#endif /* UNIV_DEBUG */
|
||||
case DATA_CHAR:
|
||||
case DATA_FIXBINARY:
|
||||
case DATA_INT:
|
||||
case DATA_FLOAT:
|
||||
case DATA_DOUBLE:
|
||||
return(len);
|
||||
case DATA_MYSQL:
|
||||
if (prtype & DATA_BINARY_TYPE) {
|
||||
return(len);
|
||||
} else {
|
||||
ulint mbminlen = DATA_MBMINLEN(mbminmaxlen);
|
||||
ulint mbmaxlen = DATA_MBMAXLEN(mbminmaxlen);
|
||||
|
||||
if (mbminlen == mbmaxlen) {
|
||||
return(len);
|
||||
}
|
||||
|
||||
/* this is a variable-length character set */
|
||||
ut_a(mbminlen > 0);
|
||||
ut_a(mbmaxlen > mbminlen);
|
||||
ut_a(len % mbmaxlen == 0);
|
||||
return(len * mbminlen / mbmaxlen);
|
||||
}
|
||||
case DATA_VARCHAR:
|
||||
case DATA_BINARY:
|
||||
case DATA_DECIMAL:
|
||||
case DATA_VARMYSQL:
|
||||
case DATA_BLOB:
|
||||
return(0);
|
||||
default:
|
||||
ut_error;
|
||||
}
|
||||
|
||||
return(0);
|
||||
}
|
||||
|
||||
/***********************************************************************//**
|
||||
Returns the maximum size of a data type. Note: types in system tables may be
|
||||
incomplete and return incorrect information.
|
||||
@return maximum size */
|
||||
UNIV_INLINE
|
||||
ulint
|
||||
dtype_get_max_size_low(
|
||||
/*===================*/
|
||||
ulint mtype, /*!< in: main type */
|
||||
ulint len) /*!< in: length */
|
||||
{
|
||||
switch (mtype) {
|
||||
case DATA_SYS:
|
||||
case DATA_CHAR:
|
||||
case DATA_FIXBINARY:
|
||||
case DATA_INT:
|
||||
case DATA_FLOAT:
|
||||
case DATA_DOUBLE:
|
||||
case DATA_MYSQL:
|
||||
case DATA_VARCHAR:
|
||||
case DATA_BINARY:
|
||||
case DATA_DECIMAL:
|
||||
case DATA_VARMYSQL:
|
||||
return(len);
|
||||
case DATA_BLOB:
|
||||
break;
|
||||
default:
|
||||
ut_error;
|
||||
}
|
||||
|
||||
return(ULINT_MAX);
|
||||
}
|
||||
#endif /* !UNIV_HOTBACKUP */
|
||||
|
||||
/***********************************************************************//**
|
||||
Returns the ROW_FORMAT=REDUNDANT stored SQL NULL size of a type.
|
||||
For fixed length types it is the fixed length of the type, otherwise 0.
|
||||
@return SQL null storage size in ROW_FORMAT=REDUNDANT */
|
||||
UNIV_INLINE
|
||||
ulint
|
||||
dtype_get_sql_null_size(
|
||||
/*====================*/
|
||||
const dtype_t* type, /*!< in: type */
|
||||
ulint comp) /*!< in: nonzero=ROW_FORMAT=COMPACT */
|
||||
{
|
||||
#ifndef UNIV_HOTBACKUP
|
||||
return(dtype_get_fixed_size_low(type->mtype, type->prtype, type->len,
|
||||
type->mbminmaxlen, comp));
|
||||
#else /* !UNIV_HOTBACKUP */
|
||||
return(dtype_get_fixed_size_low(type->mtype, type->prtype, type->len,
|
||||
0, 0));
|
||||
#endif /* !UNIV_HOTBACKUP */
|
||||
}
|
||||
36
storage/innobase/include/data0types.h
Normal file
36
storage/innobase/include/data0types.h
Normal file
|
|
@ -0,0 +1,36 @@
|
|||
/*****************************************************************************
|
||||
|
||||
Copyright (c) 2000, 2009, Oracle and/or its affiliates. All Rights Reserved.
|
||||
|
||||
This program is free software; you can redistribute it and/or modify it under
|
||||
the terms of the GNU General Public License as published by the Free Software
|
||||
Foundation; version 2 of the License.
|
||||
|
||||
This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
|
||||
FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License along with
|
||||
this program; if not, write to the Free Software Foundation, Inc.,
|
||||
51 Franklin Street, Suite 500, Boston, MA 02110-1335 USA
|
||||
|
||||
*****************************************************************************/
|
||||
|
||||
/********************************************************************//**
|
||||
@file include/data0types.h
|
||||
Some type definitions
|
||||
|
||||
Created 9/21/2000 Heikki Tuuri
|
||||
*************************************************************************/
|
||||
|
||||
#ifndef data0types_h
|
||||
#define data0types_h
|
||||
|
||||
/* SQL data field struct */
|
||||
struct dfield_t;
|
||||
|
||||
/* SQL data tuple struct */
|
||||
struct dtuple_t;
|
||||
|
||||
#endif
|
||||
|
||||
161
storage/innobase/include/db0err.h
Normal file
161
storage/innobase/include/db0err.h
Normal file
|
|
@ -0,0 +1,161 @@
|
|||
/*****************************************************************************
|
||||
|
||||
Copyright (c) 1996, 2014, Oracle and/or its affiliates. All Rights Reserved.
|
||||
|
||||
This program is free software; you can redistribute it and/or modify it under
|
||||
the terms of the GNU General Public License as published by the Free Software
|
||||
Foundation; version 2 of the License.
|
||||
|
||||
This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
|
||||
FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License along with
|
||||
this program; if not, write to the Free Software Foundation, Inc.,
|
||||
51 Franklin Street, Suite 500, Boston, MA 02110-1335 USA
|
||||
|
||||
*****************************************************************************/
|
||||
|
||||
/**************************************************//**
|
||||
@file include/db0err.h
|
||||
Global error codes for the database
|
||||
|
||||
Created 5/24/1996 Heikki Tuuri
|
||||
*******************************************************/
|
||||
|
||||
#ifndef db0err_h
|
||||
#define db0err_h
|
||||
|
||||
|
||||
enum dberr_t {
|
||||
DB_SUCCESS_LOCKED_REC = 9, /*!< like DB_SUCCESS, but a new
|
||||
explicit record lock was created */
|
||||
DB_SUCCESS = 10,
|
||||
|
||||
/* The following are error codes */
|
||||
DB_ERROR,
|
||||
DB_INTERRUPTED,
|
||||
DB_OUT_OF_MEMORY,
|
||||
DB_OUT_OF_FILE_SPACE,
|
||||
DB_LOCK_WAIT,
|
||||
DB_DEADLOCK,
|
||||
DB_ROLLBACK,
|
||||
DB_DUPLICATE_KEY,
|
||||
DB_QUE_THR_SUSPENDED,
|
||||
DB_MISSING_HISTORY, /*!< required history data has been
|
||||
deleted due to lack of space in
|
||||
rollback segment */
|
||||
DB_CLUSTER_NOT_FOUND = 30,
|
||||
DB_TABLE_NOT_FOUND,
|
||||
DB_MUST_GET_MORE_FILE_SPACE, /*!< the database has to be stopped
|
||||
and restarted with more file space */
|
||||
DB_TABLE_IS_BEING_USED,
|
||||
DB_TOO_BIG_RECORD, /*!< a record in an index would not fit
|
||||
on a compressed page, or it would
|
||||
become bigger than 1/2 free space in
|
||||
an uncompressed page frame */
|
||||
DB_LOCK_WAIT_TIMEOUT, /*!< lock wait lasted too long */
|
||||
DB_NO_REFERENCED_ROW, /*!< referenced key value not found
|
||||
for a foreign key in an insert or
|
||||
update of a row */
|
||||
DB_ROW_IS_REFERENCED, /*!< cannot delete or update a row
|
||||
because it contains a key value
|
||||
which is referenced */
|
||||
DB_CANNOT_ADD_CONSTRAINT, /*!< adding a foreign key constraint
|
||||
to a table failed */
|
||||
DB_CORRUPTION, /*!< data structure corruption noticed */
|
||||
DB_CANNOT_DROP_CONSTRAINT, /*!< dropping a foreign key constraint
|
||||
from a table failed */
|
||||
DB_NO_SAVEPOINT, /*!< no savepoint exists with the given
|
||||
name */
|
||||
DB_TABLESPACE_EXISTS, /*!< we cannot create a new single-table
|
||||
tablespace because a file of the same
|
||||
name already exists */
|
||||
DB_TABLESPACE_DELETED, /*!< tablespace was deleted or is
|
||||
being dropped right now */
|
||||
DB_TABLESPACE_NOT_FOUND, /*<! Attempt to delete a tablespace
|
||||
instance that was not found in the
|
||||
tablespace hash table */
|
||||
DB_LOCK_TABLE_FULL, /*!< lock structs have exhausted the
|
||||
buffer pool (for big transactions,
|
||||
InnoDB stores the lock structs in the
|
||||
buffer pool) */
|
||||
DB_FOREIGN_DUPLICATE_KEY, /*!< foreign key constraints
|
||||
activated by the operation would
|
||||
lead to a duplicate key in some
|
||||
table */
|
||||
DB_TOO_MANY_CONCURRENT_TRXS, /*!< when InnoDB runs out of the
|
||||
preconfigured undo slots, this can
|
||||
only happen when there are too many
|
||||
concurrent transactions */
|
||||
DB_UNSUPPORTED, /*!< when InnoDB sees any artefact or
|
||||
a feature that it can't recoginize or
|
||||
work with e.g., FT indexes created by
|
||||
a later version of the engine. */
|
||||
|
||||
DB_INVALID_NULL, /*!< a NOT NULL column was found to
|
||||
be NULL during table rebuild */
|
||||
|
||||
DB_STATS_DO_NOT_EXIST, /*!< an operation that requires the
|
||||
persistent storage, used for recording
|
||||
table and index statistics, was
|
||||
requested but this storage does not
|
||||
exist itself or the stats for a given
|
||||
table do not exist */
|
||||
DB_FOREIGN_EXCEED_MAX_CASCADE, /*!< Foreign key constraint related
|
||||
cascading delete/update exceeds
|
||||
maximum allowed depth */
|
||||
DB_CHILD_NO_INDEX, /*!< the child (foreign) table does
|
||||
not have an index that contains the
|
||||
foreign keys as its prefix columns */
|
||||
DB_PARENT_NO_INDEX, /*!< the parent table does not
|
||||
have an index that contains the
|
||||
foreign keys as its prefix columns */
|
||||
DB_TOO_BIG_INDEX_COL, /*!< index column size exceeds
|
||||
maximum limit */
|
||||
DB_INDEX_CORRUPT, /*!< we have corrupted index */
|
||||
DB_UNDO_RECORD_TOO_BIG, /*!< the undo log record is too big */
|
||||
DB_READ_ONLY, /*!< Update operation attempted in
|
||||
a read-only transaction */
|
||||
DB_FTS_INVALID_DOCID, /* FTS Doc ID cannot be zero */
|
||||
DB_TABLE_IN_FK_CHECK, /* table is being used in foreign
|
||||
key check */
|
||||
DB_ONLINE_LOG_TOO_BIG, /*!< Modification log grew too big
|
||||
during online index creation */
|
||||
|
||||
DB_IO_ERROR, /*!< Generic IO error */
|
||||
DB_IDENTIFIER_TOO_LONG, /*!< Identifier name too long */
|
||||
DB_FTS_EXCEED_RESULT_CACHE_LIMIT, /*!< FTS query memory
|
||||
exceeds result cache limit */
|
||||
DB_TEMP_FILE_WRITE_FAILURE, /*!< Temp file write failure */
|
||||
DB_FTS_TOO_MANY_WORDS_IN_PHRASE,
|
||||
/*< Too many words in a phrase */
|
||||
DB_TOO_BIG_FOR_REDO, /* Record length greater than 10%
|
||||
of redo log */
|
||||
/* The following are partial failure codes */
|
||||
DB_FAIL = 1000,
|
||||
DB_OVERFLOW,
|
||||
DB_UNDERFLOW,
|
||||
DB_STRONG_FAIL,
|
||||
DB_ZIP_OVERFLOW,
|
||||
DB_RECORD_NOT_FOUND = 1500,
|
||||
DB_END_OF_INDEX,
|
||||
DB_DICT_CHANGED, /*!< Some part of table dictionary has
|
||||
changed. Such as index dropped or
|
||||
foreign key dropped */
|
||||
|
||||
|
||||
/* The following are API only error codes. */
|
||||
DB_DATA_MISMATCH = 2000, /*!< Column update or read failed
|
||||
because the types mismatch */
|
||||
|
||||
DB_SCHEMA_NOT_LOCKED, /*!< If an API function expects the
|
||||
schema to be locked in exclusive mode
|
||||
and if it's not then that API function
|
||||
will return this error code */
|
||||
|
||||
DB_NOT_FOUND /*!< Generic error code for "Not found"
|
||||
type of errors */
|
||||
};
|
||||
|
||||
#endif
|
||||
342
storage/innobase/include/dict0boot.h
Normal file
342
storage/innobase/include/dict0boot.h
Normal file
|
|
@ -0,0 +1,342 @@
|
|||
/*****************************************************************************
|
||||
|
||||
Copyright (c) 1996, 2012, Oracle and/or its affiliates. All Rights Reserved.
|
||||
|
||||
This program is free software; you can redistribute it and/or modify it under
|
||||
the terms of the GNU General Public License as published by the Free Software
|
||||
Foundation; version 2 of the License.
|
||||
|
||||
This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
|
||||
FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License along with
|
||||
this program; if not, write to the Free Software Foundation, Inc.,
|
||||
51 Franklin Street, Suite 500, Boston, MA 02110-1335 USA
|
||||
|
||||
*****************************************************************************/
|
||||
|
||||
/**************************************************//**
|
||||
@file include/dict0boot.h
|
||||
Data dictionary creation and booting
|
||||
|
||||
Created 4/18/1996 Heikki Tuuri
|
||||
*******************************************************/
|
||||
|
||||
#ifndef dict0boot_h
|
||||
#define dict0boot_h
|
||||
|
||||
#include "univ.i"
|
||||
|
||||
#include "mtr0mtr.h"
|
||||
#include "mtr0log.h"
|
||||
#include "ut0byte.h"
|
||||
#include "buf0buf.h"
|
||||
#include "fsp0fsp.h"
|
||||
#include "dict0dict.h"
|
||||
|
||||
typedef byte dict_hdr_t;
|
||||
|
||||
/**********************************************************************//**
|
||||
Gets a pointer to the dictionary header and x-latches its page.
|
||||
@return pointer to the dictionary header, page x-latched */
|
||||
UNIV_INTERN
|
||||
dict_hdr_t*
|
||||
dict_hdr_get(
|
||||
/*=========*/
|
||||
mtr_t* mtr); /*!< in: mtr */
|
||||
/**********************************************************************//**
|
||||
Returns a new table, index, or space id. */
|
||||
UNIV_INTERN
|
||||
void
|
||||
dict_hdr_get_new_id(
|
||||
/*================*/
|
||||
table_id_t* table_id, /*!< out: table id
|
||||
(not assigned if NULL) */
|
||||
index_id_t* index_id, /*!< out: index id
|
||||
(not assigned if NULL) */
|
||||
ulint* space_id); /*!< out: space id
|
||||
(not assigned if NULL) */
|
||||
/**********************************************************************//**
|
||||
Writes the current value of the row id counter to the dictionary header file
|
||||
page. */
|
||||
UNIV_INTERN
|
||||
void
|
||||
dict_hdr_flush_row_id(void);
|
||||
/*=======================*/
|
||||
/**********************************************************************//**
|
||||
Returns a new row id.
|
||||
@return the new id */
|
||||
UNIV_INLINE
|
||||
row_id_t
|
||||
dict_sys_get_new_row_id(void);
|
||||
/*=========================*/
|
||||
/**********************************************************************//**
|
||||
Reads a row id from a record or other 6-byte stored form.
|
||||
@return row id */
|
||||
UNIV_INLINE
|
||||
row_id_t
|
||||
dict_sys_read_row_id(
|
||||
/*=================*/
|
||||
const byte* field); /*!< in: record field */
|
||||
/**********************************************************************//**
|
||||
Writes a row id to a record or other 6-byte stored form. */
|
||||
UNIV_INLINE
|
||||
void
|
||||
dict_sys_write_row_id(
|
||||
/*==================*/
|
||||
byte* field, /*!< in: record field */
|
||||
row_id_t row_id);/*!< in: row id */
|
||||
/*****************************************************************//**
|
||||
Initializes the data dictionary memory structures when the database is
|
||||
started. This function is also called when the data dictionary is created.
|
||||
@return DB_SUCCESS or error code. */
|
||||
UNIV_INTERN
|
||||
dberr_t
|
||||
dict_boot(void)
|
||||
/*===========*/
|
||||
__attribute__((warn_unused_result));
|
||||
|
||||
/*****************************************************************//**
|
||||
Creates and initializes the data dictionary at the server bootstrap.
|
||||
@return DB_SUCCESS or error code. */
|
||||
UNIV_INTERN
|
||||
dberr_t
|
||||
dict_create(void)
|
||||
/*=============*/
|
||||
__attribute__((warn_unused_result));
|
||||
|
||||
/*********************************************************************//**
|
||||
Check if a table id belongs to system table.
|
||||
@return true if the table id belongs to a system table. */
|
||||
UNIV_INLINE
|
||||
bool
|
||||
dict_is_sys_table(
|
||||
/*==============*/
|
||||
table_id_t id) /*!< in: table id to check */
|
||||
__attribute__((warn_unused_result));
|
||||
|
||||
/* Space id and page no where the dictionary header resides */
|
||||
#define DICT_HDR_SPACE 0 /* the SYSTEM tablespace */
|
||||
#define DICT_HDR_PAGE_NO FSP_DICT_HDR_PAGE_NO
|
||||
|
||||
/* The ids for the basic system tables and their indexes */
|
||||
#define DICT_TABLES_ID 1
|
||||
#define DICT_COLUMNS_ID 2
|
||||
#define DICT_INDEXES_ID 3
|
||||
#define DICT_FIELDS_ID 4
|
||||
/* The following is a secondary index on SYS_TABLES */
|
||||
#define DICT_TABLE_IDS_ID 5
|
||||
|
||||
#define DICT_HDR_FIRST_ID 10 /* the ids for tables etc. start
|
||||
from this number, except for basic
|
||||
system tables and their above defined
|
||||
indexes; ibuf tables and indexes are
|
||||
assigned as the id the number
|
||||
DICT_IBUF_ID_MIN plus the space id */
|
||||
|
||||
/* The offset of the dictionary header on the page */
|
||||
#define DICT_HDR FSEG_PAGE_DATA
|
||||
|
||||
/*-------------------------------------------------------------*/
|
||||
/* Dictionary header offsets */
|
||||
#define DICT_HDR_ROW_ID 0 /* The latest assigned row id */
|
||||
#define DICT_HDR_TABLE_ID 8 /* The latest assigned table id */
|
||||
#define DICT_HDR_INDEX_ID 16 /* The latest assigned index id */
|
||||
#define DICT_HDR_MAX_SPACE_ID 24 /* The latest assigned space id,or 0*/
|
||||
#define DICT_HDR_MIX_ID_LOW 28 /* Obsolete,always DICT_HDR_FIRST_ID*/
|
||||
#define DICT_HDR_TABLES 32 /* Root of SYS_TABLES clust index */
|
||||
#define DICT_HDR_TABLE_IDS 36 /* Root of SYS_TABLE_IDS sec index */
|
||||
#define DICT_HDR_COLUMNS 40 /* Root of SYS_COLUMNS clust index */
|
||||
#define DICT_HDR_INDEXES 44 /* Root of SYS_INDEXES clust index */
|
||||
#define DICT_HDR_FIELDS 48 /* Root of SYS_FIELDS clust index */
|
||||
|
||||
#define DICT_HDR_FSEG_HEADER 56 /* Segment header for the tablespace
|
||||
segment into which the dictionary
|
||||
header is created */
|
||||
/*-------------------------------------------------------------*/
|
||||
|
||||
/* The columns in SYS_TABLES */
|
||||
enum dict_col_sys_tables_enum {
|
||||
DICT_COL__SYS_TABLES__NAME = 0,
|
||||
DICT_COL__SYS_TABLES__ID = 1,
|
||||
DICT_COL__SYS_TABLES__N_COLS = 2,
|
||||
DICT_COL__SYS_TABLES__TYPE = 3,
|
||||
DICT_COL__SYS_TABLES__MIX_ID = 4,
|
||||
DICT_COL__SYS_TABLES__MIX_LEN = 5,
|
||||
DICT_COL__SYS_TABLES__CLUSTER_ID = 6,
|
||||
DICT_COL__SYS_TABLES__SPACE = 7,
|
||||
DICT_NUM_COLS__SYS_TABLES = 8
|
||||
};
|
||||
/* The field numbers in the SYS_TABLES clustered index */
|
||||
enum dict_fld_sys_tables_enum {
|
||||
DICT_FLD__SYS_TABLES__NAME = 0,
|
||||
DICT_FLD__SYS_TABLES__DB_TRX_ID = 1,
|
||||
DICT_FLD__SYS_TABLES__DB_ROLL_PTR = 2,
|
||||
DICT_FLD__SYS_TABLES__ID = 3,
|
||||
DICT_FLD__SYS_TABLES__N_COLS = 4,
|
||||
DICT_FLD__SYS_TABLES__TYPE = 5,
|
||||
DICT_FLD__SYS_TABLES__MIX_ID = 6,
|
||||
DICT_FLD__SYS_TABLES__MIX_LEN = 7,
|
||||
DICT_FLD__SYS_TABLES__CLUSTER_ID = 8,
|
||||
DICT_FLD__SYS_TABLES__SPACE = 9,
|
||||
DICT_NUM_FIELDS__SYS_TABLES = 10
|
||||
};
|
||||
/* The field numbers in the SYS_TABLE_IDS index */
|
||||
enum dict_fld_sys_table_ids_enum {
|
||||
DICT_FLD__SYS_TABLE_IDS__ID = 0,
|
||||
DICT_FLD__SYS_TABLE_IDS__NAME = 1,
|
||||
DICT_NUM_FIELDS__SYS_TABLE_IDS = 2
|
||||
};
|
||||
/* The columns in SYS_COLUMNS */
|
||||
enum dict_col_sys_columns_enum {
|
||||
DICT_COL__SYS_COLUMNS__TABLE_ID = 0,
|
||||
DICT_COL__SYS_COLUMNS__POS = 1,
|
||||
DICT_COL__SYS_COLUMNS__NAME = 2,
|
||||
DICT_COL__SYS_COLUMNS__MTYPE = 3,
|
||||
DICT_COL__SYS_COLUMNS__PRTYPE = 4,
|
||||
DICT_COL__SYS_COLUMNS__LEN = 5,
|
||||
DICT_COL__SYS_COLUMNS__PREC = 6,
|
||||
DICT_NUM_COLS__SYS_COLUMNS = 7
|
||||
};
|
||||
/* The field numbers in the SYS_COLUMNS clustered index */
|
||||
enum dict_fld_sys_columns_enum {
|
||||
DICT_FLD__SYS_COLUMNS__TABLE_ID = 0,
|
||||
DICT_FLD__SYS_COLUMNS__POS = 1,
|
||||
DICT_FLD__SYS_COLUMNS__DB_TRX_ID = 2,
|
||||
DICT_FLD__SYS_COLUMNS__DB_ROLL_PTR = 3,
|
||||
DICT_FLD__SYS_COLUMNS__NAME = 4,
|
||||
DICT_FLD__SYS_COLUMNS__MTYPE = 5,
|
||||
DICT_FLD__SYS_COLUMNS__PRTYPE = 6,
|
||||
DICT_FLD__SYS_COLUMNS__LEN = 7,
|
||||
DICT_FLD__SYS_COLUMNS__PREC = 8,
|
||||
DICT_NUM_FIELDS__SYS_COLUMNS = 9
|
||||
};
|
||||
/* The columns in SYS_INDEXES */
|
||||
enum dict_col_sys_indexes_enum {
|
||||
DICT_COL__SYS_INDEXES__TABLE_ID = 0,
|
||||
DICT_COL__SYS_INDEXES__ID = 1,
|
||||
DICT_COL__SYS_INDEXES__NAME = 2,
|
||||
DICT_COL__SYS_INDEXES__N_FIELDS = 3,
|
||||
DICT_COL__SYS_INDEXES__TYPE = 4,
|
||||
DICT_COL__SYS_INDEXES__SPACE = 5,
|
||||
DICT_COL__SYS_INDEXES__PAGE_NO = 6,
|
||||
DICT_NUM_COLS__SYS_INDEXES = 7
|
||||
};
|
||||
/* The field numbers in the SYS_INDEXES clustered index */
|
||||
enum dict_fld_sys_indexes_enum {
|
||||
DICT_FLD__SYS_INDEXES__TABLE_ID = 0,
|
||||
DICT_FLD__SYS_INDEXES__ID = 1,
|
||||
DICT_FLD__SYS_INDEXES__DB_TRX_ID = 2,
|
||||
DICT_FLD__SYS_INDEXES__DB_ROLL_PTR = 3,
|
||||
DICT_FLD__SYS_INDEXES__NAME = 4,
|
||||
DICT_FLD__SYS_INDEXES__N_FIELDS = 5,
|
||||
DICT_FLD__SYS_INDEXES__TYPE = 6,
|
||||
DICT_FLD__SYS_INDEXES__SPACE = 7,
|
||||
DICT_FLD__SYS_INDEXES__PAGE_NO = 8,
|
||||
DICT_NUM_FIELDS__SYS_INDEXES = 9
|
||||
};
|
||||
/* The columns in SYS_FIELDS */
|
||||
enum dict_col_sys_fields_enum {
|
||||
DICT_COL__SYS_FIELDS__INDEX_ID = 0,
|
||||
DICT_COL__SYS_FIELDS__POS = 1,
|
||||
DICT_COL__SYS_FIELDS__COL_NAME = 2,
|
||||
DICT_NUM_COLS__SYS_FIELDS = 3
|
||||
};
|
||||
/* The field numbers in the SYS_FIELDS clustered index */
|
||||
enum dict_fld_sys_fields_enum {
|
||||
DICT_FLD__SYS_FIELDS__INDEX_ID = 0,
|
||||
DICT_FLD__SYS_FIELDS__POS = 1,
|
||||
DICT_FLD__SYS_FIELDS__DB_TRX_ID = 2,
|
||||
DICT_FLD__SYS_FIELDS__DB_ROLL_PTR = 3,
|
||||
DICT_FLD__SYS_FIELDS__COL_NAME = 4,
|
||||
DICT_NUM_FIELDS__SYS_FIELDS = 5
|
||||
};
|
||||
/* The columns in SYS_FOREIGN */
|
||||
enum dict_col_sys_foreign_enum {
|
||||
DICT_COL__SYS_FOREIGN__ID = 0,
|
||||
DICT_COL__SYS_FOREIGN__FOR_NAME = 1,
|
||||
DICT_COL__SYS_FOREIGN__REF_NAME = 2,
|
||||
DICT_COL__SYS_FOREIGN__N_COLS = 3,
|
||||
DICT_NUM_COLS__SYS_FOREIGN = 4
|
||||
};
|
||||
/* The field numbers in the SYS_FOREIGN clustered index */
|
||||
enum dict_fld_sys_foreign_enum {
|
||||
DICT_FLD__SYS_FOREIGN__ID = 0,
|
||||
DICT_FLD__SYS_FOREIGN__DB_TRX_ID = 1,
|
||||
DICT_FLD__SYS_FOREIGN__DB_ROLL_PTR = 2,
|
||||
DICT_FLD__SYS_FOREIGN__FOR_NAME = 3,
|
||||
DICT_FLD__SYS_FOREIGN__REF_NAME = 4,
|
||||
DICT_FLD__SYS_FOREIGN__N_COLS = 5,
|
||||
DICT_NUM_FIELDS__SYS_FOREIGN = 6
|
||||
};
|
||||
/* The field numbers in the SYS_FOREIGN_FOR_NAME secondary index */
|
||||
enum dict_fld_sys_foreign_for_name_enum {
|
||||
DICT_FLD__SYS_FOREIGN_FOR_NAME__NAME = 0,
|
||||
DICT_FLD__SYS_FOREIGN_FOR_NAME__ID = 1,
|
||||
DICT_NUM_FIELDS__SYS_FOREIGN_FOR_NAME = 2
|
||||
};
|
||||
/* The columns in SYS_FOREIGN_COLS */
|
||||
enum dict_col_sys_foreign_cols_enum {
|
||||
DICT_COL__SYS_FOREIGN_COLS__ID = 0,
|
||||
DICT_COL__SYS_FOREIGN_COLS__POS = 1,
|
||||
DICT_COL__SYS_FOREIGN_COLS__FOR_COL_NAME = 2,
|
||||
DICT_COL__SYS_FOREIGN_COLS__REF_COL_NAME = 3,
|
||||
DICT_NUM_COLS__SYS_FOREIGN_COLS = 4
|
||||
};
|
||||
/* The field numbers in the SYS_FOREIGN_COLS clustered index */
|
||||
enum dict_fld_sys_foreign_cols_enum {
|
||||
DICT_FLD__SYS_FOREIGN_COLS__ID = 0,
|
||||
DICT_FLD__SYS_FOREIGN_COLS__POS = 1,
|
||||
DICT_FLD__SYS_FOREIGN_COLS__DB_TRX_ID = 2,
|
||||
DICT_FLD__SYS_FOREIGN_COLS__DB_ROLL_PTR = 3,
|
||||
DICT_FLD__SYS_FOREIGN_COLS__FOR_COL_NAME = 4,
|
||||
DICT_FLD__SYS_FOREIGN_COLS__REF_COL_NAME = 5,
|
||||
DICT_NUM_FIELDS__SYS_FOREIGN_COLS = 6
|
||||
};
|
||||
/* The columns in SYS_TABLESPACES */
|
||||
enum dict_col_sys_tablespaces_enum {
|
||||
DICT_COL__SYS_TABLESPACES__SPACE = 0,
|
||||
DICT_COL__SYS_TABLESPACES__NAME = 1,
|
||||
DICT_COL__SYS_TABLESPACES__FLAGS = 2,
|
||||
DICT_NUM_COLS__SYS_TABLESPACES = 3
|
||||
};
|
||||
/* The field numbers in the SYS_TABLESPACES clustered index */
|
||||
enum dict_fld_sys_tablespaces_enum {
|
||||
DICT_FLD__SYS_TABLESPACES__SPACE = 0,
|
||||
DICT_FLD__SYS_TABLESPACES__DB_TRX_ID = 1,
|
||||
DICT_FLD__SYS_TABLESPACES__DB_ROLL_PTR = 2,
|
||||
DICT_FLD__SYS_TABLESPACES__NAME = 3,
|
||||
DICT_FLD__SYS_TABLESPACES__FLAGS = 4,
|
||||
DICT_NUM_FIELDS__SYS_TABLESPACES = 5
|
||||
};
|
||||
/* The columns in SYS_DATAFILES */
|
||||
enum dict_col_sys_datafiles_enum {
|
||||
DICT_COL__SYS_DATAFILES__SPACE = 0,
|
||||
DICT_COL__SYS_DATAFILES__PATH = 1,
|
||||
DICT_NUM_COLS__SYS_DATAFILES = 2
|
||||
};
|
||||
/* The field numbers in the SYS_DATAFILES clustered index */
|
||||
enum dict_fld_sys_datafiles_enum {
|
||||
DICT_FLD__SYS_DATAFILES__SPACE = 0,
|
||||
DICT_FLD__SYS_DATAFILES__DB_TRX_ID = 1,
|
||||
DICT_FLD__SYS_DATAFILES__DB_ROLL_PTR = 2,
|
||||
DICT_FLD__SYS_DATAFILES__PATH = 3,
|
||||
DICT_NUM_FIELDS__SYS_DATAFILES = 4
|
||||
};
|
||||
|
||||
/* A number of the columns above occur in multiple tables. These are the
|
||||
length of thos fields. */
|
||||
#define DICT_FLD_LEN_SPACE 4
|
||||
#define DICT_FLD_LEN_FLAGS 4
|
||||
|
||||
/* When a row id which is zero modulo this number (which must be a power of
|
||||
two) is assigned, the field DICT_HDR_ROW_ID on the dictionary header page is
|
||||
updated */
|
||||
#define DICT_HDR_ROW_ID_WRITE_MARGIN 256
|
||||
|
||||
#ifndef UNIV_NONINL
|
||||
#include "dict0boot.ic"
|
||||
#endif
|
||||
|
||||
#endif
|
||||
96
storage/innobase/include/dict0boot.ic
Normal file
96
storage/innobase/include/dict0boot.ic
Normal file
|
|
@ -0,0 +1,96 @@
|
|||
/*****************************************************************************
|
||||
|
||||
Copyright (c) 1996, 2012, Oracle and/or its affiliates. All Rights Reserved.
|
||||
|
||||
This program is free software; you can redistribute it and/or modify it under
|
||||
the terms of the GNU General Public License as published by the Free Software
|
||||
Foundation; version 2 of the License.
|
||||
|
||||
This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
|
||||
FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License along with
|
||||
this program; if not, write to the Free Software Foundation, Inc.,
|
||||
51 Franklin Street, Suite 500, Boston, MA 02110-1335 USA
|
||||
|
||||
*****************************************************************************/
|
||||
|
||||
/**************************************************//**
|
||||
@file include/dict0boot.ic
|
||||
Data dictionary creation and booting
|
||||
|
||||
Created 4/18/1996 Heikki Tuuri
|
||||
*******************************************************/
|
||||
|
||||
/**********************************************************************//**
|
||||
Returns a new row id.
|
||||
@return the new id */
|
||||
UNIV_INLINE
|
||||
row_id_t
|
||||
dict_sys_get_new_row_id(void)
|
||||
/*=========================*/
|
||||
{
|
||||
row_id_t id;
|
||||
|
||||
mutex_enter(&(dict_sys->mutex));
|
||||
|
||||
id = dict_sys->row_id;
|
||||
|
||||
if (0 == (id % DICT_HDR_ROW_ID_WRITE_MARGIN)) {
|
||||
|
||||
dict_hdr_flush_row_id();
|
||||
}
|
||||
|
||||
dict_sys->row_id++;
|
||||
|
||||
mutex_exit(&(dict_sys->mutex));
|
||||
|
||||
return(id);
|
||||
}
|
||||
|
||||
/**********************************************************************//**
|
||||
Reads a row id from a record or other 6-byte stored form.
|
||||
@return row id */
|
||||
UNIV_INLINE
|
||||
row_id_t
|
||||
dict_sys_read_row_id(
|
||||
/*=================*/
|
||||
const byte* field) /*!< in: record field */
|
||||
{
|
||||
#if DATA_ROW_ID_LEN != 6
|
||||
# error "DATA_ROW_ID_LEN != 6"
|
||||
#endif
|
||||
|
||||
return(mach_read_from_6(field));
|
||||
}
|
||||
|
||||
/**********************************************************************//**
|
||||
Writes a row id to a record or other 6-byte stored form. */
|
||||
UNIV_INLINE
|
||||
void
|
||||
dict_sys_write_row_id(
|
||||
/*==================*/
|
||||
byte* field, /*!< in: record field */
|
||||
row_id_t row_id) /*!< in: row id */
|
||||
{
|
||||
#if DATA_ROW_ID_LEN != 6
|
||||
# error "DATA_ROW_ID_LEN != 6"
|
||||
#endif
|
||||
|
||||
mach_write_to_6(field, row_id);
|
||||
}
|
||||
|
||||
/*********************************************************************//**
|
||||
Check if a table id belongs to system table.
|
||||
@return true if the table id belongs to a system table. */
|
||||
UNIV_INLINE
|
||||
bool
|
||||
dict_is_sys_table(
|
||||
/*==============*/
|
||||
table_id_t id) /*!< in: table id to check */
|
||||
{
|
||||
return(id < DICT_HDR_FIRST_ID);
|
||||
}
|
||||
|
||||
|
||||
246
storage/innobase/include/dict0crea.h
Normal file
246
storage/innobase/include/dict0crea.h
Normal file
|
|
@ -0,0 +1,246 @@
|
|||
/*****************************************************************************
|
||||
|
||||
Copyright (c) 1996, 2014, Oracle and/or its affiliates. All Rights Reserved.
|
||||
|
||||
This program is free software; you can redistribute it and/or modify it under
|
||||
the terms of the GNU General Public License as published by the Free Software
|
||||
Foundation; version 2 of the License.
|
||||
|
||||
This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
|
||||
FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License along with
|
||||
this program; if not, write to the Free Software Foundation, Inc.,
|
||||
51 Franklin Street, Suite 500, Boston, MA 02110-1335 USA
|
||||
|
||||
*****************************************************************************/
|
||||
|
||||
/**************************************************//**
|
||||
@file include/dict0crea.h
|
||||
Database object creation
|
||||
|
||||
Created 1/8/1996 Heikki Tuuri
|
||||
*******************************************************/
|
||||
|
||||
#ifndef dict0crea_h
|
||||
#define dict0crea_h
|
||||
|
||||
#include "univ.i"
|
||||
#include "dict0types.h"
|
||||
#include "dict0dict.h"
|
||||
#include "que0types.h"
|
||||
#include "row0types.h"
|
||||
#include "mtr0mtr.h"
|
||||
|
||||
/*********************************************************************//**
|
||||
Creates a table create graph.
|
||||
@return own: table create node */
|
||||
UNIV_INTERN
|
||||
tab_node_t*
|
||||
tab_create_graph_create(
|
||||
/*====================*/
|
||||
dict_table_t* table, /*!< in: table to create, built as a memory data
|
||||
structure */
|
||||
mem_heap_t* heap, /*!< in: heap where created */
|
||||
bool commit);/*!< in: true if the commit node should be
|
||||
added to the query graph */
|
||||
/*********************************************************************//**
|
||||
Creates an index create graph.
|
||||
@return own: index create node */
|
||||
UNIV_INTERN
|
||||
ind_node_t*
|
||||
ind_create_graph_create(
|
||||
/*====================*/
|
||||
dict_index_t* index, /*!< in: index to create, built as a memory data
|
||||
structure */
|
||||
mem_heap_t* heap, /*!< in: heap where created */
|
||||
bool commit);/*!< in: true if the commit node should be
|
||||
added to the query graph */
|
||||
/***********************************************************//**
|
||||
Creates a table. This is a high-level function used in SQL execution graphs.
|
||||
@return query thread to run next or NULL */
|
||||
UNIV_INTERN
|
||||
que_thr_t*
|
||||
dict_create_table_step(
|
||||
/*===================*/
|
||||
que_thr_t* thr); /*!< in: query thread */
|
||||
/***********************************************************//**
|
||||
Creates an index. This is a high-level function used in SQL execution
|
||||
graphs.
|
||||
@return query thread to run next or NULL */
|
||||
UNIV_INTERN
|
||||
que_thr_t*
|
||||
dict_create_index_step(
|
||||
/*===================*/
|
||||
que_thr_t* thr); /*!< in: query thread */
|
||||
/*******************************************************************//**
|
||||
Truncates the index tree associated with a row in SYS_INDEXES table.
|
||||
@return new root page number, or FIL_NULL on failure */
|
||||
UNIV_INTERN
|
||||
ulint
|
||||
dict_truncate_index_tree(
|
||||
/*=====================*/
|
||||
dict_table_t* table, /*!< in: the table the index belongs to */
|
||||
ulint space, /*!< in: 0=truncate,
|
||||
nonzero=create the index tree in the
|
||||
given tablespace */
|
||||
btr_pcur_t* pcur, /*!< in/out: persistent cursor pointing to
|
||||
record in the clustered index of
|
||||
SYS_INDEXES table. The cursor may be
|
||||
repositioned in this call. */
|
||||
mtr_t* mtr); /*!< in: mtr having the latch
|
||||
on the record page. The mtr may be
|
||||
committed and restarted in this call. */
|
||||
/*******************************************************************//**
|
||||
Drops the index tree associated with a row in SYS_INDEXES table. */
|
||||
UNIV_INTERN
|
||||
void
|
||||
dict_drop_index_tree(
|
||||
/*=================*/
|
||||
rec_t* rec, /*!< in/out: record in the clustered index
|
||||
of SYS_INDEXES table */
|
||||
mtr_t* mtr); /*!< in: mtr having the latch on the record page */
|
||||
/****************************************************************//**
|
||||
Creates the foreign key constraints system tables inside InnoDB
|
||||
at server bootstrap or server start if they are not found or are
|
||||
not of the right form.
|
||||
@return DB_SUCCESS or error code */
|
||||
UNIV_INTERN
|
||||
dberr_t
|
||||
dict_create_or_check_foreign_constraint_tables(void);
|
||||
/*================================================*/
|
||||
/********************************************************************//**
|
||||
Generate a foreign key constraint name when it was not named by the user.
|
||||
A generated constraint has a name of the format dbname/tablename_ibfk_NUMBER,
|
||||
where the numbers start from 1, and are given locally for this table, that is,
|
||||
the number is not global, as it used to be before MySQL 4.0.18. */
|
||||
UNIV_INLINE
|
||||
dberr_t
|
||||
dict_create_add_foreign_id(
|
||||
/*=======================*/
|
||||
ulint* id_nr, /*!< in/out: number to use in id generation;
|
||||
incremented if used */
|
||||
const char* name, /*!< in: table name */
|
||||
dict_foreign_t* foreign)/*!< in/out: foreign key */
|
||||
__attribute__((nonnull));
|
||||
|
||||
/** Adds the given set of foreign key objects to the dictionary tables
|
||||
in the database. This function does not modify the dictionary cache. The
|
||||
caller must ensure that all foreign key objects contain a valid constraint
|
||||
name in foreign->id.
|
||||
@param[in] local_fk_set set of foreign key objects, to be added to
|
||||
the dictionary tables
|
||||
@param[in] table table to which the foreign key objects in
|
||||
local_fk_set belong to
|
||||
@param[in,out] trx transaction
|
||||
@return error code or DB_SUCCESS */
|
||||
UNIV_INTERN
|
||||
dberr_t
|
||||
dict_create_add_foreigns_to_dictionary(
|
||||
/*===================================*/
|
||||
const dict_foreign_set& local_fk_set,
|
||||
const dict_table_t* table,
|
||||
trx_t* trx)
|
||||
__attribute__((nonnull, warn_unused_result));
|
||||
/****************************************************************//**
|
||||
Creates the tablespaces and datafiles system tables inside InnoDB
|
||||
at server bootstrap or server start if they are not found or are
|
||||
not of the right form.
|
||||
@return DB_SUCCESS or error code */
|
||||
UNIV_INTERN
|
||||
dberr_t
|
||||
dict_create_or_check_sys_tablespace(void);
|
||||
/*=====================================*/
|
||||
/********************************************************************//**
|
||||
Add a single tablespace definition to the data dictionary tables in the
|
||||
database.
|
||||
@return error code or DB_SUCCESS */
|
||||
UNIV_INTERN
|
||||
dberr_t
|
||||
dict_create_add_tablespace_to_dictionary(
|
||||
/*=====================================*/
|
||||
ulint space, /*!< in: tablespace id */
|
||||
const char* name, /*!< in: tablespace name */
|
||||
ulint flags, /*!< in: tablespace flags */
|
||||
const char* path, /*!< in: tablespace path */
|
||||
trx_t* trx, /*!< in: transaction */
|
||||
bool commit); /*!< in: if true then commit the
|
||||
transaction */
|
||||
/********************************************************************//**
|
||||
Add a foreign key definition to the data dictionary tables.
|
||||
@return error code or DB_SUCCESS */
|
||||
UNIV_INTERN
|
||||
dberr_t
|
||||
dict_create_add_foreign_to_dictionary(
|
||||
/*==================================*/
|
||||
const char* name, /*!< in: table name */
|
||||
const dict_foreign_t* foreign,/*!< in: foreign key */
|
||||
trx_t* trx) /*!< in/out: dictionary transaction */
|
||||
__attribute__((nonnull, warn_unused_result));
|
||||
|
||||
/* Table create node structure */
|
||||
struct tab_node_t{
|
||||
que_common_t common; /*!< node type: QUE_NODE_TABLE_CREATE */
|
||||
dict_table_t* table; /*!< table to create, built as a memory data
|
||||
structure with dict_mem_... functions */
|
||||
ins_node_t* tab_def; /* child node which does the insert of
|
||||
the table definition; the row to be inserted
|
||||
is built by the parent node */
|
||||
ins_node_t* col_def; /* child node which does the inserts of
|
||||
the column definitions; the row to be inserted
|
||||
is built by the parent node */
|
||||
commit_node_t* commit_node;
|
||||
/* child node which performs a commit after
|
||||
a successful table creation */
|
||||
/*----------------------*/
|
||||
/* Local storage for this graph node */
|
||||
ulint state; /*!< node execution state */
|
||||
ulint col_no; /*!< next column definition to insert */
|
||||
mem_heap_t* heap; /*!< memory heap used as auxiliary storage */
|
||||
};
|
||||
|
||||
/* Table create node states */
|
||||
#define TABLE_BUILD_TABLE_DEF 1
|
||||
#define TABLE_BUILD_COL_DEF 2
|
||||
#define TABLE_COMMIT_WORK 3
|
||||
#define TABLE_ADD_TO_CACHE 4
|
||||
#define TABLE_COMPLETED 5
|
||||
|
||||
/* Index create node struct */
|
||||
|
||||
struct ind_node_t{
|
||||
que_common_t common; /*!< node type: QUE_NODE_INDEX_CREATE */
|
||||
dict_index_t* index; /*!< index to create, built as a memory data
|
||||
structure with dict_mem_... functions */
|
||||
ins_node_t* ind_def; /* child node which does the insert of
|
||||
the index definition; the row to be inserted
|
||||
is built by the parent node */
|
||||
ins_node_t* field_def; /* child node which does the inserts of
|
||||
the field definitions; the row to be inserted
|
||||
is built by the parent node */
|
||||
commit_node_t* commit_node;
|
||||
/* child node which performs a commit after
|
||||
a successful index creation */
|
||||
/*----------------------*/
|
||||
/* Local storage for this graph node */
|
||||
ulint state; /*!< node execution state */
|
||||
ulint page_no;/* root page number of the index */
|
||||
dict_table_t* table; /*!< table which owns the index */
|
||||
dtuple_t* ind_row;/* index definition row built */
|
||||
ulint field_no;/* next field definition to insert */
|
||||
mem_heap_t* heap; /*!< memory heap used as auxiliary storage */
|
||||
};
|
||||
|
||||
/* Index create node states */
|
||||
#define INDEX_BUILD_INDEX_DEF 1
|
||||
#define INDEX_BUILD_FIELD_DEF 2
|
||||
#define INDEX_CREATE_INDEX_TREE 3
|
||||
#define INDEX_COMMIT_WORK 4
|
||||
#define INDEX_ADD_TO_CACHE 5
|
||||
|
||||
#ifndef UNIV_NONINL
|
||||
#include "dict0crea.ic"
|
||||
#endif
|
||||
|
||||
#endif
|
||||
98
storage/innobase/include/dict0crea.ic
Normal file
98
storage/innobase/include/dict0crea.ic
Normal file
|
|
@ -0,0 +1,98 @@
|
|||
/*****************************************************************************
|
||||
|
||||
Copyright (c) 1996, 2012, Oracle and/or its affiliates. All Rights Reserved.
|
||||
|
||||
This program is free software; you can redistribute it and/or modify it under
|
||||
the terms of the GNU General Public License as published by the Free Software
|
||||
Foundation; version 2 of the License.
|
||||
|
||||
This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
|
||||
FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License along with
|
||||
this program; if not, write to the Free Software Foundation, Inc.,
|
||||
51 Franklin Street, Suite 500, Boston, MA 02110-1335 USA
|
||||
|
||||
*****************************************************************************/
|
||||
|
||||
/**************************************************//**
|
||||
@file include/dict0crea.ic
|
||||
Database object creation
|
||||
|
||||
Created 1/8/1996 Heikki Tuuri
|
||||
*******************************************************/
|
||||
|
||||
#include "mem0mem.h"
|
||||
|
||||
/*********************************************************************//**
|
||||
Checks if a table name contains the string "/#sql" which denotes temporary
|
||||
tables in MySQL.
|
||||
@return true if temporary table */
|
||||
UNIV_INTERN
|
||||
bool
|
||||
row_is_mysql_tmp_table_name(
|
||||
/*========================*/
|
||||
const char* name) __attribute__((warn_unused_result));
|
||||
/*!< in: table name in the form
|
||||
'database/tablename' */
|
||||
|
||||
|
||||
/********************************************************************//**
|
||||
Generate a foreign key constraint name when it was not named by the user.
|
||||
A generated constraint has a name of the format dbname/tablename_ibfk_NUMBER,
|
||||
where the numbers start from 1, and are given locally for this table, that is,
|
||||
the number is not global, as it used to be before MySQL 4.0.18. */
|
||||
UNIV_INLINE
|
||||
dberr_t
|
||||
dict_create_add_foreign_id(
|
||||
/*=======================*/
|
||||
ulint* id_nr, /*!< in/out: number to use in id generation;
|
||||
incremented if used */
|
||||
const char* name, /*!< in: table name */
|
||||
dict_foreign_t* foreign)/*!< in/out: foreign key */
|
||||
{
|
||||
if (foreign->id == NULL) {
|
||||
/* Generate a new constraint id */
|
||||
ulint namelen = strlen(name);
|
||||
char* id = static_cast<char*>(
|
||||
mem_heap_alloc(foreign->heap,
|
||||
namelen + 20));
|
||||
|
||||
if (row_is_mysql_tmp_table_name(name)) {
|
||||
|
||||
/* no overflow if number < 1e13 */
|
||||
sprintf(id, "%s_ibfk_%lu", name,
|
||||
(ulong) (*id_nr)++);
|
||||
} else {
|
||||
char table_name[MAX_TABLE_NAME_LEN + 20] = "";
|
||||
uint errors = 0;
|
||||
|
||||
strncpy(table_name, name,
|
||||
MAX_TABLE_NAME_LEN + 20);
|
||||
|
||||
innobase_convert_to_system_charset(
|
||||
strchr(table_name, '/') + 1,
|
||||
strchr(name, '/') + 1,
|
||||
MAX_TABLE_NAME_LEN, &errors);
|
||||
|
||||
if (errors) {
|
||||
strncpy(table_name, name,
|
||||
MAX_TABLE_NAME_LEN + 20);
|
||||
}
|
||||
|
||||
/* no overflow if number < 1e13 */
|
||||
sprintf(id, "%s_ibfk_%lu", table_name,
|
||||
(ulong) (*id_nr)++);
|
||||
|
||||
if (innobase_check_identifier_length(
|
||||
strchr(id,'/') + 1)) {
|
||||
return(DB_IDENTIFIER_TOO_LONG);
|
||||
}
|
||||
}
|
||||
foreign->id = id;
|
||||
}
|
||||
|
||||
return(DB_SUCCESS);
|
||||
}
|
||||
|
||||
1841
storage/innobase/include/dict0dict.h
Normal file
1841
storage/innobase/include/dict0dict.h
Normal file
File diff suppressed because it is too large
Load diff
1433
storage/innobase/include/dict0dict.ic
Normal file
1433
storage/innobase/include/dict0dict.ic
Normal file
File diff suppressed because it is too large
Load diff
428
storage/innobase/include/dict0load.h
Normal file
428
storage/innobase/include/dict0load.h
Normal file
|
|
@ -0,0 +1,428 @@
|
|||
/*****************************************************************************
|
||||
|
||||
Copyright (c) 1996, 2013, Oracle and/or its affiliates. All Rights Reserved.
|
||||
|
||||
This program is free software; you can redistribute it and/or modify it under
|
||||
the terms of the GNU General Public License as published by the Free Software
|
||||
Foundation; version 2 of the License.
|
||||
|
||||
This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
|
||||
FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License along with
|
||||
this program; if not, write to the Free Software Foundation, Inc.,
|
||||
51 Franklin Street, Suite 500, Boston, MA 02110-1335 USA
|
||||
|
||||
*****************************************************************************/
|
||||
|
||||
/**************************************************//**
|
||||
@file include/dict0load.h
|
||||
Loads to the memory cache database object definitions
|
||||
from dictionary tables
|
||||
|
||||
Created 4/24/1996 Heikki Tuuri
|
||||
*******************************************************/
|
||||
|
||||
#ifndef dict0load_h
|
||||
#define dict0load_h
|
||||
|
||||
#include "univ.i"
|
||||
#include "dict0types.h"
|
||||
#include "trx0types.h"
|
||||
#include "ut0byte.h"
|
||||
#include "mem0mem.h"
|
||||
#include "btr0types.h"
|
||||
|
||||
/** enum that defines all system table IDs. @see SYSTEM_TABLE_NAME[] */
|
||||
enum dict_system_id_t {
|
||||
SYS_TABLES = 0,
|
||||
SYS_INDEXES,
|
||||
SYS_COLUMNS,
|
||||
SYS_FIELDS,
|
||||
SYS_FOREIGN,
|
||||
SYS_FOREIGN_COLS,
|
||||
SYS_TABLESPACES,
|
||||
SYS_DATAFILES,
|
||||
|
||||
/* This must be last item. Defines the number of system tables. */
|
||||
SYS_NUM_SYSTEM_TABLES
|
||||
};
|
||||
|
||||
/** Status bit for dict_process_sys_tables_rec_and_mtr_commit() */
|
||||
enum dict_table_info_t {
|
||||
DICT_TABLE_LOAD_FROM_RECORD = 0,/*!< Directly populate a dict_table_t
|
||||
structure with information from
|
||||
a SYS_TABLES record */
|
||||
DICT_TABLE_LOAD_FROM_CACHE = 1 /*!< Check first whether dict_table_t
|
||||
is in the cache, if so, return it */
|
||||
};
|
||||
|
||||
/** Check type for dict_check_tablespaces_and_store_max_id() */
|
||||
enum dict_check_t {
|
||||
/** No user tablespaces have been opened
|
||||
(no crash recovery, no transactions recovered). */
|
||||
DICT_CHECK_NONE_LOADED = 0,
|
||||
/** Some user tablespaces may have been opened
|
||||
(no crash recovery; recovered table locks for transactions). */
|
||||
DICT_CHECK_SOME_LOADED,
|
||||
/** All user tablespaces have been opened (crash recovery). */
|
||||
DICT_CHECK_ALL_LOADED
|
||||
};
|
||||
|
||||
/********************************************************************//**
|
||||
In a crash recovery we already have all the tablespace objects created.
|
||||
This function compares the space id information in the InnoDB data dictionary
|
||||
to what we already read with fil_load_single_table_tablespaces().
|
||||
|
||||
In a normal startup, we create the tablespace objects for every table in
|
||||
InnoDB's data dictionary, if the corresponding .ibd file exists.
|
||||
We also scan the biggest space id, and store it to fil_system. */
|
||||
UNIV_INTERN
|
||||
void
|
||||
dict_check_tablespaces_and_store_max_id(
|
||||
/*====================================*/
|
||||
dict_check_t dict_check); /*!< in: how to check */
|
||||
/********************************************************************//**
|
||||
Finds the first table name in the given database.
|
||||
@return own: table name, NULL if does not exist; the caller must free
|
||||
the memory in the string! */
|
||||
UNIV_INTERN
|
||||
char*
|
||||
dict_get_first_table_name_in_db(
|
||||
/*============================*/
|
||||
const char* name); /*!< in: database name which ends to '/' */
|
||||
|
||||
/********************************************************************//**
|
||||
Loads a table definition from a SYS_TABLES record to dict_table_t.
|
||||
Does not load any columns or indexes.
|
||||
@return error message, or NULL on success */
|
||||
UNIV_INTERN
|
||||
const char*
|
||||
dict_load_table_low(
|
||||
/*================*/
|
||||
const char* name, /*!< in: table name */
|
||||
const rec_t* rec, /*!< in: SYS_TABLES record */
|
||||
dict_table_t** table); /*!< out,own: table, or NULL */
|
||||
/********************************************************************//**
|
||||
Loads a table column definition from a SYS_COLUMNS record to
|
||||
dict_table_t.
|
||||
@return error message, or NULL on success */
|
||||
UNIV_INTERN
|
||||
const char*
|
||||
dict_load_column_low(
|
||||
/*=================*/
|
||||
dict_table_t* table, /*!< in/out: table, could be NULL
|
||||
if we just populate a dict_column_t
|
||||
struct with information from
|
||||
a SYS_COLUMNS record */
|
||||
mem_heap_t* heap, /*!< in/out: memory heap
|
||||
for temporary storage */
|
||||
dict_col_t* column, /*!< out: dict_column_t to fill,
|
||||
or NULL if table != NULL */
|
||||
table_id_t* table_id, /*!< out: table id */
|
||||
const char** col_name, /*!< out: column name */
|
||||
const rec_t* rec); /*!< in: SYS_COLUMNS record */
|
||||
/********************************************************************//**
|
||||
Loads an index definition from a SYS_INDEXES record to dict_index_t.
|
||||
If allocate=TRUE, we will create a dict_index_t structure and fill it
|
||||
accordingly. If allocated=FALSE, the dict_index_t will be supplied by
|
||||
the caller and filled with information read from the record. @return
|
||||
error message, or NULL on success */
|
||||
UNIV_INTERN
|
||||
const char*
|
||||
dict_load_index_low(
|
||||
/*================*/
|
||||
byte* table_id, /*!< in/out: table id (8 bytes),
|
||||
an "in" value if allocate=TRUE
|
||||
and "out" when allocate=FALSE */
|
||||
const char* table_name, /*!< in: table name */
|
||||
mem_heap_t* heap, /*!< in/out: temporary memory heap */
|
||||
const rec_t* rec, /*!< in: SYS_INDEXES record */
|
||||
ibool allocate, /*!< in: TRUE=allocate *index,
|
||||
FALSE=fill in a pre-allocated
|
||||
*index */
|
||||
dict_index_t** index); /*!< out,own: index, or NULL */
|
||||
/********************************************************************//**
|
||||
Loads an index field definition from a SYS_FIELDS record to
|
||||
dict_index_t.
|
||||
@return error message, or NULL on success */
|
||||
UNIV_INTERN
|
||||
const char*
|
||||
dict_load_field_low(
|
||||
/*================*/
|
||||
byte* index_id, /*!< in/out: index id (8 bytes)
|
||||
an "in" value if index != NULL
|
||||
and "out" if index == NULL */
|
||||
dict_index_t* index, /*!< in/out: index, could be NULL
|
||||
if we just populate a dict_field_t
|
||||
struct with information from
|
||||
a SYS_FIELDS record */
|
||||
dict_field_t* sys_field, /*!< out: dict_field_t to be
|
||||
filled */
|
||||
ulint* pos, /*!< out: Field position */
|
||||
byte* last_index_id, /*!< in: last index id */
|
||||
mem_heap_t* heap, /*!< in/out: memory heap
|
||||
for temporary storage */
|
||||
const rec_t* rec); /*!< in: SYS_FIELDS record */
|
||||
/********************************************************************//**
|
||||
Using the table->heap, copy the null-terminated filepath into
|
||||
table->data_dir_path and put a null byte before the extension.
|
||||
This allows SHOW CREATE TABLE to return the correct DATA DIRECTORY path.
|
||||
Make this data directory path only if it has not yet been saved. */
|
||||
UNIV_INTERN
|
||||
void
|
||||
dict_save_data_dir_path(
|
||||
/*====================*/
|
||||
dict_table_t* table, /*!< in/out: table */
|
||||
char* filepath); /*!< in: filepath of tablespace */
|
||||
/*****************************************************************//**
|
||||
Make sure the data_file_name is saved in dict_table_t if needed. Try to
|
||||
read it from the file dictionary first, then from SYS_DATAFILES. */
|
||||
UNIV_INTERN
|
||||
void
|
||||
dict_get_and_save_data_dir_path(
|
||||
/*============================*/
|
||||
dict_table_t* table, /*!< in/out: table */
|
||||
bool dict_mutex_own); /*!< in: true if dict_sys->mutex
|
||||
is owned already */
|
||||
/********************************************************************//**
|
||||
Loads a table definition and also all its index definitions, and also
|
||||
the cluster definition if the table is a member in a cluster. Also loads
|
||||
all foreign key constraints where the foreign key is in the table or where
|
||||
a foreign key references columns in this table.
|
||||
@return table, NULL if does not exist; if the table is stored in an
|
||||
.ibd file, but the file does not exist, then we set the
|
||||
ibd_file_missing flag TRUE in the table object we return */
|
||||
UNIV_INTERN
|
||||
dict_table_t*
|
||||
dict_load_table(
|
||||
/*============*/
|
||||
const char* name, /*!< in: table name in the
|
||||
databasename/tablename format */
|
||||
ibool cached, /*!< in: TRUE=add to cache, FALSE=do not */
|
||||
dict_err_ignore_t ignore_err);
|
||||
/*!< in: error to be ignored when loading
|
||||
table and its indexes' definition */
|
||||
/***********************************************************************//**
|
||||
Loads a table object based on the table id.
|
||||
@return table; NULL if table does not exist */
|
||||
UNIV_INTERN
|
||||
dict_table_t*
|
||||
dict_load_table_on_id(
|
||||
/*==================*/
|
||||
table_id_t table_id, /*!< in: table id */
|
||||
dict_err_ignore_t ignore_err); /*!< in: errors to ignore
|
||||
when loading the table */
|
||||
/********************************************************************//**
|
||||
This function is called when the database is booted.
|
||||
Loads system table index definitions except for the clustered index which
|
||||
is added to the dictionary cache at booting before calling this function. */
|
||||
UNIV_INTERN
|
||||
void
|
||||
dict_load_sys_table(
|
||||
/*================*/
|
||||
dict_table_t* table); /*!< in: system table */
|
||||
/***********************************************************************//**
|
||||
Loads foreign key constraints where the table is either the foreign key
|
||||
holder or where the table is referenced by a foreign key. Adds these
|
||||
constraints to the data dictionary. Note that we know that the dictionary
|
||||
cache already contains all constraints where the other relevant table is
|
||||
already in the dictionary cache.
|
||||
@return DB_SUCCESS or error code */
|
||||
UNIV_INTERN
|
||||
dberr_t
|
||||
dict_load_foreigns(
|
||||
/*===============*/
|
||||
const char* table_name, /*!< in: table name */
|
||||
const char** col_names, /*!< in: column names, or NULL
|
||||
to use table->col_names */
|
||||
bool check_recursive,/*!< in: Whether to check
|
||||
recursive load of tables
|
||||
chained by FK */
|
||||
bool check_charsets, /*!< in: whether to check
|
||||
charset compatibility */
|
||||
dict_err_ignore_t ignore_err) /*!< in: error to be ignored */
|
||||
__attribute__((nonnull(1), warn_unused_result));
|
||||
/********************************************************************//**
|
||||
Prints to the standard output information on all tables found in the data
|
||||
dictionary system table. */
|
||||
UNIV_INTERN
|
||||
void
|
||||
dict_print(void);
|
||||
/*============*/
|
||||
|
||||
/********************************************************************//**
|
||||
This function opens a system table, and return the first record.
|
||||
@return first record of the system table */
|
||||
UNIV_INTERN
|
||||
const rec_t*
|
||||
dict_startscan_system(
|
||||
/*==================*/
|
||||
btr_pcur_t* pcur, /*!< out: persistent cursor to
|
||||
the record */
|
||||
mtr_t* mtr, /*!< in: the mini-transaction */
|
||||
dict_system_id_t system_id); /*!< in: which system table to open */
|
||||
/********************************************************************//**
|
||||
This function get the next system table record as we scan the table.
|
||||
@return the record if found, NULL if end of scan. */
|
||||
UNIV_INTERN
|
||||
const rec_t*
|
||||
dict_getnext_system(
|
||||
/*================*/
|
||||
btr_pcur_t* pcur, /*!< in/out: persistent cursor
|
||||
to the record */
|
||||
mtr_t* mtr); /*!< in: the mini-transaction */
|
||||
/********************************************************************//**
|
||||
This function processes one SYS_TABLES record and populate the dict_table_t
|
||||
struct for the table. Extracted out of dict_print() to be used by
|
||||
both monitor table output and information schema innodb_sys_tables output.
|
||||
@return error message, or NULL on success */
|
||||
UNIV_INTERN
|
||||
const char*
|
||||
dict_process_sys_tables_rec_and_mtr_commit(
|
||||
/*=======================================*/
|
||||
mem_heap_t* heap, /*!< in: temporary memory heap */
|
||||
const rec_t* rec, /*!< in: SYS_TABLES record */
|
||||
dict_table_t** table, /*!< out: dict_table_t to fill */
|
||||
dict_table_info_t status, /*!< in: status bit controls
|
||||
options such as whether we shall
|
||||
look for dict_table_t from cache
|
||||
first */
|
||||
mtr_t* mtr); /*!< in/out: mini-transaction,
|
||||
will be committed */
|
||||
/********************************************************************//**
|
||||
This function parses a SYS_INDEXES record and populate a dict_index_t
|
||||
structure with the information from the record. For detail information
|
||||
about SYS_INDEXES fields, please refer to dict_boot() function.
|
||||
@return error message, or NULL on success */
|
||||
UNIV_INTERN
|
||||
const char*
|
||||
dict_process_sys_indexes_rec(
|
||||
/*=========================*/
|
||||
mem_heap_t* heap, /*!< in/out: heap memory */
|
||||
const rec_t* rec, /*!< in: current SYS_INDEXES rec */
|
||||
dict_index_t* index, /*!< out: dict_index_t to be
|
||||
filled */
|
||||
table_id_t* table_id); /*!< out: table id */
|
||||
/********************************************************************//**
|
||||
This function parses a SYS_COLUMNS record and populate a dict_column_t
|
||||
structure with the information from the record.
|
||||
@return error message, or NULL on success */
|
||||
UNIV_INTERN
|
||||
const char*
|
||||
dict_process_sys_columns_rec(
|
||||
/*=========================*/
|
||||
mem_heap_t* heap, /*!< in/out: heap memory */
|
||||
const rec_t* rec, /*!< in: current SYS_COLUMNS rec */
|
||||
dict_col_t* column, /*!< out: dict_col_t to be filled */
|
||||
table_id_t* table_id, /*!< out: table id */
|
||||
const char** col_name); /*!< out: column name */
|
||||
/********************************************************************//**
|
||||
This function parses a SYS_FIELDS record and populate a dict_field_t
|
||||
structure with the information from the record.
|
||||
@return error message, or NULL on success */
|
||||
UNIV_INTERN
|
||||
const char*
|
||||
dict_process_sys_fields_rec(
|
||||
/*========================*/
|
||||
mem_heap_t* heap, /*!< in/out: heap memory */
|
||||
const rec_t* rec, /*!< in: current SYS_FIELDS rec */
|
||||
dict_field_t* sys_field, /*!< out: dict_field_t to be
|
||||
filled */
|
||||
ulint* pos, /*!< out: Field position */
|
||||
index_id_t* index_id, /*!< out: current index id */
|
||||
index_id_t last_id); /*!< in: previous index id */
|
||||
/********************************************************************//**
|
||||
This function parses a SYS_FOREIGN record and populate a dict_foreign_t
|
||||
structure with the information from the record. For detail information
|
||||
about SYS_FOREIGN fields, please refer to dict_load_foreign() function
|
||||
@return error message, or NULL on success */
|
||||
UNIV_INTERN
|
||||
const char*
|
||||
dict_process_sys_foreign_rec(
|
||||
/*=========================*/
|
||||
mem_heap_t* heap, /*!< in/out: heap memory */
|
||||
const rec_t* rec, /*!< in: current SYS_FOREIGN rec */
|
||||
dict_foreign_t* foreign); /*!< out: dict_foreign_t to be
|
||||
filled */
|
||||
/********************************************************************//**
|
||||
This function parses a SYS_FOREIGN_COLS record and extract necessary
|
||||
information from the record and return to caller.
|
||||
@return error message, or NULL on success */
|
||||
UNIV_INTERN
|
||||
const char*
|
||||
dict_process_sys_foreign_col_rec(
|
||||
/*=============================*/
|
||||
mem_heap_t* heap, /*!< in/out: heap memory */
|
||||
const rec_t* rec, /*!< in: current SYS_FOREIGN_COLS rec */
|
||||
const char** name, /*!< out: foreign key constraint name */
|
||||
const char** for_col_name, /*!< out: referencing column name */
|
||||
const char** ref_col_name, /*!< out: referenced column name
|
||||
in referenced table */
|
||||
ulint* pos); /*!< out: column position */
|
||||
/********************************************************************//**
|
||||
This function parses a SYS_TABLESPACES record, extracts necessary
|
||||
information from the record and returns to caller.
|
||||
@return error message, or NULL on success */
|
||||
UNIV_INTERN
|
||||
const char*
|
||||
dict_process_sys_tablespaces(
|
||||
/*=========================*/
|
||||
mem_heap_t* heap, /*!< in/out: heap memory */
|
||||
const rec_t* rec, /*!< in: current SYS_TABLESPACES rec */
|
||||
ulint* space, /*!< out: pace id */
|
||||
const char** name, /*!< out: tablespace name */
|
||||
ulint* flags); /*!< out: tablespace flags */
|
||||
/********************************************************************//**
|
||||
This function parses a SYS_DATAFILES record, extracts necessary
|
||||
information from the record and returns to caller.
|
||||
@return error message, or NULL on success */
|
||||
UNIV_INTERN
|
||||
const char*
|
||||
dict_process_sys_datafiles(
|
||||
/*=======================*/
|
||||
mem_heap_t* heap, /*!< in/out: heap memory */
|
||||
const rec_t* rec, /*!< in: current SYS_DATAFILES rec */
|
||||
ulint* space, /*!< out: pace id */
|
||||
const char** path); /*!< out: datafile path */
|
||||
/********************************************************************//**
|
||||
Get the filepath for a spaceid from SYS_DATAFILES. This function provides
|
||||
a temporary heap which is used for the table lookup, but not for the path.
|
||||
The caller must free the memory for the path returned. This function can
|
||||
return NULL if the space ID is not found in SYS_DATAFILES, then the caller
|
||||
will assume that the ibd file is in the normal datadir.
|
||||
@return own: A copy of the first datafile found in SYS_DATAFILES.PATH for
|
||||
the given space ID. NULL if space ID is zero or not found. */
|
||||
UNIV_INTERN
|
||||
char*
|
||||
dict_get_first_path(
|
||||
/*================*/
|
||||
ulint space, /*!< in: space id */
|
||||
const char* name); /*!< in: tablespace name */
|
||||
/********************************************************************//**
|
||||
Update the record for space_id in SYS_TABLESPACES to this filepath.
|
||||
@return DB_SUCCESS if OK, dberr_t if the insert failed */
|
||||
UNIV_INTERN
|
||||
dberr_t
|
||||
dict_update_filepath(
|
||||
/*=================*/
|
||||
ulint space_id, /*!< in: space id */
|
||||
const char* filepath); /*!< in: filepath */
|
||||
/********************************************************************//**
|
||||
Insert records into SYS_TABLESPACES and SYS_DATAFILES.
|
||||
@return DB_SUCCESS if OK, dberr_t if the insert failed */
|
||||
UNIV_INTERN
|
||||
dberr_t
|
||||
dict_insert_tablespace_and_filepath(
|
||||
/*================================*/
|
||||
ulint space, /*!< in: space id */
|
||||
const char* name, /*!< in: talespace name */
|
||||
const char* filepath, /*!< in: filepath */
|
||||
ulint fsp_flags); /*!< in: tablespace flags */
|
||||
|
||||
#ifndef UNIV_NONINL
|
||||
#include "dict0load.ic"
|
||||
#endif
|
||||
|
||||
#endif
|
||||
26
storage/innobase/include/dict0load.ic
Normal file
26
storage/innobase/include/dict0load.ic
Normal file
|
|
@ -0,0 +1,26 @@
|
|||
/*****************************************************************************
|
||||
|
||||
Copyright (c) 1996, 2009, Oracle and/or its affiliates. All Rights Reserved.
|
||||
|
||||
This program is free software; you can redistribute it and/or modify it under
|
||||
the terms of the GNU General Public License as published by the Free Software
|
||||
Foundation; version 2 of the License.
|
||||
|
||||
This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
|
||||
FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License along with
|
||||
this program; if not, write to the Free Software Foundation, Inc.,
|
||||
51 Franklin Street, Suite 500, Boston, MA 02110-1335 USA
|
||||
|
||||
*****************************************************************************/
|
||||
|
||||
/**************************************************//**
|
||||
@file include/dict0load.ic
|
||||
Loads to the memory cache database object definitions
|
||||
from dictionary tables
|
||||
|
||||
Created 4/24/1996 Heikki Tuuri
|
||||
*******************************************************/
|
||||
|
||||
1214
storage/innobase/include/dict0mem.h
Normal file
1214
storage/innobase/include/dict0mem.h
Normal file
File diff suppressed because it is too large
Load diff
74
storage/innobase/include/dict0mem.ic
Normal file
74
storage/innobase/include/dict0mem.ic
Normal file
|
|
@ -0,0 +1,74 @@
|
|||
/*****************************************************************************
|
||||
|
||||
Copyright (c) 1996, 2009, Oracle and/or its affiliates. All Rights Reserved.
|
||||
|
||||
This program is free software; you can redistribute it and/or modify it under
|
||||
the terms of the GNU General Public License as published by the Free Software
|
||||
Foundation; version 2 of the License.
|
||||
|
||||
This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
|
||||
FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License along with
|
||||
this program; if not, write to the Free Software Foundation, Inc.,
|
||||
51 Franklin Street, Suite 500, Boston, MA 02110-1335 USA
|
||||
|
||||
*****************************************************************************/
|
||||
|
||||
/******************************************************************//**
|
||||
@file include/dict0mem.ic
|
||||
Data dictionary memory object creation
|
||||
|
||||
Created 1/8/1996 Heikki Tuuri
|
||||
***********************************************************************/
|
||||
|
||||
#include "data0type.h"
|
||||
#include "dict0mem.h"
|
||||
#include "fil0fil.h"
|
||||
|
||||
/**********************************************************************//**
|
||||
This function poplulates a dict_index_t index memory structure with
|
||||
supplied information. */
|
||||
UNIV_INLINE
|
||||
void
|
||||
dict_mem_fill_index_struct(
|
||||
/*=======================*/
|
||||
dict_index_t* index, /*!< out: index to be filled */
|
||||
mem_heap_t* heap, /*!< in: memory heap */
|
||||
const char* table_name, /*!< in: table name */
|
||||
const char* index_name, /*!< in: index name */
|
||||
ulint space, /*!< in: space where the index tree is
|
||||
placed, ignored if the index is of
|
||||
the clustered type */
|
||||
ulint type, /*!< in: DICT_UNIQUE,
|
||||
DICT_CLUSTERED, ... ORed */
|
||||
ulint n_fields) /*!< in: number of fields */
|
||||
{
|
||||
|
||||
if (heap) {
|
||||
index->heap = heap;
|
||||
index->name = mem_heap_strdup(heap, index_name);
|
||||
index->fields = (dict_field_t*) mem_heap_alloc(
|
||||
heap, 1 + n_fields * sizeof(dict_field_t));
|
||||
} else {
|
||||
index->name = index_name;
|
||||
index->heap = NULL;
|
||||
index->fields = NULL;
|
||||
}
|
||||
|
||||
/* Assign a ulint to a 4-bit-mapped field.
|
||||
Only the low-order 4 bits are assigned. */
|
||||
index->type = type;
|
||||
#ifndef UNIV_HOTBACKUP
|
||||
index->space = (unsigned int) space;
|
||||
index->page = FIL_NULL;
|
||||
#endif /* !UNIV_HOTBACKUP */
|
||||
index->table_name = table_name;
|
||||
index->n_fields = (unsigned int) n_fields;
|
||||
/* The '1 +' above prevents allocation
|
||||
of an empty mem block */
|
||||
#ifdef UNIV_DEBUG
|
||||
index->magic_n = DICT_INDEX_MAGIC_N;
|
||||
#endif /* UNIV_DEBUG */
|
||||
}
|
||||
63
storage/innobase/include/dict0priv.h
Normal file
63
storage/innobase/include/dict0priv.h
Normal file
|
|
@ -0,0 +1,63 @@
|
|||
/*****************************************************************************
|
||||
|
||||
Copyright (c) 2010, 2013, Oracle and/or its affiliates. All Rights Reserved.
|
||||
|
||||
This program is free software; you can redistribute it and/or modify it under
|
||||
the terms of the GNU General Public License as published by the Free Software
|
||||
Foundation; version 2 of the License.
|
||||
|
||||
This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
|
||||
FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License along with
|
||||
this program; if not, write to the Free Software Foundation, Inc.,
|
||||
51 Franklin Street, Suite 500, Boston, MA 02110-1335 USA
|
||||
|
||||
*****************************************************************************/
|
||||
|
||||
/**************************************************//**
|
||||
@file include/dict0priv.h
|
||||
Data dictionary private functions
|
||||
|
||||
Created Fri 2 Jul 2010 13:30:38 EST - Sunny Bains
|
||||
*******************************************************/
|
||||
|
||||
#ifndef dict0priv_h
|
||||
#define dict0priv_h
|
||||
|
||||
/**********************************************************************//**
|
||||
Gets a table; loads it to the dictionary cache if necessary. A low-level
|
||||
function. Note: Not to be called from outside dict0*c functions.
|
||||
@return table, NULL if not found */
|
||||
UNIV_INLINE
|
||||
dict_table_t*
|
||||
dict_table_get_low(
|
||||
/*===============*/
|
||||
const char* table_name); /*!< in: table name */
|
||||
|
||||
/**********************************************************************//**
|
||||
Checks if a table is in the dictionary cache.
|
||||
@return table, NULL if not found */
|
||||
UNIV_INLINE
|
||||
dict_table_t*
|
||||
dict_table_check_if_in_cache_low(
|
||||
/*=============================*/
|
||||
const char* table_name); /*!< in: table name */
|
||||
|
||||
/**********************************************************************//**
|
||||
Returns a table object based on table id.
|
||||
@return table, NULL if does not exist */
|
||||
UNIV_INLINE
|
||||
dict_table_t*
|
||||
dict_table_open_on_id_low(
|
||||
/*=====================*/
|
||||
table_id_t table_id, /*!< in: table id */
|
||||
dict_err_ignore_t ignore_err); /*!< in: errors to ignore
|
||||
when loading the table */
|
||||
|
||||
#ifndef UNIV_NONINL
|
||||
#include "dict0priv.ic"
|
||||
#endif
|
||||
|
||||
#endif /* dict0priv.h */
|
||||
125
storage/innobase/include/dict0priv.ic
Normal file
125
storage/innobase/include/dict0priv.ic
Normal file
|
|
@ -0,0 +1,125 @@
|
|||
/*****************************************************************************
|
||||
|
||||
Copyright (c) 2010, 2013, Oracle and/or its affiliates. All Rights Reserved.
|
||||
|
||||
This program is free software; you can redistribute it and/or modify it under
|
||||
the terms of the GNU General Public License as published by the Free Software
|
||||
Foundation; version 2 of the License.
|
||||
|
||||
This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
|
||||
FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License along with
|
||||
this program; if not, write to the Free Software Foundation, Inc.,
|
||||
51 Franklin Street, Suite 500, Boston, MA 02110-1335 USA
|
||||
|
||||
*****************************************************************************/
|
||||
|
||||
/******************************************************************//**
|
||||
@file include/dict0priv.ic
|
||||
Data dictionary system private include file
|
||||
|
||||
Created Wed 13 Oct 2010 16:10:14 EST Sunny Bains
|
||||
***********************************************************************/
|
||||
|
||||
#include "dict0dict.h"
|
||||
#include "dict0load.h"
|
||||
#include "dict0priv.h"
|
||||
#ifndef UNIV_HOTBACKUP
|
||||
|
||||
/**********************************************************************//**
|
||||
Gets a table; loads it to the dictionary cache if necessary. A low-level
|
||||
function.
|
||||
@return table, NULL if not found */
|
||||
UNIV_INLINE
|
||||
dict_table_t*
|
||||
dict_table_get_low(
|
||||
/*===============*/
|
||||
const char* table_name) /*!< in: table name */
|
||||
{
|
||||
dict_table_t* table;
|
||||
|
||||
ut_ad(table_name);
|
||||
ut_ad(mutex_own(&(dict_sys->mutex)));
|
||||
|
||||
table = dict_table_check_if_in_cache_low(table_name);
|
||||
|
||||
if (table && table->corrupted) {
|
||||
fprintf(stderr, "InnoDB: table");
|
||||
ut_print_name(stderr, NULL, TRUE, table->name);
|
||||
if (srv_load_corrupted) {
|
||||
fputs(" is corrupted, but"
|
||||
" innodb_force_load_corrupted is set\n", stderr);
|
||||
} else {
|
||||
fputs(" is corrupted\n", stderr);
|
||||
return(NULL);
|
||||
}
|
||||
}
|
||||
|
||||
if (table == NULL) {
|
||||
table = dict_load_table(table_name, TRUE, DICT_ERR_IGNORE_NONE);
|
||||
}
|
||||
|
||||
ut_ad(!table || table->cached);
|
||||
|
||||
return(table);
|
||||
}
|
||||
|
||||
/**********************************************************************//**
|
||||
Returns a table object based on table id.
|
||||
@return table, NULL if does not exist */
|
||||
UNIV_INLINE
|
||||
dict_table_t*
|
||||
dict_table_open_on_id_low(
|
||||
/*======================*/
|
||||
table_id_t table_id, /*!< in: table id */
|
||||
dict_err_ignore_t ignore_err) /*!< in: errors to ignore
|
||||
when loading the table */
|
||||
{
|
||||
dict_table_t* table;
|
||||
ulint fold;
|
||||
|
||||
ut_ad(mutex_own(&(dict_sys->mutex)));
|
||||
|
||||
/* Look for the table name in the hash table */
|
||||
fold = ut_fold_ull(table_id);
|
||||
|
||||
HASH_SEARCH(id_hash, dict_sys->table_id_hash, fold,
|
||||
dict_table_t*, table, ut_ad(table->cached),
|
||||
table->id == table_id);
|
||||
if (table == NULL) {
|
||||
table = dict_load_table_on_id(table_id, ignore_err);
|
||||
}
|
||||
|
||||
ut_ad(!table || table->cached);
|
||||
|
||||
/* TODO: should get the type information from MySQL */
|
||||
|
||||
return(table);
|
||||
}
|
||||
|
||||
/**********************************************************************//**
|
||||
Checks if a table is in the dictionary cache.
|
||||
@return table, NULL if not found */
|
||||
UNIV_INLINE
|
||||
dict_table_t*
|
||||
dict_table_check_if_in_cache_low(
|
||||
/*=============================*/
|
||||
const char* table_name) /*!< in: table name */
|
||||
{
|
||||
dict_table_t* table;
|
||||
ulint table_fold;
|
||||
|
||||
ut_ad(table_name);
|
||||
ut_ad(mutex_own(&(dict_sys->mutex)));
|
||||
|
||||
/* Look for the table name in the hash table */
|
||||
table_fold = ut_fold_string(table_name);
|
||||
|
||||
HASH_SEARCH(name_hash, dict_sys->table_hash, table_fold,
|
||||
dict_table_t*, table, ut_ad(table->cached),
|
||||
!strcmp(table->name, table_name));
|
||||
return(table);
|
||||
}
|
||||
#endif /*! UNIV_HOTBACKUP */
|
||||
202
storage/innobase/include/dict0stats.h
Normal file
202
storage/innobase/include/dict0stats.h
Normal file
|
|
@ -0,0 +1,202 @@
|
|||
/*****************************************************************************
|
||||
|
||||
Copyright (c) 2009, 2012, Oracle and/or its affiliates. All Rights Reserved.
|
||||
|
||||
This program is free software; you can redistribute it and/or modify it under
|
||||
the terms of the GNU General Public License as published by the Free Software
|
||||
Foundation; version 2 of the License.
|
||||
|
||||
This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
|
||||
FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License along with
|
||||
this program; if not, write to the Free Software Foundation, Inc.,
|
||||
51 Franklin Street, Suite 500, Boston, MA 02110-1335 USA
|
||||
|
||||
*****************************************************************************/
|
||||
|
||||
/**************************************************//**
|
||||
@file include/dict0stats.h
|
||||
Code used for calculating and manipulating table statistics.
|
||||
|
||||
Created Jan 06, 2010 Vasil Dimov
|
||||
*******************************************************/
|
||||
|
||||
#ifndef dict0stats_h
|
||||
#define dict0stats_h
|
||||
|
||||
#include "univ.i"
|
||||
|
||||
#include "db0err.h"
|
||||
#include "dict0types.h"
|
||||
#include "trx0types.h"
|
||||
|
||||
enum dict_stats_upd_option_t {
|
||||
DICT_STATS_RECALC_PERSISTENT,/* (re) calculate the
|
||||
statistics using a precise and slow
|
||||
algo and save them to the persistent
|
||||
storage, if the persistent storage is
|
||||
not present then emit a warning and
|
||||
fall back to transient stats */
|
||||
DICT_STATS_RECALC_TRANSIENT,/* (re) calculate the statistics
|
||||
using an imprecise quick algo
|
||||
without saving the results
|
||||
persistently */
|
||||
DICT_STATS_EMPTY_TABLE, /* Write all zeros (or 1 where it makes sense)
|
||||
into a table and its indexes' statistics
|
||||
members. The resulting stats correspond to an
|
||||
empty table. If the table is using persistent
|
||||
statistics, then they are saved on disk. */
|
||||
DICT_STATS_FETCH_ONLY_IF_NOT_IN_MEMORY /* fetch the stats
|
||||
from the persistent storage if the in-memory
|
||||
structures have not been initialized yet,
|
||||
otherwise do nothing */
|
||||
};
|
||||
|
||||
/*********************************************************************//**
|
||||
Calculates new estimates for table and index statistics. This function
|
||||
is relatively quick and is used to calculate transient statistics that
|
||||
are not saved on disk.
|
||||
This was the only way to calculate statistics before the
|
||||
Persistent Statistics feature was introduced. */
|
||||
UNIV_INTERN
|
||||
void
|
||||
dict_stats_update_transient(
|
||||
/*========================*/
|
||||
dict_table_t* table); /*!< in/out: table */
|
||||
|
||||
/*********************************************************************//**
|
||||
Set the persistent statistics flag for a given table. This is set only
|
||||
in the in-memory table object and is not saved on disk. It will be read
|
||||
from the .frm file upon first open from MySQL after a server restart. */
|
||||
UNIV_INLINE
|
||||
void
|
||||
dict_stats_set_persistent(
|
||||
/*======================*/
|
||||
dict_table_t* table, /*!< in/out: table */
|
||||
ibool ps_on, /*!< in: persistent stats explicitly enabled */
|
||||
ibool ps_off) /*!< in: persistent stats explicitly disabled */
|
||||
__attribute__((nonnull));
|
||||
|
||||
/*********************************************************************//**
|
||||
Check whether persistent statistics is enabled for a given table.
|
||||
@return TRUE if enabled, FALSE otherwise */
|
||||
UNIV_INLINE
|
||||
ibool
|
||||
dict_stats_is_persistent_enabled(
|
||||
/*=============================*/
|
||||
const dict_table_t* table) /*!< in: table */
|
||||
__attribute__((nonnull, warn_unused_result));
|
||||
|
||||
/*********************************************************************//**
|
||||
Set the auto recalc flag for a given table (only honored for a persistent
|
||||
stats enabled table). The flag is set only in the in-memory table object
|
||||
and is not saved in InnoDB files. It will be read from the .frm file upon
|
||||
first open from MySQL after a server restart. */
|
||||
UNIV_INLINE
|
||||
void
|
||||
dict_stats_auto_recalc_set(
|
||||
/*=======================*/
|
||||
dict_table_t* table, /*!< in/out: table */
|
||||
ibool auto_recalc_on, /*!< in: explicitly enabled */
|
||||
ibool auto_recalc_off); /*!< in: explicitly disabled */
|
||||
|
||||
/*********************************************************************//**
|
||||
Check whether auto recalc is enabled for a given table.
|
||||
@return TRUE if enabled, FALSE otherwise */
|
||||
UNIV_INLINE
|
||||
ibool
|
||||
dict_stats_auto_recalc_is_enabled(
|
||||
/*==============================*/
|
||||
const dict_table_t* table); /*!< in: table */
|
||||
|
||||
/*********************************************************************//**
|
||||
Initialize table's stats for the first time when opening a table. */
|
||||
UNIV_INLINE
|
||||
void
|
||||
dict_stats_init(
|
||||
/*============*/
|
||||
dict_table_t* table); /*!< in/out: table */
|
||||
|
||||
/*********************************************************************//**
|
||||
Deinitialize table's stats after the last close of the table. This is
|
||||
used to detect "FLUSH TABLE" and refresh the stats upon next open. */
|
||||
UNIV_INLINE
|
||||
void
|
||||
dict_stats_deinit(
|
||||
/*==============*/
|
||||
dict_table_t* table) /*!< in/out: table */
|
||||
__attribute__((nonnull));
|
||||
|
||||
/*********************************************************************//**
|
||||
Calculates new estimates for table and index statistics. The statistics
|
||||
are used in query optimization.
|
||||
@return DB_* error code or DB_SUCCESS */
|
||||
UNIV_INTERN
|
||||
dberr_t
|
||||
dict_stats_update(
|
||||
/*==============*/
|
||||
dict_table_t* table, /*!< in/out: table */
|
||||
dict_stats_upd_option_t stats_upd_option);
|
||||
/*!< in: whether to (re) calc
|
||||
the stats or to fetch them from
|
||||
the persistent storage */
|
||||
|
||||
/*********************************************************************//**
|
||||
Removes the information for a particular index's stats from the persistent
|
||||
storage if it exists and if there is data stored for this index.
|
||||
This function creates its own trx and commits it.
|
||||
@return DB_SUCCESS or error code */
|
||||
UNIV_INTERN
|
||||
dberr_t
|
||||
dict_stats_drop_index(
|
||||
/*==================*/
|
||||
const char* tname, /*!< in: table name */
|
||||
const char* iname, /*!< in: index name */
|
||||
char* errstr, /*!< out: error message if != DB_SUCCESS
|
||||
is returned */
|
||||
ulint errstr_sz);/*!< in: size of the errstr buffer */
|
||||
|
||||
/*********************************************************************//**
|
||||
Removes the statistics for a table and all of its indexes from the
|
||||
persistent storage if it exists and if there is data stored for the table.
|
||||
This function creates its own transaction and commits it.
|
||||
@return DB_SUCCESS or error code */
|
||||
UNIV_INTERN
|
||||
dberr_t
|
||||
dict_stats_drop_table(
|
||||
/*==================*/
|
||||
const char* table_name, /*!< in: table name */
|
||||
char* errstr, /*!< out: error message
|
||||
if != DB_SUCCESS is returned */
|
||||
ulint errstr_sz); /*!< in: size of errstr buffer */
|
||||
|
||||
/*********************************************************************//**
|
||||
Fetches or calculates new estimates for index statistics. */
|
||||
UNIV_INTERN
|
||||
void
|
||||
dict_stats_update_for_index(
|
||||
/*========================*/
|
||||
dict_index_t* index) /*!< in/out: index */
|
||||
__attribute__((nonnull));
|
||||
|
||||
/*********************************************************************//**
|
||||
Renames a table in InnoDB persistent stats storage.
|
||||
This function creates its own transaction and commits it.
|
||||
@return DB_SUCCESS or error code */
|
||||
UNIV_INTERN
|
||||
dberr_t
|
||||
dict_stats_rename_table(
|
||||
/*====================*/
|
||||
const char* old_name, /*!< in: old table name */
|
||||
const char* new_name, /*!< in: new table name */
|
||||
char* errstr, /*!< out: error string if != DB_SUCCESS
|
||||
is returned */
|
||||
size_t errstr_sz); /*!< in: errstr size */
|
||||
|
||||
#ifndef UNIV_NONINL
|
||||
#include "dict0stats.ic"
|
||||
#endif
|
||||
|
||||
#endif /* dict0stats_h */
|
||||
236
storage/innobase/include/dict0stats.ic
Normal file
236
storage/innobase/include/dict0stats.ic
Normal file
|
|
@ -0,0 +1,236 @@
|
|||
/*****************************************************************************
|
||||
|
||||
Copyright (c) 2012, 2013, Oracle and/or its affiliates. All Rights Reserved.
|
||||
|
||||
This program is free software; you can redistribute it and/or modify it under
|
||||
the terms of the GNU General Public License as published by the Free Software
|
||||
Foundation; version 2 of the License.
|
||||
|
||||
This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
|
||||
FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License along with
|
||||
this program; if not, write to the Free Software Foundation, Inc.,
|
||||
51 Franklin Street, Suite 500, Boston, MA 02110-1335 USA
|
||||
|
||||
*****************************************************************************/
|
||||
|
||||
/**************************************************//**
|
||||
@file include/dict0stats.ic
|
||||
Code used for calculating and manipulating table statistics.
|
||||
|
||||
Created Jan 23, 2012 Vasil Dimov
|
||||
*******************************************************/
|
||||
|
||||
#include "univ.i"
|
||||
#include "dict0dict.h" /* dict_table_stats_lock() */
|
||||
#include "dict0types.h" /* dict_table_t */
|
||||
#include "srv0srv.h" /* srv_stats_persistent, srv_stats_auto_recalc */
|
||||
|
||||
/*********************************************************************//**
|
||||
Set the persistent statistics flag for a given table. This is set only
|
||||
in the in-memory table object and is not saved on disk. It will be read
|
||||
from the .frm file upon first open from MySQL after a server restart. */
|
||||
UNIV_INLINE
|
||||
void
|
||||
dict_stats_set_persistent(
|
||||
/*======================*/
|
||||
dict_table_t* table, /*!< in/out: table */
|
||||
ibool ps_on, /*!< in: persistent stats explicitly enabled */
|
||||
ibool ps_off) /*!< in: persistent stats explicitly disabled */
|
||||
{
|
||||
/* Not allowed to have both flags set, but a CREATE or ALTER
|
||||
statement that contains "STATS_PERSISTENT=0 STATS_PERSISTENT=1" would
|
||||
end up having both set. In this case we clear the OFF flag. */
|
||||
if (ps_on && ps_off) {
|
||||
ps_off = FALSE;
|
||||
}
|
||||
|
||||
ib_uint32_t stat_persistent = 0;
|
||||
|
||||
if (ps_on) {
|
||||
stat_persistent |= DICT_STATS_PERSISTENT_ON;
|
||||
}
|
||||
|
||||
if (ps_off) {
|
||||
stat_persistent |= DICT_STATS_PERSISTENT_OFF;
|
||||
}
|
||||
|
||||
/* we rely on this assignment to be atomic */
|
||||
table->stat_persistent = stat_persistent;
|
||||
}
|
||||
|
||||
/*********************************************************************//**
|
||||
Check whether persistent statistics is enabled for a given table.
|
||||
@return TRUE if enabled, FALSE otherwise */
|
||||
UNIV_INLINE
|
||||
ibool
|
||||
dict_stats_is_persistent_enabled(
|
||||
/*=============================*/
|
||||
const dict_table_t* table) /*!< in: table */
|
||||
{
|
||||
/* Because of the nature of this check (non-locking) it is possible
|
||||
that a table becomes:
|
||||
* PS-disabled immediately after this function has returned TRUE or
|
||||
* PS-enabled immediately after this function has returned FALSE.
|
||||
This means that it is possible that we do:
|
||||
+ dict_stats_update(DICT_STATS_RECALC_PERSISTENT) on a table that has
|
||||
just been PS-disabled or
|
||||
+ dict_stats_update(DICT_STATS_RECALC_TRANSIENT) on a table that has
|
||||
just been PS-enabled.
|
||||
This is acceptable. Avoiding this would mean that we would have to
|
||||
protect the ::stat_persistent with dict_table_stats_lock() like the
|
||||
other ::stat_ members which would be too big performance penalty,
|
||||
especially when this function is called from
|
||||
row_update_statistics_if_needed(). */
|
||||
|
||||
/* we rely on this read to be atomic */
|
||||
ib_uint32_t stat_persistent = table->stat_persistent;
|
||||
|
||||
if (stat_persistent & DICT_STATS_PERSISTENT_ON) {
|
||||
ut_ad(!(stat_persistent & DICT_STATS_PERSISTENT_OFF));
|
||||
return(TRUE);
|
||||
} else if (stat_persistent & DICT_STATS_PERSISTENT_OFF) {
|
||||
return(FALSE);
|
||||
} else {
|
||||
return(srv_stats_persistent);
|
||||
}
|
||||
}
|
||||
|
||||
/*********************************************************************//**
|
||||
Set the auto recalc flag for a given table (only honored for a persistent
|
||||
stats enabled table). The flag is set only in the in-memory table object
|
||||
and is not saved in InnoDB files. It will be read from the .frm file upon
|
||||
first open from MySQL after a server restart. */
|
||||
UNIV_INLINE
|
||||
void
|
||||
dict_stats_auto_recalc_set(
|
||||
/*=======================*/
|
||||
dict_table_t* table, /*!< in/out: table */
|
||||
ibool auto_recalc_on, /*!< in: explicitly enabled */
|
||||
ibool auto_recalc_off) /*!< in: explicitly disabled */
|
||||
{
|
||||
ut_ad(!auto_recalc_on || !auto_recalc_off);
|
||||
|
||||
ib_uint32_t stats_auto_recalc = 0;
|
||||
|
||||
if (auto_recalc_on) {
|
||||
stats_auto_recalc |= DICT_STATS_AUTO_RECALC_ON;
|
||||
}
|
||||
|
||||
if (auto_recalc_off) {
|
||||
stats_auto_recalc |= DICT_STATS_AUTO_RECALC_OFF;
|
||||
}
|
||||
|
||||
/* we rely on this assignment to be atomic */
|
||||
table->stats_auto_recalc = stats_auto_recalc;
|
||||
}
|
||||
|
||||
/*********************************************************************//**
|
||||
Check whether auto recalc is enabled for a given table.
|
||||
@return TRUE if enabled, FALSE otherwise */
|
||||
UNIV_INLINE
|
||||
ibool
|
||||
dict_stats_auto_recalc_is_enabled(
|
||||
/*==============================*/
|
||||
const dict_table_t* table) /*!< in: table */
|
||||
{
|
||||
/* we rely on this read to be atomic */
|
||||
ib_uint32_t stats_auto_recalc = table->stats_auto_recalc;
|
||||
|
||||
if (stats_auto_recalc & DICT_STATS_AUTO_RECALC_ON) {
|
||||
ut_ad(!(stats_auto_recalc & DICT_STATS_AUTO_RECALC_OFF));
|
||||
return(TRUE);
|
||||
} else if (stats_auto_recalc & DICT_STATS_AUTO_RECALC_OFF) {
|
||||
return(FALSE);
|
||||
} else {
|
||||
return(srv_stats_auto_recalc);
|
||||
}
|
||||
}
|
||||
|
||||
/*********************************************************************//**
|
||||
Initialize table's stats for the first time when opening a table. */
|
||||
UNIV_INLINE
|
||||
void
|
||||
dict_stats_init(
|
||||
/*============*/
|
||||
dict_table_t* table) /*!< in/out: table */
|
||||
{
|
||||
ut_ad(!mutex_own(&dict_sys->mutex));
|
||||
|
||||
if (table->stat_initialized) {
|
||||
return;
|
||||
}
|
||||
|
||||
dict_stats_upd_option_t opt;
|
||||
|
||||
if (dict_stats_is_persistent_enabled(table)) {
|
||||
opt = DICT_STATS_FETCH_ONLY_IF_NOT_IN_MEMORY;
|
||||
} else {
|
||||
opt = DICT_STATS_RECALC_TRANSIENT;
|
||||
}
|
||||
|
||||
dict_stats_update(table, opt);
|
||||
}
|
||||
|
||||
/*********************************************************************//**
|
||||
Deinitialize table's stats after the last close of the table. This is
|
||||
used to detect "FLUSH TABLE" and refresh the stats upon next open. */
|
||||
UNIV_INLINE
|
||||
void
|
||||
dict_stats_deinit(
|
||||
/*==============*/
|
||||
dict_table_t* table) /*!< in/out: table */
|
||||
{
|
||||
ut_ad(mutex_own(&dict_sys->mutex));
|
||||
|
||||
ut_a(table->n_ref_count == 0);
|
||||
|
||||
dict_table_stats_lock(table, RW_X_LATCH);
|
||||
|
||||
if (!table->stat_initialized) {
|
||||
dict_table_stats_unlock(table, RW_X_LATCH);
|
||||
return;
|
||||
}
|
||||
|
||||
table->stat_initialized = FALSE;
|
||||
|
||||
#ifdef UNIV_DEBUG_VALGRIND
|
||||
UNIV_MEM_INVALID(&table->stat_n_rows,
|
||||
sizeof(table->stat_n_rows));
|
||||
UNIV_MEM_INVALID(&table->stat_clustered_index_size,
|
||||
sizeof(table->stat_clustered_index_size));
|
||||
UNIV_MEM_INVALID(&table->stat_sum_of_other_index_sizes,
|
||||
sizeof(table->stat_sum_of_other_index_sizes));
|
||||
UNIV_MEM_INVALID(&table->stat_modified_counter,
|
||||
sizeof(table->stat_modified_counter));
|
||||
|
||||
dict_index_t* index;
|
||||
|
||||
for (index = dict_table_get_first_index(table);
|
||||
index != NULL;
|
||||
index = dict_table_get_next_index(index)) {
|
||||
|
||||
ulint n_uniq = dict_index_get_n_unique(index);
|
||||
|
||||
UNIV_MEM_INVALID(
|
||||
index->stat_n_diff_key_vals,
|
||||
n_uniq * sizeof(index->stat_n_diff_key_vals[0]));
|
||||
UNIV_MEM_INVALID(
|
||||
index->stat_n_sample_sizes,
|
||||
n_uniq * sizeof(index->stat_n_sample_sizes[0]));
|
||||
UNIV_MEM_INVALID(
|
||||
index->stat_n_non_null_key_vals,
|
||||
n_uniq * sizeof(index->stat_n_non_null_key_vals[0]));
|
||||
UNIV_MEM_INVALID(
|
||||
&index->stat_index_size,
|
||||
sizeof(index->stat_index_size));
|
||||
UNIV_MEM_INVALID(
|
||||
&index->stat_n_leaf_pages,
|
||||
sizeof(index->stat_n_leaf_pages));
|
||||
}
|
||||
#endif /* UNIV_DEBUG_VALGRIND */
|
||||
|
||||
dict_table_stats_unlock(table, RW_X_LATCH);
|
||||
}
|
||||
127
storage/innobase/include/dict0stats_bg.h
Normal file
127
storage/innobase/include/dict0stats_bg.h
Normal file
|
|
@ -0,0 +1,127 @@
|
|||
/*****************************************************************************
|
||||
|
||||
Copyright (c) 2012, 2013, Oracle and/or its affiliates. All Rights Reserved.
|
||||
|
||||
This program is free software; you can redistribute it and/or modify it under
|
||||
the terms of the GNU General Public License as published by the Free Software
|
||||
Foundation; version 2 of the License.
|
||||
|
||||
This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
|
||||
FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License along with
|
||||
this program; if not, write to the Free Software Foundation, Inc.,
|
||||
51 Franklin Street, Suite 500, Boston, MA 02110-1335 USA
|
||||
|
||||
*****************************************************************************/
|
||||
|
||||
/**************************************************//**
|
||||
@file include/dict0stats_bg.h
|
||||
Code used for background table and index stats gathering.
|
||||
|
||||
Created Apr 26, 2012 Vasil Dimov
|
||||
*******************************************************/
|
||||
|
||||
#ifndef dict0stats_bg_h
|
||||
#define dict0stats_bg_h
|
||||
|
||||
#include "univ.i"
|
||||
|
||||
#include "dict0types.h" /* dict_table_t, table_id_t */
|
||||
#include "os0sync.h" /* os_event_t */
|
||||
#include "os0thread.h" /* DECLARE_THREAD */
|
||||
|
||||
/** Event to wake up the stats thread */
|
||||
extern os_event_t dict_stats_event;
|
||||
|
||||
/*****************************************************************//**
|
||||
Add a table to the recalc pool, which is processed by the
|
||||
background stats gathering thread. Only the table id is added to the
|
||||
list, so the table can be closed after being enqueued and it will be
|
||||
opened when needed. If the table does not exist later (has been DROPped),
|
||||
then it will be removed from the pool and skipped. */
|
||||
UNIV_INTERN
|
||||
void
|
||||
dict_stats_recalc_pool_add(
|
||||
/*=======================*/
|
||||
const dict_table_t* table); /*!< in: table to add */
|
||||
|
||||
/*****************************************************************//**
|
||||
Delete a given table from the auto recalc pool.
|
||||
dict_stats_recalc_pool_del() */
|
||||
UNIV_INTERN
|
||||
void
|
||||
dict_stats_recalc_pool_del(
|
||||
/*=======================*/
|
||||
const dict_table_t* table); /*!< in: table to remove */
|
||||
|
||||
/** Yield the data dictionary latch when waiting
|
||||
for the background thread to stop accessing a table.
|
||||
@param trx transaction holding the data dictionary locks */
|
||||
#define DICT_STATS_BG_YIELD(trx) do { \
|
||||
row_mysql_unlock_data_dictionary(trx); \
|
||||
os_thread_sleep(250000); \
|
||||
row_mysql_lock_data_dictionary(trx); \
|
||||
} while (0)
|
||||
|
||||
/*****************************************************************//**
|
||||
Request the background collection of statistics to stop for a table.
|
||||
@retval true when no background process is active
|
||||
@retval false when it is not safe to modify the table definition */
|
||||
UNIV_INLINE
|
||||
bool
|
||||
dict_stats_stop_bg(
|
||||
/*===============*/
|
||||
dict_table_t* table) /*!< in/out: table */
|
||||
__attribute__((warn_unused_result));
|
||||
|
||||
/*****************************************************************//**
|
||||
Wait until background stats thread has stopped using the specified table.
|
||||
The caller must have locked the data dictionary using
|
||||
row_mysql_lock_data_dictionary() and this function may unlock it temporarily
|
||||
and restore the lock before it exits.
|
||||
The background stats thread is guaranteed not to start using the specified
|
||||
table after this function returns and before the caller unlocks the data
|
||||
dictionary because it sets the BG_STAT_IN_PROGRESS bit in table->stats_bg_flag
|
||||
under dict_sys->mutex. */
|
||||
UNIV_INTERN
|
||||
void
|
||||
dict_stats_wait_bg_to_stop_using_table(
|
||||
/*===================================*/
|
||||
dict_table_t* table, /*!< in/out: table */
|
||||
trx_t* trx); /*!< in/out: transaction to use for
|
||||
unlocking/locking the data dict */
|
||||
/*****************************************************************//**
|
||||
Initialize global variables needed for the operation of dict_stats_thread().
|
||||
Must be called before dict_stats_thread() is started. */
|
||||
UNIV_INTERN
|
||||
void
|
||||
dict_stats_thread_init();
|
||||
/*====================*/
|
||||
|
||||
/*****************************************************************//**
|
||||
Free resources allocated by dict_stats_thread_init(), must be called
|
||||
after dict_stats_thread() has exited. */
|
||||
UNIV_INTERN
|
||||
void
|
||||
dict_stats_thread_deinit();
|
||||
/*======================*/
|
||||
|
||||
/*****************************************************************//**
|
||||
This is the thread for background stats gathering. It pops tables, from
|
||||
the auto recalc list and proceeds them, eventually recalculating their
|
||||
statistics.
|
||||
@return this function does not return, it calls os_thread_exit() */
|
||||
extern "C" UNIV_INTERN
|
||||
os_thread_ret_t
|
||||
DECLARE_THREAD(dict_stats_thread)(
|
||||
/*==============================*/
|
||||
void* arg); /*!< in: a dummy parameter
|
||||
required by os_thread_create */
|
||||
|
||||
# ifndef UNIV_NONINL
|
||||
# include "dict0stats_bg.ic"
|
||||
# endif
|
||||
|
||||
#endif /* dict0stats_bg_h */
|
||||
45
storage/innobase/include/dict0stats_bg.ic
Normal file
45
storage/innobase/include/dict0stats_bg.ic
Normal file
|
|
@ -0,0 +1,45 @@
|
|||
/*****************************************************************************
|
||||
|
||||
Copyright (c) 2012, 2013, Oracle and/or its affiliates. All Rights Reserved.
|
||||
|
||||
This program is free software; you can redistribute it and/or modify it under
|
||||
the terms of the GNU General Public License as published by the Free Software
|
||||
Foundation; version 2 of the License.
|
||||
|
||||
This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
|
||||
FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License along with
|
||||
this program; if not, write to the Free Software Foundation, Inc.,
|
||||
51 Franklin Street, Suite 500, Boston, MA 02110-1335 USA
|
||||
|
||||
*****************************************************************************/
|
||||
|
||||
/**************************************************//**
|
||||
@file include/dict0stats_bg.ic
|
||||
Code used for background table and index stats gathering.
|
||||
|
||||
Created Feb 8, 2013 Marko Makela
|
||||
*******************************************************/
|
||||
|
||||
/*****************************************************************//**
|
||||
Request the background collection of statistics to stop for a table.
|
||||
@retval true when no background process is active
|
||||
@retval false when it is not safe to modify the table definition */
|
||||
UNIV_INLINE
|
||||
bool
|
||||
dict_stats_stop_bg(
|
||||
/*===============*/
|
||||
dict_table_t* table) /*!< in/out: table */
|
||||
{
|
||||
ut_ad(!srv_read_only_mode);
|
||||
ut_ad(mutex_own(&dict_sys->mutex));
|
||||
|
||||
if (!(table->stats_bg_flag & BG_STAT_IN_PROGRESS)) {
|
||||
return(true);
|
||||
}
|
||||
|
||||
table->stats_bg_flag |= BG_STAT_SHOULD_QUIT;
|
||||
return(false);
|
||||
}
|
||||
91
storage/innobase/include/dict0types.h
Normal file
91
storage/innobase/include/dict0types.h
Normal file
|
|
@ -0,0 +1,91 @@
|
|||
/*****************************************************************************
|
||||
|
||||
Copyright (c) 1996, 2013, Oracle and/or its affiliates. All Rights Reserved.
|
||||
|
||||
This program is free software; you can redistribute it and/or modify it under
|
||||
the terms of the GNU General Public License as published by the Free Software
|
||||
Foundation; version 2 of the License.
|
||||
|
||||
This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
|
||||
FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License along with
|
||||
this program; if not, write to the Free Software Foundation, Inc.,
|
||||
51 Franklin Street, Suite 500, Boston, MA 02110-1335 USA
|
||||
|
||||
*****************************************************************************/
|
||||
|
||||
/**************************************************//**
|
||||
@file include/dict0types.h
|
||||
Data dictionary global types
|
||||
|
||||
Created 1/8/1996 Heikki Tuuri
|
||||
*******************************************************/
|
||||
|
||||
#ifndef dict0types_h
|
||||
#define dict0types_h
|
||||
|
||||
struct dict_sys_t;
|
||||
struct dict_col_t;
|
||||
struct dict_field_t;
|
||||
struct dict_index_t;
|
||||
struct dict_table_t;
|
||||
struct dict_foreign_t;
|
||||
|
||||
struct ind_node_t;
|
||||
struct tab_node_t;
|
||||
|
||||
/* Space id and page no where the dictionary header resides */
|
||||
#define DICT_HDR_SPACE 0 /* the SYSTEM tablespace */
|
||||
#define DICT_HDR_PAGE_NO FSP_DICT_HDR_PAGE_NO
|
||||
|
||||
/* The ibuf table and indexes's ID are assigned as the number
|
||||
DICT_IBUF_ID_MIN plus the space id */
|
||||
#define DICT_IBUF_ID_MIN 0xFFFFFFFF00000000ULL
|
||||
|
||||
typedef ib_id_t table_id_t;
|
||||
typedef ib_id_t index_id_t;
|
||||
|
||||
/** Error to ignore when we load table dictionary into memory. However,
|
||||
the table and index will be marked as "corrupted", and caller will
|
||||
be responsible to deal with corrupted table or index.
|
||||
Note: please define the IGNORE_ERR_* as bits, so their value can
|
||||
be or-ed together */
|
||||
enum dict_err_ignore_t {
|
||||
DICT_ERR_IGNORE_NONE = 0, /*!< no error to ignore */
|
||||
DICT_ERR_IGNORE_INDEX_ROOT = 1, /*!< ignore error if index root
|
||||
page is FIL_NULL or incorrect value */
|
||||
DICT_ERR_IGNORE_CORRUPT = 2, /*!< skip corrupted indexes */
|
||||
DICT_ERR_IGNORE_FK_NOKEY = 4, /*!< ignore error if any foreign
|
||||
key is missing */
|
||||
DICT_ERR_IGNORE_RECOVER_LOCK = 8,
|
||||
/*!< Used when recovering table locks
|
||||
for resurrected transactions.
|
||||
Silently load a missing
|
||||
tablespace, and do not load
|
||||
incomplete index definitions. */
|
||||
DICT_ERR_IGNORE_ALL = 0xFFFF /*!< ignore all errors */
|
||||
};
|
||||
|
||||
/** Quiescing states for flushing tables to disk. */
|
||||
enum ib_quiesce_t {
|
||||
QUIESCE_NONE,
|
||||
QUIESCE_START, /*!< Initialise, prepare to start */
|
||||
QUIESCE_COMPLETE /*!< All done */
|
||||
};
|
||||
|
||||
/** Prefix for tmp tables, adopted from sql/table.h */
|
||||
#define tmp_file_prefix "#sql"
|
||||
#define tmp_file_prefix_length 4
|
||||
#define TEMP_FILE_PREFIX_INNODB "#sql-ib"
|
||||
|
||||
#define TEMP_TABLE_PREFIX "#sql"
|
||||
#define TEMP_TABLE_PATH_PREFIX "/" TEMP_TABLE_PREFIX
|
||||
|
||||
#if defined UNIV_DEBUG || defined UNIV_IBUF_DEBUG
|
||||
/** Flag to control insert buffer debugging. */
|
||||
extern uint ibuf_debug;
|
||||
#endif /* UNIV_DEBUG || UNIV_IBUF_DEBUG */
|
||||
|
||||
#endif
|
||||
199
storage/innobase/include/dyn0dyn.h
Normal file
199
storage/innobase/include/dyn0dyn.h
Normal file
|
|
@ -0,0 +1,199 @@
|
|||
/*****************************************************************************
|
||||
|
||||
Copyright (c) 1996, 2013, Oracle and/or its affiliates. All Rights Reserved.
|
||||
|
||||
This program is free software; you can redistribute it and/or modify it under
|
||||
the terms of the GNU General Public License as published by the Free Software
|
||||
Foundation; version 2 of the License.
|
||||
|
||||
This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
|
||||
FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License along with
|
||||
this program; if not, write to the Free Software Foundation, Inc.,
|
||||
51 Franklin Street, Suite 500, Boston, MA 02110-1335 USA
|
||||
|
||||
*****************************************************************************/
|
||||
|
||||
/**************************************************//**
|
||||
@file include/dyn0dyn.h
|
||||
The dynamically allocated array
|
||||
|
||||
Created 2/5/1996 Heikki Tuuri
|
||||
*******************************************************/
|
||||
|
||||
#ifndef dyn0dyn_h
|
||||
#define dyn0dyn_h
|
||||
|
||||
#include "univ.i"
|
||||
#include "ut0lst.h"
|
||||
#include "mem0mem.h"
|
||||
|
||||
/** A block in a dynamically allocated array */
|
||||
struct dyn_block_t;
|
||||
/** Dynamically allocated array */
|
||||
typedef dyn_block_t dyn_array_t;
|
||||
|
||||
/** This is the initial 'payload' size of a dynamic array;
|
||||
this must be > MLOG_BUF_MARGIN + 30! */
|
||||
#define DYN_ARRAY_DATA_SIZE 512
|
||||
|
||||
/*********************************************************************//**
|
||||
Initializes a dynamic array.
|
||||
@return initialized dyn array */
|
||||
UNIV_INLINE
|
||||
dyn_array_t*
|
||||
dyn_array_create(
|
||||
/*=============*/
|
||||
dyn_array_t* arr) /*!< in/out memory buffer of
|
||||
size sizeof(dyn_array_t) */
|
||||
__attribute__((nonnull));
|
||||
/************************************************************//**
|
||||
Frees a dynamic array. */
|
||||
UNIV_INLINE
|
||||
void
|
||||
dyn_array_free(
|
||||
/*===========*/
|
||||
dyn_array_t* arr) /*!< in,own: dyn array */
|
||||
__attribute__((nonnull));
|
||||
/*********************************************************************//**
|
||||
Makes room on top of a dyn array and returns a pointer to a buffer in it.
|
||||
After copying the elements, the caller must close the buffer using
|
||||
dyn_array_close.
|
||||
@return pointer to the buffer */
|
||||
UNIV_INLINE
|
||||
byte*
|
||||
dyn_array_open(
|
||||
/*===========*/
|
||||
dyn_array_t* arr, /*!< in: dynamic array */
|
||||
ulint size) /*!< in: size in bytes of the buffer; MUST be
|
||||
smaller than DYN_ARRAY_DATA_SIZE! */
|
||||
__attribute__((nonnull, warn_unused_result));
|
||||
/*********************************************************************//**
|
||||
Closes the buffer returned by dyn_array_open. */
|
||||
UNIV_INLINE
|
||||
void
|
||||
dyn_array_close(
|
||||
/*============*/
|
||||
dyn_array_t* arr, /*!< in: dynamic array */
|
||||
const byte* ptr) /*!< in: end of used space */
|
||||
__attribute__((nonnull));
|
||||
/*********************************************************************//**
|
||||
Makes room on top of a dyn array and returns a pointer to
|
||||
the added element. The caller must copy the element to
|
||||
the pointer returned.
|
||||
@return pointer to the element */
|
||||
UNIV_INLINE
|
||||
void*
|
||||
dyn_array_push(
|
||||
/*===========*/
|
||||
dyn_array_t* arr, /*!< in/out: dynamic array */
|
||||
ulint size) /*!< in: size in bytes of the element */
|
||||
__attribute__((nonnull, warn_unused_result));
|
||||
/************************************************************//**
|
||||
Returns pointer to an element in dyn array.
|
||||
@return pointer to element */
|
||||
UNIV_INLINE
|
||||
void*
|
||||
dyn_array_get_element(
|
||||
/*==================*/
|
||||
const dyn_array_t* arr, /*!< in: dyn array */
|
||||
ulint pos) /*!< in: position of element
|
||||
in bytes from array start */
|
||||
__attribute__((nonnull, warn_unused_result));
|
||||
/************************************************************//**
|
||||
Returns the size of stored data in a dyn array.
|
||||
@return data size in bytes */
|
||||
UNIV_INLINE
|
||||
ulint
|
||||
dyn_array_get_data_size(
|
||||
/*====================*/
|
||||
const dyn_array_t* arr) /*!< in: dyn array */
|
||||
__attribute__((nonnull, warn_unused_result, pure));
|
||||
/************************************************************//**
|
||||
Gets the first block in a dyn array.
|
||||
@param arr dyn array
|
||||
@return first block */
|
||||
#define dyn_array_get_first_block(arr) (arr)
|
||||
/************************************************************//**
|
||||
Gets the last block in a dyn array.
|
||||
@param arr dyn array
|
||||
@return last block */
|
||||
#define dyn_array_get_last_block(arr) \
|
||||
((arr)->heap ? UT_LIST_GET_LAST((arr)->base) : (arr))
|
||||
/********************************************************************//**
|
||||
Gets the next block in a dyn array.
|
||||
@param arr dyn array
|
||||
@param block dyn array block
|
||||
@return pointer to next, NULL if end of list */
|
||||
#define dyn_array_get_next_block(arr, block) \
|
||||
((arr)->heap ? UT_LIST_GET_NEXT(list, block) : NULL)
|
||||
/********************************************************************//**
|
||||
Gets the previous block in a dyn array.
|
||||
@param arr dyn array
|
||||
@param block dyn array block
|
||||
@return pointer to previous, NULL if end of list */
|
||||
#define dyn_array_get_prev_block(arr, block) \
|
||||
((arr)->heap ? UT_LIST_GET_PREV(list, block) : NULL)
|
||||
/********************************************************************//**
|
||||
Gets the number of used bytes in a dyn array block.
|
||||
@return number of bytes used */
|
||||
UNIV_INLINE
|
||||
ulint
|
||||
dyn_block_get_used(
|
||||
/*===============*/
|
||||
const dyn_block_t* block) /*!< in: dyn array block */
|
||||
__attribute__((nonnull, warn_unused_result, pure));
|
||||
/********************************************************************//**
|
||||
Gets pointer to the start of data in a dyn array block.
|
||||
@return pointer to data */
|
||||
UNIV_INLINE
|
||||
byte*
|
||||
dyn_block_get_data(
|
||||
/*===============*/
|
||||
const dyn_block_t* block) /*!< in: dyn array block */
|
||||
__attribute__((nonnull, warn_unused_result, pure));
|
||||
/********************************************************//**
|
||||
Pushes n bytes to a dyn array. */
|
||||
UNIV_INLINE
|
||||
void
|
||||
dyn_push_string(
|
||||
/*============*/
|
||||
dyn_array_t* arr, /*!< in/out: dyn array */
|
||||
const byte* str, /*!< in: string to write */
|
||||
ulint len) /*!< in: string length */
|
||||
__attribute__((nonnull));
|
||||
|
||||
/*#################################################################*/
|
||||
|
||||
/** @brief A block in a dynamically allocated array.
|
||||
NOTE! Do not access the fields of the struct directly: the definition
|
||||
appears here only for the compiler to know its size! */
|
||||
struct dyn_block_t{
|
||||
mem_heap_t* heap; /*!< in the first block this is != NULL
|
||||
if dynamic allocation has been needed */
|
||||
ulint used; /*!< number of data bytes used in this block;
|
||||
DYN_BLOCK_FULL_FLAG is set when the block
|
||||
becomes full */
|
||||
byte data[DYN_ARRAY_DATA_SIZE];
|
||||
/*!< storage for array elements */
|
||||
UT_LIST_BASE_NODE_T(dyn_block_t) base;
|
||||
/*!< linear list of dyn blocks: this node is
|
||||
used only in the first block */
|
||||
UT_LIST_NODE_T(dyn_block_t) list;
|
||||
/*!< linear list node: used in all blocks */
|
||||
#ifdef UNIV_DEBUG
|
||||
ulint buf_end;/*!< only in the debug version: if dyn
|
||||
array is opened, this is the buffer
|
||||
end offset, else this is 0 */
|
||||
ulint magic_n;/*!< magic number (DYN_BLOCK_MAGIC_N) */
|
||||
#endif
|
||||
};
|
||||
|
||||
|
||||
#ifndef UNIV_NONINL
|
||||
#include "dyn0dyn.ic"
|
||||
#endif
|
||||
|
||||
#endif
|
||||
306
storage/innobase/include/dyn0dyn.ic
Normal file
306
storage/innobase/include/dyn0dyn.ic
Normal file
|
|
@ -0,0 +1,306 @@
|
|||
/*****************************************************************************
|
||||
|
||||
Copyright (c) 1996, 2013, Oracle and/or its affiliates. All Rights Reserved.
|
||||
|
||||
This program is free software; you can redistribute it and/or modify it under
|
||||
the terms of the GNU General Public License as published by the Free Software
|
||||
Foundation; version 2 of the License.
|
||||
|
||||
This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
|
||||
FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License along with
|
||||
this program; if not, write to the Free Software Foundation, Inc.,
|
||||
51 Franklin Street, Suite 500, Boston, MA 02110-1335 USA
|
||||
|
||||
*****************************************************************************/
|
||||
|
||||
/**************************************************//**
|
||||
@file include/dyn0dyn.ic
|
||||
The dynamically allocated array
|
||||
|
||||
Created 2/5/1996 Heikki Tuuri
|
||||
*******************************************************/
|
||||
|
||||
/** Value of dyn_block_t::magic_n */
|
||||
#define DYN_BLOCK_MAGIC_N 375767
|
||||
/** Flag for dyn_block_t::used that indicates a full block */
|
||||
#define DYN_BLOCK_FULL_FLAG 0x1000000UL
|
||||
|
||||
/************************************************************//**
|
||||
Adds a new block to a dyn array.
|
||||
@return created block */
|
||||
UNIV_INTERN
|
||||
dyn_block_t*
|
||||
dyn_array_add_block(
|
||||
/*================*/
|
||||
dyn_array_t* arr) /*!< in/out: dyn array */
|
||||
__attribute__((nonnull, warn_unused_result));
|
||||
|
||||
/********************************************************************//**
|
||||
Gets the number of used bytes in a dyn array block.
|
||||
@return number of bytes used */
|
||||
UNIV_INLINE
|
||||
ulint
|
||||
dyn_block_get_used(
|
||||
/*===============*/
|
||||
const dyn_block_t* block) /*!< in: dyn array block */
|
||||
{
|
||||
ut_ad(block);
|
||||
|
||||
return((block->used) & ~DYN_BLOCK_FULL_FLAG);
|
||||
}
|
||||
|
||||
/********************************************************************//**
|
||||
Gets pointer to the start of data in a dyn array block.
|
||||
@return pointer to data */
|
||||
UNIV_INLINE
|
||||
byte*
|
||||
dyn_block_get_data(
|
||||
/*===============*/
|
||||
const dyn_block_t* block) /*!< in: dyn array block */
|
||||
{
|
||||
ut_ad(block);
|
||||
|
||||
return(const_cast<byte*>(block->data));
|
||||
}
|
||||
|
||||
/*********************************************************************//**
|
||||
Initializes a dynamic array.
|
||||
@return initialized dyn array */
|
||||
UNIV_INLINE
|
||||
dyn_array_t*
|
||||
dyn_array_create(
|
||||
/*=============*/
|
||||
dyn_array_t* arr) /*!< in/out: memory buffer of
|
||||
size sizeof(dyn_array_t) */
|
||||
{
|
||||
ut_ad(arr);
|
||||
#if DYN_ARRAY_DATA_SIZE >= DYN_BLOCK_FULL_FLAG
|
||||
# error "DYN_ARRAY_DATA_SIZE >= DYN_BLOCK_FULL_FLAG"
|
||||
#endif
|
||||
|
||||
arr->heap = NULL;
|
||||
arr->used = 0;
|
||||
|
||||
ut_d(arr->buf_end = 0);
|
||||
ut_d(arr->magic_n = DYN_BLOCK_MAGIC_N);
|
||||
|
||||
return(arr);
|
||||
}
|
||||
|
||||
/************************************************************//**
|
||||
Frees a dynamic array. */
|
||||
UNIV_INLINE
|
||||
void
|
||||
dyn_array_free(
|
||||
/*===========*/
|
||||
dyn_array_t* arr) /*!< in: dyn array */
|
||||
{
|
||||
if (arr->heap != NULL) {
|
||||
mem_heap_free(arr->heap);
|
||||
}
|
||||
|
||||
ut_d(arr->magic_n = 0);
|
||||
}
|
||||
|
||||
/*********************************************************************//**
|
||||
Makes room on top of a dyn array and returns a pointer to the added element.
|
||||
The caller must copy the element to the pointer returned.
|
||||
@return pointer to the element */
|
||||
UNIV_INLINE
|
||||
void*
|
||||
dyn_array_push(
|
||||
/*===========*/
|
||||
dyn_array_t* arr, /*!< in/out: dynamic array */
|
||||
ulint size) /*!< in: size in bytes of the element */
|
||||
{
|
||||
dyn_block_t* block;
|
||||
ulint used;
|
||||
|
||||
ut_ad(arr);
|
||||
ut_ad(arr->magic_n == DYN_BLOCK_MAGIC_N);
|
||||
ut_ad(size <= DYN_ARRAY_DATA_SIZE);
|
||||
ut_ad(size);
|
||||
|
||||
block = arr;
|
||||
|
||||
if (block->used + size > DYN_ARRAY_DATA_SIZE) {
|
||||
/* Get the last array block */
|
||||
|
||||
block = dyn_array_get_last_block(arr);
|
||||
|
||||
if (block->used + size > DYN_ARRAY_DATA_SIZE) {
|
||||
block = dyn_array_add_block(arr);
|
||||
}
|
||||
}
|
||||
|
||||
used = block->used;
|
||||
|
||||
block->used = used + size;
|
||||
ut_ad(block->used <= DYN_ARRAY_DATA_SIZE);
|
||||
|
||||
return(block->data + used);
|
||||
}
|
||||
|
||||
/*********************************************************************//**
|
||||
Makes room on top of a dyn array and returns a pointer to a buffer in it.
|
||||
After copying the elements, the caller must close the buffer using
|
||||
dyn_array_close.
|
||||
@return pointer to the buffer */
|
||||
UNIV_INLINE
|
||||
byte*
|
||||
dyn_array_open(
|
||||
/*===========*/
|
||||
dyn_array_t* arr, /*!< in: dynamic array */
|
||||
ulint size) /*!< in: size in bytes of the buffer; MUST be
|
||||
smaller than DYN_ARRAY_DATA_SIZE! */
|
||||
{
|
||||
dyn_block_t* block;
|
||||
|
||||
ut_ad(arr);
|
||||
ut_ad(arr->magic_n == DYN_BLOCK_MAGIC_N);
|
||||
ut_ad(size <= DYN_ARRAY_DATA_SIZE);
|
||||
ut_ad(size);
|
||||
|
||||
block = arr;
|
||||
|
||||
if (block->used + size > DYN_ARRAY_DATA_SIZE) {
|
||||
/* Get the last array block */
|
||||
|
||||
block = dyn_array_get_last_block(arr);
|
||||
|
||||
if (block->used + size > DYN_ARRAY_DATA_SIZE) {
|
||||
block = dyn_array_add_block(arr);
|
||||
ut_a(size <= DYN_ARRAY_DATA_SIZE);
|
||||
}
|
||||
}
|
||||
|
||||
ut_ad(block->used <= DYN_ARRAY_DATA_SIZE);
|
||||
ut_ad(arr->buf_end == 0);
|
||||
ut_d(arr->buf_end = block->used + size);
|
||||
|
||||
return(block->data + block->used);
|
||||
}
|
||||
|
||||
/*********************************************************************//**
|
||||
Closes the buffer returned by dyn_array_open. */
|
||||
UNIV_INLINE
|
||||
void
|
||||
dyn_array_close(
|
||||
/*============*/
|
||||
dyn_array_t* arr, /*!< in/out: dynamic array */
|
||||
const byte* ptr) /*!< in: end of used space */
|
||||
{
|
||||
dyn_block_t* block;
|
||||
|
||||
ut_ad(arr);
|
||||
ut_ad(arr->magic_n == DYN_BLOCK_MAGIC_N);
|
||||
|
||||
block = dyn_array_get_last_block(arr);
|
||||
|
||||
ut_ad(arr->buf_end + block->data >= ptr);
|
||||
|
||||
block->used = ptr - block->data;
|
||||
|
||||
ut_ad(block->used <= DYN_ARRAY_DATA_SIZE);
|
||||
|
||||
ut_d(arr->buf_end = 0);
|
||||
}
|
||||
|
||||
/************************************************************//**
|
||||
Returns pointer to an element in dyn array.
|
||||
@return pointer to element */
|
||||
UNIV_INLINE
|
||||
void*
|
||||
dyn_array_get_element(
|
||||
/*==================*/
|
||||
const dyn_array_t* arr, /*!< in: dyn array */
|
||||
ulint pos) /*!< in: position of element
|
||||
in bytes from array start */
|
||||
{
|
||||
const dyn_block_t* block;
|
||||
|
||||
ut_ad(arr);
|
||||
ut_ad(arr->magic_n == DYN_BLOCK_MAGIC_N);
|
||||
|
||||
/* Get the first array block */
|
||||
block = dyn_array_get_first_block(arr);
|
||||
|
||||
if (arr->heap != NULL) {
|
||||
for (;;) {
|
||||
ulint used = dyn_block_get_used(block);
|
||||
|
||||
if (pos < used) {
|
||||
break;
|
||||
}
|
||||
|
||||
pos -= used;
|
||||
block = UT_LIST_GET_NEXT(list, block);
|
||||
ut_ad(block);
|
||||
}
|
||||
}
|
||||
|
||||
ut_ad(block);
|
||||
ut_ad(dyn_block_get_used(block) >= pos);
|
||||
|
||||
return(const_cast<byte*>(block->data) + pos);
|
||||
}
|
||||
|
||||
/************************************************************//**
|
||||
Returns the size of stored data in a dyn array.
|
||||
@return data size in bytes */
|
||||
UNIV_INLINE
|
||||
ulint
|
||||
dyn_array_get_data_size(
|
||||
/*====================*/
|
||||
const dyn_array_t* arr) /*!< in: dyn array */
|
||||
{
|
||||
const dyn_block_t* block;
|
||||
ulint sum = 0;
|
||||
|
||||
ut_ad(arr);
|
||||
ut_ad(arr->magic_n == DYN_BLOCK_MAGIC_N);
|
||||
|
||||
if (arr->heap == NULL) {
|
||||
|
||||
return(arr->used);
|
||||
}
|
||||
|
||||
/* Get the first array block */
|
||||
block = dyn_array_get_first_block(arr);
|
||||
|
||||
while (block != NULL) {
|
||||
sum += dyn_block_get_used(block);
|
||||
block = dyn_array_get_next_block(arr, block);
|
||||
}
|
||||
|
||||
return(sum);
|
||||
}
|
||||
|
||||
/********************************************************//**
|
||||
Pushes n bytes to a dyn array. */
|
||||
UNIV_INLINE
|
||||
void
|
||||
dyn_push_string(
|
||||
/*============*/
|
||||
dyn_array_t* arr, /*!< in/out: dyn array */
|
||||
const byte* str, /*!< in: string to write */
|
||||
ulint len) /*!< in: string length */
|
||||
{
|
||||
ulint n_copied;
|
||||
|
||||
while (len > 0) {
|
||||
if (len > DYN_ARRAY_DATA_SIZE) {
|
||||
n_copied = DYN_ARRAY_DATA_SIZE;
|
||||
} else {
|
||||
n_copied = len;
|
||||
}
|
||||
|
||||
memcpy(dyn_array_push(arr, n_copied), str, n_copied);
|
||||
|
||||
str += n_copied;
|
||||
len -= n_copied;
|
||||
}
|
||||
}
|
||||
114
storage/innobase/include/eval0eval.h
Normal file
114
storage/innobase/include/eval0eval.h
Normal file
|
|
@ -0,0 +1,114 @@
|
|||
/*****************************************************************************
|
||||
|
||||
Copyright (c) 1997, 2009, Oracle and/or its affiliates. All Rights Reserved.
|
||||
|
||||
This program is free software; you can redistribute it and/or modify it under
|
||||
the terms of the GNU General Public License as published by the Free Software
|
||||
Foundation; version 2 of the License.
|
||||
|
||||
This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
|
||||
FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License along with
|
||||
this program; if not, write to the Free Software Foundation, Inc.,
|
||||
51 Franklin Street, Suite 500, Boston, MA 02110-1335 USA
|
||||
|
||||
*****************************************************************************/
|
||||
|
||||
/**************************************************//**
|
||||
@file include/eval0eval.h
|
||||
SQL evaluator: evaluates simple data structures, like expressions, in
|
||||
a query graph
|
||||
|
||||
Created 12/29/1997 Heikki Tuuri
|
||||
*******************************************************/
|
||||
|
||||
#ifndef eval0eval_h
|
||||
#define eval0eval_h
|
||||
|
||||
#include "univ.i"
|
||||
#include "que0types.h"
|
||||
#include "pars0sym.h"
|
||||
#include "pars0pars.h"
|
||||
|
||||
/*****************************************************************//**
|
||||
Free the buffer from global dynamic memory for a value of a que_node,
|
||||
if it has been allocated in the above function. The freeing for pushed
|
||||
column values is done in sel_col_prefetch_buf_free. */
|
||||
UNIV_INTERN
|
||||
void
|
||||
eval_node_free_val_buf(
|
||||
/*===================*/
|
||||
que_node_t* node); /*!< in: query graph node */
|
||||
/*****************************************************************//**
|
||||
Evaluates a symbol table symbol. */
|
||||
UNIV_INLINE
|
||||
void
|
||||
eval_sym(
|
||||
/*=====*/
|
||||
sym_node_t* sym_node); /*!< in: symbol table node */
|
||||
/*****************************************************************//**
|
||||
Evaluates an expression. */
|
||||
UNIV_INLINE
|
||||
void
|
||||
eval_exp(
|
||||
/*=====*/
|
||||
que_node_t* exp_node); /*!< in: expression */
|
||||
/*****************************************************************//**
|
||||
Sets an integer value as the value of an expression node. */
|
||||
UNIV_INLINE
|
||||
void
|
||||
eval_node_set_int_val(
|
||||
/*==================*/
|
||||
que_node_t* node, /*!< in: expression node */
|
||||
lint val); /*!< in: value to set */
|
||||
/*****************************************************************//**
|
||||
Gets an integer value from an expression node.
|
||||
@return integer value */
|
||||
UNIV_INLINE
|
||||
lint
|
||||
eval_node_get_int_val(
|
||||
/*==================*/
|
||||
que_node_t* node); /*!< in: expression node */
|
||||
/*****************************************************************//**
|
||||
Copies a binary string value as the value of a query graph node. Allocates a
|
||||
new buffer if necessary. */
|
||||
UNIV_INLINE
|
||||
void
|
||||
eval_node_copy_and_alloc_val(
|
||||
/*=========================*/
|
||||
que_node_t* node, /*!< in: query graph node */
|
||||
const byte* str, /*!< in: binary string */
|
||||
ulint len); /*!< in: string length or UNIV_SQL_NULL */
|
||||
/*****************************************************************//**
|
||||
Copies a query node value to another node. */
|
||||
UNIV_INLINE
|
||||
void
|
||||
eval_node_copy_val(
|
||||
/*===============*/
|
||||
que_node_t* node1, /*!< in: node to copy to */
|
||||
que_node_t* node2); /*!< in: node to copy from */
|
||||
/*****************************************************************//**
|
||||
Gets a iboolean value from a query node.
|
||||
@return iboolean value */
|
||||
UNIV_INLINE
|
||||
ibool
|
||||
eval_node_get_ibool_val(
|
||||
/*====================*/
|
||||
que_node_t* node); /*!< in: query graph node */
|
||||
/*****************************************************************//**
|
||||
Evaluates a comparison node.
|
||||
@return the result of the comparison */
|
||||
UNIV_INTERN
|
||||
ibool
|
||||
eval_cmp(
|
||||
/*=====*/
|
||||
func_node_t* cmp_node); /*!< in: comparison node */
|
||||
|
||||
|
||||
#ifndef UNIV_NONINL
|
||||
#include "eval0eval.ic"
|
||||
#endif
|
||||
|
||||
#endif
|
||||
255
storage/innobase/include/eval0eval.ic
Normal file
255
storage/innobase/include/eval0eval.ic
Normal file
|
|
@ -0,0 +1,255 @@
|
|||
/*****************************************************************************
|
||||
|
||||
Copyright (c) 1997, 2011, Oracle and/or its affiliates. All Rights Reserved.
|
||||
|
||||
This program is free software; you can redistribute it and/or modify it under
|
||||
the terms of the GNU General Public License as published by the Free Software
|
||||
Foundation; version 2 of the License.
|
||||
|
||||
This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
|
||||
FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License along with
|
||||
this program; if not, write to the Free Software Foundation, Inc.,
|
||||
51 Franklin Street, Suite 500, Boston, MA 02110-1335 USA
|
||||
|
||||
*****************************************************************************/
|
||||
|
||||
/**************************************************//**
|
||||
@file include/eval0eval.ic
|
||||
SQL evaluator: evaluates simple data structures, like expressions, in
|
||||
a query graph
|
||||
|
||||
Created 12/29/1997 Heikki Tuuri
|
||||
*******************************************************/
|
||||
|
||||
#include "que0que.h"
|
||||
#include "rem0cmp.h"
|
||||
#include "pars0grm.h"
|
||||
|
||||
/*****************************************************************//**
|
||||
Evaluates a function node. */
|
||||
UNIV_INTERN
|
||||
void
|
||||
eval_func(
|
||||
/*======*/
|
||||
func_node_t* func_node); /*!< in: function node */
|
||||
/*****************************************************************//**
|
||||
Allocate a buffer from global dynamic memory for a value of a que_node.
|
||||
NOTE that this memory must be explicitly freed when the query graph is
|
||||
freed. If the node already has allocated buffer, that buffer is freed
|
||||
here. NOTE that this is the only function where dynamic memory should be
|
||||
allocated for a query node val field.
|
||||
@return pointer to allocated buffer */
|
||||
UNIV_INTERN
|
||||
byte*
|
||||
eval_node_alloc_val_buf(
|
||||
/*====================*/
|
||||
que_node_t* node, /*!< in: query graph node; sets the val field
|
||||
data field to point to the new buffer, and
|
||||
len field equal to size */
|
||||
ulint size); /*!< in: buffer size */
|
||||
|
||||
|
||||
/*****************************************************************//**
|
||||
Allocates a new buffer if needed.
|
||||
@return pointer to buffer */
|
||||
UNIV_INLINE
|
||||
byte*
|
||||
eval_node_ensure_val_buf(
|
||||
/*=====================*/
|
||||
que_node_t* node, /*!< in: query graph node; sets the val field
|
||||
data field to point to the new buffer, and
|
||||
len field equal to size */
|
||||
ulint size) /*!< in: buffer size */
|
||||
{
|
||||
dfield_t* dfield;
|
||||
byte* data;
|
||||
|
||||
dfield = que_node_get_val(node);
|
||||
dfield_set_len(dfield, size);
|
||||
|
||||
data = static_cast<byte*>(dfield_get_data(dfield));
|
||||
|
||||
if (!data || que_node_get_val_buf_size(node) < size) {
|
||||
|
||||
data = eval_node_alloc_val_buf(node, size);
|
||||
}
|
||||
|
||||
return(data);
|
||||
}
|
||||
|
||||
/*****************************************************************//**
|
||||
Evaluates a symbol table symbol. */
|
||||
UNIV_INLINE
|
||||
void
|
||||
eval_sym(
|
||||
/*=====*/
|
||||
sym_node_t* sym_node) /*!< in: symbol table node */
|
||||
{
|
||||
|
||||
ut_ad(que_node_get_type(sym_node) == QUE_NODE_SYMBOL);
|
||||
|
||||
if (sym_node->indirection) {
|
||||
/* The symbol table node is an alias for a variable or a
|
||||
column */
|
||||
|
||||
dfield_copy_data(que_node_get_val(sym_node),
|
||||
que_node_get_val(sym_node->indirection));
|
||||
}
|
||||
}
|
||||
|
||||
/*****************************************************************//**
|
||||
Evaluates an expression. */
|
||||
UNIV_INLINE
|
||||
void
|
||||
eval_exp(
|
||||
/*=====*/
|
||||
que_node_t* exp_node) /*!< in: expression */
|
||||
{
|
||||
if (que_node_get_type(exp_node) == QUE_NODE_SYMBOL) {
|
||||
|
||||
eval_sym((sym_node_t*) exp_node);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
eval_func(static_cast<func_node_t*>(exp_node));
|
||||
}
|
||||
|
||||
/*****************************************************************//**
|
||||
Sets an integer value as the value of an expression node. */
|
||||
UNIV_INLINE
|
||||
void
|
||||
eval_node_set_int_val(
|
||||
/*==================*/
|
||||
que_node_t* node, /*!< in: expression node */
|
||||
lint val) /*!< in: value to set */
|
||||
{
|
||||
dfield_t* dfield;
|
||||
byte* data;
|
||||
|
||||
dfield = que_node_get_val(node);
|
||||
|
||||
data = static_cast<byte*>(dfield_get_data(dfield));
|
||||
|
||||
if (data == NULL) {
|
||||
data = eval_node_alloc_val_buf(node, 4);
|
||||
}
|
||||
|
||||
ut_ad(dfield_get_len(dfield) == 4);
|
||||
|
||||
mach_write_to_4(data, (ulint) val);
|
||||
}
|
||||
|
||||
/*****************************************************************//**
|
||||
Gets an integer non-SQL null value from an expression node.
|
||||
@return integer value */
|
||||
UNIV_INLINE
|
||||
lint
|
||||
eval_node_get_int_val(
|
||||
/*==================*/
|
||||
que_node_t* node) /*!< in: expression node */
|
||||
{
|
||||
const byte* ptr;
|
||||
dfield_t* dfield;
|
||||
|
||||
dfield = que_node_get_val(node);
|
||||
ptr = static_cast<byte*>(dfield_get_data(dfield));
|
||||
|
||||
ut_ad(dfield_get_len(dfield) == 4);
|
||||
|
||||
return((int) mach_read_from_4(ptr));
|
||||
}
|
||||
|
||||
/*****************************************************************//**
|
||||
Gets a iboolean value from a query node.
|
||||
@return iboolean value */
|
||||
UNIV_INLINE
|
||||
ibool
|
||||
eval_node_get_ibool_val(
|
||||
/*====================*/
|
||||
que_node_t* node) /*!< in: query graph node */
|
||||
{
|
||||
dfield_t* dfield;
|
||||
byte* data;
|
||||
|
||||
dfield = que_node_get_val(node);
|
||||
|
||||
data = static_cast<byte*>(dfield_get_data(dfield));
|
||||
|
||||
ut_ad(data != NULL);
|
||||
|
||||
return(mach_read_from_1(data));
|
||||
}
|
||||
|
||||
/*****************************************************************//**
|
||||
Sets a iboolean value as the value of a function node. */
|
||||
UNIV_INLINE
|
||||
void
|
||||
eval_node_set_ibool_val(
|
||||
/*====================*/
|
||||
func_node_t* func_node, /*!< in: function node */
|
||||
ibool val) /*!< in: value to set */
|
||||
{
|
||||
dfield_t* dfield;
|
||||
byte* data;
|
||||
|
||||
dfield = que_node_get_val(func_node);
|
||||
|
||||
data = static_cast<byte*>(dfield_get_data(dfield));
|
||||
|
||||
if (data == NULL) {
|
||||
/* Allocate 1 byte to hold the value */
|
||||
|
||||
data = eval_node_alloc_val_buf(func_node, 1);
|
||||
}
|
||||
|
||||
ut_ad(dfield_get_len(dfield) == 1);
|
||||
|
||||
mach_write_to_1(data, val);
|
||||
}
|
||||
|
||||
/*****************************************************************//**
|
||||
Copies a binary string value as the value of a query graph node. Allocates a
|
||||
new buffer if necessary. */
|
||||
UNIV_INLINE
|
||||
void
|
||||
eval_node_copy_and_alloc_val(
|
||||
/*=========================*/
|
||||
que_node_t* node, /*!< in: query graph node */
|
||||
const byte* str, /*!< in: binary string */
|
||||
ulint len) /*!< in: string length or UNIV_SQL_NULL */
|
||||
{
|
||||
byte* data;
|
||||
|
||||
if (len == UNIV_SQL_NULL) {
|
||||
dfield_set_len(que_node_get_val(node), len);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
data = eval_node_ensure_val_buf(node, len);
|
||||
|
||||
ut_memcpy(data, str, len);
|
||||
}
|
||||
|
||||
/*****************************************************************//**
|
||||
Copies a query node value to another node. */
|
||||
UNIV_INLINE
|
||||
void
|
||||
eval_node_copy_val(
|
||||
/*===============*/
|
||||
que_node_t* node1, /*!< in: node to copy to */
|
||||
que_node_t* node2) /*!< in: node to copy from */
|
||||
{
|
||||
dfield_t* dfield2;
|
||||
|
||||
dfield2 = que_node_get_val(node2);
|
||||
|
||||
eval_node_copy_and_alloc_val(
|
||||
node1,
|
||||
static_cast<byte*>(dfield_get_data(dfield2)),
|
||||
dfield_get_len(dfield2));
|
||||
}
|
||||
104
storage/innobase/include/eval0proc.h
Normal file
104
storage/innobase/include/eval0proc.h
Normal file
|
|
@ -0,0 +1,104 @@
|
|||
/*****************************************************************************
|
||||
|
||||
Copyright (c) 1998, 2009, Oracle and/or its affiliates. All Rights Reserved.
|
||||
|
||||
This program is free software; you can redistribute it and/or modify it under
|
||||
the terms of the GNU General Public License as published by the Free Software
|
||||
Foundation; version 2 of the License.
|
||||
|
||||
This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
|
||||
FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License along with
|
||||
this program; if not, write to the Free Software Foundation, Inc.,
|
||||
51 Franklin Street, Suite 500, Boston, MA 02110-1335 USA
|
||||
|
||||
*****************************************************************************/
|
||||
|
||||
/**************************************************//**
|
||||
@file include/eval0proc.h
|
||||
Executes SQL stored procedures and their control structures
|
||||
|
||||
Created 1/20/1998 Heikki Tuuri
|
||||
*******************************************************/
|
||||
|
||||
#ifndef eval0proc_h
|
||||
#define eval0proc_h
|
||||
|
||||
#include "univ.i"
|
||||
#include "que0types.h"
|
||||
#include "pars0sym.h"
|
||||
#include "pars0pars.h"
|
||||
|
||||
/**********************************************************************//**
|
||||
Performs an execution step of a procedure node.
|
||||
@return query thread to run next or NULL */
|
||||
UNIV_INLINE
|
||||
que_thr_t*
|
||||
proc_step(
|
||||
/*======*/
|
||||
que_thr_t* thr); /*!< in: query thread */
|
||||
/**********************************************************************//**
|
||||
Performs an execution step of an if-statement node.
|
||||
@return query thread to run next or NULL */
|
||||
UNIV_INTERN
|
||||
que_thr_t*
|
||||
if_step(
|
||||
/*====*/
|
||||
que_thr_t* thr); /*!< in: query thread */
|
||||
/**********************************************************************//**
|
||||
Performs an execution step of a while-statement node.
|
||||
@return query thread to run next or NULL */
|
||||
UNIV_INTERN
|
||||
que_thr_t*
|
||||
while_step(
|
||||
/*=======*/
|
||||
que_thr_t* thr); /*!< in: query thread */
|
||||
/**********************************************************************//**
|
||||
Performs an execution step of a for-loop node.
|
||||
@return query thread to run next or NULL */
|
||||
UNIV_INTERN
|
||||
que_thr_t*
|
||||
for_step(
|
||||
/*=====*/
|
||||
que_thr_t* thr); /*!< in: query thread */
|
||||
/**********************************************************************//**
|
||||
Performs an execution step of an assignment statement node.
|
||||
@return query thread to run next or NULL */
|
||||
UNIV_INTERN
|
||||
que_thr_t*
|
||||
assign_step(
|
||||
/*========*/
|
||||
que_thr_t* thr); /*!< in: query thread */
|
||||
/**********************************************************************//**
|
||||
Performs an execution step of a procedure call node.
|
||||
@return query thread to run next or NULL */
|
||||
UNIV_INLINE
|
||||
que_thr_t*
|
||||
proc_eval_step(
|
||||
/*===========*/
|
||||
que_thr_t* thr); /*!< in: query thread */
|
||||
/**********************************************************************//**
|
||||
Performs an execution step of an exit statement node.
|
||||
@return query thread to run next or NULL */
|
||||
UNIV_INTERN
|
||||
que_thr_t*
|
||||
exit_step(
|
||||
/*======*/
|
||||
que_thr_t* thr); /*!< in: query thread */
|
||||
/**********************************************************************//**
|
||||
Performs an execution step of a return-statement node.
|
||||
@return query thread to run next or NULL */
|
||||
UNIV_INTERN
|
||||
que_thr_t*
|
||||
return_step(
|
||||
/*========*/
|
||||
que_thr_t* thr); /*!< in: query thread */
|
||||
|
||||
|
||||
#ifndef UNIV_NONINL
|
||||
#include "eval0proc.ic"
|
||||
#endif
|
||||
|
||||
#endif
|
||||
88
storage/innobase/include/eval0proc.ic
Normal file
88
storage/innobase/include/eval0proc.ic
Normal file
|
|
@ -0,0 +1,88 @@
|
|||
/*****************************************************************************
|
||||
|
||||
Copyright (c) 1998, 2011, Oracle and/or its affiliates. All Rights Reserved.
|
||||
|
||||
This program is free software; you can redistribute it and/or modify it under
|
||||
the terms of the GNU General Public License as published by the Free Software
|
||||
Foundation; version 2 of the License.
|
||||
|
||||
This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
|
||||
FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License along with
|
||||
this program; if not, write to the Free Software Foundation, Inc.,
|
||||
51 Franklin Street, Suite 500, Boston, MA 02110-1335 USA
|
||||
|
||||
*****************************************************************************/
|
||||
|
||||
/**************************************************//**
|
||||
@file include/eval0proc.ic
|
||||
Executes SQL stored procedures and their control structures
|
||||
|
||||
Created 1/20/1998 Heikki Tuuri
|
||||
*******************************************************/
|
||||
|
||||
#include "pars0pars.h"
|
||||
#include "que0que.h"
|
||||
#include "eval0eval.h"
|
||||
|
||||
/**********************************************************************//**
|
||||
Performs an execution step of a procedure node.
|
||||
@return query thread to run next or NULL */
|
||||
UNIV_INLINE
|
||||
que_thr_t*
|
||||
proc_step(
|
||||
/*======*/
|
||||
que_thr_t* thr) /*!< in: query thread */
|
||||
{
|
||||
proc_node_t* node;
|
||||
|
||||
ut_ad(thr);
|
||||
|
||||
node = static_cast<proc_node_t*>(thr->run_node);
|
||||
ut_ad(que_node_get_type(node) == QUE_NODE_PROC);
|
||||
|
||||
if (thr->prev_node == que_node_get_parent(node)) {
|
||||
/* Start execution from the first statement in the statement
|
||||
list */
|
||||
|
||||
thr->run_node = node->stat_list;
|
||||
} else {
|
||||
/* Move to the next statement */
|
||||
ut_ad(que_node_get_next(thr->prev_node) == NULL);
|
||||
|
||||
thr->run_node = NULL;
|
||||
}
|
||||
|
||||
if (thr->run_node == NULL) {
|
||||
thr->run_node = que_node_get_parent(node);
|
||||
}
|
||||
|
||||
return(thr);
|
||||
}
|
||||
|
||||
/**********************************************************************//**
|
||||
Performs an execution step of a procedure call node.
|
||||
@return query thread to run next or NULL */
|
||||
UNIV_INLINE
|
||||
que_thr_t*
|
||||
proc_eval_step(
|
||||
/*===========*/
|
||||
que_thr_t* thr) /*!< in: query thread */
|
||||
{
|
||||
func_node_t* node;
|
||||
|
||||
ut_ad(thr);
|
||||
|
||||
node = static_cast<func_node_t*>(thr->run_node);
|
||||
ut_ad(que_node_get_type(node) == QUE_NODE_FUNC);
|
||||
|
||||
/* Evaluate the procedure */
|
||||
|
||||
eval_exp(node);
|
||||
|
||||
thr->run_node = que_node_get_parent(node);
|
||||
|
||||
return(thr);
|
||||
}
|
||||
1019
storage/innobase/include/fil0fil.h
Normal file
1019
storage/innobase/include/fil0fil.h
Normal file
File diff suppressed because it is too large
Load diff
747
storage/innobase/include/fsp0fsp.h
Normal file
747
storage/innobase/include/fsp0fsp.h
Normal file
|
|
@ -0,0 +1,747 @@
|
|||
/*****************************************************************************
|
||||
|
||||
Copyright (c) 1995, 2012, Oracle and/or its affiliates. All Rights Reserved.
|
||||
|
||||
This program is free software; you can redistribute it and/or modify it under
|
||||
the terms of the GNU General Public License as published by the Free Software
|
||||
Foundation; version 2 of the License.
|
||||
|
||||
This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
|
||||
FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License along with
|
||||
this program; if not, write to the Free Software Foundation, Inc.,
|
||||
51 Franklin Street, Suite 500, Boston, MA 02110-1335 USA
|
||||
|
||||
*****************************************************************************/
|
||||
|
||||
/**************************************************//**
|
||||
@file include/fsp0fsp.h
|
||||
File space management
|
||||
|
||||
Created 12/18/1995 Heikki Tuuri
|
||||
*******************************************************/
|
||||
|
||||
#ifndef fsp0fsp_h
|
||||
#define fsp0fsp_h
|
||||
|
||||
#include "univ.i"
|
||||
|
||||
#ifndef UNIV_INNOCHECKSUM
|
||||
|
||||
#include "mtr0mtr.h"
|
||||
#include "fut0lst.h"
|
||||
#include "ut0byte.h"
|
||||
#include "page0types.h"
|
||||
#include "fsp0types.h"
|
||||
|
||||
#endif /* !UNIV_INNOCHECKSUM */
|
||||
|
||||
/* @defgroup fsp_flags InnoDB Tablespace Flag Constants @{ */
|
||||
|
||||
/** Width of the POST_ANTELOPE flag */
|
||||
#define FSP_FLAGS_WIDTH_POST_ANTELOPE 1
|
||||
/** Number of flag bits used to indicate the tablespace zip page size */
|
||||
#define FSP_FLAGS_WIDTH_ZIP_SSIZE 4
|
||||
/** Width of the ATOMIC_BLOBS flag. The ability to break up a long
|
||||
column into an in-record prefix and an externally stored part is available
|
||||
to the two Barracuda row formats COMPRESSED and DYNAMIC. */
|
||||
#define FSP_FLAGS_WIDTH_ATOMIC_BLOBS 1
|
||||
/** Number of flag bits used to indicate the tablespace page size */
|
||||
#define FSP_FLAGS_WIDTH_PAGE_SSIZE 4
|
||||
/** Width of the DATA_DIR flag. This flag indicates that the tablespace
|
||||
is found in a remote location, not the default data directory. */
|
||||
#define FSP_FLAGS_WIDTH_DATA_DIR 1
|
||||
/** Width of all the currently known tablespace flags */
|
||||
#define FSP_FLAGS_WIDTH (FSP_FLAGS_WIDTH_POST_ANTELOPE \
|
||||
+ FSP_FLAGS_WIDTH_ZIP_SSIZE \
|
||||
+ FSP_FLAGS_WIDTH_ATOMIC_BLOBS \
|
||||
+ FSP_FLAGS_WIDTH_PAGE_SSIZE \
|
||||
+ FSP_FLAGS_WIDTH_DATA_DIR)
|
||||
|
||||
/** A mask of all the known/used bits in tablespace flags */
|
||||
#define FSP_FLAGS_MASK (~(~0 << FSP_FLAGS_WIDTH))
|
||||
|
||||
/** Zero relative shift position of the POST_ANTELOPE field */
|
||||
#define FSP_FLAGS_POS_POST_ANTELOPE 0
|
||||
/** Zero relative shift position of the ZIP_SSIZE field */
|
||||
#define FSP_FLAGS_POS_ZIP_SSIZE (FSP_FLAGS_POS_POST_ANTELOPE \
|
||||
+ FSP_FLAGS_WIDTH_POST_ANTELOPE)
|
||||
/** Zero relative shift position of the ATOMIC_BLOBS field */
|
||||
#define FSP_FLAGS_POS_ATOMIC_BLOBS (FSP_FLAGS_POS_ZIP_SSIZE \
|
||||
+ FSP_FLAGS_WIDTH_ZIP_SSIZE)
|
||||
/** Zero relative shift position of the PAGE_SSIZE field */
|
||||
#define FSP_FLAGS_POS_PAGE_SSIZE (FSP_FLAGS_POS_ATOMIC_BLOBS \
|
||||
+ FSP_FLAGS_WIDTH_ATOMIC_BLOBS)
|
||||
/** Zero relative shift position of the start of the UNUSED bits */
|
||||
#define FSP_FLAGS_POS_DATA_DIR (FSP_FLAGS_POS_PAGE_SSIZE \
|
||||
+ FSP_FLAGS_WIDTH_PAGE_SSIZE)
|
||||
/** Zero relative shift position of the start of the UNUSED bits */
|
||||
#define FSP_FLAGS_POS_UNUSED (FSP_FLAGS_POS_DATA_DIR \
|
||||
+ FSP_FLAGS_WIDTH_DATA_DIR)
|
||||
|
||||
/** Bit mask of the POST_ANTELOPE field */
|
||||
#define FSP_FLAGS_MASK_POST_ANTELOPE \
|
||||
((~(~0 << FSP_FLAGS_WIDTH_POST_ANTELOPE)) \
|
||||
<< FSP_FLAGS_POS_POST_ANTELOPE)
|
||||
/** Bit mask of the ZIP_SSIZE field */
|
||||
#define FSP_FLAGS_MASK_ZIP_SSIZE \
|
||||
((~(~0 << FSP_FLAGS_WIDTH_ZIP_SSIZE)) \
|
||||
<< FSP_FLAGS_POS_ZIP_SSIZE)
|
||||
/** Bit mask of the ATOMIC_BLOBS field */
|
||||
#define FSP_FLAGS_MASK_ATOMIC_BLOBS \
|
||||
((~(~0 << FSP_FLAGS_WIDTH_ATOMIC_BLOBS)) \
|
||||
<< FSP_FLAGS_POS_ATOMIC_BLOBS)
|
||||
/** Bit mask of the PAGE_SSIZE field */
|
||||
#define FSP_FLAGS_MASK_PAGE_SSIZE \
|
||||
((~(~0 << FSP_FLAGS_WIDTH_PAGE_SSIZE)) \
|
||||
<< FSP_FLAGS_POS_PAGE_SSIZE)
|
||||
/** Bit mask of the DATA_DIR field */
|
||||
#define FSP_FLAGS_MASK_DATA_DIR \
|
||||
((~(~0 << FSP_FLAGS_WIDTH_DATA_DIR)) \
|
||||
<< FSP_FLAGS_POS_DATA_DIR)
|
||||
|
||||
/** Return the value of the POST_ANTELOPE field */
|
||||
#define FSP_FLAGS_GET_POST_ANTELOPE(flags) \
|
||||
((flags & FSP_FLAGS_MASK_POST_ANTELOPE) \
|
||||
>> FSP_FLAGS_POS_POST_ANTELOPE)
|
||||
/** Return the value of the ZIP_SSIZE field */
|
||||
#define FSP_FLAGS_GET_ZIP_SSIZE(flags) \
|
||||
((flags & FSP_FLAGS_MASK_ZIP_SSIZE) \
|
||||
>> FSP_FLAGS_POS_ZIP_SSIZE)
|
||||
/** Return the value of the ATOMIC_BLOBS field */
|
||||
#define FSP_FLAGS_HAS_ATOMIC_BLOBS(flags) \
|
||||
((flags & FSP_FLAGS_MASK_ATOMIC_BLOBS) \
|
||||
>> FSP_FLAGS_POS_ATOMIC_BLOBS)
|
||||
/** Return the value of the PAGE_SSIZE field */
|
||||
#define FSP_FLAGS_GET_PAGE_SSIZE(flags) \
|
||||
((flags & FSP_FLAGS_MASK_PAGE_SSIZE) \
|
||||
>> FSP_FLAGS_POS_PAGE_SSIZE)
|
||||
/** Return the value of the DATA_DIR field */
|
||||
#define FSP_FLAGS_HAS_DATA_DIR(flags) \
|
||||
((flags & FSP_FLAGS_MASK_DATA_DIR) \
|
||||
>> FSP_FLAGS_POS_DATA_DIR)
|
||||
/** Return the contents of the UNUSED bits */
|
||||
#define FSP_FLAGS_GET_UNUSED(flags) \
|
||||
(flags >> FSP_FLAGS_POS_UNUSED)
|
||||
|
||||
/** Set a PAGE_SSIZE into the correct bits in a given
|
||||
tablespace flags. */
|
||||
#define FSP_FLAGS_SET_PAGE_SSIZE(flags, ssize) \
|
||||
(flags | (ssize << FSP_FLAGS_POS_PAGE_SSIZE))
|
||||
|
||||
/* @} */
|
||||
|
||||
/* @defgroup Tablespace Header Constants (moved from fsp0fsp.c) @{ */
|
||||
|
||||
/** Offset of the space header within a file page */
|
||||
#define FSP_HEADER_OFFSET FIL_PAGE_DATA
|
||||
|
||||
/* The data structures in files are defined just as byte strings in C */
|
||||
typedef byte fsp_header_t;
|
||||
typedef byte xdes_t;
|
||||
|
||||
/* SPACE HEADER
|
||||
============
|
||||
|
||||
File space header data structure: this data structure is contained in the
|
||||
first page of a space. The space for this header is reserved in every extent
|
||||
descriptor page, but used only in the first. */
|
||||
|
||||
/*-------------------------------------*/
|
||||
#define FSP_SPACE_ID 0 /* space id */
|
||||
#define FSP_NOT_USED 4 /* this field contained a value up to
|
||||
which we know that the modifications
|
||||
in the database have been flushed to
|
||||
the file space; not used now */
|
||||
#define FSP_SIZE 8 /* Current size of the space in
|
||||
pages */
|
||||
#define FSP_FREE_LIMIT 12 /* Minimum page number for which the
|
||||
free list has not been initialized:
|
||||
the pages >= this limit are, by
|
||||
definition, free; note that in a
|
||||
single-table tablespace where size
|
||||
< 64 pages, this number is 64, i.e.,
|
||||
we have initialized the space
|
||||
about the first extent, but have not
|
||||
physically allocted those pages to the
|
||||
file */
|
||||
#define FSP_SPACE_FLAGS 16 /* fsp_space_t.flags, similar to
|
||||
dict_table_t::flags */
|
||||
#define FSP_FRAG_N_USED 20 /* number of used pages in the
|
||||
FSP_FREE_FRAG list */
|
||||
#define FSP_FREE 24 /* list of free extents */
|
||||
#define FSP_FREE_FRAG (24 + FLST_BASE_NODE_SIZE)
|
||||
/* list of partially free extents not
|
||||
belonging to any segment */
|
||||
#define FSP_FULL_FRAG (24 + 2 * FLST_BASE_NODE_SIZE)
|
||||
/* list of full extents not belonging
|
||||
to any segment */
|
||||
#define FSP_SEG_ID (24 + 3 * FLST_BASE_NODE_SIZE)
|
||||
/* 8 bytes which give the first unused
|
||||
segment id */
|
||||
#define FSP_SEG_INODES_FULL (32 + 3 * FLST_BASE_NODE_SIZE)
|
||||
/* list of pages containing segment
|
||||
headers, where all the segment inode
|
||||
slots are reserved */
|
||||
#define FSP_SEG_INODES_FREE (32 + 4 * FLST_BASE_NODE_SIZE)
|
||||
/* list of pages containing segment
|
||||
headers, where not all the segment
|
||||
header slots are reserved */
|
||||
/*-------------------------------------*/
|
||||
/* File space header size */
|
||||
#define FSP_HEADER_SIZE (32 + 5 * FLST_BASE_NODE_SIZE)
|
||||
|
||||
#define FSP_FREE_ADD 4 /* this many free extents are added
|
||||
to the free list from above
|
||||
FSP_FREE_LIMIT at a time */
|
||||
/* @} */
|
||||
|
||||
#ifndef UNIV_INNOCHECKSUM
|
||||
|
||||
/* @defgroup File Segment Inode Constants (moved from fsp0fsp.c) @{ */
|
||||
|
||||
/* FILE SEGMENT INODE
|
||||
==================
|
||||
|
||||
Segment inode which is created for each segment in a tablespace. NOTE: in
|
||||
purge we assume that a segment having only one currently used page can be
|
||||
freed in a few steps, so that the freeing cannot fill the file buffer with
|
||||
bufferfixed file pages. */
|
||||
|
||||
typedef byte fseg_inode_t;
|
||||
|
||||
#define FSEG_INODE_PAGE_NODE FSEG_PAGE_DATA
|
||||
/* the list node for linking
|
||||
segment inode pages */
|
||||
|
||||
#define FSEG_ARR_OFFSET (FSEG_PAGE_DATA + FLST_NODE_SIZE)
|
||||
/*-------------------------------------*/
|
||||
#define FSEG_ID 0 /* 8 bytes of segment id: if this is 0,
|
||||
it means that the header is unused */
|
||||
#define FSEG_NOT_FULL_N_USED 8
|
||||
/* number of used segment pages in
|
||||
the FSEG_NOT_FULL list */
|
||||
#define FSEG_FREE 12
|
||||
/* list of free extents of this
|
||||
segment */
|
||||
#define FSEG_NOT_FULL (12 + FLST_BASE_NODE_SIZE)
|
||||
/* list of partially free extents */
|
||||
#define FSEG_FULL (12 + 2 * FLST_BASE_NODE_SIZE)
|
||||
/* list of full extents */
|
||||
#define FSEG_MAGIC_N (12 + 3 * FLST_BASE_NODE_SIZE)
|
||||
/* magic number used in debugging */
|
||||
#define FSEG_FRAG_ARR (16 + 3 * FLST_BASE_NODE_SIZE)
|
||||
/* array of individual pages
|
||||
belonging to this segment in fsp
|
||||
fragment extent lists */
|
||||
#define FSEG_FRAG_ARR_N_SLOTS (FSP_EXTENT_SIZE / 2)
|
||||
/* number of slots in the array for
|
||||
the fragment pages */
|
||||
#define FSEG_FRAG_SLOT_SIZE 4 /* a fragment page slot contains its
|
||||
page number within space, FIL_NULL
|
||||
means that the slot is not in use */
|
||||
/*-------------------------------------*/
|
||||
#define FSEG_INODE_SIZE \
|
||||
(16 + 3 * FLST_BASE_NODE_SIZE \
|
||||
+ FSEG_FRAG_ARR_N_SLOTS * FSEG_FRAG_SLOT_SIZE)
|
||||
|
||||
#define FSP_SEG_INODES_PER_PAGE(zip_size) \
|
||||
(((zip_size ? zip_size : UNIV_PAGE_SIZE) \
|
||||
- FSEG_ARR_OFFSET - 10) / FSEG_INODE_SIZE)
|
||||
/* Number of segment inodes which fit on a
|
||||
single page */
|
||||
|
||||
#define FSEG_MAGIC_N_VALUE 97937874
|
||||
|
||||
#define FSEG_FILLFACTOR 8 /* If this value is x, then if
|
||||
the number of unused but reserved
|
||||
pages in a segment is less than
|
||||
reserved pages * 1/x, and there are
|
||||
at least FSEG_FRAG_LIMIT used pages,
|
||||
then we allow a new empty extent to
|
||||
be added to the segment in
|
||||
fseg_alloc_free_page. Otherwise, we
|
||||
use unused pages of the segment. */
|
||||
|
||||
#define FSEG_FRAG_LIMIT FSEG_FRAG_ARR_N_SLOTS
|
||||
/* If the segment has >= this many
|
||||
used pages, it may be expanded by
|
||||
allocating extents to the segment;
|
||||
until that only individual fragment
|
||||
pages are allocated from the space */
|
||||
|
||||
#define FSEG_FREE_LIST_LIMIT 40 /* If the reserved size of a segment
|
||||
is at least this many extents, we
|
||||
allow extents to be put to the free
|
||||
list of the extent: at most
|
||||
FSEG_FREE_LIST_MAX_LEN many */
|
||||
#define FSEG_FREE_LIST_MAX_LEN 4
|
||||
/* @} */
|
||||
|
||||
/* @defgroup Extent Descriptor Constants (moved from fsp0fsp.c) @{ */
|
||||
|
||||
/* EXTENT DESCRIPTOR
|
||||
=================
|
||||
|
||||
File extent descriptor data structure: contains bits to tell which pages in
|
||||
the extent are free and which contain old tuple version to clean. */
|
||||
|
||||
/*-------------------------------------*/
|
||||
#define XDES_ID 0 /* The identifier of the segment
|
||||
to which this extent belongs */
|
||||
#define XDES_FLST_NODE 8 /* The list node data structure
|
||||
for the descriptors */
|
||||
#define XDES_STATE (FLST_NODE_SIZE + 8)
|
||||
/* contains state information
|
||||
of the extent */
|
||||
#define XDES_BITMAP (FLST_NODE_SIZE + 12)
|
||||
/* Descriptor bitmap of the pages
|
||||
in the extent */
|
||||
/*-------------------------------------*/
|
||||
|
||||
#define XDES_BITS_PER_PAGE 2 /* How many bits are there per page */
|
||||
#define XDES_FREE_BIT 0 /* Index of the bit which tells if
|
||||
the page is free */
|
||||
#define XDES_CLEAN_BIT 1 /* NOTE: currently not used!
|
||||
Index of the bit which tells if
|
||||
there are old versions of tuples
|
||||
on the page */
|
||||
/* States of a descriptor */
|
||||
#define XDES_FREE 1 /* extent is in free list of space */
|
||||
#define XDES_FREE_FRAG 2 /* extent is in free fragment list of
|
||||
space */
|
||||
#define XDES_FULL_FRAG 3 /* extent is in full fragment list of
|
||||
space */
|
||||
#define XDES_FSEG 4 /* extent belongs to a segment */
|
||||
|
||||
/** File extent data structure size in bytes. */
|
||||
#define XDES_SIZE \
|
||||
(XDES_BITMAP \
|
||||
+ UT_BITS_IN_BYTES(FSP_EXTENT_SIZE * XDES_BITS_PER_PAGE))
|
||||
|
||||
/** File extent data structure size in bytes for MAX page size. */
|
||||
#define XDES_SIZE_MAX \
|
||||
(XDES_BITMAP \
|
||||
+ UT_BITS_IN_BYTES(FSP_EXTENT_SIZE_MAX * XDES_BITS_PER_PAGE))
|
||||
|
||||
/** File extent data structure size in bytes for MIN page size. */
|
||||
#define XDES_SIZE_MIN \
|
||||
(XDES_BITMAP \
|
||||
+ UT_BITS_IN_BYTES(FSP_EXTENT_SIZE_MIN * XDES_BITS_PER_PAGE))
|
||||
|
||||
/** Offset of the descriptor array on a descriptor page */
|
||||
#define XDES_ARR_OFFSET (FSP_HEADER_OFFSET + FSP_HEADER_SIZE)
|
||||
|
||||
/* @} */
|
||||
|
||||
/**********************************************************************//**
|
||||
Initializes the file space system. */
|
||||
UNIV_INTERN
|
||||
void
|
||||
fsp_init(void);
|
||||
/*==========*/
|
||||
/**********************************************************************//**
|
||||
Gets the size of the system tablespace from the tablespace header. If
|
||||
we do not have an auto-extending data file, this should be equal to
|
||||
the size of the data files. If there is an auto-extending data file,
|
||||
this can be smaller.
|
||||
@return size in pages */
|
||||
UNIV_INTERN
|
||||
ulint
|
||||
fsp_header_get_tablespace_size(void);
|
||||
/*================================*/
|
||||
/**********************************************************************//**
|
||||
Reads the file space size stored in the header page.
|
||||
@return tablespace size stored in the space header */
|
||||
UNIV_INTERN
|
||||
ulint
|
||||
fsp_get_size_low(
|
||||
/*=============*/
|
||||
page_t* page); /*!< in: header page (page 0 in the tablespace) */
|
||||
/**********************************************************************//**
|
||||
Reads the space id from the first page of a tablespace.
|
||||
@return space id, ULINT UNDEFINED if error */
|
||||
UNIV_INTERN
|
||||
ulint
|
||||
fsp_header_get_space_id(
|
||||
/*====================*/
|
||||
const page_t* page); /*!< in: first page of a tablespace */
|
||||
/**********************************************************************//**
|
||||
Reads the space flags from the first page of a tablespace.
|
||||
@return flags */
|
||||
UNIV_INTERN
|
||||
ulint
|
||||
fsp_header_get_flags(
|
||||
/*=================*/
|
||||
const page_t* page); /*!< in: first page of a tablespace */
|
||||
/**********************************************************************//**
|
||||
Reads the compressed page size from the first page of a tablespace.
|
||||
@return compressed page size in bytes, or 0 if uncompressed */
|
||||
UNIV_INTERN
|
||||
ulint
|
||||
fsp_header_get_zip_size(
|
||||
/*====================*/
|
||||
const page_t* page); /*!< in: first page of a tablespace */
|
||||
/**********************************************************************//**
|
||||
Writes the space id and flags to a tablespace header. The flags contain
|
||||
row type, physical/compressed page size, and logical/uncompressed page
|
||||
size of the tablespace. */
|
||||
UNIV_INTERN
|
||||
void
|
||||
fsp_header_init_fields(
|
||||
/*===================*/
|
||||
page_t* page, /*!< in/out: first page in the space */
|
||||
ulint space_id, /*!< in: space id */
|
||||
ulint flags); /*!< in: tablespace flags (FSP_SPACE_FLAGS):
|
||||
0, or table->flags if newer than COMPACT */
|
||||
/**********************************************************************//**
|
||||
Initializes the space header of a new created space and creates also the
|
||||
insert buffer tree root if space == 0. */
|
||||
UNIV_INTERN
|
||||
void
|
||||
fsp_header_init(
|
||||
/*============*/
|
||||
ulint space, /*!< in: space id */
|
||||
ulint size, /*!< in: current size in blocks */
|
||||
mtr_t* mtr); /*!< in/out: mini-transaction */
|
||||
/**********************************************************************//**
|
||||
Increases the space size field of a space. */
|
||||
UNIV_INTERN
|
||||
void
|
||||
fsp_header_inc_size(
|
||||
/*================*/
|
||||
ulint space, /*!< in: space id */
|
||||
ulint size_inc, /*!< in: size increment in pages */
|
||||
mtr_t* mtr); /*!< in/out: mini-transaction */
|
||||
/**********************************************************************//**
|
||||
Creates a new segment.
|
||||
@return the block where the segment header is placed, x-latched, NULL
|
||||
if could not create segment because of lack of space */
|
||||
UNIV_INTERN
|
||||
buf_block_t*
|
||||
fseg_create(
|
||||
/*========*/
|
||||
ulint space, /*!< in: space id */
|
||||
ulint page, /*!< in: page where the segment header is placed: if
|
||||
this is != 0, the page must belong to another segment,
|
||||
if this is 0, a new page will be allocated and it
|
||||
will belong to the created segment */
|
||||
ulint byte_offset, /*!< in: byte offset of the created segment header
|
||||
on the page */
|
||||
mtr_t* mtr); /*!< in/out: mini-transaction */
|
||||
/**********************************************************************//**
|
||||
Creates a new segment.
|
||||
@return the block where the segment header is placed, x-latched, NULL
|
||||
if could not create segment because of lack of space */
|
||||
UNIV_INTERN
|
||||
buf_block_t*
|
||||
fseg_create_general(
|
||||
/*================*/
|
||||
ulint space, /*!< in: space id */
|
||||
ulint page, /*!< in: page where the segment header is placed: if
|
||||
this is != 0, the page must belong to another segment,
|
||||
if this is 0, a new page will be allocated and it
|
||||
will belong to the created segment */
|
||||
ulint byte_offset, /*!< in: byte offset of the created segment header
|
||||
on the page */
|
||||
ibool has_done_reservation, /*!< in: TRUE if the caller has already
|
||||
done the reservation for the pages with
|
||||
fsp_reserve_free_extents (at least 2 extents: one for
|
||||
the inode and the other for the segment) then there is
|
||||
no need to do the check for this individual
|
||||
operation */
|
||||
mtr_t* mtr); /*!< in/out: mini-transaction */
|
||||
/**********************************************************************//**
|
||||
Calculates the number of pages reserved by a segment, and how many pages are
|
||||
currently used.
|
||||
@return number of reserved pages */
|
||||
UNIV_INTERN
|
||||
ulint
|
||||
fseg_n_reserved_pages(
|
||||
/*==================*/
|
||||
fseg_header_t* header, /*!< in: segment header */
|
||||
ulint* used, /*!< out: number of pages used (<= reserved) */
|
||||
mtr_t* mtr); /*!< in/out: mini-transaction */
|
||||
/**********************************************************************//**
|
||||
Allocates a single free page from a segment. This function implements
|
||||
the intelligent allocation strategy which tries to minimize
|
||||
file space fragmentation.
|
||||
@param[in/out] seg_header segment header
|
||||
@param[in] hint hint of which page would be desirable
|
||||
@param[in] direction if the new page is needed because
|
||||
of an index page split, and records are
|
||||
inserted there in order, into which
|
||||
direction they go alphabetically: FSP_DOWN,
|
||||
FSP_UP, FSP_NO_DIR
|
||||
@param[in/out] mtr mini-transaction
|
||||
@return X-latched block, or NULL if no page could be allocated */
|
||||
#define fseg_alloc_free_page(seg_header, hint, direction, mtr) \
|
||||
fseg_alloc_free_page_general(seg_header, hint, direction, \
|
||||
FALSE, mtr, mtr)
|
||||
/**********************************************************************//**
|
||||
Allocates a single free page from a segment. This function implements
|
||||
the intelligent allocation strategy which tries to minimize file space
|
||||
fragmentation.
|
||||
@retval NULL if no page could be allocated
|
||||
@retval block, rw_lock_x_lock_count(&block->lock) == 1 if allocation succeeded
|
||||
(init_mtr == mtr, or the page was not previously freed in mtr)
|
||||
@retval block (not allocated or initialized) otherwise */
|
||||
UNIV_INTERN
|
||||
buf_block_t*
|
||||
fseg_alloc_free_page_general(
|
||||
/*=========================*/
|
||||
fseg_header_t* seg_header,/*!< in/out: segment header */
|
||||
ulint hint, /*!< in: hint of which page would be
|
||||
desirable */
|
||||
byte direction,/*!< in: if the new page is needed because
|
||||
of an index page split, and records are
|
||||
inserted there in order, into which
|
||||
direction they go alphabetically: FSP_DOWN,
|
||||
FSP_UP, FSP_NO_DIR */
|
||||
ibool has_done_reservation, /*!< in: TRUE if the caller has
|
||||
already done the reservation for the page
|
||||
with fsp_reserve_free_extents, then there
|
||||
is no need to do the check for this individual
|
||||
page */
|
||||
mtr_t* mtr, /*!< in/out: mini-transaction */
|
||||
mtr_t* init_mtr)/*!< in/out: mtr or another mini-transaction
|
||||
in which the page should be initialized.
|
||||
If init_mtr!=mtr, but the page is already
|
||||
latched in mtr, do not initialize the page. */
|
||||
__attribute__((warn_unused_result, nonnull));
|
||||
/**********************************************************************//**
|
||||
Reserves free pages from a tablespace. All mini-transactions which may
|
||||
use several pages from the tablespace should call this function beforehand
|
||||
and reserve enough free extents so that they certainly will be able
|
||||
to do their operation, like a B-tree page split, fully. Reservations
|
||||
must be released with function fil_space_release_free_extents!
|
||||
|
||||
The alloc_type below has the following meaning: FSP_NORMAL means an
|
||||
operation which will probably result in more space usage, like an
|
||||
insert in a B-tree; FSP_UNDO means allocation to undo logs: if we are
|
||||
deleting rows, then this allocation will in the long run result in
|
||||
less space usage (after a purge); FSP_CLEANING means allocation done
|
||||
in a physical record delete (like in a purge) or other cleaning operation
|
||||
which will result in less space usage in the long run. We prefer the latter
|
||||
two types of allocation: when space is scarce, FSP_NORMAL allocations
|
||||
will not succeed, but the latter two allocations will succeed, if possible.
|
||||
The purpose is to avoid dead end where the database is full but the
|
||||
user cannot free any space because these freeing operations temporarily
|
||||
reserve some space.
|
||||
|
||||
Single-table tablespaces whose size is < 32 pages are a special case. In this
|
||||
function we would liberally reserve several 64 page extents for every page
|
||||
split or merge in a B-tree. But we do not want to waste disk space if the table
|
||||
only occupies < 32 pages. That is why we apply different rules in that special
|
||||
case, just ensuring that there are 3 free pages available.
|
||||
@return TRUE if we were able to make the reservation */
|
||||
UNIV_INTERN
|
||||
ibool
|
||||
fsp_reserve_free_extents(
|
||||
/*=====================*/
|
||||
ulint* n_reserved,/*!< out: number of extents actually reserved; if we
|
||||
return TRUE and the tablespace size is < 64 pages,
|
||||
then this can be 0, otherwise it is n_ext */
|
||||
ulint space, /*!< in: space id */
|
||||
ulint n_ext, /*!< in: number of extents to reserve */
|
||||
ulint alloc_type,/*!< in: FSP_NORMAL, FSP_UNDO, or FSP_CLEANING */
|
||||
mtr_t* mtr); /*!< in: mini-transaction */
|
||||
/**********************************************************************//**
|
||||
This function should be used to get information on how much we still
|
||||
will be able to insert new data to the database without running out the
|
||||
tablespace. Only free extents are taken into account and we also subtract
|
||||
the safety margin required by the above function fsp_reserve_free_extents.
|
||||
@return available space in kB */
|
||||
UNIV_INTERN
|
||||
ullint
|
||||
fsp_get_available_space_in_free_extents(
|
||||
/*====================================*/
|
||||
ulint space); /*!< in: space id */
|
||||
/**********************************************************************//**
|
||||
Frees a single page of a segment. */
|
||||
UNIV_INTERN
|
||||
void
|
||||
fseg_free_page(
|
||||
/*===========*/
|
||||
fseg_header_t* seg_header, /*!< in: segment header */
|
||||
ulint space, /*!< in: space id */
|
||||
ulint page, /*!< in: page offset */
|
||||
mtr_t* mtr); /*!< in/out: mini-transaction */
|
||||
/**********************************************************************//**
|
||||
Checks if a single page of a segment is free.
|
||||
@return true if free */
|
||||
UNIV_INTERN
|
||||
bool
|
||||
fseg_page_is_free(
|
||||
/*==============*/
|
||||
fseg_header_t* seg_header, /*!< in: segment header */
|
||||
ulint space, /*!< in: space id */
|
||||
ulint page) /*!< in: page offset */
|
||||
__attribute__((nonnull, warn_unused_result));
|
||||
/**********************************************************************//**
|
||||
Frees part of a segment. This function can be used to free a segment
|
||||
by repeatedly calling this function in different mini-transactions.
|
||||
Doing the freeing in a single mini-transaction might result in
|
||||
too big a mini-transaction.
|
||||
@return TRUE if freeing completed */
|
||||
UNIV_INTERN
|
||||
ibool
|
||||
fseg_free_step(
|
||||
/*===========*/
|
||||
fseg_header_t* header, /*!< in, own: segment header; NOTE: if the header
|
||||
resides on the first page of the frag list
|
||||
of the segment, this pointer becomes obsolete
|
||||
after the last freeing step */
|
||||
mtr_t* mtr); /*!< in/out: mini-transaction */
|
||||
/**********************************************************************//**
|
||||
Frees part of a segment. Differs from fseg_free_step because this function
|
||||
leaves the header page unfreed.
|
||||
@return TRUE if freeing completed, except the header page */
|
||||
UNIV_INTERN
|
||||
ibool
|
||||
fseg_free_step_not_header(
|
||||
/*======================*/
|
||||
fseg_header_t* header, /*!< in: segment header which must reside on
|
||||
the first fragment page of the segment */
|
||||
mtr_t* mtr); /*!< in/out: mini-transaction */
|
||||
/***********************************************************************//**
|
||||
Checks if a page address is an extent descriptor page address.
|
||||
@return TRUE if a descriptor page */
|
||||
UNIV_INLINE
|
||||
ibool
|
||||
fsp_descr_page(
|
||||
/*===========*/
|
||||
ulint zip_size,/*!< in: compressed page size in bytes;
|
||||
0 for uncompressed pages */
|
||||
ulint page_no);/*!< in: page number */
|
||||
/***********************************************************//**
|
||||
Parses a redo log record of a file page init.
|
||||
@return end of log record or NULL */
|
||||
UNIV_INTERN
|
||||
byte*
|
||||
fsp_parse_init_file_page(
|
||||
/*=====================*/
|
||||
byte* ptr, /*!< in: buffer */
|
||||
byte* end_ptr, /*!< in: buffer end */
|
||||
buf_block_t* block); /*!< in: block or NULL */
|
||||
/*******************************************************************//**
|
||||
Validates the file space system and its segments.
|
||||
@return TRUE if ok */
|
||||
UNIV_INTERN
|
||||
ibool
|
||||
fsp_validate(
|
||||
/*=========*/
|
||||
ulint space); /*!< in: space id */
|
||||
/*******************************************************************//**
|
||||
Prints info of a file space. */
|
||||
UNIV_INTERN
|
||||
void
|
||||
fsp_print(
|
||||
/*======*/
|
||||
ulint space); /*!< in: space id */
|
||||
#ifdef UNIV_DEBUG
|
||||
/*******************************************************************//**
|
||||
Validates a segment.
|
||||
@return TRUE if ok */
|
||||
UNIV_INTERN
|
||||
ibool
|
||||
fseg_validate(
|
||||
/*==========*/
|
||||
fseg_header_t* header, /*!< in: segment header */
|
||||
mtr_t* mtr); /*!< in/out: mini-transaction */
|
||||
#endif /* UNIV_DEBUG */
|
||||
#ifdef UNIV_BTR_PRINT
|
||||
/*******************************************************************//**
|
||||
Writes info of a segment. */
|
||||
UNIV_INTERN
|
||||
void
|
||||
fseg_print(
|
||||
/*=======*/
|
||||
fseg_header_t* header, /*!< in: segment header */
|
||||
mtr_t* mtr); /*!< in/out: mini-transaction */
|
||||
#endif /* UNIV_BTR_PRINT */
|
||||
|
||||
/********************************************************************//**
|
||||
Validate and return the tablespace flags, which are stored in the
|
||||
tablespace header at offset FSP_SPACE_FLAGS. They should be 0 for
|
||||
ROW_FORMAT=COMPACT and ROW_FORMAT=REDUNDANT. The newer row formats,
|
||||
COMPRESSED and DYNAMIC, use a file format > Antelope so they should
|
||||
have a file format number plus the DICT_TF_COMPACT bit set.
|
||||
@return true if check ok */
|
||||
UNIV_INLINE
|
||||
bool
|
||||
fsp_flags_is_valid(
|
||||
/*===============*/
|
||||
ulint flags) /*!< in: tablespace flags */
|
||||
__attribute__((warn_unused_result, const));
|
||||
/********************************************************************//**
|
||||
Determine if the tablespace is compressed from dict_table_t::flags.
|
||||
@return TRUE if compressed, FALSE if not compressed */
|
||||
UNIV_INLINE
|
||||
ibool
|
||||
fsp_flags_is_compressed(
|
||||
/*====================*/
|
||||
ulint flags); /*!< in: tablespace flags */
|
||||
|
||||
/********************************************************************//**
|
||||
Calculates the descriptor index within a descriptor page.
|
||||
@return descriptor index */
|
||||
UNIV_INLINE
|
||||
ulint
|
||||
xdes_calc_descriptor_index(
|
||||
/*=======================*/
|
||||
ulint zip_size, /*!< in: compressed page size in bytes;
|
||||
0 for uncompressed pages */
|
||||
ulint offset); /*!< in: page offset */
|
||||
|
||||
/**********************************************************************//**
|
||||
Gets a descriptor bit of a page.
|
||||
@return TRUE if free */
|
||||
UNIV_INLINE
|
||||
ibool
|
||||
xdes_get_bit(
|
||||
/*=========*/
|
||||
const xdes_t* descr, /*!< in: descriptor */
|
||||
ulint bit, /*!< in: XDES_FREE_BIT or XDES_CLEAN_BIT */
|
||||
ulint offset);/*!< in: page offset within extent:
|
||||
0 ... FSP_EXTENT_SIZE - 1 */
|
||||
|
||||
/********************************************************************//**
|
||||
Calculates the page where the descriptor of a page resides.
|
||||
@return descriptor page offset */
|
||||
UNIV_INLINE
|
||||
ulint
|
||||
xdes_calc_descriptor_page(
|
||||
/*======================*/
|
||||
ulint zip_size, /*!< in: compressed page size in bytes;
|
||||
0 for uncompressed pages */
|
||||
ulint offset); /*!< in: page offset */
|
||||
|
||||
#endif /* !UNIV_INNOCHECKSUM */
|
||||
|
||||
/********************************************************************//**
|
||||
Extract the zip size from tablespace flags. A tablespace has only one
|
||||
physical page size whether that page is compressed or not.
|
||||
@return compressed page size of the file-per-table tablespace in bytes,
|
||||
or zero if the table is not compressed. */
|
||||
UNIV_INLINE
|
||||
ulint
|
||||
fsp_flags_get_zip_size(
|
||||
/*====================*/
|
||||
ulint flags); /*!< in: tablespace flags */
|
||||
/********************************************************************//**
|
||||
Extract the page size from tablespace flags.
|
||||
@return page size of the tablespace in bytes */
|
||||
UNIV_INLINE
|
||||
ulint
|
||||
fsp_flags_get_page_size(
|
||||
/*====================*/
|
||||
ulint flags); /*!< in: tablespace flags */
|
||||
|
||||
#ifndef UNIV_NONINL
|
||||
#include "fsp0fsp.ic"
|
||||
#endif
|
||||
|
||||
#endif
|
||||
314
storage/innobase/include/fsp0fsp.ic
Normal file
314
storage/innobase/include/fsp0fsp.ic
Normal file
|
|
@ -0,0 +1,314 @@
|
|||
/*****************************************************************************
|
||||
|
||||
Copyright (c) 1995, 2012, Oracle and/or its affiliates. All Rights Reserved.
|
||||
|
||||
This program is free software; you can redistribute it and/or modify it under
|
||||
the terms of the GNU General Public License as published by the Free Software
|
||||
Foundation; version 2 of the License.
|
||||
|
||||
This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
|
||||
FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License along with
|
||||
this program; if not, write to the Free Software Foundation, Inc.,
|
||||
51 Franklin Street, Suite 500, Boston, MA 02110-1335 USA
|
||||
|
||||
*****************************************************************************/
|
||||
|
||||
/**************************************************//**
|
||||
@file include/fsp0fsp.ic
|
||||
File space management
|
||||
|
||||
Created 12/18/1995 Heikki Tuuri
|
||||
*******************************************************/
|
||||
|
||||
#ifndef UNIV_INNOCHECKSUM
|
||||
|
||||
/***********************************************************************//**
|
||||
Checks if a page address is an extent descriptor page address.
|
||||
@return TRUE if a descriptor page */
|
||||
UNIV_INLINE
|
||||
ibool
|
||||
fsp_descr_page(
|
||||
/*===========*/
|
||||
ulint zip_size,/*!< in: compressed page size in bytes;
|
||||
0 for uncompressed pages */
|
||||
ulint page_no)/*!< in: page number */
|
||||
{
|
||||
ut_ad(ut_is_2pow(zip_size));
|
||||
|
||||
if (!zip_size) {
|
||||
return((page_no & (UNIV_PAGE_SIZE - 1)) == FSP_XDES_OFFSET);
|
||||
}
|
||||
|
||||
return((page_no & (zip_size - 1)) == FSP_XDES_OFFSET);
|
||||
}
|
||||
|
||||
/********************************************************************//**
|
||||
Validate and return the tablespace flags, which are stored in the
|
||||
tablespace header at offset FSP_SPACE_FLAGS. They should be 0 for
|
||||
ROW_FORMAT=COMPACT and ROW_FORMAT=REDUNDANT. The newer row formats,
|
||||
COMPRESSED and DYNAMIC, use a file format > Antelope so they should
|
||||
have a file format number plus the DICT_TF_COMPACT bit set.
|
||||
@return true if check ok */
|
||||
UNIV_INLINE
|
||||
bool
|
||||
fsp_flags_is_valid(
|
||||
/*===============*/
|
||||
ulint flags) /*!< in: tablespace flags */
|
||||
{
|
||||
ulint post_antelope = FSP_FLAGS_GET_POST_ANTELOPE(flags);
|
||||
ulint zip_ssize = FSP_FLAGS_GET_ZIP_SSIZE(flags);
|
||||
ulint atomic_blobs = FSP_FLAGS_HAS_ATOMIC_BLOBS(flags);
|
||||
ulint page_ssize = FSP_FLAGS_GET_PAGE_SSIZE(flags);
|
||||
ulint unused = FSP_FLAGS_GET_UNUSED(flags);
|
||||
|
||||
DBUG_EXECUTE_IF("fsp_flags_is_valid_failure", return(false););
|
||||
|
||||
/* fsp_flags is zero unless atomic_blobs is set. */
|
||||
/* Make sure there are no bits that we do not know about. */
|
||||
if (unused != 0 || flags == 1) {
|
||||
return(false);
|
||||
} else if (post_antelope) {
|
||||
/* The Antelope row formats REDUNDANT and COMPACT did
|
||||
not use tablespace flags, so this flag and the entire
|
||||
4-byte field is zero for Antelope row formats. */
|
||||
|
||||
if (!atomic_blobs) {
|
||||
return(false);
|
||||
}
|
||||
}
|
||||
|
||||
if (!atomic_blobs) {
|
||||
/* Barracuda row formats COMPRESSED and DYNAMIC build on
|
||||
the page structure introduced for the COMPACT row format
|
||||
by allowing long fields to be broken into prefix and
|
||||
externally stored parts. */
|
||||
|
||||
if (post_antelope || zip_ssize != 0) {
|
||||
return(false);
|
||||
}
|
||||
|
||||
} else if (!post_antelope || zip_ssize > PAGE_ZIP_SSIZE_MAX) {
|
||||
return(false);
|
||||
} else if (page_ssize > UNIV_PAGE_SSIZE_MAX) {
|
||||
|
||||
/* The page size field can be used for any row type, or it may
|
||||
be zero for an original 16k page size.
|
||||
Validate the page shift size is within allowed range. */
|
||||
|
||||
return(false);
|
||||
|
||||
} else if (UNIV_PAGE_SIZE != UNIV_PAGE_SIZE_ORIG && !page_ssize) {
|
||||
return(false);
|
||||
}
|
||||
|
||||
#if UNIV_FORMAT_MAX != UNIV_FORMAT_B
|
||||
# error "UNIV_FORMAT_MAX != UNIV_FORMAT_B, Add more validations."
|
||||
#endif
|
||||
|
||||
/* The DATA_DIR field can be used for any row type so there is
|
||||
nothing here to validate. */
|
||||
|
||||
return(true);
|
||||
}
|
||||
|
||||
/********************************************************************//**
|
||||
Determine if the tablespace is compressed from dict_table_t::flags.
|
||||
@return TRUE if compressed, FALSE if not compressed */
|
||||
UNIV_INLINE
|
||||
ibool
|
||||
fsp_flags_is_compressed(
|
||||
/*====================*/
|
||||
ulint flags) /*!< in: tablespace flags */
|
||||
{
|
||||
return(FSP_FLAGS_GET_ZIP_SSIZE(flags) != 0);
|
||||
}
|
||||
|
||||
#endif /* !UNIV_INNOCHECKSUM */
|
||||
|
||||
/********************************************************************//**
|
||||
Extract the zip size from tablespace flags.
|
||||
@return compressed page size of the file-per-table tablespace in bytes,
|
||||
or zero if the table is not compressed. */
|
||||
UNIV_INLINE
|
||||
ulint
|
||||
fsp_flags_get_zip_size(
|
||||
/*===================*/
|
||||
ulint flags) /*!< in: tablespace flags */
|
||||
{
|
||||
ulint zip_size = 0;
|
||||
ulint ssize = FSP_FLAGS_GET_ZIP_SSIZE(flags);
|
||||
|
||||
/* Convert from a 'log2 minus 9' to a page size in bytes. */
|
||||
if (ssize) {
|
||||
zip_size = ((UNIV_ZIP_SIZE_MIN >> 1) << ssize);
|
||||
|
||||
ut_ad(zip_size <= UNIV_ZIP_SIZE_MAX);
|
||||
}
|
||||
|
||||
return(zip_size);
|
||||
}
|
||||
|
||||
/********************************************************************//**
|
||||
Extract the page size from tablespace flags.
|
||||
@return page size of the tablespace in bytes */
|
||||
UNIV_INLINE
|
||||
ulint
|
||||
fsp_flags_get_page_size(
|
||||
/*====================*/
|
||||
ulint flags) /*!< in: tablespace flags */
|
||||
{
|
||||
ulint page_size = 0;
|
||||
ulint ssize = FSP_FLAGS_GET_PAGE_SSIZE(flags);
|
||||
|
||||
/* Convert from a 'log2 minus 9' to a page size in bytes. */
|
||||
if (UNIV_UNLIKELY(ssize)) {
|
||||
page_size = ((UNIV_ZIP_SIZE_MIN >> 1) << ssize);
|
||||
|
||||
ut_ad(page_size <= UNIV_PAGE_SIZE_MAX);
|
||||
} else {
|
||||
/* If the page size was not stored, then it is the
|
||||
original 16k. */
|
||||
page_size = UNIV_PAGE_SIZE_ORIG;
|
||||
}
|
||||
|
||||
return(page_size);
|
||||
}
|
||||
|
||||
#ifndef UNIV_INNOCHECKSUM
|
||||
|
||||
/********************************************************************//**
|
||||
Add the page size to the tablespace flags.
|
||||
@return tablespace flags after page size is added */
|
||||
UNIV_INLINE
|
||||
ulint
|
||||
fsp_flags_set_page_size(
|
||||
/*====================*/
|
||||
ulint flags, /*!< in: tablespace flags */
|
||||
ulint page_size) /*!< in: page size in bytes */
|
||||
{
|
||||
ulint ssize = 0;
|
||||
ulint shift;
|
||||
|
||||
/* Page size should be > UNIV_PAGE_SIZE_MIN */
|
||||
ut_ad(page_size >= UNIV_PAGE_SIZE_MIN);
|
||||
ut_ad(page_size <= UNIV_PAGE_SIZE_MAX);
|
||||
|
||||
if (page_size == UNIV_PAGE_SIZE_ORIG) {
|
||||
ut_ad(0 == FSP_FLAGS_GET_PAGE_SSIZE(flags));
|
||||
return(flags);
|
||||
}
|
||||
|
||||
for (shift = UNIV_PAGE_SIZE_SHIFT_MAX;
|
||||
shift >= UNIV_PAGE_SIZE_SHIFT_MIN;
|
||||
shift--) {
|
||||
ulint mask = (1 << shift);
|
||||
if (page_size & mask) {
|
||||
ut_ad(!(page_size & ~mask));
|
||||
ssize = shift - UNIV_ZIP_SIZE_SHIFT_MIN + 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
ut_ad(ssize);
|
||||
ut_ad(ssize <= UNIV_PAGE_SSIZE_MAX);
|
||||
|
||||
flags = FSP_FLAGS_SET_PAGE_SSIZE(flags, ssize);
|
||||
|
||||
ut_ad(fsp_flags_is_valid(flags));
|
||||
|
||||
return(flags);
|
||||
}
|
||||
|
||||
/********************************************************************//**
|
||||
Calculates the descriptor index within a descriptor page.
|
||||
@return descriptor index */
|
||||
UNIV_INLINE
|
||||
ulint
|
||||
xdes_calc_descriptor_index(
|
||||
/*=======================*/
|
||||
ulint zip_size, /*!< in: compressed page size in bytes;
|
||||
0 for uncompressed pages */
|
||||
ulint offset) /*!< in: page offset */
|
||||
{
|
||||
ut_ad(ut_is_2pow(zip_size));
|
||||
|
||||
if (zip_size == 0) {
|
||||
return(ut_2pow_remainder(offset, UNIV_PAGE_SIZE)
|
||||
/ FSP_EXTENT_SIZE);
|
||||
} else {
|
||||
return(ut_2pow_remainder(offset, zip_size) / FSP_EXTENT_SIZE);
|
||||
}
|
||||
}
|
||||
|
||||
/**********************************************************************//**
|
||||
Gets a descriptor bit of a page.
|
||||
@return TRUE if free */
|
||||
UNIV_INLINE
|
||||
ibool
|
||||
xdes_get_bit(
|
||||
/*=========*/
|
||||
const xdes_t* descr, /*!< in: descriptor */
|
||||
ulint bit, /*!< in: XDES_FREE_BIT or XDES_CLEAN_BIT */
|
||||
ulint offset) /*!< in: page offset within extent:
|
||||
0 ... FSP_EXTENT_SIZE - 1 */
|
||||
{
|
||||
ut_ad(offset < FSP_EXTENT_SIZE);
|
||||
ut_ad(bit == XDES_FREE_BIT || bit == XDES_CLEAN_BIT);
|
||||
|
||||
ulint index = bit + XDES_BITS_PER_PAGE * offset;
|
||||
|
||||
ulint bit_index = index % 8;
|
||||
ulint byte_index = index / 8;
|
||||
|
||||
return(ut_bit_get_nth(
|
||||
mach_read_ulint(descr + XDES_BITMAP + byte_index,
|
||||
MLOG_1BYTE),
|
||||
bit_index));
|
||||
}
|
||||
|
||||
/********************************************************************//**
|
||||
Calculates the page where the descriptor of a page resides.
|
||||
@return descriptor page offset */
|
||||
UNIV_INLINE
|
||||
ulint
|
||||
xdes_calc_descriptor_page(
|
||||
/*======================*/
|
||||
ulint zip_size, /*!< in: compressed page size in bytes;
|
||||
0 for uncompressed pages */
|
||||
ulint offset) /*!< in: page offset */
|
||||
{
|
||||
#ifndef DOXYGEN /* Doxygen gets confused by these */
|
||||
# if UNIV_PAGE_SIZE_MAX <= XDES_ARR_OFFSET \
|
||||
+ (UNIV_PAGE_SIZE_MAX / FSP_EXTENT_SIZE_MAX) \
|
||||
* XDES_SIZE_MAX
|
||||
# error
|
||||
# endif
|
||||
# if UNIV_ZIP_SIZE_MIN <= XDES_ARR_OFFSET \
|
||||
+ (UNIV_ZIP_SIZE_MIN / FSP_EXTENT_SIZE_MIN) \
|
||||
* XDES_SIZE_MIN
|
||||
# error
|
||||
# endif
|
||||
#endif /* !DOXYGEN */
|
||||
|
||||
ut_ad(UNIV_PAGE_SIZE > XDES_ARR_OFFSET
|
||||
+ (UNIV_PAGE_SIZE / FSP_EXTENT_SIZE)
|
||||
* XDES_SIZE);
|
||||
ut_ad(UNIV_ZIP_SIZE_MIN > XDES_ARR_OFFSET
|
||||
+ (UNIV_ZIP_SIZE_MIN / FSP_EXTENT_SIZE)
|
||||
* XDES_SIZE);
|
||||
|
||||
ut_ad(ut_is_2pow(zip_size));
|
||||
|
||||
if (zip_size == 0) {
|
||||
return(ut_2pow_round(offset, UNIV_PAGE_SIZE));
|
||||
} else {
|
||||
ut_ad(zip_size > XDES_ARR_OFFSET
|
||||
+ (zip_size / FSP_EXTENT_SIZE) * XDES_SIZE);
|
||||
return(ut_2pow_round(offset, zip_size));
|
||||
}
|
||||
}
|
||||
|
||||
#endif /* !UNIV_INNOCHECKSUM */
|
||||
116
storage/innobase/include/fsp0types.h
Normal file
116
storage/innobase/include/fsp0types.h
Normal file
|
|
@ -0,0 +1,116 @@
|
|||
/*****************************************************************************
|
||||
|
||||
Copyright (c) 1995, 2009, Oracle and/or its affiliates. All Rights Reserved.
|
||||
|
||||
This program is free software; you can redistribute it and/or modify it under
|
||||
the terms of the GNU General Public License as published by the Free Software
|
||||
Foundation; version 2 of the License.
|
||||
|
||||
This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
|
||||
FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License along with
|
||||
this program; if not, write to the Free Software Foundation, Inc.,
|
||||
51 Franklin Street, Suite 500, Boston, MA 02110-1335 USA
|
||||
|
||||
*****************************************************************************/
|
||||
|
||||
/******************************************************
|
||||
@file include/fsp0types.h
|
||||
File space management types
|
||||
|
||||
Created May 26, 2009 Vasil Dimov
|
||||
*******************************************************/
|
||||
|
||||
#ifndef fsp0types_h
|
||||
#define fsp0types_h
|
||||
|
||||
#include "univ.i"
|
||||
|
||||
#include "fil0fil.h" /* for FIL_PAGE_DATA */
|
||||
|
||||
/** @name Flags for inserting records in order
|
||||
If records are inserted in order, there are the following
|
||||
flags to tell this (their type is made byte for the compiler
|
||||
to warn if direction and hint parameters are switched in
|
||||
fseg_alloc_free_page) */
|
||||
/* @{ */
|
||||
#define FSP_UP ((byte)111) /*!< alphabetically upwards */
|
||||
#define FSP_DOWN ((byte)112) /*!< alphabetically downwards */
|
||||
#define FSP_NO_DIR ((byte)113) /*!< no order */
|
||||
/* @} */
|
||||
|
||||
/** File space extent size (one megabyte) in pages */
|
||||
#define FSP_EXTENT_SIZE (1048576U / UNIV_PAGE_SIZE)
|
||||
|
||||
/** File space extent size (one megabyte) in pages for MAX page size */
|
||||
#define FSP_EXTENT_SIZE_MAX (1048576 / UNIV_PAGE_SIZE_MAX)
|
||||
|
||||
/** File space extent size (one megabyte) in pages for MIN page size */
|
||||
#define FSP_EXTENT_SIZE_MIN (1048576 / UNIV_PAGE_SIZE_MIN)
|
||||
|
||||
/** On a page of any file segment, data may be put starting from this
|
||||
offset */
|
||||
#define FSEG_PAGE_DATA FIL_PAGE_DATA
|
||||
|
||||
/** @name File segment header
|
||||
The file segment header points to the inode describing the file segment. */
|
||||
/* @{ */
|
||||
/** Data type for file segment header */
|
||||
typedef byte fseg_header_t;
|
||||
|
||||
#define FSEG_HDR_SPACE 0 /*!< space id of the inode */
|
||||
#define FSEG_HDR_PAGE_NO 4 /*!< page number of the inode */
|
||||
#define FSEG_HDR_OFFSET 8 /*!< byte offset of the inode */
|
||||
|
||||
#define FSEG_HEADER_SIZE 10 /*!< Length of the file system
|
||||
header, in bytes */
|
||||
/* @} */
|
||||
|
||||
/** Flags for fsp_reserve_free_extents @{ */
|
||||
#define FSP_NORMAL 1000000
|
||||
#define FSP_UNDO 2000000
|
||||
#define FSP_CLEANING 3000000
|
||||
/* @} */
|
||||
|
||||
/* Number of pages described in a single descriptor page: currently each page
|
||||
description takes less than 1 byte; a descriptor page is repeated every
|
||||
this many file pages */
|
||||
/* #define XDES_DESCRIBED_PER_PAGE UNIV_PAGE_SIZE */
|
||||
/* This has been replaced with either UNIV_PAGE_SIZE or page_zip->size. */
|
||||
|
||||
/** @name The space low address page map
|
||||
The pages at FSP_XDES_OFFSET and FSP_IBUF_BITMAP_OFFSET are repeated
|
||||
every XDES_DESCRIBED_PER_PAGE pages in every tablespace. */
|
||||
/* @{ */
|
||||
/*--------------------------------------*/
|
||||
#define FSP_XDES_OFFSET 0 /* !< extent descriptor */
|
||||
#define FSP_IBUF_BITMAP_OFFSET 1 /* !< insert buffer bitmap */
|
||||
/* The ibuf bitmap pages are the ones whose
|
||||
page number is the number above plus a
|
||||
multiple of XDES_DESCRIBED_PER_PAGE */
|
||||
|
||||
#define FSP_FIRST_INODE_PAGE_NO 2 /*!< in every tablespace */
|
||||
/* The following pages exist
|
||||
in the system tablespace (space 0). */
|
||||
#define FSP_IBUF_HEADER_PAGE_NO 3 /*!< insert buffer
|
||||
header page, in
|
||||
tablespace 0 */
|
||||
#define FSP_IBUF_TREE_ROOT_PAGE_NO 4 /*!< insert buffer
|
||||
B-tree root page in
|
||||
tablespace 0 */
|
||||
/* The ibuf tree root page number in
|
||||
tablespace 0; its fseg inode is on the page
|
||||
number FSP_FIRST_INODE_PAGE_NO */
|
||||
#define FSP_TRX_SYS_PAGE_NO 5 /*!< transaction
|
||||
system header, in
|
||||
tablespace 0 */
|
||||
#define FSP_FIRST_RSEG_PAGE_NO 6 /*!< first rollback segment
|
||||
page, in tablespace 0 */
|
||||
#define FSP_DICT_HDR_PAGE_NO 7 /*!< data dictionary header
|
||||
page, in tablespace 0 */
|
||||
/*--------------------------------------*/
|
||||
/* @} */
|
||||
|
||||
#endif /* fsp0types_h */
|
||||
339
storage/innobase/include/fts0ast.h
Normal file
339
storage/innobase/include/fts0ast.h
Normal file
|
|
@ -0,0 +1,339 @@
|
|||
/*****************************************************************************
|
||||
|
||||
Copyright (c) 2007, 2014, Oracle and/or its affiliates. All Rights Reserved.
|
||||
|
||||
This program is free software; you can redistribute it and/or modify it under
|
||||
the terms of the GNU General Public License as published by the Free Software
|
||||
Foundation; version 2 of the License.
|
||||
|
||||
This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
|
||||
FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License along with
|
||||
this program; if not, write to the Free Software Foundation, Inc.,
|
||||
51 Franklin Street, Suite 500, Boston, MA 02110-1335 USA
|
||||
|
||||
*****************************************************************************/
|
||||
|
||||
/******************************************************************//**
|
||||
@file include/fts0ast.h
|
||||
The FTS query parser (AST) abstract syntax tree routines
|
||||
|
||||
Created 2007/03/16/03 Sunny Bains
|
||||
*******************************************************/
|
||||
|
||||
#ifndef INNOBASE_FST0AST_H
|
||||
#define INNOBASE_FST0AST_H
|
||||
|
||||
#include "mem0mem.h"
|
||||
#include "ha_prototypes.h"
|
||||
|
||||
/* The type of AST Node */
|
||||
enum fts_ast_type_t {
|
||||
FTS_AST_OPER, /*!< Operator */
|
||||
FTS_AST_NUMB, /*!< Number */
|
||||
FTS_AST_TERM, /*!< Term (or word) */
|
||||
FTS_AST_TEXT, /*!< Text string */
|
||||
FTS_AST_LIST, /*!< Expression list */
|
||||
FTS_AST_SUBEXP_LIST /*!< Sub-Expression list */
|
||||
};
|
||||
|
||||
/* The FTS query operators that we support */
|
||||
enum fts_ast_oper_t {
|
||||
FTS_NONE, /*!< No operator */
|
||||
|
||||
FTS_IGNORE, /*!< Ignore rows that contain
|
||||
this word */
|
||||
|
||||
FTS_EXIST, /*!< Include rows that contain
|
||||
this word */
|
||||
|
||||
FTS_NEGATE, /*!< Include rows that contain
|
||||
this word but rank them
|
||||
lower*/
|
||||
|
||||
FTS_INCR_RATING, /*!< Increase the rank for this
|
||||
word*/
|
||||
|
||||
FTS_DECR_RATING, /*!< Decrease the rank for this
|
||||
word*/
|
||||
|
||||
FTS_DISTANCE, /*!< Proximity distance */
|
||||
FTS_IGNORE_SKIP, /*!< Transient node operator
|
||||
signifies that this is a
|
||||
FTS_IGNORE node, and ignored in
|
||||
the first pass of
|
||||
fts_ast_visit() */
|
||||
FTS_EXIST_SKIP /*!< Transient node operator
|
||||
signifies that this ia a
|
||||
FTS_EXIST node, and ignored in
|
||||
the first pass of
|
||||
fts_ast_visit() */
|
||||
};
|
||||
|
||||
/* Data types used by the FTS parser */
|
||||
struct fts_lexer_t;
|
||||
struct fts_ast_node_t;
|
||||
struct fts_ast_state_t;
|
||||
struct fts_ast_string_t;
|
||||
|
||||
typedef dberr_t (*fts_ast_callback)(fts_ast_oper_t, fts_ast_node_t*, void*);
|
||||
|
||||
/********************************************************************
|
||||
Parse the string using the lexer setup within state.*/
|
||||
int
|
||||
fts_parse(
|
||||
/*======*/
|
||||
/* out: 0 on OK, 1 on error */
|
||||
fts_ast_state_t* state); /*!< in: ast state instance.*/
|
||||
|
||||
/********************************************************************
|
||||
Create an AST operator node */
|
||||
extern
|
||||
fts_ast_node_t*
|
||||
fts_ast_create_node_oper(
|
||||
/*=====================*/
|
||||
void* arg, /*!< in: ast state */
|
||||
fts_ast_oper_t oper); /*!< in: ast operator */
|
||||
/********************************************************************
|
||||
Create an AST term node, makes a copy of ptr */
|
||||
extern
|
||||
fts_ast_node_t*
|
||||
fts_ast_create_node_term(
|
||||
/*=====================*/
|
||||
void* arg, /*!< in: ast state */
|
||||
const fts_ast_string_t* ptr); /*!< in: term string */
|
||||
/********************************************************************
|
||||
Create an AST text node */
|
||||
extern
|
||||
fts_ast_node_t*
|
||||
fts_ast_create_node_text(
|
||||
/*=====================*/
|
||||
void* arg, /*!< in: ast state */
|
||||
const fts_ast_string_t* ptr); /*!< in: text string */
|
||||
/********************************************************************
|
||||
Create an AST expr list node */
|
||||
extern
|
||||
fts_ast_node_t*
|
||||
fts_ast_create_node_list(
|
||||
/*=====================*/
|
||||
void* arg, /*!< in: ast state */
|
||||
fts_ast_node_t* expr); /*!< in: ast expr */
|
||||
/********************************************************************
|
||||
Create a sub-expression list node. This function takes ownership of
|
||||
expr and is responsible for deleting it. */
|
||||
extern
|
||||
fts_ast_node_t*
|
||||
fts_ast_create_node_subexp_list(
|
||||
/*============================*/
|
||||
/* out: new node */
|
||||
void* arg, /*!< in: ast state instance */
|
||||
fts_ast_node_t* expr); /*!< in: ast expr instance */
|
||||
/********************************************************************
|
||||
Set the wildcard attribute of a term.*/
|
||||
extern
|
||||
void
|
||||
fts_ast_term_set_wildcard(
|
||||
/*======================*/
|
||||
fts_ast_node_t* node); /*!< in: term to change */
|
||||
/********************************************************************
|
||||
Set the proximity attribute of a text node. */
|
||||
|
||||
void
|
||||
fts_ast_term_set_distance(
|
||||
/*======================*/
|
||||
fts_ast_node_t* node, /*!< in/out: text node */
|
||||
ulint distance); /*!< in: the text proximity
|
||||
distance */
|
||||
/********************************************************************//**
|
||||
Free a fts_ast_node_t instance.
|
||||
@return next node to free */
|
||||
UNIV_INTERN
|
||||
fts_ast_node_t*
|
||||
fts_ast_free_node(
|
||||
/*==============*/
|
||||
fts_ast_node_t* node); /*!< in: node to free */
|
||||
/********************************************************************
|
||||
Add a sub-expression to an AST*/
|
||||
extern
|
||||
fts_ast_node_t*
|
||||
fts_ast_add_node(
|
||||
/*=============*/
|
||||
fts_ast_node_t* list, /*!< in: list node instance */
|
||||
fts_ast_node_t* node); /*!< in: (sub) expr to add */
|
||||
/********************************************************************
|
||||
Print the AST node recursively.*/
|
||||
extern
|
||||
void
|
||||
fts_ast_node_print(
|
||||
/*===============*/
|
||||
fts_ast_node_t* node); /*!< in: ast node to print */
|
||||
/********************************************************************
|
||||
For tracking node allocations, in case there is an during parsing.*/
|
||||
extern
|
||||
void
|
||||
fts_ast_state_add_node(
|
||||
/*===================*/
|
||||
fts_ast_state_t*state, /*!< in: ast state instance */
|
||||
fts_ast_node_t* node); /*!< in: node to add to state */
|
||||
/********************************************************************
|
||||
Free node and expr allocations.*/
|
||||
extern
|
||||
void
|
||||
fts_ast_state_free(
|
||||
/*===============*/
|
||||
fts_ast_state_t*state); /*!< in: state instance
|
||||
to free */
|
||||
/******************************************************************//**
|
||||
Traverse the AST - in-order traversal.
|
||||
@return DB_SUCCESS if all went well */
|
||||
UNIV_INTERN
|
||||
dberr_t
|
||||
fts_ast_visit(
|
||||
/*==========*/
|
||||
fts_ast_oper_t oper, /*!< in: FTS operator */
|
||||
fts_ast_node_t* node, /*!< in: instance to traverse*/
|
||||
fts_ast_callback visitor, /*!< in: callback */
|
||||
void* arg, /*!< in: callback arg */
|
||||
bool* has_ignore) /*!< out: whether we encounter
|
||||
and ignored processing an
|
||||
operator, currently we only
|
||||
ignore FTS_IGNORE operator */
|
||||
__attribute__((nonnull, warn_unused_result));
|
||||
/*****************************************************************//**
|
||||
Process (nested) sub-expression, create a new result set to store the
|
||||
sub-expression result by processing nodes under current sub-expression
|
||||
list. Merge the sub-expression result with that of parent expression list.
|
||||
@return DB_SUCCESS if all went well */
|
||||
UNIV_INTERN
|
||||
dberr_t
|
||||
fts_ast_visit_sub_exp(
|
||||
/*==================*/
|
||||
fts_ast_node_t* node, /*!< in: instance to traverse*/
|
||||
fts_ast_callback visitor, /*!< in: callback */
|
||||
void* arg) /*!< in: callback arg */
|
||||
__attribute__((nonnull, warn_unused_result));
|
||||
/********************************************************************
|
||||
Create a lex instance.*/
|
||||
UNIV_INTERN
|
||||
fts_lexer_t*
|
||||
fts_lexer_create(
|
||||
/*=============*/
|
||||
ibool boolean_mode, /*!< in: query type */
|
||||
const byte* query, /*!< in: query string */
|
||||
ulint query_len) /*!< in: query string len */
|
||||
__attribute__((nonnull, malloc, warn_unused_result));
|
||||
/********************************************************************
|
||||
Free an fts_lexer_t instance.*/
|
||||
UNIV_INTERN
|
||||
void
|
||||
fts_lexer_free(
|
||||
/*===========*/
|
||||
fts_lexer_t* fts_lexer) /*!< in: lexer instance to
|
||||
free */
|
||||
__attribute__((nonnull));
|
||||
|
||||
/**
|
||||
Create an ast string object, with NUL-terminator, so the string
|
||||
has one more byte than len
|
||||
@param[in] str pointer to string
|
||||
@param[in] len length of the string
|
||||
@return ast string with NUL-terminator */
|
||||
UNIV_INTERN
|
||||
fts_ast_string_t*
|
||||
fts_ast_string_create(
|
||||
const byte* str,
|
||||
ulint len);
|
||||
|
||||
/**
|
||||
Free an ast string instance
|
||||
@param[in,out] ast_str string to free */
|
||||
UNIV_INTERN
|
||||
void
|
||||
fts_ast_string_free(
|
||||
fts_ast_string_t* ast_str);
|
||||
|
||||
/**
|
||||
Translate ast string of type FTS_AST_NUMB to unsigned long by strtoul
|
||||
@param[in] str string to translate
|
||||
@param[in] base the base
|
||||
@return translated number */
|
||||
UNIV_INTERN
|
||||
ulint
|
||||
fts_ast_string_to_ul(
|
||||
const fts_ast_string_t* ast_str,
|
||||
int base);
|
||||
|
||||
/**
|
||||
Print the ast string
|
||||
@param[in] str string to print */
|
||||
UNIV_INTERN
|
||||
void
|
||||
fts_ast_string_print(
|
||||
const fts_ast_string_t* ast_str);
|
||||
|
||||
/* String of length len.
|
||||
We always store the string of length len with a terminating '\0',
|
||||
regardless of there is any 0x00 in the string itself */
|
||||
struct fts_ast_string_t {
|
||||
/*!< Pointer to string. */
|
||||
byte* str;
|
||||
|
||||
/*!< Length of the string. */
|
||||
ulint len;
|
||||
};
|
||||
|
||||
/* Query term type */
|
||||
struct fts_ast_term_t {
|
||||
fts_ast_string_t* ptr; /*!< Pointer to term string.*/
|
||||
ibool wildcard; /*!< TRUE if wild card set.*/
|
||||
};
|
||||
|
||||
/* Query text type */
|
||||
struct fts_ast_text_t {
|
||||
fts_ast_string_t* ptr; /*!< Pointer to text string.*/
|
||||
ulint distance; /*!< > 0 if proximity distance
|
||||
set */
|
||||
};
|
||||
|
||||
/* The list of nodes in an expr list */
|
||||
struct fts_ast_list_t {
|
||||
fts_ast_node_t* head; /*!< Children list head */
|
||||
fts_ast_node_t* tail; /*!< Children list tail */
|
||||
};
|
||||
|
||||
/* FTS AST node to store the term, text, operator and sub-expressions.*/
|
||||
struct fts_ast_node_t {
|
||||
fts_ast_type_t type; /*!< The type of node */
|
||||
fts_ast_text_t text; /*!< Text node */
|
||||
fts_ast_term_t term; /*!< Term node */
|
||||
fts_ast_oper_t oper; /*!< Operator value */
|
||||
fts_ast_list_t list; /*!< Expression list */
|
||||
fts_ast_node_t* next; /*!< Link for expr list */
|
||||
fts_ast_node_t* next_alloc; /*!< For tracking allocations */
|
||||
bool visited; /*!< whether this node is
|
||||
already processed */
|
||||
};
|
||||
|
||||
/* To track state during parsing */
|
||||
struct fts_ast_state_t {
|
||||
mem_heap_t* heap; /*!< Heap to use for alloc */
|
||||
fts_ast_node_t* root; /*!< If all goes OK, then this
|
||||
will point to the root.*/
|
||||
|
||||
fts_ast_list_t list; /*!< List of nodes allocated */
|
||||
|
||||
fts_lexer_t* lexer; /*!< Lexer callback + arg */
|
||||
CHARSET_INFO* charset; /*!< charset used for
|
||||
tokenization */
|
||||
};
|
||||
|
||||
#ifdef UNIV_DEBUG
|
||||
const char*
|
||||
fts_ast_oper_name_get(fts_ast_oper_t oper);
|
||||
const char*
|
||||
fts_ast_node_type_get(fts_ast_type_t type);
|
||||
#endif /* UNIV_DEBUG */
|
||||
|
||||
#endif /* INNOBASE_FSTS0AST_H */
|
||||
349
storage/innobase/include/fts0blex.h
Normal file
349
storage/innobase/include/fts0blex.h
Normal file
|
|
@ -0,0 +1,349 @@
|
|||
#ifndef fts0bHEADER_H
|
||||
#define fts0bHEADER_H 1
|
||||
#define fts0bIN_HEADER 1
|
||||
|
||||
#line 6 "../include/fts0blex.h"
|
||||
|
||||
#line 8 "../include/fts0blex.h"
|
||||
|
||||
#define YY_INT_ALIGNED short int
|
||||
|
||||
/* A lexical scanner generated by flex */
|
||||
|
||||
#define FLEX_SCANNER
|
||||
#define YY_FLEX_MAJOR_VERSION 2
|
||||
#define YY_FLEX_MINOR_VERSION 5
|
||||
#define YY_FLEX_SUBMINOR_VERSION 35
|
||||
#if YY_FLEX_SUBMINOR_VERSION > 0
|
||||
#define FLEX_BETA
|
||||
#endif
|
||||
|
||||
/* First, we deal with platform-specific or compiler-specific issues. */
|
||||
|
||||
/* begin standard C headers. */
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <errno.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
/* end standard C headers. */
|
||||
|
||||
/* flex integer type definitions */
|
||||
|
||||
#ifndef FLEXINT_H
|
||||
#define FLEXINT_H
|
||||
|
||||
/* C99 systems have <inttypes.h>. Non-C99 systems may or may not. */
|
||||
|
||||
#if defined (__STDC_VERSION__) && __STDC_VERSION__ >= 199901L
|
||||
|
||||
/* C99 says to define __STDC_LIMIT_MACROS before including stdint.h,
|
||||
* if you want the limit (max/min) macros for int types.
|
||||
*/
|
||||
#ifndef __STDC_LIMIT_MACROS
|
||||
#define __STDC_LIMIT_MACROS 1
|
||||
#endif
|
||||
|
||||
#include <inttypes.h>
|
||||
typedef int8_t flex_int8_t;
|
||||
typedef uint8_t flex_uint8_t;
|
||||
typedef int16_t flex_int16_t;
|
||||
typedef uint16_t flex_uint16_t;
|
||||
typedef int32_t flex_int32_t;
|
||||
typedef uint32_t flex_uint32_t;
|
||||
#else
|
||||
typedef signed char flex_int8_t;
|
||||
typedef short int flex_int16_t;
|
||||
typedef int flex_int32_t;
|
||||
typedef unsigned char flex_uint8_t;
|
||||
typedef unsigned short int flex_uint16_t;
|
||||
typedef unsigned int flex_uint32_t;
|
||||
|
||||
/* Limits of integral types. */
|
||||
#ifndef INT8_MIN
|
||||
#define INT8_MIN (-128)
|
||||
#endif
|
||||
#ifndef INT16_MIN
|
||||
#define INT16_MIN (-32767-1)
|
||||
#endif
|
||||
#ifndef INT32_MIN
|
||||
#define INT32_MIN (-2147483647-1)
|
||||
#endif
|
||||
#ifndef INT8_MAX
|
||||
#define INT8_MAX (127)
|
||||
#endif
|
||||
#ifndef INT16_MAX
|
||||
#define INT16_MAX (32767)
|
||||
#endif
|
||||
#ifndef INT32_MAX
|
||||
#define INT32_MAX (2147483647)
|
||||
#endif
|
||||
#ifndef UINT8_MAX
|
||||
#define UINT8_MAX (255U)
|
||||
#endif
|
||||
#ifndef UINT16_MAX
|
||||
#define UINT16_MAX (65535U)
|
||||
#endif
|
||||
#ifndef UINT32_MAX
|
||||
#define UINT32_MAX (4294967295U)
|
||||
#endif
|
||||
|
||||
#endif /* ! C99 */
|
||||
|
||||
#endif /* ! FLEXINT_H */
|
||||
|
||||
#ifdef __cplusplus
|
||||
|
||||
/* The "const" storage-class-modifier is valid. */
|
||||
#define YY_USE_CONST
|
||||
|
||||
#else /* ! __cplusplus */
|
||||
|
||||
/* C99 requires __STDC__ to be defined as 1. */
|
||||
#if defined (__STDC__)
|
||||
|
||||
#define YY_USE_CONST
|
||||
|
||||
#endif /* defined (__STDC__) */
|
||||
#endif /* ! __cplusplus */
|
||||
|
||||
#ifdef YY_USE_CONST
|
||||
#define yyconst const
|
||||
#else
|
||||
#define yyconst
|
||||
#endif
|
||||
|
||||
/* An opaque pointer. */
|
||||
#ifndef YY_TYPEDEF_YY_SCANNER_T
|
||||
#define YY_TYPEDEF_YY_SCANNER_T
|
||||
typedef void* yyscan_t;
|
||||
#endif
|
||||
|
||||
/* For convenience, these vars (plus the bison vars far below)
|
||||
are macros in the reentrant scanner. */
|
||||
#define yyin yyg->yyin_r
|
||||
#define yyout yyg->yyout_r
|
||||
#define yyextra yyg->yyextra_r
|
||||
#define yyleng yyg->yyleng_r
|
||||
#define yytext yyg->yytext_r
|
||||
#define yylineno (YY_CURRENT_BUFFER_LVALUE->yy_bs_lineno)
|
||||
#define yycolumn (YY_CURRENT_BUFFER_LVALUE->yy_bs_column)
|
||||
#define yy_flex_debug yyg->yy_flex_debug_r
|
||||
|
||||
/* Size of default input buffer. */
|
||||
#ifndef YY_BUF_SIZE
|
||||
#ifdef __ia64__
|
||||
/* On IA-64, the buffer size is 16k, not 8k.
|
||||
* Moreover, YY_BUF_SIZE is 2*YY_READ_BUF_SIZE in the general case.
|
||||
* Ditto for the __ia64__ case accordingly.
|
||||
*/
|
||||
#define YY_BUF_SIZE 32768
|
||||
#else
|
||||
#define YY_BUF_SIZE 16384
|
||||
#endif /* __ia64__ */
|
||||
#endif
|
||||
|
||||
#ifndef YY_TYPEDEF_YY_BUFFER_STATE
|
||||
#define YY_TYPEDEF_YY_BUFFER_STATE
|
||||
typedef struct yy_buffer_state *YY_BUFFER_STATE;
|
||||
#endif
|
||||
|
||||
#ifndef YY_TYPEDEF_YY_SIZE_T
|
||||
#define YY_TYPEDEF_YY_SIZE_T
|
||||
typedef size_t yy_size_t;
|
||||
#endif
|
||||
|
||||
#ifndef YY_STRUCT_YY_BUFFER_STATE
|
||||
#define YY_STRUCT_YY_BUFFER_STATE
|
||||
struct yy_buffer_state
|
||||
{
|
||||
FILE *yy_input_file;
|
||||
|
||||
char *yy_ch_buf; /* input buffer */
|
||||
char *yy_buf_pos; /* current position in input buffer */
|
||||
|
||||
/* Size of input buffer in bytes, not including room for EOB
|
||||
* characters.
|
||||
*/
|
||||
yy_size_t yy_buf_size;
|
||||
|
||||
/* Number of characters read into yy_ch_buf, not including EOB
|
||||
* characters.
|
||||
*/
|
||||
int yy_n_chars;
|
||||
|
||||
/* Whether we "own" the buffer - i.e., we know we created it,
|
||||
* and can realloc() it to grow it, and should free() it to
|
||||
* delete it.
|
||||
*/
|
||||
int yy_is_our_buffer;
|
||||
|
||||
/* Whether this is an "interactive" input source; if so, and
|
||||
* if we're using stdio for input, then we want to use getc()
|
||||
* instead of fread(), to make sure we stop fetching input after
|
||||
* each newline.
|
||||
*/
|
||||
int yy_is_interactive;
|
||||
|
||||
/* Whether we're considered to be at the beginning of a line.
|
||||
* If so, '^' rules will be active on the next match, otherwise
|
||||
* not.
|
||||
*/
|
||||
int yy_at_bol;
|
||||
|
||||
int yy_bs_lineno; /**< The line count. */
|
||||
int yy_bs_column; /**< The column count. */
|
||||
|
||||
/* Whether to try to fill the input buffer when we reach the
|
||||
* end of it.
|
||||
*/
|
||||
int yy_fill_buffer;
|
||||
|
||||
int yy_buffer_status;
|
||||
|
||||
};
|
||||
#endif /* !YY_STRUCT_YY_BUFFER_STATE */
|
||||
|
||||
void fts0brestart (FILE *input_file ,yyscan_t yyscanner );
|
||||
void fts0b_switch_to_buffer (YY_BUFFER_STATE new_buffer ,yyscan_t yyscanner );
|
||||
YY_BUFFER_STATE fts0b_create_buffer (FILE *file,int size ,yyscan_t yyscanner );
|
||||
void fts0b_delete_buffer (YY_BUFFER_STATE b ,yyscan_t yyscanner );
|
||||
void fts0b_flush_buffer (YY_BUFFER_STATE b ,yyscan_t yyscanner );
|
||||
void fts0bpush_buffer_state (YY_BUFFER_STATE new_buffer ,yyscan_t yyscanner );
|
||||
void fts0bpop_buffer_state (yyscan_t yyscanner );
|
||||
|
||||
YY_BUFFER_STATE fts0b_scan_buffer (char *base,yy_size_t size ,yyscan_t yyscanner );
|
||||
YY_BUFFER_STATE fts0b_scan_string (yyconst char *yy_str ,yyscan_t yyscanner );
|
||||
YY_BUFFER_STATE fts0b_scan_bytes (yyconst char *bytes,int len ,yyscan_t yyscanner );
|
||||
|
||||
void *fts0balloc (yy_size_t ,yyscan_t yyscanner );
|
||||
void *fts0brealloc (void *,yy_size_t ,yyscan_t yyscanner );
|
||||
void fts0bfree (void * ,yyscan_t yyscanner );
|
||||
|
||||
/* Begin user sect3 */
|
||||
|
||||
#define fts0bwrap(n) 1
|
||||
#define YY_SKIP_YYWRAP
|
||||
|
||||
#define yytext_ptr yytext_r
|
||||
|
||||
#ifdef YY_HEADER_EXPORT_START_CONDITIONS
|
||||
#define INITIAL 0
|
||||
|
||||
#endif
|
||||
|
||||
#ifndef YY_NO_UNISTD_H
|
||||
/* Special case for "unistd.h", since it is non-ANSI. We include it way
|
||||
* down here because we want the user's section 1 to have been scanned first.
|
||||
* The user has a chance to override it with an option.
|
||||
*/
|
||||
#include <unistd.h>
|
||||
#endif
|
||||
|
||||
#ifndef YY_EXTRA_TYPE
|
||||
#define YY_EXTRA_TYPE void *
|
||||
#endif
|
||||
|
||||
int fts0blex_init (yyscan_t* scanner);
|
||||
|
||||
int fts0blex_init_extra (YY_EXTRA_TYPE user_defined,yyscan_t* scanner);
|
||||
|
||||
/* Accessor methods to globals.
|
||||
These are made visible to non-reentrant scanners for convenience. */
|
||||
|
||||
int fts0blex_destroy (yyscan_t yyscanner );
|
||||
|
||||
int fts0bget_debug (yyscan_t yyscanner );
|
||||
|
||||
void fts0bset_debug (int debug_flag ,yyscan_t yyscanner );
|
||||
|
||||
YY_EXTRA_TYPE fts0bget_extra (yyscan_t yyscanner );
|
||||
|
||||
void fts0bset_extra (YY_EXTRA_TYPE user_defined ,yyscan_t yyscanner );
|
||||
|
||||
FILE *fts0bget_in (yyscan_t yyscanner );
|
||||
|
||||
void fts0bset_in (FILE * in_str ,yyscan_t yyscanner );
|
||||
|
||||
FILE *fts0bget_out (yyscan_t yyscanner );
|
||||
|
||||
void fts0bset_out (FILE * out_str ,yyscan_t yyscanner );
|
||||
|
||||
int fts0bget_leng (yyscan_t yyscanner );
|
||||
|
||||
char *fts0bget_text (yyscan_t yyscanner );
|
||||
|
||||
int fts0bget_lineno (yyscan_t yyscanner );
|
||||
|
||||
void fts0bset_lineno (int line_number ,yyscan_t yyscanner );
|
||||
|
||||
/* Macros after this point can all be overridden by user definitions in
|
||||
* section 1.
|
||||
*/
|
||||
|
||||
#ifndef YY_SKIP_YYWRAP
|
||||
#ifdef __cplusplus
|
||||
extern "C" int fts0bwrap (yyscan_t yyscanner );
|
||||
#else
|
||||
extern int fts0bwrap (yyscan_t yyscanner );
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifndef yytext_ptr
|
||||
static void yy_flex_strncpy (char *,yyconst char *,int ,yyscan_t yyscanner);
|
||||
#endif
|
||||
|
||||
#ifdef YY_NEED_STRLEN
|
||||
static int yy_flex_strlen (yyconst char * ,yyscan_t yyscanner);
|
||||
#endif
|
||||
|
||||
#ifndef YY_NO_INPUT
|
||||
|
||||
#endif
|
||||
|
||||
/* Amount of stuff to slurp up with each read. */
|
||||
#ifndef YY_READ_BUF_SIZE
|
||||
#ifdef __ia64__
|
||||
/* On IA-64, the buffer size is 16k, not 8k */
|
||||
#define YY_READ_BUF_SIZE 16384
|
||||
#else
|
||||
#define YY_READ_BUF_SIZE 8192
|
||||
#endif /* __ia64__ */
|
||||
#endif
|
||||
|
||||
/* Number of entries by which start-condition stack grows. */
|
||||
#ifndef YY_START_STACK_INCR
|
||||
#define YY_START_STACK_INCR 25
|
||||
#endif
|
||||
|
||||
/* Default declaration of generated scanner - a define so the user can
|
||||
* easily add parameters.
|
||||
*/
|
||||
#ifndef YY_DECL
|
||||
#define YY_DECL_IS_OURS 1
|
||||
|
||||
extern int fts0blex (yyscan_t yyscanner);
|
||||
|
||||
#define YY_DECL int fts0blex (yyscan_t yyscanner)
|
||||
#endif /* !YY_DECL */
|
||||
|
||||
/* yy_get_previous_state - get the state just before the EOB char was reached */
|
||||
|
||||
#undef YY_NEW_FILE
|
||||
#undef YY_FLUSH_BUFFER
|
||||
#undef yy_set_bol
|
||||
#undef yy_new_buffer
|
||||
#undef yy_set_interactive
|
||||
#undef YY_DO_BEFORE_ACTION
|
||||
|
||||
#ifdef YY_DECL_IS_OURS
|
||||
#undef YY_DECL_IS_OURS
|
||||
#undef YY_DECL
|
||||
#endif
|
||||
|
||||
#line 73 "fts0blex.l"
|
||||
|
||||
|
||||
#line 348 "../include/fts0blex.h"
|
||||
#undef fts0bIN_HEADER
|
||||
#endif /* fts0bHEADER_H */
|
||||
1039
storage/innobase/include/fts0fts.h
Normal file
1039
storage/innobase/include/fts0fts.h
Normal file
File diff suppressed because it is too large
Load diff
37
storage/innobase/include/fts0opt.h
Normal file
37
storage/innobase/include/fts0opt.h
Normal file
|
|
@ -0,0 +1,37 @@
|
|||
/*****************************************************************************
|
||||
|
||||
Copyright (c) 2001, 2011, Oracle and/or its affiliates. All Rights Reserved.
|
||||
|
||||
This program is free software; you can redistribute it and/or modify it under
|
||||
the terms of the GNU General Public License as published by the Free Software
|
||||
Foundation; version 2 of the License.
|
||||
|
||||
This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
|
||||
FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License along with
|
||||
this program; if not, write to the Free Software Foundation, Inc.,
|
||||
51 Franklin Street, Suite 500, Boston, MA 02110-1335 USA
|
||||
|
||||
*****************************************************************************/
|
||||
|
||||
/******************************************************************//**
|
||||
@file include/fts0opt.h
|
||||
Full Text Search optimize thread
|
||||
|
||||
Created 2011-02-15 Jimmy Yang
|
||||
***********************************************************************/
|
||||
#ifndef INNODB_FTS0OPT_H
|
||||
#define INNODB_FTS0OPT_H
|
||||
|
||||
/********************************************************************
|
||||
Callback function to fetch the rows in an FTS INDEX record. */
|
||||
UNIV_INTERN
|
||||
ibool
|
||||
fts_optimize_index_fetch_node(
|
||||
/*==========================*/
|
||||
/* out: always returns non-NULL */
|
||||
void* row, /* in: sel_node_t* */
|
||||
void* user_arg); /* in: pointer to ib_vector_t */
|
||||
#endif
|
||||
72
storage/innobase/include/fts0pars.h
Normal file
72
storage/innobase/include/fts0pars.h
Normal file
|
|
@ -0,0 +1,72 @@
|
|||
/* A Bison parser, made by GNU Bison 2.5. */
|
||||
|
||||
/* Bison interface for Yacc-like parsers in C
|
||||
|
||||
Copyright (C) 1984, 1989-1990, 2000-2011 Free Software Foundation, Inc.
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>. */
|
||||
|
||||
/* As a special exception, you may create a larger work that contains
|
||||
part or all of the Bison parser skeleton and distribute that work
|
||||
under terms of your choice, so long as that work isn't itself a
|
||||
parser generator using the skeleton or a modified version thereof
|
||||
as a parser skeleton. Alternatively, if you modify or redistribute
|
||||
the parser skeleton itself, you may (at your option) remove this
|
||||
special exception, which will cause the skeleton and the resulting
|
||||
Bison output files to be licensed under the GNU General Public
|
||||
License without this special exception.
|
||||
|
||||
This special exception was added by the Free Software Foundation in
|
||||
version 2.2 of Bison. */
|
||||
|
||||
|
||||
/* Tokens. */
|
||||
#ifndef YYTOKENTYPE
|
||||
# define YYTOKENTYPE
|
||||
/* Put the tokens into the symbol table, so that GDB and other debuggers
|
||||
know about them. */
|
||||
enum yytokentype {
|
||||
FTS_OPER = 258,
|
||||
FTS_TEXT = 259,
|
||||
FTS_TERM = 260,
|
||||
FTS_NUMB = 261
|
||||
};
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
#if ! defined YYSTYPE && ! defined YYSTYPE_IS_DECLARED
|
||||
typedef union YYSTYPE
|
||||
{
|
||||
|
||||
/* Line 2068 of yacc.c */
|
||||
#line 61 "fts0pars.y"
|
||||
|
||||
int oper;
|
||||
fts_ast_string_t* token;
|
||||
fts_ast_node_t* node;
|
||||
|
||||
|
||||
|
||||
/* Line 2068 of yacc.c */
|
||||
#line 64 "fts0pars.hh"
|
||||
} YYSTYPE;
|
||||
# define YYSTYPE_IS_TRIVIAL 1
|
||||
# define yystype YYSTYPE /* obsolescent; will be withdrawn */
|
||||
# define YYSTYPE_IS_DECLARED 1
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
|
||||
653
storage/innobase/include/fts0priv.h
Normal file
653
storage/innobase/include/fts0priv.h
Normal file
|
|
@ -0,0 +1,653 @@
|
|||
/*****************************************************************************
|
||||
|
||||
Copyright (c) 2011, 2013, Oracle and/or its affiliates. All Rights Reserved.
|
||||
|
||||
This program is free software; you can redistribute it and/or modify it under
|
||||
the terms of the GNU General Public License as published by the Free Software
|
||||
Foundation; version 2 of the License.
|
||||
|
||||
This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
|
||||
FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License along with
|
||||
this program; if not, write to the Free Software Foundation, Inc.,
|
||||
51 Franklin Street, Suite 500, Boston, MA 02110-1335 USA
|
||||
|
||||
*****************************************************************************/
|
||||
|
||||
/******************************************************************//**
|
||||
@file include/fts0priv.h
|
||||
Full text search internal header file
|
||||
|
||||
Created 2011/09/02 Sunny Bains
|
||||
***********************************************************************/
|
||||
|
||||
#ifndef INNOBASE_FTS0PRIV_H
|
||||
#define INNOBASE_FTS0PRIV_H
|
||||
|
||||
#include "dict0dict.h"
|
||||
#include "pars0pars.h"
|
||||
#include "que0que.h"
|
||||
#include "que0types.h"
|
||||
#include "fts0types.h"
|
||||
|
||||
/* The various states of the FTS sub system pertaining to a table with
|
||||
FTS indexes defined on it. */
|
||||
enum fts_table_state_enum {
|
||||
/* !<This must be 0 since we insert
|
||||
a hard coded '0' at create time
|
||||
to the config table */
|
||||
|
||||
FTS_TABLE_STATE_RUNNING = 0, /*!< Auxiliary tables created OK */
|
||||
|
||||
FTS_TABLE_STATE_OPTIMIZING, /*!< This is a substate of RUNNING */
|
||||
|
||||
FTS_TABLE_STATE_DELETED /*!< All aux tables to be dropped when
|
||||
it's safe to do so */
|
||||
};
|
||||
|
||||
typedef enum fts_table_state_enum fts_table_state_t;
|
||||
|
||||
/** The default time to wait for the background thread (in microsecnds). */
|
||||
#define FTS_MAX_BACKGROUND_THREAD_WAIT 10000
|
||||
|
||||
/** Maximum number of iterations to wait before we complain */
|
||||
#define FTS_BACKGROUND_THREAD_WAIT_COUNT 1000
|
||||
|
||||
/** The maximum length of the config table's value column in bytes */
|
||||
#define FTS_MAX_CONFIG_NAME_LEN 64
|
||||
|
||||
/** The maximum length of the config table's value column in bytes */
|
||||
#define FTS_MAX_CONFIG_VALUE_LEN 1024
|
||||
|
||||
/** Approx. upper limit of ilist length in bytes. */
|
||||
#define FTS_ILIST_MAX_SIZE (64 * 1024)
|
||||
|
||||
/** FTS config table name parameters */
|
||||
|
||||
/** The number of seconds after which an OPTIMIZE run will stop */
|
||||
#define FTS_OPTIMIZE_LIMIT_IN_SECS "optimize_checkpoint_limit"
|
||||
|
||||
/** The next doc id */
|
||||
#define FTS_SYNCED_DOC_ID "synced_doc_id"
|
||||
|
||||
/** The last word that was OPTIMIZED */
|
||||
#define FTS_LAST_OPTIMIZED_WORD "last_optimized_word"
|
||||
|
||||
/** Total number of documents that have been deleted. The next_doc_id
|
||||
minus this count gives us the total number of documents. */
|
||||
#define FTS_TOTAL_DELETED_COUNT "deleted_doc_count"
|
||||
|
||||
/** Total number of words parsed from all documents */
|
||||
#define FTS_TOTAL_WORD_COUNT "total_word_count"
|
||||
|
||||
/** Start of optimize of an FTS index */
|
||||
#define FTS_OPTIMIZE_START_TIME "optimize_start_time"
|
||||
|
||||
/** End of optimize for an FTS index */
|
||||
#define FTS_OPTIMIZE_END_TIME "optimize_end_time"
|
||||
|
||||
/** User specified stopword table name */
|
||||
#define FTS_STOPWORD_TABLE_NAME "stopword_table_name"
|
||||
|
||||
/** Whether to use (turn on/off) stopword */
|
||||
#define FTS_USE_STOPWORD "use_stopword"
|
||||
|
||||
/** State of the FTS system for this table. It can be one of
|
||||
RUNNING, OPTIMIZING, DELETED. */
|
||||
#define FTS_TABLE_STATE "table_state"
|
||||
|
||||
/** The minimum length of an FTS auxiliary table names's id component
|
||||
e.g., For an auxiliary table name
|
||||
|
||||
FTS_<TABLE_ID>_SUFFIX
|
||||
|
||||
This constant is for the minimum length required to store the <TABLE_ID>
|
||||
component.
|
||||
*/
|
||||
#define FTS_AUX_MIN_TABLE_ID_LENGTH 48
|
||||
|
||||
/** Maximum length of an integer stored in the config table value column. */
|
||||
#define FTS_MAX_INT_LEN 32
|
||||
|
||||
/******************************************************************//**
|
||||
Parse an SQL string. %s is replaced with the table's id.
|
||||
@return query graph */
|
||||
UNIV_INTERN
|
||||
que_t*
|
||||
fts_parse_sql(
|
||||
/*==========*/
|
||||
fts_table_t* fts_table, /*!< in: FTS aux table */
|
||||
pars_info_t* info, /*!< in: info struct, or NULL */
|
||||
const char* sql) /*!< in: SQL string to evaluate */
|
||||
__attribute__((nonnull(3), malloc, warn_unused_result));
|
||||
/******************************************************************//**
|
||||
Evaluate a parsed SQL statement
|
||||
@return DB_SUCCESS or error code */
|
||||
UNIV_INTERN
|
||||
dberr_t
|
||||
fts_eval_sql(
|
||||
/*=========*/
|
||||
trx_t* trx, /*!< in: transaction */
|
||||
que_t* graph) /*!< in: Parsed statement */
|
||||
__attribute__((nonnull, warn_unused_result));
|
||||
/******************************************************************//**
|
||||
Construct the name of an ancillary FTS table for the given table.
|
||||
@return own: table name, must be freed with mem_free() */
|
||||
UNIV_INTERN
|
||||
char*
|
||||
fts_get_table_name(
|
||||
/*===============*/
|
||||
const fts_table_t*
|
||||
fts_table) /*!< in: FTS aux table info */
|
||||
__attribute__((nonnull, malloc, warn_unused_result));
|
||||
/******************************************************************//**
|
||||
Construct the column specification part of the SQL string for selecting the
|
||||
indexed FTS columns for the given table. Adds the necessary bound
|
||||
ids to the given 'info' and returns the SQL string. Examples:
|
||||
|
||||
One indexed column named "text":
|
||||
|
||||
"$sel0",
|
||||
info/ids: sel0 -> "text"
|
||||
|
||||
Two indexed columns named "subject" and "content":
|
||||
|
||||
"$sel0, $sel1",
|
||||
info/ids: sel0 -> "subject", sel1 -> "content",
|
||||
@return heap-allocated WHERE string */
|
||||
UNIV_INTERN
|
||||
const char*
|
||||
fts_get_select_columns_str(
|
||||
/*=======================*/
|
||||
dict_index_t* index, /*!< in: FTS index */
|
||||
pars_info_t* info, /*!< in/out: parser info */
|
||||
mem_heap_t* heap) /*!< in: memory heap */
|
||||
__attribute__((nonnull, warn_unused_result));
|
||||
|
||||
/** define for fts_doc_fetch_by_doc_id() "option" value, defines whether
|
||||
we want to get Doc whose ID is equal to or greater or smaller than supplied
|
||||
ID */
|
||||
#define FTS_FETCH_DOC_BY_ID_EQUAL 1
|
||||
#define FTS_FETCH_DOC_BY_ID_LARGE 2
|
||||
#define FTS_FETCH_DOC_BY_ID_SMALL 3
|
||||
|
||||
/*************************************************************//**
|
||||
Fetch document (= a single row's indexed text) with the given
|
||||
document id.
|
||||
@return: DB_SUCCESS if fetch is successful, else error */
|
||||
UNIV_INTERN
|
||||
dberr_t
|
||||
fts_doc_fetch_by_doc_id(
|
||||
/*====================*/
|
||||
fts_get_doc_t* get_doc, /*!< in: state */
|
||||
doc_id_t doc_id, /*!< in: id of document to fetch */
|
||||
dict_index_t* index_to_use, /*!< in: caller supplied FTS index,
|
||||
or NULL */
|
||||
ulint option, /*!< in: search option, if it is
|
||||
greater than doc_id or equal */
|
||||
fts_sql_callback
|
||||
callback, /*!< in: callback to read
|
||||
records */
|
||||
void* arg) /*!< in: callback arg */
|
||||
__attribute__((nonnull(6)));
|
||||
|
||||
/*******************************************************************//**
|
||||
Callback function for fetch that stores the text of an FTS document,
|
||||
converting each column to UTF-16.
|
||||
@return always FALSE */
|
||||
UNIV_INTERN
|
||||
ibool
|
||||
fts_query_expansion_fetch_doc(
|
||||
/*==========================*/
|
||||
void* row, /*!< in: sel_node_t* */
|
||||
void* user_arg) /*!< in: fts_doc_t* */
|
||||
__attribute__((nonnull));
|
||||
/********************************************************************
|
||||
Write out a single word's data as new entry/entries in the INDEX table.
|
||||
@return DB_SUCCESS if all OK. */
|
||||
UNIV_INTERN
|
||||
dberr_t
|
||||
fts_write_node(
|
||||
/*===========*/
|
||||
trx_t* trx, /*!< in: transaction */
|
||||
que_t** graph, /*!< in: query graph */
|
||||
fts_table_t* fts_table, /*!< in: the FTS aux index */
|
||||
fts_string_t* word, /*!< in: word in UTF-8 */
|
||||
fts_node_t* node) /*!< in: node columns */
|
||||
__attribute__((nonnull, warn_unused_result));
|
||||
/*******************************************************************//**
|
||||
Tokenize a document. */
|
||||
UNIV_INTERN
|
||||
void
|
||||
fts_tokenize_document(
|
||||
/*==================*/
|
||||
fts_doc_t* doc, /*!< in/out: document to
|
||||
tokenize */
|
||||
fts_doc_t* result) /*!< out: if provided, save
|
||||
result tokens here */
|
||||
__attribute__((nonnull(1)));
|
||||
|
||||
/*******************************************************************//**
|
||||
Continue to tokenize a document. */
|
||||
UNIV_INTERN
|
||||
void
|
||||
fts_tokenize_document_next(
|
||||
/*=======================*/
|
||||
fts_doc_t* doc, /*!< in/out: document to
|
||||
tokenize */
|
||||
ulint add_pos, /*!< in: add this position to all
|
||||
tokens from this tokenization */
|
||||
fts_doc_t* result) /*!< out: if provided, save
|
||||
result tokens here */
|
||||
__attribute__((nonnull(1)));
|
||||
/******************************************************************//**
|
||||
Initialize a document. */
|
||||
UNIV_INTERN
|
||||
void
|
||||
fts_doc_init(
|
||||
/*=========*/
|
||||
fts_doc_t* doc) /*!< in: doc to initialize */
|
||||
__attribute__((nonnull));
|
||||
|
||||
/******************************************************************//**
|
||||
Do a binary search for a doc id in the array
|
||||
@return +ve index if found -ve index where it should be
|
||||
inserted if not found */
|
||||
UNIV_INTERN
|
||||
int
|
||||
fts_bsearch(
|
||||
/*========*/
|
||||
fts_update_t* array, /*!< in: array to sort */
|
||||
int lower, /*!< in: lower bound of array*/
|
||||
int upper, /*!< in: upper bound of array*/
|
||||
doc_id_t doc_id) /*!< in: doc id to lookup */
|
||||
__attribute__((nonnull, warn_unused_result));
|
||||
/******************************************************************//**
|
||||
Free document. */
|
||||
UNIV_INTERN
|
||||
void
|
||||
fts_doc_free(
|
||||
/*=========*/
|
||||
fts_doc_t* doc) /*!< in: document */
|
||||
__attribute__((nonnull));
|
||||
/******************************************************************//**
|
||||
Free fts_optimizer_word_t instanace.*/
|
||||
UNIV_INTERN
|
||||
void
|
||||
fts_word_free(
|
||||
/*==========*/
|
||||
fts_word_t* word) /*!< in: instance to free.*/
|
||||
__attribute__((nonnull));
|
||||
/******************************************************************//**
|
||||
Read the rows from the FTS inde
|
||||
@return DB_SUCCESS or error code */
|
||||
UNIV_INTERN
|
||||
dberr_t
|
||||
fts_index_fetch_nodes(
|
||||
/*==================*/
|
||||
trx_t* trx, /*!< in: transaction */
|
||||
que_t** graph, /*!< in: prepared statement */
|
||||
fts_table_t* fts_table, /*!< in: FTS aux table */
|
||||
const fts_string_t*
|
||||
word, /*!< in: the word to fetch */
|
||||
fts_fetch_t* fetch) /*!< in: fetch callback.*/
|
||||
__attribute__((nonnull));
|
||||
/******************************************************************//**
|
||||
Create a fts_optimizer_word_t instance.
|
||||
@return new instance */
|
||||
UNIV_INTERN
|
||||
fts_word_t*
|
||||
fts_word_init(
|
||||
/*==========*/
|
||||
fts_word_t* word, /*!< in: word to initialize */
|
||||
byte* utf8, /*!< in: UTF-8 string */
|
||||
ulint len) /*!< in: length of string in bytes */
|
||||
__attribute__((nonnull));
|
||||
/******************************************************************//**
|
||||
Compare two fts_trx_table_t instances, we actually compare the
|
||||
table id's here.
|
||||
@return < 0 if n1 < n2, 0 if n1 == n2, > 0 if n1 > n2 */
|
||||
UNIV_INLINE
|
||||
int
|
||||
fts_trx_table_cmp(
|
||||
/*==============*/
|
||||
const void* v1, /*!< in: id1 */
|
||||
const void* v2) /*!< in: id2 */
|
||||
__attribute__((nonnull, warn_unused_result));
|
||||
/******************************************************************//**
|
||||
Compare a table id with a trx_table_t table id.
|
||||
@return < 0 if n1 < n2, 0 if n1 == n2, > 0 if n1 > n2 */
|
||||
UNIV_INLINE
|
||||
int
|
||||
fts_trx_table_id_cmp(
|
||||
/*=================*/
|
||||
const void* p1, /*!< in: id1 */
|
||||
const void* p2) /*!< in: id2 */
|
||||
__attribute__((nonnull, warn_unused_result));
|
||||
/******************************************************************//**
|
||||
Commit a transaction.
|
||||
@return DB_SUCCESS if all OK */
|
||||
UNIV_INTERN
|
||||
dberr_t
|
||||
fts_sql_commit(
|
||||
/*===========*/
|
||||
trx_t* trx) /*!< in: transaction */
|
||||
__attribute__((nonnull));
|
||||
/******************************************************************//**
|
||||
Rollback a transaction.
|
||||
@return DB_SUCCESS if all OK */
|
||||
UNIV_INTERN
|
||||
dberr_t
|
||||
fts_sql_rollback(
|
||||
/*=============*/
|
||||
trx_t* trx) /*!< in: transaction */
|
||||
__attribute__((nonnull));
|
||||
/******************************************************************//**
|
||||
Parse an SQL string. %s is replaced with the table's id. Don't acquire
|
||||
the dict mutex
|
||||
@return query graph */
|
||||
UNIV_INTERN
|
||||
que_t*
|
||||
fts_parse_sql_no_dict_lock(
|
||||
/*=======================*/
|
||||
fts_table_t* fts_table, /*!< in: table with FTS index */
|
||||
pars_info_t* info, /*!< in: parser info */
|
||||
const char* sql) /*!< in: SQL string to evaluate */
|
||||
__attribute__((nonnull(3), malloc, warn_unused_result));
|
||||
/******************************************************************//**
|
||||
Get value from config table. The caller must ensure that enough
|
||||
space is allocated for value to hold the column contents
|
||||
@return DB_SUCCESS or error code */
|
||||
UNIV_INTERN
|
||||
dberr_t
|
||||
fts_config_get_value(
|
||||
/*=================*/
|
||||
trx_t* trx, /* transaction */
|
||||
fts_table_t* fts_table, /*!< in: the indexed FTS table */
|
||||
const char* name, /*!< in: get config value for
|
||||
this parameter name */
|
||||
fts_string_t* value) /*!< out: value read from
|
||||
config table */
|
||||
__attribute__((nonnull));
|
||||
/******************************************************************//**
|
||||
Get value specific to an FTS index from the config table. The caller
|
||||
must ensure that enough space is allocated for value to hold the
|
||||
column contents.
|
||||
@return DB_SUCCESS or error code */
|
||||
UNIV_INTERN
|
||||
dberr_t
|
||||
fts_config_get_index_value(
|
||||
/*=======================*/
|
||||
trx_t* trx, /*!< transaction */
|
||||
dict_index_t* index, /*!< in: index */
|
||||
const char* param, /*!< in: get config value for
|
||||
this parameter name */
|
||||
fts_string_t* value) /*!< out: value read from
|
||||
config table */
|
||||
__attribute__((nonnull, warn_unused_result));
|
||||
/******************************************************************//**
|
||||
Set the value in the config table for name.
|
||||
@return DB_SUCCESS or error code */
|
||||
UNIV_INTERN
|
||||
dberr_t
|
||||
fts_config_set_value(
|
||||
/*=================*/
|
||||
trx_t* trx, /*!< transaction */
|
||||
fts_table_t* fts_table, /*!< in: the indexed FTS table */
|
||||
const char* name, /*!< in: get config value for
|
||||
this parameter name */
|
||||
const fts_string_t*
|
||||
value) /*!< in: value to update */
|
||||
__attribute__((nonnull));
|
||||
/****************************************************************//**
|
||||
Set an ulint value in the config table.
|
||||
@return DB_SUCCESS if all OK else error code */
|
||||
UNIV_INTERN
|
||||
dberr_t
|
||||
fts_config_set_ulint(
|
||||
/*=================*/
|
||||
trx_t* trx, /*!< in: transaction */
|
||||
fts_table_t* fts_table, /*!< in: the indexed FTS table */
|
||||
const char* name, /*!< in: param name */
|
||||
ulint int_value) /*!< in: value */
|
||||
__attribute__((nonnull, warn_unused_result));
|
||||
/******************************************************************//**
|
||||
Set the value specific to an FTS index in the config table.
|
||||
@return DB_SUCCESS or error code */
|
||||
UNIV_INTERN
|
||||
dberr_t
|
||||
fts_config_set_index_value(
|
||||
/*=======================*/
|
||||
trx_t* trx, /*!< transaction */
|
||||
dict_index_t* index, /*!< in: index */
|
||||
const char* param, /*!< in: get config value for
|
||||
this parameter name */
|
||||
fts_string_t* value) /*!< out: value read from
|
||||
config table */
|
||||
__attribute__((nonnull, warn_unused_result));
|
||||
/******************************************************************//**
|
||||
Increment the value in the config table for column name.
|
||||
@return DB_SUCCESS or error code */
|
||||
UNIV_INTERN
|
||||
dberr_t
|
||||
fts_config_increment_value(
|
||||
/*=======================*/
|
||||
trx_t* trx, /*!< transaction */
|
||||
fts_table_t* fts_table, /*!< in: the indexed FTS table */
|
||||
const char* name, /*!< in: increment config value
|
||||
for this parameter name */
|
||||
ulint delta) /*!< in: increment by this much */
|
||||
__attribute__((nonnull, warn_unused_result));
|
||||
/******************************************************************//**
|
||||
Increment the per index value in the config table for column name.
|
||||
@return DB_SUCCESS or error code */
|
||||
UNIV_INTERN
|
||||
dberr_t
|
||||
fts_config_increment_index_value(
|
||||
/*=============================*/
|
||||
trx_t* trx, /*!< transaction */
|
||||
dict_index_t* index, /*!< in: FTS index */
|
||||
const char* name, /*!< in: increment config value
|
||||
for this parameter name */
|
||||
ulint delta) /*!< in: increment by this much */
|
||||
__attribute__((nonnull));
|
||||
/******************************************************************//**
|
||||
Get an ulint value from the config table.
|
||||
@return DB_SUCCESS or error code */
|
||||
UNIV_INTERN
|
||||
dberr_t
|
||||
fts_config_get_index_ulint(
|
||||
/*=======================*/
|
||||
trx_t* trx, /*!< in: transaction */
|
||||
dict_index_t* index, /*!< in: FTS index */
|
||||
const char* name, /*!< in: param name */
|
||||
ulint* int_value) /*!< out: value */
|
||||
__attribute__((nonnull, warn_unused_result));
|
||||
/******************************************************************//**
|
||||
Set an ulint value int the config table.
|
||||
@return DB_SUCCESS or error code */
|
||||
UNIV_INTERN
|
||||
dberr_t
|
||||
fts_config_set_index_ulint(
|
||||
/*=======================*/
|
||||
trx_t* trx, /*!< in: transaction */
|
||||
dict_index_t* index, /*!< in: FTS index */
|
||||
const char* name, /*!< in: param name */
|
||||
ulint int_value) /*!< in: value */
|
||||
__attribute__((nonnull, warn_unused_result));
|
||||
/******************************************************************//**
|
||||
Get an ulint value from the config table.
|
||||
@return DB_SUCCESS or error code */
|
||||
UNIV_INTERN
|
||||
dberr_t
|
||||
fts_config_get_ulint(
|
||||
/*=================*/
|
||||
trx_t* trx, /*!< in: transaction */
|
||||
fts_table_t* fts_table, /*!< in: the indexed FTS table */
|
||||
const char* name, /*!< in: param name */
|
||||
ulint* int_value) /*!< out: value */
|
||||
__attribute__((nonnull));
|
||||
/******************************************************************//**
|
||||
Search cache for word.
|
||||
@return the word node vector if found else NULL */
|
||||
UNIV_INTERN
|
||||
const ib_vector_t*
|
||||
fts_cache_find_word(
|
||||
/*================*/
|
||||
const fts_index_cache_t*
|
||||
index_cache, /*!< in: cache to search */
|
||||
const fts_string_t*
|
||||
text) /*!< in: word to search for */
|
||||
__attribute__((nonnull, warn_unused_result));
|
||||
/******************************************************************//**
|
||||
Check cache for deleted doc id.
|
||||
@return TRUE if deleted */
|
||||
UNIV_INTERN
|
||||
ibool
|
||||
fts_cache_is_deleted_doc_id(
|
||||
/*========================*/
|
||||
const fts_cache_t*
|
||||
cache, /*!< in: cache ito search */
|
||||
doc_id_t doc_id) /*!< in: doc id to search for */
|
||||
__attribute__((nonnull, warn_unused_result));
|
||||
/******************************************************************//**
|
||||
Append deleted doc ids to vector and sort the vector. */
|
||||
UNIV_INTERN
|
||||
void
|
||||
fts_cache_append_deleted_doc_ids(
|
||||
/*=============================*/
|
||||
const fts_cache_t*
|
||||
cache, /*!< in: cache to use */
|
||||
ib_vector_t* vector); /*!< in: append to this vector */
|
||||
/******************************************************************//**
|
||||
Wait for the background thread to start. We poll to detect change
|
||||
of state, which is acceptable, since the wait should happen only
|
||||
once during startup.
|
||||
@return true if the thread started else FALSE (i.e timed out) */
|
||||
UNIV_INTERN
|
||||
ibool
|
||||
fts_wait_for_background_thread_to_start(
|
||||
/*====================================*/
|
||||
dict_table_t* table, /*!< in: table to which the thread
|
||||
is attached */
|
||||
ulint max_wait); /*!< in: time in microseconds, if set
|
||||
to 0 then it disables timeout
|
||||
checking */
|
||||
#ifdef FTS_DOC_STATS_DEBUG
|
||||
/******************************************************************//**
|
||||
Get the total number of words in the FTS for a particular FTS index.
|
||||
@return DB_SUCCESS or error code */
|
||||
UNIV_INTERN
|
||||
dberr_t
|
||||
fts_get_total_word_count(
|
||||
/*=====================*/
|
||||
trx_t* trx, /*!< in: transaction */
|
||||
dict_index_t* index, /*!< in: for this index */
|
||||
ulint* total) /*!< out: total words */
|
||||
__attribute__((nonnull, warn_unused_result));
|
||||
#endif
|
||||
/******************************************************************//**
|
||||
Search the index specific cache for a particular FTS index.
|
||||
@return the index specific cache else NULL */
|
||||
UNIV_INTERN
|
||||
fts_index_cache_t*
|
||||
fts_find_index_cache(
|
||||
/*================*/
|
||||
const fts_cache_t*
|
||||
cache, /*!< in: cache to search */
|
||||
const dict_index_t*
|
||||
index) /*!< in: index to search for */
|
||||
__attribute__((nonnull, warn_unused_result));
|
||||
/******************************************************************//**
|
||||
Write the table id to the given buffer (including final NUL). Buffer must be
|
||||
at least FTS_AUX_MIN_TABLE_ID_LENGTH bytes long.
|
||||
@return number of bytes written */
|
||||
UNIV_INLINE
|
||||
int
|
||||
fts_write_object_id(
|
||||
/*================*/
|
||||
ib_id_t id, /*!< in: a table/index id */
|
||||
char* str, /*!< in: buffer to write the id to */
|
||||
bool hex_format __attribute__((unused)))
|
||||
/*!< in: true for fixed hex format,
|
||||
false for old ambiguous format */
|
||||
__attribute__((nonnull));
|
||||
/******************************************************************//**
|
||||
Read the table id from the string generated by fts_write_object_id().
|
||||
@return TRUE if parse successful */
|
||||
UNIV_INLINE
|
||||
ibool
|
||||
fts_read_object_id(
|
||||
/*===============*/
|
||||
ib_id_t* id, /*!< out: a table id */
|
||||
const char* str) /*!< in: buffer to read from */
|
||||
__attribute__((nonnull, warn_unused_result));
|
||||
/******************************************************************//**
|
||||
Get the table id.
|
||||
@return number of bytes written */
|
||||
UNIV_INTERN
|
||||
int
|
||||
fts_get_table_id(
|
||||
/*=============*/
|
||||
const fts_table_t*
|
||||
fts_table, /*!< in: FTS Auxiliary table */
|
||||
char* table_id) /*!< out: table id, must be at least
|
||||
FTS_AUX_MIN_TABLE_ID_LENGTH bytes
|
||||
long */
|
||||
__attribute__((nonnull, warn_unused_result));
|
||||
/******************************************************************//**
|
||||
Add the table to add to the OPTIMIZER's list. */
|
||||
UNIV_INTERN
|
||||
void
|
||||
fts_optimize_add_table(
|
||||
/*===================*/
|
||||
dict_table_t* table) /*!< in: table to add */
|
||||
__attribute__((nonnull));
|
||||
/******************************************************************//**
|
||||
Optimize a table. */
|
||||
UNIV_INTERN
|
||||
void
|
||||
fts_optimize_do_table(
|
||||
/*==================*/
|
||||
dict_table_t* table) /*!< in: table to optimize */
|
||||
__attribute__((nonnull));
|
||||
/******************************************************************//**
|
||||
Construct the prefix name of an FTS table.
|
||||
@return own: table name, must be freed with mem_free() */
|
||||
UNIV_INTERN
|
||||
char*
|
||||
fts_get_table_name_prefix(
|
||||
/*======================*/
|
||||
const fts_table_t*
|
||||
fts_table) /*!< in: Auxiliary table type */
|
||||
__attribute__((nonnull, malloc, warn_unused_result));
|
||||
/******************************************************************//**
|
||||
Add node positions. */
|
||||
UNIV_INTERN
|
||||
void
|
||||
fts_cache_node_add_positions(
|
||||
/*=========================*/
|
||||
fts_cache_t* cache, /*!< in: cache */
|
||||
fts_node_t* node, /*!< in: word node */
|
||||
doc_id_t doc_id, /*!< in: doc id */
|
||||
ib_vector_t* positions) /*!< in: fts_token_t::positions */
|
||||
__attribute__((nonnull(2,4)));
|
||||
|
||||
/******************************************************************//**
|
||||
Create the config table name for retrieving index specific value.
|
||||
@return index config parameter name */
|
||||
UNIV_INTERN
|
||||
char*
|
||||
fts_config_create_index_param_name(
|
||||
/*===============================*/
|
||||
const char* param, /*!< in: base name of param */
|
||||
const dict_index_t* index) /*!< in: index for config */
|
||||
__attribute__((nonnull, malloc, warn_unused_result));
|
||||
|
||||
#ifndef UNIV_NONINL
|
||||
#include "fts0priv.ic"
|
||||
#endif
|
||||
|
||||
#endif /* INNOBASE_FTS0PRIV_H */
|
||||
130
storage/innobase/include/fts0priv.ic
Normal file
130
storage/innobase/include/fts0priv.ic
Normal file
|
|
@ -0,0 +1,130 @@
|
|||
/*****************************************************************************
|
||||
|
||||
Copyright (c) 2011, 2013, Oracle and/or its affiliates. All Rights Reserved.
|
||||
|
||||
This program is free software; you can redistribute it and/or modify it under
|
||||
the terms of the GNU General Public License as published by the Free Software
|
||||
Foundation; version 2 of the License.
|
||||
|
||||
This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
|
||||
FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License along with
|
||||
this program; if not, write to the Free Software Foundation, Inc.,
|
||||
51 Franklin Street, Suite 500, Boston, MA 02110-1335 USA
|
||||
|
||||
*****************************************************************************/
|
||||
|
||||
/******************************************************************//**
|
||||
@file include/fts0priv.ic
|
||||
Full text search internal header file
|
||||
|
||||
Created 2011/11/12 Sunny Bains
|
||||
***********************************************************************/
|
||||
|
||||
/******************************************************************//**
|
||||
Write the table id to the given buffer (including final NUL). Buffer must be
|
||||
at least FTS_AUX_MIN_TABLE_ID_LENGTH bytes long.
|
||||
@return number of bytes written */
|
||||
UNIV_INLINE
|
||||
int
|
||||
fts_write_object_id(
|
||||
/*================*/
|
||||
ib_id_t id, /* in: a table/index id */
|
||||
char* str, /* in: buffer to write the id to */
|
||||
bool hex_format __attribute__((unused)))
|
||||
/* in: true for fixed hex format,
|
||||
false for old ambiguous format */
|
||||
{
|
||||
|
||||
#ifdef _WIN32
|
||||
|
||||
DBUG_EXECUTE_IF("innodb_test_wrong_non_windows_fts_aux_table_name",
|
||||
return(sprintf(str, UINT64PFx, id)););
|
||||
|
||||
/* Use this to construct old(5.6.14 and 5.7.3) windows
|
||||
ambiguous aux table names */
|
||||
DBUG_EXECUTE_IF("innodb_test_wrong_fts_aux_table_name",
|
||||
return(sprintf(str, "%016llu", id)););
|
||||
|
||||
#else /* _WIN32 */
|
||||
|
||||
/* Use this to construct old(5.6.14 and 5.7.3) windows
|
||||
ambiguous aux table names */
|
||||
DBUG_EXECUTE_IF("innodb_test_wrong_windows_fts_aux_table_name",
|
||||
return(sprintf(str, "%016"PRIu64, id)););
|
||||
|
||||
DBUG_EXECUTE_IF("innodb_test_wrong_fts_aux_table_name",
|
||||
return(sprintf(str, UINT64PFx, id)););
|
||||
|
||||
#endif /* _WIN32 */
|
||||
|
||||
/* As above, but this is only for those tables failing to rename. */
|
||||
if (!hex_format) {
|
||||
#ifdef _WIN32
|
||||
// FIXME: Use ut_snprintf(), so does following one.
|
||||
return(sprintf(str, "%016llu", id));
|
||||
#else /* _WIN32 */
|
||||
return(sprintf(str, "%016"PRIu64, id));
|
||||
#endif /* _WIN32 */
|
||||
}
|
||||
|
||||
return(sprintf(str, UINT64PFx, id));
|
||||
}
|
||||
|
||||
/******************************************************************//**
|
||||
Read the table id from the string generated by fts_write_object_id().
|
||||
@return TRUE if parse successful */
|
||||
UNIV_INLINE
|
||||
ibool
|
||||
fts_read_object_id(
|
||||
/*===============*/
|
||||
ib_id_t* id, /* out: an id */
|
||||
const char* str) /* in: buffer to read from */
|
||||
{
|
||||
/* NOTE: this func doesn't care about whether current table
|
||||
is set with HEX_NAME, the user of the id read here will check
|
||||
if the id is HEX or DEC and do the right thing with it. */
|
||||
return(sscanf(str, UINT64PFx, id) == 1);
|
||||
}
|
||||
|
||||
/******************************************************************//**
|
||||
Compare two fts_trx_table_t instances.
|
||||
@return < 0 if n1 < n2, 0 if n1 == n2, > 0 if n1 > n2 */
|
||||
UNIV_INLINE
|
||||
int
|
||||
fts_trx_table_cmp(
|
||||
/*==============*/
|
||||
const void* p1, /*!< in: id1 */
|
||||
const void* p2) /*!< in: id2 */
|
||||
{
|
||||
const dict_table_t* table1 = (*(const fts_trx_table_t**) p1)->table;
|
||||
const dict_table_t* table2 = (*(const fts_trx_table_t**) p2)->table;
|
||||
|
||||
return((table1->id > table2->id)
|
||||
? 1
|
||||
: (table1->id == table2->id)
|
||||
? 0
|
||||
: -1);
|
||||
}
|
||||
|
||||
/******************************************************************//**
|
||||
Compare a table id with a fts_trx_table_t table id.
|
||||
@return < 0 if n1 < n2, 0 if n1 == n2,> 0 if n1 > n2 */
|
||||
UNIV_INLINE
|
||||
int
|
||||
fts_trx_table_id_cmp(
|
||||
/*=================*/
|
||||
const void* p1, /*!< in: id1 */
|
||||
const void* p2) /*!< in: id2 */
|
||||
{
|
||||
const ullint* table_id = (const ullint*) p1;
|
||||
const dict_table_t* table2 = (*(const fts_trx_table_t**) p2)->table;
|
||||
|
||||
return((*table_id > table2->id)
|
||||
? 1
|
||||
: (*table_id == table2->id)
|
||||
? 0
|
||||
: -1);
|
||||
}
|
||||
349
storage/innobase/include/fts0tlex.h
Normal file
349
storage/innobase/include/fts0tlex.h
Normal file
|
|
@ -0,0 +1,349 @@
|
|||
#ifndef fts0tHEADER_H
|
||||
#define fts0tHEADER_H 1
|
||||
#define fts0tIN_HEADER 1
|
||||
|
||||
#line 6 "../include/fts0tlex.h"
|
||||
|
||||
#line 8 "../include/fts0tlex.h"
|
||||
|
||||
#define YY_INT_ALIGNED short int
|
||||
|
||||
/* A lexical scanner generated by flex */
|
||||
|
||||
#define FLEX_SCANNER
|
||||
#define YY_FLEX_MAJOR_VERSION 2
|
||||
#define YY_FLEX_MINOR_VERSION 5
|
||||
#define YY_FLEX_SUBMINOR_VERSION 35
|
||||
#if YY_FLEX_SUBMINOR_VERSION > 0
|
||||
#define FLEX_BETA
|
||||
#endif
|
||||
|
||||
/* First, we deal with platform-specific or compiler-specific issues. */
|
||||
|
||||
/* begin standard C headers. */
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <errno.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
/* end standard C headers. */
|
||||
|
||||
/* flex integer type definitions */
|
||||
|
||||
#ifndef FLEXINT_H
|
||||
#define FLEXINT_H
|
||||
|
||||
/* C99 systems have <inttypes.h>. Non-C99 systems may or may not. */
|
||||
|
||||
#if defined (__STDC_VERSION__) && __STDC_VERSION__ >= 199901L
|
||||
|
||||
/* C99 says to define __STDC_LIMIT_MACROS before including stdint.h,
|
||||
* if you want the limit (max/min) macros for int types.
|
||||
*/
|
||||
#ifndef __STDC_LIMIT_MACROS
|
||||
#define __STDC_LIMIT_MACROS 1
|
||||
#endif
|
||||
|
||||
#include <inttypes.h>
|
||||
typedef int8_t flex_int8_t;
|
||||
typedef uint8_t flex_uint8_t;
|
||||
typedef int16_t flex_int16_t;
|
||||
typedef uint16_t flex_uint16_t;
|
||||
typedef int32_t flex_int32_t;
|
||||
typedef uint32_t flex_uint32_t;
|
||||
#else
|
||||
typedef signed char flex_int8_t;
|
||||
typedef short int flex_int16_t;
|
||||
typedef int flex_int32_t;
|
||||
typedef unsigned char flex_uint8_t;
|
||||
typedef unsigned short int flex_uint16_t;
|
||||
typedef unsigned int flex_uint32_t;
|
||||
|
||||
/* Limits of integral types. */
|
||||
#ifndef INT8_MIN
|
||||
#define INT8_MIN (-128)
|
||||
#endif
|
||||
#ifndef INT16_MIN
|
||||
#define INT16_MIN (-32767-1)
|
||||
#endif
|
||||
#ifndef INT32_MIN
|
||||
#define INT32_MIN (-2147483647-1)
|
||||
#endif
|
||||
#ifndef INT8_MAX
|
||||
#define INT8_MAX (127)
|
||||
#endif
|
||||
#ifndef INT16_MAX
|
||||
#define INT16_MAX (32767)
|
||||
#endif
|
||||
#ifndef INT32_MAX
|
||||
#define INT32_MAX (2147483647)
|
||||
#endif
|
||||
#ifndef UINT8_MAX
|
||||
#define UINT8_MAX (255U)
|
||||
#endif
|
||||
#ifndef UINT16_MAX
|
||||
#define UINT16_MAX (65535U)
|
||||
#endif
|
||||
#ifndef UINT32_MAX
|
||||
#define UINT32_MAX (4294967295U)
|
||||
#endif
|
||||
|
||||
#endif /* ! C99 */
|
||||
|
||||
#endif /* ! FLEXINT_H */
|
||||
|
||||
#ifdef __cplusplus
|
||||
|
||||
/* The "const" storage-class-modifier is valid. */
|
||||
#define YY_USE_CONST
|
||||
|
||||
#else /* ! __cplusplus */
|
||||
|
||||
/* C99 requires __STDC__ to be defined as 1. */
|
||||
#if defined (__STDC__)
|
||||
|
||||
#define YY_USE_CONST
|
||||
|
||||
#endif /* defined (__STDC__) */
|
||||
#endif /* ! __cplusplus */
|
||||
|
||||
#ifdef YY_USE_CONST
|
||||
#define yyconst const
|
||||
#else
|
||||
#define yyconst
|
||||
#endif
|
||||
|
||||
/* An opaque pointer. */
|
||||
#ifndef YY_TYPEDEF_YY_SCANNER_T
|
||||
#define YY_TYPEDEF_YY_SCANNER_T
|
||||
typedef void* yyscan_t;
|
||||
#endif
|
||||
|
||||
/* For convenience, these vars (plus the bison vars far below)
|
||||
are macros in the reentrant scanner. */
|
||||
#define yyin yyg->yyin_r
|
||||
#define yyout yyg->yyout_r
|
||||
#define yyextra yyg->yyextra_r
|
||||
#define yyleng yyg->yyleng_r
|
||||
#define yytext yyg->yytext_r
|
||||
#define yylineno (YY_CURRENT_BUFFER_LVALUE->yy_bs_lineno)
|
||||
#define yycolumn (YY_CURRENT_BUFFER_LVALUE->yy_bs_column)
|
||||
#define yy_flex_debug yyg->yy_flex_debug_r
|
||||
|
||||
/* Size of default input buffer. */
|
||||
#ifndef YY_BUF_SIZE
|
||||
#ifdef __ia64__
|
||||
/* On IA-64, the buffer size is 16k, not 8k.
|
||||
* Moreover, YY_BUF_SIZE is 2*YY_READ_BUF_SIZE in the general case.
|
||||
* Ditto for the __ia64__ case accordingly.
|
||||
*/
|
||||
#define YY_BUF_SIZE 32768
|
||||
#else
|
||||
#define YY_BUF_SIZE 16384
|
||||
#endif /* __ia64__ */
|
||||
#endif
|
||||
|
||||
#ifndef YY_TYPEDEF_YY_BUFFER_STATE
|
||||
#define YY_TYPEDEF_YY_BUFFER_STATE
|
||||
typedef struct yy_buffer_state *YY_BUFFER_STATE;
|
||||
#endif
|
||||
|
||||
#ifndef YY_TYPEDEF_YY_SIZE_T
|
||||
#define YY_TYPEDEF_YY_SIZE_T
|
||||
typedef size_t yy_size_t;
|
||||
#endif
|
||||
|
||||
#ifndef YY_STRUCT_YY_BUFFER_STATE
|
||||
#define YY_STRUCT_YY_BUFFER_STATE
|
||||
struct yy_buffer_state
|
||||
{
|
||||
FILE *yy_input_file;
|
||||
|
||||
char *yy_ch_buf; /* input buffer */
|
||||
char *yy_buf_pos; /* current position in input buffer */
|
||||
|
||||
/* Size of input buffer in bytes, not including room for EOB
|
||||
* characters.
|
||||
*/
|
||||
yy_size_t yy_buf_size;
|
||||
|
||||
/* Number of characters read into yy_ch_buf, not including EOB
|
||||
* characters.
|
||||
*/
|
||||
int yy_n_chars;
|
||||
|
||||
/* Whether we "own" the buffer - i.e., we know we created it,
|
||||
* and can realloc() it to grow it, and should free() it to
|
||||
* delete it.
|
||||
*/
|
||||
int yy_is_our_buffer;
|
||||
|
||||
/* Whether this is an "interactive" input source; if so, and
|
||||
* if we're using stdio for input, then we want to use getc()
|
||||
* instead of fread(), to make sure we stop fetching input after
|
||||
* each newline.
|
||||
*/
|
||||
int yy_is_interactive;
|
||||
|
||||
/* Whether we're considered to be at the beginning of a line.
|
||||
* If so, '^' rules will be active on the next match, otherwise
|
||||
* not.
|
||||
*/
|
||||
int yy_at_bol;
|
||||
|
||||
int yy_bs_lineno; /**< The line count. */
|
||||
int yy_bs_column; /**< The column count. */
|
||||
|
||||
/* Whether to try to fill the input buffer when we reach the
|
||||
* end of it.
|
||||
*/
|
||||
int yy_fill_buffer;
|
||||
|
||||
int yy_buffer_status;
|
||||
|
||||
};
|
||||
#endif /* !YY_STRUCT_YY_BUFFER_STATE */
|
||||
|
||||
void fts0trestart (FILE *input_file ,yyscan_t yyscanner );
|
||||
void fts0t_switch_to_buffer (YY_BUFFER_STATE new_buffer ,yyscan_t yyscanner );
|
||||
YY_BUFFER_STATE fts0t_create_buffer (FILE *file,int size ,yyscan_t yyscanner );
|
||||
void fts0t_delete_buffer (YY_BUFFER_STATE b ,yyscan_t yyscanner );
|
||||
void fts0t_flush_buffer (YY_BUFFER_STATE b ,yyscan_t yyscanner );
|
||||
void fts0tpush_buffer_state (YY_BUFFER_STATE new_buffer ,yyscan_t yyscanner );
|
||||
void fts0tpop_buffer_state (yyscan_t yyscanner );
|
||||
|
||||
YY_BUFFER_STATE fts0t_scan_buffer (char *base,yy_size_t size ,yyscan_t yyscanner );
|
||||
YY_BUFFER_STATE fts0t_scan_string (yyconst char *yy_str ,yyscan_t yyscanner );
|
||||
YY_BUFFER_STATE fts0t_scan_bytes (yyconst char *bytes,int len ,yyscan_t yyscanner );
|
||||
|
||||
void *fts0talloc (yy_size_t ,yyscan_t yyscanner );
|
||||
void *fts0trealloc (void *,yy_size_t ,yyscan_t yyscanner );
|
||||
void fts0tfree (void * ,yyscan_t yyscanner );
|
||||
|
||||
/* Begin user sect3 */
|
||||
|
||||
#define fts0twrap(n) 1
|
||||
#define YY_SKIP_YYWRAP
|
||||
|
||||
#define yytext_ptr yytext_r
|
||||
|
||||
#ifdef YY_HEADER_EXPORT_START_CONDITIONS
|
||||
#define INITIAL 0
|
||||
|
||||
#endif
|
||||
|
||||
#ifndef YY_NO_UNISTD_H
|
||||
/* Special case for "unistd.h", since it is non-ANSI. We include it way
|
||||
* down here because we want the user's section 1 to have been scanned first.
|
||||
* The user has a chance to override it with an option.
|
||||
*/
|
||||
#include <unistd.h>
|
||||
#endif
|
||||
|
||||
#ifndef YY_EXTRA_TYPE
|
||||
#define YY_EXTRA_TYPE void *
|
||||
#endif
|
||||
|
||||
int fts0tlex_init (yyscan_t* scanner);
|
||||
|
||||
int fts0tlex_init_extra (YY_EXTRA_TYPE user_defined,yyscan_t* scanner);
|
||||
|
||||
/* Accessor methods to globals.
|
||||
These are made visible to non-reentrant scanners for convenience. */
|
||||
|
||||
int fts0tlex_destroy (yyscan_t yyscanner );
|
||||
|
||||
int fts0tget_debug (yyscan_t yyscanner );
|
||||
|
||||
void fts0tset_debug (int debug_flag ,yyscan_t yyscanner );
|
||||
|
||||
YY_EXTRA_TYPE fts0tget_extra (yyscan_t yyscanner );
|
||||
|
||||
void fts0tset_extra (YY_EXTRA_TYPE user_defined ,yyscan_t yyscanner );
|
||||
|
||||
FILE *fts0tget_in (yyscan_t yyscanner );
|
||||
|
||||
void fts0tset_in (FILE * in_str ,yyscan_t yyscanner );
|
||||
|
||||
FILE *fts0tget_out (yyscan_t yyscanner );
|
||||
|
||||
void fts0tset_out (FILE * out_str ,yyscan_t yyscanner );
|
||||
|
||||
int fts0tget_leng (yyscan_t yyscanner );
|
||||
|
||||
char *fts0tget_text (yyscan_t yyscanner );
|
||||
|
||||
int fts0tget_lineno (yyscan_t yyscanner );
|
||||
|
||||
void fts0tset_lineno (int line_number ,yyscan_t yyscanner );
|
||||
|
||||
/* Macros after this point can all be overridden by user definitions in
|
||||
* section 1.
|
||||
*/
|
||||
|
||||
#ifndef YY_SKIP_YYWRAP
|
||||
#ifdef __cplusplus
|
||||
extern "C" int fts0twrap (yyscan_t yyscanner );
|
||||
#else
|
||||
extern int fts0twrap (yyscan_t yyscanner );
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifndef yytext_ptr
|
||||
static void yy_flex_strncpy (char *,yyconst char *,int ,yyscan_t yyscanner);
|
||||
#endif
|
||||
|
||||
#ifdef YY_NEED_STRLEN
|
||||
static int yy_flex_strlen (yyconst char * ,yyscan_t yyscanner);
|
||||
#endif
|
||||
|
||||
#ifndef YY_NO_INPUT
|
||||
|
||||
#endif
|
||||
|
||||
/* Amount of stuff to slurp up with each read. */
|
||||
#ifndef YY_READ_BUF_SIZE
|
||||
#ifdef __ia64__
|
||||
/* On IA-64, the buffer size is 16k, not 8k */
|
||||
#define YY_READ_BUF_SIZE 16384
|
||||
#else
|
||||
#define YY_READ_BUF_SIZE 8192
|
||||
#endif /* __ia64__ */
|
||||
#endif
|
||||
|
||||
/* Number of entries by which start-condition stack grows. */
|
||||
#ifndef YY_START_STACK_INCR
|
||||
#define YY_START_STACK_INCR 25
|
||||
#endif
|
||||
|
||||
/* Default declaration of generated scanner - a define so the user can
|
||||
* easily add parameters.
|
||||
*/
|
||||
#ifndef YY_DECL
|
||||
#define YY_DECL_IS_OURS 1
|
||||
|
||||
extern int fts0tlex (yyscan_t yyscanner);
|
||||
|
||||
#define YY_DECL int fts0tlex (yyscan_t yyscanner)
|
||||
#endif /* !YY_DECL */
|
||||
|
||||
/* yy_get_previous_state - get the state just before the EOB char was reached */
|
||||
|
||||
#undef YY_NEW_FILE
|
||||
#undef YY_FLUSH_BUFFER
|
||||
#undef yy_set_bol
|
||||
#undef yy_new_buffer
|
||||
#undef yy_set_interactive
|
||||
#undef YY_DO_BEFORE_ACTION
|
||||
|
||||
#ifdef YY_DECL_IS_OURS
|
||||
#undef YY_DECL_IS_OURS
|
||||
#undef YY_DECL
|
||||
#endif
|
||||
|
||||
#line 68 "fts0tlex.l"
|
||||
|
||||
|
||||
#line 348 "../include/fts0tlex.h"
|
||||
#undef fts0tIN_HEADER
|
||||
#endif /* fts0tHEADER_H */
|
||||
474
storage/innobase/include/fts0types.h
Normal file
474
storage/innobase/include/fts0types.h
Normal file
|
|
@ -0,0 +1,474 @@
|
|||
/*****************************************************************************
|
||||
|
||||
Copyright (c) 2007, 2011, Oracle and/or its affiliates. All Rights Reserved.
|
||||
|
||||
This program is free software; you can redistribute it and/or modify it under
|
||||
the terms of the GNU General Public License as published by the Free Software
|
||||
Foundation; version 2 of the License.
|
||||
|
||||
This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
|
||||
FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License along with
|
||||
this program; if not, write to the Free Software Foundation, Inc.,
|
||||
51 Franklin Street, Suite 500, Boston, MA 02110-1335 USA
|
||||
|
||||
*****************************************************************************/
|
||||
|
||||
/******************************************************************//**
|
||||
@file include/fts0types.h
|
||||
Full text search types file
|
||||
|
||||
Created 2007-03-27 Sunny Bains
|
||||
*******************************************************/
|
||||
|
||||
#ifndef INNOBASE_FTS0TYPES_H
|
||||
#define INNOBASE_FTS0TYPES_H
|
||||
|
||||
#include "que0types.h"
|
||||
#include "ut0byte.h"
|
||||
#include "fut0fut.h"
|
||||
#include "ut0rbt.h"
|
||||
#include "fts0fts.h"
|
||||
|
||||
/** Types used within FTS. */
|
||||
struct fts_que_t;
|
||||
struct fts_node_t;
|
||||
struct fts_utf8_str_t;
|
||||
|
||||
/** Callbacks used within FTS. */
|
||||
typedef pars_user_func_cb_t fts_sql_callback;
|
||||
typedef void (*fts_filter)(void*, fts_node_t*, void*, ulint len);
|
||||
|
||||
/** Statistics relevant to a particular document, used during retrieval. */
|
||||
struct fts_doc_stats_t {
|
||||
doc_id_t doc_id; /*!< Document id */
|
||||
ulint word_count; /*!< Total words in the document */
|
||||
};
|
||||
|
||||
/** It's main purpose is to store the SQL prepared statements that
|
||||
are required to retrieve a document from the database. */
|
||||
struct fts_get_doc_t {
|
||||
fts_index_cache_t*
|
||||
index_cache; /*!< The index cache instance */
|
||||
|
||||
/*!< Parsed sql statement */
|
||||
que_t* get_document_graph;
|
||||
fts_cache_t* cache; /*!< The parent cache */
|
||||
};
|
||||
|
||||
/** Since we can have multiple FTS indexes on a table, we keep a
|
||||
per index cache of words etc. */
|
||||
struct fts_index_cache_t {
|
||||
dict_index_t* index; /*!< The FTS index instance */
|
||||
|
||||
ib_rbt_t* words; /*!< Nodes; indexed by fts_string_t*,
|
||||
cells are fts_tokenizer_word_t*.*/
|
||||
|
||||
ib_vector_t* doc_stats; /*!< Array of the fts_doc_stats_t
|
||||
contained in the memory buffer.
|
||||
Must be in sorted order (ascending).
|
||||
The ideal choice is an rb tree but
|
||||
the rb tree imposes a space overhead
|
||||
that we can do without */
|
||||
|
||||
que_t** ins_graph; /*!< Insert query graphs */
|
||||
|
||||
que_t** sel_graph; /*!< Select query graphs */
|
||||
CHARSET_INFO* charset; /*!< charset */
|
||||
};
|
||||
|
||||
/** For supporting the tracking of updates on multiple FTS indexes we need
|
||||
to track which FTS indexes need to be updated. For INSERT and DELETE we
|
||||
update all fts indexes. */
|
||||
struct fts_update_t {
|
||||
doc_id_t doc_id; /*!< The doc id affected */
|
||||
|
||||
ib_vector_t* fts_indexes; /*!< The FTS indexes that need to be
|
||||
updated. A NULL value means all
|
||||
indexes need to be updated. This
|
||||
vector is not allocated on the heap
|
||||
and so must be freed explicitly,
|
||||
when we are done with it */
|
||||
};
|
||||
|
||||
/** Stop word control infotmation. */
|
||||
struct fts_stopword_t {
|
||||
ulint status; /*!< Status of the stopword tree */
|
||||
ib_alloc_t* heap; /*!< The memory allocator to use */
|
||||
ib_rbt_t* cached_stopword;/*!< This stores all active stopwords */
|
||||
CHARSET_INFO* charset; /*!< charset for stopword */
|
||||
};
|
||||
|
||||
/** The SYNC state of the cache. There is one instance of this struct
|
||||
associated with each ADD thread. */
|
||||
struct fts_sync_t {
|
||||
trx_t* trx; /*!< The transaction used for SYNCing
|
||||
the cache to disk */
|
||||
dict_table_t* table; /*!< Table with FTS index(es) */
|
||||
ulint max_cache_size; /*!< Max size in bytes of the cache */
|
||||
ibool cache_full; /*!< flag, when true it indicates that
|
||||
we need to sync the cache to disk */
|
||||
ulint lower_index; /*!< the start index of the doc id
|
||||
vector from where to start adding
|
||||
documents to the FTS cache */
|
||||
ulint upper_index; /*!< max index of the doc id vector to
|
||||
add to the FTS cache */
|
||||
ibool interrupted; /*!< TRUE if SYNC was interrupted */
|
||||
doc_id_t min_doc_id; /*!< The smallest doc id added to the
|
||||
cache. It should equal to
|
||||
doc_ids[lower_index] */
|
||||
doc_id_t max_doc_id; /*!< The doc id at which the cache was
|
||||
noted as being full, we use this to
|
||||
set the upper_limit field */
|
||||
ib_time_t start_time; /*!< SYNC start time */
|
||||
};
|
||||
|
||||
/** The cache for the FTS system. It is a memory-based inverted index
|
||||
that new entries are added to, until it grows over the configured maximum
|
||||
size, at which time its contents are written to the INDEX table. */
|
||||
struct fts_cache_t {
|
||||
rw_lock_t lock; /*!< lock protecting all access to the
|
||||
memory buffer. FIXME: this needs to
|
||||
be our new upgrade-capable rw-lock */
|
||||
|
||||
rw_lock_t init_lock; /*!< lock used for the cache
|
||||
intialization, it has different
|
||||
SYNC level as above cache lock */
|
||||
|
||||
ib_mutex_t optimize_lock; /*!< Lock for OPTIMIZE */
|
||||
|
||||
ib_mutex_t deleted_lock; /*!< Lock covering deleted_doc_ids */
|
||||
|
||||
ib_mutex_t doc_id_lock; /*!< Lock covering Doc ID */
|
||||
|
||||
ib_vector_t* deleted_doc_ids;/*!< Array of deleted doc ids, each
|
||||
element is of type fts_update_t */
|
||||
|
||||
ib_vector_t* indexes; /*!< We store the stats and inverted
|
||||
index for the individual FTS indexes
|
||||
in this vector. Each element is
|
||||
an instance of fts_index_cache_t */
|
||||
|
||||
ib_vector_t* get_docs; /*!< information required to read
|
||||
the document from the table. Each
|
||||
element is of type fts_doc_t */
|
||||
|
||||
ulint total_size; /*!< total size consumed by the ilist
|
||||
field of all nodes. SYNC is run
|
||||
whenever this gets too big */
|
||||
fts_sync_t* sync; /*!< sync structure to sync data to
|
||||
disk */
|
||||
ib_alloc_t* sync_heap; /*!< The heap allocator, for indexes
|
||||
and deleted_doc_ids, ie. transient
|
||||
objects, they are recreated after
|
||||
a SYNC is completed */
|
||||
|
||||
|
||||
ib_alloc_t* self_heap; /*!< This heap is the heap out of
|
||||
which an instance of the cache itself
|
||||
was created. Objects created using
|
||||
this heap will last for the lifetime
|
||||
of the cache */
|
||||
|
||||
doc_id_t next_doc_id; /*!< Next doc id */
|
||||
|
||||
doc_id_t synced_doc_id; /*!< Doc ID sync-ed to CONFIG table */
|
||||
|
||||
doc_id_t first_doc_id; /*!< first doc id since this table
|
||||
was opened */
|
||||
|
||||
ulint deleted; /*!< Number of doc ids deleted since
|
||||
last optimized. This variable is
|
||||
covered by deleted_lock */
|
||||
|
||||
ulint added; /*!< Number of doc ids added since last
|
||||
optimized. This variable is covered by
|
||||
the deleted lock */
|
||||
|
||||
fts_stopword_t stopword_info; /*!< Cached stopwords for the FTS */
|
||||
mem_heap_t* cache_heap; /*!< Cache Heap */
|
||||
};
|
||||
|
||||
/** Columns of the FTS auxiliary INDEX table */
|
||||
struct fts_node_t {
|
||||
doc_id_t first_doc_id; /*!< First document id in ilist. */
|
||||
|
||||
doc_id_t last_doc_id; /*!< Last document id in ilist. */
|
||||
|
||||
byte* ilist; /*!< Binary list of documents & word
|
||||
positions the token appears in.
|
||||
TODO: For now, these are simply
|
||||
ut_malloc'd, but if testing shows
|
||||
that they waste memory unacceptably, a
|
||||
special memory allocator will have
|
||||
to be written */
|
||||
|
||||
ulint doc_count; /*!< Number of doc ids in ilist */
|
||||
|
||||
ulint ilist_size; /*!< Used size of ilist in bytes. */
|
||||
|
||||
ulint ilist_size_alloc;
|
||||
/*!< Allocated size of ilist in
|
||||
bytes */
|
||||
};
|
||||
|
||||
/** A tokenizer word. Contains information about one word. */
|
||||
struct fts_tokenizer_word_t {
|
||||
fts_string_t text; /*!< Token text. */
|
||||
|
||||
ib_vector_t* nodes; /*!< Word node ilists, each element is
|
||||
of type fts_node_t */
|
||||
};
|
||||
|
||||
/** Word text plus it's array of nodes as on disk in FTS index */
|
||||
struct fts_word_t {
|
||||
fts_string_t text; /*!< Word value in UTF-8 */
|
||||
ib_vector_t* nodes; /*!< Nodes read from disk */
|
||||
|
||||
ib_alloc_t* heap_alloc; /*!< For handling all allocations */
|
||||
};
|
||||
|
||||
/** Callback for reading and filtering nodes that are read from FTS index */
|
||||
struct fts_fetch_t {
|
||||
void* read_arg; /*!< Arg for the sql_callback */
|
||||
|
||||
fts_sql_callback
|
||||
read_record; /*!< Callback for reading index
|
||||
record */
|
||||
ulint total_memory; /*!< Total memory used */
|
||||
};
|
||||
|
||||
/** For horizontally splitting an FTS auxiliary index */
|
||||
struct fts_index_selector_t {
|
||||
ulint value; /*!< Character value at which
|
||||
to split */
|
||||
|
||||
const char* suffix; /*!< FTS aux index suffix */
|
||||
};
|
||||
|
||||
/** This type represents a single document. */
|
||||
struct fts_doc_t {
|
||||
fts_string_t text; /*!< document text */
|
||||
|
||||
ibool found; /*!< TRUE if the document was found
|
||||
successfully in the database */
|
||||
|
||||
ib_rbt_t* tokens; /*!< This is filled when the document
|
||||
is tokenized. Tokens; indexed by
|
||||
fts_string_t*, cells are of type
|
||||
fts_token_t* */
|
||||
|
||||
ib_alloc_t* self_heap; /*!< An instance of this type is
|
||||
allocated from this heap along
|
||||
with any objects that have the
|
||||
same lifespan, most notably
|
||||
the vector of token positions */
|
||||
CHARSET_INFO* charset; /*!< Document's charset info */
|
||||
};
|
||||
|
||||
/** A token and its positions within a document. */
|
||||
struct fts_token_t {
|
||||
fts_string_t text; /*!< token text */
|
||||
|
||||
ib_vector_t* positions; /*!< an array of the positions the
|
||||
token is found in; each item is
|
||||
actually an ulint. */
|
||||
};
|
||||
|
||||
/** It's defined in fts/fts0fts.c */
|
||||
extern const fts_index_selector_t fts_index_selector[];
|
||||
|
||||
/******************************************************************//**
|
||||
Compare two UTF-8 strings. */
|
||||
UNIV_INLINE
|
||||
int
|
||||
fts_utf8_string_cmp(
|
||||
/*================*/
|
||||
/*!< out:
|
||||
< 0 if n1 < n2,
|
||||
0 if n1 == n2,
|
||||
> 0 if n1 > n2 */
|
||||
const void* p1, /*!< in: key */
|
||||
const void* p2); /*!< in: node */
|
||||
|
||||
/******************************************************************//**
|
||||
Compare two UTF-8 strings, and return match (0) if
|
||||
passed in "key" value equals or is the prefix of the "node" value. */
|
||||
UNIV_INLINE
|
||||
int
|
||||
fts_utf8_string_cmp_prefix(
|
||||
/*=======================*/
|
||||
/*!< out:
|
||||
< 0 if n1 < n2,
|
||||
0 if n1 == n2,
|
||||
> 0 if n1 > n2 */
|
||||
const void* p1, /*!< in: key */
|
||||
const void* p2); /*!< in: node */
|
||||
|
||||
/******************************************************************//**
|
||||
Compare two fts_trx_row_t instances doc_ids. */
|
||||
UNIV_INLINE
|
||||
int
|
||||
fts_trx_row_doc_id_cmp(
|
||||
/*===================*/
|
||||
/*!< out:
|
||||
< 0 if n1 < n2,
|
||||
0 if n1 == n2,
|
||||
> 0 if n1 > n2 */
|
||||
const void* p1, /*!< in: id1 */
|
||||
const void* p2); /*!< in: id2 */
|
||||
|
||||
/******************************************************************//**
|
||||
Compare two fts_ranking_t instances doc_ids. */
|
||||
UNIV_INLINE
|
||||
int
|
||||
fts_ranking_doc_id_cmp(
|
||||
/*===================*/
|
||||
/*!< out:
|
||||
< 0 if n1 < n2,
|
||||
0 if n1 == n2,
|
||||
> 0 if n1 > n2 */
|
||||
const void* p1, /*!< in: id1 */
|
||||
const void* p2); /*!< in: id2 */
|
||||
|
||||
/******************************************************************//**
|
||||
Compare two fts_update_t instances doc_ids. */
|
||||
UNIV_INLINE
|
||||
int
|
||||
fts_update_doc_id_cmp(
|
||||
/*==================*/
|
||||
/*!< out:
|
||||
< 0 if n1 < n2,
|
||||
0 if n1 == n2,
|
||||
> 0 if n1 > n2 */
|
||||
const void* p1, /*!< in: id1 */
|
||||
const void* p2); /*!< in: id2 */
|
||||
|
||||
/******************************************************************//**
|
||||
Decode and return the integer that was encoded using our VLC scheme.*/
|
||||
UNIV_INLINE
|
||||
ulint
|
||||
fts_decode_vlc(
|
||||
/*===========*/
|
||||
/*!< out: value decoded */
|
||||
byte** ptr); /*!< in: ptr to decode from, this ptr is
|
||||
incremented by the number of bytes decoded */
|
||||
|
||||
/******************************************************************//**
|
||||
Duplicate an UTF-8 string. */
|
||||
UNIV_INLINE
|
||||
void
|
||||
fts_utf8_string_dup(
|
||||
/*================*/
|
||||
/*!< out:
|
||||
< 0 if n1 < n2,
|
||||
0 if n1 == n2,
|
||||
> 0 if n1 > n2 */
|
||||
fts_string_t* dst, /*!< in: dup to here */
|
||||
const fts_string_t* src, /*!< in: src string */
|
||||
mem_heap_t* heap); /*!< in: heap to use */
|
||||
|
||||
/******************************************************************//**
|
||||
Return length of val if it were encoded using our VLC scheme. */
|
||||
UNIV_INLINE
|
||||
ulint
|
||||
fts_get_encoded_len(
|
||||
/*================*/
|
||||
/*!< out: length of value
|
||||
encoded, in bytes */
|
||||
ulint val); /*!< in: value to encode */
|
||||
|
||||
/******************************************************************//**
|
||||
Encode an integer using our VLC scheme and return the length in bytes. */
|
||||
UNIV_INLINE
|
||||
ulint
|
||||
fts_encode_int(
|
||||
/*===========*/
|
||||
/*!< out: length of value
|
||||
encoded, in bytes */
|
||||
ulint val, /*!< in: value to encode */
|
||||
byte* buf); /*!< in: buffer, must have
|
||||
enough space */
|
||||
|
||||
/******************************************************************//**
|
||||
Decode a UTF-8 character.
|
||||
|
||||
http://www.unicode.org/versions/Unicode4.0.0/ch03.pdf:
|
||||
|
||||
Scalar Value 1st Byte 2nd Byte 3rd Byte 4th Byte
|
||||
00000000 0xxxxxxx 0xxxxxxx
|
||||
00000yyy yyxxxxxx 110yyyyy 10xxxxxx
|
||||
zzzzyyyy yyxxxxxx 1110zzzz 10yyyyyy 10xxxxxx
|
||||
000uuuzz zzzzyyyy yyxxxxxx 11110uuu 10zzzzzz 10yyyyyy 10xxxxxx
|
||||
|
||||
This function decodes UTF-8 sequences up to 6 bytes (31 bits).
|
||||
|
||||
On error *ptr will point to the first byte that was not correctly
|
||||
decoded. This will hopefully help in resyncing the input. */
|
||||
UNIV_INLINE
|
||||
ulint
|
||||
fts_utf8_decode(
|
||||
/*============*/
|
||||
/*!< out: UTF8_ERROR if *ptr
|
||||
did not point to a valid
|
||||
UTF-8 sequence, or the
|
||||
Unicode code point. */
|
||||
const byte** ptr); /*!< in/out: pointer to
|
||||
UTF-8 string. The
|
||||
pointer is advanced to
|
||||
the start of the next
|
||||
character. */
|
||||
|
||||
/******************************************************************//**
|
||||
Lowercase an UTF-8 string. */
|
||||
UNIV_INLINE
|
||||
void
|
||||
fts_utf8_tolower(
|
||||
/*=============*/
|
||||
fts_string_t* str); /*!< in: string */
|
||||
|
||||
/******************************************************************//**
|
||||
Get the selected FTS aux INDEX suffix. */
|
||||
UNIV_INLINE
|
||||
const char*
|
||||
fts_get_suffix(
|
||||
/*===========*/
|
||||
ulint selected); /*!< in: selected index */
|
||||
|
||||
/********************************************************************
|
||||
Get the number of index selectors. */
|
||||
UNIV_INLINE
|
||||
ulint
|
||||
fts_get_n_selectors(void);
|
||||
/*=====================*/
|
||||
|
||||
/******************************************************************//**
|
||||
Select the FTS auxiliary index for the given string.
|
||||
@return the index to use for the string */
|
||||
UNIV_INLINE
|
||||
ulint
|
||||
fts_select_index(
|
||||
/*=============*/
|
||||
const CHARSET_INFO* cs, /*!< Charset */
|
||||
const byte* str, /*!< in: word string */
|
||||
ulint len); /*!< in: string length */
|
||||
|
||||
/********************************************************************
|
||||
Select the next FTS auxiliary index for the given character.
|
||||
@return the next index to use for character */
|
||||
UNIV_INLINE
|
||||
ulint
|
||||
fts_select_next_index(
|
||||
/*==================*/
|
||||
const CHARSET_INFO* cs, /*!< Charset */
|
||||
const byte* str, /*!< in: string */
|
||||
ulint len); /*!< in: string length */
|
||||
|
||||
#ifndef UNIV_NONINL
|
||||
#include "fts0types.ic"
|
||||
#include "fts0vlc.ic"
|
||||
#endif
|
||||
|
||||
#endif /* INNOBASE_FTS0TYPES_H */
|
||||
388
storage/innobase/include/fts0types.ic
Normal file
388
storage/innobase/include/fts0types.ic
Normal file
|
|
@ -0,0 +1,388 @@
|
|||
/*****************************************************************************
|
||||
|
||||
Copyright (c) 2007, 2011, Oracle and/or its affiliates. All Rights Reserved.
|
||||
|
||||
This program is free software; you can redistribute it and/or modify it under
|
||||
the terms of the GNU General Public License as published by the Free Software
|
||||
Foundation; version 2 of the License.
|
||||
|
||||
This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
|
||||
FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License along with
|
||||
this program; if not, write to the Free Software Foundation, Inc.,
|
||||
51 Franklin Street, Suite 500, Boston, MA 02110-1335 USA
|
||||
|
||||
*****************************************************************************/
|
||||
|
||||
/******************************************************************//**
|
||||
@file include/fts0types.ic
|
||||
Full text search types.
|
||||
|
||||
Created 2007-03-27 Sunny Bains
|
||||
*******************************************************/
|
||||
|
||||
#ifndef INNOBASE_FTS0TYPES_IC
|
||||
#define INNOBASE_FTS0TYPES_IC
|
||||
|
||||
#include <ctype.h>
|
||||
|
||||
#include "rem0cmp.h"
|
||||
#include "ha_prototypes.h"
|
||||
|
||||
extern const ulint UTF8_ERROR;
|
||||
|
||||
/* Determine if a UTF-8 continuation byte is valid. */
|
||||
#define fts_utf8_is_valid(b) (((b) & 0xC0) == 0x80)
|
||||
|
||||
/******************************************************************//**
|
||||
Duplicate an UTF-8 string.
|
||||
@return < 0 if n1 < n2, 0 if n1 == n2, > 0 if n1 > n2 */
|
||||
UNIV_INLINE
|
||||
void
|
||||
fts_utf8_string_dup(
|
||||
/*================*/
|
||||
fts_string_t* dst, /*!< in: dup to here */
|
||||
const fts_string_t* src, /*!< in: src string */
|
||||
mem_heap_t* heap) /*!< in: heap to use */
|
||||
{
|
||||
dst->f_str = (byte*)mem_heap_alloc(heap, src->f_len + 1);
|
||||
memcpy(dst->f_str, src->f_str, src->f_len);
|
||||
|
||||
dst->f_len = src->f_len;
|
||||
dst->f_str[src->f_len] = 0;
|
||||
dst->f_n_char = src->f_n_char;
|
||||
}
|
||||
|
||||
/******************************************************************//**
|
||||
Compare two fts_trx_row_t doc_ids.
|
||||
@return < 0 if n1 < n2, 0 if n1 == n2, > 0 if n1 > n2 */
|
||||
UNIV_INLINE
|
||||
int
|
||||
fts_trx_row_doc_id_cmp(
|
||||
/*===================*/
|
||||
const void* p1, /*!< in: id1 */
|
||||
const void* p2) /*!< in: id2 */
|
||||
{
|
||||
const fts_trx_row_t* tr1 = (const fts_trx_row_t*) p1;
|
||||
const fts_trx_row_t* tr2 = (const fts_trx_row_t*) p2;
|
||||
|
||||
return((int)(tr1->doc_id - tr2->doc_id));
|
||||
}
|
||||
|
||||
/******************************************************************//**
|
||||
Compare two fts_ranking_t doc_ids.
|
||||
@return < 0 if n1 < n2, 0 if n1 == n2, > 0 if n1 > n2 */
|
||||
UNIV_INLINE
|
||||
int
|
||||
fts_ranking_doc_id_cmp(
|
||||
/*===================*/
|
||||
const void* p1, /*!< in: id1 */
|
||||
const void* p2) /*!< in: id2 */
|
||||
{
|
||||
const fts_ranking_t* rk1 = (const fts_ranking_t*) p1;
|
||||
const fts_ranking_t* rk2 = (const fts_ranking_t*) p2;
|
||||
|
||||
return((int)(rk1->doc_id - rk2->doc_id));
|
||||
}
|
||||
|
||||
/******************************************************************//**
|
||||
Compare two fts_update_t doc_ids.
|
||||
@return < 0 if n1 < n2, 0 if n1 == n2, > 0 if n1 > n2 */
|
||||
UNIV_INLINE
|
||||
int
|
||||
fts_update_doc_id_cmp(
|
||||
/*==================*/
|
||||
const void* p1, /*!< in: id1 */
|
||||
const void* p2) /*!< in: id2 */
|
||||
{
|
||||
const fts_update_t* up1 = (const fts_update_t*) p1;
|
||||
const fts_update_t* up2 = (const fts_update_t*) p2;
|
||||
|
||||
return((int)(up1->doc_id - up2->doc_id));
|
||||
}
|
||||
|
||||
|
||||
/******************************************************************//**
|
||||
Lowercase an UTF-8 string. */
|
||||
UNIV_INLINE
|
||||
void
|
||||
fts_utf8_tolower(
|
||||
/*=============*/
|
||||
fts_string_t* str) /*!< in: string */
|
||||
{
|
||||
innobase_casedn_str((char*) str->f_str);
|
||||
}
|
||||
|
||||
/******************************************************************//**
|
||||
Compare two UTF-8 strings.
|
||||
@return < 0 if n1 < n2, 0 if n1 == n2, > 0 if n1 > n2 */
|
||||
UNIV_INLINE
|
||||
int
|
||||
fts_utf8_string_cmp(
|
||||
/*================*/
|
||||
const void* p1, /*!< in: key */
|
||||
const void* p2) /*!< in: node */
|
||||
{
|
||||
const fts_string_t* s1 = (const fts_string_t*) p1;
|
||||
const fts_string_t* s2 = (const fts_string_t*) p2;
|
||||
|
||||
return(cmp_data_data_slow_varchar(
|
||||
s1->f_str, s1->f_len, s2->f_str, s2->f_len));
|
||||
}
|
||||
|
||||
/******************************************************************//**
|
||||
Compare two UTF-8 strings, and return match (0) if
|
||||
passed in "key" value equals or is the prefix of the "node" value.
|
||||
@return < 0 if n1 < n2, 0 if n1 == n2, > 0 if n1 > n2 */
|
||||
UNIV_INLINE
|
||||
int
|
||||
fts_utf8_string_cmp_prefix(
|
||||
/*=======================*/
|
||||
const void* p1, /*!< in: key */
|
||||
const void* p2) /*!< in: node */
|
||||
{
|
||||
int result;
|
||||
ulint len;
|
||||
|
||||
const fts_string_t* s1 = (const fts_string_t*) p1;
|
||||
const fts_string_t* s2 = (const fts_string_t*) p2;
|
||||
|
||||
len = ut_min(s1->f_len, s2->f_len);
|
||||
|
||||
result = cmp_data_data_slow_varchar(s1->f_str, len, s2->f_str, len);
|
||||
|
||||
if (result) {
|
||||
return(result);
|
||||
}
|
||||
|
||||
if (s1->f_len > s2->f_len) {
|
||||
return(1);
|
||||
}
|
||||
|
||||
return(0);
|
||||
}
|
||||
|
||||
/******************************************************************//**
|
||||
Decode a UTF-8 character.
|
||||
|
||||
http://www.unicode.org/versions/Unicode4.0.0/ch03.pdf:
|
||||
|
||||
Scalar Value 1st Byte 2nd Byte 3rd Byte 4th Byte
|
||||
00000000 0xxxxxxx 0xxxxxxx
|
||||
00000yyy yyxxxxxx 110yyyyy 10xxxxxx
|
||||
zzzzyyyy yyxxxxxx 1110zzzz 10yyyyyy 10xxxxxx
|
||||
000uuuzz zzzzyyyy yyxxxxxx 11110uuu 10zzzzzz 10yyyyyy 10xxxxxx
|
||||
|
||||
This function decodes UTF-8 sequences up to 6 bytes (31 bits).
|
||||
|
||||
On error *ptr will point to the first byte that was not correctly
|
||||
decoded. This will hopefully help in resyncing the input.
|
||||
@return UTF8_ERROR if *ptr did not point to a valid
|
||||
UTF-8 sequence, or the Unicode code point. */
|
||||
UNIV_INLINE
|
||||
ulint
|
||||
fts_utf8_decode(
|
||||
/*============*/
|
||||
const byte** ptr) /*!< in/out: pointer to
|
||||
UTF-8 string. The
|
||||
pointer is advanced to
|
||||
the start of the next
|
||||
character. */
|
||||
{
|
||||
const byte* p = *ptr;
|
||||
ulint ch = *p++;
|
||||
#ifdef UNIV_DEBUG
|
||||
ulint min_ch;
|
||||
#endif /* UNIV_DEBUG */
|
||||
|
||||
if (UNIV_LIKELY(ch < 0x80)) {
|
||||
/* 0xxxxxxx */
|
||||
} else if (UNIV_UNLIKELY(ch < 0xC0)) {
|
||||
/* A continuation byte cannot start a code. */
|
||||
goto err_exit;
|
||||
} else if (ch < 0xE0) {
|
||||
/* 110yyyyy 10xxxxxx */
|
||||
ch &= 0x1F;
|
||||
ut_d(min_ch = 0x80);
|
||||
goto get1;
|
||||
} else if (ch < 0xF0) {
|
||||
/* 1110zzzz 10yyyyyy 10xxxxxx */
|
||||
ch &= 0x0F;
|
||||
ut_d(min_ch = 0x800);
|
||||
goto get2;
|
||||
} else if (ch < 0xF8) {
|
||||
/* 11110uuu 10zzzzzz 10yyyyyy 10xxxxxx */
|
||||
ch &= 0x07;
|
||||
ut_d(min_ch = 0x10000);
|
||||
goto get3;
|
||||
} else if (ch < 0xFC) {
|
||||
/* 111110tt 10uuuuuu 10zzzzzz 10yyyyyy 10xxxxxx */
|
||||
ch &= 0x03;
|
||||
ut_d(min_ch = 0x200000);
|
||||
goto get4;
|
||||
} else if (ch < 0xFE) {
|
||||
/* 1111110s 10tttttt 10uuuuuu 10zzzzzz 10yyyyyy 10xxxxxx */
|
||||
ut_d(min_ch = 0x4000000);
|
||||
if (!fts_utf8_is_valid(*p)) {
|
||||
goto err_exit;
|
||||
}
|
||||
ch <<= 6;
|
||||
ch |= (*p++) & 0x3F;
|
||||
get4:
|
||||
if (!fts_utf8_is_valid(*p)) {
|
||||
goto err_exit;
|
||||
}
|
||||
ch <<= 6;
|
||||
ch |= (*p++) & 0x3F;
|
||||
get3:
|
||||
if (!fts_utf8_is_valid(*p)) {
|
||||
goto err_exit;
|
||||
}
|
||||
ch <<= 6;
|
||||
ch |= (*p++) & 0x3F;
|
||||
get2:
|
||||
if (!fts_utf8_is_valid(*p)) {
|
||||
goto err_exit;
|
||||
}
|
||||
ch <<= 6;
|
||||
ch |= (*p++) & 0x3F;
|
||||
get1:
|
||||
if (!fts_utf8_is_valid(*p)) {
|
||||
goto err_exit;
|
||||
}
|
||||
ch <<= 6;
|
||||
ch |= (*p++) & 0x3F;
|
||||
|
||||
/* The following is needed in the 6-byte case
|
||||
when ulint is wider than 32 bits. */
|
||||
ch &= 0xFFFFFFFF;
|
||||
|
||||
/* The code positions U+D800 to U+DFFF (UTF-16 surrogate pairs)
|
||||
and U+FFFE and U+FFFF cannot occur in valid UTF-8. */
|
||||
|
||||
if ( (ch >= 0xD800 && ch <= 0xDFFF)
|
||||
#ifdef UNIV_DEBUG
|
||||
|| ch < min_ch
|
||||
#endif /* UNIV_DEBUG */
|
||||
|| ch == 0xFFFE || ch == 0xFFFF) {
|
||||
|
||||
ch = UTF8_ERROR;
|
||||
}
|
||||
} else {
|
||||
err_exit:
|
||||
ch = UTF8_ERROR;
|
||||
}
|
||||
|
||||
*ptr = p;
|
||||
|
||||
return(ch);
|
||||
}
|
||||
|
||||
/******************************************************************//**
|
||||
Get the first character's code position for FTS index partition */
|
||||
extern
|
||||
ulint
|
||||
innobase_strnxfrm(
|
||||
/*==============*/
|
||||
const CHARSET_INFO* cs, /*!< in: Character set */
|
||||
const uchar* p2, /*!< in: string */
|
||||
const ulint len2); /*!< in: string length */
|
||||
|
||||
/******************************************************************//**
|
||||
Select the FTS auxiliary index for the given character.
|
||||
@return the index to use for the string */
|
||||
UNIV_INLINE
|
||||
ulint
|
||||
fts_select_index(
|
||||
/*=============*/
|
||||
const CHARSET_INFO* cs, /*!< in: Charset */
|
||||
const byte* str, /*!< in: string */
|
||||
ulint len) /*!< in: string length */
|
||||
{
|
||||
ulint selected = 0;
|
||||
ulint value = innobase_strnxfrm(cs, str, len);
|
||||
|
||||
while (fts_index_selector[selected].value != 0) {
|
||||
|
||||
if (fts_index_selector[selected].value == value) {
|
||||
|
||||
return(selected);
|
||||
|
||||
} else if (fts_index_selector[selected].value > value) {
|
||||
|
||||
return(selected > 0 ? selected - 1 : 0);
|
||||
}
|
||||
|
||||
++selected;
|
||||
}
|
||||
|
||||
ut_ad(selected > 1);
|
||||
|
||||
return(selected - 1);
|
||||
}
|
||||
|
||||
/******************************************************************//**
|
||||
Select the next FTS auxiliary index for the given character.
|
||||
@return the next index to use for character */
|
||||
UNIV_INLINE
|
||||
ulint
|
||||
fts_select_next_index(
|
||||
/*==================*/
|
||||
const CHARSET_INFO* cs, /*!< in: Charset */
|
||||
const byte* str, /*!< in: string */
|
||||
ulint len) /*!< in: string length */
|
||||
{
|
||||
ulint selected = 0;
|
||||
ulint value = innobase_strnxfrm(cs, str, len);
|
||||
|
||||
while (fts_index_selector[selected].value != 0) {
|
||||
|
||||
if (fts_index_selector[selected].value == value) {
|
||||
|
||||
return(selected + 1);
|
||||
|
||||
} else if (fts_index_selector[selected].value > value) {
|
||||
|
||||
return(selected);
|
||||
}
|
||||
|
||||
++selected;
|
||||
}
|
||||
|
||||
ut_ad(selected > 0);
|
||||
|
||||
return((ulint) selected);
|
||||
}
|
||||
|
||||
/******************************************************************//**
|
||||
Return the selected FTS aux index suffix. */
|
||||
UNIV_INLINE
|
||||
const char*
|
||||
fts_get_suffix(
|
||||
/*===========*/
|
||||
ulint selected) /*!< in: selected index */
|
||||
{
|
||||
return(fts_index_selector[selected].suffix);
|
||||
}
|
||||
|
||||
/******************************************************************//**
|
||||
Get the number of index selectors.
|
||||
@return The number of selectors */
|
||||
UNIV_INLINE
|
||||
ulint
|
||||
fts_get_n_selectors(void)
|
||||
/*=====================*/
|
||||
{
|
||||
ulint i = 0;
|
||||
|
||||
// FIXME: This is a hack
|
||||
while (fts_index_selector[i].value != 0) {
|
||||
++i;
|
||||
}
|
||||
|
||||
return(i);
|
||||
}
|
||||
|
||||
#endif /* INNOBASE_FTS0TYPES_IC */
|
||||
142
storage/innobase/include/fts0vlc.ic
Normal file
142
storage/innobase/include/fts0vlc.ic
Normal file
|
|
@ -0,0 +1,142 @@
|
|||
/*****************************************************************************
|
||||
|
||||
Copyright (c) 2007, 2011, Oracle and/or its affiliates. All Rights Reserved.
|
||||
|
||||
This program is free software; you can redistribute it and/or modify it under
|
||||
the terms of the GNU General Public License as published by the Free Software
|
||||
Foundation; version 2 of the License.
|
||||
|
||||
This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
|
||||
FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License along with
|
||||
this program; if not, write to the Free Software Foundation, Inc.,
|
||||
51 Franklin Street, Suite 500, Boston, MA 02110-1335 USA
|
||||
|
||||
*****************************************************************************/
|
||||
|
||||
/******************************************************************//**
|
||||
@file include/fts0vlc.ic
|
||||
Full text variable length integer encoding/decoding.
|
||||
|
||||
Created 2007-03-27 Sunny Bains
|
||||
*******************************************************/
|
||||
|
||||
#ifndef INNOBASE_FTS0VLC_IC
|
||||
#define INNOBASE_FTS0VLC_IC
|
||||
|
||||
#include "fts0types.h"
|
||||
|
||||
/******************************************************************//**
|
||||
Return length of val if it were encoded using our VLC scheme.
|
||||
FIXME: We will need to be able encode 8 bytes value
|
||||
@return length of value encoded, in bytes */
|
||||
UNIV_INLINE
|
||||
ulint
|
||||
fts_get_encoded_len(
|
||||
/*================*/
|
||||
ulint val) /* in: value to encode */
|
||||
{
|
||||
if (val <= 127) {
|
||||
return(1);
|
||||
} else if (val <= 16383) {
|
||||
return(2);
|
||||
} else if (val <= 2097151) {
|
||||
return(3);
|
||||
} else if (val <= 268435455) {
|
||||
return(4);
|
||||
} else {
|
||||
/* Possibly we should care that on 64-bit machines ulint can
|
||||
contain values that we can't encode in 5 bytes, but
|
||||
fts_encode_int doesn't handle them either so it doesn't much
|
||||
matter. */
|
||||
|
||||
return(5);
|
||||
}
|
||||
}
|
||||
|
||||
/******************************************************************//**
|
||||
Encode an integer using our VLC scheme and return the length in bytes.
|
||||
@return length of value encoded, in bytes */
|
||||
UNIV_INLINE
|
||||
ulint
|
||||
fts_encode_int(
|
||||
/*===========*/
|
||||
ulint val, /* in: value to encode */
|
||||
byte* buf) /* in: buffer, must have enough space */
|
||||
{
|
||||
ulint len;
|
||||
|
||||
if (val <= 127) {
|
||||
*buf = (byte) val;
|
||||
|
||||
len = 1;
|
||||
} else if (val <= 16383) {
|
||||
*buf++ = (byte)(val >> 7);
|
||||
*buf = (byte)(val & 0x7F);
|
||||
|
||||
len = 2;
|
||||
} else if (val <= 2097151) {
|
||||
*buf++ = (byte)(val >> 14);
|
||||
*buf++ = (byte)((val >> 7) & 0x7F);
|
||||
*buf = (byte)(val & 0x7F);
|
||||
|
||||
len = 3;
|
||||
} else if (val <= 268435455) {
|
||||
*buf++ = (byte)(val >> 21);
|
||||
*buf++ = (byte)((val >> 14) & 0x7F);
|
||||
*buf++ = (byte)((val >> 7) & 0x7F);
|
||||
*buf = (byte)(val & 0x7F);
|
||||
|
||||
len = 4;
|
||||
} else {
|
||||
/* Best to keep the limitations of the 32/64 bit versions
|
||||
identical, at least for the time being. */
|
||||
ut_ad(val <= 4294967295u);
|
||||
|
||||
*buf++ = (byte)(val >> 28);
|
||||
*buf++ = (byte)((val >> 21) & 0x7F);
|
||||
*buf++ = (byte)((val >> 14) & 0x7F);
|
||||
*buf++ = (byte)((val >> 7) & 0x7F);
|
||||
*buf = (byte)(val & 0x7F);
|
||||
|
||||
len = 5;
|
||||
}
|
||||
|
||||
/* High-bit on means "last byte in the encoded integer". */
|
||||
*buf |= 0x80;
|
||||
|
||||
return(len);
|
||||
}
|
||||
|
||||
/******************************************************************//**
|
||||
Decode and return the integer that was encoded using our VLC scheme.
|
||||
@return value decoded */
|
||||
UNIV_INLINE
|
||||
ulint
|
||||
fts_decode_vlc(
|
||||
/*===========*/
|
||||
byte** ptr) /* in: ptr to decode from, this ptr is
|
||||
incremented by the number of bytes decoded */
|
||||
{
|
||||
ulint val = 0;
|
||||
|
||||
for (;;) {
|
||||
byte b = **ptr;
|
||||
|
||||
++*ptr;
|
||||
val |= (b & 0x7F);
|
||||
|
||||
/* High-bit on means "last byte in the encoded integer". */
|
||||
if (b & 0x80) {
|
||||
break;
|
||||
} else {
|
||||
val <<= 7;
|
||||
}
|
||||
}
|
||||
|
||||
return(val);
|
||||
}
|
||||
|
||||
#endif
|
||||
55
storage/innobase/include/fut0fut.h
Normal file
55
storage/innobase/include/fut0fut.h
Normal file
|
|
@ -0,0 +1,55 @@
|
|||
/*****************************************************************************
|
||||
|
||||
Copyright (c) 1995, 2009, Oracle and/or its affiliates. All Rights Reserved.
|
||||
|
||||
This program is free software; you can redistribute it and/or modify it under
|
||||
the terms of the GNU General Public License as published by the Free Software
|
||||
Foundation; version 2 of the License.
|
||||
|
||||
This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
|
||||
FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License along with
|
||||
this program; if not, write to the Free Software Foundation, Inc.,
|
||||
51 Franklin Street, Suite 500, Boston, MA 02110-1335 USA
|
||||
|
||||
*****************************************************************************/
|
||||
|
||||
/******************************************************************//**
|
||||
@file include/fut0fut.h
|
||||
File-based utilities
|
||||
|
||||
Created 12/13/1995 Heikki Tuuri
|
||||
***********************************************************************/
|
||||
|
||||
|
||||
#ifndef fut0fut_h
|
||||
#define fut0fut_h
|
||||
|
||||
#include "univ.i"
|
||||
|
||||
#include "fil0fil.h"
|
||||
#include "mtr0mtr.h"
|
||||
|
||||
/********************************************************************//**
|
||||
Gets a pointer to a file address and latches the page.
|
||||
@return pointer to a byte in a frame; the file page in the frame is
|
||||
bufferfixed and latched */
|
||||
UNIV_INLINE
|
||||
byte*
|
||||
fut_get_ptr(
|
||||
/*========*/
|
||||
ulint space, /*!< in: space id */
|
||||
ulint zip_size,/*!< in: compressed page size in bytes
|
||||
or 0 for uncompressed pages */
|
||||
fil_addr_t addr, /*!< in: file address */
|
||||
ulint rw_latch, /*!< in: RW_S_LATCH, RW_X_LATCH */
|
||||
mtr_t* mtr); /*!< in: mtr handle */
|
||||
|
||||
#ifndef UNIV_NONINL
|
||||
#include "fut0fut.ic"
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
56
storage/innobase/include/fut0fut.ic
Normal file
56
storage/innobase/include/fut0fut.ic
Normal file
|
|
@ -0,0 +1,56 @@
|
|||
/*****************************************************************************
|
||||
|
||||
Copyright (c) 1995, 2009, Oracle and/or its affiliates. All Rights Reserved.
|
||||
|
||||
This program is free software; you can redistribute it and/or modify it under
|
||||
the terms of the GNU General Public License as published by the Free Software
|
||||
Foundation; version 2 of the License.
|
||||
|
||||
This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
|
||||
FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License along with
|
||||
this program; if not, write to the Free Software Foundation, Inc.,
|
||||
51 Franklin Street, Suite 500, Boston, MA 02110-1335 USA
|
||||
|
||||
*****************************************************************************/
|
||||
|
||||
/******************************************************************//**
|
||||
@file include/fut0fut.ic
|
||||
File-based utilities
|
||||
|
||||
Created 12/13/1995 Heikki Tuuri
|
||||
***********************************************************************/
|
||||
|
||||
#include "sync0rw.h"
|
||||
#include "buf0buf.h"
|
||||
|
||||
/********************************************************************//**
|
||||
Gets a pointer to a file address and latches the page.
|
||||
@return pointer to a byte in a frame; the file page in the frame is
|
||||
bufferfixed and latched */
|
||||
UNIV_INLINE
|
||||
byte*
|
||||
fut_get_ptr(
|
||||
/*========*/
|
||||
ulint space, /*!< in: space id */
|
||||
ulint zip_size,/*!< in: compressed page size in bytes
|
||||
or 0 for uncompressed pages */
|
||||
fil_addr_t addr, /*!< in: file address */
|
||||
ulint rw_latch, /*!< in: RW_S_LATCH, RW_X_LATCH */
|
||||
mtr_t* mtr) /*!< in: mtr handle */
|
||||
{
|
||||
buf_block_t* block;
|
||||
byte* ptr;
|
||||
|
||||
ut_ad(addr.boffset < UNIV_PAGE_SIZE);
|
||||
ut_ad((rw_latch == RW_S_LATCH) || (rw_latch == RW_X_LATCH));
|
||||
|
||||
block = buf_page_get(space, zip_size, addr.page, rw_latch, mtr);
|
||||
ptr = buf_block_get_frame(block) + addr.boffset;
|
||||
|
||||
buf_block_dbg_add_level(block, SYNC_NO_ORDER_CHECK);
|
||||
|
||||
return(ptr);
|
||||
}
|
||||
217
storage/innobase/include/fut0lst.h
Normal file
217
storage/innobase/include/fut0lst.h
Normal file
|
|
@ -0,0 +1,217 @@
|
|||
/*****************************************************************************
|
||||
|
||||
Copyright (c) 1995, 2009, Oracle and/or its affiliates. All Rights Reserved.
|
||||
|
||||
This program is free software; you can redistribute it and/or modify it under
|
||||
the terms of the GNU General Public License as published by the Free Software
|
||||
Foundation; version 2 of the License.
|
||||
|
||||
This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
|
||||
FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License along with
|
||||
this program; if not, write to the Free Software Foundation, Inc.,
|
||||
51 Franklin Street, Suite 500, Boston, MA 02110-1335 USA
|
||||
|
||||
*****************************************************************************/
|
||||
|
||||
/******************************************************************//**
|
||||
@file include/fut0lst.h
|
||||
File-based list utilities
|
||||
|
||||
Created 11/28/1995 Heikki Tuuri
|
||||
***********************************************************************/
|
||||
|
||||
#ifndef fut0lst_h
|
||||
#define fut0lst_h
|
||||
|
||||
#include "univ.i"
|
||||
|
||||
#include "fil0fil.h"
|
||||
#include "mtr0mtr.h"
|
||||
|
||||
|
||||
/* The C 'types' of base node and list node: these should be used to
|
||||
write self-documenting code. Of course, the sizeof macro cannot be
|
||||
applied to these types! */
|
||||
|
||||
typedef byte flst_base_node_t;
|
||||
typedef byte flst_node_t;
|
||||
|
||||
/* The physical size of a list base node in bytes */
|
||||
#define FLST_BASE_NODE_SIZE (4 + 2 * FIL_ADDR_SIZE)
|
||||
|
||||
/* The physical size of a list node in bytes */
|
||||
#define FLST_NODE_SIZE (2 * FIL_ADDR_SIZE)
|
||||
|
||||
#ifndef UNIV_HOTBACKUP
|
||||
/********************************************************************//**
|
||||
Initializes a list base node. */
|
||||
UNIV_INLINE
|
||||
void
|
||||
flst_init(
|
||||
/*======*/
|
||||
flst_base_node_t* base, /*!< in: pointer to base node */
|
||||
mtr_t* mtr); /*!< in: mini-transaction handle */
|
||||
/********************************************************************//**
|
||||
Adds a node as the last node in a list. */
|
||||
UNIV_INTERN
|
||||
void
|
||||
flst_add_last(
|
||||
/*==========*/
|
||||
flst_base_node_t* base, /*!< in: pointer to base node of list */
|
||||
flst_node_t* node, /*!< in: node to add */
|
||||
mtr_t* mtr); /*!< in: mini-transaction handle */
|
||||
/********************************************************************//**
|
||||
Adds a node as the first node in a list. */
|
||||
UNIV_INTERN
|
||||
void
|
||||
flst_add_first(
|
||||
/*===========*/
|
||||
flst_base_node_t* base, /*!< in: pointer to base node of list */
|
||||
flst_node_t* node, /*!< in: node to add */
|
||||
mtr_t* mtr); /*!< in: mini-transaction handle */
|
||||
/********************************************************************//**
|
||||
Inserts a node after another in a list. */
|
||||
UNIV_INTERN
|
||||
void
|
||||
flst_insert_after(
|
||||
/*==============*/
|
||||
flst_base_node_t* base, /*!< in: pointer to base node of list */
|
||||
flst_node_t* node1, /*!< in: node to insert after */
|
||||
flst_node_t* node2, /*!< in: node to add */
|
||||
mtr_t* mtr); /*!< in: mini-transaction handle */
|
||||
/********************************************************************//**
|
||||
Inserts a node before another in a list. */
|
||||
UNIV_INTERN
|
||||
void
|
||||
flst_insert_before(
|
||||
/*===============*/
|
||||
flst_base_node_t* base, /*!< in: pointer to base node of list */
|
||||
flst_node_t* node2, /*!< in: node to insert */
|
||||
flst_node_t* node3, /*!< in: node to insert before */
|
||||
mtr_t* mtr); /*!< in: mini-transaction handle */
|
||||
/********************************************************************//**
|
||||
Removes a node. */
|
||||
UNIV_INTERN
|
||||
void
|
||||
flst_remove(
|
||||
/*========*/
|
||||
flst_base_node_t* base, /*!< in: pointer to base node of list */
|
||||
flst_node_t* node2, /*!< in: node to remove */
|
||||
mtr_t* mtr); /*!< in: mini-transaction handle */
|
||||
/********************************************************************//**
|
||||
Cuts off the tail of the list, including the node given. The number of
|
||||
nodes which will be removed must be provided by the caller, as this function
|
||||
does not measure the length of the tail. */
|
||||
UNIV_INTERN
|
||||
void
|
||||
flst_cut_end(
|
||||
/*=========*/
|
||||
flst_base_node_t* base, /*!< in: pointer to base node of list */
|
||||
flst_node_t* node2, /*!< in: first node to remove */
|
||||
ulint n_nodes,/*!< in: number of nodes to remove,
|
||||
must be >= 1 */
|
||||
mtr_t* mtr); /*!< in: mini-transaction handle */
|
||||
/********************************************************************//**
|
||||
Cuts off the tail of the list, not including the given node. The number of
|
||||
nodes which will be removed must be provided by the caller, as this function
|
||||
does not measure the length of the tail. */
|
||||
UNIV_INTERN
|
||||
void
|
||||
flst_truncate_end(
|
||||
/*==============*/
|
||||
flst_base_node_t* base, /*!< in: pointer to base node of list */
|
||||
flst_node_t* node2, /*!< in: first node not to remove */
|
||||
ulint n_nodes,/*!< in: number of nodes to remove */
|
||||
mtr_t* mtr); /*!< in: mini-transaction handle */
|
||||
/********************************************************************//**
|
||||
Gets list length.
|
||||
@return length */
|
||||
UNIV_INLINE
|
||||
ulint
|
||||
flst_get_len(
|
||||
/*=========*/
|
||||
const flst_base_node_t* base, /*!< in: pointer to base node */
|
||||
mtr_t* mtr); /*!< in: mini-transaction handle */
|
||||
/********************************************************************//**
|
||||
Gets list first node address.
|
||||
@return file address */
|
||||
UNIV_INLINE
|
||||
fil_addr_t
|
||||
flst_get_first(
|
||||
/*===========*/
|
||||
const flst_base_node_t* base, /*!< in: pointer to base node */
|
||||
mtr_t* mtr); /*!< in: mini-transaction handle */
|
||||
/********************************************************************//**
|
||||
Gets list last node address.
|
||||
@return file address */
|
||||
UNIV_INLINE
|
||||
fil_addr_t
|
||||
flst_get_last(
|
||||
/*==========*/
|
||||
const flst_base_node_t* base, /*!< in: pointer to base node */
|
||||
mtr_t* mtr); /*!< in: mini-transaction handle */
|
||||
/********************************************************************//**
|
||||
Gets list next node address.
|
||||
@return file address */
|
||||
UNIV_INLINE
|
||||
fil_addr_t
|
||||
flst_get_next_addr(
|
||||
/*===============*/
|
||||
const flst_node_t* node, /*!< in: pointer to node */
|
||||
mtr_t* mtr); /*!< in: mini-transaction handle */
|
||||
/********************************************************************//**
|
||||
Gets list prev node address.
|
||||
@return file address */
|
||||
UNIV_INLINE
|
||||
fil_addr_t
|
||||
flst_get_prev_addr(
|
||||
/*===============*/
|
||||
const flst_node_t* node, /*!< in: pointer to node */
|
||||
mtr_t* mtr); /*!< in: mini-transaction handle */
|
||||
/********************************************************************//**
|
||||
Writes a file address. */
|
||||
UNIV_INLINE
|
||||
void
|
||||
flst_write_addr(
|
||||
/*============*/
|
||||
fil_faddr_t* faddr, /*!< in: pointer to file faddress */
|
||||
fil_addr_t addr, /*!< in: file address */
|
||||
mtr_t* mtr); /*!< in: mini-transaction handle */
|
||||
/********************************************************************//**
|
||||
Reads a file address.
|
||||
@return file address */
|
||||
UNIV_INLINE
|
||||
fil_addr_t
|
||||
flst_read_addr(
|
||||
/*===========*/
|
||||
const fil_faddr_t* faddr, /*!< in: pointer to file faddress */
|
||||
mtr_t* mtr); /*!< in: mini-transaction handle */
|
||||
/********************************************************************//**
|
||||
Validates a file-based list.
|
||||
@return TRUE if ok */
|
||||
UNIV_INTERN
|
||||
ibool
|
||||
flst_validate(
|
||||
/*==========*/
|
||||
const flst_base_node_t* base, /*!< in: pointer to base node of list */
|
||||
mtr_t* mtr1); /*!< in: mtr */
|
||||
/********************************************************************//**
|
||||
Prints info of a file-based list. */
|
||||
UNIV_INTERN
|
||||
void
|
||||
flst_print(
|
||||
/*=======*/
|
||||
const flst_base_node_t* base, /*!< in: pointer to base node of list */
|
||||
mtr_t* mtr); /*!< in: mtr */
|
||||
|
||||
|
||||
#ifndef UNIV_NONINL
|
||||
#include "fut0lst.ic"
|
||||
#endif
|
||||
|
||||
#endif /* !UNIV_HOTBACKUP */
|
||||
|
||||
#endif
|
||||
167
storage/innobase/include/fut0lst.ic
Normal file
167
storage/innobase/include/fut0lst.ic
Normal file
|
|
@ -0,0 +1,167 @@
|
|||
/*****************************************************************************
|
||||
|
||||
Copyright (c) 1995, 2009, Oracle and/or its affiliates. All Rights Reserved.
|
||||
|
||||
This program is free software; you can redistribute it and/or modify it under
|
||||
the terms of the GNU General Public License as published by the Free Software
|
||||
Foundation; version 2 of the License.
|
||||
|
||||
This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
|
||||
FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License along with
|
||||
this program; if not, write to the Free Software Foundation, Inc.,
|
||||
51 Franklin Street, Suite 500, Boston, MA 02110-1335 USA
|
||||
|
||||
*****************************************************************************/
|
||||
|
||||
/******************************************************************//**
|
||||
@file include/fut0lst.ic
|
||||
File-based list utilities
|
||||
|
||||
Created 11/28/1995 Heikki Tuuri
|
||||
***********************************************************************/
|
||||
|
||||
#include "fut0fut.h"
|
||||
#include "mtr0log.h"
|
||||
#include "buf0buf.h"
|
||||
|
||||
/* We define the field offsets of a node for the list */
|
||||
#define FLST_PREV 0 /* 6-byte address of the previous list element;
|
||||
the page part of address is FIL_NULL, if no
|
||||
previous element */
|
||||
#define FLST_NEXT FIL_ADDR_SIZE /* 6-byte address of the next
|
||||
list element; the page part of address
|
||||
is FIL_NULL, if no next element */
|
||||
|
||||
/* We define the field offsets of a base node for the list */
|
||||
#define FLST_LEN 0 /* 32-bit list length field */
|
||||
#define FLST_FIRST 4 /* 6-byte address of the first element
|
||||
of the list; undefined if empty list */
|
||||
#define FLST_LAST (4 + FIL_ADDR_SIZE) /* 6-byte address of the
|
||||
last element of the list; undefined
|
||||
if empty list */
|
||||
|
||||
/********************************************************************//**
|
||||
Writes a file address. */
|
||||
UNIV_INLINE
|
||||
void
|
||||
flst_write_addr(
|
||||
/*============*/
|
||||
fil_faddr_t* faddr, /*!< in: pointer to file faddress */
|
||||
fil_addr_t addr, /*!< in: file address */
|
||||
mtr_t* mtr) /*!< in: mini-transaction handle */
|
||||
{
|
||||
ut_ad(faddr && mtr);
|
||||
ut_ad(mtr_memo_contains_page(mtr, faddr, MTR_MEMO_PAGE_X_FIX));
|
||||
ut_a(addr.page == FIL_NULL || addr.boffset >= FIL_PAGE_DATA);
|
||||
ut_a(ut_align_offset(faddr, UNIV_PAGE_SIZE) >= FIL_PAGE_DATA);
|
||||
|
||||
mlog_write_ulint(faddr + FIL_ADDR_PAGE, addr.page, MLOG_4BYTES, mtr);
|
||||
mlog_write_ulint(faddr + FIL_ADDR_BYTE, addr.boffset,
|
||||
MLOG_2BYTES, mtr);
|
||||
}
|
||||
|
||||
/********************************************************************//**
|
||||
Reads a file address.
|
||||
@return file address */
|
||||
UNIV_INLINE
|
||||
fil_addr_t
|
||||
flst_read_addr(
|
||||
/*===========*/
|
||||
const fil_faddr_t* faddr, /*!< in: pointer to file faddress */
|
||||
mtr_t* mtr) /*!< in: mini-transaction handle */
|
||||
{
|
||||
fil_addr_t addr;
|
||||
|
||||
ut_ad(faddr && mtr);
|
||||
|
||||
addr.page = mtr_read_ulint(faddr + FIL_ADDR_PAGE, MLOG_4BYTES, mtr);
|
||||
addr.boffset = mtr_read_ulint(faddr + FIL_ADDR_BYTE, MLOG_2BYTES,
|
||||
mtr);
|
||||
ut_a(addr.page == FIL_NULL || addr.boffset >= FIL_PAGE_DATA);
|
||||
ut_a(ut_align_offset(faddr, UNIV_PAGE_SIZE) >= FIL_PAGE_DATA);
|
||||
return(addr);
|
||||
}
|
||||
|
||||
/********************************************************************//**
|
||||
Initializes a list base node. */
|
||||
UNIV_INLINE
|
||||
void
|
||||
flst_init(
|
||||
/*======*/
|
||||
flst_base_node_t* base, /*!< in: pointer to base node */
|
||||
mtr_t* mtr) /*!< in: mini-transaction handle */
|
||||
{
|
||||
ut_ad(mtr_memo_contains_page(mtr, base, MTR_MEMO_PAGE_X_FIX));
|
||||
|
||||
mlog_write_ulint(base + FLST_LEN, 0, MLOG_4BYTES, mtr);
|
||||
flst_write_addr(base + FLST_FIRST, fil_addr_null, mtr);
|
||||
flst_write_addr(base + FLST_LAST, fil_addr_null, mtr);
|
||||
}
|
||||
|
||||
/********************************************************************//**
|
||||
Gets list length.
|
||||
@return length */
|
||||
UNIV_INLINE
|
||||
ulint
|
||||
flst_get_len(
|
||||
/*=========*/
|
||||
const flst_base_node_t* base, /*!< in: pointer to base node */
|
||||
mtr_t* mtr) /*!< in: mini-transaction handle */
|
||||
{
|
||||
return(mtr_read_ulint(base + FLST_LEN, MLOG_4BYTES, mtr));
|
||||
}
|
||||
|
||||
/********************************************************************//**
|
||||
Gets list first node address.
|
||||
@return file address */
|
||||
UNIV_INLINE
|
||||
fil_addr_t
|
||||
flst_get_first(
|
||||
/*===========*/
|
||||
const flst_base_node_t* base, /*!< in: pointer to base node */
|
||||
mtr_t* mtr) /*!< in: mini-transaction handle */
|
||||
{
|
||||
return(flst_read_addr(base + FLST_FIRST, mtr));
|
||||
}
|
||||
|
||||
/********************************************************************//**
|
||||
Gets list last node address.
|
||||
@return file address */
|
||||
UNIV_INLINE
|
||||
fil_addr_t
|
||||
flst_get_last(
|
||||
/*==========*/
|
||||
const flst_base_node_t* base, /*!< in: pointer to base node */
|
||||
mtr_t* mtr) /*!< in: mini-transaction handle */
|
||||
{
|
||||
return(flst_read_addr(base + FLST_LAST, mtr));
|
||||
}
|
||||
|
||||
/********************************************************************//**
|
||||
Gets list next node address.
|
||||
@return file address */
|
||||
UNIV_INLINE
|
||||
fil_addr_t
|
||||
flst_get_next_addr(
|
||||
/*===============*/
|
||||
const flst_node_t* node, /*!< in: pointer to node */
|
||||
mtr_t* mtr) /*!< in: mini-transaction handle */
|
||||
{
|
||||
return(flst_read_addr(node + FLST_NEXT, mtr));
|
||||
}
|
||||
|
||||
/********************************************************************//**
|
||||
Gets list prev node address.
|
||||
@return file address */
|
||||
UNIV_INLINE
|
||||
fil_addr_t
|
||||
flst_get_prev_addr(
|
||||
/*===============*/
|
||||
const flst_node_t* node, /*!< in: pointer to node */
|
||||
mtr_t* mtr) /*!< in: mini-transaction handle */
|
||||
{
|
||||
return(flst_read_addr(node + FLST_PREV, mtr));
|
||||
}
|
||||
265
storage/innobase/include/ha0ha.h
Normal file
265
storage/innobase/include/ha0ha.h
Normal file
|
|
@ -0,0 +1,265 @@
|
|||
/*****************************************************************************
|
||||
|
||||
Copyright (c) 1994, 2011, Oracle and/or its affiliates. All Rights Reserved.
|
||||
|
||||
This program is free software; you can redistribute it and/or modify it under
|
||||
the terms of the GNU General Public License as published by the Free Software
|
||||
Foundation; version 2 of the License.
|
||||
|
||||
This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
|
||||
FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License along with
|
||||
this program; if not, write to the Free Software Foundation, Inc.,
|
||||
51 Franklin Street, Suite 500, Boston, MA 02110-1335 USA
|
||||
|
||||
*****************************************************************************/
|
||||
|
||||
/**************************************************//**
|
||||
@file include/ha0ha.h
|
||||
The hash table with external chains
|
||||
|
||||
Created 8/18/1994 Heikki Tuuri
|
||||
*******************************************************/
|
||||
|
||||
#ifndef ha0ha_h
|
||||
#define ha0ha_h
|
||||
|
||||
#include "univ.i"
|
||||
|
||||
#include "hash0hash.h"
|
||||
#include "page0types.h"
|
||||
#include "buf0types.h"
|
||||
#include "rem0types.h"
|
||||
|
||||
/*************************************************************//**
|
||||
Looks for an element in a hash table.
|
||||
@return pointer to the data of the first hash table node in chain
|
||||
having the fold number, NULL if not found */
|
||||
UNIV_INLINE
|
||||
const rec_t*
|
||||
ha_search_and_get_data(
|
||||
/*===================*/
|
||||
hash_table_t* table, /*!< in: hash table */
|
||||
ulint fold); /*!< in: folded value of the searched data */
|
||||
/*********************************************************//**
|
||||
Looks for an element when we know the pointer to the data and updates
|
||||
the pointer to data if found.
|
||||
@return TRUE if found */
|
||||
UNIV_INTERN
|
||||
ibool
|
||||
ha_search_and_update_if_found_func(
|
||||
/*===============================*/
|
||||
hash_table_t* table, /*!< in/out: hash table */
|
||||
ulint fold, /*!< in: folded value of the searched data */
|
||||
const rec_t* data, /*!< in: pointer to the data */
|
||||
#if defined UNIV_AHI_DEBUG || defined UNIV_DEBUG
|
||||
buf_block_t* new_block,/*!< in: block containing new_data */
|
||||
#endif /* UNIV_AHI_DEBUG || UNIV_DEBUG */
|
||||
const rec_t* new_data);/*!< in: new pointer to the data */
|
||||
|
||||
#if defined UNIV_AHI_DEBUG || defined UNIV_DEBUG
|
||||
/** Looks for an element when we know the pointer to the data and
|
||||
updates the pointer to data if found.
|
||||
@param table in/out: hash table
|
||||
@param fold in: folded value of the searched data
|
||||
@param data in: pointer to the data
|
||||
@param new_block in: block containing new_data
|
||||
@param new_data in: new pointer to the data */
|
||||
# define ha_search_and_update_if_found(table,fold,data,new_block,new_data) \
|
||||
ha_search_and_update_if_found_func(table,fold,data,new_block,new_data)
|
||||
#else /* UNIV_AHI_DEBUG || UNIV_DEBUG */
|
||||
/** Looks for an element when we know the pointer to the data and
|
||||
updates the pointer to data if found.
|
||||
@param table in/out: hash table
|
||||
@param fold in: folded value of the searched data
|
||||
@param data in: pointer to the data
|
||||
@param new_block ignored: block containing new_data
|
||||
@param new_data in: new pointer to the data */
|
||||
# define ha_search_and_update_if_found(table,fold,data,new_block,new_data) \
|
||||
ha_search_and_update_if_found_func(table,fold,data,new_data)
|
||||
#endif /* UNIV_AHI_DEBUG || UNIV_DEBUG */
|
||||
/*************************************************************//**
|
||||
Creates a hash table with at least n array cells. The actual number
|
||||
of cells is chosen to be a prime number slightly bigger than n.
|
||||
@return own: created table */
|
||||
UNIV_INTERN
|
||||
hash_table_t*
|
||||
ha_create_func(
|
||||
/*===========*/
|
||||
ulint n, /*!< in: number of array cells */
|
||||
#ifdef UNIV_SYNC_DEBUG
|
||||
ulint mutex_level, /*!< in: level of the mutexes in the latching
|
||||
order: this is used in the debug version */
|
||||
#endif /* UNIV_SYNC_DEBUG */
|
||||
ulint n_mutexes, /*!< in: number of mutexes to protect the
|
||||
hash table: must be a power of 2, or 0 */
|
||||
ulint type); /*!< in: type of datastructure for which
|
||||
the memory heap is going to be used e.g.:
|
||||
MEM_HEAP_FOR_BTR_SEARCH or
|
||||
MEM_HEAP_FOR_PAGE_HASH */
|
||||
#ifdef UNIV_SYNC_DEBUG
|
||||
/** Creates a hash table.
|
||||
@return own: created table
|
||||
@param n_c in: number of array cells. The actual number of cells is
|
||||
chosen to be a slightly bigger prime number.
|
||||
@param level in: level of the mutexes in the latching order
|
||||
@param n_m in: number of mutexes to protect the hash table;
|
||||
must be a power of 2, or 0 */
|
||||
# define ha_create(n_c,n_m,type,level) ha_create_func(n_c,level,n_m,type)
|
||||
#else /* UNIV_SYNC_DEBUG */
|
||||
/** Creates a hash table.
|
||||
@return own: created table
|
||||
@param n_c in: number of array cells. The actual number of cells is
|
||||
chosen to be a slightly bigger prime number.
|
||||
@param level in: level of the mutexes in the latching order
|
||||
@param n_m in: number of mutexes to protect the hash table;
|
||||
must be a power of 2, or 0 */
|
||||
# define ha_create(n_c,n_m,type,level) ha_create_func(n_c,n_m,type)
|
||||
#endif /* UNIV_SYNC_DEBUG */
|
||||
|
||||
/*************************************************************//**
|
||||
Empties a hash table and frees the memory heaps. */
|
||||
UNIV_INTERN
|
||||
void
|
||||
ha_clear(
|
||||
/*=====*/
|
||||
hash_table_t* table); /*!< in, own: hash table */
|
||||
|
||||
/*************************************************************//**
|
||||
Inserts an entry into a hash table. If an entry with the same fold number
|
||||
is found, its node is updated to point to the new data, and no new node
|
||||
is inserted.
|
||||
@return TRUE if succeed, FALSE if no more memory could be allocated */
|
||||
UNIV_INTERN
|
||||
ibool
|
||||
ha_insert_for_fold_func(
|
||||
/*====================*/
|
||||
hash_table_t* table, /*!< in: hash table */
|
||||
ulint fold, /*!< in: folded value of data; if a node with
|
||||
the same fold value already exists, it is
|
||||
updated to point to the same data, and no new
|
||||
node is created! */
|
||||
#if defined UNIV_AHI_DEBUG || defined UNIV_DEBUG
|
||||
buf_block_t* block, /*!< in: buffer block containing the data */
|
||||
#endif /* UNIV_AHI_DEBUG || UNIV_DEBUG */
|
||||
const rec_t* data); /*!< in: data, must not be NULL */
|
||||
|
||||
#if defined UNIV_AHI_DEBUG || defined UNIV_DEBUG
|
||||
/**
|
||||
Inserts an entry into a hash table. If an entry with the same fold number
|
||||
is found, its node is updated to point to the new data, and no new node
|
||||
is inserted.
|
||||
@return TRUE if succeed, FALSE if no more memory could be allocated
|
||||
@param t in: hash table
|
||||
@param f in: folded value of data
|
||||
@param b in: buffer block containing the data
|
||||
@param d in: data, must not be NULL */
|
||||
# define ha_insert_for_fold(t,f,b,d) do { \
|
||||
ha_insert_for_fold_func(t,f,b,d); \
|
||||
MONITOR_INC(MONITOR_ADAPTIVE_HASH_ROW_ADDED); \
|
||||
} while(0)
|
||||
#else /* UNIV_AHI_DEBUG || UNIV_DEBUG */
|
||||
/**
|
||||
Inserts an entry into a hash table. If an entry with the same fold number
|
||||
is found, its node is updated to point to the new data, and no new node
|
||||
is inserted.
|
||||
@return TRUE if succeed, FALSE if no more memory could be allocated
|
||||
@param t in: hash table
|
||||
@param f in: folded value of data
|
||||
@param b ignored: buffer block containing the data
|
||||
@param d in: data, must not be NULL */
|
||||
# define ha_insert_for_fold(t,f,b,d) do { \
|
||||
ha_insert_for_fold_func(t,f,d); \
|
||||
MONITOR_INC(MONITOR_ADAPTIVE_HASH_ROW_ADDED); \
|
||||
} while (0)
|
||||
#endif /* UNIV_AHI_DEBUG || UNIV_DEBUG */
|
||||
|
||||
/*********************************************************//**
|
||||
Looks for an element when we know the pointer to the data and deletes
|
||||
it from the hash table if found.
|
||||
@return TRUE if found */
|
||||
UNIV_INLINE
|
||||
ibool
|
||||
ha_search_and_delete_if_found(
|
||||
/*==========================*/
|
||||
hash_table_t* table, /*!< in: hash table */
|
||||
ulint fold, /*!< in: folded value of the searched data */
|
||||
const rec_t* data); /*!< in: pointer to the data */
|
||||
#ifndef UNIV_HOTBACKUP
|
||||
/*****************************************************************//**
|
||||
Removes from the chain determined by fold all nodes whose data pointer
|
||||
points to the page given. */
|
||||
UNIV_INTERN
|
||||
void
|
||||
ha_remove_all_nodes_to_page(
|
||||
/*========================*/
|
||||
hash_table_t* table, /*!< in: hash table */
|
||||
ulint fold, /*!< in: fold value */
|
||||
const page_t* page); /*!< in: buffer page */
|
||||
#if defined UNIV_AHI_DEBUG || defined UNIV_DEBUG
|
||||
/*************************************************************//**
|
||||
Validates a given range of the cells in hash table.
|
||||
@return TRUE if ok */
|
||||
UNIV_INTERN
|
||||
ibool
|
||||
ha_validate(
|
||||
/*========*/
|
||||
hash_table_t* table, /*!< in: hash table */
|
||||
ulint start_index, /*!< in: start index */
|
||||
ulint end_index); /*!< in: end index */
|
||||
#endif /* defined UNIV_AHI_DEBUG || defined UNIV_DEBUG */
|
||||
/*************************************************************//**
|
||||
Prints info of a hash table. */
|
||||
UNIV_INTERN
|
||||
void
|
||||
ha_print_info(
|
||||
/*==========*/
|
||||
FILE* file, /*!< in: file where to print */
|
||||
hash_table_t* table); /*!< in: hash table */
|
||||
#endif /* !UNIV_HOTBACKUP */
|
||||
|
||||
/** The hash table external chain node */
|
||||
struct ha_node_t {
|
||||
ha_node_t* next; /*!< next chain node or NULL if none */
|
||||
#if defined UNIV_AHI_DEBUG || defined UNIV_DEBUG
|
||||
buf_block_t* block; /*!< buffer block containing the data, or NULL */
|
||||
#endif /* UNIV_AHI_DEBUG || UNIV_DEBUG */
|
||||
const rec_t* data; /*!< pointer to the data */
|
||||
ulint fold; /*!< fold value for the data */
|
||||
};
|
||||
|
||||
#ifdef UNIV_DEBUG
|
||||
/********************************************************************//**
|
||||
Assert that the synchronization object in a hash operation involving
|
||||
possible change in the hash table is held.
|
||||
Note that in case of mutexes we assert that mutex is owned while in case
|
||||
of rw-locks we assert that it is held in exclusive mode. */
|
||||
UNIV_INLINE
|
||||
void
|
||||
hash_assert_can_modify(
|
||||
/*===================*/
|
||||
hash_table_t* table, /*!< in: hash table */
|
||||
ulint fold); /*!< in: fold value */
|
||||
/********************************************************************//**
|
||||
Assert that the synchronization object in a hash search operation is held.
|
||||
Note that in case of mutexes we assert that mutex is owned while in case
|
||||
of rw-locks we assert that it is held either in x-mode or s-mode. */
|
||||
UNIV_INLINE
|
||||
void
|
||||
hash_assert_can_search(
|
||||
/*===================*/
|
||||
hash_table_t* table, /*!< in: hash table */
|
||||
ulint fold); /*!< in: fold value */
|
||||
#else /* UNIV_DEBUG */
|
||||
#define hash_assert_can_modify(t, f)
|
||||
#define hash_assert_can_search(t, f)
|
||||
#endif /* UNIV_DEBUG */
|
||||
|
||||
|
||||
#ifndef UNIV_NONINL
|
||||
#include "ha0ha.ic"
|
||||
#endif
|
||||
|
||||
#endif
|
||||
246
storage/innobase/include/ha0ha.ic
Normal file
246
storage/innobase/include/ha0ha.ic
Normal file
|
|
@ -0,0 +1,246 @@
|
|||
/*****************************************************************************
|
||||
|
||||
Copyright (c) 1994, 2011, Oracle and/or its affiliates. All Rights Reserved.
|
||||
|
||||
This program is free software; you can redistribute it and/or modify it under
|
||||
the terms of the GNU General Public License as published by the Free Software
|
||||
Foundation; version 2 of the License.
|
||||
|
||||
This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
|
||||
FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License along with
|
||||
this program; if not, write to the Free Software Foundation, Inc.,
|
||||
51 Franklin Street, Suite 500, Boston, MA 02110-1335 USA
|
||||
|
||||
*****************************************************************************/
|
||||
|
||||
/********************************************************************//**
|
||||
@file include/ha0ha.ic
|
||||
The hash table with external chains
|
||||
|
||||
Created 8/18/1994 Heikki Tuuri
|
||||
*************************************************************************/
|
||||
|
||||
#include "ut0rnd.h"
|
||||
#include "mem0mem.h"
|
||||
#include "btr0types.h"
|
||||
|
||||
/***********************************************************//**
|
||||
Deletes a hash node. */
|
||||
UNIV_INTERN
|
||||
void
|
||||
ha_delete_hash_node(
|
||||
/*================*/
|
||||
hash_table_t* table, /*!< in: hash table */
|
||||
ha_node_t* del_node); /*!< in: node to be deleted */
|
||||
|
||||
/******************************************************************//**
|
||||
Gets a hash node data.
|
||||
@return pointer to the data */
|
||||
UNIV_INLINE
|
||||
const rec_t*
|
||||
ha_node_get_data(
|
||||
/*=============*/
|
||||
const ha_node_t* node) /*!< in: hash chain node */
|
||||
{
|
||||
return(node->data);
|
||||
}
|
||||
|
||||
/******************************************************************//**
|
||||
Sets hash node data. */
|
||||
UNIV_INLINE
|
||||
void
|
||||
ha_node_set_data_func(
|
||||
/*==================*/
|
||||
ha_node_t* node, /*!< in: hash chain node */
|
||||
#if defined UNIV_AHI_DEBUG || defined UNIV_DEBUG
|
||||
buf_block_t* block, /*!< in: buffer block containing the data */
|
||||
#endif /* UNIV_AHI_DEBUG || UNIV_DEBUG */
|
||||
const rec_t* data) /*!< in: pointer to the data */
|
||||
{
|
||||
#if defined UNIV_AHI_DEBUG || defined UNIV_DEBUG
|
||||
node->block = block;
|
||||
#endif /* UNIV_AHI_DEBUG || UNIV_DEBUG */
|
||||
node->data = data;
|
||||
}
|
||||
|
||||
#if defined UNIV_AHI_DEBUG || defined UNIV_DEBUG
|
||||
/** Sets hash node data.
|
||||
@param n in: hash chain node
|
||||
@param b in: buffer block containing the data
|
||||
@param d in: pointer to the data */
|
||||
# define ha_node_set_data(n,b,d) ha_node_set_data_func(n,b,d)
|
||||
#else /* UNIV_AHI_DEBUG || UNIV_DEBUG */
|
||||
/** Sets hash node data.
|
||||
@param n in: hash chain node
|
||||
@param b in: buffer block containing the data
|
||||
@param d in: pointer to the data */
|
||||
# define ha_node_set_data(n,b,d) ha_node_set_data_func(n,d)
|
||||
#endif /* UNIV_AHI_DEBUG || UNIV_DEBUG */
|
||||
|
||||
/******************************************************************//**
|
||||
Gets the next node in a hash chain.
|
||||
@return next node, NULL if none */
|
||||
UNIV_INLINE
|
||||
ha_node_t*
|
||||
ha_chain_get_next(
|
||||
/*==============*/
|
||||
ha_node_t* node) /*!< in: hash chain node */
|
||||
{
|
||||
return(node->next);
|
||||
}
|
||||
|
||||
/******************************************************************//**
|
||||
Gets the first node in a hash chain.
|
||||
@return first node, NULL if none */
|
||||
UNIV_INLINE
|
||||
ha_node_t*
|
||||
ha_chain_get_first(
|
||||
/*===============*/
|
||||
hash_table_t* table, /*!< in: hash table */
|
||||
ulint fold) /*!< in: fold value determining the chain */
|
||||
{
|
||||
return((ha_node_t*)
|
||||
hash_get_nth_cell(table, hash_calc_hash(fold, table))->node);
|
||||
}
|
||||
|
||||
#ifdef UNIV_DEBUG
|
||||
/********************************************************************//**
|
||||
Assert that the synchronization object in a hash operation involving
|
||||
possible change in the hash table is held.
|
||||
Note that in case of mutexes we assert that mutex is owned while in case
|
||||
of rw-locks we assert that it is held in exclusive mode. */
|
||||
UNIV_INLINE
|
||||
void
|
||||
hash_assert_can_modify(
|
||||
/*===================*/
|
||||
hash_table_t* table, /*!< in: hash table */
|
||||
ulint fold) /*!< in: fold value */
|
||||
{
|
||||
if (table->type == HASH_TABLE_SYNC_MUTEX) {
|
||||
ut_ad(mutex_own(hash_get_mutex(table, fold)));
|
||||
} else if (table->type == HASH_TABLE_SYNC_RW_LOCK) {
|
||||
# ifdef UNIV_SYNC_DEBUG
|
||||
rw_lock_t* lock = hash_get_lock(table, fold);
|
||||
ut_ad(rw_lock_own(lock, RW_LOCK_EX));
|
||||
# endif
|
||||
} else {
|
||||
ut_ad(table->type == HASH_TABLE_SYNC_NONE);
|
||||
}
|
||||
}
|
||||
|
||||
/********************************************************************//**
|
||||
Assert that the synchronization object in a hash search operation is held.
|
||||
Note that in case of mutexes we assert that mutex is owned while in case
|
||||
of rw-locks we assert that it is held either in x-mode or s-mode. */
|
||||
UNIV_INLINE
|
||||
void
|
||||
hash_assert_can_search(
|
||||
/*===================*/
|
||||
hash_table_t* table, /*!< in: hash table */
|
||||
ulint fold) /*!< in: fold value */
|
||||
{
|
||||
if (table->type == HASH_TABLE_SYNC_MUTEX) {
|
||||
ut_ad(mutex_own(hash_get_mutex(table, fold)));
|
||||
} else if (table->type == HASH_TABLE_SYNC_RW_LOCK) {
|
||||
# ifdef UNIV_SYNC_DEBUG
|
||||
rw_lock_t* lock = hash_get_lock(table, fold);
|
||||
ut_ad(rw_lock_own(lock, RW_LOCK_EX)
|
||||
|| rw_lock_own(lock, RW_LOCK_SHARED));
|
||||
# endif
|
||||
} else {
|
||||
ut_ad(table->type == HASH_TABLE_SYNC_NONE);
|
||||
}
|
||||
}
|
||||
#endif /* UNIV_DEBUG */
|
||||
|
||||
/*************************************************************//**
|
||||
Looks for an element in a hash table.
|
||||
@return pointer to the data of the first hash table node in chain
|
||||
having the fold number, NULL if not found */
|
||||
UNIV_INLINE
|
||||
const rec_t*
|
||||
ha_search_and_get_data(
|
||||
/*===================*/
|
||||
hash_table_t* table, /*!< in: hash table */
|
||||
ulint fold) /*!< in: folded value of the searched data */
|
||||
{
|
||||
ha_node_t* node;
|
||||
|
||||
hash_assert_can_search(table, fold);
|
||||
ut_ad(btr_search_enabled);
|
||||
|
||||
node = ha_chain_get_first(table, fold);
|
||||
|
||||
while (node) {
|
||||
if (node->fold == fold) {
|
||||
|
||||
return(node->data);
|
||||
}
|
||||
|
||||
node = ha_chain_get_next(node);
|
||||
}
|
||||
|
||||
return(NULL);
|
||||
}
|
||||
|
||||
/*********************************************************//**
|
||||
Looks for an element when we know the pointer to the data.
|
||||
@return pointer to the hash table node, NULL if not found in the table */
|
||||
UNIV_INLINE
|
||||
ha_node_t*
|
||||
ha_search_with_data(
|
||||
/*================*/
|
||||
hash_table_t* table, /*!< in: hash table */
|
||||
ulint fold, /*!< in: folded value of the searched data */
|
||||
const rec_t* data) /*!< in: pointer to the data */
|
||||
{
|
||||
ha_node_t* node;
|
||||
|
||||
hash_assert_can_search(table, fold);
|
||||
|
||||
ut_ad(btr_search_enabled);
|
||||
|
||||
node = ha_chain_get_first(table, fold);
|
||||
|
||||
while (node) {
|
||||
if (node->data == data) {
|
||||
|
||||
return(node);
|
||||
}
|
||||
|
||||
node = ha_chain_get_next(node);
|
||||
}
|
||||
|
||||
return(NULL);
|
||||
}
|
||||
|
||||
/*********************************************************//**
|
||||
Looks for an element when we know the pointer to the data, and deletes
|
||||
it from the hash table, if found.
|
||||
@return TRUE if found */
|
||||
UNIV_INLINE
|
||||
ibool
|
||||
ha_search_and_delete_if_found(
|
||||
/*==========================*/
|
||||
hash_table_t* table, /*!< in: hash table */
|
||||
ulint fold, /*!< in: folded value of the searched data */
|
||||
const rec_t* data) /*!< in: pointer to the data */
|
||||
{
|
||||
ha_node_t* node;
|
||||
|
||||
hash_assert_can_modify(table, fold);
|
||||
ut_ad(btr_search_enabled);
|
||||
|
||||
node = ha_search_with_data(table, fold, data);
|
||||
|
||||
if (node) {
|
||||
ha_delete_hash_node(table, node);
|
||||
|
||||
return(TRUE);
|
||||
}
|
||||
|
||||
return(FALSE);
|
||||
}
|
||||
140
storage/innobase/include/ha0storage.h
Normal file
140
storage/innobase/include/ha0storage.h
Normal file
|
|
@ -0,0 +1,140 @@
|
|||
/*****************************************************************************
|
||||
|
||||
Copyright (c) 2007, 2009, Oracle and/or its affiliates. All Rights Reserved.
|
||||
|
||||
This program is free software; you can redistribute it and/or modify it under
|
||||
the terms of the GNU General Public License as published by the Free Software
|
||||
Foundation; version 2 of the License.
|
||||
|
||||
This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
|
||||
FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License along with
|
||||
this program; if not, write to the Free Software Foundation, Inc.,
|
||||
51 Franklin Street, Suite 500, Boston, MA 02110-1335 USA
|
||||
|
||||
*****************************************************************************/
|
||||
|
||||
/**************************************************//**
|
||||
@file include/ha0storage.h
|
||||
Hash storage.
|
||||
Provides a data structure that stores chunks of data in
|
||||
its own storage, avoiding duplicates.
|
||||
|
||||
Created September 22, 2007 Vasil Dimov
|
||||
*******************************************************/
|
||||
|
||||
#ifndef ha0storage_h
|
||||
#define ha0storage_h
|
||||
|
||||
#include "univ.i"
|
||||
|
||||
/** This value is used by default by ha_storage_create(). More memory
|
||||
is allocated later when/if it is needed. */
|
||||
#define HA_STORAGE_DEFAULT_HEAP_BYTES 1024
|
||||
|
||||
/** This value is used by default by ha_storage_create(). It is a
|
||||
constant per ha_storage's lifetime. */
|
||||
#define HA_STORAGE_DEFAULT_HASH_CELLS 4096
|
||||
|
||||
/** Hash storage */
|
||||
struct ha_storage_t;
|
||||
|
||||
/*******************************************************************//**
|
||||
Creates a hash storage. If any of the parameters is 0, then a default
|
||||
value is used.
|
||||
@return own: hash storage */
|
||||
UNIV_INLINE
|
||||
ha_storage_t*
|
||||
ha_storage_create(
|
||||
/*==============*/
|
||||
ulint initial_heap_bytes, /*!< in: initial heap's size */
|
||||
ulint initial_hash_cells); /*!< in: initial number of cells
|
||||
in the hash table */
|
||||
|
||||
/*******************************************************************//**
|
||||
Copies data into the storage and returns a pointer to the copy. If the
|
||||
same data chunk is already present, then pointer to it is returned.
|
||||
Data chunks are considered to be equal if len1 == len2 and
|
||||
memcmp(data1, data2, len1) == 0. If "data" is not present (and thus
|
||||
data_len bytes need to be allocated) and the size of storage is going to
|
||||
become more than "memlim" then "data" is not added and NULL is returned.
|
||||
To disable this behavior "memlim" can be set to 0, which stands for
|
||||
"no limit".
|
||||
@return pointer to the copy */
|
||||
UNIV_INTERN
|
||||
const void*
|
||||
ha_storage_put_memlim(
|
||||
/*==================*/
|
||||
ha_storage_t* storage, /*!< in/out: hash storage */
|
||||
const void* data, /*!< in: data to store */
|
||||
ulint data_len, /*!< in: data length */
|
||||
ulint memlim); /*!< in: memory limit to obey */
|
||||
|
||||
/*******************************************************************//**
|
||||
Same as ha_storage_put_memlim() but without memory limit.
|
||||
@param storage in/out: hash storage
|
||||
@param data in: data to store
|
||||
@param data_len in: data length
|
||||
@return pointer to the copy of the string */
|
||||
#define ha_storage_put(storage, data, data_len) \
|
||||
ha_storage_put_memlim((storage), (data), (data_len), 0)
|
||||
|
||||
/*******************************************************************//**
|
||||
Copies string into the storage and returns a pointer to the copy. If the
|
||||
same string is already present, then pointer to it is returned.
|
||||
Strings are considered to be equal if strcmp(str1, str2) == 0.
|
||||
@param storage in/out: hash storage
|
||||
@param str in: string to put
|
||||
@return pointer to the copy of the string */
|
||||
#define ha_storage_put_str(storage, str) \
|
||||
((const char*) ha_storage_put((storage), (str), strlen(str) + 1))
|
||||
|
||||
/*******************************************************************//**
|
||||
Copies string into the storage and returns a pointer to the copy obeying
|
||||
a memory limit.
|
||||
If the same string is already present, then pointer to it is returned.
|
||||
Strings are considered to be equal if strcmp(str1, str2) == 0.
|
||||
@param storage in/out: hash storage
|
||||
@param str in: string to put
|
||||
@param memlim in: memory limit to obey
|
||||
@return pointer to the copy of the string */
|
||||
#define ha_storage_put_str_memlim(storage, str, memlim) \
|
||||
((const char*) ha_storage_put_memlim((storage), (str), \
|
||||
strlen(str) + 1, (memlim)))
|
||||
|
||||
/*******************************************************************//**
|
||||
Empties a hash storage, freeing memory occupied by data chunks.
|
||||
This invalidates any pointers previously returned by ha_storage_put().
|
||||
The hash storage is not invalidated itself and can be used again. */
|
||||
UNIV_INLINE
|
||||
void
|
||||
ha_storage_empty(
|
||||
/*=============*/
|
||||
ha_storage_t** storage); /*!< in/out: hash storage */
|
||||
|
||||
/*******************************************************************//**
|
||||
Frees a hash storage and everything it contains, it cannot be used after
|
||||
this call.
|
||||
This invalidates any pointers previously returned by ha_storage_put(). */
|
||||
UNIV_INLINE
|
||||
void
|
||||
ha_storage_free(
|
||||
/*============*/
|
||||
ha_storage_t* storage); /*!< in, own: hash storage */
|
||||
|
||||
/*******************************************************************//**
|
||||
Gets the size of the memory used by a storage.
|
||||
@return bytes used */
|
||||
UNIV_INLINE
|
||||
ulint
|
||||
ha_storage_get_size(
|
||||
/*================*/
|
||||
const ha_storage_t* storage); /*!< in: hash storage */
|
||||
|
||||
#ifndef UNIV_NONINL
|
||||
#include "ha0storage.ic"
|
||||
#endif
|
||||
|
||||
#endif /* ha0storage_h */
|
||||
146
storage/innobase/include/ha0storage.ic
Normal file
146
storage/innobase/include/ha0storage.ic
Normal file
|
|
@ -0,0 +1,146 @@
|
|||
/*****************************************************************************
|
||||
|
||||
Copyright (c) 2007, 2009, Oracle and/or its affiliates. All Rights Reserved.
|
||||
|
||||
This program is free software; you can redistribute it and/or modify it under
|
||||
the terms of the GNU General Public License as published by the Free Software
|
||||
Foundation; version 2 of the License.
|
||||
|
||||
This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
|
||||
FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License along with
|
||||
this program; if not, write to the Free Software Foundation, Inc.,
|
||||
51 Franklin Street, Suite 500, Boston, MA 02110-1335 USA
|
||||
|
||||
*****************************************************************************/
|
||||
|
||||
/**************************************************//**
|
||||
@file include/ha0storage.ic
|
||||
Hash storage.
|
||||
Provides a data structure that stores chunks of data in
|
||||
its own storage, avoiding duplicates.
|
||||
|
||||
Created September 24, 2007 Vasil Dimov
|
||||
*******************************************************/
|
||||
|
||||
#include "univ.i"
|
||||
#include "ha0storage.h"
|
||||
#include "hash0hash.h"
|
||||
#include "mem0mem.h"
|
||||
|
||||
/** Hash storage for strings */
|
||||
struct ha_storage_t {
|
||||
mem_heap_t* heap; /*!< memory heap from which memory is
|
||||
allocated */
|
||||
hash_table_t* hash; /*!< hash table used to avoid
|
||||
duplicates */
|
||||
};
|
||||
|
||||
/** Objects of this type are stored in ha_storage_t */
|
||||
struct ha_storage_node_t {
|
||||
ulint data_len;/*!< length of the data */
|
||||
const void* data; /*!< pointer to data */
|
||||
ha_storage_node_t* next; /*!< next node in hash chain */
|
||||
};
|
||||
|
||||
/*******************************************************************//**
|
||||
Creates a hash storage. If any of the parameters is 0, then a default
|
||||
value is used.
|
||||
@return own: hash storage */
|
||||
UNIV_INLINE
|
||||
ha_storage_t*
|
||||
ha_storage_create(
|
||||
/*==============*/
|
||||
ulint initial_heap_bytes, /*!< in: initial heap's size */
|
||||
ulint initial_hash_cells) /*!< in: initial number of cells
|
||||
in the hash table */
|
||||
{
|
||||
ha_storage_t* storage;
|
||||
mem_heap_t* heap;
|
||||
|
||||
if (initial_heap_bytes == 0) {
|
||||
|
||||
initial_heap_bytes = HA_STORAGE_DEFAULT_HEAP_BYTES;
|
||||
}
|
||||
|
||||
if (initial_hash_cells == 0) {
|
||||
|
||||
initial_hash_cells = HA_STORAGE_DEFAULT_HASH_CELLS;
|
||||
}
|
||||
|
||||
/* we put "storage" within "storage->heap" */
|
||||
|
||||
heap = mem_heap_create(sizeof(ha_storage_t)
|
||||
+ initial_heap_bytes);
|
||||
|
||||
storage = (ha_storage_t*) mem_heap_alloc(heap,
|
||||
sizeof(ha_storage_t));
|
||||
|
||||
storage->heap = heap;
|
||||
storage->hash = hash_create(initial_hash_cells);
|
||||
|
||||
return(storage);
|
||||
}
|
||||
|
||||
/*******************************************************************//**
|
||||
Empties a hash storage, freeing memory occupied by data chunks.
|
||||
This invalidates any pointers previously returned by ha_storage_put().
|
||||
The hash storage is not invalidated itself and can be used again. */
|
||||
UNIV_INLINE
|
||||
void
|
||||
ha_storage_empty(
|
||||
/*=============*/
|
||||
ha_storage_t** storage) /*!< in/out: hash storage */
|
||||
{
|
||||
ha_storage_t temp_storage;
|
||||
|
||||
temp_storage.heap = (*storage)->heap;
|
||||
temp_storage.hash = (*storage)->hash;
|
||||
|
||||
hash_table_clear(temp_storage.hash);
|
||||
mem_heap_empty(temp_storage.heap);
|
||||
|
||||
*storage = (ha_storage_t*) mem_heap_alloc(temp_storage.heap,
|
||||
sizeof(ha_storage_t));
|
||||
|
||||
(*storage)->heap = temp_storage.heap;
|
||||
(*storage)->hash = temp_storage.hash;
|
||||
}
|
||||
|
||||
/*******************************************************************//**
|
||||
Frees a hash storage and everything it contains, it cannot be used after
|
||||
this call.
|
||||
This invalidates any pointers previously returned by ha_storage_put(). */
|
||||
UNIV_INLINE
|
||||
void
|
||||
ha_storage_free(
|
||||
/*============*/
|
||||
ha_storage_t* storage) /*!< in, own: hash storage */
|
||||
{
|
||||
/* order is important because the pointer storage->hash is
|
||||
within the heap */
|
||||
hash_table_free(storage->hash);
|
||||
mem_heap_free(storage->heap);
|
||||
}
|
||||
|
||||
/*******************************************************************//**
|
||||
Gets the size of the memory used by a storage.
|
||||
@return bytes used */
|
||||
UNIV_INLINE
|
||||
ulint
|
||||
ha_storage_get_size(
|
||||
/*================*/
|
||||
const ha_storage_t* storage) /*!< in: hash storage */
|
||||
{
|
||||
ulint ret;
|
||||
|
||||
ret = mem_heap_get_size(storage->heap);
|
||||
|
||||
/* this assumes hash->heap and hash->heaps are NULL */
|
||||
ret += sizeof(hash_table_t);
|
||||
ret += sizeof(hash_cell_t) * hash_get_n_cells(storage->hash);
|
||||
|
||||
return(ret);
|
||||
}
|
||||
596
storage/innobase/include/ha_prototypes.h
Normal file
596
storage/innobase/include/ha_prototypes.h
Normal file
|
|
@ -0,0 +1,596 @@
|
|||
/*****************************************************************************
|
||||
|
||||
Copyright (c) 2006, 2014, Oracle and/or its affiliates. All Rights Reserved.
|
||||
|
||||
This program is free software; you can redistribute it and/or modify it under
|
||||
the terms of the GNU General Public License as published by the Free Software
|
||||
Foundation; version 2 of the License.
|
||||
|
||||
This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
|
||||
FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License along with
|
||||
this program; if not, write to the Free Software Foundation, Inc.,
|
||||
51 Franklin Street, Suite 500, Boston, MA 02110-1335 USA
|
||||
|
||||
*****************************************************************************/
|
||||
|
||||
/*******************************************************************//**
|
||||
@file include/ha_prototypes.h
|
||||
Prototypes for global functions in ha_innodb.cc that are called by
|
||||
InnoDB C code
|
||||
|
||||
Created 5/11/2006 Osku Salerma
|
||||
************************************************************************/
|
||||
|
||||
#ifndef HA_INNODB_PROTOTYPES_H
|
||||
#define HA_INNODB_PROTOTYPES_H
|
||||
|
||||
#include "my_dbug.h"
|
||||
#include "mysqld_error.h"
|
||||
#include "my_compare.h"
|
||||
#include "my_sys.h"
|
||||
#include "m_string.h"
|
||||
#include "debug_sync.h"
|
||||
|
||||
#include "trx0types.h"
|
||||
#include "m_ctype.h" /* CHARSET_INFO */
|
||||
|
||||
// Forward declarations
|
||||
class Field;
|
||||
struct fts_string_t;
|
||||
|
||||
/*********************************************************************//**
|
||||
Wrapper around MySQL's copy_and_convert function.
|
||||
@return number of bytes copied to 'to' */
|
||||
UNIV_INTERN
|
||||
ulint
|
||||
innobase_convert_string(
|
||||
/*====================*/
|
||||
void* to, /*!< out: converted string */
|
||||
ulint to_length, /*!< in: number of bytes reserved
|
||||
for the converted string */
|
||||
CHARSET_INFO* to_cs, /*!< in: character set to convert to */
|
||||
const void* from, /*!< in: string to convert */
|
||||
ulint from_length, /*!< in: number of bytes to convert */
|
||||
CHARSET_INFO* from_cs, /*!< in: character set to convert
|
||||
from */
|
||||
uint* errors); /*!< out: number of errors encountered
|
||||
during the conversion */
|
||||
|
||||
/*******************************************************************//**
|
||||
Formats the raw data in "data" (in InnoDB on-disk format) that is of
|
||||
type DATA_(CHAR|VARCHAR|MYSQL|VARMYSQL) using "charset_coll" and writes
|
||||
the result to "buf". The result is converted to "system_charset_info".
|
||||
Not more than "buf_size" bytes are written to "buf".
|
||||
The result is always NUL-terminated (provided buf_size > 0) and the
|
||||
number of bytes that were written to "buf" is returned (including the
|
||||
terminating NUL).
|
||||
@return number of bytes that were written */
|
||||
UNIV_INTERN
|
||||
ulint
|
||||
innobase_raw_format(
|
||||
/*================*/
|
||||
const char* data, /*!< in: raw data */
|
||||
ulint data_len, /*!< in: raw data length
|
||||
in bytes */
|
||||
ulint charset_coll, /*!< in: charset collation */
|
||||
char* buf, /*!< out: output buffer */
|
||||
ulint buf_size); /*!< in: output buffer size
|
||||
in bytes */
|
||||
|
||||
/*****************************************************************//**
|
||||
Invalidates the MySQL query cache for the table. */
|
||||
UNIV_INTERN
|
||||
void
|
||||
innobase_invalidate_query_cache(
|
||||
/*============================*/
|
||||
trx_t* trx, /*!< in: transaction which
|
||||
modifies the table */
|
||||
const char* full_name, /*!< in: concatenation of
|
||||
database name, null char NUL,
|
||||
table name, null char NUL;
|
||||
NOTE that in Windows this is
|
||||
always in LOWER CASE! */
|
||||
ulint full_name_len); /*!< in: full name length where
|
||||
also the null chars count */
|
||||
|
||||
/*****************************************************************//**
|
||||
Convert a table or index name to the MySQL system_charset_info (UTF-8)
|
||||
and quote it if needed.
|
||||
@return pointer to the end of buf */
|
||||
UNIV_INTERN
|
||||
char*
|
||||
innobase_convert_name(
|
||||
/*==================*/
|
||||
char* buf, /*!< out: buffer for converted identifier */
|
||||
ulint buflen, /*!< in: length of buf, in bytes */
|
||||
const char* id, /*!< in: identifier to convert */
|
||||
ulint idlen, /*!< in: length of id, in bytes */
|
||||
THD* thd, /*!< in: MySQL connection thread, or NULL */
|
||||
ibool table_id);/*!< in: TRUE=id is a table or database name;
|
||||
FALSE=id is an index name */
|
||||
|
||||
/******************************************************************//**
|
||||
Returns true if the thread is the replication thread on the slave
|
||||
server. Used in srv_conc_enter_innodb() to determine if the thread
|
||||
should be allowed to enter InnoDB - the replication thread is treated
|
||||
differently than other threads. Also used in
|
||||
srv_conc_force_exit_innodb().
|
||||
@return true if thd is the replication thread */
|
||||
UNIV_INTERN
|
||||
ibool
|
||||
thd_is_replication_slave_thread(
|
||||
/*============================*/
|
||||
THD* thd); /*!< in: thread handle */
|
||||
|
||||
/******************************************************************//**
|
||||
Gets information on the durability property requested by thread.
|
||||
Used when writing either a prepare or commit record to the log
|
||||
buffer.
|
||||
@return the durability property. */
|
||||
UNIV_INTERN
|
||||
enum durability_properties
|
||||
thd_requested_durability(
|
||||
/*=====================*/
|
||||
const THD* thd) /*!< in: thread handle */
|
||||
__attribute__((nonnull, warn_unused_result));
|
||||
|
||||
/******************************************************************//**
|
||||
Returns true if the transaction this thread is processing has edited
|
||||
non-transactional tables. Used by the deadlock detector when deciding
|
||||
which transaction to rollback in case of a deadlock - we try to avoid
|
||||
rolling back transactions that have edited non-transactional tables.
|
||||
@return true if non-transactional tables have been edited */
|
||||
UNIV_INTERN
|
||||
ibool
|
||||
thd_has_edited_nontrans_tables(
|
||||
/*===========================*/
|
||||
THD* thd); /*!< in: thread handle */
|
||||
|
||||
/*************************************************************//**
|
||||
Prints info of a THD object (== user session thread) to the given file. */
|
||||
UNIV_INTERN
|
||||
void
|
||||
innobase_mysql_print_thd(
|
||||
/*=====================*/
|
||||
FILE* f, /*!< in: output stream */
|
||||
THD* thd, /*!< in: pointer to a MySQL THD object */
|
||||
uint max_query_len); /*!< in: max query length to print, or 0 to
|
||||
use the default max length */
|
||||
|
||||
/*************************************************************//**
|
||||
InnoDB uses this function to compare two data fields for which the data type
|
||||
is such that we must use MySQL code to compare them.
|
||||
@return 1, 0, -1, if a is greater, equal, less than b, respectively */
|
||||
UNIV_INTERN
|
||||
int
|
||||
innobase_mysql_cmp(
|
||||
/*===============*/
|
||||
int mysql_type, /*!< in: MySQL type */
|
||||
uint charset_number, /*!< in: number of the charset */
|
||||
const unsigned char* a, /*!< in: data field */
|
||||
unsigned int a_length, /*!< in: data field length,
|
||||
not UNIV_SQL_NULL */
|
||||
const unsigned char* b, /*!< in: data field */
|
||||
unsigned int b_length) /*!< in: data field length,
|
||||
not UNIV_SQL_NULL */
|
||||
__attribute__((nonnull, warn_unused_result));
|
||||
/**************************************************************//**
|
||||
Converts a MySQL type to an InnoDB type. Note that this function returns
|
||||
the 'mtype' of InnoDB. InnoDB differentiates between MySQL's old <= 4.1
|
||||
VARCHAR and the new true VARCHAR in >= 5.0.3 by the 'prtype'.
|
||||
@return DATA_BINARY, DATA_VARCHAR, ... */
|
||||
UNIV_INTERN
|
||||
ulint
|
||||
get_innobase_type_from_mysql_type(
|
||||
/*==============================*/
|
||||
ulint* unsigned_flag, /*!< out: DATA_UNSIGNED if an
|
||||
'unsigned type';
|
||||
at least ENUM and SET,
|
||||
and unsigned integer
|
||||
types are 'unsigned types' */
|
||||
const void* field) /*!< in: MySQL Field */
|
||||
__attribute__((nonnull));
|
||||
|
||||
/******************************************************************//**
|
||||
Get the variable length bounds of the given character set. */
|
||||
UNIV_INTERN
|
||||
void
|
||||
innobase_get_cset_width(
|
||||
/*====================*/
|
||||
ulint cset, /*!< in: MySQL charset-collation code */
|
||||
ulint* mbminlen, /*!< out: minimum length of a char (in bytes) */
|
||||
ulint* mbmaxlen); /*!< out: maximum length of a char (in bytes) */
|
||||
|
||||
/******************************************************************//**
|
||||
Compares NUL-terminated UTF-8 strings case insensitively.
|
||||
@return 0 if a=b, <0 if a<b, >1 if a>b */
|
||||
UNIV_INTERN
|
||||
int
|
||||
innobase_strcasecmp(
|
||||
/*================*/
|
||||
const char* a, /*!< in: first string to compare */
|
||||
const char* b); /*!< in: second string to compare */
|
||||
|
||||
/******************************************************************//**
|
||||
Compares NUL-terminated UTF-8 strings case insensitively. The
|
||||
second string contains wildcards.
|
||||
@return 0 if a match is found, 1 if not */
|
||||
UNIV_INTERN
|
||||
int
|
||||
innobase_wildcasecmp(
|
||||
/*=================*/
|
||||
const char* a, /*!< in: string to compare */
|
||||
const char* b); /*!< in: wildcard string to compare */
|
||||
|
||||
/******************************************************************//**
|
||||
Strip dir name from a full path name and return only its file name.
|
||||
@return file name or "null" if no file name */
|
||||
UNIV_INTERN
|
||||
const char*
|
||||
innobase_basename(
|
||||
/*==============*/
|
||||
const char* path_name); /*!< in: full path name */
|
||||
|
||||
/******************************************************************//**
|
||||
Returns true if the thread is executing a SELECT statement.
|
||||
@return true if thd is executing SELECT */
|
||||
UNIV_INTERN
|
||||
ibool
|
||||
thd_is_select(
|
||||
/*==========*/
|
||||
const THD* thd); /*!< in: thread handle */
|
||||
|
||||
/******************************************************************//**
|
||||
Converts an identifier to a table name. */
|
||||
UNIV_INTERN
|
||||
void
|
||||
innobase_convert_from_table_id(
|
||||
/*===========================*/
|
||||
struct charset_info_st* cs, /*!< in: the 'from' character set */
|
||||
char* to, /*!< out: converted identifier */
|
||||
const char* from, /*!< in: identifier to convert */
|
||||
ulint len); /*!< in: length of 'to', in bytes; should
|
||||
be at least 5 * strlen(to) + 1 */
|
||||
/******************************************************************//**
|
||||
Converts an identifier to UTF-8. */
|
||||
UNIV_INTERN
|
||||
void
|
||||
innobase_convert_from_id(
|
||||
/*=====================*/
|
||||
struct charset_info_st* cs, /*!< in: the 'from' character set */
|
||||
char* to, /*!< out: converted identifier */
|
||||
const char* from, /*!< in: identifier to convert */
|
||||
ulint len); /*!< in: length of 'to', in bytes;
|
||||
should be at least 3 * strlen(to) + 1 */
|
||||
/******************************************************************//**
|
||||
Makes all characters in a NUL-terminated UTF-8 string lower case. */
|
||||
UNIV_INTERN
|
||||
void
|
||||
innobase_casedn_str(
|
||||
/*================*/
|
||||
char* a); /*!< in/out: string to put in lower case */
|
||||
|
||||
/**********************************************************************//**
|
||||
Determines the connection character set.
|
||||
@return connection character set */
|
||||
UNIV_INTERN
|
||||
struct charset_info_st*
|
||||
innobase_get_charset(
|
||||
/*=================*/
|
||||
THD* thd); /*!< in: MySQL thread handle */
|
||||
/**********************************************************************//**
|
||||
Determines the current SQL statement.
|
||||
@return SQL statement string */
|
||||
UNIV_INTERN
|
||||
const char*
|
||||
innobase_get_stmt(
|
||||
/*==============*/
|
||||
THD* thd, /*!< in: MySQL thread handle */
|
||||
size_t* length) /*!< out: length of the SQL statement */
|
||||
__attribute__((nonnull));
|
||||
/******************************************************************//**
|
||||
This function is used to find the storage length in bytes of the first n
|
||||
characters for prefix indexes using a multibyte character set. The function
|
||||
finds charset information and returns length of prefix_len characters in the
|
||||
index field in bytes.
|
||||
@return number of bytes occupied by the first n characters */
|
||||
UNIV_INTERN
|
||||
ulint
|
||||
innobase_get_at_most_n_mbchars(
|
||||
/*===========================*/
|
||||
ulint charset_id, /*!< in: character set id */
|
||||
ulint prefix_len, /*!< in: prefix length in bytes of the index
|
||||
(this has to be divided by mbmaxlen to get the
|
||||
number of CHARACTERS n in the prefix) */
|
||||
ulint data_len, /*!< in: length of the string in bytes */
|
||||
const char* str); /*!< in: character string */
|
||||
|
||||
/*************************************************************//**
|
||||
InnoDB index push-down condition check
|
||||
@return ICP_NO_MATCH, ICP_MATCH, or ICP_OUT_OF_RANGE */
|
||||
UNIV_INTERN
|
||||
enum icp_result
|
||||
innobase_index_cond(
|
||||
/*================*/
|
||||
void* file) /*!< in/out: pointer to ha_innobase */
|
||||
__attribute__((nonnull, warn_unused_result));
|
||||
/******************************************************************//**
|
||||
Returns true if the thread supports XA,
|
||||
global value of innodb_supports_xa if thd is NULL.
|
||||
@return true if thd supports XA */
|
||||
UNIV_INTERN
|
||||
ibool
|
||||
thd_supports_xa(
|
||||
/*============*/
|
||||
THD* thd); /*!< in: thread handle, or NULL to query
|
||||
the global innodb_supports_xa */
|
||||
|
||||
/******************************************************************//**
|
||||
Returns the lock wait timeout for the current connection.
|
||||
@return the lock wait timeout, in seconds */
|
||||
UNIV_INTERN
|
||||
ulong
|
||||
thd_lock_wait_timeout(
|
||||
/*==================*/
|
||||
THD* thd); /*!< in: thread handle, or NULL to query
|
||||
the global innodb_lock_wait_timeout */
|
||||
/******************************************************************//**
|
||||
Add up the time waited for the lock for the current query. */
|
||||
UNIV_INTERN
|
||||
void
|
||||
thd_set_lock_wait_time(
|
||||
/*===================*/
|
||||
THD* thd, /*!< in/out: thread handle */
|
||||
ulint value); /*!< in: time waited for the lock */
|
||||
|
||||
/**********************************************************************//**
|
||||
Get the current setting of the table_cache_size global parameter. We do
|
||||
a dirty read because for one there is no synchronization object and
|
||||
secondly there is little harm in doing so even if we get a torn read.
|
||||
@return SQL statement string */
|
||||
UNIV_INTERN
|
||||
ulint
|
||||
innobase_get_table_cache_size(void);
|
||||
/*===============================*/
|
||||
|
||||
/**********************************************************************//**
|
||||
Get the current setting of the lower_case_table_names global parameter from
|
||||
mysqld.cc. We do a dirty read because for one there is no synchronization
|
||||
object and secondly there is little harm in doing so even if we get a torn
|
||||
read.
|
||||
@return value of lower_case_table_names */
|
||||
UNIV_INTERN
|
||||
ulint
|
||||
innobase_get_lower_case_table_names(void);
|
||||
/*=====================================*/
|
||||
|
||||
/*****************************************************************//**
|
||||
Frees a possible InnoDB trx object associated with the current THD.
|
||||
@return 0 or error number */
|
||||
UNIV_INTERN
|
||||
int
|
||||
innobase_close_thd(
|
||||
/*===============*/
|
||||
THD* thd); /*!< in: MySQL thread handle for
|
||||
which to close the connection */
|
||||
/*************************************************************//**
|
||||
Get the next token from the given string and store it in *token. */
|
||||
UNIV_INTERN
|
||||
ulint
|
||||
innobase_mysql_fts_get_token(
|
||||
/*=========================*/
|
||||
CHARSET_INFO* charset, /*!< in: Character set */
|
||||
const byte* start, /*!< in: start of text */
|
||||
const byte* end, /*!< in: one character past end of
|
||||
text */
|
||||
fts_string_t* token, /*!< out: token's text */
|
||||
ulint* offset); /*!< out: offset to token,
|
||||
measured as characters from
|
||||
'start' */
|
||||
|
||||
/******************************************************************//**
|
||||
compare two character string case insensitively according to their charset. */
|
||||
UNIV_INTERN
|
||||
int
|
||||
innobase_fts_text_case_cmp(
|
||||
/*=======================*/
|
||||
const void* cs, /*!< in: Character set */
|
||||
const void* p1, /*!< in: key */
|
||||
const void* p2); /*!< in: node */
|
||||
|
||||
/****************************************************************//**
|
||||
Get FTS field charset info from the field's prtype
|
||||
@return charset info */
|
||||
UNIV_INTERN
|
||||
CHARSET_INFO*
|
||||
innobase_get_fts_charset(
|
||||
/*=====================*/
|
||||
int mysql_type, /*!< in: MySQL type */
|
||||
uint charset_number);/*!< in: number of the charset */
|
||||
/******************************************************************//**
|
||||
Returns true if transaction should be flagged as read-only.
|
||||
@return true if the thd is marked as read-only */
|
||||
UNIV_INTERN
|
||||
ibool
|
||||
thd_trx_is_read_only(
|
||||
/*=================*/
|
||||
THD* thd); /*!< in/out: thread handle */
|
||||
|
||||
/******************************************************************//**
|
||||
Check if the transaction is an auto-commit transaction. TRUE also
|
||||
implies that it is a SELECT (read-only) transaction.
|
||||
@return true if the transaction is an auto commit read-only transaction. */
|
||||
UNIV_INTERN
|
||||
ibool
|
||||
thd_trx_is_auto_commit(
|
||||
/*===================*/
|
||||
THD* thd); /*!< in: thread handle, or NULL */
|
||||
|
||||
/*****************************************************************//**
|
||||
A wrapper function of innobase_convert_name(), convert a table or
|
||||
index name to the MySQL system_charset_info (UTF-8) and quote it if needed.
|
||||
@return pointer to the end of buf */
|
||||
UNIV_INTERN
|
||||
void
|
||||
innobase_format_name(
|
||||
/*==================*/
|
||||
char* buf, /*!< out: buffer for converted
|
||||
identifier */
|
||||
ulint buflen, /*!< in: length of buf, in bytes */
|
||||
const char* name, /*!< in: index or table name
|
||||
to format */
|
||||
ibool is_index_name) /*!< in: index name */
|
||||
__attribute__((nonnull));
|
||||
|
||||
/** Corresponds to Sql_condition:enum_warning_level. */
|
||||
enum ib_log_level_t {
|
||||
IB_LOG_LEVEL_INFO,
|
||||
IB_LOG_LEVEL_WARN,
|
||||
IB_LOG_LEVEL_ERROR,
|
||||
IB_LOG_LEVEL_FATAL
|
||||
};
|
||||
|
||||
/******************************************************************//**
|
||||
Use this when the args are first converted to a formatted string and then
|
||||
passed to the format string from errmsg-utf8.txt. The error message format
|
||||
must be: "Some string ... %s".
|
||||
|
||||
Push a warning message to the client, it is a wrapper around:
|
||||
|
||||
void push_warning_printf(
|
||||
THD *thd, Sql_condition::enum_warning_level level,
|
||||
uint code, const char *format, ...);
|
||||
*/
|
||||
UNIV_INTERN
|
||||
void
|
||||
ib_errf(
|
||||
/*====*/
|
||||
THD* thd, /*!< in/out: session */
|
||||
ib_log_level_t level, /*!< in: warning level */
|
||||
ib_uint32_t code, /*!< MySQL error code */
|
||||
const char* format, /*!< printf format */
|
||||
...) /*!< Args */
|
||||
__attribute__((format(printf, 4, 5)));
|
||||
|
||||
/******************************************************************//**
|
||||
Use this when the args are passed to the format string from
|
||||
errmsg-utf8.txt directly as is.
|
||||
|
||||
Push a warning message to the client, it is a wrapper around:
|
||||
|
||||
void push_warning_printf(
|
||||
THD *thd, Sql_condition::enum_warning_level level,
|
||||
uint code, const char *format, ...);
|
||||
*/
|
||||
UNIV_INTERN
|
||||
void
|
||||
ib_senderrf(
|
||||
/*========*/
|
||||
THD* thd, /*!< in/out: session */
|
||||
ib_log_level_t level, /*!< in: warning level */
|
||||
ib_uint32_t code, /*!< MySQL error code */
|
||||
...); /*!< Args */
|
||||
|
||||
/******************************************************************//**
|
||||
Write a message to the MySQL log, prefixed with "InnoDB: ".
|
||||
Wrapper around sql_print_information() */
|
||||
UNIV_INTERN
|
||||
void
|
||||
ib_logf(
|
||||
/*====*/
|
||||
ib_log_level_t level, /*!< in: warning level */
|
||||
const char* format, /*!< printf format */
|
||||
...) /*!< Args */
|
||||
__attribute__((format(printf, 2, 3)));
|
||||
|
||||
/******************************************************************//**
|
||||
Returns the NUL terminated value of glob_hostname.
|
||||
@return pointer to glob_hostname. */
|
||||
UNIV_INTERN
|
||||
const char*
|
||||
server_get_hostname();
|
||||
/*=================*/
|
||||
|
||||
/******************************************************************//**
|
||||
Get the error message format string.
|
||||
@return the format string or 0 if not found. */
|
||||
UNIV_INTERN
|
||||
const char*
|
||||
innobase_get_err_msg(
|
||||
/*=================*/
|
||||
int error_code); /*!< in: MySQL error code */
|
||||
|
||||
/*********************************************************************//**
|
||||
Compute the next autoinc value.
|
||||
|
||||
For MySQL replication the autoincrement values can be partitioned among
|
||||
the nodes. The offset is the start or origin of the autoincrement value
|
||||
for a particular node. For n nodes the increment will be n and the offset
|
||||
will be in the interval [1, n]. The formula tries to allocate the next
|
||||
value for a particular node.
|
||||
|
||||
Note: This function is also called with increment set to the number of
|
||||
values we want to reserve for multi-value inserts e.g.,
|
||||
|
||||
INSERT INTO T VALUES(), (), ();
|
||||
|
||||
innobase_next_autoinc() will be called with increment set to 3 where
|
||||
autoinc_lock_mode != TRADITIONAL because we want to reserve 3 values for
|
||||
the multi-value INSERT above.
|
||||
@return the next value */
|
||||
UNIV_INTERN
|
||||
ulonglong
|
||||
innobase_next_autoinc(
|
||||
/*==================*/
|
||||
ulonglong current, /*!< in: Current value */
|
||||
ulonglong need, /*!< in: count of values needed */
|
||||
ulonglong step, /*!< in: AUTOINC increment step */
|
||||
ulonglong offset, /*!< in: AUTOINC offset */
|
||||
ulonglong max_value) /*!< in: max value for type */
|
||||
__attribute__((pure, warn_unused_result));
|
||||
|
||||
/********************************************************************//**
|
||||
Get the upper limit of the MySQL integral and floating-point type.
|
||||
@return maximum allowed value for the field */
|
||||
UNIV_INTERN
|
||||
ulonglong
|
||||
innobase_get_int_col_max_value(
|
||||
/*===========================*/
|
||||
const Field* field) /*!< in: MySQL field */
|
||||
__attribute__((nonnull, pure, warn_unused_result));
|
||||
|
||||
/**********************************************************************
|
||||
Check if the length of the identifier exceeds the maximum allowed.
|
||||
The input to this function is an identifier in charset my_charset_filename.
|
||||
return true when length of identifier is too long. */
|
||||
UNIV_INTERN
|
||||
my_bool
|
||||
innobase_check_identifier_length(
|
||||
/*=============================*/
|
||||
const char* id); /* in: identifier to check. it must belong
|
||||
to charset my_charset_filename */
|
||||
|
||||
/**********************************************************************
|
||||
Converts an identifier from my_charset_filename to UTF-8 charset. */
|
||||
uint
|
||||
innobase_convert_to_system_charset(
|
||||
/*===============================*/
|
||||
char* to, /* out: converted identifier */
|
||||
const char* from, /* in: identifier to convert */
|
||||
ulint len, /* in: length of 'to', in bytes */
|
||||
uint* errors); /* out: error return */
|
||||
|
||||
/**********************************************************************
|
||||
Converts an identifier from my_charset_filename to UTF-8 charset. */
|
||||
uint
|
||||
innobase_convert_to_filename_charset(
|
||||
/*=================================*/
|
||||
char* to, /* out: converted identifier */
|
||||
const char* from, /* in: identifier to convert */
|
||||
ulint len); /* in: length of 'to', in bytes */
|
||||
|
||||
|
||||
#endif /* HA_INNODB_PROTOTYPES_H */
|
||||
114
storage/innobase/include/handler0alter.h
Normal file
114
storage/innobase/include/handler0alter.h
Normal file
|
|
@ -0,0 +1,114 @@
|
|||
/*****************************************************************************
|
||||
|
||||
Copyright (c) 2005, 2013, Oracle and/or its affiliates. All Rights Reserved.
|
||||
|
||||
This program is free software; you can redistribute it and/or modify it under
|
||||
the terms of the GNU General Public License as published by the Free Software
|
||||
Foundation; version 2 of the License.
|
||||
|
||||
This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
|
||||
FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License along with
|
||||
this program; if not, write to the Free Software Foundation, Inc.,
|
||||
51 Franklin Street, Suite 500, Boston, MA 02110-1335 USA
|
||||
|
||||
*****************************************************************************/
|
||||
|
||||
/**************************************************//**
|
||||
@file include/handler0alter.h
|
||||
Smart ALTER TABLE
|
||||
*******************************************************/
|
||||
|
||||
/*************************************************************//**
|
||||
Copies an InnoDB record to table->record[0]. */
|
||||
UNIV_INTERN
|
||||
void
|
||||
innobase_rec_to_mysql(
|
||||
/*==================*/
|
||||
struct TABLE* table, /*!< in/out: MySQL table */
|
||||
const rec_t* rec, /*!< in: record */
|
||||
const dict_index_t* index, /*!< in: index */
|
||||
const ulint* offsets)/*!< in: rec_get_offsets(
|
||||
rec, index, ...) */
|
||||
__attribute__((nonnull));
|
||||
|
||||
/*************************************************************//**
|
||||
Copies an InnoDB index entry to table->record[0]. */
|
||||
UNIV_INTERN
|
||||
void
|
||||
innobase_fields_to_mysql(
|
||||
/*=====================*/
|
||||
struct TABLE* table, /*!< in/out: MySQL table */
|
||||
const dict_index_t* index, /*!< in: InnoDB index */
|
||||
const dfield_t* fields) /*!< in: InnoDB index fields */
|
||||
__attribute__((nonnull));
|
||||
|
||||
/*************************************************************//**
|
||||
Copies an InnoDB row to table->record[0]. */
|
||||
UNIV_INTERN
|
||||
void
|
||||
innobase_row_to_mysql(
|
||||
/*==================*/
|
||||
struct TABLE* table, /*!< in/out: MySQL table */
|
||||
const dict_table_t* itab, /*!< in: InnoDB table */
|
||||
const dtuple_t* row) /*!< in: InnoDB row */
|
||||
__attribute__((nonnull));
|
||||
|
||||
/*************************************************************//**
|
||||
Resets table->record[0]. */
|
||||
UNIV_INTERN
|
||||
void
|
||||
innobase_rec_reset(
|
||||
/*===============*/
|
||||
struct TABLE* table) /*!< in/out: MySQL table */
|
||||
__attribute__((nonnull));
|
||||
|
||||
/** Generate the next autoinc based on a snapshot of the session
|
||||
auto_increment_increment and auto_increment_offset variables. */
|
||||
struct ib_sequence_t {
|
||||
|
||||
/**
|
||||
@param thd - the session
|
||||
@param start_value - the lower bound
|
||||
@param max_value - the upper bound (inclusive) */
|
||||
ib_sequence_t(THD* thd, ulonglong start_value, ulonglong max_value);
|
||||
|
||||
/**
|
||||
Postfix increment
|
||||
@return the value to insert */
|
||||
ulonglong operator++(int) UNIV_NOTHROW;
|
||||
|
||||
/** Check if the autoinc "sequence" is exhausted.
|
||||
@return true if the sequence is exhausted */
|
||||
bool eof() const UNIV_NOTHROW
|
||||
{
|
||||
return(m_eof);
|
||||
}
|
||||
|
||||
/**
|
||||
@return the next value in the sequence */
|
||||
ulonglong last() const UNIV_NOTHROW
|
||||
{
|
||||
ut_ad(m_next_value > 0);
|
||||
|
||||
return(m_next_value);
|
||||
}
|
||||
|
||||
/** Maximum calumn value if adding an AUTOINC column else 0. Once
|
||||
we reach the end of the sequence it will be set to ~0. */
|
||||
const ulonglong m_max_value;
|
||||
|
||||
/** Value of auto_increment_increment */
|
||||
ulong m_increment;
|
||||
|
||||
/** Value of auto_increment_offset */
|
||||
ulong m_offset;
|
||||
|
||||
/** Next value in the sequence */
|
||||
ulonglong m_next_value;
|
||||
|
||||
/** true if no more values left in the sequence */
|
||||
bool m_eof;
|
||||
};
|
||||
575
storage/innobase/include/hash0hash.h
Normal file
575
storage/innobase/include/hash0hash.h
Normal file
|
|
@ -0,0 +1,575 @@
|
|||
/*****************************************************************************
|
||||
|
||||
Copyright (c) 1997, 2011, Oracle and/or its affiliates. All Rights Reserved.
|
||||
|
||||
This program is free software; you can redistribute it and/or modify it under
|
||||
the terms of the GNU General Public License as published by the Free Software
|
||||
Foundation; version 2 of the License.
|
||||
|
||||
This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
|
||||
FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License along with
|
||||
this program; if not, write to the Free Software Foundation, Inc.,
|
||||
51 Franklin Street, Suite 500, Boston, MA 02110-1335 USA
|
||||
|
||||
*****************************************************************************/
|
||||
|
||||
/**************************************************//**
|
||||
@file include/hash0hash.h
|
||||
The simple hash table utility
|
||||
|
||||
Created 5/20/1997 Heikki Tuuri
|
||||
*******************************************************/
|
||||
|
||||
#ifndef hash0hash_h
|
||||
#define hash0hash_h
|
||||
|
||||
#include "univ.i"
|
||||
#include "mem0mem.h"
|
||||
#ifndef UNIV_HOTBACKUP
|
||||
# include "sync0sync.h"
|
||||
# include "sync0rw.h"
|
||||
#endif /* !UNIV_HOTBACKUP */
|
||||
|
||||
struct hash_table_t;
|
||||
struct hash_cell_t;
|
||||
|
||||
typedef void* hash_node_t;
|
||||
|
||||
/* Fix Bug #13859: symbol collision between imap/mysql */
|
||||
#define hash_create hash0_create
|
||||
|
||||
/* Differnt types of hash_table based on the synchronization
|
||||
method used for it. */
|
||||
enum hash_table_sync_t {
|
||||
HASH_TABLE_SYNC_NONE = 0, /*!< Don't use any internal
|
||||
synchronization objects for
|
||||
this hash_table. */
|
||||
HASH_TABLE_SYNC_MUTEX, /*!< Use mutexes to control
|
||||
access to this hash_table. */
|
||||
HASH_TABLE_SYNC_RW_LOCK /*!< Use rw_locks to control
|
||||
access to this hash_table. */
|
||||
};
|
||||
|
||||
/*************************************************************//**
|
||||
Creates a hash table with >= n array cells. The actual number
|
||||
of cells is chosen to be a prime number slightly bigger than n.
|
||||
@return own: created table */
|
||||
UNIV_INTERN
|
||||
hash_table_t*
|
||||
hash_create(
|
||||
/*========*/
|
||||
ulint n); /*!< in: number of array cells */
|
||||
#ifndef UNIV_HOTBACKUP
|
||||
/*************************************************************//**
|
||||
Creates a sync object array array to protect a hash table.
|
||||
::sync_obj can be mutexes or rw_locks depening on the type of
|
||||
hash table. */
|
||||
UNIV_INTERN
|
||||
void
|
||||
hash_create_sync_obj_func(
|
||||
/*======================*/
|
||||
hash_table_t* table, /*!< in: hash table */
|
||||
enum hash_table_sync_t type, /*!< in: HASH_TABLE_SYNC_MUTEX
|
||||
or HASH_TABLE_SYNC_RW_LOCK */
|
||||
#ifdef UNIV_SYNC_DEBUG
|
||||
ulint sync_level,/*!< in: latching order level
|
||||
of the mutexes: used in the
|
||||
debug version */
|
||||
#endif /* UNIV_SYNC_DEBUG */
|
||||
ulint n_sync_obj);/*!< in: number of sync objects,
|
||||
must be a power of 2 */
|
||||
#ifdef UNIV_SYNC_DEBUG
|
||||
# define hash_create_sync_obj(t, s, n, level) \
|
||||
hash_create_sync_obj_func(t, s, level, n)
|
||||
#else /* UNIV_SYNC_DEBUG */
|
||||
# define hash_create_sync_obj(t, s, n, level) \
|
||||
hash_create_sync_obj_func(t, s, n)
|
||||
#endif /* UNIV_SYNC_DEBUG */
|
||||
#endif /* !UNIV_HOTBACKUP */
|
||||
|
||||
/*************************************************************//**
|
||||
Frees a hash table. */
|
||||
UNIV_INTERN
|
||||
void
|
||||
hash_table_free(
|
||||
/*============*/
|
||||
hash_table_t* table); /*!< in, own: hash table */
|
||||
/**************************************************************//**
|
||||
Calculates the hash value from a folded value.
|
||||
@return hashed value */
|
||||
UNIV_INLINE
|
||||
ulint
|
||||
hash_calc_hash(
|
||||
/*===========*/
|
||||
ulint fold, /*!< in: folded value */
|
||||
hash_table_t* table); /*!< in: hash table */
|
||||
#ifndef UNIV_HOTBACKUP
|
||||
/********************************************************************//**
|
||||
Assert that the mutex for the table is held */
|
||||
# define HASH_ASSERT_OWN(TABLE, FOLD) \
|
||||
ut_ad((TABLE)->type != HASH_TABLE_SYNC_MUTEX \
|
||||
|| (mutex_own(hash_get_mutex((TABLE), FOLD))));
|
||||
#else /* !UNIV_HOTBACKUP */
|
||||
# define HASH_ASSERT_OWN(TABLE, FOLD)
|
||||
#endif /* !UNIV_HOTBACKUP */
|
||||
|
||||
/*******************************************************************//**
|
||||
Inserts a struct to a hash table. */
|
||||
|
||||
#define HASH_INSERT(TYPE, NAME, TABLE, FOLD, DATA)\
|
||||
do {\
|
||||
hash_cell_t* cell3333;\
|
||||
TYPE* struct3333;\
|
||||
\
|
||||
HASH_ASSERT_OWN(TABLE, FOLD)\
|
||||
\
|
||||
(DATA)->NAME = NULL;\
|
||||
\
|
||||
cell3333 = hash_get_nth_cell(TABLE, hash_calc_hash(FOLD, TABLE));\
|
||||
\
|
||||
if (cell3333->node == NULL) {\
|
||||
cell3333->node = DATA;\
|
||||
} else {\
|
||||
struct3333 = (TYPE*) cell3333->node;\
|
||||
\
|
||||
while (struct3333->NAME != NULL) {\
|
||||
\
|
||||
struct3333 = (TYPE*) struct3333->NAME;\
|
||||
}\
|
||||
\
|
||||
struct3333->NAME = DATA;\
|
||||
}\
|
||||
} while (0)
|
||||
|
||||
#ifdef UNIV_HASH_DEBUG
|
||||
# define HASH_ASSERT_VALID(DATA) ut_a((void*) (DATA) != (void*) -1)
|
||||
# define HASH_INVALIDATE(DATA, NAME) *(void**) (&DATA->NAME) = (void*) -1
|
||||
#else
|
||||
# define HASH_ASSERT_VALID(DATA) do {} while (0)
|
||||
# define HASH_INVALIDATE(DATA, NAME) do {} while (0)
|
||||
#endif
|
||||
|
||||
/*******************************************************************//**
|
||||
Deletes a struct from a hash table. */
|
||||
|
||||
#define HASH_DELETE(TYPE, NAME, TABLE, FOLD, DATA)\
|
||||
do {\
|
||||
hash_cell_t* cell3333;\
|
||||
TYPE* struct3333;\
|
||||
\
|
||||
HASH_ASSERT_OWN(TABLE, FOLD)\
|
||||
\
|
||||
cell3333 = hash_get_nth_cell(TABLE, hash_calc_hash(FOLD, TABLE));\
|
||||
\
|
||||
if (cell3333->node == DATA) {\
|
||||
HASH_ASSERT_VALID(DATA->NAME);\
|
||||
cell3333->node = DATA->NAME;\
|
||||
} else {\
|
||||
struct3333 = (TYPE*) cell3333->node;\
|
||||
\
|
||||
while (struct3333->NAME != DATA) {\
|
||||
\
|
||||
struct3333 = (TYPE*) struct3333->NAME;\
|
||||
ut_a(struct3333);\
|
||||
}\
|
||||
\
|
||||
struct3333->NAME = DATA->NAME;\
|
||||
}\
|
||||
HASH_INVALIDATE(DATA, NAME);\
|
||||
} while (0)
|
||||
|
||||
/*******************************************************************//**
|
||||
Gets the first struct in a hash chain, NULL if none. */
|
||||
|
||||
#define HASH_GET_FIRST(TABLE, HASH_VAL)\
|
||||
(hash_get_nth_cell(TABLE, HASH_VAL)->node)
|
||||
|
||||
/*******************************************************************//**
|
||||
Gets the next struct in a hash chain, NULL if none. */
|
||||
|
||||
#define HASH_GET_NEXT(NAME, DATA) ((DATA)->NAME)
|
||||
|
||||
/********************************************************************//**
|
||||
Looks for a struct in a hash table. */
|
||||
#define HASH_SEARCH(NAME, TABLE, FOLD, TYPE, DATA, ASSERTION, TEST)\
|
||||
{\
|
||||
\
|
||||
HASH_ASSERT_OWN(TABLE, FOLD)\
|
||||
\
|
||||
(DATA) = (TYPE) HASH_GET_FIRST(TABLE, hash_calc_hash(FOLD, TABLE));\
|
||||
HASH_ASSERT_VALID(DATA);\
|
||||
\
|
||||
while ((DATA) != NULL) {\
|
||||
ASSERTION;\
|
||||
if (TEST) {\
|
||||
break;\
|
||||
} else {\
|
||||
HASH_ASSERT_VALID(HASH_GET_NEXT(NAME, DATA));\
|
||||
(DATA) = (TYPE) HASH_GET_NEXT(NAME, DATA);\
|
||||
}\
|
||||
}\
|
||||
}
|
||||
|
||||
/********************************************************************//**
|
||||
Looks for an item in all hash buckets. */
|
||||
#define HASH_SEARCH_ALL(NAME, TABLE, TYPE, DATA, ASSERTION, TEST) \
|
||||
do { \
|
||||
ulint i3333; \
|
||||
\
|
||||
for (i3333 = (TABLE)->n_cells; i3333--; ) { \
|
||||
(DATA) = (TYPE) HASH_GET_FIRST(TABLE, i3333); \
|
||||
\
|
||||
while ((DATA) != NULL) { \
|
||||
HASH_ASSERT_VALID(DATA); \
|
||||
ASSERTION; \
|
||||
\
|
||||
if (TEST) { \
|
||||
break; \
|
||||
} \
|
||||
\
|
||||
(DATA) = (TYPE) HASH_GET_NEXT(NAME, DATA); \
|
||||
} \
|
||||
\
|
||||
if ((DATA) != NULL) { \
|
||||
break; \
|
||||
} \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
/************************************************************//**
|
||||
Gets the nth cell in a hash table.
|
||||
@return pointer to cell */
|
||||
UNIV_INLINE
|
||||
hash_cell_t*
|
||||
hash_get_nth_cell(
|
||||
/*==============*/
|
||||
hash_table_t* table, /*!< in: hash table */
|
||||
ulint n); /*!< in: cell index */
|
||||
|
||||
/*************************************************************//**
|
||||
Clears a hash table so that all the cells become empty. */
|
||||
UNIV_INLINE
|
||||
void
|
||||
hash_table_clear(
|
||||
/*=============*/
|
||||
hash_table_t* table); /*!< in/out: hash table */
|
||||
|
||||
/*************************************************************//**
|
||||
Returns the number of cells in a hash table.
|
||||
@return number of cells */
|
||||
UNIV_INLINE
|
||||
ulint
|
||||
hash_get_n_cells(
|
||||
/*=============*/
|
||||
hash_table_t* table); /*!< in: table */
|
||||
/*******************************************************************//**
|
||||
Deletes a struct which is stored in the heap of the hash table, and compacts
|
||||
the heap. The fold value must be stored in the struct NODE in a field named
|
||||
'fold'. */
|
||||
|
||||
#define HASH_DELETE_AND_COMPACT(TYPE, NAME, TABLE, NODE)\
|
||||
do {\
|
||||
TYPE* node111;\
|
||||
TYPE* top_node111;\
|
||||
hash_cell_t* cell111;\
|
||||
ulint fold111;\
|
||||
\
|
||||
fold111 = (NODE)->fold;\
|
||||
\
|
||||
HASH_DELETE(TYPE, NAME, TABLE, fold111, NODE);\
|
||||
\
|
||||
top_node111 = (TYPE*) mem_heap_get_top(\
|
||||
hash_get_heap(TABLE, fold111),\
|
||||
sizeof(TYPE));\
|
||||
\
|
||||
/* If the node to remove is not the top node in the heap, compact the\
|
||||
heap of nodes by moving the top node in the place of NODE. */\
|
||||
\
|
||||
if (NODE != top_node111) {\
|
||||
\
|
||||
/* Copy the top node in place of NODE */\
|
||||
\
|
||||
*(NODE) = *top_node111;\
|
||||
\
|
||||
cell111 = hash_get_nth_cell(TABLE,\
|
||||
hash_calc_hash(top_node111->fold, TABLE));\
|
||||
\
|
||||
/* Look for the pointer to the top node, to update it */\
|
||||
\
|
||||
if (cell111->node == top_node111) {\
|
||||
/* The top node is the first in the chain */\
|
||||
\
|
||||
cell111->node = NODE;\
|
||||
} else {\
|
||||
/* We have to look for the predecessor of the top\
|
||||
node */\
|
||||
node111 = static_cast<TYPE*>(cell111->node);\
|
||||
\
|
||||
while (top_node111 != HASH_GET_NEXT(NAME, node111)) {\
|
||||
\
|
||||
node111 = static_cast<TYPE*>(\
|
||||
HASH_GET_NEXT(NAME, node111));\
|
||||
}\
|
||||
\
|
||||
/* Now we have the predecessor node */\
|
||||
\
|
||||
node111->NAME = NODE;\
|
||||
}\
|
||||
}\
|
||||
\
|
||||
/* Free the space occupied by the top node */\
|
||||
\
|
||||
mem_heap_free_top(hash_get_heap(TABLE, fold111), sizeof(TYPE));\
|
||||
} while (0)
|
||||
|
||||
#ifndef UNIV_HOTBACKUP
|
||||
/****************************************************************//**
|
||||
Move all hash table entries from OLD_TABLE to NEW_TABLE. */
|
||||
|
||||
#define HASH_MIGRATE(OLD_TABLE, NEW_TABLE, NODE_TYPE, PTR_NAME, FOLD_FUNC) \
|
||||
do {\
|
||||
ulint i2222;\
|
||||
ulint cell_count2222;\
|
||||
\
|
||||
cell_count2222 = hash_get_n_cells(OLD_TABLE);\
|
||||
\
|
||||
for (i2222 = 0; i2222 < cell_count2222; i2222++) {\
|
||||
NODE_TYPE* node2222 = HASH_GET_FIRST((OLD_TABLE), i2222);\
|
||||
\
|
||||
while (node2222) {\
|
||||
NODE_TYPE* next2222 = node2222->PTR_NAME;\
|
||||
ulint fold2222 = FOLD_FUNC(node2222);\
|
||||
\
|
||||
HASH_INSERT(NODE_TYPE, PTR_NAME, (NEW_TABLE),\
|
||||
fold2222, node2222);\
|
||||
\
|
||||
node2222 = next2222;\
|
||||
}\
|
||||
}\
|
||||
} while (0)
|
||||
|
||||
/************************************************************//**
|
||||
Gets the sync object index for a fold value in a hash table.
|
||||
@return index */
|
||||
UNIV_INLINE
|
||||
ulint
|
||||
hash_get_sync_obj_index(
|
||||
/*====================*/
|
||||
hash_table_t* table, /*!< in: hash table */
|
||||
ulint fold); /*!< in: fold */
|
||||
/************************************************************//**
|
||||
Gets the nth heap in a hash table.
|
||||
@return mem heap */
|
||||
UNIV_INLINE
|
||||
mem_heap_t*
|
||||
hash_get_nth_heap(
|
||||
/*==============*/
|
||||
hash_table_t* table, /*!< in: hash table */
|
||||
ulint i); /*!< in: index of the heap */
|
||||
/************************************************************//**
|
||||
Gets the heap for a fold value in a hash table.
|
||||
@return mem heap */
|
||||
UNIV_INLINE
|
||||
mem_heap_t*
|
||||
hash_get_heap(
|
||||
/*==========*/
|
||||
hash_table_t* table, /*!< in: hash table */
|
||||
ulint fold); /*!< in: fold */
|
||||
/************************************************************//**
|
||||
Gets the nth mutex in a hash table.
|
||||
@return mutex */
|
||||
UNIV_INLINE
|
||||
ib_mutex_t*
|
||||
hash_get_nth_mutex(
|
||||
/*===============*/
|
||||
hash_table_t* table, /*!< in: hash table */
|
||||
ulint i); /*!< in: index of the mutex */
|
||||
/************************************************************//**
|
||||
Gets the nth rw_lock in a hash table.
|
||||
@return rw_lock */
|
||||
UNIV_INLINE
|
||||
rw_lock_t*
|
||||
hash_get_nth_lock(
|
||||
/*==============*/
|
||||
hash_table_t* table, /*!< in: hash table */
|
||||
ulint i); /*!< in: index of the rw_lock */
|
||||
/************************************************************//**
|
||||
Gets the mutex for a fold value in a hash table.
|
||||
@return mutex */
|
||||
UNIV_INLINE
|
||||
ib_mutex_t*
|
||||
hash_get_mutex(
|
||||
/*===========*/
|
||||
hash_table_t* table, /*!< in: hash table */
|
||||
ulint fold); /*!< in: fold */
|
||||
/************************************************************//**
|
||||
Gets the rw_lock for a fold value in a hash table.
|
||||
@return rw_lock */
|
||||
UNIV_INLINE
|
||||
rw_lock_t*
|
||||
hash_get_lock(
|
||||
/*==========*/
|
||||
hash_table_t* table, /*!< in: hash table */
|
||||
ulint fold); /*!< in: fold */
|
||||
/************************************************************//**
|
||||
Reserves the mutex for a fold value in a hash table. */
|
||||
UNIV_INTERN
|
||||
void
|
||||
hash_mutex_enter(
|
||||
/*=============*/
|
||||
hash_table_t* table, /*!< in: hash table */
|
||||
ulint fold); /*!< in: fold */
|
||||
/************************************************************//**
|
||||
Releases the mutex for a fold value in a hash table. */
|
||||
UNIV_INTERN
|
||||
void
|
||||
hash_mutex_exit(
|
||||
/*============*/
|
||||
hash_table_t* table, /*!< in: hash table */
|
||||
ulint fold); /*!< in: fold */
|
||||
/************************************************************//**
|
||||
Reserves all the mutexes of a hash table, in an ascending order. */
|
||||
UNIV_INTERN
|
||||
void
|
||||
hash_mutex_enter_all(
|
||||
/*=================*/
|
||||
hash_table_t* table); /*!< in: hash table */
|
||||
/************************************************************//**
|
||||
Releases all the mutexes of a hash table. */
|
||||
UNIV_INTERN
|
||||
void
|
||||
hash_mutex_exit_all(
|
||||
/*================*/
|
||||
hash_table_t* table); /*!< in: hash table */
|
||||
/************************************************************//**
|
||||
Releases all but the passed in mutex of a hash table. */
|
||||
UNIV_INTERN
|
||||
void
|
||||
hash_mutex_exit_all_but(
|
||||
/*====================*/
|
||||
hash_table_t* table, /*!< in: hash table */
|
||||
ib_mutex_t* keep_mutex); /*!< in: mutex to keep */
|
||||
/************************************************************//**
|
||||
s-lock a lock for a fold value in a hash table. */
|
||||
UNIV_INTERN
|
||||
void
|
||||
hash_lock_s(
|
||||
/*========*/
|
||||
hash_table_t* table, /*!< in: hash table */
|
||||
ulint fold); /*!< in: fold */
|
||||
/************************************************************//**
|
||||
x-lock a lock for a fold value in a hash table. */
|
||||
UNIV_INTERN
|
||||
void
|
||||
hash_lock_x(
|
||||
/*========*/
|
||||
hash_table_t* table, /*!< in: hash table */
|
||||
ulint fold); /*!< in: fold */
|
||||
/************************************************************//**
|
||||
unlock an s-lock for a fold value in a hash table. */
|
||||
UNIV_INTERN
|
||||
void
|
||||
hash_unlock_s(
|
||||
/*==========*/
|
||||
|
||||
hash_table_t* table, /*!< in: hash table */
|
||||
ulint fold); /*!< in: fold */
|
||||
/************************************************************//**
|
||||
unlock x-lock for a fold value in a hash table. */
|
||||
UNIV_INTERN
|
||||
void
|
||||
hash_unlock_x(
|
||||
/*==========*/
|
||||
hash_table_t* table, /*!< in: hash table */
|
||||
ulint fold); /*!< in: fold */
|
||||
/************************************************************//**
|
||||
Reserves all the locks of a hash table, in an ascending order. */
|
||||
UNIV_INTERN
|
||||
void
|
||||
hash_lock_x_all(
|
||||
/*============*/
|
||||
hash_table_t* table); /*!< in: hash table */
|
||||
/************************************************************//**
|
||||
Releases all the locks of a hash table, in an ascending order. */
|
||||
UNIV_INTERN
|
||||
void
|
||||
hash_unlock_x_all(
|
||||
/*==============*/
|
||||
hash_table_t* table); /*!< in: hash table */
|
||||
/************************************************************//**
|
||||
Releases all but passed in lock of a hash table, */
|
||||
UNIV_INTERN
|
||||
void
|
||||
hash_unlock_x_all_but(
|
||||
/*==================*/
|
||||
hash_table_t* table, /*!< in: hash table */
|
||||
rw_lock_t* keep_lock); /*!< in: lock to keep */
|
||||
|
||||
#else /* !UNIV_HOTBACKUP */
|
||||
# define hash_get_heap(table, fold) ((table)->heap)
|
||||
# define hash_mutex_enter(table, fold) ((void) 0)
|
||||
# define hash_mutex_exit(table, fold) ((void) 0)
|
||||
# define hash_mutex_enter_all(table) ((void) 0)
|
||||
# define hash_mutex_exit_all(table) ((void) 0)
|
||||
# define hash_mutex_exit_all_but(t, m) ((void) 0)
|
||||
# define hash_lock_s(t, f) ((void) 0)
|
||||
# define hash_lock_x(t, f) ((void) 0)
|
||||
# define hash_unlock_s(t, f) ((void) 0)
|
||||
# define hash_unlock_x(t, f) ((void) 0)
|
||||
# define hash_lock_x_all(t) ((void) 0)
|
||||
# define hash_unlock_x_all(t) ((void) 0)
|
||||
# define hash_unlock_x_all_but(t, l) ((void) 0)
|
||||
#endif /* !UNIV_HOTBACKUP */
|
||||
|
||||
struct hash_cell_t{
|
||||
void* node; /*!< hash chain node, NULL if none */
|
||||
};
|
||||
|
||||
/* The hash table structure */
|
||||
struct hash_table_t {
|
||||
enum hash_table_sync_t type; /*<! type of hash_table. */
|
||||
#if defined UNIV_AHI_DEBUG || defined UNIV_DEBUG
|
||||
# ifndef UNIV_HOTBACKUP
|
||||
ibool adaptive;/* TRUE if this is the hash
|
||||
table of the adaptive hash
|
||||
index */
|
||||
# endif /* !UNIV_HOTBACKUP */
|
||||
#endif /* UNIV_AHI_DEBUG || UNIV_DEBUG */
|
||||
ulint n_cells;/* number of cells in the hash table */
|
||||
hash_cell_t* array; /*!< pointer to cell array */
|
||||
#ifndef UNIV_HOTBACKUP
|
||||
ulint n_sync_obj;/* if sync_objs != NULL, then
|
||||
the number of either the number
|
||||
of mutexes or the number of
|
||||
rw_locks depending on the type.
|
||||
Must be a power of 2 */
|
||||
union {
|
||||
ib_mutex_t* mutexes;/* NULL, or an array of mutexes
|
||||
used to protect segments of the
|
||||
hash table */
|
||||
rw_lock_t* rw_locks;/* NULL, or an array of rw_lcoks
|
||||
used to protect segments of the
|
||||
hash table */
|
||||
} sync_obj;
|
||||
|
||||
mem_heap_t** heaps; /*!< if this is non-NULL, hash
|
||||
chain nodes for external chaining
|
||||
can be allocated from these memory
|
||||
heaps; there are then n_mutexes
|
||||
many of these heaps */
|
||||
#endif /* !UNIV_HOTBACKUP */
|
||||
mem_heap_t* heap;
|
||||
#ifdef UNIV_DEBUG
|
||||
ulint magic_n;
|
||||
# define HASH_TABLE_MAGIC_N 76561114
|
||||
#endif /* UNIV_DEBUG */
|
||||
};
|
||||
|
||||
#ifndef UNIV_NONINL
|
||||
#include "hash0hash.ic"
|
||||
#endif
|
||||
|
||||
#endif
|
||||
225
storage/innobase/include/hash0hash.ic
Normal file
225
storage/innobase/include/hash0hash.ic
Normal file
|
|
@ -0,0 +1,225 @@
|
|||
/*****************************************************************************
|
||||
|
||||
Copyright (c) 1997, 2009, Oracle and/or its affiliates. All Rights Reserved.
|
||||
|
||||
This program is free software; you can redistribute it and/or modify it under
|
||||
the terms of the GNU General Public License as published by the Free Software
|
||||
Foundation; version 2 of the License.
|
||||
|
||||
This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
|
||||
FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License along with
|
||||
this program; if not, write to the Free Software Foundation, Inc.,
|
||||
51 Franklin Street, Suite 500, Boston, MA 02110-1335 USA
|
||||
|
||||
*****************************************************************************/
|
||||
|
||||
/**************************************************//**
|
||||
@file include/hash0hash.ic
|
||||
The simple hash table utility
|
||||
|
||||
Created 5/20/1997 Heikki Tuuri
|
||||
*******************************************************/
|
||||
|
||||
#include "ut0rnd.h"
|
||||
|
||||
/************************************************************//**
|
||||
Gets the nth cell in a hash table.
|
||||
@return pointer to cell */
|
||||
UNIV_INLINE
|
||||
hash_cell_t*
|
||||
hash_get_nth_cell(
|
||||
/*==============*/
|
||||
hash_table_t* table, /*!< in: hash table */
|
||||
ulint n) /*!< in: cell index */
|
||||
{
|
||||
ut_ad(table);
|
||||
ut_ad(table->magic_n == HASH_TABLE_MAGIC_N);
|
||||
ut_ad(n < table->n_cells);
|
||||
|
||||
return(table->array + n);
|
||||
}
|
||||
|
||||
/*************************************************************//**
|
||||
Clears a hash table so that all the cells become empty. */
|
||||
UNIV_INLINE
|
||||
void
|
||||
hash_table_clear(
|
||||
/*=============*/
|
||||
hash_table_t* table) /*!< in/out: hash table */
|
||||
{
|
||||
ut_ad(table);
|
||||
ut_ad(table->magic_n == HASH_TABLE_MAGIC_N);
|
||||
memset(table->array, 0x0,
|
||||
table->n_cells * sizeof(*table->array));
|
||||
}
|
||||
|
||||
/*************************************************************//**
|
||||
Returns the number of cells in a hash table.
|
||||
@return number of cells */
|
||||
UNIV_INLINE
|
||||
ulint
|
||||
hash_get_n_cells(
|
||||
/*=============*/
|
||||
hash_table_t* table) /*!< in: table */
|
||||
{
|
||||
ut_ad(table);
|
||||
ut_ad(table->magic_n == HASH_TABLE_MAGIC_N);
|
||||
return(table->n_cells);
|
||||
}
|
||||
|
||||
/**************************************************************//**
|
||||
Calculates the hash value from a folded value.
|
||||
@return hashed value */
|
||||
UNIV_INLINE
|
||||
ulint
|
||||
hash_calc_hash(
|
||||
/*===========*/
|
||||
ulint fold, /*!< in: folded value */
|
||||
hash_table_t* table) /*!< in: hash table */
|
||||
{
|
||||
ut_ad(table);
|
||||
ut_ad(table->magic_n == HASH_TABLE_MAGIC_N);
|
||||
return(ut_hash_ulint(fold, table->n_cells));
|
||||
}
|
||||
|
||||
#ifndef UNIV_HOTBACKUP
|
||||
/************************************************************//**
|
||||
Gets the sync object index for a fold value in a hash table.
|
||||
@return index */
|
||||
UNIV_INLINE
|
||||
ulint
|
||||
hash_get_sync_obj_index(
|
||||
/*====================*/
|
||||
hash_table_t* table, /*!< in: hash table */
|
||||
ulint fold) /*!< in: fold */
|
||||
{
|
||||
ut_ad(table);
|
||||
ut_ad(table->magic_n == HASH_TABLE_MAGIC_N);
|
||||
ut_ad(table->type != HASH_TABLE_SYNC_NONE);
|
||||
ut_ad(ut_is_2pow(table->n_sync_obj));
|
||||
return(ut_2pow_remainder(hash_calc_hash(fold, table),
|
||||
table->n_sync_obj));
|
||||
}
|
||||
|
||||
/************************************************************//**
|
||||
Gets the nth heap in a hash table.
|
||||
@return mem heap */
|
||||
UNIV_INLINE
|
||||
mem_heap_t*
|
||||
hash_get_nth_heap(
|
||||
/*==============*/
|
||||
hash_table_t* table, /*!< in: hash table */
|
||||
ulint i) /*!< in: index of the heap */
|
||||
{
|
||||
ut_ad(table);
|
||||
ut_ad(table->magic_n == HASH_TABLE_MAGIC_N);
|
||||
ut_ad(table->type != HASH_TABLE_SYNC_NONE);
|
||||
ut_ad(i < table->n_sync_obj);
|
||||
|
||||
return(table->heaps[i]);
|
||||
}
|
||||
|
||||
/************************************************************//**
|
||||
Gets the heap for a fold value in a hash table.
|
||||
@return mem heap */
|
||||
UNIV_INLINE
|
||||
mem_heap_t*
|
||||
hash_get_heap(
|
||||
/*==========*/
|
||||
hash_table_t* table, /*!< in: hash table */
|
||||
ulint fold) /*!< in: fold */
|
||||
{
|
||||
ulint i;
|
||||
|
||||
ut_ad(table);
|
||||
ut_ad(table->magic_n == HASH_TABLE_MAGIC_N);
|
||||
|
||||
if (table->heap) {
|
||||
return(table->heap);
|
||||
}
|
||||
|
||||
i = hash_get_sync_obj_index(table, fold);
|
||||
|
||||
return(hash_get_nth_heap(table, i));
|
||||
}
|
||||
|
||||
/************************************************************//**
|
||||
Gets the nth mutex in a hash table.
|
||||
@return mutex */
|
||||
UNIV_INLINE
|
||||
ib_mutex_t*
|
||||
hash_get_nth_mutex(
|
||||
/*===============*/
|
||||
hash_table_t* table, /*!< in: hash table */
|
||||
ulint i) /*!< in: index of the mutex */
|
||||
{
|
||||
ut_ad(table);
|
||||
ut_ad(table->magic_n == HASH_TABLE_MAGIC_N);
|
||||
ut_ad(table->type == HASH_TABLE_SYNC_MUTEX);
|
||||
ut_ad(i < table->n_sync_obj);
|
||||
|
||||
return(table->sync_obj.mutexes + i);
|
||||
}
|
||||
|
||||
/************************************************************//**
|
||||
Gets the mutex for a fold value in a hash table.
|
||||
@return mutex */
|
||||
UNIV_INLINE
|
||||
ib_mutex_t*
|
||||
hash_get_mutex(
|
||||
/*===========*/
|
||||
hash_table_t* table, /*!< in: hash table */
|
||||
ulint fold) /*!< in: fold */
|
||||
{
|
||||
ulint i;
|
||||
|
||||
ut_ad(table);
|
||||
ut_ad(table->magic_n == HASH_TABLE_MAGIC_N);
|
||||
|
||||
i = hash_get_sync_obj_index(table, fold);
|
||||
|
||||
return(hash_get_nth_mutex(table, i));
|
||||
}
|
||||
|
||||
/************************************************************//**
|
||||
Gets the nth rw_lock in a hash table.
|
||||
@return rw_lock */
|
||||
UNIV_INLINE
|
||||
rw_lock_t*
|
||||
hash_get_nth_lock(
|
||||
/*==============*/
|
||||
hash_table_t* table, /*!< in: hash table */
|
||||
ulint i) /*!< in: index of the rw_lock */
|
||||
{
|
||||
ut_ad(table);
|
||||
ut_ad(table->magic_n == HASH_TABLE_MAGIC_N);
|
||||
ut_ad(table->type == HASH_TABLE_SYNC_RW_LOCK);
|
||||
ut_ad(i < table->n_sync_obj);
|
||||
|
||||
return(table->sync_obj.rw_locks + i);
|
||||
}
|
||||
|
||||
/************************************************************//**
|
||||
Gets the rw_lock for a fold value in a hash table.
|
||||
@return rw_lock */
|
||||
UNIV_INLINE
|
||||
rw_lock_t*
|
||||
hash_get_lock(
|
||||
/*==========*/
|
||||
hash_table_t* table, /*!< in: hash table */
|
||||
ulint fold) /*!< in: fold */
|
||||
{
|
||||
ulint i;
|
||||
|
||||
ut_ad(table);
|
||||
ut_ad(table->type == HASH_TABLE_SYNC_RW_LOCK);
|
||||
ut_ad(table->magic_n == HASH_TABLE_MAGIC_N);
|
||||
|
||||
i = hash_get_sync_obj_index(table, fold);
|
||||
|
||||
return(hash_get_nth_lock(table, i));
|
||||
}
|
||||
#endif /* !UNIV_HOTBACKUP */
|
||||
467
storage/innobase/include/ibuf0ibuf.h
Normal file
467
storage/innobase/include/ibuf0ibuf.h
Normal file
|
|
@ -0,0 +1,467 @@
|
|||
/*****************************************************************************
|
||||
|
||||
Copyright (c) 1997, 2013, Oracle and/or its affiliates. All Rights Reserved.
|
||||
|
||||
This program is free software; you can redistribute it and/or modify it under
|
||||
the terms of the GNU General Public License as published by the Free Software
|
||||
Foundation; version 2 of the License.
|
||||
|
||||
This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
|
||||
FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License along with
|
||||
this program; if not, write to the Free Software Foundation, Inc.,
|
||||
51 Franklin Street, Suite 500, Boston, MA 02110-1335 USA
|
||||
|
||||
*****************************************************************************/
|
||||
|
||||
/**************************************************//**
|
||||
@file include/ibuf0ibuf.h
|
||||
Insert buffer
|
||||
|
||||
Created 7/19/1997 Heikki Tuuri
|
||||
*******************************************************/
|
||||
|
||||
#ifndef ibuf0ibuf_h
|
||||
#define ibuf0ibuf_h
|
||||
|
||||
#include "univ.i"
|
||||
|
||||
#include "mtr0mtr.h"
|
||||
#include "dict0mem.h"
|
||||
#include "fsp0fsp.h"
|
||||
|
||||
#ifndef UNIV_HOTBACKUP
|
||||
# include "ibuf0types.h"
|
||||
|
||||
/** Default value for maximum on-disk size of change buffer in terms
|
||||
of percentage of the buffer pool. */
|
||||
#define CHANGE_BUFFER_DEFAULT_SIZE (25)
|
||||
|
||||
/* Possible operations buffered in the insert/whatever buffer. See
|
||||
ibuf_insert(). DO NOT CHANGE THE VALUES OF THESE, THEY ARE STORED ON DISK. */
|
||||
typedef enum {
|
||||
IBUF_OP_INSERT = 0,
|
||||
IBUF_OP_DELETE_MARK = 1,
|
||||
IBUF_OP_DELETE = 2,
|
||||
|
||||
/* Number of different operation types. */
|
||||
IBUF_OP_COUNT = 3
|
||||
} ibuf_op_t;
|
||||
|
||||
/** Combinations of operations that can be buffered. Because the enum
|
||||
values are used for indexing innobase_change_buffering_values[], they
|
||||
should start at 0 and there should not be any gaps. */
|
||||
typedef enum {
|
||||
IBUF_USE_NONE = 0,
|
||||
IBUF_USE_INSERT, /* insert */
|
||||
IBUF_USE_DELETE_MARK, /* delete */
|
||||
IBUF_USE_INSERT_DELETE_MARK, /* insert+delete */
|
||||
IBUF_USE_DELETE, /* delete+purge */
|
||||
IBUF_USE_ALL, /* insert+delete+purge */
|
||||
|
||||
IBUF_USE_COUNT /* number of entries in ibuf_use_t */
|
||||
} ibuf_use_t;
|
||||
|
||||
/** Operations that can currently be buffered. */
|
||||
extern ibuf_use_t ibuf_use;
|
||||
|
||||
/** The insert buffer control structure */
|
||||
extern ibuf_t* ibuf;
|
||||
|
||||
/* The purpose of the insert buffer is to reduce random disk access.
|
||||
When we wish to insert a record into a non-unique secondary index and
|
||||
the B-tree leaf page where the record belongs to is not in the buffer
|
||||
pool, we insert the record into the insert buffer B-tree, indexed by
|
||||
(space_id, page_no). When the page is eventually read into the buffer
|
||||
pool, we look up the insert buffer B-tree for any modifications to the
|
||||
page, and apply these upon the completion of the read operation. This
|
||||
is called the insert buffer merge. */
|
||||
|
||||
/* The insert buffer merge must always succeed. To guarantee this,
|
||||
the insert buffer subsystem keeps track of the free space in pages for
|
||||
which it can buffer operations. Two bits per page in the insert
|
||||
buffer bitmap indicate the available space in coarse increments. The
|
||||
free bits in the insert buffer bitmap must never exceed the free space
|
||||
on a page. It is safe to decrement or reset the bits in the bitmap in
|
||||
a mini-transaction that is committed before the mini-transaction that
|
||||
affects the free space. It is unsafe to increment the bits in a
|
||||
separately committed mini-transaction, because in crash recovery, the
|
||||
free bits could momentarily be set too high. */
|
||||
|
||||
/******************************************************************//**
|
||||
Creates the insert buffer data structure at a database startup. */
|
||||
UNIV_INTERN
|
||||
void
|
||||
ibuf_init_at_db_start(void);
|
||||
/*=======================*/
|
||||
/*********************************************************************//**
|
||||
Updates the max_size value for ibuf. */
|
||||
UNIV_INTERN
|
||||
void
|
||||
ibuf_max_size_update(
|
||||
/*=================*/
|
||||
ulint new_val); /*!< in: new value in terms of
|
||||
percentage of the buffer pool size */
|
||||
/*********************************************************************//**
|
||||
Reads the biggest tablespace id from the high end of the insert buffer
|
||||
tree and updates the counter in fil_system. */
|
||||
UNIV_INTERN
|
||||
void
|
||||
ibuf_update_max_tablespace_id(void);
|
||||
/*===============================*/
|
||||
/***************************************************************//**
|
||||
Starts an insert buffer mini-transaction. */
|
||||
UNIV_INLINE
|
||||
void
|
||||
ibuf_mtr_start(
|
||||
/*===========*/
|
||||
mtr_t* mtr) /*!< out: mini-transaction */
|
||||
__attribute__((nonnull));
|
||||
/***************************************************************//**
|
||||
Commits an insert buffer mini-transaction. */
|
||||
UNIV_INLINE
|
||||
void
|
||||
ibuf_mtr_commit(
|
||||
/*============*/
|
||||
mtr_t* mtr) /*!< in/out: mini-transaction */
|
||||
__attribute__((nonnull));
|
||||
/*********************************************************************//**
|
||||
Initializes an ibuf bitmap page. */
|
||||
UNIV_INTERN
|
||||
void
|
||||
ibuf_bitmap_page_init(
|
||||
/*==================*/
|
||||
buf_block_t* block, /*!< in: bitmap page */
|
||||
mtr_t* mtr); /*!< in: mtr */
|
||||
/************************************************************************//**
|
||||
Resets the free bits of the page in the ibuf bitmap. This is done in a
|
||||
separate mini-transaction, hence this operation does not restrict
|
||||
further work to only ibuf bitmap operations, which would result if the
|
||||
latch to the bitmap page were kept. NOTE: The free bits in the insert
|
||||
buffer bitmap must never exceed the free space on a page. It is safe
|
||||
to decrement or reset the bits in the bitmap in a mini-transaction
|
||||
that is committed before the mini-transaction that affects the free
|
||||
space. */
|
||||
UNIV_INTERN
|
||||
void
|
||||
ibuf_reset_free_bits(
|
||||
/*=================*/
|
||||
buf_block_t* block); /*!< in: index page; free bits are set to 0
|
||||
if the index is a non-clustered
|
||||
non-unique, and page level is 0 */
|
||||
/************************************************************************//**
|
||||
Updates the free bits of an uncompressed page in the ibuf bitmap if
|
||||
there is not enough free on the page any more. This is done in a
|
||||
separate mini-transaction, hence this operation does not restrict
|
||||
further work to only ibuf bitmap operations, which would result if the
|
||||
latch to the bitmap page were kept. NOTE: The free bits in the insert
|
||||
buffer bitmap must never exceed the free space on a page. It is
|
||||
unsafe to increment the bits in a separately committed
|
||||
mini-transaction, because in crash recovery, the free bits could
|
||||
momentarily be set too high. It is only safe to use this function for
|
||||
decrementing the free bits. Should more free space become available,
|
||||
we must not update the free bits here, because that would break crash
|
||||
recovery. */
|
||||
UNIV_INLINE
|
||||
void
|
||||
ibuf_update_free_bits_if_full(
|
||||
/*==========================*/
|
||||
buf_block_t* block, /*!< in: index page to which we have added new
|
||||
records; the free bits are updated if the
|
||||
index is non-clustered and non-unique and
|
||||
the page level is 0, and the page becomes
|
||||
fuller */
|
||||
ulint max_ins_size,/*!< in: value of maximum insert size with
|
||||
reorganize before the latest operation
|
||||
performed to the page */
|
||||
ulint increase);/*!< in: upper limit for the additional space
|
||||
used in the latest operation, if known, or
|
||||
ULINT_UNDEFINED */
|
||||
/**********************************************************************//**
|
||||
Updates the free bits for an uncompressed page to reflect the present
|
||||
state. Does this in the mtr given, which means that the latching
|
||||
order rules virtually prevent any further operations for this OS
|
||||
thread until mtr is committed. NOTE: The free bits in the insert
|
||||
buffer bitmap must never exceed the free space on a page. It is safe
|
||||
to set the free bits in the same mini-transaction that updated the
|
||||
page. */
|
||||
UNIV_INTERN
|
||||
void
|
||||
ibuf_update_free_bits_low(
|
||||
/*======================*/
|
||||
const buf_block_t* block, /*!< in: index page */
|
||||
ulint max_ins_size, /*!< in: value of
|
||||
maximum insert size
|
||||
with reorganize before
|
||||
the latest operation
|
||||
performed to the page */
|
||||
mtr_t* mtr); /*!< in/out: mtr */
|
||||
/**********************************************************************//**
|
||||
Updates the free bits for a compressed page to reflect the present
|
||||
state. Does this in the mtr given, which means that the latching
|
||||
order rules virtually prevent any further operations for this OS
|
||||
thread until mtr is committed. NOTE: The free bits in the insert
|
||||
buffer bitmap must never exceed the free space on a page. It is safe
|
||||
to set the free bits in the same mini-transaction that updated the
|
||||
page. */
|
||||
UNIV_INTERN
|
||||
void
|
||||
ibuf_update_free_bits_zip(
|
||||
/*======================*/
|
||||
buf_block_t* block, /*!< in/out: index page */
|
||||
mtr_t* mtr); /*!< in/out: mtr */
|
||||
/**********************************************************************//**
|
||||
Updates the free bits for the two pages to reflect the present state.
|
||||
Does this in the mtr given, which means that the latching order rules
|
||||
virtually prevent any further operations until mtr is committed.
|
||||
NOTE: The free bits in the insert buffer bitmap must never exceed the
|
||||
free space on a page. It is safe to set the free bits in the same
|
||||
mini-transaction that updated the pages. */
|
||||
UNIV_INTERN
|
||||
void
|
||||
ibuf_update_free_bits_for_two_pages_low(
|
||||
/*====================================*/
|
||||
ulint zip_size,/*!< in: compressed page size in bytes;
|
||||
0 for uncompressed pages */
|
||||
buf_block_t* block1, /*!< in: index page */
|
||||
buf_block_t* block2, /*!< in: index page */
|
||||
mtr_t* mtr); /*!< in: mtr */
|
||||
/**********************************************************************//**
|
||||
A basic partial test if an insert to the insert buffer could be possible and
|
||||
recommended. */
|
||||
UNIV_INLINE
|
||||
ibool
|
||||
ibuf_should_try(
|
||||
/*============*/
|
||||
dict_index_t* index, /*!< in: index where to insert */
|
||||
ulint ignore_sec_unique); /*!< in: if != 0, we should
|
||||
ignore UNIQUE constraint on
|
||||
a secondary index when we
|
||||
decide */
|
||||
/******************************************************************//**
|
||||
Returns TRUE if the current OS thread is performing an insert buffer
|
||||
routine.
|
||||
|
||||
For instance, a read-ahead of non-ibuf pages is forbidden by threads
|
||||
that are executing an insert buffer routine.
|
||||
@return TRUE if inside an insert buffer routine */
|
||||
UNIV_INLINE
|
||||
ibool
|
||||
ibuf_inside(
|
||||
/*========*/
|
||||
const mtr_t* mtr) /*!< in: mini-transaction */
|
||||
__attribute__((nonnull, pure));
|
||||
/***********************************************************************//**
|
||||
Checks if a page address is an ibuf bitmap page (level 3 page) address.
|
||||
@return TRUE if a bitmap page */
|
||||
UNIV_INLINE
|
||||
ibool
|
||||
ibuf_bitmap_page(
|
||||
/*=============*/
|
||||
ulint zip_size,/*!< in: compressed page size in bytes;
|
||||
0 for uncompressed pages */
|
||||
ulint page_no);/*!< in: page number */
|
||||
/***********************************************************************//**
|
||||
Checks if a page is a level 2 or 3 page in the ibuf hierarchy of pages.
|
||||
Must not be called when recv_no_ibuf_operations==TRUE.
|
||||
@return TRUE if level 2 or level 3 page */
|
||||
UNIV_INTERN
|
||||
ibool
|
||||
ibuf_page_low(
|
||||
/*==========*/
|
||||
ulint space, /*!< in: space id */
|
||||
ulint zip_size,/*!< in: compressed page size in bytes, or 0 */
|
||||
ulint page_no,/*!< in: page number */
|
||||
#ifdef UNIV_DEBUG
|
||||
ibool x_latch,/*!< in: FALSE if relaxed check
|
||||
(avoid latching the bitmap page) */
|
||||
#endif /* UNIV_DEBUG */
|
||||
const char* file, /*!< in: file name */
|
||||
ulint line, /*!< in: line where called */
|
||||
mtr_t* mtr) /*!< in: mtr which will contain an
|
||||
x-latch to the bitmap page if the page
|
||||
is not one of the fixed address ibuf
|
||||
pages, or NULL, in which case a new
|
||||
transaction is created. */
|
||||
__attribute__((warn_unused_result));
|
||||
#ifdef UNIV_DEBUG
|
||||
/** Checks if a page is a level 2 or 3 page in the ibuf hierarchy of
|
||||
pages. Must not be called when recv_no_ibuf_operations==TRUE.
|
||||
@param space tablespace identifier
|
||||
@param zip_size compressed page size in bytes, or 0
|
||||
@param page_no page number
|
||||
@param mtr mini-transaction or NULL
|
||||
@return TRUE if level 2 or level 3 page */
|
||||
# define ibuf_page(space, zip_size, page_no, mtr) \
|
||||
ibuf_page_low(space, zip_size, page_no, TRUE, __FILE__, __LINE__, mtr)
|
||||
#else /* UVIV_DEBUG */
|
||||
/** Checks if a page is a level 2 or 3 page in the ibuf hierarchy of
|
||||
pages. Must not be called when recv_no_ibuf_operations==TRUE.
|
||||
@param space tablespace identifier
|
||||
@param zip_size compressed page size in bytes, or 0
|
||||
@param page_no page number
|
||||
@param mtr mini-transaction or NULL
|
||||
@return TRUE if level 2 or level 3 page */
|
||||
# define ibuf_page(space, zip_size, page_no, mtr) \
|
||||
ibuf_page_low(space, zip_size, page_no, __FILE__, __LINE__, mtr)
|
||||
#endif /* UVIV_DEBUG */
|
||||
/***********************************************************************//**
|
||||
Frees excess pages from the ibuf free list. This function is called when an OS
|
||||
thread calls fsp services to allocate a new file segment, or a new page to a
|
||||
file segment, and the thread did not own the fsp latch before this call. */
|
||||
UNIV_INTERN
|
||||
void
|
||||
ibuf_free_excess_pages(void);
|
||||
/*========================*/
|
||||
/*********************************************************************//**
|
||||
Buffer an operation in the insert/delete buffer, instead of doing it
|
||||
directly to the disk page, if this is possible. Does not do it if the index
|
||||
is clustered or unique.
|
||||
@return TRUE if success */
|
||||
UNIV_INTERN
|
||||
ibool
|
||||
ibuf_insert(
|
||||
/*========*/
|
||||
ibuf_op_t op, /*!< in: operation type */
|
||||
const dtuple_t* entry, /*!< in: index entry to insert */
|
||||
dict_index_t* index, /*!< in: index where to insert */
|
||||
ulint space, /*!< in: space id where to insert */
|
||||
ulint zip_size,/*!< in: compressed page size in bytes, or 0 */
|
||||
ulint page_no,/*!< in: page number where to insert */
|
||||
que_thr_t* thr); /*!< in: query thread */
|
||||
/*********************************************************************//**
|
||||
When an index page is read from a disk to the buffer pool, this function
|
||||
applies any buffered operations to the page and deletes the entries from the
|
||||
insert buffer. If the page is not read, but created in the buffer pool, this
|
||||
function deletes its buffered entries from the insert buffer; there can
|
||||
exist entries for such a page if the page belonged to an index which
|
||||
subsequently was dropped. */
|
||||
UNIV_INTERN
|
||||
void
|
||||
ibuf_merge_or_delete_for_page(
|
||||
/*==========================*/
|
||||
buf_block_t* block, /*!< in: if page has been read from
|
||||
disk, pointer to the page x-latched,
|
||||
else NULL */
|
||||
ulint space, /*!< in: space id of the index page */
|
||||
ulint page_no,/*!< in: page number of the index page */
|
||||
ulint zip_size,/*!< in: compressed page size in bytes,
|
||||
or 0 */
|
||||
ibool update_ibuf_bitmap);/*!< in: normally this is set
|
||||
to TRUE, but if we have deleted or are
|
||||
deleting the tablespace, then we
|
||||
naturally do not want to update a
|
||||
non-existent bitmap page */
|
||||
/*********************************************************************//**
|
||||
Deletes all entries in the insert buffer for a given space id. This is used
|
||||
in DISCARD TABLESPACE and IMPORT TABLESPACE.
|
||||
NOTE: this does not update the page free bitmaps in the space. The space will
|
||||
become CORRUPT when you call this function! */
|
||||
UNIV_INTERN
|
||||
void
|
||||
ibuf_delete_for_discarded_space(
|
||||
/*============================*/
|
||||
ulint space); /*!< in: space id */
|
||||
/*********************************************************************//**
|
||||
Contracts insert buffer trees by reading pages to the buffer pool.
|
||||
@return a lower limit for the combined size in bytes of entries which
|
||||
will be merged from ibuf trees to the pages read, 0 if ibuf is
|
||||
empty */
|
||||
UNIV_INTERN
|
||||
ulint
|
||||
ibuf_contract_in_background(
|
||||
/*========================*/
|
||||
table_id_t table_id, /*!< in: if merge should be done only
|
||||
for a specific table, for all tables
|
||||
this should be 0 */
|
||||
ibool full); /*!< in: TRUE if the caller wants to
|
||||
do a full contract based on PCT_IO(100).
|
||||
If FALSE then the size of contract
|
||||
batch is determined based on the
|
||||
current size of the ibuf tree. */
|
||||
#endif /* !UNIV_HOTBACKUP */
|
||||
/*********************************************************************//**
|
||||
Parses a redo log record of an ibuf bitmap page init.
|
||||
@return end of log record or NULL */
|
||||
UNIV_INTERN
|
||||
byte*
|
||||
ibuf_parse_bitmap_init(
|
||||
/*===================*/
|
||||
byte* ptr, /*!< in: buffer */
|
||||
byte* end_ptr,/*!< in: buffer end */
|
||||
buf_block_t* block, /*!< in: block or NULL */
|
||||
mtr_t* mtr); /*!< in: mtr or NULL */
|
||||
#ifndef UNIV_HOTBACKUP
|
||||
#ifdef UNIV_IBUF_COUNT_DEBUG
|
||||
/******************************************************************//**
|
||||
Gets the ibuf count for a given page.
|
||||
@return number of entries in the insert buffer currently buffered for
|
||||
this page */
|
||||
UNIV_INTERN
|
||||
ulint
|
||||
ibuf_count_get(
|
||||
/*===========*/
|
||||
ulint space, /*!< in: space id */
|
||||
ulint page_no);/*!< in: page number */
|
||||
#endif
|
||||
/******************************************************************//**
|
||||
Looks if the insert buffer is empty.
|
||||
@return true if empty */
|
||||
UNIV_INTERN
|
||||
bool
|
||||
ibuf_is_empty(void);
|
||||
/*===============*/
|
||||
/******************************************************************//**
|
||||
Prints info of ibuf. */
|
||||
UNIV_INTERN
|
||||
void
|
||||
ibuf_print(
|
||||
/*=======*/
|
||||
FILE* file); /*!< in: file where to print */
|
||||
/********************************************************************
|
||||
Read the first two bytes from a record's fourth field (counter field in new
|
||||
records; something else in older records).
|
||||
@return "counter" field, or ULINT_UNDEFINED if for some reason it can't be read */
|
||||
UNIV_INTERN
|
||||
ulint
|
||||
ibuf_rec_get_counter(
|
||||
/*=================*/
|
||||
const rec_t* rec); /*!< in: ibuf record */
|
||||
/******************************************************************//**
|
||||
Closes insert buffer and frees the data structures. */
|
||||
UNIV_INTERN
|
||||
void
|
||||
ibuf_close(void);
|
||||
/*============*/
|
||||
|
||||
/******************************************************************//**
|
||||
Checks the insert buffer bitmaps on IMPORT TABLESPACE.
|
||||
@return DB_SUCCESS or error code */
|
||||
UNIV_INTERN
|
||||
dberr_t
|
||||
ibuf_check_bitmap_on_import(
|
||||
/*========================*/
|
||||
const trx_t* trx, /*!< in: transaction */
|
||||
ulint space_id) /*!< in: tablespace identifier */
|
||||
__attribute__((nonnull, warn_unused_result));
|
||||
|
||||
#define IBUF_HEADER_PAGE_NO FSP_IBUF_HEADER_PAGE_NO
|
||||
#define IBUF_TREE_ROOT_PAGE_NO FSP_IBUF_TREE_ROOT_PAGE_NO
|
||||
|
||||
#endif /* !UNIV_HOTBACKUP */
|
||||
|
||||
/* The ibuf header page currently contains only the file segment header
|
||||
for the file segment from which the pages for the ibuf tree are allocated */
|
||||
#define IBUF_HEADER PAGE_DATA
|
||||
#define IBUF_TREE_SEG_HEADER 0 /* fseg header for ibuf tree */
|
||||
|
||||
/* The insert buffer tree itself is always located in space 0. */
|
||||
#define IBUF_SPACE_ID 0
|
||||
|
||||
#ifndef UNIV_NONINL
|
||||
#include "ibuf0ibuf.ic"
|
||||
#endif
|
||||
|
||||
#endif
|
||||
367
storage/innobase/include/ibuf0ibuf.ic
Normal file
367
storage/innobase/include/ibuf0ibuf.ic
Normal file
|
|
@ -0,0 +1,367 @@
|
|||
/*****************************************************************************
|
||||
|
||||
Copyright (c) 1997, 2013, Oracle and/or its affiliates. All Rights Reserved.
|
||||
|
||||
This program is free software; you can redistribute it and/or modify it under
|
||||
the terms of the GNU General Public License as published by the Free Software
|
||||
Foundation; version 2 of the License.
|
||||
|
||||
This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
|
||||
FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License along with
|
||||
this program; if not, write to the Free Software Foundation, Inc.,
|
||||
51 Franklin Street, Suite 500, Boston, MA 02110-1335 USA
|
||||
|
||||
*****************************************************************************/
|
||||
|
||||
/**************************************************//**
|
||||
@file include/ibuf0ibuf.ic
|
||||
Insert buffer
|
||||
|
||||
Created 7/19/1997 Heikki Tuuri
|
||||
*******************************************************/
|
||||
|
||||
#include "page0page.h"
|
||||
#include "page0zip.h"
|
||||
#ifndef UNIV_HOTBACKUP
|
||||
#include "buf0lru.h"
|
||||
|
||||
/** An index page must contain at least UNIV_PAGE_SIZE /
|
||||
IBUF_PAGE_SIZE_PER_FREE_SPACE bytes of free space for ibuf to try to
|
||||
buffer inserts to this page. If there is this much of free space, the
|
||||
corresponding bits are set in the ibuf bitmap. */
|
||||
#define IBUF_PAGE_SIZE_PER_FREE_SPACE 32
|
||||
|
||||
/***************************************************************//**
|
||||
Starts an insert buffer mini-transaction. */
|
||||
UNIV_INLINE
|
||||
void
|
||||
ibuf_mtr_start(
|
||||
/*===========*/
|
||||
mtr_t* mtr) /*!< out: mini-transaction */
|
||||
{
|
||||
mtr_start(mtr);
|
||||
mtr->inside_ibuf = TRUE;
|
||||
}
|
||||
/***************************************************************//**
|
||||
Commits an insert buffer mini-transaction. */
|
||||
UNIV_INLINE
|
||||
void
|
||||
ibuf_mtr_commit(
|
||||
/*============*/
|
||||
mtr_t* mtr) /*!< in/out: mini-transaction */
|
||||
{
|
||||
ut_ad(mtr->inside_ibuf);
|
||||
ut_d(mtr->inside_ibuf = FALSE);
|
||||
mtr_commit(mtr);
|
||||
}
|
||||
|
||||
/** Insert buffer struct */
|
||||
struct ibuf_t{
|
||||
ulint size; /*!< current size of the ibuf index
|
||||
tree, in pages */
|
||||
ulint max_size; /*!< recommended maximum size of the
|
||||
ibuf index tree, in pages */
|
||||
ulint seg_size; /*!< allocated pages of the file
|
||||
segment containing ibuf header and
|
||||
tree */
|
||||
bool empty; /*!< Protected by the page
|
||||
latch of the root page of the
|
||||
insert buffer tree
|
||||
(FSP_IBUF_TREE_ROOT_PAGE_NO). true
|
||||
if and only if the insert
|
||||
buffer tree is empty. */
|
||||
ulint free_list_len; /*!< length of the free list */
|
||||
ulint height; /*!< tree height */
|
||||
dict_index_t* index; /*!< insert buffer index */
|
||||
|
||||
ulint n_merges; /*!< number of pages merged */
|
||||
ulint n_merged_ops[IBUF_OP_COUNT];
|
||||
/*!< number of operations of each type
|
||||
merged to index pages */
|
||||
ulint n_discarded_ops[IBUF_OP_COUNT];
|
||||
/*!< number of operations of each type
|
||||
discarded without merging due to the
|
||||
tablespace being deleted or the
|
||||
index being dropped */
|
||||
};
|
||||
|
||||
/************************************************************************//**
|
||||
Sets the free bit of the page in the ibuf bitmap. This is done in a separate
|
||||
mini-transaction, hence this operation does not restrict further work to only
|
||||
ibuf bitmap operations, which would result if the latch to the bitmap page
|
||||
were kept. */
|
||||
UNIV_INTERN
|
||||
void
|
||||
ibuf_set_free_bits_func(
|
||||
/*====================*/
|
||||
buf_block_t* block, /*!< in: index page of a non-clustered index;
|
||||
free bit is reset if page level is 0 */
|
||||
#ifdef UNIV_IBUF_DEBUG
|
||||
ulint max_val,/*!< in: ULINT_UNDEFINED or a maximum
|
||||
value which the bits must have before
|
||||
setting; this is for debugging */
|
||||
#endif /* UNIV_IBUF_DEBUG */
|
||||
ulint val); /*!< in: value to set: < 4 */
|
||||
#ifdef UNIV_IBUF_DEBUG
|
||||
# define ibuf_set_free_bits(b,v,max) ibuf_set_free_bits_func(b,max,v)
|
||||
#else /* UNIV_IBUF_DEBUG */
|
||||
# define ibuf_set_free_bits(b,v,max) ibuf_set_free_bits_func(b,v)
|
||||
#endif /* UNIV_IBUF_DEBUG */
|
||||
|
||||
/**********************************************************************//**
|
||||
A basic partial test if an insert to the insert buffer could be possible and
|
||||
recommended. */
|
||||
UNIV_INLINE
|
||||
ibool
|
||||
ibuf_should_try(
|
||||
/*============*/
|
||||
dict_index_t* index, /*!< in: index where to insert */
|
||||
ulint ignore_sec_unique) /*!< in: if != 0, we should
|
||||
ignore UNIQUE constraint on
|
||||
a secondary index when we
|
||||
decide */
|
||||
{
|
||||
return(ibuf_use != IBUF_USE_NONE
|
||||
&& ibuf->max_size != 0
|
||||
&& !dict_index_is_clust(index)
|
||||
&& index->table->quiesce == QUIESCE_NONE
|
||||
&& (ignore_sec_unique || !dict_index_is_unique(index)));
|
||||
}
|
||||
|
||||
/******************************************************************//**
|
||||
Returns TRUE if the current OS thread is performing an insert buffer
|
||||
routine.
|
||||
|
||||
For instance, a read-ahead of non-ibuf pages is forbidden by threads
|
||||
that are executing an insert buffer routine.
|
||||
@return TRUE if inside an insert buffer routine */
|
||||
UNIV_INLINE
|
||||
ibool
|
||||
ibuf_inside(
|
||||
/*========*/
|
||||
const mtr_t* mtr) /*!< in: mini-transaction */
|
||||
{
|
||||
return(mtr->inside_ibuf);
|
||||
}
|
||||
|
||||
/***********************************************************************//**
|
||||
Checks if a page address is an ibuf bitmap page address.
|
||||
@return TRUE if a bitmap page */
|
||||
UNIV_INLINE
|
||||
ibool
|
||||
ibuf_bitmap_page(
|
||||
/*=============*/
|
||||
ulint zip_size,/*!< in: compressed page size in bytes;
|
||||
0 for uncompressed pages */
|
||||
ulint page_no)/*!< in: page number */
|
||||
{
|
||||
ut_ad(ut_is_2pow(zip_size));
|
||||
|
||||
if (!zip_size) {
|
||||
return((page_no & (UNIV_PAGE_SIZE - 1))
|
||||
== FSP_IBUF_BITMAP_OFFSET);
|
||||
}
|
||||
|
||||
return((page_no & (zip_size - 1)) == FSP_IBUF_BITMAP_OFFSET);
|
||||
}
|
||||
|
||||
/*********************************************************************//**
|
||||
Translates the free space on a page to a value in the ibuf bitmap.
|
||||
@return value for ibuf bitmap bits */
|
||||
UNIV_INLINE
|
||||
ulint
|
||||
ibuf_index_page_calc_free_bits(
|
||||
/*===========================*/
|
||||
ulint zip_size, /*!< in: compressed page size in bytes;
|
||||
0 for uncompressed pages */
|
||||
ulint max_ins_size) /*!< in: maximum insert size after reorganize
|
||||
for the page */
|
||||
{
|
||||
ulint n;
|
||||
ut_ad(ut_is_2pow(zip_size));
|
||||
ut_ad(!zip_size || zip_size > IBUF_PAGE_SIZE_PER_FREE_SPACE);
|
||||
ut_ad(zip_size <= UNIV_ZIP_SIZE_MAX);
|
||||
|
||||
if (zip_size) {
|
||||
n = max_ins_size
|
||||
/ (zip_size / IBUF_PAGE_SIZE_PER_FREE_SPACE);
|
||||
} else {
|
||||
n = max_ins_size
|
||||
/ (UNIV_PAGE_SIZE / IBUF_PAGE_SIZE_PER_FREE_SPACE);
|
||||
}
|
||||
|
||||
if (n == 3) {
|
||||
n = 2;
|
||||
}
|
||||
|
||||
if (n > 3) {
|
||||
n = 3;
|
||||
}
|
||||
|
||||
return(n);
|
||||
}
|
||||
|
||||
/*********************************************************************//**
|
||||
Translates the ibuf free bits to the free space on a page in bytes.
|
||||
@return maximum insert size after reorganize for the page */
|
||||
UNIV_INLINE
|
||||
ulint
|
||||
ibuf_index_page_calc_free_from_bits(
|
||||
/*================================*/
|
||||
ulint zip_size,/*!< in: compressed page size in bytes;
|
||||
0 for uncompressed pages */
|
||||
ulint bits) /*!< in: value for ibuf bitmap bits */
|
||||
{
|
||||
ut_ad(bits < 4);
|
||||
ut_ad(ut_is_2pow(zip_size));
|
||||
ut_ad(!zip_size || zip_size > IBUF_PAGE_SIZE_PER_FREE_SPACE);
|
||||
ut_ad(zip_size <= UNIV_ZIP_SIZE_MAX);
|
||||
|
||||
if (zip_size) {
|
||||
if (bits == 3) {
|
||||
return(4 * zip_size / IBUF_PAGE_SIZE_PER_FREE_SPACE);
|
||||
}
|
||||
|
||||
return(bits * zip_size / IBUF_PAGE_SIZE_PER_FREE_SPACE);
|
||||
}
|
||||
|
||||
if (bits == 3) {
|
||||
return(4 * UNIV_PAGE_SIZE / IBUF_PAGE_SIZE_PER_FREE_SPACE);
|
||||
}
|
||||
|
||||
return(bits * (UNIV_PAGE_SIZE / IBUF_PAGE_SIZE_PER_FREE_SPACE));
|
||||
}
|
||||
|
||||
/*********************************************************************//**
|
||||
Translates the free space on a compressed page to a value in the ibuf bitmap.
|
||||
@return value for ibuf bitmap bits */
|
||||
UNIV_INLINE
|
||||
ulint
|
||||
ibuf_index_page_calc_free_zip(
|
||||
/*==========================*/
|
||||
ulint zip_size,
|
||||
/*!< in: compressed page size in bytes */
|
||||
const buf_block_t* block) /*!< in: buffer block */
|
||||
{
|
||||
ulint max_ins_size;
|
||||
const page_zip_des_t* page_zip;
|
||||
lint zip_max_ins;
|
||||
|
||||
ut_ad(zip_size == buf_block_get_zip_size(block));
|
||||
ut_ad(zip_size);
|
||||
|
||||
/* Consider the maximum insert size on the uncompressed page
|
||||
without reorganizing the page. We must not assume anything
|
||||
about the compression ratio. If zip_max_ins > max_ins_size and
|
||||
there is 1/4 garbage on the page, recompression after the
|
||||
reorganize could fail, in theory. So, let us guarantee that
|
||||
merging a buffered insert to a compressed page will always
|
||||
succeed without reorganizing or recompressing the page, just
|
||||
by using the page modification log. */
|
||||
max_ins_size = page_get_max_insert_size(
|
||||
buf_block_get_frame(block), 1);
|
||||
|
||||
page_zip = buf_block_get_page_zip(block);
|
||||
zip_max_ins = page_zip_max_ins_size(page_zip,
|
||||
FALSE/* not clustered */);
|
||||
|
||||
if (zip_max_ins < 0) {
|
||||
return(0);
|
||||
} else if (max_ins_size > (ulint) zip_max_ins) {
|
||||
max_ins_size = (ulint) zip_max_ins;
|
||||
}
|
||||
|
||||
return(ibuf_index_page_calc_free_bits(zip_size, max_ins_size));
|
||||
}
|
||||
|
||||
/*********************************************************************//**
|
||||
Translates the free space on a page to a value in the ibuf bitmap.
|
||||
@return value for ibuf bitmap bits */
|
||||
UNIV_INLINE
|
||||
ulint
|
||||
ibuf_index_page_calc_free(
|
||||
/*======================*/
|
||||
ulint zip_size,/*!< in: compressed page size in bytes;
|
||||
0 for uncompressed pages */
|
||||
const buf_block_t* block) /*!< in: buffer block */
|
||||
{
|
||||
ut_ad(zip_size == buf_block_get_zip_size(block));
|
||||
|
||||
if (!zip_size) {
|
||||
ulint max_ins_size;
|
||||
|
||||
max_ins_size = page_get_max_insert_size_after_reorganize(
|
||||
buf_block_get_frame(block), 1);
|
||||
|
||||
return(ibuf_index_page_calc_free_bits(0, max_ins_size));
|
||||
} else {
|
||||
return(ibuf_index_page_calc_free_zip(zip_size, block));
|
||||
}
|
||||
}
|
||||
|
||||
/************************************************************************//**
|
||||
Updates the free bits of an uncompressed page in the ibuf bitmap if
|
||||
there is not enough free on the page any more. This is done in a
|
||||
separate mini-transaction, hence this operation does not restrict
|
||||
further work to only ibuf bitmap operations, which would result if the
|
||||
latch to the bitmap page were kept. NOTE: The free bits in the insert
|
||||
buffer bitmap must never exceed the free space on a page. It is
|
||||
unsafe to increment the bits in a separately committed
|
||||
mini-transaction, because in crash recovery, the free bits could
|
||||
momentarily be set too high. It is only safe to use this function for
|
||||
decrementing the free bits. Should more free space become available,
|
||||
we must not update the free bits here, because that would break crash
|
||||
recovery. */
|
||||
UNIV_INLINE
|
||||
void
|
||||
ibuf_update_free_bits_if_full(
|
||||
/*==========================*/
|
||||
buf_block_t* block, /*!< in: index page to which we have added new
|
||||
records; the free bits are updated if the
|
||||
index is non-clustered and non-unique and
|
||||
the page level is 0, and the page becomes
|
||||
fuller */
|
||||
ulint max_ins_size,/*!< in: value of maximum insert size with
|
||||
reorganize before the latest operation
|
||||
performed to the page */
|
||||
ulint increase)/*!< in: upper limit for the additional space
|
||||
used in the latest operation, if known, or
|
||||
ULINT_UNDEFINED */
|
||||
{
|
||||
ulint before;
|
||||
ulint after;
|
||||
|
||||
ut_ad(!buf_block_get_page_zip(block));
|
||||
|
||||
before = ibuf_index_page_calc_free_bits(0, max_ins_size);
|
||||
|
||||
if (max_ins_size >= increase) {
|
||||
#if ULINT32_UNDEFINED <= UNIV_PAGE_SIZE_MAX
|
||||
# error "ULINT32_UNDEFINED <= UNIV_PAGE_SIZE_MAX"
|
||||
#endif
|
||||
after = ibuf_index_page_calc_free_bits(0, max_ins_size
|
||||
- increase);
|
||||
#ifdef UNIV_IBUF_DEBUG
|
||||
ut_a(after <= ibuf_index_page_calc_free(0, block));
|
||||
#endif
|
||||
} else {
|
||||
after = ibuf_index_page_calc_free(0, block);
|
||||
}
|
||||
|
||||
if (after == 0) {
|
||||
/* We move the page to the front of the buffer pool LRU list:
|
||||
the purpose of this is to prevent those pages to which we
|
||||
cannot make inserts using the insert buffer from slipping
|
||||
out of the buffer pool */
|
||||
|
||||
buf_page_make_young(&block->page);
|
||||
}
|
||||
|
||||
if (before > after) {
|
||||
ibuf_set_free_bits(block, after, before);
|
||||
}
|
||||
}
|
||||
#endif /* !UNIV_HOTBACKUP */
|
||||
31
storage/innobase/include/ibuf0types.h
Normal file
31
storage/innobase/include/ibuf0types.h
Normal file
|
|
@ -0,0 +1,31 @@
|
|||
/*****************************************************************************
|
||||
|
||||
Copyright (c) 1997, 2009, Oracle and/or its affiliates. All Rights Reserved.
|
||||
|
||||
This program is free software; you can redistribute it and/or modify it under
|
||||
the terms of the GNU General Public License as published by the Free Software
|
||||
Foundation; version 2 of the License.
|
||||
|
||||
This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
|
||||
FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License along with
|
||||
this program; if not, write to the Free Software Foundation, Inc.,
|
||||
51 Franklin Street, Suite 500, Boston, MA 02110-1335 USA
|
||||
|
||||
*****************************************************************************/
|
||||
|
||||
/**************************************************//**
|
||||
@file include/ibuf0types.h
|
||||
Insert buffer global types
|
||||
|
||||
Created 7/29/1997 Heikki Tuuri
|
||||
*******************************************************/
|
||||
|
||||
#ifndef ibuf0types_h
|
||||
#define ibuf0types_h
|
||||
|
||||
struct ibuf_t;
|
||||
|
||||
#endif
|
||||
69
storage/innobase/include/lock0iter.h
Normal file
69
storage/innobase/include/lock0iter.h
Normal file
|
|
@ -0,0 +1,69 @@
|
|||
/*****************************************************************************
|
||||
|
||||
Copyright (c) 2007, 2009, Oracle and/or its affiliates. All Rights Reserved.
|
||||
|
||||
This program is free software; you can redistribute it and/or modify it under
|
||||
the terms of the GNU General Public License as published by the Free Software
|
||||
Foundation; version 2 of the License.
|
||||
|
||||
This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
|
||||
FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License along with
|
||||
this program; if not, write to the Free Software Foundation, Inc.,
|
||||
51 Franklin Street, Suite 500, Boston, MA 02110-1335 USA
|
||||
|
||||
*****************************************************************************/
|
||||
|
||||
/**************************************************//**
|
||||
@file include/lock0iter.h
|
||||
Lock queue iterator type and function prototypes.
|
||||
|
||||
Created July 16, 2007 Vasil Dimov
|
||||
*******************************************************/
|
||||
|
||||
#ifndef lock0iter_h
|
||||
#define lock0iter_h
|
||||
|
||||
#include "univ.i"
|
||||
#include "lock0types.h"
|
||||
|
||||
struct lock_queue_iterator_t {
|
||||
const lock_t* current_lock;
|
||||
/* In case this is a record lock queue (not table lock queue)
|
||||
then bit_no is the record number within the heap in which the
|
||||
record is stored. */
|
||||
ulint bit_no;
|
||||
};
|
||||
|
||||
/*******************************************************************//**
|
||||
Initialize lock queue iterator so that it starts to iterate from
|
||||
"lock". bit_no specifies the record number within the heap where the
|
||||
record is stored. It can be undefined (ULINT_UNDEFINED) in two cases:
|
||||
1. If the lock is a table lock, thus we have a table lock queue;
|
||||
2. If the lock is a record lock and it is a wait lock. In this case
|
||||
bit_no is calculated in this function by using
|
||||
lock_rec_find_set_bit(). There is exactly one bit set in the bitmap
|
||||
of a wait lock. */
|
||||
UNIV_INTERN
|
||||
void
|
||||
lock_queue_iterator_reset(
|
||||
/*======================*/
|
||||
lock_queue_iterator_t* iter, /*!< out: iterator */
|
||||
const lock_t* lock, /*!< in: lock to start from */
|
||||
ulint bit_no);/*!< in: record number in the
|
||||
heap */
|
||||
|
||||
/*******************************************************************//**
|
||||
Gets the previous lock in the lock queue, returns NULL if there are no
|
||||
more locks (i.e. the current lock is the first one). The iterator is
|
||||
receded (if not-NULL is returned).
|
||||
@return previous lock or NULL */
|
||||
|
||||
const lock_t*
|
||||
lock_queue_iterator_get_prev(
|
||||
/*=========================*/
|
||||
lock_queue_iterator_t* iter); /*!< in/out: iterator */
|
||||
|
||||
#endif /* lock0iter_h */
|
||||
979
storage/innobase/include/lock0lock.h
Normal file
979
storage/innobase/include/lock0lock.h
Normal file
|
|
@ -0,0 +1,979 @@
|
|||
/*****************************************************************************
|
||||
|
||||
Copyright (c) 1996, 2014, Oracle and/or its affiliates. All Rights Reserved.
|
||||
|
||||
This program is free software; you can redistribute it and/or modify it under
|
||||
the terms of the GNU General Public License as published by the Free Software
|
||||
Foundation; version 2 of the License.
|
||||
|
||||
This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
|
||||
FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License along with
|
||||
this program; if not, write to the Free Software Foundation, Inc.,
|
||||
51 Franklin Street, Suite 500, Boston, MA 02110-1335 USA
|
||||
|
||||
*****************************************************************************/
|
||||
|
||||
/**************************************************//**
|
||||
@file include/lock0lock.h
|
||||
The transaction lock system
|
||||
|
||||
Created 5/7/1996 Heikki Tuuri
|
||||
*******************************************************/
|
||||
|
||||
#ifndef lock0lock_h
|
||||
#define lock0lock_h
|
||||
|
||||
#include "univ.i"
|
||||
#include "buf0types.h"
|
||||
#include "trx0types.h"
|
||||
#include "mtr0types.h"
|
||||
#include "rem0types.h"
|
||||
#include "dict0types.h"
|
||||
#include "que0types.h"
|
||||
#include "lock0types.h"
|
||||
#include "read0types.h"
|
||||
#include "hash0hash.h"
|
||||
#include "srv0srv.h"
|
||||
#include "ut0vec.h"
|
||||
|
||||
#ifdef UNIV_DEBUG
|
||||
extern ibool lock_print_waits;
|
||||
#endif /* UNIV_DEBUG */
|
||||
|
||||
/*********************************************************************//**
|
||||
Gets the size of a lock struct.
|
||||
@return size in bytes */
|
||||
UNIV_INTERN
|
||||
ulint
|
||||
lock_get_size(void);
|
||||
/*===============*/
|
||||
/*********************************************************************//**
|
||||
Creates the lock system at database start. */
|
||||
UNIV_INTERN
|
||||
void
|
||||
lock_sys_create(
|
||||
/*============*/
|
||||
ulint n_cells); /*!< in: number of slots in lock hash table */
|
||||
/*********************************************************************//**
|
||||
Closes the lock system at database shutdown. */
|
||||
UNIV_INTERN
|
||||
void
|
||||
lock_sys_close(void);
|
||||
/*================*/
|
||||
/*********************************************************************//**
|
||||
Gets the heap_no of the smallest user record on a page.
|
||||
@return heap_no of smallest user record, or PAGE_HEAP_NO_SUPREMUM */
|
||||
UNIV_INLINE
|
||||
ulint
|
||||
lock_get_min_heap_no(
|
||||
/*=================*/
|
||||
const buf_block_t* block); /*!< in: buffer block */
|
||||
/*************************************************************//**
|
||||
Updates the lock table when we have reorganized a page. NOTE: we copy
|
||||
also the locks set on the infimum of the page; the infimum may carry
|
||||
locks if an update of a record is occurring on the page, and its locks
|
||||
were temporarily stored on the infimum. */
|
||||
UNIV_INTERN
|
||||
void
|
||||
lock_move_reorganize_page(
|
||||
/*======================*/
|
||||
const buf_block_t* block, /*!< in: old index page, now
|
||||
reorganized */
|
||||
const buf_block_t* oblock);/*!< in: copy of the old, not
|
||||
reorganized page */
|
||||
/*************************************************************//**
|
||||
Moves the explicit locks on user records to another page if a record
|
||||
list end is moved to another page. */
|
||||
UNIV_INTERN
|
||||
void
|
||||
lock_move_rec_list_end(
|
||||
/*===================*/
|
||||
const buf_block_t* new_block, /*!< in: index page to move to */
|
||||
const buf_block_t* block, /*!< in: index page */
|
||||
const rec_t* rec); /*!< in: record on page: this
|
||||
is the first record moved */
|
||||
/*************************************************************//**
|
||||
Moves the explicit locks on user records to another page if a record
|
||||
list start is moved to another page. */
|
||||
UNIV_INTERN
|
||||
void
|
||||
lock_move_rec_list_start(
|
||||
/*=====================*/
|
||||
const buf_block_t* new_block, /*!< in: index page to move to */
|
||||
const buf_block_t* block, /*!< in: index page */
|
||||
const rec_t* rec, /*!< in: record on page:
|
||||
this is the first
|
||||
record NOT copied */
|
||||
const rec_t* old_end); /*!< in: old
|
||||
previous-to-last
|
||||
record on new_page
|
||||
before the records
|
||||
were copied */
|
||||
/*************************************************************//**
|
||||
Updates the lock table when a page is split to the right. */
|
||||
UNIV_INTERN
|
||||
void
|
||||
lock_update_split_right(
|
||||
/*====================*/
|
||||
const buf_block_t* right_block, /*!< in: right page */
|
||||
const buf_block_t* left_block); /*!< in: left page */
|
||||
/*************************************************************//**
|
||||
Updates the lock table when a page is merged to the right. */
|
||||
UNIV_INTERN
|
||||
void
|
||||
lock_update_merge_right(
|
||||
/*====================*/
|
||||
const buf_block_t* right_block, /*!< in: right page to
|
||||
which merged */
|
||||
const rec_t* orig_succ, /*!< in: original
|
||||
successor of infimum
|
||||
on the right page
|
||||
before merge */
|
||||
const buf_block_t* left_block); /*!< in: merged index
|
||||
page which will be
|
||||
discarded */
|
||||
/*************************************************************//**
|
||||
Updates the lock table when the root page is copied to another in
|
||||
btr_root_raise_and_insert. Note that we leave lock structs on the
|
||||
root page, even though they do not make sense on other than leaf
|
||||
pages: the reason is that in a pessimistic update the infimum record
|
||||
of the root page will act as a dummy carrier of the locks of the record
|
||||
to be updated. */
|
||||
UNIV_INTERN
|
||||
void
|
||||
lock_update_root_raise(
|
||||
/*===================*/
|
||||
const buf_block_t* block, /*!< in: index page to which copied */
|
||||
const buf_block_t* root); /*!< in: root page */
|
||||
/*************************************************************//**
|
||||
Updates the lock table when a page is copied to another and the original page
|
||||
is removed from the chain of leaf pages, except if page is the root! */
|
||||
UNIV_INTERN
|
||||
void
|
||||
lock_update_copy_and_discard(
|
||||
/*=========================*/
|
||||
const buf_block_t* new_block, /*!< in: index page to
|
||||
which copied */
|
||||
const buf_block_t* block); /*!< in: index page;
|
||||
NOT the root! */
|
||||
/*************************************************************//**
|
||||
Updates the lock table when a page is split to the left. */
|
||||
UNIV_INTERN
|
||||
void
|
||||
lock_update_split_left(
|
||||
/*===================*/
|
||||
const buf_block_t* right_block, /*!< in: right page */
|
||||
const buf_block_t* left_block); /*!< in: left page */
|
||||
/*************************************************************//**
|
||||
Updates the lock table when a page is merged to the left. */
|
||||
UNIV_INTERN
|
||||
void
|
||||
lock_update_merge_left(
|
||||
/*===================*/
|
||||
const buf_block_t* left_block, /*!< in: left page to
|
||||
which merged */
|
||||
const rec_t* orig_pred, /*!< in: original predecessor
|
||||
of supremum on the left page
|
||||
before merge */
|
||||
const buf_block_t* right_block); /*!< in: merged index page
|
||||
which will be discarded */
|
||||
/*************************************************************//**
|
||||
Resets the original locks on heir and replaces them with gap type locks
|
||||
inherited from rec. */
|
||||
UNIV_INTERN
|
||||
void
|
||||
lock_rec_reset_and_inherit_gap_locks(
|
||||
/*=================================*/
|
||||
const buf_block_t* heir_block, /*!< in: block containing the
|
||||
record which inherits */
|
||||
const buf_block_t* block, /*!< in: block containing the
|
||||
record from which inherited;
|
||||
does NOT reset the locks on
|
||||
this record */
|
||||
ulint heir_heap_no, /*!< in: heap_no of the
|
||||
inheriting record */
|
||||
ulint heap_no); /*!< in: heap_no of the
|
||||
donating record */
|
||||
/*************************************************************//**
|
||||
Updates the lock table when a page is discarded. */
|
||||
UNIV_INTERN
|
||||
void
|
||||
lock_update_discard(
|
||||
/*================*/
|
||||
const buf_block_t* heir_block, /*!< in: index page
|
||||
which will inherit the locks */
|
||||
ulint heir_heap_no, /*!< in: heap_no of the record
|
||||
which will inherit the locks */
|
||||
const buf_block_t* block); /*!< in: index page
|
||||
which will be discarded */
|
||||
/*************************************************************//**
|
||||
Updates the lock table when a new user record is inserted. */
|
||||
UNIV_INTERN
|
||||
void
|
||||
lock_update_insert(
|
||||
/*===============*/
|
||||
const buf_block_t* block, /*!< in: buffer block containing rec */
|
||||
const rec_t* rec); /*!< in: the inserted record */
|
||||
/*************************************************************//**
|
||||
Updates the lock table when a record is removed. */
|
||||
UNIV_INTERN
|
||||
void
|
||||
lock_update_delete(
|
||||
/*===============*/
|
||||
const buf_block_t* block, /*!< in: buffer block containing rec */
|
||||
const rec_t* rec); /*!< in: the record to be removed */
|
||||
/*********************************************************************//**
|
||||
Stores on the page infimum record the explicit locks of another record.
|
||||
This function is used to store the lock state of a record when it is
|
||||
updated and the size of the record changes in the update. The record
|
||||
is in such an update moved, perhaps to another page. The infimum record
|
||||
acts as a dummy carrier record, taking care of lock releases while the
|
||||
actual record is being moved. */
|
||||
UNIV_INTERN
|
||||
void
|
||||
lock_rec_store_on_page_infimum(
|
||||
/*===========================*/
|
||||
const buf_block_t* block, /*!< in: buffer block containing rec */
|
||||
const rec_t* rec); /*!< in: record whose lock state
|
||||
is stored on the infimum
|
||||
record of the same page; lock
|
||||
bits are reset on the
|
||||
record */
|
||||
/*********************************************************************//**
|
||||
Restores the state of explicit lock requests on a single record, where the
|
||||
state was stored on the infimum of the page. */
|
||||
UNIV_INTERN
|
||||
void
|
||||
lock_rec_restore_from_page_infimum(
|
||||
/*===============================*/
|
||||
const buf_block_t* block, /*!< in: buffer block containing rec */
|
||||
const rec_t* rec, /*!< in: record whose lock state
|
||||
is restored */
|
||||
const buf_block_t* donator);/*!< in: page (rec is not
|
||||
necessarily on this page)
|
||||
whose infimum stored the lock
|
||||
state; lock bits are reset on
|
||||
the infimum */
|
||||
/*********************************************************************//**
|
||||
Determines if there are explicit record locks on a page.
|
||||
@return an explicit record lock on the page, or NULL if there are none */
|
||||
UNIV_INTERN
|
||||
lock_t*
|
||||
lock_rec_expl_exist_on_page(
|
||||
/*========================*/
|
||||
ulint space, /*!< in: space id */
|
||||
ulint page_no)/*!< in: page number */
|
||||
__attribute__((warn_unused_result));
|
||||
/*********************************************************************//**
|
||||
Checks if locks of other transactions prevent an immediate insert of
|
||||
a record. If they do, first tests if the query thread should anyway
|
||||
be suspended for some reason; if not, then puts the transaction and
|
||||
the query thread to the lock wait state and inserts a waiting request
|
||||
for a gap x-lock to the lock queue.
|
||||
@return DB_SUCCESS, DB_LOCK_WAIT, DB_DEADLOCK, or DB_QUE_THR_SUSPENDED */
|
||||
UNIV_INTERN
|
||||
dberr_t
|
||||
lock_rec_insert_check_and_lock(
|
||||
/*===========================*/
|
||||
ulint flags, /*!< in: if BTR_NO_LOCKING_FLAG bit is
|
||||
set, does nothing */
|
||||
const rec_t* rec, /*!< in: record after which to insert */
|
||||
buf_block_t* block, /*!< in/out: buffer block of rec */
|
||||
dict_index_t* index, /*!< in: index */
|
||||
que_thr_t* thr, /*!< in: query thread */
|
||||
mtr_t* mtr, /*!< in/out: mini-transaction */
|
||||
ibool* inherit)/*!< out: set to TRUE if the new
|
||||
inserted record maybe should inherit
|
||||
LOCK_GAP type locks from the successor
|
||||
record */
|
||||
__attribute__((nonnull, warn_unused_result));
|
||||
/*********************************************************************//**
|
||||
Checks if locks of other transactions prevent an immediate modify (update,
|
||||
delete mark, or delete unmark) of a clustered index record. If they do,
|
||||
first tests if the query thread should anyway be suspended for some
|
||||
reason; if not, then puts the transaction and the query thread to the
|
||||
lock wait state and inserts a waiting request for a record x-lock to the
|
||||
lock queue.
|
||||
@return DB_SUCCESS, DB_LOCK_WAIT, DB_DEADLOCK, or DB_QUE_THR_SUSPENDED */
|
||||
UNIV_INTERN
|
||||
dberr_t
|
||||
lock_clust_rec_modify_check_and_lock(
|
||||
/*=================================*/
|
||||
ulint flags, /*!< in: if BTR_NO_LOCKING_FLAG
|
||||
bit is set, does nothing */
|
||||
const buf_block_t* block, /*!< in: buffer block of rec */
|
||||
const rec_t* rec, /*!< in: record which should be
|
||||
modified */
|
||||
dict_index_t* index, /*!< in: clustered index */
|
||||
const ulint* offsets,/*!< in: rec_get_offsets(rec, index) */
|
||||
que_thr_t* thr) /*!< in: query thread */
|
||||
__attribute__((warn_unused_result, nonnull));
|
||||
/*********************************************************************//**
|
||||
Checks if locks of other transactions prevent an immediate modify
|
||||
(delete mark or delete unmark) of a secondary index record.
|
||||
@return DB_SUCCESS, DB_LOCK_WAIT, DB_DEADLOCK, or DB_QUE_THR_SUSPENDED */
|
||||
UNIV_INTERN
|
||||
dberr_t
|
||||
lock_sec_rec_modify_check_and_lock(
|
||||
/*===============================*/
|
||||
ulint flags, /*!< in: if BTR_NO_LOCKING_FLAG
|
||||
bit is set, does nothing */
|
||||
buf_block_t* block, /*!< in/out: buffer block of rec */
|
||||
const rec_t* rec, /*!< in: record which should be
|
||||
modified; NOTE: as this is a secondary
|
||||
index, we always have to modify the
|
||||
clustered index record first: see the
|
||||
comment below */
|
||||
dict_index_t* index, /*!< in: secondary index */
|
||||
que_thr_t* thr, /*!< in: query thread
|
||||
(can be NULL if BTR_NO_LOCKING_FLAG) */
|
||||
mtr_t* mtr) /*!< in/out: mini-transaction */
|
||||
__attribute__((warn_unused_result, nonnull(2,3,4,6)));
|
||||
/*********************************************************************//**
|
||||
Like lock_clust_rec_read_check_and_lock(), but reads a
|
||||
secondary index record.
|
||||
@return DB_SUCCESS, DB_SUCCESS_LOCKED_REC, DB_LOCK_WAIT, DB_DEADLOCK,
|
||||
or DB_QUE_THR_SUSPENDED */
|
||||
UNIV_INTERN
|
||||
dberr_t
|
||||
lock_sec_rec_read_check_and_lock(
|
||||
/*=============================*/
|
||||
ulint flags, /*!< in: if BTR_NO_LOCKING_FLAG
|
||||
bit is set, does nothing */
|
||||
const buf_block_t* block, /*!< in: buffer block of rec */
|
||||
const rec_t* rec, /*!< in: user record or page
|
||||
supremum record which should
|
||||
be read or passed over by a
|
||||
read cursor */
|
||||
dict_index_t* index, /*!< in: secondary index */
|
||||
const ulint* offsets,/*!< in: rec_get_offsets(rec, index) */
|
||||
enum lock_mode mode, /*!< in: mode of the lock which
|
||||
the read cursor should set on
|
||||
records: LOCK_S or LOCK_X; the
|
||||
latter is possible in
|
||||
SELECT FOR UPDATE */
|
||||
ulint gap_mode,/*!< in: LOCK_ORDINARY, LOCK_GAP, or
|
||||
LOCK_REC_NOT_GAP */
|
||||
que_thr_t* thr); /*!< in: query thread */
|
||||
/*********************************************************************//**
|
||||
Checks if locks of other transactions prevent an immediate read, or passing
|
||||
over by a read cursor, of a clustered index record. If they do, first tests
|
||||
if the query thread should anyway be suspended for some reason; if not, then
|
||||
puts the transaction and the query thread to the lock wait state and inserts a
|
||||
waiting request for a record lock to the lock queue. Sets the requested mode
|
||||
lock on the record.
|
||||
@return DB_SUCCESS, DB_SUCCESS_LOCKED_REC, DB_LOCK_WAIT, DB_DEADLOCK,
|
||||
or DB_QUE_THR_SUSPENDED */
|
||||
UNIV_INTERN
|
||||
dberr_t
|
||||
lock_clust_rec_read_check_and_lock(
|
||||
/*===============================*/
|
||||
ulint flags, /*!< in: if BTR_NO_LOCKING_FLAG
|
||||
bit is set, does nothing */
|
||||
const buf_block_t* block, /*!< in: buffer block of rec */
|
||||
const rec_t* rec, /*!< in: user record or page
|
||||
supremum record which should
|
||||
be read or passed over by a
|
||||
read cursor */
|
||||
dict_index_t* index, /*!< in: clustered index */
|
||||
const ulint* offsets,/*!< in: rec_get_offsets(rec, index) */
|
||||
enum lock_mode mode, /*!< in: mode of the lock which
|
||||
the read cursor should set on
|
||||
records: LOCK_S or LOCK_X; the
|
||||
latter is possible in
|
||||
SELECT FOR UPDATE */
|
||||
ulint gap_mode,/*!< in: LOCK_ORDINARY, LOCK_GAP, or
|
||||
LOCK_REC_NOT_GAP */
|
||||
que_thr_t* thr); /*!< in: query thread */
|
||||
/*********************************************************************//**
|
||||
Checks if locks of other transactions prevent an immediate read, or passing
|
||||
over by a read cursor, of a clustered index record. If they do, first tests
|
||||
if the query thread should anyway be suspended for some reason; if not, then
|
||||
puts the transaction and the query thread to the lock wait state and inserts a
|
||||
waiting request for a record lock to the lock queue. Sets the requested mode
|
||||
lock on the record. This is an alternative version of
|
||||
lock_clust_rec_read_check_and_lock() that does not require the parameter
|
||||
"offsets".
|
||||
@return DB_SUCCESS, DB_LOCK_WAIT, DB_DEADLOCK, or DB_QUE_THR_SUSPENDED */
|
||||
UNIV_INTERN
|
||||
dberr_t
|
||||
lock_clust_rec_read_check_and_lock_alt(
|
||||
/*===================================*/
|
||||
ulint flags, /*!< in: if BTR_NO_LOCKING_FLAG
|
||||
bit is set, does nothing */
|
||||
const buf_block_t* block, /*!< in: buffer block of rec */
|
||||
const rec_t* rec, /*!< in: user record or page
|
||||
supremum record which should
|
||||
be read or passed over by a
|
||||
read cursor */
|
||||
dict_index_t* index, /*!< in: clustered index */
|
||||
enum lock_mode mode, /*!< in: mode of the lock which
|
||||
the read cursor should set on
|
||||
records: LOCK_S or LOCK_X; the
|
||||
latter is possible in
|
||||
SELECT FOR UPDATE */
|
||||
ulint gap_mode,/*!< in: LOCK_ORDINARY, LOCK_GAP, or
|
||||
LOCK_REC_NOT_GAP */
|
||||
que_thr_t* thr) /*!< in: query thread */
|
||||
__attribute__((nonnull, warn_unused_result));
|
||||
/*********************************************************************//**
|
||||
Checks that a record is seen in a consistent read.
|
||||
@return true if sees, or false if an earlier version of the record
|
||||
should be retrieved */
|
||||
UNIV_INTERN
|
||||
bool
|
||||
lock_clust_rec_cons_read_sees(
|
||||
/*==========================*/
|
||||
const rec_t* rec, /*!< in: user record which should be read or
|
||||
passed over by a read cursor */
|
||||
dict_index_t* index, /*!< in: clustered index */
|
||||
const ulint* offsets,/*!< in: rec_get_offsets(rec, index) */
|
||||
read_view_t* view); /*!< in: consistent read view */
|
||||
/*********************************************************************//**
|
||||
Checks that a non-clustered index record is seen in a consistent read.
|
||||
|
||||
NOTE that a non-clustered index page contains so little information on
|
||||
its modifications that also in the case false, the present version of
|
||||
rec may be the right, but we must check this from the clustered index
|
||||
record.
|
||||
|
||||
@return true if certainly sees, or false if an earlier version of the
|
||||
clustered index record might be needed */
|
||||
UNIV_INTERN
|
||||
bool
|
||||
lock_sec_rec_cons_read_sees(
|
||||
/*========================*/
|
||||
const rec_t* rec, /*!< in: user record which
|
||||
should be read or passed over
|
||||
by a read cursor */
|
||||
const read_view_t* view) /*!< in: consistent read view */
|
||||
__attribute__((nonnull, warn_unused_result));
|
||||
/*********************************************************************//**
|
||||
Locks the specified database table in the mode given. If the lock cannot
|
||||
be granted immediately, the query thread is put to wait.
|
||||
@return DB_SUCCESS, DB_LOCK_WAIT, DB_DEADLOCK, or DB_QUE_THR_SUSPENDED */
|
||||
UNIV_INTERN
|
||||
dberr_t
|
||||
lock_table(
|
||||
/*=======*/
|
||||
ulint flags, /*!< in: if BTR_NO_LOCKING_FLAG bit is set,
|
||||
does nothing */
|
||||
dict_table_t* table, /*!< in/out: database table
|
||||
in dictionary cache */
|
||||
enum lock_mode mode, /*!< in: lock mode */
|
||||
que_thr_t* thr) /*!< in: query thread */
|
||||
__attribute__((nonnull, warn_unused_result));
|
||||
/*********************************************************************//**
|
||||
Creates a table IX lock object for a resurrected transaction. */
|
||||
UNIV_INTERN
|
||||
void
|
||||
lock_table_ix_resurrect(
|
||||
/*====================*/
|
||||
dict_table_t* table, /*!< in/out: table */
|
||||
trx_t* trx); /*!< in/out: transaction */
|
||||
/*************************************************************//**
|
||||
Removes a granted record lock of a transaction from the queue and grants
|
||||
locks to other transactions waiting in the queue if they now are entitled
|
||||
to a lock. */
|
||||
UNIV_INTERN
|
||||
void
|
||||
lock_rec_unlock(
|
||||
/*============*/
|
||||
trx_t* trx, /*!< in/out: transaction that has
|
||||
set a record lock */
|
||||
const buf_block_t* block, /*!< in: buffer block containing rec */
|
||||
const rec_t* rec, /*!< in: record */
|
||||
enum lock_mode lock_mode);/*!< in: LOCK_S or LOCK_X */
|
||||
/*********************************************************************//**
|
||||
Releases a transaction's locks, and releases possible other transactions
|
||||
waiting because of these locks. Change the state of the transaction to
|
||||
TRX_STATE_COMMITTED_IN_MEMORY. */
|
||||
UNIV_INTERN
|
||||
void
|
||||
lock_trx_release_locks(
|
||||
/*===================*/
|
||||
trx_t* trx); /*!< in/out: transaction */
|
||||
/*********************************************************************//**
|
||||
Removes locks on a table to be dropped or truncated.
|
||||
If remove_also_table_sx_locks is TRUE then table-level S and X locks are
|
||||
also removed in addition to other table-level and record-level locks.
|
||||
No lock, that is going to be removed, is allowed to be a wait lock. */
|
||||
UNIV_INTERN
|
||||
void
|
||||
lock_remove_all_on_table(
|
||||
/*=====================*/
|
||||
dict_table_t* table, /*!< in: table to be dropped
|
||||
or truncated */
|
||||
ibool remove_also_table_sx_locks);/*!< in: also removes
|
||||
table S and X locks */
|
||||
|
||||
/*********************************************************************//**
|
||||
Calculates the fold value of a page file address: used in inserting or
|
||||
searching for a lock in the hash table.
|
||||
@return folded value */
|
||||
UNIV_INLINE
|
||||
ulint
|
||||
lock_rec_fold(
|
||||
/*==========*/
|
||||
ulint space, /*!< in: space */
|
||||
ulint page_no)/*!< in: page number */
|
||||
__attribute__((const));
|
||||
/*********************************************************************//**
|
||||
Calculates the hash value of a page file address: used in inserting or
|
||||
searching for a lock in the hash table.
|
||||
@return hashed value */
|
||||
UNIV_INLINE
|
||||
ulint
|
||||
lock_rec_hash(
|
||||
/*==========*/
|
||||
ulint space, /*!< in: space */
|
||||
ulint page_no);/*!< in: page number */
|
||||
|
||||
/**********************************************************************//**
|
||||
Looks for a set bit in a record lock bitmap. Returns ULINT_UNDEFINED,
|
||||
if none found.
|
||||
@return bit index == heap number of the record, or ULINT_UNDEFINED if
|
||||
none found */
|
||||
UNIV_INTERN
|
||||
ulint
|
||||
lock_rec_find_set_bit(
|
||||
/*==================*/
|
||||
const lock_t* lock); /*!< in: record lock with at least one
|
||||
bit set */
|
||||
|
||||
/*********************************************************************//**
|
||||
Gets the source table of an ALTER TABLE transaction. The table must be
|
||||
covered by an IX or IS table lock.
|
||||
@return the source table of transaction, if it is covered by an IX or
|
||||
IS table lock; dest if there is no source table, and NULL if the
|
||||
transaction is locking more than two tables or an inconsistency is
|
||||
found */
|
||||
UNIV_INTERN
|
||||
dict_table_t*
|
||||
lock_get_src_table(
|
||||
/*===============*/
|
||||
trx_t* trx, /*!< in: transaction */
|
||||
dict_table_t* dest, /*!< in: destination of ALTER TABLE */
|
||||
enum lock_mode* mode); /*!< out: lock mode of the source table */
|
||||
/*********************************************************************//**
|
||||
Determine if the given table is exclusively "owned" by the given
|
||||
transaction, i.e., transaction holds LOCK_IX and possibly LOCK_AUTO_INC
|
||||
on the table.
|
||||
@return TRUE if table is only locked by trx, with LOCK_IX, and
|
||||
possibly LOCK_AUTO_INC */
|
||||
UNIV_INTERN
|
||||
ibool
|
||||
lock_is_table_exclusive(
|
||||
/*====================*/
|
||||
const dict_table_t* table, /*!< in: table */
|
||||
const trx_t* trx) /*!< in: transaction */
|
||||
__attribute__((nonnull));
|
||||
/*********************************************************************//**
|
||||
Checks if a lock request lock1 has to wait for request lock2.
|
||||
@return TRUE if lock1 has to wait for lock2 to be removed */
|
||||
UNIV_INTERN
|
||||
ibool
|
||||
lock_has_to_wait(
|
||||
/*=============*/
|
||||
const lock_t* lock1, /*!< in: waiting lock */
|
||||
const lock_t* lock2); /*!< in: another lock; NOTE that it is
|
||||
assumed that this has a lock bit set
|
||||
on the same record as in lock1 if the
|
||||
locks are record locks */
|
||||
/*********************************************************************//**
|
||||
Reports that a transaction id is insensible, i.e., in the future. */
|
||||
UNIV_INTERN
|
||||
void
|
||||
lock_report_trx_id_insanity(
|
||||
/*========================*/
|
||||
trx_id_t trx_id, /*!< in: trx id */
|
||||
const rec_t* rec, /*!< in: user record */
|
||||
dict_index_t* index, /*!< in: index */
|
||||
const ulint* offsets, /*!< in: rec_get_offsets(rec, index) */
|
||||
trx_id_t max_trx_id) /*!< in: trx_sys_get_max_trx_id() */
|
||||
__attribute__((nonnull));
|
||||
/*********************************************************************//**
|
||||
Prints info of a table lock. */
|
||||
UNIV_INTERN
|
||||
void
|
||||
lock_table_print(
|
||||
/*=============*/
|
||||
FILE* file, /*!< in: file where to print */
|
||||
const lock_t* lock); /*!< in: table type lock */
|
||||
/*********************************************************************//**
|
||||
Prints info of a record lock. */
|
||||
UNIV_INTERN
|
||||
void
|
||||
lock_rec_print(
|
||||
/*===========*/
|
||||
FILE* file, /*!< in: file where to print */
|
||||
const lock_t* lock); /*!< in: record type lock */
|
||||
/*********************************************************************//**
|
||||
Prints info of locks for all transactions.
|
||||
@return FALSE if not able to obtain lock mutex and exits without
|
||||
printing info */
|
||||
UNIV_INTERN
|
||||
ibool
|
||||
lock_print_info_summary(
|
||||
/*====================*/
|
||||
FILE* file, /*!< in: file where to print */
|
||||
ibool nowait) /*!< in: whether to wait for the lock mutex */
|
||||
__attribute__((nonnull, warn_unused_result));
|
||||
/*********************************************************************//**
|
||||
Prints info of locks for each transaction. This function assumes that the
|
||||
caller holds the lock mutex and more importantly it will release the lock
|
||||
mutex on behalf of the caller. (This should be fixed in the future). */
|
||||
UNIV_INTERN
|
||||
void
|
||||
lock_print_info_all_transactions(
|
||||
/*=============================*/
|
||||
FILE* file); /*!< in: file where to print */
|
||||
/*********************************************************************//**
|
||||
Return approximate number or record locks (bits set in the bitmap) for
|
||||
this transaction. Since delete-marked records may be removed, the
|
||||
record count will not be precise.
|
||||
The caller must be holding lock_sys->mutex. */
|
||||
UNIV_INTERN
|
||||
ulint
|
||||
lock_number_of_rows_locked(
|
||||
/*=======================*/
|
||||
const trx_lock_t* trx_lock) /*!< in: transaction locks */
|
||||
__attribute__((nonnull, warn_unused_result));
|
||||
|
||||
/*******************************************************************//**
|
||||
Gets the type of a lock. Non-inline version for using outside of the
|
||||
lock module.
|
||||
@return LOCK_TABLE or LOCK_REC */
|
||||
UNIV_INTERN
|
||||
ulint
|
||||
lock_get_type(
|
||||
/*==========*/
|
||||
const lock_t* lock); /*!< in: lock */
|
||||
|
||||
/*******************************************************************//**
|
||||
Gets the id of the transaction owning a lock.
|
||||
@return transaction id */
|
||||
UNIV_INTERN
|
||||
trx_id_t
|
||||
lock_get_trx_id(
|
||||
/*============*/
|
||||
const lock_t* lock); /*!< in: lock */
|
||||
|
||||
/*******************************************************************//**
|
||||
Gets the mode of a lock in a human readable string.
|
||||
The string should not be free()'d or modified.
|
||||
@return lock mode */
|
||||
UNIV_INTERN
|
||||
const char*
|
||||
lock_get_mode_str(
|
||||
/*==============*/
|
||||
const lock_t* lock); /*!< in: lock */
|
||||
|
||||
/*******************************************************************//**
|
||||
Gets the type of a lock in a human readable string.
|
||||
The string should not be free()'d or modified.
|
||||
@return lock type */
|
||||
UNIV_INTERN
|
||||
const char*
|
||||
lock_get_type_str(
|
||||
/*==============*/
|
||||
const lock_t* lock); /*!< in: lock */
|
||||
|
||||
/*******************************************************************//**
|
||||
Gets the id of the table on which the lock is.
|
||||
@return id of the table */
|
||||
UNIV_INTERN
|
||||
table_id_t
|
||||
lock_get_table_id(
|
||||
/*==============*/
|
||||
const lock_t* lock); /*!< in: lock */
|
||||
|
||||
/*******************************************************************//**
|
||||
Gets the name of the table on which the lock is.
|
||||
The string should not be free()'d or modified.
|
||||
@return name of the table */
|
||||
UNIV_INTERN
|
||||
const char*
|
||||
lock_get_table_name(
|
||||
/*================*/
|
||||
const lock_t* lock); /*!< in: lock */
|
||||
|
||||
/*******************************************************************//**
|
||||
For a record lock, gets the index on which the lock is.
|
||||
@return index */
|
||||
UNIV_INTERN
|
||||
const dict_index_t*
|
||||
lock_rec_get_index(
|
||||
/*===============*/
|
||||
const lock_t* lock); /*!< in: lock */
|
||||
|
||||
/*******************************************************************//**
|
||||
For a record lock, gets the name of the index on which the lock is.
|
||||
The string should not be free()'d or modified.
|
||||
@return name of the index */
|
||||
UNIV_INTERN
|
||||
const char*
|
||||
lock_rec_get_index_name(
|
||||
/*====================*/
|
||||
const lock_t* lock); /*!< in: lock */
|
||||
|
||||
/*******************************************************************//**
|
||||
For a record lock, gets the tablespace number on which the lock is.
|
||||
@return tablespace number */
|
||||
UNIV_INTERN
|
||||
ulint
|
||||
lock_rec_get_space_id(
|
||||
/*==================*/
|
||||
const lock_t* lock); /*!< in: lock */
|
||||
|
||||
/*******************************************************************//**
|
||||
For a record lock, gets the page number on which the lock is.
|
||||
@return page number */
|
||||
UNIV_INTERN
|
||||
ulint
|
||||
lock_rec_get_page_no(
|
||||
/*=================*/
|
||||
const lock_t* lock); /*!< in: lock */
|
||||
/*******************************************************************//**
|
||||
Check if there are any locks (table or rec) against table.
|
||||
@return TRUE if locks exist */
|
||||
UNIV_INTERN
|
||||
ibool
|
||||
lock_table_has_locks(
|
||||
/*=================*/
|
||||
const dict_table_t* table); /*!< in: check if there are any locks
|
||||
held on records in this table or on the
|
||||
table itself */
|
||||
|
||||
/*********************************************************************//**
|
||||
A thread which wakes up threads whose lock wait may have lasted too long.
|
||||
@return a dummy parameter */
|
||||
extern "C" UNIV_INTERN
|
||||
os_thread_ret_t
|
||||
DECLARE_THREAD(lock_wait_timeout_thread)(
|
||||
/*=====================================*/
|
||||
void* arg); /*!< in: a dummy parameter required by
|
||||
os_thread_create */
|
||||
|
||||
/********************************************************************//**
|
||||
Releases a user OS thread waiting for a lock to be released, if the
|
||||
thread is already suspended. */
|
||||
UNIV_INTERN
|
||||
void
|
||||
lock_wait_release_thread_if_suspended(
|
||||
/*==================================*/
|
||||
que_thr_t* thr); /*!< in: query thread associated with the
|
||||
user OS thread */
|
||||
|
||||
/***************************************************************//**
|
||||
Puts a user OS thread to wait for a lock to be released. If an error
|
||||
occurs during the wait trx->error_state associated with thr is
|
||||
!= DB_SUCCESS when we return. DB_LOCK_WAIT_TIMEOUT and DB_DEADLOCK
|
||||
are possible errors. DB_DEADLOCK is returned if selective deadlock
|
||||
resolution chose this transaction as a victim. */
|
||||
UNIV_INTERN
|
||||
void
|
||||
lock_wait_suspend_thread(
|
||||
/*=====================*/
|
||||
que_thr_t* thr); /*!< in: query thread associated with the
|
||||
user OS thread */
|
||||
/*********************************************************************//**
|
||||
Unlocks AUTO_INC type locks that were possibly reserved by a trx. This
|
||||
function should be called at the the end of an SQL statement, by the
|
||||
connection thread that owns the transaction (trx->mysql_thd). */
|
||||
UNIV_INTERN
|
||||
void
|
||||
lock_unlock_table_autoinc(
|
||||
/*======================*/
|
||||
trx_t* trx); /*!< in/out: transaction */
|
||||
/*********************************************************************//**
|
||||
Check whether the transaction has already been rolled back because it
|
||||
was selected as a deadlock victim, or if it has to wait then cancel
|
||||
the wait lock.
|
||||
@return DB_DEADLOCK, DB_LOCK_WAIT or DB_SUCCESS */
|
||||
UNIV_INTERN
|
||||
dberr_t
|
||||
lock_trx_handle_wait(
|
||||
/*=================*/
|
||||
trx_t* trx) /*!< in/out: trx lock state */
|
||||
__attribute__((nonnull));
|
||||
/*********************************************************************//**
|
||||
Get the number of locks on a table.
|
||||
@return number of locks */
|
||||
UNIV_INTERN
|
||||
ulint
|
||||
lock_table_get_n_locks(
|
||||
/*===================*/
|
||||
const dict_table_t* table) /*!< in: table */
|
||||
__attribute__((nonnull));
|
||||
#ifdef UNIV_DEBUG
|
||||
/*********************************************************************//**
|
||||
Checks that a transaction id is sensible, i.e., not in the future.
|
||||
@return true if ok */
|
||||
UNIV_INTERN
|
||||
bool
|
||||
lock_check_trx_id_sanity(
|
||||
/*=====================*/
|
||||
trx_id_t trx_id, /*!< in: trx id */
|
||||
const rec_t* rec, /*!< in: user record */
|
||||
dict_index_t* index, /*!< in: index */
|
||||
const ulint* offsets) /*!< in: rec_get_offsets(rec, index) */
|
||||
__attribute__((nonnull, warn_unused_result));
|
||||
/*******************************************************************//**
|
||||
Check if the transaction holds any locks on the sys tables
|
||||
or its records.
|
||||
@return the strongest lock found on any sys table or 0 for none */
|
||||
UNIV_INTERN
|
||||
const lock_t*
|
||||
lock_trx_has_sys_table_locks(
|
||||
/*=========================*/
|
||||
const trx_t* trx) /*!< in: transaction to check */
|
||||
__attribute__((warn_unused_result));
|
||||
|
||||
/*******************************************************************//**
|
||||
Check if the transaction holds an exclusive lock on a record.
|
||||
@return whether the locks are held */
|
||||
UNIV_INTERN
|
||||
bool
|
||||
lock_trx_has_rec_x_lock(
|
||||
/*====================*/
|
||||
const trx_t* trx, /*!< in: transaction to check */
|
||||
const dict_table_t* table, /*!< in: table to check */
|
||||
const buf_block_t* block, /*!< in: buffer block of the record */
|
||||
ulint heap_no)/*!< in: record heap number */
|
||||
__attribute__((nonnull, warn_unused_result));
|
||||
#endif /* UNIV_DEBUG */
|
||||
|
||||
/** Lock modes and types */
|
||||
/* @{ */
|
||||
#define LOCK_MODE_MASK 0xFUL /*!< mask used to extract mode from the
|
||||
type_mode field in a lock */
|
||||
/** Lock types */
|
||||
/* @{ */
|
||||
#define LOCK_TABLE 16 /*!< table lock */
|
||||
#define LOCK_REC 32 /*!< record lock */
|
||||
#define LOCK_TYPE_MASK 0xF0UL /*!< mask used to extract lock type from the
|
||||
type_mode field in a lock */
|
||||
#if LOCK_MODE_MASK & LOCK_TYPE_MASK
|
||||
# error "LOCK_MODE_MASK & LOCK_TYPE_MASK"
|
||||
#endif
|
||||
|
||||
#define LOCK_WAIT 256 /*!< Waiting lock flag; when set, it
|
||||
means that the lock has not yet been
|
||||
granted, it is just waiting for its
|
||||
turn in the wait queue */
|
||||
/* Precise modes */
|
||||
#define LOCK_ORDINARY 0 /*!< this flag denotes an ordinary
|
||||
next-key lock in contrast to LOCK_GAP
|
||||
or LOCK_REC_NOT_GAP */
|
||||
#define LOCK_GAP 512 /*!< when this bit is set, it means that the
|
||||
lock holds only on the gap before the record;
|
||||
for instance, an x-lock on the gap does not
|
||||
give permission to modify the record on which
|
||||
the bit is set; locks of this type are created
|
||||
when records are removed from the index chain
|
||||
of records */
|
||||
#define LOCK_REC_NOT_GAP 1024 /*!< this bit means that the lock is only on
|
||||
the index record and does NOT block inserts
|
||||
to the gap before the index record; this is
|
||||
used in the case when we retrieve a record
|
||||
with a unique key, and is also used in
|
||||
locking plain SELECTs (not part of UPDATE
|
||||
or DELETE) when the user has set the READ
|
||||
COMMITTED isolation level */
|
||||
#define LOCK_INSERT_INTENTION 2048 /*!< this bit is set when we place a waiting
|
||||
gap type record lock request in order to let
|
||||
an insert of an index record to wait until
|
||||
there are no conflicting locks by other
|
||||
transactions on the gap; note that this flag
|
||||
remains set when the waiting lock is granted,
|
||||
or if the lock is inherited to a neighboring
|
||||
record */
|
||||
|
||||
#if (LOCK_WAIT|LOCK_GAP|LOCK_REC_NOT_GAP|LOCK_INSERT_INTENTION)&LOCK_MODE_MASK
|
||||
# error
|
||||
#endif
|
||||
#if (LOCK_WAIT|LOCK_GAP|LOCK_REC_NOT_GAP|LOCK_INSERT_INTENTION)&LOCK_TYPE_MASK
|
||||
# error
|
||||
#endif
|
||||
/* @} */
|
||||
|
||||
/** Lock operation struct */
|
||||
struct lock_op_t{
|
||||
dict_table_t* table; /*!< table to be locked */
|
||||
enum lock_mode mode; /*!< lock mode */
|
||||
};
|
||||
|
||||
/** The lock system struct */
|
||||
struct lock_sys_t{
|
||||
ib_mutex_t mutex; /*!< Mutex protecting the
|
||||
locks */
|
||||
hash_table_t* rec_hash; /*!< hash table of the record
|
||||
locks */
|
||||
ib_mutex_t wait_mutex; /*!< Mutex protecting the
|
||||
next two fields */
|
||||
srv_slot_t* waiting_threads; /*!< Array of user threads
|
||||
suspended while waiting for
|
||||
locks within InnoDB, protected
|
||||
by the lock_sys->wait_mutex */
|
||||
srv_slot_t* last_slot; /*!< highest slot ever used
|
||||
in the waiting_threads array,
|
||||
protected by
|
||||
lock_sys->wait_mutex */
|
||||
ibool rollback_complete;
|
||||
/*!< TRUE if rollback of all
|
||||
recovered transactions is
|
||||
complete. Protected by
|
||||
lock_sys->mutex */
|
||||
|
||||
ulint n_lock_max_wait_time; /*!< Max wait time */
|
||||
|
||||
os_event_t timeout_event; /*!< Set to the event that is
|
||||
created in the lock wait monitor
|
||||
thread. A value of 0 means the
|
||||
thread is not active */
|
||||
|
||||
bool timeout_thread_active; /*!< True if the timeout thread
|
||||
is running */
|
||||
};
|
||||
|
||||
/** The lock system */
|
||||
extern lock_sys_t* lock_sys;
|
||||
|
||||
/** Test if lock_sys->mutex can be acquired without waiting. */
|
||||
#define lock_mutex_enter_nowait() mutex_enter_nowait(&lock_sys->mutex)
|
||||
|
||||
/** Test if lock_sys->mutex is owned. */
|
||||
#define lock_mutex_own() mutex_own(&lock_sys->mutex)
|
||||
|
||||
/** Acquire the lock_sys->mutex. */
|
||||
#define lock_mutex_enter() do { \
|
||||
mutex_enter(&lock_sys->mutex); \
|
||||
} while (0)
|
||||
|
||||
/** Release the lock_sys->mutex. */
|
||||
#define lock_mutex_exit() do { \
|
||||
mutex_exit(&lock_sys->mutex); \
|
||||
} while (0)
|
||||
|
||||
/** Test if lock_sys->wait_mutex is owned. */
|
||||
#define lock_wait_mutex_own() mutex_own(&lock_sys->wait_mutex)
|
||||
|
||||
/** Acquire the lock_sys->wait_mutex. */
|
||||
#define lock_wait_mutex_enter() do { \
|
||||
mutex_enter(&lock_sys->wait_mutex); \
|
||||
} while (0)
|
||||
|
||||
/** Release the lock_sys->wait_mutex. */
|
||||
#define lock_wait_mutex_exit() do { \
|
||||
mutex_exit(&lock_sys->wait_mutex); \
|
||||
} while (0)
|
||||
|
||||
#ifndef UNIV_NONINL
|
||||
#include "lock0lock.ic"
|
||||
#endif
|
||||
|
||||
#endif
|
||||
92
storage/innobase/include/lock0lock.ic
Normal file
92
storage/innobase/include/lock0lock.ic
Normal file
|
|
@ -0,0 +1,92 @@
|
|||
/*****************************************************************************
|
||||
|
||||
Copyright (c) 1996, 2009, Oracle and/or its affiliates. All Rights Reserved.
|
||||
|
||||
This program is free software; you can redistribute it and/or modify it under
|
||||
the terms of the GNU General Public License as published by the Free Software
|
||||
Foundation; version 2 of the License.
|
||||
|
||||
This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
|
||||
FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License along with
|
||||
this program; if not, write to the Free Software Foundation, Inc.,
|
||||
51 Franklin Street, Suite 500, Boston, MA 02110-1335 USA
|
||||
|
||||
*****************************************************************************/
|
||||
|
||||
/**************************************************//**
|
||||
@file include/lock0lock.ic
|
||||
The transaction lock system
|
||||
|
||||
Created 5/7/1996 Heikki Tuuri
|
||||
*******************************************************/
|
||||
|
||||
#include "sync0sync.h"
|
||||
#include "srv0srv.h"
|
||||
#include "dict0dict.h"
|
||||
#include "row0row.h"
|
||||
#include "trx0sys.h"
|
||||
#include "trx0trx.h"
|
||||
#include "buf0buf.h"
|
||||
#include "page0page.h"
|
||||
#include "page0cur.h"
|
||||
#include "row0vers.h"
|
||||
#include "que0que.h"
|
||||
#include "btr0cur.h"
|
||||
#include "read0read.h"
|
||||
#include "log0recv.h"
|
||||
|
||||
/*********************************************************************//**
|
||||
Calculates the fold value of a page file address: used in inserting or
|
||||
searching for a lock in the hash table.
|
||||
@return folded value */
|
||||
UNIV_INLINE
|
||||
ulint
|
||||
lock_rec_fold(
|
||||
/*==========*/
|
||||
ulint space, /*!< in: space */
|
||||
ulint page_no)/*!< in: page number */
|
||||
{
|
||||
return(ut_fold_ulint_pair(space, page_no));
|
||||
}
|
||||
|
||||
/*********************************************************************//**
|
||||
Calculates the hash value of a page file address: used in inserting or
|
||||
searching for a lock in the hash table.
|
||||
@return hashed value */
|
||||
UNIV_INLINE
|
||||
ulint
|
||||
lock_rec_hash(
|
||||
/*==========*/
|
||||
ulint space, /*!< in: space */
|
||||
ulint page_no)/*!< in: page number */
|
||||
{
|
||||
return(hash_calc_hash(lock_rec_fold(space, page_no),
|
||||
lock_sys->rec_hash));
|
||||
}
|
||||
|
||||
/*********************************************************************//**
|
||||
Gets the heap_no of the smallest user record on a page.
|
||||
@return heap_no of smallest user record, or PAGE_HEAP_NO_SUPREMUM */
|
||||
UNIV_INLINE
|
||||
ulint
|
||||
lock_get_min_heap_no(
|
||||
/*=================*/
|
||||
const buf_block_t* block) /*!< in: buffer block */
|
||||
{
|
||||
const page_t* page = block->frame;
|
||||
|
||||
if (page_is_comp(page)) {
|
||||
return(rec_get_heap_no_new(
|
||||
page
|
||||
+ rec_get_next_offs(page + PAGE_NEW_INFIMUM,
|
||||
TRUE)));
|
||||
} else {
|
||||
return(rec_get_heap_no_old(
|
||||
page
|
||||
+ rec_get_next_offs(page + PAGE_OLD_INFIMUM,
|
||||
FALSE)));
|
||||
}
|
||||
}
|
||||
126
storage/innobase/include/lock0priv.h
Normal file
126
storage/innobase/include/lock0priv.h
Normal file
|
|
@ -0,0 +1,126 @@
|
|||
/*****************************************************************************
|
||||
|
||||
Copyright (c) 2007, 2011, Oracle and/or its affiliates. All Rights Reserved.
|
||||
|
||||
This program is free software; you can redistribute it and/or modify it under
|
||||
the terms of the GNU General Public License as published by the Free Software
|
||||
Foundation; version 2 of the License.
|
||||
|
||||
This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
|
||||
FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License along with
|
||||
this program; if not, write to the Free Software Foundation, Inc.,
|
||||
51 Franklin Street, Suite 500, Boston, MA 02110-1335 USA
|
||||
|
||||
*****************************************************************************/
|
||||
|
||||
/**************************************************//**
|
||||
@file include/lock0priv.h
|
||||
Lock module internal structures and methods.
|
||||
|
||||
Created July 12, 2007 Vasil Dimov
|
||||
*******************************************************/
|
||||
|
||||
#ifndef lock0priv_h
|
||||
#define lock0priv_h
|
||||
|
||||
#ifndef LOCK_MODULE_IMPLEMENTATION
|
||||
/* If you need to access members of the structures defined in this
|
||||
file, please write appropriate functions that retrieve them and put
|
||||
those functions in lock/ */
|
||||
#error Do not include lock0priv.h outside of the lock/ module
|
||||
#endif
|
||||
|
||||
#include "univ.i"
|
||||
#include "dict0types.h"
|
||||
#include "hash0hash.h"
|
||||
#include "trx0types.h"
|
||||
#include "ut0lst.h"
|
||||
|
||||
/** A table lock */
|
||||
struct lock_table_t {
|
||||
dict_table_t* table; /*!< database table in dictionary
|
||||
cache */
|
||||
UT_LIST_NODE_T(lock_t)
|
||||
locks; /*!< list of locks on the same
|
||||
table */
|
||||
};
|
||||
|
||||
/** Record lock for a page */
|
||||
struct lock_rec_t {
|
||||
ulint space; /*!< space id */
|
||||
ulint page_no; /*!< page number */
|
||||
ulint n_bits; /*!< number of bits in the lock
|
||||
bitmap; NOTE: the lock bitmap is
|
||||
placed immediately after the
|
||||
lock struct */
|
||||
};
|
||||
|
||||
/** Lock struct; protected by lock_sys->mutex */
|
||||
struct lock_t {
|
||||
trx_t* trx; /*!< transaction owning the
|
||||
lock */
|
||||
UT_LIST_NODE_T(lock_t)
|
||||
trx_locks; /*!< list of the locks of the
|
||||
transaction */
|
||||
ulint type_mode; /*!< lock type, mode, LOCK_GAP or
|
||||
LOCK_REC_NOT_GAP,
|
||||
LOCK_INSERT_INTENTION,
|
||||
wait flag, ORed */
|
||||
hash_node_t hash; /*!< hash chain node for a record
|
||||
lock */
|
||||
dict_index_t* index; /*!< index for a record lock */
|
||||
union {
|
||||
lock_table_t tab_lock;/*!< table lock */
|
||||
lock_rec_t rec_lock;/*!< record lock */
|
||||
} un_member; /*!< lock details */
|
||||
};
|
||||
|
||||
/*********************************************************************//**
|
||||
Gets the type of a lock.
|
||||
@return LOCK_TABLE or LOCK_REC */
|
||||
UNIV_INLINE
|
||||
ulint
|
||||
lock_get_type_low(
|
||||
/*==============*/
|
||||
const lock_t* lock); /*!< in: lock */
|
||||
|
||||
/*********************************************************************//**
|
||||
Gets the previous record lock set on a record.
|
||||
@return previous lock on the same record, NULL if none exists */
|
||||
UNIV_INTERN
|
||||
const lock_t*
|
||||
lock_rec_get_prev(
|
||||
/*==============*/
|
||||
const lock_t* in_lock,/*!< in: record lock */
|
||||
ulint heap_no);/*!< in: heap number of the record */
|
||||
|
||||
/*********************************************************************//**
|
||||
Cancels a waiting lock request and releases possible other transactions
|
||||
waiting behind it. */
|
||||
UNIV_INTERN
|
||||
void
|
||||
lock_cancel_waiting_and_release(
|
||||
/*============================*/
|
||||
lock_t* lock); /*!< in/out: waiting lock request */
|
||||
|
||||
/*********************************************************************//**
|
||||
Checks if some transaction has an implicit x-lock on a record in a clustered
|
||||
index.
|
||||
@return transaction id of the transaction which has the x-lock, or 0 */
|
||||
UNIV_INLINE
|
||||
trx_id_t
|
||||
lock_clust_rec_some_has_impl(
|
||||
/*=========================*/
|
||||
const rec_t* rec, /*!< in: user record */
|
||||
const dict_index_t* index, /*!< in: clustered index */
|
||||
const ulint* offsets)/*!< in: rec_get_offsets(rec, index) */
|
||||
__attribute__((nonnull, warn_unused_result));
|
||||
|
||||
#ifndef UNIV_NONINL
|
||||
#include "lock0priv.ic"
|
||||
#endif
|
||||
|
||||
#endif /* lock0priv_h */
|
||||
67
storage/innobase/include/lock0priv.ic
Normal file
67
storage/innobase/include/lock0priv.ic
Normal file
|
|
@ -0,0 +1,67 @@
|
|||
/*****************************************************************************
|
||||
|
||||
Copyright (c) 2007, 2009, Oracle and/or its affiliates. All Rights Reserved.
|
||||
|
||||
This program is free software; you can redistribute it and/or modify it under
|
||||
the terms of the GNU General Public License as published by the Free Software
|
||||
Foundation; version 2 of the License.
|
||||
|
||||
This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
|
||||
FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License along with
|
||||
this program; if not, write to the Free Software Foundation, Inc.,
|
||||
51 Franklin Street, Suite 500, Boston, MA 02110-1335 USA
|
||||
|
||||
*****************************************************************************/
|
||||
|
||||
/**************************************************//**
|
||||
@file include/lock0priv.ic
|
||||
Lock module internal inline methods.
|
||||
|
||||
Created July 16, 2007 Vasil Dimov
|
||||
*******************************************************/
|
||||
|
||||
/* This file contains only methods which are used in
|
||||
lock/lock0* files, other than lock/lock0lock.cc.
|
||||
I.e. lock/lock0lock.cc contains more internal inline
|
||||
methods but they are used only in that file. */
|
||||
|
||||
#ifndef LOCK_MODULE_IMPLEMENTATION
|
||||
#error Do not include lock0priv.ic outside of the lock/ module
|
||||
#endif
|
||||
|
||||
/*********************************************************************//**
|
||||
Gets the type of a lock.
|
||||
@return LOCK_TABLE or LOCK_REC */
|
||||
UNIV_INLINE
|
||||
ulint
|
||||
lock_get_type_low(
|
||||
/*==============*/
|
||||
const lock_t* lock) /*!< in: lock */
|
||||
{
|
||||
ut_ad(lock);
|
||||
|
||||
return(lock->type_mode & LOCK_TYPE_MASK);
|
||||
}
|
||||
|
||||
/*********************************************************************//**
|
||||
Checks if some transaction has an implicit x-lock on a record in a clustered
|
||||
index.
|
||||
@return transaction id of the transaction which has the x-lock, or 0 */
|
||||
UNIV_INLINE
|
||||
trx_id_t
|
||||
lock_clust_rec_some_has_impl(
|
||||
/*=========================*/
|
||||
const rec_t* rec, /*!< in: user record */
|
||||
const dict_index_t* index, /*!< in: clustered index */
|
||||
const ulint* offsets)/*!< in: rec_get_offsets(rec, index) */
|
||||
{
|
||||
ut_ad(dict_index_is_clust(index));
|
||||
ut_ad(page_rec_is_user_rec(rec));
|
||||
|
||||
return(row_get_rec_trx_id(rec, index, offsets));
|
||||
}
|
||||
|
||||
/* vim: set filetype=c: */
|
||||
47
storage/innobase/include/lock0types.h
Normal file
47
storage/innobase/include/lock0types.h
Normal file
|
|
@ -0,0 +1,47 @@
|
|||
/*****************************************************************************
|
||||
|
||||
Copyright (c) 1996, 2009, Oracle and/or its affiliates. All Rights Reserved.
|
||||
|
||||
This program is free software; you can redistribute it and/or modify it under
|
||||
the terms of the GNU General Public License as published by the Free Software
|
||||
Foundation; version 2 of the License.
|
||||
|
||||
This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
|
||||
FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License along with
|
||||
this program; if not, write to the Free Software Foundation, Inc.,
|
||||
51 Franklin Street, Suite 500, Boston, MA 02110-1335 USA
|
||||
|
||||
*****************************************************************************/
|
||||
|
||||
/**************************************************//**
|
||||
@file include/lock0types.h
|
||||
The transaction lock system global types
|
||||
|
||||
Created 5/7/1996 Heikki Tuuri
|
||||
*******************************************************/
|
||||
|
||||
#ifndef lock0types_h
|
||||
#define lock0types_h
|
||||
|
||||
#define lock_t ib_lock_t
|
||||
struct lock_t;
|
||||
struct lock_sys_t;
|
||||
|
||||
/* Basic lock modes */
|
||||
enum lock_mode {
|
||||
LOCK_IS = 0, /* intention shared */
|
||||
LOCK_IX, /* intention exclusive */
|
||||
LOCK_S, /* shared */
|
||||
LOCK_X, /* exclusive */
|
||||
LOCK_AUTO_INC, /* locks the auto-inc counter of a table
|
||||
in an exclusive mode */
|
||||
LOCK_NONE, /* this is used elsewhere to note consistent read */
|
||||
LOCK_NUM = LOCK_NONE, /* number of lock modes */
|
||||
LOCK_NONE_UNSET = 255
|
||||
};
|
||||
|
||||
|
||||
#endif
|
||||
999
storage/innobase/include/log0log.h
Normal file
999
storage/innobase/include/log0log.h
Normal file
|
|
@ -0,0 +1,999 @@
|
|||
/*****************************************************************************
|
||||
|
||||
Copyright (c) 1995, 2013, Oracle and/or its affiliates. All rights reserved.
|
||||
Copyright (c) 2009, Google Inc.
|
||||
|
||||
Portions of this file contain modifications contributed and copyrighted by
|
||||
Google, Inc. Those modifications are gratefully acknowledged and are described
|
||||
briefly in the InnoDB documentation. The contributions by Google are
|
||||
incorporated with their permission, and subject to the conditions contained in
|
||||
the file COPYING.Google.
|
||||
|
||||
This program is free software; you can redistribute it and/or modify it under
|
||||
the terms of the GNU General Public License as published by the Free Software
|
||||
Foundation; version 2 of the License.
|
||||
|
||||
This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
|
||||
FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License along with
|
||||
this program; if not, write to the Free Software Foundation, Inc.,
|
||||
51 Franklin Street, Suite 500, Boston, MA 02110-1335 USA
|
||||
|
||||
*****************************************************************************/
|
||||
|
||||
/**************************************************//**
|
||||
@file include/log0log.h
|
||||
Database log
|
||||
|
||||
Created 12/9/1995 Heikki Tuuri
|
||||
*******************************************************/
|
||||
|
||||
#ifndef log0log_h
|
||||
#define log0log_h
|
||||
|
||||
#include "univ.i"
|
||||
#include "ut0byte.h"
|
||||
#include "ut0lst.h"
|
||||
#ifndef UNIV_HOTBACKUP
|
||||
#include "sync0sync.h"
|
||||
#include "sync0rw.h"
|
||||
#endif /* !UNIV_HOTBACKUP */
|
||||
|
||||
/* Type used for all log sequence number storage and arithmetics */
|
||||
typedef ib_uint64_t lsn_t;
|
||||
#define LSN_MAX IB_UINT64_MAX
|
||||
|
||||
#define LSN_PF UINT64PF
|
||||
|
||||
/** Redo log buffer */
|
||||
struct log_t;
|
||||
/** Redo log group */
|
||||
struct log_group_t;
|
||||
|
||||
#ifdef UNIV_DEBUG
|
||||
/** Flag: write to log file? */
|
||||
extern ibool log_do_write;
|
||||
/** Flag: enable debug output when writing to the log? */
|
||||
extern ibool log_debug_writes;
|
||||
#else /* UNIV_DEBUG */
|
||||
/** Write to log */
|
||||
# define log_do_write TRUE
|
||||
#endif /* UNIV_DEBUG */
|
||||
|
||||
/** Wait modes for log_write_up_to @{ */
|
||||
#define LOG_NO_WAIT 91
|
||||
#define LOG_WAIT_ONE_GROUP 92
|
||||
#define LOG_WAIT_ALL_GROUPS 93
|
||||
/* @} */
|
||||
/** Maximum number of log groups in log_group_t::checkpoint_buf */
|
||||
#define LOG_MAX_N_GROUPS 32
|
||||
|
||||
/*******************************************************************//**
|
||||
Calculates where in log files we find a specified lsn.
|
||||
@return log file number */
|
||||
UNIV_INTERN
|
||||
ulint
|
||||
log_calc_where_lsn_is(
|
||||
/*==================*/
|
||||
ib_int64_t* log_file_offset, /*!< out: offset in that file
|
||||
(including the header) */
|
||||
ib_uint64_t first_header_lsn, /*!< in: first log file start
|
||||
lsn */
|
||||
ib_uint64_t lsn, /*!< in: lsn whose position to
|
||||
determine */
|
||||
ulint n_log_files, /*!< in: total number of log
|
||||
files */
|
||||
ib_int64_t log_file_size); /*!< in: log file size
|
||||
(including the header) */
|
||||
#ifndef UNIV_HOTBACKUP
|
||||
/************************************************************//**
|
||||
Writes to the log the string given. The log must be released with
|
||||
log_release.
|
||||
@return end lsn of the log record, zero if did not succeed */
|
||||
UNIV_INLINE
|
||||
lsn_t
|
||||
log_reserve_and_write_fast(
|
||||
/*=======================*/
|
||||
const void* str, /*!< in: string */
|
||||
ulint len, /*!< in: string length */
|
||||
lsn_t* start_lsn);/*!< out: start lsn of the log record */
|
||||
/***********************************************************************//**
|
||||
Releases the log mutex. */
|
||||
UNIV_INLINE
|
||||
void
|
||||
log_release(void);
|
||||
/*=============*/
|
||||
/***********************************************************************//**
|
||||
Checks if there is need for a log buffer flush or a new checkpoint, and does
|
||||
this if yes. Any database operation should call this when it has modified
|
||||
more than about 4 pages. NOTE that this function may only be called when the
|
||||
OS thread owns no synchronization objects except the dictionary mutex. */
|
||||
UNIV_INLINE
|
||||
void
|
||||
log_free_check(void);
|
||||
/*================*/
|
||||
/************************************************************//**
|
||||
Opens the log for log_write_low. The log must be closed with log_close and
|
||||
released with log_release.
|
||||
@return start lsn of the log record */
|
||||
UNIV_INTERN
|
||||
lsn_t
|
||||
log_reserve_and_open(
|
||||
/*=================*/
|
||||
ulint len); /*!< in: length of data to be catenated */
|
||||
/************************************************************//**
|
||||
Writes to the log the string given. It is assumed that the caller holds the
|
||||
log mutex. */
|
||||
UNIV_INTERN
|
||||
void
|
||||
log_write_low(
|
||||
/*==========*/
|
||||
byte* str, /*!< in: string */
|
||||
ulint str_len); /*!< in: string length */
|
||||
/************************************************************//**
|
||||
Closes the log.
|
||||
@return lsn */
|
||||
UNIV_INTERN
|
||||
lsn_t
|
||||
log_close(void);
|
||||
/*===========*/
|
||||
/************************************************************//**
|
||||
Gets the current lsn.
|
||||
@return current lsn */
|
||||
UNIV_INLINE
|
||||
lsn_t
|
||||
log_get_lsn(void);
|
||||
/*=============*/
|
||||
/****************************************************************
|
||||
Gets the log group capacity. It is OK to read the value without
|
||||
holding log_sys->mutex because it is constant.
|
||||
@return log group capacity */
|
||||
UNIV_INLINE
|
||||
lsn_t
|
||||
log_get_capacity(void);
|
||||
/*==================*/
|
||||
/****************************************************************
|
||||
Get log_sys::max_modified_age_async. It is OK to read the value without
|
||||
holding log_sys::mutex because it is constant.
|
||||
@return max_modified_age_async */
|
||||
UNIV_INLINE
|
||||
lsn_t
|
||||
log_get_max_modified_age_async(void);
|
||||
/*================================*/
|
||||
/******************************************************//**
|
||||
Initializes the log. */
|
||||
UNIV_INTERN
|
||||
void
|
||||
log_init(void);
|
||||
/*==========*/
|
||||
/******************************************************************//**
|
||||
Inits a log group to the log system. */
|
||||
UNIV_INTERN
|
||||
void
|
||||
log_group_init(
|
||||
/*===========*/
|
||||
ulint id, /*!< in: group id */
|
||||
ulint n_files, /*!< in: number of log files */
|
||||
lsn_t file_size, /*!< in: log file size in bytes */
|
||||
ulint space_id, /*!< in: space id of the file space
|
||||
which contains the log files of this
|
||||
group */
|
||||
ulint archive_space_id); /*!< in: space id of the file space
|
||||
which contains some archived log
|
||||
files for this group; currently, only
|
||||
for the first log group this is
|
||||
used */
|
||||
/******************************************************//**
|
||||
Completes an i/o to a log file. */
|
||||
UNIV_INTERN
|
||||
void
|
||||
log_io_complete(
|
||||
/*============*/
|
||||
log_group_t* group); /*!< in: log group */
|
||||
/******************************************************//**
|
||||
This function is called, e.g., when a transaction wants to commit. It checks
|
||||
that the log has been written to the log file up to the last log entry written
|
||||
by the transaction. If there is a flush running, it waits and checks if the
|
||||
flush flushed enough. If not, starts a new flush. */
|
||||
UNIV_INTERN
|
||||
void
|
||||
log_write_up_to(
|
||||
/*============*/
|
||||
lsn_t lsn, /*!< in: log sequence number up to which
|
||||
the log should be written, LSN_MAX if not specified */
|
||||
ulint wait, /*!< in: LOG_NO_WAIT, LOG_WAIT_ONE_GROUP,
|
||||
or LOG_WAIT_ALL_GROUPS */
|
||||
ibool flush_to_disk);
|
||||
/*!< in: TRUE if we want the written log
|
||||
also to be flushed to disk */
|
||||
/****************************************************************//**
|
||||
Does a syncronous flush of the log buffer to disk. */
|
||||
UNIV_INTERN
|
||||
void
|
||||
log_buffer_flush_to_disk(void);
|
||||
/*==========================*/
|
||||
/****************************************************************//**
|
||||
This functions writes the log buffer to the log file and if 'flush'
|
||||
is set it forces a flush of the log file as well. This is meant to be
|
||||
called from background master thread only as it does not wait for
|
||||
the write (+ possible flush) to finish. */
|
||||
UNIV_INTERN
|
||||
void
|
||||
log_buffer_sync_in_background(
|
||||
/*==========================*/
|
||||
ibool flush); /*<! in: flush the logs to disk */
|
||||
/******************************************************//**
|
||||
Makes a checkpoint. Note that this function does not flush dirty
|
||||
blocks from the buffer pool: it only checks what is lsn of the oldest
|
||||
modification in the pool, and writes information about the lsn in
|
||||
log files. Use log_make_checkpoint_at to flush also the pool.
|
||||
@return TRUE if success, FALSE if a checkpoint write was already running */
|
||||
UNIV_INTERN
|
||||
ibool
|
||||
log_checkpoint(
|
||||
/*===========*/
|
||||
ibool sync, /*!< in: TRUE if synchronous operation is
|
||||
desired */
|
||||
ibool write_always); /*!< in: the function normally checks if the
|
||||
the new checkpoint would have a greater
|
||||
lsn than the previous one: if not, then no
|
||||
physical write is done; by setting this
|
||||
parameter TRUE, a physical write will always be
|
||||
made to log files */
|
||||
/****************************************************************//**
|
||||
Makes a checkpoint at a given lsn or later. */
|
||||
UNIV_INTERN
|
||||
void
|
||||
log_make_checkpoint_at(
|
||||
/*===================*/
|
||||
lsn_t lsn, /*!< in: make a checkpoint at this or a
|
||||
later lsn, if LSN_MAX, makes
|
||||
a checkpoint at the latest lsn */
|
||||
ibool write_always); /*!< in: the function normally checks if
|
||||
the new checkpoint would have a
|
||||
greater lsn than the previous one: if
|
||||
not, then no physical write is done;
|
||||
by setting this parameter TRUE, a
|
||||
physical write will always be made to
|
||||
log files */
|
||||
/****************************************************************//**
|
||||
Makes a checkpoint at the latest lsn and writes it to first page of each
|
||||
data file in the database, so that we know that the file spaces contain
|
||||
all modifications up to that lsn. This can only be called at database
|
||||
shutdown. This function also writes all log in log files to the log archive. */
|
||||
UNIV_INTERN
|
||||
void
|
||||
logs_empty_and_mark_files_at_shutdown(void);
|
||||
/*=======================================*/
|
||||
/******************************************************//**
|
||||
Reads a checkpoint info from a log group header to log_sys->checkpoint_buf. */
|
||||
UNIV_INTERN
|
||||
void
|
||||
log_group_read_checkpoint_info(
|
||||
/*===========================*/
|
||||
log_group_t* group, /*!< in: log group */
|
||||
ulint field); /*!< in: LOG_CHECKPOINT_1 or LOG_CHECKPOINT_2 */
|
||||
/*******************************************************************//**
|
||||
Gets info from a checkpoint about a log group. */
|
||||
UNIV_INTERN
|
||||
void
|
||||
log_checkpoint_get_nth_group_info(
|
||||
/*==============================*/
|
||||
const byte* buf, /*!< in: buffer containing checkpoint info */
|
||||
ulint n, /*!< in: nth slot */
|
||||
ulint* file_no,/*!< out: archived file number */
|
||||
ulint* offset);/*!< out: archived file offset */
|
||||
/******************************************************//**
|
||||
Writes checkpoint info to groups. */
|
||||
UNIV_INTERN
|
||||
void
|
||||
log_groups_write_checkpoint_info(void);
|
||||
/*==================================*/
|
||||
/********************************************************************//**
|
||||
Starts an archiving operation.
|
||||
@return TRUE if succeed, FALSE if an archiving operation was already running */
|
||||
UNIV_INTERN
|
||||
ibool
|
||||
log_archive_do(
|
||||
/*===========*/
|
||||
ibool sync, /*!< in: TRUE if synchronous operation is desired */
|
||||
ulint* n_bytes);/*!< out: archive log buffer size, 0 if nothing to
|
||||
archive */
|
||||
/****************************************************************//**
|
||||
Writes the log contents to the archive up to the lsn when this function was
|
||||
called, and stops the archiving. When archiving is started again, the archived
|
||||
log file numbers start from a number one higher, so that the archiving will
|
||||
not write again to the archived log files which exist when this function
|
||||
returns.
|
||||
@return DB_SUCCESS or DB_ERROR */
|
||||
UNIV_INTERN
|
||||
ulint
|
||||
log_archive_stop(void);
|
||||
/*==================*/
|
||||
/****************************************************************//**
|
||||
Starts again archiving which has been stopped.
|
||||
@return DB_SUCCESS or DB_ERROR */
|
||||
UNIV_INTERN
|
||||
ulint
|
||||
log_archive_start(void);
|
||||
/*===================*/
|
||||
/****************************************************************//**
|
||||
Stop archiving the log so that a gap may occur in the archived log files.
|
||||
@return DB_SUCCESS or DB_ERROR */
|
||||
UNIV_INTERN
|
||||
ulint
|
||||
log_archive_noarchivelog(void);
|
||||
/*==========================*/
|
||||
/****************************************************************//**
|
||||
Start archiving the log so that a gap may occur in the archived log files.
|
||||
@return DB_SUCCESS or DB_ERROR */
|
||||
UNIV_INTERN
|
||||
ulint
|
||||
log_archive_archivelog(void);
|
||||
/*========================*/
|
||||
/******************************************************//**
|
||||
Generates an archived log file name. */
|
||||
UNIV_INTERN
|
||||
void
|
||||
log_archived_file_name_gen(
|
||||
/*=======================*/
|
||||
char* buf, /*!< in: buffer where to write */
|
||||
ulint id, /*!< in: group id */
|
||||
ulint file_no);/*!< in: file number */
|
||||
#else /* !UNIV_HOTBACKUP */
|
||||
/******************************************************//**
|
||||
Writes info to a buffer of a log group when log files are created in
|
||||
backup restoration. */
|
||||
UNIV_INTERN
|
||||
void
|
||||
log_reset_first_header_and_checkpoint(
|
||||
/*==================================*/
|
||||
byte* hdr_buf,/*!< in: buffer which will be written to the
|
||||
start of the first log file */
|
||||
ib_uint64_t start); /*!< in: lsn of the start of the first log file;
|
||||
we pretend that there is a checkpoint at
|
||||
start + LOG_BLOCK_HDR_SIZE */
|
||||
#endif /* !UNIV_HOTBACKUP */
|
||||
/********************************************************************//**
|
||||
Checks that there is enough free space in the log to start a new query step.
|
||||
Flushes the log buffer or makes a new checkpoint if necessary. NOTE: this
|
||||
function may only be called if the calling thread owns no synchronization
|
||||
objects! */
|
||||
UNIV_INTERN
|
||||
void
|
||||
log_check_margins(void);
|
||||
/*===================*/
|
||||
#ifndef UNIV_HOTBACKUP
|
||||
/******************************************************//**
|
||||
Reads a specified log segment to a buffer. */
|
||||
UNIV_INTERN
|
||||
void
|
||||
log_group_read_log_seg(
|
||||
/*===================*/
|
||||
ulint type, /*!< in: LOG_ARCHIVE or LOG_RECOVER */
|
||||
byte* buf, /*!< in: buffer where to read */
|
||||
log_group_t* group, /*!< in: log group */
|
||||
lsn_t start_lsn, /*!< in: read area start */
|
||||
lsn_t end_lsn); /*!< in: read area end */
|
||||
/******************************************************//**
|
||||
Writes a buffer to a log file group. */
|
||||
UNIV_INTERN
|
||||
void
|
||||
log_group_write_buf(
|
||||
/*================*/
|
||||
log_group_t* group, /*!< in: log group */
|
||||
byte* buf, /*!< in: buffer */
|
||||
ulint len, /*!< in: buffer len; must be divisible
|
||||
by OS_FILE_LOG_BLOCK_SIZE */
|
||||
lsn_t start_lsn, /*!< in: start lsn of the buffer; must
|
||||
be divisible by
|
||||
OS_FILE_LOG_BLOCK_SIZE */
|
||||
ulint new_data_offset);/*!< in: start offset of new data in
|
||||
buf: this parameter is used to decide
|
||||
if we have to write a new log file
|
||||
header */
|
||||
/********************************************************//**
|
||||
Sets the field values in group to correspond to a given lsn. For this function
|
||||
to work, the values must already be correctly initialized to correspond to
|
||||
some lsn, for instance, a checkpoint lsn. */
|
||||
UNIV_INTERN
|
||||
void
|
||||
log_group_set_fields(
|
||||
/*=================*/
|
||||
log_group_t* group, /*!< in/out: group */
|
||||
lsn_t lsn); /*!< in: lsn for which the values should be
|
||||
set */
|
||||
/******************************************************//**
|
||||
Calculates the data capacity of a log group, when the log file headers are not
|
||||
included.
|
||||
@return capacity in bytes */
|
||||
UNIV_INTERN
|
||||
lsn_t
|
||||
log_group_get_capacity(
|
||||
/*===================*/
|
||||
const log_group_t* group); /*!< in: log group */
|
||||
#endif /* !UNIV_HOTBACKUP */
|
||||
/************************************************************//**
|
||||
Gets a log block flush bit.
|
||||
@return TRUE if this block was the first to be written in a log flush */
|
||||
UNIV_INLINE
|
||||
ibool
|
||||
log_block_get_flush_bit(
|
||||
/*====================*/
|
||||
const byte* log_block); /*!< in: log block */
|
||||
/************************************************************//**
|
||||
Gets a log block number stored in the header.
|
||||
@return log block number stored in the block header */
|
||||
UNIV_INLINE
|
||||
ulint
|
||||
log_block_get_hdr_no(
|
||||
/*=================*/
|
||||
const byte* log_block); /*!< in: log block */
|
||||
/************************************************************//**
|
||||
Gets a log block data length.
|
||||
@return log block data length measured as a byte offset from the block start */
|
||||
UNIV_INLINE
|
||||
ulint
|
||||
log_block_get_data_len(
|
||||
/*===================*/
|
||||
const byte* log_block); /*!< in: log block */
|
||||
/************************************************************//**
|
||||
Sets the log block data length. */
|
||||
UNIV_INLINE
|
||||
void
|
||||
log_block_set_data_len(
|
||||
/*===================*/
|
||||
byte* log_block, /*!< in/out: log block */
|
||||
ulint len); /*!< in: data length */
|
||||
/************************************************************//**
|
||||
Calculates the checksum for a log block.
|
||||
@return checksum */
|
||||
UNIV_INLINE
|
||||
ulint
|
||||
log_block_calc_checksum(
|
||||
/*====================*/
|
||||
const byte* block); /*!< in: log block */
|
||||
/************************************************************//**
|
||||
Gets a log block checksum field value.
|
||||
@return checksum */
|
||||
UNIV_INLINE
|
||||
ulint
|
||||
log_block_get_checksum(
|
||||
/*===================*/
|
||||
const byte* log_block); /*!< in: log block */
|
||||
/************************************************************//**
|
||||
Sets a log block checksum field value. */
|
||||
UNIV_INLINE
|
||||
void
|
||||
log_block_set_checksum(
|
||||
/*===================*/
|
||||
byte* log_block, /*!< in/out: log block */
|
||||
ulint checksum); /*!< in: checksum */
|
||||
/************************************************************//**
|
||||
Gets a log block first mtr log record group offset.
|
||||
@return first mtr log record group byte offset from the block start, 0
|
||||
if none */
|
||||
UNIV_INLINE
|
||||
ulint
|
||||
log_block_get_first_rec_group(
|
||||
/*==========================*/
|
||||
const byte* log_block); /*!< in: log block */
|
||||
/************************************************************//**
|
||||
Sets the log block first mtr log record group offset. */
|
||||
UNIV_INLINE
|
||||
void
|
||||
log_block_set_first_rec_group(
|
||||
/*==========================*/
|
||||
byte* log_block, /*!< in/out: log block */
|
||||
ulint offset); /*!< in: offset, 0 if none */
|
||||
/************************************************************//**
|
||||
Gets a log block checkpoint number field (4 lowest bytes).
|
||||
@return checkpoint no (4 lowest bytes) */
|
||||
UNIV_INLINE
|
||||
ulint
|
||||
log_block_get_checkpoint_no(
|
||||
/*========================*/
|
||||
const byte* log_block); /*!< in: log block */
|
||||
/************************************************************//**
|
||||
Initializes a log block in the log buffer. */
|
||||
UNIV_INLINE
|
||||
void
|
||||
log_block_init(
|
||||
/*===========*/
|
||||
byte* log_block, /*!< in: pointer to the log buffer */
|
||||
lsn_t lsn); /*!< in: lsn within the log block */
|
||||
/************************************************************//**
|
||||
Initializes a log block in the log buffer in the old, < 3.23.52 format, where
|
||||
there was no checksum yet. */
|
||||
UNIV_INLINE
|
||||
void
|
||||
log_block_init_in_old_format(
|
||||
/*=========================*/
|
||||
byte* log_block, /*!< in: pointer to the log buffer */
|
||||
lsn_t lsn); /*!< in: lsn within the log block */
|
||||
/************************************************************//**
|
||||
Converts a lsn to a log block number.
|
||||
@return log block number, it is > 0 and <= 1G */
|
||||
UNIV_INLINE
|
||||
ulint
|
||||
log_block_convert_lsn_to_no(
|
||||
/*========================*/
|
||||
lsn_t lsn); /*!< in: lsn of a byte within the block */
|
||||
/******************************************************//**
|
||||
Prints info of the log. */
|
||||
UNIV_INTERN
|
||||
void
|
||||
log_print(
|
||||
/*======*/
|
||||
FILE* file); /*!< in: file where to print */
|
||||
/******************************************************//**
|
||||
Peeks the current lsn.
|
||||
@return TRUE if success, FALSE if could not get the log system mutex */
|
||||
UNIV_INTERN
|
||||
ibool
|
||||
log_peek_lsn(
|
||||
/*=========*/
|
||||
lsn_t* lsn); /*!< out: if returns TRUE, current lsn is here */
|
||||
/**********************************************************************//**
|
||||
Refreshes the statistics used to print per-second averages. */
|
||||
UNIV_INTERN
|
||||
void
|
||||
log_refresh_stats(void);
|
||||
/*===================*/
|
||||
/********************************************************//**
|
||||
Closes all log groups. */
|
||||
UNIV_INTERN
|
||||
void
|
||||
log_group_close_all(void);
|
||||
/*=====================*/
|
||||
/********************************************************//**
|
||||
Shutdown the log system but do not release all the memory. */
|
||||
UNIV_INTERN
|
||||
void
|
||||
log_shutdown(void);
|
||||
/*==============*/
|
||||
/********************************************************//**
|
||||
Free the log system data structures. */
|
||||
UNIV_INTERN
|
||||
void
|
||||
log_mem_free(void);
|
||||
/*==============*/
|
||||
|
||||
extern log_t* log_sys;
|
||||
|
||||
/* Values used as flags */
|
||||
#define LOG_FLUSH 7652559
|
||||
#define LOG_CHECKPOINT 78656949
|
||||
#ifdef UNIV_LOG_ARCHIVE
|
||||
# define LOG_ARCHIVE 11122331
|
||||
#endif /* UNIV_LOG_ARCHIVE */
|
||||
#define LOG_RECOVER 98887331
|
||||
|
||||
/* The counting of lsn's starts from this value: this must be non-zero */
|
||||
#define LOG_START_LSN ((lsn_t) (16 * OS_FILE_LOG_BLOCK_SIZE))
|
||||
|
||||
#define LOG_BUFFER_SIZE (srv_log_buffer_size * UNIV_PAGE_SIZE)
|
||||
#define LOG_ARCHIVE_BUF_SIZE (srv_log_buffer_size * UNIV_PAGE_SIZE / 4)
|
||||
|
||||
/* Offsets of a log block header */
|
||||
#define LOG_BLOCK_HDR_NO 0 /* block number which must be > 0 and
|
||||
is allowed to wrap around at 2G; the
|
||||
highest bit is set to 1 if this is the
|
||||
first log block in a log flush write
|
||||
segment */
|
||||
#define LOG_BLOCK_FLUSH_BIT_MASK 0x80000000UL
|
||||
/* mask used to get the highest bit in
|
||||
the preceding field */
|
||||
#define LOG_BLOCK_HDR_DATA_LEN 4 /* number of bytes of log written to
|
||||
this block */
|
||||
#define LOG_BLOCK_FIRST_REC_GROUP 6 /* offset of the first start of an
|
||||
mtr log record group in this log block,
|
||||
0 if none; if the value is the same
|
||||
as LOG_BLOCK_HDR_DATA_LEN, it means
|
||||
that the first rec group has not yet
|
||||
been catenated to this log block, but
|
||||
if it will, it will start at this
|
||||
offset; an archive recovery can
|
||||
start parsing the log records starting
|
||||
from this offset in this log block,
|
||||
if value not 0 */
|
||||
#define LOG_BLOCK_CHECKPOINT_NO 8 /* 4 lower bytes of the value of
|
||||
log_sys->next_checkpoint_no when the
|
||||
log block was last written to: if the
|
||||
block has not yet been written full,
|
||||
this value is only updated before a
|
||||
log buffer flush */
|
||||
#define LOG_BLOCK_HDR_SIZE 12 /* size of the log block header in
|
||||
bytes */
|
||||
|
||||
/* Offsets of a log block trailer from the end of the block */
|
||||
#define LOG_BLOCK_CHECKSUM 4 /* 4 byte checksum of the log block
|
||||
contents; in InnoDB versions
|
||||
< 3.23.52 this did not contain the
|
||||
checksum but the same value as
|
||||
.._HDR_NO */
|
||||
#define LOG_BLOCK_TRL_SIZE 4 /* trailer size in bytes */
|
||||
|
||||
/* Offsets for a checkpoint field */
|
||||
#define LOG_CHECKPOINT_NO 0
|
||||
#define LOG_CHECKPOINT_LSN 8
|
||||
#define LOG_CHECKPOINT_OFFSET_LOW32 16
|
||||
#define LOG_CHECKPOINT_LOG_BUF_SIZE 20
|
||||
#define LOG_CHECKPOINT_ARCHIVED_LSN 24
|
||||
#define LOG_CHECKPOINT_GROUP_ARRAY 32
|
||||
|
||||
/* For each value smaller than LOG_MAX_N_GROUPS the following 8 bytes: */
|
||||
|
||||
#define LOG_CHECKPOINT_ARCHIVED_FILE_NO 0
|
||||
#define LOG_CHECKPOINT_ARCHIVED_OFFSET 4
|
||||
|
||||
#define LOG_CHECKPOINT_ARRAY_END (LOG_CHECKPOINT_GROUP_ARRAY\
|
||||
+ LOG_MAX_N_GROUPS * 8)
|
||||
#define LOG_CHECKPOINT_CHECKSUM_1 LOG_CHECKPOINT_ARRAY_END
|
||||
#define LOG_CHECKPOINT_CHECKSUM_2 (4 + LOG_CHECKPOINT_ARRAY_END)
|
||||
#if 0
|
||||
#define LOG_CHECKPOINT_FSP_FREE_LIMIT (8 + LOG_CHECKPOINT_ARRAY_END)
|
||||
/*!< Not used (0);
|
||||
This used to contain the
|
||||
current fsp free limit in
|
||||
tablespace 0, in units of one
|
||||
megabyte.
|
||||
|
||||
This information might have been used
|
||||
since mysqlbackup version 0.35 but
|
||||
before 1.41 to decide if unused ends of
|
||||
non-auto-extending data files
|
||||
in space 0 can be truncated.
|
||||
|
||||
This information was made obsolete
|
||||
by mysqlbackup --compress. */
|
||||
#define LOG_CHECKPOINT_FSP_MAGIC_N (12 + LOG_CHECKPOINT_ARRAY_END)
|
||||
/*!< Not used (0);
|
||||
This magic number tells if the
|
||||
checkpoint contains the above field:
|
||||
the field was added to
|
||||
InnoDB-3.23.50 and
|
||||
removed from MySQL 5.6 */
|
||||
#define LOG_CHECKPOINT_FSP_MAGIC_N_VAL 1441231243
|
||||
/*!< if LOG_CHECKPOINT_FSP_MAGIC_N
|
||||
contains this value, then
|
||||
LOG_CHECKPOINT_FSP_FREE_LIMIT
|
||||
is valid */
|
||||
#endif
|
||||
#define LOG_CHECKPOINT_OFFSET_HIGH32 (16 + LOG_CHECKPOINT_ARRAY_END)
|
||||
#define LOG_CHECKPOINT_SIZE (20 + LOG_CHECKPOINT_ARRAY_END)
|
||||
|
||||
|
||||
/* Offsets of a log file header */
|
||||
#define LOG_GROUP_ID 0 /* log group number */
|
||||
#define LOG_FILE_START_LSN 4 /* lsn of the start of data in this
|
||||
log file */
|
||||
#define LOG_FILE_NO 12 /* 4-byte archived log file number;
|
||||
this field is only defined in an
|
||||
archived log file */
|
||||
#define LOG_FILE_WAS_CREATED_BY_HOT_BACKUP 16
|
||||
/* a 32-byte field which contains
|
||||
the string 'ibbackup' and the
|
||||
creation time if the log file was
|
||||
created by mysqlbackup --restore;
|
||||
when mysqld is first time started
|
||||
on the restored database, it can
|
||||
print helpful info for the user */
|
||||
#define LOG_FILE_ARCH_COMPLETED OS_FILE_LOG_BLOCK_SIZE
|
||||
/* this 4-byte field is TRUE when
|
||||
the writing of an archived log file
|
||||
has been completed; this field is
|
||||
only defined in an archived log file */
|
||||
#define LOG_FILE_END_LSN (OS_FILE_LOG_BLOCK_SIZE + 4)
|
||||
/* lsn where the archived log file
|
||||
at least extends: actually the
|
||||
archived log file may extend to a
|
||||
later lsn, as long as it is within the
|
||||
same log block as this lsn; this field
|
||||
is defined only when an archived log
|
||||
file has been completely written */
|
||||
#define LOG_CHECKPOINT_1 OS_FILE_LOG_BLOCK_SIZE
|
||||
/* first checkpoint field in the log
|
||||
header; we write alternately to the
|
||||
checkpoint fields when we make new
|
||||
checkpoints; this field is only defined
|
||||
in the first log file of a log group */
|
||||
#define LOG_CHECKPOINT_2 (3 * OS_FILE_LOG_BLOCK_SIZE)
|
||||
/* second checkpoint field in the log
|
||||
header */
|
||||
#define LOG_FILE_HDR_SIZE (4 * OS_FILE_LOG_BLOCK_SIZE)
|
||||
|
||||
#define LOG_GROUP_OK 301
|
||||
#define LOG_GROUP_CORRUPTED 302
|
||||
|
||||
/** Log group consists of a number of log files, each of the same size; a log
|
||||
group is implemented as a space in the sense of the module fil0fil. */
|
||||
struct log_group_t{
|
||||
/* The following fields are protected by log_sys->mutex */
|
||||
ulint id; /*!< log group id */
|
||||
ulint n_files; /*!< number of files in the group */
|
||||
lsn_t file_size; /*!< individual log file size in bytes,
|
||||
including the log file header */
|
||||
ulint space_id; /*!< file space which implements the log
|
||||
group */
|
||||
ulint state; /*!< LOG_GROUP_OK or
|
||||
LOG_GROUP_CORRUPTED */
|
||||
lsn_t lsn; /*!< lsn used to fix coordinates within
|
||||
the log group */
|
||||
lsn_t lsn_offset; /*!< the offset of the above lsn */
|
||||
ulint n_pending_writes;/*!< number of currently pending flush
|
||||
writes for this log group */
|
||||
byte** file_header_bufs_ptr;/*!< unaligned buffers */
|
||||
byte** file_header_bufs;/*!< buffers for each file
|
||||
header in the group */
|
||||
#ifdef UNIV_LOG_ARCHIVE
|
||||
/*-----------------------------*/
|
||||
byte** archive_file_header_bufs_ptr;/*!< unaligned buffers */
|
||||
byte** archive_file_header_bufs;/*!< buffers for each file
|
||||
header in the group */
|
||||
ulint archive_space_id;/*!< file space which
|
||||
implements the log group
|
||||
archive */
|
||||
ulint archived_file_no;/*!< file number corresponding to
|
||||
log_sys->archived_lsn */
|
||||
ulint archived_offset;/*!< file offset corresponding to
|
||||
log_sys->archived_lsn, 0 if we have
|
||||
not yet written to the archive file
|
||||
number archived_file_no */
|
||||
ulint next_archived_file_no;/*!< during an archive write,
|
||||
until the write is completed, we
|
||||
store the next value for
|
||||
archived_file_no here: the write
|
||||
completion function then sets the new
|
||||
value to ..._file_no */
|
||||
ulint next_archived_offset; /*!< like the preceding field */
|
||||
#endif /* UNIV_LOG_ARCHIVE */
|
||||
/*-----------------------------*/
|
||||
lsn_t scanned_lsn; /*!< used only in recovery: recovery scan
|
||||
succeeded up to this lsn in this log
|
||||
group */
|
||||
byte* checkpoint_buf_ptr;/*!< unaligned checkpoint header */
|
||||
byte* checkpoint_buf; /*!< checkpoint header is written from
|
||||
this buffer to the group */
|
||||
UT_LIST_NODE_T(log_group_t)
|
||||
log_groups; /*!< list of log groups */
|
||||
};
|
||||
|
||||
/** Redo log buffer */
|
||||
struct log_t{
|
||||
byte pad[64]; /*!< padding to prevent other memory
|
||||
update hotspots from residing on the
|
||||
same memory cache line */
|
||||
lsn_t lsn; /*!< log sequence number */
|
||||
ulint buf_free; /*!< first free offset within the log
|
||||
buffer */
|
||||
#ifndef UNIV_HOTBACKUP
|
||||
ib_mutex_t mutex; /*!< mutex protecting the log */
|
||||
|
||||
ib_mutex_t log_flush_order_mutex;/*!< mutex to serialize access to
|
||||
the flush list when we are putting
|
||||
dirty blocks in the list. The idea
|
||||
behind this mutex is to be able
|
||||
to release log_sys->mutex during
|
||||
mtr_commit and still ensure that
|
||||
insertions in the flush_list happen
|
||||
in the LSN order. */
|
||||
#endif /* !UNIV_HOTBACKUP */
|
||||
byte* buf_ptr; /* unaligned log buffer */
|
||||
byte* buf; /*!< log buffer */
|
||||
ulint buf_size; /*!< log buffer size in bytes */
|
||||
ulint max_buf_free; /*!< recommended maximum value of
|
||||
buf_free, after which the buffer is
|
||||
flushed */
|
||||
#ifdef UNIV_LOG_DEBUG
|
||||
ulint old_buf_free; /*!< value of buf free when log was
|
||||
last time opened; only in the debug
|
||||
version */
|
||||
ib_uint64_t old_lsn; /*!< value of lsn when log was
|
||||
last time opened; only in the
|
||||
debug version */
|
||||
#endif /* UNIV_LOG_DEBUG */
|
||||
ibool check_flush_or_checkpoint;
|
||||
/*!< this is set to TRUE when there may
|
||||
be need to flush the log buffer, or
|
||||
preflush buffer pool pages, or make
|
||||
a checkpoint; this MUST be TRUE when
|
||||
lsn - last_checkpoint_lsn >
|
||||
max_checkpoint_age; this flag is
|
||||
peeked at by log_free_check(), which
|
||||
does not reserve the log mutex */
|
||||
UT_LIST_BASE_NODE_T(log_group_t)
|
||||
log_groups; /*!< log groups */
|
||||
|
||||
#ifndef UNIV_HOTBACKUP
|
||||
/** The fields involved in the log buffer flush @{ */
|
||||
|
||||
ulint buf_next_to_write;/*!< first offset in the log buffer
|
||||
where the byte content may not exist
|
||||
written to file, e.g., the start
|
||||
offset of a log record catenated
|
||||
later; this is advanced when a flush
|
||||
operation is completed to all the log
|
||||
groups */
|
||||
volatile bool is_extending; /*!< this is set to true during extend
|
||||
the log buffer size */
|
||||
lsn_t written_to_some_lsn;
|
||||
/*!< first log sequence number not yet
|
||||
written to any log group; for this to
|
||||
be advanced, it is enough that the
|
||||
write i/o has been completed for any
|
||||
one log group */
|
||||
lsn_t written_to_all_lsn;
|
||||
/*!< first log sequence number not yet
|
||||
written to some log group; for this to
|
||||
be advanced, it is enough that the
|
||||
write i/o has been completed for all
|
||||
log groups.
|
||||
Note that since InnoDB currently
|
||||
has only one log group therefore
|
||||
this value is redundant. Also it
|
||||
is possible that this value
|
||||
falls behind the
|
||||
flushed_to_disk_lsn transiently.
|
||||
It is appropriate to use either
|
||||
flushed_to_disk_lsn or
|
||||
write_lsn which are always
|
||||
up-to-date and accurate. */
|
||||
lsn_t write_lsn; /*!< end lsn for the current running
|
||||
write */
|
||||
ulint write_end_offset;/*!< the data in buffer has
|
||||
been written up to this offset
|
||||
when the current write ends:
|
||||
this field will then be copied
|
||||
to buf_next_to_write */
|
||||
lsn_t current_flush_lsn;/*!< end lsn for the current running
|
||||
write + flush operation */
|
||||
lsn_t flushed_to_disk_lsn;
|
||||
/*!< how far we have written the log
|
||||
AND flushed to disk */
|
||||
ulint n_pending_writes;/*!< number of currently
|
||||
pending flushes or writes */
|
||||
/* NOTE on the 'flush' in names of the fields below: starting from
|
||||
4.0.14, we separate the write of the log file and the actual fsync()
|
||||
or other method to flush it to disk. The names below shhould really
|
||||
be 'flush_or_write'! */
|
||||
os_event_t no_flush_event; /*!< this event is in the reset state
|
||||
when a flush or a write is running;
|
||||
a thread should wait for this without
|
||||
owning the log mutex, but NOTE that
|
||||
to set or reset this event, the
|
||||
thread MUST own the log mutex! */
|
||||
ibool one_flushed; /*!< during a flush, this is
|
||||
first FALSE and becomes TRUE
|
||||
when one log group has been
|
||||
written or flushed */
|
||||
os_event_t one_flushed_event;/*!< this event is reset when the
|
||||
flush or write has not yet completed
|
||||
for any log group; e.g., this means
|
||||
that a transaction has been committed
|
||||
when this is set; a thread should wait
|
||||
for this without owning the log mutex,
|
||||
but NOTE that to set or reset this
|
||||
event, the thread MUST own the log
|
||||
mutex! */
|
||||
ulint n_log_ios; /*!< number of log i/os initiated thus
|
||||
far */
|
||||
ulint n_log_ios_old; /*!< number of log i/o's at the
|
||||
previous printout */
|
||||
time_t last_printout_time;/*!< when log_print was last time
|
||||
called */
|
||||
/* @} */
|
||||
|
||||
/** Fields involved in checkpoints @{ */
|
||||
lsn_t log_group_capacity; /*!< capacity of the log group; if
|
||||
the checkpoint age exceeds this, it is
|
||||
a serious error because it is possible
|
||||
we will then overwrite log and spoil
|
||||
crash recovery */
|
||||
lsn_t max_modified_age_async;
|
||||
/*!< when this recommended
|
||||
value for lsn -
|
||||
buf_pool_get_oldest_modification()
|
||||
is exceeded, we start an
|
||||
asynchronous preflush of pool pages */
|
||||
lsn_t max_modified_age_sync;
|
||||
/*!< when this recommended
|
||||
value for lsn -
|
||||
buf_pool_get_oldest_modification()
|
||||
is exceeded, we start a
|
||||
synchronous preflush of pool pages */
|
||||
lsn_t max_checkpoint_age_async;
|
||||
/*!< when this checkpoint age
|
||||
is exceeded we start an
|
||||
asynchronous writing of a new
|
||||
checkpoint */
|
||||
lsn_t max_checkpoint_age;
|
||||
/*!< this is the maximum allowed value
|
||||
for lsn - last_checkpoint_lsn when a
|
||||
new query step is started */
|
||||
ib_uint64_t next_checkpoint_no;
|
||||
/*!< next checkpoint number */
|
||||
lsn_t last_checkpoint_lsn;
|
||||
/*!< latest checkpoint lsn */
|
||||
lsn_t next_checkpoint_lsn;
|
||||
/*!< next checkpoint lsn */
|
||||
ulint n_pending_checkpoint_writes;
|
||||
/*!< number of currently pending
|
||||
checkpoint writes */
|
||||
rw_lock_t checkpoint_lock;/*!< this latch is x-locked when a
|
||||
checkpoint write is running; a thread
|
||||
should wait for this without owning
|
||||
the log mutex */
|
||||
#endif /* !UNIV_HOTBACKUP */
|
||||
byte* checkpoint_buf_ptr;/* unaligned checkpoint header */
|
||||
byte* checkpoint_buf; /*!< checkpoint header is read to this
|
||||
buffer */
|
||||
/* @} */
|
||||
#ifdef UNIV_LOG_ARCHIVE
|
||||
/** Fields involved in archiving @{ */
|
||||
ulint archiving_state;/*!< LOG_ARCH_ON, LOG_ARCH_STOPPING
|
||||
LOG_ARCH_STOPPED, LOG_ARCH_OFF */
|
||||
lsn_t archived_lsn; /*!< archiving has advanced to this
|
||||
lsn */
|
||||
lsn_t max_archived_lsn_age_async;
|
||||
/*!< recommended maximum age of
|
||||
archived_lsn, before we start
|
||||
asynchronous copying to the archive */
|
||||
lsn_t max_archived_lsn_age;
|
||||
/*!< maximum allowed age for
|
||||
archived_lsn */
|
||||
lsn_t next_archived_lsn;/*!< during an archive write,
|
||||
until the write is completed, we
|
||||
store the next value for
|
||||
archived_lsn here: the write
|
||||
completion function then sets the new
|
||||
value to archived_lsn */
|
||||
ulint archiving_phase;/*!< LOG_ARCHIVE_READ or
|
||||
LOG_ARCHIVE_WRITE */
|
||||
ulint n_pending_archive_ios;
|
||||
/*!< number of currently pending reads
|
||||
or writes in archiving */
|
||||
rw_lock_t archive_lock; /*!< this latch is x-locked when an
|
||||
archive write is running; a thread
|
||||
should wait for this without owning
|
||||
the log mutex */
|
||||
ulint archive_buf_size;/*!< size of archive_buf */
|
||||
byte* archive_buf; /*!< log segment is written to the
|
||||
archive from this buffer */
|
||||
os_event_t archiving_on; /*!< if archiving has been stopped,
|
||||
a thread can wait for this event to
|
||||
become signaled */
|
||||
/* @} */
|
||||
#endif /* UNIV_LOG_ARCHIVE */
|
||||
};
|
||||
|
||||
/** Test if flush order mutex is owned. */
|
||||
#define log_flush_order_mutex_own() \
|
||||
mutex_own(&log_sys->log_flush_order_mutex)
|
||||
|
||||
/** Acquire the flush order mutex. */
|
||||
#define log_flush_order_mutex_enter() do { \
|
||||
mutex_enter(&log_sys->log_flush_order_mutex); \
|
||||
} while (0)
|
||||
/** Release the flush order mutex. */
|
||||
# define log_flush_order_mutex_exit() do { \
|
||||
mutex_exit(&log_sys->log_flush_order_mutex); \
|
||||
} while (0)
|
||||
|
||||
#ifdef UNIV_LOG_ARCHIVE
|
||||
/** Archiving state @{ */
|
||||
#define LOG_ARCH_ON 71
|
||||
#define LOG_ARCH_STOPPING 72
|
||||
#define LOG_ARCH_STOPPING2 73
|
||||
#define LOG_ARCH_STOPPED 74
|
||||
#define LOG_ARCH_OFF 75
|
||||
/* @} */
|
||||
#endif /* UNIV_LOG_ARCHIVE */
|
||||
|
||||
#ifndef UNIV_NONINL
|
||||
#include "log0log.ic"
|
||||
#endif
|
||||
|
||||
#endif
|
||||
462
storage/innobase/include/log0log.ic
Normal file
462
storage/innobase/include/log0log.ic
Normal file
|
|
@ -0,0 +1,462 @@
|
|||
/*****************************************************************************
|
||||
|
||||
Copyright (c) 1995, 2010, Oracle and/or its affiliates. All Rights Reserved.
|
||||
|
||||
This program is free software; you can redistribute it and/or modify it under
|
||||
the terms of the GNU General Public License as published by the Free Software
|
||||
Foundation; version 2 of the License.
|
||||
|
||||
This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
|
||||
FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License along with
|
||||
this program; if not, write to the Free Software Foundation, Inc.,
|
||||
51 Franklin Street, Suite 500, Boston, MA 02110-1335 USA
|
||||
|
||||
*****************************************************************************/
|
||||
|
||||
/**************************************************//**
|
||||
@file include/log0log.ic
|
||||
Database log
|
||||
|
||||
Created 12/9/1995 Heikki Tuuri
|
||||
*******************************************************/
|
||||
|
||||
#include "os0file.h"
|
||||
#include "mach0data.h"
|
||||
#include "mtr0mtr.h"
|
||||
#include "srv0mon.h"
|
||||
|
||||
#ifdef UNIV_LOG_DEBUG
|
||||
/******************************************************//**
|
||||
Checks by parsing that the catenated log segment for a single mtr is
|
||||
consistent. */
|
||||
UNIV_INTERN
|
||||
ibool
|
||||
log_check_log_recs(
|
||||
/*===============*/
|
||||
const byte* buf, /*!< in: pointer to the start of
|
||||
the log segment in the
|
||||
log_sys->buf log buffer */
|
||||
ulint len, /*!< in: segment length in bytes */
|
||||
ib_uint64_t buf_start_lsn); /*!< in: buffer start lsn */
|
||||
#endif /* UNIV_LOG_DEBUG */
|
||||
|
||||
/************************************************************//**
|
||||
Gets a log block flush bit.
|
||||
@return TRUE if this block was the first to be written in a log flush */
|
||||
UNIV_INLINE
|
||||
ibool
|
||||
log_block_get_flush_bit(
|
||||
/*====================*/
|
||||
const byte* log_block) /*!< in: log block */
|
||||
{
|
||||
if (LOG_BLOCK_FLUSH_BIT_MASK
|
||||
& mach_read_from_4(log_block + LOG_BLOCK_HDR_NO)) {
|
||||
|
||||
return(TRUE);
|
||||
}
|
||||
|
||||
return(FALSE);
|
||||
}
|
||||
|
||||
/************************************************************//**
|
||||
Sets the log block flush bit. */
|
||||
UNIV_INLINE
|
||||
void
|
||||
log_block_set_flush_bit(
|
||||
/*====================*/
|
||||
byte* log_block, /*!< in/out: log block */
|
||||
ibool val) /*!< in: value to set */
|
||||
{
|
||||
ulint field;
|
||||
|
||||
field = mach_read_from_4(log_block + LOG_BLOCK_HDR_NO);
|
||||
|
||||
if (val) {
|
||||
field = field | LOG_BLOCK_FLUSH_BIT_MASK;
|
||||
} else {
|
||||
field = field & ~LOG_BLOCK_FLUSH_BIT_MASK;
|
||||
}
|
||||
|
||||
mach_write_to_4(log_block + LOG_BLOCK_HDR_NO, field);
|
||||
}
|
||||
|
||||
/************************************************************//**
|
||||
Gets a log block number stored in the header.
|
||||
@return log block number stored in the block header */
|
||||
UNIV_INLINE
|
||||
ulint
|
||||
log_block_get_hdr_no(
|
||||
/*=================*/
|
||||
const byte* log_block) /*!< in: log block */
|
||||
{
|
||||
return(~LOG_BLOCK_FLUSH_BIT_MASK
|
||||
& mach_read_from_4(log_block + LOG_BLOCK_HDR_NO));
|
||||
}
|
||||
|
||||
/************************************************************//**
|
||||
Sets the log block number stored in the header; NOTE that this must be set
|
||||
before the flush bit! */
|
||||
UNIV_INLINE
|
||||
void
|
||||
log_block_set_hdr_no(
|
||||
/*=================*/
|
||||
byte* log_block, /*!< in/out: log block */
|
||||
ulint n) /*!< in: log block number: must be > 0 and
|
||||
< LOG_BLOCK_FLUSH_BIT_MASK */
|
||||
{
|
||||
ut_ad(n > 0);
|
||||
ut_ad(n < LOG_BLOCK_FLUSH_BIT_MASK);
|
||||
|
||||
mach_write_to_4(log_block + LOG_BLOCK_HDR_NO, n);
|
||||
}
|
||||
|
||||
/************************************************************//**
|
||||
Gets a log block data length.
|
||||
@return log block data length measured as a byte offset from the block start */
|
||||
UNIV_INLINE
|
||||
ulint
|
||||
log_block_get_data_len(
|
||||
/*===================*/
|
||||
const byte* log_block) /*!< in: log block */
|
||||
{
|
||||
return(mach_read_from_2(log_block + LOG_BLOCK_HDR_DATA_LEN));
|
||||
}
|
||||
|
||||
/************************************************************//**
|
||||
Sets the log block data length. */
|
||||
UNIV_INLINE
|
||||
void
|
||||
log_block_set_data_len(
|
||||
/*===================*/
|
||||
byte* log_block, /*!< in/out: log block */
|
||||
ulint len) /*!< in: data length */
|
||||
{
|
||||
mach_write_to_2(log_block + LOG_BLOCK_HDR_DATA_LEN, len);
|
||||
}
|
||||
|
||||
/************************************************************//**
|
||||
Gets a log block first mtr log record group offset.
|
||||
@return first mtr log record group byte offset from the block start, 0
|
||||
if none */
|
||||
UNIV_INLINE
|
||||
ulint
|
||||
log_block_get_first_rec_group(
|
||||
/*==========================*/
|
||||
const byte* log_block) /*!< in: log block */
|
||||
{
|
||||
return(mach_read_from_2(log_block + LOG_BLOCK_FIRST_REC_GROUP));
|
||||
}
|
||||
|
||||
/************************************************************//**
|
||||
Sets the log block first mtr log record group offset. */
|
||||
UNIV_INLINE
|
||||
void
|
||||
log_block_set_first_rec_group(
|
||||
/*==========================*/
|
||||
byte* log_block, /*!< in/out: log block */
|
||||
ulint offset) /*!< in: offset, 0 if none */
|
||||
{
|
||||
mach_write_to_2(log_block + LOG_BLOCK_FIRST_REC_GROUP, offset);
|
||||
}
|
||||
|
||||
/************************************************************//**
|
||||
Gets a log block checkpoint number field (4 lowest bytes).
|
||||
@return checkpoint no (4 lowest bytes) */
|
||||
UNIV_INLINE
|
||||
ulint
|
||||
log_block_get_checkpoint_no(
|
||||
/*========================*/
|
||||
const byte* log_block) /*!< in: log block */
|
||||
{
|
||||
return(mach_read_from_4(log_block + LOG_BLOCK_CHECKPOINT_NO));
|
||||
}
|
||||
|
||||
/************************************************************//**
|
||||
Sets a log block checkpoint number field (4 lowest bytes). */
|
||||
UNIV_INLINE
|
||||
void
|
||||
log_block_set_checkpoint_no(
|
||||
/*========================*/
|
||||
byte* log_block, /*!< in/out: log block */
|
||||
ib_uint64_t no) /*!< in: checkpoint no */
|
||||
{
|
||||
mach_write_to_4(log_block + LOG_BLOCK_CHECKPOINT_NO, (ulint) no);
|
||||
}
|
||||
|
||||
/************************************************************//**
|
||||
Converts a lsn to a log block number.
|
||||
@return log block number, it is > 0 and <= 1G */
|
||||
UNIV_INLINE
|
||||
ulint
|
||||
log_block_convert_lsn_to_no(
|
||||
/*========================*/
|
||||
lsn_t lsn) /*!< in: lsn of a byte within the block */
|
||||
{
|
||||
return(((ulint) (lsn / OS_FILE_LOG_BLOCK_SIZE) & 0x3FFFFFFFUL) + 1);
|
||||
}
|
||||
|
||||
/************************************************************//**
|
||||
Calculates the checksum for a log block.
|
||||
@return checksum */
|
||||
UNIV_INLINE
|
||||
ulint
|
||||
log_block_calc_checksum(
|
||||
/*====================*/
|
||||
const byte* block) /*!< in: log block */
|
||||
{
|
||||
ulint sum;
|
||||
ulint sh;
|
||||
ulint i;
|
||||
|
||||
sum = 1;
|
||||
sh = 0;
|
||||
|
||||
for (i = 0; i < OS_FILE_LOG_BLOCK_SIZE - LOG_BLOCK_TRL_SIZE; i++) {
|
||||
ulint b = (ulint) block[i];
|
||||
sum &= 0x7FFFFFFFUL;
|
||||
sum += b;
|
||||
sum += b << sh;
|
||||
sh++;
|
||||
if (sh > 24) {
|
||||
sh = 0;
|
||||
}
|
||||
}
|
||||
|
||||
return(sum);
|
||||
}
|
||||
|
||||
/************************************************************//**
|
||||
Gets a log block checksum field value.
|
||||
@return checksum */
|
||||
UNIV_INLINE
|
||||
ulint
|
||||
log_block_get_checksum(
|
||||
/*===================*/
|
||||
const byte* log_block) /*!< in: log block */
|
||||
{
|
||||
return(mach_read_from_4(log_block + OS_FILE_LOG_BLOCK_SIZE
|
||||
- LOG_BLOCK_CHECKSUM));
|
||||
}
|
||||
|
||||
/************************************************************//**
|
||||
Sets a log block checksum field value. */
|
||||
UNIV_INLINE
|
||||
void
|
||||
log_block_set_checksum(
|
||||
/*===================*/
|
||||
byte* log_block, /*!< in/out: log block */
|
||||
ulint checksum) /*!< in: checksum */
|
||||
{
|
||||
mach_write_to_4(log_block + OS_FILE_LOG_BLOCK_SIZE
|
||||
- LOG_BLOCK_CHECKSUM,
|
||||
checksum);
|
||||
}
|
||||
|
||||
/************************************************************//**
|
||||
Initializes a log block in the log buffer. */
|
||||
UNIV_INLINE
|
||||
void
|
||||
log_block_init(
|
||||
/*===========*/
|
||||
byte* log_block, /*!< in: pointer to the log buffer */
|
||||
lsn_t lsn) /*!< in: lsn within the log block */
|
||||
{
|
||||
ulint no;
|
||||
|
||||
ut_ad(mutex_own(&(log_sys->mutex)));
|
||||
|
||||
no = log_block_convert_lsn_to_no(lsn);
|
||||
|
||||
log_block_set_hdr_no(log_block, no);
|
||||
|
||||
log_block_set_data_len(log_block, LOG_BLOCK_HDR_SIZE);
|
||||
log_block_set_first_rec_group(log_block, 0);
|
||||
}
|
||||
|
||||
/************************************************************//**
|
||||
Initializes a log block in the log buffer in the old format, where there
|
||||
was no checksum yet. */
|
||||
UNIV_INLINE
|
||||
void
|
||||
log_block_init_in_old_format(
|
||||
/*=========================*/
|
||||
byte* log_block, /*!< in: pointer to the log buffer */
|
||||
lsn_t lsn) /*!< in: lsn within the log block */
|
||||
{
|
||||
ulint no;
|
||||
|
||||
ut_ad(mutex_own(&(log_sys->mutex)));
|
||||
|
||||
no = log_block_convert_lsn_to_no(lsn);
|
||||
|
||||
log_block_set_hdr_no(log_block, no);
|
||||
mach_write_to_4(log_block + OS_FILE_LOG_BLOCK_SIZE
|
||||
- LOG_BLOCK_CHECKSUM, no);
|
||||
log_block_set_data_len(log_block, LOG_BLOCK_HDR_SIZE);
|
||||
log_block_set_first_rec_group(log_block, 0);
|
||||
}
|
||||
|
||||
#ifndef UNIV_HOTBACKUP
|
||||
/************************************************************//**
|
||||
Writes to the log the string given. The log must be released with
|
||||
log_release.
|
||||
@return end lsn of the log record, zero if did not succeed */
|
||||
UNIV_INLINE
|
||||
lsn_t
|
||||
log_reserve_and_write_fast(
|
||||
/*=======================*/
|
||||
const void* str, /*!< in: string */
|
||||
ulint len, /*!< in: string length */
|
||||
lsn_t* start_lsn)/*!< out: start lsn of the log record */
|
||||
{
|
||||
ulint data_len;
|
||||
#ifdef UNIV_LOG_LSN_DEBUG
|
||||
/* length of the LSN pseudo-record */
|
||||
ulint lsn_len;
|
||||
#endif /* UNIV_LOG_LSN_DEBUG */
|
||||
|
||||
mutex_enter(&log_sys->mutex);
|
||||
#ifdef UNIV_LOG_LSN_DEBUG
|
||||
lsn_len = 1
|
||||
+ mach_get_compressed_size(log_sys->lsn >> 32)
|
||||
+ mach_get_compressed_size(log_sys->lsn & 0xFFFFFFFFUL);
|
||||
#endif /* UNIV_LOG_LSN_DEBUG */
|
||||
|
||||
data_len = len
|
||||
#ifdef UNIV_LOG_LSN_DEBUG
|
||||
+ lsn_len
|
||||
#endif /* UNIV_LOG_LSN_DEBUG */
|
||||
+ log_sys->buf_free % OS_FILE_LOG_BLOCK_SIZE;
|
||||
|
||||
if (data_len >= OS_FILE_LOG_BLOCK_SIZE - LOG_BLOCK_TRL_SIZE) {
|
||||
|
||||
/* The string does not fit within the current log block
|
||||
or the log block would become full */
|
||||
|
||||
mutex_exit(&log_sys->mutex);
|
||||
|
||||
return(0);
|
||||
}
|
||||
|
||||
*start_lsn = log_sys->lsn;
|
||||
|
||||
#ifdef UNIV_LOG_LSN_DEBUG
|
||||
{
|
||||
/* Write the LSN pseudo-record. */
|
||||
byte* b = &log_sys->buf[log_sys->buf_free];
|
||||
*b++ = MLOG_LSN | (MLOG_SINGLE_REC_FLAG & *(const byte*) str);
|
||||
/* Write the LSN in two parts,
|
||||
as a pseudo page number and space id. */
|
||||
b += mach_write_compressed(b, log_sys->lsn >> 32);
|
||||
b += mach_write_compressed(b, log_sys->lsn & 0xFFFFFFFFUL);
|
||||
ut_a(b - lsn_len == &log_sys->buf[log_sys->buf_free]);
|
||||
|
||||
memcpy(b, str, len);
|
||||
len += lsn_len;
|
||||
}
|
||||
#else /* UNIV_LOG_LSN_DEBUG */
|
||||
memcpy(log_sys->buf + log_sys->buf_free, str, len);
|
||||
#endif /* UNIV_LOG_LSN_DEBUG */
|
||||
|
||||
log_block_set_data_len((byte*) ut_align_down(log_sys->buf
|
||||
+ log_sys->buf_free,
|
||||
OS_FILE_LOG_BLOCK_SIZE),
|
||||
data_len);
|
||||
#ifdef UNIV_LOG_DEBUG
|
||||
log_sys->old_buf_free = log_sys->buf_free;
|
||||
log_sys->old_lsn = log_sys->lsn;
|
||||
#endif
|
||||
log_sys->buf_free += len;
|
||||
|
||||
ut_ad(log_sys->buf_free <= log_sys->buf_size);
|
||||
|
||||
log_sys->lsn += len;
|
||||
|
||||
MONITOR_SET(MONITOR_LSN_CHECKPOINT_AGE,
|
||||
log_sys->lsn - log_sys->last_checkpoint_lsn);
|
||||
|
||||
#ifdef UNIV_LOG_DEBUG
|
||||
log_check_log_recs(log_sys->buf + log_sys->old_buf_free,
|
||||
log_sys->buf_free - log_sys->old_buf_free,
|
||||
log_sys->old_lsn);
|
||||
#endif
|
||||
return(log_sys->lsn);
|
||||
}
|
||||
|
||||
/***********************************************************************//**
|
||||
Releases the log mutex. */
|
||||
UNIV_INLINE
|
||||
void
|
||||
log_release(void)
|
||||
/*=============*/
|
||||
{
|
||||
mutex_exit(&(log_sys->mutex));
|
||||
}
|
||||
|
||||
/************************************************************//**
|
||||
Gets the current lsn.
|
||||
@return current lsn */
|
||||
UNIV_INLINE
|
||||
lsn_t
|
||||
log_get_lsn(void)
|
||||
/*=============*/
|
||||
{
|
||||
lsn_t lsn;
|
||||
|
||||
mutex_enter(&(log_sys->mutex));
|
||||
|
||||
lsn = log_sys->lsn;
|
||||
|
||||
mutex_exit(&(log_sys->mutex));
|
||||
|
||||
return(lsn);
|
||||
}
|
||||
|
||||
/****************************************************************
|
||||
Gets the log group capacity. It is OK to read the value without
|
||||
holding log_sys->mutex because it is constant.
|
||||
@return log group capacity */
|
||||
UNIV_INLINE
|
||||
lsn_t
|
||||
log_get_capacity(void)
|
||||
/*==================*/
|
||||
{
|
||||
return(log_sys->log_group_capacity);
|
||||
}
|
||||
|
||||
/****************************************************************
|
||||
Get log_sys::max_modified_age_async. It is OK to read the value without
|
||||
holding log_sys::mutex because it is constant.
|
||||
@return max_modified_age_async */
|
||||
UNIV_INLINE
|
||||
lsn_t
|
||||
log_get_max_modified_age_async(void)
|
||||
/*================================*/
|
||||
{
|
||||
return(log_sys->max_modified_age_async);
|
||||
}
|
||||
|
||||
/***********************************************************************//**
|
||||
Checks if there is need for a log buffer flush or a new checkpoint, and does
|
||||
this if yes. Any database operation should call this when it has modified
|
||||
more than about 4 pages. NOTE that this function may only be called when the
|
||||
OS thread owns no synchronization objects except the dictionary mutex. */
|
||||
UNIV_INLINE
|
||||
void
|
||||
log_free_check(void)
|
||||
/*================*/
|
||||
{
|
||||
|
||||
#ifdef UNIV_SYNC_DEBUG
|
||||
ut_ad(sync_thread_levels_empty_except_dict());
|
||||
#endif /* UNIV_SYNC_DEBUG */
|
||||
|
||||
if (log_sys->check_flush_or_checkpoint) {
|
||||
|
||||
log_check_margins();
|
||||
}
|
||||
}
|
||||
#endif /* !UNIV_HOTBACKUP */
|
||||
505
storage/innobase/include/log0recv.h
Normal file
505
storage/innobase/include/log0recv.h
Normal file
|
|
@ -0,0 +1,505 @@
|
|||
/*****************************************************************************
|
||||
|
||||
Copyright (c) 1997, 2014, Oracle and/or its affiliates. All Rights Reserved.
|
||||
|
||||
This program is free software; you can redistribute it and/or modify it under
|
||||
the terms of the GNU General Public License as published by the Free Software
|
||||
Foundation; version 2 of the License.
|
||||
|
||||
This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
|
||||
FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License along with
|
||||
this program; if not, write to the Free Software Foundation, Inc.,
|
||||
51 Franklin Street, Suite 500, Boston, MA 02110-1335 USA
|
||||
|
||||
*****************************************************************************/
|
||||
|
||||
/**************************************************//**
|
||||
@file include/log0recv.h
|
||||
Recovery
|
||||
|
||||
Created 9/20/1997 Heikki Tuuri
|
||||
*******************************************************/
|
||||
|
||||
#ifndef log0recv_h
|
||||
#define log0recv_h
|
||||
|
||||
#include "univ.i"
|
||||
#include "ut0byte.h"
|
||||
#include "buf0types.h"
|
||||
#include "hash0hash.h"
|
||||
#include "log0log.h"
|
||||
#include <list>
|
||||
|
||||
#ifdef UNIV_HOTBACKUP
|
||||
extern ibool recv_replay_file_ops;
|
||||
|
||||
/*******************************************************************//**
|
||||
Reads the checkpoint info needed in hot backup.
|
||||
@return TRUE if success */
|
||||
UNIV_INTERN
|
||||
ibool
|
||||
recv_read_checkpoint_info_for_backup(
|
||||
/*=================================*/
|
||||
const byte* hdr, /*!< in: buffer containing the log group
|
||||
header */
|
||||
lsn_t* lsn, /*!< out: checkpoint lsn */
|
||||
lsn_t* offset, /*!< out: checkpoint offset in the log group */
|
||||
lsn_t* cp_no, /*!< out: checkpoint number */
|
||||
lsn_t* first_header_lsn)
|
||||
/*!< out: lsn of of the start of the
|
||||
first log file */
|
||||
__attribute__((nonnull));
|
||||
/*******************************************************************//**
|
||||
Scans the log segment and n_bytes_scanned is set to the length of valid
|
||||
log scanned. */
|
||||
UNIV_INTERN
|
||||
void
|
||||
recv_scan_log_seg_for_backup(
|
||||
/*=========================*/
|
||||
byte* buf, /*!< in: buffer containing log data */
|
||||
ulint buf_len, /*!< in: data length in that buffer */
|
||||
lsn_t* scanned_lsn, /*!< in/out: lsn of buffer start,
|
||||
we return scanned lsn */
|
||||
ulint* scanned_checkpoint_no,
|
||||
/*!< in/out: 4 lowest bytes of the
|
||||
highest scanned checkpoint number so
|
||||
far */
|
||||
ulint* n_bytes_scanned);/*!< out: how much we were able to
|
||||
scan, smaller than buf_len if log
|
||||
data ended here */
|
||||
#endif /* UNIV_HOTBACKUP */
|
||||
/*******************************************************************//**
|
||||
Returns TRUE if recovery is currently running.
|
||||
@return recv_recovery_on */
|
||||
UNIV_INLINE
|
||||
ibool
|
||||
recv_recovery_is_on(void);
|
||||
/*=====================*/
|
||||
#ifdef UNIV_LOG_ARCHIVE
|
||||
/*******************************************************************//**
|
||||
Returns TRUE if recovery from backup is currently running.
|
||||
@return recv_recovery_from_backup_on */
|
||||
UNIV_INLINE
|
||||
ibool
|
||||
recv_recovery_from_backup_is_on(void);
|
||||
/*=================================*/
|
||||
#endif /* UNIV_LOG_ARCHIVE */
|
||||
/************************************************************************//**
|
||||
Applies the hashed log records to the page, if the page lsn is less than the
|
||||
lsn of a log record. This can be called when a buffer page has just been
|
||||
read in, or also for a page already in the buffer pool. */
|
||||
UNIV_INTERN
|
||||
void
|
||||
recv_recover_page_func(
|
||||
/*===================*/
|
||||
#ifndef UNIV_HOTBACKUP
|
||||
ibool just_read_in,
|
||||
/*!< in: TRUE if the i/o handler calls
|
||||
this for a freshly read page */
|
||||
#endif /* !UNIV_HOTBACKUP */
|
||||
buf_block_t* block); /*!< in/out: buffer block */
|
||||
#ifndef UNIV_HOTBACKUP
|
||||
/** Wrapper for recv_recover_page_func().
|
||||
Applies the hashed log records to the page, if the page lsn is less than the
|
||||
lsn of a log record. This can be called when a buffer page has just been
|
||||
read in, or also for a page already in the buffer pool.
|
||||
@param jri in: TRUE if just read in (the i/o handler calls this for
|
||||
a freshly read page)
|
||||
@param block in/out: the buffer block
|
||||
*/
|
||||
# define recv_recover_page(jri, block) recv_recover_page_func(jri, block)
|
||||
#else /* !UNIV_HOTBACKUP */
|
||||
/** Wrapper for recv_recover_page_func().
|
||||
Applies the hashed log records to the page, if the page lsn is less than the
|
||||
lsn of a log record. This can be called when a buffer page has just been
|
||||
read in, or also for a page already in the buffer pool.
|
||||
@param jri in: TRUE if just read in (the i/o handler calls this for
|
||||
a freshly read page)
|
||||
@param block in/out: the buffer block
|
||||
*/
|
||||
# define recv_recover_page(jri, block) recv_recover_page_func(block)
|
||||
#endif /* !UNIV_HOTBACKUP */
|
||||
/********************************************************//**
|
||||
Recovers from a checkpoint. When this function returns, the database is able
|
||||
to start processing of 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.
|
||||
@return error code or DB_SUCCESS */
|
||||
UNIV_INTERN
|
||||
dberr_t
|
||||
recv_recovery_from_checkpoint_start_func(
|
||||
/*=====================================*/
|
||||
#ifdef UNIV_LOG_ARCHIVE
|
||||
ulint type, /*!< in: LOG_CHECKPOINT or
|
||||
LOG_ARCHIVE */
|
||||
lsn_t limit_lsn, /*!< in: recover up to this lsn
|
||||
if possible */
|
||||
#endif /* UNIV_LOG_ARCHIVE */
|
||||
lsn_t min_flushed_lsn,/*!< in: min flushed lsn from
|
||||
data files */
|
||||
lsn_t max_flushed_lsn);/*!< in: max flushed lsn from
|
||||
data files */
|
||||
#ifdef UNIV_LOG_ARCHIVE
|
||||
/** Wrapper for recv_recovery_from_checkpoint_start_func().
|
||||
Recovers from a checkpoint. When this function returns, the database is able
|
||||
to start processing of 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.
|
||||
@param type in: LOG_CHECKPOINT or LOG_ARCHIVE
|
||||
@param lim in: recover up to this log sequence number if possible
|
||||
@param min in: minimum flushed log sequence number from data files
|
||||
@param max in: maximum flushed log sequence number from data files
|
||||
@return error code or DB_SUCCESS */
|
||||
# define recv_recovery_from_checkpoint_start(type,lim,min,max) \
|
||||
recv_recovery_from_checkpoint_start_func(type,lim,min,max)
|
||||
#else /* UNIV_LOG_ARCHIVE */
|
||||
/** Wrapper for recv_recovery_from_checkpoint_start_func().
|
||||
Recovers from a checkpoint. When this function returns, the database is able
|
||||
to start processing of 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.
|
||||
@param type ignored: LOG_CHECKPOINT or LOG_ARCHIVE
|
||||
@param lim ignored: recover up to this log sequence number if possible
|
||||
@param min in: minimum flushed log sequence number from data files
|
||||
@param max in: maximum flushed log sequence number from data files
|
||||
@return error code or DB_SUCCESS */
|
||||
# define recv_recovery_from_checkpoint_start(type,lim,min,max) \
|
||||
recv_recovery_from_checkpoint_start_func(min,max)
|
||||
#endif /* UNIV_LOG_ARCHIVE */
|
||||
/********************************************************//**
|
||||
Completes recovery from a checkpoint. */
|
||||
UNIV_INTERN
|
||||
void
|
||||
recv_recovery_from_checkpoint_finish(void);
|
||||
/*======================================*/
|
||||
/********************************************************//**
|
||||
Initiates the rollback of active transactions. */
|
||||
UNIV_INTERN
|
||||
void
|
||||
recv_recovery_rollback_active(void);
|
||||
/*===============================*/
|
||||
/*******************************************************//**
|
||||
Scans log from a buffer and stores new log data to the parsing buffer.
|
||||
Parses and hashes the log records if new data found. Unless
|
||||
UNIV_HOTBACKUP is defined, this function will apply log records
|
||||
automatically when the hash table becomes full.
|
||||
@return TRUE if limit_lsn has been reached, or not able to scan any
|
||||
more in this log group */
|
||||
UNIV_INTERN
|
||||
ibool
|
||||
recv_scan_log_recs(
|
||||
/*===============*/
|
||||
ulint available_memory,/*!< in: we let the hash table of recs
|
||||
to grow to this size, at the maximum */
|
||||
ibool store_to_hash, /*!< in: TRUE if the records should be
|
||||
stored to the hash table; this is set
|
||||
to FALSE if just debug checking is
|
||||
needed */
|
||||
const byte* buf, /*!< in: buffer containing a log
|
||||
segment or garbage */
|
||||
ulint len, /*!< in: buffer length */
|
||||
lsn_t start_lsn, /*!< in: buffer start lsn */
|
||||
lsn_t* contiguous_lsn, /*!< in/out: it is known that all log
|
||||
groups contain contiguous log data up
|
||||
to this lsn */
|
||||
lsn_t* group_scanned_lsn);/*!< out: scanning succeeded up to
|
||||
this lsn */
|
||||
/******************************************************//**
|
||||
Resets the logs. The contents of log files will be lost! */
|
||||
UNIV_INTERN
|
||||
void
|
||||
recv_reset_logs(
|
||||
/*============*/
|
||||
#ifdef UNIV_LOG_ARCHIVE
|
||||
ulint arch_log_no, /*!< in: next archived log file number */
|
||||
ibool new_logs_created,/*!< in: TRUE if resetting logs
|
||||
is done at the log creation;
|
||||
FALSE if it is done after
|
||||
archive recovery */
|
||||
#endif /* UNIV_LOG_ARCHIVE */
|
||||
lsn_t lsn); /*!< in: reset to this lsn
|
||||
rounded up to be divisible by
|
||||
OS_FILE_LOG_BLOCK_SIZE, after
|
||||
which we add
|
||||
LOG_BLOCK_HDR_SIZE */
|
||||
#ifdef UNIV_HOTBACKUP
|
||||
/******************************************************//**
|
||||
Creates new log files after a backup has been restored. */
|
||||
UNIV_INTERN
|
||||
void
|
||||
recv_reset_log_files_for_backup(
|
||||
/*============================*/
|
||||
const char* log_dir, /*!< in: log file directory path */
|
||||
ulint n_log_files, /*!< in: number of log files */
|
||||
lsn_t log_file_size, /*!< in: log file size */
|
||||
lsn_t lsn); /*!< in: new start lsn, must be
|
||||
divisible by OS_FILE_LOG_BLOCK_SIZE */
|
||||
#endif /* UNIV_HOTBACKUP */
|
||||
/********************************************************//**
|
||||
Creates the recovery system. */
|
||||
UNIV_INTERN
|
||||
void
|
||||
recv_sys_create(void);
|
||||
/*=================*/
|
||||
/**********************************************************//**
|
||||
Release recovery system mutexes. */
|
||||
UNIV_INTERN
|
||||
void
|
||||
recv_sys_close(void);
|
||||
/*================*/
|
||||
/********************************************************//**
|
||||
Frees the recovery system memory. */
|
||||
UNIV_INTERN
|
||||
void
|
||||
recv_sys_mem_free(void);
|
||||
/*===================*/
|
||||
/********************************************************//**
|
||||
Inits the recovery system for a recovery operation. */
|
||||
UNIV_INTERN
|
||||
void
|
||||
recv_sys_init(
|
||||
/*==========*/
|
||||
ulint available_memory); /*!< in: available memory in bytes */
|
||||
#ifndef UNIV_HOTBACKUP
|
||||
/********************************************************//**
|
||||
Reset the state of the recovery system variables. */
|
||||
UNIV_INTERN
|
||||
void
|
||||
recv_sys_var_init(void);
|
||||
/*===================*/
|
||||
#endif /* !UNIV_HOTBACKUP */
|
||||
/*******************************************************************//**
|
||||
Empties the hash table of stored log records, applying them to appropriate
|
||||
pages. */
|
||||
UNIV_INTERN
|
||||
void
|
||||
recv_apply_hashed_log_recs(
|
||||
/*=======================*/
|
||||
ibool allow_ibuf); /*!< in: if TRUE, also ibuf operations are
|
||||
allowed during the application; if FALSE,
|
||||
no ibuf operations are allowed, and after
|
||||
the application all file pages are flushed to
|
||||
disk and invalidated in buffer pool: this
|
||||
alternative means that no new log records
|
||||
can be generated during the application */
|
||||
#ifdef UNIV_HOTBACKUP
|
||||
/*******************************************************************//**
|
||||
Applies log records in the hash table to a backup. */
|
||||
UNIV_INTERN
|
||||
void
|
||||
recv_apply_log_recs_for_backup(void);
|
||||
/*================================*/
|
||||
#endif
|
||||
#ifdef UNIV_LOG_ARCHIVE
|
||||
/********************************************************//**
|
||||
Recovers from archived log files, and also from log files, if they exist.
|
||||
@return error code or DB_SUCCESS */
|
||||
UNIV_INTERN
|
||||
ulint
|
||||
recv_recovery_from_archive_start(
|
||||
/*=============================*/
|
||||
lsn_t min_flushed_lsn,/*!< in: min flushed lsn field from the
|
||||
data files */
|
||||
lsn_t limit_lsn, /*!< in: recover up to this lsn if
|
||||
possible */
|
||||
ulint first_log_no); /*!< in: number of the first archived
|
||||
log file to use in the recovery; the
|
||||
file will be searched from
|
||||
INNOBASE_LOG_ARCH_DIR specified in
|
||||
server config file */
|
||||
/********************************************************//**
|
||||
Completes recovery from archive. */
|
||||
UNIV_INTERN
|
||||
void
|
||||
recv_recovery_from_archive_finish(void);
|
||||
/*===================================*/
|
||||
#endif /* UNIV_LOG_ARCHIVE */
|
||||
|
||||
/** Block of log record data */
|
||||
struct recv_data_t{
|
||||
recv_data_t* next; /*!< pointer to the next block or NULL */
|
||||
/*!< the log record data is stored physically
|
||||
immediately after this struct, max amount
|
||||
RECV_DATA_BLOCK_SIZE bytes of it */
|
||||
};
|
||||
|
||||
/** Stored log record struct */
|
||||
struct recv_t{
|
||||
byte type; /*!< log record type */
|
||||
ulint len; /*!< log record body length in bytes */
|
||||
recv_data_t* data; /*!< chain of blocks containing the log record
|
||||
body */
|
||||
lsn_t start_lsn;/*!< start lsn of the log segment written by
|
||||
the mtr which generated this log record: NOTE
|
||||
that this is not necessarily the start lsn of
|
||||
this log record */
|
||||
lsn_t end_lsn;/*!< end lsn of the log segment written by
|
||||
the mtr which generated this log record: NOTE
|
||||
that this is not necessarily the end lsn of
|
||||
this log record */
|
||||
UT_LIST_NODE_T(recv_t)
|
||||
rec_list;/*!< list of log records for this page */
|
||||
};
|
||||
|
||||
/** States of recv_addr_t */
|
||||
enum recv_addr_state {
|
||||
/** not yet processed */
|
||||
RECV_NOT_PROCESSED,
|
||||
/** page is being read */
|
||||
RECV_BEING_READ,
|
||||
/** log records are being applied on the page */
|
||||
RECV_BEING_PROCESSED,
|
||||
/** log records have been applied on the page, or they have
|
||||
been discarded because the tablespace does not exist */
|
||||
RECV_PROCESSED
|
||||
};
|
||||
|
||||
/** Hashed page file address struct */
|
||||
struct recv_addr_t{
|
||||
enum recv_addr_state state;
|
||||
/*!< recovery state of the page */
|
||||
unsigned space:32;/*!< space id */
|
||||
unsigned page_no:32;/*!< page number */
|
||||
UT_LIST_BASE_NODE_T(recv_t)
|
||||
rec_list;/*!< list of log records for this page */
|
||||
hash_node_t addr_hash;/*!< hash node in the hash bucket chain */
|
||||
};
|
||||
|
||||
struct recv_dblwr_t {
|
||||
void add(byte* page);
|
||||
|
||||
byte* find_page(ulint space_id, ulint page_no);
|
||||
|
||||
std::list<byte *> pages; /* Pages from double write buffer */
|
||||
|
||||
void operator() () {
|
||||
pages.clear();
|
||||
}
|
||||
};
|
||||
|
||||
/** Recovery system data structure */
|
||||
struct recv_sys_t{
|
||||
#ifndef UNIV_HOTBACKUP
|
||||
ib_mutex_t mutex; /*!< mutex protecting the fields apply_log_recs,
|
||||
n_addrs, and the state field in each recv_addr
|
||||
struct */
|
||||
ib_mutex_t writer_mutex;/*!< mutex coordinating
|
||||
flushing between recv_writer_thread and
|
||||
the recovery thread. */
|
||||
#endif /* !UNIV_HOTBACKUP */
|
||||
ibool apply_log_recs;
|
||||
/*!< this is TRUE when log rec application to
|
||||
pages is allowed; this flag tells the
|
||||
i/o-handler if it should do log record
|
||||
application */
|
||||
ibool apply_batch_on;
|
||||
/*!< this is TRUE when a log rec application
|
||||
batch is running */
|
||||
lsn_t lsn; /*!< log sequence number */
|
||||
ulint last_log_buf_size;
|
||||
/*!< size of the log buffer when the database
|
||||
last time wrote to the log */
|
||||
byte* last_block;
|
||||
/*!< possible incomplete last recovered log
|
||||
block */
|
||||
byte* last_block_buf_start;
|
||||
/*!< the nonaligned start address of the
|
||||
preceding buffer */
|
||||
byte* buf; /*!< buffer for parsing log records */
|
||||
ulint len; /*!< amount of data in buf */
|
||||
lsn_t parse_start_lsn;
|
||||
/*!< this is the lsn from which we were able to
|
||||
start parsing log records and adding them to
|
||||
the hash table; zero if a suitable
|
||||
start point not found yet */
|
||||
lsn_t scanned_lsn;
|
||||
/*!< the log data has been scanned up to this
|
||||
lsn */
|
||||
ulint scanned_checkpoint_no;
|
||||
/*!< the log data has been scanned up to this
|
||||
checkpoint number (lowest 4 bytes) */
|
||||
ulint recovered_offset;
|
||||
/*!< start offset of non-parsed log records in
|
||||
buf */
|
||||
lsn_t recovered_lsn;
|
||||
/*!< the log records have been parsed up to
|
||||
this lsn */
|
||||
lsn_t limit_lsn;/*!< recovery should be made at most
|
||||
up to this lsn */
|
||||
ibool found_corrupt_log;
|
||||
/*!< this is set to TRUE if we during log
|
||||
scan find a corrupt log block, or a corrupt
|
||||
log record, or there is a log parsing
|
||||
buffer overflow */
|
||||
#ifdef UNIV_LOG_ARCHIVE
|
||||
log_group_t* archive_group;
|
||||
/*!< in archive recovery: the log group whose
|
||||
archive is read */
|
||||
#endif /* !UNIV_LOG_ARCHIVE */
|
||||
mem_heap_t* heap; /*!< memory heap of log records and file
|
||||
addresses*/
|
||||
hash_table_t* addr_hash;/*!< hash table of file addresses of pages */
|
||||
ulint n_addrs;/*!< number of not processed hashed file
|
||||
addresses in the hash table */
|
||||
|
||||
recv_dblwr_t dblwr;
|
||||
};
|
||||
|
||||
/** The recovery system */
|
||||
extern recv_sys_t* recv_sys;
|
||||
|
||||
/** TRUE when applying redo log records during crash recovery; FALSE
|
||||
otherwise. Note that this is FALSE while a background thread is
|
||||
rolling back incomplete transactions. */
|
||||
extern ibool recv_recovery_on;
|
||||
/** If the following is TRUE, the buffer pool file pages must be invalidated
|
||||
after recovery and no ibuf operations are allowed; this becomes TRUE if
|
||||
the log record hash table becomes too full, and log records must be merged
|
||||
to file pages already before the recovery is finished: in this case no
|
||||
ibuf operations are allowed, as they could modify the pages read in the
|
||||
buffer pool before the pages have been recovered to the up-to-date state.
|
||||
|
||||
TRUE means that recovery is running and no operations on the log files
|
||||
are allowed yet: the variable name is misleading. */
|
||||
extern ibool recv_no_ibuf_operations;
|
||||
/** TRUE when recv_init_crash_recovery() has been called. */
|
||||
extern ibool recv_needed_recovery;
|
||||
#ifdef UNIV_DEBUG
|
||||
/** TRUE if writing to the redo log (mtr_commit) is forbidden.
|
||||
Protected by log_sys->mutex. */
|
||||
extern ibool recv_no_log_write;
|
||||
#endif /* UNIV_DEBUG */
|
||||
|
||||
/** TRUE if buf_page_is_corrupted() should check if the log sequence
|
||||
number (FIL_PAGE_LSN) is in the future. Initially FALSE, and set by
|
||||
recv_recovery_from_checkpoint_start_func(). */
|
||||
extern ibool recv_lsn_checks_on;
|
||||
#ifdef UNIV_HOTBACKUP
|
||||
/** TRUE when the redo log is being backed up */
|
||||
extern ibool recv_is_making_a_backup;
|
||||
#endif /* UNIV_HOTBACKUP */
|
||||
/** Maximum page number encountered in the redo log */
|
||||
extern ulint recv_max_parsed_page_no;
|
||||
|
||||
/** Size of the parsing buffer; it must accommodate RECV_SCAN_SIZE many
|
||||
times! */
|
||||
#define RECV_PARSING_BUF_SIZE (2 * 1024 * 1024)
|
||||
|
||||
/** Size of block reads when the log groups are scanned forward to do a
|
||||
roll-forward */
|
||||
#define RECV_SCAN_SIZE (4 * UNIV_PAGE_SIZE)
|
||||
|
||||
/** This many frames must be left free in the buffer pool when we scan
|
||||
the log and store the scanned log records in the buffer pool: we will
|
||||
use these free frames to read in pages when we start applying the
|
||||
log records to the database. */
|
||||
extern ulint recv_n_pool_free_frames;
|
||||
|
||||
#ifndef UNIV_NONINL
|
||||
#include "log0recv.ic"
|
||||
#endif
|
||||
|
||||
#endif
|
||||
53
storage/innobase/include/log0recv.ic
Normal file
53
storage/innobase/include/log0recv.ic
Normal file
|
|
@ -0,0 +1,53 @@
|
|||
/*****************************************************************************
|
||||
|
||||
Copyright (c) 1997, 2009, Oracle and/or its affiliates. All Rights Reserved.
|
||||
|
||||
This program is free software; you can redistribute it and/or modify it under
|
||||
the terms of the GNU General Public License as published by the Free Software
|
||||
Foundation; version 2 of the License.
|
||||
|
||||
This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
|
||||
FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License along with
|
||||
this program; if not, write to the Free Software Foundation, Inc.,
|
||||
51 Franklin Street, Suite 500, Boston, MA 02110-1335 USA
|
||||
|
||||
*****************************************************************************/
|
||||
|
||||
/**************************************************//**
|
||||
@file include/log0recv.ic
|
||||
Recovery
|
||||
|
||||
Created 9/20/1997 Heikki Tuuri
|
||||
*******************************************************/
|
||||
|
||||
#include "univ.i"
|
||||
|
||||
/*******************************************************************//**
|
||||
Returns TRUE if recovery is currently running.
|
||||
@return recv_recovery_on */
|
||||
UNIV_INLINE
|
||||
ibool
|
||||
recv_recovery_is_on(void)
|
||||
/*=====================*/
|
||||
{
|
||||
return(recv_recovery_on);
|
||||
}
|
||||
|
||||
#ifdef UNIV_LOG_ARCHIVE
|
||||
/** TRUE when applying redo log records from an archived log file */
|
||||
extern ibool recv_recovery_from_backup_on;
|
||||
|
||||
/*******************************************************************//**
|
||||
Returns TRUE if recovery from backup is currently running.
|
||||
@return recv_recovery_from_backup_on */
|
||||
UNIV_INLINE
|
||||
ibool
|
||||
recv_recovery_from_backup_is_on(void)
|
||||
/*=================================*/
|
||||
{
|
||||
return(recv_recovery_from_backup_on);
|
||||
}
|
||||
#endif /* UNIV_LOG_ARCHIVE */
|
||||
418
storage/innobase/include/mach0data.h
Normal file
418
storage/innobase/include/mach0data.h
Normal file
|
|
@ -0,0 +1,418 @@
|
|||
/*****************************************************************************
|
||||
|
||||
Copyright (c) 1995, 2009, Oracle and/or its affiliates. All Rights Reserved.
|
||||
|
||||
This program is free software; you can redistribute it and/or modify it under
|
||||
the terms of the GNU General Public License as published by the Free Software
|
||||
Foundation; version 2 of the License.
|
||||
|
||||
This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
|
||||
FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License along with
|
||||
this program; if not, write to the Free Software Foundation, Inc.,
|
||||
51 Franklin Street, Suite 500, Boston, MA 02110-1335 USA
|
||||
|
||||
*****************************************************************************/
|
||||
|
||||
/******************************************************************//**
|
||||
@file include/mach0data.h
|
||||
Utilities for converting data from the database file
|
||||
to the machine format.
|
||||
|
||||
Created 11/28/1995 Heikki Tuuri
|
||||
***********************************************************************/
|
||||
|
||||
#ifndef mach0data_h
|
||||
#define mach0data_h
|
||||
|
||||
#ifndef UNIV_INNOCHECKSUM
|
||||
|
||||
#include "univ.i"
|
||||
#include "ut0byte.h"
|
||||
|
||||
/* The data and all fields are always stored in a database file
|
||||
in the same format: ascii, big-endian, ... .
|
||||
All data in the files MUST be accessed using the functions in this
|
||||
module. */
|
||||
|
||||
/*******************************************************//**
|
||||
The following function is used to store data in one byte. */
|
||||
UNIV_INLINE
|
||||
void
|
||||
mach_write_to_1(
|
||||
/*============*/
|
||||
byte* b, /*!< in: pointer to byte where to store */
|
||||
ulint n); /*!< in: ulint integer to be stored, >= 0, < 256 */
|
||||
/********************************************************//**
|
||||
The following function is used to fetch data from one byte.
|
||||
@return ulint integer, >= 0, < 256 */
|
||||
UNIV_INLINE
|
||||
ulint
|
||||
mach_read_from_1(
|
||||
/*=============*/
|
||||
const byte* b) /*!< in: pointer to byte */
|
||||
__attribute__((nonnull, pure));
|
||||
/*******************************************************//**
|
||||
The following function is used to store data in two consecutive
|
||||
bytes. We store the most significant byte to the lower address. */
|
||||
UNIV_INLINE
|
||||
void
|
||||
mach_write_to_2(
|
||||
/*============*/
|
||||
byte* b, /*!< in: pointer to two bytes where to store */
|
||||
ulint n); /*!< in: ulint integer to be stored, >= 0, < 64k */
|
||||
/********************************************************//**
|
||||
The following function is used to fetch data from two consecutive
|
||||
bytes. The most significant byte is at the lowest address.
|
||||
@return ulint integer, >= 0, < 64k */
|
||||
UNIV_INLINE
|
||||
ulint
|
||||
mach_read_from_2(
|
||||
/*=============*/
|
||||
const byte* b) /*!< in: pointer to two bytes */
|
||||
__attribute__((nonnull, pure));
|
||||
|
||||
/********************************************************//**
|
||||
The following function is used to convert a 16-bit data item
|
||||
to the canonical format, for fast bytewise equality test
|
||||
against memory.
|
||||
@return 16-bit integer in canonical format */
|
||||
UNIV_INLINE
|
||||
uint16
|
||||
mach_encode_2(
|
||||
/*==========*/
|
||||
ulint n) /*!< in: integer in machine-dependent format */
|
||||
__attribute__((const));
|
||||
/********************************************************//**
|
||||
The following function is used to convert a 16-bit data item
|
||||
from the canonical format, for fast bytewise equality test
|
||||
against memory.
|
||||
@return integer in machine-dependent format */
|
||||
UNIV_INLINE
|
||||
ulint
|
||||
mach_decode_2(
|
||||
/*==========*/
|
||||
uint16 n) /*!< in: 16-bit integer in canonical format */
|
||||
__attribute__((const));
|
||||
/*******************************************************//**
|
||||
The following function is used to store data in 3 consecutive
|
||||
bytes. We store the most significant byte to the lowest address. */
|
||||
UNIV_INLINE
|
||||
void
|
||||
mach_write_to_3(
|
||||
/*============*/
|
||||
byte* b, /*!< in: pointer to 3 bytes where to store */
|
||||
ulint n); /*!< in: ulint integer to be stored */
|
||||
/********************************************************//**
|
||||
The following function is used to fetch data from 3 consecutive
|
||||
bytes. The most significant byte is at the lowest address.
|
||||
@return ulint integer */
|
||||
UNIV_INLINE
|
||||
ulint
|
||||
mach_read_from_3(
|
||||
/*=============*/
|
||||
const byte* b) /*!< in: pointer to 3 bytes */
|
||||
__attribute__((nonnull, pure));
|
||||
/*******************************************************//**
|
||||
The following function is used to store data in four consecutive
|
||||
bytes. We store the most significant byte to the lowest address. */
|
||||
UNIV_INLINE
|
||||
void
|
||||
mach_write_to_4(
|
||||
/*============*/
|
||||
byte* b, /*!< in: pointer to four bytes where to store */
|
||||
ulint n); /*!< in: ulint integer to be stored */
|
||||
/********************************************************//**
|
||||
The following function is used to fetch data from 4 consecutive
|
||||
bytes. The most significant byte is at the lowest address.
|
||||
@return ulint integer */
|
||||
UNIV_INLINE
|
||||
ulint
|
||||
mach_read_from_4(
|
||||
/*=============*/
|
||||
const byte* b) /*!< in: pointer to four bytes */
|
||||
__attribute__((nonnull, pure));
|
||||
/*********************************************************//**
|
||||
Writes a ulint in a compressed form (1..5 bytes).
|
||||
@return stored size in bytes */
|
||||
UNIV_INLINE
|
||||
ulint
|
||||
mach_write_compressed(
|
||||
/*==================*/
|
||||
byte* b, /*!< in: pointer to memory where to store */
|
||||
ulint n); /*!< in: ulint integer to be stored */
|
||||
/*********************************************************//**
|
||||
Returns the size of an ulint when written in the compressed form.
|
||||
@return compressed size in bytes */
|
||||
UNIV_INLINE
|
||||
ulint
|
||||
mach_get_compressed_size(
|
||||
/*=====================*/
|
||||
ulint n) /*!< in: ulint integer to be stored */
|
||||
__attribute__((const));
|
||||
/*********************************************************//**
|
||||
Reads a ulint in a compressed form.
|
||||
@return read integer */
|
||||
UNIV_INLINE
|
||||
ulint
|
||||
mach_read_compressed(
|
||||
/*=================*/
|
||||
const byte* b) /*!< in: pointer to memory from where to read */
|
||||
__attribute__((nonnull, pure));
|
||||
/*******************************************************//**
|
||||
The following function is used to store data in 6 consecutive
|
||||
bytes. We store the most significant byte to the lowest address. */
|
||||
UNIV_INLINE
|
||||
void
|
||||
mach_write_to_6(
|
||||
/*============*/
|
||||
byte* b, /*!< in: pointer to 6 bytes where to store */
|
||||
ib_uint64_t id); /*!< in: 48-bit integer */
|
||||
/********************************************************//**
|
||||
The following function is used to fetch data from 6 consecutive
|
||||
bytes. The most significant byte is at the lowest address.
|
||||
@return 48-bit integer */
|
||||
UNIV_INLINE
|
||||
ib_uint64_t
|
||||
mach_read_from_6(
|
||||
/*=============*/
|
||||
const byte* b) /*!< in: pointer to 6 bytes */
|
||||
__attribute__((nonnull, pure));
|
||||
/*******************************************************//**
|
||||
The following function is used to store data in 7 consecutive
|
||||
bytes. We store the most significant byte to the lowest address. */
|
||||
UNIV_INLINE
|
||||
void
|
||||
mach_write_to_7(
|
||||
/*============*/
|
||||
byte* b, /*!< in: pointer to 7 bytes where to store */
|
||||
ib_uint64_t n); /*!< in: 56-bit integer */
|
||||
/********************************************************//**
|
||||
The following function is used to fetch data from 7 consecutive
|
||||
bytes. The most significant byte is at the lowest address.
|
||||
@return 56-bit integer */
|
||||
UNIV_INLINE
|
||||
ib_uint64_t
|
||||
mach_read_from_7(
|
||||
/*=============*/
|
||||
const byte* b) /*!< in: pointer to 7 bytes */
|
||||
__attribute__((nonnull, pure));
|
||||
/*******************************************************//**
|
||||
The following function is used to store data in 8 consecutive
|
||||
bytes. We store the most significant byte to the lowest address. */
|
||||
UNIV_INLINE
|
||||
void
|
||||
mach_write_to_8(
|
||||
/*============*/
|
||||
void* b, /*!< in: pointer to 8 bytes where to store */
|
||||
ib_uint64_t n); /*!< in: 64-bit integer to be stored */
|
||||
/********************************************************//**
|
||||
The following function is used to fetch data from 8 consecutive
|
||||
bytes. The most significant byte is at the lowest address.
|
||||
@return 64-bit integer */
|
||||
UNIV_INLINE
|
||||
ib_uint64_t
|
||||
mach_read_from_8(
|
||||
/*=============*/
|
||||
const byte* b) /*!< in: pointer to 8 bytes */
|
||||
__attribute__((nonnull, pure));
|
||||
/*********************************************************//**
|
||||
Writes a 64-bit integer in a compressed form (5..9 bytes).
|
||||
@return size in bytes */
|
||||
UNIV_INLINE
|
||||
ulint
|
||||
mach_ull_write_compressed(
|
||||
/*======================*/
|
||||
byte* b, /*!< in: pointer to memory where to store */
|
||||
ib_uint64_t n); /*!< in: 64-bit integer to be stored */
|
||||
/*********************************************************//**
|
||||
Returns the size of a 64-bit integer when written in the compressed form.
|
||||
@return compressed size in bytes */
|
||||
UNIV_INLINE
|
||||
ulint
|
||||
mach_ull_get_compressed_size(
|
||||
/*=========================*/
|
||||
ib_uint64_t n); /*!< in: 64-bit integer to be stored */
|
||||
/*********************************************************//**
|
||||
Reads a 64-bit integer in a compressed form.
|
||||
@return the value read */
|
||||
UNIV_INLINE
|
||||
ib_uint64_t
|
||||
mach_ull_read_compressed(
|
||||
/*=====================*/
|
||||
const byte* b) /*!< in: pointer to memory from where to read */
|
||||
__attribute__((nonnull, pure));
|
||||
/*********************************************************//**
|
||||
Writes a 64-bit integer in a compressed form (1..11 bytes).
|
||||
@return size in bytes */
|
||||
UNIV_INLINE
|
||||
ulint
|
||||
mach_ull_write_much_compressed(
|
||||
/*===========================*/
|
||||
byte* b, /*!< in: pointer to memory where to store */
|
||||
ib_uint64_t n); /*!< in: 64-bit integer to be stored */
|
||||
/*********************************************************//**
|
||||
Returns the size of a 64-bit integer when written in the compressed form.
|
||||
@return compressed size in bytes */
|
||||
UNIV_INLINE
|
||||
ulint
|
||||
mach_ull_get_much_compressed_size(
|
||||
/*==============================*/
|
||||
ib_uint64_t n) /*!< in: 64-bit integer to be stored */
|
||||
__attribute__((const));
|
||||
/*********************************************************//**
|
||||
Reads a 64-bit integer in a compressed form.
|
||||
@return the value read */
|
||||
UNIV_INLINE
|
||||
ib_uint64_t
|
||||
mach_ull_read_much_compressed(
|
||||
/*==========================*/
|
||||
const byte* b) /*!< in: pointer to memory from where to read */
|
||||
__attribute__((nonnull, pure));
|
||||
/*********************************************************//**
|
||||
Reads a ulint in a compressed form if the log record fully contains it.
|
||||
@return pointer to end of the stored field, NULL if not complete */
|
||||
UNIV_INTERN
|
||||
byte*
|
||||
mach_parse_compressed(
|
||||
/*==================*/
|
||||
byte* ptr, /*!< in: pointer to buffer from where to read */
|
||||
byte* end_ptr,/*!< in: pointer to end of the buffer */
|
||||
ulint* val); /*!< out: read value */
|
||||
/*********************************************************//**
|
||||
Reads a 64-bit integer in a compressed form
|
||||
if the log record fully contains it.
|
||||
@return pointer to end of the stored field, NULL if not complete */
|
||||
UNIV_INLINE
|
||||
byte*
|
||||
mach_ull_parse_compressed(
|
||||
/*======================*/
|
||||
byte* ptr, /*!< in: pointer to buffer from where to read */
|
||||
byte* end_ptr,/*!< in: pointer to end of the buffer */
|
||||
ib_uint64_t* val); /*!< out: read value */
|
||||
#ifndef UNIV_HOTBACKUP
|
||||
/*********************************************************//**
|
||||
Reads a double. It is stored in a little-endian format.
|
||||
@return double read */
|
||||
UNIV_INLINE
|
||||
double
|
||||
mach_double_read(
|
||||
/*=============*/
|
||||
const byte* b) /*!< in: pointer to memory from where to read */
|
||||
__attribute__((nonnull, pure));
|
||||
/*********************************************************//**
|
||||
Writes a double. It is stored in a little-endian format. */
|
||||
UNIV_INLINE
|
||||
void
|
||||
mach_double_write(
|
||||
/*==============*/
|
||||
byte* b, /*!< in: pointer to memory where to write */
|
||||
double d); /*!< in: double */
|
||||
/*********************************************************//**
|
||||
Reads a float. It is stored in a little-endian format.
|
||||
@return float read */
|
||||
UNIV_INLINE
|
||||
float
|
||||
mach_float_read(
|
||||
/*============*/
|
||||
const byte* b) /*!< in: pointer to memory from where to read */
|
||||
__attribute__((nonnull, pure));
|
||||
/*********************************************************//**
|
||||
Writes a float. It is stored in a little-endian format. */
|
||||
UNIV_INLINE
|
||||
void
|
||||
mach_float_write(
|
||||
/*=============*/
|
||||
byte* b, /*!< in: pointer to memory where to write */
|
||||
float d); /*!< in: float */
|
||||
/*********************************************************//**
|
||||
Reads a ulint stored in the little-endian format.
|
||||
@return unsigned long int */
|
||||
UNIV_INLINE
|
||||
ulint
|
||||
mach_read_from_n_little_endian(
|
||||
/*===========================*/
|
||||
const byte* buf, /*!< in: from where to read */
|
||||
ulint buf_size) /*!< in: from how many bytes to read */
|
||||
__attribute__((nonnull, pure));
|
||||
/*********************************************************//**
|
||||
Writes a ulint in the little-endian format. */
|
||||
UNIV_INLINE
|
||||
void
|
||||
mach_write_to_n_little_endian(
|
||||
/*==========================*/
|
||||
byte* dest, /*!< in: where to write */
|
||||
ulint dest_size, /*!< in: into how many bytes to write */
|
||||
ulint n); /*!< in: unsigned long int to write */
|
||||
/*********************************************************//**
|
||||
Reads a ulint stored in the little-endian format.
|
||||
@return unsigned long int */
|
||||
UNIV_INLINE
|
||||
ulint
|
||||
mach_read_from_2_little_endian(
|
||||
/*===========================*/
|
||||
const byte* buf) /*!< in: from where to read */
|
||||
__attribute__((nonnull, pure));
|
||||
/*********************************************************//**
|
||||
Writes a ulint in the little-endian format. */
|
||||
UNIV_INLINE
|
||||
void
|
||||
mach_write_to_2_little_endian(
|
||||
/*==========================*/
|
||||
byte* dest, /*!< in: where to write */
|
||||
ulint n); /*!< in: unsigned long int to write */
|
||||
/*********************************************************//**
|
||||
Convert integral type from storage byte order (big endian) to
|
||||
host byte order.
|
||||
@return integer value */
|
||||
UNIV_INLINE
|
||||
ib_uint64_t
|
||||
mach_read_int_type(
|
||||
/*===============*/
|
||||
const byte* src, /*!< in: where to read from */
|
||||
ulint len, /*!< in: length of src */
|
||||
ibool unsigned_type); /*!< in: signed or unsigned flag */
|
||||
/***********************************************************//**
|
||||
Convert integral type from host byte order to (big-endian) storage
|
||||
byte order. */
|
||||
UNIV_INLINE
|
||||
void
|
||||
mach_write_int_type(
|
||||
/*================*/
|
||||
byte* dest, /*!< in: where to write*/
|
||||
const byte* src, /*!< in: where to read from */
|
||||
ulint len, /*!< in: length of src */
|
||||
bool usign); /*!< in: signed or unsigned flag */
|
||||
|
||||
/*************************************************************
|
||||
Convert a ulonglong integer from host byte order to (big-endian)
|
||||
storage byte order. */
|
||||
UNIV_INLINE
|
||||
void
|
||||
mach_write_ulonglong(
|
||||
/*=================*/
|
||||
byte* dest, /*!< in: where to write */
|
||||
ulonglong src, /*!< in: where to read from */
|
||||
ulint len, /*!< in: length of dest */
|
||||
bool usign); /*!< in: signed or unsigned flag */
|
||||
|
||||
/********************************************************//**
|
||||
Reads 1 - 4 bytes from a file page buffered in the buffer pool.
|
||||
@return value read */
|
||||
UNIV_INLINE
|
||||
ulint
|
||||
mach_read_ulint(
|
||||
/*============*/
|
||||
const byte* ptr, /*!< in: pointer from where to read */
|
||||
ulint type); /*!< in: MLOG_1BYTE, MLOG_2BYTES, MLOG_4BYTES */
|
||||
|
||||
#endif /* !UNIV_HOTBACKUP */
|
||||
#endif /* !UNIV_INNOCHECKSUM */
|
||||
|
||||
#ifndef UNIV_NONINL
|
||||
#include "mach0data.ic"
|
||||
#endif
|
||||
|
||||
#endif
|
||||
881
storage/innobase/include/mach0data.ic
Normal file
881
storage/innobase/include/mach0data.ic
Normal file
|
|
@ -0,0 +1,881 @@
|
|||
/*****************************************************************************
|
||||
|
||||
Copyright (c) 1995, 2009, Oracle and/or its affiliates. All Rights Reserved.
|
||||
|
||||
This program is free software; you can redistribute it and/or modify it under
|
||||
the terms of the GNU General Public License as published by the Free Software
|
||||
Foundation; version 2 of the License.
|
||||
|
||||
This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
|
||||
FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License along with
|
||||
this program; if not, write to the Free Software Foundation, Inc.,
|
||||
51 Franklin Street, Suite 500, Boston, MA 02110-1335 USA
|
||||
|
||||
*****************************************************************************/
|
||||
|
||||
/******************************************************************//**
|
||||
@file include/mach0data.ic
|
||||
Utilities for converting data from the database file
|
||||
to the machine format.
|
||||
|
||||
Created 11/28/1995 Heikki Tuuri
|
||||
***********************************************************************/
|
||||
|
||||
#ifndef UNIV_INNOCHECKSUM
|
||||
|
||||
#include "ut0mem.h"
|
||||
|
||||
/*******************************************************//**
|
||||
The following function is used to store data in one byte. */
|
||||
UNIV_INLINE
|
||||
void
|
||||
mach_write_to_1(
|
||||
/*============*/
|
||||
byte* b, /*!< in: pointer to byte where to store */
|
||||
ulint n) /*!< in: ulint integer to be stored, >= 0, < 256 */
|
||||
{
|
||||
ut_ad(b);
|
||||
ut_ad((n | 0xFFUL) <= 0xFFUL);
|
||||
|
||||
b[0] = (byte) n;
|
||||
}
|
||||
|
||||
/********************************************************//**
|
||||
The following function is used to fetch data from one byte.
|
||||
@return ulint integer, >= 0, < 256 */
|
||||
UNIV_INLINE
|
||||
ulint
|
||||
mach_read_from_1(
|
||||
/*=============*/
|
||||
const byte* b) /*!< in: pointer to byte */
|
||||
{
|
||||
ut_ad(b);
|
||||
return((ulint)(b[0]));
|
||||
}
|
||||
|
||||
/*******************************************************//**
|
||||
The following function is used to store data in two consecutive
|
||||
bytes. We store the most significant byte to the lowest address. */
|
||||
UNIV_INLINE
|
||||
void
|
||||
mach_write_to_2(
|
||||
/*============*/
|
||||
byte* b, /*!< in: pointer to two bytes where to store */
|
||||
ulint n) /*!< in: ulint integer to be stored */
|
||||
{
|
||||
ut_ad(b);
|
||||
ut_ad((n | 0xFFFFUL) <= 0xFFFFUL);
|
||||
|
||||
b[0] = (byte)(n >> 8);
|
||||
b[1] = (byte)(n);
|
||||
}
|
||||
|
||||
/********************************************************//**
|
||||
The following function is used to fetch data from 2 consecutive
|
||||
bytes. The most significant byte is at the lowest address.
|
||||
@return ulint integer */
|
||||
UNIV_INLINE
|
||||
ulint
|
||||
mach_read_from_2(
|
||||
/*=============*/
|
||||
const byte* b) /*!< in: pointer to 2 bytes */
|
||||
{
|
||||
return(((ulint)(b[0]) << 8) | (ulint)(b[1]));
|
||||
}
|
||||
|
||||
/********************************************************//**
|
||||
The following function is used to convert a 16-bit data item
|
||||
to the canonical format, for fast bytewise equality test
|
||||
against memory.
|
||||
@return 16-bit integer in canonical format */
|
||||
UNIV_INLINE
|
||||
uint16
|
||||
mach_encode_2(
|
||||
/*==========*/
|
||||
ulint n) /*!< in: integer in machine-dependent format */
|
||||
{
|
||||
uint16 ret;
|
||||
ut_ad(2 == sizeof ret);
|
||||
mach_write_to_2((byte*) &ret, n);
|
||||
return(ret);
|
||||
}
|
||||
/********************************************************//**
|
||||
The following function is used to convert a 16-bit data item
|
||||
from the canonical format, for fast bytewise equality test
|
||||
against memory.
|
||||
@return integer in machine-dependent format */
|
||||
UNIV_INLINE
|
||||
ulint
|
||||
mach_decode_2(
|
||||
/*==========*/
|
||||
uint16 n) /*!< in: 16-bit integer in canonical format */
|
||||
{
|
||||
ut_ad(2 == sizeof n);
|
||||
return(mach_read_from_2((const byte*) &n));
|
||||
}
|
||||
|
||||
/*******************************************************//**
|
||||
The following function is used to store data in 3 consecutive
|
||||
bytes. We store the most significant byte to the lowest address. */
|
||||
UNIV_INLINE
|
||||
void
|
||||
mach_write_to_3(
|
||||
/*============*/
|
||||
byte* b, /*!< in: pointer to 3 bytes where to store */
|
||||
ulint n) /*!< in: ulint integer to be stored */
|
||||
{
|
||||
ut_ad(b);
|
||||
ut_ad((n | 0xFFFFFFUL) <= 0xFFFFFFUL);
|
||||
|
||||
b[0] = (byte)(n >> 16);
|
||||
b[1] = (byte)(n >> 8);
|
||||
b[2] = (byte)(n);
|
||||
}
|
||||
|
||||
/********************************************************//**
|
||||
The following function is used to fetch data from 3 consecutive
|
||||
bytes. The most significant byte is at the lowest address.
|
||||
@return ulint integer */
|
||||
UNIV_INLINE
|
||||
ulint
|
||||
mach_read_from_3(
|
||||
/*=============*/
|
||||
const byte* b) /*!< in: pointer to 3 bytes */
|
||||
{
|
||||
ut_ad(b);
|
||||
return( ((ulint)(b[0]) << 16)
|
||||
| ((ulint)(b[1]) << 8)
|
||||
| (ulint)(b[2])
|
||||
);
|
||||
}
|
||||
|
||||
/*******************************************************//**
|
||||
The following function is used to store data in four consecutive
|
||||
bytes. We store the most significant byte to the lowest address. */
|
||||
UNIV_INLINE
|
||||
void
|
||||
mach_write_to_4(
|
||||
/*============*/
|
||||
byte* b, /*!< in: pointer to four bytes where to store */
|
||||
ulint n) /*!< in: ulint integer to be stored */
|
||||
{
|
||||
ut_ad(b);
|
||||
|
||||
b[0] = (byte)(n >> 24);
|
||||
b[1] = (byte)(n >> 16);
|
||||
b[2] = (byte)(n >> 8);
|
||||
b[3] = (byte) n;
|
||||
}
|
||||
|
||||
#endif /* !UNIV_INNOCHECKSUM */
|
||||
|
||||
/********************************************************//**
|
||||
The following function is used to fetch data from 4 consecutive
|
||||
bytes. The most significant byte is at the lowest address.
|
||||
@return ulint integer */
|
||||
UNIV_INLINE
|
||||
ulint
|
||||
mach_read_from_4(
|
||||
/*=============*/
|
||||
const byte* b) /*!< in: pointer to four bytes */
|
||||
{
|
||||
ut_ad(b);
|
||||
return( ((ulint)(b[0]) << 24)
|
||||
| ((ulint)(b[1]) << 16)
|
||||
| ((ulint)(b[2]) << 8)
|
||||
| (ulint)(b[3])
|
||||
);
|
||||
}
|
||||
|
||||
#ifndef UNIV_INNOCHECKSUM
|
||||
|
||||
/*********************************************************//**
|
||||
Writes a ulint in a compressed form where the first byte codes the
|
||||
length of the stored ulint. We look at the most significant bits of
|
||||
the byte. If the most significant bit is zero, it means 1-byte storage,
|
||||
else if the 2nd bit is 0, it means 2-byte storage, else if 3rd is 0,
|
||||
it means 3-byte storage, else if 4th is 0, it means 4-byte storage,
|
||||
else the storage is 5-byte.
|
||||
@return compressed size in bytes */
|
||||
UNIV_INLINE
|
||||
ulint
|
||||
mach_write_compressed(
|
||||
/*==================*/
|
||||
byte* b, /*!< in: pointer to memory where to store */
|
||||
ulint n) /*!< in: ulint integer (< 2^32) to be stored */
|
||||
{
|
||||
ut_ad(b);
|
||||
|
||||
if (n < 0x80UL) {
|
||||
mach_write_to_1(b, n);
|
||||
return(1);
|
||||
} else if (n < 0x4000UL) {
|
||||
mach_write_to_2(b, n | 0x8000UL);
|
||||
return(2);
|
||||
} else if (n < 0x200000UL) {
|
||||
mach_write_to_3(b, n | 0xC00000UL);
|
||||
return(3);
|
||||
} else if (n < 0x10000000UL) {
|
||||
mach_write_to_4(b, n | 0xE0000000UL);
|
||||
return(4);
|
||||
} else {
|
||||
mach_write_to_1(b, 0xF0UL);
|
||||
mach_write_to_4(b + 1, n);
|
||||
return(5);
|
||||
}
|
||||
}
|
||||
|
||||
/*********************************************************//**
|
||||
Returns the size of a ulint when written in the compressed form.
|
||||
@return compressed size in bytes */
|
||||
UNIV_INLINE
|
||||
ulint
|
||||
mach_get_compressed_size(
|
||||
/*=====================*/
|
||||
ulint n) /*!< in: ulint integer (< 2^32) to be stored */
|
||||
{
|
||||
if (n < 0x80UL) {
|
||||
return(1);
|
||||
} else if (n < 0x4000UL) {
|
||||
return(2);
|
||||
} else if (n < 0x200000UL) {
|
||||
return(3);
|
||||
} else if (n < 0x10000000UL) {
|
||||
return(4);
|
||||
} else {
|
||||
return(5);
|
||||
}
|
||||
}
|
||||
|
||||
/*********************************************************//**
|
||||
Reads a ulint in a compressed form.
|
||||
@return read integer (< 2^32) */
|
||||
UNIV_INLINE
|
||||
ulint
|
||||
mach_read_compressed(
|
||||
/*=================*/
|
||||
const byte* b) /*!< in: pointer to memory from where to read */
|
||||
{
|
||||
ulint flag;
|
||||
|
||||
ut_ad(b);
|
||||
|
||||
flag = mach_read_from_1(b);
|
||||
|
||||
if (flag < 0x80UL) {
|
||||
return(flag);
|
||||
} else if (flag < 0xC0UL) {
|
||||
return(mach_read_from_2(b) & 0x7FFFUL);
|
||||
} else if (flag < 0xE0UL) {
|
||||
return(mach_read_from_3(b) & 0x3FFFFFUL);
|
||||
} else if (flag < 0xF0UL) {
|
||||
return(mach_read_from_4(b) & 0x1FFFFFFFUL);
|
||||
} else {
|
||||
ut_ad(flag == 0xF0UL);
|
||||
return(mach_read_from_4(b + 1));
|
||||
}
|
||||
}
|
||||
|
||||
/*******************************************************//**
|
||||
The following function is used to store data in 8 consecutive
|
||||
bytes. We store the most significant byte to the lowest address. */
|
||||
UNIV_INLINE
|
||||
void
|
||||
mach_write_to_8(
|
||||
/*============*/
|
||||
void* b, /*!< in: pointer to 8 bytes where to store */
|
||||
ib_uint64_t n) /*!< in: 64-bit integer to be stored */
|
||||
{
|
||||
ut_ad(b);
|
||||
|
||||
mach_write_to_4(static_cast<byte*>(b), (ulint) (n >> 32));
|
||||
mach_write_to_4(static_cast<byte*>(b) + 4, (ulint) n);
|
||||
}
|
||||
|
||||
/********************************************************//**
|
||||
The following function is used to fetch data from 8 consecutive
|
||||
bytes. The most significant byte is at the lowest address.
|
||||
@return 64-bit integer */
|
||||
UNIV_INLINE
|
||||
ib_uint64_t
|
||||
mach_read_from_8(
|
||||
/*=============*/
|
||||
const byte* b) /*!< in: pointer to 8 bytes */
|
||||
{
|
||||
ib_uint64_t ull;
|
||||
|
||||
ull = ((ib_uint64_t) mach_read_from_4(b)) << 32;
|
||||
ull |= (ib_uint64_t) mach_read_from_4(b + 4);
|
||||
|
||||
return(ull);
|
||||
}
|
||||
|
||||
/*******************************************************//**
|
||||
The following function is used to store data in 7 consecutive
|
||||
bytes. We store the most significant byte to the lowest address. */
|
||||
UNIV_INLINE
|
||||
void
|
||||
mach_write_to_7(
|
||||
/*============*/
|
||||
byte* b, /*!< in: pointer to 7 bytes where to store */
|
||||
ib_uint64_t n) /*!< in: 56-bit integer */
|
||||
{
|
||||
ut_ad(b);
|
||||
|
||||
mach_write_to_3(b, (ulint) (n >> 32));
|
||||
mach_write_to_4(b + 3, (ulint) n);
|
||||
}
|
||||
|
||||
/********************************************************//**
|
||||
The following function is used to fetch data from 7 consecutive
|
||||
bytes. The most significant byte is at the lowest address.
|
||||
@return 56-bit integer */
|
||||
UNIV_INLINE
|
||||
ib_uint64_t
|
||||
mach_read_from_7(
|
||||
/*=============*/
|
||||
const byte* b) /*!< in: pointer to 7 bytes */
|
||||
{
|
||||
ut_ad(b);
|
||||
|
||||
return(ut_ull_create(mach_read_from_3(b), mach_read_from_4(b + 3)));
|
||||
}
|
||||
|
||||
/*******************************************************//**
|
||||
The following function is used to store data in 6 consecutive
|
||||
bytes. We store the most significant byte to the lowest address. */
|
||||
UNIV_INLINE
|
||||
void
|
||||
mach_write_to_6(
|
||||
/*============*/
|
||||
byte* b, /*!< in: pointer to 6 bytes where to store */
|
||||
ib_uint64_t n) /*!< in: 48-bit integer */
|
||||
{
|
||||
ut_ad(b);
|
||||
|
||||
mach_write_to_2(b, (ulint) (n >> 32));
|
||||
mach_write_to_4(b + 2, (ulint) n);
|
||||
}
|
||||
|
||||
/********************************************************//**
|
||||
The following function is used to fetch data from 6 consecutive
|
||||
bytes. The most significant byte is at the lowest address.
|
||||
@return 48-bit integer */
|
||||
UNIV_INLINE
|
||||
ib_uint64_t
|
||||
mach_read_from_6(
|
||||
/*=============*/
|
||||
const byte* b) /*!< in: pointer to 6 bytes */
|
||||
{
|
||||
ut_ad(b);
|
||||
|
||||
return(ut_ull_create(mach_read_from_2(b), mach_read_from_4(b + 2)));
|
||||
}
|
||||
|
||||
/*********************************************************//**
|
||||
Writes a 64-bit integer in a compressed form (5..9 bytes).
|
||||
@return size in bytes */
|
||||
UNIV_INLINE
|
||||
ulint
|
||||
mach_ull_write_compressed(
|
||||
/*======================*/
|
||||
byte* b, /*!< in: pointer to memory where to store */
|
||||
ib_uint64_t n) /*!< in: 64-bit integer to be stored */
|
||||
{
|
||||
ulint size;
|
||||
|
||||
ut_ad(b);
|
||||
|
||||
size = mach_write_compressed(b, (ulint) (n >> 32));
|
||||
mach_write_to_4(b + size, (ulint) n);
|
||||
|
||||
return(size + 4);
|
||||
}
|
||||
|
||||
/*********************************************************//**
|
||||
Returns the size of a 64-bit integer when written in the compressed form.
|
||||
@return compressed size in bytes */
|
||||
UNIV_INLINE
|
||||
ulint
|
||||
mach_ull_get_compressed_size(
|
||||
/*=========================*/
|
||||
ib_uint64_t n) /*!< in: 64-bit integer to be stored */
|
||||
{
|
||||
return(4 + mach_get_compressed_size((ulint) (n >> 32)));
|
||||
}
|
||||
|
||||
/*********************************************************//**
|
||||
Reads a 64-bit integer in a compressed form.
|
||||
@return the value read */
|
||||
UNIV_INLINE
|
||||
ib_uint64_t
|
||||
mach_ull_read_compressed(
|
||||
/*=====================*/
|
||||
const byte* b) /*!< in: pointer to memory from where to read */
|
||||
{
|
||||
ib_uint64_t n;
|
||||
ulint size;
|
||||
|
||||
ut_ad(b);
|
||||
|
||||
n = (ib_uint64_t) mach_read_compressed(b);
|
||||
|
||||
size = mach_get_compressed_size((ulint) n);
|
||||
|
||||
n <<= 32;
|
||||
n |= (ib_uint64_t) mach_read_from_4(b + size);
|
||||
|
||||
return(n);
|
||||
}
|
||||
|
||||
/*********************************************************//**
|
||||
Writes a 64-bit integer in a compressed form (1..11 bytes).
|
||||
@return size in bytes */
|
||||
UNIV_INLINE
|
||||
ulint
|
||||
mach_ull_write_much_compressed(
|
||||
/*===========================*/
|
||||
byte* b, /*!< in: pointer to memory where to store */
|
||||
ib_uint64_t n) /*!< in: 64-bit integer to be stored */
|
||||
{
|
||||
ulint size;
|
||||
|
||||
ut_ad(b);
|
||||
|
||||
if (!(n >> 32)) {
|
||||
return(mach_write_compressed(b, (ulint) n));
|
||||
}
|
||||
|
||||
*b = (byte)0xFF;
|
||||
size = 1 + mach_write_compressed(b + 1, (ulint) (n >> 32));
|
||||
|
||||
size += mach_write_compressed(b + size, (ulint) n & 0xFFFFFFFF);
|
||||
|
||||
return(size);
|
||||
}
|
||||
|
||||
/*********************************************************//**
|
||||
Returns the size of a 64-bit integer when written in the compressed form.
|
||||
@return compressed size in bytes */
|
||||
UNIV_INLINE
|
||||
ulint
|
||||
mach_ull_get_much_compressed_size(
|
||||
/*==============================*/
|
||||
ib_uint64_t n) /*!< in: 64-bit integer to be stored */
|
||||
{
|
||||
if (!(n >> 32)) {
|
||||
return(mach_get_compressed_size((ulint) n));
|
||||
}
|
||||
|
||||
return(1 + mach_get_compressed_size((ulint) (n >> 32))
|
||||
+ mach_get_compressed_size((ulint) n & ULINT32_MASK));
|
||||
}
|
||||
|
||||
/*********************************************************//**
|
||||
Reads a 64-bit integer in a compressed form.
|
||||
@return the value read */
|
||||
UNIV_INLINE
|
||||
ib_uint64_t
|
||||
mach_ull_read_much_compressed(
|
||||
/*==========================*/
|
||||
const byte* b) /*!< in: pointer to memory from where to read */
|
||||
{
|
||||
ib_uint64_t n;
|
||||
ulint size;
|
||||
|
||||
ut_ad(b);
|
||||
|
||||
if (*b != (byte)0xFF) {
|
||||
n = 0;
|
||||
size = 0;
|
||||
} else {
|
||||
n = (ib_uint64_t) mach_read_compressed(b + 1);
|
||||
|
||||
size = 1 + mach_get_compressed_size((ulint) n);
|
||||
n <<= 32;
|
||||
}
|
||||
|
||||
n |= mach_read_compressed(b + size);
|
||||
|
||||
return(n);
|
||||
}
|
||||
|
||||
/*********************************************************//**
|
||||
Reads a 64-bit integer in a compressed form
|
||||
if the log record fully contains it.
|
||||
@return pointer to end of the stored field, NULL if not complete */
|
||||
UNIV_INLINE
|
||||
byte*
|
||||
mach_ull_parse_compressed(
|
||||
/*======================*/
|
||||
byte* ptr, /* in: pointer to buffer from where to read */
|
||||
byte* end_ptr,/* in: pointer to end of the buffer */
|
||||
ib_uint64_t* val) /* out: read value */
|
||||
{
|
||||
ulint size;
|
||||
|
||||
ut_ad(ptr);
|
||||
ut_ad(end_ptr);
|
||||
ut_ad(val);
|
||||
|
||||
if (end_ptr < ptr + 5) {
|
||||
|
||||
return(NULL);
|
||||
}
|
||||
|
||||
*val = mach_read_compressed(ptr);
|
||||
|
||||
size = mach_get_compressed_size((ulint) *val);
|
||||
|
||||
ptr += size;
|
||||
|
||||
if (end_ptr < ptr + 4) {
|
||||
|
||||
return(NULL);
|
||||
}
|
||||
|
||||
*val <<= 32;
|
||||
*val |= mach_read_from_4(ptr);
|
||||
|
||||
return(ptr + 4);
|
||||
}
|
||||
#ifndef UNIV_HOTBACKUP
|
||||
/*********************************************************//**
|
||||
Reads a double. It is stored in a little-endian format.
|
||||
@return double read */
|
||||
UNIV_INLINE
|
||||
double
|
||||
mach_double_read(
|
||||
/*=============*/
|
||||
const byte* b) /*!< in: pointer to memory from where to read */
|
||||
{
|
||||
double d;
|
||||
ulint i;
|
||||
byte* ptr;
|
||||
|
||||
ptr = (byte*) &d;
|
||||
|
||||
for (i = 0; i < sizeof(double); i++) {
|
||||
#ifdef WORDS_BIGENDIAN
|
||||
ptr[sizeof(double) - i - 1] = b[i];
|
||||
#else
|
||||
ptr[i] = b[i];
|
||||
#endif
|
||||
}
|
||||
|
||||
return(d);
|
||||
}
|
||||
|
||||
/*********************************************************//**
|
||||
Writes a double. It is stored in a little-endian format. */
|
||||
UNIV_INLINE
|
||||
void
|
||||
mach_double_write(
|
||||
/*==============*/
|
||||
byte* b, /*!< in: pointer to memory where to write */
|
||||
double d) /*!< in: double */
|
||||
{
|
||||
ulint i;
|
||||
byte* ptr;
|
||||
|
||||
ptr = (byte*) &d;
|
||||
|
||||
for (i = 0; i < sizeof(double); i++) {
|
||||
#ifdef WORDS_BIGENDIAN
|
||||
b[i] = ptr[sizeof(double) - i - 1];
|
||||
#else
|
||||
b[i] = ptr[i];
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
/*********************************************************//**
|
||||
Reads a float. It is stored in a little-endian format.
|
||||
@return float read */
|
||||
UNIV_INLINE
|
||||
float
|
||||
mach_float_read(
|
||||
/*============*/
|
||||
const byte* b) /*!< in: pointer to memory from where to read */
|
||||
{
|
||||
float d;
|
||||
ulint i;
|
||||
byte* ptr;
|
||||
|
||||
ptr = (byte*) &d;
|
||||
|
||||
for (i = 0; i < sizeof(float); i++) {
|
||||
#ifdef WORDS_BIGENDIAN
|
||||
ptr[sizeof(float) - i - 1] = b[i];
|
||||
#else
|
||||
ptr[i] = b[i];
|
||||
#endif
|
||||
}
|
||||
|
||||
return(d);
|
||||
}
|
||||
|
||||
/*********************************************************//**
|
||||
Writes a float. It is stored in a little-endian format. */
|
||||
UNIV_INLINE
|
||||
void
|
||||
mach_float_write(
|
||||
/*=============*/
|
||||
byte* b, /*!< in: pointer to memory where to write */
|
||||
float d) /*!< in: float */
|
||||
{
|
||||
ulint i;
|
||||
byte* ptr;
|
||||
|
||||
ptr = (byte*) &d;
|
||||
|
||||
for (i = 0; i < sizeof(float); i++) {
|
||||
#ifdef WORDS_BIGENDIAN
|
||||
b[i] = ptr[sizeof(float) - i - 1];
|
||||
#else
|
||||
b[i] = ptr[i];
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
/*********************************************************//**
|
||||
Reads a ulint stored in the little-endian format.
|
||||
@return unsigned long int */
|
||||
UNIV_INLINE
|
||||
ulint
|
||||
mach_read_from_n_little_endian(
|
||||
/*===========================*/
|
||||
const byte* buf, /*!< in: from where to read */
|
||||
ulint buf_size) /*!< in: from how many bytes to read */
|
||||
{
|
||||
ulint n = 0;
|
||||
const byte* ptr;
|
||||
|
||||
ut_ad(buf_size > 0);
|
||||
|
||||
ptr = buf + buf_size;
|
||||
|
||||
for (;;) {
|
||||
ptr--;
|
||||
|
||||
n = n << 8;
|
||||
|
||||
n += (ulint)(*ptr);
|
||||
|
||||
if (ptr == buf) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return(n);
|
||||
}
|
||||
|
||||
/*********************************************************//**
|
||||
Writes a ulint in the little-endian format. */
|
||||
UNIV_INLINE
|
||||
void
|
||||
mach_write_to_n_little_endian(
|
||||
/*==========================*/
|
||||
byte* dest, /*!< in: where to write */
|
||||
ulint dest_size, /*!< in: into how many bytes to write */
|
||||
ulint n) /*!< in: unsigned long int to write */
|
||||
{
|
||||
byte* end;
|
||||
|
||||
ut_ad(dest_size <= sizeof(ulint));
|
||||
ut_ad(dest_size > 0);
|
||||
|
||||
end = dest + dest_size;
|
||||
|
||||
for (;;) {
|
||||
*dest = (byte)(n & 0xFF);
|
||||
|
||||
n = n >> 8;
|
||||
|
||||
dest++;
|
||||
|
||||
if (dest == end) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
ut_ad(n == 0);
|
||||
}
|
||||
|
||||
/*********************************************************//**
|
||||
Reads a ulint stored in the little-endian format.
|
||||
@return unsigned long int */
|
||||
UNIV_INLINE
|
||||
ulint
|
||||
mach_read_from_2_little_endian(
|
||||
/*===========================*/
|
||||
const byte* buf) /*!< in: from where to read */
|
||||
{
|
||||
return((ulint)(buf[0]) | ((ulint)(buf[1]) << 8));
|
||||
}
|
||||
|
||||
/*********************************************************//**
|
||||
Writes a ulint in the little-endian format. */
|
||||
UNIV_INLINE
|
||||
void
|
||||
mach_write_to_2_little_endian(
|
||||
/*==========================*/
|
||||
byte* dest, /*!< in: where to write */
|
||||
ulint n) /*!< in: unsigned long int to write */
|
||||
{
|
||||
ut_ad(n < 256 * 256);
|
||||
|
||||
*dest = (byte)(n & 0xFFUL);
|
||||
|
||||
n = n >> 8;
|
||||
dest++;
|
||||
|
||||
*dest = (byte)(n & 0xFFUL);
|
||||
}
|
||||
|
||||
/*********************************************************//**
|
||||
Convert integral type from storage byte order (big endian) to
|
||||
host byte order.
|
||||
@return integer value */
|
||||
UNIV_INLINE
|
||||
ib_uint64_t
|
||||
mach_read_int_type(
|
||||
/*===============*/
|
||||
const byte* src, /*!< in: where to read from */
|
||||
ulint len, /*!< in: length of src */
|
||||
ibool unsigned_type) /*!< in: signed or unsigned flag */
|
||||
{
|
||||
/* XXX this can be optimized on big-endian machines */
|
||||
|
||||
ullint ret;
|
||||
uint i;
|
||||
|
||||
if (unsigned_type || (src[0] & 0x80)) {
|
||||
|
||||
ret = 0x0000000000000000ULL;
|
||||
} else {
|
||||
|
||||
ret = 0xFFFFFFFFFFFFFF00ULL;
|
||||
}
|
||||
|
||||
if (unsigned_type) {
|
||||
|
||||
ret |= src[0];
|
||||
} else {
|
||||
|
||||
ret |= src[0] ^ 0x80;
|
||||
}
|
||||
|
||||
for (i = 1; i < len; i++) {
|
||||
ret <<= 8;
|
||||
ret |= src[i];
|
||||
}
|
||||
|
||||
return(ret);
|
||||
}
|
||||
/*********************************************************//**
|
||||
Swap byte ordering. */
|
||||
UNIV_INLINE
|
||||
void
|
||||
mach_swap_byte_order(
|
||||
/*=================*/
|
||||
byte* dest, /*!< out: where to write */
|
||||
const byte* from, /*!< in: where to read from */
|
||||
ulint len) /*!< in: length of src */
|
||||
{
|
||||
ut_ad(len > 0);
|
||||
ut_ad(len <= 8);
|
||||
|
||||
dest += len;
|
||||
|
||||
switch (len & 0x7) {
|
||||
case 0: *--dest = *from++;
|
||||
case 7: *--dest = *from++;
|
||||
case 6: *--dest = *from++;
|
||||
case 5: *--dest = *from++;
|
||||
case 4: *--dest = *from++;
|
||||
case 3: *--dest = *from++;
|
||||
case 2: *--dest = *from++;
|
||||
case 1: *--dest = *from;
|
||||
}
|
||||
}
|
||||
|
||||
/*************************************************************
|
||||
Convert integral type from host byte order (big-endian) storage
|
||||
byte order. */
|
||||
UNIV_INLINE
|
||||
void
|
||||
mach_write_int_type(
|
||||
/*================*/
|
||||
byte* dest, /*!< in: where to write */
|
||||
const byte* src, /*!< in: where to read from */
|
||||
ulint len, /*!< in: length of src */
|
||||
bool usign) /*!< in: signed or unsigned flag */
|
||||
{
|
||||
#ifdef WORDS_BIGENDIAN
|
||||
memcpy(dest, src, len);
|
||||
#else
|
||||
mach_swap_byte_order(dest, src, len);
|
||||
#endif /* WORDS_BIGENDIAN */
|
||||
|
||||
if (!usign) {
|
||||
*dest ^= 0x80;
|
||||
}
|
||||
}
|
||||
|
||||
/*************************************************************
|
||||
Convert a ulonglong integer from host byte order to (big-endian)
|
||||
storage byte order. */
|
||||
UNIV_INLINE
|
||||
void
|
||||
mach_write_ulonglong(
|
||||
/*=================*/
|
||||
byte* dest, /*!< in: where to write */
|
||||
ulonglong src, /*!< in: where to read from */
|
||||
ulint len, /*!< in: length of dest */
|
||||
bool usign) /*!< in: signed or unsigned flag */
|
||||
{
|
||||
byte* ptr = reinterpret_cast<byte*>(&src);
|
||||
|
||||
ut_ad(len <= sizeof(ulonglong));
|
||||
|
||||
#ifdef WORDS_BIGENDIAN
|
||||
memcpy(dest, ptr + (sizeof(src) - len), len);
|
||||
#else
|
||||
mach_swap_byte_order(dest, reinterpret_cast<byte*>(ptr), len);
|
||||
#endif /* WORDS_BIGENDIAN */
|
||||
|
||||
if (!usign) {
|
||||
*dest ^= 0x80;
|
||||
}
|
||||
}
|
||||
|
||||
/********************************************************//**
|
||||
Reads 1 - 4 bytes from a file page buffered in the buffer pool.
|
||||
@return value read */
|
||||
UNIV_INLINE
|
||||
ulint
|
||||
mach_read_ulint(
|
||||
/*============*/
|
||||
const byte* ptr, /*!< in: pointer from where to read */
|
||||
ulint type) /*!< in: 1,2 or 4 bytes */
|
||||
{
|
||||
switch (type) {
|
||||
case 1:
|
||||
return(mach_read_from_1(ptr));
|
||||
case 2:
|
||||
return(mach_read_from_2(ptr));
|
||||
case 4:
|
||||
return(mach_read_from_4(ptr));
|
||||
default:
|
||||
ut_error;
|
||||
}
|
||||
|
||||
return(0);
|
||||
}
|
||||
|
||||
#endif /* !UNIV_HOTBACKUP */
|
||||
#endif /* !UNIV_INNOCHECKSUM */
|
||||
150
storage/innobase/include/mem0dbg.h
Normal file
150
storage/innobase/include/mem0dbg.h
Normal file
|
|
@ -0,0 +1,150 @@
|
|||
/*****************************************************************************
|
||||
|
||||
Copyright (c) 1994, 2010, Oracle and/or its affiliates. All Rights Reserved.
|
||||
|
||||
This program is free software; you can redistribute it and/or modify it under
|
||||
the terms of the GNU General Public License as published by the Free Software
|
||||
Foundation; version 2 of the License.
|
||||
|
||||
This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
|
||||
FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License along with
|
||||
this program; if not, write to the Free Software Foundation, Inc.,
|
||||
51 Franklin Street, Suite 500, Boston, MA 02110-1335 USA
|
||||
|
||||
*****************************************************************************/
|
||||
|
||||
/**************************************************//**
|
||||
@file include/mem0dbg.h
|
||||
The memory management: the debug code. This is not a compilation module,
|
||||
but is included in mem0mem.* !
|
||||
|
||||
Created 6/9/1994 Heikki Tuuri
|
||||
*******************************************************/
|
||||
|
||||
/* In the debug version each allocated field is surrounded with
|
||||
check fields whose sizes are given below */
|
||||
|
||||
#ifdef UNIV_MEM_DEBUG
|
||||
# ifndef UNIV_HOTBACKUP
|
||||
/* The mutex which protects in the debug version the hash table
|
||||
containing the list of live memory heaps, and also the global
|
||||
variables in mem0dbg.cc. */
|
||||
extern ib_mutex_t mem_hash_mutex;
|
||||
# endif /* !UNIV_HOTBACKUP */
|
||||
|
||||
#define MEM_FIELD_HEADER_SIZE ut_calc_align(2 * sizeof(ulint),\
|
||||
UNIV_MEM_ALIGNMENT)
|
||||
#define MEM_FIELD_TRAILER_SIZE sizeof(ulint)
|
||||
#else
|
||||
#define MEM_FIELD_HEADER_SIZE 0
|
||||
#endif
|
||||
|
||||
|
||||
/* Space needed when allocating for a user a field of
|
||||
length N. The space is allocated only in multiples of
|
||||
UNIV_MEM_ALIGNMENT. In the debug version there are also
|
||||
check fields at the both ends of the field. */
|
||||
#ifdef UNIV_MEM_DEBUG
|
||||
#define MEM_SPACE_NEEDED(N) ut_calc_align((N) + MEM_FIELD_HEADER_SIZE\
|
||||
+ MEM_FIELD_TRAILER_SIZE, UNIV_MEM_ALIGNMENT)
|
||||
#else
|
||||
#define MEM_SPACE_NEEDED(N) ut_calc_align((N), UNIV_MEM_ALIGNMENT)
|
||||
#endif
|
||||
|
||||
#if defined UNIV_MEM_DEBUG || defined UNIV_DEBUG
|
||||
/***************************************************************//**
|
||||
Checks a memory heap for consistency and prints the contents if requested.
|
||||
Outputs the sum of sizes of buffers given to the user (only in
|
||||
the debug version), the physical size of the heap and the number of
|
||||
blocks in the heap. In case of error returns 0 as sizes and number
|
||||
of blocks. */
|
||||
UNIV_INTERN
|
||||
void
|
||||
mem_heap_validate_or_print(
|
||||
/*=======================*/
|
||||
mem_heap_t* heap, /*!< in: memory heap */
|
||||
byte* top, /*!< in: calculate and validate only until
|
||||
this top pointer in the heap is reached,
|
||||
if this pointer is NULL, ignored */
|
||||
ibool print, /*!< in: if TRUE, prints the contents
|
||||
of the heap; works only in
|
||||
the debug version */
|
||||
ibool* error, /*!< out: TRUE if error */
|
||||
ulint* us_size,/*!< out: allocated memory
|
||||
(for the user) in the heap,
|
||||
if a NULL pointer is passed as this
|
||||
argument, it is ignored; in the
|
||||
non-debug version this is always -1 */
|
||||
ulint* ph_size,/*!< out: physical size of the heap,
|
||||
if a NULL pointer is passed as this
|
||||
argument, it is ignored */
|
||||
ulint* n_blocks); /*!< out: number of blocks in the heap,
|
||||
if a NULL pointer is passed as this
|
||||
argument, it is ignored */
|
||||
/**************************************************************//**
|
||||
Validates the contents of a memory heap.
|
||||
@return TRUE if ok */
|
||||
UNIV_INTERN
|
||||
ibool
|
||||
mem_heap_validate(
|
||||
/*==============*/
|
||||
mem_heap_t* heap); /*!< in: memory heap */
|
||||
#endif /* UNIV_MEM_DEBUG || UNIV_DEBUG */
|
||||
#ifdef UNIV_DEBUG
|
||||
/**************************************************************//**
|
||||
Checks that an object is a memory heap (or a block of it)
|
||||
@return TRUE if ok */
|
||||
UNIV_INTERN
|
||||
ibool
|
||||
mem_heap_check(
|
||||
/*===========*/
|
||||
mem_heap_t* heap); /*!< in: memory heap */
|
||||
#endif /* UNIV_DEBUG */
|
||||
#ifdef UNIV_MEM_DEBUG
|
||||
/*****************************************************************//**
|
||||
TRUE if no memory is currently allocated.
|
||||
@return TRUE if no heaps exist */
|
||||
UNIV_INTERN
|
||||
ibool
|
||||
mem_all_freed(void);
|
||||
/*===============*/
|
||||
/*****************************************************************//**
|
||||
Validates the dynamic memory
|
||||
@return TRUE if error */
|
||||
UNIV_INTERN
|
||||
ibool
|
||||
mem_validate_no_assert(void);
|
||||
/*=========================*/
|
||||
/************************************************************//**
|
||||
Validates the dynamic memory
|
||||
@return TRUE if ok */
|
||||
UNIV_INTERN
|
||||
ibool
|
||||
mem_validate(void);
|
||||
/*===============*/
|
||||
#endif /* UNIV_MEM_DEBUG */
|
||||
/************************************************************//**
|
||||
Tries to find neigboring memory allocation blocks and dumps to stderr
|
||||
the neighborhood of a given pointer. */
|
||||
UNIV_INTERN
|
||||
void
|
||||
mem_analyze_corruption(
|
||||
/*===================*/
|
||||
void* ptr); /*!< in: pointer to place of possible corruption */
|
||||
/*****************************************************************//**
|
||||
Prints information of dynamic memory usage and currently allocated memory
|
||||
heaps or buffers. Can only be used in the debug version. */
|
||||
UNIV_INTERN
|
||||
void
|
||||
mem_print_info(void);
|
||||
/*================*/
|
||||
/*****************************************************************//**
|
||||
Prints information of dynamic memory usage and currently allocated memory
|
||||
heaps or buffers since the last ..._print_info or..._print_new_info. */
|
||||
UNIV_INTERN
|
||||
void
|
||||
mem_print_new_info(void);
|
||||
/*====================*/
|
||||
109
storage/innobase/include/mem0dbg.ic
Normal file
109
storage/innobase/include/mem0dbg.ic
Normal file
|
|
@ -0,0 +1,109 @@
|
|||
/*****************************************************************************
|
||||
|
||||
Copyright (c) 1994, 2010, Oracle and/or its affiliates. All Rights Reserved.
|
||||
|
||||
This program is free software; you can redistribute it and/or modify it under
|
||||
the terms of the GNU General Public License as published by the Free Software
|
||||
Foundation; version 2 of the License.
|
||||
|
||||
This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
|
||||
FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License along with
|
||||
this program; if not, write to the Free Software Foundation, Inc.,
|
||||
51 Franklin Street, Suite 500, Boston, MA 02110-1335 USA
|
||||
|
||||
*****************************************************************************/
|
||||
|
||||
/********************************************************************//**
|
||||
@file include/mem0dbg.ic
|
||||
The memory management: the debug code. This is not an independent
|
||||
compilation module but is included in mem0mem.*.
|
||||
|
||||
Created 6/8/1994 Heikki Tuuri
|
||||
*************************************************************************/
|
||||
|
||||
#ifdef UNIV_MEM_DEBUG
|
||||
extern ulint mem_current_allocated_memory;
|
||||
|
||||
/******************************************************************//**
|
||||
Initializes an allocated memory field in the debug version. */
|
||||
UNIV_INTERN
|
||||
void
|
||||
mem_field_init(
|
||||
/*===========*/
|
||||
byte* buf, /*!< in: memory field */
|
||||
ulint n); /*!< in: how many bytes the user requested */
|
||||
/******************************************************************//**
|
||||
Erases an allocated memory field in the debug version. */
|
||||
UNIV_INTERN
|
||||
void
|
||||
mem_field_erase(
|
||||
/*============*/
|
||||
byte* buf, /*!< in: memory field */
|
||||
ulint n); /*!< in: how many bytes the user requested */
|
||||
/***************************************************************//**
|
||||
Initializes a buffer to a random combination of hex BA and BE.
|
||||
Used to initialize allocated memory. */
|
||||
UNIV_INTERN
|
||||
void
|
||||
mem_init_buf(
|
||||
/*=========*/
|
||||
byte* buf, /*!< in: pointer to buffer */
|
||||
ulint n); /*!< in: length of buffer */
|
||||
/***************************************************************//**
|
||||
Initializes a buffer to a random combination of hex DE and AD.
|
||||
Used to erase freed memory. */
|
||||
UNIV_INTERN
|
||||
void
|
||||
mem_erase_buf(
|
||||
/*==========*/
|
||||
byte* buf, /*!< in: pointer to buffer */
|
||||
ulint n); /*!< in: length of buffer */
|
||||
/***************************************************************//**
|
||||
Inserts a created memory heap to the hash table of
|
||||
current allocated memory heaps.
|
||||
Initializes the hash table when first called. */
|
||||
UNIV_INTERN
|
||||
void
|
||||
mem_hash_insert(
|
||||
/*============*/
|
||||
mem_heap_t* heap, /*!< in: the created heap */
|
||||
const char* file_name, /*!< in: file name of creation */
|
||||
ulint line); /*!< in: line where created */
|
||||
/***************************************************************//**
|
||||
Removes a memory heap (which is going to be freed by the caller)
|
||||
from the list of live memory heaps. Returns the size of the heap
|
||||
in terms of how much memory in bytes was allocated for the user of
|
||||
the heap (not the total space occupied by the heap).
|
||||
Also validates the heap.
|
||||
NOTE: This function does not free the storage occupied by the
|
||||
heap itself, only the node in the list of heaps. */
|
||||
UNIV_INTERN
|
||||
void
|
||||
mem_hash_remove(
|
||||
/*============*/
|
||||
mem_heap_t* heap, /*!< in: the heap to be freed */
|
||||
const char* file_name, /*!< in: file name of freeing */
|
||||
ulint line); /*!< in: line where freed */
|
||||
|
||||
|
||||
void
|
||||
mem_field_header_set_len(byte* field, ulint len);
|
||||
|
||||
ulint
|
||||
mem_field_header_get_len(byte* field);
|
||||
|
||||
void
|
||||
mem_field_header_set_check(byte* field, ulint check);
|
||||
|
||||
ulint
|
||||
mem_field_header_get_check(byte* field);
|
||||
|
||||
void
|
||||
mem_field_trailer_set_check(byte* field, ulint check);
|
||||
|
||||
ulint
|
||||
mem_field_trailer_get_check(byte* field);
|
||||
#endif /* UNIV_MEM_DEBUG */
|
||||
425
storage/innobase/include/mem0mem.h
Normal file
425
storage/innobase/include/mem0mem.h
Normal file
|
|
@ -0,0 +1,425 @@
|
|||
/*****************************************************************************
|
||||
|
||||
Copyright (c) 1994, 2010, Oracle and/or its affiliates. All Rights Reserved.
|
||||
|
||||
This program is free software; you can redistribute it and/or modify it under
|
||||
the terms of the GNU General Public License as published by the Free Software
|
||||
Foundation; version 2 of the License.
|
||||
|
||||
This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
|
||||
FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License along with
|
||||
this program; if not, write to the Free Software Foundation, Inc.,
|
||||
51 Franklin Street, Suite 500, Boston, MA 02110-1335 USA
|
||||
|
||||
*****************************************************************************/
|
||||
|
||||
/**************************************************//**
|
||||
@file include/mem0mem.h
|
||||
The memory management
|
||||
|
||||
Created 6/9/1994 Heikki Tuuri
|
||||
*******************************************************/
|
||||
|
||||
#ifndef mem0mem_h
|
||||
#define mem0mem_h
|
||||
|
||||
#include "univ.i"
|
||||
#include "ut0mem.h"
|
||||
#include "ut0byte.h"
|
||||
#include "ut0rnd.h"
|
||||
#ifndef UNIV_HOTBACKUP
|
||||
# include "sync0sync.h"
|
||||
#endif /* UNIV_HOTBACKUP */
|
||||
#include "ut0lst.h"
|
||||
#include "mach0data.h"
|
||||
|
||||
/* -------------------- MEMORY HEAPS ----------------------------- */
|
||||
|
||||
/* A block of a memory heap consists of the info structure
|
||||
followed by an area of memory */
|
||||
typedef struct mem_block_info_t mem_block_t;
|
||||
|
||||
/* A memory heap is a nonempty linear list of memory blocks */
|
||||
typedef mem_block_t mem_heap_t;
|
||||
|
||||
/* Types of allocation for memory heaps: DYNAMIC means allocation from the
|
||||
dynamic memory pool of the C compiler, BUFFER means allocation from the
|
||||
buffer pool; the latter method is used for very big heaps */
|
||||
|
||||
#define MEM_HEAP_DYNAMIC 0 /* the most common type */
|
||||
#define MEM_HEAP_BUFFER 1
|
||||
#define MEM_HEAP_BTR_SEARCH 2 /* this flag can optionally be
|
||||
ORed to MEM_HEAP_BUFFER, in which
|
||||
case heap->free_block is used in
|
||||
some cases for memory allocations,
|
||||
and if it's NULL, the memory
|
||||
allocation functions can return
|
||||
NULL. */
|
||||
|
||||
/* Different type of heaps in terms of which datastructure is using them */
|
||||
#define MEM_HEAP_FOR_BTR_SEARCH (MEM_HEAP_BTR_SEARCH | MEM_HEAP_BUFFER)
|
||||
#define MEM_HEAP_FOR_PAGE_HASH (MEM_HEAP_DYNAMIC)
|
||||
#define MEM_HEAP_FOR_RECV_SYS (MEM_HEAP_BUFFER)
|
||||
#define MEM_HEAP_FOR_LOCK_HEAP (MEM_HEAP_BUFFER)
|
||||
|
||||
/* The following start size is used for the first block in the memory heap if
|
||||
the size is not specified, i.e., 0 is given as the parameter in the call of
|
||||
create. The standard size is the maximum (payload) size of the blocks used for
|
||||
allocations of small buffers. */
|
||||
|
||||
#define MEM_BLOCK_START_SIZE 64
|
||||
#define MEM_BLOCK_STANDARD_SIZE \
|
||||
(UNIV_PAGE_SIZE >= 16384 ? 8000 : MEM_MAX_ALLOC_IN_BUF)
|
||||
|
||||
/* If a memory heap is allowed to grow into the buffer pool, the following
|
||||
is the maximum size for a single allocated buffer: */
|
||||
#define MEM_MAX_ALLOC_IN_BUF (UNIV_PAGE_SIZE - 200)
|
||||
|
||||
/******************************************************************//**
|
||||
Initializes the memory system. */
|
||||
UNIV_INTERN
|
||||
void
|
||||
mem_init(
|
||||
/*=====*/
|
||||
ulint size); /*!< in: common pool size in bytes */
|
||||
/******************************************************************//**
|
||||
Closes the memory system. */
|
||||
UNIV_INTERN
|
||||
void
|
||||
mem_close(void);
|
||||
/*===========*/
|
||||
|
||||
#ifdef UNIV_DEBUG
|
||||
/**************************************************************//**
|
||||
Use this macro instead of the corresponding function! Macro for memory
|
||||
heap creation. */
|
||||
|
||||
# define mem_heap_create(N) mem_heap_create_func( \
|
||||
(N), __FILE__, __LINE__, MEM_HEAP_DYNAMIC)
|
||||
/**************************************************************//**
|
||||
Use this macro instead of the corresponding function! Macro for memory
|
||||
heap creation. */
|
||||
|
||||
# define mem_heap_create_typed(N, T) mem_heap_create_func( \
|
||||
(N), __FILE__, __LINE__, (T))
|
||||
|
||||
#else /* UNIV_DEBUG */
|
||||
/**************************************************************//**
|
||||
Use this macro instead of the corresponding function! Macro for memory
|
||||
heap creation. */
|
||||
|
||||
# define mem_heap_create(N) mem_heap_create_func( \
|
||||
(N), MEM_HEAP_DYNAMIC)
|
||||
/**************************************************************//**
|
||||
Use this macro instead of the corresponding function! Macro for memory
|
||||
heap creation. */
|
||||
|
||||
# define mem_heap_create_typed(N, T) mem_heap_create_func( \
|
||||
(N), (T))
|
||||
|
||||
#endif /* UNIV_DEBUG */
|
||||
/**************************************************************//**
|
||||
Use this macro instead of the corresponding function! Macro for memory
|
||||
heap freeing. */
|
||||
|
||||
#define mem_heap_free(heap) mem_heap_free_func(\
|
||||
(heap), __FILE__, __LINE__)
|
||||
/*****************************************************************//**
|
||||
NOTE: Use the corresponding macros instead of this function. Creates a
|
||||
memory heap. For debugging purposes, takes also the file name and line as
|
||||
arguments.
|
||||
@return own: memory heap, NULL if did not succeed (only possible for
|
||||
MEM_HEAP_BTR_SEARCH type heaps) */
|
||||
UNIV_INLINE
|
||||
mem_heap_t*
|
||||
mem_heap_create_func(
|
||||
/*=================*/
|
||||
ulint n, /*!< in: desired start block size,
|
||||
this means that a single user buffer
|
||||
of size n will fit in the block,
|
||||
0 creates a default size block */
|
||||
#ifdef UNIV_DEBUG
|
||||
const char* file_name, /*!< in: file name where created */
|
||||
ulint line, /*!< in: line where created */
|
||||
#endif /* UNIV_DEBUG */
|
||||
ulint type); /*!< in: heap type */
|
||||
/*****************************************************************//**
|
||||
NOTE: Use the corresponding macro instead of this function. Frees the space
|
||||
occupied by a memory heap. In the debug version erases the heap memory
|
||||
blocks. */
|
||||
UNIV_INLINE
|
||||
void
|
||||
mem_heap_free_func(
|
||||
/*===============*/
|
||||
mem_heap_t* heap, /*!< in, own: heap to be freed */
|
||||
const char* file_name, /*!< in: file name where freed */
|
||||
ulint line); /*!< in: line where freed */
|
||||
/***************************************************************//**
|
||||
Allocates and zero-fills n bytes of memory from a memory heap.
|
||||
@return allocated, zero-filled storage */
|
||||
UNIV_INLINE
|
||||
void*
|
||||
mem_heap_zalloc(
|
||||
/*============*/
|
||||
mem_heap_t* heap, /*!< in: memory heap */
|
||||
ulint n); /*!< in: number of bytes; if the heap is allowed
|
||||
to grow into the buffer pool, this must be
|
||||
<= MEM_MAX_ALLOC_IN_BUF */
|
||||
/***************************************************************//**
|
||||
Allocates n bytes of memory from a memory heap.
|
||||
@return allocated storage, NULL if did not succeed (only possible for
|
||||
MEM_HEAP_BTR_SEARCH type heaps) */
|
||||
UNIV_INLINE
|
||||
void*
|
||||
mem_heap_alloc(
|
||||
/*===========*/
|
||||
mem_heap_t* heap, /*!< in: memory heap */
|
||||
ulint n); /*!< in: number of bytes; if the heap is allowed
|
||||
to grow into the buffer pool, this must be
|
||||
<= MEM_MAX_ALLOC_IN_BUF */
|
||||
/*****************************************************************//**
|
||||
Returns a pointer to the heap top.
|
||||
@return pointer to the heap top */
|
||||
UNIV_INLINE
|
||||
byte*
|
||||
mem_heap_get_heap_top(
|
||||
/*==================*/
|
||||
mem_heap_t* heap); /*!< in: memory heap */
|
||||
/*****************************************************************//**
|
||||
Frees the space in a memory heap exceeding the pointer given. The
|
||||
pointer must have been acquired from mem_heap_get_heap_top. The first
|
||||
memory block of the heap is not freed. */
|
||||
UNIV_INLINE
|
||||
void
|
||||
mem_heap_free_heap_top(
|
||||
/*===================*/
|
||||
mem_heap_t* heap, /*!< in: heap from which to free */
|
||||
byte* old_top);/*!< in: pointer to old top of heap */
|
||||
/*****************************************************************//**
|
||||
Empties a memory heap. The first memory block of the heap is not freed. */
|
||||
UNIV_INLINE
|
||||
void
|
||||
mem_heap_empty(
|
||||
/*===========*/
|
||||
mem_heap_t* heap); /*!< in: heap to empty */
|
||||
/*****************************************************************//**
|
||||
Returns a pointer to the topmost element in a memory heap.
|
||||
The size of the element must be given.
|
||||
@return pointer to the topmost element */
|
||||
UNIV_INLINE
|
||||
void*
|
||||
mem_heap_get_top(
|
||||
/*=============*/
|
||||
mem_heap_t* heap, /*!< in: memory heap */
|
||||
ulint n); /*!< in: size of the topmost element */
|
||||
/*****************************************************************//**
|
||||
Frees the topmost element in a memory heap.
|
||||
The size of the element must be given. */
|
||||
UNIV_INLINE
|
||||
void
|
||||
mem_heap_free_top(
|
||||
/*==============*/
|
||||
mem_heap_t* heap, /*!< in: memory heap */
|
||||
ulint n); /*!< in: size of the topmost element */
|
||||
/*****************************************************************//**
|
||||
Returns the space in bytes occupied by a memory heap. */
|
||||
UNIV_INLINE
|
||||
ulint
|
||||
mem_heap_get_size(
|
||||
/*==============*/
|
||||
mem_heap_t* heap); /*!< in: heap */
|
||||
/**************************************************************//**
|
||||
Use this macro instead of the corresponding function!
|
||||
Macro for memory buffer allocation */
|
||||
|
||||
#define mem_zalloc(N) memset(mem_alloc(N), 0, (N))
|
||||
|
||||
#ifdef UNIV_DEBUG
|
||||
#define mem_alloc(N) mem_alloc_func((N), __FILE__, __LINE__, NULL)
|
||||
#define mem_alloc2(N,S) mem_alloc_func((N), __FILE__, __LINE__, (S))
|
||||
#else /* UNIV_DEBUG */
|
||||
#define mem_alloc(N) mem_alloc_func((N), NULL)
|
||||
#define mem_alloc2(N,S) mem_alloc_func((N), (S))
|
||||
#endif /* UNIV_DEBUG */
|
||||
|
||||
/***************************************************************//**
|
||||
NOTE: Use the corresponding macro instead of this function.
|
||||
Allocates a single buffer of memory from the dynamic memory of
|
||||
the C compiler. Is like malloc of C. The buffer must be freed
|
||||
with mem_free.
|
||||
@return own: free storage */
|
||||
UNIV_INLINE
|
||||
void*
|
||||
mem_alloc_func(
|
||||
/*===========*/
|
||||
ulint n, /*!< in: requested size in bytes */
|
||||
#ifdef UNIV_DEBUG
|
||||
const char* file_name, /*!< in: file name where created */
|
||||
ulint line, /*!< in: line where created */
|
||||
#endif /* UNIV_DEBUG */
|
||||
ulint* size); /*!< out: allocated size in bytes,
|
||||
or NULL */
|
||||
|
||||
/**************************************************************//**
|
||||
Use this macro instead of the corresponding function!
|
||||
Macro for memory buffer freeing */
|
||||
|
||||
#define mem_free(PTR) mem_free_func((PTR), __FILE__, __LINE__)
|
||||
/***************************************************************//**
|
||||
NOTE: Use the corresponding macro instead of this function.
|
||||
Frees a single buffer of storage from
|
||||
the dynamic memory of C compiler. Similar to free of C. */
|
||||
UNIV_INLINE
|
||||
void
|
||||
mem_free_func(
|
||||
/*==========*/
|
||||
void* ptr, /*!< in, own: buffer to be freed */
|
||||
const char* file_name, /*!< in: file name where created */
|
||||
ulint line); /*!< in: line where created */
|
||||
|
||||
/**********************************************************************//**
|
||||
Duplicates a NUL-terminated string.
|
||||
@return own: a copy of the string, must be deallocated with mem_free */
|
||||
UNIV_INLINE
|
||||
char*
|
||||
mem_strdup(
|
||||
/*=======*/
|
||||
const char* str); /*!< in: string to be copied */
|
||||
/**********************************************************************//**
|
||||
Makes a NUL-terminated copy of a nonterminated string.
|
||||
@return own: a copy of the string, must be deallocated with mem_free */
|
||||
UNIV_INLINE
|
||||
char*
|
||||
mem_strdupl(
|
||||
/*========*/
|
||||
const char* str, /*!< in: string to be copied */
|
||||
ulint len); /*!< in: length of str, in bytes */
|
||||
|
||||
/**********************************************************************//**
|
||||
Duplicates a NUL-terminated string, allocated from a memory heap.
|
||||
@return own: a copy of the string */
|
||||
UNIV_INTERN
|
||||
char*
|
||||
mem_heap_strdup(
|
||||
/*============*/
|
||||
mem_heap_t* heap, /*!< in: memory heap where string is allocated */
|
||||
const char* str); /*!< in: string to be copied */
|
||||
/**********************************************************************//**
|
||||
Makes a NUL-terminated copy of a nonterminated string,
|
||||
allocated from a memory heap.
|
||||
@return own: a copy of the string */
|
||||
UNIV_INLINE
|
||||
char*
|
||||
mem_heap_strdupl(
|
||||
/*=============*/
|
||||
mem_heap_t* heap, /*!< in: memory heap where string is allocated */
|
||||
const char* str, /*!< in: string to be copied */
|
||||
ulint len); /*!< in: length of str, in bytes */
|
||||
|
||||
/**********************************************************************//**
|
||||
Concatenate two strings and return the result, using a memory heap.
|
||||
@return own: the result */
|
||||
UNIV_INTERN
|
||||
char*
|
||||
mem_heap_strcat(
|
||||
/*============*/
|
||||
mem_heap_t* heap, /*!< in: memory heap where string is allocated */
|
||||
const char* s1, /*!< in: string 1 */
|
||||
const char* s2); /*!< in: string 2 */
|
||||
|
||||
/**********************************************************************//**
|
||||
Duplicate a block of data, allocated from a memory heap.
|
||||
@return own: a copy of the data */
|
||||
UNIV_INTERN
|
||||
void*
|
||||
mem_heap_dup(
|
||||
/*=========*/
|
||||
mem_heap_t* heap, /*!< in: memory heap where copy is allocated */
|
||||
const void* data, /*!< in: data to be copied */
|
||||
ulint len); /*!< in: length of data, in bytes */
|
||||
|
||||
/****************************************************************//**
|
||||
A simple sprintf replacement that dynamically allocates the space for the
|
||||
formatted string from the given heap. This supports a very limited set of
|
||||
the printf syntax: types 's' and 'u' and length modifier 'l' (which is
|
||||
required for the 'u' type).
|
||||
@return heap-allocated formatted string */
|
||||
UNIV_INTERN
|
||||
char*
|
||||
mem_heap_printf(
|
||||
/*============*/
|
||||
mem_heap_t* heap, /*!< in: memory heap */
|
||||
const char* format, /*!< in: format string */
|
||||
...) __attribute__ ((format (printf, 2, 3)));
|
||||
|
||||
#ifdef MEM_PERIODIC_CHECK
|
||||
/******************************************************************//**
|
||||
Goes through the list of all allocated mem blocks, checks their magic
|
||||
numbers, and reports possible corruption. */
|
||||
UNIV_INTERN
|
||||
void
|
||||
mem_validate_all_blocks(void);
|
||||
/*=========================*/
|
||||
#endif
|
||||
|
||||
/*#######################################################################*/
|
||||
|
||||
/** The info structure stored at the beginning of a heap block */
|
||||
struct mem_block_info_t {
|
||||
ulint magic_n;/* magic number for debugging */
|
||||
#ifdef UNIV_DEBUG
|
||||
char file_name[8];/* file name where the mem heap was created */
|
||||
ulint line; /*!< line number where the mem heap was created */
|
||||
#endif /* UNIV_DEBUG */
|
||||
UT_LIST_BASE_NODE_T(mem_block_t) base; /* In the first block in the
|
||||
the list this is the base node of the list of blocks;
|
||||
in subsequent blocks this is undefined */
|
||||
UT_LIST_NODE_T(mem_block_t) list; /* This contains pointers to next
|
||||
and prev in the list. The first block allocated
|
||||
to the heap is also the first block in this list,
|
||||
though it also contains the base node of the list. */
|
||||
ulint len; /*!< physical length of this block in bytes */
|
||||
ulint total_size; /*!< physical length in bytes of all blocks
|
||||
in the heap. This is defined only in the base
|
||||
node and is set to ULINT_UNDEFINED in others. */
|
||||
ulint type; /*!< type of heap: MEM_HEAP_DYNAMIC, or
|
||||
MEM_HEAP_BUF possibly ORed to MEM_HEAP_BTR_SEARCH */
|
||||
ulint free; /*!< offset in bytes of the first free position for
|
||||
user data in the block */
|
||||
ulint start; /*!< the value of the struct field 'free' at the
|
||||
creation of the block */
|
||||
#ifndef UNIV_HOTBACKUP
|
||||
void* free_block;
|
||||
/* if the MEM_HEAP_BTR_SEARCH bit is set in type,
|
||||
and this is the heap root, this can contain an
|
||||
allocated buffer frame, which can be appended as a
|
||||
free block to the heap, if we need more space;
|
||||
otherwise, this is NULL */
|
||||
void* buf_block;
|
||||
/* if this block has been allocated from the buffer
|
||||
pool, this contains the buf_block_t handle;
|
||||
otherwise, this is NULL */
|
||||
#endif /* !UNIV_HOTBACKUP */
|
||||
#ifdef MEM_PERIODIC_CHECK
|
||||
UT_LIST_NODE_T(mem_block_t) mem_block_list;
|
||||
/* List of all mem blocks allocated; protected
|
||||
by the mem_comm_pool mutex */
|
||||
#endif
|
||||
};
|
||||
|
||||
#define MEM_BLOCK_MAGIC_N 764741555
|
||||
#define MEM_FREED_BLOCK_MAGIC_N 547711122
|
||||
|
||||
/* Header size for a memory heap block */
|
||||
#define MEM_BLOCK_HEADER_SIZE ut_calc_align(sizeof(mem_block_info_t),\
|
||||
UNIV_MEM_ALIGNMENT)
|
||||
#include "mem0dbg.h"
|
||||
|
||||
#ifndef UNIV_NONINL
|
||||
#include "mem0mem.ic"
|
||||
#endif
|
||||
|
||||
#endif
|
||||
649
storage/innobase/include/mem0mem.ic
Normal file
649
storage/innobase/include/mem0mem.ic
Normal file
|
|
@ -0,0 +1,649 @@
|
|||
/*****************************************************************************
|
||||
|
||||
Copyright (c) 1994, 2010, Oracle and/or its affiliates. All Rights Reserved.
|
||||
|
||||
This program is free software; you can redistribute it and/or modify it under
|
||||
the terms of the GNU General Public License as published by the Free Software
|
||||
Foundation; version 2 of the License.
|
||||
|
||||
This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
|
||||
FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License along with
|
||||
this program; if not, write to the Free Software Foundation, Inc.,
|
||||
51 Franklin Street, Suite 500, Boston, MA 02110-1335 USA
|
||||
|
||||
*****************************************************************************/
|
||||
|
||||
/********************************************************************//**
|
||||
@file include/mem0mem.ic
|
||||
The memory management
|
||||
|
||||
Created 6/8/1994 Heikki Tuuri
|
||||
*************************************************************************/
|
||||
|
||||
#include "mem0dbg.ic"
|
||||
#ifndef UNIV_HOTBACKUP
|
||||
# include "mem0pool.h"
|
||||
#endif /* !UNIV_HOTBACKUP */
|
||||
|
||||
#ifdef UNIV_DEBUG
|
||||
# define mem_heap_create_block(heap, n, type, file_name, line) \
|
||||
mem_heap_create_block_func(heap, n, file_name, line, type)
|
||||
# define mem_heap_create_at(N, file_name, line) \
|
||||
mem_heap_create_func(N, file_name, line, MEM_HEAP_DYNAMIC)
|
||||
#else /* UNIV_DEBUG */
|
||||
# define mem_heap_create_block(heap, n, type, file_name, line) \
|
||||
mem_heap_create_block_func(heap, n, type)
|
||||
# define mem_heap_create_at(N, file_name, line) \
|
||||
mem_heap_create_func(N, MEM_HEAP_DYNAMIC)
|
||||
#endif /* UNIV_DEBUG */
|
||||
/***************************************************************//**
|
||||
Creates a memory heap block where data can be allocated.
|
||||
@return own: memory heap block, NULL if did not succeed (only possible
|
||||
for MEM_HEAP_BTR_SEARCH type heaps) */
|
||||
UNIV_INTERN
|
||||
mem_block_t*
|
||||
mem_heap_create_block_func(
|
||||
/*=======================*/
|
||||
mem_heap_t* heap, /*!< in: memory heap or NULL if first block
|
||||
should be created */
|
||||
ulint n, /*!< in: number of bytes needed for user data */
|
||||
#ifdef UNIV_DEBUG
|
||||
const char* file_name,/*!< in: file name where created */
|
||||
ulint line, /*!< in: line where created */
|
||||
#endif /* UNIV_DEBUG */
|
||||
ulint type); /*!< in: type of heap: MEM_HEAP_DYNAMIC or
|
||||
MEM_HEAP_BUFFER */
|
||||
/******************************************************************//**
|
||||
Frees a block from a memory heap. */
|
||||
UNIV_INTERN
|
||||
void
|
||||
mem_heap_block_free(
|
||||
/*================*/
|
||||
mem_heap_t* heap, /*!< in: heap */
|
||||
mem_block_t* block); /*!< in: block to free */
|
||||
#ifndef UNIV_HOTBACKUP
|
||||
/******************************************************************//**
|
||||
Frees the free_block field from a memory heap. */
|
||||
UNIV_INTERN
|
||||
void
|
||||
mem_heap_free_block_free(
|
||||
/*=====================*/
|
||||
mem_heap_t* heap); /*!< in: heap */
|
||||
#endif /* !UNIV_HOTBACKUP */
|
||||
/***************************************************************//**
|
||||
Adds a new block to a memory heap.
|
||||
@return created block, NULL if did not succeed (only possible for
|
||||
MEM_HEAP_BTR_SEARCH type heaps) */
|
||||
UNIV_INTERN
|
||||
mem_block_t*
|
||||
mem_heap_add_block(
|
||||
/*===============*/
|
||||
mem_heap_t* heap, /*!< in: memory heap */
|
||||
ulint n); /*!< in: number of bytes user needs */
|
||||
|
||||
UNIV_INLINE
|
||||
void
|
||||
mem_block_set_len(mem_block_t* block, ulint len)
|
||||
{
|
||||
ut_ad(len > 0);
|
||||
|
||||
block->len = len;
|
||||
}
|
||||
|
||||
UNIV_INLINE
|
||||
ulint
|
||||
mem_block_get_len(mem_block_t* block)
|
||||
{
|
||||
return(block->len);
|
||||
}
|
||||
|
||||
UNIV_INLINE
|
||||
void
|
||||
mem_block_set_type(mem_block_t* block, ulint type)
|
||||
{
|
||||
ut_ad((type == MEM_HEAP_DYNAMIC) || (type == MEM_HEAP_BUFFER)
|
||||
|| (type == MEM_HEAP_BUFFER + MEM_HEAP_BTR_SEARCH));
|
||||
|
||||
block->type = type;
|
||||
}
|
||||
|
||||
UNIV_INLINE
|
||||
ulint
|
||||
mem_block_get_type(mem_block_t* block)
|
||||
{
|
||||
return(block->type);
|
||||
}
|
||||
|
||||
UNIV_INLINE
|
||||
void
|
||||
mem_block_set_free(mem_block_t* block, ulint free)
|
||||
{
|
||||
ut_ad(free > 0);
|
||||
ut_ad(free <= mem_block_get_len(block));
|
||||
|
||||
block->free = free;
|
||||
}
|
||||
|
||||
UNIV_INLINE
|
||||
ulint
|
||||
mem_block_get_free(mem_block_t* block)
|
||||
{
|
||||
return(block->free);
|
||||
}
|
||||
|
||||
UNIV_INLINE
|
||||
void
|
||||
mem_block_set_start(mem_block_t* block, ulint start)
|
||||
{
|
||||
ut_ad(start > 0);
|
||||
|
||||
block->start = start;
|
||||
}
|
||||
|
||||
UNIV_INLINE
|
||||
ulint
|
||||
mem_block_get_start(mem_block_t* block)
|
||||
{
|
||||
return(block->start);
|
||||
}
|
||||
|
||||
/***************************************************************//**
|
||||
Allocates and zero-fills n bytes of memory from a memory heap.
|
||||
@return allocated, zero-filled storage */
|
||||
UNIV_INLINE
|
||||
void*
|
||||
mem_heap_zalloc(
|
||||
/*============*/
|
||||
mem_heap_t* heap, /*!< in: memory heap */
|
||||
ulint n) /*!< in: number of bytes; if the heap is allowed
|
||||
to grow into the buffer pool, this must be
|
||||
<= MEM_MAX_ALLOC_IN_BUF */
|
||||
{
|
||||
ut_ad(heap);
|
||||
ut_ad(!(heap->type & MEM_HEAP_BTR_SEARCH));
|
||||
return(memset(mem_heap_alloc(heap, n), 0, n));
|
||||
}
|
||||
|
||||
/***************************************************************//**
|
||||
Allocates n bytes of memory from a memory heap.
|
||||
@return allocated storage, NULL if did not succeed (only possible for
|
||||
MEM_HEAP_BTR_SEARCH type heaps) */
|
||||
UNIV_INLINE
|
||||
void*
|
||||
mem_heap_alloc(
|
||||
/*===========*/
|
||||
mem_heap_t* heap, /*!< in: memory heap */
|
||||
ulint n) /*!< in: number of bytes; if the heap is allowed
|
||||
to grow into the buffer pool, this must be
|
||||
<= MEM_MAX_ALLOC_IN_BUF */
|
||||
{
|
||||
mem_block_t* block;
|
||||
void* buf;
|
||||
ulint free;
|
||||
|
||||
ut_ad(mem_heap_check(heap));
|
||||
|
||||
block = UT_LIST_GET_LAST(heap->base);
|
||||
|
||||
ut_ad(!(block->type & MEM_HEAP_BUFFER) || (n <= MEM_MAX_ALLOC_IN_BUF));
|
||||
|
||||
/* Check if there is enough space in block. If not, create a new
|
||||
block to the heap */
|
||||
|
||||
if (mem_block_get_len(block)
|
||||
< mem_block_get_free(block) + MEM_SPACE_NEEDED(n)) {
|
||||
|
||||
block = mem_heap_add_block(heap, n);
|
||||
|
||||
if (block == NULL) {
|
||||
|
||||
return(NULL);
|
||||
}
|
||||
}
|
||||
|
||||
free = mem_block_get_free(block);
|
||||
|
||||
buf = (byte*) block + free;
|
||||
|
||||
mem_block_set_free(block, free + MEM_SPACE_NEEDED(n));
|
||||
|
||||
#ifdef UNIV_MEM_DEBUG
|
||||
UNIV_MEM_ALLOC(buf,
|
||||
n + MEM_FIELD_HEADER_SIZE + MEM_FIELD_TRAILER_SIZE);
|
||||
|
||||
/* In the debug version write debugging info to the field */
|
||||
mem_field_init((byte*) buf, n);
|
||||
|
||||
/* Advance buf to point at the storage which will be given to the
|
||||
caller */
|
||||
buf = (byte*) buf + MEM_FIELD_HEADER_SIZE;
|
||||
|
||||
#endif
|
||||
UNIV_MEM_ALLOC(buf, n);
|
||||
return(buf);
|
||||
}
|
||||
|
||||
/*****************************************************************//**
|
||||
Returns a pointer to the heap top.
|
||||
@return pointer to the heap top */
|
||||
UNIV_INLINE
|
||||
byte*
|
||||
mem_heap_get_heap_top(
|
||||
/*==================*/
|
||||
mem_heap_t* heap) /*!< in: memory heap */
|
||||
{
|
||||
mem_block_t* block;
|
||||
byte* buf;
|
||||
|
||||
ut_ad(mem_heap_check(heap));
|
||||
|
||||
block = UT_LIST_GET_LAST(heap->base);
|
||||
|
||||
buf = (byte*) block + mem_block_get_free(block);
|
||||
|
||||
return(buf);
|
||||
}
|
||||
|
||||
/*****************************************************************//**
|
||||
Frees the space in a memory heap exceeding the pointer given. The
|
||||
pointer must have been acquired from mem_heap_get_heap_top. The first
|
||||
memory block of the heap is not freed. */
|
||||
UNIV_INLINE
|
||||
void
|
||||
mem_heap_free_heap_top(
|
||||
/*===================*/
|
||||
mem_heap_t* heap, /*!< in: heap from which to free */
|
||||
byte* old_top)/*!< in: pointer to old top of heap */
|
||||
{
|
||||
mem_block_t* block;
|
||||
mem_block_t* prev_block;
|
||||
#if defined UNIV_MEM_DEBUG || defined UNIV_DEBUG
|
||||
ibool error;
|
||||
ulint total_size;
|
||||
ulint size;
|
||||
|
||||
ut_ad(mem_heap_check(heap));
|
||||
|
||||
/* Validate the heap and get its total allocated size */
|
||||
mem_heap_validate_or_print(heap, NULL, FALSE, &error, &total_size,
|
||||
NULL, NULL);
|
||||
ut_a(!error);
|
||||
|
||||
/* Get the size below top pointer */
|
||||
mem_heap_validate_or_print(heap, old_top, FALSE, &error, &size, NULL,
|
||||
NULL);
|
||||
ut_a(!error);
|
||||
|
||||
#endif
|
||||
|
||||
block = UT_LIST_GET_LAST(heap->base);
|
||||
|
||||
while (block != NULL) {
|
||||
if (((byte*) block + mem_block_get_free(block) >= old_top)
|
||||
&& ((byte*) block <= old_top)) {
|
||||
/* Found the right block */
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
/* Store prev_block value before freeing the current block
|
||||
(the current block will be erased in freeing) */
|
||||
|
||||
prev_block = UT_LIST_GET_PREV(list, block);
|
||||
|
||||
mem_heap_block_free(heap, block);
|
||||
|
||||
block = prev_block;
|
||||
}
|
||||
|
||||
ut_ad(block);
|
||||
|
||||
/* Set the free field of block */
|
||||
mem_block_set_free(block, old_top - (byte*) block);
|
||||
|
||||
ut_ad(mem_block_get_start(block) <= mem_block_get_free(block));
|
||||
UNIV_MEM_ASSERT_W(old_top, (byte*) block + block->len - old_top);
|
||||
#if defined UNIV_MEM_DEBUG
|
||||
/* In the debug version erase block from top up */
|
||||
mem_erase_buf(old_top, (byte*) block + block->len - old_top);
|
||||
|
||||
/* Update allocated memory count */
|
||||
mutex_enter(&mem_hash_mutex);
|
||||
mem_current_allocated_memory -= (total_size - size);
|
||||
mutex_exit(&mem_hash_mutex);
|
||||
#endif /* UNIV_MEM_DEBUG */
|
||||
UNIV_MEM_ALLOC(old_top, (byte*) block + block->len - old_top);
|
||||
|
||||
/* If free == start, we may free the block if it is not the first
|
||||
one */
|
||||
|
||||
if ((heap != block) && (mem_block_get_free(block)
|
||||
== mem_block_get_start(block))) {
|
||||
mem_heap_block_free(heap, block);
|
||||
}
|
||||
}
|
||||
|
||||
/*****************************************************************//**
|
||||
Empties a memory heap. The first memory block of the heap is not freed. */
|
||||
UNIV_INLINE
|
||||
void
|
||||
mem_heap_empty(
|
||||
/*===========*/
|
||||
mem_heap_t* heap) /*!< in: heap to empty */
|
||||
{
|
||||
mem_heap_free_heap_top(heap, (byte*) heap + mem_block_get_start(heap));
|
||||
#ifndef UNIV_HOTBACKUP
|
||||
if (heap->free_block) {
|
||||
mem_heap_free_block_free(heap);
|
||||
}
|
||||
#endif /* !UNIV_HOTBACKUP */
|
||||
}
|
||||
|
||||
/*****************************************************************//**
|
||||
Returns a pointer to the topmost element in a memory heap. The size of the
|
||||
element must be given.
|
||||
@return pointer to the topmost element */
|
||||
UNIV_INLINE
|
||||
void*
|
||||
mem_heap_get_top(
|
||||
/*=============*/
|
||||
mem_heap_t* heap, /*!< in: memory heap */
|
||||
ulint n) /*!< in: size of the topmost element */
|
||||
{
|
||||
mem_block_t* block;
|
||||
byte* buf;
|
||||
|
||||
ut_ad(mem_heap_check(heap));
|
||||
|
||||
block = UT_LIST_GET_LAST(heap->base);
|
||||
|
||||
buf = (byte*) block + mem_block_get_free(block) - MEM_SPACE_NEEDED(n);
|
||||
|
||||
#ifdef UNIV_MEM_DEBUG
|
||||
ut_ad(mem_block_get_start(block) <= (ulint) (buf - (byte*) block));
|
||||
|
||||
/* In the debug version, advance buf to point at the storage which
|
||||
was given to the caller in the allocation*/
|
||||
|
||||
buf += MEM_FIELD_HEADER_SIZE;
|
||||
|
||||
/* Check that the field lengths agree */
|
||||
ut_ad(n == mem_field_header_get_len(buf));
|
||||
#endif
|
||||
|
||||
return((void*) buf);
|
||||
}
|
||||
|
||||
/*****************************************************************//**
|
||||
Frees the topmost element in a memory heap. The size of the element must be
|
||||
given. */
|
||||
UNIV_INLINE
|
||||
void
|
||||
mem_heap_free_top(
|
||||
/*==============*/
|
||||
mem_heap_t* heap, /*!< in: memory heap */
|
||||
ulint n) /*!< in: size of the topmost element */
|
||||
{
|
||||
mem_block_t* block;
|
||||
|
||||
ut_ad(mem_heap_check(heap));
|
||||
|
||||
block = UT_LIST_GET_LAST(heap->base);
|
||||
|
||||
/* Subtract the free field of block */
|
||||
mem_block_set_free(block, mem_block_get_free(block)
|
||||
- MEM_SPACE_NEEDED(n));
|
||||
UNIV_MEM_ASSERT_W((byte*) block + mem_block_get_free(block), n);
|
||||
#ifdef UNIV_MEM_DEBUG
|
||||
|
||||
ut_ad(mem_block_get_start(block) <= mem_block_get_free(block));
|
||||
|
||||
/* In the debug version check the consistency, and erase field */
|
||||
mem_field_erase((byte*) block + mem_block_get_free(block), n);
|
||||
#endif
|
||||
|
||||
/* If free == start, we may free the block if it is not the first
|
||||
one */
|
||||
|
||||
if ((heap != block) && (mem_block_get_free(block)
|
||||
== mem_block_get_start(block))) {
|
||||
mem_heap_block_free(heap, block);
|
||||
} else {
|
||||
/* Avoid a bogus UNIV_MEM_ASSERT_W() warning in a
|
||||
subsequent invocation of mem_heap_free_top().
|
||||
Originally, this was UNIV_MEM_FREE(), to catch writes
|
||||
to freed memory. */
|
||||
UNIV_MEM_ALLOC((byte*) block + mem_block_get_free(block), n);
|
||||
}
|
||||
}
|
||||
|
||||
/*****************************************************************//**
|
||||
NOTE: Use the corresponding macros instead of this function. Creates a
|
||||
memory heap. For debugging purposes, takes also the file name and line as
|
||||
argument.
|
||||
@return own: memory heap, NULL if did not succeed (only possible for
|
||||
MEM_HEAP_BTR_SEARCH type heaps) */
|
||||
UNIV_INLINE
|
||||
mem_heap_t*
|
||||
mem_heap_create_func(
|
||||
/*=================*/
|
||||
ulint n, /*!< in: desired start block size,
|
||||
this means that a single user buffer
|
||||
of size n will fit in the block,
|
||||
0 creates a default size block */
|
||||
#ifdef UNIV_DEBUG
|
||||
const char* file_name, /*!< in: file name where created */
|
||||
ulint line, /*!< in: line where created */
|
||||
#endif /* UNIV_DEBUG */
|
||||
ulint type) /*!< in: heap type */
|
||||
{
|
||||
mem_block_t* block;
|
||||
|
||||
if (!n) {
|
||||
n = MEM_BLOCK_START_SIZE;
|
||||
}
|
||||
|
||||
block = mem_heap_create_block(NULL, n, type, file_name, line);
|
||||
|
||||
if (block == NULL) {
|
||||
|
||||
return(NULL);
|
||||
}
|
||||
|
||||
UT_LIST_INIT(block->base);
|
||||
|
||||
/* Add the created block itself as the first block in the list */
|
||||
UT_LIST_ADD_FIRST(list, block->base, block);
|
||||
|
||||
#ifdef UNIV_MEM_DEBUG
|
||||
|
||||
mem_hash_insert(block, file_name, line);
|
||||
|
||||
#endif
|
||||
|
||||
return(block);
|
||||
}
|
||||
|
||||
/*****************************************************************//**
|
||||
NOTE: Use the corresponding macro instead of this function. Frees the space
|
||||
occupied by a memory heap. In the debug version erases the heap memory
|
||||
blocks. */
|
||||
UNIV_INLINE
|
||||
void
|
||||
mem_heap_free_func(
|
||||
/*===============*/
|
||||
mem_heap_t* heap, /*!< in, own: heap to be freed */
|
||||
const char* file_name __attribute__((unused)),
|
||||
/*!< in: file name where freed */
|
||||
ulint line __attribute__((unused)))
|
||||
{
|
||||
mem_block_t* block;
|
||||
mem_block_t* prev_block;
|
||||
|
||||
ut_ad(mem_heap_check(heap));
|
||||
|
||||
block = UT_LIST_GET_LAST(heap->base);
|
||||
|
||||
#ifdef UNIV_MEM_DEBUG
|
||||
|
||||
/* In the debug version remove the heap from the hash table of heaps
|
||||
and check its consistency */
|
||||
|
||||
mem_hash_remove(heap, file_name, line);
|
||||
|
||||
#endif
|
||||
#ifndef UNIV_HOTBACKUP
|
||||
if (heap->free_block) {
|
||||
mem_heap_free_block_free(heap);
|
||||
}
|
||||
#endif /* !UNIV_HOTBACKUP */
|
||||
|
||||
while (block != NULL) {
|
||||
/* Store the contents of info before freeing current block
|
||||
(it is erased in freeing) */
|
||||
|
||||
prev_block = UT_LIST_GET_PREV(list, block);
|
||||
|
||||
mem_heap_block_free(heap, block);
|
||||
|
||||
block = prev_block;
|
||||
}
|
||||
}
|
||||
|
||||
/***************************************************************//**
|
||||
NOTE: Use the corresponding macro instead of this function.
|
||||
Allocates a single buffer of memory from the dynamic memory of
|
||||
the C compiler. Is like malloc of C. The buffer must be freed
|
||||
with mem_free.
|
||||
@return own: free storage */
|
||||
UNIV_INLINE
|
||||
void*
|
||||
mem_alloc_func(
|
||||
/*===========*/
|
||||
ulint n, /*!< in: desired number of bytes */
|
||||
#ifdef UNIV_DEBUG
|
||||
const char* file_name, /*!< in: file name where created */
|
||||
ulint line, /*!< in: line where created */
|
||||
#endif /* UNIV_DEBUG */
|
||||
ulint* size) /*!< out: allocated size in bytes,
|
||||
or NULL */
|
||||
{
|
||||
mem_heap_t* heap;
|
||||
void* buf;
|
||||
|
||||
heap = mem_heap_create_at(n, file_name, line);
|
||||
|
||||
/* Note that as we created the first block in the heap big enough
|
||||
for the buffer requested by the caller, the buffer will be in the
|
||||
first block and thus we can calculate the pointer to the heap from
|
||||
the pointer to the buffer when we free the memory buffer. */
|
||||
|
||||
if (size) {
|
||||
/* Adjust the allocation to the actual size of the
|
||||
memory block. */
|
||||
ulint m = mem_block_get_len(heap)
|
||||
- mem_block_get_free(heap);
|
||||
#ifdef UNIV_MEM_DEBUG
|
||||
m -= MEM_FIELD_HEADER_SIZE + MEM_FIELD_TRAILER_SIZE;
|
||||
#endif /* UNIV_MEM_DEBUG */
|
||||
ut_ad(m >= n);
|
||||
n = m;
|
||||
*size = m;
|
||||
}
|
||||
|
||||
buf = mem_heap_alloc(heap, n);
|
||||
|
||||
ut_a((byte*) heap == (byte*) buf - MEM_BLOCK_HEADER_SIZE
|
||||
- MEM_FIELD_HEADER_SIZE);
|
||||
return(buf);
|
||||
}
|
||||
|
||||
/***************************************************************//**
|
||||
NOTE: Use the corresponding macro instead of this function. Frees a single
|
||||
buffer of storage from the dynamic memory of the C compiler. Similar to the
|
||||
free of C. */
|
||||
UNIV_INLINE
|
||||
void
|
||||
mem_free_func(
|
||||
/*==========*/
|
||||
void* ptr, /*!< in, own: buffer to be freed */
|
||||
const char* file_name, /*!< in: file name where created */
|
||||
ulint line) /*!< in: line where created */
|
||||
{
|
||||
mem_heap_t* heap;
|
||||
|
||||
heap = (mem_heap_t*)((byte*) ptr - MEM_BLOCK_HEADER_SIZE
|
||||
- MEM_FIELD_HEADER_SIZE);
|
||||
mem_heap_free_func(heap, file_name, line);
|
||||
}
|
||||
|
||||
/*****************************************************************//**
|
||||
Returns the space in bytes occupied by a memory heap. */
|
||||
UNIV_INLINE
|
||||
ulint
|
||||
mem_heap_get_size(
|
||||
/*==============*/
|
||||
mem_heap_t* heap) /*!< in: heap */
|
||||
{
|
||||
ulint size = 0;
|
||||
|
||||
ut_ad(mem_heap_check(heap));
|
||||
|
||||
size = heap->total_size;
|
||||
|
||||
#ifndef UNIV_HOTBACKUP
|
||||
if (heap->free_block) {
|
||||
size += UNIV_PAGE_SIZE;
|
||||
}
|
||||
#endif /* !UNIV_HOTBACKUP */
|
||||
|
||||
return(size);
|
||||
}
|
||||
|
||||
/**********************************************************************//**
|
||||
Duplicates a NUL-terminated string.
|
||||
@return own: a copy of the string, must be deallocated with mem_free */
|
||||
UNIV_INLINE
|
||||
char*
|
||||
mem_strdup(
|
||||
/*=======*/
|
||||
const char* str) /*!< in: string to be copied */
|
||||
{
|
||||
ulint len = strlen(str) + 1;
|
||||
return((char*) memcpy(mem_alloc(len), str, len));
|
||||
}
|
||||
|
||||
/**********************************************************************//**
|
||||
Makes a NUL-terminated copy of a nonterminated string.
|
||||
@return own: a copy of the string, must be deallocated with mem_free */
|
||||
UNIV_INLINE
|
||||
char*
|
||||
mem_strdupl(
|
||||
/*========*/
|
||||
const char* str, /*!< in: string to be copied */
|
||||
ulint len) /*!< in: length of str, in bytes */
|
||||
{
|
||||
char* s = (char*) mem_alloc(len + 1);
|
||||
s[len] = 0;
|
||||
return((char*) memcpy(s, str, len));
|
||||
}
|
||||
|
||||
/**********************************************************************//**
|
||||
Makes a NUL-terminated copy of a nonterminated string,
|
||||
allocated from a memory heap.
|
||||
@return own: a copy of the string */
|
||||
UNIV_INLINE
|
||||
char*
|
||||
mem_heap_strdupl(
|
||||
/*=============*/
|
||||
mem_heap_t* heap, /*!< in: memory heap where string is allocated */
|
||||
const char* str, /*!< in: string to be copied */
|
||||
ulint len) /*!< in: length of str, in bytes */
|
||||
{
|
||||
char* s = (char*) mem_heap_alloc(heap, len + 1);
|
||||
s[len] = 0;
|
||||
return((char*) memcpy(s, str, len));
|
||||
}
|
||||
121
storage/innobase/include/mem0pool.h
Normal file
121
storage/innobase/include/mem0pool.h
Normal file
|
|
@ -0,0 +1,121 @@
|
|||
/*****************************************************************************
|
||||
|
||||
Copyright (c) 1994, 2009, Oracle and/or its affiliates. All Rights Reserved.
|
||||
|
||||
This program is free software; you can redistribute it and/or modify it under
|
||||
the terms of the GNU General Public License as published by the Free Software
|
||||
Foundation; version 2 of the License.
|
||||
|
||||
This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
|
||||
FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License along with
|
||||
this program; if not, write to the Free Software Foundation, Inc.,
|
||||
51 Franklin Street, Suite 500, Boston, MA 02110-1335 USA
|
||||
|
||||
*****************************************************************************/
|
||||
|
||||
/**************************************************//**
|
||||
@file include/mem0pool.h
|
||||
The lowest-level memory management
|
||||
|
||||
Created 6/9/1994 Heikki Tuuri
|
||||
*******************************************************/
|
||||
|
||||
#ifndef mem0pool_h
|
||||
#define mem0pool_h
|
||||
|
||||
#include "univ.i"
|
||||
#include "os0file.h"
|
||||
#include "ut0lst.h"
|
||||
|
||||
/** Memory pool */
|
||||
struct mem_pool_t;
|
||||
|
||||
/** The common memory pool */
|
||||
extern mem_pool_t* mem_comm_pool;
|
||||
|
||||
/** Memory area header */
|
||||
struct mem_area_t{
|
||||
ulint size_and_free; /*!< memory area size is obtained by
|
||||
anding with ~MEM_AREA_FREE; area in
|
||||
a free list if ANDing with
|
||||
MEM_AREA_FREE results in nonzero */
|
||||
UT_LIST_NODE_T(mem_area_t)
|
||||
free_list; /*!< free list node */
|
||||
};
|
||||
|
||||
/** Each memory area takes this many extra bytes for control information */
|
||||
#define MEM_AREA_EXTRA_SIZE (ut_calc_align(sizeof(struct mem_area_t),\
|
||||
UNIV_MEM_ALIGNMENT))
|
||||
|
||||
/********************************************************************//**
|
||||
Creates a memory pool.
|
||||
@return memory pool */
|
||||
UNIV_INTERN
|
||||
mem_pool_t*
|
||||
mem_pool_create(
|
||||
/*============*/
|
||||
ulint size); /*!< in: pool size in bytes */
|
||||
/********************************************************************//**
|
||||
Frees a memory pool. */
|
||||
UNIV_INTERN
|
||||
void
|
||||
mem_pool_free(
|
||||
/*==========*/
|
||||
mem_pool_t* pool); /*!< in, own: memory pool */
|
||||
/********************************************************************//**
|
||||
Allocates memory from a pool. NOTE: This low-level function should only be
|
||||
used in mem0mem.*!
|
||||
@return own: allocated memory buffer */
|
||||
UNIV_INTERN
|
||||
void*
|
||||
mem_area_alloc(
|
||||
/*===========*/
|
||||
ulint* psize, /*!< in: requested size in bytes; for optimum
|
||||
space usage, the size should be a power of 2
|
||||
minus MEM_AREA_EXTRA_SIZE;
|
||||
out: allocated size in bytes (greater than
|
||||
or equal to the requested size) */
|
||||
mem_pool_t* pool); /*!< in: memory pool */
|
||||
/********************************************************************//**
|
||||
Frees memory to a pool. */
|
||||
UNIV_INTERN
|
||||
void
|
||||
mem_area_free(
|
||||
/*==========*/
|
||||
void* ptr, /*!< in, own: pointer to allocated memory
|
||||
buffer */
|
||||
mem_pool_t* pool); /*!< in: memory pool */
|
||||
/********************************************************************//**
|
||||
Returns the amount of reserved memory.
|
||||
@return reserved mmeory in bytes */
|
||||
UNIV_INTERN
|
||||
ulint
|
||||
mem_pool_get_reserved(
|
||||
/*==================*/
|
||||
mem_pool_t* pool); /*!< in: memory pool */
|
||||
/********************************************************************//**
|
||||
Validates a memory pool.
|
||||
@return TRUE if ok */
|
||||
UNIV_INTERN
|
||||
ibool
|
||||
mem_pool_validate(
|
||||
/*==============*/
|
||||
mem_pool_t* pool); /*!< in: memory pool */
|
||||
/********************************************************************//**
|
||||
Prints info of a memory pool. */
|
||||
UNIV_INTERN
|
||||
void
|
||||
mem_pool_print_info(
|
||||
/*================*/
|
||||
FILE* outfile,/*!< in: output file to write to */
|
||||
mem_pool_t* pool); /*!< in: memory pool */
|
||||
|
||||
|
||||
#ifndef UNIV_NONINL
|
||||
#include "mem0pool.ic"
|
||||
#endif
|
||||
|
||||
#endif
|
||||
Some files were not shown because too many files have changed in this diff Show more
Loading…
Add table
Add a link
Reference in a new issue