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"
14 #include "convert.hpp"
15 #include "iterator.hpp"
17 /******************************************************************************
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);
27 cache_set (string buffer
, tree key
, tree t
) {
28 tree ckey
= tuple (buffer
, key
);
29 if (cache_data
[ckey
] != t
) {
31 cache_changed
->insert (buffer
);
36 cache_reset (string buffer
, tree key
) {
37 tree ckey
= tuple (buffer
, key
);
38 cache_data
->reset (ckey
);
39 cache_changed
->insert (buffer
);
43 is_cached (string buffer
, tree key
) {
44 tree ckey
= tuple (buffer
, key
);
45 return cache_data
->contains (ckey
);
49 cache_get (string buffer
, tree key
) {
50 tree ckey
= tuple (buffer
, key
);
51 return cache_data
[ckey
];
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
);
63 cache_valid (name_dir
)= 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;
75 is_recursively_up_to_date (url dir
) {
76 if (!is_up_to_date (dir
)) return false;
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
]))
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
;
101 do_cache_dir (string name
) {
103 starts (name
, texmacs_path_string
) ||
104 starts (name
, texmacs_doc_path_string
);
108 do_cache_stat (string name
) {
110 starts (name
, texmacs_path_string
) ||
111 starts (name
, texmacs_font_path_string
) ||
112 starts (name
, texmacs_doc_path_string
);
116 do_cache_stat_fail (string name
) {
118 starts (name
, texmacs_path_string
) ||
119 starts (name
, texmacs_doc_path_string
);
123 do_cache_file (string name
) {
125 starts (name
, texmacs_path_string
) ||
126 starts (name
, texmacs_font_path_string
);
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 ******************************************************************************/
139 cache_save (string buffer
) {
140 if (cache_changed
->contains (buffer
)) {
141 url cache_file
= texmacs_home_path
* url ("system/cache/" * buffer
);
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";
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";
165 (void) save_string (cache_file
, cached
);
166 cache_changed
->remove (buffer
);
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;
176 if (!load_string (cache_file
, cached
, false)) {
177 if (buffer
== "file_cache" || buffer
== "doc_cache") {
178 int i
=0, n
= N(cached
);
181 while (i
<n
&& cached
[i
] != '\n') i
++;
182 string key
= cached (start
, i
);
184 while (i
<n
&& (cached
[i
] != '\n' ||
185 !test (cached
, i
+1, "%-%-tm-cache-%-%"))) i
++;
186 string im
= cached (start
, i
);
188 while (i
<n
&& cached
[i
] != '\n') i
++;
190 //cout << "key= " << key << "\n----------------------\n";
191 //cout << "im= " << im << "\n----------------------\n";
192 cache_data (tuple (buffer
, key
))= im
;
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
);
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");
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");
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/");
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 ("*"));