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.004';
4 2     2   218719 use strict;
  2         25  
  2         61  
5 2     2   10 use warnings;
  2         3  
  2         51  
6              
7 2     2   24 use v5.6.0;
  2         6  
8              
9             sub new {
10 6     6 1 905 my $class = shift;
11 6         15 my $devices = shift;
12 6 50       24 $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         19  
16              
17 6 100       28 die "three devices needed.\n" if ($device_count < 3);
18              
19             # half a hanoi cycle is just what we need for backup
20 5         22 my $hanoi_cycles_half = (2**$device_count) / 2;
21              
22 5         21 my $self = { devices => $devices,
23             hanoi_cycles_half => $hanoi_cycles_half,
24             };
25              
26 5         12 bless $self, $class;
27              
28 5         21 return $self;
29             }
30              
31             sub get_device_for_cycle {
32              
33 91     91 1 223 my $self = shift;
34 91         169 my $cycle = shift;
35              
36 91 100       238 $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       225 ->[(scalar @{$self->{devices}}) + $cycle -1]
  3         27  
42             if ($cycle < 0);
43              
44             # allow cycle to cross hanoi limit, map it to first half
45 88         186 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       179 if ($modulo_cycle == 0);
50              
51             # calculate which device is used for given cycle
52 88         173 my $hanoi_number =
53             _get_right_zeros_from_digital_representation(
54             $modulo_cycle);
55              
56             # select and return device
57 88         473 return $self->{devices}->[$hanoi_number];
58              
59             }
60              
61             sub _get_right_zeros_from_digital_representation {
62              
63 88     88   169 my $number = shift;
64              
65             # convert to binary format: e.g. number 5 -> 101
66 88         350 my $binary = sprintf "%b", $number;
67              
68             # represent number zero as empty string
69 88 50       252 $binary = '' if ($binary == 0);
70              
71              
72             # count the zeros, at the right from the binary number
73              
74 88         126 my $zeros_from_the_right = 0;
75              
76 88 100       454 if ( $binary =~ /(0+)$/ ) {
77 48         129 my $zero_capture = $1;
78              
79 48         90 $zeros_from_the_right = length $zero_capture;
80             }
81              
82 88         180 return $zeros_from_the_right;
83             }
84              
85             1;
86              
87             __END__