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