From: Martin DeMello Date: 2006-11-23T02:19:29+09:00 Subject: Re: inotify over nfs On 11/22/06, ara.t.howard@noaa.gov wrote: > > how is this working for you? i think when i looked into inotify i found that > messages would get sent twice or not at all or out of order or something like > that... i forget this exact issues. have you seen any? btw. could i/we have > a look at your code? Code inlined (not sure how the usenet and forum sides handle actual attachments) - one watcher.rb per node and one process-inotify sitting on the server. martin --- watcher.rb --- require 'inotify' require 'find' require 'drb' DRb.start_service $www = DRbObject.new(nil, 'druby://www:7777') EVENTS = { Inotify::CREATE => "created", Inotify::DELETE => "deleted" } ACTIONS = { Inotify::CREATE => :from_inotify, Inotify::MOVED_TO => :from_inotify, Inotify::MOVED_FROM => :delete_from_inotify, Inotify::DELETE => :delete_from_inotify } HOME_WATCHES = {} INOTIFY_WATCHES = {} HOME = Inotify.new INOTIFY = Inotify.new def watch(user) dir = File.join('/home', user) begin wd = INOTIFY.add_watch(dir, Inotify::CREATE | Inotify::DELETE | Inotify::MOVED_TO) INOTIFY_WATCHES[wd] = user rescue Exception => e puts "Skipping #{e}: #{$!}" end end # watch the home directory HOME.add_watch("/home", Inotify::CREATE | Inotify::ISDIR) Thread.new do HOME.each_event {|ev| p ["HOME", ev] if ev.mask == Inotify::CREATE | Inotify::ISDIR newusr = ev.name watch(newusr) end } end # watch all the user subdirectories Dir['/home/*'].each {|dir| user = File.basename(dir) watch(user) } t = Thread.new do INOTIFY.each_event {|ev| # skip hidden files unless ev.name =~ /^\./ user = INOTIFY_WATCHES[ev.wd] str = ev.name action = ACTIONS[ev.mask] if action begin $www.incoming('resource', user, action, str) rescue Exception => e puts "!! exception: #{e}" end end end } end t.join ----------------------------------- --- process-inotify.rb --- #!usr/bin/ruby require 'rubygems' require 'active_record' require 'config/environment' require 'app/models/user' require 'app/models/resource' require 'drb' require 'inotify' require 'find' require 'thread' require 'logger' # queue incoming events $incoming = Queue.new class InotifyListener def incoming(*args) $incoming << args end end DRb.start_service("druby://:7777", InotifyListener.new) LOG = Logger.new('log/inotify.log') def log(msg) LOG.info(msg) end log "opening db connection..." db_config = YAML::load(File.open("config/database.yml")) ActiveRecord::Base.establish_connection(db_config['production']) log "done!" t = Thread.new do loop do if $incoming.empty? sleep 1 next else begin signal = $incoming.shift log signal.inspect recv, username, action, file = signal user = User.find_by_login(username) unless user log "Unrecognized user #{username}: #{[recv, action, file].inspect}" next end if action begin Resource.send(action.to_sym, user, file) rescue Exception => e log "!! exception: #{e}" end end rescue Exception => e1 log "!! exception: #{e1}" end end end end DRb.thread.join ------------------------------