Skip to content

Commit b165c28

Browse files
Implement load_into for file data loader
Differential Revision: D61147536 Pull Request resolved: #4671
1 parent 3e0eb0f commit b165c28

File tree

2 files changed

+74
-41
lines changed

2 files changed

+74
-41
lines changed

extension/data_loader/file_data_loader.cpp

Lines changed: 68 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -49,7 +49,6 @@ static uint8_t* align_pointer(void* ptr, size_t alignment) {
4949
addr = (addr | (alignment - 1)) + 1;
5050
return reinterpret_cast<uint8_t*>(addr);
5151
}
52-
5352
} // namespace
5453

5554
FileDataLoader::~FileDataLoader() {
@@ -143,19 +142,6 @@ Result<FreeableBuffer> FileDataLoader::load(
143142
return FreeableBuffer(nullptr, 0, /*free_fn=*/nullptr);
144143
}
145144

146-
// Seek to the right place in the file.
147-
off_t seek_offset = ::lseek(fd_, offset, SEEK_SET);
148-
if (seek_offset != offset) {
149-
ET_LOG(
150-
Error,
151-
"Seeking %s to offset %zu returned %zd: %s",
152-
file_name_,
153-
offset,
154-
(ssize_t)seek_offset,
155-
strerror(errno));
156-
return Error::AccessFailed;
157-
}
158-
159145
// Allocate memory for the FreeableBuffer.
160146
size_t alloc_size = size;
161147
if (alignment_ > alignof(std::max_align_t)) {
@@ -187,9 +173,75 @@ Result<FreeableBuffer> FileDataLoader::load(
187173
buffer,
188174
alloc_size);
189175

176+
auto err = load_into(offset, size, segment_info, aligned_buffer);
177+
if (err != Error::Ok) {
178+
// Free `buffer`, which is what malloc() gave us, not `aligned_buffer`.
179+
std::free(buffer);
180+
return err;
181+
}
182+
183+
// We can't naively free this pointer, since it may not be what malloc() gave
184+
// us. Pass the offset to the real buffer as context. This is the number of
185+
// bytes that need to be subtracted from the FreeableBuffer::data() pointer to
186+
// find the actual pointer to free.
187+
return FreeableBuffer(
188+
aligned_buffer,
189+
size,
190+
FreeSegment,
191+
/*free_fn_context=*/
192+
reinterpret_cast<void*>(
193+
// Using signed types here because it will produce a signed ptrdiff_t
194+
// value, though for us it will always be non-negative.
195+
reinterpret_cast<intptr_t>(aligned_buffer) -
196+
reinterpret_cast<intptr_t>(buffer)));
197+
}
198+
199+
Result<size_t> FileDataLoader::size() const {
200+
ET_CHECK_OR_RETURN_ERROR(
201+
// Probably had its value moved to another instance.
202+
fd_ >= 0,
203+
InvalidState,
204+
"Uninitialized");
205+
return file_size_;
206+
}
207+
208+
__ET_NODISCARD Error FileDataLoader::load_into(
209+
size_t offset,
210+
size_t size,
211+
__ET_UNUSED const SegmentInfo& segment_info,
212+
void* buffer) {
213+
ET_CHECK_OR_RETURN_ERROR(
214+
// Probably had its value moved to another instance.
215+
fd_ >= 0,
216+
InvalidState,
217+
"Uninitialized");
218+
ET_CHECK_OR_RETURN_ERROR(
219+
offset + size <= file_size_,
220+
InvalidArgument,
221+
"File %s: offset %zu + size %zu > file_size_ %zu",
222+
file_name_,
223+
offset,
224+
size,
225+
file_size_);
226+
ET_CHECK_OR_RETURN_ERROR(
227+
buffer != nullptr, InvalidArgument, "Provided buffer cannot be null");
228+
229+
// Seek to the right place in the file.
230+
off_t seek_offset = ::lseek(fd_, offset, SEEK_SET);
231+
if (seek_offset != offset) {
232+
ET_LOG(
233+
Error,
234+
"Seeking %s to offset %zu returned %zd: %s",
235+
file_name_,
236+
offset,
237+
(ssize_t)seek_offset,
238+
strerror(errno));
239+
return Error::AccessFailed;
240+
}
241+
190242
// Read the data into the aligned address.
191243
size_t needed = size;
192-
uint8_t* buf = reinterpret_cast<uint8_t*>(aligned_buffer);
244+
uint8_t* buf = reinterpret_cast<uint8_t*>(buffer);
193245
while (needed > 0) {
194246
// Reads on macos will fail with EINVAL if size > INT32_MAX.
195247
ssize_t nread = ::read(
@@ -211,37 +263,12 @@ Result<FreeableBuffer> FileDataLoader::load(
211263
size,
212264
offset,
213265
nread == 0 ? "EOF" : strerror(errno));
214-
// Free `buffer`, which is what malloc() gave us, not `aligned_buffer`.
215-
std::free(buffer);
216266
return Error::AccessFailed;
217267
}
218268
needed -= nread;
219269
buf += nread;
220270
}
221-
222-
// We can't naively free this pointer, since it may not be what malloc() gave
223-
// us. Pass the offset to the real buffer as context. This is the number of
224-
// bytes that need to be subtracted from the FreeableBuffer::data() pointer to
225-
// find the actual pointer to free.
226-
return FreeableBuffer(
227-
aligned_buffer,
228-
size,
229-
FreeSegment,
230-
/*free_fn_context=*/
231-
reinterpret_cast<void*>(
232-
// Using signed types here because it will produce a signed ptrdiff_t
233-
// value, though for us it will always be non-negative.
234-
reinterpret_cast<intptr_t>(aligned_buffer) -
235-
reinterpret_cast<intptr_t>(buffer)));
236-
}
237-
238-
Result<size_t> FileDataLoader::size() const {
239-
ET_CHECK_OR_RETURN_ERROR(
240-
// Probably had its value moved to another instance.
241-
fd_ >= 0,
242-
InvalidState,
243-
"Uninitialized");
244-
return file_size_;
271+
return Error::Ok;
245272
}
246273

247274
} // namespace util

extension/data_loader/file_data_loader.h

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -72,6 +72,12 @@ class FileDataLoader : public DataLoader {
7272

7373
__ET_NODISCARD Result<size_t> size() const override;
7474

75+
__ET_NODISCARD Error load_into(
76+
size_t offset,
77+
size_t size,
78+
__ET_UNUSED const SegmentInfo& segment_info,
79+
void* buffer) override;
80+
7581
private:
7682
FileDataLoader(
7783
int fd,

0 commit comments

Comments
 (0)