fuse
changeset 5 bef1e4dd8e85
parent 2 79eb9a0609af
child 12 46a3e65e850f
equal deleted inserted replaced
4:fb2455a007a7 5:bef1e4dd8e85
    30 
    30 
    31 
    31 
    32 { package fs;
    32 { package fs;
    33   use strict;
    33   use strict;
    34   use warnings;
    34   use warnings;
    35   use POSIX qw(:errno_h);
    35   use POSIX qw(:errno_h); 
       
    36   use IO::Uncompress::Gunzip qw(gunzip $GunzipError);
    36   use autodie qw(:all);
    37   use autodie qw(:all);
    37 
    38 
    38   our ($ROOT, $DATA, $IDX);
    39   our ($ROOT, $DATA, $IDX);
    39   my %FILE;
    40   my %FILE;
    40   my %CACHE;
    41   my %CACHE;
    41 
    42 
    42     sub getattr {
    43     sub getattr {
    43 		my $path = $IDX . shift;
    44 	my $path = $IDX . shift;
    44 		return stat $path if -d $path;
    45 	return stat $path if -d $path;
    45 		# rest are the idx
    46 	# rest are the idx
    46 		my @attr = stat $path or return -(ENOENT);
    47 	my @attr = stat $path or return -(ENOENT);
    47 		my %meta = _get_meta($path);
    48 	my %meta = _get_meta($path);
    48 		use Data::Dumper;
    49 	$attr[7] = $meta{devsize};
    49 		warn Dumper \%meta;
    50 	$attr[9] = $meta{timestamp};
    50 		$attr[7] = $meta{devsize};
    51 	$attr[2] &= ~0222;		# r/o
    51 		$attr[9] = $meta{timestamp};
    52 	return @attr;
    52 		$attr[2] &= ~0222;		# r/o
       
    53 		warn Dumper \@attr;
       
    54 		return @attr;
       
    55     }
    53     }
    56 
    54 
    57     sub getdir {
    55     sub getdir {
    58 	my $path = $IDX . shift;
    56 	my $path = $IDX . shift;
    59 	opendir(my $dh, $path) or return 0;
    57 	opendir(my $dh, $path) or return 0;
    60 	return (readdir($dh), 0);
    58 	return (readdir($dh), 0);
    61     }
    59     }
    62 
       
    63 
    60 
    64     sub openfile {
    61     sub openfile {
    65 	my $path = $IDX . shift;
    62 	my $path = $IDX . shift;
    66 	return 0 if exists $FILE{$path};
    63 	return 0 if exists $FILE{$path};
    67 	$FILE{$path}{meta} = { _get_meta($path) };
    64 	$FILE{$path}{meta} = { _get_meta($path) };
    76 	    /^#/ and last;
    73 	    /^#/ and last;
    77 	    my ($block, $cs, $file) = split;
    74 	    my ($block, $cs, $file) = split;
    78 	    $block-- if not $FILE{$path}{meta}{format};
    75 	    $block-- if not $FILE{$path}{meta}{format};
    79 	    $FILE{$path}{blocklist}{$block} = $file;
    76 	    $FILE{$path}{blocklist}{$block} = $file;
    80 	}
    77 	}
       
    78 	close $fh;
    81 	return 0;
    79 	return 0;
    82     }
    80     }
    83 
    81 
    84     sub readbuffer {
    82     sub readbuffer {
    85 	my $path = $IDX . shift;
    83 	my $path = $IDX . shift;
    86 	my ($size, $offset) = @_;
    84 	my ($size, $offset) = @_;
    87 	my $finfo = $FILE{$path} or die "File $path is not opened!";
    85 	my $finfo = $FILE{$path} or die "File $path is not opened!";
    88 	return "" if $offset >= $finfo->{meta}{devsize};
    86 	return "" if $offset >= $finfo->{meta}{devsize};
    89 
    87 
    90 	my $buffer = "";
    88 	my $buffer = "";
    91 	for (my $need = $size; $need; $need = $size - length($buffer)) {
    89 	for (my $need = $size; $need > 0; $need = $size - length($buffer)) {
    92 	    $buffer .= _readblock($finfo, $need, $offset + length($buffer));
    90 	    $buffer .= _readblock($finfo, $need, $offset + length($buffer));
    93 	}
    91 	}
    94 
    92 
    95 	return $buffer;
    93 	return $buffer;
    96     }
    94     }
   106 
   104 
   107 	if (exists $CACHE{$finfo}{$block}) {
   105 	if (exists $CACHE{$finfo}{$block}) {
   108 	    return substr $CACHE{$finfo}{$block}, $blockoffset, $length;
   106 	    return substr $CACHE{$finfo}{$block}, $blockoffset, $length;
   109 	}
   107 	}
   110 
   108 
   111 	open(my $fh => "$DATA/" . $finfo->{blocklist}{$block});
   109 	my $fn = "$DATA/" . $finfo->{blocklist}{$block};
   112 	seek($fh => $blockoffset, 0) or die "seek: $!";
   110 	if (-e $fn) {
   113 	local $/ = \$length;
   111 		open(my $fh => $fn);
   114 	return scalar <$fh>;
   112 		binmode($fh);
       
   113 		seek($fh => $blockoffset, 0) or die "seek: $!";
       
   114 		local $/ = \$length;
       
   115 		return scalar <$fh>;
       
   116 	}
       
   117 	elsif (-e "$fn.gz") {
       
   118 		open(my $fh => "$fn.gz");
       
   119 		binmode($fh);
       
   120 		my $buffer;
       
   121 		gunzip($fh => \$buffer)
       
   122 			or die $GunzipError;
       
   123 		close($fh);
       
   124 		return substr($buffer, $blockoffset, $size);
       
   125 	}
       
   126 	
       
   127 	die "$fn: $!\n";
   115     }
   128     }
   116 
   129 
   117     sub writebuffer {
   130     sub writebuffer {
   118 	my $path = $IDX . shift;
   131 	my $path = $IDX . shift;
   119 	my ($buffer, $offset) = @_;
   132 	my ($buffer, $offset) = @_;
   120 	my $size = length($buffer);
   133 	my $size = length($buffer);
   121 	my $finfo = $FILE{$path} or die "File $path is not opened!";
   134 	my $finfo = $FILE{$path} or die "File $path is not opened!";
   122 
   135 
   123 	my $written = 0;
   136 	for (my $written = 0; $written < $size;) {
   124 	while ($written < $size) {
   137 	     # OPTIMIZE: we should not ask for writing more than the
   125 	     my $n = _writeblock($finfo, substr($buffer, $written), $offset + $written); 
   138 	     # blocksize
   126 	     return $written if not $n;
   139 	     my $n = _writeblock($finfo, substr($buffer, $written), $offset + $written) 
       
   140 		or return $written;
   127 	     $written += $n;
   141 	     $written += $n;
   128 	}
   142 	}
   129 	return $size;
   143 	return $size;
   130     }
   144     }
   131 
   145 
   135 
   149 
   136 	my $block = int($offset / $finfo->{meta}{blocksize});
   150 	my $block = int($offset / $finfo->{meta}{blocksize});
   137 	my $blockoffset = $offset % $finfo->{meta}{blocksize};
   151 	my $blockoffset = $offset % $finfo->{meta}{blocksize};
   138 
   152 
   139 	if (not exists $CACHE{$finfo}{$block}) {
   153 	if (not exists $CACHE{$finfo}{$block}) {
   140 	    open(my $fh => "$DATA/" . $finfo->{blocklist}{$block});
   154 	    #open(my $fh => "$DATA/" . $finfo->{blocklist}{$block});
   141 	    local $/ = undef;
   155 	    #local $/ = undef;
   142 	    $CACHE{$finfo}{$block} = <$fh>;
   156 	    #$CACHE{$finfo}{$block} = <$fh>;
   143 	    close($fh);
   157 	    #close($fh);
       
   158 	    $CACHE{$finfo}{$block} = _readblock($finfo, $finfo->{meta}{blocksize}, $block * $finfo->{meta}{blocksize});
   144 	}
   159 	}
   145 
   160 
   146 	my $length = $finfo->{meta}{blocksize} - $blockoffset;
   161 	my $length = $finfo->{meta}{blocksize} - $blockoffset;
   147 	$length = $size if $size <= $length;
   162 	$length = $size if $size < $length;
   148 
   163 
   149 	substr($CACHE{$finfo}{$block}, $blockoffset, $length)
   164 	substr($CACHE{$finfo}{$block}, $blockoffset, $length)
   150 	    = substr($buffer, 0, $length);
   165 	    = substr($buffer, 0, $length);
   151 
   166 
   152 	return $length;
   167 	return $length;