root/trunk/fuse/fuse.pl @ 992

Revision 992, 4.0 kB (checked in by bradfitz, 3 years ago)

checking in Leon Brocard's fuse mounter for MogileFS.

RevLine 
[992]1#!/usr/bin/perl
2use strict;
3use warnings;
4use Fuse;
5use LWP::UserAgent;
6use LWP::Simple;
7use List::MoreUtils qw(uniq);
8use MogileFS::Client;
9use Path::Class;
10use POSIX qw(ENOENT EISDIR EINVAL);
11my $DEBUG = 0;
12
13my $mogilefs = MogileFS::Client->new(
14    domain  => 'resources',
15    hosts   => [ 'cluster7:6001', 'cluster10:6001' ],
16    timeout => 5,
17);
18$mogilefs->readonly(1);
19
20my $ua = LWP::UserAgent->new;
21
22sub e_getattr {
23    my $filename = shift;
24    warn "getattr $filename\n" if $DEBUG;
25
26    my ( $size, $modes );
27    my ( $dev, $ino, $rdev, $blocks, $gid, $uid, $nlink, $blksize )
28        = ( 0, 0, 0, 1, 0, 0, 1, 1024 );
29    my ( $atime, $ctime, $mtime ) = ( time, time, time );
30
31    if ( $filename !~ m{\.} ) {
32
33        #        warn "directory!";
34        $size  = 0;
35        $modes = ( 0040 << 9 ) + 0755;
36    } else {
37
38        #        warn "file!";
39        $size  = 123;
40        $modes = ( 0100 << 9 ) + 0644;
41
42        my @paths = $mogilefs->get_paths( $filename, { noverify => 1 } );
43        my ( $content_type, $document_length, $modified_time, $expires,
44            $server )
45            = head( $paths[0] );
46        $size = $document_length;
47        ( $atime, $ctime, $mtime ) = ($modified_time) x 3;
48
49        return -ENOENT() unless @paths;
50    }
51
52    warn(
53        join(
54            ",",
55            (   $dev,   $ino,     $modes, $nlink, $uid,
56                $gid,   $rdev,    $size,  $atime, $mtime,
57                $ctime, $blksize, $blocks
58            )
59        ),
60        "\n"
61    ) if $DEBUG;
62
63    return (
64        $dev,  $ino,   $modes, $nlink, $uid,     $gid, $rdev,
65        $size, $atime, $mtime, $ctime, $blksize, $blocks
66    );
67}
68
69sub e_getdir {
70    my $prefix = shift;
71    warn "getdir $prefix\n" if $DEBUG;
72    my @filenames;
73    my $seen;
74    $mogilefs->foreach_key(
75        prefix => $prefix,
76        sub {
77            my $filename = shift;
78            $filename =~ s/$prefix//;
79
80            #            warn "file $filename";
81            $filename =~ s{^/}{};
82            push @filenames, $filename unless $filename =~ m{/};
83            my $parent = file($filename)->parent;
84            while (1) {
85                last if $seen->{$parent}++;
86                push @filenames, $parent unless $parent =~ m{/};
87
88                #                 warn "dir $parent";
89                $parent = $parent->parent;
90                last if $parent eq '.';
91                last if $parent eq '/';
92                last if $parent =~ /\.\./;
93            }
94        }
95    );
96
97    @filenames = uniq @filenames;
98    warn "returning: @filenames\n" if $DEBUG;
99    return ( @filenames, 0 );
100}
101
102sub e_open {
103    my $filename = shift;
104    warn "open $filename\n" if $DEBUG;
105
106    return -EISDIR() unless $filename =~ m{\.};
107    my @paths = $mogilefs->get_paths( $filename, { noverify => 1 } );
108    return -ENOENT() unless @paths;
109    return 0;
110}
111
112sub e_read {
113    my ( $filename, $buf, $off ) = @_;
114    warn "read $filename $buf $off\n" if $DEBUG;
115
116    return -EISDIR() if $filename =~ m{/$};
117    my @paths = $mogilefs->get_paths( $filename, { noverify => 1 } );
118    return -ENOENT() unless @paths;
119
120    my ( $content_type, $document_length, $modified_time, $expires, $server )
121        = head( $paths[0] );
122    return 0 if $off == $document_length;
123
124    my $maxoff = $off + ( $buf - 1 );
125    $maxoff = $document_length if $maxoff > $document_length;
126    my $range = $off . "-" . $maxoff;
127    warn "  Range: bytes=$range\n" if $DEBUG;
128    my $response = $ua->get( $paths[0], "Range" => "bytes=$range" );
129    if ( $response->is_success ) {
130        return $response->content;
131    } else {
132        warn $response->as_string;
133    }
134}
135
136sub e_statfs { return 255, 1, 1, 1, 1, 2 }
137
138# If you run the script directly, it will run fusermount, which will in turn
139# re-run this script - hence the funky semantics
140my ($mountpoint) = "";
141$mountpoint = shift(@ARGV) if @ARGV;
142Fuse::main(
143    debug      => 1,
144    mountpoint => $mountpoint,
145    getattr    => "main::e_getattr",
146    getdir     => "main::e_getdir",
147    open       => "main::e_open",
148    statfs     => "main::e_statfs",
149    read       => "main::e_read",
150    threaded   => 0,
151);
152
153
Note: See TracBrowser for help on using the browser.