Index: base/metrics/field_trial.cc |
=================================================================== |
--- base/metrics/field_trial.cc (revision 71810) |
+++ base/metrics/field_trial.cc (working copy) |
@@ -7,14 +7,15 @@ |
#include "base/logging.h" |
#include "base/rand_util.h" |
#include "base/stringprintf.h" |
+#include "base/utf_string_conversions.h" |
namespace base { |
// static |
-const int FieldTrial::kNotParticipating = -1; |
+const int FieldTrial::kNotFinalized = -1; |
// static |
-const int FieldTrial::kAllRemainingProbability = -2; |
+const int FieldTrial::kDefaultGroupNumber = 0; |
// static |
bool FieldTrial::enable_benchmarking_ = false; |
@@ -28,30 +29,53 @@ |
// FieldTrial methods and members. |
FieldTrial::FieldTrial(const std::string& name, |
- const Probability total_probability) |
+ const Probability total_probability, |
+ const std::string& default_group_name, |
+ const int year, |
+ const int month, |
+ const int day_of_month) |
: name_(name), |
divisor_(total_probability), |
+ default_group_name_(default_group_name), |
random_(static_cast<Probability>(divisor_ * base::RandDouble())), |
accumulated_group_probability_(0), |
- next_group_number_(0), |
- group_(kNotParticipating) { |
+ next_group_number_(kDefaultGroupNumber+1), |
+ group_(kNotFinalized) { |
+ DCHECK(!default_group_name_.empty()); |
FieldTrialList::Register(this); |
+ |
+ DCHECK_GT(year, 1970); |
+ DCHECK_GT(month, 0); |
+ DCHECK_LT(month, 13); |
+ DCHECK_GT(day_of_month, 0); |
+ DCHECK_LT(day_of_month, 32); |
+ |
+ base::Time::Exploded exploded; |
+ exploded.year = year; |
+ exploded.month = month; |
+ exploded.day_of_week = 0; // Should be unusued. |
+ exploded.day_of_month = day_of_month; |
+ exploded.hour = 0; |
+ exploded.minute = 0; |
+ exploded.second = 0; |
+ exploded.millisecond = 0; |
+ |
+ base::Time expiration_time = Time::FromLocalExploded(exploded); |
+ disable_field_trial_ = (GetBuildTime() > expiration_time) ? true : false; |
} |
int FieldTrial::AppendGroup(const std::string& name, |
Probability group_probability) { |
DCHECK(group_probability <= divisor_); |
- DCHECK(group_probability >=0 || |
- group_probability == kAllRemainingProbability); |
- if (group_probability == kAllRemainingProbability) { |
- accumulated_group_probability_ = divisor_; |
- } else { |
- if (enable_benchmarking_) |
- group_probability = 0; |
- accumulated_group_probability_ += group_probability; |
- } |
+ DCHECK_GE(group_probability, 0); |
+ |
+ if (enable_benchmarking_ || disable_field_trial_) |
+ group_probability = 0; |
+ |
+ accumulated_group_probability_ += group_probability; |
+ |
DCHECK(accumulated_group_probability_ <= divisor_); |
- if (group_ == kNotParticipating && 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()) |
@@ -62,6 +86,20 @@ |
return next_group_number_++; |
} |
+int FieldTrial::group() { |
+ if (group_ == kNotFinalized) { |
+ accumulated_group_probability_ = divisor_; |
+ group_ = kDefaultGroupNumber; |
+ group_name_ = default_group_name_; |
+ } |
+ return group_; |
+} |
+ |
+std::string FieldTrial::group_name() { |
+ group(); // call group() to make group assignment was done. |
+ return group_name_; |
+} |
+ |
// static |
std::string FieldTrial::MakeName(const std::string& name_prefix, |
const std::string& trial_name) { |
@@ -76,6 +114,16 @@ |
enable_benchmarking_ = true; |
} |
+// static |
+Time FieldTrial::GetBuildTime() { |
+ Time integral_build_time; |
+ const char* kDateTime = __DATE__ " " __TIME__; |
+ bool result = Time::FromString(ASCIIToWide(kDateTime).c_str(), |
+ &integral_build_time); |
+ DCHECK(result); |
+ return integral_build_time; |
+} |
+ |
FieldTrial::~FieldTrial() {} |
//------------------------------------------------------------------------------ |
@@ -129,7 +177,7 @@ |
FieldTrial* field_trial = Find(name); |
if (field_trial) |
return field_trial->group(); |
- return FieldTrial::kNotParticipating; |
+ return FieldTrial::kNotFinalized; |
} |
// static |
@@ -149,9 +197,11 @@ |
for (RegistrationList::iterator it = global_->registered_.begin(); |
it != global_->registered_.end(); ++it) { |
const std::string name = it->first; |
- const std::string group_name = it->second->group_name(); |
+ std::string group_name = it->second->group_name_internal(); |
if (group_name.empty()) |
- continue; // No definitive winner in this trial. |
+ // No definitive winner in this trial, use default_group_name as the |
+ // group_name. |
+ group_name = it->second->default_group_name(); |
DCHECK_EQ(name.find(kPersistentStringSeparator), std::string::npos); |
DCHECK_EQ(group_name.find(kPersistentStringSeparator), std::string::npos); |
output->append(name); |
@@ -162,34 +212,43 @@ |
} |
// static |
-bool FieldTrialList::StringAugmentsState(const std::string& prior_state) { |
+bool FieldTrialList::CreateTrialsInChildProcess( |
+ const std::string& parent_trials) { |
DCHECK(global_); |
- if (prior_state.empty() || !global_) |
+ if (parent_trials.empty() || !global_) |
return true; |
+ Time::Exploded exploded; |
+ Time two_years_from_now = |
+ Time::NowFromSystemTime() + TimeDelta::FromDays(730); |
+ two_years_from_now.LocalExplode(&exploded); |
+ const int kTwoYearsFromNow = exploded.year; |
+ |
size_t next_item = 0; |
- while (next_item < prior_state.length()) { |
- size_t name_end = prior_state.find(kPersistentStringSeparator, next_item); |
- if (name_end == prior_state.npos || next_item == name_end) |
+ 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) |
return false; |
- size_t group_name_end = prior_state.find(kPersistentStringSeparator, |
- name_end + 1); |
- if (group_name_end == prior_state.npos || name_end + 1 == group_name_end) |
+ size_t group_name_end = parent_trials.find(kPersistentStringSeparator, |
+ name_end + 1); |
+ if (group_name_end == parent_trials.npos || name_end + 1 == group_name_end) |
return false; |
- std::string name(prior_state, next_item, name_end - next_item); |
- std::string group_name(prior_state, name_end + 1, |
+ std::string name(parent_trials, next_item, name_end - next_item); |
+ std::string group_name(parent_trials, name_end + 1, |
group_name_end - name_end - 1); |
next_item = group_name_end + 1; |
FieldTrial *field_trial(FieldTrialList::Find(name)); |
if (field_trial) { |
// In single process mode, we may have already created the field trial. |
- if (field_trial->group_name() != group_name) |
+ if ((field_trial->group_name_internal() != group_name) && |
+ (field_trial->default_group_name() != group_name)) |
return false; |
continue; |
} |
const int kTotalProbability = 100; |
- field_trial = new FieldTrial(name, kTotalProbability); |
+ field_trial = new FieldTrial(name, kTotalProbability, group_name, |
+ kTwoYearsFromNow, 1, 1); |
field_trial->AppendGroup(group_name, kTotalProbability); |
} |
return true; |