Commit 2f7bcc7d authored by marko's avatar marko

branches/zip: In hash table lookups, assert that the traversed items

satisfy some conditions when UNIV_DEBUG is defined.

HASH_SEARCH(): New parameter: ASSERTION. All users will pass an appropriate
ut_ad() or nothing.

dict_table_add_to_columns(): Assert that the table being added to the data
dictionary cache is not already being pointed to by the name_hash and
id_hash tables.

HASH_SEARCH_ALL(): New macro, for use in dict_table_add_to_columns().

dict_mem_table_free(): Set ut_d(table->cached = FALSE), so that we can
check ut_ad(table->cached) when traversing the hash tables, as in
HASH_SEARCH(name_hash, dict_sys->table_hash, ...) and
HASH_SEARCH(id_hash, dict_sys->table_id_hash, ...).

dict_table_get_low(), dict_table_get_on_id_low(): Assert
ut_ad(!table || table->cached).

fil_space_get_by_id(): Check ut_ad(space->magic_n == FIL_SPACE_MAGIC_N)
in HASH_SEARCH(hash, fil_system->spaces, ...).

fil_space_get_by_name(): Check ut_ad(space->magic_n == FIL_SPACE_MAGIC_N)
in HASH_SEARCH(name_hash, fil_system->name_hash, ...).

buf_buddy_block_free(): Check that the blocks are in valid state in
HASH_SEARCH(hash, buf_pool->zip_hash, ...).

buf_page_hash_get(): Check that the blocks are in valid state in
HASH_SEARCH(hash, buf_pool->page_hash, ...).

get_share(), free_share(): Check ut_ad(share->use_count > 0) in
HASH_SEARCH(table_name_hash, innobase_open_tables, ...).

This was posted as rb://75 for tracking down errors similar to Issue #153.
parent 108ac96c
2009-01-13 The InnoDB Team
* include/hash0hash.h, include/dict0dict.ic, dict/dict0dict.c,
include/buf0buf.ic, buf/buf0buddy.c, trx/trx0i_s.c,
handler/ha_innodb.cc, handler/win_delay_loader.cc,
dict/dict0mem.c, ha/ha0storage.c, thr/thr0loc.c, fil/fil0fil.c:
Add the parameter ASSERTION to HASH_SEARCH() macro, and use it for
light validation of the traversed items in hash table lookups when
UNIV_DEBUG is enabled.
2009-01-09 The InnoDB Team 2009-01-09 The InnoDB Team
* include/buf0flu.h, include/buf0flu.ic, buf/buf0flu.c: * include/buf0flu.h, include/buf0flu.ic, buf/buf0flu.c:
......
...@@ -172,6 +172,8 @@ buf_buddy_block_free( ...@@ -172,6 +172,8 @@ buf_buddy_block_free(
ut_a(!ut_align_offset(buf, UNIV_PAGE_SIZE)); ut_a(!ut_align_offset(buf, UNIV_PAGE_SIZE));
HASH_SEARCH(hash, buf_pool->zip_hash, fold, buf_page_t*, bpage, HASH_SEARCH(hash, buf_pool->zip_hash, fold, buf_page_t*, bpage,
ut_ad(buf_page_get_state(bpage) == BUF_BLOCK_MEMORY
&& bpage->in_zip_hash && !bpage->in_page_hash),
((buf_block_t*) bpage)->frame == buf); ((buf_block_t*) bpage)->frame == buf);
ut_a(bpage); ut_a(bpage);
ut_a(buf_page_get_state(bpage) == BUF_BLOCK_MEMORY); ut_a(buf_page_get_state(bpage) == BUF_BLOCK_MEMORY);
......
...@@ -751,18 +751,34 @@ dict_table_add_to_cache( ...@@ -751,18 +751,34 @@ dict_table_add_to_cache(
{ {
dict_table_t* table2; dict_table_t* table2;
HASH_SEARCH(name_hash, dict_sys->table_hash, fold, HASH_SEARCH(name_hash, dict_sys->table_hash, fold,
dict_table_t*, table2, dict_table_t*, table2, ut_ad(table2->cached),
(ut_strcmp(table2->name, table->name) == 0)); ut_strcmp(table2->name, table->name) == 0);
ut_a(table2 == NULL); ut_a(table2 == NULL);
#ifdef UNIV_DEBUG
/* Look for the same table pointer with a different name */
HASH_SEARCH_ALL(name_hash, dict_sys->table_hash,
dict_table_t*, table2, ut_ad(table2->cached),
table2 == table);
ut_ad(table2 == NULL);
#endif /* UNIV_DEBUG */
} }
/* Look for a table with the same id: error if such exists */ /* Look for a table with the same id: error if such exists */
{ {
dict_table_t* table2; dict_table_t* table2;
HASH_SEARCH(id_hash, dict_sys->table_id_hash, id_fold, HASH_SEARCH(id_hash, dict_sys->table_id_hash, id_fold,
dict_table_t*, table2, dict_table_t*, table2, ut_ad(table2->cached),
(ut_dulint_cmp(table2->id, table->id) == 0)); ut_dulint_cmp(table2->id, table->id) == 0);
ut_a(table2 == NULL); ut_a(table2 == NULL);
#ifdef UNIV_DEBUG
/* Look for the same table pointer with a different id */
HASH_SEARCH_ALL(id_hash, dict_sys->table_id_hash,
dict_table_t*, table2, ut_ad(table2->cached),
table2 == table);
ut_ad(table2 == NULL);
#endif /* UNIV_DEBUG */
} }
/* Add table to hash table of tables */ /* Add table to hash table of tables */
...@@ -844,7 +860,7 @@ dict_table_rename_in_cache( ...@@ -844,7 +860,7 @@ dict_table_rename_in_cache(
{ {
dict_table_t* table2; dict_table_t* table2;
HASH_SEARCH(name_hash, dict_sys->table_hash, fold, HASH_SEARCH(name_hash, dict_sys->table_hash, fold,
dict_table_t*, table2, dict_table_t*, table2, ut_ad(table2->cached),
(ut_strcmp(table2->name, new_name) == 0)); (ut_strcmp(table2->name, new_name) == 0));
if (UNIV_LIKELY_NULL(table2)) { if (UNIV_LIKELY_NULL(table2)) {
ut_print_timestamp(stderr); ut_print_timestamp(stderr);
......
...@@ -84,6 +84,7 @@ dict_mem_table_free( ...@@ -84,6 +84,7 @@ dict_mem_table_free(
{ {
ut_ad(table); ut_ad(table);
ut_ad(table->magic_n == DICT_TABLE_MAGIC_N); ut_ad(table->magic_n == DICT_TABLE_MAGIC_N);
ut_d(table->cached = FALSE);
mutex_free(&(table->autoinc_mutex)); mutex_free(&(table->autoinc_mutex));
mem_heap_free(table->heap); mem_heap_free(table->heap);
......
...@@ -363,7 +363,9 @@ fil_space_get_by_id( ...@@ -363,7 +363,9 @@ fil_space_get_by_id(
ut_ad(mutex_own(&fil_system->mutex)); ut_ad(mutex_own(&fil_system->mutex));
HASH_SEARCH(hash, fil_system->spaces, id, HASH_SEARCH(hash, fil_system->spaces, id,
fil_space_t*, space, space->id == id); fil_space_t*, space,
ut_ad(space->magic_n == FIL_SPACE_MAGIC_N),
space->id == id);
return(space); return(space);
} }
...@@ -384,7 +386,9 @@ fil_space_get_by_name( ...@@ -384,7 +386,9 @@ fil_space_get_by_name(
fold = ut_fold_string(name); fold = ut_fold_string(name);
HASH_SEARCH(name_hash, fil_system->name_hash, fold, HASH_SEARCH(name_hash, fil_system->name_hash, fold,
fil_space_t*, space, !strcmp(name, space->name)); fil_space_t*, space,
ut_ad(space->magic_n == FIL_SPACE_MAGIC_N),
!strcmp(name, space->name));
return(space); return(space);
} }
......
...@@ -45,6 +45,7 @@ ha_storage_get( ...@@ -45,6 +45,7 @@ ha_storage_get(
fold, /* key */ fold, /* key */
ha_storage_node_t*, /* type of node->next */ ha_storage_node_t*, /* type of node->next */
node, /* auxiliary variable */ node, /* auxiliary variable */
, /* assertion */
IS_FOUND); /* search criteria */ IS_FOUND); /* search criteria */
if (node == NULL) { if (node == NULL) {
......
...@@ -8164,6 +8164,7 @@ static INNOBASE_SHARE* get_share(const char* table_name) ...@@ -8164,6 +8164,7 @@ static INNOBASE_SHARE* get_share(const char* table_name)
HASH_SEARCH(table_name_hash, innobase_open_tables, fold, HASH_SEARCH(table_name_hash, innobase_open_tables, fold,
INNOBASE_SHARE*, share, INNOBASE_SHARE*, share,
ut_ad(share->use_count > 0),
!my_strnncoll(system_charset_info, !my_strnncoll(system_charset_info,
share->table_name, share->table_name,
share->table_name_length, share->table_name_length,
...@@ -8205,6 +8206,7 @@ static void free_share(INNOBASE_SHARE* share) ...@@ -8205,6 +8206,7 @@ static void free_share(INNOBASE_SHARE* share)
HASH_SEARCH(table_name_hash, innobase_open_tables, fold, HASH_SEARCH(table_name_hash, innobase_open_tables, fold,
INNOBASE_SHARE*, share2, INNOBASE_SHARE*, share2,
ut_ad(share->use_count > 0),
!my_strnncoll(system_charset_info, !my_strnncoll(system_charset_info,
share->table_name, share->table_name,
share->table_name_length, share->table_name_length,
......
...@@ -453,6 +453,7 @@ wdl_get_procaddr_from_map( ...@@ -453,6 +453,7 @@ wdl_get_procaddr_from_map(
map_fold, map_fold,
map_hash_chain_t*, map_hash_chain_t*,
hash_chain, hash_chain,
,
(ut_strcmp(hash_chain->symbol, import_proc) == 0)); (ut_strcmp(hash_chain->symbol, import_proc) == 0));
if (hash_chain == NULL) { if (hash_chain == NULL) {
...@@ -472,6 +473,7 @@ wdl_get_procaddr_from_map( ...@@ -472,6 +473,7 @@ wdl_get_procaddr_from_map(
map_fold, map_fold,
map_hash_chain_t*, map_hash_chain_t*,
hash_chain, hash_chain,
,
(ut_strcmp(hash_chain->symbol, import_proc) == 0)); (ut_strcmp(hash_chain->symbol, import_proc) == 0));
if (hash_chain == NULL) { if (hash_chain == NULL) {
...@@ -515,6 +517,7 @@ wdl_get_varaddr_from_map( ...@@ -515,6 +517,7 @@ wdl_get_varaddr_from_map(
map_fold, map_fold,
map_hash_chain_t*, map_hash_chain_t*,
hash_chain, hash_chain,
,
(ut_strcmp(hash_chain->symbol, import_variable) == 0)); (ut_strcmp(hash_chain->symbol, import_variable) == 0));
if (hash_chain == NULL) { if (hash_chain == NULL) {
...@@ -534,6 +537,7 @@ wdl_get_varaddr_from_map( ...@@ -534,6 +537,7 @@ wdl_get_varaddr_from_map(
map_fold, map_fold,
map_hash_chain_t*, map_hash_chain_t*,
hash_chain, hash_chain,
,
(ut_strcmp(hash_chain->symbol, import_variable) == 0)); (ut_strcmp(hash_chain->symbol, import_variable) == 0));
if (hash_chain == NULL) { if (hash_chain == NULL) {
......
...@@ -928,6 +928,8 @@ buf_page_hash_get( ...@@ -928,6 +928,8 @@ buf_page_hash_get(
fold = buf_page_address_fold(space, offset); fold = buf_page_address_fold(space, offset);
HASH_SEARCH(hash, buf_pool->page_hash, fold, buf_page_t*, bpage, HASH_SEARCH(hash, buf_pool->page_hash, fold, buf_page_t*, bpage,
ut_ad(bpage->in_page_hash && !bpage->in_zip_hash
&& buf_page_in_file(bpage)),
bpage->space == space && bpage->offset == offset); bpage->space == space && bpage->offset == offset);
if (bpage) { if (bpage) {
ut_a(buf_page_in_file(bpage)); ut_a(buf_page_in_file(bpage));
......
...@@ -720,7 +720,8 @@ dict_table_check_if_in_cache_low( ...@@ -720,7 +720,8 @@ dict_table_check_if_in_cache_low(
table_fold = ut_fold_string(table_name); table_fold = ut_fold_string(table_name);
HASH_SEARCH(name_hash, dict_sys->table_hash, table_fold, HASH_SEARCH(name_hash, dict_sys->table_hash, table_fold,
dict_table_t*, table, !strcmp(table->name, table_name)); dict_table_t*, table, ut_ad(table->cached),
!strcmp(table->name, table_name));
return(table); return(table);
} }
...@@ -745,6 +746,8 @@ dict_table_get_low( ...@@ -745,6 +746,8 @@ dict_table_get_low(
table = dict_load_table(table_name); table = dict_load_table(table_name);
} }
ut_ad(!table || table->cached);
return(table); return(table);
} }
...@@ -766,11 +769,14 @@ dict_table_get_on_id_low( ...@@ -766,11 +769,14 @@ dict_table_get_on_id_low(
fold = ut_fold_dulint(table_id); fold = ut_fold_dulint(table_id);
HASH_SEARCH(id_hash, dict_sys->table_id_hash, fold, HASH_SEARCH(id_hash, dict_sys->table_id_hash, fold,
dict_table_t*, table, !ut_dulint_cmp(table->id, table_id)); dict_table_t*, table, ut_ad(table->cached),
!ut_dulint_cmp(table->id, table_id));
if (table == NULL) { if (table == NULL) {
table = dict_load_table_on_id(table_id); table = dict_load_table_on_id(table_id);
} }
ut_ad(!table || table->cached);
/* TODO: should get the type information from MySQL */ /* TODO: should get the type information from MySQL */
return(table); return(table);
......
...@@ -147,7 +147,7 @@ Gets the next struct in a hash chain, NULL if none. */ ...@@ -147,7 +147,7 @@ Gets the next struct in a hash chain, NULL if none. */
/************************************************************************ /************************************************************************
Looks for a struct in a hash table. */ Looks for a struct in a hash table. */
#define HASH_SEARCH(NAME, TABLE, FOLD, TYPE, DATA, TEST)\ #define HASH_SEARCH(NAME, TABLE, FOLD, TYPE, DATA, ASSERTION, TEST)\
{\ {\
\ \
HASH_ASSERT_OWNED(TABLE, FOLD)\ HASH_ASSERT_OWNED(TABLE, FOLD)\
...@@ -156,6 +156,7 @@ Looks for a struct in a hash table. */ ...@@ -156,6 +156,7 @@ Looks for a struct in a hash table. */
HASH_ASSERT_VALID(DATA);\ HASH_ASSERT_VALID(DATA);\
\ \
while ((DATA) != NULL) {\ while ((DATA) != NULL) {\
ASSERTION;\
if (TEST) {\ if (TEST) {\
break;\ break;\
} else {\ } else {\
...@@ -165,6 +166,32 @@ Looks for a struct in a hash table. */ ...@@ -165,6 +166,32 @@ Looks for a struct in a hash table. */
}\ }\
} }
/************************************************************************
Looks for an item in all hash buckets. */
#define HASH_SEARCH_ALL(NAME, TABLE, TYPE, DATA, ASSERTION, TEST) \
do { \
ulint i3333; \
\
for (i3333 = (TABLE)->n_cells; i3333--; ) { \
(DATA) = (TYPE) HASH_GET_FIRST(TABLE, i3333); \
\
while ((DATA) != NULL) { \
HASH_ASSERT_VALID(DATA); \
ASSERTION; \
\
if (TEST) { \
break; \
} \
\
(DATA) = (TYPE) HASH_GET_NEXT(NAME, DATA); \
} \
\
if ((DATA) != NULL) { \
break; \
} \
} \
} while (0)
/**************************************************************** /****************************************************************
Gets the nth cell in a hash table. */ Gets the nth cell in a hash table. */
UNIV_INLINE UNIV_INLINE
......
...@@ -71,7 +71,7 @@ thr_local_get( ...@@ -71,7 +71,7 @@ thr_local_get(
local = NULL; local = NULL;
HASH_SEARCH(hash, thr_local_hash, os_thread_pf(id), HASH_SEARCH(hash, thr_local_hash, os_thread_pf(id),
thr_local_t*, local, os_thread_eq(local->id, id)); thr_local_t*, local,, os_thread_eq(local->id, id));
if (local == NULL) { if (local == NULL) {
mutex_exit(&thr_local_mutex); mutex_exit(&thr_local_mutex);
...@@ -195,7 +195,7 @@ thr_local_free( ...@@ -195,7 +195,7 @@ thr_local_free(
/* Look for the local struct in the hash table */ /* Look for the local struct in the hash table */
HASH_SEARCH(hash, thr_local_hash, os_thread_pf(id), HASH_SEARCH(hash, thr_local_hash, os_thread_pf(id),
thr_local_t*, local, os_thread_eq(local->id, id)); thr_local_t*, local,, os_thread_eq(local->id, id));
if (local == NULL) { if (local == NULL) {
mutex_exit(&thr_local_mutex); mutex_exit(&thr_local_mutex);
......
...@@ -821,6 +821,8 @@ search_innodb_locks( ...@@ -821,6 +821,8 @@ search_innodb_locks(
i_s_hash_chain_t*, i_s_hash_chain_t*,
/* auxiliary variable */ /* auxiliary variable */
hash_chain, hash_chain,
/* assertion on every traversed item */
,
/* this determines if we have found the lock */ /* this determines if we have found the lock */
locks_row_eq_lock(hash_chain->value, lock, heap_no)); locks_row_eq_lock(hash_chain->value, lock, heap_no));
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment