summaryrefslogtreecommitdiff
path: root/src/System
diff options
context:
space:
mode:
Diffstat (limited to 'src/System')
-rw-r--r--src/System/Torrent/Storage.hs24
1 files changed, 22 insertions, 2 deletions
diff --git a/src/System/Torrent/Storage.hs b/src/System/Torrent/Storage.hs
index 8c220721..6dda07e1 100644
--- a/src/System/Torrent/Storage.hs
+++ b/src/System/Torrent/Storage.hs
@@ -60,6 +60,7 @@ import Data.Torrent.Piece
60import System.Torrent.FileMap as FM 60import System.Torrent.FileMap as FM
61 61
62 62
63-- | Some storage operations may throw an exception if misused.
63data StorageFailure 64data StorageFailure
64 -- | Occurs on a write operation if the storage has been opened 65 -- | Occurs on a write operation if the storage has been opened
65 -- using 'ReadOnly' mode. 66 -- using 'ReadOnly' mode.
@@ -75,30 +76,45 @@ data StorageFailure
75 76
76instance Exception StorageFailure 77instance Exception StorageFailure
77 78
78-- TODO validation 79-- | Pieces store.
79data Storage = Storage 80data Storage = Storage
80 { mode :: !Mode 81 { mode :: !Mode
81 , pieceLen :: {-# UNPACK #-} !PieceSize 82 , pieceLen :: {-# UNPACK #-} !PieceSize
82 , fileMap :: {-# UNPACK #-} !FileMap 83 , fileMap :: {-# UNPACK #-} !FileMap
83 } 84 }
84 85
85-- ResourceT ? 86-- | Map torrent files:
87--
88-- * when torrent first created use 'ReadWriteEx' mode;
89--
90-- * when seeding, validation 'ReadOnly' mode.
91--
86open :: Mode -> PieceSize -> FileLayout FileSize -> IO Storage 92open :: Mode -> PieceSize -> FileLayout FileSize -> IO Storage
87open mode s l = Storage mode s <$> mmapFiles mode l 93open mode s l = Storage mode s <$> mmapFiles mode l
88 94
95-- | Unmaps all files forcefully. It is recommended but not required.
89close :: Storage -> IO () 96close :: Storage -> IO ()
90close Storage {..} = unmapFiles fileMap 97close Storage {..} = unmapFiles fileMap
91 98
99-- | Normally you need to use 'Control.Monad.Trans.Resource.allocate'.
92withStorage :: Mode -> PieceSize -> FileLayout FileSize 100withStorage :: Mode -> PieceSize -> FileLayout FileSize
93 -> (Storage -> IO ()) -> IO () 101 -> (Storage -> IO ()) -> IO ()
94withStorage m s l = bracket (open m s l) close 102withStorage m s l = bracket (open m s l) close
95 103
104-- TODO allocateStorage?
105
106-- | Count of pieces in the storage.
96totalPieces :: Storage -> PieceCount 107totalPieces :: Storage -> PieceCount
97totalPieces Storage {..} = FM.size fileMap `sizeInBase` pieceLen 108totalPieces Storage {..} = FM.size fileMap `sizeInBase` pieceLen
98 109
99isValidIx :: PieceIx -> Storage -> Bool 110isValidIx :: PieceIx -> Storage -> Bool
100isValidIx i s = 0 <= i && i < totalPieces s 111isValidIx i s = 0 <= i && i < totalPieces s
101 112
113-- | Put piece data at the piece index by overwriting existing
114-- data.
115--
116-- This operation may throw 'StorageFailure'.
117--
102writePiece :: Piece BL.ByteString -> Storage -> IO () 118writePiece :: Piece BL.ByteString -> Storage -> IO ()
103writePiece p @ Piece {..} s @ Storage {..} 119writePiece p @ Piece {..} s @ Storage {..}
104 | mode == ReadOnly = throwIO StorageIsRO 120 | mode == ReadOnly = throwIO StorageIsRO
@@ -120,6 +136,10 @@ writePiece p @ Piece {..} s @ Storage {..}
120 pcount = totalPieces s 136 pcount = totalPieces s
121 offset = fromIntegral pieceIndex * fromIntegral pieceLen 137 offset = fromIntegral pieceIndex * fromIntegral pieceLen
122 138
139-- | Read specific piece from storage.
140--
141-- This operation may throw 'StorageFailure'.
142--
123readPiece :: PieceIx -> Storage -> IO (Piece BL.ByteString) 143readPiece :: PieceIx -> Storage -> IO (Piece BL.ByteString)
124readPiece pix s @ Storage {..} 144readPiece pix s @ Storage {..}
125 | not (isValidIx pix s) = throwIO (InvalidIndex pix) 145 | not (isValidIx pix s) = throwIO (InvalidIndex pix)