use md5_get instead of TokyoCabinet::HDB
[cloudstore.git] / lib / CloudStore / dedup.pm
1 package CloudStore::dedup;
2 use warnings;
3 use strict;
4 use autodie;
5
6 use CloudStore::JSON;
7 use File::Path qw(make_path);
8 use Data::Dump qw(dump);
9
10 sub path_md5 {
11         my ( $path, $md5 ) = @_;
12
13         my $pool = 'md5'; # FIXME sharding?
14         mkdir $pool unless -e $pool;
15
16         if ( -e "$pool/$md5" ) {
17                 warn "dedup hit $md5 $path\n";
18                 my $dedup = $path . '.dedup';
19                 rename $path, $dedup;
20                 link "$pool/$md5", $path;
21                 unlink $dedup;
22         } else {
23                 link $path, "$pool/$md5";
24         }
25 }
26
27 sub path_remove {
28         my $path = shift;
29
30         my $deleted = CloudStore::JSON::file_data( $path );
31
32         my $md5_path = "md5/$deleted->{md5}";
33
34         my ( undef, undef, undef, $nlink ) = stat $md5_path;
35
36         warn "path_remove $path $nlink ",dump $deleted;
37         open(my $fh, '>>', 'var/dedup.log');
38         print $fh join(' ', $md5_path, $nlink, @_), $/;
39         close $fh;
40 }
41
42 my $empty_md5 = " " x 32;
43
44 sub data {
45         my $data = shift;
46
47         my $blob = "users/$data->{login}/blob";
48         my $path = "$blob/$data->{file}";
49
50         return if -d $path;
51
52         if ( $data->{file} =~ /^(.+\/)?md5sum$/ ) {
53                 my $dir = $1;
54                 my $imported = 0;
55                 warn "$path import\n";
56                 open(my $md5sum, '<', $path);
57                 while(<$md5sum>) {
58                         chomp;
59                         my ( $md5, $file ) = split(/\s+/,$_,2);
60                         if ( ! -e "md5/$md5" ) {
61                                 warn "MISSING $md5 $file\n";
62                                 next;
63                         }
64                         my $new = "users/$data->{login}/blob/$dir$file";
65                         if ( ! -e $new ) {
66                                 # create path from md5sum file
67                                 my $dir = $1 if $new =~ m{^(.+)/[^/]+$};
68                                 make_path $dir unless -d $dir;
69                                 $imported += link "md5/$md5", $new;
70                         } else {
71                                 path_md5 $new => $md5;
72                         }
73                 }
74                 print "INFO: $path imported $imported files\n";
75         }
76
77         if ( $data->{md5} ne $empty_md5 ) {
78                 path_md5 $path => $data->{md5};
79         } else {
80                 path_remove $path, $data->{timestamp};
81         }
82 }
83
84 1;