forked from TrueCloudLab/frostfs-node
[#1445] services/tree: Cache the list of container nodes
Signed-off-by: Evgenii Stratonikov <evgeniy@nspcc.ru>
This commit is contained in:
parent
a2edfec0c3
commit
39f47f61c6
4 changed files with 142 additions and 55 deletions
90
pkg/services/tree/container.go
Normal file
90
pkg/services/tree/container.go
Normal file
|
@ -0,0 +1,90 @@
|
|||
package tree
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"crypto/sha256"
|
||||
"fmt"
|
||||
"sync"
|
||||
|
||||
"github.com/hashicorp/golang-lru/simplelru"
|
||||
"github.com/nspcc-dev/neofs-node/pkg/core/container"
|
||||
"github.com/nspcc-dev/neofs-node/pkg/services/object_manager/placement"
|
||||
cidSDK "github.com/nspcc-dev/neofs-sdk-go/container/id"
|
||||
netmapSDK "github.com/nspcc-dev/neofs-sdk-go/netmap"
|
||||
)
|
||||
|
||||
type containerCache struct {
|
||||
sync.Mutex
|
||||
nm *netmapSDK.NetMap
|
||||
lru *simplelru.LRU
|
||||
}
|
||||
|
||||
func (c *containerCache) init() {
|
||||
c.lru, _ = simplelru.NewLRU(defaultContainerCacheSize, nil) // no error, size is positive
|
||||
}
|
||||
|
||||
type containerCacheItem struct {
|
||||
cnr *container.Container
|
||||
local int
|
||||
nodes []netmapSDK.NodeInfo
|
||||
}
|
||||
|
||||
const defaultContainerCacheSize = 10
|
||||
|
||||
// getContainerNodes returns nodes in the container and a position of local key in the list.
|
||||
func (s *Service) getContainerNodes(cid cidSDK.ID) ([]netmapSDK.NodeInfo, int, error) {
|
||||
nm, err := s.nmSource.GetNetMap(0)
|
||||
if err != nil {
|
||||
return nil, -1, fmt.Errorf("can't get netmap: %w", err)
|
||||
}
|
||||
|
||||
cnr, err := s.cnrSource.Get(cid)
|
||||
if err != nil {
|
||||
return nil, -1, fmt.Errorf("can't get container: %w", err)
|
||||
}
|
||||
|
||||
cidStr := cid.String()
|
||||
|
||||
s.containerCache.Lock()
|
||||
if s.containerCache.nm != nm {
|
||||
s.containerCache.lru.Purge()
|
||||
} else if v, ok := s.containerCache.lru.Get(cidStr); ok {
|
||||
item := v.(containerCacheItem)
|
||||
if item.cnr == cnr {
|
||||
s.containerCache.Unlock()
|
||||
return item.nodes, item.local, nil
|
||||
}
|
||||
}
|
||||
s.containerCache.Unlock()
|
||||
|
||||
policy := cnr.Value.PlacementPolicy()
|
||||
|
||||
rawCID := make([]byte, sha256.Size)
|
||||
cid.Encode(rawCID)
|
||||
|
||||
cntNodes, err := nm.ContainerNodes(policy, rawCID)
|
||||
if err != nil {
|
||||
return nil, -1, err
|
||||
}
|
||||
|
||||
nodes := placement.FlattenNodes(cntNodes)
|
||||
|
||||
localPos := -1
|
||||
for i := range nodes {
|
||||
if bytes.Equal(nodes[i].PublicKey(), s.rawPub) {
|
||||
localPos = i
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
s.containerCache.Lock()
|
||||
s.containerCache.nm = nm
|
||||
s.containerCache.lru.Add(cidStr, containerCacheItem{
|
||||
cnr: cnr,
|
||||
local: localPos,
|
||||
nodes: nodes,
|
||||
})
|
||||
s.containerCache.Unlock()
|
||||
|
||||
return nodes, localPos, err
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue