前回のエントリについて、宮川さんから「AnyDBM_File をつかうといいかも」というアドバイスを頂いたので、Deduped::AnyDBM_File を書いてみた。
package Plagger::Rule::Deduped::AnyDBM_File;
use strict;
use base qw( Plagger::Rule::Deduped::Base );
use UNIVERSAL::require;
use Fcntl;
sub import {
my ( $class, @arguments ) = @_;
@AnyDBM_File::ISA = () if @arguments;
for ( @arguments ) {
push @AnyDBM_File::ISA, $_ . '_File';
}
AnyDBM_File->require;
}
sub init {
my($self, $rule) = @_;
$self->{path} = $rule->{path} || Plagger->context->cache->path_to('Deduped.db');
tie my %cache, 'AnyDBM_File', $self->{path}, O_RDWR|O_CREAT, 0666
or Plagger->context->error("Can't open DB_File $self->{path}: $!");
$self->{db} = \%cache;
}
sub find_entry {
my($self, $url) = @_;
my $value = $self->{db}->{$url};
return $value;
}
sub create_entry {
my($self, $url, $digest) = @_;
$self->{db}->{$url} = $digest;
}
sub DESTROY {
my $self = shift;
untie $self->{db};
}
1;
以下の様な感じで、利用するモジュールを NDBM_File, DB_File, GDBM_File, SDBM_File, ODBM_File の中から選べます。(何も指定しなければ DB_File が使われる。_File は省略する。)
rule:
module: Deduped
engine: GDBM
また、現在の Rule::Deduped では、Rule::Deduped::$self->{engine} を呼び出すようになっているけれど、上記 NDBM, DB, GDBM, SDBM, ODBM のいずれかが指定された場合には、Rule::Deduped::AnyDBM_File を呼び出す必要があるため、Rule::Deduped も少しいじってみた。
Index: lib/Plagger/Rule/Deduped.pm
===================================================================
--- lib/Plagger/Rule/Deduped.pm (revision 1688)
+++ lib/Plagger/Rule/Deduped.pm (working copy)
@@ -6,11 +6,19 @@
sub init {
my $self = shift;
+ my @dbms = qw( NDBM DB GDBM SDBM ODBM );
- $self->{engine} ||= 'DB_File';
+ $self->{engine} ||= 'DB';
- my $class = "Plagger::Rule::Deduped::$self->{engine}";
- $class->require or Plagger->context->error("Error loading $class: $@");
+ my $class;
+ if( grep { $_ eq $self->{engine} } @dbms ){
+ $class = 'Plagger::Rule::Deduped::AnyDBM_File';
+ $class->use($self->{engine}) or Plagger->context->error("Error loading $class: $@");
+ }
+ else {
+ $class = "Plagger::Rule::Deduped::$self->{engine}";
+ $class->require or Plagger->context->error("Error loading $class: $@");
+ }
my $deduper = $class->new($self);
$self->{deduper} = $deduper;
こうすると現在の Deduped::DB_File も、Deduped::AnyDBM_File で吸収できます。