diff options
| author | Stefan Boberg <[email protected]> | 2021-05-27 18:14:44 +0200 |
|---|---|---|
| committer | Stefan Boberg <[email protected]> | 2021-05-27 18:14:44 +0200 |
| commit | b335dd7cccd20a539e165145e7e89b2b2e185ab4 (patch) | |
| tree | 7f02d23892e8d7dc4c9ac37e9eda58095b61bf66 | |
| parent | Added EnableMesh setting, fixed lifetime management (diff) | |
| download | zen-b335dd7cccd20a539e165145e7e89b2b2e185ab4.tar.xz zen-b335dd7cccd20a539e165145e7e89b2b2e185ab4.zip | |
Added locks to protect against races in parallel oplog updates
| -rw-r--r-- | zenserver/projectstore.cpp | 21 |
1 files changed, 21 insertions, 0 deletions
diff --git a/zenserver/projectstore.cpp b/zenserver/projectstore.cpp index c94a8fe35..6cf5dc161 100644 --- a/zenserver/projectstore.cpp +++ b/zenserver/projectstore.cpp @@ -269,13 +269,19 @@ ProjectStore::Oplog::ReplayLog() IoBuffer ProjectStore::Oplog::FindChunk(Oid ChunkId) { + RwLock::SharedLockScope _(m_OplogLock); + if (auto ChunkIt = m_ChunkMap.find(ChunkId); ChunkIt != m_ChunkMap.end()) { + _.ReleaseNow(); + return m_CasStore.FindChunk(ChunkIt->second); } if (auto FileIt = m_FileMap.find(ChunkId); FileIt != m_FileMap.end()) { + _.ReleaseNow(); + std::filesystem::path FilePath = m_OuterProject->RootDir / FileIt->second.ServerPath; return IoBufferBuilder::MakeFromFile(FilePath.native().c_str()); @@ -283,6 +289,8 @@ ProjectStore::Oplog::FindChunk(Oid ChunkId) if (auto MetaIt = m_MetaMap.find(ChunkId); MetaIt != m_MetaMap.end()) { + _.ReleaseNow(); + return m_CasStore.FindChunk(MetaIt->second); } @@ -292,6 +300,8 @@ ProjectStore::Oplog::FindChunk(Oid ChunkId) void ProjectStore::Oplog::IterateFileMap(std::function<void(const Oid&, const std::string_view&)>&& Fn) { + RwLock::SharedLockScope _(m_OplogLock); + for (const auto& Kv : m_FileMap) { Fn(Kv.first, Kv.second.ClientPath); @@ -301,6 +311,8 @@ ProjectStore::Oplog::IterateFileMap(std::function<void(const Oid&, const std::st bool ProjectStore::Oplog::AddFileMapping(Oid FileId, IoHash Hash, std::string_view ServerPath, std::string_view ClientPath) { + // NOTE: Caller must hold an exclusive lock on m_OplogLock + if (ServerPath.empty() || ClientPath.empty()) { return false; @@ -328,12 +340,16 @@ ProjectStore::Oplog::AddFileMapping(Oid FileId, IoHash Hash, std::string_view Se void ProjectStore::Oplog::AddChunkMapping(Oid ChunkId, IoHash Hash) { + // NOTE: Caller must hold an exclusive lock on m_OplogLock + m_ChunkMap.emplace(ChunkId, Hash); } void ProjectStore::Oplog::AddMetaMapping(Oid ChunkId, IoHash Hash) { + // NOTE: Caller must hold an exclusive lock on m_OplogLock + m_MetaMap.emplace(ChunkId, Hash); } @@ -342,6 +358,11 @@ ProjectStore::Oplog::RegisterOplogEntry(CbObject Core, const OplogEntry& OpEntry { ZEN_UNUSED(TypeOfUpdate); + // For now we're assuming the update is all in-memory so we can hold an exclusive lock without causing + // too many problems. Longer term we'll probably want to ensure we can do concurrent updates however + + RwLock::ExclusiveLockScope _(m_OplogLock); + using namespace std::literals; // Update chunk id maps |