From cafdfaea35e3c321b480ea0f96f5bfd0a15a7db5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Roman=20Smr=C5=BE?= Date: Sat, 13 Aug 2022 13:20:53 +0200 Subject: Storage: retry opening lock file --- src/Storage/Internal.hs | 20 ++++++++++++-------- 1 file changed, 12 insertions(+), 8 deletions(-) (limited to 'src/Storage/Internal.hs') diff --git a/src/Storage/Internal.hs b/src/Storage/Internal.hs index 3facff2..85742a3 100644 --- a/src/Storage/Internal.hs +++ b/src/Storage/Internal.hs @@ -38,7 +38,6 @@ import System.IO.Error import System.IO.Unsafe (unsafePerformIO) import System.Posix.Files import System.Posix.IO -import System.Posix.Types data Storage' c = Storage @@ -218,14 +217,20 @@ refPath spath rdgst = intercalate "/" [spath, "objects", BC.unpack alg, pref, re (pref, rest) = splitAt 2 $ BC.unpack dgst -openFdParents :: FilePath -> OpenMode -> Maybe FileMode -> OpenFileFlags -> IO Fd -openFdParents path omode fmode flags = do +openLockFile :: FilePath -> IO Handle +openLockFile path = do createDirectoryIfMissing True (takeDirectory path) - openFd path omode fmode flags + fd <- retry 10 $ + openFd path WriteOnly (Just $ unionFileModes ownerReadMode ownerWriteMode) (defaultFileFlags { exclusive = True }) + fdToHandle fd + where + retry :: Int -> IO a -> IO a + retry 0 act = act + retry n act = catchJust (\e -> if isAlreadyExistsError e then Just () else Nothing) + act (\_ -> threadDelay (100 * 1000) >> retry (n - 1) act) writeFileOnce :: FilePath -> BL.ByteString -> IO () -writeFileOnce file content = bracket - (fdToHandle =<< openFdParents locked WriteOnly (Just $ unionFileModes ownerReadMode ownerWriteMode) (defaultFileFlags { exclusive = True })) +writeFileOnce file content = bracket (openLockFile locked) hClose $ \h -> do fileExist file >>= \case True -> removeLink locked @@ -235,8 +240,7 @@ writeFileOnce file content = bracket where locked = file ++ ".lock" writeFileChecked :: FilePath -> Maybe ByteString -> ByteString -> IO (Either (Maybe ByteString) ()) -writeFileChecked file prev content = bracket - (fdToHandle =<< openFdParents locked WriteOnly (Just $ unionFileModes ownerReadMode ownerWriteMode) (defaultFileFlags { exclusive = True })) +writeFileChecked file prev content = bracket (openLockFile locked) hClose $ \h -> do (prev,) <$> fileExist file >>= \case (Nothing, True) -> do -- cgit v1.2.3