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