diff options
author | joe <joe@jerkface.net> | 2017-07-22 01:15:44 -0400 |
---|---|---|
committer | joe <joe@jerkface.net> | 2017-07-22 01:15:44 -0400 |
commit | 77f6b96492223e7d7b147dac8d026e0b6f6a651b (patch) | |
tree | 661e2115a814de82ba251bccf0ab21ae4dfd1ff1 /Kademlia.hs | |
parent | 7f1eb53d34ea6dda02cae1934b5011e38de248a6 (diff) |
Implemented bucket refresh for Mainline.
Diffstat (limited to 'Kademlia.hs')
-rw-r--r-- | Kademlia.hs | 38 |
1 files changed, 32 insertions, 6 deletions
diff --git a/Kademlia.hs b/Kademlia.hs index 9316f135..bcddfab1 100644 --- a/Kademlia.hs +++ b/Kademlia.hs | |||
@@ -18,7 +18,6 @@ import GHC.Conc (labelThread) | |||
18 | import Control.Concurrent.Lifted | 18 | import Control.Concurrent.Lifted |
19 | #endif | 19 | #endif |
20 | import Data.Bits | 20 | import Data.Bits |
21 | |||
22 | import Text.PrettyPrint as PP hiding ((<>), ($$)) | 21 | import Text.PrettyPrint as PP hiding ((<>), ($$)) |
23 | import Text.PrettyPrint.HughesPJClass hiding ((<>),($$)) | 22 | import Text.PrettyPrint.HughesPJClass hiding ((<>),($$)) |
24 | import Data.IP | 23 | import Data.IP |
@@ -28,6 +27,11 @@ import Data.Monoid | |||
28 | import Data.Time.Clock.POSIX (POSIXTime) | 27 | import Data.Time.Clock.POSIX (POSIXTime) |
29 | import Data.Wrapper.PSQInt ( pattern (:->) ) | 28 | import Data.Wrapper.PSQInt ( pattern (:->) ) |
30 | import qualified Data.Wrapper.PSQInt as Int | 29 | import qualified Data.Wrapper.PSQInt as Int |
30 | import Network.BitTorrent.DHT.Search | ||
31 | import Network.DatagramServer.Types (genBucketSample) | ||
32 | import Network.Address (bucketRange) | ||
33 | import Data.Serialize (Serialize) | ||
34 | import Data.Hashable | ||
31 | 35 | ||
32 | -- | The status of a given node with respect to a given routint table. | 36 | -- | The status of a given node with respect to a given routint table. |
33 | data RoutingStatus | 37 | data RoutingStatus |
@@ -206,15 +210,16 @@ insertNode (Kademlia reporter space io) node = do | |||
206 | -- It might also be better to pass the timestamp of the transition here and | 210 | -- It might also be better to pass the timestamp of the transition here and |
207 | -- keep the refresh queue in better sync with the routing table by updating it | 211 | -- keep the refresh queue in better sync with the routing table by updating it |
208 | -- within the STM monad. | 212 | -- within the STM monad. |
209 | touchBucket :: POSIXTime -> (ni -> Int) -> TVar (Int.PSQ POSIXTime) -> RoutingTransition ni -> STM (IO ()) | 213 | touchBucket :: KademliaSpace nid ni -> POSIXTime -> TVar (BucketList ni) -> TVar (Int.PSQ POSIXTime) -> RoutingTransition ni -> STM (IO ()) |
210 | touchBucket interval bktnum psq tr | 214 | touchBucket space interval bkts psq tr |
211 | | (transitionedTo tr == Applicant) | 215 | | (transitionedTo tr == Applicant) |
212 | = return $ return () | 216 | = return $ return () |
213 | | otherwise = return $ do | 217 | | otherwise = return $ do |
214 | now <- getPOSIXTime | 218 | now <- getPOSIXTime |
215 | atomically $ modifyTVar' psq | 219 | atomically $ do |
216 | $ Int.insert (bktnum $ transitioningNode tr) | 220 | let nid = kademliaLocation space (transitioningNode tr) |
217 | (now + interval) | 221 | num <- R.bucketNumber space nid <$> readTVar bkts |
222 | modifyTVar' psq $ Int.insert num (now + interval) | ||
218 | 223 | ||
219 | -- | > pollForRefresh interval queue refresh | 224 | -- | > pollForRefresh interval queue refresh |
220 | -- | 225 | -- |
@@ -250,3 +255,24 @@ pollForRefresh interval psq refresh = do | |||
250 | return () | 255 | return () |
251 | seconds -> threadDelay ( seconds * 1000000 ) | 256 | seconds -> threadDelay ( seconds * 1000000 ) |
252 | again | 257 | again |
258 | |||
259 | refreshBucket :: forall nid ni addr. | ||
260 | ( FiniteBits nid, Serialize nid, Ord nid, Ord ni, Hashable nid, Hashable ni, Ord addr ) => | ||
261 | Search nid addr ni ni -> TVar (BucketList ni) -> nid -> Int -> IO () | ||
262 | refreshBucket sch var nid n = do | ||
263 | tbl <- atomically (readTVar var) | ||
264 | sample <- genBucketSample nid (bucketRange (n) (n + 1 < bktCount tbl)) | ||
265 | resultCounter <- atomically $ newTVar 0 | ||
266 | let fullcount = R.defaultBucketSize | ||
267 | let checkBucketFull :: ni -> STM Bool | ||
268 | checkBucketFull found_node = do | ||
269 | tbl <- readTVar var | ||
270 | let counts = R.shape tbl | ||
271 | when (n == R.bucketNumber (searchSpace sch) (kademliaLocation (searchSpace sch) found_node) tbl) | ||
272 | $ modifyTVar resultCounter (+ 1) | ||
273 | resultCount <- readTVar resultCounter | ||
274 | case drop (n - 1) counts of | ||
275 | (cnt:_) | cnt < fullcount -> return True | ||
276 | _ | resultCount + 3 < fullcount -> return True -- +3 because maybe duplicates. | ||
277 | _ -> return False | ||
278 | search sch tbl sample checkBucketFull | ||