Merge pull request #2499 from nspcc-dev/fix-concurrent-seek

core: avoid concurrent map iteration and map write during SeekAsync over private MemCachedStore
This commit is contained in:
Roman Khimov 2022-05-18 11:36:57 +03:00 committed by GitHub
commit 34e7d3e53c
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
2 changed files with 13 additions and 2 deletions

View file

@ -195,7 +195,14 @@ func storageFind(ic *interop.Context) error {
seekres := ic.DAO.SeekAsync(ctx, stc.ID, storage.SeekRange{Prefix: prefix})
item := istorage.NewIterator(seekres, prefix, opts)
ic.VM.Estack().PushItem(stackitem.NewInterop(item))
ic.RegisterCancelFunc(cancel)
ic.RegisterCancelFunc(func() {
cancel()
// Underlying persistent store is likely to be a private MemCachedStore. Thus,
// to avoid concurrent map iteration and map write we need to wait until internal
// seek goroutine is finished, because it can access underlying persistent store.
for range seekres {
}
})
return nil
}

View file

@ -969,7 +969,11 @@ func (n *NEO) getAllCandidatesCall(ic *interop.Context, _ []stackitem.Item) stac
opts := istorage.FindRemovePrefix | istorage.FindDeserialize | istorage.FindPick1
item := istorage.NewIterator(filteredRes, prefix, int64(opts))
ic.RegisterCancelFunc(cancel)
ic.RegisterCancelFunc(func() {
cancel()
for range seekres {
}
})
return stackitem.NewInterop(item)
}