assistant: Logs are rotated to avoid them using too much disk space.
This cannot completely guard against a runaway log event, and only runs every hour anyway, but it should avoid most problems with very long-running, active assistants using up too much space.
This commit is contained in:
parent
fed56e24a4
commit
1865b28094
5 changed files with 73 additions and 34 deletions
|
@ -175,7 +175,7 @@ startDaemon assistant foreground startbrowser = do
|
||||||
fdToHandle =<< dup stdOutput
|
fdToHandle =<< dup stdOutput
|
||||||
origerr <- liftIO $ catchMaybeIO $
|
origerr <- liftIO $ catchMaybeIO $
|
||||||
fdToHandle =<< dup stdError
|
fdToHandle =<< dup stdError
|
||||||
liftIO $ Utility.Daemon.redirLog logfd
|
liftIO $ Utility.LogFile.redirLog logfd
|
||||||
showStart (if assistant then "assistant" else "watch") "."
|
showStart (if assistant then "assistant" else "watch") "."
|
||||||
start id $
|
start id $
|
||||||
case startbrowser of
|
case startbrowser of
|
||||||
|
@ -217,7 +217,8 @@ startDaemon assistant foreground startbrowser = do
|
||||||
, assist $ transferPollerThread
|
, assist $ transferPollerThread
|
||||||
, assist $ transfererThread
|
, assist $ transfererThread
|
||||||
, assist $ daemonStatusThread
|
, assist $ daemonStatusThread
|
||||||
, assist $ sanityCheckerThread
|
, assist $ sanityCheckerDailyThread
|
||||||
|
, assist $ sanityCheckerHourlyThread
|
||||||
, assist $ mountWatcherThread
|
, assist $ mountWatcherThread
|
||||||
, assist $ netWatcherThread
|
, assist $ netWatcherThread
|
||||||
, assist $ netWatcherFallbackThread
|
, assist $ netWatcherFallbackThread
|
||||||
|
|
|
@ -6,7 +6,8 @@
|
||||||
-}
|
-}
|
||||||
|
|
||||||
module Assistant.Threads.SanityChecker (
|
module Assistant.Threads.SanityChecker (
|
||||||
sanityCheckerThread
|
sanityCheckerDailyThread,
|
||||||
|
sanityCheckerHourlyThread
|
||||||
) where
|
) where
|
||||||
|
|
||||||
import Assistant.Common
|
import Assistant.Common
|
||||||
|
@ -15,12 +16,19 @@ import Assistant.Alert
|
||||||
import qualified Git.LsFiles
|
import qualified Git.LsFiles
|
||||||
import Utility.ThreadScheduler
|
import Utility.ThreadScheduler
|
||||||
import qualified Assistant.Threads.Watcher as Watcher
|
import qualified Assistant.Threads.Watcher as Watcher
|
||||||
|
import Utility.LogFile
|
||||||
|
|
||||||
import Data.Time.Clock.POSIX
|
import Data.Time.Clock.POSIX
|
||||||
|
|
||||||
{- This thread wakes up occasionally to make sure the tree is in good shape. -}
|
{- This thread wakes up hourly for inxepensive frequent sanity checks. -}
|
||||||
sanityCheckerThread :: NamedThread
|
sanityCheckerHourlyThread :: NamedThread
|
||||||
sanityCheckerThread = namedThread "SanityChecker" $ forever $ do
|
sanityCheckerHourlyThread = namedThread "SanityCheckerHourly" $ forever $ do
|
||||||
|
liftIO $ threadDelaySeconds $ Seconds oneHour
|
||||||
|
hourlyCheck
|
||||||
|
|
||||||
|
{- This thread wakes up daily to make sure the tree is in good shape. -}
|
||||||
|
sanityCheckerDailyThread :: NamedThread
|
||||||
|
sanityCheckerDailyThread = namedThread "SanityCheckerDaily" $ forever $ do
|
||||||
waitForNextCheck
|
waitForNextCheck
|
||||||
|
|
||||||
debug ["starting sanity check"]
|
debug ["starting sanity check"]
|
||||||
|
@ -31,7 +39,7 @@ sanityCheckerThread = namedThread "SanityChecker" $ forever $ do
|
||||||
modifyDaemonStatus_ $ \s -> s { sanityCheckRunning = True }
|
modifyDaemonStatus_ $ \s -> s { sanityCheckRunning = True }
|
||||||
|
|
||||||
now <- liftIO $ getPOSIXTime -- before check started
|
now <- liftIO $ getPOSIXTime -- before check started
|
||||||
r <- either showerr return =<< tryIO <~> check
|
r <- either showerr return =<< tryIO <~> dailyCheck
|
||||||
|
|
||||||
modifyDaemonStatus_ $ \s -> s
|
modifyDaemonStatus_ $ \s -> s
|
||||||
{ sanityCheckRunning = False
|
{ sanityCheckRunning = False
|
||||||
|
@ -57,14 +65,11 @@ waitForNextCheck = do
|
||||||
oneDay - truncate (now - lastcheck)
|
oneDay - truncate (now - lastcheck)
|
||||||
| otherwise = oneDay
|
| otherwise = oneDay
|
||||||
|
|
||||||
oneDay :: Int
|
|
||||||
oneDay = 24 * 60 * 60
|
|
||||||
|
|
||||||
{- It's important to stay out of the Annex monad as much as possible while
|
{- It's important to stay out of the Annex monad as much as possible while
|
||||||
- running potentially expensive parts of this check, since remaining in it
|
- running potentially expensive parts of this check, since remaining in it
|
||||||
- will block the watcher. -}
|
- will block the watcher. -}
|
||||||
check :: Assistant Bool
|
dailyCheck :: Assistant Bool
|
||||||
check = do
|
dailyCheck = do
|
||||||
g <- liftAnnex gitRepo
|
g <- liftAnnex gitRepo
|
||||||
-- Find old unstaged symlinks, and add them to git.
|
-- Find old unstaged symlinks, and add them to git.
|
||||||
(unstaged, cleanup) <- liftIO $ Git.LsFiles.notInRepo False ["."] g
|
(unstaged, cleanup) <- liftIO $ Git.LsFiles.notInRepo False ["."] g
|
||||||
|
@ -86,3 +91,32 @@ check = do
|
||||||
addsymlink file s = do
|
addsymlink file s = do
|
||||||
Watcher.runHandler Watcher.onAddSymlink file s
|
Watcher.runHandler Watcher.onAddSymlink file s
|
||||||
insanity $ "found unstaged symlink: " ++ file
|
insanity $ "found unstaged symlink: " ++ file
|
||||||
|
|
||||||
|
hourlyCheck :: Assistant ()
|
||||||
|
hourlyCheck = checkLogSize 0
|
||||||
|
|
||||||
|
{- Rotate logs until log file size is < 1 mb. -}
|
||||||
|
checkLogSize :: Int -> Assistant ()
|
||||||
|
checkLogSize n = do
|
||||||
|
f <- liftAnnex $ fromRepo gitAnnexLogFile
|
||||||
|
logs <- liftIO $ listLogs f
|
||||||
|
totalsize <- liftIO $ sum <$> mapM filesize logs
|
||||||
|
when (totalsize > oneMegabyte) $ do
|
||||||
|
notice ["Rotated logs due to size:", show totalsize]
|
||||||
|
liftIO $ do
|
||||||
|
rotateLog f
|
||||||
|
logfd <- openLog f
|
||||||
|
redirLog logfd
|
||||||
|
when (n < maxLogs + 1) $
|
||||||
|
checkLogSize $ n + 1
|
||||||
|
where
|
||||||
|
filesize f = fromIntegral . fileSize <$> liftIO (getFileStatus f)
|
||||||
|
|
||||||
|
oneMegabyte :: Int
|
||||||
|
oneMegabyte = 1000000
|
||||||
|
|
||||||
|
oneHour :: Int
|
||||||
|
oneHour = 60 * 60
|
||||||
|
|
||||||
|
oneDay :: Int
|
||||||
|
oneDay = 24 * oneHour
|
||||||
|
|
|
@ -8,6 +8,7 @@
|
||||||
module Utility.Daemon where
|
module Utility.Daemon where
|
||||||
|
|
||||||
import Common
|
import Common
|
||||||
|
import Utility.LogFile
|
||||||
|
|
||||||
import System.Posix
|
import System.Posix
|
||||||
|
|
||||||
|
@ -40,16 +41,6 @@ daemonize logfd pidfile changedirectory a = do
|
||||||
out
|
out
|
||||||
out = exitImmediately ExitSuccess
|
out = exitImmediately ExitSuccess
|
||||||
|
|
||||||
redirLog :: Fd -> IO ()
|
|
||||||
redirLog logfd = do
|
|
||||||
mapM_ (redir logfd) [stdOutput, stdError]
|
|
||||||
closeFd logfd
|
|
||||||
|
|
||||||
redir :: Fd -> Fd -> IO ()
|
|
||||||
redir newh h = do
|
|
||||||
closeFd h
|
|
||||||
void $ dupTo newh h
|
|
||||||
|
|
||||||
{- Locks the pid file, with an exclusive, non-blocking lock.
|
{- Locks the pid file, with an exclusive, non-blocking lock.
|
||||||
- Writes the pid to the file, fully atomically.
|
- Writes the pid to the file, fully atomically.
|
||||||
- Fails if the pid file is already locked by another process. -}
|
- Fails if the pid file is already locked by another process. -}
|
||||||
|
|
|
@ -13,22 +13,24 @@ import System.Posix
|
||||||
|
|
||||||
openLog :: FilePath -> IO Fd
|
openLog :: FilePath -> IO Fd
|
||||||
openLog logfile = do
|
openLog logfile = do
|
||||||
rotateLog logfile 0
|
rotateLog logfile
|
||||||
openFd logfile WriteOnly (Just stdFileMode)
|
openFd logfile WriteOnly (Just stdFileMode)
|
||||||
defaultFileFlags { append = True }
|
defaultFileFlags { append = True }
|
||||||
|
|
||||||
rotateLog :: FilePath -> Int -> IO ()
|
rotateLog :: FilePath -> IO ()
|
||||||
rotateLog logfile num
|
rotateLog logfile = go 0
|
||||||
| num > maxLogs = return ()
|
|
||||||
| otherwise = whenM (doesFileExist currfile) $ do
|
|
||||||
rotateLog logfile (num + 1)
|
|
||||||
renameFile currfile nextfile
|
|
||||||
where
|
where
|
||||||
currfile = filename num
|
go num
|
||||||
nextfile = filename (num + 1)
|
| num > maxLogs = return ()
|
||||||
filename n
|
| otherwise = whenM (doesFileExist currfile) $ do
|
||||||
| n == 0 = logfile
|
go (num + 1)
|
||||||
| otherwise = rotatedLog logfile n
|
renameFile currfile nextfile
|
||||||
|
where
|
||||||
|
currfile = filename num
|
||||||
|
nextfile = filename (num + 1)
|
||||||
|
filename n
|
||||||
|
| n == 0 = logfile
|
||||||
|
| otherwise = rotatedLog logfile n
|
||||||
|
|
||||||
rotatedLog :: FilePath -> Int -> FilePath
|
rotatedLog :: FilePath -> Int -> FilePath
|
||||||
rotatedLog logfile n = logfile ++ "." ++ show n
|
rotatedLog logfile n = logfile ++ "." ++ show n
|
||||||
|
@ -40,3 +42,13 @@ listLogs logfile = filterM doesFileExist $ reverse $
|
||||||
|
|
||||||
maxLogs :: Int
|
maxLogs :: Int
|
||||||
maxLogs = 9
|
maxLogs = 9
|
||||||
|
|
||||||
|
redirLog :: Fd -> IO ()
|
||||||
|
redirLog logfd = do
|
||||||
|
mapM_ (redir logfd) [stdOutput, stdError]
|
||||||
|
closeFd logfd
|
||||||
|
|
||||||
|
redir :: Fd -> Fd -> IO ()
|
||||||
|
redir newh h = do
|
||||||
|
closeFd h
|
||||||
|
void $ dupTo newh h
|
||||||
|
|
1
debian/changelog
vendored
1
debian/changelog
vendored
|
@ -4,6 +4,7 @@ git-annex (4.20130228) UNRELEASED; urgency=low
|
||||||
* Android: Enable test suite.
|
* Android: Enable test suite.
|
||||||
* webapp: Only show up to 10 queued transfers.
|
* webapp: Only show up to 10 queued transfers.
|
||||||
* Several improvements to Makefile and cabal file. Thanks, Peter Simmons
|
* Several improvements to Makefile and cabal file. Thanks, Peter Simmons
|
||||||
|
* assistant: Logs are rotated to avoid them using too much disk space.
|
||||||
|
|
||||||
-- Joey Hess <joeyh@debian.org> Wed, 27 Feb 2013 23:20:40 -0400
|
-- Joey Hess <joeyh@debian.org> Wed, 27 Feb 2013 23:20:40 -0400
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue