Evaluate path predicates incrementally from cached directory paths
This commit is contained in:
@@ -43,13 +43,20 @@ func Apply(ctx context.Context, t *inventory.Tree, q *Query, m inventory.SizeMod
|
||||
r := &Result{Query: q, Mode: m, Sizes: make([]int64, n), Matched: make([]bool, n)}
|
||||
covered := make([]bool, n)
|
||||
c := &Ctx{Tree: t, Now: time.Now().UnixNano()}
|
||||
if q.UsesPath {
|
||||
c.dirPaths = map[inventory.NodeID]string{}
|
||||
}
|
||||
for i := range n {
|
||||
if i&0xffff == 0 && ctx.Err() != nil {
|
||||
return nil, ctx.Err()
|
||||
}
|
||||
id := inventory.NodeID(i)
|
||||
nd := t.Node(id)
|
||||
c.ID, c.Node = id, nd
|
||||
c.ID, c.Node, c.path = id, nd, ""
|
||||
if c.dirPaths != nil && nd.IsDir() {
|
||||
c.path = c.lowerPath()
|
||||
c.dirPaths[id] = c.path
|
||||
}
|
||||
if i > 0 && q.Match(c) {
|
||||
r.Matched[i] = true
|
||||
covered[i] = true
|
||||
|
||||
+21
-5
@@ -16,6 +16,9 @@ type Ctx struct {
|
||||
Node *inventory.Node
|
||||
Now int64 // unix nanoseconds
|
||||
path string
|
||||
// dirPaths caches lower-cased directory paths during Apply, which visits
|
||||
// parents before children, so a node's path is one concatenation.
|
||||
dirPaths map[inventory.NodeID]string
|
||||
}
|
||||
|
||||
func (c *Ctx) str(f Field) string {
|
||||
@@ -25,7 +28,7 @@ func (c *Ctx) str(f Field) string {
|
||||
return strings.ToLower(n.Name)
|
||||
case FPath:
|
||||
if c.path == "" {
|
||||
c.path = strings.ToLower(c.Tree.Path(c.ID))
|
||||
c.path = c.lowerPath()
|
||||
}
|
||||
return c.path
|
||||
case FExt:
|
||||
@@ -62,6 +65,22 @@ func (c *Ctx) num(f Field) int64 {
|
||||
return 0
|
||||
}
|
||||
|
||||
func (c *Ctx) lowerPath() string {
|
||||
if c.dirPaths != nil {
|
||||
if p, ok := c.dirPaths[c.ID]; ok {
|
||||
return p
|
||||
}
|
||||
if pp, ok := c.dirPaths[c.Node.Parent]; ok {
|
||||
sep := string(filepath.Separator)
|
||||
if strings.HasSuffix(pp, sep) {
|
||||
sep = ""
|
||||
}
|
||||
return pp + sep + strings.ToLower(c.Node.Name)
|
||||
}
|
||||
}
|
||||
return strings.ToLower(c.Tree.Path(c.ID))
|
||||
}
|
||||
|
||||
type node interface{ eval(*Ctx) bool }
|
||||
|
||||
type andNode struct{ l, r node }
|
||||
@@ -154,7 +173,4 @@ func (n numNode) eval(c *Ctx) bool {
|
||||
}
|
||||
|
||||
// Match evaluates the query against one node.
|
||||
func (q *Query) Match(c *Ctx) bool {
|
||||
c.path = ""
|
||||
return q.root.eval(c)
|
||||
}
|
||||
func (q *Query) Match(c *Ctx) bool { return q.root.eval(c) }
|
||||
|
||||
Reference in New Issue
Block a user