-- avoid two threads both importing the same content identifier.
importing <- liftIO $ newTVarIO S.empty
withciddb $ \db -> do
- CIDDb.needsUpdateFromLog db
- >>= maybe noop (CIDDb.updateFromLog db)
- (prepclock (run cidmap importing db))
+ db' <- CIDDb.needsUpdateFromLog db
+ >>= maybe (pure db) (CIDDb.updateFromLog db)
+ (prepclock (run cidmap importing db'))
where
-- When not importing content, reuse the same vector
-- clock for all state that's recorded. This can save
getTopFilePath subdir P.</> fromImportLocation loc
getcidkey cidmap db cid = liftIO $
- CIDDb.getContentIdentifierKeys db rs cid >>= \case
- [] -> atomically $
- maybeToList . M.lookup cid <$> readTVar cidmap
- l -> return l
+ -- Avoiding querying the database when it's empty speeds up
+ -- the initial import.
+ if CIDDb.databaseIsEmpty db
+ then getcidkeymap cidmap cid
+ else CIDDb.getContentIdentifierKeys db rs cid >>= \case
+ [] -> getcidkeymap cidmap cid
+ l -> return l
+
+ getcidkeymap cidmap cid =
+ atomically $ maybeToList . M.lookup cid <$> readTVar cidmap
recordcidkey cidmap cid k = do
liftIO $ atomically $ modifyTVar' cidmap $
{- Sqlite database of ContentIdentifiers imported from special remotes.
-
- - Copyright 2019 Joey Hess <id@joeyh.name>
+ - Copyright 2019-2023 Joey Hess <id@joeyh.name>
-:
- Licensed under the GNU AGPL version 3 or higher.
-}
module Database.ContentIdentifier (
ContentIdentifierHandle,
+ databaseIsEmpty,
openDb,
closeDb,
flushDbQueue,
import qualified System.FilePath.ByteString as P
import qualified Data.Text as T
-data ContentIdentifierHandle = ContentIdentifierHandle H.DbQueue
+data ContentIdentifierHandle = ContentIdentifierHandle H.DbQueue Bool
+
+databaseIsEmpty :: ContentIdentifierHandle -> Bool
+databaseIsEmpty (ContentIdentifierHandle _ b) = b
share [mkPersist sqlSettings, mkMigrate "migrateContentIdentifier"] [persistLowerCase|
ContentIdentifiers
openDb = do
dbdir <- calcRepo' gitAnnexContentIdentifierDbDir
let db = dbdir P.</> "db"
- ifM (liftIO $ not <$> R.doesPathExist db)
- ( initDb db $ void $
+ isnew <- liftIO $ not <$> R.doesPathExist db
+ if isnew
+ then initDb db $ void $
runMigrationSilent migrateContentIdentifier
-- Migrate from old version of database, which had
-- an incorrect uniqueness constraint on the
-- ContentIdentifiers table.
- , liftIO $ runSqlite (T.pack (fromRawFilePath db)) $ void $
+ else liftIO $ runSqlite (T.pack (fromRawFilePath db)) $ void $
runMigrationSilent migrateContentIdentifier
- )
h <- liftIO $ H.openDbQueue db "content_identifiers"
- return $ ContentIdentifierHandle h
+ return $ ContentIdentifierHandle h isnew
closeDb :: ContentIdentifierHandle -> Annex ()
-closeDb (ContentIdentifierHandle h) = liftIO $ H.closeDbQueue h
+closeDb (ContentIdentifierHandle h _) = liftIO $ H.closeDbQueue h
queueDb :: ContentIdentifierHandle -> SqlPersistM () -> IO ()
-queueDb (ContentIdentifierHandle h) = H.queueDb h checkcommit
+queueDb (ContentIdentifierHandle h _) = H.queueDb h checkcommit
where
-- commit queue after 1000 changes
checkcommit sz _lastcommittime
| otherwise = return False
flushDbQueue :: ContentIdentifierHandle -> IO ()
-flushDbQueue (ContentIdentifierHandle h) = H.flushDbQueue h
+flushDbQueue (ContentIdentifierHandle h _) = H.flushDbQueue h
-- Be sure to also update the git-annex branch when using this.
recordContentIdentifier :: ContentIdentifierHandle -> RemoteStateHandle -> ContentIdentifier -> Key -> IO ()
void $ insertUniqueFast $ ContentIdentifiers u cid k
getContentIdentifiers :: ContentIdentifierHandle -> RemoteStateHandle -> Key -> IO [ContentIdentifier]
-getContentIdentifiers (ContentIdentifierHandle h) (RemoteStateHandle u) k =
+getContentIdentifiers (ContentIdentifierHandle h _) (RemoteStateHandle u) k =
H.queryDbQueue h $ do
l <- selectList
[ ContentIdentifiersKey ==. k
return $ map (contentIdentifiersCid . entityVal) l
getContentIdentifierKeys :: ContentIdentifierHandle -> RemoteStateHandle -> ContentIdentifier -> IO [Key]
-getContentIdentifierKeys (ContentIdentifierHandle h) (RemoteStateHandle u) cid =
+getContentIdentifierKeys (ContentIdentifierHandle h _) (RemoteStateHandle u) cid =
H.queryDbQueue h $ do
l <- selectList
[ ContentIdentifiersCid ==. cid
void $ insertUniqueFast $ AnnexBranch $ toSSha s
getAnnexBranchTree :: ContentIdentifierHandle -> IO Sha
-getAnnexBranchTree (ContentIdentifierHandle h) = H.queryDbQueue h $ do
+getAnnexBranchTree (ContentIdentifierHandle h _) = H.queryDbQueue h $ do
l <- selectList ([] :: [Filter AnnexBranch]) []
case l of
(s:[]) -> return $ fromSSha $ annexBranchTree $ entityVal s
_ -> return Nothing
{- The database should be locked for write when calling this. -}
-updateFromLog :: ContentIdentifierHandle -> (Sha, Sha) -> Annex ()
-updateFromLog db (oldtree, currtree) = do
+updateFromLog :: ContentIdentifierHandle -> (Sha, Sha) -> Annex ContentIdentifierHandle
+updateFromLog db@(ContentIdentifierHandle h _) (oldtree, currtree) = do
(l, cleanup) <- inRepo $
DiffTree.diffTreeRecursive oldtree currtree
mapM_ go l
liftIO $ do
recordAnnexBranchTree db currtree
flushDbQueue db
+ return (ContentIdentifierHandle h False)
where
go ti = case extLogFileKey remoteContentIdentifierExt (getTopFilePath (DiffTree.file ti)) of
Nothing -> return ()