Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(168)

Unified Diff: base/metrics/field_trial.cc

Issue 2463223002: Store field trial parameters in shared memory (Closed)
Patch Set: address comments Created 4 years, 1 month ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
Index: base/metrics/field_trial.cc
diff --git a/base/metrics/field_trial.cc b/base/metrics/field_trial.cc
index 4b83451e12b534914cd02399e64cddc267348b3a..fcfd50d139bd7f744284cad1123d761a5d768b2f 100644
--- a/base/metrics/field_trial.cc
+++ b/base/metrics/field_trial.cc
@@ -51,28 +51,61 @@ const size_t kFieldTrialAllocationSize = 4 << 10; // 4 KiB = one page
// 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))
+ // Takes the iterator and writes out the first two items into |trial_name| and
+ // |group_name|.
+ bool ReadStringPair(PickleIterator iter,
+ StringPiece* trial_name,
+ StringPiece* group_name) const {
+ if (!iter.ReadStringPiece(trial_name))
return false;
- if (!pickle_iter.ReadStringPiece(group_name))
+ if (!iter.ReadStringPiece(group_name))
return false;
return true;
}
+
+ // 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();
+ return ReadStringPair(iter, trial_name, group_name);
+ }
+
+ bool GetParams(FieldTrialParamAssociator::FieldTrialParams* params) const {
+ PickleIterator iter = GetPickleIterator();
+ StringPiece tmp;
+ if (!ReadStringPair(iter, &tmp, &tmp))
+ return false;
+
+ while (true) {
+ 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 +214,26 @@ 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()
+ ->GetFieldTrialParamsWithGroupName(
+ trial_state.trial_name.as_string(),
+ trial_state.group_name.as_string(), &params)) {
+ return false;
+ }
+
+ for (const auto& param : params) {
+ pickle->WriteString(StringPiece(param.first));
+ pickle->WriteString(StringPiece(param.second));
+ }
+ return true;
+}
+
} // namespace
// statics
@@ -527,6 +580,30 @@ std::string FieldTrialList::FindFullName(const std::string& trial_name) {
}
// static
+bool FieldTrialList::FindParams(
+ const std::string& trial_name,
+ FieldTrialParamAssociator::FieldTrialParams* params) {
+ // Check that the allocator exists (it may not exist on Linux or macOS). This
+ // shouldn't ever happen on Windows, as child processes should get an
+ // allocator during initialization, and browser processes won't hit this
+ // function since it has the mapping in FieldTrialParamAssociator.
+ SharedPersistentMemoryAllocator* allocator =
+ global_->field_trial_allocator_.get();
+ if (allocator == nullptr)
+ return false;
+
+ // Get the field trial's corresponding reference in shared memory. This
+ // shouldn't happen for on Windows the same reasons above.
+ FieldTrial* field_trial = Find(trial_name);
+ if (field_trial->ref_ == SharedPersistentMemoryAllocator::kReferenceNull)
+ 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;
}
@@ -823,15 +900,17 @@ size_t FieldTrialList::GetFieldTrialCount() {
// static
void FieldTrialList::CreateTrialsFromSharedMemory(
std::unique_ptr<SharedMemory> shm) {
- const SharedPersistentMemoryAllocator shalloc(std::move(shm), 0,
- kAllocatorName, true);
- PersistentMemoryAllocator::Iterator mem_iter(&shalloc);
+ global_->field_trial_allocator_.reset(new SharedPersistentMemoryAllocator(
+ std::move(shm), 0, kAllocatorName, true));
+ SharedPersistentMemoryAllocator* shalloc =
+ global_->field_trial_allocator_.get();
+ PersistentMemoryAllocator::Iterator mem_iter(shalloc);
SharedPersistentMemoryAllocator::Reference ref;
while ((ref = mem_iter.GetNextOfType(kFieldTrialType)) !=
SharedPersistentMemoryAllocator::kReferenceNull) {
const FieldTrialEntry* entry =
- shalloc.GetAsObject<const FieldTrialEntry>(ref, kFieldTrialType);
+ shalloc->GetAsObject<const FieldTrialEntry>(ref, kFieldTrialType);
StringPiece trial_name;
StringPiece group_name;
@@ -904,8 +983,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 =

Powered by Google App Engine
This is Rietveld 408576698