The OpenNET Project / Index page

[ новости /+++ | форум | теги | ]

форумы  помощь  поиск  регистрация  майллист  вход/выход  слежка  RSS
"перегрузка функций, DBI модуль, Oracle, timeout"
Вариант для распечатки  
Пред. тема | След. тема 
Форумы Программирование под UNIX (Public)
Изначальное сообщение [Проследить за развитием треда]

"перегрузка функций, DBI модуль, Oracle, timeout"  
Сообщение от jr email(ok) on 20-Сен-07, 12:22 
Есть мдуль DBD::Oracle для работы с базой данных Oracle. В этом модуле нет опции настройки таймаута при работе с базой.

Так же есть решение, описанное тут http://search.cpan.org/~lbaxter/Sys-SigAction/dbd-oracle-timeout.POD, которое позволяет решить проблему. Но при этом приходится каждый раз при вызове любого метода обращения к базе (connect, prepare, execute, do и т.д.) "заворачивать" его в громоздкую "обертку" с обработкой сигналов, как это описано в методе.

Что хочется.
Создать прослойку (дочерний класс для DBD::Oracle), в котором один раз описать все эти методы обращения к базе с "оберткой" и уже в коде основной программы использовать этот дочерний класс.
Как это сделать?

P.S. С классами в Perl я на "Вы" по большей части,- от этого такой вопрос.

Высказать мнение | Ответить | Правка | Наверх | Cообщить модератору

 Оглавление

Сообщения по теме [Сортировка по времени, UBB]


1. "перегрузка функций, DBI модуль, Oracle, timeout"  
Сообщение от NuINu (??) on 21-Сен-07, 11:27 
>Есть мдуль DBD::Oracle для работы с базой данных Oracle. В этом модуле
>нет опции настройки таймаута при работе с базой.
>
>Так же есть решение, описанное тут http://search.cpan.org/~lbaxter/Sys-SigAction/dbd-oracle-timeout.POD, которое позволяет решить проблему. Но

можно конечно и классами, но вот посмотри, правда тут много лишнего но ведь это тест:
--------------------------------------------------------------------------------------
#!/usr/bin/perl -w

use strict;
use Data::Dumper;

sub safetimeout {
    my ($action_ref, $param_ref, $timeoutaction_ref, $timeout_param_ref, $timeout) = @_;
    my $result_ref;
    undef($@);
    eval {
      #print "set timeout action: $timeoutaction_ref with param:\n";
      #print Dumper($timeout_param_ref)."\n";
      local $SIG{ALRM} = sub { &$timeoutaction_ref(@$$timeout_param_ref); };
      print "set timeout: $timeout sec .\n";
      alarm($timeout); #implement N second time out
      #print "call: $action_ref with param:\n";
      #print Dumper($param_ref)."\n";
      $result_ref = \&$action_ref( @$$param_ref);
      #\&$action_ref( @$param_ref);
      alarm(0);
    };
    alarm(0);
    if ( $@ ) { print "execute timed out or error: $@\n" }    
    if(defined($result_ref) ) {
    if(ref($result_ref) eq 'ARRAY') {
        return @$result_ref;
    } elsif (ref($result_ref) eq 'SCALAR'){
        return $$result_ref;
    } else {
        return $result_ref;
    }
    } else {
    print "undefined result!\n";
    }
}


sub act_test1 {
    my @arg_list = @_;
    print "test1: start short operation\n";
    print "get argument list\n";
    print Dumper(@arg_list);
    print "test1: end short operation\n";
    return 'for test1_return';
}

sub timeout_test1 {
    my @arg_list = @_;
    print "TIMEOUT!!! operation test!!";
    print "get argument list\n";
    print Dumper(@arg_list)."\n";
    return "ret from timeout";
}

sub test1 {
    print "start test 1!\n";
    print "call timeout safe procedure!\n";
    my $ret = safetimeout(\&act_test1, \['param1', 'p2', 'p3'], \&timeout_test1, \["timeout param1"], 2);
    print "return resultis:\n";
    print Dumper($ret);

    print "end test 1!\n";
}


sub act_test2 {
    my @arg_list = @_;
    print "test2: start long operation\n";
    print "get argument list\n";
    print Dumper(@arg_list);
    my $time_sleep = $arg_list[0] || 1;
    print "start sleeping: $time_sleep sec.\n";
    sleep $time_sleep;
    print "end sleeping\n";
    print "test2: end  operation\n";
    return ['for test2_return', 1, 3, 'ret test2'];
}


sub test2 {
    print "start test 2!\n";
    print "call timeout safe procedure!\n";
    my $ret = safetimeout(\&act_test2, \[5, 'p2', 'p3'], \&timeout_test1, \["timeout param1"], 2);
    print "return resultis:\n";
    print Dumper($ret);

    print "end test 2!\n";
}

sub test2_1 {
    print "start test 2_1!\n";
    print "call timeout safe procedure!\n";
    my @ret = safetimeout(\&act_test2, \[5, 'p2', 'p3'], \&timeout_test1, \["timeout param1"], 7);
    print "return resultis:\n";
    print Dumper(@ret);

    print "end test 2_1!\n";
}


print "--------------------------------------------------\n";
&test1();
&test2();
&test2_1();


exit(0);
----------------------------------------------------------
все зависающие операции можно вызывать через оболочку:
safetimeout(), передав саму операцию, аргументы, можно еще и обработчик таймаутов, да и само время тайм аута.

поскольку здесь мы имеем дело с объектами, можно в параметре предать объект, а в фукции защищаемой функции вызвать необходимый метод, и передать туда необходимые аргументы,
всего таких фукций надо написать по числу защищаемых методов. но зато исходный код пострадает не сильно. хотя не знаю может быть можно как нибудь еще и имя метода передать, чтобы не писать кучу функций, надо подумать.

Высказать мнение | Ответить | Правка | Наверх | Cообщить модератору

2. "перегрузка функций, DBI модуль, Oracle, timeout"  
Сообщение от NuINu (??) on 21-Сен-07, 13:13 
>>Есть мдуль DBD::Oracle для работы с базой данных Oracle. В этом модуле
>>нет опции настройки таймаута при работе с базой.
>>
>>Так же есть решение, описанное тут http://search.cpan.org/~lbaxter/Sys-SigAction/dbd-oracle-timeout.POD, которое позволяет решить проблему. Но
>
>всего таких фукций надо написать по числу защищаемых методов. но зато исходный
>код пострадает не сильно. хотя не знаю может быть можно как
>нибудь еще и имя метода передать, чтобы не писать кучу функций,
>надо подумать.

в принципе я сделал и для объектов, так же рабоатет правда вот определения адреса метода у меня немного по дурацки получилось, т.е явное указание файла объекта.:
   my $ret = safetimeout($a, \&myObj::getdata, \['param2'], \&timeout_test1, \["timeout param1"], 3);

ну и вызов его в safetime:
$result_ref = $obj->$action_ref( @$$param_ref);

Высказать мнение | Ответить | Правка | Наверх | Cообщить модератору

3. "перегрузка функций, DBI модуль, Oracle, timeout"  
Сообщение от NuINu (??) on 21-Сен-07, 14:07 
>[оверквотинг удален]
>>>нет опции настройки таймаута при работе с базой.
>>>
>>>Так же есть решение, описанное тут http://search.cpan.org/~lbaxter/Sys-SigAction/dbd-oracle-timeout.POD, которое позволяет решить проблему. Но
>>
>>всего таких фукций надо написать по числу защищаемых методов. но зато исходный
>>код пострадает не сильно. хотя не знаю может быть можно как
>>нибудь еще и имя метода передать, чтобы не писать кучу функций,
>>надо подумать.
>
>в принципе я сделал и для объектов, так же рабоатет правда вот

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

вызов:    
my $ret = safetimeout($a, 'getdata', \['param2'], \&timeout_test1, \["timeout param1"], 3);

использование: в safetimeout
sub safetimeout {
    my ($obj, $action_symref, $param_ref, $timeoutaction_ref, $timeout_param_ref, $timeout) = @_;
    my $result_ref;
    undef($@);
    eval {
      local $SIG{ALRM} = sub { &$timeoutaction_ref(@$$timeout_param_ref); };
      print "set timeout: $timeout sec .\n";
      alarm($timeout); #implement N second time out
      $result_ref = $obj->$action_symref( @$$param_ref);
....

Высказать мнение | Ответить | Правка | Наверх | Cообщить модератору

4. "перегрузка функций, DBI модуль, Oracle, timeout"  
Сообщение от jr email(ok) on 21-Сен-07, 15:48 
>[оверквотинг удален]
>    undef($@);
>    eval {
>      local $SIG{ALRM} = sub { &$timeoutaction_ref(@$$timeout_param_ref);
>};
>      print "set timeout: $timeout sec .\n";
>
>      alarm($timeout); #implement N second time out
>
>      $result_ref = $obj->$action_symref( @$$param_ref);
>....

у меня немного другая задумка была - так примерно:

в DBI есть, например, функции do, prepare и execute
есть так же функция errstr, в которая возвращает текст возникающих ошибок

т.е. я создаю класс и делаю запрос:

####### подключаюсь к серверу
my $db = DBI->new( 'DBI:mysql:database=base;host=host', $user, $psaaword );

####### пусть тут у меня неожиднно пропадает коннект к базе
####### где-то маршрутизатор сломался, например
sleep 5;

####### вот эта функция не выполнится о-о-очень долго из-за потери связи
####### она должна быть "обернута в таймаут уловитель"
my $res = $db->do( 'SELECT * FROM duel' );

unless( $res ) {
  print $db->errstr;
}

вот как бы сделать так, чтобы я по прежнему мог использовать do функцию DBI модуля без всяческих ухищрений, а если будет ошибка по таймауту, то эта ошибка так же будет в доступна через errstr?
т.е. я так понимаю, что нужно унаследовать DBI класс и перегрузить все функции - do, prepare и execute - так, что бы они работали через "таймаут уловитель", т.е. что то типа этого:

package MyDBI;
use DBI;
### тут перегрузить все функци, что мне нужны
sub do {
   ## оборачиваю родительскую функцию в "таймаут уловитель"
}

sub errstr {
   ## если будет таймаут, то эта функция будет возвращать текст ошибки таймаута
}

package main;

# использую MyDBI вместо DBI
my $db = MyDBI->new( 'DBI:mysql:database=base;host=host', $user, $psaaword );
sleep 5;
my $res = $db->do( 'SELECT * FROM duel' );
unless( $res ) {
  print $db->errstr;
}

не хватает знаний по классам, что бы такую штуку сделать...

Высказать мнение | Ответить | Правка | Наверх | Cообщить модератору

5. "перегрузка функций, DBI модуль, Oracle, timeout"  
Сообщение от NuINu (??) on 21-Сен-07, 16:13 
Да я понял чего ты хочешь сделать. я бы не стал уж больно муторно, потом еще отлаживать заколебешся.


>####### подключаюсь к серверу
>my $db = DBI->new( 'DBI:mysql:database=base;host=host', $user, $psaaword );
>
>####### вот эта функция не выполнится о-о-очень долго из-за потери связи
>####### она должна быть "обернута в таймаут уловитель"
>my $res = $db->do( 'SELECT * FROM duel' );

пото до и ехекут вообще разным классам принадлежат.
my $timeouterr;


вот пользуй синтаксис:
в safetimeout
undef $timeoutstr;
а в timeout_proc ее присваивай.


my $ret = safetimeout($db, 'do', \['SELECT * FROM duel'], \&timeout_proc, \[], 3);
if(defined($timeoutstr)) {
....
}

и вообще каждую операцию не обязательно в тайм аут брать выдели всю транзакцию в и защити ее по тайм ауту. те и подключение и несколько обновлений.

Высказать мнение | Ответить | Правка | Наверх | Cообщить модератору

6. "перегрузка функций, DBI модуль, Oracle, timeout"  
Сообщение от jr email(ok) on 21-Сен-07, 16:16 
>и вообще каждую операцию не обязательно в тайм аут брать выдели всю
>транзакцию в и защити ее по тайм ауту. те и подключение
>и несколько обновлений.

да, так и сделаю
спасибо! :)

Высказать мнение | Ответить | Правка | Наверх | Cообщить модератору

Архив | Удалить

Индекс форумов | Темы | Пред. тема | След. тема
Оцените тред (1=ужас, 5=супер)? [ 1 | 2 | 3 | 4 | 5 ] [Рекомендовать для помещения в FAQ]




Партнёры:
PostgresPro
Inferno Solutions
Hosting by Hoster.ru
Хостинг:

Закладки на сайте
Проследить за страницей
Created 1996-2024 by Maxim Chirkov
Добавить, Поддержать, Вебмастеру