From 4887f3789817f87bf1272af0b52684e3364270c2 Mon Sep 17 00:00:00 2001 From: jacqueline Date: Wed, 8 Mar 2023 11:35:54 +1100 Subject: add leveldb --- src/database/include/env_esp.hpp | 152 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 152 insertions(+) create mode 100644 src/database/include/env_esp.hpp (limited to 'src/database/include/env_esp.hpp') diff --git a/src/database/include/env_esp.hpp b/src/database/include/env_esp.hpp new file mode 100644 index 00000000..c9b3fbc8 --- /dev/null +++ b/src/database/include/env_esp.hpp @@ -0,0 +1,152 @@ +#pragma once + +#include +#include + +#include "freertos/FreeRTOS.h" +#include "freertos/queue.h" +#include "leveldb/env.h" +#include "leveldb/status.h" + +namespace leveldb { + +// Tracks the files locked by EspEnv::LockFile(). +// +// We maintain a separate set instead of relying on fcntl(F_SETLK) because +// fcntl(F_SETLK) does not provide any protection against multiple uses from the +// same process. +// +// Instances are thread-safe because all member data is guarded by a mutex. +class InMemoryLockTable { + public: + bool Insert(const std::string& fname) { + mu_.lock(); + bool succeeded = locked_files_.insert(fname).second; + mu_.unlock(); + return succeeded; + } + void Remove(const std::string& fname) { + mu_.lock(); + locked_files_.erase(fname); + mu_.unlock(); + } + + private: + std::mutex mu_; + std::set locked_files_; +}; + +class EspEnv : public leveldb::Env { + public: + EspEnv(); + ~EspEnv() override; + + Status NewSequentialFile(const std::string& filename, + SequentialFile** result) override; + + Status NewRandomAccessFile(const std::string& filename, + RandomAccessFile** result) override; + + Status NewWritableFile(const std::string& filename, + WritableFile** result) override; + + Status NewAppendableFile(const std::string& filename, + WritableFile** result) override; + + bool FileExists(const std::string& filename) override; + + Status GetChildren(const std::string& directory_path, + std::vector* result) override; + + Status RemoveFile(const std::string& filename) override; + + Status CreateDir(const std::string& dirname) override; + + Status RemoveDir(const std::string& dirname) override; + + Status GetFileSize(const std::string& filename, uint64_t* size) override; + + Status RenameFile(const std::string& from, const std::string& to) override; + + Status LockFile(const std::string& filename, FileLock** lock) override; + + Status UnlockFile(FileLock* lock) override; + + void Schedule(void (*background_work_function)(void* background_work_arg), + void* background_work_arg) override; + + void StartThread(void (*thread_main)(void* thread_main_arg), + void* thread_main_arg) override; + + Status GetTestDirectory(std::string* result) override; + + Status NewLogger(const std::string& filename, Logger** result) override; + + uint64_t NowMicros() override; + + void SleepForMicroseconds(int micros) override; + + void BackgroundThreadMain(); + + private: + // Stores the work item data in a Schedule() call. + // + // Instances are constructed on the thread calling Schedule() and used on the + // background thread. + // + // This structure is thread-safe beacuse it is immutable. + struct BackgroundWorkItem { + explicit BackgroundWorkItem(void (*f)(void*), void* a) + : function(f), arg(a) {} + + void (*const function)(void*); + void* const arg; + }; + + std::mutex background_work_mutex_; + bool started_background_thread_; + + QueueHandle_t background_work_queue_; + + InMemoryLockTable locks_; // Thread-safe. +}; + +} // namespace leveldb + +namespace database { + +// Wraps an Env instance whose destructor is never created. +// +// Intended usage: +// using PlatformSingletonEnv = SingletonEnv; +// void ConfigurePosixEnv(int param) { +// PlatformSingletonEnv::AssertEnvNotInitialized(); +// // set global configuration flags. +// } +// Env* Env::Default() { +// static PlatformSingletonEnv default_env; +// return default_env.env(); +// } +template +class SingletonEnv { + public: + SingletonEnv() { + static_assert(sizeof(env_storage_) >= sizeof(EnvType), + "env_storage_ will not fit the Env"); + static_assert(alignof(decltype(env_storage_)) >= alignof(EnvType), + "env_storage_ does not meet the Env's alignment needs"); + new (&env_storage_) EnvType(); + } + ~SingletonEnv() = default; + + SingletonEnv(const SingletonEnv&) = delete; + SingletonEnv& operator=(const SingletonEnv&) = delete; + + leveldb::Env* env() { return reinterpret_cast(&env_storage_); } + + private: + typename std::aligned_storage::type + env_storage_; +}; + +} // namespace database -- cgit v1.2.3