Loading cmds/statsd/Android.mk +3 −2 Original line number Diff line number Diff line Loading @@ -54,7 +54,7 @@ statsd_common_src := \ src/storage/StorageManager.cpp \ src/StatsLogProcessor.cpp \ src/StatsService.cpp \ src/stats_util.cpp \ src/HashableDimensionKey.cpp \ src/guardrail/MemoryLeakTrackUtil.cpp \ src/guardrail/StatsdStats.cpp Loading Loading @@ -174,7 +174,8 @@ LOCAL_SRC_FILES := \ tests/metrics/EventMetricProducer_test.cpp \ tests/metrics/ValueMetricProducer_test.cpp \ tests/metrics/GaugeMetricProducer_test.cpp \ tests/guardrail/StatsdStats_test.cpp tests/guardrail/StatsdStats_test.cpp \ tests/metrics/metrics_test_helper.cpp LOCAL_STATIC_LIBRARIES := \ $(statsd_common_static_libraries) \ Loading cmds/statsd/src/stats_util.cpp→cmds/statsd/src/HashableDimensionKey.cpp +110 −0 Original line number Diff line number Diff line Loading @@ -13,19 +13,17 @@ * See the License for the specific language governing permissions and * limitations under the License. */ #include "stats_util.h" #include "HashableDimensionKey.h" namespace android { namespace os { namespace statsd { // There is no existing hash function for the dimension key ("repeated KeyValuePair"). // Temporarily use a string concatenation as the hashable key. // TODO: Find a better hash function for std::vector<KeyValuePair>. HashableDimensionKey getHashableKey(std::vector<KeyValuePair> keys) { std::string flattened; for (const KeyValuePair& pair : keys) { using std::string; string HashableDimensionKey::toString() const { string flattened; for (const auto& pair : mKeyValuePairs) { flattened += std::to_string(pair.key()); flattened += ":"; switch (pair.value_case()) { Loading @@ -52,6 +50,61 @@ HashableDimensionKey getHashableKey(std::vector<KeyValuePair> keys) { return flattened; } bool HashableDimensionKey::operator==(const HashableDimensionKey& that) const { const auto& keyValue2 = that.getKeyValuePairs(); if (mKeyValuePairs.size() != keyValue2.size()) { return false; } for (size_t i = 0; i < keyValue2.size(); i++) { const auto& kv1 = mKeyValuePairs[i]; const auto& kv2 = keyValue2[i]; if (kv1.key() != kv2.key()) { return false; } if (kv1.value_case() != kv2.value_case()) { return false; } switch (kv1.value_case()) { case KeyValuePair::ValueCase::kValueStr: if (kv1.value_str() != kv2.value_str()) { return false; } break; case KeyValuePair::ValueCase::kValueInt: if (kv1.value_int() != kv2.value_int()) { return false; } break; case KeyValuePair::ValueCase::kValueLong: if (kv1.value_long() != kv2.value_long()) { return false; } break; case KeyValuePair::ValueCase::kValueBool: if (kv1.value_bool() != kv2.value_bool()) { return false; } break; case KeyValuePair::ValueCase::kValueFloat: { if (kv1.value_float() != kv2.value_float()) { return false; } break; } case KeyValuePair::ValueCase::VALUE_NOT_SET: break; } } return true; }; bool HashableDimensionKey::operator<(const HashableDimensionKey& that) const { return toString().compare(that.toString()) < 0; }; } // namespace statsd } // namespace os } // namespace android No newline at end of file cmds/statsd/src/HashableDimensionKey.h 0 → 100644 +102 −0 Original line number Diff line number Diff line /* * Copyright (C) 2017 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #pragma once #include <utils/JenkinsHash.h> #include "frameworks/base/cmds/statsd/src/stats_log.pb.h" namespace android { namespace os { namespace statsd { class HashableDimensionKey { public: explicit HashableDimensionKey(const std::vector<KeyValuePair>& keyValuePairs) : mKeyValuePairs(keyValuePairs){}; HashableDimensionKey(){}; HashableDimensionKey(const HashableDimensionKey& that) : mKeyValuePairs(that.getKeyValuePairs()){}; HashableDimensionKey& operator=(const HashableDimensionKey& from) = default; std::string toString() const; inline const std::vector<KeyValuePair>& getKeyValuePairs() const { return mKeyValuePairs; } bool operator==(const HashableDimensionKey& that) const; bool operator<(const HashableDimensionKey& that) const; inline const char* c_str() const { return toString().c_str(); } private: std::vector<KeyValuePair> mKeyValuePairs; }; } // namespace statsd } // namespace os } // namespace android namespace std { using android::os::statsd::HashableDimensionKey; using android::os::statsd::KeyValuePair; template <> struct hash<HashableDimensionKey> { std::size_t operator()(const HashableDimensionKey& key) const { android::hash_t hash = 0; for (const auto& pair : key.getKeyValuePairs()) { hash = android::JenkinsHashMix(hash, android::hash_type(pair.key())); hash = android::JenkinsHashMix( hash, android::hash_type(static_cast<int32_t>(pair.value_case()))); switch (pair.value_case()) { case KeyValuePair::ValueCase::kValueStr: hash = android::JenkinsHashMix( hash, static_cast<uint32_t>(std::hash<std::string>()(pair.value_str()))); break; case KeyValuePair::ValueCase::kValueInt: hash = android::JenkinsHashMix(hash, android::hash_type(pair.value_int())); break; case KeyValuePair::ValueCase::kValueLong: hash = android::JenkinsHashMix( hash, android::hash_type(static_cast<int64_t>(pair.value_long()))); break; case KeyValuePair::ValueCase::kValueBool: hash = android::JenkinsHashMix(hash, android::hash_type(pair.value_bool())); break; case KeyValuePair::ValueCase::kValueFloat: { float floatVal = pair.value_float(); hash = android::JenkinsHashMixBytes(hash, (uint8_t*)&floatVal, sizeof(float)); break; } case KeyValuePair::ValueCase::VALUE_NOT_SET: break; } } return hash; } }; } // namespace std cmds/statsd/src/condition/SimpleConditionTracker.cpp +1 −1 Original line number Diff line number Diff line Loading @@ -279,7 +279,7 @@ void SimpleConditionTracker::evaluateCondition(const LogEvent& event, } // outputKey is the output key values. e.g, uid:1234 const HashableDimensionKey outputKey = getHashableKey(getDimensionKey(event, mOutputDimension)); const HashableDimensionKey outputKey(getDimensionKey(event, mOutputDimension)); handleConditionEvent(outputKey, matchedState == 1, conditionCache, conditionChangedCache); } Loading cmds/statsd/src/condition/condition_util.cpp +1 −1 Original line number Diff line number Diff line Loading @@ -109,7 +109,7 @@ HashableDimensionKey getDimensionKeyForCondition(const LogEvent& event, kv.set_key(link.key_in_condition(i).key()); } return getHashableKey(dimensionKey); return HashableDimensionKey(dimensionKey); } } // namespace statsd Loading Loading
cmds/statsd/Android.mk +3 −2 Original line number Diff line number Diff line Loading @@ -54,7 +54,7 @@ statsd_common_src := \ src/storage/StorageManager.cpp \ src/StatsLogProcessor.cpp \ src/StatsService.cpp \ src/stats_util.cpp \ src/HashableDimensionKey.cpp \ src/guardrail/MemoryLeakTrackUtil.cpp \ src/guardrail/StatsdStats.cpp Loading Loading @@ -174,7 +174,8 @@ LOCAL_SRC_FILES := \ tests/metrics/EventMetricProducer_test.cpp \ tests/metrics/ValueMetricProducer_test.cpp \ tests/metrics/GaugeMetricProducer_test.cpp \ tests/guardrail/StatsdStats_test.cpp tests/guardrail/StatsdStats_test.cpp \ tests/metrics/metrics_test_helper.cpp LOCAL_STATIC_LIBRARIES := \ $(statsd_common_static_libraries) \ Loading
cmds/statsd/src/stats_util.cpp→cmds/statsd/src/HashableDimensionKey.cpp +110 −0 Original line number Diff line number Diff line Loading @@ -13,19 +13,17 @@ * See the License for the specific language governing permissions and * limitations under the License. */ #include "stats_util.h" #include "HashableDimensionKey.h" namespace android { namespace os { namespace statsd { // There is no existing hash function for the dimension key ("repeated KeyValuePair"). // Temporarily use a string concatenation as the hashable key. // TODO: Find a better hash function for std::vector<KeyValuePair>. HashableDimensionKey getHashableKey(std::vector<KeyValuePair> keys) { std::string flattened; for (const KeyValuePair& pair : keys) { using std::string; string HashableDimensionKey::toString() const { string flattened; for (const auto& pair : mKeyValuePairs) { flattened += std::to_string(pair.key()); flattened += ":"; switch (pair.value_case()) { Loading @@ -52,6 +50,61 @@ HashableDimensionKey getHashableKey(std::vector<KeyValuePair> keys) { return flattened; } bool HashableDimensionKey::operator==(const HashableDimensionKey& that) const { const auto& keyValue2 = that.getKeyValuePairs(); if (mKeyValuePairs.size() != keyValue2.size()) { return false; } for (size_t i = 0; i < keyValue2.size(); i++) { const auto& kv1 = mKeyValuePairs[i]; const auto& kv2 = keyValue2[i]; if (kv1.key() != kv2.key()) { return false; } if (kv1.value_case() != kv2.value_case()) { return false; } switch (kv1.value_case()) { case KeyValuePair::ValueCase::kValueStr: if (kv1.value_str() != kv2.value_str()) { return false; } break; case KeyValuePair::ValueCase::kValueInt: if (kv1.value_int() != kv2.value_int()) { return false; } break; case KeyValuePair::ValueCase::kValueLong: if (kv1.value_long() != kv2.value_long()) { return false; } break; case KeyValuePair::ValueCase::kValueBool: if (kv1.value_bool() != kv2.value_bool()) { return false; } break; case KeyValuePair::ValueCase::kValueFloat: { if (kv1.value_float() != kv2.value_float()) { return false; } break; } case KeyValuePair::ValueCase::VALUE_NOT_SET: break; } } return true; }; bool HashableDimensionKey::operator<(const HashableDimensionKey& that) const { return toString().compare(that.toString()) < 0; }; } // namespace statsd } // namespace os } // namespace android No newline at end of file
cmds/statsd/src/HashableDimensionKey.h 0 → 100644 +102 −0 Original line number Diff line number Diff line /* * Copyright (C) 2017 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #pragma once #include <utils/JenkinsHash.h> #include "frameworks/base/cmds/statsd/src/stats_log.pb.h" namespace android { namespace os { namespace statsd { class HashableDimensionKey { public: explicit HashableDimensionKey(const std::vector<KeyValuePair>& keyValuePairs) : mKeyValuePairs(keyValuePairs){}; HashableDimensionKey(){}; HashableDimensionKey(const HashableDimensionKey& that) : mKeyValuePairs(that.getKeyValuePairs()){}; HashableDimensionKey& operator=(const HashableDimensionKey& from) = default; std::string toString() const; inline const std::vector<KeyValuePair>& getKeyValuePairs() const { return mKeyValuePairs; } bool operator==(const HashableDimensionKey& that) const; bool operator<(const HashableDimensionKey& that) const; inline const char* c_str() const { return toString().c_str(); } private: std::vector<KeyValuePair> mKeyValuePairs; }; } // namespace statsd } // namespace os } // namespace android namespace std { using android::os::statsd::HashableDimensionKey; using android::os::statsd::KeyValuePair; template <> struct hash<HashableDimensionKey> { std::size_t operator()(const HashableDimensionKey& key) const { android::hash_t hash = 0; for (const auto& pair : key.getKeyValuePairs()) { hash = android::JenkinsHashMix(hash, android::hash_type(pair.key())); hash = android::JenkinsHashMix( hash, android::hash_type(static_cast<int32_t>(pair.value_case()))); switch (pair.value_case()) { case KeyValuePair::ValueCase::kValueStr: hash = android::JenkinsHashMix( hash, static_cast<uint32_t>(std::hash<std::string>()(pair.value_str()))); break; case KeyValuePair::ValueCase::kValueInt: hash = android::JenkinsHashMix(hash, android::hash_type(pair.value_int())); break; case KeyValuePair::ValueCase::kValueLong: hash = android::JenkinsHashMix( hash, android::hash_type(static_cast<int64_t>(pair.value_long()))); break; case KeyValuePair::ValueCase::kValueBool: hash = android::JenkinsHashMix(hash, android::hash_type(pair.value_bool())); break; case KeyValuePair::ValueCase::kValueFloat: { float floatVal = pair.value_float(); hash = android::JenkinsHashMixBytes(hash, (uint8_t*)&floatVal, sizeof(float)); break; } case KeyValuePair::ValueCase::VALUE_NOT_SET: break; } } return hash; } }; } // namespace std
cmds/statsd/src/condition/SimpleConditionTracker.cpp +1 −1 Original line number Diff line number Diff line Loading @@ -279,7 +279,7 @@ void SimpleConditionTracker::evaluateCondition(const LogEvent& event, } // outputKey is the output key values. e.g, uid:1234 const HashableDimensionKey outputKey = getHashableKey(getDimensionKey(event, mOutputDimension)); const HashableDimensionKey outputKey(getDimensionKey(event, mOutputDimension)); handleConditionEvent(outputKey, matchedState == 1, conditionCache, conditionChangedCache); } Loading
cmds/statsd/src/condition/condition_util.cpp +1 −1 Original line number Diff line number Diff line Loading @@ -109,7 +109,7 @@ HashableDimensionKey getDimensionKeyForCondition(const LogEvent& event, kv.set_key(link.key_in_condition(i).key()); } return getHashableKey(dimensionKey); return HashableDimensionKey(dimensionKey); } } // namespace statsd Loading