Commit 85dbe88d authored by Marko Mäkelä's avatar Marko Mäkelä

Bug#11766305 - 59392: Remove thr0loc.c and ibuf_inside() [part 4 of 4]

ibuf_inside(), ibuf_enter(), ibuf_exit(): Add the parameter mtr. The
flag is no longer kept in the thread-local storage but in the
mini-transaction (mtr->inside_ibuf).

mtr_start(): Clean up the comment and remove the unused return value.
mtr_commit(): Assert !ibuf_inside(mtr) in debug builds.

ibuf_mtr_start(): Like mtr_start(), but sets the flag.
ibuf_mtr_commit(), ibuf_btr_pcur_commit_specify_mtr(): Wrappers that
assert ibuf_inside().

buf_page_get_zip(), buf_page_init_for_read(),
buf_read_ibuf_merge_pages(), fil_io(), ibuf_free_excess_pages(),
ibuf_contract_ext(): Remove assertions on ibuf_inside(), because a
mini-transaction is not available.

buf_read_ahead_linear(): Add the parameter inside_ibuf.

ibuf_restore_pos(): When this function returns FALSE, it commits mtr
and must therefore do ibuf_exit(mtr).

ibuf_delete_rec(): This function commits mtr and must therefore do
ibuf_exit(mtr).

ibuf_rec_get_page_no(), ibuf_rec_get_space(), ibuf_rec_get_info(),
ibuf_rec_get_op_type(), ibuf_build_entry_from_ibuf_rec(),
ibuf_rec_get_volume(), ibuf_get_merge_page_nos(),
ibuf_get_volume_buffered_count(), ibuf_get_entry_counter_low(): Add
the parameter mtr in debug builds, for asserting ibuf_inside(mtr).

rb:585 approved by Sunny Bains
parent a4d2a3a3
...@@ -241,7 +241,6 @@ SET(INNOBASE_SOURCES btr/btr0btr.c btr/btr0cur.c btr/btr0pcur.c btr/btr0sea.c ...@@ -241,7 +241,6 @@ SET(INNOBASE_SOURCES btr/btr0btr.c btr/btr0cur.c btr/btr0pcur.c btr/btr0sea.c
row/row0sel.c row/row0uins.c row/row0umod.c row/row0undo.c row/row0upd.c row/row0vers.c row/row0sel.c row/row0uins.c row/row0umod.c row/row0undo.c row/row0upd.c row/row0vers.c
srv/srv0srv.c srv/srv0start.c srv/srv0srv.c srv/srv0start.c
sync/sync0arr.c sync/sync0rw.c sync/sync0sync.c sync/sync0arr.c sync/sync0rw.c sync/sync0sync.c
thr/thr0loc.c
trx/trx0i_s.c trx/trx0purge.c trx/trx0rec.c trx/trx0roll.c trx/trx0rseg.c trx/trx0i_s.c trx/trx0purge.c trx/trx0rec.c trx/trx0roll.c trx/trx0rseg.c
trx/trx0sys.c trx/trx0trx.c trx/trx0undo.c trx/trx0sys.c trx/trx0trx.c trx/trx0undo.c
usr/usr0sess.c usr/usr0sess.c
......
...@@ -402,7 +402,7 @@ btr_cur_search_to_nth_level( ...@@ -402,7 +402,7 @@ btr_cur_search_to_nth_level(
ut_ad(level == 0 || mode == PAGE_CUR_LE); ut_ad(level == 0 || mode == PAGE_CUR_LE);
ut_ad(dict_index_check_search_tuple(index, tuple)); ut_ad(dict_index_check_search_tuple(index, tuple));
ut_ad(!dict_index_is_ibuf(index) || ibuf_inside()); ut_ad(!dict_index_is_ibuf(index) || ibuf_inside(mtr));
ut_ad(dtuple_check_typed(tuple)); ut_ad(dtuple_check_typed(tuple));
#ifdef UNIV_DEBUG #ifdef UNIV_DEBUG
......
...@@ -2316,9 +2316,6 @@ buf_page_get_zip( ...@@ -2316,9 +2316,6 @@ buf_page_get_zip(
unsigned access_time; unsigned access_time;
buf_pool_t* buf_pool = buf_pool_get(space, offset); buf_pool_t* buf_pool = buf_pool_get(space, offset);
#ifndef UNIV_LOG_DEBUG
ut_ad(!ibuf_inside());
#endif
buf_pool->stat.n_page_gets++; buf_pool->stat.n_page_gets++;
for (;;) { for (;;) {
...@@ -2758,8 +2755,9 @@ buf_page_get_gen( ...@@ -2758,8 +2755,9 @@ buf_page_get_gen(
ut_ad(zip_size == fil_space_get_zip_size(space)); ut_ad(zip_size == fil_space_get_zip_size(space));
ut_ad(ut_is_2pow(zip_size)); ut_ad(ut_is_2pow(zip_size));
#ifndef UNIV_LOG_DEBUG #ifndef UNIV_LOG_DEBUG
ut_ad(!ibuf_inside() || ibuf_page_low(space, zip_size, offset, ut_ad(!ibuf_inside(mtr)
FALSE, file, line, NULL)); || ibuf_page_low(space, zip_size, offset,
FALSE, file, line, NULL));
#endif #endif
buf_pool->stat.n_page_gets++; buf_pool->stat.n_page_gets++;
fold = buf_page_address_fold(space, offset); fold = buf_page_address_fold(space, offset);
...@@ -3132,7 +3130,8 @@ wait_until_unfixed: ...@@ -3132,7 +3130,8 @@ wait_until_unfixed:
/* In the case of a first access, try to apply linear /* In the case of a first access, try to apply linear
read-ahead */ read-ahead */
buf_read_ahead_linear(space, zip_size, offset); buf_read_ahead_linear(space, zip_size, offset,
ibuf_inside(mtr));
} }
#ifdef UNIV_IBUF_COUNT_DEBUG #ifdef UNIV_IBUF_COUNT_DEBUG
...@@ -3189,7 +3188,7 @@ buf_page_optimistic_get( ...@@ -3189,7 +3188,7 @@ buf_page_optimistic_get(
access_time = buf_page_is_accessed(&block->page); access_time = buf_page_is_accessed(&block->page);
buf_page_set_accessed_make_young(&block->page, access_time); buf_page_set_accessed_make_young(&block->page, access_time);
ut_ad(!ibuf_inside() ut_ad(!ibuf_inside(mtr)
|| ibuf_page(buf_block_get_space(block), || ibuf_page(buf_block_get_space(block),
buf_block_get_zip_size(block), buf_block_get_zip_size(block),
buf_block_get_page_no(block), NULL)); buf_block_get_page_no(block), NULL));
...@@ -3245,7 +3244,8 @@ buf_page_optimistic_get( ...@@ -3245,7 +3244,8 @@ buf_page_optimistic_get(
buf_read_ahead_linear(buf_block_get_space(block), buf_read_ahead_linear(buf_block_get_space(block),
buf_block_get_zip_size(block), buf_block_get_zip_size(block),
buf_block_get_page_no(block)); buf_block_get_page_no(block),
ibuf_inside(mtr));
} }
#ifdef UNIV_IBUF_COUNT_DEBUG #ifdef UNIV_IBUF_COUNT_DEBUG
...@@ -3321,7 +3321,7 @@ buf_page_get_known_nowait( ...@@ -3321,7 +3321,7 @@ buf_page_get_known_nowait(
buf_pool_mutex_exit(buf_pool); buf_pool_mutex_exit(buf_pool);
} }
ut_ad(!ibuf_inside() || (mode == BUF_KEEP_OLD)); ut_ad(!ibuf_inside(mtr) || mode == BUF_KEEP_OLD);
if (rw_latch == RW_S_LATCH) { if (rw_latch == RW_S_LATCH) {
success = rw_lock_s_lock_nowait(&(block->lock), success = rw_lock_s_lock_nowait(&(block->lock),
...@@ -3586,14 +3586,13 @@ buf_page_init_for_read( ...@@ -3586,14 +3586,13 @@ buf_page_init_for_read(
/* It is a read-ahead within an ibuf routine */ /* It is a read-ahead within an ibuf routine */
ut_ad(!ibuf_bitmap_page(zip_size, offset)); ut_ad(!ibuf_bitmap_page(zip_size, offset));
ut_ad(ibuf_inside());
mtr_start(&mtr); ibuf_mtr_start(&mtr);
if (!recv_no_ibuf_operations if (!recv_no_ibuf_operations
&& !ibuf_page(space, zip_size, offset, &mtr)) { && !ibuf_page(space, zip_size, offset, &mtr)) {
mtr_commit(&mtr); ibuf_mtr_commit(&mtr);
return(NULL); return(NULL);
} }
...@@ -3778,7 +3777,7 @@ func_exit: ...@@ -3778,7 +3777,7 @@ func_exit:
if (mode == BUF_READ_IBUF_PAGES_ONLY) { if (mode == BUF_READ_IBUF_PAGES_ONLY) {
mtr_commit(&mtr); ibuf_mtr_commit(&mtr);
} }
ut_ad(!bpage || buf_page_in_file(bpage)); ut_ad(!bpage || buf_page_in_file(bpage));
......
...@@ -236,10 +236,10 @@ UNIV_INTERN ...@@ -236,10 +236,10 @@ UNIV_INTERN
ulint ulint
buf_read_ahead_linear( buf_read_ahead_linear(
/*==================*/ /*==================*/
ulint space, /*!< in: space id */ ulint space, /*!< in: space id */
ulint zip_size,/*!< in: compressed page size in bytes, or 0 */ ulint zip_size, /*!< in: compressed page size in bytes, or 0 */
ulint offset) /*!< in: page number of a page; NOTE: the current thread ulint offset, /*!< in: page number; see NOTE 3 above */
must want access to this page (see NOTE 3 above) */ ibool inside_ibuf) /*!< in: TRUE if we are inside ibuf routine */
{ {
buf_pool_t* buf_pool = buf_pool_get(space, offset); buf_pool_t* buf_pool = buf_pool_get(space, offset);
ib_int64_t tablespace_version; ib_int64_t tablespace_version;
...@@ -429,11 +429,9 @@ buf_read_ahead_linear( ...@@ -429,11 +429,9 @@ buf_read_ahead_linear(
/* If we got this far, read-ahead can be sensible: do it */ /* If we got this far, read-ahead can be sensible: do it */
if (ibuf_inside()) { ibuf_mode = inside_ibuf
ibuf_mode = BUF_READ_IBUF_PAGES_ONLY; ? BUF_READ_IBUF_PAGES_ONLY | OS_AIO_SIMULATED_WAKE_LATER
} else { : BUF_READ_ANY_PAGE | OS_AIO_SIMULATED_WAKE_LATER;
ibuf_mode = BUF_READ_ANY_PAGE;
}
count = 0; count = 0;
...@@ -450,7 +448,7 @@ buf_read_ahead_linear( ...@@ -450,7 +448,7 @@ buf_read_ahead_linear(
if (!ibuf_bitmap_page(zip_size, i)) { if (!ibuf_bitmap_page(zip_size, i)) {
count += buf_read_page_low( count += buf_read_page_low(
&err, FALSE, &err, FALSE,
ibuf_mode | OS_AIO_SIMULATED_WAKE_LATER, ibuf_mode,
space, zip_size, FALSE, tablespace_version, i); space, zip_size, FALSE, tablespace_version, i);
if (err == DB_TABLESPACE_DELETED) { if (err == DB_TABLESPACE_DELETED) {
ut_print_timestamp(stderr); ut_print_timestamp(stderr);
...@@ -520,7 +518,6 @@ buf_read_ibuf_merge_pages( ...@@ -520,7 +518,6 @@ buf_read_ibuf_merge_pages(
{ {
ulint i; ulint i;
ut_ad(!ibuf_inside());
#ifdef UNIV_IBUF_DEBUG #ifdef UNIV_IBUF_DEBUG
ut_a(n_stored < UNIV_PAGE_SIZE); ut_a(n_stored < UNIV_PAGE_SIZE);
#endif #endif
......
...@@ -4342,8 +4342,6 @@ fil_io( ...@@ -4342,8 +4342,6 @@ fil_io(
ut_ad(recv_no_ibuf_operations || (type == OS_FILE_WRITE) ut_ad(recv_no_ibuf_operations || (type == OS_FILE_WRITE)
|| !ibuf_bitmap_page(zip_size, block_offset) || !ibuf_bitmap_page(zip_size, block_offset)
|| sync || is_log); || sync || is_log);
ut_ad(!ibuf_inside() || is_log || (type == OS_FILE_WRITE)
|| ibuf_page(space_id, zip_size, block_offset, NULL));
# endif /* UNIV_LOG_DEBUG */ # endif /* UNIV_LOG_DEBUG */
if (sync) { if (sync) {
mode = OS_AIO_SYNC; mode = OS_AIO_SYNC;
......
...@@ -82,7 +82,6 @@ extern "C" { ...@@ -82,7 +82,6 @@ extern "C" {
#include "fil0fil.h" #include "fil0fil.h"
#include "trx0xa.h" #include "trx0xa.h"
#include "row0merge.h" #include "row0merge.h"
#include "thr0loc.h"
#include "dict0boot.h" #include "dict0boot.h"
#include "ha_prototypes.h" #include "ha_prototypes.h"
#include "ut0mem.h" #include "ut0mem.h"
...@@ -280,7 +279,6 @@ static PSI_mutex_info all_innodb_mutexes[] = { ...@@ -280,7 +279,6 @@ static PSI_mutex_info all_innodb_mutexes[] = {
{&sync_thread_mutex_key, "sync_thread_mutex", 0}, {&sync_thread_mutex_key, "sync_thread_mutex", 0},
# endif /* UNIV_SYNC_DEBUG */ # endif /* UNIV_SYNC_DEBUG */
{&trx_doublewrite_mutex_key, "trx_doublewrite_mutex", 0}, {&trx_doublewrite_mutex_key, "trx_doublewrite_mutex", 0},
{&thr_local_mutex_key, "thr_local_mutex", 0},
{&trx_undo_mutex_key, "trx_undo_mutex", 0} {&trx_undo_mutex_key, "trx_undo_mutex", 0}
}; };
# endif /* UNIV_PFS_MUTEX */ # endif /* UNIV_PFS_MUTEX */
...@@ -3042,7 +3040,6 @@ innobase_close_connection( ...@@ -3042,7 +3040,6 @@ innobase_close_connection(
innobase_rollback_trx(trx); innobase_rollback_trx(trx);
thr_local_free(trx->mysql_thread_id);
trx_free_for_mysql(trx); trx_free_for_mysql(trx);
DBUG_RETURN(0); DBUG_RETURN(0);
......
...@@ -44,7 +44,6 @@ Created 7/19/1997 Heikki Tuuri ...@@ -44,7 +44,6 @@ Created 7/19/1997 Heikki Tuuri
#include "fsp0fsp.h" #include "fsp0fsp.h"
#include "trx0sys.h" #include "trx0sys.h"
#include "fil0fil.h" #include "fil0fil.h"
#include "thr0loc.h"
#include "rem0rec.h" #include "rem0rec.h"
#include "btr0cur.h" #include "btr0cur.h"
#include "btr0pcur.h" #include "btr0pcur.h"
...@@ -324,52 +323,43 @@ still physically like the index page even if the index would have been ...@@ -324,52 +323,43 @@ still physically like the index page even if the index would have been
dropped! So, there seems to be no problem. */ dropped! So, there seems to be no problem. */
/******************************************************************//** /******************************************************************//**
Sets the flag in the current OS thread local storage denoting that it is Sets the flag in the current mini-transaction record indicating we're
inside an insert buffer routine. */ inside an insert buffer routine. */
UNIV_INLINE UNIV_INLINE
void void
ibuf_enter(void) ibuf_enter(
/*============*/ /*=======*/
mtr_t* mtr) /*!< in/out: mini-transaction */
{ {
ibool* ptr; ut_ad(!mtr->inside_ibuf);
mtr->inside_ibuf = TRUE;
ptr = thr_local_get_in_ibuf_field();
ut_ad(*ptr == FALSE);
*ptr = TRUE;
} }
/******************************************************************//** /******************************************************************//**
Sets the flag in the current OS thread local storage denoting that it is Sets the flag in the current mini-transaction record indicating we're
exiting an insert buffer routine. */ exiting an insert buffer routine. */
UNIV_INLINE UNIV_INLINE
void void
ibuf_exit(void) ibuf_exit(
/*===========*/ /*======*/
mtr_t* mtr) /*!< in/out: mini-transaction */
{ {
ibool* ptr; ut_ad(mtr->inside_ibuf);
mtr->inside_ibuf = FALSE;
ptr = thr_local_get_in_ibuf_field();
ut_ad(*ptr == TRUE);
*ptr = FALSE;
} }
/******************************************************************//** /**************************************************************//**
Returns TRUE if the current OS thread is performing an insert buffer Commits an insert buffer mini-transaction and sets the persistent
routine. cursor latch mode to BTR_NO_LATCHES, that is, detaches the cursor. */
UNIV_INLINE
For instance, a read-ahead of non-ibuf pages is forbidden by threads void
that are executing an insert buffer routine. ibuf_btr_pcur_commit_specify_mtr(
@return TRUE if inside an insert buffer routine */ /*=============================*/
UNIV_INTERN btr_pcur_t* pcur, /*!< in/out: persistent cursor */
ibool mtr_t* mtr) /*!< in/out: mini-transaction */
ibuf_inside(void)
/*=============*/
{ {
return(*thr_local_get_in_ibuf_field()); ut_d(ibuf_exit(mtr));
btr_pcur_commit_specify_mtr(pcur, mtr);
} }
/******************************************************************//** /******************************************************************//**
...@@ -379,11 +369,11 @@ static ...@@ -379,11 +369,11 @@ static
page_t* page_t*
ibuf_header_page_get( ibuf_header_page_get(
/*=================*/ /*=================*/
mtr_t* mtr) /*!< in: mtr */ mtr_t* mtr) /*!< in/out: mini-transaction */
{ {
buf_block_t* block; buf_block_t* block;
ut_ad(!ibuf_inside()); ut_ad(!ibuf_inside(mtr));
block = buf_page_get( block = buf_page_get(
IBUF_SPACE_ID, 0, FSP_IBUF_HEADER_PAGE_NO, RW_X_LATCH, mtr); IBUF_SPACE_ID, 0, FSP_IBUF_HEADER_PAGE_NO, RW_X_LATCH, mtr);
...@@ -404,7 +394,7 @@ ibuf_tree_root_get( ...@@ -404,7 +394,7 @@ ibuf_tree_root_get(
buf_block_t* block; buf_block_t* block;
page_t* root; page_t* root;
ut_ad(ibuf_inside()); ut_ad(ibuf_inside(mtr));
ut_ad(mutex_own(&ibuf_mutex)); ut_ad(mutex_own(&ibuf_mutex));
mtr_x_lock(dict_index_get_lock(ibuf->index), mtr); mtr_x_lock(dict_index_get_lock(ibuf->index), mtr);
...@@ -547,7 +537,7 @@ ibuf_init_at_db_start(void) ...@@ -547,7 +537,7 @@ ibuf_init_at_db_start(void)
fseg_n_reserved_pages(header_page + IBUF_HEADER + IBUF_TREE_SEG_HEADER, fseg_n_reserved_pages(header_page + IBUF_HEADER + IBUF_TREE_SEG_HEADER,
&n_used, &mtr); &n_used, &mtr);
ibuf_enter(); ibuf_enter(&mtr);
ut_ad(n_used >= 2); ut_ad(n_used >= 2);
...@@ -568,9 +558,7 @@ ibuf_init_at_db_start(void) ...@@ -568,9 +558,7 @@ ibuf_init_at_db_start(void)
mutex_exit(&ibuf_mutex); mutex_exit(&ibuf_mutex);
ibuf->empty = (page_get_n_recs(root) == 0); ibuf->empty = (page_get_n_recs(root) == 0);
mtr_commit(&mtr); ibuf_mtr_commit(&mtr);
ibuf_exit();
heap = mem_heap_create(450); heap = mem_heap_create(450);
...@@ -1230,19 +1218,30 @@ ibuf_page_low( ...@@ -1230,19 +1218,30 @@ ibuf_page_low(
return(ret); return(ret);
} }
#ifdef UNIV_DEBUG
# define ibuf_rec_get_page_no(mtr,rec) ibuf_rec_get_page_no_func(mtr,rec)
#else /* UNIV_DEBUG */
# define ibuf_rec_get_page_no(mtr,rec) ibuf_rec_get_page_no_func(rec)
#endif /* UNIV_DEBUG */
/********************************************************************//** /********************************************************************//**
Returns the page number field of an ibuf record. Returns the page number field of an ibuf record.
@return page number */ @return page number */
static static
ulint ulint
ibuf_rec_get_page_no( ibuf_rec_get_page_no_func(
/*=================*/ /*======================*/
#ifdef UNIV_DEBUG
mtr_t* mtr, /*!< in: mini-transaction owning rec */
#endif /* UNIV_DEBUG */
const rec_t* rec) /*!< in: ibuf record */ const rec_t* rec) /*!< in: ibuf record */
{ {
const byte* field; const byte* field;
ulint len; ulint len;
ut_ad(ibuf_inside()); ut_ad(mtr_memo_contains_page(mtr, rec, MTR_MEMO_PAGE_X_FIX)
|| mtr_memo_contains_page(mtr, rec, MTR_MEMO_PAGE_S_FIX));
ut_ad(ibuf_inside(mtr));
ut_ad(rec_get_n_fields_old(rec) > 2); ut_ad(rec_get_n_fields_old(rec) > 2);
field = rec_get_nth_field_old(rec, 1, &len); field = rec_get_nth_field_old(rec, 1, &len);
...@@ -1264,20 +1263,31 @@ ibuf_rec_get_page_no( ...@@ -1264,20 +1263,31 @@ ibuf_rec_get_page_no(
return(mach_read_from_4(field)); return(mach_read_from_4(field));
} }
#ifdef UNIV_DEBUG
# define ibuf_rec_get_space(mtr,rec) ibuf_rec_get_space_func(mtr,rec)
#else /* UNIV_DEBUG */
# define ibuf_rec_get_space(mtr,rec) ibuf_rec_get_space_func(rec)
#endif /* UNIV_DEBUG */
/********************************************************************//** /********************************************************************//**
Returns the space id field of an ibuf record. For < 4.1.x format records Returns the space id field of an ibuf record. For < 4.1.x format records
returns 0. returns 0.
@return space id */ @return space id */
static static
ulint ulint
ibuf_rec_get_space( ibuf_rec_get_space_func(
/*===============*/ /*====================*/
#ifdef UNIV_DEBUG
mtr_t* mtr, /*!< in: mini-transaction owning rec */
#endif /* UNIV_DEBUG */
const rec_t* rec) /*!< in: ibuf record */ const rec_t* rec) /*!< in: ibuf record */
{ {
const byte* field; const byte* field;
ulint len; ulint len;
ut_ad(ibuf_inside()); ut_ad(mtr_memo_contains_page(mtr, rec, MTR_MEMO_PAGE_X_FIX)
|| mtr_memo_contains_page(mtr, rec, MTR_MEMO_PAGE_S_FIX));
ut_ad(ibuf_inside(mtr));
ut_ad(rec_get_n_fields_old(rec) > 2); ut_ad(rec_get_n_fields_old(rec) > 2);
field = rec_get_nth_field_old(rec, 1, &len); field = rec_get_nth_field_old(rec, 1, &len);
...@@ -1298,12 +1308,22 @@ ibuf_rec_get_space( ...@@ -1298,12 +1308,22 @@ ibuf_rec_get_space(
return(0); return(0);
} }
#ifdef UNIV_DEBUG
# define ibuf_rec_get_info(mtr,rec,op,comp,info_len,counter) \
ibuf_rec_get_info_func(mtr,rec,op,comp,info_len,counter)
#else /* UNIV_DEBUG */
# define ibuf_rec_get_info(mtr,rec,op,comp,info_len,counter) \
ibuf_rec_get_info_func(rec,op,comp,info_len,counter)
#endif
/****************************************************************//** /****************************************************************//**
Get various information about an ibuf record in >= 4.1.x format. */ Get various information about an ibuf record in >= 4.1.x format. */
static static
void void
ibuf_rec_get_info( ibuf_rec_get_info_func(
/*==============*/ /*===================*/
#ifdef UNIV_DEBUG
mtr_t* mtr, /*!< in: mini-transaction owning rec */
#endif /* UNIV_DEBUG */
const rec_t* rec, /*!< in: ibuf record */ const rec_t* rec, /*!< in: ibuf record */
ibuf_op_t* op, /*!< out: operation type, or NULL */ ibuf_op_t* op, /*!< out: operation type, or NULL */
ibool* comp, /*!< out: compact flag, or NULL */ ibool* comp, /*!< out: compact flag, or NULL */
...@@ -1322,7 +1342,9 @@ ibuf_rec_get_info( ...@@ -1322,7 +1342,9 @@ ibuf_rec_get_info(
ulint info_len_local; ulint info_len_local;
ulint counter_local; ulint counter_local;
ut_ad(ibuf_inside()); ut_ad(mtr_memo_contains_page(mtr, rec, MTR_MEMO_PAGE_X_FIX)
|| mtr_memo_contains_page(mtr, rec, MTR_MEMO_PAGE_S_FIX));
ut_ad(ibuf_inside(mtr));
fields = rec_get_n_fields_old(rec); fields = rec_get_n_fields_old(rec);
ut_a(fields > 4); ut_a(fields > 4);
...@@ -1371,18 +1393,29 @@ ibuf_rec_get_info( ...@@ -1371,18 +1393,29 @@ ibuf_rec_get_info(
} }
} }
#ifdef UNIV_DEBUG
# define ibuf_rec_get_op_type(mtr,rec) ibuf_rec_get_op_type_func(mtr,rec)
#else /* UNIV_DEBUG */
# define ibuf_rec_get_op_type(mtr,rec) ibuf_rec_get_op_type_func(rec)
#endif
/****************************************************************//** /****************************************************************//**
Returns the operation type field of an ibuf record. Returns the operation type field of an ibuf record.
@return operation type */ @return operation type */
static static
ibuf_op_t ibuf_op_t
ibuf_rec_get_op_type( ibuf_rec_get_op_type_func(
/*=================*/ /*======================*/
#ifdef UNIV_DEBUG
mtr_t* mtr, /*!< in: mini-transaction owning rec */
#endif /* UNIV_DEBUG */
const rec_t* rec) /*!< in: ibuf record */ const rec_t* rec) /*!< in: ibuf record */
{ {
ulint len; ulint len;
ut_ad(ibuf_inside()); ut_ad(mtr_memo_contains_page(mtr, rec, MTR_MEMO_PAGE_X_FIX)
|| mtr_memo_contains_page(mtr, rec, MTR_MEMO_PAGE_S_FIX));
ut_ad(ibuf_inside(mtr));
ut_ad(rec_get_n_fields_old(rec) > 2); ut_ad(rec_get_n_fields_old(rec) > 2);
(void) rec_get_nth_field_old(rec, 1, &len); (void) rec_get_nth_field_old(rec, 1, &len);
...@@ -1394,7 +1427,7 @@ ibuf_rec_get_op_type( ...@@ -1394,7 +1427,7 @@ ibuf_rec_get_op_type(
} else { } else {
ibuf_op_t op; ibuf_op_t op;
ibuf_rec_get_info(rec, &op, NULL, NULL, NULL); ibuf_rec_get_info(mtr, rec, &op, NULL, NULL, NULL);
return(op); return(op);
} }
...@@ -1593,6 +1626,14 @@ ibuf_build_entry_pre_4_1_x( ...@@ -1593,6 +1626,14 @@ ibuf_build_entry_pre_4_1_x(
return(tuple); return(tuple);
} }
#ifdef UNIV_DEBUG
# define ibuf_build_entry_from_ibuf_rec(mtr,ibuf_rec,heap,pindex) \
ibuf_build_entry_from_ibuf_rec_func(mtr,ibuf_rec,heap,pindex)
#else /* UNIV_DEBUG */
# define ibuf_build_entry_from_ibuf_rec(mtr,ibuf_rec,heap,pindex) \
ibuf_build_entry_from_ibuf_rec_func(ibuf_rec,heap,pindex)
#endif
/*********************************************************************//** /*********************************************************************//**
Builds the entry used to Builds the entry used to
...@@ -1611,8 +1652,11 @@ hold a latch to the ibuf_rec page as long as the entry is used! ...@@ -1611,8 +1652,11 @@ hold a latch to the ibuf_rec page as long as the entry is used!
@return own: entry to insert to a non-clustered index */ @return own: entry to insert to a non-clustered index */
static static
dtuple_t* dtuple_t*
ibuf_build_entry_from_ibuf_rec( ibuf_build_entry_from_ibuf_rec_func(
/*===========================*/ /*================================*/
#ifdef UNIV_DEBUG
mtr_t* mtr, /*!< in: mini-transaction owning rec */
#endif /* UNIV_DEBUG */
const rec_t* ibuf_rec, /*!< in: record in an insert buffer */ const rec_t* ibuf_rec, /*!< in: record in an insert buffer */
mem_heap_t* heap, /*!< in: heap where built */ mem_heap_t* heap, /*!< in: heap where built */
dict_index_t** pindex) /*!< out, own: dummy index that dict_index_t** pindex) /*!< out, own: dummy index that
...@@ -1629,6 +1673,10 @@ ibuf_build_entry_from_ibuf_rec( ...@@ -1629,6 +1673,10 @@ ibuf_build_entry_from_ibuf_rec(
ulint comp; ulint comp;
dict_index_t* index; dict_index_t* index;
ut_ad(mtr_memo_contains_page(mtr, ibuf_rec, MTR_MEMO_PAGE_X_FIX)
|| mtr_memo_contains_page(mtr, ibuf_rec, MTR_MEMO_PAGE_S_FIX));
ut_ad(ibuf_inside(mtr));
data = rec_get_nth_field_old(ibuf_rec, 1, &len); data = rec_get_nth_field_old(ibuf_rec, 1, &len);
if (len > 1) { if (len > 1) {
...@@ -1649,7 +1697,7 @@ ibuf_build_entry_from_ibuf_rec( ...@@ -1649,7 +1697,7 @@ ibuf_build_entry_from_ibuf_rec(
types = rec_get_nth_field_old(ibuf_rec, 3, &len); types = rec_get_nth_field_old(ibuf_rec, 3, &len);
ibuf_rec_get_info(ibuf_rec, NULL, &comp, &info_len, NULL); ibuf_rec_get_info(mtr, ibuf_rec, NULL, &comp, &info_len, NULL);
index = ibuf_dummy_index_create(n_fields, comp); index = ibuf_dummy_index_create(n_fields, comp);
...@@ -1736,6 +1784,12 @@ ibuf_rec_get_size( ...@@ -1736,6 +1784,12 @@ ibuf_rec_get_size(
return(size); return(size);
} }
#ifdef UNIV_DEBUG
# define ibuf_rec_get_volume(mtr,rec) ibuf_rec_get_volume_func(mtr,rec)
#else /* UNIV_DEBUG */
# define ibuf_rec_get_volume(mtr,rec) ibuf_rec_get_volume_func(rec)
#endif
/********************************************************************//** /********************************************************************//**
Returns the space taken by a stored non-clustered index entry if converted to Returns the space taken by a stored non-clustered index entry if converted to
an index record. an index record.
...@@ -1743,8 +1797,11 @@ an index record. ...@@ -1743,8 +1797,11 @@ an index record.
taken in the page directory */ taken in the page directory */
static static
ulint ulint
ibuf_rec_get_volume( ibuf_rec_get_volume_func(
/*================*/ /*=====================*/
#ifdef UNIV_DEBUG
mtr_t* mtr, /*!< in: mini-transaction owning rec */
#endif /* UNIV_DEBUG */
const rec_t* ibuf_rec)/*!< in: ibuf record */ const rec_t* ibuf_rec)/*!< in: ibuf record */
{ {
ulint len; ulint len;
...@@ -1755,7 +1812,9 @@ ibuf_rec_get_volume( ...@@ -1755,7 +1812,9 @@ ibuf_rec_get_volume(
ibool pre_4_1; ibool pre_4_1;
ulint comp; ulint comp;
ut_ad(ibuf_inside()); ut_ad(mtr_memo_contains_page(mtr, ibuf_rec, MTR_MEMO_PAGE_X_FIX)
|| mtr_memo_contains_page(mtr, ibuf_rec, MTR_MEMO_PAGE_S_FIX));
ut_ad(ibuf_inside(mtr));
ut_ad(rec_get_n_fields_old(ibuf_rec) > 2); ut_ad(rec_get_n_fields_old(ibuf_rec) > 2);
data = rec_get_nth_field_old(ibuf_rec, 1, &len); data = rec_get_nth_field_old(ibuf_rec, 1, &len);
...@@ -1783,7 +1842,7 @@ ibuf_rec_get_volume( ...@@ -1783,7 +1842,7 @@ ibuf_rec_get_volume(
types = rec_get_nth_field_old(ibuf_rec, 3, &len); types = rec_get_nth_field_old(ibuf_rec, 3, &len);
ibuf_rec_get_info(ibuf_rec, &op, &comp, &info_len, NULL); ibuf_rec_get_info(mtr, ibuf_rec, &op, &comp, &info_len, NULL);
if (op == IBUF_OP_DELETE_MARK || op == IBUF_OP_DELETE) { if (op == IBUF_OP_DELETE_MARK || op == IBUF_OP_DELETE) {
/* Delete-marking a record doesn't take any /* Delete-marking a record doesn't take any
...@@ -1800,7 +1859,7 @@ ibuf_rec_get_volume( ...@@ -1800,7 +1859,7 @@ ibuf_rec_get_volume(
mem_heap_t* heap = mem_heap_create(500); mem_heap_t* heap = mem_heap_create(500);
entry = ibuf_build_entry_from_ibuf_rec( entry = ibuf_build_entry_from_ibuf_rec(
ibuf_rec, heap, &dummy_index); mtr, ibuf_rec, heap, &dummy_index);
volume = rec_get_converted_size(dummy_index, entry, 0); volume = rec_get_converted_size(dummy_index, entry, 0);
...@@ -2158,21 +2217,15 @@ ibuf_add_free_page(void) ...@@ -2158,21 +2217,15 @@ ibuf_add_free_page(void)
mtr_commit(&mtr); mtr_commit(&mtr);
return(FALSE); return(FALSE);
} } else {
buf_block_t* block = buf_page_get(
{
buf_block_t* block;
block = buf_page_get(
IBUF_SPACE_ID, 0, page_no, RW_X_LATCH, &mtr); IBUF_SPACE_ID, 0, page_no, RW_X_LATCH, &mtr);
buf_block_dbg_add_level(block, SYNC_TREE_NODE_NEW); buf_block_dbg_add_level(block, SYNC_TREE_NODE_NEW);
page = buf_block_get_frame(block); page = buf_block_get_frame(block);
} }
ibuf_enter(); ibuf_enter(&mtr);
mutex_enter(&ibuf_mutex); mutex_enter(&ibuf_mutex);
...@@ -2200,9 +2253,7 @@ ibuf_add_free_page(void) ...@@ -2200,9 +2253,7 @@ ibuf_add_free_page(void)
ibuf_bitmap_page_set_bits( ibuf_bitmap_page_set_bits(
bitmap_page, page_no, zip_size, IBUF_BITMAP_IBUF, TRUE, &mtr); bitmap_page, page_no, zip_size, IBUF_BITMAP_IBUF, TRUE, &mtr);
mtr_commit(&mtr); ibuf_mtr_commit(&mtr);
ibuf_exit();
return(TRUE); return(TRUE);
} }
...@@ -2234,7 +2285,7 @@ ibuf_remove_free_page(void) ...@@ -2234,7 +2285,7 @@ ibuf_remove_free_page(void)
header_page = ibuf_header_page_get(&mtr); header_page = ibuf_header_page_get(&mtr);
/* Prevent pessimistic inserts to insert buffer trees for a while */ /* Prevent pessimistic inserts to insert buffer trees for a while */
ibuf_enter(); ibuf_enter(&mtr);
mutex_enter(&ibuf_pessimistic_insert_mutex); mutex_enter(&ibuf_pessimistic_insert_mutex);
mutex_enter(&ibuf_mutex); mutex_enter(&ibuf_mutex);
...@@ -2243,14 +2294,12 @@ ibuf_remove_free_page(void) ...@@ -2243,14 +2294,12 @@ ibuf_remove_free_page(void)
mutex_exit(&ibuf_mutex); mutex_exit(&ibuf_mutex);
mutex_exit(&ibuf_pessimistic_insert_mutex); mutex_exit(&ibuf_pessimistic_insert_mutex);
ibuf_exit(); ibuf_mtr_commit(&mtr);
mtr_commit(&mtr);
return; return;
} }
mtr_start(&mtr2); ibuf_mtr_start(&mtr2);
root = ibuf_tree_root_get(&mtr2); root = ibuf_tree_root_get(&mtr2);
...@@ -2263,9 +2312,8 @@ ibuf_remove_free_page(void) ...@@ -2263,9 +2312,8 @@ ibuf_remove_free_page(void)
because in fseg_free_page we access level 1 pages, and the root because in fseg_free_page we access level 1 pages, and the root
is a level 2 page. */ is a level 2 page. */
mtr_commit(&mtr2); ibuf_mtr_commit(&mtr2);
ibuf_exit(&mtr);
ibuf_exit();
/* Since pessimistic inserts were prevented, we know that the /* Since pessimistic inserts were prevented, we know that the
page is still in the free list. NOTE that also deletes may take page is still in the free list. NOTE that also deletes may take
...@@ -2280,7 +2328,7 @@ ibuf_remove_free_page(void) ...@@ -2280,7 +2328,7 @@ ibuf_remove_free_page(void)
buf_page_reset_file_page_was_freed(IBUF_SPACE_ID, page_no); buf_page_reset_file_page_was_freed(IBUF_SPACE_ID, page_no);
#endif /* UNIV_DEBUG_FILE_ACCESSES || UNIV_DEBUG */ #endif /* UNIV_DEBUG_FILE_ACCESSES || UNIV_DEBUG */
ibuf_enter(); ibuf_enter(&mtr);
mutex_enter(&ibuf_mutex); mutex_enter(&ibuf_mutex);
...@@ -2325,9 +2373,7 @@ ibuf_remove_free_page(void) ...@@ -2325,9 +2373,7 @@ ibuf_remove_free_page(void)
#if defined UNIV_DEBUG_FILE_ACCESSES || defined UNIV_DEBUG #if defined UNIV_DEBUG_FILE_ACCESSES || defined UNIV_DEBUG
buf_page_set_file_page_was_freed(IBUF_SPACE_ID, page_no); buf_page_set_file_page_was_freed(IBUF_SPACE_ID, page_no);
#endif /* UNIV_DEBUG_FILE_ACCESSES || UNIV_DEBUG */ #endif /* UNIV_DEBUG_FILE_ACCESSES || UNIV_DEBUG */
mtr_commit(&mtr); ibuf_mtr_commit(&mtr);
ibuf_exit();
} }
/***********************************************************************//** /***********************************************************************//**
...@@ -2349,8 +2395,6 @@ ibuf_free_excess_pages(void) ...@@ -2349,8 +2395,6 @@ ibuf_free_excess_pages(void)
ut_ad(rw_lock_get_x_lock_count( ut_ad(rw_lock_get_x_lock_count(
fil_space_get_latch(IBUF_SPACE_ID, NULL)) == 1); fil_space_get_latch(IBUF_SPACE_ID, NULL)) == 1);
ut_ad(!ibuf_inside());
/* NOTE: We require that the thread did not own the latch before, /* NOTE: We require that the thread did not own the latch before,
because then we know that we can obey the correct latching order because then we know that we can obey the correct latching order
for ibuf latches */ for ibuf latches */
...@@ -2381,20 +2425,30 @@ ibuf_free_excess_pages(void) ...@@ -2381,20 +2425,30 @@ ibuf_free_excess_pages(void)
} }
} }
#ifdef UNIV_DEBUG
# define ibuf_get_merge_page_nos(contract,rec,mtr,ids,vers,pages,n_stored) \
ibuf_get_merge_page_nos_func(contract,rec,mtr,ids,vers,pages,n_stored)
#else /* UNIV_DEBUG */
# define ibuf_get_merge_page_nos(contract,rec,mtr,ids,vers,pages,n_stored) \
ibuf_get_merge_page_nos_func(contract,rec,ids,vers,pages,n_stored)
#endif /* UNIV_DEBUG */
/*********************************************************************//** /*********************************************************************//**
Reads page numbers from a leaf in an ibuf tree. Reads page numbers from a leaf in an ibuf tree.
@return a lower limit for the combined volume of records which will be @return a lower limit for the combined volume of records which will be
merged */ merged */
static static
ulint ulint
ibuf_get_merge_page_nos( ibuf_get_merge_page_nos_func(
/*====================*/ /*=========================*/
ibool contract,/*!< in: TRUE if this function is called to ibool contract,/*!< in: TRUE if this function is called to
contract the tree, FALSE if this is called contract the tree, FALSE if this is called
when a single page becomes full and we look when a single page becomes full and we look
if it pays to read also nearby pages */ if it pays to read also nearby pages */
rec_t* rec, /*!< in: record from which we read up and down const rec_t* rec, /*!< in: insert buffer record */
in the chain of records */ #ifdef UNIV_DEBUG
mtr_t* mtr, /*!< in: mini-transaction holding rec */
#endif /* UNIV_DEBUG */
ulint* space_ids,/*!< in/out: space id's of the pages */ ulint* space_ids,/*!< in/out: space id's of the pages */
ib_int64_t* space_versions,/*!< in/out: tablespace version ib_int64_t* space_versions,/*!< in/out: tablespace version
timestamps; used to prevent reading in old timestamps; used to prevent reading in old
...@@ -2417,18 +2471,22 @@ ibuf_get_merge_page_nos( ...@@ -2417,18 +2471,22 @@ ibuf_get_merge_page_nos(
ulint limit; ulint limit;
ulint n_pages; ulint n_pages;
ut_ad(mtr_memo_contains_page(mtr, rec, MTR_MEMO_PAGE_X_FIX)
|| mtr_memo_contains_page(mtr, rec, MTR_MEMO_PAGE_S_FIX));
ut_ad(ibuf_inside(mtr));
*n_stored = 0; *n_stored = 0;
limit = ut_min(IBUF_MAX_N_PAGES_MERGED, buf_pool_get_curr_size() / 4); limit = ut_min(IBUF_MAX_N_PAGES_MERGED, buf_pool_get_curr_size() / 4);
if (page_rec_is_supremum(rec)) { if (page_rec_is_supremum(rec)) {
rec = page_rec_get_prev(rec); rec = page_rec_get_prev_const(rec);
} }
if (page_rec_is_infimum(rec)) { if (page_rec_is_infimum(rec)) {
rec = page_rec_get_next(rec); rec = page_rec_get_next_const(rec);
} }
if (page_rec_is_supremum(rec)) { if (page_rec_is_supremum(rec)) {
...@@ -2436,8 +2494,8 @@ ibuf_get_merge_page_nos( ...@@ -2436,8 +2494,8 @@ ibuf_get_merge_page_nos(
return(0); return(0);
} }
first_page_no = ibuf_rec_get_page_no(rec); first_page_no = ibuf_rec_get_page_no(mtr, rec);
first_space_id = ibuf_rec_get_space(rec); first_space_id = ibuf_rec_get_space(mtr, rec);
n_pages = 0; n_pages = 0;
prev_page_no = 0; prev_page_no = 0;
prev_space_id = 0; prev_space_id = 0;
...@@ -2448,8 +2506,8 @@ ibuf_get_merge_page_nos( ...@@ -2448,8 +2506,8 @@ ibuf_get_merge_page_nos(
while (!page_rec_is_infimum(rec) && UNIV_LIKELY(n_pages < limit)) { while (!page_rec_is_infimum(rec) && UNIV_LIKELY(n_pages < limit)) {
rec_page_no = ibuf_rec_get_page_no(rec); rec_page_no = ibuf_rec_get_page_no(mtr, rec);
rec_space_id = ibuf_rec_get_space(rec); rec_space_id = ibuf_rec_get_space(mtr, rec);
if (rec_space_id != first_space_id if (rec_space_id != first_space_id
|| (rec_page_no / IBUF_MERGE_AREA) || (rec_page_no / IBUF_MERGE_AREA)
...@@ -2466,10 +2524,10 @@ ibuf_get_merge_page_nos( ...@@ -2466,10 +2524,10 @@ ibuf_get_merge_page_nos(
prev_page_no = rec_page_no; prev_page_no = rec_page_no;
prev_space_id = rec_space_id; prev_space_id = rec_space_id;
rec = page_rec_get_prev(rec); rec = page_rec_get_prev_const(rec);
} }
rec = page_rec_get_next(rec); rec = page_rec_get_next_const(rec);
/* At the loop start there is no prev page; we mark this with a pair /* At the loop start there is no prev page; we mark this with a pair
of space id, page no (0, 0) for which there can never be entries in of space id, page no (0, 0) for which there can never be entries in
...@@ -2487,8 +2545,8 @@ ibuf_get_merge_page_nos( ...@@ -2487,8 +2545,8 @@ ibuf_get_merge_page_nos(
rec_page_no = 1; rec_page_no = 1;
rec_space_id = 0; rec_space_id = 0;
} else { } else {
rec_page_no = ibuf_rec_get_page_no(rec); rec_page_no = ibuf_rec_get_page_no(mtr, rec);
rec_space_id = ibuf_rec_get_space(rec); rec_space_id = ibuf_rec_get_space(mtr, rec);
ut_ad(rec_page_no > IBUF_TREE_ROOT_PAGE_NO); ut_ad(rec_page_no > IBUF_TREE_ROOT_PAGE_NO);
} }
...@@ -2499,9 +2557,9 @@ ibuf_get_merge_page_nos( ...@@ -2499,9 +2557,9 @@ ibuf_get_merge_page_nos(
|| rec_page_no != prev_page_no) || rec_page_no != prev_page_no)
&& (prev_space_id != 0 || prev_page_no != 0)) { && (prev_space_id != 0 || prev_page_no != 0)) {
if ((prev_page_no == first_page_no if (contract
&& prev_space_id == first_space_id) || (prev_page_no == first_page_no
|| contract && prev_space_id == first_space_id)
|| (volume_for_page || (volume_for_page
> ((IBUF_MERGE_THRESHOLD - 1) > ((IBUF_MERGE_THRESHOLD - 1)
* 4 * UNIV_PAGE_SIZE * 4 * UNIV_PAGE_SIZE
...@@ -2534,14 +2592,14 @@ ibuf_get_merge_page_nos( ...@@ -2534,14 +2592,14 @@ ibuf_get_merge_page_nos(
break; break;
} }
rec_volume = ibuf_rec_get_volume(rec); rec_volume = ibuf_rec_get_volume(mtr, rec);
volume_for_page += rec_volume; volume_for_page += rec_volume;
prev_page_no = rec_page_no; prev_page_no = rec_page_no;
prev_space_id = rec_space_id; prev_space_id = rec_space_id;
rec = page_rec_get_next(rec); rec = page_rec_get_next_const(rec);
} }
#ifdef UNIV_IBUF_DEBUG #ifdef UNIV_IBUF_DEBUG
...@@ -2576,7 +2634,6 @@ ibuf_contract_ext( ...@@ -2576,7 +2634,6 @@ ibuf_contract_ext(
mtr_t mtr; mtr_t mtr;
*n_pages = 0; *n_pages = 0;
ut_ad(!ibuf_inside());
/* We perform a dirty read of ibuf->empty, without latching /* We perform a dirty read of ibuf->empty, without latching
the insert buffer root page. We trust this dirty read except the insert buffer root page. We trust this dirty read except
...@@ -2588,9 +2645,7 @@ ibuf_contract_ext( ...@@ -2588,9 +2645,7 @@ ibuf_contract_ext(
return(0); return(0);
} }
mtr_start(&mtr); ibuf_mtr_start(&mtr);
ibuf_enter();
/* Open a cursor to a randomly chosen leaf of the tree, at a random /* Open a cursor to a randomly chosen leaf of the tree, at a random
position within the leaf */ position within the leaf */
...@@ -2609,24 +2664,21 @@ ibuf_contract_ext( ...@@ -2609,24 +2664,21 @@ ibuf_contract_ext(
ut_ad(page_get_page_no(btr_pcur_get_page(&pcur)) ut_ad(page_get_page_no(btr_pcur_get_page(&pcur))
== FSP_IBUF_TREE_ROOT_PAGE_NO); == FSP_IBUF_TREE_ROOT_PAGE_NO);
ibuf_exit(); ibuf_mtr_commit(&mtr);
mtr_commit(&mtr);
btr_pcur_close(&pcur); btr_pcur_close(&pcur);
return(0); return(0);
} }
sum_sizes = ibuf_get_merge_page_nos(TRUE, btr_pcur_get_rec(&pcur), sum_sizes = ibuf_get_merge_page_nos(TRUE,
btr_pcur_get_rec(&pcur), &mtr,
space_ids, space_versions, space_ids, space_versions,
page_nos, n_pages); page_nos, n_pages);
#if 0 /* defined UNIV_IBUF_DEBUG */ #if 0 /* defined UNIV_IBUF_DEBUG */
fprintf(stderr, "Ibuf contract sync %lu pages %lu volume %lu\n", fprintf(stderr, "Ibuf contract sync %lu pages %lu volume %lu\n",
sync, *n_pages, sum_sizes); sync, *n_pages, sum_sizes);
#endif #endif
ibuf_exit(); ibuf_mtr_commit(&mtr);
mtr_commit(&mtr);
btr_pcur_close(&pcur); btr_pcur_close(&pcur);
buf_read_ibuf_merge_pages(sync, space_ids, space_versions, page_nos, buf_read_ibuf_merge_pages(sync, space_ids, space_versions, page_nos,
...@@ -2766,6 +2818,13 @@ ibuf_get_volume_buffered_hash( ...@@ -2766,6 +2818,13 @@ ibuf_get_volume_buffered_hash(
return(TRUE); return(TRUE);
} }
#ifdef UNIV_DEBUG
# define ibuf_get_volume_buffered_count(mtr,rec,hash,size,n_recs) \
ibuf_get_volume_buffered_count_func(mtr,rec,hash,size,n_recs)
#else /* UNIV_DEBUG */
# define ibuf_get_volume_buffered_count(mtr,rec,hash,size,n_recs) \
ibuf_get_volume_buffered_count_func(rec,hash,size,n_recs)
#endif
/*********************************************************************//** /*********************************************************************//**
Update the estimate of the number of records on a page, and Update the estimate of the number of records on a page, and
get the space taken by merging the buffered record to the index page. get the space taken by merging the buffered record to the index page.
...@@ -2773,8 +2832,11 @@ get the space taken by merging the buffered record to the index page. ...@@ -2773,8 +2832,11 @@ get the space taken by merging the buffered record to the index page.
taken in the page directory */ taken in the page directory */
static static
ulint ulint
ibuf_get_volume_buffered_count( ibuf_get_volume_buffered_count_func(
/*===========================*/ /*================================*/
#ifdef UNIV_DEBUG
mtr_t* mtr, /*!< in: mini-transaction owning rec */
#endif /* UNIV_DEBUG */
const rec_t* rec, /*!< in: insert buffer record */ const rec_t* rec, /*!< in: insert buffer record */
ulint* hash, /*!< in/out: hash array */ ulint* hash, /*!< in/out: hash array */
ulint size, /*!< in: number of elements in hash array */ ulint size, /*!< in: number of elements in hash array */
...@@ -2784,9 +2846,13 @@ ibuf_get_volume_buffered_count( ...@@ -2784,9 +2846,13 @@ ibuf_get_volume_buffered_count(
ulint len; ulint len;
ibuf_op_t ibuf_op; ibuf_op_t ibuf_op;
const byte* types; const byte* types;
ulint n_fields = rec_get_n_fields_old(rec); ulint n_fields;
ut_ad(ibuf_inside()); ut_ad(mtr_memo_contains_page(mtr, rec, MTR_MEMO_PAGE_X_FIX)
|| mtr_memo_contains_page(mtr, rec, MTR_MEMO_PAGE_S_FIX));
ut_ad(ibuf_inside(mtr));
n_fields = rec_get_n_fields_old(rec);
ut_ad(n_fields > 4); ut_ad(n_fields > 4);
n_fields -= 4; n_fields -= 4;
...@@ -2871,7 +2937,7 @@ get_volume_comp: ...@@ -2871,7 +2937,7 @@ get_volume_comp:
mem_heap_t* heap = mem_heap_create(500); mem_heap_t* heap = mem_heap_create(500);
entry = ibuf_build_entry_from_ibuf_rec( entry = ibuf_build_entry_from_ibuf_rec(
rec, heap, &dummy_index); mtr, rec, heap, &dummy_index);
volume = rec_get_converted_size(dummy_index, entry, 0); volume = rec_get_converted_size(dummy_index, entry, 0);
...@@ -2892,7 +2958,7 @@ static ...@@ -2892,7 +2958,7 @@ static
ulint ulint
ibuf_get_volume_buffered( ibuf_get_volume_buffered(
/*=====================*/ /*=====================*/
btr_pcur_t* pcur, /*!< in: pcur positioned at a place in an const btr_pcur_t*pcur, /*!< in: pcur positioned at a place in an
insert buffer tree where we would insert an insert buffer tree where we would insert an
entry for the index page whose number is entry for the index page whose number is
page_no, latch mode has to be BTR_MODIFY_PREV page_no, latch mode has to be BTR_MODIFY_PREV
...@@ -2902,16 +2968,17 @@ ibuf_get_volume_buffered( ...@@ -2902,16 +2968,17 @@ ibuf_get_volume_buffered(
lint* n_recs, /*!< in/out: minimum number of records on the lint* n_recs, /*!< in/out: minimum number of records on the
page after the buffered changes have been page after the buffered changes have been
applied, or NULL to disable the counting */ applied, or NULL to disable the counting */
mtr_t* mtr) /*!< in: mtr */ mtr_t* mtr) /*!< in: mini-transaction of pcur */
{ {
ulint volume; ulint volume;
rec_t* rec; const rec_t* rec;
page_t* page; const page_t* page;
ulint prev_page_no; ulint prev_page_no;
page_t* prev_page; const page_t* prev_page;
ulint next_page_no; ulint next_page_no;
page_t* next_page; const page_t* next_page;
ulint hash_bitmap[128 / sizeof(ulint)]; /* bitmap of buffered recs */ /* bitmap of buffered recs */
ulint hash_bitmap[128 / sizeof(ulint)];
ut_a(trx_sys_multiple_tablespace_format); ut_a(trx_sys_multiple_tablespace_format);
...@@ -2932,26 +2999,22 @@ ibuf_get_volume_buffered( ...@@ -2932,26 +2999,22 @@ ibuf_get_volume_buffered(
ut_ad(page_validate(page, ibuf->index)); ut_ad(page_validate(page, ibuf->index));
if (page_rec_is_supremum(rec)) { if (page_rec_is_supremum(rec)) {
rec = page_rec_get_prev(rec); rec = page_rec_get_prev_const(rec);
} }
for (;;) { for (; !page_rec_is_infimum(rec);
if (page_rec_is_infimum(rec)) { rec = page_rec_get_prev_const(rec)) {
ut_ad(page_align(rec) == page);
break;
}
if (page_no != ibuf_rec_get_page_no(rec) if (page_no != ibuf_rec_get_page_no(mtr, rec)
|| space != ibuf_rec_get_space(rec)) { || space != ibuf_rec_get_space(mtr, rec)) {
goto count_later; goto count_later;
} }
volume += ibuf_get_volume_buffered_count( volume += ibuf_get_volume_buffered_count(
rec, hash_bitmap, UT_ARR_SIZE(hash_bitmap), n_recs); mtr, rec,
hash_bitmap, UT_ARR_SIZE(hash_bitmap), n_recs);
rec = page_rec_get_prev(rec);
ut_ad(page_align(rec) == page);
} }
/* Look at the previous page */ /* Look at the previous page */
...@@ -2967,7 +3030,8 @@ ibuf_get_volume_buffered( ...@@ -2967,7 +3030,8 @@ ibuf_get_volume_buffered(
buf_block_t* block; buf_block_t* block;
block = buf_page_get( block = buf_page_get(
IBUF_SPACE_ID, 0, prev_page_no, RW_X_LATCH, mtr); IBUF_SPACE_ID, 0, prev_page_no, RW_X_LATCH,
mtr);
buf_block_dbg_add_level(block, SYNC_TREE_NODE); buf_block_dbg_add_level(block, SYNC_TREE_NODE);
...@@ -2977,14 +3041,15 @@ ibuf_get_volume_buffered( ...@@ -2977,14 +3041,15 @@ ibuf_get_volume_buffered(
} }
#ifdef UNIV_BTR_DEBUG #ifdef UNIV_BTR_DEBUG
ut_a(btr_page_get_next(prev_page, mtr) ut_a(btr_page_get_next(prev_page, mtr) == page_get_page_no(page));
== page_get_page_no(page));
#endif /* UNIV_BTR_DEBUG */ #endif /* UNIV_BTR_DEBUG */
rec = page_get_supremum_rec(prev_page); rec = page_get_supremum_rec(prev_page);
rec = page_rec_get_prev(rec); rec = page_rec_get_prev_const(rec);
for (;; rec = page_rec_get_prev_const(rec)) {
ut_ad(page_align(rec) == prev_page);
for (;;) {
if (page_rec_is_infimum(rec)) { if (page_rec_is_infimum(rec)) {
/* We cannot go to yet a previous page, because we /* We cannot go to yet a previous page, because we
...@@ -2994,42 +3059,35 @@ ibuf_get_volume_buffered( ...@@ -2994,42 +3059,35 @@ ibuf_get_volume_buffered(
return(UNIV_PAGE_SIZE); return(UNIV_PAGE_SIZE);
} }
if (page_no != ibuf_rec_get_page_no(rec) if (page_no != ibuf_rec_get_page_no(mtr, rec)
|| space != ibuf_rec_get_space(rec)) { || space != ibuf_rec_get_space(mtr, rec)) {
goto count_later; goto count_later;
} }
volume += ibuf_get_volume_buffered_count( volume += ibuf_get_volume_buffered_count(
rec, hash_bitmap, UT_ARR_SIZE(hash_bitmap), n_recs); mtr, rec,
hash_bitmap, UT_ARR_SIZE(hash_bitmap), n_recs);
rec = page_rec_get_prev(rec);
ut_ad(page_align(rec) == prev_page);
} }
count_later: count_later:
rec = btr_pcur_get_rec(pcur); rec = btr_pcur_get_rec(pcur);
if (!page_rec_is_supremum(rec)) { if (!page_rec_is_supremum(rec)) {
rec = page_rec_get_next(rec); rec = page_rec_get_next_const(rec);
} }
for (;;) { for (; !page_rec_is_supremum(rec);
if (page_rec_is_supremum(rec)) { rec = page_rec_get_next_const(rec)) {
if (page_no != ibuf_rec_get_page_no(mtr, rec)
break; || space != ibuf_rec_get_space(mtr, rec)) {
}
if (page_no != ibuf_rec_get_page_no(rec)
|| space != ibuf_rec_get_space(rec)) {
return(volume); return(volume);
} }
volume += ibuf_get_volume_buffered_count( volume += ibuf_get_volume_buffered_count(
rec, hash_bitmap, UT_ARR_SIZE(hash_bitmap), n_recs); mtr, rec,
hash_bitmap, UT_ARR_SIZE(hash_bitmap), n_recs);
rec = page_rec_get_next(rec);
} }
/* Look at the next page */ /* Look at the next page */
...@@ -3045,7 +3103,8 @@ count_later: ...@@ -3045,7 +3103,8 @@ count_later:
buf_block_t* block; buf_block_t* block;
block = buf_page_get( block = buf_page_get(
IBUF_SPACE_ID, 0, next_page_no, RW_X_LATCH, mtr); IBUF_SPACE_ID, 0, next_page_no, RW_X_LATCH,
mtr);
buf_block_dbg_add_level(block, SYNC_TREE_NODE); buf_block_dbg_add_level(block, SYNC_TREE_NODE);
...@@ -3059,9 +3118,11 @@ count_later: ...@@ -3059,9 +3118,11 @@ count_later:
#endif /* UNIV_BTR_DEBUG */ #endif /* UNIV_BTR_DEBUG */
rec = page_get_infimum_rec(next_page); rec = page_get_infimum_rec(next_page);
rec = page_rec_get_next(rec); rec = page_rec_get_next_const(rec);
for (;; rec = page_rec_get_next_const(rec)) {
ut_ad(page_align(rec) == next_page);
for (;;) {
if (page_rec_is_supremum(rec)) { if (page_rec_is_supremum(rec)) {
/* We give up */ /* We give up */
...@@ -3069,17 +3130,15 @@ count_later: ...@@ -3069,17 +3130,15 @@ count_later:
return(UNIV_PAGE_SIZE); return(UNIV_PAGE_SIZE);
} }
if (page_no != ibuf_rec_get_page_no(rec) if (page_no != ibuf_rec_get_page_no(mtr, rec)
|| space != ibuf_rec_get_space(rec)) { || space != ibuf_rec_get_space(mtr, rec)) {
return(volume); return(volume);
} }
volume += ibuf_get_volume_buffered_count( volume += ibuf_get_volume_buffered_count(
rec, hash_bitmap, UT_ARR_SIZE(hash_bitmap), n_recs); mtr, rec,
hash_bitmap, UT_ARR_SIZE(hash_bitmap), n_recs);
rec = page_rec_get_next(rec);
ut_ad(page_align(rec) == next_page);
} }
} }
...@@ -3100,9 +3159,7 @@ ibuf_update_max_tablespace_id(void) ...@@ -3100,9 +3159,7 @@ ibuf_update_max_tablespace_id(void)
ut_a(!dict_table_is_comp(ibuf->index->table)); ut_a(!dict_table_is_comp(ibuf->index->table));
ibuf_enter(); ibuf_mtr_start(&mtr);
mtr_start(&mtr);
btr_pcur_open_at_index_side( btr_pcur_open_at_index_side(
FALSE, ibuf->index, BTR_SEARCH_LEAF, &pcur, TRUE, &mtr); FALSE, ibuf->index, BTR_SEARCH_LEAF, &pcur, TRUE, &mtr);
...@@ -3125,14 +3182,20 @@ ibuf_update_max_tablespace_id(void) ...@@ -3125,14 +3182,20 @@ ibuf_update_max_tablespace_id(void)
max_space_id = mach_read_from_4(field); max_space_id = mach_read_from_4(field);
} }
mtr_commit(&mtr); ibuf_mtr_commit(&mtr);
ibuf_exit();
/* printf("Maximum space id in insert buffer %lu\n", max_space_id); */ /* printf("Maximum space id in insert buffer %lu\n", max_space_id); */
fil_set_max_space_id_if_bigger(max_space_id); fil_set_max_space_id_if_bigger(max_space_id);
} }
#ifdef UNIV_DEBUG
# define ibuf_get_entry_counter_low(mtr,rec,space,page_no) \
ibuf_get_entry_counter_low_func(mtr,rec,space,page_no)
#else /* UNIV_DEBUG */
# define ibuf_get_entry_counter_low(mtr,rec,space,page_no) \
ibuf_get_entry_counter_low_func(rec,space,page_no)
#endif
/****************************************************************//** /****************************************************************//**
Helper function for ibuf_set_entry_counter. Checks if rec is for (space, Helper function for ibuf_set_entry_counter. Checks if rec is for (space,
page_no), and if so, reads counter value from it and returns that + 1. page_no), and if so, reads counter value from it and returns that + 1.
...@@ -3140,8 +3203,11 @@ Otherwise, returns 0. ...@@ -3140,8 +3203,11 @@ Otherwise, returns 0.
@return new counter value, or 0 */ @return new counter value, or 0 */
static static
ulint ulint
ibuf_get_entry_counter_low( ibuf_get_entry_counter_low_func(
/*=======================*/ /*============================*/
#ifdef UNIV_DEBUG
mtr_t* mtr, /*!< in: mini-transaction of rec */
#endif /* UNIV_DEBUG */
const rec_t* rec, /*!< in: insert buffer record */ const rec_t* rec, /*!< in: insert buffer record */
ulint space, /*!< in: space id */ ulint space, /*!< in: space id */
ulint page_no) /*!< in: page number */ ulint page_no) /*!< in: page number */
...@@ -3150,7 +3216,9 @@ ibuf_get_entry_counter_low( ...@@ -3150,7 +3216,9 @@ ibuf_get_entry_counter_low(
const byte* field; const byte* field;
ulint len; ulint len;
ut_ad(ibuf_inside()); ut_ad(ibuf_inside(mtr));
ut_ad(mtr_memo_contains_page(mtr, rec, MTR_MEMO_PAGE_X_FIX)
|| mtr_memo_contains_page(mtr, rec, MTR_MEMO_PAGE_S_FIX));
ut_ad(rec_get_n_fields_old(rec) > 2); ut_ad(rec_get_n_fields_old(rec) > 2);
field = rec_get_nth_field_old(rec, 1, &len); field = rec_get_nth_field_old(rec, 1, &len);
...@@ -3222,12 +3290,15 @@ ibuf_set_entry_counter( ...@@ -3222,12 +3290,15 @@ ibuf_set_entry_counter(
ulint counter = 0; ulint counter = 0;
/* pcur points to either a user rec or to a page's infimum record. */ /* pcur points to either a user rec or to a page's infimum record. */
ut_ad(ibuf_inside(mtr));
ut_ad(mtr_memo_contains(mtr, btr_pcur_get_block(pcur),
MTR_MEMO_PAGE_X_FIX));
ut_ad(page_validate(btr_pcur_get_page(pcur), ibuf->index)); ut_ad(page_validate(btr_pcur_get_page(pcur), ibuf->index));
if (btr_pcur_is_on_user_rec(pcur)) { if (btr_pcur_is_on_user_rec(pcur)) {
counter = ibuf_get_entry_counter_low( counter = ibuf_get_entry_counter_low(
btr_pcur_get_rec(pcur), space, page_no); mtr, btr_pcur_get_rec(pcur), space, page_no);
if (UNIV_UNLIKELY(counter == ULINT_UNDEFINED)) { if (UNIV_UNLIKELY(counter == ULINT_UNDEFINED)) {
/* The record lacks a counter field. /* The record lacks a counter field.
...@@ -3283,7 +3354,7 @@ ibuf_set_entry_counter( ...@@ -3283,7 +3354,7 @@ ibuf_set_entry_counter(
ut_ad(page_rec_is_user_rec(rec)); ut_ad(page_rec_is_user_rec(rec));
counter = ibuf_get_entry_counter_low( counter = ibuf_get_entry_counter_low(
rec, space, page_no); mtr, rec, space, page_no);
if (UNIV_UNLIKELY(counter == ULINT_UNDEFINED)) { if (UNIV_UNLIKELY(counter == ULINT_UNDEFINED)) {
/* The record lacks a counter field. /* The record lacks a counter field.
...@@ -3435,7 +3506,6 @@ ibuf_insert_low( ...@@ -3435,7 +3506,6 @@ ibuf_insert_low(
if (mode == BTR_MODIFY_TREE) { if (mode == BTR_MODIFY_TREE) {
for (;;) { for (;;) {
ibuf_enter();
mutex_enter(&ibuf_pessimistic_insert_mutex); mutex_enter(&ibuf_pessimistic_insert_mutex);
mutex_enter(&ibuf_mutex); mutex_enter(&ibuf_mutex);
...@@ -3446,7 +3516,6 @@ ibuf_insert_low( ...@@ -3446,7 +3516,6 @@ ibuf_insert_low(
mutex_exit(&ibuf_mutex); mutex_exit(&ibuf_mutex);
mutex_exit(&ibuf_pessimistic_insert_mutex); mutex_exit(&ibuf_pessimistic_insert_mutex);
ibuf_exit();
if (UNIV_UNLIKELY(!ibuf_add_free_page())) { if (UNIV_UNLIKELY(!ibuf_add_free_page())) {
...@@ -3454,11 +3523,9 @@ ibuf_insert_low( ...@@ -3454,11 +3523,9 @@ ibuf_insert_low(
return(DB_STRONG_FAIL); return(DB_STRONG_FAIL);
} }
} }
} else {
ibuf_enter();
} }
mtr_start(&mtr); ibuf_mtr_start(&mtr);
btr_pcur_open(ibuf->index, ibuf_entry, PAGE_CUR_LE, mode, &pcur, &mtr); btr_pcur_open(ibuf->index, ibuf_entry, PAGE_CUR_LE, mode, &pcur, &mtr);
ut_ad(page_validate(btr_pcur_get_page(&pcur), ibuf->index)); ut_ad(page_validate(btr_pcur_get_page(&pcur), ibuf->index));
...@@ -3513,7 +3580,7 @@ fail_exit: ...@@ -3513,7 +3580,7 @@ fail_exit:
#ifdef UNIV_IBUF_COUNT_DEBUG #ifdef UNIV_IBUF_COUNT_DEBUG
ut_a((buffered == 0) || ibuf_count_get(space, page_no)); ut_a((buffered == 0) || ibuf_count_get(space, page_no));
#endif #endif
mtr_start(&bitmap_mtr); ibuf_mtr_start(&bitmap_mtr);
bitmap_page = ibuf_bitmap_get_map_page(space, page_no, bitmap_page = ibuf_bitmap_get_map_page(space, page_no,
zip_size, &bitmap_mtr); zip_size, &bitmap_mtr);
...@@ -3534,15 +3601,15 @@ fail_exit: ...@@ -3534,15 +3601,15 @@ fail_exit:
if (buffered + entry_size + page_dir_calc_reserved_space(1) if (buffered + entry_size + page_dir_calc_reserved_space(1)
> ibuf_index_page_calc_free_from_bits(zip_size, bits)) { > ibuf_index_page_calc_free_from_bits(zip_size, bits)) {
/* Release the bitmap page latch early. */ /* Release the bitmap page latch early. */
mtr_commit(&bitmap_mtr); ibuf_mtr_commit(&bitmap_mtr);
/* It may not fit */ /* It may not fit */
do_merge = TRUE; do_merge = TRUE;
ibuf_get_merge_page_nos( ibuf_get_merge_page_nos(FALSE,
FALSE, btr_pcur_get_rec(&pcur), btr_pcur_get_rec(&pcur), &mtr,
space_ids, space_versions, space_ids, space_versions,
page_nos, &n_stored); page_nos, &n_stored);
goto fail_exit; goto fail_exit;
} }
...@@ -3555,7 +3622,7 @@ fail_exit: ...@@ -3555,7 +3622,7 @@ fail_exit:
&& !ibuf_set_entry_counter(ibuf_entry, space, page_no, &pcur, && !ibuf_set_entry_counter(ibuf_entry, space, page_no, &pcur,
mode == BTR_MODIFY_PREV, &mtr)) { mode == BTR_MODIFY_PREV, &mtr)) {
bitmap_fail: bitmap_fail:
mtr_commit(&bitmap_mtr); ibuf_mtr_commit(&bitmap_mtr);
goto fail_exit; goto fail_exit;
} }
...@@ -3573,7 +3640,7 @@ bitmap_fail: ...@@ -3573,7 +3640,7 @@ bitmap_fail:
&bitmap_mtr); &bitmap_mtr);
} }
mtr_commit(&bitmap_mtr); ibuf_mtr_commit(&bitmap_mtr);
cursor = btr_pcur_get_btr_cur(&pcur); cursor = btr_pcur_get_btr_cur(&pcur);
...@@ -3638,9 +3705,8 @@ func_exit: ...@@ -3638,9 +3705,8 @@ func_exit:
} }
#endif #endif
mtr_commit(&mtr); ibuf_mtr_commit(&mtr);
btr_pcur_close(&pcur); btr_pcur_close(&pcur);
ibuf_exit();
mem_heap_free(heap); mem_heap_free(heap);
...@@ -3898,7 +3964,7 @@ ibuf_insert_to_index_page( ...@@ -3898,7 +3964,7 @@ ibuf_insert_to_index_page(
page_t* page = buf_block_get_frame(block); page_t* page = buf_block_get_frame(block);
rec_t* rec; rec_t* rec;
ut_ad(ibuf_inside()); ut_ad(ibuf_inside(mtr));
ut_ad(dtuple_check_typed(entry)); ut_ad(dtuple_check_typed(entry));
ut_ad(!buf_block_align(page)->is_hashed); ut_ad(!buf_block_align(page)->is_hashed);
...@@ -4045,7 +4111,7 @@ ibuf_set_del_mark( ...@@ -4045,7 +4111,7 @@ ibuf_set_del_mark(
page_cur_t page_cur; page_cur_t page_cur;
ulint low_match; ulint low_match;
ut_ad(ibuf_inside()); ut_ad(ibuf_inside(mtr));
ut_ad(dtuple_check_typed(entry)); ut_ad(dtuple_check_typed(entry));
low_match = page_cur_search( low_match = page_cur_search(
...@@ -4102,7 +4168,7 @@ ibuf_delete( ...@@ -4102,7 +4168,7 @@ ibuf_delete(
page_cur_t page_cur; page_cur_t page_cur;
ulint low_match; ulint low_match;
ut_ad(ibuf_inside()); ut_ad(ibuf_inside(mtr));
ut_ad(dtuple_check_typed(entry)); ut_ad(dtuple_check_typed(entry));
low_match = page_cur_search( low_match = page_cur_search(
...@@ -4190,7 +4256,7 @@ ibuf_restore_pos( ...@@ -4190,7 +4256,7 @@ ibuf_restore_pos(
/* The tablespace has been dropped. It is possible /* The tablespace has been dropped. It is possible
that another thread has deleted the insert buffer that another thread has deleted the insert buffer
entry. Do not complain. */ entry. Do not complain. */
btr_pcur_commit_specify_mtr(pcur, mtr); ibuf_btr_pcur_commit_specify_mtr(pcur, mtr);
} else { } else {
fprintf(stderr, fprintf(stderr,
"InnoDB: ERROR: Submit the output to" "InnoDB: ERROR: Submit the output to"
...@@ -4208,7 +4274,7 @@ ibuf_restore_pos( ...@@ -4208,7 +4274,7 @@ ibuf_restore_pos(
page_rec_get_next(btr_pcur_get_rec(pcur))); page_rec_get_next(btr_pcur_get_rec(pcur)));
fflush(stderr); fflush(stderr);
btr_pcur_commit_specify_mtr(pcur, mtr); ibuf_btr_pcur_commit_specify_mtr(pcur, mtr);
fputs("InnoDB: Validating insert buffer tree:\n", stderr); fputs("InnoDB: Validating insert buffer tree:\n", stderr);
if (!btr_validate_index(ibuf->index, NULL)) { if (!btr_validate_index(ibuf->index, NULL)) {
...@@ -4232,8 +4298,8 @@ ibool ...@@ -4232,8 +4298,8 @@ ibool
ibuf_delete_rec( ibuf_delete_rec(
/*============*/ /*============*/
ulint space, /*!< in: space id */ ulint space, /*!< in: space id */
ulint page_no,/*!< in: index page number where the record ulint page_no,/*!< in: index page number that the record
should belong */ should belong to */
btr_pcur_t* pcur, /*!< in: pcur positioned on the record to btr_pcur_t* pcur, /*!< in: pcur positioned on the record to
delete, having latch mode BTR_MODIFY_LEAF */ delete, having latch mode BTR_MODIFY_LEAF */
const dtuple_t* search_tuple, const dtuple_t* search_tuple,
...@@ -4244,10 +4310,10 @@ ibuf_delete_rec( ...@@ -4244,10 +4310,10 @@ ibuf_delete_rec(
page_t* root; page_t* root;
ulint err; ulint err;
ut_ad(ibuf_inside()); ut_ad(ibuf_inside(mtr));
ut_ad(page_rec_is_user_rec(btr_pcur_get_rec(pcur))); ut_ad(page_rec_is_user_rec(btr_pcur_get_rec(pcur)));
ut_ad(ibuf_rec_get_page_no(btr_pcur_get_rec(pcur)) == page_no); ut_ad(ibuf_rec_get_page_no(mtr, btr_pcur_get_rec(pcur)) == page_no);
ut_ad(ibuf_rec_get_space(btr_pcur_get_rec(pcur)) == space); ut_ad(ibuf_rec_get_space(mtr, btr_pcur_get_rec(pcur)) == space);
success = btr_cur_optimistic_delete(btr_pcur_get_btr_cur(pcur), mtr); success = btr_cur_optimistic_delete(btr_pcur_get_btr_cur(pcur), mtr);
...@@ -4280,22 +4346,22 @@ ibuf_delete_rec( ...@@ -4280,22 +4346,22 @@ ibuf_delete_rec(
} }
ut_ad(page_rec_is_user_rec(btr_pcur_get_rec(pcur))); ut_ad(page_rec_is_user_rec(btr_pcur_get_rec(pcur)));
ut_ad(ibuf_rec_get_page_no(btr_pcur_get_rec(pcur)) == page_no); ut_ad(ibuf_rec_get_page_no(mtr, btr_pcur_get_rec(pcur)) == page_no);
ut_ad(ibuf_rec_get_space(btr_pcur_get_rec(pcur)) == space); ut_ad(ibuf_rec_get_space(mtr, btr_pcur_get_rec(pcur)) == space);
/* We have to resort to a pessimistic delete from ibuf */ /* We have to resort to a pessimistic delete from ibuf */
btr_pcur_store_position(pcur, mtr); btr_pcur_store_position(pcur, mtr);
ibuf_btr_pcur_commit_specify_mtr(pcur, mtr);
btr_pcur_commit_specify_mtr(pcur, mtr); ibuf_mtr_start(mtr);
mutex_enter(&ibuf_mutex); mutex_enter(&ibuf_mutex);
mtr_start(mtr);
if (!ibuf_restore_pos(space, page_no, search_tuple, if (!ibuf_restore_pos(space, page_no, search_tuple,
BTR_MODIFY_TREE, pcur, mtr)) { BTR_MODIFY_TREE, pcur, mtr)) {
mutex_exit(&ibuf_mutex); mutex_exit(&ibuf_mutex);
ut_ad(!ibuf_inside(mtr));
ut_ad(mtr->state == MTR_COMMITTED);
goto func_exit; goto func_exit;
} }
...@@ -4312,9 +4378,11 @@ ibuf_delete_rec( ...@@ -4312,9 +4378,11 @@ ibuf_delete_rec(
mutex_exit(&ibuf_mutex); mutex_exit(&ibuf_mutex);
ibuf->empty = (page_get_n_recs(root) == 0); ibuf->empty = (page_get_n_recs(root) == 0);
btr_pcur_commit_specify_mtr(pcur, mtr); ibuf_btr_pcur_commit_specify_mtr(pcur, mtr);
func_exit: func_exit:
ut_ad(!ibuf_inside(mtr));
ut_ad(mtr->state == MTR_COMMITTED);
btr_pcur_close(pcur); btr_pcur_close(pcur);
return(TRUE); return(TRUE);
...@@ -4406,18 +4474,20 @@ ibuf_merge_or_delete_for_page( ...@@ -4406,18 +4474,20 @@ ibuf_merge_or_delete_for_page(
update_ibuf_bitmap = FALSE; update_ibuf_bitmap = FALSE;
} else { } else {
page_t* bitmap_page; page_t* bitmap_page;
ulint bitmap_bits;
mtr_start(&mtr); ibuf_mtr_start(&mtr);
bitmap_page = ibuf_bitmap_get_map_page( bitmap_page = ibuf_bitmap_get_map_page(
space, page_no, zip_size, &mtr); space, page_no, zip_size, &mtr);
bitmap_bits = ibuf_bitmap_page_get_bits(
bitmap_page, page_no, zip_size,
IBUF_BITMAP_BUFFERED, &mtr);
if (!ibuf_bitmap_page_get_bits(bitmap_page, page_no, ibuf_mtr_commit(&mtr);
zip_size,
IBUF_BITMAP_BUFFERED, if (!bitmap_bits) {
&mtr)) {
/* No inserts buffered for this page */ /* No inserts buffered for this page */
mtr_commit(&mtr);
if (!tablespace_being_deleted) { if (!tablespace_being_deleted) {
fil_decr_pending_ibuf_merges(space); fil_decr_pending_ibuf_merges(space);
...@@ -4425,7 +4495,6 @@ ibuf_merge_or_delete_for_page( ...@@ -4425,7 +4495,6 @@ ibuf_merge_or_delete_for_page(
return; return;
} }
mtr_commit(&mtr);
} }
} else if (block } else if (block
&& (ibuf_fixed_addr_page(space, zip_size, page_no) && (ibuf_fixed_addr_page(space, zip_size, page_no)
...@@ -4434,11 +4503,9 @@ ibuf_merge_or_delete_for_page( ...@@ -4434,11 +4503,9 @@ ibuf_merge_or_delete_for_page(
return; return;
} }
ibuf_enter();
heap = mem_heap_create(512); heap = mem_heap_create(512);
if (!trx_sys_multiple_tablespace_format) { if (UNIV_UNLIKELY(!trx_sys_multiple_tablespace_format)) {
ut_a(trx_doublewrite_must_reset_space_ids); ut_a(trx_doublewrite_must_reset_space_ids);
search_tuple = ibuf_search_tuple_build(space, page_no, heap); search_tuple = ibuf_search_tuple_build(space, page_no, heap);
} else { } else {
...@@ -4465,7 +4532,7 @@ ibuf_merge_or_delete_for_page( ...@@ -4465,7 +4532,7 @@ ibuf_merge_or_delete_for_page(
ut_print_timestamp(stderr); ut_print_timestamp(stderr);
mtr_start(&mtr); ibuf_mtr_start(&mtr);
fputs(" InnoDB: Dump of the ibuf bitmap page:\n", fputs(" InnoDB: Dump of the ibuf bitmap page:\n",
stderr); stderr);
...@@ -4473,8 +4540,7 @@ ibuf_merge_or_delete_for_page( ...@@ -4473,8 +4540,7 @@ ibuf_merge_or_delete_for_page(
bitmap_page = ibuf_bitmap_get_map_page(space, page_no, bitmap_page = ibuf_bitmap_get_map_page(space, page_no,
zip_size, &mtr); zip_size, &mtr);
buf_page_print(bitmap_page, 0); buf_page_print(bitmap_page, 0);
ibuf_mtr_commit(&mtr);
mtr_commit(&mtr);
fputs("\nInnoDB: Dump of the page:\n", stderr); fputs("\nInnoDB: Dump of the page:\n", stderr);
...@@ -4505,7 +4571,7 @@ ibuf_merge_or_delete_for_page( ...@@ -4505,7 +4571,7 @@ ibuf_merge_or_delete_for_page(
memset(dops, 0, sizeof(dops)); memset(dops, 0, sizeof(dops));
loop: loop:
mtr_start(&mtr); ibuf_mtr_start(&mtr);
if (block) { if (block) {
ibool success; ibool success;
...@@ -4539,8 +4605,8 @@ loop: ...@@ -4539,8 +4605,8 @@ loop:
rec = btr_pcur_get_rec(&pcur); rec = btr_pcur_get_rec(&pcur);
/* Check if the entry is for this index page */ /* Check if the entry is for this index page */
if (ibuf_rec_get_page_no(rec) != page_no if (ibuf_rec_get_page_no(&mtr, rec) != page_no
|| ibuf_rec_get_space(rec) != space) { || ibuf_rec_get_space(&mtr, rec) != space) {
if (block) { if (block) {
page_header_reset_last_insert( page_header_reset_last_insert(
...@@ -4563,7 +4629,7 @@ loop: ...@@ -4563,7 +4629,7 @@ loop:
dtuple_t* entry; dtuple_t* entry;
trx_id_t max_trx_id; trx_id_t max_trx_id;
dict_index_t* dummy_index; dict_index_t* dummy_index;
ibuf_op_t op = ibuf_rec_get_op_type(rec); ibuf_op_t op = ibuf_rec_get_op_type(&mtr, rec);
max_trx_id = page_get_max_trx_id(page_align(rec)); max_trx_id = page_get_max_trx_id(page_align(rec));
page_update_max_trx_id(block, page_zip, max_trx_id, page_update_max_trx_id(block, page_zip, max_trx_id,
...@@ -4572,7 +4638,7 @@ loop: ...@@ -4572,7 +4638,7 @@ loop:
ut_ad(page_validate(page_align(rec), ibuf->index)); ut_ad(page_validate(page_align(rec), ibuf->index));
entry = ibuf_build_entry_from_ibuf_rec( entry = ibuf_build_entry_from_ibuf_rec(
rec, heap, &dummy_index); &mtr, rec, heap, &dummy_index);
ut_ad(page_validate(block->frame, dummy_index)); ut_ad(page_validate(block->frame, dummy_index));
...@@ -4605,13 +4671,14 @@ loop: ...@@ -4605,13 +4671,14 @@ loop:
Store and restore the cursor position. */ Store and restore the cursor position. */
ut_ad(rec == btr_pcur_get_rec(&pcur)); ut_ad(rec == btr_pcur_get_rec(&pcur));
ut_ad(page_rec_is_user_rec(rec)); ut_ad(page_rec_is_user_rec(rec));
ut_ad(ibuf_rec_get_page_no(rec) == page_no); ut_ad(ibuf_rec_get_page_no(&mtr, rec)
ut_ad(ibuf_rec_get_space(rec) == space); == page_no);
ut_ad(ibuf_rec_get_space(&mtr, rec) == space);
btr_pcur_store_position(&pcur, &mtr); btr_pcur_store_position(&pcur, &mtr);
btr_pcur_commit_specify_mtr(&pcur, &mtr); ibuf_btr_pcur_commit_specify_mtr(&pcur, &mtr);
mtr_start(&mtr); ibuf_mtr_start(&mtr);
success = buf_page_get_known_nowait( success = buf_page_get_known_nowait(
RW_X_LATCH, block, RW_X_LATCH, block,
...@@ -4626,7 +4693,8 @@ loop: ...@@ -4626,7 +4693,8 @@ loop:
BTR_MODIFY_LEAF, BTR_MODIFY_LEAF,
&pcur, &mtr)) { &pcur, &mtr)) {
mtr_commit(&mtr); ut_ad(!ibuf_inside(&mtr));
ut_ad(mtr.state == MTR_COMMITTED);
mops[op]++; mops[op]++;
ibuf_dummy_index_free(dummy_index); ibuf_dummy_index_free(dummy_index);
goto loop; goto loop;
...@@ -4641,7 +4709,7 @@ loop: ...@@ -4641,7 +4709,7 @@ loop:
ibuf_dummy_index_free(dummy_index); ibuf_dummy_index_free(dummy_index);
} else { } else {
dops[ibuf_rec_get_op_type(rec)]++; dops[ibuf_rec_get_op_type(&mtr, rec)]++;
} }
/* Delete the record from ibuf */ /* Delete the record from ibuf */
...@@ -4652,7 +4720,7 @@ loop: ...@@ -4652,7 +4720,7 @@ loop:
goto loop; goto loop;
} else if (btr_pcur_is_after_last_on_page(&pcur)) { } else if (btr_pcur_is_after_last_on_page(&pcur)) {
mtr_commit(&mtr); ibuf_mtr_commit(&mtr);
btr_pcur_close(&pcur); btr_pcur_close(&pcur);
goto loop; goto loop;
...@@ -4686,7 +4754,7 @@ reset_bit: ...@@ -4686,7 +4754,7 @@ reset_bit:
} }
} }
mtr_commit(&mtr); ibuf_mtr_commit(&mtr);
btr_pcur_close(&pcur); btr_pcur_close(&pcur);
mem_heap_free(heap); mem_heap_free(heap);
...@@ -4710,8 +4778,6 @@ reset_bit: ...@@ -4710,8 +4778,6 @@ reset_bit:
fil_decr_pending_ibuf_merges(space); fil_decr_pending_ibuf_merges(space);
} }
ibuf_exit();
#ifdef UNIV_IBUF_COUNT_DEBUG #ifdef UNIV_IBUF_COUNT_DEBUG
ut_a(ibuf_count_get(space, page_no) == 0); ut_a(ibuf_count_get(space, page_no) == 0);
#endif #endif
...@@ -4731,9 +4797,8 @@ ibuf_delete_for_discarded_space( ...@@ -4731,9 +4797,8 @@ ibuf_delete_for_discarded_space(
mem_heap_t* heap; mem_heap_t* heap;
btr_pcur_t pcur; btr_pcur_t pcur;
dtuple_t* search_tuple; dtuple_t* search_tuple;
rec_t* ibuf_rec; const rec_t* ibuf_rec;
ulint page_no; ulint page_no;
ibool closed;
mtr_t mtr; mtr_t mtr;
/* Counts for discarded operations. */ /* Counts for discarded operations. */
...@@ -4748,9 +4813,7 @@ ibuf_delete_for_discarded_space( ...@@ -4748,9 +4813,7 @@ ibuf_delete_for_discarded_space(
memset(dops, 0, sizeof(dops)); memset(dops, 0, sizeof(dops));
loop: loop:
ibuf_enter(); ibuf_mtr_start(&mtr);
mtr_start(&mtr);
/* Position pcur in the insert buffer at the first entry for the /* Position pcur in the insert buffer at the first entry for the
space */ space */
...@@ -4770,39 +4833,34 @@ loop: ...@@ -4770,39 +4833,34 @@ loop:
ibuf_rec = btr_pcur_get_rec(&pcur); ibuf_rec = btr_pcur_get_rec(&pcur);
/* Check if the entry is for this space */ /* Check if the entry is for this space */
if (ibuf_rec_get_space(ibuf_rec) != space) { if (ibuf_rec_get_space(&mtr, ibuf_rec) != space) {
goto leave_loop; goto leave_loop;
} }
page_no = ibuf_rec_get_page_no(ibuf_rec); page_no = ibuf_rec_get_page_no(&mtr, ibuf_rec);
dops[ibuf_rec_get_op_type(ibuf_rec)]++; dops[ibuf_rec_get_op_type(&mtr, ibuf_rec)]++;
/* Delete the record from ibuf */ /* Delete the record from ibuf */
closed = ibuf_delete_rec(space, page_no, &pcur, search_tuple, if (ibuf_delete_rec(space, page_no, &pcur, search_tuple,
&mtr); &mtr)) {
if (closed) {
/* Deletion was pessimistic and mtr was committed: /* Deletion was pessimistic and mtr was committed:
we start from the beginning again */ we start from the beginning again */
ibuf_exit();
goto loop; goto loop;
} }
if (btr_pcur_is_after_last_on_page(&pcur)) { if (btr_pcur_is_after_last_on_page(&pcur)) {
mtr_commit(&mtr); ibuf_mtr_commit(&mtr);
btr_pcur_close(&pcur); btr_pcur_close(&pcur);
ibuf_exit();
goto loop; goto loop;
} }
} }
leave_loop: leave_loop:
mtr_commit(&mtr); ibuf_mtr_commit(&mtr);
btr_pcur_close(&pcur); btr_pcur_close(&pcur);
#ifdef HAVE_ATOMIC_BUILTINS #ifdef HAVE_ATOMIC_BUILTINS
...@@ -4814,8 +4872,6 @@ leave_loop: ...@@ -4814,8 +4872,6 @@ leave_loop:
mutex_exit(&ibuf_mutex); mutex_exit(&ibuf_mutex);
#endif /* HAVE_ATOMIC_BUILTINS */ #endif /* HAVE_ATOMIC_BUILTINS */
ibuf_exit();
mem_heap_free(heap); mem_heap_free(heap);
} }
...@@ -4831,18 +4887,15 @@ ibuf_is_empty(void) ...@@ -4831,18 +4887,15 @@ ibuf_is_empty(void)
const page_t* root; const page_t* root;
mtr_t mtr; mtr_t mtr;
ibuf_enter(); ibuf_mtr_start(&mtr);
mtr_start(&mtr);
mutex_enter(&ibuf_mutex); mutex_enter(&ibuf_mutex);
root = ibuf_tree_root_get(&mtr); root = ibuf_tree_root_get(&mtr);
mutex_exit(&ibuf_mutex); mutex_exit(&ibuf_mutex);
is_empty = (page_get_n_recs(root) == 0); is_empty = (page_get_n_recs(root) == 0);
mtr_commit(&mtr);
ibuf_exit();
ut_a(is_empty == ibuf->empty); ut_a(is_empty == ibuf->empty);
ibuf_mtr_commit(&mtr);
return(is_empty); return(is_empty);
} }
......
...@@ -70,10 +70,10 @@ UNIV_INTERN ...@@ -70,10 +70,10 @@ UNIV_INTERN
ulint ulint
buf_read_ahead_linear( buf_read_ahead_linear(
/*==================*/ /*==================*/
ulint space, /*!< in: space id */ ulint space, /*!< in: space id */
ulint zip_size,/*!< in: compressed page size in bytes, or 0 */ ulint zip_size, /*!< in: compressed page size in bytes, or 0 */
ulint offset);/*!< in: page number of a page; NOTE: the current thread ulint offset, /*!< in: page number; see NOTE 3 above */
must want access to this page (see NOTE 3 above) */ ibool inside_ibuf); /*!< in: TRUE if we are inside ibuf routine */
/********************************************************************//** /********************************************************************//**
Issues read requests for pages which the ibuf module wants to read in, in Issues read requests for pages which the ibuf module wants to read in, in
order to contract the insert buffer tree. Technically, this function is like order to contract the insert buffer tree. Technically, this function is like
......
...@@ -104,6 +104,22 @@ UNIV_INTERN ...@@ -104,6 +104,22 @@ UNIV_INTERN
void void
ibuf_update_max_tablespace_id(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. */ Initializes an ibuf bitmap page. */
UNIV_INTERN UNIV_INTERN
...@@ -224,10 +240,12 @@ routine. ...@@ -224,10 +240,12 @@ routine.
For instance, a read-ahead of non-ibuf pages is forbidden by threads For instance, a read-ahead of non-ibuf pages is forbidden by threads
that are executing an insert buffer routine. that are executing an insert buffer routine.
@return TRUE if inside an insert buffer routine */ @return TRUE if inside an insert buffer routine */
UNIV_INTERN UNIV_INLINE
ibool 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. Checks if a page address is an ibuf bitmap page (level 3 page) address.
@return TRUE if a bitmap page */ @return TRUE if a bitmap page */
......
...@@ -37,6 +37,30 @@ buffer inserts to this page. If there is this much of free space, the ...@@ -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. */ corresponding bits are set in the ibuf bitmap. */
#define IBUF_PAGE_SIZE_PER_FREE_SPACE 32 #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 */ /** Insert buffer struct */
struct ibuf_struct{ struct ibuf_struct{
ulint size; /*!< current size of the ibuf index ulint size; /*!< current size of the ibuf index
...@@ -120,6 +144,22 @@ ibuf_should_try( ...@@ -120,6 +144,22 @@ ibuf_should_try(
return(FALSE); 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. Checks if a page address is an ibuf bitmap page address.
@return TRUE if a bitmap page */ @return TRUE if a bitmap page */
......
...@@ -190,21 +190,21 @@ functions). The page number parameter was originally written as 0. @{ */ ...@@ -190,21 +190,21 @@ functions). The page number parameter was originally written as 0. @{ */
/* @} */ /* @} */
/***************************************************************//** /***************************************************************//**
Starts a mini-transaction and creates a mini-transaction handle Starts a mini-transaction. */
and buffer in the memory buffer given by the caller.
@return mtr buffer which also acts as the mtr handle */
UNIV_INLINE UNIV_INLINE
mtr_t* void
mtr_start( mtr_start(
/*======*/ /*======*/
mtr_t* mtr); /*!< in: memory buffer for the mtr buffer */ mtr_t* mtr) /*!< out: mini-transaction */
__attribute__((nonnull));
/***************************************************************//** /***************************************************************//**
Commits a mini-transaction. */ Commits a mini-transaction. */
UNIV_INTERN UNIV_INTERN
void void
mtr_commit( mtr_commit(
/*=======*/ /*=======*/
mtr_t* mtr); /*!< in: mini-transaction */ mtr_t* mtr) /*!< in/out: mini-transaction */
__attribute__((nonnull));
/**********************************************************//** /**********************************************************//**
Sets and returns a savepoint in mtr. Sets and returns a savepoint in mtr.
@return savepoint */ @return savepoint */
...@@ -378,6 +378,8 @@ struct mtr_struct{ ...@@ -378,6 +378,8 @@ struct mtr_struct{
#endif #endif
dyn_array_t memo; /*!< memo stack for locks etc. */ dyn_array_t memo; /*!< memo stack for locks etc. */
dyn_array_t log; /*!< mini-transaction log */ dyn_array_t log; /*!< mini-transaction log */
ibool inside_ibuf;
/*!< TRUE if inside ibuf changes */
ibool modifications; ibool modifications;
/* TRUE if the mtr made modifications to /* TRUE if the mtr made modifications to
buffer pool pages */ buffer pool pages */
......
...@@ -30,26 +30,23 @@ Created 11/26/1995 Heikki Tuuri ...@@ -30,26 +30,23 @@ Created 11/26/1995 Heikki Tuuri
#include "mach0data.h" #include "mach0data.h"
/***************************************************************//** /***************************************************************//**
Starts a mini-transaction and creates a mini-transaction handle Starts a mini-transaction. */
and a buffer in the memory buffer given by the caller.
@return mtr buffer which also acts as the mtr handle */
UNIV_INLINE UNIV_INLINE
mtr_t* void
mtr_start( 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->memo));
dyn_array_create(&(mtr->log)); dyn_array_create(&(mtr->log));
mtr->log_mode = MTR_LOG_ALL; mtr->log_mode = MTR_LOG_ALL;
mtr->modifications = FALSE; mtr->modifications = FALSE;
mtr->inside_ibuf = FALSE;
mtr->n_log_recs = 0; mtr->n_log_recs = 0;
ut_d(mtr->state = MTR_ACTIVE); ut_d(mtr->state = MTR_ACTIVE);
ut_d(mtr->magic_n = MTR_MAGIC_N); ut_d(mtr->magic_n = MTR_MAGIC_N);
return(mtr);
} }
/***************************************************//** /***************************************************//**
......
...@@ -110,7 +110,6 @@ extern mysql_pfs_key_t syn_arr_mutex_key; ...@@ -110,7 +110,6 @@ extern mysql_pfs_key_t syn_arr_mutex_key;
extern mysql_pfs_key_t sync_thread_mutex_key; extern mysql_pfs_key_t sync_thread_mutex_key;
# endif /* UNIV_SYNC_DEBUG */ # endif /* UNIV_SYNC_DEBUG */
extern mysql_pfs_key_t trx_doublewrite_mutex_key; extern mysql_pfs_key_t trx_doublewrite_mutex_key;
extern mysql_pfs_key_t thr_local_mutex_key;
extern mysql_pfs_key_t trx_undo_mutex_key; extern mysql_pfs_key_t trx_undo_mutex_key;
#endif /* UNIV_PFS_MUTEX */ #endif /* UNIV_PFS_MUTEX */
......
/*****************************************************************************
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 */
/*******************************************************************//**
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);
/*=============================*/
#ifndef UNIV_NONINL
#include "thr0loc.ic"
#endif
#endif
/*****************************************************************************
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
*******************************************************/
...@@ -251,6 +251,7 @@ mtr_commit( ...@@ -251,6 +251,7 @@ mtr_commit(
ut_ad(mtr); ut_ad(mtr);
ut_ad(mtr->magic_n == MTR_MAGIC_N); ut_ad(mtr->magic_n == MTR_MAGIC_N);
ut_ad(mtr->state == MTR_ACTIVE); ut_ad(mtr->state == MTR_ACTIVE);
ut_ad(!mtr->inside_ibuf);
ut_d(mtr->state = MTR_COMMITTING); ut_d(mtr->state = MTR_COMMITTING);
#ifndef UNIV_HOTBACKUP #ifndef UNIV_HOTBACKUP
......
...@@ -66,7 +66,6 @@ Created 10/8/1995 Heikki Tuuri ...@@ -66,7 +66,6 @@ Created 10/8/1995 Heikki Tuuri
#include "mem0mem.h" #include "mem0mem.h"
#include "mem0pool.h" #include "mem0pool.h"
#include "sync0sync.h" #include "sync0sync.h"
#include "thr0loc.h"
#include "que0que.h" #include "que0que.h"
#include "log0recv.h" #include "log0recv.h"
#include "pars0pars.h" #include "pars0pars.h"
...@@ -1129,7 +1128,6 @@ srv_general_init(void) ...@@ -1129,7 +1128,6 @@ srv_general_init(void)
os_sync_init(); os_sync_init();
sync_init(); sync_init();
mem_init(srv_mem_pool_size); mem_init(srv_mem_pool_size);
thr_local_init();
} }
/*======================= InnoDB Server FIFO queue =======================*/ /*======================= InnoDB Server FIFO queue =======================*/
...@@ -3071,8 +3069,6 @@ suspend_thread: ...@@ -3071,8 +3069,6 @@ suspend_thread:
main thread goes back to loop. */ main thread goes back to loop. */
goto loop; goto loop;
OS_THREAD_DUMMY_RETURN; /* Not reached, avoid compiler warning */
} }
/*********************************************************************//** /*********************************************************************//**
......
...@@ -85,7 +85,6 @@ Created 2/16/1996 Heikki Tuuri ...@@ -85,7 +85,6 @@ Created 2/16/1996 Heikki Tuuri
# include "row0row.h" # include "row0row.h"
# include "row0mysql.h" # include "row0mysql.h"
# include "btr0pcur.h" # include "btr0pcur.h"
# include "thr0loc.h"
# include "os0sync.h" /* for INNODB_RW_LOCKS_USE_ATOMICS */ # include "os0sync.h" /* for INNODB_RW_LOCKS_USE_ATOMICS */
# include "zlib.h" /* for ZLIB_VERSION */ # include "zlib.h" /* for ZLIB_VERSION */
...@@ -2210,7 +2209,6 @@ innobase_shutdown_for_mysql(void) ...@@ -2210,7 +2209,6 @@ innobase_shutdown_for_mysql(void)
ibuf_close(); ibuf_close();
log_shutdown(); log_shutdown();
lock_sys_close(); lock_sys_close();
thr_local_close();
trx_sys_file_format_close(); trx_sys_file_format_close();
trx_sys_close(); trx_sys_close();
......
/*****************************************************************************
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 thr/thr0loc.c
The thread local storage
Created 10/5/1995 Heikki Tuuri
*******************************************************/
#include "thr0loc.h"
#ifdef UNIV_NONINL
#include "thr0loc.ic"
#endif
#include "sync0sync.h"
#include "hash0hash.h"
#include "mem0mem.h"
#include "srv0srv.h"
/*
IMPLEMENTATION OF THREAD LOCAL STORAGE
======================================
The threads sometimes need private data which depends on the thread id.
This is implemented as a hash table, where the hash value is calculated
from the thread id, to prepare for a large number of threads. The hash table
is protected by a mutex. If you need modify the program and put new data to
the thread local storage, just add it to struct thr_local_struct in the
header file. */
/** Mutex protecting thr_local_hash */
static mutex_t thr_local_mutex;
/** The hash table. The module is not yet initialized when it is NULL. */
static hash_table_t* thr_local_hash = NULL;
/** Thread local data */
typedef struct thr_local_struct thr_local_t;
#ifdef UNIV_PFS_MUTEX
/* Key to register the mutex with performance schema */
UNIV_INTERN mysql_pfs_key_t thr_local_mutex_key;
#endif /* UNIV_PFS_MUTEX */
/** @brief Thread local data.
The private data for each thread should be put to
the structure below and the accessor functions written
for the field. */
struct thr_local_struct{
os_thread_id_t id; /*!< id of the thread which owns this struct */
os_thread_t handle; /*!< operating system handle to the thread */
ibool in_ibuf;/*!< TRUE if the thread is doing an ibuf
operation */
hash_node_t hash; /*!< hash chain node */
ulint magic_n;/*!< magic number (THR_LOCAL_MAGIC_N) */
};
/** The value of thr_local_struct::magic_n */
#define THR_LOCAL_MAGIC_N 1231234
#ifdef UNIV_DEBUG
/*******************************************************************//**
Validates thread local data.
@return TRUE if valid */
static
ibool
thr_local_validate(
/*===============*/
const thr_local_t* local) /*!< in: data to validate */
{
ut_ad(local->magic_n == THR_LOCAL_MAGIC_N);
ut_ad(local->in_ibuf == FALSE || local->in_ibuf == TRUE);
return(TRUE);
}
#endif /* UNIV_DEBUG */
/*******************************************************************//**
Returns the local storage struct for a thread.
@return local storage */
static
thr_local_t*
thr_local_get(
/*==========*/
os_thread_id_t id) /*!< in: thread id of the thread */
{
thr_local_t* local;
try_again:
ut_ad(thr_local_hash);
ut_ad(mutex_own(&thr_local_mutex));
/* Look for the local struct in the hash table */
local = NULL;
HASH_SEARCH(hash, thr_local_hash, os_thread_pf(id),
thr_local_t*, local, ut_ad(thr_local_validate(local)),
os_thread_eq(local->id, id));
if (local == NULL) {
mutex_exit(&thr_local_mutex);
thr_local_create();
mutex_enter(&thr_local_mutex);
goto try_again;
}
ut_ad(thr_local_validate(local));
return(local);
}
/*******************************************************************//**
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)
/*=============================*/
{
thr_local_t* local;
mutex_enter(&thr_local_mutex);
local = thr_local_get(os_thread_get_curr_id());
mutex_exit(&thr_local_mutex);
return(&(local->in_ibuf));
}
/*******************************************************************//**
Creates a local storage struct for the calling new thread. */
UNIV_INTERN
void
thr_local_create(void)
/*==================*/
{
thr_local_t* local;
if (thr_local_hash == NULL) {
thr_local_init();
}
local = mem_alloc(sizeof(thr_local_t));
local->id = os_thread_get_curr_id();
local->handle = os_thread_get_curr();
local->magic_n = THR_LOCAL_MAGIC_N;
local->in_ibuf = FALSE;
mutex_enter(&thr_local_mutex);
HASH_INSERT(thr_local_t, hash, thr_local_hash,
os_thread_pf(os_thread_get_curr_id()),
local);
mutex_exit(&thr_local_mutex);
}
/*******************************************************************//**
Frees the local storage struct for the specified thread. */
UNIV_INTERN
void
thr_local_free(
/*===========*/
os_thread_id_t id) /*!< in: thread id */
{
thr_local_t* local;
mutex_enter(&thr_local_mutex);
/* Look for the local struct in the hash table */
HASH_SEARCH(hash, thr_local_hash, os_thread_pf(id),
thr_local_t*, local, ut_ad(thr_local_validate(local)),
os_thread_eq(local->id, id));
if (local == NULL) {
mutex_exit(&thr_local_mutex);
return;
}
HASH_DELETE(thr_local_t, hash, thr_local_hash,
os_thread_pf(id), local);
mutex_exit(&thr_local_mutex);
ut_a(local->magic_n == THR_LOCAL_MAGIC_N);
ut_ad(thr_local_validate(local));
mem_free(local);
}
/****************************************************************//**
Initializes the thread local storage module. */
UNIV_INTERN
void
thr_local_init(void)
/*================*/
{
ut_a(thr_local_hash == NULL);
thr_local_hash = hash_create(OS_THREAD_MAX_N + 100);
mutex_create(thr_local_mutex_key,
&thr_local_mutex, SYNC_THR_LOCAL);
}
/********************************************************************
Close the thread local storage module. */
UNIV_INTERN
void
thr_local_close(void)
/*=================*/
{
ulint i;
ut_a(thr_local_hash != NULL);
/* Free the hash elements. We don't remove them from the table
because we are going to destroy the table anyway. */
for (i = 0; i < hash_get_n_cells(thr_local_hash); i++) {
thr_local_t* local;
local = HASH_GET_FIRST(thr_local_hash, i);
while (local) {
thr_local_t* prev_local = local;
local = HASH_GET_NEXT(hash, prev_local);
ut_a(prev_local->magic_n == THR_LOCAL_MAGIC_N);
ut_ad(thr_local_validate(prev_local));
mem_free(prev_local);
}
}
hash_table_free(thr_local_hash);
thr_local_hash = NULL;
}
...@@ -38,7 +38,6 @@ Created 3/26/1996 Heikki Tuuri ...@@ -38,7 +38,6 @@ Created 3/26/1996 Heikki Tuuri
#include "usr0sess.h" #include "usr0sess.h"
#include "read0read.h" #include "read0read.h"
#include "srv0srv.h" #include "srv0srv.h"
#include "thr0loc.h"
#include "btr0sea.h" #include "btr0sea.h"
#include "os0proc.h" #include "os0proc.h"
#include "trx0xa.h" #include "trx0xa.h"
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment