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 ADDED
@@ -0,0 +1,2 @@
1
+ === 1.0.0 (2010-3-7)
2
+ * Initial release.
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