summaryrefslogtreecommitdiff
path: root/doc/design/assistant/blog/day_40__dbus.mdwn
blob: 049c3ffe0d663b7789582e3dc95a49b7ebc1c51c (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
Really productive day today, now that I'm out of the threaded runtime
tarpit!

First, brought back `--debug` logging, better than before! As part of that, I
wrote some 250 lines of code to provide a IMHO more pleasant interface to
`System.Process` (itself only 650 lines of code) that avoids all the
low-level setup, cleanup, and tuple unpacking. Now I can do things like
write to a pipe to a process, and ensure it exits nonzero, this easily:

	withHandle StdinHandle createProcessSuccess (proc "git" ["hash-object", "--stdin"]) $ \h ->
		hHutStr h objectdata

My interface also makes it easy to run nasty background processes,
reading their output lazily.

	lazystring <- withHandle StdoutHandle createBackgroundProcess (proc "find" ["/"]) hGetContents

Any true Haskellers are shuddering here, I really should be using
conduits or pipes, or something. One day..

----

The assistant needs to detect when removable drives are attached, and
sync with them. This is a reasonable thing to be working on at this point,
because it'll make the currently incomplete data transfer code fully usable
for the sneakernet use case, and firming that up will probably be a good
step toward handing other use cases involving data transfer over the
network, including cases where network remotes are transientely available.

So I've been playing with using dbus to detect mount events.
There's a very nice Haskell library to use dbus.

This simple program will detect removable drives being mounted, and
works on Xfce (as long as you have automounting enabled in its
configuration), and should also work on Gnome, and, probably, KDE:

[[!format haskell """
{-# LANGUAGE OverloadedStrings #-}

import Data.List (sort)
import DBus
import DBus.Client
import Control.Monad

main = do
	client <- connectSession
    
	listen client mountadded $ \s ->
		putStrLn (show s)

	forever $ getLine -- let listener thread run forever

	where
		mountadded = matchAny
			{ matchInterface = Just "org.gtk.Private.RemoteVolumeMonitor"
			, matchMember = Just "MountAdded"
			}
"""]]

(Yeah... "org.gtk.Private.RemoteVolumeMonitor". There are so
many things wrong with that string. What does gtk have to do with
mounting a drive? Why is it Private? Bleagh. Should I only match
the "MountAdded" member and not the interface? Seems everyone who does
this relies on google to find other people who have cargo-culted it,
or just runs `dbus-monitor` and picks out things.
There seems to be no canonical list of events. Bleagh.)

----

Spent a while shaving a yak of needing a `getmntent` interface in Haskell.
Found one in a hsshellscript library; since that library is not packaged
in Debian, and I don't really want to depend on it, I extracted just
the mtab and fstab parts of it into a little library in git-annex.

----

I've started putting together a MountWatcher thread. On systems without
dbus (do OSX or the BSDs have dbus?), or if dbus is not running, it polls
`/etc/mtab` every 10 seconds for new mounts. When dbus is available,
it doesn't need the polling, and should notice mounts more quickly.

Open question: Should it still poll even when dbus is available? Some of us
like to mount our own drives, by hand and may have automounting disabled. It'd
be good if the assistant supported that. This might need a
`annex.no-dbus` setting, but I'd rather avoid needing such manual
configuration.

One idea is to do polling in addition to dbus, if `/etc/fstab` contains
mount points that seem to be removable drives, on which git remotes lives.
Or it could always do polling in addition to dbus, which is just some extra
work. Or, it could try to introspect dbus to see if mount events will
be generated.

The MountWatcher so far only detects new mounts and prints out what
happened. Next up: Do something in response to them. 

This will involve manipulating the Annex state to belatedly add the Remote
on the mount point.. tricky. And then, for Git Remotes, it should pull/push
the Remote to sync git data. Finally, for all remotes, it will need to
queue Transfers of file contents from/to the newly available Remote.