Commit 5a3d78d8 authored by Nikita Malyavin's avatar Nikita Malyavin

adapt mysys hash

parent 188db687
......@@ -56,6 +56,7 @@ typedef struct st_hash {
DYNAMIC_ARRAY array; /* Place for hash_keys */
my_hash_get_key get_key;
my_hash_function hash_function;
int (*keycmp)(const uchar*, const uchar*);
void (*free)(void *);
CHARSET_INFO *charset;
} HASH;
......@@ -69,6 +70,24 @@ my_bool my_hash_init2(PSI_memory_key psi_key, HASH *hash, size_t growth_size,
size_t key_offset, size_t key_length,
my_hash_get_key get_key, my_hash_function hash_function,
void (*free_element)(void*), uint flags);
inline static
my_bool my_hash_init3(PSI_memory_key psi_key, HASH *hash, size_t growth_size,
CHARSET_INFO *charset, size_t default_array_elements,
size_t key_offset, size_t key_length,
my_hash_get_key get_key, my_hash_function hash_function,
void (*free_element)(void*),
int (*keycmp)(const uchar*, const uchar*),
uint flags)
{
my_bool res= my_hash_init2(psi_key, hash, growth_size, charset,
default_array_elements, key_offset, key_length, get_key,
hash_function, free_element, flags);
if (res)
return res;
hash->keycmp= keycmp;
return 0;
}
void my_hash_free(HASH *tree);
void my_hash_reset(HASH *hash);
uchar *my_hash_element(HASH *hash, size_t idx);
......
......@@ -7,6 +7,8 @@
#include "my_global.h"
#include "m_ctype.h"
#include "hash.h"
namespace traits
{
template<typename Key>
......@@ -41,126 +43,39 @@ class Open_address_hash
{
if (!first.mark())
{
DBUG_ASSERT(hash_array);
free(hash_array);
my_hash_free(&hash);
}
}
private:
Hash_value_type to_index(const Hash_value_type &hash_value) const
{
return hash_value & ((1UL << capacity_power) - 1);
}
Hash_value_type hash_from_value(const Value &value) const
{
return Key_trait::get_hash_value(get_key(value));
}
bool insert_into_bucket(const Value &value)
inline bool insert_into_bucket(const Value &value)
{
auto hash_val= to_index(hash_from_value(value));
while (!is_empty(hash_array[hash_val]))
{
if (is_equal(hash_array[hash_val], value))
return false;
hash_val= to_index(hash_val + 1);
}
hash_array[hash_val]= value;
return true;
return !my_hash_insert(&hash, (uchar*)value);
};
uint rehash_subsequence(uint i)
{
for (uint j= to_index(i + 1); !is_empty(hash_array[j]); j= to_index(j + 1))
{
auto temp_el= hash_array[j];
if (to_index(hash_from_value(temp_el)) == j)
continue;
hash_array[j]= EMPTY;
insert_into_bucket(temp_el);
}
return i;
}
bool erase_from_bucket(const Value &value)
{
for (auto key= to_index(Key_trait::get_hash_value(get_key(value)));
!is_empty(hash_array[key]); key= to_index(key + 1))
{
if (is_equal(hash_array[key], value))
{
hash_array[key]= EMPTY;
rehash_subsequence(key);
return true;
}
}
return false;
}
bool grow(const uint new_capacity_power)
{
DBUG_ASSERT(new_capacity_power > capacity_power);
size_t past_capacity= 1UL << capacity_power;
size_t capacity= 1UL << new_capacity_power;
capacity_power= new_capacity_power;
hash_array= (Value *) realloc(hash_array, capacity * sizeof(Value));
if (!hash_array)
return false;
bzero(hash_array + past_capacity,
(capacity - past_capacity) * sizeof(Value*));
for (size_t i= 0; i < capacity; i++)
{
if (hash_array[i] && i != to_index(hash_from_value(hash_array[i])))
{
auto temp_el= hash_array[i];
hash_array[i]= EMPTY;
insert_into_bucket(temp_el);
}
}
return true;
}
void shrink(const uint new_capacity_power)
{
DBUG_ASSERT(new_capacity_power < capacity_power);
size_t past_capacity= 1UL << capacity_power;
size_t capacity= 1UL << new_capacity_power;
capacity_power= new_capacity_power;
for (size_t i= capacity; i < past_capacity; i++)
{
if (hash_array[i])
{
auto temp_el= hash_array[i];
insert_into_bucket(temp_el);
}
}
hash_array= (Value *) realloc(hash_array, capacity * sizeof(Value));
}
bool init_hash_array()
{
Value _first= first.ptr();
Value _second= second;
capacity_power= CAPACITY_POWER_INITIAL;
hash_array= (Value*)calloc(1UL << capacity_power, sizeof (Value*));
_size= 0;
my_hash_init3(PSI_NOT_INSTRUMENTED, &hash, 0, &my_charset_bin, 16, 0, 0,
NULL,
Key_trait::hash_function_compat, NULL,
(int (*)(const uchar*, const uchar*))
Key_trait::is_equal,
0);
if (!insert_into_bucket(_first))
return false;
_size++;
if (!insert_into_bucket(_second))
return false;
_size++;
return true;
}
......@@ -185,11 +100,13 @@ class Open_address_hash
return EMPTY;
}
for (auto idx= to_index(Key_trait::get_hash_value(&key));
!is_empty(hash_array[idx]); idx= to_index(idx + 1))
HASH_SEARCH_STATE state;
for (auto res= my_hash_first(&hash, (uchar*)&key, sizeof key, &state);
res;
res= my_hash_next(&hash, (uchar*)&key, sizeof key, &state))
{
if (elem_suits(hash_array[idx]))
return hash_array[idx];
if (elem_suits((Value)res))
return (Value)res;
}
return EMPTY;
......@@ -212,14 +129,7 @@ class Open_address_hash
return false;
}
const size_t capacity= 1UL << capacity_power;
if (unlikely(capacity > 7 && (_size - 1) * LOW_LOAD_FACTOR < capacity))
shrink(capacity_power - 1);
if (!erase_from_bucket(value))
return false;
_size--;
return true;
return !my_hash_delete(&hash, (uchar*)value);;
}
bool insert(const Value &value)
......@@ -248,18 +158,10 @@ class Open_address_hash
}
}
if (unlikely(_size == TABLE_SIZE_MAX))
if (unlikely(hash.blength == TABLE_SIZE_MAX))
return false;
bool res= true;
const size_t capacity= 1UL << capacity_power;
if (unlikely(((ulonglong)_size + 1) * MAX_LOAD_FACTOR > capacity))
res= grow(capacity_power + 1);
res= res && insert_into_bucket(value);
if (res)
_size++;
return res;
return insert_into_bucket(value);
};
bool clear()
......@@ -270,11 +172,8 @@ class Open_address_hash
second= EMPTY;
return true;
}
if (!hash_array)
return false;
free(hash_array);
capacity_power= CAPACITY_POWER_INITIAL;
my_hash_free(&hash);
first.set_mark(true);
first.set_ptr(EMPTY);
......@@ -284,23 +183,9 @@ class Open_address_hash
}
size_t size() const
{
if (first.mark())
{
size_t ret_size= 0;
if (!is_empty(first.ptr()))
ret_size++;
if (!is_empty(second))
ret_size++;
return ret_size;
}
else
{
return _size;
}
{
return hash.array.elements;
}
size_t buffer_size() const { return first.mark() ? 0 :
1UL << capacity_power; }
Open_address_hash &operator=(const Open_address_hash&)
{
......@@ -352,12 +237,7 @@ class Open_address_hash
markable_reference first;
Value second;
};
struct
{
Value *hash_array;
uint capacity_power: 6;
size_t _size: SIZE_BITS;
};
HASH hash;
};
};
......@@ -376,12 +256,26 @@ struct Open_address_hash_key_trait
my_ci_hash_sort(&my_charset_bin, (uchar*) key, sizeof (Key), &nr1, &nr2);
return (Hash_value_type) nr1;
}
static inline Hash_value_type hash_function_compat(CHARSET_INFO *ci,
const uchar *key, size_t len)
{
ulong nr1= 1, nr2= 4;
my_ci_hash_sort(&my_charset_bin, (uchar*) key, sizeof (Key), &nr1, &nr2);
return (Hash_value_type) nr1;
};
/**
Function returning key based on value, needed to be able to rehash the table
on expansion. Value should be able to return Key from itself.
The provided instantiation implements "set", i.e. Key matches Value
*/
static Key *get_key(Key *value) { return value; }
const uchar* get_key_compat(const uchar* _val,
size_t* size, char first)
{
*size= sizeof(Key);
return _val;
}
};
template<typename Value>
......
......@@ -96,6 +96,7 @@ my_hash_init2(PSI_memory_key psi_key, HASH *hash, size_t growth_size,
hash->free=free_element;
hash->flags=flags;
hash->charset=charset;
hash->keycmp=NULL;
res= init_dynamic_array2(psi_key, &hash->array, sizeof(HASH_LINK), NULL, size,
growth_size, MYF((flags & HASH_THREAD_SPECIFIC ?
MY_THREAD_SPECIFIC : 0)));
......@@ -378,7 +379,8 @@ static int hashcmp(const HASH *hash, HASH_LINK *pos, const uchar *key,
size_t rec_keylength;
uchar *rec_key;
rec_key= (uchar*) my_hash_key(hash, pos->data, &rec_keylength, 1);
return (length != rec_keylength) ||
return hash->keycmp? hash->keycmp(key, rec_key) :
(length != rec_keylength) ||
my_strnncoll(hash->charset, (uchar*) rec_key, rec_keylength,
(uchar*) key, rec_keylength);
}
......
......@@ -672,6 +672,8 @@ class MDL_wait_for_subgraph
virtual uint get_deadlock_weight() const = 0;
};
struct TABLE;
/**
A granted metadata lock.
......@@ -861,10 +863,27 @@ struct MDL_key_trait
using Hash_value_type= decltype(MDL_key().tc_hash_value());
static MDL_key *get_key(T *t) { return t->get_key(); }
static int is_equal(MDL_key *lhs, MDL_key* rhs)
{
return lhs->is_equal(rhs);
}
const uchar* get_key_compat(const uchar* _val,
size_t* size, char first)
{
T *value= (T*)_val;
*size= sizeof(MDL_key);
return value->get_key();
}
static my_hash_value_type get_hash_value(const MDL_key *key)
{
return key->tc_hash_value();
}
static my_hash_value_type hash_function_compat(CHARSET_INFO *ci,
const uchar *key, size_t len)
{
return ((MDL_key*)key)->tc_hash_value();
}
};
namespace traits
{
......
......@@ -4937,10 +4937,7 @@ TABLE_LIST *find_fk_prelocked_table(const Query_tables_list *prelocking_ctx,
{
return prelocking_ctx->fk_table_hash.find(key,
[&key, lock_type](const TABLE_LIST *tl) {
return tl->lock_type >= lock_type
&& tl->prelocking_placeholder == TABLE_LIST::PRELOCK_FK
&& strcmp(tl->table_name.str, key.name()) == 0
&& strcmp(tl->db.str, key.db_name()) == 0;
return tl->lock_type >= lock_type;
});
}
......
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