Использование flock()

Shhh

Новичок
Использование flock()

Прочитал вот здесь http://php.spb.ru/php/flock.html про использование flock

<?

// верхняя часть страницы

// код счетчика:

$f2=fopen("counter.txt","r"); // чтобы файл заблокировать, его надо открыть
// открыли файл на чтение
flock($f2,LOCK_EX); // заблокировали файл

$counter=file("counter.txt"); // прочитали файл в массив $counter
$f=fopen("counter.txt","w+"); // открыли файл на запись
fputs($f,$counter[0]+1); // записали "число + 1"
fclose($f); // закрыли файл
echo $counter[0]+1; // вывели число на экран

flock($f2,LOCK_UN); // сняли блокировку (при закрытии снимается автоматически)
fclose($f2); // и закрыли файл (при выходе закрывается автоматически)

// нижняя часть страницы

?>

Вот только на локалке в ХР оно не работает (просто очищается файл) Это так и должно быть?
И возникает еще вопрос, если мы открыли файл на считывание $f2=fopen("counter.txt","r") то чего его нельзя и прочитать через fread, а используется file()? Эта функция быстрее работает?
 

japplegame

Новичок
Видимо баг. Но вообще-то скрипт написан через, простите, ж...у. Руки бы поотбивал за такие манули. Я бы написал вот так:
Код:
$f=fopen("counter.txt","a+");// Открываем файл на добавление.
/* Если открыть просто на запись,
   то после ftruncate() придется делать fseek() на начало файла
*/
flock($f,LOCK_EX);    // блокируем файл
$counter=fgets($f)+1; // читаем значение счетчика и увеличиваем его на единицу
ftruncate($f,0);      // обнуляем файл
fputs($f,$counter);   // пишем новое значение счетчика
echo $counter;        // выводим на экран счетчик
flock($f,LOCK_UN);    // снимаем блокировку (необязательно, ибо сама снимется при закрытии)
fclose($f);           // закрываем
Кроме того надо понимать, что flock() на самом деле ничего не блокирует и другие процессы вполне могут записывать в этот файл. Чтобы flock() работал, надо его использовать во всех скриптах, которые используют блокируемый файл.
 

CMD

Новичок
Вместо flock() лучше создавать временный файл а потом делать rename() т.к. эта фунцкия имеет более высокий приоритет во всех файловых системах
 

SiMM

Новичок
> Вместо flock() лучше создавать временный файл а потом делать rename() т.к. эта фунцкия имеет более высокий приоритет во всех файловых система
Проблемы одновременного доступа к файлу это не решает.
 

Shhh

Новичок
Автор оригинала: CMD
Вместо flock() лучше создавать временный файл а потом делать rename() т.к. эта фунцкия имеет более высокий приоритет во всех файловых системах
Мне кажется тогда получится так. Пусть на счетчике "5". Первый юзер считал файл, добавил единицу в временном файле - получается "6", в это время второй юзер считывает файл (старый файл где написано "5") тоже добавляет единицу в временный файл и тоже имеет "6". Потом первый переименовывает временный файл и получается на счетчике "6", второй тоже переименовывает и на счетчике все то же "6":)
 

CMD

Новичок
да но при одновременном доступе файл вообще может потерять всю инфорамцию. из двух зол выбираем
 

SiMM

Новичок
> да но при одновременном доступе файл вообще может потерять всю инфорамцию.
При правильной работе с flock'ом? Да ну?
 

McSimm

Новичок
При правильной работе с flock'ом? Да ну?
Есть преимущества у использования временных файлов.
Например надо открыть, прочитать и полностью перезаписать с какими-то изменениями.
При правильной работе с flock() и аварийной ситуации потеря данных весьма возможна. Практически.

Т.к. при перезаписи оригинального файла, возникает ситуация, когда информация существует в единственном экземпляре в памяти процесса.
Если использовать временный файл (и при этом правильно использовать flock()), смерть процесса приводит максимум к потере текущих изменений, но не существующей информации.
 

timasik

Новичок
PHP:
function savedata($input){
$file="./data/data.php";

if(is_array($input)){
for($i=0;$i<count($input);$i++){
if(@$input[$i]){
if(is_array($input[$i])){
$input[$i]=implode("¦¦",$input[$i]);
}
$input[$i].="\n";
}else{
$input[$i]="";
}
}
$input=implode("",$input);
}

$fp=fopen($file,"w");
flock($fp,2);
fwrite($fp,$input);
flock($fp,3);
fclose($fp);

}
А теперь вопрос: У меня на сайте до 7000 посетителей в день (в среднем 70 онлайн) при просмотре файла из базы (этой же) происходит запись в одну из ячеек данной строки (просматриваемой) для статистики просмотров.

Так вот с тех пор как data.php стал размером более 1,3 мб видимо при одновременной записи от толпы народа flock не помогает (из 12000 записей пропадает больше половины).... вопрос "Что делать?" подскажите плиз... не хочу MSQl....
 

timasik

Новичок
whirlwind дело в том что хостинг мой тоже не поддерживает баз данных (у меня самый дешёвый за 900 рублей в год) есть у меня ещё хостинг там есть базы но переносить туда домен не только не хочется но и хлопотно, т.к. придётся изучать MySQL а это время... понятно что это нужно... но сейчас у меня со временем проблемы... а теперь ещё и со своей .txt базой

если есть выход в данной ситуации (может разбить базу на куски и через цикл их листать, может ещё что) подскажите плиз... как мне статистику просмотров сделать целостно и органично... со своей .txt базой
 

SiMM

Новичок
> Так вот с тех пор как data.php стал размером более 1,3 мб видимо при одновременной записи от толпы народа flock не помогает (из 12000 записей пропадает больше половины)....

Потому что код кривой. Открываешь файл на чтение-запись, лочишь его, читаешь данные, меняешь то, что нужно, разлочиваешь файл и закрываешь. И делаешь всё это максимально быстро.
 

Breeze

goshogun
Команда форума
Партнер клуба
самое интересное, что все вышесказанное написано здесь: [m]flock[/m]
 

timasik

Новичок
Автор оригинала: SiMM
> Так вот с тех пор как data.php стал размером более 1,3 мб видимо при одновременной записи от толпы народа flock не помогает (из 12000 записей пропадает больше половины)....

Потому что код кривой. Открываешь файл на чтение-запись, лочишь его, читаешь данные, меняешь то, что нужно, разлочиваешь файл и закрываешь. И делаешь всё это максимально быстро.
Если код кривой подскажи что я написал не так?

открываю файл:

PHP:
function data(){
$file="./data/data.php";
$output=file($file);

for($i=0;$i<count($output);$i++){
$output[$i]=trim($output[$i]);
$output[$i]=explode("¦¦",$output[$i]);
}

return $output;
}
циклом нахожу нужную строку с данными
прибавляю в $data[$i][9] единичку и записываю так как я написал выше.
В чём ошибка?

-~{}~ 21.09.06 11:11:

Breeze а разве не flock() отвечает за очерёдность записи в файл т.е. блокирует его чтобы не было сбоя записи?
если вопрос в деньгах!!! я заплачу... но помогите...

суть в чём: у меня два вида статистики, первая когда пользователь просматривайт информацию о файле ($data[$i][9]) вторая когда он кликает на ссылку "Скачать" ($data[$i][12]). До тех пор пока было меньше 1 мб документ (типа база) всё ок, а теперь выбивает часть информации в произволном порядке. Из-за этого информация о файлах теряется и статистические данные тоже, мне приходится загружать локальную копию со старыми параметрами (востанавливать) документ.
 

McSimm

Новичок
а в этот момент параллельный экзепмляр пишет в этот файл, соответственно в $output попадает только часть данных.

а разве не flock() отвечает за
В общем случае - нет, только программист. Частный случай - ОС, в которой flock блокирует доступ к файлу.
 

timasik

Новичок
Автор оригинала: McSimm
а в этот момент параллельный экзепмляр пишет в этот файл, соответственно в $output попадает только часть данных.
Подскажи как этого избежать?
Поможет если сначала файл загонять в массив, закрывать файл, и в уже массиве рыться в поиске?
 

SiMM

Новичок
> Подскажи как этого избежать?
Я уже написал. Читай выше. Что конкретно из сказанного непонятно?

> Поможет если сначала файл загонять в массив, закрывать файл, и в уже массиве рыться в поиске?
Ты же туда ещё писать собрался.

Основная мысль до безобразия проста - между чтением и записью в процессе исполнения скрипта другие экземпляры вклиниваться не должны.
 
Сверху