/*
 * Copyright (C) 2019 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#include "src/trace_processor/importers/ftrace/rss_stat_tracker.h"

#include "src/trace_processor/importers/common/event_tracker.h"
#include "src/trace_processor/importers/common/process_tracker.h"
#include "src/trace_processor/types/trace_processor_context.h"

#include "protos/perfetto/trace/ftrace/ftrace_event.pbzero.h"
#include "protos/perfetto/trace/ftrace/kmem.pbzero.h"
#include "protos/perfetto/trace/ftrace/synthetic.pbzero.h"

namespace perfetto {
namespace trace_processor {

using FtraceEvent = protos::pbzero::FtraceEvent;

RssStatTracker::RssStatTracker(TraceProcessorContext* context)
    : context_(context) {
  rss_members_.emplace_back(context->storage->InternString("mem.rss.file"));
  rss_members_.emplace_back(context->storage->InternString("mem.rss.anon"));
  rss_members_.emplace_back(context->storage->InternString("mem.swap"));
  rss_members_.emplace_back(context->storage->InternString("mem.rss.shmem"));
  rss_members_.emplace_back(
      context->storage->InternString("mem.unreclaimable"));
  rss_members_.emplace_back(
      context->storage->InternString("mem.unknown"));  // Keep this last.
}

void RssStatTracker::ParseRssStat(int64_t ts,
                                  int32_t field_id,
                                  uint32_t pid,
                                  ConstBytes blob) {
  uint32_t member;
  int64_t size;
  std::optional<bool> curr;
  std::optional<int64_t> mm_id;

  if (field_id == FtraceEvent::kRssStatFieldNumber) {
    protos::pbzero::RssStatFtraceEvent::Decoder rss(blob.data, blob.size);

    member = static_cast<uint32_t>(rss.member());
    size = rss.size();
    if (rss.has_curr()) {
      curr = std::make_optional(static_cast<bool>(rss.curr()));
    }
    if (rss.has_mm_id()) {
      mm_id = std::make_optional(rss.mm_id());
    }

    ParseRssStat(ts, pid, size, member, curr, mm_id);
  } else if (field_id == FtraceEvent::kRssStatThrottledFieldNumber) {
    protos::pbzero::RssStatThrottledFtraceEvent::Decoder rss(blob.data,
                                                             blob.size);

    member = static_cast<uint32_t>(rss.member());
    size = rss.size();
    curr = std::make_optional(static_cast<bool>(rss.curr()));
    mm_id = std::make_optional(rss.mm_id());

    ParseRssStat(ts, pid, size, member, curr, mm_id);
  } else {
    PERFETTO_DFATAL("Unexpected field id");
  }
}

void RssStatTracker::ParseRssStat(int64_t ts,
                                  uint32_t pid,
                                  int64_t size,
                                  uint32_t member,
                                  std::optional<bool> curr,
                                  std::optional<int64_t> mm_id) {
  const auto kRssStatUnknown = static_cast<uint32_t>(rss_members_.size()) - 1;
  if (member >= rss_members_.size()) {
    context_->storage->IncrementStats(stats::rss_stat_unknown_keys);
    member = kRssStatUnknown;
  }

  if (size < 0) {
    context_->storage->IncrementStats(stats::rss_stat_negative_size);
    return;
  }

  std::optional<UniqueTid> utid;
  if (mm_id.has_value() && curr.has_value()) {
    utid = FindUtidForMmId(*mm_id, *curr, pid);
  } else {
    utid = context_->process_tracker->GetOrCreateThread(pid);
  }

  if (utid) {
    context_->event_tracker->PushProcessCounterForThread(
        ts, static_cast<double>(size), rss_members_[member], *utid);
  } else {
    context_->storage->IncrementStats(stats::rss_stat_unknown_thread_for_mm_id);
  }
}

std::optional<UniqueTid> RssStatTracker::FindUtidForMmId(int64_t mm_id,
                                                         bool is_curr,
                                                         uint32_t pid) {
  // If curr is true, we can just overwrite the state in the map and return
  // the utid correspodning to |pid|.
  if (is_curr) {
    UniqueTid utid = context_->process_tracker->GetOrCreateThread(pid);
    mm_id_to_utid_[mm_id] = utid;
    return utid;
  }

  // If curr is false, try and lookup the utid we previously saw for this
  // mm id.
  auto* it = mm_id_to_utid_.Find(mm_id);
  if (!it)
    return std::nullopt;

  // If the utid in the map is the same as our current utid but curr is false,
  // that means we are in the middle of a process changing mm structs (i.e. in
  // the middle of a vfork + exec). Therefore, we should discard the association
  // of this vm struct with this thread.
  const UniqueTid mm_utid = *it;
  const UniqueTid utid = context_->process_tracker->GetOrCreateThread(pid);
  if (mm_utid == utid) {
    mm_id_to_utid_.Erase(mm_id);
    return std::nullopt;
  }

  // Verify that the utid in the map is still alive. This can happen if an mm
  // struct we saw in the past is about to be reused after thread but we don't
  // know the new process that struct will be associated with.
  if (!context_->process_tracker->IsThreadAlive(mm_utid)) {
    mm_id_to_utid_.Erase(mm_id);
    return std::nullopt;
  }

  // This case happens when a process is changing the VM of another process and
  // we know that the utid corresponding to the target process. Just return that
  // utid.
  return mm_utid;
}

}  // namespace trace_processor
}  // namespace perfetto
