generalized waitfordeb; use inotify to track file creation and upload progress rsync
authorMatthias Förste foerste@schlittermann.de
Thu, 19 Apr 2012 20:53:29 +0200
branchrsync
changeset 41 40df28fd3562
parent 40 5f159c41e8a3
child 42 73cb1d7a1bd8
generalized waitfordeb; use inotify to track file creation and upload progress
bin/waitfordeb
--- a/bin/waitfordeb	Wed Apr 18 11:09:40 2012 +0200
+++ b/bin/waitfordeb	Thu Apr 19 20:53:29 2012 +0200
@@ -4,38 +4,72 @@
 use strict;
 use warnings;
 
-my $to = 600;
-my $i = "$ENV{HOME}/incoming";
+use File::Basename;
+use Linux::Inotify2;
+
+#my $to = 600;
+my $to = 60;
 
-# XXX
-#$| = 1;
+my $inotify = new Linux::Inotify2
+    or die "unable to create new inotify object: $!";
+$inotify->blocking(0);
+
+my %size;
+my $exit_after;
 
-my $s = time;
+my $ME = basename $0;
 
-if ($ARGV[0] =~ m,^(\Q$i\E/)?repair_.*\.changes$,) {
-    my $d = "$i/$&";
-    $d =~ s/\.changes$/.deb/;
-    my $p = qr/^\Q$d\E:( [0-9]+[cefFrm]*)+$/;
+sub delay_exit { my $fn = shift; $exit_after = time + $to if $size{basename $fn}; }
+sub verify_size { 
+    my $fn = shift;
+    delay_exit $fn;
+    my $bn = basename $fn;
+    my $s = -s $fn;
+    delete $size{$bn} if defined $s and $s >= $size{$bn};
+}
+
+my $incoming = "$ENV{HOME}/incoming";
+my $nfiles = 0;
+my $c = "$incoming/$ARGV[0]";
 
-    { # 'last' needs this in a 'do ... while' loop? see 'man perlsyn'
-	do {
-
-	    if (-e $d) {
-
-		$_ = qx(fuser $d);
+# first setup a file creation watch on the incoming directory (we cannot set
+# watches on objects that dont exist yet); then *if* a file which is listed in
+# the changes file is created inside that directory then setup file
+# {modification,close} watches on it; we need the modification watch to reset
+# the 'timeout counter' and verify the file size in the close watch. ofcourse
+# we need the list of files from the changes file first; we build it here
+open C, '<', $c or die "Can't open '<$c': $!\n";
+my $skip = 1;
+while (<C>) {
+    no warnings qw(syntax);
+    if (/^files:\s*$/i) { $skip = 0; next; }
+    next if $skip;
+    unless (/^ ([^ ]+) +([^ ]+) +([^ ]+) +([^ ]+) +([^ \n]+) *$/) { $skip = 1; next; }
+    use warnings;
+    $size{$5} = $2;
+    $nfiles++;
+}
+close C;
+warn "$ME: no files found in changes file.\n" unless $nfiles;
 
-		die "output from 'fuser' expected but got none - is it in \$PATH?" unless defined;
-		last if $_ eq '';
-		die "unexpected output - please check" unless /$p/;
+$inotify->watch($incoming, IN_MODIFY, sub { my $e = shift; delay_exit $e->fullname; } ) or warn "Can't watch: $!";
+$inotify->watch($incoming, IN_CLOSE, sub { my $e = shift; verify_size $e->fullname; } ) or warn "Can't watch: $!";
+
+# do initial check on file in case its upload is already finished
+verify_size "$incoming/$_" for keys %size;
 
-	    }
+my $done = 0;
+do {
+
+    warn scalar localtime;
 
-	    die "timeout exceeded while waiting for package file '$d'" if time - $s > $to;
-
-	} while (sleep 10);
-
+    $inotify->poll;
+    if (time > $exit_after) {
+        warn "$ME: file upload timed out.\n";
+        $done = 1;
     }
 
-}
+    $done = 1 unless %size;
+    exec "$ENV{HOME}/bin/rpi" if $done;
 
-exec "$ENV{HOME}/bin/rpi";
+} while (sleep 1);