1 package File
::Rsync
::Mirror
::Recentfile
::Done
;
6 use File
::Rsync
::Mirror
::Recentfile
::FakeBigFloat
qw(:all);
12 File::Rsync::Mirror::Recentfile::Done - intervals of already rsynced timespans
16 use version
; our $VERSION = qv
('0.0.1');
20 my $done = File::Rsync::Mirror::Recentfile::Done->new;
21 $done->register ( $recent_events, [3,4,5,9] ); # registers elements 3-5 and 9
22 my $boolean = $done->covered ( $epoch );
26 Keeping track of already rsynced timespans.
34 =head2 my $obj = CLASS->new(%hash)
36 Constructor. On every argument pair the key is a method name and the
37 value is an argument to that method name.
42 my($class, @args) = @_;
43 my $self = bless {}, $class;
45 my($method,$arg) = splice @args, 0, 2;
60 "_logfile", # undocced: a small yaml dump appended on every change
61 "_rfinterval", # undocced: the interval of the holding rf
65 split /\n/, <<'=cut'; push @accessors, grep {s/^=item\s+//} @pod_lines; }
71 Boolean to turn on a bit verbosity.
77 use accessors
@accessors;
81 =head2 $boolean = $obj->covered ( $epoch1, $epoch2 )
83 =head2 $boolean = $obj->covered ( $epoch )
85 The first form returns true if both timestamps $epoch1 and $epoch2 in
86 floating point notation have been registered within one interval,
89 The second form returns true if this timestamp has been registered.
94 my($self, $epoch_high, $epoch_low) = @_;
95 die "Alert: covered() called without or with undefined first argument" unless defined $epoch_high;
96 my $intervals = $self->_intervals;
97 return unless @
$intervals;
98 if (defined $epoch_low) {
99 ($epoch_high,$epoch_low) = ($epoch_low,$epoch_high) if _bigfloatgt
($epoch_low,$epoch_high);
101 for my $iv (@
$intervals) {
102 my($upper,$lower) = @
$iv; # may be the same
103 if (defined $epoch_low) {
105 for my $e ($epoch_high,$epoch_low) {
107 $e eq $upper || $e eq $lower || (_bigfloatlt
($e,$upper) && _bigfloatgt
($e,$lower));
109 return 1 if $goodbound > 1;
111 return 1 if _bigfloatle
($epoch_high,$upper) && _bigfloatge
($epoch_high, $lower); # "between"
117 =head2 (void) $obj1->merge ( $obj2 )
119 Integrates all intervals in $obj2 into $obj1. Overlapping intervals
120 are conflated/folded/consolidated. Sort order is preserved as decreasing.
124 my($self, $other) = @_;
125 my $intervals = $self->_intervals;
126 my $ointervals = $other->_intervals;
127 OTHER
: for my $oiv (@
$ointervals) {
130 SELF
: for my $i (0..$#$intervals) {
131 my $iv = $intervals->[$i];
132 if ( _bigfloatlt
($oiv->[0],$iv->[1]) ) {
133 # both oiv lower than iv => next
136 if ( _bigfloatgt
($oiv->[1],$iv->[0]) ) {
137 # both oiv greater than iv => insert
141 # larger(left-iv,left-oiv) becomes left, smaller(right-iv,right-oiv) becomes right
142 $iv->[0] = _bigfloatmax
($oiv->[0],$iv->[0]);
143 $iv->[1] = _bigfloatmin
($oiv->[1],$iv->[1]);
146 unless (defined $splicepos) {
147 if ( _bigfloatlt
($oiv->[0], $intervals->[-1][1]) ) {
148 $splicepos = @
$intervals;
150 die "Panic: left-oiv[$oiv->[0]] should be smaller than smallest[$intervals->[-1][1]]";
153 splice @
$intervals, $splicepos, 0, [@
$oiv];
155 $intervals->[0] = [@
$oiv];
160 =head2 (void) $obj->register ( $recent_events_arrayref, $register_arrayref )
162 =head2 (void) $obj->register ( $recent_events_arrayref )
164 The first arrayref is a list of hashes that contain a key called
165 C<epoch> which is a string looking like a number. The second arrayref
166 is a list if integers which point to elements in the first arrayref to
169 The second form registers all events in $recent_events_arrayref.
174 my($self, $re, $reg) = @_;
175 my $intervals = $self->_intervals;
179 REGISTRANT
: for my $i (@
$reg) {
180 my $logfile = $self->_logfile;
183 open my $fh, ">>", $logfile or die "Could not open '$logfile': $!";
184 print $fh YAML
::Syck
::Dump
({
186 Brfinterval
=> $self->_rfinterval,
188 ($i>0 ?
("Dre-1" => $re->[$i-1]) : ()),
189 "Dre-0" => $re->[$i],
190 ($i<$#$re ? ("Dre+1" => $re->[$i+1]) : ()),
191 Eintervals
=> $intervals,
198 intervals
=> $intervals,
202 open my $fh, ">>", $logfile or die "Could not open '$logfile': $!";
203 print $fh YAML
::Syck
::Dump
({
205 intervals
=> $intervals,
212 my($self, $one) = @_;
213 my($i,$re,$intervals) = @
{$one}{qw(i re intervals)};
214 die sprintf "Panic: illegal i[%d] larger than number of events[%d]", $i, $#$re
216 my $epoch = $re->[$i]{epoch
};
217 return if $self->covered ( $epoch );
220 IV
: for my $iv (@
$intervals) {
221 my($ivhi,$ivlo) = @
$iv; # may be the same
223 && _bigfloatge
($re->[$i-1]{epoch
}, $ivlo)
224 && _bigfloatle
($re->[$i-1]{epoch
}, $ivhi)
225 && _bigfloatge
($iv->[1],$epoch)
227 # if left neighbor in re belongs to this interval,
228 # then I belong to it too; let us lower the ivlo
233 && _bigfloatle
($re->[$i+1]{epoch
}, $ivhi)
234 && _bigfloatge
($re->[$i+1]{epoch
}, $ivlo)
235 && _bigfloatle
($iv->[0],$epoch)
237 # ditto for right neighbor; increase the ivhi
241 last IV
if $registered>=2;
243 if ($registered == 2) {
244 $self->_register_one_fold2
249 } elsif ($registered == 1) {
250 $self->_register_one_fold1 ($intervals);
252 $self->_register_one_fold0
259 $intervals->[0] = [($epoch)x2
];
263 sub _register_one_fold0
{
269 for my $i (0..$#$intervals) {
270 if (_bigfloatgt
($epoch, $intervals->[$i][0])) {
275 unless (defined $splicepos) {
276 if (_bigfloatlt
($epoch, $intervals->[-1][1])) {
277 $splicepos = @
$intervals;
279 die "Panic: epoch[$epoch] should be smaller than smallest[$intervals->[-1][1]]";
282 splice @
$intervals, $splicepos, 0, [($epoch)x2
];
285 # conflate: eliminate overlapping intervals
286 sub _register_one_fold1
{
287 my($self,$intervals) = @_;
290 for my $i (0..$#$intervals-1) {
291 if (_bigfloatle
($intervals->[$i][1],
292 $intervals->[$i+1][0])) {
293 $intervals->[$i+1][0] = $intervals->[$i][0];
298 if (defined $splicepos) {
299 splice @
$intervals, $splicepos, 1;
306 sub _register_one_fold2
{
311 # we know we have hit twice, like in
312 # 40:[45,40], [40,35]
313 # 40:[45,40],[42,37],[40,35]
314 # 45:[45,40], [45,35]
315 # 45:[45,40],[42,37],[45,35]
316 # 35:[45,35], [40,35]
317 # 35:[45,35],[42,37],[40,35]
318 my($splicepos, $splicelen, %assert_between);
319 for my $i (0..$#$intervals) {
320 if ( $epoch eq $intervals->[$i][0]
321 or $epoch eq $intervals->[$i][1]
323 for (my $j = 1; $i+$j <= $#$intervals; $j++) {
324 if ( $epoch eq $intervals->[$i+$j][0]
325 or $epoch eq $intervals->[$i+$j][1]) {
326 $intervals->[$i+$j][0] = _bigfloatmax
($intervals->[$i][0],$intervals->[$i+$j][0]);
327 $intervals->[$i+$j][1] = _bigfloatmin
($intervals->[$i][1],$intervals->[$i+$j][1]);
333 $assert_between{$intervals->[$i+$j][$k]}++;
339 if (defined $splicepos) {
340 for my $k (keys %assert_between) {
341 if (_bigfloatgt
($k,$intervals->[$splicepos+$splicelen][0])
342 or _bigfloatlt
($k,$intervals->[$splicepos+$splicelen][1])){
344 require Data
::Dumper
;
345 die "Panic: broken intervals:".Data
::Dumper
::Dumper
($intervals);
348 splice @
$intervals, $splicepos, $splicelen;
351 die "Panic: Could not find an interval position to insert '$epoch'";
357 Forgets everything ever done and gives way for a new round of
358 mirroring. Usually called when the dirtymark on upstream has changed.
364 $self->_intervals(undef);
367 =head1 PRIVATE METHODS
375 $self->__intervals($set);
377 my $x = $self->__intervals;
378 unless (defined $x) {
380 $self->__intervals ($x);
385 =head1 COPYRIGHT & LICENSE
387 Copyright 2008, 2009 Andreas König.
389 This program is free software; you can redistribute it and/or modify it
390 under the same terms as Perl itself.
394 1; # End of File::Rsync::Mirror::Recentfile
398 # cperl-indent-level: 4