Files
UnrealEngine/Engine/Source/Runtime/Online/BuildPatchServices/Private/BuildPatchInstaller.h
2025-05-18 13:04:45 +08:00

438 lines
15 KiB
C++

// Copyright Epic Games, Inc. All Rights Reserved.
/*=============================================================================
BuildPatchInstaller.h: Declares the FBuildPatchInstaller class which
controls the process of installing a build described by a build manifest.
=============================================================================*/
#pragma once
#include "HAL/Runnable.h"
#include "HAL/ThreadSafeBool.h"
#include "Templates/SharedPointer.h"
#include "CoreMinimal.h"
#include "Interfaces/IBuildInstaller.h"
#include "Interfaces/IBuildPatchServicesModule.h"
#include "BuildPatchSettings.h"
#include "Common/HttpManager.h"
#include "Core/AsyncHelpers.h"
#include "Core/Platform.h"
#include "Core/ProcessTimer.h"
#include "BuildPatchManifest.h"
#include "BuildPatchProgress.h"
#include "IBuildManifestSet.h"
PRAGMA_DISABLE_DEPRECATION_WARNINGS
namespace BuildPatchServices
{
struct FChunkDbSourceConfig;
struct FCloudSourceConfig;
struct FDownloadConnectionCountConfig;
struct FInstallSourceConfig;
class IInstallerError;
class IFileOperationTracker;
class IMemoryChunkStoreStatistics;
class IDiskChunkStoreStatistics;
class ISpeedRecorder;
class IChunkDataSizeProvider;
class IDownloadServiceStatistics;
class IChunkDbChunkSourceStatistics;
class ICloudChunkSourceStatistics;
class IInstallChunkSourceStatistics;
class IFileConstructorStatistics;
class IVerifierStatistics;
class IInstallerAnalytics;
class IDownloadService;
class IOptimisedDelta;
class IMessagePump;
class IVerifier;
class IBuildManifestSet;
/**
* FBuildPatchInstaller
* This class controls a thread that wraps the code to install/patch an app from manifests.
*/
class FBuildPatchInstaller
: public IBuildInstaller
, public FRunnable
, public TSharedFromThis<FBuildPatchInstaller, ESPMode::ThreadSafe>
{
private:
// Simple unique installer guid to help logging functions have context.
FGuid SessionId;
// Hold a pointer to my thread for easier deleting.
IBuildInstallerThread* Thread;
// The delegates that we will be calling when started.
const FBuildPatchInstallerDelegate StartDelegate;
// The delegates that we will be calling on complete.
const FBuildPatchInstallerDelegate CompleteDelegate;
// The installer configuration.
FBuildInstallerConfiguration Configuration;
// The Configuration.InstallerActions array converted into private class type.
TArray<FBuildPatchInstallerAction> InstallerActions;
// The directory created in staging, to store local patch data.
FString DataStagingDir;
// The directory created in staging to construct install files to.
FString InstallStagingDir;
// The directory created in staging to store any required meta, such as resume info.
FString MetaStagingDir;
// The filename used to mark a previous install that did not complete but moved staged files into the install directory.
FString PreviousMoveMarker;
// A critical section to protect variables.
mutable FCriticalSection ThreadLock;
// A flag storing whether the process was a success.
FThreadSafeBool bSuccess;
// A flag marking that we a running.
FThreadSafeBool bIsRunning;
// A flag marking that we initialized correctly.
FThreadSafeBool bIsInited;
// A flag that stores whether we are on the first install iteration.
FThreadSafeBool bFirstInstallIteration;
// Tracks required download data between install retries.
FThreadSafeInt64 PreviousTotalDownloadRequired;
// Keep track of build stats.
FBuildInstallStats BuildStats;
// Keep track of install progress.
FBuildPatchProgress BuildProgress;
// Whether we are currently paused.
bool bIsPaused;
// Whether we are needing to abort.
bool bShouldAbort;
// Holds a list of files that have been placed into the install directory.
TArray<FString> FilesInstalled;
// Holds the files which are all required.
TSet<FString> TaggedFiles;
// Holds the files which are outdated.
TSet<FString> OutdatedFiles;
// The files to be constructed in the current install attempt.
TSet<FString> FilesToConstruct;
// The files that were removed during installation due to destructive patch behavior.
TSet<FString> OldFilesRemovedBySystem;
// With bInstallToMemory, files end up here after construction.
TMap<FString, TArray64<uint8>> FilesInstalledToMemory;
// Map of registered installations.
TMultiMap<FString, FBuildPatchAppManifestRef> InstallationInfo;
// The file which contains per machine configuration information.
FString LocalMachineConfigFile;
// HTTP manager used to make requests for download data.
TUniquePtr<IHttpManager> HttpManager;
// File systems for classes requiring disk access.
TUniquePtr<IFileSystem> FileSystem;
// Platform abstraction.
TUniquePtr<IPlatform> Platform;
// Installer error tracking system.
TUniquePtr<IInstallerError> InstallerError;
// The analytics provider interface.
TSharedPtr<IAnalyticsProvider> Analytics;
// Installer analytics handler.
TUniquePtr<IInstallerAnalytics> InstallerAnalytics;
// Installer statistics tracking.
TUniquePtr<IFileOperationTracker> FileOperationTracker;
TUniquePtr<ISpeedRecorder> DownloadSpeedRecorder;
TUniquePtr<ISpeedRecorder> DiskReadSpeedRecorder;
TUniquePtr<ISpeedRecorder> DiskWriteSpeedRecorder;
TUniquePtr<IChunkDataSizeProvider> ChunkDataSizeProvider;
TUniquePtr<IDownloadServiceStatistics> DownloadServiceStatistics;
TUniquePtr<IChunkDbChunkSourceStatistics> ChunkDbChunkSourceStatistics;
TUniquePtr<IInstallChunkSourceStatistics> InstallChunkSourceStatistics;
TUniquePtr<ICloudChunkSourceStatistics> CloudChunkSourceStatistics;
TUniquePtr<IFileConstructorStatistics> FileConstructorStatistics;
TUniquePtr<IVerifierStatistics> VerifierStatistics;
// Download service.
TUniquePtr<IDownloadService> DownloadService;
// The message pump controller.
TUniquePtr<IMessagePump> MessagePump;
// The interface for manifest data aggregation.
TUniquePtr<IBuildManifestSet> ManifestSet;
// The interface for verification of files built.
TUniquePtr<IVerifier> Verifier;
// List of controllable classes that have been constructed.
TArray<IControllable*> Controllables;
// Stage timers for build stats.
FProcessTimer InitializeTimer;
FProcessTimer ConstructTimer;
FProcessTimer MoveFromStageTimer;
FProcessTimer FileAttributesTimer;
FProcessTimer VerifyTimer;
FProcessTimer CleanUpTimer;
FProcessTimer PrereqTimer;
FProcessTimer ProcessPausedTimer;
FProcessTimer ProcessActiveTimer;
FProcessTimer ProcessExecuteTimer;
// Caches verification errors encountered each run.
TMap<BuildPatchServices::EVerifyError, int32> CachedVerifyErrorCounts;
public:
/**
* Constructor takes configuration and dependencies.
* @param Configuration The installer configuration structure.
* @param InstallationInfo Map of locally installed apps for use as chunk sources.
* @param LocalMachineConfigFile Filename for the local machine's config. This is used for per-machine configuration rather than shipped or user config.
* @param Analytics Optionally valid ptr to an analytics provider for sending events.
* @param StartDelegate Delegate for when the process has started.
* @param CompleteDelegate Delegate for when the process has completed.
*/
FBuildPatchInstaller(FBuildInstallerConfiguration Configuration, TMultiMap<FString, FBuildPatchAppManifestRef> InstallationInfo, const FString& LocalMachineConfigFile, TSharedPtr<IAnalyticsProvider> Analytics, FBuildPatchInstallerDelegate StartDelegate, FBuildPatchInstallerDelegate CompleteDelegate);
/**
* Default Destructor, will delete the allocated Thread.
*/
~FBuildPatchInstaller();
// FRunnable interface begin.
uint32 Run() override;
// FRunnable interface end.
// IBuildInstaller interface begin.
virtual bool StartInstallation() override;
virtual bool IsComplete() const override;
virtual bool IsCanceled() const override;
virtual bool IsPaused() const override;
virtual bool IsResumable() const override;
virtual bool IsUpdate() const override;
virtual bool CompletedSuccessfully() const override;
virtual bool HasError() const override;
virtual EBuildPatchInstallError GetErrorType() const override;
virtual FString GetErrorCode() const override;
//@todo this is deprecated and shouldn't be used anymore [6/4/2014 justin.sargent]
virtual FText GetPercentageText() const override;
//@todo this is deprecated and shouldn't be used anymore [6/4/2014 justin.sargent]
virtual FText GetDownloadSpeedText() const override;
virtual double GetDownloadSpeed() const override;
virtual int64 GetTotalDownloadRequired() const override;
virtual int64 GetTotalDownloaded() const override;
virtual EBuildPatchState GetState() const override;
virtual FText GetStatusText() const override;
virtual float GetUpdateProgress() const override;
virtual FBuildInstallStats GetBuildStatistics() const override;
virtual EBuildPatchDownloadHealth GetDownloadHealth() const override;
virtual FText GetErrorText() const override;
virtual void CancelInstall() override;
virtual bool TogglePauseInstall() override;
virtual void RegisterMessageHandler(FMessageHandler* MessageHandler) override;
virtual void UnregisterMessageHandler(FMessageHandler* MessageHandler) override;
virtual const FBuildInstallerConfiguration& GetConfiguration() const override;
#if !UE_BUILD_SHIPPING
virtual void GetDebugText(TArray<FString>& Output) override;
#endif
virtual TMap<FString, TArray64<uint8>>& GetFilesInstalledToMemory() override;
// IBuildInstaller interface end.
/**
* Tick function called from the module to give us game thread time.
*/
bool Tick();
/**
* Called by the module during shutdown.
*/
void PreExit();
/**
* @return the file operation tracker for granular data progress states.
*/
const IFileOperationTracker* GetFileOperationTracker() const;
/**
* @return the speed recorder for download speed.
*/
const ISpeedRecorder* GetDownloadSpeedRecorder() const;
/**
* @return the speed recorder for disk read speed.
*/
const ISpeedRecorder* GetDiskReadSpeedRecorder() const;
/**
* @return the speed recorder for disk write speed.
*/
const ISpeedRecorder* GetDiskWriteSpeedRecorder() const;
/**
* @return the download service statistics interface.
*/
const IDownloadServiceStatistics* GetDownloadServiceStatistics() const;
/**
* @return the install chunk source statistics interface.
*/
const IInstallChunkSourceStatistics* GetInstallChunkSourceStatistics() const;
/**
* @return the cloud chunk source statistics interface.
*/
const ICloudChunkSourceStatistics* GetCloudChunkSourceStatistics() const;
/**
* @return the file constructor statistics interface.
*/
const IFileConstructorStatistics* GetFileConstructorStatistics() const;
const IChunkDbChunkSourceStatistics* GetChunkDbChunkSourceStatistics() const;
/**
* @return the verifier statistics interface.
*/
const IVerifierStatistics* GetVerifierStatistics() const;
private:
/**
* Initialize the installer.
* @return Whether initialization was successful.
*/
bool Initialize();
/**
* Executes the on complete delegate. This should only be called when completed, and is separated out
* to allow control to make this call on the main thread.
*/
void ExecuteCompleteDelegate();
/**
* Pumps all queued messages to registered handlers.
*/
void PumpMessages();
/**
* Checks the installation directory for any already existing files of the correct size, with may account for manual
* installation. Should be used for new installation detecting existing files.
* NB: Not useful for patches, where we'd expect existing files anyway.
* @param FilesToCheck The list of files that we would expect to not exist yet.
* @return Returns true if there were potentially already installed files.
*/
bool CheckForExternallyInstalledFiles(const TSet<FString>& FilesToCheck);
/**
* Runs the installation process.
* @param CorruptFiles A list of files that were corrupt, to only install those.
* @return Returns true if there were no errors blocking installation.
*/
bool RunInstallation(TArray<FString>& CorruptFiles);
/**
* Runs the prerequisite installation process.
*/
bool RunPrerequisites();
/**
* Runs the backup process for locally changed files, and then moves new files into installation directory.
* @return Returns true if there were no errors.
*/
bool RunBackupAndMove();
/**
* Runs the process to setup all file attributes required.
* @return Returns true if there were no errors.
*/
bool RunFileAttributes();
/**
* Runs the verification process.
* @param CorruptFiles OUT Receives the list of files that failed verification.
* @return Returns true if there were no corrupt files.
*/
bool RunVerification(TArray<FString>& CorruptFiles);
/**
* Checks a particular file in the install directory to see if it needs backing up, and does so if necessary.
* @param Filename The filename to check, which should match a filename in a manifest.
* @param bDiscoveredByVerification Optional, whether the file was detected changed already by verification stage. Default: false.
* @return Returns true if there were no errors.
*/
bool BackupFileIfNecessary(const FString& Filename, bool bDiscoveredByVerification = false);
/**
* Delete empty directories from an installation.
* @param RootDirectory Root Directory for search.
*/
void CleanupEmptyDirectories(const FString& RootDirectory);
/**
* Remove from the set any files that do not exist.
* @param RootDirectory Root Directory for search.
* @param Files Set of fles to filter.
*/
void FilterToExistingFiles(const FString& RootDirectory, TSet<FString>& Files);
/**
* Attempt to remove a file, using configured retries.
* @param FullFilename The full filename to remove.
* @param ErrorCode OUT The error code if failed.
* @return true if the file was removed.
*/
bool RemoveFileWithRetries(const FString& FullFilename, uint32& ErrorCode);
/**
* Attempt to relocate a file by move or copy, using configured retries
* @param ToFullFilename The full filename of the destination.
* @param FromFullFilename The full filename of the source.
* @param RenameErrorCode OUT The move/rename error code if failed.
* @param CopyErrorCode OUT The copy error code if failed.
* @return true if the file was relocated.
*/
bool RelocateFileWithRetries(const FString& ToFullFilename, const FString& FromFullFilename, uint32& RenameErrorCode, uint32& CopyErrorCode);
/**
* Builds the cloud source configuration struct.
*/
FDownloadConnectionCountConfig BuildConnectionCountConfig();
/**
* Destroys the internal worker thread
*/
void CleanupThread();
};
}
PRAGMA_ENABLE_DEPRECATION_WARNINGS
typedef TSharedPtr< BuildPatchServices::FBuildPatchInstaller, ESPMode::ThreadSafe > FBuildPatchInstallerPtr;
typedef TSharedRef< BuildPatchServices::FBuildPatchInstaller, ESPMode::ThreadSafe > FBuildPatchInstallerRef;
typedef TWeakPtr< BuildPatchServices::FBuildPatchInstaller, ESPMode::ThreadSafe > FBuildPatchInstallerWeakPtr;