Web - кодинг: PHP:


Как мы побороли flock



  Автор: Дмитрий Смирнов
  Источник:

Дано: файл, в который часто пишется информация и часто из него считывается. Например, простой текстовый счетчик на страницу.

Проблема: рано или поздно, но обязательно случится ситуация, когда одновременно к файлу будет несколько обращений — и на запись и на чтение. И вся информация, натурально, потеряется.

Чтобы этого не случилось, существует специальный оператор в PHP — . Который, по идее, должен с этим бороться — сначала мы получаем эксклюзивные права доступа к файлу, пишем туда, что хотим, а потом эти права теряем.

В идеале это работает. Но — цитирую документацию по PHP — «flock() will not work on NFS and many other networked file systems. Check your operating system documentation for more details». Если почитать все ту же документацию, то в комментариях пользователей приводится множество способов побороть flock, вплоть до самых экзотичных.

Стоит ли говорить, что у меня ни сам flock, ни другие способы просто не работали?

В конце концов, я набрел в одном англоязычном на интересную фразу как раз по этому поводу: «A file rename operation is guaranteed to be atomic by the operating system, and is very efficient as file functions are always highly optimized».

То есть, rename — это атомарная, сиречь неделимая функция операционной системы. К тому же она очень эффективная, потому что файловые функции всегда хорошо оптимизированы.

Так что я попробовал побороть flock следующим образом: сначала пишем все, что нам нужно, в временный файл (не забудьте выставить правильный chmod на директорию, в которую он будет писаться), а потом просто переименовываем этот файл в тот файл, который нужно. Причем в unix-овых системах старый файл удалять нет необходимости — все будет перезаписано сверху.

Я написал две функции. Первая функция — это функция записи в файл, вторая — чтения из файла. Эти две функции интенсивно работают у меня вот уже больше месяца, и пока не было ни одного сбоя.

Запись в файл:

function S_fw ($COUNT_FILE, $text)
{
$z=rand (0,100000);
$fp = @fopen($COUNT_FILE.".".$z, "wb+");
@fwrite($fp,$text);
@fclose($fp);
if (@rename ($COUNT_FILE.".".$z, $COUNT_FILE)==false)
{
@unlink ($COUNT_FILE);
@rename ($COUNT_FILE.".".$z, $COUNT_FILE);
}
}

Чтение из файла (flock здесь стоит «на всякий случай»):

function S_fr ($COUNT_FILE)
{
clearstatcache();
$fp = @fopen($COUNT_FILE, "rb");
@flock ($fp,LOCK_SH);
$conts=@fread ($fp, filesize ($COUNT_FILE));
@fclose ($fp);
@flock($fp, LOCK_UN);
return $conts;
}

Пользуйтесь на здоровье.

PS. Мне тут подсказывают про . Использовать ее будет более правильно, чем rand.

PSS. Прислали ссылку на , как это можно сделать. Я не проверял.






При перепечатке любого материала с сайта, видимая ссылка на источник www.warayg.narod.ru и все имена, ссылки авторов обязательны.

© 2005
 

Hosted by uCoz