diff options
author | Roman Smrž <roman.smrz@seznam.cz> | 2022-08-13 13:20:53 +0200 |
---|---|---|
committer | Roman Smrž <roman.smrz@seznam.cz> | 2022-08-13 13:20:53 +0200 |
commit | cafdfaea35e3c321b480ea0f96f5bfd0a15a7db5 (patch) | |
tree | 14bde478f260b944f17eb4c7c1dff05d80b89d05 | |
parent | 7baa631f3c227b29fe702053a20f1ea98fc1f51e (diff) |
Storage: retry opening lock file
-rw-r--r-- | src/Storage/Internal.hs | 20 |
1 files changed, 12 insertions, 8 deletions
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 |