File Coverage

blib/lib/Backup/Hanoi.pm
Criterion Covered Total %
statement 31 31 100.0
branch 8 10 80.0
condition 2 4 50.0
subroutine 5 5 100.0
pod 2 2 100.0
total 48 52 92.3


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