Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате
Форум программистов > Perl: разработка для Web > Одновременная запись в один файл


Автор: Dimoon 2.5.2006, 00:32
Скажите пожалуйста, 
что будет, если два пользователя моей гостевой книги одновременно добавят сообщение? 
Где то читал, что от этого надо предохраняться. 
А как именно? Как запретить пользователю доступ к файлу на запись, если в этот момент кто то ее производит?
 
smile 

Большое спасибо! 

Автор: Wilmer 2.5.2006, 15:35
Нужно было попробывать самому, что из этого получиться.
Скорее всего одна запись добавиться, а у второй будет ошибка.
Либо одна запись добавится, а вторая поверх нее запишется.

Блокировку можно установить функцией flock.

Вариант 1.
Для каждого сообщения создавать свой файл. Другим скриптом собирать
все записи в один файл. Т.е. каждый открывать, читать, записывать в основной,
удалять. Такой скрипт лучше всего запускать через какое-то промежуток время.

Вариант 2.
Использовать БД и не мучаться с файлами. Хотя для гостевой использовать БД,
не лучший вариант.

Вариант 3.
Использовать блокировку файла.

Добавлено @ 15:39 
Если я не ошибаюсь, почти в каждой книге в разделе по работе с файлами описана блокировка.
Лучше всего приобрести книгу.   

Автор: nitr 2.5.2006, 17:10
Цитата(Wilmer @  2.5.2006,  15:35 Найти цитируемый пост)
Использовать БД и не мучаться с файлами. Хотя для гостевой использовать БД,
не лучший вариант.

Не соглашусь, БД в любых случаях (практически) лучший вариант. Но и с БД могут быть... запись <-> чтение ;)

Добавлено @ 17:11 
Сделай типа предупреждающее сообщение... данные обновляются... а про гостевухи... их множество ;)

Добавлено @ 17:11 
А нельзя форум под гостевуху ;) ... тож ведь вариант 

Автор: GoodBoy 3.5.2006, 09:20
Цитата(Wilmer @  2.5.2006,  15:35 Найти цитируемый пост)
Блокировку можно установить функцией flock.

не все ОС поддерживают эту функцию! 

Автор: sharq 3.5.2006, 12:10
Цитата(GoodBoy @  3.5.2006,  10:20 Найти цитируемый пост)
не все ОС поддерживают эту функцию! 

поэтому можно использовать файлы-семафоры.

 smile 
 

Автор: Dimoon 3.5.2006, 15:44
Вот что я нашел, работает под любую OC:

Описание

Суть метода простая - перед тем, как "занять" файл данных, скрипт создает этот временный файл, а после освобождения - удаляет. Таким образом, наличие этого временного файла означает, что файл данных занят. Другой экземпляр скрипта перед записью проверяет наличие временного файла и, если он есть, дожидается его удаления первым экземпляром, и только затем начинает работу с файлом данных. 

Имя для временного файла может быть любым - главное, чтобы для блокировки разных файлов данных разными скриптами использовались разные имена. 
#########################################
$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) более чем достаточное, чтобы другой процесс завершил работу с файлом данных). Как только временный файл будет удален другим процессом, произойдет выход из цикла; далее скрипт создает свой временный файл, осущетсвляет работу с файлом данных и удаляет временный файл.

Автор: Андрей Черный  

Автор: Wilmer 3.5.2006, 16:19
Мне кажется, что вернее будет если размещать функции для работы с файлом до его закрытия.
Иначе ничего интересного не будет.  smile 
Потом, как я знаю, если делается закрытие файла, то блокировка автоматически снимается.
Лучше блокировку снимать до закрытия файла.

Если я ошибаюсь, поправьте меня.  smile   

Автор: Dimoon 3.5.2006, 18:51
Подскажите пожалуйста, как выглядит "код обработки непредвиденной ошибки" 

Автор: sharq 4.5.2006, 10:14
Dimoon, смотря в каком контексте, привиди пример.

Обычно ошибку можно поймать через проверку результата выполнения команды (в таком случае ошибка обычно содержится в $!)
Код

open my $fh, '>', 'file.txt' or die "Cant' open file: $!\n";


или 

через блок eval (ошибка содержится в переменной $@).
Код

eval { my $result = 10/2; }
die "Error: $@\n" if $@;


 smile   

Powered by Invision Power Board (http://www.invisionboard.com)
© Invision Power Services (http://www.invisionpower.com)