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

224 lines
7.1 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. #ROBOMERGE-AUTHOR: paul.chipchase #ROBOMERGE-SOURCE: CL 17550126 in //UE5/Main/... #ROBOMERGE-BOT: STARSHIP (Main -> Release-Engine-Test) (v870-17433530) [CL 17550133 by paul chipchase in ue5-release-engine-test branch]
2021-09-17 06:03:03 -04:00
#include "HAL/PlatformProcess.h"
#include "Misc/Parse.h"
#include "Misc/Paths.h"
#include "VirtualizationUtilities.h"
namespace UE::Virtualization
{
FFileSystemBackend::FFileSystemBackend(FStringView ProjectName, FStringView ConfigName, FStringView DebugName)
: IVirtualizationBackend(ConfigName, DebugName, EOperations::Both)
{
}
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"), *GetDebugName());
return false;
}
FPaths::NormalizeDirectoryName(RootDirectory);
if (RootDirectory.IsEmpty())
{
UE_LOG(LogVirtualization, Error, TEXT("[%s] Config file entry 'Path=' was empty"), *GetDebugName());
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. #ROBOMERGE-AUTHOR: paul.chipchase #ROBOMERGE-SOURCE: CL 17550126 in //UE5/Main/... #ROBOMERGE-BOT: STARSHIP (Main -> Release-Engine-Test) (v870-17433530) [CL 17550133 by paul chipchase in ue5-release-engine-test branch]
2021-09-17 06:03:03 -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'"), *GetDebugName(), *RootDirectory);
UE_LOG(LogVirtualization, Log, TEXT("[%s] Will retry failed read attempts %d times with a gap of %dms betwen them"), *GetDebugName(), RetryCount, RetryWaitTimeMS);
return true;
}
EPushResult FFileSystemBackend::PushData(const FIoHash& Id, const FCompressedBuffer& Payload, const FString& PackageContext)
{
TRACE_CPUPROFILER_EVENT_SCOPE(FFileSystemBackend::PushData);
Submitting packages on projects with virtualization enabled is much faster when none of the payloads actually needs to be virtualized. #rb PJ.Kack #rnx #preflight 61a795773c29b3cf13cd8250 ### PackageSubmissionChecks - Under the old model submitting a large number of packages could be very slow as each package would check each payload that it owns and is currently stored locally one at a time. For the source control backend this created quite a large overhead even when all of the payloads were already virtualized. - Now we do a pass over the submitted files to find all valid packages that have package trailers with locally stored payloads, gather the payloads into a single list and then query that in one large batch. - Once we find which payloads are not in permanent storage (note that in the case where a project is using multiple permanent storage solutions, if a payload is missing in one backend it counts as not being in permanent storage) we then attempt to virtualized them. - Only after all of this is done will we create the truncated copy of each package and then append the updated trailer to each one. In theory doing it in this order this might slightly increase the change of submit failures that occur after virtualization that result in a package never being submitted and orphaned payloads being added to permanent storage, but this will always be a risk. - Added an assert to fire if we detect a trailer with some virtualized and some local payloads. This should be a supported feature but needs proper testing first before we can allow it. With out current project settings no project should actually encounter this scenario. - To make the code easier to follow we now early out of the entire check when errors are encountered. - Added logging at various stages in the process to help show the user that something is happening and make problems easier to identify in the future. - Notes -- There is a lot of handling of invalid FPayloads. This is because it is currently possible to add empty payloads to the trailer which is inefficient and wastes space. The trailer will be modified to reject empty payloads in a future update at which point a lot of this handling can be removed. -- This could've also been solved by not fully rehydrating a package on save by the end user, which will be added as a project setting in a future piece of work, but this approach will solve the edge case when the user does have a large amount of hydrated packages which contain payloads that are already virtualized so it was better to fix that now while we have good test cases for it. -- We still have scaling problems with large number of package being submitted that do have payloads that need to be virtualized, this will be fixed by extending IVirtualizationSystem::Push to also accept batches of payloads in future work. -- OnPrePackageSubmission could be broken up into smaller chunks to make the code easier to follow. This will be done after the batch payload submission work is done. ### VirtualizationSystem - EStorageType has been promoted to enum class. - Added a new enum FPayloadStatus to be used when querying if a payload exists in a backend storage system or not. - Add a new method ::DoPayloadsExist which allows the caller to query if one or more payloads exists in the given backend storage system. ### VirtualizationManager - Implemented ::DoPayloadsExist. First we get the results from each backend in the storage system (which return as true or false from each backend) then total how many backends found the payload in order to set the correct status. ### IVirtualizationBackend - ::DoesPayloadExist which queries the existence of a single payload has been added to the interface. Most backends already implemented this for private use and if so have had their implementation renamed to match this. - Also added ::DoPayloadsExist which takes a batch of FpayloadIdsto query. Some backends can deal with a batch of payload ids much more efficiently than one at a time, although the default implementation does call ::DoesPayloadExist for each requested payload. -- The default implementation prevents every backend from needing to implement the same for loop but does allow backends that can gain from batching to override it. ### VirtualizationSourceControlBackend - This backend does override ::DoPayloadsExist and implements it's own version as it tends to perform very poorly when not operating on larger batches. - In this case ::DoesPayloadExist calls back to ::DoPayloadsExist to check each payload rather than implement as specific version. ### PackageTrailer - The trailer can now be queries to request how many payloads of a given type it contains #ROBOMERGE-AUTHOR: paul.chipchase #ROBOMERGE-SOURCE: CL 18339847 in //UE5/Release-5.0/... via CL 18339852 #ROBOMERGE-BOT: STARSHIP (Release-Engine-Staging -> Release-Engine-Test) (v895-18170469) [CL 18339859 by paul chipchase in ue5-release-engine-test branch]
2021-12-01 11:13:31 -05:00
if (DoesPayloadExist(Id))
{
UE_LOG(LogVirtualization, Verbose, TEXT("[%s] Already has a copy of the payload '%s'."), *GetDebugName(), *LexToString(Id));
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. #ROBOMERGE-AUTHOR: paul.chipchase #ROBOMERGE-SOURCE: CL 17550126 in //UE5/Main/... #ROBOMERGE-BOT: STARSHIP (Main -> Release-Engine-Test) (v870-17433530) [CL 17550133 by paul chipchase in ue5-release-engine-test branch]
2021-09-17 06:03:03 -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;
Utils::GetFormattedSystemError(SystemErrorMsg);
UE_LOG(LogVirtualization, Error, TEXT("[%s] Failed to write payload '%s' to '%s' due to system error: %s"),
*GetDebugName(),
*LexToString(Id),
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. #ROBOMERGE-AUTHOR: paul.chipchase #ROBOMERGE-SOURCE: CL 17550126 in //UE5/Main/... #ROBOMERGE-BOT: STARSHIP (Main -> Release-Engine-Test) (v870-17433530) [CL 17550133 by paul chipchase in ue5-release-engine-test branch]
2021-09-17 06:03:03 -04:00
*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. #ROBOMERGE-AUTHOR: paul.chipchase #ROBOMERGE-SOURCE: CL 17550126 in //UE5/Main/... #ROBOMERGE-BOT: STARSHIP (Main -> Release-Engine-Test) (v870-17433530) [CL 17550133 by paul chipchase in ue5-release-engine-test branch]
2021-09-17 06:03:03 -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. #ROBOMERGE-AUTHOR: paul.chipchase #ROBOMERGE-SOURCE: CL 17550126 in //UE5/Main/... #ROBOMERGE-BOT: STARSHIP (Main -> Release-Engine-Test) (v870-17433530) [CL 17550133 by paul chipchase in ue5-release-engine-test branch]
2021-09-17 06:03:03 -04:00
TStringBuilder<MAX_SPRINTF> SystemErrorMsg;
Utils::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. #ROBOMERGE-AUTHOR: paul.chipchase #ROBOMERGE-SOURCE: CL 17550126 in //UE5/Main/... #ROBOMERGE-BOT: STARSHIP (Main -> Release-Engine-Test) (v870-17433530) [CL 17550133 by paul chipchase in ue5-release-engine-test branch]
2021-09-17 06:03:03 -04:00
UE_LOG(LogVirtualization, Error, TEXT("[%s] Failed to write payload '%s' contents to '%s' due to system error: %s"),
*GetDebugName(),
*LexToString(Id),
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. #ROBOMERGE-AUTHOR: paul.chipchase #ROBOMERGE-SOURCE: CL 17550126 in //UE5/Main/... #ROBOMERGE-BOT: STARSHIP (Main -> Release-Engine-Test) (v870-17433530) [CL 17550133 by paul chipchase in ue5-release-engine-test branch]
2021-09-17 06:03:03 -04:00
*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. #ROBOMERGE-AUTHOR: paul.chipchase #ROBOMERGE-SOURCE: CL 17550126 in //UE5/Main/... #ROBOMERGE-BOT: STARSHIP (Main -> Release-Engine-Test) (v870-17433530) [CL 17550133 by paul chipchase in ue5-release-engine-test branch]
2021-09-17 06:03:03 -04:00
}
TStringBuilder<512> FilePath;
CreateFilePath(Id, FilePath);
// If the file already exists we don't need to replace it, we will also do our own error logging.
if (!IFileManager::Get().Move(FilePath.ToString(), *TempFilePath, /*Replace*/ false, /*EvenIfReadOnly*/ false, /*Attributes*/ false, /*bDoNotRetryOrError*/ true))
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. #ROBOMERGE-AUTHOR: paul.chipchase #ROBOMERGE-SOURCE: CL 17550126 in //UE5/Main/... #ROBOMERGE-BOT: STARSHIP (Main -> Release-Engine-Test) (v870-17433530) [CL 17550133 by paul chipchase in ue5-release-engine-test branch]
2021-09-17 06:03:03 -04:00
{
// Store the error message in case we need to display it
TStringBuilder<MAX_SPRINTF> SystemErrorMsg;
Utils::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. #ROBOMERGE-AUTHOR: paul.chipchase #ROBOMERGE-SOURCE: CL 17550126 in //UE5/Main/... #ROBOMERGE-BOT: STARSHIP (Main -> Release-Engine-Test) (v870-17433530) [CL 17550133 by paul chipchase in ue5-release-engine-test branch]
2021-09-17 06:03:03 -04:00
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.
Submitting packages on projects with virtualization enabled is much faster when none of the payloads actually needs to be virtualized. #rb PJ.Kack #rnx #preflight 61a795773c29b3cf13cd8250 ### PackageSubmissionChecks - Under the old model submitting a large number of packages could be very slow as each package would check each payload that it owns and is currently stored locally one at a time. For the source control backend this created quite a large overhead even when all of the payloads were already virtualized. - Now we do a pass over the submitted files to find all valid packages that have package trailers with locally stored payloads, gather the payloads into a single list and then query that in one large batch. - Once we find which payloads are not in permanent storage (note that in the case where a project is using multiple permanent storage solutions, if a payload is missing in one backend it counts as not being in permanent storage) we then attempt to virtualized them. - Only after all of this is done will we create the truncated copy of each package and then append the updated trailer to each one. In theory doing it in this order this might slightly increase the change of submit failures that occur after virtualization that result in a package never being submitted and orphaned payloads being added to permanent storage, but this will always be a risk. - Added an assert to fire if we detect a trailer with some virtualized and some local payloads. This should be a supported feature but needs proper testing first before we can allow it. With out current project settings no project should actually encounter this scenario. - To make the code easier to follow we now early out of the entire check when errors are encountered. - Added logging at various stages in the process to help show the user that something is happening and make problems easier to identify in the future. - Notes -- There is a lot of handling of invalid FPayloads. This is because it is currently possible to add empty payloads to the trailer which is inefficient and wastes space. The trailer will be modified to reject empty payloads in a future update at which point a lot of this handling can be removed. -- This could've also been solved by not fully rehydrating a package on save by the end user, which will be added as a project setting in a future piece of work, but this approach will solve the edge case when the user does have a large amount of hydrated packages which contain payloads that are already virtualized so it was better to fix that now while we have good test cases for it. -- We still have scaling problems with large number of package being submitted that do have payloads that need to be virtualized, this will be fixed by extending IVirtualizationSystem::Push to also accept batches of payloads in future work. -- OnPrePackageSubmission could be broken up into smaller chunks to make the code easier to follow. This will be done after the batch payload submission work is done. ### VirtualizationSystem - EStorageType has been promoted to enum class. - Added a new enum FPayloadStatus to be used when querying if a payload exists in a backend storage system or not. - Add a new method ::DoPayloadsExist which allows the caller to query if one or more payloads exists in the given backend storage system. ### VirtualizationManager - Implemented ::DoPayloadsExist. First we get the results from each backend in the storage system (which return as true or false from each backend) then total how many backends found the payload in order to set the correct status. ### IVirtualizationBackend - ::DoesPayloadExist which queries the existence of a single payload has been added to the interface. Most backends already implemented this for private use and if so have had their implementation renamed to match this. - Also added ::DoPayloadsExist which takes a batch of FpayloadIdsto query. Some backends can deal with a batch of payload ids much more efficiently than one at a time, although the default implementation does call ::DoesPayloadExist for each requested payload. -- The default implementation prevents every backend from needing to implement the same for loop but does allow backends that can gain from batching to override it. ### VirtualizationSourceControlBackend - This backend does override ::DoPayloadsExist and implements it's own version as it tends to perform very poorly when not operating on larger batches. - In this case ::DoesPayloadExist calls back to ::DoPayloadsExist to check each payload rather than implement as specific version. ### PackageTrailer - The trailer can now be queries to request how many payloads of a given type it contains #ROBOMERGE-AUTHOR: paul.chipchase #ROBOMERGE-SOURCE: CL 18339847 in //UE5/Release-5.0/... via CL 18339852 #ROBOMERGE-BOT: STARSHIP (Release-Engine-Staging -> Release-Engine-Test) (v895-18170469) [CL 18339859 by paul chipchase in ue5-release-engine-test branch]
2021-12-01 11:13:31 -05:00
if (DoesPayloadExist(Id))
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. #ROBOMERGE-AUTHOR: paul.chipchase #ROBOMERGE-SOURCE: CL 17550126 in //UE5/Main/... #ROBOMERGE-BOT: STARSHIP (Main -> Release-Engine-Test) (v870-17433530) [CL 17550133 by paul chipchase in ue5-release-engine-test branch]
2021-09-17 06:03:03 -04:00
{
UE_LOG(LogVirtualization, Verbose, TEXT("[%s] Already has a copy of the payload '%s'."), *GetDebugName(), *LexToString(Id));
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. #ROBOMERGE-AUTHOR: paul.chipchase #ROBOMERGE-SOURCE: CL 17550126 in //UE5/Main/... #ROBOMERGE-BOT: STARSHIP (Main -> Release-Engine-Test) (v870-17433530) [CL 17550133 by paul chipchase in ue5-release-engine-test branch]
2021-09-17 06:03:03 -04:00
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"),
*GetDebugName(),
*LexToString(Id),
*FilePath,
SystemErrorMsg.ToString());
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. #ROBOMERGE-AUTHOR: paul.chipchase #ROBOMERGE-SOURCE: CL 17550126 in //UE5/Main/... #ROBOMERGE-BOT: STARSHIP (Main -> Release-Engine-Test) (v870-17433530) [CL 17550133 by paul chipchase in ue5-release-engine-test branch]
2021-09-17 06:03:03 -04:00
return EPushResult::Failed;
}
}
return EPushResult::Success;
}
FCompressedBuffer FFileSystemBackend::PullData(const FIoHash& 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'"), *GetDebugName(), *LexToString(Id));
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. #ROBOMERGE-AUTHOR: paul.chipchase #ROBOMERGE-SOURCE: CL 17550126 in //UE5/Main/... #ROBOMERGE-BOT: STARSHIP (Main -> Release-Engine-Test) (v870-17433530) [CL 17550133 by paul chipchase in ue5-release-engine-test branch]
2021-09-17 06:03:03 -04:00
TUniquePtr<FArchive> FileAr = OpenFileForReading(FilePath.ToString());
if (FileAr == nullptr)
{
TStringBuilder<MAX_SPRINTF> SystemErrorMsg;
Utils::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. #ROBOMERGE-AUTHOR: paul.chipchase #ROBOMERGE-SOURCE: CL 17550126 in //UE5/Main/... #ROBOMERGE-BOT: STARSHIP (Main -> Release-Engine-Test) (v870-17433530) [CL 17550133 by paul chipchase in ue5-release-engine-test branch]
2021-09-17 06:03:03 -04:00
UE_LOG(LogVirtualization, Error, TEXT("[%s] Failed to load payload '%s' from file '%s' due to system error: %s"),
*GetDebugName(),
*LexToString(Id),
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. #ROBOMERGE-AUTHOR: paul.chipchase #ROBOMERGE-SOURCE: CL 17550126 in //UE5/Main/... #ROBOMERGE-BOT: STARSHIP (Main -> Release-Engine-Test) (v870-17433530) [CL 17550133 by paul chipchase in ue5-release-engine-test branch]
2021-09-17 06:03:03 -04:00
FilePath.ToString(),
SystemErrorMsg.ToString());
return FCompressedBuffer();
}
return FCompressedBuffer::Load(*FileAr);
}
bool FFileSystemBackend::DoesPayloadExist(const FIoHash& Id)
{
Submitting packages on projects with virtualization enabled is much faster when none of the payloads actually needs to be virtualized. #rb PJ.Kack #rnx #preflight 61a795773c29b3cf13cd8250 ### PackageSubmissionChecks - Under the old model submitting a large number of packages could be very slow as each package would check each payload that it owns and is currently stored locally one at a time. For the source control backend this created quite a large overhead even when all of the payloads were already virtualized. - Now we do a pass over the submitted files to find all valid packages that have package trailers with locally stored payloads, gather the payloads into a single list and then query that in one large batch. - Once we find which payloads are not in permanent storage (note that in the case where a project is using multiple permanent storage solutions, if a payload is missing in one backend it counts as not being in permanent storage) we then attempt to virtualized them. - Only after all of this is done will we create the truncated copy of each package and then append the updated trailer to each one. In theory doing it in this order this might slightly increase the change of submit failures that occur after virtualization that result in a package never being submitted and orphaned payloads being added to permanent storage, but this will always be a risk. - Added an assert to fire if we detect a trailer with some virtualized and some local payloads. This should be a supported feature but needs proper testing first before we can allow it. With out current project settings no project should actually encounter this scenario. - To make the code easier to follow we now early out of the entire check when errors are encountered. - Added logging at various stages in the process to help show the user that something is happening and make problems easier to identify in the future. - Notes -- There is a lot of handling of invalid FPayloads. This is because it is currently possible to add empty payloads to the trailer which is inefficient and wastes space. The trailer will be modified to reject empty payloads in a future update at which point a lot of this handling can be removed. -- This could've also been solved by not fully rehydrating a package on save by the end user, which will be added as a project setting in a future piece of work, but this approach will solve the edge case when the user does have a large amount of hydrated packages which contain payloads that are already virtualized so it was better to fix that now while we have good test cases for it. -- We still have scaling problems with large number of package being submitted that do have payloads that need to be virtualized, this will be fixed by extending IVirtualizationSystem::Push to also accept batches of payloads in future work. -- OnPrePackageSubmission could be broken up into smaller chunks to make the code easier to follow. This will be done after the batch payload submission work is done. ### VirtualizationSystem - EStorageType has been promoted to enum class. - Added a new enum FPayloadStatus to be used when querying if a payload exists in a backend storage system or not. - Add a new method ::DoPayloadsExist which allows the caller to query if one or more payloads exists in the given backend storage system. ### VirtualizationManager - Implemented ::DoPayloadsExist. First we get the results from each backend in the storage system (which return as true or false from each backend) then total how many backends found the payload in order to set the correct status. ### IVirtualizationBackend - ::DoesPayloadExist which queries the existence of a single payload has been added to the interface. Most backends already implemented this for private use and if so have had their implementation renamed to match this. - Also added ::DoPayloadsExist which takes a batch of FpayloadIdsto query. Some backends can deal with a batch of payload ids much more efficiently than one at a time, although the default implementation does call ::DoesPayloadExist for each requested payload. -- The default implementation prevents every backend from needing to implement the same for loop but does allow backends that can gain from batching to override it. ### VirtualizationSourceControlBackend - This backend does override ::DoPayloadsExist and implements it's own version as it tends to perform very poorly when not operating on larger batches. - In this case ::DoesPayloadExist calls back to ::DoPayloadsExist to check each payload rather than implement as specific version. ### PackageTrailer - The trailer can now be queries to request how many payloads of a given type it contains #ROBOMERGE-AUTHOR: paul.chipchase #ROBOMERGE-SOURCE: CL 18339847 in //UE5/Release-5.0/... via CL 18339852 #ROBOMERGE-BOT: STARSHIP (Release-Engine-Staging -> Release-Engine-Test) (v895-18170469) [CL 18339859 by paul chipchase in ue5-release-engine-test branch]
2021-12-01 11:13:31 -05:00
TRACE_CPUPROFILER_EVENT_SCOPE(FFileSystemBackend::DoesPayloadExist);
TStringBuilder<512> FilePath;
CreateFilePath(Id, FilePath);
return IFileManager::Get().FileExists(FilePath.ToString());
}
void FFileSystemBackend::CreateFilePath(const FIoHash& 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. #ROBOMERGE-AUTHOR: paul.chipchase #ROBOMERGE-SOURCE: CL 17550126 in //UE5/Main/... #ROBOMERGE-BOT: STARSHIP (Main -> Release-Engine-Test) (v870-17433530) [CL 17550133 by paul chipchase in ue5-release-engine-test branch]
2021-09-17 06:03:03 -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..."), *GetDebugName(), FilePath, Retries, RetryCount, RetryWaitTimeMS);
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. #ROBOMERGE-AUTHOR: paul.chipchase #ROBOMERGE-SOURCE: CL 17550126 in //UE5/Main/... #ROBOMERGE-BOT: STARSHIP (Main -> Release-Engine-Test) (v870-17433530) [CL 17550133 by paul chipchase in ue5-release-engine-test branch]
2021-09-17 06:03:03 -04:00
FPlatformProcess::SleepNoStats(RetryWaitTimeMS * 0.001f);
Retries++;
}
}
return nullptr;
}
UE_REGISTER_VIRTUALIZATION_BACKEND_FACTORY(FFileSystemBackend, FileSystem);
} // namespace UE::Virtualization