eventmachine-tail 0.2.20100517011408 → 0.2.20100524185851
Sign up to get free protection for your applications and to get access to all the features.
- data/lib/em/filetail.rb +29 -7
- data/lib/em/globwatcher.rb +1 -0
- data/samples/tail-with-block.rb +26 -0
- data/test/test_filetail.rb +26 -1
- metadata +4 -3
data/lib/em/filetail.rb
CHANGED
@@ -4,6 +4,7 @@ require "eventmachine"
|
|
4
4
|
require "logger"
|
5
5
|
|
6
6
|
EventMachine.epoll if EventMachine.epoll?
|
7
|
+
EventMachine.kqueue = true if EventMachine.kqueue?
|
7
8
|
|
8
9
|
# Tail a file.
|
9
10
|
#
|
@@ -44,7 +45,7 @@ class EventMachine::FileTail
|
|
44
45
|
# See also: EventMachine::file_tail
|
45
46
|
#
|
46
47
|
public
|
47
|
-
def initialize(path, startpos=-1)
|
48
|
+
def initialize(path, startpos=-1, &block)
|
48
49
|
@path = path
|
49
50
|
@logger = Logger.new(STDOUT)
|
50
51
|
@logger.level = ($DEBUG and Logger::DEBUG or Logger::WARN)
|
@@ -53,6 +54,11 @@ class EventMachine::FileTail
|
|
53
54
|
@file = nil
|
54
55
|
@fstat = File.stat(@path)
|
55
56
|
|
57
|
+
if block_given?
|
58
|
+
@handler = block
|
59
|
+
@buffer = BufferedTokenizer.new
|
60
|
+
end
|
61
|
+
|
56
62
|
if @fstat.directory?
|
57
63
|
raise Errno::EISDIR.new(@path)
|
58
64
|
end
|
@@ -86,9 +92,15 @@ class EventMachine::FileTail
|
|
86
92
|
# end
|
87
93
|
public
|
88
94
|
def receive_data(data)
|
89
|
-
|
90
|
-
|
91
|
-
|
95
|
+
if @handler # FileTail.new called with a block
|
96
|
+
@buffer.extract(data).each do |line|
|
97
|
+
@handler.call(self, line)
|
98
|
+
end
|
99
|
+
else
|
100
|
+
raise NotImplementedError.new("#{self.class.name}#receive_data is not "\
|
101
|
+
"implemented. Did you forget to implement this in your subclass or "\
|
102
|
+
"module?")
|
103
|
+
end
|
92
104
|
end # def receive_data
|
93
105
|
|
94
106
|
# notify is invoked when the file you are tailing has been modified or
|
@@ -217,13 +229,23 @@ module EventMachine
|
|
217
229
|
# path is the path to the file to tail.
|
218
230
|
# handler should be a module implementing 'receive_data' or
|
219
231
|
# must be a subclasses of EventMachine::FileTail
|
220
|
-
|
232
|
+
#
|
233
|
+
# For example:
|
234
|
+
# EM::file_tail("/var/log/messages", MyHandler)
|
235
|
+
#
|
236
|
+
# If a block is given, and the handler is not specified or does
|
237
|
+
# not implement EventMachine::FileTail#receive_data, then it
|
238
|
+
# will be called as such:
|
239
|
+
# EM::file_tail(...) do |filetail, line|
|
240
|
+
# # filetail is the FileTail instance watching the file
|
241
|
+
# # line is the line read from the file
|
242
|
+
# end
|
243
|
+
def self.file_tail(path, handler=nil, *args, &block)
|
221
244
|
# This code mostly styled on what EventMachine does in many of it's other
|
222
245
|
# methods.
|
223
246
|
args = [path, *args]
|
224
247
|
klass = klass_from_handler(EventMachine::FileTail, handler, *args);
|
225
|
-
c = klass.new(*args)
|
226
|
-
yield c if block_given?
|
248
|
+
c = klass.new(*args, &block)
|
227
249
|
return c
|
228
250
|
end # def self.file_tail
|
229
251
|
end # module EventMachine
|
data/lib/em/globwatcher.rb
CHANGED
@@ -0,0 +1,26 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
#
|
3
|
+
# Simple 'tail -f' example.
|
4
|
+
# Usage example:
|
5
|
+
# tail.rb /var/log/messages
|
6
|
+
|
7
|
+
require "rubygems"
|
8
|
+
require "eventmachine"
|
9
|
+
require "eventmachine-tail"
|
10
|
+
|
11
|
+
def main(args)
|
12
|
+
if args.length == 0
|
13
|
+
puts "Usage: #{$0} <path> [path2] [...]"
|
14
|
+
return 1
|
15
|
+
end
|
16
|
+
|
17
|
+
EventMachine.run do
|
18
|
+
args.each do |path|
|
19
|
+
EventMachine::file_tail(path) do |filetail, line|
|
20
|
+
puts line
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end # def main
|
25
|
+
|
26
|
+
exit(main(ARGV))
|
data/test/test_filetail.rb
CHANGED
@@ -11,7 +11,7 @@ require 'testcase_helpers.rb'
|
|
11
11
|
|
12
12
|
# Generate some data
|
13
13
|
DATA = (1..10).collect { |i| rand.to_s }
|
14
|
-
SLEEPMAX =
|
14
|
+
SLEEPMAX = 1
|
15
15
|
|
16
16
|
class Reader < EventMachine::FileTail
|
17
17
|
def initialize(path, startpos=-1, testobj=nil)
|
@@ -67,5 +67,30 @@ class TestFileTail < Test::Unit::TestCase
|
|
67
67
|
EM::file_tail(tmp.path, Reader, 0, self)
|
68
68
|
end # EM.run
|
69
69
|
end # def test_filetail
|
70
|
+
|
71
|
+
def test_filetail_with_block
|
72
|
+
tmp = Tempfile.new("testfiletail")
|
73
|
+
data = DATA.clone
|
74
|
+
EM.run do
|
75
|
+
abort_after_timeout(DATA.length * SLEEPMAX + 10)
|
76
|
+
|
77
|
+
lineno = 0
|
78
|
+
EM::file_tail(tmp.path) do |filetail, line|
|
79
|
+
lineno += 1
|
80
|
+
expected = data.shift
|
81
|
+
assert_equal(expected, line,
|
82
|
+
"Expected '#{expected}' on line #{@lineno}, but got '#{line}'")
|
83
|
+
finish if data.length == 0
|
84
|
+
end
|
85
|
+
|
86
|
+
data_copy = data.clone
|
87
|
+
timer = EM::PeriodicTimer.new(0.2) do
|
88
|
+
tmp.puts data_copy.shift
|
89
|
+
tmp.flush
|
90
|
+
sleep(rand * SLEEPMAX)
|
91
|
+
timer.cancel if data_copy.length == 0
|
92
|
+
end
|
93
|
+
end # EM.run
|
94
|
+
end # def test_filetail_with_block
|
70
95
|
end # class TestFileTail
|
71
96
|
|
metadata
CHANGED
@@ -5,8 +5,8 @@ version: !ruby/object:Gem::Version
|
|
5
5
|
segments:
|
6
6
|
- 0
|
7
7
|
- 2
|
8
|
-
-
|
9
|
-
version: 0.2.
|
8
|
+
- 20100524185851
|
9
|
+
version: 0.2.20100524185851
|
10
10
|
platform: ruby
|
11
11
|
authors:
|
12
12
|
- Jordan Sissel
|
@@ -14,7 +14,7 @@ autorequire:
|
|
14
14
|
bindir: bin
|
15
15
|
cert_chain: []
|
16
16
|
|
17
|
-
date: 2010-05-
|
17
|
+
date: 2010-05-24 00:00:00 -07:00
|
18
18
|
default_executable:
|
19
19
|
dependencies:
|
20
20
|
- !ruby/object:Gem::Dependency
|
@@ -44,6 +44,7 @@ files:
|
|
44
44
|
- samples/tail.rb
|
45
45
|
- samples/glob-tail.rb
|
46
46
|
- samples/globwatch.rb
|
47
|
+
- samples/tail-with-block.rb
|
47
48
|
- test/test_filetail.rb
|
48
49
|
- test/test_glob.rb
|
49
50
|
- test/alltests.rb
|