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
data/lib/dtr/raketasks.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.
@@ -13,22 +13,77 @@
13
13
  # limitations under the License.
14
14
 
15
15
  require "rubygems"
16
- require 'dtr'
17
- require 'dtr/shared/sync_codebase/package'
18
- require 'dtr/shared/ruby_ext'
19
16
  require 'rake'
20
17
  require 'rake/testtask'
21
18
  require 'rake/tasklib'
22
19
 
20
+ require 'dtr'
21
+ require 'dtr/shared/ruby_ext'
22
+ require 'dtr/shared/utils'
23
+ require 'dtr/shared/sync_codebase/package'
24
+
23
25
  module DTR
26
+ # Create tasks that run a set of tests with DTR injected.
27
+ # The TestTask will create the following targets:
28
+ #
29
+ # [<b>:dtr</b>]:
30
+ # Create a task that runs a set of tests by DTR master.
31
+ #
32
+ # [DTR::PackageTask]:
33
+ # Create a packaging task that will package the project into
34
+ # distributable files for running test on remote machine.
35
+ # All test files should be included.
36
+ #
37
+ # Example:
38
+ # require 'dtr/raketasks'
39
+ #
40
+ # DTR::TestTask.new do |t|
41
+ # t.libs << "test"
42
+ # t.test_files = FileList['test/test*.rb']
43
+ # t.verbose = true
44
+ # t.processes = 1 # default is 1
45
+ # t.package_files.include("lib/**/*") # default is FileList["**/*"]
46
+ # t.package_files.include("test/**/*")
47
+ # end
48
+ #
49
+ # This task inherits from Rake::TestTask, and adds 2 DTR specific
50
+ # options: processes and package_files.
51
+ #
24
52
  class TestTask < Rake::TestTask
53
+
54
+ #
55
+ # The option processes is used to start an DTR agent in same directory
56
+ # with master process. The number of processes is the size of runners
57
+ # launched by agent for running tests. If processes is set to 0,
58
+ # then there is no agent started locally.
59
+ # Default is 1.
25
60
  attr_accessor :processes
26
-
61
+
62
+ # List of files to be included in the package for running tests on
63
+ # remote agent.
64
+ # The agent, which starts in same directory on same machine with
65
+ # master process, would skip copying codebase.
66
+ # The default package files is Rake::FileList["**/*"].
67
+ attr_accessor :package_files
68
+
69
+ def initialize(name=:dtr)
70
+ @processes = 1
71
+ @package_files = Rake::FileList.new
72
+ super(name)
73
+ end
74
+
27
75
  def define
76
+ PackageTask.new do |p|
77
+ p.package_files = package_files
78
+ if p.package_files.empty?
79
+ p.package_files.include("**/*")
80
+ end
81
+ end
82
+
28
83
  @libs.unshift DTR.lib_path
29
84
  lib_path = @libs.join(File::PATH_SEPARATOR)
30
85
 
31
- desc "Run tests" + (@name==:test ? "" : " for #{@name}")
86
+ desc "Run tests with DTR injected"
32
87
  task @name do
33
88
  @agent = start_agent
34
89
  run_code = ''
@@ -45,43 +100,59 @@ module DTR
45
100
  end
46
101
  ensure
47
102
  if defined?(@agent)
48
- Process.kill 'TERM', @agent rescue nil
103
+ DTR.kill_process @agent
49
104
  end
50
105
  end
51
106
  end
52
107
  self
53
108
  end
54
-
55
- def processes
56
- @processes ? @processes.to_i : 2
57
- end
58
-
109
+
59
110
  private
60
111
  def start_agent
61
112
  return if self.processes.to_i <= 0
62
113
  runner_names = []
63
114
  self.processes.to_i.times {|i| runner_names << "runner#{i}"}
64
115
 
65
- Process.fork do
116
+ DTR.fork_process do
66
117
  DTR_AGENT_OPTIONS[:runners] = runner_names if DTR_AGENT_OPTIONS[:runners].empty?
67
118
  DTR.start_agent
68
119
  end
69
120
  end
70
121
  end
71
122
 
72
- # The following task is copied & modified from 'rake/packagetask'
123
+ # Create a packaging task that will package the project into
124
+ # distributable files for running test on remote machine.
125
+ # It uses zip and unzip to package and unpackage files.
126
+ # All test files should be included.
127
+ #
128
+ # The PackageTask will create the following targets:
129
+ #
130
+ # [<b>:dtr_package</b>]
131
+ # Create all the requested package files.
132
+ #
133
+ # [<b>:dtr_clobber_package</b>]
134
+ # Delete all the package files. This target is automatically
135
+ # added to the main clobber target.
136
+ #
137
+ # [<b>:dtr_repackage</b>]
138
+ # Rebuild the package files from scratch, even if they are not out
139
+ # of date.
140
+ #
141
+ # Example:
142
+ #
143
+ # DTR::PackageTask.new do |p|
144
+ # p.package_files.include("lib/**/*.rb")
145
+ # p.package_files.include("test/**/*.rb")
146
+ # end
147
+ #
73
148
  class PackageTask < Rake::TaskLib
74
149
  include SyncCodebase::Package
75
150
  # List of files to be included in the package.
76
151
  attr_accessor :package_files
77
152
 
78
- # Tar command for gzipped or bzip2ed archives. The default is 'tar'.
79
- attr_accessor :tar_command
80
-
81
153
  # Create a Package Task with the given name and version.
82
154
  def initialize
83
155
  @package_files = Rake::FileList.new
84
- @tar_command = 'tar'
85
156
  yield self if block_given?
86
157
  define
87
158
  end
@@ -104,7 +175,7 @@ module DTR
104
175
 
105
176
  file "#{package_dir}/#{file}" => [package_dir_path] do
106
177
  chdir(package_dir) do
107
- sh %{#{@tar_command} #{flag}cvf #{file} #{package_name}}
178
+ do_work(package_cmd)
108
179
  end
109
180
  end
110
181
 
@@ -112,6 +183,7 @@ module DTR
112
183
 
113
184
  file package_dir_path do
114
185
  mkdir_p package_dir rescue nil
186
+ @package_files.exclude(package_dir)
115
187
  @package_files.each do |fn|
116
188
  f = File.join(package_dir_path, fn)
117
189
  fdir = File.dirname(f)
@@ -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,17 +16,16 @@ require 'timeout'
16
16
 
17
17
  module DTR
18
18
  module Adapter
19
- AGENT_PORT = 7788
20
-
21
19
  WAKEUP_MESSAGE = 'wakeup'
22
20
  SLEEP_MESSAGE = 'sleep'
23
21
 
24
22
  module Follower
25
23
  def wakeup?
26
- msg, host = listen
27
- if msg == Adapter::WAKEUP_MESSAGE
28
- port = host.split(':').last.to_i
29
- DTR.configuration.rinda_server_port = port
24
+ msg, host, group = listen
25
+ if group == DTR.configuration.group && msg == Adapter::WAKEUP_MESSAGE
26
+ ip, port = host.split(':')
27
+ DTR.configuration.rinda_server_port = port.to_i
28
+ DTR.configuration.broadcast_list = [ip]
30
29
  @wakeup_for_host = host
31
30
  true
32
31
  end
@@ -34,40 +33,48 @@ module DTR
34
33
 
35
34
  def sleep?
36
35
  return true unless defined?(@wakeup_for_host)
37
- msg, host = Timeout.timeout(DTR.configuration.follower_listen_sleep_timeout) do
38
- loop do
39
- msg, host = listen
40
- break if host == @wakeup_for_host
41
- end
42
- [msg, host]
36
+ Timeout.timeout(DTR.configuration.follower_listen_heartbeat_timeout) do
37
+ until (msg, host = listen) && host == @wakeup_for_host; end
38
+ msg == Adapter::SLEEP_MESSAGE
43
39
  end
44
- DTR.info "Received: #{msg} from #{host}"
45
- msg == Adapter::SLEEP_MESSAGE
46
40
  rescue Timeout::Error => e
47
- DTR.info "Timeout while listening command"
41
+ DTR.info {"Timeout while listening command"}
48
42
  true
49
43
  end
50
44
 
45
+ def relax
46
+ if defined?(@soc) && @soc
47
+ @soc.close rescue nil
48
+ end
49
+ end
50
+
51
51
  private
52
52
  def listen
53
53
  unless defined?(@soc)
54
54
  @soc = UDPSocket.open
55
- @soc.bind('', Adapter::AGENT_PORT)
55
+ @soc.bind('', DTR.configuration.agent_listen_port)
56
+ DTR.info("DTR Agent is listening on port #{DTR.configuration.agent_listen_port}")
56
57
  end
57
- @soc.recv(1024).split
58
+ message, client_address = @soc.recvfrom(400)
59
+ cmd, port, group = message.split
60
+
61
+ hostname = client_address[2]
62
+ host_ip = client_address[3]
63
+ DTR.info {"Received: #{cmd} for group #{group} from #{hostname}(#{host_ip}):#{port}"}
64
+ [cmd, "#{host_ip}:#{port}", group]
58
65
  end
59
66
  end
60
67
 
61
68
  module Master
62
69
  def hypnotize_agents
63
- yell_agents("#{Adapter::SLEEP_MESSAGE} #{host}")
70
+ yell_agents("#{Adapter::SLEEP_MESSAGE} #{DTR.configuration.rinda_server_port}")
64
71
  end
65
72
 
66
73
  def with_wakeup_agents(&block)
67
74
  heartbeat = Thread.new do
68
75
  loop do
69
76
  do_wakeup_agents
70
- sleep(DTR.configuration.master_yell_interval)
77
+ sleep(DTR.configuration.master_heartbeat_interval)
71
78
  end
72
79
  end
73
80
  #heartbeat thread should have high priority for agent is listening
@@ -80,7 +87,7 @@ module DTR
80
87
  end
81
88
 
82
89
  def do_wakeup_agents
83
- yell_agents("#{Adapter::WAKEUP_MESSAGE} #{host}")
90
+ yell_agents("#{Adapter::WAKEUP_MESSAGE} #{DTR.configuration.rinda_server_port} #{DTR.configuration.group}")
84
91
  end
85
92
 
86
93
  private
@@ -91,16 +98,12 @@ module DTR
91
98
  end
92
99
  end
93
100
 
94
- def host
95
- "#{Socket.gethostname}:#{DTR.configuration.rinda_server_port}"
96
- end
97
-
98
101
  def broadcast(it, msg)
99
102
  soc = UDPSocket.open
100
103
  begin
101
104
  soc.setsockopt(Socket::SOL_SOCKET, Socket::SO_BROADCAST, true)
102
105
  DTR.debug {"broadcast sending #{msg} to #{it}"}
103
- soc.send(msg, 0, it, Adapter::AGENT_PORT)
106
+ soc.send(msg, 0, it, DTR.configuration.agent_listen_port)
104
107
  rescue
105
108
  nil
106
109
  ensure
@@ -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.
@@ -13,7 +13,7 @@
13
13
  # limitations under the License.
14
14
 
15
15
  require 'singleton'
16
- require 'rinda/rinda'
16
+ require 'rinda/ring'
17
17
  require 'rinda/tuplespace'
18
18
 
19
19
  module DTR
@@ -24,31 +24,59 @@ module DTR
24
24
 
25
25
  module_function :configuration
26
26
 
27
+ # DTR Configuration includes:
28
+ # For both master & agent process:
29
+ # * broadcast_list: broadcast ip list for looking for dtr services(agent and DTR master rinda server).
30
+ # * group: grouping agents for specific usage, master process should specify same group for catching agents to work
31
+ # For master process:
32
+ # * rinda_server_port: DTR would automatically detect unused port for master rinda server. The default port is 3344.
33
+ # * master_heartbeat_interval: master process heartbeat for keeping agents working. The default is 10 sec.
34
+ # For agent process:
35
+ # * agent_listen_port: agent listen master process command port, the default port is 7788.
36
+ # * follower_listen_heartbeat_timeout: agents would be going to sleep if listening master heartbeat timeout. The default is 15 sec.
37
+ #
38
+ # All configurations except rinda_server_port would be stored into pstore file .dtr_env_pstore in the DTR process launching directory.
39
+ #
27
40
  class Configuration
28
41
  include Singleton
29
42
  include Service::Rinda
30
43
 
31
- attr_accessor :broadcast_list, :rinda_server_port, :master_yell_interval, :follower_listen_sleep_timeout
44
+ attr_accessor :broadcast_list, :rinda_server_port, :agent_listen_port, :master_heartbeat_interval, :follower_listen_heartbeat_timeout
45
+ attr_reader :group
32
46
 
33
47
  def initialize
48
+ load
49
+ end
50
+
51
+ def load
34
52
  store = EnvStore.new
53
+ # always have 'localhost' in broadcast_list, for our master process would start rinda server locally,
54
+ # and dtr should work well on local machine when the machine leaves dtr grid network environment.
35
55
  @broadcast_list = ['localhost'].concat(store[:broadcast_list] || []).uniq
36
- @rinda_server_port = store[:port] || 3344
37
- @master_yell_interval = store[:master_yell_interval] || 10
38
- @follower_listen_sleep_timeout = store[:follower_listen_sleep_timeout] || 15
56
+ @rinda_server_port = 3344
57
+ @agent_listen_port = store[:agent_listen_port] || 7788
58
+ @master_heartbeat_interval = store[:master_heartbeat_interval] || 10
59
+ @follower_listen_heartbeat_timeout = store[:follower_listen_heartbeat_timeout] || 15
60
+ @group = store[:group]
39
61
  end
40
62
 
41
63
  def save
42
64
  store = EnvStore.new
43
65
  store[:broadcast_list] = @broadcast_list
44
- store[:port] = @rinda_server_port
45
- store[:master_yell_interval] = @master_yell_interval
46
- store[:follower_listen_sleep_timeout] = @follower_listen_sleep_timeout
66
+ store[:agent_listen_port] = @agent_listen_port
67
+ store[:master_heartbeat_interval] = @master_heartbeat_interval
68
+ store[:follower_listen_heartbeat_timeout] = @follower_listen_heartbeat_timeout
69
+ store[:group] = @group
70
+ end
71
+
72
+ def group=(group)
73
+ @group = group.blank? ? nil : group.gsub(' ', '_')
47
74
  end
48
75
 
49
76
  def with_rinda_server(&block)
77
+ DTR.do_println("Booting DTR service")
50
78
  start_service
51
- DTR.info '-- Booting DTR Rinda server...'
79
+ DTR.info {'-- Booting DTR Rinda server'}
52
80
  loop do
53
81
  begin
54
82
  Rinda::RingServer.new Rinda::TupleSpace.new, @rinda_server_port
@@ -57,7 +85,7 @@ module DTR
57
85
  @rinda_server_port += 1
58
86
  end
59
87
  end
60
- DTR.info "-- DTR Rinda server started on port #{@rinda_server_port}"
88
+ DTR.info {"-- DTR Rinda server started on port #{@rinda_server_port}"}
61
89
  block.call
62
90
  ensure
63
91
  stop_service rescue nil
@@ -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.
@@ -12,30 +12,6 @@
12
12
  # See the License for the specific language governing permissions and
13
13
  # limitations under the License.
14
14
 
15
- class Null
16
- class << self
17
- def instance(overrides = {})
18
- self.new.define_overrides(overrides)
19
- end
20
- end
21
-
22
- #override Object#id for removing the warning
23
- def id
24
- nil
25
- end
26
-
27
- def method_missing(sym, *args, &block)
28
- nil
29
- end
30
-
31
- def define_overrides(overrides)
32
- overrides.each_pair do |key, value|
33
- (class << self; self; end;).send(:define_method, key, lambda { value })
34
- end
35
- self
36
- end
37
- end
38
-
39
15
  # from activesupport-2.1.1
40
16
  class Object
41
17
  def blank?
@@ -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.
@@ -28,6 +28,10 @@ module DTR
28
28
  }
29
29
  lookup_ring.write [:agent, agent]
30
30
  end
31
+
32
+ def all_agents_info
33
+ lookup_ring.read_all([:agent, nil]).collect{|t|t[1]}
34
+ end
31
35
  end
32
36
  end
33
37
  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.
@@ -20,8 +20,16 @@ module DTR
20
20
  module Rinda
21
21
 
22
22
  def start_service
23
- DTR.info "-- Start drb service..."
24
- DRb.start_service
23
+ DTR.info {"-- Start drb service..."}
24
+ #todo need figure why agents couldn't be killed directly when start drb service by DRb.start_service
25
+ if ENV['DTR_ENV'] == 'test'
26
+ DRb.start_service("druby://#{Socket.gethostname}:0")
27
+ else
28
+ DRb.start_service
29
+ end
30
+ rescue
31
+ # for ruby 1.8.7 need specify uri
32
+ DRb.start_service("druby://#{Socket.gethostname}:0")
25
33
  end
26
34
 
27
35
  def stop_service
@@ -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,14 +20,15 @@ module DTR
20
20
  include Rinda
21
21
 
22
22
  def provide_runner(runner)
23
- renewer = ::Rinda::SimpleRenewer.new
24
- tuple = [:name, 'DTR::Runner'.to_sym, runner, "DTR remote runner #{Process.pid}-#{runner.name}"]
25
- lookup_ring.write(tuple, renewer)
23
+ tuple = ['DTR::Runner'.to_sym, runner, "DTR remote runner #{Process.pid}-#{runner.name}"]
24
+ #expires after 1 sec for we don't need runner service anymore if there is no one is waiting for taking it
25
+ lookup_ring.write(tuple, 1)
26
26
  end
27
27
 
28
28
  def lookup_runner
29
- lookup(:take, [:name, 'DTR::Runner'.to_sym, nil, nil])[2]
29
+ lookup(:take, ['DTR::Runner'.to_sym, nil, nil])[1]
30
30
  end
31
+
31
32
  end
32
33
  end
33
34
  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.
@@ -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,19 +14,27 @@
14
14
 
15
15
  module DTR
16
16
  module SyncCodebase
17
- class Codebase
17
+ class CopiablePackage
18
18
  include DRbUndumped
19
19
  include Package
20
20
 
21
21
  CHUNK_SIZE = 1024*1024
22
22
 
23
- def write(remote_io)
24
- File.open(File.join(package_dir, package_file), "rb") do |f|
25
- while chunk = f.read(CHUNK_SIZE) and chunk.length > 0
23
+ def initialize
24
+ raise "Package(#{codebase_package}) doesn't exist!" unless File.exist?(codebase_package)
25
+ end
26
+
27
+ def copy_into(remote_io)
28
+ File.open(codebase_package, "rb") do |f|
29
+ while (chunk = f.read(CHUNK_SIZE) || '') && chunk.length > 0
26
30
  remote_io.write(chunk)
27
31
  end
28
32
  end
29
33
  end
34
+
35
+ def codebase_package
36
+ File.join(package_dir, package_file)
37
+ end
30
38
  end
31
39
  end
32
40
  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.
@@ -12,10 +12,10 @@
12
12
  # See the License for the specific language governing permissions and
13
13
  # limitations under the License.
14
14
 
15
- require 'test/unit/testresult'
16
-
17
15
  module DTR
18
16
  module SyncCodebase
17
+ # Inject synchronizing codebase ability into Master#with_dtr_master
18
+ # Packaging codebase by rake task dtr_repackage (See DTR::PackageTask)
19
19
  module MasterExt
20
20
  include Service::File
21
21
 
@@ -25,22 +25,10 @@ module DTR
25
25
 
26
26
  def with_dtr_master_with_sync_codebase(&block)
27
27
  with_dtr_master_without_sync_codebase do
28
- unless Cmd.execute('rake dtr_repackage --trace')
29
- $stderr.puts %{
30
- Execute dtr_repackage rake task failed, see log for details.
31
- For running DTR test task, you must define a DTR::PackageTask task in your rakefile for DTR need package and synchronize your codebase within grid.
32
- Example:
33
- require 'dtr/raketasks'
34
- DTR::PackageTask.new do |p|
35
- p.package_files.include("**/*")
36
- p.package_files.exclude("tmp")
37
- p.package_files.exclude("log")
38
- end
39
- }
40
- return Test::Unit::TestResult.new
41
- end
28
+ DTR.do_println("Packaging codebase")
29
+ raise 'Packaging for dtr task failed, see log for details!' unless Cmd.execute('rake dtr_repackage --trace')
42
30
  begin
43
- provide_file Codebase.new
31
+ provide_file CopiablePackage.new
44
32
  block.call
45
33
  ensure
46
34
  Cmd.execute('rake dtr_clobber_package --trace')
@@ -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.
@@ -28,12 +28,26 @@ module DTR
28
28
  end
29
29
 
30
30
  def package_file
31
- "#{package_name}.tar.bz2"
31
+ "#{package_name}.zip"
32
32
  end
33
33
 
34
34
  def package_copy_file
35
35
  "copy_#{package_file}"
36
36
  end
37
+
38
+ def unpackage_cmd
39
+ "unzip #{package_copy_file}"
40
+ end
41
+
42
+ def package_cmd
43
+ "zip -r #{package_file} #{package_name}"
44
+ end
45
+
46
+ def do_work(cmd)
47
+ unless Cmd.execute(cmd)
48
+ raise "Execute command: #{cmd} failed. See log for details."
49
+ end
50
+ end
37
51
  end
38
52
  end
39
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.
@@ -18,21 +18,16 @@ module DTR
18
18
  include Package
19
19
  include Service::File
20
20
  def sync_codebase
21
- DTR.info("start sync codebase, clean #{File.join(Dir.pwd, package_name)}")
21
+ DTR.info("Start sync codebase, clean #{File.join(Dir.pwd, package_name)}")
22
22
  FileUtils.rm_rf(File.join(Dir.pwd, package_name))
23
23
 
24
- DTR.info("lookup codebase file")
25
- codebase = lookup_file
26
- DTR.info("receiving codebase: #{package_copy_file}")
24
+ DTR.info("Lookup codebase package file")
25
+ package = lookup_file
26
+ DTR.info("Receiving package file and writing to #{package_copy_file}")
27
27
  File.open(package_copy_file, 'w') do |f|
28
- codebase.write(f)
29
- end
30
- unless File.exists?(package_copy_file)
31
- raise "#{package_copy_file} does not exist, sync codebase failed."
32
- end
33
- unless Cmd.execute("tar -xjf #{package_copy_file}")
34
- raise "Extracting #{package_copy_file} by 'tar' failed."
28
+ package.copy_into(f)
35
29
  end
30
+ do_work(unpackage_cmd)
36
31
  DTR.info("sync codebase finished, clean #{package_copy_file}")
37
32
  FileUtils.rm_f(package_copy_file)
38
33
  end