1
0
mirror of https://github.com/MariaDB/server.git synced 2025-12-09 08:01:34 +03:00

branches/zip: Merge revisions 465:532 from trunk.

This commit is contained in:
marko
2006-05-08 06:18:59 +00:00
parent a9ee619a9b
commit d30e44bc32
71 changed files with 1967 additions and 1678 deletions

View File

@@ -26,57 +26,65 @@ SUBDIRS = os ut btr buf data dict dyn eval fil fsp fut \
ha ibuf lock log mach mem mtr page \ ha ibuf lock log mach mem mtr page \
pars que read rem row srv sync thr trx usr pars que read rem row srv sync thr trx usr
EXTRA_DIST = include/btr0btr.h include/btr0btr.ic include/btr0cur.h include/btr0cur.ic \ EXTRA_DIST = include/btr0btr.h include/btr0btr.ic include/btr0cur.h \
include/btr0pcur.h include/btr0pcur.ic include/btr0sea.h include/btr0sea.ic \ include/btr0cur.ic include/btr0pcur.h include/btr0pcur.ic \
include/btr0types.h \ include/btr0sea.h include/btr0sea.ic include/btr0types.h \
include/buf0buf.h include/buf0buf.ic include/buf0flu.h include/buf0flu.ic \ include/buf0buf.h include/buf0buf.ic include/buf0flu.h \
include/buf0lru.h include/buf0lru.ic include/buf0rea.h include/buf0types.h \ include/buf0flu.ic include/buf0lru.h include/buf0lru.ic \
include/data0data.h include/data0data.ic include/data0type.h include/data0type.ic \ include/buf0rea.h include/buf0types.h include/data0data.h \
include/data0types.h include/db0err.h \ include/data0data.ic include/data0type.h include/data0type.ic \
include/dict0boot.h include/dict0boot.ic include/dict0crea.h include/dict0crea.ic \ include/data0types.h include/db0err.h include/dict0boot.h \
include/dict0dict.h include/dict0dict.ic include/dict0load.h include/dict0load.ic \ include/dict0boot.ic include/dict0crea.h include/dict0crea.ic \
include/dict0mem.h include/dict0mem.ic include/dict0types.h \ include/dict0dict.h include/dict0dict.ic include/dict0load.h \
include/dyn0dyn.h include/dyn0dyn.ic \ include/dict0load.ic include/dict0mem.h include/dict0mem.ic \
include/eval0eval.h include/eval0eval.ic include/eval0proc.h include/eval0proc.ic \ include/dict0types.h include/dyn0dyn.h include/dyn0dyn.ic \
include/fil0fil.h include/fsp0fsp.h include/fsp0fsp.ic \ include/eval0eval.h include/eval0eval.ic include/eval0proc.h \
include/fut0fut.h include/fut0fut.ic include/fut0lst.h include/fut0lst.ic \ include/eval0proc.ic include/fil0fil.h include/fsp0fsp.h \
include/ha0ha.h include/ha0ha.ic include/hash0hash.h include/hash0hash.ic \ include/fsp0fsp.ic include/fut0fut.h include/fut0fut.ic \
include/fut0lst.h include/fut0lst.ic include/ha0ha.h \
include/ha0ha.ic include/hash0hash.h include/hash0hash.ic \
include/ibuf0ibuf.h include/ibuf0ibuf.ic include/ibuf0types.h \ include/ibuf0ibuf.h include/ibuf0ibuf.ic include/ibuf0types.h \
include/lock0lock.h include/lock0lock.ic include/lock0types.h \ include/lock0lock.h include/lock0lock.ic include/lock0types.h \
include/log0log.h include/log0log.ic include/log0recv.h include/log0recv.ic \ include/log0log.h include/log0log.ic include/log0recv.h \
include/mach0data.h include/mach0data.ic include/mem0dbg.h include/mem0dbg.ic \ include/log0recv.ic include/mach0data.h include/mach0data.ic \
include/mem0mem.h include/mem0mem.ic include/mem0pool.h include/mem0pool.ic \ include/mem0dbg.h include/mem0dbg.ic include/mem0mem.h \
include/mtr0log.h include/mtr0log.ic include/mtr0mtr.h include/mtr0mtr.ic \ include/mem0mem.ic include/mem0pool.h include/mem0pool.ic \
include/mtr0types.h include/os0file.h \ include/mtr0log.h include/mtr0log.ic include/mtr0mtr.h \
include/os0proc.h include/os0proc.ic include/os0sync.h include/os0sync.ic \ include/mtr0mtr.ic include/mtr0types.h include/os0file.h \
include/os0thread.h include/os0thread.ic \ include/os0proc.h include/os0proc.ic include/os0sync.h \
include/page0cur.h include/page0cur.ic include/page0page.h include/page0page.ic \ include/os0sync.ic include/os0thread.h include/os0thread.ic \
include/page0types.h \ include/page0cur.h include/page0cur.ic include/page0page.h \
include/pars0grm.h include/pars0opt.h include/pars0opt.ic \ include/page0page.ic include/page0types.h include/pars0grm.h \
include/pars0pars.h include/pars0pars.ic include/pars0sym.h include/pars0sym.ic \ include/pars0opt.h include/pars0opt.ic include/pars0pars.h \
include/pars0types.h \ include/pars0pars.ic include/pars0sym.h include/pars0sym.ic \
include/que0que.h include/que0que.ic include/que0types.h \ include/pars0types.h include/que0que.h include/que0que.ic \
include/read0read.h include/read0read.ic include/read0types.h \ include/que0types.h include/read0read.h include/read0read.ic \
include/rem0cmp.h include/rem0cmp.ic include/rem0rec.h include/rem0rec.ic \ include/read0types.h include/rem0cmp.h include/rem0cmp.ic \
include/rem0types.h \ include/rem0rec.h include/rem0rec.ic include/rem0types.h \
include/row0ins.h include/row0ins.ic include/row0mysql.h include/row0mysql.ic \ include/row0ins.h include/row0ins.ic include/row0mysql.h \
include/row0purge.h include/row0purge.ic include/row0row.h include/row0row.ic \ include/row0mysql.ic include/row0purge.h include/row0purge.ic \
include/row0sel.h include/row0sel.ic include/row0types.h \ include/row0row.h include/row0row.ic include/row0sel.h \
include/row0uins.h include/row0uins.ic include/row0umod.h include/row0umod.ic \ include/row0sel.ic include/row0types.h include/row0uins.h \
include/row0undo.h include/row0undo.ic include/row0upd.h include/row0upd.ic \ include/row0uins.ic include/row0umod.h include/row0umod.ic \
include/row0vers.h include/row0vers.ic \ include/row0undo.h include/row0undo.ic include/row0upd.h \
include/srv0que.h include/srv0srv.h include/srv0srv.ic include/srv0start.h \ include/row0upd.ic include/row0vers.h include/row0vers.ic \
include/sync0arr.h include/sync0arr.ic include/sync0rw.h include/sync0rw.ic \ include/srv0que.h include/srv0srv.h include/srv0srv.ic \
include/sync0sync.h include/sync0sync.ic include/sync0types.h \ include/srv0start.h include/sync0arr.h include/sync0arr.ic \
include/thr0loc.h include/thr0loc.ic \ include/sync0rw.h include/sync0rw.ic include/sync0sync.h \
include/trx0purge.h include/trx0purge.ic include/trx0rec.h include/trx0rec.ic \ include/sync0sync.ic include/sync0types.h include/thr0loc.h \
include/trx0roll.h include/trx0roll.ic include/trx0rseg.h include/trx0rseg.ic \ include/thr0loc.ic include/trx0purge.h include/trx0purge.ic \
include/trx0sys.h include/trx0sys.ic include/trx0trx.h include/trx0trx.ic \ include/trx0rec.h include/trx0rec.ic include/trx0roll.h \
include/trx0types.h include/trx0undo.h include/trx0undo.ic include/trx0xa.h \ include/trx0roll.ic include/trx0rseg.h include/trx0rseg.ic \
include/univ.i include/usr0sess.h include/usr0sess.ic include/usr0types.h \ include/trx0sys.h include/trx0sys.ic include/trx0trx.h \
include/ut0byte.h include/ut0byte.ic include/ut0dbg.h include/ut0lst.h \ include/trx0trx.ic include/trx0types.h include/trx0undo.h \
include/ut0mem.h include/ut0mem.ic include/ut0rnd.h include/ut0rnd.ic \ include/trx0undo.ic include/trx0xa.h include/univ.i \
include/ut0sort.h include/ut0ut.h include/ut0ut.ic include/ut0vec.h include/ut0vec.ic include/usr0sess.h include/usr0sess.ic include/usr0types.h \
include/ut0byte.h include/ut0byte.ic include/ut0dbg.h \
include/ut0lst.h include/ut0mem.h include/ut0mem.ic \
include/ut0rnd.h include/ut0rnd.ic include/ut0sort.h \
include/ut0ut.h include/ut0ut.ic include/ut0vec.h \
include/ut0vec.ic include/ut0list.h include/ut0list.ic \
include/ut0wqueue.h cmakelists.txt
# Don't update the files from bitkeeper # Don't update the files from bitkeeper
%::SCCS/s.% %::SCCS/s.%

View File

@@ -136,13 +136,12 @@ btr_search_sys_create(
btr_search_latch_temp = mem_alloc(sizeof(rw_lock_t)); btr_search_latch_temp = mem_alloc(sizeof(rw_lock_t));
rw_lock_create(&btr_search_latch); rw_lock_create(&btr_search_latch, SYNC_SEARCH_SYS);
btr_search_sys = mem_alloc(sizeof(btr_search_sys_t)); btr_search_sys = mem_alloc(sizeof(btr_search_sys_t));
btr_search_sys->hash_index = ha_create(TRUE, hash_size, 0, 0); btr_search_sys->hash_index = ha_create(TRUE, hash_size, 0, 0);
rw_lock_set_level(&btr_search_latch, SYNC_SEARCH_SYS);
} }
/********************************************************************* /*********************************************************************

View File

@@ -612,12 +612,11 @@ buf_block_init(
page_zip_des_init(&block->page_zip); page_zip_des_init(&block->page_zip);
rw_lock_create(&(block->lock)); rw_lock_create(&block->lock, SYNC_LEVEL_VARYING);
ut_ad(rw_lock_validate(&(block->lock))); ut_ad(rw_lock_validate(&(block->lock)));
#ifdef UNIV_SYNC_DEBUG #ifdef UNIV_SYNC_DEBUG
rw_lock_create(&(block->debug_latch)); rw_lock_create(&block->debug_latch, SYNC_NO_ORDER_CHECK);
rw_lock_set_level(&(block->debug_latch), SYNC_NO_ORDER_CHECK);
#endif /* UNIV_SYNC_DEBUG */ #endif /* UNIV_SYNC_DEBUG */
} }
@@ -660,8 +659,7 @@ buf_pool_init(
/* 1. Initialize general fields /* 1. Initialize general fields
------------------------------- */ ------------------------------- */
mutex_create(&(buf_pool->mutex)); mutex_create(&buf_pool->mutex, SYNC_BUF_POOL);
mutex_set_level(&(buf_pool->mutex), SYNC_BUF_POOL);
mutex_enter(&(buf_pool->mutex)); mutex_enter(&(buf_pool->mutex));
@@ -1953,7 +1951,6 @@ buf_page_io_complete(
buf_block_t* block) /* in: pointer to the block in question */ buf_block_t* block) /* in: pointer to the block in question */
{ {
ulint io_type; ulint io_type;
ulint read_page_no;
ut_ad(block); ut_ad(block);
@@ -1978,16 +1975,36 @@ buf_page_io_complete(
} }
/* If this page is not uninitialized and not in the /* If this page is not uninitialized and not in the
doublewrite buffer, then the page number should be the doublewrite buffer, then the page number and space id
same as in block */ should be the same as in block. */
ulint read_page_no = mach_read_from_4((block->frame)
read_page_no = mach_read_from_4((block->frame)
+ FIL_PAGE_OFFSET); + FIL_PAGE_OFFSET);
if (read_page_no && read_page_no != block->offset) { ulint read_space_id = mach_read_from_4((block->frame)
+ FIL_PAGE_ARCH_LOG_NO_OR_SPACE_ID);
if (!block->space && trx_doublewrite_page_inside(
block->offset)) {
ut_print_timestamp(stderr);
fprintf(stderr, fprintf(stderr,
"InnoDB: Error: page n:o stored in the page read in is %lu, should be %lu!\n", " InnoDB: Error: reading page %lu\n"
(ulong) read_page_no, (ulong) block->offset); "InnoDB: which is in the doublewrite buffer!\n",
(ulong) block->offset);
} else if (!read_space_id && !read_page_no) {
/* This is likely an uninitialized page. */
} else if ((block->space && block->space != read_space_id)
|| block->offset != read_page_no) {
/* We did not compare space_id to read_space_id
if block->space == 0, because the field on the
page may contain garbage in MySQL < 4.1.1,
which only supported block->space == 0. */
ut_print_timestamp(stderr);
fprintf(stderr,
" InnoDB: Error: space id and page n:o stored in the page\n"
"InnoDB: read in are %lu:%lu, should be %lu:%lu!\n",
(ulong) read_space_id, (ulong) read_page_no,
(ulong) block->space, (ulong) block->offset);
} }
/* From version 3.23.38 up we store the page checksum /* From version 3.23.38 up we store the page checksum
@@ -2345,7 +2362,8 @@ buf_get_latched_pages_number(void)
} }
mutex_exit(&(buf_pool->mutex)); mutex_exit(&(buf_pool->mutex));
return fixed_pages_number;
return(fixed_pages_number);
} }
/************************************************************************* /*************************************************************************

View File

@@ -27,7 +27,7 @@ Created 11/11/1995 Heikki Tuuri
#include "trx0sys.h" #include "trx0sys.h"
#include "srv0srv.h" #include "srv0srv.h"
/* When flushed, dirty blocks are searched in neigborhoods of this size, and /* When flushed, dirty blocks are searched in neighborhoods of this size, and
flushed along with the original page. */ flushed along with the original page. */
#define BUF_FLUSH_AREA ut_min(BUF_READ_AHEAD_AREA,\ #define BUF_FLUSH_AREA ut_min(BUF_READ_AHEAD_AREA,\

View File

@@ -32,4 +32,4 @@ ADD_LIBRARY(innobase btr/btr0btr.c btr/btr0cur.c btr/btr0pcur.c btr/btr0sea.c
thr/thr0loc.c thr/thr0loc.c
trx/trx0purge.c trx/trx0rec.c trx/trx0roll.c trx/trx0rseg.c trx/trx0sys.c trx/trx0trx.c trx/trx0undo.c trx/trx0purge.c trx/trx0rec.c trx/trx0roll.c trx/trx0rseg.c trx/trx0sys.c trx/trx0trx.c trx/trx0undo.c
usr/usr0sess.c usr/usr0sess.c
ut/ut0byte.c ut/ut0dbg.c ut/ut0mem.c ut/ut0rnd.c ut/ut0ut.c ut/ut0vec.c) ut/ut0byte.c ut/ut0dbg.c ut/ut0mem.c ut/ut0rnd.c ut/ut0ut.c ut/ut0vec.c ut/ut0list.c ut/ut0wqueue.c)

View File

@@ -1139,11 +1139,8 @@ dict_create_or_check_foreign_constraint_tables(void)
{ {
dict_table_t* table1; dict_table_t* table1;
dict_table_t* table2; dict_table_t* table2;
que_thr_t* thr;
que_t* graph;
ulint error; ulint error;
trx_t* trx; trx_t* trx;
const char* str;
mutex_enter(&(dict_sys->mutex)); mutex_enter(&(dict_sys->mutex));
@@ -1195,7 +1192,7 @@ dict_create_or_check_foreign_constraint_tables(void)
VARBINARY, like in other InnoDB system tables, to get a clean VARBINARY, like in other InnoDB system tables, to get a clean
design. */ design. */
str = error = que_eval_sql(NULL,
"PROCEDURE CREATE_FOREIGN_SYS_TABLES_PROC () IS\n" "PROCEDURE CREATE_FOREIGN_SYS_TABLES_PROC () IS\n"
"BEGIN\n" "BEGIN\n"
"CREATE TABLE\n" "CREATE TABLE\n"
@@ -1207,22 +1204,8 @@ dict_create_or_check_foreign_constraint_tables(void)
"SYS_FOREIGN_COLS(ID CHAR, POS INT, FOR_COL_NAME CHAR, REF_COL_NAME CHAR);\n" "SYS_FOREIGN_COLS(ID CHAR, POS INT, FOR_COL_NAME CHAR, REF_COL_NAME CHAR);\n"
"CREATE UNIQUE CLUSTERED INDEX ID_IND ON SYS_FOREIGN_COLS (ID, POS);\n" "CREATE UNIQUE CLUSTERED INDEX ID_IND ON SYS_FOREIGN_COLS (ID, POS);\n"
"COMMIT WORK;\n" "COMMIT WORK;\n"
"END;\n"; "END;\n"
, trx);
graph = pars_sql(NULL, str);
ut_a(graph);
graph->trx = trx;
trx->graph = NULL;
graph->fork_type = QUE_FORK_MYSQL_INTERFACE;
ut_a(thr = que_fork_start_command(graph));
que_run_threads(thr);
error = trx->error_state;
if (error != DB_SUCCESS) { if (error != DB_SUCCESS) {
fprintf(stderr, "InnoDB: error %lu in creation\n", fprintf(stderr, "InnoDB: error %lu in creation\n",
@@ -1241,8 +1224,6 @@ dict_create_or_check_foreign_constraint_tables(void)
error = DB_MUST_GET_MORE_FILE_SPACE; error = DB_MUST_GET_MORE_FILE_SPACE;
} }
que_graph_free(graph);
trx->op_info = ""; trx->op_info = "";
row_mysql_unlock_data_dictionary(trx); row_mysql_unlock_data_dictionary(trx);

View File

@@ -235,11 +235,10 @@ dict_remove_db_name(
const char* name) /* in: table name in the form const char* name) /* in: table name in the form
dbname '/' tablename */ dbname '/' tablename */
{ {
const char* s; const char* s = strchr(name, '/');
s = strchr(name, '/');
ut_a(s); ut_a(s);
if (s) s++;
return(s); return(s + 1);
} }
/************************************************************************ /************************************************************************
@@ -600,7 +599,7 @@ dict_index_get_nth_field_pos(
} }
/************************************************************************** /**************************************************************************
Returns a table object, based on table id, and memoryfixes it. */ Returns a table object based on table id. */
dict_table_t* dict_table_t*
dict_table_get_on_id( dict_table_get_on_id(
@@ -622,12 +621,12 @@ dict_table_get_on_id(
ut_ad(mutex_own(&(dict_sys->mutex))); ut_ad(mutex_own(&(dict_sys->mutex)));
#endif /* UNIV_SYNC_DEBUG */ #endif /* UNIV_SYNC_DEBUG */
return(dict_table_get_on_id_low(table_id, trx)); return(dict_table_get_on_id_low(table_id));
} }
mutex_enter(&(dict_sys->mutex)); mutex_enter(&(dict_sys->mutex));
table = dict_table_get_on_id_low(table_id, trx); table = dict_table_get_on_id_low(table_id);
mutex_exit(&(dict_sys->mutex)); mutex_exit(&(dict_sys->mutex));
@@ -709,8 +708,7 @@ dict_init(void)
{ {
dict_sys = mem_alloc(sizeof(dict_sys_t)); dict_sys = mem_alloc(sizeof(dict_sys_t));
mutex_create(&(dict_sys->mutex)); mutex_create(&dict_sys->mutex, SYNC_DICT);
mutex_set_level(&(dict_sys->mutex), SYNC_DICT);
dict_sys->table_hash = hash_create(buf_pool_get_max_size() / dict_sys->table_hash = hash_create(buf_pool_get_max_size() /
(DICT_POOL_PER_TABLE_HASH * (DICT_POOL_PER_TABLE_HASH *
@@ -725,32 +723,28 @@ dict_init(void)
UT_LIST_INIT(dict_sys->table_LRU); UT_LIST_INIT(dict_sys->table_LRU);
rw_lock_create(&dict_operation_lock); rw_lock_create(&dict_operation_lock, SYNC_DICT_OPERATION);
rw_lock_set_level(&dict_operation_lock, SYNC_DICT_OPERATION);
dict_foreign_err_file = os_file_create_tmpfile(); dict_foreign_err_file = os_file_create_tmpfile();
ut_a(dict_foreign_err_file); ut_a(dict_foreign_err_file);
mutex_create(&dict_foreign_err_mutex);
mutex_set_level(&dict_foreign_err_mutex, SYNC_ANY_LATCH); mutex_create(&dict_foreign_err_mutex, SYNC_ANY_LATCH);
} }
/************************************************************************** /**************************************************************************
Returns a table object and memoryfixes it. NOTE! This is a high-level Returns a table object. NOTE! This is a high-level function to be used
function to be used mainly from outside the 'dict' directory. Inside this mainly from outside the 'dict' directory. Inside this directory
directory dict_table_get_low is usually the appropriate function. */ dict_table_get_low is usually the appropriate function. */
dict_table_t* dict_table_t*
dict_table_get( dict_table_get(
/*===========*/ /*===========*/
/* out: table, NULL if /* out: table, NULL if
does not exist */ does not exist */
const char* table_name, /* in: table name */ const char* table_name) /* in: table name */
trx_t* trx) /* in: transaction handle or NULL */
{ {
dict_table_t* table; dict_table_t* table;
UT_NOT_USED(trx);
mutex_enter(&(dict_sys->mutex)); mutex_enter(&(dict_sys->mutex));
table = dict_table_get_low(table_name); table = dict_table_get_low(table_name);
@@ -774,13 +768,10 @@ dict_table_get_and_increment_handle_count(
/*======================================*/ /*======================================*/
/* out: table, NULL if /* out: table, NULL if
does not exist */ does not exist */
const char* table_name, /* in: table name */ const char* table_name) /* in: table name */
trx_t* trx) /* in: transaction handle or NULL */
{ {
dict_table_t* table; dict_table_t* table;
UT_NOT_USED(trx);
mutex_enter(&(dict_sys->mutex)); mutex_enter(&(dict_sys->mutex));
table = dict_table_get_low(table_name); table = dict_table_get_low(table_name);
@@ -890,10 +881,7 @@ dict_table_add_to_cache(
/* Add table to LRU list of tables */ /* Add table to LRU list of tables */
UT_LIST_ADD_FIRST(table_LRU, dict_sys->table_LRU, table); UT_LIST_ADD_FIRST(table_LRU, dict_sys->table_LRU, table);
/* If the dictionary cache grows too big, trim the table LRU list */
dict_sys->size += mem_heap_get_size(table->heap); dict_sys->size += mem_heap_get_size(table->heap);
/* dict_table_LRU_trim(); */
} }
/************************************************************************** /**************************************************************************
@@ -1258,38 +1246,6 @@ dict_table_remove_from_cache(
dict_mem_table_free(table); dict_mem_table_free(table);
} }
/**************************************************************************
Frees tables from the end of table_LRU if the dictionary cache occupies
too much space. Currently not used! */
void
dict_table_LRU_trim(void)
/*=====================*/
{
dict_table_t* table;
dict_table_t* prev_table;
ut_error;
#ifdef UNIV_SYNC_DEBUG
ut_ad(mutex_own(&(dict_sys->mutex)));
#endif /* UNIV_SYNC_DEBUG */
table = UT_LIST_GET_LAST(dict_sys->table_LRU);
while (table && (dict_sys->size >
buf_pool_get_max_size() / DICT_POOL_PER_VARYING)) {
prev_table = UT_LIST_GET_PREV(table_LRU, table);
if (table->mem_fix == 0) {
dict_table_remove_from_cache(table);
}
table = prev_table;
}
}
/************************************************************************** /**************************************************************************
Adds a column to the data dictionary hash table. */ Adds a column to the data dictionary hash table. */
static static
@@ -1519,10 +1475,7 @@ dict_index_add_to_cache(
/* Add the index to the list of indexes stored in the tree */ /* Add the index to the list of indexes stored in the tree */
tree->tree_index = new_index; tree->tree_index = new_index;
/* If the dictionary cache grows too big, trim the table LRU list */
dict_sys->size += mem_heap_get_size(new_index->heap); dict_sys->size += mem_heap_get_size(new_index->heap);
/* dict_table_LRU_trim(); */
dict_mem_index_free(index); dict_mem_index_free(index);
@@ -2994,7 +2947,8 @@ loop:
if so, immediately reject the command if the table is a if so, immediately reject the command if the table is a
temporary one. For now, this kludge will work. */ temporary one. For now, this kludge will work. */
if (reject_fks && (UT_LIST_GET_LEN(table->foreign_list) > 0)) { if (reject_fks && (UT_LIST_GET_LEN(table->foreign_list) > 0)) {
return DB_CANNOT_ADD_CONSTRAINT;
return(DB_CANNOT_ADD_CONSTRAINT);
} }
/**********************************************************/ /**********************************************************/
@@ -3664,9 +3618,7 @@ dict_tree_create(
tree->magic_n = DICT_TREE_MAGIC_N; tree->magic_n = DICT_TREE_MAGIC_N;
rw_lock_create(&(tree->lock)); rw_lock_create(&tree->lock, SYNC_INDEX_TREE);
rw_lock_set_level(&(tree->lock), SYNC_INDEX_TREE);
return(tree); return(tree);
} }

View File

@@ -660,7 +660,7 @@ dict_load_indexes(
break; break;
} }
if (rec_get_deleted_flag(rec, dict_table_is_comp(table))) { if (rec_get_deleted_flag(rec, 0)) {
dict_load_report_deleted_index(table->name, dict_load_report_deleted_index(table->name,
ULINT_UNDEFINED); ULINT_UNDEFINED);

View File

@@ -57,7 +57,6 @@ dict_mem_table_create(
table->tablespace_discarded = FALSE; table->tablespace_discarded = FALSE;
table->n_def = 0; table->n_def = 0;
table->n_cols = n_cols + DATA_N_SYS_COLS; table->n_cols = n_cols + DATA_N_SYS_COLS;
table->mem_fix = 0;
table->n_mysql_handles_opened = 0; table->n_mysql_handles_opened = 0;
table->n_foreign_key_checks_running = 0; table->n_foreign_key_checks_running = 0;
@@ -82,8 +81,7 @@ dict_mem_table_create(
table->stat_modified_counter = 0; table->stat_modified_counter = 0;
mutex_create(&(table->autoinc_mutex)); mutex_create(&table->autoinc_mutex, SYNC_DICT_AUTOINC_MUTEX);
mutex_set_level(&(table->autoinc_mutex), SYNC_DICT_AUTOINC_MUTEX);
table->autoinc_inited = FALSE; table->autoinc_inited = FALSE;

View File

@@ -1,19 +1,29 @@
#!/bin/bash #!/bin/bash
# #
# export current working directory in a format suitable for sending to # export current working directory in a format suitable for sending to MySQL
# MySQL as a snapshot. # as a snapshot. also generates the actual snapshot and sends it to MySQL.
set -eu set -eu
if [ $# -ne 1 ] ; then die () {
echo "Usage: export.sh revision-number-of-last-snapshot" echo $*
exit 1 exit 1
}
if [ $# -ne 2 ] ; then
die "Usage: export.sh revision-number-of-last-snapshot current-revision-number"
fi fi
set +u
if test -z $EDITOR; then
die "\$EDITOR is not set"
fi
set -u
rm -rf to-mysql rm -rf to-mysql
mkdir -p to-mysql/storage/ mkdir -p to-mysql/storage/
svn log -v -r "$1:BASE" > to-mysql/log svn log -v -r "$(($1 + 1)):BASE" > to-mysql/log
svn export . to-mysql/storage/innobase svn export -q . to-mysql/storage/innobase
cd to-mysql cd to-mysql
mkdir -p sql mysql-test/t mysql-test/r mysql-test/include mkdir -p sql mysql-test/t mysql-test/r mysql-test/include
@@ -27,5 +37,18 @@ mv mysql-test/*.result ../../mysql-test/r
mv mysql-test/*.inc ../../mysql-test/include mv mysql-test/*.inc ../../mysql-test/include
rmdir mysql-test rmdir mysql-test
rm setup.sh export.sh compile-innodb-debug rm setup.sh export.sh revert_gen.sh compile-innodb-debug compile-innodb
cd ../..
$EDITOR log
cd ..
fname="innodb-5.1-ss$2.tar.gz"
rm -f $fname
tar czf $fname to-mysql
scp $fname mysql:snapshots
rm $fname
rm -rf to-mysql
echo "Sent $fname to MySQL"

View File

@@ -1067,8 +1067,7 @@ try_again:
space->ibuf_data = NULL; space->ibuf_data = NULL;
rw_lock_create(&(space->latch)); rw_lock_create(&space->latch, SYNC_FSP);
rw_lock_set_level(&(space->latch), SYNC_FSP);
HASH_INSERT(fil_space_t, hash, system->spaces, id, space); HASH_INSERT(fil_space_t, hash, system->spaces, id, space);
@@ -1362,9 +1361,7 @@ fil_system_create(
system = mem_alloc(sizeof(fil_system_t)); system = mem_alloc(sizeof(fil_system_t));
mutex_create(&(system->mutex)); mutex_create(&system->mutex, SYNC_ANY_LATCH);
mutex_set_level(&(system->mutex), SYNC_ANY_LATCH);
system->spaces = hash_create(hash_size); system->spaces = hash_create(hash_size);
system->name_hash = hash_create(hash_size); system->name_hash = hash_create(hash_size);

View File

@@ -144,9 +144,7 @@ hash_create_mutexes(
table->mutexes = mem_alloc(n_mutexes * sizeof(mutex_t)); table->mutexes = mem_alloc(n_mutexes * sizeof(mutex_t));
for (i = 0; i < n_mutexes; i++) { for (i = 0; i < n_mutexes; i++) {
mutex_create(table->mutexes + i); mutex_create(table->mutexes + i, sync_level);
mutex_set_level(table->mutexes + i, sync_level);
} }
table->n_mutexes = n_mutexes; table->n_mutexes = n_mutexes;

View File

@@ -238,7 +238,8 @@ handlerton innobase_hton = {
NULL, /* Fill FILES table */ NULL, /* Fill FILES table */
HTON_NO_FLAGS, HTON_NO_FLAGS,
NULL, /* binlog_func */ NULL, /* binlog_func */
NULL /* binlog_log_query */ NULL, /* binlog_log_query */
innobase_release_temporary_latches
}; };
@@ -1768,25 +1769,6 @@ innobase_report_binlog_offset_and_commit(
trx->mysql_log_file_name = log_file_name; trx->mysql_log_file_name = log_file_name;
trx->mysql_log_offset = (ib_longlong)end_offset; trx->mysql_log_offset = (ib_longlong)end_offset;
#ifdef HAVE_REPLICATION
if (thd->variables.sync_replication) {
/* Let us store the binlog file name and the position, so that
we know how long to wait for the binlog to the replicated to
the slave in synchronous replication. */
if (trx->repl_wait_binlog_name == NULL) {
trx->repl_wait_binlog_name =
(char*)mem_alloc_noninline(FN_REFLEN + 100);
}
ut_a(strlen(log_file_name) < FN_REFLEN + 100);
strcpy(trx->repl_wait_binlog_name, log_file_name);
trx->repl_wait_binlog_pos = (ib_longlong)end_offset;
}
#endif /* HAVE_REPLICATION */
trx->flush_log_later = TRUE; trx->flush_log_later = TRUE;
innobase_commit(thd, TRUE); innobase_commit(thd, TRUE);
@@ -1855,224 +1837,9 @@ innobase_commit_complete(
trx_commit_complete_for_mysql(trx); trx_commit_complete_for_mysql(trx);
} }
#ifdef HAVE_REPLICATION
if (thd->variables.sync_replication
&& trx->repl_wait_binlog_name
&& innobase_repl_state != 0) {
struct timespec abstime;
int cmp;
int ret;
/* In synchronous replication, let us wait until the MySQL
replication has sent the relevant binlog segment to the
replication slave. */
pthread_mutex_lock(&innobase_repl_cond_mutex);
try_again:
if (innobase_repl_state == 0) {
pthread_mutex_unlock(&innobase_repl_cond_mutex);
return(0);
}
cmp = strcmp(innobase_repl_file_name,
trx->repl_wait_binlog_name);
if (cmp > 0
|| (cmp == 0 && innobase_repl_pos
>= (my_off_t)trx->repl_wait_binlog_pos)) {
/* We have already sent the relevant binlog to the
slave: no need to wait here */
pthread_mutex_unlock(&innobase_repl_cond_mutex);
/* printf("Binlog now sent\n"); */
return(0);
}
/* Let us update the info about the minimum binlog position
of waiting threads in the innobase_repl_... variables */
if (innobase_repl_wait_file_name_inited != 0) {
cmp = strcmp(trx->repl_wait_binlog_name,
innobase_repl_wait_file_name);
if (cmp < 0
|| (cmp == 0
&& (my_off_t)trx->repl_wait_binlog_pos
<= innobase_repl_wait_pos)) {
/* This thd has an even lower position, let
us update the minimum info */
strcpy(innobase_repl_wait_file_name,
trx->repl_wait_binlog_name);
innobase_repl_wait_pos =
trx->repl_wait_binlog_pos;
}
} else {
strcpy(innobase_repl_wait_file_name,
trx->repl_wait_binlog_name);
innobase_repl_wait_pos = trx->repl_wait_binlog_pos;
innobase_repl_wait_file_name_inited = 1;
}
set_timespec(abstime, thd->variables.sync_replication_timeout);
/* Let us suspend this thread to wait on the condition;
when replication has progressed far enough, we will release
these waiting threads. The following call
pthread_cond_timedwait also atomically unlocks
innobase_repl_cond_mutex. */
innobase_repl_n_wait_threads++;
/* printf("Waiting for binlog to be sent\n"); */
ret = pthread_cond_timedwait(&innobase_repl_cond,
&innobase_repl_cond_mutex, &abstime);
innobase_repl_n_wait_threads--;
if (ret != 0) {
ut_print_timestamp(stderr);
sql_print_error("MySQL synchronous replication was "
"not able to send the binlog to the "
"slave within the timeout %lu. We "
"assume that the slave has become "
"inaccessible, and switch off "
"synchronous replication until the "
"communication to the slave works "
"again. MySQL synchronous replication "
"has sent binlog to the slave up to "
"file %s, position %lu. This "
"transaction needs it to be sent up "
"to file %s, position %lu.",
thd->variables.sync_replication_timeout,
innobase_repl_file_name,
(ulong) innobase_repl_pos,
trx->repl_wait_binlog_name,
(ulong) trx->repl_wait_binlog_pos);
innobase_repl_state = 0;
pthread_mutex_unlock(&innobase_repl_cond_mutex);
return(0);
}
goto try_again;
}
#endif // HAVE_REPLICATION
return(0); return(0);
} }
#ifdef HAVE_REPLICATION
/*********************************************************************
In synchronous replication, reports to InnoDB up to which binlog position
we have sent the binlog to the slave. Note that replication is synchronous
for one slave only. For other slaves, we do nothing in this function. This
function is used in a replication master. */
int
innobase_repl_report_sent_binlog(
/*=============================*/
/* out: 0 */
THD* thd, /* in: thread doing the binlog communication to
the slave */
char* log_file_name, /* in: binlog file name */
my_off_t end_offset) /* in: the offset in the binlog file up to
which we sent the contents to the slave */
{
int cmp;
ibool can_release_threads = 0;
if (!innodb_inited) {
return 0;
}
/* If synchronous replication is not switched on, or this thd is
sending binlog to a slave where we do not need synchronous replication,
then return immediately */
if (thd->server_id != thd->variables.sync_replication_slave_id) {
/* Do nothing */
return(0);
}
pthread_mutex_lock(&innobase_repl_cond_mutex);
if (innobase_repl_state == 0) {
ut_print_timestamp(stderr);
sql_print_warning("Switching MySQL synchronous replication on "
"again at binlog file %s, position %lu",
log_file_name, (ulong) end_offset);
innobase_repl_state = 1;
}
/* The position should increase monotonically, since just one thread
is sending the binlog to the slave for which we want synchronous
replication. Let us check this, and print an error to the .err log
if that is not the case. */
if (innobase_repl_file_name_inited) {
cmp = strcmp(log_file_name, innobase_repl_file_name);
if (cmp < 0
|| (cmp == 0 && end_offset < innobase_repl_pos)) {
ut_print_timestamp(stderr);
sql_print_error("MySQL synchronous replication has "
"sent binlog to the slave up to file "
"%s, position %lu, but now MySQL "
"reports that it sent the binlog only "
"up to file %s, position %lu",
innobase_repl_file_name,
(ulong) innobase_repl_pos,
log_file_name, (ulong) end_offset);
}
}
strcpy(innobase_repl_file_name, log_file_name);
innobase_repl_pos = end_offset;
innobase_repl_file_name_inited = 1;
if (innobase_repl_n_wait_threads > 0) {
/* Let us check if some of the waiting threads doing a trx
commit can now proceed */
cmp = strcmp(innobase_repl_file_name,
innobase_repl_wait_file_name);
if (cmp > 0
|| (cmp == 0 && innobase_repl_pos
>= innobase_repl_wait_pos)) {
/* Yes, at least one waiting thread can now proceed:
let us release all waiting threads with a broadcast */
can_release_threads = 1;
innobase_repl_wait_file_name_inited = 0;
}
}
pthread_mutex_unlock(&innobase_repl_cond_mutex);
if (can_release_threads) {
pthread_cond_broadcast(&innobase_repl_cond);
}
return(0);
}
#endif /* HAVE_REPLICATION */
/********************************************************************* /*********************************************************************
Rolls back a transaction or the latest SQL statement. */ Rolls back a transaction or the latest SQL statement. */
@@ -2444,8 +2211,7 @@ ha_innobase::open(
/* Get pointer to a table object in InnoDB dictionary cache */ /* Get pointer to a table object in InnoDB dictionary cache */
ib_table = dict_table_get_and_increment_handle_count( ib_table = dict_table_get_and_increment_handle_count(norm_name);
norm_name, NULL);
if (NULL == ib_table) { if (NULL == ib_table) {
ut_print_timestamp(stderr); ut_print_timestamp(stderr);
@@ -5026,7 +4792,7 @@ ha_innobase::create(
log_buffer_flush_to_disk(); log_buffer_flush_to_disk();
innobase_table = dict_table_get(norm_name, NULL); innobase_table = dict_table_get(norm_name);
DBUG_ASSERT(innobase_table != 0); DBUG_ASSERT(innobase_table != 0);

View File

@@ -316,9 +316,6 @@ int innobase_rollback_by_xid(
XID *xid); /* in : X/Open XA Transaction Identification */ XID *xid); /* in : X/Open XA Transaction Identification */
int innobase_repl_report_sent_binlog(THD *thd, char *log_file_name,
my_off_t end_offset);
/*********************************************************************** /***********************************************************************
Create a consistent view for a cursor based on current transaction Create a consistent view for a cursor based on current transaction
which is created if the corresponding MySQL thread still lacks one. which is created if the corresponding MySQL thread still lacks one.

View File

@@ -144,6 +144,7 @@ static ulint ibuf_rnd = 986058871;
ulint ibuf_flush_count = 0; ulint ibuf_flush_count = 0;
#ifdef UNIV_IBUF_DEBUG
/* Dimensions for the ibuf_count array */ /* Dimensions for the ibuf_count array */
#define IBUF_COUNT_N_SPACES 500 #define IBUF_COUNT_N_SPACES 500
#define IBUF_COUNT_N_PAGES 2000 #define IBUF_COUNT_N_PAGES 2000
@@ -152,6 +153,7 @@ ulint ibuf_flush_count = 0;
static ulint* ibuf_counts[IBUF_COUNT_N_SPACES]; static ulint* ibuf_counts[IBUF_COUNT_N_SPACES];
static ibool ibuf_counts_inited = FALSE; static ibool ibuf_counts_inited = FALSE;
#endif
/* The start address for an insert buffer bitmap page bitmap */ /* The start address for an insert buffer bitmap page bitmap */
#define IBUF_BITMAP PAGE_DATA #define IBUF_BITMAP PAGE_DATA
@@ -314,6 +316,7 @@ ibuf_tree_root_get(
return(page); return(page);
} }
#ifdef UNIV_IBUF_DEBUG
/********************************************************************** /**********************************************************************
Gets the ibuf count for a given page. */ Gets the ibuf count for a given page. */
@@ -338,7 +341,6 @@ ibuf_count_get(
/********************************************************************** /**********************************************************************
Sets the ibuf count for a given page. */ Sets the ibuf count for a given page. */
#ifdef UNIV_IBUF_DEBUG
static static
void void
ibuf_count_set( ibuf_count_set(
@@ -389,23 +391,18 @@ ibuf_init_at_db_start(void)
ibuf_count_set(i, j, 0); ibuf_count_set(i, j, 0);
} }
} }
ibuf_counts_inited = TRUE;
} }
#endif #endif
mutex_create(&ibuf_pessimistic_insert_mutex); mutex_create(&ibuf_pessimistic_insert_mutex,
SYNC_IBUF_PESS_INSERT_MUTEX);
mutex_set_level(&ibuf_pessimistic_insert_mutex, mutex_create(&ibuf_mutex, SYNC_IBUF_MUTEX);
SYNC_IBUF_PESS_INSERT_MUTEX);
mutex_create(&ibuf_mutex);
mutex_set_level(&ibuf_mutex, SYNC_IBUF_MUTEX); mutex_create(&ibuf_bitmap_mutex, SYNC_IBUF_BITMAP_MUTEX);
mutex_create(&ibuf_bitmap_mutex);
mutex_set_level(&ibuf_bitmap_mutex, SYNC_IBUF_BITMAP_MUTEX);
fil_ibuf_init_at_db_start(); fil_ibuf_init_at_db_start();
ibuf_counts_inited = TRUE;
} }
/********************************************************************** /**********************************************************************

View File

@@ -265,17 +265,16 @@ dict_foreign_parse_drop_constraints(
const char*** constraints_to_drop); /* out: id's of the const char*** constraints_to_drop); /* out: id's of the
constraints to drop */ constraints to drop */
/************************************************************************** /**************************************************************************
Returns a table object and memoryfixes it. NOTE! This is a high-level Returns a table object. NOTE! This is a high-level function to be used
function to be used mainly from outside the 'dict' directory. Inside this mainly from outside the 'dict' directory. Inside this directory
directory dict_table_get_low is usually the appropriate function. */ dict_table_get_low is usually the appropriate function. */
dict_table_t* dict_table_t*
dict_table_get( dict_table_get(
/*===========*/ /*===========*/
/* out: table, NULL if /* out: table, NULL if
does not exist */ does not exist */
const char* table_name, /* in: table name */ const char* table_name); /* in: table name */
trx_t* trx); /* in: transaction handle */
/************************************************************************** /**************************************************************************
Returns a table object and increments MySQL open handle count on the table. Returns a table object and increments MySQL open handle count on the table.
*/ */
@@ -285,10 +284,9 @@ dict_table_get_and_increment_handle_count(
/*======================================*/ /*======================================*/
/* out: table, NULL if /* out: table, NULL if
does not exist */ does not exist */
const char* table_name, /* in: table name */ const char* table_name); /* in: table name */
trx_t* trx); /* in: transaction handle or NULL */
/************************************************************************** /**************************************************************************
Returns a table object, based on table id, and memoryfixes it. */ Returns a table object based on table id. */
dict_table_t* dict_table_t*
dict_table_get_on_id( dict_table_get_on_id(
@@ -297,21 +295,13 @@ dict_table_get_on_id(
dulint table_id, /* in: table id */ dulint table_id, /* in: table id */
trx_t* trx); /* in: transaction handle */ trx_t* trx); /* in: transaction handle */
/************************************************************************** /**************************************************************************
Returns a table object, based on table id, and memoryfixes it. */ Returns a table object based on table id. */
UNIV_INLINE UNIV_INLINE
dict_table_t* dict_table_t*
dict_table_get_on_id_low( dict_table_get_on_id_low(
/*=====================*/ /*=====================*/
/* out: table, NULL if does not exist */ /* out: table, NULL if does not exist */
dulint table_id, /* in: table id */ dulint table_id); /* in: table id */
trx_t* trx); /* in: transaction handle */
/**************************************************************************
Releases a table from being memoryfixed. Currently this has no relevance. */
UNIV_INLINE
void
dict_table_release(
/*===============*/
dict_table_t* table); /* in: table to be released */
/************************************************************************** /**************************************************************************
Checks if a table is in the dictionary cache. */ Checks if a table is in the dictionary cache. */
UNIV_INLINE UNIV_INLINE

View File

@@ -577,14 +577,13 @@ dict_table_get_low(
} }
/************************************************************************** /**************************************************************************
Returns a table object, based on table id, and memoryfixes it. */ Returns a table object based on table id. */
UNIV_INLINE UNIV_INLINE
dict_table_t* dict_table_t*
dict_table_get_on_id_low( dict_table_get_on_id_low(
/*=====================*/ /*=====================*/
/* out: table, NULL if does not exist */ /* out: table, NULL if does not exist */
dulint table_id, /* in: table id */ dulint table_id) /* in: table id */
trx_t* trx) /* in: transaction handle */
{ {
dict_table_t* table; dict_table_t* table;
ulint fold; ulint fold;
@@ -592,7 +591,6 @@ dict_table_get_on_id_low(
#ifdef UNIV_SYNC_DEBUG #ifdef UNIV_SYNC_DEBUG
ut_ad(mutex_own(&(dict_sys->mutex))); ut_ad(mutex_own(&(dict_sys->mutex)));
#endif /* UNIV_SYNC_DEBUG */ #endif /* UNIV_SYNC_DEBUG */
UT_NOT_USED(trx);
/* Look for the table name in the hash table */ /* Look for the table name in the hash table */
fold = ut_fold_dulint(table_id); fold = ut_fold_dulint(table_id);
@@ -603,32 +601,11 @@ dict_table_get_on_id_low(
table = dict_load_table_on_id(table_id); table = dict_load_table_on_id(table_id);
} }
if (table != NULL) {
table->mem_fix++;
/* lock_push(trx, table, LOCK_DICT_MEM_FIX) */
}
/* TODO: should get the type information from MySQL */ /* TODO: should get the type information from MySQL */
return(table); return(table);
} }
/**************************************************************************
Releases a table from being memoryfixed. Currently this has no relevance. */
UNIV_INLINE
void
dict_table_release(
/*===============*/
dict_table_t* table) /* in: table to be released */
{
mutex_enter(&(dict_sys->mutex));
table->mem_fix--;
mutex_exit(&(dict_sys->mutex));
}
/************************************************************************** /**************************************************************************
Returns an index object. */ Returns an index object. */
UNIV_INLINE UNIV_INLINE

View File

@@ -172,10 +172,6 @@ struct dict_tree_struct{
the same memory cache line */ the same memory cache line */
rw_lock_t lock; /* read-write lock protecting the upper levels rw_lock_t lock; /* read-write lock protecting the upper levels
of the index tree */ of the index tree */
ulint mem_fix;/* count of how many times this tree
struct has been memoryfixed (by mini-
transactions wanting to access the index
tree) */
dict_index_t* tree_index; /* the index stored in the dict_index_t* tree_index; /* the index stored in the
index tree */ index tree */
ulint magic_n;/* magic number */ ulint magic_n;/* magic number */
@@ -318,9 +314,6 @@ struct dict_table_struct{
which refer to this table */ which refer to this table */
UT_LIST_NODE_T(dict_table_t) UT_LIST_NODE_T(dict_table_t)
table_LRU; /* node of the LRU list of tables */ table_LRU; /* node of the LRU list of tables */
ulint mem_fix;/* count of how many times the table
and its indexes has been fixed in memory;
currently NOT used */
ulint n_mysql_handles_opened; ulint n_mysql_handles_opened;
/* count of how many handles MySQL has opened /* count of how many handles MySQL has opened
to this table; dropping of the table is to this table; dropping of the table is

View File

@@ -369,24 +369,28 @@ description takes less than 1 byte; a descriptor page is repeated every
this many file pages */ this many file pages */
#define XDES_DESCRIBED_PER_PAGE UNIV_PAGE_SIZE #define XDES_DESCRIBED_PER_PAGE UNIV_PAGE_SIZE
/* The space low address page map, and also offsets for extent descriptor and /* The space low address page map */
bitmap pages which are repeated always after XDES_DESCRIBED_PER_PAGE more
pages: */
/*--------------------------------------*/ /*--------------------------------------*/
#define FSP_XDES_OFFSET 0 /* The following two pages are repeated
#define FSP_IBUF_BITMAP_OFFSET 1 every XDES_DESCRIBED_PER_PAGE pages in
every tablespace. */
#define FSP_XDES_OFFSET 0 /* extent descriptor */
#define FSP_IBUF_BITMAP_OFFSET 1 /* insert buffer bitmap */
/* The ibuf bitmap pages are the ones whose /* The ibuf bitmap pages are the ones whose
page number is the number above plus a page number is the number above plus a
multiple of XDES_DESCRIBED_PER_PAGE */ multiple of XDES_DESCRIBED_PER_PAGE */
#define FSP_FIRST_INODE_PAGE_NO 2
#define FSP_IBUF_HEADER_PAGE_NO 3 #define FSP_FIRST_INODE_PAGE_NO 2 /* in every tablespace */
#define FSP_IBUF_TREE_ROOT_PAGE_NO 4 /* The following pages exist
in the system tablespace (space 0). */
#define FSP_IBUF_HEADER_PAGE_NO 3 /* in tablespace 0 */
#define FSP_IBUF_TREE_ROOT_PAGE_NO 4 /* in tablespace 0 */
/* The ibuf tree root page number in /* The ibuf tree root page number in
tablespace 0; its fseg inode is on the page tablespace 0; its fseg inode is on the page
number FSP_FIRST_INODE_PAGE_NO */ number FSP_FIRST_INODE_PAGE_NO */
#define FSP_TRX_SYS_PAGE_NO 5 #define FSP_TRX_SYS_PAGE_NO 5 /* in tablespace 0 */
#define FSP_FIRST_RSEG_PAGE_NO 6 #define FSP_FIRST_RSEG_PAGE_NO 6 /* in tablespace 0 */
#define FSP_DICT_HDR_PAGE_NO 7 #define FSP_DICT_HDR_PAGE_NO 7 /* in tablespace 0 */
/*--------------------------------------*/ /*--------------------------------------*/
#ifndef UNIV_NONINL #ifndef UNIV_NONINL

View File

@@ -267,6 +267,7 @@ ibuf_parse_bitmap_init(
byte* end_ptr,/* in: buffer end */ byte* end_ptr,/* in: buffer end */
page_t* page, /* in: page or NULL */ page_t* page, /* in: page or NULL */
mtr_t* mtr); /* in: mtr or NULL */ mtr_t* mtr); /* in: mtr or NULL */
#ifdef UNIV_IBUF_DEBUG
/********************************************************************** /**********************************************************************
Gets the ibuf count for a given page. */ Gets the ibuf count for a given page. */
@@ -277,6 +278,7 @@ ibuf_count_get(
currently buffered for this page */ currently buffered for this page */
ulint space, /* in: space id */ ulint space, /* in: space id */
ulint page_no);/* in: page number */ ulint page_no);/* in: page number */
#endif
/********************************************************************** /**********************************************************************
Looks if the insert buffer is empty. */ Looks if the insert buffer is empty. */

View File

@@ -297,8 +297,8 @@ char*
mem_heap_strdup( mem_heap_strdup(
/*============*/ /*============*/
/* out, own: a copy of the string */ /* out, own: a copy of the string */
mem_heap_t* heap, /* in: memory heap where string is allocated */ mem_heap_t* heap, /* in: memory heap where string is allocated */
const char* str); /* in: string to be copied */ const char* str); /* in: string to be copied */
/************************************************************************** /**************************************************************************
Makes a NUL-terminated copy of a nonterminated string, Makes a NUL-terminated copy of a nonterminated string,
allocated from a memory heap. */ allocated from a memory heap. */
@@ -311,6 +311,28 @@ mem_heap_strdupl(
const char* str, /* in: string to be copied */ const char* str, /* in: string to be copied */
ulint len); /* in: length of str, in bytes */ ulint len); /* in: length of str, in bytes */
/**************************************************************************
Concatenate two strings and return the result, using a memory heap. */
char*
mem_heap_strcat(
/*============*/
/* out, own: the result */
mem_heap_t* heap, /* in: memory heap where string is allocated */
const char* s1, /* in: string 1 */
const char* s2); /* in: string 2 */
/**************************************************************************
Duplicate a block of data, allocated from a memory heap. */
void*
mem_heap_dup(
/*=========*/
/* out, own: a copy of the data */
mem_heap_t* heap, /* in: memory heap where copy is allocated */
const void* data, /* in: data to be copied */
ulint len); /* in: length of data, in bytes */
#ifdef MEM_PERIODIC_CHECK #ifdef MEM_PERIODIC_CHECK
/********************************************************************** /**********************************************************************
Goes through the list of all allocated mem blocks, checks their magic Goes through the list of all allocated mem blocks, checks their magic

View File

@@ -77,7 +77,7 @@ os_thread_create(
void* arg, /* in: argument to start void* arg, /* in: argument to start
function */ function */
os_thread_id_t* thread_id); /* out: id of the created os_thread_id_t* thread_id); /* out: id of the created
thread */ thread, or NULL */
int int
os_thread_join( os_thread_join(
/*===========*/ /*===========*/

View File

@@ -531,6 +531,16 @@ pars_info_add_function(
pars_user_func_cb_t func, /* in: function address */ pars_user_func_cb_t func, /* in: function address */
void* arg); /* in: user-supplied argument */ void* arg); /* in: user-supplied argument */
/********************************************************************
Add bound id. */
void
pars_info_add_id(
/*=============*/
pars_info_t* info, /* in: info struct */
const char* name, /* in: name */
const char* id); /* in: id */
/******************************************************************** /********************************************************************
Get user function with the given name.*/ Get user function with the given name.*/
@@ -553,6 +563,17 @@ pars_info_get_bound_lit(
pars_info_t* info, /* in: info struct */ pars_info_t* info, /* in: info struct */
const char* name); /* in: bound literal name to find */ const char* name); /* in: bound literal name to find */
/********************************************************************
Get bound id with the given name.*/
pars_bound_id_t*
pars_info_get_bound_id(
/*===================*/
/* out: bound id, or NULL if not
found */
pars_info_t* info, /* in: info struct */
const char* name); /* in: bound id name to find */
/* Extra information supplied for pars_sql(). */ /* Extra information supplied for pars_sql(). */
struct pars_info_struct { struct pars_info_struct {
@@ -562,6 +583,8 @@ struct pars_info_struct {
(pars_user_func_t*) */ (pars_user_func_t*) */
ib_vector_t* bound_lits; /* bound literals, or NULL ib_vector_t* bound_lits; /* bound literals, or NULL
(pars_bound_lit_t*) */ (pars_bound_lit_t*) */
ib_vector_t* bound_ids; /* bound ids, or NULL
(pars_bound_id_t*) */
ibool graph_owns_us; /* if TRUE (which is the default), ibool graph_owns_us; /* if TRUE (which is the default),
que_graph_free() will free us */ que_graph_free() will free us */
@@ -583,6 +606,12 @@ struct pars_bound_lit_struct {
ulint prtype; /* precise type, e.g. DATA_UNSIGNED */ ulint prtype; /* precise type, e.g. DATA_UNSIGNED */
}; };
/* Bound id. */
struct pars_bound_id_struct {
const char* name; /* name */
const char* id; /* id */
};
/* Struct used to denote a reserved word in a parsing tree */ /* Struct used to denote a reserved word in a parsing tree */
struct pars_res_word_struct{ struct pars_res_word_struct{
int code; /* the token code for the reserved word from int code; /* the token code for the reserved word from

View File

@@ -82,6 +82,16 @@ sym_tab_add_id(
byte* name, /* in: identifier name */ byte* name, /* in: identifier name */
ulint len); /* in: identifier length */ ulint len); /* in: identifier length */
/**********************************************************************
Add a bound identifier to a symbol table. */
sym_node_t*
sym_tab_add_bound_id(
/*===========*/
/* out: symbol table node */
sym_tab_t* sym_tab, /* in: symbol table */
const char* name); /* in: name of bound id */
#define SYM_CLUST_FIELD_NO 0 #define SYM_CLUST_FIELD_NO 0
#define SYM_SEC_FIELD_NO 1 #define SYM_SEC_FIELD_NO 1

View File

@@ -12,6 +12,7 @@ Created 1/11/1998 Heikki Tuuri
typedef struct pars_info_struct pars_info_t; typedef struct pars_info_struct pars_info_t;
typedef struct pars_user_func_struct pars_user_func_t; typedef struct pars_user_func_struct pars_user_func_t;
typedef struct pars_bound_lit_struct pars_bound_lit_t; typedef struct pars_bound_lit_struct pars_bound_lit_t;
typedef struct pars_bound_id_struct pars_bound_id_t;
typedef struct sym_node_struct sym_node_t; typedef struct sym_node_struct sym_node_t;
typedef struct sym_tab_struct sym_tab_t; typedef struct sym_tab_struct sym_tab_t;
typedef struct pars_res_word_struct pars_res_word_t; typedef struct pars_res_word_struct pars_res_word_t;

View File

@@ -56,9 +56,7 @@ struct purge_node_struct{
determined by ref was found in the clustered determined by ref was found in the clustered
index, and we were able to position pcur on index, and we were able to position pcur on
it */ it */
dict_table_t* table; /* table where purge is done; NOTE that the dict_table_t* table; /* table where purge is done */
table has to be released explicitly with
dict_table_release */
ulint cmpl_info;/* compiler analysis info of an update */ ulint cmpl_info;/* compiler analysis info of an update */
upd_t* update; /* update vector for a clustered index record */ upd_t* update; /* update vector for a clustered index record */
dtuple_t* ref; /* NULL, or row reference to the next row to dtuple_t* ref; /* NULL, or row reference to the next row to

View File

@@ -84,9 +84,7 @@ struct undo_node_struct{
record */ record */
btr_pcur_t pcur; /* persistent cursor used in searching the btr_pcur_t pcur; /* persistent cursor used in searching the
clustered index record */ clustered index record */
dict_table_t* table; /* table where undo is done; NOTE that the dict_table_t* table; /* table where undo is done */
table has to be released explicitly with
dict_table_release */
ulint cmpl_info;/* compiler analysis of an update */ ulint cmpl_info;/* compiler analysis of an update */
upd_t* update; /* update vector for a clustered index record */ upd_t* update; /* update vector for a clustered index record */
dtuple_t* ref; /* row reference to the next row to handle */ dtuple_t* ref; /* row reference to the next row to handle */

View File

@@ -157,33 +157,12 @@ extern ulint srv_pool_size;
extern ulint srv_mem_pool_size; extern ulint srv_mem_pool_size;
extern ulint srv_lock_table_size; extern ulint srv_lock_table_size;
extern ulint srv_sim_disk_wait_pct;
extern ulint srv_sim_disk_wait_len;
extern ibool srv_sim_disk_wait_by_yield;
extern ibool srv_sim_disk_wait_by_wait;
extern ibool srv_measure_contention;
extern ibool srv_measure_by_spin;
extern ibool srv_print_thread_releases; extern ibool srv_print_thread_releases;
extern ibool srv_print_lock_waits; extern ibool srv_print_lock_waits;
extern ibool srv_print_buf_io; extern ibool srv_print_buf_io;
extern ibool srv_print_log_io; extern ibool srv_print_log_io;
extern ibool srv_print_parsed_sql;
extern ibool srv_print_latch_waits; extern ibool srv_print_latch_waits;
extern ibool srv_test_nocache;
extern ibool srv_test_cache_evict;
extern ibool srv_test_extra_mutexes;
extern ibool srv_test_sync;
extern ulint srv_test_n_threads;
extern ulint srv_test_n_loops;
extern ulint srv_test_n_free_rnds;
extern ulint srv_test_n_reserved_rnds;
extern ulint srv_test_n_mutexes;
extern ulint srv_test_array_size;
extern ulint srv_activity_count; extern ulint srv_activity_count;
extern ulint srv_fatal_semaphore_wait_threshold; extern ulint srv_fatal_semaphore_wait_threshold;
extern ulint srv_dml_needed_delay; extern ulint srv_dml_needed_delay;
@@ -365,11 +344,7 @@ srv_release_threads(
/************************************************************************* /*************************************************************************
The master thread controlling the server. */ The master thread controlling the server. */
#ifndef __WIN__ os_thread_ret_t
void*
#else
ulint
#endif
srv_master_thread( srv_master_thread(
/*==============*/ /*==============*/
/* out: a dummy parameter */ /* out: a dummy parameter */
@@ -451,11 +426,7 @@ srv_release_mysql_thread_if_suspended(
A thread which wakes up threads whose lock wait may have lasted too long. A thread which wakes up threads whose lock wait may have lasted too long.
This also prints the info output by various InnoDB monitors. */ This also prints the info output by various InnoDB monitors. */
#ifndef __WIN__ os_thread_ret_t
void*
#else
ulint
#endif
srv_lock_timeout_and_monitor_thread( srv_lock_timeout_and_monitor_thread(
/*================================*/ /*================================*/
/* out: a dummy parameter */ /* out: a dummy parameter */
@@ -465,11 +436,7 @@ srv_lock_timeout_and_monitor_thread(
A thread which prints warnings about semaphore waits which have lasted A thread which prints warnings about semaphore waits which have lasted
too long. These can be used to track bugs which cause hangs. */ too long. These can be used to track bugs which cause hangs. */
#ifndef __WIN__ os_thread_ret_t
void*
#else
ulint
#endif
srv_error_monitor_thread( srv_error_monitor_thread(
/*=====================*/ /*=====================*/
/* out: a dummy parameter */ /* out: a dummy parameter */
@@ -567,9 +534,6 @@ struct export_var_struct{
/* The server system struct */ /* The server system struct */
struct srv_sys_struct{ struct srv_sys_struct{
os_event_t operational; /* created threads must wait for the
server to become operational by
waiting for this event */
srv_table_t* threads; /* server thread table */ srv_table_t* threads; /* server thread table */
UT_LIST_BASE_NODE_T(que_thr_t) UT_LIST_BASE_NODE_T(que_thr_t)
tasks; /* task queue */ tasks; /* task queue */

View File

@@ -61,7 +61,7 @@ Creates, or rather, initializes an rw-lock object in a specified memory
location (which must be appropriately aligned). The rw-lock is initialized location (which must be appropriately aligned). The rw-lock is initialized
to the non-locked state. Explicit freeing of the rw-lock with rw_lock_free to the non-locked state. Explicit freeing of the rw-lock with rw_lock_free
is necessary only if the memory block containing it is freed. */ is necessary only if the memory block containing it is freed. */
#define rw_lock_create(L) rw_lock_create_func((L), __FILE__, __LINE__, #L) #define rw_lock_create(L, level) rw_lock_create_func((L), (level), __FILE__, __LINE__, #L)
/*=====================*/ /*=====================*/
/********************************************************************** /**********************************************************************
@@ -74,9 +74,10 @@ void
rw_lock_create_func( rw_lock_create_func(
/*================*/ /*================*/
rw_lock_t* lock, /* in: pointer to memory */ rw_lock_t* lock, /* in: pointer to memory */
ulint level, /* in: level */
const char* cfile_name, /* in: file name where created */ const char* cfile_name, /* in: file name where created */
ulint cline, /* in: file line where created */ ulint cline, /* in: file line where created */
const char* cmutex_name); /* in: mutex name */ const char* cmutex_name); /* in: mutex name */
/********************************************************************** /**********************************************************************
Calling this function is obligatory only if the memory buffer containing Calling this function is obligatory only if the memory buffer containing
the rw-lock is freed. Removes an rw-lock object from the global list. The the rw-lock is freed. Removes an rw-lock object from the global list. The
@@ -299,14 +300,6 @@ rw_lock_x_unlock_direct(
/*====================*/ /*====================*/
rw_lock_t* lock); /* in: rw-lock */ rw_lock_t* lock); /* in: rw-lock */
/********************************************************************** /**********************************************************************
Sets the rw-lock latching level field. */
void
rw_lock_set_level(
/*==============*/
rw_lock_t* lock, /* in: rw-lock */
ulint level); /* in: level */
/**********************************************************************
Returns the value of writer_count for the lock. Does not reserve the lock Returns the value of writer_count for the lock. Does not reserve the lock
mutex, so the caller must be sure it is not changed during the call. */ mutex, so the caller must be sure it is not changed during the call. */
UNIV_INLINE UNIV_INLINE
@@ -448,8 +441,8 @@ struct rw_lock_struct {
/* In the debug version: pointer to the debug /* In the debug version: pointer to the debug
info list of the lock */ info list of the lock */
#endif /* UNIV_SYNC_DEBUG */ #endif /* UNIV_SYNC_DEBUG */
ulint level; /* Level in the global latching
order; default SYNC_LEVEL_NONE */ ulint level; /* Level in the global latching order. */
const char* cfile_name;/* File name where lock created */ const char* cfile_name;/* File name where lock created */
ulint cline; /* Line where created */ ulint cline; /* Line where created */
const char* last_s_file_name;/* File name where last s-locked */ const char* last_s_file_name;/* File name where last s-locked */

View File

@@ -39,7 +39,7 @@ location (which must be appropriately aligned). The mutex is initialized
in the reset state. Explicit freeing of the mutex with mutex_free is in the reset state. Explicit freeing of the mutex with mutex_free is
necessary only if the memory block containing it is freed. */ necessary only if the memory block containing it is freed. */
#define mutex_create(M) mutex_create_func((M), __FILE__, __LINE__, #M) #define mutex_create(M, level) mutex_create_func((M), (level), __FILE__, __LINE__, #M)
/*===================*/ /*===================*/
/********************************************************************** /**********************************************************************
Creates, or rather, initializes a mutex object in a specified memory Creates, or rather, initializes a mutex object in a specified memory
@@ -51,6 +51,7 @@ void
mutex_create_func( mutex_create_func(
/*==============*/ /*==============*/
mutex_t* mutex, /* in: pointer to memory */ mutex_t* mutex, /* in: pointer to memory */
ulint level, /* in: level */
const char* cfile_name, /* in: file name where created */ const char* cfile_name, /* in: file name where created */
ulint cline, /* in: file line where created */ ulint cline, /* in: file line where created */
const char* cmutex_name); /* in: mutex name */ const char* cmutex_name); /* in: mutex name */
@@ -155,14 +156,6 @@ mutex_validate(
/*===========*/ /*===========*/
mutex_t* mutex); mutex_t* mutex);
/********************************************************************** /**********************************************************************
Sets the mutex latching level field. */
void
mutex_set_level(
/*============*/
mutex_t* mutex, /* in: mutex */
ulint level); /* in: level */
/**********************************************************************
Adds a latch and its level in the thread level array. Allocates the memory Adds a latch and its level in the thread level array. Allocates the memory
for the array if called first time for this OS thread. Makes the checks for the array if called first time for this OS thread. Makes the checks
against other latch levels stored in the array for this thread. */ against other latch levels stored in the array for this thread. */
@@ -171,8 +164,8 @@ void
sync_thread_add_level( sync_thread_add_level(
/*==================*/ /*==================*/
void* latch, /* in: pointer to a mutex or an rw-lock */ void* latch, /* in: pointer to a mutex or an rw-lock */
ulint level); /* in: level in the latching order; if SYNC_LEVEL_NONE, ulint level); /* in: level in the latching order; if
nothing is done */ SYNC_LEVEL_VARYING, nothing is done */
/********************************************************************** /**********************************************************************
Removes a latch from the thread level array if it is found there. */ Removes a latch from the thread level array if it is found there. */
@@ -383,7 +376,12 @@ or row lock! */
#define SYNC_USER_TRX_LOCK 9999 #define SYNC_USER_TRX_LOCK 9999
#define SYNC_NO_ORDER_CHECK 3000 /* this can be used to suppress #define SYNC_NO_ORDER_CHECK 3000 /* this can be used to suppress
latching order checking */ latching order checking */
#define SYNC_LEVEL_NONE 2000 /* default: level not defined */ #define SYNC_LEVEL_VARYING 2000 /* Level is varying. Only used with
buffer pool page locks, which do not
have a fixed level, but instead have
their level set after the page is
locked; see e.g.
ibuf_bitmap_get_map_page(). */
#define SYNC_DICT_OPERATION 1001 /* table create, drop, etc. reserve #define SYNC_DICT_OPERATION 1001 /* table create, drop, etc. reserve
this in X-mode, implicit or backround this in X-mode, implicit or backround
operations purge, rollback, foreign operations purge, rollback, foreign
@@ -426,6 +424,7 @@ or row lock! */
#define SYNC_TRX_SYS_HEADER 290 #define SYNC_TRX_SYS_HEADER 290
#define SYNC_LOG 170 #define SYNC_LOG 170
#define SYNC_RECV 168 #define SYNC_RECV 168
#define SYNC_WORK_QUEUE 161
#define SYNC_SEARCH_SYS 160 /* NOTE that if we have a memory #define SYNC_SEARCH_SYS 160 /* NOTE that if we have a memory
heap that can be extended to the heap that can be extended to the
buffer pool, its logical level is buffer pool, its logical level is
@@ -472,8 +471,7 @@ struct mutex_struct {
os_thread_id_t thread_id; /* Debug version: The thread id of the os_thread_id_t thread_id; /* Debug version: The thread id of the
thread which locked the mutex. */ thread which locked the mutex. */
#endif /* UNIV_SYNC_DEBUG */ #endif /* UNIV_SYNC_DEBUG */
ulint level; /* Level in the global latching ulint level; /* Level in the global latching order */
order; default SYNC_LEVEL_NONE */
const char* cfile_name;/* File name where mutex created */ const char* cfile_name;/* File name where mutex created */
ulint cline; /* Line where created */ ulint cline; /* Line where created */
ulint magic_n; ulint magic_n;

View File

@@ -107,11 +107,7 @@ transaction already was committed, then we clean up a possible insert
undo log. If the transaction was not yet committed, then we roll it back. undo log. If the transaction was not yet committed, then we roll it back.
Note: this is done in a background thread. */ Note: this is done in a background thread. */
#ifndef __WIN__ os_thread_ret_t
void*
#else
ulint
#endif
trx_rollback_or_clean_all_without_sess( trx_rollback_or_clean_all_without_sess(
/*===================================*/ /*===================================*/
/* out: a dummy parameter */ /* out: a dummy parameter */

View File

@@ -75,6 +75,15 @@ multiple tablespace format. */
void void
trx_sys_mark_upgraded_to_multiple_tablespaces(void); trx_sys_mark_upgraded_to_multiple_tablespaces(void);
/*===============================================*/ /*===============================================*/
/********************************************************************
Determines if a page number is located inside the doublewrite buffer. */
ibool
trx_doublewrite_page_inside(
/*========================*/
/* out: TRUE if the location is inside
the two blocks of the doublewrite buffer */
ulint page_no); /* in: page number */
/******************************************************************* /*******************************************************************
Checks if a page address is the trx sys header page. */ Checks if a page address is the trx sys header page. */
UNIV_INLINE UNIV_INLINE

View File

@@ -82,17 +82,18 @@ memory is read outside the allocated blocks. */
/* Make a non-inline debug version */ /* Make a non-inline debug version */
#if 0
#define UNIV_DEBUG #define UNIV_DEBUG
/*
#define UNIV_MEM_DEBUG #define UNIV_MEM_DEBUG
#define UNIV_IBUF_DEBUG #define UNIV_IBUF_DEBUG
#define UNIV_SYNC_DEBUG #define UNIV_SYNC_DEBUG
#define UNIV_SEARCH_DEBUG #define UNIV_SEARCH_DEBUG
#define UNIV_SYNC_PERF_STAT #define UNIV_SYNC_PERF_STAT
#define UNIV_SEARCH_PERF_STAT #define UNIV_SEARCH_PERF_STAT
#define UNIV_SRV_PRINT_LATCH_WAITS; #define UNIV_SRV_PRINT_LATCH_WAITS
#define UNIV_ZIP_DEBUG #define UNIV_ZIP_DEBUG
*/ #endif
#define UNIV_LIGHT_MEM_DEBUG #define UNIV_LIGHT_MEM_DEBUG
#define YYDEBUG 1 #define YYDEBUG 1
@@ -274,6 +275,18 @@ it is read or written. */
/* Compile-time constant of the given array's size. */ /* Compile-time constant of the given array's size. */
#define UT_ARR_SIZE(a) (sizeof(a) / sizeof((a)[0])) #define UT_ARR_SIZE(a) (sizeof(a) / sizeof((a)[0]))
/* The return type from a thread's start function differs between Unix and
Windows, so define a typedef for it and a macro to use at the end of such
functions. */
#ifdef __WIN__
typedef ulint os_thread_ret_t;
#define OS_THREAD_DUMMY_RETURN return(0)
#else
typedef void* os_thread_ret_t;
#define OS_THREAD_DUMMY_RETURN return(NULL)
#endif
#include <stdio.h> #include <stdio.h>
#include "ut0dbg.h" #include "ut0dbg.h"
#include "ut0ut.h" #include "ut0ut.h"

134
include/ut0list.h Normal file
View File

@@ -0,0 +1,134 @@
/***********************************************************************
A double-linked list. This differs from the one in ut0lst.h in that in this
one, each list node contains a pointer to the data, whereas the one in
ut0lst.h uses a strategy where the list pointers are embedded in the data
items themselves.
Use this one when you need to store arbitrary data in the list where you
can't embed the list pointers in the data, if a data item needs to be
stored in multiple lists, etc.
Note about the memory management: ib_list_t is a fixed-size struct whose
allocation/deallocation is done through ib_list_create/ib_list_free, but the
memory for the list nodes is allocated through a user-given memory heap,
which can either be the same for all nodes or vary per node. Most users will
probably want to create a memory heap to store the item-specific data, and
pass in this same heap to the list node creation functions, thus
automatically freeing the list node when the item's heap is freed.
************************************************************************/
#ifndef IB_LIST_H
#define IB_LIST_H
#include "mem0mem.h"
typedef struct ib_list_struct ib_list_t;
typedef struct ib_list_node_struct ib_list_node_t;
typedef struct ib_list_helper_struct ib_list_helper_t;
/********************************************************************
Create a new list. */
ib_list_t*
ib_list_create(void);
/*=================*/
/* out: list */
/********************************************************************
Free a list. */
void
ib_list_free(
/*=========*/
ib_list_t* list); /* in: list */
/********************************************************************
Add the data to the start of the list. */
ib_list_node_t*
ib_list_add_first(
/*==============*/
/* out: new list node*/
ib_list_t* list, /* in: list */
void* data, /* in: data */
mem_heap_t* heap); /* in: memory heap to use */
/********************************************************************
Add the data to the end of the list. */
ib_list_node_t*
ib_list_add_last(
/*=============*/
/* out: new list node*/
ib_list_t* list, /* in: list */
void* data, /* in: data */
mem_heap_t* heap); /* in: memory heap to use */
/********************************************************************
Add the data after the indicated node. */
ib_list_node_t*
ib_list_add_after(
/*==============*/
/* out: new list node*/
ib_list_t* list, /* in: list */
ib_list_node_t* prev_node, /* in: node preceding new node (can
be NULL) */
void* data, /* in: data */
mem_heap_t* heap); /* in: memory heap to use */
/********************************************************************
Remove the node from the list. */
void
ib_list_remove(
/*===========*/
ib_list_t* list, /* in: list */
ib_list_node_t* node); /* in: node to remove */
/********************************************************************
Get the first node in the list. */
UNIV_INLINE
ib_list_node_t*
ib_list_get_first(
/*==============*/
/* out: first node, or NULL */
ib_list_t* list); /* in: list */
/********************************************************************
Get the last node in the list. */
UNIV_INLINE
ib_list_node_t*
ib_list_get_last(
/*=============*/
/* out: last node, or NULL */
ib_list_t* list); /* in: list */
/* List. */
struct ib_list_struct {
ib_list_node_t* first; /* first node */
ib_list_node_t* last; /* last node */
};
/* A list node. */
struct ib_list_node_struct {
ib_list_node_t* prev; /* previous node */
ib_list_node_t* next; /* next node */
void* data; /* user data */
};
/* Quite often, the only additional piece of data you need is the per-item
memory heap, so we have this generic struct available to use in those
cases. */
struct ib_list_helper_struct {
mem_heap_t* heap; /* memory heap */
void* data; /* user data */
};
#ifndef UNIV_NONINL
#include "ut0list.ic"
#endif
#endif

23
include/ut0list.ic Normal file
View File

@@ -0,0 +1,23 @@
/********************************************************************
Get the first node in the list. */
UNIV_INLINE
ib_list_node_t*
ib_list_get_first(
/*==============*/
/* out: first node, or NULL */
ib_list_t* list) /* in: list */
{
return(list->first);
}
/********************************************************************
Get the last node in the list. */
UNIV_INLINE
ib_list_node_t*
ib_list_get_last(
/*=============*/
/* out: last node, or NULL */
ib_list_t* list) /* in: list */
{
return(list->last);
}

60
include/ut0wqueue.h Normal file
View File

@@ -0,0 +1,60 @@
/***********************************************************************
A Work queue. Threads can add work items to the queue and other threads can
wait for work items to be available and take them off the queue for
processing.
************************************************************************/
#ifndef IB_WORK_QUEUE_H
#define IB_WORK_QUEUE_H
#include "ut0list.h"
#include "mem0mem.h"
#include "os0sync.h"
#include "sync0types.h"
typedef struct ib_wqueue_struct ib_wqueue_t;
/********************************************************************
Create a new work queue. */
ib_wqueue_t*
ib_wqueue_create(void);
/*===================*/
/* out: work queue */
/********************************************************************
Free a work queue. */
void
ib_wqueue_free(
/*===========*/
ib_wqueue_t* wq); /* in: work queue */
/********************************************************************
Add a work item to the queue. */
void
ib_wqueue_add(
/*==========*/
ib_wqueue_t* wq, /* in: work queue */
void* item, /* in: work item */
mem_heap_t* heap); /* in: memory heap to use for allocating the
list node */
/********************************************************************
Wait for a work item to appear in the queue. */
void*
ib_wqueue_wait(
/* out: work item */
ib_wqueue_t* wq); /* in: work queue */
/* Work queue. */
struct ib_wqueue_struct {
mutex_t mutex; /* mutex protecting everything */
ib_list_t* items; /* work item list */
os_event_t event; /* event we use to signal additions to list */
};
#endif

View File

@@ -741,8 +741,7 @@ log_init(void)
log_sys = mem_alloc(sizeof(log_t)); log_sys = mem_alloc(sizeof(log_t));
mutex_create(&(log_sys->mutex)); mutex_create(&log_sys->mutex, SYNC_LOG);
mutex_set_level(&(log_sys->mutex), SYNC_LOG);
mutex_enter(&(log_sys->mutex)); mutex_enter(&(log_sys->mutex));
@@ -798,8 +797,7 @@ log_init(void)
log_sys->last_checkpoint_lsn = log_sys->lsn; log_sys->last_checkpoint_lsn = log_sys->lsn;
log_sys->n_pending_checkpoint_writes = 0; log_sys->n_pending_checkpoint_writes = 0;
rw_lock_create(&(log_sys->checkpoint_lock)); rw_lock_create(&log_sys->checkpoint_lock, SYNC_NO_ORDER_CHECK);
rw_lock_set_level(&(log_sys->checkpoint_lock), SYNC_NO_ORDER_CHECK);
log_sys->checkpoint_buf = ut_align( log_sys->checkpoint_buf = ut_align(
mem_alloc(2 * OS_FILE_LOG_BLOCK_SIZE), mem_alloc(2 * OS_FILE_LOG_BLOCK_SIZE),
@@ -815,8 +813,7 @@ log_init(void)
log_sys->n_pending_archive_ios = 0; log_sys->n_pending_archive_ios = 0;
rw_lock_create(&(log_sys->archive_lock)); rw_lock_create(&log_sys->archive_lock, SYNC_NO_ORDER_CHECK);
rw_lock_set_level(&(log_sys->archive_lock), SYNC_NO_ORDER_CHECK);
log_sys->archive_buf = NULL; log_sys->archive_buf = NULL;

View File

@@ -113,8 +113,7 @@ recv_sys_create(void)
recv_sys = mem_alloc(sizeof(recv_sys_t)); recv_sys = mem_alloc(sizeof(recv_sys_t));
mutex_create(&(recv_sys->mutex)); mutex_create(&recv_sys->mutex, SYNC_RECV);
mutex_set_level(&(recv_sys->mutex), SYNC_RECV);
recv_sys->heap = NULL; recv_sys->heap = NULL;
recv_sys->addr_hash = NULL; recv_sys->addr_hash = NULL;
@@ -2969,7 +2968,6 @@ recv_recovery_from_checkpoint_finish(void)
/*======================================*/ /*======================================*/
{ {
int i; int i;
os_thread_id_t recovery_thread_id;
/* Apply the hashed log records to the respective file pages */ /* Apply the hashed log records to the respective file pages */
@@ -3013,7 +3011,7 @@ recv_recovery_from_checkpoint_finish(void)
session */ session */
os_thread_create(trx_rollback_or_clean_all_without_sess, os_thread_create(trx_rollback_or_clean_all_without_sess,
(void *)&i, &recovery_thread_id); (void *)&i, NULL);
} }
} }

View File

@@ -122,8 +122,7 @@ mem_init(
/* Initialize the hash table */ /* Initialize the hash table */
ut_a(FALSE == mem_hash_initialized); ut_a(FALSE == mem_hash_initialized);
mutex_create(&mem_hash_mutex); mutex_create(&mem_hash_mutex, SYNC_MEM_HASH);
mutex_set_level(&mem_hash_mutex, SYNC_MEM_HASH);
for (i = 0; i < MEM_HASH_SIZE; i++) { for (i = 0; i < MEM_HASH_SIZE; i++) {
UT_LIST_INIT(*mem_hash_get_nth_cell(i)); UT_LIST_INIT(*mem_hash_get_nth_cell(i));

View File

@@ -107,11 +107,49 @@ char*
mem_heap_strdup( mem_heap_strdup(
/*============*/ /*============*/
/* out, own: a copy of the string */ /* out, own: a copy of the string */
mem_heap_t* heap, /* in: memory heap where string is allocated */ mem_heap_t* heap, /* in: memory heap where string is allocated */
const char* str) /* in: string to be copied */ const char* str) /* in: string to be copied */
{ {
ulint len = strlen(str) + 1; return(mem_heap_dup(heap, str, strlen(str) + 1));
return(memcpy(mem_heap_alloc(heap, len), str, len)); }
/**************************************************************************
Duplicate a block of data, allocated from a memory heap. */
void*
mem_heap_dup(
/*=========*/
/* out, own: a copy of the data */
mem_heap_t* heap, /* in: memory heap where copy is allocated */
const void* data, /* in: data to be copied */
ulint len) /* in: length of data, in bytes */
{
return(memcpy(mem_heap_alloc(heap, len), data, len));
}
/**************************************************************************
Concatenate two strings and return the result, using a memory heap. */
char*
mem_heap_strcat(
/*============*/
/* out, own: the result */
mem_heap_t* heap, /* in: memory heap where string is allocated */
const char* s1, /* in: string 1 */
const char* s2) /* in: string 2 */
{
char* s;
ulint s1_len = strlen(s1);
ulint s2_len = strlen(s2);
s = mem_heap_alloc(heap, s1_len + s2_len + 1);
memcpy(s, s1, s1_len);
memcpy(s + s1_len, s2, s2_len);
s[s1_len + s2_len] = '\0';
return(s);
} }
/******************************************************************* /*******************************************************************

View File

@@ -204,8 +204,7 @@ mem_pool_create(
pool->buf = ut_malloc_low(size, FALSE, TRUE); pool->buf = ut_malloc_low(size, FALSE, TRUE);
pool->size = size; pool->size = size;
mutex_create(&(pool->mutex)); mutex_create(&pool->mutex, SYNC_MEM_POOL);
mutex_set_level(&(pool->mutex), SYNC_MEM_POOL);
/* Initialize the free lists */ /* Initialize the free lists */

View File

@@ -1632,6 +1632,30 @@ t2 CREATE TABLE `t2` (
CONSTRAINT `t2_ibfk_2` FOREIGN KEY (`b`) REFERENCES `t1` (`id`) CONSTRAINT `t2_ibfk_2` FOREIGN KEY (`b`) REFERENCES `t1` (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1 ) ENGINE=InnoDB DEFAULT CHARSET=latin1
drop table t2, t1; drop table t2, t1;
flush status;
show status like "binlog_cache_use";
Variable_name Value
Binlog_cache_use 0
show status like "binlog_cache_disk_use";
Variable_name Value
Binlog_cache_disk_use 0
create table t1 (a int) engine=innodb;
show status like "binlog_cache_use";
Variable_name Value
Binlog_cache_use 1
show status like "binlog_cache_disk_use";
Variable_name Value
Binlog_cache_disk_use 1
begin;
delete from t1;
commit;
show status like "binlog_cache_use";
Variable_name Value
Binlog_cache_use 2
show status like "binlog_cache_disk_use";
Variable_name Value
Binlog_cache_disk_use 1
drop table t1;
create table t1 (c char(10), index (c,c)) engine=innodb; create table t1 (c char(10), index (c,c)) engine=innodb;
ERROR 42S21: Duplicate column name 'c' ERROR 42S21: Duplicate column name 'c'
create table t1 (c1 char(10), c2 char(10), index (c1,c2,c1)) engine=innodb; create table t1 (c1 char(10), c2 char(10), index (c1,c2,c1)) engine=innodb;
@@ -3125,9 +3149,7 @@ SHOW CREATE TABLE t2;
Table Create Table Table Create Table
t2 CREATE TABLE `t2` ( t2 CREATE TABLE `t2` (
`a` int(11) DEFAULT NULL, `a` int(11) DEFAULT NULL,
KEY `t2_ibfk_0` (`a`), KEY `t2_ibfk_0` (`a`)
CONSTRAINT `t2_ibfk_0` FOREIGN KEY (`a`) REFERENCES `t1` (`a`),
CONSTRAINT `t2_ibfk_1` FOREIGN KEY (`a`) REFERENCES `t1` (`a`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1 ) ENGINE=InnoDB DEFAULT CHARSET=latin1
DROP TABLE t2,t1; DROP TABLE t2,t1;
create table t1(a int not null, b int, c int, d int, primary key(a)) engine=innodb; create table t1(a int not null, b int, c int, d int, primary key(a)) engine=innodb;
@@ -3206,6 +3228,46 @@ UPDATE t1 SET field1 = 'other' WHERE field2 = 'somevalu';
ERROR 23000: Upholding foreign key constraints for table 't1', entry 'other-somevalu', key 1 would lead to a duplicate entry ERROR 23000: Upholding foreign key constraints for table 't1', entry 'other-somevalu', key 1 would lead to a duplicate entry
DROP TABLE t2; DROP TABLE t2;
DROP TABLE t1; DROP TABLE t1;
create table t1 (
c1 bigint not null,
c2 bigint not null,
primary key (c1),
unique key (c2)
) engine=innodb;
create table t2 (
c1 bigint not null,
primary key (c1)
) engine=innodb;
alter table t1 add constraint c2_fk foreign key (c2)
references t2(c1) on delete cascade;
show create table t1;
Table Create Table
t1 CREATE TABLE `t1` (
`c1` bigint(20) NOT NULL,
`c2` bigint(20) NOT NULL,
PRIMARY KEY (`c1`),
UNIQUE KEY `c2` (`c2`),
CONSTRAINT `c2_fk` FOREIGN KEY (`c2`) REFERENCES `t2` (`c1`) ON DELETE CASCADE
) ENGINE=InnoDB DEFAULT CHARSET=latin1
alter table t1 drop foreign key c2_fk;
show create table t1;
Table Create Table
t1 CREATE TABLE `t1` (
`c1` bigint(20) NOT NULL,
`c2` bigint(20) NOT NULL,
PRIMARY KEY (`c1`),
UNIQUE KEY `c2` (`c2`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1
drop table t1, t2;
create table t1(a date) engine=innodb;
create table t2(a date, key(a)) engine=innodb;
insert into t1 values('2005-10-01');
insert into t2 values('2005-10-01');
select * from t1, t2
where t2.a between t1.a - interval 2 day and t1.a + interval 2 day;
a a
2005-10-01 2005-10-01
drop table t1, t2;
create table t1 (id int not null, f_id int not null, f int not null, create table t1 (id int not null, f_id int not null, f int not null,
primary key(f_id, id)) engine=innodb; primary key(f_id, id)) engine=innodb;
create table t2 (id int not null,s_id int not null,s varchar(200), create table t2 (id int not null,s_id int not null,s varchar(200),

View File

@@ -1,3 +1,16 @@
#######################################################################
# #
# Please, DO NOT TOUCH this file as well as the innodb.result file. #
# These files are to be modified ONLY BY INNOBASE guys. #
# #
# Use innodb_mysql.[test|result] files instead. #
# #
# If nevertheless you need to make some changes here, please, forward #
# your commit message To: dev@innodb.com Cc: dev-innodb@mysql.com #
# (otherwise your changes may be erased). #
# #
#######################################################################
-- source include/have_innodb.inc -- source include/have_innodb.inc
# #
@@ -1133,6 +1146,41 @@ show create table t2;
drop table t2, t1; drop table t2, t1;
#
# Let us test binlog_cache_use and binlog_cache_disk_use status vars.
# Actually this test has nothing to do with innodb per se, it just requires
# transactional table.
#
flush status;
show status like "binlog_cache_use";
show status like "binlog_cache_disk_use";
create table t1 (a int) engine=innodb;
# Now we are going to create transaction which is long enough so its
# transaction binlog will be flushed to disk...
let $1=2000;
disable_query_log;
begin;
while ($1)
{
eval insert into t1 values( $1 );
dec $1;
}
commit;
enable_query_log;
show status like "binlog_cache_use";
show status like "binlog_cache_disk_use";
# Transaction which should not be flushed to disk and so should not
# increase binlog_cache_disk_use.
begin;
delete from t1;
commit;
show status like "binlog_cache_use";
show status like "binlog_cache_disk_use";
drop table t1;
# #
# Bug #6126: Duplicate columns in keys gives misleading error message # Bug #6126: Duplicate columns in keys gives misleading error message
# #
@@ -2106,6 +2154,42 @@ UPDATE t1 SET field1 = 'other' WHERE field2 = 'somevalu';
DROP TABLE t2; DROP TABLE t2;
DROP TABLE t1; DROP TABLE t1;
#
# Bug#18477 - MySQL/InnoDB Ignoring Foreign Keys in ALTER TABLE
#
create table t1 (
c1 bigint not null,
c2 bigint not null,
primary key (c1),
unique key (c2)
) engine=innodb;
#
create table t2 (
c1 bigint not null,
primary key (c1)
) engine=innodb;
#
alter table t1 add constraint c2_fk foreign key (c2)
references t2(c1) on delete cascade;
show create table t1;
#
alter table t1 drop foreign key c2_fk;
show create table t1;
#
drop table t1, t2;
#
# Bug #14360: problem with intervals
#
create table t1(a date) engine=innodb;
create table t2(a date, key(a)) engine=innodb;
insert into t1 values('2005-10-01');
insert into t2 values('2005-10-01');
select * from t1, t2
where t2.a between t1.a - interval 2 day and t1.a + interval 2 day;
drop table t1, t2;
create table t1 (id int not null, f_id int not null, f int not null, create table t1 (id int not null, f_id int not null, f int not null,
primary key(f_id, id)) engine=innodb; primary key(f_id, id)) engine=innodb;
create table t2 (id int not null,s_id int not null,s varchar(200), create table t2 (id int not null,s_id int not null,s varchar(200),

View File

@@ -0,0 +1 @@
drop table if exists t1;

View File

@@ -0,0 +1,5 @@
-- source include/have_innodb.inc
--disable_warnings
drop table if exists t1;
--enable_warnings

View File

@@ -3679,6 +3679,37 @@ os_aio_posix_handle(
} }
#endif #endif
/**************************************************************************
Do a 'last millisecond' check that the end of an uncompressed page is sensible;
reported page checksum errors from Linux seem to wipe over the page end. */
static
void
os_file_check_page_trailers(
/*========================*/
byte* combined_buf, /* in: combined write buffer */
ulint total_len) /* in: size of combined_buf, in bytes
(a multiple of UNIV_PAGE_SIZE) */
{
ulint len;
for (len = 0; len + UNIV_PAGE_SIZE <= total_len;
len += UNIV_PAGE_SIZE) {
byte* buf = combined_buf + len;
if (memcmp(buf + (FIL_PAGE_LSN + 4), buf + (UNIV_PAGE_SIZE
- FIL_PAGE_END_LSN_OLD_CHKSUM + 4), 4)) {
ut_print_timestamp(stderr);
fprintf(stderr,
" InnoDB: ERROR: The page to be written seems corrupt!\n"
"InnoDB: Writing a block of %lu bytes, currently at offset %lu\n",
(ulong)total_len, (ulong)len);
buf_page_print(buf, 0);
fprintf(stderr,
"InnoDB: ERROR: The page to be written seems corrupt!\n");
}
}
}
/************************************************************************** /**************************************************************************
Does simulated aio. This function should be called by an i/o-handler Does simulated aio. This function should be called by an i/o-handler
thread. */ thread. */
@@ -3716,7 +3747,6 @@ os_aio_simulated_handle(
ibool ret; ibool ret;
ulint n; ulint n;
ulint i; ulint i;
ulint len2;
segment = os_aio_get_array_and_local_segment(&array, global_segment); segment = os_aio_get_array_and_local_segment(&array, global_segment);
@@ -3924,34 +3954,15 @@ consecutive_loop:
ut_error; ut_error;
} }
/* Do a 'last millisecond' check that the page end os_file_check_page_trailers(combined_buf, total_len);
is sensible; reported page checksum errors from
Linux seem to wipe over the page end */
/* TODO: disable this for compressed pages */
for (len2 = 0; len2 + UNIV_PAGE_SIZE <= total_len;
len2 += UNIV_PAGE_SIZE) {
if (mach_read_from_4(combined_buf + len2
+ FIL_PAGE_LSN + 4)
!= mach_read_from_4(combined_buf + len2
+ UNIV_PAGE_SIZE
- FIL_PAGE_END_LSN_OLD_CHKSUM + 4)) {
ut_print_timestamp(stderr);
fprintf(stderr,
" InnoDB: ERROR: The page to be written seems corrupt!\n");
fprintf(stderr,
"InnoDB: Writing a block of %lu bytes, currently writing at offset %lu\n",
(ulong)total_len, (ulong)len2);
buf_page_print(combined_buf + len2, 0);
fprintf(stderr,
"InnoDB: ERROR: The page to be written seems corrupt!\n");
}
}
} }
ret = os_file_write(slot->name, slot->file, combined_buf, ret = os_file_write(slot->name, slot->file, combined_buf,
slot->offset, slot->offset_high, total_len); slot->offset, slot->offset_high, total_len);
if (array == os_aio_write_array) {
os_file_check_page_trailers(combined_buf, total_len);
}
} else { } else {
ret = os_file_read(slot->file, combined_buf, ret = os_file_read(slot->file, combined_buf,
slot->offset, slot->offset_high, total_len); slot->offset, slot->offset_high, total_len);

View File

@@ -96,7 +96,7 @@ os_thread_create(
void* arg, /* in: argument to start void* arg, /* in: argument to start
function */ function */
os_thread_id_t* thread_id) /* out: id of the created os_thread_id_t* thread_id) /* out: id of the created
thread */ thread, or NULL */
{ {
#ifdef __WIN__ #ifdef __WIN__
os_thread_t thread; os_thread_t thread;
@@ -122,7 +122,9 @@ os_thread_create(
ut_a(SetThreadPriority(thread, srv_query_thread_priority)); ut_a(SetThreadPriority(thread, srv_query_thread_priority));
} }
*thread_id = win_thread_id; if (thread_id) {
*thread_id = win_thread_id;
}
return(thread); return(thread);
#else #else
@@ -180,7 +182,9 @@ os_thread_create(
my_pthread_setprio(pthread, srv_query_thread_priority); my_pthread_setprio(pthread, srv_query_thread_priority);
} }
*thread_id = pthread; if (thread_id) {
*thread_id = pthread;
}
return(pthread); return(pthread);
#endif #endif
@@ -216,7 +220,7 @@ os_thread_join(
/*===========*/ /*===========*/
os_thread_id_t thread_id) /* in: id of the thread to join */ os_thread_id_t thread_id) /* in: id of the thread to join */
{ {
return pthread_join(thread_id, NULL); return(pthread_join(thread_id, NULL));
} }
#endif #endif
/********************************************************************* /*********************************************************************

File diff suppressed because it is too large Load Diff

View File

@@ -84,6 +84,7 @@ string_append(
DIGIT [0-9] DIGIT [0-9]
ID [a-z_A-Z][a-z_A-Z0-9]* ID [a-z_A-Z][a-z_A-Z0-9]*
BOUND_LIT \:[a-z_A-Z0-9]+ BOUND_LIT \:[a-z_A-Z0-9]+
BOUND_ID \$[a-z_A-Z0-9]+
%x comment %x comment
%x quoted %x quoted
@@ -111,6 +112,13 @@ BOUND_LIT \:[a-z_A-Z0-9]+
return(type); return(type);
} }
{BOUND_ID} {
yylval = sym_tab_add_bound_id(pars_sym_tab_global,
yytext + 1);
return(PARS_ID_TOKEN);
}
"'" { "'" {
/* Quoted character string literals are handled in an explicit /* Quoted character string literals are handled in an explicit
start state 'quoted'. This state is entered and the buffer for start state 'quoted'. This state is entered and the buffer for

View File

@@ -1931,6 +1931,7 @@ pars_info_create(void)
info->heap = heap; info->heap = heap;
info->funcs = NULL; info->funcs = NULL;
info->bound_lits = NULL; info->bound_lits = NULL;
info->bound_ids = NULL;
info->graph_owns_us = TRUE; info->graph_owns_us = TRUE;
return(info); return(info);
@@ -1963,6 +1964,8 @@ pars_info_add_literal(
{ {
pars_bound_lit_t* pbl; pars_bound_lit_t* pbl;
ut_ad(!pars_info_get_bound_lit(info, name));
pbl = mem_heap_alloc(info->heap, sizeof(*pbl)); pbl = mem_heap_alloc(info->heap, sizeof(*pbl));
pbl->name = name; pbl->name = name;
@@ -2053,6 +2056,8 @@ pars_info_add_function(
{ {
pars_user_func_t* puf; pars_user_func_t* puf;
ut_ad(!pars_info_get_user_func(info, name));
puf = mem_heap_alloc(info->heap, sizeof(*puf)); puf = mem_heap_alloc(info->heap, sizeof(*puf));
puf->name = name; puf->name = name;
@@ -2066,6 +2071,32 @@ pars_info_add_function(
ib_vector_push(info->funcs, puf); ib_vector_push(info->funcs, puf);
} }
/********************************************************************
Add bound id. */
void
pars_info_add_id(
/*=============*/
pars_info_t* info, /* in: info struct */
const char* name, /* in: name */
const char* id) /* in: id */
{
pars_bound_id_t* bid;
ut_ad(!pars_info_get_bound_id(info, name));
bid = mem_heap_alloc(info->heap, sizeof(*bid));
bid->name = name;
bid->id = id;
if (!info->bound_ids) {
info->bound_ids = ib_vector_create(info->heap, 8);
}
ib_vector_push(info->bound_ids, bid);
}
/******************************************************************** /********************************************************************
Get user function with the given name.*/ Get user function with the given name.*/
@@ -2127,3 +2158,34 @@ pars_info_get_bound_lit(
return(NULL); return(NULL);
} }
/********************************************************************
Get bound id with the given name.*/
pars_bound_id_t*
pars_info_get_bound_id(
/*===================*/
/* out: bound id, or NULL if not
found */
pars_info_t* info, /* in: info struct */
const char* name) /* in: bound id name to find */
{
ulint i;
ib_vector_t* vec;
if (!info || !info->bound_ids) {
return(NULL);
}
vec = info->bound_ids;
for (i = 0; i < ib_vector_size(vec); i++) {
pars_bound_id_t* bid = ib_vector_get(vec, i);
if (strcmp(bid->name, name) == 0) {
return(bid);
}
}
return(NULL);
}

View File

@@ -304,3 +304,42 @@ sym_tab_add_id(
return(node); return(node);
} }
/**********************************************************************
Add a bound identifier to a symbol table. */
sym_node_t*
sym_tab_add_bound_id(
/*===========*/
/* out: symbol table node */
sym_tab_t* sym_tab, /* in: symbol table */
const char* name) /* in: name of bound id */
{
sym_node_t* node;
pars_bound_id_t* bid;
bid = pars_info_get_bound_id(sym_tab->info, name);
ut_a(bid);
node = mem_heap_alloc(sym_tab->heap, sizeof(sym_node_t));
node->common.type = QUE_NODE_SYMBOL;
node->resolved = FALSE;
node->indirection = NULL;
node->name = mem_heap_strdup(sym_tab->heap, bid->id);
node->name_len = strlen(node->name);
UT_LIST_ADD_LAST(sym_list, sym_tab->sym_list, node);
dfield_set_data(&(node->common.val), NULL, UNIV_SQL_NULL);
node->common.val_buf_size = 0;
node->prefetch_buf = NULL;
node->cursor_def = NULL;
node->sym_table = sym_tab;
return(node);
}

View File

@@ -1340,14 +1340,6 @@ loop:
next_thr = que_thr_step(thr); next_thr = que_thr_step(thr);
/*-------------------------*/ /*-------------------------*/
/* Test the effect on performance of adding extra mutex
reservations */
/* if (srv_test_extra_mutexes) {
mutex_enter(&kernel_mutex);
mutex_exit(&kernel_mutex);
}
*/
loop_count++; loop_count++;
if (next_thr != thr) { if (next_thr != thr) {

View File

@@ -1519,8 +1519,7 @@ row_ins_check_foreign_constraints(
if (foreign->foreign_index == index) { if (foreign->foreign_index == index) {
if (foreign->referenced_table == NULL) { if (foreign->referenced_table == NULL) {
dict_table_get(foreign->referenced_table_name, dict_table_get(foreign->referenced_table_name);
trx);
} }
if (0 == trx->dict_operation_lock_mode) { if (0 == trx->dict_operation_lock_mode) {

View File

@@ -2384,11 +2384,9 @@ row_discard_tablespace_for_mysql(
dict_foreign_t* foreign; dict_foreign_t* foreign;
dulint new_id; dulint new_id;
dict_table_t* table; dict_table_t* table;
que_thr_t* thr;
que_t* graph = NULL;
ibool success; ibool success;
ulint err; ulint err;
char* buf; pars_info_t* info = NULL;
/* How do we prevent crashes caused by ongoing operations on the table? Old /* How do we prevent crashes caused by ongoing operations on the table? Old
operations could try to access non-existent pages. operations could try to access non-existent pages.
@@ -2410,36 +2408,6 @@ discard ongoing operations.
5) FOREIGN KEY operations: if table->n_foreign_key_checks_running > 0, we 5) FOREIGN KEY operations: if table->n_foreign_key_checks_running > 0, we
do not allow the discard. We also reserve the data dictionary latch. */ do not allow the discard. We also reserve the data dictionary latch. */
static const char discard_tablespace_proc1[] =
"PROCEDURE DISCARD_TABLESPACE_PROC () IS\n"
"old_id CHAR;\n"
"new_id CHAR;\n"
"new_id_low INT;\n"
"new_id_high INT;\n"
"table_name CHAR;\n"
"BEGIN\n"
"table_name := '";
static const char discard_tablespace_proc2[] =
"';\n"
"new_id_high := %lu;\n"
"new_id_low := %lu;\n"
"new_id := CONCAT(TO_BINARY(new_id_high, 4), TO_BINARY(new_id_low, 4));\n"
"SELECT ID INTO old_id\n"
"FROM SYS_TABLES\n"
"WHERE NAME = table_name;\n"
"IF (SQL %% NOTFOUND) THEN\n"
" COMMIT WORK;\n"
" RETURN;\n"
"END IF;\n"
"UPDATE SYS_TABLES SET ID = new_id\n"
"WHERE ID = old_id;\n"
"UPDATE SYS_COLUMNS SET TABLE_ID = new_id\n"
"WHERE TABLE_ID = old_id;\n"
"UPDATE SYS_INDEXES SET TABLE_ID = new_id\n"
"WHERE TABLE_ID = old_id;\n"
"COMMIT WORK;\n"
"END;\n";
ut_ad(trx->mysql_thread_id == os_thread_get_curr_id()); ut_ad(trx->mysql_thread_id == os_thread_get_curr_id());
trx->op_info = "discarding tablespace"; trx->op_info = "discarding tablespace";
@@ -2519,35 +2487,34 @@ do not allow the discard. We also reserve the data dictionary latch. */
new_id = dict_hdr_get_new_id(DICT_HDR_TABLE_ID); new_id = dict_hdr_get_new_id(DICT_HDR_TABLE_ID);
buf = mem_alloc((sizeof discard_tablespace_proc1) +
(sizeof discard_tablespace_proc2) +
20 + ut_strlenq(name, '\''));
memcpy(buf, discard_tablespace_proc1, sizeof discard_tablespace_proc1);
sprintf(ut_strcpyq(buf + (sizeof discard_tablespace_proc1 - 1),
'\'', name),
discard_tablespace_proc2,
(ulong) ut_dulint_get_high(new_id),
(ulong) ut_dulint_get_low(new_id));
graph = pars_sql(NULL, buf);
ut_a(graph);
/* Remove any locks there are on the table or its records */ /* Remove any locks there are on the table or its records */
lock_reset_all_on_table(table); lock_reset_all_on_table(table);
graph->trx = trx; info = pars_info_create();
trx->graph = NULL;
graph->fork_type = QUE_FORK_MYSQL_INTERFACE; pars_info_add_str_literal(info, "table_name", name);
pars_info_add_dulint_literal(info, "new_id", new_id);
ut_a(thr = que_fork_start_command(graph)); err = que_eval_sql(info,
"PROCEDURE DISCARD_TABLESPACE_PROC () IS\n"
que_run_threads(thr); "old_id CHAR;\n"
"BEGIN\n"
err = trx->error_state; "SELECT ID INTO old_id\n"
"FROM SYS_TABLES\n"
"WHERE NAME = :table_name;\n"
"IF (SQL % NOTFOUND) THEN\n"
" COMMIT WORK;\n"
" RETURN;\n"
"END IF;\n"
"UPDATE SYS_TABLES SET ID = :new_id\n"
" WHERE ID = old_id;\n"
"UPDATE SYS_COLUMNS SET TABLE_ID = :new_id\n"
" WHERE TABLE_ID = old_id;\n"
"UPDATE SYS_INDEXES SET TABLE_ID = :new_id\n"
" WHERE TABLE_ID = old_id;\n"
"COMMIT WORK;\n"
"END;\n"
, trx);
if (err != DB_SUCCESS) { if (err != DB_SUCCESS) {
trx->error_state = DB_SUCCESS; trx->error_state = DB_SUCCESS;
@@ -2571,13 +2538,10 @@ do not allow the discard. We also reserve the data dictionary latch. */
table->ibd_file_missing = TRUE; table->ibd_file_missing = TRUE;
} }
} }
funct_exit: funct_exit:
row_mysql_unlock_data_dictionary(trx); row_mysql_unlock_data_dictionary(trx);
if (graph) {
que_graph_free(graph);
}
trx_commit_for_mysql(trx); trx_commit_for_mysql(trx);
trx->op_info = ""; trx->op_info = "";
@@ -2738,9 +2702,7 @@ row_truncate_table_for_mysql(
btr_pcur_t pcur; btr_pcur_t pcur;
mtr_t mtr; mtr_t mtr;
dulint new_id; dulint new_id;
char* sql; pars_info_t* info = NULL;
que_thr_t* thr;
que_t* graph = NULL;
/* How do we prevent crashes caused by ongoing operations on the table? Old /* How do we prevent crashes caused by ongoing operations on the table? Old
operations could try to access non-existent pages. operations could try to access non-existent pages.
@@ -2768,30 +2730,6 @@ by DISCARD TABLESPACE.)
5) FOREIGN KEY operations: if table->n_foreign_key_checks_running > 0, we 5) FOREIGN KEY operations: if table->n_foreign_key_checks_running > 0, we
do not allow the TRUNCATE. We also reserve the data dictionary latch. */ do not allow the TRUNCATE. We also reserve the data dictionary latch. */
static const char renumber_tablespace_proc[] =
"PROCEDURE RENUMBER_TABLESPACE_PROC () IS\n"
"old_id CHAR;\n"
"new_id CHAR;\n"
"old_id_low INT;\n"
"old_id_high INT;\n"
"new_id_low INT;\n"
"new_id_high INT;\n"
"BEGIN\n"
"old_id_high := %lu;\n"
"old_id_low := %lu;\n"
"new_id_high := %lu;\n"
"new_id_low := %lu;\n"
"old_id := CONCAT(TO_BINARY(old_id_high, 4), TO_BINARY(old_id_low, 4));\n"
"new_id := CONCAT(TO_BINARY(new_id_high, 4), TO_BINARY(new_id_low, 4));\n"
"UPDATE SYS_TABLES SET ID = new_id\n"
"WHERE ID = old_id;\n"
"UPDATE SYS_COLUMNS SET TABLE_ID = new_id\n"
"WHERE TABLE_ID = old_id;\n"
"UPDATE SYS_INDEXES SET TABLE_ID = new_id\n"
"WHERE TABLE_ID = old_id;\n"
"COMMIT WORK;\n"
"END;\n";
ut_ad(trx->mysql_thread_id == os_thread_get_curr_id()); ut_ad(trx->mysql_thread_id == os_thread_get_curr_id());
ut_ad(table); ut_ad(table);
@@ -2952,35 +2890,27 @@ do not allow the TRUNCATE. We also reserve the data dictionary latch. */
btr_pcur_close(&pcur); btr_pcur_close(&pcur);
mtr_commit(&mtr); mtr_commit(&mtr);
new_id = dict_hdr_get_new_id(DICT_HDR_TABLE_ID);
mem_heap_empty(heap);
sql = mem_heap_alloc(heap, (sizeof renumber_tablespace_proc) + 40);
sprintf(sql, renumber_tablespace_proc,
(ulong) ut_dulint_get_high(table->id),
(ulong) ut_dulint_get_low(table->id),
(ulong) ut_dulint_get_high(new_id),
(ulong) ut_dulint_get_low(new_id));
graph = pars_sql(NULL, sql);
ut_a(graph);
mem_heap_free(heap); mem_heap_free(heap);
graph->trx = trx; new_id = dict_hdr_get_new_id(DICT_HDR_TABLE_ID);
trx->graph = NULL;
graph->fork_type = QUE_FORK_MYSQL_INTERFACE; info = pars_info_create();
thr = que_fork_start_command(graph); pars_info_add_dulint_literal(info, "old_id", table->id);
ut_a(thr); pars_info_add_dulint_literal(info, "new_id", new_id);
que_run_threads(thr); err = que_eval_sql(info,
"PROCEDURE RENUMBER_TABLESPACE_PROC () IS\n"
que_graph_free(graph); "BEGIN\n"
"UPDATE SYS_TABLES SET ID = :new_id\n"
err = trx->error_state; " WHERE ID = :old_id;\n"
"UPDATE SYS_COLUMNS SET TABLE_ID = :new_id\n"
" WHERE TABLE_ID = :old_id;\n"
"UPDATE SYS_INDEXES SET TABLE_ID = :new_id\n"
" WHERE TABLE_ID = :old_id;\n"
"COMMIT WORK;\n"
"END;\n"
, trx);
if (err != DB_SUCCESS) { if (err != DB_SUCCESS) {
trx->error_state = DB_SUCCESS; trx->error_state = DB_SUCCESS;
@@ -3030,83 +2960,13 @@ row_drop_table_for_mysql(
dict_foreign_t* foreign; dict_foreign_t* foreign;
dict_table_t* table; dict_table_t* table;
ulint space_id; ulint space_id;
que_thr_t* thr;
que_t* graph;
ulint err; ulint err;
const char* table_name; const char* table_name;
ulint namelen; ulint namelen;
char* dir_path_of_temp_table = NULL; char* dir_path_of_temp_table = NULL;
ibool success; ibool success;
ibool locked_dictionary = FALSE; ibool locked_dictionary = FALSE;
char* quoted_name; pars_info_t* info = NULL;
char* sql;
/* We use the private SQL parser of Innobase to generate the
query graphs needed in deleting the dictionary data from system
tables in Innobase. Deleting a row from SYS_INDEXES table also
frees the file segments of the B-tree associated with the index. */
static const char str1[] =
"PROCEDURE DROP_TABLE_PROC () IS\n"
"table_name CHAR;\n"
"sys_foreign_id CHAR;\n"
"table_id CHAR;\n"
"index_id CHAR;\n"
"foreign_id CHAR;\n"
"found INT;\n"
"BEGIN\n"
"table_name := ";
static const char str2[] =
";\n"
"SELECT ID INTO table_id\n"
"FROM SYS_TABLES\n"
"WHERE NAME = table_name;\n"
"IF (SQL % NOTFOUND) THEN\n"
" COMMIT WORK;\n"
" RETURN;\n"
"END IF;\n"
"found := 1;\n"
"SELECT ID INTO sys_foreign_id\n"
"FROM SYS_TABLES\n"
"WHERE NAME = 'SYS_FOREIGN';\n"
"IF (SQL % NOTFOUND) THEN\n"
" found := 0;\n"
"END IF;\n"
"IF (table_name = 'SYS_FOREIGN') THEN\n"
" found := 0;\n"
"END IF;\n"
"IF (table_name = 'SYS_FOREIGN_COLS') THEN\n"
" found := 0;\n"
"END IF;\n"
"WHILE found = 1 LOOP\n"
" SELECT ID INTO foreign_id\n"
" FROM SYS_FOREIGN\n"
" WHERE FOR_NAME = table_name\n"
" AND TO_BINARY(FOR_NAME) = TO_BINARY(table_name);\n"
" IF (SQL % NOTFOUND) THEN\n"
" found := 0;\n"
" ELSE"
" DELETE FROM SYS_FOREIGN_COLS WHERE ID = foreign_id;\n"
" DELETE FROM SYS_FOREIGN WHERE ID = foreign_id;\n"
" END IF;\n"
"END LOOP;\n"
"found := 1;\n"
"WHILE found = 1 LOOP\n"
" SELECT ID INTO index_id\n"
" FROM SYS_INDEXES\n"
" WHERE TABLE_ID = table_id;\n"
" IF (SQL % NOTFOUND) THEN\n"
" found := 0;\n"
" ELSE"
" DELETE FROM SYS_FIELDS WHERE INDEX_ID = index_id;\n"
" DELETE FROM SYS_INDEXES WHERE ID = index_id\n"
" AND TABLE_ID = table_id;\n"
" END IF;\n"
"END LOOP;\n"
"DELETE FROM SYS_COLUMNS WHERE TABLE_ID = table_id;\n"
"DELETE FROM SYS_TABLES WHERE ID = table_id;\n"
"COMMIT WORK;\n"
"END;\n";
ut_a(name != NULL); ut_a(name != NULL);
@@ -3161,14 +3021,6 @@ row_drop_table_for_mysql(
srv_print_innodb_table_monitor = FALSE; srv_print_innodb_table_monitor = FALSE;
} }
quoted_name = mem_strdupq(name, '\'');
namelen = strlen(quoted_name);
sql = mem_alloc((sizeof str1) + (sizeof str2) - 2 + 1 + namelen);
memcpy(sql, str1, (sizeof str1) - 1);
memcpy(sql + (sizeof str1) - 1, quoted_name, namelen);
memcpy(sql + (sizeof str1) - 1 + namelen, str2, sizeof str2);
mem_free(quoted_name);
/* Serialize data dictionary operations with dictionary mutex: /* Serialize data dictionary operations with dictionary mutex:
no deadlocks can occur then in these operations */ no deadlocks can occur then in these operations */
@@ -3186,16 +3038,6 @@ row_drop_table_for_mysql(
ut_ad(rw_lock_own(&dict_operation_lock, RW_LOCK_EX)); ut_ad(rw_lock_own(&dict_operation_lock, RW_LOCK_EX));
#endif /* UNIV_SYNC_DEBUG */ #endif /* UNIV_SYNC_DEBUG */
graph = pars_sql(NULL, sql);
ut_a(graph);
mem_free(sql);
graph->trx = trx;
trx->graph = NULL;
graph->fork_type = QUE_FORK_MYSQL_INTERFACE;
table = dict_table_get_low(name); table = dict_table_get_low(name);
if (!table) { if (!table) {
@@ -3319,18 +3161,80 @@ fputs(" InnoDB: You are trying to drop table ", stderr);
trx->dict_operation = TRUE; trx->dict_operation = TRUE;
trx->table_id = table->id; trx->table_id = table->id;
ut_a(thr = que_fork_start_command(graph)); /* We use the private SQL parser of Innobase to generate the
query graphs needed in deleting the dictionary data from system
tables in Innobase. Deleting a row from SYS_INDEXES table also
frees the file segments of the B-tree associated with the index. */
que_run_threads(thr); info = pars_info_create();
err = trx->error_state; pars_info_add_str_literal(info, "table_name", name);
err = que_eval_sql(info,
"PROCEDURE DROP_TABLE_PROC () IS\n"
"sys_foreign_id CHAR;\n"
"table_id CHAR;\n"
"index_id CHAR;\n"
"foreign_id CHAR;\n"
"found INT;\n"
"BEGIN\n"
"SELECT ID INTO table_id\n"
"FROM SYS_TABLES\n"
"WHERE NAME = :table_name;\n"
"IF (SQL % NOTFOUND) THEN\n"
" COMMIT WORK;\n"
" RETURN;\n"
"END IF;\n"
"found := 1;\n"
"SELECT ID INTO sys_foreign_id\n"
"FROM SYS_TABLES\n"
"WHERE NAME = 'SYS_FOREIGN';\n"
"IF (SQL % NOTFOUND) THEN\n"
" found := 0;\n"
"END IF;\n"
"IF (:table_name = 'SYS_FOREIGN') THEN\n"
" found := 0;\n"
"END IF;\n"
"IF (:table_name = 'SYS_FOREIGN_COLS') THEN\n"
" found := 0;\n"
"END IF;\n"
"WHILE found = 1 LOOP\n"
" SELECT ID INTO foreign_id\n"
" FROM SYS_FOREIGN\n"
" WHERE FOR_NAME = :table_name\n"
" AND TO_BINARY(FOR_NAME) = TO_BINARY(:table_name);\n"
" IF (SQL % NOTFOUND) THEN\n"
" found := 0;\n"
" ELSE"
" DELETE FROM SYS_FOREIGN_COLS WHERE ID = foreign_id;\n"
" DELETE FROM SYS_FOREIGN WHERE ID = foreign_id;\n"
" END IF;\n"
"END LOOP;\n"
"found := 1;\n"
"WHILE found = 1 LOOP\n"
" SELECT ID INTO index_id\n"
" FROM SYS_INDEXES\n"
" WHERE TABLE_ID = table_id;\n"
" IF (SQL % NOTFOUND) THEN\n"
" found := 0;\n"
" ELSE"
" DELETE FROM SYS_FIELDS WHERE INDEX_ID = index_id;\n"
" DELETE FROM SYS_INDEXES WHERE ID = index_id\n"
" AND TABLE_ID = table_id;\n"
" END IF;\n"
"END LOOP;\n"
"DELETE FROM SYS_COLUMNS WHERE TABLE_ID = table_id;\n"
"DELETE FROM SYS_TABLES WHERE ID = table_id;\n"
"COMMIT WORK;\n"
"END;\n"
, trx);
if (err != DB_SUCCESS) { if (err != DB_SUCCESS) {
ut_a(err == DB_OUT_OF_FILE_SPACE); ut_a(err == DB_OUT_OF_FILE_SPACE);
err = DB_MUST_GET_MORE_FILE_SPACE; err = DB_MUST_GET_MORE_FILE_SPACE;
row_mysql_handle_errors(&err, trx, thr, NULL); row_mysql_handle_errors(&err, trx, NULL, NULL);
ut_error; ut_error;
} else { } else {
@@ -3408,8 +3312,6 @@ funct_exit:
mem_free(dir_path_of_temp_table); mem_free(dir_path_of_temp_table);
} }
que_graph_free(graph);
trx_commit_for_mysql(trx); trx_commit_for_mysql(trx);
trx->op_info = ""; trx->op_info = "";
@@ -3514,6 +3416,62 @@ row_is_mysql_tmp_table_name(
return(strstr(name, "/@0023sql") != NULL); return(strstr(name, "/@0023sql") != NULL);
} }
/********************************************************************
Delete a single constraint. */
static
int
row_delete_constraint_low(
/*======================*/
/* out: error code or DB_SUCCESS */
const char* id, /* in: constraint id */
trx_t* trx) /* in: transaction handle */
{
pars_info_t* info = pars_info_create();
pars_info_add_str_literal(info, "id", id);
return(que_eval_sql(info,
"PROCEDURE DELETE_CONSTRAINT () IS\n"
"BEGIN\n"
"DELETE FROM SYS_FOREIGN_COLS WHERE ID = :id;\n"
"DELETE FROM SYS_FOREIGN WHERE ID = :id;\n"
"END;\n"
, trx));
}
/********************************************************************
Delete a single constraint. */
static
int
row_delete_constraint(
/*==================*/
/* out: error code or DB_SUCCESS */
const char* id, /* in: constraint id */
const char* database_name, /* in: database name, with the
trailing '/' */
mem_heap_t* heap, /* in: memory heap */
trx_t* trx) /* in: transaction handle */
{
ulint err;
/* New format constraints have ids <databasename>/<constraintname>. */
err = row_delete_constraint_low(
mem_heap_strcat(heap, database_name, id), trx);
if ((err == DB_SUCCESS) && !strchr(id, '/')) {
/* Old format < 4.0.18 constraints have constraint ids
<number>_<number>. We only try deleting them if the
constraint name does not contain a '/' character, otherwise
deleting a new format constraint named 'foo/bar' from
database 'baz' would remove constraint 'bar' from database
'foo', if it existed. */
err = row_delete_constraint_low(id, trx);
}
return(err);
}
/************************************************************************* /*************************************************************************
Renames a table for MySQL. */ Renames a table for MySQL. */
@@ -3526,100 +3484,13 @@ row_rename_table_for_mysql(
trx_t* trx) /* in: transaction handle */ trx_t* trx) /* in: transaction handle */
{ {
dict_table_t* table; dict_table_t* table;
que_thr_t* thr;
que_t* graph = NULL;
ulint err; ulint err;
/* We use the private SQL parser of Innobase to generate the
query graphs needed in deleting the dictionary data from system
tables in Innobase. Deleting a row from SYS_INDEXES table also
frees the file segments of the B-tree associated with the index. */
static const char str1[] =
"PROCEDURE RENAME_TABLE_PROC () IS\n"
"new_table_name CHAR;\n"
"old_table_name CHAR;\n"
"gen_constr_prefix CHAR;\n"
"new_db_name CHAR;\n"
"foreign_id CHAR;\n"
"new_foreign_id CHAR;\n"
"old_db_name_len INT;\n"
"old_t_name_len INT;\n"
"new_db_name_len INT;\n"
"id_len INT;\n"
"found INT;\n"
"BEGIN\n"
"new_table_name := '";
static const char str2[] =
"';\nold_table_name := '";
static const char str3[] =
"';\n"
"UPDATE SYS_TABLES SET NAME = new_table_name\n"
"WHERE NAME = old_table_name;\n";
static const char str4a1[] = /* drop some constraints of tmp tables */
"DELETE FROM SYS_FOREIGN_COLS WHERE ID = '";
static const char str4a2[] = "';\n"
"DELETE FROM SYS_FOREIGN WHERE ID = '";
static const char str4a3[] = "';\n";
static const char str4b[] = /* rename all constraints */
"found := 1;\n"
"old_db_name_len := INSTR(old_table_name, '/') - 1;\n"
"new_db_name_len := INSTR(new_table_name, '/') - 1;\n"
"new_db_name := SUBSTR(new_table_name, 0, new_db_name_len);\n"
"old_t_name_len := LENGTH(old_table_name);\n"
"gen_constr_prefix := CONCAT(old_table_name, '_ibfk_');\n"
"WHILE found = 1 LOOP\n"
" SELECT ID INTO foreign_id\n"
" FROM SYS_FOREIGN\n"
" WHERE FOR_NAME = old_table_name\n"
" AND TO_BINARY(FOR_NAME) = TO_BINARY(old_table_name);\n"
" IF (SQL % NOTFOUND) THEN\n"
" found := 0;\n"
" ELSE\n"
" UPDATE SYS_FOREIGN\n"
" SET FOR_NAME = new_table_name\n"
" WHERE ID = foreign_id;\n"
" id_len := LENGTH(foreign_id);\n"
" IF (INSTR(foreign_id, '/') > 0) THEN\n"
" IF (INSTR(foreign_id,\n"
" gen_constr_prefix) > 0)\n"
" THEN\n"
" new_foreign_id :=\n"
" CONCAT(new_table_name,\n"
" SUBSTR(foreign_id, old_t_name_len,\n"
" id_len - old_t_name_len));\n"
" ELSE\n"
" new_foreign_id :=\n"
" CONCAT(new_db_name,\n"
" SUBSTR(foreign_id,\n"
" old_db_name_len,\n"
" id_len - old_db_name_len));\n"
" END IF;\n"
" UPDATE SYS_FOREIGN\n"
" SET ID = new_foreign_id\n"
" WHERE ID = foreign_id;\n"
" UPDATE SYS_FOREIGN_COLS\n"
" SET ID = new_foreign_id\n"
" WHERE ID = foreign_id;\n"
" END IF;\n"
" END IF;\n"
"END LOOP;\n"
"UPDATE SYS_FOREIGN SET REF_NAME = new_table_name\n"
"WHERE REF_NAME = old_table_name\n"
" AND TO_BINARY(REF_NAME) = TO_BINARY(old_table_name);\n";
static const char str5[] =
"END;\n";
mem_heap_t* heap = NULL; mem_heap_t* heap = NULL;
const char** constraints_to_drop = NULL; const char** constraints_to_drop = NULL;
ulint n_constraints_to_drop = 0; ulint n_constraints_to_drop = 0;
ibool recovering_temp_table = FALSE; ibool recovering_temp_table = FALSE;
ibool old_is_tmp, new_is_tmp; ibool old_is_tmp, new_is_tmp;
ulint len; pars_info_t* info = NULL;
ulint i;
ibool success;
/* length of database name; 0 if not renaming to a temporary table */
ulint db_name_len;
char* sql;
char* sqlend;
ut_ad(trx->mysql_thread_id == os_thread_get_curr_id()); ut_ad(trx->mysql_thread_id == os_thread_get_curr_id());
ut_a(old_name != NULL); ut_a(old_name != NULL);
@@ -3697,13 +3568,7 @@ row_rename_table_for_mysql(
goto funct_exit; goto funct_exit;
} }
/* calculate the length of the SQL string */
len = (sizeof str1) + (sizeof str2) + (sizeof str3) + (sizeof str5) - 4
+ ut_strlenq(new_name, '\'') + ut_strlenq(old_name, '\'');
if (new_is_tmp) { if (new_is_tmp) {
db_name_len = dict_get_db_name_len(old_name) + 1;
/* MySQL is doing an ALTER TABLE command and it renames the /* MySQL is doing an ALTER TABLE command and it renames the
original table to a temporary table name. We want to preserve original table to a temporary table name. We want to preserve
the original foreign key constraint definitions despite the the original foreign key constraint definitions despite the
@@ -3713,110 +3578,124 @@ row_rename_table_for_mysql(
heap = mem_heap_create(100); heap = mem_heap_create(100);
err = dict_foreign_parse_drop_constraints(heap, trx, err = dict_foreign_parse_drop_constraints(heap, trx,
table, table, &n_constraints_to_drop, &constraints_to_drop);
&n_constraints_to_drop,
&constraints_to_drop);
if (err != DB_SUCCESS) { if (err != DB_SUCCESS) {
goto funct_exit; goto funct_exit;
} }
/* reserve space for all database names */
len += 2 * n_constraints_to_drop
* (ut_strlenq(old_name, '\'')
- ut_strlenq(old_name + db_name_len, '\''));
for (i = 0; i < n_constraints_to_drop; i++) {
ulint addlen
= 2 * ut_strlenq(constraints_to_drop[i], '\'')
+ ((sizeof str4a1) + (sizeof str4a2)
+ (sizeof str4a3) - 3);
if (!strchr(constraints_to_drop[i], '/')) {
addlen *= 2;
}
len += addlen;
}
} else {
db_name_len = 0;
len += (sizeof str4b) - 1;
} }
sql = sqlend = mem_alloc(len + 1); /* We use the private SQL parser of Innobase to generate the query
memcpy(sql, str1, (sizeof str1) - 1); graphs needed in deleting the dictionary data from system tables in
sqlend += (sizeof str1) - 1; Innobase. Deleting a row from SYS_INDEXES table also frees the file
sqlend = ut_strcpyq(sqlend, '\'', new_name); segments of the B-tree associated with the index. */
memcpy(sqlend, str2, (sizeof str2) - 1);
sqlend += (sizeof str2) - 1;
sqlend = ut_strcpyq(sqlend, '\'', old_name);
memcpy(sqlend, str3, (sizeof str3) - 1);
sqlend += (sizeof str3) - 1;
if (db_name_len) { info = pars_info_create();
/* Internally, old format < 4.0.18 constraints have as the
constraint id <number>_<number>, while new format constraints pars_info_add_str_literal(info, "new_table_name", new_name);
have <databasename>/<constraintname>. */ pars_info_add_str_literal(info, "old_table_name", old_name);
err = que_eval_sql(info,
"PROCEDURE RENAME_TABLE () IS\n"
"BEGIN\n"
"UPDATE SYS_TABLES SET NAME = :new_table_name\n"
" WHERE NAME = :old_table_name;\n"
"END;\n"
, trx);
if (err != DB_SUCCESS) {
goto end;
}
if (!new_is_tmp) {
/* Rename all constraints. */
info = pars_info_create();
pars_info_add_str_literal(info, "new_table_name", new_name);
pars_info_add_str_literal(info, "old_table_name", old_name);
err = que_eval_sql(info,
"PROCEDURE RENAME_CONSTRAINT_IDS () IS\n"
"gen_constr_prefix CHAR;\n"
"new_db_name CHAR;\n"
"foreign_id CHAR;\n"
"new_foreign_id CHAR;\n"
"old_db_name_len INT;\n"
"old_t_name_len INT;\n"
"new_db_name_len INT;\n"
"id_len INT;\n"
"found INT;\n"
"BEGIN\n"
"found := 1;\n"
"old_db_name_len := INSTR(:old_table_name, '/') - 1;\n"
"new_db_name_len := INSTR(:new_table_name, '/') - 1;\n"
"new_db_name := SUBSTR(:new_table_name, 0, new_db_name_len);\n"
"old_t_name_len := LENGTH(:old_table_name);\n"
"gen_constr_prefix := CONCAT(:old_table_name, '_ibfk_');\n"
"WHILE found = 1 LOOP\n"
" SELECT ID INTO foreign_id\n"
" FROM SYS_FOREIGN\n"
" WHERE FOR_NAME = :old_table_name\n"
" AND TO_BINARY(FOR_NAME) = TO_BINARY(:old_table_name);\n"
" IF (SQL % NOTFOUND) THEN\n"
" found := 0;\n"
" ELSE\n"
" UPDATE SYS_FOREIGN\n"
" SET FOR_NAME = :new_table_name\n"
" WHERE ID = foreign_id;\n"
" id_len := LENGTH(foreign_id);\n"
" IF (INSTR(foreign_id, '/') > 0) THEN\n"
" IF (INSTR(foreign_id,\n"
" gen_constr_prefix) > 0)\n"
" THEN\n"
" new_foreign_id :=\n"
" CONCAT(:new_table_name,\n"
" SUBSTR(foreign_id, old_t_name_len,\n"
" id_len - old_t_name_len));\n"
" ELSE\n"
" new_foreign_id :=\n"
" CONCAT(new_db_name,\n"
" SUBSTR(foreign_id,\n"
" old_db_name_len,\n"
" id_len - old_db_name_len));\n"
" END IF;\n"
" UPDATE SYS_FOREIGN\n"
" SET ID = new_foreign_id\n"
" WHERE ID = foreign_id;\n"
" UPDATE SYS_FOREIGN_COLS\n"
" SET ID = new_foreign_id\n"
" WHERE ID = foreign_id;\n"
" END IF;\n"
" END IF;\n"
"END LOOP;\n"
"UPDATE SYS_FOREIGN SET REF_NAME = :new_table_name\n"
"WHERE REF_NAME = :old_table_name\n"
" AND TO_BINARY(REF_NAME) = TO_BINARY(:old_table_name);\n"
"END;\n"
, trx);
} else if (n_constraints_to_drop > 0) {
/* Drop some constraints of tmp tables. */
ulint db_name_len = dict_get_db_name_len(old_name) + 1;
char* db_name = mem_heap_strdupl(heap, old_name,
db_name_len);
ulint i;
for (i = 0; i < n_constraints_to_drop; i++) { for (i = 0; i < n_constraints_to_drop; i++) {
memcpy(sqlend, str4a1, (sizeof str4a1) - 1); err = row_delete_constraint(constraints_to_drop[i],
sqlend += (sizeof str4a1) - 1; db_name, heap, trx);
sqlend = ut_memcpyq(sqlend, '\'',
old_name, db_name_len);
sqlend = ut_strcpyq(sqlend, '\'',
constraints_to_drop[i]);
memcpy(sqlend, str4a2, (sizeof str4a2) - 1);
sqlend += (sizeof str4a2) - 1;
sqlend = ut_memcpyq(sqlend, '\'',
old_name, db_name_len);
sqlend = ut_strcpyq(sqlend, '\'',
constraints_to_drop[i]);
memcpy(sqlend, str4a3, (sizeof str4a3) - 1);
sqlend += (sizeof str4a3) - 1;
if (!strchr(constraints_to_drop[i], '/')) { if (err != DB_SUCCESS) {
/* If this happens to be an old format break;
constraint, let us delete it. Since all new
format constraints contain '/', it does no
harm to run these DELETEs anyway. */
memcpy(sqlend, str4a1, (sizeof str4a1) - 1);
sqlend += (sizeof str4a1) - 1;
sqlend = ut_strcpyq(sqlend, '\'',
constraints_to_drop[i]);
memcpy(sqlend, str4a2, (sizeof str4a2) - 1);
sqlend += (sizeof str4a2) - 1;
sqlend = ut_strcpyq(sqlend, '\'',
constraints_to_drop[i]);
memcpy(sqlend, str4a3, (sizeof str4a3) - 1);
sqlend += (sizeof str4a3) - 1;
} }
} }
} }
else {
memcpy(sqlend, str4b, (sizeof str4b) - 1);
sqlend += (sizeof str4b) - 1;
}
memcpy(sqlend, str5, sizeof str5);
sqlend += sizeof str5;
ut_a(sqlend == sql + len + 1);
graph = pars_sql(NULL, sql);
ut_a(graph);
mem_free(sql);
graph->trx = trx;
trx->graph = NULL;
graph->fork_type = QUE_FORK_MYSQL_INTERFACE;
ut_a(thr = que_fork_start_command(graph));
que_run_threads(thr);
err = trx->error_state;
end:
if (err != DB_SUCCESS) { if (err != DB_SUCCESS) {
if (err == DB_DUPLICATE_KEY) { if (err == DB_DUPLICATE_KEY) {
ut_print_timestamp(stderr); ut_print_timestamp(stderr);
@@ -3853,8 +3732,9 @@ row_rename_table_for_mysql(
/* The following call will also rename the .ibd data file if /* The following call will also rename the .ibd data file if
the table is stored in a single-table tablespace */ the table is stored in a single-table tablespace */
success = dict_table_rename_in_cache(table, new_name, ibool success = dict_table_rename_in_cache(table, new_name,
!new_is_tmp); !new_is_tmp);
if (!success) { if (!success) {
trx->error_state = DB_SUCCESS; trx->error_state = DB_SUCCESS;
trx_general_rollback_for_mysql(trx, FALSE, NULL); trx_general_rollback_for_mysql(trx, FALSE, NULL);
@@ -3902,20 +3782,16 @@ row_rename_table_for_mysql(
ut_a(dict_table_rename_in_cache(table, ut_a(dict_table_rename_in_cache(table,
old_name, FALSE)); old_name, FALSE));
trx->error_state = DB_SUCCESS; trx->error_state = DB_SUCCESS;
trx_general_rollback_for_mysql(trx, FALSE, trx_general_rollback_for_mysql(trx, FALSE, NULL);
NULL);
trx->error_state = DB_SUCCESS; trx->error_state = DB_SUCCESS;
} }
} }
funct_exit: funct_exit:
if (!recovering_temp_table) { if (!recovering_temp_table) {
row_mysql_unlock_data_dictionary(trx); row_mysql_unlock_data_dictionary(trx);
} }
if (graph) {
que_graph_free(graph);
}
if (UNIV_LIKELY_NULL(heap)) { if (UNIV_LIKELY_NULL(heap)) {
mem_heap_free(heap); mem_heap_free(heap);
} }

View File

@@ -521,7 +521,7 @@ row_purge_parse_undo_rec(
mutex_enter(&(dict_sys->mutex)); mutex_enter(&(dict_sys->mutex));
node->table = dict_table_get_on_id_low(table_id, trx); node->table = dict_table_get_on_id_low(table_id);
mutex_exit(&(dict_sys->mutex)); mutex_exit(&(dict_sys->mutex));

View File

@@ -2036,8 +2036,13 @@ row_fetch_print(
dtype_print(type); dtype_print(type);
fprintf(stderr, "\n"); fprintf(stderr, "\n");
ut_print_buf(stderr, dfield_get_data(dfield), if (dfield_get_len(dfield) != UNIV_SQL_NULL) {
dfield_get_len(dfield)); ut_print_buf(stderr, dfield_get_data(dfield),
dfield_get_len(dfield));
} else {
fprintf(stderr, " <NULL>;");
}
fprintf(stderr, "\n"); fprintf(stderr, "\n");
exp = que_node_get_next(exp); exp = que_node_get_next(exp);
@@ -4401,7 +4406,7 @@ row_search_check_if_query_cache_permitted(
dict_table_t* table; dict_table_t* table;
ibool ret = FALSE; ibool ret = FALSE;
table = dict_table_get(norm_name, trx); table = dict_table_get(norm_name);
if (table == NULL) { if (table == NULL) {

View File

@@ -202,8 +202,7 @@ row_upd_check_references_constraints(
foreign->n_fields))) { foreign->n_fields))) {
if (foreign->foreign_table == NULL) { if (foreign->foreign_table == NULL) {
dict_table_get(foreign->foreign_table_name, dict_table_get(foreign->foreign_table_name);
trx);
} }
if (foreign->foreign_table) { if (foreign->foreign_table) {

View File

@@ -362,30 +362,6 @@ ibool srv_print_innodb_lock_monitor = FALSE;
ibool srv_print_innodb_tablespace_monitor = FALSE; ibool srv_print_innodb_tablespace_monitor = FALSE;
ibool srv_print_innodb_table_monitor = FALSE; ibool srv_print_innodb_table_monitor = FALSE;
/* The parameters below are obsolete: */
ibool srv_print_parsed_sql = FALSE;
ulint srv_sim_disk_wait_pct = ULINT_MAX;
ulint srv_sim_disk_wait_len = ULINT_MAX;
ibool srv_sim_disk_wait_by_yield = FALSE;
ibool srv_sim_disk_wait_by_wait = FALSE;
ibool srv_measure_contention = FALSE;
ibool srv_measure_by_spin = FALSE;
ibool srv_test_extra_mutexes = FALSE;
ibool srv_test_nocache = FALSE;
ibool srv_test_cache_evict = FALSE;
ibool srv_test_sync = FALSE;
ulint srv_test_n_threads = ULINT_MAX;
ulint srv_test_n_loops = ULINT_MAX;
ulint srv_test_n_free_rnds = ULINT_MAX;
ulint srv_test_n_reserved_rnds = ULINT_MAX;
ulint srv_test_array_size = ULINT_MAX;
ulint srv_test_n_mutexes = ULINT_MAX;
/* Array of English strings describing the current state of an /* Array of English strings describing the current state of an
i/o handler thread */ i/o handler thread */
@@ -873,11 +849,9 @@ srv_init(void)
srv_sys = mem_alloc(sizeof(srv_sys_t)); srv_sys = mem_alloc(sizeof(srv_sys_t));
kernel_mutex_temp = mem_alloc(sizeof(mutex_t)); kernel_mutex_temp = mem_alloc(sizeof(mutex_t));
mutex_create(&kernel_mutex); mutex_create(&kernel_mutex, SYNC_KERNEL);
mutex_set_level(&kernel_mutex, SYNC_KERNEL);
mutex_create(&srv_innodb_monitor_mutex); mutex_create(&srv_innodb_monitor_mutex, SYNC_NO_ORDER_CHECK);
mutex_set_level(&srv_innodb_monitor_mutex, SYNC_NO_ORDER_CHECK);
srv_sys->threads = mem_alloc(OS_THREAD_MAX_N * sizeof(srv_slot_t)); srv_sys->threads = mem_alloc(OS_THREAD_MAX_N * sizeof(srv_slot_t));
@@ -911,10 +885,6 @@ srv_init(void)
srv_meter_foreground[i] = 250; srv_meter_foreground[i] = 250;
} }
srv_sys->operational = os_event_create(NULL);
ut_a(srv_sys->operational);
UT_LIST_INIT(srv_sys->tasks); UT_LIST_INIT(srv_sys->tasks);
/* create dummy table and index for old-style infimum and supremum */ /* create dummy table and index for old-style infimum and supremum */
@@ -1847,11 +1817,7 @@ srv_export_innodb_status(void)
A thread which wakes up threads whose lock wait may have lasted too long. A thread which wakes up threads whose lock wait may have lasted too long.
This also prints the info output by various InnoDB monitors. */ This also prints the info output by various InnoDB monitors. */
#ifndef __WIN__ os_thread_ret_t
void*
#else
ulint
#endif
srv_lock_timeout_and_monitor_thread( srv_lock_timeout_and_monitor_thread(
/*================================*/ /*================================*/
/* out: a dummy parameter */ /* out: a dummy parameter */
@@ -2023,22 +1989,15 @@ exit_func:
thread should always use that to exit and not use return() to exit. */ thread should always use that to exit and not use return() to exit. */
os_thread_exit(NULL); os_thread_exit(NULL);
#ifndef __WIN__
return(NULL); OS_THREAD_DUMMY_RETURN;
#else
return(0);
#endif
} }
/************************************************************************* /*************************************************************************
A thread which prints warnings about semaphore waits which have lasted A thread which prints warnings about semaphore waits which have lasted
too long. These can be used to track bugs which cause hangs. */ too long. These can be used to track bugs which cause hangs. */
#ifndef __WIN__ os_thread_ret_t
void*
#else
ulint
#endif
srv_error_monitor_thread( srv_error_monitor_thread(
/*=====================*/ /*=====================*/
/* out: a dummy parameter */ /* out: a dummy parameter */
@@ -2120,11 +2079,7 @@ loop:
os_thread_exit(NULL); os_thread_exit(NULL);
#ifndef __WIN__ OS_THREAD_DUMMY_RETURN;
return(NULL);
#else
return(0);
#endif
} }
/*********************************************************************** /***********************************************************************
@@ -2169,11 +2124,7 @@ srv_wake_master_thread(void)
/************************************************************************* /*************************************************************************
The master thread controlling the server. */ The master thread controlling the server. */
#ifndef __WIN__ os_thread_ret_t
void*
#else
ulint
#endif
srv_master_thread( srv_master_thread(
/*==============*/ /*==============*/
/* out: a dummy parameter */ /* out: a dummy parameter */
@@ -2212,7 +2163,6 @@ srv_master_thread(
mutex_exit(&kernel_mutex); mutex_exit(&kernel_mutex);
os_event_set(srv_sys->operational);
loop: loop:
/*****************************************************************/ /*****************************************************************/
/* ---- When there is database activity by users, we cycle in this /* ---- When there is database activity by users, we cycle in this
@@ -2607,22 +2557,9 @@ suspend_thread:
os_thread_exit(NULL); os_thread_exit(NULL);
} }
/* When there is user activity, InnoDB will set the event and the main /* When there is user activity, InnoDB will set the event and the
thread goes back to loop: */ main thread goes back to loop. */
goto loop; goto loop;
/* We count the number of threads in os_thread_exit(). A created
thread should always use that to exit and not use return() to exit.
The thread actually never comes here because it is exited in an
os_event_wait(). */
os_thread_exit(NULL);
#ifndef __WIN__
return(NULL); /* Not reached */
#else
return(0);
#endif
} }
#endif /* !UNIV_HOTBACKUP */ #endif /* !UNIV_HOTBACKUP */

View File

@@ -108,8 +108,10 @@ static char* srv_monitor_file_name;
static int inno_bcmp(register const char *s1, register const char *s2, static int inno_bcmp(register const char *s1, register const char *s2,
register uint len) register uint len)
{ {
while (len-- != 0 && *s1++ == *s2++) ; while ((len-- != 0) && (*s1++ == *s2++))
return len+1; ;
return(len + 1);
} }
#define memcmp(A,B,C) inno_bcmp((A),(B),(C)) #define memcmp(A,B,C) inno_bcmp((A),(B),(C))
#endif #endif
@@ -426,11 +428,7 @@ srv_parse_log_group_home_dirs(
I/o-handler thread function. */ I/o-handler thread function. */
static static
#ifndef __WIN__ os_thread_ret_t
void*
#else
ulint
#endif
io_handler_thread( io_handler_thread(
/*==============*/ /*==============*/
void* arg) void* arg)
@@ -459,11 +457,7 @@ io_handler_thread(
os_thread_exit(NULL); os_thread_exit(NULL);
#ifndef __WIN__ OS_THREAD_DUMMY_RETURN;
return(NULL); /* Not reached */
#else
return(0);
#endif
} }
#endif /* !UNIV_HOTBACKUP */ #endif /* !UNIV_HOTBACKUP */
@@ -942,8 +936,7 @@ skip_size_check:
ios = 0; ios = 0;
mutex_create(&ios_mutex); mutex_create(&ios_mutex, SYNC_NO_ORDER_CHECK);
mutex_set_level(&ios_mutex, SYNC_NO_ORDER_CHECK);
return(DB_SUCCESS); return(DB_SUCCESS);
} }
@@ -1175,8 +1168,8 @@ NetWare. */
return((int) err); return((int) err);
} }
mutex_create(&srv_monitor_file_mutex); mutex_create(&srv_monitor_file_mutex, SYNC_NO_ORDER_CHECK);
mutex_set_level(&srv_monitor_file_mutex, SYNC_NO_ORDER_CHECK);
if (srv_innodb_status) { if (srv_innodb_status) {
srv_monitor_file_name = mem_alloc( srv_monitor_file_name = mem_alloc(
strlen(fil_path_to_mysql_datadir) + strlen(fil_path_to_mysql_datadir) +
@@ -1197,15 +1190,15 @@ NetWare. */
} }
} }
mutex_create(&srv_dict_tmpfile_mutex); mutex_create(&srv_dict_tmpfile_mutex, SYNC_DICT_OPERATION);
mutex_set_level(&srv_dict_tmpfile_mutex, SYNC_DICT_OPERATION);
srv_dict_tmpfile = os_file_create_tmpfile(); srv_dict_tmpfile = os_file_create_tmpfile();
if (!srv_dict_tmpfile) { if (!srv_dict_tmpfile) {
return(DB_ERROR); return(DB_ERROR);
} }
mutex_create(&srv_misc_tmpfile_mutex); mutex_create(&srv_misc_tmpfile_mutex, SYNC_ANY_LATCH);
mutex_set_level(&srv_misc_tmpfile_mutex, SYNC_ANY_LATCH);
srv_misc_tmpfile = os_file_create_tmpfile(); srv_misc_tmpfile = os_file_create_tmpfile();
if (!srv_misc_tmpfile) { if (!srv_misc_tmpfile) {
return(DB_ERROR); return(DB_ERROR);
@@ -1539,11 +1532,6 @@ NetWare. */
} }
#endif /* UNIV_LOG_ARCHIVE */ #endif /* UNIV_LOG_ARCHIVE */
if (srv_measure_contention) {
/* os_thread_create(&test_measure_cont, NULL, thread_ids +
SRV_MAX_N_IO_THREADS); */
}
/* fprintf(stderr, "Max allowed record size %lu\n", /* fprintf(stderr, "Max allowed record size %lu\n",
page_get_free_space_of_empty() / 2); */ page_get_free_space_of_empty() / 2); */

View File

@@ -213,8 +213,7 @@ sync_array_create(
if (protection == SYNC_ARRAY_OS_MUTEX) { if (protection == SYNC_ARRAY_OS_MUTEX) {
arr->os_mutex = os_mutex_create(NULL); arr->os_mutex = os_mutex_create(NULL);
} else if (protection == SYNC_ARRAY_MUTEX) { } else if (protection == SYNC_ARRAY_MUTEX) {
mutex_create(&(arr->mutex)); mutex_create(&arr->mutex, SYNC_NO_ORDER_CHECK);
mutex_set_level(&(arr->mutex), SYNC_NO_ORDER_CHECK);
} else { } else {
ut_error; ut_error;
} }

View File

@@ -89,19 +89,19 @@ void
rw_lock_create_func( rw_lock_create_func(
/*================*/ /*================*/
rw_lock_t* lock, /* in: pointer to memory */ rw_lock_t* lock, /* in: pointer to memory */
ulint level, /* in: level */
const char* cfile_name, /* in: file name where created */ const char* cfile_name, /* in: file name where created */
ulint cline, /* in: file line where created */ ulint cline, /* in: file line where created */
const char* cmutex_name) /* in: mutex name */ const char* cmutex_name) /* in: mutex name */
{ {
/* If this is the very first time a synchronization /* If this is the very first time a synchronization object is
object is created, then the following call initializes created, then the following call initializes the sync system. */
the sync system. */
mutex_create(rw_lock_get_mutex(lock)); mutex_create(rw_lock_get_mutex(lock), SYNC_NO_ORDER_CHECK);
mutex_set_level(rw_lock_get_mutex(lock), SYNC_NO_ORDER_CHECK);
lock->mutex.cfile_name = cfile_name; lock->mutex.cfile_name = cfile_name;
lock->mutex.cline = cline; lock->mutex.cline = cline;
#ifndef UNIV_HOTBACKUP #ifndef UNIV_HOTBACKUP
lock->mutex.cmutex_name = cmutex_name; lock->mutex.cmutex_name = cmutex_name;
lock->mutex.mutex_type = 1; lock->mutex.mutex_type = 1;
@@ -116,9 +116,10 @@ rw_lock_create_func(
#ifdef UNIV_SYNC_DEBUG #ifdef UNIV_SYNC_DEBUG
UT_LIST_INIT(lock->debug_list); UT_LIST_INIT(lock->debug_list);
lock->level = SYNC_LEVEL_NONE;
#endif /* UNIV_SYNC_DEBUG */ #endif /* UNIV_SYNC_DEBUG */
lock->level = level;
lock->magic_n = RW_LOCK_MAGIC_N; lock->magic_n = RW_LOCK_MAGIC_N;
lock->cfile_name = cfile_name; lock->cfile_name = cfile_name;
@@ -669,18 +670,6 @@ rw_lock_remove_debug_info(
} }
#endif /* UNIV_SYNC_DEBUG */ #endif /* UNIV_SYNC_DEBUG */
/**********************************************************************
Sets the rw-lock latching level field. */
void
rw_lock_set_level(
/*==============*/
rw_lock_t* lock, /* in: rw-lock */
ulint level) /* in: level */
{
lock->level = level;
}
#ifdef UNIV_SYNC_DEBUG #ifdef UNIV_SYNC_DEBUG
/********************************************************************** /**********************************************************************
Checks if the thread has locked the rw-lock in the specified mode, with Checks if the thread has locked the rw-lock in the specified mode, with

View File

@@ -202,6 +202,7 @@ void
mutex_create_func( mutex_create_func(
/*==============*/ /*==============*/
mutex_t* mutex, /* in: pointer to memory */ mutex_t* mutex, /* in: pointer to memory */
ulint level, /* in: level */
const char* cfile_name, /* in: file name where created */ const char* cfile_name, /* in: file name where created */
ulint cline, /* in: file line where created */ ulint cline, /* in: file line where created */
const char* cmutex_name) /* in: mutex name */ const char* cmutex_name) /* in: mutex name */
@@ -218,7 +219,7 @@ mutex_create_func(
mutex->line = 0; mutex->line = 0;
mutex->file_name = "not yet reserved"; mutex->file_name = "not yet reserved";
#endif /* UNIV_SYNC_DEBUG */ #endif /* UNIV_SYNC_DEBUG */
mutex->level = SYNC_LEVEL_NONE; mutex->level = level;
mutex->cfile_name = cfile_name; mutex->cfile_name = cfile_name;
mutex->cline = cline; mutex->cline = cline;
#ifndef UNIV_HOTBACKUP #ifndef UNIV_HOTBACKUP
@@ -598,19 +599,6 @@ mutex_get_debug_info(
} }
#endif /* UNIV_SYNC_DEBUG */ #endif /* UNIV_SYNC_DEBUG */
/**********************************************************************
Sets the mutex latching level field. */
void
mutex_set_level(
/*============*/
mutex_t* mutex, /* in: mutex */
ulint level) /* in: level */
{
mutex->level = level;
}
#ifdef UNIV_SYNC_DEBUG #ifdef UNIV_SYNC_DEBUG
/********************************************************************** /**********************************************************************
Checks that the current thread owns the mutex. Works only in the debug Checks that the current thread owns the mutex. Works only in the debug
@@ -979,8 +967,8 @@ void
sync_thread_add_level( sync_thread_add_level(
/*==================*/ /*==================*/
void* latch, /* in: pointer to a mutex or an rw-lock */ void* latch, /* in: pointer to a mutex or an rw-lock */
ulint level) /* in: level in the latching order; if SYNC_LEVEL_NONE, ulint level) /* in: level in the latching order; if
nothing is done */ SYNC_LEVEL_VARYING, nothing is done */
{ {
sync_level_t* array; sync_level_t* array;
sync_level_t* slot; sync_level_t* slot;
@@ -1002,7 +990,7 @@ sync_thread_add_level(
return; return;
} }
if (level == SYNC_LEVEL_NONE) { if (level == SYNC_LEVEL_VARYING) {
return; return;
} }
@@ -1050,6 +1038,9 @@ sync_thread_add_level(
case SYNC_RECV: case SYNC_RECV:
ut_a(sync_thread_levels_g(array, SYNC_RECV)); ut_a(sync_thread_levels_g(array, SYNC_RECV));
break; break;
case SYNC_WORK_QUEUE:
ut_a(sync_thread_levels_g(array, SYNC_WORK_QUEUE));
break;
case SYNC_LOG: case SYNC_LOG:
ut_a(sync_thread_levels_g(array, SYNC_LOG)); ut_a(sync_thread_levels_g(array, SYNC_LOG));
break; break;
@@ -1290,21 +1281,17 @@ sync_init(void)
/* Init the mutex list and create the mutex to protect it. */ /* Init the mutex list and create the mutex to protect it. */
UT_LIST_INIT(mutex_list); UT_LIST_INIT(mutex_list);
mutex_create(&mutex_list_mutex); mutex_create(&mutex_list_mutex, SYNC_NO_ORDER_CHECK);
mutex_set_level(&mutex_list_mutex, SYNC_NO_ORDER_CHECK);
mutex_create(&sync_thread_mutex); mutex_create(&sync_thread_mutex, SYNC_NO_ORDER_CHECK);
mutex_set_level(&sync_thread_mutex, SYNC_NO_ORDER_CHECK);
/* Init the rw-lock list and create the mutex to protect it. */ /* Init the rw-lock list and create the mutex to protect it. */
UT_LIST_INIT(rw_lock_list); UT_LIST_INIT(rw_lock_list);
mutex_create(&rw_lock_list_mutex); mutex_create(&rw_lock_list_mutex, SYNC_NO_ORDER_CHECK);
mutex_set_level(&rw_lock_list_mutex, SYNC_NO_ORDER_CHECK);
#ifdef UNIV_SYNC_DEBUG #ifdef UNIV_SYNC_DEBUG
mutex_create(&rw_lock_debug_mutex); mutex_create(&rw_lock_debug_mutex, SYNC_NO_ORDER_CHECK);
mutex_set_level(&rw_lock_debug_mutex, SYNC_NO_ORDER_CHECK);
rw_lock_debug_event = os_event_create(NULL); rw_lock_debug_event = os_event_create(NULL);
rw_lock_debug_waiters = FALSE; rw_lock_debug_waiters = FALSE;

View File

@@ -226,6 +226,5 @@ thr_local_init(void)
thr_local_hash = hash_create(OS_THREAD_MAX_N + 100); thr_local_hash = hash_create(OS_THREAD_MAX_N + 100);
mutex_create(&thr_local_mutex); mutex_create(&thr_local_mutex, SYNC_THR_LOCAL);
mutex_set_level(&thr_local_mutex, SYNC_THR_LOCAL);
} }

View File

@@ -211,11 +211,9 @@ trx_purge_sys_create(void)
purge_sys->purge_undo_no = ut_dulint_zero; purge_sys->purge_undo_no = ut_dulint_zero;
purge_sys->next_stored = FALSE; purge_sys->next_stored = FALSE;
rw_lock_create(&(purge_sys->latch)); rw_lock_create(&purge_sys->latch, SYNC_PURGE_LATCH);
rw_lock_set_level(&(purge_sys->latch), SYNC_PURGE_LATCH);
mutex_create(&(purge_sys->mutex)); mutex_create(&purge_sys->mutex, SYNC_PURGE_SYS);
mutex_set_level(&(purge_sys->mutex), SYNC_PURGE_SYS);
purge_sys->heap = mem_heap_create(256); purge_sys->heap = mem_heap_create(256);

View File

@@ -391,11 +391,7 @@ transaction already was committed, then we clean up a possible insert
undo log. If the transaction was not yet committed, then we roll it back. undo log. If the transaction was not yet committed, then we roll it back.
Note: this is done in a background thread. */ Note: this is done in a background thread. */
#ifndef __WIN__ os_thread_ret_t
void*
#else
ulint
#endif
trx_rollback_or_clean_all_without_sess( trx_rollback_or_clean_all_without_sess(
/*===================================*/ /*===================================*/
/* out: a dummy parameter */ /* out: a dummy parameter */
@@ -544,7 +540,7 @@ loop:
(ulong) ut_dulint_get_high(trx->table_id), (ulong) ut_dulint_get_high(trx->table_id),
(ulong) ut_dulint_get_low(trx->table_id)); (ulong) ut_dulint_get_low(trx->table_id));
table = dict_table_get_on_id_low(trx->table_id, trx); table = dict_table_get_on_id_low(trx->table_id);
if (table) { if (table) {
fputs("InnoDB: Table found: dropping table ", stderr); fputs("InnoDB: Table found: dropping table ", stderr);
@@ -576,13 +572,7 @@ leave_function:
os_thread_exit(NULL); os_thread_exit(NULL);
/* The following is dummy code to keep the compiler happy: */ OS_THREAD_DUMMY_RETURN;
#ifndef __WIN__
return(NULL);
#else
return(0);
#endif
} }
/*********************************************************************** /***********************************************************************

View File

@@ -147,8 +147,7 @@ trx_rseg_mem_create(
rseg->space = space; rseg->space = space;
rseg->page_no = page_no; rseg->page_no = page_no;
mutex_create(&(rseg->mutex)); mutex_create(&rseg->mutex, SYNC_RSEG);
mutex_set_level(&(rseg->mutex), SYNC_RSEG);
UT_LIST_ADD_LAST(rseg_list, trx_sys->rseg_list, rseg); UT_LIST_ADD_LAST(rseg_list, trx_sys->rseg_list, rseg);

View File

@@ -54,6 +54,36 @@ char trx_sys_mysql_bin_log_name[TRX_SYS_MYSQL_LOG_NAME_LEN];
ib_longlong trx_sys_mysql_bin_log_pos = -1; ib_longlong trx_sys_mysql_bin_log_pos = -1;
/********************************************************************
Determines if a page number is located inside the doublewrite buffer. */
ibool
trx_doublewrite_page_inside(
/*========================*/
/* out: TRUE if the location is inside
the two blocks of the doublewrite buffer */
ulint page_no) /* in: page number */
{
if (trx_doublewrite == NULL) {
return(FALSE);
}
if (page_no >= trx_doublewrite->block1
&& page_no < trx_doublewrite->block1
+ TRX_SYS_DOUBLEWRITE_BLOCK_SIZE) {
return(TRUE);
}
if (page_no >= trx_doublewrite->block2
&& page_no < trx_doublewrite->block2
+ TRX_SYS_DOUBLEWRITE_BLOCK_SIZE) {
return(TRUE);
}
return(FALSE);
}
/******************************************************************** /********************************************************************
Creates or initialializes the doublewrite buffer at a database start. */ Creates or initialializes the doublewrite buffer at a database start. */
static static
@@ -71,8 +101,7 @@ trx_doublewrite_init(
os_do_not_call_flush_at_each_write = TRUE; os_do_not_call_flush_at_each_write = TRUE;
#endif /* UNIV_DO_FLUSH */ #endif /* UNIV_DO_FLUSH */
mutex_create(&(trx_doublewrite->mutex)); mutex_create(&trx_doublewrite->mutex, SYNC_DOUBLEWRITE);
mutex_set_level(&(trx_doublewrite->mutex), SYNC_DOUBLEWRITE);
trx_doublewrite->first_free = 0; trx_doublewrite->first_free = 0;

View File

@@ -144,8 +144,7 @@ trx_create(
trx->repl_wait_binlog_name = NULL; trx->repl_wait_binlog_name = NULL;
trx->repl_wait_binlog_pos = 0; trx->repl_wait_binlog_pos = 0;
mutex_create(&(trx->undo_mutex)); mutex_create(&trx->undo_mutex, SYNC_TRX_UNDO);
mutex_set_level(&(trx->undo_mutex), SYNC_TRX_UNDO);
trx->rseg = NULL; trx->rseg = NULL;

View File

@@ -19,6 +19,6 @@ include ../include/Makefile.i
noinst_LIBRARIES = libut.a noinst_LIBRARIES = libut.a
libut_a_SOURCES = ut0byte.c ut0dbg.c ut0mem.c ut0rnd.c ut0ut.c ut0vec.c libut_a_SOURCES = ut0byte.c ut0dbg.c ut0mem.c ut0rnd.c ut0ut.c ut0vec.c ut0list.c ut0wqueue.c
EXTRA_PROGRAMS = EXTRA_PROGRAMS =

147
ut/ut0list.c Normal file
View File

@@ -0,0 +1,147 @@
#include "ut0list.h"
#ifdef UNIV_NONINL
#include "ut0list.ic"
#endif
/********************************************************************
Create a new list. */
ib_list_t*
ib_list_create(void)
/*=================*/
/* out: list */
{
ib_list_t* list = mem_alloc(sizeof(ib_list_t));
list->first = NULL;
list->last = NULL;
return(list);
}
/********************************************************************
Free a list. */
void
ib_list_free(
/*=========*/
ib_list_t* list) /* in: list */
{
/* We don't check that the list is empty because it's entirely valid
to e.g. have all the nodes allocated from a single heap that is then
freed after the list itself is freed. */
mem_free(list);
}
/********************************************************************
Add the data to the start of the list. */
ib_list_node_t*
ib_list_add_first(
/*==============*/
/* out: new list node*/
ib_list_t* list, /* in: list */
void* data, /* in: data */
mem_heap_t* heap) /* in: memory heap to use */
{
return(ib_list_add_after(list, ib_list_get_first(list), data, heap));
}
/********************************************************************
Add the data to the end of the list. */
ib_list_node_t*
ib_list_add_last(
/*=============*/
/* out: new list node*/
ib_list_t* list, /* in: list */
void* data, /* in: data */
mem_heap_t* heap) /* in: memory heap to use */
{
return(ib_list_add_after(list, ib_list_get_last(list), data, heap));
}
/********************************************************************
Add the data after the indicated node. */
ib_list_node_t*
ib_list_add_after(
/*==============*/
/* out: new list node*/
ib_list_t* list, /* in: list */
ib_list_node_t* prev_node, /* in: node preceding new node (can
be NULL) */
void* data, /* in: data */
mem_heap_t* heap) /* in: memory heap to use */
{
ib_list_node_t* node = mem_heap_alloc(heap, sizeof(ib_list_node_t));
node->data = data;
if (!list->first) {
/* Empty list. */
ut_a(!prev_node);
node->prev = NULL;
node->next = NULL;
list->first = node;
list->last = node;
} else if (!prev_node) {
/* Start of list. */
node->prev = NULL;
node->next = list->first;
list->first->prev = node;
list->first = node;
} else {
/* Middle or end of list. */
node->prev = prev_node;
node->next = prev_node->next;
prev_node->next = node;
if (node->next) {
node->next->prev = node;
} else {
list->last = node;
}
}
return(node);
}
/********************************************************************
Remove the node from the list. */
void
ib_list_remove(
/*===========*/
ib_list_t* list, /* in: list */
ib_list_node_t* node) /* in: node to remove */
{
if (node->prev) {
node->prev->next = node->next;
} else {
/* First item in list. */
ut_ad(list->first == node);
list->first = node->next;
}
if (node->next) {
node->next->prev = node->prev;
} else {
/* Last item in list. */
ut_ad(list->last == node);
list->last = node->prev;
}
}

92
ut/ut0wqueue.c Normal file
View File

@@ -0,0 +1,92 @@
#include "ut0wqueue.h"
/********************************************************************
Create a new work queue. */
ib_wqueue_t*
ib_wqueue_create(void)
/*===================*/
/* out: work queue */
{
ib_wqueue_t* wq = mem_alloc(sizeof(ib_wqueue_t));
mutex_create(&wq->mutex, SYNC_WORK_QUEUE);
wq->items = ib_list_create();
wq->event = os_event_create(NULL);
return(wq);
}
/********************************************************************
Free a work queue. */
void
ib_wqueue_free(
/*===========*/
ib_wqueue_t* wq) /* in: work queue */
{
ut_a(!ib_list_get_first(wq->items));
mutex_free(&wq->mutex);
ib_list_free(wq->items);
os_event_free(wq->event);
mem_free(wq);
}
/********************************************************************
Add a work item to the queue. */
void
ib_wqueue_add(
/*==========*/
ib_wqueue_t* wq, /* in: work queue */
void* item, /* in: work item */
mem_heap_t* heap) /* in: memory heap to use for allocating the
list node */
{
mutex_enter(&wq->mutex);
ib_list_add_last(wq->items, item, heap);
os_event_set(wq->event);
mutex_exit(&wq->mutex);
}
/********************************************************************
Wait for a work item to appear in the queue. */
void*
ib_wqueue_wait(
/* out: work item */
ib_wqueue_t* wq) /* in: work queue */
{
ib_list_node_t* node;
for (;;) {
os_event_wait(wq->event);
mutex_enter(&wq->mutex);
node = ib_list_get_first(wq->items);
if (node) {
ib_list_remove(wq->items, node);
if (!ib_list_get_first(wq->items)) {
/* We must reset the event when the list
gets emptied. */
os_event_reset(wq->event);
}
break;
}
mutex_exit(&wq->mutex);
}
mutex_exit(&wq->mutex);
return(node->data);
}