App-MtAws
view release on metacpan or search on metacpan
lib/App/MtAws/Journal.pm view on Meta::CPAN
confess unless length($self->{journal_file});
$self->{last_read_time} = time();
$self->{active_retrievals} = {} if $self->{use_active_retrievals};
my $binary_filename = binaryfilename $self->{journal_file};
if ($args{should_exist} && !-e $binary_filename) {
confess;
} elsif (-e $binary_filename) {
open_file(my $F, $self->{journal_file}, file_encoding => $self->{journal_encoding}, mode => '<') or
die exception journal_open_error => "Unable to open journal file %string filename% for reading, errno=%errno%",
filename => $self->{journal_file}, 'ERRNO';
my $lineno = 0;
while (!eof($F)) {
defined( my $line = <$F> ) or confess;
++$lineno;
$line =~ s/\r?\n$// or
die exception journal_format_error => "Invalid format of journal, line %lineno% not fully written", lineno => $lineno;
$self->process_line($line, $lineno);
}
close $F or confess;
}
$self->_index_archives_as_files();
return;
}
sub open_for_write
{
my ($self) = @_;
open_file($self->{append_file}, $self->{journal_file}, mode => '>>', file_encoding => $self->{journal_encoding}) or
die exception journal_open_error => "Unable to open journal file %string filename% for writing, errno=%errno%",
filename => $self->{journal_file}, 'ERRNO';
$self->{append_file}->autoflush();
}
sub close_for_write
{
my ($self) = @_;
$self->{append_file} or confess;
close $self->{append_file} or confess;
}
sub process_line
{
my ($self, $line, $lineno) = @_;
try_drop_utf8_flag $line;
my ($ver, $time, $archive_id, $size, $mtime, $treehash, $relfilename, $job_id);
# TODO: replace \S and \s, make tests for this
# Journal version 'A', 'B', 'C'
# 'B' and 'C' two way compatible
# 'A' is not compatible, but share some common code
if (($ver, $time, $archive_id, $size, $mtime, $treehash, $relfilename) =
$line =~ /^([ABC])\t([0-9]{1,20})\tCREATED\t(\S+)\t([0-9]{1,20})\t([+-]?[0-9]{1,20}|NONE)\t(\S+)\t(.*?)$/) {
confess "invalid filename" unless is_relative_filename($relfilename);
# here goes difference between 'A' and 'B','C'
if ($ver eq 'A') {
confess if $mtime eq 'NONE'; # this is not supported by format 'A'
# version 'A' produce records with mtime set even when there is no mtime in Amazon metadata
# (this is possible when archive uploaded by 3rd party program, or mtglacier <= v0.7)
# we detect this as $archive_id eq $relfilename - this is practical impossible
# unless such record was created by download-inventory command
$mtime = undef if ($archive_id eq $relfilename);
} else {
$mtime = undef if $mtime eq 'NONE';
}
$self->_add_archive({
relfilename => $relfilename,
time => $time+0, # numify
archive_id => $archive_id,
size => $size+0, # numify
mtime => defined($mtime) ? $mtime + 0 : undef,
treehash => $treehash,
});
$self->{used_versions}->{$ver} = 1 unless $self->{used_versions}->{$ver};
} elsif (($ver, $time, $archive_id, $relfilename) = $line =~ /^([ABC])\t([0-9]{1,20})\tDELETED\t(\S+)\t(.*?)$/) {
$self->_delete_archive($archive_id, $relfilename);
$self->{used_versions}->{$ver} = 1 unless $self->{used_versions}->{$ver};
} elsif (($ver, $time, $archive_id, $job_id) = $line =~ /^([ABC])\t([0-9]{1,20})\tRETRIEVE_JOB\t(\S+)\t(.*?)$/) {
$self->_retrieve_job($time+0, $archive_id, $job_id);
$self->{used_versions}->{$ver} = 1 unless $self->{used_versions}->{$ver};
# Journal version '0'
} elsif (($time, $archive_id, $size, $treehash, $relfilename) =
$line =~ /^([0-9]{1,20}) CREATED (\S+) ([0-9]{1,20}) (\S+) (.*?)$/) {
confess "invalid filename" unless is_relative_filename($relfilename);
$self->_add_archive({
relfilename => $relfilename,
time => $time+0,
mtime => undef,
archive_id => $archive_id,
size => $size+0,
treehash => $treehash,
});
$self->{used_versions}->{0} = 1 unless $self->{used_versions}->{0};
} elsif (($archive_id, $relfilename) = $line =~ /^[0-9]{1,20}\s+DELETED\s+(\S+)\s+(.*?)$/) { # TODO: delete file, parse time too!
$self->_delete_archive($archive_id, $relfilename);
$self->{used_versions}->{0} = 1 unless $self->{used_versions}->{0};
} elsif (($time, $archive_id) = $line =~ /^([0-9]{1,20})\s+RETRIEVE_JOB\s+(\S+)$/) {
$self->_retrieve_job($time+0, $archive_id);
$self->{used_versions}->{0} = 1 unless $self->{used_versions}->{0};
} elsif ( ($line =~ /^([0-9]{1,20}) /) || ($line =~ /^[A-$self->{last_supported_version}]\t/) ) {
die exception journal_format_error_broken => "Invalid format of journal, line %lineno% is broken: %line%",
lineno => $lineno, line => hex_dump_string($line);
} elsif ( ($line =~ /^[$self->{first_unsupported_version}-Z]\t/) ) {
die exception journal_format_error_future => "Invalid format of journal, line %lineno% is from future version of mtglacier",
lineno => $lineno;
} else {
die exception journal_format_error_unknown => "Invalid format of journal, line %lineno% is in unknown format: %line%",
lineno => $lineno, line => hex_dump_string($line);
}
}
sub _add_archive
{
my ($self, $args) = @_;
if ($self->check_filenames($args->{relfilename})) {
( run in 1.074 second using v1.01-cache-2.11-cpan-b16cb0d3907 )