| line |
stmt |
bran |
cond |
sub |
pod |
time |
code |
|
1
|
|
|
|
|
|
|
# mt-aws-glacier - Amazon Glacier sync client |
|
2
|
|
|
|
|
|
|
# Copyright (C) 2012-2014 Victor Efimov |
|
3
|
|
|
|
|
|
|
# http://mt-aws.com (also http://vs-dev.com) vs@vs-dev.com |
|
4
|
|
|
|
|
|
|
# License: GPLv3 |
|
5
|
|
|
|
|
|
|
# |
|
6
|
|
|
|
|
|
|
# This file is part of "mt-aws-glacier" |
|
7
|
|
|
|
|
|
|
# |
|
8
|
|
|
|
|
|
|
# mt-aws-glacier is free software: you can redistribute it and/or modify |
|
9
|
|
|
|
|
|
|
# it under the terms of the GNU General Public License as published by |
|
10
|
|
|
|
|
|
|
# the Free Software Foundation, either version 3 of the License, or |
|
11
|
|
|
|
|
|
|
# (at your option) any later version. |
|
12
|
|
|
|
|
|
|
# |
|
13
|
|
|
|
|
|
|
# mt-aws-glacier is distributed in the hope that it will be useful, |
|
14
|
|
|
|
|
|
|
# but WITHOUT ANY WARRANTY; without even the implied warranty of |
|
15
|
|
|
|
|
|
|
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|
16
|
|
|
|
|
|
|
# GNU General Public License for more details. |
|
17
|
|
|
|
|
|
|
# |
|
18
|
|
|
|
|
|
|
# You should have received a copy of the GNU General Public License |
|
19
|
|
|
|
|
|
|
# along with this program. If not, see <http://www.gnu.org/licenses/>. |
|
20
|
|
|
|
|
|
|
|
|
21
|
|
|
|
|
|
|
package App::MtAws::ChildWorker; |
|
22
|
|
|
|
|
|
|
|
|
23
|
|
|
|
|
|
|
our $VERSION = '1.114_2'; |
|
24
|
|
|
|
|
|
|
|
|
25
|
18
|
|
|
18
|
|
8023
|
use App::MtAws::LineProtocol; |
|
|
18
|
|
|
|
|
35
|
|
|
|
18
|
|
|
|
|
1183
|
|
|
26
|
18
|
|
|
18
|
|
8030
|
use App::MtAws::GlacierRequest; |
|
|
18
|
|
|
|
|
47
|
|
|
|
18
|
|
|
|
|
708
|
|
|
27
|
18
|
|
|
18
|
|
120
|
use App::MtAws::Utils; |
|
|
18
|
|
|
|
|
32
|
|
|
|
18
|
|
|
|
|
2617
|
|
|
28
|
18
|
|
|
18
|
|
120
|
use App::MtAws::Exceptions; |
|
|
18
|
|
|
|
|
19
|
|
|
|
18
|
|
|
|
|
1187
|
|
|
29
|
18
|
|
|
18
|
|
94
|
use strict; |
|
|
18
|
|
|
|
|
28
|
|
|
|
18
|
|
|
|
|
420
|
|
|
30
|
18
|
|
|
18
|
|
77
|
use warnings; |
|
|
18
|
|
|
|
|
27
|
|
|
|
18
|
|
|
|
|
432
|
|
|
31
|
18
|
|
|
18
|
|
78
|
use utf8; |
|
|
18
|
|
|
|
|
27
|
|
|
|
18
|
|
|
|
|
101
|
|
|
32
|
18
|
|
|
18
|
|
370
|
use Carp; |
|
|
18
|
|
|
|
|
21
|
|
|
|
18
|
|
|
|
|
1662
|
|
|
33
|
18
|
|
|
18
|
|
2436
|
use IO::Select; |
|
|
18
|
|
|
|
|
6123
|
|
|
|
18
|
|
|
|
|
583
|
|
|
34
|
18
|
|
|
18
|
|
65
|
use POSIX; |
|
|
18
|
|
|
|
|
19
|
|
|
|
18
|
|
|
|
|
128
|
|
|
35
|
|
|
|
|
|
|
|
|
36
|
|
|
|
|
|
|
sub new |
|
37
|
|
|
|
|
|
|
{ |
|
38
|
0
|
|
|
0
|
0
|
0
|
my ($class, %args) = @_; |
|
39
|
0
|
|
|
|
|
0
|
my $self = \%args; |
|
40
|
0
|
0
|
|
|
|
0
|
$self->{fromchild}||die; |
|
41
|
0
|
0
|
|
|
|
0
|
$self->{tochild}||die; |
|
42
|
0
|
0
|
|
|
|
0
|
$self->{options}||die; |
|
43
|
0
|
|
|
|
|
0
|
bless $self, $class; |
|
44
|
0
|
|
|
|
|
0
|
return $self; |
|
45
|
|
|
|
|
|
|
} |
|
46
|
|
|
|
|
|
|
|
|
47
|
|
|
|
|
|
|
sub process |
|
48
|
|
|
|
|
|
|
{ |
|
49
|
0
|
|
|
0
|
0
|
0
|
my ($self) = @_; |
|
50
|
|
|
|
|
|
|
|
|
51
|
0
|
|
|
|
|
0
|
my $tochild = $self->{tochild}; |
|
52
|
0
|
|
|
|
|
0
|
my $fromchild = $self->{fromchild}; |
|
53
|
0
|
|
|
|
|
0
|
while (1) { |
|
54
|
0
|
|
|
|
|
0
|
my ($remote_pid, $action, $taskid, $data, $attachmentref) = get_data($tochild); |
|
55
|
0
|
0
|
|
|
|
0
|
$remote_pid or comm_error(); # we exit() if eof or socket error. we don't distinct |
|
56
|
0
|
|
|
|
|
0
|
my ($result, $result_attachmentref, $console_out) = $self->process_task($action, $data, $attachmentref); |
|
57
|
0
|
|
|
|
|
0
|
$result->{console_out}=$console_out; |
|
58
|
0
|
0
|
|
|
|
0
|
send_data($fromchild, 'response', $taskid, $result, $result_attachmentref) or comm_error(); |
|
59
|
|
|
|
|
|
|
}; |
|
60
|
|
|
|
|
|
|
# unreachable |
|
61
|
|
|
|
|
|
|
} |
|
62
|
|
|
|
|
|
|
|
|
63
|
|
|
|
|
|
|
sub process_task |
|
64
|
|
|
|
|
|
|
{ |
|
65
|
1
|
|
|
1
|
0
|
827
|
my ($self, $action, $data, $attachmentref) = @_; |
|
66
|
1
|
|
|
|
|
2
|
my ($result, $result_attachmentref) = (undef, undef); |
|
67
|
|
|
|
|
|
|
|
|
68
|
1
|
|
|
|
|
1
|
my $console_out = undef; |
|
69
|
1
|
50
|
|
|
|
11
|
if ($action eq 'create_upload') { |
|
|
|
50
|
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
70
|
|
|
|
|
|
|
# TODO: partsize confusing, need use another name for option partsize. partsize Amazon Upload partsize vs Download 'Range' partsize |
|
71
|
0
|
|
|
|
|
0
|
my $req = App::MtAws::GlacierRequest->new($self->{options}); |
|
72
|
0
|
|
|
|
|
0
|
my $uploadid = $req->create_multipart_upload($data->{partsize}, $data->{relfilename}, $data->{mtime}); |
|
73
|
0
|
0
|
|
|
|
0
|
confess unless $uploadid; |
|
74
|
0
|
|
|
|
|
0
|
$result = { upload_id => $uploadid }; |
|
75
|
0
|
|
|
|
|
0
|
$console_out = "Created an upload_id $uploadid"; |
|
76
|
|
|
|
|
|
|
} elsif ($action eq "upload_part") { |
|
77
|
0
|
|
|
|
|
0
|
my $req = App::MtAws::GlacierRequest->new($self->{options}); |
|
78
|
0
|
|
|
|
|
0
|
my $r = $req->upload_part($data->{upload_id}, $attachmentref, $data->{start}, $data->{part_final_hash}); |
|
79
|
0
|
0
|
|
|
|
0
|
confess "upload_part failed" unless $r; |
|
80
|
0
|
|
|
|
|
0
|
$result = { uploaded => $data->{start} } ; |
|
81
|
0
|
|
|
|
|
0
|
$console_out = "Uploaded part for $data->{relfilename} at offset [$data->{start}]"; |
|
82
|
|
|
|
|
|
|
} elsif ($action eq 'finish_upload') { |
|
83
|
|
|
|
|
|
|
# TODO: move vault to task, not to options! |
|
84
|
0
|
|
|
|
|
0
|
my $req = App::MtAws::GlacierRequest->new($self->{options}); |
|
85
|
0
|
|
|
|
|
0
|
my $archive_id = $req->finish_multipart_upload($data->{upload_id}, $data->{filesize}, $data->{final_hash}); |
|
86
|
0
|
0
|
|
|
|
0
|
confess "finish_upload failed" unless $archive_id; |
|
87
|
|
|
|
|
|
|
$result = { |
|
88
|
|
|
|
|
|
|
final_hash => $data->{final_hash}, |
|
89
|
|
|
|
|
|
|
archive_id => $archive_id, |
|
90
|
|
|
|
|
|
|
journal_entry => { |
|
91
|
|
|
|
|
|
|
type=> 'CREATED', |
|
92
|
|
|
|
|
|
|
'time' => $req->{last_request_time}, |
|
93
|
|
|
|
|
|
|
archive_id => $archive_id, |
|
94
|
|
|
|
|
|
|
size => $data->{filesize}, |
|
95
|
|
|
|
|
|
|
mtime => $data->{mtime}, |
|
96
|
|
|
|
|
|
|
treehash => $data->{final_hash}, |
|
97
|
|
|
|
|
|
|
relfilename => $data->{relfilename} |
|
98
|
|
|
|
|
|
|
}, |
|
99
|
0
|
|
|
|
|
0
|
}; |
|
100
|
0
|
|
|
|
|
0
|
$console_out = "Finished $data->{relfilename} hash [$data->{final_hash}] archive_id [$archive_id]"; |
|
101
|
|
|
|
|
|
|
} elsif ($action eq 'delete_archive') { |
|
102
|
0
|
|
|
|
|
0
|
my $req = App::MtAws::GlacierRequest->new($self->{options}); |
|
103
|
0
|
|
|
|
|
0
|
my $r = $req->delete_archive($data->{archive_id}); |
|
104
|
0
|
0
|
|
|
|
0
|
confess "delete_archive failed" unless $r; |
|
105
|
|
|
|
|
|
|
$result = { |
|
106
|
|
|
|
|
|
|
journal_entry => { |
|
107
|
|
|
|
|
|
|
type=> 'DELETED', |
|
108
|
|
|
|
|
|
|
'time' => $req->{last_request_time}, |
|
109
|
|
|
|
|
|
|
archive_id => $data->{archive_id}, |
|
110
|
|
|
|
|
|
|
relfilename => $data->{relfilename} |
|
111
|
|
|
|
|
|
|
} |
|
112
|
0
|
|
|
|
|
0
|
}; |
|
113
|
0
|
|
|
|
|
0
|
$console_out = "Deleted $data->{relfilename} archive_id [$data->{archive_id}]"; |
|
114
|
|
|
|
|
|
|
} elsif ($action eq 'retrieval_download_job') { |
|
115
|
1
|
|
|
|
|
9
|
my $req = App::MtAws::GlacierRequest->new($self->{options}); |
|
116
|
|
|
|
|
|
|
|
|
117
|
1
|
|
|
|
|
9
|
my $i_tmp = App::MtAws::IntermediateFile->new(target_file => $data->{filename}, mtime => $data->{mtime}); |
|
118
|
1
|
|
|
|
|
4
|
my $tempfile = $i_tmp->tempfilename; |
|
119
|
|
|
|
|
|
|
|
|
120
|
1
|
|
|
|
|
7
|
my $r = $req->retrieval_download_job($data->{jobid}, $data->{relfilename}, $tempfile, $data->{size}, $data->{treehash}); |
|
121
|
|
|
|
|
|
|
|
|
122
|
1
|
50
|
|
|
|
3
|
confess "retrieval_download_job failed" unless $r; |
|
123
|
|
|
|
|
|
|
|
|
124
|
1
|
|
|
|
|
3
|
$i_tmp->make_permanent; |
|
125
|
|
|
|
|
|
|
|
|
126
|
1
|
|
|
|
|
3
|
$result = { response => $r }; |
|
127
|
1
|
|
|
|
|
6
|
$console_out = "Downloaded archive $data->{filename}"; |
|
128
|
|
|
|
|
|
|
} elsif ($action eq 'segment_download_job') { |
|
129
|
0
|
|
|
|
|
0
|
my $req = App::MtAws::GlacierRequest->new($self->{options}); |
|
130
|
0
|
|
|
|
|
0
|
my $r = $req->segment_download_job($data->{jobid}, $data->{tempfile}, $data->{filename}, $data->{position}, $data->{download_size}); |
|
131
|
0
|
0
|
|
|
|
0
|
confess "segment_download_job failed" unless $r; |
|
132
|
0
|
|
|
|
|
0
|
$result = { response => $r }; |
|
133
|
0
|
|
|
|
|
0
|
$console_out = "Downloaded part of archive $data->{filename} at offset $data->{position}, size $data->{download_size}"; |
|
134
|
|
|
|
|
|
|
} elsif ($action eq 'inventory_download_job') { |
|
135
|
0
|
|
|
|
|
0
|
my $req = App::MtAws::GlacierRequest->new($self->{options}); |
|
136
|
0
|
|
|
|
|
0
|
my ($r, $inventory_type) = $req->retrieval_download_to_memory($data->{job_id}); |
|
137
|
0
|
0
|
|
|
|
0
|
confess "inventory_download_job failed" unless $r; |
|
138
|
0
|
|
|
|
|
0
|
$result = { response => !! $r, inventory_type => $inventory_type }; |
|
139
|
0
|
|
|
|
|
0
|
$result_attachmentref = \$r; |
|
140
|
0
|
0
|
|
|
|
0
|
$console_out = "Downloaded inventory in ".($inventory_type eq INVENTORY_TYPE_JSON ? "JSON" : "CSV")." format"; |
|
141
|
|
|
|
|
|
|
} elsif ($action eq 'retrieve_archive') { |
|
142
|
0
|
|
|
|
|
0
|
my $req = App::MtAws::GlacierRequest->new($self->{options}); |
|
143
|
0
|
|
|
|
|
0
|
my $r = $req->retrieve_archive( $data->{archive_id}); |
|
144
|
0
|
0
|
|
|
|
0
|
return "retrieve_archive failed" unless $r; |
|
145
|
|
|
|
|
|
|
$result = { |
|
146
|
|
|
|
|
|
|
journal_entry => { |
|
147
|
|
|
|
|
|
|
type=> 'RETRIEVE_JOB', |
|
148
|
|
|
|
|
|
|
'time' => $req->{last_request_time}, |
|
149
|
|
|
|
|
|
|
archive_id => $data->{archive_id}, |
|
150
|
0
|
|
|
|
|
0
|
job_id => $r, |
|
151
|
|
|
|
|
|
|
} |
|
152
|
|
|
|
|
|
|
}; |
|
153
|
0
|
|
|
|
|
0
|
$console_out = "Retrieved Archive $data->{archive_id}"; |
|
154
|
|
|
|
|
|
|
} elsif ($action eq 'retrieval_fetch_job') { |
|
155
|
0
|
|
|
|
|
0
|
my $req = App::MtAws::GlacierRequest->new($self->{options}); |
|
156
|
0
|
|
|
|
|
0
|
my $r = $req->retrieval_fetch_job($data->{marker}); |
|
157
|
0
|
0
|
|
|
|
0
|
confess unless $r; |
|
158
|
0
|
|
|
|
|
0
|
$result = { response => $r }; |
|
159
|
0
|
|
|
|
|
0
|
$console_out = "Retrieved Job List"; |
|
160
|
|
|
|
|
|
|
} elsif ($action eq 'inventory_fetch_job') { |
|
161
|
0
|
|
|
|
|
0
|
my $req = App::MtAws::GlacierRequest->new($self->{options}); |
|
162
|
0
|
|
|
|
|
0
|
my $r = $req->retrieval_fetch_job($data->{marker}); |
|
163
|
0
|
0
|
|
|
|
0
|
confess unless $r; |
|
164
|
0
|
|
|
|
|
0
|
$result = { response => $r }; |
|
165
|
0
|
|
|
|
|
0
|
$console_out = "Fetched job list for inventory retrieval"; |
|
166
|
|
|
|
|
|
|
} elsif ($action eq 'retrieve_inventory_job') { |
|
167
|
0
|
|
|
|
|
0
|
my $req = App::MtAws::GlacierRequest->new($self->{options}); |
|
168
|
0
|
|
|
|
|
0
|
my $r = $req->retrieve_inventory($data->{format}); |
|
169
|
0
|
0
|
|
|
|
0
|
confess unless $r; |
|
170
|
0
|
|
|
|
|
0
|
$result = { job_id => $r }; |
|
171
|
0
|
|
|
|
|
0
|
$console_out = "Retrieved Inventory, job id $r"; |
|
172
|
|
|
|
|
|
|
} elsif ($action eq 'create_vault_job') { |
|
173
|
0
|
|
|
|
|
0
|
my $req = App::MtAws::GlacierRequest->new($self->{options}); |
|
174
|
0
|
|
|
|
|
0
|
my $r = $req->create_vault($data->{name}); |
|
175
|
0
|
0
|
|
|
|
0
|
confess unless $r; |
|
176
|
0
|
|
|
|
|
0
|
$result = { }; |
|
177
|
0
|
|
|
|
|
0
|
$console_out = "Created vault $data->{name}"; |
|
178
|
|
|
|
|
|
|
} elsif ($action eq 'delete_vault_job') { |
|
179
|
0
|
|
|
|
|
0
|
my $req = App::MtAws::GlacierRequest->new($self->{options}); |
|
180
|
0
|
|
|
|
|
0
|
my $r = $req->delete_vault($data->{name}); |
|
181
|
0
|
0
|
|
|
|
0
|
confess unless $r; |
|
182
|
0
|
|
|
|
|
0
|
$result = { }; |
|
183
|
0
|
|
|
|
|
0
|
$console_out = "Deleted vault $data->{name}"; |
|
184
|
|
|
|
|
|
|
} elsif ($action eq 'verify_file') { |
|
185
|
0
|
|
|
|
|
0
|
my $th = App::MtAws::TreeHash->new(); |
|
186
|
0
|
|
|
|
|
0
|
my $binaryfilename = binaryfilename $data->{filename}; |
|
187
|
|
|
|
|
|
|
die exception file_is_zero => "File size is zero (and it was not when we read directory listing). Filename: %string filename%", |
|
188
|
|
|
|
|
|
|
filename => $data->{filename} |
|
189
|
0
|
0
|
|
|
|
0
|
unless -s $binaryfilename; |
|
190
|
|
|
|
|
|
|
|
|
191
|
|
|
|
|
|
|
open_file(my $F, $data->{filename}, mode => '<', binary => 1) or |
|
192
|
|
|
|
|
|
|
die exception upload_file_open_error => "Unable to open task file %string filename% for reading, errno=%errno%", |
|
193
|
0
|
0
|
|
|
|
0
|
filename => $data->{filename}, 'ERRNO'; # TODO: test |
|
194
|
|
|
|
|
|
|
|
|
195
|
0
|
|
|
|
|
0
|
$th->eat_file($F); |
|
196
|
0
|
0
|
|
|
|
0
|
close $F or confess; |
|
197
|
0
|
|
|
|
|
0
|
$th->calc_tree(); |
|
198
|
0
|
|
|
|
|
0
|
my $treehash = $th->get_final_hash(); |
|
199
|
|
|
|
|
|
|
|
|
200
|
0
|
0
|
|
|
|
0
|
if ($treehash eq $data->{treehash}) { |
|
201
|
0
|
|
|
|
|
0
|
$result = { match => 1 }; |
|
202
|
0
|
|
|
|
|
0
|
$console_out = "Checked treehash for $data->{filename} - MATCH"; |
|
203
|
|
|
|
|
|
|
} else { |
|
204
|
0
|
|
|
|
|
0
|
$result = { match => 0 }; |
|
205
|
0
|
|
|
|
|
0
|
$console_out = "Checked treehash for $data->{filename} - DOES NOT MATCH"; |
|
206
|
|
|
|
|
|
|
} |
|
207
|
|
|
|
|
|
|
} else { |
|
208
|
0
|
|
|
|
|
0
|
die $action; |
|
209
|
|
|
|
|
|
|
} |
|
210
|
1
|
|
|
|
|
3
|
return ($result, $result_attachmentref, $console_out); |
|
211
|
|
|
|
|
|
|
} |
|
212
|
|
|
|
|
|
|
|
|
213
|
|
|
|
|
|
|
sub comm_error |
|
214
|
|
|
|
|
|
|
{ |
|
215
|
|
|
|
|
|
|
# error message useless here |
|
216
|
0
|
|
|
0
|
0
|
|
exit(1); |
|
217
|
|
|
|
|
|
|
} |
|
218
|
|
|
|
|
|
|
|
|
219
|
|
|
|
|
|
|
1; |