Revision 8 (by ahitrov@rambler.ru, 2010/03/29 11:46:38) |
Contenido UTF-8 core files
|
package Contenido::DB::PostgreSQL;
# ----------------------------------------------------------------------------
# Класс реализации работы базой данных PostgreSQL
# ----------------------------------------------------------------------------
use strict;
use warnings;
use DBI;
use DBD::Pg;
use Contenido::Globals;
use Contenido::Msg;
# МЕТОДЫ ДОСТУПА К СОЕДИНЕНИЯМ С БАЗОЙ УМНЫЕ
# получение соединения с базой или установка нового если его не было
sub SQL {
my $self = shift;
return ($self->connect_check() ? $self->{SQL} : undef);
}
#получение транзакционного соединения с базой или установка нового если его не было
sub TSQL {
my $self = shift;
return ($self->t_connect_check() ? $self->{TSQL} : undef);
}
# -------------------------------------------------------------------------------------------------
# Открываем соединение с базой данных
# -------------------------------------------------------------------------------------------------
sub connect {
my $self = shift;
#соединение уже есть
if ($self->is_connected) {
} else {
unless ($self->{SQL} = $self->create_db_connect) {
$log->error("Не могу соединиться с базой данных");
die;
}
$self->{SQL}->do("SET NAMES '".$self->state->db_client_encoding."'") if ($self->state->db_client_encoding);
}
$self->{_connect_ok} = 1;
return 1;
}
sub t_connect {
my $self = shift;
#транзакционный connect уже есть
if ($self->is_t_connected) {
$self->{TSQL_level}++;
} else {
unless ($self->{TSQL} = $self->create_db_t_connect) {
$log->error("Не могу соединиться с базой данных");
die;
}
$self->{TSQL}->do("SET NAMES '".$self->state->db_client_encoding."'") if ($self->state->db_client_encoding);
$self->{TSQL_level} = 1;
#если не проставлено значение то 0
$self->{TSQLStable} = 0 unless (exists $self->{TSQLStable});
}
$self->{_t_connect_ok} = 1;
$self->{oldSQL} = $self->{SQL} if ($self->{SQL} and (!$self->{oldSQL}));
$self->{SQL} = $self->{TSQL};
return 1;
}
#получение соединения с базой (возможно кому то вне keeper надо)
#возвращает $dbh или undef
sub create_db_connect {
my $self = shift;
return DBI->connect("dbi:Pg:dbname=$self->{db_name};".( $self->{db_host} ne 'localhost' ? "host=$self->{db_host};" : "" )."port=$self->{db_port}", $self->{db_user}, $self->{db_password}, { 'AutoCommit' => 1, pg_server_prepare => $self->{db_prepare}, 'pg_enable_utf8' => $self->{db_enable_utf8} } );
}
sub create_db_t_connect {
my $self = shift;
return DBI->connect("dbi:Pg:dbname=$self->{db_name};".( $self->{db_host} ne 'localhost' ? "host=$self->{db_host};" : "" )."port=$self->{db_port}", $self->{db_user}, $self->{db_password}, { 'AutoCommit' => 0, pg_server_prepare => $self->{db_prepare}, 'pg_enable_utf8' => $self->{db_enable_utf8} } );
}
#физическая проверка состояния соединения с базой
sub is_connected {
my $self = shift;
if (ref($self->{SQL}) and $self->{SQL}->can('ping') and $self->{SQL}->ping()) {
$self->{_connect_ok} = 1;
return 1;
} else {
$self->{_connect_ok} = 0;
return 0;
}
}
#физическая проверка состояния соединения с базой
sub is_t_connected {
my $self = shift;
if (ref($self->{TSQL}) and $self->{TSQL}->can('ping') and $self->{TSQL}->ping()) {
$self->{_t_connect_ok} = 1;
return 1;
} else {
$self->{_t_connect_ok} = 0;
return 0;
}
}
#проверка соединения с базой кеширующая состояние соединения
sub connect_check {
my $self = shift;
return 1 if ($self->{_connect_ok});
if ($self->is_connected) {
$self->{_connect_ok} = 1;
return 1;
} else {
if ($self->connect) {
return 1;
} else {
#сюда по логике попадать не должно так как die вылететь должен
return 0;
}
}
}
sub t_connect_check {
my $self = shift;
return 1 if ($self->{_t_connect_ok});
if ($self->is_t_connected) {
$self->{_t_connect_ok} = 1;
return 1;
} else {
if ($self->t_connect) {
return 1;
} else {
#сюда по логике попадать не должно так как die вылететь должен
return 0;
}
}
}
# -------------------------------------------------------------------------------------------------
# Закрываем соединение с базой данных
# -------------------------------------------------------------------------------------------------
sub shutdown
{
my $self = shift;
$self->{SQL} = $self->{oldSQL} if $self->{oldSQL};
delete $self->{oldSQL};
$self->{SQL}->disconnect() if ($self->is_connected);
delete $self->{SQL};
$self->{_connect_ok} = 0;
$log->info("Закрыто соединение с базой данных PostgreSQL на порту ".$self->{db_port}." keepalive=".$self->state->db_keepalive) if $self->{debug};
return 1;
}
#завершение соединения с поддержкой транзакций
sub t_shutdown {
my $self = shift;
my $force = shift;
#если не указан stable transaction enabled connect то сносим его
if ($force or !$self->TSQLStable) {
$self->{SQL} = $self->{oldSQL} if ($self->{oldSQL});
$self->{TSQL}->disconnect() if ($self->is_t_connected);
delete $self->{TSQL};
$self->{_t_connect_ok} = 0;
}
return 1;
}
#rollback+disconnect 2 в 1 флаконе для отката в аварийных ситуациях
#наиболее эффективно что то типа || return $keeper->t_abort("что то сломалось похоже");
sub t_abort {
my $self=shift;
if ($self->is_t_connected) {
$self->{TSQL}->rollback();
#в случе t_abort не проверяем уровень вложенности транзакции
$self->t_shutdown();
}
return undef;
}
#commit+disconnect 2 в 1 флаконе
sub t_finish {
my $self=shift;
if ($self->is_t_connected) {
$self->{TSQL_level}--;
#вышли на самый верх наконец то
#надо реально комитить
# <0 защита от всевозможных глюков
if ($self->{TSQL_level}<=0) {
$self->{TSQL}->commit();
$self->t_shutdown();
}
}
return 1;
}
#доступ к управлению состоянием TSQLStable (постоянного транзакционного соединения)
sub TSQLStable {
my $self = shift;
my $val = shift;
if (defined $val) {
$self->{TSQLStable} = $val;
} else {
$self->{TSQLStable} ||= 0;
}
return $self->{TSQLStable};
}
#COMPATIBILITY SUBS
sub db_connect {
return shift->connect;
}
sub t_dis_connect {
return shift->t_shutdown;
}
1;
Небольшая справка по веткам
cnddist – контейнер, в котором хранятся все дистрибутивы всех библиотек и программных пакетов, которые использовались при построении различных версий Contenido. Если какой-то библиотеки в данном хранилище нет, инсталлятор сделает попытку "подтянуть" ее с веба (например, с CPAN). Если библиотека слишком старая, есть очень большая вероятность, что ее там уже нет. Поэтому мы храним весь хлам от всех сборок. Если какой-то дистрибутив вдруг отсутствует в cnddist - напишите нам, мы положим его туда.
koi8 – отмирающая ветка, чей код, выдача и все внутренние библиотеки заточены на кодировку KOI8-R. Вносятся только те дополнения, которые касаются внешнего вида и функционала админки, баги ядра, обязательные обновления портов и мелочи, которые легко скопипастить. В дальнейшем планируется полная остановка поддержки по данной ветке.
utf8 – актуальная ветка, заточенная под UTF-8.
Внутри каждой ветки: core – исходники ядра; install – скрипт установки инсталляции; plugins – плагины; samples – "готовые к употреблению" проекты, которые можно поставить, запустить и посмотреть, как они работают.