diff --git a/include/ircd/db/database/env/port.h b/include/ircd/db/database/env/port.h new file mode 100644 index 000000000..f6e0bc137 --- /dev/null +++ b/include/ircd/db/database/env/port.h @@ -0,0 +1,89 @@ +// Matrix Construct +// +// Copyright (C) Matrix Construct Developers, Authors & Contributors +// Copyright (C) 2016-2018 Jason Volk +// +// Permission to use, copy, modify, and/or distribute this software for any +// purpose with or without fee is hereby granted, provided that the above +// copyright notice and this permission notice is present in all copies. The +// full license for this software is available in the LICENSE file. + +#pragma once +#define HAVE_IRCD_DB_DATABASE_ENV_PORT_H + +// This file is not part of the standard include stack because it requires +// RocksDB symbols which we cannot forward declare. It is used internally +// and does not need to be included by general users of IRCd. + +// !!! EXPERIMENTAL !!! +// +// This file is special; even within the context of embedding RocksDB through +// its env interface. The functionality provided here is NOT done via +// overriding virtual interfaces called by RocksDB like with the rest of env. +// This functionality is deemed too critical for runtime virtual interfaces. +// +// Instead, the definitions we provide override those that RocksDB uses at +// link-time during the compilation of libircd. Interface declarations are not +// provided by RocksDB in its include path either, thus our interface here must +// match the rocksdb::port interface. +// +// Unfortunately if the rocksdb::port interface partially changes and we leave +// unresolved symbols at link time that may be bad, and go silently unnoticed. +// +// !!! EXPERIMENTAL !!! + +namespace rocksdb::port +{ + struct Mutex; + struct CondVar; + struct RWMutex; +} + +class rocksdb::port::Mutex +{ + friend class CondVar; + + std::mutex mu; + + public: + void Lock(); + void Unlock(); + void AssertHeld(); + + Mutex(); + Mutex(bool adaptive); + Mutex(const Mutex &) = delete; + Mutex &operator=(const Mutex &) = delete; + ~Mutex(); +}; + +class rocksdb::port::CondVar +{ + Mutex *mu; + std::condition_variable cv; + + public: + void Wait(); + bool TimedWait(uint64_t abs_time_us); // Returns true if timeout occurred + void Signal(); + void SignalAll(); + + CondVar(Mutex *mu); + ~CondVar(); +}; + +class rocksdb::port::RWMutex +{ + std::shared_mutex mu; + + public: + void ReadLock(); + void WriteLock(); + void ReadUnlock(); + void WriteUnlock(); + + RWMutex(); + RWMutex(const RWMutex &) = delete; + RWMutex &operator=(const RWMutex &) = delete; + ~RWMutex(); +}; diff --git a/ircd/db.cc b/ircd/db.cc index 385eac652..e99108907 100644 --- a/ircd/db.cc +++ b/ircd/db.cc @@ -26,6 +26,7 @@ #include #include +// ircd::db interfaces requiring complete RocksDB (frontside). #include #include #include @@ -34,6 +35,8 @@ #include #include #include + +// RocksDB embedding environment callback interfaces (backside). #include #include #include @@ -42,8 +45,18 @@ #include #include +// RocksDB port linktime-overriding interfaces (experimental). +#ifdef IRCD_DB_PORT +#include +#endif + +// Internal utility interface for this definition file. #include "db.h" +// +// Misc / General linkages +// + decltype(ircd::db::log) ircd::db::log { @@ -2923,6 +2936,125 @@ noexcept { } +// +// rocksdb::port (EXPERIMENTAL) +// + +#ifdef IRCD_DB_PORT + +// +// Mutex +// + +rocksdb::port::Mutex::Mutex() +{ +} + +rocksdb::port::Mutex::Mutex(bool adaptive) +{ +} + +void +rocksdb::port::Mutex::Lock() +{ + mu.lock(); +} + +void +rocksdb::port::Mutex::Unlock() +{ + mu.unlock(); +} + +void +rocksdb::port::Mutex::AssertHeld() +{ + assert(1); +} + +// +// RWMutex +// + +rocksdb::port::RWMutex::RWMutex() +{ +} + +rocksdb::port::RWMutex::~RWMutex() +{ +} + +void +rocksdb::port::RWMutex::ReadLock() +{ + mu.lock_shared(); +} + +void +rocksdb::port::RWMutex::WriteLock() +{ + mu.lock(); +} + +void +rocksdb::port::RWMutex::ReadUnlock() +{ + mu.unlock_shared(); +} + +void +rocksdb::port::RWMutex::WriteUnlock() +{ + mu.unlock(); +} + +// +// CondVar +// + +rocksdb::port::CondVar::CondVar(Mutex *mu) +:mu{mu} +{ +} + +rocksdb::port::CondVar::~CondVar() +{ +} + +void +rocksdb::port::CondVar::Wait() +{ + assert(mu); + std::unique_lockmu)> ul(mu->mu); + cv.wait(ul); +} + +// Returns true if timeout occurred +bool +rocksdb::port::CondVar::TimedWait(uint64_t abs_time_us) +{ + assert(mu); + const std::chrono::microseconds us(abs_time_us); + const std::chrono::system_clock::time_point tp(us); + std::unique_lockmu)> ul(mu->mu); + const auto cvs(cv.wait_until(ul, tp)); + return cvs == std::cv_status::timeout; +} + +void +rocksdb::port::CondVar::Signal() +{ + cv.notify_one(); +} + +void +rocksdb::port::CondVar::SignalAll() +{ + cv.notify_all(); +} + +#endif // IRCD_DB_PORT + /////////////////////////////////////////////////////////////////////////////// // // db/txn.h