libwebsockets
Lightweight C library for HTML5 websockets
|
lws_cache implements a single- or multi-level cache for generic payload items that are keyed by a unique string.
L1 cache is always stored on heap, but it may be hooked up to additional levels of cache objects with different backing storage. The last level always contains a complete set of cached items, earlier levels may be empty or contain a partial set of objects.
User code can define its own subclassed lws_cache objects with custom storage formats and media, while being able to take advantage of a suitably-sized L1 heap cache to minimize the cost of repeated access.
You can find examples of how to create, use and destroy single and multilevel caches in minimal-examples/api-tests/api-test-lws_cache
The max heap footprint of its items and max number of items can be capped. LRU tracking is performed so the least recently relevant items are evicted first. It's also possible to limit the maximum size of any single payload.
Time To Live (TTL) tracking is also performed automatically, so cached items auto-expire if a non-zero TTL is provided when the object is created. A user callback can be defined to get called when an item is about to be removed from a particular cache level, in case any housekeeping needed.
Items in L1 can be accessed in heap casually and reliably if the following is borne in mind:
In short process cache results before returning to the event loop or writing or removing items in the cache.
Caches are created using an info struct struct lws_cache_creation_info
that should be zeroed down. Most members are optional and can be left at zero, a pointer to the lws_context and a short cache name are mandatory.
How caches work is defined by an "ops struct" that the cache is bound to at creation time. lws_cache_ops_heap
ops struct is provided by lws, you can define your own to implement your own specialized cache level. See ./include/libwebsockets/lws-cache-ttl.h
for the definition.
Created cache levels should be destroyed when you are finished with them.
For L1, in heap, this frees any allocations. For other levels, eg, with file storage for the items, this would close the file and leave any entries as they are.
The combined caches are always accessed via the L1 cache, writing new items is done at L1 and writes through to each cache layer immediately, so new items go into the backing store without delay, but are available from heap for read.
If existing keys are rewritten, the previous item of the same key is deleted from all levels of the cache before writing the new one.
Removal also is performed at all cache levels at once.
internally earlier cache levels can evict cached items just at their level, but this is triggered automatically and not by api.
A wildcard key is supported, removing all items matching, eg "myitem*".
Apis are provided to get the blob related to a specific key, if it exists at any cache layer. Again this should use L1, it will bring a copy of the item into L1 if one is not already there, so it can be accessed from heap.
lws_cache also supports lookup queries that contain wildcards or otherwise match on multiple keys according to cache-specific rules. These queries do not return a single item, instead they return lists of keys that match, in a blob of its own that is also cached in L1.
The user can walk the lookup results blob using a provided helper api
After recovering each result key this way, the user code can use the _get api to access the blob for each indiviudally.
The lookup results themselves are cached in L1, any new key that matches the wildcard lookup in any cached results, or any deletion of items with keys matching the cached wildcard lookup invalidate the affected cached lookup results so they will be regenerated next time.
In the typical case after a lookup, at least for a while the lookup results blob and all items mentioned in the lookup results will already be in L1 and cheaply accessible.
An api is also provided to "expunge" or completely empty all cache levels and corresponding backing stores.