かずひこです。
以下の件、特に反対がなければ、後半のパッチの内容で今週末にコミットしよう
と思います。
At Thu, 16 Dec 2004 23:01:05 +0900,
Kazuhiko wrote:
>
> かずひこです。
>
> mod_ruby 環境の Matz 日記がときどきささっていたのですが、どうやら排他ロッ
> クがごくまれに残ったままになっていたようです。fastcgi や webrick による動
> 作でも同じことが起こり得ると思われます。
>
> ですので、flock した後を begin でくくって、ensure で確実に close させるほ
> うがいいように思います。
>
> # 見やすさのために、-b で diff をとってタブを 2 スペースに置換しています。
>
> diff -u -b -r1.28 defaultio.rb
> --- tdiary/defaultio.rb 17 Jul 2004 17:29:19 -0000 1.28
> +++ tdiary/defaultio.rb 16 Dec 2004 13:47:42 -0000
> @@ -128,6 +128,7 @@
> end
> fh.flock( File::LOCK_EX )
>
> + begin
> cache = @tdiary.restore_parser_cache( date, 'defaultio' )
> unless cache then
> restore( fh, diaries )
> @@ -144,7 +145,6 @@
> @tdiary.store_parser_cache( date, 'defaultio', diaries )
> end
>
> - fh.close
> if diaries.empty?
> File::delete( @dfile )
> # also delete parser cache
> @@ -152,6 +152,9 @@
> end
> # delete dispensable data directory
> Dir.delete( dir ) if Dir.new( dir ).entries.reject {|f| "." == f or ".." == f}.empty?
> + ensure
> + fh.close
> + end
> end
> end
>
> ただ、それはそれとして、yyyymm.td2 ファイルを、日記・コメント・リファラの
> 三つのトランザクション全体を通して排他ロックしているのもちょっと抵抗があ
> ります。大半のリクエストである閲覧時は、日記・コメントは読み込みで、リファ
> ラだけが書き込みです。また、日記・コメント・リファラのトランザクションは
> それぞれ独立していても問題ないと思います。
>
> というわけで、日記・コメント・リファラのそれぞれのアクセスに対して、読み
> 込み時は共有ロック、書き込み時は排他ロックを個別に行うようにするパッチを
> 提案します。
>
> なお、第二 tDiary.Net ではこのパッチをあてた状態で既に 2 ヵ月半も安定稼働
> しています。:)
>
> diff -u -b -r1.28 defaultio.rb
> --- tdiary/defaultio.rb 17 Jul 2004 17:29:19 -0000 1.28
> +++ tdiary/defaultio.rb 16 Dec 2004 07:48:47 -0000
> @@ -28,6 +28,7 @@
> def restore_comment( file, diaries )
> begin
> File::open( file, 'r' ) do |fh|
> + fh.flock( File::LOCK_SH )
> while l = fh.gets( "\n.\n" )
> headers, body = TDiary::parse_tdiary( l )
> next unless body
> @@ -45,7 +46,8 @@
> end
>
> def store_comment( file, diaries )
> - fhc = File::open( file, 'w' )
> + File::open( file, 'w' ) do |fhc|
> + fhc.flock( File::LOCK_EX )
> fhc.puts( TDIARY_MAGIC )
> diaries.each do |date,diary|
> diary.each_comment( diary.count_comments( true ) ) do |com|
> @@ -59,7 +61,7 @@
> fhc.puts( '.' )
> end
> end
> - fhc.close
> + end
> end
> end
>
> @@ -71,6 +73,7 @@
> def restore_referer( file, diaries )
> begin
> File::open( file, 'r' ) do |fh|
> + fh.flock( File::LOCK_SH )
> while l = fh.gets( "\n.\n" )
> headers, body = TDiary::parse_tdiary( l )
> next unless body
> @@ -86,7 +89,8 @@
> end
>
> def store_referer( file, diaries )
> - fhr = File::open( file, 'w' )
> + File::open( file, 'w' ) do |fhr|
> + fhr.flock( File::LOCK_EX )
> fhr.puts( TDiary::TDIARY_MAGIC )
> diaries.each do |date,diary|
> fhr.puts( "Date: #{date}" )
> @@ -96,7 +100,7 @@
> end
> fhr.puts( '.' )
> end
> - fhr.close
> + end
> end
> end
>
> @@ -126,7 +130,6 @@
> rescue
> fh = File::open( @dfile, 'w+' )
> end
> - fh.flock( File::LOCK_EX )
>
> cache = @tdiary.restore_parser_cache( date, 'defaultio' )
> unless cache then
> @@ -144,7 +147,6 @@
> @tdiary.store_parser_cache( date, 'defaultio', diaries )
> end
>
> - fh.close
> if diaries.empty?
> File::delete( @dfile )
> # also delete parser cache
> @@ -152,6 +154,8 @@
> end
> # delete dispensable data directory
> Dir.delete( dir ) if Dir.new( dir ).entries.reject {|f| "." == f or ".." == f}.empty?
> + ensure
> + fh.close
> end
> end
>
> @@ -175,6 +179,8 @@
>
> private
> def restore( fh, diaries )
> + fh.flock( File::LOCK_SH )
> + begin
> fh.seek( 0 )
> begin
> major, minor = fh.gets.split( /\./, 2 )
> @@ -198,9 +204,14 @@
> raise
> end
> end
> + ensure
> + fh.flock( File::LOCK_UN )
> + end
> end
>
> def store( fh, diaries )
> + fh.flock( File::LOCK_EX )
> + begin
> fh.seek( 0 )
> fh.puts( TDIARY_MAGIC )
> diaries.each do |date,diary|
> @@ -215,6 +226,9 @@
> fh.puts( '.' )
> end
> fh.truncate( fh.tell )
> + ensure
> + fh.flock( File::LOCK_UN )
> + end
> end
> end
> end
--
かずひこ <http://wiki.fdiary.net/kazuhiko/>
★シャア「名字が付いてない」
☆一兵卒「あんなの飾りです。偉い人にはそれが分からんのです」
|