File Coverage

blib/lib/Backup/Hanoi.pm
Criterion Covered Total %
statement 35 35 100.0
branch 12 14 85.7
condition n/a
subroutine 6 6 100.0
pod 2 2 100.0
total 55 57 96.4


line stmt bran cond sub pod time code
1             package Backup::Hanoi;
2             # ABSTRACT: select backup according to algo
3             $Backup::Hanoi::VERSION = '0.005';
4 2     2   271572 use strict;
  2         20  
  2         85  
5 2     2   18 use warnings;
  2         9  
  2         82  
6              
7 2     2   49 use v5.6.0;
  2         12  
8              
9             sub new {
10 6     6 1 1190 my $class = shift;
11 6         16 my $devices = shift;
12 6 50       20 $devices = [] unless ($devices); # // operator needs v5.10
13              
14             # the number of devices predicts the size of the cycles
15 6         12 my $device_count = scalar @{$devices};
  6         14  
16              
17 6 100       30 die "three devices needed.\n" if ($device_count < 3);
18              
19             # half a hanoi cycle is just what we need for backup
20 5         20 my $hanoi_cycles_half = (2**$device_count) / 2;
21              
22 5         22 my $self = { devices => $devices,
23             hanoi_cycles_half => $hanoi_cycles_half,
24             };
25              
26 5         13 bless $self, $class;
27              
28 5         23 return $self;
29             }
30              
31             sub get_device_for_cycle {
32              
33 91     91 1 243 my $self = shift;
34 91         143 my $cycle = shift;
35              
36 91 100       243 $cycle = 0 unless ($cycle); # // operator needs v5.10
37              
38             # treat negative numbers as normal FIFO
39             # e.g. index -1 gives the second last element
40             return $self->{devices}
41 91 100       223 ->[(scalar @{$self->{devices}}) + $cycle -1]
  3         22  
42             if ($cycle < 0);
43              
44             # allow cycle to cross hanoi limit, map it to first half
45 88         196 my $modulo_cycle = $cycle % $self->{hanoi_cycles_half};
46              
47             # change zero to maximum, so that zero gets highest device
48             $modulo_cycle = $self->{hanoi_cycles_half}
49 88 100       233 if ($modulo_cycle == 0);
50              
51             # calculate which device is used for given cycle
52 88         186 my $hanoi_number =
53             _get_right_zeros_from_digital_representation(
54             $modulo_cycle);
55              
56             # select and return device
57 88         504 return $self->{devices}->[$hanoi_number];
58              
59             }
60              
61             sub _get_right_zeros_from_digital_representation {
62              
63 88     88   152 my $number = shift;
64              
65             # convert to binary format: e.g. number 5 -> 101
66 88         376 my $binary = sprintf "%b", $number;
67              
68             # represent number zero as empty string
69 88 50       276 $binary = '' if ($binary == 0);
70              
71              
72             # count the zeros, at the right from the binary number
73              
74 88         139 my $zeros_from_the_right = 0;
75              
76 88 100       492 if ( $binary =~ /(0+)$/ ) {
77 48         138 my $zero_capture = $1;
78              
79 48         90 $zeros_from_the_right = length $zero_capture;
80             }
81              
82 88         182 return $zeros_from_the_right;
83             }
84              
85             1;
86              
87             __END__