Many files:

  Multiple tablespaces for InnoDB
sql_table.cc:
  Tell explicitly that InnoDB should retrieve all columns in CHECKSUM TABLE
sql_update.cc, sql_select.cc, my_base.h:
  More descriptive flag name HA_EXTRA_RETRIEVE_ALL_COLS
parent 862ff0ed
......@@ -121,7 +121,10 @@ enum ha_extra_function {
HA_EXTRA_RESET_STATE, /* Reset positions */
HA_EXTRA_IGNORE_DUP_KEY, /* Dup keys don't rollback everything*/
HA_EXTRA_NO_IGNORE_DUP_KEY,
HA_EXTRA_DONT_USE_CURSOR_TO_UPDATE, /* Cursor will not be used for update */
HA_EXTRA_RETRIEVE_ALL_COLS, /* Instructs InnoDB to retrieve all
columns, not just those where
field->query_id is the same as the
current query id */
HA_EXTRA_PREPARE_FOR_DELETE,
HA_EXTRA_PREPARE_FOR_UPDATE, /* Remove read cache if problems */
HA_EXTRA_PRELOAD_BUFFER_SIZE /* Set buffer size for preloading */
......
......@@ -957,7 +957,7 @@ btr_cur_optimistic_insert(
/* Now, try the insert */
*rec = page_cur_insert_rec_low(page_cursor, entry, data_size,
NULL, mtr);
NULL, mtr);
if (!(*rec)) {
/* If the record did not fit, reorganize */
btr_page_reorganize(page, mtr);
......@@ -1048,6 +1048,7 @@ btr_cur_pessimistic_insert(
ibool dummy_inh;
ibool success;
ulint n_extents = 0;
ulint n_reserved;
ut_ad(dtuple_check_typed(entry));
......@@ -1067,7 +1068,7 @@ btr_cur_pessimistic_insert(
cursor->flag = BTR_CUR_BINARY;
err = btr_cur_optimistic_insert(flags, cursor, entry, rec, big_rec,
thr, mtr);
thr, mtr);
if (err != DB_FAIL) {
return(err);
......@@ -1090,7 +1091,7 @@ btr_cur_pessimistic_insert(
n_extents = cursor->tree_height / 16 + 3;
success = fsp_reserve_free_extents(index->space,
success = fsp_reserve_free_extents(&n_reserved, index->space,
n_extents, FSP_NORMAL, mtr);
if (!success) {
err = DB_OUT_OF_FILE_SPACE;
......@@ -1112,7 +1113,7 @@ btr_cur_pessimistic_insert(
if (n_extents > 0) {
fil_space_release_free_extents(index->space,
n_extents);
n_reserved);
}
return(DB_TOO_BIG_RECORD);
}
......@@ -1140,7 +1141,7 @@ btr_cur_pessimistic_insert(
err = DB_SUCCESS;
if (n_extents > 0) {
fil_space_release_free_extents(index->space, n_extents);
fil_space_release_free_extents(index->space, n_reserved);
}
*big_rec = big_rec_vec;
......@@ -1721,6 +1722,7 @@ btr_cur_pessimistic_update(
ibool was_first;
ibool success;
ulint n_extents = 0;
ulint n_reserved;
ulint* ext_vect;
ulint n_ext_vect;
ulint reserve_flag;
......@@ -1767,7 +1769,8 @@ btr_cur_pessimistic_update(
reserve_flag = FSP_NORMAL;
}
success = fsp_reserve_free_extents(cursor->index->space,
success = fsp_reserve_free_extents(&n_reserved,
cursor->index->space,
n_extents, reserve_flag, mtr);
if (!success) {
err = DB_OUT_OF_FILE_SPACE;
......@@ -1916,7 +1919,7 @@ btr_cur_pessimistic_update(
if (n_extents > 0) {
fil_space_release_free_extents(cursor->index->space,
n_extents);
n_reserved);
}
*big_rec = big_rec_vec;
......@@ -2387,6 +2390,7 @@ btr_cur_pessimistic_delete(
rec_t* rec;
dtuple_t* node_ptr;
ulint n_extents = 0;
ulint n_reserved;
ibool success;
ibool ret = FALSE;
mem_heap_t* heap;
......@@ -2405,7 +2409,8 @@ btr_cur_pessimistic_delete(
n_extents = cursor->tree_height / 32 + 1;
success = fsp_reserve_free_extents(cursor->index->space,
success = fsp_reserve_free_extents(&n_reserved,
cursor->index->space,
n_extents, FSP_CLEANING, mtr);
if (!success) {
*err = DB_OUT_OF_FILE_SPACE;
......@@ -2484,7 +2489,8 @@ btr_cur_pessimistic_delete(
}
if (n_extents > 0) {
fil_space_release_free_extents(cursor->index->space, n_extents);
fil_space_release_free_extents(cursor->index->space,
n_reserved);
}
return(ret);
......@@ -3156,7 +3162,7 @@ btr_store_big_rec_extern_fields(
ut_ad(mtr_memo_contains(local_mtr, dict_tree_get_lock(index->tree),
MTR_MEMO_X_LOCK));
ut_ad(mtr_memo_contains(local_mtr, buf_block_align(rec),
MTR_MEMO_PAGE_X_FIX));
MTR_MEMO_PAGE_X_FIX));
ut_a(index->type & DICT_CLUSTERED);
space_id = buf_frame_get_space_id(rec);
......@@ -3322,7 +3328,7 @@ btr_free_externally_stored_field(
ut_ad(mtr_memo_contains(local_mtr, dict_tree_get_lock(index->tree),
MTR_MEMO_X_LOCK));
ut_ad(mtr_memo_contains(local_mtr, buf_block_align(data),
MTR_MEMO_PAGE_X_FIX));
MTR_MEMO_PAGE_X_FIX));
ut_a(local_len >= BTR_EXTERN_FIELD_REF_SIZE);
local_len -= BTR_EXTERN_FIELD_REF_SIZE;
......
......@@ -1022,12 +1022,14 @@ btr_search_drop_page_hash_when_freed(
mtr_start(&mtr);
/* We assume that if the caller has a latch on the page,
then the caller has already dropped the hash index for the page,
and we never get here. Therefore we can acquire the s-latch to
the page without fearing a deadlock. */
/* We assume that if the caller has a latch on the page, then the
caller has already dropped the hash index for the page, and we never
get here. Therefore we can acquire the s-latch to the page without
having to fear a deadlock. */
page = buf_page_get(space, page_no, RW_S_LATCH, &mtr);
page = buf_page_get_gen(space, page_no, RW_S_LATCH, NULL,
BUF_GET_IF_IN_POOL, IB__FILE__, __LINE__,
&mtr);
buf_page_dbg_add_level(page, SYNC_TREE_NODE_FROM_HASH);
......
......@@ -243,9 +243,10 @@ buf_calc_page_new_checksum(
{
ulint checksum;
/* Since the fields FIL_PAGE_FILE_FLUSH_LSN and ..._ARCH_LOG_NO
are written outside the buffer pool to the first pages of data
files, we have to skip them in the page checksum calculation.
/* Since the field FIL_PAGE_FILE_FLUSH_LSN, and in versions <= 4.1.x
..._ARCH_LOG_NO, are written outside the buffer pool to the first
pages of data files, we have to skip them in the page checksum
calculation.
We must also skip the field FIL_PAGE_SPACE_OR_CHKSUM where the
checksum is stored, and also the last 8 bytes of page because
there we store the old formula checksum. */
......@@ -255,7 +256,7 @@ buf_calc_page_new_checksum(
+ ut_fold_binary(page + FIL_PAGE_DATA,
UNIV_PAGE_SIZE - FIL_PAGE_DATA
- FIL_PAGE_END_LSN_OLD_CHKSUM);
checksum = checksum & 0xFFFFFFFF;
checksum = checksum & 0xFFFFFFFFUL;
return(checksum);
}
......@@ -278,7 +279,7 @@ buf_calc_page_old_checksum(
checksum = ut_fold_binary(page, FIL_PAGE_FILE_FLUSH_LSN);
checksum = checksum & 0xFFFFFFFF;
checksum = checksum & 0xFFFFFFFFUL;
return(checksum);
}
......@@ -378,7 +379,7 @@ buf_page_print(
ut_print_timestamp(stderr);
fprintf(stderr,
" InnoDB: Page dump in ascii and hex (%lu bytes):\n%s",
" InnoDB: Page dump in ascii and hex (%lu bytes):\n%s",
(ulint)UNIV_PAGE_SIZE, buf);
fprintf(stderr, "InnoDB: End of page dump\n");
......@@ -396,11 +397,16 @@ buf_page_print(
mach_read_from_4(read_buf + UNIV_PAGE_SIZE
- FIL_PAGE_END_LSN_OLD_CHKSUM));
fprintf(stderr,
"InnoDB: Page lsn %lu %lu, low 4 bytes of lsn at page end %lu\n",
"InnoDB: Page lsn %lu %lu, low 4 bytes of lsn at page end %lu\n"
"InnoDB: Page number (if stored to page already) %lu,\n"
"InnoDB: space id (if created with >= MySQL-4.1.1 and stored already) %lu\n",
mach_read_from_4(read_buf + FIL_PAGE_LSN),
mach_read_from_4(read_buf + FIL_PAGE_LSN + 4),
mach_read_from_4(read_buf + UNIV_PAGE_SIZE
- FIL_PAGE_END_LSN_OLD_CHKSUM + 4));
- FIL_PAGE_END_LSN_OLD_CHKSUM + 4),
mach_read_from_4(read_buf + FIL_PAGE_OFFSET),
mach_read_from_4(read_buf + FIL_PAGE_ARCH_LOG_NO_OR_SPACE_ID));
if (mach_read_from_2(read_buf + TRX_UNDO_PAGE_HDR + TRX_UNDO_PAGE_TYPE)
== TRX_UNDO_INSERT) {
fprintf(stderr,
......@@ -414,10 +420,7 @@ buf_page_print(
if (fil_page_get_type(read_buf) == FIL_PAGE_INDEX) {
fprintf(stderr,
"InnoDB: Page may be an index page ");
fprintf(stderr,
"where index id is %lu %lu\n",
"InnoDB: Page may be an index page where index id is %lu %lu\n",
ut_dulint_get_high(btr_page_get_index_id(read_buf)),
ut_dulint_get_low(btr_page_get_index_id(read_buf)));
......@@ -435,7 +438,6 @@ buf_page_print(
index->name);
}
}
} else if (fil_page_get_type(read_buf) == FIL_PAGE_INODE) {
fprintf(stderr, "InnoDB: Page may be an 'inode' page\n");
} else if (fil_page_get_type(read_buf) == FIL_PAGE_IBUF_FREE_LIST) {
......@@ -581,8 +583,8 @@ buf_pool_init(
the window */
os_awe_map_physical_mem_to_window(buf_pool->frame_zero,
n_frames *
(UNIV_PAGE_SIZE / OS_AWE_X86_PAGE_SIZE),
n_frames *
(UNIV_PAGE_SIZE / OS_AWE_X86_PAGE_SIZE),
buf_pool->awe_info);
/*----------------------------------------*/
}
......@@ -1554,25 +1556,35 @@ buf_page_init(
/************************************************************************
Function which inits a page for read to the buffer buf_pool. If the page is
already in buf_pool, does nothing. Sets the io_fix flag to BUF_IO_READ and
sets a non-recursive exclusive lock on the buffer frame. The io-handler must
take care that the flag is cleared and the lock released later. This is one
of the functions which perform the state transition NOT_USED => FILE_PAGE to
a block (the other is buf_page_create). */
(1) already in buf_pool, or
(2) if we specify to read only ibuf pages and the page is not an ibuf page, or
(3) if the space is deleted or being deleted,
then this function does nothing.
Sets the io_fix flag to BUF_IO_READ and sets a non-recursive exclusive lock
on the buffer frame. The io-handler must take care that the flag is cleared
and the lock released later. This is one of the functions which perform the
state transition NOT_USED => FILE_PAGE to a block (the other is
buf_page_create). */
buf_block_t*
buf_page_init_for_read(
/*===================*/
/* out: pointer to the block or NULL */
ulint mode, /* in: BUF_READ_IBUF_PAGES_ONLY, ... */
ulint space, /* in: space id */
ulint offset) /* in: page number */
/* out: pointer to the block or NULL */
ulint* err, /* out: DB_SUCCESS or DB_TABLESPACE_DELETED */
ulint mode, /* in: BUF_READ_IBUF_PAGES_ONLY, ... */
ulint space, /* in: space id */
ib_longlong tablespace_version,/* in: prevents reading from a wrong
version of the tablespace in case we have done
DISCARD + IMPORT */
ulint offset) /* in: page number */
{
buf_block_t* block;
mtr_t mtr;
ut_ad(buf_pool);
*err = DB_SUCCESS;
if (mode == BUF_READ_IBUF_PAGES_ONLY) {
/* It is a read-ahead within an ibuf routine */
......@@ -1596,10 +1608,17 @@ buf_page_init_for_read(
ut_ad(block);
mutex_enter(&(buf_pool->mutex));
if (NULL != buf_page_hash_get(space, offset)) {
/* The page is already in buf_pool, return */
if (fil_tablespace_deleted_or_being_deleted_in_mem(space,
tablespace_version)) {
*err = DB_TABLESPACE_DELETED;
}
if (*err == DB_TABLESPACE_DELETED
|| NULL != buf_page_hash_get(space, offset)) {
/* The page belongs to a space which has been deleted or is
being deleted, or the page is already in buf_pool, return */
mutex_exit(&(buf_pool->mutex));
buf_block_free(block);
......@@ -1715,7 +1734,7 @@ buf_page_create(
/* Delete possible entries for the page from the insert buffer:
such can exist if the page belonged to an index which was dropped */
ibuf_merge_or_delete_for_page(NULL, space, offset);
ibuf_merge_or_delete_for_page(NULL, space, offset, TRUE);
/* Flush pages from the end of the LRU list if necessary */
buf_flush_free_margin();
......@@ -1828,7 +1847,7 @@ buf_page_io_complete(
if (!recv_no_ibuf_operations) {
ibuf_merge_or_delete_for_page(block->frame,
block->space, block->offset);
block->space, block->offset, TRUE);
}
}
......@@ -2294,7 +2313,7 @@ buf_all_freed(void)
if (!buf_flush_ready_for_replace(block)) {
/* printf("Page %lu %lu still fixed or dirty\n",
/* printf("Page %lu %lu still fixed or dirty\n",
block->space, block->offset); */
ut_error;
}
......
......@@ -361,16 +361,15 @@ buf_flush_init_for_writing(
ulint space, /* in: space id */
ulint page_no) /* in: page number */
{
UT_NOT_USED(space);
/* Write the newest modification lsn to the page header and trailer */
mach_write_to_8(page + FIL_PAGE_LSN, newest_lsn);
mach_write_to_8(page + UNIV_PAGE_SIZE - FIL_PAGE_END_LSN_OLD_CHKSUM,
newest_lsn);
/* Write the page number */
/* Write the page number and the space id */
mach_write_to_4(page + FIL_PAGE_OFFSET, page_no);
mach_write_to_4(page + FIL_PAGE_ARCH_LOG_NO_OR_SPACE_ID, space);
/* Store the new formula checksum */
......
......@@ -61,6 +61,87 @@ buf_LRU_block_free_hashed_page(
buf_block_t* block); /* in: block, must contain a file page and
be in a state where it can be freed */
/**********************************************************************
Invalidates all pages belonging to a given tablespace when we are deleting
the data file(s) of that tablespace. */
void
buf_LRU_invalidate_tablespace(
/*==========================*/
ulint id) /* in: space id */
{
buf_block_t* block;
ulint page_no;
ibool all_freed;
scan_again:
mutex_enter(&(buf_pool->mutex));
all_freed = TRUE;
block = UT_LIST_GET_LAST(buf_pool->LRU);
while (block != NULL) {
if (block->space == id
&& (block->buf_fix_count > 0 || block->io_fix != 0)) {
/* We cannot remove this page during this scan yet;
maybe the system is currently reading it in, or
flushing the modifications to the file */
all_freed = FALSE;
goto next_page;
}
if (block->space == id) {
if (buf_debug_prints) {
printf(
"Dropping space %lu page %lu\n",
block->space, block->offset);
}
if (block->is_hashed) {
page_no = block->offset;
mutex_exit(&(buf_pool->mutex));
/* Note that the following call will acquire
an S-latch on the page */
btr_search_drop_page_hash_when_freed(id,
page_no);
goto scan_again;
}
if (0 != ut_dulint_cmp(block->oldest_modification,
ut_dulint_zero)) {
/* Remove from the flush list of modified
blocks */
block->oldest_modification = ut_dulint_zero;
UT_LIST_REMOVE(flush_list,
buf_pool->flush_list, block);
}
/* Remove from the LRU list */
buf_LRU_block_remove_hashed_page(block);
buf_LRU_block_free_hashed_page(block);
}
next_page:
block = UT_LIST_GET_PREV(LRU, block);
}
mutex_exit(&(buf_pool->mutex));
if (!all_freed) {
os_thread_sleep(20000);
goto scan_again;
}
}
/**********************************************************************
Gets the minimum LRU_position field for the blocks in an initial segment
(determined by BUF_LRU_INITIAL_RATIO) of the LRU list. The limit is not
......
This diff is collapsed.
......@@ -12,7 +12,7 @@ Created 1/16/1996 Heikki Tuuri
#include "data0type.ic"
#endif
dtype_t dtype_binary_val = {DATA_BINARY, 0, 0, 0};
dtype_t dtype_binary_val = {DATA_BINARY, 0, 0, 0, 0};
dtype_t* dtype_binary = &dtype_binary_val;
/*************************************************************************
......
......@@ -419,6 +419,4 @@ dict_create(void)
dict_boot();
dict_insert_initial_data();
sync_order_checks_on = TRUE;
}
......@@ -264,6 +264,8 @@ dict_build_table_def_step(
dict_table_t* table;
dict_table_t* cluster_table;
dtuple_t* row;
ulint error;
mtr_t mtr;
UT_NOT_USED(thr);
ut_ad(mutex_own(&(dict_sys->mutex)));
......@@ -291,6 +293,29 @@ dict_build_table_def_step(
table->mix_id = dict_hdr_get_new_id(DICT_HDR_MIX_ID);
}
if (srv_file_per_table) {
/* We create a new single-table tablespace for the table.
We initially let it be 4 pages:
- page 0 is the fsp header and an extent descriptor page,
- page 1 is an ibuf bitmap page,
- page 2 is the first inode page,
- page 3 will contain the root of the clustered index of the
table we create here. */
error = fil_create_new_single_table_tablespace(
&(table->space), table->name, 4);
if (error != DB_SUCCESS) {
return(error);
}
mtr_start(&mtr);
fsp_header_init(table->space, 4, &mtr);
mtr_commit(&mtr);
}
row = dict_create_sys_tables_tuple(table, node->heap);
ins_node_set_new_row(node->tab_def, row);
......@@ -317,7 +342,6 @@ dict_build_col_def_step(
}
#ifdef notdefined
/*************************************************************************
Creates the single index for a cluster: it contains all the columns of
the cluster definition in the order they were defined. */
......@@ -508,8 +532,8 @@ dict_create_sys_fields_tuple(
}
/*********************************************************************
Creates the tuple with which the index entry is searched for
writing the index tree root page number, if such a tree is created. */
Creates the tuple with which the index entry is searched for writing the index
tree root page number, if such a tree is created. */
static
dtuple_t*
dict_create_search_tuple(
......@@ -577,10 +601,10 @@ dict_build_index_def_step(
index->id = dict_hdr_get_new_id(DICT_HDR_INDEX_ID);
if (index->type & DICT_CLUSTERED) {
/* Inherit the space from the table */
index->space = table->space;
}
/* Inherit the space id from the table; we store all indexes of a
table in the same tablespace */
index->space = table->space;
index->page_no = FIL_NULL;
......@@ -664,6 +688,9 @@ dict_create_index_tree_step(
index->page_no = btr_create(index->type, index->space, index->id,
&mtr);
/* printf("Created a new index tree in space %lu root page %lu\n",
index->space, index->page_no); */
page_rec_write_index_page_no(btr_pcur_get_rec(&pcur),
DICT_SYS_INDEXES_PAGE_NO_FIELD,
index->page_no, &mtr);
......@@ -712,7 +739,14 @@ dict_drop_index_tree(
ut_ad(len == 4);
space = mtr_read_ulint(ptr, MLOG_4BYTES, mtr);
if (!fil_tablespace_exists_in_mem(space)) {
/* It is a single table tablespace and the .ibd file is
missing: do nothing */
return;
}
/* We free all the pages but the root page first; this operation
may span several mini-transactions */
......@@ -722,6 +756,8 @@ dict_drop_index_tree(
we write FIL_NULL to the appropriate field in the SYS_INDEXES
record: this mini-transaction marks the B-tree totally freed */
/* printf("Dropping index tree in space %lu root page %lu\n", space,
root_page_no); */
btr_free_root(space, root_page_no, mtr);
page_rec_write_index_page_no(rec, DICT_SYS_INDEXES_PAGE_NO_FIELD,
......@@ -746,7 +782,6 @@ dict_create_default_index(
dict_create_index(index, trx);
}
#endif
/*************************************************************************
......
......@@ -139,7 +139,8 @@ dict_tree_find_index_low(
/*=====================*/
/* out: index */
dict_tree_t* tree, /* in: index tree */
rec_t* rec); /* in: record for which to find correct index */
rec_t* rec); /* in: record for which to find correct
index */
/**************************************************************************
Removes a foreign constraint struct from the dictionet cache. */
static
......@@ -717,7 +718,7 @@ dict_table_get_and_increment_handle_count(
mutex_exit(&(dict_sys->mutex));
if (table != NULL) {
if (!table->stat_initialized) {
if (!table->stat_initialized && !table->ibd_file_missing) {
dict_update_statistics(table);
}
}
......@@ -869,6 +870,7 @@ dict_table_rename_in_cache(
ulint fold;
ulint old_size;
char* name_buf;
ibool success;
ulint i;
ut_ad(table);
......@@ -884,6 +886,21 @@ dict_table_rename_in_cache(
HASH_SEARCH(name_hash, dict_sys->table_hash, fold, table2,
(ut_strcmp(table2->name, new_name) == 0));
if (table2) {
fprintf(stderr,
"InnoDB: Error: dictionary cache already contains a table of name %s\n",
new_name);
return(FALSE);
}
}
/* If the table is stored in a single-table tablespace, rename the
.ibd file */
if (table->space != 0) {
success = fil_rename_tablespace(table->name, table->space,
new_name);
if (!success) {
return(FALSE);
}
}
......@@ -909,7 +926,6 @@ dict_table_rename_in_cache(
/* Add table to hash table of tables */
HASH_INSERT(dict_table_t, name_hash, dict_sys->table_hash, fold,
table);
dict_sys->size += (mem_heap_get_size(table->heap) - old_size);
/* Update the table_name field in indexes */
......@@ -999,6 +1015,31 @@ dict_table_rename_in_cache(
return(TRUE);
}
/**************************************************************************
Change the id of a table object in the dictionary cache. This is used in
DISCARD TABLESPACE. */
void
dict_table_change_id_in_cache(
/*==========================*/
dict_table_t* table, /* in: table object already in cache */
dulint new_id) /* in: new id to set */
{
ut_ad(table);
ut_ad(mutex_own(&(dict_sys->mutex)));
ut_ad(table->magic_n == DICT_TABLE_MAGIC_N);
/* Remove the table from the hash table of id's */
HASH_DELETE(dict_table_t, id_hash, dict_sys->table_id_hash,
ut_fold_dulint(table->id), table);
table->id = new_id;
/* Add the table back to the hash table */
HASH_INSERT(dict_table_t, id_hash, dict_sys->table_id_hash,
ut_fold_dulint(table->id), table);
}
/**************************************************************************
Removes a table object from the dictionary cache. */
......@@ -3295,8 +3336,8 @@ dict_tree_free(
/*===========*/
dict_tree_t* tree) /* in, own: index tree */
{
ut_ad(tree);
ut_ad(tree->magic_n == DICT_TREE_MAGIC_N);
ut_a(tree);
ut_a(tree->magic_n == DICT_TREE_MAGIC_N);
rw_lock_free(&(tree->lock));
mem_free(tree);
......@@ -3310,7 +3351,8 @@ dict_tree_find_index_low(
/*=====================*/
/* out: index */
dict_tree_t* tree, /* in: index tree */
rec_t* rec) /* in: record for which to find correct index */
rec_t* rec) /* in: record for which to find correct
index */
{
dict_index_t* index;
dict_table_t* table;
......@@ -3348,7 +3390,8 @@ dict_tree_find_index(
/*=================*/
/* out: index */
dict_tree_t* tree, /* in: index tree */
rec_t* rec) /* in: record for which to find correct index */
rec_t* rec) /* in: record for which to find correct
index */
{
dict_index_t* index;
......@@ -3438,7 +3481,8 @@ dict_tree_build_node_ptr(
/*=====================*/
/* out, own: node pointer */
dict_tree_t* tree, /* in: index tree */
rec_t* rec, /* in: record for which to build node pointer */
rec_t* rec, /* in: record for which to build node
pointer */
ulint page_no,/* in: page number to put in node pointer */
mem_heap_t* heap, /* in: memory heap where pointer created */
ulint level) /* in: level of rec in tree: 0 means leaf
......@@ -3600,6 +3644,16 @@ dict_update_statistics_low(
ulint size;
ulint sum_of_index_sizes = 0;
if (table->ibd_file_missing) {
ut_print_timestamp(stderr);
fprintf(stderr,
" InnoDB: cannot calculate statistics for table %s\n"
"InnoDB: because the .ibd file is missing. See section 15.1 of\n"
"InnoDB: http:/www.innodb.com/ibman.html for help\n", table->name);
return;
}
/* If we have set a high innodb_force_recovery level, do not calculate
statistics, as a badly corrupted index can cause a crash in it. */
......
......@@ -19,6 +19,7 @@ Created 4/24/1996 Heikki Tuuri
#include "mach0data.h"
#include "dict0dict.h"
#include "dict0boot.h"
#include "srv0start.h"
/************************************************************************
Finds the first table name in the given database. */
......@@ -120,8 +121,8 @@ dict_print(void)
rec_t* rec;
byte* field;
ulint len;
char table_name[10000];
mtr_t mtr;
char table_name[10000];
mutex_enter(&(dict_sys->mutex));
......@@ -185,6 +186,100 @@ dict_print(void)
goto loop;
}
/************************************************************************
In a crash recovery we already have all the tablespace objects created.
This function compares the space id information in the InnoDB data dictionary
to what we already read with fil_load_single_table_tablespaces().
In a normal startup we just scan the biggest space id, and store it to
fil_system. */
void
dict_check_tablespaces_or_store_max_id(
/*===================================*/
ibool in_crash_recovery) /* in: are we doing a crash recovery */
{
dict_table_t* sys_tables;
dict_index_t* sys_index;
btr_pcur_t pcur;
rec_t* rec;
byte* field;
ulint len;
ulint space_id;
ulint max_space_id = 0;
mtr_t mtr;
char name[OS_FILE_MAX_PATH];
mutex_enter(&(dict_sys->mutex));
mtr_start(&mtr);
sys_tables = dict_table_get_low((char *) "SYS_TABLES");
sys_index = UT_LIST_GET_FIRST(sys_tables->indexes);
btr_pcur_open_at_index_side(TRUE, sys_index, BTR_SEARCH_LEAF, &pcur,
TRUE, &mtr);
loop:
btr_pcur_move_to_next_user_rec(&pcur, &mtr);
rec = btr_pcur_get_rec(&pcur);
if (!btr_pcur_is_on_user_rec(&pcur, &mtr)) {
/* end of index */
btr_pcur_close(&pcur);
mtr_commit(&mtr);
/* We must make the tablespace cache aware of the biggest
known space id */
/* printf("Biggest space id in data dictionary %lu\n",
max_space_id); */
fil_set_max_space_id_if_bigger(max_space_id);
mutex_exit(&(dict_sys->mutex));
return;
}
field = rec_get_nth_field(rec, 0, &len);
if (!rec_get_deleted_flag(rec)) {
/* We found one */
ut_a(len < OS_FILE_MAX_PATH - 10);
ut_memcpy(name, field, len);
name[len] = '\0';
field = rec_get_nth_field(rec, 9, &len);
ut_a(len == 4);
space_id = mach_read_from_4(field);
btr_pcur_store_position(&pcur, &mtr);
mtr_commit(&mtr);
if (space_id != 0 && in_crash_recovery) {
/* Check that the tablespace (the .ibd file) really
exists; print a warning to the .err log if not */
fil_space_for_table_exists_in_mem(space_id, name,
TRUE, TRUE);
}
if (space_id > max_space_id) {
max_space_id = space_id;
}
mtr_start(&mtr);
btr_pcur_restore_position(BTR_SEARCH_LEAF, &pcur, &mtr);
}
goto loop;
}
/************************************************************************
Loads definitions for table columns. */
static
......@@ -359,13 +454,13 @@ dict_load_fields(
pos_and_prefix_len = mach_read_from_4(field);
ut_a((pos_and_prefix_len & 0xFFFF) == i
|| (pos_and_prefix_len & 0xFFFF0000) == (i << 16));
ut_a((pos_and_prefix_len & 0xFFFFUL) == i
|| (pos_and_prefix_len & 0xFFFF0000UL) == (i << 16));
if ((i == 0 && pos_and_prefix_len > 0)
|| (pos_and_prefix_len & 0xFFFF0000) > 0) {
|| (pos_and_prefix_len & 0xFFFF0000UL) > 0) {
prefix_len = pos_and_prefix_len & 0xFFFF;
prefix_len = pos_and_prefix_len & 0xFFFFUL;
} else {
prefix_len = 0;
}
......@@ -540,8 +635,8 @@ dict_load_indexes(
&& (0 == ut_memcmp(name_buf, (char*) "ID_IND",
name_len))))) {
/* The index was created in memory already in
booting */
/* The index was created in memory already at booting
of the database server */
} else {
index = dict_mem_index_create(table->name, name_buf,
space, type, n_fields);
......@@ -572,9 +667,14 @@ dictionary cache. */
dict_table_t*
dict_load_table(
/*============*/
/* out: table, NULL if does not exist */
char* name) /* in: table name */
/* out: table, NULL if does not exist; if the table is
stored in an .ibd file, but the file does not exist,
then we set the ibd_file_missing flag TRUE in the table
object we return */
char* name) /* in: table name in the databasename/tablename
format */
{
ibool ibd_file_missing = FALSE;
dict_table_t* table;
dict_table_t* sys_tables;
btr_pcur_t pcur;
......@@ -641,6 +741,23 @@ dict_load_table(
field = rec_get_nth_field(rec, 9, &len);
space = mach_read_from_4(field);
/* Check if the tablespace exists and has the right name */
if (space != 0) {
if (fil_space_for_table_exists_in_mem(space, name, FALSE,
FALSE)) {
/* Ok; (if we did a crash recovery then the tablespace
can already be in the memory cache) */
} else {
/* Try to open the tablespace */
if (!fil_open_single_table_tablespace(space, name)) {
/* We failed to find a sensible tablespace
file */
ibd_file_missing = TRUE;
}
}
}
ut_a(0 == ut_strcmp((char *) "N_COLS",
dict_field_get_col(
dict_index_get_nth_field(
......@@ -651,6 +768,8 @@ dict_load_table(
table = dict_mem_table_create(name, space, n_cols);
table->ibd_file_missing = ibd_file_missing;
ut_a(0 == ut_strcmp((char *) "ID",
dict_field_get_col(
dict_index_get_nth_field(
......@@ -1003,7 +1122,7 @@ dict_load_foreign(
/* We store the type to the bits 24-31 of n_fields */
foreign->type = foreign->n_fields >> 24;
foreign->n_fields = foreign->n_fields & 0xFFFFFF;
foreign->n_fields = foreign->n_fields & 0xFFFFFFUL;
foreign->id = mem_heap_alloc(foreign->heap, ut_strlen(id) + 1);
......
......@@ -56,6 +56,8 @@ dict_mem_table_create(
table->type = DICT_TABLE_ORDINARY;
table->name = str;
table->space = space;
table->ibd_file_missing = FALSE;
table->tablespace_discarded = FALSE;
table->n_def = 0;
table->n_cols = n_cols + DATA_N_SYS_COLS;
table->mem_fix = 0;
......
This diff is collapsed.
This diff is collapsed.
......@@ -294,10 +294,10 @@ ha_print_info(
{
hash_cell_t* cell;
/*
ha_node_t* node;
ulint len = 0;
ulint max_len = 0;
ulint nodes = 0;
ha_node_t* node;
ulint len = 0;
ulint max_len = 0;
ulint nodes = 0;
*/
ulint cells = 0;
ulint n_bufs;
......
This diff is collapsed.
......@@ -189,6 +189,7 @@ btr_node_ptr_get_child_page_no(
ulint n_fields;
byte* field;
ulint len;
ulint page_no;
n_fields = rec_get_n_fields(rec);
......@@ -197,7 +198,16 @@ btr_node_ptr_get_child_page_no(
ut_ad(len == 4);
return(mach_read_from_4(field));
page_no = mach_read_from_4(field);
if (page_no == 0) {
fprintf(stderr,
"InnoDB: a nonsensical page number 0 in a node ptr record at offset %lu\n",
(ulint)(rec - buf_frame_align(rec)));
buf_page_print(buf_frame_align(rec));
}
return(page_no);
}
/******************************************************************
......
......@@ -564,7 +564,7 @@ btr_pcur_open_at_index_side(
}
btr_cur_open_at_index_side(from_left, index, latch_mode,
btr_pcur_get_btr_cur(pcur), mtr);
btr_pcur_get_btr_cur(pcur), mtr);
pcur->pos_state = BTR_PCUR_IS_POSITIONED;
pcur->old_stored = BTR_PCUR_OLD_NOT_STORED;
......
......@@ -626,19 +626,27 @@ buf_pool_get_nth_block(
ulint i); /* in: index of the block */
/************************************************************************
Function which inits a page for read to the buffer buf_pool. If the page is
already in buf_pool, does nothing. Sets the io_fix flag to BUF_IO_READ and
sets a non-recursive exclusive lock on the buffer frame. The io-handler must
take care that the flag is cleared and the lock released later. This is one
of the functions which perform the state transition NOT_USED => FILE_PAGE to
a block (the other is buf_page_create). */
(1) already in buf_pool, or
(2) if we specify to read only ibuf pages and the page is not an ibuf page, or
(3) if the space is deleted or being deleted,
then this function does nothing.
Sets the io_fix flag to BUF_IO_READ and sets a non-recursive exclusive lock
on the buffer frame. The io-handler must take care that the flag is cleared
and the lock released later. This is one of the functions which perform the
state transition NOT_USED => FILE_PAGE to a block (the other is
buf_page_create). */
buf_block_t*
buf_page_init_for_read(
/*===================*/
/* out: pointer to the block */
ulint mode, /* in: BUF_READ_IBUF_PAGES_ONLY, ... */
ulint space, /* in: space id */
ulint offset);/* in: page number */
/* out: pointer to the block or NULL */
ulint* err, /* out: DB_SUCCESS or DB_TABLESPACE_DELETED */
ulint mode, /* in: BUF_READ_IBUF_PAGES_ONLY, ... */
ulint space, /* in: space id */
ib_longlong tablespace_version,/* in: prevents reading from a wrong
version of the tablespace in case we have done
DISCARD + IMPORT */
ulint offset);/* in: page number */
/************************************************************************
Completes an asynchronous read or write request of a file page to or from
the buffer pool. */
......
......@@ -36,6 +36,16 @@ These are low-level functions
#define BUF_LRU_FREE_SEARCH_LEN (5 + 2 * BUF_READ_AHEAD_AREA)
/**********************************************************************
Invalidates all pages belonging to a given tablespace when we are deleting
the data file(s) of that tablespace. A PROBLEM: if readahead is being started,
what guarantees that it will not try to read in pages after this operation has
completed? */
void
buf_LRU_invalidate_tablespace(
/*==========================*/
ulint id); /* in: space id */
/**********************************************************************
Gets the minimum LRU_position field for the blocks in an initial segment
(determined by BUF_LRU_INITIAL_RATIO) of the LRU list. The limit is not
......
......@@ -59,7 +59,7 @@ buf_read_ahead_linear(
must want access to this page (see NOTE 3 above) */
/************************************************************************
Issues read requests for pages which the ibuf module wants to read in, in
order to contract insert buffer trees. Technically, this function is like
order to contract the insert buffer tree. Technically, this function is like
a read-ahead function. */
void
......@@ -68,9 +68,14 @@ buf_read_ibuf_merge_pages(
ibool sync, /* in: TRUE if the caller wants this function
to wait for the highest address page to get
read in, before this function returns */
ulint space, /* in: space id */
ulint* page_nos, /* in: array of page numbers to read, with
the highest page number last in the array */
ulint* space_ids, /* in: array of space ids */
ib_longlong* space_versions,/* in: the spaces must have this version
number (timestamp), otherwise we discard the
read; we use this to cancel reads if
DISCARD + IMPORT may have changed the
tablespace size */
ulint* page_nos, /* in: array of page numbers to read, with the
highest page number the last in the array */
ulint n_stored); /* in: number of page numbers in the array */
/************************************************************************
Issues read requests for pages which recovery wants to read in. */
......
This diff is collapsed.
This diff is collapsed.
......@@ -48,6 +48,11 @@ Created 5/24/1996 Heikki Tuuri
from a table failed */
#define DB_NO_SAVEPOINT 42 /* no savepoint exists with the given
name */
#define DB_TABLESPACE_ALREADY_EXISTS 43 /* we cannot create a new single-table
tablespace because a file of the same
name already exists */
#define DB_TABLESPACE_DELETED 44 /* tablespace does not exist or is
being dropped right now */
/* The following are partial failure codes */
#define DB_FAIL 1000
......
......@@ -93,7 +93,7 @@ dict_create(void);
indexes; ibuf tables and indexes are
assigned as the id the number
DICT_IBUF_ID_MIN plus the space id */
#define DICT_IBUF_ID_MIN ut_dulint_create(0xFFFFFFFF, 0)
#define DICT_IBUF_ID_MIN ut_dulint_create(0xFFFFFFFFUL, 0)
/* The offset of the dictionary header on the page */
#define DICT_HDR FSEG_PAGE_DATA
......
This diff is collapsed.
This diff is collapsed.
......@@ -309,6 +309,13 @@ struct dict_table_struct{
char* name; /* table name */
ulint space; /* space where the clustered index of the
table is placed */
ibool ibd_file_missing;/* TRUE if this is in a single-table
tablespace and the .ibd file is missing; then
we must return in ha_innodb.cc an error if the
user tries to query such an orphaned table */
ibool tablespace_discarded;/* this flag is set TRUE when the
user calls DISCARD TABLESPACE on this table,
and reset to FALSE in IMPORT TABLESPACE */
hash_node_t name_hash; /* hash chain node */
hash_node_t id_hash; /* hash chain node */
ulint n_def; /* number of columns defined so far */
......
......@@ -7,7 +7,7 @@ Created 2/5/1996 Heikki Tuuri
*******************************************************/
#define DYN_BLOCK_MAGIC_N 375767
#define DYN_BLOCK_FULL_FLAG 0x1000000
#define DYN_BLOCK_FULL_FLAG 0x1000000UL
/****************************************************************
Adds a new block to a dyn array. */
......
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
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