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

Per-host HTTP cache lookup and revalidation state machine. More...

#include "mdl_cache.h"
#include <stdint.h>
#include <string.h>
#include <time.h>
#include "mdl_cache_internal.h"
#include "mdl_hash.h"
#include "ra8_attributes.h"
Include dependency graph for mdl_cache.c:

Go to the source code of this file.

Data Structures

struct  mdl_cache_lookup_t
 Prepared host paths and verified retained-entity state. More...

Enumerations

enum  mdl_cache_http_t : uint16_t {
  k_cache_http_success_min = 200U ,
  k_cache_http_success_max = 299U ,
  k_cache_http_not_modified = 304U ,
  k_cache_http_status_max = 599U
}
 HTTP response bounds used by the cache state machine. More...

Functions

static mdl_cache_record_tinternal_cache_find (mdl_cache_index_t *index, const char *url, uint64_t url_hash)
 Locate one exact URL record.
static mdl_cache_record_tinternal_cache_slot (mdl_cache_index_t *index)
 Select a record slot, evicting the oldest observation when full.
static int64_t internal_cache_age (int64_t fetched_at)
 Compute a nonnegative retained-observation age.
static int64_t internal_cache_now (void)
 Capture the current epoch for one response observation.
static bool internal_cache_copy (char *destination, size_t capacity, const char *source)
 Copy a complete bounded string without truncation.
static bool internal_cache_record_response (mdl_cache_index_t *index, mdl_cache_record_t *existing, const char *url, uint64_t url_hash, uint64_t content_hash, const char *relative_path, const mdl_net_resp_t *response)
 Update or insert one freshly published body record.
static ra8_err_t internal_cache_fetch (const mdl_cache_record_t *record, const char *url, const mdl_net_req_t *base_request, mdl_cache_fetch_fn fetch, void *fetch_context, char *buffer, size_t capacity, size_t *out_length, mdl_net_resp_t *response)
 Issue a cache-controlled request with selected validators.
static ra8_err_t internal_cache_prepare (mdl_cache_t *cache, const char *url, char *buffer, size_t capacity, mdl_cache_result_t *result, mdl_cache_lookup_t *lookup)
 Load one host index and verify any retained exact-URL entity.
static ra8_err_t internal_cache_retry_unconditional (const char *url, const mdl_net_req_t *base_request, mdl_cache_fetch_fn fetch, void *fetch_context, char *buffer, size_t capacity, size_t *out_length, mdl_net_resp_t *response)
 Retry one invalid 304 without conditional headers.
static ra8_err_t internal_cache_finish_304 (mdl_cache_t *cache, const mdl_cache_paths_t *paths, mdl_cache_record_t *record, char *buffer, size_t capacity, size_t *out_length, mdl_cache_result_t *result)
 Finish a verified HTTP 304 observation.
static ra8_err_t internal_cache_publish (mdl_cache_t *cache, const mdl_cache_paths_t *paths, mdl_cache_record_t *existing, const char *url, const char *buffer, size_t length, const mdl_net_resp_t *response, mdl_cache_result_t *result)
 Publish and index one successful nonempty response body.
static ra8_err_t internal_cache_network (mdl_cache_t *cache, const mdl_cache_lookup_t *lookup, const char *url, const mdl_net_req_t *base_request, mdl_cache_fetch_fn fetch, void *fetch_context, char *buffer, size_t capacity, size_t *out_length, mdl_net_resp_t *response, mdl_cache_result_t *result)
 Fetch, resolve 304 semantics, and publish one network observation.
ra8_err_t mdl_cache_get_buf (mdl_cache_t *cache, const char *url, const mdl_net_req_t *base_request, mdl_cache_fetch_fn fetch, void *fetch_context, char *buffer, size_t capacity, size_t *out_length, mdl_net_resp_t *response, mdl_cache_result_t *result)
 Fetch one document through the per-host persistent cache.

Detailed Description

Per-host HTTP cache lookup and revalidation state machine.

Coordinates verified body reuse, conditional requests, corruption recovery, and transactional index publication over injected seams.

Definition in file mdl_cache.c.

Enumeration Type Documentation

◆ mdl_cache_http_t

enum mdl_cache_http_t : uint16_t

HTTP response bounds used by the cache state machine.

Enumerator
k_cache_http_success_min 

First successful status.

k_cache_http_success_max 

Last successful status.

k_cache_http_not_modified 

Conditional reuse response.

k_cache_http_status_max 

Last canonical HTTP status.

Definition at line 20 of file mdl_cache.c.

Function Documentation

◆ internal_cache_age()

int64_t internal_cache_age ( int64_t fetched_at)
static

Compute a nonnegative retained-observation age.

Compares the retained epoch with the current wall clock while treating an unavailable clock or timestamp as unknown metadata.

Parameters
[in]fetched_atRetained epoch seconds.
Returns
Age in seconds, or -1 when the clock/record is unavailable.
Return values
-1The clock or retained timestamp is unavailable.
nonnegativeThe retained observation age in seconds.
Precondition
Integer input uses its declared width.
The system clock may be unavailable.
Postcondition
No global or caller state is modified.
A clock rollback reports zero rather than a negative age.
Note
Used for truthful CLI staleness reporting.
Since
0.1.0

Definition at line 93 of file mdl_cache.c.

References RA8_INTERNAL.

Referenced by internal_cache_prepare().

◆ internal_cache_copy()

bool internal_cache_copy ( char * destination,
size_t capacity,
const char * source )
static

Copy a complete bounded string without truncation.

Measures before copying so an oversized validator or URL cannot leave a truncated identity in persistent state.

Parameters
[out]destinationWritable destination.
[in]capacityDestination byte capacity.
[in]sourceNUL-terminated source.
Returns
Whether the complete source fit.
Return values
trueThe exact source and terminating NUL fit.
falseThe destination was cleared because the source was oversized.
Precondition
All pointers are non-NULL and capacity is nonzero.
capacity is the true destination extent.
Postcondition
Success leaves an exact NUL-terminated copy.
Failure clears the destination.
Note
Performs no allocation.
Since
0.1.0

Definition at line 140 of file mdl_cache.c.

References memcpy(), RA8_INTERNAL, and strlen().

Referenced by internal_cache_record_response().

◆ internal_cache_fetch()

ra8_err_t internal_cache_fetch ( const mdl_cache_record_t * record,
const char * url,
const mdl_net_req_t * base_request,
mdl_cache_fetch_fn fetch,
void * fetch_context,
char * buffer,
size_t capacity,
size_t * out_length,
mdl_net_resp_t * response )
static

Issue a cache-controlled request with selected validators.

Copies the request template, attaches only validators belonging to the hash-verified record, and delegates one bounded fetch.

Parameters
[in]recordVerified held record, or NULL.
[in]urlExact URL.
[in]base_requestCaller request template.
[in]fetchInjected fetch callback.
[in,out]fetch_contextCallback context.
[out]bufferBody destination.
[in]capacityBody capacity.
[out]out_lengthResponse body extent.
[out]responseFinished response metadata.
Returns
Canonical callback status.
Return values
k_ra8_okThe callback completed and initialized response metadata.
otherThe injected callback rejected or failed the request.
Precondition
Every required pointer is non-NULL.
record is hash-verified when non-NULL.
Postcondition
Saved validators are sent exactly when available.
Base request remains unchanged.
Note
Refetch forces this call but still permits conditional revalidation.
Since
0.1.0

Definition at line 220 of file mdl_cache.c.

References mdl_cache_record_t::etag, mdl_net_req_t::if_modified_since, mdl_net_req_t::if_none_match, mdl_cache_record_t::last_modified, and RA8_INTERNAL.

Referenced by internal_cache_network().

◆ internal_cache_find()

mdl_cache_record_t * internal_cache_find ( mdl_cache_index_t * index,
const char * url,
uint64_t url_hash )
static

Locate one exact URL record.

Parameters
[in,out]indexLoaded host index.
[in]urlExact URL.
[in]url_hashPrecomputed URL hash.
Returns
Matching mutable record or NULL.
Precondition
Both pointers are non-NULL.
Record count is within capacity.
Postcondition
No record is modified.
A hash collision cannot match a different URL.
Note
Linear bounded lookup keeps the persistent format simple.
Since
0.1.0

Definition at line 41 of file mdl_cache.c.

References mdl_cache_index_t::record_count, mdl_cache_index_t::records, strcmp(), mdl_cache_record_t::url, and mdl_cache_record_t::url_hash.

Referenced by internal_cache_prepare().

◆ internal_cache_finish_304()

ra8_err_t internal_cache_finish_304 ( mdl_cache_t * cache,
const mdl_cache_paths_t * paths,
mdl_cache_record_t * record,
char * buffer,
size_t capacity,
size_t * out_length,
mdl_cache_result_t * result )
static

Finish a verified HTTP 304 observation.

Rereads the immutable retained body after the network callback, updates only the observation metadata, and publishes a new index.

Parameters
[in,out]cacheCache binding.
[in]pathsHost paths.
[in,out]recordVerified retained record.
[out]bufferBody destination.
[in]capacityBody capacity.
[out]out_lengthExact retained body extent.
[in,out]resultOutcome to update.
Returns
Canonical body-read or index-save status.
Return values
k_ra8_okThe retained bytes and refreshed index are complete.
otherBody verification or index publication failed.
Precondition
Every pointer is non-NULL.
record previously hash-verified.
Postcondition
Success returns the body and records status 304/time.
No body file is opened for writing.
Note
The body is reread because a network backend may touch its buffer.
Since
0.1.0

Definition at line 365 of file mdl_cache.c.

References mdl_cache_result_t::body_reused, mdl_cache_record_t::fetched_at, internal_cache_now(), k_cache_http_not_modified, k_ra8_ok, mdl_cache_result_t::observed_status, priv_mdl_cache_read_body(), priv_mdl_cache_save(), RA8_INTERNAL, mdl_cache_record_t::response_status, and mdl_cache_t::storage.

Referenced by internal_cache_network().

◆ internal_cache_network()

ra8_err_t internal_cache_network ( mdl_cache_t * cache,
const mdl_cache_lookup_t * lookup,
const char * url,
const mdl_net_req_t * base_request,
mdl_cache_fetch_fn fetch,
void * fetch_context,
char * buffer,
size_t capacity,
size_t * out_length,
mdl_net_resp_t * response,
mdl_cache_result_t * result )
static

Fetch, resolve 304 semantics, and publish one network observation.

Runs exactly one conditional fetch, branches to verified 304 reuse or a single unconditional recovery, then publishes a new 2xx body.

Parameters
[in,out]cacheCache binding.
[in]lookupPrepared retained-entity state.
[in]urlExact URL.
[in]base_requestCaller request template.
[in]fetchInjected fetch callback.
[in,out]fetch_contextCallback context.
[out]bufferBody destination.
[in]capacityBody capacity.
[out]out_lengthReturned body extent.
[out]responseFinished response metadata.
[in,out]resultCache outcome.
Returns
Canonical callback, protocol, or publication status.
Return values
k_ra8_okA retained or new body is available.
otherThe callback, 304 recovery, or publication failed.
Precondition
Every pointer is non-NULL and lookup was prepared successfully.
Cache storage and body destination are exclusively owned.
Postcondition
Success returns either a verified retained or newly published body.
An invalid body-free 304 receives at most one unconditional retry.
Note
A valid 304 never opens a body transaction for writing.
Since
0.1.0

Definition at line 480 of file mdl_cache.c.

References mdl_cache_lookup_t::held, internal_cache_fetch(), internal_cache_finish_304(), internal_cache_publish(), internal_cache_retry_unconditional(), k_cache_http_not_modified, k_ra8_ok, mdl_cache_lookup_t::paths, RA8_INTERNAL, mdl_cache_lookup_t::record, mdl_cache_result_t::revalidated, and mdl_net_resp_t::status.

Referenced by mdl_cache_get_buf().

◆ internal_cache_now()

int64_t internal_cache_now ( void )
static

Capture the current epoch for one response observation.

Converts the process wall clock to the signed persistent field and substitutes zero only when the platform reports no usable time.

Returns
Nonnegative epoch seconds, or zero when unavailable.
Return values
0The platform clock is unavailable or is exactly the epoch.
positiveCurrent epoch seconds.
Precondition
The platform time provider is initialized when required.
Return zero is accepted as an unknown-but-valid epoch.
Postcondition
No cache or storage state is modified.
Result is always nonnegative.
Note
Wall time is metadata, never a security decision.
Since
0.1.0

Definition at line 117 of file mdl_cache.c.

References RA8_INTERNAL.

Referenced by internal_cache_finish_304(), and internal_cache_record_response().

◆ internal_cache_prepare()

ra8_err_t internal_cache_prepare ( mdl_cache_t * cache,
const char * url,
char * buffer,
size_t capacity,
mdl_cache_result_t * result,
mdl_cache_lookup_t * lookup )
static

Load one host index and verify any retained exact-URL entity.

Authenticates the index, matches both URL hash and exact URL bytes, then accepts a body only after exact size and content-hash checks.

Parameters
[in,out]cacheCache binding.
[in]urlExact URL.
[out]bufferBody destination used for retained verification.
[in]capacityBody destination capacity.
[in,out]resultCache outcome receiving load observations.
[out]lookupPrepared lookup state.
Returns
Canonical index-load status.
Return values
k_ra8_okLookup state is complete; the body may still be absent.
otherHost path, index recovery, or storage inspection failed.
Precondition
Every pointer is non-NULL and capacity is nonzero.
Cache storage and workspace are exclusively owned.
Postcondition
Success initializes lookup completely.
A held entity has already passed exact size/hash validation.
Note
A missing or corrupt body is treated as absent and fetched again.
Since
0.1.0

Definition at line 272 of file mdl_cache.c.

References mdl_cache_result_t::age_seconds, mdl_cache_record_t::fetched_at, mdl_cache_lookup_t::held, mdl_cache_t::index, mdl_cache_result_t::index_rebuilt, internal_cache_age(), internal_cache_find(), k_ra8_ok, mdl_hash_str(), mdl_cache_result_t::observed_status, mdl_cache_lookup_t::paths, priv_mdl_cache_load(), priv_mdl_cache_read_body(), RA8_INTERNAL, mdl_cache_lookup_t::record, mdl_cache_record_t::response_status, mdl_cache_lookup_t::retained_length, and mdl_cache_t::storage.

Referenced by mdl_cache_get_buf().

◆ internal_cache_publish()

ra8_err_t internal_cache_publish ( mdl_cache_t * cache,
const mdl_cache_paths_t * paths,
mdl_cache_record_t * existing,
const char * url,
const char * buffer,
size_t length,
const mdl_net_resp_t * response,
mdl_cache_result_t * result )
static

Publish and index one successful nonempty response body.

Derives an immutable content-addressed leaf, publishes the body, then replaces the host index only after the record is complete.

Parameters
[in,out]cacheCache binding.
[in]pathsHost paths.
[in,out]existingExact prior record, or NULL.
[in]urlExact URL.
[in]bufferComplete response body.
[in]lengthBody extent.
[in]responseSuccessful response metadata.
[in,out]resultOutcome to update.
Returns
Canonical validation or publication status.
Return values
k_ra8_okBody and index generation were published.
k_ra8_err_protocol_errorThe response status/body was unusable.
otherA bound, storage, or encoding operation failed.
Precondition
Every required pointer is non-NULL and body is nonempty.
Response status is available.
Postcondition
Success publishes immutable body bytes and one index generation.
Index failure cannot invalidate the prior indexed body.
Note
New body names include both URL and content identities.
Since
0.1.0

Definition at line 411 of file mdl_cache.c.

References mdl_cache_t::index, internal_cache_record_response(), k_cache_http_status_max, k_cache_http_success_max, k_cache_http_success_min, k_mdl_relpath_max, k_ra8_err_invalid_size, k_ra8_err_protocol_error, k_ra8_ok, mdl_hash_bytes(), mdl_hash_str(), mdl_cache_result_t::observed_status, priv_mdl_cache_publish_body(), priv_mdl_cache_save(), RA8_INTERNAL, mdl_net_resp_t::status, and mdl_cache_t::storage.

Referenced by internal_cache_network().

◆ internal_cache_record_response()

bool internal_cache_record_response ( mdl_cache_index_t * index,
mdl_cache_record_t * existing,
const char * url,
uint64_t url_hash,
uint64_t content_hash,
const char * relative_path,
const mdl_net_resp_t * response )
static

Update or insert one freshly published body record.

Builds the complete next record off to the side, then atomically assigns it to the existing or deterministically selected slot.

Parameters
[in,out]indexLoaded host index.
[in]existingExisting exact URL record, or NULL.
[in]urlExact URL.
[in]url_hashURL identity.
[in]content_hashBody identity.
[in]relative_pathPublished body leaf.
[in]responseFinished successful response.
Returns
Whether the complete record fit.
Return values
trueEvery string fit and one record was updated.
falseAt least one string exceeded its persistent field.
Precondition
All required pointers are non-NULL.
Response status is a canonical successful code.
Postcondition
Success publishes one complete in-memory record.
Failure leaves an existing record unchanged.
Note
A full index evicts its oldest observation.
Since
0.1.0

Definition at line 172 of file mdl_cache.c.

References mdl_cache_record_t::etag, mdl_net_resp_t::etag, internal_cache_copy(), internal_cache_now(), internal_cache_slot(), mdl_cache_record_t::last_modified, mdl_net_resp_t::last_modified, RA8_INTERNAL, mdl_cache_record_t::relative_path, mdl_net_resp_t::status, and mdl_cache_record_t::url.

Referenced by internal_cache_publish().

◆ internal_cache_retry_unconditional()

ra8_err_t internal_cache_retry_unconditional ( const char * url,
const mdl_net_req_t * base_request,
mdl_cache_fetch_fn fetch,
void * fetch_context,
char * buffer,
size_t capacity,
size_t * out_length,
mdl_net_resp_t * response )
static

Retry one invalid 304 without conditional headers.

Clears both conditional fields on a copy of the request so a server cannot strand an empty cache in a repeated not-modified loop.

Parameters
[in]urlExact URL.
[in]base_requestCaller request template.
[in]fetchInjected fetch callback.
[in,out]fetch_contextCallback context.
[out]bufferBody destination.
[in]capacityBody capacity.
[out]out_lengthResponse body extent.
[out]responseFinished response metadata.
Returns
Canonical callback or protocol status.
Return values
k_ra8_okThe unconditional retry returned a usable response.
k_ra8_err_protocol_errorThe unconditional retry also returned 304.
otherThe injected callback failed.
Precondition
Every required pointer is non-NULL.
No valid cached entity is available.
Postcondition
A second 304 is rejected as protocol failure.
No storage mutation occurs.
Note
This prevents a permanent 304 loop after body loss.
Since
0.1.0

Definition at line 323 of file mdl_cache.c.

References mdl_net_req_t::if_modified_since, mdl_net_req_t::if_none_match, k_cache_http_not_modified, k_ra8_err_protocol_error, k_ra8_ok, RA8_INTERNAL, and mdl_net_resp_t::status.

Referenced by internal_cache_network().

◆ internal_cache_slot()

mdl_cache_record_t * internal_cache_slot ( mdl_cache_index_t * index)
static

Select a record slot, evicting the oldest observation when full.

Parameters
[in,out]indexLoaded host index.
Returns
Writable record slot.
Precondition
index is non-NULL and valid.
Capacity is nonzero.
Postcondition
A spare slot increases record count exactly once.
A full index returns the oldest slot without changing count.
Note
Ties select the first oldest row deterministically.
Since
0.1.0

Definition at line 62 of file mdl_cache.c.

References mdl_cache_record_t::fetched_at, k_mdl_cache_record_max, RA8_INTERNAL, mdl_cache_index_t::record_count, and mdl_cache_index_t::records.

Referenced by internal_cache_record_response().

◆ mdl_cache_get_buf()

ra8_err_t mdl_cache_get_buf ( mdl_cache_t * cache,
const char * url,
const mdl_net_req_t * base_request,
mdl_cache_fetch_fn fetch,
void * fetch_context,
char * buffer,
size_t capacity,
size_t * out_length,
mdl_net_resp_t * response,
mdl_cache_result_t * result )
nodiscard

Fetch one document through the per-host persistent cache.

Verifies a retained body before reuse, sends saved validators when available, treats HTTP 304 as a body-free observation, and retries an unexpected 304 once without validators when no valid entity is held. Successful new bodies and index generations publish transactionally. A malformed/truncated index is removed and rebuilt rather than trusted or treated as library state.

Parameters
[in,out]cacheInitialized cache binding.
[in]urlExact absolute URL.
[in]base_requestRequest identity, referer, and timeout.
[in]fetchInjected network/governor callback.
[in,out]fetch_contextContext supplied to fetch.
[out]bufferCaller-owned body destination.
[in]capacityWritable byte capacity.
[out]out_lengthExact returned body bytes.
[out]responseFinished network or retained response metadata.
[out]resultCache-specific outcome.
Returns
Canonical cache, storage, network, or validation status.
Return values
k_ra8_okA nonempty verified body is in buffer.
k_ra8_err_invalid_argA binding, path, callback, or URL is invalid.
k_ra8_err_invalid_sizeThe response or persistent record is oversized.
otherThe injected storage or fetch operation failed.
Precondition
All required pointers are non-NULL and cache is exclusively owned.
buffer spans capacity nonzero writable bytes.
Postcondition
Success returns complete bytes and a truthful cache result.
Failure never publishes a partial body or index generation.
Note
Thread-safe across independent bindings and storage workspaces.
Since
0.1.0

Definition at line 537 of file mdl_cache.c.

References mdl_cache_result_t::body_reused, mdl_cache_record_t::etag, mdl_cache_lookup_t::held, mdl_cache_t::index, internal_cache_network(), internal_cache_prepare(), k_ra8_err_invalid_arg, k_ra8_ok, mdl_cache_record_t::last_modified, mdl_cache_lookup_t::record, mdl_cache_t::refetch, mdl_cache_lookup_t::retained_length, mdl_cache_t::root, and mdl_cache_t::storage.

Referenced by internal_cover_cached(), internal_mdl_fetch_chapter_html(), and priv_mdl_app_prepare_chapters().