-module(test_file). -export([test/0]). %% %% Code showing off some quirks in the file module. %% %% my_open(File, [raw, binary], false) %% - blocks during a read attempt in a process different from the %% the one that opened the file (in raw mode) %% %% my_open(File, [raw, binary], true) %% - To make sure that the problem didn't lie in the reader %% process I set up a routing mechanism to send the read %% requests to the FileOwner - where in fact they succeed! %% %% my_open(File, [binary], false) %% - there are no issues with the non-raw modes %% (other than the fact that the FileOwner must still be alive) %% test() -> File = "test.txt", case my_open(File, [binary], false) of {ok, IoDevice} -> Stream = iodevice_stream(IoDevice), %% Handle stream spawn(fun() -> read_from_stream(Stream) end), %% The FileOwner must be alive even in the non-raw mode file_server(1000), ok; Error -> io:format("Error opening file: ~p~n", [Error]) end. iodevice_stream(IoDevice) -> fun() -> io:format("Reading data from file...~n"), case my_read(IoDevice, 1024) of eof -> my_close(IoDevice), {}; {ok, Data} -> {Data, iodevice_stream(IoDevice)}; Error -> Error end end. read_from_stream(Stream) -> case Stream() of {Data, RemStream} when is_function(RemStream, 0) -> io:format("Got data: ~p~n", [Data]), read_from_stream(RemStream); {} -> io:format("Got all data!~n"), exit(normal) end. %% %% Functions implementing a router for read requests for files opened in raw mode. %% Without such a router any attempts at reading those files would simply block. %% my_open(File, Modes, Route) -> {ok, IoDevice} = file:open(File, Modes), case Route of true -> FileOwner = self(), {ok, {FileOwner, IoDevice}}; false -> {ok, IoDevice} end. my_read({FileOwner, IoDevice}, Length) -> FileOwner ! {read, self(), IoDevice, Length}, receive Msg -> Msg end; my_read(IoDevice, Length) -> file:read(IoDevice, Length). my_close({FileOwner, IoDevice}) -> FileOwner ! {close, IoDevice}; my_close(IoDevice) -> file:close(IoDevice). file_server(Timeout) -> receive {read, Pid, IoDevice, Bytes} -> Pid ! file:read(IoDevice, Bytes), file_server(Timeout); {close, IoDevice} -> file:close(IoDevice) after Timeout -> io:format("File server: got no requests in a while. Closing...") end.