|
cwist
Modern C web framework with libttak runtime
|
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>
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. | |
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.
Definition at line 1 of file big_dumb_reply.c.
| #define BDR_BUCKETS 1024 |
Definition at line 30 of file big_dumb_reply.c.
| #define BDR_DEFAULT_ENTRY_TTL 300 |
Definition at line 34 of file big_dumb_reply.c.
Definition at line 33 of file big_dumb_reply.c.
| #define BDR_DEFAULT_REVALIDATE_HITS 100000 |
Definition at line 35 of file big_dumb_reply.c.
| #define BDR_GC_SWEEP 8 |
Definition at line 31 of file big_dumb_reply.c.
| #define BDR_JANITOR_PERIOD 64 |
Definition at line 32 of file big_dumb_reply.c.
| 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().
| bdr | Cache instance. |
| method | HTTP method; must be "GET". |
| path | NUL-terminated request path. |
| out_len | Receives the copy length on a hit (may be NULL). |
Definition at line 727 of file big_dumb_reply.c.
References cap, cwist_alloc(), cwist_bdr_get_pinned(), and cwist_bdr_unpin().
| 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).
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().
| 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.
| bdr | Cache 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().
| 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.
| bdr | Cache instance. |
| method | HTTP method; must be "GET". |
| path | NUL-terminated request path. |
| out_len | Receives the reply length on a hit (may be NULL). |
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().
| 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.
| bdr | Cache instance. |
| method | HTTP method; must be "GET". |
| path | NUL-terminated request path. |
| out_len | Receives the reply length on a hit (may be NULL). |
| out_pin | Receives the pin to pass to cwist_bdr_unpin(). |
Definition at line 616 of file big_dumb_reply.c.
References cap.
Referenced by cwist_bdr_copy_get(), and cwist_bdr_get().
| 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.
| bdr | Cache instance. |
| method | HTTP method; must be "GET". |
| path | Request path bytes (not required to be NUL-terminated). |
| path_len | Length of path in bytes. |
| out_len | Receives the reply length on a hit (may be NULL). |
| out_pin | Receives the pin to pass to cwist_bdr_unpin(). |
| cursor | Reusable lookup cursor, updated on every call. |
Definition at line 642 of file big_dumb_reply.c.
References cap, and CWIST_BDR_CURSOR_PATH_MAX.
| 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.
| bdr | Cache instance (disk_db must be open). |
| req_h | Precomputed request hash (primary key). |
| data | Response bytes. |
| len | Length 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.
| bdr | Cache instance. |
| method | HTTP method; must be "GET". |
| path | NUL-terminated request path. |
| data | Observed response bytes. |
| len | Length 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.
| 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.
| bdr | Cache instance. |
| method | HTTP method; must be "GET". |
| path | NUL-terminated request path. |
| data | Response bytes to cache. |
| len | Length 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.
| 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.
| bdr | Cache instance. |
| method | HTTP method; must be "GET". |
| path | NUL-terminated request path. |
| data | Response bytes to cache. |
| len | Length of data in bytes. |
| fn | Revalidation callback invoked on hits. |
| arg | Opaque 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.
| 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.
| bdr | Cache instance. |
| max_bytes | New byte budget; 0 keeps the current value. |
| max_entry_age_sec | New entry TTL in seconds; 0 keeps the current value. |
| revalidate_hits | New 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().
| 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.
| pin | Pin 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().