File-Rsync-Mirror-Recent
view release on metacpan or search on metacpan
lib/File/Rsync/Mirror/Recentfile.pm view on Meta::CPAN
return $interval;
}
=head2 $secs = $obj->interval_secs ( $interval_spec )
$interval_spec is described below in the section INTERVAL SPEC. If
empty defaults to the inherent interval for this object.
=cut
sub interval_secs {
my ($self, $interval) = @_;
$interval ||= $self->interval;
unless (defined $interval) {
die "interval_secs() called without argument on an object without a declared one";
}
my ($n,$t) = $interval =~ /^(\d*)([smhdWMQYZ]$)/ or
die "Could not determine seconds from interval[$interval]";
if ($interval eq "Z") {
return MAX_INT;
} elsif (exists $seconds{$t} and $n =~ /^\d+$/) {
return $seconds{$t}*$n;
} else {
die "Invalid interval specification: n[$n]t[$t]";
}
}
=head2 $obj->localroot ( $localroot )
Get/set accessor. The local root of the tree. Guaranteed without
trailing slash.
=cut
sub localroot {
my ($self, $localroot) = @_;
if (@_ >= 2) {
$localroot =~ s|/$||;
$self->_localroot($localroot);
$self->_rfile(undef);
}
$localroot = $self->_localroot;
}
=head2 $ret = $obj->local_path($path_found_in_recentfile)
Combines the path to our local mirror and the path of an object found
in this I<recentfile>. In other words: the target of a mirror operation.
Implementation note: We split on slashes and then use
File::Spec::catfile to adjust to the local operating system.
=cut
sub local_path {
my($self,$path) = @_;
unless (defined $path) {
# seems like a degenerated case
return $self->localroot;
}
my @p = split m|/|, $path;
File::Spec->catfile($self->localroot,@p);
}
=head2 (void) $obj->lock
Locking is implemented with an C<mkdir> on a locking directory
(C<.lock> appended to $rfile).
=cut
sub lock {
my ($self) = @_;
# not using flock because it locks on filehandles instead of
# old school ressources.
my $locked = $self->_is_locked and return;
my $rfile = $self->rfile;
# XXX need a way to allow breaking the lock
my $start = time;
my $locktimeout = $self->locktimeout || 600;
my %have_warned;
my $lockdir = "$rfile.lock";
my $procfile = "$lockdir/process";
GETLOCK: while (not mkdir $lockdir) {
if (open my $fh, "<", $procfile) {
chomp(my $process = <$fh>);
if (0) {
} elsif ($process !~ /^\d+$/) {
warn "Warning: unknown process holds a lock in '$lockdir', waiting..." unless $have_warned{unknown}++;
} elsif ($$ == $process) {
last GETLOCK;
} elsif (kill 0, $process) {
warn "Warning: process $process holds a lock in '$lockdir', waiting..." unless $have_warned{$process}++;
} else {
warn "Warning: breaking lock held by process $process";
sleep 1;
last GETLOCK;
}
} else {
warn "Warning: unknown process holds a lock in '$lockdir', waiting..." unless $have_warned{unknown}++;
}
Time::HiRes::sleep 0.01;
if (time - $start > $locktimeout) {
die "Could not acquire lockdirectory '$rfile.lock': $!";
}
} # GETLOCK
open my $fh, ">", $procfile or die "Could not open >$procfile\: $!";
print $fh $$, "\n";
close $fh or die "Could not close: $!";
$self->_is_locked (1);
}
=head2 (void) $obj->merge ($other)
Bulk update of this object with another one. It's used to merge a
smaller and younger $other object into the current one. If this file
is a C<Z> file, then we normally do not merge in objects of type
C<delete>; this can be overridden by setting
keep_delete_objects_forever. But if we encounter an object of type
delete we delete the corresponding C<new> object if we have it.
( run in 2.315 seconds using v1.01-cache-2.11-cpan-71847e10f99 )