From: Ramakrishnan Muthukrishnan Date: Thu, 10 Dec 2015 13:23:21 +0000 (+0530) Subject: FileSystem: encapsulate more filesystem functionality into the module X-Git-Url: https://git.rkrishnan.org/about.html?a=commitdiff_plain;h=273f2b0dde373ef12e7915e82aba8e2c38733dc9;p=functorrent.git FileSystem: encapsulate more filesystem functionality into the module --- diff --git a/src/FuncTorrent/FileSystem.hs b/src/FuncTorrent/FileSystem.hs index 1b190ca..e064b71 100644 --- a/src/FuncTorrent/FileSystem.hs +++ b/src/FuncTorrent/FileSystem.hs @@ -1,7 +1,7 @@ module FuncTorrent.FileSystem (startThread, MsgChannel, - initFS, + createMsgChannel, Msg(..), Piece(..), pieceMapFromFile @@ -16,10 +16,11 @@ import Data.Map (traverseWithKey) import qualified Data.ByteString as BS import Data.Map ((!)) -import System.IO (Handle, openFile, IOMode (ReadWriteMode)) +import System.IO (Handle, IOMode (ReadWriteMode), withFile) +import System.Directory (doesFileExist) import FuncTorrent.PieceManager (PieceDlState(..), PieceData(..), PieceMap, pieceNumToOffset) -import FuncTorrent.Utils (readFileAtOffset, writeFileAtOffset, verifyHash) +import FuncTorrent.Utils (createDummyFile, readFileAtOffset, writeFileAtOffset, verifyHash) type PieceNum = Integer data Piece = Piece PieceNum BS.ByteString @@ -30,15 +31,11 @@ data Msg = ReadPiece PieceNum Integer (MVar Piece) type MsgChannel = Chan Msg --- init :: FileName -> IO (Handle, MsgChannel) -initFS :: FilePath -> IO (Handle, MsgChannel) -initFS filepath = do - c <- newChan - h <- openFile filepath ReadWriteMode - return (h, c) +createMsgChannel :: IO (Chan Msg) +createMsgChannel = newChan -startThread :: Handle -> MsgChannel -> PieceMap -> IO ThreadId -startThread handle c pieceMap = do +startThread :: PieceMap -> MsgChannel -> Handle -> IO ThreadId +startThread pieceMap c handle = do forkIO $ forever $ recvMsg >>= sendResponse where recvMsg = readChan c @@ -65,13 +62,16 @@ startThread handle c pieceMap = do bs' <- readFileAtOffset handle offset len' return $ verifyHash bs' hash' -pieceMapFromFile :: Handle -> PieceMap -> IO PieceMap -pieceMapFromFile handle pieceMap = do - traverseWithKey f pieceMap +pieceMapFromFile :: FilePath -> Integer -> PieceMap -> IO PieceMap +pieceMapFromFile filePath fileLen pieceMap = do + dfe <- doesFileExist filePath + if dfe + then traverseWithKey f pieceMap + else createDummyFile filePath (fromIntegral fileLen) >> return pieceMap where f k v = do let offset = pieceNumToOffset pieceMap k - isHashValid <- flip verifyHash (hash v) <$> readFileAtOffset handle offset (len v) + isHashValid <- flip verifyHash (hash v) <$> withFile filePath ReadWriteMode (\handle -> readFileAtOffset handle offset (len v)) if isHashValid then return $ v { dlstate = Have } else return v diff --git a/src/main/Main.hs b/src/main/Main.hs index a75f01c..a7efef0 100644 --- a/src/main/Main.hs +++ b/src/main/Main.hs @@ -6,15 +6,15 @@ import Prelude hiding (log, length, readFile, getContents) import Control.Concurrent (forkIO) import Control.Concurrent.MVar (readMVar) import Data.ByteString.Char8 (ByteString, getContents, readFile) -import qualified FuncTorrent.FileSystem as FS (initFS, pieceMapFromFile, startThread) +import qualified FuncTorrent.FileSystem as FS (createMsgChannel, pieceMapFromFile, startThread) import FuncTorrent.Logger (initLogger, logMessage, logStop) import FuncTorrent.Metainfo (Info(..), Metainfo(..), torrentToMetainfo) import FuncTorrent.Peer (handlePeerMsgs) import FuncTorrent.PieceManager (initPieceMap) import qualified FuncTorrent.Server as Server import FuncTorrent.Tracker (connectedPeers, initialTrackerState, trackerLoop, udpTrackerLoop) -import FuncTorrent.Utils (createDummyFile) import Network (PortID (PortNumber)) +import System.IO (withFile, IOMode (ReadWriteMode)) import System.Directory (doesFileExist) import System.Environment (getArgs) import System.Exit (exitSuccess) @@ -71,18 +71,11 @@ main = do pLen = pieceLength (info m) defaultPieceMap = initPieceMap pieceHash fileLen pLen log $ "create FS msg channel" - (handle, fsMsgChannel) <- FS.initFS filePath + fsMsgChannel <- FS.createMsgChannel log $ "Downloading file : " ++ filePath - dfe <- doesFileExist filePath - pieceMap <- if dfe - then - FS.pieceMapFromFile handle defaultPieceMap - else do - -- create a dummy file - createDummyFile filePath (fromIntegral fileLen) >> - return defaultPieceMap + pieceMap <- FS.pieceMapFromFile filePath fileLen defaultPieceMap log $ "start filesystem manager thread" - FS.startThread handle fsMsgChannel pieceMap + withFile filePath ReadWriteMode (FS.startThread pieceMap fsMsgChannel) log $ "starting server" (serverSock, (PortNumber portnum)) <- Server.start log $ "server started on " ++ show portnum