git-annex/Command/SendKey.hs
Joey Hess 81d402216d cache the serialization of a Key
This will speed up the common case where a Key is deserialized from
disk, but is then serialized to build eg, the path to the annex object.

Previously attempted in 4536c93bb2
and reverted in 96aba8eff7.
The problems mentioned in the latter commit are addressed now:

Read/Show of KeyData is backwards-compatible with Read/Show of Key from before
this change, so Types.Distribution will keep working.

The Eq instance is fixed.

Also, Key has smart constructors, avoiding needing to remember to update
the cached serialization.

Used git-annex benchmark:
  find is 7% faster
  whereis is 3% faster
  get when all files are already present is 5% faster
Generally, the benchmarks are running 0.1 seconds faster per 2000 files,
on a ram disk in my laptop.
2019-11-22 17:49:16 -04:00

63 lines
1.8 KiB
Haskell

{- git-annex command
-
- Copyright 2010,2012 Joey Hess <id@joeyh.name>
-
- Licensed under the GNU AGPL version 3 or higher.
-}
module Command.SendKey where
import Command
import Annex.Content
import Annex
import Utility.Rsync
import Annex.Transfer
import qualified CmdLine.GitAnnexShell.Fields as Fields
import Utility.Metered
import System.Log.Logger
cmd :: Command
cmd = noCommit $
command "sendkey" SectionPlumbing
"runs rsync in server mode to send content"
paramKey (withParams seek)
seek :: CmdParams -> CommandSeek
seek = withKeys (commandAction . start)
start :: Key -> CommandStart
start key = do
opts <- filterRsyncSafeOptions . maybe [] words
<$> getField "RsyncOptions"
ifM (inAnnex key)
( fieldTransfer Upload key $ \_p ->
sendAnnex key rollback $ liftIO . rsyncServerSend (map Param opts)
, do
warning "requested key is not present"
liftIO exitFailure
)
where
{- No need to do any rollback; when sendAnnex fails, a nonzero
- exit will be propigated, and the remote will know the transfer
- failed. -}
rollback = noop
fieldTransfer :: Direction -> Key -> (MeterUpdate -> Annex Bool) -> CommandStart
fieldTransfer direction key a = do
liftIO $ debugM "fieldTransfer" "transfer start"
afile <- AssociatedFile <$> Fields.getField Fields.associatedFile
ok <- maybe (a $ const noop)
-- Using noRetry here because we're the sender.
(\u -> runner (Transfer direction (toUUID u) (fromKey id key)) afile noRetry a)
=<< Fields.getField Fields.remoteUUID
liftIO $ debugM "fieldTransfer" "transfer done"
liftIO $ exitBool ok
where
{- Allow the key to be sent to the remote even if there seems to be
- another transfer of that key going on to that remote.
- That one may be stale, etc.
-}
runner
| direction == Upload = alwaysRunTransfer
| otherwise = runTransfer