Pools
La chose la plus importante à comprendre à propos de l’API Apache est le concept de pool. Un pool est une collection regroupant des ressources (descripteurs de fichiers, mémoire, processus fils, sockets, tubes, etc.) qui seront libérées à la destruction du pool. Quasiment toutes les ressources utilisées par Apache sont placées dans des pools et, à moins d’avoir de bonnes raisons de le faire, on ne peut les éviter.
Une caractéristique intéressantes des ressources contenues dans les pools est que la plupart d’entre elles ne peuvent être libérées que lorsque le pool est supprimé. Les pools peuvent contenir des sous-pools qui, eux-mêmes, peuvent contenir des sous-sous-pools, etc. Lorsqu’un pool est supprimé, tous ses sous-pools le sont également.
Assez naturellement, Apache crée un pool lorsqu’il démarre, à partir duquel d’autres pools seront créés. Les informations sur la configuration sont stockées dans ce pool (elles sont donc détruites et recréées lorsque le serveur est relancé par un kill ). Le niveau de pool suivant est créé pour chaque connexion reçue par Apache et supprimé à la fin de celle-ci. Comme une connexion peut s’étendre sur plusieurs requêtes, un nouveau pool est créé (et supprimé) pour chaque requête. Au cours du traitement d’une requête, les différents modules créent leurs propres pools ; certains produisent également des sous-requêtes, qui sont passées aux mécanismes de l’API comme s’il s’agissait de vraies requêtes. On a accès à chacun de ces pools via les structures qui leur correspondent (la structure de connexion, la structure de requête, etc.).
Sachant tout cela, nous pouvons établir de façon plus précise les moments où vous ne devez pas utiliser un pool : lorsque la durée de vie de la ressource en question ne correspond pas à celle d’un pool. Si vous avez besoin d’un stockage temporaire (ou de fichiers, etc.), vous pouvez créer un sous-pool dans un pool approprié (le pool de requête est le candidat le plus fréquent) et le supprimer lorsque vous n’en avez plus besoin : les durées de vie plus courtes que celle du pool peuvent être gérées facilement. Le seul exemple à notre connaissance où il n’existait pas de pool approprié dans Apache 1.3 était pour le code de gestion des listeners ( copy_listeners() et close_unused_listeners() dans http_main.c ), qui avait une durée de vie plus longue que le pool de plus haut niveau !
Les pools présentent un certain nombre d’avantages, dont le plus évident est que les modules peuvent utiliser des ressources sans devoir se soucier du moment et du moyen de les libérer. Ainsi, lorsque Apache traite une condition d’erreur, il se contente de se sortir d’affaire, détruisant le pool associé à la requête erronée et confiant dans le fait que tout sera proprement nettoyé. Comme chaque instance d’Apache peut traiter de nombreuses requêtes, cette fonctionnalité est vitale pour la fiabilité du serveur. Les pools apparaissent quasiment partout dans l’API d’Apache, comme nous le verrons dans ce chapitre. Ils sont définis dans le fichier alloc.h :
typedef struct pool pool;
La véritable définition de struct pool se trouve dans alloc.c, mais aucun module n’en aura jamais besoin : tout ce que voient les modules est un pointeur vers une telle structure, qu’ils passent ensuite aux fonctions qui en ont besoin.
Comme de nombreux autres aspects d’Apache, les pools sont configurables : vous pouvez ajouter votre propre gestion de ressource à un pool, ce qui consiste essentiellement à enregistrer des fonctions de nettoyage (voir l’API pool plus loin dans ce chapitre).