Commit Graph

73 Commits

Author SHA1 Message Date
Andrey Vasnetsov
7083e7f2b6 gridstore live reload (#8287)
* [manual] live reload functions for gridstore-read

* [AI] tests for life reload

* fmt

* Address CodeRabbit review (PR 8287)

- gridstore/mod: acquire pages read lock once in files() loop
- universal_io/mmap: use fs_err::exists() to propagate IO errors
- pages: fix live_reload last_page_id underflow when pages is empty

Made-with: Cursor

* review changes

* thx coderabbit

---------

Co-authored-by: Cursor Agent <agent@cursor.com>
Co-authored-by: Luis Cossío <luis.cossio@outlook.com>
2026-03-04 18:30:21 +01:00
Andrey Vasnetsov
77b296d579 storage-backend dependent file listing (#8286) 2026-03-04 14:18:58 +01:00
Luis Cossío
a7e78730a6 [gridstore] simplify page range calculation (#8285)
* simplify page range calculation

* smol fix

---------

Co-authored-by: generall <andrey@vasnetsov.com>
2026-03-03 16:17:03 -03:00
Andrey Vasnetsov
b6c1987038 MultiFile Universal UI in gridstore pages (#8256)
* [manual] implement Pages for read-only

* Simpler `ReadMulti`/`WriteMulti` interface (#8263)

* [manual] Dumbify `ReadMulti`/`WriteMulti` interface

* fixup! [manual] Dumbify `ReadMulti`/`WriteMulti` interface

🤷‍♀️

* fixup! [manual] Dumbify `ReadMulti`/`WriteMulti` interface

Remove `VecMultiUniversalIo`

* [manual] review fix + silplify json load option

* [AI] split read and write + revome *Multi traits

* [AI] implement write for pages

* [AI] integrate pages into gridstore

---------

Co-authored-by: Roman Titov <ffuugoo@users.noreply.github.com>
2026-03-03 14:50:44 +01:00
Andrey Vasnetsov
13ded7ab14 feat(gridstore): migrate Tracker to universal IO (#8253)
* feat(gridstore): migrate Tracker to universal IO

- Tracker<S> generic over S: UniversalRead<u8> + UniversalWrite<u8>
- Replace MmapSlice<u8> with S; use S::open, read, write, flusher, populate
- On file growth: flush, create_and_ensure_length, re-open S
- Map UniversalIoError::NotFound to tracker file missing error
- get_raw returns Result<Option<Option<ValuePointer>>>; get returns Result<Option<ValuePointer>>
- has_pointer, unset, write_pending return Result where needed
- flusher returns crate::gridstore::Flusher (universal_io Flusher mapped to GridstoreError)
- Type alias Tracker = Tracker<MmapUniversal<u8>> in lib.rs
- Tests use TestTracker = Tracker<MmapUniversal<u8>>; mapping_len/mmap_file_size .unwrap()

Made-with: Cursor

* refactor(gridstore): review follow-ups – generic view, From conversion, iter errors

- GridstoreView: use Tracker<S> with same S as Page (S: UniversalRead + UniversalWrite)
- Tracker: use ? and .map_err(Into::into) instead of .map_err(GridstoreError::from)
- View iter: propagate tracker read errors via Err(e) instead of silently skipping

Made-with: Cursor

* Split Tracker into read/write impl blocks; GridstoreView only requires UniversalRead

- Tracker: impl<S> for files/pointer_count, impl<S: UniversalRead<u8>> for
  get/get_raw/iter_pointers/has_pointer/populate and test helpers,
  impl<S: UniversalRead+UniversalWrite> for new/open/write_pending/set/unset
  and other write methods (like Page).
- GridstoreView: require S: UniversalRead<u8> only so read-only views don't
  need UniversalWrite.

Made-with: Cursor

* Move Tracker::open to read-only impl; add FILE_NAME/tracker_file_name to unbound impl

open() only uses S::open and storage.read(), so it belongs in impl<S: UniversalRead<u8>>.
read_config_and_tracker can thus use a read-only tracker open. FILE_NAME and
tracker_file_name moved to unbound impl so both read and write sections use them.

Made-with: Cursor

---------

Co-authored-by: Cursor Agent <agent@cursor.com>
2026-03-02 18:03:59 +01:00
Andrey Vasnetsov
82c49df611 feat(universal_io): add read_whole and read_json_via for config files (#8251)
* feat(universal_io): add read_whole and read_json_via for config files

- Extend UniversalRead with read_whole() for single-access whole-file read
- Default impl uses len() + read(0..len()); MmapUniversal overrides with one slice
- Add UniversalIoError::SerdeJson for JSON deserialization errors
- Add read_json_via<S,T>(path, options) in common::universal_io
- Gridstore: use read_json_via for config in read_config_and_tracker
- Segment: use read_json_via in ChunkedVectors::load_config, handle NotFound
- Segment: extend From<UniversalIoError> for OperationError with SerdeJson variant

Made-with: Cursor

* feat(universal_io): add UniversalIoError::NotFound for file-not-found

- Add NotFound { path } variant so callers can match without io::ErrorKind
- MmapUniversal::open maps io::ErrorKind::NotFound to NotFound { path }
- ChunkedVectors::load_config matches NotFound => Ok(None)
- OperationError From<UniversalIoError> handles NotFound

Made-with: Cursor

* style: apply cargo fmt

Made-with: Cursor

* fix(common): satisfy clippy explicit_auto_deref in read_json_via

Use &bytes instead of &*bytes; auto-deref handles Cow

Made-with: Cursor

---------

Co-authored-by: Cursor Agent <agent@cursor.com>
2026-03-02 16:38:17 +01:00
Luis Cossío
9444b0f07e Gridstore iter: re-fix livelock (#8248)
* release read locks after every batch

* break infinite loop

* oopsie
2026-02-27 22:02:35 +01:00
Luis Cossío
5403ea68ab Chunked vectors with UniversalWrite storage (#8233)
* use CowMultiVector as return type from storages

* add advice to OpenOptions

* Implement ChunkedVectors with generic storage

* rename ChunkedVectors->VolatileChunkedVectors and ChunkedMmapVectors-> ChunkedVectors

* propagate everywhere

fix tests

* [auto] rename BytesRange -> ElementsRange

* [auto] rename BytesOffset -> ElementOffset

* coderabbit nits

---------

Co-authored-by: generall <andrey@vasnetsov.com>
2026-02-27 12:47:15 -03:00
Andrey Vasnetsov
7084b5dd91 read write gridstore (#8244)
* [WIP] read and write separattion

* Introduce GridstoreView which contains ephermal representation of data and implements search functions

* fmt

* hide test-only method + add missing file

* fmt

* [AI] do not Copy config

* review nits

* thx coderabbit

---------

Co-authored-by: Luis Cossío <luis.cossio@outlook.com>
2026-02-26 21:57:40 +01:00
Andrey Vasnetsov
03c0fa2cf7 Universal IO: gridstore pages (#8223)
* [manunal] Gridstore page use universal IO

* fmt

* Apply review feedback for universal IO gridstore pages (#8230)

* Apply review feedback from PR #8223

- Use `super::Result` import in mmap.rs instead of fully-qualified `crate::universal_io::Result`
- Restructure ValuePointer destructuring in get_value and delete_value to
  first match Some(pointer), then destructure separately

* Replace Either<E, GridstoreError> with E: From<GridstoreError> in Gridstore::iter

Use a trait bound instead of Either to combine callback and gridstore
errors, allowing `?` to work directly on GridstoreError. This simplifies
callers by removing Either matching and io::Error conversion workarounds.

---------

Co-authored-by: qdrant-claw <qdrant-claw@users.noreply.github.com>

---------

Co-authored-by: qdrant-claw <qdrant-claw@users.noreply.github.com>
2026-02-25 19:46:00 +01:00
dependabot[bot]
18a7587d4b build(deps): bump rand_distr from 0.5.1 to 0.6.0 (#8148)
* build(deps): bump rand_distr from 0.5.1 to 0.6.0

Bumps [rand_distr](https://github.com/rust-random/rand_distr) from 0.5.1 to 0.6.0.
- [Release notes](https://github.com/rust-random/rand_distr/releases)
- [Changelog](https://github.com/rust-random/rand_distr/blob/master/CHANGELOG.md)
- [Commits](https://github.com/rust-random/rand_distr/compare/0.5.1...0.6.0)

---
updated-dependencies:
- dependency-name: rand_distr
  dependency-version: 0.6.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>

* Migrate main code base to rand 0.10

* Migrate tests

* Migrate benches

---------

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: timvisee <tim@visee.me>
2026-02-25 14:15:04 +01:00
Ivan Pleshkov
9f1a6be223 Gridstore non-blocking flush (#8188)
* gridstore unblocked flush

* review remarks
2026-02-23 12:18:14 +01:00
Tim Visée
e160308255 Don't lock Gridstore bitmask for full duration of flush (#8169) 2026-02-18 16:29:04 +01:00
xzfc
4cabb7fd8e Merge io and memory into common (#8155)
* Unify parking_lot/arc_lock feature

* Move lib/common/{io,memory}/* -> lib/common/common/*

- Mmap-related items are grouped into `common::mmap` sub-module:
  - `memory/src/chunked_utils.rs`      -> `common/src/mmap/chunked.rs`
  - `memory/src/madvise.rs`            -> `common/src/mmap/advice.rs`
  - `memory/src/mmap_ops.rs`           -> `common/src/mmap/ops.rs`
  - `memory/src/mmap_type_readonly.rs` -> `common/src/mmap/mmap_readonly.rs`
  - `memory/src/mmap_type.rs`          -> `common/src/mmap/mmap_rw.rs`
- Filesystem-related items are grouped into `common::fs` sub-module:
  - `common/src/fs.rs`          -> `common/src/fs/sync.rs`
  - `io/src/file_operations.rs` -> `common/src/fs/ops.rs`
  - `io/src/move_files.rs`      -> `common/src/fs/move.rs`
  - `io/src/safe_delete.rs`     -> `common/src/fs/safe_delete.rs`
  - `memory/src/checkfs.rs`     -> `common/src/fs/check.rs`
  - `memory/src/fadvise.rs`     -> `common/src/fs/fadvise.rs`
- Rest is moved straight into `common`:
  - `io/src/storage_version.rs` -> `common/src/storage_version.rs`

The old `io` and `memory` are now hollow crates that re-export items
from `common`. These hollow crates will be removed in next commits.

* Replace uses of `io` and `memory` with new paths in `common`

Since `io` and `memory` are just re-exports of `common`, these
replacements are no-op.

* Remove `io` and `memory` crates
2026-02-17 10:58:59 +01:00
xzfc
6bced54ca1 Chore: promote dependencies to workspace level (#8061)
* Promote `env_logger` to workspace dependency

* Promote `anyhow` to workspace dependency

* Promote `rmp-serde` to workspace dependency

* Promote `tinyvec` to workspace dependency

* Promote `async-trait` to workspace dependency

* Promote `url` to workspace dependency

* Promote `self_cell` to workspace dependency

* Promote `cc` to workspace dependency

* Promote `bitpacking` to workspace dependency
2026-02-05 16:02:28 +01:00
Ivan Boldyrev
984a9e8bd1 Fix gridstore Option unsoundness (#8011)
* Implement `Optional<T>` type

Define a type with the same presumed layout as `Option<T>`, but with defined behavior.

* Make `transmute_*` functions unsafe

The functions `memory::mmap_ops::transmute_*` are inherently unsafe, but
are not marked as are.  Their usage is documented, but it is not always clear
if the code is correct.

* Add `CsrHeader` to resolve another unsoundness

Tuples have no defined layout.
2026-02-03 17:57:09 +07:00
Andrey Vasnetsov
64040511bc gridstore iter livelock (#7983)
* granular lock for writing and flushing pending updates in gridstore tracker

* avoid grigstore tracker lock in iterator
2026-01-26 11:47:26 +01:00
Luis Cossío
9fca971d93 More graceful handle of flush cancellation (#7798)
* Reapply "return an error when cancelling a flush (#7781)" (#7799)

This reverts commit 4a1103acb7.

* log::trace cancellation of components

* gracefully handle flush cancellation inside segment flusher

* Update lib/segment/src/segment/entry.rs

Co-authored-by: Tim Visée <tim+github@visee.me>

* don't wrap cancellation errors

---------

Co-authored-by: Tim Visée <tim+github@visee.me>
2026-01-21 10:06:50 -03:00
Luis Cossío
0c1917b4ae Give lower probability to rare operations (#7876) 2026-01-06 17:14:15 -03:00
Tim Visée
4a1103acb7 Revert "return an error when cancelling a flush (#7781)" (#7799)
This reverts commit 2f443ec055.
2025-12-18 16:45:30 +01:00
Luis Cossío
2f443ec055 return an error when cancelling a flush (#7781)
* return an error when cancelling a flush

* fix test

* less verbosity
2025-12-17 10:21:20 -03:00
Arnaud Gourlay
2e66577148 Gridstore noisy log into assert (#7795) 2025-12-17 13:46:44 +01:00
Arnaud Gourlay
5175d9f64a Enrich Gridstore model testing (#7789)
* Enrich Gridstore model testing

* better

* no clear on Windows

* less windows

* sigh

* change strategy

* never give up

* x100 scale down for Windows

* last touch

* decrease for others too

* remove Iter test - the quadratic cost is not worth it

* Revert "remove Iter test - the quadratic cost is not worth it"

This reverts commit f0e98cb33b.

* try with limited Iter

* less logging as it is hurting crasher

* tracker.mapping_len() is slow

* hard limit good enough for now
2025-12-17 11:55:27 +01:00
Luis Cossío
a89f309645 new GridstoreError (#7780)
* create GridstoreError

* review nit
2025-12-16 12:04:25 -03:00
Luis Cossío
4e91702fe8 Introduce IsAliveLock (#7751)
* introduce IsAliveLock

* add tests

* rename to mark_dead

* update gridstore comment

* Update some comments

* Add must_use attribute to lock_if_alive

* Rename mark_dead to blocking_mark_dead

* make the handle take a `Weak` reference

* make dropping explicit

* use `Mutex::lock_arc` instead

* less nesting

* clippy

---------

Co-authored-by: timvisee <tim@visee.me>
2025-12-15 12:22:30 -03:00
Tim Visée
aadadd172e Gridstore: split pointer updates set/unset, simplify draining (#7749)
* Separate set and unset lists for each Gridstore pointer update

This makes the list of pointer updates much easier to grasp. The
simplification is desired because this exact structure has been a cause
for bugs multiple times now.

* Add more aggressive debug assertions

* Use consistent terminology

* Correct removal of set

* Simplify drain function

* Add safe guard to ignore empty pointer updates

* Rework tracker getter, explicitly branch variants

* Patch transmute, require Sized type

* rename and adjust comments

- set/unset is now current/to_free
- adjusted descriptions and comments for this nomenclature too

* clippy

* clippyyy

not 4, not 2, but 3 spaces

---------

Co-authored-by: Luis Cossío <luis.cossio@outlook.com>
2025-12-11 18:07:15 +01:00
Arnaud Gourlay
cb70be4969 Test Gridstore corruption on flush (#7713)
* Gridstore decompress failure

* more logs

* more logs

* hardening

* clean

* no compression

* cleanup

* typo

* misc

* wait for flush & less logs

* add compression type to the mix

* optimize
2025-12-11 15:13:16 +01:00
Tim Visée
14ebe94c90 Fix Gridstore flushing, correctly implement drain persist (#7741)
* Fix Gridstore tracker drain and persist not working properly

* Patch existing test

* Add new test to assert buggy scenario we found

* Mention PR in test
2025-12-11 10:27:40 +01:00
Arnaud Gourlay
21d52ba832 Optimize gridstore flush (#7740)
* Optimize gridstore flush

* lovely early return
2025-12-10 19:42:57 +01:00
Tim Visée
bdd3871f29 Fix flusher data race in Gridstore (#7702)
* Add lease structure to invalidate pending flushers after wipe/clear

* We don't use bitmask as barrier anymore

* Add missing early return

* Add test

* Replace flush lease with is alive boolean we also use elsewhere

* Reimplement test, now it does fail on the old implementation

* In test, cover both new fixed and old broken flushing

* Remove old test case because it is flaky

* Fix clippy

* Fix outdated comment
2025-12-09 11:23:56 +01:00
Arnaud Gourlay
76bfa2ef7c Fix to run all tests on CI (#7732)
* Fix to run all tests on CI

* adjust for macos since we bumped rocksdb

* more flags
2025-12-09 11:09:52 +01:00
Luis Cossío
d79cd9b99b activate fs-err features for nicer error messages (#7665)
* activate fs-err features for nicer error messages

* use in entire workspace
2025-12-02 10:40:36 -03:00
dependabot[bot]
35817f11bc build(deps): bump lz4_flex from 0.11.5 to 0.12.0 (#7660)
Bumps [lz4_flex](https://github.com/pseitz/lz4_flex) from 0.11.5 to 0.12.0.
- [Release notes](https://github.com/pseitz/lz4_flex/releases)
- [Changelog](https://github.com/PSeitz/lz4_flex/blob/main/CHANGELOG.md)
- [Commits](https://github.com/pseitz/lz4_flex/compare/0.11.5...0.12.0)

---
updated-dependencies:
- dependency-name: lz4_flex
  dependency-version: 0.12.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-12-01 19:25:26 -03:00
Tim Visée
4010e7219f Add runtime flag to disable opening multiple mmaps on the same file (#7614)
* Fix delete_page not dropping sequential mmap

* In Gridstore Page, support using a single mmap

* In Gridstore Page, only open multiple mmaps if supported at runtime

* Support opening single mmap in UniversalMmapChunk

* Rename environment var, log warning when QDRANT_NO_MULTI_MMAP is set

* Support opening single mmap in MmapDenseVectors

* Remove unused result response

* Import LazyLock
2025-12-01 18:34:05 +01:00
Arnaud Gourlay
eba78a6728 Fix Gridstore has pointer lookup to account for nature of pending operation (#7638) 2025-12-01 10:55:44 +01:00
Luis Cossío
6ca3e46638 Fix wiping of Gridstore (#7627)
* fix wiping of gridstore

* clippy

* address @timvisee's review
2025-11-27 11:38:19 -03:00
Luis Cossío
e0aabd6084 Weak flusher references to Gridstore components (#7624) 2025-11-26 17:01:54 -03:00
Tim Visée
b7394ce85e Bump rocksdb dependency to 0.24.0 (#7605) 2025-11-25 16:44:44 +01:00
dependabot[bot]
7f7d9981a2 build(deps): bump csv from 1.3.1 to 1.4.0 (#7594)
Bumps [csv](https://github.com/BurntSushi/rust-csv) from 1.3.1 to 1.4.0.
- [Commits](https://github.com/BurntSushi/rust-csv/compare/1.3.1...1.4.0)

---
updated-dependencies:
- dependency-name: csv
  dependency-version: 1.4.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-11-24 21:04:23 -03:00
Tim Visée
8bbeda5783 Add deferred flusher to Gridstore (#7446)
* Wrap the tracker and bitmask in Arc

* Implement deferred flusher for gridstore, defer tracker writes

* Remove clone

* Dynamically adjust list of pending updates to drain what is flushed

* Return proper flusher, defer premature Gridstore flushing errors

* Use deferred Gridstore flusher across storages

* Remove all Arc<RwLock<_>> wrappers around Gridstore in storages

* Flush pages inside closure, also wrap them in a lock

* Remove direct flush function from Gridstore

* Add test to assert behavior of deferred flushing in Gridstore

* Add much more extensive test, including concurrent flushes and deletes

* Add test for draining value pointer, make sure to drop when flushed

* Feature gate RocksDB components
2025-11-18 14:21:43 +01:00
Tim Visée
b067a7b3f8 Minor Gridstore improvements (#7415)
* Explicitly use C memory representation for Gridstore value pointers

* Inline pure function

* Grow tracker file to be next multiple of two

* In debug builds, panic if getting out of bound point from Gridstore

* Also represent region gaps as C struct

* Remove debug assertion

* Adjust file size test
2025-10-17 13:59:03 +02:00
Tim Visée
da5e5cd42d In Gridstore, also populate the tracker file (#7385) 2025-10-10 13:15:11 -03:00
xzfc
a0d62330c7 Use fs-err (#7319) 2025-09-29 12:47:10 +00:00
Arnaud Gourlay
360d7bc26d Clippy 1.90 (#7253)
* Fix Clippy 1.90

* fmt
2025-09-15 20:12:11 +02:00
xzfc
febf72a47e Generic AccessPattern (#7166) 2025-09-01 11:16:20 +00:00
Luis Cossío
bd448eb580 make Gridstore::iter iterate by owned values (#7045) 2025-08-14 10:54:39 +02:00
xzfc
a959e8a671 MADV_POPULATE_READ on sequential mmaps (#6923) 2025-07-22 14:05:07 +02:00
Luis Cossío
dd63603e98 use seq mmap in iter (#6750)
Also refactor to use const generics
2025-06-24 12:56:30 +02:00
dependabot[bot]
aadb0bd7e6 build(deps): bump lz4_flex from 0.11.4 to 0.11.5 (#6746) 2025-06-23 21:52:09 +00:00
Luis Cossío
be6e425a75 [gridstore] update a selection instead of a range of regions (#6713)
* update a selection instead of a range of regions

* extend instead of loop

* use div_ceil to calculate region_id range
2025-06-23 15:23:54 -04:00