Страницы

вторник, 28 декабря 2010 г.

SSL, openssl и генерация сертификатов

Что бы не забывать
В состав дистрибутива openssl входят скрипты CA.sh и CA.pl (/usr/local/openssl/misc)
создаем корневой сертификат
./CA.sh -newca
генерируем личный ключ и сертификационный запрос сервера
./CA.sh -newreq
и подписываем его своим корневым сертификатом.
./CA.sh -sign
переписываем ключ и сертификат сервера в служебный каталог Apache
cp newreq.pem /usr/local/etc/apache/sslkey/server.key
cp newcert.pem /usr/local/etc/apache/ssl.crt/server.crt
Файл корневого сертификата ./demoCA/cacert.pem необходимо
распространить по клиентским компьютерам.

среда, 22 декабря 2010 г.

Где брать идеи

1. Идеи не появляются от просмотра телевизора.

2. Идеи иногда появляются после прослушивания лекции.

3. Идеи часто появляются во время чтения книги.

4. Хорошие идеи появляются из плохих идей, но только если последние есть в достаточном количестве.

5. Идеи ненавидят конференц-залы, особенно такие конференц-залы, где сохранился опыт критики, личных выпадов или занудства.

6. Идеи возникают, когда сталкиваются непохожие вселенные.

7. Идеи часто стремятся соответствовать ожиданиям. Если люди ожидают идею, то она появится.

8. Идеи боятся экспертов, но восхищаются умом начинающих. Немного осведомленности не помешает.

9. Идеи идут косяками, пока вы не испугаетесь. Уилли Нельсон написал три из своих главных хитов за одну неделю.

10. Идеи приходят благодаря неприятностям.

11. Идеи приходят от нашего эго, и они выходят лучше всего, когда они щедры и самозабвенны.

12. Идеи приходят из природы.

13. Иногда идеи приходят от страха (обычно это в кино), но часто – от уверенности.

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

15. Однако иногда идеи прокрадываются к нам, когда мы спим и слишком обмякли, чтобы бояться.

16. Идеи замечаешь краем глаза, а иногда – находясь в душе, когда не прилагаешь никаких усилий.

17. Посредственные идеи склонны копировать то, что, похоже, работает как раз в эту минуту.

18. Более крутые идеи перескакивают через посредственные.

19. Идеям не нужен паспорт, и они часто пересекают границы (всякого рода) безнаказанно.

20. Идея должна прийти откуда-то, потому что если она останется там, где есть, и не присоединится к нам здесь, она будет скрытой. А скрытые идеи не превращаются во что-то конкретное, не имеют влияния, не пересекаются с рынком. Они умирают в одиночестве.

Сет Годин...

четверг, 9 декабря 2010 г.

Оптимизация кода

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

Идея 1. Назовем ее развертывание цикла.

Код :

my $ref = $dbh->selectall_arrayref(q[SELECT id FROM categories
WHERE c_status='active']);
my (@res);
my $count=10;
foreach my $tmp (@$ref){
my $ref=$dbh->selecall_hashref(qq[SELECT id,title,text,ts
FROM articles
WHERE category=$tmp
ORDER BY id DESC LIMIT $count],'id');
my @r;
push @r,$ref->{$_} foreach( key %$ref);
push @res,\@r;
}



То есть это простой пример вывода статей по 10 штук в каждой категорие. Он универсален, но его можно значительно ускорить потеряв при этом применимость нового алгоритма для некоторых частных случаев. "Развернув" внутренний цикл
мы получим ужасный код, но и более быстрый, избавившись в данном случае аж от 10 условных переходов (циклы это ничто иное как условные переходы) . Получим примерно следующее :
my $ref = $dbh->selectall_arrayref(q[SELECT id FROM categories
WHERE c_status='active']);
my @res;
my $count=10;
foreach my $tmp (@$ref){
my $ref=$dbh->selecall_arrayref(qq[SELECT id,title,text,ts
FROM articles
WHERE category=$tmp
ORDER BY id DESC LIMIT $count],'id');
my @r;
push @r,$ref->[0];
push @r,$ref->[1];
push @r,$ref->[2];
push @r,$ref->[3];
push @r,$ref->[4];
push @r,$ref->[5];
push @r,$ref->[6];
push @r,$ref->[7];
push @r,$ref->[8];
push @r,$ref->[9];
push @res,\@r;
}


Идея 2. Банальное кеширование

Не будем уходить далеко в мир высокого, а продолжим рассматривать пример выше.
Логично предположить, что новые категории добавляются не каждый день, потому от запроса на выборки списка надо избавиться путем сохранения его в памяти. Самый простой способ это Memcached, другой способ рассмотрим ниже.

sub get_cache_connection
{

require Cache::Memcached::Fast;
require Storable;
my $ref=new Cache::Memcached::Fast(
{
servers =>[{ address => '127.0.0.1:11211',weight=>2.5}],
namespace => 'sessions:',
connect_timeout => 0.2,
io_timeout => 0.5,
close_on_error => 1,
compress_threshold =>-1,
ketama_points => 150,
nowait => 1,
hash_namespace => 1,
serialize_methods => [ \&Storable::freeze, \&Storable::thaw ]
}
);

return $ref;

}

my $tabs;
my $md=get_cache_connection();
my $ref=$md->get('categories')) ;
foreach(@$ref){
###some code there

}
Кеширование применимо для данных, которые не часто меняются, при другом подходе может возникнуть проблема, что накладные расходы на работу с кешированием превысят затраты на работу с базой данных. Не забывайте, что mysql тоже кеширует запросы, и в предыдущем примере запрос на выборку категорий по сути не имеет смысла, потому что с огромной вероятностью он будет закеширован mysql. Другое дело, если вы генерируете из категорий свой особый html код, вот его можно и за кешировать.


Идея 3. Развертывание функций.


Думаю вы уже догадались в чем фишка. Рассмотрим предыдущие примеры, только добавим внутрь цикла функцию форматирования даты - ts.
my $ref = $mem_cache->get('categories')) ;
my @res;
my $count=10; foreach my $tmp (@$ref){
my $ref=$dbh->selecall_arrayref(qq[SELECT id,title,text,ts
FROM articles
WHERE category=$tmp
ORDER BY id DESC LIMIT $count],'id');
my @r;
format_date(\$ref->[0]->[3]);
push @r,$ref->[0];
format_date(\$ref->[1]->[3]);
push @r,$ref->[1];
format_date(\$ref->[2]->[3]);
push @r,$ref->[2];
format_date(\$ref->[3]->[3]);
push @r,$ref->[3];
format_date(\$ref->[4]->[3]);
push @r,$ref->[4];
format_date(\$ref->[5]->[3]);
push @r,$ref->[5];
format_date(\$ref->[6]->[3]);
push @r,$ref->[6];
format_date(\$ref->[7]->[3]);
push @r,$ref->[7];
format_date(\$ref->[8]->[3]);
push @r,$ref->[8];
format_date(\$ref->[9]->[3]);
push @r,$ref->[9];

push @res,\@r;
}


Заметка кстати, профайлинг Perl показал, что быстрее передавать параметры в функцию по значению, а не по указателю( то есть не так как здесь ;) ). И заменяем все format_date на их код.

my $ref = $mem_cache->get('categories')) ;
my @res;
my $count=10;
foreach my $tmp (@$ref){
my $ref=$dbh->selecall_arrayref(qq[SELECT id,title,text,ts
FROM articles
WHERE category=$tmp
ORDER BY id DESC LIMIT $count],'id');
my @r;

$ref->[0]->[3]=~/(\d{1,4})-(\d{1,2})-(\d{1,2})/;
$ref->[0]->[3]="$3.$2.$1";
push @r,$ref->[0];
$ref->[1]->[3]=~/(\d{1,4})-(\d{1,2})-(\d{1,2})/;
$ref->[1]->[3]="$3.$2.$1";


push @r,$ref->[1];
$ref->[2]->[3]=~/(\d{1,4})-(\d{1,2})-(\d{1,2})/;
$ref->[2]->[3]="$3.$2.$1";
push @r,$ref->[2];
$ref->[3]->[3]=~/(\d{1,4})-(\d{1,2})-(\d{1,2})/;
$ref->[3]->[3]="$3.$2.$1";
push @r,$ref->[3];
$ref->[4]->[3]=~/(\d{1,4})-(\d{1,2})-(\d{1,2})/;
$ref->[4]->[3]="$3.$2.$1";
push @r,$ref->[4];
$ref->[5]->[3]=~/(\d{1,4})-(\d{1,2})-(\d{1,2})/;
$ref->[5]->[3]="$3.$2.$1";
push @r,$ref->[5];
$ref->[6]->[3]=~/(\d{1,4})-(\d{1,2})-(\d{1,2})/;
$ref->[6]->[3]="$3.$2.$1";
push @r,$ref->[6];
$ref->[7]->[3]=~/(\d{1,4})-(\d{1,2})-(\d{1,2})/;
$ref->[7]->[3]="$3.$2.$1";
push @r,$ref->[7];
$ref->[1]->[8]=~/(\d{1,4})-(\d{1,2})-(\d{1,2})/;
$ref->[1]->[8]="$3.$2.$1";
push @r,$ref->[8];
$ref->[1]->[9]=~/(\d{1,4})-(\d{1,2})-(\d{1,2})/;
$ref->[1]->[9]="$3.$2.$1";
push @r,$ref->[9];
push @res,\@r;
}

В итоге мы види ужасный неудобоворимый код, который вызывает рвотные рефлексы при одном своем виде. Дальше агрументов много
1) А что делать, если полей в таблице дофига, и все надо форматировать, это ж "каша"
2) А если надо увеличить/уменьшить количество статей, снова лезть в код!
И так далее.. И так далее...Все эти вопросы можно решить при помощи "админки". А админка есть у любого уважающего себя сайта статусом выше, персональная страничка.
На нужно при изменение нужных вам параметров сделать генерацию нужного вам кода.
Например добавить изменение количества выводимых статей с 10 на 5( вполне обычная функция для администраторского интерфейса). Помещаем функцию обработки вывода статей в отдельный модуль например "/lib/Article.pm". Даем права на работу с этим файлом пользователю от которого работает наш скрипт
( ну или обычные авось chmod 777 /lib/Artcle.pm).
ну и в функцию изменения количества статей пишем примерно следующее:
open(Fl,">document_root/lib/Article");

print FL, q{
package lib::Artcle;
use strict;
use base qw[Exporter];
use SiteDB;##connecting to the database $dbh
our @EXPORT = qw(
list
);





sub list{
my $ref = $mem_cache->get('categories')) ;
my @res;
my $count=}.$new_count_value.q{;

foreach my $tmp (@$ref){
my $ref=$dbh->selecall_arrayref(qq[SELECT id,title,text,ts
FROM articles
WHERE category=$tmp
ORDER BY id DESC LIMIT $count],'id');
my @r;

$ref->[0]->[3]=~/(\d{1,4})-(\d{1,2})-(\d{1,2})/;
$ref->[0]->[3]="$3.$2.$1";
push @r,$ref->[0];
$ref->[1]->[3]=~/(\d{1,4})-(\d{1,2})-(\d{1,2})/;
$ref->[1]->[3]="$3.$2.$1";


push @r,$ref->[1];
$ref->[2]->[3]=~/(\d{1,4})-(\d{1,2})-(\d{1,2})/;
$ref->[2]->[3]="$3.$2.$1";
push @r,$ref->[2];
$ref->[3]->[3]=~/(\d{1,4})-(\d{1,2})-(\d{1,2})/;
$ref->[3]->[3]="$3.$2.$1";
push @r,$ref->[3];
$ref->[4]->[3]=~/(\d{1,4})-(\d{1,2})-(\d{1,2})/;
$ref->[4]->[3]="$3.$2.$1";
push @r,$ref->[4];
$ref->[5]->[3]=~/(\d{1,4})-(\d{1,2})-(\d{1,2})/;
$ref->[5]->[3]="$3.$2.$1";
push @r,$ref->[5];
$ref->[6]->[3]=~/(\d{1,4})-(\d{1,2})-(\d{1,2})/;
$ref->[6]->[3]="$3.$2.$1";
push @r,$ref->[6];
$ref->[7]->[3]=~/(\d{1,4})-(\d{1,2})-(\d{1,2})/;
$ref->[7]->[3]="$3.$2.$1";
push @r,$ref->[7];
$ref->[1]->[8]=~/(\d{1,4})-(\d{1,2})-(\d{1,2})/;
$ref->[1]->[8]="$3.$2.$1";
push @r,$ref->[8];
$ref->[1]->[9]=~/(\d{1,4})-(\d{1,2})-(\d{1,2})/;
$ref->[1]->[9]="$3.$2.$1";
push @r,$ref->[9];
push @res,\@r;
\}

return \@res;
\}

1;
};
close(FL);
Ну и далее можем использовать этот модуль у себя в скрипте обычным способом :



sub some_sub{
my $self=shift;
require lib::Article;
my $ref=lib::Article::list();
###some code there
####
}


Всем удачи.

p.s
При помощи генерации кода можно избавиться вообще от последнего цикла обхода категорий.

пятница, 3 декабря 2010 г.

perl, utf8,киррилица и mysql

Вы похвально решили перевести вашу базу данных в utf-8...
Везеде поставили в mysql :
set names utf8;
set charset utf8;

в таблицах проставили новую коддировку по умолчанию,
default charset utf8



Начинаете добавлять из скрипта данные, а вместо них пустые строки в базе данных....
Первое скрипту выставляем коддировку utf8 это вы и сами догадались, а второе
пишем в начале скрипта :
use utf8;
Теперь все работает...Ошибка неприятная, потому perl молчал как партизан, и просто
все менял на пустую строку