Add V7 raw forward index format for codec pipelines - #19307
Open
xiangfu0 wants to merge 1 commit into
Open
Conversation
This was referenced Aug 19, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Stacked on #19306 (
xiangfu0/codex/codec-stack/04-t64-gorilla). Part of the split of #18229.Summary
Adds the V7 on-disk raw forward index format — the first format that can persist a codec
pipeline — plus the factory routing that decides, per
codecSpec, whether a column can keepusing the legacy chunk formats or needs V7:
FixedByteChunkForwardIndexWriterV7(new,io.writer.impl): chunked SV fixed-byte writerfor INT/LONG. File header carries
version=7, an explicitFORMAT_MAGIC(0xC0DEC0DE)discriminator, chunk geometry, and the canonical codec spec (UTF-8) followed by a long[]
chunk-offset table; each chunk stores
encodedSize/decodedSizeand the pipeline-encodedpayload. The writer validates the pipeline's composed encoded-size bound and cumulative work
bound up front so it never emits a file it could not read back.
FixedByteChunkSVForwardIndexReaderV7(new,readers.forward): self-describing readerthat re-creates the
CodecPipelineExecutorfrom the header string and fully validates theheader (chunk geometry consistency, spec length, offset-table monotonicity/bounds, per-chunk
sizes against the composed pipeline bound) before any allocation sized from file data.
FixedByteValueWriter(new interface) + retrofit onFixedByteChunkForwardIndexWriter, soSingleValueFixedByteRawIndexCreatorholds a single writer reference and gains a V7constructor taking a
CodecPipelineExecutor.CodecSpecUtils(new, public,io.codec): classification helper —toLegacyChunkCompressionType(...)(compression-only specs that map 1:1 to a legacyChunkCompressionType, e.g.LZ4,ZSTD(3)) andhasTransform(...). AlongsideCodecPipelineExecutorthis is the only public entry into the package-private codec runtime.ForwardIndexCreatorFactory:codecSpecrouting — legacy-mappable compression-only specsgo to the existing raw writers (byte-identical files to a legacy
compressionCodecconfig);transforms/chains/non-default options go to the V7 writer (SV INT/LONG only, with
defense-in-depth checks).
ForwardIndexReaderFactory: V7 dispatch keyed on the second-intFORMAT_MAGICcheckBEFORE the
version >= 4power-of-2 fallback (legacy fixed-byte writers accept arbitraryversions ≥ 4, so the version integer alone can never identify V7), plus a truncation check
before reading the version int.
ForwardIndexConfig.CODEC_PIPELINE_WRITER_VERSION = 7andForwardIndexReader.getCodecSpec()default method (V7 readers return the canonical headerspec; every other reader returns
null).ForwardIndexHandlerguard (~6 lines): inshouldChangeRawCompressionType, if theexisting reader reports
getCodecSpec() != null, returnfalsebefore theexistingCompressionType != nullprecondition. V7 segments are never rewritten yet (the nextPR owns reload/rewrite). The
computeOperationsgate already rejects codecSpec configs;this guard protects against V7 segments on disk (e.g. tooling-created) paired with a
non-codec config transition.
Canonicalization (frozen into on-disk headers)
The V7 writer embeds
executor.getCanonicalSpec()— neverForwardIndexConfig's stored string,which is only a structural normalization (
toDslString) and can differ (e.g.ZSTANDARDvsZSTD(3)). The reader re-creates the executor from the header string, so the header is alwaysin executor-canonical form (covered by
testCanonicalSpecStoredInHeader).Gate relocation (deliberate, explicit)
The codec stack's closed feature gate (
codecSpec is not supported yet for column: %s) wasplanted at every config/creator/reader/reload surface in #19284. This PR removes exactly two
factory-level gates because it makes those code paths real:
ForwardIndexCreatorFactory.createIndexCreator— now routes instead of throwing.ForwardIndexReaderFactory.createIndexReader(both overrides) — now reads instead of throwing.All config-surface gates remain:
ForwardIndexType.validate,ForwardIndexType.shouldCreateIndex,ForwardIndexType.createMutableIndex,ForwardIndexHandler.computeOperations(rejectUnsupportedCodecSpecs), and the OPEN_STRUCTsites. Net effect: no table config carrying
codecSpeccan validate, build a segment, createa mutable index, or reload — so no V7 segment is creatable from config — but the format code
itself and its direct-construction tests work end to end.
Deliberately excluded (next PR: 06-reload-enable)
rejectUnsupportedCodecSpecsites) andtable-config validation of codecSpec column types (
validateCodecSpec).ForwardIndexHandlerrewrite support for codec-pipeline segments (codecSpec changedetection via canonical-spec comparison, legacy↔V7 conversions on reload).
Why master stays safe with only this merged
codecSpecunusable from any table config, so the new writer/reader can onlybe reached by direct construction (tests/tools). No production config can produce a V7 file.
0xC0DEC0DEsecond-int magic, which no legacy writeremits; all legacy version ≥ 4 files keep their exact previous routing (locked by
ForwardIndexReaderFactoryBackwardCompatTest, including golden base64 fixtures producedbefore this code existed).
spec, i.e. V7 segments that could not exist via config today; legacy columns follow the exact
previous logic.
Verification
Stack (split of #18229)
Each PR is based on its predecessor's branch; GitHub retargets the next PR as each merges.