packages feed

fast-logger 3.2.7 → 3.2.8

raw patch · 5 files changed

+130/−2 lines, 5 filesPVP ok

version bump matches the API change (PVP)

API changes (from Hackage documentation)

Files

ChangeLog.md view
@@ -1,3 +1,8 @@+## 3.2.8++* Take another road under the Windows native I/O manager+  [#222](https://github.com/kazu-yamamoto/logger/pull/222)+ ## 3.2.7  * Don't eat up an asynchronous exception.
System/Log/FastLogger.hs view
@@ -108,6 +108,15 @@         --   'BufSize' is a buffer size         --   for each capability.         --   File rotation is done on-demand.+        --+        --   On Windows this needs the native I\/O manager+        --   (@+RTS --io-manager=native@).  Rotation renames the+        --   log file while it is still open, which the+        --   descriptor the POSIX subsystem opens there is not+        --   shared for; the rename is refused and the file+        --   stops rotating.  Nothing is lost -- the log keeps+        --   being written to the one file, past the size asked+        --   for.     LogFileTimedRotate         :: TimedFileLogSpec         -> BufSize
System/Log/FastLogger/File.hs view
@@ -76,6 +76,14 @@     dir = takeDirectory file  -- | Rotating log files.+--+-- The log file is renamed while it is still open, which every platform+-- allows except Windows, and Windows allows it only of a file opened+-- sharing deletion.  The descriptor 'GHC.IO.FD' opens is not, so under the+-- POSIX subsystem there -- @+RTS --io-manager=posix@, which is still the+-- default -- this is refused and the file does not rotate.  Under the+-- native one the file is a 'System.IO.Handle', which is shared for+-- deletion, and it does. rotate :: FileLogSpec -> IO () rotate spec = mapM_ move srcdsts   where
System/Log/FastLogger/FileIO.hs view
@@ -1,5 +1,25 @@-module System.Log.FastLogger.FileIO where+{-# LANGUAGE CPP #-} +-- | Where the bytes actually go.+--+-- The rest of fast-logger fills its own buffer and hands it here as a raw+-- pointer, so this is deliberately one layer below 'Handle': the point of+-- 'writeRawBufferPtr2FD' is that nothing buffers the bytes a second time.+--+-- Windows has two I\/O subsystems and chooses between them at run time, from+-- the @--io-manager=@ RTS flag, so on Windows an 'FD' is one of two things.+-- See the note on 'openFileFD'.+module System.Log.FastLogger.FileIO (+    FD,+    closeFD,+    openFileFD,+    getStderrFD,+    getStdoutFD,+    writeRawBufferPtr2FD,+    invalidFD,+    isFDValid,+) where+ import Foreign.Ptr (Ptr) import GHC.IO.Device (close) import GHC.IO.FD (openFile, stderr, stdout, writeRawBufferPtr)@@ -8,6 +28,90 @@  import System.Log.FastLogger.Imports +#if defined(mingw32_HOST_OS)+import GHC.IO.SubSystem (isWindowsNativeIO)+import qualified System.IO as SIO+#endif++#if defined(mingw32_HOST_OS)++-- | A file descriptor, or on Windows under the native I\/O manager a+--   'SIO.Handle' standing in for one.+data FD+    = PosixFD !POSIX.FD+    | -- | Under the native I\/O manager.  The 'SIO.Handle' is left with+      -- whatever buffering it came with and flushed after every write, so+      -- the bytes are no more buffered than they were before.+      NativeFD !SIO.Handle+    | InvalidFD++-- | Opening a log file for appending.+--+-- Under the POSIX subsystem this is a file descriptor, as it always was.+--+-- Under the native subsystem it cannot be.  There a 'POSIX.FD' is a C+-- runtime descriptor, and the I\/O manager works in terms of Windows+-- handles registered with a completion port; the two cannot be mixed, and+-- @base@ says so by replacing every method of @IODevice FD@ and @RawIO FD@+-- with an @error@ when that subsystem is in force.  Opening and the raw+-- write happen to be plain functions and so still work, which is the trap:+-- a log file could be written and never closed, and it stayed locked for+-- the life of the process.+--+-- 'SIO.openFile' gives a handle the running subsystem owns, whichever it+-- is.  Appending is its business too, which matters because the native+-- subsystem writes at an offset given per call and has no @O_APPEND@ of+-- its own.+openFileFD :: FilePath -> IO FD+openFileFD f+    | isWindowsNativeIO = NativeFD <$> SIO.openFile f SIO.AppendMode+    | otherwise = PosixFD . fst <$> openFile f AppendMode False++-- | The standard streams are handed to us, not opened by us, and under the+--   native subsystem the descriptor numbered 1 is not what the process is+--   actually writing through: bytes put there were accepted and never+--   appeared.+getStdoutFD :: IO FD+getStdoutFD+    | isWindowsNativeIO = return $ NativeFD SIO.stdout+    | otherwise = return $ PosixFD stdout++getStderrFD :: IO FD+getStderrFD+    | isWindowsNativeIO = return $ NativeFD SIO.stderr+    | otherwise = return $ PosixFD stderr++-- | Only ever called for a log file, never for a standard stream.+closeFD :: FD -> IO ()+closeFD (PosixFD fd) = close fd+closeFD (NativeFD h) = SIO.hClose h+closeFD InvalidFD = return ()++writeRawBufferPtr2FD :: IORef FD -> Ptr Word8 -> Int -> IO Int+writeRawBufferPtr2FD fdref bf len = do+    fd <- readIORef fdref+    case fd of+        PosixFD fd'+            | POSIX.fdFD fd' /= -1 ->+                fromIntegral <$> writeRawBufferPtr "write" fd' bf 0 (fromIntegral len)+        -- 'SIO.hPutBuf' writes all of it or raises; there is no short write+        -- to report back.+        NativeFD h -> do+            SIO.hPutBuf h bf len+            SIO.hFlush h+            return len+        _ -> return (-1)++invalidFD :: FD+invalidFD = InvalidFD++isFDValid :: FD -> Bool+isFDValid (PosixFD fd) = POSIX.fdFD fd /= -1+isFDValid (NativeFD _) = True+isFDValid InvalidFD = False++#else+ type FD = POSIX.FD  closeFD :: FD -> IO ()@@ -36,3 +140,5 @@  isFDValid :: POSIX.FD -> Bool isFDValid fd = POSIX.fdFD fd /= -1++#endif
fast-logger.cabal view
@@ -1,6 +1,6 @@ cabal-version:      >=1.10 name:               fast-logger-version:            3.2.7+version:            3.2.8 license:            BSD3 license-file:       LICENSE maintainer:         Kazu Yamamoto <kazu@iij.ad.jp>