// Copyright 2017 The Cobalt Authors. All Rights Reserved.
//
// 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 "cobalt/browser/memory_tracker/tool/malloc_logger_tool.h"

#include <algorithm>

#include "base/time.h"
#include "cobalt/base/c_val.h"
#include "cobalt/browser/memory_tracker/tool/buffered_file_writer.h"
#include "cobalt/browser/memory_tracker/tool/params.h"
#include "cobalt/browser/memory_tracker/tool/util.h"
#include "nb/memory_scope.h"
#include "starboard/atomic.h"
#include "starboard/string.h"
#include "starboard/types.h"

namespace cobalt {
namespace browser {
namespace memory_tracker {

namespace {
const int kAllocationRecord = 1;
const int kDeallocationRecord = 0;
const size_t kStartIndex = 5;
const size_t kNumAddressPrints = 2;
const size_t kMaxStackSize = 10;
const size_t kRecordLimit = 1024;
const NbMemoryScopeInfo kEmptyCallstackMemoryScopeInfo = {nullptr,
  "-", "-", 0, "-", true};
}  // namespace

MallocLoggerTool::MallocLoggerTool() : start_time_(NowTime()),
  atomic_counter_(0),
  atomic_used_memory_(SbSystemGetUsedCPUMemory()) {
    buffered_file_writer_.reset(new BufferedFileWriter(MemoryLogPath()));
}

MallocLoggerTool::~MallocLoggerTool() {
  // No locks are used for the thread reporter, so when it's set to null
  // we allow one second for any suspended threads to run through and finish
  // their reporting.
  SbMemorySetReporter(NULL);
  SbThreadSleep(kSbTimeSecond);
  buffered_file_writer_.reset(NULL);
}

std::string MallocLoggerTool::tool_name() const {
  return "MemoryTrackerMallocLogger";
}

void MallocLoggerTool::Run(Params* params) {
  // Update malloc stats every second
  params->logger()->Output("MemoryTrackerMallocLogger running...");

  // There are some memory allocations which do not get tracked.
  // Those allocations show up as fragmentation.
  // It has been empirically observed that a majority (98%+) of these
  // untracked allocations happen in the first 20 seconds of Cobalt runtime.
  //
  // Also, there is minimal external fragmentation (< 1 MB) during this initial
  // period.
  //
  // The following piece of code resets atomic_used_memory_ at the 20 second
  // mark, to compensate for the deviation due to untracked memory.
  base::TimeDelta current_sample_interval =
      base::TimeDelta::FromSeconds(20);
  if (!params->wait_for_finish_signal(current_sample_interval.ToSbTime())) {
    atomic_used_memory_.store(SbSystemGetUsedCPUMemory());
  }

  // Export fragmentation as a CVal on HUD.
  base::CVal<base::cval::SizeInBytes> memory_fragmentation(
      "Memory.CPU.Fragmentation", base::cval::SizeInBytes(0),
      "Memory Fragmentation");

  // Update CVal every 5 seconds
  current_sample_interval = base::TimeDelta::FromSeconds(5);
  int64_t allocated_memory = 0;
  int64_t used_memory = 0;
  while (!params->wait_for_finish_signal(current_sample_interval.ToSbTime())) {
    allocated_memory = SbSystemGetUsedCPUMemory();
    used_memory = atomic_used_memory_.load();
    memory_fragmentation = static_cast<uint64>(
        std::max(allocated_memory - used_memory, static_cast<int64_t>(0)));
  }
}

void MallocLoggerTool::LogRecord(const void* memory_block,
    const nb::analytics::AllocationRecord& record,
    const nb::analytics::CallStack& callstack, int type) {
  const int log_counter = atomic_counter_.increment();
  const int64_t used_memory = atomic_used_memory_.load();
  const int64_t allocated_memory = SbSystemGetUsedCPUMemory();
  const int time_since_start_ms = GetTimeSinceStartMs();
  char buff[kRecordLimit] = {0};
  size_t buff_pos = 0;
  void* addresses[kMaxStackSize];

  const NbMemoryScopeInfo* memory_scope;
  if (callstack.empty()) {
    memory_scope = &kEmptyCallstackMemoryScopeInfo;
  } else {
    memory_scope = callstack.back();
  }

  int bytes_written = SbStringFormatF(buff, sizeof(buff),
    "%u,%d,%zd,\"%s\",%d,%s,%d,%" PRId64 ",%" PRId64 ",%" PRIXPTR ",\"",
    log_counter, type, record.size, memory_scope->file_name_,
    memory_scope->line_number_, memory_scope->function_name_,
    time_since_start_ms, allocated_memory, used_memory,
    reinterpret_cast<uintptr_t>(memory_block));

  buff_pos += static_cast<size_t>(bytes_written);
  const size_t count = std::max(SbSystemGetStack(addresses, kMaxStackSize), 0);
  const size_t end_index = std::min(count, kStartIndex + kNumAddressPrints);
  // For each of the stack addresses that we care about, concat them to the
  // buffer. This was originally written to do multiple stack addresses but
  // this tends to overflow on some lower platforms so it's possible that
  // this loop only iterates once.
  for (size_t i = kStartIndex; i < end_index; ++i) {
    void* p = addresses[i];
    bytes_written =
        SbStringFormatF(buff + buff_pos, kRecordLimit - buff_pos,
                        ",%" PRIXPTR "", reinterpret_cast<uintptr_t>(p));
    DCHECK_GE(bytes_written, 0);
    buff_pos += static_cast<size_t>(bytes_written);
  }

  // Adds a "\n" at the end.
  bytes_written = SbStringConcat(buff + buff_pos, "\"\n",
                                 static_cast<int>(kRecordLimit - buff_pos));
  buff_pos += bytes_written;
  buffered_file_writer_->Append(buff, buff_pos);
}

void MallocLoggerTool::OnMemoryAllocation(
    const void* memory_block, const nb::analytics::AllocationRecord& record,
    const nb::analytics::CallStack& callstack) {
  atomic_used_memory_.fetch_add(record.size);
  LogRecord(memory_block, record, callstack, kAllocationRecord);
}

void MallocLoggerTool::OnMemoryDeallocation(
    const void* memory_block, const nb::analytics::AllocationRecord& record,
    const nb::analytics::CallStack& callstack) {
  atomic_used_memory_.fetch_sub(record.size);
  LogRecord(memory_block, record, callstack, kDeallocationRecord);
}

std::string MallocLoggerTool::MemoryLogPath() {
  char file_name_buff[2048] = {};
  SbSystemGetPath(kSbSystemPathDebugOutputDirectory, file_name_buff,
                  arraysize(file_name_buff));
  std::string path(file_name_buff);
  if (!path.empty()) {  // Protect against a dangling "/" at end.
    const int back_idx_signed = static_cast<int>(path.length()) - 1;
    if (back_idx_signed >= 0) {
      const size_t idx = back_idx_signed;
      if (path[idx] == '/') {
        path.erase(idx);
      }
    }
  }

  base::Time time = base::Time::Now();
  base::Time::Exploded exploded;
  time.LocalExplode(&exploded);

  std::stringstream ss;
  ss << "/memory_log_" << exploded.year << "-"
     << exploded.month << "-" << exploded.day_of_month << ":"
     << exploded.hour << "-" << exploded.minute << "-" << exploded.second
     << ".csv";
  path.append(ss.str());
  return path;
}

base::TimeTicks MallocLoggerTool::NowTime() {
  // NowFromSystemTime() is slower but more accurate. However it might
  // be useful to use the faster but less accurate version if there is
  // a speedup.
  return base::TimeTicks::Now();
}

int MallocLoggerTool::GetTimeSinceStartMs() const {
  base::TimeDelta dt = NowTime() - start_time_;
  return static_cast<int>(dt.InMilliseconds());
}

}  // namespace memory_tracker
}  // namespace browser
}  // namespace cobalt
