12#include "ravel/clock.hpp"
13#include "ravel/rng.hpp"
14#include "ravel/scheduler.hpp"
15#include "ravel/trace.hpp"
19using DiskId = std::size_t;
21enum class DiskStatus {
31const char* to_string(DiskStatus status)
noexcept;
110 Disk& operator=(
const Disk&) =
delete;
113 const std::string&
name() const noexcept {
return name_; }
118 template <
typename Result>
121 bool await_ready()
const noexcept {
return false; }
122 void await_suspend(std::coroutine_handle<>) {
126 disk_.scheduler_.make_runnable(task);
129 Result await_resume() {
return std::move(result_); }
134 : disk_(disk), finish_(std::move(finish)) {}
137 std::function<
Result()> finish_;
149 std::uint64_t length);
195 using InodeId = std::uint64_t;
197 struct PendingWrite {
198 std::uint64_t sequence;
199 std::uint64_t offset;
205 std::vector<PendingWrite> pending;
206 std::uint64_t logical_size = 0;
209 enum class NameChange { Create, Rename, Remove };
212 struct PendingNameChange {
213 std::uint64_t sequence;
220 using Names = std::map<std::string, InodeId>;
225 void record(TraceEventKind kind) { trace_.
record({scheduler_.
now(), id_, kind}); }
227 DiskStatus finish_write(
const std::string& path, std::uint64_t offset,
const std::string& data,
228 std::uint64_t epoch);
229 ReadResult finish_read(
const std::string& path, std::uint64_t offset, std::uint64_t length,
230 std::uint64_t epoch);
231 DiskStatus finish_sync(
const std::string& path, std::uint64_t horizon, std::uint64_t epoch);
232 DiskStatus finish_rename(
const std::string& from,
const std::string& to, std::uint64_t epoch);
233 DiskStatus finish_remove(
const std::string& path, std::uint64_t epoch);
234 DiskStatus finish_sync_dir(
const std::string& dir, std::uint64_t horizon, std::uint64_t epoch);
235 ListResult finish_list(
const std::string& dir, std::uint64_t epoch);
238 void make_durable(std::size_t count);
240 static void apply(std::string& bytes, std::uint64_t offset,
const std::string& data);
241 static void apply(Names& names,
const PendingNameChange& change);
242 static void refresh_logical_size(Inode& inode);
243 static std::string parent_of(
const std::string& path);
247 DiskFaultSpec fault_;
248 Scheduler& scheduler_;
252 std::map<InodeId, Inode> inodes_;
253 Names visible_names_;
254 Names durable_names_;
255 std::vector<PendingNameChange> pending_names_;
256 InodeId next_inode_ = 1;
257 std::uint64_t next_sequence_ = 0;
258 std::uint64_t epoch_ = 0;
An operation in flight; co_await it to get its result.
Definition disk.hpp:119
A virtual disk holding named files, with the failure behavior that makes storage code hard to get rig...
Definition disk.hpp:99
Disk(const Disk &)=delete
Pending operations refer to this object, so it must never move.
Operation< DiskStatus > sync(std::string path)
Makes every write to the file that completed before this call was issued durable, and the file's crea...
std::uint64_t crash_count() const noexcept
How many times crash() has been called.
Definition disk.hpp:179
static constexpr std::size_t kSectorSize
A write torn by a crash is cut at a multiple of this many bytes.
Definition disk.hpp:102
Disk(DiskId id, std::string name, DiskFaultSpec fault, Scheduler &scheduler, VirtualRng &rng, Trace &trace)
Created by Simulation::add_disk; you do not construct one yourself.
Operation< DiskStatus > rename(std::string from, std::string to)
Renames a file, replacing to if it exists. NotFound if from does not.
std::string durable_contents(const std::string &path) const
The file as a crash right now would leave it at best: only durable data, and empty unless the file's ...
bool durable_exists(const std::string &path) const
Whether the file's name would survive a crash right now.
Operation< DiskStatus > sync_dir(std::string dir)
Makes durable every directory change, made before this call was issued, up to the last one that touch...
Operation< ListResult > list(std::string dir)
The entries directly inside dir.
std::uint64_t file_size(const std::string &path) const
The file's size as reads see it (0 if it does not exist).
std::uint64_t used_bytes() const
Total bytes of all files, as reads see them.
const DiskFaultSpec & fault() const noexcept
The fault settings this disk was created with.
Definition disk.hpp:115
Operation< DiskStatus > write(std::string path, std::uint64_t offset, std::string data)
Writes data at offset, creating the file if it does not exist and growing it (with zero bytes) if nee...
Operation< DiskStatus > remove(std::string path)
Removes a file. NotFound if it does not exist.
const std::string & name() const noexcept
The name given to add_disk.
Definition disk.hpp:113
Operation< ReadResult > read(std::string path, std::uint64_t offset, std::uint64_t length)
Reads up to length bytes at offset, seeing every completed write.
Cooperative, single-threaded task scheduler.
Definition scheduler.hpp:65
void call_after(VirtualClock::Tick delay, std::function< void()> action)
Runs action once the clock reaches now() + delay.
VirtualClock::Tick now() const noexcept
The current virtual time.
Definition scheduler.hpp:133
TaskId current_task() const noexcept
The task being resumed right now. Valid only inside a task.
Definition scheduler.hpp:136
Ordered record of everything that happened during a run (scheduling decisions and message fates),...
Definition trace.hpp:48
void record(const TraceEvent &event)
Appends an event and folds it into the digest.
std::uint64_t Tick
Virtual time, in ticks. A tick has no fixed real-world length.
Definition clock.hpp:15
The one source of randomness a Simulation may use.
Definition rng.hpp:28
std::uint64_t next_between(std::uint64_t low, std::uint64_t high)
Uniform in [low, high], both included. low must not exceed high.
Injectable disk behavior.
Definition disk.hpp:49
double sync_error_probability
In [0, 1].
Definition disk.hpp:64
VirtualClock::Tick latency_max
The upper end of the range above.
Definition disk.hpp:57
VirtualClock::Tick latency_min
Each operation takes a uniformly random time in [min, max].
Definition disk.hpp:55
std::uint64_t capacity_bytes
Total bytes across all files.
Definition disk.hpp:52
double write_error_probability
In [0, 1]. Writes, renames and removes fail with IoError, changing nothing.
Definition disk.hpp:60
The outcome of Disk::list.
Definition disk.hpp:41
std::vector< std::string > names
Sorted; a subdirectory is listed as "name/".
Definition disk.hpp:44
DiskStatus status
Ok, or why the listing failed.
Definition disk.hpp:43
The outcome of Disk::read.
Definition disk.hpp:34
std::string data
Shorter than asked if the read ran past the end of the file.
Definition disk.hpp:37
DiskStatus status
Ok, or why the read failed (for example NotFound).
Definition disk.hpp:36
How one run ended.
Definition simulation.hpp:56