MCPcopy Create free account
hub / github.com/apache/arrow / ReadMessageInternal

Function ReadMessageInternal

cpp/src/arrow/ipc/message.cc:371–441  ·  view source on GitHub ↗

Common helper for the two ReadMessage overloads that take a file + offset. When body_length is provided, metadata and body are read in a single IO. When body_length is absent, metadata is read first, then the body is read separately.

Source from the content-addressed store, hash-verified

369// When body_length is absent, metadata is read first, then the body is read
370// separately.
371static Result<std::unique_ptr<Message>> ReadMessageInternal(
372 int64_t offset, int32_t metadata_length, std::optional<int64_t> body_length,
373 io::RandomAccessFile* file, const FieldsLoaderFunction& fields_loader) {
374 std::unique_ptr<Message> result;
375 auto listener = std::make_shared<AssignMessageDecoderListener>(&result);
376 MessageDecoder decoder(listener);
377
378 if (metadata_length < decoder.next_required_size()) {
379 return Status::Invalid("metadata_length should be at least ",
380 decoder.next_required_size());
381 }
382
383 // When body_length is known, read metadata + body in one IO call.
384 // Otherwise, read only metadata first.
385 ARROW_ASSIGN_OR_RAISE(std::shared_ptr<Buffer> metadata,
386 file->ReadAt(offset, metadata_length + body_length.value_or(0)));
387
388 if (metadata->size() < metadata_length) {
389 return Status::Invalid("Expected to read ", metadata_length,
390 " metadata bytes at offset ", offset, " but got ",
391 metadata->size());
392 }
393
394 ARROW_RETURN_NOT_OK(decoder.Consume(SliceBuffer(metadata, 0, metadata_length)));
395
396 switch (decoder.state()) {
397 case MessageDecoder::State::INITIAL:
398 return result;
399 case MessageDecoder::State::METADATA_LENGTH:
400 return Status::Invalid("metadata length is missing. File offset: ", offset,
401 ", metadata length: ", metadata_length);
402 case MessageDecoder::State::METADATA:
403 return Status::Invalid("flatbuffer size ", decoder.next_required_size(),
404 " invalid. File offset: ", offset,
405 ", metadata length: ", metadata_length);
406 case MessageDecoder::State::BODY: {
407 std::shared_ptr<Buffer> body;
408 if (fields_loader) {
409 // Selective field loading: allocate a body buffer and read only the
410 // requested field ranges into it.
411 ARROW_ASSIGN_OR_RAISE(
412 body, AllocateBuffer(decoder.next_required_size(), default_memory_pool()));
413 RETURN_NOT_OK(ReadFieldsSubset(offset, metadata_length, file, fields_loader,
414 SliceBuffer(metadata, 0, metadata_length),
415 decoder.next_required_size(), body));
416 } else if (body_length.has_value()) {
417 // Body was already read as part of the combined IO; just slice it out.
418 body = SliceBuffer(metadata, metadata_length,
419 std::min(*body_length, metadata->size() - metadata_length));
420 } else {
421 // Body length was unknown; do a separate IO to read the body.
422 ARROW_ASSIGN_OR_RAISE(
423 body, file->ReadAt(offset + metadata_length, decoder.next_required_size()));
424 }
425
426 if (body->size() != decoder.next_required_size()) {
427 // The streaming decoder got out of sync with the actual advertised
428 // metadata and body size, which signals an invalid IPC file.

Callers 1

ReadMessageFunction · 0.85

Calls 12

SliceBufferFunction · 0.85
default_memory_poolFunction · 0.85
ReadFieldsSubsetFunction · 0.85
IOErrorFunction · 0.85
ARROW_ASSIGN_OR_RAISEFunction · 0.70
InvalidFunction · 0.50
AllocateBufferFunction · 0.50
next_required_sizeMethod · 0.45
ReadAtMethod · 0.45
sizeMethod · 0.45
ConsumeMethod · 0.45
stateMethod · 0.45

Tested by

no test coverage detected