Commit Graph
48 Commits
Author SHA1 Message Date
Chris LuandGitHub 339a597e7e fix(vacuum): crash-safe compaction commit with a durable .cpc marker, fsync-before-rename, and a reload fence (#9944)
* storage: make vacuum/compaction commit crash-safe with a durable .cpc marker

A crash mid-compaction-commit could lose or corrupt volume data. The
two-rename commit (.cpd->.dat, .cpx->.idx) was not atomic, fsync results
were discarded before renaming over a healthy .dat, a stale .ldb could
poison the needle map, and a duplicate/late commit could delete the live
.dat/.idx outright.

Introduce a durable .cpc commit marker so the swap is atomic across a
crash:

- CommitCompact writes and fsyncs the .cpc marker after makeupDiff
  fsyncs the .cpd/.cpx, then runs applyCompactSwap: an existence-guarded
  rename of .cpd->.dat and .cpx->.idx, a directory fsync, removal of the
  stale .ldb/.rdb, and finally removal of the marker.
- reconcileCompactState recovers an interrupted commit on load: roll
  forward (finish the renames) when the marker is present, roll back
  (delete the orphan .cpd/.cpx) when it is absent. It runs from a
  directory pre-pass keyed on .cpd/.cpc existence, since the per-volume
  loader is keyed on .idx/.vif and misses the marker-only and
  already-renamed-.idx states.
- applyCompactSwap verifies BOTH .cpd and .cpx exist before touching the
  live files, so a stale-state commit (including the Windows
  RemoveAll-then-rename path) errors without deleting anything.
- Error-check the fsyncs that gate the swap: the .cpd close-fsync and
  .cpx fsync in copyDataBasedOnIndexFile, the makeupDiff .idx fsync, and
  MemDb.SaveToIdx.
- generateLevelDbFile rebuilds from offset 0 when the stored watermark
  sits past the end of the .idx, instead of replaying zero entries and
  poisoning the needle map.
- removeVolumeFiles and cleanupCompact sweep the .cpc marker; cleanup
  refuses to unlink the temp files while a marker is present.

Mirror the commit-marker, fsync-before-rename, guard, and
load/reconcile logic in the Rust volume server.

* storage: don't reconcile an already-loaded volume's compaction state on reload

reconcileCompactStates runs in loadExistingVolumes, which is re-invoked at
runtime on SIGHUP (Store.LoadNewVolumes). For a volume that is already loaded
and mid-vacuum, its .cpd/.cpx are live temp files, not crash leftovers --
rolling them back would clobber the in-flight compaction (and remove a live
.ldb out from under an open handle). Skip any vid already present in the
volume map; genuine startup recovery runs before any volume is loaded, so the
map is empty then. Mirrored in the Rust volume server.

Also drop the .note keepVif change that crept into this branch; it belongs to
the replica-copy/verify workstream and is restored to master's behavior here
so the two changes don't collide.

* storage: roll a compaction commit forward per-file, not all-or-nothing

A crash after the .cpd->.dat rename but before .cpx->.idx leaves .cpd gone,
.cpx and .cpc present, and a stale .idx. The roll-forward required BOTH temp
files, so it skipped the swap and cleared the marker, pairing the fresh .dat
with the stale .idx (index corruption). Finish whichever temp file remains:
extract finishCompactSwap to rename .cpd->.dat and/or .cpx->.idx independently;
applyCompactSwap keeps the both-present guard for the normal commit. Existence
in the Rust mirror is checked robustly so a transient error never skips the swap.

* seaweed-volume: propagate directory fsync failures on the compaction commit path

fsync_dir dropped every sync_all error, so the commit could proceed with an
undurable marker or rename and a later restart could recover the wrong
generation. Return the error and check it at the commit call sites (marker write
and the swap), matching the Go fsyncDir which already propagates. Directory
fsync stays a no-op on Windows, where it is unsupported.

* storage: overflow-safe stale-watermark check when rebuilding the leveldb index

watermark*NeedleMapEntrySize can overflow uint64 for a corrupted watermark and
wrap below the file size, defeating the stale-.ldb guard. Compare in entries
(watermark > size/NeedleMapEntrySize) instead, which is equivalent and cannot
overflow. LevelDb-backed needle map is Go-only; no Rust mirror.

* storage: propagate idxFile.Close error when writing the compacted index

SaveToIdx writes the .cpx that is renamed to .idx at commit; a discarded Close
error (buffered data not flushed) could leave a partially-written index after a
crash. Surface it in the same durability gate as the fsync.
2026-06-13 20:06:24 -07:00
Chris Lu e4b70c2521 go fix 2026-02-20 18:42:00 -08:00
Chris LuandGitHub ba74185700 fix: CompactMap race condition causing runtime panic (#8029)
Fixed critical race condition in CompactMap where Set(), Delete(), and
Get() methods had issues with concurrent map access.

Root cause: segmentForKey() can create new map segments, which modifies
the cm.segments map. Calling this under a read lock caused concurrent
map write panics when multiple goroutines accessed the map simultaneously
(e.g., during VolumeNeedleStatus gRPC calls).

Changes:
- Set() method: Changed RLock/RUnlock to Lock/Unlock
- Delete() method: Changed RLock/RUnlock to Lock/Unlock, optimized to
  avoid creating empty segments when key doesn't exist
- Get() method: Removed segmentForKey() call to avoid race condition,
  now checks segment existence directly and returns early if segment
  doesn't exist (optimization: avoids unnecessary segment creation)

This fix resolves the runtime/maps.fatal panic that occurred under
concurrent load.

Tested with race detector: go test -v -race ./weed/storage/needle_map/...
2026-01-14 14:12:49 -08:00
Chris LuandGitHub 7920ffa98c Fix uncleanable size=0 orphans with volume.fsck -forcePurging (#7783)
This is a follow-up fix to PR #7332 which partially addressed the issue.

The problem is that size=0 needles are in a gray area:
- IsValid() returns false for size=0 (because size must be > 0)
- IsDeleted() returns false for size=0 (because size must be < 0 or == TombstoneFileSize)

PR #7332 only fixed 2 places, but several other places still had the same bug:

1. needle_map_memory.go:doLoading - line 43 still used oldSize.IsValid()
2. needle_map_memory.go:DoOffsetLoading - used during vacuum and incremental loading
3. needle_map_leveldb.go:generateLevelDbFile - used when generating LevelDB needle maps
4. needle_map_leveldb.go:DoOffsetLoading - used during incremental loading for LevelDB
5. needle_map/compact_map.go:delete - couldn't delete size=0 entries because:
   - The condition 'size > 0' failed for size=0
   - Even if it passed, negating 0 gives 0 (not marking as deleted)

Changes:
- Changed size.IsValid() to !size.IsDeleted() in doLoading and DoOffsetLoading functions
- Fixed compact_map delete to use TombstoneFileSize for size=0 entries

Fixes #7293
2025-12-15 21:39:27 -08:00
Chris LuandGitHub 69553e5ba6 convert error fromating to %w everywhere (#6995) 2025-07-16 23:39:27 -07:00
Lisandro PinandGitHub 00c621abb8 Fix dumb typo in 08556257 (#6844) 2025-06-06 05:59:11 -07:00
Lisandro PinandGitHub bed0a64693 New needle_map.CompactMap() implementation for reduced memory usage (#6842)
* Rework `needle_map.CompactMap()` to maximize memory efficiency.

* Use a memory-efficient structure for `CompactMap` needle value entries.

This slightly complicates the code, but makes a **massive** difference
in memory efficiency - preliminary results show a ~30% reduction in
heap usage, with no measurable performance impact otherwise.

* Clean up type for `CompactMap` chunk IDs.

* Add a small comment description for `CompactMap()`.

* Add the old version of `CompactMap()` for comparison purposes.
2025-06-05 14:03:29 -07:00
Chris Lu 7151a54b28 Merge branch 'master' of https://github.com/seaweedfs/seaweedfs 2025-06-02 23:57:54 -07:00
Chris Lu b25561d0d7 3.89 2025-06-02 23:56:58 -07:00
Chris LuandGitHub d40746f34e fix insert beyond look back window (#6838) 2025-06-02 23:43:01 -07:00
Lisandro PinandGitHub 7204731749 Minor fix for the CompactMap() performance test. (#6836)
Per-entry memory usage is based on `TotalAllocs`, which is incorrect - that
value is a cummulative of heap usage, which doesn't decrease when objects
are freeed.

`Allocs` is instead an accurate represeentation of actual memory usage
at the time metrics are reported.
2025-06-02 17:09:01 -07:00
Lisandro PinandGitHub 9ffc8bcb54 Further improve memory usage of needle_map.CompactMap(). (#6825) 2025-05-28 11:42:00 -07:00
Lisandro PinandGitHub 2e1506c31e Rewrite needle_map.CompactMap() for more efficient memory usage (#6813) 2025-05-23 07:05:08 -07:00
chrislu cb50b720fd Revert "Fix weed fix"
This reverts commit 6c1ce18541.
2024-01-25 08:09:36 -08:00
chrislu 81f11883e3 go fmt 2023-11-26 11:47:20 -08:00
SmsS4andChris Lu 6c1ce18541 Fix weed fix 2023-11-20 11:14:19 -08:00
Konstantin LebedevandGitHub bf8a9d2db1 [volume.chek.disk] sync of deletions the fix (#3923)
* sync of deletions the fix

* avoid return if only partiallyDeletedNeedles

* refactor sync deletions
2022-10-30 20:32:46 -07:00
Konstantin LebedevandGitHub 764d9cb105 [voluche.chek.disk] needles older than the cutoff time are not missing yet (#3922)
needles older than the cutoff time are not missing yet

https://github.com/seaweedfs/seaweedfs/issues/3919
2022-10-28 12:12:20 -07:00
Konstantin LebedevandGitHub 1f7e52c63e vacuum metrics and force sync dst files (#3832) 2022-10-13 00:51:20 -07:00
b7de4a967e fix: compact_map get error mismatching cokie (#3748)
* fix: compact_map get error

* fix: CompactSection delete lock and move test to compact_map

Co-authored-by: shibinbin <shibinbin@megvii.com>
2022-10-09 16:56:40 -07:00
chrislu 21c0587900 go fmt 2022-09-14 23:06:44 -07:00
chrislu 26dbc6c905 move to https://github.com/seaweedfs/seaweedfs 2022-07-29 00:17:28 -07:00
guol-fnst ac694f0c8f rename parameter and reuse functions
rename milestone to  watermark
2022-07-20 17:00:40 +08:00
chrislu 509a9047db test compact map with snowflake sequencer 2022-06-23 21:45:51 -07:00
chrislu 625fd16a2e reduce upfront memory usage for low density volume 2022-06-16 15:39:29 -07:00
Chris Lu 7ce97b59d8 go fmt 2021-09-01 02:45:42 -07:00
Chris Lu 24e11d1e90 look back when adding to sorted values
look back when adding to sorted values, before adding it to overflow
2021-06-28 22:46:49 -07:00
Chris Lu fc8dd58aea volume: large_volume version has bug when using in memory index
fix https://github.com/chrislusf/seaweedfs/issues/2162
2021-06-28 15:48:07 -07:00
Chris Lu b465095db1 shell: add volume.check.disk to fix inconsistency for replicated volumes
fix https://github.com/chrislusf/seaweedfs/issues/1923
2021-03-22 00:03:16 -07:00
Chris Lu f2723c1bc8 do not idx file format
revert c9ab8d05fa
2020-09-12 12:42:36 -07:00
Chris Lu c9ab8d05fa fixes for reading deleted fid 2020-09-10 14:42:52 -07:00
Chris Lu 99ecf63276 go fmt 2020-08-29 22:28:33 -07:00
Chris Lu 3b4b1d4a77 fix tests 2020-08-19 01:37:56 -07:00
Chris Lu fe01191b5b support read option readDeleted=true 2020-08-18 19:22:16 -07:00
Chris Lu 6ccd7f0a4d refactoring 2020-08-18 18:01:37 -07:00
Chris Lu ee11d98650 refactoring 2020-08-18 17:35:19 -07:00
Chris Lu 6a92f0bc7a refactoring to typed Size
Go is amazing with refactoring!
2020-08-18 17:04:28 -07:00
Chris Lu f2e8ad6241 refactoring 2020-07-11 06:35:54 -07:00
Chris Lu 0871d2cff0 volume: fix memory leak during compaction
fix https://github.com/chrislusf/seaweedfs/issues/1222
2020-03-09 22:29:02 -07:00
Chris Lu acf7ca7b93 volume: fix compaction 2020-01-08 09:45:03 -08:00
Chris Lu 9ff72f616a go fmt 2019-12-24 14:56:16 -08:00
Chris Lu d8b39fe92a testing 2019-12-24 11:29:26 -08:00
Chris Lu abffe857a1 change btree map to in memory level db 2019-12-24 10:18:56 -08:00
Chris Lu ec75b2d761 volume: fix bug with 8000GB version if using in memory index
fix https://github.com/chrislusf/seaweedfs/issues/994
2019-06-27 12:18:45 -07:00
Chris Lu 3f9ecee40f working with reading remote intervals 2019-05-28 21:29:07 -07:00
Chris Lu 87f63b9c08 generate ec01~ec14, generate ecx file with sorted needle values 2019-05-18 22:46:24 -07:00
Chris Lu ac2727853f fix needle map entry size 2019-04-19 00:39:34 -07:00
Chris Lu e5506152c0 refactoring 2019-04-18 21:43:36 -07:00