171 lines
6.3 KiB
C++
171 lines
6.3 KiB
C++
// 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_
|