swerling-sinotify 0.0.1 → 0.0.2
Sign up to get free protection for your applications and to get access to all the features.
- data/.gitignore +3 -0
- data/README.rdoc +5 -3
- data/README.txt +7 -5
- data/Rakefile +34 -12
- data/TODO +12 -0
- data/lib/sinotify/notifier.rb +37 -14
- data/lib/sinotify/prim_event.rb +0 -4
- data/lib/sinotify_info.rb +1 -1
- data/sinotify.gemspec +8 -7
- data/spec/sinotify_spec.rb +33 -15
- metadata +7 -5
data/.gitignore
CHANGED
data/README.rdoc
CHANGED
data/README.txt
CHANGED
@@ -1,6 +1,8 @@
|
|
1
|
-
sinotify
|
2
|
-
|
3
|
-
|
1
|
+
sinotify
|
2
|
+
|
3
|
+
by {Steven Swerling}[http://tab-a.slot-z.net]
|
4
|
+
|
5
|
+
{rdoc}[http://tab-a.slot-z.net] | {github}[http://www.github.com/swerling/sinotify]
|
4
6
|
|
5
7
|
== DESCRIPTION:
|
6
8
|
|
@@ -63,10 +65,10 @@ Try this:
|
|
63
65
|
require 'sinotify'
|
64
66
|
notifier = Sinotify::Notifier.new('/tmp/sinotify_test', :recurse => true, :etypes => [:create, :modify, :delete])
|
65
67
|
notifier.spy!(:logger => Logger.new('/tmp/inotify_spy.log')) # optional event spy
|
66
|
-
notifier.
|
68
|
+
notifier.on_event do |sinotify_event|
|
67
69
|
puts "Event happened at #{sinotify_event.timestamp} on #{sinotify_event.path}, etypes => #{sinotify_event.etypes.inspect}"
|
68
70
|
end
|
69
|
-
notifier.
|
71
|
+
notifier.on_event do |sinotify_event|
|
70
72
|
puts " --> demonstrate that multiple subscribers can be setup: #{sinotify_event.etypes.inspect}"
|
71
73
|
end
|
72
74
|
notifier.watch! # don't forget to start the watch
|
data/Rakefile
CHANGED
@@ -30,21 +30,43 @@ PROJ.spec.opts << '--color'
|
|
30
30
|
PROJ.rdoc.opts = ["--inline-source"]
|
31
31
|
PROJ.rdoc.exclude = ["^tasks/setup\.rb$", "\.[ch]$"]
|
32
32
|
|
33
|
+
|
34
|
+
|
35
|
+
|
36
|
+
|
37
|
+
require 'fileutils'
|
38
|
+
def this_dir; File.join(File.dirname(__FILE__)); end
|
39
|
+
def doc_dir; File.join(this_dir, 'rdoc'); end
|
40
|
+
def ext_dir; File.join(this_dir, 'ext'); end
|
41
|
+
def tab_a_doc_dir; File.join(this_dir, '../tab-a/public/sinotify/rdoc'); end
|
42
|
+
|
33
43
|
task :default => 'spec:run'
|
34
44
|
task :myclobber => [:clobber] do
|
35
|
-
|
36
|
-
sh "rm -rf #{File.join(
|
37
|
-
sh "rm -rf #{File.join(
|
38
|
-
sh "rm -rf #{File.join(
|
39
|
-
sh "rm -rf #{File.join(
|
40
|
-
sh "rm -rf #{File.join(
|
45
|
+
mydir = File.join(File.dirname(__FILE__))
|
46
|
+
sh "rm -rf #{File.join(mydir, 'pkg')}"
|
47
|
+
sh "rm -rf #{File.join(mydir, 'doc')}"
|
48
|
+
sh "rm -rf #{File.join(mydir, 'rdoc')}"
|
49
|
+
sh "rm -rf #{File.join(mydir, 'ext/*.log')}"
|
50
|
+
sh "rm -rf #{File.join(mydir, 'ext/*.o')}"
|
51
|
+
sh "rm -rf #{File.join(mydir, 'ext/*.so')}"
|
52
|
+
sh "rm -rf #{File.join(mydir, 'ext/Makefile')}"
|
53
|
+
sh "rm -rf #{File.join(mydir, 'ext/Makefile')}"
|
41
54
|
end
|
42
55
|
task :mypackage => [:myclobber] do
|
43
|
-
sh "rm -rf #{File.join(File.dirname(__FILE__), 'pkg')}"
|
44
|
-
sh "rm -rf #{File.join(File.dirname(__FILE__), 'doc')}"
|
45
|
-
sh "rm -rf #{File.join(File.dirname(__FILE__), 'ext/*.log')}"
|
46
|
-
sh "rm -rf #{File.join(File.dirname(__FILE__), 'ext/*.o')}"
|
47
|
-
sh "rm -rf #{File.join(File.dirname(__FILE__), 'ext/*.so')}"
|
48
56
|
Rake::Task['gem:package'].invoke
|
49
57
|
end
|
50
|
-
|
58
|
+
task :mydoc => [:myclobber] do
|
59
|
+
FileUtils.rm_f doc_dir()
|
60
|
+
sh "cd #{this_dir()} && rdoc -o rdoc --inline-source --format=html -T hanna README.rdoc lib/**/*.rb"
|
61
|
+
end
|
62
|
+
task :taba => [:mydoc] do
|
63
|
+
this_dir = File.join(File.dirname(__FILE__))
|
64
|
+
FileUtils.rm_rf tab_a_doc_dir
|
65
|
+
FileUtils.cp_r doc_dir, tab_a_doc_dir
|
66
|
+
end
|
67
|
+
task :mygemspec => [:myclobber] do
|
68
|
+
Rake::Task['gem:spec'].invoke
|
69
|
+
end
|
70
|
+
task :mybuild => [:myclobber] do
|
71
|
+
sh "cd #{ext_dir} && ruby extconf.rb && make"
|
72
|
+
end
|
data/TODO
ADDED
@@ -0,0 +1,12 @@
|
|
1
|
+
1. Refactor Notifier and Event so that other operating systems can be used for prim events.
|
2
|
+
|
3
|
+
Currently there are couplings between Event and PrimEvent that assume linux (easy to remove),
|
4
|
+
and couplings between Notifier and PrimEvent that assume linux (harder to remove, will need
|
5
|
+
an adapter class)
|
6
|
+
|
7
|
+
2. Batch collate events
|
8
|
+
|
9
|
+
Currently if you remove or add a directory with lots of files, events are sent out for
|
10
|
+
every single file. Would be nice option if a single event listing all the changes went
|
11
|
+
out (say, a single event that sponges up all events for 150 milliseconds, then sends them
|
12
|
+
off as an array)
|
data/lib/sinotify/notifier.rb
CHANGED
@@ -32,7 +32,8 @@ module Sinotify
|
|
32
32
|
# :etypes =>
|
33
33
|
# which inotify file system event types to listen for (eg :create, :delete, etc)
|
34
34
|
# See docs for Sinotify::Event for list of event types.
|
35
|
-
# default is :
|
35
|
+
# default is [:create, :modify, :delete]
|
36
|
+
# Use :all_events to trace everything (although this may be more than you bargained for).
|
36
37
|
#
|
37
38
|
# :logger =>
|
38
39
|
# Where to log errors to. Default is Logger.new(STDOUT).
|
@@ -60,7 +61,7 @@ module Sinotify
|
|
60
61
|
# how many directories at a time to register.
|
61
62
|
self.recurse_throttle = opts[:recurse_throttle] || 10
|
62
63
|
|
63
|
-
self.etypes = Array(opts[:etypes] || :
|
64
|
+
self.etypes = Array( opts[:etypes] || [:create, :modify, :delete] )
|
64
65
|
validate_etypes!
|
65
66
|
|
66
67
|
self.prim_notifier = Sinotify::PrimNotifier.new
|
@@ -70,7 +71,7 @@ module Sinotify
|
|
70
71
|
sleep_time = opts[:announcements_sleep_time] || 0.05
|
71
72
|
announcement_throttle = opts[:announcement_throttle] || 50
|
72
73
|
self.queue_announcements!(:sleep_time => sleep_time,
|
73
|
-
:logger =>
|
74
|
+
:logger => @logger,
|
74
75
|
:announcements_per_cycle => announcement_throttle)
|
75
76
|
|
76
77
|
self.closed = false
|
@@ -81,6 +82,24 @@ module Sinotify
|
|
81
82
|
@spy_logger_level = nil
|
82
83
|
@watch_thread = nil
|
83
84
|
end
|
85
|
+
|
86
|
+
# Sugar.
|
87
|
+
#
|
88
|
+
# Equivalent of calling cosell's
|
89
|
+
#
|
90
|
+
# self.when_announcing(Sinotify::Event) do |event|
|
91
|
+
# do_something_with_event(event)
|
92
|
+
# end
|
93
|
+
#
|
94
|
+
# becomes
|
95
|
+
#
|
96
|
+
# self.on_event { |event| do_something_with_event(event) }
|
97
|
+
#
|
98
|
+
# Since this class only announces one kind of event, it made sense to
|
99
|
+
# provide a more terse version of that statement.
|
100
|
+
def on_event &block
|
101
|
+
self.when_announcing(Sinotify::Event, &block)
|
102
|
+
end
|
84
103
|
|
85
104
|
# whether this watch is on a directory
|
86
105
|
def on_directory?
|
@@ -108,10 +127,12 @@ module Sinotify
|
|
108
127
|
# Options:
|
109
128
|
# :logger => The log to log to. Default is a logger on STDOUT
|
110
129
|
# :level => The log level to log with. Default is :info
|
130
|
+
# :spy_on_prim_events => Spy on PrimEvents (raw inotify events) too
|
111
131
|
#
|
112
132
|
def spy!(opts = {})
|
113
|
-
|
114
|
-
|
133
|
+
self.spy_on_prim_events = opts[:spy_on_prim_events].eql?(true)
|
134
|
+
self.spy_logger = opts[:logger] || Logger.new(STDOUT)
|
135
|
+
self.spy_logger_level = opts[:level] || :info
|
115
136
|
opts[:on] = Sinotify::Event
|
116
137
|
opts[:preface_with] = "Sinotify::Notifier Event Spy"
|
117
138
|
super(opts)
|
@@ -141,6 +162,8 @@ module Sinotify
|
|
141
162
|
|
142
163
|
#:stopdoc:
|
143
164
|
|
165
|
+
attr_accessor :spy_on_prim_events, :spy_logger, :spy_logger_level
|
166
|
+
|
144
167
|
def validate_etypes!
|
145
168
|
bad = self.etypes.detect{|etype| PrimEvent.mask_from_etype(etype).nil? }
|
146
169
|
raise "Unrecognized etype '#{bad}'. Please see valid list in docs for Sinotify::Event" if bad
|
@@ -229,13 +252,6 @@ module Sinotify
|
|
229
252
|
self.logger.send(level, msg) if self.logger
|
230
253
|
end
|
231
254
|
|
232
|
-
def spy_on_event(prim_event)
|
233
|
-
if @spy_logger
|
234
|
-
msg = "Sinotify::Notifier Prim Event Spy: #{prim_event.inspect}"
|
235
|
-
@spy_logger.send(@spy_logger_level, msg)
|
236
|
-
end
|
237
|
-
end
|
238
|
-
|
239
255
|
# Listen for linux inotify events, and as they come in
|
240
256
|
# 1. adapt them into Sinotify::Event objects
|
241
257
|
# 2. 'announce' them using Cosell.
|
@@ -255,9 +271,9 @@ module Sinotify
|
|
255
271
|
self.prim_notifier.each_event do |prim_event|
|
256
272
|
watch = self.watches[prim_event.watch_descriptor.to_s]
|
257
273
|
if event_is_noise?(prim_event, watch)
|
258
|
-
|
274
|
+
self.spy_logger.debug("Sinotify::Notifier Spy: Skipping noise[#{prim_event.inspect}]") if self.spy_on_prim_events
|
259
275
|
else
|
260
|
-
|
276
|
+
spy_on_prim_event(prim_event)
|
261
277
|
if watch.nil?
|
262
278
|
self.log "Could not determine watch from descriptor #{prim_event.watch_descriptor}, something is wrong. Event: #{prim_event.inspect}", :warn
|
263
279
|
else
|
@@ -294,6 +310,13 @@ module Sinotify
|
|
294
310
|
@raw_mask
|
295
311
|
end
|
296
312
|
|
313
|
+
def spy_on_prim_event(prim_event)
|
314
|
+
if self.spy_on_prim_events
|
315
|
+
msg = "Sinotify::Notifier Prim Event Spy: #{prim_event.inspect}"
|
316
|
+
self.spy_logger.send(@spy_logger_level, msg)
|
317
|
+
end
|
318
|
+
end
|
319
|
+
|
297
320
|
# ruby gives warnings in verbose mode if you use attr_accessor to set these next few:
|
298
321
|
def prim_notifier; @prim_notifier; end
|
299
322
|
def prim_notifier= x; @prim_notifier = x; end
|
data/lib/sinotify/prim_event.rb
CHANGED
@@ -60,10 +60,6 @@ module Sinotify
|
|
60
60
|
@@etype_to_mask_map = {}
|
61
61
|
@@mask_to_etype_map.each{|k,v| @@etype_to_mask_map[v] = k}
|
62
62
|
|
63
|
-
# def self.etype_from_mask(mask)
|
64
|
-
# @@mask_to_etype_map[mask]
|
65
|
-
# end
|
66
|
-
|
67
63
|
def self.etype_from_mask(mask)
|
68
64
|
@@mask_to_etype_map[mask]
|
69
65
|
end
|
data/lib/sinotify_info.rb
CHANGED
data/sinotify.gemspec
CHANGED
@@ -2,11 +2,11 @@
|
|
2
2
|
|
3
3
|
Gem::Specification.new do |s|
|
4
4
|
s.name = %q{sinotify}
|
5
|
-
s.version = "0.0.
|
5
|
+
s.version = "0.0.2"
|
6
6
|
|
7
7
|
s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
|
8
8
|
s.authors = ["Steven Swerling"]
|
9
|
-
s.date = %q{2009-
|
9
|
+
s.date = %q{2009-08-09}
|
10
10
|
s.description = %q{ALPHA Alert -- just uploaded initial release.
|
11
11
|
|
12
12
|
Linux inotify is a means to receive events describing file system activity (create, modify, delete, close, etc).
|
@@ -53,12 +53,13 @@ Selected quotes from the README for inotify:
|
|
53
53
|
s.email = %q{sswerling@yahoo.com}
|
54
54
|
s.extensions = ["ext/extconf.rb"]
|
55
55
|
s.extra_rdoc_files = ["History.txt", "README.txt"]
|
56
|
-
s.files = [".gitignore", "History.txt", "README.rdoc", "README.txt", "Rakefile", "examples/watcher.rb", "ext/extconf.rb", "ext/src/inotify-syscalls.h", "ext/src/inotify.h", "ext/src/sinotify.c", "lib/sinotify.rb", "lib/sinotify/event.rb", "lib/sinotify/notifier.rb", "lib/sinotify/prim_event.rb", "lib/sinotify/watch.rb", "lib/sinotify_info.rb", "sinotify.gemspec", "spec/prim_notify_spec.rb", "spec/sinotify_spec.rb", "spec/spec_helper.rb"]
|
56
|
+
s.files = [".gitignore", "History.txt", "README.rdoc", "README.txt", "Rakefile", "TODO", "examples/watcher.rb", "ext/extconf.rb", "ext/src/inotify-syscalls.h", "ext/src/inotify.h", "ext/src/sinotify.c", "lib/sinotify.rb", "lib/sinotify/event.rb", "lib/sinotify/notifier.rb", "lib/sinotify/prim_event.rb", "lib/sinotify/watch.rb", "lib/sinotify_info.rb", "sinotify.gemspec", "spec/prim_notify_spec.rb", "spec/sinotify_spec.rb", "spec/spec_helper.rb"]
|
57
|
+
s.has_rdoc = true
|
57
58
|
s.homepage = %q{http://tab-a.slot-z.net}
|
58
59
|
s.rdoc_options = ["--inline-source", "--main", "README.txt"]
|
59
60
|
s.require_paths = ["lib", "ext"]
|
60
61
|
s.rubyforge_project = %q{sinotify}
|
61
|
-
s.rubygems_version = %q{1.3.
|
62
|
+
s.rubygems_version = %q{1.3.2}
|
62
63
|
s.summary = %q{ALPHA Alert -- just uploaded initial release}
|
63
64
|
|
64
65
|
if s.respond_to? :specification_version then
|
@@ -67,13 +68,13 @@ Selected quotes from the README for inotify:
|
|
67
68
|
|
68
69
|
if Gem::Version.new(Gem::RubyGemsVersion) >= Gem::Version.new('1.2.0') then
|
69
70
|
s.add_runtime_dependency(%q<cosell>, [">= 0"])
|
70
|
-
s.add_development_dependency(%q<bones>, [">= 2.
|
71
|
+
s.add_development_dependency(%q<bones>, [">= 2.5.1"])
|
71
72
|
else
|
72
73
|
s.add_dependency(%q<cosell>, [">= 0"])
|
73
|
-
s.add_dependency(%q<bones>, [">= 2.
|
74
|
+
s.add_dependency(%q<bones>, [">= 2.5.1"])
|
74
75
|
end
|
75
76
|
else
|
76
77
|
s.add_dependency(%q<cosell>, [">= 0"])
|
77
|
-
s.add_dependency(%q<bones>, [">= 2.
|
78
|
+
s.add_dependency(%q<bones>, [">= 2.5.1"])
|
78
79
|
end
|
79
80
|
end
|
data/spec/sinotify_spec.rb
CHANGED
@@ -15,11 +15,17 @@ end
|
|
15
15
|
describe Sinotify do
|
16
16
|
|
17
17
|
# A lot of Sinotify work occurs in background threads (eg. adding watches, adding subdirectories),
|
18
|
-
# so the tests may insert a tiny
|
18
|
+
# so the tests may insert a tiny pauses to allow the bg threads to do their thing before making
|
19
19
|
# any assertions.
|
20
|
-
def tiny_pause
|
21
|
-
|
22
|
-
|
20
|
+
def tiny_pause!
|
21
|
+
25.times{sleep 0.0001}
|
22
|
+
end
|
23
|
+
def pause!
|
24
|
+
25.times{sleep 0.005}
|
25
|
+
end
|
26
|
+
def big_pause!
|
27
|
+
10.times{sleep 0.1}
|
28
|
+
end
|
23
29
|
|
24
30
|
def reset_test_dir!
|
25
31
|
raise 'not gonna happen' unless @test_root_dir =~ /\/tmp\//
|
@@ -74,7 +80,9 @@ describe Sinotify do
|
|
74
80
|
notifier.all_directories_being_watched.should be_eql([@test_root_dir])
|
75
81
|
|
76
82
|
# make a watch, recurse TRUE. There should only be 27 watches (a-z, and @test_root_dir)
|
77
|
-
notifier = Sinotify::Notifier.new(@test_root_dir,
|
83
|
+
notifier = Sinotify::Notifier.new(@test_root_dir,
|
84
|
+
:etypes => [:all_events],
|
85
|
+
:recurse => true).watch!
|
78
86
|
# notifier.spy!(:logger => Logger.new('/tmp/spy.log'))
|
79
87
|
|
80
88
|
pause!
|
@@ -83,7 +91,7 @@ describe Sinotify do
|
|
83
91
|
# check a single announcement on a file in a subdir
|
84
92
|
events = []
|
85
93
|
test_fn = File.join(@test_root_dir, 'a', 'hi')
|
86
|
-
notifier.
|
94
|
+
notifier.on_event { |event| events << event }
|
87
95
|
FileUtils.touch test_fn
|
88
96
|
pause!
|
89
97
|
#puts events.map{|e|e.to_s}.join("\n")
|
@@ -116,21 +124,29 @@ describe Sinotify do
|
|
116
124
|
subdir_a = File.join(@test_root_dir, 'a')
|
117
125
|
events = []
|
118
126
|
notifier = Sinotify::Notifier.new(@test_root_dir, :recurse => true).watch!
|
119
|
-
#
|
120
|
-
notifier.
|
127
|
+
#notifier.spy!(:logger => spylog = Logger.new(STDOUT))
|
128
|
+
notifier.on_event { |event| events << event }
|
121
129
|
|
122
130
|
# one watch for the root and the 26 subdirs 'a'..'z'
|
123
131
|
pause!
|
124
132
|
notifier.all_directories_being_watched.size.should be_eql(27)
|
125
133
|
|
126
134
|
# create a new subdir
|
127
|
-
|
128
|
-
|
135
|
+
subdir_abc = File.join(@test_root_dir, 'a', 'abc')
|
136
|
+
FileUtils.mkdir subdir_abc
|
137
|
+
pause! # takes a moment to sink in because the watch is added in a bg thread
|
129
138
|
notifier.all_directories_being_watched.size.should be_eql(28)
|
130
139
|
pause!
|
140
|
+
|
141
|
+
# create a file in the new subdir, it should send and event
|
142
|
+
file_in_subdir_abc = File.join(subdir_abc, 'new_file')
|
143
|
+
events_before = events.size
|
144
|
+
FileUtils.touch file_in_subdir_abc
|
145
|
+
pause!
|
146
|
+
events.size.should be_eql(events_before + 1)
|
131
147
|
end
|
132
148
|
|
133
|
-
it "should delete watches for on
|
149
|
+
it "should delete watches for on subdirectories when a parent directory is deleted" do
|
134
150
|
|
135
151
|
# Setup (create the usual test dir and 26 subdirs, and an additional sub-subdir, and a file
|
136
152
|
reset_test_dir! # creates the root dir and 'a'...'z'
|
@@ -143,7 +159,7 @@ describe Sinotify do
|
|
143
159
|
events = []
|
144
160
|
notifier = Sinotify::Notifier.new(@test_root_dir, :recurse => true).watch!
|
145
161
|
#notifier.spy!(:logger => Logger.new('/tmp/spy.log'))
|
146
|
-
notifier.
|
162
|
+
notifier.on_event { |event| events << event }
|
147
163
|
|
148
164
|
# first assert: all directories should have a watch
|
149
165
|
pause!
|
@@ -172,7 +188,7 @@ describe Sinotify do
|
|
172
188
|
events = []
|
173
189
|
notifier = Sinotify::Notifier.new(@test_root_dir, :recurse => true).watch!
|
174
190
|
#notifier.spy!(:logger => Logger.new('/tmp/spy.log'))
|
175
|
-
notifier.
|
191
|
+
notifier.on_event { |event| events << event }
|
176
192
|
|
177
193
|
# first assert: all directories should have a watch
|
178
194
|
pause!
|
@@ -196,7 +212,7 @@ describe Sinotify do
|
|
196
212
|
:recurse => true).watch!
|
197
213
|
#notifier.spy!(:logger => Logger.new('/tmp/spy.log'))
|
198
214
|
creates = deletes = modifies = closes = 0
|
199
|
-
notifier.
|
215
|
+
notifier.on_event do |event|
|
200
216
|
creates += 1 if event.etypes.include?(:create)
|
201
217
|
deletes += 1 if event.etypes.include?(:delete)
|
202
218
|
modifies += 1 if event.etypes.include?(:modify)
|
@@ -226,9 +242,11 @@ describe Sinotify do
|
|
226
242
|
break if waits > 30
|
227
243
|
#raise "Tired of waiting for create events to reach #{total_iterations}, it is only at #{creates}" if waits > 30
|
228
244
|
end
|
245
|
+
|
229
246
|
puts "It took #{Time.now - start_wait} seconds for all the create/modify/delete/close events to come through"
|
230
247
|
|
231
|
-
|
248
|
+
# give it a tiny bit longer to let any remaining modify/delete/close stragglers to come through
|
249
|
+
5.times{tiny_pause!}
|
232
250
|
|
233
251
|
puts "Ceates detected: #{creates}"
|
234
252
|
puts "Deletes: #{deletes}"
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: swerling-sinotify
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0.
|
4
|
+
version: 0.0.2
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Steven Swerling
|
@@ -9,7 +9,7 @@ autorequire:
|
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
11
|
|
12
|
-
date: 2009-
|
12
|
+
date: 2009-08-09 00:00:00 -07:00
|
13
13
|
default_executable:
|
14
14
|
dependencies:
|
15
15
|
- !ruby/object:Gem::Dependency
|
@@ -30,7 +30,7 @@ dependencies:
|
|
30
30
|
requirements:
|
31
31
|
- - ">="
|
32
32
|
- !ruby/object:Gem::Version
|
33
|
-
version: 2.
|
33
|
+
version: 2.5.1
|
34
34
|
version:
|
35
35
|
description: "ALPHA Alert -- just uploaded initial release. Linux inotify is a means to receive events describing file system activity (create, modify, delete, close, etc). Sinotify was derived from aredridel's package (http://raa.ruby-lang.org/project/ruby-inotify/), with the addition of Paul Boon's tweak for making the event_check thread more polite (see http://www.mindbucket.com/2009/02/24/ruby-daemons-verifying-good-behavior/) In sinotify, the classes Sinotify::PrimNotifier and Sinotify::PrimEvent provide a low level wrapper to inotify, with the ability to establish 'watches' and then listen for inotify events using one of inotify's synchronous event loops, and providing access to the events' masks (see 'man inotify' for details). Sinotify::PrimEvent class adds a little semantic sugar to the event in to the form of 'etypes', which are just ruby symbols that describe the event mask. If the event has a raw mask of (DELETE_SELF & IS_DIR), then the etypes array would be [:delete_self, :is_dir]. In addition to the 'straight' wrapper in inotify, sinotify provides an asynchronous implementation of the 'observer pattern' for notification. In other words, Sinotify::Notifier listens in the background for inotify events, adapting them into instances of Sinotify::Event as they come in and immediately placing them in a concurrent queue, from which they are 'announced' to 'subscribers' of the event. [Sinotify uses the 'cosell' implementation of the Announcements event notification framework, hence the terminology 'subscribe' and 'announce' rather then 'listen' and 'trigger' used in the standard event observer pattern. See the 'cosell' package on github for details.] A variety of 'knobs' are provided for controlling the behavior of the notifier: whether a watch should apply to a single directory or should recurse into subdirectores, how fast it should broadcast queued events, etc (see Sinotify::Notifier, and the example in the synopsis section below). An event 'spy' can also be setup to log all Sinotify::PrimEvents and Sinotify::Events. Sinotify::Event simplifies inotify's muddled event model, sending events only for those files/directories that have changed. That's not to say you can't setup a notifier that recurses into subdirectories, just that any individual event will apply to a single file, and not to its children. Also, event types are identified using words (in the form of ruby :symbols) instead of inotify's event masks. See Sinotify::Event for more explanation. The README for inotify: http://www.kernel.org/pub/linux/kernel/people/rml/inotify/README Selected quotes from the README for inotify: * \"Rumor is that the 'd' in 'dnotify' does not stand for 'directory' but for 'suck.'\" * \"The 'i' in inotify does not stand for 'suck' but for 'inode' -- the logical choice since inotify is inode-based.\" (The 's' in 'sinotify' does in fact stand for 'suck.')"
|
36
36
|
email: sswerling@yahoo.com
|
@@ -47,6 +47,7 @@ files:
|
|
47
47
|
- README.rdoc
|
48
48
|
- README.txt
|
49
49
|
- Rakefile
|
50
|
+
- TODO
|
50
51
|
- examples/watcher.rb
|
51
52
|
- ext/extconf.rb
|
52
53
|
- ext/src/inotify-syscalls.h
|
@@ -62,8 +63,9 @@ files:
|
|
62
63
|
- spec/prim_notify_spec.rb
|
63
64
|
- spec/sinotify_spec.rb
|
64
65
|
- spec/spec_helper.rb
|
65
|
-
has_rdoc:
|
66
|
+
has_rdoc: true
|
66
67
|
homepage: http://tab-a.slot-z.net
|
68
|
+
licenses:
|
67
69
|
post_install_message:
|
68
70
|
rdoc_options:
|
69
71
|
- --inline-source
|
@@ -87,7 +89,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
87
89
|
requirements: []
|
88
90
|
|
89
91
|
rubyforge_project: sinotify
|
90
|
-
rubygems_version: 1.
|
92
|
+
rubygems_version: 1.3.5
|
91
93
|
signing_key:
|
92
94
|
specification_version: 3
|
93
95
|
summary: ALPHA Alert -- just uploaded initial release
|