Commit Graph
95 Commits
Author SHA1 Message Date
Luis Cossío 84b2738823 flush after prefilling deleted vectors (#9992) 2026-08-04 11:18:44 +02:00
Luis Cossío f853a93a12 [CI] Enforce no default impl for batch methods (#9939)
* [AI] Add ast-grep rule to avoid default batch trait methods

* reword

* fix `FullTextIndexRead::check_match_batch`

* move to `tools/ast-grep/`

* Add tests

* pin ast-grep version

* fix spelling
2026-08-04 11:18:42 +02:00
Luis CossíoandClaude Fable 5 9a224a1d67 Mandatory batch impls (#9935)
* make `EncodedStorage::for_each_batch` mandatory

* make `DenseVectorStorageRead::for_each_in_dense_batch` mandatory

* make `DenseTQVectorStorage::for_each_in_dense_batch` mandatory

* make `DenseTQVectorStorage::read_dense_tq_bytes` mandatory

* make `QueryScorer::score_stored_batch` mandatory

...and implement for tq multivectors

* [AI] make `IdTrackerRead::internal_versions_batch` mandatory

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>

* [AI] make `IdTrackerRead::external_ids_batch` mandatory

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>

* [AI] make `DiskMappingsSource::resolve_internal_batch` mandatory

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>

---------

Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
2026-08-04 11:18:42 +02:00
Luis Cossío eaa505ecdc [io-bridge] split large reads into unordered chunks (#9896)
* read large files in unordered chunks

* use S3 error

* use a vec of ranges to track scattering

* self nits

* use less concurrent chunks
2026-08-04 11:18:42 +02:00
Luis Cossío 2e5bb066d1 make VectorStorageRead::read_vector_bytes mandatory (#9893)
Additionally:
- homogenize enum dispatch
- impl batch multivector read bytes
2026-08-04 11:18:41 +02:00
Luis Cossío f189ef5cf3 Misc nits (#9894)
* use `WithVector::is_enabled`

* suppress unused var lint

* fix non linux "useless mut" lint
2026-08-04 11:18:40 +02:00
553b6d6988 [edge] Actually use batched vector reads (#9855)
* override default impls

* Fix clippy needless_borrow in batched dense read ops

Co-authored-by: Cursor <cursoragent@cursor.com>

---------

Co-authored-by: root <111755117+qdrant-cloud-bot@users.noreply.github.com>
Co-authored-by: Cursor <cursoragent@cursor.com>
2026-08-04 11:17:04 +02:00
Luis Cossíoandxzfc b2031d8aac [UIO] Increase PHF prefetch (#9842)
* increase phf prefetch

* no duplicate comment

Co-authored-by: xzfc <5121426+xzfc@users.noreply.github.com>

---------

Co-authored-by: xzfc <5121426+xzfc@users.noreply.github.com>
2026-08-04 11:17:03 +02:00
594745f9c0 [edge] Add readonly ram sparse index (#9841)
* Add Ram variant, loads from vector storage

* impl live reload

* preopen sparse storage when using ram index

* Batch storage reads when building sparse RAM index

Rebuild `build_ram_index` around a single `read_vectors::<Sequential>`
pass instead of a per-point `get_vector_opt` loop, so Gridstore
coalesces the IO into block reads instead of a round-trip per point.
Benefits both the read-only mutable-RAM rebuild and the writable
`SparseVectorIndex::plan` build path.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>

---------

Co-authored-by: generall <andrey@vasnetsov.com>
Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
2026-08-04 11:17:03 +02:00
Luis Cossío 6b9616dff5 remove expect (#9839) 2026-08-04 11:17:03 +02:00
c00506bf46 [DiskCache] Dedup overlapping remote requests (#9838)
* [AI] piggyback on in-flight requests

* cleanup tests

* Insert in-flight fetch through Slab's VacantEntry (#9840)

Replace the peek-key-then-insert pattern with slab's vacant_entry() API:
inserting through the reserved entry guarantees the fetch lands on the
key the remote read was tagged with, instead of relying on nothing
touching the slab between the peek and the insert. A failed remote
schedule still leaves no trace, as VacantEntry allocates nothing until
insert.

get_or_init_remote_pipeline now takes the field instead of &mut self so
the VacantEntry can hold a disjoint borrow of in_flight across the
schedule call.

Co-authored-by: Claude Fable 5 <noreply@anthropic.com>

---------

Co-authored-by: Andrey Vasnetsov <andrey@vasnetsov.com>
Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
2026-08-04 11:17:03 +02:00
Luis Cossío c7e0deed7c exhaustive match on async-like backends (#9837) 2026-08-04 11:17:03 +02:00
Luis Cossío 3aaa127682 [UIO] Add and use Populate::Partial variant (#9769)
* add (and handle) `Populate::Partial`

* use partial populate

* no OOB error
2026-08-04 11:17:00 +02:00
138e24cd55 [UIO] Better populate of bool and null indexes (#9768)
* propagate `populate` to bool and null `preopen`

* derive populate from payload schema

* Fix broken doc reference: restore payload_schema identifier

Co-authored-by: Cursor <cursoragent@cursor.com>

---------

Co-authored-by: root <111755117+qdrant-cloud-bot@users.noreply.github.com>
Co-authored-by: Cursor <cursoragent@cursor.com>
2026-08-04 11:17:00 +02:00
Luis Cossío 516c59a824 [UIO] implement ReadOnlyFullTextIndex::preopen (#9765)
* prepare universalhashmap for partial populate

* [AI] implement `ReadOnlyFullTextIndex::preopen`
2026-08-04 11:17:00 +02:00
Luis Cossío de8e57b150 [AI] implement ReadOnlyGeoIndex::preopen (#9744) 2026-08-04 11:17:00 +02:00
Luis Cossío 83378d5e52 [AI] update the dispatches for ReadOnlyFieldIndex methods (#9766) 2026-08-04 11:17:00 +02:00
Luis Cossío 2e29e1561b [AI] implement ReadOnlyNumericIndex::preopen (#9743)
[AI] implement `ReadOnlyNumericIndex::preopen`
2026-08-04 11:16:59 +02:00
Luis Cossío 91ea0cda75 [UIO] Preopen map index (#9742)
* impl `OnDiskMapIndex::preopen`

* Prepare for preopen all payload indexes

* impl `ReadOnlyAppendableMapIndex::preopen`

* also use it for int and uuid index

* respect low memory mode
2026-08-04 11:16:59 +02:00
Luis Cossío f8ba0fbb01 [AI + manual] add preopen functions to id tracker (#9729) 2026-08-04 11:16:59 +02:00
Luis Cossío 604c4bdc0a add preopen functions to gridstore (#9728)
Additionally, propagate Populate for Tracker
2026-08-04 11:16:59 +02:00
Luis Cossío 2417721102 Pass file size to DiskCacheFs::open (#9730) 2026-08-04 11:16:59 +02:00
Luis Cossío b5a12f1234 [AI + manual] cleanup (#9727)
- get rid of `from_file` abstractions
- renames:
  - `CachedFs` to be the implementation
  - `CachedReadFs` to be the trait
2026-08-04 11:16:59 +02:00
Luis Cossío c5c46d4184 [DiskCache] refactor State into single enum (#9651)
* [AI + manual] refactor State into single enum

* use `let .. else`

* use explicit matches
2026-08-04 11:16:57 +02:00
09f74749b2 [UIO] Include file size in UniversalReadFileOps::list_files (#9675)
* [AI + manual] Include file size in `UniversalReadFileOps::list_files`

* Use dedicated `ListedFile` struct instead of `(PathBuf, u64)` pair

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

---------

Co-authored-by: generall <andrey@vasnetsov.com>
Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-08-04 11:16:57 +02:00
Luis Cossío e609e9372a expect unnecessary wraps (#9676) 2026-08-04 11:16:57 +02:00
Luis Cossío 889dd49f5e simplify DiskCache::read_whole (#9642)
Rely on the existing initialization logic when prefilling for
`read_whole`
2026-08-04 11:16:56 +02:00
Luis Cossío 135298abde Add s3_proxy.sh tool to simulate an S3 bucket locally (#9589) 2026-08-04 11:16:55 +02:00
Luis Cossío 6f42aec534 [UIO] Explicit Populate in R/O vector storages 2026-08-04 11:16:55 +02:00
Luis Cossío 2ed5a33f27 [DiskCache] Proper background populate on reopen (#9519)
* hold init_guard during reopen

* add `from` parameter to `OwnedReadPipeline::schedule_whole`

* add `OwnedReadPipeline::into_inner` to extract inner file

* implement proper background populate on `reopen`

* clippy

* coderabbit

* explicit owned uring pipeline destructuring

* refactor to join local and remote into one state

* @ffuugoo's nits
2026-08-04 11:16:54 +02:00
Luis Cossío c26d94e1c6 Add facet accuracy test (#9549)
* [AI] add facet accuracy test

* [manual] simplify

* [AI] delete and overwrite some points

* [AI] use immutable segments too

* lower zipf skew
2026-08-04 11:16:54 +02:00
Luis Cossíoandgenerall ce31866411 [UIO] Batched OnDiskMapIndex::for_values_map (#9505)
* override `for_values_map` for `OnDiskMapIndex`

* refactor and apply to filter as id iterator

* add comment

---------

Co-authored-by: generall <andrey@vasnetsov.com>
2026-08-04 11:16:53 +02:00
Luis Cossío 23c724408a [UIO] Batching for OnDiskMapIndex::values_iter (#9491) 2026-08-04 11:16:53 +02:00
c359fbb86e Perf improvements for facets (#9457)
* feat(facet): add sampling strategy for high-cardinality fields

For approximate facet queries the current per-segment implementation
walks every distinct value in the field index — O(unique_values_count)
even when the user asks for a tiny top-K. On UUID-style fields with
millions of unique values this dominates the request latency even
after #9208 capped the cross-shard payload.

This commit adds a parallel sampling strategy that runs in O(limit)
instead of O(unique_values_count):

1. Phase 1 — iterative novelty sampling. Stream point IDs in random
   order (filtered if requested), look up each point's value via the
   facet index, and collect distinct values into a candidate set until
   `limit * 10` (min 1000) candidates have been gathered. Uses a
   batch size of 32 to amortise the inner `for_points_values` call,
   and bails out early after 128 consecutive empty batches when the
   long tail is too thin to keep finding novel values.

2. Phase 2 — exact-count post-pass. For each candidate value, compose
   `field == value` with the user filter and count via the payload
   index. This guarantees the returned counts are exact (matching the
   semantics of the full-scan path); only the *set* of returned values
   is approximate.

The two strategies live side by side; `SegmentReadView::approximate_facet`
picks between them per-request based on
`unique_values_count > limit * FACET_FULL_SCAN_FACTOR` (FACTOR = 4).
Below that, the existing scan path runs unchanged — it'd visit most of
the index either way, and the post-pass adds no value.

The Monte-Carlo simulation behind this design (see thread context for
Zipf-distributed fields with cardinality up to 10^5 in ~1000 samples,
and trivially-correct results on UUID-style fields where every value
has count 1.

Adds a new `unique_values_count` method on the `FacetIndex` trait
(implemented for `MapIndex`, `ReadOnlyMapIndex`, `BoolIndex`,
`ReadOnlyBoolIndex`, and the `FacetIndexEnum` dispatcher) so the
strategy switch can run without touching the index.

Co-authored-by: Cursor <cursoragent@cursor.com>

* [AI] simplify, use single file

[AI] better selection of filtering approach

fmt

[AI] simplify, use single file

* manual simplification

* [AI] implement candidate-based lookups

[AI] 🧹

* precollect filter into bitmap

* avoid sampling with restrictive filter

* fix rebase + clippy

* refactor tests

* no duplicate values in map index

* polish comments

---------

Co-authored-by: root <111755117+qdrant-cloud-bot@users.noreply.github.com>
Co-authored-by: Cursor <cursoragent@cursor.com>
2026-08-04 11:16:53 +02:00
Luis Cossío dd5271bc6d Explicit Populate in payload storage (and ` (#9514)
`GridstoreReader`)

- Make the entrypoint of payload storage choose the `Populate` variant
- Mutable payload indexes now populate gridstore blockingly before using
  it to load
- Propagate `Populate` into `flags` module
- Add `UniversalRead::populate_auto` to know whether a backend chooses
  to populate or not when `Populate::Auto`
2026-08-04 11:16:53 +02:00
Luis Cossío 02eba0ac5a Add facets bench (#9456) 2026-08-04 11:16:51 +02:00
Luis Cossío 84ccdb37fc Standardize full text index (#9387)
* rename to OnDiskFullTextIndex

* rename module to `on_disk_text_index`

* rename to OnDiskPostings

* rename module to `on_disk_inverted_index`

* rename to OnDiskInvertedIndex

* remove `Box`ing

* get rid of `is_on_disk` field, propagate Populate

* add separate OnDisk and Immutable readonly variants

* rename in tests too

* nits
2026-08-04 11:16:49 +02:00
Luis Cossío 8beb3a08cf [UIO] Sorted offsets in LiveReload (#9385) 2026-08-04 11:16:49 +02:00
Luis Cossío e602e6a798 Standardize on-disk geo index & friends (#9339)
* rename GeoMapIndex -> GeoIndex

* rename on_disk module

* fmt

* remove `Box`ing

* add separate immutable and on-disk read-only variants

* propagate Populate, respect `on_disk`, remove `is_on_disk`

* rename to `new_immutable` and fix tests

* more geomap -> geo renaming

* more adhoc `open_*` suffixes
2026-08-04 11:16:48 +02:00
Luis Cossío c0fb2ed172 de-duplicate ingestion method for geo-index (#9322) 2026-08-04 11:16:47 +02:00
Luis Cossío 7f436572c1 chore: Refactor mutable map index inner (#9319)
* replace `ingest` with `add_many_to_map`

* rename to InMemoryMapIndex

* rename module

* fmt

* clippy

* don't index if there's no values
2026-08-04 11:16:47 +02:00
Luis Cossío c7f8bb2cea Standardize map index (#9305)
* rename to OnDiskMapIndex

* rename module

* remove `is_on_disk` field from `OnDiskMapIndex`

* add separate Immutable and OnDisk ReadOnlyMapIndex

* rename StoredPointToValues to OnDiskPointToValues

* rename module to `on_disk_point_to_values`

* rename to `build_from_iter` and add `populate` arg

* fix test
2026-08-04 11:16:47 +02:00
Luis Cossío 0329fb7a86 Rename indexes variants (#9281) + fixup for #9294
* rename IndexSelector variants

* rename MapIndex::Mmap to MapIndex::OnDisk

* rename NumericIndex::Mmap to NumericIndex::OnDisk

* rename BoolIndex::Mmap to BoolIndex::Mutable

* rename FullTextIndex::Mmap to FullTextIndex::OnDisk

* rename GeoMapIndex::Storage to GeoMapIndex::OnDisk

Also rename a few functions and test variants

* Standardize numeric index (#9294)

* remove `UniversalNumericIndex.is_on_disk` field

* have separate Immutable and OnDisk variants for ReadOnlyNumericIndexInner

* rename UniversalNumericIndex -> OnDiskNumericIndex

* rename module to `on_disk_numeric_index`

* actually load as immutable if on_disk=false

* fixup! Standardize numeric index (#9294)

Make builder also return proper Immutable variant

* review nits
2026-08-04 11:16:47 +02:00
Luis Cossío d1d30b9efb [UIO] More read_json_via (#9270) 2026-06-03 14:57:11 +02:00
Luis Cossío 8c6f6a267c [UIO] Open UniversalMapIndex with S::Fs (#9256)
* open UniversalMapIndex with `S::Fs`

* Not found is Ok(None)
2026-06-03 14:55:06 +02:00
Luis Cossío 12cc1e50e6 [UIO] Universal load numeric index (#9234)
* rename module, use read_via

* propagate S to `UniversalNumericIndex<T, S>`
2026-06-03 14:53:11 +02:00
Luis Cossío 623063282a [UIO] Load GraphLinks with any backend (#9214)
* load with any universal io

* Don't populate with sequential advice

* use appropriate fs for `exists`

* use `read_whole_via` more

* TODO

* clear ram cache after read_whole
2026-06-03 14:53:11 +02:00
d808afb086 [#9159 alternative] Oversample with approx facet (#9208)
* Oversample with approx facet

* return early for limit=0

* Document distributed limit flow on Collection::facet

Add an ASCII diagram showing how the facet limit is oversampled once on
the entry node and how peer nodes enter via facet_internal without
re-oversampling.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

---------

Co-authored-by: generall <andrey@vasnetsov.com>
Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-03 14:53:11 +02:00
Luis Cossío 44446128a2 [DiskCache tests] Fix reopen on windows (#9189)
* reactivate tests

* try to release remote
2026-06-03 14:49:46 +02:00
Luis Cossío f3f197ecb3 [DiskCache] use and impl schedule_whole (#9185)
* impl schedule_whole for DiskCache

* use schedule_whole for background prefill

* ignore unit arg in bench

* bundle R bounds into trait
2026-06-03 14:49:46 +02:00
Luis Cossío b6708cf510 flush BitmaskGaps before reopening (#9186) 2026-06-03 14:49:45 +02:00
Luis Cossío 24823310d8 [UIO] Use UniversalRead::reopen (#9127)
* use universal reopen

* remove unused fs args
2026-06-03 14:47:42 +02:00
Luis Cossío b82f627a60 bump ecow to 0.3.0 (#9182) 2026-06-03 14:47:42 +02:00
Luis Cossío 117a2a93fd [UIO] Impl DiskCache::reopen (#9143) 2026-06-03 14:47:01 +02:00
Luis Cossío 2843d89443 [UIO] Introduce OwnedReadPipeline::schedule_whole (#9128) 2026-06-03 14:47:01 +02:00
Luis Cossío 6a1c6047f7 Merge pull request #9097
* impl async prefill

* use enum in `init_lock`

* init from scratch if channel closes

* cfg tests with prefill

* dirty update to pipe2

* cleanup & deduplicate code

* fix prefill pipeline

* self nits

* fix rebase

* separate file for `LocalState`

* more doc comments

* use acq/rel ordering

* handle empty byte range conversion

* todo reopen

* review: remove redundant functions

* review: T: + Send

* fmt
2026-06-03 14:47:00 +02:00
Luis Cossío 6d65fddb74 [UIO] Introduce UniversalRead::reopen (#9123)
* add `UniversalRead::reopen` fn

* thx coderabbit
2026-06-03 14:45:25 +02:00
37e9400c2e Introduce simple disk cache (#8792)
* [AI + manual] initial impl

[AI] read_batch which actually batches

manual nits

[AI] better handling of local and remote paths

manual refactor, respect open options

don't delete local file

dumbify read_batch

we want to refactor it anyway

simplify

rename to `DiskCache` in `simple_disk_cache` module

* refactor to use always use ReadPipeline

pass meta to remote pipeline

* nits

* run tests for more Remotes

* fix no more <T> in UniversalRead

* fmt

* chore(deps): unify roaring as workspace dep, move duplicate to dev-deps

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

---------

Co-authored-by: generall <andrey@vasnetsov.com>
Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-22 10:46:31 +02:00
Luis Cossío 6d96cbcb53 [UIO] Generic quantized storage (#9059)
* use generic in QuantizedMmapStorage

* rename to QuantizedStorage

* be explicit about S

* rename builder to `QuantizedStorageBuilder`

* rename file to `quantized_storage.rs`
2026-05-22 10:43:06 +02:00
Luis Cossío 075dc0d247 accept Cow in quantization_preprocess (#9061) 2026-05-22 10:42:58 +02:00
Luis Cossío 6598a47933 make quantized_vector_size method static (#9060) 2026-05-22 10:42:50 +02:00
Luis Cossío 35ea107d02 Propagate S to ImmutableIdTracker (#9047) 2026-05-22 10:41:09 +02:00
4ef1417443 [UIO] Introduce Populate enum (#8946)
* introduce `Populate` enum

* fix: apply CodeRabbit auto-fixes

Fixed 6 file(s) based on 6 unresolved review comments.

Co-authored-by: CodeRabbit <noreply@coderabbit.ai>

* fix coderabbit fix

* Use from rather than into

* add `Auto` variant

* fix rebase

* fix rebase again

---------

Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com>
Co-authored-by: CodeRabbit <noreply@coderabbit.ai>
Co-authored-by: timvisee <tim@visee.me>
2026-05-22 10:40:33 +02:00
Luis Cossío ade4ace555 uring only for linux (#9046) 2026-05-22 10:40:22 +02:00
Luis Cossío a0de218411 [UIO] Additional UniversalRead/Write usage simplifications (#8961)
* bytemuck::Pod already implies 'static

* no supertraits

* regions gaps with TypedStorage

* StoredBitSlice with TypedStorage

* bytemuck for PostingsHeader

* bytemuck for TrackerHeader

* bytemuck for MmapRange

* bytemuck for stored_point_to_values::Header
2026-05-22 10:31:05 +02:00
9d1bfc0f99 [gridstore, UIO] Simplify OptionalPointer (#8945)
* derive bytemuck::Pod on `OptionalPointer`, get rid of legacy transmute

* remove one layer of Option in `get_raw`

* keep `UniversalRead<u8>` bound, do bytemuck conversion at call site (#8953)

Drop the `+ UniversalRead<OptionalPointer>` / `+ UniversalWrite<OptionalPointer>`
trait bounds added in the previous two commits. Reads and writes of
`OptionalPointer` and `TrackerHeader` now go through `bytemuck::from_bytes` /
`bytemuck::bytes_of` on the existing `u8` byte slices instead.

This keeps the unsafe-transmute removal but avoids the turbofish noise
(`UniversalWrite::<u8>::flusher(&self.storage)`, `<S as UniversalRead<u8>>::open`,
…) that two `T`s on `S` forced everywhere.

Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

* extra refactoring after #8955

* explicit zeroed instantiation

---------

Co-authored-by: Andrey Vasnetsov <andrey@vasnetsov.com>
Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-22 10:30:38 +02:00
Luis Cossío abe1b39a83 use UniversalReadFileOps::exists for status file (#8929) 2026-05-08 16:14:23 +02:00
5eac2d5092 [UIO] Genericize ChunkedVectors.status (#8928)
* genericize ChunkedVectors.status, remove `Sized` bound

* check exists with `UniversalReadFileOps`

* Inline UioChunkedVectors bound, drop the alias (#8952)

The empty trait + blanket impl was a stable-Rust trait-alias workaround
that hid a fairly short bound (UniversalWrite<T> + UniversalWrite<Status>
+ Send + 'static) at the cost of an indirection readers had to mentally
unwind. Spelling it out at the three sites that need it is shorter overall
and immediately tells the reader what is required.

Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

---------

Co-authored-by: Andrey Vasnetsov <andrey@vasnetsov.com>
Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-08 16:14:22 +02:00
Luis Cossío 62898d69e4 match exhaustively on match variants (#8947) 2026-05-08 13:48:30 +02:00
Luis Cossío b674ad495b [UIO] Generic Roaring/Bitvec flags (#8896)
* propagate to BufferedDynamicFlags

* use duplicate for tests

* propagate to Bitvec/Roaring flags

* propagate to RoaringFlags

* fixup! propagate to BufferedDynamicFlags

* propagate to BitvecFlags
2026-05-08 13:48:27 +02:00
Luis Cossío 99cea57771 Properly handle O_DIRECT in io-uring (#8833)
* handle o_direct with custom buffer

* make separate impl

* use correct inner offset

* align buffer

* codespell

* review fixes

* use o_direct in tests

* clippy

* fix simple read impl

* simpler to_vec()

* use router function

* change todo comment
2026-05-08 13:48:27 +02:00
Luis Cossío 47f81bca6e [UIO] Generic dynamic flags (#8893)
* rename status

* impl simple StoredStruct

* use StoredStruct in `status`

* rename to `DynamicStoredFlags`

* Propagate `S` generic

* codespell nit
2026-05-08 13:48:26 +02:00
Luis Cossío eeb05f3f4e cfg linux imports (#8829) 2026-05-08 13:47:42 +02:00
Luis Cossío a86861a0e7 [UIO] Dynamic mmap flags (#8760) 2026-05-08 13:47:18 +02:00
Luis Cossío 97bcc78084 [UIO, gridstore] generic Bitmask storage (#8501)
* [AI + manual] generalize BitmaskGaps storage

* [AI + manual] use StoredBitSlice in Bitmask

* use MmapFile as default storage

* rename to read_all

* duplicate import
2026-05-08 13:47:18 +02:00
Luis Cossío fa8a7bd4d0 [UIO] Migrate numeric index (#8641)
* [manual + AI] migrate `pairs` field, reimplement iterator

Co-authored by Claude

* [AI] no custom iterator, read whole range

* better bounds
2026-05-08 13:46:46 +02:00
Luis Cossío c22a3f644c [UIO] Explicit padding for numeric point (#8668)
* derive Pod for Point<T>

* remove clones on Copy type

* fix annoying clippy lint

* serde skip padding

* extract point into a new file

* assert aligment
2026-05-08 13:46:46 +02:00
Luis Cossío 94aa170527 fix remaining clippy lint (#8703) 2026-05-08 13:46:45 +02:00
Luis Cossío 69144ceec7 [UIO] BufferedUpdateBitSlice (#8679)
* rename

* migrate `MmapBitsliceBufferedUpdateWrapper` -> `BufferedUpdateBitSlice`
2026-05-08 13:46:42 +02:00
74ae4f7588 [UIO] migrate SliceBufferedUpdateWrapper (#8518)
* migrate SliceBufferedUpdateWrapper

* fix compressed versions creation

* @xzfc's review improvements

Co-authored-by: xzfc <5121426+xzfc@users.noreply.github.com>

* fix rebase

* Drop usage of `TypedStorage`

---------

Co-authored-by: xzfc <5121426+xzfc@users.noreply.github.com>
Co-authored-by: xzfc <xzfcpw@gmail.com>
2026-05-08 13:46:36 +02:00
Luis Cossío 9734a5af22 Misc clippy fixes (#8624) 2026-05-08 13:46:04 +02:00
Luis Cossío 408b050eaa Allow shorter reads in IoUring (#8466)
* use assume_init_vec

* allow shorter reads at EOF

* add prevent_caching openoption, allow short read dynamically

* codespell

* fix rebase
2026-03-26 18:53:26 +01:00
Luis Cossío 973d9aa3d4 impl populate for CachedSlice (#8462)
* impl populate

* nits
2026-03-26 18:50:07 +01:00
Luis Cossíoandxzfc 26fd12a552 impl UniversalRead for local disk cache (#8368)
* checkout from `ssd-cache-wip`

* impl UniversalRead for CachedFile

* use `CachedSlice` for `UniversalRead` implementation

* block exhaustion test

* fix block exhaustion error

* fix alignment on owned path

* merge CachedFile into CachedSlice

* propagate io errors

* self-review

- log warning if long wait
- Option for RequestState
- clippy

* handle coderabbit's comments

* fix num read bytes check

* don't allocate twice for cache misses

* not for windows, sorry

* no more dead code

* use atomic for file id

* update cache controller description

* rebase fixes

* Self: Sized

* Use imports

* Remove with_global (unused)

* Add TODO

* move common::disk_cache -> universal_io::disk_cache

---------

Co-authored-by: xzfc <xzfcpw@gmail.com>
2026-03-26 18:48:54 +01:00
9bcef50544 Use UniversalIo for MmapBitSlice (#8339)
* feat(universal_io): add storage-agnostic BitSliceStorage with read/write support`

Add BitSliceStorage<S> generic over
UniversalRead<u64>/UniversalWrite<u64>,
providing bit-level read and write operations over u64-element storage.

Read operations (S: UniversalRead<u64>):
- read_all: returns Cow<BitSlice> (zero-copy for mmap, owned for others)
- get_bit: single bit read via u64 element fetch
- read_bit_range: arbitrary bit range read

Write operations (S: UniversalWrite<u64>):
- set_bit / replace_bit: single bit write (skips write if unchanged)
- write_bit_range: arbitrary bit range write from BitSlice source
- fill_bit_range: fill range with a value
- set_bits_batch: batch individual bit updates coalesced by element
- flusher: flush underlying storage

* refactor: replace MmapBitSlice with BitSliceStorage in MmapBitSliceBufferedUpdateWrapper

Migrate all deleted-flag bitslice storage from the legacy MmapBitSlice
(Deref-based mmap wrapper) to BitSliceStorage<MmapUniversal<u64>>
(storage-agnostic universal IO backend).

Updated consumers:
- MmapMapIndex
- MmapNumericIndex
- MmapGeoMapIndex
- MmapInvertedIndex (fulltext)
- ImmutableIdTracker
- Benchmark

Additionally:
- Add BitSliceStorage::create(path, num_bits) to encapsulate
  file creation + sizing + open (eliminates duplicated size math
  across 5 call sites)
- Add MmapBitSliceStorage type alias for
BitSliceStorage<MmapUniversal<u64>>
- Add count_ones() convenience method
- Use set_bits_batch() in wrapper flusher and all build paths
  instead of per-bit set_bit() loops (coalesces u64 read-modify-writes)
- Fix silent error swallowing in wrapper get(): log + debug_assert
  on I/O errors instead of .ok().flatten()
- Remove dead bitmap_mmap_size function from immutable_id_tracker

* use bitvec's approach for offset

* less api

* misc improvements

* refactor write method

* move to segment crate

* handle creation of file outside of StoredBitSlice logic

* fix codespell

* document bitwise calculations

* coalesce more updates into a single write, batch all writes

* use native `extend_from_bitslice` instead of iterating.

* clarity refactor

* clippyyy

* use `u64` as BitStore everywhere

* assume iterator is sorted

* only use chunk_by for generating runs

* fix update wrapper flusher

* review fixes

* larger set bits batch test

* remove reintroduced file

* oops, fix new test

---------

Co-authored-by: Claude <noreply@anthropic.com>
Co-authored-by: generall <andrey@vasnetsov.com>
2026-03-26 18:25:42 +01:00
Luis Cossío 603a6d8781 make check_values_any process references directly (#8362) 2026-03-26 17:51:54 +01:00
Luis Cossío 338739b789 Rename to StoredPointToValues (#8302)
* rename trait

* rename MmapPointToValues -> StoredPointToValues

* fmt

* more explicit naming of trait functions
2026-03-26 17:40:43 +01:00
Luis CossíoandRoman Titov 653a74a904 Refactor PointToValues to use UniversalRead (#8298)
* refactor PointToValues to use UniversalRead

It includes a significant change to `MmapValue` trait to be able to
handle Cow reads, instead of just references.

* fix str parsing

* fix incorrect path

* use fallible casting

* clippy

* No eager allocation

this also makes it so that borrowed strs can keep happening :heart-eyes:

* Lifetime cleanup

---------

Co-authored-by: Roman Titov <ffuugoo@users.noreply.github.com>
2026-03-26 17:39:15 +01:00
Luis Cossíoandgenerall 71242de098 [gridstore] simplify page range calculation (#8285)
* simplify page range calculation

* smol fix

---------

Co-authored-by: generall <andrey@vasnetsov.com>
2026-03-26 17:33:58 +01:00
Luis Cossío 0cff1564a5 Allow indexing_threshold=null to disable indexing (#1702)
* feat: allow indexing_threshold=null to disable indexing

* fix: continue refactor

* amend: continue refactor

* amend: restore docstring

* update openapi.json

* test: add sanity test

* test: refactor test
2023-05-17 11:00:42 +02:00
Luis Cossío 4ac3c6a867 feat: [http] alias with_vector <-> with_vectors (#1697) 2023-04-11 18:21:33 +02:00
Luis CossíoandAndrey Vasnetsov ac4302f555 [WIP] Include startup date in telemetry (#1676)
* feat: add boot time to telemetry

* refactor: rename boot -> startup

* review fixes

* update openapi

---------

Co-authored-by: Andrey Vasnetsov <andrey@vasnetsov.com>
2023-04-11 14:32:02 +02:00
Luis CossíoandAndrey Vasnetsov e1d494d6be Include "last_responded" in telemetry (#1668)
* feat: include "last_queried" in /telemetry

* fix: anonymize responses in the WebApiTelemetry and GrpcTelemetry Anonymize impls

* fix: anonymize the last_queried field

* fix: use YYYY/MM/DD hh:mm:ss format on 'last_queried'

* tests: add and fix telemetry test

* refactor: rename last_queried -> last_responded

* cargo fmt

* update openapi models

* refactor: rename last_request_time -> last_response_date

* tests: update test

* review changes

* add chrono to schemars

---------

Co-authored-by: Andrey Vasnetsov <andrey@vasnetsov.com>
2023-04-11 14:31:28 +02:00
Luis CossíoandAndrey Vasnetsov c414a77105 feat: add "any" to "match" statements (#1466)
* feat: add "any" to "match" statements

Adds support for using "any" to match on a list of different possible values

* enable proper counting in cardinality estimation

* fmt

* upd OpenAPI

---------

Co-authored-by: Andrey Vasnetsov <andrey@vasnetsov.com>
2023-03-15 16:20:11 +01:00
Luis Cossío 55593f32b7 docs: update Github Flow link (#1421) 2023-02-06 15:21:30 +01:00