XML et flock

XML et flock - PHP - Programmation

Marsh Posté le 20-07-2010 à 22:19:48    

Bonsoir à tous !
 
J'ai le petit problème suivant :
J'ai sur mon serveur un fichier xml que je traite avec simplexml. Jusque là, aucun soucis.
Maintenant il s'avère que je peux avoir plusieurs scripts qui tournent en même temps sur mon serveur et qui cherchent à modifier le fichier (en faisant +1 sur une donnée par exemple)
 
Le problème est bien entendu que si j'ai deux scripts qui ouvrent le fichier simultanément , et bien au final je n'aurai qu'un +1 si tenté que l'écriture par le premier script se fasse après l'ouverture du fichier par le second.
 
J'ai cherché sur internet, et je suis tombé sur la fonction flock qui permettrait de résoudre le problème (je n'ai pas encore testé). Ceci pour des fichiers ouverts via fopen. Le problème est que je n'ouvre pas mon fichier avec fopen, puisque je l'ouvre via la fonction simplexml_load_file (d'ailleurs je ne suis pas parvenu à trouver le fonctionnement exact de cette fonction, que fait-elle (ouverture/lecture ou ouverture/lecture/fermeture ?).
 
Dois-je faire un fopen, récupérer le contenu de mon fichier (en faisant gaffe aux sauts de ligne et tout le tralala), balancer un flock jusqu'à plus besoin ?
 
Et le flock est-il bien préconiser dans de tels cas ?
 
Merci d'avance :)

Reply

Marsh Posté le 20-07-2010 à 22:19:48   

Reply

Marsh Posté le 21-07-2010 à 09:44:12    

Si tu souhaites utiliser flock(), tu peux très bien lire et écrire le contenu de ton fichier XML avec les fonctions fopen(), fread(), fwrite() et fclose(). Il suffit d'utiliser simplexml_load_string() au lieu de la version *_file().
 
Tu peux également générer un fichier verrou. Par exemple, si ton fichier se nomme whatever.xml, ton script génère un fichier whatever.xml.lock. Il le supprime lorsqu'il a terminé son travail. Ainsi, il suffit de tester l'existence de ce fichier pour savoir si un autre script n'est pas déjà en train de travailler sur le fichier.
 


---------------
-- Debian -- Le système d'exploitation universel | Le gras c'est la vie! | /(bb|[^b]{2})/
Reply

Marsh Posté le 21-07-2010 à 22:35:33    

dwogsi a écrit :

Si tu souhaites utiliser flock(), tu peux très bien lire et écrire le contenu de ton fichier XML avec les fonctions fopen(), fread(), fwrite() et fclose(). Il suffit d'utiliser simplexml_load_string() au lieu de la version *_file().


J'ai essayé ceci. Je me suis donc penché sur le fonctionnement de la fonction flock(). Le problème est que même l'exemple suivant (trouvé ici http://fr.php.net/manual/fr/function.flock.php) ne fonctionne pas :
Voici l'exemple en question

Code :
  1. <?php
  2. //1st script
  3. $file_handle = fopen('file.test', 'r+');
  4. flock($file_handle, LOCK_EX); //lock the file
  5. sleep(10); //sleep 10 seconds
  6. fclose($file_handle); //close and unlock the file
  7. ?>
  8. <?php
  9. //2nd script
  10. $file_handle = fopen('file.test', 'r+');
  11. flock($file_handle, LOCK_EX); //lock the file
  12. fclose($file_handle); //close and unlock the file
  13. ?>


 
Lorsque je lance dans des pages différentes les 2 scripts (le premier avant le second), et bien le second se termine immédiatement (un var_dump m'indique que le flock du second script retourne true)
 
 
 
 
 
 
 

dwogsi a écrit :


Tu peux également générer un fichier verrou. Par exemple, si ton fichier se nomme whatever.xml, ton script génère un fichier whatever.xml.lock. Il le supprime lorsqu'il a terminé son travail. Ainsi, il suffit de tester l'existence de ce fichier pour savoir si un autre script n'est pas déjà en train de travailler sur le fichier.


 
Je me suis donc dit que j'allais opté pour cette solution !
 
J'ai cependant un problème avec mon script
 
Le voici :
 
 

Code :
  1. <?php
  2. function simplexml_load_lock_file($file,$lock=true){
  3. // $file est l'adresse du fichier
  4. // $lock est un booléen permettant de savoir si l'on doit verrouiller le fichier
  5. // Adresse du fichier "verrou"
  6. $file_lock=$file.'.lock';
  7. // On attend que le fichier se délock (ceci est sauté si il est délocké lors de l'ouverture du fichier)
  8. $i=0;
  9. while(is_file($file_lock)){
  10.  // On attends 10ms
  11.  usleep(10*1000);
  12.  $i++;
  13.  // Si on a passé trop de temps en attente (15s), on arrete  
  14.  if($i>1500){
  15.  return;
  16.  }
  17. }
  18. // Quand on est arrivé ici, c'est que le fichier auquel on veut accéder est délocké
  19. if($lock){
  20.  // On crée le fichier de lock
  21.  $lock_file=fopen($file_lock,'a');
  22.  fclose($lock_file);
  23. }
  24. $data=simplexml_load_file($file);
  25. return $data;
  26. }
  27. function simplexml_load_unlock_file($file){
  28. // $file est l'adresse du fichier
  29. $file_lock=$file.'.lock';
  30. @unlink($file_lock);
  31. }
  32. ?>


 
Et maintenant mes deux scripts de test (que je lance légèrement en décalé dans deux pages différentes) :
 
Celui que je lance en premier

Code :
  1. simplexml_load_lock_file('data.xml');
  2. sleep(10);
  3. simplexml_load_unlock_file('data.xml');


 
Celui que je lance en second

Code :
  1. var_dump(simplexml_load_lock_file('data.xml',false));


 
Et là je ne comprends pas. Le comportement que j'attends et que le deuxième script affiche le var_dump quasi au moment où le premier script se termine
 
Ce qui se passe dans les faits est que le deuxième script se termine bien après, du fait du  

Code :
  1. if($i>1500){
  2.  return;
  3.  }

que j'ai mis là pour éviter un problème de boucle infinie ...
 
Et si je regarde avec mon client ftp pendant le script ce qui se passe, le fichier verrou apparait et disparait bien aux moments voulus ... il semblerait donc que ce soit lié à la fonction is_file qui rend un "faux positif"
 
 
 
 
Pourriez vous m'indiquer d'où viennent mes problèmes ?
 
 
Merci d'avance
 
PS : je suis chez OVH (sait-on jamais, cela concerne peut être leur système de fichier ...)
 
PPS : la version de php que j'utilise est la 5.2.13


Message édité par nisalon_caje le 21-07-2010 à 22:51:37
Reply

Marsh Posté le 22-07-2010 à 10:29:23    

PHP utilise un cache au niveau des fichiers. Je pense que c'est la piste à explorer. c.f page de manuel de is_file() :

Citation :

Note: Les résultats de cette fonction sont mis en cache. Voyez la fonction clearstatcache() pour plus de détails.


Message édité par dwogsi le 22-07-2010 à 10:29:52

---------------
-- Debian -- Le système d'exploitation universel | Le gras c'est la vie! | /(bb|[^b]{2})/
Reply

Marsh Posté le 22-07-2010 à 11:58:10    

merci :)
 
J'avais lu la documentation pourtant, mais ce détail n'avait pas retenu mon attention


---------------
http://nisalon.labrute.com/
Reply

Sujets relatifs:

Leave a Replay

Make sure you enter the(*)required information where indicate.HTML code is not allowed