Проблемы с счетчиком.

Николай

PHP - CooL
Проблемы с счетчиком.

Написал простейший счетчик считающий количество хитов. Принцип такой:
PHP:
$f=fopen("counter.txt","r");
$c=fread($f,1000);
fclose($f);
$c++;
$f=fopen("counter.txt","w");
flock($f, 2);
$c=fwrite($f,$c);
flock($f, 3);
fclose($f);
Но этот счетчик почему-то глюкается(очищается файл counter.txt) при частом нажатии обновить, хотя стоит блокировка...
Я это проверил так:
PHP:
for($i=0; $i<9999; $i++){
$f=fopen("http://127.0.0.1/counter.php","r");
}
Если открыть этот файл в одном окне браузера - то все нормально, но если открыть в нескольких(даже двух), файл counter.txt

становится пустым! Помогите пожалуйста решить эту проблему...
 

Alkinoy

Guest
Читаем в мане:
В некоторых ОС flock() реализуется на уровне процесса. При использовании API многопоточного сервера типа ISAPI вы не сможете рассчитывать на flock() для защиты файлов относительно других PHP-скриптов, запущенных в параллельных потоках в том же самом экземпляре сервера!

flock() не поддерживается на старинных файловых системах вроде FAT и их клонах и, следовательно, всегда возвращает FALSE в такой среде (это также верно для пользователей Windows 98 ).
 

Alkinoy

Guest
К тому же на вашем сайте, Николай, кто то пишет статью "Введение в РНР". Почему бы не спросить у него? :)
 

Николай

PHP - CooL
Согласен начсет винды, но, у меня такая же херь происходит на сервере(там Linux), редко, но метко, при этом стираются все значения счетчика!
 

lucas

Guest
Кажется, я знаю, почему счетчик обнуляется.

1.

Ты открываешь файл в режиме "w" -- он автоматически очищается. А если параллельным процессом из него читают информацию? Имеем вот что: $c -- пустая строка, счетчик сбросился.

2.

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

Попробуй такое решение:

PHP:
$file = fOpen("counter.txt","r") ;
while (fLock($file,LOCK_SH) == false) { }
$counter = fRead($file,fileSize($file)) ;
while (fLock($file,LOCK_UN) == false) { }
fClose($file) ;

$file = fOpen("counter.txt","r+") ;
while (fLock($file,LOCK_EX) == false) { }
fTruncate($file,0) ;
fWrite($file,++$counter) ;
while (fLock($file,LOCK_UN) == false) { }
fClose($file) ;
 

Николай

PHP - CooL
Во-первых, fTruncate() не работает на моем серваке(хотя в винде все нормально), не знаю почему...
Во-вторых, куча while'ов не затормозит мой скрипт?
 

lucas

Guest
1.

Куча while'ов не затормозит твой скрипт, т. к. в большинстве случаев каждый из них выполнится по одному разу.
Они необходимы для 100% уверенности, что блокировка установлена.

Пример:
1. fLock() пробует заблокировать файл.
2. Он уже заблокирован.
3. Снова пробуем блокировать.
4. Заблокировавшая его программа уже завершилась, блокировка успешно установлена.

2.

Как именно не работает fTruncate()?
Выдается сообщение обшибке, что нет такой функции?
Или ничего не происходит, но файл не усекается?
Какая версия PHP?
 

Николай

PHP - CooL
ftruncate просто не работает, ни ошибок ничего...
Да это и не важно... можно и без него обойтись! Я уже собственно привык...

А по-моему while лишний... мне кажется flock($f,3) - тоже самое...
 

lucas

Guest
fLock() лишь пытается установить блокировку, а не устанавливает ее в любом случае.
Если файл уже заблокирован, то имеем вышеописанные глюки со сбрасыванием счетчика, т. к. файл заблокирован не был.

Все остальное, как я понимаю, работает?
 
Сверху