on master help sign in
adding FdCache.
commite55e81f56c315ba557754b4078724b8e593725ad authorKazu Yamamoto <kazu@iij.ad.jp> dateThu 6 Sep 2012, 11:47 (14 years ago) parent76b2e7f
2 files changed+159−4
warp/Network/Wai/Handler/Warp/FdCache.hs+123 warp/Network/Wai/Handler/Warp/MultiMap.hs+36−4
warp/Network/Wai/Handler/Warp/FdCache.hsnew file+123
@@ -0,0 +1,123 @@
1+{-# LANGUAGE BangPatterns, FlexibleInstances #-}
2+
3+module Network.Wai.Handler.Warp.FdCache (
4+ initialize
5+ , getFd
6+ ) where
7+
8+import Control.Applicative ((<$>), (<*>))
9+import Control.Concurrent
10+import Control.Monad
11+import Data.Hashable
12+import Data.IORef
13+import Network.Wai.Handler.Warp.MultiMap
14+import System.Posix.IO
15+import System.Posix.Types
16+import System.IO.Unsafe
17+
18+----------------------------------------------------------------
19+
20+data Status = Active | Inactive deriving Show
21+
22+newtype MutableStatus = MutableStatus (IORef Status) deriving Show
23+
24+instance Show (IORef Status) where
25+ show ref = show (unsafePerformIO (readIORef ref))
26+
27+type Refresh = IO ()
28+
29+status :: MutableStatus -> IO Status
30+status (MutableStatus ref) = readIORef ref
31+
32+newActiveStatus :: IO MutableStatus
33+newActiveStatus = MutableStatus <$> newIORef Active
34+
35+refresh :: MutableStatus -> Refresh
36+refresh (MutableStatus ref) = writeIORef ref Active
37+
38+inactive :: MutableStatus -> IO ()
39+inactive (MutableStatus ref) = writeIORef ref Inactive
40+
41+----------------------------------------------------------------
42+
43+data FdEntry = FdEntry FilePath Fd MutableStatus deriving Show
44+
45+newFdEntry :: FilePath -> IO FdEntry
46+newFdEntry path = FdEntry path
47+ <$> openFd path ReadOnly Nothing defaultFileFlags
48+ <*> newActiveStatus
49+
50+----------------------------------------------------------------
51+
52+type Hash = Int
53+type FdCache = MMap Hash FdEntry
54+newtype MutableFdCache = MutableFdCache (IORef FdCache)
55+
56+newMutableFdCache :: IO MutableFdCache
57+newMutableFdCache = MutableFdCache <$> newIORef empty
58+
59+fdCache :: MutableFdCache -> IO FdCache
60+fdCache (MutableFdCache ref) = readIORef ref
61+
62+swapWithNew :: MutableFdCache -> IO FdCache
63+swapWithNew (MutableFdCache ref) = atomicModifyIORef ref (\t -> (empty, t))
64+
65+update :: MutableFdCache -> (FdCache -> FdCache) -> IO ()
66+update (MutableFdCache ref) f = do
67+ !_ <- atomicModifyIORef ref $ \t -> let !new = f t in (new, ())
68+ return ()
69+
70+look :: MutableFdCache -> FilePath -> Hash -> IO (Maybe FdEntry)
71+look mfc path key = searchWith key check <$> fdCache mfc
72+ where
73+ check (One ent@(FdEntry path' _ _))
74+ | path == path' = Just ent
75+ | otherwise = Nothing
76+ check (Tom ent@(FdEntry path' _ _) vs)
77+ | path == path' = Just ent
78+ | otherwise = check vs
79+
80+----------------------------------------------------------------
81+
82+initialize :: IO MutableFdCache
83+initialize = do
84+ mfc <- newMutableFdCache
85+ void . forkIO $ loop mfc
86+ return mfc
87+ where
88+ loop mfc = do
89+ old <- swapWithNew mfc
90+ new <- pruneWith old prune
91+ update mfc (merge new)
92+ threadDelay 30000000 -- FIXME
93+ loop mfc
94+
95+prune :: t -> Some FdEntry -> IO [(t, Some FdEntry)]
96+prune k v@(One (FdEntry _ fd mst)) = status mst >>= prune'
97+ where
98+ prune' Active = inactive mst >> return [(k,v)]
99+ prune' Inactive = closeFd fd >> return []
100+prune k (Tom ent@(FdEntry _ fd mst) vs) = status mst >>= prune'
101+ where
102+ prune' Active = do
103+ inactive mst
104+ zs <- prune k vs
105+ case zs of
106+ [] -> return [(k,One ent)]
107+ [(_,zvs)] -> return [(k,Tom ent zvs)]
108+ _ -> error "prune"
109+ prune' Inactive = closeFd fd >> prune k vs
110+
111+----------------------------------------------------------------
112+
113+getFd :: MutableFdCache -> FilePath -> IO (Fd, Refresh)
114+getFd mfc path = look mfc path key >>= getFd'
115+ where
116+ key = hash path
117+ getFd' Nothing = do
118+ ent@(FdEntry _ fd mst) <- newFdEntry path
119+ update mfc (insert key ent)
120+ return $ (fd, refresh mst)
121+ getFd' (Just (FdEntry _ fd mst)) = do
122+ refresh mst
123+ return $ (fd, refresh mst)
warp/Network/Wai/Handler/Warp/MultiMap.hs+36−4
@@ -1,15 +1,19 @@
11module Network.Wai.Handler.Warp.MultiMap (
22 MMap
3+ , Some(..)
34 , empty
45 , singleton
56 , insert
67 , search
8+ , searchWith
79 , isEmpty
810 , valid
9− , purgeWith
11+ , pruneWith
1012 , fromList
13+ , toList
1114 , fromSortedList
1215 , toSortedList
16+ , merge
1317 ) where
1418
1519import Control.Applicative ((<$>))
@@ -57,6 +61,14 @@ search xk (Node _ l k v r) = case compare xk k of
5761 GT -> search xk r
5862 EQ -> Just $ top v
5963
64+-- | O(log N)
65+searchWith :: Ord k => k -> (Some v -> Maybe v) -> MMap k v -> Maybe v
66+searchWith _ _ Leaf = Nothing
67+searchWith xk f (Node _ l k v r) = case compare xk k of
68+ LT -> searchWith xk f l
69+ GT -> searchWith xk f r
70+ EQ -> f v
71+
6072----------------------------------------------------------------
6173
6274-- | O(1)
@@ -115,6 +127,15 @@ turnB (Node _ l k v r) = Node B l k v r
115127fromList :: Ord k => [(k,v)] -> MMap k v
116128fromList = foldl' (\t (k,v) -> insert k v t) empty
117129
130+-- | O(N)
131+toList :: MMap k v -> [(k,v)]
132+toList t = inorder t []
133+ where
134+ inorder Leaf xs = xs
135+ inorder (Node _ l k v r) xs = inorder l (pairs k v ++ inorder r xs)
136+ pairs k (One v) = [(k,v)]
137+ pairs k (Tom v vs) = (k,v) : pairs k vs
138+
118139----------------------------------------------------------------
119140
120141-- | O(N)
@@ -155,9 +176,11 @@ toSortedList t = inorder t []
155176----------------------------------------------------------------
156177
157178-- | O(N)
158−purgeWith :: Ord k => (k -> Some v -> IO [(k, Some v)])
159− -> MMap k v -> IO (MMap k v)
160−purgeWith run t = fromSortedList <$> inorder t []
179+pruneWith :: Ord k =>
180+ MMap k v
181+ -> (k -> Some v -> IO [(k, Some v)])
182+ -> IO (MMap k v)
183+pruneWith t run = fromSortedList <$> inorder t []
161184 where
162185 inorder Leaf xs = return xs
163186 inorder (Node _ l k v r) xs = do
@@ -165,6 +188,15 @@ purgeWith run t = fromSortedList <$> inorder t []
165188 zs <- inorder r xs
166189 inorder l (ys ++ zs)
167190
191+----------------------------------------------------------------
192+
193+-- O(N) where N is the size of the second argument
194+merge :: Ord k => MMap k v -> MMap k v -> MMap k v
195+merge base m = foldl' ins base xs
196+ where
197+ ins t (k,v) = insert k v t
198+ xs = toList m
199+
168200----------------------------------------------------------------
169201-- for testing
170202