bool FBuildPatchAppManifest::VerifyAgainstDirectory( const FString& VerifyDirectory, TArray < FString >& OutDatedFiles, FBuildPatchFloatDelegate ProgressDelegate, FBuildPatchBoolRetDelegate ShouldPauseDelegate, double& TimeSpentPaused ) { bool bAllCorrect = true; OutDatedFiles.Empty(); TimeSpentPaused = 0; // Setup progress tracking double TotalBuildSizeDouble = GetBuildSize(); double ProcessedBytes = 0; struct FLocalProgress { double CurrentBuildPercentage; double CurrentFileWeight; FBuildPatchFloatDelegate ProgressDelegate; void PerFileProgress( float Progress ) { const double PercentComplete = CurrentBuildPercentage + ( Progress * CurrentFileWeight ); ProgressDelegate.ExecuteIfBound( PercentComplete ); } } LocalProgress; LocalProgress.CurrentBuildPercentage = 0; LocalProgress.ProgressDelegate = ProgressDelegate; // For all files in FileManifestList, check that they produce the correct SHA1 hash, adding any that don't to the list for( auto FileManifestIt = Data->FileManifestList.CreateConstIterator(); FileManifestIt && !FBuildPatchInstallError::HasFatalError(); ++FileManifestIt ) { // Pause if necessary const double PrePauseTime = FPlatformTime::Seconds(); double PostPauseTime = PrePauseTime; bool bShouldPause = ShouldPauseDelegate.IsBound() && ShouldPauseDelegate.Execute(); while( bShouldPause ) { FPlatformProcess::Sleep( 0.1f ); bShouldPause = ShouldPauseDelegate.Execute(); PostPauseTime = FPlatformTime::Seconds(); } // Count up pause time TimeSpentPaused += PostPauseTime - PrePauseTime; // Get file details and construct const FFileManifestData& FileManifest = *FileManifestIt; FString FullFilename = VerifyDirectory / FileManifest.Filename; const int64 CurrentFileSize = FileManifest.GetFileSize(); LocalProgress.CurrentFileWeight = CurrentFileSize / TotalBuildSizeDouble; const bool bSameFile = FBuildPatchUtils::VerifyFile(FullFilename, FileManifest.FileHash, FileManifest.FileHash, FBuildPatchFloatDelegate::CreateRaw(&LocalProgress, &FLocalProgress::PerFileProgress), ShouldPauseDelegate, TimeSpentPaused) != 0; ProcessedBytes += CurrentFileSize; LocalProgress.CurrentBuildPercentage = ProcessedBytes / TotalBuildSizeDouble; bAllCorrect &= bSameFile; if( !bSameFile ) { OutDatedFiles.Add( FileManifest.Filename ); } } return bAllCorrect && !FBuildPatchInstallError::HasFatalError(); }
uint8 FBuildPatchUtils::VerifyFile(const FString& FileToVerify, const FSHAHashData& Hash1, const FSHAHashData& Hash2, FBuildPatchFloatDelegate ProgressDelegate, FBuildPatchBoolRetDelegate ShouldPauseDelegate, double& TimeSpentPaused) { uint8 ReturnValue = 0; FArchive* FileReader = IFileManager::Get().CreateFileReader(*FileToVerify); ProgressDelegate.ExecuteIfBound(0.0f); if (FileReader != NULL) { FSHA1 HashState; FSHAHashData HashValue; const int64 FileSize = FileReader->TotalSize(); uint8* FileReadBuffer = new uint8[FileBufferSize]; while (!FileReader->AtEnd() && !FBuildPatchInstallError::HasFatalError()) { // Pause if necessary const double PrePauseTime = FPlatformTime::Seconds(); double PostPauseTime = PrePauseTime; bool bShouldPause = ShouldPauseDelegate.IsBound() && ShouldPauseDelegate.Execute(); while (bShouldPause && !FBuildPatchInstallError::HasFatalError()) { FPlatformProcess::Sleep(0.1f); bShouldPause = ShouldPauseDelegate.Execute(); PostPauseTime = FPlatformTime::Seconds(); } // Count up pause time TimeSpentPaused += PostPauseTime - PrePauseTime; // Read file and update hash state const int64 SizeLeft = FileSize - FileReader->Tell(); const uint32 ReadLen = FMath::Min< int64 >(FileBufferSize, SizeLeft); FileReader->Serialize(FileReadBuffer, ReadLen); HashState.Update(FileReadBuffer, ReadLen); const double FileSizeTemp = FileSize; const float Progress = 1.0f - ((SizeLeft - ReadLen) / FileSizeTemp); ProgressDelegate.ExecuteIfBound(Progress); } delete[] FileReadBuffer; HashState.Final(); HashState.GetHash(HashValue.Hash); ReturnValue = (HashValue == Hash1) ? 1 : (HashValue == Hash2) ? 2 : 0; if (ReturnValue == 0) { GLog->Logf(TEXT("BuildDataGenerator: Verify failed on %s"), *FPaths::GetCleanFilename(FileToVerify)); } FileReader->Close(); delete FileReader; } else { GLog->Logf(TEXT("BuildDataGenerator: ERROR VerifyFile cannot open %s"), *FileToVerify); } ProgressDelegate.ExecuteIfBound(1.0f); return ReturnValue; }
bool FBuildPatchVerificationImpl::VerfiyFileSize(const FString& BuildFile, double& TimeSpentPaused) { // Pause if necessary const double PrePauseTime = FPlatformTime::Seconds(); double PostPauseTime = PrePauseTime; bool bShouldPause = ShouldPauseDelegate.IsBound() && ShouldPauseDelegate.Execute(); while (bShouldPause && !FBuildPatchInstallError::HasFatalError()) { FPlatformProcess::Sleep(0.1f); bShouldPause = ShouldPauseDelegate.Execute(); PostPauseTime = FPlatformTime::Seconds(); } // Count up pause time TimeSpentPaused += PostPauseTime - PrePauseTime; PerFileProgress(0.0f); int64 FileSize = IFileManager::Get().FileSize(*SelectFullFilePath(BuildFile)); PerFileProgress(1.0f); return FileSize == Manifest->GetFileSize(BuildFile); }