remove chroot which doesn't work
[cloudstore.git] / gearman / transmission.pl
1 #!/usr/bin/perl
2 use warnings;
3 use strict;
4
5 use Transmission::Client;
6 use JSON::XS;
7 use Data::Dump qw(dump);
8 use autodie;
9 use File::Path qw(make_path remove_tree);
10
11 sub user_info {
12         my $login = shift;
13         my ( undef, undef, $uid, $gid, undef, undef, $email, $dir, $shell ) = getpwnam $login;
14         return ( $uid, $gid, $dir );
15 }
16
17 use Gearman::Worker;
18 my $worker = Gearman::Worker->new;
19 $worker->job_servers('127.0.0.1:4730');
20
21 my $tc = Transmission::Client->new( autodie => 1 );
22
23 my $j = JSON::XS->new;
24 $j->allow_blessed(1);
25 $j->convert_blessed(0);
26
27 use TokyoCabinet;
28
29 my $name = $ENV{ZSLICE} || die "need ZSLICE";
30 my $torrent_dir = "/$name/torrent";
31 $name =~ s/\W+/_/g;
32
33 =head1 host_s1_torrent_list
34
35 Returns JSON encoded list of all torrents
36
37 =cut
38
39 $worker->register_function( $name . '_torrent_list' => sub {
40         my ($job) = @_;
41         my @cols = split(/\s+/,$job->arg);
42         @cols = qw( id name seeders leechers ) unless @cols;
43         my @list;       
44         for my $torrent ($tc->read_torrents) {
45                 warn "## torrent = ",dump($torrent);
46                 my $hash;
47                 $hash->{$_} = $torrent->$_ foreach @cols;
48                 push @list, $hash;
49         }
50         warn "# torrent_list = ",dump( \@list );
51         return $j->encode( \@list );
52 } );
53
54 =head1 host_s1_torrent_download ~login/path.torrent
55
56 Start download of torrent
57
58 =cut
59
60 $worker->register_function( $name . '_torrent_download' => sub {
61         my $work = $_[0]->arg;
62         chomp $work;
63         warn "# torrent_download [$work]\n";
64         
65         my $user = $1 if $work =~ s{~(\w+)/}{};
66         my $path = $work;
67
68         my $dir = (getpwnam($user))[7] || die "no user $user";
69
70         my $torrent_file = "$dir/$path";
71
72         $path =~ s/\.torrent$//;
73         my $to_dir = "$torrent_dir/download/$user/$path";
74         my ($uid,$gid) = (stat($torrent_dir))[4,5];
75         make_path $to_dir, { uid => $uid, gid => $gid };
76
77         my $t = $tc->add( filename => $torrent_file, 'download-dir' => $to_dir );
78         warn "# added $to_dir = ",dump($t);
79
80         return $to_dir;
81 } );
82
83 $worker->register_function( $name . '_torrent_download_done' => sub {
84         my $work = $_[0]->arg;
85         chomp $work;
86         warn "# torrent_download_done [$work]\n";
87
88         my ( $id, $dir, $name, $hash ) = split(/\s+#\s+/,$work);
89
90         if ( $dir =~ m{/download/(\w+)/(.+)$} ) {
91                 my $user = $1;
92                 my $path = $2;
93
94                 warn "# check $name md5sum";
95                 my $md5sum = `md5sum "$dir/$name"`;
96                 $md5sum =~ s/\s+.*$//s;
97                 if ( $name ne $md5sum ) {
98                         warn "ERROR: invalid md5sum filename ",dump( $name, $md5sum );
99                 }
100
101                 warn "# move $name to $user $path\n";
102                 my ( $uid, $gid, $home_dir ) = user_info $user;
103                 link "$dir/$name", "$home_dir/$path";
104                 chown $uid, $gid,  "$home_dir/$path";
105                 warn "FIXME: add to md5 pool?";
106
107                 my $t = $tc->remove( $id );
108                 warn "# remove $id = ",dump($t);
109
110                 warn "# $id removed $dir $name $hash\n";
111
112                 remove_tree $dir;
113         } else {
114                 warn "ERROR: can't find user in $dir for $name\n";
115         }
116
117
118 } );
119
120 =head1 host_s1_torrent_share ~login/file.txt
121
122 Create torrent and start seeding it
123
124 =cut
125
126 $worker->register_function( $name . '_torrent_share' => sub {
127         my $work = $_[0]->arg;
128         chomp $work;
129         warn "# torrent_share [$work]\n";
130         
131         my $user = $1 if $work =~ s{~(\w+)/}{};
132         my $path = $work;
133
134         my $dir = (getpwnam($user))[7] || die "no user $user";
135         my $md5_path = "$dir/.md5";
136         my %h;
137         tie %h, "TokyoCabinet::HDB", $md5_path || die "$md5_path: $!";
138         my $md5 = $h{$path} || die "can't find $path in $md5_path";
139         untie %h;
140
141         warn "# $md5 $path";
142
143         if ( ! -e "$torrent_dir/download/$md5" ) {
144                 symlink "/rsync1/s1/md5/$md5", "$torrent_dir/download/$md5"; # FIXME slice path
145                 warn "# created $torrent_dir/download/$md5";
146         }
147
148         if ( ! -e "$torrent_dir/md5/$md5.torrent" ) {
149                 my $tracker = "http://213.186.16.27:6502/announce"; # FIXME
150                 system "mktorrent --announce $tracker --no-date --verbose --output $torrent_dir/md5/$md5.torrent $torrent_dir/download/$md5";
151
152         }
153
154         symlink "$torrent_dir/md5/$md5.torrent", "$dir/$path.torrent" unless -e "$dir/$path.torrent";
155
156         $tc->add( filename => "$torrent_dir/md5/$md5.torrent" );
157
158         return "$dir/$path";
159 } );
160
161 warn "$0 $name pid $$ waitng for jobs\n";
162 $worker->work while 1;
163