[#1248] placement: Use epoch to track netmap versions
Previously we used pointer, this could have worked, because most of the time, the netmap is cached. This didn't work, however, because `lastNm` field was always nil. Rework the mechanism completely: 1. Use epoch to track netmap versions, as it it simpler and is unrelated to the TTL of an underlying cache. 2. Fix a bug where the epoch could change while mutex was unlocked. Signed-off-by: Evgenii Stratonikov <e.stratonikov@yadro.com>
This commit is contained in:
parent
21431f22c0
commit
3a48b282b6
1 changed files with 9 additions and 5 deletions
|
@ -14,9 +14,10 @@ import (
|
|||
|
||||
type netMapBuilder struct {
|
||||
nmSrc netmap.Source
|
||||
// mtx protects lastNm and containerCache fields.
|
||||
// mtx protects lastEpoch and containerCache fields.
|
||||
mtx sync.Mutex
|
||||
lastNm *netmapSDK.NetMap
|
||||
// lastEpoch contains contains network map epoch for all values in the container cache.
|
||||
lastEpoch uint64
|
||||
// containerCache caches container nodes by ID. It is used to skip `GetContainerNodes` invocation if
|
||||
// neither netmap nor container has changed.
|
||||
containerCache simplelru.LRUCache[cid.ID, [][]netmapSDK.NodeInfo]
|
||||
|
@ -61,13 +62,14 @@ func (b *netMapBuilder) BuildPlacement(cnr cid.ID, obj *oid.ID, p netmapSDK.Plac
|
|||
cnr.Encode(binCnr)
|
||||
|
||||
b.mtx.Lock()
|
||||
if nm == b.lastNm {
|
||||
if nm.Epoch() == b.lastEpoch {
|
||||
raw, ok := b.containerCache.Get(cnr)
|
||||
b.mtx.Unlock()
|
||||
if ok {
|
||||
return BuildObjectPlacement(nm, raw, obj)
|
||||
}
|
||||
} else {
|
||||
b.lastEpoch = nm.Epoch()
|
||||
b.containerCache.Purge()
|
||||
b.mtx.Unlock()
|
||||
}
|
||||
|
@ -78,7 +80,9 @@ func (b *netMapBuilder) BuildPlacement(cnr cid.ID, obj *oid.ID, p netmapSDK.Plac
|
|||
}
|
||||
|
||||
b.mtx.Lock()
|
||||
if b.lastEpoch == nm.Epoch() {
|
||||
b.containerCache.Add(cnr, cn)
|
||||
}
|
||||
b.mtx.Unlock()
|
||||
|
||||
return BuildObjectPlacement(nm, cn, obj)
|
||||
|
|
Loading…
Reference in a new issue