// Copyright 2019 The Fuchsia 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 "src/developer/memory/metrics/digest.h"

#include <regex>

#include <trace/event.h>

namespace memory {

const std::vector<const BucketMatch> Digester::kDefaultBucketMatches = {
    {"ZBI Buffer", ".*", "uncompressed-bootfs"},
    {"Graphics", ".*", "magma_create_buffer"},
    {"Video Buffer", "driver_host:sys", "Sysmem.*"},
    {"Fshost", "fshost.cm", ".*"},
    {"Minfs", ".*minfs", ".*"},
    {"Blobfs", ".*blobfs", ".*"},
    {"Flutter", "io\\.flutter\\..*", ".*"},
    {"Web", "web_engine_exe:.*|chromium.cmx", ".*"},
    {"Kronk", "kronk.cmx|kronk_for_testing.cmx", ".*"},
    {"Scenic", "scenic.cmx", ".*"},
    {"Amlogic", "driver_host:pdev:05:00:f", ".*"},
    {"Netstack", "netstack.cmx", ".*"},
    {"Amber", "amber.cmx", ".*"},
    {"Pkgfs", "pkgfs", ".*"},
    {"Cast", "cast_agent.cmx", ".*"},
    {"Archivist", "archivist.cmx", ".*"},
    {"Cobalt", "cobalt.cmx", ".*"},
    {"Audio", "audio_core.cmx", ".*"},
    {"Context", "context_provider.cmx", ".*"},
};

BucketMatch::BucketMatch(const std::string& name, const std::string& process,
                         const std::string& vmo)
    : name_(name), process_(process), vmo_(vmo) {}

bool BucketMatch::ProcessMatch(const std::string& process) {
  const auto& pi = process_match_.find(process);
  if (pi != process_match_.end()) {
    return pi->second;
  }
  bool match = std::regex_match(process, process_);
  process_match_.emplace(process, match);
  return match;
}

bool BucketMatch::VmoMatch(const std::string& vmo) {
  const auto& vi = vmo_match_.find(vmo);
  if (vi != vmo_match_.end()) {
    return vi->second;
  }
  bool match = std::regex_match(vmo, vmo_);
  vmo_match_.emplace(vmo, match);
  return match;
}

Digest::Digest(const Capture& capture, Digester* digester) { digester->Digest(capture, this); }

Digester::Digester(const std::vector<const BucketMatch>& bucket_matches) {
  for (const auto& bucket_match : bucket_matches) {
    bucket_matches_.emplace_back(bucket_match);
  }
}

void Digester::Digest(const Capture& capture, class Digest* digest) {
  TRACE_DURATION("memory_metrics", "Digester::Digest");
  digest->time_ = capture.time();
  digest->undigested_vmos_.reserve(capture.koid_to_vmo().size());
  for (const auto& pair : capture.koid_to_vmo()) {
    digest->undigested_vmos_.emplace(pair.first);
  }

  digest->buckets_.reserve(bucket_matches_.size());
  for (auto& bucket_match : bucket_matches_) {
    auto& bucket = digest->buckets_.emplace_back(bucket_match.name(), 0);
    for (const auto& pair : capture.koid_to_process()) {
      const auto& process = pair.second;

      if (!bucket_match.ProcessMatch(process.name)) {
        continue;
      }
      for (const auto& v : process.vmos) {
        if (digest->undigested_vmos_.count(v) == 0) {
          continue;
        }
        const auto& vmo = capture.vmo_for_koid(v);
        if (!bucket_match.VmoMatch(vmo.name)) {
          continue;
        }
        bucket.size_ += vmo.committed_bytes;
        digest->undigested_vmos_.erase(v);
      }
    }
  }

  std::sort(digest->buckets_.begin(), digest->buckets_.end(),
            [](const Bucket& a, const Bucket& b) { return a.size() > b.size(); });
  uint64_t undigested_size = 0;
  for (auto v : digest->undigested_vmos_) {
    undigested_size += capture.vmo_for_koid(v).committed_bytes;
  }
  if (undigested_size > 0) {
    digest->buckets_.emplace_back("Undigested", undigested_size);
  }

  const auto& kmem = capture.kmem();
  if (kmem.total_bytes > 0) {
    uint64_t vmo_size = 0;
    for (const auto& bucket : digest->buckets_) {
      vmo_size += bucket.size_;
    }
    if (vmo_size < kmem.vmo_bytes) {
      digest->buckets_.emplace_back("Orphaned", kmem.vmo_bytes - vmo_size);
    }
    digest->buckets_.emplace_back("Kernel", kmem.wired_bytes + kmem.total_heap_bytes +
                                                kmem.mmu_overhead_bytes + kmem.ipc_bytes +
                                                kmem.other_bytes);
    digest->buckets_.emplace_back("Free", kmem.free_bytes);
  }
}

}  // namespace memory
