carnivore-files 0.2.0 → 0.2.2
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/CHANGELOG.md +3 -0
- data/carnivore-files.gemspec +2 -4
- data/lib/carnivore-files/carn_file.rb +29 -20
- data/lib/carnivore-files/util/fetcher.rb +30 -22
- data/lib/carnivore-files/util/nio.rb +12 -19
- data/lib/carnivore-files/util/penguin.rb +25 -26
- data/lib/carnivore-files/version.rb +1 -1
- metadata +16 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: c9393f45222d01b7842f08069591d1e50c3371dc
|
4
|
+
data.tar.gz: 515225fcea7f56ae7c1d4596c951ee3ca827668f
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 36b7787ad5dbbcff760a296a5dcb405d1998ed87451ecfd43bdd0461623629a8f368c7076f284409ceed821038af270837e886b5bcd803ccc4766d79013275e0
|
7
|
+
data.tar.gz: 435775b1547fa6920900783830c1fd5bbc057606608ed9a7bc7e934a3cf0bfc5790b693ffc41150a14ea0d4cc1573910867835cfc79a0c6eba477616b0814e67
|
data/CHANGELOG.md
CHANGED
data/carnivore-files.gemspec
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
$LOAD_PATH.unshift File.expand_path(File.dirname(__FILE__)) + '/lib/'
|
2
2
|
require 'carnivore-files/version'
|
3
|
-
Gem::Specification.new do |s|
|
3
|
+
spec = Gem::Specification.new do |s|
|
4
4
|
s.name = 'carnivore-files'
|
5
5
|
s.version = Carnivore::Files::VERSION.version
|
6
6
|
s.summary = 'Message processing helper'
|
@@ -11,9 +11,7 @@ Gem::Specification.new do |s|
|
|
11
11
|
s.license = 'Apache 2.0'
|
12
12
|
s.require_path = 'lib'
|
13
13
|
s.add_dependency 'carnivore', '>= 0.1.8'
|
14
|
-
# support both but don't want to install both
|
15
|
-
# update to be setup like carnivore-rabbitmq
|
16
|
-
# s.add_dependency 'nio4r'
|
17
14
|
s.add_dependency 'sleepy_penguin'
|
15
|
+
s.add_dependency 'nio4r'
|
18
16
|
s.files = Dir['{lib}/**/**/*'] + %w(carnivore-files.gemspec README.md CHANGELOG.md)
|
19
17
|
end
|
@@ -8,7 +8,10 @@ module Carnivore
|
|
8
8
|
# @return [String] path to file
|
9
9
|
attr_reader :path
|
10
10
|
# @return [Symbol] registry name of fetcher
|
11
|
-
attr_reader :
|
11
|
+
attr_reader :fetcher
|
12
|
+
|
13
|
+
trap_exit :fetcher_failure
|
14
|
+
finalizer :fetcher_destroyer
|
12
15
|
|
13
16
|
# Setup source
|
14
17
|
#
|
@@ -16,40 +19,46 @@ module Carnivore
|
|
16
19
|
# @option args [String] :path path to file
|
17
20
|
# @option args [Symbol] :foundation underlying file interaction library
|
18
21
|
# @option args [Celluloid::Actor] :notify_actor actor to notify on line receive
|
19
|
-
def setup(
|
22
|
+
def setup(*_)
|
20
23
|
@path = ::File.expand_path(args[:path])
|
21
|
-
@fetcher_name = "log_fetcher_#{name}".to_sym
|
22
24
|
unless(args[:foundation])
|
23
|
-
args[:foundation] =
|
25
|
+
args[:foundation] = RUBY_PLATFORM == 'java' ? :nio4r : :penguin
|
24
26
|
end
|
27
|
+
end
|
28
|
+
|
29
|
+
# Start the line fetcher
|
30
|
+
def connect
|
31
|
+
@fetcher_name = "log_fetcher_#{name}".to_sym
|
25
32
|
case args[:foundation].to_sym
|
26
33
|
when :nio, :nio4r
|
27
|
-
|
28
|
-
args.merge(:notify_actor => current_actor)
|
29
|
-
)
|
34
|
+
@fetcher = Carnivore::Files::Util::Fetcher::Nio.new(args)
|
30
35
|
else
|
31
|
-
|
32
|
-
args.merge(:notify_actor => current_actor)
|
33
|
-
)
|
36
|
+
@fetcher = Carnivore::Files::Util::Fetcher::Penguin.new(args)
|
34
37
|
end
|
38
|
+
self.link fetcher
|
39
|
+
fetcher.async.start_fetcher
|
35
40
|
end
|
36
41
|
|
37
|
-
#
|
38
|
-
|
39
|
-
|
42
|
+
# Restart file collector if unexpectedly failed
|
43
|
+
#
|
44
|
+
# @param object [Actor] crashed actor
|
45
|
+
# @param reason [Exception, NilClass]
|
46
|
+
def fetcher_failure(object, reason)
|
47
|
+
if(reason && object == fetcher)
|
48
|
+
error "File message collector unexpectedly failed: #{reason} (restarting)"
|
49
|
+
connect
|
50
|
+
end
|
40
51
|
end
|
41
52
|
|
42
|
-
|
43
|
-
|
44
|
-
|
53
|
+
def fetcher_destroyer
|
54
|
+
if(fetcher && fetcher.alive?)
|
55
|
+
fetcher.terminate
|
56
|
+
end
|
45
57
|
end
|
46
58
|
|
47
59
|
# @return [Array<Hash>] return messages
|
48
60
|
def receive(*args)
|
49
|
-
|
50
|
-
fetcher.return_lines.map do |l|
|
51
|
-
format_message(l)
|
52
|
-
end
|
61
|
+
format_message(Celluloid::Future.new{ fetcher.messages.pop }.value)
|
53
62
|
end
|
54
63
|
|
55
64
|
# Send payload
|
@@ -1,3 +1,5 @@
|
|
1
|
+
require 'carnivore-files'
|
2
|
+
|
1
3
|
module Carnivore
|
2
4
|
module Files
|
3
5
|
# Helper utilities
|
@@ -15,10 +17,8 @@ module Carnivore
|
|
15
17
|
attr_reader :path
|
16
18
|
# @return [String] string to split messages on
|
17
19
|
attr_reader :delimiter
|
18
|
-
# @return [Celluloid::Actor] actor to notify on new messages
|
19
|
-
attr_reader :notify_actor
|
20
20
|
|
21
|
-
# @return [
|
21
|
+
# @return [Queue] messages
|
22
22
|
attr_accessor :messages
|
23
23
|
# @return [IO] underlying IO instance
|
24
24
|
attr_accessor :io
|
@@ -33,29 +33,12 @@ module Carnivore
|
|
33
33
|
@leftover = ''
|
34
34
|
@path = ::File.expand_path(args[:path])
|
35
35
|
@delimiter = args.fetch(:delimiter, "\n")
|
36
|
-
@
|
37
|
-
@messages = []
|
36
|
+
@messages = Queue.new
|
38
37
|
end
|
39
38
|
|
40
39
|
# Start the line fetcher
|
41
40
|
def start_fetcher
|
42
|
-
|
43
|
-
loop do
|
44
|
-
build_socket
|
45
|
-
messages = nil
|
46
|
-
selector.select.each do |mon|
|
47
|
-
self.messages += retrieve_lines
|
48
|
-
end
|
49
|
-
notify_actor.signal(:new_logs_lines) unless self.messages.empty?
|
50
|
-
end
|
51
|
-
end
|
52
|
-
end
|
53
|
-
|
54
|
-
# @return [Array<String>] current lines
|
55
|
-
def return_lines
|
56
|
-
msgs = messages.dup
|
57
|
-
messages.clear
|
58
|
-
msgs
|
41
|
+
raise NotImplementedError
|
59
42
|
end
|
60
43
|
|
61
44
|
# Write line to IO
|
@@ -84,6 +67,31 @@ module Carnivore
|
|
84
67
|
end
|
85
68
|
end
|
86
69
|
|
70
|
+
# Build the IO and monitor
|
71
|
+
#
|
72
|
+
# @return [TrueClass, FalseClass]
|
73
|
+
def build_io
|
74
|
+
unless(io)
|
75
|
+
if(::File.exists?(path))
|
76
|
+
@io = ::File.open(path, 'r')
|
77
|
+
unless(@waited)
|
78
|
+
@io.seek(0, ::IO::SEEK_END) # fast-forward to EOF
|
79
|
+
else
|
80
|
+
@waited = false
|
81
|
+
retrieve_lines.each do |l|
|
82
|
+
self.messages << l
|
83
|
+
end
|
84
|
+
end
|
85
|
+
else
|
86
|
+
wait_for_file
|
87
|
+
build_io
|
88
|
+
end
|
89
|
+
true
|
90
|
+
else
|
91
|
+
false
|
92
|
+
end
|
93
|
+
end
|
94
|
+
|
87
95
|
end
|
88
96
|
end
|
89
97
|
end
|
@@ -26,14 +26,13 @@ module Carnivore
|
|
26
26
|
|
27
27
|
# Start the fetcher
|
28
28
|
def start_fetcher
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
self.messages
|
29
|
+
loop do
|
30
|
+
build_io
|
31
|
+
messages = nil
|
32
|
+
Celluloid::Future.new{ selector.select }.value.each do |mon|
|
33
|
+
retrieve_lines.each do |l|
|
34
|
+
self.messages << l
|
35
35
|
end
|
36
|
-
notify_actor.signal(:new_log_lines) unless self.messages.empty?
|
37
36
|
end
|
38
37
|
end
|
39
38
|
end
|
@@ -46,6 +45,7 @@ module Carnivore
|
|
46
45
|
begin
|
47
46
|
unless(io.stat.ino == ::File.stat(path).ino)
|
48
47
|
destroy_io
|
48
|
+
@waited = true
|
49
49
|
end
|
50
50
|
rescue Errno::ENOENT
|
51
51
|
destroy_io
|
@@ -57,19 +57,11 @@ module Carnivore
|
|
57
57
|
#
|
58
58
|
# @return [TrueClass]
|
59
59
|
def build_io
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
@io = ::File.open(path, 'r')
|
64
|
-
@io.seek(0, ::IO::SEEK_END) # fast-forward to EOF
|
65
|
-
end
|
66
|
-
@monitor = selector.register(io, :r)
|
67
|
-
else
|
68
|
-
wait_for_file
|
69
|
-
build_io
|
70
|
-
end
|
60
|
+
result = super
|
61
|
+
if(result && @monitor.nil?)
|
62
|
+
@monitor = selector.register(io, :r)
|
71
63
|
end
|
72
|
-
|
64
|
+
result
|
73
65
|
end
|
74
66
|
|
75
67
|
# Destroy the IO instance and monitor
|
@@ -93,6 +85,7 @@ module Carnivore
|
|
93
85
|
def wait_for_file
|
94
86
|
warn "Waiting for file to appear (#{path})"
|
95
87
|
until(::File.exists?(path))
|
88
|
+
@waited = true
|
96
89
|
sleep(5)
|
97
90
|
end
|
98
91
|
info "File has appeared (#{path})!"
|
@@ -24,41 +24,41 @@ module Carnivore
|
|
24
24
|
|
25
25
|
# Start the fetcher
|
26
26
|
def start_fetcher
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
self.messages
|
35
|
-
when :MOVE_SELF, :DELETE_SELF, :ATTRIB
|
36
|
-
destroy_io
|
27
|
+
loop do
|
28
|
+
build_io
|
29
|
+
notify.each do |event|
|
30
|
+
Celluloid::Future.new{ event.events }.value.each do |ev|
|
31
|
+
case ev
|
32
|
+
when :MODIFY
|
33
|
+
retrieve_lines.each do |l|
|
34
|
+
self.messages << l
|
37
35
|
end
|
36
|
+
when :MOVE_SELF, :DELETE_SELF, :ATTRIB
|
37
|
+
info "Destroying file IO due to FS modification! (#{ev.inspect})"
|
38
|
+
destroy_io
|
39
|
+
@waited = true
|
40
|
+
break
|
41
|
+
else
|
42
|
+
debug "Received unhandled event: #{ev.inspect}"
|
38
43
|
end
|
39
|
-
notify_actor.signal(:new_log_lines) unless messages.empty?
|
40
44
|
end
|
45
|
+
break unless io
|
41
46
|
end
|
42
47
|
end
|
43
48
|
end
|
44
49
|
|
50
|
+
|
45
51
|
private
|
46
52
|
|
47
53
|
# Build the IO and monitor
|
48
54
|
#
|
49
|
-
# @return [TrueClass]
|
55
|
+
# @return [TrueClass, FalseClass]
|
50
56
|
def build_io
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
@io = ::File.open(path, 'r')
|
55
|
-
@io.seek(0, ::IO::SEEK_END) # fast-forward to EOF
|
56
|
-
else
|
57
|
-
wait_for_file
|
58
|
-
build_io
|
59
|
-
end
|
57
|
+
result = super
|
58
|
+
if(result)
|
59
|
+
notify_descriptors[:file_watch] = notify.add_watch(path, :ALL_EVENTS)
|
60
60
|
end
|
61
|
-
|
61
|
+
result
|
62
62
|
end
|
63
63
|
|
64
64
|
# Destroy the IO and monitor
|
@@ -84,13 +84,12 @@ module Carnivore
|
|
84
84
|
notify_descriptors[:file_wait] = notify.add_watch(directory, :OPEN)
|
85
85
|
until(notified)
|
86
86
|
warn "Waiting for file to appear (#{path})"
|
87
|
-
event = notify.take
|
88
|
-
|
89
|
-
notified = ::File.expand_path(event.name) == path
|
90
|
-
end
|
87
|
+
event = Celluloid::Future.new{ notify.take }.value
|
88
|
+
notified = ::File.exists?(path)
|
91
89
|
end
|
92
90
|
notify.rm_watch(notify_descriptors.delete(:file_wait))
|
93
91
|
end
|
92
|
+
@waited = true
|
94
93
|
info "File has appeared (#{path})!"
|
95
94
|
end
|
96
95
|
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: carnivore-files
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.2.
|
4
|
+
version: 0.2.2
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Chris Roberts
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2015-02-02 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: carnivore
|
@@ -38,6 +38,20 @@ dependencies:
|
|
38
38
|
- - ">="
|
39
39
|
- !ruby/object:Gem::Version
|
40
40
|
version: '0'
|
41
|
+
- !ruby/object:Gem::Dependency
|
42
|
+
name: nio4r
|
43
|
+
requirement: !ruby/object:Gem::Requirement
|
44
|
+
requirements:
|
45
|
+
- - ">="
|
46
|
+
- !ruby/object:Gem::Version
|
47
|
+
version: '0'
|
48
|
+
type: :runtime
|
49
|
+
prerelease: false
|
50
|
+
version_requirements: !ruby/object:Gem::Requirement
|
51
|
+
requirements:
|
52
|
+
- - ">="
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
version: '0'
|
41
55
|
description: Carnivore file source
|
42
56
|
email: code@chrisroberts.org
|
43
57
|
executables: []
|