diff --git a/implementations/caching/cache/QueueMap.h b/implementations/caching/cache/QueueMap.h index 6d36a13c..1f3fd56d 100644 --- a/implementations/caching/cache/QueueMap.h +++ b/implementations/caching/cache/QueueMap.h @@ -26,7 +26,9 @@ public: void push(const Key &key, Value value) { auto newEntry = _entries.emplace(std::piecewise_construct, std::forward_as_tuple(key), std::forward_as_tuple(_sentinel.prev, &_sentinel)); - ASSERT(newEntry.second == true, "There is already an element with this key"); + if (!newEntry.second) { + throw std::logic_error("There is already an element with this key"); + } newEntry.first->second.init(&newEntry.first->first, std::move(value)); //The following is ok, because std::unordered_map never invalidates pointers to its entries _sentinel.prev->next = &newEntry.first->second; diff --git a/implementations/ondisk/OnDiskBlockStore.cpp b/implementations/ondisk/OnDiskBlockStore.cpp index 53adff6a..a6e32168 100644 --- a/implementations/ondisk/OnDiskBlockStore.cpp +++ b/implementations/ondisk/OnDiskBlockStore.cpp @@ -15,6 +15,8 @@ namespace ondisk { OnDiskBlockStore::OnDiskBlockStore(const boost::filesystem::path &rootdir) : _rootdir(rootdir) {} +//TODO Do I have to lock tryCreate/remove and/or load? Or does ParallelAccessBlockStore take care of that? + optional> OnDiskBlockStore::tryCreate(const Key &key, Data data) { //TODO Easier implementation? This is only so complicated because of the cast OnDiskBlock -> Block auto result = std::move(OnDiskBlock::CreateOnDisk(_rootdir, key, std::move(data))); diff --git a/implementations/testfake/FakeBlockStore.cpp b/implementations/testfake/FakeBlockStore.cpp index e03f7754..89604f96 100644 --- a/implementations/testfake/FakeBlockStore.cpp +++ b/implementations/testfake/FakeBlockStore.cpp @@ -19,6 +19,7 @@ FakeBlockStore::FakeBlockStore() : _blocks(), _used_dataregions_for_blocks() {} optional> FakeBlockStore::tryCreate(const Key &key, Data data) { + std::unique_lock lock(_mutex); auto insert_result = _blocks.emplace(key.ToString(), std::move(data)); if (!insert_result.second) { @@ -26,10 +27,15 @@ optional> FakeBlockStore::tryCreate(const Key &key, Data data) } //Return a copy of the stored data - return load(key); + return _load(key); } optional> FakeBlockStore::load(const Key &key) { + std::unique_lock lock(_mutex); + return _load(key); +} + +optional> FakeBlockStore::_load(const Key &key) { //Return a copy of the stored data string key_string = key.ToString(); try { @@ -42,6 +48,7 @@ optional> FakeBlockStore::load(const Key &key) { void FakeBlockStore::remove(unique_ref block) { Key key = block->key(); cpputils::destruct(std::move(block)); + std::unique_lock lock(_mutex); int numRemoved = _blocks.erase(key.ToString()); ASSERT(numRemoved == 1, "Block not found"); } @@ -53,6 +60,7 @@ unique_ref FakeBlockStore::makeFakeBlockFromData(const Key &key, const Da } void FakeBlockStore::updateData(const Key &key, const Data &data) { + std::unique_lock lock(_mutex); auto found = _blocks.find(key.ToString()); if (found == _blocks.end()) { auto insertResult = _blocks.emplace(key.ToString(), data.copy()); @@ -65,6 +73,7 @@ void FakeBlockStore::updateData(const Key &key, const Data &data) { } uint64_t FakeBlockStore::numBlocks() const { + std::unique_lock lock(_mutex); return _blocks.size(); } diff --git a/implementations/testfake/FakeBlockStore.h b/implementations/testfake/FakeBlockStore.h index fc04696b..b0627d4d 100644 --- a/implementations/testfake/FakeBlockStore.h +++ b/implementations/testfake/FakeBlockStore.h @@ -48,7 +48,10 @@ private: //We want to avoid this for the reasons mentioned above (overflow data). std::vector> _used_dataregions_for_blocks; + mutable std::mutex _mutex; + cpputils::unique_ref makeFakeBlockFromData(const Key &key, const cpputils::Data &data, bool dirty); + boost::optional> _load(const Key &key); DISALLOW_COPY_AND_ASSIGN(FakeBlockStore); };