diff options
author | Joey Hess <joey@kitenet.net> | 2012-06-26 17:33:34 -0400 |
---|---|---|
committer | Joey Hess <joey@kitenet.net> | 2012-06-26 19:21:44 -0400 |
commit | 67c8ef7de25ad6f433db2fa5d5fc764dd515a5b2 (patch) | |
tree | 3666619b0752df6c336fdbac270e09dbd125bcec /Assistant/Pushes.hs | |
parent | e0a65247aebb8a821f4f0b717d39a4a35136a2e6 (diff) |
use a TMVar
SampleMVar won't work; between getting the current value and changing
it, another thread could made a change, which would get lost.
TMVar works well; this update situation is handled by atomic transactions.
Diffstat (limited to 'Assistant/Pushes.hs')
-rw-r--r-- | Assistant/Pushes.hs | 49 |
1 files changed, 29 insertions, 20 deletions
diff --git a/Assistant/Pushes.hs b/Assistant/Pushes.hs index 61d2b798b..f411dda07 100644 --- a/Assistant/Pushes.hs +++ b/Assistant/Pushes.hs @@ -8,30 +8,39 @@ module Assistant.Pushes where import Common.Annex -import Control.Concurrent.SampleVar +import Control.Concurrent.STM import Data.Time.Clock import qualified Data.Map as M {- Track the most recent push failure for each remote. -} type PushMap = M.Map Remote UTCTime -type FailedPushes = SampleVar PushMap +type FailedPushMap = TMVar PushMap -newFailedPushChan :: IO FailedPushChan -newFailedPushChan = newEmptySampleVar - -{- Gets all failed pushes. Blocks until set. -} -getFailedPushes :: FailedPushChan -> IO PushMap -getFailedPushes = readSampleVar - -{- Sets all failed pushes to passed PushMap -} -setFailedPushes :: FailedPushChan -> PushMap -> IO () -setFailedPushes = writeSampleVar - -{- Indicates a failure to push to a single remote. -} -failedPush :: FailedPushChan -> Remote -> IO () -failedPush c r = - -{- Indicates that a remote was pushed to successfully. -} -successfulPush :: FailedPushChan -> Remote -> IO () -successfulPush c r = +{- The TMVar starts empty, and is left empty when there are no + - failed pushes. This way we can block until there are some failed pushes. + -} +newFailedPushMap :: IO FailedPushMap +newFailedPushMap = atomically newEmptyTMVar + +{- Blocks until there are failed pushes. + - Returns Remotes whose pushes failed a given time duration or more ago. + - (This may be an empty list.) -} +getFailedPushesBefore :: FailedPushMap -> NominalDiffTime -> IO [Remote] +getFailedPushesBefore v duration = do + m <- atomically $ readTMVar v + now <- getCurrentTime + return $ M.keys $ M.filter (not . toorecent now) m + where + toorecent now time = now `diffUTCTime` time < duration + +{- Modifies the map. -} +changeFailedPushMap :: FailedPushMap -> (PushMap -> PushMap) -> IO () +changeFailedPushMap v a = atomically $ + store . a . fromMaybe M.empty =<< tryTakeTMVar v + where + {- tryTakeTMVar empties the TMVar; refill it only if + - the modified map is not itself empty -} + store m + | m == M.empty = noop + | otherwise = putTMVar v $! m |