all repos — cgit @ 25105d7ecaba474d4b7c364ebb586aac3dfc5abb

a hyperfast web frontend for git written in c

cache.c (view raw)

 1#include "cgit.h"
 2
 3const int NOLOCK = -1;
 4
 5int cache_lookup(struct cacheitem *item)
 6{
 7	if (!cgit_query_repo) {
 8		item->name = xstrdup(fmt("%s/index.html", cgit_cache_root));
 9		item->ttl = cgit_cache_root_ttl;
10	} else if (!cgit_query_page) {
11		item->name = xstrdup(fmt("%s/%s/index.html", cgit_cache_root, 
12			   cgit_query_repo));
13		item->ttl = cgit_cache_repo_ttl;
14	} else {
15		item->name = xstrdup(fmt("%s/%s/%s/%s.html", cgit_cache_root, 
16			   cgit_query_repo, cgit_query_page, 
17			   cgit_querystring));
18		if (cgit_query_has_symref)
19			item->ttl = cgit_cache_dynamic_ttl;
20		else if (cgit_query_has_sha1)
21			item->ttl = cgit_cache_static_ttl;
22		else
23			item->ttl = cgit_cache_repo_ttl;
24	}
25	if (stat(item->name, &item->st)) {
26		item->st.st_mtime = 0;
27		return 0;
28	}
29	return 1;
30}
31
32int cache_create_dirs()
33{
34	char *path;
35
36	if (!cgit_query_repo)
37		return 0;
38
39	path = fmt("%s/%s", cgit_cache_root, cgit_query_repo);
40	if (mkdir(path, S_IRWXU) && errno!=EEXIST)
41		return 0;
42
43	if (cgit_query_page) {
44		path = fmt("%s/%s/%s", cgit_cache_root, cgit_query_repo, 
45			   cgit_query_page);
46		if (mkdir(path, S_IRWXU) && errno!=EEXIST)
47			return 0;
48	}
49	return 1;
50}
51
52int cache_lock(struct cacheitem *item)
53{
54	int ret;
55	char *lockfile = fmt("%s.lock", item->name);
56
57 top:  
58       	item->fd = open(lockfile, O_WRONLY | O_CREAT | O_EXCL, S_IRUSR|S_IWUSR);
59	if (item->fd == NOLOCK && errno == ENOENT && cache_create_dirs())
60		goto top;
61	if (item->fd == NOLOCK && errno == EEXIST) {
62		struct stat st;
63		time_t t;
64		if (stat(lockfile, &st))
65			return ret;
66		t = time(NULL);
67		if (t-st.st_mtime > cgit_cache_max_create_time && 
68		    !unlink(lockfile))
69			goto top;
70		return 0;
71	}
72	return (item->fd > 0);
73}
74
75int cache_unlock(struct cacheitem *item)
76{
77	close(item->fd);
78	return (rename(fmt("%s.lock", item->name), item->name) == 0);
79}
80
81int cache_expired(struct cacheitem *item)
82{
83	if (item->ttl < 0)
84		return 0;
85	return item->st.st_mtime + item->ttl * 60 < time(NULL);
86}