Home | History | Annotate | Download | only in src
      1 /*
      2  * Copyright (C) 2017 The Android Open Source Project
      3  *
      4  * Licensed under the Apache License, Version 2.0 (the "License");
      5  * you may not use this file except in compliance with the License.
      6  * You may obtain a copy of the License at
      7  *
      8  *      http://www.apache.org/licenses/LICENSE-2.0
      9  *
     10  * Unless required by applicable law or agreed to in writing, software
     11  * distributed under the License is distributed on an "AS IS" BASIS,
     12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     13  * See the License for the specific language governing permissions and
     14  * limitations under the License.
     15  */
     16 #define DEBUG false  // STOPSHIP if true
     17 #include "Log.h"
     18 
     19 #include <mutex>
     20 
     21 #include "HashableDimensionKey.h"
     22 #include "FieldValue.h"
     23 
     24 namespace android {
     25 namespace os {
     26 namespace statsd {
     27 
     28 using std::string;
     29 using std::vector;
     30 
     31 android::hash_t hashDimension(const HashableDimensionKey& value) {
     32     android::hash_t hash = 0;
     33     for (const auto& fieldValue : value.getValues()) {
     34         hash = android::JenkinsHashMix(hash, android::hash_type((int)fieldValue.mField.getField()));
     35         hash = android::JenkinsHashMix(hash, android::hash_type((int)fieldValue.mField.getTag()));
     36         hash = android::JenkinsHashMix(hash, android::hash_type((int)fieldValue.mValue.getType()));
     37         switch (fieldValue.mValue.getType()) {
     38             case INT:
     39                 hash = android::JenkinsHashMix(hash,
     40                                                android::hash_type(fieldValue.mValue.int_value));
     41                 break;
     42             case LONG:
     43                 hash = android::JenkinsHashMix(hash,
     44                                                android::hash_type(fieldValue.mValue.long_value));
     45                 break;
     46             case STRING:
     47                 hash = android::JenkinsHashMix(hash, static_cast<uint32_t>(std::hash<std::string>()(
     48                                                              fieldValue.mValue.str_value)));
     49                 break;
     50             case FLOAT: {
     51                 hash = android::JenkinsHashMix(hash,
     52                                                android::hash_type(fieldValue.mValue.float_value));
     53                 break;
     54             }
     55             default:
     56                 break;
     57         }
     58     }
     59     return JenkinsHashWhiten(hash);
     60 }
     61 
     62 bool filterValues(const vector<Matcher>& matcherFields, const vector<FieldValue>& values,
     63                   HashableDimensionKey* output) {
     64     size_t num_matches = 0;
     65     for (const auto& value : values) {
     66         for (size_t i = 0; i < matcherFields.size(); ++i) {
     67             const auto& matcher = matcherFields[i];
     68             if (value.mField.matches(matcher)) {
     69                 output->addValue(value);
     70                 output->mutableValue(num_matches)->mField.setTag(value.mField.getTag());
     71                 output->mutableValue(num_matches)->mField.setField(
     72                     value.mField.getField() & matcher.mMask);
     73                 num_matches++;
     74             }
     75         }
     76     }
     77     return num_matches > 0;
     78 }
     79 
     80 void filterGaugeValues(const std::vector<Matcher>& matcherFields,
     81                        const std::vector<FieldValue>& values, std::vector<FieldValue>* output) {
     82     for (const auto& field : matcherFields) {
     83         for (const auto& value : values) {
     84             if (value.mField.matches(field)) {
     85                 output->push_back(value);
     86             }
     87         }
     88     }
     89 }
     90 
     91 void getDimensionForCondition(const std::vector<FieldValue>& eventValues,
     92                               const Metric2Condition& links,
     93                               HashableDimensionKey* conditionDimension) {
     94     // Get the dimension first by using dimension from what.
     95     filterValues(links.metricFields, eventValues, conditionDimension);
     96 
     97     size_t count = conditionDimension->getValues().size();
     98     if (count != links.conditionFields.size()) {
     99         // ALOGE("WTF condition link is bad");
    100         return;
    101     }
    102 
    103     for (size_t i = 0; i < count; i++) {
    104         conditionDimension->mutableValue(i)->mField.setField(
    105             links.conditionFields[i].mMatcher.getField());
    106         conditionDimension->mutableValue(i)->mField.setTag(
    107             links.conditionFields[i].mMatcher.getTag());
    108     }
    109 }
    110 
    111 bool LessThan(const vector<FieldValue>& s1, const vector<FieldValue>& s2) {
    112     if (s1.size() != s2.size()) {
    113         return s1.size() < s2.size();
    114     }
    115 
    116     size_t count = s1.size();
    117     for (size_t i = 0; i < count; i++) {
    118         if (s1[i] != s2[i]) {
    119             return s1[i] < s2[i];
    120         }
    121     }
    122     return false;
    123 }
    124 
    125 bool HashableDimensionKey::operator==(const HashableDimensionKey& that) const {
    126     if (mValues.size() != that.getValues().size()) {
    127         return false;
    128     }
    129     size_t count = mValues.size();
    130     for (size_t i = 0; i < count; i++) {
    131         if (mValues[i] != (that.getValues())[i]) {
    132             return false;
    133         }
    134     }
    135     return true;
    136 };
    137 
    138 bool HashableDimensionKey::operator<(const HashableDimensionKey& that) const {
    139     return LessThan(getValues(), that.getValues());
    140 };
    141 
    142 bool HashableDimensionKey::contains(const HashableDimensionKey& that) const {
    143     if (mValues.size() < that.getValues().size()) {
    144         return false;
    145     }
    146 
    147     if (mValues.size() == that.getValues().size()) {
    148         return (*this) == that;
    149     }
    150 
    151     for (const auto& value : that.getValues()) {
    152         bool found = false;
    153         for (const auto& myValue : mValues) {
    154             if (value.mField == myValue.mField && value.mValue == myValue.mValue) {
    155                 found = true;
    156                 break;
    157             }
    158         }
    159         if (!found) {
    160             return false;
    161         }
    162     }
    163 
    164     return true;
    165 }
    166 
    167 string HashableDimensionKey::toString() const {
    168     std::string output;
    169     for (const auto& value : mValues) {
    170         output += StringPrintf("(%d)%#x->%s ", value.mField.getTag(), value.mField.getField(),
    171                                value.mValue.toString().c_str());
    172     }
    173     return output;
    174 }
    175 
    176 bool MetricDimensionKey::operator==(const MetricDimensionKey& that) const {
    177     return mDimensionKeyInWhat == that.getDimensionKeyInWhat() &&
    178            mDimensionKeyInCondition == that.getDimensionKeyInCondition();
    179 };
    180 
    181 string MetricDimensionKey::toString() const {
    182     return mDimensionKeyInWhat.toString() + mDimensionKeyInCondition.toString();
    183 }
    184 
    185 bool MetricDimensionKey::operator<(const MetricDimensionKey& that) const {
    186     if (mDimensionKeyInWhat < that.getDimensionKeyInWhat()) {
    187         return true;
    188     } else if (that.getDimensionKeyInWhat() < mDimensionKeyInWhat) {
    189         return false;
    190     }
    191 
    192     return mDimensionKeyInCondition < that.getDimensionKeyInCondition();
    193 }
    194 
    195 }  // namespace statsd
    196 }  // namespace os
    197 }  // namespace android
    198