Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Sync io #1247

Closed
wants to merge 4 commits into from
Closed

Sync io #1247

Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
94 changes: 93 additions & 1 deletion src/lib/io.rs
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,9 @@ type buf_reader =
fn eof() -> bool;
fn seek(int, seek_style);
fn tell() -> uint;
// Needed on readers in case one needs to flush metadata
// changes (atime)
fn fsync(level: fsync::level) -> int;
};


Expand Down Expand Up @@ -58,7 +61,9 @@ fn convert_whence(whence: seek_style) -> i32 {
};
}

resource FILE_res(f: os::libc::FILE) { os::libc::fclose(f); }
resource FILE_res(f: os::libc::FILE) {
os::libc::fclose(f);
}

obj FILE_buf_reader(f: os::libc::FILE, res: option::t<@FILE_res>) {
fn read(len: uint) -> [u8] unsafe {
Expand All @@ -76,6 +81,9 @@ obj FILE_buf_reader(f: os::libc::FILE, res: option::t<@FILE_res>) {
assert (os::libc::fseek(f, offset, convert_whence(whence)) == 0i32);
}
fn tell() -> uint { ret os::libc::ftell(f) as uint; }
fn fsync(level: fsync::level) -> int {
ret os::fsync_fd(os::libc::fileno(f), level) as int;
}
}


Expand Down Expand Up @@ -219,6 +227,7 @@ obj byte_buf_reader(bbuf: byte_buf) {
bbuf.pos = seek_in_buf(offset, pos, len, whence);
}
fn tell() -> uint { ret bbuf.pos; }
fn fsync(_level: fsync::level) -> int { ret 0; }
}

fn new_byte_buf_reader(buf: [u8]) -> buf_reader {
Expand All @@ -242,6 +251,8 @@ type buf_writer =
fn write([u8]);
fn seek(int, seek_style);
fn tell() -> uint;
fn flush() -> int;
fn fsync(level: fsync::level) -> int;
};

obj FILE_writer(f: os::libc::FILE, res: option::t<@FILE_res>) {
Expand All @@ -255,6 +266,10 @@ obj FILE_writer(f: os::libc::FILE, res: option::t<@FILE_res>) {
assert (os::libc::fseek(f, offset, convert_whence(whence)) == 0i32);
}
fn tell() -> uint { ret os::libc::ftell(f) as uint; }
fn flush() -> int { ret os::libc::fflush(f) as int; }
fn fsync(level: fsync::level) -> int {
ret os::fsync_fd(os::libc::fileno(f), level) as int;
}
}

resource fd_res(fd: fd_t) { os::libc::close(fd); }
Expand Down Expand Up @@ -283,6 +298,12 @@ obj fd_buf_writer(fd: fd_t, res: option::t<@fd_res>) {
log_err "need 64-bit native calls for tell, sorry";
fail;
}

fn flush() -> int { ret 0; }

fn fsync(level: fsync::level) -> int {
ret os::fsync_fd(fd, level) as int;
}
}

fn file_buf_writer(path: str,
Expand Down Expand Up @@ -433,6 +454,8 @@ obj byte_buf_writer(buf: mutable_byte_buf) {
buf.pos = seek_in_buf(offset, pos, len, whence);
}
fn tell() -> uint { ret buf.pos; }
fn flush() -> int { ret 0; }
fn fsync(_level: fsync::level) -> int { ret 0; }
}

fn string_writer() -> str_writer {
Expand Down Expand Up @@ -477,6 +500,75 @@ fn read_whole_file(file: str) -> result::t<[u8], str> {
})
}

// fsync related

mod fsync {

tag level {
// whatever fsync does on that platform
fsync;

// fdatasync on linux, similiar or more on other platforms
fdatasync;

// full fsync
//
// You must additionally sync the parent directory as well!
fullfsync;
}


// Resource of artifacts that need to fsync on destruction
resource res<t>(arg: arg<t>) {
alt arg.opt_level {
option::none::<level>. { }
option::some::<level>(level) {
// fail hard if not succesful
assert(arg.fsync_fn(arg.val, level) != -1);
}
}
}

type arg<t> = {
val: t,
opt_level: option::t<level>,
fsync_fn: fn(t, level) -> int
};

// fsync file after executing blk
// FIXME find better way to create resources within lifetime of outer res
fn FILE_res_sync(&&file: FILE_res, opt_level: option::t<level>,
blk: block(&&res<os::libc::FILE>)) {
blk(res({
val: *file, opt_level: opt_level,
fsync_fn: fn(&&file: os::libc::FILE, l: level) -> int {
ret os::fsync_fd(os::libc::fileno(file), l) as int;
}
}));
}

// fsync fd after executing blk
fn fd_res_sync(&&fd: fd_res, opt_level: option::t<level>,
blk: block(&&res<fd_t>)) {
blk(res({
val: *fd, opt_level: opt_level,
fsync_fn: fn(&&fd: fd_t, l: level) -> int {
ret os::fsync_fd(fd, l) as int;
}
}));
}

// Type of objects that may want to fsync
type t = obj { fn fsync(l: level) -> int; };

// Call o.fsync after executing blk
fn obj_sync(&&o: t, opt_level: option::t<level>, blk: block(&&res<t>)) {
blk(res({
val: o, opt_level: opt_level,
fsync_fn: fn(&&o: t, l: level) -> int { ret o.fsync(l); }
}));
}
}


//
Expand Down
12 changes: 12 additions & 0 deletions src/lib/linux_os.rs
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ export exec_suffix;
export target_os;
export dylib_filename;
export get_exe_path;
export fsync_fd;

// FIXME Somehow merge stuff duplicated here and macosx_os.rs. Made difficult
// by https://github.com/graydon/rust/issues#issue/268
Expand All @@ -35,6 +36,10 @@ native mod libc {
fn fopen(path: str::sbuf, mode: str::sbuf) -> FILE;
fn fdopen(fd: fd_t, mode: str::sbuf) -> FILE;
fn fclose(f: FILE);
fn fflush(f: FILE) -> c_int;
fn fsync(fd: fd_t) -> c_int;
fn fdatasync(fd: fd_t) -> c_int;
fn fileno(f: FILE) -> fd_t;
fn fgetc(f: FILE) -> c_int;
fn ungetc(c: c_int, f: FILE);
fn feof(f: FILE) -> c_int;
Expand Down Expand Up @@ -88,6 +93,13 @@ fn fclose(file: libc::FILE) {
libc::fclose(file)
}

fn fsync_fd(fd: fd_t, level: io::fsync::level) -> c_int {
alt level {
io::fsync::fsync. | io::fsync::fullfsync. { ret libc::fsync(fd); }
io::fsync::fdatasync. { ret libc::fdatasync(fd); }
}
}

fn waitpid(pid: pid_t) -> i32 {
let status = 0i32;
assert (os::libc::waitpid(pid, status, 0i32) != -1i32);
Expand Down
46 changes: 34 additions & 12 deletions src/lib/macos_os.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ export exec_suffix;
export target_os;
export dylib_filename;
export get_exe_path;
export fsync_fd;

// FIXME Refactor into unix_os module or some such. Doesn't
// seem to work right now.
Expand All @@ -28,6 +29,9 @@ native mod libc {
type FILE;
fn fopen(path: str::sbuf, mode: str::sbuf) -> FILE;
fn fdopen(fd: fd_t, mode: str::sbuf) -> FILE;
fn fflush(f: FILE) -> c_int;
fn fsync(fd: fd_t) -> c_int;
fn fileno(f: FILE) -> fd_t;
fn fclose(f: FILE);
fn fgetc(f: FILE) -> c_int;
fn ungetc(c: c_int, f: FILE);
Expand All @@ -46,21 +50,26 @@ native mod libc {
fn waitpid(pid: pid_t, &status: c_int, options: c_int) -> c_int;
fn mkdir(s: str::sbuf, mode: c_int) -> c_int;
fn rmdir(s: str::sbuf) -> c_int;

// FIXME: Needs varags
fn fcntl(fd: fd_t, cmd: c_int) -> c_int;
}

mod libc_constants {
const O_RDONLY: c_int = 0i32;
const O_WRONLY: c_int = 1i32;
const O_RDWR: c_int = 2i32;
const O_APPEND: c_int = 8i32;
const O_CREAT: c_int = 512i32;
const O_EXCL: c_int = 2048i32;
const O_TRUNC: c_int = 1024i32;
const O_TEXT: c_int = 0i32; // nonexistent in darwin libc
const O_BINARY: c_int = 0i32; // nonexistent in darwin libc

const S_IRUSR: unsigned = 256u32;
const S_IWUSR: unsigned = 128u32;
const O_RDONLY: c_int = 0i32;
const O_WRONLY: c_int = 1i32;
const O_RDWR: c_int = 2i32;
const O_APPEND: c_int = 8i32;
const O_CREAT: c_int = 512i32;
const O_EXCL: c_int = 2048i32;
const O_TRUNC: c_int = 1024i32;
const O_TEXT: c_int = 0i32; // nonexistent in darwin libc
const O_BINARY: c_int = 0i32; // nonexistent in darwin libc

const S_IRUSR: unsigned = 256u32;
const S_IWUSR: unsigned = 128u32;

const F_FULLFSYNC: c_int = 51i32;
}

fn pipe() -> {in: fd_t, out: fd_t} {
Expand All @@ -87,6 +96,19 @@ fn waitpid(pid: pid_t) -> i32 {
ret status;
}

fn fsync_fd(fd: fd_t, level: io::fsync::level) -> c_int {
alt level {
io::fsync::fsync. { ret libc::fsync(fd); }
_ {
// According to man fnctl, the ok retval is only specified to be !=-1
if (libc::fcntl(libc_constants::F_FULLFSYNC, fd) == -1 as c_int)
{ ret -1 as c_int; }
else
{ ret 0 as c_int; }
}
}
}

#[abi = "cdecl"]
native mod rustrt {
fn rust_getcwd() -> str;
Expand Down
8 changes: 8 additions & 0 deletions src/lib/win32_os.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,9 @@ native mod libc {
fn fopen(path: str::sbuf, mode: str::sbuf) -> FILE;
fn _fdopen(fd: fd_t, mode: str::sbuf) -> FILE;
fn fclose(f: FILE);
fn fflush(f: FILE) -> c_int;
fn fsync(fd: fd_t) -> c_int;
fn fileno(f: FILE) -> fd_t;
fn fgetc(f: FILE) -> c_int;
fn ungetc(c: c_int, f: FILE);
fn feof(f: FILE) -> c_int;
Expand Down Expand Up @@ -92,6 +95,11 @@ fn fclose(file: libc::FILE) {
libc::fclose(file)
}

fn fsync_fd(fd: fd_t, level: io::fsync::level) -> c_int {
// FIXME do something more apropriate
ret libc::fsync(fd);
}

#[abi = "cdecl"]
native mod rustrt {
fn rust_process_wait(handle: c_int) -> c_int;
Expand Down