5#include "Async/AsyncFileHandle.h" 
    6#include "Containers/Array.h" 
    7#include "Containers/Map.h" 
    8#include "Containers/StringConv.h" 
    9#include "Containers/UnrealString.h" 
   11#include "GenericPlatform/GenericPlatformFile.h" 
   12#include "HAL/CriticalSection.h" 
   13#include "HAL/PlatformCrt.h" 
   14#include "HAL/PlatformMisc.h" 
   15#include "HAL/PlatformProperties.h" 
   16#include "Misc/DataDrivenPlatformInfoRegistry.h" 
   17#include "Misc/DateTime.h" 
   18#include "Misc/Parse.h" 
   19#include "Misc/Paths.h" 
   21class FPlatformFileOpenLog;
 
   22class IAsyncReadFileHandle;
 
   23class IMappedFileHandle;
 
   27class FLoggingAsyncReadFileHandle final : 
public IAsyncReadFileHandle
 
   29    FPlatformFileOpenLog* Owner;
 
   31    IAsyncReadFileHandle* ActualRequest;
 
   33    FLoggingAsyncReadFileHandle(FPlatformFileOpenLog* InOwner, 
const TCHAR* InFilename, IAsyncReadFileHandle* InActualRequest)
 
   35        , Filename(InFilename)
 
   36        , ActualRequest(InActualRequest)
 
   39    ~FLoggingAsyncReadFileHandle()
 
   43    virtual IAsyncReadRequest* SizeRequest(FAsyncFileCallBack* CompleteCallback = 
nullptr) override
 
   45        return ActualRequest->SizeRequest(CompleteCallback);
 
   47    virtual IAsyncReadRequest* ReadRequest(int64 Offset, int64 BytesToRead, EAsyncIOPriorityAndFlags PriorityAndFlags = AIOP_Normal, FAsyncFileCallBack* CompleteCallback = 
nullptr, uint8* UserSuppliedMemory = 
nullptr) override;
 
   51class FPlatformFileOpenLog : 
public IPlatformFile
 
   55    IPlatformFile*          LowerLevel;
 
   56    FCriticalSection        CriticalSection;
 
   58    TMap<FString, int64>    FilenameAccessMap;
 
   59    TArray<IFileHandle*>    LogOutput;
 
   63    FPlatformFileOpenLog()
 
   69    virtual ~FPlatformFileOpenLog()
 
   74    using IPlatformFile::IterateDirectory;
 
   75    using IPlatformFile::IterateDirectoryRecursively;
 
   76    using IPlatformFile::IterateDirectoryStat;
 
   77    using IPlatformFile::IterateDirectoryStatRecursively;
 
   79    virtual bool ShouldBeUsed(IPlatformFile* Inner, 
const TCHAR* CmdLine) 
const override
 
   81        bool bResult = FParse::Param(CmdLine, TEXT(
"FileOpenLog")) || FParse::Param(CmdLine, TEXT(
"FilePackageOpenLog"));
 
   85    virtual bool Initialize(IPlatformFile* Inner, 
const TCHAR* CommandLineParam) override
 
   88        FString LogFileDirectory;
 
   91        FString OutputDirectoryBase;
 
   93        if (!FParse::Value(CommandLineParam, TEXT(
"FOOBASEDIR="), OutputDirectoryBase))
 
   95            if (FParse::Param(CommandLineParam, TEXT(
"FOOUSESAVEDDIR")))
 
   97                OutputDirectoryBase = FPaths::ProjectSavedDir();
 
  101                OutputDirectoryBase = FPlatformMisc::ProjectDir();
 
  105        if (FParse::Value(CommandLineParam, TEXT(
"TARGETPLATFORM="), PlatformStr))
 
  107            TArray<FString> PlatformNames;
 
  108            if (!(PlatformStr == TEXT(
"None") || PlatformStr == TEXT(
"All")))
 
  110                PlatformStr.ParseIntoArray(PlatformNames, TEXT(
"+"), 
true);
 
  113            for (int32 Platform = 0;Platform < PlatformNames.Num(); ++Platform)
 
  115                if (FDataDrivenPlatformInfoRegistry::GetPlatformInfo(PlatformNames[Platform]).bIsConfidential)
 
  117                    LogFileDirectory = FPaths::Combine(OutputDirectoryBase, TEXT(
"Platforms"), *PlatformNames[Platform], TEXT(
"Build"), TEXT(
"FileOpenOrder"));
 
  121                    LogFileDirectory = FPaths::Combine(OutputDirectoryBase, TEXT( 
"Build" ), *PlatformNames[Platform], TEXT(
"FileOpenOrder"));
 
  124                LogFilePath = FPaths::Combine( *LogFileDirectory, TEXT(
"EditorOpenOrder.log"));
 
  126                FString OrderSuffix = TEXT(
"");
 
  127                FParse::Value(CommandLineParam, TEXT(
"FooSuffix="), OrderSuffix);
 
  129                FString GameOpenOrderFileName = FString::Printf(TEXT(
"GameOpenOrder%s.log"), *OrderSuffix);
 
  130                LogFilePath = FPaths::Combine( *LogFileDirectory, *GameOpenOrderFileName);
 
  132                Inner->CreateDirectoryTree(*LogFileDirectory);
 
  133                auto* FileHandle = Inner->OpenWrite(*LogFilePath, 
false, 
false);
 
  136                    LogOutput.Add(FileHandle);
 
  142            if (FDataDrivenPlatformInfoRegistry::GetPlatformInfo(FPlatformProperties::IniPlatformName()).bIsConfidential)
 
  144                LogFileDirectory = FPaths::Combine(OutputDirectoryBase, TEXT(
"Platforms"), StringCast<TCHAR>(FPlatformProperties::PlatformName()).Get(), TEXT(
"Build"), TEXT(
"FileOpenOrder"));
 
  148                LogFileDirectory = FPaths::Combine(OutputDirectoryBase, TEXT(
"Build"), StringCast<TCHAR>(FPlatformProperties::PlatformName()).Get(), TEXT(
"FileOpenOrder"));
 
  151            LogFilePath = FPaths::Combine( *LogFileDirectory, TEXT(
"EditorOpenOrder.log"));
 
  153            LogFilePath = FPaths::Combine( *LogFileDirectory, TEXT(
"GameOpenOrder.log"));
 
  155            Inner->CreateDirectoryTree(*LogFileDirectory);
 
  156            auto* FileHandle = Inner->OpenWrite(*LogFilePath, 
false, 
false);
 
  159                LogOutput.Add(FileHandle);
 
  164    virtual IPlatformFile* GetLowerLevel() override
 
  168    virtual void SetLowerLevel(IPlatformFile* NewLowerLevel) override
 
  170        LowerLevel = NewLowerLevel;
 
  172    static const TCHAR* GetTypeName()
 
  174        return TEXT(
"FileOpenLog");
 
  176    virtual const TCHAR* GetName() 
const override
 
  178        return GetTypeName();
 
  180    virtual bool        FileExists(
const TCHAR* Filename) override
 
  182        return LowerLevel->FileExists(Filename);
 
  184    virtual int64       FileSize(
const TCHAR* Filename) override
 
  186        return LowerLevel->FileSize(Filename);
 
  188    virtual bool        DeleteFile(
const TCHAR* Filename) override
 
  190        return LowerLevel->DeleteFile(Filename);
 
  192    virtual bool        IsReadOnly(
const TCHAR* Filename) override
 
  194        return LowerLevel->IsReadOnly(Filename);
 
  196    virtual bool        MoveFile(
const TCHAR* To, 
const TCHAR* From) override
 
  198        return LowerLevel->MoveFile(To, From);
 
  200    virtual bool        SetReadOnly(
const TCHAR* Filename, 
bool bNewReadOnlyValue) override
 
  202        return LowerLevel->SetReadOnly(Filename, bNewReadOnlyValue);
 
  204    virtual FDateTime   GetTimeStamp(
const TCHAR* Filename) override
 
  206        return LowerLevel->GetTimeStamp(Filename);
 
  208    virtual void        SetTimeStamp(
const TCHAR* Filename, FDateTime DateTime) override
 
  210        LowerLevel->SetTimeStamp(Filename, DateTime);
 
  212    virtual FDateTime   GetAccessTimeStamp(
const TCHAR* Filename) override
 
  214        return LowerLevel->GetAccessTimeStamp(Filename);
 
  216    virtual FString GetFilenameOnDisk(
const TCHAR* Filename) override
 
  218        return LowerLevel->GetFilenameOnDisk(Filename);
 
  220    virtual IFileHandle*    OpenRead(
const TCHAR* Filename, 
bool bAllowWrite) override
 
  222        IFileHandle* Result = LowerLevel->OpenRead(Filename, bAllowWrite);
 
  225            AddToOpenLog(Filename);
 
  229    virtual IFileHandle*    OpenWrite(
const TCHAR* Filename, 
bool bAppend = 
false, 
bool bAllowRead = 
false) override
 
  231        return LowerLevel->OpenWrite(Filename, bAppend, bAllowRead);
 
  233    virtual bool        DirectoryExists(
const TCHAR* Directory) override
 
  235        return LowerLevel->DirectoryExists(Directory);
 
  237    virtual bool        CreateDirectory(
const TCHAR* Directory) override
 
  239        return LowerLevel->CreateDirectory(Directory);
 
  241    virtual bool        DeleteDirectory(
const TCHAR* Directory) override
 
  243        return LowerLevel->DeleteDirectory(Directory);
 
  245    virtual FFileStatData GetStatData(
const TCHAR* FilenameOrDirectory) override
 
  247        return LowerLevel->GetStatData(FilenameOrDirectory);
 
  249    virtual bool        IterateDirectory(
const TCHAR* Directory, IPlatformFile::FDirectoryVisitor& Visitor) override
 
  251        return LowerLevel->IterateDirectory( Directory, Visitor );
 
  253    virtual bool        IterateDirectoryRecursively(
const TCHAR* Directory, IPlatformFile::FDirectoryVisitor& Visitor) override
 
  255        return LowerLevel->IterateDirectoryRecursively( Directory, Visitor );
 
  257    virtual bool        IterateDirectoryStat(
const TCHAR* Directory, IPlatformFile::FDirectoryStatVisitor& Visitor) override
 
  259        return LowerLevel->IterateDirectoryStat( Directory, Visitor );
 
  261    virtual bool        IterateDirectoryStatRecursively(
const TCHAR* Directory, IPlatformFile::FDirectoryStatVisitor& Visitor) override
 
  263        return LowerLevel->IterateDirectoryStatRecursively( Directory, Visitor );
 
  265    virtual bool        DeleteDirectoryRecursively(
const TCHAR* Directory) override
 
  267        return LowerLevel->DeleteDirectoryRecursively( Directory );
 
  269    virtual bool        CopyFile(
const TCHAR* To, 
const TCHAR* From, EPlatformFileRead ReadFlags = EPlatformFileRead::None, EPlatformFileWrite WriteFlags = EPlatformFileWrite::None) override
 
  271        return LowerLevel->CopyFile( To, From, ReadFlags, WriteFlags);
 
  273    virtual bool        CreateDirectoryTree(
const TCHAR* Directory) override
 
  275        return LowerLevel->CreateDirectoryTree(Directory);
 
  277    virtual bool        CopyDirectoryTree(
const TCHAR* DestinationDirectory, 
const TCHAR* Source, 
bool bOverwriteAllExisting) override
 
  279        return LowerLevel->CopyDirectoryTree(DestinationDirectory, Source, bOverwriteAllExisting);
 
  281    virtual FString     ConvertToAbsolutePathForExternalAppForRead( 
const TCHAR* Filename ) override
 
  283        return LowerLevel->ConvertToAbsolutePathForExternalAppForRead(Filename);
 
  285    virtual FString     ConvertToAbsolutePathForExternalAppForWrite( 
const TCHAR* Filename ) override
 
  287        return LowerLevel->ConvertToAbsolutePathForExternalAppForWrite(Filename);
 
  289    virtual bool        SendMessageToServer(
const TCHAR* Message, IFileServerMessageHandler* Handler) override
 
  291        return LowerLevel->SendMessageToServer(Message, Handler);
 
  293    virtual IAsyncReadFileHandle* OpenAsyncRead(
const TCHAR* Filename) override
 
  296        return new FLoggingAsyncReadFileHandle(
this, Filename, LowerLevel->OpenAsyncRead(Filename));
 
  298    virtual IMappedFileHandle* OpenMapped(
const TCHAR* Filename) override
 
  300        return LowerLevel->OpenMapped(Filename);
 
  303    void AddToOpenLog(
const TCHAR* Filename)
 
  305        CriticalSection.Lock();
 
  306        if (FilenameAccessMap.Find(Filename) == 
nullptr)
 
  308            FilenameAccessMap.Emplace(Filename, ++OpenOrder);
 
  309            FString Text = FString::Printf(TEXT(
"\"%s\" %llu\n"), Filename, OpenOrder);
 
  310            for (
auto File = LogOutput.CreateIterator(); File; ++File)
 
  312                (*File)->Write((uint8*)StringCast<ANSICHAR>(*Text).Get(), Text.Len());
 
  315        CriticalSection.Unlock();
 
  318    void AddPackageToOpenLog(
const TCHAR* Filename)
 
  320        CriticalSection.Lock();
 
  321        if (FilenameAccessMap.Find(Filename) == 
nullptr)
 
  323            FilenameAccessMap.Emplace(Filename, ++OpenOrder);
 
  324            FString Text = FString::Printf(TEXT(
"\"%s\" %llu\n"), Filename, OpenOrder);
 
  325            for (
auto File = LogOutput.CreateIterator(); File; ++File)
 
  327                (*File)->Write((uint8*)StringCast<ANSICHAR>(*Text).Get(), Text.Len());
 
  330        CriticalSection.Unlock();
 
#define UE_BUILD_SHIPPING