File: configuration.rb

package info (click to toggle)
ruby-directory-watcher 1.5.1-1
  • links: PTS, VCS
  • area: main
  • in suites: jessie, jessie-kfreebsd
  • size: 224 kB
  • ctags: 224
  • sloc: ruby: 1,411; makefile: 5
file content (228 lines) | stat: -rw-r--r-- 7,386 bytes parent folder | download | duplicates (4)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
#
# The top level configuration options used by DirectoryWatcher are used by many
# of the sub components for a variety of purposes. The Configuration represents
# all those options and other global like instances.
#
# The top level DirectoryWatcher class allows the configs to be changed during
# execution, so all of the dependent classes need to be informed when their
# options have changed. This class allows that.
#
class DirectoryWatcher::Configuration
  # The directory to monitor for events. The glob's will be used in conjunction
  # with this directory to find the full list of globs available.
  attr_reader :dir

  # The glob of files to monitor. This is an Array of file matching globs
  # be aware that changing the :glob value after watching has started has the
  # potential to cause spurious events if the new globs do not match the old,
  # files will appear to have been deleted.
  #
  # The default is '*'
  attr_reader :glob

  # The interval at which to do a full scan using the +glob+ to determine Events
  # to send.
  #
  # The default is 30.0 seconds
  attr_reader :interval

  # Controls the number of intervals a file must remain unchanged before it is
  # considered "stable". When this condition is met, a stable event is
  # generated for the file. If stable is set to +nil+ then stable events
  # will not be generated.
  #
  # The default is nil, indicating no stable events are to be emitted.
  attr_reader :stable

  # pre_load says if an initial scan using the globs should be done to pre
  # populate the state of the system before sending any events.
  #
  # The default is false
  attr_reader :pre_load

  # The filename to persist the state of the DirectoryWatcher too upon calling
  # *stop*.
  #
  # The default is nil, indicating that no state is to be persisted.
  attr_reader :persist

  # The back end scanner to use. The available options are:
  #
  #   nil     => Use the default, pure ruby Threaded scanner
  #   :em     => Use the EventMachine based scanner. This requires that the
  #              'eventmachine' gem be installed.
  #   :coolio => Use the Cool.io based scanner. This requires that the
  #              'cool.io' gem be installed.
  #   :rev    => Use the Rev based scanner. This requires that the 'rev' gem be
  #              installed.
  #
  # The default is nil, indicating the pure ruby threaded scanner will be used.
  # This option may not be changed once the DirectoryWatcher is allocated.
  #
  attr_reader :scanner

  # The sorting method to use when emitting a set of Events after a Scan has
  # happened. Since a Scan may produce a number of events, if those Events should
  # be emitted in a particular order, use +sort_by+ to pick which field to sort
  # the events, and +order_by+ to say if those events are to be emitted in
  # :ascending or :descending order.
  #
  # Available options:
  #
  #   :path   => The default, they will be sorted by full pathname
  #   :mtime  => Last modified time. They will be sorted by their FileStat mtime
  #   :size   => The number of bytes in the file.
  #
  attr_accessor :sort_by

  # When sorting you may pick if the order should be:
  #
  #   :ascending  => The default, from lowest to highest
  #   :descending => from highest to lowest.
  #
  attr_accessor :order_by

  # The Queue through which the Scanner will send data to the Collector
  #
  attr_reader :collection_queue

  # The Queue through which the Collector will send data to the Notifier
  #
  attr_reader :notification_queue

  # The logger through wich every one will log
  #
  attr_reader :logger

  # Return a Hash of all the default options
  #
  def self.default_options
    {
      :dir           => '.',
      :glob          => '*',
      :interval      => 30.0,
      :stable        => nil,
      :pre_load      => false,
      :persist       => nil,
      :scanner       => nil,
      :sort_by       => :path,
      :order_by      => :ascending,
      :logger        => nil,
    }
  end

  # Create a new Configuration by blending the passed in items with the defaults
  #
  def initialize( options = {} )
    o = self.class.default_options.merge( options )
    @dir      = o[:dir]
    @pre_load = o[:pre_load]
    @scanner  = o[:scanner]
    @sort_by  = o[:sort_by]
    @order_by = o[:order_by]

    # These have validation rules
    self.persist = o[:persist]
    self.interval = o[:interval]
    self.glob = o[:glob]
    self.stable = o[:stable]
    self.logger = o[:logger]

    @notification_queue = Queue.new
    @collection_queue = Queue.new
  end

  # Is pre_load set or not
  #
  def pre_load?
    @pre_load
  end

  # The class of the scanner
  #
  def scanner_class
    class_name = scanner.to_s.capitalize + 'Scanner'
    DirectoryWatcher.const_get( class_name ) rescue DirectoryWatcher::Scanner
  end

  # call-seq:
  #    glob = '*'
  #    glob = ['lib/**/*.rb', 'test/**/*.rb']
  #
  # Sets the glob pattern that will be used when scanning the directory for
  # files. A single glob pattern can be given or an array of glob patterns.
  #
  def glob=( val )
    glob = case val
           when String; [File.join(@dir, val)]
           when Array; val.flatten.map! {|g| File.join(@dir, g)}
           else
             raise(ArgumentError,
                   'expecting a glob pattern or an array of glob patterns')
           end
    glob.uniq!
    @glob = glob
  end

  # Sets the directory scan interval. The directory will be scanned every
  # _interval_ seconds for changes to files matching the glob pattern.
  # Raises +ArgumentError+ if the interval is zero or negative.
  #
  def interval=( val )
    val = Float(val)
    raise ArgumentError, "interval must be greater than zero" if val <= 0
    @interval = val
  end

  # Sets the logger instance. This will be used by all classes for logging
  #
  def logger=( val )
    if val then
      if %w[ debug info warn error fatal ].all? { |meth| val.respond_to?( meth ) } then
        @logger = val
      end
    else
      @logger = ::DirectoryWatcher::Logable.default_logger
    end
  end

  # Sets the number of intervals a file must remain unchanged before it is
  # considered "stable". When this condition is met, a stable event is
  # generated for the file. If stable is set to +nil+ then stable events
  # will not be generated.
  #
  # A stable event will be generated once for a file. Another stable event
  # will only be generated after the file has been modified and then remains
  # unchanged for _stable_ intervals.
  #
  # Example:
  #
  #     dw = DirectoryWatcher.new( '/tmp', :glob => 'swap.*' )
  #     dw.interval = 15.0
  #     dw.stable = 4
  #
  # In this example, a directory watcher is configured to look for swap files
  # in the /tmp directory. Stable events will be generated every 4 scan
  # intervals iff a swap remains unchanged for that time. In this case the
  # time is 60 seconds (15.0 * 4).
  #
  def stable=( val )
    if val.nil?
      @stable = nil
    else
      val = Integer(val)
      raise ArgumentError, "stable must be greater than zero" if val <= 0
      @stable = val
    end
    return @stable
  end

  # Sets the name of the file to which the directory watcher state will be
  # persisted when it is stopped. Setting the persist filename to +nil+ will
  # disable this feature.
  #
  def persist=( filename )
    @persist = filename ? filename.to_s : nil
  end
end