/*
 * Copyright 2016 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 "nb/analytics/memory_tracker_helpers.h"

#include <stdint.h>
#include <vector>

#include "nb/hash.h"
#include "starboard/configuration.h"
#include "starboard/log.h"

namespace nb {
namespace analytics {

AllocationGroup::AllocationGroup(const std::string& name)
    : name_(name), allocation_bytes_(0), num_allocations_(0) {
}

AllocationGroup::~AllocationGroup() {}

void AllocationGroup::AddAllocation(int64_t num_bytes) {
  if (num_bytes == 0)
    return;
  int num_alloc_diff = num_bytes > 0 ? 1 : -1;
  allocation_bytes_.fetch_add(num_bytes);
  num_allocations_.fetch_add(num_alloc_diff);
}

void AllocationGroup::GetAggregateStats(int32_t* num_allocs,
                                        int64_t* allocation_bytes) const {
  *num_allocs = num_allocations_.load();
  *allocation_bytes = allocation_bytes_.load();
}

int64_t AllocationGroup::allocation_bytes() const {
  return allocation_bytes_.load();
}

int32_t AllocationGroup::num_allocations() const {
  return num_allocations_.load();
}

AtomicStringAllocationGroupMap::AtomicStringAllocationGroupMap() {
  unaccounted_group_ = Ensure("Unaccounted");
}

AtomicStringAllocationGroupMap::~AtomicStringAllocationGroupMap() {
  unaccounted_group_ = NULL;
  while (!group_map_.empty()) {
    Map::iterator it = group_map_.begin();
    delete it->second;
    group_map_.erase(it);
  }
}

AllocationGroup* AtomicStringAllocationGroupMap::Ensure(
    const std::string& name) {
  starboard::ScopedLock lock(mutex_);
  Map::const_iterator found_it = group_map_.find(name);
  if (found_it != group_map_.end()) {
    return found_it->second;
  }
  AllocationGroup* group = new AllocationGroup(name);
  group_map_[name] = group;
  return group;
}

AllocationGroup* AtomicStringAllocationGroupMap::GetDefaultUnaccounted() {
  return unaccounted_group_;
}

bool AtomicStringAllocationGroupMap::Erase(const std::string& name) {
  starboard::ScopedLock lock(mutex_);
  Map::iterator found_it = group_map_.find(name);
  if (found_it == group_map_.end()) {
    // Didn't find it.
    return false;
  }
  group_map_.erase(found_it);
  return true;
}

void AtomicStringAllocationGroupMap::GetAll(
    std::vector<const AllocationGroup*>* output) const {
  starboard::ScopedLock lock(mutex_);
  for (Map::const_iterator it = group_map_.begin(); it != group_map_.end();
       ++it) {
    output->push_back(it->second);
  }
}

void AllocationGroupStack::Push(AllocationGroup* group) {
  alloc_group_stack_.push_back(group);
}

void AllocationGroupStack::Pop() {
  alloc_group_stack_.pop_back();
}

AllocationGroup* AllocationGroupStack::Peek() {
  if (alloc_group_stack_.empty()) {
    return NULL;
  }
  return alloc_group_stack_.back();
}

const AllocationGroup* AllocationGroupStack::Peek() const {
  if (alloc_group_stack_.empty()) {
    return NULL;
  }
  return alloc_group_stack_.back();
}

AtomicAllocationMap::AtomicAllocationMap() {}

AtomicAllocationMap::~AtomicAllocationMap() {}

bool AtomicAllocationMap::Add(const void* memory,
                              const AllocationRecord& alloc_record) {
  starboard::ScopedLock lock(mutex_);
  const bool inserted =
      pointer_map_.insert(std::make_pair(memory, alloc_record)).second;
  return inserted;
}

bool AtomicAllocationMap::Get(const void* memory,
                              AllocationRecord* alloc_record) const {
  starboard::ScopedLock lock(mutex_);
  PointerMap::const_iterator found_it = pointer_map_.find(memory);
  if (found_it == pointer_map_.end()) {
    if (alloc_record) {
      *alloc_record = AllocationRecord::Empty();
    }
    return false;
  }
  if (alloc_record) {
    *alloc_record = found_it->second;
  }
  return true;
}

bool AtomicAllocationMap::Remove(const void* memory,
                                 AllocationRecord* alloc_record) {
  starboard::ScopedLock lock(mutex_);
  PointerMap::iterator found_it = pointer_map_.find(memory);

  if (found_it == pointer_map_.end()) {
    if (alloc_record) {
      *alloc_record = AllocationRecord::Empty();
    }
    return false;
  }
  if (alloc_record) {
    *alloc_record = found_it->second;
  }
  pointer_map_.erase(found_it);
  return true;
}

bool AtomicAllocationMap::Accept(AllocationVisitor* visitor) const {
  starboard::ScopedLock lock(mutex_);
  for (PointerMap::const_iterator it = pointer_map_.begin();
       it != pointer_map_.end(); ++it) {
    const void* memory = it->first;
    const AllocationRecord& alloc_rec = it->second;
    if (!visitor->Visit(memory, alloc_rec)) {
      return false;
    }
  }
  return true;
}

size_t AtomicAllocationMap::Size() const {
  starboard::ScopedLock lock(mutex_);
  return pointer_map_.size();
}

bool AtomicAllocationMap::Empty() const {
  starboard::ScopedLock lock(mutex_);
  return pointer_map_.empty();
}

void AtomicAllocationMap::Clear() {
  starboard::ScopedLock lock(mutex_);
  for (PointerMap::iterator it = pointer_map_.begin();
       it != pointer_map_.end(); ++it) {
    const AllocationRecord& rec = it->second;
    AllocationGroup* group = rec.allocation_group;
    const int64_t size = static_cast<int64_t>(rec.size);
    group->AddAllocation(-size);
  }
  return pointer_map_.clear();
}

ConcurrentAllocationMap::ConcurrentAllocationMap() : pointer_map_array_() {}

ConcurrentAllocationMap::~ConcurrentAllocationMap() {
  Clear();
}

bool ConcurrentAllocationMap::Add(const void* memory,
                                  const AllocationRecord& alloc_record) {
  AtomicAllocationMap& map = GetMapForPointer(memory);
  return map.Add(memory, alloc_record);
}

bool ConcurrentAllocationMap::Get(const void* memory,
                                  AllocationRecord* alloc_record) const {
  const AtomicAllocationMap& map = GetMapForPointer(memory);
  return map.Get(memory, alloc_record);
}

bool ConcurrentAllocationMap::Remove(const void* memory,
                                     AllocationRecord* alloc_record) {
  AtomicAllocationMap& map = GetMapForPointer(memory);
  bool output = map.Remove(memory, alloc_record);
  return output;
}

size_t ConcurrentAllocationMap::Size() const {
  size_t size = 0;
  for (int i = 0; i < kNumElements; ++i) {
    const AtomicAllocationMap& map = pointer_map_array_[i];
    size += map.Size();
  }
  return size;
}

bool ConcurrentAllocationMap::Empty() const {
  return 0 == Size();
}

void ConcurrentAllocationMap::Clear() {
  for (int i = 0; i < kNumElements; ++i) {
    AtomicAllocationMap& map = pointer_map_array_[i];
    map.Clear();
  }
}

bool ConcurrentAllocationMap::Accept(AllocationVisitor* visitor) const {
  for (int i = 0; i < kNumElements; ++i) {
    const AtomicAllocationMap& map = pointer_map_array_[i];
    if (!map.Accept(visitor)) {
      return false;  // Early out.
    }
  }
  return true;
}

uint32_t ConcurrentAllocationMap::hash_ptr(const void* ptr) {
  uintptr_t val = reinterpret_cast<uintptr_t>(ptr);
  return RuntimeHash32(reinterpret_cast<const char*>(&val), sizeof(val));
}

int ConcurrentAllocationMap::ToIndex(const void* ptr) const {
  SB_DCHECK(0 != kNumElements);
  uint32_t hash_val = hash_ptr(ptr);
  int index = hash_val % kNumElements;
  return index;
}

AtomicAllocationMap& ConcurrentAllocationMap::GetMapForPointer(
    const void* ptr) {
  return pointer_map_array_[ToIndex(ptr)];
}

const AtomicAllocationMap& ConcurrentAllocationMap::GetMapForPointer(
    const void* ptr) const {
  return pointer_map_array_[ToIndex(ptr)];
}

}  // namespace analytics
}  // namespace nb
