diff options
author | Sam T <pxqr.sta@gmail.com> | 2013-06-06 12:01:27 +0400 |
---|---|---|
committer | Sam T <pxqr.sta@gmail.com> | 2013-06-06 12:01:27 +0400 |
commit | 8e7c349e87a0416b595a3ef50f54f101652aa394 (patch) | |
tree | d5b8f3a2eea61341fb2824d05cfb116b28b4f6fb /src/Data | |
parent | 563d040a9ab920b715cf86caf0fb2646e2655792 (diff) |
~ Document bitfield.
Diffstat (limited to 'src/Data')
-rw-r--r-- | src/Data/Bitfield.hs | 56 |
1 files changed, 35 insertions, 21 deletions
diff --git a/src/Data/Bitfield.hs b/src/Data/Bitfield.hs index 546c68e9..024f8f71 100644 --- a/src/Data/Bitfield.hs +++ b/src/Data/Bitfield.hs | |||
@@ -15,14 +15,13 @@ module Data.Bitfield | |||
15 | ( Bitfield, PieceCount | 15 | ( Bitfield, PieceCount |
16 | 16 | ||
17 | -- * Construction | 17 | -- * Construction |
18 | , empty | ||
19 | , insert | ||
20 | , haveAll, haveNone, have | 18 | , haveAll, haveNone, have |
21 | 19 | ||
22 | -- * Query | 20 | -- * Query |
23 | , haveCount, totalCount, completeness | 21 | , haveCount, totalCount, completeness |
24 | , findMin, findMax | 22 | , findMin, findMax |
25 | , frequencies, rarest | 23 | |
24 | , Frequency, frequencies, rarest | ||
26 | 25 | ||
27 | -- * Combine | 26 | -- * Combine |
28 | , union | 27 | , union |
@@ -51,14 +50,17 @@ import Data.Serialize | |||
51 | import Network.BitTorrent.PeerWire.Block | 50 | import Network.BitTorrent.PeerWire.Block |
52 | 51 | ||
53 | 52 | ||
53 | -- | Used to represent max set bound. Min set bound is always set to | ||
54 | -- zero. | ||
54 | type PieceCount = Int | 55 | type PieceCount = Int |
55 | 56 | ||
56 | -- TODO cache some operations | 57 | -- TODO cache some operations |
57 | 58 | ||
58 | -- | Bitfields are represented just as integer sets but with | 59 | -- | Bitfields are represented just as integer sets but with |
59 | -- restriction: the each set should be within given interval (or | 60 | -- restriction: the each set should be within given interval (or |
60 | -- subset of). Size is used to specify interval, so bitfield of size | 61 | -- subset of the specified interval). Size is used to specify |
61 | -- 10 might contain only indices in interval [0..9]. | 62 | -- interval, so bitfield of size 10 might contain only indices in |
63 | -- interval [0..9]. | ||
62 | -- | 64 | -- |
63 | data Bitfield = Bitfield { | 65 | data Bitfield = Bitfield { |
64 | bfSize :: !PieceCount | 66 | bfSize :: !PieceCount |
@@ -69,61 +71,65 @@ data Bitfield = Bitfield { | |||
69 | 71 | ||
70 | instance Monoid Bitfield where | 72 | instance Monoid Bitfield where |
71 | {-# SPECIALIZE instance Monoid Bitfield #-} | 73 | {-# SPECIALIZE instance Monoid Bitfield #-} |
72 | mempty = empty 0 | 74 | mempty = haveNone 0 |
73 | mappend = union | 75 | mappend = union |
74 | mconcat = unions | 76 | mconcat = unions |
75 | 77 | ||
76 | -- TODO documentation | ||
77 | {----------------------------------------------------------------------- | 78 | {----------------------------------------------------------------------- |
78 | Construction | 79 | Construction |
79 | -----------------------------------------------------------------------} | 80 | -----------------------------------------------------------------------} |
80 | 81 | ||
81 | empty :: PieceCount -> Bitfield | 82 | -- | The empty bitfield of the given size. |
82 | empty s = Bitfield s S.empty | ||
83 | |||
84 | insert :: PieceIx -> Bitfield -> Bitfield | ||
85 | insert ix Bitfield {..} | ||
86 | | 0 <= ix && ix < bfSize = Bitfield bfSize (S.insert ix bfSet) | ||
87 | | otherwise = Bitfield bfSize bfSet | ||
88 | |||
89 | haveNone :: PieceCount -> Bitfield | 83 | haveNone :: PieceCount -> Bitfield |
90 | haveNone = empty | 84 | haveNone s = Bitfield s S.empty |
91 | 85 | ||
86 | -- | The full bitfield containing all piece indices for the given size. | ||
92 | haveAll :: PieceCount -> Bitfield | 87 | haveAll :: PieceCount -> Bitfield |
93 | haveAll s = Bitfield s (S.interval 0 (s - 1)) | 88 | haveAll s = Bitfield s (S.interval 0 (s - 1)) |
94 | 89 | ||
90 | -- | Insert the index in the set ignoring out of range indices. | ||
95 | have :: PieceIx -> Bitfield -> Bitfield | 91 | have :: PieceIx -> Bitfield -> Bitfield |
96 | have = insert | 92 | have ix Bitfield {..} |
93 | | 0 <= ix && ix < bfSize = Bitfield bfSize (S.insert ix bfSet) | ||
94 | | otherwise = Bitfield bfSize bfSet | ||
97 | 95 | ||
98 | {----------------------------------------------------------------------- | 96 | {----------------------------------------------------------------------- |
99 | Query | 97 | Query |
100 | -----------------------------------------------------------------------} | 98 | -----------------------------------------------------------------------} |
101 | 99 | ||
100 | -- | Count of peer have pieces. | ||
102 | haveCount :: Bitfield -> PieceCount | 101 | haveCount :: Bitfield -> PieceCount |
103 | haveCount = S.size . bfSet | 102 | haveCount = S.size . bfSet |
104 | 103 | ||
104 | -- | Total count of pieces and its indices. | ||
105 | totalCount :: Bitfield -> PieceCount | 105 | totalCount :: Bitfield -> PieceCount |
106 | totalCount = bfSize | 106 | totalCount = bfSize |
107 | 107 | ||
108 | -- | | 108 | -- | Ratio of /have/ piece count to the /total/ piece count. |
109 | -- | 109 | -- |
110 | -- > forall bf. 0 <= completeness bf <= 1 | 110 | -- > forall bf. 0 <= completeness bf <= 1 |
111 | -- | 111 | -- |
112 | completeness :: Bitfield -> Ratio PieceCount | 112 | completeness :: Bitfield -> Ratio PieceCount |
113 | completeness b = haveCount b % totalCount b | 113 | completeness b = haveCount b % totalCount b |
114 | 114 | ||
115 | -- | Find first available piece index. | ||
115 | findMin :: Bitfield -> Maybe PieceIx | 116 | findMin :: Bitfield -> Maybe PieceIx |
116 | findMin Bitfield {..} | 117 | findMin Bitfield {..} |
117 | | S.null bfSet = Nothing | 118 | | S.null bfSet = Nothing |
118 | | otherwise = Just (S.findMin bfSet) | 119 | | otherwise = Just (S.findMin bfSet) |
119 | 120 | ||
121 | -- | Find last available piece index. | ||
120 | findMax :: Bitfield -> Maybe PieceIx | 122 | findMax :: Bitfield -> Maybe PieceIx |
121 | findMax Bitfield {..} | 123 | findMax Bitfield {..} |
122 | | S.null bfSet = Nothing | 124 | | S.null bfSet = Nothing |
123 | | otherwise = Just (S.findMax bfSet) | 125 | | otherwise = Just (S.findMax bfSet) |
124 | 126 | ||
127 | -- | Frequencies are needed in piece selection startegies which use | ||
128 | -- availability quantity to find out the optimal next piece index to | ||
129 | -- download. | ||
125 | type Frequency = Int | 130 | type Frequency = Int |
126 | 131 | ||
132 | -- | How many times each piece index occur in the given bitfield set. | ||
127 | frequencies :: [Bitfield] -> Vector Frequency | 133 | frequencies :: [Bitfield] -> Vector Frequency |
128 | frequencies [] = V.fromList [] | 134 | frequencies [] = V.fromList [] |
129 | frequencies xs = runST $ do | 135 | frequencies xs = runST $ do |
@@ -137,6 +143,7 @@ frequencies xs = runST $ do | |||
137 | where | 143 | where |
138 | size = maximum (map bfSize xs) | 144 | size = maximum (map bfSize xs) |
139 | 145 | ||
146 | -- | Find least available piece index. If no piece available return 'Nothing'. | ||
140 | rarest :: [Bitfield] -> Maybe PieceIx | 147 | rarest :: [Bitfield] -> Maybe PieceIx |
141 | rarest xs | 148 | rarest xs |
142 | | V.null freqMap = Nothing | 149 | | V.null freqMap = Nothing |
@@ -150,42 +157,48 @@ rarest xs | |||
150 | | otherwise = acc | 157 | | otherwise = acc |
151 | 158 | ||
152 | 159 | ||
153 | |||
154 | {----------------------------------------------------------------------- | 160 | {----------------------------------------------------------------------- |
155 | Combine | 161 | Combine |
156 | -----------------------------------------------------------------------} | 162 | -----------------------------------------------------------------------} |
157 | 163 | ||
164 | -- | Find indices at least one peer have. | ||
158 | union :: Bitfield -> Bitfield -> Bitfield | 165 | union :: Bitfield -> Bitfield -> Bitfield |
159 | union a b = Bitfield { | 166 | union a b = Bitfield { |
160 | bfSize = bfSize a `max` bfSize b | 167 | bfSize = bfSize a `max` bfSize b |
161 | , bfSet = bfSet a `S.union` bfSet b | 168 | , bfSet = bfSet a `S.union` bfSet b |
162 | } | 169 | } |
163 | 170 | ||
171 | -- | Find indices both peers have. | ||
164 | intersection :: Bitfield -> Bitfield -> Bitfield | 172 | intersection :: Bitfield -> Bitfield -> Bitfield |
165 | intersection a b = Bitfield { | 173 | intersection a b = Bitfield { |
166 | bfSize = bfSize a `min` bfSize b | 174 | bfSize = bfSize a `min` bfSize b |
167 | , bfSet = bfSet a `S.intersection` bfSet b | 175 | , bfSet = bfSet a `S.intersection` bfSet b |
168 | } | 176 | } |
169 | 177 | ||
178 | -- | Find indices which have first peer but do not have the second peer. | ||
170 | difference :: Bitfield -> Bitfield -> Bitfield | 179 | difference :: Bitfield -> Bitfield -> Bitfield |
171 | difference a b = Bitfield { | 180 | difference a b = Bitfield { |
172 | bfSize = bfSize a -- FIXME is it more reasonable? | 181 | bfSize = bfSize a -- FIXME is it reasonable? |
173 | , bfSet = bfSet a `S.difference` bfSet b | 182 | , bfSet = bfSet a `S.difference` bfSet b |
174 | } | 183 | } |
175 | 184 | ||
185 | -- | | ||
176 | unions :: [Bitfield] -> Bitfield | 186 | unions :: [Bitfield] -> Bitfield |
177 | unions = foldl' union (empty 0) | 187 | unions = foldl' union (haveNone 0) |
178 | 188 | ||
179 | {----------------------------------------------------------------------- | 189 | {----------------------------------------------------------------------- |
180 | Serialization | 190 | Serialization |
181 | -----------------------------------------------------------------------} | 191 | -----------------------------------------------------------------------} |
182 | 192 | ||
193 | -- | | ||
183 | getBitfield :: Int -> Get Bitfield | 194 | getBitfield :: Int -> Get Bitfield |
184 | getBitfield = error "getBitfield" | 195 | getBitfield = error "getBitfield" |
185 | 196 | ||
197 | -- | | ||
186 | putBitfield :: Bitfield -> Put | 198 | putBitfield :: Bitfield -> Put |
187 | putBitfield = error "putBitfield" | 199 | putBitfield = error "putBitfield" |
188 | 200 | ||
201 | -- | | ||
189 | bitfieldByteCount :: Bitfield -> Int | 202 | bitfieldByteCount :: Bitfield -> Int |
190 | bitfieldByteCount = error "bitfieldByteCount" | 203 | bitfieldByteCount = error "bitfieldByteCount" |
191 | 204 | ||
@@ -193,6 +206,7 @@ bitfieldByteCount = error "bitfieldByteCount" | |||
193 | Debug | 206 | Debug |
194 | -----------------------------------------------------------------------} | 207 | -----------------------------------------------------------------------} |
195 | 208 | ||
209 | -- | For internal use only. | ||
196 | mkBitfield :: PieceCount -> [PieceIx] -> Bitfield | 210 | mkBitfield :: PieceCount -> [PieceIx] -> Bitfield |
197 | mkBitfield s ixs = Bitfield { | 211 | mkBitfield s ixs = Bitfield { |
198 | bfSize = s | 212 | bfSize = s |