• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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