File Coverage

blib/lib/MogileFS/Plugin/FileRefs.pm
Criterion Covered Total %
statement 7 9 77.7
branch n/a
condition n/a
subroutine 3 3 100.0
pod n/a
total 10 12 83.3


line stmt bran cond sub pod time code
1             package MogileFS::Plugin::FileRefs;
2              
3 1     1   32301 use strict;
  1         2  
  1         41  
4 1     1   6 use warnings;
  1         2  
  1         29  
5              
6 1     1   513 use MogileFS::Store;
  0            
  0            
7             use MogileFS::Worker::Query;
8              
9             use constant LOCK_TIMEOUT => 5;
10              
11             our $VERSION = '0.07';
12             MogileFS::Store->add_extra_tables("file_ref");
13              
14             sub load {
15             MogileFS::register_worker_command('add_file_ref', \&add_file_ref) or die;
16              
17             MogileFS::register_worker_command('del_file_ref', \&del_file_ref) or die;
18              
19             MogileFS::register_worker_command('rename_if_no_refs', \&rename_if_no_refs) or die;
20              
21             MogileFS::register_worker_command('list_refs_for_dkey', \&list_refs_for_dkey) or die;
22             }
23              
24             # By virtue of DBI, this returns true if the connection worked.
25             sub _claim_lock {
26             my ($rv) = Mgd::get_dbh->selectrow_array("SELECT GET_LOCK(?,?)", {}, "mogile-filerefs-".$_[1]->{domain}."-".$_[1]->{arg1}, LOCK_TIMEOUT());
27             return $rv;
28             }
29              
30             sub _free_lock {
31             eval { Mgd::get_dbh->do("SELECT RELEASE_LOCK(?)", {}, "mogile-filerefs-".$_[1]->{domain}."-".$_[1]->{arg1}) or warn "could not free lock: $DBI::errstr"; };
32             return;
33             }
34              
35             sub add_file_ref {
36             my ($query, $args) = @_;
37             my $dmid = $query->check_domain($args) or return $query->err_line('domain_not_found');
38             my $dbh = Mgd::get_dbh();
39             _claim_lock($query, $args) or return $query->err_line("get_key_lock_fail");
40             local $@;
41             my $updated = eval { $dbh->do("INSERT INTO file_ref (dmid, dkey, ref) VALUES (?, ?, ?) ON DUPLICATE KEY UPDATE ref=ref", {}, $dmid, $args->{arg1}, $args->{arg2}); };
42             if ($@ || $dbh->err || $updated < 1) {
43             _free_lock($query, $args);
44             return $query->err_line("add_file_ref_fail");
45             }
46             _free_lock($query, $args);
47             return $query->ok_line({made_new_ref => $updated>1 ? 0:1});
48             }
49              
50             sub del_file_ref {
51             my ($query, $args) = @_;
52             my $dbh = Mgd::get_dbh();
53             my $dmid = $query->check_domain($args) or return $query->err_line('domain_not_found');
54             local $@;
55             my $deleted = eval { $dbh->do("DELETE FROM file_ref WHERE dmid = ? AND dkey = ? AND ref = ?", {}, $dmid, $args->{arg1}, $args->{arg2}) };
56             if ($@ || $dbh->err) {
57             return $query->err_line("del_file_ref_fail");
58             }
59             return $query->ok_line({deleted_ref => $deleted>0 ? 1:0 });
60             }
61              
62             # TODO - use a stored procedure.
63              
64             sub rename_if_no_refs {
65             my ($query, $args) = @_;
66             my $dbh = Mgd::get_dbh();
67              
68             my $dmid = $query->check_domain($args) or return $query->err_line('domain_not_found');
69              
70             _claim_lock($query, $args) or return $query->err_line("get_key_lock_fail");
71              
72             my ($count) = eval { $dbh->selectrow_array("SELECT COUNT(*) FROM file_ref WHERE dmid = ? AND dkey = ?", {}, $dmid, $args->{arg1}) };
73             if ($@ || $dbh->err) {
74             _free_lock($query, $args);
75             return $query->err_line("rename_if_no_refs_failed");
76             }
77              
78             if ($count != 0) {
79             _free_lock($query, $args);
80             return $query->ok_line({files_outstanding => $count});
81             }
82              
83             my $updated = eval { $dbh->do("UPDATE file SET dkey = ? WHERE dmid = ? AND dkey = ?", {}, $args->{arg2}, $dmid, $args->{arg1}); };
84             if ($@ || $dbh->err) {
85             _free_lock($query, $args);
86             return $query->err_line("rename_if_no_refs_failed");
87             }
88             _free_lock($query, $args);
89              
90             return $query->ok_line({files_outstanding => 0, updated => $updated+0});
91             }
92              
93             sub list_refs_for_dkey {
94             my ($query, $args) = @_;
95             my $dmid = $query->check_domain($args) or return $query->err_line('domain_not_found');
96             my $dbh = Mgd::get_dbh();
97             my $result = eval {
98             $dbh->selectcol_arrayref("SELECT ref FROM file_ref WHERE dmid = ? AND dkey = ?", {}, $dmid, $args->{arg1});
99             };
100             if ($@ || $dbh->err) {
101             return $query->err_line("list_refs_for_dkey_failed");
102             }
103             my $i;
104             return $query->ok_line({
105             total => scalar(@$result),
106             map { "ref_".$i++ => $_ } @{ $result }
107             });
108              
109             }
110              
111             sub update_schema {
112             my $store = Mgd::get_store();
113             my $dbh = $store->dbh();
114             $dbh->do($store->filter_create_sql(TABLE_fileref()))
115             or die "Failed to create table file_ref: ". $dbh->errstr;
116              
117             return;
118             }
119              
120             {
121             package MogileFS::Store;
122              
123             sub TABLE_file_ref {
124             q{CREATE TABLE `file_ref` (
125             `dmid` SMALLINT UNSIGNED NOT NULL,
126             `dkey` varchar(255) DEFAULT NULL,
127             `ref` varchar(255) DEFAULT NULL,
128             UNIQUE KEY `i_unique` (`dmid`,`dkey`,`ref`)
129             );
130             };
131             }
132             }
133              
134             1;
135             __END__