Поэтому в CGI-скриптах принимают специальные меры по
блокировке одновременного использования файлов данных несколькими
скриптами одновременно. В языке Perl, как и во многих языках
программирования, есть специальная функция "блокировки" файла flock. Однако
на практике эта функция не работает в портах Perl под Windows 9x.
Соответственно, скрипты, использующие эту функцию, на мой взгляд, не
могут считаться кросс-платформенными. Это также затрудняет отладку
скриптов на машине под Windows перед перносом их на UNIX-хостинг. Тем
не менее, защиту файлов от одновременного использования можно
организовать и "своим путем", и это будет работать на всех системах. Предлагаемый здесь метод основан на использовании временного файла с заранее известным именем. Суть
метода простая - перед тем, как "занять" файл данных, скрипт создает
этот временный файл, а после освобождения - удаляет. Таким образом,
наличие этого временного файла означает, что файл данных занят. Другой
экземпляр скрипта перед записью проверяет наличие временного файла и,
если он есть, дожидается его удаления первым экземпляром, и только затем
начинает работу с файлом данных. Имя для временного файла может
быть любым - главное, чтобы для блокировки разных файлов данных разными
скриптами использовались разные имена. Фрагмент Perl-кода, реализующий такую защиту, может быть таким: $lockfile="data.tmp"; #Имя временного файла блокировки $count=50; $interval=0.05; #Кол-во попыток и интервал между ними if (-e $lockfile) { #Если временный файл есть, ждем его удаления другим процессом while (($count>0)&&(-e $lockfile)) { sleep $interval;$count-=1; }; }; if ($count==0) { #Здесь размещается код обработки непредвиденной ошибки }; open TF,">$lockfile"; #Создаем временный файл close TF; #... #Здесь размещается собственно код работы с файлом данных #... unlink $lockfile; #Удаляем временный файл Этот
участок скрипта проверяет, существует ли временный файл. Если он
существует, то производится ($count) проверок его существования через
интервалы ($interval) секунд (значения 50 и 0.05 можно заменить своими;
предполагается, что время ($count*$interval) более чем достаточное,
чтобы другой процесс завершил работу с файлом данных). Как только
временный файл будет удален другим процессом, произойдет выход из цикла;
далее скрипт создает свой временный файл, осущетсвляет работу с файлом
данных и удаляет временный файл. Если скрипт работает на запись с
несколькими файлами данных, то для защиты каждого должен быть,
естественно, свой вышеописанный фрагмент кода (в нужном месте) и свое
имя для временного файла. Во многих случаях имеет смысл
"блокировать" файл данных не только во время записи в него, а во время
всего цикла "чтение-модификация-запись". В противном случае очень
возможна потеря результатов работы одного из "экземпляров" скрипта. На
мой взгляд, этот подход не менее надежный, чем "стандартный
Perl-овский", но зато нормально работающий и под Win9x, и под
UNIX-подобными системами.
|