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

Unified Diff: base/metrics/field_trial.cc

Issue 9705074: Supporting command line argument to force field trials (Closed) Base URL: http://git.chromium.org/chromium/src.git@master
Patch Set: Fixed some ooopss... Created 8 years, 8 months 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
« no previous file with comments | « base/metrics/field_trial.h ('k') | base/metrics/field_trial_unittest.cc » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: base/metrics/field_trial.cc
diff --git a/base/metrics/field_trial.cc b/base/metrics/field_trial.cc
index b211326ac37c61e7c8130107a669fdbfc36d2b22..28886f00ee7ea1ca42c2eebd23a2399ad55a0a22 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.
@@ -43,11 +43,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 +71,9 @@ FieldTrial::FieldTrial(const std::string& name,
}
void FieldTrial::UseOneTimeRandomization() {
+ // No need to specify randomization when the group choice was forced.
+ if (forced_)
+ return;
DCHECK_EQ(group_, kNotFinalized);
DCHECK_EQ(kDefaultGroupNumber + 1, next_group_number_);
if (!FieldTrialList::IsOneTimeRandomizationEnabled()) {
@@ -89,14 +92,29 @@ void FieldTrial::Disable() {
// In case we are disabled after initialization, we need to switch
// the trial to the default group.
if (group_ != kNotFinalized) {
- group_ = kDefaultGroupNumber;
- group_name_ = default_group_name_;
- group_name_hash_ = HashName(group_name_);
+ // Only reset when not already the default group, because in case we were
+ // forced to the default group, the group number may not be
+ // kDefaultGroupNumber, so we should keep it as is.
+ if (group_name_ != default_group_name_)
+ SetGroupChoice(default_group_name_, kDefaultGroupNumber);
}
}
int FieldTrial::AppendGroup(const std::string& name,
Probability group_probability) {
+ // When the group choice was previously forced, we only need to return the
+ // the id of the chosen group, and anything can be returned for the others.
+ if (forced_) {
+ DCHECK(!group_name_.empty());
+ if (name == group_name_) {
+ return group_;
+ }
+ DCHECK_NE(next_group_number_, group_);
+ // We still return different numbers each time, in case some caller need
+ // them to be different.
+ return next_group_number_++;
+ }
+
DCHECK_LE(group_probability, divisor_);
DCHECK_GE(group_probability, 0);
@@ -108,12 +126,7 @@ int FieldTrial::AppendGroup(const std::string& name,
DCHECK_LE(accumulated_group_probability_, divisor_);
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())
- StringAppendF(&group_name_, "%d", group_);
- else
- group_name_ = name;
- group_name_hash_ = HashName(group_name_);
+ SetGroupChoice(name, next_group_number_);
FieldTrialList::NotifyFieldTrialGroupSelection(name_, group_name_);
}
return next_group_number_++;
@@ -122,9 +135,10 @@ int FieldTrial::AppendGroup(const std::string& name,
int FieldTrial::group() {
if (group_ == kNotFinalized) {
accumulated_group_probability_ = divisor_;
- group_ = kDefaultGroupNumber;
- group_name_ = default_group_name_;
- group_name_hash_ = HashName(group_name_);
+ // Here it's OK to use kDefaultGroupNumber
+ // since we can't be forced and not finalized.
+ DCHECK(!forced_);
+ SetGroupChoice(default_group_name_, kDefaultGroupNumber);
FieldTrialList::NotifyFieldTrialGroupSelection(name_, group_name_);
}
return group_;
@@ -160,6 +174,15 @@ void FieldTrial::EnableBenchmarking() {
FieldTrial::~FieldTrial() {}
+void FieldTrial::SetGroupChoice(const std::string& name, int number) {
+ group_ = number;
+ if (name.empty())
+ StringAppendF(&group_name_, "%d", group_);
+ else
+ group_name_ = name;
+ group_name_hash_ = HashName(group_name_);
+}
+
// static
double FieldTrial::HashClientId(const std::string& client_id,
const std::string& trial_name) {
@@ -234,15 +257,33 @@ FieldTrialList::~FieldTrialList() {
}
// static
-void FieldTrialList::Register(FieldTrial* trial) {
- if (!global_) {
- used_without_global_ = true;
- return;
+FieldTrial* FieldTrialList::FactoryGetFieldTrial(
+ const std::string& name,
+ FieldTrial::Probability total_probability,
+ const std::string& default_group_name,
+ const int year,
+ const int month,
+ const int day_of_month,
+ int* default_group_number) {
+ if (default_group_number)
+ *default_group_number = FieldTrial::kDefaultGroupNumber;
+ // Check if the field trial has already been created in some other way.
+ FieldTrial* existing_trial = Find(name);
+ if (existing_trial) {
+ CHECK(existing_trial->forced_);
+ // If the field trial has already been forced, check whether it was forced
+ // to the default group. Return the chosen group number, in that case..
+ if (default_group_number &&
+ default_group_name == existing_trial->default_group_name()) {
+ *default_group_number = existing_trial->group();
+ }
+ return existing_trial;
}
- AutoLock auto_lock(global_->lock_);
- DCHECK(!global_->PreLockedFind(trial->name()));
- trial->AddRef();
- global_->registered_[trial->name()] = trial;
+
+ FieldTrial* field_trial = new FieldTrial(
+ name, total_probability, default_group_name, year, month, day_of_month);
+ FieldTrialList::Register(field_trial);
+ return field_trial;
}
// static
@@ -283,7 +324,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 +354,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 +389,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;
@@ -359,7 +400,11 @@ FieldTrial* FieldTrialList::CreateFieldTrial(
const int kTotalProbability = 100;
field_trial = new FieldTrial(name, kTotalProbability, group_name,
kExpirationYearInFuture, 1, 1);
+ // This is where we may assign a group number different from
+ // kDefaultGroupNumber to the default group.
field_trial->AppendGroup(group_name, kTotalProbability);
+ field_trial->forced_ = true;
+ FieldTrialList::Register(field_trial);
return field_trial;
}
@@ -425,4 +470,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
« no previous file with comments | « base/metrics/field_trial.h ('k') | base/metrics/field_trial_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698