summaryrefslogtreecommitdiff
path: root/Assistant/Threads/ConfigMonitor.hs
blob: fe98b10e8d38b0c37a9a3c1503cc76dc0d840bc0 (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
{- git-annex assistant config monitor thread
 -
 - Copyright 2012 Joey Hess <joey@kitenet.net>
 -
 - Licensed under the GNU GPL version 3 or higher.
 -}

module Assistant.Threads.ConfigMonitor where

import Assistant.Common
import Assistant.BranchChange
import Assistant.DaemonStatus
import Assistant.Commits
import Utility.ThreadScheduler
import Logs.UUID
import Logs.Trust
import Logs.Remote
import Logs.PreferredContent
import Logs.Group
import Remote.List (remoteListRefresh)
import qualified Git.LsTree as LsTree
import qualified Annex.Branch

import qualified Data.Set as S

thisThread :: ThreadName
thisThread = "ConfigMonitor"

{- This thread detects when configuration changes have been made to the
 - git-annex branch and reloads cached configuration.
 -
 - If the branch is frequently changing, it's checked for configuration
 - changes no more often than once every 60 seconds. On the other hand,
 - if the branch has not changed in a while, configuration changes will
 - be detected immediately.
 -}
configMonitorThread :: NamedThread
configMonitorThread = NamedThread "ConfigMonitor" $ loop =<< getConfigs
  where
	loop old = do
		liftIO $ threadDelaySeconds (Seconds 60)
		waitBranchChange <<~ branchChangeHandle
		new <- getConfigs
		when (old /= new) $ do
			let changedconfigs = new `S.difference` old
			debug $ "reloading config" : 
				map fst (S.toList changedconfigs)
			reloadConfigs new
			{- Record a commit to get this config
			 - change pushed out to remotes. -}
			recordCommit <<~ commitChan
		loop new

{- Config files, and their checksums. -}
type Configs = S.Set (FilePath, String)

{- All git-annex's config files, and actions to run when they change. -}
configFilesActions :: [(FilePath, Annex ())]
configFilesActions =
	[ (uuidLog, void $ uuidMapLoad)
	, (remoteLog, void remoteListRefresh)
	, (trustLog, void trustMapLoad)
	, (groupLog, void groupMapLoad)
	-- Preferred content settings depend on most of the other configs,
	-- so will be reloaded whenever any configs change.
	, (preferredContentLog, noop)
	]

reloadConfigs :: Configs -> Assistant ()
reloadConfigs changedconfigs = do
	liftAnnex $ do
		sequence_ as
		void preferredContentMapLoad
	{- Changes to the remote log, or the trust log, can affect the
	 - syncRemotes list -}
	when (Logs.Remote.remoteLog `elem` fs || Logs.Trust.trustLog `elem` fs) $
		liftAnnex . updateSyncRemotes =<< getAssistant daemonStatusHandle
  where
	(fs, as) = unzip $ filter (flip S.member changedfiles . fst)
		configFilesActions
	changedfiles = S.map fst changedconfigs

getConfigs :: Assistant Configs
getConfigs = S.fromList . map extract
	<$> liftAnnex (inRepo $ LsTree.lsTreeFiles Annex.Branch.fullname files)
  where
	files = map fst configFilesActions
	extract treeitem = (LsTree.file treeitem, LsTree.sha treeitem)