Project

General

Profile

Actions

Feature #13696

open

Add exchange and noreplace options to File.rename

Added by Glass_saga (Masaki Matsushita) over 6 years ago. Updated over 6 years ago.

Status:
Open
Target version:
-
[ruby-core:81823]

Description

renameat2(2) introduced in linux kernel 3.15 takes following flags.

RENAME_EXCHANGE: Atomically exchange oldpath and newpath.

RENAME_NOREPLACE: Don't overwrite newpath of the rename. Return an error if newpath already exists.

This change makes File.rename take these flags as keyword arguments.

Example:

File.write("hoge", "hoge")
File.write("fuga", "fuga")
File.rename("hoge", "fuga", exchange: true) # atomically exchanged
File.read("fuga") #=> "hoge"

File.rename("hoge", "fuga", noreplace: true) #=> File exists @ syserr_fail2_in - fuga (Errno::EEXIST)

Files

patch.diff (4.19 KB) patch.diff Glass_saga (Masaki Matsushita), 06/29/2017 02:06 AM
patch.diff (4.84 KB) patch.diff Glass_saga (Masaki Matsushita), 06/30/2017 03:42 AM

Updated by nobu (Nobuyoshi Nakada) over 6 years ago

  • Description updated (diff)

Glass_saga (Masaki Matsushita) wrote:

File.rename("hoge", "fuga", exchange: true) # atomically exchanged

How about another method, say, File.exchange?

File.rename("hoge", "fuga", noreplace: true) #=> File exists @ syserr_fail2_in - fuga (Errno::EEXIST)

I prefer positive-form to negative-form as an option, i.e., File.rename(old, new[, replace: true]).

Updated by shevegen (Robert A. Heiler) over 6 years ago

I prefer positive-form to negative-form as an option

I do too. I found it in general easier (for me) to understand positive/forward
declarations.

Updated by Glass_saga (Masaki Matsushita) over 6 years ago

Thank you for your comments.
I implemented FIle.exchange and made the noreplace flag in positive-form.

File.write("hoge", "hoge")
File.write("fuga", "fuga")
File.exchange("hoge", "fuga")
p File.read("fuga") #=> "hoge"

File.rename("hoge", "fuga", replace: false) #=> File exists @ syserr_fail2_in - fuga (Errno::EEXIST)

Updated by nobu (Nobuyoshi Nakada) over 6 years ago

Is "atomically" important?
If no, it'd be possible to implement without kernel support.

Updated by normalperson (Eric Wong) over 6 years ago

wrote:

Is "atomically" important?
If no, it'd be possible to implement without kernel support.

Yes, atomicity is an important distinction.

We should not try to implement this non-atomically without kernel
support; it will quietly break code which expects the atomicity.

I am recalling similar problems around posix_fallocate in glibc:
https://sourceware.org/bugzilla/show_bug.cgi?id=15661

Updated by Glass_saga (Masaki Matsushita) over 6 years ago

I think atomicity is important. If the kernel doesn't support atomic exchange, File.exchange should raise NotImplementedError and users can handle it properly.

begin
  File.exchange("hoge", "fuga")
rescue NotImplementedError
  # exchange files in another way
end

Updated by duerst (Martin Dürst) over 6 years ago

nobu (Nobuyoshi Nakada) wrote:

Glass_saga (Masaki Matsushita) wrote:

File.rename("hoge", "fuga", exchange: true) # atomically exchanged

How about another method, say, File.exchange?

File.rename("hoge", "fuga", noreplace: true) #=> File exists @ syserr_fail2_in - fuga (Errno::EEXIST)

I prefer positive-form to negative-form as an option, i.e., File.rename(old, new[, replace: true]).

I think both exchange: and noreplace: are difficult to understand for an outside user. I think overwrite: is much easier to understand.

Updated by shyouhei (Shyouhei Urabe) over 6 years ago

I think it's hard to have platform-specific API extensions like this to be in-core. If atomicity is such an important feature (and I'm sure it is), it's hard to emulate this in pure-userland for people without OS that support it.

This should be implemented as a gem. That way, gem install can bail out purposefully for unsupported platforms. That should prevent hidden race condition that you want to avoid.

Actions #9

Updated by naruse (Yui NARUSE) over 6 years ago

  • Target version deleted (2.5)
Actions

Also available in: Atom PDF

Like0
Like0Like0Like0Like0Like0Like0Like0Like0Like0