diff options
Diffstat (limited to 'examples/MkTorrent.hs')
-rw-r--r-- | examples/MkTorrent.hs | 73 |
1 files changed, 59 insertions, 14 deletions
diff --git a/examples/MkTorrent.hs b/examples/MkTorrent.hs index 7bf8b513..49856f9b 100644 --- a/examples/MkTorrent.hs +++ b/examples/MkTorrent.hs | |||
@@ -5,10 +5,12 @@ | |||
5 | module Main (main) where | 5 | module Main (main) where |
6 | 6 | ||
7 | import Prelude as P | 7 | import Prelude as P |
8 | import Control.Concurrent.ParallelIO | ||
8 | import Control.Exception | 9 | import Control.Exception |
9 | import Control.Lens hiding (argument) | 10 | import Control.Lens hiding (argument) |
10 | import Control.Monad | 11 | import Control.Monad |
11 | import Data.List as L | 12 | import Data.List as L |
13 | import Data.Maybe | ||
12 | import Data.Monoid | 14 | import Data.Monoid |
13 | import Data.Text as T | 15 | import Data.Text as T |
14 | import qualified Data.Text.IO as T | 16 | import qualified Data.Text.IO as T |
@@ -24,8 +26,12 @@ import Text.PrettyPrint.Class | |||
24 | 26 | ||
25 | import Paths_bittorrent (version) | 27 | import Paths_bittorrent (version) |
26 | import Data.Torrent | 28 | import Data.Torrent |
29 | import Data.Torrent.Bitfield as BF | ||
30 | import Data.Torrent.Piece | ||
31 | import Data.Torrent.Layout | ||
27 | import Data.Torrent.Magnet hiding (Magnet (Magnet)) | 32 | import Data.Torrent.Magnet hiding (Magnet (Magnet)) |
28 | import Data.Torrent.Magnet (Magnet) | 33 | import Data.Torrent.Magnet (Magnet) |
34 | import System.Torrent.Storage | ||
29 | 35 | ||
30 | 36 | ||
31 | {----------------------------------------------------------------------- | 37 | {----------------------------------------------------------------------- |
@@ -138,27 +144,66 @@ amend (AmendOpts tpath) = do | |||
138 | toFile tpath $ a t | 144 | toFile tpath $ a t |
139 | 145 | ||
140 | {----------------------------------------------------------------------- | 146 | {----------------------------------------------------------------------- |
141 | -- Check command | 147 | -- Check command -- validate content files using torrent file |
142 | -----------------------------------------------------------------------} | 148 | -----------------------------------------------------------------------} |
143 | 149 | ||
144 | {- | 150 | data CheckOpts = CheckOpts |
145 | checkOpts :: Parser CheckOpts | 151 | { checkTorrentPath :: FilePath -- ^ validation torrent file |
146 | checkOpts = CheckOpts | 152 | , checkContentPath :: FilePath -- ^ root dir for content files |
147 | <$> torrentFile | 153 | } deriving Show |
148 | <*> argument Just | ||
149 | ( metavar "PATH" | ||
150 | <> value "." | ||
151 | <> help "Content directory or a single file" ) | ||
152 | 154 | ||
153 | checkInfo :: ParserInfo CheckOpts | 155 | checkInfo :: ParserInfo CheckOpts |
154 | checkInfo = info (helper <*> checkOpts) modifier | 156 | checkInfo = info (helper <*> parser) modifier |
155 | where | 157 | where |
156 | modifier = progDesc "Validate integrity of torrent data" | 158 | modifier = progDesc "Validate integrity of torrent data" |
159 | parser = CheckOpts | ||
160 | <$> torrentFile | ||
161 | <*> argument Just | ||
162 | ( metavar "PATH" | ||
163 | <> value "." | ||
164 | <> help "Content directory or a single file" | ||
165 | ) | ||
166 | |||
167 | validatePiece :: Storage -> PieceInfo -> PieceIx -> IO (Maybe PieceIx) | ||
168 | validatePiece s pinfo pix = do | ||
169 | valid <- verifyPiece s pinfo pix | ||
170 | if valid | ||
171 | then do infoM "check" $ "valid piece " ++ show pix | ||
172 | return (Just pix) | ||
173 | else do infoM "check" $ "invalid piece " ++ show pix | ||
174 | return Nothing | ||
175 | |||
176 | validateStorage :: Storage -> PieceInfo -> IO Bitfield | ||
177 | validateStorage s pinfo = do | ||
178 | infoM "check" "start storage validation" | ||
179 | let total = totalPieces s | ||
180 | pixs <- parallel $ L.map (validatePiece s pinfo) [0 .. total - 1] | ||
181 | infoM "check" "storage validation finished" | ||
182 | return $ fromList total $ catMaybes pixs | ||
183 | |||
184 | -- TODO use local thread pool | ||
185 | checkContent :: Storage -> PieceInfo -> IO () | ||
186 | checkContent s pinfo = do | ||
187 | invalids <- BF.complement <$> validateStorage s pinfo | ||
188 | if BF.null invalids | ||
189 | then noticeM "check" "all files are complete and valid" | ||
190 | else do | ||
191 | emergencyM "check" $ "there are some invalid pieces" ++ show invalids | ||
192 | exitFailure | ||
193 | |||
194 | checkTorrent :: CheckOpts -> IO () | ||
195 | checkTorrent CheckOpts {..} = do | ||
196 | InfoDict {..} <- tInfoDict <$> fromFile checkTorrentPath | ||
197 | let layout = flatLayout checkContentPath idLayoutInfo | ||
198 | withStorage ReadOnly (piPieceLength idPieceInfo) layout $ \ s -> do | ||
199 | infoM "check" "files mapped" | ||
200 | checkContent s idPieceInfo | ||
201 | infoM "check" "unmapping files" | ||
157 | 202 | ||
158 | {----------------------------------------------------------------------- | 203 | {----------------------------------------------------------------------- |
159 | -- Create command | 204 | -- Create command |
160 | -----------------------------------------------------------------------} | 205 | -----------------------------------------------------------------------} |
161 | 206 | {- | |
162 | createFlags :: Parser CreateFlags | 207 | createFlags :: Parser CreateFlags |
163 | createFlags = CreateFlags | 208 | createFlags = CreateFlags |
164 | <$> optional (option | 209 | <$> optional (option |
@@ -257,7 +302,7 @@ putTorrent opts @ ShowOpts {..} = do | |||
257 | 302 | ||
258 | data Command | 303 | data Command |
259 | = Amend AmendOpts | 304 | = Amend AmendOpts |
260 | -- | Check CheckOpts | 305 | | Check CheckOpts |
261 | -- | Create CreateOpts | 306 | -- | Create CreateOpts |
262 | | Magnet MagnetOpts | 307 | | Magnet MagnetOpts |
263 | | Show ShowOpts | 308 | | Show ShowOpts |
@@ -266,7 +311,7 @@ data Command | |||
266 | commandOpts :: Parser Command | 311 | commandOpts :: Parser Command |
267 | commandOpts = subparser $ mconcat | 312 | commandOpts = subparser $ mconcat |
268 | [ command "amend" (Amend <$> amendInfo) | 313 | [ command "amend" (Amend <$> amendInfo) |
269 | -- , command "check" (Check <$> checkInfo) | 314 | , command "check" (Check <$> checkInfo) |
270 | -- , command "create" (Create <$> createInfo) | 315 | -- , command "create" (Create <$> createInfo) |
271 | , command "magnet" (Magnet <$> magnetInfo) | 316 | , command "magnet" (Magnet <$> magnetInfo) |
272 | , command "show" (Show <$> showInfo) | 317 | , command "show" (Show <$> showInfo) |
@@ -349,7 +394,7 @@ parserInfo = info parser modifier | |||
349 | 394 | ||
350 | run :: Command -> IO () | 395 | run :: Command -> IO () |
351 | run (Amend opts) = amend opts | 396 | run (Amend opts) = amend opts |
352 | --run (Check opts) = checkTorrent opts | 397 | run (Check opts) = checkTorrent opts |
353 | --run (Create opts) = createTorrent opts | 398 | --run (Create opts) = createTorrent opts |
354 | run (Magnet opts) = magnet opts | 399 | run (Magnet opts) = magnet opts |
355 | run (Show opts) = putTorrent opts | 400 | run (Show opts) = putTorrent opts |