2021-09-28 04:00:33 -04:00
// Copyright Epic Games, Inc. All Rights Reserved.
# include "FilePackageStore.h"
# include "IO/IoContainerId.h"
# include "Misc/CommandLine.h"
# include "IO/IoContainerHeader.h"
# include "Misc/ScopeRWLock.h"
# include "ProfilingDebugging/CountersTrace.h"
# include "Internationalization/PackageLocalizationManager.h"
2021-09-28 04:10:53 -04:00
# include "Misc/ScopeLock.h"
2022-01-19 18:28:42 -05:00
# include "Misc/PackageName.h"
2021-09-28 04:00:33 -04:00
//PRAGMA_DISABLE_OPTIMIZATION
2021-11-18 14:37:34 -05:00
DEFINE_LOG_CATEGORY_STATIC ( LogFilePackageStore , Log , All ) ;
2022-05-11 13:16:30 -04:00
namespace FilePackageStore
{
FStringView GetRootPathFromPackageName ( const FStringView Path )
{
FStringView RootPath ;
int32 SecondForwardSlash = INDEX_NONE ;
if ( ensure ( FStringView ( Path . GetData ( ) + 1 , Path . Len ( ) - 1 ) . FindChar ( TEXT ( ' / ' ) , SecondForwardSlash ) ) )
{
RootPath = FStringView ( Path . GetData ( ) , SecondForwardSlash + 2 ) ;
}
return RootPath ;
}
}
2022-06-01 02:12:33 -04:00
FFilePackageStoreBackend : : FFilePackageStoreBackend ( )
2021-09-28 04:00:33 -04:00
{
2022-01-19 18:28:42 -05:00
# if WITH_EDITOR
OnContentPathMountedDelegateHandle = FPackageName : : OnContentPathMounted ( ) . AddLambda ( [ this ] ( const FString & InAssetPath , const FString & InFilesystemPath )
{
{
FScopeLock _ ( & UncookedPackageRootsLock ) ;
2022-05-11 13:16:30 -04:00
PendingAddUncookedPackageRoots . Add ( InFilesystemPath ) ;
2022-01-19 18:28:42 -05:00
}
{
FWriteScopeLock _ ( EntriesLock ) ;
2022-09-02 11:15:53 -04:00
bNeedsUncookedPackagesUpdate = true ;
2022-01-19 18:28:42 -05:00
}
} ) ;
2022-05-11 13:16:30 -04:00
OnContentPathDismountedDelegateHandle = FPackageName : : OnContentPathDismounted ( ) . AddLambda ( [ this ] ( const FString & InAssetPath , const FString & InFilesystemPath )
{
{
FScopeLock _ ( & UncookedPackageRootsLock ) ;
PendingRemoveUncookedPackageRoots . Add ( InAssetPath ) ;
PendingAddUncookedPackageRoots . Remove ( InFilesystemPath ) ;
}
{
FWriteScopeLock _ ( EntriesLock ) ;
2022-09-02 11:15:53 -04:00
bNeedsUncookedPackagesUpdate = true ;
2022-05-11 13:16:30 -04:00
}
} ) ;
2022-01-19 18:28:42 -05:00
TArray < FString > RootPaths ;
FPackageName : : QueryRootContentPaths ( RootPaths ) ;
{
FScopeLock _ ( & UncookedPackageRootsLock ) ;
2022-05-11 13:16:30 -04:00
PendingAddUncookedPackageRoots . Append ( RootPaths ) ;
2022-01-19 18:28:42 -05:00
}
{
FWriteScopeLock _ ( EntriesLock ) ;
2022-09-02 11:15:53 -04:00
bNeedsUncookedPackagesUpdate = true ;
2022-01-19 18:28:42 -05:00
}
2022-05-11 13:16:30 -04:00
# endif //if WITH_EDITOR
2021-09-28 04:00:33 -04:00
}
2022-06-01 02:12:33 -04:00
FFilePackageStoreBackend : : ~ FFilePackageStoreBackend ( )
2021-09-28 04:00:33 -04:00
{
2022-06-01 02:12:33 -04:00
# if WITH_EDITOR
FPackageName : : OnContentPathMounted ( ) . Remove ( OnContentPathMountedDelegateHandle ) ;
FPackageName : : OnContentPathDismounted ( ) . Remove ( OnContentPathDismountedDelegateHandle ) ;
# endif
2021-09-28 04:00:33 -04:00
}
2022-06-01 02:12:33 -04:00
void FFilePackageStoreBackend : : BeginRead ( )
2021-09-28 04:00:33 -04:00
{
2022-06-01 02:12:33 -04:00
EntriesLock . ReadLock ( ) ;
2022-09-02 11:15:53 -04:00
if ( bNeedsContainerUpdate
# if WITH_EDITOR
| | bNeedsUncookedPackagesUpdate
# endif
)
2022-01-19 18:28:42 -05:00
{
2022-06-01 02:12:33 -04:00
Update ( ) ;
2022-01-19 18:28:42 -05:00
}
2021-09-28 04:00:33 -04:00
}
2022-06-01 02:12:33 -04:00
void FFilePackageStoreBackend : : EndRead ( )
2021-09-28 04:00:33 -04:00
{
2022-06-01 02:12:33 -04:00
EntriesLock . ReadUnlock ( ) ;
2021-09-28 04:00:33 -04:00
}
2022-06-01 02:12:33 -04:00
EPackageStoreEntryStatus FFilePackageStoreBackend : : GetPackageStoreEntry ( FPackageId PackageId , FPackageStoreEntry & OutPackageStoreEntry )
2021-09-28 04:00:33 -04:00
{
2022-01-19 18:28:42 -05:00
# if WITH_EDITOR
const FUncookedPackage * FindUncookedPackage = UncookedPackagesMap . Find ( PackageId ) ;
if ( FindUncookedPackage )
{
OutPackageStoreEntry . UncookedPackageName = FindUncookedPackage - > PackageName ;
OutPackageStoreEntry . UncookedPackageHeaderExtension = static_cast < uint8 > ( FindUncookedPackage - > HeaderExtension ) ;
return EPackageStoreEntryStatus : : Ok ;
}
# endif
2021-09-28 04:00:33 -04:00
const FFilePackageStoreEntry * FindEntry = StoreEntriesMap . FindRef ( PackageId ) ;
2021-10-12 21:21:22 -04:00
if ( FindEntry )
2021-09-28 04:00:33 -04:00
{
2021-10-12 21:21:22 -04:00
OutPackageStoreEntry . ExportInfo . ExportCount = FindEntry - > ExportCount ;
OutPackageStoreEntry . ExportInfo . ExportBundleCount = FindEntry - > ExportBundleCount ;
OutPackageStoreEntry . ImportedPackageIds = MakeArrayView ( FindEntry - > ImportedPackages . Data ( ) , FindEntry - > ImportedPackages . Num ( ) ) ;
OutPackageStoreEntry . ShaderMapHashes = MakeArrayView ( FindEntry - > ShaderMapHashes . Data ( ) , FindEntry - > ShaderMapHashes . Num ( ) ) ;
2022-04-25 07:37:07 -04:00
# if WITH_EDITOR
const FFilePackageStoreEntry * FindOptionalSegmentEntry = OptionalSegmentStoreEntriesMap . FindRef ( PackageId ) ;
if ( FindOptionalSegmentEntry )
{
OutPackageStoreEntry . OptionalSegmentExportInfo . ExportCount = FindOptionalSegmentEntry - > ExportCount ;
OutPackageStoreEntry . OptionalSegmentExportInfo . ExportBundleCount = FindOptionalSegmentEntry - > ExportBundleCount ;
OutPackageStoreEntry . OptionalSegmentImportedPackageIds = MakeArrayView ( FindOptionalSegmentEntry - > ImportedPackages . Data ( ) , FindOptionalSegmentEntry - > ImportedPackages . Num ( ) ) ;
}
# endif
2021-10-12 21:21:22 -04:00
return EPackageStoreEntryStatus : : Ok ;
}
2022-01-19 18:28:42 -05:00
return EPackageStoreEntryStatus : : Missing ;
2021-09-28 04:00:33 -04:00
}
2022-06-01 02:12:33 -04:00
bool FFilePackageStoreBackend : : GetPackageRedirectInfo ( FPackageId PackageId , FName & OutSourcePackageName , FPackageId & OutRedirectedToPackageId )
2021-09-28 04:00:33 -04:00
{
TTuple < FName , FPackageId > * FindRedirect = RedirectsPackageMap . Find ( PackageId ) ;
if ( FindRedirect )
{
OutSourcePackageName = FindRedirect - > Get < 0 > ( ) ;
OutRedirectedToPackageId = FindRedirect - > Get < 1 > ( ) ;
2021-11-18 14:37:34 -05:00
UE_LOG ( LogFilePackageStore , Verbose , TEXT ( " Redirecting from %s to 0x%llx " ) , * OutSourcePackageName . ToString ( ) , OutRedirectedToPackageId . Value ( ) ) ;
2021-09-28 04:00:33 -04:00
return true ;
}
2021-11-18 14:37:34 -05:00
const FName * FindLocalizedPackageSourceName = LocalizedPackages . Find ( PackageId ) ;
if ( FindLocalizedPackageSourceName )
2021-09-28 04:00:33 -04:00
{
2021-11-18 14:37:34 -05:00
FName LocalizedPackageName = FPackageLocalizationManager : : Get ( ) . FindLocalizedPackageName ( * FindLocalizedPackageSourceName ) ;
if ( ! LocalizedPackageName . IsNone ( ) )
{
FPackageId LocalizedPackageId = FPackageId : : FromName ( LocalizedPackageName ) ;
if ( StoreEntriesMap . Find ( LocalizedPackageId ) )
{
OutSourcePackageName = * FindLocalizedPackageSourceName ;
OutRedirectedToPackageId = LocalizedPackageId ;
UE_LOG ( LogFilePackageStore , Verbose , TEXT ( " Redirecting from localized package %s to 0x%llx " ) , * OutSourcePackageName . ToString ( ) , OutRedirectedToPackageId . Value ( ) ) ;
return true ;
}
}
2021-09-28 04:00:33 -04:00
}
2021-11-18 14:37:34 -05:00
return false ;
2021-09-28 04:00:33 -04:00
}
2022-06-01 02:12:33 -04:00
void FFilePackageStoreBackend : : Mount ( const FIoContainerHeader * ContainerHeader , uint32 Order )
2021-09-28 04:00:33 -04:00
{
LLM_SCOPE ( ELLMTag : : AsyncLoading ) ;
FWriteScopeLock _ ( EntriesLock ) ;
2022-04-25 07:37:07 -04:00
MountedContainers . Add ( { ContainerHeader , Order , NextSequence + + } ) ;
2021-09-28 04:00:33 -04:00
Algo : : Sort ( MountedContainers , [ ] ( const FMountedContainer & A , const FMountedContainer & B )
{
2022-04-25 07:37:07 -04:00
if ( A . Order = = B . Order )
{
2022-06-03 19:15:05 -04:00
return A . Sequence > B . Sequence ;
2022-04-25 07:37:07 -04:00
}
2022-06-03 19:15:05 -04:00
return A . Order > B . Order ;
2021-09-28 04:00:33 -04:00
} ) ;
2022-09-02 11:15:53 -04:00
bNeedsContainerUpdate = true ;
2021-09-28 04:00:33 -04:00
}
2022-06-01 02:12:33 -04:00
void FFilePackageStoreBackend : : Unmount ( const FIoContainerHeader * ContainerHeader )
2021-09-28 04:00:33 -04:00
{
FWriteScopeLock _ ( EntriesLock ) ;
for ( auto It = MountedContainers . CreateIterator ( ) ; It ; + + It )
{
if ( It - > ContainerHeader = = ContainerHeader )
{
It . RemoveCurrent ( ) ;
2022-09-02 11:15:53 -04:00
bNeedsContainerUpdate = true ;
2021-09-28 04:00:33 -04:00
return ;
}
}
}
2022-06-01 02:12:33 -04:00
void FFilePackageStoreBackend : : Update ( )
2021-09-28 04:00:33 -04:00
{
LLM_SCOPE ( ELLMTag : : AsyncLoading ) ;
TRACE_CPUPROFILER_EVENT_SCOPE ( UpdateFilePackageStore ) ;
FScopeLock Lock ( & UpdateLock ) ;
2022-09-02 11:15:53 -04:00
if ( bNeedsContainerUpdate )
2021-09-28 04:00:33 -04:00
{
2022-09-02 11:15:53 -04:00
StoreEntriesMap . Empty ( ) ;
LocalizedPackages . Empty ( ) ;
RedirectsPackageMap . Empty ( ) ;
2022-04-25 07:37:07 -04:00
# if WITH_EDITOR
2022-09-02 11:15:53 -04:00
OptionalSegmentStoreEntriesMap . Empty ( ) ;
2022-04-25 07:37:07 -04:00
# endif
2021-09-28 04:00:33 -04:00
2022-09-02 11:15:53 -04:00
uint32 TotalPackageCount = 0 ;
for ( const FMountedContainer & MountedContainer : MountedContainers )
2021-09-28 04:00:33 -04:00
{
2022-09-02 11:15:53 -04:00
TotalPackageCount + = MountedContainer . ContainerHeader - > PackageIds . Num ( ) ;
2021-09-28 04:00:33 -04:00
}
2022-09-02 11:15:53 -04:00
StoreEntriesMap . Reserve ( TotalPackageCount ) ;
for ( const FMountedContainer & MountedContainer : MountedContainers )
{
const FIoContainerHeader * ContainerHeader = MountedContainer . ContainerHeader ;
TArrayView < const FFilePackageStoreEntry > ContainerStoreEntries ( reinterpret_cast < const FFilePackageStoreEntry * > ( ContainerHeader - > StoreEntries . GetData ( ) ) , ContainerHeader - > PackageIds . Num ( ) ) ;
int32 Index = 0 ;
for ( const FFilePackageStoreEntry & StoreEntry : ContainerStoreEntries )
{
const FPackageId & PackageId = ContainerHeader - > PackageIds [ Index ] ;
check ( PackageId . IsValid ( ) ) ;
StoreEntriesMap . FindOrAdd ( PackageId , & StoreEntry ) ;
+ + Index ;
}
2022-04-25 07:37:07 -04:00
# if WITH_EDITOR
2022-09-02 11:15:53 -04:00
TArrayView < const FFilePackageStoreEntry > ContainerOptionalSegmentStoreEntries ( reinterpret_cast < const FFilePackageStoreEntry * > ( ContainerHeader - > OptionalSegmentStoreEntries . GetData ( ) ) , ContainerHeader - > OptionalSegmentPackageIds . Num ( ) ) ;
Index = 0 ;
for ( const FFilePackageStoreEntry & OptionalSegmentStoreEntry : ContainerOptionalSegmentStoreEntries )
{
const FPackageId & PackageId = ContainerHeader - > OptionalSegmentPackageIds [ Index ] ;
check ( PackageId . IsValid ( ) ) ;
OptionalSegmentStoreEntriesMap . FindOrAdd ( PackageId , & OptionalSegmentStoreEntry ) ;
+ + Index ;
}
2022-05-11 13:16:30 -04:00
# endif //if WITH_EDITOR
2022-04-25 07:37:07 -04:00
2022-09-02 11:15:53 -04:00
for ( const FIoContainerHeaderLocalizedPackage & LocalizedPackage : ContainerHeader - > LocalizedPackages )
2021-09-28 04:00:33 -04:00
{
2022-09-02 11:15:53 -04:00
FName & LocalizedPackageSourceName = LocalizedPackages . FindOrAdd ( LocalizedPackage . SourcePackageId ) ;
if ( LocalizedPackageSourceName . IsNone ( ) )
{
FDisplayNameEntryId NameEntry = ContainerHeader - > RedirectsNameMap [ LocalizedPackage . SourcePackageName . GetIndex ( ) ] ;
LocalizedPackageSourceName = NameEntry . ToName ( LocalizedPackage . SourcePackageName . GetNumber ( ) ) ;
}
2021-09-28 04:00:33 -04:00
}
2022-09-02 11:15:53 -04:00
for ( const FIoContainerHeaderPackageRedirect & Redirect : ContainerHeader - > PackageRedirects )
2022-06-03 19:15:05 -04:00
{
2022-09-02 11:15:53 -04:00
TTuple < FName , FPackageId > & RedirectEntry = RedirectsPackageMap . FindOrAdd ( Redirect . SourcePackageId ) ;
FName & SourcePackageName = RedirectEntry . Key ;
if ( SourcePackageName . IsNone ( ) )
{
FDisplayNameEntryId NameEntry = ContainerHeader - > RedirectsNameMap [ Redirect . SourcePackageName . GetIndex ( ) ] ;
SourcePackageName = NameEntry . ToName ( Redirect . SourcePackageName . GetNumber ( ) ) ;
RedirectEntry . Value = Redirect . TargetPackageId ;
}
2022-06-03 19:15:05 -04:00
}
2021-09-28 04:00:33 -04:00
}
2022-09-02 11:15:53 -04:00
bNeedsContainerUpdate = false ;
2021-09-28 04:00:33 -04:00
}
2022-01-19 18:28:42 -05:00
# if WITH_EDITOR
2022-09-02 11:15:53 -04:00
if ( bNeedsUncookedPackagesUpdate )
2022-01-19 18:28:42 -05:00
{
2022-09-02 11:15:53 -04:00
TRACE_CPUPROFILER_EVENT_SCOPE ( UpdateUncookedPackages ) ;
2022-01-19 18:28:42 -05:00
FScopeLock _ ( & UncookedPackageRootsLock ) ;
2022-05-11 13:16:30 -04:00
if ( ! PendingRemoveUncookedPackageRoots . IsEmpty ( ) )
2022-01-19 18:28:42 -05:00
{
2022-05-11 13:16:30 -04:00
UE_LOG ( LogFilePackageStore , Display , TEXT ( " Removing uncooked packages from %d old roots... " ) , PendingRemoveUncookedPackageRoots . Num ( ) ) ;
uint64 TotalRemovedCount = RemoveUncookedPackagesFromRoot ( PendingRemoveUncookedPackageRoots ) ;
PendingRemoveUncookedPackageRoots . Empty ( ) ;
UE_LOG ( LogFilePackageStore , Display , TEXT ( " Removed %lld uncooked packages " ) , TotalRemovedCount ) ;
}
if ( ! PendingAddUncookedPackageRoots . IsEmpty ( ) )
{
UE_LOG ( LogFilePackageStore , Display , TEXT ( " Adding uncooked packages from %d new roots... " ) , PendingAddUncookedPackageRoots . Num ( ) ) ;
uint64 TotalAddedCount = 0 ;
for ( const FString & RootPath : PendingAddUncookedPackageRoots )
2022-01-19 18:28:42 -05:00
{
TotalAddedCount + = AddUncookedPackagesFromRoot ( RootPath ) ;
}
2022-05-11 13:16:30 -04:00
PendingAddUncookedPackageRoots . Empty ( ) ;
UE_LOG ( LogFilePackageStore , Display , TEXT ( " Added %lld uncooked packages " ) , TotalAddedCount ) ;
2022-01-19 18:28:42 -05:00
}
2022-09-02 11:15:53 -04:00
bNeedsUncookedPackagesUpdate = false ;
2022-01-19 18:28:42 -05:00
}
2022-05-11 13:16:30 -04:00
# endif //if WITH_EDITOR
2021-09-28 04:00:33 -04:00
}
2022-01-19 18:28:42 -05:00
# if WITH_EDITOR
2022-06-01 02:12:33 -04:00
uint64 FFilePackageStoreBackend : : AddUncookedPackagesFromRoot ( const FString & RootPath )
2022-01-19 18:28:42 -05:00
{
2022-05-11 13:16:30 -04:00
uint64 Count = 0 ;
FPackageName : : IteratePackagesInDirectory ( RootPath , [ this , & RootPath , & Count ] ( const TCHAR * InPackageFileName ) - > bool
2022-01-19 18:28:42 -05:00
{
FPackagePath PackagePath = FPackagePath : : FromLocalPath ( InPackageFileName ) ;
FName PackageName = PackagePath . GetPackageFName ( ) ;
if ( ! PackageName . IsNone ( ) )
{
FPackageId PackageId = FPackageId : : FromName ( PackageName ) ;
FUncookedPackage & UncookedPackage = UncookedPackagesMap . FindOrAdd ( PackageId ) ;
UncookedPackage . PackageName = PackageName ;
UncookedPackage . HeaderExtension = PackagePath . GetHeaderExtension ( ) ;
2022-05-11 13:16:30 -04:00
+ + Count ;
2022-01-19 18:28:42 -05:00
}
return true ;
} ) ;
2022-05-11 13:16:30 -04:00
return Count ;
2022-01-19 18:28:42 -05:00
}
2022-05-11 13:16:30 -04:00
2022-06-01 02:12:33 -04:00
uint64 FFilePackageStoreBackend : : RemoveUncookedPackagesFromRoot ( const TSet < FString > & RootPaths )
2022-05-11 13:16:30 -04:00
{
uint64 Count = 0 ;
TMap < FPackageId , FUncookedPackage > RemainingUncookedPackagesMap ;
RemainingUncookedPackagesMap . Reserve ( UncookedPackagesMap . Num ( ) ) ;
for ( auto & Pair : UncookedPackagesMap )
{
const FNameBuilder PackageName ( Pair . Value . PackageName ) ;
const FStringView PackageRootPath = FilePackageStore : : GetRootPathFromPackageName ( PackageName ) ;
if ( RootPaths . ContainsByHash ( GetTypeHash ( PackageRootPath ) , PackageRootPath ) )
{
+ + Count ;
}
else
{
RemainingUncookedPackagesMap . Add ( Pair . Key , MoveTemp ( Pair . Value ) ) ;
}
}
UncookedPackagesMap = MoveTemp ( RemainingUncookedPackagesMap ) ;
return Count ;
}
# endif //if WITH_EDITOR
2022-01-19 18:28:42 -05:00
2021-09-28 04:00:33 -04:00
//PRAGMA_ENABLE_OPTIMIZATION