// Copyright 2017 Google Inc. 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
