File Coverage

blib/lib/App/Rsnapshot/Rotate.pm
Criterion Covered Total %
statement 33 33 100.0
branch 10 10 100.0
condition n/a
subroutine 5 5 100.0
pod 1 1 100.0
total 49 49 100.0


line stmt bran cond sub pod time code
1             package App::Rsnapshot::Rotate;
2              
3 2     2   62497 use strict;
  2         7  
  2         77  
4 2     2   11 use warnings;
  2         4  
  2         60  
5 2     2   2411 use Data::Dumper;
  2         21908  
  2         156  
6              
7 2     2   20 use vars qw($VERSION);
  2         3  
  2         1425  
8              
9             $VERSION = '1.0';
10              
11             =head1 NAME
12              
13             App::Rsnapshot::Rotate - rotate snapshots
14              
15             =head1 SYNOPSIS
16              
17             # rotate the 'alpha' interval
18             App::Rsnapshot::Rotate::go(config => $config, interval => 'alpha');
19              
20             =head1 DESCRIPTION
21              
22             Rotates the named interval in your backups
23              
24             =head1 SUBROUTINES
25              
26             =head2 go
27              
28             Takes two named parameters, C and C, being the name
29             of the interval you want to rotate.
30              
31             If the named interval is the first interval, then every foo.$number
32             directory is renamed to foo.$number+1 except the highest numbered,
33             which is renamde to _delete.$$ where $$ is the process ID, and foo.0
34             which is left alone.
35              
36             If the named interval is *not* the first interval then it only rotates
37             if previous.last exists. In that case, every foo.$number directory is
38             renamed to foo.$number+1 except the highest numbered, which is renamde
39             to _delete.$$, and previous.last is moved to foo.0.
40              
41             =cut
42              
43             sub go {
44 11     11 1 118233 my($c, $interval) = map { {@_}->{$_} } (qw(config interval));
  22         135  
45 11         100 my @intervals = $c->intervals->interval('*');
46 11         26 my $interval0 = $intervals[0];
47 11         55 my $i = $c->intervals->interval($interval);
48 11         46 my $s = $c->snapshotroot();
49             # print Dumper(\@intervals, $interval0, $interval);
50             # print $c->snapshotroot;
51            
52 11 100       189 if($i->name() eq $interval0->name()) { # first interval ...
53             # schedule oldest for deletion
54 4 100       17 rename "$s/".$i->name().'.'.($i->retain() - 1),
55             "$s/_delete.$$"
56             if(-d "$s/".$i->name().'.'.($i->retain() - 1));
57             # now rotate the middle, oldest first
58 4         27 foreach my $number (grep {
  16         58  
59             -d "$s/".$i->name().".$_"
60             } reverse(1 .. $i->retain() - 2)) {
61 7         24 rename "$s/".$i->name().".$number",
62             "$s/".$i->name().'.'.($number + 1)
63             }
64             } else { # this isn't the first interval ...
65             # find previous interval
66 7         9 my $previous = '';
67 7         15 foreach (@intervals) {
68 21 100       87 last if($_->name() eq $i->name());
69 14         30 $previous = $_;
70             }
71             # if previous.last exists ...
72 7 100       41 if(-d "$s/".$previous->name().'.'.($previous->retain() - 1)) {
73             # schedule oldest for deletion
74 4 100       13 rename "$s/".$i->name().'.'.($i->retain() - 1),
75             "$s/_delete.$$"
76             if(-d "$s/".$i->name().'.'.($i->retain() - 1));
77             # rotate what's already there ...
78 4         24 foreach my $number (grep {
  12         37  
79             -d "$s/".$i->name().".$_"
80             } reverse(0 .. $i->retain() - 2)) {
81 6         21 rename "$s/".$i->name().".$number",
82             "$s/".$i->name().'.'.($number + 1)
83             }
84             # move previous.last to this.0
85 4         19 rename "$s/".$previous->name().'.'.($previous->retain() - 1),
86             "$s/".$i->name().".0";
87             }
88             }
89             }
90              
91             =head1 BUGS/WARNINGS/LIMITATIONS
92              
93             None known.
94              
95             =head1 SOURCE CODE REPOSITORY
96              
97             L
98              
99             =head1 AUTHOR, COPYRIGHT and LICENCE
100              
101             Copyright 2009 David Cantrell
102              
103             This software is free-as-in-speech software, and may be used,
104             distributed, and modified under the terms of either the GNU
105             General Public Licence version 2 or the Artistic Licence. It's
106             up to you which one you use. The full text of the licences can
107             be found in the files GPL2.txt and ARTISTIC.txt, respectively.
108              
109             =head1 CONSPIRACY
110              
111             This module is also free-as-in-mason software.
112              
113             =cut
114              
115             1;