2012-06-13 16:36:33 +00:00
|
|
|
{- git-annex assistant daemon
|
|
|
|
-
|
|
|
|
- Copyright 2012 Joey Hess <joey@kitenet.net>
|
|
|
|
-
|
|
|
|
- Licensed under the GNU GPL version 3 or higher.
|
|
|
|
-
|
|
|
|
- Overview of threads and MVars, etc:
|
|
|
|
-
|
|
|
|
- Thread 1: parent
|
|
|
|
- The initial thread run, double forks to background, starts other
|
|
|
|
- threads, and then stops, waiting for them to terminate,
|
|
|
|
- or for a ctrl-c.
|
2012-07-27 01:51:47 +00:00
|
|
|
- Thread 2: Watcher
|
2012-06-13 16:36:33 +00:00
|
|
|
- Notices new files, and calls handlers for events, queuing changes.
|
|
|
|
- Thread 3: inotify internal
|
|
|
|
- Used by haskell inotify library to ensure inotify event buffer is
|
|
|
|
- kept drained.
|
2012-06-13 23:32:09 +00:00
|
|
|
- Thread 4: inotify startup scanner
|
|
|
|
- Scans the tree and registers inotify watches for each directory.
|
2012-06-13 16:36:33 +00:00
|
|
|
- A MVar lock is used to prevent other inotify handlers from running
|
|
|
|
- until this is complete.
|
2012-07-27 01:51:47 +00:00
|
|
|
- Thread 5: Committer
|
2012-06-13 16:36:33 +00:00
|
|
|
- Waits for changes to occur, and runs the git queue to update its
|
2012-07-05 16:21:22 +00:00
|
|
|
- index, then commits. Also queues Transfer events to send added
|
|
|
|
- files to other remotes.
|
2012-07-27 01:51:47 +00:00
|
|
|
- Thread 6: Pusher
|
2012-06-22 21:01:08 +00:00
|
|
|
- Waits for commits to be made, and pushes updated branches to remotes,
|
|
|
|
- in parallel. (Forks a process for each git push.)
|
2012-07-27 01:51:47 +00:00
|
|
|
- Thread 7: PushRetryer
|
2012-06-25 20:38:12 +00:00
|
|
|
- Runs every 30 minutes when there are failed pushes, and retries
|
|
|
|
- them.
|
2012-07-27 01:51:47 +00:00
|
|
|
- Thread 8: Merger
|
2012-06-22 21:01:08 +00:00
|
|
|
- Waits for pushes to be received from remotes, and merges the
|
2012-07-06 00:57:06 +00:00
|
|
|
- updated branches into the current branch.
|
|
|
|
- (This uses inotify on .git/refs/heads, so there are additional
|
|
|
|
- inotify threads associated with it, too.)
|
2012-07-27 01:51:47 +00:00
|
|
|
- Thread 9: TransferWatcher
|
2012-07-03 14:58:40 +00:00
|
|
|
- Watches for transfer information files being created and removed,
|
2012-07-23 03:16:56 +00:00
|
|
|
- and maintains the DaemonStatus currentTransfers map.
|
2012-07-06 00:57:06 +00:00
|
|
|
- (This uses inotify on .git/annex/transfer/, so there are
|
|
|
|
- additional inotify threads associated with it, too.)
|
2012-08-28 18:04:28 +00:00
|
|
|
- Thread 10: TransferPoller
|
|
|
|
- Polls to determine how much of each ongoing transfer is complete.
|
|
|
|
- Thread 11: Transferrer
|
2012-07-05 20:34:20 +00:00
|
|
|
- Waits for Transfers to be queued and does them.
|
2012-08-28 18:04:28 +00:00
|
|
|
- Thread 12: StatusLogger
|
2012-06-13 16:36:33 +00:00
|
|
|
- Wakes up periodically and records the daemon's status to disk.
|
2012-08-28 18:04:28 +00:00
|
|
|
- Thread 13: SanityChecker
|
2012-06-13 23:32:09 +00:00
|
|
|
- Wakes up periodically (rarely) and does sanity checks.
|
2012-08-28 18:04:28 +00:00
|
|
|
- Thread 14: MountWatcher
|
2012-07-19 17:01:41 +00:00
|
|
|
- Either uses dbus to watch for drive mount events, or, when
|
|
|
|
- there's no dbus, polls to find newly mounted filesystems.
|
2012-07-23 03:16:56 +00:00
|
|
|
- Once a filesystem that contains a remote is mounted, updates
|
|
|
|
- state about that remote, pulls from it, and queues a push to it,
|
|
|
|
- as well as an update, and queues it onto the
|
|
|
|
- ConnectedRemoteChan
|
2012-08-28 18:04:28 +00:00
|
|
|
- Thread 15: NetWatcher
|
2012-08-21 23:58:53 +00:00
|
|
|
- Deals with network connection interruptions, which would cause
|
|
|
|
- transfers to fail, and can be recovered from by waiting for a
|
|
|
|
- network connection, and syncing with all network remotes.
|
|
|
|
- Uses dbus to watch for network connections, or when dbus
|
|
|
|
- cannot be used, assumes there's been one every 30 minutes.
|
2012-08-28 18:04:28 +00:00
|
|
|
- Thread 16: TransferScanner
|
2012-07-23 03:16:56 +00:00
|
|
|
- Does potentially expensive checks to find data that needs to be
|
|
|
|
- transferred from or to remotes, and queues Transfers.
|
2012-09-08 19:07:44 +00:00
|
|
|
- Uses the ScanRemotes map.a
|
|
|
|
- Thread 17: PairListener
|
|
|
|
- Listens for incoming pairing traffic, and takes action.
|
add ConfigMonitor thread
Monitors git-annex branch for changes, which are noticed by the Merger
thread whenever the branch ref is changed (either due to an incoming push,
or a local change), and refreshes cached config values for modified config
files.
Rate limited to run no more often than once per minute. This is important
because frequent git-annex branch changes happen when files are being
added, or transferred, etc.
A primary use case is that, when preferred content changes are made,
and get pushed to remotes, the remotes start honoring those settings.
Other use cases include propigating repository description and trust
changes to remotes, and learning when a remote has added a new special
remote, so the webapp can present the GUI to enable that special remote
locally.
Also added a uuid.log cache. All other config files already had caches.
2012-10-20 20:37:06 +00:00
|
|
|
- Thread 18: ConfigMonitor
|
|
|
|
- Triggered by changes to the git-annex branch, checks for changed
|
|
|
|
- config files, and reloads configs.
|
2012-10-24 17:35:43 +00:00
|
|
|
- Thread 19: PushNotifier
|
|
|
|
- Notifies other repositories of pushes, using out of band signaling.
|
|
|
|
- Thread 20: WebApp
|
2012-07-27 01:51:47 +00:00
|
|
|
- Spawns more threads as necessary to handle clients.
|
|
|
|
- Displays the DaemonStatus.
|
2012-06-13 16:36:33 +00:00
|
|
|
-
|
|
|
|
- ThreadState: (MVar)
|
|
|
|
- The Annex state is stored here, which allows resuscitating the
|
2012-06-28 17:04:02 +00:00
|
|
|
- Annex monad in IO actions run by the watcher and committer
|
2012-06-13 16:36:33 +00:00
|
|
|
- threads. Thus, a single state is shared amoung the threads, and
|
|
|
|
- only one at a time can access it.
|
2012-07-28 22:02:11 +00:00
|
|
|
- DaemonStatusHandle: (STM TMVar)
|
|
|
|
- The daemon's current status.
|
2012-06-13 16:36:33 +00:00
|
|
|
- ChangeChan: (STM TChan)
|
|
|
|
- Changes are indicated by writing to this channel. The committer
|
|
|
|
- reads from it.
|
2012-06-22 21:01:08 +00:00
|
|
|
- CommitChan: (STM TChan)
|
|
|
|
- Commits are indicated by writing to this channel. The pusher reads
|
|
|
|
- from it.
|
2012-06-26 21:33:34 +00:00
|
|
|
- FailedPushMap (STM TMVar)
|
|
|
|
- Failed pushes are indicated by writing to this TMVar. The push
|
|
|
|
- retrier blocks until they're available.
|
2012-07-03 14:58:40 +00:00
|
|
|
- TransferQueue (STM TChan)
|
|
|
|
- Transfers to make are indicated by writing to this channel.
|
2012-07-06 00:57:06 +00:00
|
|
|
- TransferSlots (QSemN)
|
|
|
|
- Count of the number of currently available transfer slots.
|
|
|
|
- Updated by the transfer watcher, this allows other threads
|
|
|
|
- to block until a slot is available.
|
|
|
|
- This MVar should only be manipulated from inside the Annex monad,
|
|
|
|
- which ensures it's accessed only after the ThreadState MVar.
|
2012-07-23 03:16:56 +00:00
|
|
|
- ScanRemotes (STM TMVar)
|
|
|
|
- Remotes that have been disconnected, and should be scanned
|
|
|
|
- are indicated by writing to this TMVar.
|
2012-10-24 17:35:43 +00:00
|
|
|
- BranchChanged (STM SampleVar)
|
|
|
|
- Changes to the git-annex branch are indicated by updating this
|
|
|
|
- SampleVar.
|
2012-10-24 19:42:02 +00:00
|
|
|
- PushNotifier (STM TChan)
|
2012-10-24 17:35:43 +00:00
|
|
|
- After successful pushes, this SampleVar is updated.
|
2012-09-08 23:57:15 +00:00
|
|
|
- UrlRenderer (MVar)
|
|
|
|
- A Yesod route rendering function is stored here. This allows
|
|
|
|
- things that need to render Yesod routes to block until the webapp
|
|
|
|
- has started up and such rendering is possible.
|
2012-06-13 16:36:33 +00:00
|
|
|
-}
|
|
|
|
|
2012-07-26 01:26:13 +00:00
|
|
|
{-# LANGUAGE CPP #-}
|
|
|
|
|
2012-06-13 16:36:33 +00:00
|
|
|
module Assistant where
|
|
|
|
|
2012-07-20 23:29:59 +00:00
|
|
|
import Assistant.Common
|
2012-06-13 16:36:33 +00:00
|
|
|
import Assistant.ThreadedMonad
|
|
|
|
import Assistant.DaemonStatus
|
2012-06-19 06:40:21 +00:00
|
|
|
import Assistant.Changes
|
2012-06-22 17:39:44 +00:00
|
|
|
import Assistant.Commits
|
2012-06-25 20:38:12 +00:00
|
|
|
import Assistant.Pushes
|
2012-07-23 03:16:56 +00:00
|
|
|
import Assistant.ScanRemotes
|
add ConfigMonitor thread
Monitors git-annex branch for changes, which are noticed by the Merger
thread whenever the branch ref is changed (either due to an incoming push,
or a local change), and refreshes cached config values for modified config
files.
Rate limited to run no more often than once per minute. This is important
because frequent git-annex branch changes happen when files are being
added, or transferred, etc.
A primary use case is that, when preferred content changes are made,
and get pushed to remotes, the remotes start honoring those settings.
Other use cases include propigating repository description and trust
changes to remotes, and learning when a remote has added a new special
remote, so the webapp can present the GUI to enable that special remote
locally.
Also added a uuid.log cache. All other config files already had caches.
2012-10-20 20:37:06 +00:00
|
|
|
import Assistant.BranchChange
|
2012-07-05 16:21:22 +00:00
|
|
|
import Assistant.TransferQueue
|
2012-07-06 20:39:07 +00:00
|
|
|
import Assistant.TransferSlots
|
2012-09-06 18:56:04 +00:00
|
|
|
import Assistant.Threads.DaemonStatus
|
2012-06-25 20:10:10 +00:00
|
|
|
import Assistant.Threads.Watcher
|
|
|
|
import Assistant.Threads.Committer
|
|
|
|
import Assistant.Threads.Pusher
|
|
|
|
import Assistant.Threads.Merger
|
2012-07-03 14:58:40 +00:00
|
|
|
import Assistant.Threads.TransferWatcher
|
2012-07-05 20:34:20 +00:00
|
|
|
import Assistant.Threads.Transferrer
|
2012-06-25 20:10:10 +00:00
|
|
|
import Assistant.Threads.SanityChecker
|
2012-07-19 17:01:41 +00:00
|
|
|
import Assistant.Threads.MountWatcher
|
2012-08-21 23:58:53 +00:00
|
|
|
import Assistant.Threads.NetWatcher
|
2012-07-23 03:16:56 +00:00
|
|
|
import Assistant.Threads.TransferScanner
|
2012-08-28 18:04:28 +00:00
|
|
|
import Assistant.Threads.TransferPoller
|
add ConfigMonitor thread
Monitors git-annex branch for changes, which are noticed by the Merger
thread whenever the branch ref is changed (either due to an incoming push,
or a local change), and refreshes cached config values for modified config
files.
Rate limited to run no more often than once per minute. This is important
because frequent git-annex branch changes happen when files are being
added, or transferred, etc.
A primary use case is that, when preferred content changes are made,
and get pushed to remotes, the remotes start honoring those settings.
Other use cases include propigating repository description and trust
changes to remotes, and learning when a remote has added a new special
remote, so the webapp can present the GUI to enable that special remote
locally.
Also added a uuid.log cache. All other config files already had caches.
2012-10-20 20:37:06 +00:00
|
|
|
import Assistant.Threads.ConfigMonitor
|
2012-10-24 18:39:38 +00:00
|
|
|
#ifdef WITH_XMPP
|
2012-10-24 17:35:43 +00:00
|
|
|
import Assistant.Threads.PushNotifier
|
2012-10-24 18:39:38 +00:00
|
|
|
#endif
|
2012-07-26 01:26:13 +00:00
|
|
|
#ifdef WITH_WEBAPP
|
2012-09-08 23:57:15 +00:00
|
|
|
import Assistant.WebApp
|
2012-07-26 01:26:13 +00:00
|
|
|
import Assistant.Threads.WebApp
|
2012-09-08 19:07:44 +00:00
|
|
|
#ifdef WITH_PAIRING
|
|
|
|
import Assistant.Threads.PairListener
|
|
|
|
#endif
|
2012-07-27 16:14:57 +00:00
|
|
|
#else
|
|
|
|
#warning Building without the webapp. You probably need to install Yesod..
|
2012-07-26 01:26:13 +00:00
|
|
|
#endif
|
2012-06-13 16:36:33 +00:00
|
|
|
import qualified Utility.Daemon
|
|
|
|
import Utility.LogFile
|
2012-06-28 17:37:03 +00:00
|
|
|
import Utility.ThreadScheduler
|
2012-06-13 16:36:33 +00:00
|
|
|
|
|
|
|
import Control.Concurrent
|
|
|
|
|
2012-09-06 18:56:04 +00:00
|
|
|
type NamedThread = IO () -> IO (String, IO ())
|
|
|
|
|
2012-08-01 20:10:26 +00:00
|
|
|
stopDaemon :: Annex ()
|
|
|
|
stopDaemon = liftIO . Utility.Daemon.stopDaemon =<< fromRepo gitAnnexPidFile
|
|
|
|
|
2012-08-30 17:29:06 +00:00
|
|
|
startDaemon :: Bool -> Bool -> Maybe (String -> FilePath -> IO ()) -> Annex ()
|
2012-07-27 19:33:24 +00:00
|
|
|
startDaemon assistant foreground webappwaiter
|
2012-06-13 16:36:33 +00:00
|
|
|
| foreground = do
|
2012-06-22 17:04:03 +00:00
|
|
|
showStart (if assistant then "assistant" else "watch") "."
|
2012-08-01 20:29:38 +00:00
|
|
|
liftIO . Utility.Daemon.lockPidFile =<< fromRepo gitAnnexPidFile
|
2012-06-13 16:36:33 +00:00
|
|
|
go id
|
|
|
|
| otherwise = do
|
|
|
|
logfd <- liftIO . openLog =<< fromRepo gitAnnexLogFile
|
|
|
|
pidfile <- fromRepo gitAnnexPidFile
|
|
|
|
go $ Utility.Daemon.daemonize logfd (Just pidfile) False
|
|
|
|
where
|
2012-08-01 20:10:26 +00:00
|
|
|
go d = startAssistant assistant d webappwaiter
|
|
|
|
|
2012-08-30 17:29:06 +00:00
|
|
|
startAssistant :: Bool -> (IO () -> IO ()) -> Maybe (String -> FilePath -> IO ()) -> Annex ()
|
2012-09-13 04:57:52 +00:00
|
|
|
startAssistant assistant daemonize webappwaiter = withThreadState $ \st -> do
|
|
|
|
checkCanWatch
|
|
|
|
dstatus <- startDaemonStatus
|
|
|
|
liftIO $ daemonize $ run dstatus st
|
2012-08-01 20:10:26 +00:00
|
|
|
where
|
2012-06-29 00:01:03 +00:00
|
|
|
run dstatus st = do
|
|
|
|
changechan <- newChangeChan
|
|
|
|
commitchan <- newCommitChan
|
|
|
|
pushmap <- newFailedPushMap
|
2012-07-05 16:21:22 +00:00
|
|
|
transferqueue <- newTransferQueue
|
2012-07-06 00:57:06 +00:00
|
|
|
transferslots <- newTransferSlots
|
2012-07-23 03:16:56 +00:00
|
|
|
scanremotes <- newScanRemoteMap
|
add ConfigMonitor thread
Monitors git-annex branch for changes, which are noticed by the Merger
thread whenever the branch ref is changed (either due to an incoming push,
or a local change), and refreshes cached config values for modified config
files.
Rate limited to run no more often than once per minute. This is important
because frequent git-annex branch changes happen when files are being
added, or transferred, etc.
A primary use case is that, when preferred content changes are made,
and get pushed to remotes, the remotes start honoring those settings.
Other use cases include propigating repository description and trust
changes to remotes, and learning when a remote has added a new special
remote, so the webapp can present the GUI to enable that special remote
locally.
Also added a uuid.log cache. All other config files already had caches.
2012-10-20 20:37:06 +00:00
|
|
|
branchhandle <- newBranchChangeHandle
|
2012-10-24 17:35:43 +00:00
|
|
|
pushnotifier <- newPushNotifier
|
2012-09-23 15:48:09 +00:00
|
|
|
#ifdef WITH_WEBAPP
|
2012-09-08 23:57:15 +00:00
|
|
|
urlrenderer <- newUrlRenderer
|
2012-09-23 15:48:09 +00:00
|
|
|
#endif
|
2012-09-06 18:56:04 +00:00
|
|
|
mapM_ (startthread dstatus)
|
2012-08-01 21:01:04 +00:00
|
|
|
[ watch $ commitThread st changechan commitchan transferqueue dstatus
|
2012-08-02 13:09:06 +00:00
|
|
|
#ifdef WITH_WEBAPP
|
2012-09-08 23:57:15 +00:00
|
|
|
, assist $ webAppThread (Just st) dstatus scanremotes transferqueue transferslots urlrenderer Nothing webappwaiter
|
2012-09-08 19:07:44 +00:00
|
|
|
#ifdef WITH_PAIRING
|
2012-09-11 01:55:59 +00:00
|
|
|
, assist $ pairListenerThread st dstatus scanremotes urlrenderer
|
2012-09-08 19:07:44 +00:00
|
|
|
#endif
|
2012-08-02 13:09:06 +00:00
|
|
|
#endif
|
2012-10-24 17:35:43 +00:00
|
|
|
, assist $ pushThread st dstatus commitchan pushmap pushnotifier
|
|
|
|
, assist $ pushRetryThread st dstatus pushmap pushnotifier
|
add ConfigMonitor thread
Monitors git-annex branch for changes, which are noticed by the Merger
thread whenever the branch ref is changed (either due to an incoming push,
or a local change), and refreshes cached config values for modified config
files.
Rate limited to run no more often than once per minute. This is important
because frequent git-annex branch changes happen when files are being
added, or transferred, etc.
A primary use case is that, when preferred content changes are made,
and get pushed to remotes, the remotes start honoring those settings.
Other use cases include propigating repository description and trust
changes to remotes, and learning when a remote has added a new special
remote, so the webapp can present the GUI to enable that special remote
locally.
Also added a uuid.log cache. All other config files already had caches.
2012-10-20 20:37:06 +00:00
|
|
|
, assist $ mergeThread st dstatus transferqueue branchhandle
|
when a Download finishes, queue Uploads
This ensures file propigate takes place in situations such as: Usb drive A
is connected to B. A's master branch is already in sync with B, but it is
being used to sneakernet some files around, so B downloads those. There is no
master branch change, so C does not request these files. B needs to upload
the files it just downloaded on to C, etc.
My first try at this, I saw loops happen. B uploaded to C, which then
tried to upload back to B (because it had not received the updated
git-annex branch from B yet). B already had the file, but it still created
a transfer info file from the incoming transfer, and its watcher saw
that be removed, and tried to upload back to C.
These loops should have been fixed by my previous commit. (They never
affected ssh remotes, only local ones, it seemed.) While C might still try
to upload to B, or to some other remote that already has the file, the
extra work dies out there.
2012-09-18 18:10:33 +00:00
|
|
|
, assist $ transferWatcherThread st dstatus transferqueue
|
2012-08-28 18:04:28 +00:00
|
|
|
, assist $ transferPollerThread st dstatus
|
2012-08-01 21:01:04 +00:00
|
|
|
, assist $ transfererThread st dstatus transferqueue transferslots
|
|
|
|
, assist $ daemonStatusThread st dstatus
|
|
|
|
, assist $ sanityCheckerThread st dstatus transferqueue changechan
|
2012-10-24 17:35:43 +00:00
|
|
|
, assist $ mountWatcherThread st dstatus scanremotes pushnotifier
|
|
|
|
, assist $ netWatcherThread st dstatus scanremotes pushnotifier
|
|
|
|
, assist $ netWatcherFallbackThread st dstatus scanremotes pushnotifier
|
2012-08-01 21:01:04 +00:00
|
|
|
, assist $ transferScannerThread st dstatus scanremotes transferqueue
|
2012-10-21 19:50:49 +00:00
|
|
|
, assist $ configMonitorThread st dstatus branchhandle commitchan
|
2012-10-24 18:39:38 +00:00
|
|
|
#ifdef WITH_XMPP
|
2012-10-25 20:51:01 +00:00
|
|
|
{- Bound thread, because TLS needs it. -}
|
|
|
|
, bound $ assist $ pushNotifierThread st dstatus pushnotifier
|
2012-10-24 18:39:38 +00:00
|
|
|
#endif
|
2012-08-01 21:01:04 +00:00
|
|
|
, watch $ watchThread st dstatus transferqueue changechan
|
2012-06-29 00:01:03 +00:00
|
|
|
]
|
|
|
|
waitForTermination
|
2012-10-25 19:30:49 +00:00
|
|
|
|
2012-10-25 20:51:01 +00:00
|
|
|
watch a = (forkIO, True, a)
|
|
|
|
assist a = (forkIO, False, a)
|
|
|
|
bound (_, watcher, t) = (forkOS, watcher, t)
|
|
|
|
startthread dstatus (runner, watcher, t)
|
|
|
|
| watcher || assistant = void $ runner $
|
2012-09-06 18:56:04 +00:00
|
|
|
runNamedThread dstatus t
|
2012-08-01 21:01:04 +00:00
|
|
|
| otherwise = noop
|