Here's a modified patch for Inotify2 support. It fixes a typo in
Watch_Incoming() and also tests for the existence of Linux::Inotify2.
I've also added some log messages to help with debugging.

-- 
Regards,
Andres Mejia
diff -urN debpool_released/bin/debpool debpool/bin/debpool
--- debpool_released/bin/debpool	2007-12-03 14:10:49.000000000 -0500
+++ debpool/bin/debpool	2007-12-13 04:03:38.000000000 -0500
@@ -118,26 +147,63 @@
     die "$msg\n";
 }
 
+# Print the path set for the lockfile and exit. This is mainly used to run
+# debpool with start-stop-daemon.
+
+if ($Options{'get_lock_path'}) {
+    print "$Options{'lock_file'}\n";
+    exit 0;
+}
+
 # Obtain a lockfile. We should never run more than one occurance; it's too
 # likely that we'd step on our own toes.
 
 if (!sysopen(LOCK_FILE, $Options{'lock_file'}, O_WRONLY|O_CREAT|O_EXCL, 0644)) {
-    my($msg) = "Couldn't obtain lockfile '$Options{'lock_file'}'; ";
+    my($msg) = "Couldn't obtain lockfile '$Options{'lock_file'}': ";
 
     if (open(LOCK_FILE, '<', $Options{'lock_file'}) &&
        (my($pid) = <LOCK_FILE>)) {
         chomp($pid);
-        $msg .= "(PID $pid)\n";
+        if (open(STAT_FILE, '<', "/proc/$pid/stat") &&
+            (my($stat) = <STAT_FILE>)) {
+            if ($stat =~ m/debpool/) {
+                # debpool process was already started
+                $msg .= "debpool was already running with PID $pid\n";
+                close(LOCK_FILE);
+                close(STAT_FILE);
+                die $msg;
+            }
+        } else {
+            # debpool wasn't running using the specified PID so remove
+            # the lock and create a new one
+            close(LOCK_FILE);
+            unlink $Options{'lock_file'};
+            sysopen(NEW_LOCK_FILE, $Options{'lock_file'},
+                O_WRONLY|O_CREAT|O_EXCL, 0644);
+            print NEW_LOCK_FILE "$$\n";
+            close(NEW_LOCK_FILE);
+        }
     } else {
+        # Could not read PID from lockfile
         $msg .= "(unable to read PID)\n";
     }
-
-    die $msg;
-} else { # Do something useful - like put our PID into the file.
+} else { # debpool wasn't running so create a lock
     print LOCK_FILE "$$\n";
     close(LOCK_FILE);
 }
 
+if ($Options{'daemon'} && $Options{'use_inotify'}) {
+    # Fall back to normal monitoring if Inotify setup fails.
+    if (!Setup_Incoming_Watch()) {
+        Log_Message("Not using inotify with debpool.", LOG_GENERAL, LOG_WARNING);
+        $Options{'use_inotify'} = 0;
+    }
+}
+
+# Check for any changes files in the incoming directory.
+
+my(@changefiles) = Scan_Changes($Options{'incoming_dir'});
+
 # Start the main loop. We use a do/until loop so that we always fire off at
 # least once.
 
@@ -163,10 +229,6 @@
     }
 }
 
-# Check for any changes files in the incoming directory.
-
-my(@changefiles) = Scan_Changes($Options{'incoming_dir'});
-
 # Go through each of the changes files we found, and process it. This is the
 # heart of things.
 
@@ -640,7 +700,8 @@
 if ($Options{'daemon'}) {
     Log_Message("Waiting on changes to incoming dir.", LOG_GENERAL, LOG_DEBUG);
 
-    if (!Monitor_Incoming()) {
+    @changefiles = Monitor_Incoming();
+    if ([EMAIL PROTECTED] && !$Signal_Caught) {
         my($msg) = "Error in Monitor_Incoming: " . $DebPool::Dirs::Error;
         Log_Message($msg, LOG_GENERAL, LOG_ERROR);
     }
diff -urN debpool_released/share/DebPool/Config.pm debpool/share/DebPool/Config.pm
--- debpool_released/share/DebPool/Config.pm	2007-12-03 14:10:49.000000000 -0500
+++ debpool/share/DebPool/Config.pm	2007-12-13 04:03:55.000000000 -0500
@@ -865,6 +897,17 @@
 $Options{'sleep'} = 300;
 $OptionDefs{'sleep'} = 'sleep=i';
 
+=item B<use_inotify> = I<boolean>
+
+Sets whether debpool should use inotify to monitor for incoming changes
+
+Default value: 0 (false)
+
+=cut
+
+$Options{'use_inotify'} = 0;
+$OptionDefs{'use_inotify'} = 'use_inotify!';
+
 =item B<rollback> = I<boolean>
 
 This determines whether older packages in the incoming queue are allowed
diff -urN debpool_released/share/DebPool/Dirs.pm debpool/share/DebPool/Dirs.pm
--- debpool_released/share/DebPool/Dirs.pm	2007-12-03 14:10:49.000000000 -0500
+++ debpool/share/DebPool/Dirs.pm	2007-12-13 04:04:10.000000000 -0500
@@ -60,6 +60,8 @@
     @EXPORT_OK = qw(
         &Archfile
         &Create_Tree
+        &Tree_Mkdir
+        &Setup_Incoming_Watch
         &Monitor_Incoming
         &PoolBasePath
         &PoolDir
@@ -69,7 +71,8 @@
     );
 
     %EXPORT_TAGS = (
-        'functions' => [qw(&Archfile &Create_Tree &Monitor_Incoming
+        'functions' => [qw(&Archfile &Create_Tree &Tree_Mkdir
+                           &Monitor_Incoming &Setup_Incoming_Watch
                            &PoolBasePath &PoolDir &Scan_Changes &Scan_All
                            &Strip_Subsection)],
         'vars' => [qw()],
@@ -87,6 +90,8 @@
 
 our($Error);
 
+my($inotify);
+
 ### File lexicals
 
 # None
@@ -313,10 +309,70 @@
     return [EMAIL PROTECTED];
 }
 
+# Setup_Incoming_Watch()
+#
+# Creates a Linux::Inotify2 object and adds a watch on the incoming directory.
+# Returns 1 on success, 0 on failure (and sets $Error).
+
+sub Setup_Incoming_Watch {
+    use DebPool::Logging qw(:functions :facility :level);
+    use DebPool::Config;
+    if (!eval{ require Linux::Inotify2; }) {
+        Log_Message("liblinux-inotify2-perl is required to activate inotify support for debpool.", LOG_GENERAL, LOG_WARNING);
+        return 0;
+    } else {
+        use Linux::Inotify2;
+    }
+
+    $inotify = new Linux::Inotify2;
+    if (!$inotify) {
+        $Error = "Unable to create new inotify object: $!";
+        Log_Message("$Error", LOG_GENERAL, LOG_ERROR);
+        return 0;
+    }
+    if (!$inotify->watch("$Options{'incoming_dir'}",
+                         IN_CLOSE_WRITE |
+                         IN_MOVED_TO )) {
+        $Error = "Unable to watch $Options{'incoming_dir'}: $!";
+        Log_Message("$Error", LOG_GENERAL, LOG_ERROR);
+        return 0;
+    }
+    Log_Message("Watching $Options{'incoming_dir'} with Inotify",
+                LOG_GENERAL, LOG_DEBUG);
+    return 1;
+}
+
+# Watch_Incoming()
+#
+# Reads events from the Inotify2 object (blocking until one occurs),
+# picks out the .changes file(s) and returns them (if any; otherwise
+# it loops).
+#
+# Returns a list of .changes files on success, undef on failure (which
+# includes interruption by a signal).
+    
+sub Watch_Incoming {
+    use DebPool::Logging qw(:functions :facility :level);
+
+    while (my @events = $inotify->read) {
+	my @changes;
+	foreach (@events) {
+	    push @changes, $_->name if ($_->name =~ /\.changes$/);
+	}
+        if (@changes > 0) {
+            Log_Message("Found changes: ".join(', ', @changes),
+                        LOG_GENERAL, LOG_DEBUG);
+            return @changes;
+        }
+    }
+    return undef;
+}
+
 # Monitor_Incoming()
 #
 # Monitors the incoming directory, looping until the directory is updated.
-# Returns 1 on success, 0 on failure (and sets $Error).
+# Returns a list of .changes files on success, undef on failure (which
+# includes interruption by a signal - check $DebPool::Signal::Signal_Caught).
 
 sub Monitor_Incoming {
     use DebPool::Config;
@@ -327,28 +383,29 @@
     # further.
 
     if ($DebPool::Signal::Signal_Caught) {
-        return 1;
+        return undef;
     }
 
-    my(@stat) = stat($Options{'incoming_dir'});
-    if ([EMAIL PROTECTED]) {
-        $Error = "Couldn't stat incoming_dir '$Options{'incoming_dir'}'";
-        return 0;
-    }
-    my($mtime) = $stat[9];
-
-    do {
-        Log_Message("Incoming monitor: sleeping for " .
-            $Options{'sleep'} . " seconds", LOG_GENERAL, LOG_DEBUG);
-        sleep($Options{'sleep'});
-        @stat = stat($Options{'incoming_dir'});
-        if ([EMAIL PROTECTED]) {
-            $Error = "Couldn't stat incoming_dir '$Options{'incoming_dir'}'";
-            return 0;
-        }
-    } until (($stat[9] != $mtime) || ($DebPool::Signal::Signal_Caught));
+    if ($Options{'use_inotify'}) {
+        return Watch_Incoming();
+    } else {
+        my(@stat) = stat($Options{'incoming_dir'});
+        my($mtime) = $stat[9];
 
-    return 1;
+        do {
+            Log_Message("Incoming monitor: sleeping for " .
+                        $Options{'sleep'} . " seconds", LOG_GENERAL, LOG_DEBUG);
+            sleep($Options{'sleep'});
+            @stat = stat($Options{'incoming_dir'});
+            if ([EMAIL PROTECTED]) {
+                $Error = "Couldn't stat incoming_dir '$Options{'incoming_dir'}'";
+                return undef;
+            }
+            return undef if $DebPool::Signal::Signal_Caught;
+        } until ($stat[9] != $mtime);
+        
+        return Scan_Changes();
+    }
 }
 
 # PoolDir($name, $section, $archive_base)

Reply via email to