/ 最近 .rdf 追記 編集 設定 本棚

log[20071225] PStore, category.rb: 日記に変更があるたびにカテゴリキッシュファイルが一斉に更新されるのをなんとかする



20071225() なんでもかんで「相性で片付けて原因究明を怠る(一部の)風潮が嫌い

[Ruby][tDiary] PStore, category.rb: 日記に変更があるたびにカテゴリキッシュファイルが一斉に更新されるのをなんとかする

日記を更新するとTDiary::Config#data_path/category/ 以下のカテゴリごとに作られるキッシュファイルがずいぶんたくさん更新される全部ではないが半分近い 21のファイルが更新されていた日記の内容はというと一つのカテゴリしか使っていない

どこのコドが無駄にファイルを更新しているのかと絞っていくとcategory.rbの中の Category::Cache#replace_sectionsだとわかったではこの replace_sectionsが悪いのかというとそうではないreplace_sectionsの中の

PStore.new(cache_file(c)).transaction do |db|
end

に囲まれた部分をすべてコメトアトしても 21のキッシュファイルが一斉に更新されたのだから一部の PStoreァイルは開いて閉じるだけで常に更新されるのだとしか考えられない

PStoretransactionの前後で Marshal::dump の戻り値のサイズと MD5が変化したかどうかを見て変更があったかどうかを判断しァイルに書き込みをするかしないかを決めているMarshal::load/dump が対称ではないのだろ(そもそも HashMarshal::dumpした結果が一定だと仮定してよいのだろうか*)

原因が何であるにせよサーバーの pstore.rbを書き換えるわけにもいかないのでtDiarycategory.rbに対策を施した

 PStore#transaction(true)を使う

読み出し専用であることが予めわかっている PStore#transactionはすべて trueを引数にして(readonly=trueの意)呼び出す。実はそういう transactionはすべて PStore#abortで終わっているのでこの対策は必要ないのだがァイルを排他ロックすることと MD5を計算する手間が省けるので一応

 PStore#abortを使う

肝心の Category::Cache#replace_sectionstransactionの開始前に変更があるのかどうかがわからないので PStore#transaction(true)は使えない日付の削除が空振りに終わったときにだけ PStore#abortを呼ぶことにするこれで必要最低限のキッシュファイルだけが更新されるようになった

	#
	# cache each section of diary
	# used in update_proc
	#
	def replace_sections(diary)
		return if diary.nil? or !diary.categorizable?

		categorized = categorize_diary(diary)
		categories = restore_categories
		deleted = []
		ymd = diary.date.strftime('%Y%m%d')

		categories.each do |c|
			PStore.new(cache_file(c)).transaction do |db|
				db['category'] = {} unless db.root?('category')
				if categorized[c] and diary.visible?
					db['category'].update(categorized[c])
				else
					# diary is invisible or sections of this category is deleted
					db.abort unless db['category'].delete(ymd)
					deleted << c if db['category'].empty?
				end
			end
		end

		if !deleted.empty?
			deleted.each do |c|
				File.unlink(cache_file(c))
			end
			replace_categories(categories - deleted)
		end
	end

* 追記:最近の Ruby(1.8.7だか 1.9.0)Hashkeyの順序を保存しているみたいだけど