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