1*1c60b9acSAndroid Build Coastguard Worker /*
2*1c60b9acSAndroid Build Coastguard Worker * libwebsockets - small server side websockets and web server implementation
3*1c60b9acSAndroid Build Coastguard Worker *
4*1c60b9acSAndroid Build Coastguard Worker * Copyright (C) 2010 - 2021 Andy Green <[email protected]>
5*1c60b9acSAndroid Build Coastguard Worker *
6*1c60b9acSAndroid Build Coastguard Worker * Permission is hereby granted, free of charge, to any person obtaining a copy
7*1c60b9acSAndroid Build Coastguard Worker * of this software and associated documentation files (the "Software"), to
8*1c60b9acSAndroid Build Coastguard Worker * deal in the Software without restriction, including without limitation the
9*1c60b9acSAndroid Build Coastguard Worker * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
10*1c60b9acSAndroid Build Coastguard Worker * sell copies of the Software, and to permit persons to whom the Software is
11*1c60b9acSAndroid Build Coastguard Worker * furnished to do so, subject to the following conditions:
12*1c60b9acSAndroid Build Coastguard Worker *
13*1c60b9acSAndroid Build Coastguard Worker * The above copyright notice and this permission notice shall be included in
14*1c60b9acSAndroid Build Coastguard Worker * all copies or substantial portions of the Software.
15*1c60b9acSAndroid Build Coastguard Worker *
16*1c60b9acSAndroid Build Coastguard Worker * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17*1c60b9acSAndroid Build Coastguard Worker * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18*1c60b9acSAndroid Build Coastguard Worker * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19*1c60b9acSAndroid Build Coastguard Worker * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20*1c60b9acSAndroid Build Coastguard Worker * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
21*1c60b9acSAndroid Build Coastguard Worker * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
22*1c60b9acSAndroid Build Coastguard Worker * IN THE SOFTWARE.
23*1c60b9acSAndroid Build Coastguard Worker */
24*1c60b9acSAndroid Build Coastguard Worker
25*1c60b9acSAndroid Build Coastguard Worker #include <private-lib-core.h>
26*1c60b9acSAndroid Build Coastguard Worker #include "private-lib-misc-cache-ttl.h"
27*1c60b9acSAndroid Build Coastguard Worker
28*1c60b9acSAndroid Build Coastguard Worker #include <assert.h>
29*1c60b9acSAndroid Build Coastguard Worker
30*1c60b9acSAndroid Build Coastguard Worker #if defined(write)
31*1c60b9acSAndroid Build Coastguard Worker #undef write
32*1c60b9acSAndroid Build Coastguard Worker #endif
33*1c60b9acSAndroid Build Coastguard Worker
34*1c60b9acSAndroid Build Coastguard Worker void
lws_cache_clear_matches(lws_dll2_owner_t * results_owner)35*1c60b9acSAndroid Build Coastguard Worker lws_cache_clear_matches(lws_dll2_owner_t *results_owner)
36*1c60b9acSAndroid Build Coastguard Worker {
37*1c60b9acSAndroid Build Coastguard Worker lws_start_foreach_dll_safe(struct lws_dll2 *, d, d1, results_owner->head) {
38*1c60b9acSAndroid Build Coastguard Worker lws_cache_match_t *item = lws_container_of(d, lws_cache_match_t,
39*1c60b9acSAndroid Build Coastguard Worker list);
40*1c60b9acSAndroid Build Coastguard Worker lws_dll2_remove(d);
41*1c60b9acSAndroid Build Coastguard Worker lws_free(item);
42*1c60b9acSAndroid Build Coastguard Worker } lws_end_foreach_dll_safe(d, d1);
43*1c60b9acSAndroid Build Coastguard Worker }
44*1c60b9acSAndroid Build Coastguard Worker
45*1c60b9acSAndroid Build Coastguard Worker void
lws_cache_schedule(struct lws_cache_ttl_lru * cache,sul_cb_t cb,lws_usec_t e)46*1c60b9acSAndroid Build Coastguard Worker lws_cache_schedule(struct lws_cache_ttl_lru *cache, sul_cb_t cb, lws_usec_t e)
47*1c60b9acSAndroid Build Coastguard Worker {
48*1c60b9acSAndroid Build Coastguard Worker lwsl_cache("%s: %s schedule %llu\n", __func__, cache->info.name,
49*1c60b9acSAndroid Build Coastguard Worker (unsigned long long)e);
50*1c60b9acSAndroid Build Coastguard Worker
51*1c60b9acSAndroid Build Coastguard Worker lws_sul_schedule(cache->info.cx, cache->info.tsi, &cache->sul, cb,
52*1c60b9acSAndroid Build Coastguard Worker e - lws_now_usecs());
53*1c60b9acSAndroid Build Coastguard Worker }
54*1c60b9acSAndroid Build Coastguard Worker
55*1c60b9acSAndroid Build Coastguard Worker int
lws_cache_write_through(struct lws_cache_ttl_lru * cache,const char * specific_key,const uint8_t * source,size_t size,lws_usec_t expiry,void ** ppay)56*1c60b9acSAndroid Build Coastguard Worker lws_cache_write_through(struct lws_cache_ttl_lru *cache,
57*1c60b9acSAndroid Build Coastguard Worker const char *specific_key, const uint8_t *source,
58*1c60b9acSAndroid Build Coastguard Worker size_t size, lws_usec_t expiry, void **ppay)
59*1c60b9acSAndroid Build Coastguard Worker {
60*1c60b9acSAndroid Build Coastguard Worker struct lws_cache_ttl_lru *levels[LWS_CACHE_MAX_LEVELS], *c = cache;
61*1c60b9acSAndroid Build Coastguard Worker int n = 0, r = 0;
62*1c60b9acSAndroid Build Coastguard Worker
63*1c60b9acSAndroid Build Coastguard Worker lws_cache_item_remove(cache, specific_key);
64*1c60b9acSAndroid Build Coastguard Worker
65*1c60b9acSAndroid Build Coastguard Worker /* starting from L1 */
66*1c60b9acSAndroid Build Coastguard Worker
67*1c60b9acSAndroid Build Coastguard Worker do {
68*1c60b9acSAndroid Build Coastguard Worker levels[n++] = c;
69*1c60b9acSAndroid Build Coastguard Worker c = c->info.parent;
70*1c60b9acSAndroid Build Coastguard Worker } while (c && n < (int)LWS_ARRAY_SIZE(levels));
71*1c60b9acSAndroid Build Coastguard Worker
72*1c60b9acSAndroid Build Coastguard Worker /* starting from outermost cache level */
73*1c60b9acSAndroid Build Coastguard Worker
74*1c60b9acSAndroid Build Coastguard Worker while (n) {
75*1c60b9acSAndroid Build Coastguard Worker n--;
76*1c60b9acSAndroid Build Coastguard Worker r = levels[n]->info.ops->write(levels[n], specific_key,
77*1c60b9acSAndroid Build Coastguard Worker source, size, expiry, ppay);
78*1c60b9acSAndroid Build Coastguard Worker }
79*1c60b9acSAndroid Build Coastguard Worker
80*1c60b9acSAndroid Build Coastguard Worker return r;
81*1c60b9acSAndroid Build Coastguard Worker }
82*1c60b9acSAndroid Build Coastguard Worker
83*1c60b9acSAndroid Build Coastguard Worker /*
84*1c60b9acSAndroid Build Coastguard Worker * We want to make a list of unique keys that exist at any cache level
85*1c60b9acSAndroid Build Coastguard Worker * matching a wildcard search key.
86*1c60b9acSAndroid Build Coastguard Worker *
87*1c60b9acSAndroid Build Coastguard Worker * If L1 has a cached version though, we will just use that.
88*1c60b9acSAndroid Build Coastguard Worker */
89*1c60b9acSAndroid Build Coastguard Worker
90*1c60b9acSAndroid Build Coastguard Worker int
lws_cache_lookup(struct lws_cache_ttl_lru * cache,const char * wildcard_key,const void ** pdata,size_t * psize)91*1c60b9acSAndroid Build Coastguard Worker lws_cache_lookup(struct lws_cache_ttl_lru *cache, const char *wildcard_key,
92*1c60b9acSAndroid Build Coastguard Worker const void **pdata, size_t *psize)
93*1c60b9acSAndroid Build Coastguard Worker {
94*1c60b9acSAndroid Build Coastguard Worker struct lws_cache_ttl_lru *l1 = cache;
95*1c60b9acSAndroid Build Coastguard Worker lws_dll2_owner_t results_owner;
96*1c60b9acSAndroid Build Coastguard Worker lws_usec_t expiry = 0;
97*1c60b9acSAndroid Build Coastguard Worker char meta_key[128];
98*1c60b9acSAndroid Build Coastguard Worker uint8_t *p, *temp;
99*1c60b9acSAndroid Build Coastguard Worker size_t sum = 0;
100*1c60b9acSAndroid Build Coastguard Worker int n;
101*1c60b9acSAndroid Build Coastguard Worker
102*1c60b9acSAndroid Build Coastguard Worker memset(&results_owner, 0, sizeof(results_owner));
103*1c60b9acSAndroid Build Coastguard Worker meta_key[0] = META_ITEM_LEADING;
104*1c60b9acSAndroid Build Coastguard Worker lws_strncpy(&meta_key[1], wildcard_key, sizeof(meta_key) - 2);
105*1c60b9acSAndroid Build Coastguard Worker
106*1c60b9acSAndroid Build Coastguard Worker /*
107*1c60b9acSAndroid Build Coastguard Worker * If we have a cached result set in L1 already, return that
108*1c60b9acSAndroid Build Coastguard Worker */
109*1c60b9acSAndroid Build Coastguard Worker
110*1c60b9acSAndroid Build Coastguard Worker if (!l1->info.ops->get(l1, meta_key, pdata, psize))
111*1c60b9acSAndroid Build Coastguard Worker return 0;
112*1c60b9acSAndroid Build Coastguard Worker
113*1c60b9acSAndroid Build Coastguard Worker /*
114*1c60b9acSAndroid Build Coastguard Worker * No, we have to do the actual lookup work in the backing store layer
115*1c60b9acSAndroid Build Coastguard Worker * to get results for this...
116*1c60b9acSAndroid Build Coastguard Worker */
117*1c60b9acSAndroid Build Coastguard Worker
118*1c60b9acSAndroid Build Coastguard Worker while (cache->info.parent)
119*1c60b9acSAndroid Build Coastguard Worker cache = cache->info.parent;
120*1c60b9acSAndroid Build Coastguard Worker
121*1c60b9acSAndroid Build Coastguard Worker if (cache->info.ops->lookup(cache, wildcard_key, &results_owner)) {
122*1c60b9acSAndroid Build Coastguard Worker /* eg, OOM */
123*1c60b9acSAndroid Build Coastguard Worker
124*1c60b9acSAndroid Build Coastguard Worker lwsl_cache("%s: bs lookup fail\n", __func__);
125*1c60b9acSAndroid Build Coastguard Worker
126*1c60b9acSAndroid Build Coastguard Worker lws_cache_clear_matches(&results_owner);
127*1c60b9acSAndroid Build Coastguard Worker return 1;
128*1c60b9acSAndroid Build Coastguard Worker }
129*1c60b9acSAndroid Build Coastguard Worker
130*1c60b9acSAndroid Build Coastguard Worker /*
131*1c60b9acSAndroid Build Coastguard Worker * Scan the results, we want to know how big a payload it needs in
132*1c60b9acSAndroid Build Coastguard Worker * the cache, and we want to know the earliest expiry of any of the
133*1c60b9acSAndroid Build Coastguard Worker * component parts, so the meta cache entry for these results can be
134*1c60b9acSAndroid Build Coastguard Worker * expired when any of the results would expire.
135*1c60b9acSAndroid Build Coastguard Worker */
136*1c60b9acSAndroid Build Coastguard Worker
137*1c60b9acSAndroid Build Coastguard Worker lws_start_foreach_dll(struct lws_dll2 *, d, results_owner.head) {
138*1c60b9acSAndroid Build Coastguard Worker lws_cache_match_t *m = lws_container_of(d, lws_cache_match_t,
139*1c60b9acSAndroid Build Coastguard Worker list);
140*1c60b9acSAndroid Build Coastguard Worker sum += 8; /* payload size, name length */
141*1c60b9acSAndroid Build Coastguard Worker sum += m->tag_size + 1;
142*1c60b9acSAndroid Build Coastguard Worker
143*1c60b9acSAndroid Build Coastguard Worker if (m->expiry && (!expiry || expiry < m->expiry))
144*1c60b9acSAndroid Build Coastguard Worker expiry = m->expiry;
145*1c60b9acSAndroid Build Coastguard Worker
146*1c60b9acSAndroid Build Coastguard Worker } lws_end_foreach_dll(d);
147*1c60b9acSAndroid Build Coastguard Worker
148*1c60b9acSAndroid Build Coastguard Worker lwsl_cache("%s: results %d, size %d\n", __func__,
149*1c60b9acSAndroid Build Coastguard Worker (int)results_owner.count, (int)sum);
150*1c60b9acSAndroid Build Coastguard Worker
151*1c60b9acSAndroid Build Coastguard Worker temp = lws_malloc(sum, __func__);
152*1c60b9acSAndroid Build Coastguard Worker if (!temp) {
153*1c60b9acSAndroid Build Coastguard Worker lws_cache_clear_matches(&results_owner);
154*1c60b9acSAndroid Build Coastguard Worker return 1;
155*1c60b9acSAndroid Build Coastguard Worker }
156*1c60b9acSAndroid Build Coastguard Worker
157*1c60b9acSAndroid Build Coastguard Worker /*
158*1c60b9acSAndroid Build Coastguard Worker * Fill temp with the serialized results
159*1c60b9acSAndroid Build Coastguard Worker */
160*1c60b9acSAndroid Build Coastguard Worker
161*1c60b9acSAndroid Build Coastguard Worker p = temp;
162*1c60b9acSAndroid Build Coastguard Worker lws_start_foreach_dll(struct lws_dll2 *, d, results_owner.head) {
163*1c60b9acSAndroid Build Coastguard Worker lws_cache_match_t *m = lws_container_of(d, lws_cache_match_t,
164*1c60b9acSAndroid Build Coastguard Worker list);
165*1c60b9acSAndroid Build Coastguard Worker
166*1c60b9acSAndroid Build Coastguard Worker /* we don't copy the payload in, but take note of its size */
167*1c60b9acSAndroid Build Coastguard Worker lws_ser_wu32be(p, (uint32_t)m->payload_size);
168*1c60b9acSAndroid Build Coastguard Worker p += 4;
169*1c60b9acSAndroid Build Coastguard Worker /* length of the tag name (there is an uncounted NUL after) */
170*1c60b9acSAndroid Build Coastguard Worker lws_ser_wu32be(p, (uint32_t)m->tag_size);
171*1c60b9acSAndroid Build Coastguard Worker p += 4;
172*1c60b9acSAndroid Build Coastguard Worker
173*1c60b9acSAndroid Build Coastguard Worker /* then the tag name, plus the extra NUL */
174*1c60b9acSAndroid Build Coastguard Worker memcpy(p, &m[1], m->tag_size + 1);
175*1c60b9acSAndroid Build Coastguard Worker p += m->tag_size + 1;
176*1c60b9acSAndroid Build Coastguard Worker
177*1c60b9acSAndroid Build Coastguard Worker } lws_end_foreach_dll(d);
178*1c60b9acSAndroid Build Coastguard Worker
179*1c60b9acSAndroid Build Coastguard Worker lws_cache_clear_matches(&results_owner);
180*1c60b9acSAndroid Build Coastguard Worker
181*1c60b9acSAndroid Build Coastguard Worker /*
182*1c60b9acSAndroid Build Coastguard Worker * Create the right amount of space for an L1 record of these results,
183*1c60b9acSAndroid Build Coastguard Worker * with its expiry set to the earliest of the results, and copy it in
184*1c60b9acSAndroid Build Coastguard Worker * from temp
185*1c60b9acSAndroid Build Coastguard Worker */
186*1c60b9acSAndroid Build Coastguard Worker
187*1c60b9acSAndroid Build Coastguard Worker n = l1->info.ops->write(l1, meta_key, temp, sum, expiry, (void **)&p);
188*1c60b9acSAndroid Build Coastguard Worker /* done with temp */
189*1c60b9acSAndroid Build Coastguard Worker lws_free(temp);
190*1c60b9acSAndroid Build Coastguard Worker
191*1c60b9acSAndroid Build Coastguard Worker if (n)
192*1c60b9acSAndroid Build Coastguard Worker return 1;
193*1c60b9acSAndroid Build Coastguard Worker
194*1c60b9acSAndroid Build Coastguard Worker /* point to the results in L1 */
195*1c60b9acSAndroid Build Coastguard Worker
196*1c60b9acSAndroid Build Coastguard Worker *pdata = p;
197*1c60b9acSAndroid Build Coastguard Worker *psize = sum;
198*1c60b9acSAndroid Build Coastguard Worker
199*1c60b9acSAndroid Build Coastguard Worker return 0;
200*1c60b9acSAndroid Build Coastguard Worker }
201*1c60b9acSAndroid Build Coastguard Worker
202*1c60b9acSAndroid Build Coastguard Worker int
lws_cache_item_get(struct lws_cache_ttl_lru * cache,const char * specific_key,const void ** pdata,size_t * psize)203*1c60b9acSAndroid Build Coastguard Worker lws_cache_item_get(struct lws_cache_ttl_lru *cache, const char *specific_key,
204*1c60b9acSAndroid Build Coastguard Worker const void **pdata, size_t *psize)
205*1c60b9acSAndroid Build Coastguard Worker {
206*1c60b9acSAndroid Build Coastguard Worker while (cache) {
207*1c60b9acSAndroid Build Coastguard Worker if (!cache->info.ops->get(cache, specific_key, pdata, psize)) {
208*1c60b9acSAndroid Build Coastguard Worker lwsl_cache("%s: hit\n", __func__);
209*1c60b9acSAndroid Build Coastguard Worker return 0;
210*1c60b9acSAndroid Build Coastguard Worker }
211*1c60b9acSAndroid Build Coastguard Worker
212*1c60b9acSAndroid Build Coastguard Worker cache = cache->info.parent;
213*1c60b9acSAndroid Build Coastguard Worker }
214*1c60b9acSAndroid Build Coastguard Worker
215*1c60b9acSAndroid Build Coastguard Worker return 1;
216*1c60b9acSAndroid Build Coastguard Worker }
217*1c60b9acSAndroid Build Coastguard Worker
218*1c60b9acSAndroid Build Coastguard Worker int
lws_cache_expunge(struct lws_cache_ttl_lru * cache)219*1c60b9acSAndroid Build Coastguard Worker lws_cache_expunge(struct lws_cache_ttl_lru *cache)
220*1c60b9acSAndroid Build Coastguard Worker {
221*1c60b9acSAndroid Build Coastguard Worker int ret = 0;
222*1c60b9acSAndroid Build Coastguard Worker
223*1c60b9acSAndroid Build Coastguard Worker while (cache) {
224*1c60b9acSAndroid Build Coastguard Worker ret |= cache->info.ops->expunge(cache);
225*1c60b9acSAndroid Build Coastguard Worker
226*1c60b9acSAndroid Build Coastguard Worker cache = cache->info.parent;
227*1c60b9acSAndroid Build Coastguard Worker }
228*1c60b9acSAndroid Build Coastguard Worker
229*1c60b9acSAndroid Build Coastguard Worker return ret;
230*1c60b9acSAndroid Build Coastguard Worker }
231*1c60b9acSAndroid Build Coastguard Worker
232*1c60b9acSAndroid Build Coastguard Worker int
lws_cache_item_remove(struct lws_cache_ttl_lru * cache,const char * wildcard_key)233*1c60b9acSAndroid Build Coastguard Worker lws_cache_item_remove(struct lws_cache_ttl_lru *cache, const char *wildcard_key)
234*1c60b9acSAndroid Build Coastguard Worker {
235*1c60b9acSAndroid Build Coastguard Worker while (cache) {
236*1c60b9acSAndroid Build Coastguard Worker if (cache->info.ops->invalidate(cache, wildcard_key))
237*1c60b9acSAndroid Build Coastguard Worker return 1;
238*1c60b9acSAndroid Build Coastguard Worker
239*1c60b9acSAndroid Build Coastguard Worker cache = cache->info.parent;
240*1c60b9acSAndroid Build Coastguard Worker }
241*1c60b9acSAndroid Build Coastguard Worker
242*1c60b9acSAndroid Build Coastguard Worker return 0;
243*1c60b9acSAndroid Build Coastguard Worker }
244*1c60b9acSAndroid Build Coastguard Worker
245*1c60b9acSAndroid Build Coastguard Worker uint64_t
lws_cache_footprint(struct lws_cache_ttl_lru * cache)246*1c60b9acSAndroid Build Coastguard Worker lws_cache_footprint(struct lws_cache_ttl_lru *cache)
247*1c60b9acSAndroid Build Coastguard Worker {
248*1c60b9acSAndroid Build Coastguard Worker return cache->current_footprint;
249*1c60b9acSAndroid Build Coastguard Worker }
250*1c60b9acSAndroid Build Coastguard Worker
251*1c60b9acSAndroid Build Coastguard Worker void
lws_cache_debug_dump(struct lws_cache_ttl_lru * cache)252*1c60b9acSAndroid Build Coastguard Worker lws_cache_debug_dump(struct lws_cache_ttl_lru *cache)
253*1c60b9acSAndroid Build Coastguard Worker {
254*1c60b9acSAndroid Build Coastguard Worker #if defined(_DEBUG)
255*1c60b9acSAndroid Build Coastguard Worker if (cache->info.ops->debug_dump)
256*1c60b9acSAndroid Build Coastguard Worker cache->info.ops->debug_dump(cache);
257*1c60b9acSAndroid Build Coastguard Worker #endif
258*1c60b9acSAndroid Build Coastguard Worker }
259*1c60b9acSAndroid Build Coastguard Worker
260*1c60b9acSAndroid Build Coastguard Worker int
lws_cache_results_walk(lws_cache_results_t * walk_ctx)261*1c60b9acSAndroid Build Coastguard Worker lws_cache_results_walk(lws_cache_results_t *walk_ctx)
262*1c60b9acSAndroid Build Coastguard Worker {
263*1c60b9acSAndroid Build Coastguard Worker if (!walk_ctx->size)
264*1c60b9acSAndroid Build Coastguard Worker return 1;
265*1c60b9acSAndroid Build Coastguard Worker
266*1c60b9acSAndroid Build Coastguard Worker walk_ctx->payload_len = lws_ser_ru32be(walk_ctx->ptr);
267*1c60b9acSAndroid Build Coastguard Worker walk_ctx->tag_len = lws_ser_ru32be(walk_ctx->ptr + 4);
268*1c60b9acSAndroid Build Coastguard Worker walk_ctx->tag = walk_ctx->ptr + 8;
269*1c60b9acSAndroid Build Coastguard Worker
270*1c60b9acSAndroid Build Coastguard Worker walk_ctx->ptr += walk_ctx->tag_len + 1 + 8;
271*1c60b9acSAndroid Build Coastguard Worker walk_ctx->size -= walk_ctx->tag_len + 1 + 8;
272*1c60b9acSAndroid Build Coastguard Worker
273*1c60b9acSAndroid Build Coastguard Worker return 0;
274*1c60b9acSAndroid Build Coastguard Worker }
275*1c60b9acSAndroid Build Coastguard Worker
276*1c60b9acSAndroid Build Coastguard Worker struct lws_cache_ttl_lru *
lws_cache_create(const struct lws_cache_creation_info * info)277*1c60b9acSAndroid Build Coastguard Worker lws_cache_create(const struct lws_cache_creation_info *info)
278*1c60b9acSAndroid Build Coastguard Worker {
279*1c60b9acSAndroid Build Coastguard Worker assert(info);
280*1c60b9acSAndroid Build Coastguard Worker assert(info->ops);
281*1c60b9acSAndroid Build Coastguard Worker assert(info->name);
282*1c60b9acSAndroid Build Coastguard Worker assert(info->ops->create);
283*1c60b9acSAndroid Build Coastguard Worker
284*1c60b9acSAndroid Build Coastguard Worker return info->ops->create(info);
285*1c60b9acSAndroid Build Coastguard Worker }
286*1c60b9acSAndroid Build Coastguard Worker
287*1c60b9acSAndroid Build Coastguard Worker void
lws_cache_destroy(struct lws_cache_ttl_lru ** _cache)288*1c60b9acSAndroid Build Coastguard Worker lws_cache_destroy(struct lws_cache_ttl_lru **_cache)
289*1c60b9acSAndroid Build Coastguard Worker {
290*1c60b9acSAndroid Build Coastguard Worker lws_cache_ttl_lru_t *cache = *_cache;
291*1c60b9acSAndroid Build Coastguard Worker
292*1c60b9acSAndroid Build Coastguard Worker if (!cache)
293*1c60b9acSAndroid Build Coastguard Worker return;
294*1c60b9acSAndroid Build Coastguard Worker
295*1c60b9acSAndroid Build Coastguard Worker assert(cache->info.ops->destroy);
296*1c60b9acSAndroid Build Coastguard Worker
297*1c60b9acSAndroid Build Coastguard Worker lws_sul_cancel(&cache->sul);
298*1c60b9acSAndroid Build Coastguard Worker
299*1c60b9acSAndroid Build Coastguard Worker cache->info.ops->destroy(_cache);
300*1c60b9acSAndroid Build Coastguard Worker }
301