packages feed

fast-logger (empty) → 0.0.0

raw patch · 5 files changed

+196/−0 lines, 5 filesdep +basedep +blaze-builderdep +bytestringsetup-changed

Dependencies added: base, blaze-builder, bytestring, directory, filepath

Files

+ LICENSE view
@@ -0,0 +1,29 @@+Copyright (c) 2009, IIJ Innovation Institute Inc.+All rights reserved.++Redistribution and use in source and binary forms, with or without+modification, are permitted provided that the following conditions+are met:++  * Redistributions of source code must retain the above copyright+    notice, this list of conditions and the following disclaimer.+  * Redistributions in binary form must reproduce the above copyright+    notice, this list of conditions and the following disclaimer in+    the documentation and/or other materials provided with the+    distribution.+  * Neither the name of the copyright holders nor the names of its+    contributors may be used to endorse or promote products derived+    from this software without specific prior written permission.++THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS+FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE+COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,+INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,+BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER+CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT+LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN+ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE+POSSIBILITY OF SUCH DAMAGE.
+ Setup.hs view
@@ -0,0 +1,2 @@+import Distribution.Simple+main = defaultMain
+ System/Log/FastLogger.hs view
@@ -0,0 +1,102 @@+{-# LANGUAGE DoAndIfThenElse, NoImplicitPrelude, RecordWildCards #-}++-- | Fast logging system to copy log data directly to Handle buffer.++module System.Log.FastLogger (+  -- * Initialization+    initHandle+  -- * Logging+  , LogStr(..)+  , hPutLogStr+  -- * Builder+  , hPutBuilder+  -- * File rotation+  , module System.Log.FastLogger.File+  ) where++import Blaze.ByteString.Builder+import qualified Data.ByteString as BS+import Data.ByteString.Internal (ByteString(..), c2w)+import Data.List+import Data.Maybe+import Foreign+import GHC.Base+import GHC.IO.Buffer+import qualified GHC.IO.BufferedIO as Buffered+import GHC.IO.Handle.Internals+import GHC.IO.Handle.Text+import GHC.IO.Handle.Types+import GHC.IORef+import GHC.Num+import GHC.Real+import System.IO+import System.Log.FastLogger.File++{-| Setting a proper buffering to 'Handle'.+-}+initHandle :: Handle -> IO ()+initHandle hdl = hSetBuffering hdl (BlockBuffering (Just 4096))++{-| A date type to contain 'String' and 'ByteString'.+    This data is exported so that format can be defined.+    This would be replaced with 'Builder' someday when+    it can be written directly to 'Handle' buffer.+-}+data LogStr = LS !String | LB !ByteString++{-| The 'hPut' function to copy a list of 'LogStr' to the buffer+    of 'Handle' directly.+    If 'Handle' is associated with a file, 'AppendMode' must be used.+-}+hPutLogStr :: Handle -> [LogStr] -> IO ()+hPutLogStr handle bss =+  wantWritableHandle "hPutLogStr" handle $ \h_ -> bufsWrite h_ bss++bufsWrite :: Handle__-> [LogStr] -> IO ()+bufsWrite h_@Handle__{..} bss = do+    old_buf@Buffer{+        bufRaw = old_raw+      , bufR = w+      , bufSize = size+      } <- readIORef haByteBuffer+    if size - w > len then do+        withRawBuffer old_raw $ \ptr ->+            go (ptr `plusPtr` w)  bss+        writeIORef haByteBuffer old_buf{ bufR = w + len }+    else do+        old_buf' <- Buffered.flushWriteBuffer haDevice old_buf+        writeIORef haByteBuffer old_buf'+        bufsWrite h_ bss+  where+    len = foldl' (\x y -> x + getLength y) 0 bss+    getLength (LB s) = BS.length s+    getLength (LS s) = length s+    go :: Ptr Word8 -> [LogStr] -> IO ()+    go _ [] = return ()+    go dst (LB b:bs) = do+      dst' <- copy dst b+      go dst' bs+    go dst (LS s:ss) = do+      dst' <- copy' dst s+      go dst' ss++copy :: Ptr Word8 -> ByteString -> IO (Ptr Word8)+copy dst (PS ptr off len) = withForeignPtr ptr $ \s -> do+    let src = s `plusPtr` off+    memcpy dst src (fromIntegral len)+    return (dst `plusPtr` len)++copy' :: Ptr Word8 -> String -> IO (Ptr Word8)+copy' dst [] = return dst+copy' dst (x:xs) = do+    poke dst (c2w x)+    copy' (dst `plusPtr` 1) xs++{-| The 'hPut' function directory to copy 'Builder' to the buffer.+    If 'Handle' is associated with a file, 'AppendMode' must be used.+    The current implementation is inefficient at this moment.+    'initHandle' must be called once beforehand if this function is used.+    This would replace 'hPutLogStr' someday.+-}+hPutBuilder :: Handle -> Builder -> IO ()+hPutBuilder hdl = BS.hPut hdl . toByteString
+ System/Log/FastLogger/File.hs view
@@ -0,0 +1,42 @@+module System.Log.FastLogger.File where++import Control.Monad+import System.Directory+import System.FilePath++-- | The spec for logging files+data FileLogSpec = FileLogSpec {+    log_file :: String+  , log_file_size :: Integer+  , log_backup_number :: Int+  }++-- | Checking if a log file can be written.+check :: FileLogSpec -> IO ()+check spec = do+    dirExist <- doesDirectoryExist dir+    unless dirExist $ fail $ dir ++ " does not exist or is not a directory."+    dirPerm <- getPermissions dir+    unless (writable dirPerm) $ fail $ dir ++ " is not writable."+    exist <- doesFileExist file+    when exist $ do+        perm <- getPermissions file+        unless (writable perm) $ fail $ file ++ " is not writable."+  where+    file = log_file spec+    dir = takeDirectory file++-- | Rotating log files.+rotate :: FileLogSpec -> IO ()+rotate spec = mapM_ move srcdsts+  where+    path = log_file spec+    n = log_backup_number spec+    dsts' = reverse . ("":) . map (('.':). show) $ [0..n-1]+    dsts = map (path++) dsts'+    srcs = tail dsts+    srcdsts = zip srcs dsts+    move (src,dst) = do+        exist <- doesFileExist src+        when exist $ renameFile src dst+
+ fast-logger.cabal view
@@ -0,0 +1,21 @@+Name:                   fast-logger+Version:                0.0.0+Author:                 Kazu Yamamoto <kazu@iij.ad.jp>+Maintainer:             Kazu Yamamoto <kazu@iij.ad.jp>+License:                BSD3+License-File:           LICENSE+Synopsis:               A fast logging system+Description:            A fast logging system+Category:               System+Cabal-Version:          >= 1.6+Build-Type:             Simple+library+  GHC-Options:          -Wall -fno-warn-unused-do-bind+  Exposed-Modules:      System.Log.FastLogger+                        System.Log.FastLogger.File+  Build-Depends:        base >= 4 && < 5,+                        filepath, directory, bytestring, blaze-builder+Source-Repository head+  Type:                 git+  Location:             git://github.com/kazu-yamamoto/fast-logger.git+