MySQL 8.4.0
Source Code Documentation
shared_multi_map.h
Go to the documentation of this file.
1/* Copyright (c) 2015, 2024, Oracle and/or its affiliates.
2
3 This program is free software; you can redistribute it and/or modify
4 it under the terms of the GNU General Public License, version 2.0,
5 as published by the Free Software Foundation.
6
7 This program is designed to work with certain software (including
8 but not limited to OpenSSL) that is licensed under separate terms,
9 as designated in a particular file or component or in included license
10 documentation. The authors of MySQL hereby grant you an additional
11 permission to link the program and your derivative works with the
12 separately licensed software that they have either included with
13 the program or referenced in the documentation.
14
15 This program is distributed in the hope that it will be useful,
16 but WITHOUT ANY WARRANTY; without even the implied warranty of
17 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 GNU General Public License, version 2.0, for more details.
19
20 You should have received a copy of the GNU General Public License
21 along with this program; if not, write to the Free Software
22 Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */
23
24#ifndef DD_CACHE__SHARED_MULTI_MAP_INCLUDED
25#define DD_CACHE__SHARED_MULTI_MAP_INCLUDED
26
27#include <stdio.h>
28#include <vector> // std::vector
29
30#include "my_compiler.h"
31#include "my_psi_config.h"
40#include "sql/dd/cache/multi_map_base.h" // Multi_map_base
41#include "sql/dd/impl/cache/cache_element.h" // Cache_element
42#include "sql/dd/impl/cache/free_list.h" // Free_list
48#include "sql/dd/types/event.h"
51#include "sql/dd/types/schema.h"
54#include "sql/malloc_allocator.h" // Malloc_allocator.
55#include "sql/mysqld.h" // max_connections
56#include "sql/psi_memory_key.h" // key_memory_DD_cache_infrastructure
57#include "thr_mutex.h"
58
59namespace dd {
60namespace cache {
61template <typename K, typename E>
62class Element_map;
63template <typename T>
64class Cache_element;
65} // namespace cache
66} // namespace dd
67
68#ifdef HAVE_PSI_INTERFACE
71#endif
72
73namespace dd {
74namespace cache {
75
76/**
77 Implementation of a shared set of maps for a given object type.
78
79 The implementation is an extension of the Multi_map_base, and adds support
80 for:
81
82 - Locking and thread synchronization.
83 - Broadcasting a miss which has been handled.
84 - Tracking object usage.
85 - Managing the free list.
86 - Tracking cache misses.
87 - Maintaining a pool of allocated cache elements.
88 - Deleting objects and elements after releasing the mutex.
89
90 The pool of vacant cache elements is used to avoid deleting and allocating
91 memory. We keep a pool of up to 'max_connections' elements. When a new
92 element is needed, we first try to get one from the pool. If that does
93 not succeed, a new element is allocated dynamically. In this case, the
94 allocation will happen while the mutex is locked.
95
96 When an element and object are to be removed from the shared map and
97 deleted, the size of the pool decides whether the element should be
98 added to the pool or not. If it is not added to the pool, it is signed
99 up for being deleted by the Autolocker. The element's object is always
100 signed up for being deleted, it is never reused even if the corresponding
101 element is added to the pool. The Autolocker is used for two purposes:
102
103 1. To ensure that the mutex is locked and unlocked correctly.
104 2. To delete unused elements and objects outside the scope
105 where the mutex is locked.
106
107 When the Autolocker is deleted, it will first unlock the mutex, then
108 it will iterate over the elements and objects and delete them.
109
110 @note The multi map provides support for tracking cache misses, but does
111 not handle the miss. The miss must be handled by the user of the
112 multi map.
113
114 @tparam T Dictionary object type.
115*/
116
117template <typename T>
119 private:
120 static const size_t initial_capacity = 256;
121
122 // Inner class to lock and unlock the multi map instance.
124 private:
125 // Vector containing objects to be deleted unconditionally.
126 typedef std::vector<const T *, Malloc_allocator<const T *>>
129
130 // Vector containing elements to be deleted unconditionally, which
131 // happens when elements are evicted while the pool is already full.
132 typedef std::vector<const Cache_element<T> *,
136
137 Shared_multi_map<T> *m_map; // Pointer to the enclosing multi map.
138
139 public:
140 // Lock the multi map on instantiation.
146 m_map(map) {
147 mysql_mutex_lock(&m_map->m_lock);
148 }
149
150 // Add object to be deleted.
151 void auto_delete(const T *object) { m_objects_to_delete.push_back(object); }
152
153 // Add element to be deleted.
154 void auto_delete(const Cache_element<T> *element) {
155 m_elements_to_delete.push_back(element);
156 }
157
158 // Unlock the multi map when being deleted (e.g. going out of scope)
159 // and delete the objects and elements.
161 mysql_mutex_unlock(&m_map->m_lock);
162 // Delete the objects.
163 for (typename Object_list_type::const_iterator it =
164 m_objects_to_delete.begin();
165 it != m_objects_to_delete.end(); ++it)
166 delete *it;
167
168 // Delete the elements.
169 for (typename Element_list_type::const_iterator it =
170 m_elements_to_delete.begin();
171 it != m_elements_to_delete.end(); ++it)
172 delete *it;
173 }
174 };
175
176 /**
177 We need a mutex to lock this instance for thread safety, as well as
178 a condition variable for synchronizing handling of cache misses. We
179 provide a set of operations for using these variables.
180 */
181
182 mysql_mutex_t m_lock; // Single mutex to lock the map.
183 mysql_cond_t m_miss_handled; // Broadcast a miss being handled.
184
186 std::vector<Cache_element<T> *>
187 m_element_pool; // Pool of allocated elements.
188 size_t m_capacity; // Total capacity, i.e., if the
189 // number of elements exceeds this
190 // limit, shrink the free list.
191
192 /**
193 Template helper function getting the element map.
194
195 Const and non-const variants.
196
197 @note Slightly weird syntax is needed to help the parser
198 to resolve this correctly.
199
200 @tparam K Key type.
201
202 @return The element map handling keys of type K.
203 */
204
205 template <typename K>
207 return Multi_map_base<T>::template m_map<K>();
208 }
209
210 template <typename K>
212 return Multi_map_base<T>::template m_map<K>();
213 }
214
215 /**
216 Template function to find an element and mark it as used.
217
218 The function looks up the appropriate element map. If the key
219 is present in the map, the element is marked as being used and
220 returned. If the element was in the free list, it is removed from
221 the list.
222
223 @tparam K Key type.
224 @param key Key to use for looking up the element.
225
226 @return Element found associated with the key, if
227 present, otherwise NULL.
228 */
229
230 template <typename K>
232
233 /**
234 Remove an element from the map.
235
236 This function will remove the element from the multi map. This means that
237 all keys associated with the element will be removed from the maps, and
238 the cache element wrapper will be deleted. The object itself is not
239 deleted. It is up to the outer layer to decide what to do with the object.
240
241 @param element Element to be removed.
242 @param lock Autolocker to use for signing up for auto delete.
243 */
244
245 void remove(Cache_element<T> *element, Autolocker *lock);
246
247 /**
248 Check if the current map capacity is exceeded.
249
250 @return true If the cache capacity is exceeded.
251 false If there is additional capacity in the cache.
252 */
253
256 return this->m_map<const T *>()->size() > m_capacity;
257 }
258
259 /**
260 Check if the pool capacity is exceeded.
261
262 We keep enough elements to let all connections have a cache miss
263 at the same time without needing to allocate a new element, i.e.,
264 we use 'max_connections' as the pool capacity.
265
266 @return true If the pool capacity is exceeded.
267 false If there is additional capacity for vacant elements.
268 */
269
272 return m_element_pool.size() > max_connections;
273 }
274
275 /**
276 Helper function to evict unused elements from the free list
277 until the cache capacity is not exceeded.
278
279 @param lock Autolocker to use for signing up for auto delete.
280 */
281
282 void rectify_free_list(Autolocker *lock);
283
284 /**
285 Helper function to evict all unused elements from the free list
286 and the cache. Used during e.g. shutdown.
287
288 @param lock Autolocker to use for signing up for auto delete.
289 */
290
291 void evict_all_unused(Autolocker *lock);
292
293 public:
294 /**
295 Initialize the mutex and condition variable.
296 Set initial map capacity.
297 */
298
302 }
303
304 /**
305 Destroy the mutex and condition variable.
306 */
307
311 }
312
313 /**
314 Shutdown the shared map. Delete all objects present.
315 */
316
317 void shutdown();
318
319 /**
320 Reset the shared map. Locks and deletes all objects present,
321 but keeps the element pool and the capacity setting.
322
323 @param thd Thread context.
324
325 @retval true Failure, e.g. timeout from metadata lock acquisition.
326 @retval false Otherwise.
327 */
328
329 bool reset(THD *thd);
330
331 /**
332 Set capacity of the shared map.
333 */
334
335 void set_capacity(size_t capacity) {
336 Autolocker lock(this);
337 m_capacity = capacity;
339 }
340
341 /**
342 Check if an element with the given key is available.
343 */
344
345 template <typename K>
346 bool available(const K &key) {
347 Autolocker lock(this);
348 Cache_element<T> *e = nullptr;
349 m_map<K>()->get(key, &e);
350 return (e != nullptr);
351 }
352
355 /**
356 Get a wrapper element from the map handling the given key type.
357
358 If the wrapped object is present, mark it as used and return it. If the
359 object is in the process of being loaded, wait for loading to be
360 completed. If the object is not present, and not being loaded, mark it
361 as missed and return.
362
363 @tparam K Key type.
364 @param key Key to use for looking up the object.
365 @param [out] element Wrapper element pointer, if present, either
366 immediately or after a cache miss handled by another
367 thread. NULL if awakened after a miss handled by
368 another thread, which was unable to load the object
369 from elsewhere. NULL if the object is not present,
370 and no other thread is missing it.
371
372 @retval true If the object is missed, and this thread must handle
373 the miss.
374 @retval false Otherwise.
375 */
377
378 template <typename K>
379 bool get(const K &key, Cache_element<T> **element);
380
383 /**
384 Put a new object and element wrapper into the map.
385
386 The new object may be NULL if it does not exist in the DD tables.
387 In that case, we must still update the missing set and broadcast,
388 if necessary, because other threads may be waiting. Then, the
389 element returned is also NULL.
390
391 Otherwise, we check that the actual object instance is not present
392 in the map, then all the keys are generated based on the new object.
393 The keys that are missed are removed from the missed set, and then
394 we verify that all keys are either present or absent.
395
396 If no keys are present, it means we must add the new object. We
397 remove the least recently used objects, if cache capacity is exceeded,
398 and add the new object to the reverse map. We also mark the object
399 as being used. The element wrapper of the new object is returned.
400
401 If all keys are present, we return the wrapper element already present
402 and delete the newly read object.
403
404 Finally, if at least one key was missed, we broadcast that the miss
405 has been handled.
406
407 @note This function will delete the newly read object if an object with
408 the same keys is already present.
409
410 @note The function may add a new object which is not registered as being
411 missed, i.e., without a preceding cache miss In this case, the
412 submitted key is NULL.
413
414 @tparam K Key type.
415 @param key Key used when loading the object.
416 @param object New object to be added.
417 @param [out] element Element wrapper: NULL if the new object is
418 NULL, otherwise the wrapper of the newly
419 read object or the existing object with
420 the same keys.
421 */
423
424 template <typename K>
425 void put(const K *key, const T *object, Cache_element<T> **element);
426
427 /**
428 Release one element.
429
430 The element must be present and in use. If the element becomes unused,
431 it is added to the free list, which is then rectified to enforce its
432 capacity constraints.
433
434 @param element Element pointer.
435 */
436
437 void release(Cache_element<T> *element);
438
439 /**
440 Delete an element from the map.
441
442 This function will remove the element from all maps, using remove(),
443 and delete the object pointed to. This means that all keys associated
444 with the element will be removed from the maps, and the cache element
445 wrapper will be deleted. The object may not be accessed after calling
446 this function.
447
448 @param element Element pointer.
449 */
450
451 void drop(Cache_element<T> *element);
452
455 /**
456 Delete an object corresponding to the key from the map if exists.
457
458 This function will find the element corresponding to the key if
459 it exists. After that it will remove the element from all maps, using
460 remove(), and delete the object pointed to. This means that all keys
461 associated with the element will be removed from the maps, and the
462 cache element wrapper will be deleted.
463
464 @tparam K Key type.
465 @param key Key to be checked.
466 */
468
469 template <typename K>
470 void drop_if_present(const K &key);
471
472 /**
473 Replace the object and re-generate the keys for an element.
474
475 The element must be present and in use. The keys by which it is hashed
476 are removed from the internal maps. The new keys are generated, and the
477 element, with its new keys, is added to the maps again.
478
479 @param element Element for which new keys should be generated.
480 @param object New object to replace the old one.
481 */
482
483 void replace(Cache_element<T> *element, const T *object);
484
485 /**
486 Debug dump of the shared multi map to stderr.
487 */
488 /* purecov: begin inspected */
489 void dump() const {
490#ifndef NDEBUG
491 fprintf(stderr, " --------------------------------\n");
492 fprintf(stderr, " Shared multi map for '%s'\n",
493 T::DD_table::instance().name().c_str());
495 fprintf(stderr, " Free list:\n");
496 m_free_list.dump();
497 fprintf(stderr, " --------------------------------\n");
498#endif
499 }
500 /* purecov: end */
501};
502
503} // namespace cache
504} // namespace dd
505
506#endif // DD_CACHE__SHARED_MULTI_MAP_INCLUDED
Malloc_allocator is a C++ STL memory allocator based on my_malloc/my_free.
Definition: malloc_allocator.h:63
For each client connection we create a separate thread with THD serving as a thread/connection descri...
Definition: sql_lexer_thd.h:36
Implementation of a dictionary client.
Definition: cache_element.h:69
Implementation of a map between a key type and an element type.
Definition: element_map.h:72
Template for management of a free list based on a std::vector.
Definition: free_list.h:53
Implementation of a set of maps for a given object type.
Definition: multi_map_base.h:64
void dump() const
Debug dump of the multi map base to stderr.
Definition: multi_map_base.h:181
Definition: shared_multi_map.h:123
Autolocker(Shared_multi_map< T > *map)
Definition: shared_multi_map.h:141
Object_list_type m_objects_to_delete
Definition: shared_multi_map.h:128
~Autolocker()
Definition: shared_multi_map.h:160
std::vector< const T *, Malloc_allocator< const T * > > Object_list_type
Definition: shared_multi_map.h:127
Shared_multi_map< T > * m_map
Definition: shared_multi_map.h:137
Element_list_type m_elements_to_delete
Definition: shared_multi_map.h:135
void auto_delete(const Cache_element< T > *element)
Definition: shared_multi_map.h:154
std::vector< const Cache_element< T > *, Malloc_allocator< const Cache_element< T > * > > Element_list_type
Definition: shared_multi_map.h:134
void auto_delete(const T *object)
Definition: shared_multi_map.h:151
Implementation of a shared set of maps for a given object type.
Definition: shared_multi_map.h:118
bool map_capacity_exceeded() const
Check if the current map capacity is exceeded.
Definition: shared_multi_map.h:254
std::vector< Cache_element< T > * > m_element_pool
Definition: shared_multi_map.h:187
bool get(const K &key, Cache_element< T > **element)
Get a wrapper element from the map handling the given key type.
Definition: shared_multi_map.cc:258
size_t m_capacity
Definition: shared_multi_map.h:188
static const size_t initial_capacity
Definition: shared_multi_map.h:120
mysql_mutex_t m_lock
We need a mutex to lock this instance for thread safety, as well as a condition variable for synchron...
Definition: shared_multi_map.h:182
void rectify_free_list(Autolocker *lock)
Helper function to evict unused elements from the free list until the cache capacity is not exceeded.
Definition: shared_multi_map.cc:118
void remove(Cache_element< T > *element, Autolocker *lock)
Remove an element from the map.
Definition: shared_multi_map.cc:75
bool available(const K &key)
Check if an element with the given key is available.
Definition: shared_multi_map.h:346
bool reset(THD *thd)
Reset the shared map.
Definition: shared_multi_map.cc:214
~Shared_multi_map()
Destroy the mutex and condition variable.
Definition: shared_multi_map.h:308
void replace(Cache_element< T > *element, const T *object)
Replace the object and re-generate the keys for an element.
Definition: shared_multi_map.cc:451
Free_list< Cache_element< T > > m_free_list
Definition: shared_multi_map.h:185
void shutdown()
Shutdown the shared map.
Definition: shared_multi_map.cc:148
Cache_element< T > * use_if_present(const K &key)
Template function to find an element and mark it as used.
Definition: shared_multi_map.cc:55
void drop_if_present(const K &key)
Delete an object corresponding to the key from the map if exists.
Definition: shared_multi_map.cc:439
void set_capacity(size_t capacity)
Set capacity of the shared map.
Definition: shared_multi_map.h:335
void drop(Cache_element< T > *element)
Delete an element from the map.
Definition: shared_multi_map.cc:431
void release(Cache_element< T > *element)
Release one element.
Definition: shared_multi_map.cc:398
void evict_all_unused(Autolocker *lock)
Helper function to evict all unused elements from the free list and the cache.
Definition: shared_multi_map.cc:134
Shared_multi_map()
Initialize the mutex and condition variable.
Definition: shared_multi_map.h:299
void dump() const
Debug dump of the shared multi map to stderr.
Definition: shared_multi_map.h:489
mysql_cond_t m_miss_handled
Definition: shared_multi_map.h:183
void put(const K *key, const T *object, Cache_element< T > **element)
Put a new object and element wrapper into the map.
Definition: shared_multi_map.cc:287
bool pool_capacity_exceeded() const
Check if the pool capacity is exceeded.
Definition: shared_multi_map.h:270
const Element_map< K, Cache_element< T > > * m_map() const
Definition: shared_multi_map.h:211
Element_map< K, Cache_element< T > > * m_map()
Template helper function getting the element map.
Definition: shared_multi_map.h:206
#define mysql_cond_destroy(C)
Definition: mysql_cond.h:45
#define mysql_cond_init(K, C)
Definition: mysql_cond.h:42
#define mysql_mutex_lock(M)
Definition: mysql_mutex.h:50
#define mysql_mutex_destroy(M)
Definition: mysql_mutex.h:46
#define mysql_mutex_unlock(M)
Definition: mysql_mutex.h:57
#define mysql_mutex_init(K, M, A)
Definition: mysql_mutex.h:41
unsigned int PSI_cond_key
Instrumented cond key.
Definition: psi_cond_bits.h:44
unsigned int PSI_mutex_key
Instrumented mutex key.
Definition: psi_mutex_bits.h:52
#define mysql_mutex_assert_owner(M)
Wrapper, to use safe_mutex_assert_owner with instrumented mutexes.
Definition: mysql_mutex.h:112
Instrumentation helpers for mysys threads.
Header for compiler-dependent features.
#define MY_COMPILER_DIAGNOSTIC_PUSH()
save the compiler's diagnostic (enabled warnings, errors, ...) state
Definition: my_compiler.h:285
#define MY_COMPILER_DIAGNOSTIC_POP()
restore the compiler's diagnostic (enabled warnings, errors, ...) state
Definition: my_compiler.h:286
#define MY_COMPILER_CLANG_WORKAROUND_TPARAM_DOCBUG()
ignore -Wdocumentation compiler warnings for @tparam.
Definition: my_compiler.h:308
Defines various enable/disable and HAVE_ macros related to the performance schema instrumentation sys...
Instrumentation helpers for conditions.
ABI for instrumented mutexes.
ulong max_connections
Definition: mysqld.cc:1380
The version of the current data dictionary table definitions.
Definition: dictionary_client.h:43
Provides atomic access in shared-exclusive modes.
Definition: shared_spin_lock.h:79
std::map< Key, Value, Compare, ut::allocator< std::pair< const Key, Value > > > map
Specialization of map which uses ut_allocator.
Definition: ut0new.h:2892
static std::mutex lock
Definition: net_ns.cc:56
Instrumentation helpers for conditions.
Instrumentation helpers for mutexes.
Performance schema instrumentation interface.
Performance schema instrumentation interface.
PSI_memory_key key_memory_DD_cache_infrastructure
Definition: psi_memory_key.cc:37
Instrumentation helpers for mutexes.
required string key
Definition: replication_asynchronous_connection_failover.proto:60
PSI_mutex_key key_object_cache_mutex
Definition: mysqld.cc:13340
PSI_cond_key key_object_loading_cond
Definition: mysqld.cc:13341
case opt name
Definition: sslopt-case.h:29
An instrumented cond structure.
Definition: mysql_cond_bits.h:50
An instrumented mutex structure.
Definition: mysql_mutex_bits.h:50
MySQL mutex implementation.
#define MY_MUTEX_INIT_FAST
Definition: thr_mutex.h:68