2013-08-02 6 views
2

Я хочу поделиться переменной между различными модулями perl. Таким образом, я создал Perl-модуль под названием MyCache.pm, который сохраняет переменную (в моем случае переменной хэш):методы использования в разных модулях в обработчике mod_perl

package PerlModules::MyCache; 
my %cache =(); 
sub set { 
    my ($key, $value) = @_; 
    $cache{$key} = $value; 
} 
sub get { 
    my ($key) = @_; 
    return $cache{$key}; 
} 

Теперь у меня есть два обработчика. Один обработчик вызовет метод set, а другой вызовет метод get для доступа к информации.

package PerlModules::MyCacheSetter; 
use Apache2::RequestRec(); 
use Apache2::RequestIO(); 
use Apache2::Const -compile => qw(OK); 
use PerlModules::MyCache; 
sub handler { 
    my $r = shift; 
    PerlModules::MyCache::set('test1', "true"); 
    PerlModules::MyCache::set('test2', "false"); 
    PerlModules::MyCache::set('test3', "true"); 
    return Apache2::Const::OK; 
} 

А вот обработчик геттер:

package PerlModules::MyCacheGetter; 
use Apache2::RequestRec(); 
use Apache2::RequestIO(); 
use Apache2::Const -compile => qw(OK); 
use PerlModules::MyCache; 
sub handler { 
    my $r = shift; 
    $r->print(PerlModules::MyCache::get('test1')); 
    $r->print(PerlModules::MyCache::get('test2')); 
    $r->print(PerlModules::MyCache::get('test3')); 
    return Apache2::Const::OK; 
} 

Теперь я настроил апач (через http.conf), чтобы получить доступ к этой перл модули. Я запускаю обработчик setter, а затем getter, но не было выхода.

В error.log есть теперь некоторые записи:

Use of uninitialized value in subroutine entry at ../MyCacheGetter.pm line 14. 
Use of uninitialized value in subroutine entry at ../MyCacheGetter.pm line 15. 
Use of uninitialized value in subroutine entry at ../MyCacheGetter.pm line 16. 

Эти линии являются три вызова метода GET. Так что я делаю неправильно? Как я могу исправить проблему и поделиться своей переменной кэша между разными обработчиками?

+0

Выполняете ли вы обработчик сеттера и обработчик получателя в том же запросе? Возможно, это поможет, если вы покажете, как вы называете обработчиков. – mob

+0

Привет, Я использую следующую конфигурацию httpd.conf для доступа к обработчикам. После этого я вызываю через webbrowser обработчики (localhost/mcsetter): PerlModule PerlModules :: MyCacheGetter SetHandler modperl PerlResponseHandler PerlModules :: MyCacheGetter и то же самое для установщика. – atticus3000

+0

Вы делаете два отдельных HTTP-запроса (1 для набора, а затем для получения)? Если это так, вы, вероятно, получите два разных дочерних процесса Apache. Что вы сделали, чтобы передать состояние вашего кэша другим дочерним процессам? –

ответ

0

Ваш кэш будет существовать только для времени жизни данного дочернего процесса Apache. Если вы хотите, чтобы другие процессы увидели его, вам нужно будет хранить его где-нибудь, на котором они могут все получить.

Это не проверено, но вы можете получить общую идею: (теперь проверено). EDIT: ОК, похоже, вы можете получить некоторые проблемы с Storable в зависимости от версии perl и версии Storable, которую вы используете. Я заменил StorableData::Serialize в моем примере. Я также добавил строку к методам get/set, чтобы можно было использовать синтаксис -> или ::.

package PerlModules::MyCache; 

use IPC::ShareLite qw/:lock/; 
use Data::Serializer; 
use 5.10.0; 

my $key = 1234; # Your shared memory key (you set this!) 

my $ipc = IPC::ShareLite->new(
    -key  => $key, 
    -create => 'yes', 
    -destroy => 'no' 
); 

my $ser = Data::Serializer->new(
    serializer => 'Data::Dumper' 
); 

sub set { 
    shift @_ if $_[0] eq __PACKAGE__; 
    my ($key, $value) = @_; 
    $ipc->lock(LOCK_EX); 
    my $frozen; eval { $frozen = $ipc->fetch; }; 
    my $cache = defined($frozen) ? $ser->thaw($frozen) : {}; 
    $cache->{$key} = $value; 
    $ipc->store($ser->freeze($cache)); 
    $ipc->unlock; 
    return $value; 
} 

sub get { 
    shift @_ if $_[0] eq __PACKAGE__; 
    my ($key) = @_; 
    my $frozen; eval { $frozen = $ipc->fetch; }; 
    my $cache = defined($frozen) ? $ser->thaw($frozen) : {}; 
    return $cache->{$key}; 
} 

sub clear { 
    shift @_ if $_[0] eq __PACKAGE__; 
    $ipc->store($ser->freeze({})); 
    return {}; 
} 

1; 

Вы можете запустить PerlModules::MyCache->clear один раз, прежде чем проверить, чтобы обеспечить правильную структуру хранения кэша.