2

異なる perl モジュール間で変数を共有したいと考えています。そこで、変数 (私の場合はハッシュ変数) を保存する MyCache.pm という perl モジュールを作成しました。

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

これで、2 つのハンドラーができました。1 つのハンドラーは set メソッドを呼び出し、もう 1 つのハンドラーは 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;
}

これで、これらの perl モジュールにアクセスするように (http.conf を介して) Apache を構成しました。セッターハンドラーを実行してからゲッターを実行しましたが、出力はありませんでした。

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 メソッドの 3 つの呼び出しです。それで、私は何を間違っていますか?問題を修正し、異なるハンドラー間でキャッシュ変数を共有するにはどうすればよいですか?

4

1 に答える 1

0

キャッシュは、特定の Apache 子プロセスの存続期間中のみ存在します。他のプロセスに見せたい場合は、すべてのプロセスがアクセスできる場所に保存する必要があります。

これはテストされていませんが、一般的なアイデアを得ることができます: (現在テスト済み)。Storable編集: OK、実行している perl のバージョンとバージョンによっては、いくつかの問題が発生する可能性があるようですStorableStorable私の例では に置き換えましData::Serializeた。getまた、 /setメソッドに行を追加して、 ->or::構文を使用できるようにしました。

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キャッシュ ストレージの構造が正しいことを確認するために、テストする前に 1 回実行することをお勧めします。

于 2013-08-06T04:13:55.873 に答える