mirror of
https://github.com/restic/restic.git
synced 2025-12-08 06:09:56 +00:00
index: add sub and intersect method to AssociatedSet
This commit is contained in:
parent
7e80536a9b
commit
0f05277b47
2 changed files with 112 additions and 0 deletions
|
|
@ -108,6 +108,40 @@ func (a *AssociatedSet[T]) Delete(bh restic.BlobHandle) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type haser interface {
|
||||||
|
Has(bh restic.BlobHandle) bool
|
||||||
|
}
|
||||||
|
|
||||||
|
// Intersect returns a new set containing the handles that are present in both sets.
|
||||||
|
func (a *AssociatedSet[T]) Intersect(other haser) *AssociatedSet[T] {
|
||||||
|
result := NewAssociatedSet[T](a.idx)
|
||||||
|
// Determining the smaller set already requires iterating over all keys
|
||||||
|
// and thus provides no performance benefit.
|
||||||
|
for bh := range a.Keys() {
|
||||||
|
if other.Has(bh) {
|
||||||
|
// preserve value receiver
|
||||||
|
val, _ := a.Get(bh)
|
||||||
|
result.Set(bh, val)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return result
|
||||||
|
}
|
||||||
|
|
||||||
|
// Sub returns a new set containing all handles that are present in a but not in
|
||||||
|
// other.
|
||||||
|
func (a *AssociatedSet[T]) Sub(other haser) *AssociatedSet[T] {
|
||||||
|
result := NewAssociatedSet[T](a.idx)
|
||||||
|
for bh := range a.Keys() {
|
||||||
|
if !other.Has(bh) {
|
||||||
|
val, _ := a.Get(bh)
|
||||||
|
result.Set(bh, val)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return result
|
||||||
|
}
|
||||||
|
|
||||||
func (a *AssociatedSet[T]) Len() int {
|
func (a *AssociatedSet[T]) Len() int {
|
||||||
count := 0
|
count := 0
|
||||||
for range a.All() {
|
for range a.All() {
|
||||||
|
|
|
||||||
|
|
@ -157,3 +157,81 @@ func TestAssociatedSetWithExtendedIndex(t *testing.T) {
|
||||||
test.Equals(t, list(bs), restic.BlobHandles(nil))
|
test.Equals(t, list(bs), restic.BlobHandles(nil))
|
||||||
test.Equals(t, 0, len(bs.overflow))
|
test.Equals(t, 0, len(bs.overflow))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestAssociatedSetIntersectAndSub(t *testing.T) {
|
||||||
|
mi := NewMasterIndex()
|
||||||
|
saver := &noopSaver{}
|
||||||
|
|
||||||
|
bh1, blob1 := makeFakePackedBlob()
|
||||||
|
bh2, blob2 := makeFakePackedBlob()
|
||||||
|
bh3, blob3 := makeFakePackedBlob()
|
||||||
|
bh4, blob4 := makeFakePackedBlob()
|
||||||
|
|
||||||
|
test.OK(t, mi.StorePack(context.TODO(), blob1.PackID, []restic.Blob{blob1.Blob}, saver))
|
||||||
|
test.OK(t, mi.StorePack(context.TODO(), blob2.PackID, []restic.Blob{blob2.Blob}, saver))
|
||||||
|
test.OK(t, mi.StorePack(context.TODO(), blob3.PackID, []restic.Blob{blob3.Blob}, saver))
|
||||||
|
test.OK(t, mi.StorePack(context.TODO(), blob4.PackID, []restic.Blob{blob4.Blob}, saver))
|
||||||
|
test.OK(t, mi.Flush(context.TODO(), saver))
|
||||||
|
|
||||||
|
t.Run("Intersect", func(t *testing.T) {
|
||||||
|
bs1, bs2 := NewAssociatedSet[uint8](mi), NewAssociatedSet[uint8](mi)
|
||||||
|
test.Equals(t, bs1.Intersect(bs2).Len(), 0)
|
||||||
|
|
||||||
|
bs1, bs2 = NewAssociatedSet[uint8](mi), NewAssociatedSet[uint8](mi)
|
||||||
|
bs1.Set(bh1, 10)
|
||||||
|
bs2.Set(bh2, 20)
|
||||||
|
test.Equals(t, bs1.Intersect(bs2).Len(), 0)
|
||||||
|
|
||||||
|
bs1, bs2 = NewAssociatedSet[uint8](mi), NewAssociatedSet[uint8](mi)
|
||||||
|
bs1.Set(bh3, 40)
|
||||||
|
bs2.Set(bh3, 50)
|
||||||
|
bs2.Set(bh4, 60)
|
||||||
|
result := bs1.Intersect(bs2)
|
||||||
|
test.Equals(t, result.Len(), 1)
|
||||||
|
val, _ := result.Get(bh3)
|
||||||
|
test.Equals(t, uint8(40), val)
|
||||||
|
|
||||||
|
bs1, bs2 = NewAssociatedSet[uint8](mi), NewAssociatedSet[uint8](mi)
|
||||||
|
bs1.Set(bh3, 40)
|
||||||
|
bs1.Set(bh4, 70)
|
||||||
|
bs2.Set(bh3, 50)
|
||||||
|
bs2.Set(bh4, 60)
|
||||||
|
result = bs1.Intersect(bs2)
|
||||||
|
test.Equals(t, result.Len(), 2)
|
||||||
|
val, _ = result.Get(bh3)
|
||||||
|
test.Equals(t, uint8(40), val)
|
||||||
|
val, _ = result.Get(bh4)
|
||||||
|
test.Equals(t, uint8(70), val)
|
||||||
|
})
|
||||||
|
|
||||||
|
t.Run("Sub", func(t *testing.T) {
|
||||||
|
bs1, bs2 := NewAssociatedSet[uint8](mi), NewAssociatedSet[uint8](mi)
|
||||||
|
test.Equals(t, bs1.Sub(bs2).Len(), 0)
|
||||||
|
|
||||||
|
bs1, bs2 = NewAssociatedSet[uint8](mi), NewAssociatedSet[uint8](mi)
|
||||||
|
bs1.Set(bh1, 10)
|
||||||
|
bs1.Set(bh2, 20)
|
||||||
|
bs2.Set(bh3, 30)
|
||||||
|
result := bs1.Sub(bs2)
|
||||||
|
test.Equals(t, result.Len(), 2)
|
||||||
|
val, _ := result.Get(bh1)
|
||||||
|
test.Equals(t, uint8(10), val)
|
||||||
|
val, _ = result.Get(bh2)
|
||||||
|
test.Equals(t, uint8(20), val)
|
||||||
|
|
||||||
|
bs1, bs2 = NewAssociatedSet[uint8](mi), NewAssociatedSet[uint8](mi)
|
||||||
|
bs1.Set(bh1, 10)
|
||||||
|
bs1.Set(bh2, 20)
|
||||||
|
bs1.Set(bh3, 40)
|
||||||
|
bs2.Set(bh2, 50)
|
||||||
|
result = bs1.Sub(bs2)
|
||||||
|
test.Equals(t, result.Len(), 2)
|
||||||
|
test.Assert(t, result.Has(bh1) && result.Has(bh3) && !result.Has(bh2), "only bh1 and bh3 should be in result")
|
||||||
|
|
||||||
|
bs1, bs2 = NewAssociatedSet[uint8](mi), NewAssociatedSet[uint8](mi)
|
||||||
|
bs1.Set(bh1, 60)
|
||||||
|
bs2.Set(bh1, 70)
|
||||||
|
bs2.Set(bh2, 80)
|
||||||
|
test.Equals(t, bs1.Sub(bs2).Len(), 0)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue