cwist
Modern C web framework with libttak runtime
Loading...
Searching...
No Matches
big_dumb_reply.c File Reference

Opportunistic response cache that stores stable GET replies in memory or on disk. More...

#include <cwist/sys/app/big_dumb_reply.h>
#include <cwist/core/mem/alloc.h>
#include <cwist/core/siphash/siphash.h>
#include <cwist/sys/sys_info.h>
#include <cwist/core/macros.h>
#include <ttak/mem/epoch.h>
#include <stdlib.h>
#include <string.h>
#include <stdio.h>
#include <limits.h>
Include dependency graph for big_dumb_reply.c:

Go to the source code of this file.

Macros

#define _POSIX_C_SOURCE   200809L
 
#define BDR_BUCKETS   1024
 
#define BDR_GC_SWEEP   8
 
#define BDR_JANITOR_PERIOD   64
 
#define BDR_DEFAULT_MAX_BYTES   CWIST_MIB(32)
 
#define BDR_DEFAULT_ENTRY_TTL   300
 
#define BDR_DEFAULT_REVALIDATE_HITS   100000
 

Functions

cwist_bdr_t * cwist_bdr_create (void)
 Create a reply cache instance with default limits.
 
void cwist_bdr_destroy (cwist_bdr_t *bdr)
 Destroy a cache instance and release all its resources.
 
const void * cwist_bdr_get_pinned (cwist_bdr_t *bdr, const char *method, const char *path, size_t *out_len, bdr_blob_t **out_pin)
 Look up a cached GET reply, returning epoch-pinned bytes.
 
const void * cwist_bdr_get_pinned_cursor (cwist_bdr_t *bdr, const char *method, const char *path, size_t path_len, size_t *out_len, bdr_blob_t **out_pin, cwist_bdr_cursor_t *cursor)
 Cursor-accelerated variant of cwist_bdr_get_pinned() for non-NUL-terminated paths.
 
void cwist_bdr_unpin (bdr_blob_t *pin)
 Release a pin obtained from a cwist_bdr_get_pinned*() call.
 
const void * cwist_bdr_get (cwist_bdr_t *bdr, const char *method, const char *path, size_t *out_len)
 Look up a cached GET reply and return a borrowed pointer to its bytes.
 
void * cwist_bdr_copy_get (cwist_bdr_t *bdr, const char *method, const char *path, size_t *out_len)
 Look up a cached GET reply and return an owned copy of its bytes.
 
void cwist_bdr_put (cwist_bdr_t *bdr, const char *method, const char *path, const void *data, size_t len)
 Write a reply into the SQLite fallback database (disk mode).
 
void cwist_bdr_put_fixed (cwist_bdr_t *bdr, const char *method, const char *path, const void *data, size_t len)
 Publish a reply as immediately stable, bypassing the learning phase.
 
void cwist_bdr_put_revalidatable (cwist_bdr_t *bdr, const char *method, const char *path, const void *data, size_t len, cwist_bdr_revalidate_fn fn, void *arg)
 Publish a stable reply together with a hit-time revalidation hook.
 
void cwist_bdr_set_limits (cwist_bdr_t *bdr, size_t max_bytes, time_t max_entry_age_sec, uint64_t revalidate_hits)
 Update cache limits; zero arguments leave the corresponding limit unchanged.
 

Detailed Description

Opportunistic response cache that stores stable GET replies in memory or on disk.

Concurrency model: bucket chains are published with a CAS push and entry nodes are never freed until destroy (retired entries are tombstoned), so readers walk without locks. The response blob lives behind an atomic pointer per entry; writers swap it with one exchange and retire the predecessor through libttak EBR, which guarantees a swapped-out blob outlives every reader that entered its epoch before the swap. Only the janitor (TTL/byte-trim/disk spill, every 64 learns) and the disk-fallback path take the context mutex.

Definition in file big_dumb_reply.c.

Macro Definition Documentation

◆ _POSIX_C_SOURCE

#define _POSIX_C_SOURCE   200809L

Definition at line 1 of file big_dumb_reply.c.

◆ BDR_BUCKETS

#define BDR_BUCKETS   1024

Definition at line 30 of file big_dumb_reply.c.

◆ BDR_DEFAULT_ENTRY_TTL

#define BDR_DEFAULT_ENTRY_TTL   300

Definition at line 34 of file big_dumb_reply.c.

◆ BDR_DEFAULT_MAX_BYTES

#define BDR_DEFAULT_MAX_BYTES   CWIST_MIB(32)

Definition at line 33 of file big_dumb_reply.c.

◆ BDR_DEFAULT_REVALIDATE_HITS

#define BDR_DEFAULT_REVALIDATE_HITS   100000

Definition at line 35 of file big_dumb_reply.c.

◆ BDR_GC_SWEEP

#define BDR_GC_SWEEP   8

Definition at line 31 of file big_dumb_reply.c.

◆ BDR_JANITOR_PERIOD

#define BDR_JANITOR_PERIOD   64

Definition at line 32 of file big_dumb_reply.c.

Function Documentation

◆ cwist_bdr_copy_get()

void * cwist_bdr_copy_get ( cwist_bdr_t *  bdr,
const char *  method,
const char *  path,
size_t *  out_len 
)

Look up a cached GET reply and return an owned copy of its bytes.

Copy a stable response from the cache for concurrent server use.

Unlike cwist_bdr_get(), the returned buffer is allocated with cwist_alloc() and survives cache eviction; the caller frees it with cwist_free().

Parameters
bdrCache instance.
methodHTTP method; must be "GET".
pathNUL-terminated request path.
out_lenReceives the copy length on a hit (may be NULL).
Returns
Newly allocated copy of the reply, or NULL on miss/invalid input/allocation failure.

Definition at line 727 of file big_dumb_reply.c.

References cap, cwist_alloc(), cwist_bdr_get_pinned(), and cwist_bdr_unpin().

◆ cwist_bdr_create()

cwist_bdr_t * cwist_bdr_create ( void  )

Create a reply cache instance with default limits.

Creates a BDR context.

Initializes the mutex, the bucket table, and the default tuning values (32 MiB byte budget, 300 s entry TTL, 100000 revalidate hits).

Returns
New cache instance on success, NULL on allocation or mutex failure.

Definition at line 475 of file big_dumb_reply.c.

References BDR_BUCKETS, BDR_DEFAULT_ENTRY_TTL, BDR_DEFAULT_MAX_BYTES, BDR_DEFAULT_REVALIDATE_HITS, cap, cwist_alloc(), cwist_alloc_array(), and cwist_free().

Referenced by cwist_app_create().

◆ cwist_bdr_destroy()

void cwist_bdr_destroy ( cwist_bdr_t *  bdr)

Destroy a cache instance and release all its resources.

Destroys a BDR context and frees all cached blobs.

Frees every live and retired entry and its blob, the bucket table, and the disk fallback database (including the "cwist_bdr_fallback.db" file). Safe to call with NULL.

Parameters
bdrCache instance to destroy, or NULL.

Definition at line 511 of file big_dumb_reply.c.

References cap, cwist_free(), and bdr_entry_t::retire_next.

Referenced by cwist_app_destroy().

◆ cwist_bdr_get()

const void * cwist_bdr_get ( cwist_bdr_t *  bdr,
const char *  method,
const char *  path,
size_t *  out_len 
)

Look up a cached GET reply and return a borrowed pointer to its bytes.

Try to find a cached response.

Convenience wrapper over cwist_bdr_get_pinned() that unpins immediately, so the returned pointer is only valid until the next janitor activity that could retire the entry; prefer the pinned API for anything but a memcpy.

Parameters
bdrCache instance.
methodHTTP method; must be "GET".
pathNUL-terminated request path.
out_lenReceives the reply length on a hit (may be NULL).
Returns
Reply bytes (unpinned), or NULL on miss/invalid input.

Definition at line 708 of file big_dumb_reply.c.

References cap, cwist_bdr_get_pinned(), and cwist_bdr_unpin().

Referenced by cwist_app_http_handler().

◆ cwist_bdr_get_pinned()

const void * cwist_bdr_get_pinned ( cwist_bdr_t *  bdr,
const char *  method,
const char *  path,
size_t *  out_len,
bdr_blob_t **  out_pin 
)

Look up a cached GET reply, returning epoch-pinned bytes.

Find a cached response and pin it for the duration of the serve.

Only GET requests are served, and only while the cache is in RAM mode. The caller must release the pin with cwist_bdr_unpin() once done reading.

Parameters
bdrCache instance.
methodHTTP method; must be "GET".
pathNUL-terminated request path.
out_lenReceives the reply length on a hit (may be NULL).
out_pinReceives the pin to pass to cwist_bdr_unpin().
Returns
Reply bytes pinned for the caller, or NULL on miss/invalid input.

Definition at line 616 of file big_dumb_reply.c.

References cap.

Referenced by cwist_bdr_copy_get(), and cwist_bdr_get().

◆ cwist_bdr_get_pinned_cursor()

const void * cwist_bdr_get_pinned_cursor ( cwist_bdr_t *  bdr,
const char *  method,
const char *  path,
size_t  path_len,
size_t *  out_len,
bdr_blob_t **  out_pin,
cwist_bdr_cursor_t *  cursor 
)

Cursor-accelerated variant of cwist_bdr_get_pinned() for non-NUL-terminated paths.

cwist_bdr_get_pinned() with a per-connection fast path.

When the cursor's cached entry still matches the request it is used as a lookup hint; a stale hint degrades to a full bucket walk. On a hit the cursor is refreshed to point at the served entry, so repeated reads of the same path skip the chain walk.

Parameters
bdrCache instance.
methodHTTP method; must be "GET".
pathRequest path bytes (not required to be NUL-terminated).
path_lenLength of path in bytes.
out_lenReceives the reply length on a hit (may be NULL).
out_pinReceives the pin to pass to cwist_bdr_unpin().
cursorReusable lookup cursor, updated on every call.
Returns
Reply bytes pinned for the caller, or NULL on miss/invalid input.

Definition at line 642 of file big_dumb_reply.c.

References cap, and CWIST_BDR_CURSOR_PATH_MAX.

◆ cwist_bdr_put()

void cwist_bdr_put ( cwist_bdr_t *  bdr,
const char *  method,
const char *  path,
const void *  data,
size_t  len 
)

Write a reply into the SQLite fallback database (disk mode).

Store a response in the cache (lock-free learn path).

Must be called only while the cache is in disk mode; takes the context mutex for the duration of the statement.

Parameters
bdrCache instance (disk_db must be open).
req_hPrecomputed request hash (primary key).
dataResponse bytes.
lenLength of data in bytes.

Learn a reply observation into the cache (lock-free fast path).

Only GET replies are tracked. An entry stabilizes once the same response bytes are seen twice in a row; a content change under a stable entry demotes it back to candidate. In disk mode the observation is written to SQLite instead. Triggers the janitor tick periodically.

Parameters
bdrCache instance.
methodHTTP method; must be "GET".
pathNUL-terminated request path.
dataObserved response bytes.
lenLength of data in bytes.

Definition at line 784 of file big_dumb_reply.c.

References cap, bdr_entry_t::created_at, bdr_entry_t::hits, bdr_entry_t::is_stable, and bdr_entry_t::response_hash.

◆ cwist_bdr_put_fixed()

void cwist_bdr_put_fixed ( cwist_bdr_t *  bdr,
const char *  method,
const char *  path,
const void *  data,
size_t  len 
)

Publish a reply as immediately stable, bypassing the learning phase.

Immediately cache a fixed static response on request 1.

For responses that are known to be constant; stores the bytes and marks the entry stable in one shot. In disk mode the observation is written to SQLite instead. Triggers the janitor tick periodically.

Parameters
bdrCache instance.
methodHTTP method; must be "GET".
pathNUL-terminated request path.
dataResponse bytes to cache.
lenLength of data in bytes.

Definition at line 848 of file big_dumb_reply.c.

References cap, bdr_entry_t::created_at, bdr_entry_t::hits, bdr_entry_t::is_stable, and bdr_entry_t::response_hash.

◆ cwist_bdr_put_revalidatable()

void cwist_bdr_put_revalidatable ( cwist_bdr_t *  bdr,
const char *  method,
const char *  path,
const void *  data,
size_t  len,
cwist_bdr_revalidate_fn  fn,
void *  arg 
)

Publish a stable reply together with a hit-time revalidation hook.

Cache a response whose backing value may change over time.

On every subsequent hit the hook is invoked and, if it reports fresh bytes, the entry's blob is swapped to the callback-provided buffer through one pointer exchange. The hook is published before the blob so a reader never observes a revalidatable blob without its hook. In disk mode the observation is written to SQLite instead (hook not persisted). Triggers the janitor tick periodically.

Parameters
bdrCache instance.
methodHTTP method; must be "GET".
pathNUL-terminated request path.
dataResponse bytes to cache.
lenLength of data in bytes.
fnRevalidation callback invoked on hits.
argOpaque argument passed to fn.

Definition at line 894 of file big_dumb_reply.c.

References cap, bdr_entry_t::created_at, bdr_entry_t::hits, bdr_entry_t::is_stable, bdr_entry_t::response_hash, bdr_entry_t::revalidate, and bdr_entry_t::revalidate_arg.

◆ cwist_bdr_set_limits()

void cwist_bdr_set_limits ( cwist_bdr_t *  bdr,
size_t  max_bytes,
time_t  max_entry_age_sec,
uint64_t  revalidate_hits 
)

Update cache limits; zero arguments leave the corresponding limit unchanged.

Adjusts guard-rail policies for the in-memory cache.

Takes the context mutex so the new limits are not torn against a running janitor tick.

Parameters
bdrCache instance.
max_bytesNew byte budget; 0 keeps the current value.
max_entry_age_secNew entry TTL in seconds; 0 keeps the current value.
revalidate_hitsNew stability hit threshold; 0 keeps the current value.

Definition at line 940 of file big_dumb_reply.c.

References cap.

Referenced by cwist_app_configure_bdr().

◆ cwist_bdr_unpin()

void cwist_bdr_unpin ( bdr_blob_t *  pin)

Release a pin obtained from a cwist_bdr_get_pinned*() call.

Release a pin acquired by cwist_bdr_get_pinned().

The pin is the EBR epoch itself, so this simply leaves the epoch.

Parameters
pinPin to release (ignored beyond symmetry with the get calls).

Definition at line 690 of file big_dumb_reply.c.

References cap.

Referenced by cwist_bdr_copy_get(), and cwist_bdr_get().