diff options
author | Sam Truzjan <pxqr.sta@gmail.com> | 2013-12-28 12:45:14 +0400 |
---|---|---|
committer | Sam Truzjan <pxqr.sta@gmail.com> | 2013-12-28 12:45:14 +0400 |
commit | 95bbdb559d77fa4d406cff3da0dfc7b7421a10cd (patch) | |
tree | b51b7357ba23930475faf612b3330d54ee2a3ce1 /src/Network/BitTorrent | |
parent | 573f8d0411abbf0018077487ddd58150c3d1208c (diff) |
Add routing table shape
Diffstat (limited to 'src/Network/BitTorrent')
-rw-r--r-- | src/Network/BitTorrent/DHT/Routing.hs | 51 |
1 files changed, 30 insertions, 21 deletions
diff --git a/src/Network/BitTorrent/DHT/Routing.hs b/src/Network/BitTorrent/DHT/Routing.hs index b37f2613..64c7bbee 100644 --- a/src/Network/BitTorrent/DHT/Routing.hs +++ b/src/Network/BitTorrent/DHT/Routing.hs | |||
@@ -13,6 +13,11 @@ module Network.BitTorrent.DHT.Routing | |||
13 | ( -- * Routing table | 13 | ( -- * Routing table |
14 | Table | 14 | Table |
15 | 15 | ||
16 | -- * Table attributes | ||
17 | , BucketCount | ||
18 | , BucketSize | ||
19 | , NodeCount | ||
20 | |||
16 | -- * Routing | 21 | -- * Routing |
17 | , Timestamp | 22 | , Timestamp |
18 | , Routing | 23 | , Routing |
@@ -20,6 +25,7 @@ module Network.BitTorrent.DHT.Routing | |||
20 | 25 | ||
21 | -- * Query | 26 | -- * Query |
22 | , thisId | 27 | , thisId |
28 | , shape | ||
23 | , Network.BitTorrent.DHT.Routing.size | 29 | , Network.BitTorrent.DHT.Routing.size |
24 | , Network.BitTorrent.DHT.Routing.depth | 30 | , Network.BitTorrent.DHT.Routing.depth |
25 | , K | 31 | , K |
@@ -149,7 +155,7 @@ instance (Serialize k, Serialize v) => Serialize (Binding k v) where | |||
149 | -- TODO instance Pretty where | 155 | -- TODO instance Pretty where |
150 | 156 | ||
151 | -- | Most clients use this value for maximum bucket size. | 157 | -- | Most clients use this value for maximum bucket size. |
152 | defaultBucketSize :: Int | 158 | defaultBucketSize :: BucketSize |
153 | defaultBucketSize = 20 | 159 | defaultBucketSize = 20 |
154 | 160 | ||
155 | -- | Bucket is also limited in its length — thus it's called k-bucket. | 161 | -- | Bucket is also limited in its length — thus it's called k-bucket. |
@@ -184,7 +190,7 @@ delta = 15 * 60 | |||
184 | -- | Max bucket size, in nodes. | 190 | -- | Max bucket size, in nodes. |
185 | type Alpha = Int | 191 | type Alpha = Int |
186 | 192 | ||
187 | defaultAlpha :: Int | 193 | defaultAlpha :: Alpha |
188 | defaultAlpha = 8 | 194 | defaultAlpha = 8 |
189 | 195 | ||
190 | insertBucket :: Eq ip => Timestamp -> NodeInfo ip -> Bucket ip | 196 | insertBucket :: Eq ip => Timestamp -> NodeInfo ip -> Bucket ip |
@@ -231,11 +237,11 @@ split i = (PSQ.fromList *** PSQ.fromList) . partition spanBit . PSQ.toList | |||
231 | -- Table | 237 | -- Table |
232 | -----------------------------------------------------------------------} | 238 | -----------------------------------------------------------------------} |
233 | 239 | ||
234 | defaultBucketCount :: Int | 240 | defaultBucketCount :: BucketCount |
235 | defaultBucketCount = 20 | 241 | defaultBucketCount = 20 |
236 | 242 | ||
237 | data Table ip | 243 | data Table ip |
238 | = Tip NodeId Int (Bucket ip) | 244 | = Tip NodeId BucketCount (Bucket ip) |
239 | | Zero (Table ip) (Bucket ip) | 245 | | Zero (Table ip) (Bucket ip) |
240 | | One (Bucket ip) (Table ip) | 246 | | One (Bucket ip) (Table ip) |
241 | deriving Generic | 247 | deriving Generic |
@@ -249,35 +255,38 @@ instance Serialize NominalDiffTime where | |||
249 | -- since it is included in routing table. | 255 | -- since it is included in routing table. |
250 | instance (Eq ip, Serialize ip) => Serialize (Table ip) | 256 | instance (Eq ip, Serialize ip) => Serialize (Table ip) |
251 | 257 | ||
258 | -- | Shape of the table. | ||
252 | instance Pretty (Table ip) where | 259 | instance Pretty (Table ip) where |
253 | pretty t = | 260 | pretty = hcat . punctuate "," . L.map PP.int . shape |
254 | "size = " <> PP.int (Network.BitTorrent.DHT.Routing.size t) <> | ||
255 | ", depth = " <> PP.int (depth t) | ||
256 | |||
257 | 261 | ||
262 | -- | Empty table with specified /spine/ node id. | ||
258 | nullTable :: Eq ip => NodeId -> Table ip | 263 | nullTable :: Eq ip => NodeId -> Table ip |
259 | nullTable nid = Tip nid defaultBucketCount PSQ.empty | 264 | nullTable nid = Tip nid defaultBucketCount PSQ.empty |
260 | 265 | ||
266 | -- | Get the /spine/ node id. | ||
261 | thisId :: Table ip -> NodeId | 267 | thisId :: Table ip -> NodeId |
262 | thisId (Tip nid _ _) = nid | 268 | thisId (Tip nid _ _) = nid |
263 | thisId (Zero table _) = thisId table | 269 | thisId (Zero table _) = thisId table |
264 | thisId (One _ table) = thisId table | 270 | thisId (One _ table) = thisId table |
265 | 271 | ||
272 | type BucketSize = Int | ||
273 | type BucketCount = Int | ||
274 | type NodeCount = Int | ||
275 | |||
276 | -- | Internally, routing table is similar to list of buckets or a | ||
277 | -- /matrix/ of nodes. This function returns the shape of the matrix. | ||
278 | shape :: Table ip -> [BucketSize] | ||
279 | shape (Tip _ _ bucket) = [PSQ.size bucket] | ||
280 | shape (Zero t bucket) = PSQ.size bucket : shape t | ||
281 | shape (One bucket t ) = PSQ.size bucket : shape t | ||
282 | |||
266 | -- | Get number of nodes in the table. | 283 | -- | Get number of nodes in the table. |
267 | size :: Table ip -> Int | 284 | size :: Table ip -> NodeCount |
268 | size = go | 285 | size = L.sum . shape |
269 | where | ||
270 | go (Tip _ _ bucket) = PSQ.size bucket | ||
271 | go (Zero t bucket) = go t + PSQ.size bucket | ||
272 | go (One bucket t ) = PSQ.size bucket + go t | ||
273 | 286 | ||
274 | -- | Get number of buckets in the table. | 287 | -- | Get number of buckets in the table. |
275 | depth :: Table ip -> Int | 288 | depth :: Table ip -> BucketCount |
276 | depth = go | 289 | depth = L.length . shape |
277 | where | ||
278 | go (Tip _ _ _) = 1 | ||
279 | go (Zero t _) = succ (go t) | ||
280 | go (One _ t) = succ (go t) | ||
281 | 290 | ||
282 | lookupBucket :: NodeId -> Table ip -> Maybe (Bucket ip) | 291 | lookupBucket :: NodeId -> Table ip -> Maybe (Bucket ip) |
283 | lookupBucket nid = go 0 | 292 | lookupBucket nid = go 0 |
@@ -310,7 +319,7 @@ kclosestHash k nid t = kclosest k (coerseId nid) t | |||
310 | -- Routing | 319 | -- Routing |
311 | -----------------------------------------------------------------------} | 320 | -----------------------------------------------------------------------} |
312 | 321 | ||
313 | splitTip :: Eq ip => NodeId -> Int -> BitIx -> Bucket ip -> Table ip | 322 | splitTip :: Eq ip => NodeId -> BucketCount -> BitIx -> Bucket ip -> Table ip |
314 | splitTip nid n i bucket | 323 | splitTip nid n i bucket |
315 | | testIdBit nid i = (One zeros (Tip nid (pred n) ones)) | 324 | | testIdBit nid i = (One zeros (Tip nid (pred n) ones)) |
316 | | otherwise = (Zero (Tip nid (pred n) zeros) ones) | 325 | | otherwise = (Zero (Tip nid (pred n) zeros) ones) |