summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Assistant.hs7
-rw-r--r--Assistant/Threads/MountWatcher.hs89
-rw-r--r--Assistant/Threads/Watcher.hs2
-rw-r--r--Makefile4
-rw-r--r--debian/control1
-rw-r--r--git-annex.cabal11
6 files changed, 108 insertions, 6 deletions
diff --git a/Assistant.hs b/Assistant.hs
index 06484b086..51639584c 100644
--- a/Assistant.hs
+++ b/Assistant.hs
@@ -46,6 +46,11 @@
- Wakes up periodically and records the daemon's status to disk.
- Thread 12: sanity checker
- Wakes up periodically (rarely) and does sanity checks.
+ - Thread 13: mount watcher
+ - Either uses dbus to watch for drive mount events, or, when
+ - there's no dbus, polls to find newly mounted filesystems.
+ - Once a filesystem that contains a remote is mounted, syncs
+ - with it.
-
- ThreadState: (MVar)
- The Annex state is stored here, which allows resuscitating the
@@ -92,6 +97,7 @@ import Assistant.Threads.Merger
import Assistant.Threads.TransferWatcher
import Assistant.Threads.Transferrer
import Assistant.Threads.SanityChecker
+import Assistant.Threads.MountWatcher
import qualified Utility.Daemon
import Utility.LogFile
import Utility.ThreadScheduler
@@ -127,6 +133,7 @@ startDaemon assistant foreground
, transfererThread st dstatus transferqueue transferslots
, daemonStatusThread st dstatus
, sanityCheckerThread st dstatus transferqueue changechan
+ , mountWatcherThread st dstatus
, watchThread st dstatus transferqueue changechan
]
waitForTermination
diff --git a/Assistant/Threads/MountWatcher.hs b/Assistant/Threads/MountWatcher.hs
new file mode 100644
index 000000000..f3b9c0a3a
--- /dev/null
+++ b/Assistant/Threads/MountWatcher.hs
@@ -0,0 +1,89 @@
+{- git-annex assistant mount watcher, using either dbus or mtab polling
+ -
+ - Copyright 2012 Joey Hess <joey@kitenet.net>
+ -
+ - Licensed under the GNU GPL version 3 or higher.
+ -}
+
+{-# LANGUAGE CPP #-}
+{-# LANGUAGE OverloadedStrings #-}
+
+module Assistant.Threads.MountWatcher where
+
+import Common.Annex
+import Assistant.ThreadedMonad
+import Assistant.DaemonStatus
+import Utility.ThreadScheduler
+import Utility.Mounts
+
+import Control.Concurrent
+import qualified Data.Set as S
+
+#if WITH_DBUS
+import DBus.Client
+#else
+#warning Building without dbus support; will use mtab polling
+#endif
+
+mountWatcherThread :: ThreadState -> DaemonStatusHandle -> IO ()
+mountWatcherThread st handle =
+#if WITH_DBUS
+ dbusThread st handle
+#else
+ pollingThread st handle
+#endif
+
+#if WITH_DBUS
+dbusThread :: ThreadState -> DaemonStatusHandle -> IO ()
+dbusThread st handle = do
+ r <- tryIO connectSession
+ case r of
+ Left e -> do
+ print $ "Failed to connect to dbus; falling back to mtab polling (" ++ show e ++ ")"
+ pollingThread st handle
+ Right client -> do
+ {- Store the current mount points in an mvar,
+ - to be compared later. We could in theory work
+ - out the mount point from the dbus message, but
+ - this is easier. -}
+ mvar <- newMVar =<< currentMountPoints
+ -- Spawn a listener thread, and returns.
+ listen client mountadded (go mvar)
+ where
+ mountadded = matchAny
+ { matchInterface = Just "org.gtk.Private.RemoteVolumeMonitor"
+ , matchMember = Just "MountAdded"
+ }
+ go mvar event = do
+ nowmounted <- currentMountPoints
+ wasmounted <- swapMVar mvar nowmounted
+ handleMounts st handle wasmounted nowmounted
+
+#endif
+
+pollingThread :: ThreadState -> DaemonStatusHandle -> IO ()
+pollingThread st handle = go =<< currentMountPoints
+ where
+ go wasmounted = do
+ threadDelaySeconds (Seconds 10)
+ nowmounted <- currentMountPoints
+ handleMounts st handle wasmounted nowmounted
+ go nowmounted
+
+handleMounts :: ThreadState -> DaemonStatusHandle -> MountPoints -> MountPoints -> IO ()
+handleMounts st handle wasmounted nowmounted = mapM_ (handleMount st handle) $
+ S.toList $ newMountPoints wasmounted nowmounted
+
+handleMount :: ThreadState -> DaemonStatusHandle -> FilePath -> IO ()
+handleMount st handle mountpoint = do
+ putStrLn $ "mounted: " ++ mountpoint
+
+type MountPoints = S.Set FilePath
+
+{- Reads mtab, getting the current set of mount points. -}
+currentMountPoints :: IO MountPoints
+currentMountPoints = S.fromList . map mnt_dir <$> read_mtab
+
+{- Finds new mount points, given an old and a new set. -}
+newMountPoints :: MountPoints -> MountPoints -> MountPoints
+newMountPoints old new = S.difference new old
diff --git a/Assistant/Threads/Watcher.hs b/Assistant/Threads/Watcher.hs
index 9f0eba74e..ae4fafb78 100644
--- a/Assistant/Threads/Watcher.hs
+++ b/Assistant/Threads/Watcher.hs
@@ -5,8 +5,6 @@
- Licensed under the GNU GPL version 3 or higher.
-}
-{-# LANGUAGE CPP #-}
-
module Assistant.Threads.Watcher where
import Common.Annex
diff --git a/Makefile b/Makefile
index 0afb10a7b..1791d4339 100644
--- a/Makefile
+++ b/Makefile
@@ -1,11 +1,11 @@
bins=git-annex
mans=git-annex.1 git-annex-shell.1
-sources=Build/SysConfig.hs Utility/Touch.hs
+sources=Build/SysConfig.hs Utility/Touch.hs Utility/Mounts.hs
all=$(bins) $(mans) docs
OS:=$(shell uname | sed 's/[-_].*//')
ifeq ($(OS),Linux)
-BASEFLAGS_OPTS+=-DWITH_INOTIFY
+BASEFLAGS_OPTS+=-DWITH_INOTIFY -DWITH_DBUS
clibs=Utility/libdiskfree.o
else
BASEFLAGS_OPTS+=-DWITH_KQUEUE
diff --git a/debian/control b/debian/control
index 79702ed29..35cbfde05 100644
--- a/debian/control
+++ b/debian/control
@@ -22,6 +22,7 @@ Build-Depends:
libghc-edit-distance-dev,
libghc-hinotify-dev [linux-any],
libghc-stm-dev (>= 2.3),
+ libghc-dbus-dev,
ikiwiki,
perlmagick,
git,
diff --git a/git-annex.cabal b/git-annex.cabal
index e58bd4d95..00f57319d 100644
--- a/git-annex.cabal
+++ b/git-annex.cabal
@@ -31,6 +31,9 @@ Flag S3
Flag Inotify
Description: Enable inotify support
+Flag Dbus
+ Description: Enable dbus support
+
Flag Assistant
Description: Enable git-annex assistant and watch command
@@ -41,8 +44,8 @@ Executable git-annex
pcre-light, extensible-exceptions, dataenc, SHA, process, json, HTTP,
base == 4.5.*, monad-control, transformers-base, lifted-base,
IfElse, text, QuickCheck >= 2.1, bloomfilter, edit-distance, process
- -- Need to list this because it's generated from a .hsc file.
- Other-Modules: Utility.Touch
+ -- Need to list these because they're generated from .hsc files.
+ Other-Modules: Utility.Touch Utility.Mounts
C-Sources: Utility/libdiskfree.c
Extensions: CPP
GHC-Options: -threaded
@@ -59,6 +62,10 @@ Executable git-annex
Build-Depends: hinotify
CPP-Options: -DWITH_INOTIFY
+ if flag(Dbus)
+ Build-Depends: dbus
+ CPP-Options: -DWITH_DBUS
+
Test-Suite test
Type: exitcode-stdio-1.0
Main-Is: test.hs