/* Portions Copyright (c) 2015-Present, Facebook, Inc. Portions Copyright (c) 2012, Monty Program Ab This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; version 2 of the License. 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 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 Street, Fifth Floor, Boston, MA 02111-1301 USA */ #pragma once /* C++ standard header files */ #include #include /* MySQL includes */ #include "./my_global.h" #ifdef _WIN32 #include /* Rocksdb implements their own pthread_key functions undefine some my_pthread.h macros */ #undef pthread_key_create #undef pthread_key_delete #undef pthread_setspecific #undef pthread_getspecific #endif #include // #include /* MyRocks header files */ #include "./rdb_utils.h" #include "rocksdb/db.h" namespace myrocks { class Rdb_thread { private: // Disable Copying Rdb_thread(const Rdb_thread &); Rdb_thread &operator=(const Rdb_thread &); // Make sure we run only once std::atomic_bool m_run_once; pthread_t m_handle; std::string m_name; protected: mysql_mutex_t m_signal_mutex; mysql_cond_t m_signal_cond; bool m_stop = false; public: Rdb_thread() : m_run_once(false) {} #ifdef HAVE_PSI_INTERFACE void init(my_core::PSI_mutex_key stop_bg_psi_mutex_key, my_core::PSI_cond_key stop_bg_psi_cond_key); int create_thread(const std::string &thread_name, my_core::PSI_thread_key background_psi_thread_key); #else void init(); int create_thread(const std::string &thread_name); #endif virtual void run(void) = 0; void signal(const bool stop_thread = false); int join() { #ifndef _WIN32 return pthread_join(m_handle, nullptr); #else /* mysys on Windows creates "detached" threads in pthread_create(). m_handle here is the thread id I(it is not reused by the OS thus it is safe to state there can't be other thread with the same id at this point). If thread is already finished before pthread_join(), we get EINVAL, and it is safe to ignore and handle this as success. */ pthread_join(m_handle, nullptr); return 0; #endif } void setname() { /* mysql_thread_create() ends up doing some work underneath and setting the thread name as "my-func". This isn't what we want. Our intent is to name the threads according to their purpose so that when displayed under the debugger then they'll be more easily identifiable. Therefore we'll reset the name if thread was successfully created. */ /* We originally had the creator also set the thread name, but that seems to not work correctly in all situations. Having the created thread do the pthread_setname_np resolves the issue. */ DBUG_ASSERT(!m_name.empty()); #ifdef __linux__ int err = pthread_setname_np(m_handle, m_name.c_str()); if (err) { // NO_LINT_DEBUG sql_print_warning( "MyRocks: Failed to set name (%s) for current thread, errno=%d,%d", m_name.c_str(), errno, err); } #endif } void uninit(); virtual ~Rdb_thread() = default; private: static void *thread_func(void *const thread_ptr); }; /** MyRocks background thread control N.B. This is on top of RocksDB's own background threads (@see rocksdb::CancelAllBackgroundWork()) */ class Rdb_background_thread : public Rdb_thread { private: bool m_save_stats = false; void reset() { mysql_mutex_assert_owner(&m_signal_mutex); m_stop = false; m_save_stats = false; } public: virtual void run() override; void request_save_stats() { RDB_MUTEX_LOCK_CHECK(m_signal_mutex); m_save_stats = true; RDB_MUTEX_UNLOCK_CHECK(m_signal_mutex); } }; class Rdb_manual_compaction_thread : public Rdb_thread { private: struct Manual_compaction_request { int mc_id; enum mc_state { INITED = 0, RUNNING } state; rocksdb::ColumnFamilyHandle *cf; rocksdb::Slice *start; rocksdb::Slice *limit; int concurrency = 0; }; int m_latest_mc_id; mysql_mutex_t m_mc_mutex; std::map m_requests; public: virtual void run() override; int request_manual_compaction(rocksdb::ColumnFamilyHandle *cf, rocksdb::Slice *start, rocksdb::Slice *limit, int concurrency = 0); bool is_manual_compaction_finished(int mc_id); void clear_manual_compaction_request(int mc_id, bool init_only = false); void clear_all_manual_compaction_requests(); }; /* Drop index thread control */ struct Rdb_drop_index_thread : public Rdb_thread { virtual void run() override; }; } // namespace myrocks