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

Code before:

        if (file_offset_of_buffer_end > *read_until_position)
        {
            /// Avoid race condition on impl->getInfoForLog().
            if (prefetch_future.valid())
                prefetch_future.wait();
            throw Exception(
                ErrorCodes::LOGICAL_ERROR,
                "Read beyond last offset ({} > {}): file size = {}, info: {}",
                file_offset_of_buffer_end, *read_until_position, getFileSize(), impl->getInfoForLog());
        }
    }

    return true;
}

std::future<IAsynchronousReader::Result> AsynchronousBoundedReadBuffer::readAsync(char * data, size_t size, Priority priority)
{
    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.priority = Priority{read_settings.priority.value + priority.value};
    request.ignore = bytes_to_ignore;
    request.use_page_cache = use_page_cache;
    return reader.submit(request);
}

IAsynchronousReader::Result AsynchronousBoundedReadBuffer::readSync(char * data, size_t size)
{
    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;
    request.use_page_cache = use_page_cache;
    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;

Review comment (performance):
May be avoid adding flag `use_page_cache` in `request`? As we pass `impl` (== `CachedInMemoryReadBufferFromFile`) to `ThreadPoolRemoteFSReader`, so we can figure it out there? I do not have a strong opinion here, but it seems better to avoid exposure of underlying `impl` buffer implementation as much as possible (and explicit `use_page_cache` flag does expose it quite a bit 🫠).

Code after:
    if (read_until_position)
    {
        if (file_offset_of_buffer_end == *read_until_position) /// Everything is already read.
            return false;

        if (file_offset_of_buffer_end > *read_until_position)
        {
            /// Avoid race condition on impl->getInfoForLog().
            if (prefetch_future.valid())
                prefetch_future.wait();
            throw Exception(
                ErrorCodes::LOGICAL_ERROR,
                "Read beyond last offset ({} > {}): file size = {}, info: {}",
                file_offset_of_buffer_end, *read_until_position, getFileSize(), impl->getInfoForLog());
        }
    }

    return true;
}

std::future<IAsynchronousReader::Result> AsynchronousBoundedReadBuffer::readAsync(char * data, size_t size, Priority priority)
{
    if (use_page_cache)
        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.priority = Priority{read_settings.priority.value + priority.value};
    request.ignore = bytes_to_ignore;
    return reader.submit(request);
}

IAsynchronousReader::Result AsynchronousBoundedReadBuffer::readSync(char * data, size_t size)
{
    if (use_page_cache)
        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);
}