<?xml version="1.0" encoding="utf-8"?>
<feed xmlns="http://www.w3.org/2005/Atom">
    <title>Блог Джакала</title>
    <link rel="alternate" type="text/html" href="http://jackal.in/" />
    <link rel="self" type="application/atom+xml" href="http://jackal.in/atom.xml" />
    <id>tag:jackal.in,2008-08-14://1</id>
    <updated>2009-05-18T12:42:48Z</updated>
    
    <generator uri="http://www.sixapart.com/movabletype/">Movable Type 4.2-en</generator>

<entry>
    <title>Тестинг Catalyst::Plugin::Session::Store::DBI</title>
    <link rel="alternate" type="text/html" href="http://jackal.in/2009/05/testing-catalystpluginsessionstoredbi.html" />
    <id>tag:jackal.in,2009://1.20</id>

    <published>2009-05-18T12:34:34Z</published>
    <updated>2009-05-18T12:42:48Z</updated>

    <summary> Как известно, этот модуль хранит сессии в текстовых полях в base64(nfreeze($data)), что является явно избыточным, т.к. можно юзать только Storable и blob для хранения. Поэтому - небольшой тестик: nfreeze: time: 331 sec; speed: 3021 req/sec thaw: time: 213 sec;...</summary>
    <author>
        <name>jackal</name>
        
    </author>
    
        <category term="Catalyst" scheme="http://www.sixapart.com/ns/types#category" />
    
        <category term="perl" scheme="http://www.sixapart.com/ns/types#category" />
    
    <category term="base64" label="base64" scheme="http://www.sixapart.com/ns/types#tag" />
    <category term="catalyst" label="catalyst" scheme="http://www.sixapart.com/ns/types#tag" />
    <category term="perl" label="perl" scheme="http://www.sixapart.com/ns/types#tag" />
    <category term="profiling" label="profiling" scheme="http://www.sixapart.com/ns/types#tag" />
    <category term="session" label="session" scheme="http://www.sixapart.com/ns/types#tag" />
    <category term="storable" label="storable" scheme="http://www.sixapart.com/ns/types#tag" />
    
    <content type="html" xml:lang="en" xml:base="http://jackal.in/">
        <![CDATA[ <p>Как известно, этот модуль хранит сессии в текстовых полях в base64(nfreeze($data)), что является явно избыточным, т.к. можно юзать только Storable и blob для хранения. Поэтому - небольшой тестик:</p>
<pre>
nfreeze: time: 331 sec; speed: 3021 req/sec
thaw:    time: 213 sec; speed: 4694 req/sec
encode_base64: time: 67 sec; speed: 14925 req/sec
decode_base64: time: 116 sec; speed: 8620 req/sec
STORE: time: 399 sec; speed: 2506 req/sec
GET:   time: 328 sec; speed: 3048 req/sec
</pre>
<p>В тесте разложены методы MIME::Base64 и Storable, а также - всё вместе.</p>
<p>Как видно, производительность base64 явно избыточна, т.ч. в большинстве случаев можно не париться по этому поводу.</p>

<span class="mt-enclosure mt-enclosure-file" style="display: inline;"><a href="http://jackal.in/files/t_sess.txt">t_sess.txt</a></span>]]>
        
    </content>
</entry>

<entry>
    <title>Тестинг Ямла</title>
    <link rel="alternate" type="text/html" href="http://jackal.in/2009/05/testing-jamla.html" />
    <id>tag:jackal.in,2009://1.19</id>

    <published>2009-05-18T11:46:49Z</published>
    <updated>2009-05-18T12:44:35Z</updated>

    <summary>Собсно профайлингом занималсо, заодно YAML затестил, скорость Load и Dump разных модулей. Вот результаты: YAML::Load: time: 361 sec; speed: 277 req/sec YAML::Dump: time: 203 sec; speed: 492 req/sec YAML::Syck::Load: time: 130 sec; speed: 7692 req/sec YAML::Syck::Dump: time: 86 sec; speed:...</summary>
    <author>
        <name>jackal</name>
        
    </author>
    
        <category term="perl" scheme="http://www.sixapart.com/ns/types#category" />
    
    <category term="memoryleak" label="memory leak" scheme="http://www.sixapart.com/ns/types#tag" />
    <category term="perl" label="perl" scheme="http://www.sixapart.com/ns/types#tag" />
    <category term="profiling" label="profiling" scheme="http://www.sixapart.com/ns/types#tag" />
    <category term="speed" label="speed" scheme="http://www.sixapart.com/ns/types#tag" />
    <category term="syck" label="syck" scheme="http://www.sixapart.com/ns/types#tag" />
    <category term="xs" label="xs" scheme="http://www.sixapart.com/ns/types#tag" />
    <category term="yaml" label="yaml" scheme="http://www.sixapart.com/ns/types#tag" />
    
    <content type="html" xml:lang="en" xml:base="http://jackal.in/">
        <![CDATA[<p>Собсно профайлингом занималсо, заодно YAML затестил, скорость Load и Dump разных модулей.</p>
<p>Вот результаты:</p>
<pre>YAML::Load:       time: 361 sec; speed:   277 req/sec
YAML::Dump:       time: 203 sec; speed:   492 req/sec
YAML::Syck::Load: time: 130 sec; speed:  7692 req/sec
YAML::Syck::Dump: time:  86 sec; speed: 11627 req/sec
YAML::XS::Load:   time: 124 sec; speed:  8064 req/sec
YAML::XS::Dump:   time: 118 sec; speed:  8474 req/sec
</pre>
<p>
Для pureperl - 100к циклов, для остального - 1кк.
</p>
<p>Кстати, у YAML::XS::Load утечки памяти сильные, по крайней мере на freebsd (7.2 и 8.0, i386 и amd64 соответственно). За лям итераций <a href="http://rt.cpan.org/Public/Bug/Display.html?id=46172" target="_blank">съело 1G оперативы.</a></p>

<span class="mt-enclosure mt-enclosure-file" style="display: inline;"><a href="http://jackal.in/files/t_yaml.txt">t_yaml.pl</a></span>

<p>
Вопреки стереотипам, YAML::Syck показал бОльшую производительность, чем YAML::XS. Плюс последний течет :) Ну а про pure perl вообще сказать нечего. Работает стабильно, но меееееееедленно.
</p>]]>
        
    </content>
</entry>

<entry>
    <title>Как пропатчить KDE под... Windows?</title>
    <link rel="alternate" type="text/html" href="http://jackal.in/2009/02/kak-propatchit--kde-pod-windows.html" />
    <id>tag:jackal.in,2009://1.18</id>

    <published>2009-02-03T21:01:58Z</published>
    <updated>2009-02-03T21:04:25Z</updated>

    <summary>Серьезно :) 28 января 2009г. вышел первый релиз KDE под Windows.Интересно, как это выглядит :)))...</summary>
    <author>
        <name>jackal</name>
        
    </author>
    
        <category term="kde" scheme="http://www.sixapart.com/ns/types#category" />
    
    <category term="kde" label="KDE" scheme="http://www.sixapart.com/ns/types#tag" />
    <category term="windows" label="windows" scheme="http://www.sixapart.com/ns/types#tag" />
    
    <content type="html" xml:lang="en" xml:base="http://jackal.in/">
        <![CDATA[Серьезно :) 28 января 2009г. вышел первый <a href="http://windows.kde.org/" target="_blank">релиз</a> KDE под Windows.<br />Интересно, как это выглядит :)))<br /><br /><br /> ]]>
        
    </content>
</entry>

<entry>
    <title>radeon x1400 under freebsd</title>
    <link rel="alternate" type="text/html" href="http://jackal.in/2008/12/radeon-x1400-under-freebsd.html" />
    <id>tag:jackal.in,2008://1.17</id>

    <published>2008-12-18T11:09:43Z</published>
    <updated>2009-02-03T21:50:06Z</updated>

    <summary>Удалось полноценно заставить работать radeon x1400 под freebsd 8-current :) DRI, GL, 3D, все дела...Надо накатить патч на drm_scatter и пропатчить дерево портов (чтобы апнуть xorg. Дерево сейчас заморожено, пока 7.1 релизят).Подробности и ссылки на патчи тут....</summary>
    <author>
        <name>jackal</name>
        
    </author>
    
        <category term="freebsd" scheme="http://www.sixapart.com/ns/types#category" />
    
    <category term="dri" label="dri" scheme="http://www.sixapart.com/ns/types#tag" />
    <category term="drm" label="drm" scheme="http://www.sixapart.com/ns/types#tag" />
    <category term="freebsd" label="freebsd" scheme="http://www.sixapart.com/ns/types#tag" />
    <category term="radeon" label="radeon" scheme="http://www.sixapart.com/ns/types#tag" />
    <category term="x1400" label="x1400" scheme="http://www.sixapart.com/ns/types#tag" />
    <category term="xorg" label="xorg" scheme="http://www.sixapart.com/ns/types#tag" />
    
    <content type="html" xml:lang="en" xml:base="http://jackal.in/">
        <![CDATA[Удалось полноценно заставить работать radeon x1400 под freebsd 8-current :) DRI, GL, 3D, все дела...<br />Надо накатить патч на drm_scatter и пропатчить дерево портов (чтобы апнуть xorg. Дерево сейчас заморожено, пока 7.1 релизят).<br /><br />Подробности и ссылки на патчи <a href="http://lists.freebsd.org/pipermail/freebsd-x11/2008-December/006980.html" target="_blank">тут</a>. ]]>
        
    </content>
</entry>

<entry>
    <title>Flash9 на freebsd ЗАРАБОТАЛ!</title>
    <link rel="alternate" type="text/html" href="http://jackal.in/2008/11/flash9-na-freebsd-zarabotal.html" />
    <id>tag:jackal.in,2008://1.16</id>

    <published>2008-11-26T22:39:51Z</published>
    <updated>2008-11-26T22:53:12Z</updated>

    <summary>Ура! Наконец-то, свершилось! Полноценно, стабильно заработал adobe flash9 на freebsd!В середине октября чего-то там пофиксили с compat_linux вроде как, т.о. на данный момент необходимо апнуться до 7-stable. А потом по инструкции :) Кстати, у меня вместо linux_base-f8 - linux_base-fc4 -...</summary>
    <author>
        <name>jackal</name>
        
    </author>
    
        <category term="freebsd" scheme="http://www.sixapart.com/ns/types#category" />
    
    <category term="adobeflash" label="adobe flash" scheme="http://www.sixapart.com/ns/types#tag" />
    <category term="flash9" label="flash 9" scheme="http://www.sixapart.com/ns/types#tag" />
    <category term="flash9" label="flash9" scheme="http://www.sixapart.com/ns/types#tag" />
    <category term="freebsd" label="freebsd" scheme="http://www.sixapart.com/ns/types#tag" />
    
    <content type="html" xml:lang="en" xml:base="http://jackal.in/">
        <![CDATA[<p>Ура! Наконец-то, свершилось! Полноценно, <b>стабильно</b> заработал adobe flash9 на freebsd!</p><p>В середине октября чего-то там пофиксили с compat_linux вроде как, т.о. на данный момент необходимо апнуться до 7-stable. А потом по <a href="http://www.opennet.ru/tips/info/1822.shtml" target="_blank">инструкции</a> :) </p><p>Кстати, у меня вместо linux_base-f8 - linux_base-fc4 - тоже всё прекрасно работает, как в фф2, так и в фф3.</p>]]>
        
    </content>
</entry>

<entry>
    <title>$c-&gt;forward() возвращает истину</title>
    <link rel="alternate" type="text/html" href="http://jackal.in/2008/10/c-forward-vozvraschaet-istinu.html" />
    <id>tag:jackal.in,2008://1.15</id>

    <published>2008-10-23T13:31:42Z</published>
    <updated>2008-10-23T13:46:39Z</updated>

    <summary><![CDATA[ $c-&gt;forward() возвращает только истину. Истину в последней инстанции :) А серьезно, он может вернуть лишь одно значение. И оно должно быть истинно. Если оно ложно - результатом будет ноль. И неважно, что вы хотели вернуть пустую строку или undef....]]></summary>
    <author>
        <name>jackal</name>
        
    </author>
    
        <category term="Catalyst" scheme="http://www.sixapart.com/ns/types#category" />
    
        <category term="perl" scheme="http://www.sixapart.com/ns/types#category" />
    
    <category term="catalyst" label="catalyst" scheme="http://www.sixapart.com/ns/types#tag" />
    <category term="forward" label="forward" scheme="http://www.sixapart.com/ns/types#tag" />
    <category term="perl" label="perl" scheme="http://www.sixapart.com/ns/types#tag" />
    
    <content type="html" xml:lang="en" xml:base="http://jackal.in/">
        <![CDATA[ <p>$c-&gt;forward() возвращает только истину. Истину в последней инстанции :)</p>
<p>А серьезно, он может вернуть лишь одно значение. И оно должно быть истинно. Если оно ложно - результатом будет ноль. И неважно, что вы хотели вернуть пустую строку или undef. Вернется ноль.</p>
<p>Массивы и хеши тоже нельзя возвращать. Т.к. получите последний элемент массива. Ссылки на них - пожалуйста. Ибо ссылка на массив истинна, даже если массив пустой.</p>
<p>Вот собственно и всё :) Теперь чуток примерчиков для наглядности:</p>
<pre>sub t_zero   { 0           };
sub t_empty  { ""          };
sub t_undef  { undef       };
sub t_arr    { qw/a b c/   };
sub t_scalar { "ok"        };
sub t_arref  { [qw/a b c/] };
sub t_hashref{ {}          };

sub test {
    my ( $self, $c ) = @_;
    $c-&gt;forward('t_zero');    # 0
    $c-&gt;forward('t_empty');   # 0
    $c-&gt;forward('t_undef');   # 0
    $c-&gt;forward('t_arr');     # 'c'
    $c-&gt;forward('t_scalar');  # 'ok'
    $c-&gt;forward('t_arref');   # ['a', 'b', 'c']
    $c-&gt;forward('t_hashref'); # {}
};
</pre>
]]>
        
    </content>
</entry>

<entry>
    <title>rrdtool и freebsd</title>
    <link rel="alternate" type="text/html" href="http://jackal.in/2008/10/rrdtool-i-freebsd.html" />
    <id>tag:jackal.in,2008://1.14</id>

    <published>2008-10-07T10:51:49Z</published>
    <updated>2008-10-07T11:06:15Z</updated>

    <summary> Всю жизнь свою юзал rrdtool из портов, и не заморачивался, и всё было хорошо. Но недавно её апнули до версии 1.3.x, и теперь она вместо libart_lgpl юзает cairo... а cairo тянет половину иксов. Откатился до rrdtool10, а она страшненькая...</summary>
    <author>
        <name>jackal</name>
        
    </author>
    
        <category term="freebsd" scheme="http://www.sixapart.com/ns/types#category" />
    
    <category term="freebsd" label="freebsd" scheme="http://www.sixapart.com/ns/types#tag" />
    <category term="port" label="port" scheme="http://www.sixapart.com/ns/types#tag" />
    <category term="rrdtool" label="rrdtool" scheme="http://www.sixapart.com/ns/types#tag" />
    
    <content type="html" xml:lang="en" xml:base="http://jackal.in/">
        <![CDATA[ <p>Всю жизнь свою юзал rrdtool из портов, и не заморачивался, и всё было хорошо. 
Но недавно её апнули до версии 1.3.x, и теперь она вместо libart_lgpl юзает cairo... а cairo тянет половину иксов.</p>
<p>Откатился до rrdtool10, а она страшненькая какая-то... непривычно. 
Вообщем на одном из серверов лежала 1.2.23, которую я с удовольствием и поставил :)</p>
<p>На всякий случай выкладываю, т.к. я хз где старый порт брать.</p>
<span class="mt-enclosure mt-enclosure-file" style="display: inline;"><a href="http://jackal.in/files/rrdtool_1_2_23.tar.gz">rrdtool_1_2_23.tar.gz</a></span>]]>
        
    </content>
</entry>

<entry>
    <title>Выборка рандомных элементов из массива</title>
    <link rel="alternate" type="text/html" href="http://jackal.in/2008/10/viborka-randomnix-elementov-iz-massiva.html" />
    <id>tag:jackal.in,2008://1.13</id>

    <published>2008-10-03T13:13:42Z</published>
    <updated>2008-10-04T20:30:41Z</updated>

    <summary><![CDATA[ Дано: Массив длиной L, каждый элемент массива имеет вес weight (для простоты - целочисленный) Задача: Выбрать рандомно N элементов из массива (N &lt; L), при этом не должно быть одинаковых элементов, и вероятность выборки каждого элемента должна быть прямо...]]></summary>
    <author>
        <name>jackal</name>
        
    </author>
    
        <category term="algo" scheme="http://www.sixapart.com/ns/types#category" />
    
        <category term="perl" scheme="http://www.sixapart.com/ns/types#category" />
    
    <category term="perl" label="perl" scheme="http://www.sixapart.com/ns/types#tag" />
    <category term="алгоритм" label="алгоритм" scheme="http://www.sixapart.com/ns/types#tag" />
    <category term="массив" label="массив" scheme="http://www.sixapart.com/ns/types#tag" />
    <category term="рандом" label="рандом" scheme="http://www.sixapart.com/ns/types#tag" />
    
    <content type="html" xml:lang="en" xml:base="http://jackal.in/">
        <![CDATA[ <h2>Дано:</h2>
<p>Массив длиной L, каждый элемент массива имеет вес weight (для простоты - целочисленный)</p>

<h2>Задача:</h2>
<p>Выбрать рандомно N элементов из массива (N &lt; L), при этом не должно быть одинаковых элементов, и вероятность выборки каждого элемента должна быть прямо пропорциональна весу элемента.</p>

<h2>Решение:</h2>
<p>Разместим элементы массива на оси весов, при этом длина отрезка каждого элемента равна весу этого элемента.<br />
Посчитаем суммарный вес элементов - это максимально возможная координата.<br /><br />
Теперь итерируем массив от начала (столько итераций, сколько нужно выбрать элементов). На каждой итерации:<br />
</p><ul>
<li>Выбираем рандомно точку от 1 до макс. координаты $weight</li>
<li>Ищем элемент, соответствующий отрезку, содержащему эту точку</li>
<li>Меняем местами выбранный элемент с элементом, соответствующем текущей итерации - т.о. "запоминаем" его.</li>
<li>Сдвигаем начало координат (и соотв. макс. координату) на величину, равную длине отрезка выбранного элемента</li>
</ul>
<p>Всё. Теперь N начальных элементов - и есть интересующая нас выборка. Осталось только отбросить лишнюю часть массива от N+1 до L</p>

<pre># @res - исходный массив
# $need_count - сколько нужно выбрать элементов
# $weight - суммарный вес всех элементов исходного массива

for (my $i=0; $i&lt;$need_count; $i++) {
    my $w = int(rand $weight)+1; # выбираем точку на оси весов
    for (my $j=$i; $j&lt;=$#res; $j++) { # ищем элемент, соотв. точке
        if ($res[$j]-&gt;{weight} &gt;= $w) {
            $weight -= $res[$j]-&gt;{weight};
            ($res[$i], $res[$j]) = ($res[$j], $res[$i]) if $i != $j;
            last;
        } else {
            $w -= $res[$j]-&gt;{weight};
        }
    }
}
@res = splice(@res,0,$need_count); # обрезаем массив
</pre>
]]>
        
    </content>
</entry>

<entry>
    <title>Сломали DBD::mysql</title>
    <link rel="alternate" type="text/html" href="http://jackal.in/2008/09/slomali-muskul.html" />
    <id>tag:jackal.in,2008://1.12</id>

    <published>2008-09-29T17:21:11Z</published>
    <updated>2008-09-29T20:49:30Z</updated>

    <summary>Начиная с версии 4.007 сломали $dbh-&gt;{mysql_auto_reconnect}=1 В результате при потере коннекта к мускулю вместо реконнекта происходит сегфолт перла. Оч. неприятная штука :) В версии 4.008 так и не пофиксили, хотя с ней в один день выпустили патч....</summary>
    <author>
        <name>jackal</name>
        
    </author>
    
        <category term="perl" scheme="http://www.sixapart.com/ns/types#category" />
    
    <category term="mysql" label="mysql" scheme="http://www.sixapart.com/ns/types#tag" />
    <category term="perl" label="perl" scheme="http://www.sixapart.com/ns/types#tag" />
    <category term="segfault" label="segfault" scheme="http://www.sixapart.com/ns/types#tag" />
    
    <content type="html" xml:lang="en" xml:base="http://jackal.in/">
        <![CDATA[<p>Начиная с версии 4.007 сломали $dbh->{mysql_auto_reconnect}=1</p>
<p>В результате при потере коннекта к мускулю вместо реконнекта происходит сегфолт перла. Оч. неприятная штука :)</p>
<p>В версии 4.008 так и не пофиксили, хотя с ней в один день выпустили <a href="http://rt.cpan.org/Public/Bug/Display.html?id=37027" target="_blank">патч</a>.</p>]]>
        
    </content>
</entry>

<entry>
    <title>Массовая склейка www.domain -&gt; domain и наоборот</title>
    <link rel="alternate" type="text/html" href="http://jackal.in/2008/09/massovaja-sklejka-wwwdomain---domain-i-naoborot.html" />
    <id>tag:jackal.in,2008://1.10</id>

    <published>2008-09-15T07:12:13Z</published>
    <updated>2008-09-15T08:28:20Z</updated>

    <summary><![CDATA[Маленький perl-модуль к nginx-у, который "склеивает" www.domain -&gt; domain и наоборот (т.е. на каждый урл выдает соотв. 301-редирект, плюс robots.txt для яндекса). Прелесть в том, что не нужно описывать директиву server для каждого домена. Достаточно все домены - неосновные зеркала...]]></summary>
    <author>
        <name>jackal</name>
        
    </author>
    
        <category term="nginx" scheme="http://www.sixapart.com/ns/types#category" />
    
        <category term="perl" scheme="http://www.sixapart.com/ns/types#category" />
    
    <category term="nginx" label="nginx" scheme="http://www.sixapart.com/ns/types#tag" />
    <category term="домен" label="домен" scheme="http://www.sixapart.com/ns/types#tag" />
    <category term="склейка" label="склейка" scheme="http://www.sixapart.com/ns/types#tag" />
    
    <content type="html" xml:lang="en" xml:base="http://jackal.in/">
        <![CDATA[<p>Маленький perl-модуль к nginx-у, который "склеивает" www.domain -&gt; domain и наоборот (т.е. на каждый урл выдает соотв. 301-редирект, плюс robots.txt для яндекса).</p>

<p>Прелесть в том, что не нужно описывать директиву server для каждого домена. Достаточно все домены - неосновные зеркала запихнуть в один server (поштучно или маской/регэкспом) и вообщем-то всё. Если домен с www, значит основным зеркалом считается без www, и наоборот.</p>

<span class="mt-enclosure mt-enclosure-file" style="display: inline;"><a href="http://jackal.in/files/ngx_glue.tar.gz">ngx_glue.tar.gz</a></span>

<p>А вообще это делается как-то так:</p>
<pre>server {
    server_name все_неосновные_зеркала_поштучно_или_маской;
    if ($host ~ ^www\.(.+)$) {
        set $h $1;
        rewrite ^(.*)$ http://$h$1 permanent;
        break;
    }
    rewrite ^(.*)$ http://www.$host$1 permanent;
}
</pre><p>Но тут не будет генериться robots.txt</p>
]]>
        
    </content>
</entry>

<entry>
    <title>Экспайр сессий и кук в каталисте</title>
    <link rel="alternate" type="text/html" href="http://jackal.in/2008/09/ekspajr-sessij-i-kuk-v-kataliste.html" />
    <id>tag:jackal.in,2008://1.9</id>

    <published>2008-09-12T09:44:10Z</published>
    <updated>2008-09-12T17:13:14Z</updated>

    <summary>Механизм Как известно, механизм сессий построен по принципу frontend/backend. За фронтенд отвечает Session::State, за бэкенд - Session::Store. Первый работает с пользователем - передает и принимает айди сессии (например, в урле или куке). Второй - на стороне сервера. Он отвечает за...</summary>
    <author>
        <name>jackal</name>
        
    </author>
    
        <category term="Catalyst" scheme="http://www.sixapart.com/ns/types#category" />
    
    <category term="catalyst" label="catalyst" scheme="http://www.sixapart.com/ns/types#tag" />
    <category term="cookie" label="cookie" scheme="http://www.sixapart.com/ns/types#tag" />
    <category term="expires" label="expires" scheme="http://www.sixapart.com/ns/types#tag" />
    <category term="session" label="session" scheme="http://www.sixapart.com/ns/types#tag" />
    
    <content type="html" xml:lang="en" xml:base="http://jackal.in/">
        <![CDATA[<h2>Механизм</h2>

<p>Как известно, механизм сессий построен по принципу frontend/backend. За фронтенд отвечает Session::State, за бэкенд - Session::Store. Первый работает с пользователем - передает и принимает айди сессии (например, в урле или куке). Второй - на стороне сервера. Он отвечает за хранение данных сессии.</p>

<p>В качестве фронтенда выберем State::Cookie (больше нечего, не в урлах же сессии передавать), а какой бэкенд - не столь важно.</p>

<p>Как известно, за expire сессий отвечают 2 параметра в конфиге: <b>$c-&gt;config-&gt;{session}-&gt;{expires}</b> и <b>$c-&gt;config-&gt;{session}-&gt;{cookie_expires}</b>, которые отвечают за экспайр сессии и куки соответственно.</p>

<p><b>cookie_expires</b> использует только Catalyst::Plugin::Session::State::Cookie, причем на стороне сервера оно нигде не хранится, и используется только для выставления expire в HTTP-заголовке. Причем если cookie_expires == 0, то кука будет сессионная.</p>

<p><b>expires</b> использует Catalyst::Plugin::Session. Когда происходит запрос с проэкспайренной сессией, вызываются методы delete_session_id и delete_session_data. Первый наследуется Session::State (т.о. может удалить куку, даже если она еще не проэкспайрилась), второй - наследуется Session::Store. Его предназначение - удалить данную сессию на сервере.</p>

<h2>Результат</h2>

<p>Таким образом со стороны пользователя получается всё прозрачно. Выставляем expires == cookie_expires и всё. Т.к. если cookie_expires будет больше - сессия на сервере истечет раньше, будет вызван delete_session_id, и кука всё равно удалится. Наоборот - кука удалится, данные сессии на сервере останутся, но пользователю это неважно - для него этой сессии больше нет.</p>

<p>Немного сложнее с сессионными куками (cookie_expires == 0). Здесь надо выставить expires во что-нибудь вменяемое, например - сутки. Крайне маловероятно, что пользователь не закроет сайт в браузере в течение суток, и при этом ни разу не запросит ни одной страницы.</p>

<h2>Проблемы</h2>

<p>Проблемы возникают на сервере. Дело в том, что принудительное удаление данных сессии происходит только при запросе пользователем идентификатора данной сессии. В реальной жизни такого не происходит, т.к. у пользователей экспайрится кука, и они "забывают" про данную сессию, а индексаторы поисковых систем вообще куки не поддерживают, т.о. для каждой страницы будет генериться новая сессия, и все эти сессии никогда не будут удалены.</p>

<p>Каталист предлагает "свалить" эту проблему на Session::Store::бэкенды.</p>

<p><b>Catalyst::Plugin::Session::Store</b><br />
<b>delete_expired_sessions</b><br />
This method is not called by any code at present, but may be called in the
future, as part of a Catalyst-specific maintenance script.<br />
If you are wrapping around a backend which manages its own auto expiry
you can just give this method an empty body.</p>

<p>Но реальность обстоит иначе:</p>

<p><b>Catalyst::Plugin::Session::Store::DBI</b><br />
The expires column in your table will be set with the expiration value. Note that no automatic cleanup is done on your session data, but you can use the delete_expired_sessions method to perform clean up. You can make use of the Catalyst::Plugin::Scheduler plugin to schedule automated session cleanup.<br />
Т.о. забота об очистке сессионного хранилища кладется на нас.</p>

<p><b>Catalyst::Plugin::Session::Store::File</b><br />
Здесь всё вообще "замечательно":</p>

<pre>sub delete_expired_sessions { }</pre><p>Метод тупо не реализован :) Более того:</p>

<pre>    $c-&gt;_session_file_storage(
        Cache::FileCache-&gt;new(
            {
                cache_root  =&gt; $cfg-&gt;{storage},
                (
                    map { $_ =&gt; $cfg-&gt;{$_} }
                      grep { exists $cfg-&gt;{$_} }
                      qw/namespace cache_depth directory_umask/
                ),
            }
        )
    );
</pre><p>Как мы видим, модуль вообще не заботится об expire, и даже параметра такого в Cache::File не передает. Т.о. даже невозможно написать maintenance-скрипт, который бы чистил периодически хранилище.</p>
]]>
        
    </content>
</entry>

<entry>
    <title>Анализатор поисковых реферреров</title>
    <link rel="alternate" type="text/html" href="http://jackal.in/2008/09/analizator-poiskovix-referrerov.html" />
    <id>tag:jackal.in,2008://1.8</id>

    <published>2008-09-09T06:31:53Z</published>
    <updated>2008-09-09T09:46:18Z</updated>

    <summary> Сабж. Эвристический анализатор, очень хороший :) Несмотря на то, что был написан полтора года назад, до сих пор исправно и качественно работает. Понимает все кодировки, в том числе двойной quoted-printable, utf16-be и т.п. Если бы данные кодировки не юзались...</summary>
    <author>
        <name>jackal</name>
        
    </author>
    
        <category term="perl" scheme="http://www.sixapart.com/ns/types#category" />
    
    <category term="perl" label="perl" scheme="http://www.sixapart.com/ns/types#tag" />
    <category term="referrer" label="referrer" scheme="http://www.sixapart.com/ns/types#tag" />
    <category term="se" label="se" scheme="http://www.sixapart.com/ns/types#tag" />
    <category term="анализатор" label="анализатор" scheme="http://www.sixapart.com/ns/types#tag" />
    
    <content type="html" xml:lang="en" xml:base="http://jackal.in/">
        <![CDATA[ <p>Сабж. Эвристический анализатор, очень хороший :) Несмотря на то, что был написан полтора года назад, до сих пор исправно и качественно работает.</p>
<p>Понимает все кодировки, в том числе двойной quoted-printable, utf16-be и т.п. Если бы данные кодировки не юзались где-то, я бы не стал делать их поддержку :) При разработке через анализатор было пропущено 1.5 ляма реальных рефов, далее он был доработан, чтобы понимать те рефы, которые он не понимал.</p>
<p>За давностью лет его КПД я, к сожалению, не помню, но <b>точно больше</b> 99.9%, что для эвристики - очень и очень гуд. Плюс, он работает довольно быстро.</p>
<p><span class="mt-enclosure mt-enclosure-file" style="display: inline;"><a href="http://jackal.in/files/Referrer.pm.tar.gz">Referrer.pm.tar.gz</a></span></p>
<p>Модуль экспортирует единственную функцию analyze()<br>
Использование:<br>
my ($se, $kw) = analyze($ref);<br>
$ref - исходный реферрер (без эскейпа, т.е. в том виде как он пришел из заголовка)<br>
$se - поисковик (hardcoded в @cfg_se, для незнакомых возвращает 'other')<br>
$kw - распознанный кейворд (в кодировке cp1251).</p>
<p>Также может вернуть undef, если реферрер битый (нельзя выпарсить домен, или протокол отличен от http(s)</p>]]>
        
    </content>
</entry>

<entry>
    <title>Ограничение отдачи контента с бэкендов для ботов</title>
    <link rel="alternate" type="text/html" href="http://jackal.in/2008/09/ogranichenie-otdachi-kontenta-s-bekendov-dlja-botov.html" />
    <id>tag:jackal.in,2008://1.7</id>

    <published>2008-09-01T16:16:58Z</published>
    <updated>2008-09-01T16:53:14Z</updated>

    <summary>Прошлой зимой нужно было ограничить скорость отдачи контента для ботов, т.к. они &quot;валили&quot; бэкенды, особенно ночью и особенно яндекс :) При этом имелось несколько бэкендов, и хотелось их ограничивать &quot;по-разному&quot;, или не ограничивать вовсе, в зависимости от текущей нагрузки. Вообщем...</summary>
    <author>
        <name>jackal</name>
        
    </author>
    
        <category term="apache" scheme="http://www.sixapart.com/ns/types#category" />
    
        <category term="nginx" scheme="http://www.sixapart.com/ns/types#category" />
    
        <category term="perl" scheme="http://www.sixapart.com/ns/types#category" />
    
    <category term="backend" label="backend" scheme="http://www.sixapart.com/ns/types#tag" />
    <category term="limit_rate" label="limit_rate" scheme="http://www.sixapart.com/ns/types#tag" />
    <category term="nginx" label="nginx" scheme="http://www.sixapart.com/ns/types#tag" />
    <category term="perl" label="perl" scheme="http://www.sixapart.com/ns/types#tag" />
    
    <content type="html" xml:lang="en" xml:base="http://jackal.in/">
        <![CDATA[<p>Прошлой зимой нужно было ограничить скорость отдачи контента для ботов, т.к. они "валили" бэкенды, особенно ночью и особенно яндекс :)</p>
<p>При этом имелось несколько бэкендов, и хотелось их ограничивать "по-разному", или не ограничивать вовсе, в зависимости от текущей нагрузки.</p>
<p>Вообщем в итоге родилось следующее решение:
<ul>
<li>Некий демон с определенным интервалом парсит команду "netstat -Lan", и определяет загруженность бэкендов по величине backlog. Далее смотрит текущий limit_rate для каждого из бэкендов в кеше на базе Cache::FastMmap, и понижает/повышает его, если надо.</li>
<li>Хендлер для nginx-а определяет ботов по юзер-агенту, и если пришел бот - вытаскивает из кеша текущий limit_rate для бэкенда.</li>
</ul>
 В результате нагрузка "балансирует".</p>
<p>Архив с демоном, хендлером и примером конфига для nginx: <span class="mt-enclosure mt-enclosure-file" style="display: inline;"><a href="http://jackal.in/files/nx_limitrate.tgz">nx_limitrate.tgz</a></span></p>
<p>Писалось всё исключительно для себя и <i>быстро</i>, поэтому абсолютно всё захардкодено, т.ч. претензии по этому поводу не принимаю :) Впрочем, код очень маленький и интуитивно понятный. А если нет - то велкам :)</p>
]]>
        
    </content>
</entry>

<entry>
    <title>Всякие прикольные штучки</title>
    <link rel="alternate" type="text/html" href="http://jackal.in/2008/08/vsjakie-prikol-nie-shtuchki.html" />
    <id>tag:jackal.in,2008://1.6</id>

    <published>2008-08-25T20:05:30Z</published>
    <updated>2008-08-25T20:18:28Z</updated>

    <summary>Просто чтоб не забыть :) сцылко...</summary>
    <author>
        <name>jackal</name>
        
    </author>
    
        <category term="perl" scheme="http://www.sixapart.com/ns/types#category" />
    
    <category term="hacker" label="hacker" scheme="http://www.sixapart.com/ns/types#tag" />
    <category term="perl" label="perl" scheme="http://www.sixapart.com/ns/types#tag" />
    <category term="верблюд" label="верблюд" scheme="http://www.sixapart.com/ns/types#tag" />
    
    <content type="html" xml:lang="en" xml:base="http://jackal.in/">
        <![CDATA[<p>Просто чтоб не забыть :) <a href="http://en.wikipedia.org/wiki/Just_another_Perl_hacker" target="_blank">сцылко</a></p>
]]>
        
    </content>
</entry>

<entry>
    <title>mod_realip для apache2</title>
    <link rel="alternate" type="text/html" href="http://jackal.in/2008/08/mod-realip-apache2.html" />
    <id>tag:jackal.in,2008://1.4</id>

    <published>2008-08-25T19:22:06Z</published>
    <updated>2008-08-25T19:51:37Z</updated>

    <summary> Маленький модуль для второго апача, который совершенно ничего не делает, кроме как подменяет ip-адрес из заголовка X-Real-IP. Собсно, &quot;сделан&quot; из mod_rpaf, с учетом патча, токо выкинуто всё лишнее и ненужное, в т.ч. &quot;настройка&quot;. make install и всё работает :)...</summary>
    <author>
        <name>jackal</name>
        
    </author>
    
        <category term="apache" scheme="http://www.sixapart.com/ns/types#category" />
    
    <category term="apache" label="apache" scheme="http://www.sixapart.com/ns/types#tag" />
    <category term="mod_realip" label="mod_realip" scheme="http://www.sixapart.com/ns/types#tag" />
    
    <content type="html" xml:lang="en" xml:base="http://jackal.in/">
        <![CDATA[ <p>Маленький модуль для второго апача, который совершенно ничего не делает, кроме как подменяет ip-адрес из заголовка X-Real-IP. Собсно, "сделан" из <a href="http://stderr.net/apache/rpaf/" target="_blank">mod_rpaf</a>, с учетом <a href="http://maloletka.ru/" target="blank">патча</a>, токо выкинуто всё лишнее и ненужное, в т.ч. "настройка".</p>
<p>make install и всё работает :)<br />
<span class="mt-enclosure mt-enclosure-file" style="display: inline;"><a href="http://jackal.in/files/realip_c.tar.gz">realip_c.tar.gz</a></span><p></p>]]>
        
    </content>
</entry>

</feed>
