копирование файла

predator

web designer
копирование файла

есть старый zip файл и новый
старый иногда копируется системой в отдельную диру
новым надо заместить старый (это делает отдельный скрипт)
достаточно ли сделать copy
или надо делаеть flock в обоих скриптах?

если flock то как я понял в том скрипте который копирует старый файл надо делать LOCK_EX
а в скрипте который копирует новый поверх старого надо LOCK_SH

насчёт записи в файл я в курсе, а вот насчёт copy нигде внятного ответа не нашёл
 

ps2007

Новичок
PHP:
<?php
$file = 'example.txt';
$newfile = 'example.txt.bak';

if (!copy($file, $newfile)) {
    echo "не удалось скопировать $file...\n";
}
?>
Это взято из документации по PHP.
Не пойму, в чем проблема ?
 

predator

web designer
Автор оригинала: ps2007 Не пойму, в чем проблема ?
проблема в том что я не уверен что будет ошибка при копировании
нового файла в то время как копируется старый

поэтому интересно мнение людей, которые сталкивались с похожей проблемой ;)
 

HraKK

Мудак
Команда форума
predator
Проблема в том что некоторые участники форума не умеют читать, а тем более вдумываться, в вопрос, им бы главнее бисер по метать.
 

ps2007

Новичок
1) Скопировать старый
2) Скопировать новый
В обоих случаях проверять результат выполнения функции copy()
 

HraKK

Мудак
Команда форума
ps2007
Не понимаешь в чем проблема, не пиши, договорились? Твой уровень знаний и умение читать, еще не того уровня, чтоб лезть другим помогать.
 

Sigorma

Новичок
PHP:
$fh=fopen('filename','r');
if (!$fh)
{
  echo 'Error!';
} else {
  while (!flock($fh,$mode)) sleep(1);
  // обработка файла
  fclose($fh);
}
 

predator

web designer
проверил, copy() кидает ошибку при попытке копирования нового файла в случае если старый файл копируется. но один из файлов получается битым

один скрипт:
PHP:
$i=0;
while($i<40) {
	if ( !copy( './services/old.zip', './services/old'.$i.'.zip' ) ) {
		p( 'test' );
	}
	$i++;
}
второй скрипт:
PHP:
$i=0; $_err=array();
while($i<20) {
	if ( !copy( './services/new.zip', './services/old.zip' ) ) {
		$_err[]=$i;
	}
	$i++;
}
p( $_err );
один из oldX.zip - битый

-~{}~ 04.02.10 16:42:

Автор оригинала: Sigorma
PHP:
$fh=fopen('filename','r');
во первых 2 разных скрипта
во вторых с какие $mode делать
в третьих не хочется чтобы тормозился первый скрипт (который копирует старый файл в другую диру)

-~{}~ 04.02.10 16:43:

в примере копируется в одну диру но смысл тот же
 

ps2007

Новичок
Не понимаешь в чем проблема, не пиши, договорились? Твой уровень знаний и умение читать, еще не того уровня, чтоб лезть другим помогать.
Ну так напиши ответ, если ты умеешь читать и понимаешь в чем проблема и дорос до того уровня, чтобы лезть другим помогать.
Умничать любой дурак сможет.
 

predator

web designer
dimagolov поясни что ты имеешь ввиду - мне надо копировать файлы а не переименовывать

-~{}~ 04.02.10 17:39:

один скрипт:
PHP:
$i=0;
while($i<40) {
	$fp = fopen( './services/old.zip', "r");
	while (!flock($fp,LOCK_EX)) sleep(1);
	if ( !copy( './services/old.zip', './services/old'.$i.'.zip' ) ) {
		$_err[]=$i;
	}
	flock($fp, LOCK_UN);
	fclose($fp);
	$i++;
}
p( $_err );
второй скрипт:
PHP:
$i=0; $_err=array();
while($i<20) {
	$fp = fopen( './services/old.zip', "r");
	while (!flock($fp,LOCK_EX)) sleep(1);
	if ( !copy( './services/new.zip', './services/old.zip' ) ) {
		$_err[]=$i;
	}
	flock($fp, LOCK_UN);
	fclose($fp);
	$i++;
}
p( $_err );
только в этом случае обнуляется old.zip когда запускается второй скрипт...

-~{}~ 04.02.10 17:40:

есть подозрение что таким макаром flock не поиспользуешь ))
 

dimagolov

Новичок
я про то, что операция copy - длительная и время выполнения зависит от размера файла. можно делать rename во временный файл, который копировать, а потом проверять, если за время копирования основной файл появился (его то не было, но он мог быть создад другим скриптом), то просто удаляем временный, если нет, то переименовываем обратно.
 

predator

web designer
dimagolov неплохой вариант, только нужно учесть что копировать старый файл могут несколько клиентов поэтому надо проверять не создан ли новый и если создан то как то его лочить и опять возникают те же грабли

первый скрипт это т.с. эмуляция клиент-сервера а второй исключительно серверный скрипт который выполняется по крону

-~{}~ 04.02.10 18:10:

вобщем-то всё упирается в то чтобы файл заблокировать для записи но разрешить для чтения и проверить что файл блокирован

видел решение от stillwaiting:

Я бы сделал так: создал бы свою функцию mylock($f), myunlock($f) и islocked($f).

mylock($f) - лочит файл и создает в sys_get_temp_dir() файл "mysitename_lock15" с текущим time();
myunlock($f) - разлочивает файл и удаляет этот файл;
ismylocked() - пытается прочитать содержимое файла "mysitename_lock15" и, если разница времени, которое он хранит, с текущим time() меньше TIMEOUT значения, то возвращает true, иначе false;

Также можно ввести функцию mylocktouch(), которая обновляет значение в файле... это на случай если скрипт лочит файл надолго.

но хочется решение попроще, нативное т.с. ))
взял отсюда http://phpclub.ru/talk/showthread.php?threadid=116766
 

dimagolov

Новичок
только нужно учесть что копировать старый файл могут несколько клиентов
я не знаю кто почему и зачем там хочет у тебя копировать, но если вместо копирования ты ВСЕГДА будешь использовать последовательность
1. перемеиновали в уникальный временный файл
2. скопировали во 2-й временный файл.
3. если смогли, то переименовали в нужный, возможно удалив старую версию. и опять таки, ее можно не удалять, а переименовывавть, а удалять после успешного переименования того, что скопировали.
4. вернули 1-й временный файл на место исходного, если это возможно.

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

HraKK

Мудак
Команда форума
ps2007
Я не обязан никому помогать. Это понятно? Так, что давай ты просто прислушаешься к моему совету.
 

predator

web designer
dimagolov я понял твою схему но смотри
если допустим мы переименовали в уникальный файл и начали копировать. а в это время другой процесс тоже хочет скопировать файл, а его там нет - он переименован...

такое возможно, хотя и очень редко

-~{}~ 05.02.10 13:04:

получается надо делать цикл ожидания
что замедлит работу
копирование будет не параллельным а последовательным

-~{}~ 05.02.10 14:01:

вот тут грамотная статья про flock
http://omsk777.ru/flock.html
вывод - лучше использовать базы данных при большом трафике на Вашем сайте.
я про это тоже думал но пока воспользуюсь решением от stillwaiting
вот пример реализации от моих ребят : )

один скрипт:
PHP:
set_time_limit(0);

$i=0; 
$_err=array();
while($i<300) {
 
 while(file_exists('./test/user')) {
  echo $j++;
  sleep(1);
 }
 $f=fopen('./test/system','a');

 if ( !copy( './test/new.zip', './test/old.zip' ) ) {
        $_err[]=$i;
    }

    fclose($f);
    unlink('./test/system');
    $i++;
}
print_r( $_err );
второй скрипт:
PHP:
set_time_limit(0);

$i=0;
while($i<300) {
 while (file_exists('./test/system')) {
  echo $j++;
  sleep(1);
 }
 $f = fopen('./test/user','a');
    if ( !copy( './test/old.zip', './test/old'.$i.'.zip' ) ) {
      print( 'test' ); 
    }
    fclose($f);
    unlink('./test/user');
    
    $i++;
}
 

predator

web designer
dimagolov ага - в место где собирается пакет из разных файлов, не буду углубляться в детали
 

dimagolov

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

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

predator

web designer
архитектура нормальна если учесть что
new.zip - это последняя версия wordpress
old.zip - предыдущая
а пользователи устанавливают на своих серверах wp + могут его заранее настроить под себя.

поэтому old.zip может копироваться одновременно несколькими процессами а new.zip иногда в это вклинивается

скрипты которые я привёл - тестовые, они показывают что решение рабочее, конкретная реализация ессно может сильно отличатся.

спасибо всем за помощь : ))
 
Сверху