pid locking configuration and abstraction layer for git-annex

(not actually used anywhere yet)
This commit is contained in:
Joey Hess 2015-11-12 17:47:31 -04:00
parent 77b490bfba
commit aa4192aea6
Failed to extract signature
7 changed files with 131 additions and 1 deletions

17
Annex/LockPool.hs Normal file
View file

@ -0,0 +1,17 @@
{- Wraps Utility.LockPool, making pid locks be used when git-annex is so
- configured.
-
- Copyright 2015 Joey Hess <id@joeyh.name>
-
- Licensed under the GNU GPL version 3 or higher.
-}
{-# LANGUAGE CPP #-}
module Annex.LockPool (module X) where
#ifndef mingw32_HOST_OS
import Annex.LockPool.PosixOrPid as X
#else
import Utility.LockPool.Windows as X
#endif

View file

@ -0,0 +1,74 @@
{- Wraps Utility.LockPool, making pid locks be used when git-annex is so
- configured.
-
- Copyright 2015 Joey Hess <id@joeyh.name>
-
- Licensed under the GNU GPL version 3 or higher.
-}
module Annex.LockPool.PosixOrPid where
import Common.Annex
import qualified Annex
import qualified Utility.LockPool.Posix as Posix
import qualified Utility.LockPool.PidLock as Pid
import Utility.LockFile.Posix (openLockFile)
import Utility.LockPool.STM (LockFile)
import Utility.LockPool.LockHandle
import Utility.LockFile.LockStatus
import System.Posix
lockShared :: Maybe FileMode -> LockFile -> Annex LockHandle
lockShared m f = pidLock m f $ Posix.lockShared m f
lockExclusive :: Maybe FileMode -> LockFile -> Annex LockHandle
lockExclusive m f = pidLock m f $ Posix.lockExclusive m f
tryLockShared :: Maybe FileMode -> LockFile -> Annex (Maybe LockHandle)
tryLockShared m f = tryPidLock m f $ Posix.tryLockShared m f
tryLockExclusive :: Maybe FileMode -> LockFile -> Annex (Maybe LockHandle)
tryLockExclusive m f = tryPidLock m f $ Posix.tryLockExclusive m f
checkLocked :: LockFile -> Annex (Maybe Bool)
checkLocked f = Posix.checkLocked f
`pidLockCheck` Pid.checkLocked
getLockStatus :: LockFile -> Annex LockStatus
getLockStatus f = Posix.getLockStatus f
`pidLockCheck` Pid.getLockStatus
pidLockFile :: Annex (Maybe FilePath)
pidLockFile = ifM (annexPidLock <$> Annex.getGitConfig)
( Just <$> fromRepo gitAnnexPidLockFile
, pure Nothing
)
pidLockCheck :: IO a -> (LockFile -> IO a) -> Annex a
pidLockCheck posixcheck pidcheck =
liftIO . maybe posixcheck pidcheck =<< pidLockFile
pidLock :: Maybe FileMode -> LockFile -> IO LockHandle -> Annex LockHandle
pidLock m f posixlock = go =<< pidLockFile
where
go Nothing = liftIO posixlock
go (Just pidlock) = do
timeout <- annexPidLockTimeout <$> Annex.getGitConfig
liftIO $ do
dummyPosixLock m f
Pid.waitLock timeout pidlock
tryPidLock :: Maybe FileMode -> LockFile -> IO (Maybe LockHandle) -> Annex (Maybe LockHandle)
tryPidLock m f posixlock = liftIO . go =<< pidLockFile
where
go Nothing = posixlock
go (Just pidlock) = do
dummyPosixLock m f
Pid.tryLock pidlock
-- The posix lock file is created even when using pid locks, in order to
-- avoid complicating any code that might expect to be able to see that
-- lock file.
dummyPosixLock :: Maybe FileMode -> LockFile -> IO ()
dummyPosixLock m f = closeFd =<< openLockFile ReadLock m f

View file

@ -51,6 +51,7 @@ module Locations (
gitAnnexViewLog, gitAnnexViewLog,
gitAnnexIgnoredRefs, gitAnnexIgnoredRefs,
gitAnnexPidFile, gitAnnexPidFile,
gitAnnexPidLockFile,
gitAnnexDaemonStatusFile, gitAnnexDaemonStatusFile,
gitAnnexLogFile, gitAnnexLogFile,
gitAnnexFuzzTestLogFile, gitAnnexFuzzTestLogFile,
@ -334,6 +335,10 @@ gitAnnexIgnoredRefs r = gitAnnexDir r </> "ignoredrefs"
gitAnnexPidFile :: Git.Repo -> FilePath gitAnnexPidFile :: Git.Repo -> FilePath
gitAnnexPidFile r = gitAnnexDir r </> "daemon.pid" gitAnnexPidFile r = gitAnnexDir r </> "daemon.pid"
{- Pid lock file for pidlock mode -}
gitAnnexPidLockFile :: Git.Repo -> FilePath
gitAnnexPidLockFile r = gitAnnexDir r </> "pidlock"
{- Status file for daemon mode. -} {- Status file for daemon mode. -}
gitAnnexDaemonStatusFile :: Git.Repo -> FilePath gitAnnexDaemonStatusFile :: Git.Repo -> FilePath
gitAnnexDaemonStatusFile r = gitAnnexDir r </> "daemon.status" gitAnnexDaemonStatusFile r = gitAnnexDir r </> "daemon.status"

View file

@ -1,6 +1,6 @@
{- git-annex configuration {- git-annex configuration
- -
- Copyright 2012-2014 Joey Hess <id@joeyh.name> - Copyright 2012-2015 Joey Hess <id@joeyh.name>
- -
- Licensed under the GNU GPL version 3 or higher. - Licensed under the GNU GPL version 3 or higher.
-} -}
@ -26,6 +26,7 @@ import Types.Difference
import Types.RefSpec import Types.RefSpec
import Utility.HumanTime import Utility.HumanTime
import Utility.Gpg (GpgCmd, mkGpgCmd) import Utility.Gpg (GpgCmd, mkGpgCmd)
import Utility.ThreadScheduler (Seconds(..))
{- Main git-annex settings. Each setting corresponds to a git-config key {- Main git-annex settings. Each setting corresponds to a git-config key
- such as annex.foo -} - such as annex.foo -}
@ -62,6 +63,8 @@ data GitConfig = GitConfig
, annexDifferences :: Differences , annexDifferences :: Differences
, annexUsedRefSpec :: Maybe RefSpec , annexUsedRefSpec :: Maybe RefSpec
, annexVerify :: Bool , annexVerify :: Bool
, annexPidLock :: Bool
, annexPidLockTimeout :: Seconds
, coreSymlinks :: Bool , coreSymlinks :: Bool
, coreSharedRepository :: SharedRepository , coreSharedRepository :: SharedRepository
, gcryptId :: Maybe String , gcryptId :: Maybe String
@ -105,6 +108,9 @@ extractGitConfig r = GitConfig
, annexUsedRefSpec = either (const Nothing) Just . parseRefSpec , annexUsedRefSpec = either (const Nothing) Just . parseRefSpec
=<< getmaybe (annex "used-refspec") =<< getmaybe (annex "used-refspec")
, annexVerify = getbool (annex "verify") True , annexVerify = getbool (annex "verify") True
, annexPidLock = getbool (annex "pidlock") False
, annexPidLockTimeout = Seconds $ fromMaybe 300 $
getmayberead (annex "pidlocktimeout")
, coreSymlinks = getbool "core.symlinks" True , coreSymlinks = getbool "core.symlinks" True
, coreSharedRepository = getSharedRepository r , coreSharedRepository = getSharedRepository r
, gcryptId = getmaybe "core.gcrypt-id" , gcryptId = getmaybe "core.gcrypt-id"

View file

@ -16,6 +16,8 @@ module Utility.LockFile.Posix (
LockStatus(..), LockStatus(..),
dropLock, dropLock,
checkSaneLock, checkSaneLock,
LockRequest(..),
openLockFile,
) where ) where
import Utility.Exception import Utility.Exception

2
debian/changelog vendored
View file

@ -27,6 +27,8 @@ git-annex (5.20151102.2) UNRELEASED; urgency=medium
dead repo. dead repo.
* assistant: Pass ssh-options through 3 more git pull/push calls * assistant: Pass ssh-options through 3 more git pull/push calls
that were missed before. that were missed before.
* Added annex.pidlock and annex.pidlocktimeout configuration to support
filesystems where POSIX fcntl locks cannot be used.
-- Joey Hess <id@joeyh.name> Wed, 04 Nov 2015 12:50:20 -0400 -- Joey Hess <id@joeyh.name> Wed, 04 Nov 2015 12:50:20 -0400

View file

@ -965,6 +965,30 @@ Here are all the supported configuration settings.
which does not support symbolic links, or hard links, or unix permissions. which does not support symbolic links, or hard links, or unix permissions.
This is automatically probed by "git annex init". This is automatically probed by "git annex init".
* `annex.pidlock`
Normally, git-annex uses fine-grained lock files to allow multiple
processes to run concurrently without getting in each others' way.
That works great, unless you are using git-annex on a filesystem that
does not support POSIX fcntl locks. This is sometimes the case when
using NFS or Lustre filesystems.
To support such situations, you can set annex.pidlock to true, and it
will fall back to a single top-level pid file lock.
(Although, often, you'd really be better off fixing your networked
filesystem configuration to support POSIX locks..)
* `annex.pidlocktimeout`
When using pid lock files, it's possible for a stale lock file to get
left behind by previous run of git-annex that crashed or was interrupted.
This is mostly avoided, but can occur especially when using a network
file system.
git-annex will wait up to this many seconds for the pid lock
file to go away, and will then abort if it cannot continue. Default: 300
* `remote.<name>.annex-cost` * `remote.<name>.annex-cost`
When determining which repository to When determining which repository to