From f47c818746c1df4055b1de8aabf47364f502274c Mon Sep 17 00:00:00 2001 From: Joseph Blomstedt Date: Thu, 29 Nov 2012 14:50:42 -0800 Subject: Add sync option to file:open/2 The sync option adds the POSIX O_SYNC flag to the open system call on platforms that support the flag or its equivalent, e.g., FILE_FLAG_WRITE_THROUGH on Windows. For platforms that don't support it, file:open/2 returns {error, enotsup} if the sync option is passed in. The semantics of O_SYNC are platform-specific. For example, not all platforms guarantee that all file metadata are written to the disk along with the file data when the flag is in effect. This issue is noted in the documentation this commit adds for the sync option. Add a test for the sync option. Note however that the underlying OS semantics for O_SYNC can't be tested automatically in any practical way, so the test assumes the OS does the right thing with the flag when present. For manual verification, dtruss on OS X and strace on Linux were both run against beam processes to watch calls to open(), and file:open/2 was called in Erlang shells to open files for writing, both with and without the sync option. Both the dtruss output and the strace output showed that the O_SYNC flag was present in the open() calls when sync was specified and was clear when sync was not specified. --- lib/kernel/doc/src/file.xml | 10 ++++++++++ lib/kernel/src/file.erl | 3 ++- lib/kernel/test/file_SUITE.erl | 14 ++++++++++++++ 3 files changed, 26 insertions(+), 1 deletion(-) (limited to 'lib/kernel') diff --git a/lib/kernel/doc/src/file.xml b/lib/kernel/doc/src/file.xml index 66ecba1bf2..420ecbc3a6 100644 --- a/lib/kernel/doc/src/file.xml +++ b/lib/kernel/doc/src/file.xml @@ -826,6 +826,16 @@

File must be iodata(). Returns an fd() which lets the file module operate on the data in-memory as if it is a file.

+ sync + +

On platforms that support it, enables the POSIX O_SYNC synchronous I/O flag or its platform-dependent + equivalent (e.g., FILE_FLAG_WRITE_THROUGH on Windows) so that writes to the file block until the data has + been physically written to disk. Be aware, though, that the exact semantics of this flag differ from platform to + platform; for example, neither Linux nor Windows guarantees that all file metadata are also written before the call + returns. For precise semantics, check the details of your platform's documentation. On platforms with no + support for POSIX O_SYNC or equivalent, use of the sync flag causes open to return + {error, enotsup}.

+

Returns:

diff --git a/lib/kernel/src/file.erl b/lib/kernel/src/file.erl index 36289053eb..8805215a24 100644 --- a/lib/kernel/src/file.erl +++ b/lib/kernel/src/file.erl @@ -95,7 +95,8 @@ Delay :: non_neg_integer()} | 'delayed_write' | {'read_ahead', Size :: pos_integer()} | 'read_ahead' | 'compressed' - | {'encoding', unicode:encoding()}. + | {'encoding', unicode:encoding()} + | sync. -type deep_list() :: [char() | atom() | deep_list()]. -type name() :: string() | atom() | deep_list(). -type name_all() :: string() | atom() | deep_list() | (RawFilename :: binary()). diff --git a/lib/kernel/test/file_SUITE.erl b/lib/kernel/test/file_SUITE.erl index e4c8f0ffaf..c75639ae7e 100644 --- a/lib/kernel/test/file_SUITE.erl +++ b/lib/kernel/test/file_SUITE.erl @@ -805,6 +805,20 @@ new_modes(Config) when is_list(Config) -> ?line {ok, [$\[]} = ?FILE_MODULE:read(Fd6, 1), ?line ok = ?FILE_MODULE:close(Fd6), + %% write and sync + case ?FILE_MODULE:open(Name1, [write, sync]) of + {ok, Fd7} -> + ok = io:write(Fd7, Marker), + ok = io:put_chars(Fd7, ".\n"), + ok = ?FILE_MODULE:close(Fd7), + {ok, Fd8} = ?FILE_MODULE:open(Name1, [read]), + {ok, Marker} = io:read(Fd8, prompt), + ok = ?FILE_MODULE:close(Fd8); + {error, enotsup} -> + %% for platforms that don't support the sync option + ok + end, + ?line [] = flush(), ?line test_server:timetrap_cancel(Dog), ok. -- cgit v1.2.3