From 523195d6496bfd596afcc36f95654dd88edd05ee Mon Sep 17 00:00:00 2001 From: Leeingnyo Date: Tue, 14 Sep 2021 22:37:30 +0900 Subject: [PATCH] Define ExamineContext, apply it when scanning --- src/library/library.cr | 12 ++++++++++-- src/library/title.cr | 17 +++++++++++------ src/library/types.cr | 7 +++++++ src/util/signature.cr | 4 ++-- 4 files changed, 30 insertions(+), 10 deletions(-) diff --git a/src/library/library.cr b/src/library/library.cr index 6d69563..582440a 100644 --- a/src/library/library.cr +++ b/src/library/library.cr @@ -142,20 +142,28 @@ class Library storage = Storage.new auto_close: false + examine_context : ExamineContext = { + file_count: 0, + cached_contents_signature: {} of String => String, + deleted_title_ids: [] of String, + deleted_entry_ids: [] of String + } + @title_ids.select! do |title_id| title = @title_hash[title_id] - existence = title.examine + existence = title.examine examine_context @title_hash.delete title_id unless existence existence end remained_title_dirs = @title_ids.map { |id| title_hash[id].dir } + cache = examine_context["cached_contents_signature"] (Dir.entries @dir) .select { |fn| !fn.starts_with? "." } .map { |fn| File.join @dir, fn } .select { |path| !(remained_title_dirs.includes? path) } .select { |path| File.directory? path } - .map { |path| Title.new path, "" } + .map { |path| Title.new path, "", cache } .select { |title| !(title.entries.empty? && title.titles.empty?) } .sort! { |a, b| a.title <=> b.title } .each do |title| diff --git a/src/library/title.cr b/src/library/title.cr index def2b66..12c565f 100644 --- a/src/library/title.cr +++ b/src/library/title.cr @@ -19,7 +19,7 @@ class Title @[YAML::Field(ignore: true)] @cached_cover_url : String? - def initialize(@dir : String, @parent_id) + def initialize(@dir : String, @parent_id, cache : Hash(String, String)?) storage = Storage.default @signature = Dir.signature dir id = storage.get_title_id dir, signature @@ -32,7 +32,7 @@ class Title }) end @id = id - @contents_signature = Dir.contents_signature dir + @contents_signature = Dir.contents_signature dir, cache @title = File.basename dir @encoded_title = URI.encode @title @title_ids = [] of String @@ -70,9 +70,14 @@ class Title end end - def examine(cache = {} of String => String) : Bool + def self.new(dir : String, parent_id) + new dir, parent_id, nil + end + + def examine(context : ExamineContext) : Bool return false unless Dir.exists? @dir # No title, Remove this - contents_signature = Dir.contents_signature @dir, cache + contents_signature = Dir.contents_signature @dir, + context["cached_contents_signature"] # Not changed. Reuse this return true if @contents_signature == contents_signature @@ -95,7 +100,7 @@ class Title previous_titles_size = @title_ids.size @title_ids.select! do |title_id| title = Library.default.get_title! title_id - existence = title.examine cache + existence = title.examine context Library.default.title_hash.delete title_id unless existence existence end @@ -115,7 +120,7 @@ class Title path = File.join dir, fn if File.directory? path next if remained_title_dirs.includes? path - title = Title.new path, @id + title = Title.new path, @id, context["cached_contents_signature"] next if title.entries.size == 0 && title.titles.size == 0 Library.default.title_hash[title.id] = title @title_ids << title.id diff --git a/src/library/types.cr b/src/library/types.cr index 0545184..eb87545 100644 --- a/src/library/types.cr +++ b/src/library/types.cr @@ -133,3 +133,10 @@ class TitleInfo LRUCache.set generate_cache_entry key, self.to_json end end + +alias ExamineContext = NamedTuple( + file_count: Int32, + cached_contents_signature: Hash(String, String), + deleted_title_ids: Array(String), + deleted_entry_ids: Array(String) +) diff --git a/src/util/signature.cr b/src/util/signature.cr index 190a4a6..c4104fe 100644 --- a/src/util/signature.cr +++ b/src/util/signature.cr @@ -55,7 +55,7 @@ class Dir # - When a file added, moved, removed, renamed (including which in nested # directories) def self.contents_signature(dirname, cache = {} of String => String) : String - return cache[dirname] if cache[dirname]? + return cache[dirname] if !cache.nil? && cache[dirname]? signatures = [] of String self.open dirname do |dir| dir.entries.sort.each do |fn| @@ -71,7 +71,7 @@ class Dir end end hash = Digest::SHA1.hexdigest(signatures.join) - cache[dirname] = hash + cache[dirname] = hash unless cache.nil? hash end end