aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDan Engelbrecht <[email protected]>2022-05-06 13:23:52 +0200
committerDan Engelbrecht <[email protected]>2022-05-06 13:23:52 +0200
commit1e279eb7700e7bfb35282cbc8acdaec3cb355e23 (patch)
treee1334ea03646e80dbdaceaf318f39f788bf349c4
parentFix standalone file lock in CacheBucket (diff)
downloadzen-1e279eb7700e7bfb35282cbc8acdaec3cb355e23.tar.xz
zen-1e279eb7700e7bfb35282cbc8acdaec3cb355e23.zip
clean up file on failed write
-rw-r--r--zenserver/cache/structuredcachestore.cpp73
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