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

Side by Side Diff: base/feature_list.cc

Issue 2546653002: Store and retrieve features from shared memory (Closed)
Patch Set: Address comments and fallback to command line. Created 4 years 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 unified diff | Download patch
« no previous file with comments | « base/feature_list.h ('k') | base/metrics/field_trial.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright 2015 The Chromium Authors. All rights reserved. 1 // Copyright 2015 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 #include "base/feature_list.h" 5 #include "base/feature_list.h"
6 6
7 #include <stddef.h> 7 #include <stddef.h>
8 8
9 #include <utility> 9 #include <utility>
10 #include <vector> 10 #include <vector>
11 11
12 #include "base/logging.h" 12 #include "base/logging.h"
13 #include "base/memory/ptr_util.h" 13 #include "base/memory/ptr_util.h"
14 #include "base/metrics/field_trial.h" 14 #include "base/metrics/field_trial.h"
15 #include "base/pickle.h"
15 #include "base/strings/string_split.h" 16 #include "base/strings/string_split.h"
16 #include "base/strings/string_util.h" 17 #include "base/strings/string_util.h"
17 18
18 namespace base { 19 namespace base {
19 20
20 namespace { 21 namespace {
21 22
22 // Pointer to the FeatureList instance singleton that was set via 23 // Pointer to the FeatureList instance singleton that was set via
23 // FeatureList::SetInstance(). Does not use base/memory/singleton.h in order to 24 // FeatureList::SetInstance(). Does not use base/memory/singleton.h in order to
24 // have more control over initialization timing. Leaky. 25 // have more control over initialization timing. Leaky.
25 FeatureList* g_instance = nullptr; 26 FeatureList* g_instance = nullptr;
26 27
27 // Tracks whether the FeatureList instance was initialized via an accessor. 28 // Tracks whether the FeatureList instance was initialized via an accessor.
28 bool g_initialized_from_accessor = false; 29 bool g_initialized_from_accessor = false;
29 30
31 const uint32_t kFeatureType = 0x06567CA6 + 1; // SHA1(FeatureEntry) v1
32
33 struct FeatureEntry {
lawrencewu 2016/12/01 18:50:38 Write a docstring for this struct.
lawrencewu 2016/12/01 19:30:55 Done.
34 // Expected size for 32/64-bit check.
35 static constexpr size_t kExpectedInstanceSize = 8;
36
37 // Specifies whether a feature override enables or disables the future. Same
38 // values as the OverrideState enum in feature_list.h
39 uint32_t override_state;
40
41 // Size of the pickled structure, NOT the total size of this entry.
42 uint32_t size;
43
44 bool GetFeatureAndTrialName(StringPiece* feature_name,
45 StringPiece* trial_name) const {
46 char* src = reinterpret_cast<char*>(const_cast<FeatureEntry*>(this)) +
47 sizeof(FeatureEntry);
48
49 Pickle pickle(src, size);
50 PickleIterator pickle_iter(pickle);
51
52 if (!pickle_iter.ReadStringPiece(feature_name))
53 return false;
54
55 pickle_iter.ReadStringPiece(trial_name);
56 return true;
57 }
58 };
59
30 // Some characters are not allowed to appear in feature names or the associated 60 // Some characters are not allowed to appear in feature names or the associated
31 // field trial names, as they are used as special characters for command-line 61 // field trial names, as they are used as special characters for command-line
32 // serialization. This function checks that the strings are ASCII (since they 62 // serialization. This function checks that the strings are ASCII (since they
33 // are used in command-line API functions that require ASCII) and whether there 63 // are used in command-line API functions that require ASCII) and whether there
34 // are any reserved characters present, returning true if the string is valid. 64 // are any reserved characters present, returning true if the string is valid.
35 // Only called in DCHECKs. 65 // Only called in DCHECKs.
36 bool IsValidFeatureOrFieldTrialName(const std::string& name) { 66 bool IsValidFeatureOrFieldTrialName(const std::string& name) {
37 return IsStringASCII(name) && name.find_first_of(",<*") == std::string::npos; 67 return IsStringASCII(name) && name.find_first_of(",<*") == std::string::npos;
38 } 68 }
39 69
40 } // namespace 70 } // namespace
41 71
42 FeatureList::FeatureList() {} 72 FeatureList::FeatureList() {}
43 73
44 FeatureList::~FeatureList() {} 74 FeatureList::~FeatureList() {}
45 75
46 void FeatureList::InitializeFromCommandLine( 76 void FeatureList::InitializeFromCommandLine(
47 const std::string& enable_features, 77 const std::string& enable_features,
48 const std::string& disable_features) { 78 const std::string& disable_features) {
49 DCHECK(!initialized_); 79 DCHECK(!initialized_);
50 80
51 // Process disabled features first, so that disabled ones take precedence over 81 // Process disabled features first, so that disabled ones take precedence over
52 // enabled ones (since RegisterOverride() uses insert()). 82 // enabled ones (since RegisterOverride() uses insert()).
53 RegisterOverridesFromCommandLine(disable_features, OVERRIDE_DISABLE_FEATURE); 83 RegisterOverridesFromCommandLine(disable_features, OVERRIDE_DISABLE_FEATURE);
54 RegisterOverridesFromCommandLine(enable_features, OVERRIDE_ENABLE_FEATURE); 84 RegisterOverridesFromCommandLine(enable_features, OVERRIDE_ENABLE_FEATURE);
55 85
56 initialized_from_command_line_ = true; 86 initialized_from_command_line_ = true;
57 } 87 }
58 88
89 void FeatureList::InitializeFromSharedMemory(
lawrencewu 2016/12/01 18:50:38 write a test that stores and retrieves features fr
lawrencewu 2016/12/01 19:30:55 Done.
90 SharedPersistentMemoryAllocator* allocator) {
91 DCHECK(!initialized_);
92
93 SharedPersistentMemoryAllocator::Iterator iter(allocator);
94
95 SharedPersistentMemoryAllocator::Reference ref;
96 while ((ref = iter.GetNextOfType(kFeatureType)) !=
97 SharedPersistentMemoryAllocator::kReferenceNull) {
98 const FeatureEntry* entry =
99 allocator->GetAsObject<const FeatureEntry>(ref, kFeatureType);
100
101 OverrideState override_state =
102 static_cast<OverrideState>(entry->override_state);
103
104 StringPiece feature_name;
105 StringPiece trial_name;
106 entry->GetFeatureAndTrialName(&feature_name, &trial_name);
107
108 FieldTrial* trial = FieldTrialList::Find(trial_name.as_string());
109 RegisterOverride(feature_name, override_state, trial);
110 }
111 }
112
59 bool FeatureList::IsFeatureOverriddenFromCommandLine( 113 bool FeatureList::IsFeatureOverriddenFromCommandLine(
60 const std::string& feature_name, 114 const std::string& feature_name,
61 OverrideState state) const { 115 OverrideState state) const {
62 auto it = overrides_.find(feature_name); 116 auto it = overrides_.find(feature_name);
63 return it != overrides_.end() && it->second.overridden_state == state && 117 return it != overrides_.end() && it->second.overridden_state == state &&
64 !it->second.overridden_by_field_trial; 118 !it->second.overridden_by_field_trial;
65 } 119 }
66 120
67 void FeatureList::AssociateReportingFieldTrial( 121 void FeatureList::AssociateReportingFieldTrial(
68 const std::string& feature_name, 122 const std::string& feature_name,
(...skipping 22 matching lines...) Expand all
91 DCHECK(!ContainsKey(overrides_, feature_name) || 145 DCHECK(!ContainsKey(overrides_, feature_name) ||
92 !overrides_.find(feature_name)->second.field_trial) 146 !overrides_.find(feature_name)->second.field_trial)
93 << "Feature " << feature_name 147 << "Feature " << feature_name
94 << " has conflicting field trial overrides: " 148 << " has conflicting field trial overrides: "
95 << overrides_.find(feature_name)->second.field_trial->trial_name() 149 << overrides_.find(feature_name)->second.field_trial->trial_name()
96 << " / " << field_trial->trial_name(); 150 << " / " << field_trial->trial_name();
97 151
98 RegisterOverride(feature_name, override_state, field_trial); 152 RegisterOverride(feature_name, override_state, field_trial);
99 } 153 }
100 154
155 void FeatureList::AddFeaturesToAllocator(
156 FieldTrialList::FieldTrialAllocator* allocator) {
157 DCHECK(initialized_);
158
159 for (const auto& override : overrides_) {
160 Pickle pickle;
161 pickle.WriteString(override.first);
162 if (override.second.field_trial)
163 pickle.WriteString(override.second.field_trial->trial_name());
164
165 size_t total_size = sizeof(FeatureEntry) + pickle.size();
166 SharedPersistentMemoryAllocator::Reference ref =
167 allocator->Allocate(total_size, kFeatureType);
168 if (!ref)
169 return;
170
171 FeatureEntry* entry =
172 allocator->GetAsObject<FeatureEntry>(ref, kFeatureType);
173 entry->override_state = override.second.overridden_state;
174 entry->size = pickle.size();
175
176 char* dst = reinterpret_cast<char*>(entry) + sizeof(FeatureEntry);
177 memcpy(dst, pickle.data(), pickle.size());
178
179 allocator->MakeIterable(ref);
180 // should we add a ref to each feature?
lawrencewu 2016/12/01 18:50:38 remove this comment
lawrencewu 2016/12/01 19:30:56 Done.
181 }
182 }
183
101 void FeatureList::GetFeatureOverrides(std::string* enable_overrides, 184 void FeatureList::GetFeatureOverrides(std::string* enable_overrides,
102 std::string* disable_overrides) { 185 std::string* disable_overrides) {
103 DCHECK(initialized_); 186 DCHECK(initialized_);
104 187
105 enable_overrides->clear(); 188 enable_overrides->clear();
106 disable_overrides->clear(); 189 disable_overrides->clear();
107 190
108 // Note: Since |overrides_| is a std::map, iteration will be in alphabetical 191 // Note: Since |overrides_| is a std::map, iteration will be in alphabetical
109 // order. This not guaranteed to users of this function, but is useful for 192 // order. This not guaranteed to users of this function, but is useful for
110 // tests to assume the order. 193 // tests to assume the order.
(...skipping 196 matching lines...) Expand 10 before | Expand all | Expand 10 after
307 return it->second == &feature; 390 return it->second == &feature;
308 } 391 }
309 392
310 FeatureList::OverrideEntry::OverrideEntry(OverrideState overridden_state, 393 FeatureList::OverrideEntry::OverrideEntry(OverrideState overridden_state,
311 FieldTrial* field_trial) 394 FieldTrial* field_trial)
312 : overridden_state(overridden_state), 395 : overridden_state(overridden_state),
313 field_trial(field_trial), 396 field_trial(field_trial),
314 overridden_by_field_trial(field_trial != nullptr) {} 397 overridden_by_field_trial(field_trial != nullptr) {}
315 398
316 } // namespace base 399 } // namespace base
OLDNEW
« no previous file with comments | « base/feature_list.h ('k') | base/metrics/field_trial.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698