New caching store is working, but not timeout-flushing yet
This commit is contained in:
parent
72f952b57c
commit
332f6901ef
50
implementations/caching2/Cache.cpp
Normal file
50
implementations/caching2/Cache.cpp
Normal file
@ -0,0 +1,50 @@
|
|||||||
|
#include "Cache.h"
|
||||||
|
|
||||||
|
using std::unique_ptr;
|
||||||
|
using std::make_unique;
|
||||||
|
using std::mutex;
|
||||||
|
using std::lock_guard;
|
||||||
|
using std::pair;
|
||||||
|
|
||||||
|
namespace blockstore {
|
||||||
|
namespace caching2 {
|
||||||
|
|
||||||
|
constexpr uint32_t Cache::MAX_ENTRIES;
|
||||||
|
|
||||||
|
Cache::Cache(): _cachedBlocks() {
|
||||||
|
}
|
||||||
|
|
||||||
|
Cache::~Cache() {
|
||||||
|
}
|
||||||
|
|
||||||
|
unique_ptr<Block> Cache::pop(const Key &key) {
|
||||||
|
lock_guard<mutex> lock(_mutex);
|
||||||
|
auto found = _cachedBlocks.find(key);
|
||||||
|
if (found == _cachedBlocks.end()) {
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
auto block = found->second.releaseBlock();
|
||||||
|
_cachedBlocks.erase(found);
|
||||||
|
return block;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Cache::push(unique_ptr<Block> block) {
|
||||||
|
lock_guard<mutex> lock(_mutex);
|
||||||
|
if (_cachedBlocks.size() > MAX_ENTRIES) {
|
||||||
|
deleteOldestEntry();
|
||||||
|
assert(_cachedBlocks.size() == MAX_ENTRIES-1);
|
||||||
|
}
|
||||||
|
Key key = block->key();
|
||||||
|
_cachedBlocks.emplace(key, std::move(block));
|
||||||
|
}
|
||||||
|
|
||||||
|
void Cache::deleteOldestEntry() {
|
||||||
|
auto oldestEntry = std::min_element(_cachedBlocks.begin(), _cachedBlocks.end(), [] (const pair<const Key, CacheEntry> &lhs, const pair<const Key, CacheEntry> &rhs) {
|
||||||
|
return lhs.second.ageSeconds() > rhs.second.ageSeconds();
|
||||||
|
});
|
||||||
|
//printf("Deleting age %f (vs %f)\n", oldestEntry->second.ageSeconds(), _cachedBlocks.begin()->second.ageSeconds());
|
||||||
|
_cachedBlocks.erase(oldestEntry);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
33
implementations/caching2/Cache.h
Normal file
33
implementations/caching2/Cache.h
Normal file
@ -0,0 +1,33 @@
|
|||||||
|
#pragma once
|
||||||
|
#ifndef MESSMER_BLOCKSTORE_IMPLEMENTATIONS_CACHING2_CACHE_H_
|
||||||
|
#define MESSMER_BLOCKSTORE_IMPLEMENTATIONS_CACHING2_CACHE_H_
|
||||||
|
|
||||||
|
#include "../../interface/Block.h"
|
||||||
|
#include "CacheEntry.h"
|
||||||
|
#include <memory>
|
||||||
|
#include <mutex>
|
||||||
|
|
||||||
|
namespace blockstore {
|
||||||
|
namespace caching2 {
|
||||||
|
|
||||||
|
class Cache {
|
||||||
|
public:
|
||||||
|
static constexpr uint32_t MAX_ENTRIES = 1000;
|
||||||
|
|
||||||
|
Cache();
|
||||||
|
virtual ~Cache();
|
||||||
|
|
||||||
|
void push(std::unique_ptr<Block> block);
|
||||||
|
std::unique_ptr<Block> pop(const Key &key);
|
||||||
|
|
||||||
|
private:
|
||||||
|
mutable std::mutex _mutex;
|
||||||
|
std::map<Key, CacheEntry> _cachedBlocks;
|
||||||
|
|
||||||
|
void deleteOldestEntry();
|
||||||
|
};
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
@ -15,7 +15,9 @@ public:
|
|||||||
CacheEntry(std::unique_ptr<Block> block): _lastAccess(time(nullptr)), _block(std::move(block)) {
|
CacheEntry(std::unique_ptr<Block> block): _lastAccess(time(nullptr)), _block(std::move(block)) {
|
||||||
}
|
}
|
||||||
|
|
||||||
double ageSeconds() {
|
CacheEntry(CacheEntry &&) = default;
|
||||||
|
|
||||||
|
double ageSeconds() const {
|
||||||
return difftime(time(nullptr), _lastAccess);
|
return difftime(time(nullptr), _lastAccess);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
36
implementations/caching2/CachedBlock.cpp
Normal file
36
implementations/caching2/CachedBlock.cpp
Normal file
@ -0,0 +1,36 @@
|
|||||||
|
#include "CachedBlock.h"
|
||||||
|
#include "Caching2BlockStore.h"
|
||||||
|
|
||||||
|
using std::make_unique;
|
||||||
|
|
||||||
|
namespace blockstore {
|
||||||
|
namespace caching2 {
|
||||||
|
|
||||||
|
CachedBlock::CachedBlock(std::unique_ptr<Block> baseBlock, Caching2BlockStore *blockStore)
|
||||||
|
:Block(baseBlock->key()),
|
||||||
|
_blockStore(blockStore),
|
||||||
|
_baseBlock(std::move(baseBlock)) {
|
||||||
|
}
|
||||||
|
|
||||||
|
CachedBlock::~CachedBlock() {
|
||||||
|
_blockStore->release(std::move(_baseBlock));
|
||||||
|
}
|
||||||
|
|
||||||
|
const void *CachedBlock::data() const {
|
||||||
|
return _baseBlock->data();
|
||||||
|
}
|
||||||
|
|
||||||
|
void CachedBlock::write(const void *source, uint64_t offset, uint64_t size) {
|
||||||
|
return _baseBlock->write(source, offset, size);
|
||||||
|
}
|
||||||
|
|
||||||
|
void CachedBlock::flush() {
|
||||||
|
return _baseBlock->flush();
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t CachedBlock::size() const {
|
||||||
|
return _baseBlock->size();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
36
implementations/caching2/CachedBlock.h
Normal file
36
implementations/caching2/CachedBlock.h
Normal file
@ -0,0 +1,36 @@
|
|||||||
|
#pragma once
|
||||||
|
#ifndef BLOCKSTORE_IMPLEMENTATIONS_ENCRYPTED_ENCRYPTEDBLOCK_H_
|
||||||
|
#define BLOCKSTORE_IMPLEMENTATIONS_ENCRYPTED_ENCRYPTEDBLOCK_H_
|
||||||
|
|
||||||
|
#include "../../interface/Block.h"
|
||||||
|
|
||||||
|
#include "messmer/cpp-utils/macros.h"
|
||||||
|
#include <memory>
|
||||||
|
|
||||||
|
namespace blockstore {
|
||||||
|
namespace caching2 {
|
||||||
|
class Caching2BlockStore;
|
||||||
|
|
||||||
|
class CachedBlock: public Block {
|
||||||
|
public:
|
||||||
|
//TODO Storing key twice (in parent class and in object pointed to). Once would be enough.
|
||||||
|
CachedBlock(std::unique_ptr<Block> baseBlock, Caching2BlockStore *blockStore);
|
||||||
|
virtual ~CachedBlock();
|
||||||
|
|
||||||
|
const void *data() const override;
|
||||||
|
void write(const void *source, uint64_t offset, uint64_t size) override;
|
||||||
|
void flush() override;
|
||||||
|
|
||||||
|
size_t size() const override;
|
||||||
|
|
||||||
|
private:
|
||||||
|
Caching2BlockStore *_blockStore;
|
||||||
|
std::unique_ptr<Block> _baseBlock;
|
||||||
|
|
||||||
|
DISALLOW_COPY_AND_ASSIGN(CachedBlock);
|
||||||
|
};
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
@ -1,7 +1,11 @@
|
|||||||
#include "Caching2BlockStore.h"
|
#include "Caching2BlockStore.h"
|
||||||
|
#include "CachedBlock.h"
|
||||||
#include "../../interface/Block.h"
|
#include "../../interface/Block.h"
|
||||||
|
|
||||||
|
#include <algorithm>
|
||||||
|
|
||||||
using std::unique_ptr;
|
using std::unique_ptr;
|
||||||
|
using std::make_unique;
|
||||||
|
|
||||||
namespace blockstore {
|
namespace blockstore {
|
||||||
namespace caching2 {
|
namespace caching2 {
|
||||||
@ -15,11 +19,15 @@ unique_ptr<Block> Caching2BlockStore::create(size_t size) {
|
|||||||
// 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),
|
// 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.
|
// 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.
|
// 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);
|
return make_unique<CachedBlock>(_baseBlockStore->create(size), this);
|
||||||
}
|
}
|
||||||
|
|
||||||
unique_ptr<Block> Caching2BlockStore::load(const Key &key) {
|
unique_ptr<Block> Caching2BlockStore::load(const Key &key) {
|
||||||
return _baseBlockStore->load(key);
|
auto block = _cache.pop(key);
|
||||||
|
if (block.get() != nullptr) {
|
||||||
|
return make_unique<CachedBlock>(std::move(block), this);
|
||||||
|
}
|
||||||
|
return make_unique<CachedBlock>(_baseBlockStore->load(key), this);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Caching2BlockStore::remove(std::unique_ptr<Block> block) {
|
void Caching2BlockStore::remove(std::unique_ptr<Block> block) {
|
||||||
@ -30,5 +38,9 @@ uint64_t Caching2BlockStore::numBlocks() const {
|
|||||||
return _baseBlockStore->numBlocks();
|
return _baseBlockStore->numBlocks();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Caching2BlockStore::release(unique_ptr<Block> block) {
|
||||||
|
_cache.push(std::move(block));
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -3,7 +3,7 @@
|
|||||||
#define BLOCKSTORE_IMPLEMENTATIONS_CACHING2_CACHINGBLOCKSTORE_H_
|
#define BLOCKSTORE_IMPLEMENTATIONS_CACHING2_CACHINGBLOCKSTORE_H_
|
||||||
|
|
||||||
#include "../../interface/BlockStore.h"
|
#include "../../interface/BlockStore.h"
|
||||||
#include "CacheEntry.h"
|
#include "Cache.h"
|
||||||
|
|
||||||
namespace blockstore {
|
namespace blockstore {
|
||||||
namespace caching2 {
|
namespace caching2 {
|
||||||
@ -17,10 +17,11 @@ public:
|
|||||||
void remove(std::unique_ptr<Block> block) override;
|
void remove(std::unique_ptr<Block> block) override;
|
||||||
uint64_t numBlocks() const override;
|
uint64_t numBlocks() const override;
|
||||||
|
|
||||||
private:
|
void release(std::unique_ptr<Block> block);
|
||||||
|
|
||||||
|
private:
|
||||||
std::unique_ptr<BlockStore> _baseBlockStore;
|
std::unique_ptr<BlockStore> _baseBlockStore;
|
||||||
std::map<Key, CacheEntry> _cachedBlocks;
|
Cache _cache;
|
||||||
|
|
||||||
DISALLOW_COPY_AND_ASSIGN(Caching2BlockStore);
|
DISALLOW_COPY_AND_ASSIGN(Caching2BlockStore);
|
||||||
};
|
};
|
||||||
|
Loading…
Reference in New Issue
Block a user