summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorjoe <joe@jerkface.net>2017-11-08 02:28:08 -0500
committerjoe <joe@jerkface.net>2017-11-08 02:30:43 -0500
commit29e10ec3a1fce5071d342bb02c286aecb3066868 (patch)
treec8becc7fa66a5aaccd9cf5c8ac443038d9c5422d
parent8e1aad3e0abaacd11e5e95dbd21400ad06c88375 (diff)
Finished reworked bootstrap algorithm.
-rw-r--r--src/Network/Kademlia/Bootstrap.hs55
1 files changed, 39 insertions, 16 deletions
diff --git a/src/Network/Kademlia/Bootstrap.hs b/src/Network/Kademlia/Bootstrap.hs
index 8ca0bb83..93cf08f3 100644
--- a/src/Network/Kademlia/Bootstrap.hs
+++ b/src/Network/Kademlia/Bootstrap.hs
@@ -138,7 +138,7 @@ forkPollForRefresh r@BucketRefresher{ refreshInterval
138 where 138 where
139 refresh :: Int -> IO Int 139 refresh :: Int -> IO Int
140 refresh n = do 140 refresh n = do
141 hPutStrLn stderr $ "Refresh time! "++ show n 141 -- hPutStrLn stderr $ "Refresh time! "++ show n
142 refreshBucket r n 142 refreshBucket r n
143 143
144 go again ( bktnum :-> refresh_time ) = do 144 go again ( bktnum :-> refresh_time ) = do
@@ -157,7 +157,7 @@ forkPollForRefresh r@BucketRefresher{ refreshInterval
157 return () 157 return ()
158 return () 158 return ()
159 picoseconds -> do 159 picoseconds -> do
160 hPutStrLn stderr $ show (picoseconds `div` 10^12) ++ " seconds until refresh " ++ show bktnum 160 -- hPutStrLn stderr $ show (picoseconds `div` 10^12) ++ " seconds until refresh " ++ show bktnum
161 threadDelay ( picoseconds `div` 10^6 ) 161 threadDelay ( picoseconds `div` 10^6 )
162 again 162 again
163 163
@@ -197,13 +197,13 @@ onFinishedRefresh BucketRefresher { bootstrapCountdown
197 , refreshQueue 197 , refreshQueue
198 , refreshBuckets } num now = do 198 , refreshBuckets } num now = do
199 bootstrapping <- readTVar bootstrapMode 199 bootstrapping <- readTVar bootstrapMode
200 if not bootstrapping then return $ hPutStrLn stderr $ "Finished non-boostrapping refresh: "++show num 200 if not bootstrapping then return $ return () -- hPutStrLn stderr $ "Finished non-boostrapping refresh: "++show num
201 else do 201 else do
202 tbl <- readTVar refreshBuckets 202 tbl <- readTVar refreshBuckets
203 action <- 203 action <-
204 if num /= R.bktCount tbl - 1 204 if num /= R.bktCount tbl - 1
205 then do modifyTVar' bootstrapCountdown (fmap pred) 205 then do modifyTVar' bootstrapCountdown (fmap pred)
206 return $ hPutStrLn stderr $ "BOOTSTRAP decrement" 206 return $ return () -- hPutStrLn stderr $ "BOOTSTRAP decrement"
207 else do 207 else do
208 -- The last bucket finished. 208 -- The last bucket finished.
209 cnt <- readTVar bootstrapCountdown 209 cnt <- readTVar bootstrapCountdown
@@ -220,17 +220,17 @@ onFinishedRefresh BucketRefresher { bootstrapCountdown
220 -- Schedule immediate refresh for unfull buckets (other than this one). 220 -- Schedule immediate refresh for unfull buckets (other than this one).
221 modifyTVar' refreshQueue $ Int.insert n (now - 1) 221 modifyTVar' refreshQueue $ Int.insert n (now - 1)
222 writeTVar bootstrapCountdown $! Just $! length unfull 222 writeTVar bootstrapCountdown $! Just $! length unfull
223 return $ hPutStrLn stderr $ "BOOTSTRAP scheduling: "++show unfull 223 return $ return () -- hPutStrLn stderr $ "BOOTSTRAP scheduling: "++show unfull
224 Just n -> do writeTVar bootstrapCountdown $! Just $! pred n 224 Just n -> do writeTVar bootstrapCountdown $! Just $! pred n
225 return $ hPutStrLn stderr "BOOTSTRAP decrement (last bucket)" 225 return $ return () -- hPutStrLn stderr "BOOTSTRAP decrement (last bucket)"
226 cnt <- readTVar bootstrapCountdown 226 cnt <- readTVar bootstrapCountdown
227 if (cnt == Just 0) 227 if (cnt == Just 0)
228 then do 228 then do
229 -- Boostrap finished! 229 -- Boostrap finished!
230 writeTVar bootstrapMode False 230 writeTVar bootstrapMode False
231 writeTVar bootstrapCountdown Nothing 231 writeTVar bootstrapCountdown Nothing
232 return $ do action ; hPutStrLn stderr $ "BOOTSTRAP complete (" ++ show num ++ ")." 232 return $ do action ; hPutStrLn stderr $ "BOOTSTRAP complete (" ++ show (R.shape tbl) ++ ")."
233 else return $ do action ; hPutStrLn stderr $ "BOOTSTRAP progress " ++ show (num,R.bktCount tbl,cnt) 233 else return $ do action ; hPutStrLn stderr $ "BOOTSTRAP progress " ++ show (num,R.shape tbl,cnt)
234 234
235refreshBucket :: (Show nid, Ord ni, Ord nid, Hashable nid, Hashable ni) => 235refreshBucket :: (Show nid, Ord ni, Ord nid, Hashable nid, Hashable ni) =>
236 BucketRefresher nid ni -> Int -> IO Int 236 BucketRefresher nid ni -> Int -> IO Int
@@ -268,9 +268,25 @@ refreshBucket r@BucketRefresher{ refreshSearch = sch
268 return rcount 268 return rcount
269 269
270refreshLastBucket :: SensibleNodeId nid ni => BucketRefresher nid ni -> IO () 270refreshLastBucket :: SensibleNodeId nid ni => BucketRefresher nid ni -> IO ()
271refreshLastBucket r@BucketRefresher { refreshBuckets } = do 271refreshLastBucket r@BucketRefresher { refreshBuckets
272 cnt <- atomically $ bktCount <$> readTVar refreshBuckets 272 , refreshQueue } = do
273 void $ refreshBucket r (cnt - 1) 273
274 now <- getPOSIXTime
275 atomically $ do
276 cnt <- bktCount <$> readTVar refreshBuckets
277 -- Schedule immediate refresh.
278 modifyTVar' refreshQueue $ Int.insert (cnt-1) (now - 1)
279
280restartBootstrap :: (Hashable ni, Hashable nid, Ord ni, Ord nid, Show nid) =>
281 BucketRefresher nid ni -> STM (IO ())
282restartBootstrap r@BucketRefresher{ bootstrapMode, bootstrapCountdown } = do
283 unchanged <- readTVar bootstrapMode
284 writeTVar bootstrapMode True
285 writeTVar bootstrapCountdown Nothing
286 if not unchanged then return $ do
287 hPutStrLn stderr "BOOTSTRAP entered bootstrap mode"
288 refreshLastBucket r
289 else return $ hPutStrLn stderr "BOOTSTRAP already bootstrapping"
274 290
275bootstrap :: (Ord ni, Ord nid, Hashable nid, Hashable ni, Foldable t, Foldable t1, Show nid) => 291bootstrap :: (Ord ni, Ord nid, Hashable nid, Hashable ni, Foldable t, Foldable t1, Show nid) =>
276 BucketRefresher nid ni 292 BucketRefresher nid ni
@@ -279,7 +295,8 @@ bootstrap :: (Ord ni, Ord nid, Hashable nid, Hashable ni, Foldable t, Foldable t
279 -> IO () 295 -> IO ()
280bootstrap r@BucketRefresher { refreshSearch = sch 296bootstrap r@BucketRefresher { refreshSearch = sch
281 , refreshBuckets = var 297 , refreshBuckets = var
282 , refreshPing = ping } ns ns0 = do 298 , refreshPing = ping
299 , bootstrapMode } ns ns0 = do
283 gotPing <- atomically $ newTVar False 300 gotPing <- atomically $ newTVar False
284 301
285 -- First, ping the given nodes so that they are added to 302 -- First, ping the given nodes so that they are added to
@@ -300,9 +317,10 @@ bootstrap r@BucketRefresher { refreshSearch = sch
300 forkTask g (show $ kademliaLocation (searchSpace sch) n) 317 forkTask g (show $ kademliaLocation (searchSpace sch) n)
301 (void $ ping n) 318 (void $ ping n)
302 hPutStrLn stderr "Finished bootstrap pings." 319 hPutStrLn stderr "Finished bootstrap pings."
303 -- Now search our own Id by refreshing the last bucket. 320 -- Now search our own Id by entering bootstrap mode from non-bootstrap mode.
304 refreshLastBucket r 321 join $ atomically $ do
305 -- That's it. 322 writeTVar bootstrapMode False
323 restartBootstrap r
306 -- 324 --
307 -- Hopefully 'forkPollForRefresh' was invoked and can take over 325 -- Hopefully 'forkPollForRefresh' was invoked and can take over
308 -- maintenance. 326 -- maintenance.
@@ -402,7 +420,12 @@ touchBucket r@BucketRefresher{ refreshSearch
402 nid = kademliaLocation space transitioningNode 420 nid = kademliaLocation space transitioningNode
403 tbl <- readTVar refreshBuckets 421 tbl <- readTVar refreshBuckets
404 let num = R.bucketNumber space nid tbl 422 let num = R.bucketNumber space nid tbl
405 let action = return () 423 stamp <- readTVar refreshLastTouch
424 action <- case stamp /= 0 && (now - stamp > 60) of
425 True -> do
426 -- It's been one minute since any bucket has been touched, re-enter bootstrap mode.
427 restartBootstrap r
428 False -> return $ return ()
406 interval <- effectiveRefreshInterval r num 429 interval <- effectiveRefreshInterval r num
407 modifyTVar' refreshQueue $ Int.insert num (now + interval) 430 modifyTVar' refreshQueue $ Int.insert num (now + interval)
408 writeTVar refreshLastTouch now 431 writeTVar refreshLastTouch now