// Copyright 2017 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "components/metrics/persistent_system_profile.h"

#include <set>

#include "base/atomicops.h"
#include "base/bits.h"
#include "base/memory/singleton.h"
#include "base/metrics/persistent_memory_allocator.h"
#include "base/pickle.h"
#include "base/stl_util.h"
#include "components/variations/active_field_trials.h"

namespace metrics {

namespace {

// To provide atomic addition of records so that there is no confusion between
// writers and readers, all of the metadata about a record is contained in a
// structure that can be stored as a single atomic 32-bit word.
union RecordHeader {
  struct {
    unsigned continued : 1;  // Flag indicating if there is more after this.
    unsigned type : 7;       // The type of this record.
    unsigned amount : 24;    // The amount of data to follow.
  } as_parts;
  base::subtle::Atomic32 as_atomic;
};

constexpr uint32_t kTypeIdSystemProfile = 0x330A7150;  // SHA1(SystemProfile)
constexpr size_t kSystemProfileAllocSize = 4 << 10;    // 4 KiB
constexpr size_t kMaxRecordSize = (1 << 24) - sizeof(RecordHeader);

static_assert(sizeof(RecordHeader) == sizeof(base::subtle::Atomic32),
              "bad RecordHeader size");

// Calculate the size of a record based on the amount of data. This adds room
// for the record header and rounds up to the next multiple of the record-header
// size.
size_t CalculateRecordSize(size_t data_amount) {
  return base::bits::Align(data_amount + sizeof(RecordHeader),
                           sizeof(RecordHeader));
}

}  // namespace

PersistentSystemProfile::RecordAllocator::RecordAllocator(
    base::PersistentMemoryAllocator* memory_allocator,
    size_t min_size)
    : allocator_(memory_allocator),
      has_complete_profile_(false),
      alloc_reference_(0),
      alloc_size_(0),
      end_offset_(0) {
  AddSegment(min_size);
}

PersistentSystemProfile::RecordAllocator::RecordAllocator(
    const base::PersistentMemoryAllocator* memory_allocator)
    : allocator_(
          const_cast<base::PersistentMemoryAllocator*>(memory_allocator)),
      alloc_reference_(0),
      alloc_size_(0),
      end_offset_(0) {}

void PersistentSystemProfile::RecordAllocator::Reset() {
  // Clear the first word of all blocks so they're known to be "empty".
  alloc_reference_ = 0;
  while (NextSegment()) {
    // Get the block as a char* and cast it. It can't be fetched directly as
    // an array of RecordHeader because that's not a fundamental type and only
    // arrays of fundamental types are allowed.
    RecordHeader* header =
        reinterpret_cast<RecordHeader*>(allocator_->GetAsArray<char>(
            alloc_reference_, kTypeIdSystemProfile, sizeof(RecordHeader)));
    DCHECK(header);
    base::subtle::NoBarrier_Store(&header->as_atomic, 0);
  }

  // Reset member variables.
  has_complete_profile_ = false;
  alloc_reference_ = 0;
  alloc_size_ = 0;
  end_offset_ = 0;
}

bool PersistentSystemProfile::RecordAllocator::Write(RecordType type,
                                                     base::StringPiece record) {
  const char* data = record.data();
  size_t remaining_size = record.size();

  // Allocate space and write records until everything has been stored.
  do {
    if (end_offset_ == alloc_size_) {
      if (!AddSegment(remaining_size))
        return false;
    }
    // Write out as much of the data as possible. |data| and |remaining_size|
    // are updated in place.
    if (!WriteData(type, &data, &remaining_size))
      return false;
  } while (remaining_size > 0);

  return true;
}

bool PersistentSystemProfile::RecordAllocator::HasMoreData() const {
  if (alloc_reference_ == 0 && !NextSegment())
    return false;

  char* block =
      allocator_->GetAsArray<char>(alloc_reference_, kTypeIdSystemProfile,
                                   base::PersistentMemoryAllocator::kSizeAny);
  if (!block)
    return false;

  RecordHeader header;
  header.as_atomic = base::subtle::Acquire_Load(
      reinterpret_cast<base::subtle::Atomic32*>(block + end_offset_));
  return header.as_parts.type != kUnusedSpace;
}

bool PersistentSystemProfile::RecordAllocator::Read(RecordType* type,
                                                    std::string* record) const {
  *type = kUnusedSpace;
  record->clear();

  // Access data and read records until everything has been loaded.
  while (true) {
    if (end_offset_ == alloc_size_) {
      if (!NextSegment())
        return false;
    }
    if (ReadData(type, record))
      return *type != kUnusedSpace;
  }
}

bool PersistentSystemProfile::RecordAllocator::NextSegment() const {
  base::PersistentMemoryAllocator::Iterator iter(allocator_, alloc_reference_);
  alloc_reference_ = iter.GetNextOfType(kTypeIdSystemProfile);
  alloc_size_ = allocator_->GetAllocSize(alloc_reference_);
  end_offset_ = 0;
  return alloc_reference_ != 0;
}

bool PersistentSystemProfile::RecordAllocator::AddSegment(size_t min_size) {
  if (NextSegment()) {
    // The first record-header should have been zeroed as part of the allocation
    // or by the "reset" procedure.
    DCHECK_EQ(0, base::subtle::NoBarrier_Load(
                     allocator_->GetAsArray<base::subtle::Atomic32>(
                         alloc_reference_, kTypeIdSystemProfile, 1)));
    return true;
  }

  DCHECK_EQ(0U, alloc_reference_);
  DCHECK_EQ(0U, end_offset_);

  size_t size =
      std::max(CalculateRecordSize(min_size), kSystemProfileAllocSize);

  uint32_t ref = allocator_->Allocate(size, kTypeIdSystemProfile);
  if (!ref)
    return false;  // Allocator must be full.
  allocator_->MakeIterable(ref);

  alloc_reference_ = ref;
  alloc_size_ = allocator_->GetAllocSize(ref);
  return true;
}

bool PersistentSystemProfile::RecordAllocator::WriteData(RecordType type,
                                                         const char** data,
                                                         size_t* data_size) {
  char* block =
      allocator_->GetAsArray<char>(alloc_reference_, kTypeIdSystemProfile,
                                   base::PersistentMemoryAllocator::kSizeAny);
  if (!block)
    return false;  // It's bad if there is no accessible block.

  const size_t max_write_size = std::min(
      kMaxRecordSize, alloc_size_ - end_offset_ - sizeof(RecordHeader));
  const size_t write_size = std::min(*data_size, max_write_size);
  const size_t record_size = CalculateRecordSize(write_size);
  DCHECK_LT(write_size, record_size);

  // Write the data and the record header.
  RecordHeader header;
  header.as_atomic = 0;
  header.as_parts.type = type;
  header.as_parts.amount = write_size;
  header.as_parts.continued = (write_size < *data_size);
  size_t offset = end_offset_;
  end_offset_ += record_size;
  DCHECK_GE(alloc_size_, end_offset_);
  if (end_offset_ < alloc_size_) {
    // An empty record header has to be next before this one gets written.
    base::subtle::NoBarrier_Store(
        reinterpret_cast<base::subtle::Atomic32*>(block + end_offset_), 0);
  }
  memcpy(block + offset + sizeof(header), *data, write_size);
  base::subtle::Release_Store(
      reinterpret_cast<base::subtle::Atomic32*>(block + offset),
      header.as_atomic);

  // Account for what was stored and prepare for follow-on records with any
  // remaining data.
  *data += write_size;
  *data_size -= write_size;

  return true;
}

bool PersistentSystemProfile::RecordAllocator::ReadData(
    RecordType* type,
    std::string* record) const {
  DCHECK_GT(alloc_size_, end_offset_);

  char* block =
      allocator_->GetAsArray<char>(alloc_reference_, kTypeIdSystemProfile,
                                   base::PersistentMemoryAllocator::kSizeAny);
  if (!block) {
    *type = kUnusedSpace;
    return true;  // No more data.
  }

  // Get and validate the record header.
  RecordHeader header;
  header.as_atomic = base::subtle::Acquire_Load(
      reinterpret_cast<base::subtle::Atomic32*>(block + end_offset_));
  bool continued = !!header.as_parts.continued;
  if (header.as_parts.type == kUnusedSpace) {
    *type = kUnusedSpace;
    return true;  // End of all records.
  } else if (*type == kUnusedSpace) {
    *type = static_cast<RecordType>(header.as_parts.type);
  } else if (*type != header.as_parts.type) {
    NOTREACHED();  // Continuation didn't match start of record.
    *type = kUnusedSpace;
    record->clear();
    return false;
  }
  size_t read_size = header.as_parts.amount;
  if (end_offset_ + sizeof(header) + read_size > alloc_size_) {
    NOTREACHED();  // Invalid header amount.
    *type = kUnusedSpace;
    return true;  // Don't try again.
  }

  // Append the record data to the output string.
  record->append(block + end_offset_ + sizeof(header), read_size);
  end_offset_ += CalculateRecordSize(read_size);
  DCHECK_GE(alloc_size_, end_offset_);

  return !continued;
}

PersistentSystemProfile::PersistentSystemProfile() {}

PersistentSystemProfile::~PersistentSystemProfile() {}

void PersistentSystemProfile::RegisterPersistentAllocator(
    base::PersistentMemoryAllocator* memory_allocator) {
  DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);

  // Create and store the allocator. A |min_size| of "1" ensures that a memory
  // block is reserved now.
  RecordAllocator allocator(memory_allocator, 1);
  allocators_.push_back(std::move(allocator));
  all_have_complete_profile_ = false;
}

void PersistentSystemProfile::DeregisterPersistentAllocator(
    base::PersistentMemoryAllocator* memory_allocator) {
  DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);

  // This would be more efficient with a std::map but it's not expected that
  // allocators will get deregistered with any frequency, if at all.
  base::EraseIf(allocators_, [=](RecordAllocator& records) {
    return records.allocator() == memory_allocator;
  });
}

void PersistentSystemProfile::SetSystemProfile(
    const std::string& serialized_profile,
    bool complete) {
  DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);

  if (allocators_.empty() || serialized_profile.empty())
    return;

  for (auto& allocator : allocators_) {
    // Don't overwrite a complete profile with an incomplete one.
    if (!complete && allocator.has_complete_profile())
      continue;
    // A full system profile always starts fresh. Incomplete keeps existing
    // records for merging.
    if (complete)
      allocator.Reset();
    // Write out the serialized profile.
    allocator.Write(kSystemProfileProto, serialized_profile);
    // Indicate if this is a complete profile.
    if (complete)
      allocator.set_complete_profile();
  }

  if (complete)
    all_have_complete_profile_ = true;
}

void PersistentSystemProfile::SetSystemProfile(
    const SystemProfileProto& profile,
    bool complete) {
  // Avoid serialization if passed profile is not complete and all allocators
  // already have complete ones.
  if (!complete && all_have_complete_profile_)
    return;

  std::string serialized_profile;
  if (!profile.SerializeToString(&serialized_profile))
    return;
  SetSystemProfile(serialized_profile, complete);
}

void PersistentSystemProfile::AddFieldTrial(base::StringPiece trial,
                                            base::StringPiece group) {
  DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
  DCHECK(!trial.empty());
  DCHECK(!group.empty());

  base::Pickle pickler;
  pickler.WriteString(trial);
  pickler.WriteString(group);

  WriteToAll(kFieldTrialInfo,
             base::StringPiece(static_cast<const char*>(pickler.data()),
                               pickler.size()));
}

// static
bool PersistentSystemProfile::HasSystemProfile(
    const base::PersistentMemoryAllocator& memory_allocator) {
  const RecordAllocator records(&memory_allocator);
  return records.HasMoreData();
}

// static
bool PersistentSystemProfile::GetSystemProfile(
    const base::PersistentMemoryAllocator& memory_allocator,
    SystemProfileProto* system_profile) {
  const RecordAllocator records(&memory_allocator);

  RecordType type;
  std::string record;
  do {
    if (!records.Read(&type, &record))
      return false;
  } while (type != kSystemProfileProto);

  if (!system_profile)
    return true;

  if (!system_profile->ParseFromString(record))
    return false;

  MergeUpdateRecords(memory_allocator, system_profile);
  return true;
}

// static
void PersistentSystemProfile::MergeUpdateRecords(
    const base::PersistentMemoryAllocator& memory_allocator,
    SystemProfileProto* system_profile) {
  const RecordAllocator records(&memory_allocator);

  RecordType type;
  std::string record;
  std::set<uint32_t> known_field_trial_ids;

  // This is done separate from the code that gets the profile because it
  // compartmentalizes the code and makes it possible to reuse this section
  // should it be needed to merge "update" records into a new "complete"
  // system profile that somehow didn't get all the updates.
  while (records.Read(&type, &record)) {
    switch (type) {
      case kUnusedSpace:
        // These should never be returned.
        NOTREACHED();
        break;

      case kSystemProfileProto:
        // Profile was passed in; ignore this one.
        break;

      case kFieldTrialInfo: {
        // Get the set of known trial IDs so duplicates don't get added.
        if (known_field_trial_ids.empty()) {
          for (int i = 0; i < system_profile->field_trial_size(); ++i) {
            known_field_trial_ids.insert(
                system_profile->field_trial(i).name_id());
          }
        }

        base::Pickle pickler(record.data(), record.size());
        base::PickleIterator iter(pickler);
        base::StringPiece trial;
        base::StringPiece group;
        if (iter.ReadStringPiece(&trial) && iter.ReadStringPiece(&group)) {
          variations::ActiveGroupId field_ids =
              variations::MakeActiveGroupId(trial, group);
          if (!base::ContainsKey(known_field_trial_ids, field_ids.name)) {
            SystemProfileProto::FieldTrial* field_trial =
                system_profile->add_field_trial();
            field_trial->set_name_id(field_ids.name);
            field_trial->set_group_id(field_ids.group);
            known_field_trial_ids.insert(field_ids.name);
          }
        }
      } break;
    }
  }
}

void PersistentSystemProfile::WriteToAll(RecordType type,
                                         base::StringPiece record) {
  for (auto& allocator : allocators_)
    allocator.Write(type, record);
}

GlobalPersistentSystemProfile* GlobalPersistentSystemProfile::GetInstance() {
  return base::Singleton<
      GlobalPersistentSystemProfile,
      base::LeakySingletonTraits<GlobalPersistentSystemProfile>>::get();
}

}  // namespace metrics
