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 dc64df0 commit dca9d70
Showing 1 changed file with 73 additions and 14 deletions.
87 changes: 73 additions & 14 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 @@ -168,6 +174,7 @@ func (c *HighLevelClient) ReservedCapacity(ctx context.Context, node, pool strin
}

var reserved int64

for i := range ress {
res := &ress[i]

Expand Down Expand Up @@ -215,7 +222,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 +235,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 +245,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 +260,80 @@ 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 {
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 dca9d70

Please sign in to comment.