--- trunk/fuse_dbi.pl 2004/08/04 08:58:46 1 +++ trunk/fuse_dbi.pl 2004/08/07 15:16:50 8 @@ -1,6 +1,6 @@ #!/usr/bin/perl -use POSIX qw(ENOENT EISDIR EINVAL); +use POSIX qw(ENOENT EISDIR EINVAL ENOSYS O_RDWR); use Fuse; use DBI; @@ -8,32 +8,38 @@ my $sql_filenames = q{ select - templateid as id, - namespace||'/'||name as filename, + oid as id, + namespace||'/'||name||' ['||oid||']' as filename, length(template) as size, iseditable as writable from template ; }; -my $sql_content = q{ +my $sql_read = q{ select template - from template - where templateid = ?; + from template + where oid = ?; +}; + +my $sql_update = q{ + update template + set template = ? + where oid = ?; }; my $connect = "DBI:Pg:dbname=webgui"; -my $dbh = DBI->connect($connect,"","") || die $DBI::errstr; +my $dbh = DBI->connect($connect,"","", { AutoCommit => 0 }) || die $DBI::errstr; -print STDERR "$sql_filenames\n"; +print "start transaction\n"; +#$dbh->begin_work || die $dbh->errstr; my $sth_filenames = $dbh->prepare($sql_filenames) || die $dbh->errstr(); $sth_filenames->execute() || die $sth_filenames->errstr(); -my $sth_content = $dbh->prepare($sql_content) || die $dbh->errstr(); - -print "#",join(",",@{ $sth_filenames->{NAME} }),"\n"; +my $sth_read = $dbh->prepare($sql_read) || die $dbh->errstr(); +my $sth_update = $dbh->prepare($sql_update) || die $dbh->errstr(); my $ctime_start = time(); @@ -81,7 +87,7 @@ } } -print scalar (keys %dirs), " dirs:",join(" ",keys %dirs),"\n"; +print "found ",scalar(keys %files)-scalar(keys %dirs)," files, ",scalar(keys %dirs), " dirs\n"; sub filename_fixup { my ($file) = shift; @@ -119,42 +125,129 @@ $f =~ s/^\E$dirname\Q//; $f =~ s/^\///; if ($dirname) { - $out{$f}++ if (/^\E$dirname\Q/); + $out{$f}++ if (/^\E$dirname\Q/ && $f =~ /^[^\/]+$/); } else { $out{$f}++ if ($f =~ /^[^\/]+$/); } - print "f: $_ -> $f\n"; } if (! %out) { $out{'no files? bug?'}++; } - print scalar keys %out," files found for '$dirname': ",keys %out,"\n"; + print scalar keys %out," files in dir '$dirname'\n"; return (keys %out),0; } sub e_open { # VFS sanity check; it keeps all the necessary state, not much to do here. - my ($file) = filename_fixup(shift); - print("open called\n"); + my $file = filename_fixup(shift); + my $flags = shift; + return -ENOENT() unless exists($files{$file}); return -EISDIR() unless exists($files{$file}{id}); + if (!exists($files{$file}{cont})) { - $sth_content->execute($files{$file}{id}); - ($files{$file}{cont}) = $sth_content->fetchrow_array; + $sth_read->execute($files{$file}{id}) || die $sth_read->errstr; + $files{$file}{cont} = $sth_read->fetchrow_array; + print "file '$file' content read in cache\n"; } - print("open ok\n"); + print "open '$file' ",length($files{$file}{cont})," bytes\n"; return 0; } sub e_read { - # return an error numeric, or binary/text string. (note: 0 means EOF, "0" will - # give a byte (ascii "0") to the reading program) + # return an error numeric, or binary/text string. + # (note: 0 means EOF, "0" will give a byte (ascii "0") + # to the reading program) my ($file) = filename_fixup(shift); - my ($buf,$off) = @_; + my ($buf_len,$off) = @_; + return -ENOENT() unless exists($files{$file}); - return -EINVAL() if $off > length($files{$file}{cont}); - return 0 if $off == length($files{$file}{cont}); - return substr($files{$file}{cont},$off,$buf); + + my $len = length($files{$file}{cont}); + + print "read '$file' [$len bytes] offset $off length $buf_len\n"; + + return -EINVAL() if ($off > $len); + return 0 if ($off == $len); + + $buf_len = $buf_len-$off if ($off+$buf_len > $len); + + return substr($files{$file}{cont},$off,$buf_len); +} + +sub clear_cont { + print "transaction rollback\n"; + $dbh->rollback || die $dbh->errstr; + print "invalidate all cached content\n"; + foreach my $f (keys %files) { + delete $files{$f}{cont}; + } + print "begin new transaction\n"; + $dbh->begin_work || die $dbh->errstr; +} + + +sub update_db { + my $file = shift || die; + + $files{$file}{ctime} = time(); + + if (!$sth_update->execute($files{$file}{cont},$files{$file}{id})) { + print "update problem: ",$sth_update->errstr; + clear_cont; + return 0; + } else { + if (! $dbh->commit) { + print "ERROR: commit problem: ",$sth_update->errstr; + clear_cont; + return 0; + } + print "updated '$file' [",$files{$file}{id},"]\n"; + } + return 1; +} + +sub e_write { + my $file = filename_fixup(shift); + my ($buf_len,$off) = @_; + + return -ENOENT() unless exists($files{$file}); + + my $len = length($files{$file}{cont}); + + print "write '$file' [$len bytes] offset $off length\n"; + + $files{$file}{cont} = + substr($files{$file}{cont},0,$off) . + $buf_len . + substr($files{$file}{cont},$off+length($buf_len)); + + if (! update_db($file)) { + return -ENOSYS(); + } else { + return length($buf_len); + } +} + +sub e_truncate { + my $file = filename_fixup(shift); + my $size = shift; + + $files{$file}{cont} = substr($files{$file}{cont},0,$size); + return 0 +}; + + +sub e_utime { + my ($atime,$mtime,$file) = @_; + $file = filename_fixup($file); + + return -ENOENT() unless exists($files{$file}); + + print "utime '$file' $atime $mtime\n"; + + $files{$file}{time} = $mtime; + return 0; } sub e_statfs { return 255, 1, 1, 1, 1, 2 } @@ -170,5 +263,8 @@ open=>\&e_open, statfs=>\&e_statfs, read=>\&e_read, - debug=>1, + write=>\&e_write, + utime=>\&e_utime, + truncate=>\&e_truncate, + debug=>0, );