Как на php запретить различным процессам одновременно читать файл?

Есть текстовый файл с данными, например:
101\n
string\n
string\n
string\n
...


Также есть множество различных процессов, которые сначала читают этот файл, а потом переписывают 1ое число.

Логика программы:
В первой строке записано число - текущие положение курсора n. В функции процесс считывает n-ую строку файла, дальше работает с ней, а затем сдвигает курсор, то есть переписывает первую строку файла на n+1, чтобы тот, кто будет читать файл в следующий раз, считал уже n+1 ую строку.

Сама функция с чтением/записью файла:
public function updateFile() {
        $filename = Yii::getAlias('@app') . '/config/file.dat'; 
        $lines = file($filename);

       //тут работа с массивом $lines

        SafeWriterHelper::writeData($filename, 'w',  trim(implode("", $lines)));
    }


С одновременной записью вроде разобралась. Создала свою функцию записи в файл:
class SafeWriterHelper
{ 
    // suggested mode 'a' for writing to the end of the file 
    public static function writeData($path, $mode, $data) 
    { 
        $fp = fopen($path, $mode); 
        $retries = 0; 
        $max_retries = 100; 

        if (!$fp) { 
            // failure 
            return false; 
        } 

        // keep trying to get a lock as long as possible 
        do { 
            if ($retries > 0) { 
                usleep(rand(1, 10000)); 
            } 
            $retries += 1; 
        } while (!flock($fp, LOCK_EX) and $retries <= $max_retries); 

        // couldn't get the lock, give up 
        if ($retries == $max_retries) { 
            // failure 
            return false; 
        } 

        // got the lock, write the data 
        fwrite($fp, "$data\n"); 
        // release the lock 
        flock($fp, LOCK_UN); 
        fclose($fp); 
        // success 
        return true; 
    } 
}


Как быть с чтением? И вообще как это всё реализовать по-человечески?
  • Вопрос задан
  • 279 просмотров
Пригласить эксперта
Ответы на вопрос 2
miraage
@miraage
Старый прогер
По-человечески: rdbms/redis.
Ответ написан
Комментировать
@mantyr
Пишу много Golang кода с удовольствием:)
Почитайте про блокировку файлов. php.net/manual/ru/function.flock.php

Пример из документации
<?php
$fp = fopen("/tmp/lock.txt", "r+");

if (flock($fp, LOCK_EX)) { // выполняем эксклюзивную блокировку
    ftruncate($fp, 0); // очищаем файл
    fwrite($fp, "Что-нибудь пишем сюда\n");
    fflush($fp);        // очищаем вывод перед отменой блокировки
    flock($fp, LOCK_UN); // отпираем файл
} else {
    echo "Не удалось получить блокировку !";
}
fclose($fp);
?>
Ответ написан
Комментировать
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Похожие вопросы