xtradb 5.5.13

This commit is contained in:
Sergei Golubchik 2011-07-14 21:22:41 +02:00
commit 54ab9ea20f
544 changed files with 25884 additions and 66818 deletions

View file

@ -68,19 +68,115 @@ enum btr_latch_mode {
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 */
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_latch_mode says that we can ignore possible
/** 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
#ifdef UNIV_BLOB_DEBUG
# include "ut0rbt.h"
/** An index->blobs entry for keeping track of off-page column references */
struct btr_blob_dbg_struct
{
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 */
@ -123,12 +219,23 @@ btr_block_get_func(
@return the uncompressed page frame */
# define btr_page_get(space,zip_size,page_no,mode,mtr) \
buf_block_get_frame(btr_block_get(space,zip_size,page_no,mode,mtr))
/**************************************************************//**
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 */
#endif /* !UNIV_HOTBACKUP */
/**************************************************************//**
Gets the index id field of a page.
@return index id */
UNIV_INLINE
dulint
index_id_t
btr_page_get_index_id(
/*==================*/
const page_t* page); /*!< in: index page */
@ -160,6 +267,17 @@ btr_page_get_next(
const page_t* page, /*!< in: index page */
mtr_t* mtr); /*!< in: mini-transaction handle */
/********************************************************//**
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 */
/********************************************************//**
Gets the previous index page number.
@return prev page number */
UNIV_INLINE
@ -168,6 +286,17 @@ btr_page_get_prev(
/*==============*/
const page_t* page, /*!< in: index page */
mtr_t* mtr); /*!< in: mini-transaction handle */
/********************************************************//**
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 */
/*************************************************************//**
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.
@ -213,6 +342,18 @@ 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() */
/**************************************************************//**
Creates a new index page (not the root, and also not
used in page reorganization). @see btr_page_empty(). */
UNIV_INTERN
void
btr_page_create(
/*============*/
buf_block_t* block, /*!< in/out: page to be created */
page_zip_des_t* page_zip,/*!< in/out: compressed page, or NULL */
dict_index_t* index, /*!< in: index */
ulint level, /*!< in: the B-tree level of the page */
mtr_t* mtr); /*!< in: mtr */
/************************************************************//**
Creates the root node for a new index tree.
@return page number of the created root, FIL_NULL if did not succeed */
@ -224,7 +365,7 @@ btr_create(
ulint space, /*!< in: space where created */
ulint zip_size,/*!< in: compressed page size in bytes
or 0 for uncompressed pages */
dulint index_id,/*!< in: index id */
index_id_t index_id,/*!< in: index id */
dict_index_t* index, /*!< in: index */
mtr_t* mtr); /*!< in: mini-transaction handle */
/************************************************************//**
@ -283,6 +424,17 @@ btr_page_reorganize(
dict_index_t* index, /*!< in: record descriptor */
mtr_t* mtr); /*!< in: mtr */
/*************************************************************//**
Empties an index page. @see btr_page_create(). */
UNIV_INTERN
void
btr_page_empty(
/*===========*/
buf_block_t* block, /*!< in: page to be emptied */
page_zip_des_t* page_zip,/*!< out: compressed page, or NULL */
dict_index_t* index, /*!< in: index of the page */
ulint level, /*!< in: the B-tree level of the page */
mtr_t* mtr); /*!< in: mtr */
/*************************************************************//**
Decides if the page should be split at the convergence point of
inserts converging to left.
@return TRUE if split recommended */
@ -341,6 +493,20 @@ btr_insert_on_non_leaf_level_func(
# define btr_insert_on_non_leaf_level(i,l,t,m) \
btr_insert_on_non_leaf_level_func(i,l,t,__FILE__,__LINE__,m)
#endif /* !UNIV_HOTBACKUP */
/**************************************************************//**
Attaches the halves of an index page on the appropriate level in an
index tree. */
UNIV_INTERN
void
btr_attach_half_pages(
/*==================*/
dict_index_t* index, /*!< in: the index tree */
buf_block_t* block, /*!< in/out: page to be split */
rec_t* split_rec, /*!< in: first record on upper
half page */
buf_block_t* new_block, /*!< in/out: the new half page */
ulint direction, /*!< in: FSP_UP or FSP_DOWN */
mtr_t* mtr); /*!< in: mtr */
/****************************************************************//**
Sets a record as the predefined minimum record. */
UNIV_INTERN

View file

@ -74,7 +74,7 @@ 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 */
dulint id, /*!< in: index id */
index_id_t id, /*!< in: index id */
mtr_t* mtr) /*!< in: mtr */
{
if (UNIV_LIKELY_NULL(page_zip)) {
@ -83,8 +83,7 @@ btr_page_set_index_id(
page + (PAGE_HEADER + PAGE_INDEX_ID),
8, mtr);
} else {
mlog_write_dulint(page + (PAGE_HEADER + PAGE_INDEX_ID),
id, mtr);
mlog_write_ull(page + (PAGE_HEADER + PAGE_INDEX_ID), id, mtr);
}
}
#endif /* !UNIV_HOTBACKUP */
@ -93,7 +92,7 @@ btr_page_set_index_id(
Gets the index id field of a page.
@return index id */
UNIV_INLINE
dulint
index_id_t
btr_page_get_index_id(
/*==================*/
const page_t* page) /*!< in: index page */

View file

@ -138,7 +138,8 @@ btr_cur_search_to_nth_level(
should always be made using PAGE_CUR_LE to
search the position! */
ulint latch_mode, /*!< in: BTR_SEARCH_LEAF, ..., ORed with
BTR_INSERT and BTR_ESTIMATE;
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;
@ -352,19 +353,6 @@ btr_cur_del_mark_set_sec_rec(
ibool val, /*!< in: value to set */
que_thr_t* thr, /*!< in: query thread */
mtr_t* mtr); /*!< in: mtr */
/***********************************************************//**
Clear a secondary index record's delete mark. This function is only
used by the insert buffer insert merge mechanism. */
UNIV_INTERN
void
btr_cur_del_unmark_for_ibuf(
/*========================*/
rec_t* rec, /*!< in/out: record to delete unmark */
page_zip_des_t* page_zip, /*!< in/out: compressed page
corresponding to rec, or NULL
when the tablespace is
uncompressed */
mtr_t* mtr); /*!< in: mtr */
/*************************************************************//**
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
@ -634,7 +622,20 @@ btr_push_update_extern_fields(
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: mtr */
/*######################################################################*/
/** In the pessimistic delete, if the page data size drops below this
@ -652,6 +653,11 @@ struct btr_path_struct{
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) */
@ -666,8 +672,13 @@ enum btr_cur_method {
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
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
@ -675,6 +686,7 @@ to know struct size! */
struct btr_cur_struct {
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
@ -731,6 +743,23 @@ struct btr_cur_struct {
NULL */
ulint fold; /*!< fold value used in the search if
flag is BTR_CUR_HASH */
/*----- Delete buffering -------*/
ulint ibuf_cnt; /* in searches done on insert buffer
trees, this contains the "counter"
value (the first two bytes of the
fourth field) extracted from the
page above the leaf page, from the
father node pointer that pointed to
the leaf page. in other words, it
contains the minimum counter value
for records to be inserted on the
chosen leaf page. If for some reason
this can't be read, or if the search
ended on the leftmost leaf page in
the tree (in which case the father
node pointer had the 'minimum
record' flag set), this is
ULINT_UNDEFINED. */
/*------------------------------*/
/* @} */
btr_path_t* path_arr; /*!< in estimating the number of

View file

@ -150,7 +150,7 @@ UNIV_INLINE
ulint
btr_pcur_get_up_match(
/*==================*/
btr_pcur_t* cursor); /*!< in: memory buffer for persistent cursor */
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
@ -159,7 +159,7 @@ UNIV_INLINE
ulint
btr_pcur_get_low_match(
/*===================*/
btr_pcur_t* cursor); /*!< in: memory buffer for persistent cursor */
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
@ -264,22 +264,6 @@ ulint
btr_pcur_get_rel_pos(
/*=================*/
const btr_pcur_t* cursor);/*!< in: persistent cursor */
/*********************************************************//**
Sets the mtr field for a pcur. */
UNIV_INLINE
void
btr_pcur_set_mtr(
/*=============*/
btr_pcur_t* cursor, /*!< in: persistent cursor */
mtr_t* mtr); /*!< in, own: mtr */
/*********************************************************//**
Gets the mtr field for a pcur.
@return mtr */
UNIV_INLINE
mtr_t*
btr_pcur_get_mtr(
/*=============*/
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. If there have been modifications
@ -387,10 +371,6 @@ page_cur_t*
btr_pcur_get_page_cur(
/*==================*/
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)
#endif /* UNIV_DEBUG */
/*********************************************************//**
Returns the page of a persistent cursor.
@return pointer to the page */
@ -398,7 +378,7 @@ UNIV_INLINE
page_t*
btr_pcur_get_page(
/*==============*/
btr_pcur_t* cursor);/*!< in: persistent cursor */
const btr_pcur_t* cursor);/*!< in: persistent cursor */
/*********************************************************//**
Returns the buffer block of a persistent cursor.
@return pointer to the block */
@ -406,7 +386,7 @@ UNIV_INLINE
buf_block_t*
btr_pcur_get_block(
/*===============*/
btr_pcur_t* cursor);/*!< in: persistent cursor */
const btr_pcur_t* cursor);/*!< in: persistent cursor */
/*********************************************************//**
Returns the record of a persistent cursor.
@return pointer to the record */
@ -414,7 +394,14 @@ UNIV_INLINE
rec_t*
btr_pcur_get_rec(
/*=============*/
btr_pcur_t* cursor);/*!< in: persistent cursor */
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
@ -517,9 +504,6 @@ struct btr_pcur_struct{
/* NOTE that the following fields may possess dynamically allocated
memory which should be freed if not needed anymore! */
mtr_t* mtr; /*!< NULL, or this field may contain
a mini-transaction which holds the
latch on the cursor page */
byte* old_rec_buf; /*!< NULL, or a dynamically allocated
buffer for old_rec */
ulint buf_size; /*!< old_rec_buf size if old_rec_buf

View file

@ -42,34 +42,6 @@ btr_pcur_get_rel_pos(
return(cursor->rel_pos);
}
/*********************************************************//**
Sets the mtr field for a pcur. */
UNIV_INLINE
void
btr_pcur_set_mtr(
/*=============*/
btr_pcur_t* cursor, /*!< in: persistent cursor */
mtr_t* mtr) /*!< in, own: mtr */
{
ut_ad(cursor);
cursor->mtr = mtr;
}
/*********************************************************//**
Gets the mtr field for a pcur.
@return mtr */
UNIV_INLINE
mtr_t*
btr_pcur_get_mtr(
/*=============*/
btr_pcur_t* cursor) /*!< in: persistent cursor */
{
ut_ad(cursor);
return(cursor->mtr);
}
#ifdef UNIV_DEBUG
/*********************************************************//**
Returns the btr cursor component of a persistent cursor.
@ -95,7 +67,7 @@ btr_pcur_get_page_cur(
{
return(btr_cur_get_page_cur(btr_pcur_get_btr_cur(cursor)));
}
#endif /* UNIV_DEBUG */
/*********************************************************//**
Returns the page of a persistent cursor.
@return pointer to the page */
@ -103,7 +75,7 @@ UNIV_INLINE
page_t*
btr_pcur_get_page(
/*==============*/
btr_pcur_t* cursor) /*!< in: persistent cursor */
const btr_pcur_t* cursor) /*!< in: persistent cursor */
{
ut_ad(cursor->pos_state == BTR_PCUR_IS_POSITIONED);
@ -117,7 +89,7 @@ UNIV_INLINE
buf_block_t*
btr_pcur_get_block(
/*===============*/
btr_pcur_t* cursor) /*!< in: persistent cursor */
const btr_pcur_t* cursor) /*!< in: persistent cursor */
{
ut_ad(cursor->pos_state == BTR_PCUR_IS_POSITIONED);
@ -131,13 +103,14 @@ UNIV_INLINE
rec_t*
btr_pcur_get_rec(
/*=============*/
btr_pcur_t* cursor) /*!< in: persistent cursor */
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.
@ -147,9 +120,9 @@ UNIV_INLINE
ulint
btr_pcur_get_up_match(
/*==================*/
btr_pcur_t* cursor) /*!< in: memory buffer for persistent cursor */
const btr_pcur_t* cursor) /*!< in: persistent cursor */
{
btr_cur_t* btr_cursor;
const btr_cur_t* btr_cursor;
ut_ad((cursor->pos_state == BTR_PCUR_WAS_POSITIONED)
|| (cursor->pos_state == BTR_PCUR_IS_POSITIONED));
@ -169,9 +142,9 @@ UNIV_INLINE
ulint
btr_pcur_get_low_match(
/*===================*/
btr_pcur_t* cursor) /*!< in: memory buffer for persistent cursor */
const btr_pcur_t* cursor) /*!< in: persistent cursor */
{
btr_cur_t* btr_cursor;
const btr_cur_t* btr_cursor;
ut_ad((cursor->pos_state == BTR_PCUR_WAS_POSITIONED)
|| (cursor->pos_state == BTR_PCUR_IS_POSITIONED));

View file

@ -85,7 +85,8 @@ UNIV_INTERN
ulint
btr_search_info_get_ref_count(
/*==========================*/
btr_search_t* info); /*!< in: search info. */
btr_search_t* info, /*!< in: search info. */
index_id_t key);
/*********************************************************************//**
Updates the search info. */
UNIV_INLINE
@ -136,10 +137,11 @@ UNIV_INTERN
void
btr_search_drop_page_hash_index(
/*============================*/
buf_block_t* block); /*!< in: block containing index page,
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 */
dict_index_t* index_in);
/************************************************************************
Drops a page hash index based on index */
UNIV_INTERN
@ -199,10 +201,47 @@ btr_search_validate(void);
# define btr_search_validate() TRUE
#endif /* defined UNIV_AHI_DEBUG || defined UNIV_DEBUG */
/********************************************************************//**
New functions to control split btr_search_index */
UNIV_INLINE
hash_table_t*
btr_search_get_hash_index(
/*======================*/
index_id_t key);
UNIV_INLINE
rw_lock_t*
btr_search_get_latch(
/*=================*/
index_id_t key);
UNIV_INLINE
void
btr_search_x_lock_all(void);
/*========================*/
UNIV_INLINE
void
btr_search_x_unlock_all(void);
/*==========================*/
UNIV_INLINE
void
btr_search_s_lock_all(void);
/*========================*/
UNIV_INLINE
void
btr_search_s_unlock_all(void);
/*==========================*/
/** Flag: has the search system been enabled?
Protected by btr_search_latch and btr_search_enabled_mutex. */
extern char btr_search_enabled;
extern ulint btr_search_index_num;
/** Flag: whether the search system has completed its disabling process,
It is set to TRUE right after buf_pool_drop_hash_index() in
btr_search_disable(), indicating hash index entries are cleaned up.
@ -269,7 +308,7 @@ typedef struct btr_search_sys_struct btr_search_sys_t;
/** The hash index system */
struct btr_search_sys_struct{
hash_table_t* hash_index; /*!< the adaptive hash index,
hash_table_t** hash_index; /*!< the adaptive hash index,
mapping dtuple_fold values
to rec_t pointers on index pages */
};
@ -290,10 +329,12 @@ but does NOT protect:
Bear in mind (3) and (4) when using the hash index.
*/
extern rw_lock_t* btr_search_latch_temp;
//extern rw_lock_t* btr_search_latch_temp;
extern rw_lock_t** btr_search_latch_part;
/** The latch protecting the adaptive search system */
#define btr_search_latch (*btr_search_latch_temp)
//#define btr_search_latch (*btr_search_latch_temp)
#ifdef UNIV_SEARCH_PERF_STAT
/** Number of successful adaptive hash index lookups */

View file

@ -62,8 +62,8 @@ btr_search_info_update(
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));
ut_ad(!rw_lock_own(btr_search_get_latch(index->id), RW_LOCK_SHARED));
ut_ad(!rw_lock_own(btr_search_get_latch(index->id), RW_LOCK_EX));
#endif /* UNIV_SYNC_DEBUG */
info = btr_search_get_info(index);
@ -82,3 +82,72 @@ btr_search_info_update(
btr_search_info_update_slow(info, cursor);
}
/*********************************************************************//**
New functions to control split btr_search_index */
UNIV_INLINE
hash_table_t*
btr_search_get_hash_index(
/*======================*/
index_id_t key)
{
return(btr_search_sys->hash_index[key % btr_search_index_num]);
}
UNIV_INLINE
rw_lock_t*
btr_search_get_latch(
/*=================*/
index_id_t key)
{
return(btr_search_latch_part[key % btr_search_index_num]);
}
UNIV_INLINE
void
btr_search_x_lock_all(void)
/*=======================*/
{
ulint i;
for (i = 0; i < btr_search_index_num; i++) {
rw_lock_x_lock(btr_search_latch_part[i]);
}
}
UNIV_INLINE
void
btr_search_x_unlock_all(void)
/*==========================*/
{
ulint i;
for (i = 0; i < btr_search_index_num; i++) {
rw_lock_x_unlock(btr_search_latch_part[i]);
}
}
UNIV_INLINE
void
btr_search_s_lock_all(void)
/*=======================*/
{
ulint i;
for (i = 0; i < btr_search_index_num; i++) {
rw_lock_s_lock(btr_search_latch_part[i]);
}
}
UNIV_INLINE
void
btr_search_s_unlock_all(void)
/*=========================*/
{
ulint i;
for (i = 0; i < btr_search_index_num; i++) {
rw_lock_s_unlock(btr_search_latch_part[i]);
}
}

View file

@ -38,6 +38,131 @@ typedef struct btr_cur_struct btr_cur_t;
/** B-tree search information for the adaptive hash index */
typedef struct btr_search_struct btr_search_t;
#ifdef UNIV_BLOB_DEBUG
# include "buf0types.h"
/** An index->blobs entry for keeping track of off-page column references */
typedef struct btr_blob_dbg_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. */

View file

@ -36,22 +36,24 @@ Created December 2006 by Marko Makela
/**********************************************************************//**
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 only be released and reacquired
buf_pool->mutex and must not hold buf_pool->zip_mutex or any
block->mutex. The buf_pool->mutex may only be released and reacquired
if lru != NULL. This function should only be used for allocating
compressed page frames or control blocks (buf_page_t). Allocated
control blocks must be properly initialized immediately after
buf_buddy_alloc() has returned the memory, before releasing
buf_pool_mutex.
buf_pool->mutex.
@return allocated block, possibly NULL if lru == NULL */
UNIV_INLINE
void*
buf_buddy_alloc(
/*============*/
buf_pool_t* buf_pool,
/*!< buffer pool in which the block resides */
ulint size, /*!< in: block size, up to 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,
and buf_pool->mutex was temporarily released,
or NULL if the LRU list should not be used */
ibool have_page_hash_mutex)
__attribute__((malloc));
@ -62,29 +64,14 @@ UNIV_INLINE
void
buf_buddy_free(
/*===========*/
buf_pool_t* buf_pool,
/*!< 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 */
ibool have_page_hash_mutex)
__attribute__((nonnull));
/** Statistics of buddy blocks of a given size. */
struct buf_buddy_stat_struct {
/** Number of blocks allocated from the buddy system. */
ulint used;
/** Number of blocks relocated by the buddy system. */
ib_uint64_t relocated;
/** Total duration of block relocations, in microseconds. */
ib_uint64_t relocated_usec;
};
/** Statistics of buddy blocks of a given size. */
typedef struct buf_buddy_stat_struct buf_buddy_stat_t;
/** Statistics of the buddy system, indexed by block size.
Protected by buf_pool_mutex. */
extern buf_buddy_stat_t buf_buddy_stat[BUF_BUDDY_SIZES_MAX + 1];
#ifndef UNIV_NONINL
# include "buf0buddy.ic"
#endif

View file

@ -35,18 +35,20 @@ Created December 2006 by Marko Makela
/**********************************************************************//**
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 only be released and reacquired if lru != NULL.
buf_pool->mutex and must not hold buf_pool->zip_mutex or any block->mutex.
The buf_pool->mutex may only be released and reacquired if lru != NULL.
@return allocated block, possibly NULL if lru==NULL */
UNIV_INTERN
void*
buf_buddy_alloc_low(
/*================*/
buf_pool_t* buf_pool,
/*!< in: buffer pool in which the page resides */
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,
and buf_pool->mutex was temporarily released,
or NULL if the LRU list should not be used */
ibool have_page_hash_mutex)
__attribute__((malloc));
@ -57,11 +59,12 @@ UNIV_INTERN
void
buf_buddy_free_low(
/*===============*/
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 */
ibool have_page_hash_mutex)
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 */
ibool have_page_hash_mutex)
__attribute__((nonnull));
/**********************************************************************//**
@ -85,28 +88,33 @@ buf_buddy_get_slot(
/**********************************************************************//**
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 only be released and reacquired
buf_pool->mutex and must not hold buf_pool->zip_mutex or any
block->mutex. The buf_pool->mutex may only be released and reacquired
if lru != NULL. This function should only be used for allocating
compressed page frames or control blocks (buf_page_t). Allocated
control blocks must be properly initialized immediately after
buf_buddy_alloc() has returned the memory, before releasing
buf_pool_mutex.
buf_pool->mutex.
@return allocated block, possibly NULL if lru == NULL */
UNIV_INLINE
void*
buf_buddy_alloc(
/*============*/
ulint size, /*!< in: block size, up to 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,
or NULL if the LRU list should not be used */
ibool have_page_hash_mutex)
buf_pool_t* buf_pool, /*!< in: buffer pool in which
the page resides */
ulint size, /*!< in: block size, up to
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, or NULL if
the LRU list should not be used */
ibool have_page_hash_mutex)
{
//ut_ad(buf_pool_mutex_own());
//ut_ad(buf_pool_mutex_own(buf_pool));
return(buf_buddy_alloc_low(buf_buddy_get_slot(size), lru, have_page_hash_mutex));
return(buf_buddy_alloc_low(buf_pool, buf_buddy_get_slot(size), lru, have_page_hash_mutex));
}
/**********************************************************************//**
@ -115,25 +123,27 @@ UNIV_INLINE
void
buf_buddy_free(
/*===========*/
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 */
ibool have_page_hash_mutex)
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 size, /*!< in: block size, up to
UNIV_PAGE_SIZE */
ibool have_page_hash_mutex)
{
//ut_ad(buf_pool_mutex_own());
//ut_ad(buf_pool_mutex_own(buf_pool));
if (!have_page_hash_mutex) {
mutex_enter(&LRU_list_mutex);
rw_lock_x_lock(&page_hash_latch);
mutex_enter(&buf_pool->LRU_list_mutex);
rw_lock_x_lock(&buf_pool->page_hash_latch);
}
mutex_enter(&zip_free_mutex);
buf_buddy_free_low(buf, buf_buddy_get_slot(size), TRUE);
mutex_exit(&zip_free_mutex);
mutex_enter(&buf_pool->zip_free_mutex);
buf_buddy_free_low(buf_pool, buf, buf_buddy_get_slot(size), TRUE);
mutex_exit(&buf_pool->zip_free_mutex);
if (!have_page_hash_mutex) {
mutex_exit(&LRU_list_mutex);
rw_lock_x_unlock(&page_hash_latch);
mutex_exit(&buf_pool->LRU_list_mutex);
rw_lock_x_unlock(&buf_pool->page_hash_latch);
}
}

View file

@ -33,21 +33,26 @@ Created 11/5/1995 Heikki Tuuri
#include "hash0hash.h"
#include "ut0byte.h"
#include "page0types.h"
#include "ut0rbt.h"
#ifndef UNIV_HOTBACKUP
#include "ut0rbt.h"
#include "os0proc.h"
#include "srv0srv.h"
/** @name Modes for buf_page_get_gen */
/* @{ */
#define BUF_GET 10 /*!< get always */
#define BUF_GET_IF_IN_POOL 11 /*!< get if in pool */
#define BUF_PEEK_IF_IN_POOL 12 /*!< get if in pool, do not make
the block young in the LRU list */
#define BUF_GET_NO_LATCH 14 /*!< get and bufferfix, but
set no latch; we have
separated this case, because
it is error-prone programming
not to set a latch, and it
should be used with care */
#define BUF_GET_IF_IN_POOL_OR_WATCH 15
/*!< Get the page only if it's in the
buffer pool, if not then set a watch
on the page. */
/* @} */
/** @name Modes for buf_page_get_known_nowait */
/* @{ */
@ -60,7 +65,14 @@ Created 11/5/1995 Heikki Tuuri
position of the block. */
/* @} */
extern buf_pool_t* buf_pool; /*!< The buffer pool of the database */
#define MAX_BUFFER_POOLS 64 /*!< The maximum number of buffer
pools that can be defined */
#define BUF_POOL_WATCH_SIZE 1 /*!< Maximum number of concurrent
buffer pool watches */
extern buf_pool_t* buf_pool_ptr; /*!< The buffer pools
of the database */
#ifdef UNIV_DEBUG
extern ibool buf_debug_prints;/*!< If this is set TRUE, the program
prints info whenever read or flush
@ -68,6 +80,8 @@ extern ibool buf_debug_prints;/*!< If this is set TRUE, the program
#endif /* UNIV_DEBUG */
extern ulint srv_buf_pool_write_requests; /*!< variable to count write request
issued */
extern ulint srv_buf_pool_instances;
extern ulint srv_buf_pool_curr_size;
#else /* !UNIV_HOTBACKUP */
extern buf_block_t* back_block1; /*!< first block, for --apply-log */
extern buf_block_t* back_block2; /*!< second block, for page reorganize */
@ -83,6 +97,8 @@ The enumeration values must be 0..7. */
enum buf_page_state {
BUF_BLOCK_ZIP_FREE = 0, /*!< contains a free
compressed page */
BUF_BLOCK_POOL_WATCH = 0, /*!< a sentinel for the buffer pool
watch, element of buf_pool->watch[] */
BUF_BLOCK_ZIP_PAGE, /*!< contains a clean
compressed page */
BUF_BLOCK_ZIP_DIRTY, /*!< contains a compressed
@ -102,21 +118,123 @@ enum buf_page_state {
before putting to the free list */
};
/** This structure defines information we will fetch from each buffer pool. It
will be used to print table IO stats */
struct buf_pool_info_struct{
/* General buffer pool info */
ulint pool_unique_id; /*!< Buffer Pool ID */
ulint pool_size; /*!< Buffer Pool size in pages */
ulint pool_size_bytes;
ulint lru_len; /*!< Length of buf_pool->LRU */
ulint old_lru_len; /*!< buf_pool->LRU_old_len */
ulint free_list_len; /*!< Length of buf_pool->free list */
ulint flush_list_len; /*!< Length of buf_pool->flush_list */
ulint n_pend_unzip; /*!< buf_pool->n_pend_unzip, pages
pending decompress */
ulint n_pend_reads; /*!< buf_pool->n_pend_reads, pages
pending read */
ulint n_pending_flush_lru; /*!< Pages pending flush in LRU */
ulint n_pending_flush_list; /*!< Pages pending flush in FLUSH
LIST */
ulint n_pending_flush_single_page;/*!< Pages pending flush in
BUF_FLUSH_SINGLE_PAGE list */
ulint n_pages_made_young; /*!< number of pages made young */
ulint n_pages_not_made_young; /*!< number of pages not made young */
ulint n_pages_read; /*!< buf_pool->n_pages_read */
ulint n_pages_created; /*!< buf_pool->n_pages_created */
ulint n_pages_written; /*!< buf_pool->n_pages_written */
ulint n_page_gets; /*!< buf_pool->n_page_gets */
ulint n_ra_pages_read; /*!< buf_pool->n_ra_pages_read, number
of pages readahead */
ulint n_ra_pages_evicted; /*!< buf_pool->n_ra_pages_evicted,
number of readahead pages evicted
without access */
ulint n_page_get_delta; /*!< num of buffer pool page gets since
last printout */
/* Buffer pool access stats */
double page_made_young_rate; /*!< page made young rate in pages
per second */
double page_not_made_young_rate;/*!< page not made young rate
in pages per second */
double pages_read_rate; /*!< num of pages read per second */
double pages_created_rate; /*!< num of pages create per second */
double pages_written_rate; /*!< num of pages written per second */
ulint page_read_delta; /*!< num of pages read since last
printout */
ulint young_making_delta; /*!< num of pages made young since
last printout */
ulint not_young_making_delta; /*!< num of pages not make young since
last printout */
/* Statistics about read ahead algorithm. */
double pages_readahead_rate; /*!< readahead rate in pages per
second */
double pages_evicted_rate; /*!< rate of readahead page evicted
without access, in pages per second */
/* Stats about LRU eviction */
ulint unzip_lru_len; /*!< length of buf_pool->unzip_LRU
list */
/* Counters for LRU policy */
ulint io_sum; /*!< buf_LRU_stat_sum.io */
ulint io_cur; /*!< buf_LRU_stat_cur.io, num of IO
for current interval */
ulint unzip_sum; /*!< buf_LRU_stat_sum.unzip */
ulint unzip_cur; /*!< buf_LRU_stat_cur.unzip, num
pages decompressed in current
interval */
};
typedef struct buf_pool_info_struct buf_pool_info_t;
#ifndef UNIV_HOTBACKUP
/********************************************************************//**
Acquire mutex on all buffer pool instances */
UNIV_INLINE
void
buf_pool_mutex_enter_all(void);
/*===========================*/
/********************************************************************//**
Release mutex on all buffer pool instances */
UNIV_INLINE
void
buf_pool_mutex_exit_all(void);
/*==========================*/
/********************************************************************//**
*/
UNIV_INLINE
void
buf_pool_page_hash_x_lock_all(void);
/*================================*/
/********************************************************************//**
*/
UNIV_INLINE
void
buf_pool_page_hash_x_unlock_all(void);
/*==================================*/
/********************************************************************//**
Creates the buffer pool.
@return own: buf_pool object, NULL if not enough memory or error */
UNIV_INTERN
buf_pool_t*
buf_pool_init(void);
/*===============*/
ulint
buf_pool_init(
/*=========*/
ulint size, /*!< in: Size of the total pool in bytes */
ulint n_instances); /*!< in: Number of instances */
/********************************************************************//**
Frees the buffer pool at shutdown. This must not be invoked before
freeing all mutexes. */
UNIV_INTERN
void
buf_pool_free(void);
/*===============*/
buf_pool_free(
/*==========*/
ulint n_instances); /*!< in: numbere of instances to free */
/********************************************************************//**
Drops the adaptive hash index. To prevent a livelock, this function
@ -153,21 +271,31 @@ UNIV_INLINE
ulint
buf_pool_get_curr_size(void);
/*========================*/
/*********************************************************************//**
Gets the current size of buffer buf_pool in frames.
@return size in pages */
UNIV_INLINE
ulint
buf_pool_get_n_pages(void);
/*=======================*/
/********************************************************************//**
Gets the smallest oldest_modification lsn for any page in the pool. Returns
zero if all modified pages have been flushed to disk.
@return oldest modification in pool, zero if none */
UNIV_INLINE
UNIV_INTERN
ib_uint64_t
buf_pool_get_oldest_modification(void);
/*==================================*/
/********************************************************************//**
Allocates a buffer block.
@return own: the allocated block, in state BUF_BLOCK_MEMORY */
UNIV_INLINE
UNIV_INTERN
buf_block_t*
buf_block_alloc(void);
/*=================*/
buf_block_alloc(
/*============*/
buf_pool_t* buf_pool); /*!< in: buffer pool instance,
or NULL for round-robin selection
of the buffer pool */
/********************************************************************//**
Frees a buffer block which does not contain a file page. */
UNIV_INLINE
@ -285,7 +413,8 @@ buf_page_get_gen(
ulint rw_latch,/*!< in: RW_S_LATCH, RW_X_LATCH, RW_NO_LATCH */
buf_block_t* guess, /*!< in: guessed block or NULL */
ulint mode, /*!< in: BUF_GET, BUF_GET_IF_IN_POOL,
BUF_GET_NO_LATCH */
BUF_PEEK_IF_IN_POOL, BUF_GET_NO_LATCH or
BUF_GET_IF_IN_POOL_OR_WATCH */
const char* file, /*!< in: file name */
ulint line, /*!< in: line where called */
mtr_t* mtr); /*!< in: mini-transaction */
@ -335,9 +464,8 @@ void
buf_page_release(
/*=============*/
buf_block_t* block, /*!< in: buffer block */
ulint rw_latch, /*!< in: RW_S_LATCH, RW_X_LATCH,
ulint rw_latch); /*!< in: RW_S_LATCH, RW_X_LATCH,
RW_NO_LATCH */
mtr_t* mtr); /*!< in: mtr */
/********************************************************************//**
Moves a page to the start of the buffer pool LRU list. This high-level
function can be used to prevent an important page from slipping out of
@ -447,7 +575,7 @@ buf_page_get_newest_modification(
page frame */
/********************************************************************//**
Increments the modify clock of a frame by 1. The caller must (1) own the
buf_pool mutex and block bufferfix count has to be zero, (2) or own an x-lock
buf_pool->mutex and block bufferfix count has to be zero, (2) or own an x-lock
on the block. */
UNIV_INLINE
void
@ -534,7 +662,8 @@ UNIV_INTERN
buf_block_t*
buf_pool_contains_zip(
/*==================*/
const void* data); /*!< in: pointer to compressed page */
buf_pool_t* buf_pool, /*!< in: buffer pool instance */
const void* data); /*!< in: pointer to compressed page */
#endif /* UNIV_DEBUG */
#if defined UNIV_DEBUG || defined UNIV_BUF_DEBUG
/*********************************************************************//**
@ -608,8 +737,15 @@ buf_get_modified_ratio_pct(void);
Refreshes the statistics used to print per-second averages. */
UNIV_INTERN
void
buf_refresh_io_stats(void);
/*======================*/
buf_refresh_io_stats(
/*=================*/
buf_pool_t* buf_pool); /*!< buffer pool instance */
/**********************************************************************//**
Refreshes the statistics used to print per-second averages. */
UNIV_INTERN
void
buf_refresh_io_stats_all(void);
/*=================*/
/*********************************************************************//**
Asserts that all file pages in the buffer are in a replaceable state.
@return TRUE */
@ -834,7 +970,8 @@ buf_page_set_accessed(
__attribute__((nonnull));
/*********************************************************************//**
Gets the buf_block_t handle of a buffered file block if an uncompressed
page frame exists, or NULL.
page frame exists, or NULL. Note: even though bpage is not declared a
const we don't update its value. It is safe to make this pure.
@return control block, or NULL */
UNIV_INLINE
buf_block_t*
@ -986,8 +1123,7 @@ UNIV_INTERN
void
buf_page_io_complete(
/*=================*/
buf_page_t* bpage, /*!< in: pointer to the block in question */
trx_t* trx);
buf_page_t* bpage); /*!< in: pointer to the block in question */
/********************************************************************//**
Calculates a folded value of a file page address to use in the page hash
table.
@ -999,15 +1135,81 @@ buf_page_address_fold(
ulint space, /*!< in: space id */
ulint offset) /*!< in: offset of the page within space */
__attribute__((const));
/********************************************************************//**
Calculates the index of a buffer pool to the buf_pool[] array.
@return the position of the buffer pool in buf_pool[] */
UNIV_INLINE
ulint
buf_pool_index(
/*===========*/
const buf_pool_t* buf_pool) /*!< in: buffer pool */
__attribute__((nonnull, const));
/********************************************************************//**
*/
UNIV_INTERN
buf_block_t*
buf_page_from_array(
/*================*/
buf_pool_t* buf_pool,
ulint n_block);
/******************************************************************//**
Returns the buffer pool instance given a page instance
@return buf_pool */
UNIV_INLINE
buf_pool_t*
buf_pool_from_bpage(
/*================*/
const buf_page_t* bpage); /*!< in: buffer pool page */
/******************************************************************//**
Returns the buffer pool instance given a block instance
@return buf_pool */
UNIV_INLINE
buf_pool_t*
buf_pool_from_block(
/*================*/
const buf_block_t* block); /*!< in: block */
/******************************************************************//**
Returns the buffer pool instance given space and offset of page
@return buffer pool */
UNIV_INLINE
buf_pool_t*
buf_pool_get(
/*==========*/
ulint space, /*!< in: space id */
ulint offset);/*!< in: offset of the page within space */
/******************************************************************//**
Returns the buffer pool instance given its array index
@return buffer pool */
UNIV_INLINE
buf_pool_t*
buf_pool_from_array(
/*================*/
ulint index); /*!< in: array index to get
buffer pool instance from */
/******************************************************************//**
Returns the control block of a file page, NULL if not found.
@return block, NULL if not found */
UNIV_INLINE
buf_page_t*
buf_page_hash_get_low(
/*==================*/
buf_pool_t* buf_pool, /*!< buffer pool instance */
ulint space, /*!< in: space id */
ulint offset, /*!< in: offset of the page
within space */
ulint fold); /*!< in: buf_page_address_fold(
space, offset) */
/******************************************************************//**
Returns the control block of a file page, NULL if not found.
@return block, NULL if not found or not a real control block */
UNIV_INLINE
buf_page_t*
buf_page_hash_get(
/*==============*/
ulint space, /*!< in: space id */
ulint offset);/*!< in: offset of the page within space */
buf_pool_t* buf_pool, /*!< in: buffer pool instance */
ulint space, /*!< in: space id */
ulint offset); /*!< in: offset of the page
within space */
/******************************************************************//**
Returns the control block of a file page, NULL if not found
or an uncompressed page frame does not exist.
@ -1016,8 +1218,10 @@ UNIV_INLINE
buf_block_t*
buf_block_hash_get(
/*===============*/
ulint space, /*!< in: space id */
ulint offset);/*!< in: offset of the page within space */
buf_pool_t* buf_pool, /*!< in: buffer pool instance */
ulint space, /*!< in: space id */
ulint offset); /*!< in: offset of the page
within space */
/*********************************************************************//**
Gets the current length of the free list of buffer blocks.
@return length of the free list */
@ -1025,8 +1229,67 @@ UNIV_INTERN
ulint
buf_get_free_list_len(void);
/*=======================*/
#endif /* !UNIV_HOTBACKUP */
/********************************************************************
Determine if a block is a sentinel for a buffer pool watch.
@return TRUE if a sentinel for a buffer pool watch, FALSE if not */
UNIV_INTERN
ibool
buf_pool_watch_is_sentinel(
/*=======================*/
buf_pool_t* buf_pool, /*!< buffer pool instance */
const buf_page_t* bpage) /*!< in: block */
__attribute__((nonnull, warn_unused_result));
/****************************************************************//**
Add watch for the given page to be read in. Caller must have the buffer pool
@return NULL if watch set, block if the page is in the buffer pool */
UNIV_INTERN
buf_page_t*
buf_pool_watch_set(
/*===============*/
ulint space, /*!< in: space id */
ulint offset, /*!< in: page number */
ulint fold) /*!< in: buf_page_address_fold(space, offset) */
__attribute__((warn_unused_result));
/****************************************************************//**
Stop watching if the page has been read in.
buf_pool_watch_set(space,offset) must have returned NULL before. */
UNIV_INTERN
void
buf_pool_watch_unset(
/*=================*/
ulint space, /*!< in: space id */
ulint offset);/*!< in: page number */
/****************************************************************//**
Check if the page has been read in.
This may only be called after buf_pool_watch_set(space,offset)
has returned NULL and before invoking buf_pool_watch_unset(space,offset).
@return FALSE if the given page was not read in, TRUE if it was */
UNIV_INTERN
ibool
buf_pool_watch_occurred(
/*====================*/
ulint space, /*!< in: space id */
ulint offset) /*!< in: page number */
__attribute__((warn_unused_result));
/********************************************************************//**
Get total buffer pool statistics. */
UNIV_INTERN
void
buf_get_total_list_len(
/*===================*/
ulint* LRU_len, /*!< out: length of all LRU lists */
ulint* free_len, /*!< out: length of all free lists */
ulint* flush_list_len);/*!< out: length of all flush lists */
/********************************************************************//**
Get total buffer pool statistics. */
UNIV_INTERN
void
buf_get_total_stat(
/*===============*/
buf_pool_stat_t*tot_stat); /*!< out: buffer pool stats */
#endif /* !UNIV_HOTBACKUP */
/** The common buffer control block structure
for compressed and uncompressed frames */
@ -1035,18 +1298,18 @@ struct buf_page_struct{
/** @name General fields
None of these bit-fields must be modified without holding
buf_page_get_mutex() [buf_block_struct::mutex or
buf_pool_zip_mutex], since they can be stored in the same
buf_pool->zip_mutex], since they can be stored in the same
machine word. Some of these fields are additionally protected
by buf_pool_mutex. */
by buf_pool->mutex. */
/* @{ */
unsigned space:32; /*!< tablespace id; also protected
by buf_pool_mutex. */
by buf_pool->mutex. */
unsigned offset:32; /*!< page number; also protected
by buf_pool_mutex. */
by buf_pool->mutex. */
unsigned state:3; /*!< state of the control block; also
protected by buf_pool_mutex.
protected by buf_pool->mutex.
State transitions from
BUF_BLOCK_READY_FOR_USE to
BUF_BLOCK_MEMORY need not be
@ -1058,15 +1321,23 @@ struct buf_page_struct{
flush_type.
@see enum buf_flush */
unsigned io_fix:2; /*!< type of pending I/O operation;
also protected by buf_pool_mutex
also protected by buf_pool->mutex
@see enum buf_io_fix */
unsigned buf_fix_count:25;/*!< count of how manyfold this block
unsigned buf_fix_count:19;/*!< count of how manyfold this block
is currently bufferfixed */
unsigned buf_pool_index:6;/*!< index number of the buffer pool
that this block belongs to */
# if MAX_BUFFER_POOLS > 64
# error "MAX_BUFFER_POOLS > 64; redefine buf_pool_index:6"
# endif
/* @} */
#endif /* !UNIV_HOTBACKUP */
page_zip_des_t zip; /*!< compressed page; zip.data
(but not the data it points to) is
also protected by buf_pool_mutex */
also protected by buf_pool->mutex;
state == BUF_BLOCK_ZIP_PAGE and
zip.data == NULL means an active
buf_pool->watch */
#ifndef UNIV_HOTBACKUP
buf_page_t* hash; /*!< node used in chaining to
buf_pool->page_hash or
@ -1077,14 +1348,16 @@ struct buf_page_struct{
#endif /* UNIV_DEBUG */
/** @name Page flushing fields
All these are protected by buf_pool_mutex. */
All these are protected by buf_pool->mutex. */
/* @{ */
/* UT_LIST_NODE_T(buf_page_t) list; */
/*!< based on state, this is a
list node, protected only by
buf_pool_mutex, in one of the
following lists in buf_pool:
list node, protected either by
buf_pool->mutex or by
buf_pool->flush_list_mutex,
in one of the following lists in
buf_pool:
- BUF_BLOCK_NOT_USED: free
- BUF_BLOCK_FILE_PAGE: flush_list
@ -1092,6 +1365,12 @@ struct buf_page_struct{
- BUF_BLOCK_ZIP_PAGE: zip_clean
- BUF_BLOCK_ZIP_FREE: zip_free[]
If bpage is part of flush_list
then the node pointers are
covered by buf_pool->flush_list_mutex.
Otherwise these pointers are
protected by buf_pool->mutex.
The contents of the list node
is undefined if !in_flush_list
&& state == BUF_BLOCK_FILE_PAGE,
@ -1106,12 +1385,18 @@ struct buf_page_struct{
UT_LIST_NODE_T(buf_page_t) zip_list; /* zip_clean or zip_free[] */
#ifdef UNIV_DEBUG
ibool in_flush_list; /*!< TRUE if in buf_pool->flush_list;
when buf_pool_mutex is free, the
following should hold: in_flush_list
when buf_pool->flush_list_mutex is
free, the following should hold:
in_flush_list
== (state == BUF_BLOCK_FILE_PAGE
|| state == BUF_BLOCK_ZIP_DIRTY) */
|| state == BUF_BLOCK_ZIP_DIRTY)
Writes to this field must be
covered by both block->mutex
and buf_pool->flush_list_mutex. Hence
reads can happen while holding
any one of the two mutexes */
ibool in_free_list; /*!< TRUE if in buf_pool->free; when
buf_pool_mutex is free, the following
buf_pool->mutex is free, the following
should hold: in_free_list
== (state == BUF_BLOCK_NOT_USED) */
#endif /* UNIV_DEBUG */
@ -1119,7 +1404,8 @@ struct buf_page_struct{
/*!< log sequence number of
the youngest modification to
this block, zero if not
modified */
modified. Protected by block
mutex */
ib_uint64_t oldest_modification;
/*!< log sequence number of
the START of the log entry
@ -1127,11 +1413,16 @@ struct buf_page_struct{
modification to this block
which has not yet been flushed
on disk; zero if all
modifications are on disk */
modifications are on disk.
Writes to this field must be
covered by both block->mutex
and buf_pool->flush_list_mutex. Hence
reads can happen while holding
any one of the two mutexes */
/* @} */
/** @name LRU replacement algorithm fields
These fields are protected by buf_pool_mutex only (not
buf_pool_zip_mutex or buf_block_struct::mutex). */
These fields are protected by buf_pool->mutex only (not
buf_pool->zip_mutex or buf_block_struct::mutex). */
/* @{ */
UT_LIST_NODE_T(buf_page_t) LRU;
@ -1202,7 +1493,7 @@ struct buf_block_struct{
unsigned lock_hash_val:32;/*!< hashed value of the page address
in the record lock hash table;
protected by buf_block_t::lock
(or buf_block_t::mutex, buf_pool_mutex
(or buf_block_t::mutex, buf_pool->mutex
in buf_page_get_gen(),
buf_page_init_for_read()
and buf_page_create()) */
@ -1263,7 +1554,7 @@ struct buf_block_struct{
pointers in the adaptive hash index
pointing to this frame */
#endif /* UNIV_AHI_DEBUG || UNIV_DEBUG */
unsigned is_hashed:1; /*!< TRUE if hash index has
volatile unsigned is_hashed:1; /*!< TRUE if hash index has
already been built on this
page; note that it does not
guarantee that the index is
@ -1277,6 +1568,7 @@ struct buf_block_struct{
unsigned curr_left_side:1;/*!< TRUE or FALSE in hash indexing */
dict_index_t* index; /*!< Index for which the adaptive
hash index has been created. */
volatile rw_lock_t* btr_search_latch;
/* @} */
# ifdef UNIV_SYNC_DEBUG
/** @name Debug fields */
@ -1301,10 +1593,7 @@ struct buf_block_struct{
/**********************************************************************//**
Compute the hash fold value for blocks in buf_pool->zip_hash. */
/* @{ */
/* the fold should be relative when srv_buffer_pool_shm_key is enabled */
#define BUF_POOL_ZIP_FOLD_PTR(ptr) (!srv_buffer_pool_shm_key\
?((ulint) (ptr) / UNIV_PAGE_SIZE)\
:((ulint) ((byte*)ptr - (byte*)(buf_pool->chunks->blocks->frame)) / UNIV_PAGE_SIZE))
#define BUF_POOL_ZIP_FOLD_PTR(ptr) ((ulint) (ptr) / UNIV_PAGE_SIZE)
#define BUF_POOL_ZIP_FOLD(b) BUF_POOL_ZIP_FOLD_PTR((b)->frame)
#define BUF_POOL_ZIP_FOLD_BPAGE(b) BUF_POOL_ZIP_FOLD((buf_block_t*) (b))
/* @} */
@ -1343,6 +1632,16 @@ struct buf_pool_stat_struct{
buf_page_peek_if_too_old() */
};
/** Statistics of buddy blocks of a given size. */
struct buf_buddy_stat_struct {
/** Number of blocks allocated from the buddy system. */
ulint used;
/** Number of blocks relocated by the buddy system. */
ib_uint64_t relocated;
/** Total duration of block relocations, in microseconds. */
ib_uint64_t relocated_usec;
};
/** @brief The buffer pool structure.
NOTE! The definition appears here only for other modules of this
@ -1352,7 +1651,30 @@ struct buf_pool_struct{
/** @name General fields */
/* @{ */
mutex_t mutex; /*!< Buffer pool mutex of this
instance */
mutex_t zip_mutex; /*!< Zip mutex of this buffer
pool instance, protects compressed
only pages (of type buf_page_t, not
buf_block_t */
mutex_t LRU_list_mutex;
rw_lock_t page_hash_latch;
mutex_t free_list_mutex;
mutex_t zip_free_mutex;
mutex_t zip_hash_mutex;
ulint instance_no; /*!< Array index of this buffer
pool instance */
ulint old_pool_size; /*!< Old pool size in bytes */
ulint curr_pool_size; /*!< Current pool size in bytes */
ulint LRU_old_ratio; /*!< Reserve this much of the buffer
pool for "old" blocks */
#ifdef UNIV_DEBUG
ulint buddy_n_frames; /*!< Number of frames allocated from
the buffer pool to the buddy system */
#endif
#if defined UNIV_DEBUG || defined UNIV_BUF_DEBUG
ulint mutex_exit_forbidden; /*!< Forbid release mutex */
#endif
ulint n_chunks; /*!< number of buffer pool chunks */
buf_chunk_t* chunks; /*!< buffer pool chunks */
ulint curr_size; /*!< current pool size in pages */
@ -1364,12 +1686,16 @@ struct buf_pool_struct{
whose frames are allocated to the
zip buddy system,
indexed by block->frame */
ulint n_pend_reads; /*!< number of pending read operations */
ulint n_pend_reads; /*!< number of pending read
operations */
ulint n_pend_unzip; /*!< number of pending decompressions */
time_t last_printout_time;
/*!< when buf_print_io was last time
called */
buf_buddy_stat_t buddy_stat[BUF_BUDDY_SIZES_MAX + 1];
/*!< Statistics of buddy system,
indexed by block size */
buf_pool_stat_t stat; /*!< current statistics */
buf_pool_stat_t old_stat; /*!< old statistics */
@ -1379,6 +1705,13 @@ struct buf_pool_struct{
/* @{ */
mutex_t flush_list_mutex;/*!< mutex protecting the
flush list access. This mutex
protects flush_list, flush_rbt
and bpage::list pointers when
the bpage is on flush_list. It
also protects writes to
bpage::oldest_modification */
UT_LIST_BASE_NODE_T(buf_page_t) flush_list;
/*!< base node of the modified block
list */
@ -1392,7 +1725,7 @@ struct buf_pool_struct{
/*!< this is in the set state
when there is no flush batch
of the given type running */
ib_rbt_t* flush_rbt; /* !< a red-black tree is used
ib_rbt_t* flush_rbt; /*!< a red-black tree is used
exclusively during recovery to
speed up insertions in the
flush_list. This tree contains
@ -1404,7 +1737,8 @@ struct buf_pool_struct{
also be on the flush_list.
This tree is relevant only in
recovery and is set to NULL
once the recovery is over. */
once the recovery is over.
Protected by flush_list_mutex */
ulint freed_page_clock;/*!< a sequence number used
to count the number of buffer
blocks removed from the end of
@ -1418,8 +1752,8 @@ struct buf_pool_struct{
this is incremented by one; this is
set to zero when a buffer block is
allocated */
/* @} */
/** @name LRU replacement algorithm fields */
/* @{ */
@ -1457,6 +1791,12 @@ struct buf_pool_struct{
/*!< unmodified compressed pages */
UT_LIST_BASE_NODE_T(buf_page_t) zip_free[BUF_BUDDY_SIZES_MAX];
/*!< buddy free lists */
buf_page_t watch[BUF_POOL_WATCH_SIZE];
/*!< Sentinel records for buffer
pool watches. Protected by
buf_pool->mutex. */
//#if BUF_BUDDY_HIGH != UNIV_PAGE_SIZE
//# error "BUF_BUDDY_HIGH != UNIV_PAGE_SIZE"
//#endif
@ -1466,58 +1806,56 @@ struct buf_pool_struct{
/* @} */
};
/** mutex protecting the buffer pool struct and control blocks, except the
read-write lock in them */
extern mutex_t buf_pool_mutex;
extern mutex_t LRU_list_mutex;
extern mutex_t flush_list_mutex;
extern rw_lock_t page_hash_latch;
extern mutex_t free_list_mutex;
extern mutex_t zip_free_mutex;
extern mutex_t zip_hash_mutex;
/** mutex protecting the control blocks of compressed-only pages
(of type buf_page_t, not buf_block_t) */
extern mutex_t buf_pool_zip_mutex;
/** @name Accessors for buf_pool_mutex.
Use these instead of accessing buf_pool_mutex directly. */
/** @name Accessors for buf_pool->mutex.
Use these instead of accessing buf_pool->mutex directly. */
/* @{ */
/** Test if buf_pool_mutex is owned. */
#define buf_pool_mutex_own() mutex_own(&buf_pool_mutex)
/** Acquire the buffer pool mutex. */
#define buf_pool_mutex_enter() do { \
ut_ad(!mutex_own(&buf_pool_zip_mutex)); \
mutex_enter(&buf_pool_mutex); \
/** Test if a buffer pool mutex is owned. */
#define buf_pool_mutex_own(b) mutex_own(&b->mutex)
/** Acquire a buffer pool mutex. */
/* the buf_pool_mutex is changed the latch order */
#define buf_pool_mutex_enter(b) do { \
mutex_enter(&b->mutex); \
} while (0)
/** Test if flush list mutex is owned. */
#define buf_flush_list_mutex_own(b) mutex_own(&b->flush_list_mutex)
/** Acquire the flush list mutex. */
#define buf_flush_list_mutex_enter(b) do { \
mutex_enter(&b->flush_list_mutex); \
} while (0)
/** Release the flush list mutex. */
# define buf_flush_list_mutex_exit(b) do { \
mutex_exit(&b->flush_list_mutex); \
} while (0)
#if defined UNIV_DEBUG || defined UNIV_BUF_DEBUG
/** Flag to forbid the release of the buffer pool mutex.
Protected by buf_pool_mutex. */
extern ulint buf_pool_mutex_exit_forbidden;
/** Forbid the release of the buffer pool mutex. */
# define buf_pool_mutex_exit_forbid() do { \
ut_ad(buf_pool_mutex_own()); \
buf_pool_mutex_exit_forbidden++; \
# define buf_pool_mutex_exit_forbid(b) do { \
ut_ad(buf_pool_mutex_own(b)); \
b->mutex_exit_forbidden++; \
} while (0)
/** Allow the release of the buffer pool mutex. */
# define buf_pool_mutex_exit_allow() do { \
ut_ad(buf_pool_mutex_own()); \
ut_a(buf_pool_mutex_exit_forbidden); \
buf_pool_mutex_exit_forbidden--; \
# define buf_pool_mutex_exit_allow(b) do { \
ut_ad(buf_pool_mutex_own(b)); \
ut_a(b->mutex_exit_forbidden); \
b->mutex_exit_forbidden--; \
} while (0)
/** Release the buffer pool mutex. */
# define buf_pool_mutex_exit() do { \
ut_a(!buf_pool_mutex_exit_forbidden); \
mutex_exit(&buf_pool_mutex); \
# define buf_pool_mutex_exit(b) do { \
ut_a(!b->mutex_exit_forbidden); \
mutex_exit(&b->mutex); \
} while (0)
#else
/** Forbid the release of the buffer pool mutex. */
# define buf_pool_mutex_exit_forbid() ((void) 0)
# define buf_pool_mutex_exit_forbid(b) ((void) 0)
/** Allow the release of the buffer pool mutex. */
# define buf_pool_mutex_exit_allow() ((void) 0)
# define buf_pool_mutex_exit_allow(b) ((void) 0)
/** Release the buffer pool mutex. */
# define buf_pool_mutex_exit() mutex_exit(&buf_pool_mutex)
# define buf_pool_mutex_exit(b) mutex_exit(&b->mutex)
#endif
#endif /* !UNIV_HOTBACKUP */
/* @} */

View file

@ -31,11 +31,74 @@ Created 11/5/1995 Heikki Tuuri
*******************************************************/
#include "mtr0mtr.h"
#ifndef UNIV_HOTBACKUP
#include "buf0flu.h"
#include "buf0lru.h"
#include "buf0rea.h"
#include "srv0srv.h"
/*********************************************************************//**
Gets the current size of buffer buf_pool in bytes.
@return size in bytes */
UNIV_INLINE
ulint
buf_pool_get_curr_size(void)
/*========================*/
{
return(srv_buf_pool_curr_size);
}
/********************************************************************//**
Calculates the index of a buffer pool to the buf_pool[] array.
@return the position of the buffer pool in buf_pool[] */
UNIV_INLINE
ulint
buf_pool_index(
/*===========*/
const buf_pool_t* buf_pool) /*!< in: buffer pool */
{
ulint i = buf_pool - buf_pool_ptr;
ut_ad(i < MAX_BUFFER_POOLS);
ut_ad(i < srv_buf_pool_instances);
return(i);
}
/******************************************************************//**
Returns the buffer pool instance given a page instance
@return buf_pool */
UNIV_INLINE
buf_pool_t*
buf_pool_from_bpage(
/*================*/
const buf_page_t* bpage) /*!< in: buffer pool page */
{
ulint i;
i = bpage->buf_pool_index;
ut_ad(i < srv_buf_pool_instances);
return(&buf_pool_ptr[i]);
}
/******************************************************************//**
Returns the buffer pool instance given a block instance
@return buf_pool */
UNIV_INLINE
buf_pool_t*
buf_pool_from_block(
/*================*/
const buf_block_t* block) /*!< in: block */
{
return(buf_pool_from_bpage(&block->page));
}
/*********************************************************************//**
Gets the current size of buffer buf_pool in pages.
@return size in pages*/
UNIV_INLINE
ulint
buf_pool_get_n_pages(void)
/*======================*/
{
return(buf_pool_get_curr_size() / UNIV_PAGE_SIZE);
}
/********************************************************************//**
Reads the freed_page_clock of a buffer block.
@return freed_page_clock */
@ -45,7 +108,7 @@ buf_page_get_freed_page_clock(
/*==========================*/
const buf_page_t* bpage) /*!< in: block */
{
/* This is sometimes read without holding buf_pool_mutex. */
/* This is sometimes read without holding buf_pool->mutex. */
return(bpage->freed_page_clock);
}
@ -72,6 +135,8 @@ buf_page_peek_if_too_old(
/*=====================*/
const buf_page_t* bpage) /*!< in: block to make younger */
{
buf_pool_t* buf_pool = buf_pool_from_bpage(bpage);
if (UNIV_UNLIKELY(buf_pool->freed_page_clock == 0)) {
/* If eviction has not started yet, do not update the
statistics or move blocks in the LRU list. This is
@ -93,61 +158,11 @@ buf_page_peek_if_too_old(
return((buf_pool->freed_page_clock & ((1UL << 31) - 1))
> ((ulint) bpage->freed_page_clock
+ (buf_pool->curr_size
* (BUF_LRU_OLD_RATIO_DIV - buf_LRU_old_ratio)
* (BUF_LRU_OLD_RATIO_DIV - buf_pool->LRU_old_ratio)
/ (BUF_LRU_OLD_RATIO_DIV * 4))));
}
}
/*********************************************************************//**
Gets the current size of buffer buf_pool in bytes.
@return size in bytes */
UNIV_INLINE
ulint
buf_pool_get_curr_size(void)
/*========================*/
{
return(buf_pool->curr_size * UNIV_PAGE_SIZE);
}
/********************************************************************//**
Gets the smallest oldest_modification lsn for any page in the pool. Returns
zero if all modified pages have been flushed to disk.
@return oldest modification in pool, zero if none */
UNIV_INLINE
ib_uint64_t
buf_pool_get_oldest_modification(void)
/*==================================*/
{
buf_page_t* bpage;
ib_uint64_t lsn;
try_again:
//buf_pool_mutex_enter();
mutex_enter(&flush_list_mutex);
bpage = UT_LIST_GET_LAST(buf_pool->flush_list);
if (bpage == NULL) {
lsn = 0;
} else {
ut_ad(bpage->in_flush_list);
lsn = bpage->oldest_modification;
if (lsn == 0) {
mutex_exit(&flush_list_mutex);
goto try_again;
}
}
//buf_pool_mutex_exit();
mutex_exit(&flush_list_mutex);
/* The returned answer may be out of date: the flush_list can
change after the mutex has been released. */
return(lsn);
}
#endif /* !UNIV_HOTBACKUP */
/*********************************************************************//**
Gets the state of a block.
@return state */
@ -300,13 +315,22 @@ buf_page_get_mutex(
/*===============*/
const buf_page_t* bpage) /*!< in: pointer to control block */
{
buf_pool_t* buf_pool = buf_pool_from_bpage(bpage);
if (/*equivalent to buf_pool_watch_is_sentinel(buf_pool, bpage)*/
bpage >= &buf_pool->watch[0]
&& bpage < &buf_pool->watch[BUF_POOL_WATCH_SIZE]) {
/* TODO: this code is the interim. should be confirmed later. */
return(&buf_pool->zip_mutex);
}
switch (buf_page_get_state(bpage)) {
case BUF_BLOCK_ZIP_FREE:
/* ut_error; */ /* optimistic */
return(NULL);
case BUF_BLOCK_ZIP_PAGE:
case BUF_BLOCK_ZIP_DIRTY:
return(&buf_pool_zip_mutex);
return(&buf_pool->zip_mutex);
default:
return(&((buf_block_t*) bpage)->mutex);
}
@ -415,7 +439,7 @@ Gets the io_fix state of a block.
UNIV_INLINE
enum buf_io_fix
buf_block_get_io_fix(
/*================*/
/*=================*/
const buf_block_t* block) /*!< in: pointer to the control block */
{
return(buf_page_get_io_fix(&block->page));
@ -430,7 +454,10 @@ buf_page_set_io_fix(
buf_page_t* bpage, /*!< in/out: control block */
enum buf_io_fix io_fix) /*!< in: io_fix state */
{
//ut_ad(buf_pool_mutex_own());
#ifdef UNIV_DEBUG
//buf_pool_t* buf_pool = buf_pool_from_bpage(bpage);
//ut_ad(buf_pool_mutex_own(buf_pool));
#endif
ut_ad(mutex_own(buf_page_get_mutex(bpage)));
bpage->io_fix = io_fix;
@ -458,10 +485,12 @@ buf_page_can_relocate(
/*==================*/
const buf_page_t* bpage) /*!< control block being relocated */
{
//ut_ad(buf_pool_mutex_own());
#ifdef UNIV_DEBUG
//buf_pool_t* buf_pool = buf_pool_from_bpage(bpage);
//ut_ad(buf_pool_mutex_own(buf_pool));
#endif
ut_ad(mutex_own(buf_page_get_mutex(bpage)));
ut_ad(buf_page_in_file(bpage));
/* optimistic */
//ut_ad(bpage->in_LRU_list);
return(bpage->in_LRU_list && bpage->io_fix == BUF_IO_NONE
@ -477,8 +506,11 @@ buf_page_is_old(
/*============*/
const buf_page_t* bpage) /*!< in: control block */
{
#ifdef UNIV_DEBUG
//buf_pool_t* buf_pool = buf_pool_from_bpage(bpage);
//ut_ad(buf_pool_mutex_own(buf_pool));
#endif
ut_ad(buf_page_in_file(bpage));
//ut_ad(buf_pool_mutex_own()); /* This is used in optimistic */
return(bpage->old);
}
@ -492,9 +524,12 @@ buf_page_set_old(
buf_page_t* bpage, /*!< in/out: control block */
ibool old) /*!< in: old */
{
#ifdef UNIV_DEBUG
buf_pool_t* buf_pool = buf_pool_from_bpage(bpage);
#endif /* UNIV_DEBUG */
ut_a(buf_page_in_file(bpage));
//ut_ad(buf_pool_mutex_own());
ut_ad(mutex_own(&LRU_list_mutex));
//ut_ad(buf_pool_mutex_own(buf_pool));
ut_ad(mutex_own(&buf_pool->LRU_list_mutex));
ut_ad(bpage->in_LRU_list);
#ifdef UNIV_LRU_DEBUG
@ -540,9 +575,12 @@ buf_page_set_accessed(
buf_page_t* bpage, /*!< in/out: control block */
ulint time_ms) /*!< in: ut_time_ms() */
{
ut_a(buf_page_in_file(bpage));
//ut_ad(buf_pool_mutex_own());
#ifdef UNIV_DEBUG
//buf_pool_t* buf_pool = buf_pool_from_bpage(bpage);
//ut_ad(buf_pool_mutex_own(buf_pool));
#endif
ut_ad(mutex_own(buf_page_get_mutex(bpage)));
ut_a(buf_page_in_file(bpage));
if (!bpage->access_time) {
/* Make this the time of the first access. */
@ -753,23 +791,6 @@ buf_block_get_lock_hash_val(
return(block->lock_hash_val);
}
/********************************************************************//**
Allocates a buffer block.
@return own: the allocated block, in state BUF_BLOCK_MEMORY */
UNIV_INLINE
buf_block_t*
buf_block_alloc(void)
/*=================*/
{
buf_block_t* block;
block = buf_LRU_get_free_block();
buf_block_set_state(block, BUF_BLOCK_MEMORY);
return(block);
}
/********************************************************************//**
Frees a buffer block which does not contain a file page. */
UNIV_INLINE
@ -778,7 +799,9 @@ buf_block_free(
/*===========*/
buf_block_t* block) /*!< in, own: block to be freed */
{
//buf_pool_mutex_enter();
//buf_pool_t* buf_pool = buf_pool_from_bpage((buf_page_t*)block);
//buf_pool_mutex_enter(buf_pool);
mutex_enter(&block->mutex);
@ -788,7 +811,7 @@ buf_block_free(
mutex_exit(&block->mutex);
//buf_pool_mutex_exit();
//buf_pool_mutex_exit(buf_pool);
}
#endif /* !UNIV_HOTBACKUP */
@ -862,7 +885,9 @@ buf_block_modify_clock_inc(
buf_block_t* block) /*!< in: block */
{
#ifdef UNIV_SYNC_DEBUG
ut_ad((mutex_own(&LRU_list_mutex)
buf_pool_t* buf_pool = buf_pool_from_bpage((buf_page_t*)block);
ut_ad((mutex_own(&buf_pool->LRU_list_mutex)
&& (block->page.buf_fix_count == 0))
|| rw_lock_own(&(block->lock), RW_LOCK_EXCLUSIVE));
#endif /* UNIV_SYNC_DEBUG */
@ -940,30 +965,67 @@ buf_block_buf_fix_dec(
#endif
}
/******************************************************************//**
Returns the buffer pool instance given space and offset of page
@return buffer pool */
UNIV_INLINE
buf_pool_t*
buf_pool_get(
/*==========*/
ulint space, /*!< in: space id */
ulint offset) /*!< in: offset of the page within space */
{
ulint fold;
ulint index;
ulint ignored_offset;
ignored_offset = offset >> 6; /* 2log of BUF_READ_AHEAD_AREA (64)*/
fold = buf_page_address_fold(space, ignored_offset);
index = fold % srv_buf_pool_instances;
return(&buf_pool_ptr[index]);
}
/******************************************************************//**
Returns the buffer pool instance given its array index
@return buffer pool */
UNIV_INLINE
buf_pool_t*
buf_pool_from_array(
/*================*/
ulint index) /*!< in: array index to get
buffer pool instance from */
{
ut_ad(index < MAX_BUFFER_POOLS);
ut_ad(index < srv_buf_pool_instances);
return(&buf_pool_ptr[index]);
}
/******************************************************************//**
Returns the control block of a file page, NULL if not found.
@return block, NULL if not found */
UNIV_INLINE
buf_page_t*
buf_page_hash_get(
/*==============*/
ulint space, /*!< in: space id */
ulint offset) /*!< in: offset of the page within space */
buf_page_hash_get_low(
/*==================*/
buf_pool_t* buf_pool, /*!< buffer pool instance */
ulint space, /*!< in: space id */
ulint offset, /*!< in: offset of the page
within space */
ulint fold) /*!< in: buf_page_address_fold(
space, offset) */
{
buf_page_t* bpage;
ulint fold;
ut_ad(buf_pool);
//ut_ad(buf_pool_mutex_own());
//ut_ad(buf_pool_mutex_own(buf_pool));
#ifdef UNIV_SYNC_DEBUG
ut_ad(rw_lock_own(&page_hash_latch, RW_LOCK_EX)
|| rw_lock_own(&page_hash_latch, RW_LOCK_SHARED));
ut_ad(rw_lock_own(&buf_pool->page_hash_latch, RW_LOCK_EX)
|| rw_lock_own(&buf_pool->page_hash_latch, RW_LOCK_SHARED));
#endif
ut_ad(fold == buf_page_address_fold(space, offset));
/* Look for the page in the hash table */
fold = buf_page_address_fold(space, offset);
HASH_SEARCH(hash, buf_pool->page_hash, fold, buf_page_t*, bpage,
ut_ad(bpage->in_page_hash && !bpage->in_zip_hash
&& buf_page_in_file(bpage)),
@ -983,6 +1045,30 @@ buf_page_hash_get(
return(bpage);
}
/******************************************************************//**
Returns the control block of a file page, NULL if not found.
@return block, NULL if not found or not a real control block */
UNIV_INLINE
buf_page_t*
buf_page_hash_get(
/*==============*/
buf_pool_t* buf_pool, /*!< in: buffer pool instance */
ulint space, /*!< in: space id */
ulint offset) /*!< in: offset of the page
within space */
{
buf_page_t* bpage;
ulint fold = buf_page_address_fold(space, offset);
bpage = buf_page_hash_get_low(buf_pool, space, offset, fold);
if (bpage && buf_pool_watch_is_sentinel(buf_pool, bpage)) {
bpage = NULL;
}
return(bpage);
}
/******************************************************************//**
Returns the control block of a file page, NULL if not found
or an uncompressed page frame does not exist.
@ -991,10 +1077,16 @@ UNIV_INLINE
buf_block_t*
buf_block_hash_get(
/*===============*/
ulint space, /*!< in: space id */
ulint offset) /*!< in: offset of the page within space */
buf_pool_t* buf_pool, /*!< in: buffer pool instance */
ulint space, /*!< in: space id */
ulint offset) /*!< in: offset of the page
within space */
{
return(buf_page_get_block(buf_page_hash_get(space, offset)));
buf_block_t* block;
block = buf_page_get_block(buf_page_hash_get(buf_pool, space, offset));
return(block);
}
/********************************************************************//**
@ -1012,14 +1104,15 @@ buf_page_peek(
ulint offset) /*!< in: page number */
{
const buf_page_t* bpage;
buf_pool_t* buf_pool = buf_pool_get(space, offset);
//buf_pool_mutex_enter();
rw_lock_s_lock(&page_hash_latch);
//buf_pool_mutex_enter(buf_pool);
rw_lock_s_lock(&buf_pool->page_hash_latch);
bpage = buf_page_hash_get(space, offset);
bpage = buf_page_hash_get(buf_pool, space, offset);
//buf_pool_mutex_exit();
rw_lock_s_unlock(&page_hash_latch);
//buf_pool_mutex_exit(buf_pool);
rw_lock_s_unlock(&buf_pool->page_hash_latch);
return(bpage != NULL);
}
@ -1033,6 +1126,7 @@ buf_page_release_zip(
buf_page_t* bpage) /*!< in: buffer block */
{
buf_block_t* block;
buf_pool_t* buf_pool = buf_pool_from_bpage(bpage);
ut_ad(bpage);
ut_a(bpage->buf_fix_count > 0);
@ -1040,9 +1134,9 @@ buf_page_release_zip(
switch (buf_page_get_state(bpage)) {
case BUF_BLOCK_ZIP_PAGE:
case BUF_BLOCK_ZIP_DIRTY:
mutex_enter(&buf_pool_zip_mutex);
mutex_enter(&buf_pool->zip_mutex);
bpage->buf_fix_count--;
mutex_exit(&buf_pool_zip_mutex);
mutex_exit(&buf_pool->zip_mutex);
return;
case BUF_BLOCK_FILE_PAGE:
block = (buf_block_t*) bpage;
@ -1061,6 +1155,7 @@ buf_page_release_zip(
break;
}
ut_error;
}
@ -1072,24 +1167,14 @@ void
buf_page_release(
/*=============*/
buf_block_t* block, /*!< in: buffer block */
ulint rw_latch, /*!< in: RW_S_LATCH, RW_X_LATCH,
ulint rw_latch) /*!< in: RW_S_LATCH, RW_X_LATCH,
RW_NO_LATCH */
mtr_t* mtr __attribute__((unused))) /*!< in: mtr */
{
ut_ad(block);
ut_a(buf_block_get_state(block) == BUF_BLOCK_FILE_PAGE);
ut_a(block->page.buf_fix_count > 0);
/* buf_flush_note_modification() should be called before this function. */
/*
if (rw_latch == RW_X_LATCH && mtr->modifications) {
buf_pool_mutex_enter();
buf_flush_note_modification(block, mtr);
buf_pool_mutex_exit();
}
*/
mutex_enter(&block->mutex);
#ifdef UNIV_SYNC_DEBUG
@ -1122,4 +1207,71 @@ buf_block_dbg_add_level(
sync_thread_add_level(&block->lock, level);
}
#endif /* UNIV_SYNC_DEBUG */
/********************************************************************//**
Acquire mutex on all buffer pool instances. */
UNIV_INLINE
void
buf_pool_mutex_enter_all(void)
/*==========================*/
{
ulint i;
for (i = 0; i < srv_buf_pool_instances; i++) {
buf_pool_t* buf_pool;
buf_pool = buf_pool_from_array(i);
buf_pool_mutex_enter(buf_pool);
}
}
/********************************************************************//**
Release mutex on all buffer pool instances. */
UNIV_INLINE
void
buf_pool_mutex_exit_all(void)
/*=========================*/
{
ulint i;
for (i = 0; i < srv_buf_pool_instances; i++) {
buf_pool_t* buf_pool;
buf_pool = buf_pool_from_array(i);
buf_pool_mutex_exit(buf_pool);
}
}
/********************************************************************//**
*/
UNIV_INLINE
void
buf_pool_page_hash_x_lock_all(void)
/*===============================*/
{
ulint i;
for (i = 0; i < srv_buf_pool_instances; i++) {
buf_pool_t* buf_pool;
buf_pool = buf_pool_from_array(i);
rw_lock_x_lock(&buf_pool->page_hash_latch);
}
}
/********************************************************************//**
*/
UNIV_INLINE
void
buf_pool_page_hash_x_unlock_all(void)
/*=================================*/
{
ulint i;
for (i = 0; i < srv_buf_pool_instances; i++) {
buf_pool_t* buf_pool;
buf_pool = buf_pool_from_array(i);
rw_lock_x_unlock(&buf_pool->page_hash_latch);
}
}
#endif /* !UNIV_HOTBACKUP */

View file

@ -31,6 +31,7 @@ Created 11/5/1995 Heikki Tuuri
#ifndef UNIV_HOTBACKUP
#include "mtr0types.h"
#include "buf0types.h"
#include "log0log.h"
/********************************************************************//**
Remove a block from the flush list of modified blocks. */
@ -39,7 +40,7 @@ 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. */
@ -58,12 +59,21 @@ buf_flush_write_complete(
buf_page_t* bpage); /*!< in: pointer to the block in question */
/*********************************************************************//**
Flushes pages from the end of the LRU list if there is too small
a margin of replaceable pages there. */
a margin of replaceable pages there. If buffer pool is NULL it
means flush free margin on all buffer pool instances. */
UNIV_INTERN
void
buf_flush_free_margin(
/*=======================*/
ibool wait);
/*==================*/
buf_pool_t* buf_pool,
ibool wait);
/*********************************************************************//**
Flushes pages from the end of all the LRU lists. */
UNIV_INTERN
void
buf_flush_free_margins(
/*=========================*/
ibool wait);
#endif /* !UNIV_HOTBACKUP */
/********************************************************************//**
Initializes a page for writing to the tablespace. */
@ -79,7 +89,7 @@ buf_flush_init_for_writing(
# 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
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 */
@ -87,25 +97,35 @@ 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 LRU list or flush_list.
NOTE 1: in the case of an LRU flush the calling thread may own latches to
pages: to avoid deadlocks, this function must be written so that it cannot
end up waiting for these latches! NOTE 2: in the case of a flush list flush,
the calling thread is not allowed to own any latches on pages!
This utility flushes dirty blocks from the end of the LRU list.
NOTE: The calling thread may own latches to pages: to avoid deadlocks,
this function must be written so that it cannot end up waiting for these
latches!
@return number of blocks for which the write request was queued;
ULINT_UNDEFINED if there was a flush of the same type already running */
UNIV_INTERN
ulint
buf_flush_batch(
buf_flush_LRU(
/*==========*/
buf_pool_t* buf_pool, /*!< in: buffer pool instance */
ulint min_n); /*!< in: wished minimum mumber of blocks
flushed (it is not guaranteed that the
actual number is that big, though) */
/*******************************************************************//**
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 number of blocks for which the write request was queued;
ULINT_UNDEFINED if there was a flush of the same type already running */
UNIV_INTERN
ulint
buf_flush_list(
/*============*/
enum buf_flush flush_type, /*!< in: BUF_FLUSH_LRU or
BUF_FLUSH_LIST; if BUF_FLUSH_LIST,
then the caller must not own any
latches on pages */
ulint min_n, /*!< in: wished minimum mumber of blocks
flushed (it is not guaranteed that the
actual number is that big, though) */
@ -120,7 +140,20 @@ UNIV_INTERN
void
buf_flush_wait_batch_end(
/*=====================*/
enum buf_flush type); /*!< in: BUF_FLUSH_LRU or BUF_FLUSH_LIST */
buf_pool_t* buf_pool, /*!< in: buffer pool instance */
enum buf_flush 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 */
enum buf_flush 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
@ -164,8 +197,8 @@ how much redo the workload is generating and at what rate. */
struct buf_flush_stat_struct
{
ib_uint64_t redo; /*!< amount of redo generated. */
ulint n_flushed; /*!< number of pages flushed. */
ib_uint64_t redo; /**< amount of redo generated. */
ulint n_flushed; /**< number of pages flushed. */
};
/** Statistics for selecting flush rate of dirty pages. */
@ -196,11 +229,12 @@ Validates the flush list.
@return TRUE if ok */
UNIV_INTERN
ibool
buf_flush_validate(void);
/*====================*/
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. */
@ -209,7 +243,7 @@ void
buf_flush_init_flush_rbt(void);
/*==========================*/
/******************************************************************//**
/********************************************************************//**
Frees up the red-black tree. */
UNIV_INTERN
void
@ -220,9 +254,10 @@ buf_flush_free_flush_rbt(void);
available to replacement in the free list and at the end of the LRU list (to
make sure that a read-ahead batch can be read efficiently in a single
sweep). */
#define BUF_FLUSH_FREE_BLOCK_MARGIN (5 + BUF_READ_AHEAD_AREA)
#define BUF_FLUSH_FREE_BLOCK_MARGIN(b) (5 + BUF_READ_AHEAD_AREA(b))
/** Extra margin to apply above BUF_FLUSH_FREE_BLOCK_MARGIN */
#define BUF_FLUSH_EXTRA_MARGIN (BUF_FLUSH_FREE_BLOCK_MARGIN / 4 + 100)
#define BUF_FLUSH_EXTRA_MARGIN(b) ((BUF_FLUSH_FREE_BLOCK_MARGIN(b) / 4 \
+ 100) / srv_buf_pool_instances)
#endif /* !UNIV_HOTBACKUP */
#ifndef UNIV_NONINL

View file

@ -33,7 +33,9 @@ UNIV_INTERN
void
buf_flush_insert_into_flush_list(
/*=============================*/
buf_block_t* block); /*!< in/out: block which is modified */
buf_pool_t* buf_pool, /*!< buffer pool instance */
buf_block_t* block, /*!< in/out: block which is modified */
ib_uint64_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
@ -42,7 +44,9 @@ UNIV_INTERN
void
buf_flush_insert_sorted_into_flush_list(
/*====================================*/
buf_block_t* block); /*!< in/out: block which is modified */
buf_pool_t* buf_pool, /*!< buffer pool instance */
buf_block_t* block, /*!< in/out: block which is modified */
ib_uint64_t lsn); /*!< in: oldest modification */
/********************************************************************//**
This function should be called at a mini-transaction commit, if a page was
@ -55,15 +59,7 @@ buf_flush_note_modification(
buf_block_t* block, /*!< in: block which is modified */
mtr_t* mtr) /*!< in: mtr */
{
ibool use_LRU_mutex = FALSE;
if (UT_LIST_GET_LEN(buf_pool->unzip_LRU))
use_LRU_mutex = TRUE;
if (use_LRU_mutex)
mutex_enter(&LRU_list_mutex);
mutex_enter(&block->mutex);
buf_pool_t* buf_pool = buf_pool_from_block(block);
ut_ad(block);
ut_ad(buf_block_get_state(block) == BUF_BLOCK_FILE_PAGE);
@ -71,22 +67,22 @@ buf_flush_note_modification(
#ifdef UNIV_SYNC_DEBUG
ut_ad(rw_lock_own(&(block->lock), RW_LOCK_EX));
#endif /* UNIV_SYNC_DEBUG */
//ut_ad(buf_pool_mutex_own());
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(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) {
mutex_enter(&flush_list_mutex);
block->page.oldest_modification = mtr->start_lsn;
ut_ad(block->page.oldest_modification != 0);
buf_flush_insert_into_flush_list(block);
mutex_exit(&flush_list_mutex);
buf_flush_insert_into_flush_list(
buf_pool, block, mtr->start_lsn);
} else {
ut_ad(block->page.oldest_modification <= mtr->start_lsn);
}
@ -94,9 +90,6 @@ buf_flush_note_modification(
mutex_exit(&block->mutex);
++srv_buf_pool_write_requests;
if (use_LRU_mutex)
mutex_exit(&LRU_list_mutex);
}
/********************************************************************//**
@ -111,15 +104,7 @@ buf_flush_recv_note_modification(
ib_uint64_t end_lsn) /*!< in: end lsn of the last mtr in the
set of mtr's */
{
ibool use_LRU_mutex = FALSE;
if(UT_LIST_GET_LEN(buf_pool->unzip_LRU))
use_LRU_mutex = TRUE;
if (use_LRU_mutex)
mutex_enter(&LRU_list_mutex);
mutex_enter(&(block->mutex));
buf_pool_t* buf_pool = buf_pool_from_block(block);
ut_ad(block);
ut_ad(buf_block_get_state(block) == BUF_BLOCK_FILE_PAGE);
@ -128,28 +113,24 @@ buf_flush_recv_note_modification(
ut_ad(rw_lock_own(&(block->lock), RW_LOCK_EX));
#endif /* UNIV_SYNC_DEBUG */
//buf_pool_mutex_enter();
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) {
mutex_enter(&flush_list_mutex);
block->page.oldest_modification = start_lsn;
ut_ad(block->page.oldest_modification != 0);
buf_flush_insert_sorted_into_flush_list(block);
mutex_exit(&flush_list_mutex);
buf_flush_insert_sorted_into_flush_list(
buf_pool, block, start_lsn);
} else {
ut_ad(block->page.oldest_modification <= start_lsn);
}
//buf_pool_mutex_exit();
if (use_LRU_mutex)
mutex_exit(&LRU_list_mutex);
mutex_exit(&(block->mutex));
mutex_exit(&block->mutex);
}
#endif /* !UNIV_HOTBACKUP */

View file

@ -52,8 +52,9 @@ operations need new buffer blocks, and the i/o work done in flushing would be
wasted. */
UNIV_INTERN
void
buf_LRU_try_free_flushed_blocks(void);
/*==================================*/
buf_LRU_try_free_flushed_blocks(
/*============================*/
buf_pool_t* buf_pool); /*!< in: buffer pool instance */
/******************************************************************//**
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
@ -72,7 +73,7 @@ These are low-level functions
#define BUF_LRU_OLD_MIN_LEN 512 /* 8 megabytes of 16k pages */
/** Maximum LRU list search length in buf_flush_LRU_recommendation() */
#define BUF_LRU_FREE_SEARCH_LEN (5 + 2 * BUF_READ_AHEAD_AREA)
#define BUF_LRU_FREE_SEARCH_LEN(b) (5 + 2 * BUF_READ_AHEAD_AREA(b))
/******************************************************************//**
Invalidates all pages belonging to a given tablespace when we are deleting
@ -104,10 +105,10 @@ 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 BUF_LRU_FREED, it will temporarily
release buf_pool_mutex. Furthermore, the page frame will no longer be
release buf_pool->mutex. Furthermore, the page frame will no longer be
accessible via bpage.
The caller must hold buf_pool_mutex and buf_page_get_mutex(bpage) and
The caller must hold buf_pool->mutex and buf_page_get_mutex(bpage) and
release these two mutexes after the call. No other
buf_page_get_mutex() may be held when calling this function.
@return BUF_LRU_FREED if freed, BUF_LRU_CANNOT_RELOCATE or
@ -128,22 +129,26 @@ UNIV_INTERN
ibool
buf_LRU_search_and_free_block(
/*==========================*/
ulint n_iterations); /*!< in: how many times this has been called
repeatedly without result: a high value means
that we should search farther; if
n_iterations < 10, then we search
n_iterations / 10 * buf_pool->curr_size
pages from the end of the LRU list; if
n_iterations < 5, then we will also search
n_iterations / 5 of the unzip_LRU list. */
buf_pool_t* buf_pool, /*!< in: buffer pool instance */
ulint n_iterations); /*!< in: how many times this has
been called repeatedly without
result: a high value means that
we should search farther; if
n_iterations < 10, then we search
n_iterations / 10 * buf_pool->curr_size
pages from the end of the LRU list; if
n_iterations < 5, then we will
also search n_iterations / 5
of the unzip_LRU list. */
/******************************************************************//**
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(void);
/*=======================*/
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
@ -151,9 +156,10 @@ LRU list to the free list.
@return the free control block, in state BUF_BLOCK_READY_FOR_USE */
UNIV_INTERN
buf_block_t*
buf_LRU_get_free_block(void)
/*========================*/
__attribute__((warn_unused_result));
buf_LRU_get_free_block(
/*===================*/
buf_pool_t* buf_pool) /*!< in/out: buffer pool instance */
__attribute__((nonnull,warn_unused_result));
/******************************************************************//**
Puts a block back to the free list. */
@ -201,7 +207,7 @@ buf_LRU_make_block_old(
Updates buf_LRU_old_ratio.
@return updated old_pct */
UNIV_INTERN
uint
ulint
buf_LRU_old_ratio_update(
/*=====================*/
uint old_pct,/*!< in: Reserve this percentage of
@ -249,7 +255,7 @@ buf_LRU_print(void);
/** @name Heuristics for detecting index scan @{ */
/** Reserve this much/BUF_LRU_OLD_RATIO_DIV of the buffer pool for
"old" blocks. Protected by buf_pool_mutex. */
"old" blocks. Protected by buf_pool->mutex. */
extern uint buf_LRU_old_ratio;
/** The denominator of buf_LRU_old_ratio. */
#define BUF_LRU_OLD_RATIO_DIV 1024
@ -295,7 +301,7 @@ 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. */
Updated by buf_LRU_stat_update(). Protected by buf_pool->mutex. */
extern buf_LRU_stat_t buf_LRU_stat_sum;
/********************************************************************//**

View file

@ -103,10 +103,10 @@ 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 of a page; NOTE: the current thread
must want access to this page (see NOTE 3 above) */
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 */
trx_t* trx);
/********************************************************************//**
Issues read requests for pages which the ibuf module wants to read in, in
@ -158,7 +158,7 @@ buf_read_recv_pages(
/** The size in pages of the area which the read-ahead algorithms read if
invoked */
#define BUF_READ_AHEAD_AREA 64
#define BUF_READ_AHEAD_AREA(b) 64
/** @name Modes used in read-ahead @{ */
/** read only pages belonging to the insert buffer tree */

View file

@ -36,6 +36,8 @@ typedef struct buf_chunk_struct buf_chunk_t;
typedef struct buf_pool_struct buf_pool_t;
/** Buffer pool statistics struct */
typedef struct buf_pool_stat_struct buf_pool_stat_t;
/** Buffer pool buddy statistics struct */
typedef struct buf_buddy_stat_struct buf_buddy_stat_t;
/** A buffer frame. @see page_t */
typedef byte buf_frame_t;

View file

@ -314,7 +314,7 @@ dtuple_fold(
ulint n_fields,/*!< in: number of complete fields to fold */
ulint n_bytes,/*!< in: number of bytes to fold in an
incomplete last field */
dulint tree_id)/*!< in: index tree id */
index_id_t tree_id)/*!< in: index tree id */
__attribute__((pure));
/*******************************************************************//**
Sets types of fields binary in a tuple. */

View file

@ -528,7 +528,7 @@ dtuple_fold(
ulint n_fields,/*!< in: number of complete fields to fold */
ulint n_bytes,/*!< in: number of bytes to fold in an
incomplete last field */
dulint tree_id)/*!< in: index tree id */
index_id_t tree_id)/*!< in: index tree id */
{
const dfield_t* field;
ulint i;
@ -540,7 +540,7 @@ dtuple_fold(
ut_ad(tuple->magic_n == DATA_TUPLE_MAGIC_N);
ut_ad(dtuple_check_typed(tuple));
fold = ut_fold_dulint(tree_id);
fold = ut_fold_ull(tree_id);
for (i = 0; i < n_fields; i++) {
field = dtuple_get_nth_field(tuple, i);

View file

@ -128,7 +128,7 @@ columns, and for them the precise type is usually not used at all.
/* 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 dulint */
#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 */
@ -168,6 +168,20 @@ SQL null*/
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))
#ifndef UNIV_HOTBACKUP
/*********************************************************************//**
Gets the MySQL type code from a dtype.
@ -187,10 +201,8 @@ ulint
dtype_get_at_most_n_mbchars(
/*========================*/
ulint prtype, /*!< in: precise type */
ulint mbminlen, /*!< in: minimum length of a
multi-byte character */
ulint mbmaxlen, /*!< in: maximum length of a
multi-byte character */
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) */
@ -335,6 +347,19 @@ 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
@ -354,8 +379,8 @@ dtype_get_fixed_size_low(
ulint mtype, /*!< in: main type */
ulint prtype, /*!< in: precise type */
ulint len, /*!< in: length */
ulint mbminlen, /*!< in: minimum length of a multibyte char */
ulint mbmaxlen, /*!< in: maximum length of a multibyte char */
ulint mbminmaxlen, /*!< in: minimum and maximum length of a
multibyte character, in bytes */
ulint comp); /*!< in: nonzero=ROW_FORMAT=COMPACT */
#ifndef UNIV_HOTBACKUP
/***********************************************************************//**
@ -368,8 +393,8 @@ dtype_get_min_size_low(
ulint mtype, /*!< in: main type */
ulint prtype, /*!< in: precise type */
ulint len, /*!< in: length */
ulint mbminlen, /*!< in: minimum length of a multibyte char */
ulint mbmaxlen); /*!< in: maximum length of a multibyte char */
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.
@ -472,10 +497,11 @@ struct dtype_struct{
the string, MySQL uses 1 or 2
bytes to store the string length) */
#ifndef UNIV_HOTBACKUP
unsigned mbminlen:2; /*!< minimum length of a
character, in bytes */
unsigned mbmaxlen:3; /*!< maximum length of a
character, in bytes */
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 */
};

View file

@ -93,13 +93,34 @@ dtype_get_mblen(
innobase_get_cset_width(dtype_get_charset_coll(prtype),
mbminlen, mbmaxlen);
ut_ad(*mbminlen <= *mbmaxlen);
ut_ad(*mbminlen <= 2); /* mbminlen in dtype_t is 0..3 */
ut_ad(*mbmaxlen < 1 << 3); /* mbmaxlen in dtype_t is 0..7 */
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
@ -112,8 +133,7 @@ dtype_set_mblen(
ulint mbmaxlen;
dtype_get_mblen(type->mtype, type->prtype, &mbminlen, &mbmaxlen);
type->mbminlen = mbminlen;
type->mbmaxlen = mbmaxlen;
dtype_set_mbminmaxlen(type, mbminlen, mbmaxlen);
ut_ad(dtype_validate(type));
}
@ -210,7 +230,7 @@ dtype_get_mbminlen(
const dtype_t* type) /*!< in: type */
{
ut_ad(type);
return(type->mbminlen);
return(DATA_MBMINLEN(type->mbminmaxlen));
}
/*********************************************************************//**
Gets the maximum length of a character, in bytes.
@ -223,7 +243,7 @@ dtype_get_mbmaxlen(
const dtype_t* type) /*!< in: type */
{
ut_ad(type);
return(type->mbmaxlen);
return(DATA_MBMAXLEN(type->mbminmaxlen));
}
/*********************************************************************//**
@ -404,8 +424,8 @@ dtype_get_fixed_size_low(
ulint mtype, /*!< in: main type */
ulint prtype, /*!< in: precise type */
ulint len, /*!< in: length */
ulint mbminlen, /*!< in: minimum length of a multibyte char */
ulint mbmaxlen, /*!< in: maximum length of a multibyte char */
ulint mbminmaxlen, /*!< in: minimum and maximum length of
a multibyte character, in bytes */
ulint comp) /*!< in: nonzero=ROW_FORMAT=COMPACT */
{
switch (mtype) {
@ -453,8 +473,9 @@ dtype_get_fixed_size_low(
dtype_get_charset_coll(prtype),
&i_mbminlen, &i_mbmaxlen);
if (UNIV_UNLIKELY(mbminlen != i_mbminlen)
|| UNIV_UNLIKELY(mbmaxlen != i_mbmaxlen)) {
if (UNIV_UNLIKELY
(DATA_MBMINMAXLEN(i_mbminlen, i_mbmaxlen)
!= mbminmaxlen)) {
ut_print_timestamp(stderr);
fprintf(stderr, " InnoDB: "
@ -464,10 +485,10 @@ dtype_get_fixed_size_low(
"type->mbmaxlen=%lu\n",
(ulong) i_mbminlen,
(ulong) i_mbmaxlen,
(ulong) mbminlen,
(ulong) mbmaxlen);
(ulong) DATA_MBMINLEN(mbminmaxlen),
(ulong) DATA_MBMAXLEN(mbminmaxlen));
}
if (mbminlen == mbmaxlen) {
if (i_mbminlen == i_mbmaxlen) {
return(len);
}
}
@ -499,8 +520,8 @@ dtype_get_min_size_low(
ulint mtype, /*!< in: main type */
ulint prtype, /*!< in: precise type */
ulint len, /*!< in: length */
ulint mbminlen, /*!< in: minimum length of a multibyte char */
ulint mbmaxlen) /*!< in: maximum length of a multibyte char */
ulint mbminmaxlen) /*!< in: minimum and maximum length of a
multi-byte character */
{
switch (mtype) {
case DATA_SYS:
@ -527,14 +548,22 @@ dtype_get_min_size_low(
case DATA_DOUBLE:
return(len);
case DATA_MYSQL:
if ((prtype & DATA_BINARY_TYPE) || mbminlen == mbmaxlen) {
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);
}
/* 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:
@ -595,9 +624,9 @@ dtype_get_sql_null_size(
{
#ifndef UNIV_HOTBACKUP
return(dtype_get_fixed_size_low(type->mtype, type->prtype, type->len,
type->mbminlen, type->mbmaxlen, comp));
type->mbminmaxlen, comp));
#else /* !UNIV_HOTBACKUP */
return(dtype_get_fixed_size_low(type->mtype, type->prtype, type->len,
0, 0, 0));
0, 0));
#endif /* !UNIV_HOTBACKUP */
}

View file

@ -94,9 +94,22 @@ enum db_err {
DB_PRIMARY_KEY_IS_NULL, /* a column in the PRIMARY KEY
was found to be NULL */
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 */
/* The following are partial failure codes */
DB_FAIL = 1000,

View file

@ -51,32 +51,35 @@ UNIV_INTERN
void
dict_hdr_get_new_id(
/*================*/
dulint* table_id, /*!< out: table id (not assigned if NULL) */
dulint* index_id, /*!< out: index id (not assigned if NULL) */
ulint* space_id); /*!< out: space id (not assigned if NULL) */
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) */
/**********************************************************************//**
Returns a new row id.
@return the new id */
UNIV_INLINE
dulint
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
dulint
row_id_t
dict_sys_read_row_id(
/*=================*/
byte* field); /*!< in: record field */
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 */
dulint row_id);/*!< in: 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. */
@ -97,13 +100,13 @@ dict_create(void);
#define DICT_HDR_PAGE_NO FSP_DICT_HDR_PAGE_NO
/* The ids for the basic system tables and their indexes */
#define DICT_TABLES_ID ut_dulint_create(0, 1)
#define DICT_COLUMNS_ID ut_dulint_create(0, 2)
#define DICT_INDEXES_ID ut_dulint_create(0, 3)
#define DICT_FIELDS_ID ut_dulint_create(0, 4)
#define DICT_STATS_ID ut_dulint_create(0, 6)
#define DICT_TABLES_ID 1
#define DICT_COLUMNS_ID 2
#define DICT_INDEXES_ID 3
#define DICT_FIELDS_ID 4
#define DICT_STATS_ID 6
/* The following is a secondary index on SYS_TABLES */
#define DICT_TABLE_IDS_ID ut_dulint_create(0, 5)
#define DICT_TABLE_IDS_ID 5
#define DICT_HDR_FIRST_ID 10 /* the ids for tables etc. start
from this number, except for basic
@ -111,7 +114,7 @@ dict_create(void);
indexes; ibuf tables and indexes are
assigned as the id the number
DICT_IBUF_ID_MIN plus the space id */
#define DICT_IBUF_ID_MIN ut_dulint_create(0xFFFFFFFFUL, 0)
#define DICT_IBUF_ID_MIN 0xFFFFFFFF00000000ULL
/* The offset of the dictionary header on the page */
#define DICT_HDR FSEG_PAGE_DATA
@ -153,7 +156,7 @@ two) is assigned, the field DICT_HDR_ROW_ID on the dictionary header page is
updated */
#define DICT_HDR_ROW_ID_WRITE_MARGIN 256
#define DICT_HDR_XTRADB_FLAG ut_dulint_create(0x58545241UL,0x44425F31UL) /* "XTRADB_1" */
#define DICT_HDR_XTRADB_FLAG 0x5854524144425F31ULL /* "XTRADB_1" */
#ifndef UNIV_NONINL
#include "dict0boot.ic"

View file

@ -36,22 +36,22 @@ dict_hdr_flush_row_id(void);
Returns a new row id.
@return the new id */
UNIV_INLINE
dulint
row_id_t
dict_sys_get_new_row_id(void)
/*=========================*/
{
dulint id;
row_id_t id;
mutex_enter(&(dict_sys->mutex));
id = dict_sys->row_id;
if (0 == (ut_dulint_get_low(id) % DICT_HDR_ROW_ID_WRITE_MARGIN)) {
if (0 == (id % DICT_HDR_ROW_ID_WRITE_MARGIN)) {
dict_hdr_flush_row_id();
}
UT_DULINT_INC(dict_sys->row_id);
dict_sys->row_id++;
mutex_exit(&(dict_sys->mutex));
@ -62,10 +62,10 @@ 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
dulint
row_id_t
dict_sys_read_row_id(
/*=================*/
byte* field) /*!< in: record field */
const byte* field) /*!< in: record field */
{
#if DATA_ROW_ID_LEN != 6
# error "DATA_ROW_ID_LEN != 6"
@ -80,8 +80,8 @@ UNIV_INLINE
void
dict_sys_write_row_id(
/*==================*/
byte* field, /*!< in: record field */
dulint row_id) /*!< in: 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"

View file

@ -75,8 +75,8 @@ UNIV_INTERN
dict_table_t*
dict_table_get_on_id(
/*=================*/
dulint table_id, /*!< in: table id */
trx_t* trx); /*!< in: transaction handle */
table_id_t table_id, /*!< in: table id */
trx_t* trx); /*!< in: transaction handle */
/********************************************************************//**
Decrements the count of open MySQL handles to a table. */
UNIV_INTERN
@ -102,6 +102,33 @@ void
dict_load_space_id_list(void);
/*=========================*/
/*********************************************************************//**
Gets the minimum number of bytes per character.
@return minimum multi-byte char size, in bytes */
UNIV_INLINE
ulint
dict_col_get_mbminlen(
/*==================*/
const dict_col_t* col); /*!< in: column */
/*********************************************************************//**
Gets the maximum number of bytes per character.
@return maximum multi-byte char size, in bytes */
UNIV_INLINE
ulint
dict_col_get_mbmaxlen(
/*==================*/
const dict_col_t* col); /*!< in: column */
/*********************************************************************//**
Sets the minimum and maximum number of bytes per character. */
UNIV_INLINE
void
dict_col_set_mbminmaxlen(
/*=====================*/
dict_col_t* col, /*!< in/out: column */
ulint mbminlen, /*!< in: minimum multi-byte
character size, in bytes */
ulint mbmaxlen); /*!< in: minimum multi-byte
character size, in bytes */
/*********************************************************************//**
Gets the column data type. */
UNIV_INLINE
void
@ -277,7 +304,7 @@ void
dict_table_change_id_in_cache(
/*==========================*/
dict_table_t* table, /*!< in/out: table object already in cache */
dulint new_id);/*!< in: new id to set */
table_id_t new_id);/*!< in: new id to set */
/**********************************************************************//**
Adds a foreign key constraint object to the dictionary cache. May free
the object if there already is an object with the same identifier in.
@ -398,7 +425,7 @@ dict_index_t*
dict_index_get_on_id_low(
/*=====================*/
dict_table_t* table, /*!< in: table */
dulint index_id); /*!< in: index id */
index_id_t index_id); /*!< in: index id */
/**********************************************************************//**
Checks if a table is in the dictionary cache.
@return table, NULL if not found */
@ -414,6 +441,18 @@ function.
@return table, NULL if not found */
UNIV_INLINE
dict_table_t*
dict_table_get_low_ignore_err(
/*===========================*/
const char* table_name, /*!< in: table name */
dict_err_ignore_t
ignore_err); /*!< in: error to be ignored when
loading a table definition */
/**********************************************************************//**
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 */
@ -424,7 +463,7 @@ UNIV_INLINE
dict_table_t*
dict_table_get_on_id_low(
/*=====================*/
dulint table_id); /*!< in: table id */
table_id_t table_id); /*!< in: table id */
/**********************************************************************//**
Find an index that is equivalent to the one passed in and is not marked
for deletion.
@ -727,7 +766,7 @@ UNIV_INTERN
dict_index_t*
dict_index_find_on_id_low(
/*======================*/
dulint id); /*!< in: index id */
index_id_t id); /*!< in: index id */
/**********************************************************************//**
Adds an index to the dictionary cache.
@return DB_SUCCESS, DB_TOO_BIG_RECORD, or DB_CORRUPTION */
@ -918,7 +957,7 @@ UNIV_INTERN
dict_index_t*
dict_index_get_if_in_cache_low(
/*===========================*/
dulint index_id); /*!< in: index id */
index_id_t index_id); /*!< in: index id */
#if defined UNIV_DEBUG || defined UNIV_BUF_DEBUG
/**********************************************************************//**
Returns an index object if it is found in the dictionary cache.
@ -927,7 +966,7 @@ UNIV_INTERN
dict_index_t*
dict_index_get_if_in_cache(
/*=======================*/
dulint index_id); /*!< in: index id */
index_id_t index_id); /*!< in: index id */
#endif /* UNIV_DEBUG || UNIV_BUF_DEBUG */
#ifdef UNIV_DEBUG
/**********************************************************************//**
@ -1057,7 +1096,7 @@ void
dict_update_statistics(
/*===================*/
dict_table_t* table, /*!< in/out: table */
ibool only_calc_if_missing_stats, /*!< in: only
ibool only_calc_if_missing_stats, /*!< in: only
update/recalc the stats if they have
not been initialized yet, otherwise
do nothing */
@ -1164,7 +1203,7 @@ struct dict_sys_struct{
and DROP TABLE, as well as reading
the dictionary data for a table from
system tables */
dulint row_id; /*!< the next row id to assign;
row_id_t row_id; /*!< the next row id to assign;
NOTE that at a checkpoint this
must be written to the dict system
header and flushed to a file; in

View file

@ -28,6 +28,46 @@ Created 1/8/1996 Heikki Tuuri
#include "dict0load.h"
#include "rem0types.h"
/*********************************************************************//**
Gets the minimum number of bytes per character.
@return minimum multi-byte char size, in bytes */
UNIV_INLINE
ulint
dict_col_get_mbminlen(
/*==================*/
const dict_col_t* col) /*!< in: column */
{
return(DATA_MBMINLEN(col->mbminmaxlen));
}
/*********************************************************************//**
Gets the maximum number of bytes per character.
@return maximum multi-byte char size, in bytes */
UNIV_INLINE
ulint
dict_col_get_mbmaxlen(
/*==================*/
const dict_col_t* col) /*!< in: column */
{
return(DATA_MBMAXLEN(col->mbminmaxlen));
}
/*********************************************************************//**
Sets the minimum and maximum number of bytes per character. */
UNIV_INLINE
void
dict_col_set_mbminmaxlen(
/*=====================*/
dict_col_t* col, /*!< in/out: column */
ulint mbminlen, /*!< in: minimum multi-byte
character size, in bytes */
ulint mbmaxlen) /*!< in: minimum multi-byte
character size, in bytes */
{
ut_ad(mbminlen < DATA_MBMAX);
ut_ad(mbmaxlen < DATA_MBMAX);
ut_ad(mbminlen <= mbmaxlen);
col->mbminmaxlen = DATA_MBMINMAXLEN(mbminlen, mbmaxlen);
}
/*********************************************************************//**
Gets the column data type. */
UNIV_INLINE
@ -42,8 +82,7 @@ dict_col_copy_type(
type->mtype = col->mtype;
type->prtype = col->prtype;
type->len = col->len;
type->mbminlen = col->mbminlen;
type->mbmaxlen = col->mbmaxlen;
type->mbminmaxlen = col->mbminmaxlen;
}
#endif /* !UNIV_HOTBACKUP */
@ -65,8 +104,7 @@ dict_col_type_assert_equal(
ut_ad(col->prtype == type->prtype);
ut_ad(col->len == type->len);
# ifndef UNIV_HOTBACKUP
ut_ad(col->mbminlen == type->mbminlen);
ut_ad(col->mbmaxlen == type->mbmaxlen);
ut_ad(col->mbminmaxlen == type->mbminmaxlen);
# endif /* !UNIV_HOTBACKUP */
return(TRUE);
@ -84,7 +122,7 @@ dict_col_get_min_size(
const dict_col_t* col) /*!< in: column */
{
return(dtype_get_min_size_low(col->mtype, col->prtype, col->len,
col->mbminlen, col->mbmaxlen));
col->mbminmaxlen));
}
/***********************************************************************//**
Returns the maximum size of the column.
@ -109,7 +147,7 @@ dict_col_get_fixed_size(
ulint comp) /*!< in: nonzero=ROW_FORMAT=COMPACT */
{
return(dtype_get_fixed_size_low(col->mtype, col->prtype, col->len,
col->mbminlen, col->mbmaxlen, comp));
col->mbminmaxlen, comp));
}
/***********************************************************************//**
Returns the ROW_FORMAT=REDUNDANT stored SQL NULL size of a column.
@ -796,6 +834,34 @@ dict_table_check_if_in_cache_low(
return(table);
}
/**********************************************************************//**
load a table into dictionary cache, ignore any error specified during load;
@return table, NULL if not found */
UNIV_INLINE
dict_table_t*
dict_table_get_low_ignore_err(
/*==========================*/
const char* table_name, /*!< in: table name */
dict_err_ignore_t
ignore_err) /*!< in: error to be ignored when
loading a table definition */
{
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 == NULL) {
table = dict_load_table(table_name, TRUE, ignore_err);
}
ut_ad(!table || table->cached);
return(table);
}
/**********************************************************************//**
Gets a table; loads it to the dictionary cache if necessary. A low-level
function.
@ -814,7 +880,7 @@ dict_table_get_low(
table = dict_table_check_if_in_cache_low(table_name);
if (table == NULL) {
table = dict_load_table(table_name);
table = dict_load_table(table_name, TRUE, DICT_ERR_IGNORE_NONE);
}
ut_ad(!table || table->cached);
@ -829,7 +895,7 @@ UNIV_INLINE
dict_table_t*
dict_table_get_on_id_low(
/*=====================*/
dulint table_id) /*!< in: table id */
table_id_t table_id) /*!< in: table id */
{
dict_table_t* table;
ulint fold;
@ -837,11 +903,11 @@ dict_table_get_on_id_low(
ut_ad(mutex_own(&(dict_sys->mutex)));
/* Look for the table name in the hash table */
fold = ut_fold_dulint(table_id);
fold = ut_fold_ull(table_id);
HASH_SEARCH(id_hash, dict_sys->table_id_hash, fold,
dict_table_t*, table, ut_ad(table->cached),
!ut_dulint_cmp(table->id, table_id));
table->id == table_id);
if (table == NULL) {
table = dict_load_table_on_id(table_id);
}

View file

@ -31,6 +31,36 @@ Created 4/24/1996 Heikki Tuuri
#include "dict0types.h"
#include "ut0byte.h"
#include "mem0mem.h"
#include "btr0types.h"
/** enum that defines all 6 system table IDs */
enum dict_system_table_id {
SYS_TABLES = 0,
SYS_INDEXES,
SYS_COLUMNS,
SYS_FIELDS,
SYS_FOREIGN,
SYS_FOREIGN_COLS,
SYS_STATS,
/* This must be last item. Defines the number of system tables. */
SYS_NUM_SYSTEM_TABLES
};
typedef enum dict_system_table_id dict_system_id_t;
/** Status bit for dict_process_sys_tables_rec() */
enum dict_table_info {
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 */
DICT_TABLE_UPDATE_STATS = 2 /*!< whether to update statistics
when loading SYS_TABLES information. */
};
typedef enum dict_table_info dict_table_info_t;
/********************************************************************//**
In a crash recovery we already have all the tablespace objects created.
@ -54,6 +84,79 @@ 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 */
/********************************************************************//**
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
@ -66,8 +169,12 @@ UNIV_INTERN
dict_table_t*
dict_load_table(
/*============*/
const char* name); /*!< in: table name in the
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 */
@ -75,7 +182,7 @@ UNIV_INTERN
dict_table_t*
dict_load_table_on_id(
/*==================*/
dulint table_id); /*!< in: table id */
table_id_t table_id); /*!< in: table id */
/********************************************************************//**
This function is called when the database is booted.
Loads system table index definitions except for the clustered index which
@ -109,7 +216,127 @@ 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(
/*========================*/
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 */
/********************************************************************//**
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_STATS 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_stats_rec(
/*=============================*/
mem_heap_t* heap, /*!< in/out: heap memory */
const rec_t* rec, /*!< in: current SYS_STATS rec */
index_id_t* index_id, /*!< out: INDEX_ID */
ulint* key_cols, /*!< out: KEY_COLS */
ib_uint64_t* diff_vals, /*!< out: DIFF_VALS */
ib_uint64_t* non_null_vals); /*!< out: NON_NULL_VALS */
#ifndef UNIV_NONINL
#include "dict0load.ic"
#endif

View file

@ -1,6 +1,6 @@
/*****************************************************************************
Copyright (c) 1996, 2009, Innobase Oy. All Rights Reserved.
Copyright (c) 1996, 2010, Innobase Oy. 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
@ -88,6 +88,10 @@ combination of types */
new BLOB treatment */
/** Maximum supported file format */
#define DICT_TF_FORMAT_MAX DICT_TF_FORMAT_ZIP
/** Minimum supported file format */
#define DICT_TF_FORMAT_MIN DICT_TF_FORMAT_51
/* @} */
#define DICT_TF_BITS 6 /*!< number of flag bits */
#if (1 << (DICT_TF_BITS - DICT_TF_FORMAT_SHIFT)) <= DICT_TF_FORMAT_MAX
@ -118,7 +122,7 @@ This could result in rescursive calls and out of stack error eventually.
DICT_FK_MAX_RECURSIVE_LOAD defines the maximum number of recursive loads,
when exceeded, the child table will not be loaded. It will be loaded when
the foreign constraint check needs to be run. */
#define DICT_FK_MAX_RECURSIVE_LOAD 250
#define DICT_FK_MAX_RECURSIVE_LOAD 255
/** Similarly, when tables are chained together with foreign key constraints
with on cascading delete/update clause, delete from parent table could
@ -126,7 +130,7 @@ result in recursive cascading calls. This defines the maximum number of
such cascading deletes/updates allowed. When exceeded, the delete from
parent table will fail, and user has to drop excessive foreign constraint
before proceeds. */
#define FK_MAX_CASCADE_DEL 300
#define FK_MAX_CASCADE_DEL 255
/**********************************************************************//**
Creates a table memory object.
@ -162,6 +166,36 @@ dict_mem_table_add_col(
ulint prtype, /*!< in: precise type */
ulint len); /*!< in: precision */
/**********************************************************************//**
This function populates a dict_col_t memory structure with
supplied information. */
UNIV_INTERN
void
dict_mem_fill_column_struct(
/*========================*/
dict_col_t* column, /*!< out: column struct to be
filled */
ulint col_pos, /*!< in: column position */
ulint mtype, /*!< in: main data type */
ulint prtype, /*!< in: precise type */
ulint col_len); /*!< in: column length */
/**********************************************************************//**
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 */
/**********************************************************************//**
Creates an index memory object.
@return own: index object */
UNIV_INTERN
@ -204,6 +238,30 @@ dict_foreign_t*
dict_mem_foreign_create(void);
/*=========================*/
/**********************************************************************//**
Sets the foreign_table_name_lookup pointer based on the value of
lower_case_table_names. If that is 0 or 1, foreign_table_name_lookup
will point to foreign_table_name. If 2, then another string is
allocated from the heap and set to lower case. */
UNIV_INTERN
void
dict_mem_foreign_table_name_lookup_set(
/*===================================*/
dict_foreign_t* foreign, /*!< in/out: foreign struct */
ibool do_alloc); /*!< in: is an alloc needed */
/**********************************************************************//**
Sets the referenced_table_name_lookup pointer based on the value of
lower_case_table_names. If that is 0 or 1, referenced_table_name_lookup
will point to referenced_table_name. If 2, then another string is
allocated from the heap and set to lower case. */
UNIV_INTERN
void
dict_mem_referenced_table_name_lookup_set(
/*======================================*/
dict_foreign_t* foreign, /*!< in/out: foreign struct */
ibool do_alloc); /*!< in: is an alloc needed */
/** Data structure for a column in a table */
struct dict_col_struct{
/*----------------------*/
@ -230,10 +288,11 @@ struct dict_col_struct{
the string, MySQL uses 1 or 2
bytes to store the string length) */
unsigned mbminlen:2; /*!< minimum length of a
character, in bytes */
unsigned mbmaxlen:3; /*!< maximum length of a
character, in bytes */
unsigned mbminmaxlen:5; /*!< minimum and maximum length of a
character, in bytes;
DATA_MBMINMAXLEN(mbminlen,mbmaxlen);
mbminlen=DATA_MBMINLEN(mbminmaxlen);
mbmaxlen=DATA_MBMINLEN(mbminmaxlen) */
/*----------------------*/
/* End of definitions copied from dtype_t */
/* @} */
@ -274,7 +333,7 @@ struct dict_field_struct{
/** Data structure for an index. Most fields will be
initialized to 0, NULL or FALSE in dict_mem_index_create(). */
struct dict_index_struct{
dulint id; /*!< id of the index */
index_id_t id; /*!< id of the index */
mem_heap_t* heap; /*!< memory heap */
const char* name; /*!< index name */
const char* table_name;/*!< table name */
@ -306,6 +365,8 @@ struct dict_index_struct{
/*!< TRUE if this index is marked to be
dropped in ha_innobase::prepare_drop_index(),
otherwise FALSE */
unsigned corrupted:1;
/*!< TRUE if the index object is corrupted */
dict_field_t* fields; /*!< array of field descriptions */
#ifndef UNIV_HOTBACKUP
UT_LIST_NODE_T(dict_index_t)
@ -336,10 +397,17 @@ struct dict_index_struct{
/* @} */
rw_lock_t lock; /*!< read-write lock protecting the
upper levels of the index tree */
ib_uint64_t trx_id; /*!< id of the transaction that created this
trx_id_t trx_id; /*!< id of the transaction that created this
index, or 0 if the index existed
when InnoDB was started up */
#endif /* !UNIV_HOTBACKUP */
#ifdef UNIV_BLOB_DEBUG
mutex_t blobs_mutex;
/*!< mutex protecting blobs */
void* blobs; /*!< map of (page_no,heap_no,field_no)
to first_blob_page_no; protected by
blobs_mutex; @see btr_blob_dbg_t */
#endif /* UNIV_BLOB_DEBUG */
#ifdef UNIV_DEBUG
ulint magic_n;/*!< magic number */
/** Value of dict_index_struct::magic_n */
@ -364,10 +432,14 @@ struct dict_foreign_struct{
unsigned type:6; /*!< 0 or DICT_FOREIGN_ON_DELETE_CASCADE
or DICT_FOREIGN_ON_DELETE_SET_NULL */
char* foreign_table_name;/*!< foreign table name */
char* foreign_table_name_lookup;
/*!< foreign table name used for dict lookup */
dict_table_t* foreign_table; /*!< table where the foreign key is */
const char** foreign_col_names;/*!< names of the columns in the
foreign key */
char* referenced_table_name;/*!< referenced table name */
char* referenced_table_name_lookup;
/*!< referenced table name for dict lookup*/
dict_table_t* referenced_table;/*!< table where the referenced key
is */
const char** referenced_col_names;/*!< names of the referenced
@ -401,7 +473,7 @@ a foreign key constraint is enforced, therefore RESTRICT just means no flag */
/** Data structure for a database table. Most fields will be
initialized to 0, NULL or FALSE in dict_mem_table_create(). */
struct dict_table_struct{
dulint id; /*!< id of the table */
table_id_t id; /*!< id of the table */
mem_heap_t* heap; /*!< memory heap */
char* name; /*!< table name */
const char* dir_path_of_temp_table;/*!< NULL or the directory path
@ -428,6 +500,8 @@ struct dict_table_struct{
to the dictionary cache */
unsigned n_def:10;/*!< number of columns defined so far */
unsigned n_cols:10;/*!< number of columns */
unsigned corrupted:1;
/*!< TRUE if table is corrupted */
dict_col_t* cols; /*!< array of column descriptions */
const char* col_names;
/*!< Column names packed in a character string

View file

@ -23,4 +23,50 @@ 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;
}
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 */
}

View file

@ -40,4 +40,21 @@ typedef struct tab_node_struct tab_node_t;
#define DICT_HDR_SPACE 0 /* the SYSTEM tablespace */
#define DICT_HDR_PAGE_NO FSP_DICT_HDR_PAGE_NO
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 {
DICT_ERR_IGNORE_NONE = 0, /*!< no error to ignore */
DICT_ERR_IGNORE_INDEX_ROOT = 1, /*!< ignore error if index root
page is FIL_NUL or incorrect value */
DICT_ERR_IGNORE_ALL = 0xFFFF /*!< ignore all errors */
};
typedef enum dict_err_ignore dict_err_ignore_t;
#endif

View file

@ -27,12 +27,13 @@ Created 10/25/1995 Heikki Tuuri
#define fil0fil_h
#include "univ.i"
#ifndef UNIV_HOTBACKUP
#include "sync0rw.h"
#endif /* !UNIV_HOTBACKUP */
#include "dict0types.h"
#include "ut0byte.h"
#include "os0file.h"
#ifndef UNIV_HOTBACKUP
#include "sync0rw.h"
#include "ibuf0types.h"
#endif /* !UNIV_HOTBACKUP */
/** When mysqld is run, the default directory "." is the mysqld datadir,
but in the MySQL Embedded Server Library and ibbackup it is not the default

View file

@ -1,6 +1,6 @@
/*****************************************************************************
Copyright (c) 2006, 2009, Innobase Oy. All Rights Reserved.
Copyright (c) 2006, 2010, Innobase Oy. 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
@ -173,6 +173,15 @@ innobase_strcasecmp(
const char* a, /*!< in: first string to compare */
const char* b); /*!< in: second 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 */
@ -267,13 +276,31 @@ thd_lock_wait_timeout(
/*==================*/
void* thd); /*!< in: thread handle (THD*), 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(
/*===================*/
void* thd, /*!< in: thread handle (THD*) */
ulint value); /*!< in: time waited for the lock */
/******************************************************************//**
*/
ulong
thd_flush_log_at_trx_commit_session(
thd_flush_log_at_trx_commit(
/*================================*/
void* thd);
/**********************************************************************//**
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);
/*=====================================*/
#endif

View file

@ -1,6 +1,6 @@
/*****************************************************************************
Copyright (c) 2005, 2009, Innobase Oy. All Rights Reserved.
Copyright (c) 2005, 2010, Innobase Oy. 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
@ -27,7 +27,7 @@ UNIV_INTERN
void
innobase_rec_to_mysql(
/*==================*/
TABLE* table, /*!< in/out: MySQL table */
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(
@ -39,4 +39,4 @@ UNIV_INTERN
void
innobase_rec_reset(
/*===============*/
TABLE* table); /*!< in/out: MySQL table */
struct TABLE* table); /*!< in/out: MySQL table */

View file

@ -49,28 +49,6 @@ hash_table_t*
hash_create(
/*========*/
ulint n); /*!< in: number of array cells */
/*************************************************************//**
*/
UNIV_INTERN
ulint
hash_create_needed(
/*===============*/
ulint n);
UNIV_INTERN
void
hash_create_init(
/*=============*/
hash_table_t* table,
ulint n);
UNIV_INTERN
void
hash_create_reuse(
/*==============*/
hash_table_t* table);
#ifndef UNIV_HOTBACKUP
/*************************************************************//**
Creates a mutex array to protect a hash table. */
@ -350,33 +328,6 @@ do {\
}\
} while (0)
/********************************************************************//**
Align nodes with moving location.*/
#define HASH_OFFSET(TABLE, NODE_TYPE, PTR_NAME, FADDR, FOFFSET, BOFFSET) \
do {\
ulint i2222;\
ulint cell_count2222;\
\
cell_count2222 = hash_get_n_cells(TABLE);\
\
for (i2222 = 0; i2222 < cell_count2222; i2222++) {\
NODE_TYPE* node2222;\
\
if ((TABLE)->array[i2222].node) \
(TABLE)->array[i2222].node = (void*)((byte*)(TABLE)->array[i2222].node \
+ (((TABLE)->array[i2222].node > (void*)FADDR)?FOFFSET:BOFFSET));\
node2222 = HASH_GET_FIRST((TABLE), i2222);\
\
while (node2222) {\
if (node2222->PTR_NAME) \
node2222->PTR_NAME = (void*)((byte*)(node2222->PTR_NAME) \
+ ((((void*)node2222->PTR_NAME) > (void*)FADDR)?FOFFSET:BOFFSET));\
\
node2222 = node2222->PTR_NAME;\
}\
}\
} while (0)
/************************************************************//**
Gets the mutex index for a fold value in a hash table.
@return mutex number */

View file

@ -35,12 +35,27 @@ Created 7/19/1997 Heikki Tuuri
#ifndef UNIV_HOTBACKUP
# include "ibuf0types.h"
/* 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;
@ -77,8 +92,7 @@ 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 and
initializes the data structures for the insert buffer of each tablespace. */
Creates the insert buffer data structure at a database startup. */
UNIV_INTERN
void
ibuf_init_at_db_start(void);
@ -90,6 +104,22 @@ 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
@ -210,10 +240,12 @@ 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_INTERN
UNIV_INLINE
ibool
ibuf_inside(void);
/*=============*/
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 */
@ -230,15 +262,44 @@ Must not be called when recv_no_ibuf_operations==TRUE.
@return TRUE if level 2 or level 3 page */
UNIV_INTERN
ibool
ibuf_page(
/*======*/
ulint space, /*!< in: space id */
ulint zip_size,/*!< in: compressed page size in bytes, or 0 */
ulint page_no,/*!< in: page number */
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. */
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
@ -248,14 +309,15 @@ void
ibuf_free_excess_pages(void);
/*========================*/
/*********************************************************************//**
Makes an index insert to the insert buffer, instead of directly to the disk
page, if this is possible. Does not do insert if the index is clustered
or unique.
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 */
@ -264,11 +326,11 @@ ibuf_insert(
que_thr_t* thr); /*!< in: query thread */
/*********************************************************************//**
When an index page is read from a disk to the buffer pool, this function
inserts to the page the possible index entries buffered in the insert buffer.
The entries are deleted 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. */
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(
@ -361,12 +423,37 @@ 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);
/*============*/
/******************************************************************//**
Function to pass ibuf status variables */
UNIV_INTERN
void
ibuf_export_ibuf_status(
/*====================*/
ulint* size,
ulint* free_list,
ulint* segment_size,
ulint* merges,
ulint* merged_inserts,
ulint* merged_delete_marks,
ulint* merged_deletes,
ulint* discarded_inserts,
ulint* discarded_delete_marks,
ulint* discarded_deletes);
#define IBUF_HEADER_PAGE_NO FSP_IBUF_HEADER_PAGE_NO
#define IBUF_TREE_ROOT_PAGE_NO FSP_IBUF_TREE_ROOT_PAGE_NO

View file

@ -37,6 +37,30 @@ 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_struct{
ulint size; /*!< current size of the ibuf index
@ -46,19 +70,25 @@ struct ibuf_struct{
ulint seg_size; /*!< allocated pages of the file
segment containing ibuf header and
tree */
ibool empty; /*!< after an insert to the ibuf tree
is performed, this is set to FALSE,
and if a contract operation finds
the tree empty, this is set to
TRUE */
ibool 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_inserts; /*!< number of inserts made to
the insert buffer */
ulint n_merges; /*!< number of pages merged */
ulint n_merged_recs; /*!< number of records 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 */
};
/************************************************************************//**
@ -105,7 +135,7 @@ ibuf_should_try(
if (ibuf_flush_count % 4 == 0) {
buf_LRU_try_free_flushed_blocks();
buf_LRU_try_free_flushed_blocks(NULL);
}
return(TRUE);
@ -114,6 +144,22 @@ ibuf_should_try(
return(FALSE);
}
/******************************************************************//**
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 */

View file

@ -1,6 +1,6 @@
/*****************************************************************************
Copyright (c) 1996, 2009, Innobase Oy. All Rights Reserved.
Copyright (c) 1996, 2010, Innobase Oy. 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
@ -43,7 +43,7 @@ extern ibool lock_print_waits;
#endif /* UNIV_DEBUG */
/* Buffer for storing information about the most recent deadlock error */
extern FILE* lock_latest_err_file;
extern ulint srv_n_lock_deadlock_count;
extern ulint srv_n_lock_deadlock_count;
/*********************************************************************//**
Gets the size of a lock struct.
@ -640,7 +640,7 @@ UNIV_INTERN
ulint
lock_number_of_rows_locked(
/*=======================*/
trx_t* trx); /*!< in: transaction */
const trx_t* trx); /*!< in: transaction */
/*******************************************************************//**
Check if a transaction holds any autoinc locks.
@return TRUE if the transaction holds any AUTOINC locks. */
@ -671,7 +671,7 @@ lock_get_type(
Gets the id of the transaction owning a lock.
@return transaction id */
UNIV_INTERN
ullint
trx_id_t
lock_get_trx_id(
/*============*/
const lock_t* lock); /*!< in: lock */
@ -700,7 +700,7 @@ lock_get_type_str(
Gets the id of the table on which the lock is.
@return id of the table */
UNIV_INTERN
ullint
table_id_t
lock_get_table_id(
/*==============*/
const lock_t* lock); /*!< in: lock */
@ -816,6 +816,7 @@ struct lock_op_struct{
/** The lock system struct */
struct lock_sys_struct{
hash_table_t* rec_hash; /*!< hash table of the record locks */
ulint rec_num;
};
/** The lock system */

View file

@ -766,6 +766,15 @@ struct log_struct{
#ifndef UNIV_HOTBACKUP
mutex_t mutex; /*!< mutex protecting the log */
#endif /* !UNIV_HOTBACKUP */
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. */
byte* buf_ptr; /* unaligned log buffer */
byte* buf; /*!< log buffer */
ulint buf_size; /*!< log buffer size in bytes */
@ -955,6 +964,19 @@ struct log_struct{
#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

View file

@ -435,7 +435,7 @@ log_free_check(void)
{
#ifdef UNIV_SYNC_DEBUG
ut_ad(sync_thread_levels_empty_gen(TRUE));
ut_ad(sync_thread_levels_empty_except_dict());
#endif /* UNIV_SYNC_DEBUG */
if (log_sys->check_flush_or_checkpoint) {

View file

@ -166,14 +166,14 @@ UNIV_INLINE
void
mach_write_to_6(
/*============*/
byte* b, /*!< in: pointer to 6 bytes where to store */
dulint n); /*!< in: dulint integer to be stored */
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 dulint integer */
@return 48-bit integer */
UNIV_INLINE
dulint
ib_uint64_t
mach_read_from_6(
/*=============*/
const byte* b) /*!< in: pointer to 6 bytes */
@ -185,14 +185,14 @@ UNIV_INLINE
void
mach_write_to_7(
/*============*/
byte* b, /*!< in: pointer to 7 bytes where to store */
dulint n); /*!< in: dulint integer to be stored */
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 dulint integer */
@return 56-bit integer */
UNIV_INLINE
dulint
ib_uint64_t
mach_read_from_7(
/*=============*/
const byte* b) /*!< in: pointer to 7 bytes */
@ -204,88 +204,69 @@ UNIV_INLINE
void
mach_write_to_8(
/*============*/
byte* b, /*!< in: pointer to 8 bytes where to store */
dulint n); /*!< in: dulint integer to be stored */
/*******************************************************//**
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_ull(
/*===========*/
byte* 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 dulint integer */
UNIV_INLINE
dulint
mach_read_from_8(
/*=============*/
const byte* b) /*!< in: pointer to 8 bytes */
__attribute__((nonnull, pure));
/********************************************************//**
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_ull(
/*==========*/
mach_read_from_8(
/*=============*/
const byte* b) /*!< in: pointer to 8 bytes */
__attribute__((nonnull, pure));
/*********************************************************//**
Writes a dulint in a compressed form (5..9 bytes).
Writes a 64-bit integer in a compressed form (5..9 bytes).
@return size in bytes */
UNIV_INLINE
ulint
mach_dulint_write_compressed(
/*=========================*/
byte* b, /*!< in: pointer to memory where to store */
dulint n); /*!< in: dulint integer to be stored */
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 dulint when written in the compressed form.
Returns the size of a 64-bit integer when written in the compressed form.
@return compressed size in bytes */
UNIV_INLINE
ulint
mach_dulint_get_compressed_size(
/*============================*/
dulint n); /*!< in: dulint integer to be stored */
mach_ull_get_compressed_size(
/*=========================*/
ib_uint64_t n); /*!< in: 64-bit integer to be stored */
/*********************************************************//**
Reads a dulint in a compressed form.
@return read dulint */
Reads a 64-bit integer in a compressed form.
@return the value read */
UNIV_INLINE
dulint
mach_dulint_read_compressed(
/*========================*/
ib_uint64_t
mach_ull_read_compressed(
/*=====================*/
const byte* b) /*!< in: pointer to memory from where to read */
__attribute__((nonnull, pure));
/*********************************************************//**
Writes a dulint in a compressed form (1..11 bytes).
Writes a 64-bit integer in a compressed form (1..11 bytes).
@return size in bytes */
UNIV_INLINE
ulint
mach_dulint_write_much_compressed(
/*==============================*/
byte* b, /*!< in: pointer to memory where to store */
dulint n); /*!< in: dulint integer to be stored */
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 dulint when written in the compressed form.
Returns the size of a 64-bit integer when written in the compressed form.
@return compressed size in bytes */
UNIV_INLINE
ulint
mach_dulint_get_much_compressed_size(
/*=================================*/
dulint n) /*!< in: dulint integer to be stored */
mach_ull_get_much_compressed_size(
/*==============================*/
ib_uint64_t n) /*!< in: 64-bit integer to be stored */
__attribute__((const));
/*********************************************************//**
Reads a dulint in a compressed form.
@return read dulint */
Reads a 64-bit integer in a compressed form.
@return the value read */
UNIV_INLINE
dulint
mach_dulint_read_much_compressed(
/*=============================*/
ib_uint64_t
mach_ull_read_much_compressed(
/*==========================*/
const byte* b) /*!< in: pointer to memory from where to read */
__attribute__((nonnull, pure));
/*********************************************************//**
@ -299,15 +280,16 @@ mach_parse_compressed(
byte* end_ptr,/*!< in: pointer to end of the buffer */
ulint* val); /*!< out: read value */
/*********************************************************//**
Reads a dulint 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
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_dulint_parse_compressed(
/*=========================*/
byte* ptr, /*!< in: pointer to buffer from where to read */
byte* end_ptr,/*!< in: pointer to end of the buffer */
dulint* val); /*!< out: read value */
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.

View file

@ -280,22 +280,6 @@ UNIV_INLINE
void
mach_write_to_8(
/*============*/
byte* b, /*!< in: pointer to 8 bytes where to store */
dulint n) /*!< in: dulint integer to be stored */
{
ut_ad(b);
mach_write_to_4(b, ut_dulint_get_high(n));
mach_write_to_4(b + 4, ut_dulint_get_low(n));
}
/*******************************************************//**
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_ull(
/*===========*/
byte* b, /*!< in: pointer to 8 bytes where to store */
ib_uint64_t n) /*!< in: 64-bit integer to be stored */
{
@ -305,35 +289,14 @@ mach_write_ull(
mach_write_to_4(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 dulint integer */
UNIV_INLINE
dulint
mach_read_from_8(
/*=============*/
const byte* b) /*!< in: pointer to 8 bytes */
{
ulint high;
ulint low;
ut_ad(b);
high = mach_read_from_4(b);
low = mach_read_from_4(b + 4);
return(ut_dulint_create(high, low));
}
/********************************************************//**
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_ull(
/*==========*/
mach_read_from_8(
/*=============*/
const byte* b) /*!< in: pointer to 8 bytes */
{
ib_uint64_t ull;
@ -351,34 +314,28 @@ UNIV_INLINE
void
mach_write_to_7(
/*============*/
byte* b, /*!< in: pointer to 7 bytes where to store */
dulint n) /*!< in: dulint integer to be stored */
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, ut_dulint_get_high(n));
mach_write_to_4(b + 3, ut_dulint_get_low(n));
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 dulint integer */
@return 56-bit integer */
UNIV_INLINE
dulint
ib_uint64_t
mach_read_from_7(
/*=============*/
const byte* b) /*!< in: pointer to 7 bytes */
{
ulint high;
ulint low;
ut_ad(b);
high = mach_read_from_3(b);
low = mach_read_from_4(b + 3);
return(ut_dulint_create(high, low));
return(ut_ull_create(mach_read_from_3(b), mach_read_from_4(b + 3)));
}
/*******************************************************//**
@ -388,162 +345,196 @@ UNIV_INLINE
void
mach_write_to_6(
/*============*/
byte* b, /*!< in: pointer to 6 bytes where to store */
dulint n) /*!< in: dulint integer to be stored */
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, ut_dulint_get_high(n));
mach_write_to_4(b + 2, ut_dulint_get_low(n));
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 dulint integer */
@return 48-bit integer */
UNIV_INLINE
dulint
ib_uint64_t
mach_read_from_6(
/*=============*/
const byte* b) /*!< in: pointer to 6 bytes */
{
ulint high;
ulint low;
ut_ad(b);
high = mach_read_from_2(b);
low = mach_read_from_4(b + 2);
return(ut_dulint_create(high, low));
return(ut_ull_create(mach_read_from_2(b), mach_read_from_4(b + 2)));
}
/*********************************************************//**
Writes a dulint in a compressed form (5..9 bytes).
Writes a 64-bit integer in a compressed form (5..9 bytes).
@return size in bytes */
UNIV_INLINE
ulint
mach_dulint_write_compressed(
/*=========================*/
byte* b, /*!< in: pointer to memory where to store */
dulint n) /*!< in: dulint integer to be stored */
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, ut_dulint_get_high(n));
mach_write_to_4(b + size, ut_dulint_get_low(n));
size = mach_write_compressed(b, (ulint) (n >> 32));
mach_write_to_4(b + size, (ulint) n);
return(size + 4);
}
/*********************************************************//**
Returns the size of a dulint when written in the compressed form.
Returns the size of a 64-bit integer when written in the compressed form.
@return compressed size in bytes */
UNIV_INLINE
ulint
mach_dulint_get_compressed_size(
/*============================*/
dulint n) /*!< in: dulint integer to be stored */
mach_ull_get_compressed_size(
/*=========================*/
ib_uint64_t n) /*!< in: 64-bit integer to be stored */
{
return(4 + mach_get_compressed_size(ut_dulint_get_high(n)));
return(4 + mach_get_compressed_size((ulint) (n >> 32)));
}
/*********************************************************//**
Reads a dulint in a compressed form.
@return read dulint */
Reads a 64-bit integer in a compressed form.
@return the value read */
UNIV_INLINE
dulint
mach_dulint_read_compressed(
/*========================*/
ib_uint64_t
mach_ull_read_compressed(
/*=====================*/
const byte* b) /*!< in: pointer to memory from where to read */
{
ulint high;
ulint low;
ulint size;
ib_uint64_t n;
ulint size;
ut_ad(b);
high = mach_read_compressed(b);
n = (ib_uint64_t) mach_read_compressed(b);
size = mach_get_compressed_size(high);
size = mach_get_compressed_size((ulint) n);
low = mach_read_from_4(b + size);
n <<= 32;
n |= (ib_uint64_t) mach_read_from_4(b + size);
return(ut_dulint_create(high, low));
return(n);
}
/*********************************************************//**
Writes a dulint in a compressed form (1..11 bytes).
Writes a 64-bit integer in a compressed form (1..11 bytes).
@return size in bytes */
UNIV_INLINE
ulint
mach_dulint_write_much_compressed(
/*==============================*/
byte* b, /*!< in: pointer to memory where to store */
dulint n) /*!< in: dulint integer to be stored */
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 (ut_dulint_get_high(n) == 0) {
return(mach_write_compressed(b, ut_dulint_get_low(n)));
if (!(n >> 32)) {
return(mach_write_compressed(b, (ulint) n));
}
*b = (byte)0xFF;
size = 1 + mach_write_compressed(b + 1, ut_dulint_get_high(n));
size = 1 + mach_write_compressed(b + 1, (ulint) (n >> 32));
size += mach_write_compressed(b + size, ut_dulint_get_low(n));
size += mach_write_compressed(b + size, (ulint) n & 0xFFFFFFFF);
return(size);
}
/*********************************************************//**
Returns the size of a dulint when written in the compressed form.
Returns the size of a 64-bit integer when written in the compressed form.
@return compressed size in bytes */
UNIV_INLINE
ulint
mach_dulint_get_much_compressed_size(
/*=================================*/
dulint n) /*!< in: dulint integer to be stored */
mach_ull_get_much_compressed_size(
/*==============================*/
ib_uint64_t n) /*!< in: 64-bit integer to be stored */
{
if (0 == ut_dulint_get_high(n)) {
return(mach_get_compressed_size(ut_dulint_get_low(n)));
if (!(n >> 32)) {
return(mach_get_compressed_size((ulint) n));
}
return(1 + mach_get_compressed_size(ut_dulint_get_high(n))
+ mach_get_compressed_size(ut_dulint_get_low(n)));
return(1 + mach_get_compressed_size((ulint) (n >> 32))
+ mach_get_compressed_size((ulint) n & ULINT32_MASK));
}
/*********************************************************//**
Reads a dulint in a compressed form.
@return read dulint */
Reads a 64-bit integer in a compressed form.
@return the value read */
UNIV_INLINE
dulint
mach_dulint_read_much_compressed(
/*=============================*/
ib_uint64_t
mach_ull_read_much_compressed(
/*==========================*/
const byte* b) /*!< in: pointer to memory from where to read */
{
ulint high;
ulint low;
ulint size;
ib_uint64_t n;
ulint size;
ut_ad(b);
if (*b != (byte)0xFF) {
high = 0;
n = 0;
size = 0;
} else {
high = mach_read_compressed(b + 1);
n = (ib_uint64_t) mach_read_compressed(b + 1);
size = 1 + mach_get_compressed_size(high);
size = 1 + mach_get_compressed_size((ulint) n);
n <<= 32;
}
low = mach_read_compressed(b + size);
n |= mach_read_compressed(b + size);
return(ut_dulint_create(high, low));
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
/*********************************************************//**

View file

@ -359,7 +359,7 @@ struct mem_block_info_struct {
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
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

View file

@ -350,27 +350,27 @@ mem_heap_get_top(
ulint n) /*!< in: size of the topmost element */
{
mem_block_t* block;
void* buf;
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);
buf = (byte*) block + mem_block_get_free(block) - MEM_SPACE_NEEDED(n);
#ifdef UNIV_MEM_DEBUG
ut_ad(mem_block_get_start(block) <=(ulint)((byte*)buf - (byte*)block));
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 = (byte*)buf + MEM_FIELD_HEADER_SIZE;
buf += MEM_FIELD_HEADER_SIZE;
/* Check that the field lengths agree */
ut_ad(n == (ulint)mem_field_header_get_len(buf));
ut_ad(n == mem_field_header_get_len(buf));
#endif
return(buf);
return((void*) buf);
}
/*****************************************************************//**

View file

@ -47,11 +47,11 @@ Writes 8 bytes to a file page buffered in the buffer pool.
Writes the corresponding log record to the mini-transaction log. */
UNIV_INTERN
void
mlog_write_dulint(
/*==============*/
byte* ptr, /*!< in: pointer where to write */
dulint val, /*!< in: value to write */
mtr_t* mtr); /*!< in: mini-transaction handle */
mlog_write_ull(
/*===========*/
byte* ptr, /*!< in: pointer where to write */
ib_uint64_t val, /*!< in: value to write */
mtr_t* mtr); /*!< in: mini-transaction handle */
/********************************************************//**
Writes a string to a file page buffered in the buffer pool. Writes the
corresponding log record to the mini-transaction log. */
@ -125,13 +125,13 @@ mlog_catenate_ulint_compressed(
mtr_t* mtr, /*!< in: mtr */
ulint val); /*!< in: value to write */
/********************************************************//**
Catenates a compressed dulint to mlog. */
Catenates a compressed 64-bit integer to mlog. */
UNIV_INLINE
void
mlog_catenate_dulint_compressed(
/*============================*/
mtr_t* mtr, /*!< in: mtr */
dulint val); /*!< in: value to write */
mlog_catenate_ull_compressed(
/*=========================*/
mtr_t* mtr, /*!< in: mtr */
ib_uint64_t val); /*!< in: value to write */
/********************************************************//**
Opens a buffer to mlog. It must be closed with mlog_close.
@return buffer, NULL if log mode MTR_LOG_NONE */
@ -183,7 +183,7 @@ mlog_parse_initial_log_record(
ulint* space, /*!< out: space id */
ulint* page_no);/*!< out: page number */
/********************************************************//**
Parses a log record written by mlog_write_ulint or mlog_write_dulint.
Parses a log record written by mlog_write_ulint or mlog_write_ull.
@return parsed record end, NULL if not a complete record */
UNIV_INTERN
byte*

View file

@ -142,13 +142,13 @@ mlog_catenate_ulint_compressed(
}
/********************************************************//**
Catenates a compressed dulint to mlog. */
Catenates a compressed 64-bit integer to mlog. */
UNIV_INLINE
void
mlog_catenate_dulint_compressed(
/*============================*/
mtr_t* mtr, /*!< in: mtr */
dulint val) /*!< in: value to write */
mlog_catenate_ull_compressed(
/*=========================*/
mtr_t* mtr, /*!< in: mtr */
ib_uint64_t val) /*!< in: value to write */
{
byte* log_ptr;
@ -160,7 +160,7 @@ mlog_catenate_dulint_compressed(
return;
}
log_ptr += mach_dulint_write_compressed(log_ptr, val);
log_ptr += mach_ull_write_compressed(log_ptr, val);
mlog_close(mtr, log_ptr);
}

View file

@ -190,21 +190,21 @@ functions). The page number parameter was originally written as 0. @{ */
/* @} */
/***************************************************************//**
Starts a mini-transaction and creates a mini-transaction handle
and buffer in the memory buffer given by the caller.
@return mtr buffer which also acts as the mtr handle */
Starts a mini-transaction. */
UNIV_INLINE
mtr_t*
void
mtr_start(
/*======*/
mtr_t* mtr); /*!< in: memory buffer for the mtr buffer */
mtr_t* mtr) /*!< out: mini-transaction */
__attribute__((nonnull));
/***************************************************************//**
Commits a mini-transaction. */
UNIV_INTERN
void
mtr_commit(
/*=======*/
mtr_t* mtr); /*!< in: mini-transaction */
mtr_t* mtr) /*!< in/out: mini-transaction */
__attribute__((nonnull));
/**********************************************************//**
Sets and returns a savepoint in mtr.
@return savepoint */
@ -264,15 +264,6 @@ mtr_read_ulint(
const byte* ptr, /*!< in: pointer from where to read */
ulint type, /*!< in: MLOG_1BYTE, MLOG_2BYTES, MLOG_4BYTES */
mtr_t* mtr); /*!< in: mini-transaction handle */
/********************************************************//**
Reads 8 bytes from a file page buffered in the buffer pool.
@return value read */
UNIV_INTERN
dulint
mtr_read_dulint(
/*============*/
const byte* ptr, /*!< in: pointer from where to read */
mtr_t* mtr); /*!< in: mini-transaction handle */
#ifndef UNIV_HOTBACKUP
/*********************************************************************//**
This macro locks an rw-lock in s-mode. */
@ -387,6 +378,8 @@ struct mtr_struct{
#endif
dyn_array_t memo; /*!< memo stack for locks etc. */
dyn_array_t log; /*!< mini-transaction log */
ibool inside_ibuf;
/*!< TRUE if inside ibuf changes */
ibool modifications;
/* TRUE if the mtr made modifications to
buffer pool pages */

View file

@ -30,26 +30,23 @@ Created 11/26/1995 Heikki Tuuri
#include "mach0data.h"
/***************************************************************//**
Starts a mini-transaction and creates a mini-transaction handle
and a buffer in the memory buffer given by the caller.
@return mtr buffer which also acts as the mtr handle */
Starts a mini-transaction. */
UNIV_INLINE
mtr_t*
void
mtr_start(
/*======*/
mtr_t* mtr) /*!< in: memory buffer for the mtr buffer */
mtr_t* mtr) /*!< out: mini-transaction */
{
dyn_array_create(&(mtr->memo));
dyn_array_create(&(mtr->log));
mtr->log_mode = MTR_LOG_ALL;
mtr->modifications = FALSE;
mtr->inside_ibuf = FALSE;
mtr->n_log_recs = 0;
ut_d(mtr->state = MTR_ACTIVE);
ut_d(mtr->magic_n = MTR_MAGIC_N);
return(mtr);
}
/***************************************************//**
@ -160,7 +157,7 @@ mtr_memo_contains(
while (offset > 0) {
offset -= sizeof(mtr_memo_slot_t);
slot = dyn_array_get_element(memo, offset);
slot = (mtr_memo_slot_t*) dyn_array_get_element(memo, offset);
if ((object == slot->object) && (type == slot->type)) {

View file

@ -1,33 +0,0 @@
/*****************************************************************************
Copyright (c) 2007, 2009, Innobase Oy. 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., 59 Temple
Place, Suite 330, Boston, MA 02111-1307 USA
*****************************************************************************/
/**************************************************//**
@file include/mysql_addons.h
This file contains functions that need to be added to
MySQL code but have not been added yet.
Whenever you add a function here submit a MySQL bug
report (feature request) with the implementation. Then
write the bug number in the comment before the
function in this file.
When MySQL commits the function it can be deleted from
here. In a perfect world this file exists but is empty.
Created November 07, 2007 Vasil Dimov
*******************************************************/

View file

@ -77,29 +77,23 @@ extern ulint os_n_pending_writes;
#ifdef __WIN__
/** File handle */
#define os_file_t HANDLE
# define os_file_t HANDLE
/** Convert a C file descriptor to a native file handle
@param fd file descriptor
@return native file handle */
#define OS_FILE_FROM_FD(fd) (HANDLE) _get_osfhandle(fd)
# define OS_FILE_FROM_FD(fd) (HANDLE) _get_osfhandle(fd)
#else
/** File handle */
typedef int os_file_t;
/** Convert a C file descriptor to a native file handle
@param fd file descriptor
@return native file handle */
#define OS_FILE_FROM_FD(fd) fd
# define OS_FILE_FROM_FD(fd) fd
#endif
/** Umask for creating files */
extern ulint os_innodb_umask;
/** If this flag is TRUE, then we will use the native aio of the
OS (provided we compiled Innobase with it in), otherwise we will
use simulated aio we build below with threads */
extern ibool os_aio_use_native_aio;
/** The next value should be smaller or equal to the smallest sector size used
on any disk. A log block is required to be a portion of disk which is written
so that if the start and the end of a block get written to disk, then the
@ -142,7 +136,8 @@ log. */
#define OS_FILE_SHARING_VIOLATION 76
#define OS_FILE_ERROR_NOT_SPECIFIED 77
#define OS_FILE_INSUFFICIENT_RESOURCE 78
#define OS_FILE_OPERATION_ABORTED 79
#define OS_FILE_AIO_INTERRUPTED 79
#define OS_FILE_OPERATION_ABORTED 80
/* @} */
/** Types for aio operations @{ */
@ -183,6 +178,13 @@ log. */
#define OS_WIN95 2 /*!< Microsoft Windows 95 */
#define OS_WINNT 3 /*!< Microsoft Windows NT 3.x */
#define OS_WIN2000 4 /*!< Microsoft Windows 2000 */
#define OS_WINXP 5 /*!< Microsoft Windows XP
or Windows Server 2003 */
#define OS_WINVISTA 6 /*!< Microsoft Windows Vista
or Windows Server 2008 */
#define OS_WIN7 7 /*!< Microsoft Windows 7
or Windows Server 2008 R2 */
extern ulint os_n_file_reads;
extern ulint os_n_file_writes;
@ -190,6 +192,164 @@ extern ulint os_n_fsyncs;
extern ulint srv_log_block_size;
#ifdef UNIV_PFS_IO
/* Keys to register InnoDB I/O with performance schema */
extern mysql_pfs_key_t innodb_file_data_key;
extern mysql_pfs_key_t innodb_file_log_key;
extern mysql_pfs_key_t innodb_file_temp_key;
/* Following four macros are instumentations to register
various file I/O operations with performance schema.
1) register_pfs_file_open_begin() and register_pfs_file_open_end() are
used to register file creation, opening, closing and renaming.
2) register_pfs_file_io_begin() and register_pfs_file_io_end() are
used to register actual file read, write and flush */
# define register_pfs_file_open_begin(state, locker, key, op, name, \
src_file, src_line) \
do { \
if (PSI_server) { \
locker = PSI_server->get_thread_file_name_locker( \
state, key, op, name, &locker); \
if (locker) { \
PSI_server->start_file_open_wait( \
locker, src_file, src_line); \
} \
} \
} while (0)
# define register_pfs_file_open_end(locker, file) \
do { \
if (locker) { \
PSI_server->end_file_open_wait_and_bind_to_descriptor( \
locker, file); \
} \
} while (0)
# define register_pfs_file_io_begin(state, locker, file, count, op, \
src_file, src_line) \
do { \
if (PSI_server) { \
locker = PSI_server->get_thread_file_descriptor_locker( \
state, file, op); \
if (locker) { \
PSI_server->start_file_wait( \
locker, count, src_file, src_line); \
} \
} \
} while (0)
# define register_pfs_file_io_end(locker, count) \
do { \
if (locker) { \
PSI_server->end_file_wait(locker, count); \
} \
} while (0)
#endif /* UNIV_PFS_IO */
/* Following macros/functions are file I/O APIs that would be performance
schema instrumented if "UNIV_PFS_IO" is defined. They would point to
wrapper functions with performance schema instrumentation in such case.
os_file_create
os_file_create_simple
os_file_create_simple_no_error_handling
os_file_close
os_file_rename
os_aio
os_file_read
os_file_read_no_error_handling
os_file_write
The wrapper functions have the prefix of "innodb_". */
#ifdef UNIV_PFS_IO
# define os_file_create(key, name, create, purpose, type, success) \
pfs_os_file_create_func(key, name, create, purpose, type, \
success, __FILE__, __LINE__)
# define os_file_create_simple(key, name, create, access, success) \
pfs_os_file_create_simple_func(key, name, create, access, \
success, __FILE__, __LINE__)
# define os_file_create_simple_no_error_handling( \
key, name, create_mode, access, success) \
pfs_os_file_create_simple_no_error_handling_func( \
key, name, create_mode, access, success, __FILE__, __LINE__)
# define os_file_close(file) \
pfs_os_file_close_func(file, __FILE__, __LINE__)
# define os_aio(type, mode, name, file, buf, offset, offset_high, \
n, message1, message2, space_id, trx) \
pfs_os_aio_func(type, mode, name, file, buf, offset, \
offset_high, n, message1, message2, space_id, trx,\
__FILE__, __LINE__)
# define os_file_read(file, buf, offset, offset_high, n) \
pfs_os_file_read_func(file, buf, offset, offset_high, n, NULL, \
__FILE__, __LINE__)
# define os_file_read_trx(file, buf, offset, offset_high, n, trx) \
pfs_os_file_read_func(file, buf, offset, offset_high, n, trx, \
__FILE__, __LINE__)
# define os_file_read_no_error_handling(file, buf, offset, \
offset_high, n) \
pfs_os_file_read_no_error_handling_func(file, buf, offset, \
offset_high, n, \
__FILE__, __LINE__)
# define os_file_write(name, file, buf, offset, offset_high, n) \
pfs_os_file_write_func(name, file, buf, offset, offset_high, \
n, __FILE__, __LINE__)
# define os_file_flush(file) \
pfs_os_file_flush_func(file, __FILE__, __LINE__)
# define os_file_rename(key, oldpath, newpath) \
pfs_os_file_rename_func(key, oldpath, newpath, __FILE__, __LINE__)
#else /* UNIV_PFS_IO */
/* If UNIV_PFS_IO is not defined, these I/O APIs point
to original un-instrumented file I/O APIs */
# define os_file_create(key, name, create, purpose, type, success) \
os_file_create_func(name, create, purpose, type, success)
# define os_file_create_simple(key, name, create, access, success) \
os_file_create_simple_func(name, create_mode, access, success)
# define os_file_create_simple_no_error_handling( \
key, name, create_mode, access, success) \
os_file_create_simple_no_error_handling_func( \
name, create_mode, access, success)
# define os_file_close(file) os_file_close_func(file)
# define os_aio(type, mode, name, file, buf, offset, offset_high, \
n, message1, message2, space_id, trx) \
os_aio_func(type, mode, name, file, buf, offset, offset_high, n,\
message1, message2, space_id, trx)
# define os_file_read(file, buf, offset, offset_high, n) \
os_file_read_func(file, buf, offset, offset_high, n, NULL)
# define os_file_read_trx(file, buf, offset, offset_high, n, trx) \
os_file_read_func(file, buf, offset, offset_high, n, trx)
# define os_file_read_no_error_handling(file, buf, offset, \
offset_high, n) \
os_file_read_no_error_handling_func(file, buf, offset, offset_high, n)
# define os_file_write(name, file, buf, offset, offset_high, n) \
os_file_write_func(name, file, buf, offset, offset_high, n)
# define os_file_flush(file) os_file_flush_func(file)
# define os_file_rename(key, oldpath, newpath) \
os_file_rename_func(oldpath, newpath)
#endif /* UNIV_PFS_IO */
/* File types for directory entry data type */
enum os_file_type_enum{
@ -223,13 +383,16 @@ typedef HANDLE os_file_dir_t; /*!< directory stream */
typedef DIR* os_file_dir_t; /*!< directory stream */
#endif
#ifdef __WIN__
/***********************************************************************//**
Gets the operating system version. Currently works only on Windows.
@return OS_WIN95, OS_WIN31, OS_WINNT, or OS_WIN2000 */
@return OS_WIN95, OS_WIN31, OS_WINNT, OS_WIN2000, OS_WINXP, OS_WINVISTA,
OS_WIN7. */
UNIV_INTERN
ulint
os_get_os_version(void);
/*===================*/
#endif /* __WIN__ */
#ifndef UNIV_HOTBACKUP
/****************************************************************//**
Creates the seek mutexes used in positioned reads and writes. */
@ -240,8 +403,6 @@ os_io_init_simple(void);
/***********************************************************************//**
Creates a temporary file. This function is like tmpfile(3), but
the temporary file is created in the MySQL temporary directory.
On Netware, this function is like tmpfile(3), because the C run-time
library of Netware does not expose the delete-on-close flag.
@return temporary file handle, or NULL on error */
FILE*
@ -299,13 +460,15 @@ os_file_create_directory(
ibool fail_if_exists);/*!< in: if TRUE, pre-existing directory
is treated as an error. */
/****************************************************************//**
NOTE! Use the corresponding macro os_file_create_simple(), not directly
this function!
A simple function to open or create a file.
@return own: handle to the file, not defined if error, error number
can be retrieved with os_file_get_last_error */
UNIV_INTERN
os_file_t
os_file_create_simple(
/*==================*/
os_file_create_simple_func(
/*=======================*/
const char* name, /*!< in: name of the file or path as a
null-terminated string */
ulint create_mode,/*!< in: OS_FILE_OPEN if an existing file is
@ -319,13 +482,15 @@ os_file_create_simple(
OS_FILE_READ_WRITE */
ibool* success);/*!< out: TRUE if succeed, FALSE if error */
/****************************************************************//**
NOTE! Use the corresponding macro
os_file_create_simple_no_error_handling(), not directly this function!
A simple function to open or create a file.
@return own: handle to the file, not defined if error, error number
can be retrieved with os_file_get_last_error */
UNIV_INTERN
os_file_t
os_file_create_simple_no_error_handling(
/*====================================*/
os_file_create_simple_no_error_handling_func(
/*=========================================*/
const char* name, /*!< in: name of the file or path as a
null-terminated string */
ulint create_mode,/*!< in: OS_FILE_OPEN if an existing file
@ -349,13 +514,15 @@ os_file_set_nocache(
const char* operation_name);/*!< in: "open" or "create"; used in the
diagnostic message */
/****************************************************************//**
NOTE! Use the corresponding macro os_file_create(), not directly
this function!
Opens an existing file or creates a new.
@return own: handle to the file, not defined if error, error number
can be retrieved with os_file_get_last_error */
UNIV_INTERN
os_file_t
os_file_create(
/*===========*/
os_file_create_func(
/*================*/
const char* name, /*!< in: name of the file or path as a
null-terminated string */
ulint create_mode,/*!< in: OS_FILE_OPEN if an existing file
@ -393,25 +560,261 @@ os_file_delete_if_exists(
/*=====================*/
const char* name); /*!< in: file path as a null-terminated string */
/***********************************************************************//**
NOTE! Use the corresponding macro os_file_rename(), not directly
this function!
Renames a file (can also move it to another directory). It is safest that the
file is closed before calling this function.
@return TRUE if success */
UNIV_INTERN
ibool
os_file_rename(
/*===========*/
os_file_rename_func(
/*================*/
const char* oldpath, /*!< in: old file path as a
null-terminated string */
const char* newpath); /*!< in: new file path */
/***********************************************************************//**
NOTE! Use the corresponding macro os_file_close(), not directly this
function!
Closes a file handle. In case of error, error number can be retrieved with
os_file_get_last_error.
@return TRUE if success */
UNIV_INTERN
ibool
os_file_close(
/*==========*/
os_file_close_func(
/*===============*/
os_file_t file); /*!< in, own: handle to a file */
#ifdef UNIV_PFS_IO
/****************************************************************//**
NOTE! Please use the corresponding macro os_file_create_simple(),
not directly this function!
A performance schema instrumented wrapper function for
os_file_create_simple() which opens or creates a file.
@return own: handle to the file, not defined if error, error number
can be retrieved with os_file_get_last_error */
UNIV_INLINE
os_file_t
pfs_os_file_create_simple_func(
/*===========================*/
mysql_pfs_key_t key, /*!< in: Performance Schema Key */
const char* name, /*!< in: name of the file or path as a
null-terminated string */
ulint create_mode,/*!< in: OS_FILE_OPEN if an existing file is
opened (if does not exist, error), or
OS_FILE_CREATE if a new file is created
(if exists, error), or
OS_FILE_CREATE_PATH if new file
(if exists, error) and subdirectories along
its path are created (if needed)*/
ulint access_type,/*!< in: OS_FILE_READ_ONLY or
OS_FILE_READ_WRITE */
ibool* success,/*!< out: TRUE if succeed, FALSE if error */
const char* src_file,/*!< in: file name where func invoked */
ulint src_line);/*!< in: line where the func invoked */
/****************************************************************//**
NOTE! Please use the corresponding macro
os_file_create_simple_no_error_handling(), not directly this function!
A performance schema instrumented wrapper function for
os_file_create_simple_no_error_handling(). Add instrumentation to
monitor file creation/open.
@return own: handle to the file, not defined if error, error number
can be retrieved with os_file_get_last_error */
UNIV_INLINE
os_file_t
pfs_os_file_create_simple_no_error_handling_func(
/*=============================================*/
mysql_pfs_key_t key, /*!< in: Performance Schema Key */
const char* name, /*!< in: name of the file or path as a
null-terminated string */
ulint create_mode,/*!< in: OS_FILE_OPEN if an existing file
is opened (if does not exist, error), or
OS_FILE_CREATE if a new file is created
(if exists, error) */
ulint access_type,/*!< in: OS_FILE_READ_ONLY,
OS_FILE_READ_WRITE, or
OS_FILE_READ_ALLOW_DELETE; the last option is
used by a backup program reading the file */
ibool* success,/*!< out: TRUE if succeed, FALSE if error */
const char* src_file,/*!< in: file name where func invoked */
ulint src_line);/*!< in: line where the func invoked */
/****************************************************************//**
NOTE! Please use the corresponding macro os_file_create(), not directly
this function!
A performance schema wrapper function for os_file_create().
Add instrumentation to monitor file creation/open.
@return own: handle to the file, not defined if error, error number
can be retrieved with os_file_get_last_error */
UNIV_INLINE
os_file_t
pfs_os_file_create_func(
/*====================*/
mysql_pfs_key_t key, /*!< in: Performance Schema Key */
const char* name, /*!< in: name of the file or path as a
null-terminated string */
ulint create_mode,/*!< in: OS_FILE_OPEN if an existing file
is opened (if does not exist, error), or
OS_FILE_CREATE if a new file is created
(if exists, error),
OS_FILE_OVERWRITE if a new file is created
or an old overwritten;
OS_FILE_OPEN_RAW, if a raw device or disk
partition should be opened */
ulint purpose,/*!< in: OS_FILE_AIO, if asynchronous,
non-buffered i/o is desired,
OS_FILE_NORMAL, if any normal file;
NOTE that it also depends on type, os_aio_..
and srv_.. variables whether we really use
async i/o or unbuffered i/o: look in the
function source code for the exact rules */
ulint type, /*!< in: OS_DATA_FILE or OS_LOG_FILE */
ibool* success,/*!< out: TRUE if succeed, FALSE if error */
const char* src_file,/*!< in: file name where func invoked */
ulint src_line);/*!< in: line where the func invoked */
/***********************************************************************//**
NOTE! Please use the corresponding macro os_file_close(), not directly
this function!
A performance schema instrumented wrapper function for os_file_close().
@return TRUE if success */
UNIV_INLINE
ibool
pfs_os_file_close_func(
/*===================*/
os_file_t file, /*!< in, own: handle to a file */
const char* src_file,/*!< in: file name where func invoked */
ulint src_line);/*!< in: line where the func invoked */
/*******************************************************************//**
NOTE! Please use the corresponding macro os_file_read(), not directly
this function!
This is the performance schema instrumented wrapper function for
os_file_read() which requests a synchronous read operation.
@return TRUE if request was successful, FALSE if fail */
UNIV_INLINE
ibool
pfs_os_file_read_func(
/*==================*/
os_file_t file, /*!< in: handle to a file */
void* buf, /*!< in: buffer where to read */
ulint offset, /*!< in: least significant 32 bits of file
offset where to read */
ulint offset_high,/*!< in: most significant 32 bits of
offset */
ulint n, /*!< in: number of bytes to read */
trx_t* trx,
const char* src_file,/*!< in: file name where func invoked */
ulint src_line);/*!< in: line where the func invoked */
/*******************************************************************//**
NOTE! Please use the corresponding macro os_file_read_no_error_handling(),
not directly this function!
This is the performance schema instrumented wrapper function for
os_file_read_no_error_handling_func() which requests a synchronous
read operation.
@return TRUE if request was successful, FALSE if fail */
UNIV_INLINE
ibool
pfs_os_file_read_no_error_handling_func(
/*====================================*/
os_file_t file, /*!< in: handle to a file */
void* buf, /*!< in: buffer where to read */
ulint offset, /*!< in: least significant 32 bits of file
offset where to read */
ulint offset_high,/*!< in: most significant 32 bits of
offset */
ulint n, /*!< in: number of bytes to read */
const char* src_file,/*!< in: file name where func invoked */
ulint src_line);/*!< in: line where the func invoked */
/*******************************************************************//**
NOTE! Please use the corresponding macro os_aio(), not directly this
function!
Performance schema wrapper function of os_aio() which requests
an asynchronous i/o operation.
@return TRUE if request was queued successfully, FALSE if fail */
UNIV_INLINE
ibool
pfs_os_aio_func(
/*============*/
ulint type, /*!< in: OS_FILE_READ or OS_FILE_WRITE */
ulint mode, /*!< in: OS_AIO_NORMAL etc. I/O mode */
const char* name, /*!< in: name of the file or path as a
null-terminated string */
os_file_t file, /*!< in: handle to a file */
void* buf, /*!< in: buffer where to read or from which
to write */
ulint offset, /*!< in: least significant 32 bits of file
offset where to read or write */
ulint offset_high,/*!< in: most significant 32 bits of
offset */
ulint n, /*!< in: number of bytes to read or write */
fil_node_t* message1,/*!< in: message for the aio handler
(can be used to identify a completed
aio operation); ignored if mode is
OS_AIO_SYNC */
void* message2,/*!< in: message for the aio handler
(can be used to identify a completed
aio operation); ignored if mode is
OS_AIO_SYNC */
ulint space_id,
trx_t* trx,
const char* src_file,/*!< in: file name where func invoked */
ulint src_line);/*!< in: line where the func invoked */
/*******************************************************************//**
NOTE! Please use the corresponding macro os_file_write(), not directly
this function!
This is the performance schema instrumented wrapper function for
os_file_write() which requests a synchronous write operation.
@return TRUE if request was successful, FALSE if fail */
UNIV_INLINE
ibool
pfs_os_file_write_func(
/*===================*/
const char* name, /*!< in: name of the file or path as a
null-terminated string */
os_file_t file, /*!< in: handle to a file */
const void* buf, /*!< in: buffer from which to write */
ulint offset, /*!< in: least significant 32 bits of file
offset where to write */
ulint offset_high,/*!< in: most significant 32 bits of
offset */
ulint n, /*!< in: number of bytes to write */
const char* src_file,/*!< in: file name where func invoked */
ulint src_line);/*!< in: line where the func invoked */
/***********************************************************************//**
NOTE! Please use the corresponding macro os_file_flush(), not directly
this function!
This is the performance schema instrumented wrapper function for
os_file_flush() which flushes the write buffers of a given file to the disk.
Flushes the write buffers of a given file to the disk.
@return TRUE if success */
UNIV_INLINE
ibool
pfs_os_file_flush_func(
/*===================*/
os_file_t file, /*!< in, own: handle to a file */
const char* src_file,/*!< in: file name where func invoked */
ulint src_line);/*!< in: line where the func invoked */
/***********************************************************************//**
NOTE! Please use the corresponding macro os_file_rename(), not directly
this function!
This is the performance schema instrumented wrapper function for
os_file_rename()
@return TRUE if success */
UNIV_INLINE
ibool
pfs_os_file_rename_func(
/*====================*/
mysql_pfs_key_t key, /*!< in: Performance Schema Key */
const char* oldpath,/*!< in: old file path as a null-terminated
string */
const char* newpath,/*!< in: new file path */
const char* src_file,/*!< in: file name where func invoked */
ulint src_line);/*!< in: line where the func invoked */
#endif /* UNIV_PFS_IO */
#ifdef UNIV_HOTBACKUP
/***********************************************************************//**
Closes a file handle.
@ -463,12 +866,13 @@ os_file_set_eof(
/*============*/
FILE* file); /*!< in: file to be truncated */
/***********************************************************************//**
NOTE! Use the corresponding macro os_file_flush(), not directly this function!
Flushes the write buffers of a given file to the disk.
@return TRUE if success */
UNIV_INTERN
ibool
os_file_flush(
/*==========*/
os_file_flush_func(
/*===============*/
os_file_t file); /*!< in, own: handle to a file */
/***********************************************************************//**
Retrieves the last error number if an error occurs in a file io function.
@ -483,15 +887,13 @@ os_file_get_last_error(
ibool report_all_errors); /*!< in: TRUE if we want an error message
printed of all errors */
/*******************************************************************//**
NOTE! Use the corresponding macro os_file_read(), not directly this function!
Requests a synchronous read operation.
@return TRUE if request was successful, FALSE if fail */
#define os_file_read(file, buf, offset, offset_high, n) \
_os_file_read(file, buf, offset, offset_high, n, NULL)
UNIV_INTERN
ibool
_os_file_read(
/*=========*/
os_file_read_func(
/*==============*/
os_file_t file, /*!< in: handle to a file */
void* buf, /*!< in: buffer where to read */
ulint offset, /*!< in: least significant 32 bits of file
@ -512,13 +914,15 @@ os_file_read_string(
char* str, /*!< in: buffer where to read */
ulint size); /*!< in: size of buffer */
/*******************************************************************//**
NOTE! Use the corresponding macro os_file_read_no_error_handling(),
not directly this function!
Requests a synchronous positioned read operation. This function does not do
any error handling. In case of error it returns FALSE.
@return TRUE if request was successful, FALSE if fail */
UNIV_INTERN
ibool
os_file_read_no_error_handling(
/*===========================*/
os_file_read_no_error_handling_func(
/*================================*/
os_file_t file, /*!< in: handle to a file */
void* buf, /*!< in: buffer where to read */
ulint offset, /*!< in: least significant 32 bits of file
@ -528,12 +932,14 @@ os_file_read_no_error_handling(
ulint n); /*!< in: number of bytes to read */
/*******************************************************************//**
NOTE! Use the corresponding macro os_file_write(), not directly this
function!
Requests a synchronous write operation.
@return TRUE if request was successful, FALSE if fail */
UNIV_INTERN
ibool
os_file_write(
/*==========*/
os_file_write_func(
/*===============*/
const char* name, /*!< in: name of the file or path as a
null-terminated string */
os_file_t file, /*!< in: handle to a file */
@ -602,7 +1008,7 @@ respectively. The caller must create an i/o handler thread for each
segment in these arrays. This function also creates the sync array.
No i/o handler thread needs to be created for that */
UNIV_INTERN
void
ibool
os_aio_init(
/*========*/
ulint n_per_seg, /*<! in: maximum number of pending aio
@ -619,12 +1025,13 @@ os_aio_free(void);
/*=============*/
/*******************************************************************//**
NOTE! Use the corresponding macro os_aio(), not directly this function!
Requests an asynchronous i/o operation.
@return TRUE if request was queued successfully, FALSE if fail */
UNIV_INTERN
ibool
os_aio(
/*===*/
os_aio_func(
/*========*/
ulint type, /*!< in: OS_FILE_READ or OS_FILE_WRITE */
ulint mode, /*!< in: OS_AIO_NORMAL, ..., possibly ORed
to OS_AIO_SIMULATED_WAKE_LATER: the
@ -785,7 +1192,7 @@ os_file_get_status(
os_file_stat_t* stat_info); /*!< information of a file in a
directory */
#if !defined(UNIV_HOTBACKUP) && !defined(__NETWARE__)
#if !defined(UNIV_HOTBACKUP)
/*********************************************************************//**
Creates a temporary file that will be deleted on close.
This function is defined in ha_innodb.cc.
@ -794,6 +1201,39 @@ UNIV_INTERN
int
innobase_mysql_tmpfile(void);
/*========================*/
#endif /* !UNIV_HOTBACKUP && !__NETWARE__ */
#endif /* !UNIV_HOTBACKUP */
#if defined(LINUX_NATIVE_AIO)
/**************************************************************************
This function is only used in Linux native asynchronous i/o.
Waits for an aio operation to complete. This function is used to wait the
for completed requests. The aio array of pending requests is divided
into segments. The thread specifies which segment or slot it wants to wait
for. NOTE: this function will also take care of freeing the aio slot,
therefore no other thread is allowed to do the freeing!
@return TRUE if the IO was successful */
UNIV_INTERN
ibool
os_aio_linux_handle(
/*================*/
ulint global_seg, /*!< in: segment number in the aio array
to wait for; segment 0 is the ibuf
i/o thread, segment 1 is log i/o thread,
then follow the non-ibuf read threads,
and the last are the non-ibuf write
threads. */
fil_node_t**message1, /*!< out: the messages passed with the */
void** message2, /*!< aio request; note that in case the
aio operation failed, these output
parameters are valid and can be used to
restart the operation. */
ulint* type, /*!< out: OS_FILE_WRITE or ..._READ */
ulint* space_id);
#endif /* LINUX_NATIVE_AIO */
#ifndef UNIV_NONINL
#include "os0file.ic"
#endif
#endif

421
include/os0file.ic Normal file
View file

@ -0,0 +1,421 @@
/*****************************************************************************
Copyright (c) 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., 59 Temple
Place, Suite 330, Boston, MA 02111-1307 USA
*****************************************************************************/
/**************************************************//**
@file include/os0file.ic
The interface to the operating system file io
Created 2/20/2010 Jimmy Yang
*******************************************************/
#include "univ.i"
#ifdef UNIV_PFS_IO
/****************************************************************//**
NOTE! Please use the corresponding macro os_file_create_simple(),
not directly this function!
A performance schema instrumented wrapper function for
os_file_create_simple() which opens or creates a file.
@return own: handle to the file, not defined if error, error number
can be retrieved with os_file_get_last_error */
UNIV_INLINE
os_file_t
pfs_os_file_create_simple_func(
/*===========================*/
mysql_pfs_key_t key, /*!< in: Performance Schema Key */
const char* name, /*!< in: name of the file or path as a
null-terminated string */
ulint create_mode,/*!< in: OS_FILE_OPEN if an existing file is
opened (if does not exist, error), or
OS_FILE_CREATE if a new file is created
(if exists, error), or
OS_FILE_CREATE_PATH if new file
(if exists, error) and subdirectories along
its path are created (if needed)*/
ulint access_type,/*!< in: OS_FILE_READ_ONLY or
OS_FILE_READ_WRITE */
ibool* success,/*!< out: TRUE if succeed, FALSE if error */
const char* src_file,/*!< in: file name where func invoked */
ulint src_line)/*!< in: line where the func invoked */
{
os_file_t file;
struct PSI_file_locker* locker = NULL;
PSI_file_locker_state state;
/* register a file open or creation depending on "create_mode" */
register_pfs_file_open_begin(&state, locker, key,
((create_mode == OS_FILE_CREATE)
? PSI_FILE_CREATE
: PSI_FILE_OPEN),
name, src_file, src_line);
file = os_file_create_simple_func(name, create_mode,
access_type, success);
/* Regsiter the returning "file" value with the system */
register_pfs_file_open_end(locker, file);
return(file);
}
/****************************************************************//**
NOTE! Please use the corresponding macro
os_file_create_simple_no_error_handling(), not directly this function!
A performance schema instrumented wrapper function for
os_file_create_simple_no_error_handling(). Add instrumentation to
monitor file creation/open.
@return own: handle to the file, not defined if error, error number
can be retrieved with os_file_get_last_error */
UNIV_INLINE
os_file_t
pfs_os_file_create_simple_no_error_handling_func(
/*=============================================*/
mysql_pfs_key_t key, /*!< in: Performance Schema Key */
const char* name, /*!< in: name of the file or path as a
null-terminated string */
ulint create_mode,/*!< in: OS_FILE_OPEN if an existing file
is opened (if does not exist, error), or
OS_FILE_CREATE if a new file is created
(if exists, error) */
ulint access_type,/*!< in: OS_FILE_READ_ONLY,
OS_FILE_READ_WRITE, or
OS_FILE_READ_ALLOW_DELETE; the last option is
used by a backup program reading the file */
ibool* success,/*!< out: TRUE if succeed, FALSE if error */
const char* src_file,/*!< in: file name where func invoked */
ulint src_line)/*!< in: line where the func invoked */
{
os_file_t file;
struct PSI_file_locker* locker = NULL;
PSI_file_locker_state state;
/* register a file open or creation depending on "create_mode" */
register_pfs_file_open_begin(&state, locker, key,
((create_mode == OS_FILE_CREATE)
? PSI_FILE_CREATE
: PSI_FILE_OPEN),
name, src_file, src_line);
file = os_file_create_simple_no_error_handling_func(
name, create_mode, access_type, success);
register_pfs_file_open_end(locker, file);
return(file);
}
/****************************************************************//**
NOTE! Please use the corresponding macro os_file_create(), not directly
this function!
A performance schema wrapper function for os_file_create().
Add instrumentation to monitor file creation/open.
@return own: handle to the file, not defined if error, error number
can be retrieved with os_file_get_last_error */
UNIV_INLINE
os_file_t
pfs_os_file_create_func(
/*====================*/
mysql_pfs_key_t key, /*!< in: Performance Schema Key */
const char* name, /*!< in: name of the file or path as a
null-terminated string */
ulint create_mode,/*!< in: OS_FILE_OPEN if an existing file
is opened (if does not exist, error), or
OS_FILE_CREATE if a new file is created
(if exists, error),
OS_FILE_OVERWRITE if a new file is created
or an old overwritten;
OS_FILE_OPEN_RAW, if a raw device or disk
partition should be opened */
ulint purpose,/*!< in: OS_FILE_AIO, if asynchronous,
non-buffered i/o is desired,
OS_FILE_NORMAL, if any normal file;
NOTE that it also depends on type, os_aio_..
and srv_.. variables whether we really use
async i/o or unbuffered i/o: look in the
function source code for the exact rules */
ulint type, /*!< in: OS_DATA_FILE or OS_LOG_FILE */
ibool* success,/*!< out: TRUE if succeed, FALSE if error */
const char* src_file,/*!< in: file name where func invoked */
ulint src_line)/*!< in: line where the func invoked */
{
os_file_t file;
struct PSI_file_locker* locker = NULL;
PSI_file_locker_state state;
/* register a file open or creation depending on "create_mode" */
register_pfs_file_open_begin(&state, locker, key,
((create_mode == OS_FILE_CREATE)
? PSI_FILE_CREATE
: PSI_FILE_OPEN),
name, src_file, src_line);
file = os_file_create_func(name, create_mode, purpose, type, success);
register_pfs_file_open_end(locker, file);
return(file);
}
/***********************************************************************//**
NOTE! Please use the corresponding macro os_file_close(), not directly
this function!
A performance schema instrumented wrapper function for os_file_close().
@return TRUE if success */
UNIV_INLINE
ibool
pfs_os_file_close_func(
/*===================*/
os_file_t file, /*!< in, own: handle to a file */
const char* src_file,/*!< in: file name where func invoked */
ulint src_line)/*!< in: line where the func invoked */
{
ibool result;
struct PSI_file_locker* locker = NULL;
PSI_file_locker_state state;
/* register the file close */
register_pfs_file_io_begin(&state, locker, file, 0, PSI_FILE_CLOSE,
src_file, src_line);
result = os_file_close_func(file);
register_pfs_file_io_end(locker, 0);
return(result);
}
/*******************************************************************//**
NOTE! Please use the corresponding macro os_aio(), not directly this
function!
Performance schema instrumented wrapper function of os_aio() which
requests an asynchronous i/o operation.
@return TRUE if request was queued successfully, FALSE if fail */
UNIV_INLINE
ibool
pfs_os_aio_func(
/*============*/
ulint type, /*!< in: OS_FILE_READ or OS_FILE_WRITE */
ulint mode, /*!< in: OS_AIO_NORMAL etc. I/O mode */
const char* name, /*!< in: name of the file or path as a
null-terminated string */
os_file_t file, /*!< in: handle to a file */
void* buf, /*!< in: buffer where to read or from which
to write */
ulint offset, /*!< in: least significant 32 bits of file
offset where to read or write */
ulint offset_high,/*!< in: most significant 32 bits of
offset */
ulint n, /*!< in: number of bytes to read or write */
fil_node_t* message1,/*!< in: message for the aio handler
(can be used to identify a completed
aio operation); ignored if mode is
OS_AIO_SYNC */
void* message2,/*!< in: message for the aio handler
(can be used to identify a completed
aio operation); ignored if mode is
OS_AIO_SYNC */
ulint space_id,
trx_t* trx,
const char* src_file,/*!< in: file name where func invoked */
ulint src_line)/*!< in: line where the func invoked */
{
ibool result;
struct PSI_file_locker* locker = NULL;
PSI_file_locker_state state;
/* Register the read or write I/O depending on "type" */
register_pfs_file_io_begin(&state, locker, file, n,
(type == OS_FILE_WRITE)
? PSI_FILE_WRITE
: PSI_FILE_READ,
src_file, src_line);
result = os_aio_func(type, mode, name, file, buf, offset, offset_high,
n, message1, message2, space_id, trx);
register_pfs_file_io_end(locker, n);
return(result);
}
/*******************************************************************//**
NOTE! Please use the corresponding macro os_file_read(), not directly
this function!
This is the performance schema instrumented wrapper function for
os_file_read() which requests a synchronous read operation.
@return TRUE if request was successful, FALSE if fail */
UNIV_INLINE
ibool
pfs_os_file_read_func(
/*==================*/
os_file_t file, /*!< in: handle to a file */
void* buf, /*!< in: buffer where to read */
ulint offset, /*!< in: least significant 32 bits of file
offset where to read */
ulint offset_high,/*!< in: most significant 32 bits of
offset */
ulint n, /*!< in: number of bytes to read */
trx_t* trx,
const char* src_file,/*!< in: file name where func invoked */
ulint src_line)/*!< in: line where the func invoked */
{
ibool result;
struct PSI_file_locker* locker = NULL;
PSI_file_locker_state state;
register_pfs_file_io_begin(&state, locker, file, n, PSI_FILE_READ,
src_file, src_line);
result = os_file_read_func(file, buf, offset, offset_high, n, trx);
register_pfs_file_io_end(locker, n);
return(result);
}
/*******************************************************************//**
NOTE! Please use the corresponding macro
os_file_read_no_error_handling(), not directly this function!
This is the performance schema instrumented wrapper function for
os_file_read_no_error_handling() which requests a synchronous
positioned read operation. This function does not do any error
handling. In case of error it returns FALSE.
@return TRUE if request was successful, FALSE if fail */
UNIV_INLINE
ibool
pfs_os_file_read_no_error_handling_func(
/*====================================*/
os_file_t file, /*!< in: handle to a file */
void* buf, /*!< in: buffer where to read */
ulint offset, /*!< in: least significant 32 bits of file
offset where to read */
ulint offset_high,/*!< in: most significant 32 bits of
offset */
ulint n, /*!< in: number of bytes to read */
const char* src_file,/*!< in: file name where func invoked */
ulint src_line)/*!< in: line where the func invoked */
{
ibool result;
struct PSI_file_locker* locker = NULL;
PSI_file_locker_state state;
register_pfs_file_io_begin(&state, locker, file, n, PSI_FILE_READ,
src_file, src_line);
result = os_file_read_no_error_handling_func(file, buf, offset,
offset_high, n);
register_pfs_file_io_end(locker, n);
return(result);
}
/*******************************************************************//**
NOTE! Please use the corresponding macro os_file_write(), not directly
this function!
This is the performance schema instrumented wrapper function for
os_file_write() which requests a synchronous write operation.
@return TRUE if request was successful, FALSE if fail */
UNIV_INLINE
ibool
pfs_os_file_write_func(
/*===================*/
const char* name, /*!< in: name of the file or path as a
null-terminated string */
os_file_t file, /*!< in: handle to a file */
const void* buf, /*!< in: buffer from which to write */
ulint offset, /*!< in: least significant 32 bits of file
offset where to write */
ulint offset_high,/*!< in: most significant 32 bits of
offset */
ulint n, /*!< in: number of bytes to write */
const char* src_file,/*!< in: file name where func invoked */
ulint src_line)/*!< in: line where the func invoked */
{
ibool result;
struct PSI_file_locker* locker = NULL;
PSI_file_locker_state state;
register_pfs_file_io_begin(&state, locker, file, n, PSI_FILE_WRITE,
src_file, src_line);
result = os_file_write_func(name, file, buf, offset, offset_high, n);
register_pfs_file_io_end(locker, n);
return(result);
}
/***********************************************************************//**
NOTE! Please use the corresponding macro os_file_flush(), not directly
this function!
This is the performance schema instrumented wrapper function for
os_file_flush() which flushes the write buffers of a given file to the disk.
@return TRUE if success */
UNIV_INLINE
ibool
pfs_os_file_flush_func(
/*===================*/
os_file_t file, /*!< in, own: handle to a file */
const char* src_file,/*!< in: file name where func invoked */
ulint src_line)/*!< in: line where the func invoked */
{
ibool result;
struct PSI_file_locker* locker = NULL;
PSI_file_locker_state state;
register_pfs_file_io_begin(&state, locker, file, 0, PSI_FILE_SYNC,
src_file, src_line);
result = os_file_flush_func(file);
register_pfs_file_io_end(locker, 0);
return(result);
}
/***********************************************************************//**
NOTE! Please use the corresponding macro os_file_rename(), not directly
this function!
This is the performance schema instrumented wrapper function for
os_file_rename()
@return TRUE if success */
UNIV_INLINE
ibool
pfs_os_file_rename_func(
/*====================*/
mysql_pfs_key_t key, /*!< in: Performance Schema Key */
const char* oldpath,/*!< in: old file path as a null-terminated
string */
const char* newpath,/*!< in: new file path */
const char* src_file,/*!< in: file name where func invoked */
ulint src_line)/*!< in: line where the func invoked */
{
ibool result;
struct PSI_file_locker* locker = NULL;
PSI_file_locker_state state;
register_pfs_file_open_begin(&state, locker, key, PSI_FILE_RENAME, newpath,
src_file, src_line);
result = os_file_rename_func(oldpath, newpath);
register_pfs_file_open_end(locker, 0);
return(result);
}
#endif /* UNIV_PFS_IO */

View file

@ -32,11 +32,6 @@ Created 9/30/1995 Heikki Tuuri
#ifdef UNIV_LINUX
#include <sys/ipc.h>
#include <sys/shm.h>
#else
# if defined HAVE_SYS_IPC_H && HAVE_SYS_SHM_H
#include <sys/ipc.h>
#include <sys/shm.h>
# endif
#endif
typedef void* os_process_t;
@ -75,29 +70,6 @@ os_mem_free_large(
ulint size); /*!< in: size returned by
os_mem_alloc_large() */
/****************************************************************//**
Allocates or attaches and reuses shared memory segment.
The content is not cleared automatically.
@return allocated memory */
UNIV_INTERN
void*
os_shm_alloc(
/*=========*/
ulint* n, /*!< in/out: number of bytes */
uint key,
ibool* is_new);
/****************************************************************//**
Detach shared memory segment. */
UNIV_INTERN
void
os_shm_free(
/*========*/
void *ptr, /*!< in: pointer returned by
os_shm_alloc() */
ulint size); /*!< in: size returned by
os_shm_alloc() */
#ifndef UNIV_NONINL
#include "os0proc.ic"
#endif

View file

@ -38,28 +38,18 @@ Created 9/6/1995 Heikki Tuuri
#include "ut0lst.h"
#ifdef __WIN__
/** Native event (slow)*/
typedef HANDLE os_native_event_t;
/** Native mutex */
#define os_fast_mutex_t CRITICAL_SECTION
/** Native event */
typedef HANDLE os_native_event_t;
/** Operating system event */
typedef struct os_event_struct os_event_struct_t;
/** Operating system event handle */
typedef os_event_struct_t* os_event_t;
/** An asynchronous signal sent between threads */
struct os_event_struct {
os_native_event_t handle;
/*!< Windows event */
UT_LIST_NODE_T(os_event_struct_t) os_event_list;
/*!< list of all created events */
};
typedef CRITICAL_SECTION os_fast_mutex_t;
/** Native condition variable. */
typedef CONDITION_VARIABLE os_cond_t;
#else
/** Native mutex */
typedef pthread_mutex_t os_fast_mutex_t;
typedef pthread_mutex_t os_fast_mutex_t;
/** Native condition variable */
typedef pthread_cond_t os_cond_t;
#endif
/** Operating system event */
typedef struct os_event_struct os_event_struct_t;
@ -68,6 +58,10 @@ typedef os_event_struct_t* os_event_t;
/** An asynchronous signal sent between threads */
struct os_event_struct {
#ifdef __WIN__
HANDLE handle; /*!< kernel event object, slow,
used on older Windows */
#endif
os_fast_mutex_t os_mutex; /*!< this mutex protects the next
fields */
ibool is_set; /*!< this is TRUE when the event is
@ -76,24 +70,23 @@ struct os_event_struct {
this event */
ib_int64_t signal_count; /*!< this is incremented each time
the event becomes signaled */
pthread_cond_t cond_var; /*!< condition variable is used in
os_cond_t cond_var; /*!< condition variable is used in
waiting for the event */
UT_LIST_NODE_T(os_event_struct_t) os_event_list;
/*!< list of all created events */
};
#endif
/** Denotes an infinite delay for os_event_wait_time() */
#define OS_SYNC_INFINITE_TIME ULINT_UNDEFINED
/** Return value of os_event_wait_time() when the time is exceeded */
#define OS_SYNC_TIME_EXCEEDED 1
/** Operating system mutex */
typedef struct os_mutex_struct os_mutex_str_t;
/** Operating system mutex handle */
typedef os_mutex_str_t* os_mutex_t;
/** Denotes an infinite delay for os_event_wait_time() */
#define OS_SYNC_INFINITE_TIME ((ulint)(-1))
/** Return value of os_event_wait_time() when the time is exceeded */
#define OS_SYNC_TIME_EXCEEDED 1
/** Mutex protecting counts and the event and OS 'slow' mutex lists */
extern os_mutex_t os_sync_mutex;
@ -157,10 +150,7 @@ os_event_free(
os_event_t event); /*!< in: event to free */
/**********************************************************//**
Waits for an event object until it is in the signaled state. If
srv_shutdown_state == SRV_SHUTDOWN_EXIT_THREADS this also exits the
waiting thread when the event becomes signaled (or immediately if the
event is already in the signaled state).
Waits for an event object until it is in the signaled state.
Typically, if the event has been signalled after the os_event_reset()
we'll return immediately because event->is_set == TRUE.
@ -186,43 +176,31 @@ os_event_wait_low(
os_event_reset(). */
#define os_event_wait(event) os_event_wait_low(event, 0)
#define os_event_wait_time(e, t) os_event_wait_time_low(event, t, 0)
/**********************************************************//**
Waits for an event object until it is in the signaled state or
a timeout is exceeded.
a timeout is exceeded. In Unix the timeout is always infinite.
@return 0 if success, OS_SYNC_TIME_EXCEEDED if timeout was exceeded */
UNIV_INTERN
ulint
os_event_wait_time(
/*===============*/
os_event_t event, /*!< in: event to wait */
ulint wtime); /*!< in: timeout in microseconds, or
OS_SYNC_INFINITE_TIME */
#ifdef __WIN__
/**********************************************************//**
Waits for any event in an OS native event array. Returns if even a single
one is signaled or becomes signaled.
@return index of the event which was signaled */
UNIV_INTERN
ulint
os_event_wait_multiple(
os_event_wait_time_low(
/*===================*/
ulint n, /*!< in: number of events in the
array */
os_native_event_t* native_event_array);
/*!< in: pointer to an array of event
handles */
#endif
os_event_t event, /*!< in: event to wait */
ulint time_in_usec, /*!< in: timeout in
microseconds, or
OS_SYNC_INFINITE_TIME */
ib_int64_t reset_sig_count); /*!< in: zero or the value
returned by previous call of
os_event_reset(). */
/*********************************************************//**
Creates an operating system mutex semaphore. Because these are slow, the
mutex semaphore of InnoDB itself (mutex_t) should be used where possible.
@return the mutex handle */
UNIV_INTERN
os_mutex_t
os_mutex_create(
/*============*/
const char* name); /*!< in: the name of the mutex, if NULL
the mutex is created without a name */
os_mutex_create(void);
/*=================*/
/**********************************************************//**
Acquires ownership of a mutex semaphore. */
UNIV_INTERN

View file

@ -28,8 +28,7 @@ Created 9/6/1995 Heikki Tuuri
#endif
/**********************************************************//**
Acquires ownership of a fast mutex. Currently in Windows this is the same
as os_fast_mutex_lock!
Acquires ownership of a fast mutex.
@return 0 if success, != 0 if was reserved by another thread */
UNIV_INLINE
ulint
@ -38,9 +37,13 @@ os_fast_mutex_trylock(
os_fast_mutex_t* fast_mutex) /*!< in: mutex to acquire */
{
#ifdef __WIN__
EnterCriticalSection(fast_mutex);
if (TryEnterCriticalSection(fast_mutex)) {
return(0);
return(0);
} else {
return(1);
}
#else
/* NOTE that the MySQL my_pthread.h redefines pthread_mutex_trylock
so that it returns 0 on success. In the operating system

View file

@ -56,6 +56,11 @@ typedef os_thread_t os_thread_id_t; /*!< In Unix we use the thread
/* Define a function pointer type to use in a typecast */
typedef void* (*os_posix_f_t) (void*);
#ifdef HAVE_PSI_INTERFACE
/* Define for performance schema registration key */
typedef unsigned int mysql_pfs_key_t;
#endif
/***************************************************************//**
Compares two thread ids for equality.
@return TRUE if equal */
@ -86,7 +91,7 @@ os_thread_t
os_thread_create(
/*=============*/
#ifndef __WIN__
os_posix_f_t start_f,
os_posix_f_t start_f,
#else
ulint (*start_f)(void*), /*!< in: pointer to function
from which to start */
@ -102,8 +107,9 @@ UNIV_INTERN
void
os_thread_exit(
/*===========*/
void* exit_value); /*!< in: exit value; in Windows this void*
void* exit_value) /*!< in: exit value; in Windows this void*
is cast as a DWORD */
UNIV_COLD __attribute__((noreturn));
/*****************************************************************//**
Returns the thread identifier of current thread.
@return current thread identifier */
@ -112,13 +118,6 @@ os_thread_id_t
os_thread_get_curr_id(void);
/*========================*/
/*****************************************************************//**
Returns handle to the current thread.
@return current thread handle */
UNIV_INTERN
os_thread_t
os_thread_get_curr(void);
/*====================*/
/*****************************************************************//**
Advises the os to give up remainder of the thread's time slice. */
UNIV_INTERN
void
@ -131,29 +130,6 @@ void
os_thread_sleep(
/*============*/
ulint tm); /*!< in: time in microseconds */
/******************************************************************//**
Gets a thread priority.
@return priority */
UNIV_INTERN
ulint
os_thread_get_priority(
/*===================*/
os_thread_t handle);/*!< in: OS handle to the thread */
/******************************************************************//**
Sets a thread priority. */
UNIV_INTERN
void
os_thread_set_priority(
/*===================*/
os_thread_t handle, /*!< in: OS handle to the thread */
ulint pri); /*!< in: priority: one of OS_PRIORITY_... */
/******************************************************************//**
Gets the last operating system error code for the calling thread.
@return last error on Windows, 0 otherwise */
UNIV_INTERN
ulint
os_thread_get_last_error(void);
/*==========================*/
#ifndef UNIV_NONINL
#include "os0thread.ic"

View file

@ -66,7 +66,7 @@ typedef byte page_header_t;
direction */
#define PAGE_N_RECS 16 /* number of user records on the page */
#define PAGE_MAX_TRX_ID 18 /* highest id of a trx which may have modified
a record on the page; a dulint; defined only
a record on the page; trx_id_t; defined only
in secondary indexes and in the insert buffer
tree; NOTE: this may be modified only
when the thread has an x-latch to the page,
@ -952,7 +952,7 @@ UNIV_INTERN
ibool
page_rec_validate(
/*==============*/
rec_t* rec, /*!< in: physical record */
const rec_t* rec, /*!< in: physical record */
const ulint* offsets);/*!< in: array returned by rec_get_offsets() */
/***************************************************************//**
Checks that the first directory slot points to the infimum record and
@ -972,7 +972,7 @@ UNIV_INTERN
ibool
page_simple_validate_old(
/*=====================*/
page_t* page); /*!< in: old-style index page */
const page_t* page); /*!< in: index page in ROW_FORMAT=REDUNDANT */
/***************************************************************//**
This function checks the consistency of an index page when we do not
know the index. This is also resilient so that this should never crash
@ -982,7 +982,7 @@ UNIV_INTERN
ibool
page_simple_validate_new(
/*=====================*/
page_t* block); /*!< in: new-style index page */
const page_t* page); /*!< in: index page in ROW_FORMAT!=REDUNDANT */
/***************************************************************//**
This function checks the consistency of an index page.
@return TRUE if ok */
@ -990,7 +990,7 @@ UNIV_INTERN
ibool
page_validate(
/*==========*/
page_t* page, /*!< in: index page */
const page_t* page, /*!< in: index page */
dict_index_t* index); /*!< in: data dictionary index containing
the page record type definition */
/***************************************************************//**

View file

@ -94,11 +94,10 @@ page_update_max_trx_id(
TRUE for the dummy indexes constructed during redo log
application). In that case, PAGE_MAX_TRX_ID is unused,
and trx_id is usually zero. */
ut_ad(!ut_dulint_is_zero(trx_id) || recv_recovery_is_on());
ut_ad(trx_id || recv_recovery_is_on());
ut_ad(page_is_leaf(buf_block_get_frame(block)));
if (ut_dulint_cmp(page_get_max_trx_id(buf_block_get_frame(block)),
trx_id) < 0) {
if (page_get_max_trx_id(buf_block_get_frame(block)) < trx_id) {
page_set_max_trx_id(block, page_zip, trx_id, mtr);
}

View file

@ -420,7 +420,7 @@ page_zip_copy_recs(
const page_t* src, /*!< in: page */
dict_index_t* index, /*!< in: index of the B-tree */
mtr_t* mtr) /*!< in: mini-transaction */
__attribute__((nonnull(1,2,3,4)));
__attribute__((nonnull));
#endif /* !UNIV_HOTBACKUP */
/**********************************************************************//**

View file

@ -1,6 +1,6 @@
/*****************************************************************************
Copyright (c) 1996, 2009, Innobase Oy. All Rights Reserved.
Copyright (c) 1996, 2010, Innobase Oy. 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
@ -521,17 +521,17 @@ Equivalent to:
char buf[8];
mach_write_to_8(buf, val);
pars_info_add_literal(info, name, buf, 8, DATA_BINARY, 0);
pars_info_add_literal(info, name, buf, 8, DATA_FIXBINARY, 0);
except that the buffer is dynamically allocated from the info struct's
heap. */
UNIV_INTERN
void
pars_info_add_dulint_literal(
/*=========================*/
pars_info_add_ull_literal(
/*======================*/
pars_info_t* info, /*!< in: info struct */
const char* name, /*!< in: name */
dulint val); /*!< in: value */
ib_uint64_t val); /*!< in: value */
/****************************************************************//**
Add user function. */
UNIV_INTERN

View file

@ -424,9 +424,6 @@ struct que_fork_struct{
ibool cur_on_row; /*!< TRUE if cursor is on a row, i.e.,
it is not before the first row or
after the last row */
dulint n_inserts; /*!< number of rows inserted */
dulint n_updates; /*!< number of rows updated */
dulint n_deletes; /*!< number of rows deleted */
sel_node_t* last_sel_node; /*!< last executed select node, or NULL
if none */
UT_LIST_NODE_T(que_fork_t)

View file

@ -43,8 +43,7 @@ read_view_t*
read_view_open_now(
/*===============*/
trx_id_t cr_trx_id, /*!< in: trx_id of creating
transaction, or ut_dulint_zero
used in purge */
transaction, or 0 used in purge */
mem_heap_t* heap); /*!< in: memory heap from which
allocated */
/*********************************************************************//**
@ -56,8 +55,7 @@ read_view_t*
read_view_oldest_copy_or_open_new(
/*==============================*/
trx_id_t cr_trx_id, /*!< in: trx_id of creating
transaction, or ut_dulint_zero
used in purge */
transaction, or 0 used in purge */
mem_heap_t* heap); /*!< in: memory heap from which
allocated */
/*********************************************************************//**
@ -90,6 +88,7 @@ UNIV_INTERN
void
read_view_print(
/*============*/
FILE* file,
const read_view_t* view); /*!< in: read view */
/*********************************************************************//**
Create a consistent cursor view for mysql to be used in cursors. In this
@ -125,7 +124,7 @@ read should not see the modifications to the database. */
struct read_view_struct{
ulint type; /*!< VIEW_NORMAL, VIEW_HIGH_GRANULARITY */
undo_no_t undo_no;/*!< ut_dulint_zero or if type is
undo_no_t undo_no;/*!< 0 or if type is
VIEW_HIGH_GRANULARITY
transaction undo_no when this high-granularity
consistent read view was created */
@ -156,7 +155,7 @@ struct read_view_struct{
that is, up_limit_id and low_limit_id. */
trx_id_t creator_trx_id;
/*!< trx id of creating transaction, or
ut_dulint_zero used in purge */
0 used in purge */
UT_LIST_NODE_T(read_view_t) view_list;
/*!< List of read views in trx_sys */
};

View file

@ -64,15 +64,14 @@ read_view_sees_trx_id(
trx_id_t trx_id) /*!< in: trx id */
{
ulint n_ids;
int cmp;
ulint i;
if (ut_dulint_cmp(trx_id, view->up_limit_id) < 0) {
if (trx_id < view->up_limit_id) {
return(TRUE);
}
if (ut_dulint_cmp(trx_id, view->low_limit_id) >= 0) {
if (trx_id >= view->low_limit_id) {
return(FALSE);
}
@ -85,12 +84,11 @@ read_view_sees_trx_id(
n_ids = view->n_trx_ids;
for (i = 0; i < n_ids; i++) {
trx_id_t view_trx_id
= read_view_get_nth_trx_id(view, n_ids - i - 1);
cmp = ut_dulint_cmp(
trx_id,
read_view_get_nth_trx_id(view, n_ids - i - 1));
if (cmp <= 0) {
return(cmp < 0);
if (trx_id <= view_trx_id) {
return(trx_id != view_trx_id);
}
}

View file

@ -600,6 +600,7 @@ ulint
rec_offs_size(
/*==========*/
const ulint* offsets);/*!< in: array returned by rec_get_offsets() */
#ifdef UNIV_DEBUG
/**********************************************************//**
Returns a pointer to the start of the record.
@return pointer to start */
@ -607,7 +608,7 @@ UNIV_INLINE
byte*
rec_get_start(
/*==========*/
rec_t* rec, /*!< in: pointer to record */
const rec_t* rec, /*!< in: pointer to record */
const ulint* offsets);/*!< in: array returned by rec_get_offsets() */
/**********************************************************//**
Returns a pointer to the end of the record.
@ -616,8 +617,12 @@ UNIV_INLINE
byte*
rec_get_end(
/*========*/
rec_t* rec, /*!< in: pointer to record */
const rec_t* rec, /*!< in: pointer to record */
const ulint* offsets);/*!< in: array returned by rec_get_offsets() */
#else /* UNIV_DEBUG */
# define rec_get_start(rec, offsets) ((rec) - rec_offs_extra_size(offsets))
# define rec_get_end(rec, offsets) ((rec) + rec_offs_data_size(offsets))
#endif /* UNIV_DEBUG */
/***************************************************************//**
Copies a physical record to a buffer.
@return pointer to the origin of the copy */
@ -659,7 +664,7 @@ rec_fold(
fields to fold */
ulint n_bytes, /*!< in: number of bytes to fold
in an incomplete last field */
dulint tree_id) /*!< in: index tree id */
index_id_t tree_id) /*!< in: index tree id */
__attribute__((pure));
#endif /* !UNIV_HOTBACKUP */
/*********************************************************//**
@ -801,13 +806,11 @@ UNIV_INTERN
void
rec_print(
/*======*/
FILE* file, /*!< in: file where to print */
const rec_t* rec, /*!< in: physical record */
dict_index_t* index); /*!< in: record descriptor */
FILE* file, /*!< in: file where to print */
const rec_t* rec, /*!< in: physical record */
const dict_index_t* index); /*!< in: record descriptor */
#endif /* UNIV_HOTBACKUP */
#define REC_INFO_BITS 6 /* This is single byte bit-field */
/* Maximum lengths for the data in a physical record if the offsets
are given in one byte (resp. two byte) format. */
#define REC_1BYTE_OFFS_LIMIT 0x7FUL

View file

@ -1462,6 +1462,7 @@ rec_offs_size(
return(rec_offs_data_size(offsets) + rec_offs_extra_size(offsets));
}
#ifdef UNIV_DEBUG
/**********************************************************//**
Returns a pointer to the end of the record.
@return pointer to end */
@ -1469,11 +1470,11 @@ UNIV_INLINE
byte*
rec_get_end(
/*========*/
rec_t* rec, /*!< in: pointer to record */
const rec_t* rec, /*!< in: pointer to record */
const ulint* offsets)/*!< in: array returned by rec_get_offsets() */
{
ut_ad(rec_offs_validate(rec, NULL, offsets));
return(rec + rec_offs_data_size(offsets));
return((rec_t*) rec + rec_offs_data_size(offsets));
}
/**********************************************************//**
@ -1483,12 +1484,13 @@ UNIV_INLINE
byte*
rec_get_start(
/*==========*/
rec_t* rec, /*!< in: pointer to record */
const rec_t* rec, /*!< in: pointer to record */
const ulint* offsets)/*!< in: array returned by rec_get_offsets() */
{
ut_ad(rec_offs_validate(rec, NULL, offsets));
return(rec - rec_offs_extra_size(offsets));
return((rec_t*) rec - rec_offs_extra_size(offsets));
}
#endif /* UNIV_DEBUG */
/***************************************************************//**
Copies a physical record to a buffer.
@ -1594,7 +1596,7 @@ rec_fold(
fields to fold */
ulint n_bytes, /*!< in: number of bytes to fold
in an incomplete last field */
dulint tree_id) /*!< in: index tree id */
index_id_t tree_id) /*!< in: index tree id */
{
ulint i;
const byte* data;
@ -1618,7 +1620,7 @@ rec_fold(
n_bytes = 0;
}
fold = ut_fold_dulint(tree_id);
fold = ut_fold_ull(tree_id);
for (i = 0; i < n_fields; i++) {
data = rec_get_nth_field(rec, offsets, i, &len);

View file

@ -1,6 +1,6 @@
/*****************************************************************************
Copyright (c) 2005, 2009, Innobase Oy. All Rights Reserved.
Copyright (c) 2005, 2010, Innobase Oy. 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
@ -191,7 +191,7 @@ row_merge_build_indexes(
unless creating a PRIMARY KEY */
dict_index_t** indexes, /*!< in: indexes to be created */
ulint n_indexes, /*!< in: size of indexes[] */
TABLE* table); /*!< in/out: MySQL table, for
struct TABLE* table); /*!< in/out: MySQL table, for
reporting erroneous key value
if applicable */
#endif /* row0merge.h */

View file

@ -103,6 +103,17 @@ row_mysql_read_blob_ref(
ulint col_len); /*!< in: BLOB reference length
(not BLOB length) */
/**************************************************************//**
Pad a column with spaces. */
UNIV_INTERN
void
row_mysql_pad_col(
/*==============*/
ulint mbminlen, /*!< in: minimum size of a character,
in bytes */
byte* pad, /*!< out: padded buffer */
ulint len); /*!< in: number of bytes to pad */
/**************************************************************//**
Stores a non-SQL-NULL field given in the MySQL format in the InnoDB format.
The counterpart of this function is row_sel_field_store_in_mysql_format() in
row0sel.c.

View file

@ -45,6 +45,28 @@ row_purge_node_create(
que_thr_t* parent, /*!< in: parent node, i.e., a thr node */
mem_heap_t* heap); /*!< in: memory heap where created */
/***********************************************************//**
Determines if it is possible to remove a secondary index entry.
Removal is possible if the secondary index entry does not refer to any
not delete marked version of a clustered index record where DB_TRX_ID
is newer than the purge view.
NOTE: This function should only be called by the purge thread, only
while holding a latch on the leaf page of the secondary index entry
(or keeping the buffer pool watch on the page). It is possible that
this function first returns TRUE and then FALSE, if a user transaction
inserts a record that the secondary index entry would refer to.
However, in that case, the user transaction would also re-insert the
secondary index entry after purge has removed it and released the leaf
page latch.
@return TRUE if the secondary index record can be purged */
UNIV_INTERN
ibool
row_purge_poss_sec(
/*===============*/
purge_node_t* node, /*!< in/out: row purge node */
dict_index_t* index, /*!< in: secondary index */
const dtuple_t* entry); /*!< in: secondary index entry */
/***************************************************************
Does the purge operation for a single undo log record. This is a high-level
function used in an SQL execution graph.
@return query thread to run next or NULL */

View file

@ -1,6 +1,6 @@
/*****************************************************************************
Copyright (c) 1996, 2009, Innobase Oy. All Rights Reserved.
Copyright (c) 1996, 2010, Innobase Oy. 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
@ -257,11 +257,25 @@ row_get_clust_rec(
dict_index_t* index, /*!< in: secondary index */
dict_index_t** clust_index,/*!< out: clustered index */
mtr_t* mtr); /*!< in: mtr */
/** Result of row_search_index_entry */
enum row_search_result {
ROW_FOUND = 0, /*!< the record was found */
ROW_NOT_FOUND, /*!< record not found */
ROW_BUFFERED, /*!< one of BTR_INSERT, BTR_DELETE, or
BTR_DELETE_MARK was specified, the
secondary index leaf page was not in
the buffer pool, and the operation was
enqueued in the insert/delete buffer */
ROW_NOT_DELETED_REF /*!< BTR_DELETE was specified, and
row_purge_poss_sec() failed */
};
/***************************************************************//**
Searches an index record.
@return TRUE if found */
@return whether the record was found or buffered */
UNIV_INTERN
ibool
enum row_search_result
row_search_index_entry(
/*===================*/
dict_index_t* index, /*!< in: index */

View file

@ -1,6 +1,6 @@
/*****************************************************************************
Copyright (c) 1996, 2009, Innobase Oy. All Rights Reserved.
Copyright (c) 1996, 2010, Innobase Oy. 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
@ -54,6 +54,6 @@ typedef struct purge_node_struct purge_node_t;
typedef struct row_ext_struct row_ext_t;
/* MySQL data types */
typedef struct st_table TABLE;
struct TABLE;
#endif

View file

@ -132,7 +132,7 @@ row_upd_index_entry_sys_field(
them */
dict_index_t* index, /*!< in: clustered index */
ulint type, /*!< in: DATA_TRX_ID or DATA_ROLL_PTR */
dulint val); /*!< in: value to write */
ib_uint64_t val); /*!< in: value to write */
/*********************************************************************//**
Creates an update node for a query graph.
@return own: update node */

View file

@ -158,7 +158,7 @@ row_upd_rec_sys_fields(
ut_ad(dict_index_is_clust(index));
ut_ad(rec_offs_validate(rec, index, offsets));
#ifdef UNIV_SYNC_DEBUG
if (!rw_lock_own(&btr_search_latch, RW_LOCK_EX)) {
if (!rw_lock_own(btr_search_get_latch(index->id), RW_LOCK_EX)) {
ut_ad(!buf_block_align(rec)->is_hashed);
}
#endif /* UNIV_SYNC_DEBUG */

View file

@ -1,42 +0,0 @@
/*****************************************************************************
Copyright (c) 1996, 2009, Innobase Oy. 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., 59 Temple
Place, Suite 330, Boston, MA 02111-1307 USA
*****************************************************************************/
/**************************************************//**
@file include/srv0que.h
Server query execution
Created 6/5/1996 Heikki Tuuri
*******************************************************/
#ifndef srv0que_h
#define srv0que_h
#include "univ.i"
#include "que0types.h"
/**********************************************************************//**
Enqueues a task to server task queue and releases a worker thread, if there
is a suspended one. */
UNIV_INTERN
void
srv_que_task_enqueue_low(
/*=====================*/
que_thr_t* thr); /*!< in: query thread */
#endif

View file

@ -1,6 +1,6 @@
/*****************************************************************************
Copyright (c) 1995, 2010, Innobase Oy. All Rights Reserved.
Copyright (c) 1995, 2011, Innobase Oy. All Rights Reserved.
Copyright (c) 2008, 2009, Google Inc.
Copyright (c) 2009, Percona Inc.
@ -57,8 +57,14 @@ extern const char srv_mysql50_table_name_prefix[9];
thread starts running */
extern os_event_t srv_lock_timeout_thread_event;
/* This event is set at shutdown to wakeup threads from sleep */
extern os_event_t srv_shutdown_event;
/* The monitor thread waits on this event. */
extern os_event_t srv_monitor_event;
/* The lock timeout thread waits on this event. */
extern os_event_t srv_timeout_event;
/* The error monitor thread waits on this event. */
extern os_event_t srv_error_event;
/* If the last data file is auto-extended, we add this many pages to it
at a time */
@ -68,9 +74,6 @@ at a time */
/* prototypes for new functions added to ha_innodb.cc */
ibool innobase_get_slow_log();
/* This is set to TRUE if the MySQL user has set it in MySQL */
extern ibool srv_lower_case_table_names;
/* Mutex for locking srv_monitor_file */
extern mutex_t srv_monitor_file_mutex;
/* Temporary file for innodb monitor output */
@ -107,12 +110,20 @@ extern ulint srv_file_format;
/** Whether to check file format during startup. A value of
DICT_TF_FORMAT_MAX + 1 means no checking ie. FALSE. The default is to
set it to the highest format we support. */
extern ulint srv_check_file_format_at_startup;
extern ulint srv_max_file_format_at_startup;
/** Place locks to records only i.e. do not use next-key locking except
on duplicate key checking and foreign key checking */
extern ibool srv_locks_unsafe_for_binlog;
#endif /* !UNIV_HOTBACKUP */
/* If this flag is TRUE, then we will use the native aio of the
OS (provided we compiled Innobase with it in), otherwise we will
use simulated aio we build below with threads.
Currently we support native aio on windows and linux */
extern my_bool srv_use_native_aio;
#ifdef __WIN__
extern ibool srv_use_native_conditions;
#endif
extern ulint srv_n_data_files;
extern char** srv_data_file_names;
extern ulint* srv_data_file_sizes;
@ -120,12 +131,8 @@ extern ulint* srv_data_file_is_raw_partition;
extern char* srv_doublewrite_file;
extern ibool srv_extra_undoslots;
extern ibool srv_recovery_stats;
extern ulint srv_use_purge_thread;
extern ibool srv_auto_extend_last_data_file;
extern ulint srv_last_file_size_max;
extern char** srv_log_group_home_dirs;
@ -138,7 +145,8 @@ extern ulint srv_n_log_groups;
extern ulint srv_n_log_files;
extern ulint srv_log_file_size;
extern ulint srv_log_buffer_size;
extern ulong srv_flush_log_at_trx_commit;
//extern ulong srv_flush_log_at_trx_commit;
extern char srv_use_global_flush_log_at_trx_commit;
extern char srv_adaptive_flushing;
@ -154,15 +162,12 @@ extern my_bool srv_use_sys_malloc;
extern ibool srv_use_sys_malloc;
#endif /* UNIV_HOTBACKUP */
extern ulint srv_buf_pool_size; /*!< requested size in bytes */
extern ulint srv_buf_pool_instances; /*!< requested number of buffer pool instances */
extern ulint srv_buf_pool_old_size; /*!< previously requested size */
extern ulint srv_buf_pool_curr_size; /*!< current size in bytes */
extern ulint srv_mem_pool_size;
extern ulint srv_lock_table_size;
extern uint srv_buffer_pool_shm_key;
extern ibool srv_buffer_pool_shm_is_reused;
extern ibool srv_buffer_pool_shm_checksum;
extern ibool srv_thread_concurrency_timer_based;
extern ulint srv_n_file_io_threads;
@ -183,9 +188,9 @@ as enum type because the configure option takes unsigned integer type. */
extern ulong srv_innodb_stats_method;
#ifdef UNIV_LOG_ARCHIVE
extern ibool srv_log_archive_on;
extern ibool srv_archive_recovery;
extern dulint srv_archive_recovery_limit_lsn;
extern ibool srv_log_archive_on;
extern ibool srv_archive_recovery;
extern ib_uint64_t srv_archive_recovery_limit_lsn;
#endif /* UNIV_LOG_ARCHIVE */
extern char* srv_file_flush_method_str;
@ -221,9 +226,6 @@ extern ibool srv_use_doublewrite_buf;
extern ibool srv_use_checksums;
extern ibool srv_fast_checksum;
extern ibool srv_set_thread_priorities;
extern int srv_query_thread_priority;
extern ulong srv_max_buf_pool_modified_pct;
extern ulong srv_max_purge_lag;
@ -236,12 +238,11 @@ extern ulint srv_checkpoint_age_target;
extern ulint srv_flush_neighbor_pages;
extern ulint srv_enable_unsafe_group_commit;
extern ulint srv_read_ahead;
extern ulint srv_adaptive_checkpoint;
extern ulint srv_adaptive_flushing_method;
extern ulint srv_expand_import;
extern ulint srv_pass_corrupt_table;
extern ulint srv_extra_rsegments;
extern ulint srv_dict_size_limit;
extern ulint srv_lazy_drop_table;
@ -268,6 +269,8 @@ extern ulong srv_thread_sleep_delay;
extern ulong srv_spin_wait_delay;
extern ibool srv_priority_boost;
extern ulint srv_truncated_status_writes;
extern ulint srv_mem_pool_size;
extern ulint srv_lock_table_size;
@ -318,6 +321,15 @@ extern ulint srv_os_log_pending_writes;
log buffer and have to flush it */
extern ulint srv_log_waits;
/* the number of purge threads to use from the worker pool (currently 0 or 1) */
extern ulong srv_n_purge_threads;
/* the number of pages to purge in one batch */
extern ulong srv_purge_batch_size;
/* the number of rollback segments to use */
extern ulong srv_rollback_segments;
/* variable that counts amount of data read in total (in bytes) */
extern ulint srv_data_read;
@ -344,6 +356,8 @@ extern ulint srv_buf_pool_wait_free;
buffer pool to disk */
extern ulint srv_buf_pool_flushed;
extern ulint buf_lru_flush_page_count;
/** Number of buffer pool reads that led to the
reading of a disk page */
extern ulint srv_buf_pool_reads;
@ -362,6 +376,38 @@ typedef struct srv_sys_struct srv_sys_t;
/** The server system */
extern srv_sys_t* srv_sys;
# ifdef UNIV_PFS_THREAD
/* Keys to register InnoDB threads with performance schema */
extern mysql_pfs_key_t trx_rollback_clean_thread_key;
extern mysql_pfs_key_t io_handler_thread_key;
extern mysql_pfs_key_t srv_lock_timeout_thread_key;
extern mysql_pfs_key_t srv_error_monitor_thread_key;
extern mysql_pfs_key_t srv_monitor_thread_key;
extern mysql_pfs_key_t srv_master_thread_key;
extern mysql_pfs_key_t srv_purge_thread_key;
/* This macro register the current thread and its key with performance
schema */
# define pfs_register_thread(key) \
do { \
if (PSI_server) { \
struct PSI_thread* psi = PSI_server->new_thread(key, NULL, 0);\
if (psi) { \
PSI_server->set_thread(psi); \
} \
} \
} while (0)
/* This macro delist the current thread from performance schema */
# define pfs_delete_thread() \
do { \
if (PSI_server) { \
PSI_server->delete_current_thread(); \
} \
} while (0)
# endif /* UNIV_PFS_THREAD */
#endif /* !UNIV_HOTBACKUP */
/** Types of raw partitions in innodb_data_file_path */
@ -383,7 +429,7 @@ enum {
SRV_UNIX_NOSYNC, /*!< do not flush after writing */
SRV_UNIX_O_DIRECT, /*!< invoke os_file_set_nocache() on
data files */
SRV_UNIX_ALL_O_DIRECT /* new method for examination: logfile also open O_DIRECT */
SRV_UNIX_ALL_O_DIRECT /* new method for examination: logfile also open O_DIRECT */
};
/** Alternatives for file i/o in Windows */
@ -432,18 +478,8 @@ typedef enum srv_stats_method_name_enum srv_stats_method_name_t;
#ifndef UNIV_HOTBACKUP
/** Types of threads existing in the system. */
enum srv_thread_type {
SRV_COM = 1, /**< threads serving communication and queries */
SRV_CONSOLE, /**< thread serving console */
SRV_WORKER, /**< threads serving parallelized queries and
SRV_WORKER = 0, /**< threads serving parallelized queries and
queries released from lock wait */
#if 0
/* Utility threads */
SRV_BUFFER, /**< thread flushing dirty buffer blocks */
SRV_RECOVERY, /**< threads finishing a recovery */
SRV_INSERT, /**< thread flushing the insert buffer to disk */
#endif
SRV_PURGE, /* thread purging undo records */
SRV_PURGE_WORKER, /* thread purging undo records */
SRV_MASTER /**< the master thread, (whose type number must
be biggest) */
};
@ -482,12 +518,13 @@ ulint
srv_get_n_threads(void);
/*===================*/
/*********************************************************************//**
Returns the calling thread type.
@return SRV_COM, ... */
enum srv_thread_type
srv_get_thread_type(void);
/*=====================*/
Check whether thread type has reserved a slot.
@return slot number or UNDEFINED if not found*/
UNIV_INTERN
ulint
srv_thread_has_reserved_slot(
/*=========================*/
enum srv_thread_type type); /*!< in: thread type to check */
/*********************************************************************//**
Sets the info describing an i/o thread current state. */
UNIV_INTERN
@ -517,21 +554,12 @@ srv_master_thread(
/*==============*/
void* arg); /*!< in: a dummy parameter required by
os_thread_create */
/*************************************************************************
The undo purge thread. */
/*******************************************************************//**
Wakes up the purge thread if it's not already awake. */
UNIV_INTERN
os_thread_ret_t
srv_purge_thread(
/*=============*/
void* arg); /* in: a dummy parameter required by
os_thread_create */
/*************************************************************************
The undo purge thread. */
UNIV_INTERN
os_thread_ret_t
srv_purge_worker_thread(
/*====================*/
void* arg);
void
srv_wake_purge_thread(void);
/*=======================*/
/*******************************************************************//**
Tells the Innobase server that there has been activity in the database
and wakes up the master thread if it is suspended (not sleeping). Used
@ -548,6 +576,16 @@ UNIV_INTERN
void
srv_wake_master_thread(void);
/*========================*/
/*******************************************************************//**
Tells the purge thread that there has been activity in the database
and wakes up the purge thread if it is suspended (not sleeping). Note
that there is a small chance that the purge thread stays suspended
(we do not protect our operation with the kernel mutex, for
performace reasons). */
UNIV_INTERN
void
srv_wake_purge_thread_if_not_active(void);
/*=====================================*/
/*********************************************************************//**
Puts an OS thread to wait if there are too many concurrent threads
(>= srv_thread_concurrency) inside InnoDB. The threads wait in a FIFO queue. */
@ -664,14 +702,40 @@ void
srv_export_innodb_status(void);
/*==========================*/
/** Thread slot in the thread table */
typedef struct srv_slot_struct srv_slot_t;
/*********************************************************************//**
Asynchronous purge thread.
@return a dummy parameter */
UNIV_INTERN
os_thread_ret_t
srv_purge_thread(
/*=============*/
void* arg __attribute__((unused))); /*!< in: a dummy parameter
required by os_thread_create */
/** Thread table is an array of slots */
typedef srv_slot_t srv_table_t;
/**********************************************************************//**
Enqueues a task to server task queue and releases a worker thread, if there
is a suspended one. */
UNIV_INTERN
void
srv_que_task_enqueue_low(
/*=====================*/
que_thr_t* thr); /*!< in: query thread */
/**********************************************************************//**
Check whether any background thread is active.
@return FALSE if all are are suspended or have exited. */
UNIV_INTERN
ibool
srv_is_any_background_thread_active(void);
/*======================================*/
/** Status variables to be passed to MySQL */
struct export_var_struct{
ulint innodb_adaptive_hash_cells;
ulint innodb_adaptive_hash_heap_buffers;
ulint innodb_adaptive_hash_hash_searches;
ulint innodb_adaptive_hash_non_hash_searches;
ulint innodb_background_log_sync;
ulint innodb_data_pending_reads; /*!< Pending reads */
ulint innodb_data_pending_writes; /*!< Pending writes */
ulint innodb_data_pending_fsyncs; /*!< Pending fsyncs */
@ -689,20 +753,54 @@ struct export_var_struct{
#ifdef UNIV_DEBUG
ulint innodb_buffer_pool_pages_latched; /*!< Latched pages */
#endif /* UNIV_DEBUG */
ulint innodb_buffer_pool_pages_made_not_young;
ulint innodb_buffer_pool_pages_made_young;
ulint innodb_buffer_pool_pages_old;
ulint innodb_buffer_pool_read_requests; /*!< buf_pool->stat.n_page_gets */
ulint innodb_buffer_pool_reads; /*!< srv_buf_pool_reads */
ulint innodb_buffer_pool_wait_free; /*!< srv_buf_pool_wait_free */
ulint innodb_buffer_pool_pages_flushed; /*!< srv_buf_pool_flushed */
ulint innodb_buffer_pool_pages_LRU_flushed; /*!< buf_lru_flush_page_count */
ulint innodb_buffer_pool_write_requests;/*!< srv_buf_pool_write_requests */
ulint innodb_buffer_pool_read_ahead; /*!< srv_read_ahead */
ulint innodb_buffer_pool_read_ahead_evicted;/*!< srv_read_ahead evicted*/
ulint innodb_deadlocks; /* ??? */
ulint innodb_checkpoint_age;
ulint innodb_checkpoint_max_age;
ulint innodb_checkpoint_target_age;
ulint innodb_dblwr_pages_written; /*!< srv_dblwr_pages_written */
ulint innodb_dblwr_writes; /*!< srv_dblwr_writes */
ulint innodb_deadlocks;
ibool innodb_have_atomic_builtins; /*!< HAVE_ATOMIC_BUILTINS */
ulint innodb_history_list_length;
ulint innodb_ibuf_size;
ulint innodb_ibuf_free_list;
ulint innodb_ibuf_segment_size;
ulint innodb_ibuf_merges;
ulint innodb_ibuf_merged_inserts;
ulint innodb_ibuf_merged_delete_marks;
ulint innodb_ibuf_merged_deletes;
ulint innodb_ibuf_discarded_inserts;
ulint innodb_ibuf_discarded_delete_marks;
ulint innodb_ibuf_discarded_deletes;
ulint innodb_log_waits; /*!< srv_log_waits */
ulint innodb_log_write_requests; /*!< srv_log_write_requests */
ulint innodb_log_writes; /*!< srv_log_writes */
ib_int64_t innodb_lsn_current;
ib_int64_t innodb_lsn_flushed;
ib_int64_t innodb_lsn_last_checkpoint;
ulint innodb_master_thread_1_second_loops;
ulint innodb_master_thread_10_second_loops;
ulint innodb_master_thread_background_loops;
ulint innodb_master_thread_main_flush_loops;
ulint innodb_master_thread_sleeps;
ib_int64_t innodb_max_trx_id;
ulint innodb_mem_adaptive_hash;
ulint innodb_mem_dictionary;
ulint innodb_mem_total;
ib_int64_t innodb_mutex_os_waits;
ib_int64_t innodb_mutex_spin_rounds;
ib_int64_t innodb_mutex_spin_waits;
ib_int64_t innodb_oldest_view_low_limit_trx_id;
ulint innodb_os_log_written; /*!< srv_os_log_written */
ulint innodb_os_log_fsyncs; /*!< fil_n_log_flushes */
ulint innodb_os_log_pending_writes; /*!< srv_os_log_pending_writes */
@ -711,6 +809,8 @@ struct export_var_struct{
ulint innodb_pages_created; /*!< buf_pool->stat.n_pages_created */
ulint innodb_pages_read; /*!< buf_pool->stat.n_pages_read */
ulint innodb_pages_written; /*!< buf_pool->stat.n_pages_written */
ib_int64_t innodb_purge_trx_id;
ib_int64_t innodb_purge_undo_no;
ulint innodb_row_lock_waits; /*!< srv_n_lock_wait_count */
ulint innodb_row_lock_current_waits; /*!< srv_n_lock_wait_current_count */
ib_int64_t innodb_row_lock_time; /*!< srv_n_lock_wait_time
@ -720,12 +820,26 @@ struct export_var_struct{
/ srv_n_lock_wait_count */
ulint innodb_row_lock_time_max; /*!< srv_n_lock_max_wait_time
/ 1000 */
ulint innodb_current_row_locks;
ulint innodb_rows_read; /*!< srv_n_rows_read */
ulint innodb_rows_inserted; /*!< srv_n_rows_inserted */
ulint innodb_rows_updated; /*!< srv_n_rows_updated */
ulint innodb_rows_deleted; /*!< srv_n_rows_deleted */
ulint innodb_truncated_status_writes; /*!< srv_truncated_status_writes */
ib_int64_t innodb_s_lock_os_waits;
ib_int64_t innodb_s_lock_spin_rounds;
ib_int64_t innodb_s_lock_spin_waits;
ib_int64_t innodb_x_lock_os_waits;
ib_int64_t innodb_x_lock_spin_rounds;
ib_int64_t innodb_x_lock_spin_waits;
};
/** Thread slot in the thread table */
typedef struct srv_slot_struct srv_slot_t;
/** Thread table is an array of slots */
typedef srv_slot_t srv_table_t;
/** The server system struct */
struct srv_sys_struct{
srv_table_t* threads; /*!< server thread table */
@ -735,8 +849,9 @@ struct srv_sys_struct{
extern ulint srv_n_threads_active[];
#else /* !UNIV_HOTBACKUP */
# define srv_use_checksums TRUE
# define srv_use_adaptive_hash_indexes FALSE
# define srv_use_checksums TRUE
# define srv_use_native_aio FALSE
# define srv_force_recovery 0UL
# define srv_set_io_thread_op_info(t,info) ((void) 0)
# define srv_is_being_started 0

View file

@ -91,10 +91,6 @@ extern ib_uint64_t srv_shutdown_lsn;
/** Log sequence number immediately after startup */
extern ib_uint64_t srv_start_lsn;
#ifdef __NETWARE__
void set_panic_flag_for_netware(void);
#endif
#ifdef HAVE_DARWIN_THREADS
/** TRUE if the F_FULLFSYNC option is available */
extern ibool srv_have_fullfsync;

View file

@ -115,8 +115,11 @@ Prints warnings of long semaphore waits to stderr.
@return TRUE if fatal semaphore wait threshold was exceeded */
UNIV_INTERN
ibool
sync_array_print_long_waits(void);
/*=============================*/
sync_array_print_long_waits(
/*========================*/
os_thread_id_t* waiter, /*!< out: longest waiting thread */
const void** sema) /*!< out: longest-waited-for semaphore */
__attribute__((nonnull));
/********************************************************************//**
Validates the integrity of the wait array. Checks
that the number of reserved cells equals the count variable. */

View file

@ -105,23 +105,142 @@ extern ib_int64_t rw_x_os_wait_count;
set only when UNIV_SYNC_PERF_STAT is defined */
extern ib_int64_t rw_x_exit_count;
#ifdef UNIV_PFS_RWLOCK
/* Following are rwlock keys used to register with MySQL
performance schema */
# ifdef UNIV_LOG_ARCHIVE
extern mysql_pfs_key_t archive_lock_key;
# endif /* UNIV_LOG_ARCHIVE */
extern mysql_pfs_key_t btr_search_latch_key;
extern mysql_pfs_key_t buf_pool_page_hash_key;
extern mysql_pfs_key_t buf_block_lock_key;
# ifdef UNIV_SYNC_DEBUG
extern mysql_pfs_key_t buf_block_debug_latch_key;
# endif /* UNIV_SYNC_DEBUG */
extern mysql_pfs_key_t dict_operation_lock_key;
extern mysql_pfs_key_t fil_space_latch_key;
extern mysql_pfs_key_t checkpoint_lock_key;
extern mysql_pfs_key_t trx_i_s_cache_lock_key;
extern mysql_pfs_key_t trx_purge_latch_key;
extern mysql_pfs_key_t index_tree_rw_lock_key;
extern mysql_pfs_key_t dict_table_stats_latch_key;
#endif /* UNIV_PFS_RWLOCK */
#ifndef UNIV_PFS_RWLOCK
/******************************************************************//**
Creates, or rather, initializes an rw-lock object in a specified memory
location (which must be appropriately aligned). The rw-lock is initialized
to the non-locked state. Explicit freeing of the rw-lock with rw_lock_free
is necessary only if the memory block containing it is freed. */
#ifdef UNIV_DEBUG
# ifdef UNIV_SYNC_DEBUG
# define rw_lock_create(L, level) \
is necessary only if the memory block containing it is freed.
if MySQL performance schema is enabled and "UNIV_PFS_RWLOCK" is
defined, the rwlock are instrumented with performance schema probes. */
# ifdef UNIV_DEBUG
# ifdef UNIV_SYNC_DEBUG
# define rw_lock_create(K, L, level) \
rw_lock_create_func((L), (level), __FILE__, __LINE__, #L)
# else /* UNIV_SYNC_DEBUG */
# define rw_lock_create(L, level) \
# else /* UNIV_SYNC_DEBUG */
# define rw_lock_create(K, L, level) \
rw_lock_create_func((L), __FILE__, __LINE__, #L)
# endif /* UNIV_SYNC_DEBUG */
#else /* UNIV_DEBUG */
# define rw_lock_create(L, level) \
# endif/* UNIV_SYNC_DEBUG */
# else /* UNIV_DEBUG */
# define rw_lock_create(K, L, level) \
rw_lock_create_func((L), #L)
#endif /* UNIV_DEBUG */
# endif /* UNIV_DEBUG */
/**************************************************************//**
NOTE! The following macros should be used in rw locking and
unlocking, not the corresponding function. */
# define rw_lock_s_lock(M) \
rw_lock_s_lock_func((M), 0, __FILE__, __LINE__)
# define rw_lock_s_lock_gen(M, P) \
rw_lock_s_lock_func((M), (P), __FILE__, __LINE__)
# define rw_lock_s_lock_nowait(M, F, L) \
rw_lock_s_lock_low((M), 0, (F), (L))
# ifdef UNIV_SYNC_DEBUG
# define rw_lock_s_unlock_gen(L, P) rw_lock_s_unlock_func(P, L)
# else
# define rw_lock_s_unlock_gen(L, P) rw_lock_s_unlock_func(L)
# endif
# define rw_lock_x_lock(M) \
rw_lock_x_lock_func((M), 0, __FILE__, __LINE__)
# define rw_lock_x_lock_gen(M, P) \
rw_lock_x_lock_func((M), (P), __FILE__, __LINE__)
# define rw_lock_x_lock_nowait(M) \
rw_lock_x_lock_func_nowait((M), __FILE__, __LINE__)
# ifdef UNIV_SYNC_DEBUG
# define rw_lock_x_unlock_gen(L, P) rw_lock_x_unlock_func(P, L)
# else
# define rw_lock_x_unlock_gen(L, P) rw_lock_x_unlock_func(L)
# endif
# define rw_lock_free(M) rw_lock_free_func(M)
#else /* !UNIV_PFS_RWLOCK */
/* Following macros point to Performance Schema instrumented functions. */
# ifdef UNIV_DEBUG
# ifdef UNIV_SYNC_DEBUG
# define rw_lock_create(K, L, level) \
pfs_rw_lock_create_func((K), (L), (level), __FILE__, __LINE__, #L)
# else /* UNIV_SYNC_DEBUG */
# define rw_lock_create(K, L, level) \
pfs_rw_lock_create_func((K), (L), __FILE__, __LINE__, #L)
# endif/* UNIV_SYNC_DEBUG */
# else /* UNIV_DEBUG */
# define rw_lock_create(K, L, level) \
pfs_rw_lock_create_func((K), (L), #L)
# endif /* UNIV_DEBUG */
/******************************************************************
NOTE! The following macros should be used in rw locking and
unlocking, not the corresponding function. */
# define rw_lock_s_lock(M) \
pfs_rw_lock_s_lock_func((M), 0, __FILE__, __LINE__)
# define rw_lock_s_lock_gen(M, P) \
pfs_rw_lock_s_lock_func((M), (P), __FILE__, __LINE__)
# define rw_lock_s_lock_nowait(M, F, L) \
pfs_rw_lock_s_lock_low((M), 0, (F), (L))
# ifdef UNIV_SYNC_DEBUG
# define rw_lock_s_unlock_gen(L, P) pfs_rw_lock_s_unlock_func(P, L)
# else
# define rw_lock_s_unlock_gen(L, P) pfs_rw_lock_s_unlock_func(L)
# endif
# define rw_lock_x_lock(M) \
pfs_rw_lock_x_lock_func((M), 0, __FILE__, __LINE__)
# define rw_lock_x_lock_gen(M, P) \
pfs_rw_lock_x_lock_func((M), (P), __FILE__, __LINE__)
# define rw_lock_x_lock_nowait(M) \
pfs_rw_lock_x_lock_func_nowait((M), __FILE__, __LINE__)
# ifdef UNIV_SYNC_DEBUG
# define rw_lock_x_unlock_gen(L, P) pfs_rw_lock_x_unlock_func(P, L)
# else
# define rw_lock_x_unlock_gen(L, P) pfs_rw_lock_x_unlock_func(L)
# endif
# define rw_lock_free(M) pfs_rw_lock_free_func(M)
#endif /* UNIV_PFS_RWLOCK */
#define rw_lock_s_unlock(L) rw_lock_s_unlock_gen(L, 0)
#define rw_lock_x_unlock(L) rw_lock_x_unlock_gen(L, 0)
/******************************************************************//**
Creates, or rather, initializes an rw-lock object in a specified memory
@ -147,8 +266,8 @@ the rw-lock is freed. Removes an rw-lock object from the global list. The
rw-lock is checked to be in the non-locked state. */
UNIV_INTERN
void
rw_lock_free(
/*=========*/
rw_lock_free_func(
/*==============*/
rw_lock_t* lock); /*!< in: rw-lock */
#ifdef UNIV_DEBUG
/******************************************************************//**
@ -161,24 +280,6 @@ rw_lock_validate(
/*=============*/
rw_lock_t* lock); /*!< in: rw-lock */
#endif /* UNIV_DEBUG */
/**************************************************************//**
NOTE! The following macros should be used in rw s-locking, not the
corresponding function. */
#define rw_lock_s_lock(M) rw_lock_s_lock_func(\
(M), 0, __FILE__, __LINE__)
/**************************************************************//**
NOTE! The following macros should be used in rw s-locking, not the
corresponding function. */
#define rw_lock_s_lock_gen(M, P) rw_lock_s_lock_func(\
(M), (P), __FILE__, __LINE__)
/**************************************************************//**
NOTE! The following macros should be used in rw s-locking, not the
corresponding function. */
#define rw_lock_s_lock_nowait(M, F, L) rw_lock_s_lock_low(\
(M), 0, (F), (L))
/******************************************************************//**
Low-level function which tries to lock an rw-lock in s-mode. Performs no
spinning.
@ -233,33 +334,6 @@ rw_lock_s_unlock_func(
#endif
rw_lock_t* lock); /*!< in/out: rw-lock */
#ifdef UNIV_SYNC_DEBUG
# define rw_lock_s_unlock_gen(L, P) rw_lock_s_unlock_func(P, L)
#else
# define rw_lock_s_unlock_gen(L, P) rw_lock_s_unlock_func(L)
#endif
/*******************************************************************//**
Releases a shared mode lock. */
#define rw_lock_s_unlock(L) rw_lock_s_unlock_gen(L, 0)
/**************************************************************//**
NOTE! The following macro should be used in rw x-locking, not the
corresponding function. */
#define rw_lock_x_lock(M) rw_lock_x_lock_func(\
(M), 0, __FILE__, __LINE__)
/**************************************************************//**
NOTE! The following macro should be used in rw x-locking, not the
corresponding function. */
#define rw_lock_x_lock_gen(M, P) rw_lock_x_lock_func(\
(M), (P), __FILE__, __LINE__)
/**************************************************************//**
NOTE! The following macros should be used in rw x-locking, not the
corresponding function. */
#define rw_lock_x_lock_nowait(M) rw_lock_x_lock_func_nowait(\
(M), __FILE__, __LINE__)
/******************************************************************//**
NOTE! Use the corresponding macro, not directly this function! Lock an
rw-lock in exclusive mode for the current thread. If the rw-lock is locked
@ -290,14 +364,6 @@ rw_lock_x_unlock_func(
#endif
rw_lock_t* lock); /*!< in/out: rw-lock */
#ifdef UNIV_SYNC_DEBUG
# define rw_lock_x_unlock_gen(L, P) rw_lock_x_unlock_func(P, L)
#else
# define rw_lock_x_unlock_gen(L, P) rw_lock_x_unlock_func(L)
#endif
/*******************************************************************//**
Releases an exclusive mode lock. */
#define rw_lock_x_unlock(L) rw_lock_x_unlock_gen(L, 0)
/******************************************************************//**
Low-level function which locks an rw-lock in s-mode when we know that it
@ -541,6 +607,9 @@ struct rw_lock_struct {
info list of the lock */
ulint level; /*!< Level in the global latching order. */
#endif /* UNIV_SYNC_DEBUG */
#ifdef UNIV_PFS_RWLOCK
struct PSI_rwlock *pfs_psi;/*!< The instrumentation hook */
#endif
ulint count_os_wait; /*!< Count of os_waits. May not be accurate */
//const char* cfile_name;/*!< File name where lock created */
const char* lock_name;/*!< lock name */
@ -581,6 +650,160 @@ struct rw_lock_debug_struct {
};
#endif /* UNIV_SYNC_DEBUG */
/* For performance schema instrumentation, a new set of rwlock
wrap functions are created if "UNIV_PFS_RWLOCK" is defined.
The instrumentations are not planted directly into original
functions, so that we keep the underlying function as they
are. And in case, user wants to "take out" some rwlock from
instrumentation even if performance schema (UNIV_PFS_RWLOCK)
is defined, they can do so by reinstating APIs directly link to
original underlying functions.
The instrumented function names have prefix of "pfs_rw_lock_" vs.
original name prefix of "rw_lock_". Following are list of functions
that have been instrumented:
rw_lock_create()
rw_lock_x_lock()
rw_lock_x_lock_gen()
rw_lock_x_lock_nowait()
rw_lock_x_unlock_gen()
rw_lock_s_lock()
rw_lock_s_lock_gen()
rw_lock_s_lock_nowait()
rw_lock_s_unlock_gen()
rw_lock_free()
Two function APIs rw_lock_x_unlock_direct() and rw_lock_s_unlock_direct()
do not have any caller/user, they are not instrumented.
*/
#ifdef UNIV_PFS_RWLOCK
/******************************************************************//**
Performance schema instrumented wrap function for rw_lock_create_func()
NOTE! Please use the corresponding macro rw_lock_create(), not
directly this function! */
UNIV_INLINE
void
pfs_rw_lock_create_func(
/*====================*/
PSI_rwlock_key key, /*!< in: key registered with
performance schema */
rw_lock_t* lock, /*!< in: rw lock */
#ifdef UNIV_DEBUG
# ifdef UNIV_SYNC_DEBUG
ulint level, /*!< in: level */
# endif /* UNIV_SYNC_DEBUG */
const char* cfile_name, /*!< in: file name where created */
ulint cline, /*!< in: file line where created */
#endif /* UNIV_DEBUG */
const char* cmutex_name); /*!< in: mutex name */
/******************************************************************//**
Performance schema instrumented wrap function for rw_lock_x_lock_func()
NOTE! Please use the corresponding macro rw_lock_x_lock(), not
directly this function! */
UNIV_INLINE
void
pfs_rw_lock_x_lock_func(
/*====================*/
rw_lock_t* lock, /*!< in: pointer to rw-lock */
ulint pass, /*!< in: pass value; != 0, if the lock will
be passed to another thread to unlock */
const char* file_name,/*!< in: file name where lock requested */
ulint line); /*!< in: line where requested */
/******************************************************************//**
Performance schema instrumented wrap function for
rw_lock_x_lock_func_nowait()
NOTE! Please use the corresponding macro, not directly this function!
@return TRUE if success */
UNIV_INLINE
ibool
pfs_rw_lock_x_lock_func_nowait(
/*===========================*/
rw_lock_t* lock, /*!< in: pointer to rw-lock */
const char* file_name,/*!< in: file name where lock requested */
ulint line); /*!< in: line where requested */
/******************************************************************//**
Performance schema instrumented wrap function for rw_lock_s_lock_func()
NOTE! Please use the corresponding macro rw_lock_s_lock(), not directly
this function! */
UNIV_INLINE
void
pfs_rw_lock_s_lock_func(
/*====================*/
rw_lock_t* lock, /*!< in: pointer to rw-lock */
ulint pass, /*!< in: pass value; != 0, if the lock will
be passed to another thread to unlock */
const char* file_name,/*!< in: file name where lock requested */
ulint line); /*!< in: line where requested */
/******************************************************************//**
Performance schema instrumented wrap function for rw_lock_s_lock_func()
NOTE! Please use the corresponding macro rw_lock_s_lock(), not directly
this function!
@return TRUE if success */
UNIV_INLINE
ibool
pfs_rw_lock_s_lock_low(
/*===================*/
rw_lock_t* lock, /*!< in: pointer to rw-lock */
ulint pass, /*!< in: pass value; != 0, if the
lock will be passed to another
thread to unlock */
const char* file_name, /*!< in: file name where lock requested */
ulint line); /*!< in: line where requested */
/******************************************************************//**
Performance schema instrumented wrap function for rw_lock_x_lock_func()
NOTE! Please use the corresponding macro rw_lock_x_lock(), not directly
this function! */
UNIV_INLINE
void
pfs_rw_lock_x_lock_func(
/*====================*/
rw_lock_t* lock, /*!< in: pointer to rw-lock */
ulint pass, /*!< in: pass value; != 0, if the lock will
be passed to another thread to unlock */
const char* file_name,/*!< in: file name where lock requested */
ulint line); /*!< in: line where requested */
/******************************************************************//**
Performance schema instrumented wrap function for rw_lock_s_unlock_func()
NOTE! Please use the corresponding macro rw_lock_s_unlock(), not directly
this function! */
UNIV_INLINE
void
pfs_rw_lock_s_unlock_func(
/*======================*/
#ifdef UNIV_SYNC_DEBUG
ulint pass, /*!< in: pass value; != 0, if the
lock may have been passed to another
thread to unlock */
#endif
rw_lock_t* lock); /*!< in/out: rw-lock */
/******************************************************************//**
Performance schema instrumented wrap function for rw_lock_s_unlock_func()
NOTE! Please use the corresponding macro rw_lock_x_unlock(), not directly
this function! */
UNIV_INLINE
void
pfs_rw_lock_x_unlock_func(
/*======================*/
#ifdef UNIV_SYNC_DEBUG
ulint pass, /*!< in: pass value; != 0, if the
lock may have been passed to another
thread to unlock */
#endif
rw_lock_t* lock); /*!< in/out: rw-lock */
/******************************************************************//**
Performance schema instrumented wrap function for rw_lock_free_func()
NOTE! Please use the corresponding macro rw_lock_free(), not directly
this function! */
UNIV_INLINE
void
pfs_rw_lock_free_func(
/*==================*/
rw_lock_t* lock); /*!< in: rw-lock */
#endif /* UNIV_PFS_RWLOCK */
#ifndef UNIV_NONINL
#include "sync0rw.ic"
#endif

View file

@ -622,3 +622,260 @@ rw_lock_x_unlock_direct(
rw_x_exit_count++;
#endif
}
#ifdef UNIV_PFS_RWLOCK
/******************************************************************//**
Performance schema instrumented wrap function for rw_lock_create_func().
NOTE! Please use the corresponding macro rw_lock_create(), not directly
this function! */
UNIV_INLINE
void
pfs_rw_lock_create_func(
/*====================*/
mysql_pfs_key_t key, /*!< in: key registered with
performance schema */
rw_lock_t* lock, /*!< in: pointer to memory */
# ifdef UNIV_DEBUG
# ifdef UNIV_SYNC_DEBUG
ulint level, /*!< in: level */
# endif /* UNIV_SYNC_DEBUG */
const char* cfile_name, /*!< in: file name where created */
ulint cline, /*!< in: file line where created */
# endif /* UNIV_DEBUG */
const char* cmutex_name) /*!< in: mutex name */
{
/* Initialize the rwlock for performance schema */
lock->pfs_psi = (PSI_server && PFS_IS_INSTRUMENTED(key))
? PSI_server->init_rwlock(key, lock)
: NULL;
/* The actual function to initialize an rwlock */
rw_lock_create_func(lock,
# ifdef UNIV_DEBUG
# ifdef UNIV_SYNC_DEBUG
level,
# endif /* UNIV_SYNC_DEBUG */
cfile_name,
cline,
# endif /* UNIV_DEBUG */
cmutex_name);
}
/******************************************************************//**
Performance schema instrumented wrap function for rw_lock_x_lock_func()
NOTE! Please use the corresponding macro rw_lock_x_lock(), not directly
this function! */
UNIV_INLINE
void
pfs_rw_lock_x_lock_func(
/*====================*/
rw_lock_t* lock, /*!< in: pointer to rw-lock */
ulint pass, /*!< in: pass value; != 0, if the lock will
be passed to another thread to unlock */
const char* file_name,/*!< in: file name where lock requested */
ulint line) /*!< in: line where requested */
{
struct PSI_rwlock_locker* locker = NULL;
PSI_rwlock_locker_state state;
/* Record the entry of rw x lock request in performance schema */
if (UNIV_LIKELY(PSI_server && lock->pfs_psi)) {
locker = PSI_server->get_thread_rwlock_locker(
&state, lock->pfs_psi, PSI_RWLOCK_WRITELOCK);
if (locker) {
PSI_server->start_rwlock_wrwait(locker,
file_name, line);
}
}
rw_lock_x_lock_func(lock, pass, file_name, line);
if (locker) {
PSI_server->end_rwlock_wrwait(locker, 0);
}
}
/******************************************************************//**
Performance schema instrumented wrap function for
rw_lock_x_lock_func_nowait()
NOTE! Please use the corresponding macro rw_lock_x_lock_func(),
not directly this function!
@return TRUE if success */
UNIV_INLINE
ibool
pfs_rw_lock_x_lock_func_nowait(
/*===========================*/
rw_lock_t* lock, /*!< in: pointer to rw-lock */
const char* file_name,/*!< in: file name where lock
requested */
ulint line) /*!< in: line where requested */
{
struct PSI_rwlock_locker* locker = NULL;
PSI_rwlock_locker_state state;
ibool ret;
/* Record the entry of rw x lock request in performance schema */
if (UNIV_LIKELY(PSI_server && lock->pfs_psi)) {
locker = PSI_server->get_thread_rwlock_locker(
&state, lock->pfs_psi, PSI_RWLOCK_WRITELOCK);
if (locker) {
PSI_server->start_rwlock_wrwait(locker,
file_name, line);
}
}
ret = rw_lock_x_lock_func_nowait(lock, file_name, line);
if (locker) {
PSI_server->end_rwlock_wrwait(locker, 0);
}
return(ret);
}
/******************************************************************//**
Performance schema instrumented wrap function for rw_lock_free_func()
NOTE! Please use the corresponding macro rw_lock_free(), not directly
this function! */
UNIV_INLINE
void
pfs_rw_lock_free_func(
/*==================*/
rw_lock_t* lock) /*!< in: pointer to rw-lock */
{
if (UNIV_LIKELY(PSI_server && lock->pfs_psi)) {
PSI_server->destroy_rwlock(lock->pfs_psi);
lock->pfs_psi = NULL;
}
rw_lock_free_func(lock);
}
/******************************************************************//**
Performance schema instrumented wrap function for rw_lock_s_lock_func()
NOTE! Please use the corresponding macro rw_lock_s_lock(), not
directly this function! */
UNIV_INLINE
void
pfs_rw_lock_s_lock_func(
/*====================*/
rw_lock_t* lock, /*!< in: pointer to rw-lock */
ulint pass, /*!< in: pass value; != 0, if the
lock will be passed to another
thread to unlock */
const char* file_name,/*!< in: file name where lock
requested */
ulint line) /*!< in: line where requested */
{
struct PSI_rwlock_locker* locker = NULL;
PSI_rwlock_locker_state state;
/* Instrumented to inform we are aquiring a shared rwlock */
if (UNIV_LIKELY(PSI_server && lock->pfs_psi)) {
locker = PSI_server->get_thread_rwlock_locker(
&state, lock->pfs_psi, PSI_RWLOCK_READLOCK);
if (locker) {
PSI_server->start_rwlock_rdwait(locker,
file_name, line);
}
}
rw_lock_s_lock_func(lock, pass, file_name, line);
if (locker) {
PSI_server->end_rwlock_rdwait(locker, 0);
}
}
/******************************************************************//**
Performance schema instrumented wrap function for rw_lock_s_lock_func()
NOTE! Please use the corresponding macro rw_lock_s_lock(), not
directly this function!
@return TRUE if success */
UNIV_INLINE
ibool
pfs_rw_lock_s_lock_low(
/*===================*/
rw_lock_t* lock, /*!< in: pointer to rw-lock */
ulint pass, /*!< in: pass value; != 0, if the
lock will be passed to another
thread to unlock */
const char* file_name, /*!< in: file name where lock requested */
ulint line) /*!< in: line where requested */
{
struct PSI_rwlock_locker* locker = NULL;
PSI_rwlock_locker_state state;
ibool ret;
/* Instrumented to inform we are aquiring a shared rwlock */
if (UNIV_LIKELY(PSI_server && lock->pfs_psi)) {
locker = PSI_server->get_thread_rwlock_locker(
&state, lock->pfs_psi, PSI_RWLOCK_READLOCK);
if (locker) {
PSI_server->start_rwlock_rdwait(locker,
file_name, line);
}
}
ret = rw_lock_s_lock_low(lock, pass, file_name, line);
if (locker) {
PSI_server->end_rwlock_rdwait(locker, 0);
}
return(ret);
}
/******************************************************************//**
Performance schema instrumented wrap function for rw_lock_x_unlock_func()
NOTE! Please use the corresponding macro rw_lock_x_unlock(), not directly
this function! */
UNIV_INLINE
void
pfs_rw_lock_x_unlock_func(
/*======================*/
#ifdef UNIV_SYNC_DEBUG
ulint pass, /*!< in: pass value; != 0, if the
lock may have been passed to another
thread to unlock */
#endif
rw_lock_t* lock) /*!< in/out: rw-lock */
{
/* Inform performance schema we are unlocking the lock */
if (UNIV_LIKELY(PSI_server && lock->pfs_psi)) {
PSI_server->unlock_rwlock(lock->pfs_psi);
}
rw_lock_x_unlock_func(
#ifdef UNIV_SYNC_DEBUG
pass,
#endif
lock);
}
/******************************************************************//**
Performance schema instrumented wrap function for rw_lock_s_unlock_func()
NOTE! Please use the corresponding macro pfs_rw_lock_s_unlock(), not
directly this function! */
UNIV_INLINE
void
pfs_rw_lock_s_unlock_func(
/*======================*/
#ifdef UNIV_SYNC_DEBUG
ulint pass, /*!< in: pass value; != 0, if the
lock may have been passed to another
thread to unlock */
#endif
rw_lock_t* lock) /*!< in/out: rw-lock */
{
/* Inform performance schema we are unlocking the lock */
if (UNIV_LIKELY(PSI_server && lock->pfs_psi)) {
PSI_server->unlock_rwlock(lock->pfs_psi);
}
rw_lock_s_unlock_func(
#ifdef UNIV_SYNC_DEBUG
pass,
#endif
lock);
}
#endif /* UNIV_PFS_RWLOCK */

View file

@ -1,6 +1,6 @@
/*****************************************************************************
Copyright (c) 1995, 2010, Innobase Oy. All Rights Reserved.
Copyright (c) 1995, 2011, Innobase Oy. All Rights Reserved.
Copyright (c) 2008, Google Inc.
Portions of this file contain modifications contributed and copyrighted by
@ -52,6 +52,71 @@ typedef LONG lock_word_t; /*!< On Windows, InterlockedExchange operates
typedef byte lock_word_t;
#endif
#if defined UNIV_PFS_MUTEX || defined UNIV_PFS_RWLOCK
/* There are mutexes/rwlocks that we want to exclude from
instrumentation even if their corresponding performance schema
define is set. And this PFS_NOT_INSTRUMENTED is used
as the key value to dentify those objects that would
be excluded from instrumentation. */
# define PFS_NOT_INSTRUMENTED ULINT32_UNDEFINED
# define PFS_IS_INSTRUMENTED(key) ((key) != PFS_NOT_INSTRUMENTED)
/* By default, buffer mutexes and rwlocks will be excluded from
instrumentation due to their large number of instances. */
# define PFS_SKIP_BUFFER_MUTEX_RWLOCK
#endif /* UNIV_PFS_MUTEX || UNIV_PFS_RWLOCK */
#ifdef UNIV_PFS_MUTEX
/* Key defines to register InnoDB mutexes with performance schema */
extern mysql_pfs_key_t autoinc_mutex_key;
extern mysql_pfs_key_t btr_search_enabled_mutex_key;
extern mysql_pfs_key_t buffer_block_mutex_key;
extern mysql_pfs_key_t buf_pool_mutex_key;
extern mysql_pfs_key_t buf_pool_zip_mutex_key;
extern mysql_pfs_key_t buf_pool_LRU_list_mutex_key;
extern mysql_pfs_key_t buf_pool_free_list_mutex_key;
extern mysql_pfs_key_t buf_pool_zip_free_mutex_key;
extern mysql_pfs_key_t buf_pool_zip_hash_mutex_key;
extern mysql_pfs_key_t cache_last_read_mutex_key;
extern mysql_pfs_key_t dict_foreign_err_mutex_key;
extern mysql_pfs_key_t dict_sys_mutex_key;
extern mysql_pfs_key_t file_format_max_mutex_key;
extern mysql_pfs_key_t fil_system_mutex_key;
extern mysql_pfs_key_t flush_list_mutex_key;
extern mysql_pfs_key_t hash_table_mutex_key;
extern mysql_pfs_key_t ibuf_bitmap_mutex_key;
extern mysql_pfs_key_t ibuf_mutex_key;
extern mysql_pfs_key_t ibuf_pessimistic_insert_mutex_key;
extern mysql_pfs_key_t log_sys_mutex_key;
extern mysql_pfs_key_t log_flush_order_mutex_key;
extern mysql_pfs_key_t kernel_mutex_key;
# ifdef UNIV_MEM_DEBUG
extern mysql_pfs_key_t mem_hash_mutex_key;
# endif /* UNIV_MEM_DEBUG */
extern mysql_pfs_key_t mem_pool_mutex_key;
extern mysql_pfs_key_t mutex_list_mutex_key;
extern mysql_pfs_key_t purge_sys_bh_mutex_key;
extern mysql_pfs_key_t recv_sys_mutex_key;
extern mysql_pfs_key_t rseg_mutex_key;
# ifdef UNIV_SYNC_DEBUG
extern mysql_pfs_key_t rw_lock_debug_mutex_key;
# endif /* UNIV_SYNC_DEBUG */
extern mysql_pfs_key_t rw_lock_list_mutex_key;
extern mysql_pfs_key_t rw_lock_mutex_key;
extern mysql_pfs_key_t srv_dict_tmpfile_mutex_key;
extern mysql_pfs_key_t srv_innodb_monitor_mutex_key;
extern mysql_pfs_key_t srv_misc_tmpfile_mutex_key;
extern mysql_pfs_key_t srv_monitor_file_mutex_key;
extern mysql_pfs_key_t syn_arr_mutex_key;
# ifdef UNIV_SYNC_DEBUG
extern mysql_pfs_key_t sync_thread_mutex_key;
# endif /* UNIV_SYNC_DEBUG */
extern mysql_pfs_key_t trx_doublewrite_mutex_key;
extern mysql_pfs_key_t trx_undo_mutex_key;
#endif /* UNIV_PFS_MUTEX */
/******************************************************************//**
Initializes the synchronization data structures. */
UNIV_INTERN
@ -64,24 +129,82 @@ UNIV_INTERN
void
sync_close(void);
/*===========*/
#undef mutex_free /* Fix for MacOS X */
#ifdef UNIV_PFS_MUTEX
/**********************************************************************
Following mutex APIs would be performance schema instrumented
if "UNIV_PFS_MUTEX" is defined:
mutex_create
mutex_enter
mutex_exit
mutex_enter_nowait
mutex_free
These mutex APIs will point to corresponding wrapper functions that contain
the performance schema instrumentation if "UNIV_PFS_MUTEX" is defined.
The instrumented wrapper functions have the prefix of "innodb_".
NOTE! The following macro should be used in mutex operation, not the
corresponding function. */
/******************************************************************//**
Creates, or rather, initializes a mutex object to a specified memory
location (which must be appropriately aligned). The mutex is initialized
in the reset state. Explicit freeing of the mutex with mutex_free is
necessary only if the memory block containing it is freed. */
#ifdef UNIV_DEBUG
# ifdef UNIV_SYNC_DEBUG
# define mutex_create(M, level) \
mutex_create_func((M), (level), __FILE__, __LINE__, #M)
# ifdef UNIV_DEBUG
# ifdef UNIV_SYNC_DEBUG
# define mutex_create(K, M, level) \
pfs_mutex_create_func((K), (M), (level), __FILE__, __LINE__, #M)
# else
# define mutex_create(K, M, level) \
pfs_mutex_create_func((K), (M), __FILE__, __LINE__, #M)
# endif/* UNIV_SYNC_DEBUG */
# else
# define mutex_create(M, level) \
# define mutex_create(K, M, level) \
pfs_mutex_create_func((K), (M), #M)
# endif /* UNIV_DEBUG */
# define mutex_enter(M) \
pfs_mutex_enter_func((M), __FILE__, __LINE__)
# define mutex_enter_nowait(M) \
pfs_mutex_enter_nowait_func((M), __FILE__, __LINE__)
# define mutex_exit(M) pfs_mutex_exit_func(M)
# define mutex_free(M) pfs_mutex_free_func(M)
#else /* UNIV_PFS_MUTEX */
/* If "UNIV_PFS_MUTEX" is not defined, the mutex APIs point to
original non-instrumented functions */
# ifdef UNIV_DEBUG
# ifdef UNIV_SYNC_DEBUG
# define mutex_create(K, M, level) \
mutex_create_func((M), (level), __FILE__, __LINE__, #M)
# else /* UNIV_SYNC_DEBUG */
# define mutex_create(K, M, level) \
mutex_create_func((M), __FILE__, __LINE__, #M)
# endif
#else
# define mutex_create(M, level) \
# endif /* UNIV_SYNC_DEBUG */
# else /* UNIV_DEBUG */
# define mutex_create(K, M, level) \
mutex_create_func((M), #M)
#endif
# endif /* UNIV_DEBUG */
# define mutex_enter(M) mutex_enter_func((M), __FILE__, __LINE__)
# define mutex_enter_nowait(M) \
mutex_enter_nowait_func((M), __FILE__, __LINE__)
# define mutex_exit(M) mutex_exit_func(M)
# define mutex_free(M) mutex_free_func(M)
#endif /* UNIV_PFS_MUTEX */
/******************************************************************//**
Creates, or rather, initializes a mutex object in a specified memory
@ -102,26 +225,20 @@ mutex_create_func(
#endif /* UNIV_DEBUG */
const char* cmutex_name); /*!< in: mutex name */
#undef mutex_free /* Fix for MacOS X */
/******************************************************************//**
NOTE! Use the corresponding macro mutex_free(), not directly this function!
Calling this function is obligatory only if the memory buffer containing
the mutex is freed. Removes a mutex object from the mutex list. The mutex
is checked to be in the reset state. */
UNIV_INTERN
void
mutex_free(
/*=======*/
mutex_free_func(
/*============*/
mutex_t* mutex); /*!< in: mutex */
/**************************************************************//**
NOTE! The following macro should be used in mutex locking, not the
corresponding function. */
#define mutex_enter(M) mutex_enter_func((M), __FILE__, __LINE__)
/**************************************************************//**
NOTE! The following macro should be used in mutex locking, not the
corresponding function. */
/* NOTE! currently same as mutex_enter! */
#define mutex_enter_fast(M) mutex_enter_func((M), __FILE__, __LINE__)
@ -137,12 +254,6 @@ mutex_enter_func(
mutex_t* mutex, /*!< in: pointer to mutex */
const char* file_name, /*!< in: file name where locked */
ulint line); /*!< in: line where locked */
/**************************************************************//**
NOTE! The following macro should be used in mutex locking, not the
corresponding function. */
#define mutex_enter_nowait(M) \
mutex_enter_nowait_func((M), __FILE__, __LINE__)
/********************************************************************//**
NOTE! Use the corresponding macro in the header file, not this function
directly. Tries to lock the mutex for the current thread. If the lock is not
@ -157,12 +268,86 @@ mutex_enter_nowait_func(
requested */
ulint line); /*!< in: line where requested */
/******************************************************************//**
NOTE! Use the corresponding macro mutex_exit(), not directly this function!
Unlocks a mutex owned by the current thread. */
UNIV_INLINE
void
mutex_exit(
/*=======*/
mutex_exit_func(
/*============*/
mutex_t* mutex); /*!< in: pointer to mutex */
#ifdef UNIV_PFS_MUTEX
/******************************************************************//**
NOTE! Please use the corresponding macro mutex_create(), not directly
this function!
A wrapper function for mutex_create_func(), registers the mutex
with peformance schema if "UNIV_PFS_MUTEX" is defined when
creating the mutex */
UNIV_INLINE
void
pfs_mutex_create_func(
/*==================*/
PSI_mutex_key key, /*!< in: Performance Schema key */
mutex_t* mutex, /*!< in: pointer to memory */
# ifdef UNIV_DEBUG
# ifdef UNIV_SYNC_DEBUG
ulint level, /*!< in: level */
# endif /* UNIV_SYNC_DEBUG */
const char* cfile_name, /*!< in: file name where created */
ulint cline, /*!< in: file line where created */
# endif /* UNIV_DEBUG */
const char* cmutex_name);
/******************************************************************//**
NOTE! Please use the corresponding macro mutex_enter(), not directly
this function!
This is a performance schema instrumented wrapper function for
mutex_enter_func(). */
UNIV_INLINE
void
pfs_mutex_enter_func(
/*=================*/
mutex_t* mutex, /*!< in: pointer to mutex */
const char* file_name, /*!< in: file name where locked */
ulint line); /*!< in: line where locked */
/********************************************************************//**
NOTE! Please use the corresponding macro mutex_enter_nowait(), not directly
this function!
This is a performance schema instrumented wrapper function for
mutex_enter_nowait_func.
@return 0 if succeed, 1 if not */
UNIV_INLINE
ulint
pfs_mutex_enter_nowait_func(
/*========================*/
mutex_t* mutex, /*!< in: pointer to mutex */
const char* file_name, /*!< in: file name where mutex
requested */
ulint line); /*!< in: line where requested */
/******************************************************************//**
NOTE! Please use the corresponding macro mutex_exit(), not directly
this function!
A wrap function of mutex_exit_func() with peformance schema instrumentation.
Unlocks a mutex owned by the current thread. */
UNIV_INLINE
void
pfs_mutex_exit_func(
/*================*/
mutex_t* mutex); /*!< in: pointer to mutex */
/******************************************************************//**
NOTE! Please use the corresponding macro mutex_free(), not directly
this function!
Wrapper function for mutex_free_func(). Also destroys the performance
schema probes when freeing the mutex */
UNIV_INLINE
void
pfs_mutex_free_func(
/*================*/
mutex_t* mutex); /*!< in: mutex */
#endif /* UNIV_PFS_MUTEX */
#ifdef UNIV_SYNC_DEBUG
/******************************************************************//**
Returns TRUE if no mutex or rw-lock is currently locked.
@ -232,13 +417,6 @@ sync_thread_reset_level(
/*====================*/
void* latch); /*!< in: pointer to a mutex or an rw-lock */
/******************************************************************//**
Checks that the level array for the current thread is empty.
@return TRUE if empty */
UNIV_INTERN
ibool
sync_thread_levels_empty(void);
/*==========================*/
/******************************************************************//**
Checks if the level array for the current thread contains a
mutex or rw-latch at the specified level.
@return a matching latch, or NULL if not found */
@ -249,17 +427,33 @@ sync_thread_levels_contains(
ulint level); /*!< in: latching order level
(SYNC_DICT, ...)*/
/******************************************************************//**
Checks if the level array for the current thread is empty.
Checks that the level array for the current thread is empty.
@return a latch, or NULL if empty except the exceptions specified below */
UNIV_INTERN
void*
sync_thread_levels_nonempty_gen(
/*============================*/
ibool dict_mutex_allowed); /*!< in: TRUE if dictionary mutex is
allowed to be owned by the thread,
also purge_is_running mutex is
allowed */
#define sync_thread_levels_empty_gen(d) (!sync_thread_levels_nonempty_gen(d))
ibool dict_mutex_allowed) /*!< in: TRUE if dictionary mutex is
allowed to be owned by the thread */
__attribute__((warn_unused_result));
/******************************************************************//**
Checks if the level array for the current thread is empty,
except for data dictionary latches. */
#define sync_thread_levels_empty_except_dict() \
(!sync_thread_levels_nonempty_gen(TRUE))
/******************************************************************//**
Checks if the level array for the current thread is empty,
except for the btr_search_latch.
@return a latch, or NULL if empty except the exceptions specified below */
UNIV_INTERN
void*
sync_thread_levels_nonempty_trx(
/*============================*/
ibool has_search_latch)
/*!< in: TRUE if and only if the thread
is supposed to hold btr_search_latch */
__attribute__((warn_unused_result));
/******************************************************************//**
Gets the debug information for a reserved mutex. */
UNIV_INTERN
@ -455,7 +649,6 @@ or row lock! */
#define SYNC_TREE_NODE_NEW 892
#define SYNC_TREE_NODE_FROM_HASH 891
#define SYNC_TREE_NODE 890
#define SYNC_PURGE_SYS 810
#define SYNC_PURGE_LATCH 800
#define SYNC_TRX_UNDO 700
#define SYNC_RSEG 600
@ -477,7 +670,9 @@ or row lock! */
#define SYNC_REC_LOCK 299
#define SYNC_TRX_LOCK_HEAP 298
#define SYNC_TRX_SYS_HEADER 290
#define SYNC_PURGE_QUEUE 200
#define SYNC_LOG 170
#define SYNC_LOG_FLUSH_ORDER 156
#define SYNC_RECV 168
#define SYNC_WORK_QUEUE 162
#define SYNC_SEARCH_SYS_CONF 161 /* for assigning btr_search_enabled */
@ -487,14 +682,14 @@ or row lock! */
SYNC_SEARCH_SYS, as memory allocation
can call routines there! Otherwise
the level is SYNC_MEM_HASH. */
#define SYNC_BUF_LRU_LIST 157
#define SYNC_BUF_PAGE_HASH 156
#define SYNC_BUF_BLOCK 155
#define SYNC_BUF_FREE_LIST 153
#define SYNC_BUF_ZIP_FREE 152
#define SYNC_BUF_ZIP_HASH 151
#define SYNC_BUF_POOL 150
#define SYNC_BUF_FLUSH_LIST 149
#define SYNC_BUF_LRU_LIST 158
#define SYNC_BUF_PAGE_HASH 157
#define SYNC_BUF_BLOCK 155 /* Block mutex */
#define SYNC_BUF_FREE_LIST 153
#define SYNC_BUF_ZIP_FREE 152
#define SYNC_BUF_ZIP_HASH 151
#define SYNC_BUF_POOL 150 /* Buffer pool mutex */
#define SYNC_BUF_FLUSH_LIST 145 /* Buffer flush list mutex */
#define SYNC_DOUBLEWRITE 140
#define SYNC_OUTER_ANY_LATCH 136
#define SYNC_ANY_LATCH 135
@ -557,6 +752,10 @@ struct mutex_struct {
ulint mutex_type; /*!< 0=usual mutex, 1=rw_lock mutex */
#endif /* UNIV_DEBUG */
const char* cmutex_name; /*!< mutex name */
#ifdef UNIV_PFS_MUTEX
struct PSI_mutex* pfs_psi; /*!< The performance schema
instrumentation hook */
#endif
};
/** The global array of wait cells for implementation of the databases own
@ -570,6 +769,10 @@ to 20 microseconds. */
#define SYNC_SPIN_ROUNDS srv_n_spin_wait_rounds
extern ib_int64_t mutex_spin_round_count;
extern ib_int64_t mutex_spin_wait_count;
extern ib_int64_t mutex_os_wait_count;
/** The number of mutex_exit calls. Intended for performance monitoring. */
extern ib_int64_t mutex_exit_count;

View file

@ -152,11 +152,12 @@ mutex_get_waiters(
}
/******************************************************************//**
NOTE! Use the corresponding macro mutex_exit(), not directly this function!
Unlocks a mutex owned by the current thread. */
UNIV_INLINE
void
mutex_exit(
/*=======*/
mutex_exit_func(
/*============*/
mutex_t* mutex) /*!< in: pointer to mutex */
{
ut_ad(mutex_own(mutex));
@ -220,3 +221,145 @@ mutex_enter_func(
mutex_spin_wait(mutex, file_name, line);
}
#ifdef UNIV_PFS_MUTEX
/******************************************************************//**
NOTE! Please use the corresponding macro mutex_enter(), not directly
this function!
This is a performance schema instrumented wrapper function for
mutex_enter_func(). */
UNIV_INLINE
void
pfs_mutex_enter_func(
/*=================*/
mutex_t* mutex, /*!< in: pointer to mutex */
const char* file_name, /*!< in: file name where locked */
ulint line) /*!< in: line where locked */
{
struct PSI_mutex_locker* locker = NULL;
PSI_mutex_locker_state state;
int result = 0;
if (UNIV_LIKELY(PSI_server && mutex->pfs_psi)) {
locker = PSI_server->get_thread_mutex_locker(
&state, mutex->pfs_psi, PSI_MUTEX_LOCK);
if (locker) {
PSI_server->start_mutex_wait(locker, file_name, line);
}
}
mutex_enter_func(mutex, file_name, line);
if (locker) {
PSI_server->end_mutex_wait(locker, result);
}
}
/********************************************************************//**
NOTE! Please use the corresponding macro mutex_enter_nowait(), not directly
this function!
This is a performance schema instrumented wrapper function for
mutex_enter_nowait_func.
@return 0 if succeed, 1 if not */
UNIV_INLINE
ulint
pfs_mutex_enter_nowait_func(
/*========================*/
mutex_t* mutex, /*!< in: pointer to mutex */
const char* file_name, /*!< in: file name where mutex
requested */
ulint line) /*!< in: line where requested */
{
ulint ret;
struct PSI_mutex_locker* locker = NULL;
PSI_mutex_locker_state state;
int result = 0;
if (UNIV_LIKELY(PSI_server && mutex->pfs_psi)) {
locker = PSI_server->get_thread_mutex_locker(
&state, mutex->pfs_psi, PSI_MUTEX_LOCK);
if (locker) {
PSI_server->start_mutex_wait(locker, file_name, line);
}
}
ret = mutex_enter_nowait_func(mutex, file_name, line);
if (locker) {
PSI_server->end_mutex_wait(locker, result);
}
return(ret);
}
/******************************************************************//**
NOTE! Please use the corresponding macro mutex_exit(), not directly
this function!
A wrap function of mutex_exit_func() with performance schema instrumentation.
Unlocks a mutex owned by the current thread. */
UNIV_INLINE
void
pfs_mutex_exit_func(
/*================*/
mutex_t* mutex) /*!< in: pointer to mutex */
{
if (UNIV_LIKELY(PSI_server && mutex->pfs_psi)) {
PSI_server->unlock_mutex(mutex->pfs_psi);
}
mutex_exit_func(mutex);
}
/******************************************************************//**
NOTE! Please use the corresponding macro mutex_create(), not directly
this function!
A wrapper function for mutex_create_func(), registers the mutex
with performance schema if "UNIV_PFS_MUTEX" is defined when
creating the mutex */
UNIV_INLINE
void
pfs_mutex_create_func(
/*==================*/
mysql_pfs_key_t key, /*!< in: Performance Schema key */
mutex_t* mutex, /*!< in: pointer to memory */
# ifdef UNIV_DEBUG
# ifdef UNIV_SYNC_DEBUG
ulint level, /*!< in: level */
# endif /* UNIV_SYNC_DEBUG */
const char* cfile_name, /*!< in: file name where created */
ulint cline, /*!< in: file line where created */
# endif /* UNIV_DEBUG */
const char* cmutex_name) /*!< in: mutex name */
{
mutex->pfs_psi = (PSI_server && PFS_IS_INSTRUMENTED(key))
? PSI_server->init_mutex(key, mutex)
: NULL;
mutex_create_func(mutex,
# ifdef UNIV_DEBUG
# ifdef UNIV_SYNC_DEBUG
level,
# endif /* UNIV_SYNC_DEBUG */
cfile_name,
cline,
# endif /* UNIV_DEBUG */
cmutex_name);
}
/******************************************************************//**
NOTE! Please use the corresponding macro mutex_free(), not directly
this function!
Wrapper function for mutex_free_func(). Also destroys the performance
schema probes when freeing the mutex */
UNIV_INLINE
void
pfs_mutex_free_func(
/*================*/
mutex_t* mutex) /*!< in: mutex */
{
if (UNIV_LIKELY(PSI_server && mutex->pfs_psi)) {
PSI_server->destroy_mutex(mutex->pfs_psi);
mutex->pfs_psi = NULL;
}
mutex_free_func(mutex);
}
#endif /* UNIV_PFS_MUTEX */

View file

@ -1,101 +0,0 @@
/*****************************************************************************
Copyright (c) 1995, 2009, Innobase Oy. 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., 59 Temple
Place, Suite 330, Boston, MA 02111-1307 USA
*****************************************************************************/
/**************************************************//**
@file include/thr0loc.h
The thread local storage
Created 10/5/1995 Heikki Tuuri
*******************************************************/
/* This module implements storage private to each thread,
a capability useful in some situations like storing the
OS handle to the current thread, or its priority. */
#ifndef thr0loc_h
#define thr0loc_h
#include "univ.i"
#include "os0thread.h"
/****************************************************************//**
Initializes the thread local storage module. */
UNIV_INTERN
void
thr_local_init(void);
/*================*/
/****************************************************************//**
Close the thread local storage module. */
UNIV_INTERN
void
thr_local_close(void);
/*=================*/
/*******************************************************************//**
Creates a local storage struct for the calling new thread. */
UNIV_INTERN
void
thr_local_create(void);
/*==================*/
/*******************************************************************//**
Frees the local storage struct for the specified thread. */
UNIV_INTERN
void
thr_local_free(
/*===========*/
os_thread_id_t id); /*!< in: thread id */
/*******************************************************************//**
Gets the slot number in the thread table of a thread.
@return slot number */
UNIV_INTERN
ulint
thr_local_get_slot_no(
/*==================*/
os_thread_id_t id); /*!< in: thread id of the thread */
/*******************************************************************//**
Sets in the local storage the slot number in the thread table of a thread. */
UNIV_INTERN
void
thr_local_set_slot_no(
/*==================*/
os_thread_id_t id, /*!< in: thread id of the thread */
ulint slot_no);/*!< in: slot number */
/*******************************************************************//**
Returns pointer to the 'in_ibuf' field within the current thread local
storage.
@return pointer to the in_ibuf field */
UNIV_INTERN
ibool*
thr_local_get_in_ibuf_field(void);
/*=============================*/
/*************************************************************************
Return local hash table informations. */
ulint
thr_local_hash_cells(void);
/*=======================*/
ulint
thr_local_hash_nodes(void);
/*=======================*/
#ifndef UNIV_NONINL
#include "thr0loc.ic"
#endif
#endif

View file

@ -1,24 +0,0 @@
/*****************************************************************************
Copyright (c) 1995, 2009, Innobase Oy. 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., 59 Temple
Place, Suite 330, Boston, MA 02111-1307 USA
*****************************************************************************/
/**************************************************//**
@file include/thr0loc.ic
Thread local storage
Created 10/4/1995 Heikki Tuuri
*******************************************************/

View file

@ -30,6 +30,7 @@ Created July 17, 2007 Vasil Dimov
#include "univ.i"
#include "trx0types.h"
#include "dict0types.h"
#include "ut0ut.h"
/** The maximum amount of memory that can be consumed by innodb_trx,
@ -44,6 +45,37 @@ i_s_locks_row_t::lock_data */
i_s_trx_row_t::trx_query */
#define TRX_I_S_TRX_QUERY_MAX_LEN 1024
/** The maximum length of a string that can be stored in
i_s_trx_row_t::trx_operation_state */
#define TRX_I_S_TRX_OP_STATE_MAX_LEN 64
/** The maximum length of a string that can be stored in
i_s_trx_row_t::trx_foreign_key_error */
#define TRX_I_S_TRX_FK_ERROR_MAX_LEN 256
/** The maximum length of a string that can be stored in
i_s_trx_row_t::trx_isolation_level */
#define TRX_I_S_TRX_ISOLATION_LEVEL_MAX_LEN 16
/** Safely copy strings in to the INNODB_TRX table's
string based columns */
#define TRX_I_S_STRING_COPY(data, field, constraint, tcache) \
do { \
if (strlen(data) > constraint) { \
char buff[constraint + 1]; \
strncpy(buff, data, constraint); \
buff[constraint] = '\0'; \
\
field = ha_storage_put_memlim( \
(tcache)->storage, buff, constraint + 1,\
MAX_ALLOWED_FOR_STORAGE(tcache)); \
} else { \
field = ha_storage_put_str_memlim( \
(tcache)->storage, data, \
MAX_ALLOWED_FOR_STORAGE(tcache)); \
} \
} while (0)
/** A row of INFORMATION_SCHEMA.innodb_locks */
typedef struct i_s_locks_row_struct i_s_locks_row_t;
/** A row of INFORMATION_SCHEMA.innodb_trx */
@ -64,7 +96,7 @@ struct i_s_hash_chain_struct {
/** This structure represents INFORMATION_SCHEMA.innodb_locks row */
struct i_s_locks_row_struct {
ullint lock_trx_id; /*!< transaction identifier */
trx_id_t lock_trx_id; /*!< transaction identifier */
const char* lock_mode; /*!< lock mode from
lock_get_mode_str() */
const char* lock_type; /*!< lock type from
@ -85,7 +117,7 @@ struct i_s_locks_row_struct {
/** The following are auxiliary and not included in the table */
/* @{ */
ullint lock_table_id;
table_id_t lock_table_id;
/*!< table identifier from
lock_get_table_id */
i_s_hash_chain_t hash_chain; /*!< hash table chain node for
@ -95,23 +127,52 @@ struct i_s_locks_row_struct {
/** This structure represents INFORMATION_SCHEMA.innodb_trx row */
struct i_s_trx_row_struct {
ullint trx_id; /*!< transaction identifier */
trx_id_t trx_id; /*!< transaction identifier */
const char* trx_state; /*!< transaction state from
trx_get_que_state_str() */
ib_time_t trx_started; /*!< trx_struct::start_time */
const i_s_locks_row_t* requested_lock_row;
/*!< pointer to a row
in innodb_locks if trx
is waiting, or NULL */
ib_time_t trx_wait_started;
/*!< trx_struct::wait_started */
ullint trx_weight; /*!< TRX_WEIGHT() */
ulint trx_mysql_thread_id;
/*!< thd_get_thread_id() */
const char* trx_query; /*!< MySQL statement being
executed in the transaction */
struct charset_info_st* trx_query_cs; /*!< charset encode the MySQL
statement */
/*!< pointer to a row
in innodb_locks if trx
is waiting, or NULL */
ib_time_t trx_wait_started; /*!< trx_struct::wait_started */
ullint trx_weight; /*!< TRX_WEIGHT() */
ulint trx_mysql_thread_id; /*!< thd_get_thread_id() */
const char* trx_query; /*!< MySQL statement being
executed in the transaction */
struct charset_info_st* trx_query_cs;
/*!< charset encode the MySQL
statement */
const char* trx_operation_state; /*!< trx_struct::op_info */
ulint trx_tables_in_use;/*!< n_mysql_tables_in_use in
trx_struct */
ulint trx_tables_locked;
/*!< mysql_n_tables_locked in
trx_struct */
ulint trx_lock_structs;/*!< list len of trx_locks in
trx_struct */
ulint trx_lock_memory_bytes;
/*!< mem_heap_get_size(
trx->lock_heap) */
ulint trx_rows_locked;/*!< lock_number_of_rows_locked() */
ullint trx_rows_modified;/*!< trx_struct::undo_no */
ulint trx_concurrency_tickets;
/*!< n_tickets_to_enter_innodb in
trx_struct */
const char* trx_isolation_level;
/*!< isolation_level in trx_struct*/
ibool trx_unique_checks;
/*!< check_unique_secondary in
trx_struct*/
ibool trx_foreign_key_checks;
/*!< check_foreigns in trx_struct */
const char* trx_foreign_key_error;
/*!< detailed_error in trx_struct */
ibool trx_has_search_latch;
/*!< has_search_latch in trx_struct */
ulint trx_search_latch_timeout;
/*!< search_latch_timeout in
trx_struct */
};
/** This structure represents INFORMATION_SCHEMA.innodb_lock_waits row */

View file

@ -1,6 +1,6 @@
/*****************************************************************************
Copyright (c) 1996, 2009, Innobase Oy. All Rights Reserved.
Copyright (c) 1996, 2011, Innobase Oy. 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
@ -68,8 +68,9 @@ Creates the global purge system control structure and inits the history
mutex. */
UNIV_INTERN
void
trx_purge_sys_create(void);
/*======================*/
trx_purge_sys_create(
/*=================*/
ib_bh_t* ib_bh); /*!< in/own: UNDO log min binary heap*/
/********************************************************************//**
Frees the global purge system control structure. */
UNIV_INTERN
@ -112,27 +113,10 @@ This function runs a purge batch.
@return number of undo log pages handled in the batch */
UNIV_INTERN
ulint
trx_purge(void);
/*===========*/
/**********************************************************************
This function runs a purge worker batch */
UNIV_INTERN
void
trx_purge_worker(
/*=============*/
ulint worker_id);
/**********************************************************************
This function waits the event for worker batch */
UNIV_INTERN
void
trx_purge_worker_wait(void);
/*========================*/
/**********************************************************************
This function wakes the waiting worker batch */
UNIV_INTERN
void
trx_purge_worker_wake(void);
/*========================*/
trx_purge(
/*======*/
ulint limit); /*!< in: the maximum number of records to
purge in one batch */
/******************************************************************//**
Prints information of the purge system to stderr. */
UNIV_INTERN
@ -145,25 +129,20 @@ struct trx_purge_struct{
ulint state; /*!< Purge system state */
sess_t* sess; /*!< System session running the purge
query */
trx_t* trx; /*!< System transaction running the purge
trx_t* trx; /*!< System transaction running the
purge
query: this trx is not in the trx list
of the trx system and it never ends */
que_t* query; /*!< The query graph which will do the
parallelized purge operation */
ulint n_worker;
os_event_t worker_event;
sess_t** sess_arr;
trx_t** trx_arr;
que_t** query_arr;
rw_lock_t latch; /*!< The latch protecting the purge view.
A purge operation must acquire an
x-latch here for the instant at which
rw_lock_t latch; /*!< The latch protecting the purge
view. A purge operation must acquire
an x-latch here for the instant at which
it changes the purge view: an undo
log operation can prevent this by
obtaining an s-latch here. */
read_view_t* view; /*!< The purge will not remove undo logs
which are >= this view (purge view) */
mutex_t mutex; /*!< Mutex protecting the fields below */
ulint n_pages_handled;/*!< Approximate number of undo log
pages processed in purge */
ulint handle_limit; /*!< Target of how many pages to get
@ -201,6 +180,11 @@ struct trx_purge_struct{
mem_heap_t* heap; /*!< Temporary storage used during a
purge: can be emptied after purge
completes */
/*-----------------------------*/
ib_bh_t* ib_bh; /*!< Binary min-heap, ordered on
rseg_queue_t::trx_no. It is protected
by the bh_mutex */
mutex_t bh_mutex; /*!< Mutex protecting ib_bh */
};
#define TRX_PURGE_ON 1 /* purge operation is running */

View file

@ -108,7 +108,7 @@ trx_undo_rec_get_pars(
ibool* updated_extern, /*!< out: TRUE if we updated an
externally stored fild */
undo_no_t* undo_no, /*!< out: undo log record number */
dulint* table_id); /*!< out: table id */
table_id_t* table_id); /*!< out: table id */
/*******************************************************************//**
Builds a row reference from an undo log record.
@return pointer to remaining part of undo record */
@ -227,7 +227,7 @@ trx_undo_report_row_operation(
index, otherwise NULL */
roll_ptr_t* roll_ptr); /*!< out: rollback pointer to the
inserted undo log record,
ut_dulint_zero if BTR_NO_UNDO_LOG
0 if BTR_NO_UNDO_LOG
flag was specified */
/******************************************************************//**
Copies an undo record to heap. This function can be called if we know that

View file

@ -78,7 +78,7 @@ trx_undo_rec_get_undo_no(
ptr = undo_rec + 3;
return(mach_dulint_read_much_compressed(ptr));
return(mach_ull_read_much_compressed(ptr));
}
/**********************************************************************//**
@ -90,7 +90,7 @@ trx_undo_rec_get_offset(
/*====================*/
undo_no_t undo_no) /*!< in: undo no read from node */
{
return (3 + mach_dulint_get_much_compressed_size(undo_no));
return (3 + mach_ull_get_much_compressed_size(undo_no));
}
/***********************************************************************//**

View file

@ -1,6 +1,6 @@
/*****************************************************************************
Copyright (c) 1996, 2010, Innobase Oy. All Rights Reserved.
Copyright (c) 1996, 2011, Innobase Oy. 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
@ -103,7 +103,7 @@ trx_rseg_header_create(
ulint zip_size, /*!< in: compressed page size in bytes
or 0 for uncompressed pages */
ulint max_size, /*!< in: max size in pages */
ulint* slot_no, /*!< out: rseg id == slot number in trx sys */
ulint rseg_slot_no, /*!< in: rseg id == slot number in trx sys */
mtr_t* mtr); /*!< in: mtr */
/*********************************************************************//**
Creates the memory copies for rollback segments and initializes the
@ -113,18 +113,9 @@ void
trx_rseg_list_and_array_init(
/*=========================*/
trx_sysf_t* sys_header, /*!< in: trx system header */
ib_bh_t* ib_bh, /*!< in: rseg queue */
mtr_t* mtr); /*!< in: mtr */
/****************************************************************//**
Creates a new rollback segment to the database.
@return the created segment object, NULL if fail */
UNIV_INTERN
trx_rseg_t*
trx_rseg_create(
/*============*/
ulint space, /*!< in: space id */
ulint max_size, /*!< in: max size in pages */
ulint* id, /*!< out: rseg id */
mtr_t* mtr); /*!< in: mtr */
/***************************************************************************
Free's an instance of the rollback segment in memory. */
UNIV_INTERN
@ -133,12 +124,15 @@ trx_rseg_mem_free(
/*==============*/
trx_rseg_t* rseg); /* in, own: instance to free */
/* Real max value may be 4076 in usual. But reserve 4 slot for safety or etc... */
#define TRX_RSEG_N_EXTRA_SLOTS (((UNIV_PAGE_SIZE - (FIL_PAGE_DATA + FIL_PAGE_DATA_END + TRX_RSEG_UNDO_SLOTS)) / TRX_RSEG_SLOT_SIZE) - 4)
/*********************************************************************
Creates a rollback segment. */
UNIV_INTERN
trx_rseg_t*
trx_rseg_create(void);
/*==================*/
/* Number of undo log slots in a rollback segment file copy */
#define TRX_RSEG_N_SLOTS (srv_extra_undoslots ? TRX_RSEG_N_EXTRA_SLOTS : (UNIV_PAGE_SIZE / 16))
#define TRX_RSEG_N_SLOTS (UNIV_PAGE_SIZE / 16)
/* Maximum number of transactions supported by a single rollback segment */
#define TRX_RSEG_MAX_N_TRXS (TRX_RSEG_N_SLOTS / 2)
@ -188,6 +182,14 @@ struct trx_rseg_struct{
memory objects */
};
/** For prioritising the rollback segments for purge. */
struct rseg_queue_struct {
trx_id_t trx_no; /*!< trx_rseg_t::last_trx_no */
trx_rseg_t* rseg; /*!< Rollback segment */
};
typedef struct rseg_queue_struct rseg_queue_t;
/* Undo log segment slot in a rollback segment header */
/*-------------------------------------------------------------*/
#define TRX_RSEG_SLOT_PAGE_NO 0 /* Page number of the header page of

View file

@ -1,6 +1,6 @@
/*****************************************************************************
Copyright (c) 1996, 2009, Innobase Oy. All Rights Reserved.
Copyright (c) 1996, 2011, Innobase Oy. 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
@ -38,6 +38,7 @@ Created 3/26/1996 Heikki Tuuri
#include "mem0mem.h"
#include "sync0sync.h"
#include "ut0lst.h"
#include "ut0bh.h"
#include "read0types.h"
#include "page0types.h"
@ -160,13 +161,6 @@ void
trx_sys_dummy_create(
/*=================*/
ulint space);
/*********************************************************************
Create extra rollback segments when create_new_db */
UNIV_INTERN
void
trx_sys_create_extra_rseg(
/*======================*/
ulint num); /* in: number of extra user rollback segments */
/****************************************************************//**
Looks for a free slot for a rollback segment in the trx system file copy.
@return slot index or ULINT_UNDEFINED if not found */
@ -254,13 +248,6 @@ UNIV_INLINE
trx_id_t
trx_sys_get_new_trx_id(void);
/*========================*/
/*****************************************************************//**
Allocates a new transaction number.
@return new, allocated trx number */
UNIV_INLINE
trx_id_t
trx_sys_get_new_trx_no(void);
/*========================*/
#endif /* !UNIV_HOTBACKUP */
/*****************************************************************//**
Writes a trx id to an index page. In case that the id size changes in
@ -465,6 +452,14 @@ trx_sys_file_format_id_to_name(
const ulint id); /*!< in: id of the file format */
#endif /* !UNIV_HOTBACKUP */
/*********************************************************************
Creates the rollback segments */
UNIV_INTERN
void
trx_sys_create_rsegs(
/*=================*/
ulint n_rsegs); /*!< number of rollback segments to create */
/* The automatically created system rollback segment has this id */
#define TRX_SYS_SYSTEM_RSEG_ID 0
@ -501,11 +496,16 @@ trx_sys_file_format_id_to_name(
slots */
/*------------------------------------------------------------- @} */
/** Maximum number of rollback segments: the number of segment
specification slots in the transaction system array; rollback segment
id must fit in one byte, therefore 256; each slot is currently 8 bytes
in size */
#define TRX_SYS_N_RSEGS 256
/* Max number of rollback segments: the number of segment specification slots
in the transaction system array; rollback segment id must fit in one (signed)
byte, therefore 128; each slot is currently 8 bytes in size. If you want
to raise the level to 256 then you will need to fix some assertions that
impose the 7 bit restriction. e.g., mach_write_to_3() */
#define TRX_SYS_N_RSEGS 128
/* Originally, InnoDB defined TRX_SYS_N_RSEGS as 256 but created only one
rollback segment. It initialized some arrays with this number of entries.
We must remember this limit in order to keep file compatibility. */
#define TRX_SYS_OLD_N_RSEGS 256
/** Maximum length of MySQL binlog file name, in bytes.
@see trx_sys_mysql_master_log_name
@ -593,11 +593,16 @@ FIL_PAGE_ARCH_LOG_NO_OR_SPACE_NO. */
(TRX_SYS_PAGE_NO of TRX_SYS_SPACE) */
#define TRX_SYS_FILE_FORMAT_TAG (UNIV_PAGE_SIZE - 16)
/** Contents of TRX_SYS_FILE_FORMAT_TAG when valid. The file format
/** Contents of TRX_SYS_FILE_FORMAT_TAG when valid. The file format
identifier is added to this constant. */
#define TRX_SYS_FILE_FORMAT_TAG_MAGIC_N_LOW 3645922177UL
/** Contents of TRX_SYS_FILE_FORMAT_TAG+4 when valid */
#define TRX_SYS_FILE_FORMAT_TAG_MAGIC_N_HIGH 2745987765UL
/** Contents of TRX_SYS_FILE_FORMAT_TAG when valid. The file format
identifier is added to this 64-bit constant. */
#define TRX_SYS_FILE_FORMAT_TAG_MAGIC_N \
((ib_uint64_t) TRX_SYS_FILE_FORMAT_TAG_MAGIC_N_HIGH << 32 \
| TRX_SYS_FILE_FORMAT_TAG_MAGIC_N_LOW)
/* @} */
/** Doublewrite control struct */

View file

@ -300,7 +300,7 @@ trx_get_on_id(
trx = UT_LIST_GET_FIRST(trx_sys->trx_list);
while (trx != NULL) {
if (0 == ut_dulint_cmp(trx_id, trx->id)) {
if (trx_id == trx->id) {
return(trx);
}
@ -349,12 +349,12 @@ trx_is_active(
ut_ad(mutex_own(&(kernel_mutex)));
if (ut_dulint_cmp(trx_id, trx_list_get_min_trx_id()) < 0) {
if (trx_id < trx_list_get_min_trx_id()) {
return(FALSE);
}
if (ut_dulint_cmp(trx_id, trx_sys->max_trx_id) >= 0) {
if (UNIV_UNLIKELY(trx_id >= trx_sys->max_trx_id)) {
/* There must be corruption: we return TRUE because this
function is only called by lock_clust_rec_some_has_impl()
@ -393,29 +393,14 @@ trx_sys_get_new_trx_id(void)
Thus trx id values will not overlap when the database is
repeatedly started! */
if (ut_dulint_get_low(trx_sys->max_trx_id)
% TRX_SYS_TRX_ID_WRITE_MARGIN == 0) {
if ((ulint) trx_sys->max_trx_id % TRX_SYS_TRX_ID_WRITE_MARGIN == 0) {
trx_sys_flush_max_trx_id();
}
id = trx_sys->max_trx_id;
UT_DULINT_INC(trx_sys->max_trx_id);
id = trx_sys->max_trx_id++;
return(id);
}
/*****************************************************************//**
Allocates a new transaction number.
@return new, allocated trx number */
UNIV_INLINE
trx_id_t
trx_sys_get_new_trx_no(void)
/*========================*/
{
ut_ad(mutex_own(&kernel_mutex));
return(trx_sys_get_new_trx_id());
}
#endif /* !UNIV_HOTBACKUP */

View file

@ -44,6 +44,9 @@ extern sess_t* trx_dummy_sess;
/** Number of transactions currently allocated for MySQL: protected by
the kernel mutex */
extern ulint trx_n_mysql_transactions;
/** Number of transactions currently in the XA PREPARED state: protected by
the kernel mutex */
extern ulint trx_n_prepared;
/********************************************************************//**
Releases the search latch if trx has reserved it. */
@ -108,6 +111,14 @@ trx_free(
/*=====*/
trx_t* trx); /*!< in, own: trx object */
/********************************************************************//**
At shutdown, frees a transaction object that is in the PREPARED state. */
UNIV_INTERN
void
trx_free_prepared(
/*==============*/
trx_t* trx) /*!< in, own: trx object */
UNIV_COLD __attribute__((nonnull));
/********************************************************************//**
Frees a transaction object for MySQL. */
UNIV_INTERN
void
@ -408,30 +419,20 @@ Calculates the "weight" of a transaction. The weight of one transaction
is estimated as the number of altered rows + the number of locked rows.
@param t transaction
@return transaction weight */
#define TRX_WEIGHT(t) \
ut_dulint_add((t)->undo_no, UT_LIST_GET_LEN((t)->trx_locks))
#define TRX_WEIGHT(t) ((t)->undo_no + UT_LIST_GET_LEN((t)->trx_locks))
/*******************************************************************//**
Compares the "weight" (or size) of two transactions. Transactions that
have edited non-transactional tables are considered heavier than ones
that have not.
@return <0, 0 or >0; similar to strcmp(3) */
@return TRUE if weight(a) >= weight(b) */
UNIV_INTERN
int
trx_weight_cmp(
/*===========*/
ibool
trx_weight_ge(
/*==========*/
const trx_t* a, /*!< in: the first transaction to be compared */
const trx_t* b); /*!< in: the second transaction to be compared */
/*******************************************************************//**
Retrieves transacion's id, represented as unsigned long long.
@return transaction's id */
UNIV_INLINE
ullint
trx_get_id(
/*=======*/
const trx_t* trx); /*!< in: transaction */
/* Maximum length of a string that can be returned by
trx_get_que_state_str(). */
#define TRX_QUE_STATE_STR_MAX_LEN 12 /* "ROLLING BACK" */
@ -480,6 +481,20 @@ struct trx_struct{
of view of concurrency control:
TRX_ACTIVE, TRX_COMMITTED_IN_MEMORY,
... */
/*------------------------------*/
/* MySQL has a transaction coordinator to coordinate two phase
commit between multiple storage engines and the binary log. When
an engine participates in a transaction, it's responsible for
registering itself using the trans_register_ha() API. */
unsigned is_registered:1;/* This flag is set to 1 after the
transaction has been registered with
the coordinator using the XA API, and
is set to 0 after commit or rollback. */
unsigned owns_prepare_mutex:1;/* 1 if owns prepare mutex, if
this is set to 1 then registered should
also be set to 1. This is used in the
XA code */
/*------------------------------*/
ulint isolation_level;/* TRX_ISO_REPEATABLE_READ, ... */
ulint check_foreigns; /* normally TRUE, but if the user
wants to suppress foreign key checks,
@ -497,7 +512,6 @@ struct trx_struct{
FALSE, one can save CPU time and about
150 bytes in the undo log size as then
we skip XA steps */
ulint flush_log_at_trx_commit_session;
ulint flush_log_later;/* In 2PC, we hold the
prepare_commit mutex across
both phases. In that case, we
@ -511,9 +525,6 @@ struct trx_struct{
in that case we must flush the log
in trx_commit_complete_for_mysql() */
ulint duplicates; /*!< TRX_DUP_IGNORE | TRX_DUP_REPLACE */
ulint active_trans; /*!< 1 - if a transaction in MySQL
is active. 2 - if prepare_commit_mutex
was taken */
ulint has_search_latch;
/* TRUE if this trx has latched the
search system latch in S-mode */
@ -556,8 +567,8 @@ struct trx_struct{
max trx id when the transaction is
moved to COMMITTED_IN_MEMORY state */
ib_uint64_t commit_lsn; /*!< lsn at the time of the commit */
trx_id_t table_id; /*!< Table to drop iff dict_operation
is TRUE, or ut_dulint_zero. */
table_id_t table_id; /*!< Table to drop iff dict_operation
is TRUE, or 0. */
/*------------------------------*/
void* mysql_thd; /*!< MySQL thread handle corresponding
to this trx, or NULL */
@ -583,12 +594,6 @@ struct trx_struct{
replication has processed */
const char* mysql_relay_log_file_name;
ib_int64_t mysql_relay_log_pos;
os_thread_id_t mysql_thread_id;/* id of the MySQL thread associated
with this transaction object */
ulint mysql_process_no;/* since in Linux, 'top' reports
process id's and not thread id's, we
store the process number too */
/*------------------------------*/
ulint n_mysql_tables_in_use; /* number of Innobase tables
used in the processing of the current

View file

@ -68,18 +68,6 @@ trx_get_error_info(
return(trx->error_info);
}
/*******************************************************************//**
Retrieves transacion's id, represented as unsigned long long.
@return transaction's id */
UNIV_INLINE
ullint
trx_get_id(
/*=======*/
const trx_t* trx) /*!< in: transaction */
{
return((ullint)ut_conv_dulint_to_longlong(trx->id));
}
/*******************************************************************//**
Retrieves transaction's que state in a human readable string. The string
should not be free()'d or modified.

View file

@ -28,10 +28,7 @@ Created 3/26/1996 Heikki Tuuri
#include "ut0byte.h"
/** prepare trx_t::id for being printed via printf(3) */
#define TRX_ID_PREP_PRINTF(id) (ullint) ut_conv_dulint_to_longlong(id)
/** printf(3) format used for printing TRX_ID_PRINTF_PREP() */
/** printf(3) format used for printing DB_TRX_ID and other system fields */
#define TRX_ID_FMT "%llX"
/** maximum length that a formatted trx_t::id could take, not including
@ -81,12 +78,14 @@ enum trx_rb_ctx {
in crash recovery */
};
/** Row identifier (DB_ROW_ID, DATA_ROW_ID) */
typedef ib_id_t row_id_t;
/** Transaction identifier (DB_TRX_ID, DATA_TRX_ID) */
typedef dulint trx_id_t;
typedef ib_id_t trx_id_t;
/** Rollback pointer (DB_ROLL_PTR, DATA_ROLL_PTR) */
typedef dulint roll_ptr_t;
typedef ib_id_t roll_ptr_t;
/** Undo number */
typedef dulint undo_no_t;
typedef ib_id_t undo_no_t;
/** Transaction savepoint */
typedef struct trx_savept_struct trx_savept_t;

View file

@ -262,8 +262,6 @@ UNIV_INTERN
page_t*
trx_undo_set_state_at_finish(
/*=========================*/
trx_rseg_t* rseg, /*!< in: rollback segment memory object */
trx_t* trx, /*!< in: transaction */
trx_undo_t* undo, /*!< in: undo log memory copy */
mtr_t* mtr); /*!< in: mtr */
/******************************************************************//**
@ -298,6 +296,15 @@ void
trx_undo_insert_cleanup(
/*====================*/
trx_t* trx); /*!< in: transaction handle */
/********************************************************************//**
At shutdown, frees the undo logs of a PREPARED transaction. */
UNIV_INTERN
void
trx_undo_free_prepared(
/*===================*/
trx_t* trx) /*!< in/out: PREPARED transaction */
UNIV_COLD __attribute__((nonnull));
#endif /* !UNIV_HOTBACKUP */
/***********************************************************//**
Parses the redo log entry of an undo log page initialization.
@ -383,7 +390,7 @@ struct trx_undo_struct{
XID xid; /*!< X/Open XA transaction
identification */
ibool dict_operation; /*!< TRUE if a dict operation trx */
dulint table_id; /*!< if a dict operation, then the table
table_id_t table_id; /*!< if a dict operation, then the table
id */
trx_rseg_t* rseg; /*!< rseg where the undo log belongs */
/*-----------------------------*/

View file

@ -39,16 +39,19 @@ trx_undo_build_roll_ptr(
ulint page_no, /*!< in: page number */
ulint offset) /*!< in: offset of the undo entry within page */
{
roll_ptr_t roll_ptr;
#if DATA_ROLL_PTR_LEN != 7
# error "DATA_ROLL_PTR_LEN != 7"
#endif
ut_ad(rseg_id < 128);
ut_ad(is_insert == 0 || is_insert == 1);
ut_ad(rseg_id < TRX_SYS_N_RSEGS);
ut_ad(offset < 65536);
return(ut_dulint_create(is_insert * 128 * 256 * 256
+ rseg_id * 256 * 256
+ (page_no / 256) / 256,
(page_no % (256 * 256)) * 256 * 256
+ offset));
roll_ptr = (roll_ptr_t) is_insert << 55
| (roll_ptr_t) rseg_id << 48
| (roll_ptr_t) page_no << 16
| offset;
return(roll_ptr);
}
/***********************************************************************//**
@ -64,24 +67,20 @@ trx_undo_decode_roll_ptr(
ulint* offset) /*!< out: offset of the undo
entry within page */
{
ulint low;
ulint high;
#if DATA_ROLL_PTR_LEN != 7
# error "DATA_ROLL_PTR_LEN != 7"
#endif
#if TRUE != 1
# error "TRUE != 1"
#endif
high = ut_dulint_get_high(roll_ptr);
low = ut_dulint_get_low(roll_ptr);
*offset = low % (256 * 256);
*is_insert = high / (256 * 256 * 128); /* TRUE == 1 */
*rseg_id = (high / (256 * 256)) % 128;
*page_no = (high % (256 * 256)) * 256 * 256
+ (low / 256) / 256;
ut_ad(roll_ptr < (1ULL << 56));
*offset = (ulint) roll_ptr & 0xFFFF;
roll_ptr >>= 16;
*page_no = (ulint) roll_ptr & 0xFFFFFFFF;
roll_ptr >>= 32;
*rseg_id = (ulint) roll_ptr & 0x7F;
roll_ptr >>= 7;
*is_insert = (ibool) roll_ptr; /* TRUE==1 */
}
/***********************************************************************//**
@ -93,16 +92,14 @@ trx_undo_roll_ptr_is_insert(
/*========================*/
roll_ptr_t roll_ptr) /*!< in: roll pointer */
{
ulint high;
#if DATA_ROLL_PTR_LEN != 7
# error "DATA_ROLL_PTR_LEN != 7"
#endif
#if TRUE != 1
# error "TRUE != 1"
#endif
high = ut_dulint_get_high(roll_ptr);
return(high / (256 * 256 * 128));
ut_ad(roll_ptr < (1ULL << 56));
return((ibool) (roll_ptr >> 55));
}
#endif /* !UNIV_HOTBACKUP */

View file

@ -44,12 +44,17 @@ Created 1/20/1994 Heikki Tuuri
#include "hb_univ.i"
#endif /* UNIV_HOTBACKUP */
/* aux macros to convert M into "123" (string) if M is defined like
#define M 123 */
#define _IB_TO_STR(s) #s
#define IB_TO_STR(s) _IB_TO_STR(s)
#define INNODB_VERSION_MAJOR 1
#define INNODB_VERSION_MINOR 0
#define INNODB_VERSION_BUGFIX 15
#define INNODB_VERSION_MINOR 1
#define INNODB_VERSION_BUGFIX 7
#ifndef PERCONA_INNODB_VERSION
#define PERCONA_INNODB_VERSION 12.5
#define PERCONA_INNODB_VERSION 20.1
#endif
@ -62,18 +67,15 @@ component, i.e. we show M.N.P as M.N */
#define INNODB_VERSION_SHORT \
(INNODB_VERSION_MAJOR << 8 | INNODB_VERSION_MINOR)
/* auxiliary macros to help creating the version as string */
#define __INNODB_VERSION(a, b, c, d) (#a "." #b "." #c "-" #d)
#define _INNODB_VERSION(a, b, c, d) __INNODB_VERSION(a, b, c, d)
#define INNODB_VERSION_STR \
_INNODB_VERSION(INNODB_VERSION_MAJOR, \
INNODB_VERSION_MINOR, \
INNODB_VERSION_BUGFIX, \
PERCONA_INNODB_VERSION)
IB_TO_STR(INNODB_VERSION_MAJOR) "." \
IB_TO_STR(INNODB_VERSION_MINOR) "." \
IB_TO_STR(INNODB_VERSION_BUGFIX) "-" \
IB_TO_STR(PERCONA_INNODB_VERSION)
#define REFMAN "http://dev.mysql.com/doc/refman/5.1/en/"
#define REFMAN "http://dev.mysql.com/doc/refman/" \
IB_TO_STR(MYSQL_MAJOR_VERSION) "." \
IB_TO_STR(MYSQL_MINOR_VERSION) "/en/"
#ifdef MYSQL_DYNAMIC_PLUGIN
/* In the dynamic plugin, redefine some externally visible symbols
@ -85,19 +87,6 @@ the virtual method table (vtable) in GCC 3. */
# define ha_innobase ha_innodb
#endif /* MYSQL_DYNAMIC_PLUGIN */
/* if any of the following macros is defined at this point this means
that the code from the "right" plug.in was executed and we do not
need to include ut0auxconf.h which would either define the same macros
or will be empty */
#if !defined(HAVE_IB_GCC_ATOMIC_BUILTINS) \
&& !defined(HAVE_IB_ATOMIC_PTHREAD_T_GCC) \
&& !defined(HAVE_IB_SOLARIS_ATOMICS) \
&& !defined(HAVE_IB_ATOMIC_PTHREAD_T_SOLARIS) \
&& !defined(SIZEOF_PTHREAD_T) \
&& !defined(HAVE_IB_PAUSE_INSTRUCTION)
# include "ut0auxconf.h"
#endif
#if (defined(WIN32) || defined(_WIN32) || defined(WIN64) || defined(_WIN64)) && !defined(MYSQL_SERVER) && !defined(__WIN__)
# undef __WIN__
# define __WIN__
@ -122,7 +111,7 @@ if we are compiling on Windows. */
/* Include <sys/stat.h> to get S_I... macros defined for os0file.c */
# include <sys/stat.h>
# if !defined(__NETWARE__) && !defined(__WIN__)
# if !defined(__WIN__)
# include <sys/mman.h> /* mmap() for os0proc.c */
# endif
@ -151,6 +140,23 @@ Sun Studio */
#endif /* #if (defined(WIN32) || ... */
/* Following defines are to enable performance schema
instrumentation in each of four InnoDB modules if
HAVE_PSI_INTERFACE is defined. */
#ifdef HAVE_PSI_INTERFACE
# define UNIV_PFS_MUTEX
# define UNIV_PFS_RWLOCK
/* For I/O instrumentation, performance schema rely
on a native descriptor to identify the file, this
descriptor could conflict with our OS level descriptor.
Disable IO instrumentation on Windows until this is
resolved */
# ifndef __WIN__
# define UNIV_PFS_IO
# endif
# define UNIV_PFS_THREAD
#endif /* HAVE_PSI_INTERFACE */
/* DEBUG VERSION CONTROL
===================== */
@ -201,6 +207,8 @@ this will break redo log file compatibility, but it may be useful when
debugging redo log application problems. */
#define UNIV_MEM_DEBUG /* detect memory leaks etc */
#define UNIV_IBUF_DEBUG /* debug the insert buffer */
#define UNIV_BLOB_DEBUG /* track BLOB ownership;
assumes that no BLOBs survive server restart */
#define UNIV_IBUF_COUNT_DEBUG /* debug the insert buffer;
this limits the database to IBUF_COUNT_N_SPACES and IBUF_COUNT_N_PAGES,
and the insert buffer must be empty when the database is started */
@ -219,6 +227,9 @@ operations (very slow); also UNIV_DEBUG must be defined */
for compressed pages */
#define UNIV_ZIP_COPY /* call page_zip_copy_recs()
more often */
#define UNIV_AIO_DEBUG /* prints info about
submitted and reaped AIO
requests to the log. */
#endif
#define UNIV_BTR_DEBUG /* check B-tree links */
@ -242,14 +253,29 @@ by one. */
option off; also some ibuf tests are suppressed */
/* Linkage specifier for non-static InnoDB symbols (variables and functions)
that are only referenced from within InnoDB, not from MySQL */
#if defined(__GNUC__) && (__GNUC__ >= 4) || defined(__INTEL_COMPILER)
that are only referenced from within InnoDB, not from MySQL. We disable the
GCC visibility directive on all Sun operating systems because there is no
easy way to get it to work. See http://bugs.mysql.com/bug.php?id=52263. */
#if defined(__GNUC__) && (__GNUC__ >= 4) && !defined(sun) || defined(__INTEL_COMPILER)
# define UNIV_INTERN __attribute__((visibility ("hidden")))
#else
# define UNIV_INTERN
#endif
#if defined __GNUC__ && (__GNUC__ > 4 || __GNUC__ == 4 && __GNUC_MINOR__ >= 3)
/** Starting with GCC 4.3, the "cold" attribute is used to inform the
compiler that a function is unlikely executed. The function is
optimized for size rather than speed and on many targets it is placed
into special subsection of the text section so all cold functions
appears close together improving code locality of non-cold parts of
program. The paths leading to call of cold functions within code are
marked as unlikely by the branch prediction mechanism. optimize a
rarely invoked function for size instead for speed. */
# define UNIV_COLD __attribute__((cold))
#else
# define UNIV_COLD /* empty */
#endif
#if (!defined(UNIV_DEBUG) && !defined(UNIV_MUST_NOT_INLINE))
#ifndef UNIV_MUST_NOT_INLINE
/* Definition for inline version */
#ifdef __WIN__
@ -375,8 +401,10 @@ typedef unsigned long long int ullint;
/* The 'undefined' value for a ulint */
#define ULINT_UNDEFINED ((ulint)(-1))
/** The bitmask of 32-bit unsigned integer */
#define ULINT32_MASK 0xFFFFFFFF
/* The undefined 32-bit unsigned integer */
#define ULINT32_UNDEFINED 0xFFFFFFFF
#define ULINT32_UNDEFINED ULINT32_MASK
/* Maximum value for a ulint */
#define ULINT_MAX ((ulint)(-2))
@ -384,7 +412,10 @@ typedef unsigned long long int ullint;
/* Maximum value for ib_uint64_t */
#define IB_ULONGLONG_MAX ((ib_uint64_t) (~0ULL))
/* THe 'undefined' value for ullint */
/** The generic InnoDB system object identifier data type */
typedef ib_uint64_t ib_id_t;
/* The 'undefined' value for a ullint */
#define ULLINT_UNDEFINED ((ullint)(-1))
/* This 'ibool' type is used within Innobase. Remember that different included

View file

@ -1,14 +0,0 @@
/* Do not remove this file even though it is empty.
This file is included in univ.i and will cause compilation failure
if not present.
A custom checks have been added in the generated
storage/innobase/Makefile.in that is shipped with the InnoDB Plugin
source archive. These checks eventually define some macros and put
them in this file.
This is a hack that has been developed in order to deploy new compile
time checks without the need to regenerate the ./configure script that is
distributed in the MySQL 5.1 official source archives.
If by any chance Makefile.in and ./configure are regenerated and thus
the hack from Makefile.in wiped away then the "real" checks from plug.in
will take over.
*/

152
include/ut0bh.h Normal file
View file

@ -0,0 +1,152 @@
/***************************************************************************//**
Copyright (c) 2011, Oracle Corpn. 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., 59 Temple
Place, Suite 330, Boston, MA 02111-1307 USA
*****************************************************************************/
/******************************************************************//**
@file include/ut0bh.h
Binary min-heap interface.
Created 2010-05-28 by Sunny Bains
*******************************************************/
#ifndef INNOBASE_UT0BH_H
#define INNOBASE_UT0BH_H
#include "univ.i"
/** Comparison function for objects in the binary heap. */
typedef int (*ib_bh_cmp_t)(const void* p1, const void* p2);
typedef struct ib_bh_struct ib_bh_t;
/**********************************************************************//**
Get the number of elements in the binary heap.
@return number of elements */
UNIV_INLINE
ulint
ib_bh_size(
/*=======*/
const ib_bh_t* ib_bh); /*!< in: instance */
/**********************************************************************//**
Test if binary heap is empty.
@return TRUE if empty. */
UNIV_INLINE
ibool
ib_bh_is_empty(
/*===========*/
const ib_bh_t* ib_bh); /*!< in: instance */
/**********************************************************************//**
Test if binary heap is full.
@return TRUE if full. */
UNIV_INLINE
ibool
ib_bh_is_full(
/*===========*/
const ib_bh_t* ib_bh); /*!< in: instance */
/**********************************************************************//**
Get a pointer to the element.
@return pointer to element */
UNIV_INLINE
void*
ib_bh_get(
/*=======*/
ib_bh_t* ib_bh, /*!< in: instance */
ulint i); /*!< in: index */
/**********************************************************************//**
Copy an element to the binary heap.
@return pointer to copied element */
UNIV_INLINE
void*
ib_bh_set(
/*======*/
ib_bh_t* ib_bh, /*!< in/out: instance */
ulint i, /*!< in: index */
const void* elem); /*!< in: element to add */
/**********************************************************************//**
Return the first element from the binary heap.
@return pointer to first element or NULL if empty. */
UNIV_INLINE
void*
ib_bh_first(
/*========*/
ib_bh_t* ib_bh); /*!< in: instance */
/**********************************************************************//**
Return the last element from the binary heap.
@return pointer to last element or NULL if empty. */
UNIV_INLINE
void*
ib_bh_last(
/*========*/
ib_bh_t* ib_bh); /*!< in/out: instance */
/**********************************************************************//**
Create a binary heap.
@return a new binary heap */
UNIV_INTERN
ib_bh_t*
ib_bh_create(
/*=========*/
ib_bh_cmp_t compare, /*!< in: comparator */
ulint sizeof_elem, /*!< in: size of one element */
ulint max_elems); /*!< in: max elements allowed */
/**********************************************************************//**
Free a binary heap.
@return a new binary heap */
UNIV_INTERN
void
ib_bh_free(
/*=======*/
ib_bh_t* ib_bh); /*!< in,own: instance */
/**********************************************************************//**
Add an element to the binary heap. Note: The element is copied.
@return pointer to added element or NULL if full. */
UNIV_INTERN
void*
ib_bh_push(
/*=======*/
ib_bh_t* ib_bh, /*!< in/out: instance */
const void* elem); /*!< in: element to add */
/**********************************************************************//**
Remove the first element from the binary heap. */
UNIV_INTERN
void
ib_bh_pop(
/*======*/
ib_bh_t* ib_bh); /*!< in/out: instance */
/** Binary heap data structure */
struct ib_bh_struct {
ulint max_elems; /*!< max elements allowed */
ulint n_elems; /*!< current size */
ulint sizeof_elem; /*!< sizeof element */
ib_bh_cmp_t compare; /*!< comparator */
};
#ifndef UNIV_NONINL
#include "ut0bh.ic"
#endif
#endif /* INNOBASE_UT0BH_H */

125
include/ut0bh.ic Normal file
View file

@ -0,0 +1,125 @@
/***************************************************************************//**
Copyright (c) 2011, Oracle Corpn. 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., 59 Temple
Place, Suite 330, Boston, MA 02111-1307 USA
*****************************************************************************/
/******************************************************************//**
@file include/ut0bh.ic
Binary min-heap implementation.
Created 2011-01-15 by Sunny Bains
*******************************************************/
#include "ut0bh.h"
#include "ut0mem.h" /* For ut_memcpy() */
/**********************************************************************//**
Get the number of elements in the binary heap.
@return number of elements */
UNIV_INLINE
ulint
ib_bh_size(
/*=======*/
const ib_bh_t* ib_bh) /*!< in: instance */
{
return(ib_bh->n_elems);
}
/**********************************************************************//**
Test if binary heap is empty.
@return TRUE if empty. */
UNIV_INLINE
ibool
ib_bh_is_empty(
/*===========*/
const ib_bh_t* ib_bh) /*!< in: instance */
{
return(ib_bh_size(ib_bh) == 0);
}
/**********************************************************************//**
Test if binary heap is full.
@return TRUE if full. */
UNIV_INLINE
ibool
ib_bh_is_full(
/*===========*/
const ib_bh_t* ib_bh) /*!< in: instance */
{
return(ib_bh_size(ib_bh) >= ib_bh->max_elems);
}
/**********************************************************************//**
Get a pointer to the element.
@return pointer to element */
UNIV_INLINE
void*
ib_bh_get(
/*=======*/
ib_bh_t* ib_bh, /*!< in: instance */
ulint i) /*!< in: index */
{
byte* ptr = (byte*) (ib_bh + 1);
ut_a(i < ib_bh_size(ib_bh));
return(ptr + (ib_bh->sizeof_elem * i));
}
/**********************************************************************//**
Copy an element to the binary heap.
@return pointer to copied element */
UNIV_INLINE
void*
ib_bh_set(
/*======*/
ib_bh_t* ib_bh, /*!< in/out: instance */
ulint i, /*!< in: index */
const void* elem) /*!< in: element to add */
{
void* ptr = ib_bh_get(ib_bh, i);
ut_memcpy(ptr, elem, ib_bh->sizeof_elem);
return(ptr);
}
/**********************************************************************//**
Return the first element from the binary heap.
@return pointer to first element or NULL if empty. */
UNIV_INLINE
void*
ib_bh_first(
/*========*/
ib_bh_t* ib_bh) /*!< in: instance */
{
return(ib_bh_is_empty(ib_bh) ? NULL : ib_bh_get(ib_bh, 0));
}
/**********************************************************************//**
Return the last element from the binary heap.
@return pointer to last element or NULL if empty. */
UNIV_INLINE
void*
ib_bh_last(
/*========*/
ib_bh_t* ib_bh) /*!< in/out: instance */
{
return(ib_bh_is_empty(ib_bh)
? NULL
: ib_bh_get(ib_bh, ib_bh_size(ib_bh) - 1));
}

View file

@ -27,145 +27,22 @@ Created 1/20/1994 Heikki Tuuri
#define ut0byte_h
#include "univ.i"
/** Pair of ulint integers. */
typedef struct dulint_struct dulint;
/** Type definition for a 64-bit unsigned integer, which works also
in 32-bit machines. NOTE! Access the fields only with the accessor
functions. This definition appears here only for the compiler to
know the size of a dulint. */
struct dulint_struct{
ulint high; /*!< most significant 32 bits */
ulint low; /*!< least significant 32 bits */
};
/** Zero value for a dulint */
extern const dulint ut_dulint_zero;
/** Maximum value for a dulint */
extern const dulint ut_dulint_max;
/*******************************************************//**
Creates a 64-bit dulint out of two ulints.
Creates a 64-bit integer out of two 32-bit integers.
@return created dulint */
UNIV_INLINE
dulint
ut_dulint_create(
/*=============*/
ib_uint64_t
ut_ull_create(
/*==========*/
ulint high, /*!< in: high-order 32 bits */
ulint low); /*!< in: low-order 32 bits */
/*******************************************************//**
Gets the high-order 32 bits of a dulint.
@return 32 bits in ulint */
UNIV_INLINE
ulint
ut_dulint_get_high(
/*===============*/
dulint d); /*!< in: dulint */
/*******************************************************//**
Gets the low-order 32 bits of a dulint.
@return 32 bits in ulint */
UNIV_INLINE
ulint
ut_dulint_get_low(
/*==============*/
dulint d); /*!< in: dulint */
/*******************************************************//**
Converts a dulint (a struct of 2 ulints) to ib_int64_t, which is a 64-bit
integer type.
@return value in ib_int64_t type */
UNIV_INLINE
ib_int64_t
ut_conv_dulint_to_longlong(
/*=======================*/
dulint d); /*!< in: dulint */
/*******************************************************//**
Tests if a dulint is zero.
@return TRUE if zero */
UNIV_INLINE
ibool
ut_dulint_is_zero(
/*==============*/
dulint a); /*!< in: dulint */
/*******************************************************//**
Compares two dulints.
@return -1 if a < b, 0 if a == b, 1 if a > b */
UNIV_INLINE
int
ut_dulint_cmp(
/*==========*/
dulint a, /*!< in: dulint */
dulint b); /*!< in: dulint */
/*******************************************************//**
Calculates the max of two dulints.
@return max(a, b) */
UNIV_INLINE
dulint
ut_dulint_get_max(
/*==============*/
dulint a, /*!< in: dulint */
dulint b); /*!< in: dulint */
/*******************************************************//**
Calculates the min of two dulints.
@return min(a, b) */
UNIV_INLINE
dulint
ut_dulint_get_min(
/*==============*/
dulint a, /*!< in: dulint */
dulint b); /*!< in: dulint */
/*******************************************************//**
Adds a ulint to a dulint.
@return sum a + b */
UNIV_INLINE
dulint
ut_dulint_add(
/*==========*/
dulint a, /*!< in: dulint */
ulint b); /*!< in: ulint */
/*******************************************************//**
Subtracts a ulint from a dulint.
@return a - b */
UNIV_INLINE
dulint
ut_dulint_subtract(
/*===============*/
dulint a, /*!< in: dulint */
ulint b); /*!< in: ulint, b <= a */
/*******************************************************//**
Subtracts a dulint from another. NOTE that the difference must be positive
and smaller that 4G.
@return a - b */
UNIV_INLINE
ulint
ut_dulint_minus(
/*============*/
dulint a, /*!< in: dulint; NOTE a must be >= b and at most
2 to power 32 - 1 greater */
dulint b); /*!< in: dulint */
ulint low) /*!< in: low-order 32 bits */
__attribute__((const));
/********************************************************//**
Rounds a dulint downward to a multiple of a power of 2.
@return rounded value */
UNIV_INLINE
dulint
ut_dulint_align_down(
/*=================*/
dulint n, /*!< in: number to be rounded */
ulint align_no); /*!< in: align by this number which must be a
power of 2 */
/********************************************************//**
Rounds a dulint upward to a multiple of a power of 2.
@return rounded value */
UNIV_INLINE
dulint
ut_dulint_align_up(
/*===============*/
dulint n, /*!< in: number to be rounded */
ulint align_no); /*!< in: align by this number which must be a
power of 2 */
/********************************************************//**
Rounds a dulint downward to a multiple of a power of 2.
Rounds a 64-bit integer downward to a multiple of a power of 2.
@return rounded value */
UNIV_INLINE
ib_uint64_t
@ -184,34 +61,6 @@ ut_uint64_align_up(
ib_uint64_t n, /*!< in: number to be rounded */
ulint align_no); /*!< in: align by this number
which must be a power of 2 */
/*******************************************************//**
Increments a dulint variable by 1. */
#define UT_DULINT_INC(D)\
{\
if ((D).low == 0xFFFFFFFFUL) {\
(D).high = (D).high + 1;\
(D).low = 0;\
} else {\
(D).low = (D).low + 1;\
}\
}
/*******************************************************//**
Tests if two dulints are equal. */
#define UT_DULINT_EQ(D1, D2) (((D1).low == (D2).low)\
&& ((D1).high == (D2).high))
#ifdef notdefined
/************************************************************//**
Sort function for dulint arrays. */
UNIV_INTERN
void
ut_dulint_sort(
/*===========*/
dulint* arr, /*!< in/out: array to be sorted */
dulint* aux_arr,/*!< in/out: auxiliary array (same size as arr) */
ulint low, /*!< in: low bound of sort interval, inclusive */
ulint high); /*!< in: high bound of sort interval, noninclusive */
#endif /* notdefined */
/*********************************************************//**
The following function rounds up a pointer to the nearest aligned address.
@return aligned pointer */

View file

@ -24,260 +24,22 @@ Created 5/30/1994 Heikki Tuuri
*******************************************************************/
/*******************************************************//**
Creates a 64-bit dulint out of two ulints.
Creates a 64-bit integer out of two 32-bit integers.
@return created dulint */
UNIV_INLINE
dulint
ut_dulint_create(
/*=============*/
ib_uint64_t
ut_ull_create(
/*==========*/
ulint high, /*!< in: high-order 32 bits */
ulint low) /*!< in: low-order 32 bits */
{
dulint res;
ut_ad(high <= 0xFFFFFFFF);
ut_ad(low <= 0xFFFFFFFF);
res.high = high;
res.low = low;
return(res);
}
/*******************************************************//**
Gets the high-order 32 bits of a dulint.
@return 32 bits in ulint */
UNIV_INLINE
ulint
ut_dulint_get_high(
/*===============*/
dulint d) /*!< in: dulint */
{
return(d.high);
}
/*******************************************************//**
Gets the low-order 32 bits of a dulint.
@return 32 bits in ulint */
UNIV_INLINE
ulint
ut_dulint_get_low(
/*==============*/
dulint d) /*!< in: dulint */
{
return(d.low);
}
/*******************************************************//**
Converts a dulint (a struct of 2 ulints) to ib_int64_t, which is a 64-bit
integer type.
@return value in ib_int64_t type */
UNIV_INLINE
ib_int64_t
ut_conv_dulint_to_longlong(
/*=======================*/
dulint d) /*!< in: dulint */
{
return((ib_int64_t)d.low
+ (((ib_int64_t)d.high) << 32));
}
/*******************************************************//**
Tests if a dulint is zero.
@return TRUE if zero */
UNIV_INLINE
ibool
ut_dulint_is_zero(
/*==============*/
dulint a) /*!< in: dulint */
{
if ((a.low == 0) && (a.high == 0)) {
return(TRUE);
}
return(FALSE);
}
/*******************************************************//**
Compares two dulints.
@return -1 if a < b, 0 if a == b, 1 if a > b */
UNIV_INLINE
int
ut_dulint_cmp(
/*==========*/
dulint a, /*!< in: dulint */
dulint b) /*!< in: dulint */
{
if (a.high > b.high) {
return(1);
} else if (a.high < b.high) {
return(-1);
} else if (a.low > b.low) {
return(1);
} else if (a.low < b.low) {
return(-1);
} else {
return(0);
}
}
/*******************************************************//**
Calculates the max of two dulints.
@return max(a, b) */
UNIV_INLINE
dulint
ut_dulint_get_max(
/*==============*/
dulint a, /*!< in: dulint */
dulint b) /*!< in: dulint */
{
if (ut_dulint_cmp(a, b) > 0) {
return(a);
}
return(b);
}
/*******************************************************//**
Calculates the min of two dulints.
@return min(a, b) */
UNIV_INLINE
dulint
ut_dulint_get_min(
/*==============*/
dulint a, /*!< in: dulint */
dulint b) /*!< in: dulint */
{
if (ut_dulint_cmp(a, b) > 0) {
return(b);
}
return(a);
}
/*******************************************************//**
Adds a ulint to a dulint.
@return sum a + b */
UNIV_INLINE
dulint
ut_dulint_add(
/*==========*/
dulint a, /*!< in: dulint */
ulint b) /*!< in: ulint */
{
if (0xFFFFFFFFUL - b >= a.low) {
a.low += b;
return(a);
}
a.low = a.low - (0xFFFFFFFFUL - b) - 1;
a.high++;
return(a);
}
/*******************************************************//**
Subtracts a ulint from a dulint.
@return a - b */
UNIV_INLINE
dulint
ut_dulint_subtract(
/*===============*/
dulint a, /*!< in: dulint */
ulint b) /*!< in: ulint, b <= a */
{
if (a.low >= b) {
a.low -= b;
return(a);
}
b -= a.low + 1;
a.low = 0xFFFFFFFFUL - b;
ut_ad(a.high > 0);
a.high--;
return(a);
}
/*******************************************************//**
Subtracts a dulint from another. NOTE that the difference must be positive
and smaller that 4G.
@return a - b */
UNIV_INLINE
ulint
ut_dulint_minus(
/*============*/
dulint a, /*!< in: dulint; NOTE a must be >= b and at most
2 to power 32 - 1 greater */
dulint b) /*!< in: dulint */
{
ulint diff;
if (a.high == b.high) {
ut_ad(a.low >= b.low);
return(a.low - b.low);
}
ut_ad(a.high == b.high + 1);
diff = (ulint)(0xFFFFFFFFUL - b.low);
diff += 1 + a.low;
ut_ad(diff > a.low);
return(diff);
ut_ad(high <= ULINT32_MASK);
ut_ad(low <= ULINT32_MASK);
return(((ib_uint64_t) high) << 32 | low);
}
/********************************************************//**
Rounds a dulint downward to a multiple of a power of 2.
@return rounded value */
UNIV_INLINE
dulint
ut_dulint_align_down(
/*=================*/
dulint n, /*!< in: number to be rounded */
ulint align_no) /*!< in: align by this number which must be a
power of 2 */
{
ulint low, high;
ut_ad(align_no > 0);
ut_ad(((align_no - 1) & align_no) == 0);
low = ut_dulint_get_low(n);
high = ut_dulint_get_high(n);
low = low & ~(align_no - 1);
return(ut_dulint_create(high, low));
}
/********************************************************//**
Rounds a dulint upward to a multiple of a power of 2.
@return rounded value */
UNIV_INLINE
dulint
ut_dulint_align_up(
/*===============*/
dulint n, /*!< in: number to be rounded */
ulint align_no) /*!< in: align by this number which must be a
power of 2 */
{
return(ut_dulint_align_down(ut_dulint_add(n, align_no - 1), align_no));
}
/********************************************************//**
Rounds ib_uint64_t downward to a multiple of a power of 2.
Rounds a 64-bit integer downward to a multiple of a power of 2.
@return rounded value */
UNIV_INLINE
ib_uint64_t

View file

@ -50,33 +50,23 @@ UNIV_INTERN
void
ut_dbg_assertion_failed(
/*====================*/
const char* expr, /*!< in: the failed assertion */
const char* file, /*!< in: source file containing the assertion */
ulint line); /*!< in: line number of the assertion */
const char* expr, /*!< in: the failed assertion */
const char* file, /*!< in: source file containing the assertion */
ulint line) /*!< in: line number of the assertion */
UNIV_COLD __attribute__((nonnull(2)));
#ifdef __NETWARE__
/** Flag for ignoring further assertion failures. This is set to TRUE
when on NetWare there happens an InnoDB assertion failure or other
fatal error condition that requires an immediate shutdown. */
extern ibool panic_shutdown;
/* Abort the execution. */
void ut_dbg_panic(void);
# define UT_DBG_PANIC ut_dbg_panic()
/* Stop threads in ut_a(). */
# define UT_DBG_STOP do {} while (0) /* We do not do this on NetWare */
#else /* __NETWARE__ */
# if defined(__WIN__) || defined(__INTEL_COMPILER)
# undef UT_DBG_USE_ABORT
# elif defined(__GNUC__) && (__GNUC__ > 2)
# define UT_DBG_USE_ABORT
# endif
#if defined(__WIN__) || defined(__INTEL_COMPILER)
# undef UT_DBG_USE_ABORT
#elif defined(__GNUC__) && (__GNUC__ > 2)
# define UT_DBG_USE_ABORT
#endif
# ifndef UT_DBG_USE_ABORT
#ifndef UT_DBG_USE_ABORT
/** A null pointer that will be dereferenced to trigger a memory trap */
extern ulint* ut_dbg_null_ptr;
# endif
#endif
# if defined(UNIV_SYNC_DEBUG) || !defined(UT_DBG_USE_ABORT)
#if defined(UNIV_SYNC_DEBUG) || !defined(UT_DBG_USE_ABORT)
/** If this is set to TRUE by ut_dbg_assertion_failed(), all threads
will stop at the next ut_a() or ut_ad(). */
extern ibool ut_dbg_stop_threads;
@ -89,24 +79,23 @@ ut_dbg_stop_thread(
/*===============*/
const char* file,
ulint line);
# endif
#endif
# ifdef UT_DBG_USE_ABORT
#ifdef UT_DBG_USE_ABORT
/** Abort the execution. */
# define UT_DBG_PANIC abort()
# define UT_DBG_PANIC abort()
/** Stop threads (null operation) */
# define UT_DBG_STOP do {} while (0)
# else /* UT_DBG_USE_ABORT */
# define UT_DBG_STOP do {} while (0)
#else /* UT_DBG_USE_ABORT */
/** Abort the execution. */
# define UT_DBG_PANIC \
# define UT_DBG_PANIC \
if (*(ut_dbg_null_ptr)) ut_dbg_null_ptr = NULL
/** Stop threads in ut_a(). */
# define UT_DBG_STOP do \
# define UT_DBG_STOP do \
if (UNIV_UNLIKELY(ut_dbg_stop_threads)) { \
ut_dbg_stop_thread(__FILE__, (ulint) __LINE__); \
} while (0)
# endif /* UT_DBG_USE_ABORT */
#endif /* __NETWARE__ */
#endif /* UT_DBG_USE_ABORT */
/** Abort execution if EXPR does not evaluate to nonzero.
@param EXPR assertion expression that should hold */

View file

@ -1,6 +1,6 @@
/*****************************************************************************
Copyright (c) 1995, 2009, Innobase Oy. All Rights Reserved.
Copyright (c) 1995, 2010, Innobase Oy. 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
@ -110,7 +110,7 @@ Adds the node as the last element in a two-way linked list.
*/
#define UT_LIST_ADD_LAST(NAME, BASE, N)\
{\
ut_ad(N);\
ut_ad(N != NULL);\
((BASE).count)++;\
((N)->NAME).prev = (BASE).end;\
((N)->NAME).next = NULL;\
@ -257,48 +257,5 @@ do { \
ut_a(ut_list_node_313 == NULL); \
} while (0)
/********************************************************************//**
Align nodes with moving location.
@param NAME the name of the list
@param TYPE node type
@param BASE base node (not a pointer to it)
@param OFFSET offset moved */
#define UT_LIST_OFFSET(NAME, TYPE, BASE, FADDR, FOFFSET, BOFFSET) \
do { \
ulint ut_list_i_313; \
TYPE* ut_list_node_313; \
\
if ((BASE).start) \
(BASE).start = (void*)((byte*)((BASE).start) \
+ (((void*)((BASE).start) > (void*)FADDR)?FOFFSET:BOFFSET));\
if ((BASE).end) \
(BASE).end = (void*)((byte*)((BASE).end) \
+ (((void*)((BASE).end) > (void*)FADDR)?FOFFSET:BOFFSET));\
\
ut_list_node_313 = (BASE).start; \
\
for (ut_list_i_313 = (BASE).count; ut_list_i_313--; ) { \
ut_a(ut_list_node_313); \
if ((ut_list_node_313->NAME).prev) \
(ut_list_node_313->NAME).prev = (void*)((byte*)((ut_list_node_313->NAME).prev)\
+ (((void*)((ut_list_node_313->NAME).prev) > (void*)FADDR)?FOFFSET:BOFFSET));\
if ((ut_list_node_313->NAME).next) \
(ut_list_node_313->NAME).next = (void*)((byte*)((ut_list_node_313->NAME).next)\
+ (((void*)((ut_list_node_313->NAME).next)> (void*)FADDR)?FOFFSET:BOFFSET));\
ut_list_node_313 = (ut_list_node_313->NAME).next; \
} \
\
ut_a(ut_list_node_313 == NULL); \
\
ut_list_node_313 = (BASE).end; \
\
for (ut_list_i_313 = (BASE).count; ut_list_i_313--; ) { \
ut_a(ut_list_node_313); \
ut_list_node_313 = (ut_list_node_313->NAME).prev; \
} \
\
ut_a(ut_list_node_313 == NULL); \
} while (0)
#endif

Some files were not shown because too many files have changed in this diff Show more