diff --git a/implementations/caching2/CacheEntry.cpp b/implementations/caching2/CacheEntry.cpp new file mode 100644 index 00000000..0ca41a63 --- /dev/null +++ b/implementations/caching2/CacheEntry.cpp @@ -0,0 +1,2 @@ +#include "CacheEntry.h" +#include "../../interface/Block.h" diff --git a/implementations/caching2/CacheEntry.h b/implementations/caching2/CacheEntry.h new file mode 100644 index 00000000..ce04eb81 --- /dev/null +++ b/implementations/caching2/CacheEntry.h @@ -0,0 +1,37 @@ +#pragma once +#ifndef MESSMER_BLOCKSTORE_IMPLEMENTATIONS_CACHING2_CACHEENTRY_H_ +#define MESSMER_BLOCKSTORE_IMPLEMENTATIONS_CACHING2_CACHEENTRY_H_ + +#include +#include +#include + +namespace blockstore { +class Block; +namespace caching2 { + +class CacheEntry { +public: + CacheEntry(std::unique_ptr block): _lastAccess(time(nullptr)), _block(std::move(block)) { + } + + double ageSeconds() { + return difftime(time(nullptr), _lastAccess); + } + + std::unique_ptr releaseBlock() { + return std::move(_block); + } + +private: + time_t _lastAccess; + std::unique_ptr _block; + + DISALLOW_COPY_AND_ASSIGN(CacheEntry); +}; + +} +} + + +#endif diff --git a/implementations/caching2/Caching2BlockStore.cpp b/implementations/caching2/Caching2BlockStore.cpp new file mode 100644 index 00000000..4d77e160 --- /dev/null +++ b/implementations/caching2/Caching2BlockStore.cpp @@ -0,0 +1,34 @@ +#include "Caching2BlockStore.h" +#include "../../interface/Block.h" + +using std::unique_ptr; + +namespace blockstore { +namespace caching2 { + +Caching2BlockStore::Caching2BlockStore(std::unique_ptr baseBlockStore) + :_baseBlockStore(std::move(baseBlockStore)) { +} + +unique_ptr Caching2BlockStore::create(size_t size) { + //TODO Also cache this and only write back in the destructor? + // When writing back is done efficiently in the base store (e.g. only one safe-to-disk, not one in the create() and then one in the save(), this is not supported by the current BlockStore interface), + // then the base store could actually directly create a block in the create() call, OnDiskBlockStore wouldn't have to avoid file creation in the create() call for performance reasons and I could also adapt the OnDiskBlockStore test cases and remove a lot of flush() calls there because then blocks are loadable directly after the create call() without a flush. + // Currently, OnDiskBlockStore doesn't create new blocks directly but only after they're destructed (performance reasons), but this means a newly created block can't be loaded directly. + return _baseBlockStore->create(size); +} + +unique_ptr Caching2BlockStore::load(const Key &key) { + return _baseBlockStore->load(key); +} + +void Caching2BlockStore::remove(std::unique_ptr block) { + return _baseBlockStore->remove(std::move(block)); +} + +uint64_t Caching2BlockStore::numBlocks() const { + return _baseBlockStore->numBlocks(); +} + +} +} diff --git a/implementations/caching2/Caching2BlockStore.h b/implementations/caching2/Caching2BlockStore.h new file mode 100644 index 00000000..f89de57b --- /dev/null +++ b/implementations/caching2/Caching2BlockStore.h @@ -0,0 +1,31 @@ +#pragma once +#ifndef BLOCKSTORE_IMPLEMENTATIONS_CACHING2_CACHINGBLOCKSTORE_H_ +#define BLOCKSTORE_IMPLEMENTATIONS_CACHING2_CACHINGBLOCKSTORE_H_ + +#include "../../interface/BlockStore.h" +#include "CacheEntry.h" + +namespace blockstore { +namespace caching2 { + +class Caching2BlockStore: public BlockStore { +public: + Caching2BlockStore(std::unique_ptr baseBlockStore); + + std::unique_ptr create(size_t size) override; + std::unique_ptr load(const Key &key) override; + void remove(std::unique_ptr block) override; + uint64_t numBlocks() const override; + +private: + + std::unique_ptr _baseBlockStore; + std::map _cachedBlocks; + + DISALLOW_COPY_AND_ASSIGN(Caching2BlockStore); +}; + +} +} + +#endif diff --git a/test/implementations/caching2/Caching2BlockStoreTest.cpp b/test/implementations/caching2/Caching2BlockStoreTest.cpp new file mode 100644 index 00000000..b588b0cc --- /dev/null +++ b/test/implementations/caching2/Caching2BlockStoreTest.cpp @@ -0,0 +1,23 @@ +#include "../../../implementations/caching2/Caching2BlockStore.h" +#include "../../../implementations/testfake/FakeBlockStore.h" +#include "../../testutils/BlockStoreTest.h" +#include "google/gtest/gtest.h" + + +using blockstore::BlockStore; +using blockstore::caching2::Caching2BlockStore; +using blockstore::testfake::FakeBlockStore; + +using std::unique_ptr; +using std::make_unique; + +class Caching2BlockStoreTestFixture: public BlockStoreTestFixture { +public: + unique_ptr createBlockStore() override { + return make_unique(make_unique()); + } +}; + +INSTANTIATE_TYPED_TEST_CASE_P(Caching2, BlockStoreTest, Caching2BlockStoreTestFixture); + +//TODO Add specific tests for the blockstore