Mise en route du suivi.
[aidenligne_francais_universite.git] / ecrire / inc / invalideur.php
1 <?php
2
3 /***************************************************************************\
4 * SPIP, Systeme de publication pour l'internet *
5 * *
6 * Copyright (c) 2001-2007 *
7 * Arnaud Martin, Antoine Pitrou, Philippe Riviere, Emmanuel Saint-James *
8 * *
9 * Ce programme est un logiciel libre distribue sous licence GNU/GPL. *
10 * Pour plus de details voir le fichier COPYING.txt ou l'aide en ligne. *
11 \***************************************************************************/
12
13
14 if (!defined("_ECRIRE_INC_VERSION")) return;
15
16 include_spip('base/serial');
17
18 // http://doc.spip.org/@supprime_invalideurs
19 function supprime_invalideurs() {
20 spip_query("DELETE FROM spip_caches");
21 }
22
23 //
24 // Calcul des pages : noter dans la base les liens d'invalidation
25 //
26 // http://doc.spip.org/@maj_invalideurs
27 function maj_invalideurs ($fichier, &$page) {
28 // ne pas noter les POST et les delais=0
29 if ($fichier == '') return;
30
31 // Supprimer les anciens invalideurs
32 $f = str_replace('.gz', '', $fichier);
33 spip_query("DELETE FROM spip_caches WHERE fichier='$f' OR fichier='$f.gz'");
34
35 // Creer un invalideur 't' nous informant de la date d'expiration
36 // et de la taille du fichier cache
37 # Note : on ajoute 3600s pour eviter toute concurrence
38 # entre un invalideur et un appel public de page
39 $bedtime = time() + $page['entetes']['X-Spip-Cache'] + 3600;
40 $taille = @filesize(_DIR_CACHE . $fichier);
41 spip_query("INSERT IGNORE INTO spip_caches (fichier,id,type,taille) VALUES (" . _q($fichier) . ",'$bedtime','t','$taille')");
42
43 // invalidations
44 insere_invalideur($page['invalideurs'], $fichier);
45 }
46
47 // pour les forums l'invalideur est : 'id_forum/a23'
48 // pour les petitions et autres, l'invalideur est par exemple :
49 // 'varia/pet60'
50 // http://doc.spip.org/@insere_invalideur
51 function insere_invalideur($inval, $fichier) {
52 if ($inval)
53 foreach ($inval as $type => $a) {
54 if (is_array($a)) {
55 $values = array();
56 foreach($a as $k => $v)
57 $values[] = "('$fichier', '$type/$k')";
58 spip_query("INSERT IGNORE INTO spip_caches (fichier, id) VALUES " . join(", ", $values));
59 }
60 }
61 }
62
63
64 //
65 // Invalider les caches lies a telle condition
66 // on en profite pour noter la date de mise a jour dans les metas
67 //
68 // http://doc.spip.org/@suivre_invalideur
69 function suivre_invalideur($cond, $modif=true) {
70 include_spip('inc/meta');
71 if ($modif) {
72 ecrire_meta('derniere_modif', time());
73 ecrire_metas();
74 }
75 $result = spip_query("SELECT DISTINCT fichier FROM spip_caches WHERE $cond");
76 $tous = array();
77 while ($row = spip_fetch_array($result))
78 $tous[] = $row['fichier'];
79
80 spip_log("suivre $cond dans " . count($tous) . " caches");
81 applique_invalideur($tous);
82 }
83
84
85 //
86 // Supprimer les vieux caches
87 //
88 // http://doc.spip.org/@retire_vieux_caches
89 function retire_vieux_caches() {
90 $condition = "type='t' AND id<".time();
91 suivre_invalideur($condition);
92 }
93
94
95 //
96 // Marquer les fichiers caches invalides comme etant a supprimer
97 //
98 // http://doc.spip.org/@applique_invalideur
99 function applique_invalideur($depart) {
100
101 if ($depart) {
102 $tous = "'".join("', '", $depart)."'";
103 spip_log("applique $tous");
104
105 include_spip('base/abstract_sql'); # pour calcul_mysql_in
106 spip_query("UPDATE spip_caches SET type='x' WHERE " . calcul_mysql_in('fichier', $tous));
107
108 // Demander a inc-public de retirer les caches
109 // invalides ;
110 // - le signal (meta='invalider') indique
111 // qu'il faut faire attention ;
112 // - le signal (meta='invalider_caches') indique qu'on
113 // peut effacer 100 caches invalides
114 // (Signaux differents pour eviter de la concurrence entre
115 // les processus d'invalidation)
116 ecrire_meta('invalider', 'oui'); // se verifier soi-meme
117 ecrire_meta('invalider_caches', 'oui'); // supprimer les autres
118 ecrire_metas();
119 }
120 }
121
122
123 // Utilisee pour vider le cache depuis l'espace prive
124 // (ou juste les squelettes si un changement de config le necessite)
125 // http://doc.spip.org/@purger_repertoire
126 function purger_repertoire($dir) {
127 $handle = @opendir($dir);
128 if (!$handle) return;
129
130 while (($fichier = @readdir($handle)) !== false) {
131 // Eviter ".", "..", ".htaccess", etc.
132 if ($fichier[0] == '.') continue;
133 $chemin = "$dir/$fichier";
134 if (is_file($chemin))
135 @unlink($chemin);
136 else if (is_dir($chemin))
137 if ($fichier != 'CVS')
138 purger_repertoire($chemin);
139 }
140 closedir($handle);
141 }
142
143 // http://doc.spip.org/@cron_invalideur
144 function cron_invalideur($t) {
145
146 // A revoir: il semble y avoir une desynchro ici.
147 // Avant tout s'assurer que le cache n'a pas explose,
148 // et purger tout sans finesse dans ce cas
149 $t = spip_query("SELECT SUM(taille) AS n FROM spip_caches WHERE type IN ('t', 'x')");
150 $t = spip_fetch_array($t);
151 $total_cache = $t['n'];
152 spip_log("Taille du CACHE: $total_cache octets");
153 global $quota_cache;
154 if ($total_cache>5*$quota_cache*1024*1024){
155 spip_log("Taille explose (max $quota_cache)/ purge totale");
156 // on purge d'abord le repertoire (le plus long, qui ne tiendra peut etre pas en un hit)
157 purger_repertoire(_DIR_CACHE);
158 // on solde les invalideurs
159 supprime_invalideurs();
160 return 1;
161 }
162
163 //
164 // menage des vieux fichiers du cache
165 // marques par l'invalideur 't' = date de fin de fichier
166 //
167
168 retire_vieux_caches();
169
170 // En cas de quota sur le CACHE/, nettoyer les fichiers les plus vieux
171 $total_cache -= $quota_cache*1024*1024;
172 if ($quota_cache > 0 AND $total_cache > 0) {
173 $taille_supprimee = 0;
174 $q = spip_query("SELECT id, taille FROM spip_caches WHERE type IN ('t', 'x') ORDER BY id");
175 while ($r = spip_fetch_array($q)
176 AND ($total_cache > $taille_supprimee)) {
177 $date_limite = $r['id'];
178 $taille_supprimee += $r['taille'];
179 }
180 spip_log ("Quota cache: efface $taille_supprimee octets");
181 suivre_invalideur("id <= $date_limite AND type in ('t', 'x')", false);
182 }
183 return 1;
184 }
185
186 //
187 // Destruction des fichiers caches invalides
188 //
189
190 // Securite : est sur que c'est un cache
191 // http://doc.spip.org/@retire_cache
192 function retire_cache($cache) {
193
194 if (preg_match(
195 "|^([0-9a-f]/)?([0-9]+/)?[^.][\-_\%0-9a-z]+\.[0-9a-f]+(\.gz)?$|i",
196 $cache)) {
197 // supprimer le fichier (de facon propre)
198 supprimer_fichier(_DIR_CACHE . $cache);
199 } else
200 spip_log("Impossible de retirer $cache");
201 }
202
203 // Supprimer les caches marques "x"
204 // http://doc.spip.org/@retire_caches
205 function retire_caches($chemin = '') {
206 include_spip('base/abstract_sql');
207 include_spip('inc/meta');
208 lire_metas();
209 // recuperer la liste des caches voues a la suppression
210 $suppr = array();
211
212 // En priorite le cache qu'on appelle maintenant
213 if ($chemin) {
214 $f = spip_abstract_fetsel(array("fichier"),
215 array("spip_caches"),
216 array("fichier = " . _q($chemin) . " ",
217 "type='x'"),
218 "",
219 array(),
220 1);
221 if ($f['fichier']) $suppr[$f['fichier']] = true;
222 }
223
224 // Et puis une centaine d'autres
225 $compte = 0;
226 if (isset($GLOBALS['meta']['invalider_caches'])) {
227 $compte = 1;
228 effacer_meta('invalider_caches'); # concurrence
229 ecrire_metas();
230
231 $q = spip_abstract_select(array("fichier"),
232 array("spip_caches"),
233 array("type='x'"),
234 "",
235 array(),
236 100);
237 while ($r = spip_abstract_fetch($q)) {
238 $compte ++; # compte le nombre de resultats vus (y compris doublons)
239 $suppr[$r['fichier']] = true;
240 }
241 }
242
243 if ($n = count($suppr)) {
244 spip_log ("Retire $n caches");
245 foreach ($suppr as $cache => $ignore)
246 retire_cache($cache);
247 spip_query("DELETE FROM spip_caches WHERE " . calcul_mysql_in('fichier', "'".join("','",array_keys($suppr))."'") );
248 }
249
250 // Si on a regarde (compte > 0), signaler s'il reste des caches invalides
251 if ($compte > 0) {
252 if ($compte > 100) # s'il y en a 101 c'est qu'on n'a pas fini
253 ecrire_meta('invalider_caches', 'oui');
254 else
255 effacer_meta('invalider');
256 ecrire_metas();
257 }
258 }
259
260
261 // Pour que le compilo ajoute un invalideur a la balise #PARAMETRES_FORUM
262 // Noter l'invalideur de la page contenant ces parametres,
263 // en cas de premier post sur le forum
264 // http://doc.spip.org/@code_invalideur_forums
265 function code_invalideur_forums($p, $code) {
266 $type = 'id_forum';
267 $valeur = "\n\t\tcalcul_index_forum("
268 // Retournera 4 [$SP] mais force la demande du champ SQL
269 . champ_sql('id_article', $p) . ','
270 . champ_sql('id_breve', $p) . ','
271 . champ_sql('id_rubrique', $p) .','
272 . champ_sql('id_syndic', $p) . ")\n\t";
273
274 return '
275 // invalideur '.$type.'
276 (!($Cache[\''.$type.'\']['.$valeur."]=1) ? '':\n\t" . $code .")\n";
277 }
278
279
280 // Fonction permettant au compilo de calculer les invalideurs d'une page
281 // http://doc.spip.org/@calcul_invalideurs
282 function calcul_invalideurs($corps, $primary, &$boucles, $id_boucle) {
283 if ($primary == 'id_forum'
284 OR in_array($primary, explode(',', $GLOBALS['invalider_caches']))) {
285 $corps .= "\n\t\t\$Cache['$primary'][intval(" .
286 (($primary != 'id_forum') ?
287 index_pile($id_boucle, $primary, $boucles) :
288 ("calcul_index_forum(" .
289 // Retournera 4 [$SP] mais force la demande du champ a MySQL
290 index_pile($id_boucle, 'id_article', $boucles) . ',' .
291 index_pile($id_boucle, 'id_breve', $boucles) . ',' .
292 index_pile($id_boucle, 'id_rubrique', $boucles) .',' .
293 index_pile($id_boucle, 'id_syndic', $boucles) .
294 ")")) .
295 ")] = 1; // invalideurs\n";
296 }
297 return $corps;
298 }
299
300 ?>