Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit cc970146 authored by Tej Singh's avatar Tej Singh
Browse files

Partial config update: predicates

This cl is part of the effort to allow partial config updates in statsd.
As with matchers, there are two main steps:
1. Determine update status of each predicate
2. Perform the update
   a. Copy over preserved conditions and create new ones for ones that
need to be replaced or are new.
   b. Update the tracker and predicate indices of preserved conditions
   c. Init all conditions to initialize new ones and determine the
current condition status

Added new unit tests, and use gmock to make container assertions more
readable.

Test: atest statsd_test
Change-Id: I74249431a9db2b409253d536044acc1fc3cf5c4c
parent 612be42e
Loading
Loading
Loading
Loading
+46 −2
Original line number Original line Diff line number Diff line
@@ -25,8 +25,9 @@ namespace statsd {
using std::unordered_map;
using std::unordered_map;
using std::vector;
using std::vector;


CombinationConditionTracker::CombinationConditionTracker(const int64_t& id, const int index)
CombinationConditionTracker::CombinationConditionTracker(const int64_t& id, const int index,
    : ConditionTracker(id, index) {
                                                         const uint64_t protoHash)
    : ConditionTracker(id, index, protoHash) {
    VLOG("creating CombinationConditionTracker %lld", (long long)mConditionId);
    VLOG("creating CombinationConditionTracker %lld", (long long)mConditionId);
}
}


@@ -122,6 +123,49 @@ bool CombinationConditionTracker::init(const vector<Predicate>& allConditionConf
    return true;
    return true;
}
}


bool CombinationConditionTracker::onConfigUpdated(
        const vector<Predicate>& allConditionProtos, const int index,
        const vector<sp<ConditionTracker>>& allConditionTrackers,
        const unordered_map<int64_t, int>& atomMatchingTrackerMap,
        const unordered_map<int64_t, int>& conditionTrackerMap) {
    ConditionTracker::onConfigUpdated(allConditionProtos, index, allConditionTrackers,
                                      atomMatchingTrackerMap, conditionTrackerMap);
    mTrackerIndex.clear();
    mChildren.clear();
    mUnSlicedChildren.clear();
    mSlicedChildren.clear();
    Predicate_Combination combinationCondition = allConditionProtos[mIndex].combination();

    for (const int64_t child : combinationCondition.predicate()) {
        const auto& it = conditionTrackerMap.find(child);

        if (it == conditionTrackerMap.end()) {
            ALOGW("Predicate %lld not found in the config", (long long)child);
            return false;
        }

        int childIndex = it->second;
        const sp<ConditionTracker>& childTracker = allConditionTrackers[childIndex];

        // Ensures that the child's tracker indices are updated.
        if (!childTracker->onConfigUpdated(allConditionProtos, childIndex, allConditionTrackers,
                                           atomMatchingTrackerMap, conditionTrackerMap)) {
            ALOGW("Child update failed %lld ", (long long)child);
            return false;
        }

        if (allConditionTrackers[childIndex]->isSliced()) {
            mSlicedChildren.push_back(childIndex);
        } else {
            mUnSlicedChildren.push_back(childIndex);
        }
        mChildren.push_back(childIndex);
        mTrackerIndex.insert(childTracker->getAtomMatchingTrackerIndex().begin(),
                             childTracker->getAtomMatchingTrackerIndex().end());
    }
    return true;
}

void CombinationConditionTracker::isConditionMet(
void CombinationConditionTracker::isConditionMet(
        const ConditionKey& conditionParameters, const vector<sp<ConditionTracker>>& allConditions,
        const ConditionKey& conditionParameters, const vector<sp<ConditionTracker>>& allConditions,
        const bool isPartialLink,
        const bool isPartialLink,
+8 −2
Original line number Original line Diff line number Diff line
@@ -24,9 +24,9 @@ namespace android {
namespace os {
namespace os {
namespace statsd {
namespace statsd {


class CombinationConditionTracker : public virtual ConditionTracker {
class CombinationConditionTracker : public ConditionTracker {
public:
public:
    CombinationConditionTracker(const int64_t& id, const int index);
    CombinationConditionTracker(const int64_t& id, const int index, const uint64_t protoHash);


    ~CombinationConditionTracker();
    ~CombinationConditionTracker();


@@ -35,6 +35,11 @@ public:
              const std::unordered_map<int64_t, int>& conditionIdIndexMap, std::vector<bool>& stack,
              const std::unordered_map<int64_t, int>& conditionIdIndexMap, std::vector<bool>& stack,
              std::vector<ConditionState>& conditionCache) override;
              std::vector<ConditionState>& conditionCache) override;


    bool onConfigUpdated(const std::vector<Predicate>& allConditionProtos, const int index,
                         const std::vector<sp<ConditionTracker>>& allConditionTrackers,
                         const std::unordered_map<int64_t, int>& atomMatchingTrackerMap,
                         const std::unordered_map<int64_t, int>& conditionTrackerMap) override;

    void evaluateCondition(const LogEvent& event,
    void evaluateCondition(const LogEvent& event,
                           const std::vector<MatchingState>& eventMatcherValues,
                           const std::vector<MatchingState>& eventMatcherValues,
                           const std::vector<sp<ConditionTracker>>& mAllConditions,
                           const std::vector<sp<ConditionTracker>>& mAllConditions,
@@ -102,6 +107,7 @@ private:
    std::vector<int> mSlicedChildren;
    std::vector<int> mSlicedChildren;
    std::vector<int> mUnSlicedChildren;
    std::vector<int> mUnSlicedChildren;


    FRIEND_TEST(ConfigUpdateTest, TestUpdateConditions);
};
};


}  // namespace statsd
}  // namespace statsd
+35 −6
Original line number Original line Diff line number Diff line
@@ -31,18 +31,17 @@ namespace statsd {


class ConditionTracker : public virtual RefBase {
class ConditionTracker : public virtual RefBase {
public:
public:
    ConditionTracker(const int64_t& id, const int index)
    ConditionTracker(const int64_t& id, const int index, const uint64_t protoHash)
        : mConditionId(id),
        : mConditionId(id),
          mIndex(index),
          mIndex(index),
          mInitialized(false),
          mInitialized(false),
          mTrackerIndex(),
          mTrackerIndex(),
          mUnSlicedPartCondition(ConditionState::kUnknown),
          mUnSlicedPartCondition(ConditionState::kUnknown),
          mSliced(false){};
          mSliced(false),
          mProtoHash(protoHash){};


    virtual ~ConditionTracker(){};
    virtual ~ConditionTracker(){};


    inline const int64_t& getId() { return mConditionId; }

    // Initialize this ConditionTracker. This initialization is done recursively (DFS). It can also
    // Initialize this ConditionTracker. This initialization is done recursively (DFS). It can also
    // be done in the constructor, but we do it separately because (1) easy to return a bool to
    // be done in the constructor, but we do it separately because (1) easy to return a bool to
    // indicate whether the initialization is successful. (2) makes unit test easier.
    // indicate whether the initialization is successful. (2) makes unit test easier.
@@ -50,7 +49,7 @@ public:
    // fill the condition cache with the current condition.
    // fill the condition cache with the current condition.
    // allConditionConfig: the list of all Predicate config from statsd_config.
    // allConditionConfig: the list of all Predicate config from statsd_config.
    // allConditionTrackers: the list of all ConditionTrackers (this is needed because we may also
    // allConditionTrackers: the list of all ConditionTrackers (this is needed because we may also
    //                       need to call init() on children conditions)
    //                       need to call init() on child conditions)
    // conditionIdIndexMap: the mapping from condition id to its index.
    // conditionIdIndexMap: the mapping from condition id to its index.
    // stack: a bit map to keep track which nodes have been visited on the stack in the recursion.
    // stack: a bit map to keep track which nodes have been visited on the stack in the recursion.
    // conditionCache: tracks initial conditions of all ConditionTrackers. returns the
    // conditionCache: tracks initial conditions of all ConditionTrackers. returns the
@@ -60,6 +59,26 @@ public:
                      const std::unordered_map<int64_t, int>& conditionIdIndexMap,
                      const std::unordered_map<int64_t, int>& conditionIdIndexMap,
                      std::vector<bool>& stack, std::vector<ConditionState>& conditionCache) = 0;
                      std::vector<bool>& stack, std::vector<ConditionState>& conditionCache) = 0;


    // Update appropriate state on config updates. Primarily, all indices need to be updated.
    // This predicate and all of its children are guaranteed to be preserved across the update.
    // This function is recursive and will call onConfigUpdated on child conditions. It does not
    // manage cycle detection since all preserved conditions should not have any cycles.
    //
    // allConditionProtos: the new predicates.
    // index: the new index of this tracker in allConditionProtos and allConditionTrackers.
    // allConditionTrackers: the list of all ConditionTrackers (this is needed because we may also
    //                       need to call onConfigUpdated() on child conditions)
    // [atomMatchingTrackerMap]: map of atom matcher id to index after the config update
    // [conditionTrackerMap]: map of condition tracker id to index after the config update.
    // returns whether or not the update is successful
    virtual bool onConfigUpdated(const std::vector<Predicate>& allConditionProtos, const int index,
                                 const std::vector<sp<ConditionTracker>>& allConditionTrackers,
                                 const std::unordered_map<int64_t, int>& atomMatchingTrackerMap,
                                 const std::unordered_map<int64_t, int>& conditionTrackerMap) {
        mIndex = index;
        return true;
    }

    // evaluate current condition given the new event.
    // evaluate current condition given the new event.
    // event: the new log event
    // event: the new log event
    // eventMatcherValues: the results of the AtomMatchingTrackers. AtomMatchingTrackers always
    // eventMatcherValues: the results of the AtomMatchingTrackers. AtomMatchingTrackers always
@@ -112,6 +131,10 @@ public:
        return mConditionId;
        return mConditionId;
    }
    }


    inline uint64_t getProtoHash() const {
        return mProtoHash;
    }

    virtual void getTrueSlicedDimensions(
    virtual void getTrueSlicedDimensions(
        const std::vector<sp<ConditionTracker>>& allConditions,
        const std::vector<sp<ConditionTracker>>& allConditions,
        std::set<HashableDimensionKey>* dimensions) const = 0;
        std::set<HashableDimensionKey>* dimensions) const = 0;
@@ -133,7 +156,7 @@ protected:
    const int64_t mConditionId;
    const int64_t mConditionId;


    // the index of this condition in the manager's condition list.
    // the index of this condition in the manager's condition list.
    const int mIndex;
    int mIndex;


    // if it's properly initialized.
    // if it's properly initialized.
    bool mInitialized;
    bool mInitialized;
@@ -151,6 +174,12 @@ protected:
    ConditionState mUnSlicedPartCondition;
    ConditionState mUnSlicedPartCondition;


    bool mSliced;
    bool mSliced;

    // Hash of the Predicate's proto bytes from StatsdConfig.
    // Used to determine if the definition of this condition has changed across a config update.
    const uint64_t mProtoHash;

    FRIEND_TEST(ConfigUpdateTest, TestUpdateConditions);
};
};


}  // namespace statsd
}  // namespace statsd
+59 −39
Original line number Original line Diff line number Diff line
@@ -27,54 +27,21 @@ namespace statsd {
using std::unordered_map;
using std::unordered_map;


SimpleConditionTracker::SimpleConditionTracker(
SimpleConditionTracker::SimpleConditionTracker(
        const ConfigKey& key, const int64_t& id, const int index,
        const ConfigKey& key, const int64_t& id, const uint64_t protoHash, const int index,
        const SimplePredicate& simplePredicate,
        const SimplePredicate& simplePredicate,
        const unordered_map<int64_t, int>& trackerNameIndexMap)
        const unordered_map<int64_t, int>& atomMatchingTrackerMap)
    : ConditionTracker(id, index), mConfigKey(key), mContainANYPositionInInternalDimensions(false) {
    : ConditionTracker(id, index, protoHash),
      mConfigKey(key),
      mContainANYPositionInInternalDimensions(false) {
    VLOG("creating SimpleConditionTracker %lld", (long long)mConditionId);
    VLOG("creating SimpleConditionTracker %lld", (long long)mConditionId);
    mCountNesting = simplePredicate.count_nesting();
    mCountNesting = simplePredicate.count_nesting();


    if (simplePredicate.has_start()) {
    setMatcherIndices(simplePredicate, atomMatchingTrackerMap);
        auto pair = trackerNameIndexMap.find(simplePredicate.start());
        if (pair == trackerNameIndexMap.end()) {
            ALOGW("Start matcher %lld not found in the config", (long long)simplePredicate.start());
            return;
        }
        mStartLogMatcherIndex = pair->second;
        mTrackerIndex.insert(mStartLogMatcherIndex);
    } else {
        mStartLogMatcherIndex = -1;
    }

    if (simplePredicate.has_stop()) {
        auto pair = trackerNameIndexMap.find(simplePredicate.stop());
        if (pair == trackerNameIndexMap.end()) {
            ALOGW("Stop matcher %lld not found in the config", (long long)simplePredicate.stop());
            return;
        }
        mStopLogMatcherIndex = pair->second;
        mTrackerIndex.insert(mStopLogMatcherIndex);
    } else {
        mStopLogMatcherIndex = -1;
    }

    if (simplePredicate.has_stop_all()) {
        auto pair = trackerNameIndexMap.find(simplePredicate.stop_all());
        if (pair == trackerNameIndexMap.end()) {
            ALOGW("Stop all matcher %lld found in the config", (long long)simplePredicate.stop_all());
            return;
        }
        mStopAllLogMatcherIndex = pair->second;
        mTrackerIndex.insert(mStopAllLogMatcherIndex);
    } else {
        mStopAllLogMatcherIndex = -1;
    }


    if (simplePredicate.has_dimensions()) {
    if (simplePredicate.has_dimensions()) {
        translateFieldMatcher(simplePredicate.dimensions(), &mOutputDimensions);
        translateFieldMatcher(simplePredicate.dimensions(), &mOutputDimensions);
        if (mOutputDimensions.size() > 0) {
        if (mOutputDimensions.size() > 0) {
            mSliced = true;
            mSliced = true;
            mDimensionTag = mOutputDimensions[0].mMatcher.getTag();
        }
        }
        mContainANYPositionInInternalDimensions = HasPositionANY(simplePredicate.dimensions());
        mContainANYPositionInInternalDimensions = HasPositionANY(simplePredicate.dimensions());
    }
    }
@@ -106,6 +73,59 @@ bool SimpleConditionTracker::init(const vector<Predicate>& allConditionConfig,
    return mInitialized;
    return mInitialized;
}
}


bool SimpleConditionTracker::onConfigUpdated(
        const vector<Predicate>& allConditionProtos, const int index,
        const vector<sp<ConditionTracker>>& allConditionTrackers,
        const unordered_map<int64_t, int>& atomMatchingTrackerMap,
        const unordered_map<int64_t, int>& conditionTrackerMap) {
    ConditionTracker::onConfigUpdated(allConditionProtos, index, allConditionTrackers,
                                      atomMatchingTrackerMap, conditionTrackerMap);
    setMatcherIndices(allConditionProtos[index].simple_predicate(), atomMatchingTrackerMap);
    return true;
}

void SimpleConditionTracker::setMatcherIndices(
        const SimplePredicate& simplePredicate,
        const unordered_map<int64_t, int>& atomMatchingTrackerMap) {
    mTrackerIndex.clear();
    if (simplePredicate.has_start()) {
        auto pair = atomMatchingTrackerMap.find(simplePredicate.start());
        if (pair == atomMatchingTrackerMap.end()) {
            ALOGW("Start matcher %lld not found in the config", (long long)simplePredicate.start());
            return;
        }
        mStartLogMatcherIndex = pair->second;
        mTrackerIndex.insert(mStartLogMatcherIndex);
    } else {
        mStartLogMatcherIndex = -1;
    }

    if (simplePredicate.has_stop()) {
        auto pair = atomMatchingTrackerMap.find(simplePredicate.stop());
        if (pair == atomMatchingTrackerMap.end()) {
            ALOGW("Stop matcher %lld not found in the config", (long long)simplePredicate.stop());
            return;
        }
        mStopLogMatcherIndex = pair->second;
        mTrackerIndex.insert(mStopLogMatcherIndex);
    } else {
        mStopLogMatcherIndex = -1;
    }

    if (simplePredicate.has_stop_all()) {
        auto pair = atomMatchingTrackerMap.find(simplePredicate.stop_all());
        if (pair == atomMatchingTrackerMap.end()) {
            ALOGW("Stop all matcher %lld found in the config",
                  (long long)simplePredicate.stop_all());
            return;
        }
        mStopAllLogMatcherIndex = pair->second;
        mTrackerIndex.insert(mStopAllLogMatcherIndex);
    } else {
        mStopAllLogMatcherIndex = -1;
    }
}

void SimpleConditionTracker::dumpState() {
void SimpleConditionTracker::dumpState() {
    VLOG("%lld DUMP:", (long long)mConditionId);
    VLOG("%lld DUMP:", (long long)mConditionId);
    for (const auto& pair : mSlicedConditionState) {
    for (const auto& pair : mSlicedConditionState) {
+13 −6
Original line number Original line Diff line number Diff line
@@ -27,11 +27,11 @@ namespace android {
namespace os {
namespace os {
namespace statsd {
namespace statsd {


class SimpleConditionTracker : public virtual ConditionTracker {
class SimpleConditionTracker : public ConditionTracker {
public:
public:
    SimpleConditionTracker(const ConfigKey& key, const int64_t& id, const int index,
    SimpleConditionTracker(const ConfigKey& key, const int64_t& id, const uint64_t protoHash,
                           const SimplePredicate& simplePredicate,
                           const int index, const SimplePredicate& simplePredicate,
                           const std::unordered_map<int64_t, int>& trackerNameIndexMap);
                           const std::unordered_map<int64_t, int>& atomMatchingTrackerMap);


    ~SimpleConditionTracker();
    ~SimpleConditionTracker();


@@ -40,6 +40,11 @@ public:
              const std::unordered_map<int64_t, int>& conditionIdIndexMap, std::vector<bool>& stack,
              const std::unordered_map<int64_t, int>& conditionIdIndexMap, std::vector<bool>& stack,
              std::vector<ConditionState>& conditionCache) override;
              std::vector<ConditionState>& conditionCache) override;


    bool onConfigUpdated(const std::vector<Predicate>& allConditionProtos, const int index,
                         const std::vector<sp<ConditionTracker>>& allConditionTrackers,
                         const std::unordered_map<int64_t, int>& atomMatchingTrackerMap,
                         const std::unordered_map<int64_t, int>& conditionTrackerMap) override;

    void evaluateCondition(const LogEvent& event,
    void evaluateCondition(const LogEvent& event,
                           const std::vector<MatchingState>& eventMatcherValues,
                           const std::vector<MatchingState>& eventMatcherValues,
                           const std::vector<sp<ConditionTracker>>& mAllConditions,
                           const std::vector<sp<ConditionTracker>>& mAllConditions,
@@ -112,10 +117,11 @@ private:
    std::set<HashableDimensionKey> mLastChangedToTrueDimensions;
    std::set<HashableDimensionKey> mLastChangedToTrueDimensions;
    std::set<HashableDimensionKey> mLastChangedToFalseDimensions;
    std::set<HashableDimensionKey> mLastChangedToFalseDimensions;


    int mDimensionTag;

    std::map<HashableDimensionKey, int> mSlicedConditionState;
    std::map<HashableDimensionKey, int> mSlicedConditionState;


    void setMatcherIndices(const SimplePredicate& predicate,
                           const std::unordered_map<int64_t, int>& logTrackerMap);

    void handleStopAll(std::vector<ConditionState>& conditionCache,
    void handleStopAll(std::vector<ConditionState>& conditionCache,
                       std::vector<bool>& changedCache);
                       std::vector<bool>& changedCache);


@@ -129,6 +135,7 @@ private:
    FRIEND_TEST(SimpleConditionTrackerTest, TestSlicedCondition);
    FRIEND_TEST(SimpleConditionTrackerTest, TestSlicedCondition);
    FRIEND_TEST(SimpleConditionTrackerTest, TestSlicedWithNoOutputDim);
    FRIEND_TEST(SimpleConditionTrackerTest, TestSlicedWithNoOutputDim);
    FRIEND_TEST(SimpleConditionTrackerTest, TestStopAll);
    FRIEND_TEST(SimpleConditionTrackerTest, TestStopAll);
    FRIEND_TEST(ConfigUpdateTest, TestUpdateConditions);
};
};


}  // namespace statsd
}  // namespace statsd
Loading