Commit af194ab5 authored by Vladislav Vaintroub's avatar Vladislav Vaintroub

Merge branch 'bb-10.5-MDEV-22841' into 10.5

parents ba414869 cc0205cf
...@@ -178,13 +178,13 @@ ut_new_boot(); ...@@ -178,13 +178,13 @@ ut_new_boot();
#ifdef UNIV_PFS_MEMORY #ifdef UNIV_PFS_MEMORY
/** Retrieve a memory key (registered with PFS), given a portion of the file /**
name of the caller. Retrieve a memory key (registered with PFS),
@param[in] file portion of the filename - basename without an extension given filename hash of the caller
@return registered memory key or PSI_NOT_INSTRUMENTED if not found */
PSI_memory_key @param[in] filename_hash - FILENAME_HASH value of the caller
ut_new_get_key_by_file( @return registered memory key or PSI_NOT_INSTRUMENTED */
const char* file); PSI_memory_key ut_new_get_key_by_file(uint32_t filename_hash);
#endif /* UNIV_PFS_MEMORY */ #endif /* UNIV_PFS_MEMORY */
...@@ -293,7 +293,7 @@ class ut_allocator { ...@@ -293,7 +293,7 @@ class ut_allocator {
) )
{ {
#ifdef UNIV_PFS_MEMORY #ifdef UNIV_PFS_MEMORY
const PSI_memory_key other_key = other.get_mem_key(NULL); const PSI_memory_key other_key = other.get_mem_key(0);
m_key = (other_key != mem_key_std) m_key = (other_key != mem_key_std)
? other_key ? other_key
...@@ -315,7 +315,7 @@ class ut_allocator { ...@@ -315,7 +315,7 @@ class ut_allocator {
#endif /* UNIV_PFS_MEMORY */ #endif /* UNIV_PFS_MEMORY */
} }
pointer allocate(size_type n) { return allocate(n, NULL, NULL); } pointer allocate(size_type n) { return allocate(n, NULL, 0); }
/** Allocate a chunk of memory that can hold 'n_elements' objects of /** Allocate a chunk of memory that can hold 'n_elements' objects of
type 'T' and trace the allocation. type 'T' and trace the allocation.
...@@ -333,9 +333,9 @@ class ut_allocator { ...@@ -333,9 +333,9 @@ class ut_allocator {
allocate( allocate(
size_type n_elements, size_type n_elements,
const_pointer, const_pointer,
const char* uint32_t
#ifdef UNIV_PFS_MEMORY #ifdef UNIV_PFS_MEMORY
file /*!< file name of the caller */ filename_hash /* filename hash of the caller */
#endif #endif
, ,
bool set_to_zero = false, bool set_to_zero = false,
...@@ -397,7 +397,7 @@ class ut_allocator { ...@@ -397,7 +397,7 @@ class ut_allocator {
#ifdef UNIV_PFS_MEMORY #ifdef UNIV_PFS_MEMORY
ut_new_pfx_t* pfx = static_cast<ut_new_pfx_t*>(ptr); ut_new_pfx_t* pfx = static_cast<ut_new_pfx_t*>(ptr);
allocate_trace(total_bytes, file, pfx); allocate_trace(total_bytes, filename_hash, pfx);
return(reinterpret_cast<pointer>(pfx + 1)); return(reinterpret_cast<pointer>(pfx + 1));
#else #else
...@@ -479,7 +479,7 @@ class ut_allocator { ...@@ -479,7 +479,7 @@ class ut_allocator {
reallocate( reallocate(
void* ptr, void* ptr,
size_type n_elements, size_type n_elements,
const char* file) uint32_t filename_hash)
{ {
if (n_elements == 0) { if (n_elements == 0) {
deallocate(static_cast<pointer>(ptr)); deallocate(static_cast<pointer>(ptr));
...@@ -487,7 +487,7 @@ class ut_allocator { ...@@ -487,7 +487,7 @@ class ut_allocator {
} }
if (ptr == NULL) { if (ptr == NULL) {
return(allocate(n_elements, NULL, file, false, false)); return(allocate(n_elements, NULL, filename_hash, false, false));
} }
if (n_elements > max_size()) { if (n_elements > max_size()) {
...@@ -530,7 +530,7 @@ class ut_allocator { ...@@ -530,7 +530,7 @@ class ut_allocator {
deallocate_trace(pfx_new); deallocate_trace(pfx_new);
/* pfx_new is set here to describe the new block. */ /* pfx_new is set here to describe the new block. */
allocate_trace(total_bytes, file, pfx_new); allocate_trace(total_bytes, filename_hash, pfx_new);
return(reinterpret_cast<pointer>(pfx_new + 1)); return(reinterpret_cast<pointer>(pfx_new + 1));
} }
...@@ -546,9 +546,10 @@ class ut_allocator { ...@@ -546,9 +546,10 @@ class ut_allocator {
pointer pointer
new_array( new_array(
size_type n_elements, size_type n_elements,
const char* file) uint32_t filename_hash
)
{ {
T* p = allocate(n_elements, NULL, file, false, false); T* p = allocate(n_elements, NULL, filename_hash, false, false);
if (p == NULL) { if (p == NULL) {
return(NULL); return(NULL);
...@@ -634,7 +635,7 @@ class ut_allocator { ...@@ -634,7 +635,7 @@ class ut_allocator {
if (pfx != NULL) { if (pfx != NULL) {
#ifdef UNIV_PFS_MEMORY #ifdef UNIV_PFS_MEMORY
allocate_trace(n_bytes, NULL, pfx); allocate_trace(n_bytes, 0, pfx);
#endif /* UNIV_PFS_MEMORY */ #endif /* UNIV_PFS_MEMORY */
pfx->m_size = n_bytes; pfx->m_size = n_bytes;
} }
...@@ -687,25 +688,16 @@ class ut_allocator { ...@@ -687,25 +688,16 @@ class ut_allocator {
@return performance schema key */ @return performance schema key */
PSI_memory_key PSI_memory_key
get_mem_key( get_mem_key(
const char* file) const uint32_t filename_hash) const
{ {
if (m_key != PSI_NOT_INSTRUMENTED) { if (m_key != PSI_NOT_INSTRUMENTED) {
return(m_key); return(m_key);
} }
if (file == NULL) { if (filename_hash == 0) {
return(mem_key_std); return(mem_key_std);
} }
const PSI_memory_key key = ut_new_get_key_by_file(filename_hash);
/* e.g. "btr0cur", derived from "/path/to/btr0cur.cc" */
char keyname[FILENAME_MAX];
const size_t len = ut_basename_noext(file, keyname,
sizeof(keyname));
/* If sizeof(keyname) was not enough then the output would
be truncated, assert that this did not happen. */
ut_a(len < sizeof(keyname));
const PSI_memory_key key = ut_new_get_key_by_file(keyname);
if (key != PSI_NOT_INSTRUMENTED) { if (key != PSI_NOT_INSTRUMENTED) {
return(key); return(key);
...@@ -747,16 +739,16 @@ class ut_allocator { ...@@ -747,16 +739,16 @@ class ut_allocator {
corresponds to "file", that will be used (see ut_new_boot()) corresponds to "file", that will be used (see ut_new_boot())
4. Otherwise, the name associated with mem_key_other will be used. 4. Otherwise, the name associated with mem_key_other will be used.
@param[in] size number of bytes that were allocated @param[in] size number of bytes that were allocated
@param[in] file file name of the caller or NULL if unknown @param[in] filename_hash FILENAME_HASH of the caller
@param[out] pfx placeholder to store the info which will be @param[out] pfx placeholder to store the info which will be
needed when freeing the memory */ needed when freeing the memory */
void void
allocate_trace( allocate_trace(
size_t size, size_t size,
const char* file, const uint32_t filename_hash,
ut_new_pfx_t* pfx) ut_new_pfx_t* pfx)
{ {
const PSI_memory_key key = get_mem_key(file); const PSI_memory_key key = get_mem_key(filename_hash);
pfx->m_key = PSI_MEMORY_CALL(memory_alloc)(key, size, & pfx->m_owner); pfx->m_key = PSI_MEMORY_CALL(memory_alloc)(key, size, & pfx->m_owner);
pfx->m_size = size; pfx->m_size = size;
...@@ -806,6 +798,41 @@ operator!=( ...@@ -806,6 +798,41 @@ operator!=(
#ifdef UNIV_PFS_MEMORY #ifdef UNIV_PFS_MEMORY
/*
constexpr trickery ahead.
Retrieve the FILENAME_HASH = djb2(basename_noext(__FILE__)) at the compile time.
We use the number rather than __FILE__ because integers is better to deal with
(hashing, searching) that C style strings.
*/
static constexpr const char * basename_helper(const char* s, const char * last_slash)
{
return
*s == '\0' ? last_slash :
*s == '/' || *s == '\\' ? basename_helper(s + 1, s + 1) :
basename_helper(s + 1, last_slash);
}
static constexpr const char* ut_basename(const char *filename)
{
return basename_helper(filename, filename);
}
/** Compute djb2 hash for a string. Stop at '.' , or '\0' */
constexpr uint32_t ut_filename_hash(const char* s, uint32_t h = 5381)
{
return *s == 0 || *s == '.' ? h :
ut_filename_hash(s + 1, 33 * h + (uint8_t)*s);
}
/* Force constexpr to be evaluated at compile time.*/
#define FORCE_CONSTEXPR(expr)[&]() \
{ static constexpr auto x = (expr); return x; }()
#define FILENAME_HASH FORCE_CONSTEXPR(ut_filename_hash(ut_basename(__FILE__)))
/** Allocate, trace the allocation and construct an object. /** Allocate, trace the allocation and construct an object.
Use this macro instead of 'new' within InnoDB. Use this macro instead of 'new' within InnoDB.
For example: instead of For example: instead of
...@@ -823,7 +850,7 @@ pointer must be passed to UT_DELETE() when no longer needed. ...@@ -823,7 +850,7 @@ pointer must be passed to UT_DELETE() when no longer needed.
object if the passed in pointer is NULL, e.g. if allocate() has object if the passed in pointer is NULL, e.g. if allocate() has
failed to allocate memory and has returned NULL. */ \ failed to allocate memory and has returned NULL. */ \
::new(ut_allocator<byte>(key).allocate( \ ::new(ut_allocator<byte>(key).allocate( \
sizeof expr, NULL, __FILE__, false, false)) expr sizeof expr, NULL, FILENAME_HASH, false, false)) expr
/** Allocate, trace the allocation and construct an object. /** Allocate, trace the allocation and construct an object.
Use this macro instead of 'new' within InnoDB and instead of UT_NEW() Use this macro instead of 'new' within InnoDB and instead of UT_NEW()
...@@ -871,7 +898,7 @@ The returned pointer must be passed to UT_DELETE_ARRAY(). ...@@ -871,7 +898,7 @@ The returned pointer must be passed to UT_DELETE_ARRAY().
@param[in] key performance schema memory tracing key @param[in] key performance schema memory tracing key
@return pointer to the first allocated object or NULL */ @return pointer to the first allocated object or NULL */
#define UT_NEW_ARRAY(type, n_elements, key) \ #define UT_NEW_ARRAY(type, n_elements, key) \
ut_allocator<type>(key).new_array(n_elements, __FILE__) ut_allocator<type>(key).new_array(n_elements, FILENAME_HASH)
/** Allocate and account 'n_elements' objects of type 'type'. /** Allocate and account 'n_elements' objects of type 'type'.
Use this macro to allocate memory within InnoDB instead of 'new[]' and Use this macro to allocate memory within InnoDB instead of 'new[]' and
...@@ -902,7 +929,7 @@ ut_delete_array( ...@@ -902,7 +929,7 @@ ut_delete_array(
#define ut_malloc(n_bytes, key) static_cast<void*>( \ #define ut_malloc(n_bytes, key) static_cast<void*>( \
ut_allocator<byte>(key).allocate( \ ut_allocator<byte>(key).allocate( \
n_bytes, NULL, __FILE__, false, false)) n_bytes, NULL, FILENAME_HASH, false, false))
#define ut_malloc_dontdump(n_bytes, key) static_cast<void*>( \ #define ut_malloc_dontdump(n_bytes, key) static_cast<void*>( \
ut_allocator<byte>(key).allocate_large( \ ut_allocator<byte>(key).allocate_large( \
...@@ -910,23 +937,23 @@ ut_delete_array( ...@@ -910,23 +937,23 @@ ut_delete_array(
#define ut_zalloc(n_bytes, key) static_cast<void*>( \ #define ut_zalloc(n_bytes, key) static_cast<void*>( \
ut_allocator<byte>(key).allocate( \ ut_allocator<byte>(key).allocate( \
n_bytes, NULL, __FILE__, true, false)) n_bytes, NULL, FILENAME_HASH, true, false))
#define ut_malloc_nokey(n_bytes) static_cast<void*>( \ #define ut_malloc_nokey(n_bytes) static_cast<void*>( \
ut_allocator<byte>(PSI_NOT_INSTRUMENTED).allocate( \ ut_allocator<byte>(PSI_NOT_INSTRUMENTED).allocate( \
n_bytes, NULL, __FILE__, false, false)) n_bytes, NULL, FILENAME_HASH, false, false))
#define ut_zalloc_nokey(n_bytes) static_cast<void*>( \ #define ut_zalloc_nokey(n_bytes) static_cast<void*>( \
ut_allocator<byte>(PSI_NOT_INSTRUMENTED).allocate( \ ut_allocator<byte>(PSI_NOT_INSTRUMENTED).allocate( \
n_bytes, NULL, __FILE__, true, false)) n_bytes, NULL, FILENAME_HASH, true, false))
#define ut_zalloc_nokey_nofatal(n_bytes) static_cast<void*>( \ #define ut_zalloc_nokey_nofatal(n_bytes) static_cast<void*>( \
ut_allocator<byte, false>(PSI_NOT_INSTRUMENTED).allocate( \ ut_allocator<byte, false>(PSI_NOT_INSTRUMENTED).allocate( \
n_bytes, NULL, __FILE__, true, false)) n_bytes, NULL, FILENAME_HASH, true, false))
#define ut_realloc(ptr, n_bytes) static_cast<void*>( \ #define ut_realloc(ptr, n_bytes) static_cast<void*>( \
ut_allocator<byte>(PSI_NOT_INSTRUMENTED).reallocate( \ ut_allocator<byte>(PSI_NOT_INSTRUMENTED).reallocate( \
ptr, n_bytes, __FILE__)) ptr, n_bytes, FILENAME_HASH))
#define ut_free(ptr) ut_allocator<byte>(PSI_NOT_INSTRUMENTED).deallocate( \ #define ut_free(ptr) ut_allocator<byte>(PSI_NOT_INSTRUMENTED).deallocate( \
reinterpret_cast<byte*>(ptr)) reinterpret_cast<byte*>(ptr))
......
...@@ -25,7 +25,7 @@ Created May 26, 2014 Vasil Dimov ...@@ -25,7 +25,7 @@ Created May 26, 2014 Vasil Dimov
*******************************************************/ *******************************************************/
#include "univ.i" #include "univ.i"
#include <algorithm>
/** Maximum number of retries to allocate memory. */ /** Maximum number of retries to allocate memory. */
const size_t alloc_max_retries = 60; const size_t alloc_max_retries = 60;
...@@ -44,178 +44,273 @@ PSI_memory_key mem_key_row_merge_sort; ...@@ -44,178 +44,273 @@ PSI_memory_key mem_key_row_merge_sort;
PSI_memory_key mem_key_std; PSI_memory_key mem_key_std;
#ifdef UNIV_PFS_MEMORY #ifdef UNIV_PFS_MEMORY
static const char* auto_event_names[] =
/** Auxiliary array of performance schema 'PSI_memory_info'.
Each allocation appears in
performance_schema.memory_summary_global_by_event_name (and alike) in the form
of e.g. 'memory/innodb/NAME' where the last component NAME is picked from
the list below:
1. If key is specified, then the respective name is used
2. Without a specified key, allocations from inside std::* containers use
mem_key_std
3. Without a specified key, allocations from outside std::* pick up the key
based on the file name, and if file name is not found in the predefined list
(in ut_new_boot()) then mem_key_other is used.
Keep this list alphabetically sorted. */
static PSI_memory_info pfs_info[] = {
#ifdef BTR_CUR_HASH_ADAPT
{&mem_key_ahi, "adaptive hash index", 0},
#endif /* BTR_CUR_HASH_ADAPT */
{&mem_key_buf_buf_pool, "buf_buf_pool", 0},
{&mem_key_dict_stats_bg_recalc_pool_t, "dict_stats_bg_recalc_pool_t", 0},
{&mem_key_dict_stats_index_map_t, "dict_stats_index_map_t", 0},
{&mem_key_dict_stats_n_diff_on_level, "dict_stats_n_diff_on_level", 0},
{&mem_key_other, "other", 0},
{&mem_key_row_log_buf, "row_log_buf", 0},
{&mem_key_row_merge_sort, "row_merge_sort", 0},
{&mem_key_std, "std", 0},
};
/** Map used for default performance schema keys, based on file name of the
caller. The key is the file name of the caller and the value is a pointer
to a PSI_memory_key variable to be passed to performance schema methods.
We use ut_strcmp_functor because by default std::map will compare the pointers
themselves (cont char*) and not do strcmp(). */
typedef std::map<const char*, PSI_memory_key*, ut_strcmp_functor>
mem_keys_auto_t;
/** Map of filename/pfskey, used for tracing allocations that have not
provided a manually created pfs key. This map is only ever modified (bulk
insert) at startup in a single-threaded environment by ut_new_boot().
Later it is only read (only std::map::find() is called) from multithreaded
environment, thus it is not protected by any latch. */
static mem_keys_auto_t mem_keys_auto;
#endif /* UNIV_PFS_MEMORY */
/** Setup the internal objects needed for UT_NEW() to operate.
This must be called before the first call to UT_NEW(). */
void
ut_new_boot()
{ {
#ifdef UNIV_PFS_MEMORY
static const char* auto_event_names[] = {
/* Keep this list alphabetically sorted. */
"btr0btr", "btr0btr",
"btr0bulk", "btr0bulk",
"btr0cur", "btr0cur",
"btr0defragment",
"btr0pcur", "btr0pcur",
"btr0sea", "btr0sea",
"btr0types",
"buf0buddy",
"buf0buf", "buf0buf",
"buf0checksum",
"buf0dblwr", "buf0dblwr",
"buf0dump", "buf0dump",
"buf0flu", "buf0flu",
"buf0lru", "buf0lru",
"buf0rea",
"buf0types",
"data0data",
"data0type",
"data0types",
"db0err",
"dict0boot",
"dict0crea",
"dict0defrag_bg",
"dict0dict", "dict0dict",
"dict0load",
"dict0mem", "dict0mem",
"dict0pagecompress",
"dict0priv",
"dict0stats", "dict0stats",
"dict0stats_bg", "dict0stats_bg",
"dict0types",
"dyn0buf",
"dyn0types",
"eval0eval", "eval0eval",
"eval0proc",
"fil0crypt",
"fil0fil", "fil0fil",
"fil0pagecompress",
"fsp0file", "fsp0file",
"fsp0fsp",
"fsp0space", "fsp0space",
"fsp0sysspace", "fsp0sysspace",
"fsp0types",
"fts0ast", "fts0ast",
"fts0blex",
"fts0config", "fts0config",
"fts0fts", "fts0fts",
"fts0opt", "fts0opt",
"fts0pars", "fts0pars",
"fts0plugin",
"fts0priv",
"fts0que", "fts0que",
"fts0sql", "fts0sql",
"fts0tlex",
"fts0tokenize",
"fts0types",
"fts0vlc",
"fut0fut",
"fut0lst",
"gis0geo",
"gis0rtree",
"gis0sea", "gis0sea",
"gis0type",
"ha0ha", "ha0ha",
"ha0storage",
"ha_innodb", "ha_innodb",
"ha_prototypes",
"handler0alter", "handler0alter",
"hash0hash", "hash0hash",
"i_s", "i_s",
"ib0mutex",
"ibuf0ibuf", "ibuf0ibuf",
"ibuf0types",
"lexyy", "lexyy",
"lock0iter",
"lock0lock", "lock0lock",
"lock0prdt",
"lock0priv",
"lock0types",
"lock0wait",
"log0crypt",
"log0log", "log0log",
"log0recv", "log0recv",
"log0sync",
"log0types",
"mach0data",
"mem0mem", "mem0mem",
"mtr0log",
"mtr0mtr",
"mtr0types",
"os0api",
"os0event", "os0event",
"os0file", "os0file",
"os0proc",
"os0thread",
"page0cur", "page0cur",
"page0page",
"page0types",
"page0zip", "page0zip",
"pars0grm",
"pars0lex", "pars0lex",
"pars0opt",
"pars0pars",
"pars0sym",
"pars0types",
"que0que",
"que0types",
"read0read", "read0read",
"read0types",
"rem0cmp",
"rem0rec", "rem0rec",
"rem0types",
"row0ext",
"row0ftsort", "row0ftsort",
"row0import", "row0import",
"row0ins",
"row0log", "row0log",
"row0merge", "row0merge",
"row0mysql", "row0mysql",
"row0purge",
"row0quiesce",
"row0row",
"row0sel", "row0sel",
"row0types",
"row0uins",
"row0umod",
"row0undo",
"row0upd",
"row0vers",
"srv0conc", "srv0conc",
"srv0mon",
"srv0srv", "srv0srv",
"srv0start", "srv0start",
"sync0arr", "sync0arr",
"sync0debug", "sync0debug",
"sync0policy",
"sync0rw", "sync0rw",
"sync0sync",
"sync0types", "sync0types",
"trx0i_s", "trx0i_s",
"trx0purge", "trx0purge",
"trx0rec",
"trx0roll", "trx0roll",
"trx0rseg", "trx0rseg",
"trx0sys", "trx0sys",
"trx0trx", "trx0trx",
"trx0types",
"trx0undo", "trx0undo",
"trx0xa",
"ut0byte",
"ut0counter",
"ut0crc32",
"ut0dbg",
"ut0list", "ut0list",
"ut0lst",
"ut0mem", "ut0mem",
"ut0mutex", "ut0mutex",
"ut0new",
"ut0pool", "ut0pool",
"ut0rbt", "ut0rbt",
"ut0wqueue", "ut0rnd",
}; "ut0sort",
static const size_t n_auto = UT_ARR_SIZE(auto_event_names); "ut0stage",
static PSI_memory_key auto_event_keys[n_auto]; "ut0ut",
static PSI_memory_info pfs_info_auto[n_auto]; "ut0vec",
"ut0wqueue"
};
for (size_t i = 0; i < n_auto; i++) { /** Auxiliary array of performance schema 'PSI_memory_info'.
Each allocation appears in
performance_schema.memory_summary_global_by_event_name (and alike) in the form
of e.g. 'memory/innodb/NAME' where the last component NAME is picked from
the list below:
1. If key is specified, then the respective name is used
2. Without a specified key, allocations from inside std::* containers use
mem_key_std
3. Without a specified key, allocations from outside std::* pick up the key
based on the file name, and if file name is not found in the predefined list
(in ut_new_boot()) then mem_key_other is used.
Keep this list alphabetically sorted. */
static PSI_memory_info pfs_info[] = {
#ifdef BTR_CUR_HASH_ADAPT
{&mem_key_ahi, "adaptive hash index", 0},
#endif /* BTR_CUR_HASH_ADAPT */
{&mem_key_buf_buf_pool, "buf_buf_pool", 0},
{&mem_key_dict_stats_bg_recalc_pool_t, "dict_stats_bg_recalc_pool_t", 0},
{&mem_key_dict_stats_index_map_t, "dict_stats_index_map_t", 0},
{&mem_key_dict_stats_n_diff_on_level, "dict_stats_n_diff_on_level", 0},
{&mem_key_other, "other", 0},
{&mem_key_row_log_buf, "row_log_buf", 0},
{&mem_key_row_merge_sort, "row_merge_sort", 0},
{&mem_key_std, "std", 0},
};
const std::pair<mem_keys_auto_t::iterator, bool> ret static const int NKEYS = static_cast<int>UT_ARR_SIZE(auto_event_names);
MY_ATTRIBUTE((unused)) std::pair<uint32_t, PSI_memory_key> search_array[NKEYS];
= mem_keys_auto.insert(
mem_keys_auto_t::value_type(auto_event_names[i], /** Setup the internal objects needed for UT_NEW() to operate.
&auto_event_keys[i])); This must be called before the first call to UT_NEW(). */
void ut_new_boot()
{
PSI_MEMORY_CALL(register_memory)("innodb", pfs_info, UT_ARR_SIZE(pfs_info));
/* ret.second is true if new element has been inserted */ static PSI_memory_key auto_event_keys[NKEYS];
ut_a(ret.second); static PSI_memory_info pfs_info_auto[NKEYS];
for (int i= 0; i < NKEYS; i++)
{
pfs_info_auto[i]= {&auto_event_keys[i], auto_event_names[i], 0};
}
/* e.g. "btr0btr" */ PSI_MEMORY_CALL(register_memory)("innodb", pfs_info_auto,NKEYS);
pfs_info_auto[i].m_name = auto_event_names[i];
/* a pointer to the pfs key */ if (auto_event_keys[0] == PSI_NOT_INSTRUMENTED)
pfs_info_auto[i].m_key = &auto_event_keys[i]; return; // PSI is off
pfs_info_auto[i].m_flags = 0; for (int i= 0; i < NKEYS; i++)
{
search_array[i]= {ut_filename_hash(auto_event_names[i]), auto_event_keys[i]};
} }
PSI_MEMORY_CALL(register_memory)("innodb", pfs_info, static_cast<int>( std::sort(search_array, std::end(search_array));
UT_ARR_SIZE(pfs_info)));
PSI_MEMORY_CALL(register_memory)("innodb", pfs_info_auto, #ifdef UNIV_DEBUG
static_cast<int>(n_auto)); /* assumption that hash value is not 0 in ut0new.h, get_mem_key() */
#endif /* UNIV_PFS_MEMORY */ ut_ad(search_array[0].first);
/* Check for hash duplicates */
for(int i= 0; i < NKEYS-1; i++)
{
if (search_array[i].first == search_array[i + 1].first)
{
// This can only happen if autoevent_names was updated
// previously, or the hash function changed
ib::fatal() << __FILE__ "Duplicates found in filename hashes";
}
}
#endif
} }
#ifdef UNIV_PFS_MEMORY /** Retrieve a memory key (registered with PFS), corresponding to source file hash.
/** Retrieve a memory key (registered with PFS), given a portion of the file @param[in] filename_hash - hash value (computed at compile time) of a ut_filename_hash
name of the caller. for a one of the auto_event_names.
@param[in] file portion of the filename - basename without an extension @return registered memory key or PSI_NOT_INSTRUMENTED
@return registered memory key or PSI_NOT_INSTRUMENTED if not found */ */
PSI_memory_key PSI_memory_key ut_new_get_key_by_file(uint32_t filename_hash)
ut_new_get_key_by_file(
const char* file)
{ {
mem_keys_auto_t::const_iterator el = mem_keys_auto.find(file); if(search_array[0].second == PSI_NOT_INSTRUMENTED)
{
if (el != mem_keys_auto.end()) { // PSI is off.
return(*(el->second)); return PSI_NOT_INSTRUMENTED;
} }
return(PSI_NOT_INSTRUMENTED); std::pair<uint32, PSI_memory_key> e{ filename_hash, 0 };
auto result= std::lower_bound(search_array, std::end(search_array), e);
if (result != std::end(search_array) && result->first == filename_hash)
return result->second;
#ifdef UNIV_DEBUG
ib::fatal() << __FILE__ " ut_new_get_key_by_file : hash not found";
#endif
return PSI_NOT_INSTRUMENTED;
} }
#endif /* UNIV_PFS_MEMORY */ #else /* UNIV_PFS_MEMORY */
void ut_new_boot(){}
#endif
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