X-Git-Url: https://git.gag.com/?a=blobdiff_plain;f=installcheck%2FAmanda_DB_Catalog.pl;h=e412f21da41c5a56713fdb1deb3891dad5775851;hb=fd48f3e498442f0cbff5f3606c7c403d0566150e;hp=a93c48f891a040718942ab2bd357f27c02930f52;hpb=96f35b20267e8b1a1c846d476f27fcd330e0b018;p=debian%2Famanda diff --git a/installcheck/Amanda_DB_Catalog.pl b/installcheck/Amanda_DB_Catalog.pl index a93c48f..e412f21 100644 --- a/installcheck/Amanda_DB_Catalog.pl +++ b/installcheck/Amanda_DB_Catalog.pl @@ -1,4 +1,4 @@ -# Copyright (c) 2008 Zmanda Inc. All Rights Reserved. +# Copyright (c) 2008, 2010 Zmanda, Inc. All Rights Reserved. # # This program is free software; you can redistribute it and/or modify it # under the terms of the GNU General Public License version 2 as published @@ -13,22 +13,29 @@ # with this program; if not, write to the Free Software Foundation, Inc., # 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA # -# Contact information: Zmanda Inc., 465 S Mathlida Ave, Suite 300 +# Contact information: Zmanda Inc., 465 S. Mathilda Ave., Suite 300 # Sunnyvale, CA 94086, USA, or: http://www.zmanda.com -# TODO: check large values of 'kb' - -use Test::More tests => 35; +use Test::More tests => 76; use File::Path; +use Data::Dumper; use strict; +use warnings; use lib "@amperldir@"; -use Installcheck::Config; +use Installcheck; +use Installcheck::Run; use Amanda::Config qw( :init :getconf config_dir_relative ); use Amanda::DB::Catalog; +use Amanda::Cmdline; +use Amanda::Xfer qw( :constants ); + +# send xfer logging somewhere +Amanda::Debug::dbopen("installcheck"); +Installcheck::log_test_output(); # set up and load a simple config -my $testconf = Installcheck::Config->new(); +my $testconf = Installcheck::Run->setup(); $testconf->write(); config_init($CONFIG_INIT_EXPLICIT_NAME, 'TESTCONF') == $CFGERR_OK or die("Could not load test config"); @@ -41,16 +48,63 @@ is_deeply([ Amanda::DB::Catalog::get_write_timestamps() ], [], is_deeply(Amanda::DB::Catalog::get_latest_write_timestamp(), undef, "No latest write_timestamp in an empty catalog"); -is_deeply([ Amanda::DB::Catalog::get_dumps() ], [], - "No dumpfiles in an empty catalog"); +is_deeply([ Amanda::DB::Catalog::get_parts() ], [], + "No parts in an empty catalog"); # and add some logfiles to query, and a corresponding tapelist, while also gathering -# a list of dumpfiles for comparison with the results from Amanda::DB::Catalog +# a list of parts and dumps for comparison with the results from Amanda::DB::Catalog. +# also add some files to holding disk my $logdir = config_dir_relative(getconf($CNF_LOGDIR)); my $tapelist_fn = config_dir_relative(getconf($CNF_TAPELIST)); +my $holdingdir = "$Installcheck::TMP/holding"; my $output; my $write_timestamp; -my %dumpfiles; +my (%parts, %dumps, $last_dump); +my @dumpspecs; + +sub make_holding_file { + my ($dump) = @_; + + my $dir = "$holdingdir/$dump->{dump_timestamp}"; + my $safe_disk = $dump->{'diskname'}; + $safe_disk =~ tr{/}{_}; + my $filename = "$dir/$dump->{hostname}.$safe_disk"; + mkpath($dir); + + # (note that multi-chunk holding files are not used at this point) + my $hdr = Amanda::Header->new(); + $hdr->{'type'} = $Amanda::Header::F_DUMPFILE; + $hdr->{'datestamp'} = $dump->{'dump_timestamp'}; + $hdr->{'dumplevel'} = $dump->{'level'}; + $hdr->{'name'} = $dump->{'hostname'}; + $hdr->{'disk'} = $dump->{'diskname'}; + $hdr->{'program'} = "INSTALLCHECK"; + $hdr->{'is_partial'} = ($dump->{'status'} ne 'OK'); + + open(my $fh, ">", $filename) or die("opening '$filename': $!"); + print $fh $hdr->to_string(32768,32768); + + # transfer some data to that file + my $xfer = Amanda::Xfer->new([ + Amanda::Xfer::Source::Pattern->new(1024*$dump->{'kb'}, "+-+-+-+-"), + Amanda::Xfer::Dest::Fd->new($fh), + ]); + + $xfer->start(sub { + my ($src, $msg, $xfer) = @_; + if ($msg->{type} == $XMSG_ERROR) { + die $msg->{elt} . " failed: " . $msg->{message}; + } elsif ($msg->{'type'} == $XMSG_DONE) { + $src->remove(); + Amanda::MainLoop::quit(); + } + }); + Amanda::MainLoop::run(); + close($fh); + + return $filename; +} + open (my $tapelist, ">", $tapelist_fn); while () { # skip comments @@ -74,15 +128,71 @@ while () { next; } - # new dumpfile - if (/^:dumpfile (\S+) (\S+) (\S+) (\S+) (\d+) (\S+) (\d+) (\d+) (\d+) (\S+) (\S+) (\d+)/) { - $dumpfiles{$1} = { + # new dump + if (/^:dump (\S+) (\S+) (\S+) (\S+) (\d+) (\S+) (\S+) (\d+) (\S+) (\d+) (\d+)/) { + $last_dump = $dumps{$1} = { + 'dump_timestamp' => $2, 'hostname' => $3, 'diskname' => $4, + 'level' => $5+0, 'status' => $6, 'message' => $7, + 'nparts' => $8, 'sec' => $9+0.0, 'kb' => $10, + 'orig_kb' => $11, + 'write_timestamp' => $write_timestamp, + }; + $last_dump->{'message'} = '' + if $last_dump->{'message'} eq '""'; + next; + } elsif (/^:dump (\S+) (\S+) (\S+) (\S+) (\d+) (\S+) (\S+) (\d+) (\S+) (\d+)/) { + $last_dump = $dumps{$1} = { 'dump_timestamp' => $2, 'hostname' => $3, 'diskname' => $4, - 'level' => $5+0, 'label' => $6, 'filenum' => $7+0, - 'partnum' => $8+0, 'nparts' => $9+0, 'status' => $10, - 'sec' => $11+0.0, 'kb' => $12+0, + 'level' => $5+0, 'status' => $6, 'message' => $7, + 'nparts' => $8, 'sec' => $9+0.0, 'kb' => $10, + 'orig_kb' => 0, 'write_timestamp' => $write_timestamp, }; + $last_dump->{'message'} = '' + if $last_dump->{'message'} eq '""'; + next; + } + + # new holding-disk file + if (/^:holding (\S+) (\S+) (\S+) (\S+) (\d+) (\S+) (\d+)/) { + $last_dump = $dumps{$1} = { + 'dump_timestamp' => $2, 'hostname' => $3, 'diskname' => $4, + 'level' => $5+0, 'status' => $6, 'kb' => $7, + 'orig_kb' => 0, + 'write_timestamp' => '00000000000000', + 'message' => '', + 'nparts' => 1, + 'sec' => 0.0, + }; + $parts{$1} = { + holding_file => make_holding_file($last_dump), + dump => $last_dump, + status => $last_dump->{'status'}, + sec => 0.0, + kb => $last_dump->{'kb'}, + orig_kb => 0, + partnum => 1, + }; + $last_dump->{'parts'} = [ undef, $parts{$1}, ]; + next; + } + + # new part + if (/^:part (\S+) (\S+) (\S+) (\d+) (\d+) (\S+) (\S+) (\d+) (\d+)/) { + $parts{$1} = { + 'dump' => $dumps{$2}, 'label' => $3, 'filenum' => $4, + 'partnum' => $5, 'status' => $6, 'sec' => $7+0.0, + 'kb' => $8, 'orig_kb' => $9 + }; + $last_dump->{'parts'}->[$parts{$1}->{'partnum'}] = $parts{$1}; + next; + } elsif (/^:part (\S+) (\S+) (\S+) (\d+) (\d+) (\S+) (\S+) (\d+)/) { + $parts{$1} = { + 'dump' => $dumps{$2}, 'label' => $3, 'filenum' => $4, + 'partnum' => $5, 'status' => $6, 'sec' => $7+0.0, + 'kb' => $8, 'orig_kb' => 0 + }; + $last_dump->{'parts'}->[$parts{$1}->{'partnum'}] = $parts{$1}; next; } @@ -98,267 +208,575 @@ Amanda::DB::Catalog::_clear_cache(); # Test the timestamps is_deeply([ Amanda::DB::Catalog::get_write_timestamps(), ], - [ '20080111000000', '20080222222222', '20080313133333', '20080414144444' ], + [ '20080111000000', '20080222222222', '20080313133333', '20080414144444', '20080515155555', '20080616166666' ], "get_write_timestamps returns all logfile datestamps in proper order, with zero-padding"); -is(Amanda::DB::Catalog::get_latest_write_timestamp(), '20080414144444', +is(Amanda::DB::Catalog::get_latest_write_timestamp(), '20080616166666', "get_latest_write_timestamp correctly returns the latest write timestamp"); ## -# test get_dumps and sort_dumps +# test get_parts and sort_parts + +sub partstr { + my ($part) = @_; + if (exists $part->{'holding_file'}) { + return "$part->{holding_file}: " . + "$part->{dump}->{hostname} $part->{dump}->{diskname}"; + } else { + return "$part->{label}:$part->{filenum}: " . + "$part->{dump}->{hostname} $part->{dump}->{diskname} $part->{dump}->{orig_kb}"; + } +} + +# filter out recursive links from part->dump->parts, without changing +# the original objects. Note that this removes the object-identity of +# dumps. +sub filter_parts { + my ($parts) = @_; + + my @rv; + for my $p (@$parts) { + $p = do { my %t = %$p; \%t; }; # copy hash + $p->{'dump'} = do { my %t = %{$p->{'dump'}}; \%t; }; + $p->{'dump'}->{'parts'} = undef; + push @rv, $p; + } + + return \@rv; +} + +sub got_parts { + my ($got, $exp, $msg, %params) = @_; + + # give a warning if we accidentally select zero parts + if (@$exp == 0) { + diag("warning: zero parts expected: $msg") + unless $params{'zero_parts_expected'}; + } + + # filter recursive references to avoid confusing old is_deeply instances + if (!is_deeply(filter_parts($got), filter_parts($exp), $msg)) { + diag("got parts:"); + for (@$got) { + diag(" " . partstr($_)); + } + diag("expected parts:"); + for (@$exp) { + diag(" " . partstr($_)); + } + return ''; + } + return 1; +} + +# get parts filtered by a regexp on the key +sub parts_named($) { + my ($expr) = @_; + my @selected_keys = grep { $_ =~ $expr } keys %parts; + return map { $parts{$_} } @selected_keys; +} + +# get parts filtered by an expression on the dumpfile itself +sub parts_matching(&) { + my ($block) = @_; + return grep { &$block } values %parts; +} + +# put @_ in a canonical order +sub sortparts { + map { + # convert bigints to strings and on to integers so is_deeply doesn't get confused + $_->{'dump'}->{'level'} = "$_->{dump}->{level}" + 0; + $_->{'dump'}->{'kb'} = "$_->{dump}->{kb}" + 0; + $_->{'dump'}->{'orig_kb'} = "$_->{dump}->{orig_kb}" + 0; + if (!defined $_->{filenum}) { + $_->{'filenum'} = 0; + } else { + $_->{'filenum'} = "$_->{filenum}" + 0; + } + $_->{'kb'} = "$_->{kb}" + 0; + $_->{'orig_kb'} = "$_->{orig_kb}" + 0; + $_->{'partnum'} = "$_->{partnum}" + 0; + $_; + } sort { + if (exists $a->{'holding_file'} and exists $b->{'holding_file'}) { + return $a->{'holding_file'} cmp $b->{'holding_file'}; + } elsif (not exists $a->{'holding_file'} and not exists $b->{'holding_file'}) { + return ($a->{'label'} cmp $b->{'label'}) + || ($a->{'filenum'} <=> $b->{'filenum'}); + } else { + return (exists $a->{'holding_file'})? 1 : -1; + } + } + @_; +} + +sub dumpstr { + my ($dump) = @_; + return "$dump->{hostname} $dump->{diskname} " . + "$dump->{dump_timestamp} $dump->{level}"; +} + +# filter out recursive links from dump->parts->dump, without changing +# the original objects. +sub filter_dumps { + my ($dumps) = @_; + + my @rv; + for my $d (@$dumps) { + $d = do { my %t = %$d; \%t; }; # copy hash + my @dparts = map { + return undef unless defined $_; + my $p = do { my %t = %$_; \%t }; # copy part + $p->{'dump'} = undef; + $p; + } @{$d->{'parts'}}; + $d->{'parts'} = [ @dparts ]; + push @rv, $d; + } + + return \@rv; +} + +sub got_dumps { + my ($got, $exp, $msg, %params) = @_; + + # give a warning if we accidentally select zero dumps + if (@$exp == 0) { + diag("warning: zero dumps expected: $msg") + unless $params{'zero_dumps_expected'}; + } + + # filter recursive references to avoid confusing old is_deeply instances + if (!is_deeply(filter_dumps($got), filter_dumps($exp), $msg)) { + diag("got dumps:"); + for (@$got) { + diag(" " . dumpstr($_)); + } + diag("expected dumps:"); + for (@$exp) { + diag(" " . dumpstr($_)); + } + return ''; + } + return 1; +} # get dumps filtered by a regexp on the key -sub dump_names($) { +sub dumps_named($) { my ($expr) = @_; - my @selected_keys = grep { $_ =~ $expr } keys %dumpfiles; - return map { $dumpfiles{$_} } @selected_keys; + my @selected_keys = grep { $_ =~ $expr } keys %dumps; + return map { $dumps{$_} } @selected_keys; } # get dumps filtered by an expression on the dumpfile itself -sub dumps(&) { +sub dumps_matching(&) { my ($block) = @_; - return grep { &$block } values %dumpfiles; + return grep { &$block } values %dumps; } # put @_ in a canonical order sub sortdumps { map { - # convert bigints to strings so is_deeply doesn't get confused - $_->{'level'} = "$_->{level}"; - $_->{'filenum'} = "$_->{filenum}"; - $_->{'kb'} = "$_->{kb}"; + # convert bigints to strings and on to integers so is_deeply doesn't get confused + $_->{'level'} = "$_->{level}" + 0; + $_->{'kb'} = "$_->{kb}" + 0; + $_->{'orig_kb'} = "$_->{orig_kb}" + 0; + $_->{'nparts'} = "$_->{nparts}" + 0; $_; } sort { - $a->{'label'} cmp $b->{'label'} - or $a->{'filenum'} cmp $b->{'filenum'} + $a->{'write_timestamp'} cmp $b->{'write_timestamp'} + or $a->{'hostname'} cmp $b->{'hostname'} + or $a->{'diskname'} cmp $b->{'diskname'} + or $a->{'level'} <=> $b->{'level'} } @_; } -is_deeply([ sortdumps Amanda::DB::Catalog::get_dumps() ], - [ sortdumps dump_names qr/.*/ ], +### test part selecting + +got_parts([ sortparts Amanda::DB::Catalog::get_parts() ], + [ sortparts parts_named qr/.*/ ], + "get_parts returns all parts when given no parameters"); +got_parts([ sortparts Amanda::DB::Catalog::get_parts(write_timestamp => '20080111000000') ], + [ sortparts parts_named qr/somebox_lib_20080111/ ], + "get_parts parameter write_timestamp"); +got_parts([ sortparts Amanda::DB::Catalog::get_parts(write_timestamp => '20080111') ], + [ sortparts parts_named qr/somebox_lib_20080111/ ], + "get_parts accepts a short write_timestamp and zero-pads it"); +got_parts([ sortparts Amanda::DB::Catalog::get_parts(write_timestamps => ['20080111000000','20080222222222']) ], + [ sortparts parts_named qr/(20080111|20080222222222_p\d*)$/ ], + "get_parts parameter write_timestamps"); +got_parts([ sortparts Amanda::DB::Catalog::get_parts(write_timestamp => '20080111', holding => 1) ], + [ ], + "get_parts parameter write_timestamp + holding => 1 returns nothing", + zero_parts_expected => 1); + +got_parts([ sortparts Amanda::DB::Catalog::get_parts(dump_timestamp => '20080111000000') ], + [ sortparts parts_named qr/somebox_lib_20080111/ ], + "get_parts parameter dump_timestamp"); +got_parts([ sortparts Amanda::DB::Catalog::get_parts(dump_timestamp => '20080111') ], + [ sortparts parts_named qr/somebox_lib_20080111/ ], + "get_parts accepts a short dump_timestamp and zero-pads it"); +got_parts([ sortparts Amanda::DB::Catalog::get_parts(dump_timestamps => ['20080111000000','20080222222222']) ], + [ sortparts parts_named qr/(20080111|20080222222222_p\d*)$/ ], + "get_parts parameter dump_timestamps"); +got_parts([ sortparts Amanda::DB::Catalog::get_parts(dump_timestamp_match => '200801-2') ], + [ sortparts parts_named qr/20080[12]/ ], + "get_parts parameter dump_timestamp_match"); + +got_parts([ sortparts Amanda::DB::Catalog::get_parts(hostname => 'otherbox') ], + [ sortparts parts_named qr/^otherbox_/ ], + "get_parts parameter hostname"); +got_parts([ sortparts Amanda::DB::Catalog::get_parts(hostnames => ['otherbox','somebox']) ], + [ sortparts parts_named qr/^(otherbox_|somebox_)/ ], + "get_parts parameter hostnames"); +got_parts([ sortparts Amanda::DB::Catalog::get_parts(hostname_match => '*box') ], + [ sortparts parts_named qr/box/ ], + "get_parts parameter hostname_match"); + +got_parts([ sortparts Amanda::DB::Catalog::get_parts(diskname => '/lib') ], + [ sortparts parts_named qr/_lib_/ ], + "get_parts parameter diskname"); +got_parts([ sortparts Amanda::DB::Catalog::get_parts(disknames => ['/lib','/usr/bin']) ], + [ sortparts parts_named qr/(_lib_|_usr_bin_)/ ], + "get_parts parameter disknames"); +got_parts([ sortparts Amanda::DB::Catalog::get_parts(diskname_match => '/usr') ], + [ sortparts parts_named qr/_usr_/ ], + "get_parts parameter diskname_match"); + +got_parts([ sortparts Amanda::DB::Catalog::get_parts(label => 'Conf-001') ], + [ sortparts parts_matching { defined $_->{'label'} and $_->{'label'} eq 'Conf-001' } ], + "get_parts parameter label"); +got_parts([ sortparts Amanda::DB::Catalog::get_parts(labels => ['Conf-002','Conf-003']) ], + [ sortparts parts_matching { defined $_->{'label'} and ($_->{'label'} eq 'Conf-002' or $_->{'label'} eq 'Conf-003') } ], + "get_parts parameter labels"); + +got_parts([ sortparts Amanda::DB::Catalog::get_parts(level => 0) ], + [ sortparts parts_matching { $_->{'dump'}->{'level'} == 0 } ], + "get_parts parameter level"); +got_parts([ sortparts Amanda::DB::Catalog::get_parts(levels => [ 1 ]) ], + [ sortparts parts_matching { $_->{'dump'}->{'level'} == 1 } ], + "get_parts parameter levels"); + +got_parts([ sortparts Amanda::DB::Catalog::get_parts(status => "OK") ], + [ sortparts parts_matching { $_->{'status'} eq "OK" } ], + "get_parts parameter status = OK"); + +got_parts([ sortparts Amanda::DB::Catalog::get_parts(status => "PARTIAL") ], + [ sortparts parts_matching { $_->{'status'} eq "PARTIAL" } ], + "get_parts parameter status = PARTIAL"); + +got_parts([ sortparts Amanda::DB::Catalog::get_parts(hostname => "oldbox") ], + [ sortparts parts_named qr/^oldbox_/ ], + "get_parts finds a holding-disk dump"); + +got_parts([ sortparts Amanda::DB::Catalog::get_parts(hostname => "oldbox", holding => 0) ], + [ ], + "get_parts ignores a holding-disk dump if holding is false", + zero_parts_expected => 1); +got_parts([ sortparts Amanda::DB::Catalog::get_parts(hostname => "oldbox", holding => 1) ], + [ sortparts parts_named qr/^oldbox_/ ], + "get_parts supplies a holding-disk dump if holding is true"); +got_parts([ sortparts Amanda::DB::Catalog::get_parts(hostnames => [ "oldbox", "somebox" ]) ], + [ sortparts (parts_named qr/^oldbox_.*_holding/, parts_named qr/^somebox_/) ], + "get_parts returns both holding and on-media dumps"); +got_parts([ sortparts Amanda::DB::Catalog::get_parts(hostnames => [ "oldbox", "somebox" ], + holding => 1) ], + [ sortparts parts_named qr/^oldbox_.*_holding/ ], + "get_parts ignores an on-media dump if holding is true"); + +got_parts([ sortparts Amanda::DB::Catalog::get_parts(hostnames => [ "oldbox", "somebox" ], + holding => 0) ], + [ sortparts parts_named qr/^somebox_/ ], + "get_parts ignores an holding dump if holding is false"); + +@dumpspecs = Amanda::Cmdline::parse_dumpspecs([".*", "/lib"], 0); +got_parts([ sortparts Amanda::DB::Catalog::get_parts(dumpspecs => [ @dumpspecs ]) ], + [ sortparts parts_named qr/_lib_/ ], + "get_parts parameter dumpspecs with one dumpspec"); + +@dumpspecs = Amanda::Cmdline::parse_dumpspecs([".*", "/lib", "somebox"], 0); +got_parts([ sortparts Amanda::DB::Catalog::get_parts(dumpspecs => [ @dumpspecs ]) ], + [ sortparts parts_matching { $_->{'dump'}->{'diskname'} eq '/lib' + or $_->{'dump'}->{'hostname'} eq 'somebox' } ], + "get_parts parameter dumpspecs with two dumpspecs"); + +@dumpspecs = Amanda::Cmdline::parse_dumpspecs(["otherbox", "*", "somebox"], 0); +got_parts([ sortparts Amanda::DB::Catalog::get_parts(dumpspecs => [ @dumpspecs ]) ], + [ sortparts parts_matching { $_->{'dump'}->{'hostname'} eq 'otherbox' + or $_->{'dump'}->{'hostname'} eq 'somebox' } ], + "get_parts parameter dumpspecs with two non-overlapping dumpspecs"); + +@dumpspecs = Amanda::Cmdline::parse_dumpspecs(["otherbox", "*", "somebox"], 0); +got_parts([ sortparts Amanda::DB::Catalog::get_parts(dumpspecs => [ @dumpspecs ], holding => 1), ], + [ sortparts parts_matching { $_->{'dump'}->{'hostname'} eq 'otherbox' + and exists $_->{'holding_file'} } ], + "get_parts parameter dumpspecs with two non-overlapping dumpspecs, but holding files only"); + +## more complex, multi-parameter queries + +got_parts([ sortparts Amanda::DB::Catalog::get_parts(hostname => 'somebox', + diskname_match => '/lib') ], + [ sortparts parts_named qr/^somebox_lib_/ ], + "get_parts parameters hostname and diskname_match"); + +got_parts([ sortparts Amanda::DB::Catalog::get_parts(write_timestamp => '20080313133333', + dump_timestamp => '20080311131133') ], + [ sortparts parts_matching { $_->{'dump'}->{'dump_timestamp'} eq '20080311131133' + and $_->{'dump'}->{'write_timestamp'} eq '20080313133333' } ], + "get_parts parameters write_timestamp and dump_timestamp"); + +got_parts([ sortparts Amanda::DB::Catalog::get_parts(write_timestamp => '20080414144444', + status => 'OK') ], + [ ], # there were no OK dumps on that date + "get_parts parameters write_timestamp status", + zero_parts_expected => 1); + +## test part sorting + +got_parts([ Amanda::DB::Catalog::sort_parts(['write_timestamp'], + @parts{'somebox_lib_20080222222222_p1','somebox_lib_20080111'}) ], + [ @parts{'somebox_lib_20080111','somebox_lib_20080222222222_p1'} ], + "sort by write_timestamps"); +got_parts([ Amanda::DB::Catalog::sort_parts(['-write_timestamp'], + @parts{'somebox_lib_20080111','somebox_lib_20080222222222_p1'}) ], + [ @parts{'somebox_lib_20080222222222_p1','somebox_lib_20080111'} ], + "sort by write_timestamps, reverse"); + +got_parts([ Amanda::DB::Catalog::sort_parts(['hostname', '-diskname', 'write_timestamp'], + @parts{ + 'somebox_lib_20080222222222_p1', + 'somebox_usr_bin_20080313133333', + 'somebox_lib_20080313133333_p4', + 'otherbox_lib_20080313133333', + 'somebox_lib_20080111', + }) ], + [ @parts{ + 'otherbox_lib_20080313133333', + 'somebox_usr_bin_20080313133333', + 'somebox_lib_20080111', + 'somebox_lib_20080222222222_p1', + 'somebox_lib_20080313133333_p4', + } ], + "multi-key sort"); + +got_parts([ Amanda::DB::Catalog::sort_parts(['filenum'], + @parts{ + 'somebox_lib_20080313133333_p9', + 'somebox_lib_20080313133333_p10', + 'somebox_lib_20080313133333_p1', + }) ], + [ @parts{ + 'somebox_lib_20080313133333_p1', + 'somebox_lib_20080313133333_p9', + 'somebox_lib_20080313133333_p10', + } ], + "filenum is sorted numerically, not lexically"); + +got_parts([ Amanda::DB::Catalog::sort_parts(['-partnum'], + @parts{ + 'somebox_lib_20080313133333_p9', + 'somebox_lib_20080313133333_p10', + 'somebox_lib_20080313133333_p1', + }) ], + [ @parts{ + 'somebox_lib_20080313133333_p10', + 'somebox_lib_20080313133333_p9', + 'somebox_lib_20080313133333_p1', + } ], + "partnum is sorted numerically (and in reverse!), not lexically"); + +got_parts([ Amanda::DB::Catalog::sort_parts(['nparts'], + @parts{ + 'somebox_lib_20080313133333_p9', # nparts=10 + 'somebox_lib_20080222222222_p2', # nparts=2 + }) ], + [ @parts{ + 'somebox_lib_20080222222222_p2', # nparts=2 + 'somebox_lib_20080313133333_p9', # nparts=10 + } ], + "nparts is sorted numerically, not lexically"); + +got_parts([ Amanda::DB::Catalog::sort_parts(['label'], + @parts{ + 'somebox_lib_20080313133333_p9', # Conf-003 + 'somebox_lib_20080222222222_p2', # Conf-002 + }) ], + [ @parts{ + 'somebox_lib_20080222222222_p2', # Conf-002 + 'somebox_lib_20080313133333_p9', # Conf-003 + } ], + "labels sort correctly"); + +### test dump selecting + +got_dumps([ sortdumps Amanda::DB::Catalog::get_dumps() ], + [ sortdumps dumps_named qr/.*/ ], "get_dumps returns all dumps when given no parameters"); -is_deeply([ sortdumps Amanda::DB::Catalog::get_dumps(write_timestamp => '20080111000000') ], - [ sortdumps dump_names qr/somebox_lib_20080111/ ], +got_dumps([ sortdumps Amanda::DB::Catalog::get_dumps(write_timestamp => '20080111000000') ], + [ sortdumps dumps_named qr/somebox_lib_20080111/ ], "get_dumps parameter write_timestamp"); -is_deeply([ sortdumps Amanda::DB::Catalog::get_dumps(write_timestamp => '20080111') ], - [ sortdumps dump_names qr/somebox_lib_20080111/ ], + +got_dumps([ sortdumps Amanda::DB::Catalog::get_dumps(write_timestamp => '20080111') ], + [ sortdumps dumps_named qr/somebox_lib_20080111/ ], "get_dumps accepts a short write_timestamp and zero-pads it"); -is_deeply([ sortdumps Amanda::DB::Catalog::get_dumps(write_timestamps => ['20080111000000','20080222222222']) ], - [ sortdumps dump_names qr/(20080111|20080222222222)$/ ], - "get_dumps parameter write_timestamps"); -is_deeply([ sortdumps Amanda::DB::Catalog::get_dumps(dump_timestamp => '20080111000000') ], - [ sortdumps dump_names qr/somebox_lib_20080111/ ], - "get_dumps parameter dump_timestamp"); -is_deeply([ sortdumps Amanda::DB::Catalog::get_dumps(dump_timestamp => '20080111') ], - [ sortdumps dump_names qr/somebox_lib_20080111/ ], - "get_dumps accepts a short dump_timestamp and zero-pads it"); -is_deeply([ sortdumps Amanda::DB::Catalog::get_dumps(dump_timestamps => ['20080111000000','20080222222222']) ], - [ sortdumps dump_names qr/(20080111|20080222222222)$/ ], - "get_dumps parameter dump_timestamps"); -is_deeply([ sortdumps Amanda::DB::Catalog::get_dumps(dump_timestamp_match => '200801-2') ], - [ sortdumps dump_names qr/20080[12]/ ], - "get_dumps parameter dump_timestamp_match"); +got_dumps([ sortdumps Amanda::DB::Catalog::get_dumps(write_timestamps => ['20080111000000','20080222222222']) ], + [ sortdumps dumps_named qr/(20080111|20080222222222)$/ ], + "get_dumps parameter write_timestamps"); -is_deeply([ sortdumps Amanda::DB::Catalog::get_dumps(hostname => 'otherbox') ], - [ sortdumps dump_names qr/^otherbox_/ ], +got_dumps([ sortdumps Amanda::DB::Catalog::get_dumps(hostname => 'otherbox') ], + [ sortdumps dumps_named qr/^otherbox/ ], "get_dumps parameter hostname"); -is_deeply([ sortdumps Amanda::DB::Catalog::get_dumps(hostnames => ['otherbox','somebox']) ], - [ sortdumps dump_names qr/^(otherbox_|somebox_)/ ], + +got_dumps([ sortdumps Amanda::DB::Catalog::get_dumps(hostname => 'oldbox') ], + [ sortdumps dumps_named qr/^oldbox_.*_holding/ ], + "get_dumps parameter hostname, holding"); + +got_dumps([ sortdumps Amanda::DB::Catalog::get_dumps(hostnames => ['notthere', 'otherbox']) ], + [ sortdumps dumps_named qr/^otherbox/ ], "get_dumps parameter hostnames"); -is_deeply([ sortdumps Amanda::DB::Catalog::get_dumps(hostname_match => '*box') ], - [ sortdumps dump_names qr/box/ ], + +got_dumps([ sortdumps Amanda::DB::Catalog::get_dumps(hostname_match => 'other*') ], + [ sortdumps dumps_named qr/^otherbox/ ], "get_dumps parameter hostname_match"); -is_deeply([ sortdumps Amanda::DB::Catalog::get_dumps(diskname => '/lib') ], - [ sortdumps dump_names qr/_lib_/ ], +got_dumps([ sortdumps Amanda::DB::Catalog::get_dumps(diskname => '/lib') ], + [ sortdumps dumps_named qr/^[^_]*_lib_/ ], "get_dumps parameter diskname"); -is_deeply([ sortdumps Amanda::DB::Catalog::get_dumps(disknames => ['/lib','/usr/bin']) ], - [ sortdumps dump_names qr/(_lib_|_usr_bin_)/ ], + +got_dumps([ sortdumps Amanda::DB::Catalog::get_dumps(disknames => ['/lib', '/usr/bin']) ], + [ sortdumps dumps_named qr/^[^_]*_(usr_bin|lib)_/ ], "get_dumps parameter disknames"); -is_deeply([ sortdumps Amanda::DB::Catalog::get_dumps(diskname_match => '/usr') ], - [ sortdumps dump_names qr/_usr_/ ], + +got_dumps([ sortdumps Amanda::DB::Catalog::get_dumps(diskname_match => 'bin') ], + [ sortdumps dumps_named qr/.*_bin_/ ], "get_dumps parameter diskname_match"); -is_deeply([ sortdumps Amanda::DB::Catalog::get_dumps(label => 'Conf-001') ], - [ sortdumps dumps { $_->{'label'} eq 'Conf-001' } ], - "get_dumps parameter label"); -is_deeply([ sortdumps Amanda::DB::Catalog::get_dumps(labels => ['Conf-002','Conf-003']) ], - [ sortdumps dumps { $_->{'label'} eq 'Conf-002' or $_->{'label'} eq 'Conf-003' } ], - "get_dumps parameter labels"); +got_dumps([ sortdumps Amanda::DB::Catalog::get_dumps(dump_timestamp => '20080414144444') ], + [ sortdumps dumps_matching { $_->{'dump_timestamp'} eq '20080414144444' } ], + "get_dumps parameter dump_timestamp"); -is_deeply([ sortdumps Amanda::DB::Catalog::get_dumps(level => 0) ], - [ sortdumps dumps { $_->{'level'} == 0 } ], +got_dumps([ sortdumps Amanda::DB::Catalog::get_dumps( + dump_timestamps => ['20080414144444', '20080311131133']) ], + [ sortdumps dumps_matching { $_->{'dump_timestamp'} eq '20080414144444' + or $_->{'dump_timestamp'} eq '20080311131133' } ], + "get_dumps parameter dump_timestamps"); + +got_dumps([ sortdumps Amanda::DB::Catalog::get_dumps(dump_timestamp_match => '200804-7') ], + [ sortdumps dumps_matching { $_->{'dump_timestamp'} =~ /^20080[4567]/ } ], + "get_dumps parameter dump_timestamp_match"); + +got_dumps([ sortdumps Amanda::DB::Catalog::get_dumps(level => 0) ], + [ sortdumps dumps_matching { $_->{'level'} == 0 } ], "get_dumps parameter level"); -is_deeply([ sortdumps Amanda::DB::Catalog::get_dumps(levels => [ 1 ]) ], - [ sortdumps dumps { $_->{'level'} == 1 } ], + +got_dumps([ sortdumps Amanda::DB::Catalog::get_dumps(levels => [ 1 ]) ], + [ sortdumps dumps_matching { $_->{'level'} == 1 } ], "get_dumps parameter levels"); -is_deeply([ sortdumps Amanda::DB::Catalog::get_dumps(status => "OK") ], - [ sortdumps dumps { $_->{'status'} eq "OK" } ], +got_dumps([ sortdumps Amanda::DB::Catalog::get_dumps(status => "OK") ], + [ sortdumps dumps_matching { $_->{'status'} eq "OK" } ], "get_dumps parameter status = OK"); -is_deeply([ sortdumps Amanda::DB::Catalog::get_dumps(status => "PARTIAL") ], - [ sortdumps dumps { $_->{'status'} eq "PARTIAL" } ], +got_dumps([ sortdumps Amanda::DB::Catalog::get_dumps(status => "PARTIAL") ], + [ sortdumps dumps_matching { $_->{'status'} eq "PARTIAL" } ], "get_dumps parameter status = PARTIAL"); -## more complex, multi-parameter queries - -is_deeply([ sortdumps Amanda::DB::Catalog::get_dumps(hostname => 'somebox', - diskname_match => '/lib') ], - [ sortdumps dump_names qr/^somebox_lib_/ ], - "get_dumps parameters hostname and diskname_match"); - -is_deeply([ sortdumps Amanda::DB::Catalog::get_dumps(write_timestamp => '20080313133333', - dump_timestamp => '20080311131133') ], - [ sortdumps dumps { $_->{'dump_timestamp'} eq '20080311131133' - and $_->{'write_timestamp'} eq '20080313133333' } ], - "get_dumps parameters write_timestamp and dump_timestamp"); - -is_deeply([ sortdumps Amanda::DB::Catalog::get_dumps(write_timestamp => '20080414144444', - status => 'OK') ], - [ ], # there were no OK dumps on that date - "get_dumps parameters write_timestamp status"); - -## test sorting -# (this is not exhaustive, as that would make the tests more complex than the -# code being tested) - -is_deeply([ Amanda::DB::Catalog::sort_dumps(['write_timestamp'], - @dumpfiles{'somebox_lib_20080222222222','somebox_lib_20080111'}) ], - [ @dumpfiles{'somebox_lib_20080111','somebox_lib_20080222222222'} ], - "sort by write_timestamps"); -is_deeply([ Amanda::DB::Catalog::sort_dumps(['-write_timestamp'], - @dumpfiles{'somebox_lib_20080111','somebox_lib_20080222222222'}) ], - [ @dumpfiles{'somebox_lib_20080222222222','somebox_lib_20080111'} ], - "sort by write_timestamps, reverse"); - -is_deeply([ Amanda::DB::Catalog::sort_dumps(['hostname', '-diskname', 'write_timestamp'], - @dumpfiles{ +got_dumps([ sortdumps Amanda::DB::Catalog::get_dumps(status => "FAIL") ], + [ sortdumps dumps_matching { $_->{'status'} eq "FAIL" } ], + "get_dumps parameter status = FAIL"); + +@dumpspecs = Amanda::Cmdline::parse_dumpspecs([".*", "/lib"], 0); +got_dumps([ sortdumps Amanda::DB::Catalog::get_dumps(dumpspecs => [ @dumpspecs ]) ], + [ sortdumps dumps_named qr/_lib_/ ], + "get_dumps parameter dumpspecs with one dumpspec"); + +@dumpspecs = Amanda::Cmdline::parse_dumpspecs([".*", "/lib"], 0); +got_dumps([ sortdumps Amanda::DB::Catalog::get_dumps(dumpspecs => [ @dumpspecs ], holding => 1) ], + [ sortdumps dumps_named qr/_lib_.*_holding/ ], + "get_dumps parameter dumpspecs with one dumpspec"); + +@dumpspecs = Amanda::Cmdline::parse_dumpspecs([".*", "/lib", "somebox"], 0); +got_dumps([ sortdumps Amanda::DB::Catalog::get_dumps(dumpspecs => [ @dumpspecs ]) ], + [ sortdumps dumps_matching { $_->{'diskname'} eq '/lib' + or $_->{'hostname'} eq 'somebox' } ], + "get_dumps parameter dumpspecs with two dumpspecs"); + +@dumpspecs = Amanda::Cmdline::parse_dumpspecs(["otherbox", "*", "somebox"], 0); +got_dumps([ sortdumps Amanda::DB::Catalog::get_dumps(dumpspecs => [ @dumpspecs ]) ], + [ sortdumps dumps_matching { $_->{'hostname'} eq 'otherbox' + or $_->{'hostname'} eq 'somebox' } ], + "get_dumps parameter dumpspecs with two non-overlapping dumpspecs"); + +@dumpspecs = Amanda::Cmdline::parse_dumpspecs(["does-not-exist"], 0); +got_dumps([ sortdumps Amanda::DB::Catalog::get_dumps(dumpspecs => [ @dumpspecs ]) ], + [ ], + "get_dumps parameter dumpspecs with a dumpspec that matches nothing", + zero_dumps_expected => 1); + +## test dump sorting + +got_dumps([ Amanda::DB::Catalog::sort_dumps(['write_timestamp'], + @dumps{'somebox_lib_20080222222222','somebox_lib_20080111'}) ], + [ @dumps{'somebox_lib_20080111','somebox_lib_20080222222222'} ], + "sort dumps by write_timestamps"); +got_dumps([ Amanda::DB::Catalog::sort_dumps(['-write_timestamp'], + @dumps{'somebox_lib_20080111','somebox_lib_20080222222222'}) ], + [ @dumps{'somebox_lib_20080222222222','somebox_lib_20080111'} ], + "sort dumps by write_timestamps, reverse"); + +got_dumps([ Amanda::DB::Catalog::sort_dumps(['hostname', '-diskname', 'write_timestamp'], + @dumps{ 'somebox_lib_20080222222222', 'somebox_usr_bin_20080313133333', - 'somebox_lib_20080313133333_p4', + 'somebox_lib_20080313133333', 'otherbox_lib_20080313133333', 'somebox_lib_20080111', }) ], - [ @dumpfiles{ + [ @dumps{ 'otherbox_lib_20080313133333', 'somebox_usr_bin_20080313133333', 'somebox_lib_20080111', 'somebox_lib_20080222222222', - 'somebox_lib_20080313133333_p4', + 'somebox_lib_20080313133333', } ], - "multi-key sort"); + "multi-key dump sort"); -## add log entries - -# one to an existing logfile, same tape -Amanda::DB::Catalog::add_dump({ - 'write_timestamp' => '20080111', - 'dump_timestamp' => '20080707070707', - 'hostname' => 'newbox', - 'diskname' => '/newdisk', - 'level' => 3, - 'label' => 'Conf-001', - 'filenum' => 2, - 'partnum' => 1, - 'nparts' => 1, - 'status' => 'OK', - 'sec' => 13.0, - 'kb' => 12380, -}); - -is_deeply([ sortdumps Amanda::DB::Catalog::get_dumps(hostname => 'newbox') ], - [ sortdumps { - 'write_timestamp' => '20080111000000', - 'dump_timestamp' => '20080707070707', - 'hostname' => 'newbox', - 'diskname' => '/newdisk', - 'level' => 3, - 'label' => 'Conf-001', - 'filenum' => 2, - 'partnum' => 1, - 'nparts' => 1, - 'status' => 'OK', - 'sec' => 13.0, - 'kb' => 12380, - } ], - "successfully re-read an added dump in an existing logfile"); - -# and again, to test the last-logfile cache in Amanda::DB::Catalog -Amanda::DB::Catalog::add_dump({ - 'write_timestamp' => '20080111', - 'dump_timestamp' => '20080707070707', - 'hostname' => 'newbox', - 'diskname' => '/newdisk2', - 'level' => 0, - 'label' => 'Conf-001', - 'filenum' => 3, - 'partnum' => 1, - 'nparts' => 1, - 'status' => 'OK', - 'sec' => 27.0, - 'kb' => 32380, -}); - -is(scalar Amanda::DB::Catalog::get_dumps(hostname => 'newbox'), 2, - "adding another dump to that logfile and re-reading gives 2 dumps"); - -# and another in a new file, as well as a tapelist entry -Amanda::DB::Catalog::add_dump({ - 'write_timestamp' => '20080707070707', - 'dump_timestamp' => '20080707070707', - 'hostname' => 'newlog', - 'diskname' => '/newdisk', - 'level' => 3, - 'label' => 'Conf-009', - 'filenum' => 1, - 'partnum' => 1, - 'nparts' => 1, - 'status' => 'OK', - 'sec' => 13.0, - 'kb' => 12380, -}); - -is_deeply([ sortdumps Amanda::DB::Catalog::get_dumps(hostname => 'newlog') ], - [ sortdumps { - 'write_timestamp' => '20080707070707', - 'dump_timestamp' => '20080707070707', - 'hostname' => 'newlog', - 'diskname' => '/newdisk', - 'level' => 3, - 'label' => 'Conf-009', - 'filenum' => 1, - 'partnum' => 1, - 'nparts' => 1, - 'status' => 'OK', - 'sec' => 13.0, - 'kb' => 12380, - } ], - "successfully re-read an added dump in a new logfile"); - -# and add a multipart dump to that same logfile -for (my $i = 1; $i <= 5; $i++) { - Amanda::DB::Catalog::add_dump({ - 'write_timestamp' => '20080707070707', - 'dump_timestamp' => '20080707070707', - 'hostname' => 'newlog', - 'diskname' => '/bigdisk', - 'level' => 1, - 'label' => 'Conf-009', - 'filenum' => $i+1, - 'partnum' => $i, - 'nparts' => 5, - 'status' => 'OK', - 'sec' => 13.0, - 'kb' => 12380, - }); -} - -is(scalar Amanda::DB::Catalog::get_dumps(diskname => '/bigdisk'), 5, - "multi-part dump added and re-read successfully"); +got_dumps([ Amanda::DB::Catalog::sort_dumps(['nparts'], + @dumps{ + 'somebox_lib_20080313133333', # nparts=10 + 'somebox_lib_20080222222222', # nparts=2 + }) ], + [ @dumps{ + 'somebox_lib_20080222222222', # nparts=2 + 'somebox_lib_20080313133333', # nparts=10 + } ], + "dumps' nparts is sorted numerically, not lexically"); + +got_dumps([ Amanda::DB::Catalog::sort_dumps(['-level'], + @dumps{ + 'somebox_lib_20080313133333', # level=0 + 'somebox_usr_bin_20080313133333', # level=1 + }) ], + [ @dumps{ + 'somebox_usr_bin_20080313133333', # level=1 + 'somebox_lib_20080313133333', # level=0 + } ], + "sort dumps by level, reversed"); + +got_dumps([ Amanda::DB::Catalog::sort_dumps(['dump_timestamp'], + @dumps{ + 'somebox_lib_20080313133333', # dts=20080313133333 + 'otherbox_usr_bin_20080313133333', # dts=20080311131133 + }) ], + [ @dumps{ + 'otherbox_usr_bin_20080313133333', # dts=20080311131133 + 'somebox_lib_20080313133333', # dts=20080313133333 + } ], + "sort dumps by write_timestamp"); __DATA__ # a short-datestamp logfile with only a single, single-part file in it @@ -375,7 +793,8 @@ START taper datestamp 20080111 label Conf-001 tape 1 SUCCESS dumper somebox /lib 20080111 0 [sec 0.209 kb 1970 kps 9382.2 orig-kb 1970] SUCCESS chunker somebox /lib 20080111 0 [sec 0.305 kb 420 kps 1478.7] STATS driver estimate somebox /lib 20080111 0 [sec 1 nkb 2002 ckb 480 kps 385] -:dumpfile somebox_lib_20080111 20080111000000 somebox /lib 0 Conf-001 1 1 1 OK 4.813543 419 +:dump somebox_lib_20080111 20080111000000 somebox /lib 0 OK "" 1 4.813543 419 +:part somebox_lib_20080111 somebox_lib_20080111 Conf-001 1 1 OK 4.813543 419 PART taper Conf-001 1 somebox /lib 20080111 1/1 0 [sec 4.813543 kb 419 kps 87.133307] DONE taper somebox /lib 20080111 1 0 [sec 4.813543 kb 419 kps 87.133307] FINISH driver date 20080111 time 2167.581 @@ -394,9 +813,12 @@ SUCCESS dumper somebox /lib 20080222222222 0 [sec 0.012 kb 100 kps 8115.6 orig-k SUCCESS chunker somebox /lib 20080222222222 0 [sec 5.075 kb 100 kps 26.0] STATS driver estimate somebox /lib 20080222222222 0 [sec 0 nkb 132 ckb 160 kps 1024] START taper datestamp 20080222222222 label Conf-002 tape 1 -:dumpfile somebox_lib_20080222222222 20080222222222 somebox /lib 0 Conf-002 1 1 1 OK 0.000733 100 -PART taper Conf-002 1 somebox /lib 20080222222222 1/1 0 [sec 0.000733 kb 100 kps 136425.648022] -DONE taper somebox /lib 20080222222222 1 0 [sec 0.000733 kb 100 kps 136425.648022] +:dump somebox_lib_20080222222222 20080222222222 somebox /lib 0 OK "" 2 0.001161 172 +:part somebox_lib_20080222222222_p1 somebox_lib_20080222222222 Conf-002 1 1 OK 0.000733 100 +PART taper Conf-002 1 somebox /lib 20080222222222 1/2 0 [sec 0.000733 kb 100 kps 136425.648022] +:part somebox_lib_20080222222222_p2 somebox_lib_20080222222222 Conf-002 2 2 OK 0.000428 72 +PART taper Conf-002 2 somebox /lib 20080222222222 2/2 0 [sec 0.000428 kb 72 kps 136425.648022] +DONE taper somebox /lib 20080222222222 2 0 [sec 0.001161 kb 172 kps 136425.648022] FINISH driver date 20080222222222 time 6.206 # a logfile with several dumps in it, one of which comes in many parts, and one of which is @@ -418,30 +840,47 @@ SUCCESS dumper somebox /usr/bin 20080313133333 1 [sec 0.001 kb 20 kps 10352.0 or SUCCESS chunker somebox /usr/bin 20080313133333 1 [sec 1.023 kb 20 kps 50.8] STATS driver estimate somebox /usr/bin 20080313133333 1 [sec 0 nkb 52 ckb 64 kps 1024] START taper datestamp 20080313133333 label Conf-003 tape 1 -:dumpfile somebox_usr_bin_20080313133333 20080313133333 somebox /usr/bin 1 Conf-003 1 1 1 OK 0.000370 20 +:dump somebox_usr_bin_20080313133333 20080313133333 somebox /usr/bin 1 OK "" 1 0.000370 20 +:part somebox_usr_bin_20080313133333 somebox_usr_bin_20080313133333 Conf-003 1 1 OK 0.000370 20 PART taper Conf-003 1 somebox /usr/bin 20080313133333 1/1 1 [sec 0.000370 kb 20 kps 54054.054054] DONE taper somebox /usr/bin 20080313133333 1 1 [sec 0.000370 kb 20 kps 54054.054054] # a multi-part dump SUCCESS dumper somebox /lib 20080313133333 0 [sec 0.189 kb 3156 kps 50253.1 orig-kb 3156] SUCCESS chunker somebox /lib 20080313133333 0 [sec 5.250 kb 3156 kps 1815.5] STATS driver estimate somebox /lib 20080313133333 0 [sec 1 nkb 3156 ckb 3156 kps 9500] -:dumpfile somebox_lib_20080313133333_p1 20080313133333 somebox /lib 0 Conf-003 2 1 4 OK 0.005621 1024 -PART taper Conf-003 2 somebox /lib 20080313133333 1/4 0 [sec 0.005621 kb 1024 kps 182173.990393] -:dumpfile somebox_lib_20080313133333_p2 20080313133333 somebox /lib 0 Conf-003 3 2 4 OK 0.006527 1024 -PART taper Conf-003 3 somebox /lib 20080313133333 2/4 0 [sec 0.006527 kb 1024 kps 156886.777999] -:dumpfile somebox_lib_20080313133333_p3 20080313133333 somebox /lib 0 Conf-003 4 3 4 OK 0.005854 1024 -PART taper Conf-003 4 somebox /lib 20080313133333 3/4 0 [sec 0.005854 kb 1024 kps 174923.129484] -:dumpfile somebox_lib_20080313133333_p4 20080313133333 somebox /lib 0 Conf-003 5 4 4 OK 0.001919 284 -PART taper Conf-003 5 somebox /lib 20080313133333 4/4 0 [sec 0.001919 kb 284 kps 147993.746743] +:dump somebox_lib_20080313133333 20080313133333 somebox /lib 0 OK "" 10 0.051436 3156 +:part somebox_lib_20080313133333_p1 somebox_lib_20080313133333 Conf-003 2 1 OK 0.005621 1024 +PART taper Conf-003 2 somebox /lib 20080313133333 1/10 0 [sec 0.005621 kb 1024 kps 182173.990393] +:part somebox_lib_20080313133333_p2 somebox_lib_20080313133333 Conf-003 3 2 OK 0.006527 1024 +PART taper Conf-003 3 somebox /lib 20080313133333 2/10 0 [sec 0.006527 kb 1024 kps 156886.777999] +:part somebox_lib_20080313133333_p3 somebox_lib_20080313133333 Conf-003 4 3 OK 0.005854 1024 +PART taper Conf-003 4 somebox /lib 20080313133333 3/10 0 [sec 0.005854 kb 1024 kps 174923.129484] +:part somebox_lib_20080313133333_p4 somebox_lib_20080313133333 Conf-003 5 4 OK 0.007344 1024 +PART taper Conf-003 5 somebox /lib 20080313133333 4/10 0 [sec 0.007344 kb 1024 kps 147993.746743] +:part somebox_lib_20080313133333_p5 somebox_lib_20080313133333 Conf-003 6 5 OK 0.007344 1024 +PART taper Conf-003 6 somebox /lib 20080313133333 5/10 0 [sec 0.007344 kb 1024 kps 147993.746743] +:part somebox_lib_20080313133333_p6 somebox_lib_20080313133333 Conf-003 7 6 OK 0.007344 1024 +PART taper Conf-003 7 somebox /lib 20080313133333 6/10 0 [sec 0.007344 kb 1024 kps 147993.746743] +:part somebox_lib_20080313133333_p7 somebox_lib_20080313133333 Conf-003 8 7 OK 0.007344 1024 +PART taper Conf-003 8 somebox /lib 20080313133333 7/10 0 [sec 0.007344 kb 1024 kps 147993.746743] +:part somebox_lib_20080313133333_p8 somebox_lib_20080313133333 Conf-003 9 8 OK 0.007344 1024 +PART taper Conf-003 9 somebox /lib 20080313133333 8/10 0 [sec 0.007344 kb 1024 kps 147993.746743] +:part somebox_lib_20080313133333_p9 somebox_lib_20080313133333 Conf-003 10 9 OK 0.007344 1024 +PART taper Conf-003 10 somebox /lib 20080313133333 9/10 0 [sec 0.007344 kb 1024 kps 147993.746743] +:part somebox_lib_20080313133333_p10 somebox_lib_20080313133333 Conf-003 11 10 OK 0.001919 284 +PART taper Conf-003 11 somebox /lib 20080313133333 10/10 0 [sec 0.001919 kb 284 kps 147993.746743] DONE taper somebox /lib 20080313133333 10 0 [sec 0.051436 kb 3156 kps 184695.543977] SUCCESS dumper otherbox /lib 20080313133333 0 [sec 0.001 kb 190 kps 10352.0 orig-kb 20] SUCCESS chunker otherbox /lib 20080313133333 0 [sec 1.023 kb 190 kps 50.8] STATS driver estimate otherbox /lib 20080313133333 0 [sec 0 nkb 190 ckb 190 kps 1024] # this dump is from a previous run, with an older dump_timestamp -:dumpfile otherbox_usr_bin_20080313133333 20080311131133 otherbox /usr/bin 0 Conf-003 6 1 1 OK 0.002733 240 -PART taper Conf-003 6 otherbox /usr/bin 20080311131133 1/1 0 [sec 0.002733 kb 240 kps 136425.648022] -:dumpfile otherbox_lib_20080313133333 20080313133333 otherbox /lib 0 Conf-003 7 1 1 OK 0.001733 190 -PART taper Conf-003 7 otherbox /lib 20080313133333 1/1 0 [sec 0.001733 kb 190 kps 136425.648022] +:dump otherbox_usr_bin_20080313133333 20080311131133 otherbox /usr/bin 0 OK "" 1 0.002733 240 +:part otherbox_usr_bin_20080313133333 otherbox_usr_bin_20080313133333 Conf-003 12 1 OK 0.002733 240 +PART taper Conf-003 12 otherbox /usr/bin 20080311131133 1/1 0 [sec 0.002733 kb 240 kps 136425.648022] +DONE taper otherbox /usr/bin 20080311131133 1 0 [sec 0.002733 kb 240 kps 136425.648022] +:dump otherbox_lib_20080313133333 20080313133333 otherbox /lib 0 OK "" 1 0.001733 190 +:part otherbox_lib_20080313133333 otherbox_lib_20080313133333 Conf-003 13 1 OK 0.001733 190 +PART taper Conf-003 13 otherbox /lib 20080313133333 1/1 0 [sec 0.001733 kb 190 kps 136425.648022] DONE taper otherbox /lib 20080313133333 1 0 [sec 0.001733 kb 190 kps 136425.648022] FINISH driver date 20080313133333 time 24.777 @@ -461,14 +900,124 @@ SUCCESS dumper otherbox /lib 20080414144444 1 [sec 0.003 kb 60 kps 16304.3 orig- SUCCESS chunker otherbox /lib 20080414144444 1 [sec 1.038 kb 60 kps 88.5] STATS driver estimate otherbox /lib 20080414144444 1 [sec 0 nkb 92 ckb 96 kps 1024] START taper datestamp 20080414144444 label Conf-004 tape 1 -:dumpfile otherbox_lib_20080414144444_try1 20080414144444 otherbox /lib 1 Conf-004 1 1 1 PARTIAL 0.000707 32 +:dump otherbox_lib_20080414144444 20080414144444 otherbox /lib 1 PARTIAL full-up 0 0.000540 32 +:part otherbox_lib_20080414144444_try1 otherbox_lib_20080414144444 Conf-004 1 1 PARTIAL 0.000707 32 PARTPARTIAL taper Conf-004 1 otherbox /lib 20080414144444 1/1 1 [sec 0.000707 kb 32 kps 45261.669024] "" INFO taper Will request retry of failed split part. INFO taper Will write new label `Conf-005' to new (previously non-amanda) tape START taper datestamp 20080414144444 label Conf-005 tape 2 -:dumpfile otherbox_lib_20080414144444_try2 20080414144444 otherbox /lib 1 Conf-005 1 1 1 PARTIAL 0.000540 32 +:part otherbox_lib_20080414144444_try2 otherbox_lib_20080414144444 Conf-005 1 1 PARTIAL 0.000540 32 PARTPARTIAL taper Conf-005 1 otherbox /lib 20080414144444 1/1 1 [sec 0.000540 kb 32 kps 59259.259259] "" INFO taper Will request retry of failed split part. WARNING driver Out of tapes; going into degraded mode. -PARTIAL taper otherbox /lib 20080414144444 1 1 [sec 0.000540 kb 32 kps 59259.259259] "" +PARTIAL taper otherbox /lib 20080414144444 1 1 [sec 0.000540 kb 32 kps 59259.259259] "full-up" +# a completely failed dump +:dump otherbox_boot_20080414144444 20080414144444 otherbox /boot 0 FAIL no-space 0 0.0 0 +FAIL taper otherbox /boot 20080414144444 0 "no-space" FINISH driver date 20080414144444 time 6.959 + +# holding-disk +:holding otherbox_lib_20080414144444_holding 20080414144444 otherbox /lib 1 OK 256 +:holding oldbox_opt_20080414144444_holding 20080414144444 oldbox /opt 0 OK 1298 + +# A logfile with orig-kb in taper line +::: log.20080515155555.0 +:tapelist 20080515155555 Conf-006 +:timestamp 20080515155555 +DISK planner somebox /usr/bin +DISK planner somebox /lib +DISK planner otherbox /lib +DISK planner otherbox /usr/bin +START planner date 20080515155555 +START driver date 20080515155555 +STATS driver hostname somebox +STATS driver startup time 0.059 +INFO planner Full dump of somebox:/lib promoted from 2 days ahead. +FINISH planner date 20080515155555 time 0.286 +SUCCESS dumper somebox /usr/bin 20080515155555 1 [sec 0.001 kb 20 kps 10352.0 orig-kb 20] +SUCCESS chunker somebox /usr/bin 20080515155555 1 [sec 1.023 kb 20 kps 50.8] +STATS driver estimate somebox /usr/bin 20080515155555 1 [sec 0 nkb 52 ckb 64 kps 1024] +START taper datestamp 20080515155555 label Conf-006 tape 1 +:dump somebox_usr_bin_20080515155555 20080515155555 somebox /usr/bin 1 OK "" 1 0.000370 20 20 +:part somebox_usr_bin_20080515155555 somebox_usr_bin_20080515155555 Conf-006 1 1 OK 0.000370 20 20 +PART taper Conf-006 1 somebox /usr/bin 20080515155555 1/1 1 [sec 0.000370 kb 20 kps 54054.054054 orig-kb 20] +DONE taper somebox /usr/bin 20080515155555 1 1 [sec 0.000370 kb 20 kps 54054.054054 orig-kb 20] +# a multi-part dump +SUCCESS dumper somebox /lib 20080515155555 0 [sec 0.189 kb 3156 kps 50253.1 orig-kb 3156] +SUCCESS chunker somebox /lib 20080515155555 0 [sec 5.250 kb 3156 kps 1815.5] +STATS driver estimate somebox /lib 20080515155555 0 [sec 1 nkb 3156 ckb 3156 kps 9500] +:dump somebox_lib_20080515155555 20080515155555 somebox /lib 0 OK "" 10 0.051436 3156 3156 +:part somebox_lib_20080515155555_p1 somebox_lib_20080515155555 Conf-006 2 1 OK 0.005621 1024 3156 +PART taper Conf-006 2 somebox /lib 20080515155555 1/10 0 [sec 0.005621 kb 1024 kps 182173.990393 orig-kb 3156] +:part somebox_lib_20080515155555_p2 somebox_lib_20080515155555 Conf-006 3 2 OK 0.006527 1024 3156 +PART taper Conf-006 3 somebox /lib 20080515155555 2/10 0 [sec 0.006527 kb 1024 kps 156886.777999 orig-kb 3156] +:part somebox_lib_20080515155555_p3 somebox_lib_20080515155555 Conf-006 4 3 OK 0.005854 1024 3156 +PART taper Conf-006 4 somebox /lib 20080515155555 3/10 0 [sec 0.005854 kb 1024 kps 174923.129484 orig-kb 3156] +:part somebox_lib_20080515155555_p4 somebox_lib_20080515155555 Conf-006 5 4 OK 0.007344 1024 3156 +PART taper Conf-006 5 somebox /lib 20080515155555 4/10 0 [sec 0.007344 kb 1024 kps 147993.746743 orig-kb 3156] +:part somebox_lib_20080515155555_p5 somebox_lib_20080515155555 Conf-006 6 5 OK 0.007344 1024 3156 +PART taper Conf-006 6 somebox /lib 20080515155555 5/10 0 [sec 0.007344 kb 1024 kps 147993.746743 orig-kb 3156] +:part somebox_lib_20080515155555_p6 somebox_lib_20080515155555 Conf-006 7 6 OK 0.007344 1024 3156 +PART taper Conf-006 7 somebox /lib 20080515155555 6/10 0 [sec 0.007344 kb 1024 kps 147993.746743 orig-kb 3156] +:part somebox_lib_20080515155555_p7 somebox_lib_20080515155555 Conf-006 8 7 OK 0.007344 1024 3156 +PART taper Conf-006 8 somebox /lib 20080515155555 7/10 0 [sec 0.007344 kb 1024 kps 147993.746743 orig-kb 3156] +:part somebox_lib_20080515155555_p8 somebox_lib_20080515155555 Conf-006 9 8 OK 0.007344 1024 3156 +PART taper Conf-006 9 somebox /lib 20080515155555 8/10 0 [sec 0.007344 kb 1024 kps 147993.746743 orig-kb 3156] +:part somebox_lib_20080515155555_p9 somebox_lib_20080515155555 Conf-006 10 9 OK 0.007344 1024 3156 +PART taper Conf-006 10 somebox /lib 20080515155555 9/10 0 [sec 0.007344 kb 1024 kps 147993.746743 orig-kb 3156] +:part somebox_lib_20080515155555_p10 somebox_lib_20080515155555 Conf-006 11 10 OK 0.001919 284 3156 +PART taper Conf-006 11 somebox /lib 20080515155555 10/10 0 [sec 0.001919 kb 284 kps 147993.746743 orig-kb 3156] +DONE taper somebox /lib 20080515155555 10 0 [sec 0.051436 kb 3156 kps 184695.543977 orig-kb 3156] +SUCCESS dumper otherbox /lib 20080515155555 0 [sec 0.001 kb 190 kps 10352.0 orig-kb 20] +SUCCESS chunker otherbox /lib 20080515155555 0 [sec 1.023 kb 190 kps 50.8] +STATS driver estimate otherbox /lib 20080515155555 0 [sec 0 nkb 190 ckb 190 kps 1024] +# this dump is from a previous run, with an older dump_timestamp +:dump otherbox_usr_bin_20080515155555 20080511151155 otherbox /usr/bin 0 OK "" 1 0.002733 240 240 +:part otherbox_usr_bin_20080515155555 otherbox_usr_bin_20080515155555 Conf-006 12 1 OK 0.002733 240 240 +PART taper Conf-006 12 otherbox /usr/bin 20080511151155 1/1 0 [sec 0.002733 kb 240 kps 136425.648022 orig-kb 240] +DONE taper otherbox /usr/bin 20080511151155 1 0 [sec 0.002733 kb 240 kps 136425.648022 orig-kb 240] +:dump otherbox_lib_20080515155555 20080511151555 otherbox /lib 0 OK "" 1 0.001733 190 190 +:part otherbox_lib_20080515155555 otherbox_lib_20080515155555 Conf-006 13 1 OK 0.001733 190 190 +PART taper Conf-006 13 otherbox /lib 20080511151555 1/1 0 [sec 0.001733 kb 190 kps 136425.648022 orig-kb 190] +DONE taper otherbox /lib 20080515155555 1 0 [sec 0.001733 kb 190 kps 136425.648022 orig-kb 190] +# this dump is a direct to tape +:dump otherbox_direct_20080515155555 20080515155555 otherbox /direct 0 OK "" 1 0.001 190 350 +:part otherbox_direct_20080515155555 otherbox_direct_20080515155555 Conf-006 14 1 OK 0.001 190 350 +SUCCESS dumper otherbox /direct 20080515155555 0 [sec 0.001 kb 190 kps 10352.0 orig-kb 350] +PART taper Conf-006 14 otherbox /direct 20080515155555 1/1 0 [sec 0.001 kb 190 kps 10352.0] +DONE taper otherbox /direct 20080515155555 1 0 [sec 0.001 kb 190 kps 10352.0 orig-kb 350] +FINISH driver date 20080515155555 time 24.777 + +# A logfile with removed tape-kb in taper line +::: log.20080616166666.0 +:tapelist 20080616166666 Conf-007 +# this tape is removed +#:tapelist 20080616166666 Conf-007 +:timestamp 20080616166666 +DISK planner somebox /usr/bin +DISK planner somebox /lib +DISK planner otherbox /lib +START planner date 20080616166666 +START driver date 20080616166666 +STATS driver hostname somebox +STATS driver startup time 0.059 +FINISH planner date 20080616166666 time 0.286 +SUCCESS dumper somebox /usr/bin 20080616166666 1 [sec 0.001 kb 20 kps 10352.0 orig-kb 20] +SUCCESS chunker somebox /usr/bin 20080616166666 1 [sec 1.023 kb 20 kps 50.8] +STATS driver estimate somebox /usr/bin 20080616166666 1 [sec 0 nkb 52 ckb 64 kps 1024] +START taper datestamp 20080616166666 label Conf-007 tape 1 +:dump somebox_usr_bin_20080616166666 20080616166666 somebox /usr/bin 1 OK "" 1 0.000370 20 20 +:part somebox_usr_bin_20080616166666 somebox_usr_bin_20080616166666 Conf-007 1 1 OK 0.000370 20 20 +PART taper Conf-007 1 somebox /usr/bin 20080616166666 1/1 1 [sec 0.000370 kb 20 kps 54054.054054 orig-kb 20] +DONE taper somebox /usr/bin 20080616166666 1 1 [sec 0.000370 kb 20 kps 54054.054054 orig-kb 20] +SUCCESS dumper somebox /lib 20080616166666 1 [sec 0.001 kb 20 kps 10352.0 orig-kb 20] +SUCCESS chunker somebox /lib 20080616166666 1 [sec 1.023 kb 20 kps 50.8] +:dump somebox_lib_20080616166666 20080616166666 somebox /lib 1 FAIL "" 1 0.000370 20 20 +:part somebox_lib_20080616166666 somebox_lib_20080616166666 Conf-007 2 1 OK 0.000370 20 20 +PART taper Conf-007 2 somebox /lib 20080616166666 1/2 1 [sec 0.000370 kb 20 kps 54054.054054 orig-kb 20] +STATS driver estimate somebox /lib 20080616166666 1 [sec 0 nkb 52 ckb 64 kps 1024] +START taper datestamp 20080616166666 label Conf-008 tape 1 +# this tape is removed +#:part somebox_lib_20080616166666 somebox_lib_20080616166666 Conf-008 1 1 OK 0.000370 20 20 +PART taper Conf-008 1 somebox /lib 20080616166666 2/2 1 [sec 0.000370 kb 20 kps 54054.054054 orig-kb 20] +DONE taper somebox /lib 20080616166666 1 1 [sec 0.000370 kb 20 kps 54054.054054 orig-kb 20]