1caf339d004fad667748b68912c254df4e75cdc5aYao Chen/*
2caf339d004fad667748b68912c254df4e75cdc5aYao Chen * Copyright (C) 2017 The Android Open Source Project
3caf339d004fad667748b68912c254df4e75cdc5aYao Chen *
4caf339d004fad667748b68912c254df4e75cdc5aYao Chen * Licensed under the Apache License, Version 2.0 (the "License");
5caf339d004fad667748b68912c254df4e75cdc5aYao Chen * you may not use this file except in compliance with the License.
6caf339d004fad667748b68912c254df4e75cdc5aYao Chen * You may obtain a copy of the License at
7caf339d004fad667748b68912c254df4e75cdc5aYao Chen *
8caf339d004fad667748b68912c254df4e75cdc5aYao Chen *      http://www.apache.org/licenses/LICENSE-2.0
9caf339d004fad667748b68912c254df4e75cdc5aYao Chen *
10caf339d004fad667748b68912c254df4e75cdc5aYao Chen * Unless required by applicable law or agreed to in writing, software
11caf339d004fad667748b68912c254df4e75cdc5aYao Chen * distributed under the License is distributed on an "AS IS" BASIS,
12caf339d004fad667748b68912c254df4e75cdc5aYao Chen * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13caf339d004fad667748b68912c254df4e75cdc5aYao Chen * See the License for the specific language governing permissions and
14caf339d004fad667748b68912c254df4e75cdc5aYao Chen * limitations under the License.
15caf339d004fad667748b68912c254df4e75cdc5aYao Chen */
16caf339d004fad667748b68912c254df4e75cdc5aYao Chen
179fc9edf95a308f5884bf541cac81ce1f41aba0baJoe Onorato#include "Log.h"
189fc9edf95a308f5884bf541cac81ce1f41aba0baJoe Onorato
19caf339d004fad667748b68912c254df4e75cdc5aYao Chen#include "CombinationLogMatchingTracker.h"
209fc9edf95a308f5884bf541cac81ce1f41aba0baJoe Onorato#include "matchers/matcher_util.h"
219fc9edf95a308f5884bf541cac81ce1f41aba0baJoe Onorato
229fc9edf95a308f5884bf541cac81ce1f41aba0baJoe Onoratonamespace android {
239fc9edf95a308f5884bf541cac81ce1f41aba0baJoe Onoratonamespace os {
249fc9edf95a308f5884bf541cac81ce1f41aba0baJoe Onoratonamespace statsd {
25caf339d004fad667748b68912c254df4e75cdc5aYao Chen
26caf339d004fad667748b68912c254df4e75cdc5aYao Chenusing std::set;
27caf339d004fad667748b68912c254df4e75cdc5aYao Chenusing std::string;
28caf339d004fad667748b68912c254df4e75cdc5aYao Chenusing std::unique_ptr;
29caf339d004fad667748b68912c254df4e75cdc5aYao Chenusing std::unordered_map;
30caf339d004fad667748b68912c254df4e75cdc5aYao Chenusing std::vector;
31caf339d004fad667748b68912c254df4e75cdc5aYao Chen
3294e197cceb2ba7df13ff8de04f60bfeec64015d9Yangster-macCombinationLogMatchingTracker::CombinationLogMatchingTracker(const int64_t& id, const int index)
3394e197cceb2ba7df13ff8de04f60bfeec64015d9Yangster-mac    : LogMatchingTracker(id, index) {
34caf339d004fad667748b68912c254df4e75cdc5aYao Chen}
35caf339d004fad667748b68912c254df4e75cdc5aYao Chen
36caf339d004fad667748b68912c254df4e75cdc5aYao ChenCombinationLogMatchingTracker::~CombinationLogMatchingTracker() {
37caf339d004fad667748b68912c254df4e75cdc5aYao Chen}
38caf339d004fad667748b68912c254df4e75cdc5aYao Chen
39b8c9aa8c9ccba4e64759c177381b742ca99a5487Stefan Lafonbool CombinationLogMatchingTracker::init(const vector<AtomMatcher>& allLogMatchers,
40caf339d004fad667748b68912c254df4e75cdc5aYao Chen                                         const vector<sp<LogMatchingTracker>>& allTrackers,
4194e197cceb2ba7df13ff8de04f60bfeec64015d9Yangster-mac                                         const unordered_map<int64_t, int>& matcherMap,
42caf339d004fad667748b68912c254df4e75cdc5aYao Chen                                         vector<bool>& stack) {
43caf339d004fad667748b68912c254df4e75cdc5aYao Chen    if (mInitialized) {
44caf339d004fad667748b68912c254df4e75cdc5aYao Chen        return true;
45caf339d004fad667748b68912c254df4e75cdc5aYao Chen    }
46caf339d004fad667748b68912c254df4e75cdc5aYao Chen
47caf339d004fad667748b68912c254df4e75cdc5aYao Chen    // mark this node as visited in the recursion stack.
48caf339d004fad667748b68912c254df4e75cdc5aYao Chen    stack[mIndex] = true;
49caf339d004fad667748b68912c254df4e75cdc5aYao Chen
50b8c9aa8c9ccba4e64759c177381b742ca99a5487Stefan Lafon    AtomMatcher_Combination matcher = allLogMatchers[mIndex].combination();
51caf339d004fad667748b68912c254df4e75cdc5aYao Chen
52caf339d004fad667748b68912c254df4e75cdc5aYao Chen    // LogicalOperation is missing in the config
53caf339d004fad667748b68912c254df4e75cdc5aYao Chen    if (!matcher.has_operation()) {
54caf339d004fad667748b68912c254df4e75cdc5aYao Chen        return false;
55caf339d004fad667748b68912c254df4e75cdc5aYao Chen    }
56caf339d004fad667748b68912c254df4e75cdc5aYao Chen
57caf339d004fad667748b68912c254df4e75cdc5aYao Chen    mLogicalOperation = matcher.operation();
58caf339d004fad667748b68912c254df4e75cdc5aYao Chen
59caf339d004fad667748b68912c254df4e75cdc5aYao Chen    if (mLogicalOperation == LogicalOperation::NOT && matcher.matcher_size() != 1) {
60caf339d004fad667748b68912c254df4e75cdc5aYao Chen        return false;
61caf339d004fad667748b68912c254df4e75cdc5aYao Chen    }
62caf339d004fad667748b68912c254df4e75cdc5aYao Chen
6394e197cceb2ba7df13ff8de04f60bfeec64015d9Yangster-mac    for (const auto& child : matcher.matcher()) {
64caf339d004fad667748b68912c254df4e75cdc5aYao Chen        auto pair = matcherMap.find(child);
65caf339d004fad667748b68912c254df4e75cdc5aYao Chen        if (pair == matcherMap.end()) {
6694e197cceb2ba7df13ff8de04f60bfeec64015d9Yangster-mac            ALOGW("Matcher %lld not found in the config", (long long)child);
67caf339d004fad667748b68912c254df4e75cdc5aYao Chen            return false;
68caf339d004fad667748b68912c254df4e75cdc5aYao Chen        }
69caf339d004fad667748b68912c254df4e75cdc5aYao Chen
70caf339d004fad667748b68912c254df4e75cdc5aYao Chen        int childIndex = pair->second;
71caf339d004fad667748b68912c254df4e75cdc5aYao Chen
72caf339d004fad667748b68912c254df4e75cdc5aYao Chen        // if the child is a visited node in the recursion -> circle detected.
73caf339d004fad667748b68912c254df4e75cdc5aYao Chen        if (stack[childIndex]) {
74caf339d004fad667748b68912c254df4e75cdc5aYao Chen            ALOGE("Circle detected in matcher config");
75caf339d004fad667748b68912c254df4e75cdc5aYao Chen            return false;
76caf339d004fad667748b68912c254df4e75cdc5aYao Chen        }
77caf339d004fad667748b68912c254df4e75cdc5aYao Chen
78caf339d004fad667748b68912c254df4e75cdc5aYao Chen        if (!allTrackers[childIndex]->init(allLogMatchers, allTrackers, matcherMap, stack)) {
7994e197cceb2ba7df13ff8de04f60bfeec64015d9Yangster-mac            ALOGW("child matcher init failed %lld", (long long)child);
80caf339d004fad667748b68912c254df4e75cdc5aYao Chen            return false;
81caf339d004fad667748b68912c254df4e75cdc5aYao Chen        }
82caf339d004fad667748b68912c254df4e75cdc5aYao Chen
83caf339d004fad667748b68912c254df4e75cdc5aYao Chen        mChildren.push_back(childIndex);
84caf339d004fad667748b68912c254df4e75cdc5aYao Chen
852087716f2bdca90c7c3034d556ac12911bd8018eYangster-mac        const set<int>& childTagIds = allTrackers[childIndex]->getAtomIds();
862087716f2bdca90c7c3034d556ac12911bd8018eYangster-mac        mAtomIds.insert(childTagIds.begin(), childTagIds.end());
87caf339d004fad667748b68912c254df4e75cdc5aYao Chen    }
88caf339d004fad667748b68912c254df4e75cdc5aYao Chen
89caf339d004fad667748b68912c254df4e75cdc5aYao Chen    mInitialized = true;
90caf339d004fad667748b68912c254df4e75cdc5aYao Chen    // unmark this node in the recursion stack.
91caf339d004fad667748b68912c254df4e75cdc5aYao Chen    stack[mIndex] = false;
92caf339d004fad667748b68912c254df4e75cdc5aYao Chen    return true;
93caf339d004fad667748b68912c254df4e75cdc5aYao Chen}
94caf339d004fad667748b68912c254df4e75cdc5aYao Chen
95c4dfae56c10a1dd571baa78c750f2e68c919d74fJoe Onoratovoid CombinationLogMatchingTracker::onLogEvent(const LogEvent& event,
96caf339d004fad667748b68912c254df4e75cdc5aYao Chen                                               const vector<sp<LogMatchingTracker>>& allTrackers,
97caf339d004fad667748b68912c254df4e75cdc5aYao Chen                                               vector<MatchingState>& matcherResults) {
98caf339d004fad667748b68912c254df4e75cdc5aYao Chen    // this event has been processed.
99caf339d004fad667748b68912c254df4e75cdc5aYao Chen    if (matcherResults[mIndex] != MatchingState::kNotComputed) {
100caf339d004fad667748b68912c254df4e75cdc5aYao Chen        return;
101caf339d004fad667748b68912c254df4e75cdc5aYao Chen    }
102caf339d004fad667748b68912c254df4e75cdc5aYao Chen
1032087716f2bdca90c7c3034d556ac12911bd8018eYangster-mac    if (mAtomIds.find(event.GetTagId()) == mAtomIds.end()) {
104caf339d004fad667748b68912c254df4e75cdc5aYao Chen        matcherResults[mIndex] = MatchingState::kNotMatched;
105caf339d004fad667748b68912c254df4e75cdc5aYao Chen        return;
106caf339d004fad667748b68912c254df4e75cdc5aYao Chen    }
107caf339d004fad667748b68912c254df4e75cdc5aYao Chen
108caf339d004fad667748b68912c254df4e75cdc5aYao Chen    // evaluate children matchers if they haven't been evaluated.
109caf339d004fad667748b68912c254df4e75cdc5aYao Chen    for (const int childIndex : mChildren) {
110caf339d004fad667748b68912c254df4e75cdc5aYao Chen        if (matcherResults[childIndex] == MatchingState::kNotComputed) {
111caf339d004fad667748b68912c254df4e75cdc5aYao Chen            const sp<LogMatchingTracker>& child = allTrackers[childIndex];
112caf339d004fad667748b68912c254df4e75cdc5aYao Chen            child->onLogEvent(event, allTrackers, matcherResults);
113caf339d004fad667748b68912c254df4e75cdc5aYao Chen        }
114caf339d004fad667748b68912c254df4e75cdc5aYao Chen    }
115caf339d004fad667748b68912c254df4e75cdc5aYao Chen
116caf339d004fad667748b68912c254df4e75cdc5aYao Chen    bool matched = combinationMatch(mChildren, mLogicalOperation, matcherResults);
117caf339d004fad667748b68912c254df4e75cdc5aYao Chen    matcherResults[mIndex] = matched ? MatchingState::kMatched : MatchingState::kNotMatched;
118caf339d004fad667748b68912c254df4e75cdc5aYao Chen}
119caf339d004fad667748b68912c254df4e75cdc5aYao Chen
120caf339d004fad667748b68912c254df4e75cdc5aYao Chen}  // namespace statsd
121caf339d004fad667748b68912c254df4e75cdc5aYao Chen}  // namespace os
122caf339d004fad667748b68912c254df4e75cdc5aYao Chen}  // namespace android
123