summaryrefslogtreecommitdiff
path: root/simpleperf/RecordFilter.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'simpleperf/RecordFilter.cpp')
-rw-r--r--simpleperf/RecordFilter.cpp256
1 files changed, 3 insertions, 253 deletions
diff --git a/simpleperf/RecordFilter.cpp b/simpleperf/RecordFilter.cpp
index 7818d32b..d85e9a63 100644
--- a/simpleperf/RecordFilter.cpp
+++ b/simpleperf/RecordFilter.cpp
@@ -19,232 +19,8 @@
#include "environment.h"
#include "utils.h"
-using android::base::Split;
-using android::base::Trim;
-
namespace simpleperf {
-namespace {
-
-using TimeRange = std::pair<uint64_t, uint64_t>;
-
-class TimeRanges {
- public:
- void Begin(uint64_t timestamp) {
- if (!begin_time_.has_value()) {
- begin_time_ = timestamp;
- }
- }
-
- bool End(uint64_t timestamp) {
- if (begin_time_.has_value()) {
- if (begin_time_ >= timestamp) {
- LOG(ERROR) << "Invalid time range in filter data: begin time " << begin_time_.value()
- << " >= end time " << timestamp;
- return false;
- }
- ranges_.emplace_back(begin_time_.value(), timestamp);
- begin_time_.reset();
- }
- return true;
- }
-
- void NoMoreTimestamp() {
- if (begin_time_.has_value()) {
- ranges_.emplace_back(begin_time_.value(), UINT64_MAX);
- }
- std::sort(ranges_.begin(), ranges_.end());
- }
-
- bool Empty() const { return ranges_.empty(); }
-
- bool InRange(uint64_t timestamp) const {
- auto it = std::upper_bound(ranges_.begin(), ranges_.end(),
- std::pair<uint64_t, uint64_t>(timestamp, 0));
- if (it != ranges_.end() && it->first == timestamp) {
- return true;
- }
- if (it != ranges_.begin()) {
- --it;
- if (it->second > timestamp) {
- return true;
- }
- }
- return false;
- }
-
- private:
- std::optional<uint64_t> begin_time_;
- std::vector<TimeRange> ranges_;
-};
-
-} // namespace
-
-class TimeFilter {
- public:
- const std::string& GetClock() const { return clock_; }
- void SetClock(const std::string& clock) { clock_ = clock; }
-
- void GlobalBegin(uint64_t timestamp) { global_ranges_.Begin(timestamp); }
-
- bool GlobalEnd(uint64_t timestamp) { return global_ranges_.End(timestamp); }
-
- void ProcessBegin(pid_t pid, uint64_t timestamp) { process_ranges_[pid].Begin(timestamp); }
-
- bool ProcessEnd(pid_t pid, uint64_t timestamp) { return process_ranges_[pid].End(timestamp); }
-
- void ThreadBegin(pid_t tid, uint64_t timestamp) { thread_ranges_[tid].Begin(timestamp); }
-
- bool ThreadEnd(pid_t tid, uint64_t timestamp) { return thread_ranges_[tid].End(timestamp); }
-
- void NoMoreTimestamp() {
- global_ranges_.NoMoreTimestamp();
- for (auto& p : process_ranges_) {
- p.second.NoMoreTimestamp();
- }
- for (auto& p : thread_ranges_) {
- p.second.NoMoreTimestamp();
- }
- }
-
- bool Empty() const {
- return global_ranges_.Empty() && process_ranges_.empty() && thread_ranges_.empty();
- }
-
- bool Check(const SampleRecord& sample) const {
- uint64_t timestamp = sample.Timestamp();
- if (!global_ranges_.Empty() && !global_ranges_.InRange(timestamp)) {
- return false;
- }
- if (!process_ranges_.empty()) {
- auto it = process_ranges_.find(sample.tid_data.pid);
- if (it == process_ranges_.end() || !it->second.InRange(timestamp)) {
- return false;
- }
- }
- if (!thread_ranges_.empty()) {
- auto it = thread_ranges_.find(sample.tid_data.tid);
- if (it == thread_ranges_.end() || !it->second.InRange(timestamp)) {
- return false;
- }
- }
- return true;
- }
-
- private:
- std::string clock_ = "monotonic";
- TimeRanges global_ranges_;
- std::unordered_map<pid_t, TimeRanges> process_ranges_;
- std::unordered_map<pid_t, TimeRanges> thread_ranges_;
-};
-
-// Read filter file. The format is in doc/sample_filter.md.
-class FilterFileReader {
- public:
- FilterFileReader(const std::string& filename) : filename_(filename) {}
-
- bool Read() {
- std::string data;
- if (!android::base::ReadFileToString(filename_, &data)) {
- PLOG(ERROR) << "failed to read " << filename_;
- return false;
- }
- line_number_ = 0;
- time_filter_.reset(new TimeFilter);
- std::string arg_str;
- std::vector<std::string> args;
- uint64_t timestamp;
- pid_t pid;
- for (const auto& line : Split(data, "\n")) {
- line_number_++;
- if (SearchCmd(line, "CLOCK", &arg_str)) {
- if (!SplitArgs(arg_str, 1, &args)) {
- return false;
- }
- time_filter_->SetClock(args[0]);
- } else if (SearchCmd(line, "GLOBAL_BEGIN", &arg_str)) {
- if (!SplitArgs(arg_str, 1, &args) || !ParseTimestamp(args[0], &timestamp)) {
- return false;
- }
- time_filter_->GlobalBegin(timestamp);
- } else if (SearchCmd(line, "GLOBAL_END", &arg_str)) {
- if (!SplitArgs(arg_str, 1, &args) || !ParseTimestamp(args[0], &timestamp) ||
- !time_filter_->GlobalEnd(timestamp)) {
- return false;
- }
- } else if (SearchCmd(line, "PROCESS_BEGIN", &arg_str)) {
- if (!SplitArgs(arg_str, 2, &args) || !ParsePid(args[0], &pid) ||
- !ParseTimestamp(args[1], &timestamp)) {
- return false;
- }
- time_filter_->ProcessBegin(pid, timestamp);
- } else if (SearchCmd(line, "PROCESS_END", &arg_str)) {
- if (!SplitArgs(arg_str, 2, &args) || !ParsePid(args[0], &pid) ||
- !ParseTimestamp(args[1], &timestamp) || !time_filter_->ProcessEnd(pid, timestamp)) {
- return false;
- }
- } else if (SearchCmd(line, "THREAD_BEGIN", &arg_str)) {
- if (!SplitArgs(arg_str, 2, &args) || !ParsePid(args[0], &pid) ||
- !ParseTimestamp(args[1], &timestamp)) {
- return false;
- }
- time_filter_->ThreadBegin(pid, timestamp);
- } else if (SearchCmd(line, "THREAD_END", &arg_str)) {
- if (!SplitArgs(arg_str, 2, &args) || !ParsePid(args[0], &pid) ||
- !ParseTimestamp(args[1], &timestamp) || !time_filter_->ThreadEnd(pid, timestamp)) {
- return false;
- }
- }
- }
- return true;
- }
-
- std::unique_ptr<TimeFilter>& GetTimeFilter() { return time_filter_; }
-
- private:
- bool SearchCmd(const std::string& s, const char* cmd, std::string* arg_str) {
- auto pos = s.find(cmd);
- if (pos == s.npos) {
- return false;
- }
- *arg_str = s.substr(pos + strlen(cmd));
- return true;
- }
-
- bool SplitArgs(const std::string& s, size_t nargs, std::vector<std::string>* args) {
- *args = Split(Trim(s), " ");
- if (args->size() != nargs) {
- LOG(ERROR) << "Invalid args in " << filename_ << ":" << line_number_ << ": " << s;
- return false;
- }
- return true;
- }
-
- bool ParsePid(const std::string& s, pid_t* pid) {
- if (!android::base::ParseInt(s.c_str(), pid, static_cast<pid_t>(0))) {
- LOG(ERROR) << "Invalid pid in " << filename_ << ":" << line_number_ << ": " << s;
- return false;
- }
- return true;
- }
-
- bool ParseTimestamp(const std::string& s, uint64_t* timestamp) {
- if (!android::base::ParseUint(s.c_str(), timestamp)) {
- LOG(ERROR) << "Invalid timestamp in " << filename_ << ":" << line_number_ << ": " << s;
- return false;
- }
- return true;
- }
-
- const std::string filename_;
- size_t line_number_ = 0;
- std::unique_ptr<TimeFilter> time_filter_;
-};
-
-RecordFilter::RecordFilter(const ThreadTree& thread_tree) : thread_tree_(thread_tree) {}
-
-RecordFilter::~RecordFilter() {}
-
bool RecordFilter::ParseOptions(OptionValueMap& options) {
for (bool exclude : {true, false}) {
std::string prefix = exclude ? "--exclude-" : "--include-";
@@ -269,18 +45,13 @@ bool RecordFilter::ParseOptions(OptionValueMap& options) {
AddThreadNameRegex(*value.str_value, exclude);
}
for (const OptionValue& value : options.PullValues(prefix + "uid")) {
- if (auto uids = ParseUintVector<uint32_t>(*value.str_value); uids) {
+ if (auto uids = ParseUintVector<uid_t>(*value.str_value); uids) {
AddUids(uids.value(), exclude);
} else {
return false;
}
}
}
- if (auto value = options.PullValue("--filter-file"); value) {
- if (!SetFilterFile(*value->str_value)) {
- return false;
- }
- }
return true;
}
@@ -308,21 +79,12 @@ void RecordFilter::AddThreadNameRegex(const std::string& thread_name, bool exclu
cond.thread_name_regs.emplace_back(thread_name, std::regex::optimize);
}
-void RecordFilter::AddUids(const std::set<uint32_t>& uids, bool exclude) {
+void RecordFilter::AddUids(const std::set<uid_t>& uids, bool exclude) {
RecordFilterCondition& cond = GetCondition(exclude);
cond.used = true;
cond.uids.insert(uids.begin(), uids.end());
}
-bool RecordFilter::SetFilterFile(const std::string& filename) {
- FilterFileReader reader(filename);
- if (!reader.Read()) {
- return false;
- }
- time_filter_ = std::move(reader.GetTimeFilter());
- return true;
-}
-
bool RecordFilter::Check(const SampleRecord* r) {
if (exclude_condition_.used && CheckCondition(r, exclude_condition_)) {
return false;
@@ -330,18 +92,6 @@ bool RecordFilter::Check(const SampleRecord* r) {
if (include_condition_.used && !CheckCondition(r, include_condition_)) {
return false;
}
- if (time_filter_ && !time_filter_->Check(*r)) {
- return false;
- }
- return true;
-}
-
-bool RecordFilter::CheckClock(const std::string& clock) {
- if (time_filter_ && time_filter_->GetClock() != clock) {
- LOG(ERROR) << "clock generating sample timestamps is " << clock
- << ", which doesn't match clock used in time filter " << time_filter_->GetClock();
- return false;
- }
return true;
}
@@ -391,7 +141,7 @@ bool RecordFilter::SearchInRegs(const std::string& s, const std::vector<std::reg
return false;
}
-std::optional<uint32_t> RecordFilter::GetUidForProcess(pid_t pid) {
+std::optional<uid_t> RecordFilter::GetUidForProcess(pid_t pid) {
if (auto it = pid_to_uid_map_.find(pid); it != pid_to_uid_map_.end()) {
return it->second;
}