-
Notifications
You must be signed in to change notification settings - Fork 6
/
Copy pathcache.d
158 lines (131 loc) · 3.91 KB
/
cache.d
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
module cache;
import quickformat;
import tools.base: read, write, split, join, slice, fail, mkdir, stuple, Stuple, ptuple;
import tools.log: logln;
string[] include_path;
static this() {
include_path ~= "/usr/local/include";
include_path ~= "/usr/include";
version(Windows) include_path ~= "/mingw/include";
}
string objdir;
import memconserve_stdfile;
alias memconserve_stdfile.exists exists;
alias memconserve_stdfile.getTimes getTimes;
private bool earlier(long t1, long t2) { return t1 < t2; }
private bool older (long t1, long t2) { return t1 > t2; }
// is file1 older than file2? if it's newer, must regenerate file2.
bool isUpToDate(string file1, string file2) {
long created1, accessed1, modified1, created2, accessed2, modified2;
file1.getTimes(created1, accessed1, modified1);
file2.getTimes(created2, accessed2, modified2);
return earlier(modified1, modified2);
}
bool mustReread(string source, string product) {
if (!product.exists()) return true;
return !isUpToDate(source, product);
}
extern(C) long atoll(char* c);
long atol(string s) {
string cstr = qformat(s, "\0");
return atoll(cstr.ptr);
}
string[string] findfile_cache;
string findfile(string file) {
if (auto p = file in findfile_cache) {
if (!*p) {
fail(qformat("lookup for ", file, " returned in null from cache"));
}
return *p;
}
string res;
if (file.exists()) res = file;
else {
foreach (entry; include_path)
if (entry.qsub(file).exists()) {
res = entry.qsub(file);
break;
}
if (!res) {
fail(qformat("File not found: ", file, ", in path ", include_path));
}
}
findfile_cache[file] = res;
if (!res) fail(qformat("lookup for ", file, " returned in uncached null"));
return res;
}
bool cachefile_read;
string[string] cachedata;
void check_cache() {
string cachefile = objdir ~ "/cache.txt";
if (!cachefile_read) {
cachefile_read = true;
if (!cachefile.exists()) return;
foreach (line; (cast(string) read(cachefile)).split("\n")) {
auto lkey = line.slice("=");
cachedata[lkey] = line;
}
}
}
Stuple!(long, long, long)[string] times_cache;
void getTimes_cached(string file, ref long c, ref long a, ref long m) {
if (auto p = file in times_cache) { ptuple(c, a, m) = *p; return; }
file.getTimes(c, a, m);
times_cache[file] = stuple(c, a, m);
}
string read_cache(string key, string filekey) {
if (filekey) {
filekey = findfile(filekey);
if (!filekey) {
logln("?? '", filekey, "'");
fail;
}
}
check_cache();
if (!cachefile_read) return null;
if (filekey) {
auto age = qformat("age ", filekey, " ", key);
if (!(age in cachedata)) return null;
long created, accessed, modified;
filekey.getTimes_cached(created, accessed, modified);
long mod2 = cachedata[age].atol();
if (older(modified, mod2)) // if the cache is older than our file
return null;
}
auto fullkey = qformat("key ", filekey, " ", key);
if (!(fullkey in cachedata)) {
if (filekey) {
logln("cache for ", key, ", ", filekey, " tracks age but not data");
fail;
} else return null;
}
return cachedata[fullkey];
}
double last_saved = 0;
import tools.time: sec;
void write_cache(string key, string filekey, string data) {
if (filekey) {
filekey = findfile(filekey);
if (!filekey) {
logln("!! ", filekey);
fail;
}
}
check_cache();
auto fullkey = qformat("key ", filekey, " ", key);
if (filekey) {
long created, accessed, modified;
filekey.getTimes(created, accessed, modified);
auto agekey = qformat("age ", filekey, " ", key);
cachedata[agekey] = qformat(modified);
}
cachedata[fullkey] = data;
}
void save_cache() {
string cachefile = objdir ~ "/cache.txt";
string[] lines;
foreach (key, value; cachedata) lines ~= qformat(key, "=", value);
if (!objdir.exists()) mkdir(objdir);
scope data = lines.join("\n");
write(cachefile, data);
}