This commit is contained in:
voidlizard 2025-08-01 13:05:35 +03:00
parent 3c37f9e468
commit d71a66111a
5 changed files with 46 additions and 2 deletions

View File

@ -39,6 +39,7 @@ import System.Posix.Files qualified as PFS
import System.IO.MMap as MMap import System.IO.MMap as MMap
import Control.Concurrent.STM qualified as STM import Control.Concurrent.STM qualified as STM
import Control.Concurrent.STM.TSem import Control.Concurrent.STM.TSem
import System.FileLock as FL
ncqStorageOpen3 :: MonadIO m => FilePath -> (NCQStorage3 -> NCQStorage3) -> m NCQStorage3 ncqStorageOpen3 :: MonadIO m => FilePath -> (NCQStorage3 -> NCQStorage3) -> m NCQStorage3
ncqStorageOpen3 fp upd = do ncqStorageOpen3 fp upd = do
@ -80,11 +81,16 @@ ncqStorageOpen3 fp upd = do
ncqStateKey <- newTVarIO (FileKey maxBound) ncqStateKey <- newTVarIO (FileKey maxBound)
ncqStateUse <- newTVarIO mempty ncqStateUse <- newTVarIO mempty
ncqServiceSem <- atomically $ newTSem 1 ncqServiceSem <- atomically $ newTSem 1
ncqFileLock <- newTVarIO Nothing
let ncq = NCQStorage3{..} & upd let ncq = NCQStorage3{..} & upd
mkdir (ncqGetWorkDir ncq) mkdir (ncqGetWorkDir ncq)
liftIO (FL.tryLockFile (ncqGetFileName ncq ".lock") Exclusive)
>>= orThrow NCQStorageCurrentAlreadyOpen
>>= atomically . writeTVar ncqFileLock . Just
liftIO (ncqTryLoadState ncq) liftIO (ncqTryLoadState ncq)
pure ncq pure ncq

View File

@ -34,6 +34,7 @@ module HBS2.Storage.NCQ3.Internal.Prelude
) where ) where
import HBS2.Prelude as Exported import HBS2.Prelude as Exported
import HBS2.OrDie as Exported
import HBS2.Data.Log.Structured.NCQ as Exported import HBS2.Data.Log.Structured.NCQ as Exported
import HBS2.Data.Types.Refs as Exported import HBS2.Data.Types.Refs as Exported

View File

@ -38,9 +38,11 @@ import System.Posix.Files ( getFileStatus
import System.Posix.Files qualified as PFS import System.Posix.Files qualified as PFS
import System.IO.MMap as MMap import System.IO.MMap as MMap
import Control.Concurrent.STM qualified as STM import Control.Concurrent.STM qualified as STM
import System.FileLock as FL
ncqStorageStop3 :: forall m . MonadUnliftIO m => NCQStorage3 -> m () ncqStorageStop3 :: forall m . MonadUnliftIO m => NCQStorage3 -> m ()
ncqStorageStop3 NCQStorage3{..} = atomically $ writeTVar ncqStopReq True ncqStorageStop3 NCQStorage3{..} = do
atomically $ writeTVar ncqStopReq True
ncqStorageRun3 :: forall m . MonadUnliftIO m ncqStorageRun3 :: forall m . MonadUnliftIO m
=> NCQStorage3 => NCQStorage3
@ -48,6 +50,9 @@ ncqStorageRun3 :: forall m . MonadUnliftIO m
ncqStorageRun3 ncq@NCQStorage3{..} = flip runContT pure do ncqStorageRun3 ncq@NCQStorage3{..} = flip runContT pure do
ContT $ bracket setAlive (const unsetAlive) ContT $ bracket setAlive (const unsetAlive)
ContT $ bracket none $ const $ liftIO do
readTVarIO ncqFileLock >>= mapM_ FL.unlockFile
closeQ <- liftIO newTQueueIO closeQ <- liftIO newTQueueIO
closer <- spawnActivity $ liftIO $ fix \loop -> do closer <- spawnActivity $ liftIO $ fix \loop -> do

View File

@ -10,7 +10,7 @@ import Data.Set qualified as Set
import Data.HashSet qualified as HS import Data.HashSet qualified as HS
import Text.Printf import Text.Printf
import Control.Concurrent.STM.TSem (TSem,waitTSem,signalTSem) import Control.Concurrent.STM.TSem (TSem,waitTSem,signalTSem)
import System.FileLock (FileLock)
data CachedData = CachedData !ByteString data CachedData = CachedData !ByteString
data CachedIndex = CachedIndex !ByteString !NWayHash data CachedIndex = CachedIndex !ByteString !NWayHash
@ -104,6 +104,7 @@ data NCQStorage3 =
, ncqOnRunWriteIdle :: TVar (IO ()) , ncqOnRunWriteIdle :: TVar (IO ())
, ncqSyncNo :: TVar Int , ncqSyncNo :: TVar Int
, ncqServiceSem :: TSem , ncqServiceSem :: TSem
, ncqFileLock :: TVar (Maybe FileLock)
} }

View File

@ -536,6 +536,37 @@ ncq3Tests = do
pause @'Seconds 600 pause @'Seconds 600
entry $ bindMatch "test:ncq3:lock" $ nil_ $ \e -> runTest $ \TestEnv{..} -> do
w <- newTVarIO 0
r <- try @_ @SomeException do
flip runContT pure do
notice $ "run 1st storage" <+> pretty testEnvDir
sto1 <- ContT $ ncqWithStorage3 testEnvDir
atomically $ writeTVar w 1
pause @'Seconds 1
notice $ "run 2nd storage" <+> pretty testEnvDir
sto1 <- ContT $ ncqWithStorage3 testEnvDir
pause @'Seconds 1
notice "so what?"
atomically $ writeTVar w 2
pure 42
wx <- readTVarIO w
liftIO $ assertBool "first run, second fail" (wx == 1)
notice $ "second must fail" <+> pretty wx <+> "=>" <+> viaShow r
testNCQ3Concurrent1 :: MonadUnliftIO m testNCQ3Concurrent1 :: MonadUnliftIO m
=> Bool => Bool
-> Int -> Int