par
Beethoven » 14 nov. 2018, 12:45
Bonjour, je voudrais mettre un verrou sur un fichier, pour que tant que le verrou n'est pas libéré, être au courant pour mettre en attente le 2ème traitement sur ce même fichier.
Je pensais que les verrous en écriture gèrent le fait de ne pas pouvoir écrire à 2 en même temps et donc, que si on met un verrou en écriture sur un fichier, on ne peut pas en mettre un deuxième tant que le premier n'est pas libéré.
j'ai fait le test ci-dessous, mais il montre que l'on peut successivement acquérir un verrou en écriture sur un même fichier sans qu'il ne soit libéré entre 2.
en effet voici les log retourné par l'exécution de ce script sur apache linux et PHP 5.6 :
- ------ begin ---------
lock_for_writing
file opened
verrous mis
verrous mis
file_put_content: ok
file_put_contents_locking file opened
verrous relach\xc3\xa9
file_put_contents return = fait
et voici le code :
monTest appel une fonction file_put_contents_locking qui en retour de appel une fonction générique lock_for_writing qui lock 2 fois de suite un même fichier en écriture sans problème (voir //1 et //2) :
Code : Tout sélectionner
<?php
class maClass
{
public function lock_for_writing($name, $handler)
{
error_log("lock_for_writing", 0);
$filename = sys_get_temp_dir().'/'.$name.'.lock';
$file = fopen($filename, 'w');
if ($file === false) {
error_log("fopen return false", 0);
return false;
}else{
error_log("file opened", 0);
}
//1
$lock = flock($file, LOCK_EX);//pour acquérir un verrou exclusif (écriture)
if (!$lock) {//il y a une erreur? (ou le fichier est locké?)
fclose($file);
error_log("flock erreur ou fichier locké", 0);
return false;
}else{
error_log("verrous mis", 0);
}
//2
$lock = flock($file, LOCK_EX);//pour acquérir un verrou exclusif (écriture)
if (!$lock) {//il y a une erreur? (ou le fichier est locké?)
fclose($file);
error_log("flock erreur ou fichier locké", 0);
return false;
}else{
error_log("verrous mis", 0);
}
// on arrive ici si le vérrou est mis
$result = $handler();//on exécute la tâche a faire (passée en paramettre dans $handler) une fois le vérrou mis
//une fois la tâche exécutée on libère le verrou
$lock2 = flock($file, LOCK_UN);//pour libérer un verrou (partagé ou exclusif).
if (!$lock2) {//il y a une erreur? (ou le fichier est locké?)
error_log("verrous non relaché", 0);
}else{
error_log("verrous relaché", 0);
}
fclose($file);
return $result;
}
//appel de la fonction générique en passant la fonction à éxécuter en paramettre
public function file_put_contents_locking($name, $string)
{
return $this->lock_for_writing($name, function() use ($name, $string) {
$filename = sys_get_temp_dir().'/'.$name.'.lock';
error_log("file_put_content: ".$string, 0);
//return file_put_contents($filename, $string);
$file = fopen($filename, 'w');
if ($file === false) {
error_log("file_put_contents_locking fopen return false", 0);
return "pas fait";
}else{
error_log("file_put_contents_locking file opened", 0);
}
//ftruncate($file, 0); // effacement du contenu
fwrite($file, $string);
fflush($file);
return "fait";
});
}
public function monTest()
{
error_log("------ begin ---------", 0);
$ret = $this->file_put_contents_locking("lefichier", "ok");
error_log("file_put_contents return = ".strval($ret), 0);
}
}
$mc = new maClass;
$mc->monTest();
?>
Merci de votre aide

Bonjour, je voudrais mettre un verrou sur un fichier, pour que tant que le verrou n'est pas libéré, être au courant pour mettre en attente le 2ème traitement sur ce même fichier.
Je pensais que les verrous en écriture gèrent le fait de ne pas pouvoir écrire à 2 en même temps et donc, que si on met un verrou en écriture sur un fichier, on ne peut pas en mettre un deuxième tant que le premier n'est pas libéré.
j'ai fait le test ci-dessous, mais il montre que l'on peut successivement acquérir un verrou en écriture sur un même fichier sans qu'il ne soit libéré entre 2.
en effet voici les log retourné par l'exécution de ce script sur apache linux et PHP 5.6 :
[list]------ begin ---------
lock_for_writing
file opened
verrous mis
verrous mis
file_put_content: ok
file_put_contents_locking file opened
verrous relach\xc3\xa9
file_put_contents return = fait[/list]
et voici le code :
monTest appel une fonction file_put_contents_locking qui en retour de appel une fonction générique lock_for_writing qui lock 2 fois de suite un même fichier en écriture sans problème (voir //1 et //2) :
[code]<?php
class maClass
{
public function lock_for_writing($name, $handler)
{
error_log("lock_for_writing", 0);
$filename = sys_get_temp_dir().'/'.$name.'.lock';
$file = fopen($filename, 'w');
if ($file === false) {
error_log("fopen return false", 0);
return false;
}else{
error_log("file opened", 0);
}
//1
$lock = flock($file, LOCK_EX);//pour acquérir un verrou exclusif (écriture)
if (!$lock) {//il y a une erreur? (ou le fichier est locké?)
fclose($file);
error_log("flock erreur ou fichier locké", 0);
return false;
}else{
error_log("verrous mis", 0);
}
//2
$lock = flock($file, LOCK_EX);//pour acquérir un verrou exclusif (écriture)
if (!$lock) {//il y a une erreur? (ou le fichier est locké?)
fclose($file);
error_log("flock erreur ou fichier locké", 0);
return false;
}else{
error_log("verrous mis", 0);
}
// on arrive ici si le vérrou est mis
$result = $handler();//on exécute la tâche a faire (passée en paramettre dans $handler) une fois le vérrou mis
//une fois la tâche exécutée on libère le verrou
$lock2 = flock($file, LOCK_UN);//pour libérer un verrou (partagé ou exclusif).
if (!$lock2) {//il y a une erreur? (ou le fichier est locké?)
error_log("verrous non relaché", 0);
}else{
error_log("verrous relaché", 0);
}
fclose($file);
return $result;
}
//appel de la fonction générique en passant la fonction à éxécuter en paramettre
public function file_put_contents_locking($name, $string)
{
return $this->lock_for_writing($name, function() use ($name, $string) {
$filename = sys_get_temp_dir().'/'.$name.'.lock';
error_log("file_put_content: ".$string, 0);
//return file_put_contents($filename, $string);
$file = fopen($filename, 'w');
if ($file === false) {
error_log("file_put_contents_locking fopen return false", 0);
return "pas fait";
}else{
error_log("file_put_contents_locking file opened", 0);
}
//ftruncate($file, 0); // effacement du contenu
fwrite($file, $string);
fflush($file);
return "fait";
});
}
public function monTest()
{
error_log("------ begin ---------", 0);
$ret = $this->file_put_contents_locking("lefichier", "ok");
error_log("file_put_contents return = ".strval($ret), 0);
}
}
$mc = new maClass;
$mc->monTest();
?>[/code]
Merci de votre aide ;)