summaryrefslogtreecommitdiff
path: root/innobase/include
diff options
context:
space:
mode:
authorunknown <heikki@donna.mysql.fi>2001-10-10 22:47:08 +0300
committerunknown <heikki@donna.mysql.fi>2001-10-10 22:47:08 +0300
commit1904897be71cba7e6f2cf1192ba0cc2e8d907e00 (patch)
treefc361924d14a3d1727a8b88f61352ed039054720 /innobase/include
parent151ffe886b4b21499471658fdf01ea8347287092 (diff)
downloadmariadb-git-1904897be71cba7e6f2cf1192ba0cc2e8d907e00.tar.gz
ut0mem.c Merge changes in InnoDB-3.23.43b
ut0ut.c Merge changes in InnoDB-3.23.43b trx0purge.c Merge changes in InnoDB-3.23.43b trx0rec.c Merge changes in InnoDB-3.23.43b trx0trx.c Merge changes in InnoDB-3.23.43b trx0undo.c Merge changes in InnoDB-3.23.43b thr0loc.c Merge changes in InnoDB-3.23.43b sync0arr.c Merge changes in InnoDB-3.23.43b sync0rw.c Merge changes in InnoDB-3.23.43b sync0sync.c Merge changes in InnoDB-3.23.43b srv0srv.c Merge changes in InnoDB-3.23.43b srv0start.c Merge changes in InnoDB-3.23.43b row0ins.c Merge changes in InnoDB-3.23.43b row0mysql.c Merge changes in InnoDB-3.23.43b row0purge.c Merge changes in InnoDB-3.23.43b row0sel.c Merge changes in InnoDB-3.23.43b row0umod.c Merge changes in InnoDB-3.23.43b row0upd.c Merge changes in InnoDB-3.23.43b row0vers.c Merge changes in InnoDB-3.23.43b rem0cmp.c Merge changes in InnoDB-3.23.43b que0que.c Merge changes in InnoDB-3.23.43b pars0opt.c Merge changes in InnoDB-3.23.43b pars0pars.c Merge changes in InnoDB-3.23.43b lexyy.c Merge changes in InnoDB-3.23.43b pars0grm.c Merge changes in InnoDB-3.23.43b page0page.c Merge changes in InnoDB-3.23.43b os0file.c Merge changes in InnoDB-3.23.43b mtr0log.c Merge changes in InnoDB-3.23.43b mem0pool.c Merge changes in InnoDB-3.23.43b log0log.c Merge changes in InnoDB-3.23.43b log0recv.c Merge changes in InnoDB-3.23.43b lock0lock.c Merge changes in InnoDB-3.23.43b ibuf0ibuf.c Merge changes in InnoDB-3.23.43b fil0fil.c Merge changes in InnoDB-3.23.43b dict0crea.c Merge changes in InnoDB-3.23.43b dict0dict.c Merge changes in InnoDB-3.23.43b dict0load.c Merge changes in InnoDB-3.23.43b dict0mem.c Merge changes in InnoDB-3.23.43b data0data.c Merge changes in InnoDB-3.23.43b data0type.c Merge changes in InnoDB-3.23.43b buf0buf.c Merge changes in InnoDB-3.23.43b buf0lru.c Merge changes in InnoDB-3.23.43b btr0btr.c Merge changes in InnoDB-3.23.43b btr0cur.c Merge changes in InnoDB-3.23.43b btr0pcur.c Merge changes in InnoDB-3.23.43b btr0sea.c Merge changes in InnoDB-3.23.43b data0type.ic Merge changes in InnoDB-3.23.43b dict0dict.ic Merge changes in InnoDB-3.23.43b mtr0mtr.ic Merge changes in InnoDB-3.23.43b row0upd.ic Merge changes in InnoDB-3.23.43b sync0ipm.ic Merge changes in InnoDB-3.23.43b sync0rw.ic Merge changes in InnoDB-3.23.43b sync0sync.ic Merge changes in InnoDB-3.23.43b trx0rseg.ic Merge changes in InnoDB-3.23.43b btr0pcur.ic Merge changes in InnoDB-3.23.43b buf0buf.ic Merge changes in InnoDB-3.23.43b data0data.ic Merge changes in InnoDB-3.23.43b row0upd.h Merge changes in InnoDB-3.23.43b srv0srv.h Merge changes in InnoDB-3.23.43b sync0arr.h Merge changes in InnoDB-3.23.43b sync0rw.h Merge changes in InnoDB-3.23.43b sync0sync.h Merge changes in InnoDB-3.23.43b trx0trx.h Merge changes in InnoDB-3.23.43b ut0mem.h Merge changes in InnoDB-3.23.43b data0data.h Merge changes in InnoDB-3.23.43b data0type.h Merge changes in InnoDB-3.23.43b db0err.h Merge changes in InnoDB-3.23.43b dict0crea.h Merge changes in InnoDB-3.23.43b dict0dict.h Merge changes in InnoDB-3.23.43b dict0load.h Merge changes in InnoDB-3.23.43b dict0mem.h Merge changes in InnoDB-3.23.43b dict0types.h Merge changes in InnoDB-3.23.43b fil0fil.h Merge changes in InnoDB-3.23.43b ibuf0ibuf.h Merge changes in InnoDB-3.23.43b lock0lock.h Merge changes in InnoDB-3.23.43b log0log.h Merge changes in InnoDB-3.23.43b mtr0mtr.h Merge changes in InnoDB-3.23.43b rem0cmp.h Merge changes in InnoDB-3.23.43b row0ins.h Merge changes in InnoDB-3.23.43b row0mysql.h Merge changes in InnoDB-3.23.43b btr0cur.h Merge changes in InnoDB-3.23.43b btr0pcur.h Merge changes in InnoDB-3.23.43b btr0sea.h Merge changes in InnoDB-3.23.43b buf0buf.h Merge changes in InnoDB-3.23.43b sql_table.cc Merge changes in InnoDB-3.23.43b sql_db.cc Merge changes in InnoDB-3.23.43b ha_innobase.cc Merge changes in InnoDB-3.23.43b handler.cc Merge changes in InnoDB-3.23.43b ha_innobase.h Merge changes in InnoDB-3.23.43b handler.h Merge changes in InnoDB-3.23.43b sql/ha_innobase.h: Merge changes in InnoDB-3.23.43b sql/handler.h: Merge changes in InnoDB-3.23.43b sql/ha_innobase.cc: Merge changes in InnoDB-3.23.43b sql/handler.cc: Merge changes in InnoDB-3.23.43b sql/sql_db.cc: Merge changes in InnoDB-3.23.43b sql/sql_table.cc: Merge changes in InnoDB-3.23.43b innobase/include/btr0cur.h: Merge changes in InnoDB-3.23.43b innobase/include/btr0pcur.h: Merge changes in InnoDB-3.23.43b innobase/include/btr0sea.h: Merge changes in InnoDB-3.23.43b innobase/include/buf0buf.h: Merge changes in InnoDB-3.23.43b innobase/include/data0data.h: Merge changes in InnoDB-3.23.43b innobase/include/data0type.h: Merge changes in InnoDB-3.23.43b innobase/include/db0err.h: Merge changes in InnoDB-3.23.43b innobase/include/dict0crea.h: Merge changes in InnoDB-3.23.43b innobase/include/dict0dict.h: Merge changes in InnoDB-3.23.43b innobase/include/dict0load.h: Merge changes in InnoDB-3.23.43b innobase/include/dict0mem.h: Merge changes in InnoDB-3.23.43b innobase/include/dict0types.h: Merge changes in InnoDB-3.23.43b innobase/include/fil0fil.h: Merge changes in InnoDB-3.23.43b innobase/include/ibuf0ibuf.h: Merge changes in InnoDB-3.23.43b innobase/include/lock0lock.h: Merge changes in InnoDB-3.23.43b innobase/include/log0log.h: Merge changes in InnoDB-3.23.43b innobase/include/mtr0mtr.h: Merge changes in InnoDB-3.23.43b innobase/include/rem0cmp.h: Merge changes in InnoDB-3.23.43b innobase/include/row0ins.h: Merge changes in InnoDB-3.23.43b innobase/include/row0mysql.h: Merge changes in InnoDB-3.23.43b innobase/include/row0upd.h: Merge changes in InnoDB-3.23.43b innobase/include/srv0srv.h: Merge changes in InnoDB-3.23.43b innobase/include/sync0arr.h: Merge changes in InnoDB-3.23.43b innobase/include/sync0rw.h: Merge changes in InnoDB-3.23.43b innobase/include/sync0sync.h: Merge changes in InnoDB-3.23.43b innobase/include/trx0trx.h: Merge changes in InnoDB-3.23.43b innobase/include/ut0mem.h: Merge changes in InnoDB-3.23.43b innobase/include/btr0pcur.ic: Merge changes in InnoDB-3.23.43b innobase/include/buf0buf.ic: Merge changes in InnoDB-3.23.43b innobase/include/data0data.ic: Merge changes in InnoDB-3.23.43b innobase/include/data0type.ic: Merge changes in InnoDB-3.23.43b innobase/include/dict0dict.ic: Merge changes in InnoDB-3.23.43b innobase/include/mtr0mtr.ic: Merge changes in InnoDB-3.23.43b innobase/include/row0upd.ic: Merge changes in InnoDB-3.23.43b innobase/include/sync0ipm.ic: Merge changes in InnoDB-3.23.43b innobase/include/sync0rw.ic: Merge changes in InnoDB-3.23.43b innobase/include/sync0sync.ic: Merge changes in InnoDB-3.23.43b innobase/include/trx0rseg.ic: Merge changes in InnoDB-3.23.43b innobase/btr/btr0btr.c: Merge changes in InnoDB-3.23.43b innobase/btr/btr0cur.c: Merge changes in InnoDB-3.23.43b innobase/btr/btr0pcur.c: Merge changes in InnoDB-3.23.43b innobase/btr/btr0sea.c: Merge changes in InnoDB-3.23.43b innobase/buf/buf0buf.c: Merge changes in InnoDB-3.23.43b innobase/buf/buf0lru.c: Merge changes in InnoDB-3.23.43b innobase/data/data0data.c: Merge changes in InnoDB-3.23.43b innobase/data/data0type.c: Merge changes in InnoDB-3.23.43b innobase/dict/dict0crea.c: Merge changes in InnoDB-3.23.43b innobase/dict/dict0dict.c: Merge changes in InnoDB-3.23.43b innobase/dict/dict0load.c: Merge changes in InnoDB-3.23.43b innobase/dict/dict0mem.c: Merge changes in InnoDB-3.23.43b innobase/fil/fil0fil.c: Merge changes in InnoDB-3.23.43b innobase/ibuf/ibuf0ibuf.c: Merge changes in InnoDB-3.23.43b innobase/lock/lock0lock.c: Merge changes in InnoDB-3.23.43b innobase/log/log0log.c: Merge changes in InnoDB-3.23.43b innobase/log/log0recv.c: Merge changes in InnoDB-3.23.43b innobase/mem/mem0pool.c: Merge changes in InnoDB-3.23.43b innobase/mtr/mtr0log.c: Merge changes in InnoDB-3.23.43b innobase/os/os0file.c: Merge changes in InnoDB-3.23.43b innobase/page/page0page.c: Merge changes in InnoDB-3.23.43b innobase/pars/lexyy.c: Merge changes in InnoDB-3.23.43b innobase/pars/pars0grm.c: Merge changes in InnoDB-3.23.43b innobase/pars/pars0opt.c: Merge changes in InnoDB-3.23.43b innobase/pars/pars0pars.c: Merge changes in InnoDB-3.23.43b innobase/que/que0que.c: Merge changes in InnoDB-3.23.43b innobase/rem/rem0cmp.c: Merge changes in InnoDB-3.23.43b innobase/row/row0ins.c: Merge changes in InnoDB-3.23.43b innobase/row/row0mysql.c: Merge changes in InnoDB-3.23.43b innobase/row/row0purge.c: Merge changes in InnoDB-3.23.43b innobase/row/row0sel.c: Merge changes in InnoDB-3.23.43b innobase/row/row0umod.c: Merge changes in InnoDB-3.23.43b innobase/row/row0upd.c: Merge changes in InnoDB-3.23.43b innobase/row/row0vers.c: Merge changes in InnoDB-3.23.43b innobase/srv/srv0srv.c: Merge changes in InnoDB-3.23.43b innobase/srv/srv0start.c: Merge changes in InnoDB-3.23.43b innobase/sync/sync0arr.c: Merge changes in InnoDB-3.23.43b innobase/sync/sync0rw.c: Merge changes in InnoDB-3.23.43b innobase/sync/sync0sync.c: Merge changes in InnoDB-3.23.43b innobase/thr/thr0loc.c: Merge changes in InnoDB-3.23.43b innobase/trx/trx0purge.c: Merge changes in InnoDB-3.23.43b innobase/trx/trx0rec.c: Merge changes in InnoDB-3.23.43b innobase/trx/trx0trx.c: Merge changes in InnoDB-3.23.43b innobase/trx/trx0undo.c: Merge changes in InnoDB-3.23.43b innobase/ut/ut0mem.c: Merge changes in InnoDB-3.23.43b innobase/ut/ut0ut.c: Merge changes in InnoDB-3.23.43b BitKeeper/etc/logging_ok: Logging to logging@openlogging.org accepted
Diffstat (limited to 'innobase/include')
-rw-r--r--innobase/include/btr0cur.h23
-rw-r--r--innobase/include/btr0pcur.h64
-rw-r--r--innobase/include/btr0pcur.ic4
-rw-r--r--innobase/include/btr0sea.h6
-rw-r--r--innobase/include/buf0buf.h50
-rw-r--r--innobase/include/buf0buf.ic8
-rw-r--r--innobase/include/data0data.h26
-rw-r--r--innobase/include/data0data.ic70
-rw-r--r--innobase/include/data0type.h11
-rw-r--r--innobase/include/data0type.ic21
-rw-r--r--innobase/include/db0err.h13
-rw-r--r--innobase/include/dict0crea.h18
-rw-r--r--innobase/include/dict0dict.h77
-rw-r--r--innobase/include/dict0dict.ic28
-rw-r--r--innobase/include/dict0load.h32
-rw-r--r--innobase/include/dict0mem.h70
-rw-r--r--innobase/include/dict0types.h1
-rw-r--r--innobase/include/fil0fil.h3
-rw-r--r--innobase/include/ibuf0ibuf.h15
-rw-r--r--innobase/include/lock0lock.h32
-rw-r--r--innobase/include/log0log.h5
-rw-r--r--innobase/include/mtr0mtr.h12
-rw-r--r--innobase/include/mtr0mtr.ic16
-rw-r--r--innobase/include/rem0cmp.h26
-rw-r--r--innobase/include/row0ins.h22
-rw-r--r--innobase/include/row0mysql.h49
-rw-r--r--innobase/include/row0upd.h45
-rw-r--r--innobase/include/row0upd.ic17
-rw-r--r--innobase/include/srv0srv.h51
-rw-r--r--innobase/include/sync0arr.h24
-rw-r--r--innobase/include/sync0ipm.ic4
-rw-r--r--innobase/include/sync0rw.h98
-rw-r--r--innobase/include/sync0rw.ic93
-rw-r--r--innobase/include/sync0sync.h36
-rw-r--r--innobase/include/sync0sync.ic41
-rw-r--r--innobase/include/trx0rseg.ic12
-rw-r--r--innobase/include/trx0trx.h19
-rw-r--r--innobase/include/ut0mem.h3
38 files changed, 734 insertions, 411 deletions
diff --git a/innobase/include/btr0cur.h b/innobase/include/btr0cur.h
index f56a5662253..bce1f0685cc 100644
--- a/innobase/include/btr0cur.h
+++ b/innobase/include/btr0cur.h
@@ -188,6 +188,22 @@ btr_cur_pessimistic_insert(
que_thr_t* thr, /* in: query thread or NULL */
mtr_t* mtr); /* in: mtr */
/*****************************************************************
+Updates a secondary index record when the update causes no size
+changes in its fields. The only case when this function is currently
+called is that in a char field characters change to others which
+are identified in the collation order. */
+
+ulint
+btr_cur_update_sec_rec_in_place(
+/*============================*/
+ /* out: DB_SUCCESS or error number */
+ btr_cur_t* cursor, /* in: cursor on the record to update;
+ cursor stays valid and positioned on the
+ same record */
+ upd_t* update, /* in: update vector */
+ que_thr_t* thr, /* in: query thread */
+ mtr_t* mtr); /* in: mtr */
+/*****************************************************************
Updates a record when the update causes no size changes in its fields. */
ulint
@@ -411,12 +427,13 @@ btr_estimate_n_rows_in_range(
dtuple_t* tuple2, /* in: range end, may also be empty tuple */
ulint mode2); /* in: search mode for range end */
/***********************************************************************
-Estimates the number of different key values in a given index. */
+Estimates the number of different key values in a given index, for
+each n-column prefix of the index where n <= dict_index_get_n_unique(index).
+The estimates are stored in the array index->stat_n_diff_key_vals. */
-ulint
+void
btr_estimate_number_of_different_key_vals(
/*======================================*/
- /* out: estimated number of key values */
dict_index_t* index); /* in: index */
/***********************************************************************
Marks not updated extern fields as not-owned by this record. The ownership
diff --git a/innobase/include/btr0pcur.h b/innobase/include/btr0pcur.h
index 6465093e3c1..05b55e4491d 100644
--- a/innobase/include/btr0pcur.h
+++ b/innobase/include/btr0pcur.h
@@ -19,9 +19,15 @@ Created 2/23/1996 Heikki Tuuri
#include "btr0types.h"
/* Relative positions for a stored cursor position */
-#define BTR_PCUR_ON 1
-#define BTR_PCUR_BEFORE 2
-#define BTR_PCUR_AFTER 3
+#define BTR_PCUR_ON 1
+#define BTR_PCUR_BEFORE 2
+#define BTR_PCUR_AFTER 3
+/* Note that if the tree is not empty, btr_pcur_store_position does not
+use the following, but only uses the above three alternatives, where the
+position is stored relative to a specific record: this makes implementation
+of a scroll cursor easier */
+#define BTR_PCUR_BEFORE_FIRST_IN_TREE 4 /* in an empty tree */
+#define BTR_PCUR_AFTER_LAST_IN_TREE 5 /* in an empty tree */
/******************************************************************
Allocates memory for a persistent cursor object and initializes the cursor. */
@@ -170,34 +176,16 @@ btr_pcur_close(
/******************************************************************
The position of the cursor is stored by taking an initial segment of the
record the cursor is positioned on, before, or after, and copying it to the
-cursor data structure. NOTE that the page where the cursor is positioned
-must not be empty! */
+cursor data structure, or just setting a flag if the cursor id before the
+first in an EMPTY tree, or after the last in an EMPTY tree. NOTE that the
+page where the cursor is positioned must not be empty if the index tree is
+not totally empty! */
void
btr_pcur_store_position(
/*====================*/
- btr_pcur_t* cursor, /* in: persistent cursor */
- mtr_t* mtr); /* in: mtr */
-/******************************************************************
-If the latch mode of the cursor is BTR_LEAF_SEARCH or BTR_LEAF_MODIFY,
-releases the page latch and bufferfix reserved by the cursor.
-NOTE! In the case of BTR_LEAF_MODIFY, there should not exist changes
-made by the current mini-transaction to the data protected by the
-cursor latch, as then the latch must not be released until mtr_commit. */
-
-void
-btr_pcur_release_leaf(
-/*==================*/
btr_pcur_t* cursor, /* in: persistent cursor */
mtr_t* mtr); /* in: mtr */
-/*************************************************************
-Gets the rel_pos field for a cursor whose position has been stored. */
-UNIV_INLINE
-ulint
-btr_pcur_get_rel_pos(
-/*=================*/
- /* out: BTR_PCUR_ON, ... */
- btr_pcur_t* cursor);/* in: persistent cursor */
/******************************************************************
Restores the stored position of a persistent cursor bufferfixing the page and
obtaining the specified latches. If the cursor position was saved when the
@@ -207,7 +195,9 @@ to the last record LESS OR EQUAL to the stored record;
the last record LESS than the user record which was the successor of the page
infimum;
(3) cursor was positioned on the page supremum: restores to the first record
-GREATER than the user record which was the predecessor of the supremum. */
+GREATER than the user record which was the predecessor of the supremum.
+(4) cursor was positioned before the first or after the last in an empty tree:
+restores to before first or after the last in the tree. */
ibool
btr_pcur_restore_position(
@@ -220,6 +210,26 @@ btr_pcur_restore_position(
ulint latch_mode, /* in: BTR_SEARCH_LEAF, ... */
btr_pcur_t* cursor, /* in: detached persistent cursor */
mtr_t* mtr); /* in: mtr */
+/******************************************************************
+If the latch mode of the cursor is BTR_LEAF_SEARCH or BTR_LEAF_MODIFY,
+releases the page latch and bufferfix reserved by the cursor.
+NOTE! In the case of BTR_LEAF_MODIFY, there should not exist changes
+made by the current mini-transaction to the data protected by the
+cursor latch, as then the latch must not be released until mtr_commit. */
+
+void
+btr_pcur_release_leaf(
+/*==================*/
+ btr_pcur_t* cursor, /* in: persistent cursor */
+ mtr_t* mtr); /* in: mtr */
+/*************************************************************
+Gets the rel_pos field for a cursor whose position has been stored. */
+UNIV_INLINE
+ulint
+btr_pcur_get_rel_pos(
+/*=================*/
+ /* out: BTR_PCUR_ON, ... */
+ btr_pcur_t* cursor);/* in: persistent cursor */
/*************************************************************
Sets the mtr field for a pcur. */
UNIV_INLINE
@@ -458,7 +468,7 @@ struct btr_pcur_struct{
ulint search_mode; /* PAGE_CUR_G, ... */
/*-----------------------------*/
/* NOTE that the following fields may possess dynamically allocated
- memory, which should be freed if not needed anymore! */
+ memory which should be freed if not needed anymore! */
mtr_t* mtr; /* NULL, or this field may contain
a mini-transaction which holds the
diff --git a/innobase/include/btr0pcur.ic b/innobase/include/btr0pcur.ic
index 8e927689208..a60140e4aa9 100644
--- a/innobase/include/btr0pcur.ic
+++ b/innobase/include/btr0pcur.ic
@@ -19,8 +19,8 @@ btr_pcur_get_rel_pos(
ut_ad(cursor);
ut_ad(cursor->old_rec);
ut_ad(cursor->old_stored == BTR_PCUR_OLD_STORED);
- ut_ad((cursor->pos_state == BTR_PCUR_WAS_POSITIONED)
- || (cursor->pos_state == BTR_PCUR_IS_POSITIONED));
+ ut_ad(cursor->pos_state == BTR_PCUR_WAS_POSITIONED
+ || cursor->pos_state == BTR_PCUR_IS_POSITIONED);
return(cursor->rel_pos);
}
diff --git a/innobase/include/btr0sea.h b/innobase/include/btr0sea.h
index c319e16d740..fdf5cf375a3 100644
--- a/innobase/include/btr0sea.h
+++ b/innobase/include/btr0sea.h
@@ -262,6 +262,12 @@ index */
#define BTR_SEARCH_ON_HASH_LIMIT 3
+/* We do this many searches before trying to keep the search latch over calls
+from MySQL. If we notice someone waiting for the latch, we again set this
+much timeout. This is to reduce contention. */
+
+#define BTR_SEA_TIMEOUT 10000
+
#ifndef UNIV_NONINL
#include "btr0sea.ic"
#endif
diff --git a/innobase/include/buf0buf.h b/innobase/include/buf0buf.h
index 66071030402..5ddbf39335a 100644
--- a/innobase/include/buf0buf.h
+++ b/innobase/include/buf0buf.h
@@ -116,53 +116,30 @@ buf_frame_copy(
NOTE! The following macros should be used instead of buf_page_get_gen,
to improve debugging. Only values RW_S_LATCH and RW_X_LATCH are allowed
in LA! */
-#ifdef UNIV_SYNC_DEBUG
#define buf_page_get(SP, OF, LA, MTR) buf_page_get_gen(\
SP, OF, LA, NULL,\
BUF_GET, IB__FILE__, __LINE__, MTR)
-#else
-#define buf_page_get(SP, OF, LA, MTR) buf_page_get_gen(\
- SP, OF, LA, NULL,\
- BUF_GET, MTR)
-#endif
/******************************************************************
Use these macros to bufferfix a page with no latching. Remember not to
read the contents of the page unless you know it is safe. Do not modify
the contents of the page! We have separated this case, because it is
error-prone programming not to set a latch, and it should be used
with care. */
-#ifdef UNIV_SYNC_DEBUG
#define buf_page_get_with_no_latch(SP, OF, MTR) buf_page_get_gen(\
SP, OF, RW_NO_LATCH, NULL,\
BUF_GET_NO_LATCH, IB__FILE__, __LINE__, MTR)
-#else
-#define buf_page_get_with_no_latch(SP, OF, MTR) buf_page_get_gen(\
- SP, OF, RW_NO_LATCH, NULL,\
- BUF_GET_NO_LATCH, MTR)
-#endif
/******************************************************************
NOTE! The following macros should be used instead of buf_page_get_gen, to
improve debugging. Only values RW_S_LATCH and RW_X_LATCH are allowed as LA! */
-#ifdef UNIV_SYNC_DEBUG
#define buf_page_get_nowait(SP, OF, LA, MTR) buf_page_get_gen(\
SP, OF, LA, NULL,\
BUF_GET_NOWAIT, IB__FILE__, __LINE__, MTR)
-#else
-#define buf_page_get_nowait(SP, OF, LA, MTR) buf_page_get_gen(\
- SP, OF, LA, NULL,\
- BUF_GET_NOWAIT, MTR)
-#endif
/******************************************************************
NOTE! The following macros should be used instead of
buf_page_optimistic_get_func, to improve debugging. Only values RW_S_LATCH and
RW_X_LATCH are allowed as LA! */
-#ifdef UNIV_SYNC_DEBUG
#define buf_page_optimistic_get(LA, G, MC, MTR) buf_page_optimistic_get_func(\
LA, G, MC, IB__FILE__, __LINE__, MTR)
-#else
-#define buf_page_optimistic_get(LA, G, MC, MTR) buf_page_optimistic_get_func(\
- LA, G, MC, MTR)
-#endif
/************************************************************************
This is the general function used to get optimistic access to a database
page. */
@@ -175,10 +152,8 @@ buf_page_optimistic_get_func(
buf_frame_t* guess, /* in: guessed frame */
dulint modify_clock,/* in: modify clock value if mode is
..._GUESS_ON_CLOCK */
-#ifdef UNIV_SYNC_DEBUG
char* file, /* in: file name */
ulint line, /* in: line where called */
-#endif
mtr_t* mtr); /* in: mini-transaction */
/************************************************************************
Tries to get the page, but if file io is required, releases all latches
@@ -210,10 +185,8 @@ buf_page_get_known_nowait(
ulint rw_latch,/* in: RW_S_LATCH, RW_X_LATCH */
buf_frame_t* guess, /* in: the known page frame */
ulint mode, /* in: BUF_MAKE_YOUNG or BUF_KEEP_OLD */
-#ifdef UNIV_SYNC_DEBUG
char* file, /* in: file name */
ulint line, /* in: line where called */
-#endif
mtr_t* mtr); /* in: mini-transaction */
/************************************************************************
This is the general function used to get access to a database page. */
@@ -228,10 +201,8 @@ buf_page_get_gen(
buf_frame_t* guess, /* in: guessed frame or NULL */
ulint mode, /* in: BUF_GET, BUF_GET_IF_IN_POOL,
BUF_GET_NO_LATCH */
-#ifdef UNIV_SYNC_DEBUG
char* file, /* in: file name */
ulint line, /* in: line where called */
-#endif
mtr_t* mtr); /* in: mini-transaction */
/************************************************************************
Initializes a page to the buffer buf_pool. The page is usually not read
@@ -455,6 +426,13 @@ Validates the buffer pool data structure. */
ibool
buf_validate(void);
/*==============*/
+/************************************************************************
+Prints a page to stderr. */
+
+void
+buf_page_print(
+/*===========*/
+ byte* read_buf); /* in: a database page */
/*************************************************************************
Prints info of the buffer pool data structure. */
@@ -462,6 +440,12 @@ void
buf_print(void);
/*===========*/
/*************************************************************************
+Returns the number of pending buf pool ios. */
+
+ulint
+buf_get_n_pending_ios(void);
+/*=======================*/
+/*************************************************************************
Prints info of the buffer i/o. */
void
@@ -760,6 +744,8 @@ struct buf_pool_struct{
byte* frame_zero; /* pointer to the first buffer frame:
this may differ from frame_mem, because
this is aligned by the frame size */
+ byte* high_end; /* pointer to the end of the
+ buffer pool */
buf_block_t* blocks; /* array of buffer control blocks */
ulint max_size; /* number of control blocks ==
maximum pool size in pages */
@@ -767,6 +753,9 @@ struct buf_pool_struct{
hash_table_t* page_hash; /* hash table of the file pages */
ulint n_pend_reads; /* number of pending read operations */
+
+ time_t last_printout_time; /* when buf_print was last time
+ called */
ulint n_pages_read; /* number read operations */
ulint n_pages_written;/* number write operations */
ulint n_pages_created;/* number of pages created in the pool
@@ -782,6 +771,9 @@ struct buf_pool_struct{
hit rate */
ulint n_pages_read_old;/* n_pages_read when buf_print was
last time called */
+ ulint n_pages_written_old;/* number write operations */
+ ulint n_pages_created_old;/* number of pages created in
+ the pool with no read */
/* 2. Page flushing algorithm fields */
UT_LIST_BASE_NODE_T(buf_block_t) flush_list;
diff --git a/innobase/include/buf0buf.ic b/innobase/include/buf0buf.ic
index 1ecc6f34a78..3d88d087e63 100644
--- a/innobase/include/buf0buf.ic
+++ b/innobase/include/buf0buf.ic
@@ -486,11 +486,7 @@ buf_block_buf_fix_inc_debug(
{
ibool ret;
- ret = rw_lock_s_lock_func_nowait(&(block->debug_latch)
-#ifdef UNIV_SYNC_DEBUG
- ,file, line
-#endif
- );
+ ret = rw_lock_s_lock_func_nowait(&(block->debug_latch), file, line);
ut_ad(ret == TRUE);
@@ -557,9 +553,7 @@ buf_page_get_release_on_io(
frame = buf_page_get_gen(space, offset, rw_latch, guess,
BUF_GET_IF_IN_POOL,
-#ifdef UNIV_SYNC_DEBUG
IB__FILE__, __LINE__,
-#endif
mtr);
if (frame != NULL) {
diff --git a/innobase/include/data0data.h b/innobase/include/data0data.h
index c314281d758..c19d7ea5552 100644
--- a/innobase/include/data0data.h
+++ b/innobase/include/data0data.h
@@ -116,8 +116,8 @@ dfield_copy(
Tests if data length and content is equal for two dfields. */
UNIV_INLINE
ibool
-dfield_datas_are_equal(
-/*===================*/
+dfield_datas_are_binary_equal(
+/*==========================*/
/* out: TRUE if equal */
dfield_t* field1, /* in: field */
dfield_t* field2);/* in: field */
@@ -125,8 +125,8 @@ dfield_datas_are_equal(
Tests if dfield data length and content is equal to the given. */
UNIV_INLINE
ibool
-dfield_data_is_equal(
-/*=================*/
+dfield_data_is_binary_equal(
+/*========================*/
/* out: TRUE if equal */
dfield_t* field, /* in: field */
ulint len, /* in: data length or UNIV_SQL_NULL */
@@ -230,14 +230,18 @@ dtuple_get_data_size(
dtuple_t* tuple); /* in: typed data tuple */
/****************************************************************
Returns TRUE if lengths of two dtuples are equal and respective data fields
-in them are equal. */
-UNIV_INLINE
+in them are equal when compared with collation in char fields (not as binary
+strings). */
+
ibool
-dtuple_datas_are_equal(
-/*===================*/
- /* out: TRUE if length and datas are equal */
+dtuple_datas_are_ordering_equal(
+/*============================*/
+ /* out: TRUE if length and fieds are equal
+ when compared with cmp_data_data:
+ NOTE: in character type fields some letters
+ are identified with others! (collation) */
dtuple_t* tuple1, /* in: tuple 1 */
- dtuple_t* tuple2); /* in: tuple 2 */
+ dtuple_t* tuple2);/* in: tuple 2 */
/****************************************************************
Folds a prefix given as the number of fields of a tuple. */
UNIV_INLINE
@@ -447,7 +451,7 @@ struct dfield_struct{
struct dtuple_struct {
ulint info_bits; /* info bits of an index record:
- default is 0; this field is used
+ the default is 0; this field is used
if an index record is built from
a data tuple */
ulint n_fields; /* number of fields in dtuple */
diff --git a/innobase/include/data0data.ic b/innobase/include/data0data.ic
index b886ad6c69c..0750a3894d1 100644
--- a/innobase/include/data0data.ic
+++ b/innobase/include/data0data.ic
@@ -133,8 +133,8 @@ dfield_copy(
Tests if data length and content is equal for two dfields. */
UNIV_INLINE
ibool
-dfield_datas_are_equal(
-/*===================*/
+dfield_datas_are_binary_equal(
+/*==========================*/
/* out: TRUE if equal */
dfield_t* field1, /* in: field */
dfield_t* field2) /* in: field */
@@ -157,8 +157,8 @@ dfield_datas_are_equal(
Tests if dfield data length and content is equal to the given. */
UNIV_INLINE
ibool
-dfield_data_is_equal(
-/*=================*/
+dfield_data_is_binary_equal(
+/*========================*/
/* out: TRUE if equal */
dfield_t* field, /* in: field */
ulint len, /* in: data length or UNIV_SQL_NULL */
@@ -169,8 +169,7 @@ dfield_data_is_equal(
return(FALSE);
}
- if ((len != UNIV_SQL_NULL)
- && (0 != ut_memcmp(field->data, data, len))) {
+ if (len != UNIV_SQL_NULL && 0 != ut_memcmp(field->data, data, len)) {
return(FALSE);
}
@@ -342,65 +341,6 @@ dtuple_get_data_size(
return(sum);
}
-/****************************************************************
-Returns TRUE if lengths of two dtuples are equal and respective data fields
-in them are equal. */
-UNIV_INLINE
-ibool
-dtuple_datas_are_equal(
-/*===================*/
- /* out: TRUE if length and datas are equal */
- dtuple_t* tuple1, /* in: tuple 1 */
- dtuple_t* tuple2) /* in: tuple 2 */
-{
- dfield_t* field1;
- dfield_t* field2;
- ulint n_fields;
- byte* data1;
- byte* data2;
- ulint len1;
- ulint len2;
- ulint i;
-
- ut_ad(tuple1 && tuple2);
- ut_ad(tuple1->magic_n = DATA_TUPLE_MAGIC_N);
- ut_ad(tuple2->magic_n = DATA_TUPLE_MAGIC_N);
- ut_ad(dtuple_check_typed(tuple1));
- ut_ad(dtuple_check_typed(tuple2));
-
- n_fields = dtuple_get_n_fields(tuple1);
-
- if (n_fields != dtuple_get_n_fields(tuple2)) {
-
- return(FALSE);
- }
-
- for (i = 0; i < n_fields; i++) {
-
- field1 = dtuple_get_nth_field(tuple1, i);
- data1 = (byte*) dfield_get_data(field1);
- len1 = dfield_get_len(field1);
-
- field2 = dtuple_get_nth_field(tuple2, i);
- data2 = (byte*) dfield_get_data(field2);
- len2 = dfield_get_len(field2);
-
- if (len1 != len2) {
-
- return(FALSE);
- }
-
- if (len1 != UNIV_SQL_NULL) {
- if (ut_memcmp(data1, data2, len1) != 0) {
-
- return(FALSE);
- }
- }
- }
-
- return(TRUE);
-}
-
/***********************************************************************
Sets types of fields binary in a tuple. */
UNIV_INLINE
diff --git a/innobase/include/data0type.h b/innobase/include/data0type.h
index 4817f0ca839..b53a70a8909 100644
--- a/innobase/include/data0type.h
+++ b/innobase/include/data0type.h
@@ -124,17 +124,6 @@ dtype_get_pad_char(
/* out: padding character code, or
ULINT_UNDEFINED if no padding specified */
dtype_t* type); /* in: typeumn */
-/*************************************************************************
-Transforms the character code so that it is ordered appropriately
-for the language. */
-UNIV_INLINE
-ulint
-dtype_collate(
-/*==========*/
- /* out: padding character */
- dtype_t* type, /* in: type */
- ulint code); /* in: character code stored in database
- record */
/***************************************************************************
Returns the size of a fixed size data type, 0 if not a fixed size type. */
UNIV_INLINE
diff --git a/innobase/include/data0type.ic b/innobase/include/data0type.ic
index f6bdaf69662..4a62902eb1b 100644
--- a/innobase/include/data0type.ic
+++ b/innobase/include/data0type.ic
@@ -120,23 +120,6 @@ dtype_get_pad_char(
return(ULINT_UNDEFINED);
}
-/*************************************************************************
-Transforms the character code so that it is ordered appropriately for the
-language. */
-UNIV_INLINE
-ulint
-dtype_collate(
-/*==========*/
- /* out: collation order position */
- dtype_t* type, /* in: type */
- ulint code) /* in: character code stored in database
- record */
-{
- ut_ad((type->mtype == DATA_CHAR) || (type->mtype == DATA_VARCHAR));
-
- return(toupper(code));
-}
-
/**************************************************************************
Stores to a type the information which determines its alphabetical
ordering. */
@@ -198,6 +181,10 @@ dtype_get_fixed_size(
case DATA_SYS: if (type->prtype == DATA_ROW_ID) {
return(DATA_ROW_ID_LEN);
+ } else if (type->prtype == DATA_TRX_ID) {
+ return(DATA_TRX_ID_LEN);
+ } else if (type->prtype == DATA_ROLL_PTR) {
+ return(DATA_ROLL_PTR_LEN);
} else {
return(0);
}
diff --git a/innobase/include/db0err.h b/innobase/include/db0err.h
index 34513545faa..ddfbd5b7862 100644
--- a/innobase/include/db0err.h
+++ b/innobase/include/db0err.h
@@ -27,12 +27,21 @@ Created 5/24/1996 Heikki Tuuri
#define DB_CLUSTER_NOT_FOUND 30
#define DB_TABLE_NOT_FOUND 31
#define DB_MUST_GET_MORE_FILE_SPACE 32 /* the database has to be stopped
- and restrated with more file space */
+ and restarted with more file space */
#define DB_TABLE_IS_BEING_USED 33
#define DB_TOO_BIG_RECORD 34 /* a record in an index would become
bigger than 1/2 free space in a page
frame */
-
+#define DB_LOCK_WAIT_TIMEOUT 35 /* lock wait lasted too long */
+#define DB_NO_REFERENCED_ROW 36 /* referenced key value not found
+ for a foreign key in an insert or
+ update of a row */
+#define DB_ROW_IS_REFERENCED 37 /* cannot delete or update a row
+ because it contains a key value
+ which is referenced */
+#define DB_CANNOT_ADD_CONSTRAINT 38 /* adding a foreign key constraint
+ to a table failed */
+
/* The following are partial failure codes */
#define DB_FAIL 1000
#define DB_OVERFLOW 1001
diff --git a/innobase/include/dict0crea.h b/innobase/include/dict0crea.h
index 6bc31e1e722..ccdedff42c8 100644
--- a/innobase/include/dict0crea.h
+++ b/innobase/include/dict0crea.h
@@ -71,6 +71,24 @@ dict_drop_index_tree(
rec_t* rec, /* in: record in the clustered index of SYS_INDEXES
table */
mtr_t* mtr); /* in: mtr having the latch on the record page */
+/********************************************************************
+Creates the foreign key constraints system tables inside InnoDB
+at database creation or database start if they are not found or are
+not of the right form. */
+
+ulint
+dict_create_or_check_foreign_constraint_tables(void);
+/*================================================*/
+ /* out: DB_SUCCESS or error code */
+/************************************************************************
+Adds foreign key definitions to data dictionary tables in the database. */
+
+ulint
+dict_create_add_foreigns_to_dictionary(
+/*===================================*/
+ /* out: error code or DB_SUCCESS */
+ dict_table_t* table, /* in: table */
+ trx_t* trx); /* in: transaction */
/* Table create node structure */
diff --git a/innobase/include/dict0dict.h b/innobase/include/dict0dict.h
index cec1430c9e9..56b55b8a417 100644
--- a/innobase/include/dict0dict.h
+++ b/innobase/include/dict0dict.h
@@ -138,6 +138,38 @@ dict_table_rename_in_cache(
dict_table_t* table, /* in: table */
char* new_name); /* in: new name */
/**************************************************************************
+Adds a foreign key constraint object to the dictionary cache. May free
+the object if there already is an object with the same identifier in.
+At least one of foreign table or referenced table must already be in
+the dictionary cache! */
+
+ulint
+dict_foreign_add_to_cache(
+/*======================*/
+ /* out: DB_SUCCESS or error code */
+ dict_foreign_t* foreign); /* in, own: foreign key constraint */
+/*************************************************************************
+Scans a table create SQL string and adds to the data dictionary
+the foreign key constraints declared in the string. This function
+should be called after the indexes for a table have been created.
+Each foreign key constraint must be accompanied with indexes in
+bot participating tables. The indexes are allowed to contain more
+fields than mentioned in the constraint. */
+
+ulint
+dict_create_foreign_constraints(
+/*============================*/
+ /* out: error code or DB_SUCCESS */
+ trx_t* trx, /* in: transaction */
+ char* sql_string, /* in: table create statement where
+ foreign keys are declared like:
+ FOREIGN KEY (a, b) REFERENCES table2(c, d),
+ table2 can be written also with the database
+ name before it: test.table2; the default
+ database id the database of parameter name */
+ char* name); /* in: table full name in the normalized form
+ database_name/table_name */
+/**************************************************************************
Returns a table object and memoryfixes it. NOTE! This is a high-level
function to be used mainly from outside the 'dict' directory. Inside this
directory dict_table_get_low is usually the appropriate function. */
@@ -174,6 +206,14 @@ dict_table_release(
/*===============*/
dict_table_t* table); /* in: table to be released */
/**************************************************************************
+Checks if a table is in the dictionary cache. */
+UNIV_INLINE
+dict_table_t*
+dict_table_check_if_in_cache_low(
+/*==============================*/
+ /* out: table, NULL if not found */
+ char* table_name); /* in: table name */
+/**************************************************************************
Gets a table; loads it to the dictionary cache if necessary. A low-level
function. */
UNIV_INLINE
@@ -208,6 +248,13 @@ dict_table_print(
/*=============*/
dict_table_t* table); /* in: table */
/**************************************************************************
+Prints a table data. */
+
+void
+dict_table_print_low(
+/*=================*/
+ dict_table_t* table); /* in: table */
+/**************************************************************************
Prints a table data when we know the table name. */
void
@@ -319,6 +366,16 @@ dict_table_copy_types(
dtuple_t* tuple, /* in: data tuple */
dict_table_t* table); /* in: index */
/**************************************************************************
+Looks for an index with the given id. NOTE that we do not reserve
+the dictionary mutex: this function is for emergency purposes like
+printing info of a corrupt database page! */
+
+dict_index_t*
+dict_index_find_on_id_low(
+/*======================*/
+ /* out: index or NULL if not found from cache */
+ dulint id); /* in: index id */
+/**************************************************************************
Adds an index to dictionary cache. */
ibool
@@ -640,6 +697,23 @@ dict_tree_get_space_reserve(
reserved for updates */
dict_tree_t* tree); /* in: a tree */
/*************************************************************************
+Calculates the minimum record length in an index. */
+
+ulint
+dict_index_calc_min_rec_len(
+/*========================*/
+ dict_index_t* index); /* in: index */
+/*************************************************************************
+Calculates new estimates for table and index statistics. The statistics
+are used in query optimization. */
+
+void
+dict_update_statistics_low(
+/*=======================*/
+ dict_table_t* table, /* in: table */
+ ibool has_dict_mutex);/* in: TRUE if the caller has the
+ dictionary mutex */
+/*************************************************************************
Calculates new estimates for table and index statistics. The statistics
are used in query optimization. */
@@ -661,7 +735,8 @@ dict_mutex_exit_for_mysql(void);
/*===========================*/
-extern dict_sys_t* dict_sys; /* the dictionary system */
+extern dict_sys_t* dict_sys; /* the dictionary system */
+extern rw_lock_t dict_foreign_key_check_lock;
/* Dictionary system struct */
struct dict_sys_struct{
diff --git a/innobase/include/dict0dict.ic b/innobase/include/dict0dict.ic
index 9089ebe8edd..821465f96a8 100644
--- a/innobase/include/dict0dict.ic
+++ b/innobase/include/dict0dict.ic
@@ -532,12 +532,11 @@ dict_tree_get_space_reserve(
}
/**************************************************************************
-Gets a table; loads it to the dictionary cache if necessary. A low-level
-function. */
+Checks if a table is in the dictionary cache. */
UNIV_INLINE
dict_table_t*
-dict_table_get_low(
-/*===============*/
+dict_table_check_if_in_cache_low(
+/*==============================*/
/* out: table, NULL if not found */
char* table_name) /* in: table name */
{
@@ -552,6 +551,26 @@ dict_table_get_low(
HASH_SEARCH(name_hash, dict_sys->table_hash, table_fold, table,
ut_strcmp(table->name, table_name) == 0);
+ return(table);
+}
+
+/**************************************************************************
+Gets a table; loads it to the dictionary cache if necessary. A low-level
+function. */
+UNIV_INLINE
+dict_table_t*
+dict_table_get_low(
+/*===============*/
+ /* out: table, NULL if not found */
+ char* table_name) /* in: table name */
+{
+ dict_table_t* table;
+
+ ut_ad(table_name);
+ ut_ad(mutex_own(&(dict_sys->mutex)));
+
+ table = dict_table_check_if_in_cache_low(table_name);
+
if (table == NULL) {
table = dict_load_table(table_name);
}
@@ -603,6 +622,7 @@ dict_table_get_on_id_low(
dict_table_t* table;
ulint fold;
+ ut_ad(mutex_own(&(dict_sys->mutex)));
UT_NOT_USED(trx);
/* Look for the table name in the hash table */
diff --git a/innobase/include/dict0load.h b/innobase/include/dict0load.h
index d0298d8df37..b60996a8dab 100644
--- a/innobase/include/dict0load.h
+++ b/innobase/include/dict0load.h
@@ -15,8 +15,19 @@ Created 4/24/1996 Heikki Tuuri
#include "ut0byte.h"
/************************************************************************
+Finds the first table name in the given database. */
+
+char*
+dict_get_first_table_name_in_db(
+/*============================*/
+ /* out, own: table name, NULL if does not exist;
+ the caller must free the memory in the string! */
+ char* name); /* in: database name which ends to '/' */
+/************************************************************************
Loads a table definition and also all its index definitions, and also
-the cluster definition, if the table is a member in a cluster. */
+the cluster definition if the table is a member in a cluster. Also loads
+all foreign key constraints where the foreign key is in the table or where
+a foreign key references columns in this table. */
dict_table_t*
dict_load_table(
@@ -40,6 +51,25 @@ void
dict_load_sys_table(
/*================*/
dict_table_t* table); /* in: system table */
+/***************************************************************************
+Loads foreign key constraints where the table is either the foreign key
+holder or where the table is referenced by a foreign key. Adds these
+constraints to the data dictionary. Note that we know that the dictionary
+cache already contains all constraints where the other relevant table is
+already in the dictionary cache. */
+
+ulint
+dict_load_foreigns(
+/*===============*/
+ /* out: DB_SUCCESS or error code */
+ char* table_name); /* in: table name */
+/************************************************************************
+Prints to the standard output information on all tables found in the data
+dictionary system table. */
+
+void
+dict_print(void);
+/*============*/
#ifndef UNIV_NONINL
diff --git a/innobase/include/dict0mem.h b/innobase/include/dict0mem.h
index 74ecbc8bba2..bd24d1539ca 100644
--- a/innobase/include/dict0mem.h
+++ b/innobase/include/dict0mem.h
@@ -123,6 +123,13 @@ dict_mem_index_free(
/*================*/
dict_index_t* index); /* in: index */
/**************************************************************************
+Creates and initializes a foreign constraint memory object. */
+
+dict_foreign_t*
+dict_mem_foreign_create(void);
+/*=========================*/
+ /* out, own: foreign constraint struct */
+/**************************************************************************
Creates a procedure memory object. */
dict_proc_t*
@@ -221,15 +228,56 @@ struct dict_index_struct{
dictionary cache */
btr_search_t* search_info; /* info used in optimistic searches */
/*----------------------*/
- ulint stat_n_diff_key_vals;
+ ib_longlong* stat_n_diff_key_vals;
/* approximate number of different key values
- for this index; we periodically calculate
- new estimates */
+ for this index, for each n-column prefix
+ where n <= dict_get_n_unique(index); we
+ periodically calculate new estimates */
ulint stat_index_size;
/* approximate index size in database pages */
+ ulint stat_n_leaf_pages;
+ /* approximate number of leaf pages in the
+ index tree */
ulint magic_n;/* magic number */
};
+/* Data structure for a foreign key constraint; an example:
+FOREIGN KEY (A, B) REFERENCES TABLE2 (C, D) */
+
+struct dict_foreign_struct{
+ mem_heap_t* heap; /* this object is allocated from
+ this memory heap */
+ char* id; /* id of the constraint as a
+ null-terminated string */
+ char* foreign_table_name;/* foreign table name */
+ dict_table_t* foreign_table; /* table where the foreign key is */
+ char** foreign_col_names;/* names of the columns in the
+ foreign key */
+ char* referenced_table_name;/* referenced table name */
+ dict_table_t* referenced_table;/* table where the referenced key
+ is */
+ char** referenced_col_names;/* names of the referenced
+ columns in the referenced table */
+ ulint n_fields; /* number of indexes' first fields
+ for which the the foreign key
+ constraint is defined: we allow the
+ indexes to contain more fields than
+ mentioned in the constraint, as long
+ as the first fields are as mentioned */
+ dict_index_t* foreign_index; /* foreign index; we require that
+ both tables contain explicitly defined
+ indexes for the constraint: InnoDB
+ does not generate new indexes
+ implicitly */
+ dict_index_t* referenced_index;/* referenced index */
+ UT_LIST_NODE_T(dict_foreign_t)
+ foreign_list; /* list node for foreign keys of the
+ table */
+ UT_LIST_NODE_T(dict_foreign_t)
+ referenced_list;/* list node for referenced keys of the
+ table */
+};
+
#define DICT_INDEX_MAGIC_N 76789786
/* Data structure for a database table */
@@ -247,6 +295,13 @@ struct dict_table_struct{
dict_col_t* cols; /* array of column descriptions */
UT_LIST_BASE_NODE_T(dict_index_t)
indexes; /* list of indexes of the table */
+ UT_LIST_BASE_NODE_T(dict_foreign_t)
+ foreign_list;/* list of foreign key constraints
+ in the table; these refer to columns
+ in other tables */
+ UT_LIST_BASE_NODE_T(dict_foreign_t)
+ referenced_list;/* list of foreign key constraints
+ which refer to this table */
UT_LIST_NODE_T(dict_table_t)
table_LRU; /* node of the LRU list of tables */
ulint mem_fix;/* count of how many times the table
@@ -254,6 +309,13 @@ struct dict_table_struct{
currently NOT used */
ibool cached; /* TRUE if the table object has been added
to the dictionary cache */
+ lock_t* auto_inc_lock;/* a buffer for an auto-inc lock
+ for this table: we allocate the memory here
+ so that individual transactions can get it
+ and release it without a need to allocate
+ space from the lock heap of the trx:
+ otherwise the lock heap would grow rapidly
+ if we do a large insert from a select */
UT_LIST_BASE_NODE_T(lock_t)
locks; /* list of locks on the table */
/*----------------------*/
@@ -278,7 +340,7 @@ struct dict_table_struct{
forget about value TRUE if it has to reload
the table definition from disk */
/*----------------------*/
- ulint stat_n_rows;
+ ib_longlong stat_n_rows;
/* approximate number of rows in the table;
we periodically calculate new estimates */
ulint stat_clustered_index_size;
diff --git a/innobase/include/dict0types.h b/innobase/include/dict0types.h
index fe1bad45063..498c6f46b7b 100644
--- a/innobase/include/dict0types.h
+++ b/innobase/include/dict0types.h
@@ -16,6 +16,7 @@ typedef struct dict_index_struct dict_index_t;
typedef struct dict_tree_struct dict_tree_t;
typedef struct dict_table_struct dict_table_t;
typedef struct dict_proc_struct dict_proc_t;
+typedef struct dict_foreign_struct dict_foreign_t;
/* A cluster object is a table object with the type field set to
DICT_CLUSTERED */
diff --git a/innobase/include/fil0fil.h b/innobase/include/fil0fil.h
index bfc322270fc..ca74ea4cb2c 100644
--- a/innobase/include/fil0fil.h
+++ b/innobase/include/fil0fil.h
@@ -76,6 +76,9 @@ extern fil_addr_t fil_addr_null;
#define FIL_TABLESPACE 501
#define FIL_LOG 502
+extern ulint fil_n_pending_log_flushes;
+extern ulint fil_n_pending_tablespace_flushes;
+
/***********************************************************************
Reserves a right to open a single file. The right must be released with
fil_release_right_to_open. */
diff --git a/innobase/include/ibuf0ibuf.h b/innobase/include/ibuf0ibuf.h
index f0b333192de..99fb1595f49 100644
--- a/innobase/include/ibuf0ibuf.h
+++ b/innobase/include/ibuf0ibuf.h
@@ -226,6 +226,21 @@ ibuf_contract(
issued read with the highest tablespace address
to complete */
/*************************************************************************
+Contracts insert buffer trees by reading pages to the buffer pool. */
+
+ulint
+ibuf_contract_for_n_pages(
+/*======================*/
+ /* out: a lower limit for the combined size in bytes
+ of entries which will be merged from ibuf trees to the
+ pages read, 0 if ibuf is empty */
+ ibool sync, /* in: TRUE if the caller wants to wait for the
+ issued read with the highest tablespace address
+ to complete */
+ ulint n_pages);/* in: try to read at least this many pages to
+ the buffer pool and merge the ibuf contents to
+ them */
+/*************************************************************************
Parses a redo log record of an ibuf bitmap page init. */
byte*
diff --git a/innobase/include/lock0lock.h b/innobase/include/lock0lock.h
index c492e7b8ef3..5a15b78b869 100644
--- a/innobase/include/lock0lock.h
+++ b/innobase/include/lock0lock.h
@@ -21,15 +21,13 @@ Created 5/7/1996 Heikki Tuuri
extern ibool lock_print_waits;
-/*****************************************************************
-Cancels a waiting record lock request and releases the waiting transaction
-that requested it. NOTE: does NOT check if waiting lock requests behind this
-one can now be granted! */
+/*************************************************************************
+Gets the size of a lock struct. */
-void
-lock_rec_cancel(
-/*============*/
- lock_t* lock); /* in: waiting record lock request */
+ulint
+lock_get_size(void);
+/*===============*/
+ /* out: size in bytes */
/*************************************************************************
Creates the lock system at database start. */
@@ -388,6 +386,14 @@ lock_is_on_table(
/* out: TRUE if there are lock(s) */
dict_table_t* table); /* in: database table in dictionary cache */
/*************************************************************************
+Releases an auto-inc lock a transaction possibly has on a table.
+Releases possible other transactions waiting for this lock. */
+
+void
+lock_table_unlock_auto_inc(
+/*=======================*/
+ trx_t* trx); /* in: transaction */
+/*************************************************************************
Releases transaction locks, and releases possible other transactions waiting
because of these locks. */
@@ -396,6 +402,14 @@ lock_release_off_kernel(
/*====================*/
trx_t* trx); /* in: transaction */
/*************************************************************************
+Cancels a waiting lock request and releases possible other transactions
+waiting behind it. */
+
+void
+lock_cancel_waiting_and_release(
+/*============================*/
+ lock_t* lock); /* in: waiting lock request */
+/*************************************************************************
Resets all locks, both table and record locks, on a table to be dropped.
No lock is allowed to be a wait lock. */
@@ -495,6 +509,8 @@ extern lock_sys_t* lock_sys;
#define LOCK_IX 3 /* intention exclusive */
#define LOCK_S 4 /* shared */
#define LOCK_X 5 /* exclusive */
+#define LOCK_AUTO_INC 6 /* locks the auto-inc counter of a table
+ in an exclusive mode */
#define LOCK_MODE_MASK 0xF /* mask used to extract mode from the
type_mode field in a lock */
#define LOCK_TABLE 16 /* these type values should be so high that */
diff --git a/innobase/include/log0log.h b/innobase/include/log0log.h
index 001f98cfc3c..adff9fae544 100644
--- a/innobase/include/log0log.h
+++ b/innobase/include/log0log.h
@@ -659,6 +659,11 @@ struct log_struct{
mutex! */
ulint n_log_ios; /* number of log i/os initiated thus
far */
+ ulint n_log_ios_old; /* number of log i/o's at the
+ previous printout */
+ time_t last_printout_time;/* when log_print was last time
+ called */
+
/* Fields involved in checkpoints */
ulint max_modified_age_async;
/* when this recommended value for lsn
diff --git a/innobase/include/mtr0mtr.h b/innobase/include/mtr0mtr.h
index dec8eeb1e15..0ef25b3d1ee 100644
--- a/innobase/include/mtr0mtr.h
+++ b/innobase/include/mtr0mtr.h
@@ -203,20 +203,12 @@ mtr_read_dulint(
mtr_t* mtr); /* in: mini-transaction handle */
/*************************************************************************
This macro locks an rw-lock in s-mode. */
-#ifdef UNIV_SYNC_DEBUG
#define mtr_s_lock(B, MTR) mtr_s_lock_func((B), IB__FILE__, __LINE__,\
(MTR))
-#else
-#define mtr_s_lock(B, MTR) mtr_s_lock_func((B), (MTR))
-#endif
/*************************************************************************
This macro locks an rw-lock in x-mode. */
-#ifdef UNIV_SYNC_DEBUG
#define mtr_x_lock(B, MTR) mtr_x_lock_func((B), IB__FILE__, __LINE__,\
(MTR))
-#else
-#define mtr_x_lock(B, MTR) mtr_x_lock_func((B), (MTR))
-#endif
/*************************************************************************
NOTE! Use the macro above!
Locks a lock in s-mode. */
@@ -225,10 +217,8 @@ void
mtr_s_lock_func(
/*============*/
rw_lock_t* lock, /* in: rw-lock */
-#ifdef UNIV_SYNC_DEBUG
char* file, /* in: file name */
ulint line, /* in: line number */
-#endif
mtr_t* mtr); /* in: mtr */
/*************************************************************************
NOTE! Use the macro above!
@@ -238,10 +228,8 @@ void
mtr_x_lock_func(
/*============*/
rw_lock_t* lock, /* in: rw-lock */
-#ifdef UNIV_SYNC_DEBUG
char* file, /* in: file name */
ulint line, /* in: line number */
-#endif
mtr_t* mtr); /* in: mtr */
/*******************************************************
diff --git a/innobase/include/mtr0mtr.ic b/innobase/include/mtr0mtr.ic
index 5718d872bcb..51112fc0d14 100644
--- a/innobase/include/mtr0mtr.ic
+++ b/innobase/include/mtr0mtr.ic
@@ -217,20 +217,14 @@ void
mtr_s_lock_func(
/*============*/
rw_lock_t* lock, /* in: rw-lock */
-#ifdef UNIV_SYNC_DEBUG
char* file, /* in: file name */
ulint line, /* in: line number */
-#endif
mtr_t* mtr) /* in: mtr */
{
ut_ad(mtr);
ut_ad(lock);
- rw_lock_s_lock_func(lock
- #ifdef UNIV_SYNC_DEBUG
- ,0, file, line
- #endif
- );
+ rw_lock_s_lock_func(lock, 0, file, line);
mtr_memo_push(mtr, lock, MTR_MEMO_S_LOCK);
}
@@ -242,20 +236,14 @@ void
mtr_x_lock_func(
/*============*/
rw_lock_t* lock, /* in: rw-lock */
-#ifdef UNIV_SYNC_DEBUG
char* file, /* in: file name */
ulint line, /* in: line number */
-#endif
mtr_t* mtr) /* in: mtr */
{
ut_ad(mtr);
ut_ad(lock);
- rw_lock_x_lock_func(lock, 0
- #ifdef UNIV_SYNC_DEBUG
- , file, line
- #endif
- );
+ rw_lock_x_lock_func(lock, 0, file, line);
mtr_memo_push(mtr, lock, MTR_MEMO_X_LOCK);
}
diff --git a/innobase/include/rem0cmp.h b/innobase/include/rem0cmp.h
index 10c428cb9ca..6f2a99fc8c2 100644
--- a/innobase/include/rem0cmp.h
+++ b/innobase/include/rem0cmp.h
@@ -16,6 +16,32 @@ Created 7/1/1994 Heikki Tuuri
#include "rem0rec.h"
/*****************************************************************
+Returns TRUE if two types are equal for comparison purposes. */
+
+ibool
+cmp_types_are_equal(
+/*================*/
+ /* out: TRUE if the types are considered
+ equal in comparisons */
+ dtype_t* type1, /* in: type 1 */
+ dtype_t* type2); /* in: type 2 */
+/*****************************************************************
+This function is used to compare two data fields for which we know the
+data type. */
+UNIV_INLINE
+int
+cmp_data_data(
+/*==========*/
+ /* out: 1, 0, -1, if data1 is greater, equal,
+ less than data2, respectively */
+ dtype_t* cur_type,/* in: data type of the fields */
+ byte* data1, /* in: data field (== a pointer to a memory
+ buffer) */
+ ulint len1, /* in: data field length or UNIV_SQL_NULL */
+ byte* data2, /* in: data field (== a pointer to a memory
+ buffer) */
+ ulint len2); /* in: data field length or UNIV_SQL_NULL */
+/*****************************************************************
This function is used to compare two dfields where at least the first
has its data type field set. */
UNIV_INLINE
diff --git a/innobase/include/row0ins.h b/innobase/include/row0ins.h
index 612b9e8d73a..cc3b9fa7e9a 100644
--- a/innobase/include/row0ins.h
+++ b/innobase/include/row0ins.h
@@ -16,6 +16,28 @@ Created 4/20/1996 Heikki Tuuri
#include "trx0types.h"
#include "row0types.h"
+/*******************************************************************
+Checks if foreign key constraint fails for an index entry. Sets shared locks
+which lock either the success or the failure of the constraint. NOTE that
+the caller must have a shared latch on dict_foreign_key_check_lock. */
+
+ulint
+row_ins_check_foreign_constraint(
+/*=============================*/
+ /* out: DB_SUCCESS, DB_LOCK_WAIT,
+ DB_NO_REFERENCED_ROW,
+ or DB_ROW_IS_REFERENCED */
+ ibool check_ref,/* in: TRUE If we want to check that
+ the referenced table is ok, FALSE if we
+ want to to check the foreign key table */
+ dict_foreign_t* foreign,/* in: foreign constraint; NOTE that the
+ tables mentioned in it must be in the
+ dictionary cache if they exist at all */
+ dict_table_t* table, /* in: if check_ref is TRUE, then the foreign
+ table, else the referenced table */
+ dict_index_t* index, /* in: index in table */
+ dtuple_t* entry, /* in: index entry for index */
+ que_thr_t* thr); /* in: query thread */
/*************************************************************************
Creates an insert node struct. */
diff --git a/innobase/include/row0mysql.h b/innobase/include/row0mysql.h
index 31f9e15cddc..4e90c0ac590 100644
--- a/innobase/include/row0mysql.h
+++ b/innobase/include/row0mysql.h
@@ -133,6 +133,26 @@ row_update_prebuilt_trx(
handle */
trx_t* trx); /* in: transaction handle */
/*************************************************************************
+Unlocks an AUTO_INC type lock possibly reserved by trx. */
+
+void
+row_unlock_table_autoinc_for_mysql(
+/*===============================*/
+ trx_t* trx); /* in: transaction */
+/*************************************************************************
+Sets an AUTO_INC type lock on the table mentioned in prebuilt. The
+AUTO_INC lock gives exclusive access to the auto-inc counter of the
+table. The lock is reserved only for the duration of an SQL statement.
+It is not compatible with another AUTO_INC or exclusive lock on the
+table. */
+
+int
+row_lock_table_autoinc_for_mysql(
+/*=============================*/
+ /* out: error code or DB_SUCCESS */
+ row_prebuilt_t* prebuilt); /* in: prebuilt struct in the MySQL
+ table handle */
+/*************************************************************************
Does an insert for MySQL. */
int
@@ -211,6 +231,26 @@ row_create_index_for_mysql(
dict_index_t* index, /* in: index defintion */
trx_t* trx); /* in: transaction handle */
/*************************************************************************
+Scans a table create SQL string and adds to the data dictionary
+the foreign key constraints declared in the string. This function
+should be called after the indexes for a table have been created.
+Each foreign key constraint must be accompanied with indexes in
+bot participating tables. The indexes are allowed to contain more
+fields than mentioned in the constraint. */
+
+int
+row_table_add_foreign_constraints(
+/*==============================*/
+ /* out: error code or DB_SUCCESS */
+ trx_t* trx, /* in: transaction */
+ char* sql_string, /* in: table create statement where
+ foreign keys are declared like:
+ FOREIGN KEY (a, b) REFERENCES table2(c, d),
+ table2 can be written also with the database
+ name before it: test.table2 */
+ char* name); /* in: table full name in the normalized form
+ database_name/table_name */
+/*************************************************************************
Drops a table for MySQL. If the name of the dropped table ends to
characters INNODB_MONITOR, then this also stops printing of monitor
output by the master thread. */
@@ -224,6 +264,15 @@ row_drop_table_for_mysql(
ibool has_dict_mutex);/* in: TRUE if the caller already owns the
dictionary system mutex */
/*************************************************************************
+Drops a database for MySQL. */
+
+int
+row_drop_database_for_mysql(
+/*========================*/
+ /* out: error code or DB_SUCCESS */
+ char* name, /* in: database name which ends to '/' */
+ trx_t* trx); /* in: transaction handle */
+/*************************************************************************
Renames a table for MySQL. */
int
diff --git a/innobase/include/row0upd.h b/innobase/include/row0upd.h
index 9bb73726b29..106d3866b25 100644
--- a/innobase/include/row0upd.h
+++ b/innobase/include/row0upd.h
@@ -47,8 +47,7 @@ upd_get_nth_field(
upd_t* update, /* in: update vector */
ulint n); /* in: field position in update vector */
/*************************************************************************
-Sets the clustered index field number to be updated by an update vector
-field. */
+Sets an index field number to be updated by an update vector field. */
UNIV_INLINE
void
upd_field_set_field_no(
@@ -56,7 +55,7 @@ upd_field_set_field_no(
upd_field_t* upd_field, /* in: update vector field */
ulint field_no, /* in: field number in a clustered
index */
- dict_index_t* index); /* in: clustered index */
+ dict_index_t* index); /* in: index */
/*************************************************************************
Writes into the redo log the values of trx id and roll ptr and enough info
to determine their positions within a clustered index record. */
@@ -136,13 +135,27 @@ row_upd_rec_in_place(
rec_t* rec, /* in/out: record where replaced */
upd_t* update);/* in: update vector */
/*******************************************************************
+Builds an update vector from those fields which in a secondary index entry
+differ from a record that has the equal ordering fields. NOTE: we compare
+the fields as binary strings! */
+
+upd_t*
+row_upd_build_sec_rec_difference_binary(
+/*====================================*/
+ /* out, own: update vector of differing
+ fields */
+ dict_index_t* index, /* in: index */
+ dtuple_t* entry, /* in: entry to insert */
+ rec_t* rec, /* in: secondary index record */
+ mem_heap_t* heap); /* in: memory heap from which allocated */
+/*******************************************************************
Builds an update vector from those fields, excluding the roll ptr and
trx id fields, which in an index entry differ from a record that has
-the equal ordering fields. */
+the equal ordering fields. NOTE: we compare the fields as binary strings! */
upd_t*
-row_upd_build_difference(
-/*=====================*/
+row_upd_build_difference_binary(
+/*============================*/
/* out, own: update vector of differing
fields, excluding roll ptr and trx id */
dict_index_t* index, /* in: clustered index */
@@ -175,13 +188,16 @@ row_upd_clust_index_replace_new_col_vals(
/***************************************************************
Checks if an update vector changes an ordering field of an index record.
This function is fast if the update vector is short or the number of ordering
-fields in the index is small. Otherwise, this can be quadratic. */
-
+fields in the index is small. Otherwise, this can be quadratic.
+NOTE: we compare the fields as binary strings! */
+
ibool
-row_upd_changes_ord_field(
-/*======================*/
+row_upd_changes_ord_field_binary(
+/*=============================*/
/* out: TRUE if update vector changes
- an ordering field in the index record */
+ an ordering field in the index record;
+ NOTE: the fields are compared as binary
+ strings */
dtuple_t* row, /* in: old value of row, or NULL if the
row and the data values in update are not
known when this function is called, e.g., at
@@ -191,11 +207,12 @@ row_upd_changes_ord_field(
/***************************************************************
Checks if an update vector changes an ordering field of an index record.
This function is fast if the update vector is short or the number of ordering
-fields in the index is small. Otherwise, this can be quadratic. */
+fields in the index is small. Otherwise, this can be quadratic.
+NOTE: we compare the fields as binary strings! */
ibool
-row_upd_changes_some_index_ord_field(
-/*=================================*/
+row_upd_changes_some_index_ord_field_binary(
+/*========================================*/
/* out: TRUE if update vector may change
an ordering field in an index record */
dict_table_t* table, /* in: table */
diff --git a/innobase/include/row0upd.ic b/innobase/include/row0upd.ic
index b785e52caa0..7015b2eda13 100644
--- a/innobase/include/row0upd.ic
+++ b/innobase/include/row0upd.ic
@@ -70,8 +70,7 @@ upd_get_nth_field(
}
/*************************************************************************
-Sets the clustered index field number to be updated by an update vector
-field. */
+Sets an index field number to be updated by an update vector field. */
UNIV_INLINE
void
upd_field_set_field_no(
@@ -79,12 +78,18 @@ upd_field_set_field_no(
upd_field_t* upd_field, /* in: update vector field */
ulint field_no, /* in: field number in a clustered
index */
- dict_index_t* index) /* in: clustered index */
-{
- ut_ad(index->type & DICT_CLUSTERED);
-
+ dict_index_t* index) /* in: index */
+{
upd_field->field_no = field_no;
+ if (field_no >= dict_index_get_n_fields(index)) {
+ fprintf(stderr,
+ "InnoDB: Error: trying to access field %lu in table %s\n"
+ "InnoDB: index %s, but index has only %lu fields\n",
+ field_no, index->table_name, index->name,
+ dict_index_get_n_fields(index));
+ }
+
dtype_copy(dfield_get_type(&(upd_field->new_val)),
dict_index_get_nth_type(index, field_no));
}
diff --git a/innobase/include/srv0srv.h b/innobase/include/srv0srv.h
index 3f014adb76c..49eb2b6ec35 100644
--- a/innobase/include/srv0srv.h
+++ b/innobase/include/srv0srv.h
@@ -16,6 +16,11 @@ Created 10/10/1995 Heikki Tuuri
#include "com0com.h"
#include "que0types.h"
+
+/* When this event is set the lock timeout and InnoDB monitor
+thread starts running */
+extern os_event_t srv_lock_timeout_thread_event;
+
/* Server parameters which are read from the initfile */
extern char* srv_data_home;
@@ -27,6 +32,8 @@ extern char** srv_data_file_names;
extern ulint* srv_data_file_sizes;
extern ulint* srv_data_file_is_raw_partition;
+extern ibool srv_created_new_raw;
+
#define SRV_NEW_RAW 1
#define SRV_OLD_RAW 2
@@ -39,6 +46,8 @@ extern ibool srv_log_archive_on;
extern ulint srv_log_buffer_size;
extern ibool srv_flush_log_at_trx_commit;
+extern byte srv_latin1_ordering[256];/* The sort order table of the latin1
+ character set */
extern ibool srv_use_native_aio;
extern ulint srv_pool_size;
@@ -54,6 +63,7 @@ extern ulint srv_lock_wait_timeout;
extern char* srv_unix_file_flush_method_str;
extern ulint srv_unix_file_flush_method;
+extern ulint srv_force_recovery;
extern ibool srv_use_doublewrite_buf;
@@ -70,6 +80,7 @@ extern ulint srv_n_rows_read;
extern ibool srv_print_innodb_monitor;
extern ibool srv_print_innodb_lock_monitor;
extern ibool srv_print_innodb_tablespace_monitor;
+extern ibool srv_print_innodb_table_monitor;
extern ulint srv_n_spin_wait_rounds;
extern ulint srv_spin_wait_delay;
@@ -132,6 +143,25 @@ what these mean */
#define SRV_UNIX_LITTLESYNC 3
#define SRV_UNIX_NOSYNC 4
+/* Alternatives for srv_force_recovery. Non-zero values are intended
+to help the user get a damaged database up so that he can dump intact
+tables and rows with SELECT INTO OUTFILE. The database must not otherwise
+be used with these options! A bigger number below means that all precautions
+of lower numbers are included. */
+
+#define SRV_FORCE_IGNORE_CORRUPT 1 /* let the server run even if it
+ detects a corrupt page */
+#define SRV_FORCE_NO_BACKGROUND 2 /* prevent the main thread from
+ running: if a crash would occur
+ in purge, this prevents it */
+#define SRV_FORCE_NO_TRX_UNDO 3 /* do not run trx rollback after
+ recovery */
+#define SRV_FORCE_NO_IBUF_MERGE 4 /* prevent also ibuf operations:
+ if they would cause a crash, better
+ not do them */
+#define SRV_FORCE_NO_LOG_REDO 5 /* do not do the log roll-forward
+ in connection with recovery */
+
/*************************************************************************
Boots Innobase server. */
@@ -224,15 +254,30 @@ srv_release_mysql_thread_if_suspended(
que_thr_t* thr); /* in: query thread associated with the
MySQL OS thread */
/*************************************************************************
-A thread which wakes up threads whose lock wait may have lasted too long. */
+A thread which wakes up threads whose lock wait may have lasted too long.
+This also prints the info output by various InnoDB monitors. */
+
+#ifndef __WIN__
+void*
+#else
+ulint
+#endif
+srv_lock_timeout_and_monitor_thread(
+/*================================*/
+ /* out: a dummy parameter */
+ void* arg); /* in: a dummy parameter required by
+ os_thread_create */
+/*************************************************************************
+A thread which prints warnings about semaphore waits which have lasted
+too long. These can be used to track bugs which cause hangs. */
#ifndef __WIN__
void*
#else
ulint
#endif
-srv_lock_timeout_monitor_thread(
-/*============================*/
+srv_error_monitor_thread(
+/*=====================*/
/* out: a dummy parameter */
void* arg); /* in: a dummy parameter required by
os_thread_create */
diff --git a/innobase/include/sync0arr.h b/innobase/include/sync0arr.h
index 75d79f4c93f..f0134894997 100644
--- a/innobase/include/sync0arr.h
+++ b/innobase/include/sync0arr.h
@@ -51,13 +51,9 @@ sync_array_reserve_cell(
sync_array_t* arr, /* in: wait array */
void* object, /* in: pointer to the object to wait for */
ulint type, /* in: lock request type */
- #ifdef UNIV_SYNC_DEBUG
- char* file, /* in: in debug version file where
- requested */
- ulint line, /* in: in the debug version line where
- requested */
- #endif
- ulint* index); /* out: index of the reserved cell */
+ char* file, /* in: file where requested */
+ ulint line, /* in: line where requested */
+ ulint* index); /* out: index of the reserved cell */
/**********************************************************************
This function should be called when a thread starts to wait on
a wait array cell. In the debug version this function checks
@@ -90,6 +86,20 @@ sync_array_signal_object(
/*=====================*/
sync_array_t* arr, /* in: wait array */
void* object);/* in: wait object */
+/**************************************************************************
+If the wakeup algorithm does not work perfectly at semaphore relases,
+this function will do the waking (see the comment in mutex_exit). This
+function should be called about every 1 second in the server. */
+
+void
+sync_arr_wake_threads_if_sema_free(void);
+/*====================================*/
+/**************************************************************************
+Prints warnings of long semaphore waits to stderr. Currently > 120 sec. */
+
+void
+sync_array_print_long_waits(void);
+/*=============================*/
/************************************************************************
Validates the integrity of the wait array. Checks
that the number of reserved cells equals the count variable. */
diff --git a/innobase/include/sync0ipm.ic b/innobase/include/sync0ipm.ic
index 8487830e1dd..b8aa87ba6d6 100644
--- a/innobase/include/sync0ipm.ic
+++ b/innobase/include/sync0ipm.ic
@@ -92,7 +92,7 @@ loop:
loop_count++;
ut_ad(loop_count < 15);
- if (mutex_enter_nowait(mutex) == 0) {
+ if (mutex_enter_nowait(mutex, IB__FILE__, __LINE__) == 0) {
/* Succeeded! */
return(0);
@@ -105,7 +105,7 @@ loop:
/* Order is important here: FIRST reset event, then set waiters */
ip_mutex_set_waiters(ip_mutex, 1);
- if (mutex_enter_nowait(mutex) == 0) {
+ if (mutex_enter_nowait(mutex, IB__FILE__, __LINE__) == 0) {
/* Succeeded! */
return(0);
diff --git a/innobase/include/sync0rw.h b/innobase/include/sync0rw.h
index 4e055da3810..7ad38f5bc7f 100644
--- a/innobase/include/sync0rw.h
+++ b/innobase/include/sync0rw.h
@@ -46,9 +46,10 @@ extern ibool rw_lock_debug_waiters; /* This is set to TRUE, if
extern ulint rw_s_system_call_count;
extern ulint rw_s_spin_wait_count;
extern ulint rw_s_exit_count;
-
+extern ulint rw_s_os_wait_count;
extern ulint rw_x_system_call_count;
extern ulint rw_x_spin_wait_count;
+extern ulint rw_x_os_wait_count;
extern ulint rw_x_exit_count;
/**********************************************************************
@@ -92,32 +93,20 @@ rw_lock_validate(
NOTE! The following macros should be used in rw s-locking, not the
corresponding function. */
-#ifdef UNIV_SYNC_DEBUG
#define rw_lock_s_lock(M) rw_lock_s_lock_func(\
(M), 0, IB__FILE__, __LINE__)
-#else
-#define rw_lock_s_lock(M) rw_lock_s_lock_func(M)
-#endif
/******************************************************************
NOTE! The following macros should be used in rw s-locking, not the
corresponding function. */
-#ifdef UNIV_SYNC_DEBUG
#define rw_lock_s_lock_gen(M, P) rw_lock_s_lock_func(\
(M), (P), IB__FILE__, __LINE__)
-#else
-#define rw_lock_s_lock_gen(M, P) rw_lock_s_lock_func(M)
-#endif
/******************************************************************
NOTE! The following macros should be used in rw s-locking, not the
corresponding function. */
-#ifdef UNIV_SYNC_DEBUG
#define rw_lock_s_lock_nowait(M) rw_lock_s_lock_func_nowait(\
(M), IB__FILE__, __LINE__)
-#else
-#define rw_lock_s_lock_nowait(M) rw_lock_s_lock_func_nowait(M)
-#endif
/**********************************************************************
NOTE! Use the corresponding macro, not directly this function, except if
you supply the file name and line number. Lock an rw-lock in shared mode
@@ -129,14 +118,11 @@ UNIV_INLINE
void
rw_lock_s_lock_func(
/*================*/
- rw_lock_t* lock /* in: pointer to rw-lock */
- #ifdef UNIV_SYNC_DEBUG
- ,ulint pass, /* in: pass value; != 0, if the lock will
+ rw_lock_t* lock, /* in: pointer to rw-lock */
+ ulint pass, /* in: pass value; != 0, if the lock will
be passed to another thread to unlock */
- char* file_name, /* in: file name where lock requested */
- ulint line /* in: line where requested */
- #endif
-);
+ char* file_name,/* in: file name where lock requested */
+ ulint line); /* in: line where requested */
/**********************************************************************
NOTE! Use the corresponding macro, not directly this function, except if
you supply the file name and line number. Lock an rw-lock in shared mode
@@ -146,12 +132,9 @@ ibool
rw_lock_s_lock_func_nowait(
/*=======================*/
/* out: TRUE if success */
- rw_lock_t* lock /* in: pointer to rw-lock */
- #ifdef UNIV_SYNC_DEBUG
- ,char* file_name, /* in: file name where lock requested */
- ulint line /* in: line where requested */
- #endif
-);
+ rw_lock_t* lock, /* in: pointer to rw-lock */
+ char* file_name,/* in: file name where lock requested */
+ ulint line); /* in: line where requested */
/**********************************************************************
NOTE! Use the corresponding macro, not directly this function! Lock an
rw-lock in exclusive mode for the current thread if the lock can be
@@ -161,12 +144,9 @@ ibool
rw_lock_x_lock_func_nowait(
/*=======================*/
/* out: TRUE if success */
- rw_lock_t* lock /* in: pointer to rw-lock */
- #ifdef UNIV_SYNC_DEBUG
- ,char* file_name, /* in: file name where lock requested */
- ulint line /* in: line where requested */
- #endif
-);
+ rw_lock_t* lock, /* in: pointer to rw-lock */
+ char* file_name,/* in: file name where lock requested */
+ ulint line); /* in: line where requested */
/**********************************************************************
Releases a shared mode lock. */
UNIV_INLINE
@@ -199,32 +179,20 @@ Releases a shared mode lock. */
NOTE! The following macro should be used in rw x-locking, not the
corresponding function. */
-#ifdef UNIV_SYNC_DEBUG
#define rw_lock_x_lock(M) rw_lock_x_lock_func(\
(M), 0, IB__FILE__, __LINE__)
-#else
-#define rw_lock_x_lock(M) rw_lock_x_lock_func(M, 0)
-#endif
/******************************************************************
NOTE! The following macro should be used in rw x-locking, not the
corresponding function. */
-#ifdef UNIV_SYNC_DEBUG
#define rw_lock_x_lock_gen(M, P) rw_lock_x_lock_func(\
(M), (P), IB__FILE__, __LINE__)
-#else
-#define rw_lock_x_lock_gen(M, P) rw_lock_x_lock_func(M, P)
-#endif
/******************************************************************
NOTE! The following macros should be used in rw x-locking, not the
corresponding function. */
-#ifdef UNIV_SYNC_DEBUG
#define rw_lock_x_lock_nowait(M) rw_lock_x_lock_func_nowait(\
(M), IB__FILE__, __LINE__)
-#else
-#define rw_lock_x_lock_nowait(M) rw_lock_x_lock_func_nowait(M)
-#endif
/**********************************************************************
NOTE! Use the corresponding macro, not directly this function! Lock an
rw-lock in exclusive mode for the current thread. If the rw-lock is locked
@@ -239,13 +207,10 @@ void
rw_lock_x_lock_func(
/*================*/
rw_lock_t* lock, /* in: pointer to rw-lock */
- ulint pass /* in: pass value; != 0, if the lock will
+ ulint pass, /* in: pass value; != 0, if the lock will
be passed to another thread to unlock */
- #ifdef UNIV_SYNC_DEBUG
- ,char* file_name, /* in: file name where lock requested */
- ulint line /* in: line where requested */
- #endif
-);
+ char* file_name,/* in: file name where lock requested */
+ ulint line); /* in: line where requested */
/**********************************************************************
Releases an exclusive mode lock. */
UNIV_INLINE
@@ -283,10 +248,8 @@ void
rw_lock_s_lock_direct(
/*==================*/
rw_lock_t* lock /* in: pointer to rw-lock */
- #ifdef UNIV_SYNC_DEBUG
,char* file_name, /* in: file name where lock requested */
ulint line /* in: line where requested */
- #endif
);
/**********************************************************************
Low-level function which locks an rw-lock in x-mode when we know that it
@@ -297,10 +260,8 @@ void
rw_lock_x_lock_direct(
/*==================*/
rw_lock_t* lock /* in: pointer to rw-lock */
- #ifdef UNIV_SYNC_DEBUG
,char* file_name, /* in: file name where lock requested */
ulint line /* in: line where requested */
- #endif
);
/**********************************************************************
This function is used in the insert buffer to move the ownership of an
@@ -349,6 +310,23 @@ rw_lock_get_x_lock_count(
/*=====================*/
/* out: value of writer_count */
rw_lock_t* lock); /* in: rw-lock */
+/************************************************************************
+Accessor functions for rw lock. */
+UNIV_INLINE
+ulint
+rw_lock_get_waiters(
+/*================*/
+ rw_lock_t* lock);
+UNIV_INLINE
+ulint
+rw_lock_get_writer(
+/*===============*/
+ rw_lock_t* lock);
+UNIV_INLINE
+ulint
+rw_lock_get_reader_count(
+/*=====================*/
+ rw_lock_t* lock);
/**********************************************************************
Checks if the thread has locked the rw-lock in the specified mode, with
the pass value == 0. */
@@ -414,9 +392,6 @@ rw_lock_debug_print(
/*================*/
rw_lock_debug_t* info); /* in: debug struct */
-
-#define RW_CNAME_LEN 8
-
/* NOTE! The structure appears here only for the compiler to know its size.
Do not use its fields directly! The structure used in the spin lock
implementation of a read-write lock. Several threads may have a shared lock
@@ -447,7 +422,7 @@ struct rw_lock_struct {
ulint waiters; /* This ulint is set to 1 if there are
waiters (readers or writers) in the global
wait array, waiting for this rw_lock.
- Otherwise, = 0. */
+ Otherwise, == 0. */
ibool writer_is_wait_ex;
/* This is TRUE if the writer field is
RW_LOCK_WAIT_EX; this field is located far
@@ -463,9 +438,12 @@ struct rw_lock_struct {
info list of the lock */
ulint level; /* Debug version: level in the global latching
order; default SYNC_LEVEL_NONE */
- char cfile_name[RW_CNAME_LEN];
- /* File name where lock created */
+ char* cfile_name; /* File name where lock created */
ulint cline; /* Line where created */
+ char* last_s_file_name;/* File name where last time s-locked */
+ char* last_x_file_name;/* File name where last time x-locked */
+ ulint last_s_line; /* Line number where last time s-locked */
+ ulint last_x_line; /* Line number where last time x-locked */
ulint magic_n;
};
diff --git a/innobase/include/sync0rw.ic b/innobase/include/sync0rw.ic
index 11add13d2d0..2a02cfb6a53 100644
--- a/innobase/include/sync0rw.ic
+++ b/innobase/include/sync0rw.ic
@@ -15,14 +15,11 @@ waiting for the lock before suspending the thread. */
void
rw_lock_s_lock_spin(
/*================*/
- rw_lock_t* lock /* in: pointer to rw-lock */
- #ifdef UNIV_SYNC_DEBUG
- ,ulint pass, /* in: pass value; != 0, if the lock will
+ rw_lock_t* lock, /* in: pointer to rw-lock */
+ ulint pass, /* in: pass value; != 0, if the lock will
be passed to another thread to unlock */
- char* file_name, /* in: file name where lock requested */
- ulint line /* in: line where requested */
- #endif
-);
+ char* file_name,/* in: file name where lock requested */
+ ulint line); /* in: line where requested */
/**********************************************************************
Inserts the debug information for an rw-lock. */
@@ -128,14 +125,11 @@ ibool
rw_lock_s_lock_low(
/*===============*/
/* out: TRUE if success */
- rw_lock_t* lock /* in: pointer to rw-lock */
- #ifdef UNIV_SYNC_DEBUG
- ,ulint pass, /* in: pass value; != 0, if the lock will be
+ rw_lock_t* lock, /* in: pointer to rw-lock */
+ ulint pass, /* in: pass value; != 0, if the lock will be
passed to another thread to unlock */
char* file_name, /* in: file name where lock requested */
- ulint line /* in: line where requested */
- #endif
-)
+ ulint line) /* in: line where requested */
{
ut_ad(mutex_own(rw_lock_get_mutex(lock)));
@@ -150,6 +144,9 @@ rw_lock_s_lock_low(
line);
#endif
+ lock->last_s_file_name = file_name;
+ lock->last_s_line = line;
+
return(TRUE); /* locking succeeded */
}
@@ -164,12 +161,9 @@ UNIV_INLINE
void
rw_lock_s_lock_direct(
/*==================*/
- rw_lock_t* lock /* in: pointer to rw-lock */
- #ifdef UNIV_SYNC_DEBUG
- ,char* file_name, /* in: file name where lock requested */
- ulint line /* in: line where requested */
- #endif
-)
+ rw_lock_t* lock, /* in: pointer to rw-lock */
+ char* file_name,/* in: file name where lock requested */
+ ulint line) /* in: line where requested */
{
ut_ad(lock->writer == RW_LOCK_NOT_LOCKED);
ut_ad(rw_lock_get_reader_count(lock) == 0);
@@ -177,6 +171,9 @@ rw_lock_s_lock_direct(
/* Set the shared lock by incrementing the reader count */
lock->reader_count++;
+ lock->last_s_file_name = file_name;
+ lock->last_s_line = line;
+
#ifdef UNIV_SYNC_DEBUG
rw_lock_add_debug_info(lock, 0, RW_LOCK_SHARED, file_name, line);
#endif
@@ -190,12 +187,9 @@ UNIV_INLINE
void
rw_lock_x_lock_direct(
/*==================*/
- rw_lock_t* lock /* in: pointer to rw-lock */
- #ifdef UNIV_SYNC_DEBUG
- ,char* file_name, /* in: file name where lock requested */
- ulint line /* in: line where requested */
- #endif
-)
+ rw_lock_t* lock, /* in: pointer to rw-lock */
+ char* file_name, /* in: file name where lock requested */
+ ulint line) /* in: line where requested */
{
ut_ad(rw_lock_validate(lock));
ut_ad(rw_lock_get_reader_count(lock) == 0);
@@ -206,6 +200,9 @@ rw_lock_x_lock_direct(
lock->writer_count++;
lock->pass = 0;
+ lock->last_x_file_name = file_name;
+ lock->last_x_line = line;
+
#ifdef UNIV_SYNC_DEBUG
rw_lock_add_debug_info(lock, 0, RW_LOCK_EX, file_name, line);
#endif
@@ -221,14 +218,11 @@ UNIV_INLINE
void
rw_lock_s_lock_func(
/*================*/
- rw_lock_t* lock /* in: pointer to rw-lock */
- #ifdef UNIV_SYNC_DEBUG
- ,ulint pass, /* in: pass value; != 0, if the lock will
+ rw_lock_t* lock, /* in: pointer to rw-lock */
+ ulint pass, /* in: pass value; != 0, if the lock will
be passed to another thread to unlock */
char* file_name, /* in: file name where lock requested */
- ulint line /* in: line where requested */
- #endif
-)
+ ulint line) /* in: line where requested */
{
/* NOTE: As we do not know the thread ids for threads which have
s-locked a latch, and s-lockers will be served only after waiting
@@ -245,11 +239,7 @@ rw_lock_s_lock_func(
mutex_enter(rw_lock_get_mutex(lock));
- if (TRUE == rw_lock_s_lock_low(lock
- #ifdef UNIV_SYNC_DEBUG
- ,pass, file_name, line
- #endif
- )) {
+ if (TRUE == rw_lock_s_lock_low(lock, pass, file_name, line)) {
mutex_exit(rw_lock_get_mutex(lock));
return; /* Success */
@@ -257,11 +247,8 @@ rw_lock_s_lock_func(
/* Did not succeed, try spin wait */
mutex_exit(rw_lock_get_mutex(lock));
- rw_lock_s_lock_spin(lock
- #ifdef UNIV_SYNC_DEBUG
- ,pass, file_name, line
- #endif
- );
+ rw_lock_s_lock_spin(lock, pass, file_name, line);
+
return;
}
}
@@ -275,12 +262,9 @@ ibool
rw_lock_s_lock_func_nowait(
/*=======================*/
/* out: TRUE if success */
- rw_lock_t* lock /* in: pointer to rw-lock */
- #ifdef UNIV_SYNC_DEBUG
- ,char* file_name, /* in: file name where lock requested */
- ulint line /* in: line where requested */
- #endif
-)
+ rw_lock_t* lock, /* in: pointer to rw-lock */
+ char* file_name,/* in: file name where lock requested */
+ ulint line) /* in: line where requested */
{
ibool success = FALSE;
@@ -294,6 +278,9 @@ rw_lock_s_lock_func_nowait(
rw_lock_add_debug_info(lock, 0, RW_LOCK_SHARED, file_name,
line);
#endif
+
+ lock->last_s_file_name = file_name;
+ lock->last_s_line = line;
success = TRUE;
}
@@ -312,12 +299,9 @@ ibool
rw_lock_x_lock_func_nowait(
/*=======================*/
/* out: TRUE if success */
- rw_lock_t* lock /* in: pointer to rw-lock */
- #ifdef UNIV_SYNC_DEBUG
- ,char* file_name, /* in: file name where lock requested */
- ulint line /* in: line where requested */
- #endif
-)
+ rw_lock_t* lock, /* in: pointer to rw-lock */
+ char* file_name, /* in: file name where lock requested */
+ ulint line) /* in: line where requested */
{
ibool success = FALSE;
@@ -338,6 +322,9 @@ rw_lock_x_lock_func_nowait(
rw_lock_add_debug_info(lock, 0, RW_LOCK_EX, file_name, line);
#endif
+ lock->last_x_file_name = file_name;
+ lock->last_x_line = line;
+
success = TRUE;
}
diff --git a/innobase/include/sync0sync.h b/innobase/include/sync0sync.h
index cb86b2b815c..6c3bff66e27 100644
--- a/innobase/include/sync0sync.h
+++ b/innobase/include/sync0sync.h
@@ -64,24 +64,15 @@ mutex_free(
NOTE! The following macro should be used in mutex locking, not the
corresponding function. */
-#ifdef UNIV_SYNC_DEBUG
#define mutex_enter(M) mutex_enter_func((M), IB__FILE__, __LINE__)
-#else
-#define mutex_enter(M) mutex_enter_func(M)
-#endif
/******************************************************************
NOTE! The following macro should be used in mutex locking, not the
corresponding function. */
/* NOTE! currently same as mutex_enter! */
-#ifdef UNIV_SYNC_DEBUG
-#define mutex_enter_fast(M) mutex_enter_func((M), IB__FILE__, __LINE__)
-#else
-#define mutex_enter_fast(M) mutex_enter_func(M)
-#endif
-
-#define mutex_enter_fast_func mutex_enter_func;
+#define mutex_enter_fast(M) mutex_enter_func((M), IB__FILE__, __LINE__)
+#define mutex_enter_fast_func mutex_enter_func;
/**********************************************************************
NOTE! Use the corresponding macro in the header file, not this function
directly. Locks a mutex for the current thread. If the mutex is reserved
@@ -91,12 +82,9 @@ UNIV_INLINE
void
mutex_enter_func(
/*=============*/
- mutex_t* mutex /* in: pointer to mutex */
- #ifdef UNIV_SYNC_DEBUG
- ,char* file_name, /* in: file name where locked */
- ulint line /* in: line where locked */
- #endif
- );
+ mutex_t* mutex, /* in: pointer to mutex */
+ char* file_name, /* in: file name where locked */
+ ulint line); /* in: line where locked */
/************************************************************************
Tries to lock the mutex for the current thread. If the lock is not acquired
immediately, returns with return value 1. */
@@ -104,8 +92,11 @@ immediately, returns with return value 1. */
ulint
mutex_enter_nowait(
/*===============*/
- /* out: 0 if succeed, 1 if not */
- mutex_t* mutex); /* in: pointer to mutex */
+ /* out: 0 if succeed, 1 if not */
+ mutex_t* mutex, /* in: pointer to mutex */
+ char* file_name, /* in: file name where mutex
+ requested */
+ ulint line); /* in: line where requested */
/**********************************************************************
Unlocks a mutex owned by the current thread. */
UNIV_INLINE
@@ -373,6 +364,7 @@ Memory pool mutex */
#define SYNC_LEVEL_NONE 2000 /* default: level not defined */
#define SYNC_DICT 1000
#define SYNC_DICT_AUTOINC_MUTEX 999
+#define SYNC_FOREIGN_KEY_CHECK 998
#define SYNC_PURGE_IS_RUNNING 997
#define SYNC_DICT_HEADER 995
#define SYNC_IBUF_HEADER 914
@@ -418,6 +410,7 @@ Memory pool mutex */
#define SYNC_BUF_BLOCK 149
#define SYNC_DOUBLEWRITE 140
#define SYNC_ANY_LATCH 135
+#define SYNC_THR_LOCAL 133
#define SYNC_MEM_HASH 131
#define SYNC_MEM_POOL 130
@@ -429,8 +422,6 @@ Memory pool mutex */
#define RW_LOCK_WAIT_EX 353
#define SYNC_MUTEX 354
-#define MUTEX_CNAME_LEN 8
-
/* NOTE! The structure appears here only for the compiler to know its size.
Do not use its fields directly! The structure used in the spin lock
implementation of a mutual exclusion semaphore. */
@@ -457,8 +448,7 @@ struct mutex_struct {
locked */
ulint level; /* Debug version: level in the global latching
order; default SYNC_LEVEL_NONE */
- char cfile_name[MUTEX_CNAME_LEN];
- /* File name where mutex created */
+ char* cfile_name; /* File name where mutex created */
ulint cline; /* Line where created */
ulint magic_n;
};
diff --git a/innobase/include/sync0sync.ic b/innobase/include/sync0sync.ic
index f7b341cb386..9531377ce0b 100644
--- a/innobase/include/sync0sync.ic
+++ b/innobase/include/sync0sync.ic
@@ -22,13 +22,9 @@ for the mutex before suspending the thread. */
void
mutex_spin_wait(
/*============*/
- mutex_t* mutex /* in: pointer to mutex */
-
- #ifdef UNIV_SYNC_DEBUG
- ,char* file_name, /* in: file name where mutex requested */
- ulint line /* in: line where requested */
- #endif
-);
+ mutex_t* mutex, /* in: pointer to mutex */
+ char* file_name,/* in: file name where mutex requested */
+ ulint line); /* in: line where requested */
/**********************************************************************
Sets the debug information for a reserved mutex. */
@@ -209,6 +205,18 @@ mutex_exit(
#endif
mutex_reset_lock_word(mutex);
+ /* A problem: we assume that mutex_reset_lock word
+ is a memory barrier, that is when we read the waiters
+ field next, the read must be serialized in memory
+ after the reset. A speculative processor might
+ perform the read first, which could leave a waiting
+ thread hanging indefinitely.
+
+ Our current solution call every 10 seconds
+ sync_arr_wake_threads_if_sema_free()
+ to wake up possible hanging threads if
+ they are missed in mutex_signal_object. */
+
if (mutex_get_waiters(mutex) != 0) {
mutex_signal_object(mutex);
@@ -227,12 +235,9 @@ UNIV_INLINE
void
mutex_enter_func(
/*=============*/
- mutex_t* mutex /* in: pointer to mutex */
- #ifdef UNIV_SYNC_DEBUG
- ,char* file_name, /* in: file name where locked */
- ulint line /* in: line where locked */
- #endif
- )
+ mutex_t* mutex, /* in: pointer to mutex */
+ char* file_name,/* in: file name where locked */
+ ulint line) /* in: line where locked */
{
ut_ad(mutex_validate(mutex));
@@ -245,13 +250,11 @@ mutex_enter_func(
mutex_set_debug_info(mutex, file_name, line);
#endif
+ mutex->file_name = file_name;
+ mutex->line = line;
+
return; /* Succeeded! */
}
- mutex_spin_wait(mutex
- #ifdef UNIV_SYNC_DEBUG
- ,file_name,
- line
- #endif
- );
+ mutex_spin_wait(mutex, file_name, line);
}
diff --git a/innobase/include/trx0rseg.ic b/innobase/include/trx0rseg.ic
index aeb4466ff0f..423447d5566 100644
--- a/innobase/include/trx0rseg.ic
+++ b/innobase/include/trx0rseg.ic
@@ -61,7 +61,11 @@ trx_rsegf_get_nth_undo(
ulint n, /* in: index of slot */
mtr_t* mtr) /* in: mtr */
{
- ut_ad(n < TRX_RSEG_N_SLOTS);
+ if (n >= TRX_RSEG_N_SLOTS) {
+ fprintf(stderr,
+ "InnoDB: Error: trying to get slot %lu of rseg\n", n);
+ ut_a(0);
+ }
return(mtr_read_ulint(rsegf + TRX_RSEG_UNDO_SLOTS +
n * TRX_RSEG_SLOT_SIZE, MLOG_4BYTES, mtr));
@@ -78,7 +82,11 @@ trx_rsegf_set_nth_undo(
ulint page_no,/* in: page number of the undo log segment */
mtr_t* mtr) /* in: mtr */
{
- ut_ad(n < TRX_RSEG_N_SLOTS);
+ if (n >= TRX_RSEG_N_SLOTS) {
+ fprintf(stderr,
+ "InnoDB: Error: trying to set slot %lu of rseg\n", n);
+ ut_a(0);
+ }
mlog_write_ulint(rsegf + TRX_RSEG_UNDO_SLOTS + n * TRX_RSEG_SLOT_SIZE,
page_no, MLOG_4BYTES, mtr);
diff --git a/innobase/include/trx0trx.h b/innobase/include/trx0trx.h
index f179e20ad62..8db0b39d3b4 100644
--- a/innobase/include/trx0trx.h
+++ b/innobase/include/trx0trx.h
@@ -317,6 +317,19 @@ struct trx_struct{
ibool has_search_latch;
/* TRUE if this trx has latched the
search system latch in S-mode */
+ ulint search_latch_timeout;
+ /* If we notice that someone is
+ waiting for our S-lock on the search
+ latch to be released, we wait in
+ row0sel.c for BTR_SEA_TIMEOUT new
+ searches until we try to keep
+ the search latch again over
+ calls from MySQL; this is intended
+ to reduce contention on the search
+ latch */
+ lock_t* auto_inc_lock; /* possible auto-inc lock reserved by
+ the transaction; note that it is also
+ in the lock list trx_locks */
ibool ignore_duplicates_in_insert;
/* in an insert roll back only insert
of the latest row in case
@@ -401,11 +414,9 @@ struct trx_struct{
checking algorithm */
/*------------------------------*/
mem_heap_t* lock_heap; /* memory heap for the locks of the
- transaction; protected by
- lock_heap_mutex */
+ transaction */
UT_LIST_BASE_NODE_T(lock_t)
- trx_locks; /* locks reserved by the transaction;
- protected by lock_heap_mutex */
+ trx_locks; /* locks reserved by the transaction */
/*------------------------------*/
mem_heap_t* read_view_heap; /* memory heap for the read view */
read_view_t* read_view; /* consistent read view or NULL */
diff --git a/innobase/include/ut0mem.h b/innobase/include/ut0mem.h
index 8e5a4fda0d3..2d245e5f72f 100644
--- a/innobase/include/ut0mem.h
+++ b/innobase/include/ut0mem.h
@@ -13,6 +13,9 @@ Created 5/30/1994 Heikki Tuuri
#include <string.h>
#include <stdlib.h>
+/* The total amount of memory currently allocated from the OS with malloc */
+extern ulint ut_total_allocated_memory;
+
UNIV_INLINE
void*
ut_memcpy(void* dest, void* sour, ulint n);