cockroachdb / cockroachdb/swiss

Mutating the map while iterating All() is unhealthy

Open
#20 6 comments 0 reactions 0 assignees View on GitHub
Dominant language
Go
Stars
477
Forks
21
Avg merge
1d 3h
Merged PRs (30d)
1

Description

There's two ways in which the following test case fails. It either fails because the same key is seen twice or `require.EqualValues(t, e, vals)` fails because some of the expected keys were not seen at all. So run it multiple times to see both behaviours. The bug is somehow caused by the fact that during splitting the original bucket instance is reused but I forgot my thought process on how I arrived there.

```golang
func TestIterateMutate2(t *testing.T) {
for repeat := 0; repeat < 10*1000; repeat++ {
m := New[int, int](0)
// initialize map so that it will split during the Put()s done during All()
for i := 0; i < int(defaultMaxBucketCapacity*groupSize*3/4); i++ {
m.Put(i, i)
}
e := m.toBuiltinMap()
require.EqualValues(t, (defaultMaxBucketCapacity * groupSize * 3 / 4), m.Len())
require.EqualValues(t, (defaultMaxBucketCapacity * groupSize * 3 / 4), len(e))

// Iterate over the map, occasionally inserting new entries to it.
vals := make(map[int]int)
fools := make(map[int]int)
fool := m.Len() + 10
foolstart := fool
m.All(func(k, v int) bool {
if (k % 10) == 0 {
m.Put(fool, fool)
fool++
}
if k >= foolstart {
// Did we see this key already?
if v2, ok := fools[k]; ok {
t.Fatalf("visiting key %v for the second time! Previously we got value %v, now %v", k, v2, v)
}
fools[k] = v
return true
}
// Did we see this key already?
if v2, ok := vals[k]; ok {
t.Fatalf("visiting key %v for the second time! Previously we got value %v, now %v", k, v2, v)
}
vals[k] = v
return true
})
require.EqualValues(t, e, vals)
}
}
```

Contributor guide

No contributing guide indexed for this repository

Assessment

This issue has not been assessed yet.

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.