summaryrefslogtreecommitdiff
path: root/storage/innobase/trx/trx0i_s.cc
diff options
context:
space:
mode:
Diffstat (limited to 'storage/innobase/trx/trx0i_s.cc')
-rw-r--r--storage/innobase/trx/trx0i_s.cc350
1 files changed, 164 insertions, 186 deletions
diff --git a/storage/innobase/trx/trx0i_s.cc b/storage/innobase/trx/trx0i_s.cc
index 993006efc6d..4fb214a89c4 100644
--- a/storage/innobase/trx/trx0i_s.cc
+++ b/storage/innobase/trx/trx0i_s.cc
@@ -1,6 +1,6 @@
/*****************************************************************************
-Copyright (c) 2007, 2012, Oracle and/or its affiliates. All Rights Reserved.
+Copyright (c) 2007, 2015, Oracle and/or its affiliates. All Rights Reserved.
This program is free software; you can redistribute it and/or modify it under
the terms of the GNU General Public License as published by the Free Software
@@ -34,14 +34,13 @@ Created July 17, 2007 Vasil Dimov
so they must come first.
From the symptoms, this is related to bug#46587 in the MySQL bug DB.
*/
-#include "univ.i"
-#include <mysql/plugin.h>
+#include "ha_prototypes.h"
+#include <sql_class.h>
#include "buf0buf.h"
#include "dict0dict.h"
#include "ha0storage.h"
-#include "ha_prototypes.h"
#include "hash0hash.h"
#include "lock0iter.h"
#include "lock0lock.h"
@@ -52,12 +51,10 @@ Created July 17, 2007 Vasil Dimov
#include "srv0srv.h"
#include "sync0rw.h"
#include "sync0sync.h"
-#include "sync0types.h"
#include "trx0i_s.h"
#include "trx0sys.h"
#include "trx0trx.h"
#include "ut0mem.h"
-#include "ut0ut.h"
/** Initial number of rows in the table cache */
#define TABLE_CACHE_INITIAL_ROWSNUM 1024
@@ -114,15 +111,15 @@ noop because it will be empty. */
/* @} */
/** Memory limit passed to ha_storage_put_memlim().
-@param cache hash storage
-@return maximum allowed allocation size */
+@param cache hash storage
+@return maximum allowed allocation size */
#define MAX_ALLOWED_FOR_STORAGE(cache) \
(TRX_I_S_MEM_LIMIT \
- (cache)->mem_allocd)
/** Memory limit in table_cache_create_empty_row().
-@param cache hash storage
-@return maximum allowed allocation size */
+@param cache hash storage
+@return maximum allowed allocation size */
#define MAX_ALLOWED_FOR_ALLOC(cache) \
(TRX_I_S_MEM_LIMIT \
- (cache)->mem_allocd \
@@ -150,11 +147,15 @@ struct i_s_table_cache_t {
/** This structure describes the intermediate buffer */
struct trx_i_s_cache_t {
- rw_lock_t rw_lock; /*!< read-write lock protecting
+ rw_lock_t* rw_lock; /*!< read-write lock protecting
the rest of this structure */
- ullint last_read; /*!< last time the cache was read;
+ uintmax_t last_read; /*!< last time the cache was read;
measured in microseconds since
epoch */
+ ib_mutex_t last_read_mutex;/*!< mutex protecting the
+ last_read member - it is updated
+ inside a shared lock of the
+ rw_lock member */
i_s_table_cache_t innodb_trx; /*!< innodb_trx table */
i_s_table_cache_t innodb_locks; /*!< innodb_locks table */
i_s_table_cache_t innodb_lock_waits;/*!< innodb_lock_waits table */
@@ -185,21 +186,12 @@ static trx_i_s_cache_t trx_i_s_cache_static;
/** This is the intermediate buffer where data needed to fill the
INFORMATION SCHEMA tables is fetched and later retrieved by the C++
code in handler/i_s.cc. */
-UNIV_INTERN trx_i_s_cache_t* trx_i_s_cache = &trx_i_s_cache_static;
-
-/* Key to register the lock/mutex with performance schema */
-#ifdef UNIV_PFS_RWLOCK
-UNIV_INTERN mysql_pfs_key_t trx_i_s_cache_lock_key;
-#endif /* UNIV_PFS_RWLOCK */
-
-#ifdef UNIV_PFS_MUTEX
-UNIV_INTERN mysql_pfs_key_t cache_last_read_mutex_key;
-#endif /* UNIV_PFS_MUTEX */
+trx_i_s_cache_t* trx_i_s_cache = &trx_i_s_cache_static;
/*******************************************************************//**
For a record lock that is in waiting state retrieves the only bit that
is set, for a table lock returns ULINT_UNDEFINED.
-@return record number within the heap */
+@return record number within the heap */
static
ulint
wait_lock_get_heap_no(
@@ -262,7 +254,7 @@ table_cache_free(
/* the memory is actually allocated in
table_cache_create_empty_row() */
if (table_cache->chunks[i].base) {
- mem_free(table_cache->chunks[i].base);
+ ut_free(table_cache->chunks[i].base);
table_cache->chunks[i].base = NULL;
}
}
@@ -273,7 +265,7 @@ Returns an empty row from a table cache. The row is allocated if no more
empty rows are available. The number of used rows is incremented.
If the memory limit is hit then NULL is returned and nothing is
allocated.
-@return empty row, or NULL if out of memory */
+@return empty row, or NULL if out of memory */
static
void*
table_cache_create_empty_row(
@@ -343,16 +335,17 @@ table_cache_create_empty_row(
chunk = &table_cache->chunks[i];
- chunk->base = mem_alloc2(req_bytes, &got_bytes);
+ got_bytes = req_bytes;
+ chunk->base = ut_malloc_nokey(req_bytes);
got_rows = got_bytes / table_cache->row_size;
cache->mem_allocd += got_bytes;
#if 0
- printf("allocating chunk %d req bytes=%lu, got bytes=%lu, "
- "row size=%lu, "
- "req rows=%lu, got rows=%lu\n",
+ printf("allocating chunk %d req bytes=%lu, got bytes=%lu,"
+ " row size=%lu,"
+ " req rows=%lu, got rows=%lu\n",
i, req_bytes, got_bytes,
table_cache->row_size,
req_rows, got_rows);
@@ -414,14 +407,13 @@ table_cache_create_empty_row(
#ifdef UNIV_DEBUG
/*******************************************************************//**
Validates a row in the locks cache.
-@return TRUE if valid */
+@return TRUE if valid */
static
ibool
i_s_locks_row_validate(
/*===================*/
const i_s_locks_row_t* row) /*!< in: row to validate */
{
- ut_ad(row->lock_trx_id != 0);
ut_ad(row->lock_mode != NULL);
ut_ad(row->lock_type != NULL);
ut_ad(row->lock_table != NULL);
@@ -450,7 +442,7 @@ i_s_locks_row_validate(
/*******************************************************************//**
Fills i_s_trx_row_t object.
If memory can not be allocated then FALSE is returned.
-@return FALSE if allocation fails */
+@return FALSE if allocation fails */
static
ibool
fill_trx_row(
@@ -468,13 +460,12 @@ fill_trx_row(
which to copy volatile
strings */
{
- const char* stmt;
size_t stmt_len;
const char* s;
ut_ad(lock_mutex_own());
- row->trx_id = trx->id;
+ row->trx_id = trx_get_id_for_print(trx);
row->trx_started = (ib_time_t) trx->start_time;
row->trx_state = trx_get_que_state_str(trx);
row->requested_lock_row = requested_lock_row;
@@ -490,7 +481,7 @@ fill_trx_row(
row->trx_wait_started = 0;
}
- row->trx_weight = (ullint) TRX_WEIGHT(trx);
+ row->trx_weight = static_cast<uintmax_t>(TRX_WEIGHT(trx));
if (trx->mysql_thd == NULL) {
/* For internal transactions e.g., purge and transactions
@@ -503,17 +494,10 @@ fill_trx_row(
row->trx_mysql_thread_id = thd_get_thread_id(trx->mysql_thd);
- stmt = innobase_get_stmt(trx->mysql_thd, &stmt_len);
-
- if (stmt != NULL) {
- char query[TRX_I_S_TRX_QUERY_MAX_LEN + 1];
-
- if (stmt_len > TRX_I_S_TRX_QUERY_MAX_LEN) {
- stmt_len = TRX_I_S_TRX_QUERY_MAX_LEN;
- }
+ char query[TRX_I_S_TRX_QUERY_MAX_LEN + 1];
+ stmt_len = innobase_get_stmt_safe(trx->mysql_thd, query, sizeof(query));
- memcpy(query, stmt, stmt_len);
- query[stmt_len] = '\0';
+ if (stmt_len > 0) {
row->trx_query = static_cast<const char*>(
ha_storage_put_memlim(
@@ -550,7 +534,7 @@ thd_done:
row->trx_tables_in_use = trx->n_mysql_tables_in_use;
- row->trx_tables_locked = trx->mysql_n_tables_locked;
+ row->trx_tables_locked = lock_number_of_tables_locked(&trx->lock);
/* These are protected by both trx->mutex or lock_sys->mutex,
or just lock_sys->mutex. For reading, it suffices to hold
@@ -606,8 +590,6 @@ thd_done:
row->trx_has_search_latch = (ibool) trx->has_search_latch;
- row->trx_search_latch_timeout = trx->search_latch_timeout;
-
row->trx_is_read_only = trx->read_only;
row->trx_is_autocommit_non_locking = trx_is_autocommit_non_locking(trx);
@@ -619,7 +601,7 @@ thd_done:
Format the nth field of "rec" and put it in "buf". The result is always
NUL-terminated. Returns the number of bytes that were written to "buf"
(including the terminating NUL).
-@return end of the result */
+@return end of the result */
static
ulint
put_nth_field(
@@ -677,7 +659,7 @@ put_nth_field(
/*******************************************************************//**
Fills the "lock_data" member of i_s_locks_row_t object.
If memory can not be allocated then FALSE is returned.
-@return FALSE if allocation fails */
+@return FALSE if allocation fails */
static
ibool
fill_lock_data(
@@ -688,18 +670,38 @@ fill_lock_data(
trx_i_s_cache_t* cache) /*!< in/out: cache where to store
volatile data */
{
+ ut_a(lock_get_type(lock) == LOCK_REC);
+
+ switch (heap_no) {
+ case PAGE_HEAP_NO_INFIMUM:
+ case PAGE_HEAP_NO_SUPREMUM:
+ *lock_data = ha_storage_put_str_memlim(
+ cache->storage,
+ heap_no == PAGE_HEAP_NO_INFIMUM
+ ? "infimum pseudo-record"
+ : "supremum pseudo-record",
+ MAX_ALLOWED_FOR_STORAGE(cache));
+ return(*lock_data != NULL);
+ }
+
mtr_t mtr;
const buf_block_t* block;
const page_t* page;
const rec_t* rec;
-
- ut_a(lock_get_type(lock) == LOCK_REC);
+ const dict_index_t* index;
+ ulint n_fields;
+ mem_heap_t* heap;
+ ulint offsets_onstack[REC_OFFS_NORMAL_SIZE];
+ ulint* offsets;
+ char buf[TRX_I_S_LOCK_DATA_MAX_LEN];
+ ulint buf_used;
+ ulint i;
mtr_start(&mtr);
- block = buf_page_try_get(lock_rec_get_space_id(lock),
- lock_rec_get_page_no(lock),
+ block = buf_page_try_get(page_id_t(lock_rec_get_space_id(lock),
+ lock_rec_get_page_no(lock)),
&mtr);
if (block == NULL) {
@@ -711,66 +713,45 @@ fill_lock_data(
return(TRUE);
}
- page = (const page_t*) buf_block_get_frame(block);
-
- rec = page_find_rec_with_heap_no(page, heap_no);
-
- if (page_rec_is_infimum(rec)) {
+ page = reinterpret_cast<const page_t*>(buf_block_get_frame(block));
- *lock_data = ha_storage_put_str_memlim(
- cache->storage, "infimum pseudo-record",
- MAX_ALLOWED_FOR_STORAGE(cache));
- } else if (page_rec_is_supremum(rec)) {
-
- *lock_data = ha_storage_put_str_memlim(
- cache->storage, "supremum pseudo-record",
- MAX_ALLOWED_FOR_STORAGE(cache));
- } else {
- const dict_index_t* index;
- ulint n_fields;
- mem_heap_t* heap;
- ulint offsets_onstack[REC_OFFS_NORMAL_SIZE];
- ulint* offsets;
- char buf[TRX_I_S_LOCK_DATA_MAX_LEN];
- ulint buf_used;
- ulint i;
+ rec_offs_init(offsets_onstack);
+ offsets = offsets_onstack;
- rec_offs_init(offsets_onstack);
- offsets = offsets_onstack;
+ rec = page_find_rec_with_heap_no(page, heap_no);
- index = lock_rec_get_index(lock);
+ index = lock_rec_get_index(lock);
- n_fields = dict_index_get_n_unique(index);
+ n_fields = dict_index_get_n_unique(index);
- ut_a(n_fields > 0);
+ ut_a(n_fields > 0);
- heap = NULL;
- offsets = rec_get_offsets(rec, index, offsets, n_fields,
- &heap);
+ heap = NULL;
+ offsets = rec_get_offsets(rec, index, offsets, n_fields,
+ &heap);
- /* format and store the data */
+ /* format and store the data */
- buf_used = 0;
- for (i = 0; i < n_fields; i++) {
+ buf_used = 0;
+ for (i = 0; i < n_fields; i++) {
- buf_used += put_nth_field(
- buf + buf_used, sizeof(buf) - buf_used,
- i, index, rec, offsets) - 1;
- }
+ buf_used += put_nth_field(
+ buf + buf_used, sizeof(buf) - buf_used,
+ i, index, rec, offsets) - 1;
+ }
- *lock_data = (const char*) ha_storage_put_memlim(
- cache->storage, buf, buf_used + 1,
- MAX_ALLOWED_FOR_STORAGE(cache));
+ *lock_data = (const char*) ha_storage_put_memlim(
+ cache->storage, buf, buf_used + 1,
+ MAX_ALLOWED_FOR_STORAGE(cache));
- if (UNIV_UNLIKELY(heap != NULL)) {
+ if (heap != NULL) {
- /* this means that rec_get_offsets() has created a new
- heap and has stored offsets in it; check that this is
- really the case and free the heap */
- ut_a(offsets != offsets_onstack);
- mem_heap_free(heap);
- }
+ /* this means that rec_get_offsets() has created a new
+ heap and has stored offsets in it; check that this is
+ really the case and free the heap */
+ ut_a(offsets != offsets_onstack);
+ mem_heap_free(heap);
}
mtr_commit(&mtr);
@@ -786,7 +767,7 @@ fill_lock_data(
/*******************************************************************//**
Fills i_s_locks_row_t object. Returns its first argument.
If memory can not be allocated then FALSE is returned.
-@return FALSE if allocation fails */
+@return FALSE if allocation fails */
static
ibool
fill_locks_row(
@@ -804,7 +785,7 @@ fill_locks_row(
row->lock_type = lock_get_type_str(lock);
row->lock_table = ha_storage_put_str_memlim(
- cache->storage, lock_get_table_name(lock),
+ cache->storage, lock_get_table_name(lock).m_name,
MAX_ALLOWED_FOR_STORAGE(cache));
/* memory could not be allocated */
@@ -860,7 +841,7 @@ fill_locks_row(
/*******************************************************************//**
Fills i_s_lock_waits_row_t object. Returns its first argument.
-@return result object that's filled */
+@return result object that's filled */
static
i_s_lock_waits_row_t*
fill_lock_waits_row(
@@ -888,7 +869,7 @@ Calculates a hash fold for a lock. For a record lock the fold is
calculated from 4 elements, which uniquely identify a lock at a given
point in time: transaction id, space id, page number, record number.
For a table lock the fold is table's id.
-@return fold */
+@return fold */
static
ulint
fold_lock(
@@ -937,7 +918,7 @@ fold_lock(
/*******************************************************************//**
Checks whether i_s_locks_row_t object represents a lock_t object.
-@return TRUE if they match */
+@return TRUE if they match */
static
ibool
locks_row_eq_lock(
@@ -981,7 +962,7 @@ locks_row_eq_lock(
Searches for a row in the innodb_locks cache that has a specified id.
This happens in O(1) time since a hash table is used. Returns pointer to
the row or NULL if none is found.
-@return row or NULL */
+@return row or NULL */
static
i_s_locks_row_t*
search_innodb_locks(
@@ -1024,7 +1005,7 @@ Adds new element to the locks cache, enlarging it if necessary.
Returns a pointer to the added row. If the row is already present then
no row is added and a pointer to the existing row is returned.
If row can not be allocated then NULL is returned.
-@return row */
+@return row */
static
i_s_locks_row_t*
add_lock_to_cache(
@@ -1091,7 +1072,7 @@ add_lock_to_cache(
/*******************************************************************//**
Adds new pair of locks to the lock waits cache.
If memory can not be allocated then FALSE is returned.
-@return FALSE if allocation fails */
+@return FALSE if allocation fails */
static
ibool
add_lock_wait_to_cache(
@@ -1128,7 +1109,7 @@ innodb_locks and a pointer to the added row is returned in
requested_lock_row, otherwise requested_lock_row is set to NULL.
If rows can not be allocated then FALSE is returned and the value of
requested_lock_row is undefined.
-@return FALSE if allocation fails */
+@return FALSE if allocation fails */
static
ibool
add_trx_relevant_locks_to_cache(
@@ -1222,18 +1203,23 @@ the same version of the cache. */
/*******************************************************************//**
Checks if the cache can safely be updated.
-@return TRUE if can be updated */
+@return TRUE if can be updated */
static
ibool
can_cache_be_updated(
/*=================*/
trx_i_s_cache_t* cache) /*!< in: cache */
{
- ullint now;
+ uintmax_t now;
-#ifdef UNIV_SYNC_DEBUG
- ut_a(rw_lock_own(&cache->rw_lock, RW_LOCK_EX));
-#endif
+ /* Here we read cache->last_read without acquiring its mutex
+ because last_read is only updated when a shared rw lock on the
+ whole cache is being held (see trx_i_s_cache_end_read()) and
+ we are currently holding an exclusive rw lock on the cache.
+ So it is not possible for last_read to be updated while we are
+ reading it. */
+
+ ut_ad(rw_lock_own(cache->rw_lock, RW_LOCK_X));
now = ut_time_us(NULL);
if (now - cache->last_read > CACHE_MIN_IDLE_TIME_US) {
@@ -1270,17 +1256,14 @@ void
fetch_data_into_cache_low(
/*======================*/
trx_i_s_cache_t* cache, /*!< in/out: cache */
- ibool only_ac_nl, /*!< in: only select non-locking
- autocommit transactions */
- trx_list_t* trx_list) /*!< in: trx list */
+ bool read_write, /*!< in: only read-write
+ transactions */
+ trx_ut_list_t* trx_list) /*!< in: trx list */
{
const trx_t* trx;
+ bool rw_trx_list = trx_list == &trx_sys->rw_trx_list;
- ut_ad(trx_list == &trx_sys->rw_trx_list
- || trx_list == &trx_sys->ro_trx_list
- || trx_list == &trx_sys->mysql_trx_list);
-
- ut_ad(only_ac_nl == (trx_list == &trx_sys->mysql_trx_list));
+ ut_ad(rw_trx_list || trx_list == &trx_sys->mysql_trx_list);
/* Iterate over the transaction list and add each one
to innodb_trx's cache. We also add all locks that are relevant
@@ -1290,26 +1273,24 @@ fetch_data_into_cache_low(
for (trx = UT_LIST_GET_FIRST(*trx_list);
trx != NULL;
trx =
- (trx_list == &trx_sys->mysql_trx_list
- ? UT_LIST_GET_NEXT(mysql_trx_list, trx)
- : UT_LIST_GET_NEXT(trx_list, trx))) {
+ (rw_trx_list
+ ? UT_LIST_GET_NEXT(trx_list, trx)
+ : UT_LIST_GET_NEXT(mysql_trx_list, trx))) {
i_s_trx_row_t* trx_row;
i_s_locks_row_t* requested_lock_row;
- if (trx->state == TRX_STATE_NOT_STARTED
- || (only_ac_nl && !trx_is_autocommit_non_locking(trx))) {
+ /* Note: Read only transactions that modify temporary
+ tables an have a transaction ID */
+ if (!trx_is_started(trx)
+ || (!rw_trx_list && trx->id != 0 && !trx->read_only)) {
continue;
}
assert_trx_nonlocking_or_in_list(trx);
- ut_ad(trx->in_ro_trx_list
- == (trx_list == &trx_sys->ro_trx_list));
-
- ut_ad(trx->in_rw_trx_list
- == (trx_list == &trx_sys->rw_trx_list));
+ ut_ad(trx->in_rw_trx_list == rw_trx_list);
if (!add_trx_relevant_locks_to_cache(cache, trx,
&requested_lock_row)) {
@@ -1318,9 +1299,9 @@ fetch_data_into_cache_low(
return;
}
- trx_row = (i_s_trx_row_t*)
- table_cache_create_empty_row(&cache->innodb_trx,
- cache);
+ trx_row = reinterpret_cast<i_s_trx_row_t*>(
+ table_cache_create_empty_row(
+ &cache->innodb_trx, cache));
/* memory could not be allocated */
if (trx_row == NULL) {
@@ -1332,7 +1313,7 @@ fetch_data_into_cache_low(
if (!fill_trx_row(trx_row, trx, requested_lock_row, cache)) {
/* memory could not be allocated */
- cache->innodb_trx.rows_used--;
+ --cache->innodb_trx.rows_used;
cache->is_truncated = TRUE;
return;
}
@@ -1349,16 +1330,16 @@ fetch_data_into_cache(
trx_i_s_cache_t* cache) /*!< in/out: cache */
{
ut_ad(lock_mutex_own());
- ut_ad(mutex_own(&trx_sys->mutex));
+ ut_ad(trx_sys_mutex_own());
trx_i_s_cache_clear(cache);
- fetch_data_into_cache_low(cache, FALSE, &trx_sys->rw_trx_list);
- fetch_data_into_cache_low(cache, FALSE, &trx_sys->ro_trx_list);
+ /* Capture the state of the read-write transactions. This includes
+ internal transactions too. They are not on mysql_trx_list */
+ fetch_data_into_cache_low(cache, true, &trx_sys->rw_trx_list);
- /* Only select autocommit non-locking selects because they can
- only be on the MySQL transaction list (TRUE). */
- fetch_data_into_cache_low(cache, TRUE, &trx_sys->mysql_trx_list);
+ /* Capture the state of the read-only active transactions */
+ fetch_data_into_cache_low(cache, false, &trx_sys->mysql_trx_list);
cache->is_truncated = FALSE;
}
@@ -1366,19 +1347,12 @@ fetch_data_into_cache(
/*******************************************************************//**
Update the transactions cache if it has not been read for some time.
Called from handler/i_s.cc.
-@return 0 - fetched, 1 - not */
-UNIV_INTERN
+@return 0 - fetched, 1 - not */
int
trx_i_s_possibly_fetch_data_into_cache(
/*===================================*/
trx_i_s_cache_t* cache) /*!< in/out: cache */
{
- ullint now;
-
-#ifdef UNIV_SYNC_DEBUG
- ut_a(rw_lock_own(&cache->rw_lock, RW_LOCK_EX));
-#endif
-
if (!can_cache_be_updated(cache)) {
return(1);
@@ -1388,16 +1362,16 @@ trx_i_s_possibly_fetch_data_into_cache(
lock_mutex_enter();
- mutex_enter(&trx_sys->mutex);
+ trx_sys_mutex_enter();
fetch_data_into_cache(cache);
- mutex_exit(&trx_sys->mutex);
+ trx_sys_mutex_exit();
lock_mutex_exit();
/* update cache last read time */
- now = ut_time_us(NULL);
+ time_t now = ut_time_us(NULL);
cache->last_read = now;
return(0);
@@ -1406,8 +1380,7 @@ trx_i_s_possibly_fetch_data_into_cache(
/*******************************************************************//**
Returns TRUE if the data in the cache is truncated due to the memory
limit posed by TRX_I_S_MEM_LIMIT.
-@return TRUE if truncated */
-UNIV_INTERN
+@return TRUE if truncated */
ibool
trx_i_s_cache_is_truncated(
/*=======================*/
@@ -1418,7 +1391,6 @@ trx_i_s_cache_is_truncated(
/*******************************************************************//**
Initialize INFORMATION SCHEMA trx related cache. */
-UNIV_INTERN
void
trx_i_s_cache_init(
/*===============*/
@@ -1430,13 +1402,20 @@ trx_i_s_cache_init(
release lock mutex
release trx_i_s_cache_t::rw_lock
acquire trx_i_s_cache_t::rw_lock, S
+ acquire trx_i_s_cache_t::last_read_mutex
+ release trx_i_s_cache_t::last_read_mutex
release trx_i_s_cache_t::rw_lock */
- rw_lock_create(trx_i_s_cache_lock_key, &cache->rw_lock,
+ cache->rw_lock = static_cast<rw_lock_t*>(
+ ut_malloc_nokey(sizeof(*cache->rw_lock)));
+
+ rw_lock_create(trx_i_s_cache_lock_key, cache->rw_lock,
SYNC_TRX_I_S_RWLOCK);
cache->last_read = 0;
+ mutex_create(LATCH_ID_CACHE_LAST_READ, &cache->last_read_mutex);
+
table_cache_init(&cache->innodb_trx, sizeof(i_s_trx_row_t));
table_cache_init(&cache->innodb_locks, sizeof(i_s_locks_row_t));
table_cache_init(&cache->innodb_lock_waits,
@@ -1454,75 +1433,79 @@ trx_i_s_cache_init(
/*******************************************************************//**
Free the INFORMATION SCHEMA trx related cache. */
-UNIV_INTERN
void
trx_i_s_cache_free(
/*===============*/
trx_i_s_cache_t* cache) /*!< in, own: cache to free */
{
+ rw_lock_free(cache->rw_lock);
+ ut_free(cache->rw_lock);
+ cache->rw_lock = NULL;
+
+ mutex_free(&cache->last_read_mutex);
+
hash_table_free(cache->locks_hash);
ha_storage_free(cache->storage);
table_cache_free(&cache->innodb_trx);
table_cache_free(&cache->innodb_locks);
table_cache_free(&cache->innodb_lock_waits);
- memset(cache, 0, sizeof *cache);
}
/*******************************************************************//**
Issue a shared/read lock on the tables cache. */
-UNIV_INTERN
void
trx_i_s_cache_start_read(
/*=====================*/
trx_i_s_cache_t* cache) /*!< in: cache */
{
- rw_lock_s_lock(&cache->rw_lock);
+ rw_lock_s_lock(cache->rw_lock);
}
/*******************************************************************//**
Release a shared/read lock on the tables cache. */
-UNIV_INTERN
void
trx_i_s_cache_end_read(
/*===================*/
trx_i_s_cache_t* cache) /*!< in: cache */
{
-#ifdef UNIV_SYNC_DEBUG
- ut_a(rw_lock_own(&cache->rw_lock, RW_LOCK_SHARED));
-#endif
+ uintmax_t now;
+
+ ut_ad(rw_lock_own(cache->rw_lock, RW_LOCK_S));
- rw_lock_s_unlock(&cache->rw_lock);
+ /* update cache last read time */
+ now = ut_time_us(NULL);
+ mutex_enter(&cache->last_read_mutex);
+ cache->last_read = now;
+ mutex_exit(&cache->last_read_mutex);
+
+ rw_lock_s_unlock(cache->rw_lock);
}
/*******************************************************************//**
Issue an exclusive/write lock on the tables cache. */
-UNIV_INTERN
void
trx_i_s_cache_start_write(
/*======================*/
trx_i_s_cache_t* cache) /*!< in: cache */
{
- rw_lock_x_lock(&cache->rw_lock);
+ rw_lock_x_lock(cache->rw_lock);
}
/*******************************************************************//**
Release an exclusive/write lock on the tables cache. */
-UNIV_INTERN
void
trx_i_s_cache_end_write(
/*====================*/
trx_i_s_cache_t* cache) /*!< in: cache */
{
-#ifdef UNIV_SYNC_DEBUG
- ut_a(rw_lock_own(&cache->rw_lock, RW_LOCK_EX));
-#endif
+ ut_ad(rw_lock_own(cache->rw_lock, RW_LOCK_X));
- rw_lock_x_unlock(&cache->rw_lock);
+ rw_lock_x_unlock(cache->rw_lock);
}
/*******************************************************************//**
Selects a INFORMATION SCHEMA table cache from the whole cache.
-@return table cache */
+@return table cache */
static
i_s_table_cache_t*
cache_select_table(
@@ -1532,10 +1515,8 @@ cache_select_table(
{
i_s_table_cache_t* table_cache;
-#ifdef UNIV_SYNC_DEBUG
- ut_a(rw_lock_own(&cache->rw_lock, RW_LOCK_SHARED)
- || rw_lock_own(&cache->rw_lock, RW_LOCK_EX));
-#endif
+ ut_ad(rw_lock_own(cache->rw_lock, RW_LOCK_S)
+ || rw_lock_own(cache->rw_lock, RW_LOCK_X));
switch (table) {
case I_S_INNODB_TRX:
@@ -1557,8 +1538,7 @@ cache_select_table(
/*******************************************************************//**
Retrieves the number of used rows in the cache for a given
INFORMATION SCHEMA table.
-@return number of rows */
-UNIV_INTERN
+@return number of rows */
ulint
trx_i_s_cache_get_rows_used(
/*========================*/
@@ -1575,8 +1555,7 @@ trx_i_s_cache_get_rows_used(
/*******************************************************************//**
Retrieves the nth row (zero-based) in the cache for a given
INFORMATION SCHEMA table.
-@return row */
-UNIV_INTERN
+@return row */
void*
trx_i_s_cache_get_nth_row(
/*======================*/
@@ -1616,8 +1595,7 @@ Crafts a lock id string from a i_s_locks_row_t object. Returns its
second argument. This function aborts if there is not enough space in
lock_id. Be sure to provide at least TRX_I_S_LOCK_ID_MAX_LEN + 1 if you
want to be 100% sure that it will not abort.
-@return resulting lock id */
-UNIV_INTERN
+@return resulting lock id */
char*
trx_i_s_create_lock_id(
/*===================*/
@@ -1639,7 +1617,7 @@ trx_i_s_create_lock_id(
} else {
/* table lock */
res_len = ut_snprintf(lock_id, lock_id_size,
- TRX_ID_FMT ":" UINT64PF,
+ TRX_ID_FMT":" UINT64PF,
row->lock_trx_id,
row->lock_table_id);
}