Модераторы: skyboy, MoLeX, Aliance, ksnk

Поиск:

Ответ в темуСоздание новой темы Создание опроса
> Multi cURL, xmlsitemap, постоянный рост RAM 
:(
    Опции темы
Psytodelist
  Дата 6.5.2012, 22:09 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 89
Регистрация: 5.3.2010

Репутация: нет
Всего: нет



Здравствуйте! Есть класс для создания xml-карты сайта:
Код

<?php
//echo $uniqid;
class sitemap
{
    private $sitemap_urls = array();
    private $base;
    private $protocol;
    private $domain;
    private $check = array();
    private $proxy = "";
    

    public function set_ignore($ignore_list){
        $this->check = $ignore_list;
    }

    public function set_proxy($host_port){
        $this->proxy = $host_port;
    }

    private function validate($url){
        $valid = true;

        foreach($this->check as $val)
        {
            if(stripos($url, $val) !== false)
            {
                $valid = false;
                break;
            }
        }
        return $valid;
    }
    

    private function multi_curl($urls){

        $curl_handlers = array();

        foreach ($urls as $url) 
        {
            $curl = curl_init();
            curl_setopt($curl, CURLOPT_URL, $url);
            curl_setopt($curl, CURLOPT_RETURNTRANSFER, 1);
            if (isset($this->proxy) && !$this->proxy == '') 
            {
                curl_setopt($curl, CURLOPT_PROXY, $this->proxy);
            }
            $curl_handlers[] = $curl;
        }

        $multi_curl_handler = curl_multi_init();
    

        foreach($curl_handlers as $key => $curl)
        {
            curl_multi_add_handle($multi_curl_handler,$curl);
        }
        

        do 
        {
            $multi_curl = curl_multi_exec($multi_curl_handler, $active);
        } 
        while ($multi_curl == CURLM_CALL_MULTI_PERFORM  || $active);
        
        foreach($curl_handlers as $curl)
        {

            if(curl_errno($curl) == CURLE_OK)
            {

                $content = curl_multi_getcontent($curl);

                $this->parse_content($content);
            }
        }
        curl_multi_close($multi_curl_handler);
        return true;
    }


    public function get_links($domain){
        
        $this->base = str_replace("http://", "", $domain);
        $this->base = str_replace("https://", "", $this->base);
        $host = explode("/", $this->base);
        $this->base = $host[0];

        $this->domain = trim($domain);
        if(strpos($this->domain, "http") !== 0)
        {
            $this->protocol = "http://";
            $this->domain = $this->protocol.$this->domain;
        }
        else
        {
            $protocol = explode("//", $domain);
            $this->protocol = $protocol[0]."//";
        }
        
        if(!in_array($this->domain, $this->sitemap_urls))
        {
            $this->sitemap_urls[] = $this->domain;
        }

        $curl = curl_init();
        curl_setopt($curl, CURLOPT_URL, $this->domain);
        if (isset($this->proxy) && !$this->proxy == '') 
        {
            curl_setopt($curl, CURLOPT_PROXY, $this->proxy);
        }
        curl_setopt($curl, CURLOPT_RETURNTRANSFER, 1);
        $page = curl_exec($curl);
        curl_close($curl);
        $this->parse_content($page);
    }
    

    private function parse_content($page){

        preg_match_all("/<a[^>]*href\s*=\s*'([^']*)'|".
                    '<a[^>]*href\s*=\s*"([^"]*)"'."/is", $page, $match);

        $new_links = array();
        for($i = 1; $i < sizeof($match); $i++)
        {

            foreach($match[$i] as $url)
            {

                if(strpos($url, "http") === false  && trim($url) !== "")
                {

                    if($url[0] == "/") $url = substr($url, 1);

                    else if($url[0] == ".")
                    {
                        while($url[0] != "/")
                        {
                            $url = substr($url, 1);
                        }
                        $url = substr($url, 1);
                    }

                    $url = $this->protocol.$this->base."/".$url;
                }

                if(!in_array($url, $this->sitemap_urls) && trim($url) !== "")
                {

                    if($this->validate($url))
                    {

                        if(strpos($url, "http://".$this->base) === 0 || strpos($url, "https://".$this->base) === 0)
                        {

                            $this->sitemap_urls[] = $url;
                            
                             mysql_query("UPDATE scans SET lastlink='".$url."', linkcounter=linkcounter+1");

                            $new_links[] = $url;
                        }
                    }
                }
            }
        }
        $this->multi_curl($new_links);
        return true;
    }


    public function get_array(){
        return $this->sitemap_urls;
    }


    public function generate_sitemap(){
        $sitemap = new SimpleXMLElement('<urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9"></urlset>');
        foreach($this->sitemap_urls as $url) 
        {
            $url_tag = $sitemap->addChild("url");
            $url_tag->addChild("loc", htmlspecialchars($url));
        }
        return $sitemap->asXML();
    }
}
?>

При сканировании ссылок больших сайтов, скрипт упирается в memory_limit,
в этот момент приблизительно выходит спарсено около 5000 ссылок (128М), увеличил до (500М) - 21000 ссылок.

Когда я пользовался простым curl, парсил большие каталоги,
то подобного постоянного роста RAM я не замечал.
Данные заносились в БД.

Тут же мы видем, что данные сохраняются в переменной.
Именно это вызывает рост потребляемой оперативной памяти или что-то другое?
Посоветуйте, пожалуйста, как оптимизировать данный класс. Благодарю.

Это сообщение отредактировал(а) Psytodelist - 6.5.2012, 22:18
PM MAIL   Вверх
Wolf1994
Дата 7.5.2012, 11:00 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
***


Профиль
Группа: Завсегдатай
Сообщений: 1701
Регистрация: 5.10.2004

Репутация: нет
Всего: 29



Цитата(Psytodelist @  6.5.2012,  22:09 Найти цитируемый пост)
Тут же мы видем, что данные сохраняются в переменной.
Именно это вызывает рост потребляемой оперативной памяти или что-то другое?

Можно узнать, закомментировав сохранение данных:

Код

//            $url_tag = $sitemap->addChild("url");
//            $url_tag->addChild("loc", htmlspecialchars($url));


Цитата(Psytodelist @  6.5.2012,  22:09 Найти цитируемый пост)
  mysql_query("UPDATE scans SET lastlink='".$url."', linkcounter=linkcounter+1");

То же можно записывать в переменную, а в SQL - после выполенения класса.

Это сообщение отредактировал(а) Wolf1994 - 7.5.2012, 11:36
PM MAIL WWW   Вверх
Wolf1994
Дата 7.5.2012, 11:41 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
***


Профиль
Группа: Завсегдатай
Сообщений: 1701
Регистрация: 5.10.2004

Репутация: нет
Всего: 29



Цитата(Psytodelist @  6.5.2012,  22:09 Найти цитируемый пост)
Именно это вызывает рост потребляемой оперативной памяти или что-то другое?

Размер ссылки почти всегда не больше четверти килобайта. 21000 / 4 = 5 Мб.

Ошибка в том, что скрипт обрабатывает новые ссылки, не закончив обработку уже имеющихся. То есть, одновременно создаёт очень много запросов через cURL.
PM MAIL WWW   Вверх
Wolf1994
Дата 7.5.2012, 11:59 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
***


Профиль
Группа: Завсегдатай
Сообщений: 1701
Регистрация: 5.10.2004

Репутация: нет
Всего: 29



Решение.

Код

    private $sitemap_urls = array();
    private $new_links = array();// Объявить new_links на глобальном уровне

    private function parse_content($page){
...
//       $this->multi_curl($new_links); - закомментировать


multi_curl($new_links); вызывать после каждого выполнения multi_curl (), при условии, что массив не пустой, очищая  $new_links перед обращением:

Код

while (sizeof ($new_links)>0)
{
 $new_links_tmp=$new_links;
 unset ($new_links);
 private $new_links = array();// Не владею ООП и не уверен, что правильно так
 multi_curl($new_links_tmp);
 unset ($new_links_tmp);
}

PM MAIL WWW   Вверх
Psytodelist
Дата 7.5.2012, 12:42 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 89
Регистрация: 5.3.2010

Репутация: нет
Всего: нет



Цитата(Wolf1994 @ 7.5.2012,  11:00)
Цитата(Psytodelist @  6.5.2012,  22:09 Найти цитируемый пост)
Тут же мы видем, что данные сохраняются в переменной.
Именно это вызывает рост потребляемой оперативной памяти или что-то другое?

Можно узнать, закомментировав сохранение данных:

Код

//            $url_tag = $sitemap->addChild("url");
//            $url_tag->addChild("loc", htmlspecialchars($url));


Цитата(Psytodelist @  6.5.2012,  22:09 Найти цитируемый пост)
  mysql_query("UPDATE scans SET lastlink='".$url."', linkcounter=linkcounter+1");

То же можно записывать в переменную, а в SQL - после выполенения класса.

Код

//            $url_tag = $sitemap->addChild("url");
//            $url_tag->addChild("loc", htmlspecialchars($url));


- это вообще вызывается по завершении
программы, идет форматирование массива ссылок в XML

Цитата(Psytodelist @  6.5.2012,  22:09 Найти цитируемый пост)
  mysql_query("UPDATE scans SET lastlink='".$url."', linkcounter=linkcounter+1");

Что именно записывать в переменную? Зачем?
Это счетчик для AJAX, чтобы видеть прогресс в реальном времени.
Забыл дописать WHERE uniqid='$uniqid' , но это не страшно.

Добавлено через 2 минуты и 8 секунд
Цитата(Wolf1994 @ 7.5.2012,  11:59)
Решение.

Код

    private $sitemap_urls = array();
    private $new_links = array();// Объявить new_links на глобальном уровне

    private function parse_content($page){
...
//       $this->multi_curl($new_links); - закомментировать


multi_curl($new_links); вызывать после каждого выполнения multi_curl (), при условии, что массив не пустой, очищая  $new_links перед обращением:

Код

while (sizeof ($new_links)>0)
{
 $new_links_tmp=$new_links;
 unset ($new_links);
 private $new_links = array();// Не владею ООП и не уверен, что правильно так
 multi_curl($new_links_tmp);
 unset ($new_links_tmp);
}

Цитата

// Не владею ООП и не уверен, что правильно так


Спасибо хоть за попытку помочь, 
а-то гуры-партизаны или их вообще тут нет.
PM MAIL   Вверх
Fortop
Дата 7.5.2012, 13:07 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Завсегдатай
Сообщений: 2200
Регистрация: 13.11.2007
Где: Донецк

Репутация: 1
Всего: 42



Psytodelist, лень

Проблема собственно в том, что не очищается какая-то из переменных в процессе циклов.
А искать ее желания нет smile

Попробуйте делать unset объектам связанным с запросами после каждых 5000 (или сколько у вас там) ссылок.


--------------------
Мир это Я.
Живее всех живых.
PM MAIL   Вверх
Wolf1994
Дата 7.5.2012, 14:28 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
***


Профиль
Группа: Завсегдатай
Сообщений: 1701
Регистрация: 5.10.2004

Репутация: нет
Всего: 29



Цитата(Psytodelist @  7.5.2012,  12:42 Найти цитируемый пост)
- это вообще вызывается по завершении

Потому и зачеркнул ответ (надо было стереть, наверно).

Цитата(Psytodelist @  7.5.2012,  12:42 Найти цитируемый пост)
Что именно записывать в переменную? Зачем?

21000 UPDATE'ов не займут памяти, но немного (в зависимости от "железа" и типа таблицы) нагрузят систему без особой на то необходимости (для AJAX'а хватит и записи в файл и не на каждой итерации).

Цитата(Psytodelist @  7.5.2012,  12:42 Найти цитируемый пост)
Спасибо хоть за попытку помочь, 
а-то гуры-партизаны или их вообще тут нет. 

Вопрос не имеет отношения к уровню владения языком, а связан с алгоритмом, который создаёт многоуровневую параллельную обработку, вместо последовательной.

Имел в виду, что не знаю, как пересоздавать массив при объектно-ориентированном стиле.
PM MAIL WWW   Вверх
Psytodelist
  Дата 7.5.2012, 16:47 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 89
Регистрация: 5.3.2010

Репутация: нет
Всего: нет



Wolf1994, я приблизительно понял в чем причина.
Проштудировал весь код memory_get_usage()
и выяснил, что память занимают переменные,
которые получают результат от curl_exec() и curl_multi_exec() .
Т.е. переменные $page = curl_exec($curl); и $multi_curl = curl_multi_exec($multi_curl_handler, $active); 
А это - целые страницы... Теперь попробую как-то это дело исправить.  smile

Это сообщение отредактировал(а) Psytodelist - 7.5.2012, 17:11
PM MAIL   Вверх
Wolf1994
Дата 7.5.2012, 17:05 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
***


Профиль
Группа: Завсегдатай
Сообщений: 1701
Регистрация: 5.10.2004

Репутация: нет
Всего: 29



Цитата(Psytodelist @  7.5.2012,  16:47 Найти цитируемый пост)

Т.е. переменные $page = curl_exec($curl); и $multi_curl = curl_multi_exec($multi_curl_handler, $active); 

Да, из-за того, что каждая ссылка ведёт к созданию новых cURL запросов, которые создают под-запросы и так до бесконечности (в зависимости от структуры сайта и количества ссылок) - поэтому выделятся память под всё это и на стороне cURL и на PHP: под переменные, которые получают по нему страницы.
PM MAIL WWW   Вверх
Psytodelist
Дата 7.5.2012, 17:16 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 89
Регистрация: 5.3.2010

Репутация: нет
Всего: нет



Цитата(Wolf1994 @ 7.5.2012,  17:05)
Цитата(Psytodelist @  7.5.2012,  16:47 Найти цитируемый пост)

Т.е. переменные $page = curl_exec($curl); и $multi_curl = curl_multi_exec($multi_curl_handler, $active); 

Да, из-за того, что каждая ссылка ведёт к созданию новых cURL запросов, которые создают под-запросы и так до бесконечности (в зависимости от структуры сайта и количества ссылок) - поэтому выделятся память под всё это и на стороне cURL и на PHP: под переменные, которые получают по нему страницы.

Походу ему все-равно на то, что я поставил unset-ы

curl_multi_close($multi_curl_handler);
unset($multi_curl, $content);

$this->parse_content($page);
unset($page);

 smile 
PM MAIL   Вверх
Wolf1994
Дата 7.5.2012, 17:42 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
***


Профиль
Группа: Завсегдатай
Сообщений: 1701
Регистрация: 5.10.2004

Репутация: нет
Всего: 29



Цитата(Psytodelist @  7.5.2012,  17:16 Найти цитируемый пост)
Походу ему все-равно на то, что я поставил unset-ы

Потому что unset'ы срабатывают после вложенного запроса. То есть, $content через $this->parse_content($content); сначала передаётся в функцию parse_content, которая снова обращается к функции multi_curl и только по возвращению из последней происходит unset переданной переменной.
PM MAIL WWW   Вверх
Psytodelist
Дата 7.5.2012, 17:45 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 89
Регистрация: 5.3.2010

Репутация: нет
Всего: нет



Цитата(Wolf1994 @ 7.5.2012,  17:42)
Цитата(Psytodelist @  7.5.2012,  17:16 Найти цитируемый пост)
Походу ему все-равно на то, что я поставил unset-ы

Потому что unset'ы срабатывают после вложенного запроса. То есть, $content через $this->parse_content($content); сначала передаётся в функцию parse_content, которая снова обращается к функции multi_curl и только по возвращению из последней происходит unset переданной переменной.

Ага, точно. Исправить это надежды нет?

Добавлено через 4 минуты и 53 секунды
strlen-ом проверил переменную $content.
Именно она, зараза, кушает оперативку.
И как её ансетить при устовии многопоточной рекурсии, 
если можно это так назвать, я не знаю  smile 
PM MAIL   Вверх
Psytodelist
Дата 7.5.2012, 18:03 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 89
Регистрация: 5.3.2010

Репутация: нет
Всего: нет



unset($page);
в конце скрипта - помогает,
а unset($content); - нет
unset($page); удаляет самое первое обращение к странице
посредством простого курла. А когда я пишу unset($content);
он не поймет же. Или поймет и-то в том цикле и-то если
успеет закончится рекурсия.  smile


Это сообщение отредактировал(а) Psytodelist - 7.5.2012, 18:18
PM MAIL   Вверх
Wolf1994
Дата 7.5.2012, 18:19 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
***


Профиль
Группа: Завсегдатай
Сообщений: 1701
Регистрация: 5.10.2004

Репутация: нет
Всего: 29



Цитата(Psytodelist @  7.5.2012,  17:45 Найти цитируемый пост)
Ага, точно. Исправить это надежды нет?


Код

<?php
//echo $uniqid;
class sitemap
{
    private $sitemap_urls = array();
    private $new_links = array();
    private $new_links_i = 0;
    private $base;
    private $protocol;
    private $domain;
    private $check = array();
    private $proxy = "";
    
    public function set_ignore($ignore_list){
        $this->check = $ignore_list;
    }
    public function set_proxy($host_port){
        $this->proxy = $host_port;
    }
    private function validate($url){
        $valid = true;
        foreach($this->check as $val)
        {
            if(stripos($url, $val) !== false)
            {
                $valid = false;
                break;
            }
        }
        return $valid;
    }
    
    private function multi_curl($urls){
        $curl_handlers = array();
//        foreach ($urls as $url) 
        for ($i=0; $i<$new_links_i; $i++)
        {
            $curl = curl_init();
            curl_setopt($curl, CURLOPT_URL, $urls [$i]);
            curl_setopt($curl, CURLOPT_RETURNTRANSFER, 1);
            if (isset($this->proxy) && !$this->proxy == '') 
            {
                curl_setopt($curl, CURLOPT_PROXY, $this->proxy);
            }
            $curl_handlers[] = $curl;
        }
        $multi_curl_handler = curl_multi_init();
    
        foreach($curl_handlers as $key => $curl)
        {
            curl_multi_add_handle($multi_curl_handler,$curl);
        }
        
        do 
        {
            $multi_curl = curl_multi_exec($multi_curl_handler, $active);
        } 
        while ($multi_curl == CURLM_CALL_MULTI_PERFORM  || $active);
        
        foreach($curl_handlers as $curl)
        {
            if(curl_errno($curl) == CURLE_OK)
            {
                $content = curl_multi_getcontent($curl);
                $this->parse_content($content);
            }
        }
        curl_multi_close($multi_curl_handler);
        return true;
    }
    public function get_links($domain){
        
        $this->base = str_replace("http://", "", $domain);
        $this->base = str_replace("https://", "", $this->base);
        $host = explode("/", $this->base);
        $this->base = $host[0];
        $this->domain = trim($domain);
        if(strpos($this->domain, "http") !== 0)
        {
            $this->protocol = "http://";
            $this->domain = $this->protocol.$this->domain;
        }
        else
        {
            $protocol = explode("//", $domain);
            $this->protocol = $protocol[0]."//";
        }
        
        if(!in_array($this->domain, $this->sitemap_urls))
        {
            $this->sitemap_urls[] = $this->domain;
        }
        $curl = curl_init();
        curl_setopt($curl, CURLOPT_URL, $this->domain);
        if (isset($this->proxy) && !$this->proxy == '') 
        {
            curl_setopt($curl, CURLOPT_PROXY, $this->proxy);
        }
        curl_setopt($curl, CURLOPT_RETURNTRANSFER, 1);
        $page = curl_exec($curl);
        curl_close($curl);

        $this->parse_content($page);

        while ($new_links_i>0)
        {
         $new_links_i=0;
         multi_curl($new_links);
        }
    }
    
    private function parse_content($page){
        preg_match_all("/<a[^>]*href\s*=\s*'([^']*)'|".
                    '<a[^>]*href\s*=\s*"([^"]*)"'."/is", $page, $match);
//        $new_links = array();
        for($i = 1; $i < sizeof($match); $i++)
        {
            foreach($match[$i] as $url)
            {
                if(strpos($url, "http") === false  && trim($url) !== "")
                {
                    if($url[0] == "/") $url = substr($url, 1);
                    else if($url[0] == ".")
                    {
                        while($url[0] != "/")
                        {
                            $url = substr($url, 1);
                        }
                        $url = substr($url, 1);
                    }
                    $url = $this->protocol.$this->base."/".$url;
                }
                if(!in_array($url, $this->sitemap_urls) && trim($url) !== "")
                {
                    if($this->validate($url))
                    {
                        if(strpos($url, "http://".$this->base) === 0 || strpos($url, "https://".$this->base) === 0)
                        {
                            $this->sitemap_urls[] = $url;
                            
                             mysql_query("UPDATE scans SET lastlink='".$url."', linkcounter=linkcounter+1");
                            $new_links[$new_links_i] = $url;
                            $new_links_i++;
                        }
                    }
                }
            }
        }

//        $this->multi_curl($new_links);
        return true;
    }
    public function get_array(){
        return $this->sitemap_urls;
    }
    public function generate_sitemap(){
        $sitemap = new SimpleXMLElement('<urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9"></urlset>');
        foreach($this->sitemap_urls as $url) 
        {
            $url_tag = $sitemap->addChild("url");
            $url_tag->addChild("loc", htmlspecialchars($url));
        }
        return $sitemap->asXML();
    }
}
?>


Есть, изменив параллельную работу на последовательную. Не проверял, но логику можно понять.

Ключевые изменения:
Код

// Прерывание рекурсии
//        $this->multi_curl($new_links);


Код

// Последовательный вызов multi_curl для каждого массива ссылок
        while ($new_links_i>0)
        {
         $new_links_i=0;
         multi_curl($new_links);
        }


Это сообщение отредактировал(а) Wolf1994 - 7.5.2012, 18:21
PM MAIL WWW   Вверх
Psytodelist
Дата 7.5.2012, 18:21 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 89
Регистрация: 5.3.2010

Репутация: нет
Всего: нет



Код

  $uniqcontentid = md5(uniqid(rand(), true));
                $GLOBALS['content'][$uniqcontentid] = curl_multi_getcontent($curl);
                
                $this->parse_content($GLOBALS['content'][$uniqcontentid], $uniqcontentid);


в конце $this->parse_content()
unset($GLOBALS['content'][$uniqcontentid]);
не помогло  smile 
PM MAIL   Вверх
Ответ в темуСоздание новой темы Создание опроса

Внимание: данный раздел предназначен для решения сложных, нестандартных задач.

 
1 Пользователей читают эту тему (1 Гостей и 0 Скрытых Пользователей)
0 Пользователей:
« Предыдущая тема | PHP: Для профи | Следующая тема »


 




[ Время генерации скрипта: 0.1097 ]   [ Использовано запросов: 21 ]   [ GZIP включён ]


Реклама на сайте     Информационное спонсорство

 
По вопросам размещения рекламы пишите на vladimir(sobaka)vingrad.ru
Отказ от ответственности     Powered by Invision Power Board(R) 1.3 © 2003  IPS, Inc.