Class: FChange::Notifier

Inherits:
Object
  • Object
show all
Defined in:
lib/vendor/windows/lib/rb-fchange/notifier.rb

Overview

Notifier wraps a single instance of FChange. It’s possible to have more than one instance, but usually unnecessary.

Examples:

# Create the notifier
notifier = FChange::Notifier.new

# Run this callback whenever the file path/to/foo.txt is read
notifier.watch("path/to/foo/", :all_events) do
  puts "foo was accessed!"
end

# Nothing happens until you run the notifier!
notifier.run

Constant Summary collapse

INFINITE =
0xFFFFFFFF
WAIT_OBJECT_0 =
0x00000000

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initializeNotifier

Creates a new FChange::Notifier.



37
38
39
40
41
# File 'lib/vendor/windows/lib/rb-fchange/notifier.rb', line 37

def initialize
  @watchers = {}
  @dwChangeHandles = []
  @lp_dwChangeHandles = 0
end

Instance Attribute Details

#dwChangeHandlesObject (readonly)

Returns the value of attribute dwChangeHandles.



31
32
33
# File 'lib/vendor/windows/lib/rb-fchange/notifier.rb', line 31

def dwChangeHandles
  @dwChangeHandles
end

#lp_dwChangeHandlesObject (readonly)

Returns the value of attribute lp_dwChangeHandles.



32
33
34
# File 'lib/vendor/windows/lib/rb-fchange/notifier.rb', line 32

def lp_dwChangeHandles
  @lp_dwChangeHandles
end

#watchers{Fixnum => Watcher} (readonly)

A hash from Watcher ids to the instances themselves.

Returns:



29
30
31
# File 'lib/vendor/windows/lib/rb-fchange/notifier.rb', line 29

def watchers
  @watchers
end

Instance Method Details

#add_watcher(watcher) ⇒ Object

Adds a new Watcher to the queue.



44
45
46
47
48
49
50
51
52
53
54
# File 'lib/vendor/windows/lib/rb-fchange/notifier.rb', line 44

def add_watcher(watcher)

  @watchers[watcher.id] = watcher

  @dwChangeHandles.push watcher.id

  # Pack event handles into newly created storage area 
  # to be used for Win32 call
  @lp_dwChangeHandles = dwChangeHandles.pack("L" * dwChangeHandles.count)

end

#closeObject



144
145
146
# File 'lib/vendor/windows/lib/rb-fchange/notifier.rb', line 144

def close
  
end

#processObject

Blocks until there are one or more filesystem events that this notifier has watchers registered for. Once there are events, the appropriate callbacks are called and this function returns.

See Also:



111
112
113
# File 'lib/vendor/windows/lib/rb-fchange/notifier.rb', line 111

def process
  read_events.each {|event| event.callback!}
end

#read_eventsObject

Blocks until there are one or more filesystem events that this notifier has watchers registered for. Once there are events, returns their Event objects.



120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
# File 'lib/vendor/windows/lib/rb-fchange/notifier.rb', line 120

def read_events

  # can return WAIT_TIMEOUT  = 0x00000102
  dwWaitStatus = Native.WaitForMultipleObjects(@dwChangeHandles.count, 
    @lp_dwChangeHandles, 0, 500)

  events = []

  # this call blocks all threads completely.
  @dwChangeHandles.each_index do |index|
    if dwWaitStatus == WAIT_OBJECT_0 + index

      ev = Event.new(@watchers[@dwChangeHandles[index]])
      events << ev
    
      r = Native.FindNextChangeNotification(@dwChangeHandles[index]) 
      if r == 0 
          raise SystemCallError.new("Failed to watch", r) 
      end
    end
  end
  events
end

#runObject

Starts the notifier watching for filesystem events. Blocks until #stop is called.

See Also:



93
94
95
96
# File 'lib/vendor/windows/lib/rb-fchange/notifier.rb', line 93

def run
  @stop = false
  process until @stop
end

#stopObject

Stop watching for filesystem events. That is, if we’re in a #run loop, exit out as soon as we finish handling the events.



101
102
103
# File 'lib/vendor/windows/lib/rb-fchange/notifier.rb', line 101

def stop
  @stop = true
end

#watch(path, *flags) {|event| ... } ⇒ Watcher

Watches a file or directory for changes, calling the callback when there are. This is only activated once #process or #run is called.

**Note that by default, this does not recursively watch subdirectories of the watched directory**. To do so, use the ‘:recursive` flag.

‘:recursive` : Recursively watch any subdirectories that are created.

Parameters:

  • path (String)

    The path to the file or directory

  • flags (Array<Symbol>)

    Which events to watch for

Yields:

  • (event)

    A block that will be called whenever one of the specified events occur

Yield Parameters:

  • event (Event)

    The Event object containing information about the event that occured

Returns:

  • (Watcher)

    A Watcher set up to watch this path for these events

Raises:

  • (SystemCallError)

    if the file or directory can’t be watched, e.g. if the file isn’t found, read access is denied, or the flags don’t contain any events



77
78
79
80
81
82
83
84
85
86
87
# File 'lib/vendor/windows/lib/rb-fchange/notifier.rb', line 77

def watch(path, *flags, &callback)
  recursive = flags.include?(:recursive)
  #:latency = 0.5
  flags = flags - [:recursive]
  if flags.empty?
    @flags = [:all_events]
  else
    @flags = flags.freeze
  end
  Watcher.new(self, path, recursive, *@flags, &callback)
end