2021-12-02 06:21:36 -05:00
// Copyright Epic Games, Inc. All Rights Reserved.
# pragma once
# include "IVirtualizationBackend.h"
# include "Containers/StringView.h"
2022-03-08 11:22:45 -05:00
class ISourceControlProvider ;
2021-12-02 06:21:36 -05:00
namespace UE : : Virtualization
{
2022-05-03 09:39:48 -04:00
class FSemaphore ;
2021-12-02 06:21:36 -05:00
/**
* This backend can be used to access payloads stored in source control.
* The backend doesn't 'check out' a payload file but instead will just download the payload as
* a binary blob.
* It is assumed that the files are stored with the same path convention as the file system
* backend, found in Utils::PayloadIdToPath.
2023-03-20 09:49:52 -04:00
* ----------------------------------------------------------------------------
*
2021-12-02 06:21:36 -05:00
* Ini file setup:
2023-04-13 10:11:47 -04:00
* 'Name'=(Type=P4SourceControl)
* Where 'Name' is the backend name in the hierarchy
2021-12-07 03:21:51 -05:00
*
2023-04-13 10:11:47 -04:00
* Required Values:
*
2023-06-20 04:26:06 -04:00
* DepotPath [string] The path (in depot format) to the location where virtualized payloads are stored.
* [Default=""]
* ClientStream [string]: Used when the payloads are stored in a stream based depot. It should contain
* the stream name to use when creating a workspace for payload submission. [Default=""]
2023-04-13 10:11:47 -04:00
*
* If the payloads are being stored in a depot with type 'stream' them config value 'ClientStream' must be set to a valid
* stream. The 'DepotPath' value can still be set to choose a specific location within that stream or when the stream
* name is not a valid depot path (such as virtual streams)
*
* If the payloads are not being stored in a 'stream' depot then only 'DepotPath' is required.
*
* Optional Values:
*
2023-06-20 04:26:06 -04:00
* Server [string]: When set the backend will use this server address to connect to. When not
* set the backend will use the environment defaults. [Default=""]
* UsePartitionedClient [bool]: When true the temporary workspace client created to submit payloads
* from will be created as a partitioned workspace which is less overhead
* on the source control server. If your server does not support this then
* use false. [Default=True]
* WorkingDir [string]: Sets the temp location on disk where payloads are submitted from. The path can
* contain config file expansions (see ConfigCacheIni.cpp ::MatchExpansions) and
* environment variables with the format $(EnvVarName).
* [Default="%GAMESAVEDDIR%/VASubmission"]
* RetryCount [int32]: How many times we should try to download a payload before giving up with
* an error. Useful when the connection is unreliable but does not experience
* frequent persistent outages. [Default=2]
* RetryWaitTime [int32]: The length of time the process should wait between each download attempt
* in milliseconds. Remember that the max length of time that the process
* can stall attempting to download a payload file is
* RetryCount * RetryWaitTime; [Default=100ms]
* MaxConnections [int32] The maximum number of perforce connections that can be made concurrently.
* If this value is exceeded then additional requests will wait until a
* connection becomes free. Pass in '-1' to disable this feature and allow
* unlimited connections. [Default=8]
* BatchCount [int32] The max number of payloads that can be pushed to source control in a
* single submit. If the number of payloads in a request batch exceeds
* this size then it will be split into multiple smaller batches. [Default=100]
* SuppressNotifications[bool]: When true the system will not display a pop up notification when a
* connection error occurs, allowing the user to stay unaware of the error
* unless it actually causes some sort of problem. [Default=false]
* UseLocalIniFileSettings[bool] When true the revision control provider will be allowed to load connection
* settings from the users locally saved 'SourceControlSettings.ini' file, if
* false then the settings in this file (if any) will be ignored. [Default=true]
* IgnoreFile [string]: Sets the name of the p4 ignore file to use. When submitting payloads we
* create a custom p4 ignore file to override any ignore settings for a project
* which allows us to submit from the saved directory which is normally prevented
* by the default ignore file. This value can be set to what ever is used by
* your perforce environment. [Default=".p4ignore.txt"]
* UseRetryConnectionDialog[bool] When true a slate dialog will be shown if the initial connection to the
* source control server fails allowing the user to attempt to input the correct
* login values. [Default=false]&
2022-03-01 09:05:41 -05:00
*
* Environment Variables:
* UE-VirtualizationWorkingDir [string]: This can be set to a valid directory path that the backend
* should use as the root location to submit payloads from.
* If the users machine has this set then 'SubmitFromTempDir'
* will be ignored.
2023-03-20 09:49:52 -04:00
* ----------------------------------------------------------------------------
*
* Perforce Storage Setup:
*
* Once you have decided where in perforce you want to store the virtualized payloads you will need to submit
* a dummy file to the root of that location named "payload_metainfo.txt" preferably with a short message describing
* the storage locations purpose.
* When initialized this backend will first attempt to find and download this dummy file as a way of validating that
* a) the process can correctly connect to perforce
* b) the process has the correct location setup in the config file.
* This validation not only allows us to alert the user to misconfiguration issues before they need to access the data
* but allows us to prevent users from accidentally pushing virtualized payloads to the wrong location.
*
* So for example, if the virtualized payloads are to be stored under '//payloads/project/...' then the backend would
* expect to find a '//payloads/project/payload_metainfo.txt' file that it would download via a p4 print command.
*
* If this file is not found then the backend will log an error the first time that it attempts to connect and will prevent
* the user from pulling or pushing payloads until the issue is resolved.
* ----------------------------------------------------------------------------
*
* Perforce Settings Setup:
2022-09-23 20:05:59 -04:00
*
* The backend will attempt to use the current global environment settings for perforce to determine
* the P4PORT and P4USER values. If you wish to set them via an ini file then they can be done per
* user by adding the following to Saved\Config\<platform>Editor\SourceControlSettings.ini
*
* -----
* [PerforceSourceControl.VirtualizationSettings]
* Port=<server address>
* UserName=<username>
* -----
* Note that the backend will read from these ini file settings but will not write to them.
2021-12-02 06:21:36 -05:00
*/
class FSourceControlBackend final : public IVirtualizationBackend
{
public :
2022-03-08 11:22:45 -05:00
explicit FSourceControlBackend ( FStringView ProjectName , FStringView ConfigName , FStringView InDebugName ) ;
2021-12-02 06:21:36 -05:00
virtual ~ FSourceControlBackend ( ) = default ;
private :
/* IVirtualizationBackend implementation */
virtual bool Initialize ( const FString & ConfigEntry ) override ;
2022-08-23 13:01:15 -04:00
virtual EConnectionStatus OnConnect ( ) override ;
2023-08-23 08:22:30 -04:00
IVirtualizationBackend : : EConnectionStatus OnConnectInternal ( FString & InOutPort , FString & InOutUsername , bool bSaveConnectionSettings , FText & OutErrorMessage ) ;
2021-12-02 06:21:36 -05:00
2023-04-14 10:13:46 -04:00
virtual bool PushData ( TArrayView < FPushRequest > Requests , EPushFlags Flags ) override ;
2023-04-25 08:47:06 -04:00
virtual bool PullData ( TArrayView < FPullRequest > Requests , EPullFlags Flags , FText & OutErrors ) override ;
2021-12-02 06:21:36 -05:00
2022-02-02 02:21:24 -05:00
virtual bool DoesPayloadExist ( const FIoHash & Id ) override ;
2021-12-02 06:21:36 -05:00
2022-02-02 02:21:24 -05:00
virtual bool DoPayloadsExist ( TArrayView < const FIoHash > PayloadIds , TArray < bool > & OutResults ) override ;
2021-12-02 06:21:36 -05:00
private :
2022-04-14 05:32:56 -04:00
bool TryApplySettingsFromConfigFiles ( const FString & ConfigEntry ) ;
2022-02-02 02:21:24 -05:00
void CreateDepotPath ( const FIoHash & PayloadId , FStringBuilderBase & OutPath ) ;
2021-12-02 06:21:36 -05:00
2022-03-01 09:05:41 -05:00
bool FindSubmissionWorkingDir ( const FString & ConfigEntry ) ;
2022-01-18 04:50:38 -05:00
/** Will display a FMessage notification to the user on the next valid engine tick to try and keep them aware of connection failures */
2023-08-23 08:22:30 -04:00
void OnConnectionError ( FText ErrorMessage ) ;
2022-03-08 11:22:45 -05:00
2022-03-09 07:43:59 -05:00
/** A source control connection owned by the backend*/
TUniquePtr < ISourceControlProvider > SCCProvider ;
2022-03-08 11:22:45 -05:00
/** The name of the current project */
FString ProjectName ;
2023-04-13 10:11:47 -04:00
/** The path (in depot format) to where the virtualized payloads are stored in source control */
FString DepotPathRoot ;
2021-12-07 03:21:51 -05:00
2022-09-21 16:29:44 -04:00
/** Address of the server to connect to */
FString ServerAddress ;
2022-08-10 08:51:05 -04:00
/** The stream containing the DepotRoot where the virtualized payloads are stored in source control */
FString ClientStream ;
2022-03-01 09:05:41 -05:00
/** The root directory from which payloads are submitted. */
FString SubmissionRootDir ;
2023-02-24 09:58:54 -05:00
/** The name to use for the p4 ignore file */
FString IgnoreFileName = TEXT ( " .p4ignore.txt " ) ;
2021-12-07 03:21:51 -05:00
/** Should we try to make the temp client partitioned or not? */
bool bUsePartitionedClient = true ;
2022-07-07 11:37:36 -04:00
/** When true, the backend will not raise a pop up notification on connection error */
bool bSuppressNotifications = false ;
/** The maximum number of files to send in a single source control operation */
2022-05-05 03:11:20 -04:00
int32 MaxBatchCount = 100 ;
2022-05-03 09:39:48 -04:00
/** A counted semaphore that will limit the number of concurrent connections that we can make */
TUniquePtr < UE : : Virtualization : : FSemaphore > ConcurrentConnectionLimit ;
2022-04-14 05:32:56 -04:00
/** The number of times to retry pulling a payload from the depot */
int32 RetryCount = 2 ;
/** The length of time (in milliseconds) to wait after each pull attempt before retrying. */
int32 RetryWaitTimeMS = 100 ;
2023-03-15 10:17:32 -04:00
/** When true we allow the revision control provider to read settings from the users local SourceControlSettings.ini file */
bool bUseLocalIniFileSettings = true ;
2023-06-20 04:26:06 -04:00
/* When true, if the initial connection to the revision control provider fails we will show a slate dialog (if possible) to the user prompting for correct settings */
bool bUseRetryConnectionDialog = false ;
2021-12-02 06:21:36 -05:00
} ;
} // namespace UE::Virtualization