diff options
Diffstat (limited to 'zenserver/cache/structuredcachestore.cpp')
| -rw-r--r-- | zenserver/cache/structuredcachestore.cpp | 73 |
1 files changed, 41 insertions, 32 deletions
diff --git a/zenserver/cache/structuredcachestore.cpp b/zenserver/cache/structuredcachestore.cpp index 163a3f2f2..77307bc2d 100644 --- a/zenserver/cache/structuredcachestore.cpp +++ b/zenserver/cache/structuredcachestore.cpp @@ -1765,27 +1765,41 @@ ZenCacheDiskLayer::CacheBucket::PutStandaloneCacheValue(const IoHash& HashKey, c m_TotalSize.fetch_add(Loc.Size(), std::memory_order::relaxed); }; - std::error_code Ec; - BasicFile DataFile; + auto WritePayload = [&](BasicFile& File, const IoBuffer& Payload) { + std::error_code Ec; + File.WriteAll(Payload, Ec); + if (Ec) + { + File.Close(); + std::error_code RemoveEc; + std::filesystem::remove(FsPath, RemoveEc); + if (RemoveEc) + { + ZEN_WARN("Failed cleaning up file '{}' after failed write for put in '{}', reason '{}'", + FsPath.string(), + m_BucketDir, + RemoveEc.message()); + } + + throw std::system_error(Ec, + fmt::format("Failed to write payload ({} bytes) to file '{}' for put in '{}'", + NiceBytes(Payload.Size()), + FsPath, + m_BucketDir)); + } + File.Close(); + }; // Happy path - directory structure exists and nobody is busy reading the file { + std::error_code Ec; + BasicFile DataFile; + RwLock::ExclusiveLockScope ValueLock(LockForHash(HashKey)); DataFile.Open(FsPath, BasicFile::Mode::kTruncate, Ec); if (!Ec) { - DataFile.WriteAll(Value.Value, Ec); - if (Ec) - { - if (Ec) - { - throw std::system_error(Ec, - fmt::format("Failed to write payload ({} bytes) to file '{}' in '{}'", - NiceBytes(Value.Value.Size()), - FsPath, - m_BucketDir)); - } - } + WritePayload(DataFile, Value.Value); ValueLock.ReleaseNow(); UpdateIndex(); return; @@ -1795,7 +1809,7 @@ ZenCacheDiskLayer::CacheBucket::PutStandaloneCacheValue(const IoHash& HashKey, c std::filesystem::path ParentPath = FsPath.parent_path(); if (!std::filesystem::is_directory(ParentPath)) { - Ec.clear(); + std::error_code Ec; std::filesystem::create_directories(ParentPath, Ec); if (Ec) { @@ -1805,41 +1819,36 @@ ZenCacheDiskLayer::CacheBucket::PutStandaloneCacheValue(const IoHash& HashKey, c } } - // We retry to open the file since it can be held open for read - // This happens if the server gets a Get request for the file or + // We retry to open the file since it can be held open for read. + // This happens if the server processes a Get request for the file or // if we are busy sending the file upstream - int RetryCount = 3; + int RetryCount = 3; + std::error_code Ec; do { + BasicFile DataFile; Ec.clear(); + RwLock::ExclusiveLockScope ValueLock(LockForHash(HashKey)); DataFile.Open(FsPath, BasicFile::Mode::kTruncate, Ec); if (!Ec) { - DataFile.WriteAll(Value.Value, Ec); - if (Ec) - { - if (Ec) - { - throw std::system_error(Ec, - fmt::format("Failed to write payload ({} bytes) to file '{}' in '{}'", - NiceBytes(Value.Value.Size()), - FsPath, - m_BucketDir)); - } - } + WritePayload(DataFile, Value.Value); ValueLock.ReleaseNow(); UpdateIndex(); return; } - ZEN_INFO("Failed writing opening file '{}' for writing, pausing and retrying, reason '{}'", FsPath.string(), Ec.message()); + ZEN_INFO("Failed writing opening file '{}' for writing for put in '{}', pausing and retrying, reason '{}'", + FsPath.string(), + m_BucketDir, + Ec.message()); ValueLock.ReleaseNow(); // Semi arbitrary back-off zen::Sleep(200 * (4 - RetryCount)); // Sleep at most for a total of 2 seconds } while (RetryCount--); - throw std::system_error(Ec, fmt::format("Failed to finalize file '{}' in '{}'", DataFilePath.ToUtf8(), m_BucketDir)); + throw std::system_error(Ec, fmt::format("Failed to finalize file '{}' for put in '{}'", DataFilePath.ToUtf8(), m_BucketDir)); } void |