mirror of
https://github.com/Icinga/icingadb.git
synced 2026-05-28 04:35:54 -04:00
Delta#start(): avoid a race across maps by using a mutex
Imagine an Icinga restart w/o any config changes and a full dump already being done. One goroutine reads Redis, the other the database. Both get the same object at the same time and check it in the map of the other goroutine - not present. So they store it in their own map. I.e. the same object hasn't been changed, but has to be deleted and inserted. If the insert comes first, that causes a duplicate key error.
This commit is contained in:
parent
d1b1693d14
commit
d36928afd3
1 changed files with 9 additions and 0 deletions
|
|
@ -46,6 +46,7 @@ func (delta *Delta) start(ctx context.Context, actualCh, desiredCh <-chan contra
|
|||
}
|
||||
actual := sync.Map{}
|
||||
desired := sync.Map{}
|
||||
var mtx sync.Mutex
|
||||
g, ctx := errgroup.WithContext(ctx)
|
||||
|
||||
g.Go(func() error {
|
||||
|
|
@ -61,14 +62,18 @@ func (delta *Delta) start(ctx context.Context, actualCh, desiredCh <-chan contra
|
|||
}
|
||||
|
||||
id := a.ID().String()
|
||||
mtx.Lock()
|
||||
|
||||
if d, ok := desired.Load(id); ok {
|
||||
desired.Delete(id)
|
||||
mtx.Unlock()
|
||||
|
||||
if delta.WithChecksum && !a.(contracts.Checksumer).Checksum().Equal(d.(contracts.Checksumer).Checksum()) {
|
||||
update.Store(id, d)
|
||||
}
|
||||
} else {
|
||||
actual.Store(id, a)
|
||||
mtx.Unlock()
|
||||
}
|
||||
|
||||
cnt.Inc()
|
||||
|
|
@ -91,14 +96,18 @@ func (delta *Delta) start(ctx context.Context, actualCh, desiredCh <-chan contra
|
|||
}
|
||||
|
||||
id := d.ID().String()
|
||||
mtx.Lock()
|
||||
|
||||
if a, ok := actual.Load(id); ok {
|
||||
actual.Delete(id)
|
||||
mtx.Unlock()
|
||||
|
||||
if delta.WithChecksum && !a.(contracts.Checksumer).Checksum().Equal(d.(contracts.Checksumer).Checksum()) {
|
||||
update.Store(id, d)
|
||||
}
|
||||
} else {
|
||||
desired.Store(id, d)
|
||||
mtx.Unlock()
|
||||
}
|
||||
|
||||
cnt.Inc()
|
||||
|
|
|
|||
Loading…
Reference in a new issue