blob: 58576c7f8cbb5907bcf61a7c5549d2ce4b7fb8be [file] [log] [blame]
// Copyright 2020 The Pigweed Authors
//
// Licensed under the Apache License, Version 2.0 (the "License"); you may not
// use this file except in compliance with the License. You may obtain a copy of
// the License at
//
// https://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
// License for the specific language governing permissions and limitations under
// the License.
#pragma once
#include <climits>
#include <cstddef>
#include <cstdint>
namespace pw::kvs::internal {
// Tracks the available and used space in each sector used by the KVS.
class SectorDescriptor {
public:
explicit constexpr SectorDescriptor(uint16_t sector_size_bytes)
: tail_free_bytes_(sector_size_bytes), valid_bytes_(0) {}
SectorDescriptor(const SectorDescriptor&) = default;
SectorDescriptor& operator=(const SectorDescriptor&) = default;
// The number of bytes available to be written in this sector. It the sector
// is marked as corrupt, no bytes are available.
size_t writable_bytes() const {
return (tail_free_bytes_ == kCorruptSector) ? 0 : tail_free_bytes_;
}
void set_writable_bytes(uint16_t writable_bytes) {
tail_free_bytes_ = writable_bytes;
}
void mark_corrupt() { tail_free_bytes_ = kCorruptSector; }
bool corrupt() const { return tail_free_bytes_ == kCorruptSector; }
// The number of bytes of valid data in this sector.
size_t valid_bytes() const { return valid_bytes_; }
// Adds valid bytes without updating the writable bytes.
void AddValidBytes(uint16_t bytes) { valid_bytes_ += bytes; }
// Removes valid bytes without updating the writable bytes.
void RemoveValidBytes(uint16_t bytes) {
if (bytes > valid_bytes()) {
// TODO: use a DCHECK instead -- this is a programming error
valid_bytes_ = 0;
} else {
valid_bytes_ -= bytes;
}
}
// Removes writable bytes without updating the valid bytes.
void RemoveWritableBytes(uint16_t bytes) {
if (bytes > writable_bytes()) {
// TODO: use a DCHECK instead -- this is a programming error
tail_free_bytes_ = 0;
} else {
tail_free_bytes_ -= bytes;
}
}
bool HasSpace(size_t required_space) const {
return writable_bytes() >= required_space;
}
bool Empty(size_t sector_size_bytes) const {
return writable_bytes() == sector_size_bytes;
}
// Returns the number of bytes that would be recovered if this sector is
// garbage collected.
size_t RecoverableBytes(size_t sector_size_bytes) const {
return sector_size_bytes - valid_bytes_ - writable_bytes();
}
static constexpr size_t max_sector_size() { return kMaxSectorSize; }
private:
static constexpr uint16_t kCorruptSector = UINT16_MAX;
static constexpr size_t kMaxSectorSize = UINT16_MAX - 1;
uint16_t tail_free_bytes_; // writable bytes at the end of the sector
uint16_t valid_bytes_; // sum of sizes of valid entries
};
} // namespace pw::kvs::internal