xli-dtr 0.0.5 → 1.0.0

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.
Files changed (76) hide show
  1. data/CHANGES +7 -0
  2. data/README.rdoc +208 -0
  3. data/Rakefile +54 -63
  4. data/TODO +7 -16
  5. data/bin/dtr +26 -20
  6. data/dtr.gemspec +7 -10
  7. data/lib/dtr/agent/brain.rb +13 -22
  8. data/lib/dtr/agent/herald.rb +24 -14
  9. data/lib/dtr/agent/runner.rb +22 -35
  10. data/lib/dtr/agent/sync_codebase.rb +1 -1
  11. data/lib/dtr/agent/sync_logger.rb +38 -8
  12. data/lib/dtr/agent/test_case.rb +53 -0
  13. data/lib/dtr/agent/test_unit.rb +3 -5
  14. data/lib/dtr/agent/worker.rb +29 -32
  15. data/lib/dtr/agent/working_env_ext.rb +4 -2
  16. data/lib/dtr/agent.rb +2 -1
  17. data/lib/dtr/facade.rb +65 -0
  18. data/lib/dtr/master.rb +3 -3
  19. data/lib/dtr/monitor.rb +69 -11
  20. data/lib/dtr/raketasks.rb +91 -19
  21. data/lib/dtr/shared/adapter.rb +29 -26
  22. data/lib/dtr/shared/configuration.rb +39 -11
  23. data/lib/dtr/shared/message_decorator.rb +1 -1
  24. data/lib/dtr/shared/ruby_ext.rb +1 -25
  25. data/lib/dtr/shared/service/agent.rb +5 -1
  26. data/lib/dtr/shared/service/file.rb +1 -1
  27. data/lib/dtr/shared/service/rinda.rb +11 -3
  28. data/lib/dtr/shared/service/runner.rb +6 -5
  29. data/lib/dtr/shared/service/working_env.rb +1 -1
  30. data/lib/dtr/shared/service.rb +1 -1
  31. data/lib/dtr/shared/sync_codebase/{codebase.rb → copiable_package.rb} +13 -5
  32. data/lib/dtr/shared/sync_codebase/master_ext.rb +6 -18
  33. data/lib/dtr/shared/sync_codebase/package.rb +16 -2
  34. data/lib/dtr/shared/sync_codebase/sync_service.rb +7 -12
  35. data/lib/dtr/shared/sync_codebase.rb +2 -2
  36. data/lib/dtr/shared/sync_logger.rb +6 -14
  37. data/lib/dtr/shared/utils/cmd.rb +5 -5
  38. data/lib/dtr/shared/utils/env_store.rb +1 -1
  39. data/lib/dtr/shared/utils/logger.rb +33 -17
  40. data/lib/dtr/shared/utils.rb +1 -1
  41. data/lib/dtr/shared/working_env.rb +2 -2
  42. data/lib/dtr/shared.rb +1 -1
  43. data/lib/dtr/test_unit/drb_test_runner.rb +5 -14
  44. data/lib/dtr/test_unit/injection.rb +1 -2
  45. data/lib/dtr/test_unit/test_case_injection.rb +13 -13
  46. data/lib/dtr/test_unit/test_suite_injection.rb +24 -0
  47. data/lib/dtr/test_unit/testrunnermediator_injection.rb +11 -11
  48. data/lib/dtr/test_unit/thread_safe_test_result.rb +1 -3
  49. data/lib/dtr/test_unit/worker_club.rb +7 -7
  50. data/lib/dtr/test_unit.rb +2 -1
  51. data/lib/dtr/test_unit_injection.rb +1 -1
  52. data/lib/dtr.rb +5 -36
  53. data/test/acceptance/agent_working_env_test.rb +28 -34
  54. data/test/acceptance/dtr_package_task_test.rb +13 -3
  55. data/test/acceptance/general_test.rb +139 -83
  56. data/test/acceptance/raketasks_test.rb +23 -0
  57. data/test/acceptance/sync_codebase_test.rb +12 -13
  58. data/test/acceptance/sync_logger_test.rb +12 -21
  59. data/test/agent_helper.rb +8 -10
  60. data/test/logger_stub.rb +4 -0
  61. data/test/test_helper.rb +33 -5
  62. data/test/unit/adapter_test.rb +58 -16
  63. data/test/unit/configuration_test.rb +44 -0
  64. data/test/unit/facade_test.rb +41 -0
  65. data/test/unit/logger_test.rb +72 -0
  66. data/test/unit/test_unit_test.rb +0 -21
  67. data/testdata/Rakefile +1 -5
  68. data/testdata/hacked_run_method_test_case.rb +15 -0
  69. data/testdata/raketasks/Rakefile +7 -0
  70. data/testdata/raketasks/success_test_case.rb +6 -0
  71. data/testdata/sleep_3_secs_test_case.rb +9 -0
  72. data/testdata/{should_not_sync_codebase_and_setup_working_dir_when_agent_is_in_same_dir_with_master_process → verify_dir_pwd}/verify_dir_pwd_test_case.rb +1 -1
  73. metadata +33 -13
  74. data/README +0 -182
  75. data/install.rb +0 -88
  76. /data/testdata/{should_not_sync_codebase_and_setup_working_dir_when_agent_is_in_same_dir_with_master_process → verify_dir_pwd}/Rakefile +0 -0
@@ -1,4 +1,4 @@
1
- # Copyright (c) 2007-2008 Li Xiao
1
+ # Copyright (c) 2007-2008 Li Xiao <iam@li-xiao.com>
2
2
  #
3
3
  # Licensed under the Apache License, Version 2.0 (the "License");
4
4
  # you may not use this file except in compliance with the License.
@@ -16,6 +16,9 @@ module DTR
16
16
 
17
17
  module Agent
18
18
  class Herald
19
+ class WorkingEnvError < StandardError
20
+ end
21
+
19
22
  include Service::WorkingEnv
20
23
  include Service::Agent
21
24
 
@@ -24,26 +27,33 @@ module DTR
24
27
  @agent_env_setup_cmd = agent_env_setup_cmd
25
28
  @runners = runners
26
29
  @env_store = EnvStore.new
30
+ start_service
27
31
  start_off
32
+ ensure
33
+ stop_service
28
34
  end
29
35
 
30
36
  def start_off
31
- start_service
32
- DTR.info "=> Herald starts off..."
37
+ DTR.info {"=> Herald starts off..."}
33
38
  provide_agent_info(@agent_env_setup_cmd, @runners)
34
39
 
40
+ @env_store[@working_env_key] = fetch_working_env
41
+ rescue WorkingEnvError
42
+ DTR.error $!.message
43
+ exit(-1)
44
+ rescue
45
+ DTR.error $!.message
46
+ DTR.error $!.backtrace.join("\n")
47
+ exit(-1)
48
+ end
49
+
50
+ def fetch_working_env
35
51
  working_env = lookup_working_env
36
- DTR.info "=> Got working environment created at #{working_env[:created_at]} by #{working_env[:host]}"
37
- if working_env[:files].blank?
38
- DTR.error "No test files need to load?(working env: #{working_env})"
39
- return
40
- end
41
-
42
- if working_env.setup_env(@agent_env_setup_cmd)
43
- @env_store[@working_env_key] = working_env
44
- else
45
- DTR.info {'Setup working environment failed, no runner started.'}
46
- end
52
+ DTR.info {"=> Got working environment created at #{working_env[:created_at]} by #{working_env[:host]}"}
53
+
54
+ raise WorkingEnvError.new("No test files need to load?(working env: #{working_env})") if working_env[:files].blank?
55
+ raise WorkingEnvError.new('Setup working environment failed, no runner started.') unless working_env.setup_env(@agent_env_setup_cmd)
56
+ working_env
47
57
  end
48
58
  end
49
59
  end
@@ -1,4 +1,4 @@
1
- # Copyright (c) 2007-2008 Li Xiao
1
+ # Copyright (c) 2007-2008 Li Xiao <iam@li-xiao.com>
2
2
  #
3
3
  # Licensed under the Apache License, Version 2.0 (the "License");
4
4
  # you may not use this file except in compliance with the License.
@@ -20,7 +20,6 @@ module DTR
20
20
 
21
21
  def self.start(name, env)
22
22
  self.new(name, env).start
23
- DTR.info "=> Runner #{name} provided"
24
23
  DRb.thread.join if DRb.thread
25
24
  end
26
25
 
@@ -30,8 +29,6 @@ module DTR
30
29
  @name = name
31
30
  @identifier = env[:identifier]
32
31
  @env = env
33
- @started = 0
34
- @run_finished = 0
35
32
  end
36
33
 
37
34
  def start
@@ -39,59 +36,49 @@ module DTR
39
36
  start_service
40
37
  DTR.info("=> Starting runner #{name} at #{Dir.pwd}, pid: #{Process.pid}")
41
38
  init_environment
42
- provide_runner(self)
39
+ provide
40
+ DTR.info {"=> Runner #{name} provided"}
41
+ rescue Exception
42
+ DTR.error($!.message)
43
+ DTR.error($!.backtrace.join("\n"))
43
44
  end
44
45
 
45
46
  def init_environment
46
- DTR.info "#{name}: Initialize working environment..."
47
+ DTR.info {"#{name}: Initialize working environment..."}
48
+ ENV['DTR_RUNNER_NAME'] = name
49
+
47
50
  @env[:libs].select{ |lib| !$LOAD_PATH.include?(lib) && File.exists?(lib) }.each do |lib|
48
51
  $LOAD_PATH << lib
49
- DTR.debug "#{name}: appended lib: #{lib}"
52
+ DTR.debug {"#{name}: appended lib: #{lib}"}
50
53
  end
51
- DTR.info "#{name}: libs loaded"
52
- DTR.debug "#{name}: $LOAD_PATH: #{$LOAD_PATH.inspect}"
54
+ DTR.info {"#{name}: libs loaded"}
55
+ DTR.debug {"#{name}: $LOAD_PATH: #{$LOAD_PATH.inspect}"}
53
56
 
54
57
  @env[:files].each do |f|
55
58
  begin
56
59
  load f unless f =~ /^-/
57
- DTR.debug "#{name}: loaded #{f}"
60
+ DTR.debug {"#{name}: loaded #{f}"}
58
61
  rescue LoadError => e
59
- DTR.error "#{name}: No such file to load -- #{f}"
60
- DTR.debug "Environment: #{@env}"
62
+ DTR.error {"#{name}: No such file to load -- #{f}"}
63
+ DTR.debug {"Environment: #{@env}"}
61
64
  end
62
65
  end
63
- DTR.info "#{name}: test files loaded"
66
+ DTR.info {"#{name}: test files loaded"}
64
67
  end
65
68
 
66
69
  def run(test, result, &progress_block)
67
- DTR.info "#{name}: +"
68
- DTR.debug "#{name}: running #{test}..."
69
- @started += 1
70
- test.run(result, &progress_block)
71
- rescue DRb::DRbConnError => e
72
- DTR.info "Rescued DRb::DRbConnError(#{e.message}), while running test: #{test.name}. The master process may be stopped."
73
- rescue Exception => e
74
- DTR.error "Unexpected exception: #{e.message}"
75
- DTR.error e.backtrace.join("\n")
76
- result.add_error(Test::Unit::Error.new(test.name, e))
77
- result.add_run
78
- progress_block.call(Test::Unit::TestCase::FINISHED, test.name)
70
+ DTR.debug {"#{name}: running #{test}..."}
71
+ Agent::TestCase.new(test, result, &progress_block).run
72
+ DTR.debug {"#{name}: done #{test}"}
79
73
  ensure
80
- DTR.debug "#{name}: done #{test}"
81
- @run_finished += 1
82
- provide_runner(self)
74
+ provide
75
+ DTR.debug {"=> Runner #{name} provided"}
83
76
  end
84
77
 
85
- def reboot
86
- DTR.info "#{self} is rebooting. Ran #{@started} tests, finished #{@run_finished}."
78
+ def provide
87
79
  provide_runner(self)
88
80
  end
89
81
 
90
- def shutdown
91
- DTR.info "#{self} is shutting down. Ran #{@started} tests, finished #{@run_finished}."
92
- stop_service rescue exit!
93
- end
94
-
95
82
  def to_s
96
83
  "Runner #{@name}"
97
84
  end
@@ -1,4 +1,4 @@
1
- # Copyright (c) 2007-2008 Li Xiao
1
+ # Copyright (c) 2007-2008 Li Xiao <iam@li-xiao.com>
2
2
  #
3
3
  # Licensed under the Apache License, Version 2.0 (the "License");
4
4
  # you may not use this file except in compliance with the License.
@@ -1,4 +1,4 @@
1
- # Copyright (c) 2007-2008 Li Xiao
1
+ # Copyright (c) 2007-2008 Li Xiao <iam@li-xiao.com>
2
2
  #
3
3
  # Licensed under the Apache License, Version 2.0 (the "License");
4
4
  # you may not use this file except in compliance with the License.
@@ -15,12 +15,12 @@
15
15
  module DTR
16
16
  module SyncLogger
17
17
 
18
- # Synchronizer loads SyncLogger from master process
19
- # Any process need sync logs with master process should start service first.
20
- # For logs would be sent back to master process, output log code should use
21
- # message string instead of block, for example:
22
- # right: DTR.debug 'message'
23
- # not: DTR.debug { 'message' }
18
+ # Synchronizer loads SyncLogger provided by master process from Rinda server.
19
+ # Any process need sync logs with master process should start service first,
20
+ # so that local logger could be replaced by SyncLogger.
21
+ # For logs would be sent back to master process, all messages would be sent
22
+ # as string message. The message logged as block would be converted to string
23
+ # message.
24
24
  module Synchronizer
25
25
  def self.included(base)
26
26
  base.alias_method_chain :start_service, :sync_logger
@@ -30,10 +30,40 @@ module DTR
30
30
  start_service_without_sync_logger
31
31
  if logger_tuple = lookup_ring.read_all([:logger, nil]).first
32
32
  sync_logger = logger_tuple[1]
33
- DTR.logger = sync_logger
33
+ DTR.logger = MessageDecoratedLogger.new(sync_logger)
34
34
  end
35
35
  end
36
36
  end
37
+
38
+ class MessageDecoratedLogger
39
+ include MessageDecorator
40
+
41
+ def initialize(logger)
42
+ @logger = logger
43
+ end
44
+
45
+ def debug(message=nil, &block)
46
+ with_decorating_message(:debug, message, &block)
47
+ end
48
+
49
+ def info(message=nil, &block)
50
+ with_decorating_message(:info, message, &block)
51
+ end
52
+
53
+ def error(message=nil, &block)
54
+ with_decorating_message(:error, message, &block)
55
+ end
56
+
57
+ def level
58
+ @logger_level ||= @logger.level
59
+ end
60
+
61
+ private
62
+ def with_decorating_message(level, msg, &block)
63
+ raise 'Should not use block to send log remotely' if block_given?
64
+ @logger.send(level, decorate_message(msg))
65
+ end
66
+ end
37
67
  end
38
68
 
39
69
  Service::Rinda.send(:include, SyncLogger::Synchronizer)
@@ -0,0 +1,53 @@
1
+ # Copyright (c) 2007-2008 Li Xiao <iam@li-xiao.com>
2
+ #
3
+ # Licensed under the Apache License, Version 2.0 (the "License");
4
+ # you may not use this file except in compliance with the License.
5
+ # You may obtain a copy of the License at
6
+ #
7
+ # http://www.apache.org/licenses/LICENSE-2.0
8
+ #
9
+ # Unless required by applicable law or agreed to in writing, software
10
+ # distributed under the License is distributed on an "AS IS" BASIS,
11
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
+ # See the License for the specific language governing permissions and
13
+ # limitations under the License.
14
+
15
+ module DTR
16
+ module Agent
17
+ class UnknownTestError < StandardError
18
+ end
19
+ class TestCase
20
+ def initialize(test, result, &progress_block)
21
+ @test = test
22
+ @result = result
23
+ @progress_block = progress_block
24
+ end
25
+
26
+ def run
27
+ if @test.is_a?(DRb::DRbUnknown)
28
+ add_error(UnknownTestError.new("No such test loaded: #{@test.name}"))
29
+ else
30
+ @test.run(@result, &@progress_block)
31
+ end
32
+ rescue DRb::DRbConnError => e
33
+ msg = "Rescued DRb::DRbConnError(#{e.message}), while running test: #{test}. The master process may be stopped."
34
+ DTR.do_println(msg)
35
+ DTR.info {msg}
36
+ rescue Exception => e
37
+ unexpected_error(e)
38
+ end
39
+
40
+ def unexpected_error(e)
41
+ DTR.error "Unexpected exception: #{e.message}"
42
+ DTR.error e.backtrace.join("\n")
43
+ add_error(e)
44
+ end
45
+
46
+ def add_error(e)
47
+ @result.add_error(Test::Unit::Error.new(@test.name, RemoteError.new(e)))
48
+ @result.add_run
49
+ @progress_block.call(Test::Unit::TestCase::FINISHED, @test.name)
50
+ end
51
+ end
52
+ end
53
+ end
@@ -1,4 +1,4 @@
1
- # Copyright (c) 2007-2008 Li Xiao
1
+ # Copyright (c) 2007-2008 Li Xiao <iam@li-xiao.com>
2
2
  #
3
3
  # Licensed under the Apache License, Version 2.0 (the "License");
4
4
  # you may not use this file except in compliance with the License.
@@ -35,8 +35,6 @@ module DTR
35
35
  end
36
36
  end
37
37
 
38
+ # set run to true first, so that test auto runner wouldn't work
38
39
  Test::Unit.run = true
39
-
40
- class Test::Unit::TestCase
41
- include DTR::Agent::TestCaseExt
42
- end
40
+ Test::Unit::TestCase.send(:include, DTR::Agent::TestCaseExt)
@@ -1,4 +1,4 @@
1
- # Copyright (c) 2007-2008 Li Xiao
1
+ # Copyright (c) 2007-2008 Li Xiao <iam@li-xiao.com>
2
2
  #
3
3
  # Licensed under the Apache License, Version 2.0 (the "License");
4
4
  # you may not use this file except in compliance with the License.
@@ -15,6 +15,8 @@
15
15
  module DTR
16
16
 
17
17
  module Agent
18
+ # Worker works during one dtr test task running.
19
+ # Worker manages Herald & Runner processes life cycle.
18
20
  class Worker
19
21
  def initialize(runner_names, agent_env_setup_cmd)
20
22
  @runner_names = runner_names.is_a?(Array) ? runner_names : [runner_names.to_s]
@@ -26,13 +28,13 @@ module DTR
26
28
  end
27
29
 
28
30
  def launch
29
- DTR.info "=> Agent worker started at: #{Dir.pwd}, pid: #{Process.pid}"
31
+ DTR.info {"=> Agent worker started at: #{Dir.pwd}, pid: #{Process.pid}"}
30
32
  setup
31
33
  begin
32
34
  run
33
35
  ensure
34
36
  teardown
35
- DTR.info "Agent worker is dieing"
37
+ DTR.info {"Agent worker is dieing"}
36
38
  end
37
39
  end
38
40
 
@@ -42,50 +44,45 @@ module DTR
42
44
  end
43
45
 
44
46
  def teardown
45
- kill_all_runners
47
+ unless @runner_pids.blank?
48
+ @runner_pids.each{ |pid| DTR.kill_process pid }
49
+ DTR.info {"=> All runners(#{@runner_pids.join(", ")}) were killed." }
50
+ @runner_pids = []
51
+ end
46
52
  if @herald
47
- Process.kill 'TERM', @herald rescue nil
53
+ DTR.kill_process @herald
48
54
  @herald = nil
49
- DTR.info "=> Herald is killed."
55
+ DTR.info {"=> Herald is killed."}
50
56
  end
51
57
  end
52
58
 
53
59
  def run
54
- @herald = drb_fork { Herald.new @working_env_key, @agent_env_setup_cmd, @runner_names }
55
- while @env_store[@working_env_key].nil?
56
- sleep(1)
57
- end
60
+ herald
61
+ runners
62
+ DTR.info {"=> All agent worker sub processes exited."}
63
+ end
64
+
65
+ def herald
66
+ @herald = DTR.fork_process { Herald.new @working_env_key, @agent_env_setup_cmd, @runner_names }
67
+ Process.waitpid @herald
68
+ exit(-1) unless $?.exitstatus == 0
69
+ end
70
+
71
+ def runners
58
72
  working_env = @env_store[@working_env_key]
59
73
 
60
74
  @runner_names.each do |name|
61
- @runner_pids << drb_fork {
75
+ @runner_pids << DTR.fork_process {
76
+ at_exit {
77
+ # exit anyway, for DRb may hang on the process to be a deadwalk
78
+ exit!
79
+ }
62
80
  working_env.within do
63
81
  Runner.start name, working_env
64
82
  end
65
83
  }
66
84
  end
67
85
  Process.waitall
68
- DTR.info "=> All agent worker sub processes exited."
69
- end
70
-
71
- def kill_all_runners
72
- unless @runner_pids.blank?
73
- @runner_pids.each{ |pid| Process.kill 'TERM', pid rescue nil }
74
- DTR.info "=> All runners(#{@runner_pids.join(", ")}) were killed."
75
- @runner_pids = []
76
- end
77
- end
78
-
79
- def drb_fork
80
- Process.fork do
81
- begin
82
- yield
83
- rescue Interrupt, SystemExit, SignalException
84
- rescue Exception => e
85
- DTR.error "Worker drb fork is stopped by Exception => #{e.class.name}, message => #{e.message}"
86
- DTR.info e.backtrace.join("\n")
87
- end
88
- end
89
86
  end
90
87
  end
91
88
  end
@@ -1,4 +1,4 @@
1
- # Copyright (c) 2007-2008 Li Xiao
1
+ # Copyright (c) 2007-2008 Li Xiao <iam@li-xiao.com>
2
2
  #
3
3
  # Licensed under the Apache License, Version 2.0 (the "License");
4
4
  # you may not use this file except in compliance with the License.
@@ -14,6 +14,7 @@
14
14
 
15
15
  module DTR
16
16
  module Agent
17
+ # Provides working environment setup beheaviours for Herald & Runner process
17
18
  module WorkingEnvExt
18
19
  def within
19
20
  ENV['DTR_MASTER_ENV'] = self[:dtr_master_env]
@@ -35,7 +36,8 @@ module DTR
35
36
 
36
37
  def working_dir
37
38
  return @working_dir if defined?(@working_dir)
38
- project_name = self[:pwd].length > 20 ? self[:pwd][-20..-1] : self[:pwd]
39
+ project_specific_len = 20
40
+ project_name = self[:pwd].length > project_specific_len ? self[:pwd][-project_specific_len..-1] : self[:pwd]
39
41
  @working_dir = File.join(escape(self[:host]), escape(project_name))
40
42
  FileUtils.mkdir_p(@working_dir)
41
43
  @working_dir
data/lib/dtr/agent.rb CHANGED
@@ -1,4 +1,4 @@
1
- # Copyright (c) 2007-2008 Li Xiao
1
+ # Copyright (c) 2007-2008 Li Xiao <iam@li-xiao.com>
2
2
  #
3
3
  # Licensed under the Apache License, Version 2.0 (the "License");
4
4
  # you may not use this file except in compliance with the License.
@@ -21,6 +21,7 @@ require 'dtr/agent/brain'
21
21
  require 'dtr/agent/worker'
22
22
  require 'dtr/agent/test_unit'
23
23
  require 'dtr/agent/herald'
24
+ require 'dtr/agent/test_case'
24
25
  require 'dtr/agent/runner'
25
26
 
26
27
  module DTR
data/lib/dtr/facade.rb ADDED
@@ -0,0 +1,65 @@
1
+ # Copyright (c) 2007-2008 Li Xiao <iam@li-xiao.com>
2
+ #
3
+ # Licensed under the Apache License, Version 2.0 (the "License");
4
+ # you may not use this file except in compliance with the License.
5
+ # You may obtain a copy of the License at
6
+ #
7
+ # http://www.apache.org/licenses/LICENSE-2.0
8
+ #
9
+ # Unless required by applicable law or agreed to in writing, software
10
+ # distributed under the License is distributed on an "AS IS" BASIS,
11
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
+ # See the License for the specific language governing permissions and
13
+ # limitations under the License.
14
+
15
+ module DTR
16
+ module Facade
17
+ def start_agent
18
+ launch_agent(DTR_AGENT_OPTIONS[:runners], DTR_AGENT_OPTIONS[:agent_env_setup_cmd])
19
+ end
20
+
21
+ def launch_agent(names, setup=nil)
22
+ require 'dtr/agent'
23
+ names = names || "DTR(#{Time.now})"
24
+ DTR::Agent.start(names, setup)
25
+ end
26
+
27
+ def lib_path
28
+ File.expand_path(File.dirname(__FILE__) + '/../')
29
+ end
30
+
31
+ def broadcast_list=(list)
32
+ require 'dtr/shared'
33
+ DTR.configuration.broadcast_list = list
34
+ DTR.configuration.save
35
+ end
36
+
37
+ def agent_listen_port=(port)
38
+ require 'dtr/shared'
39
+ DTR.configuration.agent_listen_port = port
40
+ DTR.configuration.save
41
+ end
42
+
43
+ def group=(group)
44
+ require 'dtr/shared'
45
+ DTR.configuration.group = group
46
+ DTR.configuration.save
47
+ end
48
+
49
+ def monitor
50
+ require 'dtr/monitor'
51
+ DTR.logger('dtr_monitor.log')
52
+ Monitor.new.start
53
+ end
54
+
55
+ # For safe fork & kill sub process, should use Process.kill and Process.fork
56
+ # At least have problem on ruby 1.8.6 114 with Kernel#kill & fork
57
+ def kill_process(pid)
58
+ Process.kill 'TERM', pid rescue nil
59
+ end
60
+
61
+ def fork_process(&block)
62
+ Process.fork(&block)
63
+ end
64
+ end
65
+ end
data/lib/dtr/master.rb CHANGED
@@ -1,4 +1,4 @@
1
- # Copyright (c) 2007-2008 Li Xiao
1
+ # Copyright (c) 2007-2008 Li Xiao <iam@li-xiao.com>
2
2
  #
3
3
  # Licensed under the Apache License, Version 2.0 (the "License");
4
4
  # you may not use this file except in compliance with the License.
@@ -21,8 +21,8 @@ module DTR
21
21
  ActiveRecord::Base.clear_active_connections! rescue nil
22
22
  end
23
23
 
24
- DTR.info ""
25
- DTR.info "--------------------beautiful line--------------------------"
24
+ DTR.info {""}
25
+ DTR.info {"--------------------beautiful line--------------------------"}
26
26
  DTR.info {"Master process started at #{Time.now}"}
27
27
 
28
28
  DTR.configuration.with_rinda_server do
data/lib/dtr/monitor.rb CHANGED
@@ -1,4 +1,4 @@
1
- # Copyright (c) 2007-2008 Li Xiao
1
+ # Copyright (c) 2007-2008 Li Xiao <iam@li-xiao.com>
2
2
  #
3
3
  # Licensed under the Apache License, Version 2.0 (the "License");
4
4
  # you may not use this file except in compliance with the License.
@@ -15,23 +15,81 @@
15
15
  require 'dtr/master'
16
16
 
17
17
  module DTR
18
+
19
+ # Monitor provides a way to monitor agent/master process working status.
18
20
  class Monitor
19
- include Adapter::Master
20
- include Service::Agent
21
- def start
22
- DTR.configuration.with_rinda_server do
23
- monitor_thread = Thread.new do
24
- new_agent_monitor.each { |t| puts t.last.last }
21
+
22
+ class AgentsMonitor
23
+ include Adapter::Master
24
+
25
+ def start
26
+ DTR.fork_process do
27
+ monitor
28
+ end
29
+ end
30
+ def monitor
31
+ DTR.configuration.with_rinda_server do
32
+ with_wakeup_agents do
33
+ begin
34
+ sleep
35
+ rescue Interrupt
36
+ end
37
+ end
25
38
  end
26
- puts "Monitor process started at #{Time.now}"
27
-
28
- with_wakeup_agents do
39
+ end
40
+ end
41
+
42
+ class MasterMonitor
43
+ include Adapter::Follower
44
+ include Service::Agent
45
+
46
+ def start
47
+ DTR.fork_process do
29
48
  begin
30
- monitor_thread.join
49
+ loop do
50
+ monitor
51
+ end
52
+ rescue Errno::EADDRINUSE
53
+ puts "There is DTR agent started on this machine."
54
+ puts "Shutdown it for monitoring working DTR Master info."
31
55
  rescue Interrupt
56
+ ensure
57
+ relax
32
58
  end
33
59
  end
34
60
  end
61
+
62
+ def monitor
63
+ msg, from_host, group = listen
64
+ unless ["127.0.0.1:#{DTR.configuration.rinda_server_port}"].include?(from_host)
65
+ puts "Master process message from #{from_host}: #{msg} for group #{group}"
66
+ ip, port = from_host.split(':')
67
+ with_configuration(ip, port) do
68
+ start_service
69
+ puts "Agents working for #{from_host}: "
70
+ puts all_agents_info.collect{|i| " #{i.strip}"}.join("\n")
71
+ end
72
+ end
73
+ end
74
+
75
+ def with_configuration(ip, port)
76
+ my_port = DTR.configuration.rinda_server_port
77
+ my_broadcast_list = DTR.configuration.broadcast_list
78
+ DTR.configuration.rinda_server_port = port.to_i
79
+ DTR.configuration.broadcast_list = [ip]
80
+ yield
81
+ ensure
82
+ DTR.configuration.broadcast_list = my_broadcast_list
83
+ DTR.configuration.rinda_server_port = my_port
84
+ end
85
+ end
86
+
87
+ def start
88
+ MasterMonitor.new.start
89
+ AgentsMonitor.new.start
90
+ puts "Monitor process started at #{Time.now}"
91
+ Process.waitall
92
+ rescue Interrupt
35
93
  end
36
94
  end
37
95
  end