given these types (HFuse), can I share state?

Hi, Firstly, this is my first post to this list, I consider myself a Haskell beginner but this question might be a bit esoteric so please let me know if I'm better directing this elsewhere. I'm writing a small fuse-based filesystem[1] using hfuse[2]. I get to write functions to a defined type. One of these is 'open', for when the user opens a file; another is 'read', for when a user invokes the read syscall. Here are the type signatures: fuseOpen :: FilePath -> OpenMode -> OpenFileFlags -> IO (Either Errno fh) fuseRead :: FilePath -> fh -> ByteCount -> FileOffset -> IO (Either Errno ByteString) In the case of my filesystem, for a typical work pattern of open, read, read, read…; there's an amount of setup that is required up front (possibly combining two or more files via patches; uncompressing files, etc.) which can be quite expensive. With my current implementation, I am having to do this work in the read function[3], because I can't figure out a way of doing it in the open function and sharing the state with subsequent reads. I think this is likely to be a performance issue and I'd prefer to have it done once, in the open function. I know that there are various 'state' monads, although I've never used them. In my case the signature for my functions is fixed, but the 'return' type is the IO monad. Is there any possibility for me to hide/share state 'through' the IO monad? Thanks for your help, [1] http://jmtd.net/software/rdifffs/ [2] http://hackage.haskell.org/packages/archive/HFuse/0.2.4/doc/html/System-Fuse... [3] the work takes place within 'rdiffIncrementReadFile', here: https://github.com/jmtd/rdifffs/blob/master/rdifffs.lhs#L558 -- Jon Dowland

On Wed, Mar 28, 2012 at 9:32 AM, Jon Dowland
Hi,
Firstly, this is my first post to this list, I consider myself a Haskell beginner but this question might be a bit esoteric so please let me know if I'm better directing this elsewhere.
I'm writing a small fuse-based filesystem[1] using hfuse[2]. I get to write functions to a defined type. One of these is 'open', for when the user opens a file; another is 'read', for when a user invokes the read syscall. Here are the type signatures:
fuseOpen :: FilePath -> OpenMode -> OpenFileFlags -> IO (Either Errno fh)
fuseRead :: FilePath -> fh -> ByteCount -> FileOffset -> IO (Either Errno ByteString)
In the case of my filesystem, for a typical work pattern of open, read, read, read…; there's an amount of setup that is required up front (possibly combining two or more files via patches; uncompressing files, etc.) which can be quite expensive.
With my current implementation, I am having to do this work in the read function[3], because I can't figure out a way of doing it in the open function and sharing the state with subsequent reads. I think this is likely to be a performance issue and I'd prefer to have it done once, in the open function.
I've never used hfuse, but can't you put the state you need in the 'fh' type you pass back from 'fuseOpen'? In your case it is the 'HT' type. I'm imagining something like:
data HT = HT (IORef HandleState)
Antoine

You can create shared state prior to making FuseOperations. Define
functions like this:
mkFuseOperations :: SharedState -> FuseOperations MyHandleType
mkSharedState :: IO SharedState
The type SharedState can be anything you like, similarly to MyHandleType.
type SharedState = IORef String
type MyHandleType = Handle
Example implementation:
mkSharedState name = newIORef name
mkFuseOperations shared = defaultFuseOps {
fuseInit = do { print "FUSE INIT MODULE"; print =<< readIORef shared
},
fuseDestroy = do { print "FUSE DESTROY MODULE"; print =<< readIORef
shared }; }
main = do
ss <- mkSharedState "my fuse module"
let fo = mkFuseOperations ss
fuseMain fo defaultExceptionHandler
Best regards,
Krzysztof Skrzętnicki
On Wed, Mar 28, 2012 at 16:32, Jon Dowland wrote: Hi, Firstly, this is my first post to this list, I consider myself a Haskell
beginner but this question might be a bit esoteric so please let me know
if I'm
better directing this elsewhere. I'm writing a small fuse-based filesystem[1] using hfuse[2]. I get to
write
functions to a defined type. One of these is 'open', for when the user
opens a
file; another is 'read', for when a user invokes the read syscall. Here
are the
type signatures: fuseOpen :: FilePath -> OpenMode -> OpenFileFlags -> IO (Either Errno fh) fuseRead :: FilePath -> fh -> ByteCount -> FileOffset -> IO (Either Errno
ByteString) In the case of my filesystem, for a typical work pattern of open, read,
read, read…;
there's an amount of setup that is required up front (possibly combining
two or more
files via patches; uncompressing files, etc.) which can be quite expensive. With my current implementation, I am having to do this work in the read
function[3],
because I can't figure out a way of doing it in the open function and
sharing the
state with subsequent reads. I think this is likely to be a performance
issue and
I'd prefer to have it done once, in the open function. I know that there are various 'state' monads, although I've never used
them. In
my case the signature for my functions is fixed, but the 'return' type is
the
IO monad. Is there any possibility for me to hide/share state 'through'
the IO
monad? Thanks for your help, [1] http://jmtd.net/software/rdifffs/
[2]
http://hackage.haskell.org/packages/archive/HFuse/0.2.4/doc/html/System-Fuse...
[3] the work takes place within 'rdiffIncrementReadFile', here:
https://github.com/jmtd/rdifffs/blob/master/rdifffs.lhs#L558 --
Jon Dowland _______________________________________________
Beginners mailing list
Beginners@haskell.org
http://www.haskell.org/mailman/listinfo/beginners
participants (3)
-
Antoine Latter
-
Jon Dowland
-
Krzysztof Skrzętnicki