Summary:
- Use the liburing TSAN suppressions in `tools/tsan_suppressions.txt` instead of defining the process-wide `__tsan_default_suppressions()` hook, avoiding conflicts with downstream applications.
- Wire RocksDB TSAN make and crash-test flows to use that suppressions file by default without overriding caller-provided `TSAN_OPTIONS`.
- Cover direct `db_crashtest.py` launches by passing the default suppressions to `db_stress` subprocesses.
- Fix the GCC 16 unity-build warning in `CacheItemHelper` by directly initializing the no-secondary-cache helper fields instead of delegating with `this`.
Imported from D101303486.
Pull Request resolved: https://github.com/facebook/rocksdb/pull/14710
Test Plan:
- `COMPILE_WITH_TSAN=1 make -j128 env_test`
- `timeout 60s ./env_test --gtest_filter=EnvPosixTest.IOUringAddressReuseNoTsanFalsePositive`
- `python3 tools/db_crashtest_test.py`
- `python3 -m py_compile tools/db_crashtest.py tools/db_crashtest_test.py`
- CI: `build-linux-unity-and-headers` passed after the `CacheItemHelper` fix
Reviewed By: hx235
Differential Revision: D104103800
Pulled By: xingbowang
fbshipit-source-id: 6066d9abe02a3c44d75f9ce449889468c927ce56
Summary:
Pull Request resolved: https://github.com/facebook/rocksdb/pull/14704
Add an immutable DBOption `reuse_manifest_on_open` (default false). When enabled, `DB::Open` can keep using the recovered MANIFEST for the first post-open metadata update instead of rebuilding a fresh MANIFEST, which can reduce warm-open latency for DBs whose MANIFEST is expensive to regenerate.
Reuse is still best-effort. If RocksDB cannot safely resume appending to the recovered MANIFEST, it falls back to the existing fresh-MANIFEST path. The option is also disabled under `best_efforts_recovery`.
This diff also teaches the reopened MANIFEST writer to adopt the existing file size before appending, documents the small-`max_manifest_file_size` caveat for the reused path, and keeps the full warm-reopen composition working with `optimize_manifest_for_recovery`.
Reviewed By: hx235, pdillinger
Differential Revision: D103568447
fbshipit-source-id: f4f5c35ea3ef0b80a0d52d94be40c6bd11505999
Summary:
Pull Request resolved: https://github.com/facebook/rocksdb/pull/14703
Extend `optimize_manifest_for_recovery` so a clean `DB::Close` can persist up-to-date WAL recovery markers when that can be done safely. Combined with the recovery-side optimization in the previous diff, a clean close/reopen can avoid recovery-time MANIFEST appends.
This remains best-effort: if the close-time write is disabled, skipped, or fails, RocksDB falls back to the standard recovery path on the next open. The option stays mutable so it can be turned off before close to suppress the optimization without restarting the DB.
The close-time path respects the existing recovery constraints for 2PC, non-empty column families, dropped column families, and WAL tracking, and preserves the existing file-number invariants.
Reviewed By: pdillinger, hx235
Differential Revision: D103568449
fbshipit-source-id: ae62867507a8a87640a2c140bea852b7c608cb66
Summary:
Pull Request resolved: https://github.com/facebook/rocksdb/pull/14702
Add a mutable DBOption `optimize_manifest_for_recovery` (default false) as a temporary rollout / kill switch for warm-reopen MANIFEST optimizations.
In this diff, enabling the option lets recovery skip MANIFEST updates during `DB::Open` when the recovered state is already reflected on disk, which reduces metadata appends after a clean shutdown and can lower warm-reopen latency on storage where MANIFEST appends are expensive.
If the option is disabled, RocksDB follows the existing recovery path unchanged. The optimization is disabled under `best_efforts_recovery`, where recovery intentionally rewrites metadata as part of salvage, and the option is mutable so later diffs in this stack can share the same rollout knob.
Reviewed By: pdillinger, hx235
Differential Revision: D103568448
fbshipit-source-id: 9ec930343e434f1bee6130bcdbd7738dddd92b6d
Summary:
This fixes a GCC 16 unity-build failure in `Cache::CacheItemHelper`. The no-secondary-cache constructor delegated to the full constructor while passing this as `without_secondary_compat`. GCC 16 reports that pattern as `-Wmaybe-uninitialized` because the delegated constructor receives a pointer to the object under construction and its debug assertions dereference it. Since RocksDB builds with `-Werror`, the warning is promoted to a build error. We see it now because the unity job uses `gcc:latest`, which now has `GCC 16.1.0`. The code pattern itself dates back to PR https://github.com/facebook/rocksdb/issues/11299 / ccaa3225b from 2023.
Pull Request resolved: https://github.com/facebook/rocksdb/pull/14713
Reviewed By: xingbowang
Differential Revision: D104162382
Pulled By: mszeszko-meta
fbshipit-source-id: d6cb579e37bed0d833c6427c3b0541c857425d42
Summary:
Add MLIR-compatible PrefixVarint32/64 helpers in util/prefix_varint.h. Document the format, split decode API, and hot paths, and cover the codec in coding_test with round-trip, disk-read, overflow, and truncation cases.
I'm intending to use this in the new blog file format because you only need to read the first byte to know how many varint bytes to read total, and it might be more CPU efficient in other uses as well (to be determined in follow-up work).
Pull Request resolved: https://github.com/facebook/rocksdb/pull/14692
Test Plan: Unit tests included
Reviewed By: joshkang97
Differential Revision: D103245079
Pulled By: pdillinger
fbshipit-source-id: dca435beccb6e666d864a31d8683ad19e2121c34
Summary:
Reduces per-step heap allocations in the external table iterator's hot path
by replacing the `InternalKey` member of `ExternalTableIteratorAdapter` with
`IterKey`. `InternalKey` stores its bytes in a `std::string`, which
heap-allocates whenever a key exceeds the small-string threshold. `IterKey`
keeps a 39-byte inline buffer and only spills to the heap for larger keys.
`UpdateKey` runs on every `Next` / `Prev` / `Seek*`, so this swap removes a
recurring per-step allocation for typical key sizes.
Pull Request resolved: https://github.com/facebook/rocksdb/pull/14695
Test Plan: CI
Reviewed By: anand1976
Differential Revision: D103440780
Pulled By: joshkang97
fbshipit-source-id: deb0a8ea04110e3dff0a1bcad767e7136192fdc6
Summary:
See SC crash test failure 2729181374202803470.
Flush/compaction retention was protecting only explicit snapshots, while readers without an explicit snapshot were still bounded by GetLastPublishedSequence(). That mismatch becomes observable in WRITE_COMMITTED when commit_bypass_memtable runs: a newer version can already be installed into WBWI-backed immutable memtables before SetLastSequence() publishes it. This can happen with two-write-queue enabled OR disabled.
Example setup:
- K@P = "old_value" is the current published version of key K.
- K@U = "new_value" is written later with U > P.
- commit_bypass_memtable ingests K@U into immutable memtables, but publication is still at P.
- flush starts in that window and builds its snapshot context.
Before this change, if there was no explicit snapshot at P, flush/compaction was free to collapse K@P under K@U. A reader at the published boundary P then saw neither version: K@P had been discarded, while K@U was still too new, so Get(K) returned NotFound.
A simple solution is to add a "fake" snapshot boundary for pessimistic write committed txns.
NOTE: A behavioral side effect is that this will prevent a merge operand at snapshot seqno from being filtered via compaction filter because of the new managed snapshot. But this keeps it aligned with the behavior that write prepared and write unprepared have.
Pull Request resolved: https://github.com/facebook/rocksdb/pull/14681
Test Plan: Regression test that fails without fix, specifically K@P gets deleted and a snapshot read returns NotFound, when it should exist.
Reviewed By: hx235
Differential Revision: D102856943
Pulled By: joshkang97
fbshipit-source-id: 46cb3936e9d4e771966d39fd0d15436335bf6ccf
Summary:
This commit fixes several potential issues introduced by cc8d9ea04 (CI: AI review workflow improvements) that broke the agent review jobs in GitHub CI.
1. Codex workflows fail when OPENAI_API_KEY is not configured:
- Added Codex review workflows fail with exit code 1 if the API key secret is missing
- Added script-level checks to skip Codex steps gracefully when OPENAI_API_KEY is unset, avoiding CI noise
2. Missing pull-requests: read permission in manual-review job:
- The manual-review job calls github.rest.pulls.get() but lacked the required permission
- Added 'pull-requests: read' to the manual-review job permissions
3. Potential crash when headSha is undefined:
- parse-claude-review.js and parse-codex-review.js accessed meta.headSha.substring() without null check
- Added defensive checks to handle undefined headSha gracefully
4. Claude model claude-opus-4-7 incompatible with thinking API:
- The commit upgraded default model to claude-opus-4-7, but this model doesn't support the 'thinking.type.enabled' API used by the Claude Code action
- Error: 'thinking.type.enabled' is not supported for this model. Use 'thinking.type.adaptive' and 'output_config.effort' to control thinking behavior
- Reverted default model to claude-opus-4-6 and removed claude-opus-4-7 from options
Pull Request resolved: https://github.com/facebook/rocksdb/pull/14696
Test Plan: Created a draft PR with this change and draft production code changes, including a branch on facebook/rocksdb. Go to https://github.com/facebook/rocksdb/actions/workflows/claude-review.yml and choose "Run workflow" with that branch and PR. (Changes in the PR do are not picked up for the agent code review workflows; the only way to test what is outside of main is with a branch on facebook/rocksdb)
Reviewed By: joshkang97
Differential Revision: D103453631
Pulled By: pdillinger
fbshipit-source-id: 15a82257b5762e9e0b1b393dc45c4b343c866f7a
Summary:
Two CPU-side optimizations to `DBIter`'s hot iteration path.
1. `PrepareValueInternal` always re-parses the internal key after `iter_.PrepareValue()`, even though most inner iterators report their value was already prepared and cannot have moved `iter_.key()`.
2. `ResetValueAndColumns` and `ResetBlobData` unconditionally clear wide-column / blob state at the top of every `Next()`, even on plain-value scans where neither has been populated since the last reset.
Both wins are pure CPU on hot, fully-cached workloads. The dirty-flag bookkeeping introduced for (2) is extracted into a small reusable `DirtyTracked<T>` utility so the same pattern can be reused for any T whose `Reset()` is non-trivial.
Pull Request resolved: https://github.com/facebook/rocksdb/pull/14684
Test Plan:
**Benchmark — `db_bench seekrandom`.** Each op = 1 Seek + 100 Next on a fully cached 10M-key DB (16 B key, 100 B value, no compression).
| | ops/sec |
|---|---:|
| BEFORE | 42,131 |
| AFTER | 45,269 |
| **Δ** | **+3,138 (+7.4%)** |
Reviewed By: xingbowang
Differential Revision: D103070805
Pulled By: joshkang97
fbshipit-source-id: 6b184a1aa559649c575d95be28ab43bbee9ffe64
Summary:
Pull Request resolved: https://github.com/facebook/rocksdb/pull/14685
D100235293 and D102823090 migrated the generated RocksDB BUCK file from
`//folly/experimental/coro:*` to `//folly/coro:*`, but did not update
the buckifier script that generates it in internal_repo_rocksdb. The next release would revert the change.
Update buckify_rocksdb.py to match, so the generated BUCK file stays consistent with the folly coro migration.
Reviewed By: nmk70
Differential Revision: D103096688
fbshipit-source-id: 9055769ed5e9893397c7504ada22e21980f59dd2
Summary:
- Upgrade the Claude review workflow models and add complexity-based thinking budget selection for the main review run.
- Keep AI review comments tied to the reviewed commit and restructure long reviews so high-severity findings stay visible while details live in a collapsible section.
- Add early auto-trigger gating plus Codex review/comment workflows, including shared comment-building and parsing helpers.
## Testing
- Not run. The branch refresh was a no-op rebase onto current `upstream/main`, and no new code changes were made during this task.
Pull Request resolved: https://github.com/facebook/rocksdb/pull/14659
Reviewed By: pdillinger
Differential Revision: D102224743
Pulled By: xingbowang
fbshipit-source-id: 39c25494062cbcd52d3e85f8a859b5a3907c758e
Summary: Migrate coro references across the repo to the non shim version.
Differential Revision: D102823090
fbshipit-source-id: 3bec59aed1f2645139a1ad9c18363e6af462e61f
Summary:
The previous pre-push hook auto-formatted, committed, and re-pushed on behalf of the user. This was fragile: it's not clear whether the format fix should amend the current commit or create a new one. Adding a commit breaks populating the summary for creating a new PR. Also, the hook's internal re-push would drop flags like --set-upstream from the original command. Replace with a simple check-only approach that blocks the push and tells the user what to fix.
Also add a new check for untracked source files (.cc, .h, .py, etc.) in tracked directories (excluding third-party/). These typically indicate files that were forgotten in the commit, which would cause the pushed code to fail to build.
Pull Request resolved: https://github.com/facebook/rocksdb/pull/14680
Test Plan: manual
Reviewed By: xingbowang
Differential Revision: D102855227
Pulled By: pdillinger
fbshipit-source-id: 7dc2c4e7a2b2c392bf8da74d7ea43883c8c075a9
Summary:
Pull Request resolved: https://github.com/facebook/rocksdb/pull/14676
When fast_sst_open is disabled, RocksDB was still passing previously-persisted
file_open_metadata from the MANIFEST to NewRandomAccessFile. This could cause
failures when the metadata becomes stale (e.g. expired filesystem credentials).
This change gates the consumption of file_open_metadata in
TableCache::GetTableReader on the fast_sst_open option. When fast_sst_open is
false, previously persisted metadata is ignored and not passed to the filesystem
via FileOptions::file_metadata.
The fast_sst_open flag is threaded from MutableDBOptions through VersionSet ->
ColumnFamilySet -> ColumnFamilyData -> TableCache at construction time, ensuring
the gate is active before any table readers are opened during recovery. Dynamic
changes via SetDBOptions are also propagated to all existing TableCache instances.
Reviewed By: mszeszko-meta, xingbowang
Differential Revision: D102735581
fbshipit-source-id: 9a2c4dc0644a2f65c36b2468605df57779e127cd
Summary:
Fix false internal warnings about skipped tests (seen on D102718613).
ROCKSDB_GTEST_SKIP signals a gap in test coverage due to the build/execution
environment, while ROCKSDB_GTEST_BYPASS is for intentionally and permanently
omitting certain parameterizations. These six tests skip based on the test
parameterization (forward vs reverse, primary vs secondary mode), not due to
any environment limitation, so BYPASS is the correct macro.
Pull Request resolved: https://github.com/facebook/rocksdb/pull/14679
Test Plan: these are tests, look at internal signals
Reviewed By: joshkang97
Differential Revision: D102833346
Pulled By: pdillinger
fbshipit-source-id: e57bd1e217ca63aaf418b68c788563e67bbb07e3
Summary:
- External Table is only PUTs with no seqno, so we can route it to the simpler more efficient `GetContext::SaveValue`.
- `SstFileReader::Get` was allocating a string to append key footer, instead use LookUpKey to allocate on stack for short keys.
Pull Request resolved: https://github.com/facebook/rocksdb/pull/14673
Test Plan: CI passes
Reviewed By: anand1976
Differential Revision: D102659533
Pulled By: joshkang97
fbshipit-source-id: e55127548c9e4b7bdeb63c46acfdb8eb5883db14
Summary:
Pull Request resolved: https://github.com/facebook/rocksdb/pull/14672
This fixes the forward path introduced in the original pull request: https://www.internalfb.com/diff/D102409405
That change tried to avoid using user-owned `iterate_upper_bound_` memory by reading `iter_.key()` when the internal iterator was still valid and using it as the exclusive end key for the synthetic range tombstone. That is not safe: after the upper-bound break, `iter_.key()` is only the current merged child position, not a key the bounded scan proved safe to read or use as a range endpoint.
Example: run a prefix-bounded scan over prefix `b` with tombstones `ba`, `bb`, `bc`, `iterate_upper_bound = "bd"`, live key `be` in an SST, and later same-prefix key `bz` in the memtable. The SST child can drop out when it notices `be >= bd`, while the memtable child is not upper-bound aware and can still surface `bz`. If cleanup uses `iter_.key() == "bz"`, it inserts `[ba, bz)` and covers the live `be`, even though that key was never safe for the bounded scan to reason about.
The fix is to always end the forward range at `saved_key_`, which is the last tombstone user key the iterator actually proved deleted. That is conservative but safe. The regression test builds the mixed SST/memtable example above and asserts that the live `be` remains visible. The diff also re-enables randomized `min_tombstones_for_range_conversion` in `db_crashtest.py` and forces it back to `0` when `use_multiscan == 1`, since multiscan still does not support read-path range conversion.
Reviewed By: xingbowang
Differential Revision: D102493855
fbshipit-source-id: 45bdb86464268e2c4fa2ea735dbb059a5e054f28
Summary:
Replace raw owning pointers with std::unique_ptr for StreamingCompress/Uncompress in Create functions and log::Writer/Reader, eliminating manual delete calls in destructors. Also update the StreamingCompressionTest to use unique_ptr for its local StreamingCompress, StreamingUncompress, and MemoryAllocator objects.
Bonus: improve error message for missing/broken ruby (new build requirement)
Pull Request resolved: https://github.com/facebook/rocksdb/pull/14665
Test Plan: ./log_test - all 211 tests pass.
Reviewed By: xingbowang
Differential Revision: D102381893
Pulled By: pdillinger
fbshipit-source-id: 02806b46c8371474a969d6fa3012fff5eb7886c3
Summary:
Pull Request resolved: https://github.com/facebook/rocksdb/pull/14662
When a file becomes obsolete, `ReleaseObsolete()` calls `ReleaseAndEraseIfLastRef()` to remove it from the table cache. However, if concurrent readers hold references to the cache entry, this is not the last ref, so the entry stays. When those readers later call plain `Release()`, the entry becomes unreferenced but remains in the cache — there is no mechanism to trigger cleanup.
The fix is to call `cache->Erase()` in `ReleaseObsolete()` instead of relying solely on `ReleaseAndEraseIfLastRef()`. `Erase()` marks the entry as Invisible in the cache. The cache's `Release()` implementation already checks `IsInvisible()` and erases Invisible entries when the last reference is released. This guarantees that obsolete file entries are cleaned up regardless of concurrent reader timing.
Also reverts the D102158618 workaround that reordered `EraseUnRefEntries()` before `TEST_VerifyNoObsoleteFilesCached` in `CloseHelper`. With the root cause fixed, the assertion correctly passes in its original position.
Reviewed By: pdillinger
Differential Revision: D102158618
fbshipit-source-id: 5796abee916dfbd99554a36d3bbf579842d2fb8b
Summary:
Seems like crashtests are failing more often now, disabling again to investigate.
Pull Request resolved: https://github.com/facebook/rocksdb/pull/14670
Reviewed By: archang19
Differential Revision: D102479287
Pulled By: joshkang97
fbshipit-source-id: 3f147f58b0cf2901ffe3b99e8681ed5a6085e7c8
Summary:
`blob_compression_opts` is dynamically changeable through `SetOptions()`, but
blob direct write cached its per-thread compressor by `CompressionType` only.
After updating `blob_compression_opts`, new blob records on an existing writer
thread could keep using stale compression settings.
This change threads `CompressionOptions` through the direct-write settings and
rebuilds the cached per-thread compressor whenever the published options for
that compression type change. When the options stay the same, the steady-state
cache behavior is unchanged.
It also adds a regression test that toggles the ZSTD checksum flag through
`SetOptions()` and inspects the raw blob records to confirm each direct-write
record used the latest compression options.
## Testing
- `timeout 60s ./db_blob_direct_write_test --gtest_filter='DBBlobDirectWriteTest.DirectWriteCompressionOptionsUpdateRebuildsCachedCompressor' --gtest_repeat=5`
Pull Request resolved: https://github.com/facebook/rocksdb/pull/14669
Reviewed By: jainraj91
Differential Revision: D102423376
Pulled By: xingbowang
fbshipit-source-id: 504243d72cf22e62097f7e88ac1cc36c5bf29eee
Summary:
kNoChecksum was not being tested in db_crashtest.py despite being a supported checksum type. Add it to the random selection to ensure crash test coverage of the no-checksum code path.
Pull Request resolved: https://github.com/facebook/rocksdb/pull/14667
Test Plan: Ran multiple blackbox and whitebox crash test validation runs with kNoChecksum forced and with random selection including kNoChecksum. All passed crash-recovery verification.
Reviewed By: hx235
Differential Revision: D102404837
Pulled By: pdillinger
fbshipit-source-id: 0120f1269c917dd6e347764f2bdc0095d46ff71a
Summary:
`DBIter::FindNextUserEntryInternal` previously used `iterate_upper_bound_` (user-controlled memory) as the exclusive end-key when flushing an accumulated tombstone run. That pointer is dangerous as it points to user memory space, which can be modified at any moment.
This PR removes that dependency: the end-key is always derived from RocksDB-owned data — either the live `iter_` key that broke the run, or `saved_key_` when `iter_` is exhausted.
The tradeoff here is that there is potentially 1 less tombstone to get covered in this path, which is reasonable.
Pull Request resolved: https://github.com/facebook/rocksdb/pull/14664
Test Plan: Updated unit tests, CI passes
Reviewed By: xingbowang
Differential Revision: D102409405
Pulled By: joshkang97
fbshipit-source-id: b2beed73e5fe5b955b2d782fc467eda637c4fcf2
Summary:
CONTEXT: The manifest validation on close feature (verify_manifest_content_on_close) detects corruption but does not increment any statistics counter, making it harder to monitor in production.
WHAT: Add a new ticker MANIFEST_VALIDATION_FAILURE_COUNT that is incremented each time content validation detects manifest corruption during DB::Close(). The counter fires per corruption detection, so it can increment up to 2 times per close (once on initial check, once after rewrite attempt). Updated all existing manifest validation tests to verify the counter value.
Pull Request resolved: https://github.com/facebook/rocksdb/pull/14657
Test Plan:
- All 7 manifest validation tests pass with new stat assertions
- 5x repeat with COERCE_CONTEXT_SWITCH=1 shows no flakiness
- Full version_set_test suite (212 tests) passes
Reviewed By: anand1976
Differential Revision: D102404260
Pulled By: dannyhchen
fbshipit-source-id: 21a0aa1ad8de12a935caf5642e41ccf2a47b46d9
Summary:
Pull Request resolved: https://github.com/facebook/rocksdb/pull/14658
Follow up to D101463511. Add a hook and a manager-aware overload of so custom CompressionManagers can provide human-readable names for custom compression types while preserving the existing generic fallback when no compatible manager is available.
Reviewed By: pdillinger
Differential Revision: D102201365
fbshipit-source-id: 0c7456bb9db2e54927a4349d12c035fc8b5ad562
Summary:
There is a separate way to handle incompatibility. Revert this.
- revert the temporary workaround from https://github.com/facebook/rocksdb/issues/14656 that serialized `InternalStats::CompactionStats::counts` with the pre-11.2 compaction-reason count
- restore remote compaction stats serialization to use the full `CompactionReason::kNumOfReasons` array size again
## Context
https://github.com/facebook/rocksdb/issues/14656 temporarily shrank the serialized `counts` array to keep remote compaction metadata readable across the 11.1/11.2 boundary. This follow-up removes that special case because the compatibility issue is being handled separately.
Pull Request resolved: https://github.com/facebook/rocksdb/pull/14663
Test Plan: - Not run in this metadata-prep task
Reviewed By: jaykorean
Differential Revision: D102376258
Pulled By: xingbowang
fbshipit-source-id: 55693ea25a97b70de9d53b0d6eebcbd88a325b1c
Summary:
Fixes a correctness bug in read-path range-tombstone synthesis when it races with `IngestExternalFile`. The synthesis path could insert a tombstone into the active memtable at a snapshot's sequence number, while ingestion installed an L0 SST at `LastSequence + 1` — a higher seqno than the synthesized tombstone. This breaks the main assumption of range tombstone reads that all lower levels have lower seqno.
The fix introduces a per-CF `port::RWMutex` (`ColumnFamilyData::ingest_sst_lock_`) plus a per-memtable `ingest_seqno_barrier_`. Ingestion takes the read lock and range tombstone synthesis **tries** to take a write lock.
If iterator lock is successful, then we have a new updated barrier seqno that we can validate the iterator seqno against. An added benefit is we no longer need to gate against empty memtable. This was originally added as an easy fix to prevent memtables from being inserted into while ingestion was happening.
## The bug, by example
`ReadPathRangeTombstoneTest.NewerPointInOlderFileStillVisible` (`db/db_iterator_test.cc:6929`):
1. L0 file `b@1, c@2, d@3`, then L0 file `Delete(b)4, Delete(c)5`.
2. Active memtable: `Put(z)6`. Snapshot taken at seq 6.
3. `IngestExternalFile({c → "vc_live"})` → installed at L0 with seq 7.
4. Iterator at snap 6 walks the deletion run and synthesizes `[b, d) @ seq 6` into the active memtable via `MemTable::AddLogicallyRedundantRangeTombstone`.
5. `Get("c")` at the latest snapshot: memtable returns covering tombstone (seq 6), `Version::Get` short-circuits, **never reads `c@7`** — returns `NotFound` instead of `"vc_live"`.
The invariant `Version::Get` relies on (memtable seqs ≥ any L0 seq for the same key) is broken because synthesis writes at the *snapshot's* seq while ingestion writes at `LastSequence + 1`.
Pull Request resolved: https://github.com/facebook/rocksdb/pull/14654
Test Plan:
- Updated regression test
- Re-enable crashtests and manually run
| Flavor | Jobs |
|---|---:|
| `fbcode_blackbox_crash_test` | 200 |
| `fbcode_whitebox_crash_test` | 30 |
| `fbcode_asan_blackbox_crash_test` | 30 |
| `fbcode_tsan_blackbox_crash_test` | 30 |
| `fbcode_crash_test_with_atomic_flush` | 30 |
| `fbcode_crash_test_with_wc_txn` | 30 |
| `fbcode_crash_test_with_ts` | 30 |
| **Total** | **380** |
Reviewed By: xingbowang
Differential Revision: D102044512
Pulled By: joshkang97
fbshipit-source-id: 0c69187595edc5a5fa80be24bffdba710a92e56e
Summary:
Pull Request resolved: https://github.com/facebook/rocksdb/pull/14637
Add public API ParseCompressionNameForDisplay() to render TableProperties::compression_name in human-readable form for both legacy and format_version >= 7 SST metadata, including BuiltinV2/compression-manager encodings and filtered no-compression markers for display.
Reviewed By: xingbowang
Differential Revision: D101463511
fbshipit-source-id: 51c44850183cb9757644a323376844adffc7a8c2
Summary:
- Keep remote compaction stats serialization compatible with RocksDB 11.1.
- Serialize `InternalStats::CompactionStats::counts` using the pre-11.2 compaction-reason count so remote compaction metadata remains readable across the version boundary.
- Preserve the existing formatting-only follow-up commit on the branch.
## Notes
- Needs a better mechanism to make OptionTypeInfo::Array ser/des friendly. Will follow up after 11.2 release.
Pull Request resolved: https://github.com/facebook/rocksdb/pull/14656
Reviewed By: pdillinger
Differential Revision: D102071507
Pulled By: xingbowang
fbshipit-source-id: 6eeb87d86494f528f0d1ce46ce4c3e8e7dd2da53
Summary:
This reverts commit `bad2d5b0af7e160de5ca58869f40941af0f9da95`.
The reverted change switched fbcode Buck dependencies from `//folly/experimental/coro:*` to `//folly/coro:*` in:
- `BUCK`
- `buckifier/buckify_rocksdb.py`
That change broke the internal build, so this PR restores the previous dependency paths.
## Testing
- Not run locally; this task only fetched, rebased, and verified the existing revert branch.
Pull Request resolved: https://github.com/facebook/rocksdb/pull/14652
Reviewed By: archang19
Differential Revision: D101980062
Pulled By: xingbowang
fbshipit-source-id: 9a6edf14c226caf87e2c63c7f2806d409dc809ef
Summary:
**Summary:**
Assert the DB::Open status before asserting on the DB pointer in FaultInjectionTest::OpenDB(). This avoids aborting the test process when reopen fails and preserves the underlying RocksDB error for ASSERT_OK(OpenDB()). This is to deal with recent failures on a host with nearby tests failing with space issue already.
```
[ RUN ] ExternalSSTFileBasicTest.LargeSizeSstFileWriter
db/external_sst_file_basic_test.cc:3303: Failure
sst_file_writer.Finish()
IO error: No space left on device: While appending to file: /dev/shm/rocksdb_testt/run-external_sst_file_basic_test-shard-3/external_sst_file_basic_test_578578_8746831521190564136/large_key.sst: No space left on device
[ FAILED ] ExternalSSTFileBasicTest.LargeSizeSstFileWriter (8551 ms)
[ RUN ] FaultTest/FaultInjectionTestSplitted.FaultTest/2
fault_injection_test: db/fault_injection_test.cc:269: rocksdb::Status rocksdb::FaultInjectionTest::OpenDB(): Assertion `db_ != nullptr' failed.
Received signal 6 (Aborted)
```
Pull Request resolved: https://github.com/facebook/rocksdb/pull/14646
Test Plan: Test changes only
Reviewed By: anand1976
Differential Revision: D101742874
Pulled By: hx235
fbshipit-source-id: de3b9349d9d067dd8f538b44ac08d108924faed3
Summary:
**Summary:**
When remote compaction is enabled with skip_stats_update_on_db_open=true, the remote worker's secondary DB skips UpdateAccumulatedStats(), leaving FileMetaData fields (num_entries, num_range_deletions) at 0. This breaks standalone range deletion file filtering in
FilterInputsForCompactionIterator() (https://github.com/facebook/rocksdb/blob/b374ba5968bdd6b16ff58918c561781c8bdab442/db/compaction/compaction.cc#L1085 + https://github.com/facebook/rocksdb/blob/b374ba5968bdd6b16ff58918c561781c8bdab442/db/version_edit.h#L462) , causing the primary and remote worker to disagree on input key count and triggering a "Compaction number of input keys does not match number of keys processed" corruption error.
Repro test (should be landed with the fix in the future): https://github.com/hx235/rocksdb/commit/aa1225c69cd6b6e2d2af735e1d1d9b147edfd6ae
```
[==========] Running 1 test from 1 test case.
[----------] Global test environment set-up.
[----------] 1 test from CompactionServiceTest
[ RUN ] CompactionServiceTest.StandaloneRangeDeletionWithSkipStatsUpdateOnOpen
db/compaction/compaction_service_test.cc:2970: Failure
s
Corruption: Compaction number of input keys does not match number of keys processed. Expected 0 but processed 4. Compaction summary: Base version 15 Base level 5, inputs: [20(1280B)], [18(1270B filtered:true) 19(1270B filtered:true)]
[ FAILED ] CompactionServiceTest.StandaloneRangeDeletionWithSkipStatsUpdateOnOpen (1257 ms)
[----------] 1 test from CompactionServiceTest (1257 ms total)
[----------] Global test environment tear-down
[==========] 1 test from 1 test case ran. (1257 ms total)
[ PASSED ] 0 tests.
[ FAILED ] 1 test, listed below:
[ FAILED ] CompactionServiceTest.StandaloneRangeDeletionWithSkipStatsUpdateOnOpen
1 FAILED TEST
```
This can happen even when standalone range deletion ingestion is disabled in the current run, because such files may have been ingested in a previous crash test run with different randomized options. So we disable skip_stats_update_on_db_open unconditionally when remote compaction is active until the real fix lands .
Pull Request resolved: https://github.com/facebook/rocksdb/pull/14647
Test Plan:
1. Verify skip_stats_update_on_db_open is forced to 0 with remote compaction
2. Verify skip_stats_update_on_db_open can still be 1 without remote compaction:
Reviewed By: anand1976
Differential Revision: D101744943
Pulled By: hx235
fbshipit-source-id: c1dcd8943433e8a9dfb7385c998be2c339e3b859
Summary:
**Summary:**
Temporarily disables inplace_update_support in db_crashtest.py. See the db_crashtest.py new comments for mow.
Pull Request resolved: https://github.com/facebook/rocksdb/pull/14645
Test Plan: - Run db_crashtest.py without passing inplace_update_support option, with short interval, and verify each run shows inplace_update_support is false in the db_stress command line.
Reviewed By: joshkang97
Differential Revision: D101739997
Pulled By: hx235
fbshipit-source-id: 39936b8282e392e688afea5e9bd074b60138f210
Summary:
Restore the iterator contract for blob-backed wide-column entities by eagerly materializing all blob-backed columns before a `DBIter` entry is exposed as valid. Also capture similar error inside compaction filter V4, so that the error is captured a surfaced up like older compaction filter V3.
## Problem
Lazy wide-column blob resolution let `DBIter` report `Valid() == true` before all columns were actually prepared. Callers could read `value()` successfully, then hit a blob-read failure in `columns()`, which flipped the iterator to invalid after the entry had already been observed as valid.
## Solution
- Restore back to old behavior.
- Resolve and materialize all blob-backed wide columns during iterator positioning.
- Keep `columns()` as a pure accessor once `Valid()` is true.
- Add coverage for eager blob resolution on iterator scans.
- Add coverage for blob resolution failures invalidating the iterator before the entry is exposed.
- Capture the same error in compaction filter and set db to bg error status if the error is not retriable.
## Next step
If we want lazy iterator resolution in the future, we will need an API that can surface lazy resolution failures explicitly instead of hiding I/O and status transitions inside value() or columns().
## Testing
- `make -j14 db_wide_blob_direct_write_test`
- `timeout 60s ./db_wide_blob_direct_write_test --gtest_filter='*DirectWriteIteratorValueScanEagerlyResolvesBlobColumns:*DirectWriteIteratorBlobResolutionErrorInvalidatesEntry'`
## Task
T265294130
# Bonus fix
## Non-compaction blob filtering fixes
### 1. Flush-time wide-entity lazy blob resolution now works correctly
Blob direct-write can leave wide-entity blob references in memtables before flush. Flush already runs through `CompactionIterator`, but outside a real compaction it did not have blob read support. As a result, `FilterV4` lazy resolution on flush could fail immediately with
`NotSupported("Blob fetcher not available")` instead of either:
- resolving the blob successfully, or
- surfacing the real blob read error and failing the flush
This stack fixes that by plumbing blob read support into non-compaction table-file creation. `BuildTable()` now gives `CompactionIterator` enough context to construct a `BlobFetcher` for flush/recovery table building, including write-path fallback for direct-write blob files
that are not yet manifest-visible.
With that in place:
- flush-time `FilterV4` can lazily resolve blob-backed wide columns
- if resolution fails, the failure is latched and flush fails after `FilterV4()` returns
- `bg_error` is set instead of silently preserving the entry
### 2. Plain blob fallback outside compaction now uses the resolved user value
For plain blob-backed values, `FilterBlobByKey()` is allowed to return `kUndetermined`, which is supposed to fall back to the normal value-based filter path. That fallback worked in compaction, but the non-compaction `BuildTable()` path still treated plain blob indexes as
unsupported/corrupt because it could not read the blob.
This stack fixes that behavior for flush/recovery table-file creation:
- when `FilterBlobByKey()` returns `kUndetermined`, RocksDB now eagerly resolves the plain blob value
- `FilterV2`/`FilterV3`/`FilterV4` then see the actual user value as `ValueType::kValue`, not the `BlobIndex` encoding
- legacy filters therefore behave the same way outside compaction as they already do inside compaction
Wide-column entities still use the `FilterV4` lazy resolver path. The plain-blob fix is specifically about restoring the documented fallback behavior for blob-backed `kValue` records outside compaction.
## Why this matters
Without these last two commits, flush-time filtering still had two inconsistent behaviors:
- wide-entity lazy resolution could not actually read blob-backed columns in the direct-write case
- plain blob-backed values could not fall back to normal value-based filtering outside compaction
So even after fixing iterator validity and compaction error propagation, non-compaction table-file creation still had remaining contract holes. These commits make flush/recovery behave consistently with compaction.
## Coverage added
The tests added in these commits cover:
- flush-time plain-blob `FilterV3` fallback using the resolved user value
- flush-time plain-blob `FilterV4` fallback using the resolved user value
- flush-time direct-write wide-entity lazy resolver success
- flush-time direct-write wide-entity lazy resolver failure on missing blob file, including flush failure and `bg_error` latching
Pull Request resolved: https://github.com/facebook/rocksdb/pull/14632
Reviewed By: anand1976
Differential Revision: D101425233
Pulled By: xingbowang
fbshipit-source-id: 695b2df5189033d30309b35849815e31fd965664
Summary:
Fix nightly build regressions introduced by recent CI/toolchain changes.
This PR includes two parts:
- CMake/link fixes for the Folly and Folly Lite nightly jobs
- a targeted nightly workflow fix for the clang-21 ASAN/UBSAN + Folly job
Changes:
- link gflags explicitly for USE_FOLLY CMake tool and benchmark targets
- resolve USE_FOLLY_LITE glog via its installed library path instead of bare -lglog
- in the clang-21 nightly job, build Folly/getdeps with gcc/g++ instead of inheriting clang-21 for third-party dependency builds
- disable ccache only for that standalone Folly build step so getdeps/CMake does not inject the broken ccache compiler launcher for ASM
Root cause:
- recent CI/container changes exposed missing explicit link dependencies in the CMake Folly paths
- the clang-21 nightly job exported CC/CXX at job scope, so Folly getdeps inherited clang-21 into libiberty/binutils build logic that expects GCC-style driver behavior such as -print-multi-os-directory
- the same standalone Folly build path also misbehaved when ccache was auto-detected and used as a compiler launcher for assembler-with-cpp inputs
Verification:
- make format-auto
- git diff --check
- local CMake configure sanity check for default config
- upstream nightly reruns used to confirm failure signatures before and after the first-round fixes
Pull Request resolved: https://github.com/facebook/rocksdb/pull/14609
Reviewed By: anand1976
Differential Revision: D100695693
Pulled By: xingbowang
fbshipit-source-id: 703546ad3ddc518ab80c936442709d65fe2d22af
Summary:
The prior fix (https://github.com/facebook/rocksdb/issues/14586) disabled read-path range tombstone synthesis at the `DBIter` level when `table_filter` was set. However, synthesized tombstones persist in the memtable beyond the lifetime of the iterator that created them. A prior unfiltered iterator can synthesize a range tombstone that then silently affects a subsequent filtered iterator's results — the filtered scan sees the tombstone but not the SSTs it was derived from, allowing hidden SST state to corrupt the filtered view. See failed crash test in T264151327.
This PR takes the stronger approach of rejecting iterator creation outright (`InvalidArgument`) when `ReadOptions::table_filter` is used on a column family with `min_tombstones_for_range_conversion > 0`. This eliminates the entire class of interaction bugs between the two features rather than trying to suppress conversion in individual code paths.
## Example
- `min_tombstones_for_range_conversion = 2`
- L1 SST_keep: `Put(a), Put(b), Put(c)` (`c` is the live boundary)
- L0 SST_dels: `Delete(a), Delete(b)` (2 contiguous tombstones, newer)
### Step 1 — Iterator A (no filter)
A walks `Del(a) Del(b)` (2 contig) then `c` (live).
Synthesizes range tombstone `[a, c)` into the active memtable.
### Step 2 — Iterator B (`table_filter` skips SST_dels)
B's filter excludes SST_dels, so `a, b` from SST_keep should appear live.
But the memtable now holds range tombstone `[a, c)` from step 1, which
applies to B regardless of `table_filter`. B sees only `c` —
**a, b are silently hidden**.
Pull Request resolved: https://github.com/facebook/rocksdb/pull/14618
Test Plan:
- `TableFilterNotAllowed` test validates the rejection path end-to-end: unfiltered scan synthesizes the tombstone, filtered iterator is rejected with `InvalidArgument`, and the full-DB view remains correct via `VerifyIteration`.
- Crash test sanitization ensures `db_stress` won't hit the incompatible configuration.
- Run crash test sanitization unit test: `python3 tools/db_crashtest_test.py`
- Run iterator tests: `make db_iterator_test && ./db_iterator_test --gtest_filter="*TableFilterNotAllowed*"`
Reviewed By: xingbowang
Differential Revision: D100873156
Pulled By: joshkang97
fbshipit-source-id: dd0d123d94b1bfda2a4a5040681fcc7cf14f760e
Summary:
There is an assumption in the code that within a given prefix all keys can be seen after a seek to that prefix. The problem occurs when there is a Next() followed by a Prev() back into the same prefix. The merging iterator actually uses SeekForPrev during Prev for non-child iterators, and as a result changes the prefix being used. Now that we are back to our original prefix, the view is incomplete.
The fix is to simply disable range tombstone conversion in this legacy prefix mode.
### Example
Use a 1-byte prefix extractor, so the prefix is just the first character.
Think of the merged iterator as combining two children:
- Child A: `b8`
- Child B: `b7, c1`
Global sorted order is:
```text
b7, b8, c1
```
So:
- predecessor of `c1` should be `b8`
- predecessor of `b8` should be `b7`
## Sequence
Start in legacy prefix mode:
- `total_order_seek = false`
- `prefix_same_as_start = false`
Now do:
1. `Seek("b8")`
2. `Next()`
3. `Prev()`
## What should happen
```text
Seek("b8") -> b8
Next() -> c1
Prev() -> b8
```
Because in the global order, `b8` is immediately before `c1`.
## What the buggy iterator did
```text
Seek("b8") -> b8
Next() -> c1
Prev() -> b7
```
So it skipped `b8`.
## Why it happens
When `Prev()` switches direction, the merging iterator tells all non-current
children to `SeekForPrev(current_key)`.
At that moment:
- current key is `c1`
- so the other children get `SeekForPrev("c1")`
But in legacy prefix mode, those child seeks are allowed to use prefix
filtering. So a child that only contains `b*` keys can effectively say:
```text
"I was asked for prefix c; I do not have prefix c."
```
That child drops out instead of returning its real global predecessor `b8`.
Then the current child simply moves back from `c1` to `b7`, and the merged
result becomes `b7`.
Pull Request resolved: https://github.com/facebook/rocksdb/pull/14625
Test Plan: Update unit tests to disable feature.
Reviewed By: xingbowang
Differential Revision: D101259748
Pulled By: joshkang97
fbshipit-source-id: 23e19c470f931406f96a34a7baebca89e91c7e39