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 \
pars que read rem row srv sync thr trx usr
EXTRA_DIST = include/btr0btr.h include/btr0btr.ic include/btr0cur.h include/btr0cur.ic \
include/btr0pcur.h include/btr0pcur.ic include/btr0sea.h include/btr0sea.ic \
include/btr0types.h \
include/buf0buf.h include/buf0buf.ic include/buf0flu.h include/buf0flu.ic \
include/buf0lru.h include/buf0lru.ic include/buf0rea.h include/buf0types.h \
include/data0data.h include/data0data.ic include/data0type.h include/data0type.ic \
include/data0types.h include/db0err.h \
include/dict0boot.h include/dict0boot.ic include/dict0crea.h include/dict0crea.ic \
include/dict0dict.h include/dict0dict.ic include/dict0load.h include/dict0load.ic \
include/dict0mem.h include/dict0mem.ic include/dict0types.h \
include/dyn0dyn.h include/dyn0dyn.ic \
include/eval0eval.h include/eval0eval.ic include/eval0proc.h include/eval0proc.ic \
include/fil0fil.h include/fsp0fsp.h 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 \
EXTRA_DIST = include/btr0btr.h include/btr0btr.ic include/btr0cur.h \
include/btr0cur.ic include/btr0pcur.h include/btr0pcur.ic \
include/btr0sea.h include/btr0sea.ic include/btr0types.h \
include/buf0buf.h include/buf0buf.ic include/buf0flu.h \
include/buf0flu.ic include/buf0lru.h include/buf0lru.ic \
include/buf0rea.h include/buf0types.h include/data0data.h \
include/data0data.ic include/data0type.h include/data0type.ic \
include/data0types.h include/db0err.h include/dict0boot.h \
include/dict0boot.ic include/dict0crea.h include/dict0crea.ic \
include/dict0dict.h include/dict0dict.ic include/dict0load.h \
include/dict0load.ic include/dict0mem.h include/dict0mem.ic \
include/dict0types.h include/dyn0dyn.h include/dyn0dyn.ic \
include/eval0eval.h include/eval0eval.ic include/eval0proc.h \
include/eval0proc.ic include/fil0fil.h include/fsp0fsp.h \
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/lock0lock.h include/lock0lock.ic include/lock0types.h \
include/log0log.h include/log0log.ic include/log0recv.h include/log0recv.ic \
include/mach0data.h include/mach0data.ic include/mem0dbg.h include/mem0dbg.ic \
include/mem0mem.h include/mem0mem.ic include/mem0pool.h include/mem0pool.ic \
include/mtr0log.h include/mtr0log.ic include/mtr0mtr.h include/mtr0mtr.ic \
include/mtr0types.h include/os0file.h \
include/os0proc.h include/os0proc.ic include/os0sync.h include/os0sync.ic \
include/os0thread.h include/os0thread.ic \
include/page0cur.h include/page0cur.ic include/page0page.h include/page0page.ic \
include/page0types.h \
include/pars0grm.h include/pars0opt.h include/pars0opt.ic \
include/pars0pars.h include/pars0pars.ic include/pars0sym.h include/pars0sym.ic \
include/pars0types.h \
include/que0que.h include/que0que.ic include/que0types.h \
include/read0read.h include/read0read.ic include/read0types.h \
include/rem0cmp.h include/rem0cmp.ic include/rem0rec.h include/rem0rec.ic \
include/rem0types.h \
include/row0ins.h include/row0ins.ic include/row0mysql.h include/row0mysql.ic \
include/row0purge.h include/row0purge.ic include/row0row.h include/row0row.ic \
include/row0sel.h include/row0sel.ic include/row0types.h \
include/row0uins.h include/row0uins.ic include/row0umod.h include/row0umod.ic \
include/row0undo.h include/row0undo.ic include/row0upd.h include/row0upd.ic \
include/row0vers.h include/row0vers.ic \
include/srv0que.h include/srv0srv.h include/srv0srv.ic include/srv0start.h \
include/sync0arr.h include/sync0arr.ic include/sync0rw.h include/sync0rw.ic \
include/sync0sync.h include/sync0sync.ic include/sync0types.h \
include/thr0loc.h include/thr0loc.ic \
include/trx0purge.h include/trx0purge.ic include/trx0rec.h include/trx0rec.ic \
include/trx0roll.h include/trx0roll.ic include/trx0rseg.h include/trx0rseg.ic \
include/trx0sys.h include/trx0sys.ic include/trx0trx.h include/trx0trx.ic \
include/trx0types.h include/trx0undo.h include/trx0undo.ic include/trx0xa.h \
include/univ.i 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/log0log.h include/log0log.ic include/log0recv.h \
include/log0recv.ic include/mach0data.h include/mach0data.ic \
include/mem0dbg.h include/mem0dbg.ic include/mem0mem.h \
include/mem0mem.ic include/mem0pool.h include/mem0pool.ic \
include/mtr0log.h include/mtr0log.ic include/mtr0mtr.h \
include/mtr0mtr.ic include/mtr0types.h include/os0file.h \
include/os0proc.h include/os0proc.ic include/os0sync.h \
include/os0sync.ic include/os0thread.h include/os0thread.ic \
include/page0cur.h include/page0cur.ic include/page0page.h \
include/page0page.ic include/page0types.h include/pars0grm.h \
include/pars0opt.h include/pars0opt.ic include/pars0pars.h \
include/pars0pars.ic include/pars0sym.h include/pars0sym.ic \
include/pars0types.h include/que0que.h include/que0que.ic \
include/que0types.h include/read0read.h include/read0read.ic \
include/read0types.h include/rem0cmp.h include/rem0cmp.ic \
include/rem0rec.h include/rem0rec.ic include/rem0types.h \
include/row0ins.h include/row0ins.ic include/row0mysql.h \
include/row0mysql.ic include/row0purge.h include/row0purge.ic \
include/row0row.h include/row0row.ic include/row0sel.h \
include/row0sel.ic include/row0types.h include/row0uins.h \
include/row0uins.ic include/row0umod.h include/row0umod.ic \
include/row0undo.h include/row0undo.ic include/row0upd.h \
include/row0upd.ic include/row0vers.h include/row0vers.ic \
include/srv0que.h include/srv0srv.h include/srv0srv.ic \
include/srv0start.h include/sync0arr.h include/sync0arr.ic \
include/sync0rw.h include/sync0rw.ic include/sync0sync.h \
include/sync0sync.ic include/sync0types.h include/thr0loc.h \
include/thr0loc.ic include/trx0purge.h include/trx0purge.ic \
include/trx0rec.h include/trx0rec.ic include/trx0roll.h \
include/trx0roll.ic include/trx0rseg.h include/trx0rseg.ic \
include/trx0sys.h include/trx0sys.ic include/trx0trx.h \
include/trx0trx.ic include/trx0types.h include/trx0undo.h \
include/trx0undo.ic include/trx0xa.h include/univ.i \
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
%::SCCS/s.%

View File

@@ -136,13 +136,12 @@ btr_search_sys_create(
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->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);
rw_lock_create(&(block->lock));
rw_lock_create(&block->lock, SYNC_LEVEL_VARYING);
ut_ad(rw_lock_validate(&(block->lock)));
#ifdef UNIV_SYNC_DEBUG
rw_lock_create(&(block->debug_latch));
rw_lock_set_level(&(block->debug_latch), SYNC_NO_ORDER_CHECK);
rw_lock_create(&block->debug_latch, SYNC_NO_ORDER_CHECK);
#endif /* UNIV_SYNC_DEBUG */
}
@@ -660,8 +659,7 @@ buf_pool_init(
/* 1. Initialize general fields
------------------------------- */
mutex_create(&(buf_pool->mutex));
mutex_set_level(&(buf_pool->mutex), SYNC_BUF_POOL);
mutex_create(&buf_pool->mutex, SYNC_BUF_POOL);
mutex_enter(&(buf_pool->mutex));
@@ -1953,7 +1951,6 @@ buf_page_io_complete(
buf_block_t* block) /* in: pointer to the block in question */
{
ulint io_type;
ulint read_page_no;
ut_ad(block);
@@ -1978,16 +1975,36 @@ buf_page_io_complete(
}
/* If this page is not uninitialized and not in the
doublewrite buffer, then the page number should be the
same as in block */
read_page_no = mach_read_from_4((block->frame)
doublewrite buffer, then the page number and space id
should be the same as in block. */
ulint read_page_no = mach_read_from_4((block->frame)
+ 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,
"InnoDB: Error: page n:o stored in the page read in is %lu, should be %lu!\n",
(ulong) read_page_no, (ulong) block->offset);
" InnoDB: Error: reading page %lu\n"
"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
@@ -2345,7 +2362,8 @@ buf_get_latched_pages_number(void)
}
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 "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. */
#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
trx/trx0purge.c trx/trx0rec.c trx/trx0roll.c trx/trx0rseg.c trx/trx0sys.c trx/trx0trx.c trx/trx0undo.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* table2;
que_thr_t* thr;
que_t* graph;
ulint error;
trx_t* trx;
const char* str;
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
design. */
str =
error = que_eval_sql(NULL,
"PROCEDURE CREATE_FOREIGN_SYS_TABLES_PROC () IS\n"
"BEGIN\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"
"CREATE UNIQUE CLUSTERED INDEX ID_IND ON SYS_FOREIGN_COLS (ID, POS);\n"
"COMMIT WORK;\n"
"END;\n";
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;
"END;\n"
, trx);
if (error != DB_SUCCESS) {
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;
}
que_graph_free(graph);
trx->op_info = "";
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
dbname '/' tablename */
{
const char* s;
s = strchr(name, '/');
const char* s = strchr(name, '/');
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_get_on_id(
@@ -622,12 +621,12 @@ dict_table_get_on_id(
ut_ad(mutex_own(&(dict_sys->mutex)));
#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));
table = dict_table_get_on_id_low(table_id, trx);
table = dict_table_get_on_id_low(table_id);
mutex_exit(&(dict_sys->mutex));
@@ -709,8 +708,7 @@ dict_init(void)
{
dict_sys = mem_alloc(sizeof(dict_sys_t));
mutex_create(&(dict_sys->mutex));
mutex_set_level(&(dict_sys->mutex), SYNC_DICT);
mutex_create(&dict_sys->mutex, SYNC_DICT);
dict_sys->table_hash = hash_create(buf_pool_get_max_size() /
(DICT_POOL_PER_TABLE_HASH *
@@ -725,32 +723,28 @@ dict_init(void)
UT_LIST_INIT(dict_sys->table_LRU);
rw_lock_create(&dict_operation_lock);
rw_lock_set_level(&dict_operation_lock, SYNC_DICT_OPERATION);
rw_lock_create(&dict_operation_lock, SYNC_DICT_OPERATION);
dict_foreign_err_file = os_file_create_tmpfile();
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
function to be used mainly from outside the 'dict' directory. Inside this
directory dict_table_get_low is usually the appropriate function. */
Returns a table object. NOTE! This is a high-level function to be used
mainly from outside the 'dict' directory. Inside this directory
dict_table_get_low is usually the appropriate function. */
dict_table_t*
dict_table_get(
/*===========*/
/* out: table, NULL if
does not exist */
const char* table_name, /* in: table name */
trx_t* trx) /* in: transaction handle or NULL */
const char* table_name) /* in: table name */
{
dict_table_t* table;
UT_NOT_USED(trx);
mutex_enter(&(dict_sys->mutex));
table = dict_table_get_low(table_name);
@@ -774,13 +768,10 @@ dict_table_get_and_increment_handle_count(
/*======================================*/
/* out: table, NULL if
does not exist */
const char* table_name, /* in: table name */
trx_t* trx) /* in: transaction handle or NULL */
const char* table_name) /* in: table name */
{
dict_table_t* table;
UT_NOT_USED(trx);
mutex_enter(&(dict_sys->mutex));
table = dict_table_get_low(table_name);
@@ -890,10 +881,7 @@ dict_table_add_to_cache(
/* Add table to LRU list of tables */
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_table_LRU_trim(); */
}
/**************************************************************************
@@ -1258,38 +1246,6 @@ dict_table_remove_from_cache(
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. */
static
@@ -1519,10 +1475,7 @@ dict_index_add_to_cache(
/* Add the index to the list of indexes stored in the tree */
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_table_LRU_trim(); */
dict_mem_index_free(index);
@@ -2994,7 +2947,8 @@ loop:
if so, immediately reject the command if the table is a
temporary one. For now, this kludge will work. */
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;
rw_lock_create(&(tree->lock));
rw_lock_set_level(&(tree->lock), SYNC_INDEX_TREE);
rw_lock_create(&tree->lock, SYNC_INDEX_TREE);
return(tree);
}

View File

@@ -660,7 +660,7 @@ dict_load_indexes(
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,
ULINT_UNDEFINED);

View File

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

View File

@@ -1,19 +1,29 @@
#!/bin/bash
#
# export current working directory in a format suitable for sending to
# MySQL as a snapshot.
# export current working directory in a format suitable for sending to MySQL
# as a snapshot. also generates the actual snapshot and sends it to MySQL.
set -eu
if [ $# -ne 1 ] ; then
echo "Usage: export.sh revision-number-of-last-snapshot"
die () {
echo $*
exit 1
}
if [ $# -ne 2 ] ; then
die "Usage: export.sh revision-number-of-last-snapshot current-revision-number"
fi
set +u
if test -z $EDITOR; then
die "\$EDITOR is not set"
fi
set -u
rm -rf to-mysql
mkdir -p to-mysql/storage/
svn log -v -r "$1:BASE" > to-mysql/log
svn export . to-mysql/storage/innobase
svn log -v -r "$(($1 + 1)):BASE" > to-mysql/log
svn export -q . to-mysql/storage/innobase
cd to-mysql
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
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;
rw_lock_create(&(space->latch));
rw_lock_set_level(&(space->latch), SYNC_FSP);
rw_lock_create(&space->latch, SYNC_FSP);
HASH_INSERT(fil_space_t, hash, system->spaces, id, space);
@@ -1362,9 +1361,7 @@ fil_system_create(
system = mem_alloc(sizeof(fil_system_t));
mutex_create(&(system->mutex));
mutex_set_level(&(system->mutex), SYNC_ANY_LATCH);
mutex_create(&system->mutex, SYNC_ANY_LATCH);
system->spaces = 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));
for (i = 0; i < n_mutexes; i++) {
mutex_create(table->mutexes + i);
mutex_set_level(table->mutexes + i, sync_level);
mutex_create(table->mutexes + i, sync_level);
}
table->n_mutexes = n_mutexes;

View File

@@ -238,7 +238,8 @@ handlerton innobase_hton = {
NULL, /* Fill FILES table */
HTON_NO_FLAGS,
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_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;
innobase_commit(thd, TRUE);
@@ -1855,224 +1837,9 @@ innobase_commit_complete(
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);
}
#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. */
@@ -2444,8 +2211,7 @@ ha_innobase::open(
/* Get pointer to a table object in InnoDB dictionary cache */
ib_table = dict_table_get_and_increment_handle_count(
norm_name, NULL);
ib_table = dict_table_get_and_increment_handle_count(norm_name);
if (NULL == ib_table) {
ut_print_timestamp(stderr);
@@ -5026,7 +4792,7 @@ ha_innobase::create(
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);

View File

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

View File

@@ -265,17 +265,16 @@ dict_foreign_parse_drop_constraints(
const char*** constraints_to_drop); /* out: id's of the
constraints to drop */
/**************************************************************************
Returns a table object and memoryfixes it. NOTE! This is a high-level
function to be used mainly from outside the 'dict' directory. Inside this
directory dict_table_get_low is usually the appropriate function. */
Returns a table object. NOTE! This is a high-level function to be used
mainly from outside the 'dict' directory. Inside this directory
dict_table_get_low is usually the appropriate function. */
dict_table_t*
dict_table_get(
/*===========*/
/* out: table, NULL if
does not exist */
const char* table_name, /* in: table name */
trx_t* trx); /* in: transaction handle */
const char* table_name); /* in: table name */
/**************************************************************************
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
does not exist */
const char* table_name, /* in: table name */
trx_t* trx); /* in: transaction handle or NULL */
const char* table_name); /* in: table name */
/**************************************************************************
Returns a table object, based on table id, and memoryfixes it. */
Returns a table object based on table id. */
dict_table_t*
dict_table_get_on_id(
@@ -297,21 +295,13 @@ dict_table_get_on_id(
dulint table_id, /* in: table id */
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
dict_table_t*
dict_table_get_on_id_low(
/*=====================*/
/* out: table, NULL if does not exist */
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 */
dulint table_id); /* in: table id */
/**************************************************************************
Checks if a table is in the dictionary cache. */
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
dict_table_t*
dict_table_get_on_id_low(
/*=====================*/
/* out: table, NULL if does not exist */
dulint table_id, /* in: table id */
trx_t* trx) /* in: transaction handle */
dulint table_id) /* in: table id */
{
dict_table_t* table;
ulint fold;
@@ -592,7 +591,6 @@ dict_table_get_on_id_low(
#ifdef UNIV_SYNC_DEBUG
ut_ad(mutex_own(&(dict_sys->mutex)));
#endif /* UNIV_SYNC_DEBUG */
UT_NOT_USED(trx);
/* Look for the table name in the hash table */
fold = ut_fold_dulint(table_id);
@@ -603,32 +601,11 @@ dict_table_get_on_id_low(
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 */
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. */
UNIV_INLINE

View File

@@ -172,10 +172,6 @@ struct dict_tree_struct{
the same memory cache line */
rw_lock_t lock; /* read-write lock protecting the upper levels
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
index tree */
ulint magic_n;/* magic number */
@@ -318,9 +314,6 @@ struct dict_table_struct{
which refer to this table */
UT_LIST_NODE_T(dict_table_t)
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;
/* count of how many handles MySQL has opened
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 */
#define XDES_DESCRIBED_PER_PAGE UNIV_PAGE_SIZE
/* The space low address page map, and also offsets for extent descriptor and
bitmap pages which are repeated always after XDES_DESCRIBED_PER_PAGE more
pages: */
/* The space low address page map */
/*--------------------------------------*/
#define FSP_XDES_OFFSET 0
#define FSP_IBUF_BITMAP_OFFSET 1
/* The following two pages are repeated
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
page number is the number above plus a
multiple of XDES_DESCRIBED_PER_PAGE */
#define FSP_FIRST_INODE_PAGE_NO 2
#define FSP_IBUF_HEADER_PAGE_NO 3
#define FSP_IBUF_TREE_ROOT_PAGE_NO 4
#define FSP_FIRST_INODE_PAGE_NO 2 /* in every tablespace */
/* 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
tablespace 0; its fseg inode is on the page
number FSP_FIRST_INODE_PAGE_NO */
#define FSP_TRX_SYS_PAGE_NO 5
#define FSP_FIRST_RSEG_PAGE_NO 6
#define FSP_DICT_HDR_PAGE_NO 7
#define FSP_TRX_SYS_PAGE_NO 5 /* in tablespace 0 */
#define FSP_FIRST_RSEG_PAGE_NO 6 /* in tablespace 0 */
#define FSP_DICT_HDR_PAGE_NO 7 /* in tablespace 0 */
/*--------------------------------------*/
#ifndef UNIV_NONINL

View File

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

View File

@@ -311,6 +311,28 @@ mem_heap_strdupl(
const char* str, /* in: string to be copied */
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
/**********************************************************************
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
function */
os_thread_id_t* thread_id); /* out: id of the created
thread */
thread, or NULL */
int
os_thread_join(
/*===========*/

View File

@@ -531,6 +531,16 @@ pars_info_add_function(
pars_user_func_cb_t func, /* in: function address */
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.*/
@@ -553,6 +563,17 @@ pars_info_get_bound_lit(
pars_info_t* info, /* in: info struct */
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(). */
struct pars_info_struct {
@@ -562,6 +583,8 @@ struct pars_info_struct {
(pars_user_func_t*) */
ib_vector_t* bound_lits; /* bound literals, or NULL
(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),
que_graph_free() will free us */
@@ -583,6 +606,12 @@ struct pars_bound_lit_struct {
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 pars_res_word_struct{
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 */
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_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_user_func_struct pars_user_func_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_tab_struct sym_tab_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
index, and we were able to position pcur on
it */
dict_table_t* table; /* table where purge is done; NOTE that the
table has to be released explicitly with
dict_table_release */
dict_table_t* table; /* table where purge is done */
ulint cmpl_info;/* compiler analysis info of an update */
upd_t* update; /* update vector for a clustered index record */
dtuple_t* ref; /* NULL, or row reference to the next row to

View File

@@ -84,9 +84,7 @@ struct undo_node_struct{
record */
btr_pcur_t pcur; /* persistent cursor used in searching the
clustered index record */
dict_table_t* table; /* table where undo is done; NOTE that the
table has to be released explicitly with
dict_table_release */
dict_table_t* table; /* table where undo is done */
ulint cmpl_info;/* compiler analysis of an update */
upd_t* update; /* update vector for a clustered index record */
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_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_lock_waits;
extern ibool srv_print_buf_io;
extern ibool srv_print_log_io;
extern ibool srv_print_parsed_sql;
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_fatal_semaphore_wait_threshold;
extern ulint srv_dml_needed_delay;
@@ -365,11 +344,7 @@ srv_release_threads(
/*************************************************************************
The master thread controlling the server. */
#ifndef __WIN__
void*
#else
ulint
#endif
os_thread_ret_t
srv_master_thread(
/*==============*/
/* 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.
This also prints the info output by various InnoDB monitors. */
#ifndef __WIN__
void*
#else
ulint
#endif
os_thread_ret_t
srv_lock_timeout_and_monitor_thread(
/*================================*/
/* 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
too long. These can be used to track bugs which cause hangs. */
#ifndef __WIN__
void*
#else
ulint
#endif
os_thread_ret_t
srv_error_monitor_thread(
/*=====================*/
/* out: a dummy parameter */
@@ -567,9 +534,6 @@ struct export_var_struct{
/* The server system 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 */
UT_LIST_BASE_NODE_T(que_thr_t)
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
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. */
#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,6 +74,7 @@ void
rw_lock_create_func(
/*================*/
rw_lock_t* lock, /* in: pointer to memory */
ulint level, /* in: level */
const char* cfile_name, /* in: file name where created */
ulint cline, /* in: file line where created */
const char* cmutex_name); /* in: mutex name */
@@ -299,14 +300,6 @@ rw_lock_x_unlock_direct(
/*====================*/
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
mutex, so the caller must be sure it is not changed during the call. */
UNIV_INLINE
@@ -448,8 +441,8 @@ struct rw_lock_struct {
/* In the debug version: pointer to the debug
info list of the lock */
#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 */
ulint cline; /* Line where created */
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
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
@@ -51,6 +51,7 @@ void
mutex_create_func(
/*==============*/
mutex_t* mutex, /* in: pointer to memory */
ulint level, /* in: level */
const char* cfile_name, /* in: file name where created */
ulint cline, /* in: file line where created */
const char* cmutex_name); /* in: mutex name */
@@ -155,14 +156,6 @@ mutex_validate(
/*===========*/
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
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. */
@@ -171,8 +164,8 @@ void
sync_thread_add_level(
/*==================*/
void* latch, /* in: pointer to a mutex or an rw-lock */
ulint level); /* in: level in the latching order; if SYNC_LEVEL_NONE,
nothing is done */
ulint level); /* in: level in the latching order; if
SYNC_LEVEL_VARYING, nothing is done */
/**********************************************************************
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_NO_ORDER_CHECK 3000 /* this can be used to suppress
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
this in X-mode, implicit or backround
operations purge, rollback, foreign
@@ -426,6 +424,7 @@ or row lock! */
#define SYNC_TRX_SYS_HEADER 290
#define SYNC_LOG 170
#define SYNC_RECV 168
#define SYNC_WORK_QUEUE 161
#define SYNC_SEARCH_SYS 160 /* NOTE that if we have a memory
heap that can be extended to the
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
thread which locked the mutex. */
#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 mutex created */
ulint cline; /* Line where created */
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.
Note: this is done in a background thread. */
#ifndef __WIN__
void*
#else
ulint
#endif
os_thread_ret_t
trx_rollback_or_clean_all_without_sess(
/*===================================*/
/* out: a dummy parameter */

View File

@@ -75,6 +75,15 @@ multiple tablespace format. */
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. */
UNIV_INLINE

View File

@@ -82,17 +82,18 @@ memory is read outside the allocated blocks. */
/* Make a non-inline debug version */
#if 0
#define UNIV_DEBUG
/*
#define UNIV_MEM_DEBUG
#define UNIV_IBUF_DEBUG
#define UNIV_SYNC_DEBUG
#define UNIV_SEARCH_DEBUG
#define UNIV_SYNC_PERF_STAT
#define UNIV_SEARCH_PERF_STAT
#define UNIV_SRV_PRINT_LATCH_WAITS;
#define UNIV_SRV_PRINT_LATCH_WAITS
#define UNIV_ZIP_DEBUG
*/
#endif
#define UNIV_LIGHT_MEM_DEBUG
#define YYDEBUG 1
@@ -274,6 +275,18 @@ it is read or written. */
/* Compile-time constant of the given array's size. */
#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 "ut0dbg.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));
mutex_create(&(log_sys->mutex));
mutex_set_level(&(log_sys->mutex), SYNC_LOG);
mutex_create(&log_sys->mutex, SYNC_LOG);
mutex_enter(&(log_sys->mutex));
@@ -798,8 +797,7 @@ log_init(void)
log_sys->last_checkpoint_lsn = log_sys->lsn;
log_sys->n_pending_checkpoint_writes = 0;
rw_lock_create(&(log_sys->checkpoint_lock));
rw_lock_set_level(&(log_sys->checkpoint_lock), SYNC_NO_ORDER_CHECK);
rw_lock_create(&log_sys->checkpoint_lock, SYNC_NO_ORDER_CHECK);
log_sys->checkpoint_buf = ut_align(
mem_alloc(2 * OS_FILE_LOG_BLOCK_SIZE),
@@ -815,8 +813,7 @@ log_init(void)
log_sys->n_pending_archive_ios = 0;
rw_lock_create(&(log_sys->archive_lock));
rw_lock_set_level(&(log_sys->archive_lock), SYNC_NO_ORDER_CHECK);
rw_lock_create(&log_sys->archive_lock, SYNC_NO_ORDER_CHECK);
log_sys->archive_buf = NULL;

View File

@@ -113,8 +113,7 @@ recv_sys_create(void)
recv_sys = mem_alloc(sizeof(recv_sys_t));
mutex_create(&(recv_sys->mutex));
mutex_set_level(&(recv_sys->mutex), SYNC_RECV);
mutex_create(&recv_sys->mutex, SYNC_RECV);
recv_sys->heap = NULL;
recv_sys->addr_hash = NULL;
@@ -2969,7 +2968,6 @@ recv_recovery_from_checkpoint_finish(void)
/*======================================*/
{
int i;
os_thread_id_t recovery_thread_id;
/* Apply the hashed log records to the respective file pages */
@@ -3013,7 +3011,7 @@ recv_recovery_from_checkpoint_finish(void)
session */
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 */
ut_a(FALSE == mem_hash_initialized);
mutex_create(&mem_hash_mutex);
mutex_set_level(&mem_hash_mutex, SYNC_MEM_HASH);
mutex_create(&mem_hash_mutex, SYNC_MEM_HASH);
for (i = 0; i < MEM_HASH_SIZE; i++) {
UT_LIST_INIT(*mem_hash_get_nth_cell(i));

View File

@@ -110,8 +110,46 @@ mem_heap_strdup(
mem_heap_t* heap, /* in: memory heap where string is allocated */
const char* str) /* in: string to be copied */
{
ulint len = strlen(str) + 1;
return(memcpy(mem_heap_alloc(heap, len), str, len));
return(mem_heap_dup(heap, str, strlen(str) + 1));
}
/**************************************************************************
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->size = size;
mutex_create(&(pool->mutex));
mutex_set_level(&(pool->mutex), SYNC_MEM_POOL);
mutex_create(&pool->mutex, SYNC_MEM_POOL);
/* Initialize the free lists */

View File

@@ -1632,6 +1632,30 @@ t2 CREATE TABLE `t2` (
CONSTRAINT `t2_ibfk_2` FOREIGN KEY (`b`) REFERENCES `t1` (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1
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;
ERROR 42S21: Duplicate column name 'c'
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
t2 CREATE TABLE `t2` (
`a` int(11) DEFAULT NULL,
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`)
KEY `t2_ibfk_0` (`a`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1
DROP TABLE t2,t1;
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
DROP TABLE t2;
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,
primary key(f_id, id)) engine=innodb;
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
#
@@ -1133,6 +1146,41 @@ show create table t2;
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
#
@@ -2106,6 +2154,42 @@ UPDATE t1 SET field1 = 'other' WHERE field2 = 'somevalu';
DROP TABLE t2;
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,
primary key(f_id, id)) engine=innodb;
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
/**************************************************************************
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
thread. */
@@ -3716,7 +3747,6 @@ os_aio_simulated_handle(
ibool ret;
ulint n;
ulint i;
ulint len2;
segment = os_aio_get_array_and_local_segment(&array, global_segment);
@@ -3924,34 +3954,15 @@ consecutive_loop:
ut_error;
}
/* Do a 'last millisecond' check that the page end
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");
}
}
os_file_check_page_trailers(combined_buf, total_len);
}
ret = os_file_write(slot->name, slot->file, combined_buf,
slot->offset, slot->offset_high, total_len);
if (array == os_aio_write_array) {
os_file_check_page_trailers(combined_buf, total_len);
}
} else {
ret = os_file_read(slot->file, combined_buf,
slot->offset, slot->offset_high, total_len);

View File

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

File diff suppressed because it is too large Load Diff

View File

@@ -84,6 +84,7 @@ string_append(
DIGIT [0-9]
ID [a-z_A-Z][a-z_A-Z0-9]*
BOUND_LIT \:[a-z_A-Z0-9]+
BOUND_ID \$[a-z_A-Z0-9]+
%x comment
%x quoted
@@ -111,6 +112,13 @@ BOUND_LIT \:[a-z_A-Z0-9]+
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
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->funcs = NULL;
info->bound_lits = NULL;
info->bound_ids = NULL;
info->graph_owns_us = TRUE;
return(info);
@@ -1963,6 +1964,8 @@ pars_info_add_literal(
{
pars_bound_lit_t* pbl;
ut_ad(!pars_info_get_bound_lit(info, name));
pbl = mem_heap_alloc(info->heap, sizeof(*pbl));
pbl->name = name;
@@ -2053,6 +2056,8 @@ pars_info_add_function(
{
pars_user_func_t* puf;
ut_ad(!pars_info_get_user_func(info, name));
puf = mem_heap_alloc(info->heap, sizeof(*puf));
puf->name = name;
@@ -2066,6 +2071,32 @@ pars_info_add_function(
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.*/
@@ -2127,3 +2158,34 @@ pars_info_get_bound_lit(
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);
}
/**********************************************************************
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);
/*-------------------------*/
/* 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++;
if (next_thr != thr) {

View File

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

View File

@@ -2384,11 +2384,9 @@ row_discard_tablespace_for_mysql(
dict_foreign_t* foreign;
dulint new_id;
dict_table_t* table;
que_thr_t* thr;
que_t* graph = NULL;
ibool success;
ulint err;
char* buf;
pars_info_t* info = NULL;
/* How do we prevent crashes caused by ongoing operations on the table? Old
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
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());
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);
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 */
lock_reset_all_on_table(table);
graph->trx = trx;
trx->graph = NULL;
info = pars_info_create();
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));
que_run_threads(thr);
err = trx->error_state;
err = que_eval_sql(info,
"PROCEDURE DISCARD_TABLESPACE_PROC () IS\n"
"old_id CHAR;\n"
"BEGIN\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"
, trx);
if (err != 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;
}
}
funct_exit:
row_mysql_unlock_data_dictionary(trx);
if (graph) {
que_graph_free(graph);
}
trx_commit_for_mysql(trx);
trx->op_info = "";
@@ -2738,9 +2702,7 @@ row_truncate_table_for_mysql(
btr_pcur_t pcur;
mtr_t mtr;
dulint new_id;
char* sql;
que_thr_t* thr;
que_t* graph = NULL;
pars_info_t* info = NULL;
/* How do we prevent crashes caused by ongoing operations on the table? Old
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
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(table);
@@ -2952,35 +2890,27 @@ do not allow the TRUNCATE. We also reserve the data dictionary latch. */
btr_pcur_close(&pcur);
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);
graph->trx = trx;
trx->graph = NULL;
new_id = dict_hdr_get_new_id(DICT_HDR_TABLE_ID);
graph->fork_type = QUE_FORK_MYSQL_INTERFACE;
info = pars_info_create();
thr = que_fork_start_command(graph);
ut_a(thr);
pars_info_add_dulint_literal(info, "old_id", table->id);
pars_info_add_dulint_literal(info, "new_id", new_id);
que_run_threads(thr);
que_graph_free(graph);
err = trx->error_state;
err = que_eval_sql(info,
"PROCEDURE RENUMBER_TABLESPACE_PROC () IS\n"
"BEGIN\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) {
trx->error_state = DB_SUCCESS;
@@ -3030,83 +2960,13 @@ row_drop_table_for_mysql(
dict_foreign_t* foreign;
dict_table_t* table;
ulint space_id;
que_thr_t* thr;
que_t* graph;
ulint err;
const char* table_name;
ulint namelen;
char* dir_path_of_temp_table = NULL;
ibool success;
ibool locked_dictionary = FALSE;
char* quoted_name;
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";
pars_info_t* info = NULL;
ut_a(name != NULL);
@@ -3161,14 +3021,6 @@ row_drop_table_for_mysql(
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:
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));
#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);
if (!table) {
@@ -3319,18 +3161,80 @@ fputs(" InnoDB: You are trying to drop table ", stderr);
trx->dict_operation = TRUE;
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) {
ut_a(err == DB_OUT_OF_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;
} else {
@@ -3408,8 +3312,6 @@ funct_exit:
mem_free(dir_path_of_temp_table);
}
que_graph_free(graph);
trx_commit_for_mysql(trx);
trx->op_info = "";
@@ -3514,6 +3416,62 @@ row_is_mysql_tmp_table_name(
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. */
@@ -3526,100 +3484,13 @@ row_rename_table_for_mysql(
trx_t* trx) /* in: transaction handle */
{
dict_table_t* table;
que_thr_t* thr;
que_t* graph = NULL;
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;
const char** constraints_to_drop = NULL;
ulint n_constraints_to_drop = 0;
ibool recovering_temp_table = FALSE;
ibool old_is_tmp, new_is_tmp;
ulint len;
ulint i;
ibool success;
/* length of database name; 0 if not renaming to a temporary table */
ulint db_name_len;
char* sql;
char* sqlend;
pars_info_t* info = NULL;
ut_ad(trx->mysql_thread_id == os_thread_get_curr_id());
ut_a(old_name != NULL);
@@ -3697,13 +3568,7 @@ row_rename_table_for_mysql(
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) {
db_name_len = dict_get_db_name_len(old_name) + 1;
/* MySQL is doing an ALTER TABLE command and it renames the
original table to a temporary table name. We want to preserve
the original foreign key constraint definitions despite the
@@ -3713,110 +3578,124 @@ row_rename_table_for_mysql(
heap = mem_heap_create(100);
err = dict_foreign_parse_drop_constraints(heap, trx,
table,
&n_constraints_to_drop,
&constraints_to_drop);
table, &n_constraints_to_drop, &constraints_to_drop);
if (err != DB_SUCCESS) {
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, '\''));
/* 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. */
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_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++) {
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;
}
err = row_delete_constraint(constraints_to_drop[i],
db_name, heap, trx);
sql = sqlend = mem_alloc(len + 1);
memcpy(sql, str1, (sizeof str1) - 1);
sqlend += (sizeof str1) - 1;
sqlend = ut_strcpyq(sqlend, '\'', new_name);
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) {
/* Internally, old format < 4.0.18 constraints have as the
constraint id <number>_<number>, while new format constraints
have <databasename>/<constraintname>. */
for (i = 0; i < n_constraints_to_drop; i++) {
memcpy(sqlend, str4a1, (sizeof str4a1) - 1);
sqlend += (sizeof str4a1) - 1;
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 this happens to be an old format
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;
if (err != DB_SUCCESS) {
break;
}
}
}
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_DUPLICATE_KEY) {
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 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);
if (!success) {
trx->error_state = DB_SUCCESS;
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,
old_name, FALSE));
trx->error_state = DB_SUCCESS;
trx_general_rollback_for_mysql(trx, FALSE,
NULL);
trx_general_rollback_for_mysql(trx, FALSE, NULL);
trx->error_state = DB_SUCCESS;
}
}
funct_exit:
if (!recovering_temp_table) {
row_mysql_unlock_data_dictionary(trx);
}
if (graph) {
que_graph_free(graph);
}
if (UNIV_LIKELY_NULL(heap)) {
mem_heap_free(heap);
}

View File

@@ -521,7 +521,7 @@ row_purge_parse_undo_rec(
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));

View File

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

View File

@@ -202,8 +202,7 @@ row_upd_check_references_constraints(
foreign->n_fields))) {
if (foreign->foreign_table == NULL) {
dict_table_get(foreign->foreign_table_name,
trx);
dict_table_get(foreign->foreign_table_name);
}
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_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
i/o handler thread */
@@ -873,11 +849,9 @@ srv_init(void)
srv_sys = mem_alloc(sizeof(srv_sys_t));
kernel_mutex_temp = mem_alloc(sizeof(mutex_t));
mutex_create(&kernel_mutex);
mutex_set_level(&kernel_mutex, SYNC_KERNEL);
mutex_create(&kernel_mutex, SYNC_KERNEL);
mutex_create(&srv_innodb_monitor_mutex);
mutex_set_level(&srv_innodb_monitor_mutex, SYNC_NO_ORDER_CHECK);
mutex_create(&srv_innodb_monitor_mutex, SYNC_NO_ORDER_CHECK);
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_sys->operational = os_event_create(NULL);
ut_a(srv_sys->operational);
UT_LIST_INIT(srv_sys->tasks);
/* 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.
This also prints the info output by various InnoDB monitors. */
#ifndef __WIN__
void*
#else
ulint
#endif
os_thread_ret_t
srv_lock_timeout_and_monitor_thread(
/*================================*/
/* out: a dummy parameter */
@@ -2023,22 +1989,15 @@ exit_func:
thread should always use that to exit and not use return() to exit. */
os_thread_exit(NULL);
#ifndef __WIN__
return(NULL);
#else
return(0);
#endif
OS_THREAD_DUMMY_RETURN;
}
/*************************************************************************
A thread which prints warnings about semaphore waits which have lasted
too long. These can be used to track bugs which cause hangs. */
#ifndef __WIN__
void*
#else
ulint
#endif
os_thread_ret_t
srv_error_monitor_thread(
/*=====================*/
/* out: a dummy parameter */
@@ -2120,11 +2079,7 @@ loop:
os_thread_exit(NULL);
#ifndef __WIN__
return(NULL);
#else
return(0);
#endif
OS_THREAD_DUMMY_RETURN;
}
/***********************************************************************
@@ -2169,11 +2124,7 @@ srv_wake_master_thread(void)
/*************************************************************************
The master thread controlling the server. */
#ifndef __WIN__
void*
#else
ulint
#endif
os_thread_ret_t
srv_master_thread(
/*==============*/
/* out: a dummy parameter */
@@ -2212,7 +2163,6 @@ srv_master_thread(
mutex_exit(&kernel_mutex);
os_event_set(srv_sys->operational);
loop:
/*****************************************************************/
/* ---- When there is database activity by users, we cycle in this
@@ -2607,22 +2557,9 @@ suspend_thread:
os_thread_exit(NULL);
}
/* When there is user activity, InnoDB will set the event and the main
thread goes back to loop: */
/* When there is user activity, InnoDB will set the event and the
main thread goes back to 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 */

View File

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

View File

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

View File

@@ -89,19 +89,19 @@ void
rw_lock_create_func(
/*================*/
rw_lock_t* lock, /* in: pointer to memory */
ulint level, /* in: level */
const char* cfile_name, /* in: file name where created */
ulint cline, /* in: file line where created */
const char* cmutex_name) /* in: mutex name */
{
/* If this is the very first time a synchronization
object is created, then the following call initializes
the sync system. */
/* If this is the very first time a synchronization object is
created, then the following call initializes the sync system. */
mutex_create(rw_lock_get_mutex(lock));
mutex_set_level(rw_lock_get_mutex(lock), SYNC_NO_ORDER_CHECK);
mutex_create(rw_lock_get_mutex(lock), SYNC_NO_ORDER_CHECK);
lock->mutex.cfile_name = cfile_name;
lock->mutex.cline = cline;
#ifndef UNIV_HOTBACKUP
lock->mutex.cmutex_name = cmutex_name;
lock->mutex.mutex_type = 1;
@@ -116,9 +116,10 @@ rw_lock_create_func(
#ifdef UNIV_SYNC_DEBUG
UT_LIST_INIT(lock->debug_list);
lock->level = SYNC_LEVEL_NONE;
#endif /* UNIV_SYNC_DEBUG */
lock->level = level;
lock->magic_n = RW_LOCK_MAGIC_N;
lock->cfile_name = cfile_name;
@@ -669,18 +670,6 @@ rw_lock_remove_debug_info(
}
#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
/**********************************************************************
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_t* mutex, /* in: pointer to memory */
ulint level, /* in: level */
const char* cfile_name, /* in: file name where created */
ulint cline, /* in: file line where created */
const char* cmutex_name) /* in: mutex name */
@@ -218,7 +219,7 @@ mutex_create_func(
mutex->line = 0;
mutex->file_name = "not yet reserved";
#endif /* UNIV_SYNC_DEBUG */
mutex->level = SYNC_LEVEL_NONE;
mutex->level = level;
mutex->cfile_name = cfile_name;
mutex->cline = cline;
#ifndef UNIV_HOTBACKUP
@@ -598,19 +599,6 @@ mutex_get_debug_info(
}
#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
/**********************************************************************
Checks that the current thread owns the mutex. Works only in the debug
@@ -979,8 +967,8 @@ void
sync_thread_add_level(
/*==================*/
void* latch, /* in: pointer to a mutex or an rw-lock */
ulint level) /* in: level in the latching order; if SYNC_LEVEL_NONE,
nothing is done */
ulint level) /* in: level in the latching order; if
SYNC_LEVEL_VARYING, nothing is done */
{
sync_level_t* array;
sync_level_t* slot;
@@ -1002,7 +990,7 @@ sync_thread_add_level(
return;
}
if (level == SYNC_LEVEL_NONE) {
if (level == SYNC_LEVEL_VARYING) {
return;
}
@@ -1050,6 +1038,9 @@ sync_thread_add_level(
case SYNC_RECV:
ut_a(sync_thread_levels_g(array, SYNC_RECV));
break;
case SYNC_WORK_QUEUE:
ut_a(sync_thread_levels_g(array, SYNC_WORK_QUEUE));
break;
case SYNC_LOG:
ut_a(sync_thread_levels_g(array, SYNC_LOG));
break;
@@ -1290,21 +1281,17 @@ sync_init(void)
/* Init the mutex list and create the mutex to protect it. */
UT_LIST_INIT(mutex_list);
mutex_create(&mutex_list_mutex);
mutex_set_level(&mutex_list_mutex, SYNC_NO_ORDER_CHECK);
mutex_create(&mutex_list_mutex, SYNC_NO_ORDER_CHECK);
mutex_create(&sync_thread_mutex);
mutex_set_level(&sync_thread_mutex, SYNC_NO_ORDER_CHECK);
mutex_create(&sync_thread_mutex, SYNC_NO_ORDER_CHECK);
/* Init the rw-lock list and create the mutex to protect it. */
UT_LIST_INIT(rw_lock_list);
mutex_create(&rw_lock_list_mutex);
mutex_set_level(&rw_lock_list_mutex, SYNC_NO_ORDER_CHECK);
mutex_create(&rw_lock_list_mutex, SYNC_NO_ORDER_CHECK);
#ifdef UNIV_SYNC_DEBUG
mutex_create(&rw_lock_debug_mutex);
mutex_set_level(&rw_lock_debug_mutex, SYNC_NO_ORDER_CHECK);
mutex_create(&rw_lock_debug_mutex, SYNC_NO_ORDER_CHECK);
rw_lock_debug_event = os_event_create(NULL);
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);
mutex_create(&thr_local_mutex);
mutex_set_level(&thr_local_mutex, SYNC_THR_LOCAL);
mutex_create(&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->next_stored = FALSE;
rw_lock_create(&(purge_sys->latch));
rw_lock_set_level(&(purge_sys->latch), SYNC_PURGE_LATCH);
rw_lock_create(&purge_sys->latch, SYNC_PURGE_LATCH);
mutex_create(&(purge_sys->mutex));
mutex_set_level(&(purge_sys->mutex), SYNC_PURGE_SYS);
mutex_create(&purge_sys->mutex, SYNC_PURGE_SYS);
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.
Note: this is done in a background thread. */
#ifndef __WIN__
void*
#else
ulint
#endif
os_thread_ret_t
trx_rollback_or_clean_all_without_sess(
/*===================================*/
/* out: a dummy parameter */
@@ -544,7 +540,7 @@ loop:
(ulong) ut_dulint_get_high(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) {
fputs("InnoDB: Table found: dropping table ", stderr);
@@ -576,13 +572,7 @@ leave_function:
os_thread_exit(NULL);
/* The following is dummy code to keep the compiler happy: */
#ifndef __WIN__
return(NULL);
#else
return(0);
#endif
OS_THREAD_DUMMY_RETURN;
}
/***********************************************************************

View File

@@ -147,8 +147,7 @@ trx_rseg_mem_create(
rseg->space = space;
rseg->page_no = page_no;
mutex_create(&(rseg->mutex));
mutex_set_level(&(rseg->mutex), SYNC_RSEG);
mutex_create(&rseg->mutex, SYNC_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;
/********************************************************************
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. */
static
@@ -71,8 +101,7 @@ trx_doublewrite_init(
os_do_not_call_flush_at_each_write = TRUE;
#endif /* UNIV_DO_FLUSH */
mutex_create(&(trx_doublewrite->mutex));
mutex_set_level(&(trx_doublewrite->mutex), SYNC_DOUBLEWRITE);
mutex_create(&trx_doublewrite->mutex, SYNC_DOUBLEWRITE);
trx_doublewrite->first_free = 0;

View File

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

View File

@@ -19,6 +19,6 @@ include ../include/Makefile.i
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 =

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);
}