| [992] | 1 | #!/usr/bin/perl |
|---|
| 2 | use strict; |
|---|
| 3 | use warnings; |
|---|
| 4 | use Fuse; |
|---|
| 5 | use LWP::UserAgent; |
|---|
| 6 | use LWP::Simple; |
|---|
| 7 | use List::MoreUtils qw(uniq); |
|---|
| 8 | use MogileFS::Client; |
|---|
| 9 | use Path::Class; |
|---|
| 10 | use POSIX qw(ENOENT EISDIR EINVAL); |
|---|
| 11 | my $DEBUG = 0; |
|---|
| 12 | |
|---|
| 13 | my $mogilefs = MogileFS::Client->new( |
|---|
| 14 | domain => 'resources', |
|---|
| 15 | hosts => [ 'cluster7:6001', 'cluster10:6001' ], |
|---|
| 16 | timeout => 5, |
|---|
| 17 | ); |
|---|
| 18 | $mogilefs->readonly(1); |
|---|
| 19 | |
|---|
| 20 | my $ua = LWP::UserAgent->new; |
|---|
| 21 | |
|---|
| 22 | sub 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 | |
|---|
| 69 | sub 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 | |
|---|
| 102 | sub 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 | |
|---|
| 112 | sub 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 | |
|---|
| 136 | sub 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 |
|---|
| 140 | my ($mountpoint) = ""; |
|---|
| 141 | $mountpoint = shift(@ARGV) if @ARGV; |
|---|
| 142 | Fuse::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 | |
|---|