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