Caching blocks works
This commit is contained in:
parent
332f6901ef
commit
b185729113
@ -19,31 +19,23 @@ Cache::~Cache() {
|
|||||||
|
|
||||||
unique_ptr<Block> Cache::pop(const Key &key) {
|
unique_ptr<Block> Cache::pop(const Key &key) {
|
||||||
lock_guard<mutex> lock(_mutex);
|
lock_guard<mutex> lock(_mutex);
|
||||||
auto found = _cachedBlocks.find(key);
|
auto found = _cachedBlocks.pop(key);
|
||||||
if (found == _cachedBlocks.end()) {
|
if (found.get() == nullptr) {
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
auto block = found->second.releaseBlock();
|
auto block = found->releaseBlock();
|
||||||
_cachedBlocks.erase(found);
|
|
||||||
return block;
|
return block;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Cache::push(unique_ptr<Block> block) {
|
void Cache::push(unique_ptr<Block> block) {
|
||||||
lock_guard<mutex> lock(_mutex);
|
lock_guard<mutex> lock(_mutex);
|
||||||
if (_cachedBlocks.size() > MAX_ENTRIES) {
|
assert(_cachedBlocks.size() <= MAX_ENTRIES);
|
||||||
deleteOldestEntry();
|
if (_cachedBlocks.size() == MAX_ENTRIES) {
|
||||||
|
_cachedBlocks.pop();
|
||||||
assert(_cachedBlocks.size() == MAX_ENTRIES-1);
|
assert(_cachedBlocks.size() == MAX_ENTRIES-1);
|
||||||
}
|
}
|
||||||
Key key = block->key();
|
Key key = block->key();
|
||||||
_cachedBlocks.emplace(key, std::move(block));
|
_cachedBlocks.push(key, make_unique<CacheEntry>(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);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -4,12 +4,16 @@
|
|||||||
|
|
||||||
#include "../../interface/Block.h"
|
#include "../../interface/Block.h"
|
||||||
#include "CacheEntry.h"
|
#include "CacheEntry.h"
|
||||||
|
#include "QueueMap.h"
|
||||||
#include <memory>
|
#include <memory>
|
||||||
#include <mutex>
|
#include <mutex>
|
||||||
|
|
||||||
namespace blockstore {
|
namespace blockstore {
|
||||||
namespace caching2 {
|
namespace caching2 {
|
||||||
|
|
||||||
|
//TODO Test
|
||||||
|
//TODO Also throw blocks out after a timeout
|
||||||
|
|
||||||
class Cache {
|
class Cache {
|
||||||
public:
|
public:
|
||||||
static constexpr uint32_t MAX_ENTRIES = 1000;
|
static constexpr uint32_t MAX_ENTRIES = 1000;
|
||||||
@ -22,9 +26,7 @@ public:
|
|||||||
|
|
||||||
private:
|
private:
|
||||||
mutable std::mutex _mutex;
|
mutable std::mutex _mutex;
|
||||||
std::map<Key, CacheEntry> _cachedBlocks;
|
QueueMap<Key, CacheEntry> _cachedBlocks;
|
||||||
|
|
||||||
void deleteOldestEntry();
|
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -25,9 +25,18 @@ public:
|
|||||||
return std::move(_block);
|
return std::move(_block);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void setNextEntry(const CacheEntry *entry) {
|
||||||
|
_nextEntry = entry;
|
||||||
|
}
|
||||||
|
|
||||||
|
const CacheEntry *nextEntry() {
|
||||||
|
return _nextEntry;
|
||||||
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
time_t _lastAccess;
|
time_t _lastAccess;
|
||||||
std::unique_ptr<Block> _block;
|
std::unique_ptr<Block> _block;
|
||||||
|
const CacheEntry *_nextEntry;
|
||||||
|
|
||||||
DISALLOW_COPY_AND_ASSIGN(CacheEntry);
|
DISALLOW_COPY_AND_ASSIGN(CacheEntry);
|
||||||
};
|
};
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
#include "CachedBlock.h"
|
#include "CachedBlock.h"
|
||||||
#include "Caching2BlockStore.h"
|
#include "Caching2BlockStore.h"
|
||||||
|
|
||||||
|
using std::unique_ptr;
|
||||||
using std::make_unique;
|
using std::make_unique;
|
||||||
|
|
||||||
namespace blockstore {
|
namespace blockstore {
|
||||||
@ -13,8 +14,10 @@ CachedBlock::CachedBlock(std::unique_ptr<Block> baseBlock, Caching2BlockStore *b
|
|||||||
}
|
}
|
||||||
|
|
||||||
CachedBlock::~CachedBlock() {
|
CachedBlock::~CachedBlock() {
|
||||||
|
if (_baseBlock.get() != nullptr) {
|
||||||
_blockStore->release(std::move(_baseBlock));
|
_blockStore->release(std::move(_baseBlock));
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
const void *CachedBlock::data() const {
|
const void *CachedBlock::data() const {
|
||||||
return _baseBlock->data();
|
return _baseBlock->data();
|
||||||
@ -32,5 +35,9 @@ size_t CachedBlock::size() const {
|
|||||||
return _baseBlock->size();
|
return _baseBlock->size();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
unique_ptr<Block> CachedBlock::releaseBlock() {
|
||||||
|
return std::move(_baseBlock);
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -23,6 +23,9 @@ public:
|
|||||||
|
|
||||||
size_t size() const override;
|
size_t size() const override;
|
||||||
|
|
||||||
|
bool alreadyExistsInBaseStore();
|
||||||
|
std::unique_ptr<Block> releaseBlock();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
Caching2BlockStore *_blockStore;
|
Caching2BlockStore *_blockStore;
|
||||||
std::unique_ptr<Block> _baseBlock;
|
std::unique_ptr<Block> _baseBlock;
|
||||||
|
@ -3,9 +3,11 @@
|
|||||||
#include "../../interface/Block.h"
|
#include "../../interface/Block.h"
|
||||||
|
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
|
#include <messmer/cpp-utils/pointer.h>
|
||||||
|
|
||||||
using std::unique_ptr;
|
using std::unique_ptr;
|
||||||
using std::make_unique;
|
using std::make_unique;
|
||||||
|
using cpputils::dynamic_pointer_move;
|
||||||
|
|
||||||
namespace blockstore {
|
namespace blockstore {
|
||||||
namespace caching2 {
|
namespace caching2 {
|
||||||
@ -27,11 +29,15 @@ unique_ptr<Block> Caching2BlockStore::load(const Key &key) {
|
|||||||
if (block.get() != nullptr) {
|
if (block.get() != nullptr) {
|
||||||
return make_unique<CachedBlock>(std::move(block), this);
|
return make_unique<CachedBlock>(std::move(block), this);
|
||||||
}
|
}
|
||||||
return make_unique<CachedBlock>(_baseBlockStore->load(key), this);
|
block = _baseBlockStore->load(key);
|
||||||
|
if (block.get() == nullptr) {
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
return make_unique<CachedBlock>(std::move(block), this);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Caching2BlockStore::remove(std::unique_ptr<Block> block) {
|
void Caching2BlockStore::remove(std::unique_ptr<Block> block) {
|
||||||
return _baseBlockStore->remove(std::move(block));
|
return _baseBlockStore->remove(std::move(dynamic_pointer_move<CachedBlock>(block)->releaseBlock()));
|
||||||
}
|
}
|
||||||
|
|
||||||
uint64_t Caching2BlockStore::numBlocks() const {
|
uint64_t Caching2BlockStore::numBlocks() const {
|
||||||
|
1
implementations/caching2/QueueMap.cpp
Normal file
1
implementations/caching2/QueueMap.cpp
Normal file
@ -0,0 +1 @@
|
|||||||
|
#include "QueueMap.h"
|
68
implementations/caching2/QueueMap.h
Normal file
68
implementations/caching2/QueueMap.h
Normal file
@ -0,0 +1,68 @@
|
|||||||
|
#pragma once
|
||||||
|
#ifndef MESSMER_BLOCKSTORE_IMPLEMENTATIONS_CACHING2_MAP_H_
|
||||||
|
#define MESSMER_BLOCKSTORE_IMPLEMENTATIONS_CACHING2_MAP_H_
|
||||||
|
|
||||||
|
#include <memory>
|
||||||
|
#include <map>
|
||||||
|
|
||||||
|
namespace blockstore {
|
||||||
|
namespace caching2 {
|
||||||
|
|
||||||
|
//TODO Test
|
||||||
|
template<class Key, class Value>
|
||||||
|
class QueueMap {
|
||||||
|
public:
|
||||||
|
QueueMap(): _entries(), _sentinel(Key(), nullptr, &_sentinel, &_sentinel) {
|
||||||
|
}
|
||||||
|
virtual ~QueueMap() {}
|
||||||
|
|
||||||
|
void push(const Key &key, std::unique_ptr<Value> value) {
|
||||||
|
auto newEntry = std::make_unique<Entry>(key, std::move(value), _sentinel.prev, &_sentinel);
|
||||||
|
_sentinel.prev->next = newEntry.get();
|
||||||
|
_sentinel.prev = newEntry.get();
|
||||||
|
auto insertResult = _entries.emplace(key, std::move(newEntry));
|
||||||
|
assert(insertResult.second == true);
|
||||||
|
}
|
||||||
|
|
||||||
|
std::unique_ptr<Value> pop(const Key &key) {
|
||||||
|
auto found = _entries.find(key);
|
||||||
|
if (found == _entries.end()) {
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
_removeFromQueue(found->second.get());
|
||||||
|
auto value = std::move(found->second->value);
|
||||||
|
_entries.erase(found);
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::unique_ptr<Value> pop() {
|
||||||
|
return pop(_sentinel.next->key);
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32_t size() {
|
||||||
|
return _entries.size();
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
struct Entry {
|
||||||
|
Entry(const Key &key_, std::unique_ptr<Value> value_, Entry *prev_, Entry *next_): key(key_), value(std::move(value_)), prev(prev_), next(next_) {}
|
||||||
|
Key key;
|
||||||
|
std::unique_ptr<Value> value;
|
||||||
|
Entry *prev;
|
||||||
|
Entry *next;
|
||||||
|
};
|
||||||
|
|
||||||
|
void _removeFromQueue(Entry *entry) {
|
||||||
|
entry->prev->next = entry->next;
|
||||||
|
entry->next->prev = entry->prev;
|
||||||
|
}
|
||||||
|
|
||||||
|
//TODO Double indirection unique_ptr<Entry> and Entry has unique_ptr<Value>. Necessary?
|
||||||
|
std::map<Key, std::unique_ptr<Entry>> _entries;
|
||||||
|
Entry _sentinel;
|
||||||
|
};
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
@ -12,6 +12,7 @@ namespace blockstore {
|
|||||||
template<int SIZE>
|
template<int SIZE>
|
||||||
class FixedSizeData {
|
class FixedSizeData {
|
||||||
public:
|
public:
|
||||||
|
FixedSizeData() {}
|
||||||
//Non-virtual destructor because we want objects to be small
|
//Non-virtual destructor because we want objects to be small
|
||||||
~FixedSizeData() {}
|
~FixedSizeData() {}
|
||||||
|
|
||||||
@ -29,8 +30,6 @@ public:
|
|||||||
const unsigned char *data() const;
|
const unsigned char *data() const;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
FixedSizeData() {}
|
|
||||||
|
|
||||||
static CryptoPP::AutoSeededRandomPool &RandomPool();
|
static CryptoPP::AutoSeededRandomPool &RandomPool();
|
||||||
|
|
||||||
unsigned char _data[BINARY_LENGTH];
|
unsigned char _data[BINARY_LENGTH];
|
||||||
|
Loading…
Reference in New Issue
Block a user