// Copyright 2021 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.

#ifdef __Fuchsia__
#include "f2fs.h"

namespace f2fs {

DirEntryCache::DirEntryCache() {
  std::lock_guard lock(lock_);

  slab_allocator_ = std::make_unique<ElementAllocator>(kDirEntryCacheSlabCount, true);
}

DirEntryCache::~DirEntryCache() { Reset(); }

void DirEntryCache::Reset() {
  std::lock_guard lock(lock_);

  map_.clear();
  element_lru_list_.clear();
}

DirEntryCacheElement &DirEntryCache::AllocateElement(ino_t parent_ino,
                                                     std::string_view child_name) {
  ElementRefPtr element = slab_allocator_->New(parent_ino, child_name);
  if (element == nullptr) {
    Evict();
    element = slab_allocator_->New(parent_ino, child_name);
  }

  ZX_ASSERT(element != nullptr);

  map_[GenerateKey(parent_ino, child_name)] = element;

  OnCacheHit(element);

  return *element;
}

void DirEntryCache::DeallocateElement(ElementRefPtr element) {
  map_.erase(GenerateKey(element->GetParentIno(), element->GetName()));

  if (element->InContainer()) {
    element_lru_list_.erase(*element);
  }
}

ElementRefPtr DirEntryCache::FindElementRefPtr(ino_t parent_ino,
                                               std::string_view child_name) const {
  auto search = map_.find(GenerateKey(parent_ino, child_name));
  if (search == map_.end()) {
    return nullptr;
  }

  return search->second;
}

DirEntryCacheElement *DirEntryCache::FindElement(ino_t parent_ino, std::string_view child_name) {
  ElementRefPtr element = FindElementRefPtr(parent_ino, child_name);
  if (element == nullptr) {
    return nullptr;
  }

  OnCacheHit(element);

  return element.get();
}

void DirEntryCache::OnCacheHit(ElementRefPtr &element) {
  if (element->InContainer()) {
    element_lru_list_.erase(*element);
  }
  element_lru_list_.push_front(element);
}

void DirEntryCache::Evict() {
  if (!element_lru_list_.is_empty()) {
    DeallocateElement(element_lru_list_.pop_back());
  }
}

zx::status<DirEntry> DirEntryCache::LookupDirEntry(ino_t parent_ino, std::string_view child_name) {
  if (IsDotOrDotDot(child_name)) {
    return zx::error(ZX_ERR_NOT_SUPPORTED);
  }

  std::lock_guard lock(lock_);

  DirEntryCacheElement *element = FindElement(parent_ino, child_name);
  if (element == nullptr) {
    return zx::error(ZX_ERR_NOT_FOUND);
  }

  // The |element| may be evicted while the caller is using it.
  // Therefore, return copied value rather than reference.
  return zx::ok(element->GetDirEntry());
}

zx::status<pgoff_t> DirEntryCache::LookupDataPageIndex(ino_t parent_ino,
                                                       std::string_view child_name) {
  if (IsDotOrDotDot(child_name)) {
    return zx::error(ZX_ERR_NOT_SUPPORTED);
  }

  std::lock_guard lock(lock_);

  DirEntryCacheElement *element = FindElement(parent_ino, child_name);
  if (element == nullptr) {
    return zx::error(ZX_ERR_NOT_FOUND);
  }

  return zx::ok(element->GetDataPageIndex());
}

void DirEntryCache::AddNewDirEntry(ino_t parent_ino, std::string_view child_name,
                                   DirEntry &dir_entry, pgoff_t data_page_index) {
  DirEntryCacheElement &element = AllocateElement(parent_ino, child_name);

  element.SetDirEntry(dir_entry);
  element.SetDataPageIndex(data_page_index);
}

void DirEntryCache::UpdateDirEntry(ino_t parent_ino, std::string_view child_name,
                                   DirEntry &dir_entry, pgoff_t data_page_index) {
  if (IsDotOrDotDot(child_name)) {
    return;
  }

  std::lock_guard lock(lock_);

  DirEntryCacheElement *element = FindElement(parent_ino, child_name);
  if (element == nullptr) {
    AddNewDirEntry(parent_ino, child_name, dir_entry, data_page_index);
    return;
  }

  element->SetDirEntry(dir_entry);
  element->SetDataPageIndex(data_page_index);
}

void DirEntryCache::RemoveDirEntry(ino_t parent_ino, std::string_view child_name) {
  if (IsDotOrDotDot(child_name)) {
    return;
  }

  std::lock_guard lock(lock_);

  ElementRefPtr element = FindElementRefPtr(parent_ino, child_name);
  if (element != nullptr) {
    DeallocateElement(std::move(element));
  }
}

bool DirEntryCache::IsElementInCache(ino_t parent_ino, std::string_view child_name) const {
  std::lock_guard lock(lock_);
  auto search = map_.find(DirEntryCache::GenerateKey(parent_ino, child_name));
  if (search == map_.end()) {
    return false;
  }
  return true;
}

bool DirEntryCache::IsElementAtHead(ino_t parent_ino, std::string_view child_name) const {
  std::lock_guard lock(lock_);
  if (element_lru_list_.is_empty()) {
    return false;
  }

  auto element = element_lru_list_.begin();
  return (element->GetParentIno() == parent_ino) && (element->GetName() == child_name);
}

const std::map<EntryKey, ElementRefPtr> &DirEntryCache::GetMap() const {
  std::lock_guard lock(lock_);
  return map_;
}

}  // namespace f2fs

#endif  // __Fuchsia__
