Fix concurrency bug that occurred on the first download from an exporttree remote
Block other threads while the export database is being constructed (or updated) by the first thread to try to access it. This work is supported by the NIH-funded NICEMAN (ReproNim TR&D3) project.
This commit is contained in:
parent
fc26fd059b
commit
c24e255de1
3 changed files with 22 additions and 9 deletions
|
@ -19,6 +19,8 @@ git-annex (6.20181012) UNRELEASED; urgency=medium
|
||||||
GIT_ANNEX_PACKAGE_INSTALL set. (For Neurodebian packages.)
|
GIT_ANNEX_PACKAGE_INSTALL set. (For Neurodebian packages.)
|
||||||
* v6: Fix database inconsistency that could cause git-annex to
|
* v6: Fix database inconsistency that could cause git-annex to
|
||||||
get confused about whether a locked file's content was present.
|
get confused about whether a locked file's content was present.
|
||||||
|
* Fix concurrency bug that occurred on the first download from an
|
||||||
|
exporttree remote.
|
||||||
|
|
||||||
-- Joey Hess <id@joeyh.name> Sat, 13 Oct 2018 00:52:02 -0400
|
-- Joey Hess <id@joeyh.name> Sat, 13 Oct 2018 00:52:02 -0400
|
||||||
|
|
||||||
|
|
|
@ -89,23 +89,32 @@ adjustExportable r = case M.lookup "exporttree" (config r) of
|
||||||
}
|
}
|
||||||
isexport = do
|
isexport = do
|
||||||
db <- openDb (uuid r)
|
db <- openDb (uuid r)
|
||||||
|
updateflag <- liftIO $ newTVarIO Nothing
|
||||||
|
|
||||||
updateflag <- liftIO newEmptyTMVarIO
|
-- When multiple threads run this, all except the first
|
||||||
let updateonce = liftIO $ atomically $
|
-- will block until the first runs doneupdateonce.
|
||||||
ifM (isEmptyTMVar updateflag)
|
-- Returns True when an update should be done and False
|
||||||
( do
|
-- when the update has already been done.
|
||||||
putTMVar updateflag ()
|
let startupdateonce = liftIO $ atomically $
|
||||||
|
readTVar updateflag >>= \case
|
||||||
|
Nothing -> do
|
||||||
|
writeTVar updateflag (Just True)
|
||||||
return True
|
return True
|
||||||
, return False
|
Just True -> retry
|
||||||
)
|
Just False -> return False
|
||||||
|
let doneupdateonce = \updated ->
|
||||||
|
when updated $
|
||||||
|
liftIO $ atomically $
|
||||||
|
writeTVar updateflag (Just False)
|
||||||
|
|
||||||
-- Get export locations for a key. Checks once
|
-- Get export locations for a key. Checks once
|
||||||
-- if the export log is different than the database and
|
-- if the export log is different than the database and
|
||||||
-- updates the database, to notice when an export has been
|
-- updates the database, to notice when an export has been
|
||||||
-- updated from another repository.
|
-- updated from another repository.
|
||||||
let getexportlocs = \k -> do
|
let getexportlocs = \k -> do
|
||||||
whenM updateonce $
|
bracket startupdateonce doneupdateonce $ \updatenow ->
|
||||||
updateExportTreeFromLog db
|
when updatenow $
|
||||||
|
updateExportTreeFromLog db
|
||||||
liftIO $ getExportTree db k
|
liftIO $ getExportTree db k
|
||||||
|
|
||||||
return $ r
|
return $ r
|
||||||
|
|
|
@ -47,3 +47,5 @@ get sub-01/ses-01/func/sub-01_ses-01_task-Stroop_acq-cf0AP_run-03_physio.tsv.gz
|
||||||
|
|
||||||
|
|
||||||
[[!meta author=yoh]]
|
[[!meta author=yoh]]
|
||||||
|
|
||||||
|
> [[fixed|done]] --[[Joey]]
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue