What is the bug?
DiskSeismicIndex does not override Index::add_with_ids, so it cannot be used with external document ids the way the other seismic indexes can.
Calling it directly falls through to the base implementation, which throws:
// nsparse/index.cpp:58
void Index::add_with_ids(...) {
throw_not_implemented("add_with_ids not implemented in Index");
}
IDMapIndex is the wrapper that normally provides id mapping (idmap,seismic_sq, idmap,seismic), and it does not require the delegate to override add_with_ids — IDMapIndex::add_with_ids routes to delegate_->add() (nsparse/id_map_index.cpp:70-80). So an in-memory idmap,disk_seismic does accept ids, but the combination still cannot be used end-to-end, because the wrapped index cannot be loaded back:
IDMapIndex::read_index always does a copying read of its delegate — delegate_.reset(nsparse::detail::read_index(io_reader, true, io_flags)) (nsparse/id_map_index.cpp:101).
DiskSeismicIndex::read_index unconditionally throws, since its inline forward index is borrowed from a mapping and never copied to the heap (nsparse/disk_seismic_index.cpp:311-317):
"DiskSeismicIndex is mmap-only; load with read_index(file, IndexIoFlag::kUseMmap)".
mmap_index_payload() in nsparse/io/index_io.cpp has no entry for IDMP, so the mmap fast path can only be taken for a top-level DiskSeismicIndex, not for one nested under an id map. The nested path also inherits InlineForwardIndex's alignment expectations about where the payload starts, which the id-map prefix shifts.
There is no test or demo covering idmap + disk_seismic (tests/disk_seismic_index_test.cpp never mentions IDMapIndex), which is why this went unnoticed.
How can one reproduce the bug?
Direct call:
nsparse::DiskSeismicIndex index(dim);
index.add_with_ids(n, indptr, indices, values, ids); // throws: add_with_ids not implemented in Index
Through the id map (Python, same shape as demos/seismic_sq_idmap.py):
index = nsparse.index_factory(dim, "idmap,disk_seismic,lambda=10|beta=2|alpha=0.4")
index.add_with_ids(n, indptr, indices, values, ids) # ok — routed to delegate add()
index.build()
nsparse.write_index(index, "idmap_dsei.bin") # ok
nsparse.read_index("idmap_dsei.bin") # throws: DiskSeismicIndex is mmap-only
nsparse.read_index("idmap_dsei.bin", nsparse.IndexIoFlag_kUseMmap) # IDMP has no mmap payload reader
What is the expected behavior?
disk_seismic should support external ids like seismic and seismic_sq do: either DiskSeismicIndex overrides add_with_ids, or IDMapIndex learns to carry an mmap-only delegate (an IDMP entry in mmap_index_payload() plus alignment-correct nesting of the payload), with tests covering idmap,disk_seismic add → build → search → write → mmap-load → search.
If the combination is not intended to be supported, it should fail loudly at construction time (e.g. index_factory rejecting idmap,disk_seismic) rather than only when the index is read back.
Do you have any additional context?
Introduced with #32 (DiskSeismic: Add disk_seismic_index).
What is the bug?
DiskSeismicIndexdoes not overrideIndex::add_with_ids, so it cannot be used with external document ids the way the other seismic indexes can.Calling it directly falls through to the base implementation, which throws:
IDMapIndexis the wrapper that normally provides id mapping (idmap,seismic_sq,idmap,seismic), and it does not require the delegate to overrideadd_with_ids—IDMapIndex::add_with_idsroutes todelegate_->add()(nsparse/id_map_index.cpp:70-80). So an in-memoryidmap,disk_seismicdoes accept ids, but the combination still cannot be used end-to-end, because the wrapped index cannot be loaded back:IDMapIndex::read_indexalways does a copying read of its delegate —delegate_.reset(nsparse::detail::read_index(io_reader, true, io_flags))(nsparse/id_map_index.cpp:101).DiskSeismicIndex::read_indexunconditionally throws, since its inline forward index is borrowed from a mapping and never copied to the heap (nsparse/disk_seismic_index.cpp:311-317):"DiskSeismicIndex is mmap-only; load with read_index(file, IndexIoFlag::kUseMmap)".mmap_index_payload()in nsparse/io/index_io.cpp has no entry forIDMP, so the mmap fast path can only be taken for a top-levelDiskSeismicIndex, not for one nested under an id map. The nested path also inheritsInlineForwardIndex's alignment expectations about where the payload starts, which the id-map prefix shifts.There is no test or demo covering
idmap+disk_seismic(tests/disk_seismic_index_test.cppnever mentionsIDMapIndex), which is why this went unnoticed.How can one reproduce the bug?
Direct call:
Through the id map (Python, same shape as
demos/seismic_sq_idmap.py):What is the expected behavior?
disk_seismicshould support external ids likeseismicandseismic_sqdo: eitherDiskSeismicIndexoverridesadd_with_ids, orIDMapIndexlearns to carry an mmap-only delegate (anIDMPentry inmmap_index_payload()plus alignment-correct nesting of the payload), with tests coveringidmap,disk_seismicadd → build → search → write → mmap-load → search.If the combination is not intended to be supported, it should fail loudly at construction time (e.g.
index_factoryrejectingidmap,disk_seismic) rather than only when the index is read back.Do you have any additional context?
Introduced with #32 (
DiskSeismic: Add disk_seismic_index).