Le plugin hash_documents

Le nombre de documents dans le répertoire IMG/{$ext}/ du site peut devenir beaucoup trop important et avoir un impact sur les performances du système de fichiers du serveur. La solution proposée par ce plugin est de « hasher » le répertoire IMG/.

De manière à limiter le nombre d’inode dans chaque sous-dossier de IMG/, on répartit automatiquement les fichiers dans des sous-sous-répertoires. La structure passe ainsi de
IMG/mp3/fichier-son.mp3
à
IMG/mp3/a/b/c/fichier-son.mp3

Ce plugin s’occupe de tout pour vous.

En SPIP 2, une page ecrire/?exec=hash_documents permet d’aller hasher tous les documents déjà installés (mais il n’est pas indispensable de l’utiliser pour que ça fonctionne). On peut à tout moment revenir en arrière (grâce à cette même page). En SPIP3, elle est accessible via la page d’administration des plugins (ecrire/?exec=configurer_hasher).

Dans tous les cas, la désactivation du plugin n’empêche pas le site de fonctionner normalement.

Ci-dessous, les explications techniques :

Structure du hashage

le sous-répertoire a/b/c/ doit être calculé de manière à ce que la répartition des documents soit homogène et prévisible. On utilisera pour ce faire une fonction de hashage très simple consistant à prendre les n premiers caractères du md5 du nom du fichier.

md5 ayant une représentation hexa, le nombre de sous-répertoires ainsi créés sera de l’ordre de 16^n ; pour répartir correctement un million de documents, on a les possibilités suivantes :

— n=1 16 répertoires * 62500 docs
— n=2 256 rép * 3900 docs
— n=3 4096 rép * 244 docs

Dans cette implémentation, on utilise 3 niveaux de sous-répertoires : pour un fichier d’origine situé dans IMG/{$ext}/xxxx.ext, le hasher consiste à prendre les 3 premiers caractères (a, b, c) du md5(xxxx.ext), et déplacer le fichier dans IMG/$ext/a/b/c/xxxx.ext.

fonction : function hasher_adresser_document(xxxx.ext)

Déplacement d’un document

fonction : function hasher_deplacer_document($id_document) {}

Cette fonction a pour rôle de déplacer un document proprement de sa position non hashée vers sa position hashée. Tous les contrôles d’erreur sont mis en place afin de garantir que tout se passe bien : si la création du sous-répertoire échoue, par exemple, ou si la connexion à la base de données est tombée, il faut pouvoir reprendre.

Elle appelle hasher_adresser_document()

Conversion « batch »

fonction : function hasher_deplacer_n_documents($n) {}

Cette fonction prend les n documents non hashés les plus récents, et appelle hasher_deplacer_document() sur chacun d’eux. Elle renvoie un array() contenant les id_document des documents qu’elle a déplacés.

Elle peut servir à convertir l’existant (on l’appelle répétitivement jusqu’à épuisement du stock), ou juste après un upload (en SPIP 1.9.2, car en SPIP 2 le cas de l’upload est géré nativement via le pipeline ad hoc), ou un spip2spip, afin de hasher les documents qu’on vient d’ajouter [1].

Elle peut aussi être appelée depuis la page ecrire/?exec=hash_documents

Gestion de redirection

Lorsqu’un document a été déplacé, on souhaite qu’un hit sur son ancienne adresse renvoie vers la nouvelle adresse, avec un code HTTP 301 Moved Permanently (redirection définitive).

Ceci permet, d’une part, de gérer proprement la migration ; d’autre part, ça implique qu’il n’est pas indispensable de hasher les documents juste après l’upload, donc beaucoup de souplesse dans l’intégration.

On va pour ce faire ajouter un .htaccess dans le répertoire IMG/ qui lancera, sur les fichiers non trouvés, un script de redirection écrit en PHP ; ce dernier calculera l’adresse hashée du document demandé, vérifiera si ce document est présent, et en fonction du résultat renverra soit un code 301 vers ce document, soit un 404 Not Found.

Le script PHP est le fichier hash_404.php présent dans le plugin ; la seule petite difficulté pour son activation, c’est qu’il nécessite la création d’un .htaccess spécifique dans le répertoire IMG/ contenant le code suivant :

RewriteEngine On
RewriteCond %{REQUEST_FILENAME} !-f
# Si spip est range a la racine du domaine
RewriteRule .* ../index.php?action=hash_404 [L] 
# Pour un mutualise, vaut mieux travailler en url absolue
#RewriteRule .* /index.php?action=hash_404 [L]

En fonction de la configuration technique de l’hébergeur, il faudra peut-être adapter un peu ce .htaccess.

Compatibilité

Il est important de noter que la structure proposée pour le code offre nativement une grande compatibilité, puisque, une fois les documents hashés, on peut retirer tout le code de hachage sans impact sur le fonctionnement.

On a pris soin de ne pas utiliser de fonctions « fragiles » de SPIP, qui changeraient d’une version à l’autre, afin que ce plugin soit compatible de SPIP 1.9.2 aux SPIP futurs.

La seule difficulté à prendre en compte est que le nommage des documents dans la table spip_documents a changé entre SPIP 1.9.2 et la série SPIP 2.0. En SPIP 1.9.2, en effet, spip_documents.fichier contenait une chaîne de la forme IMG/jpg/postcards.jpg, tandis qu’en SPIP 2 on a simplement jpg/postcards.jpg (le IMG/ a été supprimé).

Le plugin fonctionne nativement avec les deux représentations (avec ou sans IMG/).

Réversibilité

Les fonctions de hashage sont réversibles : un paramètre $rev permet de revenir à la structure « à plat ». Cela permet de revenir en arrière si finalement on ne souhaitait pas utiliser ce système, ou pour en utiliser un autre. Cela a aussi permis de tester le plugin, lors de son développement, en faisant des allers-retours.

Notes

[1Patch à appliquer aux fonctions qui ajoutent des fichiers dans spip_documents :

// hasher les documents
include_spip('hash_fonctions');
if (function_exists('hasher_deplacer_n_documents')) {
  hasher_deplacer_n_documents(10);
}

Discussion

Aucune discussion

Ajouter un commentaire

Avant de faire part d’un problème sur un plugin X, merci de lire ce qui suit :

  • Désactiver tous les plugins que vous ne voulez pas tester afin de vous assurer que le bug vient bien du plugin X. Cela vous évitera d’écrire sur le forum d’une contribution qui n’est finalement pas en cause.
  • Cherchez et notez les numéros de version de tout ce qui est en place au moment du test :
    • version de SPIP, en bas de la partie privée
    • version du plugin testé et des éventuels plugins nécessités
    • version de PHP (exec=info en partie privée)
    • version de MySQL / SQLite
  • Si votre problème concerne la partie publique de votre site, donnez une URL où le bug est visible, pour que les gens puissent voir par eux-mêmes.
  • En cas de page blanche, merci d’activer l’affichage des erreurs, et d’indiquer ensuite l’erreur qui apparaît.

Merci d’avance pour les personnes qui vous aideront !

Par ailleurs, n’oubliez pas que les contributeurs et contributrices ont une vie en dehors de SPIP.

Qui êtes-vous ?
[Se connecter]

Pour afficher votre trombine avec votre message, enregistrez-la d’abord sur gravatar.com (gratuit et indolore) et n’oubliez pas d’indiquer votre adresse e-mail ici.

Ajoutez votre commentaire ici

Ce champ accepte les raccourcis SPIP {{gras}} {italique} -*liste [texte->url] <quote> <code> et le code HTML <q> <del> <ins>. Pour créer des paragraphes, laissez simplement des lignes vides.

Ajouter un document

Suivre les commentaires : RSS 2.0 | Atom