carnivore-files 0.2.0 → 0.2.2
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.
- 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: []
|