In: |
lib/slave.rb
|
Parent: | Object |
the Slave class encapsulates the work of setting up a drb server in another process.
DEFAULT_SOCKET_CREATION_ATTEMPTS | = | Integer(ENV['SLAVE_SOCKET_CREATION_ATTEMPTS'] || 42) |
DEFAULT_PULSE_RATE | = | Float(ENV['SLAVE_PULSE_RATE'] || 8) |
DEFAULT_DEBUG | = | (ENV['SLAVE_DEBUG'] ? true : false) |
debug | [R] | |
debug | [RW] | if this is true and you are running from a terminal information is printed on STDERR |
obj | [R] | |
object | [R] | |
pid | [R] | |
ppid | [R] | |
psname | [R] | |
pulse_rate | [RW] | defined the rate of pinging in the Heartbeat object |
pulse_rate | [R] | |
socket | [R] | |
socket_creation_attempts | [RW] | |
uri | [R] |
just fork with out silly warnings
# File lib/slave.rb, line 47 47: def fork &block 48: #--{{{ 49: v = $VERBOSE 50: begin 51: $VERBOSE = nil 52: Process::fork &block 53: ensure 54: $VERBOSE = v 55: end 56: #--}}} 57: end
look up a value in an option hash failing back to class defaults
# File lib/slave.rb, line 39 39: def getval key, opts = {} 40: #--{{{ 41: keys = [key, key.to_s, key.to_s.intern] 42: keys.each{|k| return opts[k] if opts.has_key?(k)} 43: send key rescue nil 44: #--}}} 45: end
‘obj’ can be any object and ‘opts’ may contain the keys ‘socket_creation_attempts’, ‘pulse_rate’, ‘psname’, or ‘debug’
# File lib/slave.rb, line 73 73: def initialize obj, opts = {} 74: #--{{{ 75: @obj = obj 76: 77: @socket_creation_attempts = getval('socket_creation_attempts', opts) 78: @pulse_rate = getval('pulse_rate', opts) 79: @debug = getval('debug', opts) 80: @psname = getval('psname', opts) || gen_psname(@obj) 81: 82: trace{ "socket_creation_attempts <#{ @socket_creation_attempts }>" } 83: trace{ "pulse_rate <#{ @pulse_rate }>" } 84: trace{ "psname <#{ @psname }>" } 85: 86: @shutdown = false 87: 88: @heartbeat = Heartbeat::new @pulse_rate, @debug 89: @r, @w = IO::pipe 90: # 91: # child 92: # 93: unless((@pid = Slave::fork)) 94: begin 95: $0 = @psname 96: @pid = Process::pid 97: @ppid = Process::ppid 98: 99: @r.close 100: @socket = nil 101: @uri = nil 102: 103: tmpdir = Dir::tmpdir 104: basename = File::basename @psname 105: 106: @socket_creation_attempts.times do |attempt| 107: begin 108: s = File::join(tmpdir, "#{ basename }_#{ attempt }") 109: u = "drbunix://#{ s }" 110: DRb::start_service u, obj 111: @socket = s 112: @uri = u 113: trace{ "child - socket <#{ @socket }>" } 114: trace{ "child - uri <#{ @uri }>" } 115: break 116: rescue Errno::EADDRINUSE 117: nil 118: end 119: end 120: 121: if @socket and @uri 122: @heartbeat.start 123: @w.write @socket 124: @w.close 125: trap('SIGUSR2') do 126: @heartbeat.stop rescue nil 127: DBb::thread.kill rescue nil 128: FileUtils::rm_f @socket rescue nil 129: exit! 130: end 131: DRb::thread.join 132: else 133: @w.close 134: end 135: rescue => e 136: trace{ %[#{ e.message } (#{ e.class })\n#{ e.backtrace.join "\n" }] } 137: ensure 138: exit! 139: end 140: # 141: # parent 142: # 143: else 144: Process::detach @pid 145: @w.close 146: @socket = @r.read 147: @r.close 148: 149: trace{ "parent - socket <#{ @socket }>" } 150: 151: if @socket and File::exist? @socket 152: at_exit{ FileUtils::rm_f @socket } 153: @uri = "drbunix://#{ socket }" 154: trace{ "parent - uri <#{ @uri }>" } 155: @heartbeat.start 156: # 157: # starting drb on localhost avoids dns lookups! 158: # 159: DRb::start_service('druby://localhost:0', nil) unless DRb::thread 160: @object = DRbObject::new nil, @uri 161: else 162: raise "failed to find slave socket <#{ @socket }>" 163: end 164: end 165: #--}}} 166: end
generate a default name to appear in ps/top
# File lib/slave.rb, line 179 179: def gen_psname obj 180: #--{{{ 181: "#{ obj.class }_slave_of_#{ Process::pid }".downcase 182: #--}}} 183: end
see docs for class.getval
# File lib/slave.rb, line 185 185: def getval key, opts = {} 186: #--{{{ 187: self.class.getval key 188: #--}}} 189: end
stops the heartbeat thread and kills the child process
# File lib/slave.rb, line 168 168: def shutdown 169: #--{{{ 170: raise "already shutdown" if @shutdown 171: @heartbeat.stop rescue nil 172: Process::kill('SIGUSR2', @pid) rescue nil 173: Process::kill('SIGTERM', @pid) rescue nil 174: FileUtils::rm_f @socket 175: @shutdown = true 176: #--}}} 177: end