Improved locking when multiple git-annex processes are writing to the .git/index file

This commit is contained in:
Joey Hess 2019-05-06 15:15:12 -04:00
parent 4bc99e4c21
commit b03e65d260
No known key found for this signature in database
GPG key ID: DB12DB0FF05F8F38
6 changed files with 18 additions and 21 deletions

View file

@ -75,7 +75,6 @@ import Control.Concurrent
import Control.Concurrent.Async import Control.Concurrent.Async
import Control.Concurrent.STM import Control.Concurrent.STM
import qualified Control.Monad.Fail as Fail import qualified Control.Monad.Fail as Fail
import qualified Control.Concurrent.SSem as SSem
import qualified Data.Map.Strict as M import qualified Data.Map.Strict as M
import qualified Data.Set as S import qualified Data.Set as S
@ -116,7 +115,6 @@ data AnnexState = AnnexState
, daemon :: Bool , daemon :: Bool
, branchstate :: BranchState , branchstate :: BranchState
, repoqueue :: Maybe Git.Queue.Queue , repoqueue :: Maybe Git.Queue.Queue
, repoqueuesem :: SSem.SSem
, catfilehandles :: M.Map FilePath CatFileHandle , catfilehandles :: M.Map FilePath CatFileHandle
, hashobjecthandle :: Maybe HashObjectHandle , hashobjecthandle :: Maybe HashObjectHandle
, checkattrhandle :: Maybe CheckAttrHandle , checkattrhandle :: Maybe CheckAttrHandle
@ -159,7 +157,6 @@ newState c r = do
emptyactivekeys <- newTVarIO M.empty emptyactivekeys <- newTVarIO M.empty
o <- newMessageState o <- newMessageState
sc <- newTMVarIO False sc <- newTMVarIO False
qsem <- SSem.new 1
return $ AnnexState return $ AnnexState
{ repo = r { repo = r
, repoadjustment = return , repoadjustment = return
@ -175,7 +172,6 @@ newState c r = do
, daemon = False , daemon = False
, branchstate = startBranchState , branchstate = startBranchState
, repoqueue = Nothing , repoqueue = Nothing
, repoqueuesem = qsem
, catfilehandles = M.empty , catfilehandles = M.empty
, hashobjecthandle = Nothing , hashobjecthandle = Nothing
, checkattrhandle = Nothing , checkattrhandle = Nothing

View file

@ -43,9 +43,7 @@ dupState = do
st <- Annex.getState id st <- Annex.getState id
return $ st return $ st
{ Annex.workers = [] { Annex.workers = []
-- each thread has its own repoqueue, but the repoqueuesem -- each thread has its own repoqueue
-- is shared to prevent more than one thread flushing its
-- queue at the same time
, Annex.repoqueue = Nothing , Annex.repoqueue = Nothing
-- avoid sharing eg, open file handles -- avoid sharing eg, open file handles
, Annex.catfilehandles = M.empty , Annex.catfilehandles = M.empty

View file

@ -61,6 +61,7 @@ module Annex.Locations (
gitAnnexMergeDir, gitAnnexMergeDir,
gitAnnexJournalDir, gitAnnexJournalDir,
gitAnnexJournalLock, gitAnnexJournalLock,
gitAnnexGitQueueLock,
gitAnnexPreCommitLock, gitAnnexPreCommitLock,
gitAnnexMergeLock, gitAnnexMergeLock,
gitAnnexIndex, gitAnnexIndex,
@ -410,6 +411,11 @@ gitAnnexJournalDir r = addTrailingPathSeparator $ gitAnnexDir r </> "journal"
gitAnnexJournalLock :: Git.Repo -> FilePath gitAnnexJournalLock :: Git.Repo -> FilePath
gitAnnexJournalLock r = gitAnnexDir r </> "journal.lck" gitAnnexJournalLock r = gitAnnexDir r </> "journal.lck"
{- Lock file for flushing a git queue that writes to the git index or
- other git state that should only have one writer at a time. -}
gitAnnexGitQueueLock :: Git.Repo -> FilePath
gitAnnexGitQueueLock r = gitAnnexDir r </> "gitqueue.lck"
{- Lock file for the pre-commit hook. -} {- Lock file for the pre-commit hook. -}
gitAnnexPreCommitLock :: Git.Repo -> FilePath gitAnnexPreCommitLock :: Git.Repo -> FilePath
gitAnnexPreCommitLock r = gitAnnexDir r </> "precommit.lck" gitAnnexPreCommitLock r = gitAnnexDir r </> "precommit.lck"

View file

@ -1,6 +1,6 @@
{- git-annex command queue {- git-annex command queue
- -
- Copyright 2011, 2012 Joey Hess <id@joeyh.name> - Copyright 2011, 2012, 2019 Joey Hess <id@joeyh.name>
- -
- Licensed under the GNU AGPL version 3 or higher. - Licensed under the GNU AGPL version 3 or higher.
-} -}
@ -20,11 +20,10 @@ module Annex.Queue (
import Annex.Common import Annex.Common
import Annex hiding (new) import Annex hiding (new)
import Annex.LockFile
import qualified Git.Queue import qualified Git.Queue
import qualified Git.UpdateIndex import qualified Git.UpdateIndex
import qualified Control.Concurrent.SSem as SSem
{- Adds a git command to the queue. -} {- Adds a git command to the queue. -}
addCommand :: String -> [CommandParam] -> [FilePath] -> Annex () addCommand :: String -> [CommandParam] -> [FilePath] -> Annex ()
addCommand command params files = do addCommand command params files = do
@ -59,20 +58,14 @@ flush = do
store =<< flush' q store =<< flush' q
{- When there are multiple worker threads, each has its own queue. {- When there are multiple worker threads, each has its own queue.
- And of course multiple git-annex processes may be running each with its
- own queue.
- -
- But, flushing two queues at the same time could lead to failures due to - But, flushing two queues at the same time could lead to failures due to
- git locking files. So, only one queue is allowed to flush at a time. - git locking files. So, only one queue is allowed to flush at a time.
- The repoqueuesem is shared between threads.
-} -}
flush' :: Git.Queue.Queue -> Annex Git.Queue.Queue flush' :: Git.Queue.Queue -> Annex Git.Queue.Queue
flush' q = bracket lock unlock go flush' q = withExclusiveLock gitAnnexGitQueueLock $ do
where
lock = do
s <- getState repoqueuesem
liftIO $ SSem.wait s
return s
unlock = liftIO . SSem.signal
go _ = do
showStoringStateAction showStoringStateAction
inRepo $ Git.Queue.flush q inRepo $ Git.Queue.flush q

View file

@ -2,6 +2,8 @@ git-annex (7.20190504) UNRELEASED; urgency=medium
* Fix reversion in last release that caused wrong tree to be written * Fix reversion in last release that caused wrong tree to be written
to remote tracking branch after an export of a subtree. to remote tracking branch after an export of a subtree.
* Improved locking when multiple git-annex processes are writing to
the .git/index file
-- Joey Hess <id@joeyh.name> Mon, 06 May 2019 13:52:02 -0400 -- Joey Hess <id@joeyh.name> Mon, 06 May 2019 13:52:02 -0400

View file

@ -9,3 +9,5 @@ at a time. That locking is handled in `Annex.Queue.flush'` using a
semaphore. semaphore.
Seems that it would be better to use a lock file. --[[Joey]] Seems that it would be better to use a lock file. --[[Joey]]
> [[done]] --[[Joey]]