// 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 "src/storage/blobfs/allocator/extent-reserver.h"

#include <stdint.h>
#include <zircon/types.h>

#include <bitmap/rle-bitmap.h>
#include <blobfs/format.h>

namespace blobfs {

ReservedExtent ExtentReserver::ReserveLocked(const Extent& extent) {
  ZX_DEBUG_ASSERT_MSG(extent.Length() > 0, "Reserving empty extents is disallowed");
  size_t blkno_out;
  ZX_DEBUG_ASSERT(reserved_blocks_.Find(false, extent.Start(), extent.Start() + extent.Length(),
                                        extent.Length(), &blkno_out) == ZX_OK);
  zx_status_t status = reserved_blocks_.Set(extent.Start(), extent.Start() + extent.Length());
  ZX_DEBUG_ASSERT(status == ZX_OK);
  return ReservedExtent(this, extent);
}

void ExtentReserver::Unreserve(const Extent& extent) {
  // Ensure the blocks are already reserved.
  size_t blkno_out;
  std::scoped_lock lock(mutex_);
  ZX_DEBUG_ASSERT(reserved_blocks_.Find(true, extent.Start(), extent.Start() + extent.Length(),
                                        extent.Length(), &blkno_out) == ZX_OK);

  zx_status_t status = reserved_blocks_.Clear(extent.Start(), extent.Start() + extent.Length());
  ZX_DEBUG_ASSERT(status == ZX_OK);
}

uint64_t ExtentReserver::ReservedBlockCount() const {
  std::scoped_lock lock(mutex_);
  return reserved_blocks_.num_bits();
}

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

ReservedExtent::ReservedExtent(ReservedExtent&& o) : reserver_(o.reserver_), extent_(o.extent_) {
  o.Release();
}

ReservedExtent& ReservedExtent::operator=(ReservedExtent&& o) {
  Reset();
  reserver_ = o.reserver_;
  extent_ = o.extent_;
  o.Release();
  return *this;
}

const Extent& ReservedExtent::extent() const {
  ZX_DEBUG_ASSERT_MSG(Reserved(), "Accessing unreserved extent");
  return extent_;
}

ReservedExtent ReservedExtent::SplitAt(BlockCountType block_split) {
  ZX_DEBUG_ASSERT_MSG(Reserved(), "Accessing unreserved extent");
  ZX_DEBUG_ASSERT(block_split < extent_.Length());
  Extent latter(extent_.Start() + block_split,
                static_cast<BlockCountType>(extent_.Length() - block_split));

  extent_.SetLength(block_split);
  return ReservedExtent(reserver_, std::move(latter));
}

void ReservedExtent::Reset() {
  if (Reserved()) {
    reserver_->Unreserve(extent());
  }
  Release();
}

void ReservedExtent::Release() { reserver_ = nullptr; }

bool ReservedExtent::Reserved() const { return reserver_ != nullptr; }

}  // namespace blobfs
