forked from TrueCloudLab/frostfs-node
[#806] morph: Remove container list cache
Signed-off-by: Dmitrii Stepanov <d.stepanov@yadro.com>ttl_cache
parent
29fe8c41f3
commit
5cfb758e4e
|
@ -6,13 +6,11 @@ import (
|
||||||
|
|
||||||
"git.frostfs.info/TrueCloudLab/frostfs-node/pkg/core/container"
|
"git.frostfs.info/TrueCloudLab/frostfs-node/pkg/core/container"
|
||||||
"git.frostfs.info/TrueCloudLab/frostfs-node/pkg/core/netmap"
|
"git.frostfs.info/TrueCloudLab/frostfs-node/pkg/core/netmap"
|
||||||
cntClient "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/morph/client/container"
|
|
||||||
putsvc "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/services/object/put"
|
putsvc "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/services/object/put"
|
||||||
utilSync "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/util/sync"
|
utilSync "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/util/sync"
|
||||||
apistatus "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/client/status"
|
apistatus "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/client/status"
|
||||||
cid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/container/id"
|
cid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/container/id"
|
||||||
netmapSDK "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/netmap"
|
netmapSDK "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/netmap"
|
||||||
"git.frostfs.info/TrueCloudLab/frostfs-sdk-go/user"
|
|
||||||
lru "github.com/hashicorp/golang-lru/v2"
|
lru "github.com/hashicorp/golang-lru/v2"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -244,75 +242,6 @@ func (s *lruNetmapSource) Epoch() (uint64, error) {
|
||||||
return s.netState.CurrentEpoch(), nil
|
return s.netState.CurrentEpoch(), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// wrapper over TTL cache of values read from the network
|
|
||||||
// that implements container lister.
|
|
||||||
type ttlContainerLister struct {
|
|
||||||
inner *ttlNetCache[string, *cacheItemContainerList]
|
|
||||||
client *cntClient.Client
|
|
||||||
}
|
|
||||||
|
|
||||||
// value type for ttlNetCache used by ttlContainerLister.
|
|
||||||
type cacheItemContainerList struct {
|
|
||||||
// protects list from concurrent add/remove ops
|
|
||||||
mtx sync.RWMutex
|
|
||||||
// actual list of containers owner by the particular user
|
|
||||||
list []cid.ID
|
|
||||||
}
|
|
||||||
|
|
||||||
func newCachedContainerLister(c *cntClient.Client, ttl time.Duration) ttlContainerLister {
|
|
||||||
const containerListerCacheSize = 100
|
|
||||||
|
|
||||||
lruCnrListerCache := newNetworkTTLCache(containerListerCacheSize, ttl, func(strID string) (*cacheItemContainerList, error) {
|
|
||||||
var id *user.ID
|
|
||||||
|
|
||||||
if strID != "" {
|
|
||||||
id = new(user.ID)
|
|
||||||
|
|
||||||
err := id.DecodeString(strID)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
list, err := c.ContainersOf(id)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
return &cacheItemContainerList{
|
|
||||||
list: list,
|
|
||||||
}, nil
|
|
||||||
})
|
|
||||||
|
|
||||||
return ttlContainerLister{inner: lruCnrListerCache, client: c}
|
|
||||||
}
|
|
||||||
|
|
||||||
// List returns list of container IDs from the cache. If list is missing in the
|
|
||||||
// cache or expired, then it returns container IDs from side chain and updates
|
|
||||||
// the cache.
|
|
||||||
func (s ttlContainerLister) List(id *user.ID) ([]cid.ID, error) {
|
|
||||||
if id == nil {
|
|
||||||
return s.client.ContainersOf(nil)
|
|
||||||
}
|
|
||||||
|
|
||||||
item, err := s.inner.get(id.EncodeToString())
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
item.mtx.RLock()
|
|
||||||
res := make([]cid.ID, len(item.list))
|
|
||||||
copy(res, item.list)
|
|
||||||
item.mtx.RUnlock()
|
|
||||||
|
|
||||||
return res, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (s *ttlContainerLister) invalidate(owner user.ID) {
|
|
||||||
strOwner := owner.EncodeToString()
|
|
||||||
s.inner.remove(strOwner)
|
|
||||||
}
|
|
||||||
|
|
||||||
type cachedIRFetcher struct {
|
type cachedIRFetcher struct {
|
||||||
*ttlNetCache[struct{}, [][]byte]
|
*ttlNetCache[struct{}, [][]byte]
|
||||||
}
|
}
|
||||||
|
|
|
@ -63,7 +63,6 @@ func configureEACLAndContainerSources(c *cfg, client *cntClient.Client, cnrSrc c
|
||||||
// use RPC node as source of Container contract items (with caching)
|
// use RPC node as source of Container contract items (with caching)
|
||||||
cachedContainerStorage := newCachedContainerStorage(cnrSrc, c.cfgMorph.cacheTTL)
|
cachedContainerStorage := newCachedContainerStorage(cnrSrc, c.cfgMorph.cacheTTL)
|
||||||
cachedEACLStorage := newCachedEACLStorage(eACLFetcher, c.cfgMorph.cacheTTL)
|
cachedEACLStorage := newCachedEACLStorage(eACLFetcher, c.cfgMorph.cacheTTL)
|
||||||
cachedContainerLister := newCachedContainerLister(client, c.cfgMorph.cacheTTL)
|
|
||||||
|
|
||||||
subscribeToContainerCreation(c, func(e event.Event) {
|
subscribeToContainerCreation(c, func(e event.Event) {
|
||||||
ev := e.(containerEvent.PutSuccess)
|
ev := e.(containerEvent.PutSuccess)
|
||||||
|
@ -74,7 +73,6 @@ func configureEACLAndContainerSources(c *cfg, client *cntClient.Client, cnrSrc c
|
||||||
// creation success are most commonly tracked by polling GET op.
|
// creation success are most commonly tracked by polling GET op.
|
||||||
cnr, err := cnrSrc.Get(ev.ID)
|
cnr, err := cnrSrc.Get(ev.ID)
|
||||||
if err == nil {
|
if err == nil {
|
||||||
cachedContainerLister.invalidate(cnr.Value.Owner())
|
|
||||||
cachedContainerStorage.containerCache.set(ev.ID, cnr, nil)
|
cachedContainerStorage.containerCache.set(ev.ID, cnr, nil)
|
||||||
} else {
|
} else {
|
||||||
// unlike removal, we expect successful receive of the container
|
// unlike removal, we expect successful receive of the container
|
||||||
|
@ -92,13 +90,7 @@ func configureEACLAndContainerSources(c *cfg, client *cntClient.Client, cnrSrc c
|
||||||
|
|
||||||
subscribeToContainerRemoval(c, func(e event.Event) {
|
subscribeToContainerRemoval(c, func(e event.Event) {
|
||||||
ev := e.(containerEvent.DeleteSuccess)
|
ev := e.(containerEvent.DeleteSuccess)
|
||||||
|
|
||||||
cachedContainerStorage.handleRemoval(ev.ID)
|
cachedContainerStorage.handleRemoval(ev.ID)
|
||||||
info, err := cachedContainerStorage.DeletionInfo(ev.ID)
|
|
||||||
if err == nil {
|
|
||||||
cachedContainerLister.invalidate(info.Owner)
|
|
||||||
}
|
|
||||||
|
|
||||||
c.log.Debug(logs.FrostFSNodeContainerRemovalEventsReceipt,
|
c.log.Debug(logs.FrostFSNodeContainerRemovalEventsReceipt,
|
||||||
zap.Stringer("id", ev.ID),
|
zap.Stringer("id", ev.ID),
|
||||||
)
|
)
|
||||||
|
@ -107,7 +99,7 @@ func configureEACLAndContainerSources(c *cfg, client *cntClient.Client, cnrSrc c
|
||||||
c.cfgObject.eaclSource = cachedEACLStorage
|
c.cfgObject.eaclSource = cachedEACLStorage
|
||||||
c.cfgObject.cnrSource = cachedContainerStorage
|
c.cfgObject.cnrSource = cachedContainerStorage
|
||||||
|
|
||||||
cnrRdr.lister = cachedContainerLister
|
cnrRdr.lister = client
|
||||||
cnrRdr.eacl = c.cfgObject.eaclSource
|
cnrRdr.eacl = c.cfgObject.eaclSource
|
||||||
cnrRdr.src = c.cfgObject.cnrSource
|
cnrRdr.src = c.cfgObject.cnrSource
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue