// Copyright Epic Games, Inc. All Rights Reserved. #pragma once #include "InstallBundleManagerInterface.h" #include "InstallBundleManagerUtil.h" #include "InstallBundleCache.h" #include "Experimental/UnifiedError/UnifiedError.h" #include "Containers/StaticArray.h" #include "Templates/ValueOrError.h" #define UE_API DEFAULTINSTALLBUNDLEMANAGER_API #ifndef INSTALL_BUNDLE_ENABLE_ANALYTICS #define INSTALL_BUNDLE_ENABLE_ANALYTICS (!WITH_EDITOR) #endif enum class EPatchCheckResult : uint8; class IAnalyticsProviderET; class IInstallBundleSource; namespace UE::IoStore { class IOnDemandIoStore; } struct FPakMountOptions; class FDefaultInstallBundleManager : public IInstallBundleManager { protected: // Strongly Typed enums do not work well for this thing's use case struct FContentRequestBatchNS { enum Enum : int { Requested, Cache, Install, Count, }; }; using EContentRequestBatch = FContentRequestBatchNS::Enum; friend struct NEnumRangePrivate::TEnumRangeTraits; friend DEFAULTINSTALLBUNDLEMANAGER_API const TCHAR* LexToString(FDefaultInstallBundleManager::EContentRequestBatch Val); // Strongly Typed enums do not work well for this thing's use case struct FContentReleaseRequestBatchNS { enum Enum : int { Requested, Release, Count, }; }; using EContentReleaseRequestBatch = FContentReleaseRequestBatchNS::Enum; friend struct NEnumRangePrivate::TEnumRangeTraits; friend DEFAULTINSTALLBUNDLEMANAGER_API const TCHAR* LexToString(FDefaultInstallBundleManager::EContentReleaseRequestBatch Val); enum class EBundleState : int { NotInstalled, NeedsUpdate, NeedsMount, Mounted, Count, }; friend const TCHAR* LexToString(FDefaultInstallBundleManager::EBundleState Val) { static const TCHAR* Strings[] = { TEXT("NotInstalled"), TEXT("NeedsUpdate"), TEXT("NeedsMount"), TEXT("Mounted"), }; return InstallBundleUtil::TLexToString(Val, Strings); } bool StateSignifiesNeedsInstall(EBundleState StateIn) { return (StateIn == EBundleState::NotInstalled || StateIn == EBundleState::NeedsUpdate); } enum class EAsyncInitStep : int { None, InitBundleSources, InitBundleCaches, QueryBundleInfo, SetUpdateBundleInfoCallback, CreateAnalyticsSession, Finishing, Count, }; friend const TCHAR* LexToString(FDefaultInstallBundleManager::EAsyncInitStep Val) { static const TCHAR* Strings[] = { TEXT("None"), TEXT("InitBundleSources"), TEXT("InitBundleCaches"), TEXT("QueryBundleInfo"), TEXT("SetUpdateBundleInfoCallback"), TEXT("CreateAnalyticsSession"), TEXT("Finishing"), }; return InstallBundleUtil::TLexToString(Val, Strings); } enum class EAsyncInitStepResult : int { Waiting, Done, }; enum class EBundlePrereqs : int { CacheHintRequested, RequiresLatestClient, HasNoPendingCancels, HasNoPendingReleaseRequests, HasNoPendingUpdateRequests, DetermineSteps, Count }; friend const TCHAR* LexToString(EBundlePrereqs Val) { static const TCHAR* Strings[] = { TEXT("CacheHintRequested"), TEXT("RequiresLatestClient"), TEXT("HasNoPendingCancels"), TEXT("HasNoPendingReleaseRequests"), TEXT("HasNoPendingUpdateRequests"), TEXT("DetermineSteps"), }; return InstallBundleUtil::TLexToString(Val, Strings); } struct FBundleSourceRelevance { FInstallBundleSourceType SourceType; bool bIsRelevant = true; bool operator==(const FBundleSourceRelevance& Other) const { return SourceType == Other.SourceType; } }; struct FBundleContentPaths { TArray> ContentPaths; TArray AdditionalRootDirs; FString ProjectName; bool bContainsChunks = false; }; friend struct FBundleInfo; struct FBundleInfo { public: EBundleState GetBundleStatus(const FDefaultInstallBundleManager& BundleMan) const { check(FPlatformTLS::GetCurrentThreadId() == GGameThreadId); check(BundleMan.InitState == EInstallBundleManagerInitState::Succeeded || BundleMan.bIsCurrentlyInAsyncInit); return BundleStatus; } void SetBundleStatus(const FDefaultInstallBundleManager& BundleMan, EBundleState InBundleState) { check(FPlatformTLS::GetCurrentThreadId() == GGameThreadId); check(BundleMan.InitState == EInstallBundleManagerInitState::Succeeded || BundleMan.bIsCurrentlyInAsyncInit); BundleStatus = InBundleState; } bool GetMustWaitForPSOCache(const FDefaultInstallBundleManager& BundleMan) const { check(FPlatformTLS::GetCurrentThreadId() == GGameThreadId); check(BundleMan.InitState == EInstallBundleManagerInitState::Succeeded); return bWaitForPSOCache; } uint32 GetInitialShaderPrecompiles(const FDefaultInstallBundleManager& BundleMan) const { check(FPlatformTLS::GetCurrentThreadId() == GGameThreadId); check(BundleMan.InitState == EInstallBundleManagerInitState::Succeeded); return InitialShaderPrecompiles; } void SetMustWaitForPSOCache(const FDefaultInstallBundleManager& BundleMan, uint32 InNumPSOPrecompilesRemaining) { check(FPlatformTLS::GetCurrentThreadId() == GGameThreadId); check(BundleMan.InitState == EInstallBundleManagerInitState::Succeeded); bWaitForPSOCache = InNumPSOPrecompilesRemaining > 0; if (InNumPSOPrecompilesRemaining > InitialShaderPrecompiles) { InitialShaderPrecompiles = InNumPSOPrecompilesRemaining; } } private: EBundleState BundleStatus = EBundleState::NotInstalled; uint32 InitialShaderPrecompiles = 0; public: FString BundleNameString; // Since FNames do not preserve casing TArray Prereqs; TArray ContributingSources; // Sources contributing to this bundle info FBundleContentPaths ContentPaths; // Only valid if BundleStatus >= NeedsMount EInstallBundlePriority Priority = EInstallBundlePriority::Low; private: bool bWaitForPSOCache = false; public: bool bReleaseRequired = false; // A bundle source may have done install work so expects a release call bool bIsStartup = false; bool bContainsIoStoreOnDemandTocs = false; bool bMountedOnDemandTocs = false; }; // GetBundleStatus protects erroneous accesses of the bundle status before initialization is complete by throwing an assert UE_API EBundleState GetBundleStatus(const FBundleInfo& BundleInfo) const; UE_API void SetBundleStatus(FBundleInfo& BundleInfo, EBundleState InBundleState); UE_API bool GetMustWaitForPSOCache(const FBundleInfo& BundleInfo) const; UE_API uint32 GetInitialShaderPrecompiles(const FBundleInfo& BundleInfo) const; UE_API void SetMustWaitForPSOCache(FBundleInfo& BundleInfo, uint32 InNumPSOPrecompilesRemaining); struct FGetContentStateRequest { TMap BundleSourceContentStates; TArray BundleNames; EInstallBundleGetContentStateFlags Flags = EInstallBundleGetContentStateFlags::None; bool Started = false; bool bCancelled = false; //Used to track an individual request so that it can be canceled FName RequestTag; void SetCallback(FInstallBundleGetContentStateDelegate NewCallback) { Callback = MoveTemp(NewCallback); } void ExecCallbackIfValid(FInstallBundleCombinedContentState BundleState) { if (!bCancelled) { Callback.ExecuteIfBound(MoveTemp(BundleState)); } } const FDelegateHandle GetCallbackDelegateHandle() { return Callback.GetHandle(); } private: FInstallBundleGetContentStateDelegate Callback; }; using FGetContentStateRequestRef = TSharedRef; using FGetContentStateRequestPtr = TSharedPtr; struct FGetInstallStateRequest { TArray BundleNames; bool bCancelled = false; //Used to track an individual request so that it can be canceled FName RequestTag; void SetCallback(FInstallBundleGetInstallStateDelegate NewCallback) { Callback = MoveTemp(NewCallback); } void ExecCallbackIfValid(FInstallBundleCombinedInstallState BundleState) { if (!bCancelled) { Callback.ExecuteIfBound(MoveTemp(BundleState)); } } const FDelegateHandle GetCallbackDelegateHandle() { return Callback.GetHandle(); } private: FInstallBundleGetInstallStateDelegate Callback; }; using FGetInstallStateRequestRef = TSharedRef; using FGetInstallStateRequestPtr = TSharedPtr; enum class EContentRequestStepResult : int { Waiting, Done, }; enum class EContentRequestState : int { ReservingCache, FinishingCache, UpdatingBundleSources, Mounting, WaitingForShaderCache, Finishing, CleaningUp, Count, }; friend const TCHAR* LexToString(EContentRequestState Val) { static const TCHAR* Strings[] = { TEXT("ReservingCache"), TEXT("FinishingCache"), TEXT("UpdatingBundleSources"), TEXT("Mounting"), TEXT("WaitingForShaderCache"), TEXT("Finishing"), TEXT("CleaningUp"), }; return InstallBundleUtil::TLexToString(Val, Strings); } enum class ECacheEvictionRequestorType : int { CacheFlush, ContentRequest }; struct FCacheEvictionRequestor { TMap> BundlesToEvictFromSourcesMap; virtual ~FCacheEvictionRequestor() {} virtual FString GetEvictionRequestorName() const = 0; virtual ECacheEvictionRequestorType GetEvictionRequestorType() const = 0; virtual ELogVerbosity::Type GetLogVerbosityOverride() const = 0; }; using FCacheEvictionRequestorRef = TSharedRef; using FCacheEvictionRequestorPtr = TSharedPtr; using FCacheEvictionRequestorWeakPtr = TWeakPtr; struct FCacheFlushRequest : FCacheEvictionRequestor { FInstallBundleSourceOrCache SourceOrCache; // Bundles are evicted from all caches, but we gather them from only this one if set ELogVerbosity::Type LogVerbosityOverride = ELogVerbosity::NoLogging; FInstallBundleManagerFlushCacheCompleteDelegate Callback; virtual FString GetEvictionRequestorName() const override { if (SourceOrCache.HasSubtype()) { return FString::Printf(TEXT("CacheFlush(%s)"), *SourceOrCache.GetSubtype().ToString()); } else if (SourceOrCache.HasSubtype()) { return FString::Printf(TEXT("CacheFlush(%s)"), LexToString(SourceOrCache.GetSubtype())); } else { return TEXT("CacheFlush(All)"); } } virtual ECacheEvictionRequestorType GetEvictionRequestorType() const override { return ECacheEvictionRequestorType::CacheFlush; } virtual ELogVerbosity::Type GetLogVerbosityOverride() const override { return LogVerbosityOverride; } }; using FCacheFlushRequestRef = TSharedRef; using FCacheFlushRequestPtr = TSharedPtr; using FCacheFlushRequestWeakPtr = TWeakPtr; struct FContentRequest : FCacheEvictionRequestor { ~FContentRequest(); EContentRequestStepResult StepResult = EContentRequestStepResult::Done; TArray Steps; int32 iStep = INDEX_NONE; TStaticArray iOnCanceledStep{ InPlace, INDEX_NONE }; TArray Prereqs; int32 iPrereq = INDEX_NONE; FDelegateHandle CheckLastestClientDelegateHandle; EInstallBundleRequestFlags Flags = EInstallBundleRequestFlags::None; ELogVerbosity::Type LogVerbosityOverride = ELogVerbosity::NoLogging; bool bShouldSendAnalytics = true; bool bIsCanceled = false; bool bFinishWhenCanceled = true; // Whether to run cleanup and callback when canceled bool bDidCacheHintRequested = false; // Whether this request hinted to the bundle caches that the bundle was requested bool bContentWasInstalled = false; EInstallBundleResult Result = EInstallBundleResult::OK; FName BundleName; TMap SourcePauseFlags; EInstallBundlePauseFlags LastSentPauseFlags = EInstallBundlePauseFlags::None; bool bForcePauseCallback = false; EInstallBundleCacheReserveResult LastCacheReserveResult = EInstallBundleCacheReserveResult::Success; // how many results we are expected to have in the SourceRequestResults array int RequiredSourceRequestResultsCount = 0; // completion results from each bundle source TMap SourceRequestResults; TArray> OnDemandMountArgs; FText OptionalErrorText; FString OptionalErrorCode; TMap CachedSourceProgress; InstallBundleUtil::FContentRequestSharedContextPtr RequestSharedContext; // If needed, Keep the engine awake while process requests TOptional KeepAwake; // If needed, Banish screen savers TOptional ScreenSaveControl; virtual FString GetEvictionRequestorName() const override { return BundleName.ToString(); } virtual ECacheEvictionRequestorType GetEvictionRequestorType() const override { return ECacheEvictionRequestorType::ContentRequest; } virtual ELogVerbosity::Type GetLogVerbosityOverride() const override { return LogVerbosityOverride; } }; using FContentRequestRef = TSharedRef; using FContentRequestPtr = TSharedPtr; using FContentRequestWeakPtr = TWeakPtr; enum class EContentReleaseRequestState : int { Unmounting, UpdatingBundleSources, Finishing, CleaningUp, Count }; friend const TCHAR* LexToString(EContentReleaseRequestState Val) { static const TCHAR* Strings[] = { TEXT("Unmounting"), TEXT("UpdatingBundleSources"), TEXT("Finishing"), TEXT("CleaningUp"), }; return InstallBundleUtil::TLexToString(Val, Strings); } struct FContentReleaseRequest { EContentRequestStepResult StepResult = EContentRequestStepResult::Done; TArray Steps; int32 iStep = INDEX_NONE; TStaticArray iOnCanceledStep{ InPlace, INDEX_NONE }; TArray Prereqs; int32 iPrereq = INDEX_NONE; EInstallBundleReleaseRequestFlags Flags = EInstallBundleReleaseRequestFlags::None; EInstallBundleReleaseResult Result = EInstallBundleReleaseResult::OK; FName BundleName; TMap> SourceReleaseRequestResults; TMap> SourceRemoveRequestResults; ELogVerbosity::Type LogVerbosityOverride = ELogVerbosity::NoLogging; bool bIsCanceled = false; bool bFinishWhenCanceled = true; // Whether to run cleanup and callback when canceled }; using FContentReleaseRequestRef = TSharedRef; using FContentReleaseRequestPtr = TSharedPtr; using FContentReleaseRequestWeakPtr = TWeakPtr; struct FContentPatchCheckSharedContext { TMap Results; }; using FContentPatchCheckSharedContextRef = TSharedRef; public: typedef TUniqueFunction(FInstallBundleSourceType)> FInstallBundleSourceFactoryFunction; UE_DEPRECATED(5.4, "GInstallBundleManagerIni is deprecated, use InstallBundle.ini hierarchy instead.") FDefaultInstallBundleManager(const TCHAR* InConfigBaseName, FInstallBundleSourceFactoryFunction InBundleSourceFactory = nullptr) : FDefaultInstallBundleManager(MoveTemp(InBundleSourceFactory)) {} UE_API FDefaultInstallBundleManager(FInstallBundleSourceFactoryFunction InBundleSourceFactory = nullptr); FDefaultInstallBundleManager(const FDefaultInstallBundleManager& Other) = delete; FDefaultInstallBundleManager& operator=(const FDefaultInstallBundleManager& Other) = delete; UE_API virtual ~FDefaultInstallBundleManager(); UE_API virtual void Initialize() override; //Tick protected: UE_API bool Tick(float dt); UE_API EInstallBundleManagerInitErrorHandlerResult HandleAsyncInitError(EInstallBundleManagerInitResult InitResultError); UE_API void TickInit(); UE_API void TickGetContentState(); UE_API void TickGetInstallState(); UE_API FInstallBundleCombinedInstallState GetInstallStateInternal(TArrayView BundleNames) const; UE_API void CacheHintRequested(FContentRequestRef Request, bool bRequested); UE_API void CheckPrereqHasNoPendingCancels(FContentRequestRef Request); UE_API void CheckPrereqHasNoPendingCancels(FContentReleaseRequestRef Request); UE_API void CheckPrereqHasNoPendingReleaseRequests(FContentRequestRef Request); UE_API void CheckPrereqHasNoPendingUpdateRequests(FContentReleaseRequestRef Request); UE_API void CheckPrereqLatestClient(FContentRequestRef Request); UE_API void HandlePatchInformationReceived(EInstallBundleManagerPatchCheckResult Result, FContentRequestRef Request); UE_API void DetermineSteps(FContentRequestRef Request); UE_API void DetermineSteps(FContentReleaseRequestRef Request); UE_API void AddRequestToInitialBatch(FContentRequestRef Request); UE_API void AddRequestToInitialBatch(FContentReleaseRequestRef Request); UE_API void ReserveCache(FContentRequestRef Request); UE_API void TryReserveCache(FContentRequestRef Request); UE_API void RequestEviction(FCacheEvictionRequestorRef Requestor); UE_API void CacheEvictionComplete(TSharedRef Source, FInstallBundleSourceReleaseContentResultInfo InResultInfo); UE_API void CacheEvictionComplete(TSharedRef Source, const FInstallBundleSourceReleaseContentResultInfo& InResultInfo, FCacheEvictionRequestorRef Requestor); UE_API void UpdateBundleSources(FContentRequestRef Request); UE_API void UpdateBundleSourceComplete(TSharedRef Source, FInstallBundleSourceUpdateContentResultInfo InResultInfo, FContentRequestRef Request); UE_API void UpdateBundleSourcePause(TSharedRef Source, FInstallBundleSourcePauseInfo InPauseInfo, FContentRequestRef Request); UE_API void UpdateBundleSources(FContentReleaseRequestRef Request); UE_API void UpdateBundleSourceReleaseComplete(TSharedRef Source, FInstallBundleSourceReleaseContentResultInfo InResultInfo, FContentReleaseRequestRef Request); UE_API void MountPaks(FContentRequestRef Request); static UE_API bool MountPaksInList(TArrayView> Paths, TValueOrError& OutResult, ELogVerbosity::Type LogVerbosityOverride); UE_API void UnmountPaks(FContentReleaseRequestRef Request); UE_API virtual bool AllowIoStoreOnDemandMount(FContentRequestRef Request, const FBundleInfo& BundleInfo); UE_API virtual TArray> GetPakMountList(FContentRequestRef Request, const FBundleInfo& BundleInfo); virtual void OnPaksMountedInternal(FContentRequestRef Request, FBundleInfo& BundleInfo) {} virtual void OnPaksUnmountedInternal(FContentReleaseRequestRef Request, FBundleInfo& BundleInfo) {}; UE_API void WaitForShaderCache(FContentRequestRef Request); UE_API void FinishRequest(FContentRequestRef Request); UE_API void FinishRequest(FContentReleaseRequestRef Request); UE_API void TickUpdatePrereqs(); UE_API void TickReleasePrereqs(); UE_API void TickContentRequests(); UE_API void TickReserveCache(); UE_API void TickCacheFlush(); UE_API void TickWaitForShaderCache(); UE_API void TickPauseStatus(bool bForceCallback); UE_API void TickAsyncMountTasks(); UE_API void TickReleaseRequests(); UE_API void TickPruneBundleInfo(); UE_API void IterateContentRequests(TFunctionRef OnFound); UE_API void IterateReleaseRequests(TFunctionRef OnFound); UE_API void IterateContentRequestsForBundle(FName BundleName, TFunctionRef OnFound); UE_API void IterateReleaseRequestsForBundle(FName BundleName, TFunctionRef OnFound); UE_API TSet GetBundleDependencies(FName InBundleName, bool* bSkippedUnknownBundles = nullptr) const; UE_API TSet GetBundleDependencies(TArrayView InBundleNames, bool* bSkippedUnknownBundles = nullptr) const; UE_API TSet GatherBundlesForRequest(TArrayView InBundleNames, EInstallBundleRequestInfoFlags& OutFlags); UE_API TSet GatherBundlesForRequest(TArrayView InBundleNames); UE_API FInstallBundleSourceType GetBundleSourceFallback(FInstallBundleSourceType Type) const; UE_API EInstallBundleSourceUpdateBundleInfoResult OnUpdateBundleInfoFromSource(TSharedRef Source, FInstallBundleSourceUpdateBundleInfoResult Result); UE_API void OnBundleLostRelevanceForSource(TSharedRef Source, TSet BundleNames); UE_API void StartClientPatchCheck(); UE_API void StartContentPatchCheck(); UE_API void HandleClientPatchCheck(EPatchCheckResult Result); UE_API void HandleBundleSourceContentPatchCheck(TSharedRef Source, bool bContentPatchRequired, FContentPatchCheckSharedContextRef Context); UE_API void HandleContentPatchCheck(FContentPatchCheckSharedContextRef Context); UE_API bool CancelUpdateContentInternal(TArrayView BundleNames); UE_API bool CancelReleaseContentInternal(TArrayView BundleNames); // IInstallBundleManager interface public: UE_API virtual bool HasBundleSource(FInstallBundleSourceType SourceType) const override; UE_API virtual const TSharedPtr GetBundleSource(FInstallBundleSourceType SourceType) const override; UE_API virtual FDelegateHandle PushInitErrorCallback(FInstallBundleManagerInitErrorHandler Callback) override; UE_API virtual void PopInitErrorCallback() override; UE_API virtual void PopInitErrorCallback(FDelegateHandle Handle) override; UE_API virtual void PopInitErrorCallback(FDelegateUserObjectConst InUserObject) override; UE_API virtual EInstallBundleManagerInitState GetInitState() const override; UE_API virtual TValueOrError RequestUpdateContent(TArrayView InBundleNames, EInstallBundleRequestFlags Flags, ELogVerbosity::Type LogVerbosityOverride = ELogVerbosity::NoLogging, InstallBundleUtil::FContentRequestSharedContextPtr RequestSharedContext = nullptr) override; UE_API virtual FDelegateHandle GetContentState(TArrayView InBundleNames, EInstallBundleGetContentStateFlags Flags, bool bAddDependencies, FInstallBundleGetContentStateDelegate Callback, FName RequestTag = TEXT("None")) override; UE_API virtual void CancelAllGetContentStateRequestsForTag(FName RequestTag) override; UE_API virtual void CancelAllGetContentStateRequests(FDelegateHandle Handle) override; UE_API virtual FDelegateHandle GetInstallState(TArrayView BundleNames, bool bAddDependencies, FInstallBundleGetInstallStateDelegate Callback, FName RequestTag = NAME_None) override; UE_API virtual TValueOrError GetInstallStateSynchronous(TArrayView BundleNames, bool bAddDependencies) const override; UE_API virtual void CancelAllGetInstallStateRequestsForTag(FName RequestTag) override; UE_API virtual void CancelAllGetInstallStateRequests(FDelegateHandle Handle) override; UE_API virtual TValueOrError RequestReleaseContent(TArrayView ReleaseNames, EInstallBundleReleaseRequestFlags Flags, TArrayView KeepNames = TArrayView(), ELogVerbosity::Type LogVerbosityOverride = ELogVerbosity::NoLogging) override; UE_API virtual EInstallBundleResult FlushCache(FInstallBundleSourceOrCache SourceOrCache, FInstallBundleManagerFlushCacheCompleteDelegate Callback, ELogVerbosity::Type LogVerbosityOverride = ELogVerbosity::NoLogging) override; UE_API virtual TArray GetCacheStats(EInstallBundleCacheStatsFlags Flags = EInstallBundleCacheStatsFlags::None, ELogVerbosity::Type LogVerbosityOverride = ELogVerbosity::NoLogging) override; UE_API virtual TOptional GetCacheStats(FInstallBundleSourceOrCache SourceOrCache, EInstallBundleCacheStatsFlags Flags = EInstallBundleCacheStatsFlags::None, ELogVerbosity::Type LogVerbosityOverride = ELogVerbosity::NoLogging) override; UE_API virtual void RequestRemoveContentOnNextInit(TArrayView RemoveNames, TArrayView KeepNames = TArrayView()) override; UE_API virtual void CancelRequestRemoveContentOnNextInit(TArrayView BundleName) override; UE_API virtual TArray GetRequestedRemoveContentOnNextInit() const override; UE_API virtual void CancelUpdateContent(TArrayView BundleNames) override; UE_API virtual void PauseUpdateContent(TArrayView BundleNames) override; UE_API virtual void ResumeUpdateContent(TArrayView BundleNames) override; UE_API virtual void RequestPausedBundleCallback() override; UE_API virtual TOptional GetBundleProgress(FName BundleName) const override; UE_API virtual EInstallBundleRequestFlags GetModifyableContentRequestFlags() const override; UE_API virtual void UpdateContentRequestFlags(TArrayView BundleNames, EInstallBundleRequestFlags AddFlags, EInstallBundleRequestFlags RemoveFlags) override; UE_API virtual void SetCellularPreference(int32 Value) override; UE_API virtual void SetCacheSize(FName CacheName, uint64 CacheSize) override; UE_API virtual void StartPatchCheck() override; UE_API virtual void AddEnvironmentWantsPatchCheckBackCompatDelegate(FName Tag, FInstallBundleManagerEnvironmentWantsPatchCheck Delegate) override; UE_API virtual void RemoveEnvironmentWantsPatchCheckBackCompatDelegate(FName Tag) override; UE_API virtual bool SupportsEarlyStartupPatching() const override; UE_API virtual bool IsNullInterface() const override; UE_API virtual void SetErrorSimulationCommands(const FString& CommandLine) override; //For overrides that we need to handle even when in a shipping build UE_API void SetCommandLineOverrides(const FString& CommandLine); UE_API virtual TSharedPtr GetAnalyticsProvider() const override; UE_API virtual void StartSessionPersistentStatTracking(const FString& SessionName, const TArray& RequiredBundles = TArray(), const FString& ExpectedAnalyticsID = FString(), bool bForceResetStatData = false, const FInstallBundleCombinedContentState* State = nullptr) override; UE_API virtual void StopSessionPersistentStatTracking(const FString& SessionName) override; #if !UE_BUILD_SHIPPING UE_API virtual void GetDebugText(TArray& Output) override; #endif virtual bool HasEverUpdatedContent() const { return bHasEverUpdatedContent; } protected: //Special version of these to wrap our calls to PersistentStats UE_API void StartBundlePersistentStatTracking(TSharedRef ContentRequest, const FString& ExpectedAnalyticsID = FString(), bool bForceResetStatData = false); UE_API void StopBundlePersistentStatTracking(TSharedRef ContentRequest); UE_API void PersistentTimingStatsBegin(TSharedRef ContentRequest, InstallBundleUtil::PersistentStats::ETimingStatNames TimerStatName); UE_API void PersistentTimingStatsEnd(TSharedRef ContentRequest, InstallBundleUtil::PersistentStats::ETimingStatNames TimerStatName); UE_API TArray> GetEnabledBundleSourcesForRequest(FContentRequestRef Request) const; UE_API virtual TArray> GetEnabledBundleSourcesForRequest(const FBundleInfo& BundleInfo) const; // Initialization state machine protected: UE_API EInstallBundleManagerInitResult Init_DefaultBundleSources(); UE_API EInstallBundleManagerInitResult Init_TryCreateBundleSources(TArray SourcesToCreate, TArray>* OutNewSources = nullptr); UE_API FInstallBundleSourceType FindFallbackSource(FInstallBundleSourceType SourceType); UE_API void AsyncInit_InitBundleSources(); UE_API void AsyncInit_OnBundleSourceInitComplete(TSharedRef Source, FInstallBundleSourceAsyncInitInfo InInitInfo); UE_API void AsyncInit_InitBundleCaches(); UE_API void AsyncInit_QueryBundleInfo(); UE_API void AsyncInit_OnQueryBundleInfoComplete(TSharedRef Source, FInstallBundleSourceBundleInfoQueryResult Result); UE_API void AsyncInit_OnQueryBundleInfoComplete_HandleClientPatchCheck(EPatchCheckResult Result); UE_API void AsyncInit_SetUpdateBundleInfoCallback(); UE_API void AsyncInit_CreateAnalyticsSession(); UE_API void AsyncInit_FireInitAnlaytic(bool bCanRetry); UE_API void StatsBegin(FName BundleName); UE_API void StatsEnd(FName BundleName); UE_API void StatsBegin(FName BundleName, EContentRequestState State); UE_API void StatsEnd(FName BundleName, EContentRequestState State, uint64 DataSize = 0); UE_API void LogStats(FName BundleName, ELogVerbosity::Type LogVerbosityOverride); protected: FTSTicker::FDelegateHandle TickHandle; FDelegateHandle AsyncInit_PatchCheckHandle; FDelegateHandle PatchCheckHandle; UE::IoStore::IOnDemandIoStore* OnDemandIoStore = nullptr; FInstallBundleSourceFactoryFunction InstallBundleSourceFactory; TMap BundleInfoMap; TSet BundlesInfosToPrune; TMap> BundleSources; TMap BundleSourceFallbacks; TMap> BundleCaches; TMap BundleSourceCaches; TMap BundleCacheSizeOverrides; TMap, TArray> PendingCacheEvictions; // (Source, Bundle) -> List of requestors TMap, TArray> CachesPendingEvictToSources; // (Cache, Bundle) -> List of Sources // Only used during Init TMap> BundleSourceInitResults; TMap BundleSourceBundleInfoQueryResults; // Init EInstallBundleManagerInitState InitState = EInstallBundleManagerInitState::NotInitialized; EInstallBundleManagerInitResult InitResult = EInstallBundleManagerInitResult::OK; TArray InitErrorHandlerStack; TArray> BundleSourcesToDelete; EAsyncInitStep InitStep = EAsyncInitStep::None; EAsyncInitStep LastInitStep = EAsyncInitStep::None; EAsyncInitStepResult InitStepResult = EAsyncInitStepResult::Done; bool bUnrecoverableInitError = false; bool bIsCurrentlyInAsyncInit = false; double LastInitRetryTimeSeconds = 0.0; double InitRetryTimeDeltaSeconds = 0.0; // Content State Requests TArray GetContentStateRequests; TArray GetInstallStateRequests; // Content Requests TArray ContentRequests[EContentRequestBatch::Count]; // Content Release Requests TArray ContentReleaseRequests[EContentReleaseRequestBatch::Count]; // Cache Flush Requests TArray CacheFlushRequests; TSharedRef PersistentStats; TArray> AsyncMountTasks; bool bIsCheckingForPatch = false; bool bDelayCheckingForContentPatch = false; #if INSTALL_BUNDLE_ALLOW_ERROR_SIMULATION // Error Simulation bool bSimulateClientNotLatest = false; bool bSimulateContentNotLatest = false; #endif // INSTALL_BUNDLE_ALLOW_ERROR_SIMULATION //Not included in INSTALL_BUNDLE_ALLOW_ERROR_SIMULATION as we want to provide //this functionality even on ship builds bool bOverrideCommand_SkipPatchCheck = false; bool bHasEverUpdatedContent = false; protected: // Analytics TSharedPtr AnalyticsProvider; TSharedRef StatsMap; }; ENUM_RANGE_BY_COUNT(FDefaultInstallBundleManager::EContentRequestBatch, FDefaultInstallBundleManager::EContentRequestBatch::Count); DEFAULTINSTALLBUNDLEMANAGER_API const TCHAR* LexToString(FDefaultInstallBundleManager::EContentRequestBatch Val); ENUM_RANGE_BY_COUNT(FDefaultInstallBundleManager::EContentReleaseRequestBatch, FDefaultInstallBundleManager::EContentReleaseRequestBatch::Count); DEFAULTINSTALLBUNDLEMANAGER_API const TCHAR* LexToString(FDefaultInstallBundleManager::EContentReleaseRequestBatch Val); #undef UE_API