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:
Joey Hess 2018-10-22 12:59:10 -04:00
parent fc26fd059b
commit c24e255de1
No known key found for this signature in database
GPG key ID: DB12DB0FF05F8F38
3 changed files with 22 additions and 9 deletions

View file

@ -19,6 +19,8 @@ git-annex (6.20181012) UNRELEASED; urgency=medium
GIT_ANNEX_PACKAGE_INSTALL set. (For Neurodebian packages.)
* v6: Fix database inconsistency that could cause git-annex to
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

View file

@ -89,23 +89,32 @@ adjustExportable r = case M.lookup "exporttree" (config r) of
}
isexport = do
db <- openDb (uuid r)
updateflag <- liftIO $ newTVarIO Nothing
updateflag <- liftIO newEmptyTMVarIO
let updateonce = liftIO $ atomically $
ifM (isEmptyTMVar updateflag)
( do
putTMVar updateflag ()
-- When multiple threads run this, all except the first
-- will block until the first runs doneupdateonce.
-- Returns True when an update should be done and False
-- when the update has already been done.
let startupdateonce = liftIO $ atomically $
readTVar updateflag >>= \case
Nothing -> do
writeTVar updateflag (Just 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
-- if the export log is different than the database and
-- updates the database, to notice when an export has been
-- updated from another repository.
let getexportlocs = \k -> do
whenM updateonce $
updateExportTreeFromLog db
bracket startupdateonce doneupdateonce $ \updatenow ->
when updatenow $
updateExportTreeFromLog db
liftIO $ getExportTree db k
return $ r

View file

@ -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]]
> [[fixed|done]] --[[Joey]]