1 /* cache.c: cache management
3 * Copyright (C) 2006 Lars Hjemli
5 * Licensed under GNU General Public License v2
6 * (see COPYING for full license text)
11 const int NOLOCK
= -1;
13 void cache_prepare(struct cacheitem
*item
)
15 if (!cgit_query_repo
) {
16 item
->name
= xstrdup(fmt("%s/index.html", cgit_cache_root
));
17 item
->ttl
= cgit_cache_root_ttl
;
18 } else if (!cgit_query_page
) {
19 item
->name
= xstrdup(fmt("%s/%s/index.html", cgit_cache_root
,
21 item
->ttl
= cgit_cache_repo_ttl
;
23 item
->name
= xstrdup(fmt("%s/%s/%s/%s.html", cgit_cache_root
,
24 cgit_query_repo
, cgit_query_page
,
26 if (cgit_query_has_symref
)
27 item
->ttl
= cgit_cache_dynamic_ttl
;
28 else if (cgit_query_has_sha1
)
29 item
->ttl
= cgit_cache_static_ttl
;
31 item
->ttl
= cgit_cache_repo_ttl
;
35 int cache_exist(struct cacheitem
*item
)
37 if (stat(item
->name
, &item
->st
)) {
38 item
->st
.st_mtime
= 0;
44 int cache_create_dirs()
51 path
= fmt("%s/%s", cgit_cache_root
, cgit_query_repo
);
52 if (mkdir(path
, S_IRWXU
) && errno
!=EEXIST
)
55 if (cgit_query_page
) {
56 path
= fmt("%s/%s/%s", cgit_cache_root
, cgit_query_repo
,
58 if (mkdir(path
, S_IRWXU
) && errno
!=EEXIST
)
64 int cache_refill_overdue(const char *lockfile
)
68 if (stat(lockfile
, &st
))
71 return (time(NULL
) - st
.st_mtime
> cgit_cache_max_create_time
);
74 int cache_lock(struct cacheitem
*item
)
77 char *lockfile
= xstrdup(fmt("%s.lock", item
->name
));
80 if (++i
> cgit_max_lock_attempts
)
81 die("cache_lock: unable to lock %s: %s",
82 item
->name
, strerror(errno
));
84 item
->fd
= open(lockfile
, O_WRONLY
|O_CREAT
|O_EXCL
, S_IRUSR
|S_IWUSR
);
86 if (item
->fd
== NOLOCK
&& errno
== ENOENT
&& cache_create_dirs())
89 if (item
->fd
== NOLOCK
&& errno
== EEXIST
&&
90 cache_refill_overdue(lockfile
) && !unlink(lockfile
))
94 return (item
->fd
> 0);
97 int cache_unlock(struct cacheitem
*item
)
100 return (rename(fmt("%s.lock", item
->name
), item
->name
) == 0);
103 int cache_cancel_lock(struct cacheitem
*item
)
105 return (unlink(fmt("%s.lock", item
->name
)) == 0);
108 int cache_expired(struct cacheitem
*item
)
112 return item
->st
.st_mtime
+ item
->ttl
* 60 < time(NULL
);