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