Files
UnrealEngine/Engine/Source/Runtime/StorageServerClient/Private/Cache/CacheStorageMmap.cpp
2025-05-18 13:04:45 +08:00

146 lines
4.1 KiB
C++

// Copyright Epic Games, Inc. All Rights Reserved.
#include "CacheStorageMmap.h"
#if !UE_BUILD_SHIPPING
#include "HAL/PlatformFileManager.h"
#include "GenericPlatform/GenericPlatformFile.h"
namespace StorageServer
{
FCacheStorageMmap::FCacheStorageMmap(const TCHAR* FileNamePrefix, const uint64 FileSizeTmp)
{
if (!ensure(FPlatformProperties::SupportsMemoryMappedFiles()))
{
return;
}
const TArray<TTuple<FString, uint64>> BackingFileNames = GetBackingFileNames(FileNamePrefix, FileSizeTmp);
BackingFiles.SetNum(BackingFileNames.Num());
TotalSize = 0;
IPlatformFile& PlatformFile = FPlatformFileManager::Get().GetPlatformFile();
for (int32 i = 0; i < BackingFiles.Num(); ++i)
{
const FString& FileName = BackingFileNames[i].Key;
const uint64 DesiredFileSize = BackingFileNames[i].Value;
FBackingFile& BackingFile = BackingFiles[i];
IFileHandle* PlainFileHandle = PlatformFile.OpenWrite(*FileName, true, true);
if (!ensureAlwaysMsgf(PlainFileHandle, TEXT("FCacheStorageMmap failed to open cache storage file '%s'"), *FileName))
{
return;
}
if (PlainFileHandle->Size() != DesiredFileSize)
{
// TODO add truncate to IMappedFileHandle?
PlainFileHandle->Truncate(DesiredFileSize);
bNewlyCreatedStorage = true;
}
const uint64 ActualFileSize = PlainFileHandle->Size();
delete PlainFileHandle;
FOpenMappedResult Result = PlatformFile.OpenMappedEx(*FileName, IPlatformFile::EOpenReadFlags::AllowWrite);
if (!ensureAlwaysMsgf(!Result.HasError(), TEXT("FCacheStorageMmap OpenMappedEx failed to open '%s' due to '%s'"), *FileName, *Result.GetError().GetMessage()))
{
return;
}
BackingFile.FileHandle = Result.StealValue();
BackingFile.FileRegion = TUniquePtr<IMappedFileRegion>(BackingFile.FileHandle->MapRegion(0, ActualFileSize, EMappedFileFlags::EFileWritable));
BackingFile.MapPtr = (uint8*)BackingFile.FileRegion->GetMappedPtr(); // TODO add rw ptr to IMappedFileRegion
BackingFile.MapSize = BackingFile.FileRegion->GetMappedSize();
TotalSize += BackingFile.MapSize;
}
}
FCacheStorageMmap::~FCacheStorageMmap()
{
BackingFiles.Reset();
TotalSize = 0;
}
void FCacheStorageMmap::Flush()
{
}
void FCacheStorageMmap::Invalidate(const uint64 Offset, const uint64 Size)
{
}
FIoBuffer FCacheStorageMmap::Read(const uint64 Offset, const uint64 ReadSize, TOptional<FIoBuffer> OptDestination)
{
if (!IsValidRange(Offset, ReadSize))
{
return FIoBuffer();
}
uint32 IndexA, IndexB;
uint64 OffsetA, SizeA, OffsetB, SizeB;
if (!GetBackingIntervals(Offset, ReadSize, IndexA, OffsetA, SizeA, IndexB, OffsetB, SizeB))
{
return FIoBuffer();
}
if (SizeA > 0 && SizeB == 0)
{
if (OptDestination.IsSet() && OptDestination->GetSize() >= SizeA)
{
OptDestination->SetSize(SizeA);
FMemory::Memcpy(OptDestination->GetData(), BackingFiles[IndexA].MapPtr + OffsetA, SizeA);
return OptDestination.GetValue();
}
else
{
return FIoBuffer(FIoBuffer::Wrap, BackingFiles[IndexA].MapPtr + OffsetA, SizeA);
}
}
if (SizeA > 0 && SizeB > 0)
{
FIoBuffer Result = (OptDestination.IsSet() && OptDestination->GetSize() >= SizeA + SizeB) ? OptDestination.GetValue() : FIoBuffer(SizeA + SizeB);
Result.SetSize(SizeA + SizeB);
FMemory::Memcpy(Result.GetData(), BackingFiles[IndexA].MapPtr + OffsetA, SizeA);
FMemory::Memcpy(Result.GetData() + SizeA, BackingFiles[IndexB].MapPtr + OffsetB, SizeB);
return Result;
}
return FIoBuffer();
}
void FCacheStorageMmap::WriteAsync(const uint64 Offset, const void* Buffer, const uint64 WriteSize)
{
if (!IsValidRange(Offset, WriteSize))
{
return;
}
uint32 IndexA, IndexB;
uint64 OffsetA, SizeA, OffsetB, SizeB;
if (!GetBackingIntervals(Offset, WriteSize, IndexA, OffsetA, SizeA, IndexB, OffsetB, SizeB))
{
return;
}
if (SizeA > 0 && SizeB == 0)
{
FMemory::Memcpy(BackingFiles[IndexA].MapPtr + OffsetA, Buffer, SizeA);
}
if (SizeA > 0 && SizeB > 0)
{
FMemory::Memcpy(BackingFiles[IndexA].MapPtr + OffsetA, Buffer, SizeA);
FMemory::Memcpy(BackingFiles[IndexB].MapPtr + OffsetB, (const uint8*)Buffer + SizeA, SizeB);
}
}
}
#endif