Skip to content

Commit

Permalink
add cache for resource view
Browse files Browse the repository at this point in the history
With the addition of the overprovision parameter, we potentially start a lot
of requests for the resource view. So we add a cache for this call, in the
same way we have a cache for the node state and storage pools.

Signed-off-by: Moritz Wanzenböck <[email protected]>
  • Loading branch information
WanzenBug committed Nov 9, 2023
1 parent 086958e commit 0a16f92
Showing 1 changed file with 72 additions and 15 deletions.
87 changes: 72 additions & 15 deletions pkg/linstor/highlevelclient/high_level_client.go
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ import (
"sync"
"time"

lc "github.com/LINBIT/golinstor"
lapi "github.com/LINBIT/golinstor/client"
"github.com/container-storage-interface/spec/lib/go/csi"

Expand Down Expand Up @@ -52,6 +53,11 @@ func NewHighLevelClient(options ...lapi.Option) (*HighLevelClient, error) {
timeout: 1 * time.Minute,
}

c.Resources = &ResourceCacheProvider{
ResourceProvider: c.Resources,
timeout: 1 * time.Minute,
}

return &HighLevelClient{Client: c}, nil
}

Expand Down Expand Up @@ -215,7 +221,7 @@ func (n *NodeCacheProvider) GetAll(ctx context.Context, opts ...*lapi.ListOpts)
if n.nodesUpdated.Add(n.timeout).After(now) {
return filter(n.nodes, func(node lapi.Node) string {
return node.Name
}, opts...), nil
}, nil, opts...), nil
}

nodes, err := n.NodeProvider.GetAll(ctx)
Expand All @@ -228,7 +234,7 @@ func (n *NodeCacheProvider) GetAll(ctx context.Context, opts ...*lapi.ListOpts)

return filter(n.nodes, func(node lapi.Node) string {
return node.Name
}, opts...), nil
}, nil, opts...), nil
}

func (n *NodeCacheProvider) GetStoragePoolView(ctx context.Context, opts ...*lapi.ListOpts) ([]lapi.StoragePool, error) {
Expand All @@ -238,9 +244,11 @@ func (n *NodeCacheProvider) GetStoragePoolView(ctx context.Context, opts ...*lap
now := time.Now()

if n.poolsUpdated.Add(n.timeout).After(now) {
return filter(n.pools, func(pool lapi.StoragePool) string {
return pool.NodeName
}, opts...), nil
return filter(n.pools,
func(pool lapi.StoragePool) string { return pool.NodeName },
func(pool lapi.StoragePool) string { return pool.StoragePoolName },
opts...,
), nil
}

pools, err := n.NodeProvider.GetStoragePoolView(ctx)
Expand All @@ -251,30 +259,79 @@ func (n *NodeCacheProvider) GetStoragePoolView(ctx context.Context, opts ...*lap
n.pools = pools
n.poolsUpdated = now

return filter(n.pools, func(pool lapi.StoragePool) string {
return pool.NodeName
}, opts...), nil
return filter(n.pools,
func(pool lapi.StoragePool) string { return pool.NodeName },
func(pool lapi.StoragePool) string { return pool.StoragePoolName },
opts...,
), nil
}

type ResourceCacheProvider struct {
lapi.ResourceProvider
timeout time.Duration
resourceViewMu sync.Mutex
resourceViewUpdated time.Time
resourceView []lapi.ResourceWithVolumes
}

func (r *ResourceCacheProvider) GetResourceView(ctx context.Context, opts ...*lapi.ListOpts) ([]lapi.ResourceWithVolumes, error) {
r.resourceViewMu.Lock()
defer r.resourceViewMu.Unlock()

now := time.Now()

if r.resourceViewUpdated.Add(r.timeout).After(now) {
return filter(r.resourceView,
func(res lapi.ResourceWithVolumes) string { return res.NodeName },
func(res lapi.ResourceWithVolumes) string { return res.Props[lc.KeyStorPoolName] },
opts...,
), nil
}

view, err := r.ResourceProvider.GetResourceView(ctx)
if err != nil {
return nil, err
}

r.resourceView = view
r.resourceViewUpdated = now

return filter(r.resourceView,
func(res lapi.ResourceWithVolumes) string { return res.NodeName },
func(res lapi.ResourceWithVolumes) string { return res.Props[lc.KeyStorPoolName] },
opts...,
), nil
}

func filter[T any](items []T, getNodeName func(T) string, opts ...*lapi.ListOpts) []T {
func filter[T any](items []T, getNodeName, getPoolName func(T) string, opts ...*lapi.ListOpts) []T {
filterNames := make(map[string]struct{})
filterPools := make(map[string]struct{})

for _, o := range opts {
for _, n := range o.Node {
filterNames[n] = struct{}{}
}
}

if len(filterNames) == 0 {
return items
for _, sp := range o.StoragePool {

Check failure on line 314 in pkg/linstor/highlevelclient/high_level_client.go

View workflow job for this annotation

GitHub Actions / lint

ranges should only be cuddled with assignments used in the iteration (wsl)
filterPools[sp] = struct{}{}
}
}

var result []T

for _, item := range items {
if _, ok := filterNames[getNodeName(item)]; ok {
result = append(result, item)
if len(filterPools) > 0 {
if _, ok := filterNames[getNodeName(item)]; !ok {
continue
}
}

if len(filterPools) > 0 {
if _, ok := filterPools[getPoolName(item)]; !ok {
continue
}
}

result = append(result, item)
}

return result
Expand Down

0 comments on commit 0a16f92

Please sign in to comment.