Files
seaweedfs/weed/storage/store_delete_collection_test.go
Chris LuandGitHub a2ffc7aadf heartbeat: keep the master current through collection churn (#10657)
* heartbeat: name departed volumes in delta heartbeats

* master: release the lookup index with a deleted collection

* master: keep a fresh grow safe from the report that raced it

* volume: name the volumes a deleted collection took with it

Deleting a collection left the master to work out what went by omission from
the next full volume list, which it no longer gets: heartbeats carry the whole
list only when the master asks for it. The volumes a bucket's churn creates and
destroys between two of those requests are never named in either direction, so
the master keeps counting their slots as occupied and a cluster that creates
and drops collections quickly runs its free-slot accounting dry -- assigns fail
with no free volumes left while the disk holds a handful of volumes.

The destroy path already knows exactly which volumes it removed, so send them
down the same channel every other deletion uses.

* rust: name the volumes a deleted collection took with it

Mirrors the Go volume server. The notify path derives its deltas by diffing
snapshots, so a collection delete that does not wake it is invisible until the
master next asks for the whole list.
2026-08-08 20:23:10 -07:00

47 lines
1.5 KiB
Go

package storage
import (
"testing"
"github.com/seaweedfs/seaweedfs/weed/storage/needle"
"github.com/seaweedfs/seaweedfs/weed/storage/super_block"
)
func mountCollectionVolume(t *testing.T, loc *DiskLocation, vid needle.VolumeId, collection string) {
t.Helper()
v, err := NewVolume(loc.Directory, loc.IdxDirectory, collection, vid, NeedleMapInMemory,
&super_block.ReplicaPlacement{}, &needle.TTL{}, 0, needle.GetCurrentVersion(), 0, 0)
if err != nil {
t.Fatal(err)
}
loc.SetVolume(vid, v)
}
// A collection deleted between two heartbeats is the deletion no report would
// ever name: its volumes can be grown and destroyed without a single list
// mentioning them, so nothing but this would tell the master their slots came
// free.
func TestDeleteCollectionNamesTheVolumesItDestroyed(t *testing.T) {
store := newTestStore(t, 1)
mountCollectionVolume(t, store.Locations[0], 1, "books")
mountCollectionVolume(t, store.Locations[0], 2, "books")
mountCollectionVolume(t, store.Locations[0], 3, "movies")
if err := store.DeleteCollection("books"); err != nil {
t.Fatal(err)
}
named := make(map[uint32]string)
for len(store.DeletedVolumesChan) > 0 {
m := <-store.DeletedVolumesChan
named[m.Id] = m.Collection
}
if len(named) != 2 || named[1] != "books" || named[2] != "books" {
t.Fatalf("delete named %v, want volumes 1 and 2 of books", named)
}
if _, found := store.Locations[0].FindVolume(3); !found {
t.Error("another collection's volume was destroyed")
}
}