mirror of
https://github.com/MariaDB/server.git
synced 2025-11-10 15:56:13 +01:00
Since commit bd5a6403ca (MDEV-26033)
we can actually calculate the buf_pool.page_hash cell and latch
addresses while not holding buf_pool.mutex.
buf_page_alloc_descriptor(): Remove the MEM_UNDEFINED.
We now expect buf_page_t::hash to be zero-initialized.
buf_pool_t::hash_chain: Dedicated data type for buf_pool.page_hash.array.
buf_LRU_free_one_page(): Merged to the only caller
buf_pool_t::corrupted_evict().
197 lines
5.4 KiB
C
197 lines
5.4 KiB
C
/*****************************************************************************
|
|
|
|
Copyright (c) 1997, 2016, Oracle and/or its affiliates. All Rights Reserved.
|
|
Copyright (c) 2018, 2021, MariaDB Corporation.
|
|
|
|
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.,
|
|
51 Franklin Street, Fifth Floor, Boston, MA 02110-1335 USA
|
|
|
|
*****************************************************************************/
|
|
|
|
/**************************************************//**
|
|
@file include/hash0hash.h
|
|
The simple hash table utility
|
|
|
|
Created 5/20/1997 Heikki Tuuri
|
|
*******************************************************/
|
|
|
|
#pragma once
|
|
#include "ut0rnd.h"
|
|
#include "ut0new.h"
|
|
|
|
struct hash_table_t;
|
|
struct hash_cell_t{
|
|
void* node; /*!< hash chain node, NULL if none */
|
|
};
|
|
|
|
/*******************************************************************//**
|
|
Inserts a struct to a hash table. */
|
|
|
|
#define HASH_INSERT(TYPE, NAME, TABLE, FOLD, DATA)\
|
|
do {\
|
|
hash_cell_t* cell3333;\
|
|
TYPE* struct3333;\
|
|
\
|
|
(DATA)->NAME = NULL;\
|
|
\
|
|
cell3333 = &(TABLE)->array[(TABLE)->calc_hash(FOLD)]; \
|
|
\
|
|
if (cell3333->node == NULL) {\
|
|
cell3333->node = DATA;\
|
|
} else {\
|
|
struct3333 = (TYPE*) cell3333->node;\
|
|
\
|
|
while (struct3333->NAME != NULL) {\
|
|
\
|
|
struct3333 = (TYPE*) struct3333->NAME;\
|
|
}\
|
|
\
|
|
struct3333->NAME = DATA;\
|
|
}\
|
|
} while (0)
|
|
|
|
/*******************************************************************//**
|
|
Inserts a struct to the head of hash table. */
|
|
|
|
#define HASH_PREPEND(TYPE, NAME, TABLE, FOLD, DATA) \
|
|
do { \
|
|
hash_cell_t* cell3333; \
|
|
TYPE* struct3333; \
|
|
\
|
|
(DATA)->NAME = NULL; \
|
|
\
|
|
cell3333 = &(TABLE)->array[(TABLE)->calc_hash(FOLD)]; \
|
|
\
|
|
if (cell3333->node == NULL) { \
|
|
cell3333->node = DATA; \
|
|
DATA->NAME = NULL; \
|
|
} else { \
|
|
struct3333 = (TYPE*) cell3333->node; \
|
|
\
|
|
DATA->NAME = struct3333; \
|
|
\
|
|
cell3333->node = DATA; \
|
|
} \
|
|
} while (0)
|
|
#ifdef UNIV_HASH_DEBUG
|
|
# define HASH_ASSERT_VALID(DATA) ut_a((void*) (DATA) != (void*) -1)
|
|
# define HASH_INVALIDATE(DATA, NAME) *(void**) (&DATA->NAME) = (void*) -1
|
|
#else
|
|
# define HASH_ASSERT_VALID(DATA) do {} while (0)
|
|
# define HASH_INVALIDATE(DATA, NAME) do {} while (0)
|
|
#endif
|
|
|
|
/*******************************************************************//**
|
|
Deletes a struct from a hash table. */
|
|
|
|
#define HASH_DELETE(TYPE, NAME, TABLE, FOLD, DATA)\
|
|
do {\
|
|
hash_cell_t* cell3333;\
|
|
TYPE* struct3333;\
|
|
\
|
|
cell3333 = &(TABLE)->array[(TABLE)->calc_hash(FOLD)]; \
|
|
\
|
|
if (cell3333->node == DATA) {\
|
|
HASH_ASSERT_VALID(DATA->NAME);\
|
|
cell3333->node = DATA->NAME;\
|
|
} else {\
|
|
struct3333 = (TYPE*) cell3333->node;\
|
|
\
|
|
while (struct3333->NAME != DATA) {\
|
|
\
|
|
struct3333 = (TYPE*) struct3333->NAME;\
|
|
ut_a(struct3333);\
|
|
}\
|
|
\
|
|
struct3333->NAME = DATA->NAME;\
|
|
}\
|
|
HASH_INVALIDATE(DATA, NAME);\
|
|
} while (0)
|
|
|
|
/*******************************************************************//**
|
|
Gets the first struct in a hash chain, NULL if none. */
|
|
|
|
#define HASH_GET_FIRST(TABLE, HASH_VAL) (TABLE)->array[HASH_VAL].node
|
|
|
|
/*******************************************************************//**
|
|
Gets the next struct in a hash chain, NULL if none. */
|
|
|
|
#define HASH_GET_NEXT(NAME, DATA) ((DATA)->NAME)
|
|
|
|
/********************************************************************//**
|
|
Looks for a struct in a hash table. */
|
|
#define HASH_SEARCH(NAME, TABLE, FOLD, TYPE, DATA, ASSERTION, TEST)\
|
|
{\
|
|
(DATA) = (TYPE) HASH_GET_FIRST(TABLE, (TABLE)->calc_hash(FOLD)); \
|
|
HASH_ASSERT_VALID(DATA);\
|
|
\
|
|
while ((DATA) != NULL) {\
|
|
ASSERTION;\
|
|
if (TEST) {\
|
|
break;\
|
|
} else {\
|
|
HASH_ASSERT_VALID(HASH_GET_NEXT(NAME, DATA));\
|
|
(DATA) = (TYPE) HASH_GET_NEXT(NAME, DATA);\
|
|
}\
|
|
}\
|
|
}
|
|
|
|
/********************************************************************//**
|
|
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)
|
|
|
|
/** Hash table with singly-linked overflow lists */
|
|
struct hash_table_t
|
|
{
|
|
/** number of elements in array (a prime number) */
|
|
ulint n_cells;
|
|
/** the hash array */
|
|
hash_cell_t *array;
|
|
|
|
/** Create the hash table.
|
|
@param n the lower bound of n_cells */
|
|
void create(ulint n)
|
|
{
|
|
n_cells= ut_find_prime(n);
|
|
array= static_cast<hash_cell_t*>(ut_zalloc_nokey(n_cells * sizeof *array));
|
|
}
|
|
|
|
/** Clear the hash table. */
|
|
void clear() { memset(array, 0, n_cells * sizeof *array); }
|
|
|
|
/** Free the hash table. */
|
|
void free() { ut_free(array); array= nullptr; }
|
|
|
|
ulint calc_hash(ulint fold) const { return ut_hash_ulint(fold, n_cells); }
|
|
};
|