diff options
| author | 2009-08-21 00:41:54 (JST) | |
|---|---|---|
| committer | 2009-08-24 17:22:57 (JST) | |
| commit | d746827ec43a6dd53bce56ee8d8100a03383329e (patch) | |
| tree | f7d9e273672b7d0cf6c97bb40f7573a5d2ae178d | |
| parent | 302a3efa261b1b6127b2a2189e25ab45019b1b54 (diff) | |
| download | cgit-d746827ec43a6dd53bce56ee8d8100a03383329e.zip cgit-d746827ec43a6dd53bce56ee8d8100a03383329e.tar.gz | |
cgit.c: add support for caching autodetected repositories
Signed-off-by: Lars Hjemli <hjemli@gmail.com>
| -rw-r--r-- | cgit.c | 75 | ||||
| -rw-r--r-- | cgit.h | 1 |
2 files changed, 75 insertions, 1 deletions
| @@ -40,6 +40,8 @@ struct cgit_filter *new_filter(const char *cmd, int extra_args) | |||
| 40 | return f; | 40 | return f; |
| 41 | } | 41 | } |
| 42 | 42 | ||
| 43 | static void process_cached_repolist(const char *path); | ||
| 44 | |||
| 43 | void config_cb(const char *name, const char *value) | 45 | void config_cb(const char *name, const char *value) |
| 44 | { | 46 | { |
| 45 | if (!strcmp(name, "root-title")) | 47 | if (!strcmp(name, "root-title")) |
| @@ -96,6 +98,8 @@ void config_cb(const char *name, const char *value) | |||
| 96 | ctx.cfg.cache_root_ttl = atoi(value); | 98 | ctx.cfg.cache_root_ttl = atoi(value); |
| 97 | else if (!strcmp(name, "cache-repo-ttl")) | 99 | else if (!strcmp(name, "cache-repo-ttl")) |
| 98 | ctx.cfg.cache_repo_ttl = atoi(value); | 100 | ctx.cfg.cache_repo_ttl = atoi(value); |
| 101 | else if (!strcmp(name, "cache-scanrc-ttl")) | ||
| 102 | ctx.cfg.cache_scanrc_ttl = atoi(value); | ||
| 99 | else if (!strcmp(name, "cache-static-ttl")) | 103 | else if (!strcmp(name, "cache-static-ttl")) |
| 100 | ctx.cfg.cache_static_ttl = atoi(value); | 104 | ctx.cfg.cache_static_ttl = atoi(value); |
| 101 | else if (!strcmp(name, "cache-dynamic-ttl")) | 105 | else if (!strcmp(name, "cache-dynamic-ttl")) |
| @@ -137,7 +141,10 @@ void config_cb(const char *name, const char *value) | |||
| 137 | else if (!strcmp(name, "repo.group")) | 141 | else if (!strcmp(name, "repo.group")) |
| 138 | ctx.cfg.repo_group = xstrdup(value); | 142 | ctx.cfg.repo_group = xstrdup(value); |
| 139 | else if (!strcmp(name, "repo.scan")) | 143 | else if (!strcmp(name, "repo.scan")) |
| 140 | scan_tree(value); | 144 | if (!ctx.cfg.nocache && ctx.cfg.cache_size) |
| 145 | process_cached_repolist(value); | ||
| 146 | else | ||
| 147 | scan_tree(value); | ||
| 141 | else if (!strcmp(name, "repo.url")) | 148 | else if (!strcmp(name, "repo.url")) |
| 142 | ctx.repo = cgit_add_repo(value); | 149 | ctx.repo = cgit_add_repo(value); |
| 143 | else if (!strcmp(name, "repo.name")) | 150 | else if (!strcmp(name, "repo.name")) |
| @@ -236,6 +243,7 @@ static void prepare_context(struct cgit_context *ctx) | |||
| 236 | ctx->cfg.cache_repo_ttl = 5; | 243 | ctx->cfg.cache_repo_ttl = 5; |
| 237 | ctx->cfg.cache_root = CGIT_CACHE_ROOT; | 244 | ctx->cfg.cache_root = CGIT_CACHE_ROOT; |
| 238 | ctx->cfg.cache_root_ttl = 5; | 245 | ctx->cfg.cache_root_ttl = 5; |
| 246 | ctx->cfg.cache_scanrc_ttl = 15; | ||
| 239 | ctx->cfg.cache_static_ttl = -1; | 247 | ctx->cfg.cache_static_ttl = -1; |
| 240 | ctx->cfg.css = "/cgit.css"; | 248 | ctx->cfg.css = "/cgit.css"; |
| 241 | ctx->cfg.logo = "/cgit.png"; | 249 | ctx->cfg.logo = "/cgit.png"; |
| @@ -438,6 +446,71 @@ void print_repolist(FILE *f, struct cgit_repolist *list, int start) | |||
| 438 | print_repo(f, &list->repos[i]); | 446 | print_repo(f, &list->repos[i]); |
| 439 | } | 447 | } |
| 440 | 448 | ||
| 449 | /* Scan 'path' for git repositories, save the resulting repolist in 'cached_rc' | ||
| 450 | * and return 0 on success. | ||
| 451 | */ | ||
| 452 | static int generate_cached_repolist(const char *path, const char *cached_rc) | ||
| 453 | { | ||
| 454 | char *locked_rc; | ||
| 455 | int idx; | ||
| 456 | FILE *f; | ||
| 457 | |||
| 458 | locked_rc = xstrdup(fmt("%s.lock", cached_rc)); | ||
| 459 | f = fopen(locked_rc, "wx"); | ||
| 460 | if (!f) { | ||
| 461 | /* Inform about the error unless the lockfile already existed, | ||
| 462 | * since that only means we've got concurrent requests. | ||
| 463 | */ | ||
| 464 | if (errno != EEXIST) | ||
| 465 | fprintf(stderr, "[cgit] Error opening %s: %s (%d)\n", | ||
| 466 | locked_rc, strerror(errno), errno); | ||
| 467 | return errno; | ||
| 468 | } | ||
| 469 | idx = cgit_repolist.count; | ||
| 470 | scan_tree(path); | ||
| 471 | print_repolist(f, &cgit_repolist, idx); | ||
| 472 | if (rename(locked_rc, cached_rc)) | ||
| 473 | fprintf(stderr, "[cgit] Error renaming %s to %s: %s (%d)\n", | ||
| 474 | locked_rc, cached_rc, strerror(errno), errno); | ||
| 475 | fclose(f); | ||
| 476 | return 0; | ||
| 477 | } | ||
| 478 | |||
| 479 | static void process_cached_repolist(const char *path) | ||
| 480 | { | ||
| 481 | struct stat st; | ||
| 482 | char *cached_rc; | ||
| 483 | time_t age; | ||
| 484 | |||
| 485 | cached_rc = xstrdup(fmt("%s/rc-%8x", ctx.cfg.cache_root, | ||
| 486 | hash_str(path))); | ||
| 487 | |||
| 488 | if (stat(cached_rc, &st)) { | ||
| 489 | /* Nothing is cached, we need to scan without forking. And | ||
| 490 | * if we fail to generate a cached repolist, we need to | ||
| 491 | * invoke scan_tree manually. | ||
| 492 | */ | ||
| 493 | if (generate_cached_repolist(path, cached_rc)) | ||
| 494 | scan_tree(path); | ||
| 495 | return; | ||
| 496 | } | ||
| 497 | |||
| 498 | parse_configfile(cached_rc, config_cb); | ||
| 499 | |||
| 500 | /* If the cached configfile hasn't expired, lets exit now */ | ||
| 501 | age = time(NULL) - st.st_mtime; | ||
| 502 | if (age <= (ctx.cfg.cache_scanrc_ttl * 60)) | ||
| 503 | return; | ||
| 504 | |||
| 505 | /* The cached repolist has been parsed, but it was old. So lets | ||
| 506 | * rescan the specified path and generate a new cached repolist | ||
| 507 | * in a child-process to avoid latency for the current request. | ||
| 508 | */ | ||
| 509 | if (fork()) | ||
| 510 | return; | ||
| 511 | |||
| 512 | exit(generate_cached_repolist(path, cached_rc)); | ||
| 513 | } | ||
| 441 | 514 | ||
| 442 | static void cgit_parse_args(int argc, const char **argv) | 515 | static void cgit_parse_args(int argc, const char **argv) |
| 443 | { | 516 | { |
| @@ -168,6 +168,7 @@ struct cgit_config { | |||
| 168 | int cache_max_create_time; | 168 | int cache_max_create_time; |
| 169 | int cache_repo_ttl; | 169 | int cache_repo_ttl; |
| 170 | int cache_root_ttl; | 170 | int cache_root_ttl; |
| 171 | int cache_scanrc_ttl; | ||
| 171 | int cache_static_ttl; | 172 | int cache_static_ttl; |
| 172 | int embedded; | 173 | int embedded; |
| 173 | int enable_index_links; | 174 | int enable_index_links; |
