bin/imager.fuse
changeset 35 bbdb8ea3079a
parent 32 02ef2d1b190a
child 36 f361d688365c
equal deleted inserted replaced
34:3c71ae4facca 35:bbdb8ea3079a
    25 use constant BS => 4 * 1024;
    25 use constant BS => 4 * 1024;
    26 
    26 
    27 my ($DATA, $IDX);
    27 my ($DATA, $IDX);
    28 
    28 
    29 sub tie_vars;
    29 sub tie_vars;
    30 sub min { (sort {$a <=> $b} @_)[0] }
    30 
    31 sub max { (sort {$a <=> $b} @_)[-1] }
    31 sub min {
       
    32     (sort { $a <=> $b } @_)[0];
       
    33 }
       
    34 
       
    35 sub max {
       
    36     (sort { $a <=> $b } @_)[-1];
       
    37 }
    32 my $debug = sub { print STDERR @_ };
    38 my $debug = sub { print STDERR @_ };
    33    $debug = sub { };
    39 $debug = sub { };
    34 
       
    35 
    40 
    36 #$SIG{INT} = sub { warn "Got ^C or INT signal\n"; exit 1; };
    41 #$SIG{INT} = sub { warn "Got ^C or INT signal\n"; exit 1; };
    37 
    42 
    38 MAIN: {
    43 MAIN: {
    39 
    44 
    77         getattr    => \&getattr,
    82         getattr    => \&getattr,
    78         getdir     => \&getdir,
    83         getdir     => \&getdir,
    79         open       => \&openfile,
    84         open       => \&openfile,
    80         read       => \&readbuffer,
    85         read       => \&readbuffer,
    81         write      => \&writebuffer,
    86         write      => \&writebuffer,
    82 	release	   => \&release,
    87         release    => \&release,
    83     );
    88     );
    84 
    89 
    85     exit;
    90     exit;
    86 
    91 
    87 }
    92 }
   141         close $fh;
   146         close $fh;
   142         return 0;
   147         return 0;
   143     }
   148     }
   144 
   149 
   145     sub release {
   150     sub release {
   146 	my $path = $IDX . shift;
   151         my $path = $IDX . shift;
   147 	return 0 if not exists $IMAGE{$path};
   152         return 0 if not exists $IMAGE{$path};
   148 	$debug->("Currently we have " . keys(%DIRTY) . " dirty blocks\n");
   153         $debug->("Currently we have " . keys(%DIRTY) . " dirty blocks\n");
   149 	return 0;
   154         return 0;
   150     }
   155     }
   151 
   156 
   152     sub readbuffer {
   157     sub readbuffer {
   153         my $path = $IDX . shift;
   158         my $path = $IDX . shift;
   154         my ($size, $offset) = @_;
   159         my ($size, $offset) = @_;
   163         return $buffer;
   168         return $buffer;
   164     }
   169     }
   165 
   170 
   166     sub _readblock {
   171     sub _readblock {
   167         my ($finfo, $size, $offset) = @_;
   172         my ($finfo, $size, $offset) = @_;
   168 	my ($block, $blockoffset, $length);
   173         my ($block, $blockoffset, $length);
   169 
   174 
   170 	$debug->("<<< block offset:$offset size:$size\n");
   175         $debug->("<<< block offset:$offset size:$size\n");
   171 	$debug->( "    block @{[int($offset/BS)]} + @{[$offset % BS]}\n");
   176         $debug->("    block @{[int($offset/BS)]} + @{[$offset % BS]}\n");
   172 
   177 
   173 	# first check if it's an dirty block
   178         # first check if it's an dirty block
   174         $block       = int($offset / BS);
   179         $block = int($offset / BS);
   175         if (exists $DIRTY{ $finfo . $block }) {
   180         if (exists $DIRTY{ $finfo . $block }) {
   176 	    $blockoffset = $offset % BS;
   181             $blockoffset = $offset % BS;
   177 	    $length = min(BS - $blockoffset, $size);
   182             $length = min(BS - $blockoffset, $size);
   178 
   183 
   179 	    $debug->("+++ dirty offset:$block*@{[BS]} + $blockoffset size:$length\n");
   184             $debug->(
       
   185                 "+++ dirty offset:$block*@{[BS]} + $blockoffset size:$length\n"
       
   186             );
   180             return substr $DIRTY{ $finfo . $block }, $blockoffset, $length;
   187             return substr $DIRTY{ $finfo . $block }, $blockoffset, $length;
   181         }
   188         }
   182 
   189 
   183 
   190         # if not dirty, we've to find it on disk
   184 	# if not dirty, we've to find it on disk
   191 
   185 
   192         $block       = int($offset / $finfo->{meta}{blocksize});
   186 	$block = int($offset / $finfo->{meta}{blocksize});
   193         $blockoffset = $offset % $finfo->{meta}{blocksize};
   187 	$blockoffset = $offset % $finfo->{meta}{blocksize};
   194         $length      = min($finfo->{meta}{blocksize} - $blockoffset, $size);
   188 	$length = min($finfo->{meta}{blocksize} - $blockoffset, $size);
   195 
   189 
   196         # find the max length we can satisfy w/o colliding
   190 	# find the max length we can satisfy w/o colliding 
   197         # with dirty blocks
   191 	# with dirty blocks
   198         for (my $l = BS ; $l < $length ; $l += BS) {
   192 	for (my $l = BS; $l < $length; $l += BS) {
   199             my $b = int(($offset + $l) / BS);
   193 	    my $b = int(($offset + $l)/BS);
   200             if ($DIRTY{ $finfo . $b }) {
   194 	    if ($DIRTY{$finfo . $b}) {
   201                 $length = $l;
   195 		$length = $l;
   202                 last;
   196 		last;
   203             }
   197 	    }
   204         }
   198 	}
   205 
   199 
   206         $debug->("=== $length\n");
   200 	$debug->("=== $length\n");
   207         $debug->(
   201 	$debug->("+++ disk offset:$block*$finfo->{meta}{blocksize} + $blockoffset size:$length\n");
   208 "+++ disk offset:$block*$finfo->{meta}{blocksize} + $blockoffset size:$length\n"
       
   209         );
   202 
   210 
   203         my $fn = "$DATA/" . $finfo->{blocklist}{$block};
   211         my $fn = "$DATA/" . $finfo->{blocklist}{$block};
   204 
   212 
   205 	state %cache;
   213         state %cache;
   206 	if (not defined $cache{fn} 
   214         if (not defined $cache{fn}
   207 	    or ($cache{fn} ne $fn)) {
   215             or ($cache{fn} ne $fn))
   208 
   216         {
   209 	    if (-e $fn) {
   217 
   210 		open(my $fh => $fn);
   218             if (-e $fn) {
   211 		binmode($fh);
   219                 open(my $fh => $fn);
   212 		local $/ = undef;
   220                 binmode($fh);
   213 		$cache{data} = <$fh>;
   221                 local $/ = undef;
   214 	    }
   222                 $cache{data} = <$fh>;
   215 	    elsif (-e "$fn.gz") {
   223             }
   216 		open(my $fh => "$fn.gz");
   224             elsif (-e "$fn.gz") {
   217 		binmode($fh);
   225                 open(my $fh => "$fn.gz");
   218 		gunzip($fh => \$cache{data})
   226                 binmode($fh);
   219 		      or die $GunzipError;
   227                 gunzip($fh => \$cache{data})
   220 	    }
   228                   or die $GunzipError;
   221 	    $cache{fn} = $fn;
   229             }
   222 	}
   230             $cache{fn} = $fn;
   223 
   231         }
   224 	return substr($cache{data}, $blockoffset, $size);
   232 
   225 	die "$fn: $!\n";
   233         return substr($cache{data}, $blockoffset, $size);
   226         
   234         die "$fn: $!\n";
       
   235 
   227     }
   236     }
   228 
   237 
   229     sub writebuffer {
   238     sub writebuffer {
   230         my $path = $IDX . shift;
   239         my $path = $IDX . shift;
   231         my ($buffer, $offset) = @_;
   240         my ($buffer, $offset) = @_;
   244         return $size;
   253         return $size;
   245     }
   254     }
   246 
   255 
   247     sub _writeblock {
   256     sub _writeblock {
   248         my ($finfo, $buffer, $offset) = @_;
   257         my ($finfo, $buffer, $offset) = @_;
   249 	my ($block, $blockoffset, $length);
   258         my ($block, $blockoffset, $length);
   250         my $size = length($buffer);
   259         my $size = length($buffer);
   251 
   260 
   252 	$block = int($offset / BS);
   261         $block       = int($offset / BS);
   253 	$blockoffset = $offset % BS;
   262         $blockoffset = $offset % BS;
   254         $length = min(BS - $blockoffset, $size);
   263         $length      = min(BS - $blockoffset, $size);
   255 
   264 
   256 	$debug->(">>> offset:$offset size:$length of $size\n");
   265         $debug->(">>> offset:$offset size:$length of $size\n");
   257 	$debug->("    block @{[int($offset/BS)]} + @{[$offset % BS]}\n");
   266         $debug->("    block @{[int($offset/BS)]} + @{[$offset % BS]}\n");
   258 
   267 
   259         if (not exists $DIRTY{ $finfo . $block }) {
   268         if (not exists $DIRTY{ $finfo . $block }) {
   260 	    $debug->("+++ missing $block+$blockoffset\n");
   269             $debug->("+++ missing $block+$blockoffset\n");
   261             $DIRTY{ $finfo . $block } = _readblock(
   270             $DIRTY{ $finfo . $block } = _readblock($finfo, BS, $block * BS);
   262                 $finfo, BS, $block * BS);
       
   263         }
   271         }
   264 
   272 
   265         substr($DIRTY{ $finfo . $block }, $blockoffset, $length) =
   273         substr($DIRTY{ $finfo . $block }, $blockoffset, $length) =
   266           substr($buffer, 0, $length);
   274           substr($buffer, 0, $length);
   267 
   275