Repository: ClickHouse/ClickHouse
File: src/Disks/IO/AsynchronousBoundedReadBuffer.cpp (C++)

Code before:
}

void AsynchronousBoundedReadBuffer::prefetch(Priority priority)
{
    if (prefetch_future.valid())
        return;

    if (!hasPendingDataToRead())
        return;

    last_prefetch_info.submit_time = std::chrono::system_clock::now();
    last_prefetch_info.priority = priority;

    if (!use_page_cache)
        prefetch_buffer.resize(buffer_size);
    prefetch_future = readAsync(prefetch_buffer.data(), buffer_size, priority);
    ProfileEvents::increment(ProfileEvents::RemoteFSPrefetches);
}

void AsynchronousBoundedReadBuffer::setReadUntilPosition(size_t position)
{
    if (!read_until_position || position != *read_until_position)
    {
        if (position < file_offset_of_buffer_end)
        {
            /// file has been read beyond new read until position already
            if (available() >= file_offset_of_buffer_end - position)
            {
                /// new read until position is after the current position in the working buffer
                working_buffer.resize(working_buffer.size() - (file_offset_of_buffer_end - position));
                file_offset_of_buffer_end = position;
                pos = std::min(pos, working_buffer.end());
            }
            else
            {
                if (prefetch_future.valid())
                    prefetch_future.wait();
                /// new read until position is before the current position in the working buffer
                throw Exception(
                    ErrorCodes::LOGICAL_ERROR,
                    "Attempt to set read until position before already read data ({} > {}, info: {})",
                    position,
                    getPosition(),
                    impl->getInfoForLog());
            }
        }

        read_until_position = position;

        /// We must wait on future and reset the prefetch here, because otherwise there might be
        /// a race between reading the data in the threadpool and impl->setReadUntilPosition()

Review comment (performance):
Does this work on condition that we do not use `prefetch_buffer` and `memory` buffer in parallel? I mean if we start calling `prefetch()` at the end of each `nextImpl` (schedule to get the next data, while we did not get started with reading from just read data pointed to by `memory`) then it will not work with page cache?

Code after:
        chassert(data == nullptr);
    else
        chassert(data != nullptr);
    IAsynchronousReader::Request request;
    request.descriptor = std::make_shared<RemoteFSFileDescriptor>(*impl, async_read_counters);
    request.buf = data;
    request.size = size;
    request.offset = file_offset_of_buffer_end;
    request.ignore = bytes_to_ignore;
    return reader.execute(request);
}

void AsynchronousBoundedReadBuffer::prefetch(Priority priority)
{
    if (prefetch_future.valid())
        return;

    if (!hasPendingDataToRead())
        return;

    last_prefetch_info.submit_time = std::chrono::system_clock::now();
    last_prefetch_info.priority = priority;

    /// Don't allocate any buffers if page cache is in use, the cache has its own buffers (PageCacheCell).
    if (!use_page_cache)
        prefetch_buffer.resize(buffer_size);

    prefetch_future = readAsync(prefetch_buffer.data(), buffer_size, priority);
    ProfileEvents::increment(ProfileEvents::RemoteFSPrefetches);
}

void AsynchronousBoundedReadBuffer::setReadUntilPosition(size_t position)
{
    if (!read_until_position || position != *read_until_position)
    {
        if (position < file_offset_of_buffer_end)
        {
            /// file has been read beyond new read until position already
            if (available() >= file_offset_of_buffer_end - position)
            {
                /// new read until position is after the current position in the working buffer
                working_buffer.resize(working_buffer.size() - (file_offset_of_buffer_end - position));
                file_offset_of_buffer_end = position;
                pos = std::min(pos, working_buffer.end());
            }
            else
            {
                if (prefetch_future.valid())
                    prefetch_future.wait();
                /// new read until position is before the current position in the working buffer
                throw Exception(