Atomic-write JSON configuration backend. More...
#include <phosphor-config/include/PhosphorConfig/JsonBackend.h>
Public Types | |
| enum class | SyncPolicy { Synchronous , Deferred } |
Sync timing policy. See setSyncPolicy for the full contract. More... | |
Public Member Functions | |
| JsonBackend (QString filePath) | |
Construct a backend backed by filePath. | |
| ~JsonBackend () override | |
| std::unique_ptr< IGroup > | group (const QString &name) override |
| Return a scoped view into the named group. | |
| void | reparseConfiguration () override |
| Re-read configuration from disk, discarding any pending in-memory changes. | |
| bool | sync () override |
| Flush pending writes to disk. | |
| void | deleteGroup (const QString &name) override |
| Delete an entire group and everything inside it. | |
| QString | readRootString (const QString &key, const QString &defaultValue={}) const override |
| Read/write ungrouped (root-level) keys. | |
| void | writeRootString (const QString &key, const QString &value) override |
| void | removeRootKey (const QString &key) override |
| QStringList | groupList () const override |
| Enumerate every top-level group name. | |
| void | setPathResolver (std::shared_ptr< IGroupPathResolver > resolver) override |
| Attach a custom path resolver. | |
| std::shared_ptr< IGroupPathResolver > | pathResolver () const override |
Currently-installed resolver, or nullptr when none is set (also the default for backends that ignore setPathResolver). | |
| void | setRootGroupName (const QString &name) |
Change the JSON object that receives ungrouped writeRootString calls. | |
| QString | rootGroupName () const |
| void | setVersionStamp (const QString &key, int version) override |
Stamp-on-sync: if non-empty, every sync() that writes the file will insert key = version when the key is absent from the root. | |
| std::pair< QString, int > | versionStamp () const override |
Currently-installed version stamp as {key, version}. | |
| bool | applyMigration (const Schema &schema) override |
Run schema's migration chain against the in-memory root, and if any step bumps the version stamp, atomically rewrite the backing file and refresh the in-memory state. | |
| QJsonObject | jsonRootSnapshot () const |
| Read-only access to the in-memory document. | |
| QString | filePath () const |
Backing file path (useful for migration-chain callers that need to rewrite via writeJsonAtomically during schema upgrades). | |
| void | clearDirty () |
| Clear the dirty flag without writing. | |
| void | replaceRoot (QJsonObject root) |
Replace the in-memory document with root. | |
| void | setSyncPolicy (SyncPolicy policy, int debounceMs=500) |
Configure when sync() commits to disk. | |
| SyncPolicy | syncPolicy () const |
| bool | flushPending () |
| Flush any pending deferred-sync write to disk now. | |
Public Member Functions inherited from PhosphorConfig::IBackend | |
| virtual | ~IBackend ()=default |
| IBackend (const IBackend &)=delete | |
| IBackend & | operator= (const IBackend &)=delete |
Static Public Member Functions | |
| static bool | writeJsonAtomically (const QString &filePath, const QJsonObject &root) |
Atomically write root to filePath (temp file + rename via QSaveFile). | |
Additional Inherited Members | |
Protected Member Functions inherited from PhosphorConfig::IBackend | |
| IBackend ()=default | |
Atomic-write JSON configuration backend.
Reads and writes a single JSON document. Writes are deferred until sync() is called and then committed via QSaveFile (temp file + rename, safe against crashes and power loss).
Group resolution order:
IGroupPathResolver is installed and returns a path, use it.The "root group" (see rootGroupName) holds ungrouped keys written via writeRootString. Defaults to "General" for compatibility with QSettings INI behaviour.
|
strong |
Sync timing policy. See setSyncPolicy for the full contract.
| Enumerator | |
|---|---|
| Synchronous |
Default — matches the pre-policy behaviour so switching an existing consumer requires no change. |
| Deferred |
The actual flush happens on the timer's timeout, on the same thread that owns the backend (i.e. whichever thread is pumping the event loop that owns the timer). Callers that need a guaranteed-committed state before proceeding (e.g. closing a save dialog, shutting down a daemon) call Requires a running event loop to actually fire. Tests that exercise this path must call |
|
explicit |
Construct a backend backed by filePath.
The file is loaded immediately; missing or malformed files start with an empty root object (a warning is logged for malformed content).
|
override |
|
overridevirtual |
Run schema's migration chain against the in-memory root, and if any step bumps the version stamp, atomically rewrite the backing file and refresh the in-memory state.
Returns true unless the atomic disk rewrite fails — in which case the backend stays at the unmigrated state and the next successful sync() retries. Consumers that need the "did migrations actually apply" bit should check versionStamp() before and after, not this return value.
Reimplemented from PhosphorConfig::IBackend.
| void PhosphorConfig::JsonBackend::clearDirty | ( | ) |
Clear the dirty flag without writing.
Used by tests + async I/O that commits snapshots off-thread.
|
overridevirtual |
Delete an entire group and everything inside it.
Intermediate parents are pruned if they become empty (dot-path groups only).
Implements PhosphorConfig::IBackend.
| QString PhosphorConfig::JsonBackend::filePath | ( | ) | const |
Backing file path (useful for migration-chain callers that need to rewrite via writeJsonAtomically during schema upgrades).
| bool PhosphorConfig::JsonBackend::flushPending | ( | ) |
Flush any pending deferred-sync write to disk now.
No-op when the policy is Synchronous or when the backend is not dirty. Returns the commit result (or true when there was nothing to flush). Safe to call from any context that would otherwise be able to call sync().
|
overridevirtual |
Return a scoped view into the named group.
Caller owns the pointer; destroy it before asking for another group on this backend.
Implements PhosphorConfig::IBackend.
|
overridevirtual |
Enumerate every top-level group name.
Dot-path groups are returned with their full path ("Snapping", "Snapping.Behavior", ...). Groups produced by a plugged-in IGroupPathResolver appear in the resolver's preferred external form.
Implements PhosphorConfig::IBackend.
| QJsonObject PhosphorConfig::JsonBackend::jsonRootSnapshot | ( | ) | const |
Read-only access to the in-memory document.
Implicitly shared (COW), so the copy is cheap and isolated from future mutations.
|
overridevirtual |
Currently-installed resolver, or nullptr when none is set (also the default for backends that ignore setPathResolver).
Reimplemented from PhosphorConfig::IBackend.
|
overridevirtual |
Read/write ungrouped (root-level) keys.
Implements PhosphorConfig::IBackend.
|
overridevirtual |
Implements PhosphorConfig::IBackend.
|
overridevirtual |
Re-read configuration from disk, discarding any pending in-memory changes.
Must not be called while a group view is live.
Implements PhosphorConfig::IBackend.
| void PhosphorConfig::JsonBackend::replaceRoot | ( | QJsonObject | root | ) |
Replace the in-memory document with root.
Marks the backend dirty — callers who paired this with a successful writeJsonAtomically may call clearDirty() immediately after to restore the "in-memory matches disk" invariant. Must not be called while any JsonGroup views are alive.
| QString PhosphorConfig::JsonBackend::rootGroupName | ( | ) | const |
|
overridevirtual |
Attach a custom path resolver.
Passing nullptr removes it. Safe to call at any time; the resolver is consulted on every group access, so it should be cheap.
Reimplemented from PhosphorConfig::IBackend.
| void PhosphorConfig::JsonBackend::setRootGroupName | ( | const QString & | name | ) |
Change the JSON object that receives ungrouped writeRootString calls.
Defaults to "General". Call before the first write.
| void PhosphorConfig::JsonBackend::setSyncPolicy | ( | SyncPolicy | policy, |
| int | debounceMs = 500 |
||
| ) |
Configure when sync() commits to disk.
debounceMs is only consulted for Deferred policy; it sets the coalescing window during which repeated sync() calls restart the same timer. Values <= 0 are clamped to 1 ms.
Safe to call at any time. Switching from Deferred back to Synchronous also flushes any pending deferred write so the in-memory and on-disk state agree on return.
|
overridevirtual |
Stamp-on-sync: if non-empty, every sync() that writes the file will insert key = version when the key is absent from the root.
Used by consumers who pair a JsonBackend with a Schema so fresh stores carry the current version from day one. Default disables the behaviour (empty key).
Reimplemented from PhosphorConfig::IBackend.
|
overridevirtual |
Flush pending writes to disk.
No-op when nothing is dirty. Returns true on success (or when there was nothing to flush), false on an I/O error — backends log the reason before returning.
Implements PhosphorConfig::IBackend.
| SyncPolicy PhosphorConfig::JsonBackend::syncPolicy | ( | ) | const |
|
overridevirtual |
Currently-installed version stamp as {key, version}.
Returns an empty key when no stamp is installed. Used by shared-backend safety checks (see Store::Store) to detect a clobber.
Reimplemented from PhosphorConfig::IBackend.
|
static |
Atomically write root to filePath (temp file + rename via QSaveFile).
Exposed for use by MigrationRunner and other external callers that already have a QJsonObject in hand. Returns true on success.
|
overridevirtual |
Implements PhosphorConfig::IBackend.