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

Николай

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

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

flock() не поддерживается на старинных файловых системах вроде FAT и их клонах и, следовательно, всегда возвращает FALSE в такой среде (это также верно для пользователей Windows 98 ).
 
К тому же на вашем сайте, Николай, кто то пишет статью "Введение в РНР". Почему бы не спросить у него? :)
 
Согласен начсет винды, но, у меня такая же херь происходит на сервере(там Linux), редко, но метко, при этом стираются все значения счетчика!
 
Кажется, я знаю, почему счетчик обнуляется.

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) ;
 
Во-первых, fTruncate() не работает на моем серваке(хотя в винде все нормально), не знаю почему...
Во-вторых, куча while'ов не затормозит мой скрипт?
 
1.

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

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

2.

Как именно не работает fTruncate()?
Выдается сообщение обшибке, что нет такой функции?
Или ничего не происходит, но файл не усекается?
Какая версия PHP?
 
ftruncate просто не работает, ни ошибок ничего...
Да это и не важно... можно и без него обойтись! Я уже собственно привык...

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

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