Files
UnrealEngineUWP/Engine/Source/Developer/Virtualization/Private/VirtualizationFileBackend.cpp

257 lines
8.0 KiB
C++
Raw Normal View History

// Copyright Epic Games, Inc. All Rights Reserved.
#include "VirtualizationFileBackend.h"
#include "HAL/FileManager.h"
A quick hardening pass over the file system backend for Mirage. #rb Per.Larsson #rnx #preflight 61408a979dc6c8000148d0cf ### Misc - Updated the documentation for setting up a file system backend and added descriptions to the backend's members. - Renamed the member 'Name' to 'DebugName' to bring it in line with the other backends (still a candidate to be moved to the base class) ### Reading payloads from disk - Added the ability to retry opening file handles for read if they fail. This can commonly occur when multiple threads or processes are both pulling and pushing to the same root directory. -- By default we will retry to open the file handle up to 10 times, waiting for 100ms between each attempt. The user can configure the number of retries and the length of the pause between each attempt via the config files. -- Each failed attempt at opening the file handle will result in a warning being logged, so if the user is stalled for a long length of time while we rety over and over they are at least made aware of the cause. ### Writing payloads to disk - When attempting to write a payload to disk, we will now write to a temp file in the project save directory using a randomly generated name. Once the payload has been fully saved to disk it will then be moved to the correct location. Although not perfect this will reduce the potential for writing corrupted data to a location where it might be read in the future. -- We do attempt to clean up the temp file if the write fails but we do not print error messages if the delete fails as it is considered an optional bonus rather than an essential feature. - Previously we would only log an error if we failed to open a file handle for writing the payload to disk. Now we also log an error if the handle is opened but the actual writes fail. [CL 17550126 by paul chipchase in ue5-main branch]
2021-09-17 06:02:48 -04:00
#include "HAL/PlatformProcess.h"
#include "Misc/Parse.h"
#include "Misc/Paths.h"
#include "Virtualization/VirtualizationManager.h"
#include "VirtualizationUtilities.h"
namespace UE::Virtualization
{
Improve error handling and logging in the file and jupiter Mirage backends. #rb Per.Larsson #rnx #preflight 60f9212d1f926d0001d41223 * VirtualizationJupiterBackend - When pulling a payload we should assume that a 400 error response when trying to GET the payload header means that the payload is not in Jupiter. -- Not being able to find the payload should not log an error, instead we can make a note of it in the verbose log (similar to the file system backend) * VirtualizationFileBackend - Moved the formatting of system errors to it's own function. - Log the system error when failing to write a payload during a push as well as a pull. - We now check that the FileArchive wrote correctly to disk and delete the output file and fail the push if it did not. -- A future piece of work will change the logic to write to a tmp file at the root of the file store and them move the file to the final location to cut down on the potential of leaving corrupted files around (similar to the process when we save packages) * Perforce - The FDownloadFile command now takes an optional parameter EVerbosity that can allow the caller to choose the level of logging output that the command will generate. - The source control backend for Mirage now opts to supress the logging of the full perforce command when we are pulling payloads as we can generate many hundreds or thousands of requests and the info is not useful to users. -- We continue to log the command when validating the depot as this is the most likely command to fail so having the info in the log may prove useful. [CL 16921815 by paul chipchase in ue5-main branch]
2021-07-22 05:43:20 -04:00
/**
* Fill in the given string builder with the human readable message of the current system
* code, followed by the code value itself.
* In the system value is currently 0, then we assume that it was cleared before this was
* able to be called and write that the error is unknown instead of assuming that the
* operation was a success.
*/
void GetFormattedSystemError(FStringBuilderBase& SystemErrorMessage)
{
SystemErrorMessage.Reset();
const uint32 SystemError = FPlatformMisc::GetLastError();
// If we have a system error we can give a more informative error message but don't output it if the error is zero as
// this can lead to very confusing error messages.
if (SystemError != 0)
{
TCHAR SystemErrorMsg[MAX_SPRINTF] = { 0 };
FPlatformMisc::GetSystemErrorMessage(SystemErrorMsg, sizeof(SystemErrorMsg), SystemError);
SystemErrorMessage.Appendf(TEXT("'%s' (%d)"), SystemErrorMsg, SystemError);
}
else
{
SystemErrorMessage << TEXT("'unknown reason' (0)");
}
}
FFileSystemBackend::FFileSystemBackend(FStringView ConfigName)
: IVirtualizationBackend(EOperations::Both)
{
A quick hardening pass over the file system backend for Mirage. #rb Per.Larsson #rnx #preflight 61408a979dc6c8000148d0cf ### Misc - Updated the documentation for setting up a file system backend and added descriptions to the backend's members. - Renamed the member 'Name' to 'DebugName' to bring it in line with the other backends (still a candidate to be moved to the base class) ### Reading payloads from disk - Added the ability to retry opening file handles for read if they fail. This can commonly occur when multiple threads or processes are both pulling and pushing to the same root directory. -- By default we will retry to open the file handle up to 10 times, waiting for 100ms between each attempt. The user can configure the number of retries and the length of the pause between each attempt via the config files. -- Each failed attempt at opening the file handle will result in a warning being logged, so if the user is stalled for a long length of time while we rety over and over they are at least made aware of the cause. ### Writing payloads to disk - When attempting to write a payload to disk, we will now write to a temp file in the project save directory using a randomly generated name. Once the payload has been fully saved to disk it will then be moved to the correct location. Although not perfect this will reduce the potential for writing corrupted data to a location where it might be read in the future. -- We do attempt to clean up the temp file if the write fails but we do not print error messages if the delete fails as it is considered an optional bonus rather than an essential feature. - Previously we would only log an error if we failed to open a file handle for writing the payload to disk. Now we also log an error if the handle is opened but the actual writes fail. [CL 17550126 by paul chipchase in ue5-main branch]
2021-09-17 06:02:48 -04:00
DebugName = WriteToString<256>(TEXT("FFileSystemBackend - "), ConfigName).ToString();
}
bool FFileSystemBackend::Initialize(const FString& ConfigEntry)
{
if (!FParse::Value(*ConfigEntry, TEXT("Path="), RootDirectory))
{
UE_LOG(LogVirtualization, Error, TEXT("[%s] 'Path=' not found in the config file"), *GetDebugString());
return false;
}
FPaths::NormalizeDirectoryName(RootDirectory);
if (RootDirectory.IsEmpty())
{
UE_LOG(LogVirtualization, Error, TEXT("[%s] Config file entry 'Path=' was empty"), *GetDebugString());
return false;
}
// TODO: Validate that the given path is usable?
A quick hardening pass over the file system backend for Mirage. #rb Per.Larsson #rnx #preflight 61408a979dc6c8000148d0cf ### Misc - Updated the documentation for setting up a file system backend and added descriptions to the backend's members. - Renamed the member 'Name' to 'DebugName' to bring it in line with the other backends (still a candidate to be moved to the base class) ### Reading payloads from disk - Added the ability to retry opening file handles for read if they fail. This can commonly occur when multiple threads or processes are both pulling and pushing to the same root directory. -- By default we will retry to open the file handle up to 10 times, waiting for 100ms between each attempt. The user can configure the number of retries and the length of the pause between each attempt via the config files. -- Each failed attempt at opening the file handle will result in a warning being logged, so if the user is stalled for a long length of time while we rety over and over they are at least made aware of the cause. ### Writing payloads to disk - When attempting to write a payload to disk, we will now write to a temp file in the project save directory using a randomly generated name. Once the payload has been fully saved to disk it will then be moved to the correct location. Although not perfect this will reduce the potential for writing corrupted data to a location where it might be read in the future. -- We do attempt to clean up the temp file if the write fails but we do not print error messages if the delete fails as it is considered an optional bonus rather than an essential feature. - Previously we would only log an error if we failed to open a file handle for writing the payload to disk. Now we also log an error if the handle is opened but the actual writes fail. [CL 17550126 by paul chipchase in ue5-main branch]
2021-09-17 06:02:48 -04:00
int32 RetryCountIniFile = INDEX_NONE;
if (FParse::Value(*ConfigEntry, TEXT("RetryCount="), RetryCountIniFile))
{
RetryCount = RetryCountIniFile;
}
int32 RetryWaitTimeMSIniFile = INDEX_NONE;
if (FParse::Value(*ConfigEntry, TEXT("RetryWaitTime="), RetryWaitTimeMSIniFile))
{
RetryWaitTimeMS = RetryWaitTimeMSIniFile;
}
// Now log a summary of the backend settings to make issues easier to diagnose
UE_LOG(LogVirtualization, Log, TEXT("[%s] Using path: '%s'"), *GetDebugString(), *RootDirectory);
A quick hardening pass over the file system backend for Mirage. #rb Per.Larsson #rnx #preflight 61408a979dc6c8000148d0cf ### Misc - Updated the documentation for setting up a file system backend and added descriptions to the backend's members. - Renamed the member 'Name' to 'DebugName' to bring it in line with the other backends (still a candidate to be moved to the base class) ### Reading payloads from disk - Added the ability to retry opening file handles for read if they fail. This can commonly occur when multiple threads or processes are both pulling and pushing to the same root directory. -- By default we will retry to open the file handle up to 10 times, waiting for 100ms between each attempt. The user can configure the number of retries and the length of the pause between each attempt via the config files. -- Each failed attempt at opening the file handle will result in a warning being logged, so if the user is stalled for a long length of time while we rety over and over they are at least made aware of the cause. ### Writing payloads to disk - When attempting to write a payload to disk, we will now write to a temp file in the project save directory using a randomly generated name. Once the payload has been fully saved to disk it will then be moved to the correct location. Although not perfect this will reduce the potential for writing corrupted data to a location where it might be read in the future. -- We do attempt to clean up the temp file if the write fails but we do not print error messages if the delete fails as it is considered an optional bonus rather than an essential feature. - Previously we would only log an error if we failed to open a file handle for writing the payload to disk. Now we also log an error if the handle is opened but the actual writes fail. [CL 17550126 by paul chipchase in ue5-main branch]
2021-09-17 06:02:48 -04:00
UE_LOG(LogVirtualization, Log, TEXT("[%s] Will retry failed read attempts %d times with a gap of %dms betwen them"), *GetDebugString(), RetryCount, RetryWaitTimeMS);
return true;
}
EPushResult FFileSystemBackend::PushData(const FPayloadId& Id, const FCompressedBuffer& Payload)
{
TRACE_CPUPROFILER_EVENT_SCOPE(FFileSystemBackend::PushData);
if (DoesExist(Id))
{
UE_LOG(LogVirtualization, Verbose, TEXT("[%s] Already has a copy of the payload '%s'."), *GetDebugString(), *Id.ToString());
return EPushResult::PayloadAlreadyExisted;
}
A quick hardening pass over the file system backend for Mirage. #rb Per.Larsson #rnx #preflight 61408a979dc6c8000148d0cf ### Misc - Updated the documentation for setting up a file system backend and added descriptions to the backend's members. - Renamed the member 'Name' to 'DebugName' to bring it in line with the other backends (still a candidate to be moved to the base class) ### Reading payloads from disk - Added the ability to retry opening file handles for read if they fail. This can commonly occur when multiple threads or processes are both pulling and pushing to the same root directory. -- By default we will retry to open the file handle up to 10 times, waiting for 100ms between each attempt. The user can configure the number of retries and the length of the pause between each attempt via the config files. -- Each failed attempt at opening the file handle will result in a warning being logged, so if the user is stalled for a long length of time while we rety over and over they are at least made aware of the cause. ### Writing payloads to disk - When attempting to write a payload to disk, we will now write to a temp file in the project save directory using a randomly generated name. Once the payload has been fully saved to disk it will then be moved to the correct location. Although not perfect this will reduce the potential for writing corrupted data to a location where it might be read in the future. -- We do attempt to clean up the temp file if the write fails but we do not print error messages if the delete fails as it is considered an optional bonus rather than an essential feature. - Previously we would only log an error if we failed to open a file handle for writing the payload to disk. Now we also log an error if the handle is opened but the actual writes fail. [CL 17550126 by paul chipchase in ue5-main branch]
2021-09-17 06:02:48 -04:00
// Make sure to log any disk write failures to the user, even if this backend will often be optional as they are
// not expected and could indicate bigger problems.
//
// First we will write out the payload to a temp file, after which we will move it to the correct storage location
// this helps reduce the chance of leaving corrupted data on disk in the case of a power failure etc.
const FString TempFilePath = FPaths::CreateTempFilename(*FPaths::ProjectSavedDir(), TEXT("miragepayload"));
TUniquePtr<FArchive> FileAr(IFileManager::Get().CreateFileWriter(*TempFilePath));
if (FileAr == nullptr)
{
TStringBuilder<MAX_SPRINTF> SystemErrorMsg;
GetFormattedSystemError(SystemErrorMsg);
UE_LOG(LogVirtualization, Error, TEXT("[%s] Failed to write payload '%s' to '%s' due to system error: %s"),
A quick hardening pass over the file system backend for Mirage. #rb Per.Larsson #rnx #preflight 61408a979dc6c8000148d0cf ### Misc - Updated the documentation for setting up a file system backend and added descriptions to the backend's members. - Renamed the member 'Name' to 'DebugName' to bring it in line with the other backends (still a candidate to be moved to the base class) ### Reading payloads from disk - Added the ability to retry opening file handles for read if they fail. This can commonly occur when multiple threads or processes are both pulling and pushing to the same root directory. -- By default we will retry to open the file handle up to 10 times, waiting for 100ms between each attempt. The user can configure the number of retries and the length of the pause between each attempt via the config files. -- Each failed attempt at opening the file handle will result in a warning being logged, so if the user is stalled for a long length of time while we rety over and over they are at least made aware of the cause. ### Writing payloads to disk - When attempting to write a payload to disk, we will now write to a temp file in the project save directory using a randomly generated name. Once the payload has been fully saved to disk it will then be moved to the correct location. Although not perfect this will reduce the potential for writing corrupted data to a location where it might be read in the future. -- We do attempt to clean up the temp file if the write fails but we do not print error messages if the delete fails as it is considered an optional bonus rather than an essential feature. - Previously we would only log an error if we failed to open a file handle for writing the payload to disk. Now we also log an error if the handle is opened but the actual writes fail. [CL 17550126 by paul chipchase in ue5-main branch]
2021-09-17 06:02:48 -04:00
*GetDebugString(),
*Id.ToString(),
*TempFilePath,
SystemErrorMsg.ToString());
return EPushResult::Failed;
}
for (const FSharedBuffer& Buffer : Payload.GetCompressed().GetSegments())
{
// Const cast because FArchive requires a non-const pointer!
FileAr->Serialize(const_cast<void*>(Buffer.GetData()), static_cast<int64>(Buffer.GetSize()));
}
A quick hardening pass over the file system backend for Mirage. #rb Per.Larsson #rnx #preflight 61408a979dc6c8000148d0cf ### Misc - Updated the documentation for setting up a file system backend and added descriptions to the backend's members. - Renamed the member 'Name' to 'DebugName' to bring it in line with the other backends (still a candidate to be moved to the base class) ### Reading payloads from disk - Added the ability to retry opening file handles for read if they fail. This can commonly occur when multiple threads or processes are both pulling and pushing to the same root directory. -- By default we will retry to open the file handle up to 10 times, waiting for 100ms between each attempt. The user can configure the number of retries and the length of the pause between each attempt via the config files. -- Each failed attempt at opening the file handle will result in a warning being logged, so if the user is stalled for a long length of time while we rety over and over they are at least made aware of the cause. ### Writing payloads to disk - When attempting to write a payload to disk, we will now write to a temp file in the project save directory using a randomly generated name. Once the payload has been fully saved to disk it will then be moved to the correct location. Although not perfect this will reduce the potential for writing corrupted data to a location where it might be read in the future. -- We do attempt to clean up the temp file if the write fails but we do not print error messages if the delete fails as it is considered an optional bonus rather than an essential feature. - Previously we would only log an error if we failed to open a file handle for writing the payload to disk. Now we also log an error if the handle is opened but the actual writes fail. [CL 17550126 by paul chipchase in ue5-main branch]
2021-09-17 06:02:48 -04:00
if (!FileAr->Close())
{
A quick hardening pass over the file system backend for Mirage. #rb Per.Larsson #rnx #preflight 61408a979dc6c8000148d0cf ### Misc - Updated the documentation for setting up a file system backend and added descriptions to the backend's members. - Renamed the member 'Name' to 'DebugName' to bring it in line with the other backends (still a candidate to be moved to the base class) ### Reading payloads from disk - Added the ability to retry opening file handles for read if they fail. This can commonly occur when multiple threads or processes are both pulling and pushing to the same root directory. -- By default we will retry to open the file handle up to 10 times, waiting for 100ms between each attempt. The user can configure the number of retries and the length of the pause between each attempt via the config files. -- Each failed attempt at opening the file handle will result in a warning being logged, so if the user is stalled for a long length of time while we rety over and over they are at least made aware of the cause. ### Writing payloads to disk - When attempting to write a payload to disk, we will now write to a temp file in the project save directory using a randomly generated name. Once the payload has been fully saved to disk it will then be moved to the correct location. Although not perfect this will reduce the potential for writing corrupted data to a location where it might be read in the future. -- We do attempt to clean up the temp file if the write fails but we do not print error messages if the delete fails as it is considered an optional bonus rather than an essential feature. - Previously we would only log an error if we failed to open a file handle for writing the payload to disk. Now we also log an error if the handle is opened but the actual writes fail. [CL 17550126 by paul chipchase in ue5-main branch]
2021-09-17 06:02:48 -04:00
TStringBuilder<MAX_SPRINTF> SystemErrorMsg;
GetFormattedSystemError(SystemErrorMsg);
UE_LOG(LogVirtualization, Error, TEXT("[%s] Failed to write payload '%s' contents to '%s' due to system error: %s"),
*GetDebugString(),
*Id.ToString(),
*TempFilePath,
SystemErrorMsg.ToString());
IFileManager::Get().Delete(*TempFilePath, true, false, true); // Clean up the temp file if it is still around but do not failure cases to the user
return EPushResult::Failed;
A quick hardening pass over the file system backend for Mirage. #rb Per.Larsson #rnx #preflight 61408a979dc6c8000148d0cf ### Misc - Updated the documentation for setting up a file system backend and added descriptions to the backend's members. - Renamed the member 'Name' to 'DebugName' to bring it in line with the other backends (still a candidate to be moved to the base class) ### Reading payloads from disk - Added the ability to retry opening file handles for read if they fail. This can commonly occur when multiple threads or processes are both pulling and pushing to the same root directory. -- By default we will retry to open the file handle up to 10 times, waiting for 100ms between each attempt. The user can configure the number of retries and the length of the pause between each attempt via the config files. -- Each failed attempt at opening the file handle will result in a warning being logged, so if the user is stalled for a long length of time while we rety over and over they are at least made aware of the cause. ### Writing payloads to disk - When attempting to write a payload to disk, we will now write to a temp file in the project save directory using a randomly generated name. Once the payload has been fully saved to disk it will then be moved to the correct location. Although not perfect this will reduce the potential for writing corrupted data to a location where it might be read in the future. -- We do attempt to clean up the temp file if the write fails but we do not print error messages if the delete fails as it is considered an optional bonus rather than an essential feature. - Previously we would only log an error if we failed to open a file handle for writing the payload to disk. Now we also log an error if the handle is opened but the actual writes fail. [CL 17550126 by paul chipchase in ue5-main branch]
2021-09-17 06:02:48 -04:00
}
TStringBuilder<512> FilePath;
CreateFilePath(Id, FilePath);
if (!IFileManager::Get().Move(FilePath.ToString(), *TempFilePath))
{
// Store the error message in case we need to display it
TStringBuilder<MAX_SPRINTF> SystemErrorMsg;
GetFormattedSystemError(SystemErrorMsg);
IFileManager::Get().Delete(*TempFilePath, true, false, true); // Clean up the temp file if it is still around but do not failure cases to the user
// Check if another thread or process was writing out the payload at the same time, if so we
// don't need to give an error message.
if (DoesExist(Id))
{
UE_LOG(LogVirtualization, Verbose, TEXT("[%s] Already has a copy of the payload '%s'."), *GetDebugString(), *Id.ToString());
return EPushResult::PayloadAlreadyExisted;
}
else
{
UE_LOG(LogVirtualization, Error, TEXT("[%s] Failed to move payload '%s' to it's final location '%s' due to system error: %s"),
*GetDebugString(),
*Id.ToString(),
*FilePath,
SystemErrorMsg.ToString());
return EPushResult::Failed;
}
}
return EPushResult::Success;
}
FCompressedBuffer FFileSystemBackend::PullData(const FPayloadId& Id)
{
TRACE_CPUPROFILER_EVENT_SCOPE(FFileSystemBackend::PullData);
TStringBuilder<512> FilePath;
CreateFilePath(Id, FilePath);
// TODO: Should we allow the error severity to be configured via ini or just not report this case at all?
if (!IFileManager::Get().FileExists(FilePath.ToString()))
{
UE_LOG(LogVirtualization, Verbose, TEXT("[%s] Does not contain the payload '%s'"), *GetDebugString(), *Id.ToString());
return FCompressedBuffer();
}
A quick hardening pass over the file system backend for Mirage. #rb Per.Larsson #rnx #preflight 61408a979dc6c8000148d0cf ### Misc - Updated the documentation for setting up a file system backend and added descriptions to the backend's members. - Renamed the member 'Name' to 'DebugName' to bring it in line with the other backends (still a candidate to be moved to the base class) ### Reading payloads from disk - Added the ability to retry opening file handles for read if they fail. This can commonly occur when multiple threads or processes are both pulling and pushing to the same root directory. -- By default we will retry to open the file handle up to 10 times, waiting for 100ms between each attempt. The user can configure the number of retries and the length of the pause between each attempt via the config files. -- Each failed attempt at opening the file handle will result in a warning being logged, so if the user is stalled for a long length of time while we rety over and over they are at least made aware of the cause. ### Writing payloads to disk - When attempting to write a payload to disk, we will now write to a temp file in the project save directory using a randomly generated name. Once the payload has been fully saved to disk it will then be moved to the correct location. Although not perfect this will reduce the potential for writing corrupted data to a location where it might be read in the future. -- We do attempt to clean up the temp file if the write fails but we do not print error messages if the delete fails as it is considered an optional bonus rather than an essential feature. - Previously we would only log an error if we failed to open a file handle for writing the payload to disk. Now we also log an error if the handle is opened but the actual writes fail. [CL 17550126 by paul chipchase in ue5-main branch]
2021-09-17 06:02:48 -04:00
TUniquePtr<FArchive> FileAr = OpenFileForReading(FilePath.ToString());
if (FileAr == nullptr)
{
TStringBuilder<MAX_SPRINTF> SystemErrorMsg;
GetFormattedSystemError(SystemErrorMsg);
A quick hardening pass over the file system backend for Mirage. #rb Per.Larsson #rnx #preflight 61408a979dc6c8000148d0cf ### Misc - Updated the documentation for setting up a file system backend and added descriptions to the backend's members. - Renamed the member 'Name' to 'DebugName' to bring it in line with the other backends (still a candidate to be moved to the base class) ### Reading payloads from disk - Added the ability to retry opening file handles for read if they fail. This can commonly occur when multiple threads or processes are both pulling and pushing to the same root directory. -- By default we will retry to open the file handle up to 10 times, waiting for 100ms between each attempt. The user can configure the number of retries and the length of the pause between each attempt via the config files. -- Each failed attempt at opening the file handle will result in a warning being logged, so if the user is stalled for a long length of time while we rety over and over they are at least made aware of the cause. ### Writing payloads to disk - When attempting to write a payload to disk, we will now write to a temp file in the project save directory using a randomly generated name. Once the payload has been fully saved to disk it will then be moved to the correct location. Although not perfect this will reduce the potential for writing corrupted data to a location where it might be read in the future. -- We do attempt to clean up the temp file if the write fails but we do not print error messages if the delete fails as it is considered an optional bonus rather than an essential feature. - Previously we would only log an error if we failed to open a file handle for writing the payload to disk. Now we also log an error if the handle is opened but the actual writes fail. [CL 17550126 by paul chipchase in ue5-main branch]
2021-09-17 06:02:48 -04:00
UE_LOG(LogVirtualization, Error, TEXT("[%s] Failed to load payload '%s' from file '%s' due to system error: %s"),
*GetDebugString(),
*Id.ToString(),
FilePath.ToString(),
SystemErrorMsg.ToString());
return FCompressedBuffer();
}
return FCompressedBuffer::FromCompressed(*FileAr);
}
FString FFileSystemBackend::GetDebugString() const
{
A quick hardening pass over the file system backend for Mirage. #rb Per.Larsson #rnx #preflight 61408a979dc6c8000148d0cf ### Misc - Updated the documentation for setting up a file system backend and added descriptions to the backend's members. - Renamed the member 'Name' to 'DebugName' to bring it in line with the other backends (still a candidate to be moved to the base class) ### Reading payloads from disk - Added the ability to retry opening file handles for read if they fail. This can commonly occur when multiple threads or processes are both pulling and pushing to the same root directory. -- By default we will retry to open the file handle up to 10 times, waiting for 100ms between each attempt. The user can configure the number of retries and the length of the pause between each attempt via the config files. -- Each failed attempt at opening the file handle will result in a warning being logged, so if the user is stalled for a long length of time while we rety over and over they are at least made aware of the cause. ### Writing payloads to disk - When attempting to write a payload to disk, we will now write to a temp file in the project save directory using a randomly generated name. Once the payload has been fully saved to disk it will then be moved to the correct location. Although not perfect this will reduce the potential for writing corrupted data to a location where it might be read in the future. -- We do attempt to clean up the temp file if the write fails but we do not print error messages if the delete fails as it is considered an optional bonus rather than an essential feature. - Previously we would only log an error if we failed to open a file handle for writing the payload to disk. Now we also log an error if the handle is opened but the actual writes fail. [CL 17550126 by paul chipchase in ue5-main branch]
2021-09-17 06:02:48 -04:00
return DebugName;
}
bool FFileSystemBackend::DoesExist(const FPayloadId& Id)
{
TRACE_CPUPROFILER_EVENT_SCOPE(FFileSystemBackend::DoesExist);
TStringBuilder<512> FilePath;
CreateFilePath(Id, FilePath);
return IFileManager::Get().FileExists(FilePath.ToString());
}
void FFileSystemBackend::CreateFilePath(const FPayloadId& PayloadId, FStringBuilderBase& OutPath)
{
TStringBuilder<52> PayloadPath;
Utils::PayloadIdToPath(PayloadId, PayloadPath);
OutPath << RootDirectory << TEXT("/") << PayloadPath;
}
A quick hardening pass over the file system backend for Mirage. #rb Per.Larsson #rnx #preflight 61408a979dc6c8000148d0cf ### Misc - Updated the documentation for setting up a file system backend and added descriptions to the backend's members. - Renamed the member 'Name' to 'DebugName' to bring it in line with the other backends (still a candidate to be moved to the base class) ### Reading payloads from disk - Added the ability to retry opening file handles for read if they fail. This can commonly occur when multiple threads or processes are both pulling and pushing to the same root directory. -- By default we will retry to open the file handle up to 10 times, waiting for 100ms between each attempt. The user can configure the number of retries and the length of the pause between each attempt via the config files. -- Each failed attempt at opening the file handle will result in a warning being logged, so if the user is stalled for a long length of time while we rety over and over they are at least made aware of the cause. ### Writing payloads to disk - When attempting to write a payload to disk, we will now write to a temp file in the project save directory using a randomly generated name. Once the payload has been fully saved to disk it will then be moved to the correct location. Although not perfect this will reduce the potential for writing corrupted data to a location where it might be read in the future. -- We do attempt to clean up the temp file if the write fails but we do not print error messages if the delete fails as it is considered an optional bonus rather than an essential feature. - Previously we would only log an error if we failed to open a file handle for writing the payload to disk. Now we also log an error if the handle is opened but the actual writes fail. [CL 17550126 by paul chipchase in ue5-main branch]
2021-09-17 06:02:48 -04:00
TUniquePtr<FArchive> FFileSystemBackend::OpenFileForReading(const TCHAR* FilePath)
{
TRACE_CPUPROFILER_EVENT_SCOPE(FFileSystemBackend::OpenFileForReading);
int32 Retries = 0;
while (Retries < RetryCount)
{
TUniquePtr<FArchive> FileAr(IFileManager::Get().CreateFileReader(FilePath));
if (FileAr)
{
return FileAr;
}
else
{
UE_LOG(LogVirtualization, Warning, TEXT("[%s] Failed to open '%s' for reading attempt retrying (%d/%d) in %dms..."), *GetDebugString(), FilePath, Retries, RetryCount, RetryWaitTimeMS);
FPlatformProcess::SleepNoStats(RetryWaitTimeMS * 0.001f);
Retries++;
}
}
return nullptr;
}
UE_REGISTER_VIRTUALIZATION_BACKEND_FACTORY(FFileSystemBackend, FileSystem);
} // namespace UE::Virtualization