source: spip-zone/_plugins_/cachelab/trunk/inc/cachelab.php @ 111894

Last change on this file since 111894 was 111894, checked in by jluc@…, 14 months ago

mémo php

File size: 7.2 KB
Line 
1<?php
2if (!defined('_ECRIRE_INC_VERSION')) {
3        return;
4}
5
6include_spip ('lib/microtime.inc');
7
8if (!function_exists('plugin_est_actif')) {
9        function plugin_est_actif($prefixe) {
10                $f = chercher_filtre('info_plugin');
11                return $f($prefixe, 'est_actif');
12        }
13}
14
15function cachelab_applique ($action, $cle, $data=null, $options='') {
16global $Memoization;
17static $len_prefix;
18        if (!$len_prefix)
19                $len_prefix = strlen(_CACHE_NAMESPACE);
20        $joliecle = substr($cle, $len_prefix);
21
22        switch ($action) {
23        case 'del' :
24                $del = $Memoization->del($joliecle);
25                if (!$del) {
26                        spip_log ("Échec 'del' $joliecle", 'cachelab');
27                        return false;
28                };
29                break;
30
31        case 'echo_cache' :
32                if (!$data)
33                        $data = $Memoization->get($joliecle);
34                echo "«<xmp>".substr(print_r($data,1), 0,2000)."</xmp>»";
35                break;
36
37        case 'echo_html' :
38                if (!$data)
39                        $data = $Memoization->get($joliecle);
40                echo "<p>«<xmp>".print_r($data,1)."</xmp>»</p>";
41                break;
42
43        case 'pass' :
44        case 'list' :
45                break;
46
47        default :
48                // on pourrait appeler cachelab_applique_$action(...)
49                break;
50        }
51        return true;
52}
53
54// $chemin : liste de chaines à tester dans le chemin du squelette, séparées par |
55//      OU une regexp (hors délimiteurs et modificateurs) si la méthode est 'regexp'
56function cachelab_filtre ($action, $conditions, $options=array()) {
57global $Memoization;
58        if (!$Memoization or !in_array($Memoization->methode(), array('apc', 'apcu')))
59                die ("Il faut mémoization avec APC ou APCu");
60
61        // filtrage
62        $session = (isset($conditions['session']) ? $conditions['session'] : null);
63        if ($session=='courante')
64                $session = spip_session();
65        $chemin = (isset($conditions['chemin']) ? $conditions['chemin'] : null);
66        $chemins = explode('|', $chemin); // sert seulement pour methode_chemin == strpos
67        $cle_objet = (isset($conditions['cle_objet']) ? $conditions['cle_objet'] : null);
68        $id_objet = (isset($conditions['id_objet']) ? $conditions['id_objet'] : null);
69        if ($cle_objet and !$id_objet)
70                die ("$cle_objet est inconnu : passez le en argument d'url ou définissez XRAY_ID_OBJET_SPECIAL en php");
71        // pour 'contexte' on simule un 'more' pour donner un exemple d'extension
72        if (isset($conditions['contexte']) and $conditions['contexte'] and !isset($conditions['more']))
73                $conditions['more'] = 'contexte';
74        if ($more = (isset($conditions['more']) ? (string)$conditions['more'] : '')) {
75                $morefunc='cachelab_filtrecache_'.$more;
76                // Signature nécessaire : $morefunc ($action, $conditions, $options, &$stats)
77                if (!function_exists($morefunc))
78                        die ("La fonction '$morefunc' n'est pas définie");
79        }
80
81        // options
82        // explode+strpos par défaut pour les chemins
83        $methode_chemin = (isset ($options['methode_chemin']) ? $options['methode_chemin'] : 'strpos');
84        // clean par défaut
85        $do_clean = (isset ($options['clean']) ? $options['clean'] : (!defined('CACHELAB_CLEAN') or CACHELAB_CLEAN)); 
86        // pas de listes par défaut
87        $do_lists = ($action == 'list') or (isset ($options['list']) and $options['list']);
88        // pas de chrono par défaut sauf si CACHELAB_CHRONO
89        $do_chrono = (isset ($options['chrono']) ? $options['chrono'] : (defined('CACHELAB_CHRONO') and CACHELAB_CHRONO)); 
90        if ($do_chrono) {
91                include_spip ('lib/microtime.inc');
92                microtime_do ('begin');
93        }
94
95        // retours
96        $stats=array();
97        $stats['nb_alien']=$stats['nb_candidats']=$stats['nb_clean']=$stats['nb_no_data']=$stats['nb_not_array']=$stats['nb_cible']=0;
98        $stats['l_no_data'] = $stats['l_not_array'] = $stats['l_cible'] = array();
99
100        // On y va
101        $cache = apcu_cache_info();
102        $meta_derniere_modif = lire_meta('derniere_modif');
103        $len_prefix = strlen(_CACHE_NAMESPACE);
104
105        foreach($cache['cache_list'] as $i => $d) {
106                // on "continue=passe au suivant" dés qu'on sait que le cache n'est pas cible
107
108                $cle = $d['info'];
109                $data=null;
110
111                // on saute les caches d'autres origines
112                // (et les caches d'un précédent _CACHE_NAMESPACE pour ce même site)
113                if (strpos ($cle, _CACHE_NAMESPACE) !== 0) {
114                        $stats['nb_alien']++;
115                        continue;
116                }
117
118                // on ne veut examiner que les caches de squelettes SPIP
119                if ((substr($cle, $len_prefix-1, 7) != ':cache:')
120                        or !apcu_exists($cle))
121                        continue;
122
123                // effacer ou au moins sauter les caches périmés
124                if ($meta_derniere_modif > $d['creation_time']) {
125                        if ($do_clean) {
126                                $del=$Memoization->del(substr($cle,$len_prefix));
127                                if (!$del)
128                                        spip_log ("Echec du clean du cache périmé cle=$cle (création : {$d['creation_time']}, invalidation : $meta_derniere_modif)", "cachelab");
129                                $stats['nb_clean']++;
130                        };
131                        continue;
132                }
133
134                // caches SPIP véritablement candidats
135                $stats['nb_candidats']++;
136
137                if ($session) {
138                        if (substr ($cle, -9) != "_$session")
139                                continue;
140                }
141
142                if ($chemin) {
143                        // mémo php : « continue resumes execution just before the closing curly bracket ( } ), and break resumes execution just after the closing curly bracket. »
144                        switch ($methode_chemin) {
145                        case 'strpos' :
146                                foreach ($chemins as $unchemin)
147                                        if ($unchemin and (strpos ($cle, $unchemin) !== false))
148                                                break 2;        // trouvé : sort du foreach et du switch et poursuit le test des autres conditions
149                                continue 2;      // échec : passe à la $cle suivante
150                        case 'regexp' :
151                                if ($chemin and ($danslechemin = preg_match(",$chemin,i", $cle)))
152                                        break;  // trouvé : poursuit le test des autres conditions
153                                continue 2;     // échec : passe à la clé suivante
154                        default :
155                                die("Méthode '$methode_chemin' pas prévue pour le filtrage par le chemin");
156                        };
157                }
158                // récupérer le contenu du cache
159                if (($cle_objet and $id_objet) or $morefunc) {
160                        global $Memoization;
161                        $data = $Memoization->get(substr($cle, $len_prefix));
162                        if (!$data) {
163                                $stats['nb_no_data']++;
164                                continue;
165                        }
166                        if (!is_array($data)) {
167                                spip_log ("clé=$cle : data n'est pas un tableau : ".print_r($data,1), 'cachelab');
168                                $stats['nb_not_array']++;
169                                if ($do_lists)
170                                        $stats['l_not_array'][] = $cle;
171                                continue;
172                        };
173                };
174
175                if ($cle_objet
176                        and (!isset ($data['contexte'][$cle_objet])
177                                or ($data['contexte'][$cle_objet]!=$id_objet)))
178                        continue;
179
180                if ($morefunc
181                        and !$morefunc ($action, $conditions, $options, $cle, $data, $stats))
182                        continue;
183
184                // restent les cibles
185                $stats['nb_cible']++;
186                if ($do_lists) 
187                        $stats['l_cible'][] = $cle;
188
189                cachelab_applique ($action, $cle, $data, $options);
190        }
191
192
193        if ($do_chrono) {
194                $stats['chrono'] = microtime_do ('end', 'ms');
195                spip_log ("cachelab_filtre ($action) avec session=$session, objet $cle_objet=$id_objet, chemin=$chemin) : {$stats['nb_cible']} caches ciblés en {$stats['chrono']} ms", 'cachelab');
196        }
197
198        return $stats;
199}
200
201function controler_invalideur($action, $objets_invalidants=array()) {
202static $prev_derniere_modif_invalide;
203        switch($action) {
204        case 'stop' :
205                $objets_invalidants = array();
206                // nobreak;
207        case 'select' :
208                $prev_derniere_modif_invalide = $GLOBALS['derniere_modif_invalide'];
209                if (is_array($objets_invalidants))
210                        $GLOBALS['derniere_modif_invalide'] = $objets_invalidants;
211                break;
212        case 'go' :
213                $GLOBALS['derniere_modif_invalide'] = $prev_derniere_modif_invalide;
214                break;
215        }
216}
217
218function cachelab_filtrecache_contexte($action, $conditions, $options, $cle, &$data, &$stats) {
219        if (!isset ($data['contexte'])
220                or !isset($conditions['contexte'])
221                or !is_array($conditions['contexte']))
222                return false;
223        $diff = array_diff_assoc($conditions['contexte'], $data['contexte']);
224        return empty($diff);
225}
Note: See TracBrowser for help on using the repository browser.