Fix problem with caching
[texmacs.git] / src / src / System / Misc / data_cache.cpp
blob5c2fcd53ae1e7aef944f5189657f6e2c6d2c0e58
2 /******************************************************************************
3 * MODULE : data_cache.cpp
4 * DESCRIPTION: utilities for caching data
5 * COPYRIGHT : (C) 2005 Joris van der Hoeven
6 *******************************************************************************
7 * This software falls under the GNU general public license version 3 or later.
8 * It comes WITHOUT ANY WARRANTY WHATSOEVER. For details, see the file LICENSE
9 * in the root directory or <http://www.gnu.org/licenses/gpl-3.0.html>.
10 ******************************************************************************/
12 #include "data_cache.hpp"
13 #include "file.hpp"
14 #include "convert.hpp"
15 #include "iterator.hpp"
17 /******************************************************************************
18 * Caching routines
19 ******************************************************************************/
21 static hashmap<tree,tree> cache_data ("?");
22 static hashset<string> cache_loaded;
23 static hashset<string> cache_changed;
24 static hashmap<string,bool> cache_valid (false);
26 void
27 cache_set (string buffer, tree key, tree t) {
28 tree ckey= tuple (buffer, key);
29 if (cache_data[ckey] != t) {
30 cache_data (ckey)= t;
31 cache_changed->insert (buffer);
35 void
36 cache_reset (string buffer, tree key) {
37 tree ckey= tuple (buffer, key);
38 cache_data->reset (ckey);
39 cache_changed->insert (buffer);
42 bool
43 is_cached (string buffer, tree key) {
44 tree ckey= tuple (buffer, key);
45 return cache_data->contains (ckey);
48 tree
49 cache_get (string buffer, tree key) {
50 tree ckey= tuple (buffer, key);
51 return cache_data [ckey];
54 bool
55 is_up_to_date (url dir, bool reset) {
56 string name_dir= concretize (dir);
57 if (reset) cache_valid->reset (name_dir);
58 if (cache_valid->contains (name_dir)) return cache_valid [name_dir];
59 int l= last_modified (dir, false);
60 if (is_cached ("validate_cache.scm", name_dir)) {
61 int r= as_int (cache_get ("validate_cache.scm", name_dir) -> label);
62 if (l == r) {
63 cache_valid (name_dir)= true;
64 return true;
66 //cout << name_dir << " no longer up to date " << r << " -> " << l << "\n";
68 //else cout << name_dir << " not up to date " << l << "\n";
69 cache_set ("validate_cache.scm", name_dir, as_string (l));
70 cache_valid (name_dir)= false;
71 return false;
74 bool
75 is_recursively_up_to_date (url dir) {
76 if (!is_up_to_date (dir)) return false;
77 bool error_flag;
78 array<string> a= read_directory (dir, error_flag);
79 for (int i=0; i<N(a); i++)
80 if (url (a[i]) != url_here () && url (a[i]) != url_parent ())
81 if (is_directory (dir * a[i]))
82 if (!is_recursively_up_to_date (dir * a[i]))
83 return false;
84 return true;
87 /******************************************************************************
88 * Which files should be stored in the cache?
89 ******************************************************************************/
91 static url texmacs_path (url_none ());
92 static url texmacs_doc_path (url_none ());
93 static url texmacs_home_path (url_none ());
95 static string texmacs_path_string;
96 static string texmacs_doc_path_string;
97 static string texmacs_home_path_string;
98 static string texmacs_font_path_string;
100 bool
101 do_cache_dir (string name) {
102 return
103 starts (name, texmacs_path_string) ||
104 starts (name, texmacs_doc_path_string);
107 bool
108 do_cache_stat (string name) {
109 return
110 starts (name, texmacs_path_string) ||
111 starts (name, texmacs_font_path_string) ||
112 starts (name, texmacs_doc_path_string);
115 bool
116 do_cache_stat_fail (string name) {
117 return
118 starts (name, texmacs_path_string) ||
119 starts (name, texmacs_doc_path_string);
122 bool
123 do_cache_file (string name) {
124 return
125 starts (name, texmacs_path_string) ||
126 starts (name, texmacs_font_path_string);
129 bool
130 do_cache_doc (string name) {
131 return starts (name, texmacs_doc_path_string);
134 /******************************************************************************
135 * Saving and loading the cache to/from disk
136 ******************************************************************************/
138 void
139 cache_save (string buffer) {
140 if (cache_changed->contains (buffer)) {
141 url cache_file= texmacs_home_path * url ("system/cache/" * buffer);
142 string cached;
143 iterator<tree> it= iterate (cache_data);
144 if (buffer == "file_cache" || buffer == "doc_cache") {
145 while (it->busy ()) {
146 tree ckey= it->next ();
147 if (ckey[0] == buffer) {
148 cached << ckey[1]->label << "\n";
149 cached << cache_data [ckey]->label << "\n";
150 cached << "%-%-tm-cache-%-%\n";
154 else {
155 cached << "(tuple\n";
156 while (it->busy ()) {
157 tree ckey= it->next ();
158 if (ckey[0] == buffer) {
159 cached << tree_to_scheme (ckey[1]) << " ";
160 cached << tree_to_scheme (cache_data [ckey]) << "\n";
163 cached << ")";
165 (void) save_string (cache_file, cached);
166 cache_changed->remove (buffer);
170 void
171 cache_load (string buffer) {
172 if (!cache_loaded->contains (buffer)) {
173 url cache_file = texmacs_home_path * url ("system/cache/" * buffer);
174 //cout << "cache_file "<< cache_file << LF;
175 string cached;
176 if (!load_string (cache_file, cached, false)) {
177 if (buffer == "file_cache" || buffer == "doc_cache") {
178 int i=0, n= N(cached);
179 while (i<n) {
180 int start= i;
181 while (i<n && cached[i] != '\n') i++;
182 string key= cached (start, i);
183 i++; start= i;
184 while (i<n && (cached[i] != '\n' ||
185 !test (cached, i+1, "%-%-tm-cache-%-%"))) i++;
186 string im= cached (start, i);
187 i++;
188 while (i<n && cached[i] != '\n') i++;
189 i++;
190 //cout << "key= " << key << "\n----------------------\n";
191 //cout << "im= " << im << "\n----------------------\n";
192 cache_data (tuple (buffer, key))= im;
195 else {
196 tree t= scheme_to_tree (cached);
197 for (int i=0; i<N(t)-1; i+=2)
198 cache_data (tuple (buffer, t[i]))= t[i+1];
201 cache_loaded->insert (buffer);
205 void
206 cache_memorize () {
207 cache_save ("file_cache");
208 cache_save ("doc_cache");
209 cache_save ("dir_cache.scm");
210 cache_save ("stat_cache.scm");
211 cache_save ("font_cache.scm");
212 cache_save ("validate_cache.scm");
215 void
216 cache_refresh () {
217 cache_data = hashmap<tree,tree> ("?");
218 cache_loaded = hashset<string> ();
219 cache_changed= hashset<string> ();
220 cache_load ("file_cache");
221 cache_load ("dir_cache.scm");
222 cache_load ("stat_cache.scm");
223 cache_load ("font_cache.scm");
224 cache_load ("validate_cache.scm");
227 void
228 cache_initialize () {
229 texmacs_path= url_system ("$TEXMACS_PATH");
230 if (get_env ("TEXMACS_HOME_PATH") == "")
231 texmacs_home_path= url_system ("$HOME/.TeXmacs");
232 else texmacs_home_path= url_system ("$TEXMACS_HOME_PATH");
233 if (get_env ("TEXMACS_DOC_PATH") == "")
234 texmacs_doc_path= url_system ("$TEXMACS_PATH/doc");
235 else texmacs_doc_path= url_system ("$TEXMACS_DOC_PATH");
237 texmacs_path_string = concretize (texmacs_path);
238 texmacs_home_path_string = concretize (texmacs_home_path);
239 texmacs_doc_path_string = concretize (texmacs_doc_path);
240 texmacs_font_path_string = concretize (texmacs_home_path * "fonts/");
243 cache_refresh ();
244 if (is_recursively_up_to_date (texmacs_path * "fonts/type1") &&
245 is_recursively_up_to_date (texmacs_path * "fonts/truetype") &&
246 is_recursively_up_to_date (texmacs_home_path * "fonts/type1") &&
247 is_recursively_up_to_date (texmacs_home_path * "fonts/truetype"));
248 else remove (texmacs_home_path * "fonts/error" * url_wildcard ("*"));