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

#ifndef SRC_STORAGE_LIB_VFS_CPP_PSEUDO_DIR_H_
#define SRC_STORAGE_LIB_VFS_CPP_PSEUDO_DIR_H_

#include <fidl/fuchsia.io/cpp/common_types.h>
#include <fidl/fuchsia.io/cpp/natural_types.h>
#include <fidl/fuchsia.io/cpp/wire.h>
#include <lib/fidl/cpp/wire/channel.h>
#include <zircon/compiler.h>
#include <zircon/types.h>

#include <cstddef>
#include <cstdint>
#include <memory>
#include <string_view>

#include <fbl/intrusive_container_utils.h>
#include <fbl/intrusive_wavl_tree.h>
#include <fbl/macros.h>
#include <fbl/ref_ptr.h>
#include <fbl/string.h>

#include "src/storage/lib/vfs/cpp/vfs_types.h"
#include "src/storage/lib/vfs/cpp/vnode.h"
#include "src/storage/lib/vfs/cpp/watcher.h"

namespace fs {

// A pseudo-directory is a directory-like object whose entries are constructed by a program at
// runtime.  The client can lookup, enumerate, and watch these directory entries but it cannot
// create, remove, or rename them.
//
// This class is designed to allow programs to publish a relatively small number of entries (up to a
// few dozen) such as services, file-system roots, debugging pseudo-files, or other vnodes.  It is
// not suitable for very large directories (hundreds of entries).
//
// This class is thread-safe.
class PseudoDir : public Vnode {
 public:
  // Construct with fbl::MakeRefCounted.

  // Adds a directory entry associating the given |name| with |vn|. It is ok to add the same Vnode
  // multiple times with different names.
  //
  // Returns |ZX_OK| on success.
  // Returns |ZX_ERR_ALREADY_EXISTS| if there is already a node with the given name.
  zx_status_t AddEntry(fbl::String name, fbl::RefPtr<fs::Vnode> vn);

  // Removes a directory entry with the given |name|.
  //
  // Returns |ZX_OK| on success.
  // Returns |ZX_ERR_NOT_FOUND| if there is no node with the given name.
  zx_status_t RemoveEntry(std::string_view name);

  // An extension of |RemoveEntry| which additionally verifies
  // that the target vnode is |vn|.
  //
  // Returns |ZX_OK| on success.
  // Returns |ZX_ERR_NOT_FOUND| if there is no node with the given name/vn pair.
  zx_status_t RemoveEntry(std::string_view name, fs::Vnode* vn);

  // Removes all directory entries.
  void RemoveAllEntries();

  // Checks if directory is empty. Be careful while using this function if using this Dir in
  // multiple threads.
  bool IsEmpty() const;

  // Returns true if there are watchers.
  bool HasWatchers() const { return watcher_.HasWatchers(); }

  // |Vnode| implementation:
  fuchsia_io::NodeProtocolKinds GetProtocols() const final;
  fuchsia_io::Abilities GetAbilities() const final;
  zx_status_t Lookup(std::string_view name, fbl::RefPtr<fs::Vnode>* out) override;
  void Notify(std::string_view name, fuchsia_io::wire::WatchEvent event) final;
  zx_status_t WatchDir(fs::FuchsiaVfs* vfs, fuchsia_io::wire::WatchMask mask, uint32_t options,
                       fidl::ServerEnd<fuchsia_io::DirectoryWatcher> watcher) final;
  zx_status_t Readdir(VdirCookie* cookie, void* dirents, size_t len, size_t* out_actual) final;

 private:
  friend fbl::internal::MakeRefCountedHelper<PseudoDir>;
  friend fbl::RefPtr<PseudoDir>;

  static constexpr uint64_t kDotId = 1u;

  struct IdTreeTag {};
  struct NameTreeTag {};

  class Entry : public fbl::ContainableBaseClasses<
                    fbl::TaggedWAVLTreeContainable<std::unique_ptr<Entry>, IdTreeTag,
                                                   fbl::NodeOptions::AllowMultiContainerUptr>,
                    fbl::TaggedWAVLTreeContainable<Entry*, NameTreeTag,
                                                   fbl::NodeOptions::AllowClearUnsafe>> {
   public:
    Entry(uint64_t id, fbl::String name, fbl::RefPtr<fs::Vnode> node);
    ~Entry();

    uint64_t id() const { return id_; }
    const fbl::String& name() const { return name_; }
    const fbl::RefPtr<fs::Vnode>& node() const { return node_; }

   private:
    uint64_t const id_;
    fbl::String name_;
    fbl::RefPtr<fs::Vnode> node_;
  };

  struct KeyByIdTraits {
    static uint64_t GetKey(const Entry& entry) { return entry.id(); }
    static bool LessThan(uint64_t key1, uint64_t key2) { return key1 < key2; }
    static bool EqualTo(uint64_t key1, uint64_t key2) { return key1 == key2; }
  };

  struct KeyByNameTraits {
    static fbl::String GetKey(const Entry& entry) { return entry.name(); }
    static bool LessThan(const fbl::String& key1, const fbl::String& key2) { return key1 < key2; }
    static bool EqualTo(const fbl::String& key1, const fbl::String& key2) { return key1 == key2; }
  };

  using EntryByIdMap =
      fbl::TaggedWAVLTree<uint64_t, std::unique_ptr<Entry>, IdTreeTag, KeyByIdTraits>;
  using EntryByNameMap = fbl::TaggedWAVLTree<fbl::String, Entry*, NameTreeTag, KeyByNameTraits>;

 protected:
  // Creates a directory which is initially empty.
  PseudoDir();

  // Destroys the directory and releases the nodes it contains.
  ~PseudoDir() override;

 private:
  uint64_t next_node_id_ __TA_GUARDED(mutex_) = kDotId + 1;
  EntryByIdMap entries_by_id_ __TA_GUARDED(mutex_);
  EntryByNameMap entries_by_name_ __TA_GUARDED(mutex_);

  fs::WatcherContainer watcher_;  // note: uses its own internal mutex

  DISALLOW_COPY_ASSIGN_AND_MOVE(PseudoDir);
};

}  // namespace fs

#endif  // SRC_STORAGE_LIB_VFS_CPP_PSEUDO_DIR_H_
