|
diff --git a/cache.c b/cache.c index a996109..aa97ae1 100644 --- a/ cache.c+++ b/ cache.c |
|
@@ -231,86 +231,96 @@ static int process_slot(struct cache_slot *slot) |
231 | * serve the stale content from the original |
231 | * serve the stale content from the original |
232 | * cachefile. This way we avoid pruning the |
232 | * cachefile. This way we avoid pruning the |
233 | * newly generated slot. The same code-path |
233 | * newly generated slot. The same code-path |
234 | * is chosen if fill_slot() fails for some |
234 | * is chosen if fill_slot() fails for some |
235 | * reason. |
235 | * reason. |
236 | * |
236 | * |
237 | * TODO? check if the new slot contains the |
237 | * TODO? check if the new slot contains the |
238 | * same key as the old one, since we would |
238 | * same key as the old one, since we would |
239 | * prefer to serve the newest content. |
239 | * prefer to serve the newest content. |
240 | * This will require us to open yet another |
240 | * This will require us to open yet another |
241 | * file-descriptor and read and compare the |
241 | * file-descriptor and read and compare the |
242 | * key from the new file, so for now we're |
242 | * key from the new file, so for now we're |
243 | * lazy and just ignore the new file. |
243 | * lazy and just ignore the new file. |
244 | */ |
244 | */ |
245 | if (is_modified(slot) || fill_slot(slot)) { |
245 | if (is_modified(slot) || fill_slot(slot)) { |
246 | unlock_slot(slot, 0); |
246 | unlock_slot(slot, 0); |
247 | close_lock(slot); |
247 | close_lock(slot); |
248 | } else { |
248 | } else { |
249 | close_slot(slot); |
249 | close_slot(slot); |
250 | unlock_slot(slot, 1); |
250 | unlock_slot(slot, 1); |
251 | slot->cache_fd = slot->lock_fd; |
251 | slot->cache_fd = slot->lock_fd; |
252 | } |
252 | } |
253 | } |
253 | } |
254 | } |
254 | } |
255 | print_slot(slot); |
255 | if ((err = print_slot(slot)) != 0) { |
| |
256 | cache_log("[cgit] error printing cache %s: %s (%d)\n", |
| |
257 | slot->cache_name, |
| |
258 | strerror(err), |
| |
259 | err); |
| |
260 | } |
256 | close_slot(slot); |
261 | close_slot(slot); |
257 | return 0; |
262 | return err; |
258 | } |
263 | } |
259 | |
264 | |
260 | /* If the cache slot does not exist (or its key doesn't match the |
265 | /* If the cache slot does not exist (or its key doesn't match the |
261 | * current key), lets try to create a new cache slot for this |
266 | * current key), lets try to create a new cache slot for this |
262 | * request. If this fails (for whatever reason), lets just generate |
267 | * request. If this fails (for whatever reason), lets just generate |
263 | * the content without caching it and fool the caller to belive |
268 | * the content without caching it and fool the caller to belive |
264 | * everything worked out (but print a warning on stdout). |
269 | * everything worked out (but print a warning on stdout). |
265 | */ |
270 | */ |
266 | |
271 | |
267 | close_slot(slot); |
272 | close_slot(slot); |
268 | if ((err = lock_slot(slot)) != 0) { |
273 | if ((err = lock_slot(slot)) != 0) { |
269 | cache_log("[cgit] Unable to lock slot %s: %s (%d)\n", |
274 | cache_log("[cgit] Unable to lock slot %s: %s (%d)\n", |
270 | slot->lock_name, strerror(err), err); |
275 | slot->lock_name, strerror(err), err); |
271 | slot->fn(slot->cbdata); |
276 | slot->fn(slot->cbdata); |
272 | return 0; |
277 | return 0; |
273 | } |
278 | } |
274 | |
279 | |
275 | if ((err = fill_slot(slot)) != 0) { |
280 | if ((err = fill_slot(slot)) != 0) { |
276 | cache_log("[cgit] Unable to fill slot %s: %s (%d)\n", |
281 | cache_log("[cgit] Unable to fill slot %s: %s (%d)\n", |
277 | slot->lock_name, strerror(err), err); |
282 | slot->lock_name, strerror(err), err); |
278 | unlock_slot(slot, 0); |
283 | unlock_slot(slot, 0); |
279 | close_lock(slot); |
284 | close_lock(slot); |
280 | slot->fn(slot->cbdata); |
285 | slot->fn(slot->cbdata); |
281 | return 0; |
286 | return 0; |
282 | } |
287 | } |
283 | // We've got a valid cache slot in the lock file, which |
288 | // We've got a valid cache slot in the lock file, which |
284 | // is about to replace the old cache slot. But if we |
289 | // is about to replace the old cache slot. But if we |
285 | // release the lockfile and then try to open the new cache |
290 | // release the lockfile and then try to open the new cache |
286 | // slot, we might get a race condition with a concurrent |
291 | // slot, we might get a race condition with a concurrent |
287 | // writer for the same cache slot (with a different key). |
292 | // writer for the same cache slot (with a different key). |
288 | // Lets avoid such a race by just printing the content of |
293 | // Lets avoid such a race by just printing the content of |
289 | // the lock file. |
294 | // the lock file. |
290 | slot->cache_fd = slot->lock_fd; |
295 | slot->cache_fd = slot->lock_fd; |
291 | unlock_slot(slot, 1); |
296 | unlock_slot(slot, 1); |
292 | err = print_slot(slot); |
297 | if ((err = print_slot(slot)) != 0) { |
| |
298 | cache_log("[cgit] error printing cache %s: %s (%d)\n", |
| |
299 | slot->cache_name, |
| |
300 | strerror(err), |
| |
301 | err); |
| |
302 | } |
293 | close_slot(slot); |
303 | close_slot(slot); |
294 | return err; |
304 | return err; |
295 | } |
305 | } |
296 | |
306 | |
297 | /* Print cached content to stdout, generate the content if necessary. */ |
307 | /* Print cached content to stdout, generate the content if necessary. */ |
298 | int cache_process(int size, const char *path, const char *key, int ttl, |
308 | int cache_process(int size, const char *path, const char *key, int ttl, |
299 | cache_fill_fn fn, void *cbdata) |
309 | cache_fill_fn fn, void *cbdata) |
300 | { |
310 | { |
301 | unsigned long hash; |
311 | unsigned long hash; |
302 | int len, i; |
312 | int len, i; |
303 | char filename[1024]; |
313 | char filename[1024]; |
304 | char lockname[1024 + 5]; /* 5 = ".lock" */ |
314 | char lockname[1024 + 5]; /* 5 = ".lock" */ |
305 | struct cache_slot slot; |
315 | struct cache_slot slot; |
306 | |
316 | |
307 | /* If the cache is disabled, just generate the content */ |
317 | /* If the cache is disabled, just generate the content */ |
308 | if (size <= 0) { |
318 | if (size <= 0) { |
309 | fn(cbdata); |
319 | fn(cbdata); |
310 | return 0; |
320 | return 0; |
311 | } |
321 | } |
312 | |
322 | |
313 | /* Verify input, calculate filenames */ |
323 | /* Verify input, calculate filenames */ |
314 | if (!path) { |
324 | if (!path) { |
315 | cache_log("[cgit] Cache path not specified, caching is disabled\n"); |
325 | cache_log("[cgit] Cache path not specified, caching is disabled\n"); |
316 | fn(cbdata); |
326 | fn(cbdata); |
|
|
diff --git a/cgit.c b/cgit.c index 2036ceb..ac882c3 100644 --- a/ cgit.c+++ b/ cgit.c |
|
@@ -359,28 +359,28 @@ int main(int argc, const char **argv) |
359 | int err, ttl; |
359 | int err, ttl; |
360 | |
360 | |
361 | prepare_context(&ctx); |
361 | prepare_context(&ctx); |
362 | cgit_repolist.length = 0; |
362 | cgit_repolist.length = 0; |
363 | cgit_repolist.count = 0; |
363 | cgit_repolist.count = 0; |
364 | cgit_repolist.repos = NULL; |
364 | cgit_repolist.repos = NULL; |
365 | |
365 | |
366 | parse_configfile(cgit_config_env ? cgit_config_env : CGIT_CONFIG, |
366 | parse_configfile(cgit_config_env ? cgit_config_env : CGIT_CONFIG, |
367 | config_cb); |
367 | config_cb); |
368 | ctx.repo = NULL; |
368 | ctx.repo = NULL; |
369 | if (getenv("SCRIPT_NAME")) |
369 | if (getenv("SCRIPT_NAME")) |
370 | ctx.cfg.script_name = xstrdup(getenv("SCRIPT_NAME")); |
370 | ctx.cfg.script_name = xstrdup(getenv("SCRIPT_NAME")); |
371 | if (getenv("QUERY_STRING")) |
371 | if (getenv("QUERY_STRING")) |
372 | ctx.qry.raw = xstrdup(getenv("QUERY_STRING")); |
372 | ctx.qry.raw = xstrdup(getenv("QUERY_STRING")); |
373 | cgit_parse_args(argc, argv); |
373 | cgit_parse_args(argc, argv); |
374 | http_parse_querystring(ctx.qry.raw, querystring_cb); |
374 | http_parse_querystring(ctx.qry.raw, querystring_cb); |
375 | |
375 | |
376 | ttl = calc_ttl(); |
376 | ttl = calc_ttl(); |
377 | ctx.page.expires += ttl*60; |
377 | ctx.page.expires += ttl*60; |
378 | if (ctx.cfg.nocache) |
378 | if (ctx.cfg.nocache) |
379 | ctx.cfg.cache_size = 0; |
379 | ctx.cfg.cache_size = 0; |
380 | err = cache_process(ctx.cfg.cache_size, ctx.cfg.cache_root, |
380 | err = cache_process(ctx.cfg.cache_size, ctx.cfg.cache_root, |
381 | ctx.qry.raw, ttl, process_request, &ctx); |
381 | ctx.qry.raw, ttl, process_request, &ctx); |
382 | if (err) |
382 | if (err) |
383 | cache_log("[cgit] error %d - %s\n", |
383 | cgit_print_error(fmt("Error processing page: %s (%d)", |
384 | err, strerror(err)); |
384 | strerror(err), err)); |
385 | return err; |
385 | return err; |
386 | } |
386 | } |
|