iyyov 1.0.0-java

Sign up to get free protection for your applications and to get access to all the features.
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