git-annex/Assistant/Threads/Transferrer.hs

116 lines
3.6 KiB
Haskell
Raw Normal View History

2012-07-05 20:34:20 +00:00
{- git-annex assistant data transferrer thread
-
- Copyright 2012 Joey Hess <joey@kitenet.net>
-
- Licensed under the GNU GPL version 3 or higher.
-}
module Assistant.Threads.Transferrer where
import Assistant.Common
2012-07-05 20:34:20 +00:00
import Assistant.DaemonStatus
import Assistant.TransferQueue
import Assistant.TransferSlots
2012-08-06 21:09:23 +00:00
import Assistant.Alert
import Assistant.Commits
2012-07-05 20:34:20 +00:00
import Logs.Transfer
import Logs.Location
2012-07-05 20:34:20 +00:00
import Annex.Content
import qualified Remote
import Types.Key
import Locations.UserConfig
2012-07-05 20:34:20 +00:00
import System.Process (create_group)
2012-07-05 20:34:20 +00:00
{- For now only one transfer is run at a time. -}
maxTransfers :: Int
maxTransfers = 1
{- Dispatches transfers from the queue. -}
transfererThread :: NamedThread
transfererThread = NamedThread "Transferr" $ do
program <- liftIO readProgramFile
transferqueue <- getAssistant transferQueue
dstatus <- getAssistant daemonStatusHandle
slots <- getAssistant transferSlots
starter <- asIO2 $ startTransfer program
liftIO $ forever $ inTransferSlot dstatus slots $
maybe (return Nothing) (uncurry starter)
=<< getNextTransfer transferqueue dstatus notrunning
where
{- Skip transfers that are already running. -}
notrunning = isNothing . startedTime
2012-07-05 20:34:20 +00:00
2012-08-29 21:32:41 +00:00
{- By the time this is called, the daemonstatus's transfer map should
- already have been updated to include the transfer. -}
startTransfer :: FilePath -> Transfer -> TransferInfo -> Assistant (Maybe (Transfer, TransferInfo, IO ()))
startTransfer program t info = case (transferRemote info, associatedFile info) of
(Just remote, Just file) -> ifM (liftAnnex $ shouldTransfer t info)
( do
debug [ "Transferring:" , show t ]
notifyTransfer <<~ daemonStatusHandle
tp <- asIO2 transferprocess
return $ Just (t, info, tp remote file)
, do
debug [ "Skipping unnecessary transfer:" , show t ]
void $ flip removeTransfer t <<~ daemonStatusHandle
return Nothing
)
_ -> return Nothing
where
direction = transferDirection t
isdownload = direction == Download
transferprocess remote file = void $ do
(_, _, _, pid)
<- liftIO $ createProcess (proc program $ toCommand params)
{ create_group = True }
{- Alerts are only shown for successful transfers.
- Transfers can temporarily fail for many reasons,
- so there's no point in bothering the user about
- those. The assistant should recover.
-
- Also, after a successful transfer, the location
- log has changed. Indicate that a commit has been
- made, in order to queue a push of the git-annex
- branch out to remotes that did not participate
- in the transfer.
-}
whenM (liftIO $ (==) ExitSuccess <$> waitForProcess pid) $ do
dstatus <- getAssistant daemonStatusHandle
liftIO $ void $ addAlert dstatus $
makeAlertFiller True $
transferFileAlert direction True file
2012-10-29 23:35:18 +00:00
recordCommit
where
params =
[ Param "transferkey"
, Param "--quiet"
, Param $ key2file $ transferKey t
, Param $ if isdownload
then "--from"
else "--to"
, Param $ Remote.name remote
, Param "--file"
, File file
]
{- Checks if the file to download is already present, or the remote
- being uploaded to isn't known to have the file. -}
shouldTransfer :: Transfer -> TransferInfo -> Annex Bool
shouldTransfer t info
| transferDirection t == Download =
not <$> inAnnex key
| transferDirection t == Upload =
{- Trust the location log to check if the
- remote already has the key. This avoids
- a roundtrip to the remote. -}
case transferRemote info of
Nothing -> return False
Just remote ->
notElem (Remote.uuid remote)
<$> loggedLocations key
| otherwise = return False
where
key = transferKey t