Chromium Code Reviews| Index: base/metrics/field_trial.cc |
| diff --git a/base/metrics/field_trial.cc b/base/metrics/field_trial.cc |
| index b211326ac37c61e7c8130107a669fdbfc36d2b22..0ba4b02e95ff12a856abd94f7752c964357b2c1c 100644 |
| --- a/base/metrics/field_trial.cc |
| +++ b/base/metrics/field_trial.cc |
| @@ -1,4 +1,4 @@ |
| -// Copyright (c) 2011 The Chromium Authors. All rights reserved. |
| +// Copyright (c) 2012 The Chromium Authors. All rights reserved. |
| // Use of this source code is governed by a BSD-style license that can be |
| // found in the LICENSE file. |
| @@ -28,6 +28,22 @@ int FieldTrialList::kExpirationYearInFuture = 0; |
| //------------------------------------------------------------------------------ |
| // FieldTrial methods and members. |
| +FieldTrial* FieldTrial::CreateInstance( |
| + const std::string& name, Probability total_probability, |
| + const std::string& default_group_name, const int year, const int month, |
| + const int day_of_month) { |
| + // First check if the field trial has already been created in some other ways. |
|
Alexei Svitkine (slow)
2012/03/23 18:41:55
Nit: "some other ways" -> "some other way"
MAD
2012/03/23 20:20:12
Done.
|
| + FieldTrial* existing_trial = FieldTrialList::Find(name); |
| + if (existing_trial) { |
| + return existing_trial; |
| + } else { |
|
Alexei Svitkine (slow)
2012/03/23 18:41:55
Nit: Since you're early returning, don't need an e
MAD
2012/03/23 20:20:12
Done.
|
| + FieldTrial* new_trial = new FieldTrial( |
| + name, total_probability, default_group_name, year, month, day_of_month); |
| + FieldTrialList::Register(new_trial); |
| + return new_trial; |
| + } |
| +} |
| + |
| FieldTrial::FieldTrial(const std::string& name, |
| const Probability total_probability, |
| const std::string& default_group_name, |
| @@ -43,11 +59,11 @@ FieldTrial::FieldTrial(const std::string& name, |
| next_group_number_(kDefaultGroupNumber + 1), |
| group_(kNotFinalized), |
| group_name_hash_(kReservedHashValue), |
| - enable_field_trial_(true) { |
| + enable_field_trial_(true), |
| + forced_(false) { |
| DCHECK_GT(total_probability, 0); |
| DCHECK(!name_.empty()); |
| DCHECK(!default_group_name_.empty()); |
| - FieldTrialList::Register(this); |
| DCHECK_GT(year, 1970); |
| DCHECK_GT(month, 0); |
| @@ -71,6 +87,8 @@ FieldTrial::FieldTrial(const std::string& name, |
| } |
| void FieldTrial::UseOneTimeRandomization() { |
| + if (forced_) |
| + return; |
| DCHECK_EQ(group_, kNotFinalized); |
| DCHECK_EQ(kDefaultGroupNumber + 1, next_group_number_); |
| if (!FieldTrialList::IsOneTimeRandomizationEnabled()) { |
| @@ -97,6 +115,13 @@ void FieldTrial::Disable() { |
| int FieldTrial::AppendGroup(const std::string& name, |
| Probability group_probability) { |
| + if (forced_) { |
| + if (name == group_name_) |
| + return group_; |
| + else |
| + return group_ + 1; |
| + } |
| + |
| DCHECK_LE(group_probability, divisor_); |
| DCHECK_GE(group_probability, 0); |
| @@ -106,7 +131,7 @@ int FieldTrial::AppendGroup(const std::string& name, |
| accumulated_group_probability_ += group_probability; |
| DCHECK_LE(accumulated_group_probability_, divisor_); |
| - if (group_ == kNotFinalized && accumulated_group_probability_ > random_) { |
| + if (group_ == kNotFinalized && (accumulated_group_probability_ > random_)) { |
| // This is the group that crossed the random line, so we do the assignment. |
| group_ = next_group_number_; |
| if (name.empty()) |
| @@ -234,18 +259,6 @@ FieldTrialList::~FieldTrialList() { |
| } |
| // static |
| -void FieldTrialList::Register(FieldTrial* trial) { |
| - if (!global_) { |
| - used_without_global_ = true; |
| - return; |
| - } |
| - AutoLock auto_lock(global_->lock_); |
| - DCHECK(!global_->PreLockedFind(trial->name())); |
| - trial->AddRef(); |
| - global_->registered_[trial->name()] = trial; |
| -} |
| - |
| -// static |
| FieldTrial* FieldTrialList::Find(const std::string& name) { |
| if (!global_) |
| return NULL; |
| @@ -283,7 +296,7 @@ void FieldTrialList::StatesToString(std::string* output) { |
| for (RegistrationList::iterator it = global_->registered_.begin(); |
| it != global_->registered_.end(); ++it) { |
| - const std::string name = it->first; |
| + const std::string& name = it->first; |
| std::string group_name = it->second->group_name_internal(); |
| if (group_name.empty()) |
| continue; // Should not include uninitialized trials. |
| @@ -313,23 +326,22 @@ void FieldTrialList::GetFieldTrialNameGroupIds( |
| } |
| // static |
| -bool FieldTrialList::CreateTrialsInChildProcess( |
| - const std::string& parent_trials) { |
| +bool FieldTrialList::CreateTrialsFromString(const std::string& trials_string) { |
| DCHECK(global_); |
| - if (parent_trials.empty() || !global_) |
| + if (trials_string.empty() || !global_) |
| return true; |
| size_t next_item = 0; |
| - while (next_item < parent_trials.length()) { |
| - size_t name_end = parent_trials.find(kPersistentStringSeparator, next_item); |
| - if (name_end == parent_trials.npos || next_item == name_end) |
| + while (next_item < trials_string.length()) { |
| + size_t name_end = trials_string.find(kPersistentStringSeparator, next_item); |
| + if (name_end == trials_string.npos || next_item == name_end) |
| return false; |
| - size_t group_name_end = parent_trials.find(kPersistentStringSeparator, |
| + size_t group_name_end = trials_string.find(kPersistentStringSeparator, |
| name_end + 1); |
| - if (group_name_end == parent_trials.npos || name_end + 1 == group_name_end) |
| + if (group_name_end == trials_string.npos || name_end + 1 == group_name_end) |
| return false; |
| - std::string name(parent_trials, next_item, name_end - next_item); |
| - std::string group_name(parent_trials, name_end + 1, |
| + std::string name(trials_string, next_item, name_end - next_item); |
| + std::string group_name(trials_string, name_end + 1, |
| group_name_end - name_end - 1); |
| next_item = group_name_end + 1; |
| @@ -349,9 +361,10 @@ FieldTrial* FieldTrialList::CreateFieldTrial( |
| if (name.empty() || group_name.empty() || !global_) |
| return NULL; |
| - FieldTrial *field_trial(FieldTrialList::Find(name)); |
| + FieldTrial* field_trial(FieldTrialList::Find(name)); |
| if (field_trial) { |
| - // In single process mode, we may have already created the field trial. |
| + // In single process mode, or when we force them from the command line, |
| + // we may have already created the field trial. |
| if (field_trial->group_name_internal() != group_name) |
| return NULL; |
| return field_trial; |
| @@ -360,6 +373,8 @@ FieldTrial* FieldTrialList::CreateFieldTrial( |
| field_trial = new FieldTrial(name, kTotalProbability, group_name, |
| kExpirationYearInFuture, 1, 1); |
| field_trial->AppendGroup(group_name, kTotalProbability); |
| + field_trial->forced_ = true; |
| + FieldTrialList::Register(field_trial); |
| return field_trial; |
| } |
| @@ -425,4 +440,16 @@ FieldTrial* FieldTrialList::PreLockedFind(const std::string& name) { |
| return it->second; |
| } |
| +// static |
| +void FieldTrialList::Register(FieldTrial* trial) { |
| + if (!global_) { |
| + used_without_global_ = true; |
| + return; |
| + } |
| + AutoLock auto_lock(global_->lock_); |
| + DCHECK(!global_->PreLockedFind(trial->name())); |
| + trial->AddRef(); |
| + global_->registered_[trial->name()] = trial; |
| +} |
| + |
| } // namespace base |