// Copyright 2016 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 "base/debug/activity_analyzer.h"

#include <algorithm>
#include <utility>

#include "base/files/file.h"
#include "base/files/file_path.h"
#include "base/files/memory_mapped_file.h"
#include "base/lazy_instance.h"
#include "base/logging.h"
#include "base/memory/ptr_util.h"
#include "base/metrics/histogram_macros.h"
#include "base/stl_util.h"
#include "base/strings/string_util.h"

namespace base {
namespace debug {

namespace {
// An empty snapshot that can be returned when there otherwise is none.
LazyInstance<ActivityUserData::Snapshot>::Leaky g_empty_user_data_snapshot;

// DO NOT CHANGE VALUES. This is logged persistently in a histogram.
enum AnalyzerCreationError {
  kInvalidMemoryMappedFile,
  kPmaBadFile,
  kPmaUninitialized,
  kPmaDeleted,
  kPmaCorrupt,
  kAnalyzerCreationErrorMax  // Keep this last.
};

void LogAnalyzerCreationError(AnalyzerCreationError error) {
  UMA_HISTOGRAM_ENUMERATION("ActivityTracker.Collect.AnalyzerCreationError",
                            error, kAnalyzerCreationErrorMax);
}

}  // namespace

ThreadActivityAnalyzer::Snapshot::Snapshot() = default;
ThreadActivityAnalyzer::Snapshot::~Snapshot() = default;

ThreadActivityAnalyzer::ThreadActivityAnalyzer(
    const ThreadActivityTracker& tracker)
    : activity_snapshot_valid_(tracker.CreateSnapshot(&activity_snapshot_)) {}

ThreadActivityAnalyzer::ThreadActivityAnalyzer(void* base, size_t size)
    : ThreadActivityAnalyzer(ThreadActivityTracker(base, size)) {}

ThreadActivityAnalyzer::ThreadActivityAnalyzer(
    PersistentMemoryAllocator* allocator,
    PersistentMemoryAllocator::Reference reference)
    : ThreadActivityAnalyzer(allocator->GetAsArray<char>(
                                 reference,
                                 GlobalActivityTracker::kTypeIdActivityTracker,
                                 PersistentMemoryAllocator::kSizeAny),
                             allocator->GetAllocSize(reference)) {}

ThreadActivityAnalyzer::~ThreadActivityAnalyzer() = default;

void ThreadActivityAnalyzer::AddGlobalInformation(
    GlobalActivityAnalyzer* global) {
  if (!IsValid())
    return;

  // User-data is held at the global scope even though it's referenced at the
  // thread scope.
  activity_snapshot_.user_data_stack.clear();
  for (auto& activity : activity_snapshot_.activity_stack) {
    // The global GetUserDataSnapshot will return an empty snapshot if the ref
    // or id is not valid.
    activity_snapshot_.user_data_stack.push_back(global->GetUserDataSnapshot(
        activity_snapshot_.process_id, activity.user_data_ref,
        activity.user_data_id));
  }
}

GlobalActivityAnalyzer::GlobalActivityAnalyzer(
    std::unique_ptr<PersistentMemoryAllocator> allocator)
    : allocator_(std::move(allocator)),
      analysis_stamp_(0LL),
      allocator_iterator_(allocator_.get()) {
  DCHECK(allocator_);
}

GlobalActivityAnalyzer::~GlobalActivityAnalyzer() = default;

// static
std::unique_ptr<GlobalActivityAnalyzer>
GlobalActivityAnalyzer::CreateWithAllocator(
    std::unique_ptr<PersistentMemoryAllocator> allocator) {
  if (allocator->GetMemoryState() ==
      PersistentMemoryAllocator::MEMORY_UNINITIALIZED) {
    LogAnalyzerCreationError(kPmaUninitialized);
    return nullptr;
  }
  if (allocator->GetMemoryState() ==
      PersistentMemoryAllocator::MEMORY_DELETED) {
    LogAnalyzerCreationError(kPmaDeleted);
    return nullptr;
  }
  if (allocator->IsCorrupt()) {
    LogAnalyzerCreationError(kPmaCorrupt);
    return nullptr;
  }

  return WrapUnique(new GlobalActivityAnalyzer(std::move(allocator)));
}

#if !defined(OS_NACL)
// static
std::unique_ptr<GlobalActivityAnalyzer> GlobalActivityAnalyzer::CreateWithFile(
    const FilePath& file_path) {
  // Map the file read-write so it can guarantee consistency between
  // the analyzer and any trackers that my still be active.
  std::unique_ptr<MemoryMappedFile> mmfile(new MemoryMappedFile());
  mmfile->Initialize(file_path, MemoryMappedFile::READ_WRITE);
  if (!mmfile->IsValid()) {
    LogAnalyzerCreationError(kInvalidMemoryMappedFile);
    return nullptr;
  }

  if (!FilePersistentMemoryAllocator::IsFileAcceptable(*mmfile, true)) {
    LogAnalyzerCreationError(kPmaBadFile);
    return nullptr;
  }

  return CreateWithAllocator(std::make_unique<FilePersistentMemoryAllocator>(
      std::move(mmfile), 0, 0, StringPiece(), /*readonly=*/true));
}
#endif  // !defined(OS_NACL)

// static
std::unique_ptr<GlobalActivityAnalyzer>
GlobalActivityAnalyzer::CreateWithSharedMemory(
    std::unique_ptr<SharedMemory> shm) {
  if (shm->mapped_size() == 0 ||
      !SharedPersistentMemoryAllocator::IsSharedMemoryAcceptable(*shm)) {
    return nullptr;
  }
  return CreateWithAllocator(std::make_unique<SharedPersistentMemoryAllocator>(
      std::move(shm), 0, StringPiece(), /*readonly=*/true));
}

// static
std::unique_ptr<GlobalActivityAnalyzer>
GlobalActivityAnalyzer::CreateWithSharedMemoryHandle(
    const SharedMemoryHandle& handle,
    size_t size) {
  std::unique_ptr<SharedMemory> shm(
      new SharedMemory(handle, /*readonly=*/true));
  if (!shm->Map(size))
    return nullptr;
  return CreateWithSharedMemory(std::move(shm));
}

int64_t GlobalActivityAnalyzer::GetFirstProcess() {
  PrepareAllAnalyzers();
  return GetNextProcess();
}

int64_t GlobalActivityAnalyzer::GetNextProcess() {
  if (process_ids_.empty())
    return 0;
  int64_t pid = process_ids_.back();
  process_ids_.pop_back();
  return pid;
}

ThreadActivityAnalyzer* GlobalActivityAnalyzer::GetFirstAnalyzer(int64_t pid) {
  analyzers_iterator_ = analyzers_.begin();
  analyzers_iterator_pid_ = pid;
  if (analyzers_iterator_ == analyzers_.end())
    return nullptr;
  int64_t create_stamp;
  if (analyzers_iterator_->second->GetProcessId(&create_stamp) == pid &&
      create_stamp <= analysis_stamp_) {
    return analyzers_iterator_->second.get();
  }
  return GetNextAnalyzer();
}

ThreadActivityAnalyzer* GlobalActivityAnalyzer::GetNextAnalyzer() {
  DCHECK(analyzers_iterator_ != analyzers_.end());
  int64_t create_stamp;
  do {
    ++analyzers_iterator_;
    if (analyzers_iterator_ == analyzers_.end())
      return nullptr;
  } while (analyzers_iterator_->second->GetProcessId(&create_stamp) !=
               analyzers_iterator_pid_ ||
           create_stamp > analysis_stamp_);
  return analyzers_iterator_->second.get();
}

ThreadActivityAnalyzer* GlobalActivityAnalyzer::GetAnalyzerForThread(
    const ThreadKey& key) {
  auto found = analyzers_.find(key);
  if (found == analyzers_.end())
    return nullptr;
  return found->second.get();
}

ActivityUserData::Snapshot GlobalActivityAnalyzer::GetUserDataSnapshot(
    int64_t pid,
    uint32_t ref,
    uint32_t id) {
  ActivityUserData::Snapshot snapshot;

  void* memory = allocator_->GetAsArray<char>(
      ref, GlobalActivityTracker::kTypeIdUserDataRecord,
      PersistentMemoryAllocator::kSizeAny);
  if (memory) {
    size_t size = allocator_->GetAllocSize(ref);
    const ActivityUserData user_data(memory, size);
    user_data.CreateSnapshot(&snapshot);
    int64_t process_id;
    int64_t create_stamp;
    if (!ActivityUserData::GetOwningProcessId(memory, &process_id,
                                              &create_stamp) ||
        process_id != pid || user_data.id() != id) {
      // This allocation has been overwritten since it was created. Return an
      // empty snapshot because whatever was captured is incorrect.
      snapshot.clear();
    }
  }

  return snapshot;
}

const ActivityUserData::Snapshot&
GlobalActivityAnalyzer::GetProcessDataSnapshot(int64_t pid) {
  auto iter = process_data_.find(pid);
  if (iter == process_data_.end())
    return g_empty_user_data_snapshot.Get();
  if (iter->second.create_stamp > analysis_stamp_)
    return g_empty_user_data_snapshot.Get();
  DCHECK_EQ(pid, iter->second.process_id);
  return iter->second.data;
}

std::vector<std::string> GlobalActivityAnalyzer::GetLogMessages() {
  std::vector<std::string> messages;
  PersistentMemoryAllocator::Reference ref;

  PersistentMemoryAllocator::Iterator iter(allocator_.get());
  while ((ref = iter.GetNextOfType(
              GlobalActivityTracker::kTypeIdGlobalLogMessage)) != 0) {
    const char* message = allocator_->GetAsArray<char>(
        ref, GlobalActivityTracker::kTypeIdGlobalLogMessage,
        PersistentMemoryAllocator::kSizeAny);
    if (message)
      messages.push_back(message);
  }

  return messages;
}

std::vector<GlobalActivityTracker::ModuleInfo>
GlobalActivityAnalyzer::GetModules(int64_t pid) {
  std::vector<GlobalActivityTracker::ModuleInfo> modules;

  PersistentMemoryAllocator::Iterator iter(allocator_.get());
  const GlobalActivityTracker::ModuleInfoRecord* record;
  while (
      (record =
           iter.GetNextOfObject<GlobalActivityTracker::ModuleInfoRecord>()) !=
      nullptr) {
    int64_t process_id;
    int64_t create_stamp;
    if (!OwningProcess::GetOwningProcessId(&record->owner, &process_id,
                                           &create_stamp) ||
        pid != process_id || create_stamp > analysis_stamp_) {
      continue;
    }
    GlobalActivityTracker::ModuleInfo info;
    if (record->DecodeTo(&info, allocator_->GetAllocSize(
                                    allocator_->GetAsReference(record)))) {
      modules.push_back(std::move(info));
    }
  }

  return modules;
}

GlobalActivityAnalyzer::ProgramLocation
GlobalActivityAnalyzer::GetProgramLocationFromAddress(uint64_t address) {
  // TODO(bcwhite): Implement this.
  return { 0, 0 };
}

bool GlobalActivityAnalyzer::IsDataComplete() const {
  DCHECK(allocator_);
  return !allocator_->IsFull();
}

GlobalActivityAnalyzer::UserDataSnapshot::UserDataSnapshot() = default;
GlobalActivityAnalyzer::UserDataSnapshot::UserDataSnapshot(
    const UserDataSnapshot& rhs) = default;
GlobalActivityAnalyzer::UserDataSnapshot::UserDataSnapshot(
    UserDataSnapshot&& rhs) = default;
GlobalActivityAnalyzer::UserDataSnapshot::~UserDataSnapshot() = default;

void GlobalActivityAnalyzer::PrepareAllAnalyzers() {
  // Record the time when analysis started.
  analysis_stamp_ = base::Time::Now().ToInternalValue();

  // Fetch all the records. This will retrieve only ones created since the
  // last run since the PMA iterator will continue from where it left off.
  uint32_t type;
  PersistentMemoryAllocator::Reference ref;
  while ((ref = allocator_iterator_.GetNext(&type)) != 0) {
    switch (type) {
      case GlobalActivityTracker::kTypeIdActivityTracker:
      case GlobalActivityTracker::kTypeIdActivityTrackerFree:
      case GlobalActivityTracker::kTypeIdProcessDataRecord:
      case GlobalActivityTracker::kTypeIdProcessDataRecordFree:
      case PersistentMemoryAllocator::kTypeIdTransitioning:
        // Active, free, or transitioning: add it to the list of references
        // for later analysis.
        memory_references_.insert(ref);
        break;
    }
  }

  // Clear out any old information.
  analyzers_.clear();
  process_data_.clear();
  process_ids_.clear();
  std::set<int64_t> seen_pids;

  // Go through all the known references and create objects for them with
  // snapshots of the current state.
  for (PersistentMemoryAllocator::Reference memory_ref : memory_references_) {
    // Get the actual data segment for the tracker. Any type will do since it
    // is checked below.
    void* const base = allocator_->GetAsArray<char>(
        memory_ref, PersistentMemoryAllocator::kTypeIdAny,
        PersistentMemoryAllocator::kSizeAny);
    const size_t size = allocator_->GetAllocSize(memory_ref);
    if (!base)
      continue;

    switch (allocator_->GetType(memory_ref)) {
      case GlobalActivityTracker::kTypeIdActivityTracker: {
        // Create the analyzer on the data. This will capture a snapshot of the
        // tracker state. This can fail if the tracker is somehow corrupted or
        // is in the process of shutting down.
        std::unique_ptr<ThreadActivityAnalyzer> analyzer(
            new ThreadActivityAnalyzer(base, size));
        if (!analyzer->IsValid())
          continue;
        analyzer->AddGlobalInformation(this);

        // Track PIDs.
        int64_t pid = analyzer->GetProcessId();
        if (seen_pids.find(pid) == seen_pids.end()) {
          process_ids_.push_back(pid);
          seen_pids.insert(pid);
        }

        // Add this analyzer to the map of known ones, indexed by a unique
        // thread
        // identifier.
        DCHECK(!base::ContainsKey(analyzers_, analyzer->GetThreadKey()));
        analyzer->allocator_reference_ = ref;
        analyzers_[analyzer->GetThreadKey()] = std::move(analyzer);
      } break;

      case GlobalActivityTracker::kTypeIdProcessDataRecord: {
        // Get the PID associated with this data record.
        int64_t process_id;
        int64_t create_stamp;
        ActivityUserData::GetOwningProcessId(base, &process_id, &create_stamp);
        DCHECK(!base::ContainsKey(process_data_, process_id));

        // Create a snapshot of the data. This can fail if the data is somehow
        // corrupted or the process shutdown and the memory being released.
        UserDataSnapshot& snapshot = process_data_[process_id];
        snapshot.process_id = process_id;
        snapshot.create_stamp = create_stamp;
        const ActivityUserData process_data(base, size);
        if (!process_data.CreateSnapshot(&snapshot.data))
          break;

        // Check that nothing changed. If it did, forget what was recorded.
        ActivityUserData::GetOwningProcessId(base, &process_id, &create_stamp);
        if (process_id != snapshot.process_id ||
            create_stamp != snapshot.create_stamp) {
          process_data_.erase(process_id);
          break;
        }

        // Track PIDs.
        if (seen_pids.find(process_id) == seen_pids.end()) {
          process_ids_.push_back(process_id);
          seen_pids.insert(process_id);
        }
      } break;
    }
  }

  // Reverse the list of PIDs so that they get popped in the order found.
  std::reverse(process_ids_.begin(), process_ids_.end());
}

}  // namespace debug
}  // namespace base
