xref: /unit/src/nxt_file_cache.c (revision 0:a63ceefd6ab0)
1*0Sigor@sysoev.ru 
2*0Sigor@sysoev.ru /*
3*0Sigor@sysoev.ru  * Copyright (C) Igor Sysoev
4*0Sigor@sysoev.ru  * Copyright (C) NGINX, Inc.
5*0Sigor@sysoev.ru  */
6*0Sigor@sysoev.ru 
7*0Sigor@sysoev.ru #include <nxt_main.h>
8*0Sigor@sysoev.ru 
9*0Sigor@sysoev.ru 
10*0Sigor@sysoev.ru static nxt_int_t nxt_file_cache_lvlhsh_test(nxt_lvlhsh_key_t *hkey, void *data);
11*0Sigor@sysoev.ru static nxt_work_handler_t nxt_file_cache_query_locked(nxt_file_cache_t *cache,
12*0Sigor@sysoev.ru     nxt_file_cache_query_t *q, nxt_lvlhsh_key_t *hkey);
13*0Sigor@sysoev.ru static nxt_work_handler_t nxt_file_cache_node_hold(nxt_file_cache_t *cache,
14*0Sigor@sysoev.ru     nxt_file_cache_query_t *q, nxt_lvlhsh_key_t *hkey);
15*0Sigor@sysoev.ru static nxt_work_handler_t nxt_file_cache_node_test(nxt_file_cache_t *cache,
16*0Sigor@sysoev.ru     nxt_file_cache_query_t *q);
17*0Sigor@sysoev.ru 
18*0Sigor@sysoev.ru static void nxt_file_cache_wait_handler(void *data);
19*0Sigor@sysoev.ru static void nxt_file_cache_timeout_handler(nxt_event_timer_t *ev);
20*0Sigor@sysoev.ru static void nxt_file_cache_wake_handler(void *data);
21*0Sigor@sysoev.ru 
22*0Sigor@sysoev.ru static nxt_file_cache_node_t *nxt_file_cache_node_alloc(nxt_cache_t *cache);
23*0Sigor@sysoev.ru static void nxt_file_cache_node_free(nxt_file_cache_t *cache,
24*0Sigor@sysoev.ru     nxt_file_cache_node_t *node, nxt_bool_t fast);
25*0Sigor@sysoev.ru static nxt_file_cache_query_wait_t *nxt_file_cache_query_wait_alloc(
26*0Sigor@sysoev.ru     nxt_file_cache_t *cache, nxt_bool_t *fast);
27*0Sigor@sysoev.ru static void nxt_file_cache_query_wait_free(nxt_file_cache_t *cache,
28*0Sigor@sysoev.ru     nxt_file_cache_query_wait_t *qw);
29*0Sigor@sysoev.ru static void nxt_file_cache_lock(nxt_file_cache_t *cache);
30*0Sigor@sysoev.ru static void nxt_file_cache_unlock(nxt_file_cache_t *cache);
31*0Sigor@sysoev.ru 
32*0Sigor@sysoev.ru 
33*0Sigor@sysoev.ru void
nxt_file_cache_init(nxt_cache_t * cache)34*0Sigor@sysoev.ru nxt_file_cache_init(nxt_cache_t *cache)
35*0Sigor@sysoev.ru {
36*0Sigor@sysoev.ru     static const nxt_lvlhsh_ctx_t  ctx = {
37*0Sigor@sysoev.ru         nxt_file_cache_lvlhsh_test,
38*0Sigor@sysoev.ru         nxt_lvlhsh_alloc,
39*0Sigor@sysoev.ru         nxt_lvlhsh_free,
40*0Sigor@sysoev.ru         0,
41*0Sigor@sysoev.ru     };
42*0Sigor@sysoev.ru 
43*0Sigor@sysoev.ru     /* lvlhsh with large first level. */
44*0Sigor@sysoev.ru     cache->lvlhsh.shift[1] = 10;
45*0Sigor@sysoev.ru 
46*0Sigor@sysoev.ru     cache->lvlhsh.ctx = &ctx;
47*0Sigor@sysoev.ru 
48*0Sigor@sysoev.ru     cache->start_time = nxt_thread_time();
49*0Sigor@sysoev.ru }
50*0Sigor@sysoev.ru 
51*0Sigor@sysoev.ru 
52*0Sigor@sysoev.ru static nxt_int_t
nxt_file_cache_lvlhsh_test(nxt_lvlhsh_key_t * hkey,void * data)53*0Sigor@sysoev.ru nxt_file_cache_lvlhsh_test(nxt_lvlhsh_key_t *hkey, void *data)
54*0Sigor@sysoev.ru {
55*0Sigor@sysoev.ru     nxt_file_cache_node_t  *node;
56*0Sigor@sysoev.ru 
57*0Sigor@sysoev.ru     node = data;
58*0Sigor@sysoev.ru 
59*0Sigor@sysoev.ru     if (nxt_strmem_eq(&hkey->key, node->key_data, node->key_len)) {
60*0Sigor@sysoev.ru         return NXT_OK;
61*0Sigor@sysoev.ru     }
62*0Sigor@sysoev.ru 
63*0Sigor@sysoev.ru     return NXT_DECLINED;
64*0Sigor@sysoev.ru }
65*0Sigor@sysoev.ru 
66*0Sigor@sysoev.ru 
67*0Sigor@sysoev.ru void
nxt_file_cache_query(nxt_file_cache_t * cache,nxt_file_cache_query_t * q)68*0Sigor@sysoev.ru nxt_file_cache_query(nxt_file_cache_t *cache, nxt_file_cache_query_t *q)
69*0Sigor@sysoev.ru {
70*0Sigor@sysoev.ru     nxt_lvlhsh_key_t    hkey;
71*0Sigor@sysoev.ru     nxt_work_handler_t  handler;
72*0Sigor@sysoev.ru 
73*0Sigor@sysoev.ru     if (cache != NULL) {
74*0Sigor@sysoev.ru         hkey.key.len = q->key_len;
75*0Sigor@sysoev.ru         hkey.key.data = q->key_data;
76*0Sigor@sysoev.ru         hkey.key_hash = nxt_murmur_hash2(q->key_data, q->key_len);
77*0Sigor@sysoev.ru         hkey.replace = 0;
78*0Sigor@sysoev.ru 
79*0Sigor@sysoev.ru         nxt_file_cache_lock(cache);
80*0Sigor@sysoev.ru 
81*0Sigor@sysoev.ru         handler = nxt_file_cache_query_locked(cache, q, &hkey);
82*0Sigor@sysoev.ru 
83*0Sigor@sysoev.ru         nxt_file_cache_unlock(cache);
84*0Sigor@sysoev.ru 
85*0Sigor@sysoev.ru     } else {
86*0Sigor@sysoev.ru         handler = q->state->nocache_handler;
87*0Sigor@sysoev.ru     }
88*0Sigor@sysoev.ru 
89*0Sigor@sysoev.ru     handler(q);
90*0Sigor@sysoev.ru }
91*0Sigor@sysoev.ru 
92*0Sigor@sysoev.ru 
93*0Sigor@sysoev.ru static nxt_work_handler_t
nxt_file_cache_query_locked(nxt_file_cache_t * cache,nxt_file_cache_query_t * q,nxt_lvlhsh_key_t * hkey)94*0Sigor@sysoev.ru nxt_file_cache_query_locked(nxt_file_cache_t *cache, nxt_file_cache_query_t *q,
95*0Sigor@sysoev.ru     nxt_lvlhsh_key_t *hkey)
96*0Sigor@sysoev.ru {
97*0Sigor@sysoev.ru     nxt_int_t                     ret;
98*0Sigor@sysoev.ru     nxt_bool_t                    fast;
99*0Sigor@sysoev.ru     nxt_work_handler_t            handler;
100*0Sigor@sysoev.ru     nxt_file_cache_node_t         *node, *sentinel;
101*0Sigor@sysoev.ru     nxt_file_cache_query_wait_t   *qw;
102*0Sigor@sysoev.ru     nxt_file_cache_query_state_t  *state;
103*0Sigor@sysoev.ru 
104*0Sigor@sysoev.ru     state = q->state;
105*0Sigor@sysoev.ru     sentinel = nxt_file_cache_node_alloc(cache);
106*0Sigor@sysoev.ru 
107*0Sigor@sysoev.ru     if (nxt_slow_path(sentinel == NULL)) {
108*0Sigor@sysoev.ru         return state->error_handler;
109*0Sigor@sysoev.ru     }
110*0Sigor@sysoev.ru 
111*0Sigor@sysoev.ru     sentinel->key_data = q->key_data;
112*0Sigor@sysoev.ru     sentinel->key_len = q->key_len;
113*0Sigor@sysoev.ru     hkey->value = sentinel;
114*0Sigor@sysoev.ru 
115*0Sigor@sysoev.ru     /*
116*0Sigor@sysoev.ru      * Try to insert an empty sentinel node to hold updating
117*0Sigor@sysoev.ru      * process if there is no existent cache node in cache.
118*0Sigor@sysoev.ru      */
119*0Sigor@sysoev.ru 
120*0Sigor@sysoev.ru     ret = nxt_lvlhsh_insert(&cache->lvlhsh, hkey);
121*0Sigor@sysoev.ru 
122*0Sigor@sysoev.ru     if (ret == NXT_OK) {
123*0Sigor@sysoev.ru         /* The sentinel node was successully added. */
124*0Sigor@sysoev.ru 
125*0Sigor@sysoev.ru         q->node = sentinel;
126*0Sigor@sysoev.ru         sentinel->updating = 1;
127*0Sigor@sysoev.ru         return state->update_handler;
128*0Sigor@sysoev.ru     }
129*0Sigor@sysoev.ru 
130*0Sigor@sysoev.ru     nxt_cache_node_free(cache, sentinel, 1);
131*0Sigor@sysoev.ru 
132*0Sigor@sysoev.ru     if (ret == NXT_ERROR) {
133*0Sigor@sysoev.ru         return state->error_handler;
134*0Sigor@sysoev.ru     }
135*0Sigor@sysoev.ru 
136*0Sigor@sysoev.ru     /* NXT_DECLINED: a cache node exists. */
137*0Sigor@sysoev.ru 
138*0Sigor@sysoev.ru     node = hkey->value;
139*0Sigor@sysoev.ru     node->count++;
140*0Sigor@sysoev.ru     q->node = node;
141*0Sigor@sysoev.ru 
142*0Sigor@sysoev.ru     handler = nxt_cache_node_test(cache, q);
143*0Sigor@sysoev.ru 
144*0Sigor@sysoev.ru     if (handler == NULL) {
145*0Sigor@sysoev.ru         /* Add the node to a wait queue. */
146*0Sigor@sysoev.ru 
147*0Sigor@sysoev.ru         qw = nxt_cache_query_wait_alloc(cache, &fast);
148*0Sigor@sysoev.ru         if (nxt_slow_path(qw == NULL)) {
149*0Sigor@sysoev.ru             return state->error_handler;
150*0Sigor@sysoev.ru         }
151*0Sigor@sysoev.ru 
152*0Sigor@sysoev.ru         if (!fast) {
153*0Sigor@sysoev.ru             /* The node state may be changed during slow allocation. */
154*0Sigor@sysoev.ru             handler = nxt_cache_node_test(cache, q);
155*0Sigor@sysoev.ru 
156*0Sigor@sysoev.ru             if (handler != NULL) {
157*0Sigor@sysoev.ru                 nxt_cache_query_wait_free(cache, qw);
158*0Sigor@sysoev.ru                 return handler;
159*0Sigor@sysoev.ru             }
160*0Sigor@sysoev.ru         }
161*0Sigor@sysoev.ru 
162*0Sigor@sysoev.ru         qw->query = q;
163*0Sigor@sysoev.ru         qw->next = node->waiting;
164*0Sigor@sysoev.ru         qw->busy = 0;
165*0Sigor@sysoev.ru         qw->deleted = 0;
166*0Sigor@sysoev.ru         qw->pid = nxt_pid;
167*0Sigor@sysoev.ru         qw->engine = nxt_thread_event_engine();
168*0Sigor@sysoev.ru         qw->handler = nxt_cache_wake_handler;
169*0Sigor@sysoev.ru         qw->cache = cache;
170*0Sigor@sysoev.ru 
171*0Sigor@sysoev.ru         node->waiting = qw;
172*0Sigor@sysoev.ru 
173*0Sigor@sysoev.ru         return nxt_cache_wait_handler;
174*0Sigor@sysoev.ru     }
175*0Sigor@sysoev.ru 
176*0Sigor@sysoev.ru     return handler;
177*0Sigor@sysoev.ru }
178*0Sigor@sysoev.ru 
179*0Sigor@sysoev.ru 
180*0Sigor@sysoev.ru static nxt_work_handler_t
nxt_cache_node_test(nxt_cache_t * cache,nxt_cache_query_t * q)181*0Sigor@sysoev.ru nxt_cache_node_test(nxt_cache_t *cache, nxt_cache_query_t *q)
182*0Sigor@sysoev.ru {
183*0Sigor@sysoev.ru     nxt_time_t               expiry;
184*0Sigor@sysoev.ru     nxt_cache_node_t         *node;
185*0Sigor@sysoev.ru     nxt_cache_query_state_t  *state;
186*0Sigor@sysoev.ru 
187*0Sigor@sysoev.ru     q->stale = 0;
188*0Sigor@sysoev.ru     state = q->state;
189*0Sigor@sysoev.ru     node = q->node;
190*0Sigor@sysoev.ru 
191*0Sigor@sysoev.ru     expiry = cache->start_time + node->expiry;
192*0Sigor@sysoev.ru 
193*0Sigor@sysoev.ru     if (nxt_thread_time() < expiry) {
194*0Sigor@sysoev.ru         return state->ready_handler;
195*0Sigor@sysoev.ru     }
196*0Sigor@sysoev.ru 
197*0Sigor@sysoev.ru     /*
198*0Sigor@sysoev.ru      * A valid stale or empty sentinel cache node.
199*0Sigor@sysoev.ru      * The sentinel node can be only in updating state.
200*0Sigor@sysoev.ru      */
201*0Sigor@sysoev.ru 
202*0Sigor@sysoev.ru     if (node->updating) {
203*0Sigor@sysoev.ru 
204*0Sigor@sysoev.ru         if (node->expiry != 0) {
205*0Sigor@sysoev.ru             /* A valid stale cache node. */
206*0Sigor@sysoev.ru 
207*0Sigor@sysoev.ru             q->stale = 1;
208*0Sigor@sysoev.ru 
209*0Sigor@sysoev.ru             if (q->use_stale) {
210*0Sigor@sysoev.ru                 return state->stale_handler;
211*0Sigor@sysoev.ru             }
212*0Sigor@sysoev.ru         }
213*0Sigor@sysoev.ru 
214*0Sigor@sysoev.ru         return NULL;
215*0Sigor@sysoev.ru     }
216*0Sigor@sysoev.ru 
217*0Sigor@sysoev.ru     /* A valid stale cache node is not being updated now. */
218*0Sigor@sysoev.ru 
219*0Sigor@sysoev.ru     q->stale = 1;
220*0Sigor@sysoev.ru 
221*0Sigor@sysoev.ru     if (q->use_stale) {
222*0Sigor@sysoev.ru 
223*0Sigor@sysoev.ru         if (q->update_stale) {
224*0Sigor@sysoev.ru             node->updating = 1;
225*0Sigor@sysoev.ru             return state->update_stale_handler;
226*0Sigor@sysoev.ru         }
227*0Sigor@sysoev.ru 
228*0Sigor@sysoev.ru         return state->stale_handler;
229*0Sigor@sysoev.ru     }
230*0Sigor@sysoev.ru 
231*0Sigor@sysoev.ru     node->updating = 1;
232*0Sigor@sysoev.ru     return state->update_handler;
233*0Sigor@sysoev.ru }
234*0Sigor@sysoev.ru 
235*0Sigor@sysoev.ru 
236*0Sigor@sysoev.ru static void
nxt_cache_wait_handler(void * data)237*0Sigor@sysoev.ru nxt_cache_wait_handler(void *data)
238*0Sigor@sysoev.ru {
239*0Sigor@sysoev.ru     nxt_thread_t       *thr;
240*0Sigor@sysoev.ru     nxt_event_timer_t  *ev;
241*0Sigor@sysoev.ru     nxt_cache_query_t  *q;
242*0Sigor@sysoev.ru 
243*0Sigor@sysoev.ru     q = data;
244*0Sigor@sysoev.ru 
245*0Sigor@sysoev.ru     if (&q->timeout == 0) {
246*0Sigor@sysoev.ru         return;
247*0Sigor@sysoev.ru     }
248*0Sigor@sysoev.ru 
249*0Sigor@sysoev.ru     ev = &q->timer;
250*0Sigor@sysoev.ru 
251*0Sigor@sysoev.ru     if (!nxt_event_timer_is_set(ev)) {
252*0Sigor@sysoev.ru         thr = nxt_thread();
253*0Sigor@sysoev.ru         ev->log = thr->log;
254*0Sigor@sysoev.ru         ev->handler = nxt_cache_timeout_handler;
255*0Sigor@sysoev.ru         ev->data = q;
256*0Sigor@sysoev.ru         nxt_event_timer_ident(ev, -1);
257*0Sigor@sysoev.ru 
258*0Sigor@sysoev.ru         nxt_event_timer_add(thr->engine, ev, q->timeout);
259*0Sigor@sysoev.ru     }
260*0Sigor@sysoev.ru }
261*0Sigor@sysoev.ru 
262*0Sigor@sysoev.ru 
263*0Sigor@sysoev.ru static void
nxt_cache_timeout_handler(nxt_event_timer_t * ev)264*0Sigor@sysoev.ru nxt_cache_timeout_handler(nxt_event_timer_t *ev)
265*0Sigor@sysoev.ru {
266*0Sigor@sysoev.ru     nxt_cache_query_t  *q;
267*0Sigor@sysoev.ru 
268*0Sigor@sysoev.ru     q = ev->data;
269*0Sigor@sysoev.ru 
270*0Sigor@sysoev.ru     q->state->timeout_handler(q);
271*0Sigor@sysoev.ru }
272*0Sigor@sysoev.ru 
273*0Sigor@sysoev.ru 
274*0Sigor@sysoev.ru static void
nxt_cache_wake_handler(void * data)275*0Sigor@sysoev.ru nxt_cache_wake_handler(void *data)
276*0Sigor@sysoev.ru {
277*0Sigor@sysoev.ru     nxt_cache_t             *cache;
278*0Sigor@sysoev.ru     nxt_work_handler_t      handler;
279*0Sigor@sysoev.ru     nxt_cache_query_t       *q;
280*0Sigor@sysoev.ru     nxt_cache_query_wait_t  *qw;
281*0Sigor@sysoev.ru 
282*0Sigor@sysoev.ru     qw = data;
283*0Sigor@sysoev.ru     q = qw->query;
284*0Sigor@sysoev.ru     cache = qw->cache;
285*0Sigor@sysoev.ru 
286*0Sigor@sysoev.ru     nxt_cache_lock(cache);
287*0Sigor@sysoev.ru 
288*0Sigor@sysoev.ru     handler = nxt_cache_node_test(cache, q);
289*0Sigor@sysoev.ru 
290*0Sigor@sysoev.ru     if (handler == NULL) {
291*0Sigor@sysoev.ru         /* Wait again. */
292*0Sigor@sysoev.ru         qw->next = q->node->waiting;
293*0Sigor@sysoev.ru         q->node->waiting = qw;
294*0Sigor@sysoev.ru     }
295*0Sigor@sysoev.ru 
296*0Sigor@sysoev.ru     nxt_cache_unlock(cache);
297*0Sigor@sysoev.ru 
298*0Sigor@sysoev.ru     if (handler != NULL) {
299*0Sigor@sysoev.ru         nxt_cache_query_wait_free(cache, qw);
300*0Sigor@sysoev.ru     }
301*0Sigor@sysoev.ru 
302*0Sigor@sysoev.ru     handler(q);
303*0Sigor@sysoev.ru }
304*0Sigor@sysoev.ru 
305*0Sigor@sysoev.ru 
306*0Sigor@sysoev.ru static nxt_cache_node_t *
nxt_cache_node_alloc(nxt_cache_t * cache)307*0Sigor@sysoev.ru nxt_cache_node_alloc(nxt_cache_t *cache)
308*0Sigor@sysoev.ru {
309*0Sigor@sysoev.ru     nxt_queue_node_t  *qn;
310*0Sigor@sysoev.ru     nxt_cache_node_t  *node;
311*0Sigor@sysoev.ru 
312*0Sigor@sysoev.ru     qn = nxt_queue_first(&cache->free_nodes);
313*0Sigor@sysoev.ru 
314*0Sigor@sysoev.ru     if (nxt_fast_path(qn != nxt_queue_tail(&cache->free_nodes))) {
315*0Sigor@sysoev.ru         cache->nfree_nodes--;
316*0Sigor@sysoev.ru         nxt_queue_remove(qn);
317*0Sigor@sysoev.ru 
318*0Sigor@sysoev.ru         node = nxt_queue_node_data(qn, nxt_cache_node_t, queue);
319*0Sigor@sysoev.ru         nxt_memzero(node, sizeof(nxt_cache_node_t));
320*0Sigor@sysoev.ru 
321*0Sigor@sysoev.ru         return node;
322*0Sigor@sysoev.ru     }
323*0Sigor@sysoev.ru 
324*0Sigor@sysoev.ru     nxt_cache_unlock(cache);
325*0Sigor@sysoev.ru 
326*0Sigor@sysoev.ru     node = cache->alloc(cache->data, sizeof(nxt_cache_node_t));
327*0Sigor@sysoev.ru 
328*0Sigor@sysoev.ru     nxt_cache_lock(cache);
329*0Sigor@sysoev.ru 
330*0Sigor@sysoev.ru     return node;
331*0Sigor@sysoev.ru }
332*0Sigor@sysoev.ru 
333*0Sigor@sysoev.ru 
334*0Sigor@sysoev.ru static void
nxt_cache_node_free(nxt_cache_t * cache,nxt_cache_node_t * node,nxt_bool_t fast)335*0Sigor@sysoev.ru nxt_cache_node_free(nxt_cache_t *cache, nxt_cache_node_t *node, nxt_bool_t fast)
336*0Sigor@sysoev.ru {
337*0Sigor@sysoev.ru     if (fast || cache->nfree_nodes < 32) {
338*0Sigor@sysoev.ru         nxt_queue_insert_head(&cache->free_nodes, &node->queue);
339*0Sigor@sysoev.ru         cache->nfree_nodes++;
340*0Sigor@sysoev.ru         return;
341*0Sigor@sysoev.ru     }
342*0Sigor@sysoev.ru 
343*0Sigor@sysoev.ru     nxt_cache_unlock(cache);
344*0Sigor@sysoev.ru 
345*0Sigor@sysoev.ru     cache->free(cache->data, node);
346*0Sigor@sysoev.ru 
347*0Sigor@sysoev.ru     nxt_cache_lock(cache);
348*0Sigor@sysoev.ru }
349*0Sigor@sysoev.ru 
350*0Sigor@sysoev.ru 
351*0Sigor@sysoev.ru static nxt_cache_query_wait_t *
nxt_cache_query_wait_alloc(nxt_cache_t * cache,nxt_bool_t * fast)352*0Sigor@sysoev.ru nxt_cache_query_wait_alloc(nxt_cache_t *cache, nxt_bool_t *fast)
353*0Sigor@sysoev.ru {
354*0Sigor@sysoev.ru     nxt_cache_query_wait_t  *qw;
355*0Sigor@sysoev.ru 
356*0Sigor@sysoev.ru     qw = cache->free_query_wait;
357*0Sigor@sysoev.ru 
358*0Sigor@sysoev.ru     if (nxt_fast_path(qw != NULL)) {
359*0Sigor@sysoev.ru         cache->free_query_wait = qw->next;
360*0Sigor@sysoev.ru         cache->nfree_query_wait--;
361*0Sigor@sysoev.ru 
362*0Sigor@sysoev.ru         *fast = 1;
363*0Sigor@sysoev.ru         return qw;
364*0Sigor@sysoev.ru     }
365*0Sigor@sysoev.ru 
366*0Sigor@sysoev.ru     nxt_cache_unlock(cache);
367*0Sigor@sysoev.ru 
368*0Sigor@sysoev.ru     qw = cache->alloc(cache->data, sizeof(nxt_cache_query_wait_t));
369*0Sigor@sysoev.ru     *fast = 0;
370*0Sigor@sysoev.ru 
371*0Sigor@sysoev.ru     nxt_cache_lock(cache);
372*0Sigor@sysoev.ru 
373*0Sigor@sysoev.ru     return qw;
374*0Sigor@sysoev.ru }
375*0Sigor@sysoev.ru 
376*0Sigor@sysoev.ru 
377*0Sigor@sysoev.ru static void
nxt_cache_query_wait_free(nxt_cache_t * cache,nxt_cache_query_wait_t * qw)378*0Sigor@sysoev.ru nxt_cache_query_wait_free(nxt_cache_t *cache, nxt_cache_query_wait_t *qw)
379*0Sigor@sysoev.ru {
380*0Sigor@sysoev.ru     if (cache->nfree_query_wait < 32) {
381*0Sigor@sysoev.ru         qw->next = cache->free_query_wait;
382*0Sigor@sysoev.ru         cache->free_query_wait = qw;
383*0Sigor@sysoev.ru         cache->nfree_query_wait++;
384*0Sigor@sysoev.ru         return;
385*0Sigor@sysoev.ru     }
386*0Sigor@sysoev.ru 
387*0Sigor@sysoev.ru     nxt_cache_unlock(cache);
388*0Sigor@sysoev.ru 
389*0Sigor@sysoev.ru     cache->free(cache->data, qw);
390*0Sigor@sysoev.ru 
391*0Sigor@sysoev.ru     nxt_cache_lock(cache);
392*0Sigor@sysoev.ru }
393*0Sigor@sysoev.ru 
394*0Sigor@sysoev.ru 
395*0Sigor@sysoev.ru #if 0
396*0Sigor@sysoev.ru 
397*0Sigor@sysoev.ru nxt_int_t
398*0Sigor@sysoev.ru nxt_cache_update(nxt_cache_t *cache, nxt_cache_node_t *node)
399*0Sigor@sysoev.ru {
400*0Sigor@sysoev.ru     nxt_lvlhsh_key_t  hkey;
401*0Sigor@sysoev.ru 
402*0Sigor@sysoev.ru     if (node->expiry == 0) {
403*0Sigor@sysoev.ru         /* An empty sentinel node. */
404*0Sigor@sysoev.ru         nxt_cache_release(cache, node);
405*0Sigor@sysoev.ru         return;
406*0Sigor@sysoev.ru     }
407*0Sigor@sysoev.ru 
408*0Sigor@sysoev.ru     hkey.key.len = node->key_len;
409*0Sigor@sysoev.ru     hkey.key.data = node->key_data;
410*0Sigor@sysoev.ru     hkey.key_hash = nxt_murmur_hash2(node->key_data, node->key_len);
411*0Sigor@sysoev.ru     hkey.replace = 1;
412*0Sigor@sysoev.ru     hkey.value = node;
413*0Sigor@sysoev.ru 
414*0Sigor@sysoev.ru     node->count = 1;
415*0Sigor@sysoev.ru 
416*0Sigor@sysoev.ru     if (nxt_lvlhsh_insert(&cache->lvlhsh, &hkey) != NXT_OK) {
417*0Sigor@sysoev.ru         return NXT_ERROR;
418*0Sigor@sysoev.ru     }
419*0Sigor@sysoev.ru 
420*0Sigor@sysoev.ru     node = hkey.value;
421*0Sigor@sysoev.ru 
422*0Sigor@sysoev.ru     if (node != NULL) {
423*0Sigor@sysoev.ru         if (node->count != 0) {
424*0Sigor@sysoev.ru             node->delete = 1;
425*0Sigor@sysoev.ru 
426*0Sigor@sysoev.ru         } else {
427*0Sigor@sysoev.ru             // delete cache node
428*0Sigor@sysoev.ru         }
429*0Sigor@sysoev.ru     }
430*0Sigor@sysoev.ru 
431*0Sigor@sysoev.ru     return NXT_OK;
432*0Sigor@sysoev.ru }
433*0Sigor@sysoev.ru 
434*0Sigor@sysoev.ru #endif
435*0Sigor@sysoev.ru 
436*0Sigor@sysoev.ru 
437*0Sigor@sysoev.ru void
nxt_cache_node_release(nxt_cache_t * cache,nxt_cache_node_t * node)438*0Sigor@sysoev.ru nxt_cache_node_release(nxt_cache_t *cache, nxt_cache_node_t *node)
439*0Sigor@sysoev.ru {
440*0Sigor@sysoev.ru     nxt_bool_t  delete;
441*0Sigor@sysoev.ru 
442*0Sigor@sysoev.ru     nxt_cache_lock(cache);
443*0Sigor@sysoev.ru 
444*0Sigor@sysoev.ru     delete = nxt_cache_node_release_locked(cache, node);
445*0Sigor@sysoev.ru 
446*0Sigor@sysoev.ru     nxt_cache_unlock(cache);
447*0Sigor@sysoev.ru 
448*0Sigor@sysoev.ru     if (delete) {
449*0Sigor@sysoev.ru         nxt_thread_work_queue_add(cache->delete_handler, node);
450*0Sigor@sysoev.ru     }
451*0Sigor@sysoev.ru }
452*0Sigor@sysoev.ru 
453*0Sigor@sysoev.ru 
454*0Sigor@sysoev.ru nxt_bool_t
nxt_cache_node_release_locked(nxt_cache_t * cache,nxt_cache_node_t * node)455*0Sigor@sysoev.ru nxt_cache_node_release_locked(nxt_cache_t *cache, nxt_cache_node_t *node)
456*0Sigor@sysoev.ru {
457*0Sigor@sysoev.ru #if 0
458*0Sigor@sysoev.ru     nxt_lvlhsh_key_t  hkey;
459*0Sigor@sysoev.ru #endif
460*0Sigor@sysoev.ru 
461*0Sigor@sysoev.ru     node->count--;
462*0Sigor@sysoev.ru 
463*0Sigor@sysoev.ru     if (node->count != 0) {
464*0Sigor@sysoev.ru         return 0;
465*0Sigor@sysoev.ru     }
466*0Sigor@sysoev.ru 
467*0Sigor@sysoev.ru     if (!node->deleted) {
468*0Sigor@sysoev.ru         /*
469*0Sigor@sysoev.ru          * A cache node is locked whilst its count is non zero.
470*0Sigor@sysoev.ru          * To minimize number of operations the node's place in expiry
471*0Sigor@sysoev.ru          * queue can be updated only if the node is not currently used.
472*0Sigor@sysoev.ru          */
473*0Sigor@sysoev.ru         node->accessed = nxt_thread_time() - cache->start_time;
474*0Sigor@sysoev.ru 
475*0Sigor@sysoev.ru         nxt_queue_remove(&node->queue);
476*0Sigor@sysoev.ru         nxt_queue_insert_head(&cache->expiry_queue, &node->queue);
477*0Sigor@sysoev.ru 
478*0Sigor@sysoev.ru         return 0;
479*0Sigor@sysoev.ru     }
480*0Sigor@sysoev.ru 
481*0Sigor@sysoev.ru #if 0
482*0Sigor@sysoev.ru     hkey.key.len = node->key_len;
483*0Sigor@sysoev.ru     hkey.key.data = node->key_data;
484*0Sigor@sysoev.ru     hkey.key_hash = nxt_murmur_hash2(node->key_data, node->key_len);
485*0Sigor@sysoev.ru 
486*0Sigor@sysoev.ru     nxt_lvlhsh_delete(&cache->lvlhsh, &hkey);
487*0Sigor@sysoev.ru #endif
488*0Sigor@sysoev.ru 
489*0Sigor@sysoev.ru     return 1;
490*0Sigor@sysoev.ru }
491*0Sigor@sysoev.ru 
492*0Sigor@sysoev.ru 
493*0Sigor@sysoev.ru static void
nxt_file_cache_lock(nxt_file_cache_t * cache)494*0Sigor@sysoev.ru nxt_file_cache_lock(nxt_file_cache_t *cache)
495*0Sigor@sysoev.ru {
496*0Sigor@sysoev.ru     if (cache->shared) {
497*0Sigor@sysoev.ru         nxt_thread_spin_lock(&cache->lock);
498*0Sigor@sysoev.ru     }
499*0Sigor@sysoev.ru }
500*0Sigor@sysoev.ru 
501*0Sigor@sysoev.ru 
502*0Sigor@sysoev.ru static void
nxt_file_cache_unlock(nxt_file_cache_t * cache)503*0Sigor@sysoev.ru nxt_file_cache_unlock(nxt_file_cache_t *cache)
504*0Sigor@sysoev.ru {
505*0Sigor@sysoev.ru     if (cache->shared) {
506*0Sigor@sysoev.ru         nxt_thread_spin_unlock(&cache->lock);
507*0Sigor@sysoev.ru     }
508*0Sigor@sysoev.ru }
509