diff --git a/lib/filewatch/tail.rb b/lib/filewatch/tail.rb index 6c27bfe..20bf1bb 100644 --- a/lib/filewatch/tail.rb +++ b/lib/filewatch/tail.rb @@ -42,7 +42,8 @@ def initialize(opts={}) :stat_interval => 1, :discover_interval => 5, :exclude => [], - :start_new_files_at => :end + :start_new_files_at => :end, + :follow_only_path => false }.merge(opts) if !@opts.include?(:sincedb_path) @opts[:sincedb_path] = File.join(ENV["HOME"], ".sincedb") if ENV.include?("HOME") @@ -128,13 +129,29 @@ def _open_file(path, event) stat = File::Stat.new(path) - if @iswindows - fileId = Winhelper.GetWindowsUniqueFileIdentifier(path) - inode = [fileId, stat.dev_major, stat.dev_minor] + if @opts[:follow_only_path] + # In cases where files are rsynced to the consuming server, inodes will change when + # updated files overwrite original ones, resulting in inode changes. In order to + # avoid having the sincedb.member check from failing in this scenario, we'll + # construct the inode key using the path which will be 'stable' + # + # Because spaces and carriage returns are valid characters in linux paths, we have + # to take precautions to avoid having them show up in the .sincedb where they would + # derail any parsing that occurs in _sincedb_open. Since NULL (\0) is NOT a + # valid path character in LINUX (one of the few), we'll replace these troublesome + # characters with 'encodings' that won't be encountered in a normal path but will + # be handled properly by __sincedb_open + inode = [path.gsub(/ /, "\0\0").gsub(/\n/, "\0\1"), stat.dev_major, stat.dev_minor] else - inode = [stat.ino.to_s, stat.dev_major, stat.dev_minor] + if @iswindows + fileId = Winhelper.GetWindowsUniqueFileIdentifier(path) + inode = [fileId, stat.dev_major, stat.dev_minor] + else + inode = [stat.ino.to_s, stat.dev_major, stat.dev_minor] end - + end + + @statcache[path] = inode if @sincedb.member?(inode)