1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
|
// Copyright Epic Games, Inc. All Rights Reserved.
#include <zenutil/bufferedopenfile.h>
#include <zencore/scopeguard.h>
#include <zencore/trace.h>
namespace zen {
BufferedOpenFile::BufferedOpenFile(const std::filesystem::path Path,
std::atomic<uint64_t>& OpenReadCount,
std::atomic<uint64_t>& CurrentOpenFileCount,
std::atomic<uint64_t>& ReadCount,
std::atomic<uint64_t>& ReadByteCount)
: m_Source(Path, BasicFile::Mode::kRead)
, m_SourceSize(m_Source.FileSize())
, m_OpenReadCount(OpenReadCount)
, m_CurrentOpenFileCount(CurrentOpenFileCount)
, m_ReadCount(ReadCount)
, m_ReadByteCount(ReadByteCount)
{
m_OpenReadCount++;
m_CurrentOpenFileCount++;
}
BufferedOpenFile::~BufferedOpenFile()
{
m_CurrentOpenFileCount--;
}
CompositeBuffer
BufferedOpenFile::GetRange(uint64_t Offset, uint64_t Size)
{
ZEN_TRACE_CPU("BufferedOpenFile::GetRange");
ZEN_ASSERT((m_CacheBlockIndex == (uint64_t)-1) || m_Cache);
auto _ = MakeGuard([&]() { ZEN_ASSERT((m_CacheBlockIndex == (uint64_t)-1) || m_Cache); });
ZEN_ASSERT((Offset + Size) <= m_SourceSize);
const uint64_t BlockIndexStart = Offset / BlockSize;
const uint64_t BlockIndexEnd = (Offset + Size - 1) / BlockSize;
std::vector<SharedBuffer> BufferRanges;
BufferRanges.reserve(BlockIndexEnd - BlockIndexStart + 1);
uint64_t ReadOffset = Offset;
for (uint64_t BlockIndex = BlockIndexStart; BlockIndex <= BlockIndexEnd; BlockIndex++)
{
const uint64_t BlockStartOffset = BlockIndex * BlockSize;
if (m_CacheBlockIndex != BlockIndex)
{
uint64_t CacheSize = Min(BlockSize, m_SourceSize - BlockStartOffset);
ZEN_ASSERT(CacheSize > 0);
m_Cache = IoBuffer(CacheSize);
m_Source.Read(m_Cache.GetMutableView().GetData(), CacheSize, BlockStartOffset);
m_ReadCount++;
m_ReadByteCount += CacheSize;
m_CacheBlockIndex = BlockIndex;
}
const uint64_t BytesRead = ReadOffset - Offset;
ZEN_ASSERT(BlockStartOffset <= ReadOffset);
const uint64_t OffsetIntoBlock = ReadOffset - BlockStartOffset;
ZEN_ASSERT(OffsetIntoBlock < m_Cache.GetSize());
const uint64_t BlockBytes = Min(m_Cache.GetSize() - OffsetIntoBlock, Size - BytesRead);
BufferRanges.emplace_back(SharedBuffer(IoBuffer(m_Cache, OffsetIntoBlock, BlockBytes)));
ReadOffset += BlockBytes;
}
CompositeBuffer Result(std::move(BufferRanges));
ZEN_ASSERT(Result.GetSize() == Size);
return Result;
}
} // namespace zen
|