Skip to content

[format] Reuse one source stream for consecutive BlobRef copies#8725

Open
XiaoHongbo-Hope wants to merge 1 commit into
apache:masterfrom
XiaoHongbo-Hope:open_seek_fix
Open

[format] Reuse one source stream for consecutive BlobRef copies#8725
XiaoHongbo-Hope wants to merge 1 commit into
apache:masterfrom
XiaoHongbo-Hope:open_seek_fix

Conversation

@XiaoHongbo-Hope

@XiaoHongbo-Hope XiaoHongbo-Hope commented Jul 19, 2026

Copy link
Copy Markdown
Contributor

Purpose

BLOB compaction opens a fresh stream (file open / HTTP GET) per
BlobRef — thousands of redundant opens when one compacted file draws
from one source. This reuses one stream across references into the
same source (same UriReader + URI), seeking to each offset and
copying exactly descriptor.length bytes, bounded to the descriptor
window: N references cost one open. Non-BlobRef / unknown-length
values keep the old path, so bytes and CRC are unchanged; only exact
BlobRef takes the fast path, so subclass newInputStream() and the
exact-class equals contract are preserved.

Tests

Verified on JDK 8:

BlobReuseSourceTest
BlobFormatWriterTest
OffsetSeekableInputStreamTest
BlobFileFormatTest
BlobTest

@XiaoHongbo-Hope
XiaoHongbo-Hope marked this pull request as ready for review July 19, 2026 13:44
BLOB compaction opens a fresh stream (file open / HTTP GET) per BlobRef --
thousands of redundant opens when one compacted file draws from one source.
Reuse one stream across references into the same source (same UriReader +
URI), seeking to each offset and copying exactly descriptor.length bytes,
bounded to the descriptor window so a caller never reads past the blob.

Reuse state lives in an internal BlobReuseSource (paimon-common) that only
ever hands back a stream bounded to a reference's descriptor; the raw
UriReader never leaves the class. A stale view, a mismatched ref, an unknown
length, or a BlobRef subclass are rejected; a source that can't rewind is
reopened, and its cleanup errors surface instead of becoming a NULL write.
Non-BlobRef / unknown-length values keep the open-per-blob path, so output
bytes and CRC are unchanged, and BlobRef.equals keeps exact-class semantics.

Behavior change: a source shorter than the descriptor throws EOFException
instead of writing a truncated blob.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant