1 // Copyright 2017 The Chromium Authors
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 #ifndef COMPONENTS_METRICS_PERSISTENT_SYSTEM_PROFILE_H_
6 #define COMPONENTS_METRICS_PERSISTENT_SYSTEM_PROFILE_H_
10 #include "base/memory/raw_ptr.h"
11 #include "base/strings/string_piece.h"
12 #include "base/threading/thread_checker.h"
13 #include "third_party/metrics_proto/system_profile.pb.h"
17 struct DefaultSingletonTraits;
18 class PersistentMemoryAllocator;
23 // Manages a copy of the system profile inside persistent memory segments.
24 class PersistentSystemProfile {
26 PersistentSystemProfile();
28 PersistentSystemProfile(const PersistentSystemProfile&) = delete;
29 PersistentSystemProfile& operator=(const PersistentSystemProfile&) = delete;
31 ~PersistentSystemProfile();
33 // This object can store records in multiple memory allocators.
34 void RegisterPersistentAllocator(
35 base::PersistentMemoryAllocator* memory_allocator);
36 void DeregisterPersistentAllocator(
37 base::PersistentMemoryAllocator* memory_allocator);
39 // Stores a complete system profile. Use the version taking the serialized
40 // version if available to avoid multiple serialization actions. The
41 // |complete| flag indicates that this profile contains all known information
42 // and can replace whatever exists. If the flag is false, the existing profile
43 // will only be replaced if it is also incomplete. This method should not be
44 // called too many times with incomplete profiles before setting a complete
45 // profile to prevent impact on startup.
46 void SetSystemProfile(const std::string& serialized_profile, bool complete);
47 void SetSystemProfile(const SystemProfileProto& profile, bool complete);
49 // Records the existence of a field trial.
50 void AddFieldTrial(base::StringPiece trial, base::StringPiece group);
52 // Removes the field trial from the system profile.
53 void RemoveFieldTrial(base::StringPiece trial);
55 // Tests if a persistent memory allocator contains an system profile.
56 static bool HasSystemProfile(
57 const base::PersistentMemoryAllocator& memory_allocator);
59 // Retrieves the system profile from a persistent memory allocator. Returns
60 // true if a profile was successfully retrieved. If null is passed for the
61 // |system_profile|, only a basic check for the existence of one will be
63 static bool GetSystemProfile(
64 const base::PersistentMemoryAllocator& memory_allocator,
65 SystemProfileProto* system_profile);
68 friend class PersistentSystemProfileTest;
70 // Defines record types that can be stored inside our local Allocators.
71 enum RecordType : uint8_t {
72 kUnusedSpace = 0, // The default value for empty memory.
77 // A class for managing record allocations inside a persistent memory segment.
78 class RecordAllocator {
80 // Construct an allocator for writing.
81 RecordAllocator(base::PersistentMemoryAllocator* memory_allocator,
84 // Construct an allocator for reading.
85 RecordAllocator(const base::PersistentMemoryAllocator* memory_allocator);
87 // These methods manage writing records to the allocator. Do not mix these
88 // with "read" calls; it's one or the other.
90 bool Write(RecordType type, base::StringPiece record);
92 // Read a record from the allocator. Do not mix this with "write" calls;
93 // it's one or the other.
94 bool HasMoreData() const;
95 bool Read(RecordType* type, std::string* record) const;
97 base::PersistentMemoryAllocator* allocator() { return allocator_; }
99 bool has_complete_profile() { return has_complete_profile_; }
100 void set_complete_profile() { has_complete_profile_ = true; }
103 // Advance to the next record segment in the memory allocator.
104 bool NextSegment() const;
106 // Advance to the next record segment, creating a new one if necessary with
107 // sufficent |min_size| space.
108 bool AddSegment(size_t min_size);
110 // Writes data to the current position, updating the passed values past
111 // the amount written. Returns false in case of an error.
112 bool WriteData(RecordType type, const char** data, size_t* data_size);
114 // Reads data from the current position, updating the passed string
115 // in-place. |type| must be initialized to kUnusedSpace and |record| must
116 // be an empty string before the first call but unchanged thereafter.
117 // Returns true when record is complete.
118 bool ReadData(RecordType* type, std::string* record) const;
120 // This never changes but can't be "const" because vector calls operator=().
121 raw_ptr<base::PersistentMemoryAllocator> allocator_; // Storage location.
123 // Indicates if a complete profile has been stored.
124 bool has_complete_profile_;
126 // These change even though the underlying data may be "const".
127 mutable uint32_t alloc_reference_; // Last storage block.
128 mutable size_t alloc_size_; // Size of the block.
129 mutable size_t end_offset_; // End of data in block.
131 // Copy and assign are allowed for easy use with STL containers.
134 // Write a record to all registered allocators.
135 void WriteToAll(RecordType type, base::StringPiece record);
137 // Merges all "update" records into a system profile.
138 static void MergeUpdateRecords(
139 const base::PersistentMemoryAllocator& memory_allocator,
140 SystemProfileProto* system_profile);
142 // The list of registered persistent allocators, described by RecordAllocator
144 std::vector<RecordAllocator> allocators_;
146 // Indicates if a complete profile has been stored to all allocators.
147 bool all_have_complete_profile_ = false;
149 THREAD_CHECKER(thread_checker_);
152 // A singleton instance of the above.
153 class GlobalPersistentSystemProfile : public PersistentSystemProfile {
155 static GlobalPersistentSystemProfile* GetInstance();
157 GlobalPersistentSystemProfile(const GlobalPersistentSystemProfile&) = delete;
158 GlobalPersistentSystemProfile& operator=(
159 const GlobalPersistentSystemProfile&) = delete;
162 friend struct base::DefaultSingletonTraits<GlobalPersistentSystemProfile>;
164 GlobalPersistentSystemProfile() {}
165 ~GlobalPersistentSystemProfile() {}
168 } // namespace metrics
170 #endif // COMPONENTS_METRICS_PERSISTENT_SYSTEM_PROFILE_H_