From: Ramakrishnan Muthukrishnan <ram@rkrishnan.org>
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/components/%22news.html/running.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