summaryrefslogtreecommitdiff
path: root/storage/innobase/ha/ha0ha.c
diff options
context:
space:
mode:
Diffstat (limited to 'storage/innobase/ha/ha0ha.c')
-rw-r--r--storage/innobase/ha/ha0ha.c275
1 files changed, 168 insertions, 107 deletions
diff --git a/storage/innobase/ha/ha0ha.c b/storage/innobase/ha/ha0ha.c
index 077497493b4..cb5e541b55d 100644
--- a/storage/innobase/ha/ha0ha.c
+++ b/storage/innobase/ha/ha0ha.c
@@ -1,7 +1,24 @@
-/************************************************************************
-The hash table with external chains
+/*****************************************************************************
+
+Copyright (c) 1994, 2009, Innobase Oy. All Rights Reserved.
+
+This program is free software; you can redistribute it and/or modify it under
+the terms of the GNU General Public License as published by the Free Software
+Foundation; version 2 of the License.
+
+This program is distributed in the hope that it will be useful, but WITHOUT
+ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License along with
+this program; if not, write to the Free Software Foundation, Inc., 59 Temple
+Place, Suite 330, Boston, MA 02111-1307 USA
+
+*****************************************************************************/
-(c) 1994-1997 Innobase Oy
+/********************************************************************//**
+@file ha/ha0ha.c
+The hash table with external chains
Created 8/22/1994 Heikki Tuuri
*************************************************************************/
@@ -11,92 +28,129 @@ Created 8/22/1994 Heikki Tuuri
#include "ha0ha.ic"
#endif
-#include "buf0buf.h"
-
-/*****************************************************************
-Creates a hash table with >= n array cells. The actual number of cells is
-chosen to be a prime number slightly bigger than n. */
+#ifdef UNIV_DEBUG
+# include "buf0buf.h"
+#endif /* UNIV_DEBUG */
+#ifdef UNIV_SYNC_DEBUG
+# include "btr0sea.h"
+#endif /* UNIV_SYNC_DEBUG */
+#include "page0page.h"
+/*************************************************************//**
+Creates a hash table with at least n array cells. The actual number
+of cells is chosen to be a prime number slightly bigger than n.
+@return own: created table */
+UNIV_INTERN
hash_table_t*
ha_create_func(
/*===========*/
- /* out, own: created table */
- ibool in_btr_search, /* in: TRUE if the hash table is used in
- the btr_search module */
- ulint n, /* in: number of array cells */
+ ulint n, /*!< in: number of array cells */
#ifdef UNIV_SYNC_DEBUG
- ulint mutex_level, /* in: level of the mutexes in the latching
+ ulint mutex_level, /*!< in: level of the mutexes in the latching
order: this is used in the debug version */
#endif /* UNIV_SYNC_DEBUG */
- ulint n_mutexes) /* in: number of mutexes to protect the
+ ulint n_mutexes) /*!< in: number of mutexes to protect the
hash table: must be a power of 2, or 0 */
{
hash_table_t* table;
+#ifndef UNIV_HOTBACKUP
ulint i;
+#endif /* !UNIV_HOTBACKUP */
+ ut_ad(ut_is_2pow(n_mutexes));
table = hash_create(n);
- if (in_btr_search) {
- table->adaptive = TRUE;
- } else {
- table->adaptive = FALSE;
- }
-
+#if defined UNIV_AHI_DEBUG || defined UNIV_DEBUG
+# ifndef UNIV_HOTBACKUP
+ table->adaptive = TRUE;
+# endif /* !UNIV_HOTBACKUP */
+#endif /* UNIV_AHI_DEBUG || UNIV_DEBUG */
/* Creating MEM_HEAP_BTR_SEARCH type heaps can potentially fail,
but in practise it never should in this case, hence the asserts. */
if (n_mutexes == 0) {
- if (in_btr_search) {
- table->heap = mem_heap_create_in_btr_search(4096);
- ut_a(table->heap);
- } else {
- table->heap = mem_heap_create_in_buffer(4096);
- }
+ table->heap = mem_heap_create_in_btr_search(
+ ut_min(4096, MEM_MAX_ALLOC_IN_BUF));
+ ut_a(table->heap);
return(table);
}
+#ifndef UNIV_HOTBACKUP
hash_create_mutexes(table, n_mutexes, mutex_level);
table->heaps = mem_alloc(n_mutexes * sizeof(void*));
for (i = 0; i < n_mutexes; i++) {
- if (in_btr_search) {
- table->heaps[i] = mem_heap_create_in_btr_search(4096);
- ut_a(table->heaps[i]);
- } else {
- table->heaps[i] = mem_heap_create_in_buffer(4096);
- }
+ table->heaps[i] = mem_heap_create_in_btr_search(4096);
+ ut_a(table->heaps[i]);
}
+#endif /* !UNIV_HOTBACKUP */
return(table);
}
-/*****************************************************************
+/*************************************************************//**
+Empties a hash table and frees the memory heaps. */
+UNIV_INTERN
+void
+ha_clear(
+/*=====*/
+ hash_table_t* table) /*!< in, own: hash table */
+{
+ ulint i;
+ ulint n;
+
+#ifdef UNIV_SYNC_DEBUG
+ ut_ad(rw_lock_own(&btr_search_latch, RW_LOCK_EXCLUSIVE));
+#endif /* UNIV_SYNC_DEBUG */
+
+#ifndef UNIV_HOTBACKUP
+ /* Free the memory heaps. */
+ n = table->n_mutexes;
+
+ for (i = 0; i < n; i++) {
+ mem_heap_free(table->heaps[i]);
+ }
+#endif /* !UNIV_HOTBACKUP */
+
+ /* Clear the hash table. */
+ n = hash_get_n_cells(table);
+
+ for (i = 0; i < n; i++) {
+ hash_get_nth_cell(table, i)->node = NULL;
+ }
+}
+
+/*************************************************************//**
Inserts an entry into a hash table. If an entry with the same fold number
is found, its node is updated to point to the new data, and no new node
-is inserted. */
-
+is inserted.
+@return TRUE if succeed, FALSE if no more memory could be allocated */
+UNIV_INTERN
ibool
-ha_insert_for_fold(
-/*===============*/
- /* out: TRUE if succeed, FALSE if no more
- memory could be allocated */
- hash_table_t* table, /* in: hash table */
- ulint fold, /* in: folded value of data; if a node with
+ha_insert_for_fold_func(
+/*====================*/
+ hash_table_t* table, /*!< in: hash table */
+ ulint fold, /*!< in: folded value of data; if a node with
the same fold value already exists, it is
updated to point to the same data, and no new
node is created! */
- void* data) /* in: data, must not be NULL */
+#if defined UNIV_AHI_DEBUG || defined UNIV_DEBUG
+ buf_block_t* block, /*!< in: buffer block containing the data */
+#endif /* UNIV_AHI_DEBUG || UNIV_DEBUG */
+ void* data) /*!< in: data, must not be NULL */
{
hash_cell_t* cell;
ha_node_t* node;
ha_node_t* prev_node;
- buf_block_t* prev_block;
ulint hash;
ut_ad(table && data);
- ut_ad(!table->mutexes || mutex_own(hash_get_mutex(table, fold)));
+#if defined UNIV_AHI_DEBUG || defined UNIV_DEBUG
+ ut_a(block->frame == page_align(data));
+#endif /* UNIV_AHI_DEBUG || UNIV_DEBUG */
+ ASSERT_HASH_MUTEX_OWN(table, fold);
hash = hash_calc_hash(fold, table);
@@ -106,13 +160,20 @@ ha_insert_for_fold(
while (prev_node != NULL) {
if (prev_node->fold == fold) {
+#if defined UNIV_AHI_DEBUG || defined UNIV_DEBUG
+# ifndef UNIV_HOTBACKUP
if (table->adaptive) {
- prev_block = buf_block_align(prev_node->data);
+ buf_block_t* prev_block = prev_node->block;
+ ut_a(prev_block->frame
+ == page_align(prev_node->data));
ut_a(prev_block->n_pointers > 0);
prev_block->n_pointers--;
- buf_block_align(data)->n_pointers++;
+ block->n_pointers++;
}
+# endif /* !UNIV_HOTBACKUP */
+ prev_node->block = block;
+#endif /* UNIV_AHI_DEBUG || UNIV_DEBUG */
prev_node->data = data;
return(TRUE);
@@ -134,11 +195,15 @@ ha_insert_for_fold(
return(FALSE);
}
- ha_node_set_data(node, data);
+ ha_node_set_data(node, block, data);
+#if defined UNIV_AHI_DEBUG || defined UNIV_DEBUG
+# ifndef UNIV_HOTBACKUP
if (table->adaptive) {
- buf_block_align(data)->n_pointers++;
+ block->n_pointers++;
}
+# endif /* !UNIV_HOTBACKUP */
+#endif /* UNIV_AHI_DEBUG || UNIV_DEBUG */
node->fold = fold;
@@ -163,93 +228,88 @@ ha_insert_for_fold(
return(TRUE);
}
-/***************************************************************
+/***********************************************************//**
Deletes a hash node. */
-
+UNIV_INTERN
void
ha_delete_hash_node(
/*================*/
- hash_table_t* table, /* in: hash table */
- ha_node_t* del_node) /* in: node to be deleted */
+ hash_table_t* table, /*!< in: hash table */
+ ha_node_t* del_node) /*!< in: node to be deleted */
{
+#if defined UNIV_AHI_DEBUG || defined UNIV_DEBUG
+# ifndef UNIV_HOTBACKUP
if (table->adaptive) {
- ut_a(buf_block_align(del_node->data)->n_pointers > 0);
- buf_block_align(del_node->data)->n_pointers--;
+ ut_a(del_node->block->frame = page_align(del_node->data));
+ ut_a(del_node->block->n_pointers > 0);
+ del_node->block->n_pointers--;
}
+# endif /* !UNIV_HOTBACKUP */
+#endif /* UNIV_AHI_DEBUG || UNIV_DEBUG */
HASH_DELETE_AND_COMPACT(ha_node_t, next, table, del_node);
}
-/*****************************************************************
-Deletes an entry from a hash table. */
-
-void
-ha_delete(
-/*======*/
- hash_table_t* table, /* in: hash table */
- ulint fold, /* in: folded value of data */
- void* data) /* in: data, must not be NULL and must exist
- in the hash table */
-{
- ha_node_t* node;
-
- ut_ad(!table->mutexes || mutex_own(hash_get_mutex(table, fold)));
-
- node = ha_search_with_data(table, fold, data);
-
- ut_a(node);
-
- ha_delete_hash_node(table, node);
-}
-
-/*************************************************************
+/*********************************************************//**
Looks for an element when we know the pointer to the data, and updates
the pointer to data, if found. */
-
+UNIV_INTERN
void
-ha_search_and_update_if_found(
-/*==========================*/
- hash_table_t* table, /* in: hash table */
- ulint fold, /* in: folded value of the searched data */
- void* data, /* in: pointer to the data */
- void* new_data)/* in: new pointer to the data */
+ha_search_and_update_if_found_func(
+/*===============================*/
+ hash_table_t* table, /*!< in/out: hash table */
+ ulint fold, /*!< in: folded value of the searched data */
+ void* data, /*!< in: pointer to the data */
+#if defined UNIV_AHI_DEBUG || defined UNIV_DEBUG
+ buf_block_t* new_block,/*!< in: block containing new_data */
+#endif /* UNIV_AHI_DEBUG || UNIV_DEBUG */
+ void* new_data)/*!< in: new pointer to the data */
{
ha_node_t* node;
- ut_ad(!table->mutexes || mutex_own(hash_get_mutex(table, fold)));
+ ASSERT_HASH_MUTEX_OWN(table, fold);
+#if defined UNIV_AHI_DEBUG || defined UNIV_DEBUG
+ ut_a(new_block->frame == page_align(new_data));
+#endif /* UNIV_AHI_DEBUG || UNIV_DEBUG */
node = ha_search_with_data(table, fold, data);
if (node) {
+#if defined UNIV_AHI_DEBUG || defined UNIV_DEBUG
+# ifndef UNIV_HOTBACKUP
if (table->adaptive) {
- ut_a(buf_block_align(node->data)->n_pointers > 0);
- buf_block_align(node->data)->n_pointers--;
- buf_block_align(new_data)->n_pointers++;
+ ut_a(node->block->n_pointers > 0);
+ node->block->n_pointers--;
+ new_block->n_pointers++;
}
+# endif /* !UNIV_HOTBACKUP */
+ node->block = new_block;
+#endif /* UNIV_AHI_DEBUG || UNIV_DEBUG */
node->data = new_data;
}
}
-/*********************************************************************
+#ifndef UNIV_HOTBACKUP
+/*****************************************************************//**
Removes from the chain determined by fold all nodes whose data pointer
points to the page given. */
-
+UNIV_INTERN
void
ha_remove_all_nodes_to_page(
/*========================*/
- hash_table_t* table, /* in: hash table */
- ulint fold, /* in: fold value */
- page_t* page) /* in: buffer page */
+ hash_table_t* table, /*!< in: hash table */
+ ulint fold, /*!< in: fold value */
+ const page_t* page) /*!< in: buffer page */
{
ha_node_t* node;
- ut_ad(!table->mutexes || mutex_own(hash_get_mutex(table, fold)));
+ ASSERT_HASH_MUTEX_OWN(table, fold);
node = ha_chain_get_first(table, fold);
while (node) {
- if (buf_frame_align(ha_node_get_data(node)) == page) {
+ if (page_align(ha_node_get_data(node)) == page) {
/* Remove the hash node */
@@ -270,23 +330,23 @@ ha_remove_all_nodes_to_page(
node = ha_chain_get_first(table, fold);
while (node) {
- ut_a(buf_frame_align(ha_node_get_data(node)) != page);
+ ut_a(page_align(ha_node_get_data(node)) != page);
node = ha_chain_get_next(node);
}
#endif
}
-/*****************************************************************
-Validates a given range of the cells in hash table. */
-
+/*************************************************************//**
+Validates a given range of the cells in hash table.
+@return TRUE if ok */
+UNIV_INTERN
ibool
ha_validate(
/*========*/
- /* out: TRUE if ok */
- hash_table_t* table, /* in: hash table */
- ulint start_index, /* in: start index */
- ulint end_index) /* in: end index */
+ hash_table_t* table, /*!< in: hash table */
+ ulint start_index, /*!< in: start index */
+ ulint end_index) /*!< in: end index */
{
hash_cell_t* cell;
ha_node_t* node;
@@ -322,14 +382,14 @@ ha_validate(
return(ok);
}
-/*****************************************************************
+/*************************************************************//**
Prints info of a hash table. */
-
+UNIV_INTERN
void
ha_print_info(
/*==========*/
- FILE* file, /* in: file where to print */
- hash_table_t* table) /* in: hash table */
+ FILE* file, /*!< in: file where to print */
+ hash_table_t* table) /*!< in: hash table */
{
#ifdef UNIV_DEBUG
/* Some of the code here is disabled for performance reasons in production
@@ -378,3 +438,4 @@ builds, see http://bugs.mysql.com/36941 */
(ulong) n_bufs);
}
}
+#endif /* !UNIV_HOTBACKUP */