| 418 | } |
| 419 | |
| 420 | void LocalFileSystem::readFromFile(FileInfo& fileInfo, void* buffer, uint64_t numBytes, |
| 421 | uint64_t position) const { |
| 422 | auto localFileInfo = fileInfo.constPtrCast<LocalFileInfo>(); |
| 423 | DASSERT(localFileInfo->getFileSize() >= position + numBytes); |
| 424 | auto outputBuffer = static_cast<uint8_t*>(buffer); |
| 425 | uint64_t remainingNumBytesToRead = numBytes; |
| 426 | uint64_t bufferOffset = 0; |
| 427 | // Keep reads below common OS syscall transfer limits. |
| 428 | constexpr uint64_t maxBytesToReadAtOnce = 1ull << 30; |
| 429 | while (remainingNumBytesToRead > 0) { |
| 430 | const auto numBytesToRead = (std::min)(remainingNumBytesToRead, maxBytesToReadAtOnce); |
| 431 | #if defined(_WIN32) |
| 432 | DWORD numBytesRead; |
| 433 | OVERLAPPED overlapped = {}; |
| 434 | overlapped.Offset = position & 0xffffffff; |
| 435 | overlapped.OffsetHigh = position >> 32; |
| 436 | if (!ReadFile((HANDLE)localFileInfo->handle, outputBuffer + bufferOffset, numBytesToRead, |
| 437 | &numBytesRead, &overlapped)) { |
| 438 | auto error = GetLastError(); |
| 439 | throw IOException( |
| 440 | std::format("Cannot read from file: {} handle: {} " |
| 441 | "numBytesRead: {} numBytesToRead: {} position: {}. Error {}: {}", |
| 442 | fileInfo.path, (intptr_t)localFileInfo->handle, numBytesRead, numBytesToRead, |
| 443 | position, error, std::system_category().message(error))); |
| 444 | } |
| 445 | if (numBytesRead != numBytesToRead && fileInfo.getFileSize() != position + numBytesRead) { |
| 446 | throw IOException(std::format("Cannot read from file: {} handle: {} " |
| 447 | "numBytesRead: {} numBytesToRead: {} position: {}", |
| 448 | fileInfo.path, (intptr_t)localFileInfo->handle, numBytesRead, numBytesToRead, |
| 449 | position)); |
| 450 | } |
| 451 | #else |
| 452 | auto numBytesRead = |
| 453 | pread(localFileInfo->fd, outputBuffer + bufferOffset, numBytesToRead, position); |
| 454 | if (numBytesRead < 0) { |
| 455 | // LCOV_EXCL_START |
| 456 | throw IOException(std::format("Cannot read from file: {} fileDescriptor: {} " |
| 457 | "numBytesRead: {} numBytesToRead: {} position: {}", |
| 458 | fileInfo.path, localFileInfo->fd, numBytesRead, numBytesToRead, position)); |
| 459 | // LCOV_EXCL_STOP |
| 460 | } |
| 461 | if (static_cast<uint64_t>(numBytesRead) != numBytesToRead && |
| 462 | localFileInfo->getFileSize() != position + numBytesRead) { |
| 463 | // LCOV_EXCL_START |
| 464 | throw IOException(std::format("Cannot read from file: {} fileDescriptor: {} " |
| 465 | "numBytesRead: {} numBytesToRead: {} position: {}", |
| 466 | fileInfo.path, localFileInfo->fd, numBytesRead, numBytesToRead, position)); |
| 467 | // LCOV_EXCL_STOP |
| 468 | } |
| 469 | #endif |
| 470 | if (numBytesRead == 0) { |
| 471 | break; |
| 472 | } |
| 473 | remainingNumBytesToRead -= numBytesRead; |
| 474 | position += numBytesRead; |
| 475 | bufferOffset += numBytesRead; |
| 476 | } |
| 477 | } |
nothing calls this directly
no test coverage detected