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