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

#include <lib/fit/bridge.h>
#include <lib/fit/sequencer.h>
#include <lib/inspect/cpp/inspect.h>
#include <lib/inspect/cpp/vmo/block.h>
#include <lib/inspect/cpp/vmo/state.h>

#include <functional>
#include <sstream>

namespace inspect {
namespace internal {

namespace {
// Helper class to support RAII locking of the generation count.
class AutoGenerationIncrement final {
 public:
  AutoGenerationIncrement(BlockIndex target, Heap* heap);
  ~AutoGenerationIncrement();

  // Disallow copy assign and move.
  AutoGenerationIncrement(AutoGenerationIncrement&&) = delete;
  AutoGenerationIncrement(const AutoGenerationIncrement&) = delete;
  AutoGenerationIncrement& operator=(AutoGenerationIncrement&&) = delete;
  AutoGenerationIncrement& operator=(const AutoGenerationIncrement&) = delete;

 private:
  // Acquire the generation count lock.
  // This consists of atomically incrementing the count using
  // acquire-release ordering, ensuring readers see this increment before
  // any changes to the buffer.
  void Acquire(Block* block);

  // Release the generation count lock.
  // This consists of atomically incrementing the count using release
  // ordering, ensuring readers see this increment after all changes to
  // the buffer are committed.
  void Release(Block* block);

  BlockIndex target_;
  Heap* heap_;
};

AutoGenerationIncrement ::AutoGenerationIncrement(BlockIndex target, Heap* heap)
    : target_(target), heap_(heap) {
  Acquire(heap_->GetBlock(target_));
}
AutoGenerationIncrement::~AutoGenerationIncrement() { Release(heap_->GetBlock(target_)); }

void AutoGenerationIncrement ::Acquire(Block* block) {
  uint64_t* ptr = &block->payload.u64;
  __atomic_fetch_add(ptr, 1, std::memory_order_acq_rel);
}

void AutoGenerationIncrement::Release(Block* block) {
  uint64_t* ptr = &block->payload.u64;
  __atomic_fetch_add(ptr, 1, std::memory_order_release);
}

}  // namespace

template <typename NumericType, typename WrapperType, BlockType BlockTypeValue>
WrapperType State::InnerCreateArray(const std::string& name, BlockIndex parent, size_t slots,
                                    ArrayBlockFormat format) {
  size_t block_size_needed = slots * sizeof(NumericType) + kMinOrderSize;
  ZX_DEBUG_ASSERT_MSG(block_size_needed <= kMaxOrderSize,
                      "The requested array size cannot fit in a block");
  if (block_size_needed > kMaxOrderSize) {
    return WrapperType();
  }

  std::lock_guard<std::mutex> lock(mutex_);
  AutoGenerationIncrement gen(header_, heap_.get());

  BlockIndex name_index, value_index;
  zx_status_t status;
  status = InnerCreateValue(name, BlockType::kArrayValue, parent, &name_index, &value_index,
                            block_size_needed);
  if (status != ZX_OK) {
    return WrapperType();
  }

  auto* block = heap_->GetBlock(value_index);
  block->payload.u64 = ArrayBlockPayload::EntryType::Make(BlockTypeValue) |
                       ArrayBlockPayload::Flags::Make(format) |
                       ArrayBlockPayload::Count::Make(slots);

  return WrapperType(weak_self_ptr_.lock(), name_index, value_index);
}

template <typename NumericType, typename WrapperType, BlockType BlockTypeValue>
void State::InnerSetArray(WrapperType* metric, size_t index, NumericType value) {
  ZX_ASSERT(metric->state_.get() == this);
  std::lock_guard<std::mutex> lock(mutex_);
  AutoGenerationIncrement gen(header_, heap_.get());

  auto* block = heap_->GetBlock(metric->value_index_);
  ZX_ASSERT(GetType(block) == BlockType::kArrayValue);
  auto entry_type = ArrayBlockPayload::EntryType::Get<BlockType>(block->payload.u64);
  ZX_ASSERT(entry_type == BlockTypeValue);
  auto* slot = GetArraySlot<NumericType>(block, index);
  if (slot != nullptr) {
    *slot = value;
  }
}

template <typename NumericType, typename WrapperType, BlockType BlockTypeValue, typename Operation>
void State::InnerOperationArray(WrapperType* metric, size_t index, NumericType value) {
  ZX_ASSERT(metric->state_.get() == this);
  std::lock_guard<std::mutex> lock(mutex_);
  AutoGenerationIncrement gen(header_, heap_.get());

  auto* block = heap_->GetBlock(metric->value_index_);
  ZX_ASSERT(GetType(block) == BlockType::kArrayValue);
  auto entry_type = ArrayBlockPayload::EntryType::Get<BlockType>(block->payload.u64);
  ZX_ASSERT(entry_type == BlockTypeValue);
  auto* slot = GetArraySlot<NumericType>(block, index);
  if (slot != nullptr) {
    *slot = Operation()(*slot, value);
  }
}

template <typename WrapperType>
void State::InnerFreeArray(WrapperType* value) {
  ZX_DEBUG_ASSERT_MSG(value->state_.get() == this, "Array being freed from the wrong state");
  if (value->state_.get() != this) {
    return;
  }

  std::lock_guard<std::mutex> lock(mutex_);
  AutoGenerationIncrement gen(header_, heap_.get());

  DecrementParentRefcount(value->value_index_);

  heap_->Free(value->name_index_);
  heap_->Free(value->value_index_);
  value->state_ = nullptr;
}

std::shared_ptr<State> State::Create(std::unique_ptr<Heap> heap) {
  BlockIndex header;
  if (heap->Allocate(sizeof(Block), &header) != ZX_OK) {
    return nullptr;
  }

  ZX_DEBUG_ASSERT_MSG(header == 0, "Header must be at index 0");
  if (header != 0) {
    return nullptr;
  }

  auto* block = heap->GetBlock(header);
  block->header = HeaderBlockFields::Order::Make(GetOrder(block)) |
                  HeaderBlockFields::Type::Make(BlockType::kHeader) |
                  HeaderBlockFields::Version::Make(kVersion);
  memcpy(&block->header_data[4], kMagicNumber, 4);
  block->payload.u64 = 0;

  std::shared_ptr<State> ret(new State(std::move(heap), header));
  ret->weak_self_ptr_ = ret;
  return ret;
}

std::shared_ptr<State> State::CreateWithSize(size_t size) {
  zx::vmo vmo;
  if (size == 0 || ZX_OK != zx::vmo::create(size, 0, &vmo)) {
    return nullptr;
  }
  return State::Create(std::make_unique<Heap>(std::move(vmo)));
}

State::~State() { heap_->Free(header_); }

const zx::vmo& State::GetVmo() const {
  std::lock_guard<std::mutex> lock(mutex_);
  return heap_->GetVmo();
}

bool State::DuplicateVmo(zx::vmo* vmo) const {
  std::lock_guard<std::mutex> lock(mutex_);
  return ZX_OK == heap_->GetVmo().duplicate(ZX_RIGHTS_BASIC | ZX_RIGHT_READ | ZX_RIGHT_MAP, vmo);
}

bool State::Copy(zx::vmo* vmo) const {
  std::lock_guard<std::mutex> lock(mutex_);

  size_t size = heap_->size();
  if (zx::vmo::create(size, 0, vmo) != ZX_OK) {
    return false;
  }

  if (vmo->write(heap_->data(), 0, size) != ZX_OK) {
    return false;
  }

  return true;
}

bool State::CopyBytes(std::vector<uint8_t>* out) const {
  std::lock_guard<std::mutex> lock(mutex_);

  size_t size = heap_->size();
  if (size == 0) {
    return false;
  }

  out->resize(size);
  memcpy(out->data(), heap_->data(), size);

  return true;
}

IntProperty State::CreateIntProperty(const std::string& name, BlockIndex parent, int64_t value) {
  std::lock_guard<std::mutex> lock(mutex_);
  AutoGenerationIncrement gen(header_, heap_.get());

  BlockIndex name_index, value_index;
  zx_status_t status;
  status = InnerCreateValue(name, BlockType::kIntValue, parent, &name_index, &value_index);
  if (status != ZX_OK) {
    return IntProperty();
  }

  auto* block = heap_->GetBlock(value_index);
  block->payload.i64 = value;

  return IntProperty(weak_self_ptr_.lock(), name_index, value_index);
}

UintProperty State::CreateUintProperty(const std::string& name, BlockIndex parent, uint64_t value) {
  std::lock_guard<std::mutex> lock(mutex_);
  AutoGenerationIncrement gen(header_, heap_.get());

  BlockIndex name_index, value_index;
  zx_status_t status;
  status = InnerCreateValue(name, BlockType::kUintValue, parent, &name_index, &value_index);
  if (status != ZX_OK) {
    return UintProperty();
  }

  auto* block = heap_->GetBlock(value_index);
  block->payload.u64 = value;

  return UintProperty(weak_self_ptr_.lock(), name_index, value_index);
}

DoubleProperty State::CreateDoubleProperty(const std::string& name, BlockIndex parent,
                                           double value) {
  std::lock_guard<std::mutex> lock(mutex_);
  AutoGenerationIncrement gen(header_, heap_.get());

  BlockIndex name_index, value_index;
  zx_status_t status;
  status = InnerCreateValue(name, BlockType::kDoubleValue, parent, &name_index, &value_index);
  if (status != ZX_OK) {
    return DoubleProperty();
  }

  auto* block = heap_->GetBlock(value_index);
  block->payload.f64 = value;

  return DoubleProperty(weak_self_ptr_.lock(), name_index, value_index);
}

BoolProperty State::CreateBoolProperty(const std::string& name, BlockIndex parent, bool value) {
  std::lock_guard<std::mutex> lock(mutex_);
  AutoGenerationIncrement gen(header_, heap_.get());

  BlockIndex name_index, value_index;
  zx_status_t status;
  status = InnerCreateValue(name, BlockType::kBoolValue, parent, &name_index, &value_index);
  if (status != ZX_OK) {
    return BoolProperty();
  }

  auto* block = heap_->GetBlock(value_index);
  block->payload.u64 = value;
  return BoolProperty(weak_self_ptr_.lock(), name_index, value_index);
}

IntArray State::CreateIntArray(const std::string& name, BlockIndex parent, size_t slots,
                               ArrayBlockFormat format) {
  return InnerCreateArray<int64_t, IntArray, BlockType::kIntValue>(name, parent, slots, format);
}

UintArray State::CreateUintArray(const std::string& name, BlockIndex parent, size_t slots,
                                 ArrayBlockFormat format) {
  return InnerCreateArray<uint64_t, UintArray, BlockType::kUintValue>(name, parent, slots, format);
}

DoubleArray State::CreateDoubleArray(const std::string& name, BlockIndex parent, size_t slots,
                                     ArrayBlockFormat format) {
  return InnerCreateArray<double, DoubleArray, BlockType::kDoubleValue>(name, parent, slots,
                                                                        format);
}

template <typename WrapperType, typename ValueType>
WrapperType State::InnerCreateProperty(const std::string& name, BlockIndex parent,
                                       const char* value, size_t length,
                                       PropertyBlockFormat format) {
  std::lock_guard<std::mutex> lock(mutex_);
  AutoGenerationIncrement gen(header_, heap_.get());

  BlockIndex name_index, value_index;
  zx_status_t status;
  status = InnerCreateValue(name, BlockType::kBufferValue, parent, &name_index, &value_index);
  if (status != ZX_OK) {
    return WrapperType();
  }
  auto* block = heap_->GetBlock(value_index);
  block->payload.u64 = PropertyBlockPayload::Flags::Make(format);
  status = InnerSetStringExtents(value_index, value, length);
  if (status != ZX_OK) {
    heap_->Free(name_index);
    heap_->Free(value_index);
    return WrapperType();
  }

  return WrapperType(weak_self_ptr_.lock(), name_index, value_index);
}

StringProperty State::CreateStringProperty(const std::string& name, BlockIndex parent,
                                           const std::string& value) {
  return InnerCreateProperty<StringProperty, std::string>(
      name, parent, value.data(), value.length(), PropertyBlockFormat::kUtf8);
}

ByteVectorProperty State::CreateByteVectorProperty(const std::string& name, BlockIndex parent,
                                                   const std::vector<uint8_t>& value) {
  return InnerCreateProperty<ByteVectorProperty, std::vector<uint8_t>>(
      name, parent, reinterpret_cast<const char*>(value.data()), value.size(),
      PropertyBlockFormat::kBinary);
}

Link State::CreateLink(const std::string& name, BlockIndex parent, const std::string& content,
                       LinkBlockDisposition disposition) {
  std::lock_guard<std::mutex> lock(mutex_);
  AutoGenerationIncrement gen(header_, heap_.get());

  BlockIndex name_index, value_index, content_index;
  zx_status_t status;
  status = InnerCreateValue(name, BlockType::kLinkValue, parent, &name_index, &value_index);
  if (status != ZX_OK) {
    return Link();
  }

  status = CreateName(content, &content_index);
  if (status != ZX_OK) {
    DecrementParentRefcount(value_index);
    heap_->Free(name_index);
    heap_->Free(value_index);
    return Link();
  }

  auto* block = heap_->GetBlock(value_index);

  block->payload.u64 = LinkBlockPayload::ContentIndex::Make(content_index) |
                       LinkBlockPayload::Flags::Make(disposition);

  return Link(weak_self_ptr_.lock(), name_index, value_index, content_index);
}

Node State::CreateRootNode() {
  std::lock_guard<std::mutex> lock(mutex_);
  return Node(weak_self_ptr_.lock(), 0, 0);
}

LazyNode State::InnerCreateLazyLink(const std::string& name, BlockIndex parent,
                                    LazyNodeCallbackFn callback, LinkBlockDisposition disposition) {
  auto content = UniqueLinkName(name);
  auto link = CreateLink(name, parent, content, disposition);

  {
    std::lock_guard<std::mutex> lock(mutex_);

    link_callbacks_.emplace(content, LazyNodeCallbackHolder(std::move(callback)));

    return LazyNode(weak_self_ptr_.lock(), std::move(content), std::move(link));
  }
}

LazyNode State::CreateLazyNode(const std::string& name, BlockIndex parent,
                               LazyNodeCallbackFn callback) {
  return InnerCreateLazyLink(name, parent, std::move(callback), LinkBlockDisposition::kChild);
}

LazyNode State::CreateLazyValues(const std::string& name, BlockIndex parent,
                                 LazyNodeCallbackFn callback) {
  return InnerCreateLazyLink(name, parent, std::move(callback), LinkBlockDisposition::kInline);
}

Node State::CreateNode(const std::string& name, BlockIndex parent) {
  std::lock_guard<std::mutex> lock(mutex_);
  AutoGenerationIncrement gen(header_, heap_.get());

  BlockIndex name_index, value_index;
  zx_status_t status;
  status = InnerCreateValue(name, BlockType::kNodeValue, parent, &name_index, &value_index);
  if (status != ZX_OK) {
    return Node();
  }

  return Node(weak_self_ptr_.lock(), name_index, value_index);
}

void State::SetIntProperty(IntProperty* metric, int64_t value) {
  ZX_ASSERT(metric->state_.get() == this);
  std::lock_guard<std::mutex> lock(mutex_);
  AutoGenerationIncrement gen(header_, heap_.get());

  auto* block = heap_->GetBlock(metric->value_index_);
  ZX_DEBUG_ASSERT_MSG(GetType(block) == BlockType::kIntValue, "Expected int metric, got %d",
                      static_cast<int>(GetType(block)));
  block->payload.i64 = value;
}

void State::SetUintProperty(UintProperty* metric, uint64_t value) {
  ZX_ASSERT(metric->state_.get() == this);

  std::lock_guard<std::mutex> lock(mutex_);
  AutoGenerationIncrement gen(header_, heap_.get());

  auto* block = heap_->GetBlock(metric->value_index_);
  ZX_DEBUG_ASSERT_MSG(GetType(block) == BlockType::kUintValue, "Expected uint metric, got %d",
                      static_cast<int>(GetType(block)));
  block->payload.u64 = value;
}

void State::SetDoubleProperty(DoubleProperty* metric, double value) {
  ZX_ASSERT(metric->state_.get() == this);

  std::lock_guard<std::mutex> lock(mutex_);
  AutoGenerationIncrement gen(header_, heap_.get());

  auto* block = heap_->GetBlock(metric->value_index_);
  ZX_DEBUG_ASSERT_MSG(GetType(block) == BlockType::kDoubleValue, "Expected double metric, got %d",
                      static_cast<int>(GetType(block)));
  block->payload.f64 = value;
}

void State::SetBoolProperty(BoolProperty* metric, bool value) {
  ZX_ASSERT(metric->state_.get() == this);
  std::lock_guard<std::mutex> lock(mutex_);
  AutoGenerationIncrement gen(header_, heap_.get());

  auto* block = heap_->GetBlock(metric->value_index_);
  ZX_DEBUG_ASSERT_MSG(GetType(block) == BlockType::kBoolValue, "Expected bool metric, got %d",
                      static_cast<int>(GetType(block)));
  block->payload.u64 = value;
}

void State::SetIntArray(IntArray* array, size_t index, int64_t value) {
  InnerSetArray<int64_t, IntArray, BlockType::kIntValue>(array, index, value);
}

void State::SetUintArray(UintArray* array, size_t index, uint64_t value) {
  InnerSetArray<uint64_t, UintArray, BlockType::kUintValue>(array, index, value);
}

void State::SetDoubleArray(DoubleArray* array, size_t index, double value) {
  InnerSetArray<double, DoubleArray, BlockType::kDoubleValue>(array, index, value);
}

void State::AddIntProperty(IntProperty* metric, int64_t value) {
  ZX_ASSERT(metric->state_.get() == this);

  std::lock_guard<std::mutex> lock(mutex_);
  AutoGenerationIncrement gen(header_, heap_.get());

  auto* block = heap_->GetBlock(metric->value_index_);
  ZX_DEBUG_ASSERT_MSG(GetType(block) == BlockType::kIntValue, "Expected int metric, got %d",
                      static_cast<int>(GetType(block)));
  block->payload.i64 += value;
}

void State::AddUintProperty(UintProperty* metric, uint64_t value) {
  ZX_ASSERT(metric->state_.get() == this);

  std::lock_guard<std::mutex> lock(mutex_);
  AutoGenerationIncrement gen(header_, heap_.get());

  auto* block = heap_->GetBlock(metric->value_index_);
  ZX_DEBUG_ASSERT_MSG(GetType(block) == BlockType::kUintValue, "Expected uint metric, got %d",
                      static_cast<int>(GetType(block)));
  block->payload.u64 += value;
}

void State::AddDoubleProperty(DoubleProperty* metric, double value) {
  ZX_ASSERT(metric->state_.get() == this);

  std::lock_guard<std::mutex> lock(mutex_);
  AutoGenerationIncrement gen(header_, heap_.get());

  auto* block = heap_->GetBlock(metric->value_index_);
  ZX_DEBUG_ASSERT_MSG(GetType(block) == BlockType::kDoubleValue, "Expected double metric, got %d",
                      static_cast<int>(GetType(block)));
  block->payload.f64 += value;
}

void State::SubtractIntProperty(IntProperty* metric, int64_t value) {
  ZX_ASSERT(metric->state_.get() == this);

  std::lock_guard<std::mutex> lock(mutex_);
  AutoGenerationIncrement gen(header_, heap_.get());

  auto* block = heap_->GetBlock(metric->value_index_);
  ZX_DEBUG_ASSERT_MSG(GetType(block) == BlockType::kIntValue, "Expected int metric, got %d",
                      static_cast<int>(GetType(block)));
  block->payload.i64 -= value;
}

void State::SubtractUintProperty(UintProperty* metric, uint64_t value) {
  ZX_ASSERT(metric->state_.get() == this);

  std::lock_guard<std::mutex> lock(mutex_);
  AutoGenerationIncrement gen(header_, heap_.get());

  auto* block = heap_->GetBlock(metric->value_index_);
  ZX_DEBUG_ASSERT_MSG(GetType(block) == BlockType::kUintValue, "Expected uint metric, got %d",
                      static_cast<int>(GetType(block)));
  block->payload.u64 -= value;
}

void State::SubtractDoubleProperty(DoubleProperty* metric, double value) {
  ZX_ASSERT(metric->state_.get() == this);

  std::lock_guard<std::mutex> lock(mutex_);
  AutoGenerationIncrement gen(header_, heap_.get());

  auto* block = heap_->GetBlock(metric->value_index_);
  ZX_DEBUG_ASSERT_MSG(GetType(block) == BlockType::kDoubleValue, "Expected double metric, got %d",
                      static_cast<int>(GetType(block)));
  block->payload.f64 -= value;
}

void State::AddIntArray(IntArray* array, size_t index, int64_t value) {
  InnerOperationArray<int64_t, IntArray, BlockType::kIntValue, std::plus<int64_t>>(array, index,
                                                                                   value);
}

void State::SubtractIntArray(IntArray* array, size_t index, int64_t value) {
  InnerOperationArray<int64_t, IntArray, BlockType::kIntValue, std::minus<int64_t>>(array, index,
                                                                                    value);
}

void State::AddUintArray(UintArray* array, size_t index, uint64_t value) {
  InnerOperationArray<uint64_t, UintArray, BlockType::kUintValue, std::plus<uint64_t>>(array, index,
                                                                                       value);
}

void State::SubtractUintArray(UintArray* array, size_t index, uint64_t value) {
  InnerOperationArray<uint64_t, UintArray, BlockType::kUintValue, std::minus<uint64_t>>(
      array, index, value);
}

void State::AddDoubleArray(DoubleArray* array, size_t index, double value) {
  InnerOperationArray<double, DoubleArray, BlockType::kDoubleValue, std::plus<double>>(array, index,
                                                                                       value);
}

void State::SubtractDoubleArray(DoubleArray* array, size_t index, double value) {
  InnerOperationArray<double, DoubleArray, BlockType::kDoubleValue, std::minus<double>>(
      array, index, value);
}

template <typename WrapperType>
void State::InnerSetProperty(WrapperType* property, const char* value, size_t length) {
  ZX_ASSERT(property->state_.get() == this);

  std::lock_guard<std::mutex> lock(mutex_);
  AutoGenerationIncrement gen(header_, heap_.get());

  InnerSetStringExtents(property->value_index_, value, length);
}

void State::SetStringProperty(StringProperty* property, const std::string& value) {
  InnerSetProperty(property, value.data(), value.size());
}

void State::SetByteVectorProperty(ByteVectorProperty* property, const std::vector<uint8_t>& value) {
  InnerSetProperty(property, reinterpret_cast<const char*>(value.data()), value.size());
}

void State::DecrementParentRefcount(BlockIndex value_index) {
  Block* value = heap_->GetBlock(value_index);
  ZX_ASSERT(value);

  BlockIndex parent_index = ValueBlockFields::ParentIndex::Get<BlockIndex>(value->header);
  Block* parent;
  while ((parent = heap_->GetBlock(parent_index)) != nullptr) {
    ZX_ASSERT(parent);
    switch (GetType(parent)) {
      case BlockType::kHeader:
        return;
      case BlockType::kNodeValue:
        // Stop decrementing parent refcounts when we observe a live object.
        ZX_ASSERT(parent->payload.u64 != 0);
        --parent->payload.u64;
        return;
      case BlockType::kTombstone:
        ZX_ASSERT(parent->payload.u64 != 0);
        if (--parent->payload.u64 == 0) {
          // The tombstone parent is no longer referenced and can be deleted.
          // Continue decrementing refcounts.
          BlockIndex next_parent_index =
              ValueBlockFields::ParentIndex::Get<BlockIndex>(parent->header);
          heap_->Free(ValueBlockFields::NameIndex::Get<BlockIndex>(parent->header));
          heap_->Free(parent_index);
          parent_index = next_parent_index;
          break;
        }
        // The tombstone parent is still referenced. Done decrementing refcounts.
        return;
      default:
        ZX_DEBUG_ASSERT_MSG(false, "Invalid parent type %u",
                            static_cast<uint32_t>(GetType(parent)));
        return;
    }
  }
}

void State::FreeIntProperty(IntProperty* metric) {
  ZX_DEBUG_ASSERT_MSG(metric->state_.get() == this, "Property being freed from the wrong state");
  if (metric->state_.get() != this) {
    return;
  }

  std::lock_guard<std::mutex> lock(mutex_);
  AutoGenerationIncrement gen(header_, heap_.get());

  DecrementParentRefcount(metric->value_index_);

  heap_->Free(metric->name_index_);
  heap_->Free(metric->value_index_);
  metric->state_ = nullptr;
}

void State::FreeUintProperty(UintProperty* metric) {
  ZX_DEBUG_ASSERT_MSG(metric->state_.get() == this, "Property being freed from the wrong state");
  if (metric->state_.get() != this) {
    return;
  }

  std::lock_guard<std::mutex> lock(mutex_);
  AutoGenerationIncrement gen(header_, heap_.get());

  DecrementParentRefcount(metric->value_index_);

  heap_->Free(metric->name_index_);
  heap_->Free(metric->value_index_);
  metric->state_ = nullptr;
}

void State::FreeDoubleProperty(DoubleProperty* metric) {
  ZX_DEBUG_ASSERT_MSG(metric->state_.get() == this, "Property being freed from the wrong state");
  if (metric->state_.get() != this) {
    return;
  }

  std::lock_guard<std::mutex> lock(mutex_);
  AutoGenerationIncrement gen(header_, heap_.get());

  DecrementParentRefcount(metric->value_index_);

  heap_->Free(metric->name_index_);
  heap_->Free(metric->value_index_);
  metric->state_ = nullptr;
}

void State::FreeBoolProperty(BoolProperty* metric) {
  ZX_DEBUG_ASSERT_MSG(metric->state_.get() == this, "Property being freed from wrong state");
  if (metric->state_.get() != this) {
    return;
  }

  std::lock_guard<std::mutex> lock(mutex_);
  AutoGenerationIncrement gen(header_, heap_.get());

  DecrementParentRefcount(metric->value_index_);

  heap_->Free(metric->name_index_);
  heap_->Free(metric->value_index_);
  metric->state_ = nullptr;
}

void State::FreeIntArray(IntArray* array) { InnerFreeArray<IntArray>(array); }

void State::FreeUintArray(UintArray* array) { InnerFreeArray<UintArray>(array); }

void State::FreeDoubleArray(DoubleArray* array) { InnerFreeArray<DoubleArray>(array); }

template <typename WrapperType>
void State::InnerFreePropertyWithExtents(WrapperType* property) {
  ZX_DEBUG_ASSERT_MSG(property->state_.get() == this, "Property being freed from the wrong state");
  if (property->state_.get() != this) {
    return;
  }

  std::lock_guard<std::mutex> lock(mutex_);
  AutoGenerationIncrement gen(header_, heap_.get());

  DecrementParentRefcount(property->value_index_);

  InnerFreeStringExtents(property->value_index_);

  heap_->Free(property->name_index_);
  heap_->Free(property->value_index_);
  property->state_ = nullptr;
}

void State::FreeStringProperty(StringProperty* property) { InnerFreePropertyWithExtents(property); }

void State::FreeByteVectorProperty(ByteVectorProperty* property) {
  InnerFreePropertyWithExtents(property);
}

void State::FreeLink(Link* link) {
  ZX_DEBUG_ASSERT_MSG(link->state_.get() == this, "Link being freed from the wrong state");
  if (link->state_.get() != this) {
    return;
  }

  std::lock_guard<std::mutex> lock(mutex_);
  AutoGenerationIncrement gen(header_, heap_.get());

  DecrementParentRefcount(link->value_index_);

  heap_->Free(link->name_index_);
  heap_->Free(link->value_index_);
  heap_->Free(link->content_index_);
  link->state_ = nullptr;
}

void State::FreeNode(Node* object) {
  ZX_DEBUG_ASSERT_MSG(object->state_.get() == this, "Node being freed from the wrong state");
  if (object->state_.get() != this) {
    return;
  }

  if (object->value_index_ == 0) {
    // This is a special "root" node, it cannot be deleted.
    return;
  }

  std::lock_guard<std::mutex> lock(mutex_);
  AutoGenerationIncrement gen(header_, heap_.get());

  auto* block = heap_->GetBlock(object->value_index_);
  if (block) {
    if (block->payload.u64 == 0) {
      // Actually free the block, decrementing parent refcounts.
      DecrementParentRefcount(object->value_index_);
      // Node has no refs, free it.
      heap_->Free(object->name_index_);
      heap_->Free(object->value_index_);
    } else {
      // Node has refs, change type to tombstone so it can be removed
      // when the last ref is gone.
      ValueBlockFields::Type::Set(&block->header, static_cast<uint64_t>(BlockType::kTombstone));
    }
  }
}

void State::FreeLazyNode(LazyNode* object) {
  ZX_DEBUG_ASSERT_MSG(object->state_.get() == this, "Node being freed from the wrong state");
  if (object->state_.get() != this) {
    return;
  }

  // Free the contained link, which removes the reference to the value in the map.
  FreeLink(&object->link_);

  LazyNodeCallbackHolder holder;

  {
    // Separately lock the current state, and remove the callback for this lazy node.
    std::lock_guard<std::mutex> lock(mutex_);
    auto it = link_callbacks_.find(object->content_value_);
    if (it != link_callbacks_.end()) {
      holder = it->second;
      link_callbacks_.erase(it);
    }
    object->state_ = nullptr;
  }

  // Cancel the Holder without State locked. This avoids a deadlock in which we could be locking the
  // holder with the state lock held, meanwhile the callback itself is modifying state (with holder
  // locked).
  //
  // At this point in time, the LazyNode is still *live* and the callback may be getting executed.
  // Following this cancel call, the LazyNode is no longer live and the callback will never be
  // called again.
  holder.cancel();
}

std::vector<std::string> State::GetLinkNames() const {
  std::lock_guard<std::mutex> lock(mutex_);
  std::vector<std::string> ret;
  for (const auto& entry : link_callbacks_) {
    ret.push_back(entry.first);
  }
  return ret;
}

fit::promise<Inspector> State::CallLinkCallback(const std::string& name) {
  LazyNodeCallbackHolder holder;

  {
    std::lock_guard<std::mutex> lock(mutex_);
    auto it = link_callbacks_.find(name);
    if (it == link_callbacks_.end()) {
      return fit::make_result_promise<Inspector>(fit::error());
    }
    // Copy out the holder.
    holder = it->second;
  }

  // Call the callback.
  // This occurs without state locked, but deletion of the LazyNode synchronizes on the internal
  // mutex in the Holder. If the LazyNode is deleted before this call, the callback will not be
  // executed. If the LazyNode is being deleted concurrent with this call, it will be delayed until
  // after the callback returns.
  return holder.call();
}

zx_status_t State::InnerCreateValue(const std::string& name, BlockType type,
                                    BlockIndex parent_index, BlockIndex* out_name,
                                    BlockIndex* out_value, size_t min_size_required) {
  BlockIndex value_index, name_index;
  zx_status_t status;
  status = heap_->Allocate(min_size_required, &value_index);
  if (status != ZX_OK) {
    return status;
  }

  status = CreateName(name, &name_index);
  if (status != ZX_OK) {
    heap_->Free(value_index);
    return status;
  }

  auto* block = heap_->GetBlock(value_index);
  block->header = ValueBlockFields::Order::Make(GetOrder(block)) |
                  ValueBlockFields::Type::Make(type) |
                  ValueBlockFields::ParentIndex::Make(parent_index) |
                  ValueBlockFields::NameIndex::Make(name_index);
  memset(&block->payload, 0, min_size_required - sizeof(block->header));

  // Increment the parent refcount.
  Block* parent = heap_->GetBlock(parent_index);
  ZX_DEBUG_ASSERT_MSG(parent, "Index %lu is invalid", parent_index);
  // In release mode, do cleanup if parent is invalid.
  BlockType parent_type = (parent) ? GetType(parent) : BlockType::kFree;
  switch (parent_type) {
    case BlockType::kHeader:
      break;
    case BlockType::kNodeValue:
    case BlockType::kTombstone:
      // Increment refcount.
      parent->payload.u64++;
      break;
    default:
      ZX_DEBUG_ASSERT_MSG(false, "Invalid parent block type %u for 0x%lx",
                          static_cast<uint32_t>(GetType(parent)), parent_index);
      heap_->Free(name_index);
      heap_->Free(value_index);
      return ZX_ERR_INVALID_ARGS;
  }

  *out_name = name_index;
  *out_value = value_index;
  return ZX_OK;
}

void State::InnerFreeStringExtents(BlockIndex string_index) {
  auto* str = heap_->GetBlock(string_index);
  if (!str || GetType(str) != BlockType::kBufferValue) {
    return;
  }

  auto extent_index = PropertyBlockPayload::ExtentIndex::Get<BlockIndex>(str->payload.u64);
  auto* extent = heap_->GetBlock(extent_index);
  while (IsExtent(extent)) {
    auto next_extent = ExtentBlockFields::NextExtentIndex::Get<BlockIndex>(extent->header);
    heap_->Free(extent_index);
    extent_index = next_extent;
    extent = heap_->GetBlock(extent_index);
  }

  // Leave the string value allocated (and empty).
  str->payload.u64 = PropertyBlockPayload::TotalLength::Make(0) |
                     PropertyBlockPayload::ExtentIndex::Make(0) |
                     PropertyBlockPayload::Flags::Make(
                         PropertyBlockPayload::Flags::Get<uint8_t>(str->payload.u64));
}

zx_status_t State::InnerSetStringExtents(BlockIndex string_index, const char* value,
                                         size_t length) {
  InnerFreeStringExtents(string_index);

  auto* block = heap_->GetBlock(string_index);

  if (length == 0) {
    // The extent index is 0 if no extents were needed (the value is empty).
    block->payload.u64 = PropertyBlockPayload::TotalLength::Make(length) |
                         PropertyBlockPayload::ExtentIndex::Make(0) |
                         PropertyBlockPayload::Flags::Make(
                             PropertyBlockPayload::Flags::Get<uint8_t>(block->payload.u64));
    return ZX_OK;
  }

  BlockIndex extent_index;
  zx_status_t status;
  status = heap_->Allocate(std::min(kMaxOrderSize, BlockSizeForPayload(length)), &extent_index);
  if (status != ZX_OK) {
    return status;
  }

  block->payload.u64 = PropertyBlockPayload::TotalLength::Make(length) |
                       PropertyBlockPayload::ExtentIndex::Make(extent_index) |
                       PropertyBlockPayload::Flags::Make(
                           PropertyBlockPayload::Flags::Get<uint8_t>(block->payload.u64));

  // Thread the value through extents, creating new extents as needed.
  size_t offset = 0;
  while (offset < length) {
    auto* extent = heap_->GetBlock(extent_index);

    extent->header = ExtentBlockFields::Order::Make(GetOrder(extent)) |
                     ExtentBlockFields::Type::Make(BlockType::kExtent) |
                     ExtentBlockFields::NextExtentIndex::Make(0);

    size_t len = std::min(PayloadCapacity(GetOrder(extent)), length - offset);
    memcpy(extent->payload.data, value + offset, len);
    offset += len;

    if (offset < length) {
      status = heap_->Allocate(std::min(kMaxOrderSize, BlockSizeForPayload(length - offset)),
                               &extent_index);
      if (status != ZX_OK) {
        InnerFreeStringExtents(string_index);
        return status;
      }
      ExtentBlockFields::NextExtentIndex::Set(&extent->header, extent_index);
    }
  }

  return ZX_OK;
}

std::string State::UniqueLinkName(const std::string& prefix) {
  return prefix + "-" +
         std::to_string(next_unique_link_number_.fetch_add(1, std::memory_order_relaxed));
}

zx_status_t State::CreateName(const std::string& name, BlockIndex* out) {
  ZX_DEBUG_ASSERT_MSG(name.size() <= kMaxPayloadSize, "Name too long (length is %lu)", name.size());
  if (name.size() > kMaxPayloadSize) {
    return ZX_ERR_INVALID_ARGS;
  }

  zx_status_t status;
  status = heap_->Allocate(BlockSizeForPayload(name.size()), out);
  if (status != ZX_OK) {
    return status;
  }

  auto* block = heap_->GetBlock(*out);
  block->header = NameBlockFields::Order::Make(GetOrder(block)) |
                  NameBlockFields::Type::Make(BlockType::kName) |
                  NameBlockFields::Length::Make(name.size());
  memset(block->payload.data, 0, PayloadCapacity(GetOrder(block)));
  memcpy(block->payload.data, name.data(), name.size());
  return ZX_OK;
}

std::string State::UniqueName(const std::string& prefix) {
  std::ostringstream out;
  uint64_t value = next_unique_id_.fetch_add(1, std::memory_order_relaxed);
  out << prefix << "0x" << std::hex << value;
  return out.str();
}

}  // namespace internal
}  // namespace inspect
