| 525 | } |
| 526 | |
| 527 | size_t ReadWriteBufferFromHTTP::readBigAt(char * to, size_t n, size_t offset, const std::function<bool(size_t)> & progress_callback) const |
| 528 | { |
| 529 | /// Caller must have checked supportsReadAt(). |
| 530 | /// This ensures we've sent at least one HTTP request and populated current_uri. |
| 531 | chassert(file_info && file_info->seekable); |
| 532 | |
| 533 | size_t initial_n = n; |
| 534 | size_t total_bytes_copied = 0; |
| 535 | size_t bytes_copied = 0; |
| 536 | bool is_canceled = false; |
| 537 | |
| 538 | doWithRetries( |
| 539 | /*callable=*/ [&] () |
| 540 | { |
| 541 | auto range = HTTPRange{offset, offset + n - 1}; |
| 542 | |
| 543 | Poco::Net::HTTPResponse response; |
| 544 | auto result = callImpl(response, method, range, false); |
| 545 | |
| 546 | if (response.getStatus() != Poco::Net::HTTPResponse::HTTPStatus::HTTP_PARTIAL_CONTENT && |
| 547 | (offset != 0 || offset + n < *file_info->file_size)) |
| 548 | { |
| 549 | String explanation = fmt::format( |
| 550 | "When reading with readBigAt {}." |
| 551 | "Cannot read with range: [{}, {}] (response status: {}, reason: {}), will retry", |
| 552 | initial_uri.toString(), |
| 553 | *range.begin, *range.end, |
| 554 | toString(response.getStatus()), response.getReason()); |
| 555 | |
| 556 | throw HTTPException( |
| 557 | ErrorCodes::HTTP_RANGE_NOT_SATISFIABLE, |
| 558 | current_uri.toString(), |
| 559 | Poco::Net::HTTPResponse::HTTP_REQUESTED_RANGE_NOT_SATISFIABLE, |
| 560 | response.getReason(), |
| 561 | explanation); |
| 562 | } |
| 563 | |
| 564 | copyFromIStreamWithProgressCallback(*result.response_stream, to, n, progress_callback, &bytes_copied, &is_canceled); |
| 565 | |
| 566 | ProfileEvents::increment(ProfileEvents::ReadWriteBufferFromHTTPBytes, bytes_copied); |
| 567 | |
| 568 | offset += bytes_copied; |
| 569 | total_bytes_copied += bytes_copied; |
| 570 | to += bytes_copied; |
| 571 | n -= bytes_copied; |
| 572 | bytes_copied = 0; |
| 573 | }, |
| 574 | /*on_retry=*/ [&] () |
| 575 | { |
| 576 | ProfileEvents::increment(ProfileEvents::ReadWriteBufferFromHTTPBytes, bytes_copied); |
| 577 | |
| 578 | offset += bytes_copied; |
| 579 | total_bytes_copied += bytes_copied; |
| 580 | to += bytes_copied; |
| 581 | n -= bytes_copied; |
| 582 | bytes_copied = 0; |
| 583 | }); |
| 584 |
nothing calls this directly
no test coverage detected