summaryrefslogtreecommitdiff
path: root/Annex
diff options
context:
space:
mode:
authorGravatar Joey Hess <joeyh@joeyh.name>2015-12-09 17:00:37 -0400
committerGravatar Joey Hess <joeyh@joeyh.name>2015-12-09 17:00:37 -0400
commit76ccac53916d308aa4806d38bb8cfb6a9d1f9081 (patch)
tree10f7618585df73c335c459f9562b04f37a7eb03f /Annex
parentb5c8ba7db3ea2eb4f1cd28e49cadb5fd348ca738 (diff)
add inode cache to the db
Renamed the db to keys, since it is various info about a Keys. Dropping a key will update its pointer files, as long as their content can be verified to be unmodified. This falls back to checksum verification, but I want it to use an InodeCache of the key, for speed. But, I have not made anything populate that cache yet.
Diffstat (limited to 'Annex')
-rw-r--r--Annex/Content.hs39
-rw-r--r--Annex/Content/Direct.hs9
-rw-r--r--Annex/InodeSentinal.hs9
3 files changed, 43 insertions, 14 deletions
diff --git a/Annex/Content.hs b/Annex/Content.hs
index 564bc2dca..a530245b3 100644
--- a/Annex/Content.hs
+++ b/Annex/Content.hs
@@ -73,7 +73,8 @@ import qualified Backend
import Types.NumCopies
import Annex.UUID
import Annex.InodeSentinal
-import qualified Database.AssociatedFiles as AssociatedFiles
+import Utility.InodeCache
+import qualified Database.Keys
{- Checks if a given key's content is currently present. -}
inAnnex :: Key -> Annex Bool
@@ -447,10 +448,10 @@ moveAnnex key src = withObjectLoc key storeobject storedirect
( alreadyhave
, modifyContent dest $ do
liftIO $ moveFile src dest
- fs <- AssociatedFiles.getDb key
+ fs <- Database.Keys.getAssociatedFiles key
if null fs
then freezeContent dest
- else mapM_ (populateAssociatedFile key dest) fs
+ else mapM_ (populatePointerFile key dest) fs
)
storeindirect = storeobject =<< calcRepo (gitAnnexLocation key)
@@ -480,8 +481,8 @@ moveAnnex key src = withObjectLoc key storeobject storedirect
alreadyhave = liftIO $ removeFile src
-populateAssociatedFile :: Key -> FilePath -> FilePath -> Annex ()
-populateAssociatedFile k obj f = go =<< isPointerFile f
+populatePointerFile :: Key -> FilePath -> FilePath -> Annex ()
+populatePointerFile k obj f = go =<< isPointerFile f
where
go (Just k') | k == k' = liftIO $ do
nukeFile f
@@ -598,6 +599,8 @@ removeAnnex (ContentRemovalLock key) = withObjectLoc key remove removedirect
secureErase file
liftIO $ nukeFile file
removeInodeCache key
+ mapM_ (void . tryIO . resetPointerFile key)
+ =<< Database.Keys.getAssociatedFiles key
removedirect fs = do
cache <- recordedInodeCache key
removeInodeCache key
@@ -607,6 +610,32 @@ removeAnnex (ContentRemovalLock key) = withObjectLoc key remove removedirect
secureErase f
replaceFile f $ makeAnnexLink l
+{- To safely reset a pointer file, it has to be the unmodified content of
+ - the key. The expensive way to tell is to do a verification of its content.
+ - The cheaper way is to see if the InodeCache for the key matches the
+ - file.
+ -}
+resetPointerFile :: Key -> FilePath -> Annex ()
+resetPointerFile key f = go =<< geti
+ where
+ go Nothing = noop
+ go (Just fc) = ifM (cheapcheck fc <||> expensivecheck fc)
+ ( do
+ secureErase f
+ liftIO $ nukeFile f
+ liftIO $ writeFile f (formatPointer key)
+ , noop
+ )
+ cheapcheck fc = maybe (return False) (compareInodeCaches fc)
+ =<< Database.Keys.getInodeCache key
+ expensivecheck fc = ifM (verifyKeyContent AlwaysVerify Types.Remote.UnVerified key f)
+ -- The file could have been modified while it was
+ -- being verified. Detect that.
+ ( geti >>= maybe (return False) (compareInodeCaches fc)
+ , return False
+ )
+ geti = withTSDelta (liftIO . genInodeCache f)
+
{- Runs the secure erase command if set, otherwise does nothing.
- File may or may not be deleted at the end; caller is responsible for
- making sure it's deleted. -}
diff --git a/Annex/Content/Direct.hs b/Annex/Content/Direct.hs
index 1edcbaed5..3d2ab1c58 100644
--- a/Annex/Content/Direct.hs
+++ b/Annex/Content/Direct.hs
@@ -180,15 +180,6 @@ sameFileStatus key f status = do
([], Nothing) -> return True
_ -> return False
-{- If the inodes have changed, only the size and mtime are compared. -}
-compareInodeCaches :: InodeCache -> InodeCache -> Annex Bool
-compareInodeCaches x y
- | compareStrong x y = return True
- | otherwise = ifM inodesChanged
- ( return $ compareWeak x y
- , return False
- )
-
elemInodeCaches :: InodeCache -> [InodeCache] -> Annex Bool
elemInodeCaches _ [] = return False
elemInodeCaches c (l:ls) = ifM (compareInodeCaches c l)
diff --git a/Annex/InodeSentinal.hs b/Annex/InodeSentinal.hs
index 7047a405c..450e3b967 100644
--- a/Annex/InodeSentinal.hs
+++ b/Annex/InodeSentinal.hs
@@ -14,6 +14,15 @@ import qualified Annex
import Utility.InodeCache
import Annex.Perms
+{- If the inodes have changed, only the size and mtime are compared. -}
+compareInodeCaches :: InodeCache -> InodeCache -> Annex Bool
+compareInodeCaches x y
+ | compareStrong x y = return True
+ | otherwise = ifM inodesChanged
+ ( return $ compareWeak x y
+ , return False
+ )
+
{- Some filesystems get new inodes each time they are mounted.
- In order to work on such a filesystem, a sentinal file is used to detect
- when the inodes have changed.