summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorjoe <joe@jerkface.net>2017-07-16 17:27:43 -0400
committerjoe <joe@jerkface.net>2017-07-16 17:27:43 -0400
commitc554d48acb6861160480711d299f22f857daec97 (patch)
tree94b662acab4c8c98f4bdb521eb916166c0e3a06c
parent5164740e20d24bffb177337bcbbbe12b4d88adf0 (diff)
Added timestamps to kademlia replacement queues.
-rw-r--r--src/Network/DHT/Routing.hs38
1 files changed, 14 insertions, 24 deletions
diff --git a/src/Network/DHT/Routing.hs b/src/Network/DHT/Routing.hs
index 2521f7b9..7f0e1c94 100644
--- a/src/Network/DHT/Routing.hs
+++ b/src/Network/DHT/Routing.hs
@@ -172,10 +172,10 @@ bucketQ = seqQ
172-- table tree. Size of the bucket should be choosen such that it's 172-- table tree. Size of the bucket should be choosen such that it's
173-- very unlikely that all nodes in bucket fail within an hour of 173-- very unlikely that all nodes in bucket fail within an hour of
174-- each other. 174-- each other.
175-- 175data Bucket ni = Bucket
176data Bucket ni = Bucket { bktNodes :: !(PSQ ni Timestamp) -- current routing nodes 176 { bktNodes :: !(PSQ ni Timestamp) -- current routing nodes
177 , bktQ :: !(BucketQueue ni) -- replacements pending time-outs 177 , bktQ :: !(BucketQueue (Timestamp,ni)) -- replacements pending time-outs
178 } deriving Generic 178 } deriving Generic
179 179
180deriving instance Show ni => Show (Bucket ni) 180deriving instance Show ni => Show (Bucket ni)
181 181
@@ -249,7 +249,7 @@ updateBucketForInbound curTime info bucket
249 , bucket { -- Update timestamps so that we don't redundantly ping. 249 , bucket { -- Update timestamps so that we don't redundantly ping.
250 bktNodes = updateStamps curTime stales $ bktNodes bucket 250 bktNodes = updateStamps curTime stales $ bktNodes bucket
251 -- Update queue with the pending NodeInfo in case of ping fail. 251 -- Update queue with the pending NodeInfo in case of ping fail.
252 , bktQ = runIdentity $ pushBack bucketQ info $ bktQ bucket } ) 252 , bktQ = runIdentity $ pushBack bucketQ (curTime,info) $ bktQ bucket } )
253 -- When the bucket is full of good nodes, the new node is simply discarded. 253 -- When the bucket is full of good nodes, the new node is simply discarded.
254 -- We must return 'A.empty' here to ensure that bucket splitting happens 254 -- We must return 'A.empty' here to ensure that bucket splitting happens
255 -- inside 'modifyBucket'. 255 -- inside 'modifyBucket'.
@@ -270,7 +270,7 @@ updateBucketForInbound curTime info bucket
270 map_ns f = bucket { bktNodes = f (bktNodes bucket) } 270 map_ns f = bucket { bktNodes = f (bktNodes bucket) }
271 -- map_q f = bucket { bktQ = runIdentity \$ f (bktQ bucket) } 271 -- map_q f = bucket { bktQ = runIdentity \$ f (bktQ bucket) }
272 272
273updateBucketForPingResult curTime bad_node got_response bucket 273updateBucketForPingResult bad_node got_response bucket
274 = pure ( replacements 274 = pure ( replacements
275 , Bucket (foldr replace 275 , Bucket (foldr replace
276 (bktNodes bucket) 276 (bktNodes bucket)
@@ -286,17 +286,8 @@ updateBucketForPingResult curTime bad_node got_response bucket
286 return (bad_node, info) 286 return (bad_node, info)
287 | otherwise = [] 287 | otherwise = []
288 288
289 replace (bad_node, info) = 289 replace (bad_node, (tm, info)) =
290 PSQ.insert info curTime 290 PSQ.insert info tm
291 -- XXX: curTime is the time somebody pinged out, not the time
292 -- of which the popped node was originally queued. That's not
293 -- quite right.
294 --
295 -- It's the best we can do atm since the overflow BucketQueue
296 -- does not include timestamps.
297 --
298 -- This means that initial time-outs for replacement nodes are up to
299 -- twice as long as for the originals.
300 . PSQ.delete bad_node 291 . PSQ.delete bad_node
301 292
302 293
@@ -330,7 +321,7 @@ split :: -- ( Eq ip , Ord (NodeId) , FiniteBits (NodeId)) =>
330split testNodeIdBit i b = (Bucket ns qs, Bucket ms rs) 321split testNodeIdBit i b = (Bucket ns qs, Bucket ms rs)
331 where 322 where
332 (ns,ms) = (PSQ.fromList *** PSQ.fromList) . partition (spanBit . key) . PSQ.toList $ bktNodes b 323 (ns,ms) = (PSQ.fromList *** PSQ.fromList) . partition (spanBit . key) . PSQ.toList $ bktNodes b
333 (qs,rs) = runIdentity $ partitionQ bucketQ spanBit $ bktQ b 324 (qs,rs) = runIdentity $ partitionQ bucketQ (spanBit . snd) $ bktQ b
334 325
335 spanBit :: ni -> Bool 326 spanBit :: ni -> Bool
336 spanBit entry = testNodeIdBit entry i 327 spanBit entry = testNodeIdBit entry i
@@ -659,21 +650,20 @@ updateForInbound testIdBit nodeId tm ni tbl =
659 650
660-- | Update the routing table with the results of a ping. 651-- | Update the routing table with the results of a ping.
661-- 652--
662-- Each (a,b) in the returned list indicates that the node /a/ was deleted from the 653-- Each (a,(tm,b)) in the returned list indicates that the node /a/ was deleted from the
663-- routing table and the node /b/ has taken its place. 654-- routing table and the node /b/, with timestamp /tm/, has taken its place.
664updateForPingResult :: Ord ni => 655updateForPingResult :: Ord ni =>
665 (nid -> Word -> Bool) 656 (nid -> Word -> Bool)
666 -> (ni -> nid) 657 -> (ni -> nid)
667 -> Timestamp
668 -> ni -- ^ The pinged node. 658 -> ni -- ^ The pinged node.
669 -> Bool -- ^ True if we got a reply, False if it timed out. 659 -> Bool -- ^ True if we got a reply, False if it timed out.
670 -> Table ni nid -- ^ The routing table. 660 -> Table ni nid -- ^ The routing table.
671 -> ( [(ni,ni)], Table ni nid ) 661 -> ( [(ni,(Timestamp, ni))], Table ni nid )
672updateForPingResult testIdBit nodeId tm ni got_reply tbl = 662updateForPingResult testIdBit nodeId ni got_reply tbl =
673 fromMaybe ([],tbl) 663 fromMaybe ([],tbl)
674 $ modifyBucket testIdBit (\ni -> testIdBit $ nodeId ni) 664 $ modifyBucket testIdBit (\ni -> testIdBit $ nodeId ni)
675 (nodeId ni) 665 (nodeId ni)
676 (updateBucketForPingResult tm ni got_reply) 666 (updateBucketForPingResult ni got_reply)
677 tbl 667 tbl
678 668
679 669