1
0
mirror of https://github.com/MariaDB/server.git synced 2025-07-29 05:21:33 +03:00

Merge 10.3 into 10.4

This commit is contained in:
Marko Mäkelä
2019-04-08 21:58:18 +03:00
23 changed files with 244 additions and 377 deletions

View File

@ -16,6 +16,11 @@ IF(RPM)
ENDIF()
ENDMACRO()
# FindBoost.cmake doesn't leave any trace, do it here
IF (Boost_INCLUDE_DIR)
FIND_FILE(Boost_config_hpp boost/config.hpp PATHS ${Boost_INCLUDE_DIR})
ENDIF()
GET_CMAKE_PROPERTY(ALL_VARS CACHE_VARIABLES)
FOREACH (V ${ALL_VARS})
GET_PROPERTY(H CACHE ${V} PROPERTY HELPSTRING)

View File

@ -221,8 +221,6 @@ const char *defaults_group = "mysqld";
#define HA_INNOBASE_ROWS_IN_TABLE 10000 /* to get optimization right */
#define HA_INNOBASE_RANGE_COUNT 100
ulong innobase_large_page_size = 0;
/* The default values for the following, type long or longlong, start-up
parameters are declared in mysqld.cc: */
@ -242,7 +240,6 @@ char* innobase_data_home_dir;
char* innobase_data_file_path;
my_bool innobase_use_doublewrite;
my_bool innobase_use_large_pages;
my_bool innobase_file_per_table;
my_bool innobase_locks_unsafe_for_binlog;
my_bool innobase_rollback_on_timeout;
@ -1917,8 +1914,6 @@ static bool innodb_init_param()
srv_use_doublewrite_buf = (ibool) innobase_use_doublewrite;
os_use_large_pages = (ibool) innobase_use_large_pages;
os_large_page_size = (ulint) innobase_large_page_size;
row_rollback_on_timeout = (ibool) innobase_rollback_on_timeout;
srv_file_per_table = (my_bool) innobase_file_per_table;
@ -3999,9 +3994,7 @@ static bool xtrabackup_backup_low()
/** Implement --backup
@return whether the operation succeeded */
static
bool
xtrabackup_backup_func()
static bool xtrabackup_backup_func()
{
MY_STAT stat_info;
uint i;
@ -4134,38 +4127,25 @@ fail:
log_mutex_enter();
reread_log_header:
dberr_t err = recv_find_max_checkpoint(&max_cp_field);
if (err != DB_SUCCESS) {
log_fail:
msg("Error: cannot read redo log header");
log_mutex_exit();
goto fail;
}
if (log_sys.log.format == 0) {
old_format:
msg("Error: cannot process redo log"
" before MariaDB 10.2.2");
msg("Error: cannot process redo log before MariaDB 10.2.2");
log_mutex_exit();
goto log_fail;
goto fail;
}
const byte* buf = log_sys.checkpoint_buf;
reread_log_header:
checkpoint_lsn_start = log_sys.log.lsn;
checkpoint_lsn_start = log_sys.log.get_lsn();
checkpoint_no_start = log_sys.next_checkpoint_no;
err = recv_find_max_checkpoint(&max_cp_field);
if (err != DB_SUCCESS) {
goto log_fail;
}
if (log_sys.log.format == 0) {
goto old_format;
}
log_header_read(max_cp_field);
if (checkpoint_no_start != mach_read_from_8(buf + LOG_CHECKPOINT_NO)) {
@ -4211,6 +4191,12 @@ reread_log_header:
mach_write_to_8(log_hdr + LOG_CHECKPOINT_OFFSET,
(checkpoint_lsn_start & (OS_FILE_LOG_BLOCK_SIZE - 1))
| LOG_FILE_HDR_SIZE);
/* The least significant bits of LOG_CHECKPOINT_OFFSET must be
stored correctly in the copy of the ib_logfile. The most significant
bits, which identify the start offset of the log block in the file,
we did choose freely, as LOG_FILE_HDR_SIZE. */
ut_ad(!((log_sys.log.get_lsn() ^ checkpoint_lsn_start)
& (OS_FILE_LOG_BLOCK_SIZE - 1)));
log_block_set_checksum(log_hdr,
log_block_calc_checksum_crc32(log_hdr));
/* Write checkpoint page 1 and two empty log pages before the

View File

@ -2,18 +2,14 @@
# WL#6965: Truncate UNDO logs.
#
--source include/big_test.inc
# With larger innodb_page_size, the undo log tablespaces do not grow enough.
--source include/innodb_page_size_small.inc
--source include/have_innodb.inc
--source include/have_debug.inc
--source include/have_undo_tablespaces.inc
# Valgrind would complain about memory leaks when we crash on purpose.
--source include/not_valgrind.inc
# Embedded server does not support crashing
# Tests with embedded server do not support restarting
--source include/not_embedded.inc
# Avoid CrashReporter popup on Mac
--source include/not_crashrep.inc
SET GLOBAL innodb_undo_logs = 4;
SET GLOBAL innodb_undo_log_truncate = 1;

View File

@ -6343,7 +6343,7 @@ drop_create_field:
Key_part_spec *kp;
if ((kp= part_it++))
chkname= kp->field_name.str;
if (keyname == NULL)
if (chkname == NULL)
continue;
}
if (key->type == chk_key->type &&

View File

@ -725,159 +725,54 @@ btr_page_free_for_ibuf(
mtr));
}
/**************************************************************//**
Frees a file page used in an index tree. Can be used also to (BLOB)
external storage pages. */
void
btr_page_free_low(
/*==============*/
dict_index_t* index, /*!< in: index tree */
buf_block_t* block, /*!< in: block to be freed, x-latched */
ulint level, /*!< in: page level (ULINT_UNDEFINED=BLOB) */
bool blob, /*!< in: blob page */
mtr_t* mtr) /*!< in: mtr */
/** Free an index page.
@param[in,out] index index tree
@param[in,out] block block to be freed
@param[in,out] mtr mini-transaction
@param[in] blob whether this is freeing a BLOB page */
void btr_page_free(dict_index_t* index, buf_block_t* block, mtr_t* mtr,
bool blob)
{
fseg_header_t* seg_header;
page_t* root;
ut_ad(mtr_memo_contains(mtr, block, MTR_MEMO_PAGE_X_FIX));
#ifdef BTR_CUR_HASH_ADAPT
ut_ad(!block->index || !blob);
ut_ad(!block->index || page_is_leaf(block->frame));
#endif
ut_ad(index->table->space_id == block->page.id.space());
/* The root page is freed by btr_free_root(). */
ut_ad(block->page.id.page_no() != index->page);
ut_ad(mtr->is_named_space(index->table->space));
/* The page gets invalid for optimistic searches: increment the frame
modify clock */
buf_block_modify_clock_inc(block);
if (blob) {
ut_a(level == 0);
}
bool scrub = srv_immediate_scrub_data_uncompressed;
/* scrub page */
if (scrub && blob) {
/* blob page: scrub entire page */
// TODO(jonaso): scrub only what is actually needed
page_t* page = buf_block_get_frame(block);
memset(page + PAGE_HEADER, 0,
srv_page_size - PAGE_HEADER);
#ifdef UNIV_DEBUG_SCRUBBING
fprintf(stderr,
"btr_page_free_low: scrub blob page %lu/%lu\n",
buf_block_get_space(block),
buf_block_get_page_no(block));
#endif /* UNIV_DEBUG_SCRUBBING */
} else if (scrub) {
/* scrub records on page */
/* TODO(jonaso): in theory we could clear full page
* but, since page still remains in buffer pool, and
* gets flushed etc. Lots of routines validates consistency
* of it. And in order to remain structurally consistent
* we clear each record by it own
*
* NOTE: The TODO below mentions removing page from buffer pool
* and removing redo entries, once that is done, clearing full
* pages should be possible
*/
uint cnt = 0;
ulint bytes = 0;
page_t* page = buf_block_get_frame(block);
mem_heap_t* heap = NULL;
ulint* offsets = NULL;
rec_t* rec = page_rec_get_next(page_get_infimum_rec(page));
while (!page_rec_is_supremum(rec)) {
offsets = rec_get_offsets(rec, index, offsets,
page_is_leaf(page),
ULINT_UNDEFINED,
&heap);
ulint size = rec_offs_data_size(offsets);
memset(rec, 0, size);
rec = page_rec_get_next(rec);
cnt++;
bytes += size;
}
#ifdef UNIV_DEBUG_SCRUBBING
fprintf(stderr,
"btr_page_free_low: scrub %lu/%lu - "
"%u records " ULINTPF " bytes\n",
buf_block_get_space(block),
buf_block_get_page_no(block),
cnt, bytes);
#endif /* UNIV_DEBUG_SCRUBBING */
if (heap) {
mem_heap_free(heap);
}
}
#ifdef UNIV_DEBUG_SCRUBBING
if (scrub == false) {
fprintf(stderr,
"btr_page_free_low %lu/%lu blob: %u\n",
buf_block_get_space(block),
buf_block_get_page_no(block),
blob);
}
#endif /* UNIV_DEBUG_SCRUBBING */
if (dict_index_is_ibuf(index)) {
btr_page_free_for_ibuf(index, block, mtr);
return;
}
root = btr_root_get(index, mtr);
if (level == 0 || level == ULINT_UNDEFINED) {
seg_header = root + PAGE_HEADER + PAGE_BTR_SEG_LEAF;
} else {
seg_header = root + PAGE_HEADER + PAGE_BTR_SEG_TOP;
}
#ifdef UNIV_GIS_DEBUG
if (dict_index_is_spatial(index)) {
fprintf(stderr, "GIS_DIAG: Freed %ld\n",
(long) block->page.id.page_no());
}
#endif
if (scrub) {
/**
* Reset page type so that scrub thread won't try to scrub it
*/
mlog_write_ulint(buf_block_get_frame(block) + FIL_PAGE_TYPE,
FIL_PAGE_TYPE_ALLOCATED, MLOG_2BYTES, mtr);
}
/* TODO: Discard any operations for block from mtr->log.
The page will be freed, so previous changes to it by this
mini-transaction should not matter. */
page_t* root = btr_root_get(index, mtr);
fseg_header_t* seg_header = &root[blob || page_is_leaf(block->frame)
? PAGE_HEADER + PAGE_BTR_SEG_LEAF
: PAGE_HEADER + PAGE_BTR_SEG_TOP];
fseg_free_page(seg_header,
block->page.id.space(),
block->page.id.page_no(),
level != ULINT_UNDEFINED, mtr);
index->table->space, block->page.id.page_no(),
block->index != NULL, mtr);
/* The page was marked free in the allocation bitmap, but it
should remain buffer-fixed until mtr_commit(mtr) or until it
should remain exclusively latched until mtr_t::commit() or until it
is explicitly freed from the mini-transaction. */
ut_ad(mtr_memo_contains(mtr, block, MTR_MEMO_PAGE_X_FIX));
/* TODO: Discard any operations on the page from the redo log
and remove the block from the flush list and the buffer pool.
This would free up buffer pool earlier and reduce writes to
both the tablespace and the redo log. */
}
/**************************************************************//**
Frees a file page used in an index tree. NOTE: cannot free field external
storage pages because the page must contain info on its level. */
void
btr_page_free(
/*==========*/
dict_index_t* index, /*!< in: index tree */
buf_block_t* block, /*!< in: block to be freed, x-latched */
mtr_t* mtr) /*!< in: mtr */
{
const page_t* page = buf_block_get_frame(block);
ulint level = btr_page_get_level(page);
ut_ad(fil_page_index_page_check(block->frame));
ut_ad(level != ULINT_UNDEFINED);
btr_page_free_low(index, block, level, false, mtr);
/* MDEV-15528 FIXME: Zero out the page after the redo log for
this mini-transaction has been durably written.
This must be done unconditionally if
srv_immediate_scrub_data_uncompressed is set. */
}
/**************************************************************//**

View File

@ -1033,7 +1033,7 @@ BtrBulk::finish(dberr_t err)
root_page_bulk.copyIn(first_rec);
/* Remove last page. */
btr_page_free_low(m_index, last_block, m_root_level, false, &mtr);
btr_page_free(m_index, last_block, &mtr);
/* Do not flush the last page. */
last_block->page.flush_observer = NULL;

View File

@ -8145,8 +8145,7 @@ btr_free_externally_stored_field(
}
next_page_no = mach_read_from_4(page + FIL_PAGE_NEXT);
btr_page_free_low(index, ext_block, 0,
true, &mtr);
btr_page_free(index, ext_block, &mtr, true);
if (page_zip != NULL) {
mach_write_to_4(field_ref + BTR_EXTERN_PAGE_NO,
@ -8172,12 +8171,7 @@ btr_free_externally_stored_field(
next_page_no = mach_read_from_4(
page + FIL_PAGE_DATA
+ BTR_BLOB_HDR_NEXT_PAGE_NO);
/* We must supply the page level (= 0) as an argument
because we did not store it on the page (we save the
space overhead from an index page header. */
btr_page_free_low(index, ext_block, 0,
true, &mtr);
btr_page_free(index, ext_block, &mtr, true);
mlog_write_ulint(field_ref + BTR_EXTERN_PAGE_NO,
next_page_no,

View File

@ -1592,7 +1592,7 @@ buf_chunk_init(
/* Round down to a multiple of page size,
although it already should be. */
mem_size = ut_2pow_round(mem_size, ulint(srv_page_size));
mem_size = ut_2pow_round<ulint>(mem_size, srv_page_size);
DBUG_EXECUTE_IF("ib_buf_chunk_init_fails", return(NULL););
@ -1625,7 +1625,7 @@ buf_chunk_init(
chunk->blocks = (buf_block_t*) chunk->mem;
/* Align a pointer to the first frame. Note that when
os_large_page_size is smaller than srv_page_size,
opt_large_page_size is smaller than srv_page_size,
we may allocate one fewer block than requested. When
it is bigger, we may allocate more blocks than requested. */

View File

@ -577,58 +577,32 @@ void fsp_apply_init_file_page(buf_block_t* block)
#ifdef UNIV_DEBUG
/** Assert that the mini-transaction is compatible with
updating an allocation bitmap page.
@param[in] id tablespace identifier
@param[in] mtr mini-transaction */
static
void
fsp_space_modify_check(
const fil_space_t* space,
const mtr_t* mtr)
void fil_space_t::modify_check(const mtr_t& mtr) const
{
switch (mtr->get_log_mode()) {
switch (mtr.get_log_mode()) {
case MTR_LOG_SHORT_INSERTS:
case MTR_LOG_NONE:
/* These modes are only allowed within a non-bitmap page
when there is a higher-level redo log record written. */
ut_ad(space->purpose == FIL_TYPE_TABLESPACE
|| space->purpose == FIL_TYPE_TEMPORARY);
ut_ad(purpose == FIL_TYPE_TABLESPACE
|| purpose == FIL_TYPE_TEMPORARY);
break;
case MTR_LOG_NO_REDO:
ut_ad(space->purpose == FIL_TYPE_TEMPORARY
|| space->purpose == FIL_TYPE_IMPORT
|| space->redo_skipped_count);
ut_ad(purpose == FIL_TYPE_TEMPORARY
|| purpose == FIL_TYPE_IMPORT
|| redo_skipped_count);
return;
case MTR_LOG_ALL:
/* We may only write redo log for a persistent tablespace. */
ut_ad(space->purpose == FIL_TYPE_TABLESPACE);
ut_ad(mtr->is_named_space(space->id));
/* We may only write redo log for a persistent
tablespace. */
ut_ad(purpose == FIL_TYPE_TABLESPACE);
ut_ad(mtr.is_named_space(id));
return;
}
ut_ad(0);
ut_ad(!"invalid log mode");
}
#endif /* UNIV_DEBUG */
/** Initialize a file page.
@param[in,out] block file page
@param[in,out] mtr mini-transaction */
static void fsp_init_file_page(buf_block_t* block, mtr_t* mtr)
{
fsp_apply_init_file_page(block);
mlog_write_initial_log_record(block->frame, MLOG_INIT_FILE_PAGE2, mtr);
}
#ifdef UNIV_DEBUG
static
void
fsp_init_file_page(const fil_space_t* space, buf_block_t* block, mtr_t* mtr)
{
ut_d(fsp_space_modify_check(space, mtr));
ut_ad(space->id == block->page.id.space());
fsp_init_file_page(block, mtr);
}
#else /* UNIV_DEBUG */
# define fsp_init_file_page(space, block, mtr) fsp_init_file_page(block, mtr)
#endif
/**********************************************************************//**
@ -756,7 +730,7 @@ fsp_try_extend_data_file_with_pages(
ulint size;
ut_a(!is_system_tablespace(space->id));
ut_d(fsp_space_modify_check(space, mtr));
ut_d(space->modify_check(*mtr));
size = mach_read_from_4(header + FSP_SIZE);
ut_ad(size == space->size_in_header);
@ -826,7 +800,7 @@ fsp_try_extend_data_file(fil_space_t* space, fsp_header_t* header, mtr_t* mtr)
"ran out of space. Please add another file or use"
" 'autoextend' for the last file in setting";
ut_d(fsp_space_modify_check(space, mtr));
ut_d(space->modify_check(*mtr));
if (space->id == TRX_SYS_SPACE
&& !srv_sys_space.can_auto_extend_last_file()) {
@ -896,8 +870,7 @@ fsp_try_extend_data_file(fil_space_t* space, fsp_header_t* header, mtr_t* mtr)
/* We ignore any fragments of a full megabyte when storing the size
to the space header */
space->size_in_header = ut_calc_align_down(
space->size, (1024 * 1024) / ps);
space->size_in_header = ut_2pow_round(space->size, (1024 * 1024) / ps);
mlog_write_ulint(
header + FSP_SIZE, space->size_in_header, MLOG_4BYTES, mtr);
@ -946,7 +919,7 @@ fsp_fill_free_list(
ulint i;
ut_ad(page_offset(header) == FSP_HEADER_OFFSET);
ut_d(fsp_space_modify_check(space, mtr));
ut_d(space->modify_check(*mtr));
/* Check if we can fill free list from above the free list limit */
size = mach_read_from_4(header + FSP_SIZE);
@ -979,8 +952,8 @@ fsp_fill_free_list(
while ((init_space && i < 1)
|| ((i + FSP_EXTENT_SIZE <= size) && (count < FSP_FREE_ADD))) {
bool init_xdes
= (ut_2pow_remainder(i, space->physical_size()) == 0);
const bool init_xdes = 0
== ut_2pow_remainder(i, ulint(space->physical_size()));
space->free_limit = i + FSP_EXTENT_SIZE;
mlog_write_ulint(header + FSP_FREE_LIMIT, i + FSP_EXTENT_SIZE,
@ -1253,7 +1226,7 @@ fsp_alloc_free_page(
ulint free;
const ulint space_id = space->id;
ut_d(fsp_space_modify_check(space, mtr));
ut_d(space->modify_check(*mtr));
header = fsp_get_space_header(space, mtr);
/* Get the hinted descriptor */
@ -1349,7 +1322,7 @@ static void fsp_free_page(fil_space_t* space, page_no_t offset, mtr_t* mtr)
ulint frag_n_used;
ut_ad(mtr);
ut_d(fsp_space_modify_check(space, mtr));
ut_d(space->modify_check(*mtr));
/* fprintf(stderr, "Freeing page %lu in space %lu\n", page, space); */
@ -1667,7 +1640,7 @@ static void fsp_free_seg_inode(
page_t* page;
fsp_header_t* space_header;
ut_d(fsp_space_modify_check(space, mtr));
ut_d(space->modify_check(*mtr));
page = page_align(inode);
@ -1918,7 +1891,7 @@ fseg_create(
<= srv_page_size - FIL_PAGE_DATA_END);
mtr_x_lock(&space->latch, mtr);
ut_d(fsp_space_modify_check(space, mtr));
ut_d(space->modify_check(*mtr));
if (page != 0) {
block = buf_page_get(page_id_t(space->id, page),
@ -2092,7 +2065,7 @@ fseg_fill_free_list(
ut_ad(inode && mtr);
ut_ad(!((page_offset(inode) - FSEG_ARR_OFFSET) % FSEG_INODE_SIZE));
ut_d(fsp_space_modify_check(space, mtr));
ut_d(space->modify_check(*mtr));
reserved = fseg_n_reserved_pages_low(inode, &used, mtr);
@ -2158,7 +2131,7 @@ fseg_alloc_free_extent(
ut_ad(!((page_offset(inode) - FSEG_ARR_OFFSET) % FSEG_INODE_SIZE));
ut_ad(mach_read_from_4(inode + FSEG_MAGIC_N) == FSEG_MAGIC_N_VALUE);
ut_d(fsp_space_modify_check(space, mtr));
ut_d(space->modify_check(*mtr));
if (flst_get_len(inode + FSEG_FREE) > 0) {
/* Segment free list is not empty, allocate from it */
@ -2243,7 +2216,7 @@ fseg_alloc_free_page_low(
seg_id = mach_read_from_8(seg_inode + FSEG_ID);
ut_ad(seg_id);
ut_d(fsp_space_modify_check(space, mtr));
ut_d(space->modify_check(*mtr));
ut_ad(fil_page_get_type(page_align(seg_inode)) == FIL_PAGE_INODE);
reserved = fseg_n_reserved_pages_low(seg_inode, &used, mtr);
@ -2775,7 +2748,7 @@ fseg_free_page_low(
ut_ad(mach_read_from_4(seg_inode + FSEG_MAGIC_N)
== FSEG_MAGIC_N_VALUE);
ut_ad(!((page_offset(seg_inode) - FSEG_ARR_OFFSET) % FSEG_INODE_SIZE));
ut_d(fsp_space_modify_check(space, mtr));
ut_d(space->modify_check(*mtr));
#ifdef BTR_CUR_HASH_ADAPT
/* Drop search system page hash index if the page is found in
the pool and is hashed */
@ -2873,35 +2846,39 @@ fseg_free_page_low(
fseg_free_page_low(inode, space, offset, mtr)
#endif /* !BTR_CUR_HASH_ADAPT */
/**********************************************************************//**
Frees a single page of a segment. */
/** Free a page in a file segment.
@param[in,out] seg_header file segment header
@param[in,out] space tablespace
@param[in] offset page number
@param[in] ahi whether we may need to drop the adaptive
hash index
@param[in,out] mtr mini-transaction */
void
fseg_free_page_func(
fseg_header_t* seg_header, /*!< in: segment header */
ulint space_id,/*!< in: space id */
ulint page, /*!< in: page offset */
fseg_header_t* seg_header,
fil_space_t* space,
ulint offset,
#ifdef BTR_CUR_HASH_ADAPT
bool ahi, /*!< in: whether we may need to drop
the adaptive hash index */
bool ahi,
#endif /* BTR_CUR_HASH_ADAPT */
mtr_t* mtr) /*!< in/out: mini-transaction */
mtr_t* mtr)
{
DBUG_ENTER("fseg_free_page");
fseg_inode_t* seg_inode;
buf_block_t* iblock;
fil_space_t* space = mtr_x_lock_space(space_id, mtr);
mtr_x_lock(&space->latch, mtr);
DBUG_LOG("fseg_free_page", "space_id: " << space_id
<< ", page_no: " << page);
DBUG_LOG("fseg_free_page", "space_id: " << space->id
<< ", page_no: " << offset);
seg_inode = fseg_inode_get(seg_header, space_id, space->zip_size(),
seg_inode = fseg_inode_get(seg_header, space->id, space->zip_size(),
mtr,
&iblock);
fil_block_check_type(*iblock, FIL_PAGE_INODE, mtr);
fseg_free_page_low(seg_inode, space, page, ahi, mtr);
fseg_free_page_low(seg_inode, space, offset, ahi, mtr);
ut_d(buf_page_set_file_page_was_freed(page_id_t(space_id, page)));
ut_d(buf_page_set_file_page_was_freed(page_id_t(space->id, offset)));
DBUG_VOID_RETURN;
}
@ -2968,7 +2945,7 @@ fseg_free_extent(
ut_a(!memcmp(descr + XDES_ID, seg_inode + FSEG_ID, 8));
ut_ad(mach_read_from_4(seg_inode + FSEG_MAGIC_N)
== FSEG_MAGIC_N_VALUE);
ut_d(fsp_space_modify_check(space, mtr));
ut_d(space->modify_check(*mtr));
first_page_in_extent = page - (page % FSP_EXTENT_SIZE);

View File

@ -4017,12 +4017,6 @@ static int innodb_init_params()
innodb_log_checksums = innodb_log_checksums_func_update(
NULL, innodb_log_checksums);
#ifdef HAVE_LINUX_LARGE_PAGES
if ((os_use_large_pages = my_use_large_pages)) {
os_large_page_size = opt_large_page_size;
}
#endif
row_rollback_on_timeout = (ibool) innobase_rollback_on_timeout;
srv_locks_unsafe_for_binlog = (ibool) innobase_locks_unsafe_for_binlog;

View File

@ -2090,8 +2090,9 @@ ibuf_remove_free_page(void)
the free list was so long that they cannot have taken the last
page from it. */
compile_time_assert(IBUF_SPACE_ID == 0);
fseg_free_page(header_page + IBUF_HEADER + IBUF_TREE_SEG_HEADER,
IBUF_SPACE_ID, page_no, false, &mtr);
fil_system.sys_space, page_no, false, &mtr);
const page_id_t page_id(IBUF_SPACE_ID, page_no);

View File

@ -676,16 +676,6 @@ btr_page_alloc(
for x-latching and initializing
the page */
MY_ATTRIBUTE((warn_unused_result));
/**************************************************************//**
Frees a file page used in an index tree. NOTE: cannot free field external
storage pages because the page must contain info on its level. */
void
btr_page_free(
/*==========*/
dict_index_t* index, /*!< in: index tree */
buf_block_t* block, /*!< in: block to be freed, x-latched */
mtr_t* mtr) /*!< in: mtr */
MY_ATTRIBUTE((nonnull));
/** Empty an index page (possibly the root page). @see btr_page_create().
@param[in,out] block page to be emptied
@param[in,out] page_zip compressed page frame, or NULL
@ -711,18 +701,16 @@ btr_page_create(
dict_index_t* index, /*!< in: index */
ulint level, /*!< in: the B-tree level of the page */
mtr_t* mtr); /*!< in: mtr */
/**************************************************************//**
Frees a file page used in an index tree. Can be used also to BLOB
external storage pages. */
void
btr_page_free_low(
/*==============*/
dict_index_t* index, /*!< in: index tree */
buf_block_t* block, /*!< in: block to be freed, x-latched */
ulint level, /*!< in: page level (ULINT_UNDEFINED=BLOB) */
bool blob, /*!< in: blob page */
mtr_t* mtr) /*!< in: mtr */
MY_ATTRIBUTE((nonnull(1,2)));
/** Free an index page.
@param[in,out] index index tree
@param[in,out] block block to be freed
@param[in,out] mtr mini-transaction
@param[in] blob whether this is freeing a BLOB page */
MY_ATTRIBUTE((nonnull))
void btr_page_free(dict_index_t* index, buf_block_t* block, mtr_t* mtr,
bool blob = false);
/**************************************************************//**
Gets the root node of a tree and x- or s-latches it.
@return root page, x- or s-latched */

View File

@ -105,7 +105,7 @@ struct fil_space_t {
bool is_being_truncated;
#ifdef UNIV_DEBUG
/** reference count for operations who want to skip redo log in the
file space in order to make fsp_space_modify_check pass. */
file space in order to make modify_check() pass. */
Atomic_counter<ulint> redo_skipped_count;
#endif
fil_type_t purpose;/*!< purpose */
@ -198,6 +198,12 @@ struct fil_space_t {
fil_node_t* add(const char* name, pfs_os_file_t handle,
ulint size, bool is_raw, bool atomic_write,
ulint max_pages = ULINT_MAX);
#ifdef UNIV_DEBUG
/** Assert that the mini-transaction is compatible with
updating an allocation bitmap page.
@param[in] mtr mini-transaction */
void modify_check(const mtr_t& mtr) const;
#endif /* UNIV_DEBUG */
/** Try to reserve free extents.
@param[in] n_free_now current number of free extents

View File

@ -484,24 +484,28 @@ fsp_reserve_free_extents(
mtr_t* mtr,
ulint n_pages = 2);
/**********************************************************************//**
Frees a single page of a segment. */
/** Free a page in a file segment.
@param[in,out] seg_header file segment header
@param[in,out] space tablespace
@param[in] offset page number
@param[in] ahi whether we may need to drop the adaptive
hash index
@param[in,out] mtr mini-transaction */
void
fseg_free_page_func(
fseg_header_t* seg_header, /*!< in: segment header */
ulint space_id, /*!< in: space id */
ulint page, /*!< in: page offset */
fseg_header_t* seg_header,
fil_space_t* space,
ulint offset,
#ifdef BTR_CUR_HASH_ADAPT
bool ahi, /*!< in: whether we may need to drop
the adaptive hash index */
bool ahi,
#endif /* BTR_CUR_HASH_ADAPT */
mtr_t* mtr); /*!< in/out: mini-transaction */
mtr_t* mtr);
#ifdef BTR_CUR_HASH_ADAPT
# define fseg_free_page(header, space_id, page, ahi, mtr) \
fseg_free_page_func(header, space_id, page, ahi, mtr)
# define fseg_free_page(header, space, offset, ahi, mtr) \
fseg_free_page_func(header, space, offset, ahi, mtr)
#else /* BTR_CUR_HASH_ADAPT */
# define fseg_free_page(header, space_id, page, ahi, mtr) \
fseg_free_page_func(header, space_id, page, mtr)
# define fseg_free_page(header, space, offset, ahi, mtr) \
fseg_free_page_func(header, space, offset, mtr)
#endif /* BTR_CUR_HASH_ADAPT */
/** Determine whether a page is free.
@param[in,out] space tablespace
@ -606,6 +610,26 @@ inline bool fsp_descr_page(const page_id_t page_id, ulint physical_size)
@param[in,out] block buffer pool block */
void fsp_apply_init_file_page(buf_block_t* block);
/** Initialize a file page.
@param[in] space tablespace
@param[in,out] block file page
@param[in,out] mtr mini-transaction */
inline void fsp_init_file_page(
#ifdef UNIV_DEBUG
const fil_space_t* space,
#endif
buf_block_t* block, mtr_t* mtr)
{
ut_d(space->modify_check(*mtr));
ut_ad(space->id == block->page.id.space());
fsp_apply_init_file_page(block);
mlog_write_initial_log_record(block->frame, MLOG_INIT_FILE_PAGE2, mtr);
}
#ifndef UNIV_DEBUG
# define fsp_init_file_page(space, block, mtr) fsp_init_file_page(block, mtr)
#endif
#ifdef UNIV_BTR_PRINT
/*******************************************************************//**
Writes info of a segment. */
@ -764,8 +788,9 @@ xdes_get_bit(
@return descriptor index */
inline ulint xdes_calc_descriptor_index(ulint zip_size, ulint offset)
{
return(ut_2pow_remainder(offset, zip_size ? zip_size : srv_page_size)
/ FSP_EXTENT_SIZE);
return ut_2pow_remainder<ulint>(offset,
zip_size ? zip_size : srv_page_size)
/ FSP_EXTENT_SIZE;
}
/** Determine the descriptor page number for a page.
@ -790,7 +815,8 @@ inline ulint xdes_calc_descriptor_page(ulint zip_size, ulint offset)
ut_ad(!zip_size
|| zip_size > XDES_ARR_OFFSET
+ (zip_size / FSP_EXTENT_SIZE) * XDES_SIZE);
return ut_2pow_round(offset, zip_size ? zip_size : srv_page_size);
return ut_2pow_round<ulint>(offset,
zip_size ? zip_size : srv_page_size);
}
#endif /* UNIV_INNOCHECKSUM */

View File

@ -2,7 +2,7 @@
Copyright (c) 1995, 2017, Oracle and/or its affiliates. All rights reserved.
Copyright (c) 2009, Google Inc.
Copyright (c) 2017, 2018, MariaDB Corporation.
Copyright (c) 2017, 2019, MariaDB Corporation.
Portions of this file contain modifications contributed and copyrighted by
Google, Inc. Those modifications are gratefully acknowledged and are described
@ -559,11 +559,12 @@ struct log_t{
uint32_t subformat;
/** individual log file size in bytes, including the header */
lsn_t file_size;
private:
/** lsn used to fix coordinates within the log group */
lsn_t lsn;
/** the byte offset of the above lsn */
lsn_t lsn_offset;
public:
/** used only in recovery: recovery scan succeeded up to this
lsn in this log group */
lsn_t scanned_lsn;
@ -580,8 +581,9 @@ struct log_t{
/** Set the field values to correspond to a given lsn. */
void set_fields(lsn_t lsn)
{
lsn_offset = calc_lsn_offset(lsn);
this->lsn = lsn;
lsn_t c_lsn_offset = calc_lsn_offset(lsn);
set_lsn(lsn);
set_lsn_offset(c_lsn_offset);
}
/** Read a log segment to log_sys.buf.
@ -600,6 +602,10 @@ struct log_t{
{
n_files = 0;
}
void set_lsn(lsn_t a_lsn);
lsn_t get_lsn() const { return lsn; }
void set_lsn_offset(lsn_t a_lsn);
lsn_t get_lsn_offset() const { return lsn_offset; }
} log;
/** The fields involved in the log buffer flush @{ */
@ -760,6 +766,17 @@ inline lsn_t log_t::files::calc_lsn_offset(lsn_t lsn) const
return l + LOG_FILE_HDR_SIZE * (1 + l / (file_size - LOG_FILE_HDR_SIZE));
}
inline void log_t::files::set_lsn(lsn_t a_lsn) {
ut_ad(log_sys.mutex.is_owned() || log_sys.write_mutex.is_owned());
lsn = a_lsn;
}
inline void log_t::files::set_lsn_offset(lsn_t a_lsn) {
ut_ad(log_sys.mutex.is_owned() || log_sys.write_mutex.is_owned());
ut_ad((lsn % OS_FILE_LOG_BLOCK_SIZE) == (a_lsn % OS_FILE_LOG_BLOCK_SIZE));
lsn_offset = a_lsn;
}
/** Test if flush order mutex is owned. */
#define log_flush_order_mutex_own() \
mutex_own(&log_sys.log_flush_order_mutex)

View File

@ -1,7 +1,7 @@
/*****************************************************************************
Copyright (c) 1994, 2016, Oracle and/or its affiliates. All Rights Reserved.
Copyright (c) 2017, 2018, MariaDB Corporation.
Copyright (c) 2017, 2019, MariaDB Corporation.
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
@ -77,7 +77,7 @@ is the maximum size for a single allocated buffer: */
/** Space needed when allocating for a user a field of length N.
The space is allocated only in multiples of UNIV_MEM_ALIGNMENT. */
#define MEM_SPACE_NEEDED(N) ut_calc_align((N), UNIV_MEM_ALIGNMENT)
#define MEM_SPACE_NEEDED(N) UT_CALC_ALIGN((N), UNIV_MEM_ALIGNMENT)
#ifdef UNIV_DEBUG
/** Macro for memory heap creation.
@ -348,8 +348,8 @@ struct mem_block_info_t {
#define MEM_FREED_BLOCK_MAGIC_N 547711122
/* Header size for a memory heap block */
#define MEM_BLOCK_HEADER_SIZE ut_calc_align(sizeof(mem_block_info_t),\
UNIV_MEM_ALIGNMENT)
#define MEM_BLOCK_HEADER_SIZE UT_CALC_ALIGN(sizeof(mem_block_info_t),\
UNIV_MEM_ALIGNMENT)
#include "mem0mem.ic"
#endif

View File

@ -1,7 +1,7 @@
/*****************************************************************************
Copyright (c) 1995, 2016, Oracle and/or its affiliates. All Rights Reserved.
Copyright (c) 2017, MariaDB Corporation.
Copyright (c) 2017, 2019, MariaDB Corporation.
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
@ -42,12 +42,6 @@ typedef unsigned long int os_process_id_t;
system with os_mem_alloc_large(). */
extern Atomic_counter<ulint> os_total_large_mem_allocated;
/** Whether to use large pages in the buffer pool */
extern my_bool os_use_large_pages;
/** Large page size. This may be a boot-time option on some platforms */
extern uint os_large_page_size;
/** Converts the current process id to a number.
@return process id as a number */
ulint

View File

@ -1,6 +1,7 @@
/*****************************************************************************
Copyright (c) 1994, 2016, Oracle and/or its affiliates. All Rights Reserved.
Copyright (c) 2019, MariaDB Corporation.
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
@ -127,26 +128,23 @@ Calculates fast the remainder of n/m when m is a power of two.
@param n in: numerator
@param m in: denominator, must be a power of two
@return the remainder of n/m */
#define ut_2pow_remainder(n, m) ((n) & ((m) - 1))
template <typename T> inline T ut_2pow_remainder(T n, T m){return n & (m - 1);}
/*************************************************************//**
Calculates the biggest multiple of m that is not bigger than n
when m is a power of two. In other words, rounds n down to m * k.
@param n in: number to round down
@param m in: alignment, must be a power of two
@return n rounded down to the biggest possible integer multiple of m */
#define ut_2pow_round(n, m) ((n) & ~((m) - 1))
/** Align a number down to a multiple of a power of two.
@param n in: number to round down
@param m in: alignment, must be a power of two
@return n rounded down to the biggest possible integer multiple of m */
#define ut_calc_align_down(n, m) ut_2pow_round(n, m)
template <typename T> inline T ut_2pow_round(T n, T m) { return n & ~(m - 1); }
/********************************************************//**
Calculates the smallest multiple of m that is not smaller than n
when m is a power of two. In other words, rounds n up to m * k.
@param n in: number to round up
@param m in: alignment, must be a power of two
@return n rounded up to the smallest possible integer multiple of m */
#define ut_calc_align(n, m) (((n) + ((m) - 1)) & ~((m) - 1))
#define UT_CALC_ALIGN(n, m) ((n + m - 1) & ~(m - 1))
template <typename T> inline T ut_calc_align(T n, T m)
{ return UT_CALC_ALIGN(n, m); }
/*************************************************************//**
Calculates fast the 2-logarithm of a number, rounded upward to an

View File

@ -193,10 +193,8 @@ void log_buffer_extend(ulong len)
log_sys.is_extending = true;
while (ut_calc_align_down(log_sys.buf_free,
OS_FILE_LOG_BLOCK_SIZE)
!= ut_calc_align_down(log_sys.buf_next_to_write,
OS_FILE_LOG_BLOCK_SIZE)) {
while ((log_sys.buf_free ^ log_sys.buf_next_to_write)
& (OS_FILE_LOG_BLOCK_SIZE - 1)) {
/* Buffer might have >1 blocks to write still. */
log_mutex_exit_all();
@ -205,9 +203,8 @@ void log_buffer_extend(ulong len)
log_mutex_enter_all();
}
ulong move_start = ut_calc_align_down(
log_sys.buf_free,
OS_FILE_LOG_BLOCK_SIZE);
ulong move_start = ut_2pow_round(log_sys.buf_free,
ulong(OS_FILE_LOG_BLOCK_SIZE));
ulong move_end = log_sys.buf_free;
/* store the last log block in buffer */
@ -896,8 +893,8 @@ log_buffer_switch()
ut_ad(log_write_mutex_own());
const byte* old_buf = log_sys.buf;
ulint area_end = ut_calc_align(log_sys.buf_free,
OS_FILE_LOG_BLOCK_SIZE);
ulong area_end = ut_calc_align(
log_sys.buf_free, ulong(OS_FILE_LOG_BLOCK_SIZE));
if (log_sys.first_in_use) {
log_sys.first_in_use = false;
@ -1031,8 +1028,9 @@ loop:
start_offset = log_sys.buf_next_to_write;
end_offset = log_sys.buf_free;
area_start = ut_calc_align_down(start_offset, OS_FILE_LOG_BLOCK_SIZE);
area_end = ut_calc_align(end_offset, OS_FILE_LOG_BLOCK_SIZE);
area_start = ut_2pow_round(start_offset,
ulint(OS_FILE_LOG_BLOCK_SIZE));
area_end = ut_calc_align(end_offset, ulint(OS_FILE_LOG_BLOCK_SIZE));
ut_ad(area_end - area_start > 0);

View File

@ -987,11 +987,12 @@ recv_find_max_checkpoint_0(ulint* max_field)
*max_field = field;
max_no = checkpoint_no;
log_sys.log.lsn = mach_read_from_8(
buf + LOG_CHECKPOINT_LSN);
log_sys.log.lsn_offset = static_cast<ib_uint64_t>(
mach_read_from_4(buf + OFFSET_HIGH32)) << 32
| mach_read_from_4(buf + OFFSET_LOW32);
log_sys.log.set_lsn(mach_read_from_8(
buf + LOG_CHECKPOINT_LSN));
log_sys.log.set_lsn_offset(
lsn_t(mach_read_from_4(buf + OFFSET_HIGH32))
<< 32
| mach_read_from_4(buf + OFFSET_LOW32));
}
}
@ -1152,10 +1153,10 @@ recv_find_max_checkpoint(ulint* max_field)
if (checkpoint_no >= max_no) {
*max_field = field;
max_no = checkpoint_no;
log_sys.log.lsn = mach_read_from_8(
buf + LOG_CHECKPOINT_LSN);
log_sys.log.lsn_offset = mach_read_from_8(
buf + LOG_CHECKPOINT_OFFSET);
log_sys.log.set_lsn(mach_read_from_8(
buf + LOG_CHECKPOINT_LSN));
log_sys.log.set_lsn_offset(mach_read_from_8(
buf + LOG_CHECKPOINT_OFFSET));
log_sys.next_checkpoint_no = checkpoint_no;
}
}
@ -3625,8 +3626,8 @@ recv_reset_logs(
log_sys.lsn = ut_uint64_align_up(lsn, OS_FILE_LOG_BLOCK_SIZE);
log_sys.log.lsn = log_sys.lsn;
log_sys.log.lsn_offset = LOG_FILE_HDR_SIZE;
log_sys.log.set_lsn(log_sys.lsn);
log_sys.log.set_lsn_offset(LOG_FILE_HDR_SIZE);
log_sys.buf_next_to_write = 0;
log_sys.write_lsn = log_sys.lsn;

View File

@ -1,6 +1,7 @@
/*****************************************************************************
Copyright (c) 1995, 2016, Oracle and/or its affiliates. All Rights Reserved.
Copyright (c) 2019, MariaDB Corporation.
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
@ -25,6 +26,9 @@ Created 9/30/1995 Heikki Tuuri
*******************************************************/
#include "univ.i"
#ifdef HAVE_LINUX_LARGE_PAGES
# include "mysqld.h"
#endif
/* FreeBSD for example has only MAP_ANON, Linux has MAP_ANONYMOUS and
MAP_ANON but MAP_ANON is marked as deprecated */
@ -38,12 +42,6 @@ MAP_ANON but MAP_ANON is marked as deprecated */
system with os_mem_alloc_large(). */
Atomic_counter<ulint> os_total_large_mem_allocated;
/** Whether to use large pages in the buffer pool */
my_bool os_use_large_pages;
/** Large page size. This may be a boot-time option on some platforms */
uint os_large_page_size;
/** Converts the current process id to a number.
@return process id as a number */
ulint
@ -66,18 +64,18 @@ os_mem_alloc_large(
{
void* ptr;
ulint size;
#if defined HAVE_LINUX_LARGE_PAGES && defined UNIV_LINUX
#ifdef HAVE_LINUX_LARGE_PAGES
int shmid;
struct shmid_ds buf;
if (!os_use_large_pages || !os_large_page_size) {
if (!my_use_large_pages || !opt_large_page_size) {
goto skip;
}
/* Align block size to os_large_page_size */
ut_ad(ut_is_2pow(os_large_page_size));
size = ut_2pow_round(*n + (os_large_page_size - 1),
os_large_page_size);
/* Align block size to opt_large_page_size */
ut_ad(ut_is_2pow(opt_large_page_size));
size = ut_2pow_round(*n + opt_large_page_size - 1,
ulint(opt_large_page_size));
shmid = shmget(IPC_PRIVATE, (size_t) size, SHM_HUGETLB | SHM_R | SHM_W);
if (shmid < 0) {
@ -107,7 +105,7 @@ os_mem_alloc_large(
ib::warn() << "Using conventional memory pool";
skip:
#endif /* HAVE_LINUX_LARGE_PAGES && UNIV_LINUX */
#endif /* HAVE_LINUX_LARGE_PAGES */
#ifdef _WIN32
SYSTEM_INFO system_info;
@ -115,10 +113,8 @@ skip:
/* Align block size to system page size */
ut_ad(ut_is_2pow(system_info.dwPageSize));
/* system_info.dwPageSize is only 32-bit. Casting to ulint is required
on 64-bit Windows. */
size = *n = ut_2pow_round(*n + (system_info.dwPageSize - 1),
(ulint) system_info.dwPageSize);
size = *n = ut_2pow_round<ulint>(*n + (system_info.dwPageSize - 1),
system_info.dwPageSize);
ptr = VirtualAlloc(NULL, size, MEM_COMMIT | MEM_RESERVE,
PAGE_READWRITE);
if (!ptr) {
@ -157,12 +153,12 @@ os_mem_free_large(
{
ut_a(os_total_large_mem_allocated >= size);
#if defined HAVE_LINUX_LARGE_PAGES && defined UNIV_LINUX
if (os_use_large_pages && os_large_page_size && !shmdt(ptr)) {
#ifdef HAVE_LINUX_LARGE_PAGES
if (my_use_large_pages && opt_large_page_size && !shmdt(ptr)) {
os_total_large_mem_allocated -= size;
return;
}
#endif /* HAVE_LINUX_LARGE_PAGES && UNIV_LINUX */
#endif /* HAVE_LINUX_LARGE_PAGES */
#ifdef _WIN32
/* When RELEASE memory, the size parameter must be 0.
Do not use MEM_RELEASE with MEM_DECOMMIT. */

View File

@ -831,35 +831,30 @@ trx_undo_free_page(
undo log page; the caller must have reserved
the rollback segment mutex */
{
page_t* header_page;
page_t* undo_page;
fil_addr_t last_addr;
trx_rsegf_t* rseg_header;
ulint hist_size;
const ulint space = rseg->space->id;
ut_a(hdr_page_no != page_no);
ut_ad(mutex_own(&(rseg->mutex)));
undo_page = trx_undo_page_get(page_id_t(space, page_no), mtr);
page_t* undo_page = trx_undo_page_get(page_id_t(space, page_no), mtr);
page_t* header_page = trx_undo_page_get(page_id_t(space, hdr_page_no),
mtr);
header_page = trx_undo_page_get(page_id_t(space, hdr_page_no), mtr);
flst_remove(TRX_UNDO_SEG_HDR + TRX_UNDO_PAGE_LIST + header_page,
TRX_UNDO_PAGE_HDR + TRX_UNDO_PAGE_NODE + undo_page, mtr);
flst_remove(header_page + TRX_UNDO_SEG_HDR + TRX_UNDO_PAGE_LIST,
undo_page + TRX_UNDO_PAGE_HDR + TRX_UNDO_PAGE_NODE, mtr);
fseg_free_page(TRX_UNDO_SEG_HDR + TRX_UNDO_FSEG_HEADER + header_page,
rseg->space, page_no, false, mtr);
fseg_free_page(header_page + TRX_UNDO_SEG_HDR + TRX_UNDO_FSEG_HEADER,
space, page_no, false, mtr);
last_addr = flst_get_last(header_page + TRX_UNDO_SEG_HDR
+ TRX_UNDO_PAGE_LIST, mtr);
const fil_addr_t last_addr = flst_get_last(
TRX_UNDO_SEG_HDR + TRX_UNDO_PAGE_LIST + header_page, mtr);
rseg->curr_size--;
if (in_history) {
rseg_header = trx_rsegf_get(rseg->space, rseg->page_no, mtr);
hist_size = mtr_read_ulint(rseg_header + TRX_RSEG_HISTORY_SIZE,
MLOG_4BYTES, mtr);
trx_rsegf_t* rseg_header = trx_rsegf_get(
rseg->space, rseg->page_no, mtr);
uint32_t hist_size = mach_read_from_4(
rseg_header + TRX_RSEG_HISTORY_SIZE);
ut_ad(hist_size > 0);
mlog_write_ulint(rseg_header + TRX_RSEG_HISTORY_SIZE,
hist_size - 1, MLOG_4BYTES, mtr);

View File

@ -5,8 +5,8 @@ MACRO(SKIP_ROCKSDB_PLUGIN msg)
RETURN()
ENDMACRO()
IF (NOT EXISTS "${CMAKE_CURRENT_SOURCE_DIR}/rocksdb/Makefile")
SKIP_ROCKSDB_PLUGIN("Missing Makefile in rocksdb directory. Try \"git submodule update\".")
IF (NOT EXISTS "${CMAKE_CURRENT_SOURCE_DIR}/rocksdb/CMakeLists.txt")
SKIP_ROCKSDB_PLUGIN("Missing CMakeLists.txt in rocksdb directory. Try \"git submodule update\".")
ENDIF()
CHECK_LIBRARY_EXISTS(rt timer_delete "" HAVE_TIMER_DELETE)