Chromium Code Reviews| Index: base/metrics/field_trial.cc |
| diff --git a/base/metrics/field_trial.cc b/base/metrics/field_trial.cc |
| index 63f549e5729d69b3587de96dbef7ad61764bac26..583a0aed9278ce5bed3457cb296b7f953f341685 100644 |
| --- a/base/metrics/field_trial.cc |
| +++ b/base/metrics/field_trial.cc |
| @@ -46,33 +46,61 @@ const uint32_t kFieldTrialType = 0xABA17E13 + 1; // SHA1(FieldTrialEntry) v1 |
| #if !defined(OS_NACL) |
| const size_t kFieldTrialAllocationSize = 4 << 10; // 4 KiB = one page |
| #endif |
| +const int kFieldTrialParamLimit = 1000; |
| // We create one FieldTrialEntry per field trial in shared memory, via |
| // AddToAllocatorWhileLocked. The FieldTrialEntry is followed by a base::Pickle |
| // object that we unpickle and read from. |
| struct FieldTrialEntry { |
| + // Whether or not this field trial is activated. |
| bool activated; |
| // Size of the pickled structure, NOT the total size of this entry. |
| uint32_t size; |
| - // Calling this is only valid when the entry is initialized. That is, it |
| - // resides in shared memory and has a pickle containing the trial name and |
| - // group name following it. |
| - bool GetTrialAndGroupName(StringPiece* trial_name, |
| - StringPiece* group_name) const { |
| + // Returns an iterator over the data used for getting names and params. |
| + PickleIterator GetPickleIterator() const { |
| char* src = reinterpret_cast<char*>(const_cast<FieldTrialEntry*>(this)) + |
| sizeof(FieldTrialEntry); |
| Pickle pickle(src, size); |
| - PickleIterator pickle_iter(pickle); |
| + return PickleIterator(pickle); |
| + } |
| - if (!pickle_iter.ReadStringPiece(trial_name)) |
| + // Calling this is only valid when the entry is initialized. That is, it |
| + // resides in shared memory and has a pickle containing the trial name and |
| + // group name following it. |
| + bool GetTrialAndGroupName(StringPiece* trial_name, |
| + StringPiece* group_name) const { |
| + PickleIterator iter = GetPickleIterator(); |
| + if (!iter.ReadStringPiece(trial_name)) |
| return false; |
| - if (!pickle_iter.ReadStringPiece(group_name)) |
| + if (!iter.ReadStringPiece(group_name)) |
| return false; |
| return true; |
| } |
| + |
| + bool GetParams(FieldTrialParamAssociator::FieldTrialParams* params) const { |
| + PickleIterator iter = GetPickleIterator(); |
| + StringPiece tmp; |
| + if (!iter.ReadStringPiece(&tmp)) |
| + return false; |
| + if (!iter.ReadStringPiece(&tmp)) |
| + return false; |
|
Alexei Svitkine (slow)
2016/11/01 19:13:27
Can you refactor the code to re-use the GetTrialAn
lawrencewu
2016/11/01 19:59:58
Done.
|
| + |
| + for (int i = 0; i < kFieldTrialParamLimit; ++i) { |
|
Alexei Svitkine (slow)
2016/11/01 19:13:27
Instead of having an arbitrary limit, I suggest ju
lawrencewu
2016/11/01 19:59:58
Done.
|
| + StringPiece key; |
| + StringPiece value; |
| + if (!iter.ReadStringPiece(&key)) |
| + return true; // No more params to read. |
| + if (!iter.ReadStringPiece(&value)) |
| + return false; |
| + (*params)[key.as_string()] = value.as_string(); |
| + } |
| + |
| + NOTREACHED() << "Hit field trial param limit"; |
| + return false; |
| + } |
| }; |
| // Created a time value based on |year|, |month| and |day_of_month| parameters. |
| @@ -181,6 +209,25 @@ HANDLE CreateReadOnlyHandle(SharedPersistentMemoryAllocator* allocator) { |
| } |
| #endif |
| +bool PickleFieldTrialState(const FieldTrial::State& trial_state, |
| + Pickle* pickle) { |
| + pickle->WriteString(trial_state.trial_name); |
| + pickle->WriteString(trial_state.group_name); |
| + |
| + std::map<std::string, std::string> params; |
| + if (!FieldTrialParamAssociator::GetInstance()->GetFieldTrialParams( |
| + trial_state.trial_name.as_string(), |
| + trial_state.group_name.as_string(), ¶ms)) { |
| + return false; |
| + } |
| + |
| + for (const auto& param : params) { |
| + pickle->WriteString(StringPiece(param.first)); |
| + pickle->WriteString(StringPiece(param.second)); |
| + } |
| + return true; |
| +} |
| + |
| } // namespace |
| // statics |
| @@ -527,6 +574,24 @@ std::string FieldTrialList::FindFullName(const std::string& trial_name) { |
| } |
| // static |
| +bool FieldTrialList::FindParams( |
| + const std::string& trial_name, |
| + FieldTrialParamAssociator::FieldTrialParams* params) { |
| + SharedPersistentMemoryAllocator* allocator = |
| + global_->field_trial_allocator_.get(); |
| + if (allocator == nullptr) |
| + return false; |
| + |
| + FieldTrial* field_trial = Find(trial_name); |
| + if (field_trial->ref_ == SharedPersistentMemoryAllocator::kReferenceNull) |
|
Alexei Svitkine (slow)
2016/11/01 19:13:27
Please add comments above the early returns that e
lawrencewu
2016/11/01 19:59:58
Done.
|
| + return false; |
| + |
| + FieldTrialEntry* entry = allocator->GetAsObject<FieldTrialEntry>( |
| + field_trial->ref_, kFieldTrialType); |
| + return entry->GetParams(params); |
| +} |
| + |
| +// static |
| bool FieldTrialList::TrialExists(const std::string& trial_name) { |
| return Find(trial_name) != NULL; |
| } |
| @@ -904,8 +969,8 @@ void FieldTrialList::AddToAllocatorWhileLocked(FieldTrial* field_trial) { |
| return; |
| Pickle pickle; |
| - pickle.WriteString(trial_state.trial_name); |
| - pickle.WriteString(trial_state.group_name); |
| + if (!PickleFieldTrialState(trial_state, &pickle)) |
| + return; |
| size_t total_size = sizeof(FieldTrialEntry) + pickle.size(); |
| SharedPersistentMemoryAllocator::Reference ref = |