Fuse-Filesys-Virtual

 view release on metacpan or  search on metacpan

lib/Fuse/Filesys/Virtual/HandleCache.pm  view on Meta::CPAN

#
# Fuse::Filesys::Virtual::HandleCache
#
#

package Fuse::Filesys::Virtual::HandleCache;

use warnings;
use strict;

=head1 NAME

Fuse::Filesys::Virtual::HandleCache - R/W handle cache manager

=head1 VERSION

Version 0.02

=cut

our $VERSION = '0.02';

=head1 SYNOPSIS

In Fuse::Filesys::Virtual, read and write handle is cached for
performance reason.

=head1 EXPORT

Nothing.

=cut

use POSIX qw(:errno_h :fcntl_h);


=head1 FUNCTIONS

=head2 new

constractor

=cut

sub new {
    my $class = shift;
    my ($filesys) = shift;

    bless {
	_filesys => $filesys,
	_read => {},
	_write => {},
    }, $class;
}

=head2 is_busy

returns file or directory is used or not.

=cut

sub is_busy {
    my $self = shift;
    my ($fname) = @_;

    return 1 if ($self->{_read}->{$fname});
    return 1 if ($self->{_write}->{$fname});

    # directory is busy?
    for (keys %{$self->{_read}}, keys %{$self->{_write}}) {
	return 1 if (/^\Q$fname\E\//);
    }

    return undef;
}

sub _file_exist {
    my $self = shift;
    my ($fname) = @_;

    # by stat
    my $ret;
    eval {
	$ret = $self->{_filesys}->stat($fname);
    };
    return $ret unless ($@ =~ /Unimplemented/);

    eval {
	$ret = $self->{_filesys}->test('f', $fname);
    };
    return $ret unless ($@ =~ /Unimplemented/);

    die "cannot determine file status";
}

sub _read_open {
    my $self = shift;
    my ($fname) = @_;

    # already opened?
    return $self->{_read}->{$fname} if ($self->{_read}->{$fname});

    my $fh = $self->{_filesys}->open_read($fname);

    unless ($fh) {
	my $eno = $! + 0;
	if ($self->_file_exist($fname)) {
	    $! = $eno || EPERM;
	    die "cannot open file for reading: $!";
	}
	else {
	    $! = ENOENT;
	    die "file not found";
	}
    }

    return $self->{_read}->{$fname} = { fh => $fh, pos => 0 };
}

sub _read_seek {
    my $self = shift;
    my ($fname, $offset) = @_;

    my $c = $self->_read_open($fname);
    return $c if ($c->{pos} == $offset);

    my $ret = eval {
	if ($self->{_filesys}->seek($c->{fh}, $offset, 0)) {
	    $c->{pos} = $offset;



( run in 1.403 second using v1.01-cache-2.11-cpan-39bf76dae61 )