| OLD | NEW |
| 1 // Copyright (c) 2006-2008 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2006-2008 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 | 5 |
| 6 #include "base/field_trial.h" | 6 #include "base/field_trial.h" |
| 7 #include "base/logging.h" | 7 #include "base/logging.h" |
| 8 #include "base/rand_util.h" | 8 #include "base/rand_util.h" |
| 9 #include "base/string_util.h" | 9 #include "base/string_util.h" |
| 10 | 10 |
| 11 using base::Time; | 11 using base::Time; |
| 12 | 12 |
| 13 // static | 13 // static |
| 14 const int FieldTrial::kNotParticipating = -1; | 14 const int FieldTrial::kNotParticipating = -1; |
| 15 | 15 |
| 16 // static | 16 // static |
| 17 const char FieldTrial::kPersistentStringSeparator('/'); | 17 const int FieldTrial::kAllRemainingProbability = -2; |
| 18 |
| 19 // static |
| 20 const char FieldTrialList::kPersistentStringSeparator('/'); |
| 18 | 21 |
| 19 //------------------------------------------------------------------------------ | 22 //------------------------------------------------------------------------------ |
| 20 // FieldTrial methods and members. | 23 // FieldTrial methods and members. |
| 21 | 24 |
| 22 FieldTrial::FieldTrial(const std::string& name, | 25 FieldTrial::FieldTrial(const std::string& name, |
| 23 const Probability total_probability) | 26 const Probability total_probability) |
| 24 : name_(name), | 27 : name_(name), |
| 25 divisor_(total_probability), | 28 divisor_(total_probability), |
| 26 random_(static_cast<Probability>(divisor_ * base::RandDouble())), | 29 random_(static_cast<Probability>(divisor_ * base::RandDouble())), |
| 27 accumulated_group_probability_(0), | 30 accumulated_group_probability_(0), |
| (...skipping 18 matching lines...) Expand all Loading... |
| 46 return next_group_number_++; | 49 return next_group_number_++; |
| 47 } | 50 } |
| 48 | 51 |
| 49 // static | 52 // static |
| 50 std::string FieldTrial::MakeName(const std::string& name_prefix, | 53 std::string FieldTrial::MakeName(const std::string& name_prefix, |
| 51 const std::string& trial_name) { | 54 const std::string& trial_name) { |
| 52 std::string big_string(name_prefix); | 55 std::string big_string(name_prefix); |
| 53 return big_string.append(FieldTrialList::FindFullName(trial_name)); | 56 return big_string.append(FieldTrialList::FindFullName(trial_name)); |
| 54 } | 57 } |
| 55 | 58 |
| 56 std::string FieldTrial::MakePersistentString() const { | |
| 57 DCHECK_EQ(name_.find(kPersistentStringSeparator), std::string::npos); | |
| 58 DCHECK_EQ(group_name_.find(kPersistentStringSeparator), std::string::npos); | |
| 59 | |
| 60 std::string persistent(name_); | |
| 61 persistent = persistent.append(1, kPersistentStringSeparator); | |
| 62 persistent = persistent.append(group_name_); | |
| 63 return persistent; | |
| 64 } | |
| 65 | |
| 66 // static | |
| 67 FieldTrial* FieldTrial::RestorePersistentString(const std::string &persistent) { | |
| 68 size_t split_point = persistent.find(kPersistentStringSeparator); | |
| 69 if (std::string::npos == split_point) | |
| 70 return NULL; // Bogus string. | |
| 71 std::string new_name(persistent, 0, split_point); | |
| 72 std::string new_group_name(persistent, split_point + 1); | |
| 73 if (new_name.empty() || new_group_name.empty()) | |
| 74 return NULL; // Incomplete string. | |
| 75 | |
| 76 FieldTrial *field_trial; | |
| 77 field_trial = FieldTrialList::Find(new_name); | |
| 78 if (field_trial) { | |
| 79 // In single process mode, we may have already created the field trial. | |
| 80 if (field_trial->group_name_ != new_group_name) | |
| 81 return NULL; // Conflicting group name :-(. | |
| 82 } else { | |
| 83 const int kTotalProbability = 100; | |
| 84 field_trial = new FieldTrial(new_name, kTotalProbability); | |
| 85 field_trial->AppendGroup(new_group_name, kTotalProbability); | |
| 86 } | |
| 87 return field_trial; | |
| 88 } | |
| 89 | |
| 90 //------------------------------------------------------------------------------ | 59 //------------------------------------------------------------------------------ |
| 91 // FieldTrialList methods and members. | 60 // FieldTrialList methods and members. |
| 92 | 61 |
| 93 // static | 62 // static |
| 94 FieldTrialList* FieldTrialList::global_ = NULL; | 63 FieldTrialList* FieldTrialList::global_ = NULL; |
| 95 | 64 |
| 96 FieldTrialList::FieldTrialList() | 65 FieldTrialList::FieldTrialList() |
| 97 : application_start_time_(Time::Now()) { | 66 : application_start_time_(Time::Now()) { |
| 98 DCHECK(!global_); | 67 DCHECK(!global_); |
| 99 global_ = this; | 68 global_ = this; |
| (...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 144 AutoLock auto_lock(global_->lock_); | 113 AutoLock auto_lock(global_->lock_); |
| 145 return global_->PreLockedFind(name); | 114 return global_->PreLockedFind(name); |
| 146 } | 115 } |
| 147 | 116 |
| 148 FieldTrial* FieldTrialList::PreLockedFind(const std::string& name) { | 117 FieldTrial* FieldTrialList::PreLockedFind(const std::string& name) { |
| 149 RegistrationList::iterator it = registered_.find(name); | 118 RegistrationList::iterator it = registered_.find(name); |
| 150 if (registered_.end() == it) | 119 if (registered_.end() == it) |
| 151 return NULL; | 120 return NULL; |
| 152 return it->second; | 121 return it->second; |
| 153 } | 122 } |
| 123 |
| 124 // static |
| 125 void FieldTrialList::StatesToString(std::string* output) { |
| 126 if (!global_) |
| 127 return; |
| 128 DCHECK(output->empty()); |
| 129 for (RegistrationList::iterator it = global_->registered_.begin(); |
| 130 it != global_->registered_.end(); ++it) { |
| 131 const std::string name = it->first; |
| 132 const std::string group_name = it->second->group_name(); |
| 133 if (group_name.empty()) |
| 134 continue; // No definitive winner in this trial. |
| 135 DCHECK_EQ(name.find(kPersistentStringSeparator), std::string::npos); |
| 136 DCHECK_EQ(group_name.find(kPersistentStringSeparator), std::string::npos); |
| 137 output->append(name); |
| 138 output->append(1, kPersistentStringSeparator); |
| 139 output->append(group_name); |
| 140 output->append(1, kPersistentStringSeparator); |
| 141 } |
| 142 } |
| 143 |
| 144 // static |
| 145 bool FieldTrialList::StringAugmentsState(const std::string& prior_state) { |
| 146 DCHECK(global_); |
| 147 if (prior_state.empty() || !global_) |
| 148 return true; |
| 149 |
| 150 size_t next_item = 0; |
| 151 while (next_item < prior_state.length()) { |
| 152 size_t name_end = prior_state.find(kPersistentStringSeparator, next_item); |
| 153 if (name_end == prior_state.npos || next_item == name_end) |
| 154 return false; |
| 155 size_t group_name_end = prior_state.find(kPersistentStringSeparator, |
| 156 name_end + 1); |
| 157 if (group_name_end == prior_state.npos || name_end + 1 == group_name_end) |
| 158 return false; |
| 159 std::string name(prior_state, next_item, name_end - next_item); |
| 160 std::string group_name(prior_state, name_end + 1, |
| 161 group_name_end - name_end - 1); |
| 162 next_item = group_name_end + 1; |
| 163 |
| 164 FieldTrial *field_trial(FieldTrialList::Find(name)); |
| 165 if (field_trial) { |
| 166 // In single process mode, we may have already created the field trial. |
| 167 if (field_trial->group_name() != group_name) |
| 168 return false; |
| 169 continue; |
| 170 } |
| 171 const int kTotalProbability = 100; |
| 172 field_trial = new FieldTrial(name, kTotalProbability); |
| 173 field_trial->AppendGroup(group_name, kTotalProbability); |
| 174 } |
| 175 return true; |
| 176 } |
| 177 |
| OLD | NEW |