/* Copyright (c) 2015, 2024, Oracle and/or its affiliates. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License, version 2.0, as published by the Free Software Foundation. This program is designed to work with certain software (including but not limited to OpenSSL) that is licensed under separate terms, as designated in a particular file or component or in included license documentation. The authors of MySQL hereby grant you an additional permission to link the program and your derivative works with the separately licensed software that they have either included with the program or referenced in the documentation. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License, version 2.0, for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #ifndef DD_CACHE__STORAGE_ADAPTER_INCLUDED #define DD_CACHE__STORAGE_ADAPTER_INCLUDED #include #include "mysql/components/services/bits/mysql_mutex_bits.h" #include "mysql/components/services/bits/psi_bits.h" #include "mysql/psi/mysql_mutex.h" #include "sql/dd/cache/object_registry.h" // Object_registry #include "sql/dd/object_id.h" #include "sql/handler.h" // enum_tx_isolation #include "thr_mutex.h" class THD; namespace dd_cache_unittest { class CacheStorageTest; } namespace dd { namespace cache { /** Handling of access to persistent storage. This class provides static template functions that manipulates an object on persistent storage based on the submitted key and object type. There is also an object registry instance to keep the core DD objects that are needed to handle cache misses for table meta data. The storage adapter owns the objects in the core registry. When adding objects to the registry using core_store(), the storage adapter will clone the object and take ownership of the clone. When retrieving objects from the registry using core_get(), a clone of the object will be returned, and this is therefore owned by the caller. */ class Storage_adapter { friend class dd_cache_unittest::CacheStorageTest; private: /** Use an id not starting at 1 to make it easy to recognize ids generated before objects are stored persistently. */ static const Object_id FIRST_OID = 10001; /** Generate a new object id for a registry partition. Simulate an auto increment column. Used when the server is starting, while the scaffolding is being built. @tparam T Object registry partition. @return Next object id to be used. */ template Object_id next_oid(); /** Get a dictionary object from core storage. A clone of the registry object will be returned, owned by the caller. @tparam K Key type. @tparam T Dictionary object type. @param key Key for which to get the object. @param [out] object Object retrieved, possibly nullptr if not present. */ template void core_get(const K &key, const T **object); Object_registry m_core_registry; // Object registry storing core DD objects. mysql_mutex_t m_lock; // Single mutex to protect the registry. static bool s_use_fake_storage; // Whether to use the core registry to // simulate the storage engine. Storage_adapter() { mysql_mutex_init(PSI_NOT_INSTRUMENTED, &m_lock, MY_MUTEX_INIT_FAST); } ~Storage_adapter() { mysql_mutex_lock(&m_lock); m_core_registry.erase_all(); mysql_mutex_unlock(&m_lock); mysql_mutex_destroy(&m_lock); } public: static Storage_adapter *instance(); /** Get the number of core objects in a registry partition. @tparam T Dictionary object type. @return Number of elements. */ template size_t core_size(); /** Get a dictionary object id from core storage. @tparam T Dictionary object type. @param key Name key for which to get the object id. @return Object id, INVALID_OBJECT_ID if the object is not present. */ template Object_id core_get_id(const typename T::Name_key &key); /** Update the dd object in the core registry. This is a noop unless this member function is overloaded for a given type. See below. */ template void core_update(const T *) {} /** Overload of core_update for dd::Tablespace. Currently the core registry can only be updated for the DD tablespace when encrypting it. A clone of the dd::Tablespace object passed in is stored in the registry. @param new_tsp the new dd::Tablespace object to keep in the core registry. */ void core_update(const dd::Tablespace *new_tsp); /** Get a dictionary object from persistent storage. Create an access key based on the submitted key, and find the record from the appropriate table. Restore the record into a new dictionary object. @tparam K Key type. @tparam T Dictionary object type. @param thd Thread context. @param key Key for which to get the object. @param isolation Isolation level. @param bypass_core_registry If set to true, get the object from the DD tables. Needed during DD bootstrap. @param [out] object Object retrieved, possibly NULL if not present. @retval false No error. @retval true Error. */ template static bool get(THD *thd, const K &key, enum_tx_isolation isolation, bool bypass_core_registry, const T **object); /** Drop a dictionary object from core storage. @tparam T Dictionary object type. @param thd Thread context. @param object Object to be dropped. */ template void core_drop(THD *thd, const T *object); /** Drop a dictionary object from persistent storage. @tparam T Dictionary object type. @param thd Thread context. @param object Object to be dropped. @retval false No error. @retval true Error. */ template static bool drop(THD *thd, const T *object); /** Store a dictionary object to core storage. A clone of the submitted object will be added to the core storage. The caller is still the owner of the submitted objecct. @tparam T Dictionary object type. @param thd Thread context. @param object Object to be stored. */ template void core_store(THD *thd, T *object); /** Store a dictionary object to persistent storage. @tparam T Dictionary object type. @param thd Thread context. @param object Object to be stored. @retval false No error. @retval true Error. */ template static bool store(THD *thd, T *object); /** Sync a dictionary object from persistent to core storage. @tparam T Dictionary object type. @param thd Thread context. @param key Key for object to get from persistent storage. @param object Object to drop from the core registry. */ template bool core_sync(THD *thd, const typename T::Name_key &key, const T *object); /** Remove and delete all elements and objects from core storage. */ void erase_all(); /** Dump the contents of the core storage. */ void dump(); }; } // namespace cache } // namespace dd #endif // DD_CACHE__STORAGE_ADAPTER_INCLUDED