pid locking configuration and abstraction layer for git-annex
(not actually used anywhere yet)
This commit is contained in:
parent
77b490bfba
commit
aa4192aea6
7 changed files with 131 additions and 1 deletions
17
Annex/LockPool.hs
Normal file
17
Annex/LockPool.hs
Normal 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
|
74
Annex/LockPool/PosixOrPid.hs
Normal file
74
Annex/LockPool/PosixOrPid.hs
Normal 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
|
|
@ -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"
|
||||||
|
|
|
@ -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"
|
||||||
|
|
|
@ -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
2
debian/changelog
vendored
|
@ -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
|
||||||
|
|
||||||
|
|
|
@ -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
|
||||||
|
|
Loading…
Reference in a new issue