[#2037] services/object: Fix concurrent map writes in traverser
``` fatal error: concurrent map writes goroutine 4337 [running]: github.com/nspcc-dev/neofs-node/pkg/services/object/put.(*traversal).submitProcessed(...) github.com/nspcc-dev/neofs-node/pkg/services/object/put/distributed.go:78 github.com/nspcc-dev/neofs-node/pkg/services/object/put.(*distributedTarget).iteratePlacement.func1() github.com/nspcc-dev/neofs-node/pkg/services/object/put/distributed.go:198 +0x265 github.com/panjf2000/ants/v2.(*goWorker).run.func1() github.com/panjf2000/ants/v2@v2.4.0/worker.go:68 +0x97 created by github.com/panjf2000/ants/v2.(*goWorker).run github.com/panjf2000/ants/v2@v2.4.0/worker.go:48 +0x65 ``` Signed-off-by: Evgenii Stratonikov <evgeniy@morphbits.ru>
This commit is contained in:
parent
37f813604f
commit
2522d924b9
2 changed files with 12 additions and 2 deletions
|
@ -21,6 +21,7 @@ Changelog for NeoFS Node
|
||||||
- `neofs-cli lock object`'s `lifetime` flag handling (#1972)
|
- `neofs-cli lock object`'s `lifetime` flag handling (#1972)
|
||||||
- Do not move write-cache in read-only mode for flushing (#1906)
|
- Do not move write-cache in read-only mode for flushing (#1906)
|
||||||
- Child object collection on CLI side with a bearer token (#2000)
|
- Child object collection on CLI side with a bearer token (#2000)
|
||||||
|
- Fix concurrent map writes in `Object.Put` service
|
||||||
|
|
||||||
### Removed
|
### Removed
|
||||||
### Updated
|
### Updated
|
||||||
|
|
|
@ -48,6 +48,9 @@ type traversal struct {
|
||||||
// need of additional broadcast after the object is saved
|
// need of additional broadcast after the object is saved
|
||||||
extraBroadcastEnabled bool
|
extraBroadcastEnabled bool
|
||||||
|
|
||||||
|
// mtx protects mExclude map.
|
||||||
|
mtx sync.RWMutex
|
||||||
|
|
||||||
// container nodes which was processed during the primary object placement
|
// container nodes which was processed during the primary object placement
|
||||||
mExclude map[string]struct{}
|
mExclude map[string]struct{}
|
||||||
}
|
}
|
||||||
|
@ -71,17 +74,23 @@ func (x *traversal) submitPrimaryPlacementFinish() bool {
|
||||||
// marks the container node as processed during the primary object placement.
|
// marks the container node as processed during the primary object placement.
|
||||||
func (x *traversal) submitProcessed(n placement.Node) {
|
func (x *traversal) submitProcessed(n placement.Node) {
|
||||||
if x.extraBroadcastEnabled {
|
if x.extraBroadcastEnabled {
|
||||||
|
key := string(n.PublicKey())
|
||||||
|
|
||||||
|
x.mtx.Lock()
|
||||||
if x.mExclude == nil {
|
if x.mExclude == nil {
|
||||||
x.mExclude = make(map[string]struct{}, 1)
|
x.mExclude = make(map[string]struct{}, 1)
|
||||||
}
|
}
|
||||||
|
|
||||||
x.mExclude[string(n.PublicKey())] = struct{}{}
|
x.mExclude[key] = struct{}{}
|
||||||
|
x.mtx.Unlock()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// checks if specified node was processed during the primary object placement.
|
// checks if specified node was processed during the primary object placement.
|
||||||
func (x traversal) processed(n placement.Node) bool {
|
func (x *traversal) processed(n placement.Node) bool {
|
||||||
|
x.mtx.RLock()
|
||||||
_, ok := x.mExclude[string(n.PublicKey())]
|
_, ok := x.mExclude[string(n.PublicKey())]
|
||||||
|
x.mtx.RUnlock()
|
||||||
return ok
|
return ok
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue