diff options
Diffstat (limited to 'src/Network/QueryResponse.hs')
-rw-r--r-- | src/Network/QueryResponse.hs | 47 |
1 files changed, 19 insertions, 28 deletions
diff --git a/src/Network/QueryResponse.hs b/src/Network/QueryResponse.hs index 0fa1a05a..70d981e2 100644 --- a/src/Network/QueryResponse.hs +++ b/src/Network/QueryResponse.hs | |||
@@ -108,18 +108,18 @@ partitionTransportM parse encodex tr = do | |||
108 | } | 108 | } |
109 | return (xtr, ytr) | 109 | return (xtr, ytr) |
110 | 110 | ||
111 | addHandler :: (addr -> x -> IO (Maybe (x -> x))) -> Transport err addr x -> Transport err addr x | 111 | addHandler :: ErrorReporter addr x meth tid err -> (addr -> x -> IO (Maybe (x -> x))) -> Transport err addr x -> Transport err addr x |
112 | addHandler f tr = tr | 112 | addHandler err f tr = tr |
113 | { awaitMessage = \kont -> fix $ \eat -> awaitMessage tr $ \m -> do | 113 | { awaitMessage = \kont -> fix $ \eat -> awaitMessage tr $ \m -> do |
114 | case m of | 114 | case m of |
115 | Just (Right (x, addr)) -> f addr x >>= maybe eat (kont . Just . Right . (, addr) . ($ x)) | 115 | Just (Right (x, addr)) -> f addr x >>= maybe eat (kont . Just . Right . (, addr) . ($ x)) |
116 | Just (Left e ) -> kont $ Just (Left e) | 116 | Just (Left e ) -> reportParseError err e >> kont (Just $ Left e) |
117 | Nothing -> kont $ Nothing | 117 | Nothing -> kont $ Nothing |
118 | } | 118 | } |
119 | 119 | ||
120 | -- | Modify a 'Transport' to invoke an action upon every received packet. | 120 | -- | Modify a 'Transport' to invoke an action upon every received packet. |
121 | onInbound :: (addr -> x -> IO ()) -> Transport err addr x -> Transport err addr x | 121 | onInbound :: (addr -> x -> IO ()) -> Transport err addr x -> Transport err addr x |
122 | onInbound f tr = addHandler (\addr x -> f addr x >> return (Just id)) tr | 122 | onInbound f tr = addHandler ignoreErrors (\addr x -> f addr x >> return (Just id)) tr |
123 | 123 | ||
124 | -- * Using a query\/response client. | 124 | -- * Using a query\/response client. |
125 | 125 | ||
@@ -153,16 +153,17 @@ sendQuery :: | |||
153 | -> a -- ^ The outbound query. | 153 | -> a -- ^ The outbound query. |
154 | -> addr -- ^ Destination address of query. | 154 | -> addr -- ^ Destination address of query. |
155 | -> IO (Maybe b) -- ^ The response, or 'Nothing' if it timed out. | 155 | -> IO (Maybe b) -- ^ The response, or 'Nothing' if it timed out. |
156 | sendQuery (Client net d err pending whoami _) meth q addr = do | 156 | sendQuery (Client net d err pending whoami _) meth q addr0 = do |
157 | mvar <- newEmptyMVar | 157 | mvar <- newEmptyMVar |
158 | tid <- atomically $ do | 158 | (tid,addr,expiry) <- atomically $ do |
159 | tbl <- readTVar pending | 159 | tbl <- readTVar pending |
160 | (tid, tbl') <- dispatchRegister (tableMethods d) mvar tbl | 160 | (tid, tbl') <- dispatchRegister (tableMethods d) mvar addr0 tbl |
161 | (addr,expiry) <- methodTimeout meth tid addr0 | ||
161 | writeTVar pending tbl' | 162 | writeTVar pending tbl' |
162 | return tid | 163 | return (tid,addr,expiry) |
163 | self <- whoami (Just addr) | 164 | self <- whoami (Just addr) |
164 | sendMessage net addr (wrapQuery meth tid self addr q) | 165 | sendMessage net addr (wrapQuery meth tid self addr q) |
165 | mres <- timeout (1000000 * methodTimeout meth) $ takeMVar mvar | 166 | mres <- timeout expiry $ takeMVar mvar |
166 | case mres of | 167 | case mres of |
167 | Just x -> return $ Just $ unwrapResponse meth x | 168 | Just x -> return $ Just $ unwrapResponse meth x |
168 | Nothing -> do | 169 | Nothing -> do |
@@ -248,8 +249,10 @@ dispatchQuery (NoReply unwrapQ f) tid self x addr = | |||
248 | -- peer-to-peer algorithm will define a 'MethodSerializer' for every 'MethodHandler' that | 249 | -- peer-to-peer algorithm will define a 'MethodSerializer' for every 'MethodHandler' that |
249 | -- might be returned by 'lookupHandler'. | 250 | -- might be returned by 'lookupHandler'. |
250 | data MethodSerializer tid addr x meth a b = MethodSerializer | 251 | data MethodSerializer tid addr x meth a b = MethodSerializer |
251 | { -- | Seconds to wait for a response. | 252 | { -- | Returns the microseconds to wait for a response to this query being |
252 | methodTimeout :: Int | 253 | -- sent to the given address. The /addr/ may also be modified to add |
254 | -- routing information. | ||
255 | methodTimeout :: tid -> addr -> STM (addr,Int) | ||
253 | -- | A method identifier used for error reporting. This needn't be the | 256 | -- | A method identifier used for error reporting. This needn't be the |
254 | -- same as the /meth/ argument to 'MethodHandler', but it is suggested. | 257 | -- same as the /meth/ argument to 'MethodHandler', but it is suggested. |
255 | , method :: meth | 258 | , method :: meth |
@@ -269,13 +272,13 @@ data MethodSerializer tid addr x meth a b = MethodSerializer | |||
269 | -- | 272 | -- |
270 | -- The type variable /d/ is used to represent the current state of the | 273 | -- The type variable /d/ is used to represent the current state of the |
271 | -- transaction generator and the table of pending transactions. | 274 | -- transaction generator and the table of pending transactions. |
272 | data TransactionMethods d tid x = TransactionMethods | 275 | data TransactionMethods d tid addr x = TransactionMethods |
273 | { | 276 | { |
274 | -- | Before a query is sent, this function stores an 'MVar' to which the | 277 | -- | Before a query is sent, this function stores an 'MVar' to which the |
275 | -- response will be written too. The returned /tid/ is a transaction id | 278 | -- response will be written too. The returned /tid/ is a transaction id |
276 | -- that can be used to forget the 'MVar' if the remote peer is not | 279 | -- that can be used to forget the 'MVar' if the remote peer is not |
277 | -- responding. | 280 | -- responding. |
278 | dispatchRegister :: MVar x -> d -> STM (tid, d) | 281 | dispatchRegister :: MVar x -> addr -> d -> STM (tid, d) |
279 | -- | This method is invoked when an incoming packet /x/ indicates it is | 282 | -- | This method is invoked when an incoming packet /x/ indicates it is |
280 | -- a response to the transaction with id /tid/. The returned IO action | 283 | -- a response to the transaction with id /tid/. The returned IO action |
281 | -- is will write the packet to the correct 'MVar' thus completing the | 284 | -- is will write the packet to the correct 'MVar' thus completing the |
@@ -318,27 +321,15 @@ instance Contravariant (TableMethods t) where | |||
318 | (\k t -> del (f k) t) | 321 | (\k t -> del (f k) t) |
319 | (\k t -> lookup (f k) t) | 322 | (\k t -> lookup (f k) t) |
320 | 323 | ||
321 | -- | Since 'Int' may be 32 or 64 bits, this function is provided as a | ||
322 | -- convenience to test if an integral type, such as 'Data.Word.Word64', can be | ||
323 | -- safely transformed into an 'Int' for use with 'IntMap'. | ||
324 | -- | ||
325 | -- Returns 'True' if the proxied type can be losslessly converted to 'Int' using | ||
326 | -- 'fromIntegral'. | ||
327 | fitsInInt :: forall word. (Bounded word, Integral word) => Proxy word -> Bool | ||
328 | fitsInInt Proxy = (original == casted) | ||
329 | where | ||
330 | original = div maxBound 2 :: word | ||
331 | casted = fromIntegral (fromIntegral original :: Int) :: word | ||
332 | |||
333 | -- | Construct 'TransactionMethods' methods out of 3 lookup table primitives and a | 324 | -- | Construct 'TransactionMethods' methods out of 3 lookup table primitives and a |
334 | -- function for generating unique transaction ids. | 325 | -- function for generating unique transaction ids. |
335 | transactionMethods :: | 326 | transactionMethods :: |
336 | TableMethods t tid -- ^ Table methods to lookup values by /tid/. | 327 | TableMethods t tid -- ^ Table methods to lookup values by /tid/. |
337 | -> (g -> (tid,g)) -- ^ Generate a new unique /tid/ value and update the generator state /g/. | 328 | -> (g -> (tid,g)) -- ^ Generate a new unique /tid/ value and update the generator state /g/. |
338 | -> TransactionMethods (g,t (MVar x)) tid x | 329 | -> TransactionMethods (g,t (MVar x)) tid addr x |
339 | transactionMethods (TableMethods insert delete lookup) generate = TransactionMethods | 330 | transactionMethods (TableMethods insert delete lookup) generate = TransactionMethods |
340 | { dispatchCancel = \tid (g,t) -> return (g, delete tid t) | 331 | { dispatchCancel = \tid (g,t) -> return (g, delete tid t) |
341 | , dispatchRegister = \v (g,t) -> | 332 | , dispatchRegister = \v _ (g,t) -> |
342 | let (tid,g') = generate g | 333 | let (tid,g') = generate g |
343 | t' = insert tid v t | 334 | t' = insert tid v t |
344 | in return ( tid, (g',t') ) | 335 | in return ( tid, (g',t') ) |
@@ -356,7 +347,7 @@ data DispatchMethods tbl err meth tid addr x = DispatchMethods | |||
356 | -- | Lookup the handler for a inbound query. | 347 | -- | Lookup the handler for a inbound query. |
357 | , lookupHandler :: meth -> Maybe (MethodHandler err tid addr x) | 348 | , lookupHandler :: meth -> Maybe (MethodHandler err tid addr x) |
358 | -- | Methods for handling incoming responses. | 349 | -- | Methods for handling incoming responses. |
359 | , tableMethods :: TransactionMethods tbl tid x | 350 | , tableMethods :: TransactionMethods tbl tid addr x |
360 | } | 351 | } |
361 | 352 | ||
362 | -- | These methods indicate what should be done upon various conditions. Write | 353 | -- | These methods indicate what should be done upon various conditions. Write |