• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 {
80 	lws_dll2_t			list;
81 	lws_usec_t			expiry;
82 	/* earliest expiry amongst results */
83 	size_t				payload_size;
84 	/**< the payload is not attached here.  This is a hint about what
85 	 * (*get)() will return for this tag name.
86 	 */
87 	size_t				tag_size;
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 
195 	size_t			payload_len;
196 	size_t			tag_len;
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);
220 struct lws_cache_creation_info {
221 	struct lws_context		*cx;
222 	/**< Mandatory: the lws_context */
223 	const char			*name;
224 	/**< Mandatory: short cache name */
225 	lws_cache_item_destroy_cb	cb;
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 
241 	size_t				max_footprint;
242 	/**< 0, or the max heap allocation allowed before destroying
243 	 *   lru items to keep it under the limit */
244 	size_t				max_items;
245 	/**< 0, or the max number of items allowed in the cache before
246 	 *   destroying lru items to keep it under the limit */
247 	size_t				max_payload;
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 
253 struct lws_cache_ops {
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 *
318 lws_cache_create(const struct lws_cache_creation_info *info);
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 ///@}
348 
349