From 1176e9221a3d87f77f2d452a00ad38287a72c8e8 Mon Sep 17 00:00:00 2001 From: Benoit Brayer Date: Thu, 8 Jan 2015 13:34:52 +0100 Subject: [PATCH 1/4] adding required modifications in watch.rb and tail.rb file for hpux implementation of filewatch gem AND creating hpuxhelder.rb (not yet implemented) file based on windowsHelper.rb file --- lib/filewatch/hpuxhelper.rb | 54 +++++++++++++++++++++++++++++++++++++ lib/filewatch/tail.rb | 12 ++++++--- lib/filewatch/watch.rb | 11 +++++++- 3 files changed, 73 insertions(+), 4 deletions(-) create mode 100644 lib/filewatch/hpuxhelper.rb diff --git a/lib/filewatch/hpuxhelper.rb b/lib/filewatch/hpuxhelper.rb new file mode 100644 index 0000000..9e9ab6e --- /dev/null +++ b/lib/filewatch/hpuxhelper.rb @@ -0,0 +1,54 @@ +require "ffi" + +module Winhelper + extend FFI::Library + ffi_lib FFI::Library::LIBC + + # définition de type FileTime + class FileTime < FFI::Struct + layout :lowDateTime, :uint, + :highDateTime, :uint + end + + # définition de type FileInformation + class FileInformation < FFI::Struct + def initialize() + createTime = FileTime.new + lastAccessTime = FileTime.new + lastWriteTime = FileTime.new + end + + layout :fileAttributes, :uint, #DWORD dwFileAttributes; + :createTime, FileTime, #FILETIME ftCreationTime; + :lastAccessTime, FileTime, #FILETIME ftLastAccessTime; + :lastWriteTime, FileTime, #FILETIME ftLastWriteTime; + :volumeSerialNumber, :uint, #DWORD dwVolumeSerialNumber; + :fileSizeHigh, :uint, #DWORD nFileSizeHigh; + :fileSizeLow, :uint, #DWORD nFileSizeLow; + :numberOfLinks, :uint, #DWORD nNumberOfLinks; + :fileIndexHigh, :uint, #DWORD nFileIndexHigh; + :fileIndexLow, :uint #DWORD nFileIndexLow; + end + + + attach_function :GetOpenFileHandle, :CreateFileA, [:pointer, :uint, :uint, :pointer, :uint, :uint, :pointer], :pointer + + attach_function :GetFileInformationByHandle, [:pointer, :pointer], :int + + attach_function :CloseHandle, [:pointer], :int + + + def self.GetHpUxUniqueFileIdentifier(path) + handle = GetOpenFileHandle(path, 0, 7, nil, 3, 128, nil) + fileInfo = Winhelper::FileInformation.new + success = GetFileInformationByHandle(handle, fileInfo) + CloseHandle(handle) + if success == 1 + return "#{fileInfo[:volumeSerialNumber]}-#{fileInfo[:fileIndexLow]}-#{fileInfo[:fileIndexHigh]}" + else + #p "cannot retrieve file information, returning path" + return path; + end + end +end + diff --git a/lib/filewatch/tail.rb b/lib/filewatch/tail.rb index 6c27bfe..f9c9d1c 100644 --- a/lib/filewatch/tail.rb +++ b/lib/filewatch/tail.rb @@ -2,6 +2,8 @@ require "filewatch/watch" if RbConfig::CONFIG['host_os'] =~ /mswin|mingw|cygwin/ require "filewatch/winhelper" +elsif RbConfig::CONFIG['host_os'] == "HP-UX" + require "filewatch/hpuxhelper" end require "logger" require "rbconfig" @@ -22,7 +24,8 @@ class NoSinceDBPathGiven < StandardError; end public def initialize(opts={}) @iswindows = ((RbConfig::CONFIG['host_os'] =~ /mswin|mingw|cygwin/) != nil) - + @ishpux = ((RbConfig::CONFIG['host_os'] == "HP-UX") != false) + if opts[:logger] @logger = opts[:logger] else @@ -106,7 +109,7 @@ def subscribe(&block) def _open_file(path, event) @logger.debug("_open_file: #{path}: opening") begin - if @iswindows && defined? JRUBY_VERSION + if (@iswindows || @ishpux) && defined? JRUBY_VERSION @files[path] = Java::RubyFileExt::getRubyFile(path) else @files[path] = File.open(path) @@ -131,9 +134,12 @@ def _open_file(path, event) if @iswindows fileId = Winhelper.GetWindowsUniqueFileIdentifier(path) inode = [fileId, stat.dev_major, stat.dev_minor] + elsif @ishpux + fileInformations = Hpuxhelper.GetHpuxFileInformations(path) + inode = [fileInformations.uid, fileInformations.dev_major, fileInformations.dev_minor] else inode = [stat.ino.to_s, stat.dev_major, stat.dev_minor] - end + end @statcache[path] = inode diff --git a/lib/filewatch/watch.rb b/lib/filewatch/watch.rb index 8715130..ec4316a 100644 --- a/lib/filewatch/watch.rb +++ b/lib/filewatch/watch.rb @@ -1,6 +1,8 @@ require "logger" if RbConfig::CONFIG['host_os'] =~ /mswin|mingw|cygwin/ require "filewatch/winhelper" +elsif RbConfig::CONFIG['host_os'] == "HP-UX" + require "filewatch/hpuxhelper" end module FileWatch @@ -10,6 +12,7 @@ class Watch public def initialize(opts={}) @iswindows = ((RbConfig::CONFIG['host_os'] =~ /mswin|mingw|cygwin/) != nil) + @ishpux = ((RbConfig::CONFIG['host_os'] == "HP-UX") != false) if opts[:logger] @logger = opts[:logger] else @@ -75,6 +78,9 @@ def each(&block) if @iswindows fileId = Winhelper.GetWindowsUniqueFileIdentifier(path) inode = [fileId, stat.dev_major, stat.dev_minor] + elsif @ishpux + fileInformations = Hpuxhelper.GetHpuxFileInformations(path) + inode = [fileInformations.uid, fileInformations.dev_major, fileInformations.dev_minor] else inode = [stat.ino.to_s, stat.dev_major, stat.dev_minor] end @@ -153,9 +159,12 @@ def _discover_file(path, initial=false) :create_sent => false, } - if @iswindows + if @iswindows fileId = Winhelper.GetWindowsUniqueFileIdentifier(path) @files[file][:inode] = [fileId, stat.dev_major, stat.dev_minor] + elsif @ishpux + fileInformations = Hpuxhelper.GetHpuxFileInformations(path) + @files[file][:inode] = [fileInformations.uid, fileInformations.dev_major, fileInformations.dev_minor] else @files[file][:inode] = [stat.ino.to_s, stat.dev_major, stat.dev_minor] end From 35bfdb8995d4e90ae2f35ee11ae23c60bf4e5515 Mon Sep 17 00:00:00 2001 From: Benoit Brayer Date: Thu, 8 Jan 2015 13:34:52 +0100 Subject: [PATCH 2/4] HP-UX support : Workaround without using ruby FFI library --- lib/filewatch/hpuxhelper.rb | 54 ++++++++++++++++++++++++++++++++ lib/filewatch/tail.rb | 22 ++++++++----- lib/filewatch/watch.rb | 41 ++++++++++++++++++------ lib/java/JRubyFileExtension.jar | Bin 0 -> 1281 bytes lib/java/RubyFileExt.java | 50 +++++++++++++++++++++++++++++ 5 files changed, 150 insertions(+), 17 deletions(-) create mode 100644 lib/filewatch/hpuxhelper.rb create mode 100644 lib/java/JRubyFileExtension.jar create mode 100644 lib/java/RubyFileExt.java diff --git a/lib/filewatch/hpuxhelper.rb b/lib/filewatch/hpuxhelper.rb new file mode 100644 index 0000000..9e9ab6e --- /dev/null +++ b/lib/filewatch/hpuxhelper.rb @@ -0,0 +1,54 @@ +require "ffi" + +module Winhelper + extend FFI::Library + ffi_lib FFI::Library::LIBC + + # définition de type FileTime + class FileTime < FFI::Struct + layout :lowDateTime, :uint, + :highDateTime, :uint + end + + # définition de type FileInformation + class FileInformation < FFI::Struct + def initialize() + createTime = FileTime.new + lastAccessTime = FileTime.new + lastWriteTime = FileTime.new + end + + layout :fileAttributes, :uint, #DWORD dwFileAttributes; + :createTime, FileTime, #FILETIME ftCreationTime; + :lastAccessTime, FileTime, #FILETIME ftLastAccessTime; + :lastWriteTime, FileTime, #FILETIME ftLastWriteTime; + :volumeSerialNumber, :uint, #DWORD dwVolumeSerialNumber; + :fileSizeHigh, :uint, #DWORD nFileSizeHigh; + :fileSizeLow, :uint, #DWORD nFileSizeLow; + :numberOfLinks, :uint, #DWORD nNumberOfLinks; + :fileIndexHigh, :uint, #DWORD nFileIndexHigh; + :fileIndexLow, :uint #DWORD nFileIndexLow; + end + + + attach_function :GetOpenFileHandle, :CreateFileA, [:pointer, :uint, :uint, :pointer, :uint, :uint, :pointer], :pointer + + attach_function :GetFileInformationByHandle, [:pointer, :pointer], :int + + attach_function :CloseHandle, [:pointer], :int + + + def self.GetHpUxUniqueFileIdentifier(path) + handle = GetOpenFileHandle(path, 0, 7, nil, 3, 128, nil) + fileInfo = Winhelper::FileInformation.new + success = GetFileInformationByHandle(handle, fileInfo) + CloseHandle(handle) + if success == 1 + return "#{fileInfo[:volumeSerialNumber]}-#{fileInfo[:fileIndexLow]}-#{fileInfo[:fileIndexHigh]}" + else + #p "cannot retrieve file information, returning path" + return path; + end + end +end + diff --git a/lib/filewatch/tail.rb b/lib/filewatch/tail.rb index 6c27bfe..9fc129a 100644 --- a/lib/filewatch/tail.rb +++ b/lib/filewatch/tail.rb @@ -7,7 +7,7 @@ require "rbconfig" include Java if defined? JRUBY_VERSION -require "JRubyFileExtension.jar" if defined? JRUBY_VERSION +require "java/JRubyFileExtension.jar" if defined? JRUBY_VERSION module FileWatch class Tail @@ -22,6 +22,7 @@ class NoSinceDBPathGiven < StandardError; end public def initialize(opts={}) @iswindows = ((RbConfig::CONFIG['host_os'] =~ /mswin|mingw|cygwin/) != nil) + @ishpux = ((RbConfig::CONFIG['host_os'] == "HP-UX") != false) if opts[:logger] @logger = opts[:logger] @@ -106,7 +107,7 @@ def subscribe(&block) def _open_file(path, event) @logger.debug("_open_file: #{path}: opening") begin - if @iswindows && defined? JRUBY_VERSION + if (@iswindows || @ishpux) && defined? JRUBY_VERSION @files[path] = Java::RubyFileExt::getRubyFile(path) else @files[path] = File.open(path) @@ -126,15 +127,22 @@ def _open_file(path, event) return false end - stat = File::Stat.new(path) - + if @ishpux + # do no call Stat method on file + # (Ruby ffi does not support HP-UX systems) + else + stat = File::Stat.new(path) + end + if @iswindows fileId = Winhelper.GetWindowsUniqueFileIdentifier(path) inode = [fileId, stat.dev_major, stat.dev_minor] + elsif @ishpux + inode = [path, 0, 0] else inode = [stat.ino.to_s, stat.dev_major, stat.dev_minor] - end - + end + @statcache[path] = inode if @sincedb.member?(inode) @@ -153,7 +161,7 @@ def _open_file(path, event) @logger.debug("#{path}: initial create, no sincedb, seeking to beginning of file") @files[path].sysseek(0, IO::SEEK_SET) @sincedb[inode] = 0 - else + else # seek to end @logger.debug("#{path}: initial create, no sincedb, seeking to end #{stat.size}") @files[path].sysseek(stat.size, IO::SEEK_SET) diff --git a/lib/filewatch/watch.rb b/lib/filewatch/watch.rb index 8715130..3337921 100644 --- a/lib/filewatch/watch.rb +++ b/lib/filewatch/watch.rb @@ -10,6 +10,7 @@ class Watch public def initialize(opts={}) @iswindows = ((RbConfig::CONFIG['host_os'] =~ /mswin|mingw|cygwin/) != nil) + @ishpux = ((RbConfig::CONFIG['host_os'] == "HP-UX") != false) if opts[:logger] @logger = opts[:logger] else @@ -63,7 +64,12 @@ def each(&block) @files.keys.each do |path| begin + if @ishpux + # do no call Stat method on file + # (Ruby ffi does not support HP-UX systems) + else stat = File::Stat.new(path) + end rescue Errno::ENOENT # file has gone away or we can't read it anymore. @files.delete(path) @@ -75,10 +81,12 @@ def each(&block) if @iswindows fileId = Winhelper.GetWindowsUniqueFileIdentifier(path) inode = [fileId, stat.dev_major, stat.dev_minor] + elsif @ishpux + inode = [path, 0, 0] else inode = [stat.ino.to_s, stat.dev_major, stat.dev_minor] end - + if inode != @files[path][:inode] @logger.debug("#{path}: old inode was #{@files[path][:inode].inspect}, new is #{inode.inspect}") yield(:delete, path) @@ -146,20 +154,33 @@ def _discover_file(path, initial=false) end next if skip - stat = File::Stat.new(file) - @files[file] = { - :size => 0, - :inode => [stat.ino, stat.dev_major, stat.dev_minor], - :create_sent => false, - } - - if @iswindows + if @ishpux + # do no call Stat method on file + # (Ruby ffi does not support HP-UX systems) + @files[file] = { + :size => 0, + :inode => [path, 0, 0], + :create_sent => false, + } + else + stat = File::Stat.new(file) + @files[file] = { + :size => 0, + :inode => [stat.ino, stat.dev_major, stat.dev_minor], + :create_sent => false, + } + end + + + if @iswindows fileId = Winhelper.GetWindowsUniqueFileIdentifier(path) @files[file][:inode] = [fileId, stat.dev_major, stat.dev_minor] + elsif @ishpux + @files[file][:inode] = [path, 0, 0] else @files[file][:inode] = [stat.ino.to_s, stat.dev_major, stat.dev_minor] end - + if initial @files[file][:initial] = true end diff --git a/lib/java/JRubyFileExtension.jar b/lib/java/JRubyFileExtension.jar new file mode 100644 index 0000000000000000000000000000000000000000..4d4830064f5d1c718bae1b85c99f7f8299415d32 GIT binary patch literal 1281 zcmWIWW@Zs#;Nak3P^miY#DD}u7+4s5T|*poJ^kGDeI5Ng-CTo1^nBg^onm14?0e?4 zkGHPgMP6@Rt#fD2Zw@lJV*KFgC*Lz?E|;G3)Y01(bV5tZca_iSGoHR{H9XHUYd(7V z=qVFJfHymb;akTQrX713NN2vinSnpEkQnUm^T zQKFZelUQ8b8X6lc>?vaFdu&Tjpukj7#-sgLRb0~kmh~=@2)Nj|fphjM-Fa4?+|InV zD`$2t?f<9z)p5nvFYG@S>*Swj5o%lD8M^%a+sn`I?E7B!{CEHV{fs+WXLUZ_v9di{ zE$=bk@mS&S1@j-jceHW1c*NP}(G1g%68=6sNqvts-8&WkUI_HFI6dL)t$F+Na(})3 zWxd+T*)VZ>j3CR=nBIdLmA)qpQmno7wr_uRDPFX6x{dO->jHVcKl-*=`zhZkU}}53 zO|A0Tj-rRT5h)MqqFc|2F}6)U#M2yYBr;Lq@XURM26KGb?(lxNv5Tkts>Hgqx4s|U zBGv`G4m15CyEX2N>NmY;4H zc#3hvLHi?o3+BW-r67Xect21o!=Ip{_1;E;rmLD{wHFmt2@(nTw~qte7yJC zRq2OTXJ-}M-o$RX%|1>yyjHxWs5>h$=<(Up*B8B=biu_eUA|3M&Z4}$caoQhcA&o4 z?=SD7_Lsf8Ju~?C-m3vCmVKCgS0q?co4fck&-6F<9Xs4V>B>WzhxEwBITkNtZz5apD zLesYq?Pb$)_S(;#fA5&Xq_0wa3ep?Dv=ABUoP*JHi&LHYIN!VfK8%nS^d*g*M}kx7IBQD7kFWl({E3gGz{t@r?$!o`3) t-y=+^2QuNNAX^S92ap{GDhCi?8IXxlDg=150)4>1zzl?YfV4i?xd0!a0}ucJ literal 0 HcmV?d00001 diff --git a/lib/java/RubyFileExt.java b/lib/java/RubyFileExt.java new file mode 100644 index 0000000..10eb534 --- /dev/null +++ b/lib/java/RubyFileExt.java @@ -0,0 +1,50 @@ +/** + * Created with IntelliJ IDEA. + * User: efrey + * Date: 6/11/13 + * Time: 11:00 AM + * To change this template use File | Settings | File Templates. + * + * http://bugs.sun.com/view_bug.do?bug_id=6357433 + * + * + */ + +import org.jruby.*; +import org.jruby.anno.JRubyClass; +import org.jruby.anno.JRubyMethod; +import org.jruby.util.io.ChannelDescriptor; +import org.jruby.util.io.ChannelStream; +import org.jruby.util.io.InvalidValueException; +import org.jruby.util.io.Stream; + +import java.io.File; +import java.io.IOException; +import java.io.InputStream; +import java.net.URI; +import java.nio.channels.Channel; +import java.nio.channels.FileChannel; +import java.nio.file.*; +import java.nio.file.spi.FileSystemProvider; +import java.util.Iterator; + +@JRubyClass(name="FileExt", parent="File", include="FileTest") +public class RubyFileExt extends RubyObject { + + public RubyFileExt(Ruby runtime, RubyClass metaClass) { + super(runtime, metaClass); + } + + public RubyFileExt(RubyClass metaClass) { + super(metaClass); + } + + @JRubyMethod + public static RubyIO getRubyFile(String path) throws IOException, InvalidValueException{ + Path p = FileSystems.getDefault().getPath(path); + OpenOption[] options = new OpenOption[1]; + options[0] = StandardOpenOption.READ; + Channel channel = FileChannel.open(p, options); + return new RubyIO(Ruby.getGlobalRuntime(), channel); + } +} From 57a8044bc1d610bebc7d7be357cb2660f95753ad Mon Sep 17 00:00:00 2001 From: Benoit Brayer Date: Mon, 12 Jan 2015 15:02:25 +0100 Subject: [PATCH 3/4] Cleaning everything and using inode and filesystem mount point as file unique identifier. Adding most hpux specific code inside the hpuxhelper.rb module. Signed-off-by: Benoit Brayer --- lib/filewatch/hpuxhelper.rb | 18 ++++ lib/filewatch/tail.rb | 206 ++++++++++++------------------------ lib/filewatch/watch.rb | 92 ++++++---------- 3 files changed, 120 insertions(+), 196 deletions(-) create mode 100644 lib/filewatch/hpuxhelper.rb diff --git a/lib/filewatch/hpuxhelper.rb b/lib/filewatch/hpuxhelper.rb new file mode 100644 index 0000000..6389751 --- /dev/null +++ b/lib/filewatch/hpuxhelper.rb @@ -0,0 +1,18 @@ +module Hpuxhelper + + def self.GetHpuxFileInode(path) + hpuxfileino = "" + IO.popen("ls -i #{path} | awk '{print $1}'").each do |line| + hpuxfileino = line.chomp + end + return hpuxfileino + end + + def self.GetHpuxFileFilesystemMountPoint(path) + hpuxfsname = "" + IO.popen("df -n #{path} | awk '{print $1}'").each do |line| + hpuxfsname = line.chomp + end + return hpuxfsname + end +end \ No newline at end of file diff --git a/lib/filewatch/tail.rb b/lib/filewatch/tail.rb index ebe0005..0fa1666 100644 --- a/lib/filewatch/tail.rb +++ b/lib/filewatch/tail.rb @@ -2,6 +2,8 @@ require "filewatch/watch" if RbConfig::CONFIG['host_os'] =~ /mswin|mingw|cygwin/ require "filewatch/winhelper" +elsif RbConfig::CONFIG['host_os'] == "HP-UX" + require "filewatch/hpuxhelper" end require "logger" require "rbconfig" @@ -127,80 +129,45 @@ def _open_file(path, event) return false end - if @ishpux - # do no call Stat method on file - # (Ruby ffi does not support HP-UX systems) - else - stat = File::Stat.new(path) - end + stat = File::Stat.new(path) if @iswindows fileId = Winhelper.GetWindowsUniqueFileIdentifier(path) inode = [fileId, stat.dev_major, stat.dev_minor] elsif @ishpux - inode = [path, 0, 0] + fileId = Hpuxhelper.GetHpuxFileInode(path) + filesystemMountPoint = Hpuxhelper.GetHpuxFileFilesystemMountPoint(path) + inode = [fileId, filesystemMountPoint, 0] else inode = [stat.ino.to_s, stat.dev_major, stat.dev_minor] end @statcache[path] = inode - if @ishpux - @hpuxfilesize - # Open file to get its size - f = File.open(path, mode="r") {|f| - @hpuxfilesize = f.stat.size - } - if @sincedb.member?(inode) - last_size = @sincedb[inode] - @logger.debug("#{path}: sincedb last value #{@sincedb[inode]}, cur size #{@hpuxfilesize}") - if last_size <= @hpuxfilesize - @logger.debug("#{path}: sincedb: seeking to #{last_size}") - @files[path].sysseek(last_size, IO::SEEK_SET) - else - @logger.debug("#{path}: last value size is greater than current value, starting over") - @sincedb[inode] = 0 - end - elsif event == :create_initial && @files[path] - if @opts[:start_new_files_at] == :beginning - @logger.debug("#{path}: initial create, no sincedb, seeking to beginning of file") - @files[path].sysseek(0, IO::SEEK_SET) - @sincedb[inode] = 0 - else - # seek to end - @logger.debug("#{path}: initial create, no sincedb, seeking to end #{@hpuxfilesize}") - @files[path].sysseek(@hpuxfilesize, IO::SEEK_SET) - @sincedb[inode] = @hpuxfilesize - end - else - @logger.debug("#{path}: staying at position 0, no sincedb") - end - else - if @sincedb.member?(inode) - last_size = @sincedb[inode] - @logger.debug("#{path}: sincedb last value #{@sincedb[inode]}, cur size #{stat.size}") - if last_size <= stat.size - @logger.debug("#{path}: sincedb: seeking to #{last_size}") - @files[path].sysseek(last_size, IO::SEEK_SET) - else - @logger.debug("#{path}: last value size is greater than current value, starting over") - @sincedb[inode] = 0 - end - elsif event == :create_initial && @files[path] - # TODO(sissel): Allow starting at beginning of the file. - if @opts[:start_new_files_at] == :beginning - @logger.debug("#{path}: initial create, no sincedb, seeking to beginning of file") - @files[path].sysseek(0, IO::SEEK_SET) - @sincedb[inode] = 0 - else - # seek to end - @logger.debug("#{path}: initial create, no sincedb, seeking to end #{stat.size}") - @files[path].sysseek(stat.size, IO::SEEK_SET) - @sincedb[inode] = stat.size - end - else - @logger.debug("#{path}: staying at position 0, no sincedb") - end + if @sincedb.member?(inode) + last_size = @sincedb[inode] + @logger.debug("#{path}: sincedb last value #{@sincedb[inode]}, cur size #{stat.size}") + if last_size <= stat.size + @logger.debug("#{path}: sincedb: seeking to #{last_size}") + @files[path].sysseek(last_size, IO::SEEK_SET) + else + @logger.debug("#{path}: last value size is greater than current value, starting over") + @sincedb[inode] = 0 + end + elsif event == :create_initial && @files[path] + # TODO(sissel): Allow starting at beginning of the file. + if @opts[:start_new_files_at] == :beginning + @logger.debug("#{path}: initial create, no sincedb, seeking to beginning of file") + @files[path].sysseek(0, IO::SEEK_SET) + @sincedb[inode] = 0 + else + # seek to end + @logger.debug("#{path}: initial create, no sincedb, seeking to end #{stat.size}") + @files[path].sysseek(stat.size, IO::SEEK_SET) + @sincedb[inode] = stat.size + end + else + @logger.debug("#{path}: staying at position 0, no sincedb") end return true @@ -242,86 +209,47 @@ def sincedb_write(reason=nil) _sincedb_write end - if @ishpux - private - def _sincedb_open - path = @opts[:sincedb_path] - begin - db = File.open(path, mode="r") {|db| - db.each do |line| - ino, dev_major, dev_minor, pos = line.split(" ", 4) - inode = [ino, dev_major.to_i, dev_minor.to_i] - @logger.debug("_sincedb_open: setting #{inode.inspect} to #{pos.to_i}") - @sincedb[inode] = pos.to_i - end - } - rescue - @logger.debug("_sincedb_open: #{path}: #{$!}") - return - end - end # def _sincedb_open - else - private - def _sincedb_open - path = @opts[:sincedb_path] - begin - db = File.open(path) - rescue - @logger.debug("_sincedb_open: #{path}: #{$!}") - return - end + private + def _sincedb_open + path = @opts[:sincedb_path] + begin + db = File.open(path) + rescue + @logger.debug("_sincedb_open: #{path}: #{$!}") + return + end - @logger.debug("_sincedb_open: reading from #{path}") - db.each do |line| - ino, dev_major, dev_minor, pos = line.split(" ", 4) - inode = [ino, dev_major.to_i, dev_minor.to_i] - @logger.debug("_sincedb_open: setting #{inode.inspect} to #{pos.to_i}") - @sincedb[inode] = pos.to_i - end - end # def _sincedb_open - end + @logger.debug("_sincedb_open: reading from #{path}") + db.each do |line| + ino, dev_major, dev_minor, pos = line.split(" ", 4) + inode = [ino, dev_major.to_i, dev_minor.to_i] + @logger.debug("_sincedb_open: setting #{inode.inspect} to #{pos.to_i}") + @sincedb[inode] = pos.to_i + end + end # def _sincedb_open - if @ishpux - private - def _sincedb_write - path = @opts[:sincedb_path] - tmp = "#{path}.new" - begin - db = File.open(path, mode="w") {|db| - @sincedb.each do |inode, pos| - db.puts([inode, pos].flatten.join(" ")) - end - db.rename(tmp,path) - } - rescue => e - @logger.warn("_sincedb_write failed: #{tmp}: #{e}") - return - end - end # def _sincedb_write - else - private - def _sincedb_write - path = @opts[:sincedb_path] - tmp = "#{path}.new" - begin - db = File.open(tmp, "w") - rescue => e - @logger.warn("_sincedb_write failed: #{tmp}: #{e}") - return - end + private + def _sincedb_write + path = @opts[:sincedb_path] + tmp = "#{path}.new" + begin + db = File.open(tmp, "w") + rescue => e + @logger.warn("_sincedb_write failed: #{tmp}: #{e}") + return + end - @sincedb.each do |inode, pos| - db.puts([inode, pos].flatten.join(" ")) - end - db.close + @sincedb.each do |inode, pos| + db.puts([inode, pos].flatten.join(" ")) + end + db.close - begin - File.rename(tmp, path) - rescue => e - @logger.warn("_sincedb_write rename/sync failed: #{tmp} -> #{path}: #{e}") - end - end # def _sincedb_write - end + begin + File.rename(tmp, path) + rescue => e + @logger.warn("_sincedb_write rename/sync failed: #{tmp} -> #{path}: #{e}") + end + end # def _sincedb_write public def quit diff --git a/lib/filewatch/watch.rb b/lib/filewatch/watch.rb index 032f63b..d735252 100644 --- a/lib/filewatch/watch.rb +++ b/lib/filewatch/watch.rb @@ -1,6 +1,8 @@ require "logger" if RbConfig::CONFIG['host_os'] =~ /mswin|mingw|cygwin/ require "filewatch/winhelper" +elsif RbConfig::CONFIG['host_os'] == "HP-UX" + require "filewatch/hpuxhelper" end module FileWatch @@ -64,12 +66,7 @@ def each(&block) @files.keys.each do |path| begin - if @ishpux - # do no call Stat method on file - # (Ruby ffi does not support HP-UX systems) - else stat = File::Stat.new(path) - end rescue Errno::ENOENT # file has gone away or we can't read it anymore. @files.delete(path) @@ -82,43 +79,25 @@ def each(&block) fileId = Winhelper.GetWindowsUniqueFileIdentifier(path) inode = [fileId, stat.dev_major, stat.dev_minor] elsif @ishpux - inode = [path, 0, 0] + fileId = Hpuxhelper.GetHpuxFileInode(path) + filesystemMountPoint = Hpuxhelper.GetHpuxFileFilesystemMountPoint(path) + inode = [fileId, filesystemMountPoint, 0] else inode = [stat.ino.to_s, stat.dev_major, stat.dev_minor] end - if @ishpux - @hpuxfilesize - # Open file to get its size - f = File.open(path, mode="r") {|f| - @hpuxfilesize = f.stat.size - } - if inode != @files[path][:inode] - @logger.debug("#{path}: old inode was #{@files[path][:inode].inspect}, new is #{inode.inspect}") - yield(:delete, path) - yield(:create, path) - elsif @hpuxfilesize < @files[path][:size] - @logger.debug("#{path}: file rolled, new size is #{@hpuxfilesize}, old size #{@files[path][:size]}") - yield(:delete, path) - yield(:create, path) - elsif @hpuxfilesize > @files[path][:size] - @logger.debug("#{path}: file grew, old size #{@files[path][:size]}, new size #{@hpuxfilesize}") - yield(:modify, path) - end - else - if inode != @files[path][:inode] - @logger.debug("#{path}: old inode was #{@files[path][:inode].inspect}, new is #{inode.inspect}") - yield(:delete, path) - yield(:create, path) - elsif stat.size < @files[path][:size] - @logger.debug("#{path}: file rolled, new size is #{stat.size}, old size #{@files[path][:size]}") - yield(:delete, path) - yield(:create, path) - elsif stat.size > @files[path][:size] - @logger.debug("#{path}: file grew, old size #{@files[path][:size]}, new size #{stat.size}") - yield(:modify, path) - end - end + if inode != @files[path][:inode] + @logger.debug("#{path}: old inode was #{@files[path][:inode].inspect}, new is #{inode.inspect}") + yield(:delete, path) + yield(:create, path) + elsif stat.size < @files[path][:size] + @logger.debug("#{path}: file rolled, new size is #{stat.size}, old size #{@files[path][:size]}") + yield(:delete, path) + yield(:create, path) + elsif stat.size > @files[path][:size] + @logger.debug("#{path}: file grew, old size #{@files[path][:size]}, new size #{stat.size}") + yield(:modify, path) + end @files[path][:size] = stat.size @files[path][:inode] = inode @@ -174,31 +153,30 @@ def _discover_file(path, initial=false) end next if skip - if @ishpux - # do no call Stat method on file - # (Ruby ffi does not support HP-UX systems) - @files[file] = { + stat = File::Stat.new(file) + + if @iswindows + fileId = Winhelper.GetWindowsUniqueFileIdentifier(path) + @files[file] = { :size => 0, - :inode => [path, 0, 0], + :inode => [fileId, stat.dev_major, stat.dev_minor], :create_sent => false, } - else - stat = File::Stat.new(file) - @files[file] = { + elsif @ishpux + fileId = Hpuxhelper.GetHpuxFileInode(path) + filesystemMountPoint = Hpuxhelper.GetHpuxFileFilesystemMountPoint(path) + @files[file] = { :size => 0, - :inode => [stat.ino, stat.dev_major, stat.dev_minor], + :inode => [fileId, filesystemMountPoint, 0], :create_sent => false, } - end - - if @iswindows - fileId = Winhelper.GetWindowsUniqueFileIdentifier(path) - @files[file][:inode] = [fileId, stat.dev_major, stat.dev_minor] - elsif @ishpux - @files[file][:inode] = [path, 0, 0] - else - @files[file][:inode] = [stat.ino.to_s, stat.dev_major, stat.dev_minor] - end + else + @files[file] = { + :size => 0, + :inode => [stat.ino.to_s, stat.dev_major, stat.dev_minor], + :create_sent => false, + } + end if initial @files[file][:initial] = true From 01843d724778b2cf0ee5206769d9474940f1639c Mon Sep 17 00:00:00 2001 From: Benoit Brayer Date: Wed, 14 Jan 2015 14:14:22 +0100 Subject: [PATCH 4/4] removing tabs -> spaces instead removing end lines spaces converting line break to respect unix standard changing _sincedb_write method file open mode -> solve sincedb file initializing problem --- lib/filewatch/hpuxhelper.rb | 32 ++++----- lib/filewatch/tail.rb | 130 ++++++++++++++++++------------------ lib/filewatch/watch.rb | 26 ++++---- 3 files changed, 94 insertions(+), 94 deletions(-) diff --git a/lib/filewatch/hpuxhelper.rb b/lib/filewatch/hpuxhelper.rb index 6389751..ca92603 100644 --- a/lib/filewatch/hpuxhelper.rb +++ b/lib/filewatch/hpuxhelper.rb @@ -1,18 +1,18 @@ module Hpuxhelper - - def self.GetHpuxFileInode(path) - hpuxfileino = "" - IO.popen("ls -i #{path} | awk '{print $1}'").each do |line| - hpuxfileino = line.chomp - end - return hpuxfileino - end - - def self.GetHpuxFileFilesystemMountPoint(path) - hpuxfsname = "" - IO.popen("df -n #{path} | awk '{print $1}'").each do |line| - hpuxfsname = line.chomp - end - return hpuxfsname - end + + def self.GetHpuxFileInode(path) + hpuxfileino = "" + IO.popen("ls -i #{path} | awk '{print $1}'").each do |line| + hpuxfileino = line.chomp + end + return hpuxfileino + end + + def self.GetHpuxFileFilesystemMountPoint(path) + hpuxfsname = "" + IO.popen("df -n #{path} | awk '{print $1}'").each do |line| + hpuxfsname = line.chomp + end + return hpuxfsname + end end \ No newline at end of file diff --git a/lib/filewatch/tail.rb b/lib/filewatch/tail.rb index 0fa1666..5716b2f 100644 --- a/lib/filewatch/tail.rb +++ b/lib/filewatch/tail.rb @@ -135,8 +135,8 @@ def _open_file(path, event) fileId = Winhelper.GetWindowsUniqueFileIdentifier(path) inode = [fileId, stat.dev_major, stat.dev_minor] elsif @ishpux - fileId = Hpuxhelper.GetHpuxFileInode(path) - filesystemMountPoint = Hpuxhelper.GetHpuxFileFilesystemMountPoint(path) + fileId = Hpuxhelper.GetHpuxFileInode(path) + filesystemMountPoint = Hpuxhelper.GetHpuxFileFilesystemMountPoint(path) inode = [fileId, filesystemMountPoint, 0] else inode = [stat.ino.to_s, stat.dev_major, stat.dev_minor] @@ -145,30 +145,30 @@ def _open_file(path, event) @statcache[path] = inode if @sincedb.member?(inode) - last_size = @sincedb[inode] - @logger.debug("#{path}: sincedb last value #{@sincedb[inode]}, cur size #{stat.size}") - if last_size <= stat.size - @logger.debug("#{path}: sincedb: seeking to #{last_size}") - @files[path].sysseek(last_size, IO::SEEK_SET) - else - @logger.debug("#{path}: last value size is greater than current value, starting over") - @sincedb[inode] = 0 - end - elsif event == :create_initial && @files[path] - # TODO(sissel): Allow starting at beginning of the file. - if @opts[:start_new_files_at] == :beginning - @logger.debug("#{path}: initial create, no sincedb, seeking to beginning of file") - @files[path].sysseek(0, IO::SEEK_SET) - @sincedb[inode] = 0 - else - # seek to end - @logger.debug("#{path}: initial create, no sincedb, seeking to end #{stat.size}") - @files[path].sysseek(stat.size, IO::SEEK_SET) - @sincedb[inode] = stat.size - end - else - @logger.debug("#{path}: staying at position 0, no sincedb") - end + last_size = @sincedb[inode] + @logger.debug("#{path}: sincedb last value #{@sincedb[inode]}, cur size #{stat.size}") + if last_size <= stat.size + @logger.debug("#{path}: sincedb: seeking to #{last_size}") + @files[path].sysseek(last_size, IO::SEEK_SET) + else + @logger.debug("#{path}: last value size is greater than current value, starting over") + @sincedb[inode] = 0 + end + elsif event == :create_initial && @files[path] + # TODO(sissel): Allow starting at beginning of the file. + if @opts[:start_new_files_at] == :beginning + @logger.debug("#{path}: initial create, no sincedb, seeking to beginning of file") + @files[path].sysseek(0, IO::SEEK_SET) + @sincedb[inode] = 0 + else + # seek to end + @logger.debug("#{path}: initial create, no sincedb, seeking to end #{stat.size}") + @files[path].sysseek(stat.size, IO::SEEK_SET) + @sincedb[inode] = stat.size + end + else + @logger.debug("#{path}: staying at position 0, no sincedb") + end return true end # def _open_file @@ -209,48 +209,48 @@ def sincedb_write(reason=nil) _sincedb_write end - private - def _sincedb_open - path = @opts[:sincedb_path] - begin - db = File.open(path) - rescue - @logger.debug("_sincedb_open: #{path}: #{$!}") - return - end + private + def _sincedb_open + path = @opts[:sincedb_path] + begin + db = File.open(path) + rescue + @logger.debug("_sincedb_open: #{path}: #{$!}") + return + end - @logger.debug("_sincedb_open: reading from #{path}") - db.each do |line| - ino, dev_major, dev_minor, pos = line.split(" ", 4) - inode = [ino, dev_major.to_i, dev_minor.to_i] - @logger.debug("_sincedb_open: setting #{inode.inspect} to #{pos.to_i}") - @sincedb[inode] = pos.to_i - end - end # def _sincedb_open - - private - def _sincedb_write - path = @opts[:sincedb_path] - tmp = "#{path}.new" - begin - db = File.open(tmp, "w") - rescue => e - @logger.warn("_sincedb_write failed: #{tmp}: #{e}") - return - end + @logger.debug("_sincedb_open: reading from #{path}") + db.each do |line| + ino, dev_major, dev_minor, pos = line.split(" ", 4) + inode = [ino, dev_major.to_i, dev_minor.to_i] + @logger.debug("_sincedb_open: setting #{inode.inspect} to #{pos.to_i}") + @sincedb[inode] = pos.to_i + end + end # def _sincedb_open + + private + def _sincedb_write + path = @opts[:sincedb_path] + tmp = "#{path}.new" + begin + db = File.open(tmp, "w+") + rescue => e + @logger.warn("_sincedb_write failed: #{tmp}: #{e}") + return + end - @sincedb.each do |inode, pos| - db.puts([inode, pos].flatten.join(" ")) - end - db.close + @sincedb.each do |inode, pos| + db.puts([inode, pos].flatten.join(" ")) + end + db.close + + begin + File.rename(tmp, path) + rescue => e + @logger.warn("_sincedb_write rename/sync failed: #{tmp} -> #{path}: #{e}") + end + end # def _sincedb_write - begin - File.rename(tmp, path) - rescue => e - @logger.warn("_sincedb_write rename/sync failed: #{tmp} -> #{path}: #{e}") - end - end # def _sincedb_write - public def quit @watch.quit diff --git a/lib/filewatch/watch.rb b/lib/filewatch/watch.rb index d735252..7063b86 100644 --- a/lib/filewatch/watch.rb +++ b/lib/filewatch/watch.rb @@ -79,8 +79,8 @@ def each(&block) fileId = Winhelper.GetWindowsUniqueFileIdentifier(path) inode = [fileId, stat.dev_major, stat.dev_minor] elsif @ishpux - fileId = Hpuxhelper.GetHpuxFileInode(path) - filesystemMountPoint = Hpuxhelper.GetHpuxFileFilesystemMountPoint(path) + fileId = Hpuxhelper.GetHpuxFileInode(path) + filesystemMountPoint = Hpuxhelper.GetHpuxFileFilesystemMountPoint(path) inode = [fileId, filesystemMountPoint, 0] else inode = [stat.ino.to_s, stat.dev_major, stat.dev_minor] @@ -154,29 +154,29 @@ def _discover_file(path, initial=false) next if skip stat = File::Stat.new(file) - - if @iswindows - fileId = Winhelper.GetWindowsUniqueFileIdentifier(path) - @files[file] = { + + if @iswindows + fileId = Winhelper.GetWindowsUniqueFileIdentifier(path) + @files[file] = { :size => 0, :inode => [fileId, stat.dev_major, stat.dev_minor], :create_sent => false, } - elsif @ishpux - fileId = Hpuxhelper.GetHpuxFileInode(path) - filesystemMountPoint = Hpuxhelper.GetHpuxFileFilesystemMountPoint(path) - @files[file] = { + elsif @ishpux + fileId = Hpuxhelper.GetHpuxFileInode(path) + filesystemMountPoint = Hpuxhelper.GetHpuxFileFilesystemMountPoint(path) + @files[file] = { :size => 0, :inode => [fileId, filesystemMountPoint, 0], :create_sent => false, } - else - @files[file] = { + else + @files[file] = { :size => 0, :inode => [stat.ino.to_s, stat.dev_major, stat.dev_minor], :create_sent => false, } - end + end if initial @files[file][:initial] = true