iyyov 1.0.0-java
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/History.rdoc +2 -0
- data/Manifest.txt +18 -0
- data/README.rdoc +31 -0
- data/Rakefile +53 -0
- data/bin/iyyov-fg +63 -0
- data/init/iyyov-daemon +34 -0
- data/lib/iyyov/base.rb +20 -0
- data/lib/iyyov/context.rb +205 -0
- data/lib/iyyov/daemon.rb +348 -0
- data/lib/iyyov/errors.rb +19 -0
- data/lib/iyyov/log_rotator.rb +99 -0
- data/lib/iyyov/scheduler.rb +120 -0
- data/lib/iyyov/shutdown_handler.rb +46 -0
- data/lib/iyyov/task.rb +179 -0
- data/lib/iyyov.rb +78 -0
- data/test/setup.rb +50 -0
- data/test/test_daemon.rb +89 -0
- data/test/test_scheduler.rb +75 -0
- metadata +143 -0
data/History.rdoc
ADDED
data/Manifest.txt
ADDED
@@ -0,0 +1,18 @@
|
|
1
|
+
Manifest.txt
|
2
|
+
History.rdoc
|
3
|
+
README.rdoc
|
4
|
+
Rakefile
|
5
|
+
bin/iyyov-fg
|
6
|
+
init/iyyov-daemon
|
7
|
+
lib/iyyov/base.rb
|
8
|
+
lib/iyyov.rb
|
9
|
+
lib/iyyov/context.rb
|
10
|
+
lib/iyyov/daemon.rb
|
11
|
+
lib/iyyov/errors.rb
|
12
|
+
lib/iyyov/log_rotator.rb
|
13
|
+
lib/iyyov/scheduler.rb
|
14
|
+
lib/iyyov/shutdown_handler.rb
|
15
|
+
lib/iyyov/task.rb
|
16
|
+
test/setup.rb
|
17
|
+
test/test_daemon.rb
|
18
|
+
test/test_scheduler.rb
|
data/README.rdoc
ADDED
@@ -0,0 +1,31 @@
|
|
1
|
+
= Iyyov
|
2
|
+
|
3
|
+
* http://github.com/dekellum/iyyov
|
4
|
+
* http://en.wikipedia.org/wiki/Iyyov
|
5
|
+
* http://gravitext.com/#vblog
|
6
|
+
|
7
|
+
== Description
|
8
|
+
|
9
|
+
Down-to-earth job control and monitoring. Features include:
|
10
|
+
|
11
|
+
* Runs on JRuby (no fork)
|
12
|
+
* Ruby-based configuration
|
13
|
+
* Gem packaged/Hashdot daemon based launching
|
14
|
+
* Log rotation with daemon SIGHUP support
|
15
|
+
* Fixed and periodic time job scheduling (basic cron replacement).
|
16
|
+
|
17
|
+
== License
|
18
|
+
|
19
|
+
Copyright (c) 2010 David Kellum
|
20
|
+
|
21
|
+
Licensed under the Apache License, Version 2.0 (the "License"); you
|
22
|
+
may not use this file except in compliance with the License. You
|
23
|
+
may obtain a copy of the License at:
|
24
|
+
|
25
|
+
http://www.apache.org/licenses/LICENSE-2.0
|
26
|
+
|
27
|
+
Unless required by applicable law or agreed to in writing, software
|
28
|
+
distributed under the License is distributed on an "AS IS" BASIS,
|
29
|
+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
|
30
|
+
implied. See the License for the specific language governing
|
31
|
+
permissions and limitations under the License.
|
data/Rakefile
ADDED
@@ -0,0 +1,53 @@
|
|
1
|
+
# -*- ruby -*-
|
2
|
+
#--
|
3
|
+
# Copyright (C) 2010 David Kellum
|
4
|
+
#
|
5
|
+
# Licensed under the Apache License, Version 2.0 (the "License"); you
|
6
|
+
# may not use this file except in compliance with the License. You
|
7
|
+
# may obtain a copy of the License at
|
8
|
+
#
|
9
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
10
|
+
#
|
11
|
+
# Unless required by applicable law or agreed to in writing, software
|
12
|
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
13
|
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
|
14
|
+
# implied. See the License for the specific language governing
|
15
|
+
# permissions and limitations under the License.
|
16
|
+
#++
|
17
|
+
|
18
|
+
$LOAD_PATH << './lib'
|
19
|
+
|
20
|
+
require 'rubygems'
|
21
|
+
gem 'rjack-tarpit', '~> 1.2.0'
|
22
|
+
require 'rjack-tarpit'
|
23
|
+
|
24
|
+
require 'iyyov/base'
|
25
|
+
|
26
|
+
t = RJack::TarPit.new( 'iyyov', Iyyov::VERSION, :java_platform )
|
27
|
+
|
28
|
+
t.specify do |h|
|
29
|
+
h.developer( 'David Kellum', 'dek-oss@gravitext.com' )
|
30
|
+
h.testlib = :minitest
|
31
|
+
h.extra_deps += [ [ 'rjack-sfl4j', '~> 1.5.11' ],
|
32
|
+
[ 'rjack-logback', '~> 0.9.18' ],
|
33
|
+
[ 'logrotate', '= 1.2.1' ] ]
|
34
|
+
h.extra_dev_deps += [ [ 'minitest', '~> 1.5.0' ],
|
35
|
+
[ 'hashdot-test-daemon', '>= 1.0.0' ] ]
|
36
|
+
end
|
37
|
+
|
38
|
+
task :check_init_version do
|
39
|
+
t.test_line_match( 'init/iyyov-daemon',
|
40
|
+
/^gem.+#{t.name}/, /= #{t.version}/ )
|
41
|
+
end
|
42
|
+
task :check_history_version do
|
43
|
+
t.test_line_match( 'History.rdoc', /^==/, / #{t.version} / )
|
44
|
+
end
|
45
|
+
task :check_history_date do
|
46
|
+
t.test_line_match( 'History.rdoc', /^==/, /\([0-9\-]+\)$/ )
|
47
|
+
end
|
48
|
+
|
49
|
+
task :gem => [ :check_init_version, :check_history_version ]
|
50
|
+
task :tag => [ :check_init_version, :check_history_version, :check_history_date ]
|
51
|
+
task :push => [ :check_history_date ]
|
52
|
+
|
53
|
+
t.define_tasks
|
data/bin/iyyov-fg
ADDED
@@ -0,0 +1,63 @@
|
|
1
|
+
#!/usr/bin/env jruby
|
2
|
+
# -*- ruby -*-
|
3
|
+
#. hashdot.vm.options += -Xmx64m
|
4
|
+
#. hashdot.vm.options += -XX:+UseConcMarkSweepGC -XX:+CMSClassUnloadingEnabled
|
5
|
+
|
6
|
+
#--
|
7
|
+
# Copyright (C) 2010 David Kellum
|
8
|
+
#
|
9
|
+
# Licensed under the Apache License, Version 2.0 (the "License"); you
|
10
|
+
# may not use this file except in compliance with the License. You
|
11
|
+
# may obtain a copy of the License at
|
12
|
+
#
|
13
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
14
|
+
#
|
15
|
+
# Unless required by applicable law or agreed to in writing, software
|
16
|
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
17
|
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
|
18
|
+
# implied. See the License for the specific language governing
|
19
|
+
# permissions and limitations under the License.
|
20
|
+
#++
|
21
|
+
|
22
|
+
$LOAD_PATH.unshift File.join( File.dirname(__FILE__), "..", "lib" )
|
23
|
+
|
24
|
+
require 'rubygems'
|
25
|
+
require 'rjack-logback'
|
26
|
+
|
27
|
+
Logback.config_console( :thread => true, :lwidth => 35,
|
28
|
+
:level => Logback::INFO )
|
29
|
+
|
30
|
+
require 'optparse'
|
31
|
+
require 'iyyov'
|
32
|
+
|
33
|
+
oparser = OptionParser.new do |opts|
|
34
|
+
opts.banner = <<END
|
35
|
+
Usage: iyyov-fg [options] <job-config-files>
|
36
|
+
Run iyyov in foreground for testing job-config-files.
|
37
|
+
Default base_dir for daemons is CWD.
|
38
|
+
Options:
|
39
|
+
END
|
40
|
+
|
41
|
+
opts.on( "-d", "--debug", "Enable debug logging" ) do
|
42
|
+
Logback.root.level = Logback::DEBUG
|
43
|
+
end
|
44
|
+
|
45
|
+
opts.on( "-v", "--version", "Show version and exit" ) do
|
46
|
+
puts "Iyyov (#{$0}) version: #{ Iyyov::VERSION }"
|
47
|
+
exit
|
48
|
+
end
|
49
|
+
|
50
|
+
end
|
51
|
+
|
52
|
+
oparser.parse!
|
53
|
+
|
54
|
+
if ARGV.empty?
|
55
|
+
puts oparser.help
|
56
|
+
exit 1
|
57
|
+
end
|
58
|
+
|
59
|
+
Iyyov.run( ARGV ) do |c|
|
60
|
+
# iyyov-fg specific defaults
|
61
|
+
c.base_dir = '.'
|
62
|
+
c.stop_on_exit = true
|
63
|
+
end
|
data/init/iyyov-daemon
ADDED
@@ -0,0 +1,34 @@
|
|
1
|
+
#!/usr/bin/env jruby
|
2
|
+
#-*- ruby -*-
|
3
|
+
#. hashdot.profile += daemon
|
4
|
+
#. hashdot.pid_file = ./iyyov-daemon.pid
|
5
|
+
#. hashdot.io_redirect.file = ./iyyov-daemon.log
|
6
|
+
#. hashdot.vm.options += -Xmx64m
|
7
|
+
#. hashdot.vm.options += -XX:+UseConcMarkSweepGC -XX:+CMSClassUnloadingEnabled
|
8
|
+
|
9
|
+
#--
|
10
|
+
# Copyright (C) 2010 David Kellum
|
11
|
+
#
|
12
|
+
# Licensed under the Apache License, Version 2.0 (the "License"); you
|
13
|
+
# may not use this file except in compliance with the License. You
|
14
|
+
# may obtain a copy of the License at
|
15
|
+
#
|
16
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
17
|
+
#
|
18
|
+
# Unless required by applicable law or agreed to in writing, software
|
19
|
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
20
|
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
|
21
|
+
# implied. See the License for the specific language governing
|
22
|
+
# permissions and limitations under the License.
|
23
|
+
#++
|
24
|
+
|
25
|
+
require 'rubygems'
|
26
|
+
|
27
|
+
gem( "iyyov", "= 1.0.0" )
|
28
|
+
|
29
|
+
require 'rjack-logback'
|
30
|
+
RJack::Logback.config_console( :full => true, :thread => true )
|
31
|
+
|
32
|
+
require 'iyyov'
|
33
|
+
|
34
|
+
Iyyov.run( ARGV )
|
data/lib/iyyov/base.rb
ADDED
@@ -0,0 +1,20 @@
|
|
1
|
+
#--
|
2
|
+
# Copyright (C) 2010 David Kellum
|
3
|
+
#
|
4
|
+
# Licensed under the Apache License, Version 2.0 (the "License"); you
|
5
|
+
# may not use this file except in compliance with the License. You
|
6
|
+
# may obtain a copy of the License at
|
7
|
+
#
|
8
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
9
|
+
#
|
10
|
+
# Unless required by applicable law or agreed to in writing, software
|
11
|
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
12
|
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
|
13
|
+
# implied. See the License for the specific language governing
|
14
|
+
# permissions and limitations under the License.
|
15
|
+
#++
|
16
|
+
|
17
|
+
module Iyyov
|
18
|
+
# Iyyov version
|
19
|
+
VERSION = '1.0.0'
|
20
|
+
end
|
@@ -0,0 +1,205 @@
|
|
1
|
+
#--
|
2
|
+
# Copyright (C) 2010 David Kellum
|
3
|
+
#
|
4
|
+
# Licensed under the Apache License, Version 2.0 (the "License"); you
|
5
|
+
# may not use this file except in compliance with the License. You
|
6
|
+
# may obtain a copy of the License at
|
7
|
+
#
|
8
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
9
|
+
#
|
10
|
+
# Unless required by applicable law or agreed to in writing, software
|
11
|
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
12
|
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
|
13
|
+
# implied. See the License for the specific language governing
|
14
|
+
# permissions and limitations under the License.
|
15
|
+
#++
|
16
|
+
|
17
|
+
require 'rjack-slf4j'
|
18
|
+
require 'fileutils'
|
19
|
+
|
20
|
+
require 'iyyov/errors'
|
21
|
+
require 'iyyov/task'
|
22
|
+
require 'iyyov/scheduler'
|
23
|
+
require 'iyyov/daemon'
|
24
|
+
|
25
|
+
module Iyyov
|
26
|
+
|
27
|
+
class Context
|
28
|
+
|
29
|
+
# Default base directory under which Daemon run directories are found
|
30
|
+
#
|
31
|
+
# ~to_s (default: /opt/var)
|
32
|
+
attr_accessor :base_dir
|
33
|
+
|
34
|
+
# Default whether to make Daemon run directories if not already present.
|
35
|
+
#
|
36
|
+
# Boolean (default: true)
|
37
|
+
attr_accessor :make_run_dir
|
38
|
+
|
39
|
+
# Default whether to stop Daemons on Iyyov exit.
|
40
|
+
#
|
41
|
+
# Boolean (default: false)
|
42
|
+
attr_accessor :stop_on_exit
|
43
|
+
|
44
|
+
# Default duration in seconds between SIGTERM and final SIGKILL when
|
45
|
+
# stopping Daemons.
|
46
|
+
#
|
47
|
+
# Numeric (default: 30.0)
|
48
|
+
attr_accessor :stop_delay
|
49
|
+
|
50
|
+
# Watch loaded config files for changes?
|
51
|
+
#
|
52
|
+
# Boolean (default: true)
|
53
|
+
attr_accessor :watch_files
|
54
|
+
|
55
|
+
attr_reader :scheduler
|
56
|
+
attr_reader :daemons
|
57
|
+
|
58
|
+
def initialize
|
59
|
+
@base_dir = "/opt/var"
|
60
|
+
@make_run_dir = true
|
61
|
+
@stop_on_exit = false
|
62
|
+
@stop_delay = 30.0
|
63
|
+
@watch_files = true
|
64
|
+
|
65
|
+
#FIXME: Support other gem home than ours?
|
66
|
+
|
67
|
+
@rotators = {}
|
68
|
+
@daemons = {}
|
69
|
+
@state = :begin
|
70
|
+
@log = RJack::SLF4J[ self.class ]
|
71
|
+
@scheduler = Scheduler.new
|
72
|
+
@scheduler.on_exit { do_shutdown }
|
73
|
+
@files = {}
|
74
|
+
@root_files = []
|
75
|
+
|
76
|
+
# By default with potential for override
|
77
|
+
iyyov_log_rotate
|
78
|
+
|
79
|
+
yield self if block_given?
|
80
|
+
end
|
81
|
+
|
82
|
+
def shutdown
|
83
|
+
do_shutdown
|
84
|
+
@scheduler.off_exit
|
85
|
+
end
|
86
|
+
|
87
|
+
def do_shutdown
|
88
|
+
unless @state == :shutdown
|
89
|
+
@log.info "Shutting down"
|
90
|
+
@daemons.values.each { |d| d.do_exit }
|
91
|
+
@state = :shutdown
|
92
|
+
end
|
93
|
+
end
|
94
|
+
|
95
|
+
# Setup log rotation not associated with a daemon
|
96
|
+
def log_rotate( &block )
|
97
|
+
lr = LogRotator.new( nil, &block )
|
98
|
+
@rotators[ lr.log ] = lr
|
99
|
+
end
|
100
|
+
|
101
|
+
# Setup log rotation for the iyyov daemon itself
|
102
|
+
def iyyov_log_rotate( &block )
|
103
|
+
rf = Java::java.lang.System.get_property( "hashdot.io_redirect.file" )
|
104
|
+
if rf && File.exist?( rf )
|
105
|
+
lr = LogRotator.new( rf, &block )
|
106
|
+
lr.pid = 0
|
107
|
+
@rotators[ lr.log ] = lr
|
108
|
+
end
|
109
|
+
end
|
110
|
+
|
111
|
+
def schedule_at( opts = {}, &block )
|
112
|
+
t = Task.new( opts, &block )
|
113
|
+
@scheduler.add( t )
|
114
|
+
end
|
115
|
+
|
116
|
+
def define_daemon( &block )
|
117
|
+
d = Daemon.new( self, &block )
|
118
|
+
if @daemons.has_key?( d.full_name )
|
119
|
+
raise( SetupError,
|
120
|
+
"Can't define daemon with duplicate full_name = #{d.full_name}" )
|
121
|
+
end
|
122
|
+
@daemons[ d.full_name ] = d
|
123
|
+
nil
|
124
|
+
end
|
125
|
+
|
126
|
+
def load_file( file, is_root = false )
|
127
|
+
@log.info { "Loading #{file}" }
|
128
|
+
begin
|
129
|
+
load file
|
130
|
+
@files[ file ] = File.stat( file ).mtime
|
131
|
+
@root_files << file if is_root
|
132
|
+
true
|
133
|
+
rescue SetupError, ScriptError, StandardError => e
|
134
|
+
@log.error( "On load of #{file}", e )
|
135
|
+
false
|
136
|
+
end
|
137
|
+
end
|
138
|
+
|
139
|
+
def register_rotator_tasks
|
140
|
+
@rotators.values.each do |lr|
|
141
|
+
t = Task.new( :name => rotate_name( lr.log ),
|
142
|
+
:mode => :async,
|
143
|
+
:period => lr.check_period ) do
|
144
|
+
lr.check_rotate do |rlog|
|
145
|
+
@log.info { "Rotating log #{rlog}" }
|
146
|
+
end
|
147
|
+
end
|
148
|
+
@scheduler.add( t )
|
149
|
+
end
|
150
|
+
end
|
151
|
+
|
152
|
+
def register_files_watch_task
|
153
|
+
return unless @watch_files && ! @files.empty?
|
154
|
+
t = Task.new( :name => "watch-files", :period => 11.0 ) do
|
155
|
+
reload = false
|
156
|
+
@files.each do |fname, last_time|
|
157
|
+
begin
|
158
|
+
new_time = File.stat( fname ).mtime
|
159
|
+
if new_time != last_time
|
160
|
+
@log.info { "#{fname} has new modification time, reloading." }
|
161
|
+
reload = true
|
162
|
+
break
|
163
|
+
end
|
164
|
+
rescue Errno::ENOENT, Errno::EACCES => e
|
165
|
+
@log.error( e.to_s )
|
166
|
+
end
|
167
|
+
end
|
168
|
+
rc = :continue
|
169
|
+
if reload
|
170
|
+
@log.info { "Rescaning gems." }
|
171
|
+
Gem.clear_paths
|
172
|
+
if Iyyov.load_root_files( @root_files )
|
173
|
+
@log.info "Load passed, shutdown"
|
174
|
+
rc = :shutdown
|
175
|
+
end
|
176
|
+
end
|
177
|
+
rc
|
178
|
+
end
|
179
|
+
@scheduler.add( t )
|
180
|
+
end
|
181
|
+
|
182
|
+
def start_and_register_daemons
|
183
|
+
@daemons.values.each { |d| d.do_first( @scheduler ) }
|
184
|
+
end
|
185
|
+
|
186
|
+
def rotate_name( log_file )
|
187
|
+
"#{ File.basename( log_file, ".log" ) }.rotate"
|
188
|
+
end
|
189
|
+
|
190
|
+
def event_loop
|
191
|
+
@state = :starting
|
192
|
+
start_and_register_daemons
|
193
|
+
register_rotator_tasks
|
194
|
+
register_files_watch_task
|
195
|
+
|
196
|
+
@log.debug "Event loop starting"
|
197
|
+
@state = :running
|
198
|
+
rc = @scheduler.event_loop
|
199
|
+
@state = :exit
|
200
|
+
@log.debug { "Event loop exited: #{rc.inspect}" }
|
201
|
+
rc
|
202
|
+
end
|
203
|
+
end
|
204
|
+
|
205
|
+
end
|