summaryrefslogtreecommitdiff
path: root/innobase
diff options
context:
space:
mode:
authorunknown <monty@hundin.mysql.fi>2002-08-08 15:24:47 +0300
committerunknown <monty@hundin.mysql.fi>2002-08-08 15:24:47 +0300
commit267b80834ad524c0d72976bc71e5b5bc9815ea1a (patch)
treee7f4a2013ed3d66e640f6574e62cb7e534a5d77f /innobase
parentca1875f54033c5ea067ec3ec07b00375de6975d7 (diff)
parent40d3c3901b0427eba76119730f46784f946990b3 (diff)
downloadmariadb-git-267b80834ad524c0d72976bc71e5b5bc9815ea1a.tar.gz
merge with 3.23.52
BitKeeper/etc/logging_ok: auto-union configure.in: Auto merged Docs/manual.texi: Auto merged include/my_pthread.h: Auto merged include/mysql_com.h: Auto merged include/mysql_version.h.in: Auto merged innobase/btr/btr0cur.c: Auto merged innobase/btr/btr0sea.c: Auto merged innobase/buf/buf0buf.c: Auto merged innobase/buf/buf0lru.c: Auto merged innobase/configure.in: Auto merged innobase/dict/dict0dict.c: Auto merged innobase/fil/fil0fil.c: Auto merged innobase/fsp/fsp0fsp.c: Auto merged innobase/include/buf0buf.ic: Auto merged innobase/include/dyn0dyn.ic: Auto merged innobase/include/ha0ha.ic: Auto merged innobase/include/sync0rw.ic: Auto merged innobase/include/univ.i: Auto merged innobase/lock/lock0lock.c: Auto merged innobase/log/log0log.c: Auto merged innobase/mem/mem0dbg.c: Auto merged innobase/os/os0file.c: Auto merged innobase/os/os0thread.c: Auto merged innobase/page/page0cur.c: Auto merged innobase/srv/srv0srv.c: Auto merged innobase/sync/sync0arr.c: Auto merged innobase/sync/sync0rw.c: Auto merged innobase/sync/sync0sync.c: Auto merged innobase/trx/trx0trx.c: Auto merged myisam/mi_create.c: Auto merged sql/ha_innodb.h: Auto merged sql/lex.h: Auto merged sql/log.cc: Auto merged sql/mysqld.cc: Auto merged sql/sql_acl.cc: Auto merged sql/sql_insert.cc: Auto merged strings/Makefile.am: Auto merged support-files/mysql.server.sh: Auto merged include/my_base.h: merge with 3.23.52 (use local file) include/sslopt-usage.h: merge with 3.23.52 (use local file) myisam/mi_search.c: merge with 3.23.52 (use local file) myisam/mi_write.c: merge with 3.23.52 (use local file) mysql-test/r/group_by.result: merge with 3.23.52 (Need to be fixed before push) mysys/my_pthread.c: merge with 3.23.52 (use local file) sql/gen_lex_hash.cc: merge with 3.23.52 (use local file) sql/ha_innodb.cc: Total hand-merge with 3.23.52 sql/sql_yacc.yy: merge with 3.23.52 (use local file) support-files/mysql.spec.sh: merge with 3.23.52 (use local file)
Diffstat (limited to 'innobase')
-rw-r--r--innobase/btr/btr0cur.c8
-rw-r--r--innobase/btr/btr0sea.c1
-rw-r--r--innobase/buf/buf0buf.c42
-rw-r--r--innobase/buf/buf0lru.c39
-rw-r--r--innobase/configure.in4
-rw-r--r--innobase/dict/dict0dict.c39
-rw-r--r--innobase/fil/fil0fil.c2
-rw-r--r--innobase/fsp/fsp0fsp.c32
-rw-r--r--innobase/ha/ha0ha.c19
-rw-r--r--innobase/include/btr0btr.h8
-rw-r--r--innobase/include/buf0buf.h6
-rw-r--r--innobase/include/buf0buf.ic37
-rw-r--r--innobase/include/dict0dict.h20
-rw-r--r--innobase/include/dict0mem.h4
-rw-r--r--innobase/include/dyn0dyn.h11
-rw-r--r--innobase/include/fsp0fsp.h10
-rw-r--r--innobase/include/ha0ha.h8
-rw-r--r--innobase/include/ha0ha.ic10
-rw-r--r--innobase/include/log0log.h40
-rw-r--r--innobase/include/log0log.ic85
-rw-r--r--innobase/include/log0recv.h7
-rw-r--r--innobase/include/os0file.h6
-rw-r--r--innobase/include/os0sync.ic14
-rw-r--r--innobase/include/os0thread.h28
-rw-r--r--innobase/include/srv0start.h2
-rw-r--r--innobase/include/sync0rw.ic3
-rw-r--r--innobase/include/sync0sync.ic4
-rw-r--r--innobase/include/trx0sys.h13
-rw-r--r--innobase/include/trx0trx.h4
-rw-r--r--innobase/include/univ.i12
-rw-r--r--innobase/include/ut0dbg.h13
-rw-r--r--innobase/lock/lock0lock.c103
-rw-r--r--innobase/log/log0log.c35
-rw-r--r--innobase/log/log0recv.c249
-rw-r--r--innobase/mem/mem0dbg.c2
-rw-r--r--innobase/mem/mem0pool.c53
-rw-r--r--innobase/mtr/mtr0log.c37
-rw-r--r--innobase/os/os0file.c19
-rw-r--r--innobase/os/os0thread.c76
-rw-r--r--innobase/page/page0cur.c24
-rw-r--r--innobase/row/row0mysql.c5
-rw-r--r--innobase/row/row0vers.c22
-rw-r--r--innobase/srv/srv0srv.c70
-rw-r--r--innobase/srv/srv0start.c50
-rw-r--r--innobase/sync/sync0arr.c23
-rw-r--r--innobase/sync/sync0rw.c23
-rw-r--r--innobase/sync/sync0sync.c22
-rw-r--r--innobase/thr/thr0loc.c12
-rw-r--r--innobase/trx/trx0sys.c28
-rw-r--r--innobase/trx/trx0trx.c64
50 files changed, 1105 insertions, 343 deletions
diff --git a/innobase/btr/btr0cur.c b/innobase/btr/btr0cur.c
index 1fe322be81e..bab5c78b712 100644
--- a/innobase/btr/btr0cur.c
+++ b/innobase/btr/btr0cur.c
@@ -808,7 +808,7 @@ btr_cur_optimistic_insert(
if (!dtuple_check_typed_no_assert(entry)) {
fprintf(stderr,
-"InnoDB: Error in a tuple to insert into table %lu index %lu\n",
+"InnoDB: Error in a tuple to insert into table %lu index %s\n",
index->table_name, index->name);
}
@@ -1213,6 +1213,8 @@ btr_cur_parse_update_in_place(
rec_offset = mach_read_from_2(ptr);
ptr += 2;
+ ut_a(rec_offset <= UNIV_PAGE_SIZE);
+
heap = mem_heap_create(256);
ptr = row_upd_index_parse(ptr, end_ptr, heap, &update);
@@ -1977,6 +1979,8 @@ btr_cur_parse_del_mark_set_clust_rec(
offset = mach_read_from_2(ptr);
ptr += 2;
+ ut_a(offset <= UNIV_PAGE_SIZE);
+
if (page) {
rec = page + offset;
@@ -2127,6 +2131,8 @@ btr_cur_parse_del_mark_set_sec_rec(
offset = mach_read_from_2(ptr);
ptr += 2;
+ ut_a(offset <= UNIV_PAGE_SIZE);
+
if (page) {
rec = page + offset;
diff --git a/innobase/btr/btr0sea.c b/innobase/btr/btr0sea.c
index cfdfefebd1a..cef3a4e4b38 100644
--- a/innobase/btr/btr0sea.c
+++ b/innobase/btr/btr0sea.c
@@ -17,6 +17,7 @@ Created 2/17/1996 Heikki Tuuri
#include "btr0cur.h"
#include "btr0pcur.h"
#include "btr0btr.h"
+#include "ha0ha.h"
ulint btr_search_n_succ = 0;
ulint btr_search_n_hash_fail = 0;
diff --git a/innobase/buf/buf0buf.c b/innobase/buf/buf0buf.c
index 663c6cefce6..8b946f4b2a1 100644
--- a/innobase/buf/buf0buf.c
+++ b/innobase/buf/buf0buf.c
@@ -286,7 +286,7 @@ buf_page_print(
ut_print_timestamp(stderr);
fprintf(stderr,
" InnoDB: Page dump in ascii and hex (%u bytes):\n%s",
- UNIV_PAGE_SIZE, buf);
+ (ulint)UNIV_PAGE_SIZE, buf);
fprintf(stderr, "InnoDB: End of page dump\n");
mem_free(buf);
@@ -1707,10 +1707,11 @@ buf_print(void)
mutex_enter(&(buf_pool->mutex));
- printf("LRU len %lu \n", UT_LIST_GET_LEN(buf_pool->LRU));
- printf("free len %lu \n", UT_LIST_GET_LEN(buf_pool->free));
- printf("flush len %lu \n", UT_LIST_GET_LEN(buf_pool->flush_list));
printf("buf_pool size %lu \n", size);
+ printf("database pages %lu \n", UT_LIST_GET_LEN(buf_pool->LRU));
+ printf("free pages %lu \n", UT_LIST_GET_LEN(buf_pool->free));
+ printf("modified database pages %lu \n",
+ UT_LIST_GET_LEN(buf_pool->flush_list));
printf("n pending reads %lu \n", buf_pool->n_pend_reads);
@@ -1819,13 +1820,20 @@ buf_print_io(
mutex_enter(&(buf_pool->mutex));
buf += sprintf(buf,
- "Free list length %lu \n", UT_LIST_GET_LEN(buf_pool->free));
+ "Buffer pool size %lu\n", size);
+ buf += sprintf(buf,
+ "Free buffers %lu\n", UT_LIST_GET_LEN(buf_pool->free));
+ buf += sprintf(buf,
+ "Database pages %lu\n", UT_LIST_GET_LEN(buf_pool->LRU));
+/*
+ buf += sprintf(buf,
+ "Lock heap buffers %lu\n", buf_pool->n_lock_heap_pages);
buf += sprintf(buf,
- "LRU list length %lu \n", UT_LIST_GET_LEN(buf_pool->LRU));
+ "Hash index buffers %lu\n", buf_pool->n_adaptive_hash_pages);
+*/
buf += sprintf(buf,
- "Flush list length %lu \n",
+ "Modified db pages %lu\n",
UT_LIST_GET_LEN(buf_pool->flush_list));
- buf += sprintf(buf, "Buffer pool size %lu\n", size);
buf += sprintf(buf, "Pending reads %lu \n", buf_pool->n_pend_reads);
@@ -1836,8 +1844,8 @@ buf_print_io(
buf_pool->n_flush[BUF_FLUSH_SINGLE_PAGE]);
current_time = time(NULL);
- time_elapsed = difftime(current_time, buf_pool->last_printout_time);
-
+ time_elapsed = 0.001 + difftime(current_time,
+ buf_pool->last_printout_time);
buf_pool->last_printout_time = current_time;
buf += sprintf(buf, "Pages read %lu, created %lu, written %lu\n",
@@ -1870,6 +1878,20 @@ buf_print_io(
mutex_exit(&(buf_pool->mutex));
}
+/**************************************************************************
+Refreshes the statistics used to print per-second averages. */
+
+void
+buf_refresh_io_stats(void)
+/*======================*/
+{
+ buf_pool->last_printout_time = time(NULL);
+ buf_pool->n_page_gets_old = buf_pool->n_page_gets;
+ buf_pool->n_pages_read_old = buf_pool->n_pages_read;
+ buf_pool->n_pages_created_old = buf_pool->n_pages_created;
+ buf_pool->n_pages_written_old = buf_pool->n_pages_written;
+}
+
/*************************************************************************
Checks that all file pages in the buffer are in a replaceable state. */
diff --git a/innobase/buf/buf0lru.c b/innobase/buf/buf0lru.c
index 5ab045212c2..2ec1506c522 100644
--- a/innobase/buf/buf0lru.c
+++ b/innobase/buf/buf0lru.c
@@ -27,6 +27,7 @@ Created 11/5/1995 Heikki Tuuri
#include "buf0rea.h"
#include "btr0sea.h"
#include "os0file.h"
+#include "log0recv.h"
/* The number of blocks from the LRU_old pointer onward, including the block
pointed to, must be 3/8 of the whole LRU list length, except that the
@@ -205,6 +206,44 @@ buf_LRU_get_free_block(void)
loop:
mutex_enter(&(buf_pool->mutex));
+ if (!recv_recovery_on && UT_LIST_GET_LEN(buf_pool->free)
+ + UT_LIST_GET_LEN(buf_pool->LRU) < buf_pool->max_size / 10) {
+ ut_print_timestamp(stderr);
+
+ fprintf(stderr,
+" InnoDB: ERROR: over 9 / 10 of the buffer pool is occupied by\n"
+"InnoDB: lock heaps or the adaptive hash index!\n"
+"InnoDB: We intentionally generate a seg fault to print a stack trace\n"
+"InnoDB: on Linux!\n");
+
+ ut_a(0);
+
+ } else if (!recv_recovery_on && UT_LIST_GET_LEN(buf_pool->free)
+ + UT_LIST_GET_LEN(buf_pool->LRU) < buf_pool->max_size / 5) {
+
+ /* Over 80 % of the buffer pool is occupied by lock heaps
+ or the adaptive hash index. This may be a memory leak! */
+
+ ut_print_timestamp(stderr);
+ fprintf(stderr,
+" InnoDB: WARNING: over 4 / 5 of the buffer pool is occupied by\n"
+"InnoDB: lock heaps or the adaptive hash index! Check that your\n"
+"InnoDB: transactions do not set too many row locks. Starting InnoDB\n"
+"InnoDB: Monitor to print diagnostics, including lock heap and hash index\n"
+"InnoDB: sizes.\n");
+
+ srv_print_innodb_monitor = TRUE;
+
+ } else if (!recv_recovery_on && UT_LIST_GET_LEN(buf_pool->free)
+ + UT_LIST_GET_LEN(buf_pool->LRU) < buf_pool->max_size / 4) {
+
+ /* Switch off the InnoDB Monitor; this is a simple way
+ to stop the monitor if the situation becomes less urgent,
+ but may also surprise users! */
+
+ srv_print_innodb_monitor = FALSE;
+ }
+
if (buf_pool->LRU_flush_ended > 0) {
mutex_exit(&(buf_pool->mutex));
diff --git a/innobase/configure.in b/innobase/configure.in
index c234e1e192d..100692e06ab 100644
--- a/innobase/configure.in
+++ b/innobase/configure.in
@@ -86,8 +86,10 @@ else
fi
case "$target_os" in
+ hpux10*)
+ CFLAGS="$CFLAGS -DUNIV_MUST_NOT_INLINE -DUNIV_HPUX -DUNIV_HPUX10";;
hp*)
- CFLAGS="$CFLAGS -DUNIV_MUST_NOT_INLINE";;
+ CFLAGS="$CFLAGS -DUNIV_MUST_NOT_INLINE -DUNIV_HPUX";;
irix*)
CFLAGS="$CFLAGS -DUNIV_MUST_NOT_INLINE";;
osf*)
diff --git a/innobase/dict/dict0dict.c b/innobase/dict/dict0dict.c
index 5abec8dbb1e..85199b90a5a 100644
--- a/innobase/dict/dict0dict.c
+++ b/innobase/dict/dict0dict.c
@@ -261,7 +261,7 @@ dict_table_get_index_noninline(
{
return(dict_table_get_index(table, name));
}
-
+
/************************************************************************
Initializes the autoinc counter. It is not an error to initialize an already
initialized counter. */
@@ -270,7 +270,7 @@ void
dict_table_autoinc_initialize(
/*==========================*/
dict_table_t* table, /* in: table */
- ib_longlong value) /* in: value which was assigned to a row */
+ ib_longlong value) /* in: next value to assign to a row */
{
mutex_enter(&(table->autoinc_mutex));
@@ -281,8 +281,8 @@ dict_table_autoinc_initialize(
}
/************************************************************************
-Gets the next autoinc value, 0 if not yet initialized. If initialized,
-increments the counter by 1. */
+Gets the next autoinc value (== autoinc counter value), 0 if not yet
+initialized. If initialized, increments the counter by 1. */
ib_longlong
dict_table_autoinc_get(
@@ -298,8 +298,8 @@ dict_table_autoinc_get(
value = 0;
} else {
- table->autoinc = table->autoinc + 1;
value = table->autoinc;
+ table->autoinc = table->autoinc + 1;
}
mutex_exit(&(table->autoinc_mutex));
@@ -334,20 +334,43 @@ dict_table_autoinc_read(
}
/************************************************************************
-Updates the autoinc counter if the value supplied is bigger than the
+Peeks the autoinc counter value, 0 if not yet initialized. Does not
+increment the counter. The read not protected by any mutex! */
+
+ib_longlong
+dict_table_autoinc_peek(
+/*====================*/
+ /* out: value of the counter */
+ dict_table_t* table) /* in: table */
+{
+ ib_longlong value;
+
+ if (!table->autoinc_inited) {
+
+ value = 0;
+ } else {
+ value = table->autoinc;
+ }
+
+ return(value);
+}
+
+/************************************************************************
+Updates the autoinc counter if the value supplied is equal or bigger than the
current value. If not inited, does nothing. */
void
dict_table_autoinc_update(
/*======================*/
+
dict_table_t* table, /* in: table */
ib_longlong value) /* in: value which was assigned to a row */
{
mutex_enter(&(table->autoinc_mutex));
if (table->autoinc_inited) {
- if (value > table->autoinc) {
- table->autoinc = value;
+ if (value >= table->autoinc) {
+ table->autoinc = value + 1;
}
}
diff --git a/innobase/fil/fil0fil.c b/innobase/fil/fil0fil.c
index da4aee5db76..3e0f21395ef 100644
--- a/innobase/fil/fil0fil.c
+++ b/innobase/fil/fil0fil.c
@@ -578,7 +578,7 @@ fil_read_flushed_lsn_and_arch_log_no(
ulint arch_log_no;
buf2 = ut_malloc(2 * UNIV_PAGE_SIZE);
- /* Align the memory for a possibel read from a raw device */
+ /* Align the memory for a possible read from a raw device */
buf = ut_align(buf2, UNIV_PAGE_SIZE);
os_file_read(data_file, buf, 0, 0, UNIV_PAGE_SIZE);
diff --git a/innobase/fsp/fsp0fsp.c b/innobase/fsp/fsp0fsp.c
index 32e7f5bcad7..1abb043fdc2 100644
--- a/innobase/fsp/fsp0fsp.c
+++ b/innobase/fsp/fsp0fsp.c
@@ -933,6 +933,36 @@ fsp_header_get_free_limit(
return(limit);
}
+/**************************************************************************
+Gets the size of the tablespace from the tablespace header. If we do not
+have an auto-extending data file, this should be equal to the size of the
+data files. If there is an auto-extending data file, this can be smaller. */
+
+ulint
+fsp_header_get_tablespace_size(
+/*===========================*/
+ /* out: size in pages */
+ ulint space) /* in: space id */
+{
+ fsp_header_t* header;
+ ulint size;
+ mtr_t mtr;
+
+ ut_a(space == 0); /* We have only one log_fsp_current_... variable */
+
+ mtr_start(&mtr);
+
+ mtr_x_lock(fil_space_get_latch(space), &mtr);
+
+ header = fsp_get_space_header(space, &mtr);
+
+ size = mtr_read_ulint(header + FSP_SIZE, MLOG_4BYTES, &mtr);
+
+ mtr_commit(&mtr);
+
+ return(size);
+}
+
/***************************************************************************
Tries to extend the last data file file if it is defined as auto-extending. */
static
@@ -2629,7 +2659,7 @@ fseg_free_page_low(
"InnoDB: Dump of the tablespace extent descriptor: %s\n", errbuf);
fprintf(stderr,
-"InnoDB: Serious error! InnoDB is trying to free page %lu\n",
+"InnoDB: Serious error! InnoDB is trying to free page %lu\n"
"InnoDB: though it is already marked as free in the tablespace!\n"
"InnoDB: The tablespace free space info is corrupt.\n"
"InnoDB: You may need to dump your InnoDB tables and recreate the whole\n"
diff --git a/innobase/ha/ha0ha.c b/innobase/ha/ha0ha.c
index c3ad6cdca76..4489b25ec2b 100644
--- a/innobase/ha/ha0ha.c
+++ b/innobase/ha/ha0ha.c
@@ -298,6 +298,7 @@ ha_print_info(
ulint cells = 0;
ulint len = 0;
ulint max_len = 0;
+ ulint n_bufs;
ulint i;
if (buf_end - buf < 200) {
@@ -335,6 +336,20 @@ ha_print_info(
}
}
- buf += sprintf(buf, "Hash table size %lu, used cells %lu\n",
- hash_get_n_cells(table), cells);
+ buf += sprintf(buf,
+"Hash table size %lu, used cells %lu", hash_get_n_cells(table), cells);
+
+ if (table->heaps == NULL && table->heap != NULL) {
+
+ /* This calculation is intended for the adaptive hash
+ index: how many buffer frames we have reserved? */
+
+ n_bufs = UT_LIST_GET_LEN(table->heap->base) - 1;
+
+ if (table->heap->free_block) {
+ n_bufs++;
+ }
+
+ buf += sprintf(buf, ", node heap has %lu buffer(s)\n", n_bufs);
+ }
}
diff --git a/innobase/include/btr0btr.h b/innobase/include/btr0btr.h
index bf433c0c264..f66ad3639d4 100644
--- a/innobase/include/btr0btr.h
+++ b/innobase/include/btr0btr.h
@@ -313,14 +313,6 @@ btr_discard_page(
btr_cur_t* cursor, /* in: cursor on the page to discard: not on
the root page */
mtr_t* mtr); /* in: mtr */
-/************************************************************************
-Declares the latching order level for the page latch in the debug version. */
-UNIV_INLINE
-void
-btr_declare_page_latch(
-/*===================*/
- page_t* page, /* in: page */
- ibool leaf); /* in: TRUE if a leaf */
/********************************************************************
Parses the redo log record for setting an index record as the predefined
minimum record. */
diff --git a/innobase/include/buf0buf.h b/innobase/include/buf0buf.h
index b80ed96f54c..591c0ec54ab 100644
--- a/innobase/include/buf0buf.h
+++ b/innobase/include/buf0buf.h
@@ -463,6 +463,12 @@ buf_print_io(
/*=========*/
char* buf, /* in/out: buffer where to print */
char* buf_end);/* in: buffer end */
+/**************************************************************************
+Refreshes the statistics used to print per-second averages. */
+
+void
+buf_refresh_io_stats(void);
+/*======================*/
/*************************************************************************
Checks that all file pages in the buffer are in a replaceable state. */
diff --git a/innobase/include/buf0buf.ic b/innobase/include/buf0buf.ic
index e5a2c480922..7227c79dc6a 100644
--- a/innobase/include/buf0buf.ic
+++ b/innobase/include/buf0buf.ic
@@ -211,8 +211,15 @@ buf_block_align(
block = buf_pool_get_nth_block(buf_pool, ((ulint)(ptr - frame_zero))
>> UNIV_PAGE_SIZE_SHIFT);
- ut_a(block >= buf_pool->blocks);
- ut_a(block < buf_pool->blocks + buf_pool->max_size);
+ if (block < buf_pool->blocks
+ || block >= buf_pool->blocks + buf_pool->max_size) {
+
+ fprintf(stderr,
+"InnoDB: Error: trying to access a stray pointer %lx\n"
+"InnoDB: buf pool start is at %lx, number of pages %lu\n", (ulint)ptr,
+ (ulint)frame_zero, buf_pool->max_size);
+ ut_a(0);
+ }
return(block);
}
@@ -238,8 +245,15 @@ buf_block_align_low(
block = buf_pool_get_nth_block(buf_pool, ((ulint)(ptr - frame_zero))
>> UNIV_PAGE_SIZE_SHIFT);
- ut_a(block >= buf_pool->blocks);
- ut_a(block < buf_pool->blocks + buf_pool->max_size);
+ if (block < buf_pool->blocks
+ || block >= buf_pool->blocks + buf_pool->max_size) {
+
+ fprintf(stderr,
+"InnoDB: Error: trying to access a stray pointer %lx\n"
+"InnoDB: buf pool start is at %lx, number of pages %lu\n", (ulint)ptr,
+ (ulint)frame_zero, buf_pool->max_size);
+ ut_a(0);
+ }
return(block);
}
@@ -259,10 +273,17 @@ buf_frame_align(
frame = ut_align_down(ptr, UNIV_PAGE_SIZE);
- ut_a((ulint)frame
- >= (ulint)(buf_pool_get_nth_block(buf_pool, 0)->frame));
- ut_a((ulint)frame <= (ulint)(buf_pool_get_nth_block(buf_pool,
- buf_pool->max_size - 1)->frame));
+ if (((ulint)frame
+ < (ulint)(buf_pool->frame_zero))
+ || ((ulint)frame > (ulint)(buf_pool_get_nth_block(buf_pool,
+ buf_pool->max_size - 1)->frame))) {
+ fprintf(stderr,
+"InnoDB: Error: trying to access a stray pointer %lx\n"
+"InnoDB: buf pool start is at %lx, number of pages %lu\n", (ulint)ptr,
+ (ulint)(buf_pool->frame_zero), buf_pool->max_size);
+ ut_a(0);
+ }
+
return(frame);
}
diff --git a/innobase/include/dict0dict.h b/innobase/include/dict0dict.h
index fd79e17090a..832654d2666 100644
--- a/innobase/include/dict0dict.h
+++ b/innobase/include/dict0dict.h
@@ -96,17 +96,17 @@ dict_col_get_clust_pos(
/*===================*/
dict_col_t* col);
/************************************************************************
-Initializes the autoinc counter. It is not an error to initialize already
+Initializes the autoinc counter. It is not an error to initialize an already
initialized counter. */
void
dict_table_autoinc_initialize(
/*==========================*/
dict_table_t* table, /* in: table */
- ib_longlong value); /* in: value which was assigned to a row */
+ ib_longlong value); /* in: next value to assign to a row */
/************************************************************************
-Gets the next autoinc value, 0 if not yet initialized. If initialized,
-increments the counter by 1. */
+Gets the next autoinc value (== autoinc counter value), 0 if not yet
+initialized. If initialized, increments the counter by 1. */
ib_longlong
dict_table_autoinc_get(
@@ -123,12 +123,22 @@ dict_table_autoinc_read(
/* out: value of the counter */
dict_table_t* table); /* in: table */
/************************************************************************
-Updates the autoinc counter if the value supplied is bigger than the
+Peeks the autoinc counter value, 0 if not yet initialized. Does not
+increment the counter. The read not protected by any mutex! */
+
+ib_longlong
+dict_table_autoinc_peek(
+/*====================*/
+ /* out: value of the counter */
+ dict_table_t* table); /* in: table */
+/************************************************************************
+Updates the autoinc counter if the value supplied is equal or bigger than the
current value. If not inited, does nothing. */
void
dict_table_autoinc_update(
/*======================*/
+
dict_table_t* table, /* in: table */
ib_longlong value); /* in: value which was assigned to a row */
/**************************************************************************
diff --git a/innobase/include/dict0mem.h b/innobase/include/dict0mem.h
index ef15c99fdba..cc27f2bad12 100644
--- a/innobase/include/dict0mem.h
+++ b/innobase/include/dict0mem.h
@@ -388,8 +388,8 @@ struct dict_table_struct{
/* TRUE if the autoinc counter has been
inited; MySQL gets the init value by executing
SELECT MAX(auto inc column) */
- ib_longlong autoinc;/* autoinc counter value already given to
- a row */
+ ib_longlong autoinc;/* autoinc counter value to give to the
+ next inserted row */
ulint magic_n;/* magic number */
};
#define DICT_TABLE_MAGIC_N 76333786
diff --git a/innobase/include/dyn0dyn.h b/innobase/include/dyn0dyn.h
index 6f08da1533b..501fde05e90 100644
--- a/innobase/include/dyn0dyn.h
+++ b/innobase/include/dyn0dyn.h
@@ -17,7 +17,8 @@ typedef struct dyn_block_struct dyn_block_t;
typedef dyn_block_t dyn_array_t;
-/* This must be > MLOG_BUF_MARGIN + 30 */
+/* This is the initial 'payload' size of a dynamic array;
+this must be > MLOG_BUF_MARGIN + 30! */
#define DYN_ARRAY_DATA_SIZE 512
/*************************************************************************
@@ -123,14 +124,6 @@ dyn_block_get_data(
/*===============*/
/* out: pointer to data */
dyn_block_t* block); /* in: dyn array block */
-/************************************************************************
-Gets the next block in a dyn array. */
-UNIV_INLINE
-dyn_block_t*
-dyn_block_get_next(
-/*===============*/
- /* out: pointer to next, NULL if end of list */
- dyn_block_t* block); /* in: dyn array block */
/************************************************************
Pushes n bytes to a dyn array. */
UNIV_INLINE
diff --git a/innobase/include/fsp0fsp.h b/innobase/include/fsp0fsp.h
index a0197ec2d97..3494f336b1e 100644
--- a/innobase/include/fsp0fsp.h
+++ b/innobase/include/fsp0fsp.h
@@ -57,6 +57,16 @@ fsp_header_get_free_limit(
/* out: free limit in megabytes */
ulint space); /* in: space id */
/**************************************************************************
+Gets the size of the tablespace from the tablespace header. If we do not
+have an auto-extending data file, this should be equal to the size of the
+data files. If there is an auto-extending data file, this can be smaller. */
+
+ulint
+fsp_header_get_tablespace_size(
+/*===========================*/
+ /* out: size in pages */
+ ulint space); /* in: space id */
+/**************************************************************************
Initializes the space header of a new created space. */
void
diff --git a/innobase/include/ha0ha.h b/innobase/include/ha0ha.h
index 945b1198a41..0beac928b7e 100644
--- a/innobase/include/ha0ha.h
+++ b/innobase/include/ha0ha.h
@@ -131,6 +131,14 @@ ha_print_info(
char* buf_end,/* in: buffer end */
hash_table_t* table); /* in: hash table */
+/* The hash table external chain node */
+
+typedef struct ha_node_struct ha_node_t;
+struct ha_node_struct {
+ ha_node_t* next; /* next chain node or NULL if none */
+ void* data; /* pointer to the data */
+ ulint fold; /* fold value for the data */
+};
#ifndef UNIV_NONINL
#include "ha0ha.ic"
diff --git a/innobase/include/ha0ha.ic b/innobase/include/ha0ha.ic
index 9d344bca04c..761bc3b20de 100644
--- a/innobase/include/ha0ha.ic
+++ b/innobase/include/ha0ha.ic
@@ -9,16 +9,6 @@ Created 8/18/1994 Heikki Tuuri
#include "ut0rnd.h"
#include "mem0mem.h"
-/* The hash table external chain node */
-
-typedef struct ha_node_struct ha_node_t;
-
-struct ha_node_struct {
- ha_node_t* next; /* next chain node or NULL if none */
- void* data; /* pointer to the data */
- ulint fold; /* fold value for the data */
-};
-
/***************************************************************
Deletes a hash node. */
diff --git a/innobase/include/log0log.h b/innobase/include/log0log.h
index 5d848b85658..f200371de9d 100644
--- a/innobase/include/log0log.h
+++ b/innobase/include/log0log.h
@@ -431,15 +431,30 @@ log_block_set_data_len(
byte* log_block, /* in: log block */
ulint len); /* in: data length */
/****************************************************************
-Gets a log block number stored in the trailer. */
+Calculates the checksum for a log block. */
UNIV_INLINE
ulint
-log_block_get_trl_no(
-/*=================*/
- /* out: log block number stored in the block
- trailer */
+log_block_calc_checksum(
+/*====================*/
+ /* out: checksum */
+ byte* block); /* in: log block */
+/****************************************************************
+Gets a log block checksum field value. */
+UNIV_INLINE
+ulint
+log_block_get_checksum(
+/*===================*/
+ /* out: checksum */
byte* log_block); /* in: log block */
/****************************************************************
+Sets a log block checksum field value. */
+UNIV_INLINE
+void
+log_block_set_checksum(
+/*===================*/
+ byte* log_block, /* in: log block */
+ ulint checksum); /* in: checksum */
+/****************************************************************
Gets a log block first mtr log record group offset. */
UNIV_INLINE
ulint
@@ -497,6 +512,12 @@ log_print(
/*======*/
char* buf, /* in/out: buffer where to print */
char* buf_end);/* in: buffer end */
+/**************************************************************************
+Refreshes the statistics used to print per-second averages. */
+
+void
+log_refresh_stats(void);
+/*===================*/
extern log_t* log_sys;
@@ -544,10 +565,11 @@ extern log_t* log_sys;
bytes */
/* Offsets of a log block trailer from the end of the block */
-#define LOG_BLOCK_TRL_CHECKSUM 4 /* 1 byte checksum of the log block
- contents */
-#define LOG_BLOCK_TRL_NO 3 /* 3 lowest bytes of the log block
- number */
+#define LOG_BLOCK_CHECKSUM 4 /* 4 byte checksum of the log block
+ contents; in InnoDB versions
+ < 3.23.52 this did not contain the
+ checksum but the same value as
+ .._HDR_NO */
#define LOG_BLOCK_TRL_SIZE 4 /* trailer size in bytes */
/* Offsets for a checkpoint field */
diff --git a/innobase/include/log0log.ic b/innobase/include/log0log.ic
index 36e65239374..8de239df0bd 100644
--- a/innobase/include/log0log.ic
+++ b/innobase/include/log0log.ic
@@ -170,33 +170,6 @@ log_block_set_checkpoint_no(
}
/****************************************************************
-Gets a log block number stored in the trailer. */
-UNIV_INLINE
-ulint
-log_block_get_trl_no(
-/*=================*/
- /* out: log block number stored in the block
- trailer */
- byte* log_block) /* in: log block */
-{
- return(mach_read_from_3(log_block + OS_FILE_LOG_BLOCK_SIZE
- - LOG_BLOCK_TRL_NO));
-}
-
-/****************************************************************
-Sets the log block number stored in the trailer. */
-UNIV_INLINE
-void
-log_block_set_trl_no(
-/*=================*/
- byte* log_block, /* in: log block */
- ulint n) /* in: log block number */
-{
- mach_write_to_3(log_block + OS_FILE_LOG_BLOCK_SIZE - LOG_BLOCK_TRL_NO,
- n & 0xFFFFFF);
-}
-
-/****************************************************************
Converts a lsn to a log block number. */
UNIV_INLINE
ulint
@@ -217,6 +190,61 @@ log_block_convert_lsn_to_no(
}
/****************************************************************
+Calculates the checksum for a log block. */
+UNIV_INLINE
+ulint
+log_block_calc_checksum(
+/*====================*/
+ /* out: checksum */
+ byte* block) /* in: log block */
+{
+ ulint sum;
+ ulint sh;
+ ulint i;
+
+ sum = 1;
+ sh = 0;
+
+ for (i = 0; i < OS_FILE_LOG_BLOCK_SIZE - LOG_BLOCK_TRL_SIZE; i++) {
+ sum = sum & 0x7FFFFFFF;
+ sum += (((ulint)(*(block + i))) << sh) + (ulint)(*(block + i));
+ sh++;
+ if (sh > 24) {
+ sh = 0;
+ }
+ }
+
+ return(sum);
+}
+
+/****************************************************************
+Gets a log block checksum field value. */
+UNIV_INLINE
+ulint
+log_block_get_checksum(
+/*===================*/
+ /* out: checksum */
+ byte* log_block) /* in: log block */
+{
+ return(mach_read_from_4(log_block + OS_FILE_LOG_BLOCK_SIZE
+ - LOG_BLOCK_CHECKSUM));
+}
+
+/****************************************************************
+Sets a log block checksum field value. */
+UNIV_INLINE
+void
+log_block_set_checksum(
+/*===================*/
+ byte* log_block, /* in: log block */
+ ulint checksum) /* in: checksum */
+{
+ mach_write_to_4(log_block + OS_FILE_LOG_BLOCK_SIZE
+ - LOG_BLOCK_CHECKSUM,
+ checksum);
+}
+
+/****************************************************************
Initializes a log block in the log buffer. */
UNIV_INLINE
void
@@ -232,7 +260,6 @@ log_block_init(
no = log_block_convert_lsn_to_no(lsn);
log_block_set_hdr_no(log_block, no);
- log_block_set_trl_no(log_block, no);
log_block_set_data_len(log_block, LOG_BLOCK_HDR_SIZE);
log_block_set_first_rec_group(log_block, 0);
@@ -256,7 +283,7 @@ log_block_init_in_old_format(
log_block_set_hdr_no(log_block, no);
mach_write_to_4(log_block + OS_FILE_LOG_BLOCK_SIZE
- - LOG_BLOCK_TRL_NO - 1, no);
+ - LOG_BLOCK_CHECKSUM, no);
log_block_set_data_len(log_block, LOG_BLOCK_HDR_SIZE);
log_block_set_first_rec_group(log_block, 0);
}
diff --git a/innobase/include/log0recv.h b/innobase/include/log0recv.h
index 0825325965d..baa2ba50c7d 100644
--- a/innobase/include/log0recv.h
+++ b/innobase/include/log0recv.h
@@ -313,6 +313,11 @@ struct recv_sys_struct{
this lsn */
dulint limit_lsn;/* recovery should be made at most up to this
lsn */
+ ibool found_corrupt_log;
+ /* this is set to TRUE if we during log
+ scan find a corrupt log block, or a corrupt
+ log record, or there is a log parsing
+ buffer overflow */
log_group_t* archive_group;
/* in archive recovery: the log group whose
archive is read */
@@ -328,6 +333,8 @@ extern ibool recv_recovery_on;
extern ibool recv_no_ibuf_operations;
extern ibool recv_needed_recovery;
+extern ibool recv_is_making_a_backup;
+
/* Size of the parsing buffer; it must accommodate RECV_SCAN_SIZE many
times! */
#define RECV_PARSING_BUF_SIZE (2 * 1024 * 1024)
diff --git a/innobase/include/os0file.h b/innobase/include/os0file.h
index b7911c5014a..d65c7fd47e3 100644
--- a/innobase/include/os0file.h
+++ b/innobase/include/os0file.h
@@ -408,6 +408,12 @@ os_aio_print(
char* buf, /* in/out: buffer where to print */
char* buf_end);/* in: buffer end */
/**************************************************************************
+Refreshes the statistics used to print per-second averages. */
+
+void
+os_aio_refresh_stats(void);
+/*======================*/
+/**************************************************************************
Checks that all slots in the system have been freed, that is, there are
no pending io operations. */
diff --git a/innobase/include/os0sync.ic b/innobase/include/os0sync.ic
index 6bff75d8ec6..10b85c435e3 100644
--- a/innobase/include/os0sync.ic
+++ b/innobase/include/os0sync.ic
@@ -27,7 +27,21 @@ os_fast_mutex_trylock(
return(0);
#else
+#if defined(UNIV_HOTBACKUP) && defined(UNIV_HPUX10)
+ /* Since the hot backup version is standalone, MySQL does not redefine
+ pthread_mutex_trylock for HP-UX-10.20, and consequently we must invert
+ the return value here */
+
+ return((ulint) (1 - pthread_mutex_trylock(fast_mutex)));
+#else
+ /* NOTE that the MySQL my_pthread.h redefines pthread_mutex_trylock
+ so that it returns 0 on success. In the operating system
+ libraries, HP-UX-10.20 follows the old Posix 1003.4a Draft 4 and
+ returns 1 on success (but MySQL remaps that to 0), while Linux,
+ FreeBSD, Solaris, AIX, Tru64 Unix, HP-UX-11.0 return 0 on success. */
+
return((ulint) pthread_mutex_trylock(fast_mutex));
#endif
+#endif
}
diff --git a/innobase/include/os0thread.h b/innobase/include/os0thread.h
index 0d6fa5a8f37..636cfd79e50 100644
--- a/innobase/include/os0thread.h
+++ b/innobase/include/os0thread.h
@@ -28,12 +28,30 @@ typedef void* os_thread_t;
#else
typedef pthread_t os_thread_t;
#endif
-typedef unsigned long int os_thread_id_t;
+
+#define os_thread_id_t os_thread_t
/* Define a function pointer type to use in a typecast */
typedef void* (*os_posix_f_t) (void*);
+/*******************************************************************
+Compares two threads or thread ids for equality */
+
+ibool
+os_thread_eq(
+/*=========*/
+ /* out: TRUE if equal */
+ os_thread_t a, /* in: OS thread or thread id */
+ os_thread_t b); /* in: OS thread or thread id */
+/********************************************************************
+Converts an OS thread or thread id to a ulint. It is NOT guaranteed that
+the ulint is unique for the thread though! */
+ulint
+os_thread_pf(
+/*=========*/
+ /* out: unsigned long int */
+ os_thread_t a); /* in: thread or thread id */
/********************************************************************
Creates a new thread of execution. The execution starts from
the function given. The start function takes a void* parameter
@@ -73,14 +91,6 @@ os_thread_t
os_thread_get_curr(void);
/*====================*/
/*********************************************************************
-Converts a thread id to a ulint. */
-
-ulint
-os_thread_conv_id_to_ulint(
-/*=======================*/
- /* out: converted to ulint */
- os_thread_id_t id); /* in: thread id */
-/*********************************************************************
Waits for a thread to terminate. */
void
diff --git a/innobase/include/srv0start.h b/innobase/include/srv0start.h
index 01ac063e1c9..646d2c1bb06 100644
--- a/innobase/include/srv0start.h
+++ b/innobase/include/srv0start.h
@@ -85,7 +85,7 @@ extern ibool srv_is_being_shut_down;
/* At a shutdown the value first climbs from 0 to SRV_SHUTDOWN_CLEANUP
and then to SRV_SHUTDOWN_LAST_PHASE */
-extern ulint srv_shutdown_state;
+extern ulint srv_shutdown_state;
#define SRV_SHUTDOWN_CLEANUP 1
#define SRV_SHUTDOWN_LAST_PHASE 2
diff --git a/innobase/include/sync0rw.ic b/innobase/include/sync0rw.ic
index 43e9202360b..36ef0a985ed 100644
--- a/innobase/include/sync0rw.ic
+++ b/innobase/include/sync0rw.ic
@@ -312,7 +312,8 @@ rw_lock_x_lock_func_nowait(
&& ((rw_lock_get_writer(lock) == RW_LOCK_NOT_LOCKED)
|| ((rw_lock_get_writer(lock) == RW_LOCK_EX)
&& (lock->pass == 0)
- && (lock->writer_thread == os_thread_get_curr_id())))) {
+ && os_thread_eq(lock->writer_thread,
+ os_thread_get_curr_id())))) {
rw_lock_set_writer(lock, RW_LOCK_EX);
lock->writer_thread = os_thread_get_curr_id();
diff --git a/innobase/include/sync0sync.ic b/innobase/include/sync0sync.ic
index 9014eb5fb54..c11cc0d196e 100644
--- a/innobase/include/sync0sync.ic
+++ b/innobase/include/sync0sync.ic
@@ -104,6 +104,10 @@ mutex_test_and_set(
ret = os_fast_mutex_trylock(&(mutex->os_fast_mutex));
if (ret == 0) {
+ /* We check that os_fast_mutex_trylock does not leak
+ and allow race conditions */
+ ut_a(mutex->lock_word == 0);
+
mutex->lock_word = 1;
}
diff --git a/innobase/include/trx0sys.h b/innobase/include/trx0sys.h
index b08df7f6901..a54a6424a4f 100644
--- a/innobase/include/trx0sys.h
+++ b/innobase/include/trx0sys.h
@@ -257,6 +257,15 @@ void
trx_sys_print_mysql_binlog_offset(void);
/*===================================*/
/*********************************************************************
+Prints to stdout the MySQL binlog info in the system header if the
+magic number shows it valid. */
+
+void
+trx_sys_print_mysql_binlog_offset_from_page(
+/*========================================*/
+ byte* page); /* in: buffer containing the trx system header page,
+ i.e., page number TRX_SYS_PAGE_NO in the tablespace */
+/*********************************************************************
Prints to stderr the MySQL master log offset info in the trx system header if
the magic number shows it valid. */
@@ -300,11 +309,11 @@ therefore 256; each slot is currently 8 bytes in size */
#define TRX_SYS_MYSQL_LOG_NAME_LEN 512
#define TRX_SYS_MYSQL_LOG_MAGIC_N 873422344
-/* The offset of the MySQL replication info on the trx system header page;
+/* The offset of the MySQL replication info in the trx system header;
this contains the same fields as TRX_SYS_MYSQL_LOG_INFO below */
#define TRX_SYS_MYSQL_MASTER_LOG_INFO (UNIV_PAGE_SIZE - 2000)
-/* The offset of the MySQL binlog offset info on the trx system header page */
+/* The offset of the MySQL binlog offset info in the trx system header */
#define TRX_SYS_MYSQL_LOG_INFO (UNIV_PAGE_SIZE - 1000)
#define TRX_SYS_MYSQL_LOG_MAGIC_N_FLD 0 /* magic number which shows
if we have valid data in the
diff --git a/innobase/include/trx0trx.h b/innobase/include/trx0trx.h
index 83789966514..6e98f22c34b 100644
--- a/innobase/include/trx0trx.h
+++ b/innobase/include/trx0trx.h
@@ -309,6 +309,9 @@ struct trx_struct{
of view of concurrency control:
TRX_ACTIVE, TRX_COMMITTED_IN_MEMORY,
... */
+ time_t start_time; /* time the trx object was created
+ or the state last time became
+ TRX_ACTIVE */
ibool check_foreigns; /* normally TRUE, but if the user
wants to suppress foreign key checks,
(in table imports, for example) we
@@ -468,6 +471,7 @@ struct trx_struct{
TRX_QUE_LOCK_WAIT, this points to
the lock request, otherwise this is
NULL */
+ time_t wait_started; /* lock wait started at this time */
UT_LIST_BASE_NODE_T(que_thr_t)
wait_thrs; /* query threads belonging to this
trx that are in the QUE_THR_LOCK_WAIT
diff --git a/innobase/include/univ.i b/innobase/include/univ.i
index c852741d5ac..a4f29dc4cf3 100644
--- a/innobase/include/univ.i
+++ b/innobase/include/univ.i
@@ -80,8 +80,8 @@ memory is read outside the allocated blocks. */
/*
#define UNIV_DEBUG
-#define UNIV_MEM_DEBUG
#define UNIV_SYNC_DEBUG
+#define UNIV_MEM_DEBUG
#define UNIV_IBUF_DEBUG
#define UNIV_SEARCH_DEBUG
@@ -116,7 +116,7 @@ memory is read outside the allocated blocks. */
#define UNIV_INLINE extern inline
#else
/* extern inline doesn't work with gcc 3.0.2 */
-#define UNIV_INLINE static inline
+#define UNIV_INLINE static inline
#endif
#endif
@@ -204,8 +204,12 @@ headers may define 'bool' differently. Do not assume that 'bool' is a ulint! */
#endif
/* The following number as the length of a logical field means that the field
-has the SQL NULL as its value. */
-#define UNIV_SQL_NULL ULINT_UNDEFINED
+has the SQL NULL as its value. NOTE that because we assume that the length
+of a field is a 32-bit integer when we store it, for example, to an undo log
+on disk, we must have also this number fit in 32 bits, also in 64-bit
+computers! */
+
+#define UNIV_SQL_NULL ULINT32_UNDEFINED
/* Lengths which are not UNIV_SQL_NULL, but bigger than the following
number indicate that a field contains a reference to an externally
diff --git a/innobase/include/ut0dbg.h b/innobase/include/ut0dbg.h
index fc5d493ca5e..3407483696c 100644
--- a/innobase/include/ut0dbg.h
+++ b/innobase/include/ut0dbg.h
@@ -26,9 +26,11 @@ extern ulint* ut_dbg_null_ptr;
ulint dbg_i;\
\
if (!((ulint)(EXPR) + ut_dbg_zero)) {\
+ ut_print_timestamp(stderr);\
fprintf(stderr,\
- "InnoDB: Assertion failure in thread %lu in file %s line %lu\n",\
- os_thread_get_curr_id(), IB__FILE__, (ulint)__LINE__);\
+ " InnoDB: Assertion failure in thread %lu in file %s line %lu\n",\
+ os_thread_pf(os_thread_get_curr_id()), IB__FILE__,\
+ (ulint)__LINE__);\
fprintf(stderr,\
"InnoDB: We intentionally generate a memory trap.\n");\
fprintf(stderr,\
@@ -42,16 +44,17 @@ extern ulint* ut_dbg_null_ptr;
if (ut_dbg_stop_threads) {\
fprintf(stderr,\
"InnoDB: Thread %lu stopped in file %s line %lu\n",\
- os_thread_get_curr_id(), IB__FILE__, (ulint)__LINE__);\
+ os_thread_pf(os_thread_get_curr_id()), IB__FILE__, (ulint)__LINE__);\
os_thread_sleep(1000000000);\
}\
}
#define ut_error {\
ulint dbg_i;\
+ ut_print_timestamp(stderr);\
fprintf(stderr,\
- "InnoDB: Assertion failure in thread %lu in file %s line %lu\n",\
- os_thread_get_curr_id(), IB__FILE__, (ulint)__LINE__);\
+ " InnoDB: Assertion failure in thread %lu in file %s line %lu\n",\
+ os_thread_pf(os_thread_get_curr_id()), IB__FILE__, (ulint)__LINE__);\
fprintf(stderr,\
"InnoDB: We intentionally generate a memory trap.\n");\
fprintf(stderr,\
diff --git a/innobase/lock/lock0lock.c b/innobase/lock/lock0lock.c
index 7588a576a86..0bc7e9b4166 100644
--- a/innobase/lock/lock0lock.c
+++ b/innobase/lock/lock0lock.c
@@ -301,6 +301,11 @@ struct lock_struct{
} un_member;
};
+/* We store info on the latest deadlock error to this buffer. InnoDB
+Monitor will then fetch it and print */
+ibool lock_deadlock_found = FALSE;
+char* lock_latest_err_buf; /* We allocate 5000 bytes for this */
+
/************************************************************************
Checks if a lock request results in a deadlock. */
static
@@ -576,6 +581,8 @@ lock_sys_create(
lock_sys->rec_hash = hash_create(n_cells);
/* hash_create_mutexes(lock_sys->rec_hash, 2, SYNC_REC_LOCK); */
+
+ lock_latest_err_buf = mem_alloc(5000);
}
/*************************************************************************
@@ -1566,6 +1573,7 @@ index->table_name);
}
trx->que_state = TRX_QUE_LOCK_WAIT;
+ trx->wait_started = time(NULL);
ut_a(que_thr_stop(thr));
@@ -2698,6 +2706,7 @@ lock_deadlock_occurs(
trx_t* mark_trx;
ibool ret;
ulint cost = 0;
+ char* err_buf;
ut_ad(trx && lock);
ut_ad(mutex_own(&kernel_mutex));
@@ -2723,6 +2732,29 @@ lock_deadlock_occurs(
index = lock->index;
table = index->table;
}
+
+ lock_deadlock_found = TRUE;
+
+ err_buf = lock_latest_err_buf + strlen(lock_latest_err_buf);
+
+ err_buf += sprintf(err_buf,
+ "*** (2) WAITING FOR THIS LOCK TO BE GRANTED:\n");
+
+ ut_a(err_buf <= lock_latest_err_buf + 4000);
+
+ if (lock_get_type(lock) == LOCK_REC) {
+ lock_rec_print(err_buf, lock);
+ err_buf += strlen(err_buf);
+ } else {
+ lock_table_print(err_buf, lock);
+ err_buf += strlen(err_buf);
+ }
+
+ ut_a(err_buf <= lock_latest_err_buf + 4000);
+
+ err_buf += sprintf(err_buf,
+ "*** WE ROLL BACK TRANSACTION (2)\n");
+
/*
sess_raise_error_low(trx, DB_DEADLOCK, lock->type_mode, table,
index, NULL, NULL, NULL);
@@ -2750,6 +2782,7 @@ lock_deadlock_recursive(
lock_t* lock;
ulint bit_no = 0; /* remove warning */
trx_t* lock_trx;
+ char* err_buf;
ut_a(trx && start && wait_lock);
ut_ad(mutex_own(&kernel_mutex));
@@ -2801,6 +2834,53 @@ lock_deadlock_recursive(
lock_trx = lock->trx;
if (lock_trx == start) {
+ err_buf = lock_latest_err_buf;
+
+ ut_sprintf_timestamp(err_buf);
+ err_buf += strlen(err_buf);
+
+ err_buf += sprintf(err_buf,
+ " LATEST DETECTED DEADLOCK:\n"
+ "*** (1) TRANSACTION:\n");
+
+ trx_print(err_buf, wait_lock->trx);
+ err_buf += strlen(err_buf);
+
+ err_buf += sprintf(err_buf,
+ "*** (1) WAITING FOR THIS LOCK TO BE GRANTED:\n");
+
+ ut_a(err_buf <= lock_latest_err_buf + 4000);
+
+ if (lock_get_type(wait_lock) == LOCK_REC) {
+ lock_rec_print(err_buf, wait_lock);
+ err_buf += strlen(err_buf);
+ } else {
+ lock_table_print(err_buf, wait_lock);
+ err_buf += strlen(err_buf);
+ }
+
+ ut_a(err_buf <= lock_latest_err_buf + 4000);
+ err_buf += sprintf(err_buf,
+ "*** (2) TRANSACTION:\n");
+
+ trx_print(err_buf, lock->trx);
+ err_buf += strlen(err_buf);
+
+ err_buf += sprintf(err_buf,
+ "*** (2) HOLDS THE LOCK(S):\n");
+
+ ut_a(err_buf <= lock_latest_err_buf + 4000);
+
+ if (lock_get_type(lock) == LOCK_REC) {
+ lock_rec_print(err_buf, lock);
+ err_buf += strlen(err_buf);
+ } else {
+ lock_table_print(err_buf, lock);
+ err_buf += strlen(err_buf);
+ }
+
+ ut_a(err_buf <= lock_latest_err_buf + 4000);
+
if (lock_print_waits) {
printf("Deadlock detected\n");
}
@@ -2962,6 +3042,7 @@ table->name);
}
trx->que_state = TRX_QUE_LOCK_WAIT;
+ trx->wait_started = time(NULL);
ut_a(que_thr_stop(thr));
@@ -3432,6 +3513,9 @@ lock_rec_print(
buf += sprintf(buf,
"Suppressing further record lock prints for this page\n");
+
+ mtr_commit(&mtr);
+
return;
}
@@ -3520,6 +3604,22 @@ lock_print_info(
buf += sprintf(buf,
"Total number of lock structs in row lock hash table %lu\n",
lock_get_n_rec_locks());
+ if (lock_deadlock_found) {
+
+ if ((ulint)(buf_end - buf)
+ < 100 + strlen(lock_latest_err_buf)) {
+
+ return;
+ }
+
+ buf += sprintf(buf, "%s", lock_latest_err_buf);
+ }
+
+ if (buf_end - buf < 600) {
+ return;
+ }
+
+ buf += sprintf(buf, "LIST OF TRANSACTIONS FOR EACH SESSION:\n");
/* First print info on non-active transactions */
@@ -3588,7 +3688,8 @@ loop:
if (trx->que_state == TRX_QUE_LOCK_WAIT) {
buf += sprintf(buf,
- "------------------TRX IS WAITING FOR THE LOCK:\n");
+ "------- TRX HAS BEEN WAITING %lu SEC FOR THIS LOCK TO BE GRANTED:\n",
+ (ulint)difftime(time(NULL), trx->wait_started));
if (lock_get_type(trx->wait_lock) == LOCK_REC) {
lock_rec_print(buf, trx->wait_lock);
diff --git a/innobase/log/log0log.c b/innobase/log/log0log.c
index 9748384183c..c798a08e2de 100644
--- a/innobase/log/log0log.c
+++ b/innobase/log/log0log.c
@@ -270,7 +270,7 @@ part_loop:
log->lsn = ut_dulint_add(log->lsn, len);
- /* Initialize the next block header and trailer */
+ /* Initialize the next block header */
log_block_init(log_block + OS_FILE_LOG_BLOCK_SIZE, log->lsn);
} else {
log->lsn = ut_dulint_add(log->lsn, len);
@@ -1070,28 +1070,16 @@ log_group_file_header_flush(
}
/**********************************************************
-Stores a 1-byte checksum to the trailer checksum field of a log block
+Stores a 4-byte checksum to the trailer checksum field of a log block
before writing it to a log file. This checksum is used in recovery to
-check the consistency of a log block. The checksum is simply the 8 low
-bits of 1 + the sum of the bytes in the log block except the trailer bytes. */
+check the consistency of a log block. */
static
void
log_block_store_checksum(
/*=====================*/
byte* block) /* in/out: pointer to a log block */
{
- ulint i;
- ulint sum;
-
- sum = 1;
-
- for (i = 0; i < OS_FILE_LOG_BLOCK_SIZE - LOG_BLOCK_TRL_SIZE; i++) {
- sum += (ulint)(*(block + i));
- }
-
- mach_write_to_1(block + OS_FILE_LOG_BLOCK_SIZE
- - LOG_BLOCK_TRL_CHECKSUM,
- 0xFF & sum);
+ log_block_set_checksum(block, log_block_calc_checksum(block));
}
/**********************************************************
@@ -3113,8 +3101,8 @@ log_print(
current_time = time(NULL);
- time_elapsed = difftime(current_time, log_sys->last_printout_time);
-
+ time_elapsed = 0.001 + difftime(current_time,
+ log_sys->last_printout_time);
buf += sprintf(buf,
"%lu pending log writes, %lu pending chkp writes\n"
"%lu log i/o's done, %.2f log i/o's/second\n",
@@ -3128,3 +3116,14 @@ log_print(
mutex_exit(&(log_sys->mutex));
}
+
+/**************************************************************************
+Refreshes the statistics used to print per-second averages. */
+
+void
+log_refresh_stats(void)
+/*===================*/
+{
+ log_sys->n_log_ios_old = log_sys->n_log_ios;
+ log_sys->last_printout_time = time(NULL);
+}
diff --git a/innobase/log/log0recv.c b/innobase/log/log0recv.c
index 53f75c176ea..1223f9b6041 100644
--- a/innobase/log/log0recv.c
+++ b/innobase/log/log0recv.c
@@ -58,12 +58,16 @@ yet: the variable name is misleading */
ibool recv_no_ibuf_operations = FALSE;
-/* the following counter is used to decide when to print info on
+/* The following counter is used to decide when to print info on
log scan */
ulint recv_scan_print_counter = 0;
ibool recv_is_from_backup = FALSE;
+ibool recv_is_making_a_backup = FALSE;
+ulint recv_previous_parsed_rec_type = 999999;
+ulint recv_previous_parsed_rec_offset = 0;
+ulint recv_previous_parsed_rec_is_multi = 0;
/************************************************************
Creates the recovery system. */
@@ -124,6 +128,8 @@ recv_sys_init(
recv_sys->last_block = ut_align(recv_sys->last_block_buf_start,
OS_FILE_LOG_BLOCK_SIZE);
+ recv_sys->found_corrupt_log = FALSE;
+
mutex_exit(&(recv_sys->mutex));
}
@@ -569,9 +575,9 @@ recv_read_cp_info_for_backup(
}
/**********************************************************
-Checks the 1-byte checksum to the trailer checksum field of a log block.
-We also accept a log block in the old format where the checksum field
-contained the highest byte of the log block number. */
+Checks the 4-byte checksum to the trailer checksum field of a log block.
+We also accept a log block in the old format < InnoDB-3.23.52 where the
+checksum field contains the log block number. */
static
ibool
log_block_checksum_is_ok_or_old_format(
@@ -580,29 +586,12 @@ log_block_checksum_is_ok_or_old_format(
format of InnoDB version < 3.23.52 */
byte* block) /* in: pointer to a log block */
{
- ulint i;
- ulint sum;
-
- sum = 1;
-
- for (i = 0; i < OS_FILE_LOG_BLOCK_SIZE - LOG_BLOCK_TRL_SIZE; i++) {
- sum += (ulint)(*(block + i));
- }
-
-/* printf("Checksum %lu, byte %lu\n", 0xFF & sum,
- mach_read_from_1(block + OS_FILE_LOG_BLOCK_SIZE
- - LOG_BLOCK_TRL_CHECKSUM));
-*/
- if (mach_read_from_1(block + OS_FILE_LOG_BLOCK_SIZE
- - LOG_BLOCK_TRL_CHECKSUM)
- == (0xFF & sum)) {
+ if (log_block_calc_checksum(block) == log_block_get_checksum(block)) {
return(TRUE);
}
- if (((0xFF000000 & log_block_get_hdr_no(block)) >> 24)
- == mach_read_from_1(block + OS_FILE_LOG_BLOCK_SIZE
- - LOG_BLOCK_TRL_CHECKSUM)) {
+ if (log_block_get_hdr_no(block) == log_block_get_checksum(block)) {
/* We assume the log block is in the format of
InnoDB version < 3.23.52 and the block is ok */
@@ -649,23 +638,20 @@ recv_scan_log_seg_for_backup(
/* fprintf(stderr, "Log block header no %lu\n", no); */
- if ((no & 0xFFFFFF) != log_block_get_trl_no(log_block)
- || no != log_block_convert_lsn_to_no(*scanned_lsn)
+ if (no != log_block_convert_lsn_to_no(*scanned_lsn)
|| !log_block_checksum_is_ok_or_old_format(log_block)) {
/*
printf(
-"Log block n:o %lu, trailer n:o %lu, scanned lsn n:o %lu\n",
- no, log_block_get_trl_no(log_block),
- log_block_convert_lsn_to_no(*scanned_lsn));
+"Log block n:o %lu, scanned lsn n:o %lu\n",
+ no, log_block_convert_lsn_to_no(*scanned_lsn));
*/
/* Garbage or an incompletely written log block */
log_block += OS_FILE_LOG_BLOCK_SIZE;
/*
printf(
-"Next log block n:o %lu, trailer n:o %lu\n",
- log_block_get_hdr_no(log_block),
- log_block_get_trl_no(log_block));
+"Next log block n:o %lu\n",
+ log_block_get_hdr_no(log_block));
*/
break;
}
@@ -788,14 +774,8 @@ recv_parse_or_apply_log_rec_body(
new_ptr = mlog_parse_string(ptr, end_ptr, page);
} else {
new_ptr = NULL;
-
- fprintf(stderr,
- "InnoDB: WARNING: the log file may have been corrupt and it\n"
- "InnoDB: is possible that the log scan did not proceed\n"
- "InnoDB: far enough in recovery. Please run CHECK TABLE\n"
- "InnoDB: on your InnoDB tables to check that they are ok!\n"
- "InnoDB: Corrupt log record type %lu\n",
- (ulint)type);
+
+ recv_sys->found_corrupt_log = TRUE;
}
ut_ad(!page || new_ptr);
@@ -1399,18 +1379,30 @@ recv_apply_log_recs_for_backup(
OS_FILE_OPEN,
OS_FILE_READ_WRITE,
&success);
- ut_a(success);
+ if (!success) {
+ printf(
+"InnoDB: Error: cannot open %lu'th data file %s\n", nth_file);
+
+ exit(1);
+ }
}
recv_addr = recv_get_fil_addr_struct(0, i);
if (recv_addr != NULL) {
- os_file_read(data_file, page,
+ success = os_file_read(data_file, page,
(nth_page_in_file << UNIV_PAGE_SIZE_SHIFT)
& 0xFFFFFFFF,
nth_page_in_file >> (32 - UNIV_PAGE_SIZE_SHIFT),
UNIV_PAGE_SIZE);
+ if (!success) {
+ printf(
+"InnoDB: Error: cannot read page no %lu from %lu'th data file %s\n",
+ nth_page_in_file, nth_file);
+ exit(1);
+ }
+
/* We simulate a page read made by the buffer pool,
to make sure recovery works ok. We must init the
block corresponding to buf_pool->frame_zero
@@ -1425,12 +1417,19 @@ recv_apply_log_recs_for_backup(
mach_read_from_8(page + FIL_PAGE_LSN),
0, i);
- os_file_write(data_files[nth_file],
+ success = os_file_write(data_files[nth_file],
data_file, page,
(nth_page_in_file << UNIV_PAGE_SIZE_SHIFT)
& 0xFFFFFFFF,
nth_page_in_file >> (32 - UNIV_PAGE_SIZE_SHIFT),
UNIV_PAGE_SIZE);
+ if (!success) {
+ printf(
+"InnoDB: Error: cannot write page no %lu to %lu'th data file %s\n",
+ nth_page_in_file, nth_file);
+
+ exit(1);
+ }
}
if ((100 * i) / n_pages_total
@@ -1679,29 +1678,16 @@ recv_parse_log_rec(
new_ptr = mlog_parse_initial_log_record(ptr, end_ptr, type, space,
page_no);
-
- /* If the operating system writes to the log complete 512-byte
- blocks, we should not get the warnings below in recovery.
- A warning means that the header and the trailer appeared ok
- in a 512-byte block, but in the middle there was something wrong.
- TODO: (1) add similar warnings in the case there is an incompletely
- written log record which does not extend to the boundary of a
- 512-byte block. (2) Add a checksum to a log block. */
-
if (!new_ptr) {
+
return(0);
}
/* Check that space id and page_no are sensible */
if (*space != 0 || *page_no > 0x8FFFFFFF) {
- fprintf(stderr,
- "InnoDB: WARNING: the log file may have been corrupt and it\n"
- "InnoDB: is possible that the log scan did not proceed\n"
- "InnoDB: far enough in recovery. Please run CHECK TABLE\n"
- "InnoDB: on your InnoDB tables to check that they are ok!\n"
- "InnoDB: Corrupt log record type %lu, space id %lu, page no %lu\n",
- (ulint)(*type), *space, *page_no);
+
+ recv_sys->found_corrupt_log = TRUE;
return(0);
}
@@ -1766,14 +1752,70 @@ recv_check_incomplete_log_recs(
}
/***********************************************************
+Prints diagnostic info of corrupt log. */
+static
+void
+recv_report_corrupt_log(
+/*====================*/
+ byte* ptr, /* in: pointer to corrupt log record */
+ byte type, /* in: type of the record */
+ ulint space, /* in: space id, this may also be garbage */
+ ulint page_no)/* in: page number, this may also be garbage */
+{
+ char* err_buf;
+
+ fprintf(stderr,
+"InnoDB: ############### CORRUPT LOG RECORD FOUND\n"
+"InnoDB: Log record type %lu, space id %lu, page number %lu\n"
+"InnoDB: Log parsing proceeded successfully up to %lu %lu\n",
+ (ulint)type, space, page_no,
+ ut_dulint_get_high(recv_sys->recovered_lsn),
+ ut_dulint_get_low(recv_sys->recovered_lsn));
+
+ err_buf = ut_malloc(1000000);
+
+ fprintf(stderr,
+"InnoDB: Previous log record type %lu, is multi %lu\n"
+"InnoDB: Recv offset %lu, prev %lu\n",
+ recv_previous_parsed_rec_type,
+ recv_previous_parsed_rec_is_multi,
+ ptr - recv_sys->buf,
+ recv_previous_parsed_rec_offset);
+
+ if ((ulint)(ptr - recv_sys->buf + 100)
+ > recv_previous_parsed_rec_offset
+ && (ulint)(ptr - recv_sys->buf + 100
+ - recv_previous_parsed_rec_offset)
+ < 200000) {
+
+ ut_sprintf_buf(err_buf,
+ recv_sys->buf + recv_previous_parsed_rec_offset - 100,
+ ptr - recv_sys->buf + 200 -
+ recv_previous_parsed_rec_offset);
+ fprintf(stderr,
+"InnoDB: Hex dump of corrupt log starting 100 bytes before the start\n"
+"InnoDB: of the previous log rec,\n"
+"InnoDB: and ending 100 bytes after the start of the corrupt rec:\n%s\n",
+ err_buf);
+ }
+
+ ut_free(err_buf);
+
+ fprintf(stderr,
+ "InnoDB: WARNING: the log file may have been corrupt and it\n"
+ "InnoDB: is possible that the log scan did not proceed\n"
+ "InnoDB: far enough in recovery! Please run CHECK TABLE\n"
+ "InnoDB: on your InnoDB tables to check that they are ok!\n");
+}
+
+/***********************************************************
Parses log records from a buffer and stores them to a hash table to wait
merging to file pages. */
static
ibool
recv_parse_log_recs(
/*================*/
- /* out: TRUE if the hash table of parsed log
- records became full */
+ /* out: currently always returns FALSE */
ibool store_to_hash) /* in: TRUE if the records should be stored
to the hash table; this is set to FALSE if just
debug checking is needed */
@@ -1812,8 +1854,13 @@ loop:
len = recv_parse_log_rec(ptr, end_ptr, &type, &space,
&page_no, &body);
- if (len == 0) {
+ if (len == 0 || recv_sys->found_corrupt_log) {
+ if (recv_sys->found_corrupt_log) {
+ recv_report_corrupt_log(ptr,
+ type, space, page_no);
+ }
+
return(FALSE);
}
@@ -1828,6 +1875,10 @@ loop:
return(FALSE);
}
+ recv_previous_parsed_rec_type = (ulint)type;
+ recv_previous_parsed_rec_offset = recv_sys->recovered_offset;
+ recv_previous_parsed_rec_is_multi = 0;
+
recv_sys->recovered_offset += len;
recv_sys->recovered_lsn = new_recovered_lsn;
@@ -1851,9 +1902,10 @@ loop:
#ifdef UNIV_LOG_DEBUG
recv_check_incomplete_log_recs(ptr, len);
#endif
- recv_update_replicate(type, space, page_no, body,
+/* recv_update_replicate(type, space, page_no, body,
ptr + len);
recv_compare_replicate(space, page_no);
+*/
}
} else {
/* Check that all the records associated with the single mtr
@@ -1865,19 +1917,32 @@ loop:
for (;;) {
len = recv_parse_log_rec(ptr, end_ptr, &type, &space,
&page_no, &body);
- if (len == 0) {
+ if (len == 0 || recv_sys->found_corrupt_log) {
- return(FALSE);
+ if (recv_sys->found_corrupt_log) {
+
+ recv_report_corrupt_log(ptr,
+ type, space, page_no);
+ }
+
+ return(FALSE);
}
+ recv_previous_parsed_rec_type = (ulint)type;
+ recv_previous_parsed_rec_offset
+ = recv_sys->recovered_offset + total_len;
+ recv_previous_parsed_rec_is_multi = 1;
+
if ((!store_to_hash) && (type != MLOG_MULTI_REC_END)) {
/* In debug checking, update a replicate page
according to the log record */
#ifdef UNIV_LOG_DEBUG
recv_check_incomplete_log_recs(ptr, len);
#endif
+/*
recv_update_replicate(type, space, page_no,
body, ptr + len);
+*/
}
if (log_debug_writes) {
@@ -1919,6 +1984,12 @@ loop:
old_lsn = recv_sys->recovered_lsn;
len = recv_parse_log_rec(ptr, end_ptr, &type, &space,
&page_no, &body);
+ if (recv_sys->found_corrupt_log) {
+
+ recv_report_corrupt_log(ptr,
+ type, space, page_no);
+ }
+
ut_a(len != 0);
ut_a(0 == ((ulint)*ptr & MLOG_SINGLE_REC_FLAG));
@@ -1941,7 +2012,7 @@ loop:
page has become identical with the original
page */
- recv_compare_replicate(space, page_no);
+/* recv_compare_replicate(space, page_no); */
}
ptr += len;
@@ -2095,32 +2166,19 @@ recv_scan_log_recs(
/* fprintf(stderr, "Log block header no %lu\n", no); */
- if ((no & 0xFFFFFF) != log_block_get_trl_no(log_block)
- || no != log_block_convert_lsn_to_no(scanned_lsn)
+ if (no != log_block_convert_lsn_to_no(scanned_lsn)
|| !log_block_checksum_is_ok_or_old_format(log_block)) {
- if ((no & 0xFFFFFF) == log_block_get_trl_no(log_block)
- && no == log_block_convert_lsn_to_no(scanned_lsn)
+ if (no == log_block_convert_lsn_to_no(scanned_lsn)
&& !log_block_checksum_is_ok_or_old_format(
log_block)) {
fprintf(stderr,
"InnoDB: Log block no %lu at lsn %lu %lu has\n"
-"InnoDB: ok header and trailer, but checksum field contains %lu\n",
- no, ut_dulint_get_high(scanned_lsn),
- ut_dulint_get_low(scanned_lsn),
- mach_read_from_1(log_block
- + OS_FILE_LOG_BLOCK_SIZE
- - LOG_BLOCK_TRL_CHECKSUM));
- }
-
- if ((no & 0xFFFFFF)
- != log_block_get_trl_no(log_block)) {
- fprintf(stderr,
-"InnoDB: Log block with header no %lu at lsn %lu %lu has\n"
-"InnoDB: trailer no %lu\n",
+"InnoDB: ok header, but checksum field contains %lu, should be %lu\n",
no, ut_dulint_get_high(scanned_lsn),
ut_dulint_get_low(scanned_lsn),
- log_block_get_trl_no(log_block));
+ log_block_get_checksum(log_block),
+ log_block_calc_checksum(log_block));
}
/* Garbage or an incompletely written log block */
@@ -2192,11 +2250,14 @@ recv_scan_log_recs(
>= RECV_PARSING_BUF_SIZE) {
fprintf(stderr,
"InnoDB: Error: log parsing buffer overflow. Recovery may have failed!\n");
- finished = TRUE;
+
+ recv_sys->found_corrupt_log = TRUE;
+
+ } else if (!recv_sys->found_corrupt_log) {
+ more_data = recv_sys_add_to_parsing_buf(
+ log_block, scanned_lsn);
}
- more_data = recv_sys_add_to_parsing_buf(log_block,
- scanned_lsn);
recv_sys->scanned_lsn = scanned_lsn;
recv_sys->scanned_checkpoint_no =
log_block_get_checkpoint_no(log_block);
@@ -2213,7 +2274,8 @@ recv_scan_log_recs(
*group_scanned_lsn = scanned_lsn;
- if (recv_needed_recovery || recv_is_from_backup) {
+ if (recv_needed_recovery
+ || (recv_is_from_backup && !recv_is_making_a_backup)) {
recv_scan_print_counter++;
if (finished || (recv_scan_print_counter % 80 == 0)) {
@@ -2225,7 +2287,7 @@ recv_scan_log_recs(
}
}
- if (more_data) {
+ if (more_data && !recv_sys->found_corrupt_log) {
/* Try to parse more log records */
recv_parse_log_recs(store_to_hash);
@@ -2602,6 +2664,17 @@ recv_recovery_from_checkpoint_finish(void)
trx_sys_print_mysql_binlog_offset();
}
+ if (recv_sys->found_corrupt_log) {
+
+ fprintf(stderr,
+ "InnoDB: WARNING: the log file may have been corrupt and it\n"
+ "InnoDB: is possible that the log scan or parsing did not proceed\n"
+ "InnoDB: far enough in recovery. Please run CHECK TABLE\n"
+ "InnoDB: on your InnoDB tables to check that they are ok!\n"
+ "InnoDB: It may be safest to recover your InnoDB database from\n"
+ "InnoDB: a backup!\n");
+ }
+
/* Free the resources of the recovery system */
recv_recovery_on = FALSE;
diff --git a/innobase/mem/mem0dbg.c b/innobase/mem/mem0dbg.c
index f94119b7f38..23585e494b8 100644
--- a/innobase/mem/mem0dbg.c
+++ b/innobase/mem/mem0dbg.c
@@ -668,7 +668,7 @@ mem_print_info_low(
mem_pool_print_info(outfile, mem_comm_pool);
- mem_validate();
+/* mem_validate(); */
/* fclose(outfile); */
#endif
diff --git a/innobase/mem/mem0pool.c b/innobase/mem/mem0pool.c
index 3681c8ef779..61cf1e50ce9 100644
--- a/innobase/mem/mem0pool.c
+++ b/innobase/mem/mem0pool.c
@@ -251,6 +251,7 @@ mem_pool_fill_free_list(
mem_area_t* area;
mem_area_t* area2;
ibool ret;
+ char err_buf[500];
ut_ad(mutex_own(&(pool->mutex)));
@@ -279,15 +280,34 @@ mem_pool_fill_free_list(
area = UT_LIST_GET_FIRST(pool->free_list[i + 1]);
if (area == NULL) {
+ if (UT_LIST_GET_LEN(pool->free_list[i + 1]) > 0) {
+ ut_print_timestamp(stderr);
+
+ fprintf(stderr,
+" InnoDB: Error: mem pool free list %lu length is %lu\n"
+"InnoDB: though the list is empty!\n",
+ i + 1, UT_LIST_GET_LEN(pool->free_list[i + 1]));
+ }
+
ret = mem_pool_fill_free_list(i + 1, pool);
if (ret == FALSE) {
+
return(FALSE);
}
area = UT_LIST_GET_FIRST(pool->free_list[i + 1]);
}
-
+
+ if (UT_LIST_GET_LEN(pool->free_list[i + 1]) == 0) {
+ ut_sprintf_buf(err_buf, ((byte*)area) - 50, 100);
+ fprintf(stderr,
+"InnoDB: Error: Removing element from mem pool free list %lu\n"
+"InnoDB: though the list length is 0! Dump of 100 bytes around element:\n%s\n",
+ i + 1, err_buf);
+ ut_a(0);
+ }
+
UT_LIST_REMOVE(free_list, pool->free_list[i + 1], area);
area2 = (mem_area_t*)(((byte*)area) + ut_2_exp(i));
@@ -320,6 +340,7 @@ mem_area_alloc(
mem_area_t* area;
ulint n;
ibool ret;
+ char err_buf[500];
n = ut_2_log(ut_max(size + MEM_AREA_EXTRA_SIZE, MEM_AREA_MIN_SIZE));
@@ -342,7 +363,24 @@ mem_area_alloc(
area = UT_LIST_GET_FIRST(pool->free_list[n]);
}
- ut_a(mem_area_get_free(area));
+ if (!mem_area_get_free(area)) {
+ ut_sprintf_buf(err_buf, ((byte*)area) - 50, 100);
+ fprintf(stderr,
+"InnoDB: Error: Removing element from mem pool free list %lu though the\n"
+"InnoDB: element is not marked free! Dump of 100 bytes around element:\n%s\n",
+ n, err_buf);
+ ut_a(0);
+ }
+
+ if (UT_LIST_GET_LEN(pool->free_list[n]) == 0) {
+ ut_sprintf_buf(err_buf, ((byte*)area) - 50, 100);
+ fprintf(stderr,
+"InnoDB: Error: Removing element from mem pool free list %lu\n"
+"InnoDB: though the list length is 0! Dump of 100 bytes around element:\n%s\n",
+ n, err_buf);
+ ut_a(0);
+ }
+
ut_ad(mem_area_get_size(area) == ut_2_exp(n));
mem_area_set_free(area, FALSE);
@@ -413,6 +451,7 @@ mem_area_free(
void* new_ptr;
ulint size;
ulint n;
+ char err_buf[500];
if (mem_out_of_mem_err_msg_count > 0) {
/* It may be that the area was really allocated from the
@@ -429,10 +468,18 @@ mem_area_free(
area = (mem_area_t*) (((byte*)ptr) - MEM_AREA_EXTRA_SIZE);
+ if (mem_area_get_free(area)) {
+ ut_sprintf_buf(err_buf, ((byte*)area) - 50, 100);
+ fprintf(stderr,
+"InnoDB: Error: Freeing element to mem pool free list though the\n"
+"InnoDB: element is marked free! Dump of 100 bytes around element:\n%s\n",
+ err_buf);
+ ut_a(0);
+ }
+
size = mem_area_get_size(area);
ut_ad(size != 0);
- ut_a(!mem_area_get_free(area));
#ifdef UNIV_LIGHT_MEM_DEBUG
if (((byte*)area) + size < pool->buf + pool->size) {
diff --git a/innobase/mtr/mtr0log.c b/innobase/mtr/mtr0log.c
index b582afc5710..2cfe81d3261 100644
--- a/innobase/mtr/mtr0log.c
+++ b/innobase/mtr/mtr0log.c
@@ -14,6 +14,7 @@ Created 12/7/1995 Heikki Tuuri
#include "buf0buf.h"
#include "dict0boot.h"
+#include "log0recv.h"
/************************************************************
Catenates n bytes to the mtr log. */
@@ -121,7 +122,7 @@ byte*
mlog_parse_nbytes(
/*==============*/
/* out: parsed record end, NULL if not a complete
- record */
+ record or a corrupt record */
ulint type, /* in: log record type: MLOG_1BYTE, ... */
byte* ptr, /* in: buffer */
byte* end_ptr,/* in: buffer end */
@@ -141,6 +142,12 @@ mlog_parse_nbytes(
offset = mach_read_from_2(ptr);
ptr += 2;
+ if (offset >= UNIV_PAGE_SIZE) {
+ recv_sys->found_corrupt_log = TRUE;
+
+ return(NULL);
+ }
+
if (type == MLOG_8BYTES) {
ptr = mach_dulint_parse_compressed(ptr, end_ptr, &dval);
@@ -163,13 +170,33 @@ mlog_parse_nbytes(
return(NULL);
}
+ if (type == MLOG_1BYTE) {
+ if (val > 0xFF) {
+ recv_sys->found_corrupt_log = TRUE;
+
+ return(NULL);
+ }
+ } else if (type == MLOG_2BYTES) {
+ if (val > 0xFFFF) {
+ recv_sys->found_corrupt_log = TRUE;
+
+ return(NULL);
+ }
+ } else {
+ if (type != MLOG_4BYTES) {
+ recv_sys->found_corrupt_log = TRUE;
+
+ return(NULL);
+ }
+ }
+
if (page) {
if (type == MLOG_1BYTE) {
mach_write_to_1(page + offset, val);
} else if (type == MLOG_2BYTES) {
mach_write_to_2(page + offset, val);
} else {
- ut_ad(type == MLOG_4BYTES);
+ ut_a(type == MLOG_4BYTES);
mach_write_to_4(page + offset, val);
}
}
@@ -338,7 +365,11 @@ mlog_parse_string(
offset = mach_read_from_2(ptr);
ptr += 2;
- ut_a(offset < UNIV_PAGE_SIZE);
+ if (offset >= UNIV_PAGE_SIZE) {
+ recv_sys->found_corrupt_log = TRUE;
+
+ return(NULL);
+ }
len = mach_read_from_2(ptr);
ptr += 2;
diff --git a/innobase/os/os0file.c b/innobase/os/os0file.c
index ae3c8a45f62..3ca0fbd68a4 100644
--- a/innobase/os/os0file.c
+++ b/innobase/os/os0file.c
@@ -22,7 +22,7 @@ Created 10/21/1995 Heikki Tuuri
#endif
-/* This specifies the file permissions InnoDB uses when it craetes files in
+/* This specifies the file permissions InnoDB uses when it creates files in
Unix; the value of os_innodb_umask is initialized in ha_innodb.cc to
my_umask */
@@ -2483,7 +2483,7 @@ loop:
buf += sprintf(buf, "\n");
current_time = time(NULL);
- time_elapsed = difftime(current_time, os_last_printout);
+ time_elapsed = 0.001 + difftime(current_time, os_last_printout);
buf += sprintf(buf,
"Pending flushes (fsync) log: %lu; buffer pool: %lu\n",
@@ -2518,6 +2518,21 @@ loop:
}
/**************************************************************************
+Refreshes the statistics used to print per-second averages. */
+
+void
+os_aio_refresh_stats(void)
+/*======================*/
+{
+ os_n_file_reads_old = os_n_file_reads;
+ os_n_file_writes_old = os_n_file_writes;
+ os_n_fsyncs_old = os_n_fsyncs;
+ os_bytes_read_since_printout = 0;
+
+ os_last_printout = time(NULL);
+}
+
+/**************************************************************************
Checks that all slots in the system have been freed, that is, there are
no pending io operations. */
diff --git a/innobase/os/os0thread.c b/innobase/os/os0thread.c
index 49d4c8518fb..a8b417f4f3a 100644
--- a/innobase/os/os0thread.c
+++ b/innobase/os/os0thread.c
@@ -18,26 +18,63 @@ Created 9/8/1995 Heikki Tuuri
#include "srv0srv.h"
+/*******************************************************************
+Compares two threads or thread ids for equality */
+
+ibool
+os_thread_eq(
+/*=========*/
+ /* out: TRUE if equal */
+ os_thread_t a, /* in: OS thread or thread id */
+ os_thread_t b) /* in: OS thread or thread id */
+{
+#ifdef __WIN__
+ if (a == b) {
+ return(TRUE);
+ }
+
+ return(FALSE);
+#else
+ if (pthread_equal(a, b)) {
+ return(TRUE);
+ }
+
+ return(FALSE);
+#endif
+}
+
+/********************************************************************
+Converts an OS thread or thread id to a ulint. It is NOT guaranteed that
+the ulint is unique for the thread though! */
+
+ulint
+os_thread_pf(
+/*=========*/
+ os_thread_t a)
+{
+#ifdef UNIV_HPUX
+ /* In HP-UX a pthread_t is a struct of 3 fields: field1, field2,
+ field3. We do not know if field1 determines the thread uniquely. */
+
+ return((ulint)(a.field1));
+#else
+ return((ulint)a);
+#endif
+}
+
/*********************************************************************
-Returns the thread identifier of current thread. */
+Returns the thread identifier of current thread. Currently the thread
+identifier is the thread handle itself. Note that in HP-UX pthread_t is
+a struct of 3 fields. */
os_thread_id_t
os_thread_get_curr_id(void)
/*=======================*/
{
#ifdef __WIN__
- return(GetCurrentThreadId());
+ return(GetCurrentThread());
#else
- pthread_t pthr;
-
- pthr = pthread_self();
-
- /* TODO: in the future we have to change os_thread_id
- to pthread_t; the following cast may work in a wrong way on some
- systems if pthread_t is a struct; this is just a quick fix
- for HP-UX to eliminate a compiler warning */
-
- return(*(os_thread_id_t*)((void*) (&pthr)));
+ return(pthread_self());
#endif
}
@@ -71,7 +108,6 @@ os_thread_create(
arg,
0, /* thread runs immediately */
thread_id);
- ut_a(thread);
if (srv_set_thread_priorities) {
@@ -108,7 +144,7 @@ Returns handle to the current thread. */
os_thread_t
os_thread_get_curr(void)
-/*=======================*/
+/*====================*/
{
#ifdef __WIN__
return(GetCurrentThread());
@@ -116,18 +152,6 @@ os_thread_get_curr(void)
return(pthread_self());
#endif
}
-
-/*********************************************************************
-Converts a thread id to a ulint. */
-
-ulint
-os_thread_conv_id_to_ulint(
-/*=======================*/
- /* out: converted to ulint */
- os_thread_id_t id) /* in: thread id */
-{
- return((ulint)id);
-}
/*********************************************************************
Advises the os to give up remainder of the thread's time slice. */
diff --git a/innobase/page/page0cur.c b/innobase/page/page0cur.c
index 0eaf96f7e51..2909573b14b 100644
--- a/innobase/page/page0cur.c
+++ b/innobase/page/page0cur.c
@@ -13,6 +13,7 @@ Created 10/4/1994 Heikki Tuuri
#include "rem0cmp.h"
#include "mtr0log.h"
+#include "log0recv.h"
ulint page_cur_short_succ = 0;
@@ -481,6 +482,9 @@ page_cur_insert_rec_write_log(
/* Write the mismatch index */
log_ptr += mach_write_compressed(log_ptr, i);
+
+ ut_a(i < UNIV_PAGE_SIZE);
+ ut_a(extra_size < UNIV_PAGE_SIZE);
}
/* Write to the log the inserted index record end segment which
@@ -533,6 +537,13 @@ page_cur_parse_insert_rec(
}
offset = mach_read_from_2(ptr);
+
+ if (offset >= UNIV_PAGE_SIZE) {
+
+ recv_sys->found_corrupt_log = TRUE;
+
+ return(NULL);
+ }
ptr += 2;
}
@@ -546,6 +557,12 @@ page_cur_parse_insert_rec(
extra_info_yes = end_seg_len & 0x1;
end_seg_len = end_seg_len / 2;
+
+ if (end_seg_len >= UNIV_PAGE_SIZE) {
+ recv_sys->found_corrupt_log = TRUE;
+
+ return(NULL);
+ }
if (extra_info_yes) {
/* Read the info bits */
@@ -565,12 +582,16 @@ page_cur_parse_insert_rec(
return(NULL);
}
+ ut_a(origin_offset < UNIV_PAGE_SIZE);
+
ptr = mach_parse_compressed(ptr, end_ptr, &mismatch_index);
if (ptr == NULL) {
return(NULL);
}
+
+ ut_a(mismatch_index < UNIV_PAGE_SIZE);
}
if (end_ptr < ptr + end_seg_len) {
@@ -607,7 +628,6 @@ page_cur_parse_insert_rec(
/* Build the inserted record to buf */
ut_a(mismatch_index < UNIV_PAGE_SIZE);
- ut_a(end_seg_len < UNIV_PAGE_SIZE);
ut_memcpy(buf, rec_get_start(cursor_rec), mismatch_index);
ut_memcpy(buf + mismatch_index, ptr, end_seg_len);
@@ -1010,6 +1030,8 @@ page_cur_parse_delete_rec(
offset = mach_read_from_2(ptr);
ptr += 2;
+ ut_a(offset <= UNIV_PAGE_SIZE);
+
if (page) {
page_cur_position(page + offset, &cursor);
diff --git a/innobase/row/row0mysql.c b/innobase/row/row0mysql.c
index e0737f53213..3ee458f43bf 100644
--- a/innobase/row/row0mysql.c
+++ b/innobase/row/row0mysql.c
@@ -595,6 +595,11 @@ row_lock_table_autoinc_for_mysql(
ut_ad(trx);
ut_ad(trx->mysql_thread_id == os_thread_get_curr_id());
+ if (trx->auto_inc_lock) {
+
+ return(DB_SUCCESS);
+ }
+
trx->op_info = (char *) "setting auto-inc lock";
if (node == NULL) {
diff --git a/innobase/row/row0vers.c b/innobase/row/row0vers.c
index 9508e73f45d..cd8b18e5e12 100644
--- a/innobase/row/row0vers.c
+++ b/innobase/row/row0vers.c
@@ -58,6 +58,7 @@ row_vers_impl_x_locked_off_kernel(
ibool rec_del;
ulint err;
mtr_t mtr;
+ char err_buf[1000];
ut_ad(mutex_own(&kernel_mutex));
ut_ad(!rw_lock_own(&(purge_sys->latch), RW_LOCK_SHARED));
@@ -74,7 +75,26 @@ row_vers_impl_x_locked_off_kernel(
clust_rec = row_get_clust_rec(BTR_SEARCH_LEAF, rec, index,
&clust_index, &mtr);
- ut_a(clust_rec);
+ if (!clust_rec) {
+ rec_sprintf(err_buf, 900, rec);
+
+ ut_print_timestamp(stderr);
+ fprintf(stderr,
+" InnoDB: Error: cannot find the clustered index record\n"
+"InnoDB: for a secondary index record in table %s index %s.\n"
+"InnoDB: Secondary index record %s.\n"
+"InnoDB: The table is probably corrupt. Please run CHECK TABLE on it.\n"
+"InnoDB: You can try to repair the table by dump + drop + reimport.\n"
+"InnoDB: Send a detailed bug report to mysql@lists.mysql.com.\n",
+ index->table_name, index->name, err_buf);
+ mutex_enter(&kernel_mutex);
+ mtr_commit(&mtr);
+
+ /* We assume there is no lock on the record, though this
+ is not certain because the table is apparently corrupt */
+
+ return(NULL);
+ }
trx_id = row_get_rec_trx_id(clust_rec, clust_index);
diff --git a/innobase/srv/srv0srv.c b/innobase/srv/srv0srv.c
index 3efb82eb8eb..3b16e9557fa 100644
--- a/innobase/srv/srv0srv.c
+++ b/innobase/srv/srv0srv.c
@@ -2024,7 +2024,7 @@ srv_table_reserve_slot_for_mysql(void)
fprintf(stderr,
"Slot %lu: thread id %lu, type %lu, in use %lu, susp %lu, time %lu\n",
- i, (ulint)(slot->id),
+ i, os_thread_pf(slot->id),
slot->type, slot->in_use,
slot->suspended,
(ulint)difftime(ut_time(), slot->suspend_time));
@@ -2169,6 +2169,34 @@ srv_release_mysql_thread_if_suspended(
}
/**********************************************************************
+Refreshes the values used to calculate per-second averages. */
+static
+void
+srv_refresh_innodb_monitor_stats(void)
+/*==================================*/
+{
+ mutex_enter(&srv_innodb_monitor_mutex);
+
+ srv_last_monitor_time = time(NULL);
+
+ os_aio_refresh_stats();
+
+ btr_cur_n_sea_old = btr_cur_n_sea;
+ btr_cur_n_non_sea_old = btr_cur_n_non_sea;
+
+ log_refresh_stats();
+
+ buf_refresh_io_stats();
+
+ srv_n_rows_inserted_old = srv_n_rows_inserted;
+ srv_n_rows_updated_old = srv_n_rows_updated;
+ srv_n_rows_deleted_old = srv_n_rows_deleted;
+ srv_n_rows_read_old = srv_n_rows_read;
+
+ mutex_exit(&srv_innodb_monitor_mutex);
+}
+
+/**********************************************************************
Sprintfs to a buffer the output of the InnoDB Monitor. */
void
@@ -2205,7 +2233,7 @@ srv_sprintf_innodb_monitor(
"=====================================\n");
buf += sprintf(buf,
-"Per second values calculated from the last %lu seconds\n",
+"Per second averages calculated from the last %lu seconds\n",
(ulint)time_elapsed);
buf += sprintf(buf, "----------\n"
@@ -2242,8 +2270,8 @@ srv_sprintf_innodb_monitor(
/ time_elapsed,
(btr_cur_n_non_sea - btr_cur_n_non_sea_old)
/ time_elapsed);
- btr_cur_n_sea_old = btr_cur_n_sea;
- btr_cur_n_non_sea_old = btr_cur_n_non_sea;
+ btr_cur_n_sea_old = btr_cur_n_sea;
+ btr_cur_n_non_sea_old = btr_cur_n_non_sea;
buf += sprintf(buf,"---\n"
"LOG\n"
@@ -2285,10 +2313,10 @@ srv_sprintf_innodb_monitor(
(srv_n_rows_read - srv_n_rows_read_old)
/ time_elapsed);
- srv_n_rows_inserted_old = srv_n_rows_inserted;
- srv_n_rows_updated_old = srv_n_rows_updated;
- srv_n_rows_deleted_old = srv_n_rows_deleted;
- srv_n_rows_read_old = srv_n_rows_read;
+ srv_n_rows_inserted_old = srv_n_rows_inserted;
+ srv_n_rows_updated_old = srv_n_rows_updated;
+ srv_n_rows_deleted_old = srv_n_rows_deleted;
+ srv_n_rows_read_old = srv_n_rows_read;
buf += sprintf(buf, "----------------------------\n"
"END OF INNODB MONITOR OUTPUT\n"
@@ -2331,7 +2359,7 @@ loop:
/* When someone is waiting for a lock, we wake up every second
and check if a timeout has passed for a lock wait */
- os_thread_sleep(1000000);
+ os_thread_sleep(1000000);
/* In case mutex_exit is not a memory barrier, it is
theoretically possible some threads are left waiting though
@@ -2348,9 +2376,9 @@ loop:
if (srv_print_innodb_monitor) {
- buf = mem_alloc(100000);
+ buf = mem_alloc(100000);
- srv_sprintf_innodb_monitor(buf, 100000);
+ srv_sprintf_innodb_monitor(buf, 100000);
printf("%s", buf);
@@ -2481,12 +2509,30 @@ srv_error_monitor_thread(
void* arg) /* in: a dummy parameter required by
os_thread_create */
{
+ ulint cnt = 0;
+
UT_NOT_USED(arg);
loop:
srv_error_monitor_active = TRUE;
- os_thread_sleep(10000000);
+ cnt++;
+ os_thread_sleep(2000000);
+
+ if (difftime(time(NULL), srv_last_monitor_time) > 60) {
+ /* We referesh InnoDB Monitor values so that averages are
+ printed from at most 60 last seconds */
+
+ srv_refresh_innodb_monitor_stats();
+ }
+
+/* mem_print_new_info();
+
+ if (cnt % 10 == 0) {
+
+ mem_print_info();
+ }
+*/
sync_array_print_long_waits();
/* Flush stdout and stderr so that a database user gets their output
diff --git a/innobase/srv/srv0start.c b/innobase/srv/srv0start.c
index 55e734be3bd..dfa122b2ece 100644
--- a/innobase/srv/srv0start.c
+++ b/innobase/srv/srv0start.c
@@ -74,6 +74,12 @@ ulint ios;
ulint n[SRV_MAX_N_IO_THREADS + 5];
os_thread_id_t thread_ids[SRV_MAX_N_IO_THREADS + 5];
+/* We use this mutex to test the return value of pthread_mutex_trylock
+ on successful locking. HP-UX does NOT return 0, though Linux et al do. */
+os_fast_mutex_t srv_os_test_mutex;
+
+ibool srv_os_test_mutex_is_locked = FALSE;
+
#define SRV_N_PENDING_IOS_PER_THREAD OS_AIO_N_PENDING_IOS_PER_THREAD
#define SRV_MAX_N_PENDING_SYNC_IOS 100
@@ -927,6 +933,8 @@ innobase_start_or_create_for_mysql(void)
ulint max_arch_log_no;
ibool start_archive;
ulint sum_of_new_sizes;
+ ulint sum_of_data_file_sizes;
+ ulint tablespace_size_in_header;
ulint err;
ulint i;
ulint k;
@@ -1324,7 +1332,49 @@ innobase_start_or_create_for_mysql(void)
os_thread_create(&srv_master_thread, NULL, thread_ids + 1 +
SRV_MAX_N_IO_THREADS);
/* buf_debug_prints = TRUE; */
+
+ sum_of_data_file_sizes = 0;
+ for (i = 0; i < srv_n_data_files; i++) {
+ sum_of_data_file_sizes += srv_data_file_sizes[i];
+ }
+
+ tablespace_size_in_header = fsp_header_get_tablespace_size(0);
+
+ if (!srv_auto_extend_last_data_file
+ && sum_of_data_file_sizes != tablespace_size_in_header) {
+
+ fprintf(stderr,
+"InnoDB: Error: tablespace size stored in header is %lu pages, but\n"
+"InnoDB: the sum of data file sizes is %lu pages\n",
+ tablespace_size_in_header, sum_of_data_file_sizes);
+ }
+
+ if (srv_auto_extend_last_data_file
+ && sum_of_data_file_sizes < tablespace_size_in_header) {
+
+ fprintf(stderr,
+"InnoDB: Error: tablespace size stored in header is %lu pages, but\n"
+"InnoDB: the sum of data file sizes is only %lu pages\n",
+ tablespace_size_in_header, sum_of_data_file_sizes);
+ }
+
+ /* Check that os_fast_mutexes work as exptected */
+ os_fast_mutex_init(&srv_os_test_mutex);
+
+ if (0 != os_fast_mutex_trylock(&srv_os_test_mutex)) {
+ fprintf(stderr,
+"InnoDB: Error: pthread_mutex_trylock returns an unexpected value on\n"
+ "InnoDB: success! Cannot continue.\n");
+ exit(1);
+ }
+
+ os_fast_mutex_unlock(&srv_os_test_mutex);
+
+ os_fast_mutex_lock(&srv_os_test_mutex);
+
+ os_fast_mutex_unlock(&srv_os_test_mutex);
+
if (srv_print_verbose_log)
{
ut_print_timestamp(stderr);
diff --git a/innobase/sync/sync0arr.c b/innobase/sync/sync0arr.c
index 36dd8a7d80c..4d14c32b1ae 100644
--- a/innobase/sync/sync0arr.c
+++ b/innobase/sync/sync0arr.c
@@ -454,7 +454,7 @@ sync_array_cell_print(
buf += sprintf(buf,
"--Thread %lu has waited at %s line %lu for %.2f seconds the semaphore:\n",
- (ulint)cell->thread, cell->file, cell->line,
+ os_thread_pf(cell->thread), cell->file, cell->line,
difftime(time(NULL), cell->reservation_time));
if (type == SYNC_MUTEX) {
@@ -486,7 +486,7 @@ sync_array_cell_print(
if (rwlock->writer != RW_LOCK_NOT_LOCKED) {
buf += sprintf(buf,
"a writer (thread id %lu) has reserved it in mode",
- (ulint)rwlock->writer_thread);
+ os_thread_pf(rwlock->writer_thread));
if (rwlock->writer == RW_LOCK_EX) {
buf += sprintf(buf, " exclusive\n");
} else {
@@ -535,8 +535,8 @@ sync_array_find_thread(
cell = sync_array_get_nth_cell(arr, i);
- if ((cell->wait_object != NULL)
- && (cell->thread == thread)) {
+ if (cell->wait_object != NULL
+ && os_thread_eq(cell->thread, thread)) {
return(cell); /* Found */
}
@@ -651,9 +651,9 @@ sync_array_detect_deadlock(
sync_array_cell_print(buf, cell);
printf(
"Mutex %lx owned by thread %lu file %s line %lu\n%s",
- (ulint)mutex, mutex->thread_id,
- mutex->file_name, mutex->line,
- buf);
+ (ulint)mutex, os_thread_pf(mutex->thread_id),
+ mutex->file_name, mutex->line, buf);
+
return(TRUE);
}
}
@@ -671,9 +671,9 @@ sync_array_detect_deadlock(
thread = debug->thread_id;
if (((debug->lock_type == RW_LOCK_EX)
- && (thread != cell->thread))
+ && !os_thread_eq(thread, cell->thread))
|| ((debug->lock_type == RW_LOCK_WAIT_EX)
- && (thread != cell->thread))
+ && !os_thread_eq(thread, cell->thread))
|| (debug->lock_type == RW_LOCK_SHARED)) {
/* The (wait) x-lock request can block infinitely
@@ -771,7 +771,7 @@ sync_arr_cell_can_wake_up(
if (rw_lock_get_reader_count(lock) == 0
&& rw_lock_get_writer(lock) == RW_LOCK_WAIT_EX
- && lock->writer_thread == cell->thread) {
+ && os_thread_eq(lock->writer_thread, cell->thread)) {
return(TRUE);
}
@@ -927,7 +927,7 @@ sync_array_print_long_waits(void)
&& difftime(time(NULL), cell->reservation_time) > 420) {
fprintf(stderr,
-"InnoDB: Error: semaphore wait has lasted > 420 seconds\n"
+"InnoDB: Error: semaphore wait has lasted > 600 seconds\n"
"InnoDB: We intentionally crash the server, because it appears to be hung.\n"
);
@@ -1011,3 +1011,4 @@ sync_array_print_info(
sync_array_exit(arr);
}
+
diff --git a/innobase/sync/sync0rw.c b/innobase/sync/sync0rw.c
index 86ffed7ca95..fe837b119f3 100644
--- a/innobase/sync/sync0rw.c
+++ b/innobase/sync/sync0rw.c
@@ -223,7 +223,7 @@ lock_loop:
if (srv_print_latch_waits) {
printf(
"Thread %lu spin wait rw-s-lock at %lx cfile %s cline %lu rnds %lu\n",
- os_thread_get_curr_id(), (ulint)lock,
+ os_thread_pf(os_thread_get_curr_id()), (ulint)lock,
lock->cfile_name, lock->cline, i);
}
@@ -253,7 +253,7 @@ lock_loop:
if (srv_print_latch_waits) {
printf(
"Thread %lu OS wait rw-s-lock at %lx cfile %s cline %lu\n",
- os_thread_get_curr_id(), (ulint)lock,
+ os_thread_pf(os_thread_get_curr_id()), (ulint)lock,
lock->cfile_name, lock->cline);
}
@@ -343,7 +343,8 @@ rw_lock_x_lock_low(
}
} else if ((rw_lock_get_writer(lock) == RW_LOCK_WAIT_EX)
- && (lock->writer_thread == os_thread_get_curr_id())) {
+ && os_thread_eq(lock->writer_thread,
+ os_thread_get_curr_id())) {
if (rw_lock_get_reader_count(lock) == 0) {
@@ -368,7 +369,8 @@ rw_lock_x_lock_low(
return(RW_LOCK_WAIT_EX);
} else if ((rw_lock_get_writer(lock) == RW_LOCK_EX)
- && (lock->writer_thread == os_thread_get_curr_id())
+ && os_thread_eq(lock->writer_thread,
+ os_thread_get_curr_id())
&& (lock->pass == 0)
&& (pass == 0)) {
@@ -469,7 +471,7 @@ lock_loop:
if (srv_print_latch_waits) {
printf(
"Thread %lu spin wait rw-x-lock at %lx cfile %s cline %lu rnds %lu\n",
- os_thread_get_curr_id(), (ulint)lock,
+ os_thread_pf(os_thread_get_curr_id()), (ulint)lock,
lock->cfile_name, lock->cline, i);
}
@@ -502,8 +504,8 @@ lock_loop:
if (srv_print_latch_waits) {
printf(
"Thread %lu OS wait for rw-x-lock at %lx cfile %s cline %lu\n",
- os_thread_get_curr_id(), (ulint)lock, lock->cfile_name,
- lock->cline);
+ os_thread_pf(os_thread_get_curr_id()), (ulint)lock,
+ lock->cfile_name, lock->cline);
}
rw_x_system_call_count++;
@@ -621,7 +623,8 @@ rw_lock_remove_debug_info(
while (info != NULL) {
if ((pass == info->pass)
&& ((pass != 0)
- || (info->thread_id == os_thread_get_curr_id()))
+ || os_thread_eq(info->thread_id,
+ os_thread_get_curr_id()))
&& (info->lock_type == lock_type)) {
/* Found! */
@@ -676,7 +679,7 @@ rw_lock_own(
while (info != NULL) {
- if ((info->thread_id == os_thread_get_curr_id())
+ if (os_thread_eq(info->thread_id, os_thread_get_curr_id())
&& (info->pass == 0)
&& (info->lock_type == lock_type)) {
@@ -834,7 +837,7 @@ rw_lock_debug_print(
rwt = info->lock_type;
printf("Locked: thread %ld file %s line %ld ",
- info->thread_id, info->file_name, info->line);
+ os_thread_pf(info->thread_id), info->file_name, info->line);
if (rwt == RW_LOCK_SHARED) {
printf("S-LOCK");
} else if (rwt == RW_LOCK_EX) {
diff --git a/innobase/sync/sync0sync.c b/innobase/sync/sync0sync.c
index 14a2a6f8cc1..3ea996afd6b 100644
--- a/innobase/sync/sync0sync.c
+++ b/innobase/sync/sync0sync.c
@@ -230,7 +230,6 @@ mutex_create_func(
mutex->magic_n = MUTEX_MAGIC_N;
mutex->line = 0;
mutex->file_name = (char *) "not yet reserved";
- mutex->thread_id = ULINT_UNDEFINED;
mutex->level = SYNC_LEVEL_NONE;
mutex->cfile_name = cfile_name;
mutex->cline = cline;
@@ -392,8 +391,8 @@ spin_loop:
if (srv_print_latch_waits) {
printf(
"Thread %lu spin wait mutex at %lx cfile %s cline %lu rnds %lu\n",
- os_thread_get_curr_id(), (ulint)mutex, mutex->cfile_name,
- mutex->cline, i);
+ os_thread_pf(os_thread_get_curr_id()), (ulint)mutex,
+ mutex->cfile_name, mutex->cline, i);
}
mutex_spin_round_count += i;
@@ -458,7 +457,7 @@ spin_loop:
if (srv_print_latch_waits) {
printf(
"Thread %lu spin wait succeeds at 2: mutex at %lx\n",
- os_thread_get_curr_id(), (ulint)mutex);
+ os_thread_pf(os_thread_get_curr_id()), (ulint)mutex);
}
return;
@@ -476,8 +475,8 @@ spin_loop:
if (srv_print_latch_waits) {
printf(
"Thread %lu OS wait mutex at %lx cfile %s cline %lu rnds %lu\n",
- os_thread_get_curr_id(), (ulint)mutex, mutex->cfile_name,
- mutex->cline, i);
+ os_thread_pf(os_thread_get_curr_id()), (ulint)mutex,
+ mutex->cfile_name, mutex->cline, i);
}
mutex_system_call_count++;
@@ -572,7 +571,7 @@ mutex_own(
return(FALSE);
}
- if (mutex->thread_id != os_thread_get_curr_id()) {
+ if (!os_thread_eq(mutex->thread_id, os_thread_get_curr_id())) {
return(FALSE);
}
@@ -611,7 +610,8 @@ mutex_list_print_info(void)
&thread_id);
printf(
"Locked mutex: addr %lx thread %ld file %s line %ld\n",
- (ulint)mutex, thread_id, file_name, line);
+ (ulint)mutex, os_thread_pf(thread_id),
+ file_name, line);
}
mutex = UT_LIST_GET_NEXT(list, mutex);
@@ -716,7 +716,7 @@ sync_thread_level_arrays_find_slot(void)
slot = sync_thread_level_arrays_get_nth(i);
- if (slot->levels && (slot->id == id)) {
+ if (slot->levels && os_thread_eq(slot->id, id)) {
return(slot);
}
@@ -780,7 +780,7 @@ sync_thread_levels_g(
{
char* file_name;
ulint line;
- ulint thread_id;
+ os_thread_id_t thread_id;
sync_level_t* slot;
rw_lock_t* lock;
mutex_t* mutex;
@@ -810,7 +810,7 @@ sync_thread_levels_g(
&file_name, &line, &thread_id);
printf("InnoDB: Locked mutex: addr %lx thread %ld file %s line %ld\n",
- (ulint)mutex, thread_id,
+ (ulint)mutex, os_thread_pf(thread_id),
file_name, line);
} else {
printf("Not locked\n");
diff --git a/innobase/thr/thr0loc.c b/innobase/thr/thr0loc.c
index d3d7a58d313..fbf3e3a1dad 100644
--- a/innobase/thr/thr0loc.c
+++ b/innobase/thr/thr0loc.c
@@ -69,8 +69,8 @@ try_again:
local = NULL;
- HASH_SEARCH(hash, thr_local_hash, os_thread_conv_id_to_ulint(id),
- local, local->id == id);
+ HASH_SEARCH(hash, thr_local_hash, os_thread_pf(id),
+ local, os_thread_eq(local->id, id));
if (local == NULL) {
mutex_exit(&thr_local_mutex);
@@ -173,7 +173,7 @@ thr_local_create(void)
mutex_enter(&thr_local_mutex);
HASH_INSERT(thr_local_t, hash, thr_local_hash,
- os_thread_conv_id_to_ulint(os_thread_get_curr_id()),
+ os_thread_pf(os_thread_get_curr_id()),
local);
mutex_exit(&thr_local_mutex);
@@ -193,8 +193,8 @@ thr_local_free(
/* Look for the local struct in the hash table */
- HASH_SEARCH(hash, thr_local_hash, os_thread_conv_id_to_ulint(id),
- local, local->id == id);
+ HASH_SEARCH(hash, thr_local_hash, os_thread_pf(id),
+ local, os_thread_eq(local->id, id));
if (local == NULL) {
mutex_exit(&thr_local_mutex);
@@ -202,7 +202,7 @@ thr_local_free(
}
HASH_DELETE(thr_local_t, hash, thr_local_hash,
- os_thread_conv_id_to_ulint(id), local);
+ os_thread_pf(id), local);
mutex_exit(&thr_local_mutex);
diff --git a/innobase/trx/trx0sys.c b/innobase/trx/trx0sys.c
index 675cdf1b7e4..33c962772e8 100644
--- a/innobase/trx/trx0sys.c
+++ b/innobase/trx/trx0sys.c
@@ -494,6 +494,34 @@ trx_sys_update_mysql_binlog_offset(
}
/*********************************************************************
+Prints to stdout the MySQL binlog info in the system header if the
+magic number shows it valid. */
+
+void
+trx_sys_print_mysql_binlog_offset_from_page(
+/*========================================*/
+ byte* page) /* in: buffer containing the trx system header page,
+ i.e., page number TRX_SYS_PAGE_NO in the tablespace */
+{
+ trx_sysf_t* sys_header;
+
+ sys_header = page + TRX_SYS;
+
+ if (mach_read_from_4(sys_header + TRX_SYS_MYSQL_LOG_INFO
+ + TRX_SYS_MYSQL_LOG_MAGIC_N_FLD)
+ == TRX_SYS_MYSQL_LOG_MAGIC_N) {
+
+ printf(
+ "ibbackup: Last MySQL binlog file position %lu %lu, file name %s\n",
+ mach_read_from_4(sys_header + TRX_SYS_MYSQL_LOG_INFO
+ + TRX_SYS_MYSQL_LOG_OFFSET_HIGH),
+ mach_read_from_4(sys_header + TRX_SYS_MYSQL_LOG_INFO
+ + TRX_SYS_MYSQL_LOG_OFFSET_LOW),
+ sys_header + TRX_SYS_MYSQL_LOG_INFO + TRX_SYS_MYSQL_LOG_NAME);
+ }
+}
+
+/*********************************************************************
Prints to stderr the MySQL binlog offset info in the trx system header if
the magic number shows it valid. */
diff --git a/innobase/trx/trx0trx.c b/innobase/trx/trx0trx.c
index 8d84967a49d..ef17588a2bb 100644
--- a/innobase/trx/trx0trx.c
+++ b/innobase/trx/trx0trx.c
@@ -72,6 +72,7 @@ trx_create(
trx->type = TRX_USER;
trx->conc_state = TRX_NOT_STARTED;
+ trx->start_time = time(NULL);
trx->check_foreigns = TRUE;
trx->check_unique_secondary = TRUE;
@@ -516,6 +517,7 @@ trx_start_low(
if (trx->type == TRX_PURGE) {
trx->id = ut_dulint_zero;
trx->conc_state = TRX_ACTIVE;
+ trx->start_time = time(NULL);
return(TRUE);
}
@@ -539,6 +541,7 @@ trx_start_low(
trx->rseg = rseg;
trx->conc_state = TRX_ACTIVE;
+ trx->start_time = time(NULL);
UT_LIST_ADD_FIRST(trx_list, trx_sys->trx_list, trx);
@@ -1465,45 +1468,57 @@ trx_print(
500 bytes */
trx_t* trx) /* in: transaction */
{
- buf += sprintf(buf, "TRANSACTION %lu %lu, OS thread id %lu",
+ char* start_of_line;
+
+ buf += sprintf(buf, "TRANSACTION %lu %lu",
ut_dulint_get_high(trx->id),
- ut_dulint_get_low(trx->id),
- (ulint)trx->mysql_thread_id);
+ ut_dulint_get_low(trx->id));
- if (ut_strlen(trx->op_info) > 0) {
- buf += sprintf(buf, " %s", trx->op_info);
- }
-
- if (trx->type != TRX_USER) {
- buf += sprintf(buf, " purge trx");
- }
-
switch (trx->conc_state) {
case TRX_NOT_STARTED: buf += sprintf(buf,
", not started"); break;
case TRX_ACTIVE: buf += sprintf(buf,
- ", active"); break;
+ ", ACTIVE %lu sec",
+ (ulint)difftime(time(NULL), trx->start_time)); break;
case TRX_COMMITTED_IN_MEMORY: buf += sprintf(buf,
- ", committed in memory");
+ ", COMMITTED IN MEMORY");
break;
default: buf += sprintf(buf, " state %lu", trx->conc_state);
}
+ buf += sprintf(buf, ", OS thread id %lu",
+ os_thread_pf(trx->mysql_thread_id));
+
+ if (ut_strlen(trx->op_info) > 0) {
+ buf += sprintf(buf, " %s", trx->op_info);
+ }
+
+ if (trx->type != TRX_USER) {
+ buf += sprintf(buf, " purge trx");
+ }
+
+ buf += sprintf(buf, "\n");
+
+ start_of_line = buf;
+
switch (trx->que_state) {
- case TRX_QUE_RUNNING: buf += sprintf(buf,
- ", runs or sleeps"); break;
+ case TRX_QUE_RUNNING: break;
case TRX_QUE_LOCK_WAIT: buf += sprintf(buf,
- ", lock wait"); break;
+ "LOCK WAIT "); break;
case TRX_QUE_ROLLING_BACK: buf += sprintf(buf,
- ", rolling back"); break;
+ "ROLLING BACK "); break;
case TRX_QUE_COMMITTING: buf += sprintf(buf,
- ", committing"); break;
- default: buf += sprintf(buf, " que state %lu", trx->que_state);
+ "COMMITTING "); break;
+ default: buf += sprintf(buf, "que state %lu", trx->que_state);
}
- if (0 < UT_LIST_GET_LEN(trx->trx_locks)) {
- buf += sprintf(buf, ", has %lu lock struct(s)",
- UT_LIST_GET_LEN(trx->trx_locks));
+ if (0 < UT_LIST_GET_LEN(trx->trx_locks) ||
+ mem_heap_get_size(trx->lock_heap) > 400) {
+
+ buf += sprintf(buf,
+"%lu lock struct(s), heap size %lu",
+ UT_LIST_GET_LEN(trx->trx_locks),
+ mem_heap_get_size(trx->lock_heap));
}
if (trx->has_search_latch) {
@@ -1515,7 +1530,10 @@ trx_print(
ut_dulint_get_low(trx->undo_no));
}
- buf += sprintf(buf, "\n");
+ if (buf != start_of_line) {
+
+ buf += sprintf(buf, "\n");
+ }
if (trx->mysql_thd != NULL) {
innobase_mysql_print_thd(buf, trx->mysql_thd);