// Copyright 2019 The Chromium OS Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "smbfs/inode_map.h"

#include <utility>

#include <base/logging.h>
#include <base/stl_util.h>

namespace smbfs {

struct InodeMap::Entry {
  Entry(ino_t inode, const base::FilePath& path) : inode(inode), path(path) {}
  ~Entry() = default;

  uint64_t refcount = 0;

  const ino_t inode;
  base::FilePath path;

 private:
  DISALLOW_IMPLICIT_CONSTRUCTORS(Entry);
};

InodeMap::InodeMap(ino_t root_inode)
    : root_inode_(root_inode), seq_num_(root_inode + 1) {
  DCHECK(root_inode_);

  // Insert an entry for the root inode.
  std::unique_ptr<Entry> entry =
      std::make_unique<Entry>(root_inode, base::FilePath("/"));
  entry->refcount = 1;
  files_.emplace("/", entry.get());
  inodes_.emplace(root_inode, std::move(entry));
}

InodeMap::~InodeMap() = default;

InodeMap::Entry* InodeMap::GetEntryByPath(const base::FilePath& path) {
  CHECK(!path.empty());
  CHECK(path.IsAbsolute());
  CHECK(!path.ReferencesParent());

  const auto it = files_.find(path.value());
  if (it != files_.end()) {
    return it->second;
  }

  DCHECK(!base::Contains(inodes_, seq_num_));

  ino_t inode = seq_num_++;
  CHECK(inode) << "Inode wrap around";
  std::unique_ptr<Entry> entry = std::make_unique<Entry>(inode, path);
  Entry* raw_entry = entry.get();
  files_.emplace(path.value(), raw_entry);
  inodes_.emplace(inode, std::move(entry));
  return raw_entry;
}

ino_t InodeMap::GetWeakInode(const base::FilePath& path) {
  Entry* entry = GetEntryByPath(path);
  return entry->inode;
}

ino_t InodeMap::IncInodeRef(const base::FilePath& path) {
  Entry* entry = GetEntryByPath(path);
  entry->refcount++;
  CHECK(entry->refcount) << "Refcount wrap around";
  return entry->inode;
}

base::FilePath InodeMap::GetPath(ino_t inode) const {
  const auto it = inodes_.find(inode);
  if (it == inodes_.end() || it->second->refcount == 0) {
    return {};
  }
  return it->second->path;
}

bool InodeMap::PathExists(const base::FilePath& path) const {
  auto it = files_.find(path.value());
  return it != files_.end() && it->second->refcount > 0;
}

void InodeMap::UpdatePath(ino_t inode, const base::FilePath& new_path) {
  CHECK_NE(inode, root_inode_);
  CHECK(!new_path.empty());
  CHECK(new_path.IsAbsolute());
  CHECK(!new_path.ReferencesParent());
  DCHECK(!PathExists(new_path));

  const auto it = inodes_.find(inode);
  CHECK(it != inodes_.end());
  CHECK_GT(it->second->refcount, 0);

  const base::FilePath old_path = it->second->path;
  it->second->path = new_path;

  files_.erase(old_path.value());
  files_.emplace(new_path.value(), it->second.get());
}

bool InodeMap::Forget(ino_t inode, uint64_t forget_count) {
  if (inode == root_inode_) {
    // Ignore the root inode.
    return false;
  }

  const auto it = inodes_.find(inode);
  CHECK(it != inodes_.end());

  Entry* entry = it->second.get();
  CHECK_GE(entry->refcount, forget_count);
  entry->refcount -= forget_count;
  if (entry->refcount > 0) {
    return false;
  }
  size_t removed = files_.erase(entry->path.value());
  DCHECK_EQ(removed, 1);
  inodes_.erase(it);
  return true;
}

}  // namespace smbfs
