Skip to content

Commit

Permalink
Add simple suffix evaluation
Browse files Browse the repository at this point in the history
Summary:
# Context
Watchman is a primary vector into the eden globFiles endpoint. How watchman interprets and sends arguments to eden different based on how the query is structured. This change is intended to make a common query pathway more efficient(referred to as SimpleSuffix from here).
Query format example:
["query","<root>",{relative_root:"<rel_root>",fields:["content.sha1hex","name"],expression:["allof",["type","f"],["suffix",["<types>"]]]}]
This is currently interpreted as [rel_root/**], then post-filtered in watchman.
This change is intended to change this to use eden glob's searchRoot field and internal filtering.

# This Diff
Adds new functions to watchman QueryExprs:
evaluateSimpleSuffix - intended to determine if the expression is a valid simple suffix
getSuffixQueryGlobPatterns - basically only valid on SuffixExpr. Returns a list of suffixes in glob form.

These are intended to allow watchman to determine if a given query is using a simple suffix so we can pass arguments to eden more efficiently.

This is primarily targeted at allowing targeted SLAPI offloading, b
ut may have benefits for queries that aren't offloaded since we're returning less files from eden.

Rollout is controlled by the watchman config value eden_enable_simple_suffix

# Technical Details
evaluateSimpleSuffix - returns Excluded(Not part of a Simple Suffix), Type, Suffix, or Allof. An Allof result indicates that this is a valis SimpleSuffix.

getSuffixQueryGlobPatterns - Takes the suffix expression (eg. ['a', 'b']) and converts it to glob form (**/*.a, **/*.b)

Relative root is computed and passed down. Adjustments to filter is made to properly reflect this.

Reviewed By: jdelliot

Differential Revision: D65302345

fbshipit-source-id: 57c073022452b2ff8ea1c913d45cad2a3eee1484
  • Loading branch information
Chris Dinh authored and facebook-github-bot committed Nov 7, 2024
1 parent 3a732d5 commit 501416a
Show file tree
Hide file tree
Showing 13 changed files with 356 additions and 12 deletions.
17 changes: 17 additions & 0 deletions watchman/query/QueryExpr.h
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,11 @@ enum AggregateOp {
AllOf,
};

/**
* Describes which part of a simple suffix expression
*/
enum SimpleSuffixType { Excluded, Suffix, IsSimpleSuffix, Type };

class QueryExpr {
public:
virtual ~QueryExpr() = default;
Expand Down Expand Up @@ -78,6 +83,8 @@ class QueryExpr {
virtual std::optional<std::vector<std::string>> computeGlobUpperBound(
CaseSensitivity) const = 0;

virtual std::vector<std::string> getSuffixQueryGlobPatterns() const = 0;

enum ReturnOnlyFiles { No, Yes, Unrelated };

/**
Expand All @@ -86,6 +93,16 @@ class QueryExpr {
* method to handle this query.
*/
virtual ReturnOnlyFiles listOnlyFiles() const = 0;

/**
* Returns whether this expression is a simple suffix expression, or a part
* of a simple suffix expression. A simple suffix expression is an allof
* expression that contains a single suffix expresssion containing one or more
* suffixes, and a type expresssion that wants files only. The intention for
* this is to allow watchman to more accurately determine what arguments to
* pass to eden's globFiles API.
*/
virtual SimpleSuffixType evaluateSimpleSuffix() const = 0;
};

} // namespace watchman
53 changes: 53 additions & 0 deletions watchman/query/base.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,14 @@ class NotExpr : public QueryExpr {
}
return ReturnOnlyFiles::Unrelated;
}

SimpleSuffixType evaluateSimpleSuffix() const override {
return SimpleSuffixType::Excluded;
}

std::vector<std::string> getSuffixQueryGlobPatterns() const override {
return std::vector<std::string>{};
}
};

W_TERM_PARSER(not, NotExpr::parse);
Expand All @@ -87,6 +95,14 @@ class TrueExpr : public QueryExpr {
ReturnOnlyFiles listOnlyFiles() const override {
return ReturnOnlyFiles::Unrelated;
}

SimpleSuffixType evaluateSimpleSuffix() const override {
return SimpleSuffixType::Excluded;
}

std::vector<std::string> getSuffixQueryGlobPatterns() const override {
return std::vector<std::string>{};
}
};

W_TERM_PARSER(true, TrueExpr::parse);
Expand All @@ -110,6 +126,14 @@ class FalseExpr : public QueryExpr {
ReturnOnlyFiles listOnlyFiles() const override {
return ReturnOnlyFiles::Unrelated;
}

SimpleSuffixType evaluateSimpleSuffix() const override {
return SimpleSuffixType::Excluded;
}

std::vector<std::string> getSuffixQueryGlobPatterns() const override {
return std::vector<std::string>{};
}
};

W_TERM_PARSER(false, FalseExpr::parse);
Expand Down Expand Up @@ -312,6 +336,35 @@ class ListExpr : public QueryExpr {
}
return result;
}

SimpleSuffixType evaluateSimpleSuffix() const override {
if (allof) {
std::vector<SimpleSuffixType> types;
for (auto& subExpr : exprs) {
types.push_back(subExpr->evaluateSimpleSuffix());
}
if (types.size() == 2) {
if ((types[0] == SimpleSuffixType::Type &&
types[1] == SimpleSuffixType::Suffix) ||
(types[1] == SimpleSuffixType::Type &&
types[0] == SimpleSuffixType::Suffix)) {
return SimpleSuffixType::IsSimpleSuffix;
}
}
}
return SimpleSuffixType::Excluded;
}

std::vector<std::string> getSuffixQueryGlobPatterns() const override {
if (allof) {
for (auto& subExpr : exprs) {
if (subExpr->evaluateSimpleSuffix() == SimpleSuffixType::Suffix) {
return subExpr->getSuffixQueryGlobPatterns();
}
}
}
return std::vector<std::string>{};
}
};

W_TERM_PARSER(anyof, ListExpr::parseAnyOf);
Expand Down
8 changes: 8 additions & 0 deletions watchman/query/dirname.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -178,6 +178,14 @@ class DirNameExpr : public QueryExpr {
ReturnOnlyFiles listOnlyFiles() const override {
return ReturnOnlyFiles::Unrelated;
}

SimpleSuffixType evaluateSimpleSuffix() const override {
return SimpleSuffixType::Excluded;
}

std::vector<std::string> getSuffixQueryGlobPatterns() const override {
return std::vector<std::string>{};
}
};

W_TERM_PARSER(dirname, DirNameExpr::parseDirName);
Expand Down
16 changes: 16 additions & 0 deletions watchman/query/empty.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,14 @@ class ExistsExpr : public QueryExpr {
ReturnOnlyFiles listOnlyFiles() const override {
return ReturnOnlyFiles::Unrelated;
}

SimpleSuffixType evaluateSimpleSuffix() const override {
return SimpleSuffixType::Excluded;
}

std::vector<std::string> getSuffixQueryGlobPatterns() const override {
return std::vector<std::string>{};
}
};
W_TERM_PARSER(exists, ExistsExpr::parse);

Expand Down Expand Up @@ -79,6 +87,14 @@ class EmptyExpr : public QueryExpr {
ReturnOnlyFiles listOnlyFiles() const override {
return ReturnOnlyFiles::Unrelated;
}

SimpleSuffixType evaluateSimpleSuffix() const override {
return SimpleSuffixType::Excluded;
}

std::vector<std::string> getSuffixQueryGlobPatterns() const override {
return std::vector<std::string>{};
}
};
W_TERM_PARSER(empty, EmptyExpr::parse);

Expand Down
8 changes: 8 additions & 0 deletions watchman/query/intcompare.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -132,6 +132,14 @@ class SizeExpr : public QueryExpr {
ReturnOnlyFiles listOnlyFiles() const override {
return ReturnOnlyFiles::Unrelated;
}

SimpleSuffixType evaluateSimpleSuffix() const override {
return SimpleSuffixType::Excluded;
}

std::vector<std::string> getSuffixQueryGlobPatterns() const override {
return std::vector<std::string>{};
}
};
W_TERM_PARSER(size, SizeExpr::parse);

Expand Down
8 changes: 8 additions & 0 deletions watchman/query/match.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -212,6 +212,14 @@ class WildMatchExpr : public QueryExpr {
ReturnOnlyFiles listOnlyFiles() const override {
return ReturnOnlyFiles::Unrelated;
}

SimpleSuffixType evaluateSimpleSuffix() const override {
return SimpleSuffixType::Excluded;
}

std::vector<std::string> getSuffixQueryGlobPatterns() const override {
return std::vector<std::string>{};
}
};
W_TERM_PARSER(match, WildMatchExpr::parseMatch);
W_TERM_PARSER(imatch, WildMatchExpr::parseIMatch);
Expand Down
8 changes: 8 additions & 0 deletions watchman/query/name.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -186,6 +186,14 @@ class NameExpr : public QueryExpr {
ReturnOnlyFiles listOnlyFiles() const override {
return ReturnOnlyFiles::Unrelated;
}

SimpleSuffixType evaluateSimpleSuffix() const override {
return SimpleSuffixType::Excluded;
}

std::vector<std::string> getSuffixQueryGlobPatterns() const override {
return std::vector<std::string>{};
}
};

W_TERM_PARSER(name, NameExpr::parseName);
Expand Down
8 changes: 8 additions & 0 deletions watchman/query/pcre.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -157,6 +157,14 @@ class PcreExpr : public QueryExpr {
ReturnOnlyFiles listOnlyFiles() const override {
return ReturnOnlyFiles::Unrelated;
}

SimpleSuffixType evaluateSimpleSuffix() const override {
return SimpleSuffixType::Excluded;
}

std::vector<std::string> getSuffixQueryGlobPatterns() const override {
return std::vector<std::string>{};
}
};
W_TERM_PARSER(pcre, PcreExpr::parsePcre);
W_TERM_PARSER(ipcre, PcreExpr::parseIPcre);
Expand Down
8 changes: 8 additions & 0 deletions watchman/query/since.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -170,6 +170,14 @@ class SinceExpr : public QueryExpr {
ReturnOnlyFiles listOnlyFiles() const override {
return ReturnOnlyFiles::Unrelated;
}

SimpleSuffixType evaluateSimpleSuffix() const override {
return SimpleSuffixType::Excluded;
}

std::vector<std::string> getSuffixQueryGlobPatterns() const override {
return std::vector<std::string>{};
}
};
W_TERM_PARSER(since, SinceExpr::parse);

Expand Down
13 changes: 13 additions & 0 deletions watchman/query/suffix.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -100,6 +100,19 @@ class SuffixExpr : public QueryExpr {
ReturnOnlyFiles listOnlyFiles() const override {
return ReturnOnlyFiles::Unrelated;
}

SimpleSuffixType evaluateSimpleSuffix() const override {
return SimpleSuffixType::Suffix;
}

std::vector<std::string> getSuffixQueryGlobPatterns() const override {
std::vector<std::string> patterns;
for (const auto& suffix : suffixSet_) {
patterns.push_back("**/*." + suffix.string());
}

return patterns;
}
};
W_TERM_PARSER(suffix, SuffixExpr::parse);
W_CAP_REG("suffix-set")
Expand Down
11 changes: 11 additions & 0 deletions watchman/query/type.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -119,6 +119,17 @@ class TypeExpr : public QueryExpr {
}
return ReturnOnlyFiles::Yes;
}

SimpleSuffixType evaluateSimpleSuffix() const override {
if (arg == 'f') {
return SimpleSuffixType::Type;
}
return SimpleSuffixType::Excluded;
}

std::vector<std::string> getSuffixQueryGlobPatterns() const override {
return std::vector<std::string>{};
}
};
W_TERM_PARSER(type, TypeExpr::parse);

Expand Down
Loading

0 comments on commit 501416a

Please sign in to comment.