2015-03-31 14:02:24 +02:00
|
|
|
#include "CachedBlockRef.h"
|
2015-03-19 11:16:20 +01:00
|
|
|
#include "SynchronizedBlockStore.h"
|
2015-03-31 14:02:24 +02:00
|
|
|
#include <cassert>
|
2015-03-19 11:16:20 +01:00
|
|
|
|
|
|
|
using std::unique_ptr;
|
|
|
|
using std::make_unique;
|
|
|
|
using std::string;
|
2015-03-31 14:02:24 +02:00
|
|
|
using std::mutex;
|
|
|
|
using std::lock_guard;
|
|
|
|
using std::promise;
|
2015-03-19 11:16:20 +01:00
|
|
|
|
|
|
|
namespace blockstore {
|
|
|
|
namespace synchronized {
|
|
|
|
|
|
|
|
SynchronizedBlockStore::SynchronizedBlockStore(unique_ptr<BlockStore> baseBlockStore)
|
2015-03-28 18:44:22 +01:00
|
|
|
: _baseBlockStore(std::move(baseBlockStore)),
|
2015-03-31 14:02:24 +02:00
|
|
|
_openBlocks() {
|
2015-03-28 18:44:22 +01:00
|
|
|
}
|
2015-03-19 11:16:20 +01:00
|
|
|
|
|
|
|
unique_ptr<Block> SynchronizedBlockStore::create(size_t size) {
|
2015-03-31 14:02:24 +02:00
|
|
|
auto block = _baseBlockStore->create(size);
|
|
|
|
lock_guard<mutex> lock(_mutex);
|
|
|
|
return _addOpenBlock(std::move(block));
|
|
|
|
}
|
|
|
|
|
|
|
|
unique_ptr<Block> SynchronizedBlockStore::_addOpenBlock(unique_ptr<Block> block) {
|
|
|
|
auto insertResult = _openBlocks.emplace(block->key(), std::move(block));
|
|
|
|
assert(true == insertResult.second);
|
|
|
|
return make_unique<CachedBlockRef>(insertResult.first->second.getReference(), this);
|
2015-03-19 11:16:20 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
unique_ptr<Block> SynchronizedBlockStore::load(const Key &key) {
|
2015-03-31 14:02:24 +02:00
|
|
|
lock_guard<mutex> lock(_mutex);
|
|
|
|
auto found = _openBlocks.find(key);
|
|
|
|
if (found == _openBlocks.end()) {
|
|
|
|
auto block = _baseBlockStore->load(key);
|
|
|
|
if (block.get() == nullptr) {
|
|
|
|
return nullptr;
|
|
|
|
}
|
|
|
|
return _addOpenBlock(std::move(block));
|
|
|
|
} else {
|
|
|
|
return make_unique<CachedBlockRef>(found->second.getReference(), this);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void SynchronizedBlockStore::release(const Block *block) {
|
|
|
|
lock_guard<mutex> lock(_mutex);
|
|
|
|
Key key = block->key();
|
|
|
|
auto found = _openBlocks.find(key);
|
|
|
|
assert (found != _openBlocks.end());
|
|
|
|
found->second.releaseReference();
|
|
|
|
if (found->second.refCount == 0) {
|
|
|
|
auto foundToRemove = _blocksToRemove.find(key);
|
|
|
|
if (foundToRemove != _blocksToRemove.end()) {
|
|
|
|
foundToRemove->second.set_value(std::move(found->second.block));
|
|
|
|
}
|
|
|
|
_openBlocks.erase(found);
|
|
|
|
}
|
2015-03-19 11:16:20 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
void SynchronizedBlockStore::remove(unique_ptr<Block> block) {
|
2015-03-31 14:02:24 +02:00
|
|
|
auto insertResult = _blocksToRemove.emplace(block->key(), promise<unique_ptr<Block>>());
|
|
|
|
assert(true == insertResult.second);
|
|
|
|
block.reset();
|
|
|
|
|
|
|
|
//Wait for last block user to release it
|
|
|
|
auto blockToRemove = insertResult.first->second.get_future().get();
|
|
|
|
|
|
|
|
_baseBlockStore->remove(std::move(blockToRemove));
|
2015-03-19 11:16:20 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
uint64_t SynchronizedBlockStore::numBlocks() const {
|
|
|
|
return _baseBlockStore->numBlocks();
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
}
|