Mercurial > hg > nginx
comparison src/http/ngx_http_cache.c @ 195:8dee38ea9117
nginx-0.0.1-2003-11-25-23:44:56 import
author | Igor Sysoev <igor@sysoev.ru> |
---|---|
date | Tue, 25 Nov 2003 20:44:56 +0000 |
parents | 71ce40b3c37b |
children | 0b81c7a0b133 |
comparison
equal
deleted
inserted
replaced
194:2357fa41738a | 195:8dee38ea9117 |
---|---|
11 #define MD5Update MD5_Update | 11 #define MD5Update MD5_Update |
12 #define MD5Final MD5_Final | 12 #define MD5Final MD5_Final |
13 #endif | 13 #endif |
14 | 14 |
15 | 15 |
16 static int ngx_crc(char *data, size_t len); | |
17 | |
18 static void *ngx_http_cache_create_conf(ngx_conf_t *cf); | |
19 static char *ngx_http_core_merge_loc_conf(ngx_conf_t *cf, | |
20 void *parent, void *child); | |
21 | |
22 | |
23 static ngx_http_module_t ngx_http_cache_module_ctx = { | |
24 NULL, /* pre conf */ | |
25 | |
26 NULL, /* create main configuration */ | |
27 NULL, /* init main configuration */ | |
28 | |
29 NULL, /* create server configuration */ | |
30 NULL, /* merge server configuration */ | |
31 | |
32 ngx_http_cache_create_conf, /* create location configuration */ | |
33 ngx_http_core_merge_loc_conf /* merge location configuration */ | |
34 }; | |
35 | |
36 | |
37 ngx_module_t ngx_http_cache_module = { | |
38 NGX_MODULE, | |
39 &ngx_http_cache_module_ctx, /* module context */ | |
40 NULL, /* module directives */ | |
41 NGX_HTTP_MODULE, /* module type */ | |
42 NULL, /* init module */ | |
43 NULL /* init child */ | |
44 }; | |
45 | |
46 | |
47 | |
16 int ngx_http_cache_get_file(ngx_http_request_t *r, ngx_http_cache_ctx_t *ctx) | 48 int ngx_http_cache_get_file(ngx_http_request_t *r, ngx_http_cache_ctx_t *ctx) |
17 { | 49 { |
18 MD5_CTX md5; | 50 MD5_CTX md5; |
19 | 51 |
20 ctx->header_size = sizeof(ngx_http_cache_header_t) + ctx->key.len + 1; | 52 /* we use offsetof() because sizeof() pads struct size to int size */ |
53 ctx->header_size = offsetof(ngx_http_cache_header_t, key) | |
54 + ctx->key.len + 1; | |
21 | 55 |
22 ctx->file.name.len = ctx->path->name.len + 1 + ctx->path->len + 32; | 56 ctx->file.name.len = ctx->path->name.len + 1 + ctx->path->len + 32; |
23 if (!(ctx->file.name.data = ngx_palloc(r->pool, ctx->file.name.len + 1))) { | 57 if (!(ctx->file.name.data = ngx_palloc(r->pool, ctx->file.name.len + 1))) { |
24 return NGX_ERROR; | 58 return NGX_ERROR; |
25 } | 59 } |
44 | 78 |
45 return ngx_http_cache_open_file(ctx, 0); | 79 return ngx_http_cache_open_file(ctx, 0); |
46 } | 80 } |
47 | 81 |
48 | 82 |
49 /* TODO: Win32 inode analogy */ | 83 int ngx_http_cache_get_data(ngx_http_request_t *r, ngx_http_cache_ctx_t *ctx) |
84 { | |
85 ngx_uint_t n, i; | |
86 | |
87 ctx->crc = ngx_crc(ctx->key.data, ctx->key.len); | |
88 | |
89 n = ctx->crc % ctx->hash->hash; | |
90 for (i = 0; i < ctx->hash->nelts; i++) { | |
91 if (ctx->hash->cache[n][i].crc == ctx->crc | |
92 && ctx->hash->cache[n][i].key.len == ctx->key.len | |
93 && ngx_rstrncmp(ctx->hash->cache[n][i].key.data, ctx->key.data, | |
94 ctx->key.len) == 0) | |
95 { | |
96 ctx->cache = ctx->hash->cache[n][i].data; | |
97 ctx->hash->cache[n][i].refs++; | |
98 return NGX_OK; | |
99 } | |
100 } | |
101 | |
102 return NGX_DECLINED; | |
103 } | |
104 | |
105 | |
106 ngx_http_cache_entry_t *ngx_http_cache_get_entry(ngx_http_request_t *r, | |
107 ngx_http_cache_ctx_t *ctx) | |
108 { | |
109 time_t old; | |
110 ngx_uint_t n, i; | |
111 ngx_http_cache_entry_t *ce; | |
112 | |
113 old = ngx_time() + 1; | |
114 ce = NULL; | |
115 | |
116 n = ctx->crc % ctx->hash->hash; | |
117 for (i = 0; i < ctx->hash->nelts; i++) { | |
118 if (ctx->hash->cache[n][i].key.data == NULL) { | |
119 | |
120 /* a free entry is found */ | |
121 | |
122 ce = &ctx->hash->cache[n][i]; | |
123 break; | |
124 } | |
125 | |
126 if (ctx->hash->cache[n][i].refs == 0 | |
127 && old > ctx->hash->cache[n][i].accessed) | |
128 { | |
129 /* looking for the oldest cache entry that is not used right now */ | |
130 | |
131 old = ctx->hash->cache[n][i].accessed; | |
132 ce = &ctx->hash->cache[n][i]; | |
133 } | |
134 } | |
135 | |
136 if (ce) { | |
137 if (ce->key.data) { | |
138 if (ctx->key.len > ce->key.len) { | |
139 ngx_free(ce->key.data); | |
140 ce->key.data = NULL; | |
141 } | |
142 } | |
143 | |
144 if (ce->key.data) { | |
145 ce->key.data = ngx_alloc(ctx->key.len, r->connection->log); | |
146 if (ce->key.data == NULL) { | |
147 return NULL; | |
148 } | |
149 } | |
150 | |
151 ngx_memcpy(ce->key.data, ctx->key.data, ctx->key.len); | |
152 | |
153 ce->key.len = ctx->key.len; | |
154 ce->crc = ctx->crc; | |
155 } | |
156 | |
157 return ce; | |
158 } | |
159 | |
50 | 160 |
51 int ngx_http_cache_open_file(ngx_http_cache_ctx_t *ctx, ngx_file_uniq_t uniq) | 161 int ngx_http_cache_open_file(ngx_http_cache_ctx_t *ctx, ngx_file_uniq_t uniq) |
52 { | 162 { |
53 ssize_t n; | 163 ssize_t n; |
54 ngx_err_t err; | 164 ngx_err_t err; |
136 | 246 |
137 return NGX_OK; | 247 return NGX_OK; |
138 } | 248 } |
139 | 249 |
140 | 250 |
141 int ngx_garbage_collector_http_cache_handler(ngx_gc_t *gc, ngx_str_t *name, | |
142 ngx_dir_t *dir) | |
143 { | |
144 int rc; | |
145 char data[sizeof(ngx_http_cache_header_t)]; | |
146 ngx_hunk_t buf; | |
147 ngx_http_cache_ctx_t ctx; | |
148 | |
149 ctx.file.fd = NGX_INVALID_FILE; | |
150 ctx.file.name = *name; | |
151 ctx.file.log = gc->log; | |
152 | |
153 ctx.header_size = sizeof(ngx_http_cache_header_t); | |
154 ctx.buf = &buf; | |
155 ctx.log = gc->log; | |
156 ctx.key.len = 0; | |
157 | |
158 buf.type = NGX_HUNK_IN_MEMORY|NGX_HUNK_TEMP; | |
159 buf.pos = data; | |
160 buf.last = data; | |
161 buf.start = data; | |
162 buf.end = data + sizeof(ngx_http_cache_header_t); | |
163 | |
164 rc = ngx_http_cache_open_file(&ctx, 0); | |
165 | |
166 /* TODO: NGX_AGAIN */ | |
167 | |
168 if (rc != NGX_ERROR && rc != NGX_DECLINED && rc != NGX_HTTP_CACHE_STALE) { | |
169 return NGX_OK; | |
170 } | |
171 | |
172 if (ngx_delete_file(name->data) == NGX_FILE_ERROR) { | |
173 ngx_log_error(NGX_LOG_CRIT, gc->log, ngx_errno, | |
174 ngx_delete_file_n " \"%s\" failed", name->data); | |
175 return NGX_ERROR; | |
176 } | |
177 | |
178 gc->deleted++; | |
179 gc->freed += ngx_de_size(dir); | |
180 | |
181 return NGX_OK; | |
182 } | |
183 | |
184 | |
185 int ngx_http_cache_update_file(ngx_http_request_t *r, ngx_http_cache_ctx_t *ctx, | 251 int ngx_http_cache_update_file(ngx_http_request_t *r, ngx_http_cache_ctx_t *ctx, |
186 ngx_str_t *temp_file) | 252 ngx_str_t *temp_file) |
187 { | 253 { |
188 int retry; | 254 int retry; |
189 ngx_err_t err; | 255 ngx_err_t err; |
219 return NGX_ERROR; | 285 return NGX_ERROR; |
220 } | 286 } |
221 | 287 |
222 retry = 1; | 288 retry = 1; |
223 } | 289 } |
290 } | |
291 | |
292 | |
293 int ngx_garbage_collector_http_cache_handler(ngx_gc_t *gc, ngx_str_t *name, | |
294 ngx_dir_t *dir) | |
295 { | |
296 int rc; | |
297 char data[sizeof(ngx_http_cache_header_t)]; | |
298 ngx_hunk_t buf; | |
299 ngx_http_cache_ctx_t ctx; | |
300 | |
301 ctx.file.fd = NGX_INVALID_FILE; | |
302 ctx.file.name = *name; | |
303 ctx.file.log = gc->log; | |
304 | |
305 ctx.header_size = sizeof(ngx_http_cache_header_t); | |
306 ctx.buf = &buf; | |
307 ctx.log = gc->log; | |
308 ctx.key.len = 0; | |
309 | |
310 buf.type = NGX_HUNK_IN_MEMORY|NGX_HUNK_TEMP; | |
311 buf.pos = data; | |
312 buf.last = data; | |
313 buf.start = data; | |
314 buf.end = data + sizeof(ngx_http_cache_header_t); | |
315 | |
316 rc = ngx_http_cache_open_file(&ctx, 0); | |
317 | |
318 /* TODO: NGX_AGAIN */ | |
319 | |
320 if (rc != NGX_ERROR && rc != NGX_DECLINED && rc != NGX_HTTP_CACHE_STALE) { | |
321 return NGX_OK; | |
322 } | |
323 | |
324 if (ngx_delete_file(name->data) == NGX_FILE_ERROR) { | |
325 ngx_log_error(NGX_LOG_CRIT, gc->log, ngx_errno, | |
326 ngx_delete_file_n " \"%s\" failed", name->data); | |
327 return NGX_ERROR; | |
328 } | |
329 | |
330 gc->deleted++; | |
331 gc->freed += ngx_de_size(dir); | |
332 | |
333 return NGX_OK; | |
334 } | |
335 | |
336 | |
337 /* 32-bit crc16 */ | |
338 | |
339 static int ngx_crc(char *data, size_t len) | |
340 { | |
341 uint32_t sum; | |
342 | |
343 for (sum = 0; len; len--) { | |
344 /* | |
345 * gcc 2.95.2 x86 and icc 7.1.006 compile that operator | |
346 * into the single rol opcode. | |
347 * msvc 6.0sp2 compiles it into four opcodes. | |
348 */ | |
349 sum = sum >> 1 | sum << 31; | |
350 | |
351 sum += *data++; | |
352 } | |
353 | |
354 return sum; | |
355 } | |
356 | |
357 | |
358 static void *ngx_http_cache_create_conf(ngx_conf_t *cf) | |
359 { | |
360 ngx_http_cache_conf_t *conf; | |
361 | |
362 if (!(conf = ngx_pcalloc(cf->pool, sizeof(ngx_http_cache_conf_t)))) { | |
363 return NGX_CONF_ERROR; | |
364 } | |
365 | |
366 return conf; | |
367 } | |
368 | |
369 | |
370 static char *ngx_http_core_merge_loc_conf(ngx_conf_t *cf, | |
371 void *parent, void *child) | |
372 { | |
373 ngx_http_cache_conf_t *prev = parent; | |
374 ngx_http_cache_conf_t *conf = child; | |
375 | |
376 if (conf->hash == NULL) { | |
377 if (prev->hash) { | |
378 conf->hash = prev->hash; | |
379 | |
380 } else { | |
381 conf->hash = ngx_pcalloc(cf->pool, sizeof(ngx_http_cache_hash_t)); | |
382 if (conf->hash == NULL) { | |
383 return NGX_CONF_ERROR; | |
384 } | |
385 | |
386 conf->hash->hash = NGX_HTTP_CACHE_HASH; | |
387 conf->hash->nelts = NGX_HTTP_CACHE_NELTS; | |
388 | |
389 conf->hash->cache = ngx_pcalloc(cf->pool, | |
390 NGX_HTTP_CACHE_HASH | |
391 * NGX_HTTP_CACHE_NELTS | |
392 * sizeof(ngx_http_cache_entry_t)); | |
393 if (conf->hash->cache == NULL) { | |
394 return NGX_CONF_ERROR; | |
395 } | |
396 } | |
397 } | |
398 | |
399 return NGX_CONF_OK; | |
224 } | 400 } |
225 | 401 |
226 | 402 |
227 #if 0 | 403 #if 0 |
228 | 404 |
259 int flags; | 435 int flags; |
260 } ngx_http_cache_entry_t; | 436 } ngx_http_cache_entry_t; |
261 | 437 |
262 | 438 |
263 typedef struct { | 439 typedef struct { |
264 u_int32_t crc; | 440 uint32_t crc; |
265 ngx_str_t uri; | 441 ngx_str_t uri; |
266 ngx_http_cache_t *cache; | 442 ngx_http_cache_t *cache; |
267 } ngx_http_cache_hash_entry_t; | 443 } ngx_http_cache_hash_entry_t; |
268 | 444 |
269 | 445 |
270 typedef struct { | 446 typedef struct { |
271 ngx_http_cache_t *cache; | 447 ngx_http_cache_t *cache; |
272 u_int32_t crc; | 448 uint32_t crc; |
273 int n; | 449 int n; |
274 } ngx_http_cache_handle_t; | 450 } ngx_http_cache_handle_t; |
275 | 451 |
276 | 452 |
277 int ngx_http_cache_get(ngx_http_cache_hash_t *cache_hash, | 453 int ngx_http_cache_get(ngx_http_cache_hash_t *cache_hash, |
303 | 479 |
304 /* 32-bit crc16 */ | 480 /* 32-bit crc16 */ |
305 | 481 |
306 int ngx_crc(char *data, size_t len) | 482 int ngx_crc(char *data, size_t len) |
307 { | 483 { |
308 u_int32_t sum; | 484 uint32_t sum; |
309 | 485 |
310 for (sum = 0; len; len--) { | 486 for (sum = 0; len; len--) { |
311 /* | 487 /* |
312 * gcc 2.95.2 x86 and icc 7.1.006 compile that operator | 488 * gcc 2.95.2 x86 and icc 7.1.006 compile that operator |
313 * into the single rol opcode. | 489 * into the single rol opcode. |