From 75ff0ae082a417bc01ef3af736942531c8777109 Mon Sep 17 00:00:00 2001 From: hannahhoward Date: Tue, 22 Sep 2020 12:39:38 -0700 Subject: [PATCH] fix(selectorvalidator): memory optimization Do not reconstruct a complicated selector on each call to selector validate --- selectorvalidator/selectorvalidator.go | 37 +++++++++++++------------- 1 file changed, 19 insertions(+), 18 deletions(-) diff --git a/selectorvalidator/selectorvalidator.go b/selectorvalidator/selectorvalidator.go index 606b3618..f178d69c 100644 --- a/selectorvalidator/selectorvalidator.go +++ b/selectorvalidator/selectorvalidator.go @@ -19,27 +19,15 @@ var ( ErrInvalidLimit = errors.New("unsupported recursive selector limit") ) -// SelectorValidator returns an OnRequestReceivedHook that only validates -// requests if their selector only has no recursions that are greater than -// maxAcceptedDepth -func SelectorValidator(maxAcceptedDepth int) graphsync.OnIncomingRequestHook { - return func(p peer.ID, request graphsync.RequestData, hookActions graphsync.IncomingRequestHookActions) { - err := ValidateMaxRecursionDepth(request.Selector(), maxAcceptedDepth) - if err == nil { - hookActions.ValidateRequest() - } - } -} +var maxDepthSelector selector.Selector -// ValidateMaxRecursionDepth examines the given selector node and verifies -// recursive selectors are limited to the given fixed depth -func ValidateMaxRecursionDepth(node ipld.Node, maxAcceptedDepth int) error { +func init() { ssb := builder.NewSelectorSpecBuilder(basicnode.Prototype.Map) // this selector is a selector for traversing selectors... // it traverses the various selector types looking for recursion limit fields // and matches them - s, err := ssb.ExploreRecursive(selector.RecursionLimitNone(), ssb.ExploreFields(func(efsb builder.ExploreFieldsSpecBuilder) { + maxDepthSelector, _ = ssb.ExploreRecursive(selector.RecursionLimitNone(), ssb.ExploreFields(func(efsb builder.ExploreFieldsSpecBuilder) { efsb.Insert(selector.SelectorKey_ExploreRecursive, ssb.ExploreFields(func(efsb builder.ExploreFieldsSpecBuilder) { efsb.Insert(selector.SelectorKey_Limit, ssb.Matcher()) efsb.Insert(selector.SelectorKey_Sequence, ssb.ExploreRecursiveEdge()) @@ -61,12 +49,25 @@ func ValidateMaxRecursionDepth(node ipld.Node, maxAcceptedDepth int) error { efsb.Insert(selector.SelectorKey_Next, ssb.ExploreRecursiveEdge()) })) })).Selector() +} - if err != nil { - return err +// SelectorValidator returns an OnRequestReceivedHook that only validates +// requests if their selector only has no recursions that are greater than +// maxAcceptedDepth +func SelectorValidator(maxAcceptedDepth int) graphsync.OnIncomingRequestHook { + return func(p peer.ID, request graphsync.RequestData, hookActions graphsync.IncomingRequestHookActions) { + err := ValidateMaxRecursionDepth(request.Selector(), maxAcceptedDepth) + if err == nil { + hookActions.ValidateRequest() + } } +} + +// ValidateMaxRecursionDepth examines the given selector node and verifies +// recursive selectors are limited to the given fixed depth +func ValidateMaxRecursionDepth(node ipld.Node, maxAcceptedDepth int) error { - return traversal.WalkMatching(node, s, func(progress traversal.Progress, visited ipld.Node) error { + return traversal.WalkMatching(node, maxDepthSelector, func(progress traversal.Progress, visited ipld.Node) error { if visited.ReprKind() != ipld.ReprKind_Map || visited.Length() != 1 { return ErrInvalidLimit }