@@ -2,11 +2,27 @@
22--this module is related to persisting Project:M36 structures to disk and not related to the persistent library
33module ProjectM36.Persist (writeFileSync,
44 writeBSFileSync,
5− renameSync,
5+ renameSync,
6+ printFdCount,
67 DiskSync(..)) where
78-- on Windows, use FlushFileBuffers and MoveFileEx
89import qualified Data.Text.IO as TIO
9−import Data.Text
10+import qualified Data.Text as T
11+
12+#if defined(linux_HOST_OS)
13+# define FDCOUNTSUPPORTED 1
14+# define FDDIR "/proc/self/fd"
15+#elif defined(darwin_HOST_OS)
16+# define FDCOUNTSUPPORTED 1
17+# define FDDIR "/dev/fd"
18+#else
19+# define FDCOUNTSUPPORTED 0
20+#endif
21+
22+#if FDCOUNTSUPPORTED
23+import System.Directory
24+#endif
25+
1026#if defined(mingw32_HOST_OS)
1127import qualified System.Win32 as Win32
1228#else
@@ -16,7 +32,7 @@ import System.Posix.Unistd (fileSynchroniseDataOnly)
1632#else
1733import System.Posix.Unistd (fileSynchronise)
1834#endif
19−import System.Posix.IO (handleToFd)
35+import System.Posix.IO (handleToFd, closeFd)
2036import Foreign.C
2137#endif
2238
@@ -32,7 +48,7 @@ foreign import ccall unsafe "cDirectoryFsync" cHSDirectoryFsync :: CString -> IO
3248data DiskSync = NoDiskSync | FsyncDiskSync
3349
3450--using withFile here is OK because we use a WORM strategy- the file is written but not read until after the handle is synced, closed, and unhidden (moved from ".X" to "X") at the top level in the transaction directory
35−writeFileSync :: DiskSync -> FilePath -> Text -> IO()
51+writeFileSync :: DiskSync -> FilePath -> T.Text -> IO()
3652writeFileSync sync path strOut = withFile path WriteMode handler
3753 where
3854 handler handle = do
@@ -60,10 +76,15 @@ syncHandle FsyncDiskSync handle =
6076 withHandleToHANDLE handle (\h -> Win32.flushFileBuffers h)
6177#elif defined(linux_HOST_OS)
6278 --fdatasync doesn't exist on macOS
63− handleToFd handle >>= fileSynchroniseDataOnly
64−#else
65− handleToFd handle >>= fileSynchronise
79+ fd <- handleToFd handle
80+ fileSynchroniseDataOnly fd
81+#else
82+ do
83+ fd <- handleToFd handle
84+ fileSynchronise fd
6685#endif
86+ closeFd fd
87+
6788syncHandle NoDiskSync _ = pure ()
6889
6990syncDirectory :: DiskSync -> FilePath -> IO ()
@@ -83,3 +104,24 @@ directoryFsync _ = pure () -- on Windows directory metadata cannot be synchroniz
83104directoryFsync path = throwErrnoIfMinus1Retry_ "directoryFsync" (withCString path $ \cpath -> cHSDirectoryFsync cpath)
84105#endif
85106
107+--prints out number of consumed file descriptors
108+printFdCount :: IO ()
109+printFdCount = do
110+#if FDCOUNTSUPPORTED
111+ fdc <- fdCount
112+ putStrLn ("Fd count: " ++ show fdc)
113+ --getLine >> pure ()
114+#else
115+printFdCount = putStrLn "Fd count not supported on this OS."
116+#endif
117+
118+
119+fdCount :: IO Int
120+#if FDCOUNTSUPPORTED
121+fdCount = do
122+ fds <- getDirectoryContents FDDIR
123+ pure ((length fds) - 2)
124+#else
125+--not supported on non-linux
126+fdCount = pure 0
127+#endif