use separate lock from content file in v9

Windows has always used a separate lock file, but on unix, the content
file itself was locked, and in v9 that changes to also use a separate
lock file.

This needs to be tested more. Eg, what happens after dropping a file;
does the the content lock file get deleted too, or linger around?

Sponsored-by: Dartmouth College's Datalad project
This commit is contained in:
Joey Hess 2022-01-11 17:01:11 -04:00
parent 43f9d967ff
commit 3c042606c2
No known key found for this signature in database
GPG key ID: DB12DB0FF05F8F38
2 changed files with 25 additions and 14 deletions

View file

@ -115,8 +115,8 @@ lockContentShared key a = lockContentUsing lock key notpresent $
where where
notpresent = giveup $ "failed to lock content: not present" notpresent = giveup $ "failed to lock content: not present"
#ifndef mingw32_HOST_OS #ifndef mingw32_HOST_OS
lock contentfile Nothing = tryLockShared Nothing contentfile
lock _ (Just lockfile) = posixLocker tryLockShared lockfile lock _ (Just lockfile) = posixLocker tryLockShared lockfile
lock contentfile Nothing = tryLockShared Nothing contentfile
#else #else
lock = winLocker lockShared lock = winLocker lockShared
#endif #endif
@ -126,21 +126,25 @@ lockContentShared key a = lockContentUsing lock key notpresent $
- -
- If locking fails, throws an exception rather than running the action. - If locking fails, throws an exception rather than running the action.
- -
- But, if locking fails because the the content is not present, runs the - If locking fails because the the content is not present, runs the
- fallback action instead. - fallback action instead. However, the content is not guaranteed to be
- present when this succeeds.
-} -}
lockContentForRemoval :: Key -> Annex a -> (ContentRemovalLock -> Annex a) -> Annex a lockContentForRemoval :: Key -> Annex a -> (ContentRemovalLock -> Annex a) -> Annex a
lockContentForRemoval key fallback a = lockContentUsing lock key fallback $ lockContentForRemoval key fallback a = lockContentUsing lock key fallback $
a (ContentRemovalLock key) a (ContentRemovalLock key)
where where
#ifndef mingw32_HOST_OS #ifndef mingw32_HOST_OS
{- Since content files are stored with the write bit disabled, have
- to fiddle with permissions to open for an exclusive lock. -}
lock contentfile Nothing = bracket_
(thawContent contentfile)
(freezeContent contentfile)
(tryLockExclusive Nothing contentfile)
lock _ (Just lockfile) = posixLocker tryLockExclusive lockfile lock _ (Just lockfile) = posixLocker tryLockExclusive lockfile
{- No lock file, so the content file itself is locked.
- Since content files are stored with the write bit
- disabled, have to fiddle with permissions to open
- for an exclusive lock. -}
lock contentfile Nothing =
bracket_
(thawContent contentfile)
(freezeContent contentfile)
(tryLockExclusive Nothing contentfile)
#else #else
lock = winLocker lockExclusive lock = winLocker lockExclusive
#endif #endif
@ -170,7 +174,7 @@ winLocker _ _ Nothing = return Nothing
{- The fallback action is run if the ContentLocker throws an IO exception {- The fallback action is run if the ContentLocker throws an IO exception
- and the content is not present. It's not guaranteed to always run when - and the content is not present. It's not guaranteed to always run when
- the content is not present, because the content file is not always - the content is not present, because the content file is not always
- the file that is locked eg on Windows a different file is locked. -} - the file that is locked. -}
lockContentUsing :: ContentLocker -> Key -> Annex a -> Annex a -> Annex a lockContentUsing :: ContentLocker -> Key -> Annex a -> Annex a -> Annex a
lockContentUsing locker key fallback a = do lockContentUsing locker key fallback a = do
contentfile <- calcRepo (gitAnnexLocation key) contentfile <- calcRepo (gitAnnexLocation key)

View file

@ -24,6 +24,7 @@ import Annex.Content.Presence.LowLevel
import Annex.Common import Annex.Common
import qualified Annex import qualified Annex
import Annex.LockPool import Annex.LockPool
import Annex.Version
import qualified Database.Keys import qualified Database.Keys
import Annex.InodeSentinal import Annex.InodeSentinal
import Utility.InodeCache import Utility.InodeCache
@ -115,13 +116,19 @@ inAnnexSafe key = inAnnex' (fromMaybe True) (Just False) go key
) )
#endif #endif
{- Windows has to use a separate lock file from the content, since
- locking the actual content file would interfere with the user's
- use of it. -}
contentLockFile :: Key -> Annex (Maybe RawFilePath) contentLockFile :: Key -> Annex (Maybe RawFilePath)
#ifndef mingw32_HOST_OS #ifndef mingw32_HOST_OS
contentLockFile _ = pure Nothing {- Older versions of git-annex locked content files themselves, but newer
- versions use a separate lock file, to better support repos shared
- amoung users in eg a group. -}
contentLockFile key = ifM (versionNeedsWritableContentFiles <$> getVersion)
( pure Nothing
, Just <$> calcRepo (gitAnnexContentLock key)
)
#else #else
{- Windows always has to use a separate lock file from the content, since
- locking the actual content file would interfere with the user's
- use of it. -}
contentLockFile key = Just <$> calcRepo (gitAnnexContentLock key) contentLockFile key = Just <$> calcRepo (gitAnnexContentLock key)
#endif #endif