diff --git a/Build.PL b/Build.PL index d12dbe9..a416cc6 100644 --- a/Build.PL +++ b/Build.PL @@ -23,6 +23,7 @@ Module::Build->new( 'Test::More' => 0, }, 'requires' => { + 'CHI' => 0, 'Config::IniFiles' => 0, 'Fuse' => '0.11', 'MogileFS::Client::FilePaths' => 0, @@ -31,4 +32,7 @@ Module::Build->new( 'Scalar::Util' => 0, 'threads::shared' => '1.21', }, + 'recommends' => { + 'CHI::Driver::Memcached' => 0, + }, )->create_build_script(); diff --git a/bin/mount-mogilefs b/bin/mount-mogilefs index 4a22703..ab4bacf 100755 --- a/bin/mount-mogilefs +++ b/bin/mount-mogilefs @@ -31,8 +31,9 @@ $cfgFile = '/etc/mogilefs/mogilefuse.conf' if(!defined($cfgFile)); # load the config file if it exists before parsing command line arguments my %multiValueOption = ( - 'mountopt' => 'mountopts', - 'tracker' => 'trackers', + 'mountopt' => 'mountopts', + 'tracker' => 'trackers', + 'cache.server' => 'cache.servers', ); if(-e $cfgFile && -f $cfgFile) { use Config::IniFiles; diff --git a/lib/MogileFS/Client/Fuse.pm b/lib/MogileFS/Client/Fuse.pm index e5fcdcc..865cdf9 100644 --- a/lib/MogileFS/Client/Fuse.pm +++ b/lib/MogileFS/Client/Fuse.pm @@ -110,6 +110,11 @@ sub _init { 'readonly' => {'type' => BOOLEAN, 'default' => undef}, 'threaded' => {'type' => BOOLEAN, 'default' => THREADS}, 'trackers' => {'type' => ARRAYREF}, + + # cache configuration (& any additional opts prefixed with "cache.") + 'cache' => {'type' => BOOLEAN, 'optional' => 1}, + 'cache.driver' => {'type' => SCALAR, 'default' => 'Memory'}, + 'cache.namespace' => {'type' => SCALAR, 'default' => 'mogilefuse'}, }, ); @@ -144,7 +149,37 @@ sub _init { } } + # load cache support if required + my $cacheConfigured = exists $opt{'cache'}; + $opt{'cache'} = 1 if(!$cacheConfigured); + if($opt{'cache'}) { + eval { require CHI }; + if($@) { + die "Unable to load CHI for cache support" if($cacheConfigured); + $opt{'cache'} = undef; + } + } + + # load the requested cache driver + if($opt{'cache'}) { + #XXX: copied from CHI + my ($driver_class) = String::RewritePrefix->rewrite( + {'' => 'CHI::Driver::', '+' => ''}, + $opt{'cache.driver'} + ); + + # load the driver + unless($driver_class->can('fetch')) { + eval "require $driver_class;"; + if($@) { + die 'Unable to load specified CHI driver: ' . $opt{'driver'} if($cacheConfigured); + $opt{'cache'} = undef; + } + } + } + #initialize this object + $self->{'cache'} = shared_clone({}) if($opt{'cache'} && $opt{'cache.driver'} eq 'Memory'); $self->{'config'} = shared_clone({%opt}); $self->{'files'} = shared_clone({}); $self->{'initialized'} = 1; @@ -181,6 +216,35 @@ sub log { print STDERR strftime("[%Y-%m-%d %H:%M:%S] ", localtime), $msg, "\n"; } +sub cache { + my $cache = $_[0]->_localElem('CHI'); + + # create & store a cache object since we didn't have one + if(!defined $cache) { + my $config = $_[0]->_config; + if($config->{'cache'}) { + # configure CHI + my %opts; + foreach(grep {/^cache\./} keys %$config) { + $opt{substr($_, 6)} = $config->{$_}; + } + + # driver specific configuration + if($opt{'driver'} eq 'Memory') { + # we force usage of our internal thread safe shared cache + $opt{'datastore'} = $_[0]->{'cache'}; + delete $opt{'global'}; + } + + # create & store cache object + $cache = CHI->new(%opts); + $_[0]->_localElem('CHI', $cache); + } + } + + return $cache; +} + #method that will return a MogileFS object sub MogileFS { my $client = $_[0]->_localElem('MogileFS');