ra8-firmware 0.1.0
Bare-metal firmware for the Renesas RA8 family (RA8D2 / RA8P1)
Loading...
Searching...
No Matches
mdl_state.h File Reference

Persistent per-series library state for the media downloader. More...

#include <float.h>
#include <stddef.h>
#include <stdint.h>
#include "mdl_config.h"
#include "mdl_extract.h"
#include "mdl_net.h"
#include "mdl_storage.h"
#include "ra8_err.h"
Include dependency graph for mdl_state.h:
This graph shows which files directly or indirectly include this file:

Go to the source code of this file.

Data Structures

struct  mdl_chapter_rec_t
 One chapter's coverage in library state. More...
struct  mdl_page_rec_t
 One page's dedup/verify record in the series-wide pool. More...
struct  mdl_state_t
 One series' complete persistent state (declare at file scope). More...

Enumerations

enum  mdl_binary64_parameter_t : int16_t {
  k_mdl_binary64_mantissa_bits = 53 ,
  k_mdl_binary64_max_exponent = 1024 ,
  k_mdl_binary64_min_exponent = -1021
}
 IEC 60559 binary64 parameters required by the persisted schema. More...
enum  mdl_state_limit_t : uint16_t {
  k_mdl_state_version_v1 = 1 ,
  k_mdl_state_version_v2 = 2 ,
  k_mdl_state_version_v3 = 3 ,
  k_mdl_state_version = 4 ,
  k_mdl_chapter_id_max = 128 ,
  k_mdl_title_max = 192 ,
  k_mdl_summary_max = 1024 ,
  k_mdl_person_max = 128 ,
  k_mdl_language_max = 16 ,
  k_mdl_relpath_max = 200 ,
  k_mdl_cfgpath_max = 512 ,
  k_mdl_max_chapters = 512
}
 Fixed capacities and the schema version (zero dynamic allocation). More...
enum  mdl_state_reading_direction_t : uint8_t {
  k_mdl_state_read_ltr = 0 ,
  k_mdl_state_read_rtl = 1
}
 Persisted fixed-layout reading direction. More...
enum  mdl_state_pool_t : uint32_t { k_mdl_max_page_recs = 8192U }
 Page pool capacity (kept separate: it needs a 32-bit count). More...

Functions

void mdl_state_init (mdl_state_t *st)
 Reset a state object to an empty, current-version library.
void mdl_state_set_series (mdl_state_t *st, const char *url, const char *title, const char *site_name, const char *site_host, const char *config_path)
 Record the series identity and the descriptor used.
bool mdl_state_set_series_metadata (mdl_state_t *st, const char *summary, const char *writer, const char *artist, const char *cover_url, const char *cover_path, const char *language, mdl_state_reading_direction_t direction)
 Set the optional rich metadata persisted for a series.
ra8_err_t mdl_state_load (mdl_storage_t *storage, const char *path, mdl_state_t *st)
 Load a series' newest valid state through injected portable storage.
ra8_err_t mdl_state_load_authenticated (mdl_storage_t *storage, const char *path, mdl_state_t *st)
 Load only an authenticated checksummed state generation.
ra8_err_t mdl_state_save (mdl_storage_t *storage, const char *path, const mdl_state_t *st, bool *out_published)
 Publish a checksummed successor without sacrificing the newest state.
ra8_err_t mdl_state_probe (mdl_storage_t *storage, const char *path, bool *out_exists)
 Probe the complete two-generation state marker through portable storage.
mdl_chapter_rec_tmdl_state_find_chapter (mdl_state_t *st, const char *id)
 Find a chapter record by its stable identifier.
mdl_chapter_rec_tmdl_state_add_chapter (mdl_state_t *st, const char *id, const char *url, long number)
 Find or append a chapter record, returning it.
mdl_chapter_rec_tmdl_state_add_chapter_numbered (mdl_state_t *st, const char *id, const char *url, double number, bool number_known)
 Find or append a chapter with explicit parsed-number presence.
bool mdl_state_set_chapter_metadata (mdl_chapter_rec_t *chapter, const char *title, double number, bool number_known)
 Set a chapter's display title and explicit parsed number.
bool mdl_state_chapter_complete (const mdl_state_t *st, const char *id)
 Whether a chapter is recorded fully fetched and verified.
uint16_t mdl_state_chapter_pages (const mdl_state_t *st, const char *id)
 Recorded page count for a chapter (0 when unknown).
const mdl_page_rec_tmdl_state_find_page (const mdl_state_t *st, uint64_t url_hash)
 Find a page record by its source-URL hash (the dedup lookup).
bool mdl_state_add_page (mdl_state_t *st, uint64_t url_hash, uint64_t content_hash, const char *rel_path, const char *etag, const char *last_modified, int64_t fetched_at, uint16_t response_status)
 Add or replace a URL-keyed page cache record.
bool mdl_state_note_page_response (mdl_state_t *st, uint64_t url_hash, int64_t fetched_at, uint16_t response_status)
 Refresh the observed HTTP result for one existing URL cache entry.
void mdl_state_coverage (const mdl_state_t *st, char *buf, size_t cap)
 Render a one-line coverage summary (chapter span, count, gaps).

Detailed Description

Persistent per-series library state for the media downloader.

Without this store mdl kept nothing between runs: resuming was an index into a freshly scraped list (--start K), there was no "fetch only what is new", a kill mid-chapter left an unrecorded partial directory, and two runs (or two chapters) sharing an image re-downloaded it. This module is the on-disk record that fixes all four: one bounded, versioned state payload per series holding the series identity, the site descriptor used, and – per chapter – the parsed chapter identifier, source URL, page count, completion status and fetch time, plus a series-wide pool of per-page content identities.

Because chapters are keyed by a parsed identifier (mdl_urlname_last_segment) rather than list position, --start can mean "resume where we left off" and --update can mean "only chapters we do not already have complete", both stable as the site adds or reorders chapters. Because every page carries a source-URL hash and a content hash, a re-run skips a byte-identical image already held (mdl_state_find_page) and a torn file is detected and refetched rather than silently packaged.

On-disk payload format (v4)

A flat, line-oriented, TAB-separated text payload under the logical .mdl_state path, deliberately simple so it is human-readable and ports unchanged to the RA8. A leading # marks a comment; blank lines are ignored. Each record is a one-letter type followed by TAB-separated fields:

# mdl library state v4
V<TAB>4                                         schema version
S<TAB><series-url>                              series URL
T<TAB><series-title>                            series title
N<TAB><site-name>                               site descriptor name
H<TAB><site-host>                               site host
G<TAB><config-path>                             descriptor file used
D/W/A/O/K/L/R<TAB>value                         rich series metadata
C<TAB>id<TAB>known<TAB>binary64-hex<TAB>done<TAB>pages<TAB>ready<TAB>epoch<TAB>url<TAB>title
P<TAB>url_hash_hex<TAB>content_hash_hex<TAB>rel_path<TAB>etag<TAB>last_modified<TAB>epoch<TAB>status

Version 1 files remain readable and are migrated in memory; their integral chapter number is considered known only when nonzero because v1 had no explicit presence bit. Version 2 decimal-number records are also migrated with a bounded ASCII-only parser; version 3 stores the exact finite in-memory binary64 identity as 16 canonical hex digits, independent of locale/libc. Version 3 page records are migrated with an unknown fetch time/status. The next save always emits v4. Current saves wrap the payload in a fixed canonical-big-endian envelope containing a monotonic sequence, exact payload length, and CRC-32 checksums. Two physical generations (.mdl_state and .mdl_state.alt) alternate through validated create-new transactions, so the newest accepted generation is never removed before its successor is published. This provides truthful recovery on both atomic-replace hosts and FAT/VFS backends that cannot replace atomically.

Definition in file mdl_state.h.

Enumeration Type Documentation

◆ mdl_binary64_parameter_t

enum mdl_binary64_parameter_t : int16_t

IEC 60559 binary64 parameters required by the persisted schema.

Enumerator
k_mdl_binary64_mantissa_bits 

Binary64 significand precision.

k_mdl_binary64_max_exponent 

Binary64 maximum exponent.

k_mdl_binary64_min_exponent 

Binary64 minimum exponent.

Definition at line 72 of file mdl_state.h.

◆ mdl_state_limit_t

enum mdl_state_limit_t : uint16_t

Fixed capacities and the schema version (zero dynamic allocation).

Enumerator
k_mdl_state_version_v1 

Legacy integral schema accepted.

k_mdl_state_version_v2 

Legacy decimal schema accepted.

k_mdl_state_version_v3 

Legacy cache-metadata schema accepted.

k_mdl_state_version 

Timestamped cache schema written now.

k_mdl_chapter_id_max 

Chapter identifier bytes (sanitised).

k_mdl_title_max 

Series title bytes.

k_mdl_summary_max 

Series summary bytes.

k_mdl_person_max 

Writer/artist bytes.

k_mdl_language_max 

BCP-47 language bytes.

k_mdl_relpath_max 

Page path relative to the series dir.

k_mdl_cfgpath_max 

Site-descriptor path bytes.

k_mdl_max_chapters 

Chapters tracked per series.

Definition at line 92 of file mdl_state.h.

◆ mdl_state_pool_t

enum mdl_state_pool_t : uint32_t

Page pool capacity (kept separate: it needs a 32-bit count).

Enumerator
k_mdl_max_page_recs 

Per-page content records per series.

Definition at line 114 of file mdl_state.h.

◆ mdl_state_reading_direction_t

Persisted fixed-layout reading direction.

Enumerator
k_mdl_state_read_ltr 

Left-to-right page progression.

k_mdl_state_read_rtl 

Right-to-left page progression.

Definition at line 108 of file mdl_state.h.

Function Documentation

◆ mdl_state_add_chapter()

mdl_chapter_rec_t * mdl_state_add_chapter ( mdl_state_t * st,
const char * id,
const char * url,
long number )

Find or append a chapter record, returning it.

Parameters
[in,out]stState to update (never NULL).
[in]idChapter identifier (never NULL).
[in]urlChapter page URL (never NULL).
[in]numberParsed chapter number (0 when unnumbered).
Returns
The existing or newly-added record, or NULL when the table is full.
Return values
NULLA NULL argument, or k_mdl_max_chapters already reached.
Precondition
st, id, url are non-NULL and NUL-terminated.
The caller treats NULL as "table full" and degrades, never crashes.
Postcondition
A new record starts incomplete with page_count == 0; a nonzero number is marked known and zero retains legacy "unknown" semantics.
st->chapter_count grows by at most one.
Note
Not thread-safe.
Since
0.1.0

Definition at line 257 of file mdl_state.c.

References mdl_state_add_chapter_numbered().

◆ mdl_state_add_chapter_numbered()

mdl_chapter_rec_t * mdl_state_add_chapter_numbered ( mdl_state_t * st,
const char * id,
const char * url,
double number,
bool number_known )

Find or append a chapter with explicit parsed-number presence.

Unlike the source-compatible mdl_state_add_chapter wrapper, this API keeps chapter zero distinct from an unknown number and preserves fractional chapter numbers. An unknown number must be supplied canonically as 0.0.

Parameters
[in,out]stState to update (never NULL).
[in]idChapter identifier (never NULL).
[in]urlChapter page URL (never NULL).
[in]numberFinite parsed chapter number, or 0.0 if unknown.
[in]number_knownWhether number was explicitly parsed.
Returns
The existing or newly-added record, or NULL when invalid/full.
Return values
NULLA NULL/malformed argument, invalid number, or full table.
Precondition
st, id, and url are non-NULL.
id and url are NUL-terminated and fit their fixed fields.
Postcondition
A new record stores number and number_known exactly.
An existing record is returned without changing its metadata.
Note
Not thread-safe.
Since
0.1.0

Definition at line 262 of file mdl_state.c.

References mdl_state_t::chapter_count, mdl_chapter_rec_t::chapter_id, mdl_state_t::chapters, internal_mdl_state_chapter_number_valid(), k_mdl_chapter_id_max, k_mdl_max_chapters, k_mdl_url_max, mdl_state_find_chapter(), memset(), mdl_chapter_rec_t::number, mdl_chapter_rec_t::number_known, priv_mdl_state_field_valid(), and mdl_chapter_rec_t::source_url.

Referenced by internal_mdl_fetch_process_chapter(), internal_mdl_state_apply_chapter_values(), and mdl_state_add_chapter().

◆ mdl_state_add_page()

bool mdl_state_add_page ( mdl_state_t * st,
uint64_t url_hash,
uint64_t content_hash,
const char * rel_path,
const char * etag,
const char * last_modified,
int64_t fetched_at,
uint16_t response_status )

Add or replace a URL-keyed page cache record.

Adds or refreshes a bounded page identity and its optional HTTP validators. The URL hash is the sole cache key: when magic-byte validation changes a page's canonical extension or a combined layout relocates it, the existing record is replaced instead of leaving an older path first in lookup order. Empty or NULL validator strings are stored as empty values.

Parameters
[in,out]stState to update (never NULL).
[in]url_hashFNV-1a 64 of the page's source URL.
[in]content_hashFNV-1a 64 of the fetched page bytes.
[in]rel_pathPage path relative to the series dir (never NULL).
[in]etagCached ETag, or NULL when unavailable.
[in]last_modifiedCached Last-Modified, or NULL when unavailable.
[in]fetched_atMost recent fetch completion time in epoch seconds.
[in]response_statusMost recent HTTP status, or zero if unknown.
Returns
Whether the record was stored.
Return values
trueThe record was appended or the existing URL record replaced.
falseThe pool is full (k_mdl_max_page_recs) or a NULL argument; dedup simply degrades to a refetch next time, never a crash.
Precondition
st and rel_path are non-NULL; rel_path is NUL-terminated.
rel_path is a sanitised path with no ../leading /.
Postcondition
On true, st->page_rec_count grows by one only for a new URL hash.
On false, st is unchanged.
Note
Not thread-safe.
See also
mdl_state_find_page
Since
0.1.0

Definition at line 347 of file mdl_state.c.

References mdl_page_rec_t::content_hash, mdl_page_rec_t::etag, mdl_page_rec_t::fetched_at, internal_mdl_state_page_response_valid(), k_mdl_etag_max, k_mdl_last_mod_max, k_mdl_max_page_recs, k_mdl_relpath_max, mdl_page_rec_t::last_modified, mdl_state_t::page_rec_count, mdl_state_t::pages, priv_mdl_state_field_valid(), mdl_page_rec_t::rel_path, mdl_page_rec_t::response_status, and mdl_page_rec_t::url_hash.

Referenced by internal_mdl_fetch_publish_page(), internal_mdl_fetch_try_reuse(), and internal_mdl_state_apply_page().

◆ mdl_state_chapter_complete()

bool mdl_state_chapter_complete ( const mdl_state_t * st,
const char * id )

Whether a chapter is recorded fully fetched and verified.

Parameters
[in]stState to query (never NULL).
[in]idChapter identifier (never NULL).
Returns
Whether id is present AND its record is complete.
Return values
trueThe chapter exists and every page is fetched and verified.
falseNot recorded, incomplete, or a NULL argument.
Precondition
st and id are non-NULL; id is NUL-terminated.
The caller uses this to decide --update skips.
Postcondition
st is not modified.
Note
Not thread-safe.
Since
0.1.0

Uses fixed-capacity state supplied by the caller without allocation. Any text retained by the state is copied into bounded records.

Postcondition
Documented outputs and the return value describe the same outcome.

Definition at line 308 of file mdl_state.c.

References mdl_state_t::chapter_count, mdl_chapter_rec_t::chapter_id, mdl_state_t::chapters, mdl_chapter_rec_t::complete, and strcmp().

◆ mdl_state_chapter_pages()

uint16_t mdl_state_chapter_pages ( const mdl_state_t * st,
const char * id )

Recorded page count for a chapter (0 when unknown).

The combined-download page numbering is derived from these counts, so a run that resumes reproduces the same continuous numbering an uninterrupted run would have produced.

Parameters
[in]stState to query (never NULL).
[in]idChapter identifier (never NULL).
Returns
The chapter's recorded page_count, or 0 if unknown/absent.
Return values
0The chapter is absent, unlearned, or a NULL argument was passed.
Precondition
st and id are non-NULL; id is NUL-terminated.
The caller treats 0 as "unknown", not "zero-page chapter".
Postcondition
st is not modified.
Note
Not thread-safe.
Since
0.1.0
Postcondition
Documented outputs and the return value describe the same outcome.

Definition at line 321 of file mdl_state.c.

References mdl_state_t::chapter_count, mdl_chapter_rec_t::chapter_id, mdl_state_t::chapters, mdl_chapter_rec_t::page_count, and strcmp().

◆ mdl_state_coverage()

void mdl_state_coverage ( const mdl_state_t * st,
char * buf,
size_t cap )

Render a one-line coverage summary (chapter span, count, gaps).

Summarises which chapters are complete for the library --list view: the count, the numeric span, and the missing chapter numbers inside that span, so a reader can spot a hole without reading the directory tree.

Parameters
[in]stState to summarise (never NULL).
[out]bufDestination buffer for the NUL-terminated line (never NULL).
[in]capCapacity of buf in bytes (must be > 0).
Returns
Nothing.
Precondition
st and buf are non-NULL; cap > 0.
The caller prints buf as one line.
Postcondition
buf is NUL-terminated.
st is not modified.
Note
Not thread-safe: writes caller storage.
Since
0.1.0

Definition at line 559 of file mdl_state.c.

References mdl_state_t::chapter_count, mdl_state_t::chapters, mdl_chapter_rec_t::complete, internal_mdl_state_append_gaps(), and internal_mdl_state_complete_span().

Referenced by internal_list_cb().

◆ mdl_state_find_chapter()

mdl_chapter_rec_t * mdl_state_find_chapter ( mdl_state_t * st,
const char * id )

Find a chapter record by its stable identifier.

Parameters
[in]stState to search (never NULL).
[in]idChapter identifier (never NULL).
Returns
The matching record, or NULL when none is recorded.
Return values
NULLNo chapter with id, or a NULL argument.
Precondition
st and id are non-NULL; id is NUL-terminated.
The caller must not retain the pointer across an add that may move data.
Postcondition
st is not modified.
Note
Not thread-safe.
Since
0.1.0

Definition at line 243 of file mdl_state.c.

References mdl_state_t::chapter_count, mdl_chapter_rec_t::chapter_id, mdl_state_t::chapters, and strcmp().

Referenced by internal_export_fresh_separate(), internal_mdl_state_apply_chapter_values(), and mdl_state_add_chapter_numbered().

◆ mdl_state_find_page()

const mdl_page_rec_t * mdl_state_find_page ( const mdl_state_t * st,
uint64_t url_hash )

Find a page record by its source-URL hash (the dedup lookup).

Parameters
[in]stState to search (never NULL).
[in]url_hashFNV-1a 64 of the candidate source URL.
Returns
The first matching page record, or NULL when none is held.
Return values
NULLNo page with url_hash, or a NULL st.
Precondition
st is non-NULL.
url_hash came from mdl_hash_str on the source URL.
Postcondition
st is not modified.
Note
Not thread-safe.
See also
mdl_state_add_page
Since
0.1.0

Definition at line 334 of file mdl_state.c.

References mdl_state_t::page_rec_count, mdl_state_t::pages, and mdl_page_rec_t::url_hash.

Referenced by internal_mdl_fetch_one_page(), internal_mdl_fetch_prepare_page(), and internal_mdl_fetch_try_reuse().

◆ mdl_state_init()

void mdl_state_init ( mdl_state_t * st)

Reset a state object to an empty, current-version library.

Parameters
[out]stState to clear (never NULL).
Returns
Nothing.
Precondition
st is non-NULL and addresses a full mdl_state_t.
The caller owns st for the duration (not thread-safe).
Postcondition
st->version == k_mdl_state_version and all counts are 0.
Every metadata string is the empty string.
Note
Not thread-safe: initialises caller storage.
Since
0.1.0

Uses fixed-capacity state supplied by the caller without allocation. Any text retained by the state is copied into bounded records.

Definition at line 52 of file mdl_state.c.

References k_mdl_state_version, memset(), and mdl_state_t::version.

Referenced by internal_mdl_state_load_mode(), internal_mdl_state_load_slot(), and priv_mdl_state_parse_file().

◆ mdl_state_load()

ra8_err_t mdl_state_load ( mdl_storage_t * storage,
const char * path,
mdl_state_t * st )

Load a series' newest valid state through injected portable storage.

Authenticates both journal generations, chooses the highest valid sequence, and falls back to the older valid generation if semantic parsing fails. A legacy unenveloped v1/v2 base file remains readable as sequence zero. When neither generation exists, st is initialized empty and success is returned. Any final failure also leaves st initialized empty.

Parameters
[in,out]storageInitialized, exclusively-owned storage binding.
[in]pathCanonical logical state path (never NULL).
[out]stState to fill; always left in a valid (possibly empty) form.
Returns
An ra8_err_t result.
Return values
k_ra8_okLoaded, or the file was absent (empty state).
k_ra8_err_invalid_argpath or st was NULL.
k_ra8_err_invalid_stateThe file exists but is corrupt/unsupported.
Precondition
All pointers are non-NULL and storage was initialized successfully.
The caller exclusively owns every workspace bound to storage.
Postcondition
st is always a valid state object on return (empty on any error).
No filesystem generation is modified.
Note
Not thread-safe: borrows every workspace in storage.
See also
mdl_state_save
Since
0.1.0

Definition at line 920 of file mdl_state_store.c.

References internal_mdl_state_load_mode().

Referenced by internal_run_series_paths(), and internal_verify_series_dir().

◆ mdl_state_load_authenticated()

ra8_err_t mdl_state_load_authenticated ( mdl_storage_t * storage,
const char * path,
mdl_state_t * st )
nodiscard

Load only an authenticated checksummed state generation.

Scans the logical base path and its .alt peer, rejects legacy unenveloped text, selects the highest valid authenticated sequence, and falls back to the older authenticated generation when semantic decoding fails. An absent marker initializes st empty and succeeds; every failure also leaves st initialized empty.

Parameters
[in,out]storageInitialized, exclusively-owned storage binding.
[in]pathCanonical logical state path.
[out]stState filled from one authenticated generation.
Returns
Canonical path, stream, authentication, or schema status.
Return values
k_ra8_okAn authenticated generation loaded or both peers were absent.
k_ra8_err_invalid_stateExisting generations failed authentication.
k_ra8_err_invalid_argA pointer, path, or binding is invalid.
Precondition
Required pointers are non-NULL and storage is initialized.
The caller exclusively owns all workspaces bound to storage.
Postcondition
st is a valid state object on every return, empty on failure.
No filesystem generation is modified.
Note
Use for library trust decisions; mdl_state_load preserves import compatibility with legacy unenveloped state.
Since
0.1.0

Definition at line 925 of file mdl_state_store.c.

References internal_mdl_state_load_mode().

Referenced by internal_library_visit(), and internal_resolve_removal_target().

◆ mdl_state_note_page_response()

bool mdl_state_note_page_response ( mdl_state_t * st,
uint64_t url_hash,
int64_t fetched_at,
uint16_t response_status )

Refresh the observed HTTP result for one existing URL cache entry.

Locates the record by its stable URL hash and atomically replaces only the completion time and response-status fields.

Parameters
[in,out]stState containing the URL-keyed record.
[in]url_hashFNV-1a 64 hash selecting the record.
[in]fetched_atCompleted request time in epoch seconds.
[in]response_statusHTTP response status in 100..599.
Returns
Whether an existing record and valid observation were updated.
Return values
trueThe matching record now carries the supplied observation.
falseNo record matched or the time/status was invalid.
Precondition
st is non-NULL and exclusively owned.
fetched_at is nonnegative.
Postcondition
Success changes only the two observation fields.
Failure leaves st unchanged.
Note
Used after a bodyless 304 revalidates already-verified local bytes.
Since
0.1.0

Definition at line 393 of file mdl_state.c.

References mdl_page_rec_t::fetched_at, internal_mdl_state_page_response_valid(), mdl_state_t::page_rec_count, mdl_state_t::pages, mdl_page_rec_t::response_status, and mdl_page_rec_t::url_hash.

Referenced by internal_mdl_fetch_resolve_not_modified().

◆ mdl_state_probe()

ra8_err_t mdl_state_probe ( mdl_storage_t * storage,
const char * path,
bool * out_exists )
nodiscard

Probe the complete two-generation state marker through portable storage.

Reports a tracked marker when either the logical base path or its bounded alternate generation exists as a regular file. Integrity and schema validation remain the responsibility of mdl_state_load.

Parameters
[in,out]storageInitialized, exclusively-owned storage binding.
[in]pathCanonical logical state path.
[out]out_existsWhether at least one regular state generation exists.
Returns
Canonical namespace/path status.
Return values
k_ra8_okThe probe completed and initialized out_exists.
k_ra8_err_invalid_argA pointer/path is invalid or a marker is not a file.
Precondition
All pointers are non-NULL and storage was initialized successfully.
The caller exclusively owns the namespace binding in storage.
Postcondition
On every return out_exists is initialized false unless a marker was found.
No filesystem object or state model is modified.
Note
Not thread-safe because storage is a non-reentrant dependency bundle.
Since
0.1.0

Definition at line 835 of file mdl_state_store.c.

References fw_fs_stat_t::exists, mdl_storage_t::fs, fw_fs_stat(), internal_mdl_state_paths(), k_fw_fs_node_file, k_fw_fs_path_cap, k_ra8_err_invalid_arg, k_ra8_err_invalid_state, k_ra8_ok, fw_fs_t::names, and fw_fs_stat_t::type.

Referenced by internal_library_visit(), internal_resolve_removal_target(), internal_verify_library_root(), and mdl_app_run_verify().

◆ mdl_state_save()

ra8_err_t mdl_state_save ( mdl_storage_t * storage,
const char * path,
const mdl_state_t * st,
bool * out_published )

Publish a checksummed successor without sacrificing the newest state.

Selects the absent, invalid, or older physical generation; removes only that target; writes a create-new private transaction; independently validates its canonical envelope, exact length, and payload CRC; then commits it. The newest accepted generation remains intact until commit. Sequence exhaustion is reported rather than wrapped. Cleanup failure takes precedence while the transaction is unpublished. A commit-time durability error can accompany a true out_published and must not be retried as though nothing changed.

Parameters
[in,out]storageInitialized, exclusively-owned storage binding.
[in]pathCanonical logical state path (never NULL).
[in]stState to write (never NULL).
[out]out_publishedFalse initially; true exactly when the successor became visible, including after durability failure.
Returns
An ra8_err_t result.
Return values
k_ra8_okThe validated successor was published.
k_ra8_err_invalid_argA pointer, path, or binding is invalid.
k_ra8_err_invalid_stateExisting generations are ambiguous/corrupt.
k_ra8_err_invalid_sizeThe monotonic sequence or I/O bound is exhausted.
otherA namespace, transaction, validation, durability, or cleanup error.
Precondition
All pointers are non-NULL and storage was initialized successfully.
The caller exclusively owns every workspace bound to storage.
Postcondition
On success one generation contains the complete serialized st.
When out_published is false, the previously newest valid generation survives.
When out_published is true, the successor is visible regardless of return status.
Note
Not thread-safe: borrows every workspace in storage.
See also
mdl_state_load
Since
0.1.0

Definition at line 966 of file mdl_state_store.c.

References fw_fs_transaction_commit(), internal_mdl_state_abort(), internal_mdl_state_build_stage(), internal_mdl_state_prepare_target(), k_fw_fs_path_cap, k_ra8_err_invalid_arg, k_ra8_err_invalid_state, k_ra8_ok, and priv_mdl_state_valid().

Referenced by internal_save_series_state(), and priv_mdl_fetch_checkpoint().

◆ mdl_state_set_chapter_metadata()

bool mdl_state_set_chapter_metadata ( mdl_chapter_rec_t * chapter,
const char * title,
double number,
bool number_known )

Set a chapter's display title and explicit parsed number.

Applies both fields transactionally after validating the title and number. A known number may be zero or fractional; an unknown number must be 0.0.

Parameters
[in,out]chapterChapter record to update (never NULL).
[in]titleDisplay title (may be empty, never NULL).
[in]numberFinite parsed chapter number, or 0.0 if unknown.
[in]number_knownWhether number was explicitly parsed.
Returns
Whether the complete metadata tuple was accepted.
Return values
trueThe title and number were stored.
falseAn argument was invalid; chapter is unchanged.
Precondition
chapter is non-NULL and caller-owned.
title is non-NULL and NUL-terminated.
Postcondition
On true, the chapter metadata exactly matches the arguments.
On false, chapter is unchanged.
Note
Not thread-safe: writes caller storage.
Since
0.1.0

Definition at line 293 of file mdl_state.c.

References internal_mdl_state_chapter_number_valid(), mdl_chapter_rec_t::number, mdl_chapter_rec_t::number_known, priv_mdl_state_field_valid(), and mdl_chapter_rec_t::title.

Referenced by internal_mdl_fetch_chapter_pages_and_checkpoint(), and internal_mdl_state_apply_chapter_values().

◆ mdl_state_set_series()

void mdl_state_set_series ( mdl_state_t * st,
const char * url,
const char * title,
const char * site_name,
const char * site_host,
const char * config_path )

Record the series identity and the descriptor used.

Parameters
[in,out]stState to update (never NULL).
[in]urlSeries page URL, or NULL to leave unchanged.
[in]titleSeries title, or NULL to leave unchanged.
[in]site_nameDescriptor display name, or NULL.
[in]site_hostSite host, or NULL.
[in]config_pathDescriptor file path used (for update-all), or NULL.
Returns
Nothing.
Precondition
st is non-NULL.
Any non-NULL string argument is NUL-terminated.
Postcondition
Each non-NULL argument is copied (truncation-safe) into st.
Fields whose argument was NULL keep their previous value.
Note
Not thread-safe: writes caller storage.
Since
0.1.0

Uses fixed-capacity state supplied by the caller without allocation. Any text retained by the state is copied into bounded records.

Definition at line 226 of file mdl_state.c.

References mdl_state_t::config_path, priv_mdl_state_set_opt(), mdl_state_t::series_title, mdl_state_t::series_url, mdl_state_t::site_host, and mdl_state_t::site_name.

Referenced by internal_reconcile_series_state().

◆ mdl_state_set_series_metadata()

bool mdl_state_set_series_metadata ( mdl_state_t * st,
const char * summary,
const char * writer,
const char * artist,
const char * cover_url,
const char * cover_path,
const char * language,
mdl_state_reading_direction_t direction )

Set the optional rich metadata persisted for a series.

Copies the complete metadata tuple only when every field fits its fixed destination, contains no TAB/newline record delimiters, the cover path is a relative non-traversing path, and direction is a supported value. Empty strings explicitly clear fields; NULL string arguments are invalid.

Parameters
[in,out]stState to update (never NULL).
[in]summarySeries synopsis (may be empty).
[in]writerWriter/author name (may be empty).
[in]artistArtist/illustrator name (may be empty).
[in]cover_urlRemote cover URL (may be empty).
[in]cover_pathLocal cover path relative to the series directory.
[in]languageBCP-47 language tag (may be empty).
[in]directionPage progression direction.
Returns
Whether the complete tuple was accepted.
Return values
trueEvery value was validated and copied.
falseAn argument was NULL, overlong, malformed, or unsupported.
Precondition
st is non-NULL and caller-owned.
All string arguments are non-NULL and NUL-terminated.
Postcondition
On true, all rich series metadata fields equal the supplied values.
On false, st is unchanged.
Note
Not thread-safe: writes caller storage.
Since
0.1.0

Definition at line 186 of file mdl_state.c.

References mdl_state_t::artist, mdl_state_t::cover_path, mdl_state_t::cover_url, k_mdl_language_max, k_mdl_person_max, k_mdl_relpath_max, k_mdl_state_read_ltr, k_mdl_state_read_rtl, k_mdl_summary_max, k_mdl_url_max, mdl_state_t::language, memcpy(), priv_mdl_state_field_valid(), priv_mdl_state_relative_path_valid(), mdl_state_t::reading_direction, mdl_state_t::summary, and mdl_state_t::writer.

Referenced by internal_reconcile_series_state().