aboutsummaryrefslogtreecommitdiff
path: root/zenserver/cache/structuredcachestore.cpp
diff options
context:
space:
mode:
authorDan Engelbrecht <[email protected]>2022-05-09 22:03:45 +0200
committerDan Engelbrecht <[email protected]>2022-05-09 22:04:23 +0200
commit5ef2b317ef1965121ab0090d86962d3eea4a357e (patch)
tree6db991bf5abce49c36de9034245d65340fc6ad95 /zenserver/cache/structuredcachestore.cpp
parentMerge pull request #89 from EpicGames/de/namespaces (diff)
downloadzen-5ef2b317ef1965121ab0090d86962d3eea4a357e.tar.xz
zen-5ef2b317ef1965121ab0090d86962d3eea4a357e.zip
Make sure CacheBucket::PutStandaloneCacheValue cleans up the temp file if we fail to move the it into place
Diffstat (limited to 'zenserver/cache/structuredcachestore.cpp')
-rw-r--r--zenserver/cache/structuredcachestore.cpp48
1 files changed, 48 insertions, 0 deletions
diff --git a/zenserver/cache/structuredcachestore.cpp b/zenserver/cache/structuredcachestore.cpp
index 05c80c5bf..411717e61 100644
--- a/zenserver/cache/structuredcachestore.cpp
+++ b/zenserver/cache/structuredcachestore.cpp
@@ -1819,6 +1819,14 @@ ZenCacheDiskLayer::CacheBucket::PutStandaloneCacheValue(const IoHash& HashKey, c
RetryCount--;
} while (RetryCount > 0);
+ // Once we have called MoveTemporaryIntoPlace we no longer will automatically clean up the temp file
+ // as the file handle has already been closed
+ std::filesystem::remove(DataFile.GetPath(), Ec);
+ if (Ec)
+ {
+ ZEN_WARN("Failed to clean up temporary file '{}' for put in '{}', reason '{}'", DataFile.GetPath(), m_BucketDir, Ec.message());
+ }
+
throw std::system_error(Ec, fmt::format("Failed to finalize file '{}' for put in '{}'", DataFilePath.ToUtf8(), m_BucketDir));
}
@@ -2971,6 +2979,46 @@ TEST_CASE("z$.threadedinsert") // * doctest::skip(true))
}
}
+# if ZEN_PLATFORM_WINDOWS
+TEST_CASE("z$.blocked.disklayer.put")
+{
+ // On Windows platform we can't overwrite a standalone file that
+ // is open for read at the same time.
+ // Make sure the retry path runs and we get an exception
+
+ ScopedTemporaryDirectory TempDir;
+
+ GcStorageSize CacheSize;
+
+ const auto CreateCacheValue = [](size_t Size) -> CbObject {
+ std::vector<uint8_t> Buf;
+ Buf.resize(Size);
+
+ CbObjectWriter Writer;
+ Writer.AddBinary("Binary"sv, Buf.data(), Buf.size());
+ return Writer.Save();
+ };
+
+ CasGc Gc;
+ ZenCacheNamespace Zcs(Gc, TempDir.Path() / "cache");
+
+ CbObject CacheValue = CreateCacheValue(64 * 1024 + 64);
+
+ IoBuffer Buffer = CacheValue.GetBuffer().AsIoBuffer();
+ Buffer.SetContentType(ZenContentType::kCbObject);
+
+ size_t Key = Buffer.Size();
+ IoHash HashKey = IoHash::HashBuffer(&Key, sizeof(uint32_t));
+ Zcs.Put("test_bucket", HashKey, {.Value = Buffer});
+
+ ZenCacheValue BufferGet;
+ CHECK(Zcs.Get("test_bucket", HashKey, BufferGet));
+
+ MemoryView ValueView = BufferGet.Value.GetView();
+ CHECK_THROWS(Zcs.Put("test_bucket", HashKey, {.Value = Buffer}));
+}
+# endif
+
#endif
void