Project

General

Profile

Actions

Feature #4592

open

Tempfileを直接保存したい

Added by xibbar (Takeyuki FUJIOKA) over 13 years ago. Updated almost 7 years ago.

Status:
Assigned
Target version:
-
[ruby-dev:43412]

Description

=begin
Tempfileは一時ファイルなので、プロセスが消えたり、#closeすると、
ファイルが消えてしまいます。
Tempfileのデータを保存するために
一旦読みだして、書き込み用に別ファイルを開いて、
そこに書きこまなければいけません。
これが小さいファイルだったらいいのですが、
大きいファイルになると、
Tempfile#save みたいなメソッドを用意して、
closeと同時に保存ができると、
読みだして書きこむという無駄をなくすことができます。
10MB程度だったらいいのですが、500MとかのTempfileだと
かなり有効なメソッドだと思います。

#save とか #save! とか、何がいいかは議論の余地があると思います。
=end

Updated by sakuro (Sakuro OZAWA) over 13 years ago

#close(real=false) したあと、 #path を使って、保存したいところに File#rename とか、 File#link を使うとよいと思います。

Updated by sakuro (Sakuro OZAWA) over 13 years ago

先頭が # だと丸ごと見えなくなるのか…

#close(real=false)したあと、#path を使って、保存したいところに File#rename とか、 File#link を使うとよいと思います。

Updated by mrkn (Kenta Murata) over 13 years ago

Tempfile#mv(path) というメソッドを追加するパッチを書いてみました。
https://gist.github.com/933915

File.rename してるので、元のファイルが無くなっちゃいますし、
元のファイルと同じファイル名のまま維持したい場合は使えなかったりします。

Updated by sakuro (Sakuro OZAWA) over 13 years ago

FileUtils と間違えた。 renamelinkFile のクラスメソッドでした。

Updated by shyouhei (Shyouhei Urabe) over 13 years ago

  • closeと同時というのを諦め、closeのちょっと後でよければ、普通にmvできるのではないでしょうか。

    irb(main):001:0> f = Tempfile.new('')
    => #<File:/tmp/20110421-7098-1bvjwc0>
    irb(main):002:0> f.puts("foobar")
    => nil
    irb(main):003:0> f.close; File.rename(f, "tmp.txt")
    => 0
    irb(main):008:0> File.read("tmp.txt")
    => "foobar\n"
    
  • /tmpとRubyのカレントディレクトリが別パーティションだったら、どのみちコピーは発生するのではないでしょうか。

  • Tempfile を保存したいというのは Tempfile の意味からして本末転倒なのではないでしょうか。

といった感想を抱きました。

Updated by xibbar (Takeyuki FUJIOKA) over 13 years ago

卜部さんの言うとおりなのですが、ユースケースを書きますと、
Railsもcgi.rbも巨大なファイルをアップロードしたときは
tempfileにファイルを保存します。
これを保存したいとなったときに、
tempfileから読みだして、別ファイルをオープンして
書きこむという手間とメモリが必要なので、
tempfileに入っているんだから、そのままリネームでもして
保存出来ればいいのになと思ったのでした。

ちなみに卜部さんのやり方ももちろんOKですが、
私的にはHTTP Requestをまたいで使いたいので、
tempfileを消えないようにだけするという対応でも
OKなのでした。tempfile名をセッションにでも入れて、
次のリクエストでまた開くということをやりたかったです。

Updated by mame (Yusuke Endoh) over 12 years ago

  • Description updated (diff)
  • Status changed from Open to Assigned
  • Assignee set to mame (Yusuke Endoh)

Updated by akr (Akira Tanaka) over 12 years ago

remove_finalizer とか、save とかよりももうちょっと長い名前がいいんじゃないかなぁ、と思います。

Updated by ko1 (Koichi Sasada) over 12 years ago

(2012/03/25 15:33), akr (Akira Tanaka) wrote:

remove_finalizer とか、save とかよりももうちょっと長い名前がいいんじゃないかなぁ、と思います。

 mv なり hardlink などして,File を返すインターフェースとかだと良かった
りしないでしょかね.「消されない」Tempfile ってのに違和感がありまして.

 Tempfile#mv(filepath) #=> File とか,cp でもいいか.

--
// SASADA Koichi at atdot dot net

Updated by mame (Yusuke Endoh) over 12 years ago

どういう意味でこのチケットを自分にアサインしたか忘れてしまったのですが。

shyouhei (Shyouhei Urabe) wrote:

  • closeと同時というのを諦め、closeのちょっと後でよければ、普通にmvできるのではないでしょうか。

    irb(main):001:0> f = Tempfile.new('')
    => #<File:/tmp/20110421-7098-1bvjwc0>
    irb(main):002:0> f.puts("foobar")
    => nil
    irb(main):003:0> f.close; File.rename(f, "tmp.txt")
    => 0
    irb(main):008:0> File.read("tmp.txt")
    => "foobar\n"
    

これは、GC タイミングによっては失敗しますよね。(f.close の直後で GC)
また、rename 後に元のファイル名と同じファイルを作ったら、この tempfile が
GC される際に消されてしまう危険があると思います。
よって、workaround としては推奨しかねるものだと思います。

  • /tmpとRubyのカレントディレクトリが別パーティションだったら、どのみちコピーは発生するのではないでしょうか。

気にするなら、Tempfile 生成ディレクトリを自分で指定すればいいと思います。

  • Tempfileを保存したいというのはTempfileの意味からして本末転倒なのではないでしょうか。

これは個人の感覚の問題だと思いますが、「temporary だけど、うまく行けば
永続化するつもり」というのは私はいいかなあと思いました。

akr (Akira Tanaka) wrote:

remove_finalizer とか、save とかよりももうちょっと長い名前がいいんじゃないかなぁ、と思います。

Tempfile#persist とか、秋葉原の開発者会議で出た案でしたっけ。

--
Yusuke Endoh

Updated by mame (Yusuke Endoh) over 12 years ago

  • Assignee changed from mame (Yusuke Endoh) to matz (Yukihiro Matsumoto)

mame (Yusuke Endoh) wrote:

どういう意味でこのチケットを自分にアサインしたか忘れてしまったのですが。

思い出しました。開発者会議で出た内容をまとめて matz に振るのでした。
しかし開発者会議で出た内容を正確に覚えてないんですが、

  • ユースケースは理解できる
  • 卜部さんの workaround は推奨されない
  • 良い API・名前はなんだろう

くらいだったと思います。間違ってたら正してください > 参加者

matz が直接判断しなくても、tempfile.rb のメンテナになってくれる人が
いれば判断できると思います。
まあメンテナになるのに matz の承認が必要ですが。

あと訂正。

これは、GC タイミングによっては失敗しますよね。(f.close の直後で GC)

これは間違いでした。f の参照が残っているので GC されることはありません。
でも race condition の問題はあるので、やはり推奨はされない、という話
だったと思います。

--
Yusuke Endoh

Updated by ko1 (Koichi Sasada) over 12 years ago

(2012/04/02 21:50), mame (Yusuke Endoh) wrote:

くらいだったと思います。間違ってたら正してください > 参加者

 間違ってないですが,個人的には Tempfile インスタンスのまま消えないのは
不思議なので,Tempfile#xxx #=> File みたいなメソッド xxx があるといいん
じゃないかなぁ,と.って,ruby-dev:45436 に書いてるじゃん.

--
// SASADA Koichi at atdot dot net

Updated by mame (Yusuke Endoh) about 12 years ago

  • Target version set to 2.6

Updated by xibbar (Takeyuki FUJIOKA) over 11 years ago

Tempfile#to_file!(path)

とか?

自分の提起チケットなので反応してみました。

いろいろあった結果、担当がMatzになっていますね。

Actions #15

Updated by naruse (Yui NARUSE) almost 7 years ago

  • Target version deleted (2.6)
Actions #16

Updated by Glass_saga (Masaki Matsushita) almost 7 years ago

  • Related to Feature #13743: Support linking of files opened with O_TMPFILE added
Actions #17

Updated by Glass_saga (Masaki Matsushita) almost 7 years ago

  • Related to deleted (Feature #13743: Support linking of files opened with O_TMPFILE)
Actions

Also available in: Atom PDF

Like0
Like0Like0Like0Like0Like0Like0Like0Like0Like0Like0Like0Like0Like0Like0Like0Like0Like0