Linux-realtimed

 view release on metacpan or  search on metacpan

bin/realtimed  view on Meta::CPAN

				my $runnable = qx{runuser -l $user -c 'if test -x "\$(command -v $command)"; then echo 1; else echo 0; fi;'};
				chomp $runnable;
				$ENV{PATH} = '';
				unless ($runnable && $runnable eq '1') {
					notice "$errline - output: $runnable";
					next;
				}

				initTree({
					path => $path,
					events => $events,
					eventNames	=> $textevents,
					recursive => $recursive,
					user => $user,
					command => $command,
					arguments => $arguments,
					version => $nextversion,
					userid => $userid,
					groupid => $groupid
				});
			}
		}
	}

	watchDir($dirtree->{conf}->{$nextversion});
	$dirtree->{curversion}++;
	releaseInotifyWatchers($dirtree->{conf}->{$curversion}) if $curversion; # if $curversion 0 daemon just started and no previous config
	delete $dirtree->{conf}->{$curversion};
	printCurrentConf();
}

sub getCanonicalPath {
	my ($path) = @_;

	unless( -e $path ){
		err "dir $path does not exist";
		return '';
	}

	if ( -d $path) {
		my $dh; my $fd;
		opendir $dh, $path;
		$fd = fileno $dh;
		$path = readlink("/proc/$$/fd/$fd");
		closedir $dh;
	} else {
		my $fh; my $fd;
		open $fh, '<', $path;
		$fd = fileno $fh;
		$path = readlink("/proc/$$/fd/$fd");
		close $fh;
	}
	return $path;
}

sub initTree {
	my ($conf) = @_;
	my $path = getCanonicalPath($conf->{path});
	return unless $path;
	my $curpath = '';
	my @path = split m|/|, $path;
	shift @path;
	my $version = $conf->{version};
	$dirtree->{conf}->{$version} //= {};
	my $node = $dirtree->{conf}->{$version};
	for (@path) {
		$curpath .= "/$_";
		$node->{$curpath} = { path => $curpath } unless $node->{$curpath};
		$node = $node->{$curpath};
		next unless $curpath eq $path;
#		$node->{conf} //= {};
#		$node = $node->{conf};
		$node->{events} |= $conf->{events};
		$node->{textevents} = eventsList($node->{events});
		$node->{recursive} ||= $conf->{recursive};
		$node->{triggers} //= [];
		push @{$node->{triggers}}, $conf;
	}
}

sub releaseInotifyWatchers {
	my ($node) = @_;
	return unless ref $node eq 'HASH';
	$node->{iw}->cancel if defined $node->{iw};
	for(keys %$node){
		next if $_ eq 'path';
		next if $_ eq 'events';
		next if $_ eq 'recursive';
		releaseInotifyWatchers($node->{$_});
	}
}

sub watchDir {
	my ($node) = @_;
	unless(defined $node->{events}){
		for(keys %$node){
			next if $_ eq 'path';
			next if $_ eq 'events';
			next if $_ eq 'recursive';
			watchDir($node->{$_});
		}
		return;
	}
	my $recursive = $node->{recursive};
	my $triggers = $node->{triggers};
	my $events = $node->{events};
	my $dir = $node->{path};

	unless($node->{iw} && $node->{ew}) { # avoid watchers duplication
		my $in = Linux::Inotify2->new;
		$node->{iw} = $in->watch($node->{path}, $events | $direvents, sub {
			my $e = shift;

			# realtimed itself triggers opendir events while parsing dir tree, we need to filter them out, sorry
			# return if $e->IN_ISDIR && $e->IN_OPEN;

			$e->{eventMask} = $e->mask;
			$e->{eventName} = eventsList($e->mask);
			$e->{node} = $node;
			eventQueueOverflowed($e) if $e->mask & IN_Q_OVERFLOW;
			manageEvents($e) if $e->mask & $events;



( run in 1.398 second using v1.01-cache-2.11-cpan-71847e10f99 )