X-Git-Url: http://git.rot13.org/?a=blobdiff_plain;f=lib%2FCloudStore%2FAPI.pm;h=1b2625d9199fbee886210d609a5876d891d91233;hb=3b458e4db1acf5a7f200f38d629bed9f38632abd;hp=690252034b49f9a89c92be31ba8b2a97e7021720;hpb=e91d8468496227014365a76a7ec7b5fc9759fa52;p=cloudstore.git diff --git a/lib/CloudStore/API.pm b/lib/CloudStore/API.pm index 6902520..1b2625d 100644 --- a/lib/CloudStore/API.pm +++ b/lib/CloudStore/API.pm @@ -36,6 +36,7 @@ sub new { sub slice_dir_port { my ($self,$slice) = @_; my ( undef, $dir, $port, undef ) = getgrnam($slice); + die "getgrnam $slice: $!" if $!; warn "# slice_dir_port $slice = $dir $port\n"; return ( $dir, $port ); } @@ -72,13 +73,17 @@ sub create_user { while(<$fh>) { my ( $login, $passwd, $uid, $gid, $email, $dir, $shell ) = split(/:/,$_); $max_uid = $uid if $uid > $max_uid; - $found = $uid if $email eq $new_email; + $found = $login if $email eq $new_email; } close($fh); my $slice = $ENV{SLICE} || 's1'; + $slice =~ s{/.+/(\w+)$}{$1}; my ( $dir, $port ) = $self->slice_dir_port( $slice ); + $dir ||= $ENV{SLICE}; + $port ||= 6501; + if ( ! $found ) { $max_uid++; $dir .= "/$max_uid"; @@ -86,7 +91,7 @@ sub create_user { open(my $fh, '>>', $self->{passwd}); print $fh "u$max_uid:$new_passwd:$max_uid:$port:$new_email:$dir:/bin/true\n"; close($fh); - $found = $max_uid; + $found = "u$max_uid"; mkdir $dir; chown $max_uid, $port, $dir; @@ -106,12 +111,19 @@ sub create_user { sub mkbasepath { my ($self,$path,$opts) = @_; + cluck "ERROR: mkbasepath called without opts, so user is root!" unless $opts; + if ( $ENV{DEBUG} ) { + warn "# mkbasepath $path ",dump($opts); + $opts->{verbose} ||= 1; + } $path =~ s{/[^/]+$}{}; - make_path $path unless -d $path; + if ( ! -d $path ) { + make_path $path, $opts; + } } sub user_dir { - my ( $self,$user, $dir ) = @_; + my ( $self, $user, $dir ) = @_; $user = $self->user_info($user) unless ref $user eq 'HASH'; my $path; if ( exists $user->{dir} ) { @@ -155,6 +167,23 @@ sub append_meta { sub usage { my ( $self, $user ) = @_; $user = $self->user_info($user) unless ref $user eq 'HASH'; + + my $usage_path = $user->{dir} . '/.meta/files.usage'; + $self->mkbasepath( $usage_path, { uid => $user->{uid} } ); + if ( ! -e $usage_path ) { + warn "# usage $usage_path missing"; + $self->list_files($user); + } + + open(my $fh, '<', $usage_path); + my $size = <$fh>; + chomp $size; + + warn "# usage $user->{login} $size bytes\n"; + return $size; + +=for slow and broken + my $path = $self->user_dir( $user => 'usage'); my $sum; open(my $fh, '<', $path); @@ -171,6 +200,9 @@ sub usage { $sum->{_quota} = $quota; warn "## usage ",dump($user, $sum), $/; return $sum; + +=cut + } sub send_file { @@ -222,6 +254,8 @@ sub send_file { $self->append( $t, 'recv', $size, $f->{uid}, $t_path ); $self->append_meta('md5sum', $t, $md5 => $t_path ) if $md5; # md5sum for received files! FIXME -- cross-slice md5 $self->refresh_file_list( $t ); + } else { + warn "ERROR: send_file $f_full -> $t_full: $!"; } return $size; @@ -237,6 +271,8 @@ sub rename_file { $self->mkbasepath( $t_full, { uid => $user->{uid}, gid => $user->{gid} } ); my $ok = rename $f_full, $t_full; + $self->refresh_file_list( $user ); + my $md5 = $self->md5_get($t_full); if ( ! $md5 ) { warn "ERROR: no md5sum for $from"; @@ -246,8 +282,6 @@ sub rename_file { $self->append_meta('md5sum', $user, 'rename' => $from ); $self->append_meta('md5sum', $user, $md5 => $from ); - $self->refresh_file_list( $user ); - return $ok; } @@ -293,7 +327,58 @@ sub file_size { $user = $self->user_info($user) unless ref $user eq 'HASH'; my $full_path = "$user->{dir}/$path"; - return -s $full_path; + my $size = -s $full_path; + warn "# file_size $full_path = $size bytes\n"; + return $size; +} + +sub list_files { + my ( $self, $user, $path ) = @_; + + $user =~ s{/+$}{} && warn "cleanup list_files arg [$user]"; + + $user = $self->user_info($user) unless ref $user eq 'HASH'; + + die "no dir for ",dump($user) unless exists $user->{dir}; + + my $files = $user->{dir} . '/.meta/files'; + $self->mkbasepath( $files, { uid => $user->{uid} } ); + if ( -e $files && -s $files > 0 && -e "$files.usage") { + local $/ = undef; + open(my $fh, '<', $files); + my $list = <$fh>; + close($fh); + warn "# list_files $user->{login} from cache ", length($list), " bytes\n"; + return $list; + } + + my $dir = $user->{dir}; + open(my $pipe, '-|', qq|find -L $dir -printf "%y %s %p\n"|); + open(my $fh, '>', "$files.new"); + my $total_usage = 0; + my $list_txt; + while(<$pipe>) { + chomp; + my ( $type, $size, $name ) = split(/\s/, $_, 3); + $name =~ s{$dir}{./}; + $name =~ s{//+}{/}g; + my $line = "$type $size $name\n"; + print $fh $line; + $list_txt .= $line; + $total_usage += $size; + } + close($pipe); + close($fh); + rename "$files.new", $files; + + open(my $usage, '>', "$files.usage.new"); + print $usage $total_usage; + close($usage); + rename "$files.usage.new", "$files.usage"; + + warn "# list_files $dir usage: $total_usage\n"; + + return $list_txt; } sub refresh_file_list { @@ -302,8 +387,12 @@ sub refresh_file_list { my $full_path = "$user->{dir}/.meta/files"; if ( -e $full_path ) { warn "## refresh_file_list $full_path"; - unlink $full_path; + unlink $full_path || warn "unlink $full_path: $!"; + } else { + warn "## refresh_file_list $full_path missing"; } + + unlink "$full_path.usage" if -e "$full_path.usage"; } 1;