13.2.00 flock sur le fichier principal (PB sous win)

This commit is contained in:
Fred Tempez 2024-04-06 09:10:49 +02:00
parent 03d1dacb88
commit 6687c324e5
2 changed files with 65 additions and 66 deletions

View File

@ -166,38 +166,35 @@ class JsonDb extends \Prowebcraft\Dot
error_log('Impossible d\'encoder les données en format JSON.'); error_log('Impossible d\'encoder les données en format JSON.');
return false; return false;
} }
$lockHandle = fopen($this->db, 'r+');
$lockFile = $this->db . '.lock';
$lockHandle = fopen($lockFile, 'w');
if (flock($lockHandle, LOCK_EX)) { if (flock($lockHandle, LOCK_EX)) {
$attempts = 0; $attempts = 0;
$bytesWritten = false; $bytesWritten = false;
while ($attempts < self::MAX_FILE_WRITE_ATTEMPTS && $bytesWritten === false) { while ($attempts < self::MAX_FILE_WRITE_ATTEMPTS && $bytesWritten === false) {
$bytesWritten = file_put_contents($this->db, $jsonData); ftruncate($lockHandle, 0); // Vide le fichier
rewind($lockHandle); // Remet le pointeur au début du fichier
$bytesWritten = fwrite($lockHandle, $jsonData);
if ($bytesWritten === false) { if ($bytesWritten === false) {
$attempts++; $attempts++;
error_log('Erreur d\'écriture (tentative ' . $attempts . ') : impossible de sauvegarder les données.'); error_log('Erreur d\'écriture (tentative ' . $attempts . ') : impossible de sauvegarder les données.');
sleep(self::RETRY_DELAY_SECONDS); // Attendre avant de réessayer sleep(self::RETRY_DELAY_SECONDS); // Attendre avant de réessayer
} }
} }
flock($lockHandle, LOCK_UN); flock($lockHandle, LOCK_UN); // Libérer le verrouillage
fclose($lockHandle); fclose($lockHandle); // Fermer le fichier
if ($bytesWritten === false || $bytesWritten != strlen($jsonData)) { if ($bytesWritten === false || $bytesWritten != strlen($jsonData)) {
error_log('Erreur d\'écriture, les données n\'ont pas été sauvegardées.'); error_log('Erreur d\'écriture, les données n\'ont pas été sauvegardées.');
return false; return false;
} }
} else { } else {
error_log('Impossible d\'obtenir un verrouillage sur le fichier de base de données.'); error_log('Impossible d\'obtenir un verrouillage sur le fichier de base de données.');
fclose($lockHandle); fclose($lockHandle); // Fermer le fichier
return false; return false;
} }
// Supprimer le fichier de verrouillage
if (file_exists($lockFile)) {
unlink($lockFile);
}
return true; return true;
} }
} }

View File

@ -616,60 +616,62 @@ class common
* *
* @return bool Retourne true si l'écriture dans le fichier est réussie, false sinon. * @return bool Retourne true si l'écriture dans le fichier est réussie, false sinon.
*/ */
public static function secureFilePutContents($filename, $data, $options = 0) public static function secureFilePutContents($filename, $data, $options = 0)
{ {
// Vérifier si l'extension du fichier est JSON // Vérifier si l'extension du fichier est JSON
$extension = pathinfo($filename, PATHINFO_EXTENSION); $extension = pathinfo($filename, PATHINFO_EXTENSION);
$encodeJson = strtolower($extension) === 'json'; $encodeJson = strtolower($extension) === 'json';
// Tentatives d'encodage JSON si nécessaire // Tentatives d'encodage JSON si nécessaire
if ($encodeJson) { if ($encodeJson) {
$jsonData = null; $jsonData = null;
$attempts = 0; $attempts = 0;
while ($attempts < self::MAX_JSON_ENCODE_ATTEMPTS) { while ($attempts < self::MAX_JSON_ENCODE_ATTEMPTS) {
$jsonData = json_encode($data, JSON_UNESCAPED_UNICODE | JSON_PRETTY_PRINT); $jsonData = json_encode($data, JSON_UNESCAPED_UNICODE | JSON_PRETTY_PRINT);
if ($jsonData !== false) { if ($jsonData !== false) {
break; // Sortir de la boucle si l'encodage réussit break; // Sortir de la boucle si l'encodage réussit
}
$attempts++;
error_log('Erreur d\'encodage JSON (tentative ' . $attempts . ') : ' . json_last_error_msg());
sleep(self::RETRY_DELAY_SECONDS); // Attendre avant de réessayer
}
if ($jsonData === false) {
error_log('Impossible d\'encoder les données en format JSON.');
return false;
}
} else {
// Pas d'encodage JSON nécessaire
$jsonData = $data;
}
// Écriture sécurisée dans le fichier avec un verrouillage
$attempts = 0;
while ($attempts < self::MAX_FILE_WRITE_ATTEMPTS) {
$lockHandle = fopen($filename . '.lock', 'w');
if (flock($lockHandle, LOCK_EX)) {
$bytesWritten = file_put_contents($filename, $jsonData, $options);
flock($lockHandle, LOCK_UN);
fclose($lockHandle);
if ($bytesWritten !== false && $bytesWritten === strlen($jsonData)) {
return true; // Écriture réussie
}
} else {
fclose($lockHandle);
if (file_exists($lockHandle)) {
unlink($lockHandle);
} }
} $attempts++;
$attempts++; error_log('Erreur d\'encodage JSON (tentative ' . $attempts . ') : ' . json_last_error_msg());
error_log('Erreur d\'écriture (tentative ' . $attempts . ') : impossible de sauvegarder les données dans ' . $filename); sleep(self::RETRY_DELAY_SECONDS); // Attendre avant de réessayer
sleep(self::RETRY_DELAY_SECONDS); // Attendre avant de réessayer }
}
if ($jsonData === false) {
error_log('Impossible d\'écrire dans le fichier ' . $filename . ' après ' . self::MAX_FILE_WRITE_ATTEMPTS . ' tentatives.'); error_log('Impossible d\'encoder les données en format JSON.');
return false; return false;
} }
} else {
// Pas d'encodage JSON nécessaire
$jsonData = $data;
}
// Écriture sécurisée dans le fichier avec un verrouillage
$attempts = 0;
while ($attempts < self::MAX_FILE_WRITE_ATTEMPTS) {
$lockHandle = fopen($filename, 'c+');
if ($lockHandle !== false && flock($lockHandle, LOCK_EX)) {
$bytesWritten = fwrite($lockHandle, $jsonData);
if ($bytesWritten !== false && $bytesWritten === strlen($jsonData)) {
fflush($lockHandle); // Vider le tampon
ftruncate($lockHandle, ftell($lockHandle)); // Tronquer le fichier à la position actuelle du pointeur
flock($lockHandle, LOCK_UN); // Libérer le verrouillage
fclose($lockHandle); // Fermer le fichier
return file_put_contents($filename, $jsonData, $options) !== false; // Écriture réussie
}
flock($lockHandle, LOCK_UN); // Libérer le verrouillage en cas d'échec d'écriture
}
if ($lockHandle !== false) {
fclose($lockHandle); // Fermer le fichier en cas d'échec d'acquisition du verrouillage
}
$attempts++;
error_log('Erreur d\'écriture (tentative ' . $attempts . ') : impossible de sauvegarder les données dans ' . $filename);
sleep(self::RETRY_DELAY_SECONDS); // Attendre avant de réessayer
}
error_log('Impossible d\'écrire dans le fichier ' . $filename . ' après ' . self::MAX_FILE_WRITE_ATTEMPTS . ' tentatives.');
return false;
}
/** /**
* Effacer les données de la page * Effacer les données de la page