21 std::lock_guard lock{mMutex};
22 auto best = mFree.end();
23 for (
auto it = mFree.begin(); it != mFree.end(); ++it) {
24 if (it->capacity >=
size && (best == mFree.end() || it->capacity < best->capacity)) {
28 if (best != mFree.end()) {
29 auto buffer = std::move(*best);
38 return {std::make_unique_for_overwrite<uint8_t[]>(capacity), capacity};
43 std::lock_guard lock{mMutex};
44 mFree.push_back(std::move(
buffer));
45 if (mFree.size() > kMaxFree) {
57 for (
auto&
buffer : mBuffers) {
58 mPool->put(std::move(
buffer));
68 std::lock_guard lock{mMutex};
74 for (
auto const& branch :
tree.branches) {
75 for (
auto const& basket : branch.baskets) {
76 if (!basket.embedded) {
77 add(basket.seek, basket.nbytes);
83std::span<const uint8_t> ReadPlan::lookup(uint64_t
offset,
size_t length)
const
85 auto it = std::upper_bound(mChunks.begin(), mChunks.end(),
offset, [](uint64_t off, Chunk
const&
c) { return off < c.offset; });
86 if (it == mChunks.begin()) {
96void ReadPlan::fetchPending()
98 std::ranges::sort(mPending);
99 std::vector<Chunk> fetched;
105 if (!fetched.empty()) {
106 auto&
last = fetched.back();
107 auto lastEnd =
last.offset +
last.size;
108 auto next = std::lower_bound(mChunks.begin(), mChunks.end(), lastEnd, [](Chunk
const&
c, uint64_t off) { return c.offset < off; });
109 bool bridgesFetched = next != mChunks.end() && next->offset <
offset;
110 if (
offset <= lastEnd + mCoalesceGap && !bridgesFetched) {
120 if (fetched.empty()) {
126 for (
auto& chunk : fetched) {
129 auto buffer = mPool->get(total);
130 std::vector<ReadRequest> requests;
131 auto* at =
buffer.data.get();
132 for (
auto& chunk : fetched) {
135 requests.push_back({chunk.offset, chunk.size, chunk.data});
137 mBuffers.push_back(std::move(
buffer));
138 mSource->readvInto(requests);
139 mChunks.insert(mChunks.end(), fetched.begin(), fetched.end());
140 std::ranges::sort(mChunks, {}, &Chunk::offset);
145 std::lock_guard lock{mMutex};
147 if (
bytes.empty() && !mPending.empty()) {
156 std::lock_guard lock{mMutex};
157 if (!mPending.empty()) {
164 std::lock_guard lock{mMutex};
166 for (
auto const& chunk : mChunks) {
179 auto bytes = mSource->tryMap(off,
len);
187 mSource->readInto(off,
len,
dst);
195 mSource->readvInto(requests);
void readInto(uint64_t off, size_t len, void *dst) override
Throws IoError, or CorruptData when the range is past the end of the file.
void readvInto(std::span< ReadRequest > requests) override
PlannedByteSource(std::shared_ptr< ByteSource > source, std::shared_ptr< ReadPlan > plan)
std::span< const uint8_t > tryMap(uint64_t off, size_t len) override
A view of the bytes without copying them, if the backend can provide it.
Buffer get(size_t size)
The smallest free buffer of at least size bytes, or a new one.
void fetch()
Fetches the pending ranges now, rather than on the first find().
std::span< const uint8_t > find(uint64_t offset, size_t length)
ReadPlan(std::shared_ptr< ByteSource > source, Options const &options, std::shared_ptr< ReadBufferPool > pool=nullptr)
Without a pool, the plan allocates its own buffers.
void add(uint64_t offset, size_t length)
GLsizei GLsizei GLchar * source
GLuint GLsizei GLsizei * length
GLenum GLenum GLsizei len
std::unique_ptr< TTree > tree((TTree *) flIn.Get(std::string(o2::base::NameConf::CTFTREENAME).c_str()))