summaryrefslogtreecommitdiff
path: root/Database/Fsck.hs
diff options
context:
space:
mode:
authorGravatar Joey Hess <joeyh@joeyh.name>2015-02-17 16:39:35 -0400
committerGravatar Joey Hess <joeyh@joeyh.name>2015-02-17 16:56:12 -0400
commite6b87922f3ddc3e13b9ef7b724bb6b3e39c6875d (patch)
tree4fa7d6e531e3810603640d817caa0a36db1ae56a /Database/Fsck.hs
parent0bdaad9e26f9c25add31dbfb3afd8b61114500d9 (diff)
allow for concurrent incremental fsck processes again (sorta)
Sqlite doesn't support multiple concurrent writers at all. One of them will fail to write. It's not even possible to have two processes building up separate transactions at the same time. Before using sqlite, incremental fsck could work perfectly well with multiple fsck processes running concurrently. I'd like to keep that working. My partial solution, so far, is to make git-annex buffer writes, and every so often send them all to sqlite at once, in a transaction. So most of the time, nothing is writing to the database. (And if it gets unlucky and a write fails due to a collision with another writer, it can just wait and retry the write later.) This lets multiple processes write to the database successfully. But, for the purposes of concurrent, incremental fsck, it's not ideal. Each process doesn't immediately learn of files that another process has checked. So they'll tend to do redundant work. Only way I can see to improve this is to use some other mechanism for short-term IPC between the fsck processes. Not yet done. ---- Also, make addDb check if an item is in the database already, and not try to re-add it. That fixes an intermittent crash with "SQLite3 returned ErrorConstraint while attempting to perform step." I am not 100% sure why; it only started happening when I moved write buffering into the queue. It seemed to generally happen on the same file each time, so could just be due to multiple files having the same key. However, I doubt my sound repo has many duplicate keys, and I suspect something else is going on. ---- Updated benchmark, with the 1000 item queue: 6m33.808s
Diffstat (limited to 'Database/Fsck.hs')
-rw-r--r--Database/Fsck.hs20
1 files changed, 10 insertions, 10 deletions
diff --git a/Database/Fsck.hs b/Database/Fsck.hs
index a42988205..e742229a5 100644
--- a/Database/Fsck.hs
+++ b/Database/Fsck.hs
@@ -77,18 +77,18 @@ closeDb h = do
unlockFile =<< fromRepo gitAnnexFsckDbLock
addDb :: H.DbHandle -> Key -> IO ()
-addDb h = void . H.runDb' h commitPolicy . insert . Fscked . toSKey
+addDb h k = H.queueDb h 1000 $
+ unlessM (inDb' sk) $
+ insert_ $ Fscked sk
+ where
+ sk = toSKey k
inDb :: H.DbHandle -> Key -> IO Bool
-inDb h k = H.runDb h $ do
+inDb h = H.runDb h . inDb' . toSKey
+
+inDb' :: SKey -> SqlPersistM Bool
+inDb' sk = do
r <- select $ from $ \r -> do
- where_ (r ^. FsckedKey ==. val (toSKey k))
+ where_ (r ^. FsckedKey ==. val sk)
return (r ^. FsckedKey)
return $ not $ null r
-
-{- Bundle up addDb transactions and commit after 60 seconds.
- - This is a balance between resuming where the last incremental
- - fsck left off, and making too many commits which slows down the fsck
- - of lots of small or not present files. -}
-commitPolicy :: H.CommitPolicy
-commitPolicy = H.CommitAfter (fromIntegral (60 :: Int))