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 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
- raise NotImplementedError.new("#{self.class.name}#receive_data is not "\
90
- "implemented. Did you forget to implement this in your subclass or "\
91
- "module?")
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
- def self.file_tail(path, handler=nil, *args)
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
@@ -6,6 +6,7 @@ require "logger"
6
6
  require "set"
7
7
 
8
8
  EventMachine.epoll if EventMachine.epoll?
9
+ EventMachine.kqueue = true if EventMachine.kqueue?
9
10
 
10
11
  # A file glob pattern watcher for EventMachine.
11
12
  #
@@ -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))
@@ -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 = 2
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
- - 20100517011408
9
- version: 0.2.20100517011408
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 00:00:00 -07:00
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