1.7.09 flock sur le fichier principal (PB sous win)

This commit is contained in:
Fred Tempez 2024-04-05 18:21:09 +02:00
parent a35036e0fa
commit 6c0f34ae71
2 changed files with 66 additions and 63 deletions

View File

@ -166,38 +166,36 @@ 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

@ -792,57 +792,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++; $attempts++;
error_log('Erreur d\'encodage JSON (tentative ' . $attempts . ') : ' . json_last_error_msg()); error_log('Erreur d\'encodage JSON (tentative ' . $attempts . ') : ' . json_last_error_msg());
sleep(self::RETRY_DELAY_SECONDS); // Attendre avant de réessayer sleep(self::RETRY_DELAY_SECONDS); // Attendre avant de réessayer
} }
if ($jsonData === false) { if ($jsonData === false) {
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;
} }
} else { } else {
// Pas d'encodage JSON nécessaire // Pas d'encodage JSON nécessaire
$jsonData = $data; $jsonData = $data;
} }
// Écriture sécurisée dans le fichier avec un verrouillage // Écriture sécurisée dans le fichier avec un verrouillage
$attempts = 0; $attempts = 0;
while ($attempts < self::MAX_FILE_WRITE_ATTEMPTS) { while ($attempts < self::MAX_FILE_WRITE_ATTEMPTS) {
$lockHandle = fopen($filename . '.lock', 'w'); $lockHandle = fopen($filename, 'c+');
if (flock($lockHandle, LOCK_EX)) { if ($lockHandle !== false && flock($lockHandle, LOCK_EX)) {
$bytesWritten = file_put_contents($filename, $jsonData, $options); $bytesWritten = fwrite($lockHandle, $jsonData);
flock($lockHandle, LOCK_UN); if ($bytesWritten !== false && $bytesWritten === strlen($jsonData)) {
fclose($lockHandle); fflush($lockHandle); // Vider le tampon
if ($bytesWritten !== false && $bytesWritten === strlen($jsonData)) { ftruncate($lockHandle, ftell($lockHandle)); // Tronquer le fichier à la position actuelle du pointeur
return true; // Écriture réussie flock($lockHandle, LOCK_UN); // Libérer le verrouillage
} fclose($lockHandle); // Fermer le fichier
} else { return file_put_contents($filename, $jsonData, $options) !== false; // Écriture réussie
fclose($lockHandle); }
} flock($lockHandle, LOCK_UN); // Libérer le verrouillage en cas d'échec d'écriture
$attempts++; }
error_log('Erreur d\'écriture (tentative ' . $attempts . ') : impossible de sauvegarder les données dans ' . $filename); if ($lockHandle !== false) {
sleep(self::RETRY_DELAY_SECONDS); // Attendre avant de réessayer fclose($lockHandle); // Fermer le fichier en cas d'échec d'acquisition du verrouillage
} }
$attempts++;
error_log('Impossible d\'écrire dans le fichier ' . $filename . ' après ' . self::MAX_FILE_WRITE_ATTEMPTS . ' tentatives.'); error_log('Erreur d\'écriture (tentative ' . $attempts . ') : impossible de sauvegarder les données dans ' . $filename);
return false; 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;
}