summaryrefslogtreecommitdiff
path: root/src/Network/BitTorrent/Exchange/Selection.hs
diff options
context:
space:
mode:
Diffstat (limited to 'src/Network/BitTorrent/Exchange/Selection.hs')
-rw-r--r--src/Network/BitTorrent/Exchange/Selection.hs94
1 files changed, 94 insertions, 0 deletions
diff --git a/src/Network/BitTorrent/Exchange/Selection.hs b/src/Network/BitTorrent/Exchange/Selection.hs
new file mode 100644
index 00000000..db9e04f4
--- /dev/null
+++ b/src/Network/BitTorrent/Exchange/Selection.hs
@@ -0,0 +1,94 @@
1-- TODO tests
2-- |
3-- Copyright : (c) Sam T. 2013
4-- License : MIT
5-- Maintainer : pxqr.sta@gmail.com
6-- Stability : experimental
7-- Portability : portable
8--
9-- This module provides commonly used piece seletion algorithms
10-- which used to find out which one next piece to download.
11-- Selectors considered to be used in the following order:
12--
13-- * Random first - at the start.
14--
15-- * Rarest first selection - performed to avoid situation when
16-- rarest piece is unaccessible.
17--
18-- * _End game_ seletion - performed after a peer has requested all
19-- the subpieces of the content.
20--
21-- Note that BitTorrent applies the strict priority policy for
22-- /subpiece/ or /blocks/ selection.
23--
24module Network.BitTorrent.PeerWire.Selection
25 ( Selector
26
27 -- * Construction
28 , selector, strategyClass
29
30 -- * Strategies
31 , strictFirst, strictLast
32 , rarestFirst, randomFirst, endGame
33 ) where
34
35import Data.Bitfield
36import Data.Ratio
37import Network.BitTorrent.PeerWire.Protocol
38
39
40type Selector = Bitfield -- ^ Indices of client /have/ pieces.
41 -> Bitfield -- ^ Indices of peer /have/ pieces.
42 -> [Bitfield] -- ^ Indices of other peers /have/ pieces.
43 -> Maybe PieceIx -- ^ Zero-based index of piece to request
44 -- to, if any.
45
46selector :: Selector -- ^ Selector to use at the start.
47 -> Ratio PieceCount
48 -> Selector -- ^ Selector to use after the client have the C pieces.
49 -> Selector -- ^ Selector that changes behaviour based on completeness.
50selector start pt ready h a xs =
51 case strategyClass pt h of
52 SCBeginning -> start h a xs
53 SCReady -> ready h a xs
54 SCEnd -> endGame h a xs
55
56data StartegyClass
57 = SCBeginning
58 | SCReady
59 | SCEnd
60 deriving (Show, Eq, Ord, Enum, Bounded)
61
62
63strategyClass :: Ratio PieceCount -> Bitfield -> StartegyClass
64strategyClass threshold = classify . completeness
65 where
66 classify have
67 | have < threshold = SCBeginning
68 | have + 1 % numerator have < 1 = SCReady -- FIXME numerator have is not total count
69 | otherwise = SCEnd
70
71
72-- | Select the first available piece.
73strictFirst :: Selector
74strictFirst h a _ = findMin (difference a h)
75
76-- | Select the last available piece.
77strictLast :: Selector
78strictLast h a _ = findMax (difference a h)
79
80-- |
81rarestFirst :: Selector
82rarestFirst h a xs = rarest (map (intersection want) xs)
83 where
84 want = difference h a
85
86-- | In average random first is faster than rarest first strategy but
87-- only if all pieces are available.
88randomFirst :: Selector
89randomFirst = do
90-- randomIO
91 error "randomFirst"
92
93endGame :: Selector
94endGame = strictLast