Commit 2f9484c6 authored by Nikita Malyavin's avatar Nikita Malyavin

optimize hash api to allow "insert if not found"

parent e0b0a12e
......@@ -64,20 +64,32 @@ class Open_address_hash
return Key_trait::get_hash_value(get_key(value));
}
bool insert_into_bucket(const Value &value)
template <typename ElemSuitsFunc, typename GetElemFunc>
bool insert_into_bucket(const Key& key,
const ElemSuitsFunc &elem_suits,
const GetElemFunc &get_elem)
{
auto hash_val= to_index(hash_from_value(value));
auto hash_val= to_index(Key_trait::get_hash_value(&key));
while (!is_empty(hash_array[hash_val]))
{
if (is_equal(hash_array[hash_val], value))
if (elem_suits(hash_array[hash_val]))
return false;
hash_val= to_index(hash_val + 1);
}
hash_array[hash_val]= value;
return true;
};
Value &&value= get_elem();
hash_array[hash_val]= get_elem();
return !is_empty(value);
}
bool insert_into_bucket(const Value &value)
{
return insert_into_bucket(*get_key(value),
[&value](const Value &rhs){ return is_equal(rhs, value); },
[&value](){ return value; }
);
}
uint rehash_subsequence(uint i)
{
......@@ -175,7 +187,7 @@ class Open_address_hash
public:
Value find(const Value &elem) const
{
return find(*Key_trait::get_key(elem),
return find(*get_key(elem),
[&elem](const Value &rhs) { return is_equal(rhs, elem); });
}
......@@ -184,12 +196,9 @@ class Open_address_hash
{
if (likely(first.mark()))
{
if (first.ptr())
{
if (elem_suits(first.ptr()))
return first.ptr();
}
else if (!is_empty(second) && elem_suits(second))
if (!is_empty(first.ptr()) && elem_suits(first.ptr()))
return first.ptr();
if (!is_empty(second) && elem_suits(second))
return second;
return EMPTY;
......@@ -203,7 +212,7 @@ class Open_address_hash
}
return EMPTY;
};
}
bool erase(const Value &value)
{
......@@ -215,7 +224,7 @@ class Open_address_hash
second= EMPTY;
return true;
}
else if (second && is_equal(second, value))
else if (!is_empty(second) && is_equal(second, value))
{
second= EMPTY;
return true;
......@@ -235,30 +244,35 @@ class Open_address_hash
return true;
}
bool insert(const Value &value)
template <typename ElemSuitsFunc, typename GetElemFunc>
bool insert(const Key &key,
const ElemSuitsFunc &elem_suits,
const GetElemFunc &get_elem)
{
if (first.mark())
{
if (is_empty(first.ptr()))
{
if (is_equal(second, value))
return false;
first.set_ptr(value);
first.set_ptr(get_elem());
return true;
}
else if (is_empty(second))
{
if (is_equal(first.ptr(), value))
return false;
second= value;
if (elem_suits(first.ptr()))
return true;
}
else
if (is_empty(second))
{
first.set_mark(false);
if (!init_hash_array())
return false;
second= get_elem();
return true;
}
if (elem_suits(second))
return true;
first.set_mark(false);
if (!init_hash_array())
return false;
}
if (unlikely(_size == TABLE_SIZE_MAX))
......@@ -269,12 +283,19 @@ class Open_address_hash
if (unlikely(((ulonglong)_size + 1) * MAX_LOAD_FACTOR > capacity))
res= grow(capacity_power + 1);
res= res && insert_into_bucket(value);
res= res && insert_into_bucket(key, elem_suits, get_elem);
if (res)
_size++;
return res;
};
bool insert(const Value &value)
{
return insert(*get_key(value),
[&value](const Value &rhs){ return is_equal(rhs, value); },
[&value](){ return value; });
}
bool clear()
{
if (first.mark())
......
......@@ -1964,7 +1964,7 @@ MDL_context::find_ticket(MDL_request *mdl_request,
t->m_duration == mdl_request->duration;
};
MDL_ticket *found_ticket= ticket_hash.find(&mdl_request->key,
MDL_ticket *found_ticket= ticket_hash.find(mdl_request->key,
ticket_identical);
if (!found_ticket)
{
......
......@@ -5053,27 +5053,41 @@ prepare_fk_prelocking_list(THD *thd, Query_tables_list *prelocking_ctx,
else
lock_type= TL_READ;
MDL_key key(MDL_key::TABLE, fk->foreign_db->str, fk->foreign_table->str);
const char *db= fk->foreign_db->str;
const char *table_name= fk->foreign_table->str;
MDL_key key(MDL_key::TABLE, db, table_name);
TABLE_LIST *tl= find_fk_prelocked_table(prelocking_ctx, key, lock_type);
if (tl == NULL)
TABLE_LIST *tl= NULL;
bool success= prelocking_ctx->fk_table_hash.insert(key,
[db, table_name, lock_type](const TABLE_LIST *tl)
{
return tl->lock_type >= lock_type
&& strcmp(tl->table_name.str, table_name) == 0
&& strcmp(tl->db.str, db) == 0;
},
[&tl, thd]()
{
tl= (TABLE_LIST *) thd->alloc(sizeof(TABLE_LIST));
return tl;
}
);
if (unlikely(!success))
{
tl= (TABLE_LIST *) thd->alloc(sizeof(TABLE_LIST));
tl->init_one_table_for_prelocking(
fk->foreign_db, fk->foreign_table, NULL, lock_type,
TABLE_LIST::PRELOCK_FK, table_list->belong_to_view, op,
&prelocking_ctx->query_tables_last, &key,
table_list->for_insert_data);
bool success= prelocking_ctx->fk_table_hash.insert(tl);
if (!success)
{
my_error(ER_OUTOFMEMORY, MYF(0));
if (arena)
thd->restore_active_arena(arena, &backup);
DBUG_RETURN(TRUE);
}
my_error(ER_OUTOFMEMORY, MYF(0));
if (arena)
thd->restore_active_arena(arena, &backup);
DBUG_RETURN(TRUE);
}
if (tl != NULL)
{
tl->init_one_table_for_prelocking(
fk->foreign_db, fk->foreign_table, NULL, lock_type,
TABLE_LIST::PRELOCK_FK, table_list->belong_to_view, op,
&prelocking_ctx->query_tables_last, &key,
table_list->for_insert_data);
}
}
if (arena)
thd->restore_active_arena(arena, &backup);
......
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