#!/usr/bin/perl
use warnings;
use strict;

use autodie;
use POSIX;
use File::Slurp;
use IO::Select;
use Time::HiRes;
use Data::Dump qw(dump);
use English;
use JSON::XS;

my $dir = '/srv/cloudstore/var';
my $log_fifo = "$dir/rsyncd.log";
my $pid_file = "$dir/rsyncd.pid";
my $cfg_file = "$dir/rsyncd.conf";
my $users    = "users";

my @transfer = qw(
timestamp:%t:timestamp
login:%u:text
pid:%p:int
perms:%B:text
itemize:%i:text
mtime:%M:timestamp
op:%o:text
size:%l:int
transfered:%b:int
file:%f:text
);

my @transfer_names =          map { ( split(/:/,$_,3) )[0] } @transfer;
my $transfer_log   = join(' ',map { ( split(/:/,$_,3) )[1] } @transfer );

mkdir $dir if ! -e $dir;

mkfifo $log_fifo, 0700 unless -p $log_fifo;

my $rsync_config = qq{

#uid = nobody
#gid = nogroup
#use chroot = yes
use chroot = no

#max connections = 4
lock file = $dir/rsyncd.lock

#syslog facility = local5
log file  = $log_fifo

transfer logging = yes
log format = transfer-log:$transfer_log
max verbosity = 5

pid file  = $pid_file

# don't check secrets file permission (uid)
strict modes = no

pre-xfer exec = /srv/cloudstore/pre-xfer.sh
post-xfer exec = /srv/cloudstore/post-xfer.sh

[dpavlin]
	path = /srv/cloudstore/users/dpavlin/blob
	auth users = dpavlin
	secrets file = /srv/cloudstore/secrets/dpavlin
	read only = false

};

write_file $cfg_file, $rsync_config;
warn "created $cfg_file ", -s $cfg_file, " bytes\n";

if ( -e $pid_file ) {
	my $pid = read_file $pid_file;
	chomp($pid);
	if ( kill 0, $pid ) {
		warn "found rsync pid $pid";
	} else {
		unlink $pid_file;
	}
}

if ( ! -e $pid_file ) {
	my $exec = "rsync --daemon --config $cfg_file --no-detach --port=6501";
	warn "START $exec\n";

	die "could not fork\n" unless defined(my $pid = fork);
	unless ($pid) {
		warn "start server with $exec\n";
		exec $exec || die $!;
	}

	warn "wait for pid file";
	while ( ! -e $pid_file ) {
		sleep 1;
	}
}

use Gearman::Client;
my $gearman = Gearman::Client->new;
$gearman->job_servers('127.0.0.1:4730');

while(1) {
	warn "# reading log output from $log_fifo\n";
	open(my $fifo, '<', $log_fifo);
	while( my $line = <$fifo> ) {
		chomp $line;
		print $line, $/;
		if ( $line =~ /transfer-log:(.+)/ ) {
			my $transfer = $1;
			$transfer =~ s|(\d\d\d\d)/(\d\d)/(\d\d)[-\s](\d\d:\d\d:\d\d)|$1-$2-$3T$4|g;
warn "XXX $transfer";
			my ( $yyyy,$mm,$dd,undef,$login,undef ) = split( /[\-T\s]/, $transfer, 6 );

			my $path = "users/$login/log";
			mkdir $path unless -d $path;
			$path .= "/$yyyy-$mm-$dd";
warn "## $path $transfer\n";
			my $new_log = ! -e $path;
			open( my $log, '>>', $path );
			print $log join(' ',@transfer),"\n" if $new_log; # store header
			print $log "$transfer\n";
			close $log;


			my @v = split(/\s+/,$transfer,$#transfer + 1);
			my %data;
			@data{@transfer_names} = @v ; # FIXME validate?

			print ">>> data ",dump( \%data );

			$gearman->dispatch_background( 'rsync_transfer' => encode_json \%data );

		}
	}
	close($fifo);
	sleep 1;
}

