dfx 0.1.0
Linux-based dynamic dataflow executor
Loading...
Searching...
No Matches
dfx::Utils::AtomicFileWriter Class Reference

Atomically writes a file by staging data and publishing it in a single step. More...

#include <dfx-utilities/AtomicFileWriter.hpp>

Classes

struct  Options
 Options controlling publish permissions and durability. More...

Public Types

enum class  State { Open , Discarded , Published , Durable }
 Current lifecycle state of the writer. More...
enum class  Backend { TmpFile , Mktemp }
 Filesystem operation used to create the temporary file. More...

Public Member Functions

 AtomicFileWriter (fs::path p)
 Construct an atomic writer targeting p with default options.
 AtomicFileWriter (fs::path p, Options options)
 Construct an atomic writer targeting p with explicit options.
 DFX_PRIVATE_STATE_DECLARE_RULE_OF_5 (AtomicFileWriter)
fs::path const & path () const noexcept
 Returns the target path.
State state () const noexcept
 Returns the current state.
bool isOpen () const noexcept
 Convenience: true if state() == State::Open.
bool isDiscarded () const noexcept
 Convenience: true if state() == State::Discarded.
bool isPublished () const noexcept
 Convenience: true if the file has been published (atomically visible).
bool isDurable () const noexcept
 Convenience: true if the file publish operation is durable.
void write (std::byte const *data, std::size_t len)
 Append raw bytes to the staged file.
void write (std::span< std::byte const > data)
 Append raw bytes to the staged file.
void write (std::string_view data)
 Append text/binary data to the staged file.
void commit ()
 Publish the staged file to the target path.
void discard () noexcept
 Discard the staged file and release resources.

Detailed Description

Atomically writes a file by staging data and publishing it in a single step.

AtomicFileWriter implements the common "write-then-atomic-replace" pattern with explicit durability options.

The writer creates a temporary inode in the same directory as the target file, writes all data to it, and on commit() publishes it atomically as the final path.

This class provides two distinct notions of success:

  • Published: the directory entry has been updated atomically to point to the new file.
  • Durable: the publish operation has been made durable against power loss by syncing the parent directory (when enabled).
Note
  • The destructor never commits implicitly. If you never call commit(), changes are not published. The destructor will call discard() and release resources.
  • commit() is idempotent after a successful commit (Published/Durable). Calling it again is a no-op.
  • Obviously once discarded, the writer cannot be committed.
Durability guarantees
When Options::fsyncFile is enabled, commit() syncs the staged file contents prior to publishing. When Options::fsyncDir is enabled, commit() also attempts to sync the parent directory so that the directory entry update survives a crash or power loss.

If syncing the directory fails, the file may still be Published (visible and replaced) but not Durable (not guaranteed to persist across sudden power loss). In that case the state remains Published and a warning may be emitted.

Thread-safety
This class is not thread-safe. External synchronization is required if accessed from multiple threads.
Typical usage
dfx::Utils::AtomicFileWriter w("/var/lib/dfx/state.json");
w.write(serializedJson);
w.commit(); // atomic publish (and optional durability)
Atomically writes a file by staging data and publishing it in a single step.
Definition AtomicFileWriter.hpp:64

Member Enumeration Documentation

◆ Backend

Filesystem operation used to create the temporary file.

Enumerator
TmpFile 

Use open(O_TMPFILE) preferably (will fallback to Mktemp if EOPNOTSUPP).

Mktemp 

Use mkostemp function to create the temporary file.

◆ State

Current lifecycle state of the writer.

State transitions:

  • Open -> Discarded via discard()
  • Open -> Published via commit()
  • Published -> Durable via commit() if directory sync succeeds (and enabled)
Enumerator
Open 

The writer is active: data can be written and can be committed or discarded.

Discarded 

The writer has been discarded: resources are released and nothing new is published.

Published 

The target path has been replaced/created atomically (visible in the filesystem).

Durable 

Published + parent directory sync succeeded (when enabled), providing durability for the rename/link.

Constructor & Destructor Documentation

◆ AtomicFileWriter() [1/2]

dfx::Utils::AtomicFileWriter::AtomicFileWriter ( fs::path p)
explicit

Construct an atomic writer targeting p with default options.

The staging file is created in the same directory as p to ensure an atomic publish.

Parameters
pTarget file path that will be replaced/created upon commit.

◆ AtomicFileWriter() [2/2]

dfx::Utils::AtomicFileWriter::AtomicFileWriter ( fs::path p,
Options options )

Construct an atomic writer targeting p with explicit options.

Parameters
pTarget file path that will be replaced/created upon commit.
optionsDurability and permission options.

Member Function Documentation

◆ commit()

void dfx::Utils::AtomicFileWriter::commit ( )

Publish the staged file to the target path.

On success, the target path is updated atomically and state becomes State::Published. If Options::fsyncDir is enabled and directory sync succeeds, state becomes State::Durable.

Idempotent once published: if already Published or Durable, this function returns without effect.

Precondition
state() must not be State::Discarded.

◆ discard()

void dfx::Utils::AtomicFileWriter::discard ( )
noexcept

Discard the staged file and release resources.

After discard, no new data is published. Calling commit() or write() afterwards is invalid. This function is safe to call multiple times.

◆ isDiscarded()

bool dfx::Utils::AtomicFileWriter::isDiscarded ( ) const
inlinenoexcept

Convenience: true if state() == State::Discarded.

◆ isDurable()

bool dfx::Utils::AtomicFileWriter::isDurable ( ) const
inlinenoexcept

Convenience: true if the file publish operation is durable.

◆ isOpen()

bool dfx::Utils::AtomicFileWriter::isOpen ( ) const
inlinenoexcept

Convenience: true if state() == State::Open.

◆ isPublished()

bool dfx::Utils::AtomicFileWriter::isPublished ( ) const
inlinenoexcept

Convenience: true if the file has been published (atomically visible).

◆ path()

fs::path const & dfx::Utils::AtomicFileWriter::path ( ) const
noexcept

Returns the target path.

◆ state()

State dfx::Utils::AtomicFileWriter::state ( ) const
noexcept

Returns the current state.

◆ write() [1/3]

void dfx::Utils::AtomicFileWriter::write ( std::byte const * data,
std::size_t len )
inline

Append raw bytes to the staged file.

This method does not publish anything. Data becomes visible only after commit().

Parameters
dataPointer to bytes to write.
lenNumber of bytes to write.
Precondition
isOpen() must be true.

◆ write() [2/3]

void dfx::Utils::AtomicFileWriter::write ( std::span< std::byte const > data)
inline

Append raw bytes to the staged file.

This method does not publish anything. Data becomes visible only after commit().

Parameters
dataBytes to write.
Precondition
isOpen() must be true.

◆ write() [3/3]

void dfx::Utils::AtomicFileWriter::write ( std::string_view data)

Append text/binary data to the staged file.

This method does not publish anything. Data becomes visible only after commit(). data may contain NUL bytes; it is treated as raw bytes.

Parameters
dataData to write.
Precondition
isOpen() must be true.

The documentation for this class was generated from the following file: