From 6549b117148f01a5c35287d5de9754183dd3b781 Mon Sep 17 00:00:00 2001 From: anand76 Date: Fri, 20 Sep 2024 12:13:19 -0700 Subject: [PATCH] Make Cache a customizable class (#13024) Summary: This PR allows a Cache object to be created using the object registry. Pull Request resolved: https://github.com/facebook/rocksdb/pull/13024 Reviewed By: pdillinger Differential Revision: D63043233 Pulled By: anand1976 fbshipit-source-id: 5bc3f7c29b35ad62638ff8205451303e2cecea9d --- cache/cache.cc | 28 ++++++++++------- include/rocksdb/advanced_cache.h | 4 ++- options/customizable_test.cc | 31 +++++++++++++++++++ tools/db_bench_tool.cc | 11 ++++++- .../new_features/customizable_cache.md | 1 + 5 files changed, 61 insertions(+), 14 deletions(-) create mode 100644 unreleased_history/new_features/customizable_cache.md diff --git a/cache/cache.cc b/cache/cache.cc index 3dbea128e1..cf5febb705 100644 --- a/cache/cache.cc +++ b/cache/cache.cc @@ -133,19 +133,23 @@ Status Cache::CreateFromString(const ConfigOptions& config_options, std::shared_ptr* result) { Status status; std::shared_ptr cache; - if (value.find('=') == std::string::npos) { - cache = NewLRUCache(ParseSizeT(value)); - } else { - LRUCacheOptions cache_opts; - status = OptionTypeInfo::ParseStruct(config_options, "", - &lru_cache_options_type_info, "", - value, &cache_opts); - if (status.ok()) { - cache = NewLRUCache(cache_opts); + if (value.find("://") == std::string::npos) { + if (value.find('=') == std::string::npos) { + cache = NewLRUCache(ParseSizeT(value)); + } else { + LRUCacheOptions cache_opts; + status = OptionTypeInfo::ParseStruct(config_options, "", + &lru_cache_options_type_info, "", + value, &cache_opts); + if (status.ok()) { + cache = NewLRUCache(cache_opts); + } } - } - if (status.ok()) { - result->swap(cache); + if (status.ok()) { + result->swap(cache); + } + } else { + status = LoadSharedObject(config_options, value, result); } return status; } diff --git a/include/rocksdb/advanced_cache.h b/include/rocksdb/advanced_cache.h index ab9f722a05..d8eeb7d2e3 100644 --- a/include/rocksdb/advanced_cache.h +++ b/include/rocksdb/advanced_cache.h @@ -41,7 +41,7 @@ class Statistics; // // INTERNAL: See typed_cache.h for convenient wrappers on top of this API. // New virtual functions must also be added to CacheWrapper below. -class Cache { +class Cache : public Customizable { public: // types hidden from API client // Opaque handle to an entry stored in the cache. struct Handle {}; @@ -190,6 +190,8 @@ class Cache { // Destroys all remaining entries by calling the associated "deleter" virtual ~Cache() {} + static const char* Type() { return "Cache"; } + // Creates a new Cache based on the input value string and returns the result. // Currently, this method can be used to create LRUCaches only // @param config_options diff --git a/options/customizable_test.cc b/options/customizable_test.cc index 696f1b25ed..1ec2564a44 100644 --- a/options/customizable_test.cc +++ b/options/customizable_test.cc @@ -1396,6 +1396,19 @@ class MockFilterPolicy : public FilterPolicy { } }; +class MockCache : public CacheWrapper { + public: + static const char* kClassName() { return "MockCache"; } + const char* Name() const override { return kClassName(); } + + MockCache() + : CacheWrapper(NewLRUCache(LRUCacheOptions(100, 0, false, 0.0))) {} + + bool IsInstanceOf(const std::string& name) const override { + return name.find(Name()) == 0; + } +}; + static int RegisterLocalObjects(ObjectLibrary& library, const std::string& /*arg*/) { size_t num_types; @@ -1519,6 +1532,15 @@ static int RegisterLocalObjects(ObjectLibrary& library, return guard->get(); }); + library.AddFactory( + ObjectLibrary::PatternEntry(MockCache::kClassName()) + .AddSeparator("://", /*at_least_one=*/false), + [](const std::string& /*uri*/, std::unique_ptr* guard, + std::string* /* errmsg */) { + guard->reset(new MockCache()); + return guard->get(); + }); + return static_cast(library.GetFactoryCount(&num_types)); } } // namespace @@ -2111,6 +2133,15 @@ TEST_F(LoadCustomizableTest, LoadFlushBlockPolicyFactoryTest) { } } +TEST_F(LoadCustomizableTest, LoadCacheTest) { + if (RegisterTests("Test")) { + std::string uri(MockCache::kClassName()); + uri.append("://"); + auto cache = ExpectCreateShared(uri); + ASSERT_TRUE(cache->IsInstanceOf(MockCache::kClassName())); + } +} + } // namespace ROCKSDB_NAMESPACE int main(int argc, char** argv) { ::testing::InitGoogleTest(&argc, argv); diff --git a/tools/db_bench_tool.cc b/tools/db_bench_tool.cc index ebb5583514..713aaaa412 100644 --- a/tools/db_bench_tool.cc +++ b/tools/db_bench_tool.cc @@ -1753,6 +1753,7 @@ DEFINE_bool(read_with_latest_user_timestamp, true, "If true, always use the current latest timestamp for read. If " "false, choose a random timestamp from the past."); +DEFINE_string(cache_uri, "", "Full URI for creating a custom cache object"); DEFINE_string(secondary_cache_uri, "", "Full URI for creating a custom secondary cache object"); static class std::shared_ptr secondary_cache; @@ -3138,7 +3139,15 @@ class Benchmark { } std::shared_ptr block_cache; - if (FLAGS_cache_type == "clock_cache") { + if (!FLAGS_cache_uri.empty()) { + Status s = Cache::CreateFromString(ConfigOptions(), FLAGS_cache_uri, + &block_cache); + if (block_cache == nullptr) { + fprintf(stderr, "No cache registered matching string: %s status=%s\n", + FLAGS_cache_uri.c_str(), s.ToString().c_str()); + exit(1); + } + } else if (FLAGS_cache_type == "clock_cache") { fprintf(stderr, "Old clock cache implementation has been removed.\n"); exit(1); } else if (EndsWith(FLAGS_cache_type, "hyper_clock_cache")) { diff --git a/unreleased_history/new_features/customizable_cache.md b/unreleased_history/new_features/customizable_cache.md new file mode 100644 index 0000000000..b50d03c249 --- /dev/null +++ b/unreleased_history/new_features/customizable_cache.md @@ -0,0 +1 @@ +Make Cache a customizable class that can be instantiated by the object registry.