From 5f391179f1d8e18f736613a739dec7295d8baa40 Mon Sep 17 00:00:00 2001 From: Joey Hess Date: Fri, 6 Dec 2019 14:44:42 -0400 Subject: [PATCH] use RawFilePath getFileStatus for speed Only done on those calls to getFileStatus that had a RawFilePath, not a FilePath. The others would probably be just as fast if converted to use it with toRawFilePath, but I'm not 100% sure. Note that genInodeCache' uses fromRawFilePath, but that value only gets used on Windows, so on unix the thunk will never be evaluated. --- Annex/Link.hs | 2 +- Command/Fix.hs | 20 ++++++++++---------- Command/Fsck.hs | 3 ++- Command/Lock.hs | 4 ++-- Command/ReKey.hs | 7 ++++--- Command/Unlock.hs | 4 ++-- Utility/FileSize.hs | 5 ++++- Utility/InodeCache.hs | 6 ++++++ Utility/RawFilePath.hs | 6 +++++- 9 files changed, 36 insertions(+), 21 deletions(-) diff --git a/Annex/Link.hs b/Annex/Link.hs index 609e9eb1d3..b012b7d933 100644 --- a/Annex/Link.hs +++ b/Annex/Link.hs @@ -182,7 +182,7 @@ restagePointerFile (Restage True) f orig = withTSDelta $ \tsd -> do absf <- liftIO $ absPath $ fromRawFilePath f Annex.Queue.addInternalAction runner [(absf, isunmodified tsd)] where - isunmodified tsd = genInodeCache (fromRawFilePath f) tsd >>= return . \case + isunmodified tsd = genInodeCache' f tsd >>= return . \case Nothing -> False Just new -> compareStrong orig new diff --git a/Command/Fix.hs b/Command/Fix.hs index dec48b665e..52e076f30b 100644 --- a/Command/Fix.hs +++ b/Command/Fix.hs @@ -56,30 +56,30 @@ start fixwhat file key = do obj <- calcRepo $ gitAnnexLocation key stopUnless (isUnmodified key (fromRawFilePath file) <&&> isUnmodified key obj) $ do thin <- annexThin <$> Annex.getGitConfig - fs <- liftIO $ catchMaybeIO $ getFileStatus (fromRawFilePath file) + fs <- liftIO $ catchMaybeIO $ R.getFileStatus file os <- liftIO $ catchMaybeIO $ getFileStatus obj case (linkCount <$> fs, linkCount <$> os, thin) of (Just 1, Just 1, True) -> - fixby $ makeHardLink (fromRawFilePath file) key + fixby $ makeHardLink file key (Just n, Just n', False) | n > 1 && n == n' -> - fixby $ breakHardLink (fromRawFilePath file) key obj + fixby $ breakHardLink file key obj _ -> stop -breakHardLink :: FilePath -> Key -> FilePath -> CommandPerform +breakHardLink :: RawFilePath -> Key -> FilePath -> CommandPerform breakHardLink file key obj = do - replaceFile file $ \tmp -> do - mode <- liftIO $ catchMaybeIO $ fileMode <$> getFileStatus file + replaceFile (fromRawFilePath file) $ \tmp -> do + mode <- liftIO $ catchMaybeIO $ fileMode <$> R.getFileStatus file unlessM (checkedCopyFile key obj tmp mode) $ error "unable to break hard link" thawContent tmp modifyContent obj $ freezeContent obj - Database.Keys.storeInodeCaches key [file] + Database.Keys.storeInodeCaches key [fromRawFilePath file] next $ return True -makeHardLink :: FilePath -> Key -> CommandPerform +makeHardLink :: RawFilePath -> Key -> CommandPerform makeHardLink file key = do - replaceFile file $ \tmp -> do - mode <- liftIO $ catchMaybeIO $ fileMode <$> getFileStatus file + replaceFile (fromRawFilePath file) $ \tmp -> do + mode <- liftIO $ catchMaybeIO $ fileMode <$> R.getFileStatus file linkFromAnnex key tmp mode >>= \case LinkAnnexFailed -> error "unable to make hard link" _ -> noop diff --git a/Command/Fsck.hs b/Command/Fsck.hs index bb2dde569f..256bdfa894 100644 --- a/Command/Fsck.hs +++ b/Command/Fsck.hs @@ -35,6 +35,7 @@ import qualified Database.Fsck as FsckDb import Types.CleanupActions import Types.Key import Types.ActionItem +import qualified Utility.RawFilePath as R import Data.Time.Clock.POSIX import System.Posix.Types (EpochTime) @@ -327,7 +328,7 @@ verifyWorkTree key file = do Just k | k == key -> whenM (inAnnex key) $ do showNote "fixing worktree content" replaceFile (fromRawFilePath file) $ \tmp -> do - mode <- liftIO $ catchMaybeIO $ fileMode <$> getFileStatus (fromRawFilePath file) + mode <- liftIO $ catchMaybeIO $ fileMode <$> R.getFileStatus file ifM (annexThin <$> Annex.getGitConfig) ( void $ linkFromAnnex key tmp mode , do diff --git a/Command/Lock.hs b/Command/Lock.hs index cb104225f6..24dd6810ed 100644 --- a/Command/Lock.hs +++ b/Command/Lock.hs @@ -56,7 +56,7 @@ performNew :: RawFilePath -> Key -> CommandPerform performNew file key = do lockdown =<< calcRepo (gitAnnexLocation key) addLink (fromRawFilePath file) key - =<< withTSDelta (liftIO . genInodeCache (fromRawFilePath file)) + =<< withTSDelta (liftIO . genInodeCache' file) next $ cleanupNew file key where lockdown obj = do @@ -70,7 +70,7 @@ performNew file key = do -- It's ok if the file is hard linked to obj, but if some other -- associated file is, we need to break that link to lock down obj. breakhardlink obj = whenM (catchBoolIO $ (> 1) . linkCount <$> liftIO (getFileStatus obj)) $ do - mfc <- withTSDelta (liftIO . genInodeCache (fromRawFilePath file)) + mfc <- withTSDelta (liftIO . genInodeCache' file) unlessM (sameInodeCache obj (maybeToList mfc)) $ do modifyContent obj $ replaceFile obj $ \tmp -> do unlessM (checkedCopyFile key obj tmp Nothing) $ diff --git a/Command/ReKey.hs b/Command/ReKey.hs index b9eac59232..6e0678c2cc 100644 --- a/Command/ReKey.hs +++ b/Command/ReKey.hs @@ -19,6 +19,7 @@ import Git.FilePath import qualified Database.Keys import Annex.InodeSentinal import Utility.InodeCache +import qualified Utility.RawFilePath as R cmd :: Command cmd = command "rekey" SectionPlumbing @@ -89,14 +90,14 @@ linkKey file oldkey newkey = ifM (isJust <$> isAnnexLink file) - it's hard linked to the old key, that link must be broken. -} oldobj <- calcRepo (gitAnnexLocation oldkey) v <- tryNonAsync $ do - st <- liftIO $ getFileStatus (fromRawFilePath file) + st <- liftIO $ R.getFileStatus file when (linkCount st > 1) $ do freezeContent oldobj replaceFile (fromRawFilePath file) $ \tmp -> do unlessM (checkedCopyFile oldkey oldobj tmp Nothing) $ error "can't lock old key" thawContent tmp - ic <- withTSDelta (liftIO . genInodeCache (fromRawFilePath file)) + ic <- withTSDelta (liftIO . genInodeCache' file) case v of Left e -> do warning (show e) @@ -117,7 +118,7 @@ cleanup file oldkey newkey = do liftIO $ removeFile (fromRawFilePath file) addLink (fromRawFilePath file) newkey Nothing , do - mode <- liftIO $ catchMaybeIO $ fileMode <$> getFileStatus (fromRawFilePath file) + mode <- liftIO $ catchMaybeIO $ fileMode <$> R.getFileStatus file liftIO $ whenM (isJust <$> isPointerFile file) $ writePointerFile file newkey mode stagePointerFile file mode =<< hashPointerFile newkey diff --git a/Command/Unlock.hs b/Command/Unlock.hs index 31f8a26cf5..443ac46e3c 100644 --- a/Command/Unlock.hs +++ b/Command/Unlock.hs @@ -14,6 +14,7 @@ import Annex.Link import Annex.ReplaceFile import Git.FilePath import qualified Database.Keys +import qualified Utility.RawFilePath as R cmd :: Command cmd = mkcmd "unlock" "unlock files for modification" @@ -40,8 +41,7 @@ start file key = ifM (isJust <$> isAnnexLink file) perform :: RawFilePath -> Key -> CommandPerform perform dest key = do - destmode <- liftIO $ catchMaybeIO $ fileMode - <$> getFileStatus (fromRawFilePath dest) + destmode <- liftIO $ catchMaybeIO $ fileMode <$> R.getFileStatus dest replaceFile (fromRawFilePath dest) $ \tmp -> ifM (inAnnex key) ( do diff --git a/Utility/FileSize.hs b/Utility/FileSize.hs index dd8fc70d14..8544ad4179 100644 --- a/Utility/FileSize.hs +++ b/Utility/FileSize.hs @@ -33,7 +33,10 @@ getFileSize f = fmap (fromIntegral . fileSize) (getFileStatus f) getFileSize f = bracket (openFile f ReadMode) hClose hFileSize #endif -{- Gets the size of the file, when its FileStatus is already known. -} +{- Gets the size of the file, when its FileStatus is already known. + - + - On windows, uses getFileSize. Otherwise, the FileStatus contains the + - size, so this does not do any work. -} getFileSize' :: FilePath -> FileStatus -> IO FileSize #ifndef mingw32_HOST_OS getFileSize' _ s = return $ fromIntegral $ fileSize s diff --git a/Utility/InodeCache.hs b/Utility/InodeCache.hs index 97245b3493..a918e7bd08 100644 --- a/Utility/InodeCache.hs +++ b/Utility/InodeCache.hs @@ -22,6 +22,7 @@ module Utility.InodeCache ( readInodeCache, showInodeCache, genInodeCache, + genInodeCache', toInodeCache, likeInodeCacheWeak, @@ -43,6 +44,7 @@ module Utility.InodeCache ( import Common import Utility.TimeStamp import Utility.QuickCheck +import qualified Utility.RawFilePath as R import System.PosixCompat.Types import Data.Time.Clock.POSIX @@ -184,6 +186,10 @@ genInodeCache :: FilePath -> TSDelta -> IO (Maybe InodeCache) genInodeCache f delta = catchDefaultIO Nothing $ toInodeCache delta f =<< getFileStatus f +genInodeCache' :: RawFilePath -> TSDelta -> IO (Maybe InodeCache) +genInodeCache' f delta = catchDefaultIO Nothing $ + toInodeCache delta (fromRawFilePath f) =<< R.getFileStatus f + toInodeCache :: TSDelta -> FilePath -> FileStatus -> IO (Maybe InodeCache) toInodeCache (TSDelta getdelta) f s | isRegularFile s = do diff --git a/Utility/RawFilePath.hs b/Utility/RawFilePath.hs index 24f26e25ff..ff7057783f 100644 --- a/Utility/RawFilePath.hs +++ b/Utility/RawFilePath.hs @@ -17,11 +17,12 @@ module Utility.RawFilePath ( RawFilePath, readSymbolicLink, + getFileStatus, ) where #ifndef mingw32_HOST_OS +import Utility.FileSystemEncoding (RawFilePath) import System.Posix.Files.ByteString -import System.Posix.ByteString.FilePath #else import qualified Data.ByteString as B import qualified System.PosixCompat as P @@ -29,4 +30,7 @@ import Utility.FileSystemEncoding readSymbolicLink :: RawFilePath -> IO RawFilePath readSymbolicLink f = toRawFilePath <$> P.readSymbolicLink (fromRawFilePath f) + +getFileStatus :: RawFilePath -> IO FileStatus +getFileStatus = P.getFileStatus . fromRawFilePath #endif