Changeset 122459 in spip-zone


Ignore:
Timestamp:
Feb 13, 2020, 3:00:03 PM (6 months ago)
Author:
root
Message:

Nouveau descripteur de ciblage : 'ou' ou 'or', permettent de tester différentes combinaisons de requêtes lors d'un même appel à cachelab_cibler. Lorsqu'il y a bcp de caches et qu'on veut cibler plusieurs jeux de caches, c'est bcp + rapide que plusieurs appels à cachelab_cibler. 'ou' vaut un tableau des tableaux descripteurs de ciblage. Par exemple : 'ou' => chemin=>liste], [chemin=>document,cle_objet=>document,id_objet=>1023?. Les options sont communes à tous les operandes du 'ou'.

Location:
_plugins_/cachelab/trunk
Files:
2 edited

Legend:

Unmodified
Added
Removed
  • _plugins_/cachelab/trunk/inc/cachelab.php

    r119194 r122459  
    3636                        spip_log("Échec 'del' $joliecle", 'cachelab_erreur');
    3737                        return false;
    38                 };
    39                         break;
     38                }
     39                break;
    4040
    4141        // gérés par cachelab_cibler
     
    4343        case 'list':    // renvoie les clés
    4444        case 'clean':   // nettoie
    45                         break;
     45                break;
    4646               
    4747        case 'list_html':       // renvoie les contenus indexés par les clés sans préfixes
     
    5151                }
    5252                $return[$joliecle] = $data['texte'];
    53                         break;
     53                break;
    5454
    5555        case 'get':     // renvoie le 1er cache ciblé
     
    5858                }
    5959                $return = $data;
    60                         break;
     60                break;
    6161
    6262        case 'get_html':        // renvoie le contenu du 1er cache
     
    6565                }
    6666                $return = $data['texte'];
    67                         break;
     67                break;
    6868
    6969        default:
     
    8080
    8181/**
     82 * extrait du tableau les différentes conditions précodées
     83 * @param array $conditions
     84 * @return array ($session, $chemin, $chemins, $cle_objet, $id_objet, $plusfunc)
     85 */
     86function cachelab_prepare_conditions($conditions) {
     87        // filtrage
     88        $session = (isset($conditions['session']) ? $conditions['session'] : null);
     89        if ($session=='courante') {
     90                $session = spip_session();
     91        }
     92
     93        $chemin = (isset($conditions['chemin']) ? $conditions['chemin'] : null);
     94        $chemins = ($chemin ? explode('|', $chemin) : null); // sert seulement pour methode_chemin == strpos
     95
     96        $cle_objet = (isset($conditions['cle_objet']) ? $conditions['cle_objet'] : null);
     97        $id_objet = (isset($conditions['id_objet']) ? $conditions['id_objet'] : null);
     98        if ($cle_objet and !$id_objet) {
     99                spip_log("cachelab_cibler : $cle_objet inconnu\n".print_r(debug_backtrace(), 1), 'cachelab_erreur');
     100                $cle_objet=null;
     101        }
     102
     103        // pour 'contexte' on simule un 'plus' pour donner un exemple d'extension
     104        if (isset($conditions['contexte']) and $conditions['contexte'] and !isset($conditions['plus'])) {
     105                $conditions['plus'] = 'contexte';
     106        }
     107        if ($plus = (isset($conditions['plus']) ? (string)$conditions['plus'] : '')) {
     108                $plusfunc='cachelab_ciblercache_'.$plus;
     109                // Signature nécessaire : $plusfunc ($action, $conditions, $options, &$stats)
     110                if (!function_exists($plusfunc)) {
     111                        spip_log("La fonction '$plusfunc' n'est pas définie", 'cachelab_erreur');
     112                        return null;
     113                }
     114        } else {
     115                $plusfunc = '';
     116        }
     117        return array ($session, $chemin, $chemins, $cle_objet, $id_objet, $plusfunc);
     118}
     119/**
    82120 *
    83121 * Applique une action donnée à tous les caches vérifiant certaines conditions
     
    99137                die("cachelab_cibler($action...) : le plugin Mémoization doit être activé avec APC ou APCu");
    100138        }
    101         $return = null;
    102 
    103         // filtrage
    104         $session = (isset($conditions['session']) ? $conditions['session'] : null);
    105         if ($session=='courante') {
    106                 $session = spip_session();
    107         }
    108 
    109         $chemin = (isset($conditions['chemin']) ? $conditions['chemin'] : null);
    110         $chemins = explode('|', $chemin); // sert seulement pour methode_chemin == strpos
    111 
    112         $cle_objet = (isset($conditions['cle_objet']) ? $conditions['cle_objet'] : null);
    113         $id_objet = (isset($conditions['id_objet']) ? $conditions['id_objet'] : null);
    114         if ($cle_objet and !$id_objet) {
    115                 spip_log("cachelab_cibler : $cle_objet inconnu\n".print_r(debug_backtrace(), 1), 'cachelab_erreur');
    116                 $cle_objet=null;
    117         }
    118 
    119         // pour 'contexte' on simule un 'plus' pour donner un exemple d'extension
    120         if (isset($conditions['contexte']) and $conditions['contexte'] and !isset($conditions['plus'])) {
    121                 $conditions['plus'] = 'contexte';
    122         }
    123         if ($plus = (isset($conditions['plus']) ? (string)$conditions['plus'] : '')) {
    124                 $plusfunc='cachelab_ciblercache_'.$plus;
    125                 // Signature nécessaire : $plusfunc ($action, $conditions, $options, &$stats)
    126                 if (!function_exists($plusfunc)) {
    127                         spip_log("La fonction '$plusfunc' n'est pas définie", 'cachelab_erreur');
    128                         return null;
    129                 }
    130         } else {
    131                 $plusfunc = '';
    132         }
     139
     140        $return = $session = $chemin = $chemins = $cle_objet = $id_objet = $plusfunc = null;
     141
     142        // Prise en compte des OU (alternatives de conditions)
     143        // Attention la réentrance n'est pas prévue historiquement alors surprises en perspectives
     144        $l_conditions = (isset($conditions['ou']) ? $conditions['ou'] : '')
     145                        or (isset($conditions['or']) ? $conditions['or'] : '');
     146        if (!$l_conditions) {
     147                $l_conditions = array($conditions);
     148        }
     149        elseif (!is_array($l_conditions)) {
     150                spip_log ("La condition OU ou OR pour cachelab_cibler($action,...) n'est pas un tableau : " . print_r ($conditions, 1), 'cachelab_erreur');
     151                return null;
     152        }
     153
     154        // $l_conditions est un tableau de conditions élémentaires
     155        // La condition globale est statisfaite si l'une des condition est satisfaite (OR)
     156        // Chaque condition élémentaire est satisfaite si chacune de ses composantes est satisfaite
     157
     158        $l_conditions = array_map ('cachelab_prepare_conditions', $l_conditions);
     159        // prend la forme d'un tableau de conditions précalculées [$session, $chemin, $chemins, $cle_objet, $id_objet, $plusfunc]
    133160
    134161        // options
     
    153180        $len_prefix = strlen(_CACHE_NAMESPACE);
    154181
    155         foreach ($cache['cache_list'] as $i => $d) {
     182        foreach ($cache['cache_list'] as $d) {
    156183                // on "continue=passe au suivant" dés qu'on sait que le cache n'est pas cible
    157 
    158184                $cle = $d['info'];
    159185                $data=null;
    160186
    161                 // on saute les caches d'autres origines
    162                 // (et les caches d'un autre _CACHE_NAMESPACE pour ce même site)
    163                 if (strpos($cle, _CACHE_NAMESPACE) !== 0) {
    164                         $stats['nb_alien']++;
    165                         continue;
    166                 }
    167 
    168                 // on ne veut examiner que les caches de squelettes SPIP
    169                 if (substr($cle, $len_prefix-1, 7) != ':cache:') {
    170                         continue;
    171                 }
    172 
    173                 // effacer ou sauter les caches invalidés par une invalidation totale
    174                 // ou que apcu ne suit plus
    175                 if ($meta_derniere_modif > $d['creation_time']
    176                         or !apcu_exists($cle)) {
    177                         if ($do_clean) {
    178                                 $del=$Memoization->del(substr($cle, $len_prefix));
    179                                 if (!$del) {
    180                                         // Se produit parfois en salve de 10 à 50 logs simultanés (mm t, mm pid)
    181                                         spip_log("Echec du clean du cache $cle par Memoization (création : {$d['creation_time']}, invalidation : $meta_derniere_modif)", 'cachelab_erreur');
    182                                 }
    183                                 $stats['nb_clean']++;
    184                         };
    185                         continue;
     187                // on passe les caches non concernés
     188                if (true) {
     189                        // on saute les caches d'autres origines
     190                        // (et les caches d'un autre _CACHE_NAMESPACE pour ce même site)
     191                        if (strpos($cle, _CACHE_NAMESPACE) !== 0) {
     192                                $stats['nb_alien']++;
     193                                continue;
     194                        }
     195
     196                        // on ne veut examiner que les caches de squelettes SPIP
     197                        if (substr($cle, $len_prefix-1, 7) != ':cache:') {
     198                                continue;
     199                        }
     200
     201                        // effacer ou sauter les caches invalidés par une invalidation totale
     202                        // ou que apcu ne suit plus
     203                        if ($meta_derniere_modif > $d['creation_time']
     204                                or !apcu_exists($cle)) {
     205                                if ($do_clean) {
     206                                        $del=$Memoization->del(substr($cle, $len_prefix));
     207                                        if (!$del) {
     208                                                // Se produit parfois en salve de 10 à 50 logs simultanés (mm t, mm pid)
     209                                                spip_log("Echec du clean du cache $cle par Memoization (création : {$d['creation_time']}, invalidation : $meta_derniere_modif)", 'cachelab_erreur');
     210                                        }
     211                                        $stats['nb_clean']++;
     212                                }
     213                                continue;
     214                        }
    186215                }
    187216
     
    189218                $stats['nb_candidats']++;
    190219
    191                 // 1er filtrage : par la session
    192                 if ($session) {
    193                         if (substr($cle, -9) != "_$session") {
     220                $cible = false;
     221                // La premiere condition élémentaire composée entièrement satisfaite
     222                foreach ($l_conditions as list ($session, $chemin, $chemins, $cle_objet, $id_objet, $plusfunc)) {
     223                        // 1er filtrage : par la session
     224                        if ($session) {
     225                                if (substr ($cle, -9) != "_$session") {
     226                                        continue;
     227                                        // sur chaque échec on passe à la condition suivante dans le cas d'un OU ou d'un OR
     228                                }
     229                        }
     230
     231                        // 2eme filtrage : par le chemin
     232                        if ($chemins) {
     233                                switch ($partie_chemin) {
     234                                        case 'tout':
     235                                        case 'chemin':
     236                                                $partie_cle = $cle;
     237                                                break;
     238                                        case 'fichier':
     239                                                $parties = explode ('/', $cle);
     240                                                $partie_cle = array_pop ($parties);
     241                                                break;
     242                                        case 'dossier':
     243                                                $parties = explode ('/', $cle);
     244                                                $parties = array_pop ($parties);
     245                                                $partie_cle = array_pop ($parties);
     246                                                break;
     247                                        default:
     248                                                spip_log ("Option partie_chemin incorrecte : '$partie_chemin'", 'cachelab_erreur');
     249                                                return null;
     250                                }
     251                                // mémo php : « continue resumes execution just before the closing curly bracket },
     252                                //              and break resumes execution just after the closing curly bracket } »
     253                                switch ($methode_chemin) {
     254                                        case 'strpos':
     255                                                foreach ($chemins as $unchemin) {
     256                                                        if ($unchemin and (strpos ($partie_cle, $unchemin) !== false)) {
     257                                                                break 2;    // trouvé : sort du foreach et du switch et poursuit le test des autres conditions
     258                                                        }
     259                                                }
     260                                                continue 2;     // échec : passe à la $cle suivante
     261                                        case '==' :
     262                                        case 'egal' :
     263                                        case 'equal':
     264                                                foreach ($chemins as $unchemin) {
     265                                                        if ($unchemin == $partie_cle) {
     266                                                                break 2;    // trouvé : sort du foreach et du switch et poursuit le test des autres conditions
     267                                                        }
     268                                                }
     269                                                continue 2;     // échec : passe à la $cle suivante
     270                                        case 'regexp':
     271                                                if ($chemin and ($danslechemin = preg_match (",$chemin,i", $partie_cle))) {
     272                                                        break;    // trouvé : poursuit le test des autres conditions
     273                                                }
     274                                                continue 2;    // échec : passe à la clé suivante
     275                                        default:
     276                                                spip_log ("Méthode '$methode_chemin' pas prévue pour le filtrage par le chemin", 'cachelab_erreur');
     277                                                return null;
     278                                }
     279                        }
     280
     281                        // pour les filtres suivants on a besoin du contenu du cache
     282                        if ($cle_objet or $plusfunc) {
     283                                global $Memoization;
     284                                $data = $Memoization->get (substr ($cle, $len_prefix));
     285                                if (!$data or !is_array ($data)) {
     286                                        spip_log ("clé=$cle : data est vide ou n'est pas un tableau : " . print_r ($data, 1), 'cachelab_erreur');
     287                                        continue;
     288                                }
     289
     290                                // 3eme filtre : par une valeur dans l'environnement
     291                                if ($cle_objet
     292                                        and (!isset($data['contexte'][$cle_objet])
     293                                                or ($data['contexte'][$cle_objet] != $id_objet))) {
     294                                        continue;
     295                                }
     296
     297                                // 4eme filtre : par une extension
     298                                if ($plusfunc
     299                                        and !$plusfunc($action, $conditions, $options, $cle, $data, $stats)) {
     300                                        continue;
     301                                }
     302                        }
     303                        // Dès qu'une des conditions composée est satisfaite on sort de la boucle
     304                        $cible = true;
     305                        break;
     306                }
     307                if (!$cible) {
     308                        // si on est sorti suite sans avoir trouvé on passe au cache suivant
    194309                        continue;
    195                         }
    196                 }
    197 
    198                 // 2eme filtrage : par le chemin
    199                 if ($chemin) {
    200                         switch ($partie_chemin) {
    201                         case 'tout':
    202                         case 'chemin':
    203                                 $partie_cle = $cle;
    204                                 break;
    205                         case 'fichier':
    206                                 $parties = explode('/', $cle);
    207                                 $partie_cle = array_pop($parties);
    208                                 break;
    209                         case 'dossier':
    210                                 $parties = explode('/', $cle);
    211                                 $parties = array_pop($parties);
    212                                 $partie_cle = array_pop($parties);
    213                                 break;
    214                         default:
    215                                 spip_log("Option partie_chemin incorrecte : '$partie_chemin'", 'cachelab_erreur');
    216                                 return null;
    217                         }
    218                         // mémo php : « continue resumes execution just before the closing curly bracket ( } ),
    219                         // and break resumes execution just after the closing curly bracket. »
    220                         switch ($methode_chemin) {
    221                         case 'strpos':
    222                                 foreach ($chemins as $unchemin) {
    223                                         if ($unchemin and (strpos($partie_cle, $unchemin) !== false)) {
    224                                                 break 2;        // trouvé : sort du foreach et du switch et poursuit le test des autres conditions
    225                                         }
    226                                 }
    227                                 continue 2;      // échec : passe à la $cle suivante
    228                         case '==' :
    229                         case 'egal' :
    230                         case 'equal':
    231                                 foreach ($chemins as $unchemin) {
    232                                         if ($unchemin==$partie_cle) {
    233                                                 break 2;        // trouvé : sort du foreach et du switch et poursuit le test des autres conditions
    234                                         }
    235                                 }
    236                                 continue 2;      // échec : passe à la $cle suivante
    237                         case 'regexp':
    238                                 if ($chemin and ($danslechemin = preg_match(",$chemin,i", $partie_cle))) {
    239                                         break;  // trouvé : poursuit le test des autres conditions
    240                                 }
    241                                 continue 2;     // échec : passe à la clé suivante
    242                         default:
    243                                 spip_log("Méthode '$methode_chemin' pas prévue pour le filtrage par le chemin", 'cachelab_erreur');
    244                                 return null;
    245                         };
    246                 }
    247 
    248                 // pour les filtres suivants on a besoin du contenu du cache
    249                 if ($cle_objet or $plusfunc) {
    250                         global $Memoization;
    251                         $data = $Memoization->get(substr ($cle, $len_prefix));
    252                         if (!$data or !is_array ($data)) {
    253                                 spip_log ("clé=$cle : data est vide ou n'est pas un tableau : " . print_r ($data, 1), 'cachelab_erreur');
    254                                 continue;
    255                         };
    256 
    257                         // 3eme filtre : par une valeur dans l'environnement
    258                         if ($cle_objet
    259                                 and (!isset($data['contexte'][$cle_objet])
    260                                         or ($data['contexte'][$cle_objet] != $id_objet))) {
    261                                 continue;
    262                         }
    263 
    264                         // 4eme filtre : par une extension
    265                         if ($plusfunc
    266                                 and !$plusfunc($action, $conditions, $options, $cle, $data, $stats)) {
    267                                 continue;
    268                         }
    269                 }
    270 
     310                }
    271311                // restent les cibles atteintes
    272312                $stats['nb_cible']++;
  • _plugins_/cachelab/trunk/paquet.xml

    r119194 r122459  
    22        prefix="cachelab"
    33        categorie="performance"
    4         version="1.0.0"
     4        version="1.1.0"
    55        etat="test"
    66        compatibilite="[3.0.0;3.3.*]"
Note: See TracChangeset for help on using the changeset viewer.