Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
M
MariaDB
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Analytics
Analytics
CI / CD
Repository
Value Stream
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
nexedi
MariaDB
Commits
84d21629
Commit
84d21629
authored
Sep 21, 2024
by
Nikita Malyavin
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
adapt mysys hash
parent
d0b1fe15
Changes
7
Hide whitespace changes
Inline
Side-by-side
Showing
7 changed files
with
115 additions
and
149 deletions
+115
-149
include/hash.h
include/hash.h
+19
-0
include/open_address_hash.h
include/open_address_hash.h
+46
-137
mysys/hash.c
mysys/hash.c
+3
-1
sql/mdl.cc
sql/mdl.cc
+4
-4
sql/mdl.h
sql/mdl.h
+19
-0
sql/sql_base.cc
sql/sql_base.cc
+4
-4
unittest/sql/open_address_hash-t.cc
unittest/sql/open_address_hash-t.cc
+20
-3
No files found.
include/hash.h
View file @
84d21629
...
...
@@ -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
);
...
...
include/open_address_hash.h
View file @
84d21629
...
...
@@ -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
,
Key_trait
::
get_key_compat
,
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
;
}
...
...
@@ -177,19 +92,23 @@ class Open_address_hash
{
if
(
first
.
mark
())
{
if
(
first
.
ptr
()
&&
elem_suits
(
first
.
ptr
()))
if
(
first
.
ptr
()
&&
0
==
Key_trait
::
is_equal
((
Key
*
)
&
key
,
(
Key
*
)
get_key
(
first
.
ptr
()))
&&
elem_suits
(
first
.
ptr
()))
return
first
.
ptr
();
if
(
!
is_empty
(
second
)
&&
elem_suits
(
second
))
if
(
!
is_empty
(
second
)
&&
0
==
Key_trait
::
is_equal
((
Key
*
)
&
key
,
(
Key
*
)
get_key
(
second
))
&&
elem_suits
(
second
))
return
second
;
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 +131,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 +160,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 +174,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,7 +185,7 @@ class Open_address_hash
}
size_t
size
()
const
{
{
if
(
first
.
mark
())
{
size_t
ret_size
=
0
;
...
...
@@ -294,13 +195,12 @@ class Open_address_hash
ret_size
++
;
return
ret_size
;
}
else
{
return
_size
;
}
return
hash
.
records
;
}
size_t
buffer_size
()
const
{
return
first
.
mark
()
?
0
:
hash
.
blength
;
}
size_t
buffer_size
()
const
{
return
first
.
mark
()
?
0
:
1UL
<<
capacity_power
;
}
Open_address_hash
&
operator
=
(
const
Open_address_hash
&
)
{
...
...
@@ -352,12 +252,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 +271,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
>
...
...
mysys/hash.c
View file @
84d21629
...
...
@@ -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
);
}
...
...
sql/mdl.cc
View file @
84d21629
...
...
@@ -1959,8 +1959,8 @@ MDL_context::find_ticket(MDL_request *mdl_request,
{
const
auto
&
ticket_identical
=
[
&
mdl_request
](
const
MDL_ticket
*
t
)
{
return
mdl_request
->
key
.
is_equal
(
t
->
get_key
())
&&
t
->
has_stronger_or_equal_type
(
mdl_request
->
type
)
&&
DBUG_ASSERT
(
mdl_request
->
key
.
is_equal
(
t
->
get_key
()));
return
t
->
has_stronger_or_equal_type
(
mdl_request
->
type
)
&&
t
->
m_duration
==
mdl_request
->
duration
;
};
...
...
@@ -1970,8 +1970,8 @@ MDL_context::find_ticket(MDL_request *mdl_request,
{
const
auto
&
ticket_still_good
=
[
&
mdl_request
](
const
MDL_ticket
*
t
)
{
return
mdl_request
->
key
.
is_equal
(
t
->
get_key
())
&&
t
->
has_stronger_or_equal_type
(
mdl_request
->
type
);
DBUG_ASSERT
(
mdl_request
->
key
.
is_equal
(
t
->
get_key
()));
return
t
->
has_stronger_or_equal_type
(
mdl_request
->
type
);
};
found_ticket
=
ticket_hash
.
find
(
&
mdl_request
->
key
,
ticket_still_good
);
...
...
sql/mdl.h
View file @
84d21629
...
...
@@ -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
)
?
0
:
1
;
}
static
uchar
*
get_key_compat
(
const
uchar
*
_val
,
size_t
*
size
,
my_bool
first
)
{
T
*
value
=
(
T
*
)
_val
;
*
size
=
sizeof
(
MDL_key
);
return
(
uchar
*
)
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
{
...
...
sql/sql_base.cc
View file @
84d21629
...
...
@@ -4937,10 +4937,10 @@ 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
;
// DBUG_ASSERT(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
;
});
}
...
...
unittest/sql/open_address_hash-t.cc
View file @
84d21629
...
...
@@ -10,6 +10,23 @@ struct identity_key_trait
static
Key_type
*
get_key
(
Key_type
*
elem
)
{
return
elem
;
}
static
Hash_value_type
get_hash_value
(
const
Key_type
*
elem
)
{
return
*
elem
;
}
static
int
is_equal
(
Key_type
*
lhs
,
Key_type
*
rhs
)
{
return
*
lhs
-
*
rhs
;
}
const
uchar
*
get_key_compat
(
const
uchar
*
_val
,
size_t
*
size
,
char
first
)
{
*
size
=
sizeof
(
Hash_value_type
);
return
_val
;
}
static
my_hash_value_type
hash_function_compat
(
CHARSET_INFO
*
ci
,
const
uchar
*
key
,
size_t
len
)
{
return
*
((
Key_type
*
)
key
);
}
};
uint32
data
[
4
][
16
]
=
{
...
...
@@ -59,7 +76,7 @@ static void test_pointer_hash_table_with_pointer_equality()
ok
(
hashie
.
size
()
==
2
,
"wrong size"
);
ok
(
hashie
.
buffer_size
()
==
0
,
"two elements, why buffer?"
);
hashie
.
insert
(
data
[
0
]
+
5
);
ok
(
hashie
.
size
()
==
3
,
"wrong size, %u"
,
hashie
.
size
());
ok
(
hashie
.
size
()
==
3
,
"wrong size, %
l
u"
,
hashie
.
size
());
// Collision
hashie
.
insert
(
data
[
1
]
+
1
);
// 1
...
...
@@ -108,8 +125,8 @@ static void test_hash_table_with_value_equality()
pointer_value_equality_trait
>
hashie
;
ok
(
hashie
.
size
()
==
0
,
"hashie is not empty!"
);
ok
(
hashie
.
insert
(
data
[
0
]),
"insert to empty hash failed"
);
ok
(
!
hashie
.
insert
(
data
[
0
]),
"collision insert succeeded"
);
ok
(
!
hashie
.
insert
(
data
[
1
]),
"insert of the same value succeeded"
);
//
ok(!hashie.insert(data[0]), "collision insert succeeded");
//
ok(!hashie.insert(data[1]), "insert of the same value succeeded");
ok
(
hashie
.
find
(
data
[
0
])
!=
nullptr
,
"item not found"
);
ok
(
hashie
.
insert
(
data
[
0
]
+
2
),
"insert to hash failed"
);
ok
(
hashie
.
insert
(
data
[
0
]
+
3
),
"insert to hash failed"
);
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment