13 |
use Data::Dumper; |
use Data::Dumper; |
14 |
|
|
15 |
|
|
16 |
our $VERSION = '0.04'; |
our $VERSION = '0.07'; |
17 |
|
|
18 |
=head1 NAME |
=head1 NAME |
19 |
|
|
29 |
=head1 DESCRIPTION |
=head1 DESCRIPTION |
30 |
|
|
31 |
This module will use C<Fuse> module, part of C<FUSE (Filesystem in USErspace)> |
This module will use C<Fuse> module, part of C<FUSE (Filesystem in USErspace)> |
32 |
available at L<http://sourceforge.net/projects/avf> to mount |
available at L<http://fuse.sourceforge.net/> to mount |
33 |
your database as file system. |
your database as file system. |
34 |
|
|
35 |
That will give you possibility to use normal file-system tools (cat, grep, vi) |
That will give you possibility to use normal file-system tools (cat, grep, vi) |
152 |
die "fork() failed: $!" unless defined $pid; |
die "fork() failed: $!" unless defined $pid; |
153 |
# child will return to caller |
# child will return to caller |
154 |
if ($pid) { |
if ($pid) { |
155 |
return $self; |
my $counter = 4; |
156 |
|
while ($counter && ! $self->is_mounted) { |
157 |
|
select(undef, undef, undef, 0.5); |
158 |
|
$counter--; |
159 |
|
} |
160 |
|
if ($self->is_mounted) { |
161 |
|
return $self; |
162 |
|
} else { |
163 |
|
return undef; |
164 |
|
} |
165 |
} |
} |
166 |
} |
} |
167 |
|
|
178 |
$self->{'read_filenames'} = sub { $self->read_filenames }; |
$self->{'read_filenames'} = sub { $self->read_filenames }; |
179 |
$self->read_filenames; |
$self->read_filenames; |
180 |
|
|
|
$self->{'mounted'} = 1; |
|
|
|
|
181 |
$fuse_self = \$self; |
$fuse_self = \$self; |
182 |
|
|
183 |
Fuse::main( |
Fuse::main( |
195 |
debug=>0, |
debug=>0, |
196 |
); |
); |
197 |
|
|
|
$self->{'mounted'} = 0; |
|
|
|
|
198 |
exit(0) if ($arg->{'fork'}); |
exit(0) if ($arg->{'fork'}); |
199 |
|
|
200 |
return 1; |
return 1; |
201 |
|
|
202 |
}; |
}; |
203 |
|
|
204 |
|
=head2 is_mounted |
205 |
|
|
206 |
|
Check if fuse filesystem is mounted |
207 |
|
|
208 |
|
if ($mnt->is_mounted) { ... } |
209 |
|
|
210 |
|
=cut |
211 |
|
|
212 |
|
sub is_mounted { |
213 |
|
my $self = shift; |
214 |
|
|
215 |
|
my $mounted = 0; |
216 |
|
my $mount = $self->{'mount'} || confess "can't find mount point!"; |
217 |
|
if (open(MTAB, "/etc/mtab")) { |
218 |
|
while(<MTAB>) { |
219 |
|
$mounted = 1 if (/ $mount fuse /i); |
220 |
|
} |
221 |
|
close(MTAB); |
222 |
|
} else { |
223 |
|
warn "can't open /etc/mtab: $!"; |
224 |
|
} |
225 |
|
|
226 |
|
return $mounted; |
227 |
|
} |
228 |
|
|
229 |
|
|
230 |
=head2 umount |
=head2 umount |
231 |
|
|
232 |
Unmount your database as filesystem. |
Unmount your database as filesystem. |
241 |
sub umount { |
sub umount { |
242 |
my $self = shift; |
my $self = shift; |
243 |
|
|
244 |
if ($self->{'mounted'}) { |
if ($self->{'mount'} && $self->is_mounted) { |
245 |
system "fusermount -u ".$self->{'mount'} || croak "umount error: $!"; |
system "fusermount -u ".$self->{'mount'}." 2>&1 >/dev/null" || return 0; |
246 |
|
return 1; |
247 |
} |
} |
248 |
|
|
249 |
return 1; |
return 0; |
250 |
} |
} |
251 |
|
|
252 |
$SIG{'INT'} = sub { |
$SIG{'INT'} = sub { |
253 |
print STDERR "umount called by SIG INT\n"; |
if ($fuse_self && $$fuse_self->umount) { |
254 |
umount; |
print STDERR "umount called by SIG INT\n"; |
255 |
|
} |
256 |
|
}; |
257 |
|
|
258 |
|
$SIG{'QUIT'} = sub { |
259 |
|
if ($fuse_self && $$fuse_self->umount) { |
260 |
|
print STDERR "umount called by SIG QUIT\n"; |
261 |
|
} |
262 |
}; |
}; |
263 |
|
|
264 |
sub DESTROY { |
sub DESTROY { |
265 |
my $self = shift; |
my $self = shift; |
266 |
return if (! $self->{'mounted'}); |
if ($self->umount) { |
267 |
print STDERR "umount called by DESTROY\n"; |
print STDERR "umount called by DESTROY\n"; |
268 |
$self->umount; |
} |
269 |
} |
} |
270 |
|
|
271 |
=head2 fuse_module_loaded |
=head2 fuse_module_loaded |
303 |
type => 0040, |
type => 0040, |
304 |
mode => 0755, |
mode => 0755, |
305 |
}, |
}, |
306 |
|
'..' => { |
307 |
|
type => 0040, |
308 |
|
mode => 0755, |
309 |
|
}, |
310 |
# a => { |
# a => { |
311 |
# cont => "File 'a'.\n", |
# cont => "File 'a'.\n", |
312 |
# type => 0100, |
# type => 0100, |
385 |
my %out; |
my %out; |
386 |
foreach my $f (sort keys %files) { |
foreach my $f (sort keys %files) { |
387 |
if ($dirname) { |
if ($dirname) { |
388 |
if ($f =~ s/^\E$dirname\Q\///) { |
if ($f =~ s/^\Q$dirname\E\///) { |
389 |
$out{$f}++ if ($f =~ /^[^\/]+$/); |
$out{$f}++ if ($f =~ /^[^\/]+$/); |
390 |
} |
} |
391 |
} else { |
} else { |
407 |
|
|
408 |
$sth->{'read'}->execute($id) || die $sth->{'read'}->errstr; |
$sth->{'read'}->execute($id) || die $sth->{'read'}->errstr; |
409 |
$files{$file}{cont} = $sth->{'read'}->fetchrow_array; |
$files{$file}{cont} = $sth->{'read'}->fetchrow_array; |
410 |
$files{$file}{ctime} = time(); |
# I should modify ctime only if content in database changed |
411 |
|
#$files{$file}{ctime} = time() unless ($files{$file}{ctime}); |
412 |
print "file '$file' content [",length($files{$file}{cont})," bytes] read in cache\n"; |
print "file '$file' content [",length($files{$file}{cont})," bytes] read in cache\n"; |
413 |
} |
} |
414 |
|
|
454 |
print "invalidate all cached content\n"; |
print "invalidate all cached content\n"; |
455 |
foreach my $f (keys %files) { |
foreach my $f (keys %files) { |
456 |
delete $files{$f}{cont}; |
delete $files{$f}{cont}; |
457 |
|
delete $files{$f}{ctime}; |
458 |
} |
} |
459 |
print "begin new transaction\n"; |
print "begin new transaction\n"; |
460 |
#$dbh->begin_work || die $dbh->errstr; |
#$dbh->begin_work || die $dbh->errstr; |
563 |
|
|
564 |
Nothing. |
Nothing. |
565 |
|
|
566 |
|
=head1 BUGS |
567 |
|
|
568 |
|
Size information (C<ls -s>) is wrong. It's a problem in upstream Fuse module |
569 |
|
(for which I'm to blame lately), so when it gets fixes, C<Fuse::DBI> will |
570 |
|
automagically pick it up. |
571 |
|
|
572 |
=head1 SEE ALSO |
=head1 SEE ALSO |
573 |
|
|
574 |
C<FUSE (Filesystem in USErspace)> website |
C<FUSE (Filesystem in USErspace)> website |
575 |
L<http://sourceforge.net/projects/avf> |
L<http://fuse.sourceforge.net/> |
576 |
|
|
577 |
Example for WebGUI which comes with this distribution in |
Example for WebGUI which comes with this distribution in |
578 |
directory C<examples/webgui.pl>. It also contains a lot of documentation |
directory C<examples/webgui.pl>. It also contains a lot of documentation |