summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRoman Smrž <roman.smrz@seznam.cz>2022-08-13 13:20:53 +0200
committerRoman Smrž <roman.smrz@seznam.cz>2022-08-13 13:20:53 +0200
commitcafdfaea35e3c321b480ea0f96f5bfd0a15a7db5 (patch)
tree14bde478f260b944f17eb4c7c1dff05d80b89d05
parent7baa631f3c227b29fe702053a20f1ea98fc1f51e (diff)
Storage: retry opening lock file
-rw-r--r--src/Storage/Internal.hs20
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