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. 4 5 #ifndef COMPONENTS_METRICS_PERSISTENT_SYSTEM_PROFILE_H_ 6 #define COMPONENTS_METRICS_PERSISTENT_SYSTEM_PROFILE_H_ 7 8 #include <vector> 9 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" 14 15 namespace base { 16 template <typename T> 17 struct DefaultSingletonTraits; 18 class PersistentMemoryAllocator; 19 } // namespace base 20 21 namespace metrics { 22 23 // Manages a copy of the system profile inside persistent memory segments. 24 class PersistentSystemProfile { 25 public: 26 PersistentSystemProfile(); 27 28 PersistentSystemProfile(const PersistentSystemProfile&) = delete; 29 PersistentSystemProfile& operator=(const PersistentSystemProfile&) = delete; 30 31 ~PersistentSystemProfile(); 32 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); 38 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); 48 49 // Records the existence of a field trial. 50 void AddFieldTrial(base::StringPiece trial, base::StringPiece group); 51 52 // Removes the field trial from the system profile. 53 void RemoveFieldTrial(base::StringPiece trial); 54 55 // Tests if a persistent memory allocator contains an system profile. 56 static bool HasSystemProfile( 57 const base::PersistentMemoryAllocator& memory_allocator); 58 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 62 // done. 63 static bool GetSystemProfile( 64 const base::PersistentMemoryAllocator& memory_allocator, 65 SystemProfileProto* system_profile); 66 67 private: 68 friend class PersistentSystemProfileTest; 69 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. 73 kSystemProfileProto, 74 kFieldTrialInfo, 75 }; 76 77 // A class for managing record allocations inside a persistent memory segment. 78 class RecordAllocator { 79 public: 80 // Construct an allocator for writing. 81 RecordAllocator(base::PersistentMemoryAllocator* memory_allocator, 82 size_t min_size); 83 84 // Construct an allocator for reading. 85 RecordAllocator(const base::PersistentMemoryAllocator* memory_allocator); 86 87 // These methods manage writing records to the allocator. Do not mix these 88 // with "read" calls; it's one or the other. 89 void Reset(); 90 bool Write(RecordType type, base::StringPiece record); 91 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; 96 allocator()97 base::PersistentMemoryAllocator* allocator() { return allocator_; } 98 has_complete_profile()99 bool has_complete_profile() { return has_complete_profile_; } set_complete_profile()100 void set_complete_profile() { has_complete_profile_ = true; } 101 102 private: 103 // Advance to the next record segment in the memory allocator. 104 bool NextSegment() const; 105 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); 109 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); 113 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; 119 120 // This never changes but can't be "const" because vector calls operator=(). 121 raw_ptr<base::PersistentMemoryAllocator> allocator_; // Storage location. 122 123 // Indicates if a complete profile has been stored. 124 bool has_complete_profile_; 125 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. 130 131 // Copy and assign are allowed for easy use with STL containers. 132 }; 133 134 // Write a record to all registered allocators. 135 void WriteToAll(RecordType type, base::StringPiece record); 136 137 // Merges all "update" records into a system profile. 138 static void MergeUpdateRecords( 139 const base::PersistentMemoryAllocator& memory_allocator, 140 SystemProfileProto* system_profile); 141 142 // The list of registered persistent allocators, described by RecordAllocator 143 // instances. 144 std::vector<RecordAllocator> allocators_; 145 146 // Indicates if a complete profile has been stored to all allocators. 147 bool all_have_complete_profile_ = false; 148 149 THREAD_CHECKER(thread_checker_); 150 }; 151 152 // A singleton instance of the above. 153 class GlobalPersistentSystemProfile : public PersistentSystemProfile { 154 public: 155 static GlobalPersistentSystemProfile* GetInstance(); 156 157 GlobalPersistentSystemProfile(const GlobalPersistentSystemProfile&) = delete; 158 GlobalPersistentSystemProfile& operator=( 159 const GlobalPersistentSystemProfile&) = delete; 160 161 private: 162 friend struct base::DefaultSingletonTraits<GlobalPersistentSystemProfile>; 163 164 GlobalPersistentSystemProfile() {} 165 ~GlobalPersistentSystemProfile() {} 166 }; 167 168 } // namespace metrics 169 170 #endif // COMPONENTS_METRICS_PERSISTENT_SYSTEM_PROFILE_H_ 171