on master help sign in
self brewed HashMap for HTTP/1.
commit96f05dfd70437a5b7fdc3a0e1e8cb10852549d7a authorKazu Yamamoto <kazu@iij.ad.jp> dateFri 25 Dec 2015, 14:44 (11 years ago) parente49a84e
7 files changed+82−35
warp/Network/Wai/Handler/Warp/FdCache.hs+9−6 warp/Network/Wai/Handler/Warp/FileInfoCache.hs+34−20 warp/Network/Wai/Handler/Warp/HashMap.hs+24 warp/Network/Wai/Handler/Warp/Response.hs+9−5 warp/Network/Wai/Handler/Warp/Run.hs+2−2 warp/Network/Wai/Handler/Warp/Types.hs+3 warp/warp.cabal+1−2
warp/Network/Wai/Handler/Warp/FdCache.hs+9−6
@@ -18,6 +18,7 @@ withFdCache _ f = f Nothing
1818module Network.Wai.Handler.Warp.FdCache (
1919 withFdCache
2020 , getFd
21+ , getFd'
2122 , MutableFdCache
2223 , Refresh
2324 ) where
@@ -139,16 +140,18 @@ terminate (Just (MutableFdCache reaper)) = do
139140
140141----------------------------------------------------------------
141142
142−-- | Getting 'Fd' and 'Refresh' from the mutable Fd cacher.
143143getFd :: MutableFdCache -> FilePath -> IO (Fd, Refresh)
144−getFd mfc@(MutableFdCache reaper) path = look mfc path key >>= getFd'
144+getFd mfc path = getFd' mfc (hash path) path
145+
146+-- | Getting 'Fd' and 'Refresh' from the mutable Fd cacher.
147+getFd' :: MutableFdCache -> Hash -> FilePath -> IO (Fd, Refresh)
148+getFd' mfc@(MutableFdCache reaper) h path = look mfc path h >>= get
145149 where
146− key = hash path
147− getFd' Nothing = do
150+ get Nothing = do
148151 ent@(FdEntry _ fd mst) <- newFdEntry path
149− reaperAdd reaper (key, ent)
152+ reaperAdd reaper (h, ent)
150153 return (fd, refresh mst)
151− getFd' (Just (FdEntry _ fd mst)) = do
154+ get (Just (FdEntry _ fd mst)) = do
152155 refresh mst
153156 return (fd, refresh mst)
154157#endif
warp/Network/Wai/Handler/Warp/FileInfoCache.hs+34−20
@@ -2,6 +2,7 @@
22
33module Network.Wai.Handler.Warp.FileInfoCache (
44 FileInfo(..)
5+ , Hash
56 , withFileInfoCache
67 , getInfo -- test purpose only
78 ) where
@@ -10,13 +11,16 @@ import Control.Exception as E
1011import Control.Monad (void)
1112import Control.Reaper
1213import Data.ByteString (ByteString)
13−import Data.HashMap.Strict (HashMap)
14−import qualified Data.HashMap.Strict as M
14+import Data.Hashable (hash)
1515import Network.HTTP.Date
16+import Network.Wai.Handler.Warp.HashMap (HashMap)
17+import qualified Network.Wai.Handler.Warp.HashMap as M
1618import System.PosixCompat.Files
1719
1820----------------------------------------------------------------
1921
22+type Hash = Int
23+
2024-- | File information.
2125data FileInfo = FileInfo {
2226 fileInfoName :: !FilePath
@@ -27,7 +31,7 @@ data FileInfo = FileInfo {
2731
2832data Entry = Negative | Positive FileInfo
2933type Cache = HashMap FilePath Entry
30−type FileInfoCache = Reaper Cache (FilePath,Entry)
34+type FileInfoCache = Reaper Cache (Int,FilePath,Entry)
3135
3236----------------------------------------------------------------
3337
@@ -51,25 +55,32 @@ getInfo path = do
5155 else
5256 throwIO (userError "FileInfoCache:getInfo")
5357
58+getInfo' :: Hash -> FilePath -> IO FileInfo
59+getInfo' _ = getInfo
60+
5461----------------------------------------------------------------
5562
5663getAndRegisterInfo :: FileInfoCache -> FilePath -> IO FileInfo
57−getAndRegisterInfo reaper@Reaper{..} path = do
64+getAndRegisterInfo reaper path = getAndRegisterInfo' reaper (hash path) path
65+
66+getAndRegisterInfo' :: FileInfoCache -> Hash -> FilePath -> IO FileInfo
67+getAndRegisterInfo' reaper@Reaper{..} h path = do
5868 cache <- reaperRead
59− case M.lookup path cache of
69+ case M.lookup h path cache of
6070 Just Negative -> throwIO (userError "FileInfoCache:getAndRegisterInfo")
6171 Just (Positive x) -> return x
62− Nothing -> positive reaper path `E.onException` negative reaper path
72+ Nothing -> positive reaper h path
73+ `E.onException` negative reaper h path
6374
64−positive :: FileInfoCache -> FilePath -> IO FileInfo
65−positive Reaper{..} path = do
75+positive :: FileInfoCache -> Hash -> FilePath -> IO FileInfo
76+positive Reaper{..} h path = do
6677 info <- getInfo path
67− reaperAdd (path, Positive info)
78+ reaperAdd (h, path, Positive info)
6879 return info
6980
70−negative :: FileInfoCache -> FilePath -> IO FileInfo
71−negative Reaper{..} path = do
72− reaperAdd (path,Negative)
81+negative :: FileInfoCache -> Hash -> FilePath -> IO FileInfo
82+negative Reaper{..} h path = do
83+ reaperAdd (h, path,Negative)
7384 throwIO (userError "FileInfoCache:negative")
7485
7586----------------------------------------------------------------
@@ -77,19 +88,22 @@ negative Reaper{..} path = do
7788-- | Creating a file information cache
7889-- and executing the action in the second argument.
7990-- The first argument is a cache duration in second.
80−withFileInfoCache :: Int -> ((FilePath -> IO FileInfo) -> IO a) -> IO a
81−withFileInfoCache 0 action = action getInfo
82−withFileInfoCache duration action = E.bracket (initialize duration)
83− terminate
84− (action . getAndRegisterInfo)
85−
86−initialize :: Int -> IO FileInfoCache
91+withFileInfoCache :: Int
92+ -> ((FilePath -> IO FileInfo) -> (Hash -> FilePath -> IO FileInfo) -> IO a)
93+ -> IO a
94+withFileInfoCache 0 action = action getInfo getInfo'
95+withFileInfoCache duration action =
96+ E.bracket (initialize duration)
97+ terminate
98+ (\r -> action (getAndRegisterInfo r) (getAndRegisterInfo' r))
99+
100+initialize :: Hash -> IO FileInfoCache
87101initialize duration = mkReaper settings
88102 where
89103 settings = defaultReaperSettings {
90104 reaperAction = override
91105 , reaperDelay = duration * 1000000
92− , reaperCons = uncurry M.insert
106+ , reaperCons = \(h,k,v) -> M.insert h k v
93107 , reaperNull = M.null
94108 , reaperEmpty = M.empty
95109 }
warp/Network/Wai/Handler/Warp/HashMap.hsnew file+24
@@ -0,0 +1,24 @@
1+module Network.Wai.Handler.Warp.HashMap where
2+
3+import Data.IntMap.Strict (IntMap)
4+import qualified Data.IntMap.Strict as I
5+import Data.Map.Strict (Map)
6+import qualified Data.Map.Strict as M
7+
8+type Hash = Int
9+newtype HashMap k v = HashMap (IntMap (Map k v))
10+
11+empty :: HashMap k v
12+empty = HashMap $ I.empty
13+
14+null :: HashMap k v -> Bool
15+null (HashMap hm) = I.null hm
16+
17+insert :: Ord k => Hash -> k -> v -> HashMap k v -> HashMap k v
18+insert h k v (HashMap hm) = HashMap $ I.insertWith f h m hm
19+ where
20+ m = M.singleton k v
21+ f = M.union -- fimxe
22+
23+lookup :: Ord k => Hash -> k -> HashMap k v -> Maybe v
24+lookup h k (HashMap hm) = I.lookup h hm >>= M.lookup k
warp/Network/Wai/Handler/Warp/Response.hs+9−5
@@ -36,6 +36,7 @@ import Data.ByteString.Builder (byteString, Builder)
3636import Data.ByteString.Builder.Extra (flush)
3737import qualified Data.CaseInsensitive as CI
3838import Data.Function (on)
39+import Data.Hashable (hash)
3940import Data.List (deleteBy)
4041import Data.Maybe
4142#if MIN_VERSION_base(4,5,0)
@@ -292,8 +293,9 @@ sendRsp conn _ _ _ _ (RspRaw withApp src tickle) = do
292293-- Sophisticated WAI applications.
293294-- We respect s0. s0 MUST be a proper value.
294295sendRsp conn ii ver s0 hs0 (RspFile path (Just part) _ isHead hook) =
295− sendRspFile2XX conn ii ver s0 hs path beg len isHead hook
296+ sendRspFile2XX conn ii ver s0 hs h path beg len isHead hook
296297 where
298+ h = hash path
297299 beg = filePartOffset part
298300 len = filePartByteCount part
299301 hs = addContentHeadersForFilePart hs0 part
@@ -303,7 +305,8 @@ sendRsp conn ii ver s0 hs0 (RspFile path (Just part) _ isHead hook) =
303305-- Simple WAI applications.
304306-- Status is ignored
305307sendRsp conn ii ver _ hs0 (RspFile path Nothing idxhdr isHead hook) = do
306− efinfo <- E.try $ fileInfo ii path
308+ let h = hash path
309+ efinfo <- E.try $ fileInfo' ii h path
307310 case efinfo of
308311 Left (_ex :: E.IOException) ->
309312#ifdef WARP_DEBUG
@@ -312,7 +315,7 @@ sendRsp conn ii ver _ hs0 (RspFile path Nothing idxhdr isHead hook) = do
312315 sendRspFile404 conn ii ver hs0
313316 Right finfo -> case conditionalRequest finfo hs0 idxhdr of
314317 WithoutBody s -> sendRsp conn ii ver s hs0 RspNoBody
315− WithBody s hs beg len -> sendRspFile2XX conn ii ver s hs path beg len isHead hook
318+ WithBody s hs beg len -> sendRspFile2XX conn ii ver s hs h path beg len isHead hook
316319
317320----------------------------------------------------------------
318321
@@ -321,13 +324,14 @@ sendRspFile2XX :: Connection
321324 -> H.HttpVersion
322325 -> H.Status
323326 -> H.ResponseHeaders
327+ -> Hash
324328 -> FilePath
325329 -> Integer
326330 -> Integer
327331 -> Bool
328332 -> IO ()
329333 -> IO (Maybe H.Status, Maybe Integer)
330−sendRspFile2XX conn ii ver s hs path beg len isHead hook
334+sendRspFile2XX conn ii ver s hs h path beg len isHead hook
331335 | isHead = sendRsp conn ii ver s hs RspNoBody
332336 | otherwise = do
333337 lheader <- composeHeader ver s hs
@@ -339,7 +343,7 @@ sendRspFile2XX conn ii ver s hs path beg len isHead hook
339343 -- settingsFdCacheDuration is 0
340344 Nothing -> return (Nothing, hook)
341345 Just fdc -> do
342− (fd, fresher) <- F.getFd fdc path
346+ (fd, fresher) <- F.getFd' fdc h path
343347 return (Just fd, hook >> fresher)
344348 let fid = FileId path mfd
345349#endif
warp/Network/Wai/Handler/Warp/Run.hs+2−2
@@ -176,9 +176,9 @@ runSettingsConnectionMakerSecure set getConnMaker app = do
176176 withII action =
177177 D.withDateCache $ \dc ->
178178 F.withFdCache fdCacheDurationInSeconds $ \fc ->
179− I.withFileInfoCache fdFileInfoDurationInSeconds $ \get ->
179+ I.withFileInfoCache fdFileInfoDurationInSeconds $ \get get' ->
180180 withTimeoutManager $ \tm -> do
181− let ii0 = InternalInfo undefined tm fc get dc -- fixme: undefined
181+ let ii0 = InternalInfo undefined tm fc get get' dc -- fixme: undefined
182182 action ii0
183183
184184 fdCacheDurationInSeconds = settingsFdCacheDuration set * 1000000
warp/Network/Wai/Handler/Warp/Types.hs+3
@@ -114,12 +114,15 @@ data Connection = Connection {
114114
115115----------------------------------------------------------------
116116
117+type Hash = Int
118+
117119-- | Internal information.
118120data InternalInfo = InternalInfo {
119121 threadHandle :: T.Handle
120122 , timeoutManager :: T.Manager
121123 , fdCacher :: Maybe F.MutableFdCache
122124 , fileInfo :: FilePath -> IO I.FileInfo
125+ , fileInfo' :: Int -> FilePath -> IO I.FileInfo
123126 , dateCacher :: D.DateCache
124127 }
125128
warp/warp.cabal+1−2
@@ -53,7 +53,6 @@ Library
5353 , stm >= 2.3
5454 , word8
5555 , hashable
56− , unordered-containers
5756 , http-date
5857 if flag(network-bytestring)
5958 Build-Depends: network >= 2.2.1.5 && < 2.2.3
@@ -69,6 +68,7 @@ Library
6968 Network.Wai.Handler.Warp.FdCache
7069 Network.Wai.Handler.Warp.File
7170 Network.Wai.Handler.Warp.FileInfoCache
71+ Network.Wai.Handler.Warp.HashMap
7272 Network.Wai.Handler.Warp.HTTP2
7373 Network.Wai.Handler.Warp.HTTP2.EncodeFrame
7474 Network.Wai.Handler.Warp.HTTP2.HPACK
@@ -166,7 +166,6 @@ Test-Suite spec
166166 , http2 >= 1.4 && < 1.5
167167 , word8
168168 , hashable
169− , unordered-containers
170169 , http-date
171170
172171 if (os(linux) || os(freebsd) || os(darwin)) && flag(allow-sendfilefd)