mirror of
https://github.com/MariaDB/server.git
synced 2025-08-01 03:47:19 +03:00
Merge mysql-5.5-innodb -> mysql-5.5
This commit is contained in:
73
mysql-test/suite/innodb/r/innodb_bug60196.result
Executable file
73
mysql-test/suite/innodb/r/innodb_bug60196.result
Executable file
@ -0,0 +1,73 @@
|
||||
CREATE TABLE Bug_60196_FK1 (Primary_Key INT PRIMARY KEY) ENGINE=InnoDB;
|
||||
CREATE TABLE Bug_60196_FK2 (Primary_Key INT PRIMARY KEY) ENGINE=InnoDB;
|
||||
CREATE TABLE Bug_60196 (
|
||||
FK1_Key INT NOT NULL,
|
||||
FK2_Key INT NOT NULL,
|
||||
PRIMARY KEY (FK2_Key, FK1_Key),
|
||||
KEY FK1_Key (FK1_Key),
|
||||
KEY FK2_Key (FK2_Key),
|
||||
CONSTRAINT FK_FK1 FOREIGN KEY (FK1_Key)
|
||||
REFERENCES Bug_60196_FK1 (Primary_Key)
|
||||
ON DELETE CASCADE
|
||||
ON UPDATE CASCADE,
|
||||
CONSTRAINT FK_FK2 FOREIGN KEY (FK2_Key)
|
||||
REFERENCES Bug_60196_FK2 (Primary_Key)
|
||||
ON DELETE CASCADE
|
||||
ON UPDATE CASCADE
|
||||
) ENGINE=InnoDB;
|
||||
INSERT INTO Bug_60196_FK1 VALUES (1), (2), (3), (4), (5);
|
||||
INSERT INTO Bug_60196_FK2 VALUES (1), (2), (3), (4), (5);
|
||||
INSERT INTO Bug_60196 VALUES (1, 1);
|
||||
INSERT INTO Bug_60196 VALUES (1, 2);
|
||||
INSERT INTO Bug_60196 VALUES (1, 3);
|
||||
INSERT INTO Bug_60196 VALUES (1, 99);
|
||||
ERROR 23000: Cannot add or update a child row: a foreign key constraint fails (`test`.`bug_60196`, CONSTRAINT `FK_FK2` FOREIGN KEY (`FK2_Key`) REFERENCES `Bug_60196_FK2` (`Primary_Key`) ON DELETE CASCADE ON UPDATE CASCADE)
|
||||
INSERT INTO Bug_60196 VALUES (99, 1);
|
||||
ERROR 23000: Cannot add or update a child row: a foreign key constraint fails (`test`.`bug_60196`, CONSTRAINT `FK_FK1` FOREIGN KEY (`FK1_Key`) REFERENCES `Bug_60196_FK1` (`Primary_Key`) ON DELETE CASCADE ON UPDATE CASCADE)
|
||||
SELECT * FROM bug_60196_FK1;
|
||||
Primary_Key
|
||||
1
|
||||
2
|
||||
3
|
||||
4
|
||||
5
|
||||
SELECT * FROM bug_60196_FK2;
|
||||
Primary_Key
|
||||
1
|
||||
2
|
||||
3
|
||||
4
|
||||
5
|
||||
SELECT * FROM bug_60196;
|
||||
FK1_Key FK2_Key
|
||||
1 1
|
||||
1 2
|
||||
1 3
|
||||
# Stop server
|
||||
# Restart server.
|
||||
#
|
||||
# Try to insert more to the example table with foreign keys.
|
||||
# Bug60196 causes the foreign key file not to be found after
|
||||
# the resstart above.
|
||||
#
|
||||
SELECT * FROM Bug_60196;
|
||||
FK1_Key FK2_Key
|
||||
1 1
|
||||
1 2
|
||||
1 3
|
||||
INSERT INTO Bug_60196 VALUES (2, 1);
|
||||
INSERT INTO Bug_60196 VALUES (2, 2);
|
||||
INSERT INTO Bug_60196 VALUES (2, 3);
|
||||
SELECT * FROM Bug_60196;
|
||||
FK1_Key FK2_Key
|
||||
1 1
|
||||
1 2
|
||||
1 3
|
||||
2 1
|
||||
2 2
|
||||
2 3
|
||||
|
||||
# Clean up.
|
||||
DROP TABLE Bug_60196;
|
||||
DROP TABLE Bug_60196_FK1;
|
||||
DROP TABLE Bug_60196_FK2;
|
1
mysql-test/suite/innodb/t/innodb_bug60196-master.opt
Executable file
1
mysql-test/suite/innodb/t/innodb_bug60196-master.opt
Executable file
@ -0,0 +1 @@
|
||||
--lower-case-table-names=2
|
87
mysql-test/suite/innodb/t/innodb_bug60196.test
Executable file
87
mysql-test/suite/innodb/t/innodb_bug60196.test
Executable file
@ -0,0 +1,87 @@
|
||||
# Bug#60196 - Setting lowercase_table_names to 2 on Windows causing
|
||||
# Foreign Key problems after an engine is restarted.
|
||||
|
||||
# This test case needs InnoDB, a lowercase file system,
|
||||
# lower-case-table-names=2, and cannot use the embedded server
|
||||
# because it restarts the server.
|
||||
--source include/not_embedded.inc
|
||||
--source include/have_lowercase2.inc
|
||||
--source include/have_case_insensitive_file_system.inc
|
||||
--source include/have_innodb.inc
|
||||
|
||||
#
|
||||
# Create test data.
|
||||
#
|
||||
CREATE TABLE Bug_60196_FK1 (Primary_Key INT PRIMARY KEY) ENGINE=InnoDB;
|
||||
CREATE TABLE Bug_60196_FK2 (Primary_Key INT PRIMARY KEY) ENGINE=InnoDB;
|
||||
CREATE TABLE Bug_60196 (
|
||||
FK1_Key INT NOT NULL,
|
||||
FK2_Key INT NOT NULL,
|
||||
PRIMARY KEY (FK2_Key, FK1_Key),
|
||||
KEY FK1_Key (FK1_Key),
|
||||
KEY FK2_Key (FK2_Key),
|
||||
CONSTRAINT FK_FK1 FOREIGN KEY (FK1_Key)
|
||||
REFERENCES Bug_60196_FK1 (Primary_Key)
|
||||
ON DELETE CASCADE
|
||||
ON UPDATE CASCADE,
|
||||
CONSTRAINT FK_FK2 FOREIGN KEY (FK2_Key)
|
||||
REFERENCES Bug_60196_FK2 (Primary_Key)
|
||||
ON DELETE CASCADE
|
||||
ON UPDATE CASCADE
|
||||
) ENGINE=InnoDB;
|
||||
INSERT INTO Bug_60196_FK1 VALUES (1), (2), (3), (4), (5);
|
||||
INSERT INTO Bug_60196_FK2 VALUES (1), (2), (3), (4), (5);
|
||||
INSERT INTO Bug_60196 VALUES (1, 1);
|
||||
INSERT INTO Bug_60196 VALUES (1, 2);
|
||||
INSERT INTO Bug_60196 VALUES (1, 3);
|
||||
--error ER_NO_REFERENCED_ROW_2
|
||||
INSERT INTO Bug_60196 VALUES (1, 99);
|
||||
--error ER_NO_REFERENCED_ROW_2
|
||||
INSERT INTO Bug_60196 VALUES (99, 1);
|
||||
|
||||
SELECT * FROM bug_60196_FK1;
|
||||
SELECT * FROM bug_60196_FK2;
|
||||
SELECT * FROM bug_60196;
|
||||
|
||||
--echo # Stop server
|
||||
|
||||
# Write file to make mysql-test-run.pl wait for the server to stop
|
||||
-- exec echo "wait" > $MYSQLTEST_VARDIR/tmp/mysqld.1.expect
|
||||
|
||||
# Send a shutdown request to the server
|
||||
-- shutdown_server 10
|
||||
|
||||
# Call script that will poll the server waiting for it to disapear
|
||||
-- source include/wait_until_disconnected.inc
|
||||
|
||||
--echo # Restart server.
|
||||
|
||||
# Write file to make mysql-test-run.pl start up the server again
|
||||
--exec echo "restart" > $MYSQLTEST_VARDIR/tmp/mysqld.1.expect
|
||||
|
||||
# Turn on reconnect
|
||||
--enable_reconnect
|
||||
|
||||
# Call script that will poll the server waiting for it to be back online again
|
||||
--source include/wait_until_connected_again.inc
|
||||
|
||||
# Turn off reconnect again
|
||||
--disable_reconnect
|
||||
|
||||
--echo #
|
||||
--echo # Try to insert more to the example table with foreign keys.
|
||||
--echo # Bug60196 causes the foreign key file not to be found after
|
||||
--echo # the resstart above.
|
||||
--echo #
|
||||
SELECT * FROM Bug_60196;
|
||||
INSERT INTO Bug_60196 VALUES (2, 1);
|
||||
INSERT INTO Bug_60196 VALUES (2, 2);
|
||||
INSERT INTO Bug_60196 VALUES (2, 3);
|
||||
SELECT * FROM Bug_60196;
|
||||
|
||||
--echo
|
||||
--echo # Clean up.
|
||||
DROP TABLE Bug_60196;
|
||||
DROP TABLE Bug_60196_FK1;
|
||||
DROP TABLE Bug_60196_FK2;
|
||||
|
@ -241,7 +241,6 @@ SET(INNOBASE_SOURCES btr/btr0btr.c btr/btr0cur.c btr/btr0pcur.c btr/btr0sea.c
|
||||
row/row0sel.c row/row0uins.c row/row0umod.c row/row0undo.c row/row0upd.c row/row0vers.c
|
||||
srv/srv0srv.c srv/srv0start.c
|
||||
sync/sync0arr.c sync/sync0rw.c sync/sync0sync.c
|
||||
thr/thr0loc.c
|
||||
trx/trx0i_s.c trx/trx0purge.c trx/trx0rec.c trx/trx0roll.c trx/trx0rseg.c
|
||||
trx/trx0sys.c trx/trx0trx.c trx/trx0undo.c
|
||||
usr/usr0sess.c
|
||||
|
@ -402,7 +402,7 @@ btr_cur_search_to_nth_level(
|
||||
|
||||
ut_ad(level == 0 || mode == PAGE_CUR_LE);
|
||||
ut_ad(dict_index_check_search_tuple(index, tuple));
|
||||
ut_ad(!dict_index_is_ibuf(index) || ibuf_inside());
|
||||
ut_ad(!dict_index_is_ibuf(index) || ibuf_inside(mtr));
|
||||
ut_ad(dtuple_check_typed(tuple));
|
||||
|
||||
#ifdef UNIV_DEBUG
|
||||
@ -4904,27 +4904,45 @@ btr_copy_blob_prefix(
|
||||
|
||||
/*******************************************************************//**
|
||||
Copies the prefix of a compressed BLOB. The clustered index record
|
||||
that points to this BLOB must be protected by a lock or a page latch. */
|
||||
that points to this BLOB must be protected by a lock or a page latch.
|
||||
@return number of bytes written to buf */
|
||||
static
|
||||
void
|
||||
ulint
|
||||
btr_copy_zblob_prefix(
|
||||
/*==================*/
|
||||
z_stream* d_stream,/*!< in/out: the decompressing stream */
|
||||
byte* buf, /*!< out: the externally stored part of
|
||||
the field, or a prefix of it */
|
||||
ulint len, /*!< in: length of buf, in bytes */
|
||||
ulint zip_size,/*!< in: compressed BLOB page size */
|
||||
ulint space_id,/*!< in: space id of the BLOB pages */
|
||||
ulint page_no,/*!< in: page number of the first BLOB page */
|
||||
ulint offset) /*!< in: offset on the first BLOB page */
|
||||
{
|
||||
ulint page_type = FIL_PAGE_TYPE_ZBLOB;
|
||||
ulint page_type = FIL_PAGE_TYPE_ZBLOB;
|
||||
mem_heap_t* heap;
|
||||
int err;
|
||||
z_stream d_stream;
|
||||
|
||||
d_stream.next_out = buf;
|
||||
d_stream.avail_out = len;
|
||||
d_stream.next_in = Z_NULL;
|
||||
d_stream.avail_in = 0;
|
||||
|
||||
/* Zlib inflate needs 32 kilobytes for the default
|
||||
window size, plus a few kilobytes for small objects. */
|
||||
heap = mem_heap_create(40000);
|
||||
page_zip_set_alloc(&d_stream, heap);
|
||||
|
||||
ut_ad(ut_is_2pow(zip_size));
|
||||
ut_ad(zip_size >= PAGE_ZIP_MIN_SIZE);
|
||||
ut_ad(zip_size <= UNIV_PAGE_SIZE);
|
||||
ut_ad(space_id);
|
||||
|
||||
err = inflateInit(&d_stream);
|
||||
ut_a(err == Z_OK);
|
||||
|
||||
for (;;) {
|
||||
buf_page_t* bpage;
|
||||
int err;
|
||||
ulint next_page_no;
|
||||
|
||||
/* There is no latch on bpage directly. Instead,
|
||||
@ -4940,7 +4958,7 @@ btr_copy_zblob_prefix(
|
||||
" compressed BLOB"
|
||||
" page %lu space %lu\n",
|
||||
(ulong) page_no, (ulong) space_id);
|
||||
return;
|
||||
goto func_exit;
|
||||
}
|
||||
|
||||
if (UNIV_UNLIKELY
|
||||
@ -4966,13 +4984,13 @@ btr_copy_zblob_prefix(
|
||||
offset += 4;
|
||||
}
|
||||
|
||||
d_stream->next_in = bpage->zip.data + offset;
|
||||
d_stream->avail_in = zip_size - offset;
|
||||
d_stream.next_in = bpage->zip.data + offset;
|
||||
d_stream.avail_in = zip_size - offset;
|
||||
|
||||
err = inflate(d_stream, Z_NO_FLUSH);
|
||||
err = inflate(&d_stream, Z_NO_FLUSH);
|
||||
switch (err) {
|
||||
case Z_OK:
|
||||
if (!d_stream->avail_out) {
|
||||
if (!d_stream.avail_out) {
|
||||
goto end_of_blob;
|
||||
}
|
||||
break;
|
||||
@ -4989,13 +5007,13 @@ inflate_error:
|
||||
" compressed BLOB"
|
||||
" page %lu space %lu returned %d (%s)\n",
|
||||
(ulong) page_no, (ulong) space_id,
|
||||
err, d_stream->msg);
|
||||
err, d_stream.msg);
|
||||
case Z_BUF_ERROR:
|
||||
goto end_of_blob;
|
||||
}
|
||||
|
||||
if (next_page_no == FIL_NULL) {
|
||||
if (!d_stream->avail_in) {
|
||||
if (!d_stream.avail_in) {
|
||||
ut_print_timestamp(stderr);
|
||||
fprintf(stderr,
|
||||
" InnoDB: unexpected end of"
|
||||
@ -5004,7 +5022,7 @@ inflate_error:
|
||||
(ulong) page_no,
|
||||
(ulong) space_id);
|
||||
} else {
|
||||
err = inflate(d_stream, Z_FINISH);
|
||||
err = inflate(&d_stream, Z_FINISH);
|
||||
switch (err) {
|
||||
case Z_STREAM_END:
|
||||
case Z_BUF_ERROR:
|
||||
@ -5016,7 +5034,7 @@ inflate_error:
|
||||
|
||||
end_of_blob:
|
||||
buf_page_release_zip(bpage);
|
||||
return;
|
||||
goto func_exit;
|
||||
}
|
||||
|
||||
buf_page_release_zip(bpage);
|
||||
@ -5028,6 +5046,12 @@ end_of_blob:
|
||||
offset = FIL_PAGE_NEXT;
|
||||
page_type = FIL_PAGE_TYPE_ZBLOB2;
|
||||
}
|
||||
|
||||
func_exit:
|
||||
inflateEnd(&d_stream);
|
||||
mem_heap_free(heap);
|
||||
UNIV_MEM_ASSERT_RW(buf, d_stream.total_out);
|
||||
return(d_stream.total_out);
|
||||
}
|
||||
|
||||
/*******************************************************************//**
|
||||
@ -5053,28 +5077,8 @@ btr_copy_externally_stored_field_prefix_low(
|
||||
}
|
||||
|
||||
if (UNIV_UNLIKELY(zip_size)) {
|
||||
int err;
|
||||
z_stream d_stream;
|
||||
mem_heap_t* heap;
|
||||
|
||||
/* Zlib inflate needs 32 kilobytes for the default
|
||||
window size, plus a few kilobytes for small objects. */
|
||||
heap = mem_heap_create(40000);
|
||||
page_zip_set_alloc(&d_stream, heap);
|
||||
|
||||
err = inflateInit(&d_stream);
|
||||
ut_a(err == Z_OK);
|
||||
|
||||
d_stream.next_out = buf;
|
||||
d_stream.avail_out = len;
|
||||
d_stream.avail_in = 0;
|
||||
|
||||
btr_copy_zblob_prefix(&d_stream, zip_size,
|
||||
space_id, page_no, offset);
|
||||
inflateEnd(&d_stream);
|
||||
mem_heap_free(heap);
|
||||
UNIV_MEM_ASSERT_RW(buf, d_stream.total_out);
|
||||
return(d_stream.total_out);
|
||||
return(btr_copy_zblob_prefix(buf, len, zip_size,
|
||||
space_id, page_no, offset));
|
||||
} else {
|
||||
return(btr_copy_blob_prefix(buf, len, space_id,
|
||||
page_no, offset));
|
||||
|
@ -1213,8 +1213,8 @@ btr_search_drop_page_hash_when_freed(
|
||||
having to fear a deadlock. */
|
||||
|
||||
block = buf_page_get_gen(space, zip_size, page_no, RW_S_LATCH, NULL,
|
||||
BUF_GET_IF_IN_POOL, __FILE__, __LINE__,
|
||||
&mtr);
|
||||
BUF_PEEK_IF_IN_POOL, __FILE__, __LINE__,
|
||||
&mtr);
|
||||
/* Because the buffer pool mutex was released by
|
||||
buf_page_peek_if_search_hashed(), it is possible that the
|
||||
block was removed from the buffer pool by another thread
|
||||
|
@ -1233,7 +1233,7 @@ buf_pool_init_instance(
|
||||
|
||||
buf_pool->page_hash = hash_create(2 * buf_pool->curr_size);
|
||||
buf_pool->zip_hash = hash_create(2 * buf_pool->curr_size);
|
||||
|
||||
|
||||
buf_pool->last_printout_time = ut_time();
|
||||
}
|
||||
/* 2. Initialize flushing fields
|
||||
@ -1365,11 +1365,11 @@ buf_pool_drop_hash_index_instance(
|
||||
/* block->is_hashed cannot be modified
|
||||
when we have an x-latch on btr_search_latch;
|
||||
see the comment in buf0buf.h */
|
||||
|
||||
|
||||
if (!block->is_hashed) {
|
||||
continue;
|
||||
}
|
||||
|
||||
|
||||
/* To follow the latching order, we
|
||||
have to release btr_search_latch
|
||||
before acquiring block->latch. */
|
||||
@ -1378,14 +1378,14 @@ buf_pool_drop_hash_index_instance(
|
||||
we must rescan all blocks, because
|
||||
some may become hashed again. */
|
||||
*released_search_latch = TRUE;
|
||||
|
||||
|
||||
rw_lock_x_lock(&block->lock);
|
||||
|
||||
|
||||
/* This should be guaranteed by the
|
||||
callers, which will be holding
|
||||
btr_search_enabled_mutex. */
|
||||
ut_ad(!btr_search_enabled);
|
||||
|
||||
|
||||
/* Because we did not buffer-fix the
|
||||
block by calling buf_block_get_gen(),
|
||||
it is possible that the block has been
|
||||
@ -1395,7 +1395,7 @@ buf_pool_drop_hash_index_instance(
|
||||
block is mapped to. All we want to do
|
||||
is to drop any hash entries referring
|
||||
to the page. */
|
||||
|
||||
|
||||
/* It is possible that
|
||||
block->page.state != BUF_FILE_PAGE.
|
||||
Even that does not matter, because
|
||||
@ -1403,18 +1403,18 @@ buf_pool_drop_hash_index_instance(
|
||||
check block->is_hashed before doing
|
||||
anything. block->is_hashed can only
|
||||
be set on uncompressed file pages. */
|
||||
|
||||
|
||||
btr_search_drop_page_hash_index(block);
|
||||
|
||||
|
||||
rw_lock_x_unlock(&block->lock);
|
||||
|
||||
|
||||
rw_lock_x_lock(&btr_search_latch);
|
||||
|
||||
|
||||
ut_ad(!btr_search_enabled);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/********************************************************************//**
|
||||
Drops the adaptive hash index. To prevent a livelock, this function
|
||||
is only to be called while holding btr_search_latch and while
|
||||
@ -1990,30 +1990,30 @@ buf_pool_resize(void)
|
||||
ulint min_change_size = 1048576 * srv_buf_pool_instances;
|
||||
|
||||
buf_pool_mutex_enter_all();
|
||||
|
||||
|
||||
if (srv_buf_pool_old_size == srv_buf_pool_size) {
|
||||
|
||||
|
||||
buf_pool_mutex_exit_all();
|
||||
|
||||
return;
|
||||
|
||||
} else if (srv_buf_pool_curr_size + min_change_size
|
||||
> srv_buf_pool_size) {
|
||||
|
||||
|
||||
change_size = (srv_buf_pool_curr_size - srv_buf_pool_size)
|
||||
/ UNIV_PAGE_SIZE;
|
||||
|
||||
buf_pool_mutex_exit_all();
|
||||
|
||||
|
||||
/* Disable adaptive hash indexes and empty the index
|
||||
in order to free up memory in the buffer pool chunks. */
|
||||
buf_pool_shrink(change_size);
|
||||
|
||||
} else if (srv_buf_pool_curr_size + min_change_size
|
||||
< srv_buf_pool_size) {
|
||||
|
||||
|
||||
/* Enlarge the buffer pool by at least one megabyte */
|
||||
|
||||
|
||||
change_size = srv_buf_pool_size - srv_buf_pool_curr_size;
|
||||
|
||||
buf_pool_mutex_exit_all();
|
||||
@ -2026,10 +2026,10 @@ buf_pool_resize(void)
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
buf_pool_page_hash_rebuild();
|
||||
}
|
||||
|
||||
|
||||
/****************************************************************//**
|
||||
Remove the sentinel block for the watch before replacing it with a real block.
|
||||
buf_page_watch_clear() or buf_page_watch_occurred() will notice that
|
||||
@ -2316,9 +2316,6 @@ buf_page_get_zip(
|
||||
unsigned access_time;
|
||||
buf_pool_t* buf_pool = buf_pool_get(space, offset);
|
||||
|
||||
#ifndef UNIV_LOG_DEBUG
|
||||
ut_ad(!ibuf_inside());
|
||||
#endif
|
||||
buf_pool->stat.n_page_gets++;
|
||||
|
||||
for (;;) {
|
||||
@ -2533,16 +2530,19 @@ buf_block_align_instance(
|
||||
/* TODO: protect buf_pool->chunks with a mutex (it will
|
||||
currently remain constant after buf_pool_init()) */
|
||||
for (chunk = buf_pool->chunks, i = buf_pool->n_chunks; i--; chunk++) {
|
||||
lint offs = ptr - chunk->blocks->frame;
|
||||
ulint offs;
|
||||
|
||||
if (UNIV_UNLIKELY(offs < 0)) {
|
||||
if (UNIV_UNLIKELY(ptr < chunk->blocks->frame)) {
|
||||
|
||||
continue;
|
||||
}
|
||||
/* else */
|
||||
|
||||
offs = ptr - chunk->blocks->frame;
|
||||
|
||||
offs >>= UNIV_PAGE_SIZE_SHIFT;
|
||||
|
||||
if (UNIV_LIKELY((ulint) offs < chunk->size)) {
|
||||
if (UNIV_LIKELY(offs < chunk->size)) {
|
||||
buf_block_t* block = &chunk->blocks[offs];
|
||||
|
||||
/* The function buf_chunk_init() invokes
|
||||
@ -2719,7 +2719,7 @@ buf_page_get_gen(
|
||||
ulint rw_latch,/*!< in: RW_S_LATCH, RW_X_LATCH, RW_NO_LATCH */
|
||||
buf_block_t* guess, /*!< in: guessed block or NULL */
|
||||
ulint mode, /*!< in: BUF_GET, BUF_GET_IF_IN_POOL,
|
||||
BUF_GET_NO_LATCH, or
|
||||
BUF_PEEK_IF_IN_POOL, BUF_GET_NO_LATCH, or
|
||||
BUF_GET_IF_IN_POOL_OR_WATCH */
|
||||
const char* file, /*!< in: file name */
|
||||
ulint line, /*!< in: line where called */
|
||||
@ -2738,16 +2738,26 @@ buf_page_get_gen(
|
||||
ut_ad((rw_latch == RW_S_LATCH)
|
||||
|| (rw_latch == RW_X_LATCH)
|
||||
|| (rw_latch == RW_NO_LATCH));
|
||||
ut_ad((mode != BUF_GET_NO_LATCH) || (rw_latch == RW_NO_LATCH));
|
||||
ut_ad(mode == BUF_GET
|
||||
|| mode == BUF_GET_IF_IN_POOL
|
||||
|| mode == BUF_GET_NO_LATCH
|
||||
|| mode == BUF_GET_IF_IN_POOL_OR_WATCH);
|
||||
#ifdef UNIV_DEBUG
|
||||
switch (mode) {
|
||||
case BUF_GET_NO_LATCH:
|
||||
ut_ad(rw_latch == RW_NO_LATCH);
|
||||
break;
|
||||
case BUF_GET:
|
||||
case BUF_GET_IF_IN_POOL:
|
||||
case BUF_PEEK_IF_IN_POOL:
|
||||
case BUF_GET_IF_IN_POOL_OR_WATCH:
|
||||
break;
|
||||
default:
|
||||
ut_error;
|
||||
}
|
||||
#endif /* UNIV_DEBUG */
|
||||
ut_ad(zip_size == fil_space_get_zip_size(space));
|
||||
ut_ad(ut_is_2pow(zip_size));
|
||||
#ifndef UNIV_LOG_DEBUG
|
||||
ut_ad(!ibuf_inside() || ibuf_page_low(space, zip_size, offset,
|
||||
FALSE, file, line, NULL));
|
||||
ut_ad(!ibuf_inside(mtr)
|
||||
|| ibuf_page_low(space, zip_size, offset,
|
||||
FALSE, file, line, NULL));
|
||||
#endif
|
||||
buf_pool->stat.n_page_gets++;
|
||||
fold = buf_page_address_fold(space, offset);
|
||||
@ -2802,6 +2812,7 @@ loop2:
|
||||
buf_pool_mutex_exit(buf_pool);
|
||||
|
||||
if (mode == BUF_GET_IF_IN_POOL
|
||||
|| mode == BUF_PEEK_IF_IN_POOL
|
||||
|| mode == BUF_GET_IF_IN_POOL_OR_WATCH) {
|
||||
|
||||
return(NULL);
|
||||
@ -2842,7 +2853,8 @@ got_block:
|
||||
|
||||
must_read = buf_block_get_io_fix(block) == BUF_IO_READ;
|
||||
|
||||
if (must_read && mode == BUF_GET_IF_IN_POOL) {
|
||||
if (must_read && (mode == BUF_GET_IF_IN_POOL
|
||||
|| mode == BUF_PEEK_IF_IN_POOL)) {
|
||||
|
||||
/* The page is being read to buffer pool,
|
||||
but we cannot wait around for the read to
|
||||
@ -2876,7 +2888,7 @@ wait_until_unfixed:
|
||||
Try again later. */
|
||||
buf_pool_mutex_exit(buf_pool);
|
||||
os_thread_sleep(WAIT_FOR_READ);
|
||||
|
||||
|
||||
goto loop;
|
||||
}
|
||||
|
||||
@ -2965,6 +2977,7 @@ wait_until_unfixed:
|
||||
mutex_exit(&buf_pool->zip_mutex);
|
||||
buf_pool->n_pend_unzip++;
|
||||
|
||||
bpage->state = BUF_BLOCK_ZIP_FREE;
|
||||
buf_buddy_free(buf_pool, bpage, sizeof *bpage);
|
||||
|
||||
buf_pool_mutex_exit(buf_pool);
|
||||
@ -3058,7 +3071,9 @@ wait_until_unfixed:
|
||||
|
||||
buf_pool_mutex_exit(buf_pool);
|
||||
|
||||
buf_page_set_accessed_make_young(&block->page, access_time);
|
||||
if (UNIV_LIKELY(mode != BUF_PEEK_IF_IN_POOL)) {
|
||||
buf_page_set_accessed_make_young(&block->page, access_time);
|
||||
}
|
||||
|
||||
#if defined UNIV_DEBUG_FILE_ACCESSES || defined UNIV_DEBUG
|
||||
ut_a(!block->page.file_page_was_freed);
|
||||
@ -3111,11 +3126,12 @@ wait_until_unfixed:
|
||||
|
||||
mtr_memo_push(mtr, block, fix_type);
|
||||
|
||||
if (!access_time) {
|
||||
if (UNIV_LIKELY(mode != BUF_PEEK_IF_IN_POOL) && !access_time) {
|
||||
/* In the case of a first access, try to apply linear
|
||||
read-ahead */
|
||||
|
||||
buf_read_ahead_linear(space, zip_size, offset);
|
||||
buf_read_ahead_linear(space, zip_size, offset,
|
||||
ibuf_inside(mtr));
|
||||
}
|
||||
|
||||
#ifdef UNIV_IBUF_COUNT_DEBUG
|
||||
@ -3172,7 +3188,7 @@ buf_page_optimistic_get(
|
||||
access_time = buf_page_is_accessed(&block->page);
|
||||
buf_page_set_accessed_make_young(&block->page, access_time);
|
||||
|
||||
ut_ad(!ibuf_inside()
|
||||
ut_ad(!ibuf_inside(mtr)
|
||||
|| ibuf_page(buf_block_get_space(block),
|
||||
buf_block_get_zip_size(block),
|
||||
buf_block_get_page_no(block), NULL));
|
||||
@ -3228,7 +3244,8 @@ buf_page_optimistic_get(
|
||||
|
||||
buf_read_ahead_linear(buf_block_get_space(block),
|
||||
buf_block_get_zip_size(block),
|
||||
buf_block_get_page_no(block));
|
||||
buf_block_get_page_no(block),
|
||||
ibuf_inside(mtr));
|
||||
}
|
||||
|
||||
#ifdef UNIV_IBUF_COUNT_DEBUG
|
||||
@ -3304,7 +3321,7 @@ buf_page_get_known_nowait(
|
||||
buf_pool_mutex_exit(buf_pool);
|
||||
}
|
||||
|
||||
ut_ad(!ibuf_inside() || (mode == BUF_KEEP_OLD));
|
||||
ut_ad(!ibuf_inside(mtr) || mode == BUF_KEEP_OLD);
|
||||
|
||||
if (rw_latch == RW_S_LATCH) {
|
||||
success = rw_lock_s_lock_nowait(&(block->lock),
|
||||
@ -3569,14 +3586,13 @@ buf_page_init_for_read(
|
||||
/* It is a read-ahead within an ibuf routine */
|
||||
|
||||
ut_ad(!ibuf_bitmap_page(zip_size, offset));
|
||||
ut_ad(ibuf_inside());
|
||||
|
||||
mtr_start(&mtr);
|
||||
ibuf_mtr_start(&mtr);
|
||||
|
||||
if (!recv_no_ibuf_operations
|
||||
&& !ibuf_page(space, zip_size, offset, &mtr)) {
|
||||
|
||||
mtr_commit(&mtr);
|
||||
ibuf_mtr_commit(&mtr);
|
||||
|
||||
return(NULL);
|
||||
}
|
||||
@ -3700,6 +3716,7 @@ err_exit:
|
||||
|
||||
/* The block was added by some other thread. */
|
||||
watch_page = NULL;
|
||||
bpage->state = BUF_BLOCK_ZIP_FREE;
|
||||
buf_buddy_free(buf_pool, bpage, sizeof *bpage);
|
||||
buf_buddy_free(buf_pool, data, zip_size);
|
||||
|
||||
@ -3760,7 +3777,7 @@ func_exit:
|
||||
|
||||
if (mode == BUF_READ_IBUF_PAGES_ONLY) {
|
||||
|
||||
mtr_commit(&mtr);
|
||||
ibuf_mtr_commit(&mtr);
|
||||
}
|
||||
|
||||
ut_ad(!bpage || buf_page_in_file(bpage));
|
||||
@ -4788,7 +4805,7 @@ buf_get_modified_ratio_pct(void)
|
||||
buf_get_total_list_len(&lru_len, &free_len, &flush_list_len);
|
||||
|
||||
ratio = (100 * flush_list_len) / (1 + lru_len + free_len);
|
||||
|
||||
|
||||
/* 1 + is there to avoid division by zero */
|
||||
|
||||
return(ratio);
|
||||
@ -5171,7 +5188,7 @@ buf_all_freed(void)
|
||||
|
||||
return(TRUE);
|
||||
}
|
||||
|
||||
|
||||
/*********************************************************************//**
|
||||
Checks that there currently are no pending i/o-operations for the buffer
|
||||
pool.
|
||||
|
@ -247,74 +247,78 @@ buf_LRU_drop_page_hash_for_tablespace(
|
||||
sizeof(ulint) * BUF_LRU_DROP_SEARCH_HASH_SIZE);
|
||||
|
||||
buf_pool_mutex_enter(buf_pool);
|
||||
num_entries = 0;
|
||||
|
||||
scan_again:
|
||||
num_entries = 0;
|
||||
bpage = UT_LIST_GET_LAST(buf_pool->LRU);
|
||||
|
||||
while (bpage != NULL) {
|
||||
mutex_t* block_mutex = buf_page_get_mutex(bpage);
|
||||
buf_page_t* prev_bpage;
|
||||
ibool is_fixed;
|
||||
|
||||
mutex_enter(block_mutex);
|
||||
prev_bpage = UT_LIST_GET_PREV(LRU, bpage);
|
||||
|
||||
ut_a(buf_page_in_file(bpage));
|
||||
|
||||
if (buf_page_get_state(bpage) != BUF_BLOCK_FILE_PAGE
|
||||
|| bpage->space != id
|
||||
|| bpage->buf_fix_count > 0
|
||||
|| bpage->io_fix != BUF_IO_NONE) {
|
||||
/* We leave the fixed pages as is in this scan.
|
||||
To be dealt with later in the final scan. */
|
||||
mutex_exit(block_mutex);
|
||||
/* Compressed pages are never hashed.
|
||||
Skip blocks of other tablespaces.
|
||||
Skip I/O-fixed blocks (to be dealt with later). */
|
||||
next_page:
|
||||
bpage = prev_bpage;
|
||||
continue;
|
||||
}
|
||||
|
||||
mutex_enter(&((buf_block_t*) bpage)->mutex);
|
||||
is_fixed = bpage->buf_fix_count > 0
|
||||
|| !((buf_block_t*) bpage)->is_hashed;
|
||||
mutex_exit(&((buf_block_t*) bpage)->mutex);
|
||||
|
||||
if (is_fixed) {
|
||||
goto next_page;
|
||||
}
|
||||
|
||||
if (((buf_block_t*) bpage)->is_hashed) {
|
||||
/* Store the page number so that we can drop the hash
|
||||
index in a batch later. */
|
||||
page_arr[num_entries] = bpage->offset;
|
||||
ut_a(num_entries < BUF_LRU_DROP_SEARCH_HASH_SIZE);
|
||||
++num_entries;
|
||||
|
||||
/* Store the offset(i.e.: page_no) in the array
|
||||
so that we can drop hash index in a batch
|
||||
later. */
|
||||
page_arr[num_entries] = bpage->offset;
|
||||
mutex_exit(block_mutex);
|
||||
ut_a(num_entries < BUF_LRU_DROP_SEARCH_HASH_SIZE);
|
||||
++num_entries;
|
||||
|
||||
if (num_entries < BUF_LRU_DROP_SEARCH_HASH_SIZE) {
|
||||
goto next_page;
|
||||
}
|
||||
|
||||
/* Array full. We release the buf_pool->mutex to
|
||||
obey the latching order. */
|
||||
buf_pool_mutex_exit(buf_pool);
|
||||
|
||||
buf_LRU_drop_page_hash_batch(
|
||||
id, zip_size, page_arr, num_entries);
|
||||
|
||||
num_entries = 0;
|
||||
|
||||
buf_pool_mutex_enter(buf_pool);
|
||||
} else {
|
||||
mutex_exit(block_mutex);
|
||||
if (num_entries < BUF_LRU_DROP_SEARCH_HASH_SIZE) {
|
||||
goto next_page;
|
||||
}
|
||||
|
||||
next_page:
|
||||
/* Note that we may have released the buf_pool mutex
|
||||
above after reading the prev_bpage during processing
|
||||
of a page_hash_batch (i.e.: when the array was full).
|
||||
This means that prev_bpage can change in LRU list.
|
||||
This is OK because this function is a 'best effort'
|
||||
to drop as many search hash entries as possible and
|
||||
it does not guarantee that ALL such entries will be
|
||||
dropped. */
|
||||
bpage = prev_bpage;
|
||||
/* Array full. We release the buf_pool->mutex to obey
|
||||
the latching order. */
|
||||
buf_pool_mutex_exit(buf_pool);
|
||||
|
||||
buf_LRU_drop_page_hash_batch(
|
||||
id, zip_size, page_arr, num_entries);
|
||||
|
||||
num_entries = 0;
|
||||
|
||||
buf_pool_mutex_enter(buf_pool);
|
||||
|
||||
/* Note that we released the buf_pool mutex above
|
||||
after reading the prev_bpage during processing of a
|
||||
page_hash_batch (i.e.: when the array was full).
|
||||
Because prev_bpage could belong to a compressed-only
|
||||
block, it may have been relocated, and thus the
|
||||
pointer cannot be trusted. Because bpage is of type
|
||||
buf_block_t, it is safe to dereference.
|
||||
|
||||
bpage can change in the LRU list. This is OK because
|
||||
this function is a 'best effort' to drop as many
|
||||
search hash entries as possible and it does not
|
||||
guarantee that ALL such entries will be dropped. */
|
||||
|
||||
/* If, however, bpage has been removed from LRU list
|
||||
to the free list then we should restart the scan.
|
||||
bpage->state is protected by buf_pool mutex. */
|
||||
if (bpage && !buf_page_in_file(bpage)) {
|
||||
ut_a(num_entries == 0);
|
||||
if (bpage
|
||||
&& buf_page_get_state(bpage) != BUF_BLOCK_FILE_PAGE) {
|
||||
goto scan_again;
|
||||
}
|
||||
}
|
||||
@ -1889,6 +1893,7 @@ buf_LRU_block_remove_hashed_page(
|
||||
buf_pool, bpage->zip.data,
|
||||
page_zip_get_size(&bpage->zip));
|
||||
|
||||
bpage->state = BUF_BLOCK_ZIP_FREE;
|
||||
buf_buddy_free(buf_pool, bpage, sizeof(*bpage));
|
||||
buf_pool_mutex_exit_allow(buf_pool);
|
||||
|
||||
|
@ -236,10 +236,10 @@ UNIV_INTERN
|
||||
ulint
|
||||
buf_read_ahead_linear(
|
||||
/*==================*/
|
||||
ulint space, /*!< in: space id */
|
||||
ulint zip_size,/*!< in: compressed page size in bytes, or 0 */
|
||||
ulint offset) /*!< in: page number of a page; NOTE: the current thread
|
||||
must want access to this page (see NOTE 3 above) */
|
||||
ulint space, /*!< in: space id */
|
||||
ulint zip_size, /*!< in: compressed page size in bytes, or 0 */
|
||||
ulint offset, /*!< in: page number; see NOTE 3 above */
|
||||
ibool inside_ibuf) /*!< in: TRUE if we are inside ibuf routine */
|
||||
{
|
||||
buf_pool_t* buf_pool = buf_pool_get(space, offset);
|
||||
ib_int64_t tablespace_version;
|
||||
@ -429,11 +429,9 @@ buf_read_ahead_linear(
|
||||
|
||||
/* If we got this far, read-ahead can be sensible: do it */
|
||||
|
||||
if (ibuf_inside()) {
|
||||
ibuf_mode = BUF_READ_IBUF_PAGES_ONLY;
|
||||
} else {
|
||||
ibuf_mode = BUF_READ_ANY_PAGE;
|
||||
}
|
||||
ibuf_mode = inside_ibuf
|
||||
? BUF_READ_IBUF_PAGES_ONLY | OS_AIO_SIMULATED_WAKE_LATER
|
||||
: BUF_READ_ANY_PAGE | OS_AIO_SIMULATED_WAKE_LATER;
|
||||
|
||||
count = 0;
|
||||
|
||||
@ -450,7 +448,7 @@ buf_read_ahead_linear(
|
||||
if (!ibuf_bitmap_page(zip_size, i)) {
|
||||
count += buf_read_page_low(
|
||||
&err, FALSE,
|
||||
ibuf_mode | OS_AIO_SIMULATED_WAKE_LATER,
|
||||
ibuf_mode,
|
||||
space, zip_size, FALSE, tablespace_version, i);
|
||||
if (err == DB_TABLESPACE_DELETED) {
|
||||
ut_print_timestamp(stderr);
|
||||
@ -520,7 +518,6 @@ buf_read_ibuf_merge_pages(
|
||||
{
|
||||
ulint i;
|
||||
|
||||
ut_ad(!ibuf_inside());
|
||||
#ifdef UNIV_IBUF_DEBUG
|
||||
ut_a(n_stored < UNIV_PAGE_SIZE);
|
||||
#endif
|
||||
|
@ -2258,10 +2258,12 @@ loop:
|
||||
/* Since table names in SYS_FOREIGN are stored in a case-insensitive
|
||||
order, we have to check that the table name matches also in a binary
|
||||
string comparison. On Unix, MySQL allows table names that only differ
|
||||
in character case. */
|
||||
|
||||
if (0 != ut_memcmp(field, table_name, len)) {
|
||||
in character case. If lower_case_table_names=2 then what is stored
|
||||
may not be the same case, but the previous comparison showed that they
|
||||
match with no-case. */
|
||||
|
||||
if ((srv_lower_case_table_names != 2)
|
||||
&& (0 != ut_memcmp(field, table_name, len))) {
|
||||
goto next_rec;
|
||||
}
|
||||
|
||||
|
@ -4342,8 +4342,6 @@ fil_io(
|
||||
ut_ad(recv_no_ibuf_operations || (type == OS_FILE_WRITE)
|
||||
|| !ibuf_bitmap_page(zip_size, block_offset)
|
||||
|| sync || is_log);
|
||||
ut_ad(!ibuf_inside() || is_log || (type == OS_FILE_WRITE)
|
||||
|| ibuf_page(space_id, zip_size, block_offset, NULL));
|
||||
# endif /* UNIV_LOG_DEBUG */
|
||||
if (sync) {
|
||||
mode = OS_AIO_SYNC;
|
||||
|
@ -51,6 +51,7 @@ Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
#include <mysql/plugin.h>
|
||||
#include <mysql/innodb_priv.h>
|
||||
#include <mysql/psi/psi.h>
|
||||
#include <my_sys.h>
|
||||
|
||||
/** @file ha_innodb.cc */
|
||||
|
||||
@ -81,7 +82,6 @@ extern "C" {
|
||||
#include "fil0fil.h"
|
||||
#include "trx0xa.h"
|
||||
#include "row0merge.h"
|
||||
#include "thr0loc.h"
|
||||
#include "dict0boot.h"
|
||||
#include "ha_prototypes.h"
|
||||
#include "ut0mem.h"
|
||||
@ -279,7 +279,6 @@ static PSI_mutex_info all_innodb_mutexes[] = {
|
||||
{&sync_thread_mutex_key, "sync_thread_mutex", 0},
|
||||
# endif /* UNIV_SYNC_DEBUG */
|
||||
{&trx_doublewrite_mutex_key, "trx_doublewrite_mutex", 0},
|
||||
{&thr_local_mutex_key, "thr_local_mutex", 0},
|
||||
{&trx_undo_mutex_key, "trx_undo_mutex", 0}
|
||||
};
|
||||
# endif /* UNIV_PFS_MUTEX */
|
||||
@ -1146,6 +1145,20 @@ innobase_strcasecmp(
|
||||
return(my_strcasecmp(system_charset_info, a, b));
|
||||
}
|
||||
|
||||
/******************************************************************//**
|
||||
Strip dir name from a full path name and return only the file name
|
||||
@return file name or "null" if no file name */
|
||||
extern "C" UNIV_INTERN
|
||||
const char*
|
||||
innobase_basename(
|
||||
/*==============*/
|
||||
const char* path_name) /*!< in: full path name */
|
||||
{
|
||||
const char* name = base_name(path_name);
|
||||
|
||||
return((name) ? name : "null");
|
||||
}
|
||||
|
||||
/******************************************************************//**
|
||||
Makes all characters in a NUL-terminated UTF-8 string lower case. */
|
||||
extern "C" UNIV_INTERN
|
||||
@ -3028,7 +3041,6 @@ innobase_close_connection(
|
||||
|
||||
innobase_rollback_trx(trx);
|
||||
|
||||
thr_local_free(trx->mysql_thread_id);
|
||||
trx_free_for_mysql(trx);
|
||||
|
||||
DBUG_RETURN(0);
|
||||
@ -9263,7 +9275,8 @@ innodb_mutex_show_status(
|
||||
if (mutex->count_using > 0) {
|
||||
buf1len= my_snprintf(buf1, sizeof(buf1),
|
||||
"%s:%s",
|
||||
mutex->cmutex_name, mutex->cfile_name);
|
||||
mutex->cmutex_name,
|
||||
innobase_basename(mutex->cfile_name));
|
||||
buf2len= my_snprintf(buf2, sizeof(buf2),
|
||||
"count=%lu, spin_waits=%lu,"
|
||||
" spin_rounds=%lu, "
|
||||
@ -9293,7 +9306,8 @@ innodb_mutex_show_status(
|
||||
}
|
||||
#else /* UNIV_DEBUG */
|
||||
buf1len= (uint) my_snprintf(buf1, sizeof(buf1), "%s:%lu",
|
||||
mutex->cfile_name, (ulong) mutex->cline);
|
||||
innobase_basename(mutex->cfile_name),
|
||||
(ulong) mutex->cline);
|
||||
buf2len= (uint) my_snprintf(buf2, sizeof(buf2), "os_waits=%lu",
|
||||
(ulong) mutex->count_os_wait);
|
||||
|
||||
@ -9309,7 +9323,8 @@ innodb_mutex_show_status(
|
||||
if (block_mutex) {
|
||||
buf1len = (uint) my_snprintf(buf1, sizeof buf1,
|
||||
"combined %s:%lu",
|
||||
block_mutex->cfile_name,
|
||||
innobase_basename(
|
||||
block_mutex->cfile_name),
|
||||
(ulong) block_mutex->cline);
|
||||
buf2len = (uint) my_snprintf(buf2, sizeof buf2,
|
||||
"os_waits=%lu",
|
||||
@ -9340,7 +9355,8 @@ innodb_mutex_show_status(
|
||||
}
|
||||
|
||||
buf1len = my_snprintf(buf1, sizeof buf1, "%s:%lu",
|
||||
lock->cfile_name, (ulong) lock->cline);
|
||||
innobase_basename(lock->cfile_name),
|
||||
(ulong) lock->cline);
|
||||
buf2len = my_snprintf(buf2, sizeof buf2, "os_waits=%lu",
|
||||
(ulong) lock->count_os_wait);
|
||||
|
||||
@ -9355,7 +9371,8 @@ innodb_mutex_show_status(
|
||||
if (block_lock) {
|
||||
buf1len = (uint) my_snprintf(buf1, sizeof buf1,
|
||||
"combined %s:%lu",
|
||||
block_lock->cfile_name,
|
||||
innobase_basename(
|
||||
block_lock->cfile_name),
|
||||
(ulong) block_lock->cline);
|
||||
buf2len = (uint) my_snprintf(buf2, sizeof buf2,
|
||||
"os_waits=%lu",
|
||||
@ -11359,7 +11376,7 @@ mysql_declare_plugin(innobase)
|
||||
MYSQL_STORAGE_ENGINE_PLUGIN,
|
||||
&innobase_storage_engine,
|
||||
innobase_hton_name,
|
||||
"Innobase Oy",
|
||||
plugin_author,
|
||||
"Supports transactions, row-level locking, and foreign keys",
|
||||
PLUGIN_LICENSE_GPL,
|
||||
innobase_init, /* Plugin Init */
|
||||
|
@ -47,8 +47,6 @@ extern "C" {
|
||||
#include "trx0trx.h" /* for TRX_QUE_STATE_STR_MAX_LEN */
|
||||
}
|
||||
|
||||
static const char plugin_author[] = "Innobase Oy";
|
||||
|
||||
#define OK(expr) \
|
||||
if ((expr) != 0) { \
|
||||
DBUG_RETURN(1); \
|
||||
@ -1059,7 +1057,7 @@ UNIV_INTERN struct st_mysql_plugin i_s_innodb_lock_waits =
|
||||
|
||||
/* plugin author (for SHOW PLUGINS) */
|
||||
/* const char* */
|
||||
STRUCT_FLD(author, "Innobase Oy"),
|
||||
STRUCT_FLD(author, plugin_author),
|
||||
|
||||
/* general descriptive text (for SHOW PLUGINS) */
|
||||
/* const char* */
|
||||
|
@ -26,6 +26,8 @@ Created July 18, 2007 Vasil Dimov
|
||||
#ifndef i_s_h
|
||||
#define i_s_h
|
||||
|
||||
const char plugin_author[] = "Oracle Corporation";
|
||||
|
||||
extern struct st_mysql_plugin i_s_innodb_trx;
|
||||
extern struct st_mysql_plugin i_s_innodb_locks;
|
||||
extern struct st_mysql_plugin i_s_innodb_lock_waits;
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -150,7 +150,7 @@ UNIV_INLINE
|
||||
ulint
|
||||
btr_pcur_get_up_match(
|
||||
/*==================*/
|
||||
btr_pcur_t* cursor); /*!< in: memory buffer for persistent cursor */
|
||||
const btr_pcur_t* cursor); /*!< in: persistent cursor */
|
||||
/**************************************************************//**
|
||||
Gets the low_match value for a pcur after a search.
|
||||
@return number of matched fields at the cursor or to the right if
|
||||
@ -159,7 +159,7 @@ UNIV_INLINE
|
||||
ulint
|
||||
btr_pcur_get_low_match(
|
||||
/*===================*/
|
||||
btr_pcur_t* cursor); /*!< in: memory buffer for persistent cursor */
|
||||
const btr_pcur_t* cursor); /*!< in: persistent cursor */
|
||||
/**************************************************************//**
|
||||
If mode is PAGE_CUR_G or PAGE_CUR_GE, opens a persistent cursor on the first
|
||||
user record satisfying the search condition, in the case PAGE_CUR_L or
|
||||
@ -264,22 +264,6 @@ ulint
|
||||
btr_pcur_get_rel_pos(
|
||||
/*=================*/
|
||||
const btr_pcur_t* cursor);/*!< in: persistent cursor */
|
||||
/*********************************************************//**
|
||||
Sets the mtr field for a pcur. */
|
||||
UNIV_INLINE
|
||||
void
|
||||
btr_pcur_set_mtr(
|
||||
/*=============*/
|
||||
btr_pcur_t* cursor, /*!< in: persistent cursor */
|
||||
mtr_t* mtr); /*!< in, own: mtr */
|
||||
/*********************************************************//**
|
||||
Gets the mtr field for a pcur.
|
||||
@return mtr */
|
||||
UNIV_INLINE
|
||||
mtr_t*
|
||||
btr_pcur_get_mtr(
|
||||
/*=============*/
|
||||
btr_pcur_t* cursor); /*!< in: persistent cursor */
|
||||
/**************************************************************//**
|
||||
Commits the mtr and sets the pcur latch mode to BTR_NO_LATCHES,
|
||||
that is, the cursor becomes detached. If there have been modifications
|
||||
@ -387,10 +371,6 @@ page_cur_t*
|
||||
btr_pcur_get_page_cur(
|
||||
/*==================*/
|
||||
const btr_pcur_t* cursor); /*!< in: persistent cursor */
|
||||
#else /* UNIV_DEBUG */
|
||||
# define btr_pcur_get_btr_cur(cursor) (&(cursor)->btr_cur)
|
||||
# define btr_pcur_get_page_cur(cursor) (&(cursor)->btr_cur.page_cur)
|
||||
#endif /* UNIV_DEBUG */
|
||||
/*********************************************************//**
|
||||
Returns the page of a persistent cursor.
|
||||
@return pointer to the page */
|
||||
@ -398,7 +378,7 @@ UNIV_INLINE
|
||||
page_t*
|
||||
btr_pcur_get_page(
|
||||
/*==============*/
|
||||
btr_pcur_t* cursor);/*!< in: persistent cursor */
|
||||
const btr_pcur_t* cursor);/*!< in: persistent cursor */
|
||||
/*********************************************************//**
|
||||
Returns the buffer block of a persistent cursor.
|
||||
@return pointer to the block */
|
||||
@ -406,7 +386,7 @@ UNIV_INLINE
|
||||
buf_block_t*
|
||||
btr_pcur_get_block(
|
||||
/*===============*/
|
||||
btr_pcur_t* cursor);/*!< in: persistent cursor */
|
||||
const btr_pcur_t* cursor);/*!< in: persistent cursor */
|
||||
/*********************************************************//**
|
||||
Returns the record of a persistent cursor.
|
||||
@return pointer to the record */
|
||||
@ -414,7 +394,14 @@ UNIV_INLINE
|
||||
rec_t*
|
||||
btr_pcur_get_rec(
|
||||
/*=============*/
|
||||
btr_pcur_t* cursor);/*!< in: persistent cursor */
|
||||
const btr_pcur_t* cursor);/*!< in: persistent cursor */
|
||||
#else /* UNIV_DEBUG */
|
||||
# define btr_pcur_get_btr_cur(cursor) (&(cursor)->btr_cur)
|
||||
# define btr_pcur_get_page_cur(cursor) (&(cursor)->btr_cur.page_cur)
|
||||
# define btr_pcur_get_page(cursor) ((cursor)->btr_cur.page_cur.block->frame)
|
||||
# define btr_pcur_get_block(cursor) ((cursor)->btr_cur.page_cur.block)
|
||||
# define btr_pcur_get_rec(cursor) ((cursor)->btr_cur.page_cur.rec)
|
||||
#endif /* UNIV_DEBUG */
|
||||
/*********************************************************//**
|
||||
Checks if the persistent cursor is on a user record. */
|
||||
UNIV_INLINE
|
||||
@ -517,9 +504,6 @@ struct btr_pcur_struct{
|
||||
/* NOTE that the following fields may possess dynamically allocated
|
||||
memory which should be freed if not needed anymore! */
|
||||
|
||||
mtr_t* mtr; /*!< NULL, or this field may contain
|
||||
a mini-transaction which holds the
|
||||
latch on the cursor page */
|
||||
byte* old_rec_buf; /*!< NULL, or a dynamically allocated
|
||||
buffer for old_rec */
|
||||
ulint buf_size; /*!< old_rec_buf size if old_rec_buf
|
||||
|
@ -42,34 +42,6 @@ btr_pcur_get_rel_pos(
|
||||
return(cursor->rel_pos);
|
||||
}
|
||||
|
||||
/*********************************************************//**
|
||||
Sets the mtr field for a pcur. */
|
||||
UNIV_INLINE
|
||||
void
|
||||
btr_pcur_set_mtr(
|
||||
/*=============*/
|
||||
btr_pcur_t* cursor, /*!< in: persistent cursor */
|
||||
mtr_t* mtr) /*!< in, own: mtr */
|
||||
{
|
||||
ut_ad(cursor);
|
||||
|
||||
cursor->mtr = mtr;
|
||||
}
|
||||
|
||||
/*********************************************************//**
|
||||
Gets the mtr field for a pcur.
|
||||
@return mtr */
|
||||
UNIV_INLINE
|
||||
mtr_t*
|
||||
btr_pcur_get_mtr(
|
||||
/*=============*/
|
||||
btr_pcur_t* cursor) /*!< in: persistent cursor */
|
||||
{
|
||||
ut_ad(cursor);
|
||||
|
||||
return(cursor->mtr);
|
||||
}
|
||||
|
||||
#ifdef UNIV_DEBUG
|
||||
/*********************************************************//**
|
||||
Returns the btr cursor component of a persistent cursor.
|
||||
@ -95,7 +67,7 @@ btr_pcur_get_page_cur(
|
||||
{
|
||||
return(btr_cur_get_page_cur(btr_pcur_get_btr_cur(cursor)));
|
||||
}
|
||||
#endif /* UNIV_DEBUG */
|
||||
|
||||
/*********************************************************//**
|
||||
Returns the page of a persistent cursor.
|
||||
@return pointer to the page */
|
||||
@ -103,7 +75,7 @@ UNIV_INLINE
|
||||
page_t*
|
||||
btr_pcur_get_page(
|
||||
/*==============*/
|
||||
btr_pcur_t* cursor) /*!< in: persistent cursor */
|
||||
const btr_pcur_t* cursor) /*!< in: persistent cursor */
|
||||
{
|
||||
ut_ad(cursor->pos_state == BTR_PCUR_IS_POSITIONED);
|
||||
|
||||
@ -117,7 +89,7 @@ UNIV_INLINE
|
||||
buf_block_t*
|
||||
btr_pcur_get_block(
|
||||
/*===============*/
|
||||
btr_pcur_t* cursor) /*!< in: persistent cursor */
|
||||
const btr_pcur_t* cursor) /*!< in: persistent cursor */
|
||||
{
|
||||
ut_ad(cursor->pos_state == BTR_PCUR_IS_POSITIONED);
|
||||
|
||||
@ -131,13 +103,14 @@ UNIV_INLINE
|
||||
rec_t*
|
||||
btr_pcur_get_rec(
|
||||
/*=============*/
|
||||
btr_pcur_t* cursor) /*!< in: persistent cursor */
|
||||
const btr_pcur_t* cursor) /*!< in: persistent cursor */
|
||||
{
|
||||
ut_ad(cursor->pos_state == BTR_PCUR_IS_POSITIONED);
|
||||
ut_ad(cursor->latch_mode != BTR_NO_LATCHES);
|
||||
|
||||
return(btr_cur_get_rec(btr_pcur_get_btr_cur(cursor)));
|
||||
}
|
||||
#endif /* UNIV_DEBUG */
|
||||
|
||||
/**************************************************************//**
|
||||
Gets the up_match value for a pcur after a search.
|
||||
@ -147,9 +120,9 @@ UNIV_INLINE
|
||||
ulint
|
||||
btr_pcur_get_up_match(
|
||||
/*==================*/
|
||||
btr_pcur_t* cursor) /*!< in: memory buffer for persistent cursor */
|
||||
const btr_pcur_t* cursor) /*!< in: persistent cursor */
|
||||
{
|
||||
btr_cur_t* btr_cursor;
|
||||
const btr_cur_t* btr_cursor;
|
||||
|
||||
ut_ad((cursor->pos_state == BTR_PCUR_WAS_POSITIONED)
|
||||
|| (cursor->pos_state == BTR_PCUR_IS_POSITIONED));
|
||||
@ -169,9 +142,9 @@ UNIV_INLINE
|
||||
ulint
|
||||
btr_pcur_get_low_match(
|
||||
/*===================*/
|
||||
btr_pcur_t* cursor) /*!< in: memory buffer for persistent cursor */
|
||||
const btr_pcur_t* cursor) /*!< in: persistent cursor */
|
||||
{
|
||||
btr_cur_t* btr_cursor;
|
||||
const btr_cur_t* btr_cursor;
|
||||
|
||||
ut_ad((cursor->pos_state == BTR_PCUR_WAS_POSITIONED)
|
||||
|| (cursor->pos_state == BTR_PCUR_IS_POSITIONED));
|
||||
|
@ -41,6 +41,8 @@ Created 11/5/1995 Heikki Tuuri
|
||||
/* @{ */
|
||||
#define BUF_GET 10 /*!< get always */
|
||||
#define BUF_GET_IF_IN_POOL 11 /*!< get if in pool */
|
||||
#define BUF_PEEK_IF_IN_POOL 12 /*!< get if in pool, do not make
|
||||
the block young in the LRU list */
|
||||
#define BUF_GET_NO_LATCH 14 /*!< get and bufferfix, but
|
||||
set no latch; we have
|
||||
separated this case, because
|
||||
@ -396,7 +398,7 @@ buf_page_get_gen(
|
||||
ulint rw_latch,/*!< in: RW_S_LATCH, RW_X_LATCH, RW_NO_LATCH */
|
||||
buf_block_t* guess, /*!< in: guessed block or NULL */
|
||||
ulint mode, /*!< in: BUF_GET, BUF_GET_IF_IN_POOL,
|
||||
BUF_GET_NO_LATCH or
|
||||
BUF_PEEK_IF_IN_POOL, BUF_GET_NO_LATCH or
|
||||
BUF_GET_IF_IN_POOL_OR_WATCH */
|
||||
const char* file, /*!< in: file name */
|
||||
ulint line, /*!< in: line where called */
|
||||
|
@ -70,10 +70,10 @@ UNIV_INTERN
|
||||
ulint
|
||||
buf_read_ahead_linear(
|
||||
/*==================*/
|
||||
ulint space, /*!< in: space id */
|
||||
ulint zip_size,/*!< in: compressed page size in bytes, or 0 */
|
||||
ulint offset);/*!< in: page number of a page; NOTE: the current thread
|
||||
must want access to this page (see NOTE 3 above) */
|
||||
ulint space, /*!< in: space id */
|
||||
ulint zip_size, /*!< in: compressed page size in bytes, or 0 */
|
||||
ulint offset, /*!< in: page number; see NOTE 3 above */
|
||||
ibool inside_ibuf); /*!< in: TRUE if we are inside ibuf routine */
|
||||
/********************************************************************//**
|
||||
Issues read requests for pages which the ibuf module wants to read in, in
|
||||
order to contract the insert buffer tree. Technically, this function is like
|
||||
|
@ -173,6 +173,15 @@ innobase_strcasecmp(
|
||||
const char* a, /*!< in: first string to compare */
|
||||
const char* b); /*!< in: second string to compare */
|
||||
|
||||
/******************************************************************//**
|
||||
Strip dir name from a full path name and return only its file name.
|
||||
@return file name or "null" if no file name */
|
||||
UNIV_INTERN
|
||||
const char*
|
||||
innobase_basename(
|
||||
/*==============*/
|
||||
const char* path_name); /*!< in: full path name */
|
||||
|
||||
/******************************************************************//**
|
||||
Returns true if the thread is executing a SELECT statement.
|
||||
@return true if thd is executing SELECT */
|
||||
|
@ -104,6 +104,22 @@ UNIV_INTERN
|
||||
void
|
||||
ibuf_update_max_tablespace_id(void);
|
||||
/*===============================*/
|
||||
/***************************************************************//**
|
||||
Starts an insert buffer mini-transaction. */
|
||||
UNIV_INLINE
|
||||
void
|
||||
ibuf_mtr_start(
|
||||
/*===========*/
|
||||
mtr_t* mtr) /*!< out: mini-transaction */
|
||||
__attribute__((nonnull));
|
||||
/***************************************************************//**
|
||||
Commits an insert buffer mini-transaction. */
|
||||
UNIV_INLINE
|
||||
void
|
||||
ibuf_mtr_commit(
|
||||
/*============*/
|
||||
mtr_t* mtr) /*!< in/out: mini-transaction */
|
||||
__attribute__((nonnull));
|
||||
/*********************************************************************//**
|
||||
Initializes an ibuf bitmap page. */
|
||||
UNIV_INTERN
|
||||
@ -224,10 +240,12 @@ routine.
|
||||
For instance, a read-ahead of non-ibuf pages is forbidden by threads
|
||||
that are executing an insert buffer routine.
|
||||
@return TRUE if inside an insert buffer routine */
|
||||
UNIV_INTERN
|
||||
UNIV_INLINE
|
||||
ibool
|
||||
ibuf_inside(void);
|
||||
/*=============*/
|
||||
ibuf_inside(
|
||||
/*========*/
|
||||
const mtr_t* mtr) /*!< in: mini-transaction */
|
||||
__attribute__((nonnull, pure));
|
||||
/***********************************************************************//**
|
||||
Checks if a page address is an ibuf bitmap page (level 3 page) address.
|
||||
@return TRUE if a bitmap page */
|
||||
|
@ -37,6 +37,30 @@ buffer inserts to this page. If there is this much of free space, the
|
||||
corresponding bits are set in the ibuf bitmap. */
|
||||
#define IBUF_PAGE_SIZE_PER_FREE_SPACE 32
|
||||
|
||||
/***************************************************************//**
|
||||
Starts an insert buffer mini-transaction. */
|
||||
UNIV_INLINE
|
||||
void
|
||||
ibuf_mtr_start(
|
||||
/*===========*/
|
||||
mtr_t* mtr) /*!< out: mini-transaction */
|
||||
{
|
||||
mtr_start(mtr);
|
||||
mtr->inside_ibuf = TRUE;
|
||||
}
|
||||
/***************************************************************//**
|
||||
Commits an insert buffer mini-transaction. */
|
||||
UNIV_INLINE
|
||||
void
|
||||
ibuf_mtr_commit(
|
||||
/*============*/
|
||||
mtr_t* mtr) /*!< in/out: mini-transaction */
|
||||
{
|
||||
ut_ad(mtr->inside_ibuf);
|
||||
ut_d(mtr->inside_ibuf = FALSE);
|
||||
mtr_commit(mtr);
|
||||
}
|
||||
|
||||
/** Insert buffer struct */
|
||||
struct ibuf_struct{
|
||||
ulint size; /*!< current size of the ibuf index
|
||||
@ -120,6 +144,22 @@ ibuf_should_try(
|
||||
return(FALSE);
|
||||
}
|
||||
|
||||
/******************************************************************//**
|
||||
Returns TRUE if the current OS thread is performing an insert buffer
|
||||
routine.
|
||||
|
||||
For instance, a read-ahead of non-ibuf pages is forbidden by threads
|
||||
that are executing an insert buffer routine.
|
||||
@return TRUE if inside an insert buffer routine */
|
||||
UNIV_INLINE
|
||||
ibool
|
||||
ibuf_inside(
|
||||
/*========*/
|
||||
const mtr_t* mtr) /*!< in: mini-transaction */
|
||||
{
|
||||
return(mtr->inside_ibuf);
|
||||
}
|
||||
|
||||
/***********************************************************************//**
|
||||
Checks if a page address is an ibuf bitmap page address.
|
||||
@return TRUE if a bitmap page */
|
||||
|
@ -190,21 +190,21 @@ functions). The page number parameter was originally written as 0. @{ */
|
||||
/* @} */
|
||||
|
||||
/***************************************************************//**
|
||||
Starts a mini-transaction and creates a mini-transaction handle
|
||||
and buffer in the memory buffer given by the caller.
|
||||
@return mtr buffer which also acts as the mtr handle */
|
||||
Starts a mini-transaction. */
|
||||
UNIV_INLINE
|
||||
mtr_t*
|
||||
void
|
||||
mtr_start(
|
||||
/*======*/
|
||||
mtr_t* mtr); /*!< in: memory buffer for the mtr buffer */
|
||||
mtr_t* mtr) /*!< out: mini-transaction */
|
||||
__attribute__((nonnull));
|
||||
/***************************************************************//**
|
||||
Commits a mini-transaction. */
|
||||
UNIV_INTERN
|
||||
void
|
||||
mtr_commit(
|
||||
/*=======*/
|
||||
mtr_t* mtr); /*!< in: mini-transaction */
|
||||
mtr_t* mtr) /*!< in/out: mini-transaction */
|
||||
__attribute__((nonnull));
|
||||
/**********************************************************//**
|
||||
Sets and returns a savepoint in mtr.
|
||||
@return savepoint */
|
||||
@ -378,6 +378,8 @@ struct mtr_struct{
|
||||
#endif
|
||||
dyn_array_t memo; /*!< memo stack for locks etc. */
|
||||
dyn_array_t log; /*!< mini-transaction log */
|
||||
ibool inside_ibuf;
|
||||
/*!< TRUE if inside ibuf changes */
|
||||
ibool modifications;
|
||||
/* TRUE if the mtr made modifications to
|
||||
buffer pool pages */
|
||||
|
@ -30,26 +30,23 @@ Created 11/26/1995 Heikki Tuuri
|
||||
#include "mach0data.h"
|
||||
|
||||
/***************************************************************//**
|
||||
Starts a mini-transaction and creates a mini-transaction handle
|
||||
and a buffer in the memory buffer given by the caller.
|
||||
@return mtr buffer which also acts as the mtr handle */
|
||||
Starts a mini-transaction. */
|
||||
UNIV_INLINE
|
||||
mtr_t*
|
||||
void
|
||||
mtr_start(
|
||||
/*======*/
|
||||
mtr_t* mtr) /*!< in: memory buffer for the mtr buffer */
|
||||
mtr_t* mtr) /*!< out: mini-transaction */
|
||||
{
|
||||
dyn_array_create(&(mtr->memo));
|
||||
dyn_array_create(&(mtr->log));
|
||||
|
||||
mtr->log_mode = MTR_LOG_ALL;
|
||||
mtr->modifications = FALSE;
|
||||
mtr->inside_ibuf = FALSE;
|
||||
mtr->n_log_recs = 0;
|
||||
|
||||
ut_d(mtr->state = MTR_ACTIVE);
|
||||
ut_d(mtr->magic_n = MTR_MAGIC_N);
|
||||
|
||||
return(mtr);
|
||||
}
|
||||
|
||||
/***************************************************//**
|
||||
|
@ -952,7 +952,7 @@ UNIV_INTERN
|
||||
ibool
|
||||
page_rec_validate(
|
||||
/*==============*/
|
||||
rec_t* rec, /*!< in: physical record */
|
||||
const rec_t* rec, /*!< in: physical record */
|
||||
const ulint* offsets);/*!< in: array returned by rec_get_offsets() */
|
||||
/***************************************************************//**
|
||||
Checks that the first directory slot points to the infimum record and
|
||||
@ -972,7 +972,7 @@ UNIV_INTERN
|
||||
ibool
|
||||
page_simple_validate_old(
|
||||
/*=====================*/
|
||||
page_t* page); /*!< in: old-style index page */
|
||||
const page_t* page); /*!< in: index page in ROW_FORMAT=REDUNDANT */
|
||||
/***************************************************************//**
|
||||
This function checks the consistency of an index page when we do not
|
||||
know the index. This is also resilient so that this should never crash
|
||||
@ -982,7 +982,7 @@ UNIV_INTERN
|
||||
ibool
|
||||
page_simple_validate_new(
|
||||
/*=====================*/
|
||||
page_t* block); /*!< in: new-style index page */
|
||||
const page_t* page); /*!< in: index page in ROW_FORMAT!=REDUNDANT */
|
||||
/***************************************************************//**
|
||||
This function checks the consistency of an index page.
|
||||
@return TRUE if ok */
|
||||
@ -990,7 +990,7 @@ UNIV_INTERN
|
||||
ibool
|
||||
page_validate(
|
||||
/*==========*/
|
||||
page_t* page, /*!< in: index page */
|
||||
const page_t* page, /*!< in: index page */
|
||||
dict_index_t* index); /*!< in: data dictionary index containing
|
||||
the page record type definition */
|
||||
/***************************************************************//**
|
||||
|
@ -600,6 +600,7 @@ ulint
|
||||
rec_offs_size(
|
||||
/*==========*/
|
||||
const ulint* offsets);/*!< in: array returned by rec_get_offsets() */
|
||||
#ifdef UNIV_DEBUG
|
||||
/**********************************************************//**
|
||||
Returns a pointer to the start of the record.
|
||||
@return pointer to start */
|
||||
@ -607,7 +608,7 @@ UNIV_INLINE
|
||||
byte*
|
||||
rec_get_start(
|
||||
/*==========*/
|
||||
rec_t* rec, /*!< in: pointer to record */
|
||||
const rec_t* rec, /*!< in: pointer to record */
|
||||
const ulint* offsets);/*!< in: array returned by rec_get_offsets() */
|
||||
/**********************************************************//**
|
||||
Returns a pointer to the end of the record.
|
||||
@ -616,8 +617,12 @@ UNIV_INLINE
|
||||
byte*
|
||||
rec_get_end(
|
||||
/*========*/
|
||||
rec_t* rec, /*!< in: pointer to record */
|
||||
const rec_t* rec, /*!< in: pointer to record */
|
||||
const ulint* offsets);/*!< in: array returned by rec_get_offsets() */
|
||||
#else /* UNIV_DEBUG */
|
||||
# define rec_get_start(rec, offsets) ((rec) - rec_offs_extra_size(offsets))
|
||||
# define rec_get_end(rec, offsets) ((rec) + rec_offs_data_size(offsets))
|
||||
#endif /* UNIV_DEBUG */
|
||||
/***************************************************************//**
|
||||
Copies a physical record to a buffer.
|
||||
@return pointer to the origin of the copy */
|
||||
|
@ -1462,6 +1462,7 @@ rec_offs_size(
|
||||
return(rec_offs_data_size(offsets) + rec_offs_extra_size(offsets));
|
||||
}
|
||||
|
||||
#ifdef UNIV_DEBUG
|
||||
/**********************************************************//**
|
||||
Returns a pointer to the end of the record.
|
||||
@return pointer to end */
|
||||
@ -1469,11 +1470,11 @@ UNIV_INLINE
|
||||
byte*
|
||||
rec_get_end(
|
||||
/*========*/
|
||||
rec_t* rec, /*!< in: pointer to record */
|
||||
const rec_t* rec, /*!< in: pointer to record */
|
||||
const ulint* offsets)/*!< in: array returned by rec_get_offsets() */
|
||||
{
|
||||
ut_ad(rec_offs_validate(rec, NULL, offsets));
|
||||
return(rec + rec_offs_data_size(offsets));
|
||||
return((rec_t*) rec + rec_offs_data_size(offsets));
|
||||
}
|
||||
|
||||
/**********************************************************//**
|
||||
@ -1483,12 +1484,13 @@ UNIV_INLINE
|
||||
byte*
|
||||
rec_get_start(
|
||||
/*==========*/
|
||||
rec_t* rec, /*!< in: pointer to record */
|
||||
const rec_t* rec, /*!< in: pointer to record */
|
||||
const ulint* offsets)/*!< in: array returned by rec_get_offsets() */
|
||||
{
|
||||
ut_ad(rec_offs_validate(rec, NULL, offsets));
|
||||
return(rec - rec_offs_extra_size(offsets));
|
||||
return((rec_t*) rec - rec_offs_extra_size(offsets));
|
||||
}
|
||||
#endif /* UNIV_DEBUG */
|
||||
|
||||
/***************************************************************//**
|
||||
Copies a physical record to a buffer.
|
||||
|
@ -442,16 +442,8 @@ typedef enum srv_stats_method_name_enum srv_stats_method_name_t;
|
||||
#ifndef UNIV_HOTBACKUP
|
||||
/** Types of threads existing in the system. */
|
||||
enum srv_thread_type {
|
||||
SRV_COM = 1, /**< threads serving communication and queries */
|
||||
SRV_CONSOLE, /**< thread serving console */
|
||||
SRV_WORKER, /**< threads serving parallelized queries and
|
||||
SRV_WORKER = 0, /**< threads serving parallelized queries and
|
||||
queries released from lock wait */
|
||||
#if 0
|
||||
/* Utility threads */
|
||||
SRV_BUFFER, /**< thread flushing dirty buffer blocks */
|
||||
SRV_RECOVERY, /**< threads finishing a recovery */
|
||||
SRV_INSERT, /**< thread flushing the insert buffer to disk */
|
||||
#endif
|
||||
SRV_MASTER /**< the master thread, (whose type number must
|
||||
be biggest) */
|
||||
};
|
||||
@ -490,13 +482,6 @@ ulint
|
||||
srv_get_n_threads(void);
|
||||
/*===================*/
|
||||
/*********************************************************************//**
|
||||
Returns the calling thread type.
|
||||
@return SRV_COM, ... */
|
||||
|
||||
enum srv_thread_type
|
||||
srv_get_thread_type(void);
|
||||
/*=====================*/
|
||||
/*********************************************************************//**
|
||||
Check whether thread type has reserved a slot.
|
||||
@return slot number or UNDEFINED if not found*/
|
||||
UNIV_INTERN
|
||||
|
@ -115,8 +115,11 @@ Prints warnings of long semaphore waits to stderr.
|
||||
@return TRUE if fatal semaphore wait threshold was exceeded */
|
||||
UNIV_INTERN
|
||||
ibool
|
||||
sync_array_print_long_waits(void);
|
||||
/*=============================*/
|
||||
sync_array_print_long_waits(
|
||||
/*========================*/
|
||||
os_thread_id_t* waiter, /*!< out: longest waiting thread */
|
||||
const void** sema) /*!< out: longest-waited-for semaphore */
|
||||
__attribute__((nonnull));
|
||||
/********************************************************************//**
|
||||
Validates the integrity of the wait array. Checks
|
||||
that the number of reserved cells equals the count variable. */
|
||||
|
@ -110,7 +110,6 @@ extern mysql_pfs_key_t syn_arr_mutex_key;
|
||||
extern mysql_pfs_key_t sync_thread_mutex_key;
|
||||
# endif /* UNIV_SYNC_DEBUG */
|
||||
extern mysql_pfs_key_t trx_doublewrite_mutex_key;
|
||||
extern mysql_pfs_key_t thr_local_mutex_key;
|
||||
extern mysql_pfs_key_t trx_undo_mutex_key;
|
||||
#endif /* UNIV_PFS_MUTEX */
|
||||
|
||||
|
@ -1,90 +0,0 @@
|
||||
/*****************************************************************************
|
||||
|
||||
Copyright (c) 1995, 2009, Innobase Oy. All Rights Reserved.
|
||||
|
||||
This program is free software; you can redistribute it and/or modify it under
|
||||
the terms of the GNU General Public License as published by the Free Software
|
||||
Foundation; version 2 of the License.
|
||||
|
||||
This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
|
||||
FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License along with
|
||||
this program; if not, write to the Free Software Foundation, Inc., 59 Temple
|
||||
Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
|
||||
*****************************************************************************/
|
||||
|
||||
/**************************************************//**
|
||||
@file include/thr0loc.h
|
||||
The thread local storage
|
||||
|
||||
Created 10/5/1995 Heikki Tuuri
|
||||
*******************************************************/
|
||||
|
||||
/* This module implements storage private to each thread,
|
||||
a capability useful in some situations like storing the
|
||||
OS handle to the current thread, or its priority. */
|
||||
|
||||
#ifndef thr0loc_h
|
||||
#define thr0loc_h
|
||||
|
||||
#include "univ.i"
|
||||
#include "os0thread.h"
|
||||
|
||||
/****************************************************************//**
|
||||
Initializes the thread local storage module. */
|
||||
UNIV_INTERN
|
||||
void
|
||||
thr_local_init(void);
|
||||
/*================*/
|
||||
/****************************************************************//**
|
||||
Close the thread local storage module. */
|
||||
UNIV_INTERN
|
||||
void
|
||||
thr_local_close(void);
|
||||
/*=================*/
|
||||
/*******************************************************************//**
|
||||
Creates a local storage struct for the calling new thread. */
|
||||
UNIV_INTERN
|
||||
void
|
||||
thr_local_create(void);
|
||||
/*==================*/
|
||||
/*******************************************************************//**
|
||||
Frees the local storage struct for the specified thread. */
|
||||
UNIV_INTERN
|
||||
void
|
||||
thr_local_free(
|
||||
/*===========*/
|
||||
os_thread_id_t id); /*!< in: thread id */
|
||||
/*******************************************************************//**
|
||||
Gets the slot number in the thread table of a thread.
|
||||
@return slot number */
|
||||
UNIV_INTERN
|
||||
ulint
|
||||
thr_local_get_slot_no(
|
||||
/*==================*/
|
||||
os_thread_id_t id); /*!< in: thread id of the thread */
|
||||
/*******************************************************************//**
|
||||
Sets in the local storage the slot number in the thread table of a thread. */
|
||||
UNIV_INTERN
|
||||
void
|
||||
thr_local_set_slot_no(
|
||||
/*==================*/
|
||||
os_thread_id_t id, /*!< in: thread id of the thread */
|
||||
ulint slot_no);/*!< in: slot number */
|
||||
/*******************************************************************//**
|
||||
Returns pointer to the 'in_ibuf' field within the current thread local
|
||||
storage.
|
||||
@return pointer to the in_ibuf field */
|
||||
UNIV_INTERN
|
||||
ibool*
|
||||
thr_local_get_in_ibuf_field(void);
|
||||
/*=============================*/
|
||||
|
||||
#ifndef UNIV_NONINL
|
||||
#include "thr0loc.ic"
|
||||
#endif
|
||||
|
||||
#endif
|
@ -1,24 +0,0 @@
|
||||
/*****************************************************************************
|
||||
|
||||
Copyright (c) 1995, 2009, Innobase Oy. All Rights Reserved.
|
||||
|
||||
This program is free software; you can redistribute it and/or modify it under
|
||||
the terms of the GNU General Public License as published by the Free Software
|
||||
Foundation; version 2 of the License.
|
||||
|
||||
This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
|
||||
FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License along with
|
||||
this program; if not, write to the Free Software Foundation, Inc., 59 Temple
|
||||
Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
|
||||
*****************************************************************************/
|
||||
|
||||
/**************************************************//**
|
||||
@file include/thr0loc.ic
|
||||
Thread local storage
|
||||
|
||||
Created 10/4/1995 Heikki Tuuri
|
||||
*******************************************************/
|
@ -24,6 +24,8 @@ but is included in mem0mem.* !
|
||||
Created 6/9/1994 Heikki Tuuri
|
||||
*************************************************************************/
|
||||
|
||||
#include "ha_prototypes.h"
|
||||
|
||||
#ifdef UNIV_MEM_DEBUG
|
||||
# ifndef UNIV_HOTBACKUP
|
||||
/* The mutex which protects in the debug version the hash table
|
||||
@ -400,7 +402,7 @@ mem_hash_remove(
|
||||
fprintf(stderr,
|
||||
"Memory heap or buffer freed in %s line %lu"
|
||||
" did not exist.\n",
|
||||
file_name, (ulong) line);
|
||||
innobase_basename(file_name), (ulong) line);
|
||||
ut_error;
|
||||
}
|
||||
|
||||
@ -419,8 +421,9 @@ mem_hash_remove(
|
||||
"in %s line %lu and tried to free in %s line %lu.\n"
|
||||
"Hex dump of 400 bytes around memory heap"
|
||||
" first block start:\n",
|
||||
node->nth_heap, node->file_name, (ulong) node->line,
|
||||
file_name, (ulong) line);
|
||||
node->nth_heap,
|
||||
innobase_basename(node->file_name), (ulong) node->line,
|
||||
innobase_basename(file_name), (ulong) line);
|
||||
ut_print_buf(stderr, (byte*)node->heap - 200, 400);
|
||||
fputs("\nDump of the mem heap:\n", stderr);
|
||||
mem_heap_validate_or_print(node->heap, NULL, TRUE, &error,
|
||||
@ -763,7 +766,8 @@ mem_validate_no_assert(void)
|
||||
"Inconsistency in memory heap"
|
||||
" or buffer created\n"
|
||||
"in %s line %lu.\n",
|
||||
node->file_name, node->line);
|
||||
innobase_basename(node->file_name),
|
||||
node->line);
|
||||
|
||||
mutex_exit(&mem_hash_mutex);
|
||||
|
||||
@ -989,7 +993,8 @@ mem_print_info_low(
|
||||
fprintf(outfile,
|
||||
"%lu: file %s line %lu of size %lu phys.size %lu"
|
||||
" with %lu blocks, type %lu\n",
|
||||
node->nth_heap, node->file_name, node->line,
|
||||
node->nth_heap,
|
||||
innobase_basename(node->file_name), node->line,
|
||||
allocated_mem, ph_size, n_blocks,
|
||||
(node->heap)->type);
|
||||
next_heap:
|
||||
|
@ -251,6 +251,7 @@ mtr_commit(
|
||||
ut_ad(mtr);
|
||||
ut_ad(mtr->magic_n == MTR_MAGIC_N);
|
||||
ut_ad(mtr->state == MTR_ACTIVE);
|
||||
ut_ad(!mtr->inside_ibuf);
|
||||
ut_d(mtr->state = MTR_COMMITTING);
|
||||
|
||||
#ifndef UNIV_HOTBACKUP
|
||||
|
@ -166,11 +166,11 @@ static
|
||||
ibool
|
||||
page_dir_slot_check(
|
||||
/*================*/
|
||||
page_dir_slot_t* slot) /*!< in: slot */
|
||||
const page_dir_slot_t* slot) /*!< in: slot */
|
||||
{
|
||||
page_t* page;
|
||||
ulint n_slots;
|
||||
ulint n_owned;
|
||||
const page_t* page;
|
||||
ulint n_slots;
|
||||
ulint n_owned;
|
||||
|
||||
ut_a(slot);
|
||||
|
||||
@ -1803,12 +1803,12 @@ UNIV_INTERN
|
||||
ibool
|
||||
page_rec_validate(
|
||||
/*==============*/
|
||||
rec_t* rec, /*!< in: physical record */
|
||||
const rec_t* rec, /*!< in: physical record */
|
||||
const ulint* offsets)/*!< in: array returned by rec_get_offsets() */
|
||||
{
|
||||
ulint n_owned;
|
||||
ulint heap_no;
|
||||
page_t* page;
|
||||
ulint n_owned;
|
||||
ulint heap_no;
|
||||
const page_t* page;
|
||||
|
||||
page = page_align(rec);
|
||||
ut_a(!page_is_comp(page) == !rec_offs_comp(offsets));
|
||||
@ -1889,16 +1889,16 @@ UNIV_INTERN
|
||||
ibool
|
||||
page_simple_validate_old(
|
||||
/*=====================*/
|
||||
page_t* page) /*!< in: old-style index page */
|
||||
const page_t* page) /*!< in: index page in ROW_FORMAT=REDUNDANT */
|
||||
{
|
||||
page_dir_slot_t* slot;
|
||||
ulint slot_no;
|
||||
ulint n_slots;
|
||||
rec_t* rec;
|
||||
byte* rec_heap_top;
|
||||
ulint count;
|
||||
ulint own_count;
|
||||
ibool ret = FALSE;
|
||||
const page_dir_slot_t* slot;
|
||||
ulint slot_no;
|
||||
ulint n_slots;
|
||||
const rec_t* rec;
|
||||
const byte* rec_heap_top;
|
||||
ulint count;
|
||||
ulint own_count;
|
||||
ibool ret = FALSE;
|
||||
|
||||
ut_a(!page_is_comp(page));
|
||||
|
||||
@ -2011,7 +2011,7 @@ page_simple_validate_old(
|
||||
goto func_exit;
|
||||
}
|
||||
|
||||
rec = page_rec_get_next(rec);
|
||||
rec = page_rec_get_next_const(rec);
|
||||
own_count++;
|
||||
}
|
||||
|
||||
@ -2072,7 +2072,7 @@ page_simple_validate_old(
|
||||
goto func_exit;
|
||||
}
|
||||
|
||||
rec = page_rec_get_next(rec);
|
||||
rec = page_rec_get_next_const(rec);
|
||||
}
|
||||
|
||||
if (UNIV_UNLIKELY(page_dir_get_n_heap(page) != count + 1)) {
|
||||
@ -2099,16 +2099,16 @@ UNIV_INTERN
|
||||
ibool
|
||||
page_simple_validate_new(
|
||||
/*=====================*/
|
||||
page_t* page) /*!< in: new-style index page */
|
||||
const page_t* page) /*!< in: index page in ROW_FORMAT!=REDUNDANT */
|
||||
{
|
||||
page_dir_slot_t* slot;
|
||||
ulint slot_no;
|
||||
ulint n_slots;
|
||||
rec_t* rec;
|
||||
byte* rec_heap_top;
|
||||
ulint count;
|
||||
ulint own_count;
|
||||
ibool ret = FALSE;
|
||||
const page_dir_slot_t* slot;
|
||||
ulint slot_no;
|
||||
ulint n_slots;
|
||||
const rec_t* rec;
|
||||
const byte* rec_heap_top;
|
||||
ulint count;
|
||||
ulint own_count;
|
||||
ibool ret = FALSE;
|
||||
|
||||
ut_a(page_is_comp(page));
|
||||
|
||||
@ -2221,7 +2221,7 @@ page_simple_validate_new(
|
||||
goto func_exit;
|
||||
}
|
||||
|
||||
rec = page_rec_get_next(rec);
|
||||
rec = page_rec_get_next_const(rec);
|
||||
own_count++;
|
||||
}
|
||||
|
||||
@ -2283,7 +2283,7 @@ page_simple_validate_new(
|
||||
goto func_exit;
|
||||
}
|
||||
|
||||
rec = page_rec_get_next(rec);
|
||||
rec = page_rec_get_next_const(rec);
|
||||
}
|
||||
|
||||
if (UNIV_UNLIKELY(page_dir_get_n_heap(page) != count + 1)) {
|
||||
@ -2308,26 +2308,26 @@ UNIV_INTERN
|
||||
ibool
|
||||
page_validate(
|
||||
/*==========*/
|
||||
page_t* page, /*!< in: index page */
|
||||
const page_t* page, /*!< in: index page */
|
||||
dict_index_t* index) /*!< in: data dictionary index containing
|
||||
the page record type definition */
|
||||
{
|
||||
page_dir_slot_t*slot;
|
||||
mem_heap_t* heap;
|
||||
byte* buf;
|
||||
ulint count;
|
||||
ulint own_count;
|
||||
ulint rec_own_count;
|
||||
ulint slot_no;
|
||||
ulint data_size;
|
||||
rec_t* rec;
|
||||
rec_t* old_rec = NULL;
|
||||
ulint offs;
|
||||
ulint n_slots;
|
||||
ibool ret = FALSE;
|
||||
ulint i;
|
||||
ulint* offsets = NULL;
|
||||
ulint* old_offsets = NULL;
|
||||
const page_dir_slot_t* slot;
|
||||
mem_heap_t* heap;
|
||||
byte* buf;
|
||||
ulint count;
|
||||
ulint own_count;
|
||||
ulint rec_own_count;
|
||||
ulint slot_no;
|
||||
ulint data_size;
|
||||
const rec_t* rec;
|
||||
const rec_t* old_rec = NULL;
|
||||
ulint offs;
|
||||
ulint n_slots;
|
||||
ibool ret = FALSE;
|
||||
ulint i;
|
||||
ulint* offsets = NULL;
|
||||
ulint* old_offsets = NULL;
|
||||
|
||||
if (UNIV_UNLIKELY((ibool) !!page_is_comp(page)
|
||||
!= dict_table_is_comp(index->table))) {
|
||||
@ -2482,7 +2482,7 @@ page_validate(
|
||||
count++;
|
||||
own_count++;
|
||||
old_rec = rec;
|
||||
rec = page_rec_get_next(rec);
|
||||
rec = page_rec_get_next_const(rec);
|
||||
|
||||
/* set old_offsets to offsets; recycle offsets */
|
||||
{
|
||||
@ -2556,7 +2556,7 @@ n_owned_zero:
|
||||
buf[offs + i] = 1;
|
||||
}
|
||||
|
||||
rec = page_rec_get_next(rec);
|
||||
rec = page_rec_get_next_const(rec);
|
||||
}
|
||||
|
||||
if (UNIV_UNLIKELY(page_dir_get_n_heap(page) != count + 1)) {
|
||||
|
@ -653,13 +653,13 @@ page_zip_dir_encode(
|
||||
Allocate memory for zlib. */
|
||||
static
|
||||
void*
|
||||
page_zip_malloc(
|
||||
page_zip_zalloc(
|
||||
/*============*/
|
||||
void* opaque, /*!< in/out: memory heap */
|
||||
uInt items, /*!< in: number of items to allocate */
|
||||
uInt size) /*!< in: size of an item in bytes */
|
||||
{
|
||||
return(mem_heap_alloc(opaque, items * size));
|
||||
return(mem_heap_zalloc(opaque, items * size));
|
||||
}
|
||||
|
||||
/**********************************************************************//**
|
||||
@ -684,7 +684,7 @@ page_zip_set_alloc(
|
||||
{
|
||||
z_stream* strm = stream;
|
||||
|
||||
strm->zalloc = page_zip_malloc;
|
||||
strm->zalloc = page_zip_zalloc;
|
||||
strm->zfree = page_zip_free;
|
||||
strm->opaque = heap;
|
||||
}
|
||||
@ -2912,19 +2912,18 @@ zlib_error:
|
||||
|
||||
page_zip_set_alloc(&d_stream, heap);
|
||||
|
||||
if (UNIV_UNLIKELY(inflateInit2(&d_stream, UNIV_PAGE_SIZE_SHIFT)
|
||||
!= Z_OK)) {
|
||||
ut_error;
|
||||
}
|
||||
|
||||
d_stream.next_in = page_zip->data + PAGE_DATA;
|
||||
/* Subtract the space reserved for
|
||||
the page header and the end marker of the modification log. */
|
||||
d_stream.avail_in = page_zip_get_size(page_zip) - (PAGE_DATA + 1);
|
||||
|
||||
d_stream.next_out = page + PAGE_ZIP_START;
|
||||
d_stream.avail_out = UNIV_PAGE_SIZE - PAGE_ZIP_START;
|
||||
|
||||
if (UNIV_UNLIKELY(inflateInit2(&d_stream, UNIV_PAGE_SIZE_SHIFT)
|
||||
!= Z_OK)) {
|
||||
ut_error;
|
||||
}
|
||||
|
||||
/* Decode the zlib header and the index information. */
|
||||
if (UNIV_UNLIKELY(inflate(&d_stream, Z_BLOCK) != Z_OK)) {
|
||||
|
||||
|
@ -66,7 +66,6 @@ Created 10/8/1995 Heikki Tuuri
|
||||
#include "mem0mem.h"
|
||||
#include "mem0pool.h"
|
||||
#include "sync0sync.h"
|
||||
#include "thr0loc.h"
|
||||
#include "que0que.h"
|
||||
#include "log0recv.h"
|
||||
#include "pars0pars.h"
|
||||
@ -690,7 +689,7 @@ Unix.*/
|
||||
struct srv_slot_struct{
|
||||
os_thread_id_t id; /*!< thread id */
|
||||
os_thread_t handle; /*!< thread handle */
|
||||
unsigned type:3; /*!< thread type: user, utility etc. */
|
||||
unsigned type:1; /*!< thread type: user, utility etc. */
|
||||
unsigned in_use:1; /*!< TRUE if this slot is in use */
|
||||
unsigned suspended:1; /*!< TRUE if the thread is waiting
|
||||
for the event of this slot */
|
||||
@ -797,6 +796,7 @@ srv_table_get_nth_slot(
|
||||
/*===================*/
|
||||
ulint index) /*!< in: index of the slot */
|
||||
{
|
||||
ut_ad(mutex_own(&kernel_mutex));
|
||||
ut_a(index < OS_THREAD_MAX_N);
|
||||
|
||||
return(srv_sys->threads + index);
|
||||
@ -815,7 +815,7 @@ srv_get_n_threads(void)
|
||||
|
||||
mutex_enter(&kernel_mutex);
|
||||
|
||||
for (i = SRV_COM; i < SRV_MASTER + 1; i++) {
|
||||
for (i = 0; i < SRV_MASTER + 1; i++) {
|
||||
|
||||
n_threads += srv_n_threads[i];
|
||||
}
|
||||
@ -825,13 +825,46 @@ srv_get_n_threads(void)
|
||||
return(n_threads);
|
||||
}
|
||||
|
||||
#ifdef UNIV_DEBUG
|
||||
/*********************************************************************//**
|
||||
Reserves a slot in the thread table for the current thread. Also creates the
|
||||
thread local storage struct for the current thread. NOTE! The server mutex
|
||||
has to be reserved by the caller!
|
||||
@return reserved slot index */
|
||||
Validates the type of a thread table slot.
|
||||
@return TRUE if ok */
|
||||
static
|
||||
ulint
|
||||
ibool
|
||||
srv_thread_type_validate(
|
||||
/*=====================*/
|
||||
enum srv_thread_type type) /*!< in: thread type */
|
||||
{
|
||||
switch (type) {
|
||||
case SRV_WORKER:
|
||||
case SRV_MASTER:
|
||||
return(TRUE);
|
||||
}
|
||||
ut_error;
|
||||
return(FALSE);
|
||||
}
|
||||
#endif /* UNIV_DEBUG */
|
||||
|
||||
/*********************************************************************//**
|
||||
Gets the type of a thread table slot.
|
||||
@return thread type */
|
||||
static
|
||||
enum srv_thread_type
|
||||
srv_slot_get_type(
|
||||
/*==============*/
|
||||
const srv_slot_t* slot) /*!< in: thread slot */
|
||||
{
|
||||
enum srv_thread_type type = (enum srv_thread_type) slot->type;
|
||||
ut_ad(srv_thread_type_validate(type));
|
||||
return(type);
|
||||
}
|
||||
|
||||
/*********************************************************************//**
|
||||
Reserves a slot in the thread table for the current thread.
|
||||
NOTE! The server mutex has to be reserved by the caller!
|
||||
@return reserved slot */
|
||||
static
|
||||
srv_slot_t*
|
||||
srv_table_reserve_slot(
|
||||
/*===================*/
|
||||
enum srv_thread_type type) /*!< in: type of the thread */
|
||||
@ -839,8 +872,7 @@ srv_table_reserve_slot(
|
||||
srv_slot_t* slot;
|
||||
ulint i;
|
||||
|
||||
ut_a(type > 0);
|
||||
ut_a(type <= SRV_MASTER);
|
||||
ut_ad(srv_thread_type_validate(type));
|
||||
ut_ad(mutex_own(&kernel_mutex));
|
||||
|
||||
i = 0;
|
||||
@ -851,53 +883,40 @@ srv_table_reserve_slot(
|
||||
slot = srv_table_get_nth_slot(i);
|
||||
}
|
||||
|
||||
ut_a(slot->in_use == FALSE);
|
||||
|
||||
slot->in_use = TRUE;
|
||||
slot->suspended = FALSE;
|
||||
slot->type = type;
|
||||
ut_ad(srv_slot_get_type(slot) == type);
|
||||
slot->id = os_thread_get_curr_id();
|
||||
slot->handle = os_thread_get_curr();
|
||||
|
||||
thr_local_create();
|
||||
|
||||
thr_local_set_slot_no(os_thread_get_curr_id(), i);
|
||||
|
||||
return(i);
|
||||
return(slot);
|
||||
}
|
||||
|
||||
/*********************************************************************//**
|
||||
Suspends the calling thread to wait for the event in its thread slot.
|
||||
NOTE! The server mutex has to be reserved by the caller!
|
||||
@return event for the calling thread to wait */
|
||||
NOTE! The server mutex has to be reserved by the caller! */
|
||||
static
|
||||
os_event_t
|
||||
srv_suspend_thread(void)
|
||||
/*====================*/
|
||||
void
|
||||
srv_suspend_thread(
|
||||
/*===============*/
|
||||
srv_slot_t* slot) /*!< in/out: thread slot */
|
||||
{
|
||||
srv_slot_t* slot;
|
||||
os_event_t event;
|
||||
ulint slot_no;
|
||||
enum srv_thread_type type;
|
||||
|
||||
ut_ad(mutex_own(&kernel_mutex));
|
||||
|
||||
slot_no = thr_local_get_slot_no(os_thread_get_curr_id());
|
||||
ut_ad(slot->in_use);
|
||||
ut_ad(!slot->suspended);
|
||||
ut_ad(slot->id == os_thread_get_curr_id());
|
||||
|
||||
if (srv_print_thread_releases) {
|
||||
fprintf(stderr,
|
||||
"Suspending thread %lu to slot %lu\n",
|
||||
(ulong) os_thread_get_curr_id(), (ulong) slot_no);
|
||||
(ulong) os_thread_get_curr_id(),
|
||||
(ulong) (slot - srv_sys->threads));
|
||||
}
|
||||
|
||||
slot = srv_table_get_nth_slot(slot_no);
|
||||
|
||||
type = slot->type;
|
||||
|
||||
ut_ad(type >= SRV_WORKER);
|
||||
ut_ad(type <= SRV_MASTER);
|
||||
|
||||
event = slot->event;
|
||||
type = srv_slot_get_type(slot);
|
||||
|
||||
slot->suspended = TRUE;
|
||||
|
||||
@ -905,9 +924,7 @@ srv_suspend_thread(void)
|
||||
|
||||
srv_n_threads_active[type]--;
|
||||
|
||||
os_event_reset(event);
|
||||
|
||||
return(event);
|
||||
os_event_reset(slot->event);
|
||||
}
|
||||
|
||||
/*********************************************************************//**
|
||||
@ -926,8 +943,7 @@ srv_release_threads(
|
||||
ulint i;
|
||||
ulint count = 0;
|
||||
|
||||
ut_ad(type >= SRV_WORKER);
|
||||
ut_ad(type <= SRV_MASTER);
|
||||
ut_ad(srv_thread_type_validate(type));
|
||||
ut_ad(n > 0);
|
||||
ut_ad(mutex_own(&kernel_mutex));
|
||||
|
||||
@ -935,7 +951,8 @@ srv_release_threads(
|
||||
|
||||
slot = srv_table_get_nth_slot(i);
|
||||
|
||||
if (slot->in_use && slot->type == type && slot->suspended) {
|
||||
if (slot->in_use && slot->suspended
|
||||
&& srv_slot_get_type(slot) == type) {
|
||||
|
||||
slot->suspended = FALSE;
|
||||
|
||||
@ -962,34 +979,6 @@ srv_release_threads(
|
||||
return(count);
|
||||
}
|
||||
|
||||
/*********************************************************************//**
|
||||
Returns the calling thread type.
|
||||
@return SRV_COM, ... */
|
||||
UNIV_INTERN
|
||||
enum srv_thread_type
|
||||
srv_get_thread_type(void)
|
||||
/*=====================*/
|
||||
{
|
||||
ulint slot_no;
|
||||
srv_slot_t* slot;
|
||||
enum srv_thread_type type;
|
||||
|
||||
mutex_enter(&kernel_mutex);
|
||||
|
||||
slot_no = thr_local_get_slot_no(os_thread_get_curr_id());
|
||||
|
||||
slot = srv_table_get_nth_slot(slot_no);
|
||||
|
||||
type = slot->type;
|
||||
|
||||
ut_ad(type >= SRV_WORKER);
|
||||
ut_ad(type <= SRV_MASTER);
|
||||
|
||||
mutex_exit(&kernel_mutex);
|
||||
|
||||
return(type);
|
||||
}
|
||||
|
||||
/*********************************************************************//**
|
||||
Check whether thread type has reserved a slot. Return the first slot that
|
||||
is found. This works because we currently have only 1 thread of each type.
|
||||
@ -1003,6 +992,7 @@ srv_thread_has_reserved_slot(
|
||||
ulint i;
|
||||
ulint slot_no = ULINT_UNDEFINED;
|
||||
|
||||
ut_ad(srv_thread_type_validate(type));
|
||||
mutex_enter(&kernel_mutex);
|
||||
|
||||
for (i = 0; i < OS_THREAD_MAX_N; i++) {
|
||||
@ -1040,22 +1030,18 @@ srv_init(void)
|
||||
mutex_create(srv_innodb_monitor_mutex_key,
|
||||
&srv_innodb_monitor_mutex, SYNC_NO_ORDER_CHECK);
|
||||
|
||||
srv_sys->threads = mem_alloc(OS_THREAD_MAX_N * sizeof(srv_slot_t));
|
||||
srv_sys->threads = mem_zalloc(OS_THREAD_MAX_N * sizeof(srv_slot_t));
|
||||
|
||||
for (i = 0; i < OS_THREAD_MAX_N; i++) {
|
||||
slot = srv_table_get_nth_slot(i);
|
||||
slot->in_use = FALSE;
|
||||
slot->type=0; /* Avoid purify errors */
|
||||
slot = srv_sys->threads + i;
|
||||
slot->event = os_event_create(NULL);
|
||||
ut_a(slot->event);
|
||||
}
|
||||
|
||||
srv_mysql_table = mem_alloc(OS_THREAD_MAX_N * sizeof(srv_slot_t));
|
||||
srv_mysql_table = mem_zalloc(OS_THREAD_MAX_N * sizeof(srv_slot_t));
|
||||
|
||||
for (i = 0; i < OS_THREAD_MAX_N; i++) {
|
||||
slot = srv_mysql_table + i;
|
||||
slot->in_use = FALSE;
|
||||
slot->type = 0;
|
||||
slot->event = os_event_create(NULL);
|
||||
ut_a(slot->event);
|
||||
}
|
||||
@ -1142,7 +1128,6 @@ srv_general_init(void)
|
||||
os_sync_init();
|
||||
sync_init();
|
||||
mem_init(srv_mem_pool_size);
|
||||
thr_local_init();
|
||||
}
|
||||
|
||||
/*======================= InnoDB Server FIFO queue =======================*/
|
||||
@ -1501,7 +1486,7 @@ srv_table_reserve_slot_for_mysql(void)
|
||||
while (slot->in_use) {
|
||||
i++;
|
||||
|
||||
if (i >= OS_THREAD_MAX_N) {
|
||||
if (UNIV_UNLIKELY(i >= OS_THREAD_MAX_N)) {
|
||||
|
||||
ut_print_timestamp(stderr);
|
||||
|
||||
@ -2382,6 +2367,12 @@ srv_error_monitor_thread(
|
||||
ib_uint64_t old_lsn;
|
||||
ib_uint64_t new_lsn;
|
||||
ib_int64_t sig_count;
|
||||
/* longest waiting thread for a semaphore */
|
||||
os_thread_id_t waiter = os_thread_get_curr_id();
|
||||
os_thread_id_t old_waiter = waiter;
|
||||
/* the semaphore that is being waited for */
|
||||
const void* sema = NULL;
|
||||
const void* old_sema = NULL;
|
||||
|
||||
old_lsn = srv_start_lsn;
|
||||
|
||||
@ -2435,7 +2426,8 @@ loop:
|
||||
|
||||
sync_arr_wake_threads_if_sema_free();
|
||||
|
||||
if (sync_array_print_long_waits()) {
|
||||
if (sync_array_print_long_waits(&waiter, &sema)
|
||||
&& sema == old_sema && os_thread_eq(waiter, old_waiter)) {
|
||||
fatal_cnt++;
|
||||
if (fatal_cnt > 10) {
|
||||
|
||||
@ -2450,6 +2442,8 @@ loop:
|
||||
}
|
||||
} else {
|
||||
fatal_cnt = 0;
|
||||
old_waiter = waiter;
|
||||
old_sema = sema;
|
||||
}
|
||||
|
||||
/* Flush stderr so that a database user gets the output
|
||||
@ -2489,7 +2483,7 @@ srv_is_any_background_thread_active(void)
|
||||
|
||||
mutex_enter(&kernel_mutex);
|
||||
|
||||
for (i = SRV_COM; i <= SRV_MASTER; ++i) {
|
||||
for (i = 0; i <= SRV_MASTER; ++i) {
|
||||
if (srv_n_threads_active[i] != 0) {
|
||||
ret = TRUE;
|
||||
break;
|
||||
@ -2643,7 +2637,7 @@ srv_master_thread(
|
||||
os_thread_create */
|
||||
{
|
||||
buf_pool_stat_t buf_stat;
|
||||
os_event_t event;
|
||||
srv_slot_t* slot;
|
||||
ulint old_activity_count;
|
||||
ulint n_pages_purged = 0;
|
||||
ulint n_bytes_merged;
|
||||
@ -2671,7 +2665,7 @@ srv_master_thread(
|
||||
|
||||
mutex_enter(&kernel_mutex);
|
||||
|
||||
srv_table_reserve_slot(SRV_MASTER);
|
||||
slot = srv_table_reserve_slot(SRV_MASTER);
|
||||
|
||||
srv_n_threads_active[SRV_MASTER]++;
|
||||
|
||||
@ -3060,7 +3054,7 @@ suspend_thread:
|
||||
goto loop;
|
||||
}
|
||||
|
||||
event = srv_suspend_thread();
|
||||
srv_suspend_thread(slot);
|
||||
|
||||
mutex_exit(&kernel_mutex);
|
||||
|
||||
@ -3070,7 +3064,7 @@ suspend_thread:
|
||||
manual also mentions this string in several places. */
|
||||
srv_main_thread_op_info = "waiting for server activity";
|
||||
|
||||
os_event_wait(event);
|
||||
os_event_wait(slot->event);
|
||||
|
||||
if (srv_shutdown_state == SRV_SHUTDOWN_EXIT_THREADS) {
|
||||
/* This is only extra safety, the thread should exit
|
||||
@ -3084,8 +3078,6 @@ suspend_thread:
|
||||
main thread goes back to loop. */
|
||||
|
||||
goto loop;
|
||||
|
||||
OS_THREAD_DUMMY_RETURN; /* Not reached, avoid compiler warning */
|
||||
}
|
||||
|
||||
/*********************************************************************//**
|
||||
@ -3100,7 +3092,6 @@ srv_purge_thread(
|
||||
{
|
||||
srv_slot_t* slot;
|
||||
ulint retries = 0;
|
||||
ulint slot_no = ULINT_UNDEFINED;
|
||||
ulint n_total_purged = ULINT_UNDEFINED;
|
||||
|
||||
ut_a(srv_n_purge_threads == 1);
|
||||
@ -3116,9 +3107,7 @@ srv_purge_thread(
|
||||
|
||||
mutex_enter(&kernel_mutex);
|
||||
|
||||
slot_no = srv_table_reserve_slot(SRV_WORKER);
|
||||
|
||||
slot = srv_table_get_nth_slot(slot_no);
|
||||
slot = srv_table_reserve_slot(SRV_WORKER);
|
||||
|
||||
++srv_n_threads_active[SRV_WORKER];
|
||||
|
||||
@ -3137,15 +3126,13 @@ srv_purge_thread(
|
||||
|| (n_total_purged == 0
|
||||
&& retries >= TRX_SYS_N_RSEGS)) {
|
||||
|
||||
os_event_t event;
|
||||
|
||||
mutex_enter(&kernel_mutex);
|
||||
|
||||
event = srv_suspend_thread();
|
||||
srv_suspend_thread(slot);
|
||||
|
||||
mutex_exit(&kernel_mutex);
|
||||
|
||||
os_event_wait(event);
|
||||
os_event_wait(slot->event);
|
||||
|
||||
retries = 0;
|
||||
}
|
||||
@ -3179,16 +3166,11 @@ srv_purge_thread(
|
||||
|
||||
mutex_enter(&kernel_mutex);
|
||||
|
||||
ut_ad(srv_table_get_nth_slot(slot_no) == slot);
|
||||
|
||||
/* Decrement the active count. */
|
||||
srv_suspend_thread();
|
||||
srv_suspend_thread(slot);
|
||||
|
||||
slot->in_use = FALSE;
|
||||
|
||||
/* Free the thread local memory. */
|
||||
thr_local_free(os_thread_get_curr_id());
|
||||
|
||||
mutex_exit(&kernel_mutex);
|
||||
|
||||
#ifdef UNIV_DEBUG_THREAD_CREATION
|
||||
|
@ -85,7 +85,6 @@ Created 2/16/1996 Heikki Tuuri
|
||||
# include "row0row.h"
|
||||
# include "row0mysql.h"
|
||||
# include "btr0pcur.h"
|
||||
# include "thr0loc.h"
|
||||
# include "os0sync.h" /* for INNODB_RW_LOCKS_USE_ATOMICS */
|
||||
# include "zlib.h" /* for ZLIB_VERSION */
|
||||
|
||||
@ -2210,7 +2209,6 @@ innobase_shutdown_for_mysql(void)
|
||||
ibuf_close();
|
||||
log_shutdown();
|
||||
lock_sys_close();
|
||||
thr_local_close();
|
||||
trx_sys_file_format_close();
|
||||
trx_sys_close();
|
||||
|
||||
|
@ -40,6 +40,7 @@ Created 9/5/1995 Heikki Tuuri
|
||||
#include "os0sync.h"
|
||||
#include "os0file.h"
|
||||
#include "srv0srv.h"
|
||||
#include "ha_prototypes.h"
|
||||
|
||||
/*
|
||||
WAIT ARRAY
|
||||
@ -478,8 +479,8 @@ sync_array_cell_print(
|
||||
fprintf(file,
|
||||
"--Thread %lu has waited at %s line %lu"
|
||||
" for %.2f seconds the semaphore:\n",
|
||||
(ulong) os_thread_pf(cell->thread), cell->file,
|
||||
(ulong) cell->line,
|
||||
(ulong) os_thread_pf(cell->thread),
|
||||
innobase_basename(cell->file), (ulong) cell->line,
|
||||
difftime(time(NULL), cell->reservation_time));
|
||||
|
||||
if (type == SYNC_MUTEX) {
|
||||
@ -493,7 +494,8 @@ sync_array_cell_print(
|
||||
"Last time reserved in file %s line %lu, "
|
||||
#endif /* UNIV_SYNC_DEBUG */
|
||||
"waiters flag %lu\n",
|
||||
(void*) mutex, mutex->cfile_name, (ulong) mutex->cline,
|
||||
(void*) mutex, innobase_basename(mutex->cfile_name),
|
||||
(ulong) mutex->cline,
|
||||
(ulong) mutex->lock_word,
|
||||
#ifdef UNIV_SYNC_DEBUG
|
||||
mutex->file_name, (ulong) mutex->line,
|
||||
@ -512,7 +514,7 @@ sync_array_cell_print(
|
||||
|
||||
fprintf(file,
|
||||
" RW-latch at %p created in file %s line %lu\n",
|
||||
(void*) rwlock, rwlock->cfile_name,
|
||||
(void*) rwlock, innobase_basename(rwlock->cfile_name),
|
||||
(ulong) rwlock->cline);
|
||||
writer = rw_lock_get_writer(rwlock);
|
||||
if (writer != RW_LOCK_NOT_LOCKED) {
|
||||
@ -533,7 +535,7 @@ sync_array_cell_print(
|
||||
(ulong) rw_lock_get_reader_count(rwlock),
|
||||
(ulong) rwlock->waiters,
|
||||
rwlock->lock_word,
|
||||
rwlock->last_s_file_name,
|
||||
innobase_basename(rwlock->last_s_file_name),
|
||||
(ulong) rwlock->last_s_line,
|
||||
rwlock->last_x_file_name,
|
||||
(ulong) rwlock->last_x_line);
|
||||
@ -913,8 +915,10 @@ Prints warnings of long semaphore waits to stderr.
|
||||
@return TRUE if fatal semaphore wait threshold was exceeded */
|
||||
UNIV_INTERN
|
||||
ibool
|
||||
sync_array_print_long_waits(void)
|
||||
/*=============================*/
|
||||
sync_array_print_long_waits(
|
||||
/*========================*/
|
||||
os_thread_id_t* waiter, /*!< out: longest waiting thread */
|
||||
const void** sema) /*!< out: longest-waited-for semaphore */
|
||||
{
|
||||
sync_cell_t* cell;
|
||||
ibool old_val;
|
||||
@ -922,6 +926,7 @@ sync_array_print_long_waits(void)
|
||||
ulint i;
|
||||
ulint fatal_timeout = srv_fatal_semaphore_wait_threshold;
|
||||
ibool fatal = FALSE;
|
||||
double longest_diff = 0;
|
||||
|
||||
#ifdef UNIV_DEBUG_VALGRIND
|
||||
/* Increase the timeouts if running under valgrind because it executes
|
||||
@ -937,22 +942,36 @@ sync_array_print_long_waits(void)
|
||||
|
||||
for (i = 0; i < sync_primary_wait_array->n_cells; i++) {
|
||||
|
||||
double diff;
|
||||
void* wait_object;
|
||||
|
||||
cell = sync_array_get_nth_cell(sync_primary_wait_array, i);
|
||||
|
||||
if (cell->wait_object != NULL && cell->waiting
|
||||
&& difftime(time(NULL), cell->reservation_time)
|
||||
> SYNC_ARRAY_TIMEOUT) {
|
||||
wait_object = cell->wait_object;
|
||||
|
||||
if (wait_object == NULL || !cell->waiting) {
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
diff = difftime(time(NULL), cell->reservation_time);
|
||||
|
||||
if (diff > SYNC_ARRAY_TIMEOUT) {
|
||||
fputs("InnoDB: Warning: a long semaphore wait:\n",
|
||||
stderr);
|
||||
sync_array_cell_print(stderr, cell);
|
||||
noticed = TRUE;
|
||||
}
|
||||
|
||||
if (cell->wait_object != NULL && cell->waiting
|
||||
&& difftime(time(NULL), cell->reservation_time)
|
||||
> fatal_timeout) {
|
||||
if (diff > fatal_timeout) {
|
||||
fatal = TRUE;
|
||||
}
|
||||
|
||||
if (diff > longest_diff) {
|
||||
longest_diff = diff;
|
||||
*sema = wait_object;
|
||||
*waiter = cell->thread;
|
||||
}
|
||||
}
|
||||
|
||||
if (noticed) {
|
||||
|
@ -39,6 +39,7 @@ Created 9/11/1995 Heikki Tuuri
|
||||
#include "mem0mem.h"
|
||||
#include "srv0srv.h"
|
||||
#include "os0sync.h" /* for INNODB_RW_LOCKS_USE_ATOMICS */
|
||||
#include "ha_prototypes.h"
|
||||
|
||||
/*
|
||||
IMPLEMENTATION OF THE RW_LOCK
|
||||
@ -407,7 +408,8 @@ lock_loop:
|
||||
" cfile %s cline %lu rnds %lu\n",
|
||||
(ulong) os_thread_pf(os_thread_get_curr_id()),
|
||||
(void*) lock,
|
||||
lock->cfile_name, (ulong) lock->cline, (ulong) i);
|
||||
innobase_basename(lock->cfile_name),
|
||||
(ulong) lock->cline, (ulong) i);
|
||||
}
|
||||
|
||||
/* We try once again to obtain the lock */
|
||||
@ -442,7 +444,8 @@ lock_loop:
|
||||
"Thread %lu OS wait rw-s-lock at %p"
|
||||
" cfile %s cline %lu\n",
|
||||
os_thread_pf(os_thread_get_curr_id()),
|
||||
(void*) lock, lock->cfile_name,
|
||||
(void*) lock,
|
||||
innobase_basename(lock->cfile_name),
|
||||
(ulong) lock->cline);
|
||||
}
|
||||
|
||||
@ -664,7 +667,8 @@ lock_loop:
|
||||
"Thread %lu spin wait rw-x-lock at %p"
|
||||
" cfile %s cline %lu rnds %lu\n",
|
||||
os_thread_pf(os_thread_get_curr_id()), (void*) lock,
|
||||
lock->cfile_name, (ulong) lock->cline, (ulong) i);
|
||||
innobase_basename(lock->cfile_name),
|
||||
(ulong) lock->cline, (ulong) i);
|
||||
}
|
||||
|
||||
sync_array_reserve_cell(sync_primary_wait_array,
|
||||
@ -687,7 +691,8 @@ lock_loop:
|
||||
"Thread %lu OS wait for rw-x-lock at %p"
|
||||
" cfile %s cline %lu\n",
|
||||
os_thread_pf(os_thread_get_curr_id()), (void*) lock,
|
||||
lock->cfile_name, (ulong) lock->cline);
|
||||
innobase_basename(lock->cfile_name),
|
||||
(ulong) lock->cline);
|
||||
}
|
||||
|
||||
/* these stats may not be accurate */
|
||||
|
@ -43,6 +43,7 @@ Created 9/5/1995 Heikki Tuuri
|
||||
#ifdef UNIV_SYNC_DEBUG
|
||||
# include "srv0start.h" /* srv_is_being_started */
|
||||
#endif /* UNIV_SYNC_DEBUG */
|
||||
#include "ha_prototypes.h"
|
||||
|
||||
/*
|
||||
REASONS FOR IMPLEMENTING THE SPIN LOCK MUTEX
|
||||
@ -543,7 +544,8 @@ spin_loop:
|
||||
"Thread %lu spin wait mutex at %p"
|
||||
" cfile %s cline %lu rnds %lu\n",
|
||||
(ulong) os_thread_pf(os_thread_get_curr_id()), (void*) mutex,
|
||||
mutex->cfile_name, (ulong) mutex->cline, (ulong) i);
|
||||
innobase_basename(mutex->cfile_name),
|
||||
(ulong) mutex->cline, (ulong) i);
|
||||
#endif
|
||||
|
||||
mutex_spin_round_count += i;
|
||||
@ -620,7 +622,8 @@ spin_loop:
|
||||
fprintf(stderr,
|
||||
"Thread %lu OS wait mutex at %p cfile %s cline %lu rnds %lu\n",
|
||||
(ulong) os_thread_pf(os_thread_get_curr_id()), (void*) mutex,
|
||||
mutex->cfile_name, (ulong) mutex->cline, (ulong) i);
|
||||
innobase_basename(mutex->cfile_name),
|
||||
(ulong) mutex->cline, (ulong) i);
|
||||
#endif
|
||||
|
||||
mutex_os_wait_count++;
|
||||
@ -869,7 +872,8 @@ sync_print_warning(
|
||||
if (mutex->magic_n == MUTEX_MAGIC_N) {
|
||||
fprintf(stderr,
|
||||
"Mutex created at %s %lu\n",
|
||||
mutex->cfile_name, (ulong) mutex->cline);
|
||||
innobase_basename(mutex->cfile_name),
|
||||
(ulong) mutex->cline);
|
||||
|
||||
if (mutex_get_lock_word(mutex) != 0) {
|
||||
ulint line;
|
||||
|
@ -1,307 +0,0 @@
|
||||
/*****************************************************************************
|
||||
|
||||
Copyright (c) 1995, 2009, Innobase Oy. All Rights Reserved.
|
||||
|
||||
This program is free software; you can redistribute it and/or modify it under
|
||||
the terms of the GNU General Public License as published by the Free Software
|
||||
Foundation; version 2 of the License.
|
||||
|
||||
This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
|
||||
FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License along with
|
||||
this program; if not, write to the Free Software Foundation, Inc., 59 Temple
|
||||
Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
|
||||
*****************************************************************************/
|
||||
|
||||
/**************************************************//**
|
||||
@file thr/thr0loc.c
|
||||
The thread local storage
|
||||
|
||||
Created 10/5/1995 Heikki Tuuri
|
||||
*******************************************************/
|
||||
|
||||
#include "thr0loc.h"
|
||||
#ifdef UNIV_NONINL
|
||||
#include "thr0loc.ic"
|
||||
#endif
|
||||
|
||||
#include "sync0sync.h"
|
||||
#include "hash0hash.h"
|
||||
#include "mem0mem.h"
|
||||
#include "srv0srv.h"
|
||||
|
||||
/*
|
||||
IMPLEMENTATION OF THREAD LOCAL STORAGE
|
||||
======================================
|
||||
|
||||
The threads sometimes need private data which depends on the thread id.
|
||||
This is implemented as a hash table, where the hash value is calculated
|
||||
from the thread id, to prepare for a large number of threads. The hash table
|
||||
is protected by a mutex. If you need modify the program and put new data to
|
||||
the thread local storage, just add it to struct thr_local_struct in the
|
||||
header file. */
|
||||
|
||||
/** Mutex protecting thr_local_hash */
|
||||
static mutex_t thr_local_mutex;
|
||||
|
||||
/** The hash table. The module is not yet initialized when it is NULL. */
|
||||
static hash_table_t* thr_local_hash = NULL;
|
||||
|
||||
/** Thread local data */
|
||||
typedef struct thr_local_struct thr_local_t;
|
||||
|
||||
#ifdef UNIV_PFS_MUTEX
|
||||
/* Key to register the mutex with performance schema */
|
||||
UNIV_INTERN mysql_pfs_key_t thr_local_mutex_key;
|
||||
#endif /* UNIV_PFS_MUTEX */
|
||||
|
||||
/** @brief Thread local data.
|
||||
The private data for each thread should be put to
|
||||
the structure below and the accessor functions written
|
||||
for the field. */
|
||||
struct thr_local_struct{
|
||||
os_thread_id_t id; /*!< id of the thread which owns this struct */
|
||||
os_thread_t handle; /*!< operating system handle to the thread */
|
||||
ulint slot_no;/*!< the index of the slot in the thread table
|
||||
for this thread */
|
||||
ibool in_ibuf;/*!< TRUE if the thread is doing an ibuf
|
||||
operation */
|
||||
hash_node_t hash; /*!< hash chain node */
|
||||
ulint magic_n;/*!< magic number (THR_LOCAL_MAGIC_N) */
|
||||
};
|
||||
|
||||
/** The value of thr_local_struct::magic_n */
|
||||
#define THR_LOCAL_MAGIC_N 1231234
|
||||
|
||||
#ifdef UNIV_DEBUG
|
||||
/*******************************************************************//**
|
||||
Validates thread local data.
|
||||
@return TRUE if valid */
|
||||
static
|
||||
ibool
|
||||
thr_local_validate(
|
||||
/*===============*/
|
||||
const thr_local_t* local) /*!< in: data to validate */
|
||||
{
|
||||
ut_ad(local->magic_n == THR_LOCAL_MAGIC_N);
|
||||
ut_ad(local->slot_no == ULINT_UNDEFINED
|
||||
|| local->slot_no < OS_THREAD_MAX_N);
|
||||
ut_ad(local->in_ibuf == FALSE || local->in_ibuf == TRUE);
|
||||
return(TRUE);
|
||||
}
|
||||
#endif /* UNIV_DEBUG */
|
||||
|
||||
/*******************************************************************//**
|
||||
Returns the local storage struct for a thread.
|
||||
@return local storage */
|
||||
static
|
||||
thr_local_t*
|
||||
thr_local_get(
|
||||
/*==========*/
|
||||
os_thread_id_t id) /*!< in: thread id of the thread */
|
||||
{
|
||||
thr_local_t* local;
|
||||
|
||||
try_again:
|
||||
ut_ad(thr_local_hash);
|
||||
ut_ad(mutex_own(&thr_local_mutex));
|
||||
|
||||
/* Look for the local struct in the hash table */
|
||||
|
||||
local = NULL;
|
||||
|
||||
HASH_SEARCH(hash, thr_local_hash, os_thread_pf(id),
|
||||
thr_local_t*, local, ut_ad(thr_local_validate(local)),
|
||||
os_thread_eq(local->id, id));
|
||||
if (local == NULL) {
|
||||
mutex_exit(&thr_local_mutex);
|
||||
|
||||
thr_local_create();
|
||||
|
||||
mutex_enter(&thr_local_mutex);
|
||||
|
||||
goto try_again;
|
||||
}
|
||||
|
||||
ut_ad(thr_local_validate(local));
|
||||
|
||||
return(local);
|
||||
}
|
||||
|
||||
/*******************************************************************//**
|
||||
Gets the slot number in the thread table of a thread.
|
||||
@return slot number */
|
||||
UNIV_INTERN
|
||||
ulint
|
||||
thr_local_get_slot_no(
|
||||
/*==================*/
|
||||
os_thread_id_t id) /*!< in: thread id of the thread */
|
||||
{
|
||||
ulint slot_no;
|
||||
thr_local_t* local;
|
||||
|
||||
mutex_enter(&thr_local_mutex);
|
||||
|
||||
local = thr_local_get(id);
|
||||
|
||||
slot_no = local->slot_no;
|
||||
|
||||
mutex_exit(&thr_local_mutex);
|
||||
|
||||
return(slot_no);
|
||||
}
|
||||
|
||||
/*******************************************************************//**
|
||||
Sets the slot number in the thread table of a thread. */
|
||||
UNIV_INTERN
|
||||
void
|
||||
thr_local_set_slot_no(
|
||||
/*==================*/
|
||||
os_thread_id_t id, /*!< in: thread id of the thread */
|
||||
ulint slot_no)/*!< in: slot number */
|
||||
{
|
||||
thr_local_t* local;
|
||||
|
||||
mutex_enter(&thr_local_mutex);
|
||||
|
||||
local = thr_local_get(id);
|
||||
|
||||
local->slot_no = slot_no;
|
||||
|
||||
mutex_exit(&thr_local_mutex);
|
||||
}
|
||||
|
||||
/*******************************************************************//**
|
||||
Returns pointer to the 'in_ibuf' field within the current thread local
|
||||
storage.
|
||||
@return pointer to the in_ibuf field */
|
||||
UNIV_INTERN
|
||||
ibool*
|
||||
thr_local_get_in_ibuf_field(void)
|
||||
/*=============================*/
|
||||
{
|
||||
thr_local_t* local;
|
||||
|
||||
mutex_enter(&thr_local_mutex);
|
||||
|
||||
local = thr_local_get(os_thread_get_curr_id());
|
||||
|
||||
mutex_exit(&thr_local_mutex);
|
||||
|
||||
return(&(local->in_ibuf));
|
||||
}
|
||||
|
||||
/*******************************************************************//**
|
||||
Creates a local storage struct for the calling new thread. */
|
||||
UNIV_INTERN
|
||||
void
|
||||
thr_local_create(void)
|
||||
/*==================*/
|
||||
{
|
||||
thr_local_t* local;
|
||||
|
||||
if (thr_local_hash == NULL) {
|
||||
thr_local_init();
|
||||
}
|
||||
|
||||
local = mem_alloc(sizeof(thr_local_t));
|
||||
|
||||
local->id = os_thread_get_curr_id();
|
||||
local->handle = os_thread_get_curr();
|
||||
local->magic_n = THR_LOCAL_MAGIC_N;
|
||||
local->slot_no = ULINT_UNDEFINED;
|
||||
local->in_ibuf = FALSE;
|
||||
|
||||
mutex_enter(&thr_local_mutex);
|
||||
|
||||
HASH_INSERT(thr_local_t, hash, thr_local_hash,
|
||||
os_thread_pf(os_thread_get_curr_id()),
|
||||
local);
|
||||
|
||||
mutex_exit(&thr_local_mutex);
|
||||
}
|
||||
|
||||
/*******************************************************************//**
|
||||
Frees the local storage struct for the specified thread. */
|
||||
UNIV_INTERN
|
||||
void
|
||||
thr_local_free(
|
||||
/*===========*/
|
||||
os_thread_id_t id) /*!< in: thread id */
|
||||
{
|
||||
thr_local_t* local;
|
||||
|
||||
mutex_enter(&thr_local_mutex);
|
||||
|
||||
/* Look for the local struct in the hash table */
|
||||
|
||||
HASH_SEARCH(hash, thr_local_hash, os_thread_pf(id),
|
||||
thr_local_t*, local, ut_ad(thr_local_validate(local)),
|
||||
os_thread_eq(local->id, id));
|
||||
if (local == NULL) {
|
||||
mutex_exit(&thr_local_mutex);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
HASH_DELETE(thr_local_t, hash, thr_local_hash,
|
||||
os_thread_pf(id), local);
|
||||
|
||||
mutex_exit(&thr_local_mutex);
|
||||
|
||||
ut_a(local->magic_n == THR_LOCAL_MAGIC_N);
|
||||
ut_ad(thr_local_validate(local));
|
||||
|
||||
mem_free(local);
|
||||
}
|
||||
|
||||
/****************************************************************//**
|
||||
Initializes the thread local storage module. */
|
||||
UNIV_INTERN
|
||||
void
|
||||
thr_local_init(void)
|
||||
/*================*/
|
||||
{
|
||||
|
||||
ut_a(thr_local_hash == NULL);
|
||||
|
||||
thr_local_hash = hash_create(OS_THREAD_MAX_N + 100);
|
||||
|
||||
mutex_create(thr_local_mutex_key,
|
||||
&thr_local_mutex, SYNC_THR_LOCAL);
|
||||
}
|
||||
|
||||
/********************************************************************
|
||||
Close the thread local storage module. */
|
||||
UNIV_INTERN
|
||||
void
|
||||
thr_local_close(void)
|
||||
/*=================*/
|
||||
{
|
||||
ulint i;
|
||||
|
||||
ut_a(thr_local_hash != NULL);
|
||||
|
||||
/* Free the hash elements. We don't remove them from the table
|
||||
because we are going to destroy the table anyway. */
|
||||
for (i = 0; i < hash_get_n_cells(thr_local_hash); i++) {
|
||||
thr_local_t* local;
|
||||
|
||||
local = HASH_GET_FIRST(thr_local_hash, i);
|
||||
|
||||
while (local) {
|
||||
thr_local_t* prev_local = local;
|
||||
|
||||
local = HASH_GET_NEXT(hash, prev_local);
|
||||
ut_a(prev_local->magic_n == THR_LOCAL_MAGIC_N);
|
||||
ut_ad(thr_local_validate(prev_local));
|
||||
mem_free(prev_local);
|
||||
}
|
||||
}
|
||||
|
||||
hash_table_free(thr_local_hash);
|
||||
thr_local_hash = NULL;
|
||||
}
|
@ -518,7 +518,7 @@ fill_trx_row(
|
||||
query[stmt_len] = '\0';
|
||||
|
||||
row->trx_query = ha_storage_put_memlim(
|
||||
cache->storage, stmt, stmt_len + 1,
|
||||
cache->storage, query, stmt_len + 1,
|
||||
MAX_ALLOWED_FOR_STORAGE(cache));
|
||||
|
||||
row->trx_query_cs = innobase_get_charset(trx->mysql_thd);
|
||||
|
@ -38,7 +38,6 @@ Created 3/26/1996 Heikki Tuuri
|
||||
#include "usr0sess.h"
|
||||
#include "read0read.h"
|
||||
#include "srv0srv.h"
|
||||
#include "thr0loc.h"
|
||||
#include "btr0sea.h"
|
||||
#include "os0proc.h"
|
||||
#include "trx0xa.h"
|
||||
|
@ -25,6 +25,7 @@ Created 1/30/1994 Heikki Tuuri
|
||||
|
||||
#include "univ.i"
|
||||
#include "ut0dbg.h"
|
||||
#include "ha_prototypes.h"
|
||||
|
||||
#if defined(__GNUC__) && (__GNUC__ > 2)
|
||||
#else
|
||||
@ -55,12 +56,13 @@ ut_dbg_assertion_failed(
|
||||
ut_print_timestamp(stderr);
|
||||
#ifdef UNIV_HOTBACKUP
|
||||
fprintf(stderr, " InnoDB: Assertion failure in file %s line %lu\n",
|
||||
file, line);
|
||||
innobase_basename(file), line);
|
||||
#else /* UNIV_HOTBACKUP */
|
||||
fprintf(stderr,
|
||||
" InnoDB: Assertion failure in thread %lu"
|
||||
" in file %s line %lu\n",
|
||||
os_thread_pf(os_thread_get_curr_id()), file, line);
|
||||
os_thread_pf(os_thread_get_curr_id()),
|
||||
innobase_basename(file), line);
|
||||
#endif /* UNIV_HOTBACKUP */
|
||||
if (expr) {
|
||||
fprintf(stderr,
|
||||
@ -93,7 +95,8 @@ ut_dbg_stop_thread(
|
||||
{
|
||||
#ifndef UNIV_HOTBACKUP
|
||||
fprintf(stderr, "InnoDB: Thread %lu stopped in file %s line %lu\n",
|
||||
os_thread_pf(os_thread_get_curr_id()), file, line);
|
||||
os_thread_pf(os_thread_get_curr_id()),
|
||||
innobase_basename(file), line);
|
||||
os_thread_sleep(1000000000);
|
||||
#endif /* !UNIV_HOTBACKUP */
|
||||
}
|
||||
|
Reference in New Issue
Block a user