From 860ab08b3afc71ecc759d350d2f070c4faaeea24 Mon Sep 17 00:00:00 2001 From: Fil <fil@rezo.net> Date: Sat, 19 Nov 2005 01:15:56 +0000 Subject: [PATCH] etre un peu moins bourrin sur la gestion des stats --- .gitattributes | 1 + ecrire/inc_cron.php3 | 25 ++++--- ecrire/inc_popularites.php3 | 74 +++++++++++++++++++ ecrire/inc_version.php3 | 2 +- ecrire/inc_visites.php3 | 138 ++++++++++-------------------------- 5 files changed, 131 insertions(+), 109 deletions(-) create mode 100644 ecrire/inc_popularites.php3 diff --git a/.gitattributes b/.gitattributes index 7faa50c129..576f575d1c 100644 --- a/.gitattributes +++ b/.gitattributes @@ -289,6 +289,7 @@ ecrire/inc_messagerie.php -text ecrire/inc_mini_nav.php -text ecrire/inc_minipres.php -text ecrire/inc_naviguer.php -text +ecrire/inc_popularites.php3 -text ecrire/inc_spip_cal.php -text ecrire/inc_spip_image.php -text ecrire/inc_statistiques_repartition.php -text diff --git a/ecrire/inc_cron.php3 b/ecrire/inc_cron.php3 index 59297d7970..07182a515f 100644 --- a/ecrire/inc_cron.php3 +++ b/ecrire/inc_cron.php3 @@ -50,11 +50,11 @@ if (!defined("_ECRIRE_INC_VERSION")) return; // le fichier de verrouillage (avec la valeur absolue du code de retour). // La fonction executant la tache est un homonyme de prefixe "cron_" // Le fichier homonyme de prefixe "inc_" et de suffixe _EXTENSION_PHP -// est automatiquement charge et est supposee la definir si ce n'est fait ici. +// est automatiquement charge si besoin, et est supposee la definir si ce +// n'est fait ici. function spip_cron($taches = array()) { $t = time(); - if (@file_exists(_FILE_MYSQL_OUT) AND ($t - @filemtime(_FILE_MYSQL_OUT) < 300)) return; @@ -71,7 +71,6 @@ function spip_cron($taches = array()) { foreach ($taches as $nom => $periode) { $lock = _DIR_SESSIONS . $nom . '.lock'; $date_lock = @filemtime($lock); - if ($date_lock + $periode < $tmin) { $tmin = $date_lock + $periode; $tache = $nom; @@ -84,7 +83,6 @@ function spip_cron($taches = array()) { // pour si peu) else if ($date_lock > $t + 3600) spip_log("Erreur de date du fichier $lock : $date_lock > $t !"); - } if (!$tache) return; @@ -160,8 +158,10 @@ function taches_generales() { $taches_generales['mail']= 3600 * 24 * $GLOBALS['meta']['jours_neuf']; // stats : toutes les 5 minutes on peut vider un panier de visites - if ($GLOBALS['meta']["activer_statistiques"] == "oui") + if ($GLOBALS['meta']["activer_statistiques"] == "oui") { $taches_generales['visites'] = 300; + $taches_generales['popularites'] = 7200; # calcul lourd + } // syndication if ($GLOBALS['meta']["activer_syndic"] == "oui") @@ -222,12 +222,19 @@ function cron_visites($t) { // pour etre prioritaire lors du cron suivant if ($encore) return (0 - $t); - else { - calculer_popularites(); - return 1; - } + + return 1; } +// +// Applique la regle de decroissance des popularites +// +function cron_popularites($t) { + calculer_popularites(); + return 1; +} + + // // Mail des nouveautes // diff --git a/ecrire/inc_popularites.php3 b/ecrire/inc_popularites.php3 new file mode 100644 index 0000000000..e3393e7bbe --- /dev/null +++ b/ecrire/inc_popularites.php3 @@ -0,0 +1,74 @@ +<?php + +/***************************************************************************\ + * SPIP, Systeme de publication pour l'internet * + * * + * Copyright (c) 2001-2005 * + * Arnaud Martin, Antoine Pitrou, Philippe Riviere, Emmanuel Saint-James * + * * + * Ce programme est un logiciel libre distribue sous licence GNU/GPL. * + * Pour plus de details voir le fichier COPYING.txt ou l'aide en ligne. * +\***************************************************************************/ + + +if (!defined("_ECRIRE_INC_VERSION")) return; + + +// +// Popularite, modele logarithmique +// + +function calculer_popularites() { + + // Si c'est le premier appel, ne pas calculer + $t = $GLOBALS['meta']['date_popularites']; + ecrire_meta('date_popularites', time()); + ecrire_metas(); + if (!$t) + return; + + $duree = time() - $t; + // duree de demi-vie d'une visite dans le calcul de la popularite (en jours) + $demivie = 1; + // periode de reference en jours + $periode = 1; + // $a est le coefficient d'amortissement depuis la derniere mesure + $a = pow(2, - $duree / ($demivie * 24 * 3600)); + // $b est la constante multiplicative permettant d'avoir + // une visite par jour (periode de reference) = un point de popularite + // (en regime stationnaire) + // or, magie des maths, ca vaut log(2) * duree journee/demi-vie + // si la demi-vie n'est pas trop proche de la seconde ;) + $b = log(2) * $periode / $demivie; + + // oublier un peu le passe + spip_query("UPDATE spip_articles SET maj=maj, + popularite = popularite * $a"); + + // enregistrer les metas... + list($maxpop, $totalpop) = spip_fetch_array(spip_query( + "SELECT MAX(popularite), SUM(popularite) FROM spip_articles" + )); + ecrire_meta("popularite_max", $maxpop); + ecrire_meta("popularite_total", $totalpop); + + + // Une fois par jour purger les referers du jour ; qui deviennent + // donc ceux de la veille ; au passage on stocke une date_statistiques + // dans spip_meta - cela permet au code d'etre "reentrant", ie ce cron + // peut etre appele par deux bases SPIP ne partageant pas le meme + // _DIR_SESSIONS, sans tout casser... + $aujourdhui = date("Y-m-d"); + if ($date = $GLOBALS['meta']['date_statistiques'] + AND $date != $aujourdhui) + spip_query("UPDATE spip_referers + SET visites_veille=visites_jour, visites_jour=0"); + ecrire_meta('date_statistiques', $aujourdhui); + + // et c'est fini pour cette fois-ci + ecrire_metas(); + return 1; + +} + +?> diff --git a/ecrire/inc_version.php3 b/ecrire/inc_version.php3 index 4086776948..c601601cf8 100644 --- a/ecrire/inc_version.php3 +++ b/ecrire/inc_version.php3 @@ -936,7 +936,7 @@ function cron($gourmand = false) { // Faut-il travailler ? Pas tous en meme temps svp // Au passage si on travaille on bloque les autres - if (spip_touch(_FILE_CRON_LOCK, 1)) { + if (spip_touch(_FILE_CRON_LOCK, 2)) { include_ecrire('inc_cron.php3'); spip_cron(); } diff --git a/ecrire/inc_visites.php3 b/ecrire/inc_visites.php3 index 5f7b0f037c..cd12087ec5 100644 --- a/ecrire/inc_visites.php3 +++ b/ecrire/inc_visites.php3 @@ -13,8 +13,6 @@ if (!defined("_ECRIRE_INC_VERSION")) return; - - ### Pour se dę«arrasser du md5, comment faire ? Un index sur 'referer' ? ### ou alors la meme notion, mais sans passer par des fonctions HEX ? @@ -76,29 +74,33 @@ function calculer_visites($t) { } closedir($dir); - // 2. Manger 1000 fichiers de ces paniers (sans ordre particulier) - $compteur = 1000; + // 2. Manger 100 fichiers de ces paniers (sans ordre particulier) + $compteur = 100; $pasfini = false; foreach ($paniers as $panier) { + spip_log("traite le panier $panier"); $dir = opendir(_DIR_SESSIONS.$panier); while (($item = readdir($dir)) !== false) { + if ($compteur-- < 0) { + $pasfini = true; + break; + } if (is_file($f = _DIR_SESSIONS.$panier.'/'.$item)) { compte_fichier_visite($f, $visites, $visites_a, $referers, $referers_a, $articles); @unlink($f); } - if (-- $compteur <= 0) { - $pasfini = true; - break; - } } // effacer le panier, sauf si on a atteint la limite de fichiers vus closedir($dir); - if (!$pasfini) + if ($pasfini) + break; + else @rmdir(_DIR_SESSIONS.$panier); } if (!$visites) return; + spip_log("analyse $visites visites"); // Maintenant on dispose de plusieurs tableaux qu'il faut ventiler dans // les tables spip_visites, spip_visites_articles, spip_referers @@ -112,9 +114,6 @@ function calculer_visites($t) { spip_query("UPDATE spip_visites SET visites = visites+$visites WHERE date='$date'"); - // pour calcul_mysql_in - include_ecrire('inc_db_mysql.php3'); - // 2. les visites des articles (en deux passes pour minimiser // le nombre de requetes) if ($articles) { @@ -126,19 +125,34 @@ function calculer_visites($t) { . ")"); // enregistrer les visites dans les deux tables - $ar = array(); # tableau num -> liste des articles ayant num visites - foreach($visites_a as $id_article => $num) + $ar = array(); # tableau num -> liste des articles ayant num visites + $tous = array();# liste des articles ayant des visites + foreach($visites_a as $id_article => $num) { $ar[$num][] = $id_article; - foreach ($ar as $num => $liste) { - $in = calcul_mysql_in('id_article', join(',',$liste)); - spip_query("UPDATE spip_visites_articles - SET visites = visites+$num - WHERE date='$date' AND $in"); - spip_query("UPDATE spip_articles - SET visites = visites+$num, maj = maj - WHERE $in"); - ## Ajouter un JOIN sur le statut de l'article ? + $tous[] = $id_article; } + $tous = calcul_mysql_in('id_article', join(',', $tous)); + $sum = ''; + $in = array(); + foreach ($ar as $num => $liste) + $sum .= ' + '.$num.'*' + . calcul_mysql_in('id_article', join(',',$liste)); + + # pour les popularites ajouter 1 point par referer + $sumref = ''; + if ($referers_a) + $sumref = ' + '.calcul_mysql_in('id_article', + join(',',array_keys($referers_a))); + + spip_query("UPDATE spip_visites_articles + SET visites = visites $sum + WHERE date='$date' AND $tous"); + spip_query("UPDATE spip_articles + SET visites = visites $sum$sumref, + popularite = popularite $sum, + maj = maj + WHERE $tous"); + ## Ajouter un JOIN sur le statut de l'article ? } // 3. Les referers du site @@ -158,8 +172,8 @@ function calculer_visites($t) { // ajouter les visites foreach ($ar as $num => $liste) { spip_query("UPDATE spip_referers - SET visites = visites+$num, visites_jour = visites_jour+$num - WHERE ".calcul_mysql_in('referer_md5',join(',',$liste))); + SET visites = visites+$num, visites_jour = visites_jour+$num + WHERE ".calcul_mysql_in('referer_md5',join(',',$liste))); } } @@ -188,82 +202,8 @@ function calculer_visites($t) { } } - // 5. Calculer les popularites ; ici c'est presque comme les visites, - // sauf qu'on ajoute 1 point par referer - if ($visites_a) { - $points = array(); - foreach ($visites_a as $id_article => $v) { - // ajouter un point aux articles ayant un referer - if ($r = $referers_a[$id_article]) - $v += 1; // ou array_pop($r); - $points[$v][] = $id_article; - } - foreach ($points as $num => $liste) { - spip_query("UPDATE spip_articles - SET popularite = popularite + $num, maj = maj - WHERE ".calcul_mysql_in('id_article', join(',',$liste))); - } - } - // S'il reste des fichiers a manger, le signaler pour reexecution rapide return $pasfini; } - - -// -// Popularite, modele logarithmique -// - -function calculer_popularites() { - include_ecrire('inc_meta.php3'); - - // Si c'est le premier appel, ne pas calculer - $t = $GLOBALS['meta']['date_popularites']; - ecrire_meta('date_popularites', time()); - ecrire_metas(); - if (!$t) - return; - - $duree = time() - $t; - // duree de demi-vie d'une visite dans le calcul de la popularite (en jours) - $demivie = 1; - // periode de reference en jours - $periode = 1; - // $a est le coefficient d'amortissement depuis la derniere mesure - $a = pow(2, - $duree / ($demivie * 24 * 3600)); - // $b est la constante multiplicative permettant d'avoir - // une visite par jour (periode de reference) = un point de popularite - // (en regime stationnaire) - // or, magie des maths, ca vaut log(2) * duree journee/demi-vie - // si la demi-vie n'est pas trop proche de la seconde ;) - $b = log(2) * $periode / $demivie; - - // oublier un peu le passe - spip_query("UPDATE spip_articles SET maj=maj, popularite = popularite * $a"); - - // enregistrer les metas... - list($maxpop, $totalpop) = spip_fetch_array(spip_query("SELECT MAX(popularite), SUM(popularite) FROM spip_articles")); - ecrire_meta("popularite_max", $maxpop); - ecrire_meta("popularite_total", $totalpop); - - - // Une fois par jour purger les referers du jour ; qui deviennent - // donc ceux de la veille ; au passage on stocke une date_statistiques - // dans spip_meta - cela permet au code d'etre "reentrant", ie ce cron - // peut etre appele par deux bases SPIP ne partageant pas le meme - // _DIR_SESSIONS, sans tout casser... - $aujourdhui = date("Y-m-d"); - if ($date = $GLOBALS['meta']['date_statistiques'] - AND $date != $aujourdhui) { - spip_query("UPDATE spip_referers SET visites_veille=visites_jour, visites_jour=0"); - } - ecrire_meta('date_statistiques', $aujourdhui); - - // et c'est fini pour cette fois-ci - ecrire_metas(); - return 1; - -} - ?> -- GitLab