diff options
Diffstat (limited to 'src/Network')
-rw-r--r-- | src/Network/BitTorrent/PeerWire/Selection.hs | 56 |
1 files changed, 42 insertions, 14 deletions
diff --git a/src/Network/BitTorrent/PeerWire/Selection.hs b/src/Network/BitTorrent/PeerWire/Selection.hs index 83ab8311..9d154613 100644 --- a/src/Network/BitTorrent/PeerWire/Selection.hs +++ b/src/Network/BitTorrent/PeerWire/Selection.hs | |||
@@ -10,7 +10,7 @@ | |||
10 | -- which used to find out which one next piece to download. | 10 | -- which used to find out which one next piece to download. |
11 | -- Selectors considered to be used in the following order: | 11 | -- Selectors considered to be used in the following order: |
12 | -- | 12 | -- |
13 | -- * Random first or rarest first selection - at the start. | 13 | -- * Random first - at the start. |
14 | -- | 14 | -- |
15 | -- * Rarest first selection - performed to avoid situation when | 15 | -- * Rarest first selection - performed to avoid situation when |
16 | -- rarest piece is unaccessible. | 16 | -- rarest piece is unaccessible. |
@@ -19,28 +19,59 @@ | |||
19 | -- the subpieces of the content. | 19 | -- the subpieces of the content. |
20 | -- | 20 | -- |
21 | -- Note that BitTorrent applies the strict priority policy for | 21 | -- Note that BitTorrent applies the strict priority policy for |
22 | -- _subpiece_ or _blocks_ selection. | 22 | -- /subpiece/ or /blocks/ selection. |
23 | -- | 23 | -- |
24 | module Network.BitTorrent.PeerWire.Selection | 24 | module Network.BitTorrent.PeerWire.Selection |
25 | ( Selector | 25 | ( Selector |
26 | |||
27 | -- * Construction | ||
28 | , selector, strategyClass | ||
29 | |||
30 | -- * Strategies | ||
26 | , strictFirst, strictLast | 31 | , strictFirst, strictLast |
27 | , rarestFirst, randomFirst, endGame | 32 | , rarestFirst, randomFirst, endGame |
28 | |||
29 | , autoSelector | ||
30 | ) where | 33 | ) where |
31 | 34 | ||
32 | import Data.Bitfield | 35 | import Data.Bitfield |
33 | import Network.BitTorrent.PeerWire.Block | 36 | import Network.BitTorrent.PeerWire.Block |
34 | import Network.BitTorrent.PeerWire.Message | ||
35 | 37 | ||
36 | 38 | ||
37 | 39 | type Selector = Bitfield -- ^ Indices of client /have/ pieces. | |
38 | type Selector = Bitfield -- ^ Indices of client "have" pieces. | 40 | -> Bitfield -- ^ Indices of peer /have/ pieces. |
39 | -> Bitfield -- ^ Indices of peer "have" pieces. | 41 | -> [Bitfield] -- ^ Indices of other peers /have/ pieces. |
40 | -> [Bitfield] -- ^ Indices of other peers "have" pieces. | ||
41 | -> Maybe PieceIx -- ^ Zero-based index of piece to request | 42 | -> Maybe PieceIx -- ^ Zero-based index of piece to request |
42 | -- to, if any. | 43 | -- to, if any. |
43 | 44 | ||
45 | type PieceThreshold = Int | ||
46 | |||
47 | selector :: Selector -- ^ Selector to use at the start. | ||
48 | -> PieceThreshold | ||
49 | -> Selector -- ^ Selector to use after the client have the C pieces. | ||
50 | -> Selector -- ^ Selector that changes behaviour based on completeness. | ||
51 | selector start pt ready h a xs = | ||
52 | case strategyClass pt h of | ||
53 | SCBeginning -> start h a xs | ||
54 | SCReady -> ready h a xs | ||
55 | SCEnd -> endGame h a xs | ||
56 | |||
57 | data StartegyClass | ||
58 | = SCBeginning | ||
59 | | SCReady | ||
60 | | SCEnd | ||
61 | deriving (Show, Eq, Ord, Enum, Bounded) | ||
62 | |||
63 | endThreshold :: PieceThreshold | ||
64 | endThreshold = 1 | ||
65 | |||
66 | strategyClass :: PieceThreshold -> Bitfield -> StartegyClass | ||
67 | strategyClass pt = classify . completeness | ||
68 | where | ||
69 | classify (have, total) | ||
70 | | have < pt = SCBeginning | ||
71 | | total - have > endThreshold = SCReady | ||
72 | | otherwise = SCEnd | ||
73 | |||
74 | |||
44 | -- | Select the first available piece. | 75 | -- | Select the first available piece. |
45 | strictFirst :: Selector | 76 | strictFirst :: Selector |
46 | strictFirst h a _ = findMin (difference a h) | 77 | strictFirst h a _ = findMin (difference a h) |
@@ -56,15 +87,12 @@ rarestFirst h a xs = rarest (frequencies (map (intersection want) xs)) | |||
56 | want = difference h a | 87 | want = difference h a |
57 | rarest = Just . head | 88 | rarest = Just . head |
58 | 89 | ||
59 | -- | In general random first is faster than rarest first strategy but | 90 | -- | In average random first is faster than rarest first strategy but |
60 | -- only if all pieces are available. | 91 | -- only if all pieces are available. |
61 | randomFirst :: IO Selector | 92 | randomFirst :: Selector |
62 | randomFirst = do | 93 | randomFirst = do |
63 | -- randomIO | 94 | -- randomIO |
64 | error "randomFirst" | 95 | error "randomFirst" |
65 | 96 | ||
66 | endGame :: Selector | 97 | endGame :: Selector |
67 | endGame = strictLast | 98 | endGame = strictLast |
68 | |||
69 | autoSelector :: Selector | ||
70 | autoSelector = undefined | ||