Skip to content

Commit 5449c7a

Browse files
authored
Merge pull request #525 from authzed/fix-roaring64-or-cow
roaring64: honor copy-on-write in Bitmap.Or
2 parents 6d3d113 + 8746862 commit 5449c7a

2 files changed

Lines changed: 30 additions & 1 deletion

File tree

roaring64/roaring64.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -700,7 +700,7 @@ main:
700700
}
701701
s2 = x2.highlowcontainer.getKeyAtIndex(pos2)
702702
} else {
703-
rb.highlowcontainer.getContainerAtIndex(pos1).Or(x2.highlowcontainer.getContainerAtIndex(pos2))
703+
rb.highlowcontainer.getWritableContainerAtIndex(pos1).Or(x2.highlowcontainer.getContainerAtIndex(pos2))
704704
pos1++
705705
pos2++
706706
if (pos1 == length1) || (pos2 == length2) {

roaring64/roaring64cow_test.go

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1768,3 +1768,32 @@ func TestCloneCOWContainers(t *testing.T) {
17681768

17691769
//assert.EqualValues(t, rb.ToArray(), newRb1.ToArray())
17701770
}
1771+
1772+
// TestOrCOWSharedContainer verifies that in-place Or on a CoW-cloned bitmap
1773+
// does not mutate containers shared with the clone source.
1774+
func TestOrCOWSharedContainer(t *testing.T) {
1775+
rb1 := NewBitmap()
1776+
rb1.SetCopyOnWrite(true)
1777+
// Populate a single high-key container with values in [0, 1000).
1778+
for i := uint64(0); i < 1000; i++ {
1779+
rb1.Add(i)
1780+
}
1781+
1782+
// Clone: rb2 shares rb1's container, with needCopyOnWrite set on both sides.
1783+
rb2 := rb1.Clone()
1784+
1785+
// x has values in the same high-key container that are not already in rb1/rb2.
1786+
x := NewBitmap()
1787+
for i := uint64(1000); i < 2000; i++ {
1788+
x.Add(i)
1789+
}
1790+
1791+
// In-place Or into rb1. Must NOT mutate the container shared with rb2.
1792+
rb1.Or(x)
1793+
1794+
assert.EqualValues(t, 2000, rb1.GetCardinality())
1795+
assert.EqualValues(t, 1000, rb2.GetCardinality(),
1796+
"rb2 was corrupted: Or on rb1 mutated a CoW-shared container")
1797+
assert.False(t, rb2.Contains(1500),
1798+
"rb2 was corrupted: contains a value that was only added to rb1")
1799+
}

0 commit comments

Comments
 (0)