// Copyright 2020 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_LIB_VMO_STORE_OWNED_VMO_STORE_H_
#define SRC_LIB_VMO_STORE_OWNED_VMO_STORE_H_

#include <lib/zx/vmo.h>

#include "vmo_store.h"

namespace vmo_store {

// A `VmoStore` that may only be accessed through a `RegistrationAgent`.
//
// `OwnedVmoStore` composes with `VmoStore` to provide a wrapper that only allows access to the
// registered VMOs through the creation of `RegistrationAgent`s.
//
// `Backing` is the data structure used to store the registered VMOs. It must implement
// `AbstractStorage`.
//
// Example usage:
// ```
//   using namespace vmo_store;
//   // Declaring our types first.
//   // `MyKey` is the key type that is used to register and retrieve VMOs from a VmoStore.
//   using MyKey = size_t;
//   // `MyMeta` is extra user metadata associated with every stored VMO (can be `void`).
//   using MyMeta = std::string;
//   // Declare our store alias, we're using `HashTableStorage` in this example.
//   // See `storage_types.h` for other Backing storage types.
//   using MyOwnedVmoStore = OwnedVmoStore<HashTableStorage<MyKey, MyMeta>>;
//   MyOwnedVmoStore store(Options{...});
//
//   // Declare a registration agent for it. The agent provides a view into the store.
//   MyOwnedVmoStore::RegistrationAgent agent = store.CreateRegistrationAgent();
//
//   // Now let's register, retrieve, and unregister a `zx::vmo` obtained through `GetVmo()`.
//   // The second argument to `Register` is our user metadata.
//   fit::result<size_t, zx_status_t> result = agent.Register(GetVmo(), "my first VMO");
//   size_t key = result.take_value();
//   auto * my_registered_vmo = agent.GetVmo(key);
//
//   // Print metadata associated with VMO.
//   std::cout << "Got Vmo called " << my_registered_vmo->meta() << std::endl;
//   // see `stored_vmo.h` for other `StoredVmo` methods, like retrieving mapped or pinned memory.
//
//   // A different agent will not have access to the same VMO using the key.
//   MyVmoStore::RegistrationAgent other_agent = store.CreateRegistrationAgent();
//   ZX_ASSERT(other_agent.GetVmo(key) == nullptr, "no soup for other_agent");
//
//   // Finally, unregister the VMO, which will discard the VMO handle along with any mapping or
//   // pinning. Destroying the agent without unregistering all its VMOs will cause a crash.
//   agent.Unregister(key);
// ```
template <typename Backing>
class OwnedVmoStore : public VmoStoreBase<VmoStore<Backing>> {
 public:
  template <typename... StoreArgs>
  explicit OwnedVmoStore(StoreArgs... store_args)
      : VmoStoreBase<VmoStore<Backing>>(std::forward<StoreArgs>(store_args)...) {}

  class RegistrationAgent;

  // Creates a `RegistrationAgent` attached to this `OwnedVmoStore`.
  // The returned agent may not outlive this `OwnedVmoStore`.
  RegistrationAgent CreateRegistrationAgent() { return RegistrationAgent(this); }

  DISALLOW_COPY_ASSIGN_AND_MOVE(OwnedVmoStore);

  // An agent which owns VMOs in an `OwnedVmoStore`.
  //
  // `RegistrationAgent` serves as the registration point for VMOs stored in an `OwnedVmoStore`.
  // A `RegistrationAgent` provides runtime guardrails so that multiple agents can use the same
  // store, but they can't access each other's VMOs.
  //
  // Destroying a `RegistrationAgent` without first unregistering all the VMOs that it registered is
  // invalid, and causes the program to crash.
  //
  // Note that `RegistrationAgent` does not provide any thread-safety guarantees, users must provide
  // their own locking mechanisms to ensure that different `RegistrationAgent`s can't compete across
  // threads, taking into account the chosen `Backing` method for the `OwnedVmoStore`.
  class RegistrationAgent : internal::VmoOwner {
   public:
    using VmoStore = ::vmo_store::VmoStore<Backing>;
    using StoredVmo = typename VmoStore::StoredVmo;

    // Creates a `RegistrationAgent` attached to `store`.
    //
    // `RegistrationAgent` may not outlive `store`.
    explicit RegistrationAgent(OwnedVmoStore<Backing>* store)
        : store_(&store->impl_), registration_count_(0) {}
    ~RegistrationAgent() {
      size_t registered = registration_count_;
      ZX_ASSERT_MSG(registered == 0,
                    "Attempted to destroy a RegistrationAgent with %ld registered VMOs",
                    registered);
    }

    // Same as `VmoStore::Register`, but the registered VMO is only accessible through this
    // `RegistrationAgent`.
    template <typename... MetaArgs>
    fit::result<typename VmoStore::Key, zx_status_t> Register(zx::vmo vmo, MetaArgs... vmo_args) {
      auto result =
          store_->Register(CreateStore(std::move(vmo), std::forward<MetaArgs>(vmo_args)...));
      if (result.is_ok()) {
        registration_count_++;
      }
      return result;
    }

    // Same as `VmoStore::RegisterWithKey`, but the registered VMO is only accessible through this
    // `RegistrationAgent`.
    template <typename... MetaArgs>
    zx_status_t RegisterWithKey(typename VmoStore::Key key, zx::vmo vmo, MetaArgs... vmo_args) {
      zx_status_t result = store_->RegisterWithKey(
          std::move(key), CreateStore(std::move(vmo), std::forward<MetaArgs>(vmo_args)...));
      if (result == ZX_OK) {
        registration_count_++;
      }
      return result;
    }

    // Same as `VmoStore::Unregister`, but unregistration fails with `ZX_ERR_ACCESS_DENIED` if the
    // VMO was not initially registered by this `RegistrationAgent`.
    zx_status_t Unregister(typename VmoStore::Key key) {
      auto* vmo = store_->GetVmo(key);
      if (vmo && GetOwner(*vmo) != this) {
        return ZX_ERR_ACCESS_DENIED;
      }
      zx_status_t status = store_->Unregister(std::move(key));
      if (status == ZX_OK) {
        registration_count_--;
      }
      return status;
    }

    // Same as `VmoStore::GetVmo`, but only returns non-null if the VMO referenced by `key` was
    // originally registered by this `RegistrationAgent`.
    StoredVmo* GetVmo(const typename VmoStore::Key& key) {
      auto* vmo = store_->GetVmo(key);
      if (vmo && GetOwner(*vmo) == this) {
        return vmo;
      }
      return nullptr;
    }

    DISALLOW_COPY_ASSIGN_AND_MOVE(RegistrationAgent);

   private:
    template <typename... MetaArgs>
    StoredVmo CreateStore(zx::vmo vmo, MetaArgs... vmo_args) {
      StoredVmo stored_vmo(std::move(vmo), std::forward<MetaArgs>(vmo_args)...);
      SetOwner(&stored_vmo, this);
      return stored_vmo;
    }

    // Pointer to parent store, not owned.
    VmoStore* store_;
    std::atomic_size_t registration_count_;
  };
};

}  // namespace vmo_store

#endif  // SRC_LIB_VMO_STORE_OWNED_VMO_STORE_H_
