Анимация
JavaScript


Главная  Библионтека 

0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 [ 165 ] 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189

$Prg=array(

"Todo" => array($Root), для накопления путей необработанн1х файлов "Res" => array() результат обработки всех файлов

Пытаемся загрузить текущее состояние. Если не получается, значит, обход только что начался.

if($f=@fopen($cache,"rb")) {

if(@flock($f,LOCK SH)) {

$Prg=Unserialize(fread($f,filesize($cache)));

fclose($f);

Обходим сайт - по одной итерации цикла на кажд1Й файл или каталог. Найденн1е файл: добавляются в конец массива $Prg[Res], а подвергающиеся обработке - извлекаются из его начала. Таким образом, мы продолжаем процесс до тех пор, пока не будут " пройдены" все файлы на сервере.

do {

очередное полное имя файла

$fname=array shift($Prg[Todo]);

если это не файл и не каталог, пропускаем

if(!@is file($fname) && !@is dir($fname)) continue;

если это каталог, добавляем все его содержимое

if(@is dir($fname)) { $Files=array();

for($d=openDir($fname); $e=readDir($d); ) {

if($e=="."$e=="..") continue;

$Files[]="$fname/$e";

closeDir($d);

вставляем в начало массива, чтобы на следующей итерации цикла обрабатывались именно эти файлы $Prg[Todo]=array merge($Files,$Prg[Todo]);

вызываем функцию для обработки очередного файла или каталога $Func($fname,$Prg[Res]);

выходим, если время истекло, или же необработанных файлов не осталось.



} while(time()-$Start<$time && count($Prg[Todo]));

Вернуть текущий результат в $Result. $Result=$Prg[Res];

Если еще есть файлы для обработки, сохранить состояние. if(count($Prg[Todo])) {

Сохраняем текущее состояние. В следующий раз мы начнем с него.

$f=fopen($cache,"a+b");

flock($f,LOCK EX);

ftruncate($f,0);

fwrite($f,Serialize($Prg));

fflush($f); fclose($f);

return true; процесс продолжается

Иначе процесс закончился. Удалить файл состояния.

@unlink($cache);

return false;

?>

Я не буду приводить здесь реальный сценарий для построения карты сервера, потому что он слишком велик и, к тому же, довольно однообразен и неинтересен. Вся "изюминка" заключена именно в функции WalkSite(). Листинг 33.2 содержит небольшую "демонстрацию" ее возможностей. Сценарий собирает сведения о размере каждого файла сайта, печатая на каждом этапе имена обработанных объектов, а затем выводит сводную информацию.

i Листинг 33.2. Демонстрация возможностей функции Walksiteо : demo.php

<?

Подключаем библиотекаря " прямым" способом. include "$DOCUMENT ROOT/php/Librarian.phl"; Подключаем модуль с функцией WalkSite(). Uses("SiteWalker");

Эта функция будет вызываться для каждого файла на сервере.

Ее задача - добавить обработанные данные из этого файла

в массив $Result ( формат определяется назначением этих данных).

function Walk($fname,&$Result)

{ для диагностики выводим имя файла



print ">$fname<br>";

в качестве примера - просто добавляем имя файла в массив $Result[]="$fname: <b>".filesize($fname)."</b>";

Если WalkSite() вернула false, значит, процесс закончился.

if(!WalkSite($DOCUMENT ROOT,"Walk","map",0,$Result)) { В качестве примера просто в1водим содержимое массива, сформированного вызовами функции Walk(). Реальн1Й код должен б1л бы в1рабат1вать HTML-представление карты, данные которой накоплены в $Result. print "<hr>";

print join("<br>\n",$Result);

} else {

для примера заставляем страницу обновить саму себя,

имитируя многократные посещения пользователей.

print "<meta http-equiv=refresh content=0; url=$SCRIPT NAME>";

?>

В этом сценарии функции WalkSite() передается 0 как значение размера кванта времени, в течение которого можно собирать данные о сайте. Это означает, что файлы будут обрабатываться по одному при каждом запросе. В реальном коде карты сервера, конечно, это не так - нужно указывать приемлемый промежуток времени, чтобы в него "уложилась" обработка сразу нескольких страниц. Чем меньше будет этот промежуток, тем менее заметным для пользователя станет замедление, связанное с работой сценария, но тем значительнее будут "накладные расходы", вызванные работой функций сериализации. Так что тут нужно выбирать некоторый "средний" вариант. Проще всего это сделать опытным путем - например, так, чтобы примерно за час при известной посещаемости успевала перестроиться вся карта сервера.

Примечание

Функция WalkSite() из листинга 33.2 работает с файлами, устанавливая на них рекомендательные блокировки. Этот процесс хоть и позволяет обойти проблемы с разделением доступа к файлам, немного сложен для понимания. Он подробно описан в главе l5 части IV.

Использование самопереадресации

Термин самопереадресация (или, в английском варианте, self-redirect) означает свойство сценария подавать в браузер клиента запрос, заставляющий его (браузер) заново



0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 [ 165 ] 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189