// 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 <stdint.h>

#include <bitmap/rle-bitmap.h>
#include <blobfs/extent-reserver.h>
#include <blobfs/format.h>
#include <zircon/types.h>

namespace blobfs {

void ExtentReserver::Reserve(const Extent& extent) {
    ZX_DEBUG_ASSERT_MSG(extent.Length() > 0, "Reserving empty extents is disallowed");
    zx_status_t status = reserved_blocks_.Set(extent.Start(),
                                              extent.Start() + extent.Length());
    ZX_DEBUG_ASSERT(status == ZX_OK);
}

void ExtentReserver::Unreserve(const Extent& extent) {
    // Ensure the blocks are already reserved.
    size_t blkno_out;
    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 {
    return reserved_blocks_.num_bits();
}

ReservedExtent::ReservedExtent(ExtentReserver* reserver, Extent extent)
    : reserver_(reserver), extent_(extent) {
    reserver_->Reserve(extent_);
}

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
