3 solutions pour gérer la concurrence coté fichiers :
1: tu utilises flock() qui est fait pour ça.
- Attention, ça ne bloque que les process qui vérifient la présence d'un lock avec flock, si quelqu'un accède directement au fichier il réussira.
- Attention aussi si tu utilises le mode "w" lors du fopen() parce que ça écrasera ton fichier *avant* l'appel à flock(), donc avant de savoir si tu as le droit de le manipuler. Si tu veux utiliser du "w" il faut faire le flock() sur un fichier témoin (genre un .lock vide) et pas sur le fichier cible.
2: si tes process ne sont pas coopératifs (tu ne peux pas garantir que tout le monde fasse appel à flock) tu peux te reposer sur l'atomicité du déplacement de fichier sous Unix. Tu travailles ton fichier dans un fichier temporaire puis une fois terminé tu le déplace à la destination finale (en écrasant le précédent).
L'avantage c'est que tu n'as jamais de fichier dans un état corrompu, dans un état intermédiaire, ou de fichier manquant : toute requête de lecture réussira sans défaut. Le désavantage c'est que tu peux avoir plusieurs requêtes d'écriture parallèles. Il y a trois conséquences :
- tu peux faire bosser ton cpu inutilement (tu lances plusieurs constructions du fichier alors que si tu avais attendu la fin de la construction en cours tu n'aurais pas eu besoin des deux autres). Notes que ce n'est pas gravissime dans pas mal de cas (genre pour une reconstruction de cache c'est souvent acceptable)
- si deux constructions/modifications se font en parallèles seule une "gagnera" au final. Tu ne peux pas t'en servir pour faire des ajouts à ton fichier (sinon un seul des deux ajouts se fera). Encore une fois, c'est une contrainte tout à fait acceptable si tu reconstruis entièrement le fichier à partir d'une source tierce à chaque fois (genre à partir d'une bdd).
- si deux constructions/modifications se font en parrallèle, tu n'es pas assuré de laquelle va "gagner" en remplacant le fichier destination en dernier. Il est possible que la construction lancée en premier finisse en dernier, et donc soit celle qui va décider du contenu du fichier destination. Ca par contre ça peut être handicapant, à toi de voir.
3: tu utilises un sémaphore (oui c'est bourrin, mais ça marche)
# Solutions
Posté par Éric (site web personnel) . En réponse au message PHP: Lock sur le system de fichier ?. Évalué à 3.
1: tu utilises flock() qui est fait pour ça.
- Attention, ça ne bloque que les process qui vérifient la présence d'un lock avec flock, si quelqu'un accède directement au fichier il réussira.
- Attention aussi si tu utilises le mode "w" lors du fopen() parce que ça écrasera ton fichier *avant* l'appel à flock(), donc avant de savoir si tu as le droit de le manipuler. Si tu veux utiliser du "w" il faut faire le flock() sur un fichier témoin (genre un .lock vide) et pas sur le fichier cible.
2: si tes process ne sont pas coopératifs (tu ne peux pas garantir que tout le monde fasse appel à flock) tu peux te reposer sur l'atomicité du déplacement de fichier sous Unix. Tu travailles ton fichier dans un fichier temporaire puis une fois terminé tu le déplace à la destination finale (en écrasant le précédent).
L'avantage c'est que tu n'as jamais de fichier dans un état corrompu, dans un état intermédiaire, ou de fichier manquant : toute requête de lecture réussira sans défaut. Le désavantage c'est que tu peux avoir plusieurs requêtes d'écriture parallèles. Il y a trois conséquences :
- tu peux faire bosser ton cpu inutilement (tu lances plusieurs constructions du fichier alors que si tu avais attendu la fin de la construction en cours tu n'aurais pas eu besoin des deux autres). Notes que ce n'est pas gravissime dans pas mal de cas (genre pour une reconstruction de cache c'est souvent acceptable)
- si deux constructions/modifications se font en parallèles seule une "gagnera" au final. Tu ne peux pas t'en servir pour faire des ajouts à ton fichier (sinon un seul des deux ajouts se fera). Encore une fois, c'est une contrainte tout à fait acceptable si tu reconstruis entièrement le fichier à partir d'une source tierce à chaque fois (genre à partir d'une bdd).
- si deux constructions/modifications se font en parrallèle, tu n'es pas assuré de laquelle va "gagner" en remplacant le fichier destination en dernier. Il est possible que la construction lancée en premier finisse en dernier, et donc soit celle qui va décider du contenu du fichier destination. Ca par contre ça peut être handicapant, à toi de voir.
3: tu utilises un sémaphore (oui c'est bourrin, mais ça marche)