eventmachine-tail 0.2.20100517011408 → 0.2.20100524185851

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
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