Files
UnrealEngineUWP/Engine/Source/Developer/DerivedDataCache/Private/DerivedDataLegacyCacheStore.cpp
devin doucette 3725815687 DDC: Added ILegacyCacheStore and folded the key length limit into the new FLegacyCacheKey
This API adds a little bit of overhead but, in exchange:
- Offers a path to migrate to the new Value API.
- Offers a path to provide compression while falling back to the previous format.
- Offers a path to backends batching requests without consuming a worker thread.
- Avoids copying the value multiple times during async puts.

#rb Zousar.Shaker
#rnx
#preflight 61e0a32fed50181feb57c5d6

#ROBOMERGE-AUTHOR: devin.doucette
#ROBOMERGE-SOURCE: CL 18607028 in //UE5/Release-5.0/... via CL 18607056 via CL 18607101
#ROBOMERGE-BOT: UE5 (Release-Engine-Test -> Main) (v899-18417669)

[CL 18607126 by devin doucette in ue5-main branch]
2022-01-13 17:30:44 -05:00

87 lines
2.8 KiB
C++

// Copyright Epic Games, Inc. All Rights Reserved.
#include "DerivedDataLegacyCacheStore.h"
#include "Containers/StringConv.h"
#include "DerivedDataBackendInterface.h"
#include "Misc/Crc.h"
#include "Misc/SecureHash.h"
#include "Misc/StringBuilder.h"
#include "String/BytesToHex.h"
#include "String/Find.h"
namespace UE::DerivedData
{
FLegacyCacheKey::FLegacyCacheKey(const FStringView InFullKey, const int32 MaxKeyLength)
: FullKey(InFullKey)
{
if (InFullKey.Len() > MaxKeyLength)
{
const auto FullKeyUCS2 = StringCast<UCS2CHAR>(InFullKey.GetData(), InFullKey.Len());
const int32 FullKeyLength = FullKeyUCS2.Length();
const uint32 CRCofPayload(FCrc::MemCrc32(FullKeyUCS2.Get(), FullKeyLength * sizeof(UCS2CHAR)));
uint8 Hash[FSHA1::DigestSize];
FSHA1 HashState;
HashState.Update((const uint8*)&FullKeyLength, sizeof(int32));
HashState.Update((const uint8*)&CRCofPayload, sizeof(uint32));
HashState.Update((const uint8*)FullKeyUCS2.Get(), FullKeyLength * sizeof(UCS2CHAR));
HashState.Final();
HashState.GetHash(Hash);
TStringBuilder<128> ShortKeyBuilder;
ShortKeyBuilder << InFullKey.Left(MaxKeyLength - FSHA1::DigestSize * 2 - 2) << TEXT("__");
String::BytesToHex(Hash, ShortKeyBuilder);
check(ShortKeyBuilder.Len() == MaxKeyLength && ShortKeyBuilder.Len() > 0);
ShortKey = ShortKeyBuilder;
}
TStringBuilder<64> Bucket;
Bucket << TEXT("Legacy");
if (const int32 BucketEnd = String::FindFirstChar(InFullKey, TEXT('_')); BucketEnd != INDEX_NONE)
{
Bucket << InFullKey.Left(BucketEnd);
}
Key.Bucket = FCacheBucket(Bucket);
Key.Hash = FIoHash::HashBuffer(MakeMemoryView(FTCHARToUTF8(InFullKey)));
}
bool FLegacyCacheKey::ReadValueTrailer(FCompositeBuffer& Value) const
{
if (!ShortKey.IsEmpty())
{
TUtf8StringBuilder<256> FullKeyUtf8;
FullKeyUtf8 << FullKey;
const FMemoryView CompareKey(FullKeyUtf8.ToString(), (FullKeyUtf8.Len() + 1) * sizeof(UTF8CHAR));
if (Value.GetSize() < CompareKey.GetSize())
{
UE_LOG(LogDerivedDataCache, Display, TEXT("FLegacyCacheKey: Hash collision or short value for key %s."), *FullKey);
return false;
}
FUniqueBuffer CopyBuffer;
const uint64 KeyOffset = Value.GetSize() - CompareKey.GetSize();
const FMemoryView ValueKey = Value.ViewOrCopyRange(KeyOffset, CompareKey.GetSize(), CopyBuffer);
if (!CompareKey.EqualBytes(ValueKey))
{
UE_LOG(LogDerivedDataCache, Display, TEXT("FLegacyCacheKey: Hash collision for key %s."), *FullKey);
return false;
}
Value = Value.Mid(0, KeyOffset);
}
return true;
}
void FLegacyCacheKey::WriteValueTrailer(FCompositeBuffer& Value) const
{
if (!ShortKey.IsEmpty())
{
TUtf8StringBuilder<256> FullKeyUtf8;
FullKeyUtf8 << FullKey;
Value = FCompositeBuffer(Value, FSharedBuffer::Clone(FullKeyUtf8.ToString(), (FullKeyUtf8.Len() + 1) * sizeof(UTF8CHAR)));
}
}
} // UE::DerivedData