From c31bf75a241d6df2782da55ea333f1c275fb8fb3 Mon Sep 17 00:00:00 2001 From: Alonso Schaich Date: Thu, 14 Nov 2024 00:53:06 +0900 Subject: [PATCH] Move implementation out of interface headers (estraier/tkrzw#61) tkrzw has quite a bit of code that is implemented in header files that are supposed to be included by consuming projects. This causes some technical issues with [weak symbols](https://en.wikipedia.org/wiki/Weak_symbol) inside the consumer's translation units (or `.obj` files), that might fail to be deduplicated if the consuming project uses compiler settings different from those used by the tkrzw build system. More importantly, however, parts of the code, especially imlementations of non-virtual functions, might end up being embedded into consumer applications when an optimization phase eliminates the procedure calls, raising many concerns considering licensing. This commit moves all implementations from header files documented for inclusion into third-party projects on https://dbmx.net/tkrzw/, as well as any header that implicitly gets included by including a tkrzw interface header into source files. Further, `inline` declarations are removed as within tkrzw, the inlining happens on the discredition of the linker independed of the `inline` keyword, while cross-module inlining is what this commit is supposed to interdict. Nothing can be done about template code in tkrzw_lib_common.h , however, template code is whitelisted on GPLv3. --- VCMakefile | 2 +- configure | 2 +- configure.in | 2 +- tkrzw_compress.cc | 6 + tkrzw_compress.h | 5 +- tkrzw_dbm.cc | 673 +++++++++++++++++++++++++++++++++++++++ tkrzw_dbm.h | 618 ++++++----------------------------- tkrzw_dbm_baby.cc | 17 + tkrzw_dbm_baby.h | 17 +- tkrzw_dbm_cache.cc | 33 ++ tkrzw_dbm_cache.h | 33 +- tkrzw_dbm_hash.cc | 26 ++ tkrzw_dbm_hash.h | 26 +- tkrzw_dbm_poly.cc | 36 +++ tkrzw_dbm_poly.h | 36 +-- tkrzw_dbm_skip.cc | 18 ++ tkrzw_dbm_skip.h | 18 +- tkrzw_dbm_std.cc | 16 + tkrzw_dbm_std.h | 16 +- tkrzw_dbm_tiny.cc | 28 ++ tkrzw_dbm_tiny.h | 28 +- tkrzw_dbm_tree.cc | 16 + tkrzw_dbm_tree.h | 14 +- tkrzw_file.cc | 57 ++++ tkrzw_file.h | 37 +-- tkrzw_key_comparators.cc | 152 +++++++++ tkrzw_key_comparators.h | 132 +------- tkrzw_lib_common.cc | 240 ++++++++++++++ tkrzw_lib_common.h | 236 +++----------- 29 files changed, 1516 insertions(+), 1024 deletions(-) create mode 100644 tkrzw_file.cc create mode 100644 tkrzw_key_comparators.cc diff --git a/VCMakefile b/VCMakefile index 45d2cb8..8918bce 100644 --- a/VCMakefile +++ b/VCMakefile @@ -20,7 +20,7 @@ LIBEXECDIR = $(BASEDIR)\bin HEADERFILES = tkrzw_lib_common.h tkrzw_str_util.h tkrzw_hash_util.h tkrzw_time_util.h tkrzw_thread_util.h tkrzw_logger.h tkrzw_compress.h tkrzw_containers.h tkrzw_key_comparators.h tkrzw_file.h tkrzw_file_util.h tkrzw_file_std.h tkrzw_file_mmap.h tkrzw_file_pos.h tkrzw_file_poly.h tkrzw_message_queue.h tkrzw_dbm.h tkrzw_dbm_ulog.h tkrzw_dbm_common_impl.h tkrzw_dbm_hash_impl.h tkrzw_dbm_hash.h tkrzw_dbm_tree_impl.h tkrzw_dbm_tree.h tkrzw_dbm_skip_impl.h tkrzw_dbm_skip.h tkrzw_dbm_tiny.h tkrzw_dbm_baby.h tkrzw_dbm_cache.h tkrzw_dbm_std.h tkrzw_dbm_poly.h tkrzw_dbm_shard.h tkrzw_dbm_async.h tkrzw_index.h tkrzw_cmd_util.h tkrzw_langc.h IMPLHEADERFILES = tkrzw_sys_config.h tkrzw_sys_util_windows.h tkrzw_sys_file_mmap_std.h tkrzw_sys_file_mmap_windows.h tkrzw_sys_file_pos_std.h tkrzw_sys_file_pos_windows.h tkrzw_sys_compress_aes.h LIBRARYFILES = tkrzw.lib -LIBOBJFILES = tkrzw_lib_common.obj tkrzw_str_util.obj tkrzw_hash_util.obj tkrzw_time_util.obj tkrzw_compress.obj tkrzw_file_util.obj tkrzw_file_std.obj tkrzw_file_mmap.obj tkrzw_file_pos.obj tkrzw_file_poly.obj tkrzw_message_queue.obj tkrzw_dbm.obj tkrzw_dbm_ulog.obj tkrzw_dbm_common_impl.obj tkrzw_dbm_hash_impl.obj tkrzw_dbm_hash.obj tkrzw_dbm_tree_impl.obj tkrzw_dbm_tree.obj tkrzw_dbm_skip_impl.obj tkrzw_dbm_skip.obj tkrzw_dbm_tiny.obj tkrzw_dbm_baby.obj tkrzw_dbm_cache.obj tkrzw_dbm_std.obj tkrzw_dbm_poly.obj tkrzw_dbm_shard.obj tkrzw_dbm_async.obj tkrzw_cmd_util.obj tkrzw_langc.obj +LIBOBJFILES = tkrzw_lib_common.obj tkrzw_str_util.obj tkrzw_hash_util.obj tkrzw_time_util.obj tkrzw_compress.obj tkrzw_key_comparators.obj tkrzw_file.obj tkrzw_file_util.obj tkrzw_file_std.obj tkrzw_file_mmap.obj tkrzw_file_pos.obj tkrzw_file_poly.obj tkrzw_message_queue.obj tkrzw_dbm.obj tkrzw_dbm_ulog.obj tkrzw_dbm_common_impl.obj tkrzw_dbm_hash_impl.obj tkrzw_dbm_hash.obj tkrzw_dbm_tree_impl.obj tkrzw_dbm_tree.obj tkrzw_dbm_skip_impl.obj tkrzw_dbm_skip.obj tkrzw_dbm_tiny.obj tkrzw_dbm_baby.obj tkrzw_dbm_cache.obj tkrzw_dbm_std.obj tkrzw_dbm_poly.obj tkrzw_dbm_shard.obj tkrzw_dbm_async.obj tkrzw_cmd_util.obj tkrzw_langc.obj COMMANDFILES = tkrzw_build_util.exe tkrzw_str_perf.exe tkrzw_file_perf.exe tkrzw_dbm_util.exe tkrzw_dbm_perf.exe tkrzw_dbm_tran.exe tkrzw_ulog_util.exe tkrzw_langc_check.exe CMDLIBRARIES = tkrzw.lib EXTRALIBRARIES = diff --git a/configure b/configure index 3701db2..40f19c2 100755 --- a/configure +++ b/configure @@ -2142,7 +2142,7 @@ MYLIBFMT=0 # Targets MYHEADERFILES="tkrzw_lib_common.h tkrzw_str_util.h tkrzw_hash_util.h tkrzw_time_util.h tkrzw_thread_util.h tkrzw_logger.h tkrzw_compress.h tkrzw_containers.h tkrzw_key_comparators.h tkrzw_file.h tkrzw_file_util.h tkrzw_file_std.h tkrzw_file_mmap.h tkrzw_file_pos.h tkrzw_file_poly.h tkrzw_message_queue.h tkrzw_dbm.h tkrzw_dbm_ulog.h tkrzw_dbm_common_impl.h tkrzw_dbm_hash_impl.h tkrzw_dbm_hash.h tkrzw_dbm_tree_impl.h tkrzw_dbm_tree.h tkrzw_dbm_skip_impl.h tkrzw_dbm_skip.h tkrzw_dbm_tiny.h tkrzw_dbm_baby.h tkrzw_dbm_cache.h tkrzw_dbm_std.h tkrzw_dbm_poly.h tkrzw_dbm_shard.h tkrzw_dbm_async.h tkrzw_index.h tkrzw_cmd_util.h tkrzw_langc.h" MYLIBRARYFILES="libtkrzw.a" -MYLIBOBJFILES="tkrzw_lib_common.o tkrzw_str_util.o tkrzw_hash_util.o tkrzw_time_util.o tkrzw_compress.o tkrzw_file_util.o tkrzw_file_std.o tkrzw_file_mmap.o tkrzw_file_pos.o tkrzw_file_poly.o tkrzw_message_queue.o tkrzw_dbm.o tkrzw_dbm_ulog.o tkrzw_dbm_common_impl.o tkrzw_dbm_hash_impl.o tkrzw_dbm_hash.o tkrzw_dbm_tree_impl.o tkrzw_dbm_tree.o tkrzw_dbm_skip_impl.o tkrzw_dbm_skip.o tkrzw_dbm_tiny.o tkrzw_dbm_baby.o tkrzw_dbm_cache.o tkrzw_dbm_std.o tkrzw_dbm_poly.o tkrzw_dbm_shard.o tkrzw_dbm_async.o tkrzw_cmd_util.o tkrzw_langc.o" +MYLIBOBJFILES="tkrzw_lib_common.o tkrzw_str_util.o tkrzw_hash_util.o tkrzw_time_util.o tkrzw_compress.o tkrzw_key_comparators.o tkrzw_file.o tkrzw_file_util.o tkrzw_file_std.o tkrzw_file_mmap.o tkrzw_file_pos.o tkrzw_file_poly.o tkrzw_message_queue.o tkrzw_dbm.o tkrzw_dbm_ulog.o tkrzw_dbm_common_impl.o tkrzw_dbm_hash_impl.o tkrzw_dbm_hash.o tkrzw_dbm_tree_impl.o tkrzw_dbm_tree.o tkrzw_dbm_skip_impl.o tkrzw_dbm_skip.o tkrzw_dbm_tiny.o tkrzw_dbm_baby.o tkrzw_dbm_cache.o tkrzw_dbm_std.o tkrzw_dbm_poly.o tkrzw_dbm_shard.o tkrzw_dbm_async.o tkrzw_cmd_util.o tkrzw_langc.o" MYCOMMANDFILES="tkrzw_build_util tkrzw_str_perf tkrzw_file_perf tkrzw_dbm_util tkrzw_dbm_perf tkrzw_dbm_tran tkrzw_ulog_util tkrzw_langc_check" MYTESTFILES="tkrzw_sys_config_test tkrzw_lib_common_test tkrzw_str_util_test tkrzw_hash_util_test tkrzw_time_util_test tkrzw_thread_util_test tkrzw_logger_test tkrzw_compress_test tkrzw_containers_test tkrzw_key_comparators_test tkrzw_file_util_test tkrzw_file_std_test tkrzw_file_mmap_test tkrzw_file_pos_test tkrzw_file_poly_test tkrzw_message_queue_test tkrzw_dbm_common_impl_test tkrzw_dbm_ulog_test tkrzw_dbm_hash_impl_test tkrzw_dbm_tree_impl_test tkrzw_dbm_tree_test tkrzw_dbm_hash_test tkrzw_dbm_skip_impl_test tkrzw_dbm_skip_test tkrzw_dbm_tiny_test tkrzw_dbm_baby_test tkrzw_dbm_cache_test tkrzw_dbm_std_test tkrzw_dbm_poly_test tkrzw_dbm_shard_test tkrzw_dbm_async_test tkrzw_index_test tkrzw_cmd_util_test tkrzw_langc_test" MYPCFILES="tkrzw.pc" diff --git a/configure.in b/configure.in index 46e6de5..4feef12 100644 --- a/configure.in +++ b/configure.in @@ -15,7 +15,7 @@ MYLIBFMT=0 # Targets MYHEADERFILES="tkrzw_lib_common.h tkrzw_str_util.h tkrzw_hash_util.h tkrzw_time_util.h tkrzw_thread_util.h tkrzw_logger.h tkrzw_compress.h tkrzw_containers.h tkrzw_key_comparators.h tkrzw_file.h tkrzw_file_util.h tkrzw_file_std.h tkrzw_file_mmap.h tkrzw_file_pos.h tkrzw_file_poly.h tkrzw_message_queue.h tkrzw_dbm.h tkrzw_dbm_ulog.h tkrzw_dbm_common_impl.h tkrzw_dbm_hash_impl.h tkrzw_dbm_hash.h tkrzw_dbm_tree_impl.h tkrzw_dbm_tree.h tkrzw_dbm_skip_impl.h tkrzw_dbm_skip.h tkrzw_dbm_tiny.h tkrzw_dbm_baby.h tkrzw_dbm_cache.h tkrzw_dbm_std.h tkrzw_dbm_poly.h tkrzw_dbm_shard.h tkrzw_dbm_async.h tkrzw_index.h tkrzw_cmd_util.h tkrzw_langc.h" MYLIBRARYFILES="libtkrzw.a" -MYLIBOBJFILES="tkrzw_lib_common.o tkrzw_str_util.o tkrzw_hash_util.o tkrzw_time_util.o tkrzw_compress.o tkrzw_file_util.o tkrzw_file_std.o tkrzw_file_mmap.o tkrzw_file_pos.o tkrzw_file_poly.o tkrzw_message_queue.o tkrzw_dbm.o tkrzw_dbm_ulog.o tkrzw_dbm_common_impl.o tkrzw_dbm_hash_impl.o tkrzw_dbm_hash.o tkrzw_dbm_tree_impl.o tkrzw_dbm_tree.o tkrzw_dbm_skip_impl.o tkrzw_dbm_skip.o tkrzw_dbm_tiny.o tkrzw_dbm_baby.o tkrzw_dbm_cache.o tkrzw_dbm_std.o tkrzw_dbm_poly.o tkrzw_dbm_shard.o tkrzw_dbm_async.o tkrzw_cmd_util.o tkrzw_langc.o" +MYLIBOBJFILES="tkrzw_lib_common.o tkrzw_str_util.o tkrzw_hash_util.o tkrzw_time_util.o tkrzw_compress.o tkrzw_key_comparators.o tkrzw_file.o tkrzw_file_util.o tkrzw_file_std.o tkrzw_file_mmap.o tkrzw_file_pos.o tkrzw_file_poly.o tkrzw_message_queue.o tkrzw_dbm.o tkrzw_dbm_ulog.o tkrzw_dbm_common_impl.o tkrzw_dbm_hash_impl.o tkrzw_dbm_tree_impl.o tkrzw_dbm_tree.o tkrzw_dbm_skip_impl.o tkrzw_dbm_skip.o tkrzw_dbm_tiny.o tkrzw_dbm_baby.o tkrzw_dbm_cache.o tkrzw_dbm_std.o tkrzw_dbm_poly.o tkrzw_dbm_shard.o tkrzw_dbm_async.o tkrzw_cmd_util.o tkrzw_langc.o" MYCOMMANDFILES="tkrzw_build_util tkrzw_str_perf tkrzw_file_perf tkrzw_dbm_util tkrzw_dbm_perf tkrzw_dbm_tran tkrzw_ulog_util tkrzw_langc_check" MYTESTFILES="tkrzw_sys_config_test tkrzw_lib_common_test tkrzw_str_util_test tkrzw_hash_util_test tkrzw_time_util_test tkrzw_thread_util_test tkrzw_logger_test tkrzw_compress_test tkrzw_containers_test tkrzw_key_comparators_test tkrzw_file_util_test tkrzw_file_std_test tkrzw_file_mmap_test tkrzw_file_pos_test tkrzw_file_poly_test tkrzw_message_queue_test tkrzw_dbm_common_impl_test tkrzw_dbm_ulog_test tkrzw_dbm_hash_impl_test tkrzw_dbm_tree_impl_test tkrzw_dbm_tree_test tkrzw_dbm_hash_test tkrzw_dbm_skip_impl_test tkrzw_dbm_skip_test tkrzw_dbm_tiny_test tkrzw_dbm_baby_test tkrzw_dbm_cache_test tkrzw_dbm_std_test tkrzw_dbm_poly_test tkrzw_dbm_shard_test tkrzw_dbm_async_test tkrzw_index_test tkrzw_cmd_util_test tkrzw_langc_test" MYPCFILES="tkrzw.pc" diff --git a/tkrzw_compress.cc b/tkrzw_compress.cc index 016f5c7..9fb8a06 100644 --- a/tkrzw_compress.cc +++ b/tkrzw_compress.cc @@ -45,6 +45,12 @@ extern "C" { namespace tkrzw { +const std::type_info& Compressor::GetType() const { + const auto& entity = *this; + return typeid(entity); +} + + DummyCompressor::DummyCompressor(bool checksum) : checksum_(checksum) {} DummyCompressor::~DummyCompressor() {} diff --git a/tkrzw_compress.h b/tkrzw_compress.h index ece9082..d277056 100644 --- a/tkrzw_compress.h +++ b/tkrzw_compress.h @@ -75,10 +75,7 @@ class Compressor { * Gets the type information of the actual class. * @return The type information of the actual class. */ - const std::type_info& GetType() const { - const auto& entity = *this; - return typeid(entity); - } + const std::type_info& GetType() const; }; /** diff --git a/tkrzw_dbm.cc b/tkrzw_dbm.cc index 7624e92..4953116 100644 --- a/tkrzw_dbm.cc +++ b/tkrzw_dbm.cc @@ -26,6 +26,349 @@ const std::string_view DBM::RecordProcessor::NOOP("\x00\xBE\xEF\x02\x11", 5); const std::string_view DBM::RecordProcessor::REMOVE("\x00\xDE\xAD\x02\x11", 5); +std::string_view DBM::RecordProcessor::ProcessFull(std::string_view key, std::string_view value) { + return NOOP; +} + +std::string_view DBM::RecordProcessor::ProcessEmpty(std::string_view key) { + return NOOP; +} + + +DBM::RecordProcessorLambda::RecordProcessorLambda(RecordLambdaType proc_lambda) + : proc_lambda_(proc_lambda) {} + +std::string_view DBM::RecordProcessorLambda::ProcessFull(std::string_view key, std::string_view value) { + return proc_lambda_(key, value); +} + +std::string_view DBM::RecordProcessorLambda::ProcessEmpty(std::string_view key) { + return proc_lambda_(key, NOOP); +} + + +DBM::RecordProcessorGet::RecordProcessorGet(Status* status, std::string* value) + : status_(status), value_(value) {} + +std::string_view DBM::RecordProcessorGet::ProcessFull(std::string_view key, std::string_view value) { + if (value_ != nullptr) { + *value_ = value; + } + return NOOP; +} + + +std::string_view DBM::RecordProcessorGet::ProcessEmpty(std::string_view key) { + status_->Set(Status::NOT_FOUND_ERROR); + return NOOP; +} + +DBM::RecordProcessorSet::RecordProcessorSet(Status* status, std::string_view value, + bool overwrite, std::string* old_value) + : status_(status), value_(value), overwrite_(overwrite), old_value_(old_value) {} + + +std::string_view DBM::RecordProcessorSet::ProcessFull(std::string_view key, std::string_view value) { + if (old_value_ != nullptr) { + *old_value_ = value; + } + if (overwrite_) { + return value_; + } + status_->Set(Status::DUPLICATION_ERROR); + return NOOP; +} + +std::string_view DBM::RecordProcessorSet::ProcessEmpty(std::string_view key) { + return value_; +} + + +DBM::RecordProcessorRemove::RecordProcessorRemove(Status* status, + std::string* old_value) + : status_(status), old_value_(old_value) {} + +std::string_view DBM::RecordProcessorRemove::ProcessFull(std::string_view key, std::string_view value) { + if (old_value_ != nullptr) { + *old_value_ = value; + } + return REMOVE; +} + +std::string_view DBM::RecordProcessorRemove::ProcessEmpty(std::string_view key) { + status_->Set(Status::NOT_FOUND_ERROR); + return NOOP; +} + + +DBM::RecordProcessorAppend::RecordProcessorAppend(std::string_view value, std::string_view delim) + : value_(value), delim_(delim) {} + + +std::string_view DBM::RecordProcessorAppend::ProcessFull(std::string_view key, std::string_view value) { + if (delim_.empty()) { + new_value_.reserve(value.size() + value_.size()); + new_value_.append(value); + new_value_.append(value_); + } else { + new_value_.reserve(value.size() + delim_.size() + value_.size()); + new_value_.append(value); + new_value_.append(delim_); + new_value_.append(value_); + } + return new_value_; +} + +std::string_view DBM::RecordProcessorAppend::ProcessEmpty(std::string_view key) { + return value_; +} + + +DBM::RecordProcessorCompareExchange::RecordProcessorCompareExchange( + Status* status, std::string_view expected, std::string_view desired, std::string* actual, + bool* found) + : status_(status), expected_(expected), desired_(desired), actual_(actual), found_(found) {} + +std::string_view DBM::RecordProcessorCompareExchange::ProcessFull( + std::string_view key, std::string_view value) { + if (actual_ != nullptr) { + *actual_ = value; + } + if (found_ != nullptr) { + *found_ = true; + } + if (expected_.data() != nullptr && (expected_.data() == ANY_DATA.data() || expected_ == value)) { + return desired_.data() == nullptr ? REMOVE : + desired_.data() == ANY_DATA.data() ? NOOP : desired_; + } + status_->Set(Status::INFEASIBLE_ERROR); + return NOOP; +} + +std::string_view DBM::RecordProcessorCompareExchange::ProcessEmpty(std::string_view key) { + if (actual_ != nullptr) { + *actual_ = ""; + } + if (found_ != nullptr) { + *found_ = false; + } + if (expected_.data() == nullptr) { + return desired_.data() == nullptr || desired_.data() == ANY_DATA.data() ? NOOP : desired_; + } + status_->Set(Status::INFEASIBLE_ERROR); + return NOOP; +} + + +DBM::RecordProcessorIncrement::RecordProcessorIncrement(int64_t increment, + int64_t* current, int64_t initial) + : increment_(increment), current_(current), initial_(initial) {} + +std::string_view DBM::RecordProcessorIncrement::ProcessFull(std::string_view key, std::string_view value) { + if (increment_ == INT64MIN) { + if (current_ != nullptr) { + *current_ = StrToIntBigEndian(value); + } + return NOOP; + } + const int64_t num = StrToIntBigEndian(value) + increment_; + if (current_ != nullptr) { + *current_ = num; + } + value_ = IntToStrBigEndian(num); + return value_; +} + +std::string_view DBM::RecordProcessorIncrement::ProcessEmpty(std::string_view key) { + if (increment_ == INT64MIN) { + if (current_ != nullptr) { + *current_ = initial_; + } + return NOOP; + } + const int64_t num = initial_ + increment_; + if (current_ != nullptr) { + *current_ = num; + } + value_ = IntToStrBigEndian(num); + return value_; +} + + +DBM::RecordCheckerCompareExchangeMulti::RecordCheckerCompareExchangeMulti( + bool* noop, std::string_view expected) + : noop_(noop), expected_(expected) {} + +std::string_view DBM::RecordCheckerCompareExchangeMulti::ProcessFull( + std::string_view key, std::string_view value) { + if (expected_.data() == nullptr || (expected_.data() != ANY_DATA.data() && expected_ != value)) { + *noop_ = true; + } + return NOOP; +} + + +std::string_view DBM::RecordCheckerCompareExchangeMulti::ProcessEmpty(std::string_view key) { + if (expected_.data() != nullptr) { + *noop_ = true; + } + return NOOP; +} + + +DBM::RecordSetterCompareExchangeMulti::RecordSetterCompareExchangeMulti( + bool* noop, std::string_view desired) + : noop_(noop), desired_(desired) {} + +std::string_view DBM::RecordSetterCompareExchangeMulti::ProcessFull(std::string_view key, std::string_view value) { + if (*noop_) { + return NOOP; + } + return desired_.data() == nullptr ? REMOVE : desired_; +} + +std::string_view DBM::RecordSetterCompareExchangeMulti::ProcessEmpty(std::string_view key) { + if (*noop_) { + return NOOP; + } + return desired_.data() == nullptr ? NOOP : desired_; +} + + +DBM::RecordCheckerRekey::RecordCheckerRekey(Status* status) : status_(status) {} + +std::string_view DBM::RecordCheckerRekey::ProcessFull(std::string_view key, std::string_view value) { + status_->Set(Status::DUPLICATION_ERROR); + return NOOP; +} + +std::string_view DBM::RecordCheckerRekey::ProcessEmpty(std::string_view key) { + return NOOP; +} + + +DBM::RecordRemoverRekey::RecordRemoverRekey(Status* status, std::string* old_value, bool copying) + : status_(status), old_value_(old_value), copying_(copying) {} + +std::string_view DBM::RecordRemoverRekey::ProcessFull(std::string_view key, std::string_view value) { + if (*status_ != Status::SUCCESS) { + return NOOP; + } + *old_value_ = value; + return copying_ ? NOOP : REMOVE; +} + +std::string_view DBM::RecordRemoverRekey::ProcessEmpty(std::string_view key) { + status_->Set(Status::NOT_FOUND_ERROR); + return NOOP; +} + + +DBM::RecordSetterRekey::RecordSetterRekey(Status* status, const std::string* new_value) + : status_(status), new_value_(new_value) {} + +std::string_view DBM::RecordSetterRekey::ProcessFull(std::string_view key, std::string_view value) { + if (*status_ != Status::SUCCESS) { + return NOOP; + } + return *new_value_; +} + +std::string_view DBM::RecordSetterRekey::ProcessEmpty(std::string_view key) { + if (*status_ != Status::SUCCESS) { + return NOOP; + } + return *new_value_; +} + +DBM::RecordProcessorPopFirst::RecordProcessorPopFirst(std::string* key, std::string* value) + : key_(key), value_(value) {} + +std::string_view DBM::RecordProcessorPopFirst::ProcessFull(std::string_view key, + std::string_view value) { + if (key_ != nullptr) { + *key_ = key; + } + if (value_ != nullptr) { + *value_ = value; + } + return REMOVE; +} + + +DBM::RecordProcessorExport::RecordProcessorExport(Status* status, DBM* dbm) + : status_(status), dbm_(dbm) {} + +std::string_view DBM::RecordProcessorExport::ProcessFull( + std::string_view key, std::string_view value) { + *status_ |= dbm_->Set(key, value); + return NOOP; +} + + +DBM::RecordProcessorIterator::RecordProcessorIterator( + std::string_view new_value, std::string* cur_key, std::string* cur_value) + : new_value_(new_value), cur_key_(cur_key), cur_value_(cur_value) {} + +std::string_view DBM::RecordProcessorIterator::ProcessFull( + std::string_view key, std::string_view value) { + if (cur_key_ != nullptr) { + *cur_key_ = key; + } + if (cur_value_ != nullptr) { + *cur_value_ = value; + } + return new_value_; +} + + +Status DBM::Iterator::Process(RecordLambdaType rec_lambda, bool writable) { + RecordProcessorLambda proc(rec_lambda); + return Process(&proc, writable); +} + +Status DBM::Iterator::Get(std::string* key, std::string* value) { + RecordProcessorIterator proc(RecordProcessor::NOOP, key, value); + return Process(&proc, false); +} + +std::string DBM::Iterator::GetKey(std::string_view default_value) { + std::string key; + return Get(&key, nullptr) == Status::SUCCESS ? key : std::string(default_value); +} + +std::string DBM::Iterator::GetValue(std::string_view default_value) { + std::string value; + return Get(nullptr, &value) == Status::SUCCESS ? value : std::string(default_value); +} + +Status DBM::Iterator::Set(std::string_view value, std::string* old_key, + std::string* old_value) { + RecordProcessorIterator proc(value, old_key, old_value); + return Process(&proc, true); +} + +Status DBM::Iterator::Remove(std::string* old_key, std::string* old_value) { + RecordProcessorIterator proc(RecordProcessor::REMOVE, old_key, old_value); + return Process(&proc, true); +} + +Status DBM::Iterator::Step(std::string* key, std::string* value) { + Status status = Get(key, value); + if (status != Status::SUCCESS) { + return status; + } + status = Next(); + if (status == Status::NOT_FOUND_ERROR) { + status.Set(Status::SUCCESS); + } + return status; +} + + +void DBM::FileProcessor::Process(const std::string& path) {} + + DBM::FileProcessorCopyFileData::FileProcessorCopyFileData( Status* status, const std::string dest_path) : status_(status), dest_path_(dest_path) {} @@ -34,6 +377,336 @@ void DBM::FileProcessorCopyFileData::Process(const std::string& path) { *status_ = tkrzw::CopyFileData(path, dest_path_); } + +Status DBM::UpdateLogger::Synchronize(bool hard) { + return Status(Status::SUCCESS); +} + + +Status DBM::Process(std::string_view key, RecordLambdaType rec_lambda, bool writable) { + RecordProcessorLambda proc(rec_lambda); + return Process(key, &proc, writable); +} + +Status DBM::Get(std::string_view key, std::string* value) { + Status impl_status(Status::SUCCESS); + RecordProcessorGet proc(&impl_status, value); + const Status status = Process(key, &proc, false); + if (status != Status::SUCCESS) { + return status; + } + return impl_status; +} + +std::string DBM::GetSimple(std::string_view key, std::string_view default_value) { + std::string value; + return Get(key, &value) == Status::SUCCESS ? value : std::string(default_value); +} + +Status DBM::GetMulti( + const std::vector& keys, std::map* records) { + Status status(Status::SUCCESS); + for (const auto& key : keys) { + std::string value; + const Status tmp_status = Get(key, &value); + if (tmp_status == Status::SUCCESS) { + records->emplace(key, std::move(value)); + } else { + status |= tmp_status; + } + } + return status; +} + +Status DBM::GetMulti(const std::initializer_list& keys, + std::map* records) { + std::vector vector_keys(keys.begin(), keys.end()); + return GetMulti(vector_keys, records); +} + +Status DBM::GetMulti( + const std::vector& keys, std::map* records) { + return GetMulti(MakeStrViewVectorFromValues(keys), records); +} + +Status DBM::Set(std::string_view key, std::string_view value, bool overwrite, + std::string* old_value) { + Status impl_status(Status::SUCCESS); + RecordProcessorSet proc(&impl_status, value, overwrite, old_value); + const Status status = Process(key, &proc, true); + if (status != Status::SUCCESS) { + return status; + } + return impl_status; +} + +Status DBM::SetMulti( + const std::map& records, bool overwrite) { + Status status(Status::SUCCESS); + for (const auto& record : records) { + status |= Set(record.first, record.second, overwrite); + if (status != Status::SUCCESS && status != Status::DUPLICATION_ERROR) { + break; + } + } + return status; +} + +Status DBM::SetMulti( + const std::initializer_list>& records, + bool overwrite) { + std::map map_records; + for (const auto& record : records) { + map_records.emplace(std::pair( + std::string_view(record.first), std::string_view(record.second))); + } + return SetMulti(map_records, overwrite); +} + +Status DBM::SetMulti( + const std::map& records, bool overwrite) { + return SetMulti(MakeStrViewMapFromRecords(records), overwrite); +} + +Status DBM::Remove(std::string_view key, std::string* old_value) { + Status impl_status(Status::SUCCESS); + RecordProcessorRemove proc(&impl_status, old_value); + const Status status = Process(key, &proc, true); + if (status != Status::SUCCESS) { + return status; + } + return impl_status; +} + +Status DBM::RemoveMulti(const std::vector& keys) { + Status status(Status::SUCCESS); + for (const auto& key : keys) { + status |= Remove(key); + if (status != Status::Status::SUCCESS && status != Status::Status::NOT_FOUND_ERROR) { + break; + } + } + return status; +} + +Status DBM::RemoveMulti(const std::initializer_list& keys) { + std::vector vector_keys(keys.begin(), keys.end()); + return RemoveMulti(vector_keys); +} + +Status DBM::RemoveMulti(const std::vector& keys) { + return RemoveMulti(MakeStrViewVectorFromValues(keys)); +} + +Status DBM::Append( + std::string_view key, std::string_view value, std::string_view delim) { + RecordProcessorAppend proc(value, delim); + return Process(key, &proc, true); +} + +Status DBM::AppendMulti( + const std::map& records, std::string_view delim) { + Status status(Status::SUCCESS); + for (const auto& record : records) { + status |= Append(record.first, record.second, delim); + if (status != Status::SUCCESS) { + break; + } + } + return status; +} + +Status DBM::AppendMulti( + const std::initializer_list>& records, + std::string_view delim) { + std::map map_records; + for (const auto& record : records) { + map_records.emplace(std::pair( + std::string_view(record.first), std::string_view(record.second))); + } + return AppendMulti(map_records, delim); +} + + Status DBM::AppendMulti( + const std::map& records, std::string_view delim) { + return AppendMulti(MakeStrViewMapFromRecords(records), delim); +} + +Status DBM::CompareExchange(std::string_view key, std::string_view expected, + std::string_view desired, std::string* actual, bool* found) { + Status impl_status(Status::SUCCESS); + RecordProcessorCompareExchange proc(&impl_status, expected, desired, actual, found); + const Status status = Process(key, &proc, desired.data() != ANY_DATA.data()); + if (status != Status::SUCCESS) { + return status; + } + return impl_status; +} + +Status DBM::Increment(std::string_view key, int64_t increment, + int64_t* current, int64_t initial) { + RecordProcessorIncrement proc(increment, current, initial); + return Process(key, &proc, increment != INT64MIN); +} + +int64_t DBM::IncrementSimple(std::string_view key, int64_t increment, int64_t initial) { + int64_t current = 0; + return Increment(key, increment, ¤t, initial) == Status::SUCCESS ? current : INT64MIN; +} + +Status DBM::ProcessMulti( + const std::vector>& key_lambda_pairs, + bool writable) { + std::vector> key_proc_pairs; + key_proc_pairs.reserve(key_lambda_pairs.size()); + std::vector procs; + procs.reserve(key_lambda_pairs.size()); + for (const auto& key_lambda : key_lambda_pairs) { + procs.emplace_back(key_lambda.second); + key_proc_pairs.emplace_back(std::make_pair(key_lambda.first, &procs.back())); + } + return ProcessMulti(key_proc_pairs, writable); +} + +Status DBM::CompareExchangeMulti( + const std::vector>& expected, + const std::vector>& desired) { + std::vector> key_proc_pairs; + key_proc_pairs.reserve(expected.size() + desired.size()); + bool noop = false; + std::vector checkers; + checkers.reserve(expected.size()); + for (const auto& key_value : expected) { + checkers.emplace_back(RecordCheckerCompareExchangeMulti(&noop, key_value.second)); + key_proc_pairs.emplace_back(std::pair(key_value.first, &checkers.back())); + } + std::vector setters; + setters.reserve(desired.size()); + for (const auto& key_value : desired) { + setters.emplace_back(RecordSetterCompareExchangeMulti(&noop, key_value.second)); + key_proc_pairs.emplace_back(std::pair(key_value.first, &setters.back())); + } + const Status status = ProcessMulti(key_proc_pairs, true); + if (status != Status::SUCCESS) { + return status; + } + return noop ? Status(Status::INFEASIBLE_ERROR) : Status(Status::SUCCESS); +} + +Status DBM::Rekey(std::string_view old_key, std::string_view new_key, + bool overwrite, bool copying, std::string* value) { + std::vector> key_proc_pairs; + key_proc_pairs.reserve(3); + Status proc_status(Status::SUCCESS); + RecordCheckerRekey checker(&proc_status); + if (!overwrite) { + key_proc_pairs.emplace_back(std::pair(new_key, &checker)); + } + std::string rec_value; + RecordRemoverRekey remover(&proc_status, &rec_value, copying); + key_proc_pairs.emplace_back(std::pair(old_key, &remover)); + RecordSetterRekey setter(&proc_status, &rec_value); + key_proc_pairs.emplace_back(std::pair(new_key, &setter)); + const Status status = ProcessMulti(key_proc_pairs, true); + if (status != Status::SUCCESS) { + return status; + } + if (proc_status == Status::SUCCESS && value != nullptr) { + *value = std::move(rec_value); + } + return proc_status; +} + +Status DBM::ProcessFirst(RecordLambdaType rec_lambda, bool writable) { + RecordProcessorLambda proc(rec_lambda); + return ProcessFirst(&proc, writable); +} + +Status DBM::PopFirst(std::string* key, std::string* value) { + RecordProcessorPopFirst proc(key, value); + return ProcessFirst(&proc, true); +} + +Status DBM::PushLast(std::string_view value, double wtime, std::string* key) { + for (uint64_t seq = 0; true; seq++) { + const uint64_t timestamp = + static_cast((wtime < 0 ? GetWallTime() : wtime) * 100000000 + seq); + const std::string& time_key = IntToStrBigEndian(timestamp); + const Status status = Set(time_key, value, false); + if (status != Status::DUPLICATION_ERROR) { + if (key != nullptr) { + *key = time_key; + } + return status; + } + } + return Status(Status::UNKNOWN_ERROR); +} + +Status DBM::ProcessEach(RecordLambdaType rec_lambda, bool writable) { + RecordProcessorLambda proc(rec_lambda); + return ProcessEach(&proc, writable); +} + +int64_t DBM::CountSimple() { + int64_t count = 0; + return Count(&count) == Status::SUCCESS ? count : -1; +} + +int64_t DBM::GetFileSizeSimple() { + int64_t size = 0; + return GetFileSize(&size) == Status::SUCCESS ? size : -1; +} + +std::string DBM::GetFilePathSimple() { + std::string path; + return GetFilePath(&path) == Status::SUCCESS ? path : std::string(""); +} + +double DBM::GetTimestampSimple() { + double timestamp = 0; + return GetTimestamp(×tamp) == Status::SUCCESS ? timestamp : DOUBLENAN; +} + +bool DBM::ShouldBeRebuiltSimple() { + bool tobe = false; + return ShouldBeRebuilt(&tobe) == Status::SUCCESS ? tobe : false; +} + +Status DBM::CopyFileData(const std::string& dest_path, bool sync_hard) { + Status impl_status(Status::SUCCESS); + FileProcessorCopyFileData proc(&impl_status, dest_path); + if (IsWritable()) { + const Status status = Synchronize(sync_hard, &proc); + if (status != Status::SUCCESS) { + return status; + } + } else { + std::string path; + const Status status = GetFilePath(&path); + if (status != Status::SUCCESS) { + return status; + } + proc.Process(path); + } + return impl_status; +} + +Status DBM::Export(DBM* dest_dbm) { + Status impl_status(Status::SUCCESS); + RecordProcessorExport proc(&impl_status, dest_dbm); + const Status status = ProcessEach(&proc, false); + if (status != Status::SUCCESS) { + return status; + } + return impl_status; +} + +const std::type_info& DBM::GetType() const { + const auto& entity = *this; + return typeid(entity); +} + } // namespace tkrzw // END OF FILE diff --git a/tkrzw_dbm.h b/tkrzw_dbm.h index 61d13d2..ec61d3f 100644 --- a/tkrzw_dbm.h +++ b/tkrzw_dbm.h @@ -72,9 +72,7 @@ class DBM { * @details The memory referred to by the return value must be alive until the end of * the life-span of this object or until this function is called next time. */ - virtual std::string_view ProcessFull(std::string_view key, std::string_view value) { - return NOOP; - } + virtual std::string_view ProcessFull(std::string_view key, std::string_view value); /** * Processes an empty record space. @@ -83,9 +81,7 @@ class DBM { * @details The memory referred to by the return value must be alive until the end of * the life-span of this object or until this function is called next time. */ - virtual std::string_view ProcessEmpty(std::string_view key) { - return NOOP; - } + virtual std::string_view ProcessEmpty(std::string_view key); }; /** @@ -105,21 +101,17 @@ class DBM { * Constructor. * @param proc_lambda A lambda function to process a record. */ - explicit RecordProcessorLambda(RecordLambdaType proc_lambda) : proc_lambda_(proc_lambda) {} + explicit RecordProcessorLambda(RecordLambdaType proc_lambda); /** * Processes an existing record. */ - std::string_view ProcessFull(std::string_view key, std::string_view value) override { - return proc_lambda_(key, value); - } + std::string_view ProcessFull(std::string_view key, std::string_view value) override; /** * Processes an empty record space. */ - std::string_view ProcessEmpty(std::string_view key) override { - return proc_lambda_(key, NOOP); - } + std::string_view ProcessEmpty(std::string_view key) override; private: // Lambda function to process a record. @@ -136,25 +128,17 @@ class DBM { * @param status The pointer to a status object to contain the result status. * @param value The pointer to a string object to contain the result value. */ - RecordProcessorGet(Status* status, std::string* value) : status_(status), value_(value) {} + RecordProcessorGet(Status* status, std::string* value); /** * Processes an existing record. */ - std::string_view ProcessFull(std::string_view key, std::string_view value) override { - if (value_ != nullptr) { - *value_ = value; - } - return NOOP; - } + std::string_view ProcessFull(std::string_view key, std::string_view value) override; /** * Processes an empty record space. */ - std::string_view ProcessEmpty(std::string_view key) override { - status_->Set(Status::NOT_FOUND_ERROR); - return NOOP; - } + std::string_view ProcessEmpty(std::string_view key) override; private: /** Status to report. */ @@ -176,29 +160,17 @@ class DBM { * @param old_value The pointer to a string object to contain the existing value. */ RecordProcessorSet(Status* status, std::string_view value, bool overwrite, - std::string* old_value) - : status_(status), value_(value), overwrite_(overwrite), old_value_(old_value) {} + std::string* old_value); /** * Processes an existing record. */ - std::string_view ProcessFull(std::string_view key, std::string_view value) override { - if (old_value_ != nullptr) { - *old_value_ = value; - } - if (overwrite_) { - return value_; - } - status_->Set(Status::DUPLICATION_ERROR); - return NOOP; - } + std::string_view ProcessFull(std::string_view key, std::string_view value) override; /** * Processes an empty record space. */ - std::string_view ProcessEmpty(std::string_view key) override { - return value_; - } + std::string_view ProcessEmpty(std::string_view key) override; private: /** Status to report. */ @@ -221,26 +193,17 @@ class DBM { * @param status The pointer to a status object to contain the result status. * @param old_value The pointer to a string object to contain the existing value. */ - explicit RecordProcessorRemove(Status* status, std::string* old_value) - : status_(status), old_value_(old_value) {} + explicit RecordProcessorRemove(Status* status, std::string* old_value); /** * Processes an existing record. */ - std::string_view ProcessFull(std::string_view key, std::string_view value) override { - if (old_value_ != nullptr) { - *old_value_ = value; - } - return REMOVE; - } + std::string_view ProcessFull(std::string_view key, std::string_view value) override; /** * Processes an empty record space. */ - std::string_view ProcessEmpty(std::string_view key) override { - status_->Set(Status::NOT_FOUND_ERROR); - return NOOP; - } + std::string_view ProcessEmpty(std::string_view key) override; private: /** Status to report. */ @@ -259,32 +222,17 @@ class DBM { * @param value A string of the value to set. * @param delim A string of the delimiter. */ - RecordProcessorAppend(std::string_view value, std::string_view delim) - : value_(value), delim_(delim) {} + RecordProcessorAppend(std::string_view value, std::string_view delim); /** * Processes an existing record. */ - std::string_view ProcessFull(std::string_view key, std::string_view value) override { - if (delim_.empty()) { - new_value_.reserve(value.size() + value_.size()); - new_value_.append(value); - new_value_.append(value_); - } else { - new_value_.reserve(value.size() + delim_.size() + value_.size()); - new_value_.append(value); - new_value_.append(delim_); - new_value_.append(value_); - } - return new_value_; - } + std::string_view ProcessFull(std::string_view key, std::string_view value) override; /** * Processes an empty record space. */ - std::string_view ProcessEmpty(std::string_view key) override { - return value_; - } + std::string_view ProcessEmpty(std::string_view key) override; private: /** Value to store. */ @@ -311,46 +259,17 @@ class DBM { * it is nullptr, it is ignored. */ RecordProcessorCompareExchange(Status* status, std::string_view expected, - std::string_view desired, std::string* actual, bool* found) - : status_(status), expected_(expected), desired_(desired), - actual_(actual), found_(found) {} + std::string_view desired, std::string* actual, bool* found); /** * Processes an existing record. */ - std::string_view ProcessFull(std::string_view key, std::string_view value) override { - if (actual_ != nullptr) { - *actual_ = value; - } - if (found_ != nullptr) { - *found_ = true; - } - if (expected_.data() != nullptr && - (expected_.data() == ANY_DATA.data() || expected_ == value)) { - return desired_.data() == nullptr ? REMOVE : - desired_.data() == ANY_DATA.data() ? NOOP : desired_; - } - status_->Set(Status::INFEASIBLE_ERROR); - return NOOP; - } + std::string_view ProcessFull(std::string_view key, std::string_view value) override; /** * Processes an empty record space. */ - std::string_view ProcessEmpty(std::string_view key) override { - if (actual_ != nullptr) { - *actual_ = ""; - } - if (found_ != nullptr) { - *found_ = false; - } - if (expected_.data() == nullptr) { - return desired_.data() == nullptr || desired_.data() == ANY_DATA.data() ? - NOOP : desired_; - } - status_->Set(Status::INFEASIBLE_ERROR); - return NOOP; - } + std::string_view ProcessEmpty(std::string_view key) override; private: /** Status to report. */ @@ -376,44 +295,17 @@ class DBM { * @param current The pointer to a string object to contain the current value. * @param initial The initial value. */ - RecordProcessorIncrement(int64_t increment, int64_t* current, int64_t initial) - : increment_(increment), current_(current), initial_(initial) {} + RecordProcessorIncrement(int64_t increment, int64_t* current, int64_t initial); /** * Processes an existing record. */ - std::string_view ProcessFull(std::string_view key, std::string_view value) override { - if (increment_ == INT64MIN) { - if (current_ != nullptr) { - *current_ = StrToIntBigEndian(value); - } - return NOOP; - } - const int64_t num = StrToIntBigEndian(value) + increment_; - if (current_ != nullptr) { - *current_ = num; - } - value_ = IntToStrBigEndian(num); - return value_; - } + std::string_view ProcessFull(std::string_view key, std::string_view value) override; /** * Processes an empty record space. */ - std::string_view ProcessEmpty(std::string_view key) override { - if (increment_ == INT64MIN) { - if (current_ != nullptr) { - *current_ = initial_; - } - return NOOP; - } - const int64_t num = initial_ + increment_; - if (current_ != nullptr) { - *current_ = num; - } - value_ = IntToStrBigEndian(num); - return value_; - } + std::string_view ProcessEmpty(std::string_view key) override; private: /** The incrementing value. */ @@ -436,29 +328,17 @@ class DBM { * @param noop Whether to do no operation. * @param expected A string of the expected value. */ - RecordCheckerCompareExchangeMulti(bool* noop, std::string_view expected) - : noop_(noop), expected_(expected) {} + RecordCheckerCompareExchangeMulti(bool* noop, std::string_view expected); /** * Processes an existing record. */ - std::string_view ProcessFull(std::string_view key, std::string_view value) override { - if (expected_.data() == nullptr || - (expected_.data() != ANY_DATA.data() && expected_ != value)) { - *noop_ = true; - } - return NOOP; - } + std::string_view ProcessFull(std::string_view key, std::string_view value) override; /** * Processes an empty record space. */ - std::string_view ProcessEmpty(std::string_view key) override { - if (expected_.data() != nullptr) { - *noop_ = true; - } - return NOOP; - } + std::string_view ProcessEmpty(std::string_view key) override; private: /** Whether to do no operation. */ @@ -477,28 +357,17 @@ class DBM { * @param noop True to do no operation. * @param desired A string of the expected value. */ - RecordSetterCompareExchangeMulti(bool* noop, std::string_view desired) - : noop_(noop), desired_(desired) {} + RecordSetterCompareExchangeMulti(bool* noop, std::string_view desired); /** * Processes an existing record. */ - std::string_view ProcessFull(std::string_view key, std::string_view value) override { - if (*noop_) { - return NOOP; - } - return desired_.data() == nullptr ? REMOVE : desired_; - } + std::string_view ProcessFull(std::string_view key, std::string_view value) override; /** * Processes an empty record space. */ - std::string_view ProcessEmpty(std::string_view key) override { - if (*noop_) { - return NOOP; - } - return desired_.data() == nullptr ? NOOP : desired_; - } + std::string_view ProcessEmpty(std::string_view key) override; private: /** Whether to do no operation. */ @@ -516,22 +385,17 @@ class DBM { * Constructor. * @param status The pointer to a status object. */ - RecordCheckerRekey(Status* status) : status_(status) {} + RecordCheckerRekey(Status* status); /** * Processes an existing record. */ - std::string_view ProcessFull(std::string_view key, std::string_view value) override { - status_->Set(Status::DUPLICATION_ERROR); - return NOOP; - } + std::string_view ProcessFull(std::string_view key, std::string_view value) override; /** * Processes an empty record space. */ - std::string_view ProcessEmpty(std::string_view key) override { - return NOOP; - } + std::string_view ProcessEmpty(std::string_view key) override; private: /** The pointer to a status object. */ @@ -549,27 +413,17 @@ class DBM { * @param old_value The pointer to a string object to store the old value. * @param copying Whether to retain the record of the old key. */ - RecordRemoverRekey(Status* status, std::string* old_value, bool copying) - : status_(status), old_value_(old_value), copying_(copying) {} + RecordRemoverRekey(Status* status, std::string* old_value, bool copying); /** * Processes an existing record. */ - std::string_view ProcessFull(std::string_view key, std::string_view value) override { - if (*status_ != Status::SUCCESS) { - return NOOP; - } - *old_value_ = value; - return copying_ ? NOOP : REMOVE; - } + std::string_view ProcessFull(std::string_view key, std::string_view value) override; /** * Processes an empty record space. */ - std::string_view ProcessEmpty(std::string_view key) override { - status_->Set(Status::NOT_FOUND_ERROR); - return NOOP; - } + std::string_view ProcessEmpty(std::string_view key) override; private: /** The pointer to a status object. */ @@ -590,28 +444,17 @@ class DBM { * @param status The pointer to a status object. * @param new_value The pointer to a string object to store the old value. */ - RecordSetterRekey(Status* status, const std::string* new_value) - : status_(status), new_value_(new_value) {} + RecordSetterRekey(Status* status, const std::string* new_value); /** * Processes an existing record. */ - std::string_view ProcessFull(std::string_view key, std::string_view value) override { - if (*status_ != Status::SUCCESS) { - return NOOP; - } - return *new_value_; - } + std::string_view ProcessFull(std::string_view key, std::string_view value) override; /** * Processes an empty record space. */ - std::string_view ProcessEmpty(std::string_view key) override { - if (*status_ != Status::SUCCESS) { - return NOOP; - } - return *new_value_; - } + std::string_view ProcessEmpty(std::string_view key) override; private: /** The pointer to a status object. */ @@ -630,21 +473,12 @@ class DBM { * @param key The pointer to a string object to contain the existing value. * @param value The pointer to a string object to contain the existing value. */ - explicit RecordProcessorPopFirst(std::string* key, std::string* value) - : key_(key), value_(value) {} + explicit RecordProcessorPopFirst(std::string* key, std::string* value); /** * Processes an existing record. */ - std::string_view ProcessFull(std::string_view key, std::string_view value) override { - if (key_ != nullptr) { - *key_ = key; - } - if (value_ != nullptr) { - *value_ = value; - } - return REMOVE; - } + std::string_view ProcessFull(std::string_view key, std::string_view value) override; private: /** String to store the key. */ @@ -661,15 +495,12 @@ class DBM { /** * Constructor. */ - RecordProcessorExport(Status* status, DBM* dbm) : status_(status), dbm_(dbm) {} + RecordProcessorExport(Status* status, DBM* dbm); /** * Processes an existing record. */ - std::string_view ProcessFull(std::string_view key, std::string_view value) override { - *status_ |= dbm_->Set(key, value); - return NOOP; - } + std::string_view ProcessFull(std::string_view key, std::string_view value) override; private: /** Status to report. */ @@ -690,21 +521,12 @@ class DBM { * @param cur_value The pointer to a string object to contain the current value. */ RecordProcessorIterator( - std::string_view new_value, std::string* cur_key, std::string* cur_value) - : new_value_(new_value), cur_key_(cur_key), cur_value_(cur_value) {} + std::string_view new_value, std::string* cur_key, std::string* cur_value); /** * Processes an existing record. */ - std::string_view ProcessFull(std::string_view key, std::string_view value) override { - if (cur_key_ != nullptr) { - *cur_key_ = key; - } - if (cur_value_ != nullptr) { - *cur_value_ = value; - } - return new_value_; - } + std::string_view ProcessFull(std::string_view key, std::string_view value) override; private: /** The new value returned to the database. */ @@ -806,10 +628,7 @@ class DBM { * @param writable True if the processor can edit the record. * @return The result status. */ - virtual Status Process(RecordLambdaType rec_lambda, bool writable) { - RecordProcessorLambda proc(rec_lambda); - return Process(&proc, writable); - } + virtual Status Process(RecordLambdaType rec_lambda, bool writable); /** * Gets the key and the value of the current record of the iterator. @@ -819,30 +638,21 @@ class DBM { * the value data is ignored. * @return The result status. */ - virtual Status Get(std::string* key = nullptr, std::string* value = nullptr) { - RecordProcessorIterator proc(RecordProcessor::NOOP, key, value); - return Process(&proc, false); - } + virtual Status Get(std::string* key = nullptr, std::string* value = nullptr); /** * Gets the key of the current record, in a simple way. * @param default_value The value to be returned on failure. * @return The key of the current record on success, or the default value on failure. */ - virtual std::string GetKey(std::string_view default_value = "") { - std::string key; - return Get(&key, nullptr) == Status::SUCCESS ? key : std::string(default_value); - } + virtual std::string GetKey(std::string_view default_value = ""); /** * Gets the value of the current record, in a simple way. * @param default_value The value to be returned on failure. * @return The value of the current record on success, or the default value on failure. */ - virtual std::string GetValue(std::string_view default_value = "") { - std::string value; - return Get(nullptr, &value) == Status::SUCCESS ? value : std::string(default_value); - } + virtual std::string GetValue(std::string_view default_value = ""); /** * Sets the value of the current record. @@ -854,10 +664,7 @@ class DBM { * @return The result status. */ virtual Status Set(std::string_view value, std::string* old_key = nullptr, - std::string* old_value = nullptr) { - RecordProcessorIterator proc(value, old_key, old_value); - return Process(&proc, true); - } + std::string* old_value = nullptr); /** * Removes the current record. @@ -868,10 +675,7 @@ class DBM { * @return The result status. * @details If possible, the iterator moves to the next record. */ - virtual Status Remove(std::string* old_key = nullptr, std::string* old_value = nullptr) { - RecordProcessorIterator proc(RecordProcessor::REMOVE, old_key, old_value); - return Process(&proc, true); - } + virtual Status Remove(std::string* old_key = nullptr, std::string* old_value = nullptr); /** * Gets the current record and moves the iterator to the next record. @@ -881,17 +685,7 @@ class DBM { * the value data is ignored. * @return The result status. */ - virtual Status Step(std::string* key = nullptr, std::string* value = nullptr) { - Status status = Get(key, value); - if (status != Status::SUCCESS) { - return status; - } - status = Next(); - if (status == Status::NOT_FOUND_ERROR) { - status.Set(Status::SUCCESS); - } - return status; - } + virtual Status Step(std::string* key = nullptr, std::string* value = nullptr); }; /** @@ -908,7 +702,7 @@ class DBM { * Process a file. * @param path The path of the file. */ - virtual void Process(const std::string& path) {} + virtual void Process(const std::string& path); }; /** @@ -976,9 +770,7 @@ class DBM { * @return The result status. * @details This is called by the Synchronize method. */ - virtual Status Synchronize(bool hard) { - return Status(Status::SUCCESS); - } + virtual Status Synchronize(bool hard); }; /** @@ -1023,10 +815,7 @@ class DBM { * @param writable True if the processor can edit the record. * @return The result status. */ - virtual Status Process(std::string_view key, RecordLambdaType rec_lambda, bool writable) { - RecordProcessorLambda proc(rec_lambda); - return Process(key, &proc, writable); - } + virtual Status Process(std::string_view key, RecordLambdaType rec_lambda, bool writable); /** * Gets the value of a record of a key. @@ -1035,15 +824,7 @@ class DBM { * the value data is ignored. * @return The result status. If there's no matching record, NOT_FOUND_ERROR is returned. */ - virtual Status Get(std::string_view key, std::string* value = nullptr) { - Status impl_status(Status::SUCCESS); - RecordProcessorGet proc(&impl_status, value); - const Status status = Process(key, &proc, false); - if (status != Status::SUCCESS) { - return status; - } - return impl_status; - } + virtual Status Get(std::string_view key, std::string* value = nullptr); /** * Gets the value of a record of a key, in a simple way. @@ -1051,10 +832,7 @@ class DBM { * @param default_value The value to be returned on failure. * @return The value of the matching record on success, or the default value on failure. */ - virtual std::string GetSimple(std::string_view key, std::string_view default_value = "") { - std::string value; - return Get(key, &value) == Status::SUCCESS ? value : std::string(default_value); - } + virtual std::string GetSimple(std::string_view key, std::string_view default_value = ""); /** * Gets the values of multiple records of keys, with a string view vector. @@ -1066,19 +844,7 @@ class DBM { * code, the result map can have elements. */ virtual Status GetMulti( - const std::vector& keys, std::map* records) { - Status status(Status::SUCCESS); - for (const auto& key : keys) { - std::string value; - const Status tmp_status = Get(key, &value); - if (tmp_status == Status::SUCCESS) { - records->emplace(key, std::move(value)); - } else { - status |= tmp_status; - } - } - return status; - } + const std::vector& keys, std::map* records); /** * Gets the values of multiple records of keys, with an initializer list. @@ -1090,10 +856,7 @@ class DBM { * code, the result map can have elements. */ virtual Status GetMulti(const std::initializer_list& keys, - std::map* records) { - std::vector vector_keys(keys.begin(), keys.end()); - return GetMulti(vector_keys, records); - } + std::map* records); /** * Gets the values of multiple records of keys, with a string vector. @@ -1105,9 +868,7 @@ class DBM { * code, the result map can have elements. */ virtual Status GetMulti( - const std::vector& keys, std::map* records) { - return GetMulti(MakeStrViewVectorFromValues(keys), records); - } + const std::vector& keys, std::map* records); /** * Sets a record of a key and a value. @@ -1121,15 +882,7 @@ class DBM { * @return The result status. If overwriting is abandoned, DUPLICATION_ERROR is returned. */ virtual Status Set(std::string_view key, std::string_view value, bool overwrite = true, - std::string* old_value = nullptr) { - Status impl_status(Status::SUCCESS); - RecordProcessorSet proc(&impl_status, value, overwrite, old_value); - const Status status = Process(key, &proc, true); - if (status != Status::SUCCESS) { - return status; - } - return impl_status; - } + std::string* old_value = nullptr); /** * Sets multiple records, with a map of string views. @@ -1141,16 +894,7 @@ class DBM { * is returned. */ virtual Status SetMulti( - const std::map& records, bool overwrite = true) { - Status status(Status::SUCCESS); - for (const auto& record : records) { - status |= Set(record.first, record.second, overwrite); - if (status != Status::SUCCESS && status != Status::DUPLICATION_ERROR) { - break; - } - } - return status; - } + const std::map& records, bool overwrite = true); /** * Sets multiple records, with an initializer list. @@ -1163,14 +907,7 @@ class DBM { */ virtual Status SetMulti( const std::initializer_list>& records, - bool overwrite = true) { - std::map map_records; - for (const auto& record : records) { - map_records.emplace(std::pair( - std::string_view(record.first), std::string_view(record.second))); - } - return SetMulti(map_records, overwrite); - } + bool overwrite = true); /** * Sets multiple records, with a map of strings. @@ -1182,9 +919,7 @@ class DBM { * is returned. */ virtual Status SetMulti( - const std::map& records, bool overwrite = true) { - return SetMulti(MakeStrViewMapFromRecords(records), overwrite); - } + const std::map& records, bool overwrite = true); /** * Removes a record of a key. @@ -1193,50 +928,28 @@ class DBM { * it is ignored. * @return The result status. If there's no matching record, NOT_FOUND_ERROR is returned. */ - virtual Status Remove(std::string_view key, std::string* old_value = nullptr) { - Status impl_status(Status::SUCCESS); - RecordProcessorRemove proc(&impl_status, old_value); - const Status status = Process(key, &proc, true); - if (status != Status::SUCCESS) { - return status; - } - return impl_status; - } + virtual Status Remove(std::string_view key, std::string* old_value = nullptr); /** * Removes records of keys, with a string view vector. * @param keys The keys of records to remove. * @return The result status. If there are missing records, NOT_FOUND_ERROR is returned. */ - virtual Status RemoveMulti(const std::vector& keys) { - Status status(Status::SUCCESS); - for (const auto& key : keys) { - status |= Remove(key); - if (status != Status::Status::SUCCESS && status != Status::Status::NOT_FOUND_ERROR) { - break; - } - } - return status; - } + virtual Status RemoveMulti(const std::vector& keys); /** * Removes records of keys, with an initializer list. * @param keys The keys of records to remove. * @return The result status. */ - virtual Status RemoveMulti(const std::initializer_list& keys) { - std::vector vector_keys(keys.begin(), keys.end()); - return RemoveMulti(vector_keys); - } + virtual Status RemoveMulti(const std::initializer_list& keys); /** * Removes records of keys, with a string vector. * @param keys The keys of records to remove. * @return The result status. If there are missing records, NOT_FOUND_ERROR is returned. */ - virtual Status RemoveMulti(const std::vector& keys) { - return RemoveMulti(MakeStrViewVectorFromValues(keys)); - } + virtual Status RemoveMulti(const std::vector& keys); /** * Appends data at the end of a record of a key. @@ -1247,10 +960,7 @@ class DBM { * @details If there's no existing record, the value is set without the delimiter. */ virtual Status Append( - std::string_view key, std::string_view value, std::string_view delim = "") { - RecordProcessorAppend proc(value, delim); - return Process(key, &proc, true); - } + std::string_view key, std::string_view value, std::string_view delim = ""); /** * Appends data to multiple records, with a map of string views. @@ -1260,16 +970,7 @@ class DBM { * @details If there's no existing record, the value is set without the delimiter. */ virtual Status AppendMulti( - const std::map& records, std::string_view delim = "") { - Status status(Status::SUCCESS); - for (const auto& record : records) { - status |= Append(record.first, record.second, delim); - if (status != Status::SUCCESS) { - break; - } - } - return status; - } + const std::map& records, std::string_view delim = ""); /** * Appends data to multiple records, with an initializer list. @@ -1280,14 +981,7 @@ class DBM { */ virtual Status AppendMulti( const std::initializer_list>& records, - std::string_view delim = "") { - std::map map_records; - for (const auto& record : records) { - map_records.emplace(std::pair( - std::string_view(record.first), std::string_view(record.second))); - } - return AppendMulti(map_records, delim); - } + std::string_view delim = ""); /** * Appends data to multiple records, with a map of strings. @@ -1297,9 +991,7 @@ class DBM { * @details If there's no existing record, the value is set without the delimiter. */ virtual Status AppendMulti( - const std::map& records, std::string_view delim = "") { - return AppendMulti(MakeStrViewMapFromRecords(records), delim); - } + const std::map& records, std::string_view delim = ""); /** * Compares the value of a record and exchanges if the condition meets. @@ -1316,15 +1008,7 @@ class DBM { */ virtual Status CompareExchange(std::string_view key, std::string_view expected, std::string_view desired, std::string* actual = nullptr, - bool* found = nullptr) { - Status impl_status(Status::SUCCESS); - RecordProcessorCompareExchange proc(&impl_status, expected, desired, actual, found); - const Status status = Process(key, &proc, desired.data() != ANY_DATA.data()); - if (status != Status::SUCCESS) { - return status; - } - return impl_status; - } + bool* found = nullptr); /** * Increments the numeric value of a record. @@ -1339,10 +1023,7 @@ class DBM { * supported. */ virtual Status Increment(std::string_view key, int64_t increment = 1, - int64_t* current = nullptr, int64_t initial = 0) { - RecordProcessorIncrement proc(increment, current, initial); - return Process(key, &proc, increment != INT64MIN); - } + int64_t* current = nullptr, int64_t initial = 0); /** * Increments the numeric value of a record, in a simple way. @@ -1353,10 +1034,7 @@ class DBM { * @details The record value is treated as a decimal integer. Negative is also supported. */ virtual int64_t IncrementSimple( - std::string_view key, int64_t increment = 1, int64_t initial = 0) { - int64_t current = 0; - return Increment(key, increment, ¤t, initial) == Status::SUCCESS ? current : INT64MIN; - } + std::string_view key, int64_t increment = 1, int64_t initial = 0); /** * Processes multiple records with processors. @@ -1381,17 +1059,7 @@ class DBM { */ virtual Status ProcessMulti( const std::vector>& key_lambda_pairs, - bool writable) { - std::vector> key_proc_pairs; - key_proc_pairs.reserve(key_lambda_pairs.size()); - std::vector procs; - procs.reserve(key_lambda_pairs.size()); - for (const auto& key_lambda : key_lambda_pairs) { - procs.emplace_back(key_lambda.second); - key_proc_pairs.emplace_back(std::make_pair(key_lambda.first, &procs.back())); - } - return ProcessMulti(key_proc_pairs, writable); - } + bool writable); /** * Compares the values of records and exchanges if the condition meets. @@ -1404,28 +1072,7 @@ class DBM { */ virtual Status CompareExchangeMulti( const std::vector>& expected, - const std::vector>& desired) { - std::vector> key_proc_pairs; - key_proc_pairs.reserve(expected.size() + desired.size()); - bool noop = false; - std::vector checkers; - checkers.reserve(expected.size()); - for (const auto& key_value : expected) { - checkers.emplace_back(RecordCheckerCompareExchangeMulti(&noop, key_value.second)); - key_proc_pairs.emplace_back(std::pair(key_value.first, &checkers.back())); - } - std::vector setters; - setters.reserve(desired.size()); - for (const auto& key_value : desired) { - setters.emplace_back(RecordSetterCompareExchangeMulti(&noop, key_value.second)); - key_proc_pairs.emplace_back(std::pair(key_value.first, &setters.back())); - } - const Status status = ProcessMulti(key_proc_pairs, true); - if (status != Status::SUCCESS) { - return status; - } - return noop ? Status(Status::INFEASIBLE_ERROR) : Status(Status::SUCCESS); - } + const std::vector>& desired); /** * Changes the key of a record. @@ -1443,28 +1090,7 @@ class DBM { */ virtual Status Rekey(std::string_view old_key, std::string_view new_key, bool overwrite = true, bool copying = false, - std::string* value = nullptr) { - std::vector> key_proc_pairs; - key_proc_pairs.reserve(3); - Status proc_status(Status::SUCCESS); - RecordCheckerRekey checker(&proc_status); - if (!overwrite) { - key_proc_pairs.emplace_back(std::pair(new_key, &checker)); - } - std::string rec_value; - RecordRemoverRekey remover(&proc_status, &rec_value, copying); - key_proc_pairs.emplace_back(std::pair(old_key, &remover)); - RecordSetterRekey setter(&proc_status, &rec_value); - key_proc_pairs.emplace_back(std::pair(new_key, &setter)); - const Status status = ProcessMulti(key_proc_pairs, true); - if (status != Status::SUCCESS) { - return status; - } - if (proc_status == Status::SUCCESS && value != nullptr) { - *value = std::move(rec_value); - } - return proc_status; - } + std::string* value = nullptr); /** * Processes the first record with a processor. @@ -1486,10 +1112,7 @@ class DBM { * @param writable True if the processor can edit the record. * @return The result status. */ - virtual Status ProcessFirst(RecordLambdaType rec_lambda, bool writable) { - RecordProcessorLambda proc(rec_lambda); - return ProcessFirst(&proc, writable); - } + virtual Status ProcessFirst(RecordLambdaType rec_lambda, bool writable); /** * Gets the first record and removes it. @@ -1499,10 +1122,7 @@ class DBM { * it is nullptr, it is ignored. * @return The result status. */ - virtual Status PopFirst(std::string* key = nullptr, std::string* value = nullptr) { - RecordProcessorPopFirst proc(key, value); - return ProcessFirst(&proc, true); - } + virtual Status PopFirst(std::string* key = nullptr, std::string* value = nullptr); /** * Adds a record with a key of the current timestamp. @@ -1516,21 +1136,7 @@ class DBM { * there is an existing record matching the generated key, the key is regenerated and the * attempt is repeated until it succeeds. */ - virtual Status PushLast(std::string_view value, double wtime = -1, std::string* key = nullptr) { - for (uint64_t seq = 0; true; seq++) { - const uint64_t timestamp = - static_cast((wtime < 0 ? GetWallTime() : wtime) * 100000000 + seq); - const std::string& time_key = IntToStrBigEndian(timestamp); - const Status status = Set(time_key, value, false); - if (status != Status::DUPLICATION_ERROR) { - if (key != nullptr) { - *key = time_key; - } - return status; - } - } - return Status(Status::UNKNOWN_ERROR); - } + virtual Status PushLast(std::string_view value, double wtime = -1, std::string* key = nullptr); /** * Processes each and every record in the database with a processor. @@ -1555,10 +1161,7 @@ class DBM { * before the iteration and once after the iteration with both the key and the value being * RecordProcessor::NOOP. */ - virtual Status ProcessEach(RecordLambdaType rec_lambda, bool writable) { - RecordProcessorLambda proc(rec_lambda); - return ProcessEach(&proc, writable); - } + virtual Status ProcessEach(RecordLambdaType rec_lambda, bool writable); /** * Gets the number of records. @@ -1571,10 +1174,7 @@ class DBM { * Gets the number of records, in a simple way. * @return The number of records on success, or -1 on failure. */ - virtual int64_t CountSimple() { - int64_t count = 0; - return Count(&count) == Status::SUCCESS ? count : -1; - } + virtual int64_t CountSimple(); /** * Gets the current file size of the database. @@ -1587,10 +1187,7 @@ class DBM { * Gets the current file size of the database, in a simple way. * @return The current file size of the database, or -1 on failure. */ - virtual int64_t GetFileSizeSimple() { - int64_t size = 0; - return GetFileSize(&size) == Status::SUCCESS ? size : -1; - } + virtual int64_t GetFileSizeSimple(); /** * Gets the path of the database file. @@ -1603,10 +1200,7 @@ class DBM { * Gets the path of the database file, in a simple way. * @return The file path of the database, or an empty string on failure. */ - virtual std::string GetFilePathSimple() { - std::string path; - return GetFilePath(&path) == Status::SUCCESS ? path : std::string(""); - } + virtual std::string GetFilePathSimple(); /** * Gets the timestamp in seconds of the last modified time. @@ -1621,10 +1215,7 @@ class DBM { * Gets the timestamp of the last modified time, in a simple way. * @return The timestamp of the last modified time, or NaN on failure. */ - virtual double GetTimestampSimple() { - double timestamp = 0; - return GetTimestamp(×tamp) == Status::SUCCESS ? timestamp : DOUBLENAN; - } + virtual double GetTimestampSimple(); /** * Removes all records. @@ -1649,10 +1240,7 @@ class DBM { * Checks whether the database should be rebuilt, in a simple way. * @return True if the database should be rebuilt or false if not or on failure. */ - virtual bool ShouldBeRebuiltSimple() { - bool tobe = false; - return ShouldBeRebuilt(&tobe) == Status::SUCCESS ? tobe : false; - } + virtual bool ShouldBeRebuiltSimple(); /** * Synchronizes the content of the database to the file system. @@ -1672,39 +1260,14 @@ class DBM { * @details Copying is done while the content is synchronized and stable. So, this method is * suitable for making a backup file while running a database service. */ - virtual Status CopyFileData(const std::string& dest_path, bool sync_hard = false) { - Status impl_status(Status::SUCCESS); - FileProcessorCopyFileData proc(&impl_status, dest_path); - if (IsWritable()) { - const Status status = Synchronize(sync_hard, &proc); - if (status != Status::SUCCESS) { - return status; - } - } else { - std::string path; - const Status status = GetFilePath(&path); - if (status != Status::SUCCESS) { - return status; - } - proc.Process(path); - } - return impl_status; - } + virtual Status CopyFileData(const std::string& dest_path, bool sync_hard = false); /** * Exports all records to another database. * @param dest_dbm The pointer to the destination database. * @return The result status. */ - virtual Status Export(DBM* dest_dbm) { - Status impl_status(Status::SUCCESS); - RecordProcessorExport proc(&impl_status, dest_dbm); - const Status status = ProcessEach(&proc, false); - if (status != Status::SUCCESS) { - return status; - } - return impl_status; - } + virtual Status Export(DBM* dest_dbm); /** * Inspects the database. @@ -1765,10 +1328,7 @@ class DBM { * Gets the type information of the actual class. * @return The type information of the actual class. */ - const std::type_info& GetType() const { - const auto& entity = *this; - return typeid(entity); - } + const std::type_info& GetType() const; }; } // namespace tkrzw diff --git a/tkrzw_dbm_baby.cc b/tkrzw_dbm_baby.cc index 7dcff20..b9c6bdc 100644 --- a/tkrzw_dbm_baby.cc +++ b/tkrzw_dbm_baby.cc @@ -1534,6 +1534,15 @@ Status BabyDBM::Clear() { return impl_->Clear(); } +Status BabyDBM::Rebuild() { + return Status(Status::SUCCESS); +} + +Status BabyDBM::ShouldBeRebuilt(bool* tobe) { + *tobe = false; + return Status(Status::SUCCESS); +} + Status BabyDBM::Synchronize(bool hard, FileProcessor* proc) { return impl_->Synchronize(hard, proc); } @@ -1550,6 +1559,14 @@ bool BabyDBM::IsWritable() const { return impl_->IsWritable(); } +bool BabyDBM::IsHealthy() const { + return true; +} + +bool BabyDBM::IsOrdered() const { + return true; +} + std::unique_ptr BabyDBM::MakeIterator() { std::unique_ptr iter(new BabyDBM::Iterator(impl_)); return iter; diff --git a/tkrzw_dbm_baby.h b/tkrzw_dbm_baby.h index 0b93476..0cf3adc 100644 --- a/tkrzw_dbm_baby.h +++ b/tkrzw_dbm_baby.h @@ -285,9 +285,7 @@ class BabyDBM final : public DBM { * @return The result status. * @details This method does nothing. */ - Status Rebuild() override { - return Status(Status::SUCCESS); - } + Status Rebuild() override; /** * Checks whether the database should be rebuilt. @@ -295,10 +293,7 @@ class BabyDBM final : public DBM { * @return The result status. * @details There's no need for the database to be rebuilt. */ - Status ShouldBeRebuilt(bool* tobe) override { - *tobe = false; - return Status(Status::SUCCESS); - } + Status ShouldBeRebuilt(bool* tobe) override; /** * Synchronizes the content of the database to the file system. @@ -333,17 +328,13 @@ class BabyDBM final : public DBM { * Checks whether the database condition is healthy. * @return Always true. On-memory databases never cause system errors. */ - bool IsHealthy() const override { - return true; - } + bool IsHealthy() const override; /** * Checks whether ordered operations are supported. * @return Always true. Ordered operations are supported. */ - bool IsOrdered() const override { - return true; - } + bool IsOrdered() const override; /** * Makes an iterator for each record. diff --git a/tkrzw_dbm_cache.cc b/tkrzw_dbm_cache.cc index 80caf5c..aadad34 100644 --- a/tkrzw_dbm_cache.cc +++ b/tkrzw_dbm_cache.cc @@ -1178,10 +1178,19 @@ Status CacheDBM::Clear() { return impl_->Clear(); } +Status CacheDBM::Rebuild() { + return RebuildAdvanced(-1); +} + Status CacheDBM::RebuildAdvanced(int64_t cap_rec_num, int64_t cap_mem_size) { return impl_->Rebuild(cap_rec_num, cap_mem_size); } +Status CacheDBM::ShouldBeRebuilt(bool* tobe) { + *tobe = false; + return Status(Status::SUCCESS); +} + Status CacheDBM::Synchronize(bool hard, FileProcessor* proc) { return impl_->Synchronize(hard, proc); } @@ -1198,6 +1207,14 @@ bool CacheDBM::IsWritable() const { return impl_->IsWritable(); } +bool CacheDBM::IsHealthy() const { + return true; +} + +bool CacheDBM::IsOrdered() const { + return false; +} + std::unique_ptr CacheDBM::MakeIterator() { std::unique_ptr iter(new CacheDBM::Iterator(impl_)); return iter; @@ -1239,14 +1256,30 @@ Status CacheDBM::Iterator::First() { return impl_->First(); } +Status CacheDBM::Iterator::Last() { + return Status(Status::NOT_IMPLEMENTED_ERROR); +} + Status CacheDBM::Iterator::Jump(std::string_view key) { return impl_->Jump(key); } +Status CacheDBM::Iterator::JumpLower(std::string_view key, bool inclusive) { + return Status(Status::NOT_IMPLEMENTED_ERROR); +} + +Status CacheDBM::Iterator::JumpUpper(std::string_view key, bool inclusive) { + return Status(Status::NOT_IMPLEMENTED_ERROR); +} + Status CacheDBM::Iterator::Next() { return impl_->Next(); } +Status CacheDBM::Iterator::Previous() { + return Status(Status::NOT_IMPLEMENTED_ERROR); +} + Status CacheDBM::Iterator::Process(RecordProcessor* proc, bool writable) { assert(proc != nullptr); return impl_->Process(proc, writable); diff --git a/tkrzw_dbm_cache.h b/tkrzw_dbm_cache.h index efb9f6d..899e144 100644 --- a/tkrzw_dbm_cache.h +++ b/tkrzw_dbm_cache.h @@ -73,9 +73,7 @@ class CacheDBM final : public DBM { * @return The result status. * @details This method is not supported. */ - Status Last() override { - return Status(Status::NOT_IMPLEMENTED_ERROR); - } + Status Last() override; /** * Initializes the iterator to indicate a specific record. @@ -93,9 +91,7 @@ class CacheDBM final : public DBM { * @return The result status. * @details This method is not supported. */ - Status JumpLower(std::string_view key, bool inclusive = false) override { - return Status(Status::NOT_IMPLEMENTED_ERROR); - } + Status JumpLower(std::string_view key, bool inclusive = false) override; /** * Initializes the iterator to indicate the first record whose key is upper than a given key. @@ -104,9 +100,7 @@ class CacheDBM final : public DBM { * @return The result status. * @details This method is not supported. */ - Status JumpUpper(std::string_view key, bool inclusive = false) override { - return Status(Status::NOT_IMPLEMENTED_ERROR); - } + Status JumpUpper(std::string_view key, bool inclusive = false) override; /** * Moves the iterator to the next record. @@ -121,9 +115,7 @@ class CacheDBM final : public DBM { * @return The result status. * @details This method is not suppoerted. */ - Status Previous() override { - return Status(Status::NOT_IMPLEMENTED_ERROR); - } + Status Previous() override; /** * Processes the current record with a processor. @@ -287,9 +279,7 @@ class CacheDBM final : public DBM { * @return The result status. * @details The number of buckets is calculated implicitly. */ - Status Rebuild() override { - return RebuildAdvanced(-1); - } + Status Rebuild() override; /** * Rebuilds the entire database, in an advanced way. @@ -305,10 +295,7 @@ class CacheDBM final : public DBM { * @return The result status. * @details There's no need for the database to be rebuilt. */ - Status ShouldBeRebuilt(bool* tobe) override { - *tobe = false; - return Status(Status::SUCCESS); - } + Status ShouldBeRebuilt(bool* tobe) override; /** * Synchronizes the content of the database to the file system. @@ -343,17 +330,13 @@ class CacheDBM final : public DBM { * Checks whether the database condition is healthy. * @return Always true. On-memory databases never cause system errors. */ - bool IsHealthy() const override { - return true; - } + bool IsHealthy() const override; /** * Checks whether ordered operations are supported. * @return Always false. Ordered operations are not supported. */ - bool IsOrdered() const override { - return false; - } + bool IsOrdered() const override; /** * Makes an iterator for each record. diff --git a/tkrzw_dbm_hash.cc b/tkrzw_dbm_hash.cc index d1ce92d..555d7d1 100644 --- a/tkrzw_dbm_hash.cc +++ b/tkrzw_dbm_hash.cc @@ -2398,6 +2398,8 @@ Status HashDBMIteratorImpl::ReadKeys() { return Status(Status::SUCCESS); } +HashDBM::TuningParameters::TuningParameters() {} + HashDBM::HashDBM() { impl_ = new HashDBMImpl(std::make_unique()); } @@ -2410,6 +2412,10 @@ HashDBM::~HashDBM() { delete impl_; } +Status HashDBM::Open(const std::string& path, bool writable, int32_t options) { + return OpenAdvanced(path, writable, options); +} + Status HashDBM::OpenAdvanced(const std::string& path, bool writable, int32_t options, const TuningParameters& tuning_params) { return impl_->Open(path, writable, options, tuning_params); @@ -2495,6 +2501,10 @@ Status HashDBM::Clear() { return impl_->Clear(); } +Status HashDBM::Rebuild() { + return RebuildAdvanced(); +} + Status HashDBM::RebuildAdvanced( const TuningParameters& tuning_params, bool skip_broken_records, bool sync_hard) { return impl_->Rebuild(tuning_params, skip_broken_records, sync_hard); @@ -2529,6 +2539,10 @@ bool HashDBM::IsAutoRestored() const { return impl_->IsAutoRestored(); } +bool HashDBM::IsOrdered() const { + return false; +} + std::unique_ptr HashDBM::MakeIterator() { std::unique_ptr iter(new HashDBM::Iterator(impl_)); return iter; @@ -2632,10 +2646,22 @@ Status HashDBM::Iterator::Jump(std::string_view key) { return impl_->Jump(key); } +Status HashDBM::Iterator::JumpLower(std::string_view key, bool inclusive) { + return Status(Status::NOT_IMPLEMENTED_ERROR); +} + +Status HashDBM::Iterator::JumpUpper(std::string_view key, bool inclusive) { + return Status(Status::NOT_IMPLEMENTED_ERROR); +} + Status HashDBM::Iterator::Next() { return impl_->Next(); } +Status HashDBM::Iterator::Previous() { + return Status(Status::NOT_IMPLEMENTED_ERROR); +} + Status HashDBM::Iterator::Process(RecordProcessor* proc, bool writable) { assert(proc != nullptr); return impl_->Process(proc, writable); diff --git a/tkrzw_dbm_hash.h b/tkrzw_dbm_hash.h index 4bf0d18..7e0f46a 100644 --- a/tkrzw_dbm_hash.h +++ b/tkrzw_dbm_hash.h @@ -106,9 +106,7 @@ class HashDBM final : public DBM { * @return The result status. * @details This method is not supported. */ - Status JumpLower(std::string_view key, bool inclusive = false) override { - return Status(Status::NOT_IMPLEMENTED_ERROR); - } + Status JumpLower(std::string_view key, bool inclusive = false) override; /** * Initializes the iterator to indicate the first record whose key is upper than a given key. @@ -117,9 +115,7 @@ class HashDBM final : public DBM { * @return The result status. * @details This method is not supported. */ - Status JumpUpper(std::string_view key, bool inclusive = false) override { - return Status(Status::NOT_IMPLEMENTED_ERROR); - } + Status JumpUpper(std::string_view key, bool inclusive = false) override; /** * Moves the iterator to the next record. @@ -135,9 +131,7 @@ class HashDBM final : public DBM { * @return The result status. * @details This method is not suppoerted. */ - Status Previous() override { - return Status(Status::NOT_IMPLEMENTED_ERROR); - } + Status Previous() override; /** * Processes the current record with a processor. @@ -319,7 +313,7 @@ class HashDBM final : public DBM { /** * Constructor */ - TuningParameters() {} + TuningParameters(); }; /** @@ -354,9 +348,7 @@ class HashDBM final : public DBM { * @details Precondition: The database is not opened. */ Status Open(const std::string& path, bool writable, - int32_t options = File::OPEN_DEFAULT) override { - return OpenAdvanced(path, writable, options); - } + int32_t options = File::OPEN_DEFAULT) override; /** * Opens a database file, in an advanced way. @@ -514,9 +506,7 @@ class HashDBM final : public DBM { * @details Rebuilding a database is useful to reduce the size of the file by solving * fragmentation. All tuning parameters are succeeded or calculated implicitly. */ - Status Rebuild() override { - return RebuildAdvanced(); - } + Status Rebuild() override; /** * Rebuilds the entire database, in an advanced way. @@ -590,9 +580,7 @@ class HashDBM final : public DBM { * Checks whether ordered operations are supported. * @return Always false. Ordered operations are not supported. */ - bool IsOrdered() const override { - return false; - } + bool IsOrdered() const override; /** * Makes an iterator for each record. diff --git a/tkrzw_dbm_poly.cc b/tkrzw_dbm_poly.cc index b147305..ea5b2b2 100644 --- a/tkrzw_dbm_poly.cc +++ b/tkrzw_dbm_poly.cc @@ -803,6 +803,42 @@ Status PolyDBM::SynchronizeAdvanced( return dbm_->Synchronize(hard, proc); } +Status PolyDBM::Iterator::First() { + return iter_->First(); +} + +Status PolyDBM::Iterator::Last() { + return iter_->Last(); +} + +Status PolyDBM::Iterator::Jump(std::string_view key) { + return iter_->Jump(key); +} + +Status PolyDBM::Iterator::JumpLower(std::string_view key, bool inclusive) { + return iter_->JumpLower(key, inclusive); +} + +Status PolyDBM::Iterator::JumpUpper(std::string_view key, bool inclusive = false) { + return iter_->JumpUpper(key, inclusive); +} + +Status PolyDBM::Iterator::Next() { + return iter_->Next(); +} + +Status PolyDBM::Iterator::Previous() { + return iter_->Previous(); +} + +Status PolyDBM::Iterator::Process(RecordProcessor* proc, bool writable) { + return iter_->Process(proc, writable); +} + +Status PolyDBM::Iterator::Get(std::string* key, std::string* value) { + return iter_->Get(key, value); +} + std::vector> PolyDBM::Inspect() { if (dbm_ == nullptr) { return std::vector>(); diff --git a/tkrzw_dbm_poly.h b/tkrzw_dbm_poly.h index e3fc6a8..f1f7cae 100644 --- a/tkrzw_dbm_poly.h +++ b/tkrzw_dbm_poly.h @@ -109,9 +109,7 @@ class PolyDBM final : public ParamDBM { * @return The result status. * @details Even if there's no record, the operation doesn't fail. */ - Status First() override { - return iter_->First(); - } + Status First() override; /** * Initializes the iterator to indicate the last record. @@ -119,9 +117,7 @@ class PolyDBM final : public ParamDBM { * @details Even if there's no record, the operation doesn't fail. This method is suppoerted * only by ordered databases. */ - Status Last() override { - return iter_->Last(); - } + Status Last() override; /** * Initializes the iterator to indicate a specific record. @@ -131,9 +127,7 @@ class PolyDBM final : public ParamDBM { * same key, the iterator refers to the first record whose key is greater than the given key. * The operation fails with unordered databases if there's no record with the same key. */ - Status Jump(std::string_view key) override { - return iter_->Jump(key); - } + Status Jump(std::string_view key) override; /** * Initializes the iterator to indicate the last record whose key is lower than a given key. @@ -143,9 +137,7 @@ class PolyDBM final : public ParamDBM { * @details Even if there's no matching record, the operation doesn't fail. This method is * suppoerted only by ordered databases. */ - Status JumpLower(std::string_view key, bool inclusive = false) override { - return iter_->JumpLower(key, inclusive); - } + Status JumpLower(std::string_view key, bool inclusive = false) override; /** * Initializes the iterator to indicate the first record whose key is upper than a given key. @@ -155,9 +147,7 @@ class PolyDBM final : public ParamDBM { * @details Even if there's no matching record, the operation doesn't fail. This method is * suppoerted only by ordered databases. */ - Status JumpUpper(std::string_view key, bool inclusive = false) override { - return iter_->JumpUpper(key, inclusive); - } + Status JumpUpper(std::string_view key, bool inclusive = false) override; /** * Moves the iterator to the next record. @@ -165,9 +155,7 @@ class PolyDBM final : public ParamDBM { * @details If the current record is missing, the operation fails. Even if there's no next * record, the operation doesn't fail. */ - Status Next() override { - return iter_->Next(); - } + Status Next() override; /** * Moves the iterator to the previous record. @@ -175,9 +163,7 @@ class PolyDBM final : public ParamDBM { * @details If the current record is missing, the operation fails. Even if there's no previous * record, the operation doesn't fail. This method is suppoerted only by ordered databases. */ - Status Previous() override { - return iter_->Previous(); - } + Status Previous() override; /** * Processes the current record with a processor. @@ -188,9 +174,7 @@ class PolyDBM final : public ParamDBM { * Otherwise, this method fails and no method of the processor is called. If the current * record is removed, the iterator is moved to the next record. */ - Status Process(RecordProcessor* proc, bool writable) override { - return iter_->Process(proc, writable); - } + Status Process(RecordProcessor* proc, bool writable) override; /** * Gets the key and the value of the current record of the iterator. @@ -200,9 +184,7 @@ class PolyDBM final : public ParamDBM { * the value data is ignored. * @return The result status. */ - Status Get(std::string* key = nullptr, std::string* value = nullptr) override { - return iter_->Get(key, value); - } + Status Get(std::string* key = nullptr, std::string* value = nullptr) override; /** * Sets the value of the current record. diff --git a/tkrzw_dbm_skip.cc b/tkrzw_dbm_skip.cc index 05bec97..ccbeb78 100644 --- a/tkrzw_dbm_skip.cc +++ b/tkrzw_dbm_skip.cc @@ -1760,6 +1760,8 @@ void SkipDBMIteratorImpl::ClearPosition() { const std::string SkipDBM::REMOVING_VALUE("\xDE\xAD\x00\x19\x78\x02\x11", 7); +SkipDBM::TuningParameters::TuningParameters() {} + SkipDBM::SkipDBM() { impl_ = new SkipDBMImpl(std::make_unique()); } @@ -1772,6 +1774,10 @@ SkipDBM::~SkipDBM() { delete impl_; } +Status SkipDBM::Open(const std::string& path, bool writable, int32_t options) { + return OpenAdvanced(path, writable, options); +} + Status SkipDBM::OpenAdvanced(const std::string& path, bool writable, int32_t options, const TuningParameters& tuning_params) { return impl_->Open(path, writable, options, tuning_params); @@ -1846,6 +1852,10 @@ Status SkipDBM::Clear() { return impl_->Clear(); } +Status SkipDBM::Rebuild() { + return RebuildAdvanced(); +} + Status SkipDBM::RebuildAdvanced( const TuningParameters& tuning_params, bool skip_broken_records, bool sync_hard) { return impl_->Rebuild(tuning_params, skip_broken_records, sync_hard); @@ -1856,6 +1866,10 @@ Status SkipDBM::ShouldBeRebuilt(bool* tobe) { return impl_->ShouldBeRebuilt(tobe); } +Status SkipDBM::Synchronize(bool hard, FileProcessor* proc) { + return SynchronizeAdvanced(hard, proc, nullptr); +} + Status SkipDBM::SynchronizeAdvanced( bool hard, FileProcessor* proc, SkipDBM::ReducerType reducer) { return impl_->Synchronize(hard, proc, reducer); @@ -1881,6 +1895,10 @@ bool SkipDBM::IsAutoRestored() const { return impl_->IsAutoRestored(); } +bool SkipDBM::IsOrdered() const { + return true; +} + std::unique_ptr SkipDBM::MakeIterator() { std::unique_ptr iter(new SkipDBM::Iterator(impl_)); return iter; diff --git a/tkrzw_dbm_skip.h b/tkrzw_dbm_skip.h index 2035f17..92f0285 100644 --- a/tkrzw_dbm_skip.h +++ b/tkrzw_dbm_skip.h @@ -258,7 +258,7 @@ class SkipDBM final : public DBM { /** * Constructor */ - TuningParameters() {} + TuningParameters(); }; /** @@ -293,9 +293,7 @@ class SkipDBM final : public DBM { * @details Precondition: The database is not opened. */ Status Open(const std::string& path, bool writable, - int32_t options = File::OPEN_DEFAULT) override { - return OpenAdvanced(path, writable, options); - } + int32_t options = File::OPEN_DEFAULT) override; /** * Opens a database file, in an advanced way. @@ -460,9 +458,7 @@ class SkipDBM final : public DBM { * @details Rebuilding a database is useful to optimize the size of the file. * All tuning parameters are succeeded or calculated implicitly. */ - Status Rebuild() override { - return RebuildAdvanced(); - } + Status Rebuild() override; /** * Rebuilds the entire database, in an advanced way. @@ -501,9 +497,7 @@ class SkipDBM final : public DBM { * records. No reducer is applied to records so that all records with duplicated keys are * kept intact. */ - Status Synchronize(bool hard, FileProcessor* proc = nullptr) override { - return SynchronizeAdvanced(hard, proc, nullptr); - } + Status Synchronize(bool hard, FileProcessor* proc = nullptr) override; /** * Synchronizes the content of the database to the file system. @@ -562,9 +556,7 @@ class SkipDBM final : public DBM { * Checks whether ordered operations are supported. * @return Always true. Ordered operations are supported. */ - bool IsOrdered() const override { - return true; - } + bool IsOrdered() const override; /** * Makes an iterator for each record. diff --git a/tkrzw_dbm_std.cc b/tkrzw_dbm_std.cc index 3a2ecae..68a6211 100644 --- a/tkrzw_dbm_std.cc +++ b/tkrzw_dbm_std.cc @@ -892,6 +892,14 @@ bool StdHashDBM::IsWritable() const { return impl_->IsWritable(); } +bool StdHashDBM::IsHealthy() const { + return true; +} + +bool StdHashDBM::IsOrdered() const { + return false; +} + std::unique_ptr StdHashDBM::MakeIterator() { std::unique_ptr iter(new StdHashDBM::Iterator(impl_)); return iter; @@ -1058,6 +1066,14 @@ bool StdTreeDBM::IsWritable() const { return impl_->IsWritable(); } +bool StdTreeDBM::IsHealthy() const { + return true; +} + +bool StdTreeDBM::IsOrdered() const { + return true; +} + std::unique_ptr StdTreeDBM::MakeIterator() { std::unique_ptr iter(new StdTreeDBM::Iterator(impl_)); return iter; diff --git a/tkrzw_dbm_std.h b/tkrzw_dbm_std.h index 6af19dd..99defcd 100644 --- a/tkrzw_dbm_std.h +++ b/tkrzw_dbm_std.h @@ -313,17 +313,13 @@ class StdHashDBM final : public DBM { * Checks whether the database condition is healthy. * @return Always true. On-memory databases never cause system errors. */ - bool IsHealthy() const override { - return true; - } + bool IsHealthy() const override; /** * Checks whether ordered operations are supported. * @return Always false. Ordered operations are not supported. */ - bool IsOrdered() const override { - return false; - } + bool IsOrdered() const override; /** * Makes an iterator for each record. @@ -644,17 +640,13 @@ class StdTreeDBM final : public DBM { * Checks whether the database condition is healthy. * @return Always true. On-memory databases never cause system errors. */ - bool IsHealthy() const override { - return true; - } + bool IsHealthy() const override; /** * Checks whether ordered operations are supported. * @return Always true. Ordered operations are supported. */ - bool IsOrdered() const override { - return true; - } + bool IsOrdered() const override; /** * Makes an iterator for each record. diff --git a/tkrzw_dbm_tiny.cc b/tkrzw_dbm_tiny.cc index c05e1ca..4c98cb4 100644 --- a/tkrzw_dbm_tiny.cc +++ b/tkrzw_dbm_tiny.cc @@ -930,6 +930,10 @@ Status TinyDBM::Clear() { return impl_->Clear(); } +Status TinyDBM::Rebuild() { + return RebuildAdvanced(-1); +} + Status TinyDBM::RebuildAdvanced(int64_t num_buckets) { return impl_->Rebuild(num_buckets); } @@ -955,6 +959,14 @@ bool TinyDBM::IsWritable() const { return impl_->IsWritable(); } +bool TinyDBM::IsHealthy() const { + return true; +} + +bool TinyDBM::IsOrdered() const { + return false; +} + std::unique_ptr TinyDBM::MakeIterator() { std::unique_ptr iter(new TinyDBM::Iterator(impl_)); return iter; @@ -988,14 +1000,30 @@ Status TinyDBM::Iterator::First() { return impl_->First(); } +Status TinyDBM::Iterator::Last() { + return Status(Status::NOT_IMPLEMENTED_ERROR); +} + Status TinyDBM::Iterator::Jump(std::string_view key) { return impl_->Jump(key); } +Status TinyDBM::Iterator::JumpLower(std::string_view key, bool inclusive) { + return Status(Status::NOT_IMPLEMENTED_ERROR); +} + +Status TinyDBM::Iterator::JumpUpper(std::string_view key, bool inclusive) { + return Status(Status::NOT_IMPLEMENTED_ERROR); +} + Status TinyDBM::Iterator::Next() { return impl_->Next(); } +Status TinyDBM::Iterator::Previous() { + return Status(Status::NOT_IMPLEMENTED_ERROR); +} + Status TinyDBM::Iterator::Process(RecordProcessor* proc, bool writable) { assert(proc != nullptr); return impl_->Process(proc, writable); diff --git a/tkrzw_dbm_tiny.h b/tkrzw_dbm_tiny.h index 1e5c58d..6741040 100644 --- a/tkrzw_dbm_tiny.h +++ b/tkrzw_dbm_tiny.h @@ -73,9 +73,7 @@ class TinyDBM final : public DBM { * @return The result status. * @details This method is not supported. */ - Status Last() override { - return Status(Status::NOT_IMPLEMENTED_ERROR); - } + Status Last() override; /** * Initializes the iterator to indicate a specific record. @@ -93,9 +91,7 @@ class TinyDBM final : public DBM { * @return The result status. * @details This method is not supported. */ - Status JumpLower(std::string_view key, bool inclusive = false) override { - return Status(Status::NOT_IMPLEMENTED_ERROR); - } + Status JumpLower(std::string_view key, bool inclusive = false) override; /** * Initializes the iterator to indicate the first record whose key is upper than a given key. @@ -104,9 +100,7 @@ class TinyDBM final : public DBM { * @return The result status. * @details This method is not supported. */ - Status JumpUpper(std::string_view key, bool inclusive = false) override { - return Status(Status::NOT_IMPLEMENTED_ERROR); - } + Status JumpUpper(std::string_view key, bool inclusive = false) override; /** * Moves the iterator to the next record. @@ -121,9 +115,7 @@ class TinyDBM final : public DBM { * @return The result status. * @details This method is not suppoerted. */ - Status Previous() override { - return Status(Status::NOT_IMPLEMENTED_ERROR); - } + Status Previous() override; /** * Processes the current record with a processor. @@ -291,9 +283,7 @@ class TinyDBM final : public DBM { * @return The result status. * @details The number of buckets is calculated implicitly. */ - Status Rebuild() override { - return RebuildAdvanced(-1); - } + Status Rebuild() override; /** * Rebuilds the entire database, in an advanced way. @@ -343,17 +333,13 @@ class TinyDBM final : public DBM { * Checks whether the database condition is healthy. * @return Always true. On-memory databases never cause system errors. */ - bool IsHealthy() const override { - return true; - } + bool IsHealthy() const override; /** * Checks whether ordered operations are supported. * @return Always false. Ordered operations are not supported. */ - bool IsOrdered() const override { - return false; - } + bool IsOrdered() const override; /** * Makes an iterator for each record. diff --git a/tkrzw_dbm_tree.cc b/tkrzw_dbm_tree.cc index 9faa4d3..89ce8d8 100644 --- a/tkrzw_dbm_tree.cc +++ b/tkrzw_dbm_tree.cc @@ -2551,6 +2551,10 @@ Status TreeDBMIteratorImpl::ProcessImpl( return Status(Status::SUCCESS); } + +TreeDBM::TuningParameters::TuningParameters() {} + + TreeDBM::TreeDBM() { impl_ = new TreeDBMImpl(std::make_unique()); } @@ -2563,6 +2567,10 @@ TreeDBM::~TreeDBM() { delete impl_; } +Status TreeDBM::Open(const std::string& path, bool writable, int32_t options) { + return OpenAdvanced(path, writable, options); +} + Status TreeDBM::OpenAdvanced(const std::string& path, bool writable, int32_t options, const TuningParameters& tuning_params) { return impl_->Open(path, writable, options, tuning_params); @@ -2617,6 +2625,10 @@ Status TreeDBM::Clear() { return impl_->Clear(); } +Status TreeDBM::Rebuild() { + return RebuildAdvanced(); +} + Status TreeDBM::RebuildAdvanced( const TuningParameters& tuning_params, bool skip_broken_records, bool sync_hard) { return impl_->Rebuild(tuning_params, skip_broken_records, sync_hard); @@ -2651,6 +2663,10 @@ bool TreeDBM::IsAutoRestored() const { return impl_->IsAutoRestored(); } +bool TreeDBM::IsOrdered() const { + return true; +} + std::unique_ptr TreeDBM::MakeIterator() { std::unique_ptr iter(new TreeDBM::Iterator(impl_)); return iter; diff --git a/tkrzw_dbm_tree.h b/tkrzw_dbm_tree.h index d0b6c9d..ef7d25a 100644 --- a/tkrzw_dbm_tree.h +++ b/tkrzw_dbm_tree.h @@ -222,7 +222,7 @@ class TreeDBM final : public DBM { /** * Constructor */ - TuningParameters() {} + TuningParameters(); }; /** @@ -257,9 +257,7 @@ class TreeDBM final : public DBM { * @details Precondition: The database is not opened. */ Status Open(const std::string& path, bool writable, - int32_t options = File::OPEN_DEFAULT) override { - return OpenAdvanced(path, writable, options); - } + int32_t options = File::OPEN_DEFAULT) override; /** * Opens a database file, in an advanced way. @@ -382,9 +380,7 @@ class TreeDBM final : public DBM { * @details Rebuilding a database is useful to reduce the size of the file by solving * fragmentation. All tuning parameters are succeeded or calculated implicitly. */ - Status Rebuild() override { - return RebuildAdvanced(); - } + Status Rebuild() override; /** * Rebuilds the entire database, in an advanced way. @@ -460,9 +456,7 @@ class TreeDBM final : public DBM { * Checks whether ordered operations are supported. * @return Always true. Ordered operations are supported. */ - bool IsOrdered() const override { - return true; - } + bool IsOrdered() const override; /** * Makes an iterator for each record. diff --git a/tkrzw_file.cc b/tkrzw_file.cc new file mode 100644 index 0000000..d38d99c --- /dev/null +++ b/tkrzw_file.cc @@ -0,0 +1,57 @@ +/************************************************************************************************* + * File system utilities + * + * Copyright 2020 Google LLC + * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of the License at + * https://www.apache.org/licenses/LICENSE-2.0 + * Unless required by applicable law or agreed to in writing, software distributed under the + * License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, + * either express or implied. See the License for the specific language governing permissions + * and limitations under the License. + *************************************************************************************************/ + +#include "tkrzw_file.h" + +namespace tkrzw { + +std::string File::ReadSimple(int64_t off, size_t size) { + std::string data(size, 0); + if (Read(off, const_cast(data.data()), size) != Status::SUCCESS) { + data.clear(); + } + return data; +} + +bool File::WriteSimple(int64_t off, std::string_view data) { + return Write(off, data.data(), data.size()) == Status::SUCCESS; +} + +int64_t File::AppendSimple(const std::string& data) { + int64_t off = 0; + return Append(data.data(), data.size(), &off) == Status::SUCCESS ? off : -1; +} + +int64_t File::ExpandSimple(size_t inc_size) { + int64_t old_size = 0; + return Expand(inc_size, &old_size) == Status::SUCCESS ? old_size : -1; +} + +int64_t File::GetSizeSimple() { + int64_t size = 0; + return GetSize(&size) == Status::SUCCESS ? size : -1; +} + +std::string File::GetPathSimple() { + std::string path; + return GetPath(&path) == Status::SUCCESS ? path : ""; +} + +const std::type_info& File::GetType() const { + const auto& entity = *this; + return typeid(entity); +} + +} // namespace tkrzw + +// END OF FILE \ No newline at end of file diff --git a/tkrzw_file.h b/tkrzw_file.h index e7f916e..6aa4309 100644 --- a/tkrzw_file.h +++ b/tkrzw_file.h @@ -89,13 +89,7 @@ class File { * @param size The size of the data to be read. * @return A string of the read data. It is empty on failure. */ - virtual std::string ReadSimple(int64_t off, size_t size) { - std::string data(size, 0); - if (Read(off, const_cast(data.data()), size) != Status::SUCCESS) { - data.clear(); - } - return data; - } + virtual std::string ReadSimple(int64_t off, size_t size); /** * Writes data. @@ -112,9 +106,7 @@ class File { * @param data The data to be written. * @return True on success or false on failure. */ - virtual bool WriteSimple(int64_t off, std::string_view data) { - return Write(off, data.data(), data.size()) == Status::SUCCESS; - } + virtual bool WriteSimple(int64_t off, std::string_view data); /** * Appends data at the end of the file. @@ -131,10 +123,7 @@ class File { * @param data The data to be written. * @return The offset at which the data has been put, or -1 on failure. */ - virtual int64_t AppendSimple(const std::string& data) { - int64_t off = 0; - return Append(data.data(), data.size(), &off) == Status::SUCCESS ? off : -1; - } + virtual int64_t AppendSimple(const std::string& data); /** * Expands the file size without writing data. @@ -150,10 +139,7 @@ class File { * @param inc_size The size to increment the file size by. * @return The old size of the file, or -1 on failure. */ - virtual int64_t ExpandSimple(size_t inc_size) { - int64_t old_size = 0; - return Expand(inc_size, &old_size) == Status::SUCCESS ? old_size : -1; - } + virtual int64_t ExpandSimple(size_t inc_size); /** * Truncates the file. @@ -200,10 +186,7 @@ class File { * Gets the size of the file, in a simple way. * @return The size of the on success, or -1 on failure. */ - virtual int64_t GetSizeSimple() { - int64_t size = 0; - return GetSize(&size) == Status::SUCCESS ? size : -1; - } + virtual int64_t GetSizeSimple(); /** * Sets allocation strategy. @@ -233,10 +216,7 @@ class File { * Gets the path of the file, in a simple way. * @return The path of the file on success, or an empty string on failure. */ - virtual std::string GetPathSimple() { - std::string path; - return GetPath(&path) == Status::SUCCESS ? path : ""; - } + virtual std::string GetPathSimple(); /** * Renames the file. @@ -281,10 +261,7 @@ class File { * Gets the type information of the actual class. * @return The type information of the actual class. */ - const std::type_info& GetType() const { - const auto& entity = *this; - return typeid(entity); - } + const std::type_info& GetType() const; }; } // namespace tkrzw diff --git a/tkrzw_key_comparators.cc b/tkrzw_key_comparators.cc new file mode 100644 index 0000000..74ee2ac --- /dev/null +++ b/tkrzw_key_comparators.cc @@ -0,0 +1,152 @@ +/************************************************************************************************* + * Built-in comparators for record keys + * + * Copyright 2020 Google LLC + * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of the License at + * https://www.apache.org/licenses/LICENSE-2.0 + * Unless required by applicable law or agreed to in writing, software distributed under the + * License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, + * either express or implied. See the License for the specific language governing permissions + * and limitations under the License. + *************************************************************************************************/ + +#include "tkrzw_key_comparators.h" + +namespace tkrzw { + +int32_t LexicalKeyComparator(std::string_view a, std::string_view b) { + return a.compare(b); +} + +int32_t LexicalCaseKeyComparator(std::string_view a, std::string_view b) { + return StrCaseCompare(a, b); +} + +int32_t DecimalKeyComparator(std::string_view a, std::string_view b) { + const int64_t a_num = StrToInt(a); + const int64_t b_num = StrToInt(b); + return a_num < b_num ? -1 : (a_num > b_num ? 1 : 0); +} + +int32_t HexadecimalKeyComparator(std::string_view a, std::string_view b) { + const int64_t a_num = StrToIntHex(a); + const int64_t b_num = StrToIntHex(b); + return a_num < b_num ? -1 : (a_num > b_num ? 1 : 0); +} + +int32_t RealNumberKeyComparator(std::string_view a, std::string_view b) { + const double a_num = StrToDouble(a); + const double b_num = StrToDouble(b); + return a_num < b_num ? -1 : (a_num > b_num ? 1 : 0); +} + +int32_t SignedBigEndianKeyComparator(std::string_view a, std::string_view b) { + auto cast = [](std::string_view str) -> int64_t { + uint64_t num = StrToIntBigEndian(str); + switch(str.size()) { + case sizeof(int8_t): + num = static_cast(num); + break; + case sizeof(int16_t): + num = static_cast(num); + break; + case sizeof(int32_t): + num = static_cast(num); + break; + } + return static_cast(num); + }; + const int64_t a_num = cast(a); + const int64_t b_num = cast(b); + return a_num < b_num ? -1 : (a_num > b_num ? 1 : 0); +} + +int32_t FloatBigEndianKeyComparator(std::string_view a, std::string_view b) { + const long double a_num = StrToFloatBigEndian(a); + const long double b_num = StrToFloatBigEndian(b); + if (std::isnan(a_num)) return std::isnan(b_num) ? 0 : -1; + if (std::isnan(b_num)) return 1; + return a_num < b_num ? -1 : (a_num > b_num ? 1 : 0); +} + +int32_t PairLexicalKeyComparator(std::string_view a, std::string_view b) { + std::string_view a_key, a_value, b_key, b_value; + DeserializeStrPair(a, &a_key, &a_value); + DeserializeStrPair(b, &b_key, &b_value); + const int32_t key_cmp = LexicalKeyComparator(a_key, b_key); + if (key_cmp != 0) { + return key_cmp; + } + return LexicalKeyComparator(a_value, b_value); +} + +int32_t PairLexicalCaseKeyComparator(std::string_view a, std::string_view b) { + std::string_view a_key, a_value, b_key, b_value; + DeserializeStrPair(a, &a_key, &a_value); + DeserializeStrPair(b, &b_key, &b_value); + const int32_t key_cmp = LexicalCaseKeyComparator(a_key, b_key); + if (key_cmp != 0) { + return key_cmp; + } + return LexicalKeyComparator(a_value, b_value); +} + +int32_t PairDecimalKeyComparator(std::string_view a, std::string_view b) { + std::string_view a_key, a_value, b_key, b_value; + DeserializeStrPair(a, &a_key, &a_value); + DeserializeStrPair(b, &b_key, &b_value); + const int32_t key_cmp = DecimalKeyComparator(a_key, b_key); + if (key_cmp != 0) { + return key_cmp; + } + return LexicalKeyComparator(a_value, b_value); +} + +int32_t PairHexadecimalKeyComparator(std::string_view a, std::string_view b) { + std::string_view a_key, a_value, b_key, b_value; + DeserializeStrPair(a, &a_key, &a_value); + DeserializeStrPair(b, &b_key, &b_value); + const int32_t key_cmp = HexadecimalKeyComparator(a_key, b_key); + if (key_cmp != 0) { + return key_cmp; + } + return LexicalKeyComparator(a_value, b_value); +} + +int32_t PairRealNumberKeyComparator(std::string_view a, std::string_view b) { + std::string_view a_key, a_value, b_key, b_value; + DeserializeStrPair(a, &a_key, &a_value); + DeserializeStrPair(b, &b_key, &b_value); + const int32_t key_cmp = RealNumberKeyComparator(a_key, b_key); + if (key_cmp != 0) { + return key_cmp; + } + return LexicalKeyComparator(a_value, b_value); +} + +int32_t PairSignedBigEndianKeyComparator(std::string_view a, std::string_view b) { + std::string_view a_key, a_value, b_key, b_value; + DeserializeStrPair(a, &a_key, &a_value); + DeserializeStrPair(b, &b_key, &b_value); + const int32_t key_cmp = SignedBigEndianKeyComparator(a_key, b_key); + if (key_cmp != 0) { + return key_cmp; + } + return LexicalKeyComparator(a_value, b_value); +} + +int32_t PairFloatBigEndianKeyComparator(std::string_view a, std::string_view b) { + std::string_view a_key, a_value, b_key, b_value; + DeserializeStrPair(a, &a_key, &a_value); + DeserializeStrPair(b, &b_key, &b_value); + const int32_t key_cmp = FloatBigEndianKeyComparator(a_key, b_key); + if (key_cmp != 0) { + return key_cmp; + } + return LexicalKeyComparator(a_value, b_value); +} + +} // namespace tkrzw + +// END OF FILE \ No newline at end of file diff --git a/tkrzw_key_comparators.h b/tkrzw_key_comparators.h index 2dbc680..e21868e 100644 --- a/tkrzw_key_comparators.h +++ b/tkrzw_key_comparators.h @@ -40,9 +40,7 @@ typedef int32_t (*KeyComparator)(std::string_view, std::string_view); * @param b The other key. * @return -1 if "a" is less, 1 if "a" is greater, and 0 if both are equivalent. */ -inline int32_t LexicalKeyComparator(std::string_view a, std::string_view b) { - return a.compare(b); -} +int32_t LexicalKeyComparator(std::string_view a, std::string_view b); /** * Key comparator in the lexical order ignoring case. @@ -50,9 +48,7 @@ inline int32_t LexicalKeyComparator(std::string_view a, std::string_view b) { * @param b The other key. * @return -1 if "a" is less, 1 if "a" is greater, and 0 if both are equivalent. */ -inline int32_t LexicalCaseKeyComparator(std::string_view a, std::string_view b) { - return StrCaseCompare(a, b); -} +int32_t LexicalCaseKeyComparator(std::string_view a, std::string_view b); /** * Key comparator in the order of decimal integer numeric expressions. @@ -60,11 +56,7 @@ inline int32_t LexicalCaseKeyComparator(std::string_view a, std::string_view b) * @param b The other key. * @return -1 if "a" is less, 1 if "a" is greater, and 0 if both are equivalent. */ -inline int32_t DecimalKeyComparator(std::string_view a, std::string_view b) { - const int64_t a_num = StrToInt(a); - const int64_t b_num = StrToInt(b); - return a_num < b_num ? -1 : (a_num > b_num ? 1 : 0); -} +int32_t DecimalKeyComparator(std::string_view a, std::string_view b); /** * Key comparator in the order of hexadecimal integer numeric expressions. @@ -72,11 +64,7 @@ inline int32_t DecimalKeyComparator(std::string_view a, std::string_view b) { * @param b The other key. * @return -1 if "a" is less, 1 if "a" is greater, and 0 if both are equivalent. */ -inline int32_t HexadecimalKeyComparator(std::string_view a, std::string_view b) { - const int64_t a_num = StrToIntHex(a); - const int64_t b_num = StrToIntHex(b); - return a_num < b_num ? -1 : (a_num > b_num ? 1 : 0); -} +int32_t HexadecimalKeyComparator(std::string_view a, std::string_view b); /** * Key comparator in the order of decimal real number expressions. @@ -84,11 +72,7 @@ inline int32_t HexadecimalKeyComparator(std::string_view a, std::string_view b) * @param b The other key. * @return -1 if "a" is less, 1 if "a" is greater, and 0 if both are equivalent. */ -inline int32_t RealNumberKeyComparator(std::string_view a, std::string_view b) { - const double a_num = StrToDouble(a); - const double b_num = StrToDouble(b); - return a_num < b_num ? -1 : (a_num > b_num ? 1 : 0); -} +int32_t RealNumberKeyComparator(std::string_view a, std::string_view b); /** * Key comparator in the order of big-endian binaries of signed integer numbers. @@ -96,26 +80,7 @@ inline int32_t RealNumberKeyComparator(std::string_view a, std::string_view b) { * @param b The other key. * @return -1 if "a" is less, 1 if "a" is greater, and 0 if both are equivalent. */ -inline int32_t SignedBigEndianKeyComparator(std::string_view a, std::string_view b) { - auto cast = [](std::string_view str) -> int64_t { - uint64_t num = StrToIntBigEndian(str); - switch(str.size()) { - case sizeof(int8_t): - num = static_cast(num); - break; - case sizeof(int16_t): - num = static_cast(num); - break; - case sizeof(int32_t): - num = static_cast(num); - break; - } - return static_cast(num); - }; - const int64_t a_num = cast(a); - const int64_t b_num = cast(b); - return a_num < b_num ? -1 : (a_num > b_num ? 1 : 0); -} +int32_t SignedBigEndianKeyComparator(std::string_view a, std::string_view b); /** * Key comparator in the order of big-endian binaries of floating-point numbers. @@ -123,13 +88,7 @@ inline int32_t SignedBigEndianKeyComparator(std::string_view a, std::string_view * @param b The other key. * @return -1 if "a" is less, 1 if "a" is greater, and 0 if both are equivalent. */ -inline int32_t FloatBigEndianKeyComparator(std::string_view a, std::string_view b) { - const long double a_num = StrToFloatBigEndian(a); - const long double b_num = StrToFloatBigEndian(b); - if (std::isnan(a_num)) return std::isnan(b_num) ? 0 : -1; - if (std::isnan(b_num)) return 1; - return a_num < b_num ? -1 : (a_num > b_num ? 1 : 0); -} +int32_t FloatBigEndianKeyComparator(std::string_view a, std::string_view b); /** * Key comparator for serialized pair strings in the lexical order. @@ -137,16 +96,7 @@ inline int32_t FloatBigEndianKeyComparator(std::string_view a, std::string_view * @param b The other key. * @return -1 if "a" is less, 1 if "a" is greater, and 0 if both are equivalent. */ -inline int32_t PairLexicalKeyComparator(std::string_view a, std::string_view b) { - std::string_view a_key, a_value, b_key, b_value; - DeserializeStrPair(a, &a_key, &a_value); - DeserializeStrPair(b, &b_key, &b_value); - const int32_t key_cmp = LexicalKeyComparator(a_key, b_key); - if (key_cmp != 0) { - return key_cmp; - } - return LexicalKeyComparator(a_value, b_value); -} +int32_t PairLexicalKeyComparator(std::string_view a, std::string_view b); /** * Key comparator for serialized pair strings in the lexical order ignoring case. @@ -154,16 +104,7 @@ inline int32_t PairLexicalKeyComparator(std::string_view a, std::string_view b) * @param b The other key. * @return -1 if "a" is less, 1 if "a" is greater, and 0 if both are equivalent. */ -inline int32_t PairLexicalCaseKeyComparator(std::string_view a, std::string_view b) { - std::string_view a_key, a_value, b_key, b_value; - DeserializeStrPair(a, &a_key, &a_value); - DeserializeStrPair(b, &b_key, &b_value); - const int32_t key_cmp = LexicalCaseKeyComparator(a_key, b_key); - if (key_cmp != 0) { - return key_cmp; - } - return LexicalKeyComparator(a_value, b_value); -} +int32_t PairLexicalCaseKeyComparator(std::string_view a, std::string_view b); /** * Key comparator for serialized pair strings in the decimal integer order. @@ -171,16 +112,7 @@ inline int32_t PairLexicalCaseKeyComparator(std::string_view a, std::string_view * @param b The other key. * @return -1 if "a" is less, 1 if "a" is greater, and 0 if both are equivalent. */ -inline int32_t PairDecimalKeyComparator(std::string_view a, std::string_view b) { - std::string_view a_key, a_value, b_key, b_value; - DeserializeStrPair(a, &a_key, &a_value); - DeserializeStrPair(b, &b_key, &b_value); - const int32_t key_cmp = DecimalKeyComparator(a_key, b_key); - if (key_cmp != 0) { - return key_cmp; - } - return LexicalKeyComparator(a_value, b_value); -} +int32_t PairDecimalKeyComparator(std::string_view a, std::string_view b); /** * Key comparator for serialized pair strings in the hexadecimal integer order. @@ -188,16 +120,7 @@ inline int32_t PairDecimalKeyComparator(std::string_view a, std::string_view b) * @param b The other key. * @return -1 if "a" is less, 1 if "a" is greater, and 0 if both are equivalent. */ -inline int32_t PairHexadecimalKeyComparator(std::string_view a, std::string_view b) { - std::string_view a_key, a_value, b_key, b_value; - DeserializeStrPair(a, &a_key, &a_value); - DeserializeStrPair(b, &b_key, &b_value); - const int32_t key_cmp = HexadecimalKeyComparator(a_key, b_key); - if (key_cmp != 0) { - return key_cmp; - } - return LexicalKeyComparator(a_value, b_value); -} +int32_t PairHexadecimalKeyComparator(std::string_view a, std::string_view b); /** * Key comparator for serialized pair strings in the decimal real number order. @@ -205,16 +128,7 @@ inline int32_t PairHexadecimalKeyComparator(std::string_view a, std::string_view * @param b The other key. * @return -1 if "a" is less, 1 if "a" is greater, and 0 if both are equivalent. */ -inline int32_t PairRealNumberKeyComparator(std::string_view a, std::string_view b) { - std::string_view a_key, a_value, b_key, b_value; - DeserializeStrPair(a, &a_key, &a_value); - DeserializeStrPair(b, &b_key, &b_value); - const int32_t key_cmp = RealNumberKeyComparator(a_key, b_key); - if (key_cmp != 0) { - return key_cmp; - } - return LexicalKeyComparator(a_value, b_value); -} +int32_t PairRealNumberKeyComparator(std::string_view a, std::string_view b); /** * Key comparator for serialized pair strings in the big-endian binary signed integer order. @@ -222,16 +136,7 @@ inline int32_t PairRealNumberKeyComparator(std::string_view a, std::string_view * @param b The other key. * @return -1 if "a" is less, 1 if "a" is greater, and 0 if both are equivalent. */ -inline int32_t PairSignedBigEndianKeyComparator(std::string_view a, std::string_view b) { - std::string_view a_key, a_value, b_key, b_value; - DeserializeStrPair(a, &a_key, &a_value); - DeserializeStrPair(b, &b_key, &b_value); - const int32_t key_cmp = SignedBigEndianKeyComparator(a_key, b_key); - if (key_cmp != 0) { - return key_cmp; - } - return LexicalKeyComparator(a_value, b_value); -} +int32_t PairSignedBigEndianKeyComparator(std::string_view a, std::string_view b); /** * Key comparator for serialized pair strings in the big-endian binary floating-point number order. @@ -239,16 +144,7 @@ inline int32_t PairSignedBigEndianKeyComparator(std::string_view a, std::string_ * @param b The other key. * @return -1 if "a" is less, 1 if "a" is greater, and 0 if both are equivalent. */ -inline int32_t PairFloatBigEndianKeyComparator(std::string_view a, std::string_view b) { - std::string_view a_key, a_value, b_key, b_value; - DeserializeStrPair(a, &a_key, &a_value); - DeserializeStrPair(b, &b_key, &b_value); - const int32_t key_cmp = FloatBigEndianKeyComparator(a_key, b_key); - if (key_cmp != 0) { - return key_cmp; - } - return LexicalKeyComparator(a_value, b_value); -} +int32_t PairFloatBigEndianKeyComparator(std::string_view a, std::string_view b); } // namespace tkrzw diff --git a/tkrzw_lib_common.cc b/tkrzw_lib_common.cc index 54861af..2033313 100644 --- a/tkrzw_lib_common.cc +++ b/tkrzw_lib_common.cc @@ -39,6 +39,42 @@ const bool IS_BIG_ENDIAN = _IS_BIG_ENDIAN; #endif +void* xmalloc(size_t size) { + void* ptr = std::malloc(size); + if (ptr == nullptr) { + throw std::bad_alloc(); + } + return ptr; +} + +void* xcalloc(size_t nmemb, size_t size) { + void* ptr = std::calloc(nmemb, size); + if (ptr == nullptr) { + throw std::bad_alloc(); + } + return ptr; +} + +void* xrealloc(void* ptr, size_t size) { + ptr = std::realloc(ptr, size); + if (ptr == nullptr) { + throw std::bad_alloc(); + } + return ptr; +} + +void xfree(void* ptr) { + std::free(ptr); +} + +void* xreallocappend(void* ptr, size_t size) { + size_t aligned_size = 8; + while (aligned_size < size) { + aligned_size += aligned_size >> 1; + } + return xrealloc(ptr, aligned_size); +} + void* xmallocaligned(size_t alignment, size_t size) { #if defined(_SYS_LINUX_) assert(alignment >= sizeof(void*)); @@ -237,6 +273,160 @@ int64_t GetMemoryUsage() { return StrToInt(tkrzw::SearchMap(records, "mem_rss", "-1")); } +Status::Status() + : code_(Code::SUCCESS), message_(nullptr) {} + +Status::Status(Code code) : code_(code), message_(nullptr) {} + +Status::Status(Code code, std::string_view message) : code_(code), message_(nullptr) { + message_ = static_cast(xmalloc(message.size() + 1)); + std::memcpy(message_, message.data(), message.size()); + message_[message.size()] = '\0'; +} + +Status::Status(const Status& rhs) : code_(rhs.code_), message_(nullptr) { + if (rhs.message_ != nullptr) { + const size_t message_size = std::strlen(rhs.message_); + message_ = static_cast(xrealloc(message_, message_size + 1)); + std::memcpy(message_, rhs.message_, message_size); + message_[message_size] = '\0'; + } +} + +Status::Status(Status&& rhs) : code_(rhs.code_), message_(rhs.message_) { + rhs.message_ = nullptr; +} + +Status::~Status() { + xfree(message_); +} + +Status& Status::operator =(const Status& rhs) { + if (this != &rhs) { + code_ = rhs.code_; + if (rhs.message_ == nullptr) { + xfree(message_); + message_ = nullptr; + } else { + const size_t message_size = std::strlen(rhs.message_); + message_ = static_cast(xrealloc(message_, message_size + 1)); + std::memcpy(message_, rhs.message_, message_size); + message_[message_size] = '\0'; + } + } + return *this; +} + +Status& Status::operator =(Status&& rhs) { + if (this != &rhs) { + code_ = rhs.code_; + xfree(message_); + message_ = rhs.message_; + rhs.message_ = nullptr; + } + return *this; +} + +Status& Status::operator |=(const Status& rhs) { + if (this != &rhs && code_ == SUCCESS && rhs.code_ != SUCCESS) { + code_ = rhs.code_; + if (rhs.message_ == nullptr) { + xfree(message_); + message_ = nullptr; + } else { + const size_t message_size = std::strlen(rhs.message_); + message_ = static_cast(xrealloc(message_, message_size + 1)); + std::memcpy(message_, rhs.message_, message_size); + message_[message_size] = '\0'; + } + } + return *this; +} + +Status& Status::operator |=(Status&& rhs) { + if (this != &rhs && code_ == SUCCESS && rhs.code_ != SUCCESS) { + code_ = rhs.code_; + xfree(message_); + message_ = rhs.message_; + rhs.message_ = nullptr; + } + return *this; +} + +Status::Code Status::GetCode() const { + return code_; +} + +std::string Status::GetMessage() const { + return message_ == nullptr ? "" : message_; +} + +bool Status::HasMessage() const { + return message_ != nullptr && *message_ != '\0'; +} + +char* Status::MakeMessageC() const { + if (message_ == nullptr) { + char* str = static_cast(xmalloc(1)); + *str = '\0'; + return str; + } + const size_t size = std::strlen(message_); + char* str = static_cast(xmalloc(size + 1)); + std::memcpy(str, message_, size + 1); + return str; +} + +void Status::Set(Code code) { + code_ = code; + xfree(message_); + message_ = nullptr; +} + +void Status::Set(Code code, std::string_view message) { + code_ = code; + message_ = static_cast(xrealloc(message_, message.size() + 1)); + std::memcpy(message_, message.data(), message.size()); + message_[message.size()] = '\0'; +} + +bool Status::operator ==(const Status& rhs) const { + return code_ == rhs.code_; +} + +bool Status::operator !=(const Status& rhs) const { + return code_ != rhs.code_; +} + +bool Status::operator ==(const Code& code) const { + return code_ == code; +} + +bool Status::operator !=(const Code& code) const { + return code_ != code; +} + +bool Status::operator <(const Status& rhs) const { + if (code_ != rhs.code_) { + return code_ < rhs.code_; + } + return std::strcmp(message_ != nullptr ? message_ : "", + rhs.message_ != nullptr ? rhs.message_ : ""); +} + +Status::operator std::string() const { + std::string expr(CodeName(code_)); + if (message_ != nullptr) { + expr += ": "; + expr += message_; + } + return expr; +} + +bool Status::IsOK() const { + return code_ == SUCCESS; +} + const Status& Status::OrDie() const { if (code_ != SUCCESS) { throw StatusException(*this); @@ -244,6 +434,56 @@ const Status& Status::OrDie() const { return *this; } +const char* Status::CodeName(Code code) { + switch (code) { + case SUCCESS: return "SUCCESS"; + case UNKNOWN_ERROR: return "UNKNOWN_ERROR"; + case SYSTEM_ERROR: return "SYSTEM_ERROR"; + case NOT_IMPLEMENTED_ERROR: return "NOT_IMPLEMENTED_ERROR"; + case PRECONDITION_ERROR: return "PRECONDITION_ERROR"; + case INVALID_ARGUMENT_ERROR: return "INVALID_ARGUMENT_ERROR"; + case CANCELED_ERROR : return "CANCELED_ERROR"; + case NOT_FOUND_ERROR: return "NOT_FOUND_ERROR"; + case PERMISSION_ERROR: return "PERMISSION_ERROR"; + case INFEASIBLE_ERROR: return "INFEASIBLE_ERROR"; + case DUPLICATION_ERROR: return "DUPLICATION_ERROR"; + case BROKEN_DATA_ERROR: return "BROKEN_DATA_ERROR"; + case NETWORK_ERROR: return "NETWORK_ERROR"; + case APPLICATION_ERROR: return "APPLICATION_ERROR"; + } + return "unnamed error"; +} + +bool operator ==(const Status::Code& lhs, const Status& rhs) { + return lhs == rhs.GetCode(); +} + +bool operator !=(const Status::Code& lhs, const Status& rhs) { + return lhs != rhs.GetCode(); +} + +std::string ToString(const Status& status) { + return std::string(status); +} + +std::ostream& operator<<(std::ostream& os, const Status& status) { + return os << std::string(status); +} + + + +StatusException::StatusException(const Status& status) + : std::runtime_error(ToString(status)), status_(status) {} + +Status StatusException::GetStatus() const { + return status_; +} + +StatusException::operator std::string() const { + return std::string(status_); +} + + Status GetErrnoStatus(const char* call_name, int32_t sys_err_num) { auto msg = [&](const char* message) { return std::string(call_name) + ": " + message; diff --git a/tkrzw_lib_common.h b/tkrzw_lib_common.h index 1a87a91..076851a 100644 --- a/tkrzw_lib_common.h +++ b/tkrzw_lib_common.h @@ -147,13 +147,7 @@ extern const bool IS_BIG_ENDIAN; * @param size The size of the region. * @return The pointer to the allocated region. */ -inline void* xmalloc(size_t size) { - void* ptr = std::malloc(size); - if (ptr == nullptr) { - throw std::bad_alloc(); - } - return ptr; -} +void* xmalloc(size_t size); /** * Allocates a nullified region on memory. @@ -161,13 +155,7 @@ inline void* xmalloc(size_t size) { * @param size The size of each element. * @return The pointer to the allocated region. */ -inline void* xcalloc(size_t nmemb, size_t size) { - void* ptr = std::calloc(nmemb, size); - if (ptr == nullptr) { - throw std::bad_alloc(); - } - return ptr; -} +void* xcalloc(size_t nmemb, size_t size); /** * Re-allocates a region on memory. @@ -175,13 +163,7 @@ inline void* xcalloc(size_t nmemb, size_t size) { * @param size The size of the region. * @return The pointer to the re-allocated region. */ -inline void* xrealloc(void* ptr, size_t size) { - ptr = std::realloc(ptr, size); - if (ptr == nullptr) { - throw std::bad_alloc(); - } - return ptr; -} +void* xrealloc(void* ptr, size_t size); /** * Re-allocates a region on memory for appending operations. @@ -189,21 +171,13 @@ inline void* xrealloc(void* ptr, size_t size) { * @param size The size of the region. * @return The pointer to the re-allocated region. */ -inline void* xreallocappend(void* ptr, size_t size) { - size_t aligned_size = 8; - while (aligned_size < size) { - aligned_size += aligned_size >> 1; - } - return xrealloc(ptr, aligned_size); -} +void* xreallocappend(void* ptr, size_t size); /** * Frees a region on memory. * @param ptr The pointer to the region. */ -inline void xfree(void* ptr) { - std::free(ptr); -} +void xfree(void* ptr); /** * Allocates an aligned region on memory. @@ -332,252 +306,145 @@ class Status final { /** * Default constructor representing the success code. */ - Status() : code_(Code::SUCCESS), message_(nullptr) {} + Status(); /** * Constructor representing a specific status. * @param code The status code. */ - explicit Status(Code code) : code_(code), message_(nullptr) {} + explicit Status(Code code); /** * Constructor representing a specific status with a message. * @param code The status code. * @param message An arbitrary status message. */ - Status(Code code, std::string_view message) : code_(code), message_(nullptr) { - message_ = static_cast(xmalloc(message.size() + 1)); - std::memcpy(message_, message.data(), message.size()); - message_[message.size()] = '\0'; - } + Status(Code code, std::string_view message); /** * Copy constructor. * @param rhs The right-hand-side object. */ - Status(const Status& rhs) : code_(rhs.code_), message_(nullptr) { - if (rhs.message_ != nullptr) { - const size_t message_size = std::strlen(rhs.message_); - message_ = static_cast(xrealloc(message_, message_size + 1)); - std::memcpy(message_, rhs.message_, message_size); - message_[message_size] = '\0'; - } - } + Status(const Status& rhs); /** * Move constructor. * @param rhs The right-hand-side object. */ - Status(Status&& rhs) : code_(rhs.code_), message_(rhs.message_) { - rhs.message_ = nullptr; - } + Status(Status&& rhs); /** * Destructor. */ - ~Status() { - xfree(message_); - } + ~Status(); /** * Assigns the internal state from another status object. * @param rhs The status object. */ - Status& operator =(const Status& rhs) { - if (this != &rhs) { - code_ = rhs.code_; - if (rhs.message_ == nullptr) { - xfree(message_); - message_ = nullptr; - } else { - const size_t message_size = std::strlen(rhs.message_); - message_ = static_cast(xrealloc(message_, message_size + 1)); - std::memcpy(message_, rhs.message_, message_size); - message_[message_size] = '\0'; - } - } - return *this; - } + Status& operator =(const Status& rhs); /** * Assigns the internal state from another moved status object. * @param rhs The status object. */ - Status& operator =(Status&& rhs) { - if (this != &rhs) { - code_ = rhs.code_; - xfree(message_); - message_ = rhs.message_; - rhs.message_ = nullptr; - } - return *this; - } + Status& operator =(Status&& rhs); /** * Assigns the internal state from another status object only if the current state is success. * @param rhs The status object. */ - Status& operator |=(const Status& rhs) { - if (this != &rhs && code_ == SUCCESS && rhs.code_ != SUCCESS) { - code_ = rhs.code_; - if (rhs.message_ == nullptr) { - xfree(message_); - message_ = nullptr; - } else { - const size_t message_size = std::strlen(rhs.message_); - message_ = static_cast(xrealloc(message_, message_size + 1)); - std::memcpy(message_, rhs.message_, message_size); - message_[message_size] = '\0'; - } - } - return *this; - } + Status& operator |=(const Status& rhs); /** * Assigns the internal state from another status object only if the current state is success. * @param rhs The status object. */ - Status& operator |=(Status&& rhs) { - if (this != &rhs && code_ == SUCCESS && rhs.code_ != SUCCESS) { - code_ = rhs.code_; - xfree(message_); - message_ = rhs.message_; - rhs.message_ = nullptr; - } - return *this; - } + Status& operator |=(Status&& rhs); /** * Gets the status code. * @return The status code. */ - Code GetCode() const { - return code_; - } + Code GetCode() const; /** * Gets the status message. * @return The status message. */ - std::string GetMessage() const { - return message_ == nullptr ? "" : message_; - } + std::string GetMessage() const; /** * Checks whether the status has a non-empty message. * @return True if the status has a non-empty message. */ - bool HasMessage() const { - return message_ != nullptr && *message_ != '\0'; - } + bool HasMessage() const; /** * Makes a C string of the message. * @return The C message string, which should be released by the free function. */ - char* MakeMessageC() const { - if (message_ == nullptr) { - char* str = static_cast(xmalloc(1)); - *str = '\0'; - return str; - } - const size_t size = std::strlen(message_); - char* str = static_cast(xmalloc(size + 1)); - std::memcpy(str, message_, size + 1); - return str; - } + char* MakeMessageC() const; /** * Sets the code and an empty message. * @param code The status code. */ - void Set(Code code) { - code_ = code; - xfree(message_); - message_ = nullptr; - } + void Set(Code code); /** * Sets the code and the message. * @param code The status code. * @param message An arbitrary status message. */ - void Set(Code code, std::string_view message) { - code_ = code; - message_ = static_cast(xrealloc(message_, message.size() + 1)); - std::memcpy(message_, message.data(), message.size()); - message_[message.size()] = '\0'; - } + void Set(Code code, std::string_view message); /** * Checks whether the internal status code is equal to a given status. * @param rhs The status to compare. * @return True if the internal status code is equal to the given status. */ - bool operator ==(const Status& rhs) const { - return code_ == rhs.code_; - } + bool operator ==(const Status& rhs) const; /** * Checks whether the internal status code is not equal to a given status. * @param rhs The status to compare. * @return True if the internal status code is not equal to the given status. */ - bool operator !=(const Status& rhs) const { - return code_ != rhs.code_; - } + bool operator !=(const Status& rhs) const; /** * Checks whether the internal status code is equal to a given code. * @param code The code to compare. * @return True if the internal status code is equal to the given code. */ - bool operator ==(const Code& code) const { - return code_ == code; - } + bool operator ==(const Code& code) const; /** * Checks whether the internal status code is not equal to a given code. * @param code The code to compare. * @return True if the internal status code is not equal to the given code. */ - bool operator !=(const Code& code) const { - return code_ != code; - } + bool operator !=(const Code& code) const; /** * Compares this object with another status object. * @param rhs The status to compare. * @return True if this object is considered less than the given object. */ - bool operator <(const Status& rhs) const { - if (code_ != rhs.code_) { - return code_ < rhs.code_; - } - return std::strcmp(message_ != nullptr ? message_ : "", - rhs.message_ != nullptr ? rhs.message_ : ""); - } + bool operator <(const Status& rhs) const; /** * Gets a string expression of the status. * @return The string expression */ - operator std::string() const { - std::string expr(CodeName(code_)); - if (message_ != nullptr) { - expr += ": "; - expr += message_; - } - return expr; - } + operator std::string() const; /** * Returns true if the status is success. * @return True if the status is success, or false on failure. */ - bool IsOK() const { - return code_ == SUCCESS; - } + bool IsOK() const; /** * Throws an exception if the status is not success. @@ -590,25 +457,7 @@ class Status final { * @param code The status code. * @return The name of the status code. */ - static const char* CodeName(Code code) { - switch (code) { - case SUCCESS: return "SUCCESS"; - case UNKNOWN_ERROR: return "UNKNOWN_ERROR"; - case SYSTEM_ERROR: return "SYSTEM_ERROR"; - case NOT_IMPLEMENTED_ERROR: return "NOT_IMPLEMENTED_ERROR"; - case PRECONDITION_ERROR: return "PRECONDITION_ERROR"; - case INVALID_ARGUMENT_ERROR: return "INVALID_ARGUMENT_ERROR"; - case CANCELED_ERROR : return "CANCELED_ERROR"; - case NOT_FOUND_ERROR: return "NOT_FOUND_ERROR"; - case PERMISSION_ERROR: return "PERMISSION_ERROR"; - case INFEASIBLE_ERROR: return "INFEASIBLE_ERROR"; - case DUPLICATION_ERROR: return "DUPLICATION_ERROR"; - case BROKEN_DATA_ERROR: return "BROKEN_DATA_ERROR"; - case NETWORK_ERROR: return "NETWORK_ERROR"; - case APPLICATION_ERROR: return "APPLICATION_ERROR"; - } - return "unnamed error"; - } + static const char* CodeName(Code code); private: /** Status code. */ @@ -623,9 +472,7 @@ class Status final { * @param rhs The status object to compare. * @return True if The status code is equal to the status object. */ -inline bool operator ==(const Status::Code& lhs, const Status& rhs) { - return lhs == rhs.GetCode(); -} +bool operator ==(const Status::Code& lhs, const Status& rhs); /** * Checks whether a status code is not equal to another status object. @@ -633,18 +480,14 @@ inline bool operator ==(const Status::Code& lhs, const Status& rhs) { * @param rhs The status object to compare. * @return True if The status code is equal to the status object. */ -inline bool operator !=(const Status::Code& lhs, const Status& rhs) { - return lhs != rhs.GetCode(); -} +bool operator !=(const Status::Code& lhs, const Status& rhs); /** * Converts a status into a string. * @param status The status object. * @return The converted string. */ -inline std::string ToString(const Status& status) { - return std::string(status); -} +std::string ToString(const Status& status); /** * Outputs a status string into an output stream. @@ -652,9 +495,7 @@ inline std::string ToString(const Status& status) { * @param status The status. * @return The output stream. */ -inline std::ostream& operator<<(std::ostream& os, const Status& status) { - return os << std::string(status); -} +std::ostream& operator<<(std::ostream& os, const Status& status); /** * Exception to convey the status of operations. @@ -665,24 +506,19 @@ class StatusException final : public std::runtime_error { * Constructor. * @param status The status to convey. */ - explicit StatusException(const Status& status) - : std::runtime_error(ToString(status)), status_(status) {} + explicit StatusException(const Status& status); /** * Gets the status object. * @return The status object. */ - Status GetStatus() const { - return status_; - } + Status GetStatus() const; /** * Gets a string expression of the status. * @return The string expression */ - operator std::string() const { - return std::string(status_); - } + operator std::string() const; private: /** The status object. */