Forum Webscript.Ru

Программирование => PHP => Тема начата: UltraMax от 07 Декабря 2004, 19:20:13

Название: Внесение изменений в текстовый файл
Отправлено: UltraMax от 07 Декабря 2004, 19:20:13
я использую текстовый файл для хранения инфы
и внесения изменения в него вношу так

тут мне надо чтобы оно файл уменьшило до нуля и влепила измененный текст
    $handle = fopen ("/home/dmnorg/results.txt", "w");
    fwrite($handle, $contents_replaced);
    fclose($handle);

и в другом оно просто добавляет строчку
    $handle = fopen ("/home/dmnorg/results.txt", "a");
    fwrite($handle, $string);
    fclose($handle);

такой вопрос - оно может перезатереть файл при одновременном доступе???
может надо использовать какие-то функции для защиты от одновременного доступа?
или сам php будет отслеживать данный процесс???
в общем вопрос простой - если скрипт открыл файло на запись
и тут второй еще раз лезет его открыть на запись

что тогда?
Название: Внесение изменений в текстовый файл
Отправлено: ThE0ReTiC от 07 Декабря 2004, 23:17:02
[p]flock[/p]
Название: Внесение изменений в текстовый файл
Отправлено: UltraMax от 08 Декабря 2004, 11:49:54
Млять - как и в перле
Но почему же в документации нет ссылки на это
Точнее когда описывается функция fwrite - нет ссылки на flock
зато есть
See also fread(), fopen(), fsockopen(), and popen().
твою бабушку, два раза уже результаты херились :((
Название: Внесение изменений в текстовый файл
Отправлено: UltraMax от 08 Декабря 2004, 16:20:21
Сейчас используется вот такая конструкция
в одном скрипте вот так открываетс файл
$handle = fopen("/home/dmnorg/results.txt", "r");
    if (flock($handle, LOCK_SH)) { // do an exclusive lock
    fwrite($handle, $contents_replaced);
    flock($handle, LOCK_UN); // release the lock
    }

и во втором скрипте вот так
$handle = fopen ("/home/dmnorg/results.txt", "a");
    if (flock($handle, LOCK_EX)) { // do an exclusive lock
    fwrite($handle, $string);
    flock($handle, LOCK_UN); // release the lock

все равно из файла /home/dmnorg/results.txt
пропадают записи :( С чем это может быть связано?

Не может ли это быть связано с тем, что у меня в одном месте на чтений открывается файл без flock

$handle = fopen("/home/dmnorg/results.txt", "r");
$contents = fread($handle, filesize("/home/dmnorg/results.txt"));
fclose($handle);

??????????? Кто подскажет?
Название: Внесение изменений в текстовый файл
Отправлено: Alexey333 от 09 Декабря 2004, 08:16:58
У меня лично такой проблемы никогда не было, даже давно когда еще совсем не блокировал (был новичком). А когда начал блокировать, то тем более нет проблем.

Приведи весь скрипт. А то так не очень ясно из-за чего это. Может даже блокировка тут вообще ни при чем, а ошибка в самой программе (скорее всего из-за этого!).
И к тому же в первых 2 приведенных кодах я не вижу fclose. А fclose писать надо обязательно! Иначе такие проблемы могут случиться с большей вероятностью.
Название: Внесение изменений в текстовый файл
Отправлено: UltraMax от 09 Декабря 2004, 11:50:05
Вот коды/
Первый скрипт парсит POST данные из формы и добваляет их в текстовый файл

// variables
$first_place = $_POST[\'first_place\'];
$second_place = $_POST[\'second_place\'];
$third_place = $_POST[\'third_place\'];
$real_name= $_POST[\'name\'];
$name= urlencode($_POST[\'name\']);
$email = $_POST[\'email\'];
$subject = "Голосование";
$rnd_val = rand (123456987, 987654321);
$string=$name."/".$email."/".$first_place."/".$second_place."/".$third_place."/".$rnd_val."/n\\n";
$message="Доброго времени суток, $real_name. Вы проголосовали за лучшего игрока сезона 2004 года.

Для того, чтобы активировать ваш голос, пожалуйста, перейдите по ссылке, указанной ниже.
[url]http://xxx/vote/act.php?name=[/url]$name&email=$email&v1=$first_place&v2=$second_place&v3=$third_place&id=$rnd_val

Всего наилучшего

UltraMax";
// To send HTML mail, you can set the Content-type header.
$headers  = "MIME-Version: 1.0\\r\\n";
$headers .= "Content-type: text/html; charset=Windows-1251\\r\\n";

// additional headers
$headers .= "From: Админ \\r\\n";

$handle = fopen("/home/dmnorg/results.txt", "r");
$contents = fread($handle, filesize("/home/dmnorg/results.txt"));
fclose($handle);

$pos = strpos(strtolower($contents), strtolower($email));
if ($pos === false) {
    $handle = fopen ("/home/dmnorg/results.txt", "a");
    if (flock($handle, LOCK_EX)) { // do an exclusive lock
    fwrite($handle, $string);
    flock($handle, LOCK_UN); // release the lock
    } else {
    echo "Couldn\'t lock the file !";
    }
    fclose($handle);
    mail($email, $subject, $message, $headers) || die ("

Не удалось отправить письмо.  Попробуйте вернуться и попробовать еще раз

");
    mail("mcsim@xxx.org", $subject, $message, $headers) || die ("

Не удалось отправить письмо.  Попробуйте вернуться и попробовать еще раз

");
    echo ("

Спасибо!

На ваш e-mail $email выслано письмо с подтверждением голосования.

");
    }
    else {
    echo "

Данный адрес уже использовался для голосования!

Вернуться и попробовать с другим адресом.

";
}

?>

Второй скрипт изменяет строку в файле


$name = $_GET[\'name\'];
$real_name= urldecode($_GET[\'name\']);
$email = $_GET[\'email\'];
$id = $_GET[\'id\'];
$v1 = $_GET[\'v1\'];
$v2 = $_GET[\'v2\'];
$v3 = $_GET[\'v3\'];

$str=$name."/".$email."/".$v1."/".$v2."/".$v3."/".$id."/n\\n";
$str_y=$name."/".$email."/".$v1."/".$v2."/".$v3."/".$id."/y\\n";

$handle = fopen("/home/dmnorg/results.txt", "r");
    if (flock($handle, LOCK_SH)) { // do an exclusive lock
    fwrite($handle, $contents_replaced);
    flock($handle, LOCK_UN); // release the lock
    }
    $contents = urldecode(fread($handle, filesize("/home/dmnorg/results.txt")));
fclose($handle);

//echo $str_y, $contents;
$posit = strpos(strtolower($contents), strtolower($str));
if ($posit === false) {
    echo "Внимание, ссылка активации неправильная. Вернитесь в вашу почту, и попытайтесь еще раз!";
    } else {
    $contents_replaced=substr_replace($contents, $str_y, $posit);
//    echo $contents_replaced;
    $handle = fopen ("/home/dmnorg/results.txt", "w");
    if (flock($handle, LOCK_EX)) { // do an exclusive lock
    fwrite($handle, $contents_replaced);
    flock($handle, LOCK_UN); // release the lock
    } else {
    echo "Couldn\'t lock the file !";
    }
    fclose($handle);
    echo ("

Спасибо $real_name, ваш голос учтен!

");
    }
?>

Понимаю что тут нет нормальной защиты, но на данный момент интересует почему строчки затираются...
Хотя вот сегодня утром пришел - все ок, с файлом работало нормально...
НЕ... в след. раз тока мускул.. тока мускул... Там такого быть не может :)
Название: Внесение изменений в текстовый файл
Отправлено: CGVictor от 09 Декабря 2004, 12:55:07
Про flock еще Spectator писал. Чем его способ не устраивает?
Название: Внесение изменений в текстовый файл
Отправлено: UltraMax от 09 Декабря 2004, 13:06:44
CGVictor
ты имел ввиду вот это?
http://php.spb.ru/php/flock2.html
Давал бы сразу ссылку...
Заменил
$handle = fopen ("/home/dmnorg/results.txt", "w");
if (flock($handle, LOCK_EX)) { // do an exclusive lock
на
$handle = fopen ("/home/dmnorg/results.txt", "r+");
if (flock($handle, LOCK_EX)) { // do an exclusive lock
ftruncate($handle,0);  
сообщу будут ли затираться результаты
Название: Внесение изменений в текстовый файл
Отправлено: Djibo от 09 Декабря 2004, 14:12:47
нет, у спектатора через временный файл и ренейм.
http://spectator.ru/technology/php/flock_workaround
Название: Внесение изменений в текстовый файл
Отправлено: UltraMax от 09 Декабря 2004, 14:18:09
Да уже рассмотрел и этот вариант.
А кто скажет - что лучше
http://spectator.ru/technology/php/flock_workaround
или
http://php.spb.ru/php/flock2.html
Название: Внесение изменений в текстовый файл
Отправлено: Alexey333 от 09 Декабря 2004, 14:32:13
Ну и код у тебя запутанный. Уверен, что это чистая твоя ошибка, а не файлов. Ну сам подумай, если у других никогда такое не случается даже при большом количестве посетителей, а у тебя это случается постоянно. Проверь внимательно код и обязательно найдешь ошибку!
Я весь твой код проверять не стану, но вот некоторые ошибки бросаются в глаза:
$handle = fopen("/home/dmnorg/results.txt", "r");
    if (flock($handle, LOCK_SH)) { // do an exclusive lock
    fwrite($handle, $contents_replaced);
    flock($handle, LOCK_UN); // release the lock
    }


Открываешь файл на чтение "r", а сам пытаешься писать в него fwrite($handle, $contents_replaced); Это 100% ошибка, так как если хочешь писать, то надо использовать w или a.
К тому же не совсем понятно, что это за переменная $contents_replaced (до этого в скрипте она нигде не встречается).

В общем проверяй! ;)
Название: Внесение изменений в текстовый файл
Отправлено: UltraMax от 09 Декабря 2004, 17:42:58
Alexey333 да - это я лажанулся конкретно
Тут мне надо было прочитать файл, а я писать пытался. Я вообще отказываюсь понимать, с чего оно вообще работало дальше :)
Короче мне тут насоветовали после fwrite использовать fflush
Короче вот что у меня сейчас:
1. Чтение
$handle = fopen("/home/dmnorg/results.txt", "r");
    if (flock($handle, LOCK_SH)) { // do an exclusive lock
    $handle = fopen("/home/dmnorg/results.txt", "r");
    $contents = urldecode(fread($handle, filesize("/home/dmnorg/results.txt")));
    flock($handle, LOCK_UN); // release the lock
    }
fclose($handle);

2. Добавление
    $handle = fopen ("/home/dmnorg/results.txt", "a");
    if (flock($handle, LOCK_EX)) { // do an exclusive lock
    fwrite($handle, $string);
    fflush($handle);
    flock($handle, LOCK_UN); // release the lock

3. Изменение
    $handle = fopen ("/home/dmnorg/results.txt", "r+");
    if (flock($handle, LOCK_EX)) { // do an exclusive lock
    ftruncate($handle,0);
    fwrite($handle, $contents_replaced);
    fflush($handle);
    flock($handle, LOCK_UN); // release the lock

Посмотрим что будет

PS - а что код запутанный.. да есть наверное
Но я по образованию бухгалтер, про правильность оформления кода мне никто не говорил. Есть ссыли - велком, почитаю :)
Название: Внесение изменений в текстовый файл
Отправлено: Alexey333 от 09 Декабря 2004, 18:57:46
Много возни из ничего. Советую больше внимания уделить написанию кода и его оформлению. А то выглядит так, что ты пытаешься свои ошибки свалить на файлы, будто это они во всем виноваты, а ты белый да пушистый.
Название: Внесение изменений в текстовый файл
Отправлено: UltraMax от 09 Декабря 2004, 19:05:14
Много шума?
Еслибы где-то здесь в, faq например, было описано КАК правильно лочить файлы, вопросов бы не возникло.
То что у меня что-то пропадало, это не из за того, что я ошибся, и  в файл открытый для чтения пытался что-то писать.
А в самом принципе работы fopen и flock
и эти принципы не понять из документации
Название: Внесение изменений в текстовый файл
Отправлено: Alexey333 от 09 Декабря 2004, 19:30:34
Ха, ни у кого (например, у меня) вообще никогда ничего не пропадает из-за одновременного доступа, а у тебя сразу пропадает. Если у меня что-то и пропадает, то я ищу ошибку в программе, нахожу ее, и все работает нормально. Никакая блокировка тут ни при чем. А у тебя больно высокое самомнение!
Я пишу так:
$fp=fopen ("users/sumdown.txt","a");
flock ($fp,2);
fputs ($fp,"#");
fputs ($fp,"0");
flock ($fp,3);
fclose ($fp);

и проблем нет. А у тебя вдруг куча ошибок вылазиет, и ты все сразу свалил на блокировку!
Название: Внесение изменений в текстовый файл
Отправлено: UltraMax от 10 Декабря 2004, 13:17:52
Alexey333 никакого самомнения тут нет и в помине.
Я пришел сюда за советом, а не лажать блокировку.

Это раз - а во вторых - у тебя открывается файл на добавление, а не на обнуление. С таким открытием у меня тоже проблем нет.
Попробуй открывать файл с параметром "w" и дать ему нагрузку
Посмотрим что ты потом скажешь

Ничего личного...
Название: Внесение изменений в текстовый файл
Отправлено: Alexey333 от 10 Декабря 2004, 17:53:55
А я и с w открываю. Проблем никаких нет.
Название: Внесение изменений в текстовый файл
Отправлено: Alexey333 от 10 Декабря 2004, 17:59:58
Да, что ты хотел сказать этим "дать ему нагрузку"? Есть специальные проги для искусственной нагрузки скриптов для проверки? Если да, то дай ссылку.
Название: Внесение изменений в текстовый файл
Отправлено: UltraMax от 10 Декабря 2004, 18:51:49
Тут описано как парень тестировал flock
http://php.spb.ru/php/flock2.html
можешь посмотреть
Название: Внесение изменений в текстовый файл
Отправлено: Alexey333 от 10 Декабря 2004, 19:59:48
Цитировать
UltraMax:
Тут описано как парень тестировал flock
http://php.spb.ru/php/flock2.html
можешь посмотреть

Я слышал, что есть специальные проги для проверки.
Кстати, в данной статье этот парень совершил серьезную ошибку:

$f=fopen("flock2_test.txt","r") or die(system("echo fopen_read >> /tmp/11qq"));
   flock($f,2);
   $s=trim(fgets($f,100));
   $md=trim(fgets($f,100));


При чтении файла он использовал не ту блокировку flock($f,2);. А надо при чтении использовать  flock($f,1);!
Название: Внесение изменений в текстовый файл
Отправлено: UltraMax от 10 Декабря 2004, 20:10:12
В чем серьезность ошибки?
В том что этим локом он не дал больше никому доступиться до файла?
Не вижу тут страшного ничего...
Название: Внесение изменений в текстовый файл
Отправлено: Alexey333 от 11 Декабря 2004, 08:06:32
Цитировать
UltraMax:
В чем серьезность ошибки?
В том что этим локом он не дал больше никому доступиться до файла?
Не вижу тут страшного ничего...

Как это ты не видишь разницы?!
Вот тут хорошо написано (хоть и не из PHP):
http://www.itfond.ru/cache/41summary.html
"Усовершенствованная команда LOCK - Команда LOCK была усовершенствована для поддержки разделяемых блокировок (против эксклюзивных) и обеспечивает высокую производительность при частом применении блокировок."

Если ты и при чтении будешь применять эксклюзивную блокировку, то все процессы (и писатели и читатели) будут накапливаться, в результате чего скорость работы намного уменьшится и ошибка может стать весьма вероятной. Для этого то и была придумана разделительная блокировка, чтобы не терять время и давать процессам читателям выполнять свое чтение, когда есть такая возможность.
Название: Внесение изменений в текстовый файл
Отправлено: UltraMax от 13 Декабря 2004, 13:07:22
Alexey333, ты не объяснишь мне, при чем тут СУБД Cache (и ее описание) - к функции flock на PHP?
Название: Внесение изменений в текстовый файл
Отправлено: Alexey333 от 13 Декабря 2004, 16:22:12
Цитировать
UltraMax:
Alexey333, ты не объяснишь мне, при чем тут СУБД Cache (и ее описание) - к функции flock на PHP?

Я же ясно написал "хоть и не из PHP". Сам принцип важен!
Ну раз тебе не понятно, то напечатаю отрывок из книги Д. Котерова "Самоучитель PHP 4":
"Мы решили ровно половину нашей задачи. Действительно, теперь данные из нескольких процессов-писателей не будут перемешиваться, но как быть с читателями?........................
........
Существуют два метода обхода этой проблемы. Первый - это использовать все ту же исключительную блокировку. Действительно, кто сказал, что исключительную блокировку можно применять только в процессах, изменяющих файл? Ведь функция flock() не знает, что будет выполнено с файлом, для которого она вызвана." Однако этот метод довольно-таки неудачен, и вот по какой причине. Представьте, что процессов-читателей много, а писателей - мало, и к тому же писатели еще и вызываются, скажем, раз в пару минут, а не постоянно как читатели. В случае использования исключительной блокировки для процессов-читателей, довольно интенсивно обращающихся к файлу, мы очень скоро получим целый их рой, висящий, недовольно гудя, в очереди, пока очередному процессу разрешат читать. Но ведь никакой аварии не случится, если один и тот же файл будут читать и сразу все процессы этого роя, правда? Ведь чтение из файла его не изменяет.  
Итак, предоставив исключительную блокировку для читателей, мы потенциально получаем проблемы с производительностью, перерастающие в КАТАСТРОФУ, когда процессов-читателей становится больше некоторого определенного порога.
Название: Внесение изменений в текстовый файл
Отправлено: UltraMax от 13 Декабря 2004, 20:31:52
ладно
мы скатились не в ту тему
вопрос то остается
что у меня неправильного
я делаю 3 операции с файлом в котором хранятся данные

первая - чтение
$handle = fopen("/home/dmnorg/results.txt", "r");
$contents = fread($handle, filesize("/home/dmnorg/results.txt"));
fclose($handle);


вторая - добавление
    $handle = fopen ("/home/dmnorg/results.txt", "a");
    if (flock($handle, LOCK_EX)) { // do an exclusive lock
    fwrite($handle, $string);
    fflush($handle);
    flock($handle, LOCK_UN); // release the lock


третья - изменение
 
    $handle = fopen ("/home/dmnorg/results.txt", "r+");
    if (flock($handle, LOCK_EX)) { // do an exclusive lock
    ftruncate($handle,0);
    fwrite($handle, $contents_replaced);
    fflush($handle);
    flock($handle, LOCK_UN); // release the lock


почему пропадают строчки? причем не файл обнуляются
а какие то строчки постоянно пропадают
вот все что я хочу выяснить?
Название: Внесение изменений в текстовый файл
Отправлено: Alexey333 от 13 Декабря 2004, 20:42:23
А в $contents_replaced и $string что?
Название: Внесение изменений в текстовый файл
Отправлено: UltraMax от 13 Декабря 2004, 21:17:36
Вот что - но помоему это не так и важно?

$posit = strpos(strtolower($contents), strtolower($str));
if ($posit === false) {
    echo "Внимание, ссылка активации неправильная. Вернитесь в вашу почту, и попытайтесь еще раз!";
    } else {
    $contents_replaced=substr_replace($contents, $str_y, $posit);
//    echo $contents_replaced;
    $handle = fopen ("/home/dmnorg/results.txt", "r+");
    if (flock($handle, LOCK_EX)) { // do an exclusive lock
    ftruncate($handle,0);
    fwrite($handle, $contents_replaced);
    fflush($handle);
    flock($handle, LOCK_UN); // release the lock
    } else {
    echo "Couldn\'t lock the file !";
    }
    fclose($handle);


а $string у меня - большой большой текст
строчки 3 :)

да еще забыл - есть еще одно чтение

$handle = fopen("/home/dmnorg/results.txt", "r");
    if (flock($handle, LOCK_SH)) { // do an exclusive lock
    $handle = fopen("/home/dmnorg/results.txt", "r");
    $contents = urldecode(fread($handle, filesize("/home/dmnorg/results.txt")));
    flock($handle, LOCK_UN); // release the lock
    }
fclose($handle);
Название: Внесение изменений в текстовый файл
Отправлено: UltraMax от 22 Декабря 2004, 12:34:34
короче никто ответа по СУЩЕСТВУ не дал... :(
увы
Название: Внесение изменений в текстовый файл
Отправлено: Меняздесьдавнонет от 23 Декабря 2004, 00:08:58
почему бы тебе при перезаписи не делать все в рамках одного лока? и чтение и запись