blob: d59b82c0e56646a5b838307947819386f11d75d4 [file] [log] [blame]
// 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.
#pragma once
#include <stdbool.h>
#include <stdint.h>
#include <bitmap/rle-bitmap.h>
#include <blobfs/format.h>
#include <zircon/types.h>
namespace blobfs {
// Allows nodes to be reserved and unreserved. The purpose of reservation is to allow allocation of
// nodes to occur without yet allocating structures which could be written out to durable storage.
//
// These nodes may be observed by derived classes of NodeReserver.
// Thread-compatible.
class NodeReserver {
public:
// Reserves space for a node in memory. Does not update disk.
void Reserve(uint32_t node_index);
// Unreserves space for a node in memory. Does not update disk.
void Unreserve(uint32_t node_index);
// Returns the total number of reserved nodes.
uint32_t ReservedNodeCount() const;
protected:
// Returns true if the node at |node_index| is reserved.
bool IsNodeReserved(uint32_t node_index) const;
// Informs the NodeReserver that |node_index| has been released.
//
// If |node_index| is lower than the lowest known free node, update our
// assumption of the lowest possible free node.
void SetFreeNodeLowerBoundIfSmallest(uint32_t node_index);
// Informs the NodeReserver that |node_index| is the lower bound on free nodes.
//
// Should only be invoked when it is known that all nodes from [0, node_index) are
// free. Does not guarantee |node_index| is free.
void SetFreeNodeLowerBound(uint32_t node_index);
// Returns the earliest possible free node.
uint32_t FreeNodeLowerBound() const;
private:
// free_node_lower_bound_ is lower bound on free nodes, meaning we are sure that
// there are no free nodes with indices less than free_node_lower_bound_.
//
// By "free", in this context, we mean both "unreserved and unallocated".
//
// This doesn't mean that free_node_lower_bound_ is a free node; it just means that one can
// start looking for a free node from free_node_lower_bound_.
uint32_t free_node_lower_bound_ = 0;
bitmap::RleBitmap reserved_nodes_ = {};
};
// Wraps a node reservation in RAII to hold the reservation active, and release it when it goes out
// of scope.
// Thread-compatible.
class ReservedNode {
public:
DISALLOW_COPY_AND_ASSIGN_ALLOW_MOVE(ReservedNode);
ReservedNode(NodeReserver* reserver, uint32_t node);
ReservedNode(ReservedNode&& o);
ReservedNode& operator=(ReservedNode&& o);
~ReservedNode();
// Access the underlying node index which has been reserved.
//
// Unsafe to call if the node has not actually been reserved.
uint32_t index() const;
// Releases the underlying node, unreserving it and preventing continued access to |index()|.
void Reset();
private:
// Update internal state such that future calls to |Reserved| return false.
void Release();
// Identify if the underlying node is reserved, and able to be accessed.
bool Reserved() const;
NodeReserver* reserver_;
uint32_t node_;
};
} // namespace blobfs