mirror of https://github.com/voidlizard/hbs2
wip, remove deleted records log
This commit is contained in:
parent
671273b817
commit
03ec08509a
|
@ -22,7 +22,6 @@ import Data.HashMap.Strict (HashMap)
|
||||||
import Control.Monad.Trans.Cont
|
import Control.Monad.Trans.Cont
|
||||||
import Control.Monad.Trans.Maybe
|
import Control.Monad.Trans.Maybe
|
||||||
import Control.Concurrent.STM qualified as STM
|
import Control.Concurrent.STM qualified as STM
|
||||||
import Control.Concurrent.STM.TSem
|
|
||||||
import Data.HashPSQ qualified as HPSQ
|
import Data.HashPSQ qualified as HPSQ
|
||||||
import Data.HashPSQ (HashPSQ)
|
import Data.HashPSQ (HashPSQ)
|
||||||
import Data.IntMap qualified as IntMap
|
import Data.IntMap qualified as IntMap
|
||||||
|
@ -95,8 +94,6 @@ data NCQStorage =
|
||||||
, ncqRefsMem :: TVar (HashMap HashRef HashRef)
|
, ncqRefsMem :: TVar (HashMap HashRef HashRef)
|
||||||
, ncqRefsDirty :: TVar Int
|
, ncqRefsDirty :: TVar Int
|
||||||
, ncqWriteQueue :: TVar (HashPSQ HashRef TimeSpec LBS.ByteString)
|
, ncqWriteQueue :: TVar (HashPSQ HashRef TimeSpec LBS.ByteString)
|
||||||
, ncqDeleted :: TVar (HashMap HashRef Int16)
|
|
||||||
, ncqDeleteQ :: TBQueue (HashRef, Int16)
|
|
||||||
, ncqWaitIndex :: TVar (HashPSQ HashRef TimeSpec (Word64,Word64))
|
, ncqWaitIndex :: TVar (HashPSQ HashRef TimeSpec (Word64,Word64))
|
||||||
, ncqTrackedFiles :: TVar (HashSet FileKey)
|
, ncqTrackedFiles :: TVar (HashSet FileKey)
|
||||||
, ncqCachedIndexes :: TVar (HashPSQ FileKey TimeSpec (ByteString,NWayHash))
|
, ncqCachedIndexes :: TVar (HashPSQ FileKey TimeSpec (ByteString,NWayHash))
|
||||||
|
@ -257,9 +254,7 @@ ncqStorageStop ncq@NCQStorage{..} = do
|
||||||
ncqStorageSync ncq
|
ncqStorageSync ncq
|
||||||
atomically $ writeTVar ncqStopped True
|
atomically $ writeTVar ncqStopped True
|
||||||
atomically do
|
atomically do
|
||||||
doneW <- readTVar ncqWriteQueue <&> HPSQ.null
|
done <- readTVar ncqWriteQueue <&> HPSQ.null
|
||||||
doneD <- isEmptyTBQueue ncqDeleteQ
|
|
||||||
let done = doneW && doneD
|
|
||||||
unless done STM.retry
|
unless done STM.retry
|
||||||
debug "ncqStorageStop DONE"
|
debug "ncqStorageStop DONE"
|
||||||
|
|
||||||
|
@ -279,9 +274,8 @@ ncqStorageRun ncq@NCQStorage{..} = flip runContT pure do
|
||||||
reader <- makeReader
|
reader <- makeReader
|
||||||
indexer <- makeIndexer indexQ
|
indexer <- makeIndexer indexQ
|
||||||
writer <- makeWriter indexQ
|
writer <- makeWriter indexQ
|
||||||
delWriter <- makeDelWriter
|
|
||||||
|
|
||||||
mapM_ waitCatch [writer,indexer,refsWriter,delWriter]
|
mapM_ waitCatch [writer,indexer,refsWriter]
|
||||||
mapM_ cancel [reader]
|
mapM_ cancel [reader]
|
||||||
|
|
||||||
where
|
where
|
||||||
|
@ -392,52 +386,6 @@ ncqStorageRun ncq@NCQStorage{..} = flip runContT pure do
|
||||||
link indexer
|
link indexer
|
||||||
pure indexer
|
pure indexer
|
||||||
|
|
||||||
makeDelWriter = do
|
|
||||||
|
|
||||||
let fsyncAt = 150
|
|
||||||
|
|
||||||
delWriter <- ContT $ withAsync do
|
|
||||||
|
|
||||||
myFlushQ <- newTQueueIO
|
|
||||||
atomically $ modifyTVar ncqFlushNow (myFlushQ:)
|
|
||||||
|
|
||||||
mt <- atomically $ isEmptyTBQueue ncqDeleteQ
|
|
||||||
debug $ "delWriter running" <+> pretty mt
|
|
||||||
|
|
||||||
fix \next -> do
|
|
||||||
|
|
||||||
void $ race (pause @'Seconds 2) $ atomically do
|
|
||||||
stop <- readTVar ncqStopped
|
|
||||||
flush <- isEmptyTQueue myFlushQ <&> not
|
|
||||||
size <- lengthTBQueue ncqDeleteQ <&> (>= fsyncAt)
|
|
||||||
unless (flush || size || stop) STM.retry
|
|
||||||
|
|
||||||
toWrite <- atomically $ STM.flushTBQueue ncqDeleteQ
|
|
||||||
|
|
||||||
liftIO do
|
|
||||||
w <- readTVarIO ncqDeletedW
|
|
||||||
-- debug "write shit"
|
|
||||||
for_ toWrite $ \(hx,delta) -> do
|
|
||||||
let sdelta = N.bytestring16 (fromIntegral delta)
|
|
||||||
let k = coerce @_ @ByteString hx
|
|
||||||
let size = BS.length k + BS.length sdelta
|
|
||||||
let deleted = mconcat [ N.bytestring32 (fromIntegral size)
|
|
||||||
, k
|
|
||||||
, sdelta
|
|
||||||
]
|
|
||||||
void $ Posix.fdWrite w deleted
|
|
||||||
fileSynchronise w
|
|
||||||
|
|
||||||
stop <- readTVarIO ncqStopped
|
|
||||||
size <- atomically $ lengthTBQueue ncqDeleteQ
|
|
||||||
|
|
||||||
if stop && size <= 0 then none else next
|
|
||||||
|
|
||||||
debug "delWriter stopped"
|
|
||||||
|
|
||||||
link delWriter
|
|
||||||
pure delWriter
|
|
||||||
|
|
||||||
writeJournal indexQ syncData = liftIO do
|
writeJournal indexQ syncData = liftIO do
|
||||||
|
|
||||||
trace $ "writeJournal" <+> pretty syncData
|
trace $ "writeJournal" <+> pretty syncData
|
||||||
|
@ -552,17 +500,9 @@ ncqStoragePut ncq@NCQStorage{..} lbs = flip runContT pure $ callCC \exit -> do
|
||||||
|
|
||||||
when stoped $ exit Nothing
|
when stoped $ exit Nothing
|
||||||
|
|
||||||
let h = hashObject @HbSync lbs & coerce
|
when (LBS.null lbs) $ exit Nothing
|
||||||
|
|
||||||
ncqLocate ncq h >>= \case
|
let h = hashObject @HbSync lbs & coerce
|
||||||
Nothing -> none
|
|
||||||
Just{} -> do
|
|
||||||
d <- readTVarIO ncqDeleted <&> fromMaybe 0 . HM.lookup h
|
|
||||||
if d < 1 then
|
|
||||||
exit (Just h)
|
|
||||||
else do
|
|
||||||
let delta = negate d - 1
|
|
||||||
atomically $ writeTBQueue ncqDeleteQ (h, delta)
|
|
||||||
|
|
||||||
now <- getTimeCoarse
|
now <- getTimeCoarse
|
||||||
atomically do
|
atomically do
|
||||||
|
@ -677,7 +617,7 @@ ncqStorageScanDataFile ncq fp' action = do
|
||||||
|
|
||||||
ncqStorageIsDeleted :: MonadIO m => NCQStorage -> HashRef -> m Bool
|
ncqStorageIsDeleted :: MonadIO m => NCQStorage -> HashRef -> m Bool
|
||||||
ncqStorageIsDeleted NCQStorage{..} what = do
|
ncqStorageIsDeleted NCQStorage{..} what = do
|
||||||
readTVarIO ncqDeleted <&> (>0) . fromMaybe 0 . HM.lookup what
|
pure False
|
||||||
|
|
||||||
ncqStorageGet :: MonadUnliftIO m => NCQStorage -> HashRef -> m (Maybe LBS.ByteString)
|
ncqStorageGet :: MonadUnliftIO m => NCQStorage -> HashRef -> m (Maybe LBS.ByteString)
|
||||||
ncqStorageGet ncq@NCQStorage{..} h = flip runContT pure $ callCC \exit -> do
|
ncqStorageGet ncq@NCQStorage{..} h = flip runContT pure $ callCC \exit -> do
|
||||||
|
@ -739,12 +679,8 @@ ncqStorageDel ncq@NCQStorage{..} h = flip runContT pure $ callCC \exit -> do
|
||||||
True -> exit ()
|
True -> exit ()
|
||||||
_ -> none
|
_ -> none
|
||||||
|
|
||||||
atomically do
|
error "ncqStorageDel not implemented"
|
||||||
what <- readTVar ncqDeleted <&> fromMaybe 0 . HM.lookup h
|
|
||||||
when (what < 1) do
|
|
||||||
let delta = negate what + 1
|
|
||||||
writeTBQueue ncqDeleteQ (h, delta)
|
|
||||||
modifyTVar ncqDeleted (HM.insertWith (+) h delta)
|
|
||||||
|
|
||||||
ncqStorageSync :: MonadUnliftIO m => NCQStorage -> m ()
|
ncqStorageSync :: MonadUnliftIO m => NCQStorage -> m ()
|
||||||
ncqStorageSync NCQStorage{..} = do
|
ncqStorageSync NCQStorage{..} = do
|
||||||
|
@ -783,25 +719,12 @@ ncqFixIndexes ncq@NCQStorage{..} = do
|
||||||
atomically $ ncqAddTrackedFilesSTM ncq [newKey]
|
atomically $ ncqAddTrackedFilesSTM ncq [newKey]
|
||||||
|
|
||||||
|
|
||||||
-- NOTE:
|
|
||||||
-- merely find in fossil files,
|
|
||||||
-- because "current" is filtered on load
|
|
||||||
-- and it's okay, we may compact only
|
|
||||||
-- fossils
|
|
||||||
ncqScanDeleted :: MonadUnliftIO m => NCQStorage -> m [Location]
|
|
||||||
ncqScanDeleted ncq@NCQStorage{..} = do
|
|
||||||
readTVarIO ncqDeleted
|
|
||||||
<&> fmap fst . List.filter ((>0).snd) . HM.toList
|
|
||||||
>>= mapM (ncqLocate ncq)
|
|
||||||
<&> catMaybes
|
|
||||||
|
|
||||||
ncqStorageOpen :: MonadUnliftIO m => FilePath -> m NCQStorage
|
ncqStorageOpen :: MonadUnliftIO m => FilePath -> m NCQStorage
|
||||||
ncqStorageOpen fp = do
|
ncqStorageOpen fp = do
|
||||||
ncq@NCQStorage{..} <- ncqStorageInit_ False fp
|
ncq@NCQStorage{..} <- ncqStorageInit_ False fp
|
||||||
ncqReadTrackedFiles ncq
|
ncqReadTrackedFiles ncq
|
||||||
ncqFixIndexes ncq
|
ncqFixIndexes ncq
|
||||||
ncqLoadIndexes ncq
|
ncqLoadIndexes ncq
|
||||||
readDeleted ncq
|
|
||||||
readCurrent ncq
|
readCurrent ncq
|
||||||
readRefs ncq
|
readRefs ncq
|
||||||
atomically $ putTMVar ncqOpenDone True
|
atomically $ putTMVar ncqOpenDone True
|
||||||
|
@ -818,32 +741,6 @@ ncqStorageOpen fp = do
|
||||||
S.yield (k,v)
|
S.yield (k,v)
|
||||||
atomically $ writeTVar ncqRefsMem (HM.fromList kvs)
|
atomically $ writeTVar ncqRefsMem (HM.fromList kvs)
|
||||||
|
|
||||||
|
|
||||||
readDeleted ncq@NCQStorage{..} = do
|
|
||||||
let fn = ncqGetDeletedFileName ncq
|
|
||||||
-- liftIO $ print $ pretty "FILE" <+> pretty fn
|
|
||||||
bs0 <- liftIO $ mmapFileByteString fn Nothing
|
|
||||||
|
|
||||||
items <- HM.fromListWith (+) <$> S.toList_ do
|
|
||||||
flip runContT pure $ callCC \exit -> do
|
|
||||||
flip fix bs0 $ \next bs -> do
|
|
||||||
when (BS.length bs < 4) $ exit ()
|
|
||||||
let w = BS.take 4 bs & N.word32 & fromIntegral
|
|
||||||
let p = BS.take w (BS.drop 4 bs)
|
|
||||||
|
|
||||||
when (BS.length p < w ) do
|
|
||||||
err $ "broken file" <+> pretty fn
|
|
||||||
exit ()
|
|
||||||
|
|
||||||
let k = BS.take 32 p & coerce . BS.copy
|
|
||||||
let v = BS.take 2 (BS.drop 32 p) & N.word16 & fromIntegral @_ @Int16
|
|
||||||
lift $ S.yield (k,v)
|
|
||||||
|
|
||||||
next (BS.drop (w+4) bs)
|
|
||||||
|
|
||||||
debug $ "NCQStorage.deleted" <+> pretty (HM.size items)
|
|
||||||
atomically $ writeTVar ncqDeleted items
|
|
||||||
|
|
||||||
readCurrent ncq@NCQStorage{..} = do
|
readCurrent ncq@NCQStorage{..} = do
|
||||||
let fn = ncqGetCurrentName ncq
|
let fn = ncqGetCurrentName ncq
|
||||||
-- liftIO $ print $ pretty "FILE" <+> pretty fn
|
-- liftIO $ print $ pretty "FILE" <+> pretty fn
|
||||||
|
@ -851,8 +748,6 @@ ncqStorageOpen fp = do
|
||||||
|
|
||||||
now <- getTimeCoarse
|
now <- getTimeCoarse
|
||||||
|
|
||||||
deleted <- readTVarIO ncqDeleted
|
|
||||||
|
|
||||||
items <- S.toList_ <$>
|
items <- S.toList_ <$>
|
||||||
flip runContT pure $ callCC \exit ->do
|
flip runContT pure $ callCC \exit ->do
|
||||||
flip fix (0,bs0) $ \next (o,bs) -> do
|
flip fix (0,bs0) $ \next (o,bs) -> do
|
||||||
|
@ -867,8 +762,7 @@ ncqStorageOpen fp = do
|
||||||
let k = BS.take 32 p & coerce . BS.copy
|
let k = BS.take 32 p & coerce . BS.copy
|
||||||
let vs = w - 32
|
let vs = w - 32
|
||||||
|
|
||||||
unless (fromMaybe 0 (HM.lookup k deleted) > 0) do
|
lift $ S.yield (k,now, (fromIntegral o, fromIntegral vs))
|
||||||
lift $ S.yield (k,now, (fromIntegral o, fromIntegral vs))
|
|
||||||
|
|
||||||
next (o+w+4, BS.drop (w+4) bs)
|
next (o+w+4, BS.drop (w+4) bs)
|
||||||
|
|
||||||
|
@ -910,8 +804,6 @@ ncqStorageInit_ check path = do
|
||||||
let ncqMaxCachedData = ncqMaxCachedIdx `div` 2
|
let ncqMaxCachedData = ncqMaxCachedIdx `div` 2
|
||||||
|
|
||||||
ncqWriteQueue <- newTVarIO HPSQ.empty
|
ncqWriteQueue <- newTVarIO HPSQ.empty
|
||||||
ncqDeleted <- newTVarIO mempty
|
|
||||||
ncqDeleteQ <- newTBQueueIO 3000
|
|
||||||
|
|
||||||
ncqNotWritten <- newTVarIO 0
|
ncqNotWritten <- newTVarIO 0
|
||||||
ncqLastWritten <- getTimeCoarse >>= newTVarIO
|
ncqLastWritten <- getTimeCoarse >>= newTVarIO
|
||||||
|
|
|
@ -509,28 +509,6 @@ main = do
|
||||||
|
|
||||||
e -> throwIO $ BadFormException @C (mkList e)
|
e -> throwIO $ BadFormException @C (mkList e)
|
||||||
|
|
||||||
entry $ bindMatch "test:ncq:raw:scan-deleted" $ nil_ \case
|
|
||||||
[StringLike fn] -> liftIO $ flip runContT pure do
|
|
||||||
|
|
||||||
ncq <- lift $ ncqStorageOpen fn
|
|
||||||
|
|
||||||
writer <- ContT $ withAsync $ ncqStorageRun ncq
|
|
||||||
link writer
|
|
||||||
|
|
||||||
ContT $ bracket none $ const do
|
|
||||||
none
|
|
||||||
|
|
||||||
what <- lift $ ncqScanDeleted ncq
|
|
||||||
|
|
||||||
for_ what $ \l -> do
|
|
||||||
liftIO $ print l
|
|
||||||
|
|
||||||
liftIO $ ncqStorageStop ncq
|
|
||||||
|
|
||||||
wait writer
|
|
||||||
|
|
||||||
e -> throwIO $ BadFormException @C (mkList e)
|
|
||||||
|
|
||||||
entry $ bindMatch "test:ncq:raw:del-some" $ nil_ \case
|
entry $ bindMatch "test:ncq:raw:del-some" $ nil_ \case
|
||||||
[StringLike fn] -> liftIO $ flip runContT pure do
|
[StringLike fn] -> liftIO $ flip runContT pure do
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue