Files
UnrealEngine/Engine/Source/Runtime/Online/BuildPatchServices/Private/Installer/Statistics/VerifierStatistics.cpp
2025-05-18 13:04:45 +08:00

193 lines
6.3 KiB
C++

// Copyright Epic Games, Inc. All Rights Reserved.
#include "Installer/Statistics/VerifierStatistics.h"
#include "HAL/ThreadSafeBool.h"
#include "Core/AsyncHelpers.h"
#include "Common/SpeedRecorder.h"
#include "Common/StatsCollector.h"
#include "BuildPatchProgress.h"
#include "Installer/Statistics/FileOperationTracker.h"
#include "BuildPatchVerify.h"
namespace VerifierStatisticsHelpers
{
bool TryConvert(BuildPatchServices::EVerifyResult InResult, BuildPatchServices::EVerifyError& OutError)
{
using namespace BuildPatchServices;
switch (InResult)
{
case EVerifyResult::FileMissing: OutError = EVerifyError::FileMissing; return true;
case EVerifyResult::OpenFileFailed: OutError = EVerifyError::OpenFileFailed; return true;
case EVerifyResult::HashCheckFailed: OutError = EVerifyError::HashCheckFailed; return true;
case EVerifyResult::FileSizeFailed: OutError = EVerifyError::FileSizeFailed; return true;
}
return false;
}
}
namespace BuildPatchServices
{
class FVerifierStatistics
: public IVerifierStatistics
{
public:
FVerifierStatistics(ISpeedRecorder* SpeedRecorder, FBuildPatchProgress* BuildProgress, IFileOperationTracker* FileOperationTracker);
~FVerifierStatistics();
// IVerifierStat interface start.
virtual void OnFileStarted(const FString& Filename, int64 FileSize) override;
virtual void OnFileProgress(const FString& Filename, int64 TotalBytes) override;
virtual void OnFileCompleted(const FString& Filename, EVerifyResult VerifyResult) override;
virtual void OnFileRead(const ISpeedRecorder::FRecord& Record) override;
virtual void OnProcessedDataUpdated(int64 TotalBytes) override;
virtual void OnTotalRequiredUpdated(int64 TotalBytes) override;
// IVerifierStat interface end.
// IVerifierStatistics interface start.
virtual uint64 GetBytesVerified() const override;
virtual int32 GetNumSuccessfulFilesVerified() const override;
virtual int32 GetNumFailedFilesVerified() const override;
virtual TMap<EVerifyError, int32> GetVerifyErrorCounts() const override;
virtual bool IsCurrentlyReading() const override;
// IVerifierStatistics interface end.
private:
ISpeedRecorder* SpeedRecorder;
FBuildPatchProgress* BuildProgress;
IFileOperationTracker* FileOperationTracker;
FThreadSafeInt64 TotalBytesProcessed;
FThreadSafeInt64 TotalBytesRequired;
FThreadSafeInt64 TotalBytesRead;
FThreadSafeInt64 NumSuccessfulFilesVerified;
FThreadSafeInt64 NumFailedFilesVerified;
TMap<EVerifyError, FThreadSafeInt64> NumFileVerifyErrors;
FThreadSafeBool bIsReading;
FThreadSafeInt64 LastReadCycles;
uint64 LastByteRangeStateUpdate;
};
FVerifierStatistics::FVerifierStatistics(ISpeedRecorder* InSpeedRecorder, FBuildPatchProgress* InBuildProgress, IFileOperationTracker* InFileOperationTracker)
: SpeedRecorder(InSpeedRecorder)
, BuildProgress(InBuildProgress)
, FileOperationTracker(InFileOperationTracker)
, TotalBytesProcessed(0)
, TotalBytesRequired(0)
, TotalBytesRead(0)
, NumSuccessfulFilesVerified(0)
, NumFailedFilesVerified(0)
, bIsReading(false)
, LastReadCycles(0)
, LastByteRangeStateUpdate(0)
{
for (EVerifyError Error : TEnumRange<EVerifyError>())
{
NumFileVerifyErrors.Add(Error, 0);
}
}
FVerifierStatistics::~FVerifierStatistics()
{
}
void FVerifierStatistics::OnFileStarted(const FString& Filename, int64 FileSize)
{
bIsReading = true;
LastByteRangeStateUpdate = 0;
}
void FVerifierStatistics::OnFileProgress(const FString& Filename, int64 TotalBytes)
{
FileOperationTracker->OnFileByteRangeStateUpdate(Filename, FByteRange(LastByteRangeStateUpdate, TotalBytes), EFileOperationState::Verifying);
LastByteRangeStateUpdate = TotalBytes;
}
void FVerifierStatistics::OnFileCompleted(const FString& Filename, EVerifyResult VerifyResult)
{
const bool bSuccess = VerifyResult == EVerifyResult::Success;
if (bSuccess)
{
NumSuccessfulFilesVerified.Increment();
}
else
{
EVerifyError Error;
if (VerifierStatisticsHelpers::TryConvert(VerifyResult, Error))
{
NumFailedFilesVerified.Increment();
NumFileVerifyErrors[Error].Increment();
}
}
FileOperationTracker->OnFileStateUpdate(Filename, bSuccess ? EFileOperationState::VerifiedSuccess : EFileOperationState::VerifiedFail);
bIsReading = false;
LastReadCycles = FStatsCollector::GetCycles();
}
void FVerifierStatistics::OnFileRead(const ISpeedRecorder::FRecord& Record)
{
SpeedRecorder->AddRecord(Record);
TotalBytesRead.Add(Record.Size);
}
void FVerifierStatistics::OnProcessedDataUpdated(int64 TotalBytes)
{
TotalBytesProcessed.Set(TotalBytes);
int64 Required = TotalBytesRequired.GetValue();
if (Required > 0)
{
BuildProgress->SetStateProgress(EBuildPatchState::BuildVerification, (double)TotalBytes / (double)Required);
}
}
void FVerifierStatistics::OnTotalRequiredUpdated(int64 TotalBytes)
{
TotalBytesRequired.Set(TotalBytes);
int64 Processed = TotalBytesProcessed.GetValue();
if (TotalBytes > 0)
{
BuildProgress->SetStateProgress(EBuildPatchState::BuildVerification, (double)Processed / (double)TotalBytes);
}
}
uint64 FVerifierStatistics::GetBytesVerified() const
{
return TotalBytesRead.GetValue();
}
int32 FVerifierStatistics::GetNumSuccessfulFilesVerified() const
{
return NumSuccessfulFilesVerified.GetValue();
}
int32 FVerifierStatistics::GetNumFailedFilesVerified() const
{
return NumFailedFilesVerified.GetValue();
}
TMap<EVerifyError, int32> FVerifierStatistics::GetVerifyErrorCounts() const
{
TMap<EVerifyError, int32> ErrorResults;
for (const TPair<EVerifyError, FThreadSafeInt64>& ResultPair : NumFileVerifyErrors)
{
if (ResultPair.Value.GetValue() > 0)
{
ErrorResults.Add(ResultPair.Key, ResultPair.Value.GetValue());
}
}
return ErrorResults;
}
bool FVerifierStatistics::IsCurrentlyReading() const
{
const int64 CyclesSinceRead = FStatsCollector::GetCycles() - LastReadCycles.GetValue();
return bIsReading || FStatsCollector::CyclesToSeconds(CyclesSinceRead) < 0.05;
}
IVerifierStatistics* FVerifierStatisticsFactory::Create(ISpeedRecorder* SpeedRecorder, FBuildPatchProgress* BuildProgress, IFileOperationTracker* FileOperationTracker)
{
check(SpeedRecorder != nullptr);
check(BuildProgress != nullptr);
check(FileOperationTracker != nullptr);
return new FVerifierStatistics(SpeedRecorder, BuildProgress, FileOperationTracker);
}
};