libwebsockets
Lightweight C library for HTML5 websockets
lws-cache-ttl.h
Go to the documentation of this file.
1 /*
2  * libwebsockets - small server side websockets and web server implementation
3  *
4  * Copyright (C) 2010 - 2021 Andy Green <andy@warmcat.com>
5  *
6  * Permission is hereby granted, free of charge, to any person obtaining a copy
7  * of this software and associated documentation files (the "Software"), to
8  * deal in the Software without restriction, including without limitation the
9  * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
10  * sell copies of the Software, and to permit persons to whom the Software is
11  * furnished to do so, subject to the following conditions:
12  *
13  * The above copyright notice and this permission notice shall be included in
14  * all copies or substantial portions of the Software.
15  *
16  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19  * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
21  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
22  * IN THE SOFTWARE.
23  */
24 
25 /** \defgroup lws_cache_ttl Cache supporting expiry
26  * ##Cache supporting expiry
27  *
28  * These apis let you quickly and reliably implement caches of named objects,
29  * that have a "destroy-by date" and cache limits that will be observed.
30  *
31  * You can instantiate as many caches as you need. The first one must be an
32  * L1 / heap cache type, it can have parents and grandparents of other types
33  * which are accessible why writing / looking up and getting from the L1 cache.
34  * The outer "cache" layer may persistently store items to a backing store.
35  *
36  * Allocated object memory is entirely for the use of user code, up to the
37  * requested size.
38  *
39  * The key name for the listed objects may be any string chosen by the user,
40  * there is no special length limit as it is also allocated.
41  *
42  * Both expiry and LRU orderings are kept so it is easy to find out usage
43  * ordering and when the next object that will expire.
44  *
45  * Cached objects may be destroyed any time you go around the event loop, when
46  * you allocate new objects (to keep the whole cache under the specified limit),
47  * or when their expiry time arrives. So you shouldn't keep copies of pointers
48  * to cached objects after returning to the event loop.
49  */
50 ///@{
51 
52 
53 struct lws_cache_ttl_lru;
54 
55 /**
56  * lws_cache_write_through() - add a new cache item object in all layers
57  *
58  * \param cache: the existing cache to allocate the object in
59  * \param specific_key: a key string that identifies the item in the cache
60  * \param source: optional payload for the cached item, NULL means caller will
61  * write the payload
62  * \param size: the size of the object to allocate
63  * \param expiry: the usec time that the object will autodestroy
64  * \param ppay: NULL, or a pointer to a void * to be set to the L1 payload
65  *
66  * If an item with the key already exists, it is destroyed before allocating a
67  * new one.
68  *
69  * Returns 0 if successful. The written entry will be scheduled to be auto-
70  * destroyed when \p expiry occurs.
71  *
72  * Adding or removing cache items may cause invalidation of cached queries.
73  */
74 LWS_VISIBLE LWS_EXTERN int /* only valid until return to event loop */
75 lws_cache_write_through(struct lws_cache_ttl_lru *cache,
76  const char *specific_key, const uint8_t *source,
77  size_t size, lws_usec_t expiry, void **ppay);
78 
79 typedef struct lws_cache_match {
82  /* earliest expiry amongst results */
84  /**< the payload is not attached here. This is a hint about what
85  * (*get)() will return for this tag name.
86  */
88 
89  /* tag name + NUL is overcommitted */
90 } lws_cache_match_t;
91 
92 /**
93  * lws_cache_heap_lookup() - get a list of matching items
94  *
95  * \param cache: the cache to search for the key
96  * \param wildcard_key: the item key string, may contain wildcards
97  * \param pdata: pointer to pointer to be set to the serialized result list
98  * \param psize: pointer to size_t to receive length of serialized result list
99  *
100  * This finds all unique items in the final cache that match search_key, which
101  * may contain wildcards. It does not return the payloads for matching items,
102  * just a list of specific tags in the that match.
103  *
104  * If successful, results are provided in a serialized list format, in no
105  * particular order, each result has the following fields
106  *
107  * - BE32: payload size in bytes (payload itself is not included)
108  * - BE32: specific tag name length in bytes
109  * - chars: tag name with terminating NUL
110  *
111  * These serialized results are themselves cached in L1 cache (only) and the
112  * result pointers are set pointing into that. If the results are still in L1
113  * cache next time this api is called, the results will be returned directly
114  * from that without repeating the expensive lookup on the backup store. That
115  * is why the results are provided in serialized form.
116  *
117  * The cached results list expiry is set to the earliest expiry of any listed
118  * item. Additionally any cached results are invalidated on addition or
119  * deletion (update is done as addition + deletion) of any item that would
120  * match the results' original wildcard_key. For the typical case new items
121  * are rare compared to lookups, this is efficient.
122  *
123  * Lookup matching does not itself affect LRU or cache status of the result
124  * itsems. Typically user code will get the lookup results, and then perform
125  * get operations on each item in its desired order, that will bring the items
126  * to the head of the LRU list and occupy L1 cache.
127  *
128  * Returns 0 if proceeded alright, or nonzero if error. If there was an error,
129  * any partial results set has been deallocated cleanly before returning.
130  */
131 LWS_VISIBLE LWS_EXTERN int
132 lws_cache_lookup(struct lws_cache_ttl_lru *cache, const char *wildcard_key,
133  const void **pdata, size_t *psize);
134 
135 /**
136  * lws_cache_item_get() - bring a specific item into L1 and get payload info
137  *
138  * \param cache: the cache to search for the key
139  * \param specific_key: the key string of the item to get
140  * \param pdata: pointer to a void * to be set to the payload in L1 cache
141  * \param psize: pointer to a size_t to be set to the payload size
142  *
143  * If the cache still has an item matching the key string, it will be destroyed.
144  *
145  * Adding or removing cache items may cause invalidation of cached queries.
146  *
147  * Notice the cache payload is a blob of the given size. If you are storing
148  * strings, there is no NUL termination unless you stored them with it.
149  *
150  * Returns 0 if successful.
151  */
152 LWS_VISIBLE LWS_EXTERN int
153 lws_cache_item_get(struct lws_cache_ttl_lru *cache, const char *specific_key,
154  const void **pdata, size_t *psize);
155 
156 /**
157  * lws_cache_item_remove() - remove item from all cache levels
158  *
159  * \param cache: the cache to search for the key
160  * \param wildcard_key: the item key string
161  *
162  * Removes any copy of any item matching the \p wildcard_key from any cache
163  * level in one step.
164  *
165  * Adding or removing cache items may cause invalidation of cached queries
166  * that could refer to the removed item.
167  */
168 LWS_VISIBLE LWS_EXTERN int
169 lws_cache_item_remove(struct lws_cache_ttl_lru *cache, const char *wildcard_key);
170 
171 /**
172  * lws_cache_footprint() - query the amount of storage used by the cache layer
173  *
174  * \param cache: cache to query
175  *
176  * Returns number of payload bytes stored in cache currently
177  */
178 LWS_VISIBLE LWS_EXTERN uint64_t
179 lws_cache_footprint(struct lws_cache_ttl_lru *cache);
180 
181 /**
182  * lws_cache_debug_dump() - if built in debug mode dump cache contents to log
183  *
184  * \param cache: cache to dump
185  *
186  * If lws was built in debug mode, dump cache to log, otherwise a NOP.
187  */
188 LWS_VISIBLE LWS_EXTERN void
189 lws_cache_debug_dump(struct lws_cache_ttl_lru *cache);
190 
191 typedef struct lws_cache_results {
192  const uint8_t *ptr; /* set before using walk api */
193  size_t size; /* set before using walk api */
194 
197  const uint8_t *tag;
198 } lws_cache_results_t;
199 
200 /**
201  * lws_cache_results_walk() - parse next result
202  *
203  * \param walk_ctx: the context of the results blob to walk
204  *
205  * Caller must initialize \p walk_ctx.ptr and \p walk_ctx.size before calling.
206  * These are set to the results returned from a _lookup api call.
207  *
208  * The call returns 0 if the struct elements have been set to a result, or 1
209  * if there where no more results in the blob to walk.
210  *
211  * If successful, after the call \p payload_len is set to the length of the
212  * payload related to this result key (the payload itself is not present),
213  * \p tag_len is set to the length of the result key name, and \p tag is set
214  * to the result tag name, with a terminating NUL.
215  */
216 LWS_VISIBLE LWS_EXTERN int
217 lws_cache_results_walk(lws_cache_results_t *walk_ctx);
218 
219 typedef void (*lws_cache_item_destroy_cb)(void *item, size_t size);
221  struct lws_context *cx;
222  /**< Mandatory: the lws_context */
223  const char *name;
224  /**< Mandatory: short cache name */
226  /**< NULL, or a callback that can hook cache item destory */
227  struct lws_cache_ttl_lru *parent;
228  /**< NULL, or next cache level */
229  const struct lws_cache_ops *ops;
230  /**< NULL for default, heap-based ops, else custom cache storage and
231  * query implementation */
232 
233  union {
234  struct {
235  const char *filepath;
236  /**< the filepath to store items in */
237  } nscookiejar;
238  } u;
239  /**< these are extra configuration for specific cache types */
240 
242  /**< 0, or the max heap allocation allowed before destroying
243  * lru items to keep it under the limit */
245  /**< 0, or the max number of items allowed in the cache before
246  * destroying lru items to keep it under the limit */
248  /**< 0, or the max allowed payload size for one item */
249  int tsi;
250  /**< 0 unless using SMP, then tsi to bind sul to */
251 };
252 
254  struct lws_cache_ttl_lru *
255  (*create)(const struct lws_cache_creation_info *info);
256  /**< create an instance of the cache type specified in info */
257 
258  void
259  (*destroy)(struct lws_cache_ttl_lru **_cache);
260  /**< destroy the logical cache instance pointed to by *_cache, doesn't
261  * affect any NV backing storage */
262 
263  int
264  (*expunge)(struct lws_cache_ttl_lru *cache);
265  /**< completely delete any backing storage related to the cache
266  * instance, eg, delete the backing file */
267 
268  int
269  (*write)(struct lws_cache_ttl_lru *cache, const char *specific_key,
270  const uint8_t *source, size_t size, lws_usec_t expiry,
271  void **ppvoid);
272  /**< create an entry in the cache level according to the given info */
273  int
274  (*tag_match)(struct lws_cache_ttl_lru *cache, const char *wc,
275  const char *tag, char lookup_rules);
276  /**< Just tell us if tag would match wildcard, using whatever special
277  * rules the backing store might use for tag matching. 0 indicates
278  * it is a match on wildcard, nonzero means does not match.
279  */
280  int
281  (*lookup)(struct lws_cache_ttl_lru *cache, const char *wildcard_key,
282  lws_dll2_owner_t *results_owner);
283  /**+ add keys for search_key matches not already listed in the results
284  * owner */
285  int
286  (*invalidate)(struct lws_cache_ttl_lru *cache, const char *wildcard_key);
287  /**< remove matching item(s) from cache level */
288 
289  int
290  (*get)(struct lws_cache_ttl_lru *cache, const char *specific_key,
291  const void **pdata, size_t *psize);
292  /**< if it has the item, fills L1 with item. updates LRU, and returns
293  * pointer to payload in L1 */
294 
295  void
296  (*debug_dump)(struct lws_cache_ttl_lru *cache);
297  /**< Helper to dump the whole cache contents to log, useful for debug */
298 };
299 
300 /**
301  * lws_cache_create() - create an empty cache you can allocate items in
302  *
303  * \param info: a struct describing the cache to create
304  *
305  * Create an empty cache you can allocate items in. The cache will be kept
306  * below the max_footprint and max_items limits if they are nonzero, by
307  * destroying least-recently-used items until it remains below the limits.
308  *
309  * Items will auto-destroy when their expiry time is reached.
310  *
311  * When items are destroyed from the cache, if \p cb is non-NULL, it will be
312  * called back with the item pointer after it has been removed from the cache,
313  * but before it is deallocated and destroyed.
314  *
315  * context and tsi are used when scheduling expiry callbacks
316  */
317 LWS_VISIBLE LWS_EXTERN struct lws_cache_ttl_lru *
319 
320 /**
321  * lws_cache_destroy() - destroy a previously created cache
322  *
323  * \param cache: pointer to the cache
324  *
325  * Everything in the cache is destroyed, then the cache itself is destroyed,
326  * and *cache set to NULL.
327  */
328 LWS_VISIBLE LWS_EXTERN void
329 lws_cache_destroy(struct lws_cache_ttl_lru **cache);
330 
331 /**
332  * lws_cache_expunge() - destroy all items in cache and parents
333  *
334  * \param cache: pointer to the cache
335  *
336  * Everything in the cache and parents is destroyed, leaving it empty.
337  * If the cache has a backing store, it is deleted.
338  *
339  * Returns 0 if no problems reported at any cache layer, else nonzero.
340  */
341 LWS_VISIBLE LWS_EXTERN int
342 lws_cache_expunge(struct lws_cache_ttl_lru *cache);
343 
344 LWS_VISIBLE extern const struct lws_cache_ops lws_cache_ops_heap,
345  lws_cache_ops_nscookiejar;
346 
347 ///@}