diff options
author | joe <joe@jerkface.net> | 2017-09-30 16:21:51 -0400 |
---|---|---|
committer | joe <joe@jerkface.net> | 2017-09-30 16:21:51 -0400 |
commit | f1622c7135cdb8725dc1e13c8d1adb49c269cc2d (patch) | |
tree | a01eabfed62897822952ff619d65f9d31792fa6d /src/Network/QueryResponse.hs | |
parent | a89c59ed151a41f46355187363957c3c292b60bc (diff) |
This makes TransactionMethods into STM actions so that they can be
synced with an auxiliary data structure. I also made Contravariant
instances since we depend on contravariant anyway now.
Diffstat (limited to 'src/Network/QueryResponse.hs')
-rw-r--r-- | src/Network/QueryResponse.hs | 44 |
1 files changed, 25 insertions, 19 deletions
diff --git a/src/Network/QueryResponse.hs b/src/Network/QueryResponse.hs index b7a402b4..8c793a1a 100644 --- a/src/Network/QueryResponse.hs +++ b/src/Network/QueryResponse.hs | |||
@@ -22,6 +22,7 @@ import Control.Monad | |||
22 | import qualified Data.ByteString as B | 22 | import qualified Data.ByteString as B |
23 | ;import Data.ByteString (ByteString) | 23 | ;import Data.ByteString (ByteString) |
24 | import Data.Function | 24 | import Data.Function |
25 | import Data.Functor.Contravariant | ||
25 | import qualified Data.IntMap.Strict as IntMap | 26 | import qualified Data.IntMap.Strict as IntMap |
26 | ;import Data.IntMap.Strict (IntMap) | 27 | ;import Data.IntMap.Strict (IntMap) |
27 | import qualified Data.Map.Strict as Map | 28 | import qualified Data.Map.Strict as Map |
@@ -160,7 +161,7 @@ sendQuery (Client net d err pending whoami _) meth q addr = do | |||
160 | mvar <- newEmptyMVar | 161 | mvar <- newEmptyMVar |
161 | tid <- atomically $ do | 162 | tid <- atomically $ do |
162 | tbl <- readTVar pending | 163 | tbl <- readTVar pending |
163 | let (tid, tbl') = dispatchRegister (tableMethods d) mvar tbl | 164 | (tid, tbl') <- dispatchRegister (tableMethods d) mvar tbl |
164 | writeTVar pending tbl' | 165 | writeTVar pending tbl' |
165 | return tid | 166 | return tid |
166 | self <- whoami (Just addr) | 167 | self <- whoami (Just addr) |
@@ -169,7 +170,7 @@ sendQuery (Client net d err pending whoami _) meth q addr = do | |||
169 | case mres of | 170 | case mres of |
170 | Just x -> return $ Just $ unwrapResponse meth x | 171 | Just x -> return $ Just $ unwrapResponse meth x |
171 | Nothing -> do | 172 | Nothing -> do |
172 | atomically $ modifyTVar' pending (dispatchCancel (tableMethods d) tid) | 173 | atomically $ readTVar pending >>= dispatchCancel (tableMethods d) tid >>= writeTVar pending |
173 | reportTimeout err (method meth) tid addr | 174 | reportTimeout err (method meth) tid addr |
174 | return Nothing | 175 | return Nothing |
175 | 176 | ||
@@ -278,15 +279,15 @@ data TransactionMethods d tid x = TransactionMethods | |||
278 | -- response will be written too. The returned /tid/ is a transaction id | 279 | -- response will be written too. The returned /tid/ is a transaction id |
279 | -- that can be used to forget the 'MVar' if the remote peer is not | 280 | -- that can be used to forget the 'MVar' if the remote peer is not |
280 | -- responding. | 281 | -- responding. |
281 | dispatchRegister :: MVar x -> d -> (tid, d) | 282 | dispatchRegister :: MVar x -> d -> STM (tid, d) |
282 | -- | This method is invoked when an incomming packet /x/ indicates it is | 283 | -- | This method is invoked when an incomming packet /x/ indicates it is |
283 | -- a response to the transaction with id /tid/. The returned IO action | 284 | -- a response to the transaction with id /tid/. The returned IO action |
284 | -- is will write the packet to the correct 'MVar' thus completing the | 285 | -- is will write the packet to the correct 'MVar' thus completing the |
285 | -- dispatch. | 286 | -- dispatch. |
286 | , dispatchResponse :: tid -> x -> d -> (d, IO ()) | 287 | , dispatchResponse :: tid -> x -> d -> STM (d, IO ()) |
287 | -- | When a timeout interval elapses, this method is called to remove the | 288 | -- | When a timeout interval elapses, this method is called to remove the |
288 | -- transaction from the table. | 289 | -- transaction from the table. |
289 | , dispatchCancel :: tid -> d -> d | 290 | , dispatchCancel :: tid -> d -> STM d |
290 | } | 291 | } |
291 | 292 | ||
292 | -- | The standard lookup table methods for use as input to 'transactionMethods' | 293 | -- | The standard lookup table methods for use as input to 'transactionMethods' |
@@ -314,10 +315,12 @@ mapMethods = TableMethods Map.insert Map.delete Map.lookup | |||
314 | -- only a part of the generated /tid/ value. This is useful for /tid/ types | 315 | -- only a part of the generated /tid/ value. This is useful for /tid/ types |
315 | -- that are especially large due their use for other purposes, such as secure | 316 | -- that are especially large due their use for other purposes, such as secure |
316 | -- nonces for encryption. | 317 | -- nonces for encryption. |
317 | contramapT f (TableMethods ins del lookup) = | 318 | instance Contravariant (TableMethods t) where |
318 | TableMethods (\k v t -> ins (f k) v t) | 319 | -- contramap :: (tid -> t1) -> TableMethods t t1 -> TableMethods t tid |
319 | (\k t -> del (f k) t) | 320 | contramap f (TableMethods ins del lookup) = |
320 | (\k t -> lookup (f k) t) | 321 | TableMethods (\k v t -> ins (f k) v t) |
322 | (\k t -> del (f k) t) | ||
323 | (\k t -> lookup (f k) t) | ||
321 | 324 | ||
322 | -- | Since 'Int' may be 32 or 64 bits, this function is provided as a | 325 | -- | Since 'Int' may be 32 or 64 bits, this function is provided as a |
323 | -- convenience to test if an integral type, such as 'Data.Word.Word64', can be | 326 | -- convenience to test if an integral type, such as 'Data.Word.Word64', can be |
@@ -338,16 +341,16 @@ transactionMethods :: | |||
338 | -> (g -> (tid,g)) -- ^ Generate a new unique /tid/ value and update the generator state /g/. | 341 | -> (g -> (tid,g)) -- ^ Generate a new unique /tid/ value and update the generator state /g/. |
339 | -> TransactionMethods (g,t (MVar x)) tid x | 342 | -> TransactionMethods (g,t (MVar x)) tid x |
340 | transactionMethods (TableMethods insert delete lookup) generate = TransactionMethods | 343 | transactionMethods (TableMethods insert delete lookup) generate = TransactionMethods |
341 | { dispatchCancel = \tid (g,t) -> (g, delete tid t) | 344 | { dispatchCancel = \tid (g,t) -> return (g, delete tid t) |
342 | , dispatchRegister = \v (g,t) -> | 345 | , dispatchRegister = \v (g,t) -> |
343 | let (tid,g') = generate g | 346 | let (tid,g') = generate g |
344 | t' = insert tid v t | 347 | t' = insert tid v t |
345 | in ( tid, (g',t') ) | 348 | in return ( tid, (g',t') ) |
346 | , dispatchResponse = \tid x (g,t) -> | 349 | , dispatchResponse = \tid x (g,t) -> |
347 | case lookup tid t of | 350 | case lookup tid t of |
348 | Just v -> let t' = delete tid t | 351 | Just v -> let t' = delete tid t |
349 | in ((g,t'),void $ tryPutMVar v x) | 352 | in return ((g,t'),void $ tryPutMVar v x) |
350 | Nothing -> ((g,t), return ()) | 353 | Nothing -> return ((g,t), return ()) |
351 | } | 354 | } |
352 | 355 | ||
353 | -- | A set of methods neccessary for dispatching incomming packets. | 356 | -- | A set of methods neccessary for dispatching incomming packets. |
@@ -402,11 +405,13 @@ printErrors h = ErrorReporter | |||
402 | } | 405 | } |
403 | 406 | ||
404 | -- Change the /err/ type for an 'ErrorReporter'. | 407 | -- Change the /err/ type for an 'ErrorReporter'. |
405 | contramapE f (ErrorReporter pe mh unk tim) | 408 | instance Contravariant (ErrorReporter addr x meth tid) where |
406 | = ErrorReporter (\e -> pe (f e)) | 409 | -- contramap :: (t5 -> t4) -> ErrorReporter t3 t2 t1 t t4 -> ErrorReporter t3 t2 t1 t t5 |
407 | mh | 410 | contramap f (ErrorReporter pe mh unk tim) |
408 | (\addr x e -> unk addr x (f e)) | 411 | = ErrorReporter (\e -> pe (f e)) |
409 | tim | 412 | mh |
413 | (\addr x e -> unk addr x (f e)) | ||
414 | tim | ||
410 | 415 | ||
411 | -- | Handle a single inbound packet and then invoke the given continuation. | 416 | -- | Handle a single inbound packet and then invoke the given continuation. |
412 | -- The 'forkListener' function is implemeneted by passing this function to | 417 | -- The 'forkListener' function is implemeneted by passing this function to |
@@ -436,7 +441,7 @@ handleMessage (Client net d err pending whoami responseID) addr plain = do | |||
436 | IsResponse tid -> do | 441 | IsResponse tid -> do |
437 | action <- atomically $ do | 442 | action <- atomically $ do |
438 | ts0 <- readTVar pending | 443 | ts0 <- readTVar pending |
439 | let (ts, action) = dispatchResponse (tableMethods d) tid plain ts0 | 444 | (ts, action) <- dispatchResponse (tableMethods d) tid plain ts0 |
440 | writeTVar pending ts | 445 | writeTVar pending ts |
441 | return action | 446 | return action |
442 | action | 447 | action |
@@ -458,6 +463,7 @@ sockAddrFamily (SockAddrCan _ ) = AF_CAN | |||
458 | -- | Packets with an empty payload may trigger eof exception. | 463 | -- | Packets with an empty payload may trigger eof exception. |
459 | -- 'udpTransport' uses this function to avoid throwing in that | 464 | -- 'udpTransport' uses this function to avoid throwing in that |
460 | -- case. | 465 | -- case. |
466 | ignoreEOF :: a -> IOError -> IO a | ||
461 | ignoreEOF def e | isEOFError e = pure def | 467 | ignoreEOF def e | isEOFError e = pure def |
462 | | otherwise = throwIO e | 468 | | otherwise = throwIO e |
463 | 469 | ||