Skip to content

Commit ba6bcd5

Browse files
committed
object/acl: Cache storage policy execution results
TBD Signed-off-by: Leonard Lyubich <[email protected]>
1 parent 396bf50 commit ba6bcd5

File tree

4 files changed

+65
-58
lines changed

4 files changed

+65
-58
lines changed

cmd/neofs-node/object.go

Lines changed: 25 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -329,7 +329,7 @@ func initObjectService(c *cfg) {
329329
},
330330
)
331331

332-
aclSvc := v2.New(
332+
aclSvc := v2.New(c,
333333
v2.WithLogger(c.log),
334334
v2.WithIRFetcher(newCachedIRFetcher(irFetcher)),
335335
v2.WithNetmapSource(c.netMapSource),
@@ -676,3 +676,27 @@ func (x *containerStoragePolicy) StorageNodesForObject(obj oid.ID) ([][]netmapsd
676676

677677
return nodeLists, x.cnrNodes.primaryNodesNums, nil
678678
}
679+
680+
// TODO: docs
681+
func (c *cfg) AuthContainerNode(bPubKey []byte, cnr cid.ID, storagePolicy netmapsdk.PlacementPolicy) (bool, error) {
682+
cnrNodes, networkMap, _, err := c.cfgObject.containerNodesBuilder._getForEpochAndPolicy(cnr, 0, &storagePolicy)
683+
if err != nil {
684+
return false, err
685+
}
686+
687+
if cnrNodes.hasNodeWithPublicKey(bPubKey) {
688+
return true, nil
689+
}
690+
691+
curEpoch := networkMap.Epoch()
692+
if curEpoch > 0 {
693+
cnrNodes, _, _, err = c.cfgObject.containerNodesBuilder._getForEpochAndPolicy(cnr, curEpoch-1, &storagePolicy)
694+
if err != nil {
695+
return false, err
696+
}
697+
698+
return cnrNodes.hasNodeWithPublicKey(bPubKey), nil
699+
}
700+
701+
return false, nil
702+
}

cmd/neofs-node/storage_policy.go

Lines changed: 27 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
package main
22

33
import (
4+
"bytes"
45
"fmt"
56
"sync"
67

@@ -28,6 +29,18 @@ type containerNodes struct {
2829
nodeSets [][]netmapsdk.NodeInfo
2930
}
3031

32+
func (x containerNodes) hasNodeWithPublicKey(bPubKey []byte) bool {
33+
for i := range x.nodeSets {
34+
for j := range x.nodeSets[i] {
35+
if bytes.Equal(x.nodeSets[i][j].PublicKey(), bPubKey) {
36+
return true
37+
}
38+
}
39+
}
40+
41+
return false
42+
}
43+
3144
type containerNodesBuildRes struct {
3245
mtx sync.RWMutex
3346
val containerNodes
@@ -141,7 +154,7 @@ func (x *containerNodesBuilder) setCurrentEpoch(curEpoch uint64) {
141154
x.curEpoch = curEpoch
142155
}
143156

144-
func (x *containerNodesBuilder) _getForEpoch(cnrID cid.ID, epoch uint64) (containerNodes, *netmapsdk.NetMap, *containerNodesCacheItem, error) {
157+
func (x *containerNodesBuilder) _getForEpochAndPolicy(cnrID cid.ID, epoch uint64, storagePolicyOpt *netmapsdk.PlacementPolicy) (containerNodes, *netmapsdk.NetMap, *containerNodesCacheItem, error) {
145158
var cache *containerNodesCache
146159

147160
x.curEpochMtx.RLock()
@@ -186,12 +199,17 @@ func (x *containerNodesBuilder) _getForEpoch(cnrID cid.ID, epoch uint64) (contai
186199
}
187200
}
188201

189-
cnr, err := x.containers.Get(cnrID)
190-
if err != nil {
191-
return containerNodes{}, nil, nil, fmt.Errorf("read container by ID: %w", err)
192-
}
202+
var storagePolicy netmapsdk.PlacementPolicy
203+
if storagePolicyOpt != nil {
204+
storagePolicy = *storagePolicyOpt
205+
} else {
206+
cnr, err := x.containers.Get(cnrID)
207+
if err != nil {
208+
return containerNodes{}, nil, nil, fmt.Errorf("read container by ID: %w", err)
209+
}
193210

194-
storagePolicy := cnr.Value.PlacementPolicy()
211+
storagePolicy = cnr.Value.PlacementPolicy()
212+
}
195213

196214
if cached {
197215
cache.lruMtx.Lock()
@@ -252,6 +270,9 @@ func (x *containerNodesBuilder) _getForEpoch(cnrID cid.ID, epoch uint64) (contai
252270

253271
return res, networkMap, cachedVal, nil
254272
}
273+
func (x *containerNodesBuilder) _getForEpoch(cnrID cid.ID, epoch uint64) (containerNodes, *netmapsdk.NetMap, *containerNodesCacheItem, error) {
274+
return x._getForEpochAndPolicy(cnrID, epoch, nil)
275+
}
255276

256277
func (x *containerNodesBuilder) getForEpoch(cnrID cid.ID, epoch uint64) (containerNodes, *netmapsdk.NetMap, error) {
257278
cnrNodes, networkMap, _, err := x._getForEpoch(cnrID, epoch)

pkg/services/object/acl/v2/classifier.go

Lines changed: 2 additions & 49 deletions
Original file line numberDiff line numberDiff line change
@@ -3,18 +3,16 @@ package v2
33
import (
44
"bytes"
55

6-
core "github.com/nspcc-dev/neofs-node/pkg/core/netmap"
76
"github.com/nspcc-dev/neofs-sdk-go/container"
87
"github.com/nspcc-dev/neofs-sdk-go/container/acl"
98
cid "github.com/nspcc-dev/neofs-sdk-go/container/id"
10-
"github.com/nspcc-dev/neofs-sdk-go/netmap"
119
"go.uber.org/zap"
1210
)
1311

1412
type senderClassifier struct {
1513
log *zap.Logger
1614
innerRing InnerRingFetcher
17-
netmap core.Source
15+
node Node
1816
}
1917

2018
type classifyResult struct {
@@ -53,7 +51,7 @@ func (c senderClassifier) classify(
5351
}, nil
5452
}
5553

56-
isContainerNode, err := c.isContainerKey(ownerKey, idCnr, cnr)
54+
isContainerNode, err := c.node.AuthContainerNode(ownerKey, idCnr, cnr.PlacementPolicy())
5755
if err != nil {
5856
// error might happen if request has `RoleOther` key and placement
5957
// is not possible for previous epoch, so
@@ -89,48 +87,3 @@ func (c senderClassifier) isInnerRingKey(owner []byte) (bool, error) {
8987

9088
return false, nil
9189
}
92-
93-
func (c senderClassifier) isContainerKey(
94-
owner []byte, idCnr cid.ID,
95-
cnr container.Container) (bool, error) {
96-
nm, err := core.GetLatestNetworkMap(c.netmap) // first check current netmap
97-
if err != nil {
98-
return false, err
99-
}
100-
101-
in, err := lookupKeyInContainer(nm, owner, idCnr, cnr)
102-
if err != nil {
103-
return false, err
104-
} else if in {
105-
return true, nil
106-
}
107-
108-
// then check previous netmap, this can happen in-between epoch change
109-
// when node migrates data from last epoch container
110-
nm, err = core.GetPreviousNetworkMap(c.netmap)
111-
if err != nil {
112-
return false, err
113-
}
114-
115-
return lookupKeyInContainer(nm, owner, idCnr, cnr)
116-
}
117-
118-
func lookupKeyInContainer(
119-
nm *netmap.NetMap,
120-
owner []byte, idCnr cid.ID,
121-
cnr container.Container) (bool, error) {
122-
cnrVectors, err := nm.ContainerNodes(cnr.PlacementPolicy(), idCnr)
123-
if err != nil {
124-
return false, err
125-
}
126-
127-
for i := range cnrVectors {
128-
for j := range cnrVectors[i] {
129-
if bytes.Equal(cnrVectors[i][j].PublicKey(), owner) {
130-
return true, nil
131-
}
132-
}
133-
}
134-
135-
return false, nil
136-
}

pkg/services/object/acl/v2/service.go

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,12 +12,21 @@ import (
1212
apistatus "github.com/nspcc-dev/neofs-sdk-go/client/status"
1313
"github.com/nspcc-dev/neofs-sdk-go/container/acl"
1414
cid "github.com/nspcc-dev/neofs-sdk-go/container/id"
15+
netmapsdk "github.com/nspcc-dev/neofs-sdk-go/netmap"
1516
oid "github.com/nspcc-dev/neofs-sdk-go/object/id"
1617
sessionSDK "github.com/nspcc-dev/neofs-sdk-go/session"
1718
"github.com/nspcc-dev/neofs-sdk-go/user"
1819
"go.uber.org/zap"
1920
)
2021

22+
// Node represents local NeoFS storage node within which [Service] operates.
23+
type Node interface {
24+
// AuthContainerNode authenticates storage node by binary-encoded public key and
25+
// checks whether the node matches given storage policy of the referenced
26+
// container.
27+
AuthContainerNode(bPubKey []byte, cnrID cid.ID, storagePolicy netmapsdk.PlacementPolicy) (bool, error)
28+
}
29+
2130
// Service checks basic ACL rules.
2231
type Service struct {
2332
*cfg
@@ -78,7 +87,7 @@ func defaultCfg() *cfg {
7887
}
7988

8089
// New is a constructor for object ACL checking service.
81-
func New(opts ...Option) Service {
90+
func New(node Node, opts ...Option) Service {
8291
cfg := defaultCfg()
8392

8493
for i := range opts {
@@ -102,7 +111,7 @@ func New(opts ...Option) Service {
102111
c: senderClassifier{
103112
log: cfg.log,
104113
innerRing: cfg.irFetcher,
105-
netmap: cfg.nm,
114+
node: node,
106115
},
107116
}
108117
}

0 commit comments

Comments
 (0)